ページ 1 / 1
固定長文字列作成
Posted: 2006年5月24日(水) 21:38
by こまた
お世話になります。
固定長文字列を作成する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
Posted: 2006年5月24日(水) 23:01
by イグトランス
String型をDLL関数で受け渡すことはできません。また、ABとVBのStringは別物です。
その程度の関数だったら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
SysAllocStringByteLenの戻り値を返すようにすると,VBでは戻り値をString型で受けることができます。
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
固定長文字列作成
Posted: 2006年5月24日(水) 23:28
by こまた
イグトランスさん、ありがとうございます。
DLL可するのは、他にも関数をまとめて作りたいのと、各VBAのモジュールにいちいちコピーするのが少し手間だったからです。まあ、我慢すればいいんでしょうけど。
ソースくださいましてありがとうございます。
ちょっと勉強して何かありましたらまた質問させていただきます!
Posted: 2006年5月24日(水) 23:37
by こまた
すみません。コンパイルしたら以下のエラーがでました.
xGVBDLL.abp(31) - "BSTR" 無効な識別子です
xGVBDLL.abp(33) - "SysStringByteLen(myData)" 無効な識別子です
xGVBDLL.abp(34) - "LstrfixVB" 無効な識別子です
xGVBDLL.abp(34) - "SysAllocStringByteLen(StrPtr(ret),Len(ret))" 無効な識別子です
BSTR型って何でしょうか?
ヘルプみても無いもので・・・。
見逃してますでしょうか?
Posted: 2006年5月25日(木) 00:24
by イグトランス
それはすみませんでした。
この宣言類を書き加えてください。
コード: 全て選択
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
これで、ダメでしょうか?
Posted: 2006年5月25日(木) 01:08
by M.K
こんばんは、
コード: 全て選択
・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
・Excel2000で試しました。
Posted: 2006年5月25日(木) 20:06
by イグトランス
DLLでエクスポートされる関数にString型は使えないことになっているので,M.Kさんの方法ではメモリ周りが不安です。
憶測ですがVBに制御が戻った後,戻り値のStringのメモリは解放されずメモリリークになってしまうと思います。
固定長文字列作成
Posted: 2006年5月28日(日) 19:27
by こまた
みなさんありがとうございます。
M.Kさんの方法だとシンプルですが、メモリの問題がありそうなんですね。。。
VBでメモリを回復する方法があればいいのかな(でもそれはここで聞くことじゃないですね・・・)。
ちょっと整理します。。。