C#ATIA

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

同一UUIDのDraw参照元ファイルを差し替える2

こちらの続きです。
同一UUIDのDraw参照元ファイルを差し替える1 - C#ATIA

前回の最後に「指定したPartファイルから、どのDrawファイルを利用するか?」が
難しくと書きました。 難しいです。
一発で差し替えは個人的にほぼムリと考えています。

・組み合わせる為の暫定的なリストを、CSVファイルで作成(マクロ)
 ↓
Excelでチョロチョロ調整(人力)
 ↓
・差し替えDrawの作成(マクロ)

の2本立てを考えてます。

どうやって、暫定的な組合せを作ろうか? と思い真っ先に思いついたのが
こちらです。

レーベンシュタイン距離に触れてみる - Infomentのブログ

Infomentさん感謝してます。正直、レーベンシュタイン距離なんて知りませんでした。
リンク先のリンク先のコードを元に、テストの為のコードを作ったのですが、
文字数の制約やExcel限定っぽさがあったので少し変更しました。

'vba using-'KCL0.0.12'  by Kantoku
Sub Test_LevenshteinDistance()
    Dim path1 As String
    path1 = "C:\Program Files\Dassault Systemes\B22\win_b64\code\bin32"
    
    Dim fs1 As Object
    Set fs1 = GetFiles(path1)
    
    Dim path2 As String
    path2 = "C:\Program Files\Dassault Systemes\B27\win_b64\code\bin32"
    
    Dim fs2 As Object
    Set fs2 = GetFiles(path2)
    
    Dim dic As Object
    Set dic = KCL.InitDic()
    
    Dim v1, v2, ratio, max_ra, stack
    For Each v1 In fs1
        max_ra = 0
        stack = ""
        For Each v2 In fs2
            ratio = Levenshtein(v1, v2)
            If max_ra < ratio Then
                max_ra = ratio
                stack = v2
            End If
        Next
        Debug.Print max_ra & "% : " & v1 & " <-> " & stack
    Next
End Sub

Private Function GetFiles(ByVal path As String)
    Dim fso As Object
    Set fso = KCL.GetFSO
    
    Dim lst As Object
    Set lst = KCL.InitLst()
    
    Dim f As Object
    For Each f In fso.GetFolder(path).files
        lst.Add f.Name
    Next
    Set GetFiles = lst
End Function

'https://infoment.hatenablog.com/entry/2018/11/17/183339
'https://code.i-harness.com/ja/q/40be5c
Private Function Levenshtein( _
    ByVal str1 As String, _
    ByVal str2 As String) As Long
    
    Dim str1_len As Long
    str1_len = Len(str1)
    
    Dim str2_len As Long
    str2_len = Len(str2)
    
    Dim dist() As Long
    ReDim dist(str1_len, str2_len)
    dist(0, 0) = 0
    
    Dim smStr1() As Long
    ReDim smStr1(str1_len) As Long
    Dim i As Long
    For i = 1 To str1_len
        dist(i, 0) = i
        smStr1(i) = Asc(LCase(Mid$(str1, i, 1)))
    Next
    
    Dim smStr2() As Long
    ReDim smStr2(str2_len) As Long
    For i = 1 To str2_len
        dist(0, i) = i
        smStr2(i) = Asc(LCase(Mid$(str2, i, 1)))
    Next
    
    Dim min1 As Long, min2 As Long, min3 As Long, minmin As Long, MaxL As Long
    Dim j As Long
    For i = 1 To str1_len
        For j = 1 To str2_len
            If smStr1(i) = smStr2(j) Then
                dist(i, j) = dist(i - 1, j - 1)
            Else
                min1 = dist(i - 1, j) + 1
                min2 = dist(i, j - 1) + 1
                min3 = dist(i - 1, j - 1) + 1
                If min2 < min1 Then
                    If min2 < min3 Then minmin = min2 Else minmin = min3
                Else
                    If min1 < min3 Then minmin = min1 Else minmin = min3
                End If
                dist(i, j) = minmin
            End If
        Next
    Next
    
    MaxL = str1_len
    If str2_len > MaxL Then MaxL = str2_len
    
    Levenshtein = 100 - CLng((dist(str1_len, str2_len) * 100) / MaxL)
End Function

あまり業務っぽいファイル名だとまずいので、同一のCATIAのインストールフォルダの
一部をR22とR27で比較しています。結果はこちら

100% : CATAutoItf.dll <-> CATAutoItf.dll
100% : CATJNIBridge.dll <-> CATJNIBridge.dll
100% : CATRTCChildProcess.exe <-> CATRTCChildProcess.exe
100% : CATRTCDlg.dll <-> CATRTCDlg.dll
100% : CATRTCItf.dll <-> CATRTCItf.dll
100% : CATRTCMsgLayer.dll <-> CATRTCMsgLayer.dll
100% : CATRTCMSLiveImpl.dll <-> CATRTCMSLiveImpl.dll
100% : CATRTCSametimeImpl.dll <-> CATRTCSametimeImpl.dll
100% : CATSysAllocator.dll <-> CATSysAllocator.dll
66% : CATSysAllocator.dll.beforeSPK <-> CATSysAllocator.dll
100% : CATSysMainThreadMQ.dll <-> CATSysMainThreadMQ.dll
69% : CATSysMainThreadMQ.dll.beforeSPK <-> CATSysMainThreadMQ.dll
100% : CATSysMultiThreading.dll <-> CATSysMultiThreading.dll
71% : CATSysMultiThreading.dll.beforeSPK <-> CATSysMultiThreading.dll
100% : CATSysPreview.dll <-> CATSysPreview.dll
100% : CATSysTS.dll <-> CATSysTS.dll
55% : CATSysTS.dll.beforeSPK <-> CATSysTS.dll
100% : CATSysTSObjectModeler.dll <-> CATSysTSObjectModeler.dll
71% : CATSysTSObjectModeler.dll.beforeSPK <-> CATSysTSObjectModeler.dll
100% : CATVBAHostingApplication.exe <-> CATVBAHostingApplication.exe
100% : CATVBAInfra.dll <-> CATVBAInfra.dll
100% : JS0FM.dll <-> JS0FM.dll
47% : JS0FM.dll.beforeSPK <-> JS0FM.dll
100% : JS0GROUP.dll <-> JS0GROUP.dll
55% : JS0GROUP.dll.beforeSPK <-> JS0GROUP.dll
100% : JS0SPEXT.dll <-> JS0SPEXT.dll
55% : JS0SPEXT.dll.beforeSPK <-> JS0SPEXT.dll
100% : mfc70u.dll <-> mfc70u.dll
100% : msvci70.dll <-> msvci70.dll
100% : msvcr70.dll <-> msvcr70.dll

「~win_b64\code\bin」の様に、ファイル数が多いフォルダで試すと
処理が返って来ませんでした・・・。
恐らく毎回動的配列を確保しているからじゃないかな?

「AI採用してます」って嘘ついても大丈夫そうなぐらいな結果が
得られている気がします。