VBAのみで2進数と16進数を互いに変換してみる。

#始めに
近年のバージョンのExcelには16進数表記を2進数表記に変換するHEX2BIN関数や、2進→16進変換をするBIN2HEX関数がありますが、Accessなどにはないの作ってみました。公開して需要があるのか解りませんが、VB系には汎用性が有ると思うのでメモ替わりに公開してみます。

#16進←→2進ってどうやるんだっけ？
コンピューターにおいて二進と十六進の変換は基本中の基本だと思いますが、一応おさらいを。
##2進から16進
11010010という数を例にして見ると、まず2進の数を4桁毎に分解します。この場合は1101と0010です。
続いて下の表に従い1の数のところだけ足します。

|1  |1  |0  |1  |
|---|---|---|---|
|8  |4  |2  |1  |

|0  |0  |1  |0  |
|---|---|---|---|
|8  |4  |2  |1  |

つまり、8＋4＋1で13です。つぎの2桁は0010なので２です。そうして得られた結果の下の対処表に当てはめれば
11010010の答えがD2であることがわかります。

|1  |2  |3  |4  |5  |6  |7  |8  |9  |A  |B  |C  |D  |E  |F  |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|1  |2  |3  |4  |5  |6  |7  |8  |9  |10 |11 |12 |13 |14 |15 |

表1：10進と16進の対照表

##16進から2進
今度は逆の操作ですが、一桁ずつ算定していきます。D2の場合はDと2に分解し、以下の表に当てはめましょう。

|1   |2   |3   |4   |5   |6   |7   |8   |9   |A   |B   |C   |D   |E   |F   |
|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|
|0001|0010|0011|0100|0101|0110|0111|1000|1001|1010|1011|1100|1101|1110|1111|

表2：16進と2進の対照表

Dは1101、2は10なので0010。これを合成すると11010010となります。

#実装
16進変換はHEX関数があるのでそれを利用すれば容易にもとめられるのですが、2進にはそんな便利な関数はないので、配列に結果を格納しておいて、11なら「1011を格納したarrBin（11）」を当てはめるというやり方を考えましたし、実際[そういう実装をされている方](https://thom.hateblo.jp/entry/2015/08/09/101751)　もいらっしゃったのですが、スマートじゃないのでビット演算で求めることにしました。

##解説
どちらともvarBinaryに、若い順番から8,4,2,1を格納し、1（または４）文字取り出し演算を繰り返すシンプルな実装となりました。
varBinaryはVariant型なので念のためCLng関数で変換しています。

###16進変換のソースコード

↓↓↓↓↓↓↓ あなたの記事の内容
```VB:Bin_2_Hex
───────
```vb:Bin_2_Hex
↑↑↑↑↑↑↑ 編集リクエストの内容
   Const strBin As String = "11010010"
    
    Dim i           As Long
    Dim y           As Long
    Dim lack        As Long
    Dim tmp         As String
    Dim lngByte     As Long
    Dim strAns      As String
    Dim varBinary   As Variant

    varBinary = Array("8", "4", "2", "1")
   
   lack = 4 - (Len(strBin) Mod 4)
    
    If lack <> 4 Then
        Do Until lack = 0
            strBin = "0" & strBin
            lack = lack - 1
        Loop
    End If
         


    For i = 1 To Len(strBin) Step 4
        
        lngByte = 0    '変数の初期化
        tmp = Mid(strBin, i, 4) '値を取り出す
        
        For y = 0 To 3
            '数を取り出しフラグが立っていると足す
            If Mid(tmp, y + 1, 1) = "1" Then
                lngByte = lngByte + CLng(varBinary(y))
            End If
        Next y

        strAns = strAns & Hex(lngByte) '答えを格納する
    Next i
    
    Debug.Print "答え:" & strAns
```
追記：最初のコードでは4の倍数ではない数では誤った値が出るので修正しました。

###2進変換のソースコード

↓↓↓↓↓↓↓ あなたの記事の内容
```VB:Hex_2_Bin
───────
```vb:Hex_2_Bin
↑↑↑↑↑↑↑ 編集リクエストの内容
    Const strHex As String = "F2"
    
    Dim i           As Long
    Dim y           As Long
    Dim tmp         As Long
    Dim strAns      As String
    Dim varBinary   As Variant
    
    varBinary = Array("8", "4", "2", "1")
    
    For i = 1 To Len(strHex)
        tmp = CLng("&h" & Mid(strHex, i, 1))  '値を取り出す
        
        For y = 0 To 3
            '数を取り出しフラグが立っていると足す
            If (tmp And CLng(varBinary(y))) = 0 Then
                strAns = strAns & "0"
            Else
                strAns = strAns & "1"
            End If
        Next
    Next i
    
    Debug.Print "答え:" & strAns
```

#終わりに
あまりに基礎的なコードであるがゆえにあまりサンプルも載っていなかったこともあり投稿させていただきました。一つでも参考になれれば幸いです。

#参考サイト
-[2進数 & 10進数 & 16進数 - Part 2　- ネットワークエンジニアとして] (https://www.infraexpert.com/study/ip2.html)
-[VBAでビット演算(論理演算) - t-hom's diary](https://thom.hateblo.jp/entry/2015/08/09/101751)
-[三流君ASP:2進数文字列と16進文字列の変換処理に挑戦](http://www.ken3.org/asp/backno/asp094.html)

#追記
nukie_53さんから

>Array関数の引数には、ユーザー定義型以外の大体のものは指定できるため、直接数値を指定してもよいのではないでしょうか？
また、Array関数は、以下のようにOption Baseの影響を受けるためFor y = 0 To 3と決め打ちで書くのはちょっと怖い面があります。
下限が常に0になるVBA.Arrayを使用･･･すると、そのあたりの影響を無視できます。

とあります。試してみたところ、

```vb:newcode
'16進に変換
Sub Bin_2_Hex()
    Const strBin As String = "11010010"
    
    Dim i           As Long
    Dim y           As Long
    Dim tmp         As String
    Dim lngByte     As Long
    Dim strAns      As String
    Dim varBinary   As Variant

    varBinary = VBA.Array(8&, 4&, 2&, 1&)
    
    For i = 1 To Len(strBin) Step 4
        
        lngByte = 0    '変数の初期化
        tmp = Mid(strBin, i, 4) '値を取り出す
        
        For y = 0 To 3
            '数を取り出しフラグが立っていると足す
            If Mid(tmp, y + 1, 1) = "1" Then
                lngByte = lngByte + varBinary(y)
            End If
        Next y

        strAns = strAns & Hex(lngByte) '答えを格納する
    Next i
    
    Debug.Print "答え:" & strAns

End Sub

'2進に変換

Sub Hex_2_Bin()
 Const strHex As String = "F2"

    Dim i           As Long
    Dim y           As Long
    Dim tmp         As Long
    Dim strAns      As String
    Dim varBinary   As Variant

    varBinary = VBA.Array(8&, 4&, 2&, 1&)

    For i = 1 To Len(strHex)
        tmp = CLng("&h" & Mid(strHex, i, 1))  '値を取り出す

        For y = 0 To 3
            '数を取り出しフラグが立っていると足す
            If (tmp And varBinary(y)) = 0 Then
                strAns = strAns & "0"
            Else
                strAns = strAns & "1"
            End If
        Next
    Next i

    Debug.Print "答え:" & strAns
End Sub
```

これでも動作しました。そちらの方がスマートなコードだと思います。ありがとうございました。