cell.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023
  1. // Copyright (c) 2014-2021 Thomas Fussell
  2. // Copyright (c) 2010-2015 openpyxl
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE
  21. //
  22. // @license: http://www.opensource.org/licenses/mit-license.php
  23. // @author: see AUTHORS file
  24. #include <algorithm>
  25. #include <cmath>
  26. #include <sstream>
  27. #include <xlnt/cell/cell.hpp>
  28. #include <xlnt/cell/cell_reference.hpp>
  29. #include <xlnt/cell/comment.hpp>
  30. #include <xlnt/cell/hyperlink.hpp>
  31. #include <xlnt/cell/rich_text.hpp>
  32. #include <xlnt/packaging/manifest.hpp>
  33. #include <xlnt/packaging/relationship.hpp>
  34. #include <xlnt/styles/alignment.hpp>
  35. #include <xlnt/styles/border.hpp>
  36. #include <xlnt/styles/color.hpp>
  37. #include <xlnt/styles/fill.hpp>
  38. #include <xlnt/styles/font.hpp>
  39. #include <xlnt/styles/format.hpp>
  40. #include <xlnt/styles/number_format.hpp>
  41. #include <xlnt/styles/protection.hpp>
  42. #include <xlnt/styles/style.hpp>
  43. #include <xlnt/utils/date.hpp>
  44. #include <xlnt/utils/datetime.hpp>
  45. #include <xlnt/utils/exceptions.hpp>
  46. #include <xlnt/utils/time.hpp>
  47. #include <xlnt/utils/timedelta.hpp>
  48. #include <xlnt/workbook/workbook.hpp>
  49. #include <xlnt/worksheet/column_properties.hpp>
  50. #include <xlnt/worksheet/phonetic_pr.hpp>
  51. #include <xlnt/worksheet/row_properties.hpp>
  52. #include <xlnt/worksheet/worksheet.hpp>
  53. #include <detail/implementations/cell_impl.hpp>
  54. #include <detail/implementations/format_impl.hpp>
  55. #include <detail/implementations/hyperlink_impl.hpp>
  56. #include <detail/implementations/stylesheet.hpp>
  57. #include <detail/implementations/worksheet_impl.hpp>
  58. #include <xlnt/utils/numeric.hpp>
  59. namespace {
  60. std::pair<bool, double> cast_numeric(const std::string &s)
  61. {
  62. xlnt::detail::number_serialiser ser;
  63. ptrdiff_t len_convert;
  64. double result = ser.deserialise(s, &len_convert);
  65. return (len_convert != static_cast<ptrdiff_t>(s.size()))
  66. ? std::make_pair(false, 0.0)
  67. : std::make_pair(true, result);
  68. }
  69. std::pair<bool, double> cast_percentage(const std::string &s)
  70. {
  71. if (s.back() == '%')
  72. {
  73. auto number = cast_numeric(s.substr(0, s.size() - 1));
  74. if (number.first)
  75. {
  76. return {true, number.second / 100};
  77. }
  78. }
  79. return {false, 0.0};
  80. }
  81. std::pair<bool, xlnt::time> cast_time(const std::string &s)
  82. {
  83. xlnt::time result;
  84. std::vector<std::string> time_components;
  85. std::size_t prev = 0;
  86. auto colon_index = s.find(':');
  87. while (colon_index != std::string::npos)
  88. {
  89. time_components.push_back(s.substr(prev, colon_index - prev));
  90. prev = colon_index + 1;
  91. colon_index = s.find(':', colon_index + 1);
  92. }
  93. time_components.push_back(s.substr(prev, colon_index - prev));
  94. if (time_components.size() < 2 || time_components.size() > 3)
  95. {
  96. return {false, result};
  97. }
  98. std::vector<double> numeric_components;
  99. xlnt::detail::number_serialiser ser;
  100. for (auto component : time_components)
  101. {
  102. if (component.empty() || (component.substr(0, component.find('.')).size() > 2))
  103. {
  104. return {false, result};
  105. }
  106. for (auto d : component)
  107. {
  108. if (!(d >= '0' && d <= '9') && d != '.')
  109. {
  110. return {false, result};
  111. }
  112. }
  113. auto numeric = ser.deserialise(component);
  114. numeric_components.push_back(numeric);
  115. }
  116. result.hour = static_cast<int>(numeric_components[0]);
  117. result.minute = static_cast<int>(numeric_components[1]);
  118. if (std::fabs(static_cast<double>(result.minute) - numeric_components[1]) > std::numeric_limits<double>::epsilon())
  119. {
  120. result.minute = result.hour;
  121. result.hour = 0;
  122. result.second = static_cast<int>(numeric_components[1]);
  123. result.microsecond = static_cast<int>((numeric_components[1] - result.second) * 1E6);
  124. }
  125. else if (numeric_components.size() > 2)
  126. {
  127. result.second = static_cast<int>(numeric_components[2]);
  128. result.microsecond = static_cast<int>((numeric_components[2] - result.second) * 1E6);
  129. }
  130. return {true, result};
  131. }
  132. } // namespace
  133. namespace xlnt {
  134. const std::unordered_map<std::string, int> &cell::error_codes()
  135. {
  136. static const auto codes = std::unordered_map<std::string, int>{
  137. {"#NULL!", 0},
  138. {"#DIV/0!", 1},
  139. {"#VALUE!", 2},
  140. {"#REF!", 3},
  141. {"#NAME?", 4},
  142. {"#NUM!", 5},
  143. {"#N/A!", 6}};
  144. return codes;
  145. }
  146. std::string cell::check_string(const std::string &to_check)
  147. {
  148. // so we can modify it
  149. std::string s = to_check;
  150. if (s.size() == 0)
  151. {
  152. return s;
  153. }
  154. else if (s.size() > 32767)
  155. {
  156. s = s.substr(0, 32767); // max string length in Excel
  157. }
  158. for (char c : s)
  159. {
  160. if (c >= 0 && (c <= 8 || c == 11 || c == 12 || (c >= 14 && c <= 31)))
  161. {
  162. throw illegal_character(c);
  163. }
  164. }
  165. return s;
  166. }
  167. cell::cell(detail::cell_impl *d)
  168. : d_(d)
  169. {
  170. }
  171. bool cell::garbage_collectible() const
  172. {
  173. return d_->is_garbage_collectible();
  174. }
  175. void cell::value(std::nullptr_t)
  176. {
  177. clear_value();
  178. }
  179. void cell::value(bool boolean_value)
  180. {
  181. d_->type_ = type::boolean;
  182. d_->value_numeric_ = boolean_value ? 1.0 : 0.0;
  183. }
  184. void cell::value(int int_value)
  185. {
  186. d_->value_numeric_ = static_cast<double>(int_value);
  187. d_->type_ = type::number;
  188. }
  189. void cell::value(unsigned int int_value)
  190. {
  191. d_->value_numeric_ = static_cast<double>(int_value);
  192. d_->type_ = type::number;
  193. }
  194. void cell::value(long long int int_value)
  195. {
  196. d_->value_numeric_ = static_cast<double>(int_value);
  197. d_->type_ = type::number;
  198. }
  199. void cell::value(unsigned long long int int_value)
  200. {
  201. d_->value_numeric_ = static_cast<double>(int_value);
  202. d_->type_ = type::number;
  203. }
  204. void cell::value(float float_value)
  205. {
  206. d_->value_numeric_ = static_cast<double>(float_value);
  207. d_->type_ = type::number;
  208. }
  209. void cell::value(double float_value)
  210. {
  211. d_->value_numeric_ = static_cast<double>(float_value);
  212. d_->type_ = type::number;
  213. }
  214. void cell::value(const std::string &s)
  215. {
  216. value(rich_text(check_string(s)));
  217. }
  218. void cell::value(const rich_text &text)
  219. {
  220. check_string(text.plain_text());
  221. d_->type_ = type::shared_string;
  222. d_->value_numeric_ = static_cast<double>(workbook().add_shared_string(text));
  223. }
  224. void cell::value(const char *c)
  225. {
  226. value(std::string(c));
  227. }
  228. void cell::value(const cell c)
  229. {
  230. d_->type_ = c.d_->type_;
  231. d_->value_numeric_ = c.d_->value_numeric_;
  232. d_->value_text_ = c.d_->value_text_;
  233. d_->hyperlink_ = c.d_->hyperlink_;
  234. d_->formula_ = c.d_->formula_;
  235. d_->format_ = c.d_->format_;
  236. }
  237. void cell::value(const date &d)
  238. {
  239. d_->type_ = type::number;
  240. d_->value_numeric_ = d.to_number(base_date());
  241. number_format(number_format::date_yyyymmdd2());
  242. }
  243. void cell::value(const datetime &d)
  244. {
  245. d_->type_ = type::number;
  246. d_->value_numeric_ = d.to_number(base_date());
  247. number_format(number_format::date_datetime());
  248. }
  249. void cell::value(const time &t)
  250. {
  251. d_->type_ = type::number;
  252. d_->value_numeric_ = t.to_number();
  253. number_format(number_format::date_time6());
  254. }
  255. void cell::value(const timedelta &t)
  256. {
  257. d_->type_ = type::number;
  258. d_->value_numeric_ = t.to_number();
  259. number_format(xlnt::number_format("[hh]:mm:ss"));
  260. }
  261. row_t cell::row() const
  262. {
  263. return d_->row_;
  264. }
  265. column_t cell::column() const
  266. {
  267. return d_->column_;
  268. }
  269. column_t::index_t cell::column_index() const
  270. {
  271. return d_->column_.index;
  272. }
  273. void cell::merged(bool merged)
  274. {
  275. d_->is_merged_ = merged;
  276. }
  277. bool cell::is_merged() const
  278. {
  279. return d_->is_merged_;
  280. }
  281. bool cell::phonetics_visible() const
  282. {
  283. return d_->phonetics_visible_;
  284. }
  285. void cell::show_phonetics(bool phonetics)
  286. {
  287. d_->phonetics_visible_ = phonetics;
  288. }
  289. bool cell::is_date() const
  290. {
  291. return data_type() == type::number
  292. && has_format()
  293. && number_format().is_date_format();
  294. }
  295. cell_reference cell::reference() const
  296. {
  297. return {d_->column_, d_->row_};
  298. }
  299. bool cell::operator==(const cell &comparand) const
  300. {
  301. return d_ == comparand.d_;
  302. }
  303. bool cell::operator!=(const cell &comparand) const
  304. {
  305. return d_ != comparand.d_;
  306. }
  307. cell &cell::operator=(const cell &rhs) = default;
  308. hyperlink cell::hyperlink() const
  309. {
  310. return xlnt::hyperlink(&d_->hyperlink_.get());
  311. }
  312. void cell::hyperlink(const std::string &url, const std::string &display)
  313. {
  314. if (url.empty())
  315. {
  316. throw invalid_parameter();
  317. }
  318. auto ws = worksheet();
  319. auto &manifest = ws.workbook().manifest();
  320. d_->hyperlink_ = detail::hyperlink_impl();
  321. // check for existing relationships
  322. auto relationships = manifest.relationships(ws.path(), relationship_type::hyperlink);
  323. auto relation = std::find_if(relationships.cbegin(), relationships.cend(),
  324. [&url](xlnt::relationship rel) { return rel.target().path().string() == url; });
  325. if (relation != relationships.end())
  326. {
  327. d_->hyperlink_.get().relationship = *relation;
  328. }
  329. else
  330. { // register a new relationship
  331. auto rel_id = manifest.register_relationship(
  332. uri(ws.path().string()),
  333. relationship_type::hyperlink,
  334. uri(url),
  335. target_mode::external);
  336. // TODO: make manifest::register_relationship return the created relationship instead of rel id
  337. d_->hyperlink_.get().relationship = manifest.relationship(ws.path(), rel_id);
  338. }
  339. // if a value is already present, the display string is ignored
  340. if (has_value())
  341. {
  342. d_->hyperlink_.get().display.set(to_string());
  343. }
  344. else
  345. {
  346. d_->hyperlink_.get().display.set(display.empty() ? url : display);
  347. value(hyperlink().display());
  348. }
  349. }
  350. void cell::hyperlink(xlnt::cell target, const std::string &display)
  351. {
  352. // TODO: should this computed value be a method on a cell?
  353. const auto cell_address = target.worksheet().title() + "!" + target.reference().to_string();
  354. d_->hyperlink_ = detail::hyperlink_impl();
  355. d_->hyperlink_.get().relationship = xlnt::relationship("", relationship_type::hyperlink,
  356. uri(""), uri(cell_address), target_mode::internal);
  357. // if a value is already present, the display string is ignored
  358. if (has_value())
  359. {
  360. d_->hyperlink_.get().display.set(to_string());
  361. }
  362. else
  363. {
  364. d_->hyperlink_.get().display.set(display.empty() ? cell_address : display);
  365. value(hyperlink().display());
  366. }
  367. }
  368. void cell::hyperlink(xlnt::range target, const std::string &display)
  369. {
  370. // TODO: should this computed value be a method on a cell?
  371. const auto range_address = target.target_worksheet().title() + "!" + target.reference().to_string();
  372. d_->hyperlink_ = detail::hyperlink_impl();
  373. d_->hyperlink_.get().relationship = xlnt::relationship("", relationship_type::hyperlink,
  374. uri(""), uri(range_address), target_mode::internal);
  375. // if a value is already present, the display string is ignored
  376. if (has_value())
  377. {
  378. d_->hyperlink_.get().display.set(to_string());
  379. }
  380. else
  381. {
  382. d_->hyperlink_.get().display.set(display.empty() ? range_address : display);
  383. value(hyperlink().display());
  384. }
  385. }
  386. void cell::formula(const std::string &formula)
  387. {
  388. if (formula.empty())
  389. {
  390. return clear_formula();
  391. }
  392. if (formula[0] == '=')
  393. {
  394. d_->formula_ = formula.substr(1);
  395. }
  396. else
  397. {
  398. d_->formula_ = formula;
  399. }
  400. worksheet().register_calc_chain_in_manifest();
  401. }
  402. bool cell::has_formula() const
  403. {
  404. return d_->formula_.is_set();
  405. }
  406. std::string cell::formula() const
  407. {
  408. return d_->formula_.get();
  409. }
  410. void cell::clear_formula()
  411. {
  412. if (has_formula())
  413. {
  414. d_->formula_.clear();
  415. worksheet().garbage_collect_formulae();
  416. }
  417. }
  418. std::string cell::error() const
  419. {
  420. if (d_->type_ != type::error)
  421. {
  422. throw xlnt::exception("called error() when cell type is not error");
  423. }
  424. return value<std::string>();
  425. }
  426. void cell::error(const std::string &error)
  427. {
  428. if (error.length() == 0 || error[0] != '#')
  429. {
  430. throw invalid_data_type();
  431. }
  432. d_->value_text_.plain_text(error, false);
  433. d_->type_ = type::error;
  434. }
  435. cell cell::offset(int column, int row)
  436. {
  437. return worksheet().cell(reference().make_offset(column, row));
  438. }
  439. worksheet cell::worksheet()
  440. {
  441. return xlnt::worksheet(d_->parent_);
  442. }
  443. const worksheet cell::worksheet() const
  444. {
  445. return xlnt::worksheet(d_->parent_);
  446. }
  447. workbook &cell::workbook()
  448. {
  449. return worksheet().workbook();
  450. }
  451. const workbook &cell::workbook() const
  452. {
  453. return worksheet().workbook();
  454. }
  455. std::pair<int, int> cell::anchor() const
  456. {
  457. double left = 0;
  458. for (column_t column_index = 1; column_index <= d_->column_ - 1; column_index++)
  459. {
  460. left += worksheet().column_width(column_index);
  461. }
  462. double top = 0;
  463. for (row_t row_index = 1; row_index <= d_->row_ - 1; row_index++)
  464. {
  465. top += worksheet().row_height(row_index);
  466. }
  467. return {static_cast<int>(left), static_cast<int>(top)};
  468. }
  469. cell::type cell::data_type() const
  470. {
  471. return d_->type_;
  472. }
  473. void cell::data_type(type t)
  474. {
  475. d_->type_ = t;
  476. }
  477. number_format cell::computed_number_format() const
  478. {
  479. return xlnt::number_format();
  480. }
  481. font cell::computed_font() const
  482. {
  483. return xlnt::font();
  484. }
  485. fill cell::computed_fill() const
  486. {
  487. return xlnt::fill();
  488. }
  489. border cell::computed_border() const
  490. {
  491. return xlnt::border();
  492. }
  493. alignment cell::computed_alignment() const
  494. {
  495. return xlnt::alignment();
  496. }
  497. protection cell::computed_protection() const
  498. {
  499. return xlnt::protection();
  500. }
  501. void cell::clear_value()
  502. {
  503. d_->value_numeric_ = 0;
  504. d_->value_text_.clear();
  505. d_->type_ = cell::type::empty;
  506. clear_formula();
  507. }
  508. template <>
  509. XLNT_API bool cell::value() const
  510. {
  511. return d_->value_numeric_ != 0.0;
  512. }
  513. template <>
  514. XLNT_API int cell::value() const
  515. {
  516. return static_cast<int>(d_->value_numeric_);
  517. }
  518. template <>
  519. XLNT_API long long int cell::value() const
  520. {
  521. return static_cast<long long int>(d_->value_numeric_);
  522. }
  523. template <>
  524. XLNT_API unsigned int cell::value() const
  525. {
  526. return static_cast<unsigned int>(d_->value_numeric_);
  527. }
  528. template <>
  529. XLNT_API unsigned long long cell::value() const
  530. {
  531. return static_cast<unsigned long long>(d_->value_numeric_);
  532. }
  533. template <>
  534. XLNT_API float cell::value() const
  535. {
  536. return static_cast<float>(d_->value_numeric_);
  537. }
  538. template <>
  539. XLNT_API double cell::value() const
  540. {
  541. return static_cast<double>(d_->value_numeric_);
  542. }
  543. template <>
  544. XLNT_API time cell::value() const
  545. {
  546. return time::from_number(d_->value_numeric_);
  547. }
  548. template <>
  549. XLNT_API datetime cell::value() const
  550. {
  551. return datetime::from_number(d_->value_numeric_, base_date());
  552. }
  553. template <>
  554. XLNT_API date cell::value() const
  555. {
  556. return date::from_number(static_cast<int>(d_->value_numeric_), base_date());
  557. }
  558. template <>
  559. XLNT_API timedelta cell::value() const
  560. {
  561. return timedelta::from_number(d_->value_numeric_);
  562. }
  563. void cell::alignment(const class alignment &alignment_)
  564. {
  565. auto new_format = has_format() ? modifiable_format() : workbook().create_format();
  566. format(new_format.alignment(alignment_, optional<bool>(true)));
  567. }
  568. void cell::border(const class border &border_)
  569. {
  570. auto new_format = has_format() ? modifiable_format() : workbook().create_format();
  571. format(new_format.border(border_, optional<bool>(true)));
  572. }
  573. void cell::fill(const class fill &fill_)
  574. {
  575. auto new_format = has_format() ? modifiable_format() : workbook().create_format();
  576. format(new_format.fill(fill_, optional<bool>(true)));
  577. }
  578. void cell::font(const class font &font_)
  579. {
  580. auto new_format = has_format() ? modifiable_format() : workbook().create_format();
  581. format(new_format.font(font_, optional<bool>(true)));
  582. }
  583. void cell::number_format(const class number_format &number_format_)
  584. {
  585. auto new_format = has_format() ? modifiable_format() : workbook().create_format();
  586. format(new_format.number_format(number_format_, optional<bool>(true)));
  587. }
  588. void cell::protection(const class protection &protection_)
  589. {
  590. auto new_format = has_format() ? modifiable_format() : workbook().create_format();
  591. format(new_format.protection(protection_, optional<bool>(true)));
  592. }
  593. template <>
  594. XLNT_API std::string cell::value() const
  595. {
  596. return value<rich_text>().plain_text();
  597. }
  598. template <>
  599. XLNT_API rich_text cell::value() const
  600. {
  601. if (data_type() == cell::type::shared_string)
  602. {
  603. return workbook().shared_strings(static_cast<std::size_t>(d_->value_numeric_));
  604. }
  605. return d_->value_text_;
  606. }
  607. bool cell::has_value() const
  608. {
  609. return d_->type_ != cell::type::empty;
  610. }
  611. std::string cell::to_string() const
  612. {
  613. auto nf = computed_number_format();
  614. switch (data_type())
  615. {
  616. case cell::type::empty:
  617. return "";
  618. case cell::type::date:
  619. case cell::type::number:
  620. return nf.format(value<double>(), base_date());
  621. case cell::type::inline_string:
  622. case cell::type::shared_string:
  623. case cell::type::formula_string:
  624. case cell::type::error:
  625. return nf.format(value<std::string>());
  626. case cell::type::boolean:
  627. return value<double>() == 0.0 ? "FALSE" : "TRUE";
  628. }
  629. return "";
  630. }
  631. bool cell::has_format() const
  632. {
  633. return d_->format_.is_set();
  634. }
  635. void cell::format(const class format new_format)
  636. {
  637. if (has_format())
  638. {
  639. format().d_->references -= format().d_->references > 0 ? 1 : 0;
  640. }
  641. ++new_format.d_->references;
  642. d_->format_ = new_format.d_;
  643. }
  644. calendar cell::base_date() const
  645. {
  646. return workbook().base_date();
  647. }
  648. bool operator==(std::nullptr_t, const cell &cell)
  649. {
  650. return cell.data_type() == cell::type::empty;
  651. }
  652. bool operator==(const cell &cell, std::nullptr_t)
  653. {
  654. return nullptr == cell;
  655. }
  656. XLNT_API std::ostream &operator<<(std::ostream &stream, const xlnt::cell &cell)
  657. {
  658. return stream << cell.to_string();
  659. }
  660. void cell::value(const std::string &value_string, bool infer_type)
  661. {
  662. value(value_string);
  663. if (!infer_type || value_string.empty())
  664. {
  665. return;
  666. }
  667. if (value_string.front() == '=' && value_string.size() > 1)
  668. {
  669. formula(value_string);
  670. return;
  671. }
  672. if (value_string.front() == '#' && value_string.size() > 1)
  673. {
  674. error(value_string);
  675. return;
  676. }
  677. auto percentage = cast_percentage(value_string);
  678. if (percentage.first)
  679. {
  680. d_->value_numeric_ = percentage.second;
  681. d_->type_ = cell::type::number;
  682. number_format(xlnt::number_format::percentage());
  683. }
  684. else
  685. {
  686. auto time = cast_time(value_string);
  687. if (time.first)
  688. {
  689. d_->type_ = cell::type::number;
  690. number_format(number_format::date_time6());
  691. d_->value_numeric_ = time.second.to_number();
  692. }
  693. else
  694. {
  695. auto numeric = cast_numeric(value_string);
  696. if (numeric.first)
  697. {
  698. d_->value_numeric_ = numeric.second;
  699. d_->type_ = cell::type::number;
  700. }
  701. }
  702. }
  703. }
  704. void cell::clear_format()
  705. {
  706. if (d_->format_.is_set())
  707. {
  708. format().d_->references -= format().d_->references > 0 ? 1 : 0;
  709. d_->format_.clear();
  710. }
  711. }
  712. void cell::clear_style()
  713. {
  714. if (has_format())
  715. {
  716. modifiable_format().clear_style();
  717. }
  718. }
  719. void cell::style(const class style &new_style)
  720. {
  721. auto new_format = has_format() ? format() : workbook().create_format();
  722. new_format.border(new_style.border());
  723. new_format.fill(new_style.fill());
  724. new_format.font(new_style.font());
  725. new_format.number_format(new_style.number_format());
  726. format(new_format.style(new_style));
  727. }
  728. void cell::style(const std::string &style_name)
  729. {
  730. style(workbook().style(style_name));
  731. }
  732. style cell::style()
  733. {
  734. if (!has_format() || !format().has_style())
  735. {
  736. throw invalid_attribute();
  737. }
  738. auto f = format();
  739. return f.style();
  740. }
  741. const style cell::style() const
  742. {
  743. if (!has_format() || !format().has_style())
  744. {
  745. throw invalid_attribute();
  746. }
  747. return format().style();
  748. }
  749. bool cell::has_style() const
  750. {
  751. return has_format() && format().has_style();
  752. }
  753. format cell::modifiable_format()
  754. {
  755. if (!d_->format_.is_set())
  756. {
  757. throw invalid_attribute();
  758. }
  759. return xlnt::format(d_->format_.get());
  760. }
  761. const format cell::format() const
  762. {
  763. if (!d_->format_.is_set())
  764. {
  765. throw invalid_attribute();
  766. }
  767. return xlnt::format(d_->format_.get());
  768. }
  769. alignment cell::alignment() const
  770. {
  771. return format().alignment();
  772. }
  773. border cell::border() const
  774. {
  775. return format().border();
  776. }
  777. fill cell::fill() const
  778. {
  779. return format().fill();
  780. }
  781. font cell::font() const
  782. {
  783. return format().font();
  784. }
  785. number_format cell::number_format() const
  786. {
  787. return format().number_format();
  788. }
  789. protection cell::protection() const
  790. {
  791. return format().protection();
  792. }
  793. bool cell::has_hyperlink() const
  794. {
  795. return d_->hyperlink_.is_set();
  796. }
  797. // comment
  798. bool cell::has_comment()
  799. {
  800. return d_->comment_.is_set();
  801. }
  802. void cell::clear_comment()
  803. {
  804. if (has_comment())
  805. {
  806. d_->parent_->comments_.erase(reference().to_string());
  807. d_->comment_.clear();
  808. }
  809. }
  810. class comment cell::comment()
  811. {
  812. if (!has_comment())
  813. {
  814. throw xlnt::exception("cell has no comment");
  815. }
  816. return *d_->comment_.get();
  817. }
  818. void cell::comment(const std::string &text, const std::string &author)
  819. {
  820. comment(xlnt::comment(text, author));
  821. }
  822. void cell::comment(const std::string &text, const class font &comment_font, const std::string &author)
  823. {
  824. comment(xlnt::comment(xlnt::rich_text(text, comment_font), author));
  825. }
  826. void cell::comment(const class comment &new_comment)
  827. {
  828. if (has_comment())
  829. {
  830. *d_->comment_.get() = new_comment;
  831. }
  832. else
  833. {
  834. d_->parent_->comments_[reference().to_string()] = new_comment;
  835. d_->comment_.set(&d_->parent_->comments_[reference().to_string()]);
  836. }
  837. // offset comment 5 pixels down and 5 pixels right of the top right corner of the cell
  838. auto cell_position = anchor();
  839. cell_position.first += static_cast<int>(width()) + 5;
  840. cell_position.second += 5;
  841. d_->comment_.get()->position(cell_position.first, cell_position.second);
  842. worksheet().register_comments_in_manifest();
  843. }
  844. double cell::width() const
  845. {
  846. return worksheet().column_width(column());
  847. }
  848. double cell::height() const
  849. {
  850. return worksheet().row_height(row());
  851. }
  852. } // namespace xlnt