4

Hi I'm having a problem copying worksheets from one workbook to another in VB. The code I have works fine with brand new workbooks, but after awhile it breaks and gives me this error: "Method 'Copy' of object '_Worksheet' failed. A lot of people suggested saving the workbook and reopening it when you are copying. I tried that and it still didn't work. I also checked if maybe the name is becoming really long. I set the name of the worksheet to the counter before copying it, and I still got the bug. I am really confused, and hope someone may have figured out a solution to this. Also both workbooks only have 3 worksheets in them.

'Copies all the worksheets from one workbook to another workbook
'source_name is the Workbook's FullName
'dest_name is the Workbook's FullName
Function copyWorkbookToWorkbook(source_name As String, dest_name As String) As Boolean
    Dim dest_wb As Workbook
    Dim source_wb As Workbook
    Dim dest_app As New Excel.Application
    Dim source_app As New Excel.Application
    Dim source_ws As Worksheets
    Dim counter As Integer
    Dim num_ws As Integer
    Dim new_source As Boolean
    Dim new_dest As Boolean
    Dim ws As Worksheet
    Dim regex As String

    Application.ScreenUpdating = False

    If source_name = "" Or dest_name = "" Then
        MsgBox "Source and Target must both be selected!", vbCritical
        copyWorkbookToWorkbook = False
    ElseIf GetAttr(dest_name) = vbReadOnly Then
        MsgBox "The target file is readonly and cannot be modified", vbCritical
        copyWorkbookToWorkbook = False
    Else
        regex = "[^\\]*\.[^\\]*$"   'Gets only the filename
        copyWorkbookToWorkbook = True

        If (isWorkbookOpen(source_name)) Then
            Set source_wb = Workbooks(regExp(source_name, regex, False, True)(0).Value)
        Else
            Set source_wb = source_app.Workbooks.Open(source_name)
            new_source = True
        End If

        If (isWorkbookOpen(dest_name)) Then
            Set dest_wb = Workbooks(regExp(dest_name, regex, False, True)(0).Value)
        Else
            Set dest_wb = dest_app.Workbooks.Open(dest_name)
            new_dest = True
        End If

        'Clean the workbooks before copying the data
        'Call cleanWorkbook(source_wb)
        'Call cleanWorkbook(dest_wb)

        'Copy each worksheet from source to target

        counter = 0
        source_wb.Activate
        For Each ws In source_wb.Worksheets
            MsgBox dest_wb.Worksheets.Count
            ws.Copy After:=dest_wb.Worksheets(dest_wb.Worksheets.Count)
            counter = counter + 1
        Next ws

        'Save and close any newly opened files
        If (new_dest) Then
            dest_wb.Application.DisplayAlerts = False
            dest_wb.SaveAs Filename:=dest_name, ConflictResolution:=Excel.XlSaveConflictResolution.xlLocalSessionChanges
            dest_wb.Application.CutCopyMode = False
            dest_wb.Close
        End If
        If (new_source) Then
            source_wb.Application.DisplayAlerts = False
            source_wb.SaveAs Filename:=source_name, ConflictResolution:=Excel.XlSaveConflictResolution.xlLocalSessionChanges
            source_wb.Close
        End If

        MsgBox counter & " worksheets have been cleaned and copied.", vbInformation + vbOKOnly

    End If

    'Cleanup
    Set dest_wb = Nothing
    Set source_wb = Nothing
    Set dest_app = Nothing
    Set source_app = Nothing
    Set source_ws = Nothing
    Set ws = Nothing
End Function

Function regExp(str As String, pattern As String, ignore_case As Boolean, glo As Boolean) As MatchCollection
    Dim regex As New VBScript_RegExp_55.regExp
    Dim matches As MatchCollection

    regex.pattern = pattern
    regex.IgnoreCase = ignore_case
    regex.Global = glo

    Set regExp = regex.Execute(str)
End Function

Edit: What I meant with "this workbook breaks after awhile" is that I can run this code on it multiple times (maybe around 30 times). Eventually this error comes up "Method 'Copy' of object '_Worksheet' failed" even if I delete the worksheets in the dest_wb. It points at the Copy line.

4

2 に答える 2

2

「テンプレート」ファイルからワークシートをコピーする際にも同様の問題がありました。一定回数のコピー アンド ペーストの後に発生するメモリの問題だと思います (システムによって異なります)。

ワークシートの内容に応じて、いくつかの回避策があります。多くのワークブックをループする必要はありませんでしたが、次の関数が同じことを問題なく効果的に実行できることがわかりました。

ただし、ワークシートをあるブックから別のブックにコピーするたびに Excel の 2 つの新しいインスタンスを作成することは、おそらく役に立たないでしょう。Excel のインスタンスを使用できないのは、Excel のインスタンスを少なくとも 1 つ使用するだけです。

Sub CopyWorksheet(wsSource As Worksheet, sName As String, wsLocation As Worksheet, sLocation As String)
    'Instead of straight copying we just add a temp worksheet and copy the cells.
    Dim wsTemp As Worksheet

    'The sLocation could be a boolean for before/after. whatever.
    If sLocation = "After" Then
        Set wsTemp = wsLocation.Parent.Worksheets.Add(, wsLocation)
    ElseIf sLocation = "Before" Then
        Set wsTemp = wsLocation.Parent.Worksheets.Add(wsLocation)
    End If

    'After the new worksheet is created
    With wsTemp
        .Name = sName                           'Name it
        .Activate                               'Bring it to foreground for pasting
        wsSource.Cells.Copy                     'Copy all the cells in the original
        .Paste                                  'Paste all the cells
        .Cells(1, 1).Select                     'Select the first cell so the whole sheet isn't selected
    End With
    Application.CutCopyMode = False
End Sub
于 2013-06-07T21:44:08.413 に答える
1

はい、私が使用している一部のコードでまったく同じ問題がありますが、それを修正するために (明らかに) 必要なことを実行するのに十分なほど差し迫ったことはありません。

この問題は、このナレッジベース記事で説明されています。この記事では、次のことを示唆しています。

この問題を解決するには、コピー プロセスの実行中に定期的にブックを保存して閉じます。

「コピー時にワークブックを保存して再度開く」とおっしゃいましたが、ループ中に実行されている兆候が見られないため、コードを実行する前にそれを行っていると思います。ループ自体の中でそれを行う 1 つの方法は次のとおりです。

を持つことによってエラー処理を実装します。

On Error Goto

手順の早い段階でライン。それから

置く

Exit Function
ErrorHandler:

一番下にブロック。エラー ハンドラー自体の内部で、Err.Number が 1004 であるかどうかを確認する必要があります。そうである場合は、ソースと宛先の両方のブックを閉じてから、両方を再度開き、エラーが発生した行から再開します。無限ループに陥らないように、エラー ハンドラが呼び出された回数を追跡し、特定の回数を超えたらあきらめることをお勧めします。

これは基本的に私の問題を解決するために私が持っていたアイデアですが、それを実装する時間/差し迫った必要性はありませんでした. これを投稿する前にテストしたかったのですが、ファイルはオフィスにあり、現在アクセスできません。

あなたがその道を進むことにした場合、あなたがどのように進むかを見たいと思います.

もう 1 つのオプションは、KB 記事で提案されているもので、n 回繰り返した後にブックを閉じて再度開くことです。それに関する問題は、100回の反復を示唆しているのに対し、私の場合は32または33回後に失敗することです.(特に、シートのサイズに依存するようです.)また、10回後に失敗する場合もあります(まったく同じシートで) ) これを修正する唯一の方法は、Excel を閉じて再度開くことです。(明らかに、VBA ベースのコードのオプションはあまりありません。)

于 2013-06-07T20:35:13.383 に答える