MVVMお勉強中ですが、イヤになってきたので久々にC#でCATIAの
マクロをちょっと作ろうかなぁ と思ったのですが、諦めました。
何時かは書こうかと思っていたので、折角の機会なので。
1.マクロの記録が取れない
結構重要です。 個人的には各コマンド類(~Factory.AddNew~メソッド類)
や検索キーワード(Selection.Search "~")等は、イチイチ覚えていません。
必要な時に記録を取って、必要な部分だけ(大半が2行)コピーし後は
捨てています。こちらのマクロを作ったのは、その為です。
GrabCAD - CAD library
2.参照設定がシンドイ
こちらでは参照設定の方法を記載しましたが
DotNetでCATIA V5のマクロを作成する際の準備 - C#ATIA
こちらのコメント部に、imihitoさんアドバイスを頂きました。
Excelフォームボタンからマクロの起動 (未確認) - C#ATIA
CATIAっぽい全てのものを設定する必要は無いのですが、
結果的に何の参照が不足しているのかわからず、VBエディターを
開き、オブジェクトブラウザで該当するファイルを調べまくっている
と言うのが本音です。
3.デバッグが辛い
IDEを利用する利用の1つが、デバッグの行いやすさじゃないかと
思います。(インテリセンスもあるかもしれませんが)
個人的にはローカルウィンドウが重要で、変数の中身の状態が確認出来る
だけではなく、プロパティ類の中身をさかのぼって確認出来る点は
非常にありがたく、未知のオブジェクトを調べる際はかなり重宝します。
ところが、C#(DotNet)ではダメなんです。
こちらはVBAで"形状セット1"を選択した状態です。
スケッチやジオメトリ(点・線・面)等も確認可能ですし、Parentをさかのぼって
行けばPartやPartDocumentも取得可能です。
(Documentが取得できれば、大半 事が足ります)
一方、C#の場合はこちら。
"形状セット1"の名前すら確認出来ない状態です。 種類の部分は
”MECMOD.HybridBod{System.__ComObject}”と表示されていますが
これは形状セットとわかっている為、キャストした状態だからです。
キャストしないとこんな感じです。
"INFITF.CATBaseDispatch" じゃ何だかわからないです。
GetTypeメソッドを利用しても
{Name = "__ComObject" FullName = "System.__ComObject"}
と返って来るだけ。 COMオブジェクトだってことは、GetTypeする前から
知ってます・・・。
COM相互運用が原因だとはわかっているのですが、
「動くようにしましたよ」ってだけで同等ではないです。
4.CATSafeArrayVariantが機能していない(と思った)
今日わかったのがこれです。これが書きたかったんです。
"CATSafeArrayVariant" は、点の座標値等受け取る際のもので
Variant配列です。 単純に面を選択し重心を所得する
VBAのコードです。
'vba using-'KCL0.0.12' Sub CATMain() If Not CanExecute("PartDocument") Then Exit Sub Dim msg$: msg = "面を選択" Dim elm As SelectedElement Set elm = KCL.SelectElement(meg, "Face") If elm Is Nothing Then Exit Sub Dim doc As PartDocument Set doc = elm.Document Dim ref As Reference Set ref = elm.Reference Dim spa_wb As Object Set spa_wb = doc.GetWorkbench("SPAWorkbench") Dim mes As Variant 'Measurable Set mes = spa_wb.GetMeasurable(ref) Dim cog(2) As Variant 'これが CATSafeArrayVariant Call mes.GetCOG(cog) Debug.Print "重心 : "; Join(cog, ",") End Sub
最後の方の "cog(2)" が、"CATSafeArrayVariant"です。
取得する際のGetCOGメソッドは、Measurableオブジェクトですが、
正しく型指定するとエラーになります。
(この手の、処理結果を引数のVariant配列に返す、悪魔仕様の
ものは大半が型指定するとエラーになります)
同様の処理をC#でさせます。
(コードが長くなりすぎる為、例外処理はほぼしてません)
//cs ↓これらの参照設定必要です using System.Runtime.InteropServices; using INFITF; using MECMOD; using SPATypeLib; class Program { static void Main() { //モロモロ var cat = (INFITF.Application)Marshal.GetActiveObject("CATIA.Application"); var doc = cat.ActiveDocument as MECMOD.PartDocument; //選択 var msg = "面を選択"; var sel = doc.Selection; var cancel_code = new string[] { "Cancel", "Undo", "Redo" }; var filter = new object[] { "Face" }; sel.Clear(); string res = sel.SelectElement2(filter, msg, false); if (cancel_code.Any(x => x.ToString() == res)) { return; } var face_ref = sel.Item2(1).Reference; //SPAWorkbench var SpaWB = doc.GetWorkbench("SPAWorkbench") as SPAWorkbench; if (SpaWB == null) { return; } //Measurable var mes = SpaWB.GetMeasurable(face_ref); //重心 var cog = new object[3]; mes.GetCOG(cog); Console.WriteLine(string.Format( "重心 : {0},{1},{2}", cog[0], cog[1], cog[2])); Console.ReadKey(); } {
VBAのVariant配列は、C#の場合object配列です。 これ
mes.GetCOG(cog);
ここでエラーになる予定だったのですが、正しく処理してます・・・。
不安定ですね・・・。本当は
var mes_oj = mes as object; mes_oj.GetCenter(cog);
だと、型付けが邪魔で出来ないから
dynamic mes_oj = mes as object; mes_oj.GetCenter(cog);
にしたけど、やっぱりエラーになるよ って書きたかったのですけどね。
こちらでも機能してないって書いてあるんですけど。
http://www.coe.org/p/fo/st/per=10&sort=0&thread=24278&p=1
他にも
・C#だと "遅い" → どうでも良いです。
DLL化すれば同レベルで処理します。(要レジストリに登録ですが)
・C#だと配布しやすい → catvbsやvbsでも同様です。
・catvbsやvbsだとソースコード見られちゃう
→ CATVBAでパスワード付けるか。
vbsを暗号化
VBScriptの暗号化 | VBScript さんま屋
・他言語熟知者にとってのVBAの学習コスト
→VBA異質だから、結構納得。
検索すると結構 "PythonでCATIAのマクロ" がHitするのですが、
動的型付け言語の方がC#より向いている気がします。
現状、DotNetで作る価値が見つかりませんね。
※追記です
GetCOGのパラメータです。
配列としか出ていませんでした。