【问题标题】:Excel macro not working after Windows update - Office 365Windows 更新后 Excel 宏不起作用 - Office 365
【发布时间】:2021-01-29 00:43:29
【问题描述】:

在最近的 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

【问题讨论】:

  • 从您的帖子中很难看出您在新/工作代码中的更改与在旧/非工作版本中的更改情况
  • @Tim Williams,新旧代码之间没有任何变化。它们是相同的。问题是代码不再适用于在早期版本中创建的原始 Excel 工作簿。如果我在 2002 版(构建...)版本中生成相同的模块,它可以完美运行。没有证据表明 2002 版之前的 Excel 工作簿构建...等已损坏,并且此工作簿中的其他宏功能没有问题。

标签: excel vba updates named-ranges


【解决方案1】:

您的问题源于变量Nm 的错误声明。事实上,它没有被声明(并且你在模块顶部缺少Option Explicit),这使它成为一个变体。在您创建的相当复杂的环境中,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。因此,如果您需要知道命名范围所在的范围表,您应该寻找另一种获取方法。

【讨论】:

  • 感谢 Variatus 的意见。我接受您关于声明的观点,并且提供的代码在 2002 版(Build ..)中创建的新 Excel 工作簿中有效。但是,将相同的模块复制到版本 2002 之前创建的工作簿会产生相同的错误消息,其中 Excel 无法在工作簿中找到已定义的名称,因此在任何工作表中都找不到已定义名称的相应单元格位置。顺便说一句,在版本 2002 (Build..) 中使用新的空白工作簿时,没有声明的代码的原始形式在使用 Excel 版本 1902 (Build...) 时有效
  • 所以你现在有一个版本在一个构建上运行,另一个版本在另一个构建上运行,你想要一个在两者上运行的版本。我认为您需要更新变量声明的原始代码(以避免再次得到相同的答案),然后提出一个新问题,删除代码中所有不相关的部分并说明新目标。我不认为构建很重要,但 Excel 版本可能很重要。基本上,一个或另一个版本可能需要更精确的语法,但相同的语法应该在两个版本上运行,这增加了应用软件损坏的可能性。
  • 您好 Variatus,问题现已解决。从编程的角度来看,声明是正确的,但是当删除下面定义的隐藏变量问题时,没有定义声明的代码版本相同。再次感谢您花时间查看帖子。
【解决方案2】:

感谢这个帖子stackflow thread和用户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 & """."

下一次迭代: 下一牛米

感谢那些对帖子发表评论的人和Variatus 我会更新这些声明。

【讨论】: