【问题标题】:VBA Run-time error 1004: Method Range of object _Global failed when trying to create tables in Excel 2013VBA 运行时错误 1004:尝试在 Excel 2013 中创建表时对象 _Global 的方法范围失败
【发布时间】:2018-01-11 01:38:37
【问题描述】:

我知道之前已经发布过与这些错误类似的问题,但是在格式化表格时我什么也没找到,所以请不要关闭它。在我的 MS Access 2013 中的 VBA 代码中,它将数据从 MS Access 导出到 Excel。 6 个不同的查询被导出到 1 个 excel 文件中,每个都在不同的工作表上。这工作正常。然后我格式化每张表以将所有数据放在一个表中。我有一个表单可以让用户选择保存文件的路径。如果是第一次创建文件,它可以正常工作。如果这是第二次在同一个目录中创建文件,它不起作用,它给了我错误:

运行时错误1004:对象_Global的方法范围失败

我认为这是因为我覆盖了我的文件,而不是删除它并重新创建它。所以我添加了一些代码来检查文件是否存在,如果存在,删除它。我添加了断点,在运行这部分代码时,我正在查看我的文档文件夹。该文件已成功删除,然后重新创建,这正是我想要的。它仍然给了我这个错误。我手动去删除文件,然后再次重新运行我的代码。它工作正常。

为什么我需要手动删除这个文件才能重新运行我的代码?还是其他原因导致了问题?这是我的代码的重要部分,因为整个内容太长,无法发布:

'Checks if a file exists, then checks if it is open
Private Sub checkFile(path As String)

Dim openCheck As Boolean
'If file exists, make sure it isn't open. If it doesn't, create it
If Dir(path) <> "" Then
    openCheck = IsFileLocked(path)
    If openCheck = True Then
        MsgBox "Please close the file in " & path & " first and try again."
        End
    Else
        deleteFile (path)
    End If
Else

End If

End Sub

Sub deleteFile(ByVal FileToDelete As String)

    SetAttr FileToDelete, vbNormal
    Kill FileToDelete

End Sub

Private Sub dumpButton_Click()

On Error GoTo PROC_ERR

Dim path As String
Dim testBool As Boolean

path = pathLabel4.Caption
path = path & Format(Date, "yyyy-mm-dd") & ".xlsx"

checkFile (path)
dumpQueries (path)
formatFile (path)

'Error Handling
PROC_ERR:

If Err.Number = 2001 Then
    MsgBox "A file may have been sent to " & path
    Exit Sub
ElseIf Err.Number = 2501 Then
    MsgBox "A file may have been sent to " & path
    Exit Sub
ElseIf Err.Number = 3021 Then
    MsgBox "A file may have been sent to " & path
    Exit Sub
ElseIf Err.Number = 2302 Then
    MsgBox "A file may have been sent to " & path
    Exit Sub
ElseIf Err.Number = 0 Then
    MsgBox "Your file has been stored in " & pathLabel4.Caption
    Exit Sub
Else
    MsgBox Err.Number & ": " & Err.Description & vbCrLf & vbCrLf & "New Error. Please contact the IT department."
End If


Private Sub dumpQueries(path As String)

Dim obj As AccessObject, dB As Object

Set dB = Application.CurrentData
For Each obj In dB.AllQueries
    testBool = InStr(obj.name, "Sys")
    If testBool <> True Then
        If obj.name = "example1" Or obj.name = "example2" Then
                DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel12Xml, obj.name, path, True, editWorksheetName(obj.name)
        End If
    End If
Next obj

End Sub


'Autofits the cells in every worksheet
Private Sub formatFile(path As String)

Dim Date1 As Date, strReportAddress As String
Dim objActiveWkb As Object, appExcel As Object

Set appExcel = CreateObject("Excel.Application")
appExcel.Visible = False
appExcel.Application.Workbooks.Open (path)

Set objActiveWkb = appExcel.Application.ActiveWorkbook
With objActiveWkb
    Dim i As Integer
    For i = 1 To .Worksheets.count
        .Worksheets(i).Select
        .Worksheets(i).Cells.EntireColumn.AutoFit
        .Worksheets(i).ListObjects.Add(xlSrcRange, Range("A1").CurrentRegion, , xlYes).name = "myTable1"         
    Next
End With

appExcel.ActiveWindow.TabRatio = 0.7
objActiveWkb.Close savechanges:=True
appExcel.Application.Quit
Set objActiveWkb = Nothing: Set appExcel = Nothing

End Sub

错误发生在代码底部附近。就是这样:

.Worksheets(i).ListObjects.Add(xlSrcRange, Range("A1").CurrentRegion, , xlYes).name = "myTable1"

我可能遗漏了几个功能,但它们工作正常,不需要回答问题。

【问题讨论】:

  • xlSrcRangeRange("A1") 所指的活动工作表不在同一个工作表上。这应该是第 20000 次问这个问题了。解决方案是正确限定 RangeCells 调用/避免对活动工作表或工作簿的隐式引用。
  • @Mat'sMug 你说的是这个吗?因为它给了我这个错误:“438:对象不支持这个属性或方法”这是代码:.Worksheets(i).ListObjects.Add(SourceType:=xlSrcRange, Source:=.Cells(1).CurrentRegion, _ XlListObjectHasHeaders:=xlYes, TableStylename:="TableStyleMedium1").name = "Table"

标签: excel vba ms-access


【解决方案1】:

这是唯一相关的代码:

Set objActiveWkb = appExcel.Application.ActiveWorkbook
With objActiveWkb
    Dim i As Integer
    For i = 1 To .Worksheets.count
        .Worksheets(i).Select
        .Worksheets(i).Cells.EntireColumn.AutoFit
        .Worksheets(i).ListObjects.Add(xlSrcRange, Range("A1").CurrentRegion, , xlYes).name = "myTable1"         
    Next
End With

当您修剪掉绒毛并开始命名事物时,事情会变得更容易理解 - 不需要.Select 任何东西,appExcel 已经 @987654324 @ 对象,并且没有必要对活动工作簿进行复制引用以在 With 块中使用,特别是如果该副本将成为 Object 变量无论如何 - 如果副本是 Workbook 对象那么您至少会为其成员获得 IntelliSense...

您的来源范围不明确。 Range("A1") 在 Excel-VBA 中 是对活动工作表的隐式引用。但这是 Access-VBA,所以没有这样的东西,xlSrcRange 是在 Excel 对象模型中定义的枚举值,因此,如果您没有对 Excel 对象模型的引用(您正在后期绑定 this,对吗?),并且未指定 Option Explicit,则 VBA 会将 xlSrcRange 视为另一个未声明/未初始化的变量,因此您在那里传递了0xlSrcRange 枚举值代表1 - 而0 恰好是xlSrcExternal 的基础值。与xlYes 相同。

由于我们无法从您发布的代码中猜出实际的源代码范围应该是什么,所以我将把这个留给您:

Dim target As Object
Dim srcRange As Object
Set srcRange = TODO

With appExcel.ActiveWorkbook
    Dim i As Integer
    For i = 1 To .Worksheets.Count
        .Worksheets(i).Cells.EntireColumn.AutoFit
        Set target = .Worksheets(i).ListObjects.Add(1, srcRange, , 1)
        If target Is Not Nothing Then target.Name = "myTable1"
    Next
End With

附带问题...为什么将表命名为 myTable1,而 Excel 已经将其命名为 Table1?另请注意,如果 .Add 失败,您的代码会因运行时错误 91 而崩溃,因为您将调用 .Add 关闭 Nothing。在设置Name 之前验证target 不是Nothing 将避免这种情况。

在 cmets 中回答您的问题:

@Mat'sMug 你说的是这个吗?因为它给了我这个错误:“438:对象不支持这个属性或方法”这是代码:.Worksheets(i).ListObjects.Add(SourceType:=xlSrcRange, Source:=.Cells(1).CurrentRegion, _ XlListObjectHasHeaders:=xlYes, TableStylename:="TableStyleMedium1").name = "Table"

抛出 438 的原因是因为您的 With 块变量是 Workbook 对象,而 Workbook 对象没有 .Range 成员。

我所说的是,在 Excel VBA 中,对 RangeRowColumnCells 的非限定调用隐式引用了 ActiveSheet,以及对 Worksheets、@ 的非限定调用987654358@ 和 Names 隐式引用 ActiveWorkbook - 这是许多 VBA 代码中经常出现的问题,也是一个非常常见的错误。解决方案基本上是说你的意思,并且说你所说的;在这种情况下,失败在于“你所说的意思” - 根据错误消息,不合格的 Range("A1") 调用是调用 [_Globals].Range("A1")... 这很奇怪,因为它暗示你正在引用 Excel 对象模型库,这意味着您的后期绑定和 Object 变量也可以是早期绑定的:当您已经引用您的库时,为什么要处理 Object 变量和缺少 IntelliSense '是否要后期绑定?

【讨论】:

  • 感谢您的帮助。这对我为什么不能使用 xlSrcRange 很有意义。对于您作为“TODO”留下的 srcRange,我要为此输入什么?我尝试了“A1:B2”但收到错误。例如,我想将表格从 A1 变为 B2,我将如何使用这段代码来做到这一点?此外,我在“Nothing”行中遇到错误
  • @Michael 如果您的源范围是appExcel.ActiveWorkbook.Worksheets(1) 中的"A1:B2",那么您可以将该对象设置为appExcel.ActiveWorkbook.Worksheets(1).Range("A1:B2") - 这是包含这些单元格的工作表对象,我无法从您的代码中推断出已发布。
  • 抱歉含糊不清。我有多个不同范围的不同工作表。我需要创建一个动态范围,将每个工作表中的所有数据格式化为一个表格。为清楚起见,我有 6 个充满数据的工作表,我需要输出 6 个包含该数据的表。我不知道指定的范围。我有一些计算它的函数,但我不知道如何将它合并到 ListObjects.Add 方法中。例如,最后一行数据存储在“lastRow”变量中,最后一列数据存储在“lastColumn”变量中。
  • 我只需要知道如何使用它来创建范围规范的“A1:B2”样式,然后在 Range() 属性中使用它
  • 所以源范围与正在创建的ListObject 表在同一个工作表上?然后将您的Range("A1") 代码更改为.Worksheets(i).Range("A1")。我要强调的一点是,您不能在这里使用不合格的Range,您需要在哪个工作表上告诉它获取这些单元格。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多