ぷろぐらむTips

 このページでは、プログラミングに関するTips等をあつかいます。

目   次

VBAでWindowsAPI関数を使う

VBAで呼び出す自作DLLを作る場合の注意点


VBAでWindowsAPI関数を使う

 WordやExcelには、VBA(Visual Basic for Application)というVisual Basicのサブセットがついていて、 これだけでもかなりのプログラムが出来ますが、さらにWindowsAPI関数を使うと、VBAやVBだけでは 実現できない機能を使う事が出来ます。
 ここではVBAから、WindowsAPI関数を呼び出す方法を書いておきます。

 まず使いたい機能を持ったAPI関数の宣言文を書かなければ、なりません。
 したがってまずこの宣言文を調べなければならないのですが、そのためにはAPIビューワーというソフトが 必要になります。
 VBには、このソフトが、付属しているそうですが筆者はVBを持っていないので、持っていません。が、同じ機能を持ったフリーウェア・シェアウェアが たくさん存在しているので筆者の様にVBを持っていないという人は、例えばVectorのサイトなどで調べて手に入れてください。
 これを使って、例えばGetOpenFileNameという関数を調べると、
(ちなみにこれは「開くダイアログ」を表示してファイルのフルパスを得るのに使う関数です。 ExcelVBAには同じ機能を持ったメソッドが用意されているのでわざわざ、このAPI関数を使うメリットは少ないのですが 一つの利用例として載せて置きます)

  Public Declare Function GetOpenFileName Lib "comdlg32.dll" Alias "GetOpenFileNameA" _
  (pOpenfilename As OPENFILENAME) As Long


という風に表示されるので、これをVBA標準モジュールのDeclarationsに、コピーしてください。
ここで引数にOPENFILENAMEという構造体がありますが、VBにはこんな型はないので、これもAPIビューワー で調べると

Public Type OPENFILENAME
    lStructSize As Long
    hwndOwner As Long
    hInstance As Long
    lpstrFilter As String
    lpstrCustomFilter As String
    nMaxCustFilter As Long
    nFilterIndex As Long
    lpstrFile As String
    nMaxFile As Long
    lpstrFileTitle As String
    nMaxFileTitle As Long
    lpstrInitialDir As String
    lpstrTitle As String
    flags As Long
    nFileOffset As Integer
    nFileExtension As Integer
    lpstrDefExt As String
    lCustData As Long
    lpfnHook As Long
    lpTemplateName As String
End Type


と書いてあるので、これを標準モジュールのDeclarationsに、コピーしてください。
 こうやって宣言しておけば、あとはVBAの関数と同じように使うことができます。

 あまり実用的な例では、ないですがGetOpenFileNameを使ったプログラム例をこちらに 載せておきます。


VBAで呼び出す自作DLLを作る場合の注意点
 2001年頃ですが、自作のDLL( CodeWarrior を使ってC++ で作ったもの )を、VBA で呼び出そうとしたところ、呼び出せず大変苦労した事がありました。

 以下はその時調べた事で、結論はDLL を作成するときに stdcall規約を使わなくてはならないという事でした。
 以下に具体的なソースを載せて説明します。

@ソースコードを書く
 まずDLL のソースコードを書きます。たとえば、

/* 	
	DLL matrix ,structure call test from VisualBasic(or VBA)
	Tatsuroh Ikeda ,Feb 19,2001
*/
#include <windows.h>
#define EXP __declspec(dllexport)

/* ++++++++++++++++++++++++++++++ */
typedef struct
{
  double *val_1 ;
  short  val_2 ;

}TDMATRX ;
/* ++++++++++++++++++++++++++++++ */


EXP void __stdcall Matrix_Call(double* ,short* );
EXP void __stdcall UsrMtx_Call(TDMATRX* ,short*);					

EXP void __stdcall Matrix_Call(double *matrix ,short *dim_number)
{
	short  index_number ;
	
	for(index_number =0 ;index_number<= *dim_number ; index_number++ )
	{
	    matrix[index_number] +=2.0 ;
	}
}

EXP void __stdcall UsrMtx_Call(TDMATRX *t_matrix  , short *the_num )
{
                (以下略 )
}

 普通DLL のソースを書く場合は関数の宣言や、定義は(上の例の場合なら)
宣言文 EXP void Matrix_Call(double* ,short* ) ;

定義文 EXP void Matrix_Call(double *matrix ,short *dim_number)
{     (以下略)

という具合に書きますが、VB(VBA)で呼び出すDLL を作る場合は関数名の前に __stdcall をつける必要があります

Aモジュール定義ファイルをつくる。
 Borland C++ を使ってDLLを作成する場合は、この過程は不要です。

 モジュール定義ファイルという公開するDLL関数を羅列したファイルを作成する必要があります。
 上のソースプログラムの場合ならテキストエディタで新しいファイルを作成して、


LIBRARY matrixcall
EXPORTS
  Matrix_Call
  UsrMtx_Call

のように EXPORTS の後に使用するDLL関数を書いて、拡張子を def にして保存します。

Bコンパイルする
 Visual C++ の場合は、コマンドラインユーティリティNMAKEを使ってコンパイルするのが一般的( だった? )のようですが 私が使っていたCodeWarrior では統合開発環境でコンパイルする方法しかなかったので、上のソースファイルと モジュール定義ファイルを、(通常のDLLを作成する方法で新規作成した )プロジェクトに追加してコンパイルを実行しました。
( Visual C++ でも同様の方法でもコンパイル可だと思います。)

参考ウェッブページ MSDN内 DLL 関数の Visual Basic アプリケーションからの呼び出し方


プログラム工房にもどる