0

在最近的 Windows 更新后,以前运行的 Excel vba 脚本不再正常运行。

宏操作在工作时会打开一个 csv 文件,该文件在活动工作簿中定义为 String aString。csv 文件包含变量列表和这些变量的对应值。该宏返回原始活动工作簿并读取活动工作簿中定义的命名单元格,并使用 csv 文件中定义的值更新这些命名单元格。

问题似乎是,尽管返回到原始活动工作簿,生成 For 循环以循环遍历命名单元格的命令不再返回变量名称的值或变量所在的工作表。

命令是:

' Process to update name values
    Workbooks(strWorkBook).Activate
'    Windows(strWorkBook).Activate
'    Dim nm As Variant
         
      
'    For Each nm In ActiveWorkbook.Names
    For Each nm In Workbooks(strWorkBook).Names

        varname = nm.Name
        MsgBox "varname " & varname & " nm " & nm
        varsheet = Range(nm).Parent.Name
        MsgBox "varsheet " & varsheet

varname 的消息现在是: 在此处输入图像描述

该消息应为 varname aString nm $D$4

很确定它与更新版本相关,如在 Excel 构建版本 1902(构建 11328.20318)中它可以工作,但在版本 2002(构建 12527.21416)中不起作用

在此先感谢您的帮助。相关论坛指出了 Windows 的安全更新问题,但我还没有可以实施的解决方案。

==================================================== ====

进一步测试更新:

我创建了一个新工作簿并使用 Excel 版本 2002(内部版本 12527.21416)构建了在新工作簿中失败的宏。宏在新版本的 Excel 文件中完美运行,但在旧文件中继续产生上述错误消息。

我怀疑 2002 版构建中存在与安全更新相关的一些问题,这些问题与 1902 版构建不兼容,但无法确定问题所在。

在新版本中运行但不是原始文档的宏是:

Public Sub testName()

Dim filePath As String
Dim inFilePath As String
Dim inCase As String

'On Error GoTo ErrorHandler
Application.ScreenUpdating = False
Application.EnableEvents = False

'----------------------------------

' Find path for input file
    strWorkBook = ActiveWorkbook.Name
'        MsgBox strWorkBook
    
    filePath = Range("aString").Value
    tmpsep = InStrRev(filePath, "\")

    ' Input file workbook name
    inCase = Right(filePath, Len(filePath) - tmpsep)
    'Input file full path
    inFilePath = Left(filePath, Len(filePath) - Len(inCase))


' Open input data file
    Workbooks.Open Filename:=filePath
''       Find last row in file
'        Call FindLastRow.FindLastRow(lRow)
'        rngend = lRow + 2
''        MsgBox rngend

    Workbooks(strWorkBook).Activate

'
' VBA script to read external CSV file'    For Each nm In ActiveWorkbook.Names
    For Each nm In Workbooks(strWorkBook).Names

        varname = nm.Name
        MsgBox "varname " & varname & " nm " & nm
        varsheet = Range(nm).Parent.Name
        MsgBox "varsheet " & varsheet
        
        varcell = nm.RefersToRange.Address(False, False)
NextIteration:
Next nm

End Sub
4

2 回答 2

0

由于这个线程stackflow 线程和用户Jenn解决了问题。

似乎在 Excel V1902 和 V2002 之间,工作簿中存在一个隐藏变量 _xlfn.SINGLE。当宏循环通过时,它会看到命名范围,无法解析其地址或工作表位置并停止。直到运行 Jenn 的代码,我才能看到隐藏变量。

在此处输入图像描述

最简单的解决方案是包含一个 IF 循环以绕过此变量(如果已定义并正常继续)(如下所示)。这张纸现在可以工作了,但我不会让我生命中的那两天回来。

For Each Nm In Workbooks(strWorkBook).Names
   If Nm.Name Like "_xlfn*" Then
      GoTo NextIteration
   End If

   With Nm
        varName = .Name
        varSheet = .RefersToRange.Parent.Name
        varCell = .RefersToRange.Address(0, 0)
    End With
    MsgBox "Named range """ & varName & """ refers to range" & vbCr & _
           varCell & " on sheet """ & varSheet & """."

NextIteration:下一个 Nm

感谢那些对线程和Variatus发表评论的人,我将更新这些声明。

于 2021-02-01T00:30:45.427 回答
0

您的问题源于对变量的错误声明Nm。事实上,它没有被声明(并且你Option Explicit在模块的顶部缺少)这使它成为一个 Variant。在您创建的相当复杂的环境中,Excel 似乎无法将Name对象适合您想要的变体(更多关于此的内容)。此代码将起作用。

    Dim Nm          As Name
    Dim varName     As String
    Dim varSheet    As String
    Dim varCell     As String
    
'    For Each Nm In ActiveWorkbook.Names
    For Each Nm In Workbooks(strWorkBook).Names
        With Nm
            varName = .Name
            varSheet = .RefersToRange.Parent.Name
            varCell = .RefersToRange.Address(0, 0)
        End With
        MsgBox "Named range """ & varName & """ refers to range" & vbCr & _
               varCell & " on sheet """ & varSheet & """."
    Next Nm

我在 ActiveWorkbook 上测试了上述代码,但它也应该适用于任何其他代码。我在 Excel 365 中进行了测试,但这也不应该有所作为。

上面提到的复杂性源于您的这部分代码,Range(nm).Parent.Name. 在这种情况下nm是一个字符串。但是在您的循环上下文中nm是一个Name对象。因此,虽然在旧版本中 Name 对象的默认属性显然是引用的范围地址,但它现在似乎是别的东西。这并不重要,因为Name对象具有多个属性,可以从中提取引用的范围作为范围或其地址,并且一旦指定了要使用的属性,就无需要求 VBA 使用默认值。

顺便说一句,Range("anything")将始终在 ActiveSheet 上,并且Range("Sheet13!A2:A4").Parent会返回错误而不是 Sheet13。因此,如果您需要知道命名范围所在的范围的工作表,您应该寻找另一种方法来获取它。

于 2021-01-29T01:57:06.997 回答