2016-10-25 10:09:15 +08:00
|
|
|
// Copyright (c) 2014-2016 Thomas Fussell
|
|
|
|
//
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
|
|
// in the Software without restriction, including without limitation the rights
|
|
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
|
|
// furnished to do so, subject to the following conditions:
|
|
|
|
//
|
|
|
|
// The above copyright notice and this permission notice shall be included in
|
|
|
|
// all copies or substantial portions of the Software.
|
|
|
|
//
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, WRISING FROM,
|
|
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
// THE SOFTWARE
|
|
|
|
//
|
|
|
|
// @license: http://www.opensource.org/licenses/mit-license.php
|
|
|
|
// @author: see AUTHORS file
|
2016-10-31 03:48:40 +08:00
|
|
|
|
2016-08-05 13:52:05 +08:00
|
|
|
#include <cctype>
|
2016-10-29 22:23:04 +08:00
|
|
|
#include <numeric> // for std::accumulate
|
2016-08-05 13:52:05 +08:00
|
|
|
|
|
|
|
#include <detail/constants.hpp>
|
2016-09-18 23:32:59 +08:00
|
|
|
#include <detail/custom_value_traits.hpp>
|
2016-08-05 13:52:05 +08:00
|
|
|
#include <detail/workbook_impl.hpp>
|
2016-11-20 06:19:38 +08:00
|
|
|
#include <detail/xlsx_consumer.hpp>
|
2016-10-31 03:48:40 +08:00
|
|
|
#include <detail/zip.hpp>
|
2016-08-18 19:34:18 +08:00
|
|
|
#include <xlnt/cell/cell.hpp>
|
2016-08-05 13:52:05 +08:00
|
|
|
#include <xlnt/packaging/manifest.hpp>
|
2016-11-20 06:19:38 +08:00
|
|
|
#include <xlnt/utils/path.hpp>
|
2016-08-05 13:52:05 +08:00
|
|
|
#include <xlnt/workbook/const_worksheet_iterator.hpp>
|
|
|
|
#include <xlnt/workbook/workbook.hpp>
|
|
|
|
#include <xlnt/worksheet/worksheet.hpp>
|
|
|
|
|
2016-11-20 05:42:16 +08:00
|
|
|
namespace std {
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct hash<xml::qname>
|
|
|
|
{
|
2016-11-20 06:19:38 +08:00
|
|
|
std::size_t operator()(const xml::qname &k) const
|
2016-11-20 05:42:16 +08:00
|
|
|
{
|
|
|
|
static std::hash<std::string> hasher;
|
|
|
|
return hasher(k.string());
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace std
|
|
|
|
|
2016-08-05 13:52:05 +08:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
bool is_true(const std::string &bool_string)
|
|
|
|
{
|
2016-11-20 06:19:38 +08:00
|
|
|
return bool_string == "1" || bool_string == "true";
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
std::size_t string_to_size_t(const std::string &s)
|
|
|
|
{
|
|
|
|
#if ULLONG_MAX == SIZE_MAX
|
2016-11-20 06:19:38 +08:00
|
|
|
return std::stoull(s);
|
2016-08-05 13:52:05 +08:00
|
|
|
#else
|
2016-11-20 06:19:38 +08:00
|
|
|
return std::stoul(s);
|
2016-08-05 13:52:05 +08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
xlnt::datetime w3cdtf_to_datetime(const std::string &string)
|
|
|
|
{
|
2016-11-20 06:19:38 +08:00
|
|
|
xlnt::datetime result(1900, 1, 1);
|
|
|
|
auto separator_index = string.find('-');
|
|
|
|
result.year = std::stoi(string.substr(0, separator_index));
|
|
|
|
result.month = std::stoi(string.substr(separator_index + 1, string.find('-', separator_index + 1)));
|
|
|
|
separator_index = string.find('-', separator_index + 1);
|
|
|
|
result.day = std::stoi(string.substr(separator_index + 1, string.find('T', separator_index + 1)));
|
|
|
|
separator_index = string.find('T', separator_index + 1);
|
|
|
|
result.hour = std::stoi(string.substr(separator_index + 1, string.find(':', separator_index + 1)));
|
|
|
|
separator_index = string.find(':', separator_index + 1);
|
|
|
|
result.minute = std::stoi(string.substr(separator_index + 1, string.find(':', separator_index + 1)));
|
|
|
|
separator_index = string.find(':', separator_index + 1);
|
|
|
|
result.second = std::stoi(string.substr(separator_index + 1, string.find('Z', separator_index + 1)));
|
|
|
|
return result;
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-09-17 10:59:13 +08:00
|
|
|
xlnt::color read_color(xml::parser &parser)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-11-20 06:19:38 +08:00
|
|
|
xlnt::color result;
|
|
|
|
|
|
|
|
if (parser.attribute_present("auto"))
|
|
|
|
{
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parser.attribute_present("rgb"))
|
|
|
|
{
|
|
|
|
result = xlnt::rgb_color(parser.attribute("rgb"));
|
|
|
|
}
|
|
|
|
else if (parser.attribute_present("theme"))
|
|
|
|
{
|
|
|
|
result = xlnt::theme_color(string_to_size_t(parser.attribute("theme")));
|
|
|
|
}
|
|
|
|
else if (parser.attribute_present("indexed"))
|
|
|
|
{
|
|
|
|
result = xlnt::indexed_color(string_to_size_t(parser.attribute("indexed")));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parser.attribute_present("tint"))
|
|
|
|
{
|
|
|
|
result.set_tint(parser.attribute("tint", 0.0));
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-11-01 08:48:43 +08:00
|
|
|
std::vector<xlnt::relationship> read_relationships(const xlnt::path &part, xlnt::detail::ZipFileReader &archive)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-11-10 08:52:18 +08:00
|
|
|
std::vector<xlnt::relationship> relationships;
|
|
|
|
if (!archive.has_file(part.string())) return relationships;
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-11-01 08:48:43 +08:00
|
|
|
auto &rels_stream = archive.open(part.string());
|
|
|
|
xml::parser parser(rels_stream, part.string());
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-08-12 12:22:14 +08:00
|
|
|
xlnt::uri source(part.string());
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-11-10 08:52:18 +08:00
|
|
|
static const auto &xmlns = xlnt::constants::get_namespace("relationships");
|
2016-09-17 10:59:13 +08:00
|
|
|
parser.next_expect(xml::parser::event_type::start_element, xmlns, "Relationships");
|
|
|
|
parser.content(xml::content::complex);
|
|
|
|
|
|
|
|
while (true)
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
2016-09-17 10:59:13 +08:00
|
|
|
if (parser.peek() == xml::parser::event_type::end_element) break;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-17 10:59:13 +08:00
|
|
|
parser.next_expect(xml::parser::event_type::start_element, xmlns, "Relationship");
|
2016-11-20 06:19:38 +08:00
|
|
|
relationships.emplace_back(parser.attribute("Id"),
|
2016-09-22 07:04:16 +08:00
|
|
|
parser.attribute<xlnt::relationship::type>("Type"), source,
|
2016-11-20 06:19:38 +08:00
|
|
|
xlnt::uri(parser.attribute("Target")),
|
|
|
|
xlnt::target_mode::internal);
|
|
|
|
parser.next_expect(xml::parser::event_type::end_element, xmlns, "Relationship");
|
|
|
|
}
|
|
|
|
|
2016-09-17 10:59:13 +08:00
|
|
|
parser.next_expect(xml::parser::event_type::end_element, xmlns, "Relationships");
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
return relationships;
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void check_document_type(const std::string &document_content_type)
|
|
|
|
{
|
2016-11-20 06:19:38 +08:00
|
|
|
if (document_content_type != "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml" &&
|
|
|
|
document_content_type != "application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml ")
|
|
|
|
{
|
|
|
|
throw xlnt::invalid_file(document_content_type);
|
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
namespace xlnt {
|
|
|
|
namespace detail {
|
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
xlsx_consumer::xlsx_consumer(workbook &target)
|
|
|
|
: target_(target),
|
|
|
|
parser_(nullptr)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void xlsx_consumer::read(std::istream &source)
|
|
|
|
{
|
2016-11-20 06:19:38 +08:00
|
|
|
archive_.reset(new ZipFileReader(source));
|
|
|
|
populate_workbook();
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
xml::parser &xlsx_consumer::parser()
|
|
|
|
{
|
2016-11-20 06:19:38 +08:00
|
|
|
return *parser_;
|
2016-10-12 11:16:14 +08:00
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-11-20 05:42:16 +08:00
|
|
|
void xlsx_consumer::read_part(const std::vector<relationship> &rel_chain)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-11-20 06:19:38 +08:00
|
|
|
// ignore namespace declarations except in parts of these types
|
2016-11-20 05:42:16 +08:00
|
|
|
const auto using_namespaces = std::vector<relationship::type>
|
|
|
|
{
|
|
|
|
relationship::type::office_document,
|
|
|
|
relationship::type::stylesheet,
|
|
|
|
relationship::type::chartsheet,
|
2016-11-20 06:19:38 +08:00
|
|
|
relationship::type::dialogsheet,
|
|
|
|
relationship::type::worksheet
|
2016-11-20 05:42:16 +08:00
|
|
|
};
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-11-20 05:42:16 +08:00
|
|
|
auto receive = xml::parser::receive_default;
|
|
|
|
auto receive_namespaces = std::find(using_namespaces.begin(), using_namespaces.end(),
|
|
|
|
rel_chain.back().get_type()) != using_namespaces.end();
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-11-20 05:42:16 +08:00
|
|
|
if (receive_namespaces)
|
|
|
|
{
|
|
|
|
receive |= xml::parser::receive_namespace_decls;
|
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-11-20 05:42:16 +08:00
|
|
|
const auto &manifest = target_.get_manifest();
|
|
|
|
auto part_path = manifest.canonicalize(rel_chain);
|
|
|
|
auto &stream = archive_->open(part_path.string());
|
|
|
|
xml::parser parser(stream, part_path.string(), receive);
|
|
|
|
parser_ = &parser;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-11-20 05:42:16 +08:00
|
|
|
switch (rel_chain.back().get_type())
|
|
|
|
{
|
2016-11-20 06:19:38 +08:00
|
|
|
case relationship::type::core_properties:
|
|
|
|
read_core_properties();
|
|
|
|
break;
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
case relationship::type::extended_properties:
|
|
|
|
read_extended_properties();
|
|
|
|
break;
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
case relationship::type::custom_properties:
|
|
|
|
read_custom_property();
|
|
|
|
break;
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
case relationship::type::office_document:
|
|
|
|
read_workbook();
|
|
|
|
break;
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
case relationship::type::connections:
|
|
|
|
read_connections();
|
|
|
|
break;
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
case relationship::type::custom_xml_mappings:
|
|
|
|
read_custom_xml_mappings();
|
|
|
|
break;
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
case relationship::type::external_workbook_references:
|
|
|
|
read_external_workbook_references();
|
|
|
|
break;
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
case relationship::type::metadata:
|
|
|
|
read_metadata();
|
|
|
|
break;
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
case relationship::type::pivot_table:
|
|
|
|
read_pivot_table();
|
|
|
|
break;
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
case relationship::type::shared_workbook_revision_headers:
|
|
|
|
read_shared_workbook_revision_headers();
|
|
|
|
break;
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
case relationship::type::volatile_dependencies:
|
|
|
|
read_volatile_dependencies();
|
|
|
|
break;
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
case relationship::type::shared_string_table:
|
|
|
|
read_shared_string_table();
|
|
|
|
break;
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
case relationship::type::stylesheet:
|
|
|
|
read_stylesheet();
|
|
|
|
break;
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
case relationship::type::theme:
|
|
|
|
read_theme();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case relationship::type::chartsheet:
|
|
|
|
read_chartsheet(rel_chain.back().get_id());
|
|
|
|
break;
|
|
|
|
|
|
|
|
case relationship::type::dialogsheet:
|
|
|
|
read_dialogsheet(rel_chain.back().get_id());
|
|
|
|
break;
|
|
|
|
|
|
|
|
case relationship::type::worksheet:
|
|
|
|
read_worksheet(rel_chain.back().get_id());
|
|
|
|
break;
|
|
|
|
|
|
|
|
case relationship::type::thumbnail:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case relationship::type::calculation_chain:
|
|
|
|
read_calculation_chain();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case relationship::type::hyperlink:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case relationship::type::comments:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case relationship::type::vml_drawing:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case relationship::type::unknown:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case relationship::type::printer_settings:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case relationship::type::custom_property:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case relationship::type::drawings:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case relationship::type::pivot_table_cache_definition:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case relationship::type::pivot_table_cache_records:
|
|
|
|
break;
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
case relationship::type::query_table:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case relationship::type::shared_workbook:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case relationship::type::revision_log:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case relationship::type::shared_workbook_user_data:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case relationship::type::single_cell_table_definitions:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case relationship::type::table_definition:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case relationship::type::image:
|
|
|
|
break;
|
2016-11-20 05:42:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-11-20 05:42:16 +08:00
|
|
|
parser_ = nullptr;
|
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-11-20 05:42:16 +08:00
|
|
|
void xlsx_consumer::populate_workbook()
|
|
|
|
{
|
2016-11-20 06:19:38 +08:00
|
|
|
target_.clear();
|
|
|
|
|
|
|
|
read_manifest();
|
|
|
|
auto &manifest = target_.get_manifest();
|
2016-11-20 05:42:16 +08:00
|
|
|
|
|
|
|
auto package_parts = std::vector<relationship::type>
|
|
|
|
{
|
|
|
|
relationship::type::core_properties,
|
2016-11-20 06:19:38 +08:00
|
|
|
relationship::type::extended_properties,
|
|
|
|
relationship::type::custom_properties,
|
|
|
|
relationship::type::office_document,
|
|
|
|
relationship::type::connections,
|
|
|
|
relationship::type::custom_xml_mappings,
|
|
|
|
relationship::type::external_workbook_references,
|
|
|
|
relationship::type::metadata,
|
|
|
|
relationship::type::pivot_table,
|
|
|
|
relationship::type::shared_workbook_revision_headers,
|
|
|
|
relationship::type::volatile_dependencies
|
2016-11-20 05:42:16 +08:00
|
|
|
};
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-11-20 05:42:16 +08:00
|
|
|
auto root_path = path("/");
|
|
|
|
|
|
|
|
for (auto rel_type : package_parts)
|
|
|
|
{
|
|
|
|
if (manifest.has_relationship(root_path, rel_type))
|
|
|
|
{
|
2016-11-20 06:19:38 +08:00
|
|
|
read_part({manifest.get_relationship(root_path, rel_type)});
|
2016-11-20 05:42:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
const auto workbook_rel = manifest.get_relationship(root_path, relationship::type::office_document);
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-11-20 05:42:16 +08:00
|
|
|
const auto workbook_parts_first = std::vector<relationship::type>
|
|
|
|
{
|
|
|
|
relationship::type::shared_string_table,
|
|
|
|
relationship::type::stylesheet,
|
|
|
|
relationship::type::theme
|
|
|
|
};
|
|
|
|
|
|
|
|
for (auto rel_type : workbook_parts_first)
|
|
|
|
{
|
|
|
|
if (manifest.has_relationship(workbook_rel.get_target().get_path(), rel_type))
|
|
|
|
{
|
2016-11-20 06:19:38 +08:00
|
|
|
read_part({workbook_rel, manifest.get_relationship(workbook_rel.get_target().get_path(), rel_type)});
|
2016-11-20 05:42:16 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const auto workbook_parts_second = std::vector<relationship::type>
|
|
|
|
{
|
|
|
|
relationship::type::worksheet,
|
|
|
|
relationship::type::chartsheet,
|
|
|
|
relationship::type::dialogsheet
|
|
|
|
};
|
|
|
|
|
|
|
|
for (auto rel_type : workbook_parts_second)
|
|
|
|
{
|
|
|
|
if (manifest.has_relationship(workbook_rel.get_target().get_path(), rel_type))
|
|
|
|
{
|
|
|
|
for (auto rel : manifest.get_relationships(workbook_rel.get_target().get_path(), rel_type))
|
|
|
|
{
|
2016-11-20 06:19:38 +08:00
|
|
|
read_part({workbook_rel, rel});
|
2016-11-20 05:42:16 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Package Parts
|
|
|
|
|
|
|
|
void xlsx_consumer::read_manifest()
|
|
|
|
{
|
2016-11-20 06:19:38 +08:00
|
|
|
path package_rels_path("_rels/.rels");
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
if (!archive_->has_file(package_rels_path.string()))
|
|
|
|
{
|
|
|
|
throw invalid_file("missing package rels");
|
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
auto package_rels = read_relationships(package_rels_path, *archive_);
|
|
|
|
auto &manifest = target_.get_manifest();
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2016-11-10 08:52:18 +08:00
|
|
|
static const auto &xmlns = constants::get_namespace("content-types");
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2016-11-01 08:48:43 +08:00
|
|
|
xml::parser parser(archive_->open("[Content_Types].xml"), "[Content_Types].xml");
|
2016-09-17 10:59:13 +08:00
|
|
|
parser.next_expect(xml::parser::event_type::start_element, xmlns, "Types");
|
|
|
|
parser.content(xml::content::complex);
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-09-17 10:59:13 +08:00
|
|
|
while (true)
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
2016-09-17 10:59:13 +08:00
|
|
|
if (parser.peek() == xml::parser::event_type::end_element) break;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-17 10:59:13 +08:00
|
|
|
parser.next_expect(xml::parser::event_type::start_element);
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-17 10:59:13 +08:00
|
|
|
if (parser.name() == "Default")
|
|
|
|
{
|
2016-11-20 06:19:38 +08:00
|
|
|
auto extension = parser.attribute("Extension");
|
|
|
|
auto content_type = parser.attribute("ContentType");
|
|
|
|
manifest.register_default_type(extension, content_type);
|
|
|
|
|
2016-09-17 10:59:13 +08:00
|
|
|
parser.next_expect(xml::parser::event_type::end_element, xmlns, "Default");
|
|
|
|
}
|
|
|
|
else if (parser.name() == "Override")
|
|
|
|
{
|
2016-11-20 06:19:38 +08:00
|
|
|
auto part_name = parser.attribute("PartName");
|
|
|
|
auto content_type = parser.attribute("ContentType");
|
|
|
|
manifest.register_override_type(path(part_name), content_type);
|
|
|
|
|
2016-09-17 10:59:13 +08:00
|
|
|
parser.next_expect(xml::parser::event_type::end_element, xmlns, "Override");
|
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
}
|
|
|
|
|
2016-09-17 10:59:13 +08:00
|
|
|
parser.next_expect(xml::parser::event_type::end_element, xmlns, "Types");
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
for (const auto &package_rel : package_rels)
|
|
|
|
{
|
|
|
|
if (package_rel.get_type() == relationship::type::office_document)
|
|
|
|
{
|
|
|
|
auto content_type = manifest.get_content_type(manifest.canonicalize({ package_rel }));
|
|
|
|
check_document_type(content_type);
|
|
|
|
}
|
|
|
|
|
|
|
|
manifest.register_relationship(uri("/"),
|
2016-08-12 12:22:14 +08:00
|
|
|
package_rel.get_type(),
|
2016-11-20 06:19:38 +08:00
|
|
|
package_rel.get_target(),
|
|
|
|
package_rel.get_target_mode(),
|
|
|
|
package_rel.get_id());
|
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
for (const auto &relationship_source_string : archive_->files())
|
|
|
|
{
|
|
|
|
auto relationship_source = path(relationship_source_string);
|
2016-10-31 03:48:40 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
if (relationship_source == path("_rels/.rels") || relationship_source.extension() != "rels") continue;
|
2016-08-13 11:06:25 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
path part(relationship_source.parent().parent());
|
|
|
|
part = part.append(relationship_source.split_extension().first);
|
|
|
|
uri source(part.string());
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
path source_directory = part.parent();
|
2016-08-14 07:44:45 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
auto part_rels = read_relationships(relationship_source, *archive_);
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
for (const auto &part_rel : part_rels)
|
|
|
|
{
|
|
|
|
path target_path(source_directory.append(part_rel.get_target().get_path()));
|
|
|
|
manifest.register_relationship(source,
|
|
|
|
part_rel.get_type(),
|
|
|
|
part_rel.get_target(),
|
|
|
|
part_rel.get_target_mode(),
|
|
|
|
part_rel.get_id());
|
|
|
|
}
|
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_extended_properties()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-11-10 08:52:18 +08:00
|
|
|
static const auto &xmlns = constants::get_namespace("extended-properties");
|
|
|
|
static const auto &xmlns_vt = constants::get_namespace("vt");
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element, xmlns, "Properties");
|
|
|
|
parser().content(xml::parser::content_type::complex);
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-11-20 05:42:16 +08:00
|
|
|
read_block(
|
|
|
|
{
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-11-20 05:42:16 +08:00
|
|
|
xml::qname(xmlns, "Application"),
|
2016-11-20 06:19:38 +08:00
|
|
|
[](xlsx_consumer &c) { c.target_.set_application(c.read_text()); }
|
2016-11-20 05:42:16 +08:00
|
|
|
},
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-11-20 05:42:16 +08:00
|
|
|
xml::qname(xmlns, "DocSecurity"),
|
2016-11-20 06:19:38 +08:00
|
|
|
[](xlsx_consumer &c) { c.target_.set_doc_security(std::stoi(c.read_text())); }
|
2016-11-20 05:42:16 +08:00
|
|
|
},
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-11-20 05:42:16 +08:00
|
|
|
xml::qname(xmlns, "ScaleCrop"),
|
2016-11-20 06:19:38 +08:00
|
|
|
[](xlsx_consumer &c) { c.target_.set_scale_crop(is_true(c.read_text())); }
|
2016-11-20 05:42:16 +08:00
|
|
|
},
|
|
|
|
{
|
|
|
|
xml::qname(xmlns, "Company"),
|
2016-11-20 06:19:38 +08:00
|
|
|
[](xlsx_consumer &c) { c.target_.set_company(c.read_text()); }
|
2016-11-20 05:42:16 +08:00
|
|
|
},
|
|
|
|
{
|
|
|
|
xml::qname(xmlns, "SharedDoc"),
|
2016-11-20 06:19:38 +08:00
|
|
|
[](xlsx_consumer &c) { c.target_.set_shared_doc(is_true(c.read_text())); }
|
2016-11-20 05:42:16 +08:00
|
|
|
},
|
|
|
|
{
|
|
|
|
xml::qname(xmlns, "HyperlinksChanged"),
|
2016-11-20 06:19:38 +08:00
|
|
|
[](xlsx_consumer &c) { c.target_.set_hyperlinks_changed(is_true(c.read_text())); }
|
2016-11-20 05:42:16 +08:00
|
|
|
},
|
|
|
|
{
|
|
|
|
xml::qname(xmlns, "AppVersion"),
|
2016-11-20 06:19:38 +08:00
|
|
|
[](xlsx_consumer &c) { c.target_.set_app_version(c.read_text()); }
|
2016-11-20 05:42:16 +08:00
|
|
|
},
|
|
|
|
{
|
|
|
|
xml::qname(xmlns, "LinksUpToDate"),
|
2016-11-20 06:19:38 +08:00
|
|
|
[](xlsx_consumer &c) { c.target_.set_links_up_to_date(is_true(c.read_text())); }
|
2016-11-20 05:42:16 +08:00
|
|
|
},
|
|
|
|
{
|
|
|
|
xml::qname(xmlns, "Template"),
|
2016-11-20 06:19:38 +08:00
|
|
|
[](xlsx_consumer &c) { c.read_text(); }
|
2016-11-20 05:42:16 +08:00
|
|
|
},
|
|
|
|
{
|
|
|
|
xml::qname(xmlns, "TotalTime"),
|
2016-11-20 06:19:38 +08:00
|
|
|
[](xlsx_consumer &c) { c.read_text(); }
|
2016-11-20 05:42:16 +08:00
|
|
|
},
|
|
|
|
{
|
|
|
|
xml::qname(xmlns, "HeadingPairs"),
|
|
|
|
[](xlsx_consumer &c)
|
|
|
|
{
|
|
|
|
c.parser().content(xml::parser::content_type::complex);
|
|
|
|
c.parser().next_expect(xml::parser::event_type::start_element, xmlns_vt, "vector");
|
|
|
|
c.parser().content(xml::parser::content_type::complex);
|
|
|
|
|
|
|
|
c.parser().attribute("size");
|
|
|
|
c.parser().attribute("baseType");
|
|
|
|
|
|
|
|
c.parser().next_expect(xml::parser::event_type::start_element, xmlns_vt, "variant");
|
|
|
|
c.parser().content(xml::parser::content_type::complex);
|
|
|
|
c.parser().next_expect(xml::parser::event_type::start_element, xmlns_vt, "lpstr");
|
|
|
|
c.parser().next_expect(xml::parser::event_type::characters);
|
|
|
|
c.parser().next_expect(xml::parser::event_type::end_element, xmlns_vt, "lpstr");
|
|
|
|
c.parser().next_expect(xml::parser::event_type::end_element, xmlns_vt, "variant");
|
|
|
|
c.parser().next_expect(xml::parser::event_type::start_element, xmlns_vt, "variant");
|
|
|
|
c.parser().content(xml::parser::content_type::complex);
|
|
|
|
c.parser().next_expect(xml::parser::event_type::start_element, xmlns_vt, "i4");
|
|
|
|
c.parser().next_expect(xml::parser::event_type::characters);
|
|
|
|
c.parser().next_expect(xml::parser::event_type::end_element, xmlns_vt, "i4");
|
|
|
|
c.parser().next_expect(xml::parser::event_type::end_element, xmlns_vt, "variant");
|
|
|
|
|
|
|
|
c.parser().next_expect(xml::parser::event_type::end_element, xmlns_vt, "vector");
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
xml::qname(xmlns, "TitlesOfParts"),
|
|
|
|
[](xlsx_consumer &c)
|
|
|
|
{
|
|
|
|
c.parser().content(xml::parser::content_type::complex);
|
|
|
|
c.parser().next_expect(xml::parser::event_type::start_element, xmlns_vt, "vector");
|
|
|
|
c.parser().content(xml::parser::content_type::complex);
|
|
|
|
|
|
|
|
auto size = c.parser().attribute<std::size_t>("size");
|
|
|
|
c.parser().attribute("baseType");
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-11-20 05:42:16 +08:00
|
|
|
for (auto i = std::size_t(0); i < size; ++i)
|
|
|
|
{
|
|
|
|
c.parser().next_expect(xml::parser::event_type::start_element, xmlns_vt, "lpstr");
|
|
|
|
c.parser().content(xml::parser::content_type::simple);
|
|
|
|
c.parser().next_expect(xml::parser::event_type::characters);
|
|
|
|
c.parser().next_expect(xml::parser::event_type::end_element, xmlns_vt, "lpstr");
|
|
|
|
}
|
|
|
|
|
|
|
|
c.parser().next_expect(xml::parser::event_type::end_element, xmlns_vt, "vector");
|
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
}
|
2016-11-20 05:42:16 +08:00
|
|
|
});
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_core_properties()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-11-10 08:52:18 +08:00
|
|
|
static const auto &xmlns_cp = constants::get_namespace("core-properties");
|
|
|
|
static const auto &xmlns_dc = constants::get_namespace("dc");
|
|
|
|
static const auto &xmlns_dcterms = constants::get_namespace("dcterms");
|
|
|
|
static const auto &xmlns_xsi = constants::get_namespace("xsi");
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element, xmlns_cp, "coreProperties");
|
|
|
|
parser().content(xml::parser::content_type::complex);
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
while (true)
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().peek() == xml::parser::event_type::end_element) break;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element);
|
2016-10-25 10:09:15 +08:00
|
|
|
|
|
|
|
std::string characters;
|
|
|
|
if (parser().peek() == xml::parser::event_type::characters)
|
|
|
|
{
|
|
|
|
parser().next_expect(xml::parser::event_type::characters);
|
|
|
|
characters = parser().value();
|
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
if (parser().namespace_() == xmlns_dc && parser().name() == "creator")
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-10-25 10:09:15 +08:00
|
|
|
target_.set_creator(characters);
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
else if (parser().namespace_() == xmlns_cp && parser().name() == "lastModifiedBy")
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-10-25 10:09:15 +08:00
|
|
|
target_.set_last_modified_by(characters);
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
else if (parser().namespace_() == xmlns_dcterms && parser().name() == "created")
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().attribute(xml::qname(xmlns_xsi, "type"));
|
2016-10-25 10:09:15 +08:00
|
|
|
target_.set_created(w3cdtf_to_datetime(characters));
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
else if (parser().namespace_() == xmlns_dcterms && parser().name() == "modified")
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().attribute(xml::qname(xmlns_xsi, "type"));
|
2016-10-25 10:09:15 +08:00
|
|
|
target_.set_modified(w3cdtf_to_datetime(characters));
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element);
|
2016-11-20 06:19:38 +08:00
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns_cp, "coreProperties");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_custom_file_properties()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write SpreadsheetML-Specific Package Parts
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_workbook()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-11-10 08:52:18 +08:00
|
|
|
static const auto &xmlns = constants::get_namespace("workbook");
|
|
|
|
static const auto &xmlns_mc = constants::get_namespace("mc");
|
|
|
|
static const auto &xmlns_mx = constants::get_namespace("mx");
|
|
|
|
static const auto &xmlns_r = constants::get_namespace("r");
|
|
|
|
static const auto &xmlns_s = constants::get_namespace("worksheet");
|
|
|
|
static const auto &xmlns_x15 = constants::get_namespace("x15");
|
|
|
|
static const auto &xmlns_x15ac = constants::get_namespace("x15ac");
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element, xmlns, "workbook");
|
|
|
|
parser().content(xml::parser::content_type::complex);
|
2016-11-20 06:19:38 +08:00
|
|
|
|
|
|
|
while (parser().peek() == xml::parser::event_type::start_namespace_decl)
|
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_namespace_decl);
|
2016-11-20 05:42:16 +08:00
|
|
|
|
|
|
|
if (parser().namespace_() == xmlns_x15)
|
|
|
|
{
|
|
|
|
target_.enable_x15();
|
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().attribute_present(xml::qname(xmlns_mc, "Ignorable")))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().attribute(xml::qname(xmlns_mc, "Ignorable"));
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-08-14 07:44:45 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
while (true)
|
|
|
|
{
|
2016-11-20 06:19:38 +08:00
|
|
|
if (parser().peek() == xml::parser::event_type::end_element ||
|
|
|
|
parser().peek() == xml::parser::event_type::end_namespace_decl)
|
|
|
|
break;
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element);
|
|
|
|
parser().content(xml::parser::content_type::complex);
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
auto qname = parser().qname();
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
if (qname == xml::qname(xmlns, "fileVersion"))
|
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
target_.d_->has_file_version_ = true;
|
|
|
|
target_.d_->file_version_.app_name = parser().attribute("appName");
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
if (parser().attribute_present("lastEdited"))
|
|
|
|
{
|
|
|
|
target_.d_->file_version_.last_edited = string_to_size_t(parser().attribute("lastEdited"));
|
|
|
|
}
|
|
|
|
if (parser().attribute_present("lowestEdited"))
|
|
|
|
{
|
|
|
|
target_.d_->file_version_.lowest_edited = string_to_size_t(parser().attribute("lowestEdited"));
|
|
|
|
}
|
|
|
|
if (parser().attribute_present("lowestEdited"))
|
|
|
|
{
|
|
|
|
target_.d_->file_version_.rup_build = string_to_size_t(parser().attribute("rupBuild"));
|
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element);
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
|
|
|
else if (qname == xml::qname(xmlns_mc, "AlternateContent"))
|
|
|
|
{
|
2016-11-20 05:42:16 +08:00
|
|
|
if (parser().peek() == xml::parser::event_type::start_namespace_decl)
|
|
|
|
{
|
|
|
|
parser().next_expect(xml::parser::event_type::start_namespace_decl);
|
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element, xmlns_mc, "Choice");
|
|
|
|
parser().content(xml::parser::content_type::complex);
|
|
|
|
parser().attribute("Requires");
|
|
|
|
parser().next_expect(xml::parser::event_type::start_element, xmlns_x15ac, "absPath");
|
|
|
|
target_.set_absolute_path(path(parser().attribute("url")));
|
2016-11-20 05:42:16 +08:00
|
|
|
|
|
|
|
if (parser().peek() == xml::parser::event_type::start_namespace_decl)
|
|
|
|
{
|
|
|
|
parser().next_expect(xml::parser::event_type::start_namespace_decl);
|
|
|
|
parser().next_expect(xml::parser::event_type::end_namespace_decl);
|
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns_x15ac, "absPath");
|
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns_mc, "Choice");
|
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns_mc, "AlternateContent");
|
2016-11-20 05:42:16 +08:00
|
|
|
|
|
|
|
if (parser().peek() == xml::parser::event_type::end_namespace_decl)
|
|
|
|
{
|
|
|
|
parser().next_expect(xml::parser::event_type::end_namespace_decl);
|
|
|
|
}
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
|
|
|
else if (qname == xml::qname(xmlns, "bookViews"))
|
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().peek() == xml::parser::event_type::start_element)
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element, xmlns, "workbookView");
|
2016-09-22 07:04:16 +08:00
|
|
|
|
|
|
|
workbook_view view;
|
2016-10-12 11:16:14 +08:00
|
|
|
view.x_window = string_to_size_t(parser().attribute("xWindow"));
|
|
|
|
view.y_window = string_to_size_t(parser().attribute("yWindow"));
|
|
|
|
view.window_width = string_to_size_t(parser().attribute("windowWidth"));
|
|
|
|
view.window_height = string_to_size_t(parser().attribute("windowHeight"));
|
2016-11-20 06:19:38 +08:00
|
|
|
|
|
|
|
if (parser().attribute_present("tabRatio"))
|
|
|
|
{
|
|
|
|
view.tab_ratio = string_to_size_t(parser().attribute("tabRatio"));
|
|
|
|
}
|
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
if (parser().attribute_present("activeTab"))
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
|
|
|
parser().attribute("activeTab");
|
|
|
|
}
|
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
if (parser().attribute_present("firstSheet"))
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
|
|
|
parser().attribute("firstSheet");
|
|
|
|
}
|
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
if (parser().attribute_present("showHorizontalScroll"))
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
|
|
|
parser().attribute("showHorizontalScroll");
|
|
|
|
}
|
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
if (parser().attribute_present("showSheetTabs"))
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
|
|
|
parser().attribute("showSheetTabs");
|
|
|
|
}
|
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
if (parser().attribute_present("showVerticalScroll"))
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
|
|
|
parser().attribute("showVerticalScroll");
|
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
target_.set_view(view);
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "workbookView");
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "bookViews");
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
|
|
|
else if (qname == xml::qname(xmlns, "workbookPr"))
|
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
target_.d_->has_properties_ = true;
|
2016-08-14 07:44:45 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().attribute_present("date1904"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
const auto value = parser().attribute("date1904");
|
2016-08-14 07:44:45 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
if (value == "1" || value == "true")
|
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
target_.set_base_date(xlnt::calendar::mac_1904);
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
|
|
|
}
|
2016-10-19 07:29:04 +08:00
|
|
|
|
2016-11-21 07:36:52 +08:00
|
|
|
skip_attribute("codeName");
|
|
|
|
skip_attribute("defaultThemeVersion");
|
|
|
|
skip_attribute("backupFile");
|
|
|
|
skip_attribute("showObjects");
|
|
|
|
skip_attribute("filterPrivacy");
|
2016-11-15 21:09:17 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "workbookPr");
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
|
|
|
else if (qname == xml::qname(xmlns, "sheets"))
|
|
|
|
{
|
|
|
|
std::size_t index = 0;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
while (true)
|
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().peek() == xml::parser::event_type::end_element) break;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element, xmlns_s, "sheet");
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
std::string rel_id(parser().attribute(xml::qname(xmlns_r, "id")));
|
|
|
|
std::string title(parser().attribute("name"));
|
|
|
|
auto id = string_to_size_t(parser().attribute("sheetId"));
|
2016-09-22 07:04:16 +08:00
|
|
|
|
|
|
|
sheet_title_id_map_[title] = id;
|
|
|
|
sheet_title_index_map_[title] = index++;
|
2016-10-12 11:16:14 +08:00
|
|
|
target_.d_->sheet_title_rel_id_map_[title] = rel_id;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
if (parser().attribute_present("state"))
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
|
|
|
parser().attribute("state");
|
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns_s, "sheet");
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "sheets");
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
|
|
|
else if (qname == xml::qname(xmlns, "calcPr"))
|
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
target_.d_->has_calculation_properties_ = true;
|
2016-10-25 10:09:15 +08:00
|
|
|
|
|
|
|
if (parser().attribute_present("calcId"))
|
|
|
|
{
|
|
|
|
parser().attribute("calcId");
|
|
|
|
}
|
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
if (parser().attribute_present("concurrentCalc"))
|
|
|
|
{
|
|
|
|
parser().attribute("concurrentCalc");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parser().attribute_present("iterate"))
|
|
|
|
{
|
|
|
|
parser().attribute("iterate");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parser().attribute_present("iterateCount"))
|
|
|
|
{
|
|
|
|
parser().attribute("iterateCount");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parser().attribute_present("iterateDelta"))
|
|
|
|
{
|
|
|
|
parser().attribute("iterateDelta");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parser().attribute_present("refMode"))
|
|
|
|
{
|
|
|
|
parser().attribute("refMode");
|
|
|
|
}
|
2016-10-25 10:09:15 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "calcPr");
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
|
|
|
else if (qname == xml::qname(xmlns, "extLst"))
|
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element, xmlns, "ext");
|
|
|
|
parser().content(xml::parser::content_type::complex);
|
|
|
|
parser().attribute("uri");
|
2016-10-19 07:29:04 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
if (parser().peek() == xml::parser::event_type::end_element) break;
|
|
|
|
|
|
|
|
parser().next_expect(xml::parser::event_type::start_namespace_decl);
|
|
|
|
parser().next_expect(xml::parser::event_type::start_element);
|
|
|
|
|
|
|
|
if (parser().qname() == xml::qname(xmlns_mx, "ArchID"))
|
|
|
|
{
|
|
|
|
target_.d_->has_arch_id_ = true;
|
|
|
|
parser().attribute("Flags");
|
|
|
|
}
|
|
|
|
else if (parser().qname() == xml::qname(xmlns_x15, "workbookPr"))
|
|
|
|
{
|
|
|
|
parser().attribute("chartTrackingRefBase");
|
|
|
|
}
|
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
if (parser().attribute_present("stringRefSyntax"))
|
|
|
|
{
|
|
|
|
parser().attribute("stringRefSyntax");
|
|
|
|
}
|
2016-10-19 07:29:04 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element);
|
|
|
|
}
|
2016-10-19 07:29:04 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "ext");
|
2016-11-20 05:42:16 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_namespace_decl);
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "extLst");
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-10-25 10:09:15 +08:00
|
|
|
else if (qname == xml::qname(xmlns, "workbookProtection"))
|
|
|
|
{
|
2016-11-20 06:19:38 +08:00
|
|
|
while (parser().peek() != xml::parser::event_type::end_element ||
|
|
|
|
parser().qname() != xml::qname(xmlns, "workbookProtection"))
|
2016-10-25 10:09:15 +08:00
|
|
|
{
|
|
|
|
parser().next();
|
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
parser().next();
|
|
|
|
}
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 05:42:16 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "workbook");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Write Workbook Relationship Target Parts
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_calculation_chain()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
void xlsx_consumer::read_chartsheet(const std::string & /*title*/)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_connections()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_custom_property()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_custom_xml_mappings()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
void xlsx_consumer::read_dialogsheet(const std::string & /*title*/)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_external_workbook_references()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_metadata()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_pivot_table()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_shared_string_table()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-11-10 08:52:18 +08:00
|
|
|
static const auto &xmlns = constants::get_namespace("worksheet");
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element, xmlns, "sst");
|
2016-11-20 06:19:38 +08:00
|
|
|
parser().content(xml::content::complex);
|
2016-10-14 08:11:02 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
std::size_t unique_count = 0;
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
if (parser().attribute_present("uniqueCount"))
|
|
|
|
{
|
|
|
|
unique_count = string_to_size_t(parser().attribute("uniqueCount"));
|
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
auto &strings = target_.get_shared_strings();
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
while (true)
|
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().peek() == xml::parser::event_type::end_element) break;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element, xmlns, "si");
|
2016-11-20 06:19:38 +08:00
|
|
|
parser().content(xml::content::complex);
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element);
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-29 22:23:04 +08:00
|
|
|
formatted_text t;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
parser().attribute_map();
|
2016-11-20 06:19:38 +08:00
|
|
|
|
|
|
|
if (parser().name() == "t")
|
|
|
|
{
|
2016-11-21 08:38:58 +08:00
|
|
|
t.plain_text(read_text());
|
2016-11-20 06:19:38 +08:00
|
|
|
}
|
|
|
|
else if (parser().name() == "r") // possible multiple text entities.
|
|
|
|
{
|
2016-09-22 07:04:16 +08:00
|
|
|
while (true)
|
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().peek() == xml::parser::event_type::end_element) break;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element, xmlns, "t");
|
2016-11-20 06:19:38 +08:00
|
|
|
text_run run;
|
2016-11-21 08:38:58 +08:00
|
|
|
run.set_string(read_text());
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().peek() == xml::parser::event_type::start_element)
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element, xmlns, "rPr");
|
2016-09-22 07:04:16 +08:00
|
|
|
|
|
|
|
while (true)
|
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().peek() == xml::parser::event_type::end_element) break;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element);
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().qname() == xml::qname(xmlns, "sz"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
run.set_size(string_to_size_t(parser().attribute("val")));
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
else if (parser().qname() == xml::qname(xmlns, "rFont"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
run.set_font(parser().attribute("val"));
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
else if (parser().qname() == xml::qname(xmlns, "color"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-10-29 22:23:04 +08:00
|
|
|
run.set_color(read_color(parser()));
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
else if (parser().qname() == xml::qname(xmlns, "family"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
run.set_family(string_to_size_t(parser().attribute("val")));
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
else if (parser().qname() == xml::qname(xmlns, "scheme"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
run.set_scheme(parser().attribute("val"));
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-14 08:11:02 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element);
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
t.add_run(run);
|
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
}
|
2016-10-14 08:11:02 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element);
|
|
|
|
parser().next_expect(xml::parser::event_type::end_element);
|
2016-10-25 10:09:15 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
strings.push_back(t);
|
2016-11-20 06:19:38 +08:00
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
if (unique_count != strings.size())
|
|
|
|
{
|
|
|
|
throw invalid_file("sizes don't match");
|
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_shared_workbook_revision_headers()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_shared_workbook()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_shared_workbook_user_data()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_stylesheet()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-11-10 08:52:18 +08:00
|
|
|
static const auto &xmlns = constants::get_namespace("worksheet");
|
|
|
|
static const auto &xmlns_mc = constants::get_namespace("mc");
|
|
|
|
static const auto &xmlns_x14 = constants::get_namespace("x14");
|
|
|
|
static const auto &xmlns_x14ac = constants::get_namespace("x14ac");
|
2016-11-20 06:19:38 +08:00
|
|
|
static const auto &xmlns_x15 = constants::get_namespace("x15");
|
|
|
|
|
|
|
|
auto &stylesheet = target_.impl().stylesheet_;
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element, xmlns, "styleSheet");
|
|
|
|
parser().content(xml::parser::content_type::complex);
|
2016-09-22 07:04:16 +08:00
|
|
|
|
|
|
|
while (true)
|
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().peek() != xml::parser::event_type::start_namespace_decl) break;
|
2016-08-18 19:34:18 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_namespace_decl);
|
2016-08-18 19:34:18 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().namespace_() == xmlns_x14ac)
|
2016-09-10 22:05:06 +08:00
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
target_.enable_x15();
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().attribute_present(xml::qname(xmlns_mc, "Ignorable")))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().attribute(xml::qname(xmlns_mc, "Ignorable"));
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
struct formatting_record
|
|
|
|
{
|
2016-11-20 06:19:38 +08:00
|
|
|
std::pair<class alignment, bool> alignment = {{}, 0};
|
|
|
|
std::pair<std::size_t, bool> border_id = {0, false};
|
|
|
|
std::pair<std::size_t, bool> fill_id = {0, false};
|
|
|
|
std::pair<std::size_t, bool> font_id = {0, false};
|
|
|
|
std::pair<std::size_t, bool> number_format_id = {0, false};
|
|
|
|
std::pair<class protection, bool> protection = {{}, false};
|
|
|
|
std::pair<std::size_t, bool> style_id = {0, false};
|
2016-09-22 07:04:16 +08:00
|
|
|
};
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
struct style_data
|
|
|
|
{
|
|
|
|
std::string name;
|
|
|
|
std::size_t record_id;
|
2016-11-15 21:09:17 +08:00
|
|
|
std::pair<std::size_t, bool> builtin_id;
|
|
|
|
std::pair<std::size_t, bool> i_level;
|
|
|
|
std::pair<bool, bool> hidden;
|
2016-10-25 10:09:15 +08:00
|
|
|
bool custom_builtin;
|
2016-09-22 07:04:16 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
std::vector<style_data> style_datas;
|
|
|
|
std::vector<formatting_record> style_records;
|
|
|
|
std::vector<formatting_record> format_records;
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().peek() == xml::parser::event_type::end_element) break;
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element);
|
|
|
|
parser().content(xml::parser::content_type::complex);
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().qname() == xml::qname(xmlns, "borders"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
|
|
|
stylesheet.borders.clear();
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
auto count = parser().attribute<std::size_t>("count");
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
while (true)
|
2016-09-10 22:05:06 +08:00
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().peek() == xml::parser::event_type::end_element) break;
|
|
|
|
|
|
|
|
stylesheet.borders.push_back(xlnt::border());
|
2016-11-20 06:19:38 +08:00
|
|
|
auto &border = stylesheet.borders.back();
|
|
|
|
|
|
|
|
parser().next_expect(xml::parser::event_type::start_element); // <border>
|
|
|
|
parser().content(xml::parser::content_type::complex);
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
auto diagonal = diagonal_direction::neither;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
if (parser().attribute_present("diagonalDown") && parser().attribute("diagonalDown") == "1")
|
|
|
|
{
|
|
|
|
diagonal = diagonal_direction::down;
|
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
if (parser().attribute_present("diagonalUp") && parser().attribute("diagonalUp") == "1")
|
|
|
|
{
|
|
|
|
diagonal = diagonal == diagonal_direction::down ? diagonal_direction::both : diagonal_direction::up;
|
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
if (diagonal != diagonal_direction::neither)
|
|
|
|
{
|
|
|
|
border.diagonal(diagonal);
|
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
if (parser().peek() == xml::parser::event_type::end_element) break;
|
|
|
|
parser().next_expect(xml::parser::event_type::start_element);
|
2016-10-25 10:09:15 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
auto side_type = xml::value_traits<xlnt::border_side>::parse(parser().name(), parser());
|
|
|
|
xlnt::border::border_property side;
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
if (parser().attribute_present("style"))
|
|
|
|
{
|
|
|
|
side.style(parser().attribute<xlnt::border_style>("style"));
|
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
if (parser().peek() == xml::parser::event_type::start_element)
|
|
|
|
{
|
|
|
|
parser().next_expect(xml::parser::event_type::start_element, "color");
|
|
|
|
side.color(read_color(parser()));
|
|
|
|
parser().next_expect(xml::parser::event_type::end_element, "color");
|
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
border.side(side_type, side);
|
|
|
|
parser().next_expect(xml::parser::event_type::end_element);
|
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element); // </border>
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
if (count != stylesheet.borders.size())
|
|
|
|
{
|
|
|
|
throw xlnt::exception("counts don't match");
|
2016-09-10 22:05:06 +08:00
|
|
|
}
|
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
else if (parser().qname() == xml::qname(xmlns, "fills"))
|
2016-09-10 22:05:06 +08:00
|
|
|
{
|
2016-09-22 07:04:16 +08:00
|
|
|
stylesheet.fills.clear();
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
auto count = parser().attribute<std::size_t>("count");
|
2016-09-22 07:04:16 +08:00
|
|
|
|
|
|
|
while (true)
|
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().peek() == xml::parser::event_type::end_element) break;
|
|
|
|
|
|
|
|
stylesheet.fills.push_back(xlnt::fill());
|
2016-11-20 06:19:38 +08:00
|
|
|
auto &new_fill = stylesheet.fills.back();
|
|
|
|
|
|
|
|
parser().next_expect(xml::parser::event_type::start_element, xmlns, "fill");
|
|
|
|
parser().content(xml::parser::content_type::complex);
|
|
|
|
parser().next_expect(xml::parser::event_type::start_element);
|
|
|
|
|
|
|
|
if (parser().qname() == xml::qname(xmlns, "patternFill"))
|
|
|
|
{
|
|
|
|
xlnt::pattern_fill pattern;
|
|
|
|
|
|
|
|
if (parser().attribute_present("patternType"))
|
|
|
|
{
|
|
|
|
pattern.type(parser().attribute<xlnt::pattern_fill_type>("patternType"));
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
if (parser().peek() == xml::parser::event_type::end_element)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
parser().next_expect(xml::parser::event_type::start_element);
|
|
|
|
|
|
|
|
if (parser().name() == "fgColor")
|
|
|
|
{
|
|
|
|
pattern.foreground(read_color(parser()));
|
|
|
|
}
|
|
|
|
else if (parser().name() == "bgColor")
|
|
|
|
{
|
|
|
|
pattern.background(read_color(parser()));
|
|
|
|
}
|
|
|
|
|
|
|
|
parser().next_expect(xml::parser::event_type::end_element);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
new_fill = pattern;
|
|
|
|
}
|
|
|
|
else if (parser().qname() == xml::qname(xmlns, "gradientFill"))
|
|
|
|
{
|
|
|
|
xlnt::gradient_fill gradient;
|
|
|
|
|
|
|
|
if (parser().attribute_present("type"))
|
|
|
|
{
|
|
|
|
gradient.type(parser().attribute<xlnt::gradient_fill_type>("type"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gradient.type(xlnt::gradient_fill_type::linear);
|
|
|
|
}
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
if (parser().peek() == xml::parser::event_type::end_element) break;
|
|
|
|
|
|
|
|
parser().next_expect(xml::parser::event_type::start_element, "stop");
|
|
|
|
auto position = parser().attribute<double>("position");
|
|
|
|
parser().next_expect(xml::parser::event_type::start_element, "color");
|
|
|
|
auto color = read_color(parser());
|
|
|
|
parser().next_expect(xml::parser::event_type::end_element, "color");
|
|
|
|
parser().next_expect(xml::parser::event_type::end_element, "stop");
|
|
|
|
|
|
|
|
gradient.add_stop(position, color);
|
|
|
|
}
|
|
|
|
|
|
|
|
new_fill = gradient;
|
|
|
|
}
|
|
|
|
|
|
|
|
parser().next_expect(xml::parser::event_type::end_element); // </gradientFill> or </patternFill>
|
|
|
|
parser().next_expect(xml::parser::event_type::end_element); // </fill>
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
if (count != stylesheet.fills.size())
|
|
|
|
{
|
|
|
|
throw xlnt::exception("counts don't match");
|
|
|
|
}
|
2016-09-10 22:05:06 +08:00
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
else if (parser().qname() == xml::qname(xmlns, "fonts"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
|
|
|
stylesheet.fonts.clear();
|
2016-08-18 19:34:18 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
auto count = parser().attribute<std::size_t>("count");
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().attribute_present(xml::qname(xmlns_x14ac, "knownFonts")))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().attribute(xml::qname(xmlns_x14ac, "knownFonts"));
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().peek() == xml::parser::event_type::end_element) break;
|
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
stylesheet.fonts.push_back(xlnt::font());
|
|
|
|
auto &new_font = stylesheet.fonts.back();
|
|
|
|
|
|
|
|
parser().next_expect(xml::parser::event_type::start_element, xmlns, "font");
|
|
|
|
parser().content(xml::parser::content_type::complex);
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
if (parser().peek() == xml::parser::event_type::end_element) break;
|
|
|
|
|
|
|
|
parser().next_expect(xml::parser::event_type::start_element);
|
|
|
|
parser().content(xml::parser::content_type::simple);
|
|
|
|
|
|
|
|
if (parser().name() == "sz")
|
|
|
|
{
|
|
|
|
new_font.size(string_to_size_t(parser().attribute("val")));
|
|
|
|
}
|
|
|
|
else if (parser().name() == "name")
|
|
|
|
{
|
|
|
|
new_font.name(parser().attribute("val"));
|
|
|
|
}
|
|
|
|
else if (parser().name() == "color")
|
|
|
|
{
|
|
|
|
new_font.color(read_color(parser()));
|
|
|
|
}
|
|
|
|
else if (parser().name() == "family")
|
|
|
|
{
|
|
|
|
new_font.family(string_to_size_t(parser().attribute("val")));
|
|
|
|
}
|
|
|
|
else if (parser().name() == "scheme")
|
|
|
|
{
|
|
|
|
new_font.scheme(parser().attribute("val"));
|
|
|
|
}
|
|
|
|
else if (parser().name() == "b")
|
|
|
|
{
|
|
|
|
if (parser().attribute_present("val"))
|
|
|
|
{
|
|
|
|
new_font.bold(is_true(parser().attribute("val")));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
new_font.bold(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (parser().name() == "vertAlign")
|
|
|
|
{
|
|
|
|
new_font.superscript(parser().attribute("val") == "superscript");
|
|
|
|
}
|
|
|
|
else if (parser().name() == "strike")
|
|
|
|
{
|
|
|
|
if (parser().attribute_present("val"))
|
|
|
|
{
|
|
|
|
new_font.strikethrough(is_true(parser().attribute("val")));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
new_font.strikethrough(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (parser().name() == "i")
|
|
|
|
{
|
|
|
|
if (parser().attribute_present("val"))
|
|
|
|
{
|
|
|
|
new_font.italic(is_true(parser().attribute("val")));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
new_font.italic(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (parser().name() == "u")
|
|
|
|
{
|
|
|
|
if (parser().attribute_present("val"))
|
|
|
|
{
|
|
|
|
new_font.underline(parser().attribute<xlnt::font::underline_style>("val"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
new_font.underline(xlnt::font::underline_style::single);
|
|
|
|
}
|
|
|
|
}
|
2016-10-25 10:09:15 +08:00
|
|
|
else if (parser().name() == "charset")
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
|
|
|
if (parser().attribute_present("val"))
|
|
|
|
{
|
|
|
|
parser().attribute("val");
|
|
|
|
}
|
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element);
|
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "font");
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
if (count != stylesheet.fonts.size())
|
|
|
|
{
|
|
|
|
throw xlnt::exception("counts don't match");
|
|
|
|
}
|
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
else if (parser().qname() == xml::qname(xmlns, "numFmts"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
|
|
|
stylesheet.number_formats.clear();
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
auto count = parser().attribute<std::size_t>("count");
|
2016-09-22 07:04:16 +08:00
|
|
|
|
|
|
|
while (true)
|
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().peek() == xml::parser::event_type::end_element) break;
|
2016-10-25 10:09:15 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element, xmlns, "numFmt");
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
auto format_string = parser().attribute("formatCode");
|
2016-09-22 07:04:16 +08:00
|
|
|
|
|
|
|
if (format_string == "GENERAL")
|
|
|
|
{
|
|
|
|
format_string = "General";
|
|
|
|
}
|
|
|
|
|
|
|
|
xlnt::number_format nf;
|
|
|
|
|
|
|
|
nf.set_format_string(format_string);
|
2016-10-12 11:16:14 +08:00
|
|
|
nf.set_id(string_to_size_t(parser().attribute("numFmtId")));
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2016-11-03 10:04:51 +08:00
|
|
|
stylesheet.number_formats.push_back(nf);
|
2016-10-25 10:09:15 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element); // numFmt
|
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
if (count != stylesheet.number_formats.size())
|
|
|
|
{
|
|
|
|
throw xlnt::exception("counts don't match");
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
else if (parser().qname() == xml::qname(xmlns, "colors"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-11-20 06:19:38 +08:00
|
|
|
while (parser().peek() != xml::parser::event_type::end_element ||
|
|
|
|
parser().qname() != xml::qname(xmlns, "colors"))
|
2016-10-25 10:09:15 +08:00
|
|
|
{
|
|
|
|
if (parser().next() == xml::parser::event_type::start_element)
|
|
|
|
{
|
|
|
|
parser().attribute_map();
|
|
|
|
}
|
|
|
|
}
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
else if (parser().qname() == xml::qname(xmlns, "cellStyles"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
auto count = parser().attribute<std::size_t>("count");
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
while (true)
|
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().peek() == xml::parser::event_type::end_element) break;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
auto &data = *style_datas.emplace(style_datas.end());
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element, xmlns, "cellStyle");
|
2016-11-08 10:11:30 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
data.name = parser().attribute("name");
|
|
|
|
data.record_id = parser().attribute<std::size_t>("xfId");
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-11-15 21:09:17 +08:00
|
|
|
if (parser().attribute_present("builtinId"))
|
|
|
|
{
|
|
|
|
data.builtin_id = {parser().attribute<std::size_t>("builtinId"), true};
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parser().attribute_present("iLevel"))
|
|
|
|
{
|
|
|
|
data.i_level = {parser().attribute<std::size_t>("iLevel"), true};
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parser().attribute_present("hidden"))
|
|
|
|
{
|
|
|
|
data.hidden = {is_true(parser().attribute("hidden")), true};
|
|
|
|
}
|
2016-11-08 10:11:30 +08:00
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
if (parser().attribute_present("customBuiltin"))
|
|
|
|
{
|
2016-11-08 10:11:30 +08:00
|
|
|
data.custom_builtin = is_true(parser().attribute("customBuiltin"));
|
2016-10-25 10:09:15 +08:00
|
|
|
}
|
2016-11-08 10:11:30 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "cellStyle");
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
if (count != style_datas.size())
|
|
|
|
{
|
|
|
|
throw xlnt::exception("counts don't match");
|
|
|
|
}
|
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
else if (parser().qname() == xml::qname(xmlns, "cellStyleXfs") ||
|
|
|
|
parser().qname() == xml::qname(xmlns, "cellXfs"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
auto in_style_records = parser().name() == "cellStyleXfs";
|
|
|
|
auto count = parser().attribute<std::size_t>("count");
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
while (true)
|
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().peek() == xml::parser::event_type::end_element) break;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element, xmlns, "xf");
|
2016-11-20 06:19:38 +08:00
|
|
|
parser().content(xml::content::complex);
|
2016-09-22 07:04:16 +08:00
|
|
|
|
|
|
|
auto &record = *(!in_style_records
|
|
|
|
? format_records.emplace(format_records.end())
|
|
|
|
: style_records.emplace(style_records.end()));
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
auto apply_alignment_present = parser().attribute_present("applyAlignment");
|
2016-11-20 06:19:38 +08:00
|
|
|
auto alignment_applied = apply_alignment_present && is_true(parser().attribute("applyAlignment"));
|
2016-09-22 07:04:16 +08:00
|
|
|
record.alignment.second = alignment_applied;
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
auto border_applied = parser().attribute_present("applyBorder")
|
|
|
|
&& is_true(parser().attribute("applyBorder"));
|
|
|
|
auto border_index = parser().attribute_present("borderId")
|
|
|
|
? string_to_size_t(parser().attribute("borderId")) : 0;
|
2016-11-20 06:19:38 +08:00
|
|
|
record.border_id = {border_index, border_applied};
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
auto fill_applied = parser().attribute_present("applyFill")
|
|
|
|
&& is_true(parser().attribute("applyFill"));
|
|
|
|
auto fill_index = parser().attribute_present("fillId")
|
|
|
|
? string_to_size_t(parser().attribute("fillId")) : 0;
|
2016-11-20 06:19:38 +08:00
|
|
|
record.fill_id = {fill_index, fill_applied};
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
auto font_applied = parser().attribute_present("applyFont")
|
|
|
|
&& is_true(parser().attribute("applyFont"));
|
|
|
|
auto font_index = parser().attribute_present("fontId")
|
|
|
|
? string_to_size_t(parser().attribute("fontId")) : 0;
|
2016-11-20 06:19:38 +08:00
|
|
|
record.font_id = {font_index, font_applied};
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
auto number_format_applied = parser().attribute_present("applyNumberFormat")
|
|
|
|
&& is_true(parser().attribute("applyNumberFormat"));
|
|
|
|
auto number_format_id = parser().attribute_present("numFmtId")
|
|
|
|
? string_to_size_t(parser().attribute("numFmtId")) : 0;
|
2016-11-20 06:19:38 +08:00
|
|
|
record.number_format_id = {number_format_id, number_format_applied};
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
auto apply_protection_present = parser().attribute_present("applyProtection");
|
2016-09-22 07:04:16 +08:00
|
|
|
auto protection_applied = apply_protection_present
|
2016-10-12 11:16:14 +08:00
|
|
|
&& is_true(parser().attribute("applyProtection"));
|
2016-09-22 07:04:16 +08:00
|
|
|
record.protection.second = protection_applied;
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().attribute_present("xfId") && parser().name() == "cellXfs")
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-11-20 06:19:38 +08:00
|
|
|
record.style_id = {parser().attribute<std::size_t>("xfId"), true};
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
while (true)
|
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().peek() == xml::parser::event_type::end_element) break;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element);
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().qname() == xml::qname(xmlns, "alignment"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-11-20 06:19:38 +08:00
|
|
|
if (parser().attribute_present("wrapText"))
|
|
|
|
{
|
|
|
|
auto value = is_true(parser().attribute("wrapText"));
|
|
|
|
record.alignment.first.wrap(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parser().attribute_present("shrinkToFit"))
|
|
|
|
{
|
|
|
|
auto value = is_true(parser().attribute("shrinkToFit"));
|
|
|
|
record.alignment.first.shrink(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parser().attribute_present("indent"))
|
|
|
|
{
|
|
|
|
auto value = parser().attribute<int>("indent");
|
|
|
|
record.alignment.first.indent(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parser().attribute_present("textRotation"))
|
|
|
|
{
|
|
|
|
auto value = parser().attribute<int>("textRotation");
|
|
|
|
record.alignment.first.rotation(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parser().attribute_present("vertical"))
|
|
|
|
{
|
|
|
|
auto value = parser().attribute<xlnt::vertical_alignment>("vertical");
|
|
|
|
record.alignment.first.vertical(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parser().attribute_present("horizontal"))
|
|
|
|
{
|
|
|
|
auto value = parser().attribute<xlnt::horizontal_alignment>("horizontal");
|
|
|
|
record.alignment.first.horizontal(value);
|
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
record.alignment.second = !apply_alignment_present || alignment_applied;
|
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
else if (parser().qname() == xml::qname(xmlns, "protection"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-11-20 06:19:38 +08:00
|
|
|
record.protection.first.locked(is_true(parser().attribute("locked")));
|
|
|
|
record.protection.first.hidden(is_true(parser().attribute("hidden")));
|
2016-09-22 07:04:16 +08:00
|
|
|
record.protection.second = !apply_protection_present || protection_applied;
|
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element, parser().qname());
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "xf");
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
|
|
|
if ((in_style_records && count != style_records.size()) ||
|
|
|
|
(!in_style_records && count != format_records.size()))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
|
|
|
throw xlnt::exception("counts don't match");
|
|
|
|
}
|
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
else if (parser().qname() == xml::qname(xmlns, "dxfs"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
auto count = parser().attribute<std::size_t>("count");
|
2016-09-22 07:04:16 +08:00
|
|
|
std::size_t processed = 0;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
while (true)
|
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().peek() == xml::parser::event_type::end_element) break;
|
|
|
|
parser().next_expect(xml::parser::event_type::start_element);
|
|
|
|
parser().next_expect(xml::parser::event_type::end_element);
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
if (count != processed)
|
|
|
|
{
|
|
|
|
throw xlnt::exception("counts don't match");
|
|
|
|
}
|
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
else if (parser().qname() == xml::qname(xmlns, "tableStyles"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
auto default_table_style = parser().attribute("defaultTableStyle");
|
|
|
|
auto default_pivot_style = parser().attribute("defaultPivotStyle");
|
|
|
|
auto count = parser().attribute<std::size_t>("count");
|
2016-09-22 07:04:16 +08:00
|
|
|
std::size_t processed = 0;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
while (true)
|
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().peek() == xml::parser::event_type::end_element) break;
|
|
|
|
parser().next_expect(xml::parser::event_type::start_element);
|
|
|
|
parser().next_expect(xml::parser::event_type::end_element);
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
if (count != processed)
|
|
|
|
{
|
|
|
|
throw xlnt::exception("counts don't match");
|
|
|
|
}
|
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
else if (parser().qname() == xml::qname(xmlns, "extLst"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-11-20 06:19:38 +08:00
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
if (parser().peek() == xml::parser::event_type::end_element) break;
|
2016-10-19 07:29:04 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element, xmlns, "ext");
|
|
|
|
parser().content(xml::parser::content_type::complex);
|
|
|
|
parser().attribute("uri");
|
|
|
|
parser().next_expect(xml::parser::event_type::start_namespace_decl);
|
2016-10-19 07:29:04 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element);
|
2016-10-19 07:29:04 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
if (parser().qname() == xml::qname(xmlns_x14, "slicerStyles"))
|
|
|
|
{
|
|
|
|
parser().attribute("defaultSlicerStyle");
|
|
|
|
}
|
|
|
|
else if (parser().qname() == xml::qname(xmlns_x15, "timelineStyles"))
|
|
|
|
{
|
|
|
|
parser().attribute("defaultTimelineStyle");
|
|
|
|
}
|
2016-10-19 07:29:04 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element);
|
2016-10-19 07:29:04 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "ext");
|
|
|
|
parser().next_expect(xml::parser::event_type::end_namespace_decl);
|
|
|
|
}
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-10-25 10:09:15 +08:00
|
|
|
else if (parser().qname() == xml::qname(xmlns, "indexedColors"))
|
|
|
|
{
|
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "indexedColors");
|
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element);
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element);
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
auto lookup_number_format = [&](std::size_t number_format_id)
|
|
|
|
{
|
|
|
|
auto result = number_format::general();
|
2016-09-10 22:05:06 +08:00
|
|
|
bool is_custom_number_format = false;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-10 22:05:06 +08:00
|
|
|
for (const auto &nf : stylesheet.number_formats)
|
|
|
|
{
|
2016-11-03 10:04:51 +08:00
|
|
|
if (nf.get_id() == number_format_id)
|
2016-09-10 22:05:06 +08:00
|
|
|
{
|
2016-11-03 10:04:51 +08:00
|
|
|
result = nf;
|
2016-09-10 22:05:06 +08:00
|
|
|
is_custom_number_format = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2016-09-10 22:05:06 +08:00
|
|
|
if (number_format_id < 164 && !is_custom_number_format)
|
|
|
|
{
|
2016-09-22 07:04:16 +08:00
|
|
|
result = number_format::from_builtin_id(number_format_id);
|
2016-09-10 22:05:06 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
return result;
|
|
|
|
};
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
std::size_t xf_id = 0;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
for (const auto &record : style_records)
|
|
|
|
{
|
2016-10-25 10:09:15 +08:00
|
|
|
auto style_data_iter = std::find_if(style_datas.begin(), style_datas.end(),
|
|
|
|
[&xf_id](const style_data &s) { return s.record_id == xf_id; });
|
|
|
|
++xf_id;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
if (style_data_iter == style_datas.end()) continue;
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2016-11-08 10:11:30 +08:00
|
|
|
auto new_style = stylesheet.create_style(style_data_iter->name);
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-11-15 21:09:17 +08:00
|
|
|
if (style_data_iter->builtin_id.second)
|
|
|
|
{
|
|
|
|
new_style.builtin_id(style_data_iter->builtin_id.first);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (style_data_iter->hidden.second)
|
|
|
|
{
|
|
|
|
new_style.hidden(style_data_iter->hidden.first);
|
|
|
|
}
|
2016-09-22 07:04:16 +08:00
|
|
|
|
|
|
|
new_style.alignment(record.alignment.first, record.alignment.second);
|
|
|
|
new_style.border(stylesheet.borders.at(record.border_id.first), record.border_id.second);
|
|
|
|
new_style.fill(stylesheet.fills.at(record.fill_id.first), record.fill_id.second);
|
|
|
|
new_style.font(stylesheet.fonts.at(record.font_id.first), record.font_id.second);
|
|
|
|
new_style.number_format(lookup_number_format(record.number_format_id.first), record.number_format_id.second);
|
|
|
|
new_style.protection(record.protection.first, record.protection.second);
|
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-11-08 10:11:30 +08:00
|
|
|
std::size_t record_index = 0;
|
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
for (const auto &record : format_records)
|
|
|
|
{
|
2016-11-08 10:11:30 +08:00
|
|
|
stylesheet.format_impls.push_back(format_impl());
|
|
|
|
auto &new_format = stylesheet.format_impls.back();
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-11-08 10:11:30 +08:00
|
|
|
new_format.id = record_index++;
|
|
|
|
new_format.parent = &stylesheet;
|
2016-11-10 08:52:18 +08:00
|
|
|
|
|
|
|
++new_format.references;
|
|
|
|
|
2016-11-08 10:11:30 +08:00
|
|
|
if (record.style_id.second)
|
|
|
|
{
|
|
|
|
new_format.style = stylesheet.style_names[record.style_id.first];
|
|
|
|
}
|
|
|
|
|
|
|
|
new_format.alignment_id = stylesheet.find_or_add(stylesheet.alignments, record.alignment.first);
|
|
|
|
new_format.alignment_applied = record.alignment.second;
|
|
|
|
new_format.border_id = record.border_id.first;
|
|
|
|
new_format.border_applied = record.border_id.second;
|
|
|
|
new_format.fill_id = record.fill_id.first;
|
|
|
|
new_format.fill_applied = record.fill_id.second;
|
|
|
|
new_format.font_id = record.font_id.first;
|
|
|
|
new_format.font_applied = record.font_id.second;
|
|
|
|
new_format.number_format_id = record.number_format_id.first;
|
|
|
|
new_format.number_format_applied = record.number_format_id.second;
|
|
|
|
new_format.protection_id = stylesheet.find_or_add(stylesheet.protections, record.protection.first);
|
|
|
|
new_format.protection_applied = record.protection.second;
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_theme()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-11-20 06:19:38 +08:00
|
|
|
target_.set_theme(theme());
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_volatile_dependencies()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_worksheet(const std::string &rel_id)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-11-10 08:52:18 +08:00
|
|
|
static const auto &xmlns = constants::get_namespace("worksheet");
|
|
|
|
static const auto &xmlns_mc = constants::get_namespace("mc");
|
|
|
|
static const auto &xmlns_r = constants::get_namespace("r");
|
|
|
|
static const auto &xmlns_x14ac = constants::get_namespace("x14ac");
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
auto title = std::find_if(target_.d_->sheet_title_rel_id_map_.begin(),
|
|
|
|
target_.d_->sheet_title_rel_id_map_.end(),
|
|
|
|
[&](const std::pair<std::string, std::string> &p) { return p.second == rel_id; })->first;
|
2016-08-06 22:40:17 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
auto id = sheet_title_id_map_[title];
|
|
|
|
auto index = sheet_title_index_map_[title];
|
2016-08-06 22:40:17 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
auto insertion_iter = target_.d_->worksheets_.begin();
|
|
|
|
while (insertion_iter != target_.d_->worksheets_.end()
|
|
|
|
&& sheet_title_index_map_[insertion_iter->title_] < index)
|
|
|
|
{
|
|
|
|
++insertion_iter;
|
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
target_.d_->worksheets_.emplace(insertion_iter, &target_, id, title);
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
auto ws = target_.get_sheet_by_id(id);
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element, xmlns, "worksheet");
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().content(xml::parser::content_type::complex);
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
while (parser().peek() == xml::parser::event_type::start_namespace_decl)
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_namespace_decl);
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().namespace_() == xmlns_x14ac)
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
|
|
|
ws.enable_x14ac();
|
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().attribute_present(xml::qname(xmlns_mc, "Ignorable")))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().attribute(xml::qname(xmlns_mc, "Ignorable"));
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
xlnt::range_reference full_range;
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
while (true)
|
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().peek() == xml::parser::event_type::end_element) break;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element);
|
|
|
|
parser().content(xml::parser::content_type::complex);
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().qname() == xml::qname(xmlns, "dimension"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
full_range = xlnt::range_reference(parser().attribute("ref"));
|
2016-09-22 07:04:16 +08:00
|
|
|
ws.d_->has_dimension_ = true;
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "dimension");
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
else if (parser().qname() == xml::qname(xmlns, "sheetViews"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
|
|
|
ws.d_->has_view_ = true;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
while (true)
|
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().attribute_map();
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().next() == xml::parser::event_type::end_element && parser().name() == "sheetViews")
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
else if (parser().qname() == xml::qname(xmlns, "sheetFormatPr"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
|
|
|
ws.d_->has_format_properties_ = true;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
while (true)
|
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().attribute_map();
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().next() == xml::parser::event_type::end_element && parser().name() == "sheetFormatPr")
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
else if (parser().qname() == xml::qname(xmlns, "mergeCells"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
auto count = std::stoull(parser().attribute("count"));
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
while (true)
|
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().peek() == xml::parser::event_type::end_element) break;
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element, xmlns, "mergeCell");
|
|
|
|
ws.merge_cells(range_reference(parser().attribute("ref")));
|
|
|
|
parser().next_expect(xml::parser::event_type::start_element, xmlns, "mergeCell");
|
2016-08-14 07:44:45 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
count--;
|
|
|
|
}
|
2016-08-14 07:44:45 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
if (count != 0)
|
|
|
|
{
|
|
|
|
throw invalid_file("sizes don't match");
|
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "mergeCells");
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
else if (parser().qname() == xml::qname(xmlns, "sheetData"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
auto &shared_strings = target_.get_shared_strings();
|
2016-08-14 07:44:45 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
while (true)
|
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().peek() == xml::parser::event_type::end_element) break;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element, xmlns, "row");
|
2016-11-20 06:19:38 +08:00
|
|
|
parser().content(xml::content::complex);
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
auto row_index = static_cast<row_t>(std::stoull(parser().attribute("r")));
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().attribute_present("ht"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
ws.get_row_properties(row_index).height = std::stold(parser().attribute("ht"));
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
if (parser().attribute_present("customHeight"))
|
|
|
|
{
|
2016-10-25 10:09:15 +08:00
|
|
|
auto custom_height = parser().attribute("customHeight");
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
if (custom_height != "false")
|
|
|
|
{
|
|
|
|
ws.get_row_properties(row_index).height = std::stold(custom_height);
|
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
}
|
2016-10-14 08:11:02 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
if (parser().attribute_present(xml::qname(xmlns_x14ac, "dyDescent")))
|
|
|
|
{
|
|
|
|
parser().attribute(xml::qname(xmlns_x14ac, "dyDescent"));
|
|
|
|
}
|
2016-10-14 08:11:02 +08:00
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
auto min_column = full_range.get_top_left().get_column_index();
|
|
|
|
auto max_column = full_range.get_bottom_right().get_column_index();
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
if (parser().attribute_present("spans"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-10-25 10:09:15 +08:00
|
|
|
std::string span_string = parser().attribute("spans");
|
|
|
|
auto colon_index = span_string.find(':');
|
|
|
|
|
|
|
|
if (colon_index != std::string::npos)
|
|
|
|
{
|
|
|
|
min_column = static_cast<column_t::index_t>(std::stoll(span_string.substr(0, colon_index)));
|
|
|
|
max_column = static_cast<column_t::index_t>(std::stoll(span_string.substr(colon_index + 1)));
|
|
|
|
}
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
if (parser().attribute_present("customFormat"))
|
|
|
|
{
|
|
|
|
parser().attribute("customFormat");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parser().attribute_present("s"))
|
|
|
|
{
|
|
|
|
parser().attribute("s");
|
|
|
|
}
|
2016-10-24 09:12:47 +08:00
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
if (parser().attribute_present("collapsed"))
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
|
|
|
parser().attribute("collapsed");
|
|
|
|
}
|
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
if (parser().attribute_present("hidden"))
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
|
|
|
parser().attribute("hidden");
|
|
|
|
}
|
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
if (parser().attribute_present("outlineLevel"))
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
|
|
|
parser().attribute("outlineLevel");
|
|
|
|
}
|
2016-10-24 09:12:47 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
while (true)
|
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().peek() == xml::parser::event_type::end_element) break;
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element, xmlns, "c");
|
2016-11-20 06:19:38 +08:00
|
|
|
parser().content(xml::content::complex);
|
2016-10-12 11:16:14 +08:00
|
|
|
auto cell = ws.get_cell(cell_reference(parser().attribute("r")));
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
auto has_type = parser().attribute_present("t");
|
|
|
|
auto type = has_type ? parser().attribute("t") : "";
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
auto has_format = parser().attribute_present("s");
|
|
|
|
auto format_id = static_cast<std::size_t>(has_format ? std::stoull(parser().attribute("s")) : 0LL);
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
auto has_value = false;
|
|
|
|
auto value_string = std::string();
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
auto has_formula = false;
|
|
|
|
auto has_shared_formula = false;
|
|
|
|
auto formula_value_string = std::string();
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
while (true)
|
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().peek() == xml::parser::event_type::end_element) break;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element);
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().qname() == xml::qname(xmlns, "v"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
|
|
|
has_value = true;
|
2016-11-21 08:38:58 +08:00
|
|
|
value_string = read_text();
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
else if (parser().qname() == xml::qname(xmlns, "f"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
|
|
|
has_formula = true;
|
2016-11-20 06:19:38 +08:00
|
|
|
has_shared_formula = parser().attribute_present("t") && parser().attribute("t") == "shared";
|
2016-11-21 08:38:58 +08:00
|
|
|
formula_value_string = read_text();
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
else if (parser().qname() == xml::qname(xmlns, "is"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element, xmlns, "t");
|
2016-11-21 08:38:58 +08:00
|
|
|
value_string = read_text();
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "t");
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-14 08:11:02 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element);
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (has_formula && !has_shared_formula && !ws.get_workbook().get_data_only())
|
|
|
|
{
|
|
|
|
cell.set_formula(formula_value_string);
|
|
|
|
}
|
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
if (has_type && (type == "inlineStr" || type == "str"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
|
|
|
cell.set_value(value_string);
|
|
|
|
}
|
|
|
|
else if (has_type && type == "s" && !has_formula)
|
|
|
|
{
|
|
|
|
auto shared_string_index = static_cast<std::size_t>(std::stoull(value_string));
|
|
|
|
auto shared_string = shared_strings.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_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_format)
|
|
|
|
{
|
2016-11-08 10:11:30 +08:00
|
|
|
cell.format(target_.get_format(format_id));
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "c");
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-10-14 08:11:02 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "row");
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "sheetData");
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
else if (parser().qname() == xml::qname(xmlns, "cols"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
|
|
|
while (true)
|
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().peek() == xml::parser::event_type::end_element) break;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element, xmlns, "col");
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
auto min = static_cast<column_t::index_t>(std::stoull(parser().attribute("min")));
|
|
|
|
auto max = static_cast<column_t::index_t>(std::stoull(parser().attribute("max")));
|
2016-11-08 10:55:40 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
auto width = std::stold(parser().attribute("width"));
|
2016-11-20 06:19:38 +08:00
|
|
|
auto column_style = parser().attribute_present("style")
|
2016-11-08 10:55:40 +08:00
|
|
|
? parser().attribute<std::size_t>("style") : static_cast<std::size_t>(0);
|
|
|
|
auto custom = parser().attribute_present("customWidth")
|
|
|
|
? is_true(parser().attribute("customWidth")) : false;
|
2016-09-22 07:04:16 +08:00
|
|
|
|
|
|
|
for (auto column = min; column <= max; column++)
|
|
|
|
{
|
2016-11-08 10:55:40 +08:00
|
|
|
column_properties props;
|
|
|
|
|
|
|
|
props.width = width;
|
|
|
|
props.style = column_style;
|
|
|
|
props.custom = custom;
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2016-11-08 10:55:40 +08:00
|
|
|
ws.add_column_properties(column, props);
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-10-14 08:11:02 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
if (parser().attribute_present("bestFit"))
|
|
|
|
{
|
|
|
|
parser().attribute("bestFit");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parser().attribute_present("collapsed"))
|
|
|
|
{
|
|
|
|
parser().attribute("collapsed");
|
|
|
|
}
|
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
if (parser().attribute_present("hidden"))
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
|
|
|
parser().attribute("hidden");
|
|
|
|
}
|
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
if (parser().attribute_present("outlineLevel"))
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
|
|
|
parser().attribute("outlineLevel");
|
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "col");
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "cols");
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
else if (parser().qname() == xml::qname(xmlns, "autoFilter"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
ws.auto_filter(xlnt::range_reference(parser().attribute("ref")));
|
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "autoFilter");
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
else if (parser().qname() == xml::qname(xmlns, "pageMargins"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
|
|
|
page_margins margins;
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
margins.set_top(parser().attribute<double>("top"));
|
|
|
|
margins.set_bottom(parser().attribute<double>("bottom"));
|
|
|
|
margins.set_left(parser().attribute<double>("left"));
|
|
|
|
margins.set_right(parser().attribute<double>("right"));
|
|
|
|
margins.set_header(parser().attribute<double>("header"));
|
|
|
|
margins.set_footer(parser().attribute<double>("footer"));
|
2016-09-22 07:04:16 +08:00
|
|
|
|
|
|
|
ws.set_page_margins(margins);
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "pageMargins");
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-10-25 10:09:15 +08:00
|
|
|
else if (parser().qname() == xml::qname(xmlns, "pageSetUpPr"))
|
|
|
|
{
|
|
|
|
parser().attribute_map();
|
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "pageSetUpPr");
|
|
|
|
}
|
|
|
|
else if (parser().qname() == xml::qname(xmlns, "printOptions"))
|
|
|
|
{
|
|
|
|
parser().attribute_map();
|
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "printOptions");
|
|
|
|
}
|
|
|
|
else if (parser().qname() == xml::qname(xmlns, "pageSetup"))
|
|
|
|
{
|
|
|
|
parser().attribute_map();
|
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "pageSetup");
|
|
|
|
}
|
|
|
|
else if (parser().qname() == xml::qname(xmlns, "sheetPr"))
|
|
|
|
{
|
|
|
|
parser().attribute_map();
|
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
while (parser().peek() != xml::parser::event_type::end_element ||
|
|
|
|
parser().qname() != xml::qname(xmlns, "sheetPr"))
|
2016-10-25 10:09:15 +08:00
|
|
|
{
|
|
|
|
if (parser().next() == xml::parser::event_type::start_element)
|
|
|
|
{
|
|
|
|
parser().attribute_map();
|
|
|
|
}
|
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
parser().next();
|
|
|
|
}
|
|
|
|
else if (parser().qname() == xml::qname(xmlns, "headerFooter"))
|
|
|
|
{
|
|
|
|
parser().attribute_map();
|
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
while (parser().peek() != xml::parser::event_type::end_element ||
|
|
|
|
parser().qname() != xml::qname(xmlns, "headerFooter"))
|
2016-10-25 10:09:15 +08:00
|
|
|
{
|
|
|
|
if (parser().next() == xml::parser::event_type::start_element)
|
|
|
|
{
|
|
|
|
parser().attribute_map();
|
|
|
|
}
|
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
parser().next();
|
|
|
|
}
|
2016-10-29 22:23:04 +08:00
|
|
|
else if (parser().qname() == xml::qname(xmlns, "legacyDrawing"))
|
|
|
|
{
|
2016-11-15 21:09:17 +08:00
|
|
|
parser().attribute(xml::qname(xmlns_r, "id"));
|
2016-10-29 22:23:04 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "legacyDrawing");
|
2016-11-15 21:09:17 +08:00
|
|
|
}
|
|
|
|
else if (parser().qname() == xml::qname(xmlns, "protectedRanges"))
|
|
|
|
{
|
|
|
|
parser().attribute_map();
|
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
while (parser().peek() != xml::parser::event_type::end_element ||
|
|
|
|
parser().qname() != xml::qname(xmlns, "protectedRanges"))
|
2016-11-15 21:09:17 +08:00
|
|
|
{
|
|
|
|
if (parser().next() == xml::parser::event_type::start_element)
|
|
|
|
{
|
|
|
|
parser().attribute_map();
|
|
|
|
}
|
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-11-15 21:09:17 +08:00
|
|
|
parser().next();
|
|
|
|
}
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "worksheet");
|
2016-10-29 22:23:04 +08:00
|
|
|
|
|
|
|
auto &manifest = target_.get_manifest();
|
|
|
|
const auto workbook_rel = manifest.get_relationship(path("/"), relationship::type::office_document);
|
|
|
|
const auto sheet_rel = manifest.get_relationship(workbook_rel.get_target().get_path(), rel_id);
|
|
|
|
path sheet_path(sheet_rel.get_source().get_path().parent().append(sheet_rel.get_target().get_path()));
|
|
|
|
|
2016-11-14 00:52:39 +08:00
|
|
|
if (manifest.has_relationship(sheet_path, xlnt::relationship::type::comments))
|
2016-10-29 22:23:04 +08:00
|
|
|
{
|
2016-11-20 06:19:38 +08:00
|
|
|
auto comments_part = manifest.canonicalize(
|
|
|
|
{workbook_rel, sheet_rel, manifest.get_relationship(sheet_path, xlnt::relationship::type::comments)});
|
2016-10-31 03:48:40 +08:00
|
|
|
|
2016-10-29 22:23:04 +08:00
|
|
|
auto receive = xml::parser::receive_default;
|
2016-11-14 00:52:39 +08:00
|
|
|
xml::parser parser(archive_->open(comments_part.string()), comments_part.string(), receive);
|
2016-10-29 22:23:04 +08:00
|
|
|
parser_ = &parser;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-11-14 00:52:39 +08:00
|
|
|
read_comments(ws);
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-11-14 00:52:39 +08:00
|
|
|
if (manifest.has_relationship(sheet_path, xlnt::relationship::type::vml_drawing))
|
2016-10-29 22:23:04 +08:00
|
|
|
{
|
2016-11-14 00:52:39 +08:00
|
|
|
auto vml_drawings_part = manifest.canonicalize({workbook_rel, sheet_rel,
|
|
|
|
manifest.get_relationship(sheet_path, xlnt::relationship::type::vml_drawing)});
|
2016-10-29 22:23:04 +08:00
|
|
|
|
2016-11-21 00:06:52 +08:00
|
|
|
xml::parser vml_parser(archive_->open(vml_drawings_part.string()), vml_drawings_part.string(), receive);
|
|
|
|
parser_ = &vml_parser;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-11-14 00:52:39 +08:00
|
|
|
read_vml_drawings(ws);
|
|
|
|
}
|
2016-10-29 22:23:04 +08:00
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Sheet Relationship Target Parts
|
|
|
|
|
2016-11-21 00:06:52 +08:00
|
|
|
void xlsx_consumer::read_vml_drawings(worksheet/*ws*/)
|
2016-11-14 00:52:39 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-10-29 22:23:04 +08:00
|
|
|
void xlsx_consumer::read_comments(worksheet ws)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-11-10 08:52:18 +08:00
|
|
|
static const auto &xmlns = xlnt::constants::get_namespace("worksheet");
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-29 22:23:04 +08:00
|
|
|
std::vector<std::string> authors;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-29 22:23:04 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element, xmlns, "comments");
|
2016-11-20 06:19:38 +08:00
|
|
|
parser().content(xml::content::complex);
|
2016-10-29 22:23:04 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element, xmlns, "authors");
|
2016-11-20 06:19:38 +08:00
|
|
|
parser().content(xml::content::complex);
|
|
|
|
|
2016-10-29 22:23:04 +08:00
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
if (parser().peek() == xml::parser::event_type::end_element) break;
|
|
|
|
|
|
|
|
parser().next_expect(xml::parser::event_type::start_element, xmlns, "author");
|
|
|
|
parser().next_expect(xml::parser::event_type::characters);
|
|
|
|
authors.push_back(parser().value());
|
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "author");
|
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-29 22:23:04 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "authors");
|
2016-10-30 04:31:30 +08:00
|
|
|
|
2016-10-29 22:23:04 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element, xmlns, "commentList");
|
2016-11-20 06:19:38 +08:00
|
|
|
parser().content(xml::content::complex);
|
|
|
|
|
2016-10-29 22:23:04 +08:00
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
if (parser().peek() == xml::parser::event_type::end_element) break;
|
|
|
|
|
|
|
|
parser().next_expect(xml::parser::event_type::start_element, xmlns, "comment");
|
2016-11-20 06:19:38 +08:00
|
|
|
parser().content(xml::content::complex);
|
2016-10-29 22:23:04 +08:00
|
|
|
|
|
|
|
auto cell_ref = parser().attribute("ref");
|
|
|
|
auto author_id = parser().attribute<std::size_t>("authorId");
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-29 22:23:04 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element, xmlns, "text");
|
2016-11-20 06:19:38 +08:00
|
|
|
parser().content(xml::content::complex);
|
2016-10-29 22:23:04 +08:00
|
|
|
|
|
|
|
// todo: this is duplicated from shared strings
|
|
|
|
formatted_text text;
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
if (parser().peek() == xml::parser::event_type::end_element) break;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-29 22:23:04 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element, xmlns, "r");
|
2016-11-20 06:19:38 +08:00
|
|
|
parser().content(xml::content::complex);
|
2016-10-30 04:31:30 +08:00
|
|
|
|
2016-10-29 22:23:04 +08:00
|
|
|
text_run run;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-29 22:23:04 +08:00
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
if (parser().peek() == xml::parser::event_type::end_element) break;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-29 22:23:04 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element);
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-29 22:23:04 +08:00
|
|
|
if (parser().name() == "t")
|
|
|
|
{
|
|
|
|
parser().next_expect(xml::parser::event_type::characters);
|
|
|
|
run.set_string(parser().value());
|
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "t");
|
|
|
|
}
|
|
|
|
else if (parser().name() == "rPr")
|
|
|
|
{
|
2016-11-20 06:19:38 +08:00
|
|
|
parser().content(xml::content::complex);
|
2016-10-30 04:31:30 +08:00
|
|
|
|
2016-10-29 22:23:04 +08:00
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
if (parser().peek() == xml::parser::event_type::end_element) break;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-29 22:23:04 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::start_element);
|
|
|
|
|
|
|
|
if (parser().qname() == xml::qname(xmlns, "sz"))
|
|
|
|
{
|
|
|
|
run.set_size(string_to_size_t(parser().attribute("val")));
|
|
|
|
}
|
|
|
|
else if (parser().qname() == xml::qname(xmlns, "rFont"))
|
|
|
|
{
|
|
|
|
run.set_font(parser().attribute("val"));
|
|
|
|
}
|
|
|
|
else if (parser().qname() == xml::qname(xmlns, "color"))
|
|
|
|
{
|
|
|
|
run.set_color(read_color(parser()));
|
|
|
|
}
|
|
|
|
else if (parser().qname() == xml::qname(xmlns, "family"))
|
|
|
|
{
|
|
|
|
run.set_family(string_to_size_t(parser().attribute("val")));
|
|
|
|
}
|
|
|
|
else if (parser().qname() == xml::qname(xmlns, "scheme"))
|
|
|
|
{
|
|
|
|
run.set_scheme(parser().attribute("val"));
|
|
|
|
}
|
|
|
|
else if (parser().qname() == xml::qname(xmlns, "b"))
|
|
|
|
{
|
|
|
|
run.set_bold(true);
|
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-29 22:23:04 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element);
|
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-29 22:23:04 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "rPr");
|
|
|
|
}
|
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-29 22:23:04 +08:00
|
|
|
text.add_run(run);
|
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "r");
|
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-29 22:23:04 +08:00
|
|
|
ws.get_cell(cell_ref).comment(comment(text, authors.at(author_id)));
|
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "text");
|
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "comment");
|
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-29 22:23:04 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "commentList");
|
|
|
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "comments");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_drawings()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
// Unknown Parts
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_unknown_parts()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_unknown_relationships()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-11-20 05:42:16 +08:00
|
|
|
std::string xlsx_consumer::read_text()
|
|
|
|
{
|
|
|
|
auto text = std::string();
|
|
|
|
|
|
|
|
while (parser().peek() == xml::parser::event_type::characters)
|
|
|
|
{
|
|
|
|
parser().next_expect(xml::parser::event_type::characters);
|
|
|
|
text.append(parser().value());
|
|
|
|
}
|
|
|
|
|
|
|
|
return text;
|
|
|
|
}
|
|
|
|
|
|
|
|
void xlsx_consumer::read_block(const std::unordered_map<xml::qname, std::function<void(xlsx_consumer &)>> &handlers)
|
|
|
|
{
|
|
|
|
auto parent_block = parser().qname();
|
|
|
|
|
|
|
|
while (parser().peek() != xml::parser::event_type::end_element)
|
|
|
|
{
|
|
|
|
parser().next_expect(xml::parser::event_type::start_element);
|
|
|
|
auto block = parser().qname();
|
|
|
|
|
|
|
|
if (handlers.count(block) == 0)
|
|
|
|
{
|
|
|
|
throw xlnt::key_not_found();
|
|
|
|
}
|
|
|
|
|
|
|
|
const auto &handler = handlers.at(block);
|
|
|
|
handler(*this);
|
|
|
|
parser().next_expect(xml::parser::event_type::end_element, block);
|
|
|
|
}
|
|
|
|
|
|
|
|
parser().next_expect(xml::parser::event_type::end_element, parent_block);
|
|
|
|
}
|
|
|
|
|
2016-11-21 07:36:52 +08:00
|
|
|
void xlsx_consumer::skip_attribute(const std::string &name)
|
|
|
|
{
|
|
|
|
if (parser().attribute_present(name))
|
|
|
|
{
|
|
|
|
parser().attribute(name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-05 13:52:05 +08:00
|
|
|
} // namespace detail
|
|
|
|
} // namepsace xlnt
|