vba 批量重新设置 word 中的异常图片(2)

Sub test1()
    Dim doc As Word.Document
    Set doc = ActiveDocument
    Dim ish As inlineShape
    Dim str As String
    ' Debug.Print "InlineShapes.Count = "; doc.InlineShapes.Count
    For i = doc.InlineShapes.Count To 1 Step -1
        Set ish = doc.InlineShapes.Item(i)
        If Not ish.LinkFormat Is Nothing Then
            str = doc.InlineShapes.Item(i).Range.WordOpenXML
            str = GetInlineShapeName(ish)
            Debug.Print "Name存在", i, ish.LinkFormat.SourceFullName, str
        Else
            Debug.Print "AlternativeText", i, ish.AlternativeText
        End If
    Next
    ' Update and embed the first inline image using a new file
    'Call ReplaceInlineShapeImageAt(doc, 1, "D:\OfficeSpace\ID_E37F9BFD10BF42BDBB2A4A02668F8750.png")
End Sub

Private Function ReplaceInlineShapeAtRange(iShape As InlineShape, imgPath As String, Optional keepSize As Boolean = True, Optional linkToFile As Boolean = True) As Boolean
    On Error Resume Next
    Dim rng As Range, w As Single, h As Single
    Set rng = iShape.Range
    If keepSize Then
        w = iShape.Width
        h = iShape.Height
    End If
    
    ' 删除旧对象
    iShape.Delete
    
    ' 在同一范围插入新图片(链接或嵌入)
    Dim newIsh As InlineShape
    Set newIsh = rng.InlineShapes.AddPicture(FileName:=imgPath, LinkToFile:=linkToFile, SaveWithDocument:=Not linkToFile)
    If Not newIsh Is Nothing Then
        If keepSize Then
            newIsh.LockAspectRatio = msoTrue
            newIsh.Width = w
            ' 高度按比例由 Word 调整,或者也可强制:newIsh.Height = h
        End If
        ReplaceInlineShapeAtRange = True
    Else
        ReplaceInlineShapeAtRange = False
    End If
End Function

Function ExtractNameFromXML(inlineShape As inlineShape) As String
    '从XML中提取ID(高级方法)
    Dim xmlName As String
    Dim xmlDoc As Object
    Dim xmlnode As Object
    On Error Resume Next
    '尝试访问XML属性
    '这需要根据具体的XML结构来调整
    xmlName = ""
    '创建DOMDocument对象
    Set xmlDoc = CreateObject("MSXML2.DOMDocument.6.0")
    '加载XML内容
    xmlDoc.LoadXML inlineShape.Range.WordOpenXML
    '检查是否成功加载XML
    If Not xmlDoc Is Nothing And xmlDoc.parseError.ErrorCode = 0 Then
        'retrieve Name from wp:docPr or pic:Cnvpr
        Set xmlnode = xmlDoc.SelectSingleNode("//wp:docPr")
        Set xmlnode = xmlDoc.SelectSingleNode("//*[local-name()='docPr' or local-name()='cNvPr']/@name")
        '如果找到节点,则提取其文本内容
        If Not xmlnode Is Nothing Then
            'xmlName = xmlnode.getAttribute("name")
            xmlName = xmlnode.Text
        End If
    End If
    On Error GoTo 0
    ExtractNameFromXML = xmlName
End Function

Private Function GetInlineShapeName(iShape As inlineShape) As String
    On Error Resume Next
    Dim xml As String, nameVal As String
    xml = iShape.Range.WordOpenXML
    nameVal = GetNameFromXmlMSXML(xml)
    If nameVal <> "" Then
        GetInlineShapeName = nameVal
        Exit Function
    End If
 
    ' 如果直接片段中没有,尝试扩大范围(前后各+1个字符)
    Dim doc As Document, s As Long, e As Long
    Set doc = iShape.Parent
    s = IIf(iShape.Range.Start - 1 < doc.Content.Start, doc.Content.Start, iShape.Range.Start - 1)
    e = IIf(iShape.Range.End + 1 > doc.Content.End, doc.Content.End, iShape.Range.End + 1)
    xml = doc.Range(s, e).WordOpenXML
    nameVal = GetNameFromXmlMSXML(xml)
    If nameVal <> "" Then
        GetInlineShapeName = nameVal
        Exit Function
    End If
 
    ' 继续扩大范围到所在段落
    xml = iShape.Range.Paragraphs(1).Range.WordOpenXML
    nameVal = GetNameFromXmlMSXML(xml)
    If nameVal <> "" Then
        GetInlineShapeName = nameVal
        Exit Function
    End If
    GetInlineShapeName = ""
End Function

Private Function GetNameFromXmlMSXML(xml As String) As String
    On Error Resume Next
    Dim s As String: s = xml
    Dim dom As Object: Set dom = CreateObject("MSXML2.DOMDocument.6.0")
    dom.async = False: dom.validateOnParse = False
    If dom.LoadXML(s) Then
        Dim node As Object
        Set node = dom.SelectSingleNode("//*[local-name()='docPr' or local-name()='cNvPr']/@name")
        If Not node Is Nothing Then GetNameFromXmlMSXML = node.Text
    End If
End Function

Private Function CsvEscape(ByVal v As Variant) As String
    Dim s As String: s = CStr(v)
    If InStr(s, """") Or InStr(s, ",") Or InStr(s, vbCr) Or InStr(s, vbLf) Then
        s = Replace(s, """", """""")
        CsvEscape = """" & s & """"
    Else: CsvEscape = s
    End If
End Function
 
' 组装一行 CSV(可变参数)
Private Function CsvJoin(ParamArray arr()) As String
    Dim i As Long, parts() As String
    ReDim parts(LBound(arr) To UBound(arr))
    For i = LBound(arr) To UBound(arr)
        parts(i) = CsvEscape(arr(i))
    Next
    CsvJoin = Join(parts, ",")
End Function
 
' 写入头部(仅首次创建文件时)
Private Sub CsvMaybeWriteHeader(ByVal fnum As Integer, ByVal filePath As String)
    If LOF(fnum) = 0 Then  
        Print #fnum, CsvJoin("Status", "Index", "SourceFullName", "Name")
    End If
End Sub
 
'  
Sub ExportToCsv()
    Dim doc As Document: Set doc = ActiveDocument
    Dim csvPath As String: csvPath = "c:\officespace\images_report.csv"
    Dim f As Integer: f = FreeFile
    Open csvPath For Append As #f
 
    CsvMaybeWriteHeader f, csvPath

    Dim i As Long
    Dim ish As inlineShape
    Dim linkPath As String
    Dim nameStr As String ' 你的 str 变量(名称)
    For i = 1 To doc.InlineShapes.Count
        Set ish = doc.InlineShapes(i)
        ' 安全取 LinkFormat.SourceFullName(可能不是链接图)
        linkPath = ""
        On Error Resume Next
        If Not ish.LinkFormat Is Nothing Then
            linkPath = ish.LinkFormat.SourceFullName
            On Error GoTo 0
            ' nameStr = ... 这里生成你的名称(你之前的 str)
            ' 示例:nameStr = GetInlineShapeName(ish)
            ' 写入一行
            nameStr = GetInlineShapeName(ish)
            Print #f, CsvJoin("Name存在", i, linkPath, nameStr)
        Else
            Print #f, CsvJoin("alt", i, ish.AlternativeText)
        End If
    Next
    Close #f
    MsgBox "已写入: " & csvPath
End Sub
 
'UTF-8 版(若你需要 UTF-8 编码)
' Excel 新版对 UTF-8 支持更好,但用 Open 方式不能写 UTF-8。可用 ADODB.Stream。
' 下面示例会读入已有文件内容,追加一行,再以 UTF-8 保存。
Sub AppendCsvUtf8(filePath As String, lineToAppend As String, Optional writeHeader As Boolean = False, Optional headerLine As String = "")
    Dim stm As Object, existing As Object, textAll As String
    Set stm = CreateObject("ADODB.Stream")
    stm.Type = 2
    stm.Charset = "utf-8"
    stm.Open
    If Dir$(filePath) <> "" Then
        Set existing = CreateObject("ADODB.Stream")
        existing.Type = 2
        existing.Charset = "utf-8"
        existing.Open
        existing.LoadFromFile filePath
        textAll = existing.ReadText(-1)
        existing.Close
        If Len(textAll) > 0 And Right$(textAll, 2) <> vbCrLf Then textAll = textAll & vbCrLf
        stm.WriteText textAll, 0
    ElseIf writeHeader And Len(headerLine) > 0 Then
        stm.WriteText headerLine & vbCrLf, 0
    End If
    stm.WriteText lineToAppend & vbCrLf, 0
    stm.SaveToFile filePath, 2 'adSaveCreateOverWrite
    stm.Close
End Sub

Private Function PickListFile(Optional ByVal title As String = "请选择包含图片路径的 TXT/CSV 文件") As String
    On Error Resume Next
    Dim fd As FileDialog
    Set fd = Application.FileDialog(msoFileDialogFilePicker)
    With fd
        .title = title
        .Filters.Clear
        .Filters.Add "Text/CSV", "*.txt;*.csv", 1
        .AllowMultiSelect = False
        If .Show = -1 Then
            PickListFile = .SelectedItems(1)
        Else
            PickListFile = ""
        End If
    End With
End Function
 
' 从一行中解析出路径(最简逻辑:支持逗号分隔和双引号包裹)
Private Function ParsePathFromLine(ByVal line As String) As String
    Dim s As String: s = Trim$(line)
    If s = "" Then Exit Function
    If Left$(s, 1) = "'" Or Left$(s, 1) = "#" Then Exit Function ' 注释行
    ' 若以双引号开头,取下一对双引号之间的内容
    If Left$(s, 1) = """" Then
        Dim p As Long
        p = InStr(2, s, """")
        If p > 0 Then
            ParsePathFromLine = Mid$(s, 2, p - 2)
            Exit Function
        End If
    End If
 
    ' 否则,若含逗号,取首列(CSV 简单场景)
    Dim c As Long: c = InStr(1, s, ",")
    If c > 0 Then
        ParsePathFromLine = Trim$(Left$(s, c - 1))
    Else
        ParsePathFromLine = s
    End If
End Function
 
' 顺序映射:第1行->第1个 InlineShape, 第2行->第2个...
Public Sub UpdateInlineShapesFromListSequential()
    Dim listPath As String: listPath = PickListFile()
    If listPath = "" Then Exit Sub
    Dim doc As Document: Set doc = ActiveDocument
    Dim f As Integer: f = FreeFile
    On Error GoTo ErrOpen
    Open listPath For Input As #f
    Dim i As Long: i = 1
    Dim replaced As Long, skipped As Long
    Dim raw As String, pathText As String
    Do While Not EOF(f) And i <= doc.InlineShapes.Count
        Line Input #f, raw
        pathText = ParsePathFromLine(raw)
        If pathText <> "" And Dir$(pathText) <> "" Then
            On Error Resume Next
            ReplaceInlineShapeImageAt doc, i, pathText
            If Err.Number = 0 Then
                replaced = replaced + 1
            Else
                skipped = skipped + 1
                Err.Clear
            End If
            On Error GoTo 0
        Else
            skipped = skipped + 1
        End If
        i = i + 1
    Loop
    Close #f
    MsgBox "顺序更新完成:替换=" & replaced & ", 跳过=" & skipped, vbInformation
    Exit Sub
ErrOpen:
    MsgBox "无法打开列表文件:" & listPath, vbExclamation
    On Error Resume Next
    Close #f
End Sub
 
'按索引更新并嵌入图片
Public Sub ReplaceInlineShapeImageAt(doc As Document, ByVal index As Long, ByVal newPath As String)
    Debug.Print "start " & index & vbTab & newPath
    Dim ils As inlineShape
    If doc Is Nothing Then Exit Sub
    If index < 1 Or index > doc.InlineShapes.Count Then Exit Sub
    If Dir$(newPath) = "" Then Exit Sub
    Set ils = doc.InlineShapes(index)
    On Error GoTo Fallback
    ' 若当前是链接图片,优先走 LinkFormat 流程:更新 -> 嵌入 -> 断开链接
    If Not ils.LinkFormat Is Nothing Then
        With ils.LinkFormat
            .SourceFullName = newPath
            .SavePictureWithDocument = True
            .Update
            .BreakLink
        End With
        Exit Sub
    End If
Fallback:
    On Error Resume Next
    ' 否则直接在原位替换并嵌入(保持尺寸,linkToFile:=False 表示嵌入)
    Debug.Print "something is  wrong" & vbTab & index & vbTab & newPath
    'Call ReplaceInlineShapeAtRange(ils, newPath, True, False)
End Sub
 
 ' =============== 高效按基名匹配更新(建立索引,近似 O(N)) ===============
Private Sub DictAddIndex(ByVal dict As Object, ByVal key As String, ByVal idx As Long)
    If Len(key) = 0 Then Exit Sub
    If Not dict.Exists(key) Then
        Dim c As Object: Set c = CreateObject("System.Collections.ArrayList")
        dict.Add key, c
    End If
    dict(key).Add idx
End Sub

Private Function ListPopFirstAvailable(ByVal lst As Object, ByVal used As Object) As Long
    Dim i As Long
    For i = 0 To lst.Count - 1
        If Not used.Exists(CStr(lst(i))) Then
            ListPopFirstAvailable = CLng(lst(i))
            Exit Function
        End If
    Next
    ListPopFirstAvailable = 0
End Function

Private Sub BuildInlineShapeIndices(ByVal doc As Document, ByRef altIndex As Object, ByRef linkIndex As Object, ByRef xmlNameIndex As Object)
    Dim fso As Object: Set fso = CreateObject("Scripting.FileSystemObject")
    Set altIndex = CreateObject("Scripting.Dictionary")
    Set linkIndex = CreateObject("Scripting.Dictionary")
    Set xmlNameIndex = CreateObject("Scripting.Dictionary")
    
    Dim i As Long, ish As inlineShape
    Dim alt As String, linkPath As String, baseName As String, xmlName As String
    
    For i = 1 To doc.InlineShapes.Count
        Set ish = doc.InlineShapes(i)
        
        On Error Resume Next
        alt = ish.AlternativeText
        On Error GoTo 0
        If Len(alt) > 0 Then DictAddIndex altIndex, alt, i
        
        linkPath = ""
        On Error Resume Next
        If Not ish.LinkFormat Is Nothing Then linkPath = ish.LinkFormat.SourceFullName
        On Error GoTo 0
        If Len(linkPath) > 0 Then
            baseName = fso.GetBaseName(linkPath)
            DictAddIndex linkIndex, baseName, i
        End If
        
        xmlName = GetInlineShapeName(ish)
        If Len(xmlName) > 0 Then DictAddIndex xmlNameIndex, xmlName, i
    Next i
End Sub

Private Sub BuildNameIndexInRange(ByVal doc As Document, ByVal startIdx As Long, ByVal endIdx As Long, ByVal reverse As Boolean, ByRef nameIndex As Object, Optional ByVal preferLink As Boolean = True)
    Dim i As Long, idx As Long
    Dim nm As String
    Set nameIndex = CreateObject("Scripting.Dictionary")
    On Error Resume Next
    nameIndex.CompareMode = vbTextCompare ' 基于名称的键,忽略大小写
    On Error GoTo 0
    
    If reverse Then
        For i = endIdx To startIdx Step -1
            idx = i
            nm = ""
            ' 预先缓存 LinkFormat 与相关属性
            Dim lf As Object
            Dim sourceName As String, sourceFull As String
            On Error Resume Next
            Set lf = doc.InlineShapes(idx).LinkFormat
            If Not lf Is Nothing Then
                sourceName = lf.sourceName
                sourceFull = lf.SourceFullName
            End If
            On Error GoTo 0
            
            ' 仅当需要修复时才建立索引:
            ' 1) LinkFormat 存在且 SourceName 为空
            ' 2) 或者 SourceFullName 指向的文件不存在
            If Not lf Is Nothing Then
                If Len(Trim$(sourceName)) = 0 _
                   Or (Len(sourceFull) > 0 And Dir$(sourceFull) = "") Then
                    If preferLink And Len(sourceFull) > 0 Then
                        Dim fsoR As Object: Set fsoR = CreateObject("Scripting.FileSystemObject")
                        nm = Trim$(fsoR.GetBaseName(sourceFull))
                    Else
                        nm = Trim$(GetInlineShapeName(doc.InlineShapes(idx)))
                    End If
                End If
            End If
            If Len(nm) > 0 Then
                If Not nameIndex.Exists(nm) Then
                    Dim lst As Object: Set lst = CreateObject("System.Collections.ArrayList")
                    nameIndex.Add nm, lst
                End If
                nameIndex(nm).Add idx
            End If
        Next i
    Else
        For i = startIdx To endIdx
            idx = i
            nm = ""
            ' 预先缓存 LinkFormat 与相关属性
            Dim lf2 As Object
            Dim sourceName2 As String, sourceFull2 As String
            On Error Resume Next
            Set lf2 = doc.InlineShapes(idx).LinkFormat
            If Not lf2 Is Nothing Then
                sourceName2 = lf2.sourceName
                sourceFull2 = lf2.SourceFullName
            End If
            On Error GoTo 0
            
            ' 仅当需要修复时才建立索引
            If Not lf2 Is Nothing Then
                If Len(Trim$(sourceName2)) = 0 _
                   Or (Len(sourceFull2) > 0 And Dir$(sourceFull2) = "") Then
                    If preferLink And Len(sourceFull2) > 0 Then
                        Dim fsoR2 As Object: Set fsoR2 = CreateObject("Scripting.FileSystemObject")
                        nm = Trim$(fsoR2.GetBaseName(sourceFull2))
                    Else
                        nm = Trim$(GetInlineShapeName(doc.InlineShapes(idx)))
                    End If
                End If
            End If
            If Len(nm) > 0 Then
                If Not nameIndex.Exists(nm) Then
                    Dim lst2 As Object: Set lst2 = CreateObject("System.Collections.ArrayList")
                    nameIndex.Add nm, lst2
                End If
                nameIndex(nm).Add idx
            End If
        Next i
    End If
End Sub

Private Function PopFirstUnusedAndRemove(ByVal lst As Object, ByVal used As Object) As Long
    Dim k As Long, idx As Long
    For k = 0 To lst.Count - 1
        idx = CLng(lst(k))
        If Not used.Exists(CStr(idx)) Then
            PopFirstUnusedAndRemove = idx
            lst.RemoveAt k
            Exit Function
        End If
    Next k
    PopFirstUnusedAndRemove = 0
End Function

Public Sub UpdateInlineShapesFromListByName_RangeIndex()
    Dim doc As Document: Set doc = ActiveDocument
    Dim startIdx As Long, endIdx As Long, reverse As Boolean
    ' 固定范围:1..inlineshapes.count 倒序
    startIdx = 1: endIdx = doc.InlineShapes.Count: reverse = True
    
    Dim listPath As String: listPath = PickListFile("请选择包含图片路径的 TXT/CSV(范围小索引:按 OpenXML 名称)")
    If listPath = "" Then Exit Sub
    
    ' 1) 在范围内建立 name -> [indices] 小索引(调用 GetInlineShapeName,一次性各算一遍)
    Dim nameIndex As Object
    BuildNameIndexInRange doc, startIdx, endIdx, reverse, nameIndex
    
    ' 2) 顺序读取列表,按基名查索引并弹出一个可用下标
    Dim fso As Object: Set fso = CreateObject("Scripting.FileSystemObject")
    Dim used As Object: Set used = CreateObject("Scripting.Dictionary")
    
    Dim f As Integer: f = FreeFile
    On Error GoTo ErrOpen
    Open listPath For Input As #f
    
    Dim raw As String, pathText As String, baseName As String
    Dim idx As Long
    Dim replaced As Long, skipped As Long
    
    Do While Not EOF(f)
        Line Input #f, raw
        pathText = ParsePathFromLine(raw)
        If pathText = "" Or Dir$(pathText) = "" Then
            skipped = skipped + 1
        Else
            baseName = fso.GetBaseName(pathText)
            If nameIndex.Exists(baseName) Then
                Do
                    idx = PopFirstUnusedAndRemove(nameIndex(baseName), used)
                    If idx <= 0 Then Exit Do
                    ReplaceInlineShapeImageAt doc, idx, pathText
                    used.Add CStr(idx), True
                    replaced = replaced + 1
                Loop
            Else
                skipped = skipped + 1
            End If
        End If
    Loop
    
    Close #f
    MsgBox "按 OpenXML 名称(范围索引)更新完成:替换=" & replaced & ", 跳过=" & skipped, vbInformation
    Exit Sub

ErrOpen:
    MsgBox "无法打开列表文件:" & listPath, vbExclamation
    On Error Resume Next
    Close #f
End Sub

对存在链接,但链接丢失,且图片异常的图片按照文本中的地址进行替换。

Public Sub UpdateInlineShapesFromListByName_Fast()
    Dim listPath As String: listPath = PickListFile("请选择包含图片路径的 TXT/CSV(按基名匹配-快速)")
    If listPath = "" Then Exit Sub
    Dim doc As Document: Set doc = ActiveDocument
    
    Dim altIndex As Object, linkIndex As Object, xmlNameIndex As Object
    BuildInlineShapeIndices doc, altIndex, linkIndex, xmlNameIndex
    
    Dim used As Object: Set used = CreateObject("Scripting.Dictionary")
    Dim fso As Object: Set fso = CreateObject("Scripting.FileSystemObject")
    
    Dim f As Integer: f = FreeFile
    On Error GoTo ErrOpen
    Open listPath For Input As #f
    
    Dim raw As String, pathText As String, baseName As String
    Dim idx As Long
    Dim replaced As Long, skipped As Long
    
    Do While Not EOF(f)
        Line Input #f, raw
        pathText = ParsePathFromLine(raw)
        If pathText = "" Or Dir$(pathText) = "" Then
            skipped = skipped + 1
        Else
            baseName = fso.GetBaseName(pathText)
            idx = 0
            
            If altIndex.Exists(baseName) Then idx = ListPopFirstAvailable(altIndex(baseName), used)
            If idx = 0 And linkIndex.Exists(baseName) Then idx = ListPopFirstAvailable(linkIndex(baseName), used)
            If idx = 0 And xmlNameIndex.Exists(baseName) Then idx = ListPopFirstAvailable(xmlNameIndex(baseName), used)
            
            If idx > 0 Then
                ReplaceInlineShapeImageAt doc, idx, pathText
                used.Add CStr(idx), True
                replaced = replaced + 1
            Else
                skipped = skipped + 1
            End If
        End If
    Loop
    
    Close #f
    MsgBox "按基名匹配更新完成(快速):替换=" & replaced & ", 跳过=" & skipped, vbInformation
    Exit Sub

ErrOpen:
    MsgBox "无法打开列表文件:" & listPath, vbExclamation
    On Error Resume Next
    Close #f
End Sub
 
 
 
' 按基名匹配:行路径的文件基名与图片的 AlternativeText 或选择窗格name相同则更新
Public Sub UpdateInlineShapesFromListByName()
    Dim listPath As String: listPath = PickListFile("请选择包含图片路径的 TXT/CSV(按基名匹配)")
    If listPath = "" Then Exit Sub
    Dim doc As Document: Set doc = ActiveDocument
    Dim fso As Object: Set fso = CreateObject("Scripting.FileSystemObject")
    Dim used As Object: Set used = CreateObject("Scripting.Dictionary") ' 记录已更新的下标
    Dim f As Integer: f = FreeFile
    On Error GoTo ErrOpen
    Open listPath For Input As #f
    Dim raw As String, pathText As String, baseName As String
    Dim i As Long, found As Boolean, linkPath As String, alt As String
    Dim replaced As Long, skipped As Long
    Do While Not EOF(f)
        Line Input #f, raw
        pathText = ParsePathFromLine(raw)
        If pathText = "" Or Dir$(pathText) = "" Then
            skipped = skipped + 1
        Else
            baseName = fso.GetBaseName(pathText)
            found = False
            'For i = 1 To doc.InlineShapes.Count
            For i = 5 To 4 Step -1
                If Not used.Exists(CStr(i)) Then
                    ' 先比对 AlternativeText
                    alt = ""
                    On Error Resume Next
                    alt = doc.InlineShapes(i).AlternativeText
                    On Error GoTo 0
                    If StrComp(alt, baseName, vbTextCompare) = 0 Then
                        ReplaceInlineShapeImageAt doc, i, pathText
                        used.Add CStr(i), True
                        replaced = replaced + 1
                        found = True
                        Exit For
                    End If
 
                    '对比 inlineShape 的 name
                    On Error Resume Next
                    If Not doc.InlineShapes(i).LinkFormat Is Nothing Then
                        picname = GetInlineShapeName(doc.InlineShapes(i))
                        If StrComp(baseName, picname, vbTextCompare) = 0 Then
                            ReplaceInlineShapeImageAt doc, i, pathText
                            Debug.Print i, picname
                            used.Add CStr(i), True
                            replaced = replaced + 1
                            found = True
                            Exit For
                        End If
                    End If
                End If
            Next i
            If Not found Then skipped = skipped + 1
        End If
    Loop
    Close #f
    MsgBox "按基名匹配更新完成:替换=" & replaced & ", 跳过=" & skipped, vbInformation
    Exit Sub
ErrOpen:
    MsgBox "无法打开列表文件:" & listPath, vbExclamation
    On Error Resume Next
    Close #f
End Sub
posted @ 2025-08-22 21:58  geyee  阅读(10)  评论(0)    收藏  举报