Squeak.ru - шаблоны программирования

Объединение больших файлов Excel, не могу обойти переполнение буфера

Я пытаюсь объединить несколько больших файлов Excel в один файл, используя следующий код

Sub Macro1()
    Application.DisplayAlerts = False
    Dim Country As String
    Dim i As Integer
    Dim j As Integer
    Dim k As Integer

    k = 2
    For i = 1 To 50
        Windows("Try2").Activate
        Country = Worksheets("Names").Cells(i, 1).Value
        Workbooks.Open Filename:= "C:path\" & Country & " "
        ActiveWorkbook.Sheets("Main").Activate
        finalrow = Cells(Rows.Count, 1).End(xlUp).Row

        Workbooks(Country).Sheets("Main").Range(Cells(1, 1), Cells(10000, 64)).Copy
        Workbooks("Try2").Sheets("Output").Activate
        Workbooks("Try2").Sheets("Output").Cells(k, 2).PasteSpecial xlPasteValues
        Range(Cells(k, 1), Cells(k + 10000, 1)) = Country
        finalrow2 = 10002 + k
        k = finalrow2 + 1
        Workbooks(Country).Sheets("Main").Activate
        Workbooks(Country).Close SaveChanges:=False
    Next i
End Sub

Однако после объединения 2-3 файлов excel выдает ошибку переполнения буфера. У нас около 50 файлов. Я пытаюсь выяснить, является ли это просто проблемой, когда Excel не может обрабатывать большие файлы, или что-то не так с моим кодом. Есть ли способ направить Excel для обработки файлов большего размера?


  • Попробуйте использовать что-то в этом роде вместо специального копирования и вставки application.Workbooks(2).ActiveSheet.range("a1:c5").value=application.Workbooks(1).ActiveSheet.range("a1:c5").value 09.12.2016
  • Мне жаль, что я не могу обдумать ваше предложение. Извинения 09.12.2016
  • вы также объявили свои переменные как целые числа, я не уверен, сколько строк вы собираетесь использовать в консолидации, но если они превышают предел 32767 целых чисел в excel, он вернет ошибку переполнения, попробуйте объявить их как «длинный ' 09.12.2016
  • Я обычно стараюсь воздерживаться от копирования и брать только данные, быстрее и проще всего для меня читать всю таблицу в массив (если таблица очень большая, я беру не .Value, а .Value2, что означает, что он берет только сырые значение и значительно быстрее Печать обратно на лист, а затем форматирование тоже довольно быстро Копирование также имеет недостаток копирования всех видов иногда «забавного» форматирования. 09.12.2016

Ответы:


1

вполне в соответствии с хорошей практикой кодирования, которую Werff уже объяснил вам, вы можете попробовать этот другой (прокомментированный) код:

Sub Macro1()
    Dim outputSht As Worksheet '<--| declare a variable to set your "output" sheet to
    Dim countryData As Variant, countryNames As Variant '<--| declare arrays to store "country names" and "country data" in
    Dim country As Variant '<-- "countries" looping variable

    Application.Calculation = xlCalculationManual '<-- disable calculations
    Application.ScreenUpdating = False '<-- disable screen updating


    With Workbooks("Try").Worksheets("Names") '<--| reference "country names" worksheet
        countryNames = Application.Transpose(.Range("A1", .Cells(.Rows.count, 1).End(xlUp)).Value) '<--| store country names in column "A" from row 1 down to last not empty row
    End With

    Set outputSht = Workbooks("Try").Worksheets("Output") '<--| set "output" worksheet
    For Each country In countryNames '<-- loop through countries stored in 'countryNames'

        With Workbooks.Open(FileName:="C:path\" & Country).Sheets("Main") '<--| open current country workbook and reference its "Main" sheet
            countryData = .Range("BL1", .Cells(.Rows.count, 1).End(xlUp)).Value '<--| store current country data in 'countryData' array
            .Parent.Close SaveChanges:=False '<--| close current country workbook
        End With

        With outputSht '<--| reference output sheet
            With .Cells(.Rows.count, 1).End(xlUp).Offset(1).Resize(UBound(countryData, 1)) '<--|reference its column A range from first empty cell after last not empty cell down to as many rows as current country array has
                .Value = country '<--| write current country name in referenced range
                .Offset(, 1).Resize(, 64).Value = countryData '<--| write country data array content from column B rightwards
            End With
        End With
    Next country

    Application.Calculation = xlCalculationAutomatic
    Application.ScreenUpdating = True

End Sub

поскольку он использует массивы для хранения данных, он страдает от ограничения максимального размера массива до 65536 строк. Если ваши рабочие книги «страны» «Основные» листы имеют больше строк, чем такое ограничение, тогда необходимо использовать разные методы вставки значений (например, между значениями диапазона)

09.12.2016

2

Здесь есть пара вещей, которые могут сбить ваш макрос.

Во-первых, вы объявляете i, j и k как "целочисленный" тип данных; проблема в том, что максимально возможное значение, которое может содержать целое число, равно 32 767. Если вы пойдете выше этого, вы получите переполнение буфера.

Во-вторых, вы объявляете переменные, которые не используете, и не объявляете переменные, которые используете. Насколько я вижу, j нигде в коде не используется, а finalrow и finalrow2 используются, но нигде не объявлены.

Я бы посоветовал вам заменить ваши integer типы данных, которые могут быть очень высокими, на long типы данных (длинное целое число). Вы также можете использовать более описательные имена для ваших целых чисел, чтобы ваш код было легче читать:

Dim iCycler as integer
Dim kStart as long
Dim FinalRow as Long
Dim FinalRow2 as Long

Пройдите через это и посмотрите, что вы получите.

ОТРЕДАКТИРОВАНО ДОБАВИТЬ:

Вот полный процесс, который должен подойти вам:

Sub Duplicator()

    'Define the source file, sheet, and range
    Dim wbkSource As Workbook
    Dim shtSource As Worksheet
    Dim rngSource As Range
    'Define the target file, sheet and range
    Dim wbkTarget As Workbook
    Dim shtTarget As Worksheet
    Dim rngTarget As Range
    'Define the sheet with the list of countries
    Dim shtControl As Worksheet
    'Prepare control integers
    Dim iLoop As Integer
    Dim lLastRow As Long

    'Define the target file as the active workbook
    Set wbkTarget = ActiveWorkbook
    Set shtTarget = wbkSource.Sheets("Output")
    Set rngTarget = shtTarget.Range("A2")
    Set shtControl = wbkTarget.Sheets("Names")

    'Loop through the list
    For iLoop = 1 To 50
        'Open the source file and assign it to a variable.
        Set wbkSource = Workbooks.Open("C:\path\" & shtControl.Cells(iLoop, 1).Value)
        'Assign the source sheet
        Set shtSource = wbkSource.Sheets("Main")
        'Find the last row of data
        lLastRow = shtSource.Range("A" & Rows.Count).End(xlUp).Row
        'Use the last row to build a source range variable
        Set rngSource = shtSource.Range("A1", "BL" & lLastRow)
        'Check that there is space for the copy. If there is not, create a new sheet for the new data
        If rngTarget.Row + lLastRow > shtTarget.Rows.Count Then
            Set shtTarget = wbkTarget.Sheets.Add
            shtTarget.Name = "Output 2"
            Set rngTarget = shtTarget.Range("A2")
        End If
        'Use the size of rngSource to define the size of the target range
        Set rngTarget = rngTarget.Resize(rngSource.Rows.Count, rngSource.Columns.Count)
        'Duplicate the values over
        rngTarget.Value = rngSource.Value
        'Prepare the target range for the next loop
        Set rngTarget = shtTarget.Range("A" & Rows.Count).End(xlUp).Offset(1, 0)
        'Close the source file
        wbkSource.Close False
    Next iLoop
End Sub

Благодаря объявлению и использованию переменных код должен быть проще как для написания, так и для чтения. Он также должен работать быстрее, так как использует структуру range1.value = range2.value, которая обходит довольно медленный буфер обмена. Он также содержит проверку, чтобы убедиться, что вы не превышаете 1 048 576 строк данных, что может привести к сбою.

09.12.2016
Новые материалы

Угловая структура архитектуры
Обратите внимание, что эта статья устарела, я решил создать новую с лучшей структурой и с учетом автономных компонентов: https://medium.com/@marekpanti/angular-standalone-architecture-b645edd0d54a..

«Данные, которые большинство людей используют для обучения своих моделей искусственного интеллекта, поставляются со встроенным…
Первоначально опубликовано HalkTalks: https://hacktown.com.br/blog/blog/os-dados-que-a-maioria-das-pessoas-usa-para-treinar-seus-modelos-de-inteligencia-artificial- ja-vem-com-um-vies-embutido/..

Сильный ИИ против слабого ИИ: различия парадигм искусственного интеллекта
В последние годы изучению и развитию искусственного интеллекта (ИИ) уделяется большое внимание и прогресс. Сильный ИИ и Слабый ИИ — две основные парадигмы в области искусственного интеллекта...

Правильный способ добавить Firebase в ваш проект React с помощью React Hooks
React + Firebase - это мощная комбинация для быстрого и безопасного создания приложений, от проверки концепции до массового производства. Раньше (знаете, несколько месяцев назад) добавление..

Создайте API с помощью Python FastAPI
Создание API с помощью Python становится очень простым при использовании пакета FastAPI. После установки и импорта вы можете создать приложение FastAPI и указать несколько конечных точек. Каждой..

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

Получить бесплатный хостинг для разработчиков | Разместите свой сайт за несколько шагов 🔥
Статические веб-сайты — это веб-страницы с фиксированным содержанием и его постоянным содержанием. Но теперь статические сайты также обрабатывают динамические данные с помощью API и запросов...