mirror of
https://github.com/tfussell/xlnt.git
synced 2024-03-22 13:11:17 +08:00
keep refactoring serialization code
This commit is contained in:
parent
c884ad7f82
commit
75ec0f8eee
|
@ -21,7 +21,7 @@ project "xlnt.test"
|
|||
"../../tests/runner-autogen.cpp"
|
||||
}
|
||||
links { "xlnt", "miniz" }
|
||||
prebuildcommands { "../generate-tests.sh" }
|
||||
prebuildcommands { "../../generate-tests.sh" }
|
||||
flags { "Unicode" }
|
||||
configuration "windows"
|
||||
defines { "WIN32" }
|
||||
|
|
|
@ -37,7 +37,7 @@ class workbook;
|
|||
class excel_serializer
|
||||
{
|
||||
public:
|
||||
static std::string central_directory_signature();
|
||||
static const std::string central_directory_signature();
|
||||
static std::string repair_central_directory(const std::string &original);
|
||||
|
||||
excel_serializer(workbook &wb);
|
||||
|
@ -46,9 +46,9 @@ public:
|
|||
bool load_stream_workbook(std::istream &stream, bool guess_types = false, bool data_only = false);
|
||||
bool load_virtual_workbook(const std::vector<std::uint8_t> &bytes, bool guess_types = false, bool data_only = false);
|
||||
|
||||
bool save_workbook(workbook &wb, const std::string &filename, bool as_template = false);
|
||||
bool save_virtual_workbook(xlnt::workbook &wb, std::vector<std::uint8_t> &bytes, bool as_template = false);
|
||||
bool save_stream_workbook(xlnt::workbook &wb, std::ostream &stream, bool as_template = false);
|
||||
bool save_workbook(const std::string &filename, bool as_template = false);
|
||||
bool save_virtual_workbook(std::vector<std::uint8_t> &bytes, bool as_template = false);
|
||||
bool save_stream_workbook(std::ostream &stream, bool as_template = false);
|
||||
|
||||
private:
|
||||
void read_data(bool guess_types, bool data_only);
|
||||
|
|
|
@ -14,7 +14,7 @@ class manifest_serializer
|
|||
public:
|
||||
manifest_serializer(manifest &m);
|
||||
|
||||
bool read_mainfest(const xml_document &xml);
|
||||
bool read_manifest(const xml_document &xml);
|
||||
bool write_manifest(xml_document &xml);
|
||||
|
||||
private:
|
||||
|
|
|
@ -10,8 +10,9 @@ class xml_document;
|
|||
|
||||
class relationship_serializer
|
||||
{
|
||||
bool read_relationships(const xml_document &xml, const std::string &dir, std::vector<relationship> &relationships);
|
||||
bool write_relationships(const std::vector<relationship> &relationships, const std::string &dir, xml_document &xml);
|
||||
public:
|
||||
static bool read_relationships(const xml_document &xml, const std::string &dir, std::vector<relationship> &relationships);
|
||||
static bool write_relationships(const std::vector<relationship> &relationships, const std::string &dir, xml_document &xml);
|
||||
};
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -26,11 +26,14 @@
|
|||
#include <string>
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
class theme;
|
||||
class xml_document;
|
||||
|
||||
class theme_serializer
|
||||
{
|
||||
public:
|
||||
theme read_theme(const xml_document &xml);
|
||||
//theme read_theme(const xml_document &xml);
|
||||
xml_document write_theme(const theme &theme_);
|
||||
};
|
||||
|
||||
|
|
|
@ -35,10 +35,14 @@ class worksheet;
|
|||
class workbook;
|
||||
class zip_file;
|
||||
class xml_document;
|
||||
class xml_node;
|
||||
|
||||
class workbook_serializer
|
||||
{
|
||||
public:
|
||||
//TODO: does this go here?
|
||||
static std::string determine_document_type(const manifest &manifest_);
|
||||
|
||||
workbook_serializer(workbook &wb);
|
||||
|
||||
void read_workbook(const xml_document &xml);
|
||||
|
@ -48,17 +52,14 @@ public:
|
|||
xml_document write_workbook() const;
|
||||
xml_document write_properties_app() const;
|
||||
xml_document write_properties_core() const;
|
||||
|
||||
|
||||
private:
|
||||
//workbook_view, sheets, sheet, defined_names
|
||||
std::string determine_document_type(const manifest &manifest_);
|
||||
|
||||
using string_pair = std::pair<std::string, std::string>;
|
||||
|
||||
std::vector<string_pair> read_sheets(zip_file &archive);
|
||||
std::vector<string_pair> detect_worksheets(zip_file &archive);
|
||||
|
||||
std::string write_defined_names(const workbook &wb);
|
||||
bool write_named_ranges(xml_node &named_ranges_node);
|
||||
|
||||
workbook &wb_;
|
||||
};
|
||||
|
|
|
@ -41,9 +41,8 @@ class worksheet_serializer
|
|||
public:
|
||||
worksheet_serializer(worksheet sheet);
|
||||
|
||||
bool read_worksheet(const xml_document &xml, const std::vector<std::string> &shared_strings, const relationship &rel, worksheet ws);
|
||||
std::string read_dimension(const xml_node &dimension_node);
|
||||
bool write_worksheet(const worksheet ws, const std::vector<std::string> &string_table, xml_document &xml);
|
||||
bool read_worksheet(const xml_document &xml, const std::vector<std::string> &shared_strings, const relationship &rel);
|
||||
bool write_worksheet(const std::vector<std::string> &string_table, xml_document &xml);
|
||||
|
||||
private:
|
||||
worksheet sheet_;
|
||||
|
|
|
@ -22,6 +22,7 @@ public:
|
|||
|
||||
const std::vector<xml_node> &get_children() const;
|
||||
bool has_child(const std::string &child_name) const;
|
||||
xml_node &get_child(const std::string &child_name);
|
||||
const xml_node &get_child(const std::string &child_name) const;
|
||||
xml_node &add_child(const xml_node &child);
|
||||
xml_node &add_child(const std::string &child_name);
|
||||
|
|
|
@ -70,6 +70,8 @@ public:
|
|||
color get_color() const { return color_; }
|
||||
|
||||
bool has_family() const { return has_family_; }
|
||||
int get_family() const { return family_; }
|
||||
|
||||
bool has_scheme() const { return has_scheme_; }
|
||||
|
||||
std::size_t hash() const
|
||||
|
|
|
@ -50,12 +50,6 @@ enum class border_style
|
|||
class side
|
||||
{
|
||||
public:
|
||||
enum class color_type
|
||||
{
|
||||
theme,
|
||||
indexed
|
||||
};
|
||||
|
||||
side();
|
||||
|
||||
std::size_t hash() const
|
||||
|
|
|
@ -49,6 +49,7 @@ class range;
|
|||
class range_reference;
|
||||
class relationship;
|
||||
class style;
|
||||
class theme;
|
||||
class worksheet;
|
||||
class zip_file;
|
||||
|
||||
|
@ -199,7 +200,7 @@ public:
|
|||
|
||||
void create_relationship(const std::string &id, const std::string &target, relationship::type type);
|
||||
relationship get_relationship(const std::string &id) const;
|
||||
std::vector<relationship> get_relationships() const;
|
||||
const std::vector<relationship> &get_relationships() const;
|
||||
|
||||
void add_alignment(const alignment &a);
|
||||
void add_border(const border &b);
|
||||
|
@ -237,8 +238,8 @@ public:
|
|||
|
||||
void set_code_name(const std::string &code_name);
|
||||
|
||||
bool has_loaded_theme();
|
||||
std::string get_loaded_theme();
|
||||
bool has_loaded_theme() const;
|
||||
const theme &get_loaded_theme() const;
|
||||
|
||||
const style &get_style(std::size_t style_id) const;
|
||||
std::size_t add_style(const style &style_);
|
||||
|
@ -246,6 +247,8 @@ public:
|
|||
manifest &get_manifest();
|
||||
const manifest &get_manifest() const;
|
||||
|
||||
const std::vector<relationship> &get_root_relationships() const;
|
||||
|
||||
private:
|
||||
friend class worksheet;
|
||||
std::shared_ptr<detail::workbook_impl> d_;
|
||||
|
|
|
@ -223,7 +223,7 @@ public:
|
|||
|
||||
// relationships
|
||||
relationship create_relationship(relationship::type type, const std::string &target_uri);
|
||||
std::vector<relationship> get_relationships();
|
||||
const std::vector<relationship> &get_relationships() const;
|
||||
|
||||
// charts
|
||||
//void add_chart(chart chart);
|
||||
|
@ -262,7 +262,9 @@ public:
|
|||
const range operator()(const cell_reference &top_left, const cell_reference &bottom_right) const;
|
||||
|
||||
// page
|
||||
page_setup &get_page_setup();
|
||||
const page_setup &get_page_setup() const;
|
||||
margins &get_page_margins();
|
||||
const margins &get_page_margins() const;
|
||||
|
||||
// auto filter
|
||||
|
|
|
@ -42,11 +42,9 @@ const std::string download_url = "https://github.com/tfussell/xlnt/archive/maste
|
|||
#include "common/relationship.hpp"
|
||||
#include "common/string_table.hpp"
|
||||
#include "common/zip_file.hpp"
|
||||
#include "reader/excel_reader.hpp"
|
||||
#include "workbook/document_properties.hpp"
|
||||
#include "workbook/named_range.hpp"
|
||||
#include "workbook/workbook.hpp"
|
||||
#include "worksheet/range.hpp"
|
||||
#include "worksheet/range_reference.hpp"
|
||||
#include "worksheet/worksheet.hpp"
|
||||
#include "writer/workbook_writer.hpp"
|
||||
|
|
|
@ -13,7 +13,8 @@ struct workbook_impl
|
|||
workbook_impl(const workbook_impl &other)
|
||||
: active_sheet_index_(other.active_sheet_index_),
|
||||
worksheets_(other.worksheets_),
|
||||
relationships_(other.relationships_),
|
||||
relationships_(other.relationships_),
|
||||
root_relationships_(other.root_relationships_),
|
||||
drawings_(other.drawings_),
|
||||
properties_(other.properties_),
|
||||
guess_types_(other.guess_types_),
|
||||
|
@ -35,6 +36,8 @@ struct workbook_impl
|
|||
std::copy(other.worksheets_.begin(), other.worksheets_.end(), back_inserter(worksheets_));
|
||||
relationships_.clear();
|
||||
std::copy(other.relationships_.begin(), other.relationships_.end(), std::back_inserter(relationships_));
|
||||
root_relationships_.clear();
|
||||
std::copy(other.root_relationships_.begin(), other.root_relationships_.end(), std::back_inserter(root_relationships_));
|
||||
drawings_.clear();
|
||||
std::copy(other.drawings_.begin(), other.drawings_.end(), back_inserter(drawings_));
|
||||
properties_ = other.properties_;
|
||||
|
@ -54,6 +57,7 @@ struct workbook_impl
|
|||
std::size_t active_sheet_index_;
|
||||
std::vector<worksheet_impl> worksheets_;
|
||||
std::vector<relationship> relationships_;
|
||||
std::vector<relationship> root_relationships_;
|
||||
std::vector<drawing> drawings_;
|
||||
|
||||
document_properties properties_;
|
||||
|
@ -72,6 +76,8 @@ struct workbook_impl
|
|||
std::vector<number_format> number_formats_;
|
||||
|
||||
manifest manifest_;
|
||||
|
||||
theme theme_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
|
|
@ -1,7 +1,20 @@
|
|||
#include <xlnt/s11n/excel_serializer.hpp>
|
||||
#include <xlnt/common/exceptions.hpp>
|
||||
#include <xlnt/s11n/manifest_serializer.hpp>
|
||||
#include <xlnt/s11n/relationship_serializer.hpp>
|
||||
#include <xlnt/s11n/shared_strings_serializer.hpp>
|
||||
#include <xlnt/s11n/style_serializer.hpp>
|
||||
#include <xlnt/s11n/theme_serializer.hpp>
|
||||
#include <xlnt/s11n/workbook_serializer.hpp>
|
||||
#include <xlnt/s11n/worksheet_serializer.hpp>
|
||||
#include <xlnt/s11n/xml_document.hpp>
|
||||
#include <xlnt/s11n/xml_serializer.hpp>
|
||||
#include <xlnt/workbook/document_properties.hpp>
|
||||
#include <xlnt/workbook/manifest.hpp>
|
||||
#include <xlnt/workbook/workbook.hpp>
|
||||
#include <xlnt/worksheet/worksheet.hpp>
|
||||
|
||||
#include <detail/constants.hpp>
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -22,99 +35,69 @@ std::string::size_type find_string_in_string(const std::string &string, const st
|
|||
return possible_match_index;
|
||||
}
|
||||
|
||||
xlnt::workbook load_workbook(xlnt::zip_file &archive, bool guess_types, bool data_only)
|
||||
bool load_workbook(xlnt::zip_file &archive, bool guess_types, bool data_only, xlnt::workbook &wb)
|
||||
{
|
||||
xlnt::workbook wb;
|
||||
|
||||
wb.set_guess_types(guess_types);
|
||||
wb.set_data_only(data_only);
|
||||
|
||||
auto content_types = xlnt::read_content_types(archive);
|
||||
auto type = xlnt::determine_document_type(content_types);
|
||||
xlnt::manifest_serializer ms(wb.get_manifest());
|
||||
ms.read_manifest(xlnt::xml_serializer::deserialize(archive.read(xlnt::constants::ArcContentTypes)));
|
||||
|
||||
if(type != "excel")
|
||||
if(xlnt::workbook_serializer::determine_document_type(wb.get_manifest()) != "excel")
|
||||
{
|
||||
throw xlnt::invalid_file_exception("");
|
||||
}
|
||||
|
||||
wb.clear();
|
||||
|
||||
auto workbook_relationships = read_relationships(archive, "xl/workbook.xml");
|
||||
std::vector<xlnt::relationship> workbook_relationships;
|
||||
xlnt::relationship_serializer::read_relationships(xlnt::xml_serializer::deserialize(archive.read("xl/_rels/workbook.xml.rels")), "", workbook_relationships);
|
||||
|
||||
for(auto relationship : workbook_relationships)
|
||||
{
|
||||
wb.create_relationship(relationship.get_id(), relationship.get_target_uri(), relationship.get_type());
|
||||
}
|
||||
|
||||
pugi::xml_document doc;
|
||||
doc.load(archive.read("xl/workbook.xml").c_str());
|
||||
auto xml = xlnt::xml_serializer::deserialize(archive.read(xlnt::constants::ArcWorkbook));
|
||||
|
||||
auto root_node = doc.child("workbook");
|
||||
auto &root_node = xml.root();
|
||||
|
||||
auto workbook_pr_node = root_node.child("workbookPr");
|
||||
wb.get_properties().excel_base_date = (workbook_pr_node.attribute("date1904") != nullptr && workbook_pr_node.attribute("date1904").as_int() != 0) ? xlnt::calendar::mac_1904 : xlnt::calendar::windows_1900;
|
||||
auto &workbook_pr_node = root_node.get_child("workbookPr");
|
||||
wb.get_properties().excel_base_date = (workbook_pr_node.has_attribute("date1904") && workbook_pr_node.get_attribute("date1904") != "0") ? xlnt::calendar::mac_1904 : xlnt::calendar::windows_1900;
|
||||
|
||||
auto sheets_node = root_node.child("sheets");
|
||||
xlnt::shared_strings_serializer shared_strings_serializer_;
|
||||
std::vector<std::string> shared_strings;
|
||||
shared_strings_serializer_.read_strings(xlnt::xml_serializer::deserialize(archive.read(xlnt::constants::ArcSharedString)), shared_strings);
|
||||
|
||||
xlnt::shared_strings_reader shared_strings_reader_;
|
||||
auto shared_strings = shared_strings_reader_.read_strings(archive);
|
||||
xlnt::style_serializer style_reader_(wb);
|
||||
style_reader_.read_stylesheet(xlnt::xml_serializer::deserialize(archive.read(xlnt::constants::ArcStyles)));
|
||||
|
||||
xlnt::style_reader style_reader_(wb);
|
||||
style_reader_.read_styles(archive);
|
||||
auto &sheets_node = root_node.get_child("sheets");
|
||||
|
||||
for(const auto &border_ : style_reader_.get_borders())
|
||||
for(auto sheet_node : sheets_node.get_children())
|
||||
{
|
||||
wb.add_border(border_);
|
||||
}
|
||||
|
||||
for(const auto &fill_ : style_reader_.get_fills())
|
||||
{
|
||||
wb.add_fill(fill_);
|
||||
}
|
||||
|
||||
for(const auto &font_ : style_reader_.get_fonts())
|
||||
{
|
||||
wb.add_font(font_);
|
||||
}
|
||||
|
||||
for(const auto &number_format_ : style_reader_.get_number_formats())
|
||||
{
|
||||
wb.add_number_format(number_format_);
|
||||
}
|
||||
|
||||
for(auto &color_rgb : style_reader_.get_colors())
|
||||
{
|
||||
wb.add_color(xlnt::color(xlnt::color::type::rgb, color_rgb));
|
||||
}
|
||||
|
||||
for(const auto &style : style_reader_.get_styles())
|
||||
{
|
||||
wb.add_style(style);
|
||||
}
|
||||
|
||||
for(auto sheet_node : sheets_node.children("sheet"))
|
||||
{
|
||||
auto rel = wb.get_relationship(sheet_node.attribute("r:id").as_string());
|
||||
auto ws = wb.create_sheet(sheet_node.attribute("name").as_string(), rel);
|
||||
auto rel = wb.get_relationship(sheet_node.get_attribute("r:id"));
|
||||
auto ws = wb.create_sheet(sheet_node.get_attribute("name"), rel);
|
||||
|
||||
xlnt::read_worksheet(ws, archive, rel, shared_strings);
|
||||
xlnt::worksheet_serializer worksheet_serializer(ws);
|
||||
worksheet_serializer.read_worksheet(xlnt::xml_serializer::deserialize(archive.read(rel.get_target_uri())), shared_strings, rel);
|
||||
}
|
||||
|
||||
return wb;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
std::string excel_reader::CentralDirectorySignature()
|
||||
const std::string excel_serializer::central_directory_signature()
|
||||
{
|
||||
return "\x50\x4b\x05\x06";
|
||||
}
|
||||
|
||||
std::string excel_reader::repair_central_directory(const std::string &original)
|
||||
std::string excel_serializer::repair_central_directory(const std::string &original)
|
||||
{
|
||||
auto pos = find_string_in_string(original, CentralDirectorySignature());
|
||||
auto pos = find_string_in_string(original, central_directory_signature());
|
||||
|
||||
if(pos != std::string::npos)
|
||||
{
|
||||
|
@ -124,104 +107,76 @@ std::string excel_reader::repair_central_directory(const std::string &original)
|
|||
return original;
|
||||
}
|
||||
|
||||
workbook excel_reader::load_workbook(std::istream &stream, bool guess_types, bool data_only)
|
||||
bool excel_serializer::load_stream_workbook(std::istream &stream, bool guess_types, bool data_only)
|
||||
{
|
||||
std::vector<std::uint8_t> bytes((std::istream_iterator<char>(stream)),
|
||||
std::istream_iterator<char>());
|
||||
|
||||
return load_workbook(bytes, guess_types, data_only);
|
||||
|
||||
return load_virtual_workbook(bytes, guess_types, data_only);
|
||||
}
|
||||
|
||||
workbook excel_reader::load_workbook(const std::string &filename, bool guess_types, bool data_only)
|
||||
bool excel_serializer::load_workbook(const std::string &filename, bool guess_types, bool data_only)
|
||||
{
|
||||
xlnt::zip_file archive;
|
||||
|
||||
try
|
||||
{
|
||||
archive.load(filename);
|
||||
archive_.load(filename);
|
||||
}
|
||||
catch(std::runtime_error)
|
||||
{
|
||||
throw invalid_file_exception(filename);
|
||||
}
|
||||
|
||||
return ::load_workbook(archive, guess_types, data_only);
|
||||
return ::load_workbook(archive_, guess_types, data_only, wb_);
|
||||
}
|
||||
|
||||
xlnt::workbook excel_reader::load_workbook(const std::vector<std::uint8_t> &bytes, bool guess_types, bool data_only)
|
||||
bool excel_serializer::load_virtual_workbook(const std::vector<std::uint8_t> &bytes, bool guess_types, bool data_only)
|
||||
{
|
||||
xlnt::zip_file archive;
|
||||
archive.load(bytes);
|
||||
archive_.load(bytes);
|
||||
|
||||
return ::load_workbook(archive, guess_types, data_only);
|
||||
return ::load_workbook(archive_, guess_types, data_only, wb_);
|
||||
}
|
||||
|
||||
excel_writer::excel_writer(workbook &wb) : wb_(wb)
|
||||
excel_serializer::excel_serializer(workbook &wb) : wb_(wb)
|
||||
{
|
||||
}
|
||||
|
||||
void excel_writer::save(const std::string &filename, bool as_template)
|
||||
void excel_serializer::write_data(bool as_template)
|
||||
{
|
||||
zip_file archive;
|
||||
write_data(archive, as_template);
|
||||
archive.save(filename);
|
||||
relationship_serializer relationship_serializer_;
|
||||
|
||||
xlnt::xml_document root_rels_xml;
|
||||
relationship_serializer_.write_relationships(wb_.get_root_relationships(), "", root_rels_xml);
|
||||
archive_.writestr(constants::ArcRootRels, xml_serializer::serialize(root_rels_xml));
|
||||
|
||||
xml_document workbook_rels_xml;
|
||||
relationship_serializer_.write_relationships(wb_.get_relationships(), "", workbook_rels_xml);
|
||||
archive_.writestr(constants::ArcWorkbookRels, xml_serializer::serialize(workbook_rels_xml));
|
||||
|
||||
xml_document properties_app_xml;
|
||||
workbook_serializer workbook_serializer_(wb_);
|
||||
archive_.writestr(constants::ArcApp, xml_serializer::serialize(workbook_serializer_.write_properties_app()));
|
||||
archive_.writestr(constants::ArcCore, xml_serializer::serialize(workbook_serializer_.write_properties_core()));
|
||||
|
||||
theme_serializer theme_serializer_;
|
||||
xml_document theme_xml = theme_serializer_.write_theme(wb_.get_loaded_theme());
|
||||
archive_.writestr(constants::ArcTheme, xml_serializer::serialize(theme_xml));
|
||||
|
||||
archive_.writestr(constants::ArcWorkbook, xml_serializer::serialize(workbook_serializer_.write_workbook()));
|
||||
|
||||
style_serializer style_serializer_(wb_);
|
||||
xml_document style_xml;
|
||||
style_serializer_.write_stylesheet(style_xml);
|
||||
archive_.writestr(constants::ArcStyles, xml_serializer::serialize(style_xml));
|
||||
|
||||
manifest_serializer manifest_serializer_(wb_.get_manifest());
|
||||
xml_document manifest_xml;
|
||||
manifest_serializer_.write_manifest(manifest_xml);
|
||||
archive_.writestr(constants::ArcContentTypes, xml_serializer::serialize(manifest_xml));
|
||||
|
||||
write_worksheets();
|
||||
}
|
||||
|
||||
void excel_writer::write_data(zip_file &archive, bool as_template)
|
||||
{
|
||||
archive.writestr(constants::ArcRootRels, write_root_rels(wb_));
|
||||
archive.writestr(constants::ArcWorkbookRels, write_workbook_rels(wb_));
|
||||
archive.writestr(constants::ArcApp, write_properties_app(wb_));
|
||||
archive.writestr(constants::ArcCore, write_properties_core(wb_.get_properties()));
|
||||
|
||||
if(wb_.has_loaded_theme())
|
||||
{
|
||||
archive.writestr(constants::ArcTheme, wb_.get_loaded_theme());
|
||||
}
|
||||
else
|
||||
{
|
||||
archive.writestr(constants::ArcTheme, write_theme());
|
||||
}
|
||||
|
||||
archive.writestr(constants::ArcWorkbook, write_workbook(wb_));
|
||||
|
||||
auto shared_strings = extract_all_strings(wb_);
|
||||
|
||||
write_charts(archive);
|
||||
write_images(archive);
|
||||
write_shared_strings(archive, shared_strings);
|
||||
write_worksheets(archive, shared_strings);
|
||||
write_chartsheets(archive);
|
||||
write_external_links(archive);
|
||||
|
||||
style_writer style_writer_(wb_);
|
||||
archive.writestr(constants::ArcStyles, style_writer_.write_table());
|
||||
|
||||
auto manifest = write_content_types(wb_, as_template);
|
||||
archive.writestr(constants::ArcContentTypes, manifest);
|
||||
}
|
||||
|
||||
void excel_writer::write_shared_strings(xlnt::zip_file &archive, const std::vector<std::string> &shared_strings)
|
||||
{
|
||||
archive.writestr(constants::ArcSharedString, ::xlnt::write_shared_strings(shared_strings));
|
||||
}
|
||||
|
||||
void excel_writer::write_images(zip_file &/*archive*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void excel_writer::write_charts(zip_file &/*archive*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void excel_writer::write_chartsheets(zip_file &/*archive*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void excel_writer::write_worksheets(zip_file &archive, const std::vector<std::string> &shared_strings)
|
||||
void excel_serializer::write_worksheets()
|
||||
{
|
||||
std::size_t index = 0;
|
||||
|
||||
|
@ -232,7 +187,10 @@ void excel_writer::write_worksheets(zip_file &archive, const std::vector<std::st
|
|||
if(relationship.get_type() == relationship::type::worksheet &&
|
||||
workbook::index_from_ws_filename(relationship.get_target_uri()) == index)
|
||||
{
|
||||
archive.writestr(relationship.get_target_uri(), write_worksheet(ws, shared_strings));
|
||||
worksheet_serializer serializer_(ws);
|
||||
xml_document xml;
|
||||
serializer_.write_worksheet(shared_strings_, xml);
|
||||
archive_.writestr(relationship.get_target_uri(), xml_serializer::serialize(xml));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -241,27 +199,33 @@ void excel_writer::write_worksheets(zip_file &archive, const std::vector<std::st
|
|||
}
|
||||
}
|
||||
|
||||
void excel_writer::write_external_links(zip_file &/*archive*/)
|
||||
void excel_serializer::write_external_links()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool save_workbook(workbook &wb, const std::string &filename, bool as_template)
|
||||
|
||||
bool excel_serializer::save_stream_workbook(std::ostream &stream, bool as_template)
|
||||
{
|
||||
excel_writer writer(wb);
|
||||
writer.save(filename, as_template);
|
||||
write_data(as_template);
|
||||
archive_.save(stream);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<std::uint8_t> save_virtual_workbook(xlnt::workbook &wb, bool as_template)
|
||||
bool excel_serializer::save_workbook(const std::string &filename, bool as_template)
|
||||
{
|
||||
zip_file archive;
|
||||
excel_writer writer(wb);
|
||||
writer.write_data(archive, as_template);
|
||||
std::vector<std::uint8_t> buffer;
|
||||
archive.save(buffer);
|
||||
write_data(as_template);
|
||||
archive_.save(filename);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool excel_serializer::save_virtual_workbook(std::vector<std::uint8_t> &bytes, bool as_template)
|
||||
{
|
||||
write_data(as_template);
|
||||
archive_.save(bytes);
|
||||
|
||||
return buffer;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -7,10 +7,27 @@
|
|||
#include "detail/constants.hpp"
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
|
||||
bool relationship_serializer::read_relationships(const xml_document &xml, const std::string &dir, std::vector<relationship> &relationships)
|
||||
{
|
||||
return false;
|
||||
auto root_node = xml.root();
|
||||
root_node.set_name("Relationships");
|
||||
|
||||
for(auto relationship_node : root_node.get_children())
|
||||
{
|
||||
if(relationship_node.get_name() != "Relationship")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string id = relationship_node.get_attribute("Id");
|
||||
std::string type = relationship_node.get_attribute("Type");
|
||||
std::string target = relationship_node.get_attribute("Target");
|
||||
|
||||
relationships.push_back(xlnt::relationship(type, id, target));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool relationship_serializer::write_relationships(const std::vector<relationship> &relationships, const std::string &dir, xml_document &xml)
|
||||
|
@ -29,15 +46,15 @@ bool relationship_serializer::write_relationships(const std::vector<relationship
|
|||
target = target.substr(dir.size());
|
||||
}
|
||||
|
||||
auto app_props_node = root_node.add_child("Relationship");
|
||||
auto relationship_node = root_node.add_child("Relationship");
|
||||
|
||||
app_props_node.add_attribute("Id", relationship.get_id());
|
||||
app_props_node.add_attribute("Target", target);
|
||||
app_props_node.add_attribute("Type", relationship.get_type_string());
|
||||
relationship_node.add_attribute("Id", relationship.get_id());
|
||||
relationship_node.add_attribute("Target", target);
|
||||
relationship_node.add_attribute("Type", relationship.get_type_string());
|
||||
|
||||
if(relationship.get_target_mode() == target_mode::external)
|
||||
{
|
||||
app_props_node.add_attribute("TargetMode", "External");
|
||||
relationship_node.add_attribute("TargetMode", "External");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -526,28 +526,32 @@ bool style_serializer::write_stylesheet(xlnt::xml_document &xml) const
|
|||
xml.add_namespace("mc", "http://schemas.openxmlformats.org/markup-compatibility/2006");
|
||||
xml.add_namespace("x14ac", "http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac");
|
||||
|
||||
auto &style_sheet_node = doc.add_child("styleSheet");
|
||||
xml.add_attribute("mc:Ignorable", "x14ac");
|
||||
auto &style_sheet_node = xml.root();
|
||||
style_sheet_node.set_name("styleSheet");
|
||||
style_sheet_node.add_attribute("mc:Ignorable", "x14ac");
|
||||
|
||||
auto num_fmts_node = style_sheet_node.add_child("numFmts");
|
||||
auto num_fmts = wb_.get_number_formats();
|
||||
num_fmts_node.add_attribute("count", static_cast<int>(num_fmts.size()));
|
||||
num_fmts_node.add_attribute("count", std::to_string(num_fmts.size()));
|
||||
|
||||
for(auto &num_fmt : num_fmts)
|
||||
{
|
||||
auto num_fmt_node = num_fmts_node.add_child("numFmt");
|
||||
num_fmt_node.add_attribute("numFmtId", num_fmt.get_id());
|
||||
num_fmt_node.add_attribute("numFmtId", std::to_string(num_fmt.get_id()));
|
||||
num_fmt_node.add_attribute("formatCode", num_fmt.get_format_string());
|
||||
}
|
||||
|
||||
auto fonts_node = style_sheet_node.add_child("fonts");
|
||||
auto fonts = wb_.get_fonts();
|
||||
|
||||
if(fonts.empty())
|
||||
{
|
||||
fonts.push_back(font());
|
||||
}
|
||||
fonts_node.add_attribute("count", static_cast<int>(fonts.size()));
|
||||
fonts_node.add_attribute("x14ac:knownFonts", 1);
|
||||
|
||||
fonts_node.add_attribute("count", std::to_string(fonts.size()));
|
||||
//TODO: what does this do?
|
||||
//fonts_node.add_attribute("x14ac:knownFonts", "1");
|
||||
|
||||
for(auto &f : fonts)
|
||||
{
|
||||
|
@ -556,13 +560,13 @@ bool style_serializer::write_stylesheet(xlnt::xml_document &xml) const
|
|||
if(f.is_bold())
|
||||
{
|
||||
auto bold_node = font_node.add_child("b");
|
||||
bold_node.add_attribute("val", 1);
|
||||
bold_node.add_attribute("val", "1");
|
||||
}
|
||||
|
||||
if(f.is_italic())
|
||||
{
|
||||
auto bold_node = font_node.add_child("i");
|
||||
bold_node.add_attribute("val", 1);
|
||||
bold_node.add_attribute("val", "1");
|
||||
}
|
||||
|
||||
if(f.is_underline())
|
||||
|
@ -582,21 +586,21 @@ bool style_serializer::write_stylesheet(xlnt::xml_document &xml) const
|
|||
if(f.is_strikethrough())
|
||||
{
|
||||
auto bold_node = font_node.add_child("strike");
|
||||
bold_node.add_attribute("val", 1);
|
||||
bold_node.add_attribute("val", "1");
|
||||
}
|
||||
|
||||
auto size_node = font_node.add_child("sz");
|
||||
size_node.add_attribute("val", f.get_size());
|
||||
size_node.add_attribute("val", std::to_string(f.get_size()));
|
||||
|
||||
auto color_node = font_node.add_child("color");
|
||||
|
||||
if(f.get_color().get_type() == color::type::indexed)
|
||||
{
|
||||
color_node.add_attribute("indexed", static_cast<unsigned int>(f.get_color().get_index()));
|
||||
color_node.add_attribute("indexed", std::to_string(f.get_color().get_index()));
|
||||
}
|
||||
else if(f.get_color().get_type() == color::type::theme)
|
||||
{
|
||||
color_node.add_attribute("theme", static_cast<unsigned int>(f.get_color().get_theme()));
|
||||
color_node.add_attribute("theme", std::to_string(f.get_color().get_theme()));
|
||||
}
|
||||
|
||||
auto name_node = font_node.add_child("name");
|
||||
|
@ -605,7 +609,7 @@ bool style_serializer::write_stylesheet(xlnt::xml_document &xml) const
|
|||
if(f.has_family())
|
||||
{
|
||||
auto family_node = font_node.add_child("family");
|
||||
family_node.add_attribute("val", 2);
|
||||
family_node.add_attribute("val", std::to_string(f.get_family()));
|
||||
}
|
||||
|
||||
if(f.has_scheme())
|
||||
|
@ -617,7 +621,7 @@ bool style_serializer::write_stylesheet(xlnt::xml_document &xml) const
|
|||
|
||||
auto fills_node = style_sheet_node.add_child("fills");
|
||||
const auto &fills = wb_.get_fills();
|
||||
fills_node.add_attribute("count", static_cast<unsigned int>(fills.size()));
|
||||
fills_node.add_attribute("count", std::to_string(fills.size()));
|
||||
|
||||
for(auto &fill_ : fills)
|
||||
{
|
||||
|
@ -631,13 +635,13 @@ bool style_serializer::write_stylesheet(xlnt::xml_document &xml) const
|
|||
|
||||
if(fill_.has_foreground_color())
|
||||
{
|
||||
auto fg_color_node = pattern_fill_node.add_child("fgColor");
|
||||
auto &fg_color_node = pattern_fill_node.add_child("fgColor");
|
||||
|
||||
switch(fill_.get_foreground_color().get_type())
|
||||
{
|
||||
case color::type::auto_: fg_color_node.add_attribute("auto", fill_.get_foreground_color().get_auto()); break;
|
||||
case color::type::theme: fg_color_node.add_attribute("theme", fill_.get_foreground_color().get_theme()); break;
|
||||
case color::type::indexed: fg_color_node.add_attribute("indexed", fill_.get_foreground_color().get_index()); break;
|
||||
case color::type::auto_: fg_color_node.add_attribute("auto", std::to_string(fill_.get_foreground_color().get_auto())); break;
|
||||
case color::type::theme: fg_color_node.add_attribute("theme", std::to_string(fill_.get_foreground_color().get_theme())); break;
|
||||
case color::type::indexed: fg_color_node.add_attribute("indexed", std::to_string(fill_.get_foreground_color().get_index())); break;
|
||||
default: throw std::runtime_error("bad type");
|
||||
}
|
||||
}
|
||||
|
@ -648,9 +652,9 @@ bool style_serializer::write_stylesheet(xlnt::xml_document &xml) const
|
|||
|
||||
switch(fill_.get_background_color().get_type())
|
||||
{
|
||||
case color::type::auto_: bg_color_node.add_attribute("auto", fill_.get_background_color().get_auto()); break;
|
||||
case color::type::theme: bg_color_node.add_attribute("theme", fill_.get_background_color().get_theme()); break;
|
||||
case color::type::indexed: bg_color_node.add_attribute("indexed", fill_.get_background_color().get_index()); break;
|
||||
case color::type::auto_: bg_color_node.add_attribute("auto", std::to_string(fill_.get_background_color().get_auto())); break;
|
||||
case color::type::theme: bg_color_node.add_attribute("theme", std::to_string(fill_.get_background_color().get_theme())); break;
|
||||
case color::type::indexed: bg_color_node.add_attribute("indexed", std::to_string(fill_.get_background_color().get_index())); break;
|
||||
default: throw std::runtime_error("bad type");
|
||||
}
|
||||
}
|
||||
|
@ -666,27 +670,27 @@ bool style_serializer::write_stylesheet(xlnt::xml_document &xml) const
|
|||
|
||||
if(fill_.get_gradient_type_string() == "linear")
|
||||
{
|
||||
gradient_fill_node.add_attribute("degree", fill_.get_rotation());
|
||||
gradient_fill_node.add_attribute("degree", std::to_string(fill_.get_rotation()));
|
||||
}
|
||||
else if(fill_.get_gradient_type_string() == "path")
|
||||
{
|
||||
gradient_fill_node.add_attribute("left", fill_.get_gradient_left());
|
||||
gradient_fill_node.add_attribute("right", fill_.get_gradient_right());
|
||||
gradient_fill_node.add_attribute("top", fill_.get_gradient_top());
|
||||
gradient_fill_node.add_attribute("bottom", fill_.get_gradient_bottom());
|
||||
gradient_fill_node.add_attribute("left", std::to_string(fill_.get_gradient_left()));
|
||||
gradient_fill_node.add_attribute("right", std::to_string(fill_.get_gradient_right()));
|
||||
gradient_fill_node.add_attribute("top", std::to_string(fill_.get_gradient_top()));
|
||||
gradient_fill_node.add_attribute("bottom", std::to_string(fill_.get_gradient_bottom()));
|
||||
|
||||
auto start_node = gradient_fill_node.add_child("stop");
|
||||
start_node.add_attribute("position", 0);
|
||||
start_node.add_attribute("position", "0");
|
||||
|
||||
auto end_node = gradient_fill_node.add_child("stop");
|
||||
end_node.add_attribute("position", 1);
|
||||
end_node.add_attribute("position", "1");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto borders_node = style_sheet_node.add_child("borders");
|
||||
const auto &borders = wb_.get_borders();
|
||||
borders_node.add_attribute("count", static_cast<unsigned int>(borders.size()));
|
||||
borders_node.add_attribute("count", std::to_string(borders.size()));
|
||||
|
||||
for(const auto &border_ : borders)
|
||||
{
|
||||
|
@ -715,39 +719,41 @@ bool style_serializer::write_stylesheet(xlnt::xml_document &xml) const
|
|||
|
||||
if(side_.is_style_assigned())
|
||||
{
|
||||
auto style_attribute = side_node.add_attribute("style");
|
||||
std::string style_string;
|
||||
|
||||
switch(side_.get_style())
|
||||
{
|
||||
case border_style::none: style_attribute.set_value("none"); break;
|
||||
case border_style::dashdot : style_attribute.set_value("dashdot"); break;
|
||||
case border_style::dashdotdot : style_attribute.set_value("dashdotdot"); break;
|
||||
case border_style::dashed : style_attribute.set_value("dashed"); break;
|
||||
case border_style::dotted : style_attribute.set_value("dotted"); break;
|
||||
case border_style::double_ : style_attribute.set_value("double"); break;
|
||||
case border_style::hair : style_attribute.set_value("hair"); break;
|
||||
case border_style::medium : style_attribute.set_value("thin"); break;
|
||||
case border_style::mediumdashdot: style_attribute.set_value("mediumdashdot"); break;
|
||||
case border_style::mediumdashdotdot: style_attribute.set_value("mediumdashdotdot"); break;
|
||||
case border_style::mediumdashed: style_attribute.set_value("mediumdashed"); break;
|
||||
case border_style::slantdashdot: style_attribute.set_value("slantdashdot"); break;
|
||||
case border_style::thick: style_attribute.set_value("thick"); break;
|
||||
case border_style::thin: style_attribute.set_value("thin"); break;
|
||||
case border_style::none: style_string = "none"; break;
|
||||
case border_style::dashdot: style_string = "dashdot"; break;
|
||||
case border_style::dashdotdot: style_string = "dashdotdot"; break;
|
||||
case border_style::dashed: style_string = "dashed"; break;
|
||||
case border_style::dotted: style_string = "dotted"; break;
|
||||
case border_style::double_: style_string = "double"; break;
|
||||
case border_style::hair: style_string = "hair"; break;
|
||||
case border_style::medium: style_string = "thin"; break;
|
||||
case border_style::mediumdashdot: style_string = "mediumdashdot"; break;
|
||||
case border_style::mediumdashdotdot: style_string = "mediumdashdotdot"; break;
|
||||
case border_style::mediumdashed: style_string = "mediumdashed"; break;
|
||||
case border_style::slantdashdot: style_string = "slantdashdot"; break;
|
||||
case border_style::thick: style_string = "thick"; break;
|
||||
case border_style::thin: style_string = "thin"; break;
|
||||
default: throw std::runtime_error("invalid style");
|
||||
}
|
||||
|
||||
side_node.add_attribute("style", style_string);
|
||||
}
|
||||
|
||||
if(side_.is_color_assigned())
|
||||
{
|
||||
auto color_node = side_node.add_child("color");
|
||||
|
||||
if(side_.get_color_type() == side::color_type::indexed)
|
||||
if(side_.get_color().get_type() == color::type::indexed)
|
||||
{
|
||||
color_node.add_attribute("indexed", (int)side_.get_color());
|
||||
color_node.add_attribute("indexed", std::to_string(side_.get_color().get_index()));
|
||||
}
|
||||
else if(side_.get_color_type() == side::color_type::theme)
|
||||
else if(side_.get_color().get_type() == color::type::theme)
|
||||
{
|
||||
color_node.add_attribute("indexed", (int)side_.get_color());
|
||||
color_node.add_attribute("theme", std::to_string(side_.get_color().get_theme()));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -758,40 +764,41 @@ bool style_serializer::write_stylesheet(xlnt::xml_document &xml) const
|
|||
}
|
||||
}
|
||||
|
||||
auto cell_style_xfs_node = style_sheet_node.add_child("cellStyleXfs");
|
||||
cell_style_xfs_node.add_attribute("count", 1);
|
||||
auto style_xf_node = cell_style_xfs_node.add_child("xf");
|
||||
style_xf_node.add_attribute("numFmtId", 0);
|
||||
style_xf_node.add_attribute("fontId", 0);
|
||||
style_xf_node.add_attribute("fillId", 0);
|
||||
style_xf_node.add_attribute("borderId", 0);
|
||||
auto &cell_style_xfs_node = style_sheet_node.add_child("cellStyleXfs");
|
||||
cell_style_xfs_node.add_attribute("count", "1");
|
||||
|
||||
auto &style_xf_node = cell_style_xfs_node.add_child("xf");
|
||||
style_xf_node.add_attribute("numFmtId", "0");
|
||||
style_xf_node.add_attribute("fontId", "0");
|
||||
style_xf_node.add_attribute("fillId", "0");
|
||||
style_xf_node.add_attribute("borderId", "0");
|
||||
|
||||
auto cell_xfs_node = style_sheet_node.add_child("cellXfs");
|
||||
const auto &styles = wb_.get_styles();
|
||||
cell_xfs_node.add_attribute("count", static_cast<int>(styles.size()));
|
||||
cell_xfs_node.add_attribute("count", std::to_string(styles.size()));
|
||||
|
||||
for(auto &style : styles)
|
||||
{
|
||||
auto xf_node = cell_xfs_node.add_child("xf");
|
||||
xf_node.add_attribute("numFmtId", style.get_number_format().get_id());
|
||||
xf_node.add_attribute("fontId", (int)style.get_font_id());
|
||||
xf_node.add_attribute("numFmtId", std::to_string(style.get_number_format().get_id()));
|
||||
xf_node.add_attribute("fontId", std::to_string(style.get_font_id()));
|
||||
|
||||
if(style.fill_apply_)
|
||||
{
|
||||
xf_node.add_attribute("fillId", (int)style.get_fill_id());
|
||||
xf_node.add_attribute("fillId", std::to_string(style.get_fill_id()));
|
||||
}
|
||||
|
||||
if(style.border_apply_)
|
||||
{
|
||||
xf_node.add_attribute("borderId", (int)style.get_border_id());
|
||||
xf_node.add_attribute("borderId", std::to_string(style.get_border_id()));
|
||||
}
|
||||
|
||||
xf_node.add_attribute("applyNumberFormat", style.number_format_apply_ ? 1 : 0);
|
||||
xf_node.add_attribute("applyFont", style.font_apply_ ? 1 : 0);
|
||||
xf_node.add_attribute("applyFill", style.fill_apply_ ? 1 : 0);
|
||||
xf_node.add_attribute("applyBorder", style.border_apply_ ? 1 : 0);
|
||||
xf_node.add_attribute("applyAlignment", style.alignment_apply_ ? 1 : 0);
|
||||
xf_node.add_attribute("applyProtection", style.protection_apply_ ? 1 : 0);
|
||||
xf_node.add_attribute("applyNumberFormat", style.number_format_apply_ ? "1" : "0");
|
||||
xf_node.add_attribute("applyFont", style.font_apply_ ? "1" : "0");
|
||||
xf_node.add_attribute("applyFill", style.fill_apply_ ? "1" : "0");
|
||||
xf_node.add_attribute("applyBorder", style.border_apply_ ? "1" : "0");
|
||||
xf_node.add_attribute("applyAlignment", style.alignment_apply_ ? "1" : "0");
|
||||
xf_node.add_attribute("applyProtection", style.protection_apply_ ? "1" : "0");
|
||||
|
||||
if(style.alignment_apply_)
|
||||
{
|
||||
|
@ -847,22 +854,22 @@ bool style_serializer::write_stylesheet(xlnt::xml_document &xml) const
|
|||
|
||||
if(style.alignment_.get_wrap_text())
|
||||
{
|
||||
alignment_node.add_attribute("wrapText", 1);
|
||||
alignment_node.add_attribute("wrapText", "1");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto cell_styles_node = style_sheet_node.add_child("cellStyles");
|
||||
cell_styles_node.add_attribute("count", 1);
|
||||
cell_styles_node.add_attribute("count", "1");
|
||||
auto cell_style_node = cell_styles_node.add_child("cellStyle");
|
||||
cell_style_node.add_attribute("name", "Normal");
|
||||
cell_style_node.add_attribute("xfId", 0);
|
||||
cell_style_node.add_attribute("builtinId", 0);
|
||||
cell_style_node.add_attribute("xfId", "0");
|
||||
cell_style_node.add_attribute("builtinId", "0");
|
||||
|
||||
style_sheet_node.add_child("dxfs").add_attribute("count", 0);
|
||||
style_sheet_node.add_child("dxfs").add_attribute("count", "0");
|
||||
|
||||
auto table_styles_node = style_sheet_node.add_child("tableStyles");
|
||||
table_styles_node.add_attribute("count", 0);
|
||||
table_styles_node.add_attribute("count", "0");
|
||||
table_styles_node.add_attribute("defaultTableStyle", "TableStyleMedium2");
|
||||
table_styles_node.add_attribute("defaultPivotStyle", "PivotStyleMedium9");
|
||||
|
||||
|
|
356
source/s11n/theme_serializer.cpp
Normal file
356
source/s11n/theme_serializer.cpp
Normal file
|
@ -0,0 +1,356 @@
|
|||
#include <xlnt/s11n/theme_serializer.hpp>
|
||||
#include <xlnt/s11n/xml_document.hpp>
|
||||
#include <xlnt/s11n/xml_node.hpp>
|
||||
|
||||
#include <detail/constants.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
//I have no idea what this stuff is. I hope it was worth it.
|
||||
xml_document theme_serializer::write_theme(const theme &theme_)
|
||||
{
|
||||
xml_document xml;
|
||||
|
||||
xml.add_namespace("a", constants::Namespaces.at("drawingml"));
|
||||
|
||||
auto &theme_node = xml.root();
|
||||
theme_node.set_name("a:theme");
|
||||
theme_node.add_attribute("name", "Office Theme");
|
||||
auto &theme_elements_node = theme_node.add_child("a:themeElements");
|
||||
auto &clr_scheme_node = theme_elements_node.add_child("a:clrScheme");
|
||||
clr_scheme_node.add_attribute("name", "Office");
|
||||
|
||||
struct scheme_element
|
||||
{
|
||||
std::string name;
|
||||
std::string sub_element_name;
|
||||
std::string val;
|
||||
};
|
||||
|
||||
std::vector<scheme_element> scheme_elements =
|
||||
{
|
||||
{"a:dk1", "a:sysClr", "windowText"},
|
||||
{"a:lt1", "a:sysClr", "window"},
|
||||
{"a:dk2", "a:srgbClr", "1F497D"},
|
||||
{"a:lt2", "a:srgbClr", "EEECE1"},
|
||||
{"a:accent1", "a:srgbClr", "4F81BD"},
|
||||
{"a:accent2", "a:srgbClr", "C0504D"},
|
||||
{"a:accent3", "a:srgbClr", "9BBB59"},
|
||||
{"a:accent4", "a:srgbClr", "8064A2"},
|
||||
{"a:accent5", "a:srgbClr", "4BACC6"},
|
||||
{"a:accent6", "a:srgbClr", "F79646"},
|
||||
{"a:hlink", "a:srgbClr", "0000FF"},
|
||||
{"a:folHlink", "a:srgbClr", "800080"},
|
||||
};
|
||||
|
||||
for(auto element : scheme_elements)
|
||||
{
|
||||
auto element_node = clr_scheme_node.add_child(element.name);
|
||||
element_node.add_child(element.sub_element_name).add_attribute("val", element.val);
|
||||
|
||||
if(element.name == "a:dk1")
|
||||
{
|
||||
element_node.get_child(element.sub_element_name).add_attribute("lastClr", "000000");
|
||||
}
|
||||
else if(element.name == "a:lt1")
|
||||
{
|
||||
element_node.get_child(element.sub_element_name).add_attribute("lastClr", "FFFFFF");
|
||||
}
|
||||
}
|
||||
|
||||
struct font_scheme
|
||||
{
|
||||
bool typeface;
|
||||
std::string script;
|
||||
std::string major;
|
||||
std::string minor;
|
||||
};
|
||||
|
||||
std::vector<font_scheme> font_schemes =
|
||||
{
|
||||
{true, "a:latin", "Cambria", "Calibri"},
|
||||
{true, "a:ea", "", ""},
|
||||
{true, "a:cs", "", ""},
|
||||
{false, "Jpan", "\xef\xbc\xad\xef\xbc\xb3 \xef\xbc\xb0\xe3\x82\xb4\xe3\x82\xb7\xe3\x83\x83\xe3\x82\xaf", "\xef\xbc\xad\xef\xbc\xb3 \xef\xbc\xb0\xe3\x82\xb4\xe3\x82\xb7\xe3\x83\x83\xe3\x82\xaf"},
|
||||
{false, "Hang", "\xeb\xa7\x91\xec\x9d\x80 \xea\xb3\xa0\xeb\x94\x95", "\xeb\xa7\x91\xec\x9d\x80 \xea\xb3\xa0\xeb\x94\x95"},
|
||||
{false, "Hans", "\xe5\xae\x8b\xe4\xbd\x93", "\xe5\xae\x8b\xe4\xbd\x93"},
|
||||
{false, "Hant", "\xe6\x96\xb0\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94", "\xe6\x96\xb0\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94"},
|
||||
{false, "Arab", "Times New Roman", "Arial"},
|
||||
{false, "Hebr", "Times New Roman", "Arial"},
|
||||
{false, "Thai", "Tahoma", "Tahoma"},
|
||||
{false, "Ethi", "Nyala", "Nyala"},
|
||||
{false, "Beng", "Vrinda", "Vrinda"},
|
||||
{false, "Gujr", "Shruti", "Shruti"},
|
||||
{false, "Khmr", "MoolBoran", "DaunPenh"},
|
||||
{false, "Knda", "Tunga", "Tunga"},
|
||||
{false, "Guru", "Raavi", "Raavi"},
|
||||
{false, "Cans", "Euphemia", "Euphemia"},
|
||||
{false, "Cher", "Plantagenet Cherokee", "Plantagenet Cherokee"},
|
||||
{false, "Yiii", "Microsoft Yi Baiti", "Microsoft Yi Baiti"},
|
||||
{false, "Tibt", "Microsoft Himalaya", "Microsoft Himalaya"},
|
||||
{false, "Thaa", "MV Boli", "MV Boli"},
|
||||
{false, "Deva", "Mangal", "Mangal"},
|
||||
{false, "Telu", "Gautami", "Gautami"},
|
||||
{false, "Taml", "Latha", "Latha"},
|
||||
{false, "Syrc", "Estrangelo Edessa", "Estrangelo Edessa"},
|
||||
{false, "Orya", "Kalinga", "Kalinga"},
|
||||
{false, "Mlym", "Kartika", "Kartika"},
|
||||
{false, "Laoo", "DokChampa", "DokChampa"},
|
||||
{false, "Sinh", "Iskoola Pota", "Iskoola Pota"},
|
||||
{false, "Mong", "Mongolian Baiti", "Mongolian Baiti"},
|
||||
{false, "Viet", "Times New Roman", "Arial"},
|
||||
{false, "Uigh", "Microsoft Uighur", "Microsoft Uighur"}
|
||||
};
|
||||
|
||||
auto font_scheme_node = theme_elements_node.add_child("a:fontScheme");
|
||||
font_scheme_node.add_attribute("name", "Office");
|
||||
|
||||
auto major_fonts_node = font_scheme_node.add_child("a:majorFont");
|
||||
auto minor_fonts_node = font_scheme_node.add_child("a:minorFont");
|
||||
|
||||
for(auto scheme : font_schemes)
|
||||
{
|
||||
if(scheme.typeface)
|
||||
{
|
||||
auto &major_font_node = major_fonts_node.add_child(scheme.script);
|
||||
major_font_node.add_attribute("typeface", scheme.major);
|
||||
|
||||
auto &minor_font_node = minor_fonts_node.add_child(scheme.script);
|
||||
minor_font_node.add_attribute("typeface", scheme.minor);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto &major_font_node = major_fonts_node.add_child("a:font");
|
||||
major_font_node.add_attribute("script", scheme.script);
|
||||
major_font_node.add_attribute("typeface", scheme.major);
|
||||
|
||||
auto &minor_font_node = minor_fonts_node.add_child("a:font");
|
||||
minor_font_node.add_attribute("script", scheme.script);
|
||||
minor_font_node.add_attribute("typeface", scheme.minor);
|
||||
}
|
||||
}
|
||||
|
||||
auto format_scheme_node = theme_elements_node.add_child("a:fmtScheme");
|
||||
format_scheme_node.add_attribute("name", "Office");
|
||||
|
||||
auto fill_style_list_node = format_scheme_node.add_child("a:fillStyleLst");
|
||||
fill_style_list_node.add_child("a:solidFill").add_child("a:schemeClr").add_attribute("val", "phClr");
|
||||
|
||||
auto grad_fill_node = fill_style_list_node.add_child("a:gradFill");
|
||||
grad_fill_node.add_attribute("rotWithShape", "1");
|
||||
|
||||
auto grad_fill_list = grad_fill_node.add_child("a:gsLst");
|
||||
auto gs_node = grad_fill_list.add_child("a:gs");
|
||||
gs_node.add_attribute("pos", 0);
|
||||
auto scheme_color_node = gs_node.add_child("a:schemeClr");
|
||||
scheme_color_node.add_attribute("val", "phClr");
|
||||
scheme_color_node.add_child("a:tint").add_attribute("val", "50000");
|
||||
scheme_color_node.add_child("a:satMod").add_attribute("val", "300000");
|
||||
|
||||
gs_node = grad_fill_list.add_child("a:gs");
|
||||
gs_node.add_attribute("pos", "35000");
|
||||
scheme_color_node = gs_node.add_child("a:schemeClr");
|
||||
scheme_color_node.add_attribute("val", "phClr");
|
||||
scheme_color_node.add_child("a:tint").add_attribute("val", "37000");
|
||||
scheme_color_node.add_child("a:satMod").add_attribute("val", "300000");
|
||||
|
||||
gs_node = grad_fill_list.add_child("a:gs");
|
||||
gs_node.add_attribute("pos", "100000");
|
||||
scheme_color_node = gs_node.add_child("a:schemeClr");
|
||||
scheme_color_node.add_attribute("val", "phClr");
|
||||
scheme_color_node.add_child("a:tint").add_attribute("val", "15000");
|
||||
scheme_color_node.add_child("a:satMod").add_attribute("val", "350000");
|
||||
|
||||
auto lin_node = grad_fill_node.add_child("a:lin");
|
||||
lin_node.add_attribute("ang", "16200000");
|
||||
lin_node.add_attribute("scaled", "1");
|
||||
|
||||
grad_fill_node = fill_style_list_node.add_child("a:gradFill");
|
||||
grad_fill_node.add_attribute("rotWithShape", "1");
|
||||
|
||||
grad_fill_list = grad_fill_node.add_child("a:gsLst");
|
||||
gs_node = grad_fill_list.add_child("a:gs");
|
||||
gs_node.add_attribute("pos", "0");
|
||||
scheme_color_node = gs_node.add_child("a:schemeClr");
|
||||
scheme_color_node.add_attribute("val", "phClr");
|
||||
scheme_color_node.add_child("a:shade").add_attribute("val", "51000");
|
||||
scheme_color_node.add_child("a:satMod").add_attribute("val", "130000");
|
||||
|
||||
gs_node = grad_fill_list.add_child("a:gs");
|
||||
gs_node.add_attribute("pos", "80000");
|
||||
scheme_color_node = gs_node.add_child("a:schemeClr");
|
||||
scheme_color_node.add_attribute("val", "phClr");
|
||||
scheme_color_node.add_child("a:shade").add_attribute("val", "93000");
|
||||
scheme_color_node.add_child("a:satMod").add_attribute("val", "130000");
|
||||
|
||||
gs_node = grad_fill_list.add_child("a:gs");
|
||||
gs_node.add_attribute("pos", "100000");
|
||||
scheme_color_node = gs_node.add_child("a:schemeClr");
|
||||
scheme_color_node.add_attribute("val", "phClr");
|
||||
scheme_color_node.add_child("a:shade").add_attribute("val", "94000");
|
||||
scheme_color_node.add_child("a:satMod").add_attribute("val", "135000");
|
||||
|
||||
lin_node = grad_fill_node.add_child("a:lin");
|
||||
lin_node.add_attribute("ang", "16200000");
|
||||
lin_node.add_attribute("scaled", "0");
|
||||
|
||||
auto line_style_list_node = format_scheme_node.add_child("a:lnStyleLst");
|
||||
|
||||
auto ln_node = line_style_list_node.add_child("a:ln");
|
||||
ln_node.add_attribute("w", "9525");
|
||||
ln_node.add_attribute("cap", "flat");
|
||||
ln_node.add_attribute("cmpd", "sng");
|
||||
ln_node.add_attribute("algn", "ctr");
|
||||
|
||||
auto solid_fill_node = ln_node.add_child("a:solidFill");
|
||||
scheme_color_node = solid_fill_node.add_child("a:schemeClr");
|
||||
scheme_color_node.add_attribute("val", "phClr");
|
||||
scheme_color_node.add_child("a:shade").add_attribute("val", "95000");
|
||||
scheme_color_node.add_child("a:satMod").add_attribute("val", "105000");
|
||||
ln_node.add_child("a:prstDash").add_attribute("val", "solid");
|
||||
|
||||
ln_node = line_style_list_node.add_child("a:ln");
|
||||
ln_node.add_attribute("w", "25400");
|
||||
ln_node.add_attribute("cap", "flat");
|
||||
ln_node.add_attribute("cmpd", "sng");
|
||||
ln_node.add_attribute("algn", "ctr");
|
||||
|
||||
solid_fill_node = ln_node.add_child("a:solidFill");
|
||||
scheme_color_node = solid_fill_node.add_child("a:schemeClr");
|
||||
scheme_color_node.add_attribute("val", "phClr");
|
||||
ln_node.add_child("a:prstDash").add_attribute("val", "solid");
|
||||
|
||||
ln_node = line_style_list_node.add_child("a:ln");
|
||||
ln_node.add_attribute("w", "38100");
|
||||
ln_node.add_attribute("cap", "flat");
|
||||
ln_node.add_attribute("cmpd", "sng");
|
||||
ln_node.add_attribute("algn", "ctr");
|
||||
|
||||
solid_fill_node = ln_node.add_child("a:solidFill");
|
||||
scheme_color_node = solid_fill_node.add_child("a:schemeClr");
|
||||
scheme_color_node.add_attribute("val", "phClr");
|
||||
ln_node.add_child("a:prstDash").add_attribute("val", "solid");
|
||||
|
||||
auto effect_style_list_node = format_scheme_node.add_child("a:effectStyleLst");
|
||||
auto effect_style_node = effect_style_list_node.add_child("a:effectStyle");
|
||||
auto effect_list_node = effect_style_node.add_child("a:effectLst");
|
||||
auto outer_shadow_node = effect_list_node.add_child("a:outerShdw");
|
||||
outer_shadow_node.add_attribute("blurRad", "40000");
|
||||
outer_shadow_node.add_attribute("dist", "20000");
|
||||
outer_shadow_node.add_attribute("dir", "5400000");
|
||||
outer_shadow_node.add_attribute("rotWithShape", "0");
|
||||
auto srgb_clr_node = outer_shadow_node.add_child("a:srgbClr");
|
||||
srgb_clr_node.add_attribute("val", "000000");
|
||||
srgb_clr_node.add_child("a:alpha").add_attribute("val", "38000");
|
||||
|
||||
effect_style_node = effect_style_list_node.add_child("a:effectStyle");
|
||||
effect_list_node = effect_style_node.add_child("a:effectLst");
|
||||
outer_shadow_node = effect_list_node.add_child("a:outerShdw");
|
||||
outer_shadow_node.add_attribute("blurRad", "40000");
|
||||
outer_shadow_node.add_attribute("dist", "23000");
|
||||
outer_shadow_node.add_attribute("dir", "5400000");
|
||||
outer_shadow_node.add_attribute("rotWithShape", "0");
|
||||
srgb_clr_node = outer_shadow_node.add_child("a:srgbClr");
|
||||
srgb_clr_node.add_attribute("val", "000000");
|
||||
srgb_clr_node.add_child("a:alpha").add_attribute("val", "35000");
|
||||
|
||||
effect_style_node = effect_style_list_node.add_child("a:effectStyle");
|
||||
effect_list_node = effect_style_node.add_child("a:effectLst");
|
||||
outer_shadow_node = effect_list_node.add_child("a:outerShdw");
|
||||
outer_shadow_node.add_attribute("blurRad", "40000");
|
||||
outer_shadow_node.add_attribute("dist", "23000");
|
||||
outer_shadow_node.add_attribute("dir", "5400000");
|
||||
outer_shadow_node.add_attribute("rotWithShape", "0");
|
||||
srgb_clr_node = outer_shadow_node.add_child("a:srgbClr");
|
||||
srgb_clr_node.add_attribute("val", "000000");
|
||||
srgb_clr_node.add_child("a:alpha").add_attribute("val", "35000");
|
||||
auto scene3d_node = effect_style_node.add_child("a:scene3d");
|
||||
auto camera_node = scene3d_node.add_child("a:camera");
|
||||
camera_node.add_attribute("prst", "orthographicFront");
|
||||
auto rot_node = camera_node.add_child("a:rot");
|
||||
rot_node.add_attribute("lat", "0");
|
||||
rot_node.add_attribute("lon", "0");
|
||||
rot_node.add_attribute("rev", "0");
|
||||
auto light_rig_node = scene3d_node.add_child("a:lightRig");
|
||||
light_rig_node.add_attribute("rig", "threePt");
|
||||
light_rig_node.add_attribute("dir", "t");
|
||||
rot_node = light_rig_node.add_child("a:rot");
|
||||
rot_node.add_attribute("lat", "0");
|
||||
rot_node.add_attribute("lon", "0");
|
||||
rot_node.add_attribute("rev", "1200000");
|
||||
|
||||
auto bevel_node = effect_style_node.add_child("a:sp3d").add_child("a:bevelT");
|
||||
bevel_node.add_attribute("w", "63500");
|
||||
bevel_node.add_attribute("h", "25400");
|
||||
|
||||
auto bg_fill_style_list_node = format_scheme_node.add_child("a:bgFillStyleLst");
|
||||
|
||||
bg_fill_style_list_node.add_child("a:solidFill").add_child("a:schemeClr").add_attribute("val", "phClr");
|
||||
|
||||
grad_fill_node = bg_fill_style_list_node.add_child("a:gradFill");
|
||||
grad_fill_node.add_attribute("rotWithShape", "1");
|
||||
|
||||
grad_fill_list = grad_fill_node.add_child("a:gsLst");
|
||||
gs_node = grad_fill_list.add_child("a:gs");
|
||||
gs_node.add_attribute("pos", "0");
|
||||
scheme_color_node = gs_node.add_child("a:schemeClr");
|
||||
scheme_color_node.add_attribute("val", "phClr");
|
||||
scheme_color_node.add_child("a:tint").add_attribute("val", "40000");
|
||||
scheme_color_node.add_child("a:satMod").add_attribute("val", "350000");
|
||||
|
||||
gs_node = grad_fill_list.add_child("a:gs");
|
||||
gs_node.add_attribute("pos", "40000");
|
||||
scheme_color_node = gs_node.add_child("a:schemeClr");
|
||||
scheme_color_node.add_attribute("val", "phClr");
|
||||
scheme_color_node.add_child("a:tint").add_attribute("val", "45000");
|
||||
scheme_color_node.add_child("a:shade").add_attribute("val", "99000");
|
||||
scheme_color_node.add_child("a:satMod").add_attribute("val", "350000");
|
||||
|
||||
gs_node = grad_fill_list.add_child("a:gs");
|
||||
gs_node.add_attribute("pos", "100000");
|
||||
scheme_color_node = gs_node.add_child("a:schemeClr");
|
||||
scheme_color_node.add_attribute("val", "phClr");
|
||||
scheme_color_node.add_child("a:shade").add_attribute("val", "20000");
|
||||
scheme_color_node.add_child("a:satMod").add_attribute("val", "255000");
|
||||
|
||||
auto path_node = grad_fill_node.add_child("a:path");
|
||||
path_node.add_attribute("path", "circle");
|
||||
auto fill_to_rect_node = path_node.add_child("a:fillToRect");
|
||||
fill_to_rect_node.add_attribute("l", "50000");
|
||||
fill_to_rect_node.add_attribute("t", "-80000");
|
||||
fill_to_rect_node.add_attribute("r", "50000");
|
||||
fill_to_rect_node.add_attribute("b", "180000");
|
||||
|
||||
grad_fill_node = bg_fill_style_list_node.add_child("a:gradFill");
|
||||
grad_fill_node.add_attribute("rotWithShape", "1");
|
||||
|
||||
grad_fill_list = grad_fill_node.add_child("a:gsLst");
|
||||
gs_node = grad_fill_list.add_child("a:gs");
|
||||
gs_node.add_attribute("pos", "0");
|
||||
scheme_color_node = gs_node.add_child("a:schemeClr");
|
||||
scheme_color_node.add_attribute("val", "phClr");
|
||||
scheme_color_node.add_child("a:tint").add_attribute("val", "80000");
|
||||
scheme_color_node.add_child("a:satMod").add_attribute("val", "300000");
|
||||
|
||||
gs_node = grad_fill_list.add_child("a:gs");
|
||||
gs_node.add_attribute("pos", "100000");
|
||||
scheme_color_node = gs_node.add_child("a:schemeClr");
|
||||
scheme_color_node.add_attribute("val", "phClr");
|
||||
scheme_color_node.add_child("a:shade").add_attribute("val", "30000");
|
||||
scheme_color_node.add_child("a:satMod").add_attribute("val", "200000");
|
||||
|
||||
path_node = grad_fill_node.add_child("a:path");
|
||||
path_node.add_attribute("path", "circle");
|
||||
fill_to_rect_node = path_node.add_child("a:fillToRect");
|
||||
fill_to_rect_node.add_attribute("l", "50000");
|
||||
fill_to_rect_node.add_attribute("t", "50000");
|
||||
fill_to_rect_node.add_attribute("r", "50000");
|
||||
fill_to_rect_node.add_attribute("b", "50000");
|
||||
|
||||
theme_node.add_child("a:objectDefaults");
|
||||
theme_node.add_child("a:extraClrSchemeLst");
|
||||
|
||||
return xml;
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
|
@ -1,11 +1,15 @@
|
|||
#include <xlnt/s11n/workbook_serializer.hpp>
|
||||
#include <xlnt/common/datetime.hpp>
|
||||
#include <xlnt/common/exceptions.hpp>
|
||||
#include <xlnt/common/relationship.hpp>
|
||||
#include <xlnt/s11n/xml_document.hpp>
|
||||
#include <xlnt/s11n/xml_node.hpp>
|
||||
#include <xlnt/workbook/document_properties.hpp>
|
||||
#include <xlnt/workbook/manifest.hpp>
|
||||
#include <xlnt/workbook/named_range.hpp>
|
||||
#include <xlnt/workbook/workbook.hpp>
|
||||
#include <xlnt/worksheet/range_reference.hpp>
|
||||
#include <xlnt/worksheet/worksheet.hpp>
|
||||
|
||||
#include "detail/constants.hpp"
|
||||
|
||||
|
@ -66,15 +70,15 @@ std::vector<std::pair<std::string, std::string>> workbook_serializer::read_sheet
|
|||
|
||||
auto with_ns = [&](const std::string &base) { return ns.empty() ? base : ns + ":" + base; };
|
||||
|
||||
auto root_node = doc.child(with_ns("workbook").c_str());
|
||||
auto sheets_node = root_node.child(with_ns("sheets").c_str());
|
||||
auto root_node = doc.get_child(with_ns("workbook"));
|
||||
auto sheets_node = root_node.get_child(with_ns("sheets"));
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> sheets;
|
||||
|
||||
// store temp because pugixml iteration uses the internal char array multiple times
|
||||
auto sheet_element_name = with_ns("sheet");
|
||||
|
||||
for(auto sheet_node : sheets_node.children(sheet_element_name.c_str()))
|
||||
for(auto sheet_node : sheets_node.children(sheet_element_name))
|
||||
{
|
||||
std::string id = sheet_node.attribute("r:id").as_string();
|
||||
std::string name = sheet_node.attribute("name").as_string();
|
||||
|
@ -112,53 +116,6 @@ void workbook_serializer::read_properties_core(const xml_document &xml)
|
|||
}
|
||||
}
|
||||
|
||||
std::string workbook_serializer::read_dimension(const std::string &xml_string)
|
||||
{
|
||||
pugi::xml_document doc;
|
||||
doc.load(xml_string.c_str());
|
||||
auto root_node = doc.child("worksheet");
|
||||
auto dimension_node = root_node.child("dimension");
|
||||
std::string dimension = dimension_node.attribute("ref").as_string();
|
||||
return dimension;
|
||||
}
|
||||
|
||||
std::vector<relationship> workbook_serializer::read_relationships(zip_file &archive, const std::string &filename)
|
||||
{
|
||||
auto filename_separator_index = filename.find_last_of('/');
|
||||
auto basename = filename.substr(filename_separator_index + 1);
|
||||
auto dirname = filename.substr(0, filename_separator_index);
|
||||
auto rels_filename = dirname + "/_rels/" + basename + ".rels";
|
||||
|
||||
pugi::xml_document doc;
|
||||
auto content = archive.read(rels_filename);
|
||||
doc.load(content.c_str());
|
||||
|
||||
auto root_node = doc.child("Relationships");
|
||||
|
||||
std::vector<relationship> relationships;
|
||||
|
||||
for(auto relationship : root_node.children("Relationship"))
|
||||
{
|
||||
std::string id = relationship.attribute("Id").as_string();
|
||||
std::string type = relationship.attribute("Type").as_string();
|
||||
std::string target = relationship.attribute("Target").as_string();
|
||||
|
||||
if(target[0] != '/' && target.substr(0, 2) != "..")
|
||||
{
|
||||
target = dirname + "/" + target;
|
||||
}
|
||||
|
||||
if(target[0] == '/')
|
||||
{
|
||||
target = target.substr(1);
|
||||
}
|
||||
|
||||
relationships.push_back(xlnt::relationship(type, id, target));
|
||||
}
|
||||
|
||||
return relationships;
|
||||
}
|
||||
|
||||
std::string workbook_serializer::determine_document_type(const manifest &manifest)
|
||||
{
|
||||
if(!manifest.has_override_type(constants::ArcWorkbook))
|
||||
|
@ -184,22 +141,27 @@ std::string workbook_serializer::determine_document_type(const manifest &manifes
|
|||
return "unsupported";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a list of worksheets.
|
||||
/// content types has a list of paths but no titles
|
||||
/// workbook has a list of titles and relIds but no paths
|
||||
/// workbook_rels has a list of relIds and paths but no titles
|
||||
/// </summary>
|
||||
std::vector<std::pair<std::string, std::string>> workbook_serializer::detect_worksheets(zip_file &archive)
|
||||
{
|
||||
static const std::string ValidWorksheet = "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml";
|
||||
|
||||
auto content_types = read_content_types(archive);
|
||||
std::vector<std::string> valid_sheets;
|
||||
|
||||
for(const auto &content_type : content_types)
|
||||
for(const auto &content_type : wb_.get_manifest().get_override_types())
|
||||
{
|
||||
if(content_type.second == ValidWorksheet)
|
||||
if(content_type.get_content_type() == ValidWorksheet)
|
||||
{
|
||||
valid_sheets.push_back(content_type.first);
|
||||
valid_sheets.push_back(content_type.get_part_name());
|
||||
}
|
||||
}
|
||||
|
||||
auto workbook_relationships = read_relationships(archive, "xl/workbook.xml");
|
||||
auto &workbook_relationships = wb_.get_relationships();
|
||||
std::vector<std::pair<std::string, std::string>> result;
|
||||
|
||||
for(const auto &ws : read_sheets(archive))
|
||||
|
@ -216,456 +178,80 @@ std::vector<std::pair<std::string, std::string>> workbook_serializer::detect_wor
|
|||
return result;
|
||||
}
|
||||
|
||||
std::string workbook_serializer::write_shared_strings(const std::vector<std::string> &string_table)
|
||||
xml_document workbook_serializer::write_properties_core() const
|
||||
{
|
||||
pugi::xml_document doc;
|
||||
auto root_node = doc.append_child("sst");
|
||||
root_node.append_attribute("xmlns").set_value("http://schemas.openxmlformats.org/spreadsheetml/2006/main");
|
||||
root_node.append_attribute("uniqueCount").set_value((int)string_table.size());
|
||||
auto &props = wb_.get_properties();
|
||||
|
||||
for(auto string : string_table)
|
||||
xml_document xml;
|
||||
|
||||
xml.add_namespace("cp", "http://schemas.openxmlformats.org/package/2006/metadata/core-properties");
|
||||
xml.add_namespace("dc", "http://purl.org/dc/elements/1.1/");
|
||||
xml.add_namespace("dcmitype", "http://purl.org/dc/dcmitype/");
|
||||
xml.add_namespace("dcterms", "http://purl.org/dc/terms/");
|
||||
xml.add_namespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
|
||||
|
||||
auto &root_node = xml.root();
|
||||
root_node.set_name("cp:coreProperties");
|
||||
|
||||
root_node.add_child("dc:creator").set_text(props.creator);
|
||||
root_node.add_child("cp:lastModifiedBy").set_text(props.last_modified_by);
|
||||
root_node.add_child("dcterms:created").set_text(datetime_to_w3cdtf(props.created));
|
||||
root_node.get_child("dcterms:created").add_attribute("xsi:type", "dcterms:W3CDTF");
|
||||
root_node.add_child("dcterms:modified").set_text(datetime_to_w3cdtf(props.modified));
|
||||
root_node.get_child("dcterms:modified").add_attribute("xsi:type", "dcterms:W3CDTF");
|
||||
root_node.add_child("dc:title").set_text(props.title);
|
||||
root_node.add_child("dc:description");
|
||||
root_node.add_child("dc:subject");
|
||||
root_node.add_child("cp:keywords");
|
||||
root_node.add_child("cp:category");
|
||||
|
||||
return xml;
|
||||
}
|
||||
|
||||
xml_document workbook_serializer::write_properties_app() const
|
||||
{
|
||||
xml_document xml;
|
||||
|
||||
xml.add_namespace("xmlns", "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties");
|
||||
xml.add_namespace("xmlns:vt", "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes");
|
||||
|
||||
auto &root_node = xml.root();
|
||||
root_node.set_name("Properties");
|
||||
|
||||
root_node.add_child("Application").set_text("Microsoft Excel");
|
||||
root_node.add_child("DocSecurity").set_text("0");
|
||||
root_node.add_child("ScaleCrop").set_text("false");
|
||||
root_node.add_child("Company");
|
||||
root_node.add_child("LinksUpToDate").set_text("false");
|
||||
root_node.add_child("SharedDoc").set_text("false");
|
||||
root_node.add_child("HyperlinksChanged").set_text("false");
|
||||
root_node.add_child("AppVersion").set_text("12.0000");
|
||||
|
||||
auto heading_pairs_node = root_node.add_child("HeadingPairs");
|
||||
auto heading_pairs_vector_node = heading_pairs_node.add_child("vt:vector");
|
||||
heading_pairs_vector_node.add_attribute("baseType", "variant");
|
||||
heading_pairs_vector_node.add_attribute("size", "2");
|
||||
heading_pairs_vector_node.add_child("vt:variant").add_child("vt:lpstr").set_text("Worksheets");
|
||||
heading_pairs_vector_node.add_child("vt:variant").add_child("vt:i4").set_text(std::to_string(wb_.get_sheet_names().size()));
|
||||
|
||||
auto titles_of_parts_node = root_node.add_child("TitlesOfParts");
|
||||
auto titles_of_parts_vector_node = titles_of_parts_node.add_child("vt:vector");
|
||||
titles_of_parts_vector_node.add_attribute("baseType", "lpstr");
|
||||
titles_of_parts_vector_node.add_attribute("size", std::to_string(wb_.get_sheet_names().size()));
|
||||
|
||||
for(auto ws : wb_)
|
||||
{
|
||||
root_node.append_child("si").append_child("t").text().set(string.c_str());
|
||||
titles_of_parts_vector_node.add_child("vt:lpstr").set_text(ws.get_title());
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
doc.save(ss);
|
||||
|
||||
return ss.str();
|
||||
|
||||
return xml;
|
||||
}
|
||||
|
||||
std::string workbook_serializer::write_properties_core(const document_properties &prop)
|
||||
{
|
||||
pugi::xml_document doc;
|
||||
auto root_node = doc.append_child("cp:coreProperties");
|
||||
root_node.append_attribute("xmlns:cp").set_value("http://schemas.openxmlformats.org/package/2006/metadata/core-properties");
|
||||
root_node.append_attribute("xmlns:dc").set_value("http://purl.org/dc/elements/1.1/");
|
||||
root_node.append_attribute("xmlns:dcmitype").set_value("http://purl.org/dc/dcmitype/");
|
||||
root_node.append_attribute("xmlns:dcterms").set_value("http://purl.org/dc/terms/");
|
||||
root_node.append_attribute("xmlns:xsi").set_value("http://www.w3.org/2001/XMLSchema-instance");
|
||||
|
||||
root_node.append_child("dc:creator").text().set(prop.creator.c_str());
|
||||
root_node.append_child("cp:lastModifiedBy").text().set(prop.last_modified_by.c_str());
|
||||
root_node.append_child("dcterms:created").text().set(datetime_to_w3cdtf(prop.created).c_str());
|
||||
root_node.child("dcterms:created").append_attribute("xsi:type").set_value("dcterms:W3CDTF");
|
||||
root_node.append_child("dcterms:modified").text().set(datetime_to_w3cdtf(prop.modified).c_str());
|
||||
root_node.child("dcterms:modified").append_attribute("xsi:type").set_value("dcterms:W3CDTF");
|
||||
root_node.append_child("dc:title").text().set(prop.title.c_str());
|
||||
root_node.append_child("dc:description");
|
||||
root_node.append_child("dc:subject");
|
||||
root_node.append_child("cp:keywords");
|
||||
root_node.append_child("cp:category");
|
||||
|
||||
std::stringstream ss;
|
||||
doc.save(ss);
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string workbook_serializer::write_worksheet_rels(worksheet ws)
|
||||
{
|
||||
return write_relationships(ws.get_relationships(), "");
|
||||
}
|
||||
|
||||
std::string workbook_serializer::write_theme()
|
||||
{
|
||||
pugi::xml_document doc;
|
||||
auto theme_node = doc.append_child("a:theme");
|
||||
theme_node.append_attribute("xmlns:a").set_value(constants::Namespaces.at("drawingml").c_str());
|
||||
theme_node.append_attribute("name").set_value("Office Theme");
|
||||
auto theme_elements_node = theme_node.append_child("a:themeElements");
|
||||
auto clr_scheme_node = theme_elements_node.append_child("a:clrScheme");
|
||||
clr_scheme_node.append_attribute("name").set_value("Office");
|
||||
|
||||
struct scheme_element
|
||||
{
|
||||
std::string name;
|
||||
std::string sub_element_name;
|
||||
std::string val;
|
||||
};
|
||||
|
||||
std::vector<scheme_element> scheme_elements =
|
||||
{
|
||||
{"a:dk1", "a:sysClr", "windowText"},
|
||||
{"a:lt1", "a:sysClr", "window"},
|
||||
{"a:dk2", "a:srgbClr", "1F497D"},
|
||||
{"a:lt2", "a:srgbClr", "EEECE1"},
|
||||
{"a:accent1", "a:srgbClr", "4F81BD"},
|
||||
{"a:accent2", "a:srgbClr", "C0504D"},
|
||||
{"a:accent3", "a:srgbClr", "9BBB59"},
|
||||
{"a:accent4", "a:srgbClr", "8064A2"},
|
||||
{"a:accent5", "a:srgbClr", "4BACC6"},
|
||||
{"a:accent6", "a:srgbClr", "F79646"},
|
||||
{"a:hlink", "a:srgbClr", "0000FF"},
|
||||
{"a:folHlink", "a:srgbClr", "800080"},
|
||||
};
|
||||
|
||||
for(auto element : scheme_elements)
|
||||
{
|
||||
auto element_node = clr_scheme_node.append_child(element.name.c_str());
|
||||
element_node.append_child(element.sub_element_name.c_str()).append_attribute("val").set_value(element.val.c_str());
|
||||
|
||||
if(element.name == "a:dk1")
|
||||
{
|
||||
element_node.child(element.sub_element_name.c_str()).append_attribute("lastClr").set_value("000000");
|
||||
}
|
||||
else if(element.name == "a:lt1")
|
||||
{
|
||||
element_node.child(element.sub_element_name.c_str()).append_attribute("lastClr").set_value("FFFFFF");
|
||||
}
|
||||
}
|
||||
|
||||
struct font_scheme
|
||||
{
|
||||
bool typeface;
|
||||
std::string script;
|
||||
std::string major;
|
||||
std::string minor;
|
||||
};
|
||||
|
||||
std::vector<font_scheme> font_schemes =
|
||||
{
|
||||
{true, "a:latin", "Cambria", "Calibri"},
|
||||
{true, "a:ea", "", ""},
|
||||
{true, "a:cs", "", ""},
|
||||
{false, "Jpan", "\xef\xbc\xad\xef\xbc\xb3 \xef\xbc\xb0\xe3\x82\xb4\xe3\x82\xb7\xe3\x83\x83\xe3\x82\xaf", "\xef\xbc\xad\xef\xbc\xb3 \xef\xbc\xb0\xe3\x82\xb4\xe3\x82\xb7\xe3\x83\x83\xe3\x82\xaf"},
|
||||
{false, "Hang", "\xeb\xa7\x91\xec\x9d\x80 \xea\xb3\xa0\xeb\x94\x95", "\xeb\xa7\x91\xec\x9d\x80 \xea\xb3\xa0\xeb\x94\x95"},
|
||||
{false, "Hans", "\xe5\xae\x8b\xe4\xbd\x93", "\xe5\xae\x8b\xe4\xbd\x93"},
|
||||
{false, "Hant", "\xe6\x96\xb0\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94", "\xe6\x96\xb0\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94"},
|
||||
{false, "Arab", "Times New Roman", "Arial"},
|
||||
{false, "Hebr", "Times New Roman", "Arial"},
|
||||
{false, "Thai", "Tahoma", "Tahoma"},
|
||||
{false, "Ethi", "Nyala", "Nyala"},
|
||||
{false, "Beng", "Vrinda", "Vrinda"},
|
||||
{false, "Gujr", "Shruti", "Shruti"},
|
||||
{false, "Khmr", "MoolBoran", "DaunPenh"},
|
||||
{false, "Knda", "Tunga", "Tunga"},
|
||||
{false, "Guru", "Raavi", "Raavi"},
|
||||
{false, "Cans", "Euphemia", "Euphemia"},
|
||||
{false, "Cher", "Plantagenet Cherokee", "Plantagenet Cherokee"},
|
||||
{false, "Yiii", "Microsoft Yi Baiti", "Microsoft Yi Baiti"},
|
||||
{false, "Tibt", "Microsoft Himalaya", "Microsoft Himalaya"},
|
||||
{false, "Thaa", "MV Boli", "MV Boli"},
|
||||
{false, "Deva", "Mangal", "Mangal"},
|
||||
{false, "Telu", "Gautami", "Gautami"},
|
||||
{false, "Taml", "Latha", "Latha"},
|
||||
{false, "Syrc", "Estrangelo Edessa", "Estrangelo Edessa"},
|
||||
{false, "Orya", "Kalinga", "Kalinga"},
|
||||
{false, "Mlym", "Kartika", "Kartika"},
|
||||
{false, "Laoo", "DokChampa", "DokChampa"},
|
||||
{false, "Sinh", "Iskoola Pota", "Iskoola Pota"},
|
||||
{false, "Mong", "Mongolian Baiti", "Mongolian Baiti"},
|
||||
{false, "Viet", "Times New Roman", "Arial"},
|
||||
{false, "Uigh", "Microsoft Uighur", "Microsoft Uighur"}
|
||||
};
|
||||
|
||||
auto font_scheme_node = theme_elements_node.append_child("a:fontScheme");
|
||||
font_scheme_node.append_attribute("name").set_value("Office");
|
||||
|
||||
auto major_fonts_node = font_scheme_node.append_child("a:majorFont");
|
||||
auto minor_fonts_node = font_scheme_node.append_child("a:minorFont");
|
||||
|
||||
for(auto scheme : font_schemes)
|
||||
{
|
||||
pugi::xml_node major_font_node, minor_font_node;
|
||||
|
||||
if(scheme.typeface)
|
||||
{
|
||||
major_font_node = major_fonts_node.append_child(scheme.script.c_str());
|
||||
minor_font_node = minor_fonts_node.append_child(scheme.script.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
major_font_node = major_fonts_node.append_child("a:font");
|
||||
major_font_node.append_attribute("script").set_value(scheme.script.c_str());
|
||||
minor_font_node = minor_fonts_node.append_child("a:font");
|
||||
minor_font_node.append_attribute("script").set_value(scheme.script.c_str());
|
||||
}
|
||||
|
||||
major_font_node.append_attribute("typeface").set_value(scheme.major.c_str());
|
||||
minor_font_node.append_attribute("typeface").set_value(scheme.minor.c_str());
|
||||
}
|
||||
|
||||
auto format_scheme_node = theme_elements_node.append_child("a:fmtScheme");
|
||||
format_scheme_node.append_attribute("name").set_value("Office");
|
||||
|
||||
auto fill_style_list_node = format_scheme_node.append_child("a:fillStyleLst");
|
||||
fill_style_list_node.append_child("a:solidFill").append_child("a:schemeClr").append_attribute("val").set_value("phClr");
|
||||
|
||||
auto grad_fill_node = fill_style_list_node.append_child("a:gradFill");
|
||||
grad_fill_node.append_attribute("rotWithShape").set_value(1);
|
||||
|
||||
auto grad_fill_list = grad_fill_node.append_child("a:gsLst");
|
||||
auto gs_node = grad_fill_list.append_child("a:gs");
|
||||
gs_node.append_attribute("pos").set_value(0);
|
||||
auto scheme_color_node = gs_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:tint").append_attribute("val").set_value(50000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(300000);
|
||||
|
||||
gs_node = grad_fill_list.append_child("a:gs");
|
||||
gs_node.append_attribute("pos").set_value(35000);
|
||||
scheme_color_node = gs_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:tint").append_attribute("val").set_value(37000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(300000);
|
||||
|
||||
gs_node = grad_fill_list.append_child("a:gs");
|
||||
gs_node.append_attribute("pos").set_value(100000);
|
||||
scheme_color_node = gs_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:tint").append_attribute("val").set_value(15000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(350000);
|
||||
|
||||
auto lin_node = grad_fill_node.append_child("a:lin");
|
||||
lin_node.append_attribute("ang").set_value(16200000);
|
||||
lin_node.append_attribute("scaled").set_value(1);
|
||||
|
||||
grad_fill_node = fill_style_list_node.append_child("a:gradFill");
|
||||
grad_fill_node.append_attribute("rotWithShape").set_value(1);
|
||||
|
||||
grad_fill_list = grad_fill_node.append_child("a:gsLst");
|
||||
gs_node = grad_fill_list.append_child("a:gs");
|
||||
gs_node.append_attribute("pos").set_value(0);
|
||||
scheme_color_node = gs_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:shade").append_attribute("val").set_value(51000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(130000);
|
||||
|
||||
gs_node = grad_fill_list.append_child("a:gs");
|
||||
gs_node.append_attribute("pos").set_value(80000);
|
||||
scheme_color_node = gs_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:shade").append_attribute("val").set_value(93000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(130000);
|
||||
|
||||
gs_node = grad_fill_list.append_child("a:gs");
|
||||
gs_node.append_attribute("pos").set_value(100000);
|
||||
scheme_color_node = gs_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:shade").append_attribute("val").set_value(94000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(135000);
|
||||
|
||||
lin_node = grad_fill_node.append_child("a:lin");
|
||||
lin_node.append_attribute("ang").set_value(16200000);
|
||||
lin_node.append_attribute("scaled").set_value(0);
|
||||
|
||||
auto line_style_list_node = format_scheme_node.append_child("a:lnStyleLst");
|
||||
|
||||
auto ln_node = line_style_list_node.append_child("a:ln");
|
||||
ln_node.append_attribute("w").set_value(9525);
|
||||
ln_node.append_attribute("cap").set_value("flat");
|
||||
ln_node.append_attribute("cmpd").set_value("sng");
|
||||
ln_node.append_attribute("algn").set_value("ctr");
|
||||
|
||||
auto solid_fill_node = ln_node.append_child("a:solidFill");
|
||||
scheme_color_node = solid_fill_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:shade").append_attribute("val").set_value(95000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(105000);
|
||||
ln_node.append_child("a:prstDash").append_attribute("val").set_value("solid");
|
||||
|
||||
ln_node = line_style_list_node.append_child("a:ln");
|
||||
ln_node.append_attribute("w").set_value(25400);
|
||||
ln_node.append_attribute("cap").set_value("flat");
|
||||
ln_node.append_attribute("cmpd").set_value("sng");
|
||||
ln_node.append_attribute("algn").set_value("ctr");
|
||||
|
||||
solid_fill_node = ln_node.append_child("a:solidFill");
|
||||
scheme_color_node = solid_fill_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
ln_node.append_child("a:prstDash").append_attribute("val").set_value("solid");
|
||||
|
||||
ln_node = line_style_list_node.append_child("a:ln");
|
||||
ln_node.append_attribute("w").set_value(38100);
|
||||
ln_node.append_attribute("cap").set_value("flat");
|
||||
ln_node.append_attribute("cmpd").set_value("sng");
|
||||
ln_node.append_attribute("algn").set_value("ctr");
|
||||
|
||||
solid_fill_node = ln_node.append_child("a:solidFill");
|
||||
scheme_color_node = solid_fill_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
ln_node.append_child("a:prstDash").append_attribute("val").set_value("solid");
|
||||
|
||||
auto effect_style_list_node = format_scheme_node.append_child("a:effectStyleLst");
|
||||
auto effect_style_node = effect_style_list_node.append_child("a:effectStyle");
|
||||
auto effect_list_node = effect_style_node.append_child("a:effectLst");
|
||||
auto outer_shadow_node = effect_list_node.append_child("a:outerShdw");
|
||||
outer_shadow_node.append_attribute("blurRad").set_value(40000);
|
||||
outer_shadow_node.append_attribute("dist").set_value(20000);
|
||||
outer_shadow_node.append_attribute("dir").set_value(5400000);
|
||||
outer_shadow_node.append_attribute("rotWithShape").set_value(0);
|
||||
auto srgb_clr_node = outer_shadow_node.append_child("a:srgbClr");
|
||||
srgb_clr_node.append_attribute("val").set_value("000000");
|
||||
srgb_clr_node.append_child("a:alpha").append_attribute("val").set_value(38000);
|
||||
|
||||
effect_style_node = effect_style_list_node.append_child("a:effectStyle");
|
||||
effect_list_node = effect_style_node.append_child("a:effectLst");
|
||||
outer_shadow_node = effect_list_node.append_child("a:outerShdw");
|
||||
outer_shadow_node.append_attribute("blurRad").set_value(40000);
|
||||
outer_shadow_node.append_attribute("dist").set_value(23000);
|
||||
outer_shadow_node.append_attribute("dir").set_value(5400000);
|
||||
outer_shadow_node.append_attribute("rotWithShape").set_value(0);
|
||||
srgb_clr_node = outer_shadow_node.append_child("a:srgbClr");
|
||||
srgb_clr_node.append_attribute("val").set_value("000000");
|
||||
srgb_clr_node.append_child("a:alpha").append_attribute("val").set_value(35000);
|
||||
|
||||
effect_style_node = effect_style_list_node.append_child("a:effectStyle");
|
||||
effect_list_node = effect_style_node.append_child("a:effectLst");
|
||||
outer_shadow_node = effect_list_node.append_child("a:outerShdw");
|
||||
outer_shadow_node.append_attribute("blurRad").set_value(40000);
|
||||
outer_shadow_node.append_attribute("dist").set_value(23000);
|
||||
outer_shadow_node.append_attribute("dir").set_value(5400000);
|
||||
outer_shadow_node.append_attribute("rotWithShape").set_value(0);
|
||||
srgb_clr_node = outer_shadow_node.append_child("a:srgbClr");
|
||||
srgb_clr_node.append_attribute("val").set_value("000000");
|
||||
srgb_clr_node.append_child("a:alpha").append_attribute("val").set_value(35000);
|
||||
auto scene3d_node = effect_style_node.append_child("a:scene3d");
|
||||
auto camera_node = scene3d_node.append_child("a:camera");
|
||||
camera_node.append_attribute("prst").set_value("orthographicFront");
|
||||
auto rot_node = camera_node.append_child("a:rot");
|
||||
rot_node.append_attribute("lat").set_value(0);
|
||||
rot_node.append_attribute("lon").set_value(0);
|
||||
rot_node.append_attribute("rev").set_value(0);
|
||||
auto light_rig_node = scene3d_node.append_child("a:lightRig");
|
||||
light_rig_node.append_attribute("rig").set_value("threePt");
|
||||
light_rig_node.append_attribute("dir").set_value("t");
|
||||
rot_node = light_rig_node.append_child("a:rot");
|
||||
rot_node.append_attribute("lat").set_value(0);
|
||||
rot_node.append_attribute("lon").set_value(0);
|
||||
rot_node.append_attribute("rev").set_value(1200000);
|
||||
|
||||
auto bevel_node = effect_style_node.append_child("a:sp3d").append_child("a:bevelT");
|
||||
bevel_node.append_attribute("w").set_value(63500);
|
||||
bevel_node.append_attribute("h").set_value(25400);
|
||||
|
||||
auto bg_fill_style_list_node = format_scheme_node.append_child("a:bgFillStyleLst");
|
||||
|
||||
bg_fill_style_list_node.append_child("a:solidFill").append_child("a:schemeClr").append_attribute("val").set_value("phClr");
|
||||
|
||||
grad_fill_node = bg_fill_style_list_node.append_child("a:gradFill");
|
||||
grad_fill_node.append_attribute("rotWithShape").set_value(1);
|
||||
|
||||
grad_fill_list = grad_fill_node.append_child("a:gsLst");
|
||||
gs_node = grad_fill_list.append_child("a:gs");
|
||||
gs_node.append_attribute("pos").set_value(0);
|
||||
scheme_color_node = gs_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:tint").append_attribute("val").set_value(40000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(350000);
|
||||
|
||||
gs_node = grad_fill_list.append_child("a:gs");
|
||||
gs_node.append_attribute("pos").set_value(40000);
|
||||
scheme_color_node = gs_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:tint").append_attribute("val").set_value(45000);
|
||||
scheme_color_node.append_child("a:shade").append_attribute("val").set_value(99000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(350000);
|
||||
|
||||
gs_node = grad_fill_list.append_child("a:gs");
|
||||
gs_node.append_attribute("pos").set_value(100000);
|
||||
scheme_color_node = gs_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:shade").append_attribute("val").set_value(20000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(255000);
|
||||
|
||||
auto path_node = grad_fill_node.append_child("a:path");
|
||||
path_node.append_attribute("path").set_value("circle");
|
||||
auto fill_to_rect_node = path_node.append_child("a:fillToRect");
|
||||
fill_to_rect_node.append_attribute("l").set_value(50000);
|
||||
fill_to_rect_node.append_attribute("t").set_value(-80000);
|
||||
fill_to_rect_node.append_attribute("r").set_value(50000);
|
||||
fill_to_rect_node.append_attribute("b").set_value(180000);
|
||||
|
||||
grad_fill_node = bg_fill_style_list_node.append_child("a:gradFill");
|
||||
grad_fill_node.append_attribute("rotWithShape").set_value(1);
|
||||
|
||||
grad_fill_list = grad_fill_node.append_child("a:gsLst");
|
||||
gs_node = grad_fill_list.append_child("a:gs");
|
||||
gs_node.append_attribute("pos").set_value(0);
|
||||
scheme_color_node = gs_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:tint").append_attribute("val").set_value(80000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(300000);
|
||||
|
||||
gs_node = grad_fill_list.append_child("a:gs");
|
||||
gs_node.append_attribute("pos").set_value(100000);
|
||||
scheme_color_node = gs_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:shade").append_attribute("val").set_value(30000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(200000);
|
||||
|
||||
path_node = grad_fill_node.append_child("a:path");
|
||||
path_node.append_attribute("path").set_value("circle");
|
||||
fill_to_rect_node = path_node.append_child("a:fillToRect");
|
||||
fill_to_rect_node.append_attribute("l").set_value(50000);
|
||||
fill_to_rect_node.append_attribute("t").set_value(50000);
|
||||
fill_to_rect_node.append_attribute("r").set_value(50000);
|
||||
fill_to_rect_node.append_attribute("b").set_value(50000);
|
||||
|
||||
theme_node.append_child("a:objectDefaults");
|
||||
theme_node.append_child("a:extraClrSchemeLst");
|
||||
|
||||
std::stringstream ss;
|
||||
doc.print(ss);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string write_properties_app(const workbook &wb)
|
||||
{
|
||||
pugi::xml_document doc;
|
||||
auto root_node = doc.append_child("Properties");
|
||||
root_node.append_attribute("xmlns").set_value("http://schemas.openxmlformats.org/officeDocument/2006/extended-properties");
|
||||
root_node.append_attribute("xmlns:vt").set_value("http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes");
|
||||
|
||||
root_node.append_child("Application").text().set("Microsoft Excel");
|
||||
root_node.append_child("DocSecurity").text().set("0");
|
||||
root_node.append_child("ScaleCrop").text().set("false");
|
||||
root_node.append_child("Company");
|
||||
root_node.append_child("LinksUpToDate").text().set("false");
|
||||
root_node.append_child("SharedDoc").text().set("false");
|
||||
root_node.append_child("HyperlinksChanged").text().set("false");
|
||||
root_node.append_child("AppVersion").text().set("12.0000");
|
||||
|
||||
auto heading_pairs_node = root_node.append_child("HeadingPairs");
|
||||
auto heading_pairs_vector_node = heading_pairs_node.append_child("vt:vector");
|
||||
heading_pairs_vector_node.append_attribute("baseType").set_value("variant");
|
||||
heading_pairs_vector_node.append_attribute("size").set_value("2");
|
||||
heading_pairs_vector_node.append_child("vt:variant").append_child("vt:lpstr").text().set("Worksheets");
|
||||
heading_pairs_vector_node.append_child("vt:variant").append_child("vt:i4").text().set(std::to_string(wb.get_sheet_names().size()).c_str());
|
||||
|
||||
auto titles_of_parts_node = root_node.append_child("TitlesOfParts");
|
||||
auto titles_of_parts_vector_node = titles_of_parts_node.append_child("vt:vector");
|
||||
titles_of_parts_vector_node.append_attribute("baseType").set_value("lpstr");
|
||||
titles_of_parts_vector_node.append_attribute("size").set_value(std::to_string(wb.get_sheet_names().size()).c_str());
|
||||
|
||||
for(auto ws : wb)
|
||||
{
|
||||
titles_of_parts_vector_node.append_child("vt:lpstr").text().set(ws.get_title().c_str());
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
doc.save(ss);
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string write_root_rels(const workbook &)
|
||||
{
|
||||
std::vector<relationship> relationships;
|
||||
|
||||
relationships.push_back(relationship(relationship::type::extended_properties, "rId3", "docProps/app.xml"));
|
||||
relationships.push_back(relationship(relationship::type::core_properties, "rId2", "docProps/core.xml"));
|
||||
relationships.push_back(relationship(relationship::type::office_document, "rId1", "xl/workbook.xml"));
|
||||
|
||||
return write_relationships(relationships, "");
|
||||
}
|
||||
|
||||
std::string write_workbook(const workbook &wb)
|
||||
xml_document workbook_serializer::write_workbook() const
|
||||
{
|
||||
std::size_t num_visible = 0;
|
||||
|
||||
for(auto ws : wb)
|
||||
for(auto ws : wb_)
|
||||
{
|
||||
if(ws.get_page_setup().get_sheet_state() == xlnt::page_setup::sheet_state::visible)
|
||||
{
|
||||
|
@ -675,41 +261,44 @@ std::string write_workbook(const workbook &wb)
|
|||
|
||||
if(num_visible == 0)
|
||||
{
|
||||
throw value_error();
|
||||
throw xlnt::value_error();
|
||||
}
|
||||
|
||||
pugi::xml_document doc;
|
||||
auto root_node = doc.append_child("workbook");
|
||||
root_node.append_attribute("xmlns").set_value("http://schemas.openxmlformats.org/spreadsheetml/2006/main");
|
||||
root_node.append_attribute("xmlns:r").set_value("http://schemas.openxmlformats.org/officeDocument/2006/relationships");
|
||||
xml_document xml;
|
||||
|
||||
auto file_version_node = root_node.append_child("fileVersion");
|
||||
file_version_node.append_attribute("appName").set_value("xl");
|
||||
file_version_node.append_attribute("lastEdited").set_value("4");
|
||||
file_version_node.append_attribute("lowestEdited").set_value("4");
|
||||
file_version_node.append_attribute("rupBuild").set_value("4505");
|
||||
xml.add_namespace("xmlns", "http://schemas.openxmlformats.org/spreadsheetml/2006/main");
|
||||
xml.add_namespace("xmlns:r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships");
|
||||
|
||||
auto workbook_pr_node = root_node.append_child("workbookPr");
|
||||
workbook_pr_node.append_attribute("codeName").set_value("ThisWorkbook");
|
||||
workbook_pr_node.append_attribute("defaultThemeVersion").set_value("124226");
|
||||
workbook_pr_node.append_attribute("date1904").set_value(wb.get_properties().excel_base_date == calendar::mac_1904 ? 1 : 0);
|
||||
auto &root_node = xml.root();
|
||||
root_node.set_name("workbook");
|
||||
|
||||
auto book_views_node = root_node.append_child("bookViews");
|
||||
auto workbook_view_node = book_views_node.append_child("workbookView");
|
||||
workbook_view_node.append_attribute("activeTab").set_value("0");
|
||||
workbook_view_node.append_attribute("autoFilterDateGrouping").set_value("1");
|
||||
workbook_view_node.append_attribute("firstSheet").set_value("0");
|
||||
workbook_view_node.append_attribute("minimized").set_value("0");
|
||||
workbook_view_node.append_attribute("showHorizontalScroll").set_value("1");
|
||||
workbook_view_node.append_attribute("showSheetTabs").set_value("1");
|
||||
workbook_view_node.append_attribute("showVerticalScroll").set_value("1");
|
||||
workbook_view_node.append_attribute("tabRatio").set_value("600");
|
||||
workbook_view_node.append_attribute("visibility").set_value("visible");
|
||||
auto &file_version_node = root_node.add_child("fileVersion");
|
||||
file_version_node.add_attribute("appName", "xl");
|
||||
file_version_node.add_attribute("lastEdited", "4");
|
||||
file_version_node.add_attribute("lowestEdited", "4");
|
||||
file_version_node.add_attribute("rupBuild", "4505");
|
||||
|
||||
auto sheets_node = root_node.append_child("sheets");
|
||||
auto defined_names_node = root_node.append_child("definedNames");
|
||||
auto &workbook_pr_node = root_node.add_child("workbookPr");
|
||||
workbook_pr_node.add_attribute("codeName", "ThisWorkbook");
|
||||
workbook_pr_node.add_attribute("defaultThemeVersion", "124226");
|
||||
workbook_pr_node.add_attribute("date1904", wb_.get_properties().excel_base_date == calendar::mac_1904 ? "1" : "0");
|
||||
|
||||
for(auto relationship : wb.get_relationships())
|
||||
auto book_views_node = root_node.add_child("bookViews");
|
||||
auto workbook_view_node = book_views_node.add_child("workbookView");
|
||||
workbook_view_node.add_attribute("activeTab", "0");
|
||||
workbook_view_node.add_attribute("autoFilterDateGrouping", "1");
|
||||
workbook_view_node.add_attribute("firstSheet", "0");
|
||||
workbook_view_node.add_attribute("minimized", "0");
|
||||
workbook_view_node.add_attribute("showHorizontalScroll", "1");
|
||||
workbook_view_node.add_attribute("showSheetTabs", "1");
|
||||
workbook_view_node.add_attribute("showVerticalScroll", "1");
|
||||
workbook_view_node.add_attribute("tabRatio", "600");
|
||||
workbook_view_node.add_attribute("visibility", "visible");
|
||||
|
||||
auto sheets_node = root_node.add_child("sheets");
|
||||
auto defined_names_node = root_node.add_child("definedNames");
|
||||
|
||||
for(auto relationship : wb_.get_relationships())
|
||||
{
|
||||
if(relationship.get_type() == relationship::type::worksheet)
|
||||
{
|
||||
|
@ -723,55 +312,41 @@ std::string write_workbook(const workbook &wb)
|
|||
sheet_index_string = sheet_index_string.substr(static_cast<std::string::size_type>(first_digit + 1));
|
||||
std::size_t sheet_index = static_cast<std::size_t>(std::stoll(sheet_index_string) - 1);
|
||||
|
||||
auto ws = wb.get_sheet_by_index(sheet_index);
|
||||
auto ws = wb_.get_sheet_by_index(sheet_index);
|
||||
|
||||
auto sheet_node = sheets_node.append_child("sheet");
|
||||
sheet_node.append_attribute("name").set_value(ws.get_title().c_str());
|
||||
sheet_node.append_attribute("r:id").set_value(relationship.get_id().c_str());
|
||||
sheet_node.append_attribute("sheetId").set_value(std::to_string(sheet_index + 1).c_str());
|
||||
auto sheet_node = sheets_node.add_child("sheet");
|
||||
sheet_node.add_attribute("name", ws.get_title());
|
||||
sheet_node.add_attribute("r:id", relationship.get_id());
|
||||
sheet_node.add_attribute("sheetId", std::to_string(sheet_index + 1));
|
||||
|
||||
if(ws.has_auto_filter())
|
||||
{
|
||||
auto defined_name_node = defined_names_node.append_child("definedName");
|
||||
defined_name_node.append_attribute("name").set_value("_xlnm._FilterDatabase");
|
||||
defined_name_node.append_attribute("hidden").set_value(1);
|
||||
defined_name_node.append_attribute("localSheetId").set_value(0);
|
||||
auto &defined_name_node = defined_names_node.add_child("definedName");
|
||||
defined_name_node.add_attribute("name", "_xlnm._FilterDatabase");
|
||||
defined_name_node.add_attribute("hidden", "1");
|
||||
defined_name_node.add_attribute("localSheetId", "0");
|
||||
std::string name = "'" + ws.get_title() + "'!" + range_reference::make_absolute(ws.get_auto_filter()).to_string();
|
||||
defined_name_node.text().set(name.c_str());
|
||||
defined_name_node.set_text(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto calc_pr_node = root_node.append_child("calcPr");
|
||||
calc_pr_node.append_attribute("calcId").set_value("124519");
|
||||
calc_pr_node.append_attribute("calcMode").set_value("auto");
|
||||
calc_pr_node.append_attribute("fullCalcOnLoad").set_value("1");
|
||||
auto calc_pr_node = root_node.add_child("calcPr");
|
||||
calc_pr_node.add_attribute("calcId", "124519");
|
||||
calc_pr_node.add_attribute("calcMode", "auto");
|
||||
calc_pr_node.add_attribute("fullCalcOnLoad", "1");
|
||||
|
||||
std::stringstream ss;
|
||||
doc.save(ss);
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string workbook_serializer::write_workbook_rels(const workbook &wb)
|
||||
{
|
||||
return write_relationships(wb.get_relationships(), "xl/");
|
||||
return xml;
|
||||
}
|
||||
|
||||
std::string workbook_serializer::write_defined_names(const xlnt::workbook &wb)
|
||||
bool workbook_serializer::write_named_ranges(xlnt::xml_node &named_ranges_node)
|
||||
{
|
||||
pugi::xml_document doc;
|
||||
auto names = doc.root().append_child("names");
|
||||
|
||||
for(auto named_range : wb.get_named_ranges())
|
||||
for(auto &named_range : wb_.get_named_ranges())
|
||||
{
|
||||
names.append_child(named_range.get_name().c_str());
|
||||
named_ranges_node.add_child(named_range.get_name());
|
||||
}
|
||||
|
||||
std::ostringstream stream;
|
||||
doc.save(stream);
|
||||
|
||||
return stream.str();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
#include <sstream>
|
||||
|
||||
#include <xlnt/s11n/worksheet_serializer.hpp>
|
||||
#include <xlnt/cell/cell.hpp>
|
||||
#include <xlnt/cell/cell_reference.hpp>
|
||||
#include <xlnt/s11n/xml_document.hpp>
|
||||
#include <xlnt/s11n/xml_node.hpp>
|
||||
#include <xlnt/workbook/workbook.hpp>
|
||||
#include <xlnt/worksheet/range.hpp>
|
||||
#include <xlnt/worksheet/range_reference.hpp>
|
||||
|
||||
|
@ -18,10 +21,193 @@ bool is_integral(long double d)
|
|||
} // namepsace
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
bool worksheet_serializer::write_worksheet(const worksheet ws, const std::vector<std::string> &string_table, xml_document &xml)
|
||||
|
||||
bool worksheet_serializer::read_worksheet(const xml_document &xml, const std::vector<std::string> &string_table, const relationship &rel)
|
||||
{
|
||||
ws.get_cell("A1");
|
||||
auto &root_node = xml.root();
|
||||
|
||||
auto &dimension_node = root_node.get_child("dimension");
|
||||
std::string dimension = dimension_node.get_attribute("ref");
|
||||
auto full_range = xlnt::range_reference(dimension);
|
||||
auto sheet_data_node = root_node.get_child("sheetData");
|
||||
|
||||
if(root_node.has_child("mergeCells"))
|
||||
{
|
||||
auto merge_cells_node = root_node.get_child("mergeCells");
|
||||
auto count = std::stoull(merge_cells_node.get_attribute("count"));
|
||||
|
||||
for(auto merge_cell_node : merge_cells_node.get_children())
|
||||
{
|
||||
if(merge_cell_node.get_name() != "mergeCell")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
sheet_.merge_cells(merge_cell_node.get_attribute("ref"));
|
||||
count--;
|
||||
}
|
||||
|
||||
if(count != 0)
|
||||
{
|
||||
throw std::runtime_error("mismatch between count and actual number of merged cells");
|
||||
}
|
||||
}
|
||||
|
||||
for(auto row_node : sheet_data_node.get_children())
|
||||
{
|
||||
if(row_node.get_name() != "row")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto row_index = static_cast<row_t>(std::stoull(row_node.get_attribute("r")));
|
||||
|
||||
if(row_node.get_attribute("ht") != nullptr)
|
||||
{
|
||||
sheet_.get_row_properties(row_index).height = std::stold(row_node.get_attribute("ht"));
|
||||
}
|
||||
|
||||
std::string span_string = row_node.get_attribute("spans");
|
||||
auto colon_index = span_string.find(':');
|
||||
|
||||
column_t min_column = 0;
|
||||
column_t max_column = 0;
|
||||
|
||||
if(colon_index != std::string::npos)
|
||||
{
|
||||
min_column = static_cast<column_t>(std::stoll(span_string.substr(0, colon_index)));
|
||||
max_column = static_cast<column_t>(std::stoll(span_string.substr(colon_index + 1)));
|
||||
}
|
||||
else
|
||||
{
|
||||
min_column = static_cast<column_t>(full_range.get_top_left().get_column_index());
|
||||
max_column = static_cast<column_t>(full_range.get_bottom_right().get_column_index());
|
||||
}
|
||||
|
||||
for(column_t i = min_column; i <= max_column; i++)
|
||||
{
|
||||
std::string address = xlnt::cell_reference::column_string_from_index(i) + std::to_string(row_index);
|
||||
|
||||
xml_node cell_node;
|
||||
bool cell_found = false;
|
||||
|
||||
for(auto &check_cell_node : row_node.get_children())
|
||||
{
|
||||
if(check_cell_node.get_name() != "c")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(check_cell_node.has_attribute("r") && check_cell_node.get_attribute("r") == address)
|
||||
{
|
||||
cell_node = check_cell_node;
|
||||
cell_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(cell_found)
|
||||
{
|
||||
bool has_value = cell_node.has_child("v");
|
||||
std::string value_string = has_value ? cell_node.get_child("v").get_text() : "";
|
||||
|
||||
bool has_type = cell_node.get_attribute("t") != nullptr;
|
||||
std::string type = has_type ? cell_node.get_attribute("t") : "";
|
||||
|
||||
bool has_style = cell_node.get_attribute("s") != nullptr;
|
||||
int style_id = has_style ? std::stoull(cell_node.get_attribute("s")) : 0;
|
||||
|
||||
bool has_formula = cell_node.has_child("f");
|
||||
bool has_shared_formula = has_formula && cell_node.get_child("f").has_attribute("t") && cell_node.get_child("f").get_attribute("t") == "shared";
|
||||
|
||||
auto cell = sheet_.get_cell(address);
|
||||
|
||||
if(has_formula && !has_shared_formula && !sheet_.get_parent().get_data_only())
|
||||
{
|
||||
std::string formula = cell_node.get_child("f").get_text();
|
||||
cell.set_formula(formula);
|
||||
}
|
||||
|
||||
if(has_type && type == "inlineStr") // inline string
|
||||
{
|
||||
std::string inline_string = cell_node.get_child("is").get_child("t").get_text();
|
||||
cell.set_value(inline_string);
|
||||
}
|
||||
else if(has_type && type == "s" && !has_formula) // shared string
|
||||
{
|
||||
auto shared_string_index = std::stoull(value_string);
|
||||
auto shared_string = string_table.at(shared_string_index);
|
||||
cell.set_value(shared_string);
|
||||
}
|
||||
else if(has_type && type == "b") // boolean
|
||||
{
|
||||
cell.set_value(value_string != "0");
|
||||
}
|
||||
else if(has_type && type == "str")
|
||||
{
|
||||
cell.set_value(value_string);
|
||||
}
|
||||
else if(has_value && !value_string.empty())
|
||||
{
|
||||
if(!value_string.empty() && value_string[0] == '#')
|
||||
{
|
||||
cell.set_error(value_string);
|
||||
}
|
||||
else
|
||||
{
|
||||
cell.set_value(std::stold(value_string));
|
||||
}
|
||||
}
|
||||
|
||||
if(has_style)
|
||||
{
|
||||
cell.set_style_id(style_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto &cols_node = root_node.get_child("cols");
|
||||
|
||||
for(auto col_node : cols_node.get_children())
|
||||
{
|
||||
if(col_node.get_name() != "col")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto min = static_cast<column_t>(std::stoull(col_node.get_attribute("min")));
|
||||
auto max = static_cast<column_t>(std::stoull(col_node.get_attribute("max")));
|
||||
auto width = std::stold(col_node.get_attribute("width"));
|
||||
auto column_style = std::stoull(col_node.get_attribute("style"));
|
||||
bool custom = col_node.get_attribute("customWidth") == "1";
|
||||
|
||||
for(auto column = min; column <= max; column++)
|
||||
{
|
||||
if(!sheet_.has_column_properties(column))
|
||||
{
|
||||
sheet_.add_column_properties(column, column_properties());
|
||||
}
|
||||
|
||||
sheet_.get_column_properties(min).width = width;
|
||||
sheet_.get_column_properties(min).style = column_style;
|
||||
sheet_.get_column_properties(min).custom = custom;
|
||||
}
|
||||
}
|
||||
|
||||
if(root_node.has_child("autoFilter"))
|
||||
{
|
||||
auto &auto_filter_node = root_node.get_child("autoFilter");
|
||||
xlnt::range_reference ref(auto_filter_node.get_attribute("ref"));
|
||||
sheet_.auto_filter(ref);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool worksheet_serializer::write_worksheet(const std::vector<std::string> &string_table, xml_document &xml)
|
||||
{
|
||||
sheet_.get_cell("A1");
|
||||
|
||||
xml.add_namespace("", constants::Namespaces.at("spreadsheetml"));
|
||||
xml.add_namespace("r", constants::Namespaces.at("r"));
|
||||
|
@ -31,10 +217,10 @@ bool worksheet_serializer::write_worksheet(const worksheet ws, const std::vector
|
|||
|
||||
auto &sheet_pr_node = root_node.add_child("sheetPr");
|
||||
|
||||
if(!ws.get_page_setup().is_default())
|
||||
if(!sheet_.get_page_setup().is_default())
|
||||
{
|
||||
auto &page_set_up_pr_node = sheet_pr_node.add_child("pageSetUpPr");
|
||||
page_set_up_pr_node.add_attribute("fitToPage", ws.get_page_setup().fit_to_page() ? "1" : "0");
|
||||
page_set_up_pr_node.add_attribute("fitToPage", sheet_.get_page_setup().fit_to_page() ? "1" : "0");
|
||||
}
|
||||
|
||||
auto &outline_pr_node = sheet_pr_node.add_child("outlinePr");
|
||||
|
@ -43,7 +229,7 @@ bool worksheet_serializer::write_worksheet(const worksheet ws, const std::vector
|
|||
outline_pr_node.add_attribute("summaryRight", "1");
|
||||
|
||||
auto &dimension_node = root_node.add_child("dimension");
|
||||
dimension_node.add_attribute("ref", ws.calculate_dimension().to_string());
|
||||
dimension_node.add_attribute("ref", sheet_.calculate_dimension().to_string());
|
||||
|
||||
auto &sheet_views_node = root_node.add_child("sheetViews");
|
||||
auto &sheet_view_node = sheet_views_node.add_child("sheetView");
|
||||
|
@ -51,23 +237,23 @@ bool worksheet_serializer::write_worksheet(const worksheet ws, const std::vector
|
|||
|
||||
std::string active_pane = "bottomRight";
|
||||
|
||||
if(ws.has_frozen_panes())
|
||||
if(sheet_.has_frozen_panes())
|
||||
{
|
||||
auto pane_node = sheet_view_node.add_child("pane");
|
||||
|
||||
if(ws.get_frozen_panes().get_column_index() > 1)
|
||||
if(sheet_.get_frozen_panes().get_column_index() > 1)
|
||||
{
|
||||
pane_node.add_attribute("xSplit", std::to_string(ws.get_frozen_panes().get_column_index() - 1));
|
||||
pane_node.add_attribute("xSplit", std::to_string(sheet_.get_frozen_panes().get_column_index() - 1));
|
||||
active_pane = "topRight";
|
||||
}
|
||||
|
||||
if(ws.get_frozen_panes().get_row() > 1)
|
||||
if(sheet_.get_frozen_panes().get_row() > 1)
|
||||
{
|
||||
pane_node.add_attribute("ySplit", std::to_string(ws.get_frozen_panes().get_row() - 1));
|
||||
pane_node.add_attribute("ySplit", std::to_string(sheet_.get_frozen_panes().get_row() - 1));
|
||||
active_pane = "bottomLeft";
|
||||
}
|
||||
|
||||
if(ws.get_frozen_panes().get_row() > 1 && ws.get_frozen_panes().get_column_index() > 1)
|
||||
if(sheet_.get_frozen_panes().get_row() > 1 && sheet_.get_frozen_panes().get_column_index() > 1)
|
||||
{
|
||||
auto top_right_node = sheet_view_node.add_child("selection");
|
||||
top_right_node.add_attribute("pane", "topRight");
|
||||
|
@ -76,24 +262,24 @@ bool worksheet_serializer::write_worksheet(const worksheet ws, const std::vector
|
|||
active_pane = "bottomRight";
|
||||
}
|
||||
|
||||
pane_node.add_attribute("topLeftCell", ws.get_frozen_panes().to_string());
|
||||
pane_node.add_attribute("topLeftCell", sheet_.get_frozen_panes().to_string());
|
||||
pane_node.add_attribute("activePane", active_pane);
|
||||
pane_node.add_attribute("state", "frozen");
|
||||
}
|
||||
|
||||
auto selection_node = sheet_view_node.add_child("selection");
|
||||
|
||||
if(ws.has_frozen_panes())
|
||||
if(sheet_.has_frozen_panes())
|
||||
{
|
||||
if(ws.get_frozen_panes().get_row() > 1 && ws.get_frozen_panes().get_column_index() > 1)
|
||||
if(sheet_.get_frozen_panes().get_row() > 1 && sheet_.get_frozen_panes().get_column_index() > 1)
|
||||
{
|
||||
selection_node.add_attribute("pane", "bottomRight");
|
||||
}
|
||||
else if(ws.get_frozen_panes().get_row() > 1)
|
||||
else if(sheet_.get_frozen_panes().get_row() > 1)
|
||||
{
|
||||
selection_node.add_attribute("pane", "bottomLeft");
|
||||
}
|
||||
else if(ws.get_frozen_panes().get_column_index() > 1)
|
||||
else if(sheet_.get_frozen_panes().get_column_index() > 1)
|
||||
{
|
||||
selection_node.add_attribute("pane", "topRight");
|
||||
}
|
||||
|
@ -109,9 +295,9 @@ bool worksheet_serializer::write_worksheet(const worksheet ws, const std::vector
|
|||
|
||||
bool has_column_properties = false;
|
||||
|
||||
for(auto column = ws.get_lowest_column(); column <= ws.get_highest_column(); column++)
|
||||
for(auto column = sheet_.get_lowest_column(); column <= sheet_.get_highest_column(); column++)
|
||||
{
|
||||
if(ws.has_column_properties(column))
|
||||
if(sheet_.has_column_properties(column))
|
||||
{
|
||||
has_column_properties = true;
|
||||
break;
|
||||
|
@ -122,9 +308,9 @@ bool worksheet_serializer::write_worksheet(const worksheet ws, const std::vector
|
|||
{
|
||||
auto cols_node = root_node.add_child("cols");
|
||||
|
||||
for(auto column = ws.get_lowest_column(); column <= ws.get_highest_column(); column++)
|
||||
for(auto column = sheet_.get_lowest_column(); column <= sheet_.get_highest_column(); column++)
|
||||
{
|
||||
const auto &props = ws.get_column_properties(column);
|
||||
const auto &props = sheet_.get_column_properties(column);
|
||||
|
||||
auto col_node = cols_node.add_child("col");
|
||||
|
||||
|
@ -140,7 +326,7 @@ bool worksheet_serializer::write_worksheet(const worksheet ws, const std::vector
|
|||
|
||||
auto sheet_data_node = root_node.add_child("sheetData");
|
||||
|
||||
for(auto row : ws.rows())
|
||||
for(auto row : sheet_.rows())
|
||||
{
|
||||
row_t min = static_cast<row_t>(row.num_cells());
|
||||
row_t max = 0;
|
||||
|
@ -167,10 +353,10 @@ bool worksheet_serializer::write_worksheet(const worksheet ws, const std::vector
|
|||
row_node.add_attribute("r", std::to_string(row.front().get_row()));
|
||||
row_node.add_attribute("spans", (std::to_string(min) + ":" + std::to_string(max)));
|
||||
|
||||
if(ws.has_row_properties(row.front().get_row()))
|
||||
if(sheet_.has_row_properties(row.front().get_row()))
|
||||
{
|
||||
row_node.add_attribute("customHeight", "1");
|
||||
auto height = ws.get_row_properties(row.front().get_row()).height;
|
||||
auto height = sheet_.get_row_properties(row.front().get_row()).height;
|
||||
|
||||
if(height == std::floor(height))
|
||||
{
|
||||
|
@ -228,14 +414,14 @@ bool worksheet_serializer::write_worksheet(const worksheet ws, const std::vector
|
|||
{
|
||||
cell_node.add_attribute("t", "inlineStr");
|
||||
auto inline_string_node = cell_node.add_child("is");
|
||||
inline_string_node.add_child("t").text().set(cell.get_value<std::string>());
|
||||
inline_string_node.add_child("t").set_text(cell.get_value<std::string>());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cell_node.add_attribute("t", "s");
|
||||
auto value_node = cell_node.add_child("v");
|
||||
value_node.text().set(match_index);
|
||||
value_node.set_text(std::to_string(match_index));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -246,22 +432,23 @@ bool worksheet_serializer::write_worksheet(const worksheet ws, const std::vector
|
|||
{
|
||||
cell_node.add_attribute("t", "b");
|
||||
auto value_node = cell_node.add_child("v");
|
||||
value_node.text().set(cell.get_value<bool>() ? 1 : 0);
|
||||
value_node.set_text(cell.get_value<bool>() ? "1" : "0");
|
||||
}
|
||||
else if(cell.get_data_type() == cell::type::numeric)
|
||||
{
|
||||
if(cell.has_formula())
|
||||
{
|
||||
cell_node.add_child("f").text().set(cell.get_formula());
|
||||
cell_node.add_child("v").text().set(cell.to_string());
|
||||
cell_node.add_child("f").set_text(cell.get_formula());
|
||||
cell_node.add_child("v").set_text(cell.to_string());
|
||||
continue;
|
||||
}
|
||||
|
||||
cell_node.add_attribute("t", "n");
|
||||
auto value_node = cell_node.add_child("v");
|
||||
|
||||
if(is_integral(cell.get_value<long double>()))
|
||||
{
|
||||
value_node.text().set(cell.get_value<long long>());
|
||||
value_node.set_text(std::to_string(cell.get_value<long long>()));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -269,50 +456,49 @@ bool worksheet_serializer::write_worksheet(const worksheet ws, const std::vector
|
|||
ss.precision(20);
|
||||
ss << cell.get_value<long double>();
|
||||
ss.str();
|
||||
value_node.text().set(ss.str());
|
||||
value_node.set_text(ss.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(cell.has_formula())
|
||||
{
|
||||
cell_node.add_child("f").text().set(cell.get_formula());
|
||||
cell_node.add_child("f").set_text(cell.get_formula());
|
||||
cell_node.add_child("v");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
//if(cell.has_style())
|
||||
if(cell.has_style())
|
||||
{
|
||||
auto style_id = cell.get_style_id();
|
||||
cell_node.add_attribute("s", (int)style_id);
|
||||
cell_node.add_attribute("s", std::to_string(cell.get_style_id()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(ws.has_auto_filter())
|
||||
if(sheet_.has_auto_filter())
|
||||
{
|
||||
auto auto_filter_node = root_node.add_child("autoFilter");
|
||||
auto_filter_node.add_attribute("ref", ws.get_auto_filter().to_string());
|
||||
auto_filter_node.add_attribute("ref", sheet_.get_auto_filter().to_string());
|
||||
}
|
||||
|
||||
if(!ws.get_merged_ranges().empty())
|
||||
if(!sheet_.get_merged_ranges().empty())
|
||||
{
|
||||
auto merge_cells_node = root_node.add_child("mergeCells");
|
||||
merge_cells_node.add_attribute("count", (unsigned int)ws.get_merged_ranges().size());
|
||||
merge_cells_node.add_attribute("count", std::to_string(sheet_.get_merged_ranges().size()));
|
||||
|
||||
for(auto merged_range : ws.get_merged_ranges())
|
||||
for(auto merged_range : sheet_.get_merged_ranges())
|
||||
{
|
||||
auto merge_cell_node = merge_cells_node.add_child("mergeCell");
|
||||
merge_cell_node.add_attribute("ref", merged_range.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
if(!ws.get_relationships().empty())
|
||||
if(!sheet_.get_relationships().empty())
|
||||
{
|
||||
auto hyperlinks_node = root_node.add_child("hyperlinks");
|
||||
|
||||
for(auto relationship : ws.get_relationships())
|
||||
for(const auto &relationship : sheet_.get_relationships())
|
||||
{
|
||||
auto hyperlink_node = hyperlinks_node.add_child("hyperlink");
|
||||
hyperlink_node.add_attribute("display", relationship.get_target_uri());
|
||||
|
@ -321,48 +507,45 @@ bool worksheet_serializer::write_worksheet(const worksheet ws, const std::vector
|
|||
}
|
||||
}
|
||||
|
||||
if(!ws.get_page_setup().is_default())
|
||||
if(!sheet_.get_page_setup().is_default())
|
||||
{
|
||||
auto print_options_node = root_node.add_child("printOptions");
|
||||
print_options_node.add_attribute("horizontalCentered", ws.get_page_setup().get_horizontal_centered() ? 1 : 0);
|
||||
print_options_node.add_attribute("verticalCentered", ws.get_page_setup().get_vertical_centered() ? 1 : 0);
|
||||
print_options_node.add_attribute("horizontalCentered", sheet_.get_page_setup().get_horizontal_centered() ? "1" : "0");
|
||||
print_options_node.add_attribute("verticalCentered", sheet_.get_page_setup().get_vertical_centered() ? "1" : "0");
|
||||
}
|
||||
|
||||
auto page_margins_node = root_node.add_child("pageMargins");
|
||||
|
||||
page_margins_node.add_attribute("left", ws.get_page_margins().get_left());
|
||||
page_margins_node.add_attribute("right", ws.get_page_margins().get_right());
|
||||
page_margins_node.add_attribute("top", ws.get_page_margins().get_top());
|
||||
page_margins_node.add_attribute("bottom", ws.get_page_margins().get_bottom());
|
||||
page_margins_node.add_attribute("header", ws.get_page_margins().get_header());
|
||||
page_margins_node.add_attribute("footer", ws.get_page_margins().get_footer());
|
||||
page_margins_node.add_attribute("left", std::to_string(sheet_.get_page_margins().get_left()));
|
||||
page_margins_node.add_attribute("right", std::to_string(sheet_.get_page_margins().get_right()));
|
||||
page_margins_node.add_attribute("top", std::to_string(sheet_.get_page_margins().get_top()));
|
||||
page_margins_node.add_attribute("bottom", std::to_string(sheet_.get_page_margins().get_bottom()));
|
||||
page_margins_node.add_attribute("header", std::to_string(sheet_.get_page_margins().get_header()));
|
||||
page_margins_node.add_attribute("footer", std::to_string(sheet_.get_page_margins().get_footer()));
|
||||
|
||||
if(!ws.get_page_setup().is_default())
|
||||
if(!sheet_.get_page_setup().is_default())
|
||||
{
|
||||
auto page_setup_node = root_node.add_child("pageSetup");
|
||||
|
||||
std::string orientation_string = ws.get_page_setup().get_orientation() == page_setup::orientation::landscape ? "landscape" : "portrait";
|
||||
std::string orientation_string = sheet_.get_page_setup().get_orientation() == page_setup::orientation::landscape ? "landscape" : "portrait";
|
||||
page_setup_node.add_attribute("orientation", orientation_string);
|
||||
page_setup_node.add_attribute("paperSize", (int)ws.get_page_setup().get_paper_size());
|
||||
page_setup_node.add_attribute("fitToHeight", ws.get_page_setup().fit_to_height() ? 1 : 0);
|
||||
page_setup_node.add_attribute("fitToWidth", ws.get_page_setup().fit_to_width() ? 1 : 0);
|
||||
page_setup_node.add_attribute("paperSize", std::to_string(static_cast<int>(sheet_.get_page_setup().get_paper_size())));
|
||||
page_setup_node.add_attribute("fitToHeight", sheet_.get_page_setup().fit_to_height() ? "1" : "0");
|
||||
page_setup_node.add_attribute("fitToWidth", sheet_.get_page_setup().fit_to_width() ? "1" : "0");
|
||||
}
|
||||
|
||||
if(!ws.get_header_footer().is_default())
|
||||
if(!sheet_.get_header_footer().is_default())
|
||||
{
|
||||
auto header_footer_node = root_node.add_child("headerFooter");
|
||||
auto odd_header_node = header_footer_node.add_child("oddHeader");
|
||||
std::string header_text = "&L&\"Calibri,Regular\"&K000000Left Header Text&C&\"Arial,Regular\"&6&K445566Center Header Text&R&\"Arial,Bold\"&8&K112233Right Header Text";
|
||||
odd_header_node.text().set(header_text);
|
||||
odd_header_node.set_text(header_text);
|
||||
auto odd_footer_node = header_footer_node.add_child("oddFooter");
|
||||
std::string footer_text = "&L&\"Times New Roman,Regular\"&10&K445566Left Footer Text_x000D_And &D and &T&C&\"Times New Roman,Bold\"&12&K778899Center Footer Text &Z&F on &A&R&\"Times New Roman,Italic\"&14&KAABBCCRight Footer Text &P of &N";
|
||||
odd_footer_node.text().set(footer_text);
|
||||
odd_footer_node.set_text(footer_text);
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
doc.save(ss);
|
||||
|
||||
return ss.str();
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -68,13 +68,13 @@ void xml_node::add_attribute(const std::string &name, const std::string &value)
|
|||
|
||||
bool xml_node::has_attribute(const std::string &attribute_name) const
|
||||
{
|
||||
return std::find(attributes_.begin(), attributes_.end(),
|
||||
return std::find_if(attributes_.begin(), attributes_.end(),
|
||||
[&](const string_pair &p) { return p.first == attribute_name; }) != attributes_.end();
|
||||
}
|
||||
|
||||
std::string xml_node::get_attribute(const std::string &attribute_name) const
|
||||
{
|
||||
auto match = std::find(attributes_.begin(), attributes_.end(),
|
||||
auto match = std::find_if(attributes_.begin(), attributes_.end(),
|
||||
[&](const string_pair &p) { return p.first == attribute_name; });
|
||||
|
||||
if(match == attributes_.end())
|
||||
|
@ -87,16 +87,29 @@ std::string xml_node::get_attribute(const std::string &attribute_name) const
|
|||
|
||||
bool xml_node::has_child(const std::string &child_name) const
|
||||
{
|
||||
return std::find(children_.begin(), children_.end(),
|
||||
return std::find_if(children_.begin(), children_.end(),
|
||||
[&](const xml_node &n) { return n.get_name() == child_name; }) != children_.end();
|
||||
}
|
||||
|
||||
xml_node &xml_node::get_child(const std::string &child_name)
|
||||
{
|
||||
auto match = std::find_if(children_.begin(), children_.end(),
|
||||
[&](const xml_node &n) { return n.get_name() == child_name; });
|
||||
|
||||
if(match == children_.end())
|
||||
{
|
||||
throw std::runtime_error("child doesn't exist: " + child_name);
|
||||
}
|
||||
|
||||
return *match;
|
||||
}
|
||||
|
||||
const xml_node &xml_node::get_child(const std::string &child_name) const
|
||||
{
|
||||
auto match = std::find(children_.begin(), children_.end(),
|
||||
auto match = std::find_if(children_.begin(), children_.end(),
|
||||
[&](const xml_node &n) { return n.get_name() == child_name; });
|
||||
|
||||
if(match == attributes_.end())
|
||||
if(match == children_.end())
|
||||
{
|
||||
throw std::runtime_error("child doesn't exist: " + child_name);
|
||||
}
|
||||
|
|
|
@ -12,19 +12,21 @@
|
|||
#include <xlnt/common/relationship.hpp>
|
||||
#include <xlnt/common/zip_file.hpp>
|
||||
#include <xlnt/drawing/drawing.hpp>
|
||||
#include <xlnt/reader/excel_reader.hpp>
|
||||
#include <xlnt/s11n/excel_serializer.hpp>
|
||||
#include <xlnt/styles/alignment.hpp>
|
||||
#include <xlnt/styles/border.hpp>
|
||||
#include <xlnt/styles/fill.hpp>
|
||||
#include <xlnt/styles/font.hpp>
|
||||
#include <xlnt/styles/number_format.hpp>
|
||||
#include <xlnt/styles/protection.hpp>
|
||||
#include <xlnt/styles/style.hpp>
|
||||
#include <xlnt/workbook/document_properties.hpp>
|
||||
#include <xlnt/workbook/manifest.hpp>
|
||||
#include <xlnt/workbook/named_range.hpp>
|
||||
#include <xlnt/workbook/theme.hpp>
|
||||
#include <xlnt/workbook/workbook.hpp>
|
||||
#include <xlnt/worksheet/range.hpp>
|
||||
#include <xlnt/worksheet/worksheet.hpp>
|
||||
#include <xlnt/writer/excel_writer.hpp>
|
||||
|
||||
#include "detail/cell_impl.hpp"
|
||||
#include "detail/include_pugixml.hpp"
|
||||
|
@ -243,22 +245,25 @@ range workbook::get_named_range(const std::string &name)
|
|||
|
||||
bool workbook::load(std::istream &stream)
|
||||
{
|
||||
*this = excel_reader::load_workbook(stream);
|
||||
excel_serializer serializer_(*this);
|
||||
serializer_.load_stream_workbook(stream);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool workbook::load(const std::vector<unsigned char> &data)
|
||||
{
|
||||
*this = excel_reader::load_workbook(data);
|
||||
excel_serializer serializer_(*this);
|
||||
serializer_.load_virtual_workbook(data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool workbook::load(const std::string &filename)
|
||||
{
|
||||
*this = excel_reader::load_workbook(filename);
|
||||
|
||||
excel_serializer serializer_(*this);
|
||||
serializer_.load_workbook(filename);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -446,13 +451,18 @@ void workbook::clear()
|
|||
|
||||
bool workbook::save(std::vector<unsigned char> &data)
|
||||
{
|
||||
data = save_virtual_workbook(*this);
|
||||
excel_serializer serializer(*this);
|
||||
serializer.save_virtual_workbook(data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool workbook::save(const std::string &filename)
|
||||
{
|
||||
return save_workbook(*this, filename);
|
||||
excel_serializer serializer(*this);
|
||||
serializer.save_workbook(filename);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool workbook::operator==(std::nullptr_t) const
|
||||
|
@ -465,7 +475,7 @@ bool workbook::operator==(const workbook &rhs) const
|
|||
return d_.get() == rhs.d_.get();
|
||||
}
|
||||
|
||||
std::vector<relationship> xlnt::workbook::get_relationships() const
|
||||
const std::vector<relationship> &xlnt::workbook::get_relationships() const
|
||||
{
|
||||
return d_->relationships_;
|
||||
}
|
||||
|
@ -570,14 +580,14 @@ void workbook::set_code_name(const std::string &/*code_name*/)
|
|||
|
||||
}
|
||||
|
||||
bool workbook::has_loaded_theme()
|
||||
bool workbook::has_loaded_theme() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string workbook::get_loaded_theme()
|
||||
const theme &workbook::get_loaded_theme() const
|
||||
{
|
||||
return "";
|
||||
return d_->theme_;
|
||||
}
|
||||
|
||||
std::vector<named_range> workbook::get_named_ranges() const
|
||||
|
@ -847,4 +857,16 @@ const manifest &workbook::get_manifest() const
|
|||
return d_->manifest_;
|
||||
}
|
||||
|
||||
const std::vector<relationship> &workbook::get_root_relationships() const
|
||||
{
|
||||
if(d_->root_relationships_.empty())
|
||||
{
|
||||
d_->root_relationships_.push_back(relationship(relationship::type::extended_properties, "rId3", "docProps/app.xml"));
|
||||
d_->root_relationships_.push_back(relationship(relationship::type::core_properties, "rId2", "docProps/core.xml"));
|
||||
d_->root_relationships_.push_back(relationship(relationship::type::office_document, "rId1", "xl/workbook.xml"));
|
||||
}
|
||||
|
||||
return d_->root_relationships_;
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -330,7 +330,7 @@ const range worksheet::get_squared_range(column_t min_col, row_t min_row, column
|
|||
return get_range(reference);
|
||||
}
|
||||
|
||||
std::vector<relationship> worksheet::get_relationships()
|
||||
const std::vector<relationship> &worksheet::get_relationships() const
|
||||
{
|
||||
return d_->relationships_;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#include <xlnt/cell/cell.hpp>
|
||||
#include <xlnt/cell/cell_reference.hpp>
|
||||
#include <xlnt/common/zip_file.hpp>
|
||||
#include <xlnt/reader/worksheet_reader.hpp>
|
||||
#include <xlnt/styles/number_format.hpp>
|
||||
#include <xlnt/workbook/workbook.hpp>
|
||||
#include <xlnt/worksheet/range_reference.hpp>
|
||||
|
@ -14,158 +13,4 @@ namespace {
|
|||
} // namespace
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
void read_worksheet(worksheet ws, zip_file &archive, const relationship &rel, const std::vector<std::string> &string_table)
|
||||
{
|
||||
pugi::xml_document doc;
|
||||
doc.load(archive.read(rel.get_target_uri()).c_str());
|
||||
|
||||
auto root_node = doc.child("worksheet");
|
||||
|
||||
auto dimension_node = root_node.child("dimension");
|
||||
std::string dimension = dimension_node.attribute("ref").as_string();
|
||||
auto full_range = xlnt::range_reference(dimension);
|
||||
auto sheet_data_node = root_node.child("sheetData");
|
||||
auto merge_cells_node = root_node.child("mergeCells");
|
||||
|
||||
if(merge_cells_node != nullptr)
|
||||
{
|
||||
int count = merge_cells_node.attribute("count").as_int();
|
||||
|
||||
for(auto merge_cell_node : merge_cells_node.children("mergeCell"))
|
||||
{
|
||||
ws.merge_cells(merge_cell_node.attribute("ref").as_string());
|
||||
count--;
|
||||
}
|
||||
|
||||
if(count != 0)
|
||||
{
|
||||
throw std::runtime_error("mismatch between count and actual number of merged cells");
|
||||
}
|
||||
}
|
||||
|
||||
for(auto row_node : sheet_data_node.children("row"))
|
||||
{
|
||||
auto row_index = static_cast<row_t>(row_node.attribute("r").as_uint());
|
||||
|
||||
if(row_node.attribute("ht") != nullptr)
|
||||
{
|
||||
ws.get_row_properties(row_index).height = row_node.attribute("ht").as_double();
|
||||
}
|
||||
|
||||
std::string span_string = row_node.attribute("spans").as_string();
|
||||
auto colon_index = span_string.find(':');
|
||||
|
||||
column_t min_column = 0;
|
||||
column_t max_column = 0;
|
||||
|
||||
if(colon_index != std::string::npos)
|
||||
{
|
||||
min_column = static_cast<column_t>(std::stoll(span_string.substr(0, colon_index)));
|
||||
max_column = static_cast<column_t>(std::stoll(span_string.substr(colon_index + 1)));
|
||||
}
|
||||
else
|
||||
{
|
||||
min_column = static_cast<column_t>(full_range.get_top_left().get_column_index());
|
||||
max_column = static_cast<column_t>(full_range.get_bottom_right().get_column_index());
|
||||
}
|
||||
|
||||
for(column_t i = min_column; i <= max_column; i++)
|
||||
{
|
||||
std::string address = xlnt::cell_reference::column_string_from_index(i) + std::to_string(row_index);
|
||||
auto cell_node = row_node.find_child_by_attribute("c", "r", address.c_str());
|
||||
|
||||
if(cell_node != nullptr)
|
||||
{
|
||||
bool has_value = cell_node.child("v") != nullptr;
|
||||
std::string value_string = has_value ? cell_node.child("v").text().as_string() : "";
|
||||
|
||||
bool has_type = cell_node.attribute("t") != nullptr;
|
||||
std::string type = has_type ? cell_node.attribute("t").as_string() : "";
|
||||
|
||||
bool has_style = cell_node.attribute("s") != nullptr;
|
||||
int style_id = has_style ? cell_node.attribute("s").as_int() : 0;
|
||||
|
||||
bool has_formula = cell_node.child("f") != nullptr;
|
||||
bool has_shared_formula = has_formula && cell_node.child("f").attribute("t") != nullptr && std::string(cell_node.child("f").attribute("t").as_string()) == "shared";
|
||||
|
||||
auto cell = ws.get_cell(address);
|
||||
|
||||
if(has_formula && !has_shared_formula && !ws.get_parent().get_data_only())
|
||||
{
|
||||
std::string formula = cell_node.child("f").text().as_string();
|
||||
cell.set_formula(formula);
|
||||
}
|
||||
|
||||
if(has_type && type == "inlineStr") // inline string
|
||||
{
|
||||
std::string inline_string = cell_node.child("is").child("t").text().as_string();
|
||||
cell.set_value(inline_string);
|
||||
}
|
||||
else if(has_type && type == "s" && !has_formula) // shared string
|
||||
{
|
||||
auto shared_string_index = std::stoull(value_string);
|
||||
auto shared_string = string_table.at(shared_string_index);
|
||||
cell.set_value(shared_string);
|
||||
}
|
||||
else if(has_type && type == "b") // boolean
|
||||
{
|
||||
cell.set_value(value_string != "0");
|
||||
}
|
||||
else if(has_type && type == "str")
|
||||
{
|
||||
cell.set_value(value_string);
|
||||
}
|
||||
else if(has_value && !value_string.empty())
|
||||
{
|
||||
if(!value_string.empty() && value_string[0] == '#')
|
||||
{
|
||||
cell.set_error(value_string);
|
||||
}
|
||||
else
|
||||
{
|
||||
cell.set_value(std::stold(value_string));
|
||||
}
|
||||
}
|
||||
|
||||
if(has_style)
|
||||
{
|
||||
cell.set_style_id(style_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto cols_node = root_node.child("cols");
|
||||
|
||||
for(auto col_node : cols_node.children("col"))
|
||||
{
|
||||
column_t min = col_node.attribute("min").as_uint();
|
||||
column_t max = col_node.attribute("max").as_uint();
|
||||
double width = col_node.attribute("width").as_double();
|
||||
std::size_t column_style = col_node.attribute("style").as_ullong();
|
||||
bool custom = col_node.attribute("customWidth").as_bool();
|
||||
|
||||
for(auto column = min; column <= max; column++)
|
||||
{
|
||||
if(!ws.has_column_properties(column))
|
||||
{
|
||||
ws.add_column_properties(column, column_properties());
|
||||
}
|
||||
|
||||
ws.get_column_properties(min).width = width;
|
||||
ws.get_column_properties(min).style = column_style;
|
||||
ws.get_column_properties(min).custom = custom;
|
||||
}
|
||||
}
|
||||
|
||||
auto auto_filter_node = root_node.child("autoFilter");
|
||||
|
||||
if(auto_filter_node != nullptr)
|
||||
{
|
||||
xlnt::range_reference ref(auto_filter_node.attribute("ref").as_string());
|
||||
ws.auto_filter(ref);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -19,11 +19,6 @@
|
|||
#include <xlnt/worksheet/worksheet.hpp>
|
||||
#include <xlnt/workbook/workbook.hpp>
|
||||
|
||||
#include <xlnt/writer/excel_writer.hpp>
|
||||
#include <xlnt/reader/excel_reader.hpp>
|
||||
|
||||
#include <xlnt/common/xml_tree.hpp>
|
||||
|
||||
class test_cell : public CxxTest::TestSuite
|
||||
{
|
||||
private:
|
||||
|
@ -37,7 +32,8 @@ public:
|
|||
|
||||
void test_debug()
|
||||
{
|
||||
auto wb = xlnt::excel_reader::load_workbook("/Users/thomas/Development/xlnt/samples/formatting.xlsx");
|
||||
xlnt::workbook wb;
|
||||
wb.load("/Users/thomas/Development/xlnt/samples/formatting.xlsx");
|
||||
wb.save("/Users/thomas/Development/xlnt/samples/formatting-rt.xlsx");
|
||||
wb.save("/Users/thomas/Development/xlnt/samples/formatting-rt.zip");
|
||||
}
|
||||
|
@ -94,7 +90,6 @@ public:
|
|||
TS_ASSERT(cell.get_row() == 1);
|
||||
TS_ASSERT(cell.get_reference() == "A1");
|
||||
TS_ASSERT(!cell.has_value());
|
||||
TS_ASSERT(cell.get_xf_index() == 0);
|
||||
TS_ASSERT(!cell.has_comment());
|
||||
}
|
||||
|
||||
|
@ -179,7 +174,7 @@ public:
|
|||
auto ws = wb_guess_types.create_sheet();
|
||||
auto cell = ws.get_cell(xlnt::cell_reference(1, 1));
|
||||
|
||||
for(auto error_code : xlnt::cell::ErrorCodes)
|
||||
for(auto error_code : xlnt::cell::error_codes())
|
||||
{
|
||||
cell.set_value(error_code.first);
|
||||
TS_ASSERT(cell.get_data_type() == xlnt::cell::type::error);
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
#include <iostream>
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include <xlnt/reader/workbook_reader.hpp>
|
||||
#include <xlnt/writer/workbook_writer.hpp>
|
||||
#include <xlnt/s11n/workbook_serializer.hpp>
|
||||
|
||||
#include "helpers/path_helper.hpp"
|
||||
#include "helpers/helper.hpp"
|
||||
|
@ -16,7 +15,9 @@ public:
|
|||
{
|
||||
xlnt::zip_file archive(PathHelper::GetDataDirectory() + "/genuine/empty.xlsx");
|
||||
auto content = archive.read("docProps/core.xml");
|
||||
auto prop = xlnt::read_properties_core(content);
|
||||
xlnt::workbook wb;
|
||||
xlnt::workbook_serializer serializer(wb);
|
||||
auto prop = serializer.read_properties_core(content);
|
||||
TS_ASSERT_EQUALS(prop.creator, "*.*");
|
||||
TS_ASSERT_EQUALS(prop.last_modified_by, "Charlie Clark");
|
||||
TS_ASSERT_EQUALS(prop.created, xlnt::datetime(2010, 4, 9, 20, 43, 12));
|
||||
|
|
|
@ -5,10 +5,6 @@
|
|||
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include <xlnt/reader/excel_reader.hpp>
|
||||
#include <xlnt/reader/workbook_reader.hpp>
|
||||
#include <xlnt/reader/worksheet_reader.hpp>
|
||||
|
||||
#include "helpers/path_helper.hpp"
|
||||
|
||||
class test_read : public CxxTest::TestSuite
|
||||
|
|
Loading…
Reference in New Issue
Block a user