xlnt/source/s11n/excel_serializer.cpp

232 lines
7.6 KiB
C++
Raw Normal View History

2015-10-30 01:46:56 +08:00
#include <xlnt/s11n/excel_serializer.hpp>
2015-10-30 07:37:07 +08:00
#include <xlnt/common/exceptions.hpp>
2015-10-30 01:46:56 +08:00
#include <xlnt/s11n/manifest_serializer.hpp>
2015-10-30 07:37:07 +08:00
#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>
2015-10-30 01:46:56 +08:00
#include <xlnt/workbook/manifest.hpp>
2015-10-21 11:30:10 +08:00
#include <xlnt/workbook/workbook.hpp>
2015-10-30 07:37:07 +08:00
#include <xlnt/worksheet/worksheet.hpp>
#include <detail/constants.hpp>
2015-10-21 11:30:10 +08:00
namespace {
std::string::size_type find_string_in_string(const std::string &string, const std::string &substring)
{
std::string::size_type possible_match_index = string.find(substring.at(0));
while(possible_match_index != std::string::npos)
{
if(string.substr(possible_match_index, substring.size()) == substring)
{
return possible_match_index;
}
possible_match_index = string.find(substring.at(0), possible_match_index + 1);
}
return possible_match_index;
}
2015-10-30 07:37:07 +08:00
bool load_workbook(xlnt::zip_file &archive, bool guess_types, bool data_only, xlnt::workbook &wb)
2015-10-24 02:42:36 +08:00
{
wb.set_guess_types(guess_types);
wb.set_data_only(data_only);
2015-10-30 07:37:07 +08:00
xlnt::manifest_serializer ms(wb.get_manifest());
ms.read_manifest(xlnt::xml_serializer::deserialize(archive.read(xlnt::constants::ArcContentTypes)));
2015-10-24 02:42:36 +08:00
2015-10-30 07:37:07 +08:00
if(xlnt::workbook_serializer::determine_document_type(wb.get_manifest()) != "excel")
2015-10-24 02:42:36 +08:00
{
throw xlnt::invalid_file_exception("");
}
wb.clear();
2015-10-30 07:37:07 +08:00
std::vector<xlnt::relationship> workbook_relationships;
xlnt::relationship_serializer::read_relationships(xlnt::xml_serializer::deserialize(archive.read("xl/_rels/workbook.xml.rels")), "", workbook_relationships);
2015-10-24 02:42:36 +08:00
for(auto relationship : workbook_relationships)
{
wb.create_relationship(relationship.get_id(), relationship.get_target_uri(), relationship.get_type());
}
2015-10-30 07:37:07 +08:00
auto xml = xlnt::xml_serializer::deserialize(archive.read(xlnt::constants::ArcWorkbook));
2015-10-24 02:42:36 +08:00
2015-10-30 07:37:07 +08:00
auto &root_node = xml.root();
2015-10-24 02:42:36 +08:00
2015-10-30 07:37:07 +08:00
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;
2015-10-24 02:42:36 +08:00
2015-10-30 07:37:07 +08:00
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);
2015-10-24 02:42:36 +08:00
2015-10-30 07:37:07 +08:00
xlnt::style_serializer style_reader_(wb);
style_reader_.read_stylesheet(xlnt::xml_serializer::deserialize(archive.read(xlnt::constants::ArcStyles)));
2015-10-29 03:08:54 +08:00
2015-10-30 07:37:07 +08:00
auto &sheets_node = root_node.get_child("sheets");
2015-10-24 02:42:36 +08:00
2015-10-30 07:37:07 +08:00
for(auto sheet_node : sheets_node.get_children())
2015-10-24 02:42:36 +08:00
{
2015-10-30 07:37:07 +08:00
auto rel = wb.get_relationship(sheet_node.get_attribute("r:id"));
auto ws = wb.create_sheet(sheet_node.get_attribute("name"), rel);
2015-10-24 02:42:36 +08:00
2015-10-30 07:37:07 +08:00
xlnt::worksheet_serializer worksheet_serializer(ws);
worksheet_serializer.read_worksheet(xlnt::xml_serializer::deserialize(archive.read(rel.get_target_uri())), shared_strings, rel);
2015-10-24 02:42:36 +08:00
}
2015-10-30 07:37:07 +08:00
return true;
2015-10-24 02:42:36 +08:00
}
2015-10-21 11:30:10 +08:00
} // namespace
namespace xlnt {
2015-10-30 07:37:07 +08:00
const std::string excel_serializer::central_directory_signature()
2015-10-21 11:30:10 +08:00
{
return "\x50\x4b\x05\x06";
}
2015-10-30 07:37:07 +08:00
std::string excel_serializer::repair_central_directory(const std::string &original)
2015-10-21 11:30:10 +08:00
{
2015-10-30 07:37:07 +08:00
auto pos = find_string_in_string(original, central_directory_signature());
2015-10-21 11:30:10 +08:00
if(pos != std::string::npos)
{
return original.substr(0, pos + 22);
}
return original;
}
2015-10-30 07:37:07 +08:00
bool excel_serializer::load_stream_workbook(std::istream &stream, bool guess_types, bool data_only)
2015-10-21 11:30:10 +08:00
{
2015-10-24 02:42:36 +08:00
std::vector<std::uint8_t> bytes((std::istream_iterator<char>(stream)),
std::istream_iterator<char>());
2015-10-30 07:37:07 +08:00
return load_virtual_workbook(bytes, guess_types, data_only);
2015-10-21 11:30:10 +08:00
}
2015-10-30 07:37:07 +08:00
bool excel_serializer::load_workbook(const std::string &filename, bool guess_types, bool data_only)
2015-10-21 11:30:10 +08:00
{
2015-10-24 02:42:36 +08:00
try
{
2015-10-30 07:37:07 +08:00
archive_.load(filename);
2015-10-24 02:42:36 +08:00
}
catch(std::runtime_error)
{
throw invalid_file_exception(filename);
}
2015-10-30 07:37:07 +08:00
return ::load_workbook(archive_, guess_types, data_only, wb_);
2015-10-24 02:42:36 +08:00
}
2015-10-21 11:30:10 +08:00
2015-10-30 07:37:07 +08:00
bool excel_serializer::load_virtual_workbook(const std::vector<std::uint8_t> &bytes, bool guess_types, bool data_only)
2015-10-24 02:42:36 +08:00
{
2015-10-30 07:37:07 +08:00
archive_.load(bytes);
2015-10-21 11:30:10 +08:00
2015-10-30 07:37:07 +08:00
return ::load_workbook(archive_, guess_types, data_only, wb_);
2015-10-21 11:30:10 +08:00
}
2015-10-30 07:37:07 +08:00
excel_serializer::excel_serializer(workbook &wb) : wb_(wb)
2015-10-30 01:46:56 +08:00
{
}
2015-10-30 07:37:07 +08:00
void excel_serializer::write_data(bool as_template)
2015-10-30 01:46:56 +08:00
{
2015-10-30 07:37:07 +08:00
relationship_serializer relationship_serializer_;
2015-10-30 01:46:56 +08:00
2015-10-30 07:37:07 +08:00
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));
2015-10-30 01:46:56 +08:00
2015-10-30 07:37:07 +08:00
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));
2015-10-30 01:46:56 +08:00
2015-10-30 07:37:07 +08:00
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()));
2015-10-30 01:46:56 +08:00
2015-10-30 07:37:07 +08:00
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));
2015-10-30 01:46:56 +08:00
2015-10-30 07:37:07 +08:00
archive_.writestr(constants::ArcWorkbook, xml_serializer::serialize(workbook_serializer_.write_workbook()));
2015-10-30 01:46:56 +08:00
2015-10-30 07:37:07 +08:00
style_serializer style_serializer_(wb_);
xml_document style_xml;
style_serializer_.write_stylesheet(style_xml);
archive_.writestr(constants::ArcStyles, xml_serializer::serialize(style_xml));
2015-10-30 01:46:56 +08:00
2015-10-30 07:37:07 +08:00
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));
2015-10-30 01:46:56 +08:00
2015-10-30 07:37:07 +08:00
write_worksheets();
2015-10-30 01:46:56 +08:00
}
2015-10-30 07:37:07 +08:00
void excel_serializer::write_worksheets()
2015-10-30 01:46:56 +08:00
{
std::size_t index = 0;
for(auto ws : wb_)
{
for(auto relationship : wb_.get_relationships())
{
if(relationship.get_type() == relationship::type::worksheet &&
workbook::index_from_ws_filename(relationship.get_target_uri()) == index)
{
2015-10-30 07:37:07 +08:00
worksheet_serializer serializer_(ws);
xml_document xml;
serializer_.write_worksheet(shared_strings_, xml);
archive_.writestr(relationship.get_target_uri(), xml_serializer::serialize(xml));
2015-10-30 01:46:56 +08:00
break;
}
}
index++;
}
}
2015-10-30 07:37:07 +08:00
void excel_serializer::write_external_links()
{
}
bool excel_serializer::save_stream_workbook(std::ostream &stream, bool as_template)
2015-10-30 01:46:56 +08:00
{
2015-10-30 07:37:07 +08:00
write_data(as_template);
archive_.save(stream);
2015-10-30 01:46:56 +08:00
2015-10-30 07:37:07 +08:00
return true;
2015-10-30 01:46:56 +08:00
}
2015-10-30 07:37:07 +08:00
bool excel_serializer::save_workbook(const std::string &filename, bool as_template)
2015-10-30 01:46:56 +08:00
{
2015-10-30 07:37:07 +08:00
write_data(as_template);
archive_.save(filename);
2015-10-30 01:46:56 +08:00
return true;
}
2015-10-30 07:37:07 +08:00
bool excel_serializer::save_virtual_workbook(std::vector<std::uint8_t> &bytes, bool as_template)
2015-10-30 01:46:56 +08:00
{
2015-10-30 07:37:07 +08:00
write_data(as_template);
archive_.save(bytes);
2015-10-30 01:46:56 +08:00
2015-10-30 07:37:07 +08:00
return true;
2015-10-30 01:46:56 +08:00
}
2015-10-21 11:30:10 +08:00
} // namespace xlnt