From c43561b4bdfb66caa78e2acfb7d513c0810cd4b0 Mon Sep 17 00:00:00 2001 From: Thomas Fussell Date: Mon, 2 Jan 2017 19:12:23 -0500 Subject: [PATCH] remove calcChain when no formulae remain in any cell, correct calcChain relationship type string, closes #98 --- include/xlnt/workbook/workbook.hpp | 5 +++ include/xlnt/worksheet/worksheet.hpp | 5 +++ source/cell/cell.cpp | 3 +- source/detail/custom_value_traits.cpp | 2 +- source/workbook/tests/test_consume_xlsx.hpp | 12 +++++++ source/workbook/tests/test_produce_xlsx.hpp | 11 +++++++ source/workbook/workbook.cpp | 34 ++++++++++++++++++++ source/worksheet/worksheet.cpp | 5 +++ tests/data/22_formulae.xlsx | Bin 0 -> 21677 bytes 9 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 tests/data/22_formulae.xlsx diff --git a/include/xlnt/workbook/workbook.hpp b/include/xlnt/workbook/workbook.hpp index 4d6f5405..eab4ade7 100644 --- a/include/xlnt/workbook/workbook.hpp +++ b/include/xlnt/workbook/workbook.hpp @@ -758,6 +758,11 @@ private: /// void register_comments_in_manifest(worksheet ws); + /// + /// Removes calcChain part from manifest if no formulae remain in workbook. + /// + void garbage_collect_formulae(); + /// /// An opaque pointer to a structure that holds all of the data relating to this workbook. /// diff --git a/include/xlnt/worksheet/worksheet.hpp b/include/xlnt/worksheet/worksheet.hpp index 13205352..16fc9dc5 100644 --- a/include/xlnt/worksheet/worksheet.hpp +++ b/include/xlnt/worksheet/worksheet.hpp @@ -742,6 +742,11 @@ private: /// void register_comments_in_manifest(); + /// + /// Removes calcChain part from manifest if no formulae remain in workbook. + /// + void garbage_collect_formulae(); + /// /// /// diff --git a/source/cell/cell.cpp b/source/cell/cell.cpp index f1beb65b..7a60e095 100644 --- a/source/cell/cell.cpp +++ b/source/cell/cell.cpp @@ -508,6 +508,7 @@ std::string cell::formula() const void cell::clear_formula() { d_->formula_.clear(); + worksheet().garbage_collect_formulae(); } void cell::error(const std::string &error) @@ -609,8 +610,8 @@ void cell::clear_value() { d_->value_numeric_ = 0; d_->value_text_.clear(); - d_->formula_.clear(); d_->type_ = cell::type::null; + clear_formula(); } template <> diff --git a/source/detail/custom_value_traits.cpp b/source/detail/custom_value_traits.cpp index bd92dc82..928097c7 100644 --- a/source/detail/custom_value_traits.cpp +++ b/source/detail/custom_value_traits.cpp @@ -37,7 +37,7 @@ std::string to_string(relationship_type t) case relationship_type::thumbnail: return "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail"; case relationship_type::calculation_chain: - return "http://purl.oclc.org/ooxml/officeDocument/relationships/calcChain"; + return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/calcChain"; case relationship_type::extended_properties: return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties"; case relationship_type::core_properties: diff --git a/source/workbook/tests/test_consume_xlsx.hpp b/source/workbook/tests/test_consume_xlsx.hpp index b6a4ba77..44e0dddf 100644 --- a/source/workbook/tests/test_consume_xlsx.hpp +++ b/source/workbook/tests/test_consume_xlsx.hpp @@ -112,4 +112,16 @@ public: TS_ASSERT(wb.has_custom_property("Client")); TS_ASSERT_EQUALS(wb.custom_property("Client"), "me!"); } + + void test_read_formulae() + { + xlnt::workbook wb; + wb.load("data/22_formulae.xlsx"); + auto ws = wb.active_sheet(); + TS_ASSERT_EQUALS(ws.cell("A1").value(), 6); + TS_ASSERT(ws.cell("A1").has_formula()); + TS_ASSERT_EQUALS(ws.cell("A1").formula(), "A2*A3"); + TS_ASSERT_EQUALS(ws.cell("A2").value(), 2); + TS_ASSERT_EQUALS(ws.cell("A3").value(), 3); + } }; diff --git a/source/workbook/tests/test_produce_xlsx.hpp b/source/workbook/tests/test_produce_xlsx.hpp index e42b1f29..a3bffa32 100644 --- a/source/workbook/tests/test_produce_xlsx.hpp +++ b/source/workbook/tests/test_produce_xlsx.hpp @@ -154,4 +154,15 @@ public: TS_ASSERT(workbook_matches_file(wb, xlnt::path("data/15_basic_comments.xlsx"))); } + + void test_save_after_clear_all_formulae() + { + xlnt::workbook wb; + wb.load("data/22_formulae.xlsx"); + auto ws = wb.active_sheet(); + TS_ASSERT(ws.cell("A1").has_formula()); + TS_ASSERT_EQUALS(ws.cell("A1").formula(), "A2*A3"); + ws.cell("A1").clear_formula(); + wb.save("clear_formulae.xlsx"); + } }; diff --git a/source/workbook/workbook.cpp b/source/workbook/workbook.cpp index 87b9480e..288c5882 100644 --- a/source/workbook/workbook.cpp +++ b/source/workbook/workbook.cpp @@ -1260,4 +1260,38 @@ void workbook::calculation_properties(const class calculation_properties &props) d_->calculation_properties_ = props; } +/// +/// Removes calcChain part from manifest if no formulae remain in workbook. +/// +void workbook::garbage_collect_formulae() +{ + auto any_with_formula = false; + + for (auto ws : *this) + { + for (auto row : ws.iter_cells(true)) + { + for (auto cell : row) + { + if (cell.has_formula()) + { + any_with_formula = true; + } + } + } + } + + if (any_with_formula) return; + + auto wb_rel = manifest().relationship(path("/"), relationship_type::office_document); + + if (manifest().has_relationship(wb_rel.target().path(), relationship_type::calculation_chain)) + { + auto calc_chain_rel = manifest().relationship(wb_rel.target().path(), relationship_type::calculation_chain); + auto calc_chain_part = manifest().canonicalize({wb_rel, calc_chain_rel}); + manifest().unregister_override_type(calc_chain_part); + manifest().unregister_relationship(wb_rel.target(), calc_chain_rel.id()); + } +} + } // namespace xlnt diff --git a/source/worksheet/worksheet.cpp b/source/worksheet/worksheet.cpp index 7e1438ee..9531cf18 100644 --- a/source/worksheet/worksheet.cpp +++ b/source/worksheet/worksheet.cpp @@ -1068,4 +1068,9 @@ double worksheet::row_height(row_t row) const } } +void worksheet::garbage_collect_formulae() +{ + workbook().garbage_collect_formulae(); +} + } // namespace xlnt diff --git a/tests/data/22_formulae.xlsx b/tests/data/22_formulae.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..e450aec09642aa437704ad2621ad382dfeb56bfc GIT binary patch literal 21677 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 literal 0 HcmV?d00001