xlsxstyles.cpp 62 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334
  1. /****************************************************************************
  2. ** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
  3. ** All right reserved.
  4. **
  5. ** Permission is hereby granted, free of charge, to any person obtaining
  6. ** a copy of this software and associated documentation files (the
  7. ** "Software"), to deal in the Software without restriction, including
  8. ** without limitation the rights to use, copy, modify, merge, publish,
  9. ** distribute, sublicense, and/or sell copies of the Software, and to
  10. ** permit persons to whom the Software is furnished to do so, subject to
  11. ** the following conditions:
  12. **
  13. ** The above copyright notice and this permission notice shall be
  14. ** included in all copies or substantial portions of the Software.
  15. **
  16. ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  17. ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  18. ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  19. ** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  20. ** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  21. ** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  22. ** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23. **
  24. ****************************************************************************/
  25. #include "xlsxstyles_p.h"
  26. #include "xlsxformat_p.h"
  27. #include "xlsxutility_p.h"
  28. #include "xlsxcolor_p.h"
  29. #include <QXmlStreamWriter>
  30. #include <QXmlStreamReader>
  31. #include <QFile>
  32. #include <QMap>
  33. #include <QDataStream>
  34. #include <QDebug>
  35. #include <QBuffer>
  36. namespace QXlsx {
  37. /*
  38. When loading from existing .xlsx file. we should create a clean styles object.
  39. otherwise, default formats should be added.
  40. */
  41. Styles::Styles(CreateFlag flag)
  42. : AbstractOOXmlFile(flag), m_nextCustomNumFmtId(176), m_isIndexedColorsDefault(true)
  43. , m_emptyFormatAdded(false)
  44. {
  45. //!Fix me. Should the custom num fmt Id starts with 164 or 176 or others??
  46. //!Fix me! Where should we put these register code?
  47. if (QMetaType::type("XlsxColor") == QMetaType::UnknownType) {
  48. qRegisterMetaType<XlsxColor>("XlsxColor");
  49. qRegisterMetaTypeStreamOperators<XlsxColor>("XlsxColor");
  50. #if QT_VERSION >= 0x050200
  51. QMetaType::registerDebugStreamOperator<XlsxColor>();
  52. #endif
  53. }
  54. if (flag == F_NewFromScratch) {
  55. //Add default Format
  56. Format defaultFmt;
  57. addXfFormat(defaultFmt);
  58. //Add another fill format
  59. Format fillFmt;
  60. fillFmt.setFillPattern(Format::PatternGray125);
  61. m_fillsList.append(fillFmt);
  62. m_fillsHash.insert(fillFmt.fillKey(), fillFmt);
  63. }
  64. }
  65. Styles::~Styles()
  66. {
  67. }
  68. Format Styles::xfFormat(int idx) const
  69. {
  70. if (idx <0 || idx >= m_xf_formatsList.size())
  71. return Format();
  72. return m_xf_formatsList[idx];
  73. }
  74. Format Styles::dxfFormat(int idx) const
  75. {
  76. if (idx <0 || idx >= m_dxf_formatsList.size())
  77. return Format();
  78. return m_dxf_formatsList[idx];
  79. }
  80. void Styles::fixNumFmt(const Format &format)
  81. {
  82. if (!format.hasNumFmtData())
  83. return;
  84. if (format.hasProperty(FormatPrivate::P_NumFmt_Id)
  85. && !format.stringProperty(FormatPrivate::P_NumFmt_FormatCode).isEmpty()) {
  86. return;
  87. }
  88. if (m_builtinNumFmtsHash.isEmpty()) {
  89. m_builtinNumFmtsHash.insert(QStringLiteral("General"), 0);
  90. m_builtinNumFmtsHash.insert(QStringLiteral("0"), 1);
  91. m_builtinNumFmtsHash.insert(QStringLiteral("0.00"), 2);
  92. m_builtinNumFmtsHash.insert(QStringLiteral("#,##0"), 3);
  93. m_builtinNumFmtsHash.insert(QStringLiteral("#,##0.00"), 4);
  94. // m_builtinNumFmtsHash.insert(QStringLiteral("($#,##0_);($#,##0)"), 5);
  95. // m_builtinNumFmtsHash.insert(QStringLiteral("($#,##0_);[Red]($#,##0)"), 6);
  96. // m_builtinNumFmtsHash.insert(QStringLiteral("($#,##0.00_);($#,##0.00)"), 7);
  97. // m_builtinNumFmtsHash.insert(QStringLiteral("($#,##0.00_);[Red]($#,##0.00)"), 8);
  98. m_builtinNumFmtsHash.insert(QStringLiteral("0%"), 9);
  99. m_builtinNumFmtsHash.insert(QStringLiteral("0.00%"), 10);
  100. m_builtinNumFmtsHash.insert(QStringLiteral("0.00E+00"), 11);
  101. m_builtinNumFmtsHash.insert(QStringLiteral("# ?/?"), 12);
  102. m_builtinNumFmtsHash.insert(QStringLiteral("# ?\?/??"), 13);// Note: "??/" is a c++ trigraph, so escape one "?"
  103. m_builtinNumFmtsHash.insert(QStringLiteral("m/d/yy"), 14);
  104. m_builtinNumFmtsHash.insert(QStringLiteral("d-mmm-yy"), 15);
  105. m_builtinNumFmtsHash.insert(QStringLiteral("d-mmm"), 16);
  106. m_builtinNumFmtsHash.insert(QStringLiteral("mmm-yy"), 17);
  107. m_builtinNumFmtsHash.insert(QStringLiteral("h:mm AM/PM"), 18);
  108. m_builtinNumFmtsHash.insert(QStringLiteral("h:mm:ss AM/PM"), 19);
  109. m_builtinNumFmtsHash.insert(QStringLiteral("h:mm"), 20);
  110. m_builtinNumFmtsHash.insert(QStringLiteral("h:mm:ss"), 21);
  111. m_builtinNumFmtsHash.insert(QStringLiteral("m/d/yy h:mm"), 22);
  112. m_builtinNumFmtsHash.insert(QStringLiteral("(#,##0_);(#,##0)"), 37);
  113. m_builtinNumFmtsHash.insert(QStringLiteral("(#,##0_);[Red](#,##0)"), 38);
  114. m_builtinNumFmtsHash.insert(QStringLiteral("(#,##0.00_);(#,##0.00)"), 39);
  115. m_builtinNumFmtsHash.insert(QStringLiteral("(#,##0.00_);[Red](#,##0.00)"), 40);
  116. // m_builtinNumFmtsHash.insert(QStringLiteral("_(* #,##0_);_(* (#,##0);_(* \"-\"_);_(_)"), 41);
  117. // m_builtinNumFmtsHash.insert(QStringLiteral("_($* #,##0_);_($* (#,##0);_($* \"-\"_);_(_)"), 42);
  118. // m_builtinNumFmtsHash.insert(QStringLiteral("_(* #,##0.00_);_(* (#,##0.00);_(* \"-\"??_);_(_)"), 43);
  119. // m_builtinNumFmtsHash.insert(QStringLiteral("_($* #,##0.00_);_($* (#,##0.00);_($* \"-\"??_);_(_)"), 44);
  120. m_builtinNumFmtsHash.insert(QStringLiteral("mm:ss"), 45);
  121. m_builtinNumFmtsHash.insert(QStringLiteral("[h]:mm:ss"), 46);
  122. m_builtinNumFmtsHash.insert(QStringLiteral("mm:ss.0"), 47);
  123. m_builtinNumFmtsHash.insert(QStringLiteral("##0.0E+0"), 48);
  124. m_builtinNumFmtsHash.insert(QStringLiteral("@"), 49);
  125. }
  126. const QString str = format.numberFormat();
  127. if (!str.isEmpty()) {
  128. //Assign proper number format index
  129. if (m_builtinNumFmtsHash.contains(str)) {
  130. const_cast<Format *>(&format)->fixNumberFormat(m_builtinNumFmtsHash[str], str);
  131. } else if (m_customNumFmtsHash.contains(str)) {
  132. const_cast<Format *>(&format)->fixNumberFormat(m_customNumFmtsHash[str]->formatIndex, str);
  133. } else {
  134. //Assign a new fmt Id.
  135. const_cast<Format *>(&format)->fixNumberFormat(m_nextCustomNumFmtId, str);
  136. QSharedPointer<XlsxFormatNumberData> fmt(new XlsxFormatNumberData);
  137. fmt->formatIndex = m_nextCustomNumFmtId;
  138. fmt->formatString = str;
  139. m_customNumFmtIdMap.insert(m_nextCustomNumFmtId, fmt);
  140. m_customNumFmtsHash.insert(str, fmt);
  141. m_nextCustomNumFmtId += 1;
  142. }
  143. } else {
  144. int id = format.numberFormatIndex();
  145. //Assign proper format code, this is needed by dxf format
  146. if (m_customNumFmtIdMap.contains(id)) {
  147. const_cast<Format *>(&format)->fixNumberFormat(id, m_customNumFmtIdMap[id]->formatString);
  148. } else {
  149. QHashIterator<QString, int> it(m_builtinNumFmtsHash);
  150. bool find=false;
  151. while (it.hasNext()) {
  152. it.next();
  153. if (it.value() == id) {
  154. const_cast<Format *>(&format)->fixNumberFormat(id, it.key());
  155. find = true;
  156. break;
  157. }
  158. }
  159. if (!find) {
  160. //Wrong numFmt
  161. const_cast<Format *>(&format)->fixNumberFormat(id, QStringLiteral("General"));
  162. }
  163. }
  164. }
  165. }
  166. /*
  167. Assign index to Font/Fill/Border and Format
  168. When \a force is true, add the format to the format list, even other format has
  169. the same key have been in.
  170. This is useful when reading existing .xlsx files which may contains duplicated formats.
  171. */
  172. void Styles::addXfFormat(const Format &format, bool force)
  173. {
  174. if (format.isEmpty()) {
  175. //Try do something for empty Format.
  176. if (m_emptyFormatAdded && !force)
  177. return;
  178. m_emptyFormatAdded = true;
  179. }
  180. //numFmt
  181. if (format.hasNumFmtData() && !format.hasProperty(FormatPrivate::P_NumFmt_Id))
  182. fixNumFmt(format);
  183. //Font
  184. if (format.hasFontData() && !format.fontIndexValid()) {
  185. //Assign proper font index, if has font data.
  186. if (!m_fontsHash.contains(format.fontKey()))
  187. const_cast<Format *>(&format)->setFontIndex(m_fontsList.size());
  188. else
  189. const_cast<Format *>(&format)->setFontIndex(m_fontsHash[format.fontKey()].fontIndex());
  190. }
  191. if (!m_fontsHash.contains(format.fontKey())) {
  192. //Still a valid font if the format has no fontData. (All font properties are default)
  193. m_fontsList.append(format);
  194. m_fontsHash[format.fontKey()] = format;
  195. }
  196. //Fill
  197. if (format.hasFillData() && !format.fillIndexValid()) {
  198. //Assign proper fill index, if has fill data.
  199. if (!m_fillsHash.contains(format.fillKey()))
  200. const_cast<Format *>(&format)->setFillIndex(m_fillsList.size());
  201. else
  202. const_cast<Format *>(&format)->setFillIndex(m_fillsHash[format.fillKey()].fillIndex());
  203. }
  204. if (!m_fillsHash.contains(format.fillKey())) {
  205. //Still a valid fill if the format has no fillData. (All fill properties are default)
  206. m_fillsList.append(format);
  207. m_fillsHash[format.fillKey()] = format;
  208. }
  209. //Border
  210. if (format.hasBorderData() && !format.borderIndexValid()) {
  211. //Assign proper border index, if has border data.
  212. if (!m_bordersHash.contains(format.borderKey()))
  213. const_cast<Format *>(&format)->setBorderIndex(m_bordersList.size());
  214. else
  215. const_cast<Format *>(&format)->setBorderIndex(m_bordersHash[format.borderKey()].borderIndex());
  216. }
  217. if (!m_bordersHash.contains(format.borderKey())) {
  218. //Still a valid border if the format has no borderData. (All border properties are default)
  219. m_bordersList.append(format);
  220. m_bordersHash[format.borderKey()] = format;
  221. }
  222. //Format
  223. if (!format.isEmpty() && !format.xfIndexValid()) {
  224. if (m_xf_formatsHash.contains(format.formatKey()))
  225. const_cast<Format *>(&format)->setXfIndex(m_xf_formatsHash[format.formatKey()].xfIndex());
  226. else
  227. const_cast<Format *>(&format)->setXfIndex(m_xf_formatsList.size());
  228. }
  229. if (!m_xf_formatsHash.contains(format.formatKey()) || force) {
  230. m_xf_formatsList.append(format);
  231. m_xf_formatsHash[format.formatKey()] = format;
  232. }
  233. }
  234. void Styles::addDxfFormat(const Format &format, bool force)
  235. {
  236. //numFmt
  237. if (format.hasNumFmtData())
  238. fixNumFmt(format);
  239. if (!format.isEmpty() && !format.dxfIndexValid()) {
  240. if (m_dxf_formatsHash.contains(format.formatKey()))
  241. const_cast<Format *>(&format)->setDxfIndex(m_dxf_formatsHash[format.formatKey()].dxfIndex());
  242. else
  243. const_cast<Format *>(&format)->setDxfIndex(m_dxf_formatsList.size());
  244. }
  245. if (!m_dxf_formatsHash.contains(format.formatKey()) || force) {
  246. m_dxf_formatsList.append(format);
  247. m_dxf_formatsHash[format.formatKey()] = format;
  248. }
  249. }
  250. void Styles::saveToXmlFile(QIODevice *device) const
  251. {
  252. QXmlStreamWriter writer(device);
  253. writer.writeStartDocument(QStringLiteral("1.0"), true);
  254. writer.writeStartElement(QStringLiteral("styleSheet"));
  255. writer.writeAttribute(QStringLiteral("xmlns"), QStringLiteral("http://schemas.openxmlformats.org/spreadsheetml/2006/main"));
  256. writeNumFmts(writer);
  257. writeFonts(writer);
  258. writeFills(writer);
  259. writeBorders(writer);
  260. writer.writeStartElement(QStringLiteral("cellStyleXfs"));
  261. writer.writeAttribute(QStringLiteral("count"), QStringLiteral("1"));
  262. writer.writeStartElement(QStringLiteral("xf"));
  263. writer.writeAttribute(QStringLiteral("numFmtId"), QStringLiteral("0"));
  264. writer.writeAttribute(QStringLiteral("fontId"), QStringLiteral("0"));
  265. writer.writeAttribute(QStringLiteral("fillId"), QStringLiteral("0"));
  266. writer.writeAttribute(QStringLiteral("borderId"), QStringLiteral("0"));
  267. writer.writeEndElement();//xf
  268. writer.writeEndElement();//cellStyleXfs
  269. writeCellXfs(writer);
  270. writer.writeStartElement(QStringLiteral("cellStyles"));
  271. writer.writeAttribute(QStringLiteral("count"), QStringLiteral("1"));
  272. writer.writeStartElement(QStringLiteral("cellStyle"));
  273. writer.writeAttribute(QStringLiteral("name"), QStringLiteral("Normal"));
  274. writer.writeAttribute(QStringLiteral("xfId"), QStringLiteral("0"));
  275. writer.writeAttribute(QStringLiteral("builtinId"), QStringLiteral("0"));
  276. writer.writeEndElement();//cellStyle
  277. writer.writeEndElement();//cellStyles
  278. writeDxfs(writer);
  279. writer.writeStartElement(QStringLiteral("tableStyles"));
  280. writer.writeAttribute(QStringLiteral("count"), QStringLiteral("0"));
  281. writer.writeAttribute(QStringLiteral("defaultTableStyle"), QStringLiteral("TableStyleMedium9"));
  282. writer.writeAttribute(QStringLiteral("defaultPivotStyle"), QStringLiteral("PivotStyleLight16"));
  283. writer.writeEndElement();//tableStyles
  284. writeColors(writer);
  285. writer.writeEndElement();//styleSheet
  286. writer.writeEndDocument();
  287. }
  288. void Styles::writeNumFmts(QXmlStreamWriter &writer) const
  289. {
  290. if (m_customNumFmtIdMap.size() == 0)
  291. return;
  292. writer.writeStartElement(QStringLiteral("numFmts"));
  293. writer.writeAttribute(QStringLiteral("count"), QString::number(m_customNumFmtIdMap.count()));
  294. QMapIterator<int, QSharedPointer<XlsxFormatNumberData> > it(m_customNumFmtIdMap);
  295. while (it.hasNext()) {
  296. it.next();
  297. writer.writeEmptyElement(QStringLiteral("numFmt"));
  298. writer.writeAttribute(QStringLiteral("numFmtId"), QString::number(it.value()->formatIndex));
  299. writer.writeAttribute(QStringLiteral("formatCode"), it.value()->formatString);
  300. }
  301. writer.writeEndElement();//numFmts
  302. }
  303. /*
  304. */
  305. void Styles::writeFonts(QXmlStreamWriter &writer) const
  306. {
  307. writer.writeStartElement(QStringLiteral("fonts"));
  308. writer.writeAttribute(QStringLiteral("count"), QString::number(m_fontsList.count()));
  309. for (int i=0; i<m_fontsList.size(); ++i)
  310. writeFont(writer, m_fontsList[i], false);
  311. writer.writeEndElement();//fonts
  312. }
  313. void Styles::writeFont(QXmlStreamWriter &writer, const Format &format, bool isDxf) const
  314. {
  315. writer.writeStartElement(QStringLiteral("font"));
  316. //The condense and extend elements are mainly used in dxf format
  317. if (format.hasProperty(FormatPrivate::P_Font_Condense)
  318. && !format.boolProperty(FormatPrivate::P_Font_Condense)) {
  319. writer.writeEmptyElement(QStringLiteral("condense"));
  320. writer.writeAttribute(QStringLiteral("val"), QStringLiteral("0"));
  321. }
  322. if (format.hasProperty(FormatPrivate::P_Font_Extend)
  323. && !format.boolProperty(FormatPrivate::P_Font_Extend)) {
  324. writer.writeEmptyElement(QStringLiteral("extend"));
  325. writer.writeAttribute(QStringLiteral("val"), QStringLiteral("0"));
  326. }
  327. if (format.fontBold())
  328. writer.writeEmptyElement(QStringLiteral("b"));
  329. if (format.fontItalic())
  330. writer.writeEmptyElement(QStringLiteral("i"));
  331. if (format.fontStrikeOut())
  332. writer.writeEmptyElement(QStringLiteral("strike"));
  333. if (format.fontOutline())
  334. writer.writeEmptyElement(QStringLiteral("outline"));
  335. if (format.boolProperty(FormatPrivate::P_Font_Shadow))
  336. writer.writeEmptyElement(QStringLiteral("shadow"));
  337. if (format.hasProperty(FormatPrivate::P_Font_Underline)) {
  338. Format::FontUnderline u = format.fontUnderline();
  339. if (u != Format::FontUnderlineNone) {
  340. writer.writeEmptyElement(QStringLiteral("u"));
  341. if (u== Format::FontUnderlineDouble)
  342. writer.writeAttribute(QStringLiteral("val"), QStringLiteral("double"));
  343. else if (u == Format::FontUnderlineSingleAccounting)
  344. writer.writeAttribute(QStringLiteral("val"), QStringLiteral("singleAccounting"));
  345. else if (u == Format::FontUnderlineDoubleAccounting)
  346. writer.writeAttribute(QStringLiteral("val"), QStringLiteral("doubleAccounting"));
  347. }
  348. }
  349. if (format.hasProperty(FormatPrivate::P_Font_Script)) {
  350. Format::FontScript s = format.fontScript();
  351. if (s != Format::FontScriptNormal) {
  352. writer.writeEmptyElement(QStringLiteral("vertAlign"));
  353. if (s == Format::FontScriptSuper)
  354. writer.writeAttribute(QStringLiteral("val"), QStringLiteral("superscript"));
  355. else
  356. writer.writeAttribute(QStringLiteral("val"), QStringLiteral("subscript"));
  357. }
  358. }
  359. if (!isDxf && format.hasProperty(FormatPrivate::P_Font_Size)) {
  360. writer.writeEmptyElement(QStringLiteral("sz"));
  361. writer.writeAttribute(QStringLiteral("val"), QString::number(format.fontSize()));
  362. }
  363. if (format.hasProperty(FormatPrivate::P_Font_Color)) {
  364. XlsxColor color = format.property(FormatPrivate::P_Font_Color).value<XlsxColor>();
  365. color.saveToXml(writer);
  366. }
  367. if (!isDxf) {
  368. if (!format.fontName().isEmpty()) {
  369. writer.writeEmptyElement(QStringLiteral("name"));
  370. writer.writeAttribute(QStringLiteral("val"), format.fontName());
  371. }
  372. if (format.hasProperty(FormatPrivate::P_Font_Charset)) {
  373. writer.writeEmptyElement(QStringLiteral("charset"));
  374. writer.writeAttribute(QStringLiteral("val"), QString::number(format.intProperty(FormatPrivate::P_Font_Charset)));
  375. }
  376. if (format.hasProperty(FormatPrivate::P_Font_Family)) {
  377. writer.writeEmptyElement(QStringLiteral("family"));
  378. writer.writeAttribute(QStringLiteral("val"), QString::number(format.intProperty(FormatPrivate::P_Font_Family)));
  379. }
  380. if (format.hasProperty(FormatPrivate::P_Font_Scheme)) {
  381. writer.writeEmptyElement(QStringLiteral("scheme"));
  382. writer.writeAttribute(QStringLiteral("val"), format.stringProperty(FormatPrivate::P_Font_Scheme));
  383. }
  384. }
  385. writer.writeEndElement(); //font
  386. }
  387. void Styles::writeFills(QXmlStreamWriter &writer) const
  388. {
  389. writer.writeStartElement(QStringLiteral("fills"));
  390. writer.writeAttribute(QStringLiteral("count"), QString::number(m_fillsList.size()));
  391. for (int i=0; i<m_fillsList.size(); ++i)
  392. writeFill(writer, m_fillsList[i]);
  393. writer.writeEndElement(); //fills
  394. }
  395. void Styles::writeFill(QXmlStreamWriter &writer, const Format &fill, bool isDxf) const
  396. {
  397. static QMap<int, QString> patternStrings;
  398. if (patternStrings.isEmpty()) {
  399. patternStrings[Format::PatternNone] = QStringLiteral("none");
  400. patternStrings[Format::PatternSolid] = QStringLiteral("solid");
  401. patternStrings[Format::PatternMediumGray] = QStringLiteral("mediumGray");
  402. patternStrings[Format::PatternDarkGray] = QStringLiteral("darkGray");
  403. patternStrings[Format::PatternLightGray] = QStringLiteral("lightGray");
  404. patternStrings[Format::PatternDarkHorizontal] = QStringLiteral("darkHorizontal");
  405. patternStrings[Format::PatternDarkVertical] = QStringLiteral("darkVertical");
  406. patternStrings[Format::PatternDarkDown] = QStringLiteral("darkDown");
  407. patternStrings[Format::PatternDarkUp] = QStringLiteral("darkUp");
  408. patternStrings[Format::PatternDarkGrid] = QStringLiteral("darkGrid");
  409. patternStrings[Format::PatternDarkTrellis] = QStringLiteral("darkTrellis");
  410. patternStrings[Format::PatternLightHorizontal] = QStringLiteral("lightHorizontal");
  411. patternStrings[Format::PatternLightVertical] = QStringLiteral("lightVertical");
  412. patternStrings[Format::PatternLightDown] = QStringLiteral("lightDown");
  413. patternStrings[Format::PatternLightUp] = QStringLiteral("lightUp");
  414. patternStrings[Format::PatternLightTrellis] = QStringLiteral("lightTrellis");
  415. patternStrings[Format::PatternGray125] = QStringLiteral("gray125");
  416. patternStrings[Format::PatternGray0625] = QStringLiteral("gray0625");
  417. patternStrings[Format::PatternLightGrid] = QStringLiteral("lightGrid");
  418. }
  419. writer.writeStartElement(QStringLiteral("fill"));
  420. writer.writeStartElement(QStringLiteral("patternFill"));
  421. Format::FillPattern pattern = fill.fillPattern();
  422. // For normal fill formats, Excel prefer to outputing the default "none" attribute
  423. // But for dxf, Excel prefer to omiting the default "none"
  424. // Though not make any difference, but it make easier to compare origin files with generate files during debug
  425. if (!(pattern == Format::PatternNone && isDxf))
  426. writer.writeAttribute(QStringLiteral("patternType"), patternStrings[pattern]);
  427. // For a solid fill, Excel reverses the role of foreground and background colours
  428. if (fill.fillPattern() == Format::PatternSolid) {
  429. if (fill.hasProperty(FormatPrivate::P_Fill_BgColor))
  430. fill.property(FormatPrivate::P_Fill_BgColor).value<XlsxColor>().saveToXml(writer, QStringLiteral("fgColor"));
  431. if (fill.hasProperty(FormatPrivate::P_Fill_FgColor))
  432. fill.property(FormatPrivate::P_Fill_FgColor).value<XlsxColor>().saveToXml(writer, QStringLiteral("bgColor"));
  433. } else {
  434. if (fill.hasProperty(FormatPrivate::P_Fill_FgColor))
  435. fill.property(FormatPrivate::P_Fill_FgColor).value<XlsxColor>().saveToXml(writer, QStringLiteral("fgColor"));
  436. if (fill.hasProperty(FormatPrivate::P_Fill_BgColor))
  437. fill.property(FormatPrivate::P_Fill_BgColor).value<XlsxColor>().saveToXml(writer, QStringLiteral("bgColor"));
  438. }
  439. writer.writeEndElement();//patternFill
  440. writer.writeEndElement();//fill
  441. }
  442. void Styles::writeBorders(QXmlStreamWriter &writer) const
  443. {
  444. writer.writeStartElement(QStringLiteral("borders"));
  445. writer.writeAttribute(QStringLiteral("count"), QString::number(m_bordersList.count()));
  446. for (int i=0; i<m_bordersList.size(); ++i)
  447. writeBorder(writer, m_bordersList[i]);
  448. writer.writeEndElement();//borders
  449. }
  450. void Styles::writeBorder(QXmlStreamWriter &writer, const Format &border, bool isDxf) const
  451. {
  452. writer.writeStartElement(QStringLiteral("border"));
  453. if (border.hasProperty(FormatPrivate::P_Border_DiagonalType)) {
  454. Format::DiagonalBorderType t = border.diagonalBorderType();
  455. if (t == Format::DiagonalBorderUp) {
  456. writer.writeAttribute(QStringLiteral("diagonalUp"), QStringLiteral("1"));
  457. } else if (t == Format::DiagonalBorderDown) {
  458. writer.writeAttribute(QStringLiteral("diagonalDown"), QStringLiteral("1"));
  459. } else if (t == Format::DiagnoalBorderBoth) {
  460. writer.writeAttribute(QStringLiteral("diagonalUp"), QStringLiteral("1"));
  461. writer.writeAttribute(QStringLiteral("diagonalDown"), QStringLiteral("1"));
  462. }
  463. }
  464. writeSubBorder(writer, QStringLiteral("left"), border.leftBorderStyle(), border.property(FormatPrivate::P_Border_LeftColor).value<XlsxColor>());
  465. writeSubBorder(writer, QStringLiteral("right"), border.rightBorderStyle(), border.property(FormatPrivate::P_Border_RightColor).value<XlsxColor>());
  466. writeSubBorder(writer, QStringLiteral("top"), border.topBorderStyle(), border.property(FormatPrivate::P_Border_TopColor).value<XlsxColor>());
  467. writeSubBorder(writer, QStringLiteral("bottom"), border.bottomBorderStyle(), border.property(FormatPrivate::P_Border_BottomColor).value<XlsxColor>());
  468. //Condition DXF formats don't allow diagonal style
  469. if (!isDxf)
  470. writeSubBorder(writer, QStringLiteral("diagonal"), border.diagonalBorderStyle(), border.property(FormatPrivate::P_Border_DiagonalColor).value<XlsxColor>());
  471. if (isDxf) {
  472. // writeSubBorder(wirter, QStringLiteral("vertical"), );
  473. // writeSubBorder(writer, QStringLiteral("horizontal"), );
  474. }
  475. writer.writeEndElement();//border
  476. }
  477. void Styles::writeSubBorder(QXmlStreamWriter &writer, const QString &type, int style, const XlsxColor &color) const
  478. {
  479. if (style == Format::BorderNone) {
  480. writer.writeEmptyElement(type);
  481. return;
  482. }
  483. static QMap<int, QString> stylesString;
  484. if (stylesString.isEmpty()) {
  485. stylesString[Format::BorderNone] = QStringLiteral("none");
  486. stylesString[Format::BorderThin] = QStringLiteral("thin");
  487. stylesString[Format::BorderMedium] = QStringLiteral("medium");
  488. stylesString[Format::BorderDashed] = QStringLiteral("dashed");
  489. stylesString[Format::BorderDotted] = QStringLiteral("dotted");
  490. stylesString[Format::BorderThick] = QStringLiteral("thick");
  491. stylesString[Format::BorderDouble] = QStringLiteral("double");
  492. stylesString[Format::BorderHair] = QStringLiteral("hair");
  493. stylesString[Format::BorderMediumDashed] = QStringLiteral("mediumDashed");
  494. stylesString[Format::BorderDashDot] = QStringLiteral("dashDot");
  495. stylesString[Format::BorderMediumDashDot] = QStringLiteral("mediumDashDot");
  496. stylesString[Format::BorderDashDotDot] = QStringLiteral("dashDotDot");
  497. stylesString[Format::BorderMediumDashDotDot] = QStringLiteral("mediumDashDotDot");
  498. stylesString[Format::BorderSlantDashDot] = QStringLiteral("slantDashDot");
  499. }
  500. writer.writeStartElement(type);
  501. writer.writeAttribute(QStringLiteral("style"), stylesString[style]);
  502. color.saveToXml(writer); //write color element
  503. writer.writeEndElement();//type
  504. }
  505. void Styles::writeCellXfs(QXmlStreamWriter &writer) const
  506. {
  507. writer.writeStartElement(QStringLiteral("cellXfs"));
  508. writer.writeAttribute(QStringLiteral("count"), QString::number(m_xf_formatsList.size()));
  509. foreach (const Format &format, m_xf_formatsList) {
  510. int xf_id = 0;
  511. writer.writeStartElement(QStringLiteral("xf"));
  512. writer.writeAttribute(QStringLiteral("numFmtId"), QString::number(format.numberFormatIndex()));
  513. writer.writeAttribute(QStringLiteral("fontId"), QString::number(format.fontIndex()));
  514. writer.writeAttribute(QStringLiteral("fillId"), QString::number(format.fillIndex()));
  515. writer.writeAttribute(QStringLiteral("borderId"), QString::number(format.borderIndex()));
  516. writer.writeAttribute(QStringLiteral("xfId"), QString::number(xf_id));
  517. if (format.hasNumFmtData())
  518. writer.writeAttribute(QStringLiteral("applyNumberFormat"), QStringLiteral("1"));
  519. if (format.hasFontData())
  520. writer.writeAttribute(QStringLiteral("applyFont"), QStringLiteral("1"));
  521. if (format.hasFillData())
  522. writer.writeAttribute(QStringLiteral("applyFill"), QStringLiteral("1"));
  523. if (format.hasBorderData())
  524. writer.writeAttribute(QStringLiteral("applyBorder"), QStringLiteral("1"));
  525. if (format.hasAlignmentData())
  526. writer.writeAttribute(QStringLiteral("applyAlignment"), QStringLiteral("1"));
  527. if (format.hasAlignmentData()) {
  528. writer.writeEmptyElement(QStringLiteral("alignment"));
  529. if (format.hasProperty(FormatPrivate::P_Alignment_AlignH)) {
  530. switch (format.horizontalAlignment()) {
  531. case Format::AlignLeft:
  532. writer.writeAttribute(QStringLiteral("horizontal"), QStringLiteral("left"));
  533. break;
  534. case Format::AlignHCenter:
  535. writer.writeAttribute(QStringLiteral("horizontal"), QStringLiteral("center"));
  536. break;
  537. case Format::AlignRight:
  538. writer.writeAttribute(QStringLiteral("horizontal"), QStringLiteral("right"));
  539. break;
  540. case Format::AlignHFill:
  541. writer.writeAttribute(QStringLiteral("horizontal"), QStringLiteral("fill"));
  542. break;
  543. case Format::AlignHJustify:
  544. writer.writeAttribute(QStringLiteral("horizontal"), QStringLiteral("justify"));
  545. break;
  546. case Format::AlignHMerge:
  547. writer.writeAttribute(QStringLiteral("horizontal"), QStringLiteral("centerContinuous"));
  548. break;
  549. case Format::AlignHDistributed:
  550. writer.writeAttribute(QStringLiteral("horizontal"), QStringLiteral("distributed"));
  551. break;
  552. default:
  553. break;
  554. }
  555. }
  556. if (format.hasProperty(FormatPrivate::P_Alignment_AlignV)) {
  557. switch (format.verticalAlignment()) {
  558. case Format::AlignTop:
  559. writer.writeAttribute(QStringLiteral("vertical"), QStringLiteral("top"));
  560. break;
  561. case Format::AlignVCenter:
  562. writer.writeAttribute(QStringLiteral("vertical"), QStringLiteral("center"));
  563. break;
  564. case Format::AlignVJustify:
  565. writer.writeAttribute(QStringLiteral("vertical"), QStringLiteral("justify"));
  566. break;
  567. case Format::AlignVDistributed:
  568. writer.writeAttribute(QStringLiteral("vertical"), QStringLiteral("distributed"));
  569. break;
  570. default:
  571. break;
  572. }
  573. }
  574. if (format.hasProperty(FormatPrivate::P_Alignment_Indent))
  575. writer.writeAttribute(QStringLiteral("indent"), QString::number(format.indent()));
  576. if (format.hasProperty(FormatPrivate::P_Alignment_Wrap) && format.textWrap())
  577. writer.writeAttribute(QStringLiteral("wrapText"), QStringLiteral("1"));
  578. if (format.hasProperty(FormatPrivate::P_Alignment_ShinkToFit) && format.shrinkToFit())
  579. writer.writeAttribute(QStringLiteral("shrinkToFit"), QStringLiteral("1"));
  580. if (format.hasProperty(FormatPrivate::P_Alignment_Rotation))
  581. writer.writeAttribute(QStringLiteral("textRotation"), QString::number(format.rotation()));
  582. }
  583. writer.writeEndElement();//xf
  584. }
  585. writer.writeEndElement();//cellXfs
  586. }
  587. void Styles::writeDxfs(QXmlStreamWriter &writer) const
  588. {
  589. writer.writeStartElement(QStringLiteral("dxfs"));
  590. writer.writeAttribute(QStringLiteral("count"), QString::number(m_dxf_formatsList.size()));
  591. foreach (const Format &format, m_dxf_formatsList)
  592. writeDxf(writer, format);
  593. writer.writeEndElement(); //dxfs
  594. }
  595. void Styles::writeDxf(QXmlStreamWriter &writer, const Format &format) const
  596. {
  597. writer.writeStartElement(QStringLiteral("dxf"));
  598. if (format.hasFontData())
  599. writeFont(writer, format, true);
  600. if (format.hasNumFmtData()) {
  601. writer.writeEmptyElement(QStringLiteral("numFmt"));
  602. writer.writeAttribute(QStringLiteral("numFmtId"), QString::number(format.numberFormatIndex()));
  603. writer.writeAttribute(QStringLiteral("formatCode"), format.numberFormat());
  604. }
  605. if (format.hasFillData())
  606. writeFill(writer, format, true);
  607. if (format.hasBorderData())
  608. writeBorder(writer, format, true);
  609. writer.writeEndElement();//dxf
  610. }
  611. void Styles::writeColors(QXmlStreamWriter &writer) const
  612. {
  613. if (m_isIndexedColorsDefault) //Don't output the default indexdeColors
  614. return;
  615. writer.writeStartElement(QStringLiteral("colors"));
  616. writer.writeStartElement(QStringLiteral("indexedColors"));
  617. foreach(QColor color, m_indexedColors) {
  618. writer.writeEmptyElement(QStringLiteral("rgbColor"));
  619. writer.writeAttribute(QStringLiteral("rgb"), XlsxColor::toARGBString(color));
  620. }
  621. writer.writeEndElement();//indexedColors
  622. writer.writeEndElement();//colors
  623. }
  624. bool Styles::readNumFmts(QXmlStreamReader &reader)
  625. {
  626. Q_ASSERT(reader.name() == QLatin1String("numFmts"));
  627. QXmlStreamAttributes attributes = reader.attributes();
  628. bool hasCount = attributes.hasAttribute(QLatin1String("count"));
  629. int count = hasCount ? attributes.value(QLatin1String("count")).toString().toInt() : -1;
  630. //Read utill we find the numFmts end tag or ....
  631. while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
  632. && reader.name() == QLatin1String("numFmts"))) {
  633. reader.readNextStartElement();
  634. if (reader.tokenType() == QXmlStreamReader::StartElement) {
  635. if (reader.name() == QLatin1String("numFmt")) {
  636. QXmlStreamAttributes attributes = reader.attributes();
  637. QSharedPointer<XlsxFormatNumberData> fmt (new XlsxFormatNumberData);
  638. fmt->formatIndex = attributes.value(QLatin1String("numFmtId")).toString().toInt();
  639. fmt->formatString = attributes.value(QLatin1String("formatCode")).toString();
  640. if (fmt->formatIndex >= m_nextCustomNumFmtId)
  641. m_nextCustomNumFmtId = fmt->formatIndex + 1;
  642. m_customNumFmtIdMap.insert(fmt->formatIndex, fmt);
  643. m_customNumFmtsHash.insert(fmt->formatString, fmt);
  644. }
  645. }
  646. }
  647. if (reader.hasError())
  648. qWarning()<<reader.errorString();
  649. if (hasCount && (count != m_customNumFmtIdMap.size()))
  650. qWarning("error read custom numFmts");
  651. return true;
  652. }
  653. bool Styles::readFonts(QXmlStreamReader &reader)
  654. {
  655. Q_ASSERT(reader.name() == QLatin1String("fonts"));
  656. QXmlStreamAttributes attributes = reader.attributes();
  657. bool hasCount = attributes.hasAttribute(QLatin1String("count"));
  658. int count = hasCount ? attributes.value(QLatin1String("count")).toString().toInt() : -1;
  659. while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
  660. && reader.name() == QLatin1String("fonts"))) {
  661. reader.readNextStartElement();
  662. if (reader.tokenType() == QXmlStreamReader::StartElement) {
  663. if (reader.name() == QLatin1String("font")) {
  664. Format format;
  665. readFont(reader, format);
  666. m_fontsList.append(format);
  667. m_fontsHash.insert(format.fontKey(), format);
  668. if (format.isValid())
  669. format.setFontIndex(m_fontsList.size()-1);
  670. }
  671. }
  672. }
  673. if (reader.hasError())
  674. qWarning()<<reader.errorString();
  675. if (hasCount && (count != m_fontsList.size()))
  676. qWarning("error read fonts");
  677. return true;
  678. }
  679. bool Styles::readFont(QXmlStreamReader &reader, Format &format)
  680. {
  681. Q_ASSERT(reader.name() == QLatin1String("font"));
  682. while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
  683. && reader.name() == QLatin1String("font"))) {
  684. reader.readNextStartElement();
  685. if (reader.tokenType() == QXmlStreamReader::StartElement) {
  686. QXmlStreamAttributes attributes = reader.attributes();
  687. if (reader.name() == QLatin1String("name")) {
  688. format.setFontName(attributes.value(QLatin1String("val")).toString());
  689. } else if (reader.name() == QLatin1String("charset")) {
  690. format.setProperty(FormatPrivate::P_Font_Charset, attributes.value(QLatin1String("val")).toString().toInt());
  691. } else if (reader.name() == QLatin1String("family")) {
  692. format.setProperty(FormatPrivate::P_Font_Family, attributes.value(QLatin1String("val")).toString().toInt());
  693. } else if (reader.name() == QLatin1String("b")) {
  694. format.setFontBold(true);
  695. } else if (reader.name() == QLatin1String("i")) {
  696. format.setFontItalic(true);
  697. } else if (reader.name() == QLatin1String("strike")) {
  698. format.setFontStrikeOut(true);
  699. } else if (reader.name() == QLatin1String("outline")) {
  700. format.setFontOutline(true);
  701. } else if (reader.name() == QLatin1String("shadow")) {
  702. format.setProperty(FormatPrivate::P_Font_Shadow, true);
  703. } else if (reader.name() == QLatin1String("condense")) {
  704. format.setProperty(FormatPrivate::P_Font_Condense, attributes.value(QLatin1String("val")).toString().toInt());
  705. } else if (reader.name() == QLatin1String("extend")) {
  706. format.setProperty(FormatPrivate::P_Font_Extend, attributes.value(QLatin1String("val")).toString().toInt());
  707. } else if (reader.name() == QLatin1String("color")) {
  708. XlsxColor color;
  709. color.loadFromXml(reader);
  710. format.setProperty(FormatPrivate::P_Font_Color, color);
  711. } else if (reader.name() == QLatin1String("sz")) {
  712. int sz = attributes.value(QLatin1String("val")).toString().toInt();
  713. format.setFontSize(sz);
  714. } else if (reader.name() == QLatin1String("u")) {
  715. QString value = attributes.value(QLatin1String("val")).toString();
  716. if (value == QLatin1String("double"))
  717. format.setFontUnderline(Format::FontUnderlineDouble);
  718. else if (value == QLatin1String("doubleAccounting"))
  719. format.setFontUnderline(Format::FontUnderlineDoubleAccounting);
  720. else if (value == QLatin1String("singleAccounting"))
  721. format.setFontUnderline(Format::FontUnderlineSingleAccounting);
  722. else
  723. format.setFontUnderline(Format::FontUnderlineSingle);
  724. } else if (reader.name() == QLatin1String("vertAlign")) {
  725. QString value = attributes.value(QLatin1String("val")).toString();
  726. if (value == QLatin1String("superscript"))
  727. format.setFontScript(Format::FontScriptSuper);
  728. else if (value == QLatin1String("subscript"))
  729. format.setFontScript(Format::FontScriptSub);
  730. } else if (reader.name() == QLatin1String("scheme")) {
  731. format.setProperty(FormatPrivate::P_Font_Scheme, attributes.value(QLatin1String("val")).toString());
  732. }
  733. }
  734. }
  735. return true;
  736. }
  737. bool Styles::readFills(QXmlStreamReader &reader)
  738. {
  739. Q_ASSERT(reader.name() == QLatin1String("fills"));
  740. QXmlStreamAttributes attributes = reader.attributes();
  741. bool hasCount = attributes.hasAttribute(QLatin1String("count"));
  742. int count = hasCount ? attributes.value(QLatin1String("count")).toString().toInt() : -1;
  743. while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
  744. && reader.name() == QLatin1String("fills"))) {
  745. reader.readNextStartElement();
  746. if (reader.tokenType() == QXmlStreamReader::StartElement) {
  747. if (reader.name() == QLatin1String("fill")) {
  748. Format fill;
  749. readFill(reader, fill);
  750. m_fillsList.append(fill);
  751. m_fillsHash.insert(fill.fillKey(), fill);
  752. if (fill.isValid())
  753. fill.setFillIndex(m_fillsList.size()-1);
  754. }
  755. }
  756. }
  757. if (reader.hasError())
  758. qWarning()<<reader.errorString();
  759. if (hasCount && (count != m_fillsList.size()))
  760. qWarning("error read fills");
  761. return true;
  762. }
  763. bool Styles::readFill(QXmlStreamReader &reader, Format &fill)
  764. {
  765. Q_ASSERT(reader.name() == QLatin1String("fill"));
  766. static QMap<QString, Format::FillPattern> patternValues;
  767. if (patternValues.isEmpty()) {
  768. patternValues[QStringLiteral("none")] = Format::PatternNone;
  769. patternValues[QStringLiteral("solid")] = Format::PatternSolid;
  770. patternValues[QStringLiteral("mediumGray")] = Format::PatternMediumGray;
  771. patternValues[QStringLiteral("darkGray")] = Format::PatternDarkGray;
  772. patternValues[QStringLiteral("lightGray")] = Format::PatternLightGray;
  773. patternValues[QStringLiteral("darkHorizontal")] = Format::PatternDarkHorizontal;
  774. patternValues[QStringLiteral("darkVertical")] = Format::PatternDarkVertical;
  775. patternValues[QStringLiteral("darkDown")] = Format::PatternDarkDown;
  776. patternValues[QStringLiteral("darkUp")] = Format::PatternDarkUp;
  777. patternValues[QStringLiteral("darkGrid")] = Format::PatternDarkGrid;
  778. patternValues[QStringLiteral("darkTrellis")] = Format::PatternDarkTrellis;
  779. patternValues[QStringLiteral("lightHorizontal")] = Format::PatternLightHorizontal;
  780. patternValues[QStringLiteral("lightVertical")] = Format::PatternLightVertical;
  781. patternValues[QStringLiteral("lightDown")] = Format::PatternLightDown;
  782. patternValues[QStringLiteral("lightUp")] = Format::PatternLightUp;
  783. patternValues[QStringLiteral("lightTrellis")] = Format::PatternLightTrellis;
  784. patternValues[QStringLiteral("gray125")] = Format::PatternGray125;
  785. patternValues[QStringLiteral("gray0625")] = Format::PatternGray0625;
  786. patternValues[QStringLiteral("lightGrid")] = Format::PatternLightGrid;
  787. }
  788. while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement && reader.name() == QLatin1String("fill"))) {
  789. reader.readNextStartElement();
  790. if (reader.tokenType() == QXmlStreamReader::StartElement) {
  791. if (reader.name() == QLatin1String("patternFill")) {
  792. QXmlStreamAttributes attributes = reader.attributes();
  793. if (attributes.hasAttribute(QLatin1String("patternType"))) {
  794. QString pattern = attributes.value(QLatin1String("patternType")).toString();
  795. fill.setFillPattern(patternValues.contains(pattern) ? patternValues[pattern] : Format::PatternNone);
  796. //parse foreground and background colors if they exist
  797. while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement && reader.name() == QLatin1String("patternFill"))) {
  798. reader.readNextStartElement();
  799. if (reader.tokenType() == QXmlStreamReader::StartElement) {
  800. if (reader.name() == QLatin1String("fgColor")) {
  801. XlsxColor c;
  802. c.loadFromXml(reader);
  803. if (fill.fillPattern() == Format::PatternSolid)
  804. fill.setProperty(FormatPrivate::P_Fill_BgColor, c);
  805. else
  806. fill.setProperty(FormatPrivate::P_Fill_FgColor, c);
  807. } else if (reader.name() == QLatin1String("bgColor")) {
  808. XlsxColor c;
  809. c.loadFromXml(reader);
  810. if (fill.fillPattern() == Format::PatternSolid)
  811. fill.setProperty(FormatPrivate::P_Fill_FgColor, c);
  812. else
  813. fill.setProperty(FormatPrivate::P_Fill_BgColor, c);
  814. }
  815. }
  816. }
  817. }
  818. }
  819. }
  820. }
  821. return true;
  822. }
  823. bool Styles::readBorders(QXmlStreamReader &reader)
  824. {
  825. Q_ASSERT(reader.name() == QLatin1String("borders"));
  826. QXmlStreamAttributes attributes = reader.attributes();
  827. bool hasCount = attributes.hasAttribute(QLatin1String("count"));
  828. int count = hasCount ? attributes.value(QLatin1String("count")).toString().toInt() : -1;
  829. while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
  830. && reader.name() == QLatin1String("borders"))) {
  831. reader.readNextStartElement();
  832. if (reader.tokenType() == QXmlStreamReader::StartElement) {
  833. if (reader.name() == QLatin1String("border")) {
  834. Format border;
  835. readBorder(reader, border);
  836. m_bordersList.append(border);
  837. m_bordersHash.insert(border.borderKey(), border);
  838. if (border.isValid())
  839. border.setBorderIndex(m_bordersList.size()-1);
  840. }
  841. }
  842. }
  843. if (reader.hasError())
  844. qWarning()<<reader.errorString();
  845. if (hasCount && (count != m_bordersList.size()))
  846. qWarning("error read borders");
  847. return true;
  848. }
  849. bool Styles::readBorder(QXmlStreamReader &reader, Format &border)
  850. {
  851. Q_ASSERT(reader.name() == QLatin1String("border"));
  852. QXmlStreamAttributes attributes = reader.attributes();
  853. bool isUp = attributes.hasAttribute(QLatin1String("diagonalUp"));
  854. bool isDown = attributes.hasAttribute(QLatin1String("diagonalUp"));
  855. if (isUp && isDown)
  856. border.setDiagonalBorderType(Format::DiagnoalBorderBoth);
  857. else if (isUp)
  858. border.setDiagonalBorderType(Format::DiagonalBorderUp);
  859. else if (isDown)
  860. border.setDiagonalBorderType(Format::DiagonalBorderDown);
  861. while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement && reader.name() == QLatin1String("border"))) {
  862. reader.readNextStartElement();
  863. if (reader.tokenType() == QXmlStreamReader::StartElement) {
  864. if (reader.name() == QLatin1String("left") || reader.name() == QLatin1String("right")
  865. || reader.name() == QLatin1String("top") || reader.name() == QLatin1String("bottom")
  866. || reader.name() == QLatin1String("diagonal") ) {
  867. Format::BorderStyle style(Format::BorderNone);
  868. XlsxColor color;
  869. readSubBorder(reader, reader.name().toString(), style, color);
  870. if (reader.name() == QLatin1String("left")) {
  871. border.setLeftBorderStyle(style);
  872. if (!color.isInvalid())
  873. border.setProperty(FormatPrivate::P_Border_LeftColor, color);
  874. } else if (reader.name() == QLatin1String("right")) {
  875. border.setRightBorderStyle(style);
  876. if (!color.isInvalid())
  877. border.setProperty(FormatPrivate::P_Border_RightColor, color);
  878. } else if (reader.name() == QLatin1String("top")) {
  879. border.setTopBorderStyle(style);
  880. if (!color.isInvalid())
  881. border.setProperty(FormatPrivate::P_Border_TopColor, color);
  882. } else if (reader.name() == QLatin1String("bottom")) {
  883. border.setBottomBorderStyle(style);
  884. if (!color.isInvalid())
  885. border.setProperty(FormatPrivate::P_Border_BottomColor, color);
  886. } else if (reader.name() == QLatin1String("diagonal")) {
  887. border.setDiagonalBorderStyle(style);
  888. if (!color.isInvalid())
  889. border.setProperty(FormatPrivate::P_Border_DiagonalColor, color);
  890. }
  891. }
  892. }
  893. if (reader.tokenType() == QXmlStreamReader::EndElement && reader.name() == QLatin1String("border"))
  894. break;
  895. }
  896. return true;
  897. }
  898. bool Styles::readSubBorder(QXmlStreamReader &reader, const QString &name, Format::BorderStyle &style, XlsxColor &color)
  899. {
  900. Q_ASSERT(reader.name() == name);
  901. static QMap<QString, Format::BorderStyle> stylesStringsMap;
  902. if (stylesStringsMap.isEmpty()) {
  903. stylesStringsMap[QStringLiteral("none")] = Format::BorderNone;
  904. stylesStringsMap[QStringLiteral("thin")] = Format::BorderThin;
  905. stylesStringsMap[QStringLiteral("medium")] = Format::BorderMedium;
  906. stylesStringsMap[QStringLiteral("dashed")] = Format::BorderDashed;
  907. stylesStringsMap[QStringLiteral("dotted")] = Format::BorderDotted;
  908. stylesStringsMap[QStringLiteral("thick")] = Format::BorderThick;
  909. stylesStringsMap[QStringLiteral("double")] = Format::BorderDouble;
  910. stylesStringsMap[QStringLiteral("hair")] = Format::BorderHair;
  911. stylesStringsMap[QStringLiteral("mediumDashed")] = Format::BorderMediumDashed;
  912. stylesStringsMap[QStringLiteral("dashDot")] = Format::BorderDashDot;
  913. stylesStringsMap[QStringLiteral("mediumDashDot")] = Format::BorderMediumDashDot;
  914. stylesStringsMap[QStringLiteral("dashDotDot")] = Format::BorderDashDotDot;
  915. stylesStringsMap[QStringLiteral("mediumDashDotDot")] = Format::BorderMediumDashDotDot;
  916. stylesStringsMap[QStringLiteral("slantDashDot")] = Format::BorderSlantDashDot;
  917. }
  918. QXmlStreamAttributes attributes = reader.attributes();
  919. if (attributes.hasAttribute(QLatin1String("style"))) {
  920. QString styleString = attributes.value(QLatin1String("style")).toString();
  921. if (stylesStringsMap.contains(styleString)) {
  922. //get style
  923. style = stylesStringsMap[styleString];
  924. while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement && reader.name() == name)) {
  925. reader.readNextStartElement();
  926. if (reader.tokenType() == QXmlStreamReader::StartElement) {
  927. if (reader.name() == QLatin1String("color"))
  928. color.loadFromXml(reader);
  929. }
  930. }
  931. }
  932. }
  933. return true;
  934. }
  935. bool Styles::readCellXfs(QXmlStreamReader &reader)
  936. {
  937. Q_ASSERT(reader.name() == QLatin1String("cellXfs"));
  938. QXmlStreamAttributes attributes = reader.attributes();
  939. bool hasCount = attributes.hasAttribute(QLatin1String("count"));
  940. int count = hasCount ? attributes.value(QLatin1String("count")).toString().toInt() : -1;
  941. while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
  942. && reader.name() == QLatin1String("cellXfs"))) {
  943. reader.readNextStartElement();
  944. if (reader.tokenType() == QXmlStreamReader::StartElement) {
  945. if (reader.name() == QLatin1String("xf")) {
  946. Format format;
  947. QXmlStreamAttributes xfAttrs = reader.attributes();
  948. // qDebug()<<reader.name()<<reader.tokenString()<<" .........";
  949. // for (int i=0; i<xfAttrs.size(); ++i)
  950. // qDebug()<<"... "<<i<<" "<<xfAttrs[i].name()<<xfAttrs[i].value();
  951. if (xfAttrs.hasAttribute(QLatin1String("numFmtId"))) {
  952. int numFmtIndex = xfAttrs.value(QLatin1String("numFmtId")).toString().toInt();
  953. bool apply = parseXsdBoolean(xfAttrs.value(QLatin1String("applyNumberFormat")).toString());
  954. if(apply) {
  955. if (!m_customNumFmtIdMap.contains(numFmtIndex))
  956. format.setNumberFormatIndex(numFmtIndex);
  957. else
  958. format.setNumberFormat(numFmtIndex, m_customNumFmtIdMap[numFmtIndex]->formatString);
  959. }
  960. }
  961. if (xfAttrs.hasAttribute(QLatin1String("fontId"))) {
  962. int fontIndex = xfAttrs.value(QLatin1String("fontId")).toString().toInt();
  963. if (fontIndex >= m_fontsList.size()) {
  964. qDebug("Error read styles.xml, cellXfs fontId");
  965. } else {
  966. bool apply = parseXsdBoolean(xfAttrs.value(QLatin1String("applyFont")).toString());
  967. if(apply) {
  968. Format fontFormat = m_fontsList[fontIndex];
  969. for (int i=FormatPrivate::P_Font_STARTID; i<FormatPrivate::P_Font_ENDID; ++i) {
  970. if (fontFormat.hasProperty(i))
  971. format.setProperty(i, fontFormat.property(i));
  972. }
  973. }
  974. }
  975. }
  976. if (xfAttrs.hasAttribute(QLatin1String("fillId"))) {
  977. int id = xfAttrs.value(QLatin1String("fillId")).toString().toInt();
  978. if (id >= m_fillsList.size()) {
  979. qDebug("Error read styles.xml, cellXfs fillId");
  980. } else {
  981. bool apply = parseXsdBoolean(xfAttrs.value(QLatin1String("applyFill")).toString());
  982. if(apply) {
  983. Format fillFormat = m_fillsList[id];
  984. for (int i=FormatPrivate::P_Fill_STARTID; i<FormatPrivate::P_Fill_ENDID; ++i) {
  985. if (fillFormat.hasProperty(i))
  986. format.setProperty(i, fillFormat.property(i));
  987. }
  988. }
  989. }
  990. }
  991. if (xfAttrs.hasAttribute(QLatin1String("borderId"))) {
  992. int id = xfAttrs.value(QLatin1String("borderId")).toString().toInt();
  993. if (id >= m_bordersList.size()) {
  994. qDebug("Error read styles.xml, cellXfs borderId");
  995. } else {
  996. bool apply = parseXsdBoolean(xfAttrs.value(QLatin1String("applyBorder")).toString());
  997. if(apply) {
  998. Format borderFormat = m_bordersList[id];
  999. for (int i=FormatPrivate::P_Border_STARTID; i<FormatPrivate::P_Border_ENDID; ++i) {
  1000. if (borderFormat.hasProperty(i))
  1001. format.setProperty(i, borderFormat.property(i));
  1002. }
  1003. }
  1004. }
  1005. }
  1006. bool apply = parseXsdBoolean(xfAttrs.value(QLatin1String("applyAlignment")).toString());
  1007. if(apply) {
  1008. reader.readNextStartElement();
  1009. if (reader.name() == QLatin1String("alignment")) {
  1010. QXmlStreamAttributes alignAttrs = reader.attributes();
  1011. if (alignAttrs.hasAttribute(QLatin1String("horizontal"))) {
  1012. static QMap<QString, Format::HorizontalAlignment> alignStringMap;
  1013. if (alignStringMap.isEmpty()) {
  1014. alignStringMap.insert(QStringLiteral("left"), Format::AlignLeft);
  1015. alignStringMap.insert(QStringLiteral("center"), Format::AlignHCenter);
  1016. alignStringMap.insert(QStringLiteral("right"), Format::AlignRight);
  1017. alignStringMap.insert(QStringLiteral("justify"), Format::AlignHJustify);
  1018. alignStringMap.insert(QStringLiteral("centerContinuous"), Format::AlignHMerge);
  1019. alignStringMap.insert(QStringLiteral("distributed"), Format::AlignHDistributed);
  1020. }
  1021. QString str = alignAttrs.value(QLatin1String("horizontal")).toString();
  1022. if (alignStringMap.contains(str))
  1023. format.setHorizontalAlignment(alignStringMap[str]);
  1024. }
  1025. if (alignAttrs.hasAttribute(QLatin1String("vertical"))) {
  1026. static QMap<QString, Format::VerticalAlignment> alignStringMap;
  1027. if (alignStringMap.isEmpty()) {
  1028. alignStringMap.insert(QStringLiteral("top"), Format::AlignTop);
  1029. alignStringMap.insert(QStringLiteral("center"), Format::AlignVCenter);
  1030. alignStringMap.insert(QStringLiteral("justify"), Format::AlignVJustify);
  1031. alignStringMap.insert(QStringLiteral("distributed"), Format::AlignVDistributed);
  1032. }
  1033. QString str = alignAttrs.value(QLatin1String("vertical")).toString();
  1034. if (alignStringMap.contains(str))
  1035. format.setVerticalAlignment(alignStringMap[str]);
  1036. }
  1037. if (alignAttrs.hasAttribute(QLatin1String("indent"))) {
  1038. int indent = alignAttrs.value(QLatin1String("indent")).toString().toInt();
  1039. format.setIndent(indent);
  1040. }
  1041. if (alignAttrs.hasAttribute(QLatin1String("textRotation"))) {
  1042. int rotation = alignAttrs.value(QLatin1String("textRotation")).toString().toInt();
  1043. format.setRotation(rotation);
  1044. }
  1045. if (alignAttrs.hasAttribute(QLatin1String("wrapText")))
  1046. format.setTextWarp(true);
  1047. if (alignAttrs.hasAttribute(QLatin1String("shrinkToFit")))
  1048. format.setShrinkToFit(true);
  1049. }
  1050. }
  1051. addXfFormat(format, true);
  1052. }
  1053. }
  1054. }
  1055. if (reader.hasError())
  1056. qWarning()<<reader.errorString();
  1057. if (hasCount && (count != m_xf_formatsList.size()))
  1058. qWarning("error read CellXfs");
  1059. return true;
  1060. }
  1061. bool Styles::readDxfs(QXmlStreamReader &reader)
  1062. {
  1063. Q_ASSERT(reader.name() == QLatin1String("dxfs"));
  1064. QXmlStreamAttributes attributes = reader.attributes();
  1065. bool hasCount = attributes.hasAttribute(QLatin1String("count"));
  1066. int count = hasCount ? attributes.value(QLatin1String("count")).toString().toInt() : -1;
  1067. while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
  1068. && reader.name() == QLatin1String("dxfs"))) {
  1069. reader.readNextStartElement();
  1070. if (reader.tokenType() == QXmlStreamReader::StartElement) {
  1071. if (reader.name() == QLatin1String("dxf"))
  1072. readDxf(reader);
  1073. }
  1074. }
  1075. if (reader.hasError())
  1076. qWarning()<<reader.errorString();
  1077. if (hasCount && (count != m_dxf_formatsList.size()))
  1078. qWarning("error read dxfs");
  1079. return true;
  1080. }
  1081. bool Styles::readDxf(QXmlStreamReader &reader)
  1082. {
  1083. Q_ASSERT(reader.name() == QLatin1String("dxf"));
  1084. Format format;
  1085. while (!reader.atEnd() && !(reader.name() == QLatin1String("dxf") && reader.tokenType() == QXmlStreamReader::EndElement)) {
  1086. reader.readNextStartElement();
  1087. if (reader.tokenType() == QXmlStreamReader::StartElement) {
  1088. if (reader.name() == QLatin1String("numFmt")) {
  1089. QXmlStreamAttributes attributes = reader.attributes();
  1090. int id = attributes.value(QLatin1String("numFmtId")).toString().toInt();
  1091. QString code = attributes.value(QLatin1String("formatCode")).toString();
  1092. format.setNumberFormat(id, code);
  1093. } else if (reader.name() == QLatin1String("font")) {
  1094. readFont(reader, format);
  1095. } else if (reader.name() == QLatin1String("fill")) {
  1096. readFill(reader, format);
  1097. } else if (reader.name() == QLatin1String("border")) {
  1098. readBorder(reader, format);
  1099. }
  1100. }
  1101. }
  1102. addDxfFormat(format, true);
  1103. return true;
  1104. }
  1105. bool Styles::readColors(QXmlStreamReader &reader)
  1106. {
  1107. Q_ASSERT(reader.name() == QLatin1String("colors"));
  1108. while (!reader.atEnd() && !(reader.name() == QLatin1String("colors") && reader.tokenType() == QXmlStreamReader::EndElement)) {
  1109. reader.readNextStartElement();
  1110. if (reader.tokenType() == QXmlStreamReader::StartElement) {
  1111. if (reader.name() == QLatin1String("indexedColors")) {
  1112. readIndexedColors(reader);
  1113. } else if (reader.name() == QLatin1String("mruColors")) {
  1114. }
  1115. }
  1116. }
  1117. return true;
  1118. }
  1119. bool Styles::readIndexedColors(QXmlStreamReader &reader)
  1120. {
  1121. Q_ASSERT(reader.name() == QLatin1String("indexedColors"));
  1122. m_indexedColors.clear();
  1123. while (!reader.atEnd() && !(reader.name() == QLatin1String("indexedColors") && reader.tokenType() == QXmlStreamReader::EndElement)) {
  1124. reader.readNextStartElement();
  1125. if (reader.tokenType() == QXmlStreamReader::StartElement) {
  1126. if (reader.name() == QLatin1String("rgbColor")) {
  1127. QString color = reader.attributes().value(QLatin1String("rgb")).toString();
  1128. m_indexedColors.append(XlsxColor::fromARGBString(color));
  1129. }
  1130. }
  1131. }
  1132. if (!m_indexedColors.isEmpty())
  1133. m_isIndexedColorsDefault = false;
  1134. return true;
  1135. }
  1136. bool Styles::loadFromXmlFile(QIODevice *device)
  1137. {
  1138. QXmlStreamReader reader(device);
  1139. while (!reader.atEnd()) {
  1140. QXmlStreamReader::TokenType token = reader.readNext();
  1141. if (token == QXmlStreamReader::StartElement) {
  1142. if (reader.name() == QLatin1String("numFmts")) {
  1143. readNumFmts(reader);
  1144. } else if (reader.name() == QLatin1String("fonts")) {
  1145. readFonts(reader);
  1146. } else if (reader.name() == QLatin1String("fills")) {
  1147. readFills(reader);
  1148. } else if (reader.name() == QLatin1String("borders")) {
  1149. readBorders(reader);
  1150. } else if (reader.name() == QLatin1String("cellStyleXfs")) {
  1151. } else if (reader.name() == QLatin1String("cellXfs")) {
  1152. readCellXfs(reader);
  1153. } else if (reader.name() == QLatin1String("cellStyles")) {
  1154. } else if (reader.name() == QLatin1String("dxfs")) {
  1155. readDxfs(reader);
  1156. } else if (reader.name() == QLatin1String("colors")) {
  1157. readColors(reader);
  1158. }
  1159. }
  1160. if (reader.hasError()) {
  1161. qDebug()<<"Error when read style file: "<<reader.errorString();
  1162. }
  1163. }
  1164. return true;
  1165. }
  1166. QColor Styles::getColorByIndex(int idx)
  1167. {
  1168. if (m_indexedColors.isEmpty()) {
  1169. m_indexedColors<<QColor("#000000") <<QColor("#FFFFFF") <<QColor("#FF0000") <<QColor("#00FF00")
  1170. <<QColor("#0000FF") <<QColor("#FFFF00") <<QColor("#FF00FF") <<QColor("#00FFFF")
  1171. <<QColor("#000000") <<QColor("#FFFFFF") <<QColor("#FF0000") <<QColor("#00FF00")
  1172. <<QColor("#0000FF") <<QColor("#FFFF00") <<QColor("#FF00FF") <<QColor("#00FFFF")
  1173. <<QColor("#800000") <<QColor("#008000") <<QColor("#000080") <<QColor("#808000")
  1174. <<QColor("#800080") <<QColor("#008080") <<QColor("#C0C0C0") <<QColor("#808080")
  1175. <<QColor("#9999FF") <<QColor("#993366") <<QColor("#FFFFCC") <<QColor("#CCFFFF")
  1176. <<QColor("#660066") <<QColor("#FF8080") <<QColor("#0066CC") <<QColor("#CCCCFF")
  1177. <<QColor("#000080") <<QColor("#FF00FF") <<QColor("#FFFF00") <<QColor("#00FFFF")
  1178. <<QColor("#800080") <<QColor("#800000") <<QColor("#008080") <<QColor("#0000FF")
  1179. <<QColor("#00CCFF") <<QColor("#CCFFFF") <<QColor("#CCFFCC") <<QColor("#FFFF99")
  1180. <<QColor("#99CCFF") <<QColor("#FF99CC") <<QColor("#CC99FF") <<QColor("#FFCC99")
  1181. <<QColor("#3366FF") <<QColor("#33CCCC") <<QColor("#99CC00") <<QColor("#FFCC00")
  1182. <<QColor("#FF9900") <<QColor("#FF6600") <<QColor("#666699") <<QColor("#969696")
  1183. <<QColor("#003366") <<QColor("#339966") <<QColor("#003300") <<QColor("#333300")
  1184. <<QColor("#993300") <<QColor("#993366") <<QColor("#333399") <<QColor("#333333");
  1185. m_isIndexedColorsDefault = true;
  1186. }
  1187. if (idx < 0 || idx >= m_indexedColors.size())
  1188. return QColor();
  1189. return m_indexedColors[idx];
  1190. }
  1191. } //namespace QXlsx