Product内のCATPartをSTLファイルで出力|CATIAマクロの作成方法
今回の記事はマクロ案募集でいただいた内容です。
送って頂いた内容は以下のようなマクロです。
ワークベンチ: アセンブリデザイン
マクロ案:
Product内のパートファイルを、 STL形式でエクスポートする実はこちらのWebにアップされている
「Product内のパートファイルを、 STP形式でエクスポートする」のプログラムを自分で編集してSTL形式でエクスポートしてみよ うとしたところ「コンテキストで編集中はSTLとして保存できません」 というメッセージが出てきてしまい変換ができなかったのですが何 か良い方法をご存じないでしょうか。
本サイトでは「IGESファイルで出力」「STEPファイルで出力」の2パターンのファイルで出力するマクロの紹介をしています。基本的にはどちらも同じコードで、コード内の拡張子部分さえ書き換えればそれぞれのファイルで出力することができるようなコードになっています。
ただ「STLファイル」の場合は同じ方法では書き出すことができません。
そのためここでは、上記リンク先のサンプルマクロを書き換え、Product内のPartファイルをSTLファイルとして出力するためのマクロを紹介します。
マクロの機能
今回作成したマクロはCATPartをSTLファイル(拡張子.stl)として出力するマクロです。
具体的な機能は以下のとおりです。
・CATPartを選択した場合はそのCATPartのみをSTLファイルとして出力
・ファイル名は「各CATPartのパーツ番号.stl」
・マクロ実行後にデスクトップに新規作成される「STL書き出し 日時」フォルダに出力
・出力後はフォルダを開く
※注意点
・設計モードなっているCATPartのみ対応
・「STL書き出し 日時」と同名のフォルダがデスクトップにある場合はマクロ中断
(日時には現在の「年/月/日/時/分/秒」が入力されるため、同名フォルダは存在しないはず )
上記の注意点にも書かれているとおり設計モードのCATPartのみ出力することができます。
表示モードになっているCATPart出力処理が無視されるので注意して下さい。
(上画像の場合「Part2.CATPart」のみ表示モードになっています)
サンプルコード
マクロのコードは以下のとおりです。
マクロ実行後に選択したProduct以下にあるCATPartをすべてSTLファイルとして出力します。
実行後にマクロの操作をキャンセルしたい場合は[Esc]キーを押下してください。
※コピペで実行可能ですが、保存場所のパスだけは自身の環境に合わせて書き直す必要あり。
下記コード60行目の"SavePath"の中身を自身の環境に合わせて書き換えないと、
85行目の「Set CreateFold = FileSys.CreateFolder(FoldPath)」でエラーが発生するので注意。
Option Explicit Sub CATMain() 'アクティブドキュメント確認 If TypeName(CATIA.ActiveDocument) <> "ProductDocument" Then MsgBox "このマクロはProductDocument専用です。" & vbLf & _ "アセンブリーワークベンチに切り替えて実行してください。" Exit Sub End If Dim ProDoc As ProductDocument Set ProDoc = CATIA.ActiveDocument '********************************************* ' Product選択 '********************************************* Dim sel 'As Selection Set sel = ProDoc.Selection sel.Clear Dim Filter Filter = Array("Product") Dim msg As String msg = "Productを選択してください。" Dim Status As String Status = sel.SelectElement2(Filter, msg, False) If Status <> "Normal" Then MsgBox "キャンセルします。" Exit Sub End If 'ユーザーが選択したProduct以下にあるPartを全て取得 sel.Search ("プロダクト・ストラクチャー.パーツ,sel") If sel.Count = 0 Then MsgBox "選択したProduct内にPartは存在しません。" Exit Sub End If Dim i As Integer Dim Parts As Collection Set Parts = New Collection For i = 1 To sel.Count Parts.Add sel.Item(i).Value Next i sel.Clear '********************************************* ' 書き出し用フォルダ作成 '*********************************************[ '保存場所のパスを入力 ※必ず自分の環境のものに書き換えて下さい Dim SavePath As String SavePath = "C:\Users\ユーザー名\Desktop" '作成するフォルダ名を指定 Dim FoldName As String FoldName = "STL書き出し " & Year(Date) & Month(Date) & Day(Date) & _ Hour(Time) & Minute(Time) & Second(Time) '新規フォルダのパス作成 Dim FoldPath As String FoldPath = SavePath & "\" & FoldName '" '同名フォルダの存在を確認 Dim FileSys 'As FileSystem Set FileSys = CATIA.FileSystem Dim FoldExi As Boolean FoldExi = FileSys.FolderExists(FoldPath) If FoldExi = True Then MsgBox "予期せぬエラーが発生しました。" & vbLf & _ "再度マクロを実行し直してください。" Exit Sub End If 'フォルダ作成 Dim CreateFold As Folder Set CreateFold = FileSys.CreateFolder(FoldPath) '********************************************* ' STL出力 '********************************************* 'ループが終わるまで画面更新と確認メッセージの表示を一時的に行わない CATIA.RefreshDisplay = False CATIA.DisplayFileAlerts = False Dim PartDoc As Document Dim cnt As Integer For i = 1 To Parts.Count On Error Resume Next '条件分岐:Partのパーツ番号が""でない場合(=設計モードの場合) If Parts.Item(i).PartNumber <> "" Then 'ProductをPartDocumnet(CATPart)に変換 Set PartDoc = Parts.Item(i).ReferenceProduct.Parent On Error GoTo 0 'CATPartのフルパスを取得 Dim PartPath As String PartPath = PartDoc.FullName 'CATPartを開く Dim OpenPart As Document Set OpenPart = CATIA.Documents.Open(PartPath) 'STL形式で出力 OpenPart.ExportData FoldPath & "\" & PartDoc.Part.Name & ".stl", "stl" '" 'CATPartを閉じる OpenPart.Close cnt = cnt + 1 End If Next i CATIA.RefreshDisplay = True CATIA.DisplayFileAlerts = True 'STLファイルを出力したフォルダを開く If cnt <> 0 Then Shell "C:\Windows\Explorer.exe " & FoldPath, vbNormalFocus Else MsgBox "STL出力するPartを設計モードに切り替えて再度実行して下さい。" End If End Sub
コード解説
アクティブドキュメントの定義
'アクティブドキュメント確認 If TypeName(CATIA.ActiveDocument) <> "ProductDocument" Then MsgBox "このマクロはProductDocument専用です。" & vbLf & _ "アセンブリーワークベンチに切り替えて実行してください。" Exit Sub End If Dim ProDoc As ProductDocument Set ProDoc = CATIA.ActiveDocument
まずはじめにアクティブドキュメントの定義をします。
今回のマクロはCATProductでのみ有効なものなので、アクティブドキュメントがCATProduct以外の場合はTypeName関数を使った条件分岐でマクロを終了するようにしています。
条件分岐の先、つまりはアクティブドキュメントがCATProductの場合は変数「ProDOC」にアクティブドキュメントを代入します。
ユーザー選択のProduct内にあるすべてのPartを取得
Dim sel 'As Selection Set sel = ProDoc.Selection sel.Clear Dim Filter Filter = Array("Product") Dim msg As String msg = "Productを選択してください。" Dim Status As String Status = sel.SelectElement2(Filter, msg, False) If Status <> "Normal" Then MsgBox "キャンセルします。" Exit Sub End If 'ユーザーが選択したProduct以下にあるPartを全て取得 sel.Search ("プロダクト・ストラクチャー.パーツ,sel") If sel.Count = 0 Then MsgBox "選択したProduct内にPartは存在しません。" Exit Sub End If Dim i As Integer Dim Parts As Collection Set Parts = New Collection For i = 1 To sel.Count Parts.Add sel.Item(i).Value Next i sel.Clear
次にユーザーが選択したProduct内にあるPartをすべて取得していきます。(最終的にはループ文を使って、ここで取得したPartを1つずつSTLファイルに出力していくという処理を行います。)
まずは「Selectionオブジェクト」の「SelectElement2メソッド」を使って任意のProductを選択状態にします。つぎに同オブジェクトの「Searchメソッド」を使って選択状態にしたProduct内にあるPartノードをすべて選択状態にします。
これでユーザーが選択したProduct内にある、すべてのPartノードが選択状態となります。
※このとき選択状態のCATPartの数が0個の場合にはマクロを中断するよう条件分岐をさせます。
最後に現在選択中のPartノードを「Parts」というコレクションに格納しておきます。
この操作を行う理由は「選択しているオブジェクトを一時保管する方法」を参照下さい。
書き出し用のフォルダを作成
'保存場所のパスを入力 ※必ず自分の環境のものに書き換えて下さい Dim SavePath As String SavePath = "C:\Users\ユーザー名\Desktop" '作成するフォルダ名を指定 Dim FoldName As String FoldName = "STL書き出し " & Year(Date) & Month(Date) & Day(Date) & _ Hour(Time) & Minute(Time) & Second(Time) '新規フォルダのパス作成 Dim FoldPath As String FoldPath = SavePath & "\" & FoldName '" '同名フォルダの存在を確認 Dim FileSys 'As FileSystem Set FileSys = CATIA.FileSystem Dim FoldExi As Boolean FoldExi = FileSys.FolderExists(FoldPath) If FoldExi = True Then MsgBox "予期せぬエラーが発生しました。" & vbLf & _ "再度マクロを実行し直してください。" Exit Sub End If 'フォルダ作成 Dim CreateFold As Folder Set CreateFold = FileSys.CreateFolder(FoldPath)
STLファイルを出力するためのフォルダを作成します。
まずは保存場所のパスを取得します。
上記のコードでは保存場所を「SavePath = “C:\Users\ユーザー名\Desktop"」
つまりはデスクトップとしています。
※再三の注意となりますがここのパスはご自身のPCのパスに書き換えて下さい。
多くの場合、「ユーザー名」の部分を自分のものにすれば問題ないと思います。
次に、作成するフォルダの名称を指定します。
上記コードでは「STL書き出し 日時」というフォルダ名で作成しています。
(日時には現状の日時の年から秒までを取得し、その数字の羅列を入力しています。
たとえば2020年1月2日3時4分56秒の場合、「20200102030456」と入力されます。)
このようにフォルダ名を時間によって変更させることで
デスクトップ上に同じフォルダが存在しないようにしています。
ただ必ずしも存在しないとは言えないので
万が一同じフォルダが存在した場合にはマクロを終了するようにしています。
フォルダの存在を確認するには「FileSystemオブジェクト」の「FolderExistsメソッド」を使います。
最後に、これまでに決めた「保存場所」と「フォルダ名」を組み合わせてフォルダを新規作成します。
フォルダの作成は「FileSystemオブジェクト」の「CreateFolderメソッド」を使って行います。
「FolderExistsメソッド」「CreateFolderメソッド」の使い方は下記ページを参照ください。
STLファイル出力
'ループが終わるまで画面更新と確認メッセージの表示を一時的に行わない CATIA.RefreshDisplay = False CATIA.DisplayFileAlerts = False Dim PartDoc As Document Dim cnt As Integer For i = 1 To Parts.Count On Error Resume Next '条件分岐:Partのパーツ番号が""でない場合(=設計モードの場合) If Parts.Item(i).PartNumber <> "" Then 'ProductをPartDocumnet(CATPart)に変換 Set PartDoc = Parts.Item(i).ReferenceProduct.Parent On Error GoTo 0 'CATPartのフルパスを取得 Dim PartPath As String PartPath = PartDoc.FullName 'CATPartを開く Dim OpenPart As Document Set OpenPart = CATIA.Documents.Open(PartPath) 'STL形式で出力 OpenPart.ExportData FoldPath & "\" & PartDoc.Part.Name & ".stl", "stl" '" 'CATPartを閉じる OpenPart.Close cnt = cnt + 1 End If Next i CATIA.RefreshDisplay = True CATIA.DisplayFileAlerts = True
今回のマクロのメインの部分の処理「STLファイル出力」をしていきます。
現在、ユーザーが選択したProduct内にあるすべてのPartが入った「Parts」コレクションがあります。ここではループ文を使って「Parts」の中身を1つずつSTLファイルとして書き出していきます。
任意のドキュメントを別ファイルとして書き出すには
「Documentオブジェクト」の「ExportDataメソッド」を使います。
Documentオブジェクト.ExportData パス,“拡張子“
この構文によりDocumentオブジェクトを指定した拡張子で書き出すことができます。
パスには出力先のパス(ファイル名も含む)を入力、
拡張子には出力するファイルの拡張子を入力します。
STLファイルで出力する際はIGESやSTEPファイルの時とは違い、パスに「.stl」と拡張子を付ける必要があるので注意しましょう。
ただProductDocument上で上記のコードを使ってもSTLファイルを出力することが出ません。どうやらCATIA VBAでSTLファイルとして書き出すにはアクティブドキュメントがPartDocument(CATPart)である必要がありそうです。
(確認としてProduct上で[ファイル]>[名前を付けて保存]をクリックし[ファイルの種類]を確認するとわかりますが、「.CATProduct」は「.igs」や[.stp]に切り替えることはできますが、[.stl]に切り替えることができないことがわかります)
そこで今回のコードでは以下のような処理を行います。
② パスをもとにCATPartを新規ウィンドウで開く
③ CATPartをSTLファイルとして出力
④ CATPartを閉じる
⑤ Partsコレクション内のPartの数だけ①から④をループする
処理の流れを見るとわかる通り、CATPartを開いては閉じ、開いては閉じを繰り返します。
そのためデータが重いProductファイルでは処理に時間がかかることが予想されます。
しかし、モードを切り替えること自体はできますが、現在のモードがどちらなのかを取得するためのプロパティ/メソッドは用意されていません。
ただ、専用のプロパティ/メソッドが存在しなくとも、エラーを無視する「On Error Resume Next」とプロダクトのパーツ番号を取得するための「PartNumberプロパティ」をうまく使えば現在のモードを調べることができます。(下記コード参照)
On Error Resume Next If Productオブジェクト.PartNumber <> "" Then '設計モードの処理 Else '表示モードの処理 End If On Error GoTo 0
基本的にProductにつられているPartには必ず「パーツ番号」が存在しており、「PartNumberプロパティ」を使うことでパーツ番号を取得することができます。そのため「PartNumberプロパティ」で取得した値が「""」(空白)になることはあり得ません。
ただ「On Error Resume Next」を使うことで、必ずしもそうであるとは言えなくなります。
表示モードのProductに「PartNumberプロパティ」を使うとエラーが発生して処理が止まってしまいますが、「On Error Resume Next」を使うことでエラーは起こさないようにすることができます。このとき「PartNumberの取得」を無視するため、実質的に取得される値は「""」(空白)となります。
つまり「If Productオブジェクト.PartNumber <> “" Then」という条件を使うことで、設計モード/表示モードのProductそれぞれに処理を割り振ることができるという訳です。
出力フォルダを表示
'STLファイルを出力したフォルダを開く If cnt <> 0 Then Shell "C:\Windows\Explorer.exe " & FoldPath, vbNormalFocus Else MsgBox "STL出力するPartを設計モードに切り替えて再度実行して下さい。" End If
最後にデスクトップに作成したフォルダを「Shell関数」を使って開きます。
Shell関数についてはExcelマクロでもよく使われ、多くの解説ページがあるためここでは割愛します。
また、先のループ内でカウント変数「cnt」を使い、もしユーザーが選択したProduct内に設計モードのProductが入っていない場合には、その旨をメッセージボックスで表示するようにもしています。
まとめ
今回は任意のCATPartをSTLファイルとして出力するマクロについての内容でした。
STLファイルはCATProductから直接出力することができなかったため、今回のように少し無理矢理な方法で出力する必要がありそうです。(他にいい案があるかもしれませんが)
また、アクティブドキュメントがCATProductである際に、アクティブドキュメントを切り替えずにCATPartを取得し、STLとして書き出そうとしてもうまく出力することができませんでした。このことから、アクティブドキュメントがCATPartであることが前提なのかもしれません。
CATIAのSTLファイルに関しては海外サイトを含めても情報が少ないので他にもい方法が隠れているかもしれません。何かいい情報があれば、ぜひ「お問い合わせ」よりご連絡下さい。