プラットフォーム差による VBA の問題と AutoCAD 2014

AutoCAD API を使ったアドオン アプリケーションの移植性 の記事では、AutoCAD API の移植性についてご案内しました。その際、AutoCAD 上で VBA を使った場合、パフォーマンスや互換性に不具合が生じてしまうことをご説明しました。

念のため、そのポストを抜粋してここに記載しておきましょう。

なお、AutoCAD 2009 以前で VBA プロジェクトを利用していた方は、AutoCAD 2010 以降の VBA 環境に注意してください。VBA コンポーネントは、AutoCAD 2010 から インストールメディア(DVD-ROM) には含まれず、http://www.autodesk.com/vba-download からのダウンロード提供に切り替わっています。これは、Microsoft 社が提供する VBA コンポーネントが、32 ビット版でしか用意されていないためです。

64 ビット版 Windows 上で動作する 64 ビット版 AutoCAD で、32 ビット版 VBA を動作させるには、プログラムの実行時に AutoCAD と VBA の内部的な通信が発生します。32 ビット版 Windows 上で動作する 32 ビット版 AutoCAD の場合には、同じ 32 ビット版 VBA は AutoCAD と同じメモリ空間で動作することが出来るので、この通信が発生しないのです。この結果、 64 ビット版 AutoCAD で VBA を実行すると、パフォーマンスが低下したり、一部の VBA プログラムの互換性が崩れることになってしまいました。

Microsoft社提供のVBAコンポーネントの互換性とパフォーマンスについて解説した図。32ビットWindowsと32ビットAutoCADの組み合わせでは高速なパフォーマンスが得られ、64ビットWindowsと64ビットAutoCADではパフォーマンス低下とプロセス間通信が必要であることを示している。

今日は、32 ビットと 64 ビットのプラットフォーム差で、AutoCAD VBA の実行にどうった問題が発生するか、具体的に紹介しておきましょう。

パフォーマンス差

ここでは、モデル空間の原点を中心に、放射線状に線分を作図する簡単なプログラムで、パフォーマンスの差を実感してみましょう。仕様するプログラムは、次のコードです。   

Public Sub PerformanceCheck()

    Dim strStart As Variant
    strStart = Timer

    Dim ptStart(0 To 2) As Double
    Dim ptEnd As Variant

    ptStart(0) = 0#: ptStart(1) = 0#: ptStart(2) = 0#
    Dim i As Double

    For i = 0# To 360# Step 0.1
        ptEnd = ThisDrawing.Utility.PolarPoint(ptStart, i, 100#)
        Call ThisDrawing.ModelSpace.AddLine(ptStart, ptEnd)
    Next i

    ThisDrawing.Utility.Prompt vbCrLf & “経過時間は …” & Timer – strStart & “秒” & vbCrLf

End Sub

AutoCAD のインストーラは、AutoCAD をインストールしようとする Windows プラットフォームにビット数に合わせて、同じビット数の AutoCAD をインストールするようになっています。先にご紹介しているように、VBA コンポーネントだけが、32 ビット版しか存在しないことに注意してください。それでは、この VBA マクロを 次の環境でテストしてみます。

  • Windows 7 32 ビット版+AutoCAD 2013 32 ビット版+VBA 32 ビット版
  • Windows 7 64 ビット版+AutoCAD 2013 64 ビット版+VBA 32 ビット版

 Windows では、異なるビット数を同じプロセス内で一緒に動作させることが出来ないため、AutoCAD 64 ビット版と VBA 32 ビット版の各プロセス間を、プロセス間通信で補っているためです。このプロセス間通信をしているコンポーネントが、AutoCAD 2013 の場合 x64VBAServer19.exe で、AutoCAD 本体の acad.exe と通信しながら VBA マクロを実行しているため、全体のパフォーマンスが低下した結果に表れます。

32 ビット版 Windows に場合には、AutoCAD と VBA がどちらも 32 ビット版となるため、AutoCAD のプロセス内で VBA を動作させることができます。このため、プロセス間通信は発生しないので、高速に VBA マクロを実行することができるのです。

VBA マクロ プログラムの互換性

もう 1 つ、ここでは、64 ビット環境に移植できない VBA マクロのプログラム例をご紹介します。

Public Sub Main()

    ‘ 新しい表スタイルの作成
    On Error Resume Next
    Dim oTblDict As AcadDictionary
    Set oTblDict = ThisDrawing.Dictionaries.Item(“ACAD_TABLESTYLE”)
    Dim oTblStyle As AcadTableStyle
    Set oTblStyle = oTblDict.Item(“MyTableStyle”)
    If Err Then

        ‘ 新しい表スタイル “MyTableStyle” を作成
        Err.Clear
        Set oTblStyle = oTblDict.AddObject(“MyTableStyle”, “AcDbTableStyle”)

        ‘ タイトル欄の設定(背景色:青、文字色:白、文字高さ:4.0)
        Dim oColor As AcadAcCmColor
        Set oColor = AcadApplication.GetInterfaceObject(“AutoCAD.AcCmColor.18”)
        Call oColor.SetRGB(255, 255, 255)
        oTblStyle.SetColor acTitleRow, oColor
        oColor.ColorIndex = acBlue
        oTblStyle.SetBackgroundColor acTitleRow, oColor
        oTblStyle.SetTextHeight acTitleRow, 4#
        oTblStyle.TitleSuppressed = False

        ‘ 列見出し欄の色設定(背景色:白、文字色:緑、文字高さ:2.5)
        oColor.ColorIndex = acWhite
        oTblStyle.SetColor acHeaderRow, oColor
        oColor.ColorIndex = acGreen
        oTblStyle.SetBackgroundColorNone acHeaderRow, False
        oTblStyle.SetBackgroundColor acHeaderRow, oColor
        oTblStyle.SetTextHeight acHeaderRow, 2.5
        oTblStyle.HeaderSuppressed = False

        ‘ データ欄の色設定(背景色:なし、文字色:白、文字高さ:2.5)
        oColor.ColorIndex = acWhite
        oTblStyle.SetColor acDataRow, oColor
        oTblStyle.SetBackgroundColorNone acDataRow, True
        oTblStyle.SetTextHeight acDataRow, 2.5
        oTblStyle.SetAlignment acDataRow, acMiddleCenter

    End If
    On Error GoTo 0

    ‘ 配置基点を指示
    Dim ptBase As Variant
    ThisDrawing.Utility.InitializeUserInput 1
    ptBase = ThisDrawing.Utility.GetPoint(, vbCrLf & “表の配置点を指定:”)

    ‘ 表特性の算出
    Dim nRow As Integer
    Dim nCol As Integer
    Dim dHeight As Double
    nRow = ThisDrawing.ModelSpace.Count + 2 ‘ タイトル+列見出し
    nCol = 3
    dHeight = ThisDrawing.GetVariable(“TEXTSIZE”)

    ‘ 現在のレイアウトに表を配置
    Dim oTbl As AcadTable
    Set oTbl = ThisDrawing.ActiveLayout.Block.AddTable(ptBase, nRow, nCol, dHeight, dHeight * 10#)

    oTbl.RegenerateTableSuppressed = True

    oTbl.StyleName = “MyTableStyle”
    oTbl.GenerateLayout

    ‘ タイトルの設定
    oTbl.SetText 0, 0, “モデル空間図形の色一覧”
    oTbl.SetRowHeight 0, 7#
    oTbl.SetText 1, 0, “ハンドル番号”
    oTbl.SetText 1, 1, “クラス名”
    oTbl.SetText 1, 2, “色”
    oTbl.SetRowHeight 1, 5#

    ‘ データの設定
    Dim nRowCnt As Integer
    Dim strField As String
    Dim oEnt As AcadEntity
    For nRowCnt = 2 To ThisDrawing.ModelSpace.Count

        ‘ モデル空間要素の取得
        Set oEnt = ThisDrawing.ModelSpace.Item(nRowCnt – 2)

        ‘ ハンドル番号
        oTbl.SetText nRowCnt, 0, oEnt.Handle

        ‘ クラス名
        oTbl.SetText nRowCnt, 1, oEnt.ObjectName

        ‘ フィールド式(オブジェクトID で特定したオブジェクトの色)
        strField = “%<\AcObjProp Object(%<\_ObjId ” & CStr(oEnt.ObjectID) & “>%).TrueColor>%”
        oTbl.SetText nRowCnt, 2, strField

        ‘ 行高さの設定
        oTbl.SetRowHeight nRowCnt, 5#

    Next

    oTbl.RegenerateTableSuppressed = False

End Sub 

この VBA プログラムは、モデル空間に作図されている図形のハンドル番号、色、図形タイプを AutoCAD の表オブジェクトに書き出す処理をしています。色番号の部分では、それぞれの図形の色を フィールド として書き出されている点に注意してください。フィールドは、図面内の特定の情報を監視して、その情報を文字として表示する機能があります。このプログラムでは、モデル空間の図形、1 つ 1 つを監視して、その図形の色を文字として表示しています。

AutoCADのモデル空間における図形の色一覧を示す表。各行にはハンドル番号、クラス名、色名が記載されている。
<左手のソリッド図形の色を表右手でフィールド文字として表示>

このため、VBA マクロで作図した表の作成後に、参照されている図形の色を変更して、REGEN[再作図] コマンドを実行すると、変更した図形の色が表に自動的に反映されることがわかります(32 ビット プラットフォームのみ)。

そして、この VBA マクロは残念ながら 64 ビット版の AutoCAD では実行時にエラーで正しく動作しません。なぜなら、フィールド文字として図形の色を関連付けるときに、オブジェクト ID と呼ばれる識別子 ObjectID プロパティで利用しているためです。

' フィールド式(オブジェクトID で特定したオブジェクトの色)
strField =   "%<\AcObjProp Object(%<\_ObjId " & CStr(oEnt.ObjectID) & ">%).TrueColor>%"

オブジェクトID は、ObjectARX や AutoCAD .NET API を利用されている方にはおなじみの識別子ですが、この識別子は、プラットフォーム依存なので、このような非互換な結果になってしまうのです。

こういったプラットフォーム差を吸収するために、オートデスクでは、VBA マクロを同じ Visual Basic 言語を利用できる AutoCAD .NET API に移植することをお勧めしています。

AutoCAD 2014 と 64 ビット版 VBA

ここに来て、32 ビット版のコンポーネントしかリリースしていなかった Microsoft 社が、64 ビット版のコンポーネントをリリースすることになりました。つまり、64 ビット版の AutoCAD と同じプロセス内で VBA が実行できるようになります。そして、新しくリリースされた AutoCAD 2014 では、64 ビット版の AutoCAD 用に http://www.autodesk.com/vba-download から 64 ビット版の VBA をダウンロード提供しています。残念ながら、AutoCAD 2014(以降)にしか適用することは出来ませんが、これによって、32 ビット版 AutoCAD と 64 ビット版の AutoCAD で、VBA のパフォーマンス差やコードの非互換性も解消できることが期待できます。

ただし、この状況でも、オートデスクは AutoCAD .NET API への移植を推奨している点に注意してください。VBA の言語仕様は、十数年前の Visual Basic 6.0 のままです。VBA が持つ COM との互換性があり、.NET Framework ベースの新しい VB.NET を使うことが可能な  AutoCAD .NET API が移植先として最適なのです。

By Toshiaki Isezaki

 

 


Comments

Leave a Reply

Discover more from Autodesk Developer Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading