关于excel:VBA usedrange run-time error 438 object doesn’t support this property or method

VBA usedrange run-time error 438 object doesn't support this property or method

我正在研究一个涉及 usedrange 的宏。基本上,我的子尝试使用 opentext 打开一个文本文件并复制文本文件中的公式并粘贴到我的目标工作簿的工作表"SOE 摘要"。但是,当我尝试将工作表"SOE 摘要"的公式设置为等于文本文件中的公式时,会出现运行时错误 438。任何见解将不胜感激。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Sub Sample()
Application.ScreenUpdating = False
Dim WB As Workbook
Set WB = ActiveWorkbook


Dim fileToOpen As Variant 'Txt file that contains formulas
Dim fileName As String _
'Name of the temporary workbook that contains formulas from fileToOpen
Dim sheetName As String _
'Name of the worksheet of the temporary workbook that contains formulas from fileToOpen
fileToOpen = Application.GetOpenFilename("Text Files (*.txt), *.txt") _
'User selects the txt file that contains formulas
If fileToOpen <> False Then 'Make sure the user selects a txt file
    Workbooks.OpenText fileName:=fileToOpen, _
    DataType:=xlDelimited, Tab:=True 'Transport formulas into a temporary workbook
End If
fileName = Mid(fileToOpen, InStrRev(fileToOpen,"") + 1) _
'Name of the temporary workbook
sheetName = Left(ActiveWorkbook.Name, Len(ActiveWorkbook.Name) - 4) _
'Name of the temporary worksheet


Application.DisplayAlerts = False 'Disable any popup windows
WB.Sheets("SOE Summary").UsedRange.Value = Workbooks(fileName).Sheets(sheetName).UsedRange.Formula_
'[ERROR 438 OCCURRED] Paste formulas into"SOE Summary" worksheet
Application.DisplayAlerts = True 'Enable popup windows after the previous line of code


Workbooks(fileName).Close savechanges:=False 'Close the temporary workbook and discard any changes
WB.Sheets("SOE Summary").UsedRange.Value = WB.Sheets("SOE Summary").UsedRange.Value _
'Replace all formulas in the"SOE Summary" worksheet with values
Application.ScreenUpdating = True

End Sub


在 VBA 中,一条指令由一个新行终止,或者如果您希望在一行中包含多个指令,则由一个指令分隔符标记(即冒号 : - 不是您通常希望在一行中包含多个指令).

VBA 中的一行代码可以被视为逻辑代码行或物理代码行。当代码行变得太宽/太长时,您可以使用行继续标记(空格后跟下划线 _)将逻辑代码行继续到下一个物理代码行。

正如所指出的,这些行中的大多数不需要继续 - 事实上,您的代码只编译是因为继续的行"继续"成为注释,这隐含地终止了指令:

1
2
3
fileName = Mid(fileToOpen, InStrRev(fileToOpen,"") + 1) _
'Name of the temporary workbook
sheetName = Left(ActiveWorkbook.Name, Len(ActiveWorkbook.Name) - 4) _

删除这些注释,您的代码将停止编译:

1
2
fileName = Mid(fileToOpen, InStrRev(fileToOpen,"") + 1) _
sheetName = Left(ActiveWorkbook.Name, Len(ActiveWorkbook.Name) - 4) _

...因为你不能在同一条指令中有两个作业。

所以,是的,删除无关的续行,问题就解决了。

您得到的具体错误相当令人困惑,因为 UsedRange 返回一个实际的 Range 对象引用,这使您可以在这里预期编译时错误而不是运行时错误。在底层,这表明 Range COM 接口是可扩展的——这意味着尽管大多数成员调用在编译时是早期绑定/解析的,但 VBA 允许您对 Range 对象进行任何时髦的成员调用,并推迟验证运行时。证明:

1
2
3
4
Sub Foo()
    Dim bar As Range
    bar.Whatever = 42 ' happily compiles
End Sub

这意味着在进行 Range 成员调用时需要特别注意拼写错误,因为即使 Option Explicit 也无法帮助您解决这个问题 - 换句话说,在引用已知时使用 IntelliSense / 自动完成成员,以避免此类错误。

由于在 VBA 中标识符可以很好地以下划线结尾(例如 Formula_),只有在运行时 VBA 才查询 Range 接口并发现没有像 Formula_ 这样的东西 - 并且繁荣,错误 438。


一些事情:

  • _ 用于指示单行语句将在下一行继续。它很少需要,您将在下面看到,实际上在您的子程序中的任何地方都不需要
  • 在这种情况下,您的实际问题是您的错误行上有 UsedRange.Formula_ 而不是 UsedRange.Formula _ 。注意缺少的空间
  • 您的评论使您的代码有些混乱。尽量只对解释代码中不太明显的特性的事情发表评论。例如,您的变量命名良好,因此您无需注释 fileName'Name of the temporary workbook
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Sub Sample()
    Application.ScreenUpdating = False
    Dim WB As Workbook
    Set WB = ActiveWorkbook

    Dim fileToOpen As Variant
    Dim fileName As String, sheetName As String

    fileToOpen = Application.GetOpenFilename("Text Files (*.txt), *.txt")

    If fileToOpen <> False Then
        Workbooks.OpenText fileName:=fileToOpen, DataType:=xlDelimited, Tab:=True
    End If

    fileName = Mid(fileToOpen, InStrRev(fileToOpen,"") + 1)
    sheetName = Left(ActiveWorkbook.Name, Len(ActiveWorkbook.Name) - 4)

    Application.DisplayAlerts = False
    WB.Sheets("SOE Summary").UsedRange.Value = Workbooks(fileName).Sheets(sheetName).UsedRange.Formula
    Application.DisplayAlerts = True

    Workbooks(fileName).Close savechanges:=False

    WB.Sheets("SOE Summary").UsedRange.Value = WB.Sheets("SOE Summary").UsedRange.Value
    Application.ScreenUpdating = True
End Sub