diff --git a/include/xlnt/workbook/workbook.hpp b/include/xlnt/workbook/workbook.hpp
index f7aa4e3c2..1b977aefe 100644
--- a/include/xlnt/workbook/workbook.hpp
+++ b/include/xlnt/workbook/workbook.hpp
@@ -82,6 +82,7 @@ struct stylesheet;
struct workbook_impl;
class xlsx_consumer;
class xlsx_producer;
+struct defined_name;
} // namespace detail
@@ -751,6 +752,38 @@ class XLNT_API workbook
///
bool known_fonts_enabled() const;
+ // Defined Names
+
+ ///
+ /// Add a defined name to a sheet
+ ///
+ /// Returns a copy of workbook defined names
+ ///
+ std::vector get_defined_names() const;
+
+ ///
+ /// Returns a reference to a single defined name
+ ///
+ detail::defined_name &get_defined_name(const std::size_t index);
+
+ ///
+ /// Returns a reference to a single defined name. Finds the first name that matches, there may be multiple with the same name
+ ///
+ detail::defined_name &get_defined_name(const std::string &name);
+
+ ///
+ /// Removes the defined name at the given index
+ ///
+ void remove_defined_name(const std::size_t index);
+
+ ///
+ /// Removes the defined name that first matches the passed name.
+ ///
+ void remove_defined_name(const std::string &name);
+
// Manifest
///
diff --git a/include/xlnt/worksheet/worksheet.hpp b/include/xlnt/worksheet/worksheet.hpp
index a4cf9e077..a303c3f9d 100644
--- a/include/xlnt/worksheet/worksheet.hpp
+++ b/include/xlnt/worksheet/worksheet.hpp
@@ -64,7 +64,7 @@ namespace detail {
class xlsx_consumer;
class xlsx_producer;
-
+struct defined_name;
struct worksheet_impl;
} // namespace detail
@@ -729,6 +729,38 @@ class XLNT_API worksheet
///
cell_reference active_cell() const;
+ // Defined Names
+
+ ///
+ /// Add a defined name to a sheet
+ ///
+ /// Returns a copy of workbook defined names
+ ///
+ std::vector get_defined_names() const;
+
+ ///
+ /// Returns a reference to a single defined name
+ ///
+ detail::defined_name &get_defined_name(const std::size_t index);
+
+ ///
+ /// Returns a reference to a single defined name. Finds the first name that matches, there may be multiple with the same name
+ ///
+ detail::defined_name &get_defined_name(const std::string &name);
+
+ ///
+ /// Removes the defined name at the given index
+ ///
+ void remove_defined_name(const std::size_t index);
+
+ ///
+ /// Removes the defined name that first matches the passed name.
+ ///
+ void remove_defined_name(const std::string &name);
+
// page breaks
///
diff --git a/source/detail/implementations/workbook_impl.hpp b/source/detail/implementations/workbook_impl.hpp
index 338146188..1f5c8301a 100644
--- a/source/detail/implementations/workbook_impl.hpp
+++ b/source/detail/implementations/workbook_impl.hpp
@@ -29,6 +29,7 @@
#include
#include
+#include
#include
#include
#include
@@ -88,11 +89,20 @@ struct workbook_impl
extended_properties_ = other.extended_properties_;
custom_properties_ = other.custom_properties_;
+ defined_names_ = other.defined_names_;
+
return *this;
}
- bool operator==(const workbook_impl &other)
+ bool operator==(const workbook_impl &other) const
{
+ if (defined_names_.size() != other.defined_names_.size()) return false;
+
+ for (std::size_t i = 0; i < defined_names_.size(); i++)
+ {
+ if (defined_names_[i] != other.defined_names_[i]) return false;
+ }
+
return active_sheet_index_ == other.active_sheet_index_
&& worksheets_ == other.worksheets_
&& shared_strings_ids_ == other.shared_strings_ids_
@@ -168,6 +178,7 @@ struct workbook_impl
optional abs_path_;
optional arch_id_flags_;
optional extensions_;
+ std::vector defined_names_;
};
} // namespace detail
diff --git a/source/detail/implementations/worksheet_impl.hpp b/source/detail/implementations/worksheet_impl.hpp
index 7afcfb1d5..94f6af0c3 100644
--- a/source/detail/implementations/worksheet_impl.hpp
+++ b/source/detail/implementations/worksheet_impl.hpp
@@ -41,6 +41,7 @@
#include
#include
#include
+#include
namespace xlnt {
@@ -88,6 +89,8 @@ struct worksheet_impl
extension_list_ = other.extension_list_;
sheet_properties_ = other.sheet_properties_;
print_options_ = other.print_options_;
+ defined_names_ = other.defined_names_;
+
for (auto &cell : cell_map_)
{
@@ -97,8 +100,15 @@ struct worksheet_impl
workbook *parent_;
- bool operator==(const worksheet_impl& rhs) const
+ bool operator==(const worksheet_impl &rhs) const
{
+ if (defined_names_.size() != rhs.defined_names_.size()) return false;
+
+ for (std::size_t i = 0; i < defined_names_.size(); i++)
+ {
+ if (defined_names_[i] != rhs.defined_names_[i]) return false;
+ }
+
return id_ == rhs.id_
&& title_ == rhs.title_
&& format_properties_ == rhs.format_properties_
@@ -122,6 +132,7 @@ struct worksheet_impl
&& print_options_ == rhs.print_options_
&& sheet_properties_ == rhs.sheet_properties_
&& extension_list_ == rhs.extension_list_;
+
}
std::size_t id_;
@@ -160,6 +171,8 @@ struct worksheet_impl
std::string drawing_rel_id_;
optional drawing_;
+
+ std::vector defined_names_;
};
} // namespace detail
diff --git a/source/detail/serialization/defined_name.hpp b/source/detail/serialization/defined_name.hpp
index 3aeb91323..82a44ead1 100644
--- a/source/detail/serialization/defined_name.hpp
+++ b/source/detail/serialization/defined_name.hpp
@@ -30,10 +30,63 @@ namespace detail {
struct defined_name
{
- std::string name;
- std::size_t sheet_id;
- bool hidden;
- std::string value;
+
+ defined_name &operator=(const defined_name &other)
+ {
+ name = other.name;
+ comment = other.comment;
+ custom_menu = other.custom_menu;
+ description = other.description;
+ help = other.help;
+
+ status_bar = other.status_bar;
+ sheet_id = other.sheet_id;
+ hidden = other.hidden;
+ function = other.function;
+ function_group_id = other.function_group_id;
+
+ shortcut_key = other.shortcut_key;
+ value = other.value;
+
+ return *this;
+ }
+
+ bool operator==(const defined_name &other) const
+ {
+ return name == other.name
+ && comment == other.comment
+ && custom_menu == other.custom_menu
+ && description == other.description
+ && help == other.help
+ && status_bar == other.status_bar
+ && sheet_id == other.sheet_id
+ && hidden == other.hidden
+ && function == other.function
+ && function_group_id == other.function_group_id
+ && shortcut_key == other.shortcut_key
+ && value == other.value;
+ }
+
+ bool operator!=(const defined_name &other) const
+ {
+ return !(*this == other);
+ }
+
+ // Implements (most of) CT_RevisionDefinedName, there's several "old" members in the spec but they're also ignored in other librarie
+ std::string name; // A string representing the name for this defined name.
+ optional comment; // A string representing a comment about the defined name.
+ optional custom_menu; // A string representing the new custom menu text
+ optional description; // A string representing the new description text for the defined name.
+ optional help; // A string representing the new help topic text.
+ optional status_bar; // A string representing the new status bar text.
+ optional sheet_id; // An integer representing the id of the sheet to which this defined name belongs. This shall be used local defined names only. 0 indexed indexed.
+ optional hidden; // A Boolean value indicating whether the named range is now hidden.
+ optional function; // A Boolean value indicating that the defined name refers to a function. True if the defined name is a function, false otherwise.
+ optional function_group_id;// Represents the new function group id.
+ optional shortcut_key; // Represents the new keyboard shortcut. This is unsigned byte in the spec, but openpyxl uses string so let's try that
+ std::string value; // The actual value of the name, ie "='Sheet1'!A1"
+
+
};
} // namespace detail
diff --git a/source/detail/serialization/xlsx_consumer.cpp b/source/detail/serialization/xlsx_consumer.cpp
index dc50106cb..1aa6a6d8c 100644
--- a/source/detail/serialization/xlsx_consumer.cpp
+++ b/source/detail/serialization/xlsx_consumer.cpp
@@ -534,7 +534,7 @@ 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_);
+ read_defined_names(ws, ws.d_->defined_names_);
while (in_element(qn("spreadsheetml", "worksheet")))
{
@@ -2082,16 +2082,61 @@ void xlsx_consumer::read_office_document(const std::string &content_type) // CT_
defined_name name;
name.name = parser().attribute("name");
- name.sheet_id = parser().attribute("localSheetId");
- name.hidden = false;
+
+ if (parser().attribute_present("comment"))
+ {
+ name.comment = parser().attribute("comment");
+ }
+
+ if (parser().attribute_present("customMenu"))
+ {
+ name.custom_menu = parser().attribute("customMenu");
+ }
+
+ if (parser().attribute_present("description"))
+ {
+ name.description = parser().attribute("description");
+ }
+
+ if (parser().attribute_present("help"))
+ {
+ name.help = parser().attribute("help");
+ }
+
+ if (parser().attribute_present("statusBar"))
+ {
+ name.status_bar = parser().attribute("statusBar");
+ }
+
+ if (parser().attribute_present("localSheetId"))
+ {
+ name.sheet_id = parser().attribute("localSheetId");
+ }
+
if (parser().attribute_present("hidden"))
{
name.hidden = is_true(parser().attribute("hidden"));
}
+
+ if (parser().attribute_present("function"))
+ {
+ name.function = is_true(parser().attribute("function"));
+ }
+
+ if (parser().attribute_present("functionGroupId"))
+ {
+ name.function_group_id = parser().attribute("functionGroupId");
+ }
+
+ if (parser().attribute_present("shortcutKey"))
+ {
+ name.shortcut_key = parser().attribute("shortcutKey");
+ }
+
parser().attribute_map(); // skip remaining attributes
name.value = read_text();
- defined_names_.push_back(name);
-
+ target_.d_->defined_names_.push_back(name);
+
expect_end_element(qn("spreadsheetml", "definedName"));
}
}
@@ -2195,6 +2240,7 @@ void xlsx_consumer::read_office_document(const std::string &content_type) // CT_
}
}
+ std::vector workbook_names;
for (auto worksheet_rel : manifest().relationships(workbook_path, relationship_type::worksheet))
{
auto title = std::find_if(target_.d_->sheet_title_rel_id_map_.begin(),
@@ -2203,7 +2249,7 @@ void xlsx_consumer::read_office_document(const std::string &content_type) // CT_
return p.second == worksheet_rel.id();
})->first;
- auto id = sheet_title_id_map_[title];
+ auto id = sheet_title_id_map_[title]; // 1-indexed
auto index = sheet_title_index_map_[title];
auto insertion_iter = target_.d_->worksheets_.begin();
@@ -2215,11 +2261,34 @@ void xlsx_consumer::read_office_document(const std::string &content_type) // CT_
current_worksheet_ = &*target_.d_->worksheets_.emplace(insertion_iter, &target_, id, title);
+ // If there's any defined names that are worksheet specific, move them here.
+ for (std::size_t i = 0; i < target_.d_->defined_names_.size(); i++)
+ {
+ const auto &name = target_.d_->defined_names_[i];
+ if (name.sheet_id.is_set())
+ {
+ const auto target_id = name.sheet_id.get();
+ if (target_id == index)
+ {
+ // It's a match, remove it from the workbook and add it to the sheet
+ current_worksheet_->defined_names_.push_back(name);
+ }
+ }
+ else
+ {
+ // Name is global and belongs to the workbook, if i'ts not already added
+ if (std::find(workbook_names.begin(), workbook_names.end(), name) == workbook_names.end())
+ workbook_names.push_back(name);
+ }
+ }
+
if (!streaming_)
{
read_part({workbook_rel, worksheet_rel});
}
}
+ // Update the workbook with the new defined names
+ target_.d_->defined_names_ = workbook_names;
}
// Write Workbook Relationship Target Parts
diff --git a/source/detail/serialization/xlsx_producer.cpp b/source/detail/serialization/xlsx_producer.cpp
index 6f6e26ccc..06051958f 100644
--- a/source/detail/serialization/xlsx_producer.cpp
+++ b/source/detail/serialization/xlsx_producer.cpp
@@ -435,6 +435,9 @@ void xlsx_producer::write_workbook(const relationship &rel)
std::size_t num_visible = 0;
std::vector defined_names;
+ defined_names = source_.d_->defined_names_;
+ std::size_t sheet_id = 1;
+
for (auto ws : source_)
{
if (!ws.has_page_setup() || ws.page_setup().sheet_state() == sheet_state::visible)
@@ -444,30 +447,35 @@ void xlsx_producer::write_workbook(const relationship &rel)
auto title_ref = "'" + ws.title() + "'!";
+ bool added_auto_filter = false;
+ bool added_print_area = false;
+ bool added_print_titles = false;
if (ws.has_auto_filter())
{
defined_name name;
- name.sheet_id = ws.id();
+ name.sheet_id = sheet_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);
+ added_auto_filter = true;
}
if (ws.has_print_area())
{
defined_name name;
- name.sheet_id = ws.id();
+ name.sheet_id = sheet_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);
+ added_print_area = true;
}
if (ws.has_print_titles())
{
defined_name name;
- name.sheet_id = ws.id();
+ name.sheet_id = sheet_id;
name.name = "_xlnm.Print_Titles";
name.hidden = false;
@@ -489,7 +497,22 @@ void xlsx_producer::write_workbook(const relationship &rel)
}
defined_names.push_back(name);
+ added_print_titles = true;
+ }
+ // Add any sheet defined names to the vector
+ for (auto &sheet_defined_name : ws.d_->defined_names_)
+ {
+ sheet_defined_name.sheet_id = sheet_id;
+ if (sheet_defined_name.name == "_xlnm._FilterDatabase" && !added_auto_filter)
+ defined_names.push_back(sheet_defined_name);
+ else if (sheet_defined_name.name == "_xlnm.Print_Area" && !added_print_area)
+ defined_names.push_back(sheet_defined_name);
+ else if (sheet_defined_name.name == "_xlnm.Print_Titles" && !added_print_titles)
+ defined_names.push_back(sheet_defined_name);
+ else if (!added_auto_filter && !added_print_area && !added_print_titles)
+ defined_names.push_back(sheet_defined_name);
}
+ sheet_id++;
}
if (num_visible == 0)
@@ -664,11 +687,66 @@ void xlsx_producer::write_workbook(const relationship &rel)
{
write_start_element(xmlns, "definedName");
write_attribute("name", name.name);
- if (name.hidden)
+
+ if (name.comment.is_set())
{
- write_attribute("hidden", write_bool(true));
+ write_attribute("comment", name.comment.get());
}
- write_attribute("localSheetId", std::to_string(name.sheet_id - 1)); // 0-indexed for some reason
+
+ if (name.custom_menu.is_set())
+ {
+ write_attribute("customMenu", name.custom_menu.get());
+ }
+
+ if (name.description.is_set())
+ {
+ write_attribute("description", name.description.get());
+ }
+
+ if (name.help.is_set())
+ {
+ write_attribute("help", name.help.get());
+ }
+
+ if (name.status_bar.is_set())
+ {
+ write_attribute("statusBar", name.status_bar.get());
+ }
+
+ if (name.sheet_id.is_set())
+ {
+ write_attribute("localSheetId", std::to_string(name.sheet_id.get() - 1)); // Don't think this is meant to require subtracting 1?
+ }
+
+ if (name.hidden.is_set())
+ {
+ const auto hidden_state = name.hidden.get();
+ if (hidden_state)
+ {
+ write_attribute("hidden", write_bool(true));
+ }
+ }
+
+ if (name.function.is_set())
+ {
+ const auto function_state = name.function.get();
+ if (function_state)
+ {
+ write_attribute("function", write_bool(true));
+ }
+ }
+
+ if (name.function_group_id.is_set())
+ {
+ const auto function_group_id = name.function_group_id.get();
+ write_attribute("functionGroupId", std::to_string(function_group_id));
+ }
+
+ if (name.shortcut_key.is_set())
+ {
+ write_attribute("shortcutKey", name.shortcut_key.get());
+ }
+
write_characters(name.value);
write_end_element(xmlns, "definedName");
}
diff --git a/source/workbook/workbook.cpp b/source/workbook/workbook.cpp
index dce9d3bd0..6bf067494 100644
--- a/source/workbook/workbook.cpp
+++ b/source/workbook/workbook.cpp
@@ -60,6 +60,7 @@
#include
#include
#include
+#include
#include
namespace {
@@ -1713,4 +1714,50 @@ void workbook::reorder_relationships()
}
}
+void workbook::add_defined_name(detail::defined_name name)
+{
+ d_->defined_names_.push_back(name);
+}
+
+std::vector workbook::get_defined_names() const
+{
+ return d_->defined_names_;
+}
+
+detail::defined_name &workbook::get_defined_name(const std::size_t index)
+{
+ return d_->defined_names_[index];
+}
+
+detail::defined_name &workbook::get_defined_name(const std::string &name)
+{
+ // Only return the first matching
+ for (auto &defined_name : d_->defined_names_)
+ if (defined_name.name == name)
+ return defined_name;
+ throw key_not_found();
+}
+
+void workbook::remove_defined_name(const std::size_t index)
+{
+ d_->defined_names_.erase(d_->defined_names_.begin() + index);
+}
+
+void workbook::remove_defined_name(const std::string &name)
+{
+ // Only remove first matching
+ std::size_t offending_index = 0;
+ std::size_t index = 0;
+ for (auto &defined_name : d_->defined_names_)
+ {
+ if (defined_name.name == name)
+ {
+ offending_index = index;
+ break;
+ }
+ index++;
+ }
+ if (d_->defined_names_.size() > 0)
+ remove_defined_name(offending_index);
+}
} // namespace xlnt
diff --git a/source/worksheet/worksheet.cpp b/source/worksheet/worksheet.cpp
index bd64ac37d..9b3829a79 100644
--- a/source/worksheet/worksheet.cpp
+++ b/source/worksheet/worksheet.cpp
@@ -1352,4 +1352,51 @@ bool worksheet::is_empty() const
return d_->cell_map_.empty();
}
+void worksheet::add_defined_name(detail::defined_name name)
+{
+ d_->defined_names_.push_back(name);
+}
+
+std::vector worksheet::get_defined_names() const
+{
+ return d_->defined_names_;
+}
+
+detail::defined_name &worksheet::get_defined_name(const std::size_t index)
+{
+ return d_->defined_names_[index];
+}
+
+detail::defined_name &worksheet::get_defined_name(const std::string &name)
+{
+ // Only return the first matching
+ for (auto &defined_name : d_->defined_names_)
+ if (defined_name.name == name)
+ return defined_name;
+ throw key_not_found();
+}
+
+void worksheet::remove_defined_name(const std::size_t index)
+{
+ d_->defined_names_.erase(d_->defined_names_.begin() + index);
+}
+
+void worksheet::remove_defined_name(const std::string &name)
+{
+ // Only remove first matching
+ std::size_t offending_index = 0;
+ std::size_t index = 0;
+ for (auto &defined_name : d_->defined_names_)
+ {
+ if (defined_name.name == name)
+ {
+ offending_index = index;
+ break;
+ }
+ index++;
+ }
+ if (d_->defined_names_.size() > 0)
+ remove_defined_name(offending_index);
+}
+
} // namespace xlnt
diff --git a/tests/data/19_defined_names.xlsx b/tests/data/19_defined_names.xlsx
index 4c430ba35..a1708d863 100644
Binary files a/tests/data/19_defined_names.xlsx and b/tests/data/19_defined_names.xlsx differ
diff --git a/tests/workbook/serialization_test_suite.cpp b/tests/workbook/serialization_test_suite.cpp
index ca6383a18..8fea0ede2 100644
--- a/tests/workbook/serialization_test_suite.cpp
+++ b/tests/workbook/serialization_test_suite.cpp
@@ -73,6 +73,7 @@ class serialization_test_suite : public test_suite
register_test(test_Issue503_external_link_load);
register_test(test_formatting);
register_test(test_active_sheet);
+ register_test(test_named_range);
}
bool workbook_matches_file(xlnt::workbook &wb, const xlnt::path &file)
@@ -808,6 +809,11 @@ class serialization_test_suite : public test_suite
wb.load(path_helper::test_file("20_active_sheet.xlsx"));
xlnt_assert_equals(wb.active_sheet(), wb[2]);
}
+
+ void test_named_range()
+ {
+ xlnt_assert(round_trip_matches_rw(path_helper::test_file("19_defined_names.xlsx")));
+ }
};
static serialization_test_suite x;
diff --git a/tests/workbook/workbook_test_suite.cpp b/tests/workbook/workbook_test_suite.cpp
index 09e37660a..8dab88ac9 100644
--- a/tests/workbook/workbook_test_suite.cpp
+++ b/tests/workbook/workbook_test_suite.cpp
@@ -36,6 +36,7 @@
#include
#include
#include
+#include
class workbook_test_suite : public test_suite
{
@@ -60,6 +61,9 @@ class workbook_test_suite : public test_suite
register_test(test_add_named_range);
register_test(test_get_named_range);
register_test(test_remove_named_range);
+ register_test(test_add_defined_name);
+ register_test(test_modify_defined_name);
+ register_test(test_remove_defined_name);
register_test(test_post_increment_iterator);
register_test(test_copy_iterator);
register_test(test_manifest);
@@ -342,6 +346,63 @@ class workbook_test_suite : public test_suite
xlnt_assert_throws(wb.remove_named_range("test_nr2"), std::runtime_error);
}
+ void test_add_defined_name()
+ {
+ xlnt::workbook wb;
+ auto new_sheet = wb.create_sheet();
+
+ xlnt::detail::defined_name name;
+ const std::string dname = "Workbook Defined Name";
+ const std::string dcomment = "This should only exist on a workbook";
+ name.name = dname;
+ name.comment = dcomment;
+ name.value = "='Sheet1'!A1";
+ wb.add_defined_name(name);
+
+ xlnt_assert(wb.get_defined_names().size() == 1);
+ }
+
+ void test_modify_defined_name()
+ {
+ xlnt::workbook wb;
+ auto new_sheet = wb.create_sheet();
+
+ xlnt::detail::defined_name name;
+ const std::string dname = "Workbook Defined Name";
+ const std::string dcomment = "This should only exist on a workbook";
+ name.name = dname;
+ name.comment = dcomment;
+ name.value = "='Sheet1'!A1";
+ wb.add_defined_name(name);
+
+ xlnt_assert(wb.get_defined_name(0).name == dname);
+ xlnt_assert(wb.get_defined_name(dname).comment == dcomment);
+
+ wb.get_defined_name(0).hidden = true;
+ xlnt_assert(wb.get_defined_name(0).hidden == true);
+
+ xlnt_assert_throws(wb.get_defined_name("Doesn't exist"), xlnt::key_not_found);
+ }
+
+ void test_remove_defined_name()
+ {
+ xlnt::workbook wb;
+ auto new_sheet = wb.create_sheet();
+
+ xlnt::detail::defined_name name;
+ const std::string dname = "Workbook Defined Name";
+ const std::string dcomment = "This should only exist on a workbook";
+ name.name = dname;
+ name.comment = dcomment;
+ name.value = "='Sheet1'!A1";
+ wb.add_defined_name(name);
+
+ xlnt_assert(wb.get_defined_names().size() == 1);
+ wb.remove_defined_name(dname);
+
+ xlnt_assert(wb.get_defined_names().size() == 0);
+ }
+
void test_post_increment_iterator()
{
xlnt::workbook wb;
diff --git a/tests/worksheet/worksheet_test_suite.cpp b/tests/worksheet/worksheet_test_suite.cpp
index 9c1097a04..696dd3c48 100644
--- a/tests/worksheet/worksheet_test_suite.cpp
+++ b/tests/worksheet/worksheet_test_suite.cpp
@@ -29,6 +29,7 @@
#include
#include
#include
+#include
#include
class worksheet_test_suite : public test_suite
@@ -111,6 +112,9 @@ class worksheet_test_suite : public test_suite
register_test(test_hidden_sheet);
register_test(test_xlsm_read_write);
register_test(test_issue_484);
+ register_test(test_add_defined_name);
+ register_test(test_modify_defined_name);
+ register_test(test_remove_defined_name);
}
void test_new_worksheet()
@@ -1674,6 +1678,69 @@ class worksheet_test_suite : public test_suite
xlnt_assert_equals("B12:B12", ws.columns(true).reference());
xlnt_assert_equals("A1:B12", ws.columns(false).reference());
}
+
+
+ void test_add_defined_name()
+ {
+ xlnt::workbook wb;
+ auto ws = wb.create_sheet();
+
+ xlnt::detail::defined_name name;
+ const std::string dname = "Worksheet Defined Name";
+ const std::string dcomment = "This should only exist on a Worksheet";
+ name.name = dname;
+ name.comment = dcomment;
+ name.value = "='Sheet1'!A1";
+ ws.add_defined_name(name);
+
+ xlnt_assert(ws.get_defined_names().size() == 1);
+ ws = wb.create_sheet();
+ xlnt_assert(ws.get_defined_names().size() == 0);
+ }
+
+ void test_modify_defined_name()
+ {
+ xlnt::workbook wb;
+ auto ws = wb.create_sheet();
+
+ xlnt::detail::defined_name name;
+ const std::string dname = "Worksheet Defined Name";
+ const std::string dcomment = "This should only exist on a Worksheet";
+ name.name = dname;
+ name.comment = dcomment;
+ name.value = "='Sheet1'!A1";
+ ws.add_defined_name(name);
+
+ xlnt_assert(ws.get_defined_name(0).name == dname);
+ xlnt_assert(ws.get_defined_name(dname).comment == dcomment);
+
+ ws.get_defined_name(0).hidden = true;
+ xlnt_assert(ws.get_defined_name(0).hidden == true);
+
+ xlnt_assert_throws(ws.get_defined_name("Doesn't exist"), xlnt::key_not_found);
+
+ ws = wb.create_sheet();
+ xlnt_assert_throws(ws.get_defined_name(dname), xlnt::key_not_found);
+ }
+
+ void test_remove_defined_name()
+ {
+ xlnt::workbook wb;
+ auto ws = wb.create_sheet();
+
+ xlnt::detail::defined_name name;
+ const std::string dname = "Worksheet Defined Name";
+ const std::string dcomment = "This should only exist on a Worksheet";
+ name.name = dname;
+ name.comment = dcomment;
+ name.value = "='Sheet1'!A1";
+ ws.add_defined_name(name);
+
+ xlnt_assert(ws.get_defined_names().size() == 1);
+ ws.remove_defined_name(dname);
+
+ xlnt_assert(ws.get_defined_names().size() == 0);
+ }
};
static worksheet_test_suite x;