Использование API LightCells с C++

Архитектура, основанная на событиях

Aspose.Cells предоставляет API LightCells, преимущественно предназначенный для манипулирования данными ячейки одна за другой без построения полной модели данных (используя коллекцию Cell и т. д.) в памяти. Он работает в режиме событийного управления.

Для сохранения рабочих книг предоставьте содержание ячейки по ячейке при сохранении, и компонент сохранит его непосредственно в выходной файл.

При считывании файлов-шаблонов компонент анализирует каждую ячейку и предоставляет их значение по одной.

В обоих процедурах обрабатывается один объект ячейки, а затем он удаляется, объект Workbook не хранит коллекцию. В этом режиме, следовательно, память экономится при импорте и экспорте файлов Microsoft Excel с большим набором данных, который иначе использовал бы много памяти.

Несмотря на то, что API LightCells обрабатывает ячейки одинаково для файлов XLSX и XLS (он на самом деле не загружает все ячейки в память, а обрабатывает одну ячейку, а затем удаляет ее), он более эффективно экономит память для файлов XLSX, чем для файлов XLS из-за разных моделей данных и структур двух форматов.

Однако для файлов XLS для экономии памяти разработчики могут указать временное местоположение для сохранения временных данных, генерируемых в процессе сохранения. Обычно использование API LightCells для сохранения файла XLSX может сэкономить 50% или более памяти по сравнению с обычным способом, сохранение XLS может сэкономить от 20 до 40% памяти.

Создание большого файла Excel

Aspose.Cells предоставляет интерфейс LightCellsDataProvider, который необходимо реализовать в вашей программе. Этот интерфейс представляет собой поставщика данных для сохранения больших файлов таблиц в легком режиме.

При сохранении рабочей книги в этом режиме проверяется StartSheet(int) при сохранении каждого листа рабочей книги. Для одного листа, если StartSheet(int) возвращает true, то все данные и свойства строк и ячеек этого листа предоставляются этой реализацией. В первую очередь вызывается NextRow(), чтобы получить следующий индекс строки для сохранения. Если возвращается действительный индекс строки (индекс строки должен быть в порядке возрастания для сохраняемых строк), то для реализации предоставляется объект Row, представляющий эту строку, для установки его свойств с помощью StartRow(Row).

Для одной строки сначала проверяется NextCell(). Если возвращается действующий индекс столбца (индекс столбца должен быть в порядке возрастания для всех ячеек одной строки), то для реализации предоставляется объект Cell, представляющий эту ячейку, для установки данных и свойств с помощью StartCell(Cell). После установки данных ячейки ячейка сохраняется напрямую в создаваемом файле таблицы, и далее проверяется и обрабатывается следующая ячейка.

Запись большого Excel-файла: пример

Пожалуйста, ознакомьтесь со следующим образцовым кодом, чтобы увидеть работу API LightCells. Добавьте, удалите или обновите сегменты кода в соответствии с вашими потребностями.

Программа создает огромный файл с 10 000 (матрица 10000x30) записей на листе и заполняет их тестовыми данными. Вы можете указать свою матрицу, изменяя переменные rowsCount и colsCount в методе Main().

#include <iostream>
#include "Aspose.Cells.h"
using namespace Aspose::Cells;

class TestDataProvider : public LightCellsDataProvider {
private:
    int _row = -1;
    int _column = -1;
    int maxRows;
    int maxColumns;
    Workbook _workbook;

public:
    TestDataProvider(Workbook workbook, int maxRows, int maxColumns)
        : _workbook(workbook), maxRows(maxRows), maxColumns(maxColumns) {}

    bool IsGatherString() override {
        return false;
    }

    int NextCell() override {
        ++_column;
        if (_column < this->maxColumns)
            return _column;
        else {
            _column = -1;
            return -1;
        }
    }

    int NextRow() override {
        ++_row;
        if (_row < this->maxRows) {
            _column = -1;
            return _row;
        }
        else
            return -1;
    }

    void StartCell(Cell& cell) override {
        cell.PutValue(_row + _column);
        if (_row != 1) {
            cell.SetFormula(u"=Rand() + A2");
        }
    }

    void StartRow(Row& row) override {}

    bool StartSheet(int sheetIndex) override {
        return sheetIndex == 0;
    }
};

void WriteUsingLightCellsAPI() {
    U16String srcDir(u"..\\Data\\01_SourceDirectory\\");
    U16String outDir(u"..\\Data\\02_OutputDirectory\\");
    int rowsCount = 10000;
    int colsCount = 30;

    Workbook workbook;
    OoxmlSaveOptions ooxmlSaveOptions;

    TestDataProvider dataProvider(workbook, rowsCount, colsCount);
    ooxmlSaveOptions.SetLightCellsDataProvider(&dataProvider);

    workbook.Save(outDir + u"output.out.xlsx", ooxmlSaveOptions);

    std::cout << "File saved successfully using LightCells API!" << std::endl;
}

int main() {
    Aspose::Cells::Startup();
    WriteUsingLightCellsAPI();
    Aspose::Cells::Cleanup();
    return 0;
}

Чтение больших файлов Excel

Aspose.Cells предоставляет интерфейс LightCellsDataHandler, который необходимо реализовать в вашей программе. Этот интерфейс представляет поставщика данных для чтения больших файлов таблиц в легком режиме.

При чтении рабочей книги в этом режиме проверяется StartSheet при чтении каждого листа. Для листа, если StartSheet возвращает true, все данные и свойства ячеек в строках и столбцах листа проверяются и обрабатываются этой реализацией. Для каждой строки вызывается StartRow для проверки необходимости обработки. Если строка должна быть обработана, её свойства сначала считываются, и разработчик может получить к ним доступ через ProcessRow. Если ячейки строки также нужно обработать, тогда ProcessRow возвращает true, и для каждой существующей ячейки строки вызывается StartCell, чтобы определить, нужно ли обрабатывать ячейку. Если обработка ячейки необходима, вызывается ProcessCell.

Чтение больших Excel-файлов: пример

Пожалуйста, ознакомьтесь со следующим образцовым кодом, чтобы увидеть работу API LightCells. Добавьте, удалите или обновите сегменты кода в соответствии с вашими потребностями.

Программа считывает огромный файл с миллионами записей в листе Excel. На чтение каждого листа в книге требуется небольшое время. Ознакомьтесь с образцовым кодом чтения файла и получения общего количества ячеек, количества строк и формул в каждом листе.

#include <iostream>
#include <memory>
#include "Aspose.Cells.h"

using namespace Aspose::Cells;

class LightCellsDataHandlerVisitCells : public LightCellsDataHandler
{
private:
    int cellCount;
    int formulaCount;
    int stringCount;

public:
    LightCellsDataHandlerVisitCells() : cellCount(0), formulaCount(0), stringCount(0) {}

    int GetCellCount() const { return cellCount; }
    int GetFormulaCount() const { return formulaCount; }
    int GetStringCount() const { return stringCount; }

    bool StartSheet(Worksheet& sheet) override
    {
        std::cout << "Processing sheet[" << sheet.GetName().ToUtf8() << "]" << std::endl;
        return true;
    }

    bool StartRow(int32_t rowIndex) override
    {
        return true;
    }

    bool ProcessRow(Row& row) override
    {
        return true;
    }

    bool StartCell(int32_t columnIndex) override
    {
        return true;
    }

    bool ProcessCell(Cell& cell) override
    {
        cellCount++;
        if (cell.IsFormula())
        {
            formulaCount++;
        }
        else if (cell.GetType() == CellValueType::IsString)
        {
            stringCount++;
        }
        return false;
    }
};

void Run()
{
    // Source directory path
    U16String srcDir(u"..\\Data\\01_SourceDirectory\\");

    // Create load options and set the light cells data handler
    LoadOptions opts;
    auto handler = std::make_shared<LightCellsDataHandlerVisitCells>();
    opts.SetLightCellsDataHandler(handler.get());

    // Load the workbook with the specified options
    Workbook wb(srcDir + u"LargeBook1.xlsx", opts);

    // Get the total number of sheets
    int sheetCount = wb.GetWorksheets().GetCount();

    // Output the results
    std::cout << "Total sheets: " << sheetCount << ", cells: " << handler->GetCellCount()
              << ", strings: " << handler->GetStringCount() << ", formulas: " << handler->GetFormulaCount() << std::endl;
}

int main()
{
    Aspose::Cells::Startup();
    Run();
    Aspose::Cells::Cleanup();
    return 0;
}