MX Component Excel VBA で 実数値の読み書き 2020/10/13
Option Explicit
'' -----------------------------------------------------------
'' 情報元:「よく見かけるVBサンプル集」
'' 57「Single型をHex値(16進数)へ変換」、58「Double型をHex値(16進数)へ変換」
'' http://www.suvaru.com/pg/sampl/Sample100_50.html
'' Win32API
Declare Sub CopyValtoVal Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal length As Long)
Function SingleToHex(ByVal s As Single, _
Optional ByVal direction As Boolean = False) As String
Dim i As Integer
Dim b(3) As Byte
Dim st, st2 As String
Call CopyValtoVal(b(0), s, 4)
If direction = False Then
For i = 0 To 3
st = Hex(b(i))
st2 = st2 + String(2 - Len(st), "0") + st
Next i
Else
For i = 3 To 0 Step -1
st = Hex(b(i))
st2 = st2 + String(2 - Len(st), "0") + st
Next i
End If
SingleToHex = st2
End Function
''
Function DoubleToHex(ByVal d As Double, _
Optional ByVal direction As Boolean = False) As String
Dim i As Integer
Dim b(7) As Byte
Dim st, st2 As String
Call CopyValtoVal(b(0), d, 8) '' 7->8
If direction = False Then
For i = 0 To 7
st = Hex(b(i))
st2 = st2 + String(2 - Len(st), "0") + st
Next i
Else
For i = 7 To 0 Step -1
st = Hex(b(i))
st2 = st2 + String(2 - Len(st), "0") + st
Next i
End If
DoubleToHex = st2
End Function
'' -------------------------------------------------
'' 32 ビット実数(単精度)変換
'' Ex : HexToSingle("C2F6E666") result = -123.45
Public Function HexToSingle(sHex As String) As Single
Dim sTemp As String
Dim iSign, iExponent As Integer
Dim fTemp, fFraction As Single
' 符号 1ビット
sTemp = Mid(sHex, 1, 1)
fTemp = Val("&H" & sTemp) And &H8
iSign = IIf(fTemp = 8, -1, 1)
' 指数部 8ビット
sTemp = Mid(sHex, 1, 3)
fTemp = Val("&H" & sTemp) And &H7F8
iExponent = fTemp / 2 ^ 3 - 127 '32ビット形式のバイアス=127
' 仮数部 23ビット
sTemp = Mid(sHex, 3, 6)
fTemp = Val("&H" & sTemp) And &H7FFFFF
fFraction = 1# + (fTemp / 2 ^ 23)
HexToSingle = iSign * fFraction * 2 ^ iExponent
End Function
'' 64 ビット実数(倍精度)変換
'' Ex : HexToDouble("C05EDD2F1A9FBE77") Result = -123.456
Public Function HexToDouble(sHex As String) As Double
Dim sTemp As String
Dim iSign, iExponent As Integer
Dim fTemp, fFraction As Double
' 符号 1ビット
sTemp = Mid(sHex, 1, 1)
fTemp = Val("&H" & sTemp) And &H8
iSign = IIf(fTemp = 8, -1, 1)
' 指数部 11ビット
sTemp = Mid(sHex, 1, 3)
fTemp = Val("&H" & sTemp) And &H7FF
iExponent = fTemp - 1023 '64ビット形式のバイアス=1023
' 仮数部 52ビット
sTemp = Mid(sHex, 4, 13)
fTemp = CDbl("&H" & sTemp)
fFraction = 1 + (fTemp / 2 ^ 52)
HexToDouble = iSign * fFraction * 2 ^ iExponent
End Function
Sub ボタン2_Click()
'' 単精度実数書き込み、読み出し
Dim iData(1) As Integer
Dim sData As String
Dim i As Integer
Dim st, st2 As String
Dim f As Single
f = -123.456
sData = SingleToHex(f, True) '' "C2F6E666"
'' 下位から格納(D0 = E666, D1 = C2F6 と格納すれば良い)
For i = 0 To 1
iData(i) = CInt("&H" & Mid(sData, (1 - i) * 4 + 1, 4))
Next i
With Worksheets("Sheet1").ActUtlType1
.ActLogicalStationNumber = 6 ''通信設定ユーティリティーでの論理局番
.Open
'' 書き込み
Call .WriteDeviceBlock2("D0", 2, iData(0))
'' 読み出し
Call .ReadDeviceBlock2("D0", 2, iData(0))
For i = 1 To 0 Step -1
st = Hex(iData(i))
st2 = st2 + String(4 - Len(st), "0") + st
Next i
'' Debug.Print st2
f = HexToSingle(st2)
With Worksheets("Sheet1")
.Cells(1, 1).Value = st2
.Cells(1, 2).Value = f
End With
.Close
End With
End Sub
Sub ボタン3_Click()
'' 倍精度実数書き込み、読み出し
Dim iData(3) As Integer
Dim sData As String
Dim i As Integer
Dim st, st2 As String
Dim d As Double
d = -123.456
sData = DoubleToHex(d, True) '' "C05EDD2F1A9FBE77"
For i = 0 To 3
iData(i) = CInt("&H" & Mid(sData, (3 - i) * 4 + 1, 4))
Next i
With Worksheets("Sheet1").ActUtlType1
.ActLogicalStationNumber = 6 ''通信設定ユーティリティーでの論理局番
.Open
'' 書き込み
Call .WriteDeviceBlock2("D0", 4, iData(0))
'' 表示形式 : ワード、16bit、16 進表示の場合
'' D3=C05E, D2=DD2F, D1=1A9F, D0=BE77
'' 読み出し
Call .ReadDeviceBlock2("D0", 4, iData(0))
For i = 3 To 0 Step -1
st = Hex(iData(i))
st2 = st2 + String(4 - Len(st), "0") + st
Next i
'' Debug.Print st2
d = HexToDouble(st2)
With Worksheets("Sheet1")
.Cells(1, 1).Value = st2
.Cells(1, 2).Value = d
End With
.Close
End With
End Sub