【VBA】9桁以上の16進数表記文字列同士のORを求める
昨日、Twitter で、
「16進数のORをとるのにもっと効率のいいやり方ある?」
というやつを見つけました。
16進数のORをとるのにもっと効率のいいやり方ある?
— ささきさん (@sasaki__san) 2019年9月16日
誰かおせーて!#VBA pic.twitter.com/qmQrwBiWti
スマホの小さい画面で見ていたので、
実は細かいところまでは見えなかった(見てなかった?)ので
「単純にLongに変換して、OR とって、Hex で16進表記に戻せばいいのでは」と
返したら、どうも4Byte超相当(9桁以上)の文字列を処理したいらしい。
32bit版では Long(16進数表記で8桁)までしか処理できないので、
8桁ずつループ処理するコードを書いてみました。
なお、Twitter で返したコードを少し変えてあります。
Public Function HexStringOr(ByVal sHexValue1 As String, ByVal sHexValue2 As String) As String Dim lLen1 As Long Dim lLen2 As Long Dim lResultLen As Long Dim lOrgLen As Long Dim sHexW1 As String Dim sHexW2 As String Dim sResult As String Dim lStartPos As Long Dim lHex1 As Long Dim lHex2 As Long Dim lHexW As Long Dim i As Long Const ZERO8 As String = "00000000" '16進文字列判定 If isHexString(sHexValue1) = False Then Exit Function ElseIf isHexString(sHexValue2) = False Then Exit Function End If lLen1 = Len(sHexValue1) lLen2 = Len(sHexValue2) If lLen1 >= lLen2 Then lOrgLen = lLen1 Else lOrgLen = lLen2 End If '8の倍数となる文字列長を求める lResultLen = ((lOrgLen + 7) \ 8) * 8 'ゼロパディング sHexW1 = String$(lResultLen - lLen1, "0") & sHexValue1 sHexW2 = String$(lResultLen - lLen2, "0") & sHexValue2 '結果格納用文字列(ダミー0埋め) sResult = String$(lResultLen, "0") For i = 1 To lResultLen \ 8 '処理先頭位置 lStartPos = 1 + (i - 1) * 8 '8文字抜き出してLongに変換 lHex1 = CLng("&H" & Mid$(sHexW1, lStartPos, 8)) lHex2 = CLng("&H" & Mid$(sHexW2, lStartPos, 8)) lHexW = lHex1 Or lHex2 '結果を格納 Mid$(sResult, lStartPos, 8) = Right$(ZERO8 & Hex(lHexW), 8) Next i '元のデータの桁に合わせてから返す HexStringOr = Right$(sResult, lOrgLen) End Function '16進文字列判定 Private Function isHexString(ByVal sValue As String) As Boolean If Len(sValue) = 0 Then Exit Function End If isHexString = Not sValue Like "*[!0-9a-fA-F]*" End Function
実行サンプル
? HexStringOr("1234567890ABCDEF11","22222222") 1234567890ABEFEF33 ? HexStringOr("444444442222222200001122","1111222200008888CCCC3333") 555566662222AAAACCCC3333 ? HexStringOr("004444444422222222000011","001111") 004444444422222222001111
「これで(速度的な意味で)効率が良くなったのか?」と聞かれれば、もちろん
「ほとんど変わらないよ!!!」
と言っちゃいます。m(_ _)m
パラメータの文字列が、数千桁とか数万桁なら、こっちの方が若干速いような気がしますけど。
最後に
今回のように、生成される文字列長が予め分かっているような場合には、
都度、文字列を結合するより、
予め、結果の文字列長のダミー文字列を用意しておいて、
それに対して、Midステートメント(Mid関数ではありません)で埋め込んでいったほうが効率的です。
左辺にMidがあるのは、見慣れないかもしれませんが、
覚えておくと便利です。