こちらの続きです。
同一UUIDのDraw参照元ファイルを差し替える1 - C#ATIA
前回の最後に「指定したPartファイルから、どのDrawファイルを利用するか?」が
難しくと書きました。 難しいです。
一発で差し替えは個人的にほぼムリと考えています。
・組み合わせる為の暫定的なリストを、CSVファイルで作成(マクロ)
↓
・Excelでチョロチョロ調整(人力)
↓
・差し替えDrawの作成(マクロ)
の2本立てを考えてます。
どうやって、暫定的な組合せを作ろうか? と思い真っ先に思いついたのが
こちらです。
レーベンシュタイン距離に触れてみる - Infomentのブログ
Infomentさん感謝してます。正直、レーベンシュタイン距離なんて知りませんでした。
リンク先のリンク先のコードを元に、テストの為のコードを作ったのですが、
文字数の制約やExcel限定っぽさがあったので少し変更しました。
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
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採用してます」って嘘ついても大丈夫そうなぐらいな結果が
得られている気がします。