C#ATIA

↑タイトル詐欺 主にCATIA V5 の VBA(最近はPMillマクロとFusion360APIが多い)

CATIAのマクロをDotNetで作る事をオススメしない理由

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"を選択した状態です。
f:id:kandennti:20171103175501p:plain
スケッチやジオメトリ(点・線・面)等も確認可能ですし、Parentをさかのぼって
行けばPartやPartDocumentも取得可能です。
(Documentが取得できれば、大半 事が足ります)

一方、C#の場合はこちら。
f:id:kandennti:20171103175513p:plain
"形状セット1"の名前すら確認出来ない状態です。 種類の部分は
”MECMOD.HybridBod{System.__ComObject}”と表示されていますが
これは形状セットとわかっている為、キャストした状態だからです。
キャストしないとこんな感じです。
f:id:kandennti:20171103175523p:plain
"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のパラメータです。
f:id:kandennti:20171106092508p:plain
配列としか出ていませんでした。