diff --git a/QXlsx/header/xlsxworksheet.h b/QXlsx/header/xlsxworksheet.h index ccf48564..17a1b8a2 100644 --- a/QXlsx/header/xlsxworksheet.h +++ b/QXlsx/header/xlsxworksheet.h @@ -185,6 +185,13 @@ class QXLSX_EXPORT Worksheet : public AbstractSheet bool isWhiteSpaceVisible() const; void setWhiteSpaceVisible(bool visible); bool setStartPage(int spagen); // add by liufeijin20181028 + CellReference selectionActiveCell() const; + void setSelectionActiveCell(CellReference activeCell); + quint32 selectionActiveCellId() const; + bool selectionActiveCellId(quint32 activeCellId); + QList selectionSqref() const; + void setSelectionSqref(const QList &selectionSqref); + void setSelectionSqref(QList &&selectionSqref); QVector getFullCells(int *maxRow, int *maxCol) const; diff --git a/QXlsx/header/xlsxworksheet_p.h b/QXlsx/header/xlsxworksheet_p.h index ee784da7..50bae28e 100644 --- a/QXlsx/header/xlsxworksheet_p.h +++ b/QXlsx/header/xlsxworksheet_p.h @@ -132,6 +132,14 @@ struct XlsxColumnInfo { bool collapsed; }; +// ECMA-376 Part1 18.3.1.78 +struct XlsxSheetViewSelectionProps { + CellReference activeCell; + quint32 activeCellId; + // TODO: Add pane while adding multiple-`sheetView` support + QList sqref; +}; + class CellTable { public: @@ -286,6 +294,8 @@ class WorksheetPrivate : public AbstractSheetPrivate QRegularExpression urlPattern; + XlsxSheetViewSelectionProps selectionProps; + private: static double calculateColWidth(int characters); }; diff --git a/QXlsx/source/xlsxworksheet.cpp b/QXlsx/source/xlsxworksheet.cpp index 3e66cd6f..9d29dc59 100644 --- a/QXlsx/source/xlsxworksheet.cpp +++ b/QXlsx/source/xlsxworksheet.cpp @@ -1324,6 +1324,27 @@ void Worksheet::saveToXmlFile(QIODevice *device) const if (!d->showWhiteSpace) writer.writeAttribute(QStringLiteral("showWhiteSpace"), QStringLiteral("0")); writer.writeAttribute(QStringLiteral("workbookViewId"), QStringLiteral("0")); + if (d->selectionProps.activeCell.isValid() || !d->selectionProps.sqref.isEmpty()) { + writer.writeStartElement(QStringLiteral("selection")); + if (d->selectionProps.activeCell.isValid()) { + writer.writeAttribute(QStringLiteral("activeCell"), + d->selectionProps.activeCell.toString()); + } + if (!d->selectionProps.sqref.isEmpty()) { + QString sqrefString; + for (const auto range : d->selectionProps.sqref) { + sqrefString.append(range.toString()); + sqrefString.push_back(QLatin1Char(' ')); + } + sqrefString.truncate(sqrefString.size() - 1); + writer.writeAttribute(QStringLiteral("sqref"), sqrefString); + if (d->selectionProps.sqref.size() > 1) { + writer.writeAttribute(QStringLiteral("activeCellId"), + QString::number(d->selectionProps.activeCellId)); + } + } + writer.writeEndElement(); // selection + } writer.writeEndElement(); // sheetView writer.writeEndElement(); // sheetViews @@ -1481,6 +1502,54 @@ bool Worksheet::setStartPage(int spagen) } //}} +CellReference Worksheet::selectionActiveCell() const +{ + Q_D(const Worksheet); + return d->selectionProps.activeCell; +} + +void Worksheet::setSelectionActiveCell(CellReference activeCell) +{ + Q_D(Worksheet); + d->selectionProps.activeCell = activeCell; +} + +quint32 Worksheet::selectionActiveCellId() const +{ + Q_D(const Worksheet); + return d->selectionProps.activeCellId; +} + +bool Worksheet::selectionActiveCellId(quint32 activeCellId) +{ + Q_D(Worksheet); + if (activeCellId < d->selectionProps.sqref.size()) { + d->selectionProps.activeCellId = activeCellId; + return true; + } + return false; +} + +QList Worksheet::selectionSqref() const +{ + Q_D(const Worksheet); + return d->selectionProps.sqref; +} + +void Worksheet::setSelectionSqref(const QList &selectionSqref) +{ + Q_D(Worksheet); + d->selectionProps.sqref = selectionSqref; + d->selectionProps.activeCellId = 0; +} + +void Worksheet::setSelectionSqref(QList &&selectionSqref) +{ + Q_D(Worksheet); + d->selectionProps.sqref = std::move(selectionSqref); + d->selectionProps.activeCellId = 0; +} + void WorksheetPrivate::saveXmlSheetData(QXmlStreamWriter &writer) const { calculateSpans(); @@ -2576,6 +2645,31 @@ void WorksheetPrivate::loadXmlSheetViews(QXmlStreamReader &reader) showOutlineSymbols = attrs.value(QLatin1String("showOutlineSymbols")) != QLatin1String("0"); showWhiteSpace = attrs.value(QLatin1String("showWhiteSpace")) != QLatin1String("0"); + reader.readNextStartElement(); + if (reader.tokenType() == QXmlStreamReader::StartElement && + reader.name() == QLatin1String("selection")) { + QXmlStreamAttributes selectionAttr = reader.attributes(); + selectionProps.activeCell = + CellReference(selectionAttr.value(QLatin1String("activeCell")).toString()); + selectionProps.activeCellId = + selectionAttr.value(QLatin1String("activeCellId")).toUInt(); + QStringView sqrefStr = selectionAttr.value(QLatin1String("sqref")); + QList ranges = sqrefStr.split(QLatin1Char(' ')); + for (const auto &range : ranges) { + selectionProps.sqref.append(CellRange(range.toString())); + } + if (selectionProps.activeCellId >= selectionProps.sqref.count()) { + for (auto it = selectionProps.sqref.begin(); it != selectionProps.sqref.end(); + ++it) { + const auto &range = *it; + if (!(range.topLeft() > selectionProps.activeCell) && + !(selectionProps.activeCell > range.bottomRight())) { + selectionProps.activeCellId = it - selectionProps.sqref.begin(); + break; + } + } + } + } } } }