ULONG型を使用するアプリにデータを転送したいため
下記のようにプログラミングしましたが
Chr()で表示できないバイナリ値の場合、
szULONGには正しい数値が入りません。
lnLng=5000 の場合 szULONG= 88 13 00 00 の形式で
入ってきて欲しいのですが 00 13 00 00 となります。
どなたか教えてください。
※ちなみにデータ転送はString型でないと送れないため
szULONGは他型で定義出来ません。
Function Lng_to_ULONG(lnLng As Long)
Dim szStr As String * 8
Dim szHex(4) As String * 2
Dim szULONG As String * 4
Dim nValue(4) As Integer
Dim I, n As Integer
Dim nDigit As Integer
Dim n16 As Long
'Longを16進に変換し、2バイトづつに分ける
RSet szStr = Hex(lnLng)
szHex(1) = Mid(szStr, 7, 2)
szHex(2) = Mid(szStr, 5, 2)
szHex(3) = Mid(szStr, 3, 2)
szHex(4) = Mid(szStr, 1, 2)
'16進を10進(Long)に変換する。
For n = 4 To 1 Step -1
n16 = 1
For I = 2 To 1 Step -1
If Trim(Mid(szHex(n), I, 1)) <> "" Then
If Asc(Mid(szHex(n), I, 1)) >= Asc("A") Then
nDigit = Asc(Mid(szHex(n), I, 1)) - Asc("A") + 10
Else
nDigit = Asc(Mid(szHex(n), I, 1)) - Asc("0")
End If
nValue(n) = nValue(n) + n16 * nDigit
End If
n16 = 16 * n16
Next I
Next n
szULONG = Chr(nValue(1)) & Chr(nValue(2)) & Chr(nValue(3)) & Chr(nValue(4))
End Function
ってーか、この関数、何したいの?
あとULongってUnsigned Longじゃ…?
ウルトラですか。
>ULONG型を使用するアプリにデータを転送したいため
ああ、送りたいのか。
>下記のようにプログラミングしましたが
>Chr()で表示できないバイナリ値の場合、
バイナリ値をChr()で表示ってどーよ?
>szULONGには正しい数値が入りません。
関数最後じゃszULONGは文字なんすけど?
>lnLng=5000 の場合 szULONG= 88 13 00 00 の形式で
こんな形式見たことありません。
>入ってきて欲しいのですが 00 13 00 00 となります。
しかも関数最後じゃ空白だし。
>※ちなみにデータ転送はString型でないと送れないため
>szULONGは他型で定義出来ません。
タガタ??
あ〜ん〜と〜〜〜〜、まぁわからん。
わからんから、プログラムだけ作っといたぞ。
Msgbox proc1(5000)
とかでためしてみ。
Type tLong
datus As Long
End Type
Type tLong_Bytes
data(1 To 4) As Byte
End Type
Function proc1(ByVal nLongValue As Long) As String
Dim i As Long
Dim v1 As tLong
Dim v2 As tLong_Bytes
v1.datus = nLongValue
LSet v2 = v1
For i = 1 To 4
proc1 = proc1 + Hex(v2.data(i)) + " "
Next
End Function
いちゆさん、ありがとうございました。
表記したプログラムを実行されるとわかると思いますが
szULONG= 88 13 00 00 はHEXで見たときの結果と
言う事を書きたかったのです。
言葉不足ですみません。
実際は
szULONG= ・・・・
の4バイトとなります。
初めての投稿なので言葉がわかりづらく思われると思いますが
もしおわかりになりましたらよろしくお願いします。
>表記したプログラムを実行されるとわかると思いますが
> szULONG= 88 13 00 00 はHEXで見たときの結果と
>言う事を書きたかったのです。
>言葉不足ですみません。
>実際は
> szULONG= ・・・・
>の4バイトとなります。
ん〜、なんだかなぁ。
とりあえず、LongだろうとUnsignedLongだろうと、バイト数が一致していれば
そのブロックの先頭のメモリアドレスからどんな風に読み取るのかは相手次第で、
Longで送っても大丈夫な気がするんだが…
で、私の作ったのは実行してみたの?
第一、最初の質問の
>lnLng=5000 の場合 szULONG= 88 13 00 00 の形式で
>入ってきて欲しいのですが 00 13 00 00 となります。
だけど、あなたが書いた関数内部じゃ空白にしかなりませんでしたよ?
再現性のあるプログラムのデバッグの質問をしているのに、
再現できないのじゃどうしようもないのですが?
ウルトラロング様の関数での問題は、CHR(nvalue(1))において
CHR(136)が変換できない文字コードになっている事でしょう。
Chr関数にて文字コードで変換できない値の場合の対応は私も知りたい
所です。
どなたか教えてください。
…あ〜、もしかしてウルトラロングって文字列変数で実はUnsignedLong型じゃない…?
で、&h88の文字コード(Chr$(&h88))がVBでは認識できないから困ってると。
…Chr(&h88)が存在して読み取れないのか、Chr(&h88)が存在すらしないのかをしらべてみた。
Sub test()
Dim sbuf() As Byte
Dim s1 As String
Dim s2 As String
'chr$(&h88)はString型の中に存在できるか?
Debug.Print "TEST1"
'Byte配列に&h88を入れてみる
ReDim sbuf(1 To 1)
sbuf(1) = &H88
'String型(1)に代入してみる(Chr$(&h88)は代入できるか?)
s1 = sbuf
sbuf = s1: debugOut sbuf
'String型(2)に代入してみる(Chr$(&h88)は生存できるか?)
s2 = s1
sbuf = s2: debugOut sbuf
Debug.Print "TEST2"
'String型にChr$(&h88)を入れてみる
s1 = Chr$(&H88)
'Chr$(&h88)は生きているか?
sbuf = s1: debugOut sbuf
'String型(2)に代入してみる(Chr$(&h88)は生存できるか?)
s2 = s1
sbuf = s2: debugOut sbuf
End Sub
Sub debugOut(ByRef buf() As Byte)
Dim va As Variant
For Each va In buf
Debug.Print Hex$(va); " ";
Next
Debug.Print
End Sub
イミディエイトウィンドウには
TEST1
88
88
TEST2
0 0
0 0
と表示された。
つまりChr$関数は特定の文字コードを入れた場合はNullCharを返す。
Chr$関数では特定できない文字がある。
しかし、いったんString型に入ってしまうと、
String型の中身は影響を受けないことがわかった。
…まぁ、自己満足だけどね。
ASC136様、
わたくしの拙い文章を理解いただけて嬉しく思いました。
(もしかしてわたくしと同じCOBOL経験者ですか?)
いろいろと試しましたが、やはりうまく行かない状態です。
どなたか知ってる方がいらっしゃいましたら宜しくお願いします。
>ASC136様、
>わたくしの拙い文章を理解いただけて嬉しく思いました。
>(もしかしてわたくしと同じCOBOL経験者ですか?)
>いろいろと試しましたが、やはりうまく行かない状態です。
>どなたか知ってる方がいらっしゃいましたら宜しくお願いします。
…つっこんで悪いとは思うけど。
どんなコードを書いたのかを示してくれると助かるような気がする。
Stringに&h88を入れることができるのはわかったのだし…
いちゆ様色々と回答ありがとうございます。
今回の内容はC言語で開発されている機械に対して
接続を行なう際に色々な情報(Uchar・UShort・Ulong)
などの相手方にあわした情報を1バッファ内に設定を行なう
必要があります。
Uchar及びUSHortに対しては1バッファ内に設定ができ
Ulong型のデータについてのみ相手方でエラーとなる状態です。
ちなみにUlong方についてもASC文字コードで変換可能な値での
変換は正常値として判断されます。
最初の書込み時はULongの変換方法を記述しています。
実際にバッファに設定したい情報はChr(136)の1文字です。
>※ちなみにデータ転送はString型でないと送れないため
>szULONGは他型で定義出来ません。
と、最初の書込みでString型以外は使用できませんと書込みされていますが、
機械に送信する方法がシリアル通信である場合は(他の通信方法でも)、
下記の通りバイト配列でも送信できます。
(いちゆさんが何度か(もかな?)確認していますが。)
参考意見として受け止めて頂ければ幸いです。
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Sub Command1_Click()
Dim lnLng As Long
Dim szULONG(3) As Byte
lnLng = 5000
Call CopyMemory(szULONG(0), lnLng, 4)
MSComm1.Output = szULONG
End Sub
しゅう様書き込みありがとうございます。
いちゆ様もありがとうございます。
前回、いちゆ様の書き込みにて確認を行ってみました。
内容をASCBで確認を行うと私の意図している結果となりましたが、
一回目の発信情報で記述した文字列(string * 4)への設定方法はないでしょうか?
送信バッファの一部として設定を行いたいのです。
(ちなみに)送信バッファへの設定は
szBuf = szBuf & XXXX で行っています。
馬鹿な質問をしているのかな?
String型として&H00001388を連結する方法はわかりませんが、
Byte配列であれば下記の通り簡単に文字列と連結できます。
送信バッファをByte配列にした方が良いと思います。
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Sub Form_Load()
Dim A As Long
Dim B As String * 4
Dim C(7) As Byte
Dim i As Long
A = 5000
B = "TEST"
Call CopyMemory(C(0), A, 4)
For i = 0 To 3
C(i + 4) = Asc(Mid(B, i + 1, 1))
Next
For i = 0 To 7
Debug.Print Hex(C(i))
Next
End Sub
上の訂正します。
Long型→Byte配列→String型が可能な様です。
(いちゆさんのテスト参考にしました。)
詳しくは調べていませんが、試してみて下さい。
Private Sub Command1_Click()
Dim lnLng As Long
Dim ByteAry(3) As Byte
Dim szULONG As String * 4
lnLng = 5000
Call CopyMemory(ByteAry(0), lnLng, 4)
szULONG = ByteAry
For i = 1 To 4
Debug.Print AscB(MidB(szULONG, i, 4))
Next
End Sub
ウルトラロング様、うまくいきましたでしょうか?
現在、シリアル通信の環境がなくテストできませんが、
代わりにファイル操作でテストしてみました。
しかし、|88|13|00|00|という出力を得る事が出来ておりません。
MSDNに下記記載がありました。
やっぱり、バイト配列じゃないとだめなのかと思い始めています。
VBA では、新しいデータ型としてバイト型 (Byte) が追加されています。バイナリデータを操作する際に文字列変数を使うと入出力時に ANSI - Unicode 変換がおこなわれてバイナリデータが変更されてしまいます。バイナリデータを扱う場合は、バイト型の変数を利用するようにしてください。
しゅう様、いろいろと親切にわかりやすく教えていただき
ありがとうございました。
送信バッファをByte配列にする方法で試した所
成功しました。
いろいろ試しましたが、やはりバイト配列じゃないと
だめだと言うことですね。
勉強になりました。
本当にありがとうございました。