C#ATIA

↑タイトル詐欺 主にFusion360API 偶にCATIA V5 VBA(絶賛ネタ切れ中)

ファイル間リンクの取得6

こちらの続きです。
ファイル間リンクの取得5 - C#ATIA

ようやく、妥協しまくりですが出来上がりました。

マクロでの利用が目的な為、本来DLLファイルとして提供すべきだとは
思うのですが、C#作成のDLLをVBAで利用する為にはレジストリに
DLLを登録する必要がある為、実行ファイル(EXE)としました。

実行ファイル、ソースコード(C#)、サンプルマクロ(VBA)等は、こちらの
サイトにUPしてます。
GrabCAD - CAD library
・exe_file : リンク情報を取得するプログラム(日本語・英語のみ)
・cs_Source : ソースコード(C#) GNU General Public License
vba_SupportClass : VBA用サポートクラスモジュール
vba_sample : VBA用サンプルマクロ
hoge.CATPart & piyo.CATDrawing : サンプルCATIAデータ(R2012)
実行ファイル名は「catv5_GetLinkReport.exe」です。
又、ソースコードについては、大本さんがGNUライセンスを表記している為、
同様にGNUライセンスとさせてください。


利用する際には、VBAから外部プログラムとして実行します。
処理終了後は、アクティブなファイルと同一フォルダ内に
「アクティブファイル名 + "_LinkReport.csv"」と言うCSVフォーマットのファイルが
作成される為、このファイルを読み込む事でリンク情報を取得できます。

作成されるCSVファイルは、このような状態です。
f:id:kandennti:20160128185341p:plain
"ドキュメントのリンク" の "リンク" タブ時の情報で、"元エレメント""宛先エレメント"・・・
の順番となっています。


実際にこのプログラムを利用したサンプルです。

'VBA リンク情報取得サポートクラス
'GetLinkReportSupport.cls
Option Explicit

'-----設定-----
'catv5_LinkReport.exeファイルのフルパス
Const GetLinkReportExePath = "C:\temp\library\catv5_GetLinkReport.exe"
'--------------

'こちらは変更しないで下さい
Const FileNameFooter = "_LinkReport.csv"
Dim FSO As Object

Private Sub Class_Initialize()
    Set FSO = CreateObject("Scripting.FileSystemObject")
End Sub

Private Sub Class_Terminate()
    Set FSO = Nothing
End Sub

'リンク情報取得
Public Function GetLinkReport() As Variant
    'GetLinkReportExePathパスチェック
    If Not FSO.FileExists(GetLinkReportExePath) Then
        MsgBox "GetLinkReportExePathの設定が間違っています"
        GetLinkReport = Array()
        Exit Function
    End If
    
    'GetLinkReportExe実行
    Dim WshShell As Object: Set WshShell = CreateObject("WScript.Shell")
    Call WshShell.Run(GetLinkReportExePath + " OFF", 0, True)
    Set WshShell = Nothing
    'Call Shell(GetLinkReportExePath + " OFF", vbNormalNoFocus) 'これは確実だが遅い
    
    
    'LinkReportファイル名取得
    Dim ReportFilePath As String
    ReportFilePath = GetReportFilePath(CATIA.ActiveDocument.FullName)
    
    'LinkReportファイル有無チェック
    If Not FSO.FileExists(ReportFilePath) Then
        GetLinkReport = Array()
        Exit Function
    End If
    
    'LinkReportファイル取得
    GetLinkReport = ReadFile(ReportFilePath)
End Function

'LinkReportファイル名取得
Private Function GetReportFilePath(ByVal Path) As String
    GetReportFilePath = FSO.GetParentFolderName(Path) + "\" + FSO.GetBaseName(Path) + FileNameFooter
End Function

'ファイルを読み込み return-ジャグ配列化
Private Function ReadFile(ByVal Path) As Variant
    If FSO.GetFile(Path).Size < 1 Then
        ReadFile = Array()
        Exit Function
    End If

    Dim TxtFile As Object: Set TxtFile = FSO.OpenTextFile(Path)
    Dim txt As String: txt = TxtFile.ReadAll
    Dim arytxt As Variant: arytxt = Split(txt, vbNewLine)
    
    Dim i As Integer
    Dim Jagary() As Variant: ReDim Jagary(UBound(arytxt))
    For i = 0 To UBound(arytxt)
        Jagary(i) = Split(arytxt(i), ",")
    Next
    
    ReadFile = Jagary
    Set TxtFile = Nothing
End Function

外部プログラムを実行し、作成されたCSVファイルを読み込む為のサポートクラスモジュールです。
GetLinkReportExePath定数には、実際に利用する際のフルパスに直してください。
必ずこのクラスを使用する必要は無いのですが、説明を簡略化したかったので・・・。

Call WshShell.Run(GetLinkReportExePath + " OFF", 0, True)

この部分で、設定されたパスを元に外部プログラムを実行させていますが、
実行する際のオプションとして " OFF" を付けています。
このオプションを付ける事で、VBAマクロからの実行時の面倒なメッセージの一部の
表示を止めています。
(オプション無しでは、CSVファイルの上書きの確認と処理の終了のメッセージが出ます)


続いて、このサポートクラスを利用したサンプルです。
PartファイルからリンクしているDrawファイルをアクティブにし、Viewをクリックする事で
リンク元の "宛先エレメント" をMsgBoxで表示します。

'VBA Draw-宛先エレメント取得サンプル
'GetLinkSample.bas
Option Explicit

Dim LinkReport As Variant '取得したリンク情報

Sub CatMain()
    'DrawDocチェック
    If Not TypeName(CATIA.ActiveDocument) = "DrawingDocument" Then
        MsgBox "CATDrawingファイルをアクティブにして下さい!"
        Exit Sub
    End If
    
    'リンク情報の取得
    LinkReport = GetLinkReport
    If UBound(LinkReport) < 0 Then
        MsgBox "リンク情報が取得できませんでした"
        Exit Sub
    End If
    
    'Viewの選択
    Dim ActSel As Variant: Set ActSel = CATIA.ActiveDocument.Selection
    Dim SelFilter As Variant: SelFilter = Array("DrawingView")
    Dim SelMsg As String: SelMsg = "リンク元を調べるビューを選択して下さい : [Esc]=キャンセル"
    Do
        ActSel.Clear
        Select Case ActSel.SelectElement2(SelFilter, SelMsg, False)
            Case "Cancel", "Undo", "Redo"
                Exit Do
        End Select
        Call ShowMsg(FindLinkData(ActSel.Item(1).value.name))
    Loop
    ActSel.Clear
End Sub

'リンク情報の取得
Private Function GetLinkReport() As Variant
    Dim GetLinkClass As GetLinkReportSupport: Set GetLinkClass = New GetLinkReportSupport
    GetLinkReport = GetLinkClass.GetLinkReport
    Set GetLinkClass = Nothing
End Function

'リンク情報から検索
Private Function FindLinkData(ByVal ViewName As String) As String
    Dim lr As Variant
    Dim Result() As String: ReDim Result(UBound(LinkReport))
    Dim HitCount As Integer: HitCount = -1
    For Each lr In LinkReport
        If InStr(lr(0), ViewName) Then
            HitCount = HitCount + 1
            Result(HitCount) = lr(1)
        End If
    Next
    If HitCount < 0 Then Exit Function
    ReDim Preserve Result(HitCount)
    FindLinkData = Join(Result, vbNewLine)
End Function

'リンクメッセージ表示
Private Sub ShowMsg(ByVal Msg As String)
    Msg = IIf(Len(Msg) < 1, _
                "リンクを持っていません!", _
                "リンク元は" + vbNewLine + Msg + vbNewLine + "です")
    MsgBox Msg
End Sub

GetLinkReport関数で先程のサポートクラスを経由して、リンク情報を取得しています。
戻り値はジャグ配列となっており、FindLinkData関数で選択したView名と
照らし合わせて、リンク元の "宛先エレメント" の情報を抜き出しています。

説明不足感たっぷりですが、このような感じです。
お気付きの方もいると思うのですが、実行ファイルのため
「マクロわかんない」
と言う方も、リンク情報を取得したいファイルをアクティブにし、マウスでダブルクリック
してもらうと、CSVファイル自体は作成されます。

テスト不十分な上、英語表記がかなり疑わしいので指摘していただけると
助かります。(コード的におかしい部分の指摘していただけるとありがたいです)


最後に参考させてもらったサイトです。
○Digital Photos
Catia V5 Get Links
このコードが無ければ、作成出来ませんでした。
色々と学ぶべき部分がありました。

○MT-Soft
リストビュー文字列取得−VBパーツ
VBでのリストビューの文字列取得のコードを、参考にさせてもらいました。
VBは型変換を自動で行ってしまう部分があり、そのままC#化できません
でしたが、かなり助かりました。

○DOBON.NET
C#のWindowsAPIでツリーのテキストが取得できません: DOBON.NETプログラミング掲示板過去ログ
C#でのツリービューの文字列取得のコードを、参考にさせてもらいました。
ツリービューなのでちょっと違うのですが、C#でのWinAPIの利用の仕方は
かなり参考になりました。

○ちょくとのページ
ウィンドウメッセージリスト
WinAPIの定数関連を参考にさせてもらいました。
何のサイトかと思ったら、HSP関連のサイトなんですね。
HSPすごいなぁ。