【问题标题】:Excel VBA .SaveAs breaking in loopExcel VBA .SaveAs 打破循环
【发布时间】:2017-05-10 17:55:13
【问题描述】:

我有一个包含多个工作表的 Excel 工作簿,每个客户 1 个。在我的代码中,我试图将每个单独的客户工作表保存为自己的 excel 文件。但是,.SaveAs 命令在循环中第二次触发时会中断。任何指针都会很棒。

Dim SchedWorksheet As Worksheet
Dim SchedWorkbook As Workbook
Dim SchedName As String

Set SchedWorkbook = ActiveWorkbook
Set SchedWorksheet = ActiveSheet
Application.DisplayAlerts = False

For Each Worksheet In SchedWorkbook.Sheets
    If Worksheet.Name = "Instructions" Or Worksheet.Name = "Invoice_Items" 
    Or Worksheet.Name = "Customers" Or _
       Worksheet.Name = "Terms" Or Worksheet.Name = "Dilution_Type" Or 
       Worksheet.Name = "Approval_Status" Or _
       Worksheet.Name = "Carriers" Then
        GoTo NextSched
    End If

    If Worksheet.Name = "Invoices" Then
        'basicScheduleFileName is global set at beginning of program
        SchedName = basicScheduleFileName & "ALL"
    Else
        SchedName = Worksheet.Name
    End If

    'payoutFileName is global set at beginning of program
    Worksheet.SaveAs Application.ActiveWorkbook.Path & "\" & payoutFileName 
    & "\Basic Schedule" & "\" & SchedName, xlOpenXMLWorkbook

NextSched:
Next Worksheet

第二次迭代的错误如下: 运行时错误 1004 '应用程序定义的或对象定义的错误'

我还尝试使用 SchedWorksheet 对象代替 Worksheet 运行此循环,并在第二次迭代中得到错误“对象_Worksheet 的方法 .SaveAs 失败”。

问题 我的程序中的代码与他前面的代码非常相似,该代码采用类似的数据集并使用 exportAsFixedFormat 调用将每个工作表保存为 PDF。 .xlsx 是否有等价物? (.csv 也可以)

【问题讨论】:

  • "...第二次中断..." - 你有错误吗?什么错误?
  • 是的,很抱歉没有将其包含在 OP 中:“运行时错误 1004 应用程序定义或对象定义错误”
  • 您在哪里/如何声明和定义payoutFileName。还有,SchedName 第一次运行,第二次运行是什么?
  • 还有basicScheduleFileName是什么?
  • 尝试将“.xlsx”添加到您的 SchedName 的末尾

标签: vba excel


【解决方案1】:

我不知道“payOutFileName”有什么值,所以我把它从代码中省略了。我也不知道 basicScheduleFileName 的值,所以我将其设置为“Something”。您也必须将其更改为您需要更改的任何内容。保存到我的目录“C\Files”时效果很好可能对您来说有点麻烦。希望这将是一个开始。

Sub asdfghj()
Dim SchedWorkbook As Workbook
Dim SchedName As String
Dim basicScheduleFileName As String
Dim payoutFileName As String
Dim ws As Worksheet
Dim wb As Workbook

basicScheduleFileName = "Something"
Set SchedWorkbook = ActiveWorkbook
Application.DisplayAlerts = False

For Each ws In SchedWorkbook.Sheets
Debug.Print ws.Name
    If ws.Name = "Instructions" Or ws.Name = "Invoice_Items" _
    Or ws.Name = "Customers" Or _
       ws.Name = "Terms" Or ws.Name = "Dilution_Type" Or _
       ws.Name = "Approval_Status" Or _
       ws.Name = "Carriers" Then
        GoTo NextSched
    End If

    If ws.Name = "Invoices" Then
        SchedName = basicScheduleFileName & "ALL" & ".xlsx"
    Else
        SchedName = ws.Name & ".xlsx"
    End If

    ws.Activate

'    SaveAs Application.ActiveWorkbook.Path & "\" & payoutFileName & "\Basic Schedule" & "\" & SchedName, xlOpenXMLWorkbook

    Set wb = Workbooks.Add
    ws.Copy Before:=wb.Sheets(1)
    wb.Sheets("Sheet1").Delete
    wb.SaveAs Filename:="C:\Files\" & SchedName, FileFormat:= _
        xlOpenXMLWorkbook, CreateBackup:=False
    wb.Close

NextSched:
Next ws



End Sub

【讨论】:

  • 感谢您抽出宝贵时间整理这些内容。不幸的是,与我所有其他尝试一样,此代码在循环的第一次迭代中工作,然后在下一次迭代中中断。
  • 你知道如何设置断点进行调试吗?我们需要找到它停止的确切线。由于它在我的 Excel 2013 上运行良好,我无法检测到你的坏行。你必须自己做这件事。查看此站点进行调试。 cpearson.com/excel/DebuggingVBA.aspx
  • 代码在 .SaveAs 行中断,这与我在之前的代码中看到的行为相同。让我问你一个关于你的代码的问题,我至少有十几个工作表需要在我的代码中保存为单独的文件。您提供的代码在第一次保存后关闭工作簿 (wb.Close),一旦我保存一次,这不会把我踢出循环吗?
  • wb 是一个新工作簿,不是执行代码的工作簿,因此关闭它没有问题。
  • 尼克是正确的。您创建的新工作簿设置为 wb,因此当您关闭 wb 时,您将关闭新工作簿。但至少现在我们知道您的代码在哪里引发错误。你说这是你第二次尝试保存工作表,而不是第一次。所以在 saveas 行上放一个断点。当它第一次停止时,点击 PF5 让它完成第一个工作表。当它第二次返回并停止时,您可以将鼠标悬停在路径和文件名的变量上以查看它们的值。它们可能是不兼容的文件名或路径不存在。
【解决方案2】:

首先,感谢所有花时间和智慧来解决我的问题的人。我终于找到了一个可行的解决方法。
首先我确保删除 ActiveWorkbook 和 ActiveSheet 引用以避免在 Excel 中出现任何混淆。
其次 @NickSlash 指出,即使我的代码确实有效,它也可能会以不同的名称保存同一文件的多个副本。因此,为了解决这个问题,同时解决了我最初的问题,我更改了代码,将我需要的工作表复制到新工作簿中并以这种方式保存:

Dim WS As Worksheet
Dim WB As Workbook
Dim NWB As Workbook
Dim SchedName As String

Set WB = Workbooks("Basic_Schedule-.xls")
WB.Activate

'Application.DisplayAlerts = False

For Each WS In WB.Sheets
    WB.Activate

    If WS.Name = "Instructions" Or WS.Name = "Invoice_Items" Or WS.Name = "Customers" Or _
       WS.Name = "Terms" Or WS.Name = "Dilution_Type" Or WS.Name = "Approval_Status" Or _
       WS.Name = "Carriers" Then
        GoTo NextSched
    End If

    If WS.Name = "Invoices" Then
        SchedName = basicScheduleFileName & "ALL" & ".xlsx"
    Else
        SchedName = WS.Name & ".xlsx"
    End If


    'Copy sheet to another WB
    Set NWB = Workbooks.Add
    WB.Activate
    Sheets(WS.Name).Copy After:=NWB.Sheets(NWB.Sheets.Count)
    NWB.Sheets("Sheet1").Delete
    NWB.SaveAs filename:=basicScheduleFilePath & "\" & payoutFileName & "\Basic Schedule" & "\" & SchedName
    NWB.Close
    WB.Activate

NextSched:
Next WS

而不是这个:

'Copy sheet to another WB
Set NWB = Workbooks.Add
WB.Activate
Sheets(WS.Name).Copy After:=NWB.Sheets(NWB.Sheets.Count)
NWB.Sheets("Sheet1").Delete
NWB.SaveAs filename:=basicScheduleFilePath & "\" & payoutFileName & "\Basic Schedule" & "\" & SchedName
NWB.Close
WB.Activate

这样做 - 您可以避免“激活”方法调用,而且如果您将 WS 作为对象引用,那么当 WS 已经引用同一个工作表时,执行 WB.Sheets(WS.Name) 是多余的。

'Copy sheet to another WB
WS.Copy '## Creates a new workbook with the copied sheet.
Set NWB = ActiveWorkbook
NWB.SaveAs filename:=basicScheduleFilePath & "\" & payoutFileName & "\Basic Schedule" & "\" & SchedName
NWB.Close

【讨论】:

  • 提出了改进您的解决方案的建议,并将其编辑到您上面的答案中。干杯。
  • 非常感谢@DavidZemens 的其他提示,我会做出这些改变。
猜你喜欢
  • 2015-04-27
  • 2017-05-26
  • 2023-03-29
  • 1970-01-01
  • 2020-05-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多