固定長文字列作成

返信する


答えを正確に入力してください。答えられるかどうかでスパムボットか否かを判定します。

BBCode: ON
[img]: ON
[url]: ON
スマイリー: OFF

トピックのレビュー
   

展開ビュー トピックのレビュー: 固定長文字列作成

固定長文字列作成

by こまた » 2006年5月28日(日) 19:27

みなさんありがとうございます。
M.Kさんの方法だとシンプルですが、メモリの問題がありそうなんですね。。。
VBでメモリを回復する方法があればいいのかな(でもそれはここで聞くことじゃないですね・・・)。

ちょっと整理します。。。

by イグトランス » 2006年5月25日(木) 20:06

DLLでエクスポートされる関数にString型は使えないことになっているので,M.Kさんの方法ではメモリ周りが不安です。
憶測ですがVBに制御が戻った後,戻り値のStringのメモリは解放されずメモリリークになってしまうと思います。

これで、ダメでしょうか?

by M.K » 2006年5月25日(木) 01:08

こんばんは、

コード: 全て選択


・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で試しました。

by イグトランス » 2006年5月25日(木) 00:24

それはすみませんでした。
この宣言類を書き加えてください。

コード: 全て選択

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

by こまた » 2006年5月24日(水) 23:37

すみません。コンパイルしたら以下のエラーがでました.

xGVBDLL.abp(31) - "BSTR" 無効な識別子です
xGVBDLL.abp(33) - "SysStringByteLen(myData)" 無効な識別子です
xGVBDLL.abp(34) - "LstrfixVB" 無効な識別子です
xGVBDLL.abp(34) - "SysAllocStringByteLen(StrPtr(ret),Len(ret))" 無効な識別子です

BSTR型って何でしょうか?
ヘルプみても無いもので・・・。
見逃してますでしょうか?

固定長文字列作成

by こまた » 2006年5月24日(水) 23:28

イグトランスさん、ありがとうございます。

DLL可するのは、他にも関数をまとめて作りたいのと、各VBAのモジュールにいちいちコピーするのが少し手間だったからです。まあ、我慢すればいいんでしょうけど。


ソースくださいましてありがとうございます。
ちょっと勉強して何かありましたらまた質問させていただきます!

by イグトランス » 2006年5月24日(水) 23:01

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

固定長文字列作成

by こまた » 2006年5月24日(水) 21:38

お世話になります。

固定長文字列を作成する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

ページトップ