こちらの続きです。
ファイル間リンクの取得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ファイルは、このような状態です。
"ドキュメントのリンク" の "リンク" タブ時の情報で、"元エレメント""宛先エレメント"・・・
の順番となっています。
実際にこのプログラムを利用したサンプルです。
'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すごいなぁ。