mirror of https://github.com/tfussell/xlnt
Merge 6dda4a23e6
into 297b331435
commit
98d698fb6a
|
@ -82,6 +82,7 @@ struct stylesheet;
|
|||
struct workbook_impl;
|
||||
class xlsx_consumer;
|
||||
class xlsx_producer;
|
||||
struct defined_name;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
@ -751,6 +752,38 @@ public:
|
|||
/// </summary>
|
||||
bool known_fonts_enabled() const;
|
||||
|
||||
// Defined Names
|
||||
|
||||
/// <summary>
|
||||
/// Add a defined name to a sheet
|
||||
/// </summary
|
||||
void add_defined_name(detail::defined_name name);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a copy of workbook defined names
|
||||
/// </summary>
|
||||
std::vector<detail::defined_name> get_defined_names() const;
|
||||
|
||||
/// <summary>
|
||||
/// Returns a reference to a single defined name
|
||||
/// </summary>
|
||||
detail::defined_name &get_defined_name(const std::size_t index);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a reference to a single defined name. Finds the first name that matches, there may be multiple with the same name
|
||||
/// </summary>
|
||||
detail::defined_name &get_defined_name(const std::string &name);
|
||||
|
||||
/// <summary>
|
||||
/// Removes the defined name at the given index
|
||||
/// </summary>
|
||||
void remove_defined_name(const std::size_t index);
|
||||
|
||||
/// <summary>
|
||||
/// Removes the defined name that first matches the passed name.
|
||||
/// </summary>
|
||||
void remove_defined_name(const std::string &name);
|
||||
|
||||
// Manifest
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -64,7 +64,7 @@ namespace detail {
|
|||
|
||||
class xlsx_consumer;
|
||||
class xlsx_producer;
|
||||
|
||||
struct defined_name;
|
||||
struct worksheet_impl;
|
||||
|
||||
} // namespace detail
|
||||
|
@ -729,6 +729,38 @@ public:
|
|||
/// </summary>
|
||||
cell_reference active_cell() const;
|
||||
|
||||
// Defined Names
|
||||
|
||||
/// <summary>
|
||||
/// Add a defined name to a sheet
|
||||
/// </summary
|
||||
void add_defined_name(detail::defined_name name);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a copy of workbook defined names
|
||||
/// </summary>
|
||||
std::vector<detail::defined_name> get_defined_names() const;
|
||||
|
||||
/// <summary>
|
||||
/// Returns a reference to a single defined name
|
||||
/// </summary>
|
||||
detail::defined_name &get_defined_name(const std::size_t index);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a reference to a single defined name. Finds the first name that matches, there may be multiple with the same name
|
||||
/// </summary>
|
||||
detail::defined_name &get_defined_name(const std::string &name);
|
||||
|
||||
/// <summary>
|
||||
/// Removes the defined name at the given index
|
||||
/// </summary>
|
||||
void remove_defined_name(const std::size_t index);
|
||||
|
||||
/// <summary>
|
||||
/// Removes the defined name that first matches the passed name.
|
||||
/// </summary>
|
||||
void remove_defined_name(const std::string &name);
|
||||
|
||||
// page breaks
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include <detail/implementations/stylesheet.hpp>
|
||||
#include <detail/implementations/worksheet_impl.hpp>
|
||||
#include <detail/serialization/defined_name.hpp>
|
||||
#include <xlnt/packaging/ext_list.hpp>
|
||||
#include <xlnt/packaging/manifest.hpp>
|
||||
#include <xlnt/utils/datetime.hpp>
|
||||
|
@ -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<std::string> abs_path_;
|
||||
optional<std::size_t> arch_id_flags_;
|
||||
optional<ext_list> extensions_;
|
||||
std::vector<defined_name> defined_names_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include <xlnt/worksheet/print_options.hpp>
|
||||
#include <xlnt/worksheet/sheet_pr.hpp>
|
||||
#include <detail/implementations/cell_impl.hpp>
|
||||
#include <detail/serialization/defined_name.hpp>
|
||||
|
||||
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::spreadsheet_drawing> drawing_;
|
||||
|
||||
std::vector<defined_name> defined_names_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
|
|
@ -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<std::string> comment; // A string representing a comment about the defined name.
|
||||
optional<std::string> custom_menu; // A string representing the new custom menu text
|
||||
optional<std::string> description; // A string representing the new description text for the defined name.
|
||||
optional<std::string> help; // A string representing the new help topic text.
|
||||
optional<std::string> status_bar; // A string representing the new status bar text.
|
||||
optional<std::size_t> 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<bool> hidden; // A Boolean value indicating whether the named range is now hidden.
|
||||
optional<bool> function; // A Boolean value indicating that the defined name refers to a function. True if the defined name is a function, false otherwise.
|
||||
optional<std::size_t> function_group_id;// Represents the new function group id.
|
||||
optional<std::string> 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
|
||||
|
|
|
@ -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<std::size_t>("localSheetId");
|
||||
name.hidden = false;
|
||||
|
||||
if (parser().attribute_present("comment"))
|
||||
{
|
||||
name.comment = parser().attribute<std::string>("comment");
|
||||
}
|
||||
|
||||
if (parser().attribute_present("customMenu"))
|
||||
{
|
||||
name.custom_menu = parser().attribute<std::string>("customMenu");
|
||||
}
|
||||
|
||||
if (parser().attribute_present("description"))
|
||||
{
|
||||
name.description = parser().attribute<std::string>("description");
|
||||
}
|
||||
|
||||
if (parser().attribute_present("help"))
|
||||
{
|
||||
name.help = parser().attribute<std::string>("help");
|
||||
}
|
||||
|
||||
if (parser().attribute_present("statusBar"))
|
||||
{
|
||||
name.status_bar = parser().attribute<std::string>("statusBar");
|
||||
}
|
||||
|
||||
if (parser().attribute_present("localSheetId"))
|
||||
{
|
||||
name.sheet_id = parser().attribute<std::size_t>("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<std::size_t>("functionGroupId");
|
||||
}
|
||||
|
||||
if (parser().attribute_present("shortcutKey"))
|
||||
{
|
||||
name.shortcut_key = parser().attribute<std::string>("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<defined_name> 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
|
||||
|
|
|
@ -435,6 +435,9 @@ void xlsx_producer::write_workbook(const relationship &rel)
|
|||
std::size_t num_visible = 0;
|
||||
std::vector<defined_name> 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");
|
||||
}
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
#include <detail/serialization/open_stream.hpp>
|
||||
#include <detail/serialization/vector_streambuf.hpp>
|
||||
#include <detail/serialization/xlsx_consumer.hpp>
|
||||
#include <detail/serialization/defined_name.hpp>
|
||||
#include <detail/serialization/xlsx_producer.hpp>
|
||||
|
||||
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<detail::defined_name> 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
|
||||
|
|
|
@ -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<detail::defined_name> 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
|
||||
|
|
Binary file not shown.
|
@ -73,6 +73,7 @@ public:
|
|||
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 @@ public:
|
|||
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;
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include <xlnt/workbook/worksheet_iterator.hpp>
|
||||
#include <xlnt/worksheet/range.hpp>
|
||||
#include <xlnt/worksheet/worksheet.hpp>
|
||||
#include <detail/serialization/defined_name.hpp>
|
||||
|
||||
class workbook_test_suite : public test_suite
|
||||
{
|
||||
|
@ -60,6 +61,9 @@ public:
|
|||
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 @@ public:
|
|||
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;
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <xlnt/worksheet/range.hpp>
|
||||
#include <xlnt/worksheet/row_properties.hpp>
|
||||
#include <xlnt/worksheet/worksheet.hpp>
|
||||
#include <detail/serialization/defined_name.hpp>
|
||||
#include <helpers/test_suite.hpp>
|
||||
|
||||
class worksheet_test_suite : public test_suite
|
||||
|
@ -111,6 +112,9 @@ public:
|
|||
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 @@ public:
|
|||
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;
|
||||
|
|
Loading…
Reference in New Issue