トップ > 備忘録 > VBAをVBに変換

VBAをVBに変換2017.11.04

VBAから扱えるDLLを作成したいと思い、Visual Studio 2017を利用し、試しにつくってみました。VBAから扱えるDLLを作成
無事に動作したので、次にVBAで書いた大がかりな関数をDLLにすることにしました。
今回取り組むのは、数独を解析する関数です。VBAコード:Excelで数独解析 Ver.2.3.0

Visual Studio はVBやC#等なので、最も変換しやすいVB(2017)に、VBAコードを変換してみました。
何点か気を付ける点があったので、そのまとめとコードのメモです。
これらの情報はVB2017を前提としています。

ポイント

・変数
・配列
・構造体
・ラベル
・Function

変数

32ビット符号付き整数

32ビット符号付き整数は、VBではInteger型であるのに対し、VBA(32ビット)ではLong型になる。型が違うとエラーになる。引数の引き渡しの際に注意が必要。

[ VB ]で次のように、Integer型を引数の型に指定する。(画像クリックで拡大↓)

[ VBA ]でInteger型を引数に指定すると、エラーになる。


[ VBA ]でLong型にすると、正常に実行される。

Variant型は使えない

VBは.NET以降、Variant型が非対応。VBAで、セルの値を代入したVariant型の変数は、対応する型に変換する必要がある。次のサイトには代替案が載っている。
連載! とことん VB: 第 2 回 VB.NET における Variant 型の代替案

尚、Excelで数独解析 Ver.2.3.0のVBAコードでは、引数にセルの値を代入したVariant型の2次元配列を渡していた。VBではそれができないので、Variant型配列に代入したセルの値を、Long型の変数に代入しなおし、引数として渡すことにした。

[ VBA ]元のコード

[ VBA ] VBに対応させるため、Variant型に格納されている値をLong型に代入したコード


配列

配列のインデックス

VB(2017) で配列のインデックスの下限に設定できるのは0のみである。3つの要素を持つ配列を宣言する際、VBAでは、次のようにインデックスの下限が0でなくとも設定できる。
Dim i(1 To 3) As Long ' 1,2,3
もちろん、次の書き方だと下限は0になる(Option Base 1 を設定していなければ)。
Dim i(2) As Long ' 0,1,2

一方、VBでは次の形でしか宣言できない。
下限は0で決まっておりOption Baseステートメントもない。
Dim i(2) As Integer ' 0,1,2

では、VBAで Dim i(1 To 3) As Long ' 1,2,3 このようにインデックスの下限が0でない設定で、配列を用いていた場合はどのように修正すればよいのか。

それは Dim i(3) As Long ' 0,1,2,3 のようにするのである(もちろん状況によるが)。
そしてVBも同様に Dim i(3) As Integer ' 0,1,2,3 このように宣言すれば良い。
使用しない(0)の部分の要素数は増えるが、コードを書き換える手間は省ける。

数独を解析するコードでは、9行×9列のセル範囲をVariant型変数に代入しているため、2次元配列の下限はそれぞれ1になる。Variant型をLong型に変換する際、Dim lngRangeS(9, 9) As Longを宣言し、配列要素の0は使わずに、値を代入し、それをVBに引き渡している。もちろん、VB側もDim intRangeS(9, 9) As Integerで受け取るよう設定する。

動的配列の宣言と引き渡し

VBAでの動的配列の宣言は、次元数に関係なく 変数名() で行う。Redimで要素数や次元数を設定する。
サブルーチンや関数の引数で配列を受け取る時も、次元数に関係なく 変数名() でよい。

'VBAサンプル
Public Sub TEST()
    Dim i() As Long
    ReDim i(1)
    Call test1(i)
    MsgBox i(1)
    ReDim i(1, 1)
    Call test2(i)
    MsgBox i(1, 1)
End Sub

Private Sub test1(ByRef i() As Long) i(1) = 100 End Sub
Private Sub test2(ByRef i() As Long) i(1, 1) = 200 End Sub

一方VBでは、動的配列を宣言する際に次元数を指定する必要がある。2次元だと 変数名(,) になる。そしてRedimで設定できるのは要素数のみになる。つまり、1次元配列と2次元配列は、別々に宣言する必要がある。
サブルーチンや関数の引数で配列を受け取る時も、次元数を指定する必要がある。

'VBサンプル
Public Sub TEST()
    Dim i() As Integer
    ReDim i(1)
    Call test1(i)
    MsgBox(i(1))
    Dim ii(,) As Integer
    ReDim ii(1, 1)
    Call test2(ii)
    MsgBox(ii(1, 1))
End Sub

Private Sub test1(ByRef i() As Integer) i(1) = 100 End Sub
Private Sub test2(ByRef i(,) As Integer) i(1, 1) = 200 End Sub

ユーザー定義型(構造体)

VBAのユーザー定義型を宣言するTypeステートメントはVBにない。それに代わるのがStructureステートメント。
数独を解析するプログラムでは構造体を利用している。以下、その宣言部分。

'VBA
Type Separation
    Value() As Long
    Count(1 To 9, 1 To 9) As Long
End Type
Private typSep(1 To 52) As Separation

上記をVB変換すると、次のようになる。

'VB
Structure Separation
    Dim Value(,) As Integer
    Dim Count(9,9) As Integer
End Structure
Private typSep(52) As Separation

ラベル

VBAでも、VBでも ERR: のようなラベルは使えるが、VBではGoSubは使えない。
GoToで対応。

'VBA
Sub test()
    Call Sample(0)
End Sub

Sub Sample(ByVal n As Long) If n = 0 Then GoSub ERR Exit Sub ERR: MsgBox "Error" End Sub
'VB
Sub test()
    Call Sample(0)
End Sub

Sub Sample(ByVal n As Long) If n = 0 Then GoTo ERR Exit Sub ERR: MsgBox("Error") End Sub

Function(関数)

Functionの戻り値に関して、VBAでは関数名が戻り値になるのに対し、VBは、Returnステートメントを使い戻り値を設定する。

'VBA
Public Function VBA_Sample(ByVal c As Long) As Long
    Dim i As Long
    For i = 0 To c
        VBA_Sample = VBA_Sample + i
    Next
End Function
'VB
Public Function VB_Sample(ByVal c As Integer) As Integer
    Dim i As Integer
    For i = 0 To c
        VB_Sample = VB_Sample + i
    Next
    Return VB_Sample
End Function

VB・VBAコード比較

少し時間がかかったが、Excelで数独解析 Ver.2.3.0のVBAコードを、VB(2017)コードに変換できた。
VBとVBAのコード比較ページを準備した。 ページの左側が、実際にVisual Studio 2017に入力したVBコード、右側が、元のVBAのコードである。
比較ページ


【お薦め】マクロ・プロシージャを管理する無料のツール!
 Excelマクロ管理ツール

ページトップへ戻る
Copyright(C) 2009- 坂江 保 All Rights Reserved.