AutoCAD VBA すべてのブロック定義のプロパティを配列に格納するFunction

# はじめに

AutoCADでブロック定義を一覧で確認する際に BEDIT コマンドを使うと思いますが、そこでは「分解の許可」の状態は確認できません。「分解の許可」状態を確認するには、そこから個別にブロックエディタ画面に進み、何も選択していない状態でオブジェクトプロパティ管理パレットを確認する必要があります。

そこで今回は図面に含まれるすべてのブロック定義のプロパティを配列に格納するFunctionを作りました。
なお、表示は別途必要です。ListBoxに表示したり、Excelに直接表示させたり、CSVに吐き出すなどいろいろ考えられますね。

# ブロック定義とブロック参照

| 項目 | オブジェクト | 説明 |
|:-|:-|:-|
|  | Blocks | 図面内のすべてのブロック定義のコレクション |
| ブロック定義 | Block | ブロックの設定情報および構成する図形オブジェクト |
| ブロック参照 | BlockReference | 図面に挿入されたブロック定義のインスタンス |

## Blockオブジェクトで取得できる主要なプロパティ

Blockオブジェクトで取得できる主要なプロパティは以下の通りです。

| プロパティ | 説明 | 型 | 備考 |
|:-|:-|:-|:-|
| Handle         | ハンドル | String |   |
| Name           | 名前 | String |   |
| Comments       | コメント | String |   |
| Explodable     | 分解の許可 | Boolean |   |
| Origin         | 挿入原点 | Variant/Double | 3次元座標を示す配列 |
| Units          | 挿入単位 | Long | acInsertUnits 列挙型 |
| BlockScaling   | 許される尺度 | Long | acBlockScaling 列挙型 |
| Count          | 含まれる図形数 | Long |   |
| IsLayout       | レイアウトブロックの判定 | Boolean |  |
| IsXRef         | 外部参照ブロックの判定 | Boolean |  |
| IsDynamicBlock | ダイナミックブロックの判定 | Boolean |  |

その他、すべてのプロパティについてはヘルプを参照してください。

https://help.autodesk.com/view/OARX/2026/JPN/?guid=GUID-E6F7B03B-F5CC-4A18-9C48-BBF1D32A31FD

## 取得するプロパティの選定

今回は当初の目的を考慮して、以下のプロパティおよびブロックの種類を取得することにします。

- Name
- Comments
- Explodable

なお、ブロックの種類のうち、レイアウトブロック、外部参照ブロック、ダイナミックブロックはプロパティで判断できます。それ以外がいわゆる「単純なブロック」ということになります。
ここではさらに「単純なブロック」を「匿名ブロック」(*で始まる名前)、「特殊ブロック」(_で始まる名前)、「通常ブロック」(それら以外)に分類しました。

# コード

## すべてのブロック定義のプロパティを配列に格納する

:::note info
```text
構文  : RetVal = uFnGetBlocksInfoArray( aoDoc )
引数  : 図面 | aoDoc As AcadDocument
戻り値: 配列 | RetVal As Variant
```
:::

```vb:AutoCAD VBA
Public Function uFnGetBlocksInfoArray(ByVal aoDoc As AcadDocument) As Variant
  
  ' 仮戻り値の動的配列を定義
  Dim uTempArray() As Variant
  
  ' すべてのブロック定義を取得
  Dim oBlocks As AcadBlocks
  Set oBlocks = aoDoc.Blocks
  
  ' ブロック定義数を取得
  Dim uBlocksCount As Long
  uBlocksCount = oBlocks.Count
  
  ' 配列の要素数が確定
  ReDim uTempArray(uBlocksCount, 3)
  
  ' 初期値を格納(ヘッダー) ※テキストはダブルクォーテーションで囲う
  uTempArray(0, 0) = uFnSetDQ("ブロック種別")
  uTempArray(0, 1) = uFnSetDQ("ブロック定義名")
  uTempArray(0, 2) = uFnSetDQ("コメント")
  uTempArray(0, 3) = uFnSetDQ("分解を許可")
  
  ' 各ブロックのプロパティを格納 ※テキストはダブルクォーテーションで囲う
  Dim oBlock As AcadBlock
  Dim r As Long
  For r = 0 To uBlocksCount - 1
    Set oBlock = oBlocks.Item(r)
    uTempArray(r + 1, 0) = uFnSetDQ(zFnGetBlockType(aoBlock:=oBlock))
    uTempArray(r + 1, 1) = uFnSetDQ(oBlock.Name)
    uTempArray(r + 1, 2) = uFnSetDQ(oBlock.Comments)
    uTempArray(r + 1, 3) = oBlock.Explodable
  Next
  
  ' 戻り値
  uFnGetBlocksInfoArray = uTempArray
  
  ' オブジェクト変数の解放
  Set oBlock = Nothing
  Set oBlocks = Nothing
  
End Function
```

## テキストをダブルクォーテーションで囲うFunction

特にコメントに改行やコンマが含まれていることがあるため、配列に String を格納するときにはダブルクォーテーションで囲んでいます。
※コメント内のダブルクォーテーションのエスケープ処理は入れていません

:::note info
```text
構文  : RetVal = uFnSetDQ( aText )
引数  : 対象の文字列                       | aText As String
戻り値: ダブルクォーテーションで囲んだ文字列 | RetVal As String
```
:::
```vb:AutoCAD VBA
Public Function uFnSetDQ(ByVal aText As String) As String
  uFnSetDQ = Chr(34) & aText & Chr(34)
End Function
```

## ブロック定義の種類を取得するFunction

:::note info
```text
構文  : RetVal = zFnGetBlockType( aoBlock )
引数  : ブロック定義      | aoBlock As AcadBlock
戻り値: ブロック定義の種類 | RetVal As String
```
:::
```vb:AutoCAD VBA
Private Function zFnGetBlockType(ByVal aoBlock As AcadBlock) As String
  ' 仮戻り値
  Dim uRetVal    As String
  
  ' プロパティの取得
  Dim uBlockName As String
  uBlockName = aoBlock.Name
  Dim uIsDynamic As Boolean
  uIsDynamic = aoBlock.IsDynamicBlock
  Dim uIsLayout  As Boolean
  uIsLayout = aoBlock.IsLayout
  Dim uIsXRef    As Boolean
  uIsXRef = aoBlock.IsXRef
  
  ' ブロック種別の判定
  If uIsDynamic = True Then
    uRetVal = "ダイナミックブロック"
  ElseIf uIsLayout = True Then
    uRetVal = "レイアウトブロック"
  ElseIf uIsXRef = True Then
    uRetVal = "外部参照ブロック"
  ElseIf Left$(uBlockName, 1) = "_" Then
    uRetVal = "特殊ブロック"
  ElseIf Left$(uBlockName, 1) = "*" Then
    uRetVal = "匿名ブロック"
  Else
    uRetVal = "通常ブロック"
  End If
  
  '戻り値
  zFnGetBlockType = uRetVal
End Function
```

# おわりに

今回はすべてのブロックを配列に入れましたが、実際に必要とするのはほとんどの場合、ダイナミックブロックと通常ブロックだけだと思います。ブロック種別の判定コードも入れているので、少しいじれば作れますね。