Skip to content

Copy sheet of one workbook to another #444

@feschenko-nelya

Description

@feschenko-nelya

I need to copy a sheet from one document to another.

I've found two ways to do it:
1- write a similar method of Worksheet::copy,
2- upload and download xml data of worksheet: upload sheet from workbook A and download its xml-data to worksheet of workbook B.

1.

Method Worksheet::copy works almost fine inside one workbook, except rows and columns sizes (and maybe other properties, because I saw commented code there).
I take this method as a foundation for new method Worksheet::clone. It makes copy of current sheet with parent of another workbook.

I create a new worksheet with workbook B parent.
Copy all properties of workbook A sheet to it.

As a result all data was copied, but failed next:

  • rows sizes,
  • cell formats.

main.cpp

QXlsx::Document docA("docA.xlsx");
if (!docA.load())
{
        qFatal("File not loaded.");
        return EXIT_FAILURE;
}

QXlsx::Document docB;

auto sheetClone = docA.currentWorksheet()->clone(docB.workbook());
docB.addSheet(sheetClone);

docB.saveAs("docB.xlsx);

return EXIT_SUCCESS;

Worksheet.cpp

Worksheet *Worksheet::clone(Workbook *dstWb)
{
    Q_D(const Worksheet);

    auto newSheet                = new Worksheet(d_func()->name, 0, dstWb, F_LoadFromExists);
    WorksheetPrivate *dNewSheet = newSheet->d_func();

    dNewSheet->sheetFormatProps = d->sheetFormatProps;

    qInfo() << "cols info: " << dNewSheet->colsInfo.size() << d->colsInfo.size();
    qInfo() << "rows info: " << dNewSheet->rowsInfo.size() << d->rowsInfo.size();
    qInfo() << "rows sizes: " << dNewSheet->row_sizes.size() << d->row_sizes.size();

    dNewSheet->colsInfo = d->colsInfo;
    dNewSheet->colsInfoHelper = d->colsInfoHelper;
    dNewSheet->rowsInfo = d->rowsInfo;
    dNewSheet->row_spans = d->row_spans;
    dNewSheet->row_sizes = d->row_sizes;
    dNewSheet->col_sizes = d->col_sizes;
    dNewSheet->dimension = d->dimension;

    for (auto it = d->cellTable.cells.begin(); it != d->cellTable.cells.end(); ++it) {
        int row = it.key();
        // newSheet->setRowHeight(row, row, rowHeight(row));

        for (auto it2 = it.value().begin(); it2 != it.value().end(); ++it2) {
            int col = it2.key();

            auto srcCell = it2.value();
            auto srcCellFormat = srcCell->format();

            if (srcCell->hasFormula())
            {
                newSheet->writeFormula(row, col, srcCell->formula(), srcCellFormat);
            }
            else
            {
                switch (srcCell->cellType())
                {
                case Cell::BooleanType:
                    newSheet->writeBool(row, col, srcCell->value().toBool(), srcCellFormat);
                    break;
                case Cell::InlineStringType:
                    newSheet->writeInlineString(row, col, srcCell->value().toString(), srcCellFormat);
                    break;
                case Cell::StringType:
                case Cell::SharedStringType:
                    newSheet->writeString(row, col, srcCell->value().toString(), srcCellFormat);
                    break;
                case Cell::CustomType:
                    if (!srcCell->value().isValid() || srcCell->value().isNull())
                    {
                        newSheet->writeBlank(row, col, srcCellFormat);
                    }
                    else
                    {
                        newSheet->write(row, col, srcCell->value(), srcCellFormat);
                    }
                    break;
                default:
                    break;
                }
            }
        }
    }

dNewSheet->merges = d->merges;

return newSheet;
}

All data has copied correct. But cells formats, rows sizes missed.

Workbook A

Image

Workbook B

Image

And it looks like that it has random effect. Each time cells' format changes.

Workbook B

Image

And I have a message from Excel that sheet lost data when workbook is opened.

2.

The second way I've tried is to save sheet's data of workbook A to xml and load it in sheet of workbook B. It is the smallest and convenient way, but it doesnt work too.

    QXlsx::Document docA("docA.xlsx");
    if (!docA.load())
    {
        qFatal("File not loaded.");
        return EXIT_FAILURE;
    }

    QXlsx::Document docB;

    docB.addSheet();
    docB.currentWorksheet()->loadFromXmlData(docA.currentWorksheet()->saveToXmlData());

    docB.saveAs("docB.xlsx");

    return EXIT_SUCCESS;

What I'm doing wrong? Any advice?
Can you help to finish one of these ways, please?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions