Объединение больших листов - самый быстрый / надежный метод?

Я часто объединяю огромные рабочие листы в один для целей отчетности.

У меня часто возникают проблемы с макросами, из-за которых не хватает памяти, я отказываюсь работать, блокирую компьютер и т. д.

При поиске на этом сайте я видел много раз, что копировать вставить - это метод помедленнее для перемещения больших наборов данных.

Однако, когда я попробовал эти два разных подхода, копировать вставить был Быстрее (я даже пытался отключить обновления экрана!)

Чем превосходит dest = src? Я подумал, что, поскольку он избегает использования функций уровня приложения, это будет быстрее. (Мне также пришлось вставить эти части Sheet (i) .Activate, чтобы заставить переменные диапазона работать.)

Я тестировал 5 листов, содержащих около 60 тыс. Строк и 49 столбцов. Код копировать вставить справился с этим примерно за 30 секунд, в то время как dest = src, похоже, занял больше примерно 90 секунд.

Кроме того, я читал об использовании динамических массивов для копирования данных таким образом, но мне так и не удалось заставить его работать.

Код копировать вставить:

Sub Combine()
    Dim J As Integer
    On Error Resume Next
    Sheets(1).Select
    Worksheets.Add
    Sheets(1).Name = "Combined"
    Sheets(2).Activate
    Range("A1").EntireRow.Select
    Selection.Copy Destination:=Sheets(1).Range("A1")
    For J = 2 To Sheets.Count
        lastRow = Sheets(1).Cells(Sheets(1).Rows.Count, "A").End(xlUp).Row
        Sheets(J).Activate
        Range("A1").Select
        Selection.CurrentRegion.Select
        Selection.Offset(1, 0).Resize(Selection.Rows.Count - 1).Select
        Selection.Copy Destination:=Sheets(1).Range("A" & lastRow + 1)
    Next
End Sub

Код dest = src:

Sub collateSheets()

    Dim ws As Worksheet
    Dim LR As Long, LR2 As Long
    Dim LC As Long
    Dim i As Long
    Dim src As Range
    Dim dest As Range

    startNoUpdates

    Set ws = Worksheets.Add(before:=Sheets(1)) ' place new sheet in first position
    With ws
        .Name = "Collated Data"
        .Range("1:1").Value = Sheets(2).Range("1:1").Value
    End With
    On Error GoTo skip
    For i = 2 To Worksheets.Count ' avoiding "Collated Data"
        With Sheets(i)
            LC = .Cells(1, .Columns.Count).End(xlToLeft).Column
        End With
        LR = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
        LR2 = Sheets(i).Cells(Sheets(i).Rows.Count, 1).End(xlUp).Row
        Sheets(i).Activate
        Set src = Sheets(i).Range(Cells(2, 1), Cells(LR2, LC))
        Sheets(1).Activate
        Set dest = Sheets(1).Range(Cells(LR + 1, 1), Cells(LR + LR2 - 1, LC))
        dest.Value = src.Value
skip:
    Next

    endNoUpdates

End Sub

Sub startNoUpdates()
With Application
    .ScreenUpdating = False
    .EnableEvents = False
    .Calculation = xlCalculationManual
    .DisplayAlerts = False
End With
End Sub

Sub endNoUpdates()
With Application
    .ScreenUpdating = True
    .EnableEvents = True
    .Calculation = xlCalculationAutomatic
    .DisplayAlerts = True
End With
End Sub

РЕДАКТИРОВАТЬ1:

Я попробовал очень изощренно выглядящий код user10798192 (Что такое IIf?) И улучшенный код копирования / вставки Harassed Dad.

copy/paste - 10.6 Seconds
dest = src - > 120 seconds

Так что, по крайней мере, для объединения листов копирование / вставка, похоже, сокрушает его.

В обоих случаях, вероятно, было бы неплохо не использовать ни .Select, ни .Activate. См. Как избежать использования Select в Excel VBA.

Vincent G 17.12.2018 16:31

Вы делаете в цикле вещи, которые а) нужно выполнить только один раз за пределами цикла, б) можно избежать массовых операций, не использующих циклы.

user10798192 17.12.2018 16:36

Кроме того, если код работает, вы можете вместо этого отправить его в CodeReview

BruceWayne 17.12.2018 16:53
Преобразование HTML-таблицы в профессиональный документ Excel
Преобразование HTML-таблицы в профессиональный документ Excel
Это самый простой способ создания Excel из HTML-таблицы.
Импорт excel в laravel в базу данных
Импорт excel в laravel в базу данных
Здравствуйте, дорогой читатель, в этой статье я расскажу практическим и быстрым способом, как импортировать файл Excel в вашу базу данных с помощью...
0
3
42
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий
Sub Demo()
 'generic aggregate all sheets into 1 routine
 Application.ScreenUpdating = False
 Application.Calculation = xlCalculationManual
 On Error GoTo whoops
 Dim ws As Worksheet
 Dim dest As Worksheet
 Dim source As Range
 Dim Target As Range
 Set dest = Worksheets.Add()
 Set Target = dest.Range("a1")
 Worksheets(1).Range("a1").EntireRow.Copy Target
 Set Target = Target.Offset(1, 0)
 For Each ws In Worksheets
     If ws.Index <> 1 Then
        ws.UsedRange.Copy Target
        Set Target = dest.Range("a" & Rows.Count).End(xlUp).Offset(1, 0)
      End If
 Next ws
 whoops:
 Application.ScreenUpdating = True
 Application.Calculation = xlCalculationAutomatic
 MsgBox "Done"
 End Sub

Я думаю, вы могли бы найти этот подход немного быстрее

Option Explicit

Sub collateSheets()

    Dim ws As Worksheet, w As Long

    alterEnvironment restore:=False

    Set ws = Worksheets.Add(before:=Sheets(1))
    With ws
        .Name = "Collated Data"
        .Range("1:1").Value = Sheets(2).Range("1:1").Value
    End With

    On Error GoTo skip
    For w = 2 To Worksheets.Count
        With Worksheets(w).Cells(1).CurrentRegion.Offset(1)
            Worksheets(1).Cells(.Rows.Count, "A").End(xlUp). _
                Offset(1).Resize(.Rows.Count, .Columns.Count) = .Value
        End With
skip:
    Next w

    alterEnvironment

End Sub

Sub alterEnvironment(Optional restore As Boolean = True)

    Static origCalc As Variant

    With Application
        If IsEmpty(origCalc) Then origCalc = .Calculation
        .Calculation = IIf(restore, origCalc, xlCalculationManual)
        .ScreenUpdating = restore
        .EnableEvents = restore
        .DisplayAlerts = restore
    End With

End Sub

этот код оказался намного медленнее с большими наборами данных, я думаю, это должно быть как-то связано с тем, как используется активная память ... намного выше моей головы! Ваш код действительно интригующий, хотя мне придется его изучить

HotSauceCoconuts 17.12.2018 23:48

Другие вопросы по теме