From a52bcd5fef93e3fb6516bed104fc780e45d98f96 Mon Sep 17 00:00:00 2001 From: Thomas Fussell Date: Sun, 21 Aug 2022 10:57:02 -0500 Subject: [PATCH] implement defined names --- include/xlnt/worksheet/worksheet.hpp | 31 ++++-- .../detail/implementations/worksheet_impl.hpp | 5 +- source/detail/serialization/defined_name.hpp | 40 ++++++++ source/detail/serialization/xlsx_consumer.cpp | 92 +++++++++++++++++- source/detail/serialization/xlsx_consumer.hpp | 3 + source/detail/serialization/xlsx_producer.cpp | 72 +++++++++++--- source/worksheet/worksheet.cpp | 47 +++++---- tests/data/19_defined_names.xlsx | Bin 0 -> 9599 bytes tests/utils/datetime_test_suite.cpp | 8 +- tests/worksheet/worksheet_test_suite.cpp | 86 ++++++++-------- 10 files changed, 287 insertions(+), 97 deletions(-) create mode 100644 source/detail/serialization/defined_name.hpp create mode 100644 tests/data/19_defined_names.xlsx diff --git a/include/xlnt/worksheet/worksheet.hpp b/include/xlnt/worksheet/worksheet.hpp index 856c1a41..a4cf9e07 100644 --- a/include/xlnt/worksheet/worksheet.hpp +++ b/include/xlnt/worksheet/worksheet.hpp @@ -652,37 +652,52 @@ public: /// /// Sets rows to repeat at top during printing. /// - void print_title_rows(row_t first_row, row_t last_row); + void print_title_rows(row_t start, row_t end); /// - /// Sets rows to repeat at top during printing. + /// Get rows to repeat at top during printing. /// - void print_title_rows(row_t last_row); + optional> print_title_rows() const; /// /// Sets columns to repeat at left during printing. /// - void print_title_cols(column_t first_column, column_t last_column); + void print_title_cols(column_t start, column_t end); + + /// + /// Get columns to repeat at left during printing. + /// + optional> print_title_cols() const; /// - /// Sets columns to repeat at left during printing. + /// Returns true if the sheet has print titles defined. /// - void print_title_cols(column_t last_column); + bool has_print_titles() const; /// - /// Returns a string representation of the defined print titles. + /// Remove all print titles. /// - std::string print_titles() const; + void clear_print_titles(); /// /// Sets the print area of this sheet to print_area. /// void print_area(const std::string &print_area); + /// + /// Clear the print area of this sheet. + /// + void clear_print_area(); + /// /// Returns the print area defined for this sheet. /// range_reference print_area() const; + + /// + /// Returns true if the print area is defined for this sheet. + /// + bool has_print_area() const; /// /// Returns true if this sheet has any number of views defined. diff --git a/source/detail/implementations/worksheet_impl.hpp b/source/detail/implementations/worksheet_impl.hpp index 8c776a32..7afcfb1d 100644 --- a/source/detail/implementations/worksheet_impl.hpp +++ b/source/detail/implementations/worksheet_impl.hpp @@ -143,9 +143,8 @@ struct worksheet_impl optional phonetic_properties_; optional header_footer_; - std::string print_title_cols_; - std::string print_title_rows_; - + optional> print_title_cols_; + optional> print_title_rows_; optional print_area_; std::vector views_; diff --git a/source/detail/serialization/defined_name.hpp b/source/detail/serialization/defined_name.hpp new file mode 100644 index 00000000..3aeb9132 --- /dev/null +++ b/source/detail/serialization/defined_name.hpp @@ -0,0 +1,40 @@ +// Copyright (c) 2014-2021 Thomas Fussell +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE +// +// @license: http://www.opensource.org/licenses/mit-license.php +// @author: see AUTHORS file + +#pragma once + +#include + +namespace xlnt { +namespace detail { + +struct defined_name +{ + std::string name; + std::size_t sheet_id; + bool hidden; + std::string value; +}; + +} // namespace detail +} // namespace xlnt diff --git a/source/detail/serialization/xlsx_consumer.cpp b/source/detail/serialization/xlsx_consumer.cpp index 7959372a..88272872 100644 --- a/source/detail/serialization/xlsx_consumer.cpp +++ b/source/detail/serialization/xlsx_consumer.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -448,6 +449,70 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id) } } +void read_defined_names(worksheet ws, std::vector defined_names) +{ + for (auto &name : defined_names) + { + if (name.sheet_id != ws.id() - 1) + { + continue; + } + + if (name.name == "_xlnm.Print_Titles") + { + // Basic print titles parser + // A print title definition looks like "'Sheet3'!$B:$E,'Sheet3'!$2:$4" + // There are three cases: columns only, rows only, and both (separated by a comma). + // For this reason, we loop up to two times parsing each component. + // Titles may be quoted (with single quotes) or unquoted. We ignore them for now anyways. + // References are always absolute. + // Move this into a separate function if it needs to be used in other places. + auto i = std::size_t(0); + for (auto count = 0; count < 2; count++) + { + // Split into components based on "!", ":", and "," characters + auto j = i; + i = name.value.find("!", j); + auto title = name.value.substr(j, i - j); + j = i + 2; // skip "!$" + i = name.value.find(":", j); + auto from = name.value.substr(j, i - j); + j = i + 2; // skip ":$" + i = name.value.find(",", j); + auto to = name.value.substr(j, i - j); + + // Apply to the worksheet + if (isalpha(from.front())) // alpha=>columns + { + ws.print_title_cols(from, to); + } + else // numeric=>rows + { + ws.print_title_rows(std::stoul(from), std::stoul(to)); + } + + // Check for end condition + if (i == std::string::npos) + { + break; + } + + i++; // skip "," for next iteration + } + } + else if (name.name == "_xlnm._FilterDatabase") + { + auto i = name.value.find("!"); + ws.auto_filter(name.value.substr(i + 1)); + } + else if (name.name == "_xlnm.Print_Area") + { + auto i = name.value.find("!"); + ws.print_area(name.value.substr(i + 1)); + } + } +} + std::string xlsx_consumer::read_worksheet_begin(const std::string &rel_id) { if (streaming_ && streaming_cell_ == nullptr) @@ -468,6 +533,8 @@ std::string xlsx_consumer::read_worksheet_begin(const std::string &rel_id) expect_start_element(qn("spreadsheetml", "worksheet"), xml::content::complex); // CT_Worksheet skip_attributes({qn("mc", "Ignorable")}); + + read_defined_names(ws, defined_names_); while (in_element(qn("spreadsheetml", "worksheet"))) { @@ -2015,7 +2082,24 @@ void xlsx_consumer::read_office_document(const std::string &content_type) // CT_ } else if (current_workbook_element == qn("workbook", "definedNames")) // CT_DefinedNames 0-1 { - skip_remaining_content(current_workbook_element); + while (in_element(qn("workbook", "definedNames"))) + { + expect_start_element(qn("spreadsheetml", "definedName"), xml::content::mixed); + + defined_name name; + name.name = parser().attribute("name"); + name.sheet_id = parser().attribute("localSheetId"); + name.hidden = false; + if (parser().attribute_present("hidden")) + { + name.hidden = is_true(parser().attribute("hidden")); + } + parser().attribute_map(); // skip remaining attributes + name.value = read_text(); + defined_names_.push_back(name); + + expect_end_element(qn("spreadsheetml", "definedName")); + } } else if (current_workbook_element == qn("workbook", "calcPr")) // CT_CalcPr 0-1 { @@ -2123,14 +2207,14 @@ void xlsx_consumer::read_office_document(const std::string &content_type) // CT_ target_.d_->sheet_title_rel_id_map_.end(), [&](const std::pair &p) { return p.second == worksheet_rel.id(); - }) - ->first; + })->first; auto id = sheet_title_id_map_[title]; auto index = sheet_title_index_map_[title]; auto insertion_iter = target_.d_->worksheets_.begin(); - while (insertion_iter != target_.d_->worksheets_.end() && sheet_title_index_map_[insertion_iter->title_] < index) + while (insertion_iter != target_.d_->worksheets_.end() + && sheet_title_index_map_[insertion_iter->title_] < index) { ++insertion_iter; } diff --git a/source/detail/serialization/xlsx_consumer.hpp b/source/detail/serialization/xlsx_consumer.hpp index 914b76e9..182c9b36 100644 --- a/source/detail/serialization/xlsx_consumer.hpp +++ b/source/detail/serialization/xlsx_consumer.hpp @@ -56,6 +56,7 @@ namespace detail { class izstream; struct cell_impl; +struct defined_name; struct worksheet_impl; /// @@ -424,6 +425,8 @@ private: detail::worksheet_impl *current_worksheet_; number_serialiser converter_; + + std::vector defined_names_; }; } // namespace detail diff --git a/source/detail/serialization/xlsx_producer.cpp b/source/detail/serialization/xlsx_producer.cpp index 82df530a..6f6e26cc 100644 --- a/source/detail/serialization/xlsx_producer.cpp +++ b/source/detail/serialization/xlsx_producer.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -432,7 +433,7 @@ void xlsx_producer::write_custom_properties(const relationship & /*rel*/) void xlsx_producer::write_workbook(const relationship &rel) { std::size_t num_visible = 0; - bool any_defined_names = false; + std::vector defined_names; for (auto ws : source_) { @@ -440,10 +441,54 @@ void xlsx_producer::write_workbook(const relationship &rel) { num_visible++; } - + + auto title_ref = "'" + ws.title() + "'!"; + if (ws.has_auto_filter()) { - any_defined_names = true; + defined_name name; + name.sheet_id = ws.id(); + name.name = "_xlnm._FilterDatabase"; + name.hidden = true; + name.value = title_ref + range_reference::make_absolute(ws.auto_filter()).to_string(); + defined_names.push_back(name); + } + + if (ws.has_print_area()) + { + defined_name name; + name.sheet_id = ws.id(); + name.name = "_xlnm.Print_Area"; + name.hidden = false; + name.value = title_ref + range_reference::make_absolute(ws.print_area()).to_string(); + defined_names.push_back(name); + } + + if (ws.has_print_titles()) + { + defined_name name; + name.sheet_id = ws.id(); + name.name = "_xlnm.Print_Titles"; + name.hidden = false; + + auto cols = ws.print_title_cols(); + if (cols.is_set()) + { + name.value = title_ref + "$" + cols.get().first.column_string() + + ":" + "$" + cols.get().second.column_string(); + } + auto rows = ws.print_title_rows(); + if (rows.is_set()) + { + if (!name.value.empty()) + { + name.value.push_back(','); + } + name.value += title_ref + "$" + std::to_string(rows.get().first) + + ":" + "$" + std::to_string(rows.get().second); + } + + defined_names.push_back(name); } } @@ -612,16 +657,21 @@ void xlsx_producer::write_workbook(const relationship &rel) write_end_element(xmlns, "sheets"); - if (any_defined_names) + if (!defined_names.empty()) { write_start_element(xmlns, "definedNames"); - /* - write_attribute("name", "_xlnm._FilterDatabase"); - write_attribute("hidden", write_bool(true)); - write_attribute("localSheetId", "0"); - write_characters("'" + ws.title() + "'!" + - range_reference::make_absolute(ws.auto_filter()).to_string()); - */ + for (auto name : defined_names) + { + write_start_element(xmlns, "definedName"); + write_attribute("name", name.name); + if (name.hidden) + { + write_attribute("hidden", write_bool(true)); + } + write_attribute("localSheetId", std::to_string(name.sheet_id - 1)); // 0-indexed for some reason + write_characters(name.value); + write_end_element(xmlns, "definedName"); + } write_end_element(xmlns, "definedNames"); } diff --git a/source/worksheet/worksheet.cpp b/source/worksheet/worksheet.cpp index d7e7d9ef..bd64ac37 100644 --- a/source/worksheet/worksheet.cpp +++ b/source/worksheet/worksheet.cpp @@ -1146,40 +1146,35 @@ worksheet::const_iterator worksheet::end() const return cend(); } -void worksheet::print_title_rows(row_t last_row) +void worksheet::print_title_rows(row_t start, row_t end) { - print_title_rows(1, last_row); + d_->print_title_rows_ = std::make_pair(start, end); } -void worksheet::print_title_rows(row_t first_row, row_t last_row) +optional> worksheet::print_title_rows() const { - d_->print_title_rows_ = std::to_string(first_row) + ":" + std::to_string(last_row); + return d_->print_title_rows_; } -void worksheet::print_title_cols(column_t last_column) +void worksheet::print_title_cols(column_t start, column_t end) { - print_title_cols(1, last_column); + d_->print_title_cols_ = std::make_pair(start, end); } -void worksheet::print_title_cols(column_t first_column, column_t last_column) +optional> worksheet::print_title_cols() const { - d_->print_title_cols_ = first_column.column_string() + ":" + last_column.column_string(); + return d_->print_title_cols_; } -std::string worksheet::print_titles() const +bool worksheet::has_print_titles() const { - if (!d_->print_title_rows_.empty() && !d_->print_title_cols_.empty()) - { - return d_->title_ + "!" + d_->print_title_rows_ + "," + d_->title_ + "!" + d_->print_title_cols_; - } - else if (!d_->print_title_cols_.empty()) - { - return d_->title_ + "!" + d_->print_title_cols_; - } - else - { - return d_->title_ + "!" + d_->print_title_rows_; - } + return d_->print_title_cols_.is_set() || d_->print_title_rows_.is_set(); +} + +void worksheet::clear_print_titles() +{ + d_->print_title_rows_.clear(); + d_->print_title_cols_.clear(); } void worksheet::print_area(const std::string &print_area) @@ -1192,6 +1187,16 @@ range_reference worksheet::print_area() const return d_->print_area_.get(); } +bool worksheet::has_print_area() const +{ + return d_->print_area_.is_set(); +} + +void worksheet::clear_print_area() +{ + return d_->print_area_.clear(); +} + bool worksheet::has_view() const { return !d_->views_.empty(); diff --git a/tests/data/19_defined_names.xlsx b/tests/data/19_defined_names.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..4c430ba35d516f7518bfdc63a6c14933f6dd00c7 GIT binary patch literal 9599 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, "last"); } - void test_auto_filter() - { - xlnt::workbook wb; - auto ws = wb.active_sheet(); - - ws.auto_filter(ws.range("a1:f1")); - xlnt_assert_equals(ws.auto_filter(), "A1:F1"); - - ws.clear_auto_filter(); - xlnt_assert(!ws.has_auto_filter()); - - ws.auto_filter("c1:g9"); - xlnt_assert_equals(ws.auto_filter(), "C1:G9"); - } - void test_getitem() { xlnt::workbook wb; @@ -416,43 +398,53 @@ public: xlnt_assert_equals(ws.merged_ranges().size(), 0); } - void test_print_titles_old() + void test_defined_names() { xlnt::workbook wb; + wb.load(path_helper::test_file("19_defined_names.xlsx")); + + auto ws1 = wb.sheet_by_index(0); - auto ws = wb.active_sheet(); - ws.print_title_rows(3); - xlnt_assert_equals(ws.print_titles(), "Sheet1!1:3"); + xlnt_assert(!ws1.has_print_area()); - auto ws2 = wb.create_sheet(); - ws2.print_title_cols(4); - xlnt_assert_equals(ws2.print_titles(), "Sheet2!A:D"); - } + xlnt_assert(ws1.has_auto_filter()); + xlnt_assert_equals(ws1.auto_filter().to_string(), "A1:A6"); - void test_print_titles_new() - { - xlnt::workbook wb; + xlnt_assert(ws1.has_print_titles()); + xlnt_assert(!ws1.print_title_cols().is_set()); + xlnt_assert(ws1.print_title_rows().is_set()); + xlnt_assert_equals(ws1.print_title_rows().get().first, 1); + xlnt_assert_equals(ws1.print_title_rows().get().second, 3); + + auto ws2 = wb.sheet_by_index(1); - auto ws = wb.active_sheet(); - ws.print_title_rows(4); - xlnt_assert_equals(ws.print_titles(), "Sheet1!1:4"); + xlnt_assert(ws2.has_print_area()); + xlnt_assert_equals(ws2.print_area().to_string(), "$B$4:$B$4"); - auto ws2 = wb.create_sheet(); - ws2.print_title_cols("F"); - xlnt_assert_equals(ws2.print_titles(), "Sheet2!A:F"); + xlnt_assert(!ws2.has_auto_filter()); - auto ws3 = wb.create_sheet(); - ws3.print_title_rows(2, 3); - ws3.print_title_cols("C", "D"); - xlnt_assert_equals(ws3.print_titles(), "Sheet3!2:3,Sheet3!C:D"); - } + xlnt_assert(ws2.has_print_titles()); + xlnt_assert(!ws2.print_title_rows().is_set()); + xlnt_assert(ws2.print_title_cols().is_set()); + xlnt_assert_equals(ws2.print_title_cols().get().first, "A"); + xlnt_assert_equals(ws2.print_title_cols().get().second, "D"); + + auto ws3 = wb.sheet_by_index(2); - void test_print_area() - { - xlnt::workbook wb; - auto ws = wb.active_sheet(); - ws.print_area("A1:F5"); - xlnt_assert_equals(ws.print_area(), "$A$1:$F$5"); + xlnt_assert(ws3.has_print_area()); + xlnt_assert_equals(ws3.print_area().to_string(), "$B$2:$E$4"); + + xlnt_assert(!ws3.has_auto_filter()); + + xlnt_assert(ws3.has_print_titles()); + xlnt_assert(ws3.print_title_rows().is_set()); + xlnt_assert(ws3.print_title_cols().is_set()); + xlnt_assert_equals(ws3.print_title_cols().get().first, "B"); + xlnt_assert_equals(ws3.print_title_cols().get().second, "E"); + xlnt_assert_equals(ws3.print_title_rows().get().first, 2); + xlnt_assert_equals(ws3.print_title_rows().get().second, 4); + + wb.save("titles1.xlsx"); } void test_freeze_panes_horiz()