仕様ツリーの構成をExcelファイルに出力するマクロ|CATIAマクロの作成方法

今回の記事は「マクロ案」よりいただいた内容です。
送って頂いた内容は以下のようなマクロです。

ワークベンチ: Part Design

マクロ案: 仕様ツリー上の各要素の名称をExcelに読み込み、
              Excel上で名称を変更したものを仕様ツリーに反映するマクロ
            (CATIAのマクロというよりExcelのマクロかも)

今回のマクロは下記の2つのマクロで構成していきます。
①「仕様ツリーのオブジェクト名をExcelファイルとして出力するマクロ」
②「編集したExcelファイルを読み込み仕様ツリーに反映するマクロ」
本ページでは①のマクロについて紹介していこうと思います。
(①のマクロだけの内容ですが結構長めなので頑張ってください)

CATIA VBAのオブジェクト構造を理解している方ならある程度予想ができると思いますが、仕様ツリーの階層を考慮して上から順にオブジェクトを取得することは実はかなり難しいです。そこで今回は「パートデザイン」「ジェネレーティブ・シェイプ・デザイン」の基本的なコマンドであれば実行可能なマクロを”簡単なコード”で作成しました。

簡単なコードの分、エラー処理や一部オブジェクトには対応していないという状態ですが、どのようにしてツリー構成を取得しているのかは理解しやすい内容になっていると思います。

もし本格的に取得したい場合は下記サイトのマクロを参考にしてみて下さい。
BodyのTreeを各種フォーマットでエクスポートする – C#ATIA
ハードルは少し上がりますがクラスモジュールなども使いしっかりとしたコードで作成されています。

 

マクロの機能

今回作成したのは仕様ツリーの構成をExcelファイルに出力するマクロです。
オブジェクト名を編集する際にわかりやすいよう、上画像のように仕様ツリーの階層をExcel上で再現して出力するようになっています。

具体的な機能は以下のとおりです。

  マクロの機能まとめ ・仕様ツリーの構成をExcelファイルに出力する
・[パートデザイン]だけでなく [GSD]ワークベンチでも実行可能
・一部オブジェクトは出力されない(座標系、スケッチ内要素、ナレッジ関連のオブジェクト等)
 → 非対応オブジェクトを対応させるにはコードにそれぞれの処理を書く必要あり

※すべてのオブジェクトで試したわけではないので、場合によってエラーが発生します。
 その場合はそのオブジェクトを除外するか専用の処理を追記する必要があります
 (詳しくはコード解説部分で説明しています)

今回のマクロでは仕様ツリーの階層を考慮してExcelファイルとして出力していますが、その部分を考慮せず上から順にオブジェクト名を羅列するだけあればもっと単純なコードで済みます。
 

サンプルコード

マクロのコードは以下のとおりです。

処理の流れとしては下記のような流れになっています。ツリーの階層は考慮せずに1行でExcelに出力する場合は、”階層の取得”が不要になるため②の処理がもっとシンプルになります。

① ドキュメント内の全オブジェクトからExcelに出力するオブジェクトを選別しすべて取得 
② 取得したオブジェクトをループ処理
 ②-1 オブジェクトの階層を取得
 ②-2 オブジェクトの階層に応じてExcelの行を変化させながらオブジェクト名を出力
③ Excelを表示
 

 

コード解説

アクティブドキュメント等の定義

まずはじめにアクティブドキュメントを定義をします。
今回のマクロはCATPartのみ有効なものなので、アクティブドキュメントがCATPart以外の場合はTypeName関数を使った条件分岐でマクロを終了するようにしています。つまり、アクティブドキュメントがCATPartの場合のみ変数「doc」にアクティブドキュメントを代入し、マクロの処理を続けます。

アクティブドキュメントが定義できたら、以降で使うためのオブジェクト/変数をまとめて定義しておきます。ここでは下記の用途で各オブジェクト/変数を定義しています。

Partオブジェクト   :ツリー第1階層指定用
Selectionオブジェクト ドキュメント内のオブジェクトを”上から順”に取得する用
objs (As Collection)   :Excelに出力するオブジェクトを全て格納する用
obj  (As AnyObject)   :
objs内ループ(For Each ~ In ~)用変数
i      (As Long)            :
Forループ用カウント変数

 
Excelに出力するオブジェクトの選別

つぎにExcelに出力するオブジェクトをすべて取得します。
このとき、必要のないオブジェクトは除外します。この部分は自身の出力したい内容に合わせて書き換えて下さい。

オブジェクトの選別する方法は簡単で一度オブジェクトをすべて選択状態にし、条件を絞りながら選択しているオブジェクトを順に「objsコレクション」に格納していくだけです。この考え方は「選択しているオブジェクトを一時保管する方法」を参照下さい。

上記コードでいう「TypeName(obj)=”XXXX”」のXXXXのオブジェクトは除外するようになっています。除外する理由は2つあります。

1つ目はそこまで細かく必要ないためです。
あくまで個人の主観ですが、「長さや角度といったパラメータ」「スケッチ内の形状や拘束」などはあえて出力する必要はないと感じたため、ここでは除外しています。コードでいうと一番初めの条件分岐「If InStr(obj.Name, “\”) = 0 And InStr(TypeName(obj), “2D”) = 0 Then」と次の条件分岐内の「TypeName(obj) = “Constraint”」の部分です。

2つ目は除外しないとコードがうまく実行できないためです。
今回のコードはのちに出てくる関数「get_hierarchy」を使ってオブジェクトの階層を調べます。
この関数では単純に「obj.Parent.Parent…」のように親オブジェクトをさかのぼっていくものなのですが、一部オブジェクトではこの方法が通用しません。例えば「式」や「座標系」などのオブジェクトはVBAオブジェクトの関係上、通常のオブジェクトと同じ方法では階層を調べることが出来ません。

そのため、必要であれば関数「get_hierarchy」に各オブジェクト別の処理を追加すればここで除外する必要は無くなります。ただ、それをすべてのオブジェクトで対応するには膨大なコードになるため、ここでは個人的にやっていてうまく階層が取得できなかったオブジェクトのみを全て除外しています。(おそらく他にもうまくできないオブジェクトあるので、適宜ここで除外するか関数内に専用の処理を追加してください)
 

Excel定義 + 変数定義

つぎに出力先となるExcelのブックを新規作成し、シートを定義します。
Excelの定義方法については「CATIAマクロでExcelを操作する方法」を参照下さい。
上記ページにも書かれている通り、参照設定をしていないと実行できないので注意して下さい。

Excelが定義できたら、以降で使うための変数をまとめて定義しておきます。ここでは下記の用途で各変数を定義しています。

hierarchy (As Long):オブジェクトのの階層格納用
cnt           (As Long):カウント変数
max_r     (As Long):Excel出力時に値を持つセルの最終行格納用
max_c     (As Long):
Excel出力時に値を持つセルの最終列格納用

 
オブジェクトの階層を取得しExcelにオブジェクト名を出力する

つぎに本マクロの核となるExcel出力処理です。
objsコレクション内に入っているオブジェクトの名称を順にExcelに出力していきます。

その際に関数「get_hierarchy」を使ってオブジェクトの階層を取得します。
この取得した階層を使って「Cells(cnt, hierarchy).Value = obj.Name」と書くことで、1行目から順にオブジェクトの名前を出力するだけでなく、階層別に列もそろえることが可能になります。
あわせて「Cells(cnt, hierarchy – 1).Value = “∟”」と書いておけば、オブジェクト名を出力したセルの左側のセルにツリーの枝部分を書き出すことができます。

これでオブジェクトの書き出しの処理自体は完了です。
以降ではより見やすくなるようセルの幅を揃えたり、ツリーの枝部分を作成したりします。

また、初めに書いている2行はそれぞれ下記のような役割です。
書かなくても処理自体に大きな影響は与えません。

appExcel.ScreenUpdating = False        Excelの動作を不可視化し処理速度を上げる
CATIA.StatusBar = “ツリー構成をExcelに出力中…”  CATIAステータズバーにメッセージ表示

 

Excelファイルの体裁を整える

つぎに出力先したExcelファイルを見やすくするために軽く編集していきます。

やっていることとしては下記の3点です。
①「ツリー枝部分の列幅を調整」
②「ツリー枝部分の作成」
「ツリー最終位置に”――”を入力」

このうち②「ツリー枝部分の作成」はオブジェクトの数によっては(オブジェクト数が5000を超えたあたりから)処理が重くなるため、コメントアウトして処理速度を優先にすることもできます。場合によって使い分けるか、もっと効率の良い方法があればそちらに書き換えてみて下さい。

③「ツリー最終位置に”――”を入力」は、Cells(max_r+1 , 1)からCells(max_r+1 , max_c)の間に”―”を入力しています。つまりは、その”―”部分を読み取れば、ツリーのサイズ(最終行と最終列)を取得することができます。
これは「編集したExcelファイルを読み込み仕様ツリーに反映するマクロ」を使う際に使用するためのものです。そちらのマクロも合わせて使う場合はこの処理は残しておいて下さい

最後に出力したExcelブックや完了メッセージを表示させれば完了です。
 

関数「get_hierarchy」

最後にこれまでにも何度か出てきた関数「get_hierarchy」についてです。
この関数は入力されたオブジェクトの階層を取得し、Long型の数値として返す機能を持っています。

ここで注意してほしいのは、「ここで出力される階層≠CATIAのツリーの階層」という点です。
この関数はExcel出力用のためPartが「1」、パーツボディーやXY平面などが「2」として出力されます。
つまりは「ここで出力される階層 – 1=CATIAのツリーの階層」と思ってもらえれば大丈夫です。

階層の取得方法は、入力されたオブジェクトの親オブジェクトをたどっていき「PartDocument」にたどり着くまでの回数を数えているだけです。

ここで注意しないといけないのが一部オブジェクトではこの方法で対応できないという点です。
たとえばデータム化した点や曲線の場合、ツリーの深くの階層にいたとしても下記のような流れで「PartDocument」にたどり着くため、階層がおかしなことになってしまいます。

 HybridShapeCurveExplicit < Parameters < Part <PartDocument 

 
この場合は「Thickness」を挟めば問題が解決するとわかったため、データム化されたオブジェクト(つまりは「Explicit」と含まれるオブジェクト)には「Thickness」を挟む専用の処理を追加しています。

これと同じで親をさかのぼっていくことがうまくできないオブジェクトがいくつか存在しています。
そもそも「PartDocument」にたどり着かないもの、たどり着くまでの回数がおかしいものなどの要因があります。こういった場合はデータム化されたオブジェクトのように専用の処理を追加するか、コード冒頭のオブジェクトの選別の時点で除外するかのどちらかが必要になってきます。

本マクロを使う場合はエラーが出るたびにそのオブジェクトをどうするか(除外or専用コード追加)を決め、徐々に最適化していくことになると思います。ただ、これは一部のオブジェクトに対していえることなだけであって、基本的なオブジェクトには対応しているはずです。

 

まとめ

今回は仕様ツリーの構成をExcelファイルに出力するマクロについての内容でした。

やっていることは自体は簡単なコードにしましたが、どうしてもその分対応しきれないオブジェクトが出てきてしまっています。ある程度は対応しているので、これで良しとするのであれば問題ないですが、もっとしかっりとしたコードにしたいという場合は冒頭でも紹介した下記サイトを参考にしてみて下さい。
BodyのTreeを各種フォーマットでエクスポートする – C#ATIA
 

サンプルマクロ集に戻る
目次へ戻る

 

 CATIAマクロを本気で勉強するなら

2021年6月23日CATIA, CATIAマクロ, Excel, VBA

Posted by Lic