mirror of
https://github.com/tfussell/xlnt.git
synced 2024-03-22 13:11:17 +08:00
fix relative paths in relationships on round-trips. I really need to clean up relationship code
This commit is contained in:
parent
69032289ac
commit
4001a47ec0
|
@ -115,6 +115,7 @@ public:
|
|||
worksheet create_sheet(std::size_t index);
|
||||
worksheet create_sheet(const std::string &title);
|
||||
worksheet create_sheet(std::size_t index, const std::string &title);
|
||||
worksheet create_sheet(const std::string &title, const relationship &rel);
|
||||
|
||||
//add
|
||||
void add_sheet(worksheet worksheet);
|
||||
|
@ -172,6 +173,8 @@ public:
|
|||
std::vector<relationship> get_relationships() const;
|
||||
|
||||
private:
|
||||
static std::size_t index_from_ws_filename(const std::string &ws_filename);
|
||||
|
||||
friend class worksheet;
|
||||
std::shared_ptr<detail::workbook_impl> d_;
|
||||
};
|
||||
|
|
|
@ -61,7 +61,7 @@ public:
|
|||
static std::string write_worksheet_rels(worksheet ws);
|
||||
|
||||
private:
|
||||
static std::string write_relationships(const std::vector<relationship> &relationships);
|
||||
static std::string write_relationships(const std::vector<relationship> &relationships, const std::string &dir = "");
|
||||
};
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -180,8 +180,9 @@ worksheet workbook::create_sheet()
|
|||
}
|
||||
|
||||
d_->worksheets_.push_back(detail::worksheet_impl(this, title));
|
||||
create_relationship("rId" + std::to_string(d_->relationships_.size() + 1), "worksheets/sheet" + std::to_string(d_->worksheets_.size()) + ".xml", relationship::type::worksheet);
|
||||
return worksheet(&d_->worksheets_.back());
|
||||
create_relationship("rId" + std::to_string(d_->relationships_.size() + 1), "xl/worksheets/sheet" + std::to_string(d_->worksheets_.size()) + ".xml", relationship::type::worksheet);
|
||||
|
||||
return worksheet(&d_->worksheets_.back());
|
||||
}
|
||||
|
||||
void workbook::add_sheet(xlnt::worksheet worksheet)
|
||||
|
@ -311,7 +312,7 @@ bool workbook::load(const std::string &filename)
|
|||
|
||||
for(auto relationship : workbook_relationships)
|
||||
{
|
||||
create_relationship(relationship.get_id(), relationship.get_target_uri(), relationship.get_type());
|
||||
create_relationship(relationship.get_id(), relationship.get_target_uri(), relationship.get_type());
|
||||
}
|
||||
|
||||
pugi::xml_document doc;
|
||||
|
@ -346,9 +347,18 @@ bool workbook::load(const std::string &filename)
|
|||
|
||||
for(auto sheet_node : sheets_node.children("sheet"))
|
||||
{
|
||||
std::string relation_id = sheet_node.attribute("r:id").as_string();
|
||||
auto ws = create_sheet(sheet_node.attribute("name").as_string());
|
||||
auto sheet_filename = get_relationship(relation_id).get_target_uri();
|
||||
std::string rel_id = sheet_node.attribute("r:id").as_string();
|
||||
auto rel = std::find_if(d_->relationships_.begin(), d_->relationships_.end(),
|
||||
[&](relationship &rel) { return rel.get_id() == rel_id; });
|
||||
|
||||
if (rel == d_->relationships_.end())
|
||||
{
|
||||
throw std::runtime_error("relationship not found");
|
||||
}
|
||||
|
||||
auto ws = create_sheet(sheet_node.attribute("name").as_string(), *rel);
|
||||
auto sheet_filename = rel->get_target_uri();
|
||||
|
||||
xlnt::reader::read_worksheet(ws, f.read(sheet_filename).c_str(), shared_strings, number_format_ids);
|
||||
}
|
||||
|
||||
|
@ -400,14 +410,29 @@ worksheet workbook::create_sheet(std::size_t index)
|
|||
{
|
||||
create_sheet();
|
||||
|
||||
if(index != d_->worksheets_.size())
|
||||
{
|
||||
std::swap(d_->worksheets_[index], d_->worksheets_.back());
|
||||
}
|
||||
if (index != d_->worksheets_.size() - 1)
|
||||
{
|
||||
std::swap(d_->worksheets_.back(), d_->worksheets_[index]);
|
||||
d_->worksheets_.pop_back();
|
||||
}
|
||||
|
||||
return worksheet(&d_->worksheets_[index]);
|
||||
}
|
||||
|
||||
worksheet workbook::create_sheet(const std::string &title, const relationship &rel)
|
||||
{
|
||||
d_->worksheets_.push_back(detail::worksheet_impl(this, title));
|
||||
|
||||
auto index = index_from_ws_filename(rel.get_target_uri());
|
||||
if (index != d_->worksheets_.size() - 1)
|
||||
{
|
||||
std::swap(d_->worksheets_.back(), d_->worksheets_[index]);
|
||||
d_->worksheets_.pop_back();
|
||||
}
|
||||
|
||||
return worksheet(&d_->worksheets_[index]);
|
||||
}
|
||||
|
||||
worksheet workbook::create_sheet(std::size_t index, const std::string &title)
|
||||
{
|
||||
auto ws = create_sheet(index);
|
||||
|
@ -554,19 +579,9 @@ bool workbook::save(const std::string &filename)
|
|||
{
|
||||
if(relationship.get_type() == relationship::type::worksheet)
|
||||
{
|
||||
std::string sheet_index_string = relationship.get_target_uri();
|
||||
sheet_index_string = sheet_index_string.substr(0, sheet_index_string.find('.'));
|
||||
sheet_index_string = sheet_index_string.substr(sheet_index_string.find_last_of('/'));
|
||||
auto iter = sheet_index_string.end();
|
||||
iter--;
|
||||
while (isdigit(*iter)) iter--;
|
||||
auto first_digit = iter - sheet_index_string.begin();
|
||||
sheet_index_string = sheet_index_string.substr(first_digit + 1);
|
||||
auto sheet_index = std::stoi(sheet_index_string) - 1;
|
||||
|
||||
auto sheet_index = index_from_ws_filename(relationship.get_target_uri());
|
||||
auto ws = get_sheet_by_index(sheet_index);
|
||||
std::string sheet_uri = "xl/" + relationship.get_target_uri();
|
||||
f.writestr(sheet_uri, writer::write_worksheet(ws, shared_strings));
|
||||
f.writestr(relationship.get_target_uri(), writer::write_worksheet(ws, shared_strings));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -665,4 +680,18 @@ void workbook::set_data_only(bool data_only)
|
|||
d_->data_only_ = data_only;
|
||||
}
|
||||
|
||||
std::size_t workbook::index_from_ws_filename(const std::string &ws_filename)
|
||||
{
|
||||
std::string sheet_index_string(ws_filename);
|
||||
sheet_index_string = sheet_index_string.substr(0, sheet_index_string.find('.'));
|
||||
sheet_index_string = sheet_index_string.substr(sheet_index_string.find_last_of('/'));
|
||||
auto iter = sheet_index_string.end();
|
||||
iter--;
|
||||
while (isdigit(*iter)) iter--;
|
||||
auto first_digit = iter - sheet_index_string.begin();
|
||||
sheet_index_string = sheet_index_string.substr(first_digit + 1);
|
||||
auto sheet_index = std::stoi(sheet_index_string) - 1;
|
||||
return sheet_index;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -123,7 +123,7 @@ std::string writer::write_properties_app(const workbook &wb)
|
|||
|
||||
std::string writer::write_workbook_rels(const workbook &wb)
|
||||
{
|
||||
return write_relationships(wb.get_relationships());
|
||||
return write_relationships(wb.get_relationships(), "xl/");
|
||||
}
|
||||
|
||||
std::string writer::write_worksheet_rels(worksheet ws)
|
||||
|
@ -131,7 +131,6 @@ std::string writer::write_worksheet_rels(worksheet ws)
|
|||
return write_relationships(ws.get_relationships());
|
||||
}
|
||||
|
||||
|
||||
std::string writer::write_workbook(const workbook &wb)
|
||||
{
|
||||
pugi::xml_document doc;
|
||||
|
@ -571,18 +570,28 @@ std::string xlnt::writer::write_root_rels()
|
|||
return write_relationships(relationships);
|
||||
}
|
||||
|
||||
std::string writer::write_relationships(const std::vector<relationship> &relationships)
|
||||
std::string writer::write_relationships(const std::vector<relationship> &relationships, const std::string &dir)
|
||||
{
|
||||
pugi::xml_document doc;
|
||||
|
||||
auto root_node = doc.append_child("Relationships");
|
||||
root_node.append_attribute("xmlns").set_value(constants::Namespaces.at("relationships").c_str());
|
||||
|
||||
for(auto relationship : relationships)
|
||||
{
|
||||
auto target = relationship.get_target_uri();
|
||||
|
||||
if (dir != "" && target.substr(0, dir.size()) == dir)
|
||||
{
|
||||
target = target.substr(dir.size());
|
||||
}
|
||||
|
||||
auto app_props_node = root_node.append_child("Relationship");
|
||||
|
||||
app_props_node.append_attribute("Id").set_value(relationship.get_id().c_str());
|
||||
app_props_node.append_attribute("Target").set_value(relationship.get_target_uri().c_str());
|
||||
app_props_node.append_attribute("Target").set_value(target.c_str());
|
||||
app_props_node.append_attribute("Type").set_value(relationship.get_type_string().c_str());
|
||||
|
||||
if(relationship.get_target_mode() == target_mode::external)
|
||||
{
|
||||
app_props_node.append_attribute("TargetMode").set_value("External");
|
||||
|
|
Loading…
Reference in New Issue
Block a user