お世話になります。
固定長文字列を作成するDLL関数を作りたくて、以下のソースを作成し、エクセルのVBAで実行しました。
すると、エクセルが落ちてしまいました!
そこで
①エクセルが落ちた原因は下記コードにありますか?
②下記はmylenの値分の固定長文字列をつくるもので、nydataが桁数に満たない場合は半角スペースでうめるものです。けたあふれは無視します。
このコードであっていますか?
基本的にエクセルで使うので、mydataもmyLenもセルに入っている値です。
ちょっといい加減な質問で申し訳ございません。
そのあたりのマナーも含めてご教示ください。
よろしくお願いします。
Function export Lstrfix(myData as BytePtr, myLen as long) As String
'//変数の定義
dim mySpc As long
'▼▼▼処理▼▼▼
'//指定した固定長のバイト数から、データの分のバイト数を引いてスペースの数を取得
mySpc = myLen - Len(myData)
'//データとスペースで固定長の文字列を生成
Lstrfix = myData + Space$(mySpc)
end function
固定長文字列作成
String型をDLL関数で受け渡すことはできません。また、ABとVBのStringは別物です。
その程度の関数だったらVBAで標準モジュール内に書けば良い気がしますが,敢えてABでやるならば,こうするとどうでしょうか?
Len関数が文字列を長さを返すのはString型の値を使ったときだけで,BytePtr型の値を引数に渡してもうまくいきません。
BytePtr型に対してはlstrlen関数を使います。
ところがVBから渡された文字列はSysStringByteLenを使う方が効率的です。
(lstrlenはABのStringにも使えますが同様にLenの方が効率的です)
そこで結局私ならこうします。
SysAllocStringByteLenの戻り値を返すようにすると,VBでは戻り値をString型で受けることができます。
BSTR = VBのStringと思って差し支えありません。
(ただし文字列引数をDLLで受け取るときだけはこまたさんの元のLstrfixのようにBytePtrで受け取って構いません)
ABからLstrfixを使えるように公開したい場合は,別の方法を使います。(今は省略)
VBでは次のように宣言します。ByRef/Valを省略したときABではByValですが,VBではByRefであることに注意が必要です。
その程度の関数だったらVBAで標準モジュール内に書けば良い気がしますが,敢えてABでやるならば,こうするとどうでしょうか?
Len関数が文字列を長さを返すのはString型の値を使ったときだけで,BytePtr型の値を引数に渡してもうまくいきません。
BytePtr型に対してはlstrlen関数を使います。
ところがVBから渡された文字列はSysStringByteLenを使う方が効率的です。
(lstrlenはABのStringにも使えますが同様にLenの方が効率的です)
そこで結局私ならこうします。
コード: 全て選択
Function LstrfixLen(myData as BytePtr, dataLen As Long, myLen as long) As String
Dim mySpc As long
mySpc = myLen - dataLen
LstrfixLen = myData + Space$(mySpc)
End Function
/*
Function Lstrfix(myData as BytePtr, myLen as long) As String
Lstrfix = LstrfixLen(myData, lstrlen(myData) As Long, myLen)
End Function
*/
Function Export LstrfixVB(ByVal myData As BSTR, ByVal myLen As Long) As BSTR
Dim ret As String
ret = LstrfixLen(myData As BytePtr, SysStringByteLen(myData) As Long, myLen)
LstrfixVB = SysAllocStringByteLen(StrPtr(ret), Len(ret))
End Function
BSTR = VBのStringと思って差し支えありません。
(ただし文字列引数をDLLで受け取るときだけはこまたさんの元のLstrfixのようにBytePtrで受け取って構いません)
ABからLstrfixを使えるように公開したい場合は,別の方法を使います。(今は省略)
VBでは次のように宣言します。ByRef/Valを省略したときABではByValですが,VBではByRefであることに注意が必要です。
コード: 全て選択
Private Declare Function Lstrfix Lib "DLL名" Alias "LstrfixVB" ( _
ByVal myData As String, _
ByVal myLen As Long _
) As String
それはすみませんでした。
この宣言類を書き加えてください。
この宣言類を書き加えてください。
コード: 全て選択
TypeDef BSTR = *WCHAR
Declare Function SysAllocStringByteLen Lib "oleaut32" (
psz As BytePtr,
len As DWord
) As BSTR
Declare Function SysStringByteLen Lib "oleaut32" (
bstr As BSTR
) As BSTR
これで、ダメでしょうか?
こんばんは、
・Excel2000で試しました。
コード: 全て選択
・DLL側のコード
Function Export Lstrfix(myData As BytePtr, myLen As Long) As String
Dim mySpc As Long
Dim strMyData As String
strMyData = MakeStr(myData)
mySpc = myLen - Len(strMyData)
Lstrfix = strMyData + Space$(mySpc)
End Function
・Excel側の定義
Declare Function Lstrfix Lib "????.dll" (ByVal myData As String, ByVal myLen As Long) As String