このページでは、プログラミングに関するTips等をあつかいます。
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
Bコンパイルする
Visual C++ の場合は、コマンドラインユーティリティNMAKEを使ってコンパイルするのが一般的( だった? )のようですが
私が使っていたCodeWarrior では統合開発環境でコンパイルする方法しかなかったので、上のソースファイルと
モジュール定義ファイルを、(通常のDLLを作成する方法で新規作成した )プロジェクトに追加してコンパイルを実行しました。
( Visual C++ でも同様の方法でもコンパイル可だと思います。)
参考ウェッブページ MSDN内 DLL 関数の Visual Basic アプリケーションからの呼び出し方