xlsxdatavalidation.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  1. // xlsxdatavalidation.cpp
  2. #include <QtGlobal>
  3. #include <QXmlStreamReader>
  4. #include <QXmlStreamWriter>
  5. #include "xlsxdatavalidation.h"
  6. #include "xlsxdatavalidation_p.h"
  7. #include "xlsxworksheet.h"
  8. #include "xlsxcellrange.h"
  9. QT_BEGIN_NAMESPACE_XLSX
  10. DataValidationPrivate::DataValidationPrivate()
  11. :validationType(DataValidation::None), validationOperator(DataValidation::Between)
  12. , errorStyle(DataValidation::Stop), allowBlank(false), isPromptMessageVisible(true)
  13. , isErrorMessageVisible(true)
  14. {
  15. }
  16. DataValidationPrivate::DataValidationPrivate(DataValidation::ValidationType type, DataValidation::ValidationOperator op, const QString &formula1, const QString &formula2, bool allowBlank)
  17. :validationType(type), validationOperator(op)
  18. , errorStyle(DataValidation::Stop), allowBlank(allowBlank), isPromptMessageVisible(true)
  19. , isErrorMessageVisible(true), formula1(formula1), formula2(formula2)
  20. {
  21. }
  22. DataValidationPrivate::DataValidationPrivate(const DataValidationPrivate &other)
  23. :QSharedData(other)
  24. , validationType(DataValidation::None), validationOperator(DataValidation::Between)
  25. , errorStyle(DataValidation::Stop), allowBlank(false), isPromptMessageVisible(true)
  26. , isErrorMessageVisible(true)
  27. {
  28. }
  29. DataValidationPrivate::~DataValidationPrivate()
  30. {
  31. }
  32. /*!
  33. * \class DataValidation
  34. * \brief Data validation for single cell or a range
  35. * \inmodule QtXlsx
  36. *
  37. * The data validation can be applied to a single cell or a range of cells.
  38. */
  39. /*!
  40. * \enum DataValidation::ValidationType
  41. *
  42. * The enum type defines the type of data that you wish to validate.
  43. *
  44. * \value None the type of data is unrestricted. This is the same as not applying a data validation.
  45. * \value Whole restricts the cell to integer values. Means "Whole number"?
  46. * \value Decimal restricts the cell to decimal values.
  47. * \value List restricts the cell to a set of user specified values.
  48. * \value Date restricts the cell to date values.
  49. * \value Time restricts the cell to time values.
  50. * \value TextLength restricts the cell data based on an integer string length.
  51. * \value Custom restricts the cell based on an external Excel formula that returns a true/false value.
  52. */
  53. /*!
  54. * \enum DataValidation::ValidationOperator
  55. *
  56. * The enum type defines the criteria by which the data in the
  57. * cell is validated
  58. *
  59. * \value Between
  60. * \value NotBetween
  61. * \value Equal
  62. * \value NotEqual
  63. * \value LessThan
  64. * \value LessThanOrEqual
  65. * \value GreaterThan
  66. * \value GreaterThanOrEqual
  67. */
  68. /*!
  69. * \enum DataValidation::ErrorStyle
  70. *
  71. * The enum type defines the type of error dialog that
  72. * is displayed.
  73. *
  74. * \value Stop
  75. * \value Warning
  76. * \value Information
  77. */
  78. /*!
  79. * Construct a data validation object with the given \a type, \a op, \a formula1
  80. * \a formula2, and \a allowBlank.
  81. */
  82. DataValidation::DataValidation(ValidationType type, ValidationOperator op, const QString &formula1, const QString &formula2, bool allowBlank)
  83. :d(new DataValidationPrivate(type, op, formula1, formula2, allowBlank))
  84. {
  85. }
  86. /*!
  87. Construct a data validation object
  88. */
  89. DataValidation::DataValidation()
  90. :d(new DataValidationPrivate())
  91. {
  92. }
  93. /*!
  94. Constructs a copy of \a other.
  95. */
  96. DataValidation::DataValidation(const DataValidation &other)
  97. :d(other.d)
  98. {
  99. }
  100. /*!
  101. Assigns \a other to this validation and returns a reference to this validation.
  102. */
  103. DataValidation &DataValidation::operator=(const DataValidation &other)
  104. {
  105. this->d = other.d;
  106. return *this;
  107. }
  108. /*!
  109. * Destroy the object.
  110. */
  111. DataValidation::~DataValidation()
  112. {
  113. }
  114. /*!
  115. Returns the validation type.
  116. */
  117. DataValidation::ValidationType DataValidation::validationType() const
  118. {
  119. return d->validationType;
  120. }
  121. /*!
  122. Returns the validation operator.
  123. */
  124. DataValidation::ValidationOperator DataValidation::validationOperator() const
  125. {
  126. return d->validationOperator;
  127. }
  128. /*!
  129. Returns the validation error style.
  130. */
  131. DataValidation::ErrorStyle DataValidation::errorStyle() const
  132. {
  133. return d->errorStyle;
  134. }
  135. /*!
  136. Returns the formula1.
  137. */
  138. QString DataValidation::formula1() const
  139. {
  140. return d->formula1;
  141. }
  142. /*!
  143. Returns the formula2.
  144. */
  145. QString DataValidation::formula2() const
  146. {
  147. return d->formula2;
  148. }
  149. /*!
  150. Returns whether blank is allowed.
  151. */
  152. bool DataValidation::allowBlank() const
  153. {
  154. return d->allowBlank;
  155. }
  156. /*!
  157. Returns the error message.
  158. */
  159. QString DataValidation::errorMessage() const
  160. {
  161. return d->errorMessage;
  162. }
  163. /*!
  164. Returns the error message title.
  165. */
  166. QString DataValidation::errorMessageTitle() const
  167. {
  168. return d->errorMessageTitle;
  169. }
  170. /*!
  171. Returns the prompt message.
  172. */
  173. QString DataValidation::promptMessage() const
  174. {
  175. return d->promptMessage;
  176. }
  177. /*!
  178. Returns the prompt message title.
  179. */
  180. QString DataValidation::promptMessageTitle() const
  181. {
  182. return d->promptMessageTitle;
  183. }
  184. /*!
  185. Returns the whether prompt message is shown.
  186. */
  187. bool DataValidation::isPromptMessageVisible() const
  188. {
  189. return d->isPromptMessageVisible;
  190. }
  191. /*!
  192. Returns the whether error message is shown.
  193. */
  194. bool DataValidation::isErrorMessageVisible() const
  195. {
  196. return d->isErrorMessageVisible;
  197. }
  198. /*!
  199. Returns the ranges on which the validation will be applied.
  200. */
  201. QList<CellRange> DataValidation::ranges() const
  202. {
  203. return d->ranges;
  204. }
  205. /*!
  206. Sets the validation type to \a type.
  207. */
  208. void DataValidation::setValidationType(DataValidation::ValidationType type)
  209. {
  210. d->validationType = type;
  211. }
  212. /*!
  213. Sets the validation operator to \a op.
  214. */
  215. void DataValidation::setValidationOperator(DataValidation::ValidationOperator op)
  216. {
  217. d->validationOperator = op;
  218. }
  219. /*!
  220. Sets the error style to \a es.
  221. */
  222. void DataValidation::setErrorStyle(DataValidation::ErrorStyle es)
  223. {
  224. d->errorStyle = es;
  225. }
  226. /*!
  227. Sets the formula1 to \a formula.
  228. */
  229. void DataValidation::setFormula1(const QString &formula)
  230. {
  231. if (formula.startsWith(QLatin1Char('=')))
  232. d->formula1 = formula.mid(1);
  233. else
  234. d->formula1 = formula;
  235. }
  236. /*!
  237. Sets the formulas to \a formula.
  238. */
  239. void DataValidation::setFormula2(const QString &formula)
  240. {
  241. if (formula.startsWith(QLatin1Char('=')))
  242. d->formula2 = formula.mid(1);
  243. else
  244. d->formula2 = formula;
  245. }
  246. /*!
  247. Sets the error message to \a error with title \a title.
  248. */
  249. void DataValidation::setErrorMessage(const QString &error, const QString &title)
  250. {
  251. d->errorMessage = error;
  252. d->errorMessageTitle = title;
  253. }
  254. /*!
  255. Sets the prompt message to \a prompt with title \a title.
  256. */
  257. void DataValidation::setPromptMessage(const QString &prompt, const QString &title)
  258. {
  259. d->promptMessage = prompt;
  260. d->promptMessageTitle = title;
  261. }
  262. /*!
  263. Enable/disabe blank allow based on \a enable.
  264. */
  265. void DataValidation::setAllowBlank(bool enable)
  266. {
  267. d->allowBlank = enable;
  268. }
  269. /*!
  270. Enable/disabe prompt message visible based on \a visible.
  271. */
  272. void DataValidation::setPromptMessageVisible(bool visible)
  273. {
  274. d->isPromptMessageVisible = visible;
  275. }
  276. /*!
  277. Enable/disabe error message visible based on \a visible.
  278. */
  279. void DataValidation::setErrorMessageVisible(bool visible)
  280. {
  281. d->isErrorMessageVisible = visible;
  282. }
  283. /*!
  284. Add the \a cell on which the DataValidation will apply to.
  285. */
  286. void DataValidation::addCell(const CellReference &cell)
  287. {
  288. d->ranges.append(CellRange(cell, cell));
  289. }
  290. /*!
  291. \overload
  292. Add the cell(\a row, \a col) on which the DataValidation will apply to.
  293. */
  294. void DataValidation::addCell(int row, int col)
  295. {
  296. d->ranges.append(CellRange(row, col, row, col));
  297. }
  298. /*!
  299. \overload
  300. Add the range(\a firstRow, \a firstCol, \a lastRow, \a lastCol) on
  301. which the DataValidation will apply to.
  302. */
  303. void DataValidation::addRange(int firstRow, int firstCol, int lastRow, int lastCol)
  304. {
  305. d->ranges.append(CellRange(firstRow, firstCol, lastRow, lastCol));
  306. }
  307. /*!
  308. Add the \a range on which the DataValidation will apply to.
  309. */
  310. void DataValidation::addRange(const CellRange &range)
  311. {
  312. d->ranges.append(range);
  313. }
  314. /*!
  315. * \internal
  316. */
  317. bool DataValidation::saveToXml(QXmlStreamWriter &writer) const
  318. {
  319. static const QMap<DataValidation::ValidationType, QString> typeMap = {
  320. {DataValidation::None, QStringLiteral("none")},
  321. {DataValidation::Whole, QStringLiteral("whole")},
  322. {DataValidation::Decimal, QStringLiteral("decimal")},
  323. {DataValidation::List, QStringLiteral("list")},
  324. {DataValidation::Date, QStringLiteral("date")},
  325. {DataValidation::Time, QStringLiteral("time")},
  326. {DataValidation::TextLength, QStringLiteral("textLength")},
  327. {DataValidation::Custom, QStringLiteral("custom")}
  328. };
  329. static const QMap<DataValidation::ValidationOperator, QString> opMap = {
  330. {DataValidation::Between, QStringLiteral("between")},
  331. {DataValidation::NotBetween, QStringLiteral("notBetween")},
  332. {DataValidation::Equal, QStringLiteral("equal")},
  333. {DataValidation::NotEqual, QStringLiteral("notEqual")},
  334. {DataValidation::LessThan, QStringLiteral("lessThan")},
  335. {DataValidation::LessThanOrEqual, QStringLiteral("lessThanOrEqual")},
  336. {DataValidation::GreaterThan, QStringLiteral("greaterThan")},
  337. {DataValidation::GreaterThanOrEqual, QStringLiteral("greaterThanOrEqual")}
  338. };
  339. static const QMap<DataValidation::ErrorStyle, QString> esMap = {
  340. {DataValidation::Stop, QStringLiteral("stop")},
  341. {DataValidation::Warning, QStringLiteral("warning")},
  342. {DataValidation::Information, QStringLiteral("information")}
  343. };
  344. writer.writeStartElement(QStringLiteral("dataValidation"));
  345. if (validationType() != DataValidation::None)
  346. writer.writeAttribute(QStringLiteral("type"), typeMap[validationType()]);
  347. if (errorStyle() != DataValidation::Stop)
  348. writer.writeAttribute(QStringLiteral("errorStyle"), esMap[errorStyle()]);
  349. if (validationOperator() != DataValidation::Between)
  350. writer.writeAttribute(QStringLiteral("operator"), opMap[validationOperator()]);
  351. if (allowBlank())
  352. writer.writeAttribute(QStringLiteral("allowBlank"), QStringLiteral("1"));
  353. // if (dropDownVisible())
  354. // writer.writeAttribute(QStringLiteral("showDropDown"), QStringLiteral("1"));
  355. if (isPromptMessageVisible())
  356. writer.writeAttribute(QStringLiteral("showInputMessage"), QStringLiteral("1"));
  357. if (isErrorMessageVisible())
  358. writer.writeAttribute(QStringLiteral("showErrorMessage"), QStringLiteral("1"));
  359. if (!errorMessageTitle().isEmpty())
  360. writer.writeAttribute(QStringLiteral("errorTitle"), errorMessageTitle());
  361. if (!errorMessage().isEmpty())
  362. writer.writeAttribute(QStringLiteral("error"), errorMessage());
  363. if (!promptMessageTitle().isEmpty())
  364. writer.writeAttribute(QStringLiteral("promptTitle"), promptMessageTitle());
  365. if (!promptMessage().isEmpty())
  366. writer.writeAttribute(QStringLiteral("prompt"), promptMessage());
  367. QStringList sqref;
  368. const auto rangeList = ranges();
  369. for (const CellRange &range : rangeList)
  370. sqref.append(range.toString());
  371. writer.writeAttribute(QStringLiteral("sqref"), sqref.join(QLatin1String(" ")));
  372. if (!formula1().isEmpty())
  373. writer.writeTextElement(QStringLiteral("formula1"), formula1());
  374. if (!formula2().isEmpty())
  375. writer.writeTextElement(QStringLiteral("formula2"), formula2());
  376. writer.writeEndElement(); //dataValidation
  377. return true;
  378. }
  379. /*!
  380. * \internal
  381. */
  382. DataValidation DataValidation::loadFromXml(QXmlStreamReader &reader)
  383. {
  384. Q_ASSERT(reader.name() == QLatin1String("dataValidation"));
  385. static const QMap<QString, DataValidation::ValidationType> typeMap = {
  386. {QStringLiteral("none"), DataValidation::None},
  387. {QStringLiteral("whole"), DataValidation::Whole},
  388. {QStringLiteral("decimal"), DataValidation::Decimal},
  389. {QStringLiteral("list"), DataValidation::List},
  390. {QStringLiteral("date"), DataValidation::Date},
  391. {QStringLiteral("time"), DataValidation::Time},
  392. {QStringLiteral("textLength"), DataValidation::TextLength},
  393. {QStringLiteral("custom"), DataValidation::Custom}
  394. };
  395. static const QMap<QString, DataValidation::ValidationOperator> opMap = {
  396. {QStringLiteral("between"), DataValidation::Between},
  397. {QStringLiteral("notBetween"), DataValidation::NotBetween},
  398. {QStringLiteral("equal"), DataValidation::Equal},
  399. {QStringLiteral("notEqual"), DataValidation::NotEqual},
  400. {QStringLiteral("lessThan"), DataValidation::LessThan},
  401. {QStringLiteral("lessThanOrEqual"), DataValidation::LessThanOrEqual},
  402. {QStringLiteral("greaterThan"), DataValidation::GreaterThan},
  403. {QStringLiteral("greaterThanOrEqual"), DataValidation::GreaterThanOrEqual}
  404. };
  405. static const QMap<QString, DataValidation::ErrorStyle> esMap = {
  406. {QStringLiteral("stop"), DataValidation::Stop},
  407. {QStringLiteral("warning"), DataValidation::Warning},
  408. {QStringLiteral("information"), DataValidation::Information}
  409. };
  410. DataValidation validation;
  411. QXmlStreamAttributes attrs = reader.attributes();
  412. QString sqref = attrs.value(QLatin1String("sqref")).toString();
  413. const auto sqrefParts = sqref.split(QLatin1Char(' '));
  414. for (const QString &range : sqrefParts)
  415. validation.addRange(range);
  416. if (attrs.hasAttribute(QLatin1String("type"))) {
  417. QString t = attrs.value(QLatin1String("type")).toString();
  418. auto it = typeMap.constFind(t);
  419. validation.setValidationType(it != typeMap.constEnd() ? it.value() : DataValidation::None);
  420. }
  421. if (attrs.hasAttribute(QLatin1String("errorStyle"))) {
  422. QString es = attrs.value(QLatin1String("errorStyle")).toString();
  423. auto it = esMap.constFind(es);
  424. validation.setErrorStyle(it != esMap.constEnd() ? it.value() : DataValidation::Stop);
  425. }
  426. if (attrs.hasAttribute(QLatin1String("operator"))) {
  427. QString op = attrs.value(QLatin1String("operator")).toString();
  428. auto it = opMap.constFind(op);
  429. validation.setValidationOperator(it != opMap.constEnd() ? it.value() : DataValidation::Between);
  430. }
  431. if (attrs.hasAttribute(QLatin1String("allowBlank"))) {
  432. validation.setAllowBlank(true);
  433. } else {
  434. validation.setAllowBlank(false);
  435. }
  436. if (attrs.hasAttribute(QLatin1String("showInputMessage"))) {
  437. validation.setPromptMessageVisible(true);
  438. } else {
  439. validation.setPromptMessageVisible(false);
  440. }
  441. if (attrs.hasAttribute(QLatin1String("showErrorMessage"))) {
  442. validation.setErrorMessageVisible(true);
  443. } else {
  444. validation.setErrorMessageVisible(false);
  445. }
  446. QString et = attrs.value(QLatin1String("errorTitle")).toString();
  447. QString e = attrs.value(QLatin1String("error")).toString();
  448. if (!e.isEmpty() || !et.isEmpty())
  449. validation.setErrorMessage(e, et);
  450. QString pt = attrs.value(QLatin1String("promptTitle")).toString();
  451. QString p = attrs.value(QLatin1String("prompt")).toString();
  452. if (!p.isEmpty() || !pt.isEmpty())
  453. validation.setPromptMessage(p, pt);
  454. //find the end
  455. while(!(reader.name() == QLatin1String("dataValidation") && reader.tokenType() == QXmlStreamReader::EndElement)) {
  456. reader.readNextStartElement();
  457. if (reader.tokenType() == QXmlStreamReader::StartElement) {
  458. if (reader.name() == QLatin1String("formula1")) {
  459. validation.setFormula1(reader.readElementText());
  460. } else if (reader.name() == QLatin1String("formula2")) {
  461. validation.setFormula2(reader.readElementText());
  462. }
  463. }
  464. }
  465. return validation;
  466. }
  467. QT_END_NAMESPACE_XLSX