123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090 |
- // xlsxworksheet.cpp
- #include <QtGlobal>
- #include <QVariant>
- #include <QDateTime>
- #include <QDate>
- #include <QTime>
- #include <QPoint>
- #include <QFile>
- #include <QUrl>
- #include <QDebug>
- #include <QBuffer>
- #include <QXmlStreamWriter>
- #include <QXmlStreamReader>
- #include <QTextDocument>
- #include <QDir>
- #include <QMapIterator>
- #include <QMap>
- #include <cmath>
- #include "xlsxrichstring.h"
- #include "xlsxcellreference.h"
- #include "xlsxworksheet.h"
- #include "xlsxworksheet_p.h"
- #include "xlsxworkbook.h"
- #include "xlsxformat.h"
- #include "xlsxformat_p.h"
- #include "xlsxutility_p.h"
- #include "xlsxsharedstrings_p.h"
- #include "xlsxdrawing_p.h"
- #include "xlsxstyles_p.h"
- #include "xlsxcell.h"
- #include "xlsxcell_p.h"
- #include "xlsxcellrange.h"
- #include "xlsxconditionalformatting_p.h"
- #include "xlsxdrawinganchor_p.h"
- #include "xlsxchart.h"
- #include "xlsxcellformula.h"
- #include "xlsxcellformula_p.h"
- #include "xlsxcelllocation.h"
- QT_BEGIN_NAMESPACE_XLSX
- WorksheetPrivate::WorksheetPrivate(Worksheet *p, Worksheet::CreateFlag flag)
- : AbstractSheetPrivate(p, flag),
- windowProtection(false),
- showFormulas(false),
- showGridLines(true),
- showRowColHeaders(true),
- showZeros(true),
- rightToLeft(false),
- tabSelected(false),
- showRuler(false),
- showOutlineSymbols(true),
- showWhiteSpace(true),
- urlPattern(QStringLiteral("^([fh]tt?ps?://)|(mailto:)|(file://)"))
- {
- previous_row = 0;
- outline_row_level = 0;
- outline_col_level = 0;
- default_row_height = 15;
- default_row_zeroed = false;
- }
- WorksheetPrivate::~WorksheetPrivate()
- {
- }
- /*
- Calculate the "spans" attribute of the <row> tag. This is an
- XLSX optimisation and isn't strictly required. However, it
- makes comparing files easier. The span is the same for each
- block of 16 rows.
- */
- void WorksheetPrivate::calculateSpans() const
- {
- row_spans.clear();
- int span_min = XLSX_COLUMN_MAX+1;
- int span_max = -1;
- for (int row_num = dimension.firstRow(); row_num <= dimension.lastRow(); row_num++) {
- auto it = cellTable.constFind(row_num);
- if (it != cellTable.constEnd()) {
- for (int col_num = dimension.firstColumn(); col_num <= dimension.lastColumn(); col_num++) {
- if (it->contains(col_num)) {
- if (span_max == -1) {
- span_min = col_num;
- span_max = col_num;
- } else {
- if (col_num < span_min)
- span_min = col_num;
- else if (col_num > span_max)
- span_max = col_num;
- }
- }
- }
- }
- auto cIt = comments.constFind(row_num);
- if (cIt != comments.constEnd()) {
- for (int col_num = dimension.firstColumn(); col_num <= dimension.lastColumn(); col_num++) {
- if (cIt->contains(col_num)) {
- if (span_max == -1) {
- span_min = col_num;
- span_max = col_num;
- } else {
- if (col_num < span_min)
- span_min = col_num;
- else if (col_num > span_max)
- span_max = col_num;
- }
- }
- }
- }
- if (row_num%16 == 0 || row_num == dimension.lastRow()) {
- if (span_max != -1) {
- row_spans[row_num / 16] = QStringLiteral("%1:%2").arg(span_min).arg(span_max);
- span_min = XLSX_COLUMN_MAX+1;
- span_max = -1;
- }
- }
- }
- }
- QString WorksheetPrivate::generateDimensionString() const
- {
- if (!dimension.isValid())
- return QStringLiteral("A1");
- else
- return dimension.toString();
- }
- /*
- Check that row and col are valid and store the max and min
- values for use in other methods/elements. The ignore_row /
- ignore_col flags is used to indicate that we wish to perform
- the dimension check without storing the value. The ignore
- flags are use by setRow() and dataValidate.
- */
- int WorksheetPrivate::checkDimensions(int row, int col, bool ignore_row, bool ignore_col)
- {
- Q_ASSERT_X(row!=0, "checkDimensions", "row should start from 1 instead of 0");
- Q_ASSERT_X(col!=0, "checkDimensions", "column should start from 1 instead of 0");
- if (row > XLSX_ROW_MAX || row < 1 || col > XLSX_COLUMN_MAX || col < 1)
- return -1;
- if (!ignore_row) {
- if (row < dimension.firstRow() || dimension.firstRow() == -1) dimension.setFirstRow(row);
- if (row > dimension.lastRow()) dimension.setLastRow(row);
- }
- if (!ignore_col) {
- if (col < dimension.firstColumn() || dimension.firstColumn() == -1) dimension.setFirstColumn(col);
- if (col > dimension.lastColumn()) dimension.setLastColumn(col);
- }
- return 0;
- }
- /*!
- \class Worksheet
- \inmodule QtXlsx
- \brief Represent one worksheet in the workbook.
- */
- /*!
- * \internal
- */
- Worksheet::Worksheet(const QString &name, int id, Workbook *workbook, CreateFlag flag)
- :AbstractSheet(name, id, workbook, new WorksheetPrivate(this, flag))
- {
- if (!workbook) //For unit test propose only. Ignore the memery leak.
- d_func()->workbook = new Workbook(flag);
- }
- /*!
- * \internal
- *
- * Make a copy of this sheet.
- */
- Worksheet *Worksheet::copy(const QString &distName, int distId) const
- {
- Q_D(const Worksheet);
- Worksheet *sheet = new Worksheet(distName, distId, d->workbook, F_NewFromScratch);
- WorksheetPrivate *sheet_d = sheet->d_func();
- sheet_d->dimension = d->dimension;
- QMapIterator<int, QMap<int, QSharedPointer<Cell> > > it(d->cellTable);
- while (it.hasNext())
- {
- it.next();
- int row = it.key();
- QMapIterator<int, QSharedPointer<Cell> > it2(it.value());
- while (it2.hasNext())
- {
- it2.next();
- int col = it2.key();
- QSharedPointer<Cell> cell(new Cell(it2.value().data()));
- cell->d_ptr->parent = sheet;
- if (cell->cellType() == Cell::SharedStringType)
- d->workbook->sharedStrings()->addSharedString(cell->d_ptr->richString);
- sheet_d->cellTable[row][col] = cell;
- }
- }
- sheet_d->merges = d->merges;
- // sheet_d->rowsInfo = d->rowsInfo;
- // sheet_d->colsInfo = d->colsInfo;
- // sheet_d->colsInfoHelper = d->colsInfoHelper;
- // sheet_d->dataValidationsList = d->dataValidationsList;
- // sheet_d->conditionalFormattingList = d->conditionalFormattingList;
- return sheet;
- }
- /*!
- * Destroys this workssheet.
- */
- Worksheet::~Worksheet()
- {
- }
- /*!
- * Returns whether sheet is protected.
- */
- bool Worksheet::isWindowProtected() const
- {
- Q_D(const Worksheet);
- return d->windowProtection;
- }
- /*!
- * Protects/unprotects the sheet based on \a protect.
- */
- void Worksheet::setWindowProtected(bool protect)
- {
- Q_D(Worksheet);
- d->windowProtection = protect;
- }
- /*!
- * Return whether formulas instead of their calculated results shown in cells
- */
- bool Worksheet::isFormulasVisible() const
- {
- Q_D(const Worksheet);
- return d->showFormulas;
- }
- /*!
- * Show formulas in cells instead of their calculated results when \a visible is true.
- */
- void Worksheet::setFormulasVisible(bool visible)
- {
- Q_D(Worksheet);
- d->showFormulas = visible;
- }
- /*!
- * Return whether gridlines is shown or not.
- */
- bool Worksheet::isGridLinesVisible() const
- {
- Q_D(const Worksheet);
- return d->showGridLines;
- }
- /*!
- * Show or hide the gridline based on \a visible
- */
- void Worksheet::setGridLinesVisible(bool visible)
- {
- Q_D(Worksheet);
- d->showGridLines = visible;
- }
- /*!
- * Return whether is row and column headers is vislbe.
- */
- bool Worksheet::isRowColumnHeadersVisible() const
- {
- Q_D(const Worksheet);
- return d->showRowColHeaders;
- }
- /*!
- * Show or hide the row column headers based on \a visible
- */
- void Worksheet::setRowColumnHeadersVisible(bool visible)
- {
- Q_D(Worksheet);
- d->showRowColHeaders = visible;
- }
- /*!
- * Return whether the sheet is shown right-to-left or not.
- */
- bool Worksheet::isRightToLeft() const
- {
- Q_D(const Worksheet);
- return d->rightToLeft;
- }
- /*!
- * Enable or disable the right-to-left based on \a enable.
- */
- void Worksheet::setRightToLeft(bool enable)
- {
- Q_D(Worksheet);
- d->rightToLeft = enable;
- }
- /*!
- * Return whether is cells that have zero value show a zero.
- */
- bool Worksheet::isZerosVisible() const
- {
- Q_D(const Worksheet);
- return d->showZeros;
- }
- /*!
- * Show a zero in cells that have zero value if \a visible is true.
- */
- void Worksheet::setZerosVisible(bool visible)
- {
- Q_D(Worksheet);
- d->showZeros = visible;
- }
- /*!
- * Return whether this tab is selected.
- */
- bool Worksheet::isSelected() const
- {
- Q_D(const Worksheet);
- return d->tabSelected;
- }
- /*!
- * Select this sheet if \a select is true.
- */
- void Worksheet::setSelected(bool select)
- {
- Q_D(Worksheet);
- d->tabSelected = select;
- }
- /*!
- * Return whether is ruler is shown.
- */
- bool Worksheet::isRulerVisible() const
- {
- Q_D(const Worksheet);
- return d->showRuler;
- }
- /*!
- * Show or hide the ruler based on \a visible.
- */
- void Worksheet::setRulerVisible(bool visible)
- {
- Q_D(Worksheet);
- d->showRuler = visible;
- }
- /*!
- * Return whether is outline symbols is shown.
- */
- bool Worksheet::isOutlineSymbolsVisible() const
- {
- Q_D(const Worksheet);
- return d->showOutlineSymbols;
- }
- /*!
- * Show or hide the outline symbols based ib \a visible.
- */
- void Worksheet::setOutlineSymbolsVisible(bool visible)
- {
- Q_D(Worksheet);
- d->showOutlineSymbols = visible;
- }
- /*!
- * Return whether is white space is shown.
- */
- bool Worksheet::isWhiteSpaceVisible() const
- {
- Q_D(const Worksheet);
- return d->showWhiteSpace;
- }
- /*!
- * Show or hide the white space based on \a visible.
- */
- void Worksheet::setWhiteSpaceVisible(bool visible)
- {
- Q_D(Worksheet);
- d->showWhiteSpace = visible;
- }
- /*!
- * Write \a value to cell (\a row, \a column) with the \a format.
- * Both \a row and \a column are all 1-indexed value.
- *
- * Returns true on success.
- */
- bool Worksheet::write(int row, int column, const QVariant &value, const Format &format)
- {
- Q_D(Worksheet);
- if (d->checkDimensions(row, column))
- return false;
- bool ret = true;
- if (value.isNull())
- {
- //Blank
- ret = writeBlank(row, column, format);
- }
- else if (value.userType() == QMetaType::QString)
- {
- //String
- QString token = value.toString();
- bool ok;
- if (token.startsWith(QLatin1String("=")))
- {
- //convert to formula
- ret = writeFormula(row, column, CellFormula(token), format);
- }
- else if (d->workbook->isStringsToHyperlinksEnabled() && token.contains(d->urlPattern))
- {
- //convert to url
- ret = writeHyperlink(row, column, QUrl(token));
- }
- else if (d->workbook->isStringsToNumbersEnabled() && (value.toDouble(&ok), ok))
- {
- //Try convert string to number if the flag enabled.
- ret = writeString(row, column, value.toString(), format);
- }
- else
- {
- //normal string now
- ret = writeString(row, column, token, format);
- }
- }
- else if (value.userType() == qMetaTypeId<RichString>())
- {
- ret = writeString(row, column, value.value<RichString>(), format);
- }
- else if (value.userType() == QMetaType::Int || value.userType() == QMetaType::UInt
- || value.userType() == QMetaType::LongLong || value.userType() == QMetaType::ULongLong
- || value.userType() == QMetaType::Double || value.userType() == QMetaType::Float)
- {
- //Number
- ret = writeNumeric(row, column, value.toDouble(), format);
- }
- else if (value.userType() == QMetaType::Bool)
- {
- //Bool
- ret = writeBool(row,column, value.toBool(), format);
- }
- else if (value.userType() == QMetaType::QDateTime ) // dev67
- {
- //DateTime, Date
- // note that, QTime cann't convert to QDateTime
- ret = writeDateTime(row, column, value.toDateTime(), format);
- }
- else if ( value.userType() == QMetaType::QDate ) // dev67
- {
- ret = writeDate(row, column, value.toDate(), format);
- }
- else if (value.userType() == QMetaType::QTime)
- {
- //Time
- ret = writeTime(row, column, value.toTime(), format);
- }
- else if (value.userType() == QMetaType::QUrl)
- {
- //Url
- ret = writeHyperlink(row, column, value.toUrl(), format);
- }
- else
- {
- //Wrong type
- return false;
- }
- return ret;
- }
- /*!
- * \overload
- * Write \a value to cell \a row_column with the \a format.
- * Both row and column are all 1-indexed value.
- * Returns true on success.
- */
- bool Worksheet::write(const CellReference &row_column, const QVariant &value, const Format &format)
- {
- if (!row_column.isValid())
- return false;
- return write(row_column.row(), row_column.column(), value, format);
- }
- /*!
- \overload
- Return the contents of the cell \a row_column.
- */
- QVariant Worksheet::read(const CellReference &row_column) const
- {
- if (!row_column.isValid())
- return QVariant();
- return read(row_column.row(), row_column.column());
- }
- /*!
- Return the contents of the cell (\a row, \a column).
- */
- QVariant Worksheet::read(int row, int column) const
- {
- Q_D(const Worksheet);
- Cell *cell = cellAt(row, column);
- if (!cell)
- return QVariant();
- if (cell->hasFormula())
- {
- if (cell->formula().formulaType() == CellFormula::NormalType)
- {
- return QVariant(QLatin1String("=")+cell->formula().formulaText());
- }
- else if (cell->formula().formulaType() == CellFormula::SharedType)
- {
- if (!cell->formula().formulaText().isEmpty())
- {
- return QVariant(QLatin1String("=")+cell->formula().formulaText());
- }
- else
- {
- int si = cell->formula().sharedIndex();
- const CellFormula &rootFormula = d->sharedFormulaMap[ si ];
- CellReference rootCellRef = rootFormula.reference().topLeft();
- QString rootFormulaText = rootFormula.formulaText();
- QString newFormulaText = convertSharedFormula(rootFormulaText, rootCellRef, CellReference(row, column));
- return QVariant(QLatin1String("=")+newFormulaText);
- }
- }
- }
- if (cell->isDateTime())
- {
- QVariant vDateTime = cell->dateTime();
- return vDateTime;
- }
- return cell->value();
- }
- /*!
- * Returns the cell at the given \a row_column. If there
- * is no cell at the specified position, the function returns 0.
- */
- Cell *Worksheet::cellAt(const CellReference &row_column) const
- {
- if (!row_column.isValid())
- return 0;
- return cellAt(row_column.row(), row_column.column());
- }
- /*!
- * Returns the cell at the given \a row and \a column. If there
- * is no cell at the specified position, the function returns 0.
- */
- Cell *Worksheet::cellAt(int row, int col) const
- {
- Q_D(const Worksheet);
- auto it = d->cellTable.constFind(row);
- if (it == d->cellTable.constEnd())
- return 0;
- if (!it->contains(col))
- return 0;
- return (*it)[col].data();
- }
- Format WorksheetPrivate::cellFormat(int row, int col) const
- {
- auto it = cellTable.constFind(row);
- if (it == cellTable.constEnd())
- return Format();
- if (!it->contains(col))
- return Format();
- return (*it)[col]->format();
- }
- /*!
- \overload
- Write string \a value to the cell \a row_column with the \a format.
- Returns true on success.
- */
- bool Worksheet::writeString(const CellReference &row_column, const RichString &value, const Format &format)
- {
- if (!row_column.isValid())
- return false;
- return writeString(row_column.row(), row_column.column(), value, format);
- }
- /*!
- Write string \a value to the cell (\a row, \a column) with the \a format.
- Returns true on success.
- */
- bool Worksheet::writeString(int row, int column, const RichString &value, const Format &format)
- {
- Q_D(Worksheet);
- // QString content = value.toPlainString();
- if (d->checkDimensions(row, column))
- return false;
- // if (content.size() > d->xls_strmax) {
- // content = content.left(d->xls_strmax);
- // error = -2;
- // }
- d->sharedStrings()->addSharedString(value);
- Format fmt = format.isValid() ? format : d->cellFormat(row, column);
- if (value.fragmentCount() == 1 && value.fragmentFormat(0).isValid())
- fmt.mergeFormat(value.fragmentFormat(0));
- d->workbook->styles()->addXfFormat(fmt);
- QSharedPointer<Cell> cell = QSharedPointer<Cell>(new Cell(value.toPlainString(), Cell::SharedStringType, fmt, this));
- cell->d_ptr->richString = value;
- d->cellTable[row][column] = cell;
- return true;
- }
- /*!
- \overload
- Write string \a value to the cell \a row_column with the \a format.
- */
- bool Worksheet::writeString(const CellReference &row_column, const QString &value, const Format &format)
- {
- if (!row_column.isValid())
- return false;
- return writeString(row_column.row(), row_column.column(), value, format);
- }
- /*!
- \overload
- Write string \a value to the cell (\a row, \a column) with the \a format.
- Returns true on success.
- */
- bool Worksheet::writeString(int row, int column, const QString &value, const Format &format)
- {
- Q_D(Worksheet);
- if (d->checkDimensions(row, column))
- return false;
- RichString rs;
- if (d->workbook->isHtmlToRichStringEnabled() && Qt::mightBeRichText(value))
- rs.setHtml(value);
- else
- rs.addFragment(value, Format());
- return writeString(row, column, rs, format);
- }
- /*!
- \overload
- Write string \a value to the cell \a row_column with the \a format
- */
- bool Worksheet::writeInlineString(const CellReference &row_column, const QString &value, const Format &format)
- {
- if (!row_column.isValid())
- return false;
- return writeInlineString(row_column.row(), row_column.column(), value, format);
- }
- /*!
- Write string \a value to the cell (\a row, \a column) with the \a format.
- Returns true on success.
- */
- bool Worksheet::writeInlineString(int row, int column, const QString &value, const Format &format)
- {
- Q_D(Worksheet);
- //int error = 0;
- QString content = value;
- if (d->checkDimensions(row, column))
- return false;
- if (value.size() > XLSX_STRING_MAX) {
- content = value.left(XLSX_STRING_MAX);
- //error = -2;
- }
- Format fmt = format.isValid() ? format : d->cellFormat(row, column);
- d->workbook->styles()->addXfFormat(fmt);
- d->cellTable[row][column] = QSharedPointer<Cell>(new Cell(value, Cell::InlineStringType, fmt, this));
- return true;
- }
- /*!
- \overload
- Write numeric \a value to the cell \a row_column with the \a format.
- Returns true on success.
- */
- bool Worksheet::writeNumeric(const CellReference &row_column, double value, const Format &format)
- {
- if (!row_column.isValid())
- return false;
- return writeNumeric(row_column.row(), row_column.column(), value, format);
- }
- /*!
- Write numeric \a value to the cell (\a row, \a column) with the \a format.
- Returns true on success.
- */
- bool Worksheet::writeNumeric(int row, int column, double value, const Format &format)
- {
- Q_D(Worksheet);
- if (d->checkDimensions(row, column))
- return false;
- Format fmt = format.isValid() ? format : d->cellFormat(row, column);
- d->workbook->styles()->addXfFormat(fmt);
- d->cellTable[row][column] = QSharedPointer<Cell>(new Cell(value, Cell::NumberType, fmt, this));
- return true;
- }
- /*!
- \overload
- Write \a formula to the cell \a row_column with the \a format and \a result.
- Returns true on success.
- */
- bool Worksheet::writeFormula(const CellReference &row_column, const CellFormula &formula, const Format &format, double result)
- {
- if (!row_column.isValid())
- return false;
- return writeFormula(row_column.row(), row_column.column(), formula, format, result);
- }
- /*!
- Write \a formula_ to the cell (\a row, \a column) with the \a format and \a result.
- Returns true on success.
- */
- bool Worksheet::writeFormula(int row, int column, const CellFormula &formula_, const Format &format, double result)
- {
- Q_D(Worksheet);
- if (d->checkDimensions(row, column))
- return false;
- Format fmt = format.isValid() ? format : d->cellFormat(row, column);
- d->workbook->styles()->addXfFormat(fmt);
- CellFormula formula = formula_;
- formula.d->ca = true;
- if (formula.formulaType() == CellFormula::SharedType)
- {
- //Assign proper shared index for shared formula
- int si = 0;
- while ( d->sharedFormulaMap.contains(si) )
- {
- ++si;
- }
- formula.d->si = si;
- d->sharedFormulaMap[si] = formula;
- }
- QSharedPointer<Cell> data = QSharedPointer<Cell>(new Cell(result, Cell::NumberType, fmt, this));
- data->d_ptr->formula = formula;
- d->cellTable[row][column] = data;
- CellRange range = formula.reference();
- if (formula.formulaType() == CellFormula::SharedType) {
- CellFormula sf(QString(), CellFormula::SharedType);
- sf.d->si = formula.sharedIndex();
- for (int r=range.firstRow(); r<=range.lastRow(); ++r) {
- for (int c=range.firstColumn(); c<=range.lastColumn(); ++c) {
- if (!(r==row && c==column)) {
- if(Cell *cell = cellAt(r, c)) {
- cell->d_ptr->formula = sf;
- } else {
- QSharedPointer<Cell> newCell = QSharedPointer<Cell>(new Cell(result, Cell::NumberType, fmt, this));
- newCell->d_ptr->formula = sf;
- d->cellTable[r][c] = newCell;
- }
- }
- }
- }
- } else if (formula.formulaType() == CellFormula::SharedType) {
- }
- return true;
- }
- /*!
- \overload
- Write a empty cell \a row_column with the \a format.
- Returns true on success.
- */
- bool Worksheet::writeBlank(const CellReference &row_column, const Format &format)
- {
- if (!row_column.isValid())
- return false;
- return writeBlank(row_column.row(), row_column.column(), format);
- }
- /*!
- Write a empty cell (\a row, \a column) with the \a format.
- Returns true on success.
- */
- bool Worksheet::writeBlank(int row, int column, const Format &format)
- {
- Q_D(Worksheet);
- if (d->checkDimensions(row, column))
- return false;
- Format fmt = format.isValid() ? format : d->cellFormat(row, column);
- d->workbook->styles()->addXfFormat(fmt);
- //Note: NumberType with an invalid QVariant value means blank.
- d->cellTable[row][column] = QSharedPointer<Cell>(new Cell(QVariant(), Cell::NumberType, fmt, this));
- return true;
- }
- /*!
- \overload
- Write a bool \a value to the cell \a row_column with the \a format.
- Returns true on success.
- */
- bool Worksheet::writeBool(const CellReference &row_column, bool value, const Format &format)
- {
- if (!row_column.isValid())
- return false;
- return writeBool(row_column.row(), row_column.column(), value, format);
- }
- /*!
- Write a bool \a value to the cell (\a row, \a column) with the \a format.
- Returns true on success.
- */
- bool Worksheet::writeBool(int row, int column, bool value, const Format &format)
- {
- Q_D(Worksheet);
- if (d->checkDimensions(row, column))
- return false;
- Format fmt = format.isValid() ? format : d->cellFormat(row, column);
- d->workbook->styles()->addXfFormat(fmt);
- d->cellTable[row][column] = QSharedPointer<Cell>(new Cell(value, Cell::BooleanType, fmt, this));
- return true;
- }
- /*!
- \overload
- Write a QDateTime \a dt to the cell \a row_column with the \a format.
- Returns true on success.
- */
- bool Worksheet::writeDateTime(const CellReference &row_column, const QDateTime &dt, const Format &format)
- {
- if (!row_column.isValid())
- return false;
- return writeDateTime(row_column.row(), row_column.column(), dt, format);
- }
- /*!
- Write a QDateTime \a dt to the cell (\a row, \a column) with the \a format.
- Returns true on success.
- */
- bool Worksheet::writeDateTime(int row, int column, const QDateTime &dt, const Format &format)
- {
- Q_D(Worksheet);
- if (d->checkDimensions(row, column))
- return false;
- Format fmt = format.isValid() ? format : d->cellFormat(row, column);
- if (!fmt.isValid() || !fmt.isDateTimeFormat())
- fmt.setNumberFormat(d->workbook->defaultDateFormat());
- d->workbook->styles()->addXfFormat(fmt);
- double value = datetimeToNumber(dt, d->workbook->isDate1904());
- d->cellTable[row][column] = QSharedPointer<Cell>(new Cell(value, Cell::NumberType, fmt, this));
- return true;
- }
- // dev67
- bool Worksheet::writeDate(const CellReference &row_column, const QDate &dt, const Format &format)
- {
- if (!row_column.isValid())
- return false;
- return writeDate(row_column.row(), row_column.column(), dt, format);
- }
- // dev67
- bool Worksheet::writeDate(int row, int column, const QDate &dt, const Format &format)
- {
- Q_D(Worksheet);
- if (d->checkDimensions(row, column))
- return false;
- Format fmt = format.isValid() ? format : d->cellFormat(row, column);
- if (!fmt.isValid() || !fmt.isDateTimeFormat())
- fmt.setNumberFormat(d->workbook->defaultDateFormat());
- d->workbook->styles()->addXfFormat(fmt);
- double value = datetimeToNumber(QDateTime(dt, QTime(0,0,0)), d->workbook->isDate1904());
- d->cellTable[row][column] = QSharedPointer<Cell>(new Cell(value, Cell::NumberType, fmt, this));
- return true;
- }
- /*!
- \overload
- Write a QTime \a t to the cell \a row_column with the \a format.
- Returns true on success.
- */
- bool Worksheet::writeTime(const CellReference &row_column, const QTime &t, const Format &format)
- {
- if (!row_column.isValid())
- return false;
- return writeTime(row_column.row(), row_column.column(), t, format);
- }
- /*!
- Write a QTime \a t to the cell (\a row, \a column) with the \a format.
- Returns true on success.
- */
- bool Worksheet::writeTime(int row, int column, const QTime &t, const Format &format)
- {
- Q_D(Worksheet);
- if (d->checkDimensions(row, column))
- return false;
- Format fmt = format.isValid() ? format : d->cellFormat(row, column);
- if (!fmt.isValid() || !fmt.isDateTimeFormat())
- fmt.setNumberFormat(QStringLiteral("hh:mm:ss"));
- d->workbook->styles()->addXfFormat(fmt);
- d->cellTable[row][column] = QSharedPointer<Cell>(new Cell(timeToNumber(t), Cell::NumberType, fmt, this));
- return true;
- }
- /*!
- \overload
- Write a QUrl \a url to the cell \a row_column with the given \a format \a display and \a tip.
- Returns true on success.
- */
- bool Worksheet::writeHyperlink(const CellReference &row_column, const QUrl &url, const Format &format, const QString &display, const QString &tip)
- {
- if (!row_column.isValid())
- return false;
- return writeHyperlink(row_column.row(), row_column.column(), url, format, display, tip);
- }
- /*!
- Write a QUrl \a url to the cell (\a row, \a column) with the given \a format \a display and \a tip.
- Returns true on success.
- */
- bool Worksheet::writeHyperlink(int row, int column, const QUrl &url, const Format &format, const QString &display, const QString &tip)
- {
- Q_D(Worksheet);
- if (d->checkDimensions(row, column))
- return false;
- //int error = 0;
- QString urlString = url.toString();
- //Generate proper display string
- QString displayString = display.isEmpty() ? urlString : display;
- if (displayString.startsWith(QLatin1String("mailto:")))
- displayString.replace(QLatin1String("mailto:"), QString());
- if (displayString.size() > XLSX_STRING_MAX) {
- displayString = displayString.left(XLSX_STRING_MAX);
- //error = -2;
- }
- /*
- Location within target. If target is a workbook (or this workbook)
- this shall refer to a sheet and cell or a defined name. Can also
- be an HTML anchor if target is HTML file.
- c:\temp\file.xlsx#Sheet!A1
- http://a.com/aaa.html#aaaaa
- */
- QString locationString;
- if (url.hasFragment()) {
- locationString = url.fragment();
- urlString = url.toString(QUrl::RemoveFragment);
- }
- Format fmt = format.isValid() ? format : d->cellFormat(row, column);
- //Given a default style for hyperlink
- if (!fmt.isValid()) {
- fmt.setVerticalAlignment(Format::AlignVCenter);
- fmt.setFontColor(Qt::blue);
- fmt.setFontUnderline(Format::FontUnderlineSingle);
- }
- d->workbook->styles()->addXfFormat(fmt);
- //Write the hyperlink string as normal string.
- d->sharedStrings()->addSharedString(displayString);
- d->cellTable[row][column] = QSharedPointer<Cell>(new Cell(displayString, Cell::SharedStringType, fmt, this));
- //Store the hyperlink data in a separate table
- d->urlTable[row][column] = QSharedPointer<XlsxHyperlinkData>(new XlsxHyperlinkData(XlsxHyperlinkData::External, urlString, locationString, QString(), tip));
- return true;
- }
- /*!
- * Add one DataValidation \a validation to the sheet.
- * Returns true on success.
- */
- bool Worksheet::addDataValidation(const DataValidation &validation)
- {
- Q_D(Worksheet);
- if (validation.ranges().isEmpty() || validation.validationType()==DataValidation::None)
- return false;
- d->dataValidationsList.append(validation);
- return true;
- }
- /*!
- * Add one ConditionalFormatting \a cf to the sheet.
- * Returns true on success.
- */
- bool Worksheet::addConditionalFormatting(const ConditionalFormatting &cf)
- {
- Q_D(Worksheet);
- if (cf.ranges().isEmpty())
- return false;
- for (int i=0; i<cf.d->cfRules.size(); ++i) {
- const QSharedPointer<XlsxCfRuleData> &rule = cf.d->cfRules[i];
- if (!rule->dxfFormat.isEmpty())
- d->workbook->styles()->addDxfFormat(rule->dxfFormat);
- rule->priority = 1;
- }
- d->conditionalFormattingList.append(cf);
- return true;
- }
- /*!
- * Insert an \a image at the position \a row, \a column
- * Returns true on success.
- */
- int Worksheet::insertImage(int row, int column, const QImage &image)
- {
- Q_D(Worksheet);
- int imageIndex = 0;
- if (image.isNull())
- return imageIndex;
- if (!d->drawing)
- {
- d->drawing = QSharedPointer<Drawing>(new Drawing(this, F_NewFromScratch));
- }
- DrawingOneCellAnchor* anchor = new DrawingOneCellAnchor(d->drawing.data(), DrawingAnchor::Picture);
- /*
- The size are expressed as English Metric Units (EMUs).
- EMU is 1/360 000 of centimiter.
- */
- anchor->from = XlsxMarker(row, column, 0, 0);
- float scaleX = 36e6f / std::max(1,image.dotsPerMeterX());
- float scaleY = 36e6f / std::max(1,image.dotsPerMeterY());
- anchor->ext = QSize( int(image.width() * scaleX), int(image.height() * scaleY) );
- anchor->setObjectPicture(image);
- imageIndex = anchor->getm_id();
- return imageIndex;
- }
- bool Worksheet::getImage(int imageIndex, QImage& img)
- {
- Q_D(Worksheet);
- if( imageIndex <= (-1) )
- {
- return false;
- }
- if ( d->drawing == nullptr )
- {
- return false;
- }
- int realImageIndex = imageIndex - 1; // minus one
- DrawingAnchor* danchor = d->drawing->anchors.at( realImageIndex );
- // QSharedPointer<Drawing> // for multithread
- if ( danchor == nullptr )
- {
- return false;
- }
- bool ret= danchor->getObjectPicture(img);
- return ret;
- }
- bool Worksheet::getImage(int row, int column, QImage &img)
- {
- Q_D(Worksheet);
- if ( d->drawing == nullptr )
- {
- return false;
- }
- for(int i = 0; i < d->drawing->anchors.size(); i++)
- {
- if(d->drawing->anchors[i]->row() == row && d->drawing->anchors[i]->col() == column)
- {
- DrawingAnchor* danchor = d->drawing->anchors.at( i );
- if ( danchor == nullptr )
- {
- return false;
- }
- bool ret= danchor->getObjectPicture(img);
- return ret;
- }
- }
- return false;
- }
- uint Worksheet::getImageCount()
- {
- Q_D(Worksheet);
- if ( d->drawing == nullptr )
- {
- return false;
- }
- int size = d->drawing->anchors.size();
- return uint(size);
- }
- /*!
- * Creates an chart with the given \a size and insert
- * at the position \a row, \a column.
- * The chart will be returned.
- */
- Chart *Worksheet::insertChart(int row, int column, const QSize &size)
- {
- Q_D(Worksheet);
- if (!d->drawing)
- d->drawing = QSharedPointer<Drawing>(new Drawing(this, F_NewFromScratch));
- DrawingOneCellAnchor *anchor = new DrawingOneCellAnchor(d->drawing.data(), DrawingAnchor::Picture);
- /*
- The size are expressed as English Metric Units (EMUs). There are
- 12,700 EMUs per point. Therefore, 12,700 * 3 /4 = 9,525 EMUs per
- pixel
- */
- anchor->from = XlsxMarker(row, column, 0, 0);
- anchor->ext = size * 9525;
- QSharedPointer<Chart> chart = QSharedPointer<Chart>(new Chart(this, F_NewFromScratch));
- anchor->setObjectGraphicFrame(chart);
- return chart.data();
- }
- /*!
- Merge a \a range of cells. The first cell should contain the data and the others should
- be blank. All cells will be applied the same style if a valid \a format is given.
- Returns true on success.
- \note All cells except the top-left one will be cleared.
- */
- bool Worksheet::mergeCells(const CellRange &range, const Format &format)
- {
- Q_D(Worksheet);
- if (range.rowCount() < 2 && range.columnCount() < 2)
- return false;
- if (d->checkDimensions(range.firstRow(), range.firstColumn()))
- return false;
- if (format.isValid())
- {
- d->workbook->styles()->addXfFormat(format);
- }
- for (int row = range.firstRow(); row <= range.lastRow(); ++row)
- {
- for (int col = range.firstColumn(); col <= range.lastColumn(); ++col)
- {
- if (row == range.firstRow() && col == range.firstColumn())
- {
- Cell *cell = cellAt(row, col);
- if (cell)
- {
- if (format.isValid())
- cell->d_ptr->format = format;
- }
- else
- {
- writeBlank(row, col, format);
- }
- }
- else
- {
- writeBlank(row, col, format);
- }
- }
- }
- d->merges.append(range);
- return true;
- }
- /*!
- Unmerge the cells in the \a range. Returns true on success.
- */
- bool Worksheet::unmergeCells(const CellRange &range)
- {
- Q_D(Worksheet);
- return d->merges.removeOne(range);
- }
- /*!
- Returns all the merged cells.
- */
- QList<CellRange> Worksheet::mergedCells() const
- {
- Q_D(const Worksheet);
- // dev57
- QList<CellRange> emptyList;
- if ( d->type == AbstractSheet::ST_WorkSheet )
- {
- return d->merges;
- }
- else if ( d->type == AbstractSheet::ST_ChartSheet )
- {
- }
- else if ( d->type == AbstractSheet::ST_DialogSheet )
- {
- }
- else if ( d->type == AbstractSheet::ST_MacroSheet )
- {
- }
- else
- { // undefined
- }
- return emptyList;
- }
- /*!
- * \internal
- */
- void Worksheet::saveToXmlFile(QIODevice *device) const
- {
- Q_D(const Worksheet);
- d->relationships->clear();
- QXmlStreamWriter writer(device);
- writer.writeStartDocument(QStringLiteral("1.0"), true);
- writer.writeStartElement(QStringLiteral("worksheet"));
- writer.writeAttribute(QStringLiteral("xmlns"), QStringLiteral("http://schemas.openxmlformats.org/spreadsheetml/2006/main"));
- writer.writeAttribute(QStringLiteral("xmlns:r"), QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/relationships"));
- //for Excel 2010
- // writer.writeAttribute("xmlns:mc", "http://schemas.openxmlformats.org/markup-compatibility/2006");
- // writer.writeAttribute("xmlns:x14ac", "http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac");
- // writer.writeAttribute("mc:Ignorable", "x14ac");
- writer.writeStartElement(QStringLiteral("dimension"));
- writer.writeAttribute(QStringLiteral("ref"), d->generateDimensionString());
- writer.writeEndElement();//dimension
- writer.writeStartElement(QStringLiteral("sheetViews"));
- writer.writeStartElement(QStringLiteral("sheetView"));
- if (d->windowProtection)
- writer.writeAttribute(QStringLiteral("windowProtection"), QStringLiteral("1"));
- if (d->showFormulas)
- writer.writeAttribute(QStringLiteral("showFormulas"), QStringLiteral("1"));
- if (!d->showGridLines)
- writer.writeAttribute(QStringLiteral("showGridLines"), QStringLiteral("0"));
- if (!d->showRowColHeaders)
- writer.writeAttribute(QStringLiteral("showRowColHeaders"), QStringLiteral("0"));
- if (!d->showZeros)
- writer.writeAttribute(QStringLiteral("showZeros"), QStringLiteral("0"));
- if (d->rightToLeft)
- writer.writeAttribute(QStringLiteral("rightToLeft"), QStringLiteral("1"));
- if (d->tabSelected)
- writer.writeAttribute(QStringLiteral("tabSelected"), QStringLiteral("1"));
- if (!d->showRuler)
- writer.writeAttribute(QStringLiteral("showRuler"), QStringLiteral("0"));
- if (!d->showOutlineSymbols)
- writer.writeAttribute(QStringLiteral("showOutlineSymbols"), QStringLiteral("0"));
- if (!d->showWhiteSpace)
- writer.writeAttribute(QStringLiteral("showWhiteSpace"), QStringLiteral("0"));
- writer.writeAttribute(QStringLiteral("workbookViewId"), QStringLiteral("0"));
- writer.writeEndElement();//sheetView
- writer.writeEndElement();//sheetViews
- writer.writeStartElement(QStringLiteral("sheetFormatPr"));
- writer.writeAttribute(QStringLiteral("defaultRowHeight"), QString::number(d->default_row_height));
- if (d->default_row_height != 15)
- writer.writeAttribute(QStringLiteral("customHeight"), QStringLiteral("1"));
- if (d->default_row_zeroed)
- writer.writeAttribute(QStringLiteral("zeroHeight"), QStringLiteral("1"));
- if (d->outline_row_level)
- writer.writeAttribute(QStringLiteral("outlineLevelRow"), QString::number(d->outline_row_level));
- if (d->outline_col_level)
- writer.writeAttribute(QStringLiteral("outlineLevelCol"), QString::number(d->outline_col_level));
- //for Excel 2010
- // writer.writeAttribute("x14ac:dyDescent", "0.25");
- writer.writeEndElement();//sheetFormatPr
- if (!d->colsInfo.isEmpty())
- {
- writer.writeStartElement(QStringLiteral("cols"));
- QMapIterator<int, QSharedPointer<XlsxColumnInfo> > it(d->colsInfo);
- while (it.hasNext())
- {
- it.next();
- QSharedPointer<XlsxColumnInfo> col_info = it.value();
- writer.writeStartElement(QStringLiteral("col"));
- writer.writeAttribute(QStringLiteral("min"), QString::number(col_info->firstColumn));
- writer.writeAttribute(QStringLiteral("max"), QString::number(col_info->lastColumn));
- if (col_info->width)
- writer.writeAttribute(QStringLiteral("width"), QString::number(col_info->width, 'g', 15));
- if (!col_info->format.isEmpty())
- writer.writeAttribute(QStringLiteral("style"), QString::number(col_info->format.xfIndex()));
- if (col_info->hidden)
- writer.writeAttribute(QStringLiteral("hidden"), QStringLiteral("1"));
- if (col_info->width)
- writer.writeAttribute(QStringLiteral("customWidth"), QStringLiteral("1"));
- if (col_info->outlineLevel)
- writer.writeAttribute(QStringLiteral("outlineLevel"), QString::number(col_info->outlineLevel));
- if (col_info->collapsed)
- writer.writeAttribute(QStringLiteral("collapsed"), QStringLiteral("1"));
- writer.writeEndElement();//col
- }
- writer.writeEndElement();//cols
- }
- writer.writeStartElement(QStringLiteral("sheetData"));
- if (d->dimension.isValid())
- d->saveXmlSheetData(writer);
- writer.writeEndElement();//sheetData
- d->saveXmlMergeCells(writer);
- for (const ConditionalFormatting &cf : d->conditionalFormattingList)
- cf.saveToXml(writer);
- d->saveXmlDataValidations(writer);
- //{{ liufeijin : write pagesettings add by liufeijin 20181028
- // fixed by j2doll [dev18]
- // NOTE: empty element is not problem. but, empty structure of element is not parsed by Excel.
- // pageMargins
- if ( false == d->PMleft.isEmpty() &&
- false == d->PMright.isEmpty() &&
- false == d->PMtop.isEmpty() &&
- false == d->PMbotton.isEmpty() &&
- false == d->PMheader.isEmpty() &&
- false == d->PMfooter.isEmpty()
- )
- {
- writer.writeStartElement(QStringLiteral("pageMargins"));
- writer.writeAttribute(QStringLiteral("left"), d->PMleft );
- writer.writeAttribute(QStringLiteral("right"), d->PMright );
- writer.writeAttribute(QStringLiteral("top"), d->PMtop );
- writer.writeAttribute(QStringLiteral("bottom"), d->PMbotton );
- writer.writeAttribute(QStringLiteral("header"), d->PMheader );
- writer.writeAttribute(QStringLiteral("footer"), d->PMfooter );
- writer.writeEndElement(); // pageMargins
- }
- // dev57
- if ( !d->Prid.isEmpty() )
- {
- writer.writeStartElement(QStringLiteral("pageSetup")); // pageSetup
- writer.writeAttribute(QStringLiteral("r:id"), d->Prid);
- if ( !d->PverticalDpi.isEmpty() )
- {
- writer.writeAttribute(QStringLiteral("verticalDpi"), d->PverticalDpi);
- }
- if ( !d->PhorizontalDpi.isEmpty() )
- {
- writer.writeAttribute(QStringLiteral("horizontalDpi"), d->PhorizontalDpi);
- }
- if ( !d->PuseFirstPageNumber.isEmpty() )
- {
- writer.writeAttribute(QStringLiteral("useFirstPageNumber"), d->PuseFirstPageNumber);
- }
- if ( !d->PfirstPageNumber.isEmpty() )
- {
- writer.writeAttribute(QStringLiteral("firstPageNumber"), d->PfirstPageNumber);
- }
- if ( !d->Pscale.isEmpty() )
- {
- writer.writeAttribute(QStringLiteral("scale"), d->Pscale);
- }
- if ( !d->PpaperSize.isEmpty() )
- {
- writer.writeAttribute(QStringLiteral("paperSize"), d->PpaperSize);
- }
- if ( !d->Porientation.isEmpty() )
- {
- writer.writeAttribute(QStringLiteral("orientation"), d->Porientation);
- }
- if(!d->Pcopies.isEmpty())
- {
- writer.writeAttribute(QStringLiteral("copies"), d->Pcopies);
- }
- writer.writeEndElement(); // pageSetup
- } // if ( !d->Prid.isEmpty() )
-
- // headerFooter
- if( !(d->MoodFooter.isNull()) ||
- !(d->MoodFooter.isNull()) )
- {
- writer.writeStartElement(QStringLiteral("headerFooter")); // headerFooter
- if ( !d->MoodalignWithMargins.isEmpty() )
- {
- writer.writeAttribute(QStringLiteral("alignWithMargins"), d->MoodalignWithMargins);
- }
- if ( !d->ModdHeader.isNull() )
- {
- writer.writeStartElement(QStringLiteral("oddHeader"));
- writer.writeCharacters(d->ModdHeader);
- writer.writeEndElement(); // oddHeader
- }
- if ( !d->MoodFooter.isNull() )
- {
- writer.writeTextElement(QStringLiteral("oddFooter"), d->MoodFooter);
- }
- writer.writeEndElement(); // headerFooter
- }
- d->saveXmlHyperlinks(writer);
- d->saveXmlDrawings(writer);
- writer.writeEndElement(); // worksheet
- writer.writeEndDocument();
- }
- //{{ liufeijin
- bool Worksheet::setStartPage(int spagen)
- {
- Q_D(Worksheet);
- d->PfirstPageNumber=QString::number(spagen);
- return true;
- }
- //}}
- void WorksheetPrivate::saveXmlSheetData(QXmlStreamWriter &writer) const
- {
- calculateSpans();
- for (int row_num = dimension.firstRow(); row_num <= dimension.lastRow(); row_num++)
- {
- auto ctIt = cellTable.constFind(row_num);
- auto riIt = rowsInfo.constFind(row_num);
- if (ctIt == cellTable.constEnd() && riIt == rowsInfo.constEnd() && !comments.contains(row_num))
- {
- //Only process rows with cell data / comments / formatting
- continue;
- }
- int span_index = (row_num-1) / 16;
- QString span;
- auto rsIt = row_spans.constFind(span_index);
- if (rsIt != row_spans.constEnd())
- span = rsIt.value();
- writer.writeStartElement(QStringLiteral("row"));
- writer.writeAttribute(QStringLiteral("r"), QString::number(row_num));
- if (!span.isEmpty())
- writer.writeAttribute(QStringLiteral("spans"), span);
- if (riIt != rowsInfo.constEnd())
- {
- QSharedPointer<XlsxRowInfo> rowInfo = riIt.value();
- if (!rowInfo->format.isEmpty())
- {
- writer.writeAttribute(QStringLiteral("s"), QString::number(rowInfo->format.xfIndex()));
- writer.writeAttribute(QStringLiteral("customFormat"), QStringLiteral("1"));
- }
- //!Todo: support customHeight from info struct
- //!Todo: where does this magic number '15' come from?
- if (rowInfo->customHeight) {
- writer.writeAttribute(QStringLiteral("ht"), QString::number(rowInfo->height));
- writer.writeAttribute(QStringLiteral("customHeight"), QStringLiteral("1"));
- } else {
- writer.writeAttribute(QStringLiteral("customHeight"), QStringLiteral("0"));
- }
- if (rowInfo->hidden)
- writer.writeAttribute(QStringLiteral("hidden"), QStringLiteral("1"));
- if (rowInfo->outlineLevel > 0)
- writer.writeAttribute(QStringLiteral("outlineLevel"), QString::number(rowInfo->outlineLevel));
- if (rowInfo->collapsed)
- writer.writeAttribute(QStringLiteral("collapsed"), QStringLiteral("1"));
- }
- //Write cell data if row contains filled cells
- if (ctIt != cellTable.constEnd())
- {
- for (int col_num = dimension.firstColumn(); col_num <= dimension.lastColumn(); col_num++)
- {
- if (ctIt->contains(col_num))
- {
- saveXmlCellData(writer, row_num, col_num, (*ctIt)[col_num]);
- }
- }
- }
- writer.writeEndElement(); //row
- }
- }
- void WorksheetPrivate::saveXmlCellData(QXmlStreamWriter &writer, int row, int col, QSharedPointer<Cell> cell) const
- {
- Q_Q(const Worksheet);
- //This is the innermost loop so efficiency is important.
- QString cell_pos = CellReference(row, col).toString();
- writer.writeStartElement(QStringLiteral("c"));
- writer.writeAttribute(QStringLiteral("r"), cell_pos);
- QMap<int, QSharedPointer<XlsxRowInfo> >::ConstIterator rIt;
- QMap<int, QSharedPointer<XlsxColumnInfo> >::ConstIterator cIt;
- //Style used by the cell, row or col
- if (!cell->format().isEmpty())
- writer.writeAttribute(QStringLiteral("s"), QString::number(cell->format().xfIndex()));
- else if ((rIt = rowsInfo.constFind(row)) != rowsInfo.constEnd() && !(*rIt)->format.isEmpty())
- writer.writeAttribute(QStringLiteral("s"), QString::number((*rIt)->format.xfIndex()));
- else if ((cIt = colsInfoHelper.constFind(col)) != colsInfoHelper.constEnd() && !(*cIt)->format.isEmpty())
- writer.writeAttribute(QStringLiteral("s"), QString::number((*cIt)->format.xfIndex()));
- if (cell->cellType() == Cell::SharedStringType) // 's'
- {
- int sst_idx;
- if (cell->isRichString())
- sst_idx = sharedStrings()->getSharedStringIndex(cell->d_ptr->richString);
- else
- sst_idx = sharedStrings()->getSharedStringIndex(cell->value().toString());
- writer.writeAttribute(QStringLiteral("t"), QStringLiteral("s"));
- writer.writeTextElement(QStringLiteral("v"), QString::number(sst_idx));
- }
- else if (cell->cellType() == Cell::InlineStringType) // 'inlineStr'
- {
- writer.writeAttribute(QStringLiteral("t"), QStringLiteral("inlineStr"));
- writer.writeStartElement(QStringLiteral("is"));
- if (cell->isRichString())
- {
- //Rich text string
- RichString string = cell->d_ptr->richString;
- for (int i=0; i<string.fragmentCount(); ++i)
- {
- writer.writeStartElement(QStringLiteral("r"));
- if (string.fragmentFormat(i).hasFontData())
- {
- writer.writeStartElement(QStringLiteral("rPr"));
- //:Todo
- writer.writeEndElement();// rPr
- }
- writer.writeStartElement(QStringLiteral("t"));
- if (isSpaceReserveNeeded(string.fragmentText(i)))
- writer.writeAttribute(QStringLiteral("xml:space"), QStringLiteral("preserve"));
- writer.writeCharacters(string.fragmentText(i));
- writer.writeEndElement();// t
- writer.writeEndElement(); // r
- }
- }
- else
- {
- writer.writeStartElement(QStringLiteral("t"));
- QString string = cell->value().toString();
- if (isSpaceReserveNeeded(string))
- writer.writeAttribute(QStringLiteral("xml:space"), QStringLiteral("preserve"));
- writer.writeCharacters(string);
- writer.writeEndElement(); // t
- }
- writer.writeEndElement();//is
- }
- else if (cell->cellType() == Cell::NumberType) // 'n'
- {
- writer.writeAttribute(QStringLiteral("t"), QStringLiteral("n")); // dev67
- if (cell->hasFormula())
- {
- QString strFormula = cell->formula().d->formula;
- Q_UNUSED(strFormula);
- cell->formula().saveToXml(writer);
- }
- if (cell->value().isValid())
- { //note that, invalid value means 'v' is blank
- double value = cell->value().toDouble();
- writer.writeTextElement(QStringLiteral("v"), QString::number(value, 'g', 15));
- }
- }
- else if (cell->cellType() == Cell::StringType) // 'str'
- {
- writer.writeAttribute(QStringLiteral("t"), QStringLiteral("str"));
- if (cell->hasFormula())
- cell->formula().saveToXml(writer);
- writer.writeTextElement(QStringLiteral("v"), cell->value().toString());
- }
- else if (cell->cellType() == Cell::BooleanType) // 'b'
- {
- writer.writeAttribute(QStringLiteral("t"), QStringLiteral("b"));
- // dev34
- if (cell->hasFormula())
- {
- QString strFormula = cell->formula().d->formula;
- Q_UNUSED(strFormula);
- cell->formula().saveToXml(writer);
- }
- writer.writeTextElement(QStringLiteral("v"), cell->value().toBool() ? QStringLiteral("1") : QStringLiteral("0"));
- }
- else if (cell->cellType() == Cell::DateType) // 'd'
- {
- // dev67
- double num = cell->value().toDouble();
- bool is1904 = q->workbook()->isDate1904();
- if (!is1904 && num > 60) // for mac os excel
- {
- num = num - 1;
- }
- // number type. see for 18.18.11 ST_CellType (Cell Type) more information.
- writer.writeAttribute(QStringLiteral("t"), QStringLiteral("n"));
- writer.writeTextElement(QStringLiteral("v"), cell->value().toString() );
- }
- else if (cell->cellType() == Cell::ErrorType) // 'e'
- {
- writer.writeAttribute(QStringLiteral("t"), QStringLiteral("e"));
- writer.writeTextElement(QStringLiteral("v"), cell->value().toString() );
- }
- else // if (cell->cellType() == Cell::CustomType)
- {
- // custom type
- if (cell->hasFormula())
- {
- QString strFormula = cell->formula().d->formula;
- Q_UNUSED(strFormula);
- cell->formula().saveToXml(writer);
- }
- if (cell->value().isValid())
- { //note that, invalid value means 'v' is blank
- double value = cell->value().toDouble();
- writer.writeTextElement(QStringLiteral("v"), QString::number(value, 'g', 15));
- }
- }
- writer.writeEndElement(); // c
- }
- void WorksheetPrivate::saveXmlMergeCells(QXmlStreamWriter &writer) const
- {
- if (merges.isEmpty())
- return;
- writer.writeStartElement(QStringLiteral("mergeCells"));
- writer.writeAttribute(QStringLiteral("count"), QString::number(merges.size()));
- for (const CellRange &range : merges)
- {
- writer.writeEmptyElement(QStringLiteral("mergeCell"));
- writer.writeAttribute(QStringLiteral("ref"), range.toString());
- }
- writer.writeEndElement(); //mergeCells
- }
- void WorksheetPrivate::saveXmlDataValidations(QXmlStreamWriter &writer) const
- {
- if (dataValidationsList.isEmpty())
- return;
- writer.writeStartElement(QStringLiteral("dataValidations"));
- writer.writeAttribute(QStringLiteral("count"), QString::number(dataValidationsList.size()));
- for (const DataValidation &validation : dataValidationsList)
- validation.saveToXml(writer);
- writer.writeEndElement(); //dataValidations
- }
- void WorksheetPrivate::saveXmlHyperlinks(QXmlStreamWriter &writer) const
- {
- if (urlTable.isEmpty())
- return;
- writer.writeStartElement(QStringLiteral("hyperlinks"));
- QMapIterator<int, QMap< int, QSharedPointer<XlsxHyperlinkData> > > it(urlTable);
- while (it.hasNext())
- {
- it.next();
- int row = it.key();
- QMapIterator< int, QSharedPointer<XlsxHyperlinkData> > it2(it.value());
- while (it2.hasNext())
- {
- it2.next();
- int col = it2.key();
- QSharedPointer<XlsxHyperlinkData> data = it2.value();
- QString ref = CellReference(row, col).toString();
- // dev57
- // writer.writeEmptyElement(QStringLiteral("hyperlink"));
- writer.writeStartElement(QStringLiteral("hyperlink"));
- writer.writeAttribute(QStringLiteral("ref"), ref); // required field
- if ( data->linkType == XlsxHyperlinkData::External )
- {
- // Update relationships
- relationships->addWorksheetRelationship(QStringLiteral("/hyperlink"), data->target, QStringLiteral("External"));
- writer.writeAttribute(QStringLiteral("r:id"), QStringLiteral("rId%1").arg(relationships->count()));
- }
- if (!data->location.isEmpty())
- {
- writer.writeAttribute(QStringLiteral("location"), data->location);
- }
- if (!data->display.isEmpty())
- {
- writer.writeAttribute(QStringLiteral("display"), data->display);
- }
- if (!data->tooltip.isEmpty())
- {
- writer.writeAttribute(QStringLiteral("tooltip"), data->tooltip);
- }
- // dev57
- writer.writeEndElement(); // hyperlink
- }
- }
- writer.writeEndElement(); // hyperlinks
- }
- void WorksheetPrivate::saveXmlDrawings(QXmlStreamWriter &writer) const
- {
- if (!drawing)
- return;
- int idx = workbook->drawings().indexOf(drawing.data());
- relationships->addWorksheetRelationship(QStringLiteral("/drawing"), QStringLiteral("../drawings/drawing%1.xml").arg(idx+1));
- writer.writeEmptyElement(QStringLiteral("drawing"));
- writer.writeAttribute(QStringLiteral("r:id"), QStringLiteral("rId%1").arg(relationships->count()));
- }
- void WorksheetPrivate::splitColsInfo(int colFirst, int colLast)
- {
- // Split current columnInfo, for example, if "A:H" has been set,
- // we are trying to set "B:D", there should be "A", "B:D", "E:H".
- // This will be more complex if we try to set "C:F" after "B:D".
- {
- QMapIterator<int, QSharedPointer<XlsxColumnInfo> > it(colsInfo);
- while (it.hasNext()) {
- it.next();
- QSharedPointer<XlsxColumnInfo> info = it.value();
- if (colFirst > info->firstColumn && colFirst <= info->lastColumn) {
- //split the range,
- QSharedPointer<XlsxColumnInfo> info2(new XlsxColumnInfo(*info));
- info->lastColumn = colFirst - 1;
- info2->firstColumn = colFirst;
- colsInfo.insert(colFirst, info2);
- for (int c = info2->firstColumn; c <= info2->lastColumn; ++c)
- colsInfoHelper[c] = info2;
- break;
- }
- }
- }
- {
- QMapIterator<int, QSharedPointer<XlsxColumnInfo> > it(colsInfo);
- while (it.hasNext()) {
- it.next();
- QSharedPointer<XlsxColumnInfo> info = it.value();
- if (colLast >= info->firstColumn && colLast < info->lastColumn) {
- QSharedPointer<XlsxColumnInfo> info2(new XlsxColumnInfo(*info));
- info->lastColumn = colLast;
- info2->firstColumn = colLast + 1;
- colsInfo.insert(colLast + 1, info2);
- for (int c = info2->firstColumn; c <= info2->lastColumn; ++c)
- colsInfoHelper[c] = info2;
- break;
- }
- }
- }
- }
- bool WorksheetPrivate::isColumnRangeValid(int colFirst, int colLast)
- {
- bool ignore_row = true;
- bool ignore_col = false;
- if (colFirst > colLast)
- return false;
- if (checkDimensions(1, colLast, ignore_row, ignore_col))
- return false;
- if (checkDimensions(1, colFirst, ignore_row, ignore_col))
- return false;
- return true;
- }
- QList<int> WorksheetPrivate ::getColumnIndexes(int colFirst, int colLast)
- {
- splitColsInfo(colFirst, colLast);
- QList<int> nodes;
- nodes.append(colFirst);
- for (int col = colFirst; col <= colLast; ++col)
- {
- auto it = colsInfo.constFind(col);
- if (it != colsInfo.constEnd())
- {
- if (nodes.last() != col)
- nodes.append(col);
- int nextCol = (*it)->lastColumn + 1;
- if (nextCol <= colLast)
- nodes.append(nextCol);
- }
- }
- return nodes;
- }
- /*!
- Sets width in characters of a \a range of columns to \a width.
- Returns true on success.
- */
- bool Worksheet::setColumnWidth(const CellRange &range, double width)
- {
- if (!range.isValid())
- return false;
- return setColumnWidth(range.firstColumn(), range.lastColumn(), width);
- }
- /*!
- Sets format property of a \a range of columns to \a format. Columns are 1-indexed.
- Returns true on success.
- */
- bool Worksheet::setColumnFormat(const CellRange& range, const Format &format)
- {
- if (!range.isValid())
- return false;
- return setColumnFormat(range.firstColumn(), range.lastColumn(), format);
- }
- /*!
- Sets hidden property of a \a range of columns to \a hidden. Columns are 1-indexed.
- Hidden columns are not visible.
- Returns true on success.
- */
- bool Worksheet::setColumnHidden(const CellRange &range, bool hidden)
- {
- if (!range.isValid())
- return false;
- return setColumnHidden(range.firstColumn(), range.lastColumn(), hidden);
- }
- /*!
- Sets width in characters for columns [\a colFirst, \a colLast] to \a width.
- Columns are 1-indexed.
- Returns true on success.
- */
- bool Worksheet::setColumnWidth(int colFirst, int colLast, double width)
- {
- Q_D(Worksheet);
- const QList <QSharedPointer<XlsxColumnInfo> > columnInfoList = d->getColumnInfoList(colFirst, colLast);
- for (const QSharedPointer<XlsxColumnInfo> &columnInfo : columnInfoList)
- {
- columnInfo->width = width;
- }
- return (columnInfoList.count() > 0);
- }
- /*!
- Sets format property of a range of columns [\a colFirst, \a colLast] to \a format.
- Columns are 1-indexed.
- Returns true on success.
- */
- bool Worksheet::setColumnFormat(int colFirst, int colLast, const Format &format)
- {
- Q_D(Worksheet);
- const QList <QSharedPointer<XlsxColumnInfo> > columnInfoList = d->getColumnInfoList(colFirst, colLast);
- for (const QSharedPointer<XlsxColumnInfo> &columnInfo : columnInfoList)
- columnInfo->format = format;
- if(columnInfoList.count() > 0) {
- d->workbook->styles()->addXfFormat(format);
- return true;
- }
- return false;
- }
- /*!
- Sets hidden property of a range of columns [\a colFirst, \a colLast] to \a hidden.
- Columns are 1-indexed. Returns true on success.
- */
- bool Worksheet::setColumnHidden(int colFirst, int colLast, bool hidden)
- {
- Q_D(Worksheet);
- const QList <QSharedPointer<XlsxColumnInfo> > columnInfoList = d->getColumnInfoList(colFirst, colLast);
- for (const QSharedPointer<XlsxColumnInfo> &columnInfo : columnInfoList)
- columnInfo->hidden = hidden;
- return (columnInfoList.count() > 0);
- }
- /*!
- Returns width of the \a column in characters of the normal font. Columns are 1-indexed.
- */
- double Worksheet::columnWidth(int column)
- {
- Q_D(Worksheet);
- QList< QSharedPointer<XlsxColumnInfo> > columnInfoList = d->getColumnInfoList(column, column);
- // [dev54]
- if ( columnInfoList.size() == 0 )
- {
- // column information is not found
- // qDebug() << "[debug]" << __FUNCTION__ << "column (info) is not found. " << column;
- }
- if (columnInfoList.count() == 1)
- {
- // column information is found
- // qDebug() << "[debug]" << __FUNCTION__ << "column (info) is found. " << column << oneColWidth;
- double oneColWidth = columnInfoList.at(0)->width;
- bool isSetWidth = columnInfoList.at(0)->isSetWidth;
- if ( isSetWidth )
- {
- return oneColWidth;
- }
- }
- // use default width
- double defaultColWidth = d->sheetFormatProps.defaultColWidth;
- return defaultColWidth;
- }
- /*!
- Returns formatting of the \a column. Columns are 1-indexed.
- */
- Format Worksheet::columnFormat(int column)
- {
- Q_D(Worksheet);
- QList <QSharedPointer<XlsxColumnInfo> > columnInfoList = d->getColumnInfoList(column, column);
- if (columnInfoList.count() == 1)
- return columnInfoList.at(0)->format;
- return Format();
- }
- /*!
- Returns true if \a column is hidden. Columns are 1-indexed.
- */
- bool Worksheet::isColumnHidden(int column)
- {
- Q_D(Worksheet);
- QList <QSharedPointer<XlsxColumnInfo> > columnInfoList = d->getColumnInfoList(column, column);
- if (columnInfoList.count() == 1)
- return columnInfoList.at(0)->hidden;
- return false;
- }
- /*!
- Sets the \a height of the rows including and between \a rowFirst and \a rowLast.
- Row height measured in point size.
- Rows are 1-indexed.
- Returns true if success.
- */
- bool Worksheet::setRowHeight(int rowFirst,int rowLast, double height)
- {
- Q_D(Worksheet);
- const QList <QSharedPointer<XlsxRowInfo> > rowInfoList = d->getRowInfoList(rowFirst,rowLast);
- for (const QSharedPointer<XlsxRowInfo> &rowInfo : rowInfoList) {
- rowInfo->height = height;
- rowInfo->customHeight = true;
- }
- return rowInfoList.count() > 0;
- }
- /*!
- Sets the \a format of the rows including and between \a rowFirst and \a rowLast.
- Rows are 1-indexed.
- Returns true if success.
- */
- bool Worksheet::setRowFormat(int rowFirst,int rowLast, const Format &format)
- {
- Q_D(Worksheet);
- const QList <QSharedPointer<XlsxRowInfo> > rowInfoList = d->getRowInfoList(rowFirst,rowLast);
- for (const QSharedPointer<XlsxRowInfo> &rowInfo : rowInfoList)
- rowInfo->format = format;
- d->workbook->styles()->addXfFormat(format);
- return rowInfoList.count() > 0;
- }
- /*!
- Sets the \a hidden proeprty of the rows including and between \a rowFirst and \a rowLast.
- Rows are 1-indexed. If hidden is true rows will not be visible.
- Returns true if success.
- */
- bool Worksheet::setRowHidden(int rowFirst,int rowLast, bool hidden)
- {
- Q_D(Worksheet);
- const QList <QSharedPointer<XlsxRowInfo> > rowInfoList = d->getRowInfoList(rowFirst,rowLast);
- for (const QSharedPointer<XlsxRowInfo> &rowInfo : rowInfoList)
- rowInfo->hidden = hidden;
- return rowInfoList.count() > 0;
- }
- /*!
- Returns height of \a row in points.
- */
- double Worksheet::rowHeight(int row)
- {
- Q_D(Worksheet);
- const int min_col = d->dimension.isValid() ? d->dimension.firstColumn() : 1;
- auto it = d->rowsInfo.constFind(row);
- if (d->checkDimensions(row, min_col, false, true) || it == d->rowsInfo.constEnd())
- {
- return d->sheetFormatProps.defaultRowHeight; //return default on invalid row
- }
- return (*it)->height;
- }
- /*!
- Returns format of \a row.
- */
- Format Worksheet::rowFormat(int row)
- {
- Q_D(Worksheet);
- const int min_col = d->dimension.isValid() ? d->dimension.firstColumn() : 1;
- auto it = d->rowsInfo.constFind(row);
- if (d->checkDimensions(row, min_col, false, true) || it == d->rowsInfo.constEnd())
- return Format(); //return default on invalid row
- return (*it)->format;
- }
- /*!
- Returns true if \a row is hidden.
- */
- bool Worksheet::isRowHidden(int row)
- {
- Q_D(Worksheet);
- const int min_col = d->dimension.isValid() ? d->dimension.firstColumn() : 1;
- auto it = d->rowsInfo.constFind(row);
- if (d->checkDimensions(row, min_col, false, true) || it == d->rowsInfo.constEnd())
- return false; //return default on invalid row
- return (*it)->hidden;
- }
- /*!
- Groups rows from \a rowFirst to \a rowLast with the given \a collapsed.
- Returns false if error occurs.
- */
- bool Worksheet::groupRows(int rowFirst, int rowLast, bool collapsed)
- {
- Q_D(Worksheet);
- for (int row=rowFirst; row<=rowLast; ++row) {
- auto it = d->rowsInfo.find(row);
- if (it != d->rowsInfo.end()) {
- (*it)->outlineLevel += 1;
- } else {
- QSharedPointer<XlsxRowInfo> info(new XlsxRowInfo);
- info->outlineLevel += 1;
- it = d->rowsInfo.insert(row, info);
- }
- if (collapsed)
- (*it)->hidden = true;
- }
- if (collapsed) {
- auto it = d->rowsInfo.find(rowLast+1);
- if (it == d->rowsInfo.end())
- it = d->rowsInfo.insert(rowLast+1, QSharedPointer<XlsxRowInfo>(new XlsxRowInfo));
- (*it)->collapsed = true;
- }
- return true;
- }
- /*!
- \overload
- Groups columns with the given \a range and \a collapsed.
- */
- bool Worksheet::groupColumns(const CellRange &range, bool collapsed)
- {
- if (!range.isValid())
- return false;
- return groupColumns(range.firstColumn(), range.lastColumn(), collapsed);
- }
- /*!
- Groups columns from \a colFirst to \a colLast with the given \a collapsed.
- Returns false if error occurs.
- */
- bool Worksheet::groupColumns(int colFirst, int colLast, bool collapsed)
- {
- Q_D(Worksheet);
- d->splitColsInfo(colFirst, colLast);
- QList<int> nodes;
- nodes.append(colFirst);
- for (int col = colFirst; col <= colLast; ++col) {
- auto it = d->colsInfo.constFind(col);
- if (it != d->colsInfo.constEnd()) {
- if (nodes.last() != col)
- nodes.append(col);
- int nextCol = (*it)->lastColumn + 1;
- if (nextCol <= colLast)
- nodes.append(nextCol);
- }
- }
- for (int idx = 0; idx < nodes.size(); ++idx)
- {
- int colStart = nodes[idx];
- auto it = d->colsInfo.constFind(colStart);
- if (it != d->colsInfo.constEnd())
- {
- (*it)->outlineLevel += 1;
- if (collapsed)
- (*it)->hidden = true;
- }
- else
- {
- int colEnd = (idx == nodes.size() - 1) ? colLast : nodes[idx+1] - 1;
- QSharedPointer<XlsxColumnInfo> info(new XlsxColumnInfo(colStart, colEnd, false));
- info->outlineLevel += 1;
- d->colsInfo.insert(colFirst, info);
- if (collapsed)
- info->hidden = true;
- for (int c = colStart; c <= colEnd; ++c)
- d->colsInfoHelper[c] = info;
- }
- }
- if (collapsed) {
- int col = colLast+1;
- d->splitColsInfo(col, col);
- auto it = d->colsInfo.constFind(col);
- if (it != d->colsInfo.constEnd())
- (*it)->collapsed = true;
- else {
- QSharedPointer<XlsxColumnInfo> info(new XlsxColumnInfo(col, col, false));
- info->collapsed = true;
- d->colsInfo.insert(col, info);
- d->colsInfoHelper[col] = info;
- }
- }
- return false;
- }
- /*!
- Return the range that contains cell data.
- */
- CellRange Worksheet::dimension() const
- {
- Q_D(const Worksheet);
- return d->dimension;
- }
- /*
- Convert the height of a cell from user's units to pixels. If the
- height hasn't been set by the user we use the default value. If
- the row is hidden it has a value of zero.
- */
- int WorksheetPrivate::rowPixelsSize(int row) const
- {
- double height;
- auto it = row_sizes.constFind(row);
- if (it != row_sizes.constEnd())
- height = it.value();
- else
- height = default_row_height;
- return static_cast<int>(4.0 / 3.0 *height);
- }
- /*
- Convert the width of a cell from user's units to pixels. Excel rounds
- the column width to the nearest pixel. If the width hasn't been set
- by the user we use the default value. If the column is hidden it
- has a value of zero.
- */
- int WorksheetPrivate::colPixelsSize(int col) const
- {
- double max_digit_width = 7.0; //For Calabri 11
- double padding = 5.0;
- int pixels = 0;
- auto it = col_sizes.constFind(col);
- if (it != col_sizes.constEnd()) {
- double width = it.value();
- if (width < 1)
- pixels = static_cast<int>(width * (max_digit_width + padding) + 0.5);
- else
- pixels = static_cast<int>(width * max_digit_width + 0.5) + padding;
- } else {
- pixels = 64;
- }
- return pixels;
- }
- void WorksheetPrivate::loadXmlSheetData(QXmlStreamReader &reader)
- {
- Q_Q(Worksheet);
- Q_ASSERT(reader.name() == QLatin1String("sheetData"));
- while (!reader.atEnd() && !(reader.name() == QLatin1String("sheetData") && reader.tokenType() == QXmlStreamReader::EndElement))
- {
- if (reader.readNextStartElement())
- {
- if (reader.name() == QLatin1String("row"))
- {
- QXmlStreamAttributes attributes = reader.attributes();
- if (attributes.hasAttribute(QLatin1String("customFormat"))
- || attributes.hasAttribute(QLatin1String("customHeight"))
- || attributes.hasAttribute(QLatin1String("hidden"))
- || attributes.hasAttribute(QLatin1String("outlineLevel"))
- || attributes.hasAttribute(QLatin1String("collapsed")))
- {
- QSharedPointer<XlsxRowInfo> info(new XlsxRowInfo);
- if (attributes.hasAttribute(QLatin1String("customFormat")) &&
- attributes.hasAttribute(QLatin1String("s")))
- {
- int idx = attributes.value(QLatin1String("s")).toString().toInt();
- info->format = workbook->styles()->xfFormat(idx);
- }
- if (attributes.hasAttribute(QLatin1String("customHeight")))
- {
- info->customHeight = attributes.value(QLatin1String("customHeight")) == QLatin1String("1");
- //Row height is only specified when customHeight is set
- if(attributes.hasAttribute(QLatin1String("ht")))
- {
- info->height = attributes.value(QLatin1String("ht")).toString().toDouble();
- }
- }
- //both "hidden" and "collapsed" default are false
- info->hidden = attributes.value(QLatin1String("hidden")) == QLatin1String("1");
- info->collapsed = attributes.value(QLatin1String("collapsed")) == QLatin1String("1");
- if (attributes.hasAttribute(QLatin1String("outlineLevel")))
- info->outlineLevel = attributes.value(QLatin1String("outlineLevel")).toString().toInt();
- //"r" is optional too.
- if (attributes.hasAttribute(QLatin1String("r")))
- {
- int row = attributes.value(QLatin1String("r")).toString().toInt();
- rowsInfo[row] = info;
- }
- }
- }
- else if (reader.name() == QLatin1String("c")) // Cell
- {
-
- //Cell
- QXmlStreamAttributes attributes = reader.attributes();
- QString r = attributes.value(QLatin1String("r")).toString();
- CellReference pos(r);
- //get format
- Format format;
- qint32 styleIndex = -1;
- if (attributes.hasAttribute(QLatin1String("s"))) // Style (defined in the styles.xml file)
- {
- //"s" == style index
- int idx = attributes.value(QLatin1String("s")).toString().toInt();
- format = workbook->styles()->xfFormat(idx);
- styleIndex = idx;
- }
- // Cell::CellType cellType = Cell::NumberType;
- Cell::CellType cellType = Cell::CustomType;
- if (attributes.hasAttribute(QLatin1String("t"))) // Type
- {
- QString typeString = attributes.value(QLatin1String("t")).toString();
- if (typeString == QLatin1String("s")) // Shared string
- {
- cellType = Cell::SharedStringType;
- }
- else if (typeString == QLatin1String("inlineStr")) // Inline String
- {
- cellType = Cell::InlineStringType;
- }
- else if (typeString == QLatin1String("str")) // String
- {
- cellType = Cell::StringType;
- }
- else if (typeString == QLatin1String("b")) // Boolean
- {
- cellType = Cell::BooleanType;
- }
- else if (typeString == QLatin1String("e")) // Error
- {
- cellType = Cell::ErrorType;
- }
- else if (typeString == QLatin1String("d")) // Date
- {
- cellType = Cell::DateType;
- }
- else if (typeString == QLatin1String("n")) // Number
- {
- cellType = Cell::NumberType;
- }
- else
- {
- // custom type
- cellType = Cell::CustomType;
- }
- }
- // [dev54] temp cell for checking datetype
- Cell tempCell(QVariant(), cellType, format, q, styleIndex);
- if ( tempCell.isDateTime() )
- {
- cellType = Cell::DateType;
- }
- // create a heap of new cell
- QSharedPointer<Cell> cell(new Cell(QVariant(), cellType, format, q, styleIndex));
- while (!reader.atEnd() &&
- !(reader.name() == QLatin1String("c") &&
- reader.tokenType() == QXmlStreamReader::EndElement))
- {
- if (reader.readNextStartElement())
- {
- if (reader.name() == QLatin1String("f")) // formula
- {
- CellFormula &formula = cell->d_func()->formula;
- formula.loadFromXml(reader);
- if (formula.formulaType() == CellFormula::SharedType &&
- !formula.formulaText().isEmpty())
- {
- int si = formula.sharedIndex();
- sharedFormulaMap[ si ] = formula;
- }
- }
- else if (reader.name() == QLatin1String("v")) // Value
- {
- QString value = reader.readElementText();
- if (cellType == Cell::SharedStringType)
- {
- int sst_idx = value.toInt();
- sharedStrings()->incRefByStringIndex(sst_idx);
- RichString rs = sharedStrings()->getSharedString(sst_idx);
- QString strPlainString = rs.toPlainString();
- cell->d_func()->value = strPlainString;
- if (rs.isRichString())
- cell->d_func()->richString = rs;
- }
- else if (cellType == Cell::NumberType)
- {
- cell->d_func()->value = value.toDouble();
- }
- else if (cellType == Cell::BooleanType)
- {
- cell->d_func()->value = value.toInt() ? true : false;
- }
- else if (cellType == Cell::DateType)
- {
- // [dev54] DateType
- double dValue = value.toDouble(); // days from 1900(or 1904)
- bool bIsDate1904 = q->workbook()->isDate1904();
- QVariant vDatetimeValue = datetimeFromNumber( dValue, bIsDate1904 );
- Q_UNUSED(vDatetimeValue);
- // cell->d_func()->value = vDatetimeValue;
- cell->d_func()->value = dValue; // dev67
- }
- else
- {
- // ELSE type
- cell->d_func()->value = value;
- }
- }
- else if (reader.name() == QLatin1String("is"))
- {
- while (!reader.atEnd() &&
- !(reader.name() == QLatin1String("is") &&
- reader.tokenType() == QXmlStreamReader::EndElement))
- {
- if (reader.readNextStartElement())
- {
- //:Todo, add rich text read support
- if (reader.name() == QLatin1String("t"))
- {
- cell->d_func()->value = reader.readElementText();
- }
- }
- }
- }
- else if (reader.name() == QLatin1String("extLst"))
- {
- //skip extLst element
- while ( !reader.atEnd() &&
- !(reader.name() == QLatin1String("extLst") &&
- reader.tokenType() == QXmlStreamReader::EndElement))
- {
- reader.readNextStartElement();
- }
- }
- }
- }
- cellTable[ pos.row() ][ pos.column() ] = cell;
- }
- }
- }
- }
- void WorksheetPrivate::loadXmlColumnsInfo(QXmlStreamReader &reader)
- {
- Q_ASSERT(reader.name() == QLatin1String("cols"));
- while (!reader.atEnd() &&
- !(reader.name() == QLatin1String("cols") &&
- reader.tokenType() == QXmlStreamReader::EndElement))
- {
- reader.readNextStartElement();
- if (reader.tokenType() == QXmlStreamReader::StartElement)
- {
- if (reader.name() == QLatin1String("col"))
- {
- QSharedPointer<XlsxColumnInfo> info(new XlsxColumnInfo(0, 1, false));
- QXmlStreamAttributes colAttrs = reader.attributes();
- int min = colAttrs.value(QLatin1String("min")).toString().toInt();
- int max = colAttrs.value(QLatin1String("max")).toString().toInt();
- info->firstColumn = min;
- info->lastColumn = max;
- //Flag indicating that the column width for the affected column(s) is different from the
- // default or has been manually set
- if(colAttrs.hasAttribute(QLatin1String("customWidth")))
- {
- info->customWidth = colAttrs.value(QLatin1String("customWidth")) == QLatin1String("1");
- }
- //Note, node may have "width" without "customWidth"
- // [dev54]
- if (colAttrs.hasAttribute(QLatin1String("width")))
- {
- double width = colAttrs.value(QLatin1String("width")).toString().toDouble();
- info->width = width;
- info->isSetWidth = true; // [dev54]
- }
- info->hidden = colAttrs.value(QLatin1String("hidden")) == QLatin1String("1");
- info->collapsed = colAttrs.value(QLatin1String("collapsed")) == QLatin1String("1");
- if (colAttrs.hasAttribute(QLatin1String("style")))
- {
- int idx = colAttrs.value(QLatin1String("style")).toString().toInt();
- info->format = workbook->styles()->xfFormat(idx);
- }
- if (colAttrs.hasAttribute(QLatin1String("outlineLevel")))
- {
- info->outlineLevel = colAttrs.value(QLatin1String("outlineLevel")).toString().toInt();
- }
- // qDebug() << "[debug] " << __FUNCTION__ << min << max << info->width << hasWidth;
- colsInfo.insert(min, info);
- for (int col = min ; col <= max ; ++col)
- {
- colsInfoHelper[col] = info;
- }
- }
- }
- }
- }
- void WorksheetPrivate::loadXmlMergeCells(QXmlStreamReader &reader)
- {
- // issue #173 https://github.com/QtExcel/QXlsx/issues/173
- Q_ASSERT(reader.name() == QLatin1String("mergeCells"));
- QXmlStreamAttributes attributes = reader.attributes();
- bool isCount = attributes.hasAttribute(QLatin1String("count"));
- int count = 0;
- if ( !isCount )
- {
- qWarning("no count");
- }
- else
- {
- count = attributes.value(QLatin1String("count")).toString().toInt();
- }
- while ( !reader.atEnd() &&
- !(reader.name() == QLatin1String("mergeCells") &&
- reader.tokenType() == QXmlStreamReader::EndElement) )
- {
- reader.readNextStartElement();
- if (reader.tokenType() == QXmlStreamReader::StartElement)
- {
- if (reader.name() == QLatin1String("mergeCell"))
- {
- QXmlStreamAttributes attrs = reader.attributes();
- QString rangeStr = attrs.value(QLatin1String("ref")).toString();
- merges.append(CellRange(rangeStr));
- }
- }
- }
- if (isCount)
- {
- int mergesSize = merges.size();
- if ( mergesSize != count )
- {
- qWarning("read merge cells error");
- }
- }
- }
- void WorksheetPrivate::loadXmlDataValidations(QXmlStreamReader &reader)
- {
- Q_ASSERT(reader.name() == QLatin1String("dataValidations"));
- QXmlStreamAttributes attributes = reader.attributes();
- int count = attributes.value(QLatin1String("count")).toString().toInt();
- while (!reader.atEnd() && !(reader.name() == QLatin1String("dataValidations")
- && reader.tokenType() == QXmlStreamReader::EndElement)) {
- reader.readNextStartElement();
- if (reader.tokenType() == QXmlStreamReader::StartElement
- && reader.name() == QLatin1String("dataValidation")) {
- dataValidationsList.append(DataValidation::loadFromXml(reader));
- }
- }
- if (dataValidationsList.size() != count)
- qDebug("read data validation error");
- }
- void WorksheetPrivate::loadXmlSheetViews(QXmlStreamReader &reader)
- {
- Q_ASSERT(reader.name() == QLatin1String("sheetViews"));
- while (!reader.atEnd() && !(reader.name() == QLatin1String("sheetViews")
- && reader.tokenType() == QXmlStreamReader::EndElement)) {
- reader.readNextStartElement();
- if (reader.tokenType() == QXmlStreamReader::StartElement && reader.name() == QLatin1String("sheetView")) {
- QXmlStreamAttributes attrs = reader.attributes();
- //default false
- windowProtection = attrs.value(QLatin1String("windowProtection")) == QLatin1String("1");
- showFormulas = attrs.value(QLatin1String("showFormulas")) == QLatin1String("1");
- rightToLeft = attrs.value(QLatin1String("rightToLeft")) == QLatin1String("1");
- tabSelected = attrs.value(QLatin1String("tabSelected")) == QLatin1String("1");
- //default true
- showGridLines = attrs.value(QLatin1String("showGridLines")) != QLatin1String("0");
- showRowColHeaders = attrs.value(QLatin1String("showRowColHeaders")) != QLatin1String("0");
- showZeros = attrs.value(QLatin1String("showZeros")) != QLatin1String("0");
- showRuler = attrs.value(QLatin1String("showRuler")) != QLatin1String("0");
- showOutlineSymbols = attrs.value(QLatin1String("showOutlineSymbols")) != QLatin1String("0");
- showWhiteSpace = attrs.value(QLatin1String("showWhiteSpace")) != QLatin1String("0");
- }
- }
- }
- void WorksheetPrivate::loadXmlSheetFormatProps(QXmlStreamReader &reader)
- {
- Q_ASSERT(reader.name() == QLatin1String("sheetFormatPr"));
- const QXmlStreamAttributes attributes = reader.attributes();
- XlsxSheetFormatProps formatProps;
- bool isSetWidth = false;
- // Retain default values
- for (const QXmlStreamAttribute &attrib : attributes)
- {
- if(attrib.name() == QLatin1String("baseColWidth") )
- {
- formatProps.baseColWidth = attrib.value().toString().toInt();
- }
- else if(attrib.name() == QLatin1String("customHeight"))
- {
- formatProps.customHeight = attrib.value() == QLatin1String("1");
- }
- else if(attrib.name() == QLatin1String("defaultColWidth"))
- {
- double dDefaultColWidth = attrib.value().toString().toDouble();
- formatProps.defaultColWidth = dDefaultColWidth;
- isSetWidth = true;
- }
- else if(attrib.name() == QLatin1String("defaultRowHeight"))
- {
- formatProps.defaultRowHeight = attrib.value().toString().toDouble();
- }
- else if(attrib.name() == QLatin1String("outlineLevelCol"))
- {
- formatProps.outlineLevelCol = attrib.value().toString().toInt();
- }
- else if(attrib.name() == QLatin1String("outlineLevelRow"))
- {
- formatProps.outlineLevelRow = attrib.value().toString().toInt();
- }
- else if(attrib.name() == QLatin1String("thickBottom"))
- {
- formatProps.thickBottom = attrib.value() == QLatin1String("1");
- }
- else if(attrib.name() == QLatin1String("thickTop"))
- {
- formatProps.thickTop = attrib.value() == QLatin1String("1");
- }
- else if(attrib.name() == QLatin1String("zeroHeight"))
- {
- formatProps.zeroHeight = attrib.value() == QLatin1String("1");
- }
- }
- // if (formatProps.defaultColWidth == 0.0)
- if ( !isSetWidth )
- {
- //not set
- double dCalcWidth = WorksheetPrivate::calculateColWidth(formatProps.baseColWidth);
- formatProps.defaultColWidth = dCalcWidth;
- }
- // [dev54]
- // Where is code of setting 'formatProps'?
- this->sheetFormatProps = formatProps;
- }
- double WorksheetPrivate::calculateColWidth(int characters)
- {
- // //!Todo
- //Take normal style' font maximum width and add padding and margin pixels
- // return characters + 0.5;
- return characters;
- }
- void WorksheetPrivate::loadXmlHyperlinks(QXmlStreamReader &reader)
- {
- Q_ASSERT(reader.name() == QLatin1String("hyperlinks"));
- while (!reader.atEnd() && !(reader.name() == QLatin1String("hyperlinks")
- && reader.tokenType() == QXmlStreamReader::EndElement)) {
- reader.readNextStartElement();
- if (reader.tokenType() == QXmlStreamReader::StartElement && reader.name() == QLatin1String("hyperlink")) {
- QXmlStreamAttributes attrs = reader.attributes();
- CellReference pos(attrs.value(QLatin1String("ref")).toString());
- if (pos.isValid()) { //Valid
- QSharedPointer<XlsxHyperlinkData> link(new XlsxHyperlinkData);
- link->display = attrs.value(QLatin1String("display")).toString();
- link->tooltip = attrs.value(QLatin1String("tooltip")).toString();
- link->location = attrs.value(QLatin1String("location")).toString();
- if (attrs.hasAttribute(QLatin1String("r:id"))) {
- link->linkType = XlsxHyperlinkData::External;
- XlsxRelationship ship = relationships->getRelationshipById(attrs.value(QLatin1String("r:id")).toString());
- link->target = ship.target;
- } else {
- link->linkType = XlsxHyperlinkData::Internal;
- }
- urlTable[pos.row()][pos.column()] = link;
- }
- }
- }
- }
- QList <QSharedPointer<XlsxColumnInfo> > WorksheetPrivate::getColumnInfoList(int colFirst, int colLast)
- {
- QList <QSharedPointer<XlsxColumnInfo> > columnsInfoList;
- if (isColumnRangeValid(colFirst,colLast))
- {
- QList<int> nodes = getColumnIndexes(colFirst, colLast);
- for (int idx = 0; idx < nodes.size(); ++idx)
- {
- int colStart = nodes[idx];
- auto it = colsInfo.constFind(colStart);
- if (it != colsInfo.constEnd())
- {
- columnsInfoList.append(*it);
- }
- else
- {
- int colEnd = (idx == nodes.size() - 1) ? colLast : nodes[idx+1] - 1;
- QSharedPointer<XlsxColumnInfo> info(new XlsxColumnInfo(colStart, colEnd, false));
- colsInfo.insert(colFirst, info);
- columnsInfoList.append(info);
- for (int c = colStart; c <= colEnd; ++c)
- {
- colsInfoHelper[c] = info;
- }
- }
- }
- }
- return columnsInfoList;
- }
- QList <QSharedPointer<XlsxRowInfo> > WorksheetPrivate::getRowInfoList(int rowFirst, int rowLast)
- {
- QList <QSharedPointer<XlsxRowInfo> > rowInfoList;
- int min_col = dimension.firstColumn() < 1 ? 1 : dimension.firstColumn();
- for(int row = rowFirst; row <= rowLast; ++row) {
- if (checkDimensions(row, min_col, false, true))
- continue;
- QSharedPointer<XlsxRowInfo> rowInfo;
- if ((rowsInfo[row]).isNull()){
- rowsInfo[row] = QSharedPointer<XlsxRowInfo>(new XlsxRowInfo());
- }
- rowInfoList.append(rowsInfo[row]);
- }
- return rowInfoList;
- }
- bool Worksheet::loadFromXmlFile(QIODevice *device)
- {
- Q_D(Worksheet);
- QXmlStreamReader reader(device);
- while (!reader.atEnd())
- {
- reader.readNextStartElement();
- if (reader.tokenType() == QXmlStreamReader::StartElement)
- {
- if (reader.name() == QLatin1String("dimension"))
- {
- QXmlStreamAttributes attributes = reader.attributes();
- QString range = attributes.value(QLatin1String("ref")).toString();
- d->dimension = CellRange(range);
- }
- else if (reader.name() == QLatin1String("sheetViews"))
- {
- d->loadXmlSheetViews(reader);
- }
- else if (reader.name() == QLatin1String("sheetFormatPr"))
- {
- d->loadXmlSheetFormatProps(reader);
- }
- else if (reader.name() == QLatin1String("cols"))
- {
- d->loadXmlColumnsInfo(reader);
- }
- else if (reader.name() == QLatin1String("sheetData"))
- {
- d->loadXmlSheetData(reader);
- }
- else if (reader.name() == QLatin1String("mergeCells"))
- {
- d->loadXmlMergeCells(reader);
- }
- else if (reader.name() == QLatin1String("dataValidations"))
- {
- d->loadXmlDataValidations(reader);
- }
- else if (reader.name() == QLatin1String("conditionalFormatting"))
- {
- ConditionalFormatting cf;
- cf.loadFromXml(reader, workbook()->styles());
- d->conditionalFormattingList.append(cf);
- }
- else if (reader.name() == QLatin1String("hyperlinks"))
- {
- d->loadXmlHyperlinks(reader);
- }
- else if(reader.name() == QLatin1String("pageSetup"))
- {
- QXmlStreamAttributes attributes = reader.attributes();
- d->PpaperSize = attributes.value(QLatin1String("paperSize")).toString().trimmed();
- d->Pscale = attributes.value(QLatin1String("scale")).toString().trimmed();
- d->PfirstPageNumber = attributes.value(QLatin1String("firstPageNumber")).toString().trimmed();
- d->Porientation = attributes.value(QLatin1String("orientation")).toString().trimmed();
- d->PuseFirstPageNumber = attributes.value(QLatin1String("useFirstPageNumber")).toString().trimmed();
- d->PhorizontalDpi = attributes.value(QLatin1String("horizontalDpi")).toString().trimmed();
- d->PverticalDpi = attributes.value(QLatin1String("verticalDpi")).toString().trimmed();
- d->Prid = attributes.value(QLatin1String("r:id")).toString().trimmed();
- d->Pcopies = attributes.value(QLatin1String("copies")).toString().trimmed();
- }
- else if(reader.name() == QLatin1String("pageMargins"))
- {
- QXmlStreamAttributes attributes = reader.attributes();
- d->PMfooter= attributes.value(QLatin1String("footer")).toString().trimmed();
- d->PMheader = attributes.value(QLatin1String("header")).toString().trimmed();
- d->PMbotton = attributes.value(QLatin1String("bottom")).toString().trimmed();
- d->PMtop = attributes.value(QLatin1String("top")).toString().trimmed();
- d->PMright = attributes.value(QLatin1String("right")).toString().trimmed();
- d->PMleft = attributes.value(QLatin1String("left")).toString().trimmed();
- }
- else if(reader.name() == QLatin1String("headerFooter"))
- {
- // dev40
- while (reader.readNextStartElement())
- {
- if (reader.name() == QLatin1String("oddHeader"))
- d->ModdHeader = reader.readElementText();
- if (reader.name() == QLatin1String("oddFooter"))
- d->MoodFooter = reader.readElementText();
- }
- }
- else if (reader.name() == QLatin1String("drawing"))
- {
- QString rId = reader.attributes().value(QStringLiteral("r:id")).toString();
- QString name = d->relationships->getRelationshipById(rId).target;
- QString str = *( splitPath(filePath()).begin() );
- str = str + QLatin1String("/");
- str = str + name;
- QString path = QDir::cleanPath( str );
- d->drawing = QSharedPointer<Drawing>(new Drawing(this, F_LoadFromExists));
- d->drawing->setFilePath(path);
- }
- else if (reader.name() == QLatin1String("extLst"))
- {
- //Todo: add extLst support
- while ( !reader.atEnd() &&
- !(reader.name() == QLatin1String("extLst") &&
- reader.tokenType() == QXmlStreamReader::EndElement))
- {
- reader.readNextStartElement();
- }
- }
- }
- }
- d->validateDimension();
- return true;
- }
- /*
- * Documents imported from Google Docs does not contain dimension data.
- */
- void WorksheetPrivate::validateDimension()
- {
- if (dimension.isValid() || cellTable.isEmpty())
- return;
- const auto firstRow = cellTable.constBegin().key();
- const auto lastRow = (--cellTable.constEnd()).key();
- int firstColumn = -1;
- int lastColumn = -1;
- for ( auto&& it = cellTable.constBegin()
- ; it != cellTable.constEnd()
- ; ++it )
- {
- Q_ASSERT(!it.value().isEmpty());
- if (firstColumn == -1 || it.value().constBegin().key() < firstColumn)
- firstColumn = it.value().constBegin().key();
- if (lastColumn == -1 || (--it.value().constEnd()).key() > lastColumn)
- {
- lastColumn = (--it.value().constEnd()).key();
- }
- }
- CellRange cr(firstRow, firstColumn, lastRow, lastColumn);
- if (cr.isValid())
- dimension = cr;
- }
- /*!
- * \internal
- * Unit test can use this member to get sharedString object.
- */
- SharedStrings *WorksheetPrivate::sharedStrings() const
- {
- return workbook->sharedStrings();
- }
- QVector<CellLocation> Worksheet::getFullCells(int* maxRow, int* maxCol)
- {
- Q_D(const Worksheet);
- // return values
- (*maxRow) = -1;
- (*maxCol) = -1;
- QVector<CellLocation> ret;
- // QString privateName = d->name; // name of sheet (not object type)
- // qDebug() << privateName ;
- if ( d->type == AbstractSheet::ST_WorkSheet )
- {
- // use current sheet
- }
- else if ( d->type == AbstractSheet::ST_ChartSheet )
- {
- return ret;
- }
- else
- {
- qWarning("unsupported sheet type.");
- Q_ASSERT(false);
- return ret;
- }
- QMapIterator< int, QMap< int, QSharedPointer<Cell> > > _it( d->cellTable );
- while ( _it.hasNext() )
- {
- _it.next();
- int keyI = _it.key(); // key (cell row)
- QMapIterator<int, QSharedPointer<Cell> > _iit( _it.value() ); // value
- while ( _iit.hasNext() )
- {
- _iit.next();
- int keyII = _iit.key(); // key (cell column)
- QSharedPointer<Cell> ptrCell = _iit.value(); // value
- CellLocation cl;
- cl.row = keyI;
- if ( keyI > (*maxRow) )
- {
- (*maxRow) = keyI;
- }
- cl.col = keyII;
- if ( keyII > (*maxCol) )
- {
- (*maxCol) = keyII;
- }
- cl.cell = ptrCell;
- ret.push_back( cl );
- }
- }
- return ret;
- }
- QT_END_NAMESPACE_XLSX
|