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-09-06 11:30:25 +08:00
|
|
|
#include <cmath>
|
2016-10-30 04:31:30 +08:00
|
|
|
#include <numeric> // for std::accumulate
|
2016-09-19 09:49:37 +08:00
|
|
|
#include <string>
|
2016-08-05 13:52:05 +08:00
|
|
|
|
|
|
|
#include <detail/constants.hpp>
|
2016-11-01 08:48:43 +08:00
|
|
|
#include <detail/custom_value_traits.hpp>
|
|
|
|
#include <detail/vector_streambuf.hpp>
|
2016-08-05 13:52:05 +08:00
|
|
|
#include <detail/workbook_impl.hpp>
|
2016-11-01 08:48:43 +08:00
|
|
|
#include <detail/xlsx_producer.hpp>
|
|
|
|
#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/utils/path.hpp>
|
|
|
|
#include <xlnt/packaging/manifest.hpp>
|
|
|
|
#include <xlnt/workbook/const_worksheet_iterator.hpp>
|
|
|
|
#include <xlnt/workbook/workbook.hpp>
|
2016-08-14 02:45:26 +08:00
|
|
|
#include <xlnt/workbook/workbook_view.hpp>
|
2016-12-10 08:18:50 +08:00
|
|
|
#include <xlnt/worksheet/header_footer.hpp>
|
2016-08-05 13:52:05 +08:00
|
|
|
#include <xlnt/worksheet/worksheet.hpp>
|
|
|
|
|
2016-09-19 09:49:37 +08:00
|
|
|
using namespace std::string_literals;
|
|
|
|
|
2016-08-05 13:52:05 +08:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Returns true if d is exactly equal to an integer.
|
|
|
|
/// </summary>
|
|
|
|
bool is_integral(long double d)
|
|
|
|
{
|
2016-11-10 08:52:18 +08:00
|
|
|
return std::fabs(d - static_cast<long double>(static_cast<long long int>(d))) == 0.L;
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
namespace xlnt {
|
|
|
|
namespace detail {
|
|
|
|
|
|
|
|
xlsx_producer::xlsx_producer(const workbook &target) : source_(target)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void xlsx_producer::write(std::ostream &destination)
|
|
|
|
{
|
2016-11-01 08:48:43 +08:00
|
|
|
ZipFileWriter archive(destination);
|
2016-10-31 03:48:40 +08:00
|
|
|
archive_ = &archive;
|
2016-08-06 22:40:17 +08:00
|
|
|
populate_archive();
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Part Writing Methods
|
|
|
|
|
2016-08-06 22:40:17 +08:00
|
|
|
void xlsx_producer::populate_archive()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-09-18 23:32:59 +08:00
|
|
|
write_content_types();
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
const auto root_rels = source_.manifest().relationships(path("/"));
|
2016-09-18 23:32:59 +08:00
|
|
|
write_relationships(root_rels, path("/"));
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-09-18 23:32:59 +08:00
|
|
|
for (auto &rel : root_rels)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-11-01 08:48:43 +08:00
|
|
|
// thumbnail is binary content so we don't want to open an xml serializer stream
|
2016-12-02 21:37:50 +08:00
|
|
|
if (rel.type() == relationship_type::thumbnail)
|
2016-11-01 08:48:43 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
write_image(rel.target().path());
|
2016-11-01 08:48:43 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
begin_part(rel.target().path());
|
2016-08-06 22:40:17 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
switch (rel.type())
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::core_properties:
|
2016-09-18 23:32:59 +08:00
|
|
|
write_core_properties(rel);
|
2016-08-05 13:52:05 +08:00
|
|
|
break;
|
2016-08-12 12:22:14 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::extended_properties:
|
2016-09-18 23:32:59 +08:00
|
|
|
write_extended_properties(rel);
|
2016-08-05 13:52:05 +08:00
|
|
|
break;
|
2016-08-12 12:22:14 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::custom_properties:
|
2016-09-18 23:32:59 +08:00
|
|
|
write_custom_properties(rel);
|
2016-08-06 22:40:17 +08:00
|
|
|
break;
|
2016-08-12 12:22:14 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::office_document:
|
2016-09-18 23:32:59 +08:00
|
|
|
write_workbook(rel);
|
2016-08-05 13:52:05 +08:00
|
|
|
break;
|
2016-08-12 12:22:14 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::thumbnail: break;
|
|
|
|
case relationship_type::calculation_chain: break;
|
|
|
|
case relationship_type::worksheet: break;
|
|
|
|
case relationship_type::shared_string_table: break;
|
|
|
|
case relationship_type::stylesheet: break;
|
|
|
|
case relationship_type::theme: break;
|
|
|
|
case relationship_type::hyperlink: break;
|
|
|
|
case relationship_type::chartsheet: 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::connections: break;
|
|
|
|
case relationship_type::custom_property: break;
|
|
|
|
case relationship_type::custom_xml_mappings: break;
|
|
|
|
case relationship_type::dialogsheet: break;
|
|
|
|
case relationship_type::drawings: break;
|
|
|
|
case relationship_type::external_workbook_references: break;
|
|
|
|
case relationship_type::metadata: break;
|
|
|
|
case relationship_type::pivot_table: break;
|
|
|
|
case relationship_type::pivot_table_cache_definition: break;
|
|
|
|
case relationship_type::pivot_table_cache_records: break;
|
|
|
|
case relationship_type::query_table: break;
|
|
|
|
case relationship_type::shared_workbook_revision_headers: 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::volatile_dependencies: break;
|
|
|
|
case relationship_type::image: break;
|
2016-08-12 12:22:14 +08:00
|
|
|
}
|
2016-08-06 22:40:17 +08:00
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
|
|
|
|
// Unknown Parts
|
|
|
|
|
|
|
|
void write_unknown_parts();
|
|
|
|
void write_unknown_relationships();
|
2016-10-31 03:48:40 +08:00
|
|
|
|
|
|
|
end_part();
|
|
|
|
}
|
|
|
|
|
|
|
|
void xlsx_producer::end_part()
|
|
|
|
{
|
|
|
|
if (current_part_serializer_)
|
|
|
|
{
|
|
|
|
current_part_serializer_.reset();
|
|
|
|
}
|
2016-11-08 10:11:30 +08:00
|
|
|
|
|
|
|
archive_->close();
|
2016-10-31 03:48:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void xlsx_producer::begin_part(const path &part)
|
|
|
|
{
|
|
|
|
end_part();
|
2016-11-08 10:11:30 +08:00
|
|
|
current_part_serializer_.reset(new xml::serializer(archive_->open(part.string()), part.string()));
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Package Parts
|
|
|
|
|
2016-09-18 23:32:59 +08:00
|
|
|
void xlsx_producer::write_content_types()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-10-31 03:48:40 +08:00
|
|
|
const auto content_types_path = path("[Content_Types].xml");
|
|
|
|
begin_part(content_types_path);
|
2016-09-17 10:59:13 +08:00
|
|
|
|
2016-09-19 09:49:37 +08:00
|
|
|
const auto xmlns = "http://schemas.openxmlformats.org/package/2006/content-types"s;
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-10-31 03:48:40 +08:00
|
|
|
serializer().start_element(xmlns, "Types");
|
|
|
|
serializer().namespace_decl(xmlns, "");
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
for (const auto &extension : source_.manifest().extensions_with_default_types())
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-10-31 03:48:40 +08:00
|
|
|
serializer().start_element(xmlns, "Default");
|
|
|
|
serializer().attribute("Extension", extension);
|
|
|
|
serializer().attribute("ContentType",
|
2016-12-02 21:37:50 +08:00
|
|
|
source_.manifest().default_type(extension));
|
2016-10-31 03:48:40 +08:00
|
|
|
serializer().end_element(xmlns, "Default");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
for (const auto &part : source_.manifest().parts_with_overriden_types())
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-10-31 03:48:40 +08:00
|
|
|
serializer().start_element(xmlns, "Override");
|
|
|
|
serializer().attribute("PartName", part.resolve(path("/")).string());
|
|
|
|
serializer().attribute("ContentType",
|
2016-12-02 21:37:50 +08:00
|
|
|
source_.manifest().override_type(part));
|
2016-10-31 03:48:40 +08:00
|
|
|
serializer().end_element(xmlns, "Override");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
2016-09-17 10:59:13 +08:00
|
|
|
|
2016-10-31 03:48:40 +08:00
|
|
|
serializer().end_element(xmlns, "Types");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-11-10 08:52:18 +08:00
|
|
|
void xlsx_producer::write_extended_properties(const relationship &/*rel*/)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-09-19 09:49:37 +08:00
|
|
|
const auto xmlns = "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties"s;
|
|
|
|
const auto xmlns_vt = "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"s;
|
|
|
|
|
|
|
|
serializer().start_element(xmlns, "Properties");
|
|
|
|
serializer().namespace_decl(xmlns, "");
|
|
|
|
serializer().namespace_decl(xmlns_vt, "vt");
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (source_.has_core_property("Application"))
|
|
|
|
{
|
|
|
|
serializer().element(xmlns, "Application", source_.core_property("Application"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (source_.has_core_property("DocSecurity"))
|
|
|
|
{
|
|
|
|
serializer().element(xmlns, "DocSecurity", source_.core_property("DocSecurity"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (source_.has_core_property("ScaleCrop"))
|
|
|
|
{
|
|
|
|
serializer().element(xmlns, "ScaleCrop", source_.core_property("ScaleCrop"));
|
|
|
|
}
|
2016-09-19 09:49:37 +08:00
|
|
|
|
|
|
|
serializer().start_element(xmlns, "HeadingPairs");
|
|
|
|
serializer().start_element(xmlns_vt, "vector");
|
|
|
|
serializer().attribute("size", "2");
|
|
|
|
serializer().attribute("baseType", "variant");
|
|
|
|
serializer().start_element(xmlns_vt, "variant");
|
|
|
|
serializer().element(xmlns_vt, "lpstr", "Worksheets");
|
|
|
|
serializer().end_element(xmlns_vt, "variant");
|
|
|
|
serializer().start_element(xmlns_vt, "variant");
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().element(xmlns_vt, "i4", source_.sheet_titles().size());
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().end_element(xmlns_vt, "variant");
|
|
|
|
serializer().end_element(xmlns_vt, "vector");
|
|
|
|
serializer().end_element(xmlns, "HeadingPairs");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns, "TitlesOfParts");
|
|
|
|
serializer().start_element(xmlns_vt, "vector");
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().attribute("size", source_.sheet_titles().size());
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().attribute("baseType", "lpstr");
|
2016-08-05 13:52:05 +08:00
|
|
|
|
|
|
|
for (auto ws : source_)
|
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().element(xmlns_vt, "lpstr", ws.title());
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
2016-08-13 11:06:25 +08:00
|
|
|
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().end_element(xmlns_vt, "vector");
|
|
|
|
serializer().end_element(xmlns, "TitlesOfParts");
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (source_.has_core_property("Company"))
|
2016-08-13 11:06:25 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().element(xmlns, "Company", source_.core_property("Company"));
|
2016-08-13 11:06:25 +08:00
|
|
|
}
|
2016-12-02 21:37:50 +08:00
|
|
|
|
|
|
|
if (source_.has_core_property("LinksUpToDate"))
|
|
|
|
{
|
|
|
|
serializer().element(xmlns, "LinksUpToDate", source_.core_property("LinksUpToDate"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (source_.has_core_property("LinksUpToDate"))
|
|
|
|
{
|
|
|
|
serializer().element(xmlns, "SharedDoc", source_.core_property("SharedDoc"));
|
|
|
|
}
|
2016-09-19 09:49:37 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (source_.has_core_property("LinksUpToDate"))
|
|
|
|
{
|
|
|
|
serializer().element(xmlns, "HyperlinksChanged", source_.core_property("HyperlinksChanged"));
|
|
|
|
}
|
2016-08-13 11:06:25 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (source_.has_core_property("LinksUpToDate"))
|
|
|
|
{
|
|
|
|
serializer().element(xmlns, "AppVersion", source_.core_property("AppVersion"));
|
|
|
|
}
|
2016-09-22 07:04:16 +08:00
|
|
|
|
|
|
|
serializer().end_element(xmlns, "Properties");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-11-10 08:52:18 +08:00
|
|
|
void xlsx_producer::write_core_properties(const relationship &/*rel*/)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
static const auto &xmlns_cp = constants::namespace_("core-properties");
|
|
|
|
static const auto &xmlns_dc = constants::namespace_("dc");
|
|
|
|
static const auto &xmlns_dcterms = constants::namespace_("dcterms");
|
|
|
|
static const auto &xmlns_dcmitype = constants::namespace_("dcmitype");
|
|
|
|
static const auto &xmlns_xsi = constants::namespace_("xsi");
|
2016-09-19 09:49:37 +08:00
|
|
|
|
|
|
|
serializer().start_element(xmlns_cp, "coreProperties");
|
|
|
|
serializer().namespace_decl(xmlns_cp, "cp");
|
|
|
|
serializer().namespace_decl(xmlns_dc, "dc");
|
|
|
|
serializer().namespace_decl(xmlns_dcterms, "dcterms");
|
|
|
|
serializer().namespace_decl(xmlns_dcmitype, "dcmitype");
|
|
|
|
serializer().namespace_decl(xmlns_xsi, "xsi");
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (source_.has_core_property("creator"))
|
|
|
|
{
|
|
|
|
serializer().element(xmlns_dc, "creator", source_.core_property("creator"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (source_.has_core_property("lastModifiedBy"))
|
|
|
|
{
|
|
|
|
serializer().element(xmlns_cp, "lastModifiedBy", source_.core_property("lastModifiedBy"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (source_.has_core_property("created"))
|
|
|
|
{
|
|
|
|
serializer().start_element(xmlns_dcterms, "created");
|
|
|
|
serializer().attribute(xmlns_xsi, "type", "dcterms:W3CDTF");
|
|
|
|
serializer().characters(source_.core_property("created"));
|
|
|
|
serializer().end_element(xmlns_dcterms, "created");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (source_.has_core_property("modified"))
|
|
|
|
{
|
|
|
|
serializer().start_element(xmlns_dcterms, "modified");
|
|
|
|
serializer().attribute(xmlns_xsi, "type", "dcterms:W3CDTF");
|
|
|
|
serializer().characters(source_.core_property("modified"));
|
|
|
|
serializer().end_element(xmlns_dcterms, "modified");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (source_.has_title())
|
2016-08-13 11:06:25 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().element(xmlns_dc, "title", source_.title());
|
2016-08-13 11:06:25 +08:00
|
|
|
}
|
2016-09-19 09:49:37 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (source_.has_core_property("description"))
|
|
|
|
{
|
|
|
|
serializer().element(xmlns_dc, "description", source_.core_property("description"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (source_.has_core_property("subject"))
|
2016-09-19 09:49:37 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().element(xmlns_dc, "subject", source_.core_property("subject"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (source_.has_core_property("keywords"))
|
|
|
|
{
|
|
|
|
serializer().element(xmlns_cp, "keywords", source_.core_property("keywords"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (source_.has_core_property("category"))
|
|
|
|
{
|
|
|
|
serializer().element(xmlns_cp, "category", source_.core_property("category"));
|
2016-09-19 09:49:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
serializer().end_element(xmlns_cp, "coreProperties");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-11-10 08:52:18 +08:00
|
|
|
void xlsx_producer::write_custom_properties(const relationship &/*rel*/)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-09-18 23:32:59 +08:00
|
|
|
serializer().element("Properties");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Write SpreadsheetML-Specific Package Parts
|
|
|
|
|
2016-09-18 23:32:59 +08:00
|
|
|
void xlsx_producer::write_workbook(const relationship &rel)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
std::size_t num_visible = 0;
|
2016-08-13 11:06:25 +08:00
|
|
|
bool any_defined_names = false;
|
2016-08-05 13:52:05 +08:00
|
|
|
|
|
|
|
for (auto ws : source_)
|
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
if (!ws.has_page_setup() || ws.page_setup().sheet_state() == sheet_state::visible)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
num_visible++;
|
|
|
|
}
|
2016-08-13 11:06:25 +08:00
|
|
|
|
|
|
|
if (ws.has_auto_filter())
|
|
|
|
{
|
|
|
|
any_defined_names = true;
|
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (num_visible == 0)
|
|
|
|
{
|
2016-08-16 12:23:49 +08:00
|
|
|
throw no_visible_worksheets();
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
static const auto &xmlns = constants::namespace_("workbook");
|
|
|
|
static const auto &xmlns_r = constants::namespace_("r");
|
|
|
|
static const auto &xmlns_s = constants::namespace_("spreadsheetml");
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-09-18 23:32:59 +08:00
|
|
|
serializer().start_element(xmlns, "workbook");
|
|
|
|
serializer().namespace_decl(xmlns, "");
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().namespace_decl(xmlns_r, "r");
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-08-14 02:45:26 +08:00
|
|
|
if (source_.has_file_version())
|
|
|
|
{
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().start_element(xmlns, "fileVersion");
|
2016-08-14 02:45:26 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().attribute("appName", source_.app_name());
|
|
|
|
serializer().attribute("lastEdited", source_.last_edited());
|
|
|
|
serializer().attribute("lowestEdited", source_.lowest_edited());
|
|
|
|
serializer().attribute("rupBuild", source_.rup_build());
|
2016-09-19 09:49:37 +08:00
|
|
|
|
|
|
|
serializer().end_element(xmlns, "fileVersion");
|
2016-08-14 02:45:26 +08:00
|
|
|
}
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (source_.has_code_name() || source_.base_date() == calendar::mac_1904)
|
2016-08-14 02:45:26 +08:00
|
|
|
{
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().start_element(xmlns, "workbookPr");
|
2016-08-13 11:06:25 +08:00
|
|
|
|
2016-08-14 02:45:26 +08:00
|
|
|
if (source_.has_code_name())
|
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().attribute("codeName", source_.code_name());
|
2016-08-14 02:45:26 +08:00
|
|
|
}
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (source_.base_date() == calendar::mac_1904)
|
2016-09-19 09:49:37 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().attribute("date1904", "1");
|
2016-09-19 09:49:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
serializer().end_element(xmlns, "workbookPr");
|
2016-08-14 02:45:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (source_.has_view())
|
|
|
|
{
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().start_element(xmlns, "bookViews");
|
|
|
|
serializer().start_element(xmlns, "workbookView");
|
2016-08-14 02:45:26 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
const auto &view = source_.view();
|
2016-08-14 02:45:26 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().attribute("activeTab", "0");
|
|
|
|
serializer().attribute("autoFilterDateGrouping", "1");
|
|
|
|
serializer().attribute("firstSheet", "0");
|
|
|
|
serializer().attribute("minimized", "0");
|
|
|
|
serializer().attribute("showHorizontalScroll", "1");
|
|
|
|
serializer().attribute("showSheetTabs", "1");
|
|
|
|
serializer().attribute("showVerticalScroll", "1");
|
|
|
|
serializer().attribute("visibility", "visible");
|
2016-09-20 06:52:11 +08:00
|
|
|
|
|
|
|
serializer().attribute("xWindow", view.x_window);
|
|
|
|
serializer().attribute("yWindow", view.y_window);
|
|
|
|
serializer().attribute("windowWidth", view.window_width);
|
|
|
|
serializer().attribute("windowHeight", view.window_height);
|
|
|
|
serializer().attribute("tabRatio", view.tab_ratio);
|
2016-09-19 09:49:37 +08:00
|
|
|
|
|
|
|
serializer().end_element(xmlns, "workbookView");
|
|
|
|
serializer().end_element(xmlns, "bookViews");
|
2016-08-14 02:45:26 +08:00
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-09-18 23:32:59 +08:00
|
|
|
serializer().start_element(xmlns, "sheets");
|
2016-09-19 09:49:37 +08:00
|
|
|
|
2016-08-13 11:06:25 +08:00
|
|
|
if (any_defined_names)
|
|
|
|
{
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().element(xmlns, "definedNames", "");
|
2016-08-13 11:06:25 +08:00
|
|
|
}
|
2016-08-06 22:40:17 +08:00
|
|
|
|
2016-11-10 08:52:18 +08:00
|
|
|
#pragma clang diagnostic push
|
|
|
|
#pragma clang diagnostic ignored "-Wrange-loop-analysis"
|
2016-08-05 13:52:05 +08:00
|
|
|
for (const auto ws : source_)
|
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
auto sheet_rel_id = source_.d_->sheet_title_rel_id_map_[ws.title()];
|
|
|
|
auto sheet_rel = source_.d_->manifest_.relationship(rel.target().path(), sheet_rel_id);
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-09-18 23:32:59 +08:00
|
|
|
serializer().start_element(xmlns, "sheet");
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().attribute("name", ws.title());
|
|
|
|
serializer().attribute("sheetId", ws.id());
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (ws.has_page_setup() && ws.sheet_state() == xlnt::sheet_state::hidden)
|
2016-08-06 22:40:17 +08:00
|
|
|
{
|
2016-09-18 23:32:59 +08:00
|
|
|
serializer().attribute("state", "hidden");
|
2016-08-06 22:40:17 +08:00
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().attribute(xmlns_r, "id", sheet_rel_id);
|
|
|
|
|
2016-08-06 22:40:17 +08:00
|
|
|
if (ws.has_auto_filter())
|
|
|
|
{
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().start_element(xmlns, "definedName");
|
|
|
|
|
|
|
|
serializer().attribute("name", "_xlnm._FilterDatabase");
|
|
|
|
serializer().attribute("hidden", write_bool(true));
|
|
|
|
serializer().attribute("localSheetId", "0");
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().characters("'" + ws.title() + "'!"
|
|
|
|
+ range_reference::make_absolute(ws.auto_filter()).to_string());
|
2016-09-19 09:49:37 +08:00
|
|
|
|
|
|
|
serializer().end_element(xmlns, "definedName");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
2016-09-17 10:59:13 +08:00
|
|
|
|
2016-09-18 23:32:59 +08:00
|
|
|
serializer().end_element(xmlns, "sheet");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
2016-11-10 08:52:18 +08:00
|
|
|
#pragma clang diagnostic pop
|
2016-09-19 09:49:37 +08:00
|
|
|
|
|
|
|
serializer().end_element(xmlns, "sheets");
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().start_element(xmlns, "calcPr");
|
|
|
|
serializer().attribute("calcId", 150000);
|
|
|
|
serializer().attribute("calcMode", "auto");
|
|
|
|
serializer().attribute("fullCalcOnLoad", "1");
|
|
|
|
serializer().attribute("concurrentCalc", "0");
|
|
|
|
serializer().end_element(xmlns, "calcPr");
|
2016-08-14 02:45:26 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (!source_.named_ranges().empty())
|
2016-08-14 02:45:26 +08:00
|
|
|
{
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().start_element(xmlns, "definedNames");
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
for (auto &named_range : source_.named_ranges())
|
2016-08-14 02:45:26 +08:00
|
|
|
{
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().start_element(xmlns_s, "definedName");
|
|
|
|
serializer().namespace_decl(xmlns_s, "s");
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().attribute("name", named_range.name());
|
|
|
|
const auto &target = named_range.targets().front();
|
|
|
|
serializer().characters("'" + target.first.title()
|
2016-09-19 09:49:37 +08:00
|
|
|
+ "\'!" + target.second.to_string());
|
|
|
|
serializer().end_element(xmlns_s, "definedName");
|
2016-08-14 02:45:26 +08:00
|
|
|
}
|
2016-09-19 09:49:37 +08:00
|
|
|
|
|
|
|
serializer().end_element(xmlns, "definedNames");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
2016-08-13 11:06:25 +08:00
|
|
|
|
2016-09-18 23:32:59 +08:00
|
|
|
serializer().end_element(xmlns, "workbook");
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
auto workbook_rels = source_.manifest().relationships(rel.target().path());
|
|
|
|
write_relationships(workbook_rels, rel.target().path());
|
2016-08-12 12:22:14 +08:00
|
|
|
|
2016-09-18 23:32:59 +08:00
|
|
|
for (const auto &child_rel : workbook_rels)
|
2016-08-12 12:22:14 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
path archive_path(child_rel.source().path().parent().append(child_rel.target().path()));
|
2016-10-31 03:48:40 +08:00
|
|
|
begin_part(archive_path);
|
2016-08-12 12:22:14 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
switch (child_rel.type())
|
2016-08-12 12:22:14 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::calculation_chain:
|
2016-09-18 23:32:59 +08:00
|
|
|
write_calculation_chain(child_rel);
|
2016-08-12 12:22:14 +08:00
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::chartsheet:
|
2016-09-18 23:32:59 +08:00
|
|
|
write_chartsheet(child_rel);
|
2016-08-12 12:22:14 +08:00
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::connections:
|
2016-09-18 23:32:59 +08:00
|
|
|
write_connections(child_rel);
|
2016-08-12 12:22:14 +08:00
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::custom_xml_mappings:
|
2016-09-18 23:32:59 +08:00
|
|
|
write_custom_xml_mappings(child_rel);
|
2016-08-12 12:22:14 +08:00
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::dialogsheet:
|
2016-09-18 23:32:59 +08:00
|
|
|
write_dialogsheet(child_rel);
|
2016-08-12 12:22:14 +08:00
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::external_workbook_references:
|
2016-09-18 23:32:59 +08:00
|
|
|
write_external_workbook_references(child_rel);
|
2016-08-12 12:22:14 +08:00
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::metadata:
|
2016-09-18 23:32:59 +08:00
|
|
|
write_metadata(child_rel);
|
2016-08-12 12:22:14 +08:00
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::pivot_table:
|
2016-09-18 23:32:59 +08:00
|
|
|
write_pivot_table(child_rel);
|
2016-08-12 12:22:14 +08:00
|
|
|
break;
|
2016-08-18 19:34:18 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::shared_string_table:
|
2016-09-18 23:32:59 +08:00
|
|
|
write_shared_string_table(child_rel);
|
2016-08-12 12:22:14 +08:00
|
|
|
break;
|
2016-08-18 19:34:18 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::shared_workbook_revision_headers:
|
2016-09-18 23:32:59 +08:00
|
|
|
write_shared_workbook_revision_headers(child_rel);
|
2016-08-12 12:22:14 +08:00
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::stylesheet:
|
2016-09-18 23:32:59 +08:00
|
|
|
write_styles(child_rel);
|
2016-08-12 12:22:14 +08:00
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::theme:
|
2016-09-18 23:32:59 +08:00
|
|
|
write_theme(child_rel);
|
2016-08-12 12:22:14 +08:00
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::volatile_dependencies:
|
2016-09-18 23:32:59 +08:00
|
|
|
write_volatile_dependencies(child_rel);
|
2016-08-12 12:22:14 +08:00
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::worksheet:
|
2016-09-18 23:32:59 +08:00
|
|
|
write_worksheet(child_rel);
|
2016-08-12 12:22:14 +08:00
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::office_document: break;
|
|
|
|
case relationship_type::thumbnail: break;
|
|
|
|
case relationship_type::extended_properties: break;
|
|
|
|
case relationship_type::core_properties: 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::custom_properties: 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;
|
|
|
|
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-08-12 12:22:14 +08:00
|
|
|
}
|
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Write Workbook Relationship Target Parts
|
|
|
|
|
2016-11-10 08:52:18 +08:00
|
|
|
void xlsx_producer::write_calculation_chain(const relationship &/*rel*/)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-09-18 23:32:59 +08:00
|
|
|
serializer().start_element("calcChain");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-11-10 08:52:18 +08:00
|
|
|
void xlsx_producer::write_chartsheet(const relationship &/*rel*/)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-09-18 23:32:59 +08:00
|
|
|
serializer().start_element("chartsheet");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-11-10 08:52:18 +08:00
|
|
|
void xlsx_producer::write_connections(const relationship &/*rel*/)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-09-18 23:32:59 +08:00
|
|
|
serializer().start_element("connections");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-11-10 08:52:18 +08:00
|
|
|
void xlsx_producer::write_custom_xml_mappings(const relationship &/*rel*/)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-09-18 23:32:59 +08:00
|
|
|
serializer().start_element("MapInfo");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-11-10 08:52:18 +08:00
|
|
|
void xlsx_producer::write_dialogsheet(const relationship &/*rel*/)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-09-18 23:32:59 +08:00
|
|
|
serializer().start_element("dialogsheet");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-11-10 08:52:18 +08:00
|
|
|
void xlsx_producer::write_external_workbook_references(const relationship &/*rel*/)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-09-18 23:32:59 +08:00
|
|
|
serializer().start_element("externalLink");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-11-10 08:52:18 +08:00
|
|
|
void xlsx_producer::write_metadata(const relationship &/*rel*/)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-09-18 23:32:59 +08:00
|
|
|
serializer().start_element("metadata");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-11-10 08:52:18 +08:00
|
|
|
void xlsx_producer::write_pivot_table(const relationship &/*rel*/)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-09-18 23:32:59 +08:00
|
|
|
serializer().start_element("pivotTableDefinition");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-11-10 08:52:18 +08:00
|
|
|
void xlsx_producer::write_shared_string_table(const relationship &/*rel*/)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
static const auto &xmlns = constants::namespace_("spreadsheetml");
|
2016-09-19 09:49:37 +08:00
|
|
|
|
|
|
|
serializer().start_element(xmlns, "sst");
|
|
|
|
serializer().namespace_decl(xmlns, "");
|
|
|
|
|
|
|
|
// todo: is there a more elegant way to get this number?
|
2016-09-12 02:57:34 +08:00
|
|
|
std::size_t string_count = 0;
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-11-10 08:52:18 +08:00
|
|
|
#pragma clang diagnostic push
|
|
|
|
#pragma clang diagnostic ignored "-Wrange-loop-analysis"
|
2016-09-12 02:57:34 +08:00
|
|
|
for (const auto ws : source_)
|
|
|
|
{
|
2016-10-26 08:01:09 +08:00
|
|
|
auto dimension = ws.calculate_dimension();
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
for (xlnt::row_t row = dimension.top_left().row();
|
|
|
|
row <= dimension.bottom_right().row(); ++row)
|
2016-09-12 02:57:34 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
for (xlnt::column_t column = dimension.top_left().column();
|
|
|
|
column <= dimension.bottom_right().column(); ++column)
|
2016-09-12 02:57:34 +08:00
|
|
|
{
|
2016-10-26 08:01:09 +08:00
|
|
|
if (ws.has_cell(xlnt::cell_reference(column, row)))
|
2016-09-12 02:57:34 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
string_count += (ws.cell(xlnt::cell_reference(column, row))
|
|
|
|
.data_type() == cell::type::string) ? 1 : 0;
|
2016-09-12 02:57:34 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-11-10 08:52:18 +08:00
|
|
|
#pragma clang diagnostic pop
|
2016-09-12 02:57:34 +08:00
|
|
|
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().attribute("count", string_count);
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().attribute("uniqueCount", source_.shared_strings().size());
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
for (const auto &string : source_.shared_strings())
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-10-29 22:23:04 +08:00
|
|
|
if (string.runs().size() == 1 && !string.runs().at(0).has_formatting())
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().start_element(xmlns, "si");
|
2016-10-29 22:23:04 +08:00
|
|
|
serializer().element(xmlns, "t", string.plain_text());
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().end_element(xmlns, "si");
|
|
|
|
|
|
|
|
continue;
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().start_element(xmlns, "si");
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-10-29 22:23:04 +08:00
|
|
|
for (const auto &run : string.runs())
|
2016-09-19 09:49:37 +08:00
|
|
|
{
|
|
|
|
serializer().start_element(xmlns, "r");
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-09-19 09:49:37 +08:00
|
|
|
if (run.has_formatting())
|
|
|
|
{
|
|
|
|
serializer().start_element(xmlns, "rPr");
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-09-19 09:49:37 +08:00
|
|
|
if (run.has_size())
|
|
|
|
{
|
|
|
|
serializer().start_element(xmlns, "sz");
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().attribute("val", run.size());
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().end_element(xmlns, "sz");
|
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-09-19 09:49:37 +08:00
|
|
|
if (run.has_color())
|
|
|
|
{
|
|
|
|
serializer().start_element(xmlns, "color");
|
2016-12-02 21:37:50 +08:00
|
|
|
write_color(run.color());
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().end_element(xmlns, "color");
|
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-09-19 09:49:37 +08:00
|
|
|
if (run.has_font())
|
|
|
|
{
|
|
|
|
serializer().start_element(xmlns, "rFont");
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().attribute("val", run.font());
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().end_element(xmlns, "rFont");
|
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-09-19 09:49:37 +08:00
|
|
|
if (run.has_family())
|
|
|
|
{
|
|
|
|
serializer().start_element(xmlns, "family");
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().attribute("val", run.family());
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().end_element(xmlns, "family");
|
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-09-19 09:49:37 +08:00
|
|
|
if (run.has_scheme())
|
|
|
|
{
|
|
|
|
serializer().start_element(xmlns, "scheme");
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().attribute("val", run.scheme());
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().end_element(xmlns, "scheme");
|
|
|
|
}
|
2016-10-30 04:31:30 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (run.bold())
|
2016-10-30 04:31:30 +08:00
|
|
|
{
|
|
|
|
serializer().start_element(xmlns, "b");
|
|
|
|
serializer().end_element(xmlns, "b");
|
|
|
|
}
|
2016-09-19 09:49:37 +08:00
|
|
|
|
|
|
|
serializer().end_element(xmlns, "rPr");
|
|
|
|
}
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().element(xmlns, "t", run.string());
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().end_element(xmlns, "r");
|
|
|
|
}
|
|
|
|
|
|
|
|
serializer().end_element(xmlns, "si");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
2016-09-19 09:49:37 +08:00
|
|
|
|
|
|
|
serializer().end_element(xmlns, "sst");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-11-10 08:52:18 +08:00
|
|
|
void xlsx_producer::write_shared_workbook_revision_headers(const relationship &/*rel*/)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-09-18 23:32:59 +08:00
|
|
|
serializer().start_element("headers");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-11-10 08:52:18 +08:00
|
|
|
void xlsx_producer::write_shared_workbook(const relationship &/*rel*/)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-09-18 23:32:59 +08:00
|
|
|
serializer().start_element("revisions");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-11-10 08:52:18 +08:00
|
|
|
void xlsx_producer::write_shared_workbook_user_data(const relationship &/*rel*/)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-09-18 23:32:59 +08:00
|
|
|
serializer().start_element("users");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-11-10 08:52:18 +08:00
|
|
|
void xlsx_producer::write_styles(const relationship &/*rel*/)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
static const auto &xmlns = constants::namespace_("spreadsheetml");
|
2016-09-19 09:49:37 +08:00
|
|
|
|
|
|
|
serializer().start_element(xmlns, "styleSheet");
|
|
|
|
serializer().namespace_decl(xmlns, "");
|
2016-08-18 19:34:18 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
const auto &stylesheet = source_.impl().stylesheet_.get();
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-08-18 19:34:18 +08:00
|
|
|
// Number Formats
|
|
|
|
|
2016-08-05 13:52:05 +08:00
|
|
|
if (!stylesheet.number_formats.empty())
|
|
|
|
{
|
2016-09-19 09:49:37 +08:00
|
|
|
const auto &number_formats = stylesheet.number_formats;
|
2016-08-18 19:34:18 +08:00
|
|
|
|
2016-11-08 10:11:30 +08:00
|
|
|
auto num_custom = std::count_if(number_formats.begin(), number_formats.end(),
|
2016-12-02 21:37:50 +08:00
|
|
|
[](const number_format &nf) { return nf.id() >= 164; });
|
2016-11-08 10:11:30 +08:00
|
|
|
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().start_element(xmlns, "numFmts");
|
2016-11-08 10:11:30 +08:00
|
|
|
serializer().attribute("count", num_custom);
|
2016-08-18 19:34:18 +08:00
|
|
|
|
|
|
|
for (const auto &num_fmt : number_formats)
|
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
if (num_fmt.id() < 164) continue;
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().start_element(xmlns, "numFmt");
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().attribute("numFmtId", num_fmt.id());
|
|
|
|
serializer().attribute("formatCode", num_fmt.format_string());
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().end_element(xmlns, "numFmt");
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
2016-09-19 09:49:37 +08:00
|
|
|
|
|
|
|
serializer().end_element(xmlns, "numFmts");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-08-18 19:34:18 +08:00
|
|
|
// Fonts
|
|
|
|
|
2016-08-05 13:52:05 +08:00
|
|
|
if (!stylesheet.fonts.empty())
|
|
|
|
{
|
2016-08-18 19:34:18 +08:00
|
|
|
const auto &fonts = stylesheet.fonts;
|
|
|
|
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().start_element(xmlns, "fonts");
|
|
|
|
serializer().attribute("count", fonts.size());
|
2016-08-18 19:34:18 +08:00
|
|
|
|
|
|
|
for (const auto ¤t_font : fonts)
|
|
|
|
{
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().start_element(xmlns, "font");
|
2016-08-18 19:34:18 +08:00
|
|
|
|
|
|
|
if (current_font.bold())
|
|
|
|
{
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().start_element(xmlns, "b");
|
|
|
|
serializer().attribute("val", write_bool(true));
|
|
|
|
serializer().end_element(xmlns, "b");
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (current_font.italic())
|
|
|
|
{
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().start_element(xmlns, "i");
|
|
|
|
serializer().attribute("val", write_bool(true));
|
|
|
|
serializer().end_element(xmlns, "i");
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (current_font.underlined())
|
|
|
|
{
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().start_element(xmlns, "u");
|
|
|
|
serializer().attribute("val", current_font.underline());
|
|
|
|
serializer().end_element(xmlns, "u");
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (current_font.strikethrough())
|
|
|
|
{
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().start_element(xmlns, "strike");
|
|
|
|
serializer().attribute("val", write_bool(true));
|
|
|
|
serializer().end_element(xmlns, "strike");
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
|
|
|
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().start_element(xmlns, "sz");
|
|
|
|
serializer().attribute("val", current_font.size());
|
|
|
|
serializer().end_element(xmlns, "sz");
|
2016-08-18 19:34:18 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (current_font.has_color())
|
2016-08-18 19:34:18 +08:00
|
|
|
{
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().start_element(xmlns, "color");
|
2016-12-02 21:37:50 +08:00
|
|
|
write_color(current_font.color());
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().end_element(xmlns, "color");
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
|
|
|
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().start_element(xmlns, "name");
|
|
|
|
serializer().attribute("val", current_font.name());
|
|
|
|
serializer().end_element(xmlns, "name");
|
2016-08-18 19:34:18 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (current_font.has_family())
|
2016-08-18 19:34:18 +08:00
|
|
|
{
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().start_element(xmlns, "family");
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().attribute("val", current_font.family());
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().end_element(xmlns, "family");
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (current_font.has_scheme())
|
2016-08-18 19:34:18 +08:00
|
|
|
{
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().start_element(xmlns, "scheme");
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().attribute("val", current_font.scheme());
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().end_element(xmlns, "scheme");
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
2016-09-20 06:52:11 +08:00
|
|
|
|
|
|
|
serializer().end_element(xmlns, "font");
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
2016-09-20 06:52:11 +08:00
|
|
|
|
|
|
|
serializer().end_element(xmlns, "fonts");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
2016-09-20 06:52:11 +08:00
|
|
|
|
2016-08-18 19:34:18 +08:00
|
|
|
// Fills
|
|
|
|
|
2016-08-05 13:52:05 +08:00
|
|
|
if (!stylesheet.fills.empty())
|
|
|
|
{
|
2016-08-18 19:34:18 +08:00
|
|
|
const auto &fills = stylesheet.fills;
|
|
|
|
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().start_element(xmlns, "fills");
|
|
|
|
serializer().attribute("count", fills.size());
|
2016-08-18 19:34:18 +08:00
|
|
|
|
|
|
|
for (auto &fill_ : fills)
|
|
|
|
{
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().start_element(xmlns, "fill");
|
2016-08-18 19:34:18 +08:00
|
|
|
|
|
|
|
if (fill_.type() == xlnt::fill_type::pattern)
|
|
|
|
{
|
|
|
|
const auto &pattern = fill_.pattern_fill();
|
|
|
|
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().start_element(xmlns, "patternFill");
|
|
|
|
serializer().attribute("patternType", pattern.type());
|
2016-08-18 19:34:18 +08:00
|
|
|
|
|
|
|
if (pattern.foreground())
|
|
|
|
{
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().start_element(xmlns, "fgColor");
|
|
|
|
write_color(*pattern.foreground());
|
|
|
|
serializer().end_element(xmlns, "fgColor");
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (pattern.background())
|
|
|
|
{
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().start_element(xmlns, "bgColor");
|
|
|
|
write_color(*pattern.background());
|
|
|
|
serializer().end_element(xmlns, "bgColor");
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
2016-09-20 06:52:11 +08:00
|
|
|
|
|
|
|
serializer().end_element(xmlns, "patternFill");
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
|
|
|
else if (fill_.type() == xlnt::fill_type::gradient)
|
|
|
|
{
|
|
|
|
const auto &gradient = fill_.gradient_fill();
|
|
|
|
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().start_element(xmlns, "gradientFill");
|
|
|
|
serializer().attribute("gradientType", gradient.type());
|
2016-08-18 19:34:18 +08:00
|
|
|
|
2016-11-10 08:52:18 +08:00
|
|
|
if (gradient.degree() != 0.)
|
2016-08-18 19:34:18 +08:00
|
|
|
{
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().attribute("degree", gradient.degree());
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
|
|
|
|
2016-11-10 08:52:18 +08:00
|
|
|
if (gradient.left() != 0.)
|
2016-08-18 19:34:18 +08:00
|
|
|
{
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().attribute("left", gradient.left());
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
|
|
|
|
2016-11-10 08:52:18 +08:00
|
|
|
if (gradient.right() != 0.)
|
2016-08-18 19:34:18 +08:00
|
|
|
{
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().attribute("right", gradient.right());
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
|
|
|
|
2016-11-10 08:52:18 +08:00
|
|
|
if (gradient.top() != 0.)
|
2016-08-18 19:34:18 +08:00
|
|
|
{
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().attribute("top", gradient.top());
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
|
|
|
|
2016-11-10 08:52:18 +08:00
|
|
|
if (gradient.bottom() != 0.)
|
2016-08-18 19:34:18 +08:00
|
|
|
{
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().attribute("bottom", gradient.bottom());
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
for (const auto &stop : gradient.stops())
|
|
|
|
{
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().start_element(xmlns, "stop");
|
|
|
|
serializer().attribute("position", stop.first);
|
|
|
|
serializer().start_element(xmlns, "color");
|
|
|
|
write_color(stop.second);
|
|
|
|
serializer().end_element(xmlns, "color");
|
|
|
|
serializer().end_element(xmlns, "stop");
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
2016-09-20 06:52:11 +08:00
|
|
|
|
|
|
|
serializer().end_element(xmlns, "gradientFill");
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
2016-09-20 06:52:11 +08:00
|
|
|
|
|
|
|
serializer().end_element(xmlns, "fill");
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
2016-09-20 06:52:11 +08:00
|
|
|
|
|
|
|
serializer().end_element(xmlns, "fills");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-08-18 19:34:18 +08:00
|
|
|
// Borders
|
|
|
|
|
2016-08-05 13:52:05 +08:00
|
|
|
if (!stylesheet.borders.empty())
|
|
|
|
{
|
2016-08-18 19:34:18 +08:00
|
|
|
const auto &borders = stylesheet.borders;
|
|
|
|
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().start_element(xmlns, "borders");
|
|
|
|
serializer().attribute("count", borders.size());
|
2016-08-18 19:34:18 +08:00
|
|
|
|
|
|
|
for (const auto ¤t_border : borders)
|
|
|
|
{
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().start_element(xmlns, "border");
|
2016-08-18 19:34:18 +08:00
|
|
|
|
|
|
|
if (current_border.diagonal())
|
|
|
|
{
|
|
|
|
auto up = *current_border.diagonal() == diagonal_direction::both
|
|
|
|
|| *current_border.diagonal() == diagonal_direction::up;
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().attribute("diagonalUp", up ? "true" : "false");
|
2016-08-18 19:34:18 +08:00
|
|
|
|
|
|
|
auto down = *current_border.diagonal() == diagonal_direction::both
|
|
|
|
|| *current_border.diagonal() == diagonal_direction::down;
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().attribute("diagonalDown", down ? "true" : "false");
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
for (const auto &side : xlnt::border::all_sides())
|
|
|
|
{
|
|
|
|
if (current_border.side(side))
|
|
|
|
{
|
|
|
|
const auto current_side = *current_border.side(side);
|
|
|
|
|
|
|
|
auto side_name = to_string(side);
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().start_element(xmlns, side_name);
|
2016-08-18 19:34:18 +08:00
|
|
|
|
|
|
|
if (current_side.style())
|
|
|
|
{
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().attribute("style", *current_side.style());
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (current_side.color())
|
|
|
|
{
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().start_element(xmlns, "color");
|
|
|
|
write_color(*current_side.color());
|
|
|
|
serializer().end_element(xmlns, "color");
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
2016-09-20 06:52:11 +08:00
|
|
|
|
|
|
|
serializer().end_element(xmlns, side_name);
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
|
|
|
}
|
2016-09-20 06:52:11 +08:00
|
|
|
|
|
|
|
serializer().end_element(xmlns, "border");
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
2016-09-20 06:52:11 +08:00
|
|
|
|
|
|
|
serializer().end_element(xmlns, "borders");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-09-20 06:52:11 +08:00
|
|
|
// Style XFs
|
|
|
|
|
|
|
|
serializer().start_element(xmlns, "cellStyleXfs");
|
2016-11-08 10:11:30 +08:00
|
|
|
serializer().attribute("count", stylesheet.style_impls.size());
|
2016-08-18 19:34:18 +08:00
|
|
|
|
2016-11-10 08:52:18 +08:00
|
|
|
for (const auto ¤t_style_name : stylesheet.style_names)
|
2016-08-18 19:34:18 +08:00
|
|
|
{
|
2016-11-10 08:52:18 +08:00
|
|
|
const auto ¤t_style_impl = stylesheet.style_impls.at(current_style_name);
|
2016-11-08 10:11:30 +08:00
|
|
|
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().start_element(xmlns, "xf");
|
2016-11-08 10:11:30 +08:00
|
|
|
serializer().attribute("numFmtId", current_style_impl.number_format_id.get());
|
|
|
|
serializer().attribute("fontId", current_style_impl.font_id.get());
|
|
|
|
serializer().attribute("fillId", current_style_impl.fill_id.get());
|
|
|
|
serializer().attribute("borderId", current_style_impl.border_id.get());
|
|
|
|
|
|
|
|
if (current_style_impl.number_format_applied)
|
|
|
|
{
|
|
|
|
serializer().attribute("applyNumberFormat", write_bool(true));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (current_style_impl.fill_applied)
|
|
|
|
{
|
|
|
|
serializer().attribute("applyFill", write_bool(true));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (current_style_impl.font_applied)
|
|
|
|
{
|
|
|
|
serializer().attribute("applyFont", write_bool(true));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (current_style_impl.border_applied)
|
|
|
|
{
|
|
|
|
serializer().attribute("applyBorder", write_bool(true));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (current_style_impl.alignment_applied)
|
|
|
|
{
|
|
|
|
serializer().attribute("applyAlignment", write_bool(true));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (current_style_impl.protection_applied)
|
|
|
|
{
|
|
|
|
serializer().attribute("applyProtection", write_bool(true));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (current_style_impl.alignment_applied)
|
2016-08-18 19:34:18 +08:00
|
|
|
{
|
2016-11-08 10:11:30 +08:00
|
|
|
const auto ¤t_alignment = stylesheet.alignments[current_style_impl.alignment_id.get()];
|
2016-09-20 06:52:11 +08:00
|
|
|
|
2016-10-14 08:11:02 +08:00
|
|
|
serializer().start_element(xmlns, "alignment");
|
2016-08-18 19:34:18 +08:00
|
|
|
|
|
|
|
if (current_alignment.vertical())
|
|
|
|
{
|
2016-11-08 10:11:30 +08:00
|
|
|
serializer().attribute("vertical", current_alignment.vertical().get());
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (current_alignment.horizontal())
|
|
|
|
{
|
2016-11-08 10:11:30 +08:00
|
|
|
serializer().attribute("horizontal", current_alignment.horizontal().get());
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (current_alignment.rotation())
|
|
|
|
{
|
2016-11-08 10:11:30 +08:00
|
|
|
serializer().attribute("textRotation", current_alignment.rotation().get());
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (current_alignment.wrap())
|
|
|
|
{
|
2016-11-08 10:11:30 +08:00
|
|
|
serializer().attribute("wrapText", write_bool(current_alignment.wrap().get()));
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (current_alignment.indent())
|
|
|
|
{
|
2016-11-08 10:11:30 +08:00
|
|
|
serializer().attribute("indent", current_alignment.indent().get());
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (current_alignment.shrink())
|
|
|
|
{
|
2016-11-08 10:11:30 +08:00
|
|
|
serializer().attribute("shrinkToFit", write_bool(current_alignment.shrink().get()));
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
2016-09-20 06:52:11 +08:00
|
|
|
|
2016-10-14 08:11:02 +08:00
|
|
|
serializer().end_element(xmlns, "alignment");
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
|
|
|
|
2016-11-08 10:11:30 +08:00
|
|
|
if (current_style_impl.protection_applied)
|
2016-08-18 19:34:18 +08:00
|
|
|
{
|
2016-11-08 10:11:30 +08:00
|
|
|
const auto ¤t_protection = stylesheet.protections[current_style_impl.protection_id.get()];
|
2016-08-18 19:34:18 +08:00
|
|
|
|
2016-10-14 08:11:02 +08:00
|
|
|
serializer().start_element(xmlns, "protection");
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().attribute("locked", write_bool(current_protection.locked()));
|
|
|
|
serializer().attribute("hidden", write_bool(current_protection.hidden()));
|
2016-10-14 08:11:02 +08:00
|
|
|
serializer().end_element(xmlns, "protection");
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
2016-09-20 06:52:11 +08:00
|
|
|
|
|
|
|
serializer().end_element(xmlns, "xf");
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
2016-09-20 06:52:11 +08:00
|
|
|
|
|
|
|
serializer().end_element(xmlns, "cellStyleXfs");
|
2016-08-18 19:34:18 +08:00
|
|
|
|
2016-09-20 06:52:11 +08:00
|
|
|
// Format XFs
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().start_element(xmlns, "cellXfs");
|
2016-11-08 10:11:30 +08:00
|
|
|
serializer().attribute("count", stylesheet.format_impls.size());
|
2016-08-18 19:34:18 +08:00
|
|
|
|
2016-11-08 10:11:30 +08:00
|
|
|
for (auto ¤t_format_impl : stylesheet.format_impls)
|
2016-08-18 19:34:18 +08:00
|
|
|
{
|
2016-11-08 10:11:30 +08:00
|
|
|
serializer().start_element(xmlns, "xf");
|
2016-11-10 08:52:18 +08:00
|
|
|
|
2016-11-08 10:11:30 +08:00
|
|
|
serializer().attribute("numFmtId", current_format_impl.number_format_id.get());
|
|
|
|
serializer().attribute("fontId", current_format_impl.font_id.get());
|
2016-11-10 08:52:18 +08:00
|
|
|
|
|
|
|
if (current_format_impl.style)
|
|
|
|
{
|
|
|
|
serializer().attribute("fillId", stylesheet.style_impls.at(current_format_impl.style.get()).fill_id.get());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
serializer().attribute("fillId", current_format_impl.fill_id.get());
|
|
|
|
}
|
|
|
|
|
2016-11-08 10:11:30 +08:00
|
|
|
serializer().attribute("borderId", current_format_impl.border_id.get());
|
|
|
|
|
|
|
|
if (current_format_impl.number_format_applied)
|
|
|
|
{
|
|
|
|
serializer().attribute("applyNumberFormat", write_bool(true));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (current_format_impl.fill_applied)
|
|
|
|
{
|
|
|
|
serializer().attribute("applyFill", write_bool(true));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (current_format_impl.font_applied)
|
|
|
|
{
|
|
|
|
serializer().attribute("applyFont", write_bool(true));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (current_format_impl.border_applied)
|
|
|
|
{
|
|
|
|
serializer().attribute("applyBorder", write_bool(true));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (current_format_impl.alignment_applied)
|
|
|
|
{
|
|
|
|
serializer().attribute("applyAlignment", write_bool(true));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (current_format_impl.protection_applied)
|
|
|
|
{
|
|
|
|
serializer().attribute("applyProtection", write_bool(true));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (current_format_impl.style.is_set())
|
2016-10-14 08:11:02 +08:00
|
|
|
{
|
2016-11-08 10:11:30 +08:00
|
|
|
serializer().attribute("xfId", stylesheet.style_index(current_format_impl.style.get()));
|
2016-10-14 08:11:02 +08:00
|
|
|
}
|
|
|
|
|
2016-11-08 10:11:30 +08:00
|
|
|
if (current_format_impl.alignment_applied)
|
2016-08-18 19:34:18 +08:00
|
|
|
{
|
2016-11-08 10:11:30 +08:00
|
|
|
const auto ¤t_alignment = stylesheet.alignments[current_format_impl.alignment_id.get()];
|
2016-08-18 19:34:18 +08:00
|
|
|
|
2016-10-14 08:11:02 +08:00
|
|
|
serializer().start_element(xmlns, "alignment");
|
2016-08-18 19:34:18 +08:00
|
|
|
|
|
|
|
if (current_alignment.vertical())
|
|
|
|
{
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().attribute("vertical", *current_alignment.vertical());
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (current_alignment.horizontal())
|
|
|
|
{
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().attribute("horizontal", *current_alignment.horizontal());
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (current_alignment.rotation())
|
|
|
|
{
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().attribute("textRotation", *current_alignment.rotation());
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (current_alignment.wrap())
|
|
|
|
{
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().attribute("wrapText", write_bool(*current_alignment.wrap()));
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (current_alignment.indent())
|
|
|
|
{
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().attribute("indent", *current_alignment.indent());
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (current_alignment.shrink())
|
|
|
|
{
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().attribute("shrinkToFit", write_bool(*current_alignment.shrink()));
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
2016-09-20 06:52:11 +08:00
|
|
|
|
2016-10-14 08:11:02 +08:00
|
|
|
serializer().end_element(xmlns, "alignment");
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
|
|
|
|
2016-11-08 10:11:30 +08:00
|
|
|
if (current_format_impl.protection_applied)
|
2016-08-18 19:34:18 +08:00
|
|
|
{
|
2016-11-08 10:11:30 +08:00
|
|
|
const auto ¤t_protection = stylesheet.protections[current_format_impl.protection_id.get()];
|
2016-08-18 19:34:18 +08:00
|
|
|
|
2016-10-14 08:11:02 +08:00
|
|
|
serializer().start_element(xmlns, "protection");
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().attribute("locked", write_bool(current_protection.locked()));
|
|
|
|
serializer().attribute("hidden", write_bool(current_protection.hidden()));
|
2016-10-14 08:11:02 +08:00
|
|
|
serializer().end_element(xmlns, "protection");
|
2016-09-20 06:52:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
serializer().end_element(xmlns, "xf");
|
2016-08-18 19:34:18 +08:00
|
|
|
}
|
2016-09-20 06:52:11 +08:00
|
|
|
|
|
|
|
serializer().end_element(xmlns, "cellXfs");
|
2016-08-18 19:34:18 +08:00
|
|
|
|
2016-09-20 06:52:11 +08:00
|
|
|
// Styles
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().start_element(xmlns, "cellStyles");
|
2016-11-08 10:11:30 +08:00
|
|
|
serializer().attribute("count", stylesheet.style_impls.size());
|
2016-09-20 06:52:11 +08:00
|
|
|
std::size_t style_index = 0;
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-11-08 10:11:30 +08:00
|
|
|
for (auto ¤t_style_name : stylesheet.style_names)
|
2016-09-20 06:52:11 +08:00
|
|
|
{
|
2016-11-08 10:11:30 +08:00
|
|
|
const auto ¤t_style = stylesheet.style_impls.at(current_style_name);
|
|
|
|
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().start_element(xmlns, "cellStyle");
|
2016-08-18 19:34:18 +08:00
|
|
|
|
2016-11-08 10:11:30 +08:00
|
|
|
serializer().attribute("name", current_style.name);
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().attribute("xfId", style_index++);
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-11-08 10:11:30 +08:00
|
|
|
if (current_style.builtin_id)
|
2016-09-20 06:52:11 +08:00
|
|
|
{
|
2016-11-08 10:11:30 +08:00
|
|
|
serializer().attribute("builtinId", current_style.builtin_id.get());
|
2016-09-20 06:52:11 +08:00
|
|
|
}
|
2016-08-18 19:34:18 +08:00
|
|
|
|
2016-11-08 10:11:30 +08:00
|
|
|
if (current_style.hidden_style)
|
2016-09-20 06:52:11 +08:00
|
|
|
{
|
|
|
|
serializer().attribute("hidden", write_bool(true));
|
|
|
|
}
|
|
|
|
|
2016-11-08 10:11:30 +08:00
|
|
|
if (current_style.custom_builtin)
|
2016-09-20 06:52:11 +08:00
|
|
|
{
|
2016-11-08 10:11:30 +08:00
|
|
|
serializer().attribute("customBuiltin", write_bool(current_style.custom_builtin.get()));
|
2016-09-20 06:52:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
serializer().end_element(xmlns, "cellStyle");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
2016-09-20 06:52:11 +08:00
|
|
|
|
|
|
|
serializer().end_element(xmlns, "cellStyles");
|
2016-08-13 11:06:25 +08:00
|
|
|
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().start_element(xmlns, "dxfs");
|
|
|
|
serializer().attribute("count", "0");
|
|
|
|
serializer().end_element(xmlns, "dxfs");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns, "tableStyles");
|
|
|
|
serializer().attribute("count", "0");
|
|
|
|
serializer().attribute("defaultTableStyle", "TableStyleMedium9");
|
|
|
|
serializer().attribute("defaultPivotStyle", "PivotStyleMedium7");
|
|
|
|
serializer().end_element(xmlns, "tableStyles");
|
|
|
|
|
|
|
|
if (!stylesheet.colors.empty())
|
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().start_element(xmlns, "colors");
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().start_element(xmlns, "indexedColors");
|
2016-08-18 19:34:18 +08:00
|
|
|
|
2016-09-20 06:52:11 +08:00
|
|
|
for (auto &c : stylesheet.colors)
|
|
|
|
{
|
|
|
|
serializer().start_element(xmlns, "rgbColor");
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().attribute("rgb", c.rgb().hex_string());
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().end_element(xmlns, "rgbColor");
|
|
|
|
}
|
|
|
|
|
|
|
|
serializer().end_element(xmlns, "indexedColors");
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().end_element(xmlns, "colors");
|
2016-09-20 06:52:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
serializer().end_element(xmlns, "styleSheet");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
void xlsx_producer::write_theme(const relationship &theme_rel)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
static const auto &xmlns_a = constants::namespace_("drawingml");
|
|
|
|
static const auto &xmlns_thm15 = constants::namespace_("thm15");
|
2016-09-19 09:49:37 +08:00
|
|
|
|
|
|
|
serializer().start_element(xmlns_a, "theme");
|
|
|
|
serializer().namespace_decl(xmlns_a, "a");
|
|
|
|
serializer().attribute("name", "Office Theme");
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().start_element(xmlns_a, "themeElements");
|
|
|
|
serializer().start_element(xmlns_a, "clrScheme");
|
|
|
|
serializer().attribute("name", "Office");
|
2016-08-05 13:52:05 +08:00
|
|
|
|
|
|
|
struct scheme_element
|
|
|
|
{
|
|
|
|
std::string name;
|
|
|
|
std::string sub_element_name;
|
|
|
|
std::string val;
|
|
|
|
};
|
|
|
|
|
|
|
|
std::vector<scheme_element> scheme_elements = {
|
2016-09-19 09:49:37 +08:00
|
|
|
{ "dk1", "sysClr", "windowText" },
|
|
|
|
{ "lt1", "sysClr", "window" },
|
|
|
|
{ "dk2", "srgbClr", "44546A" },
|
|
|
|
{ "lt2", "srgbClr", "E7E6E6" },
|
|
|
|
{ "accent1", "srgbClr", "5B9BD5" },
|
|
|
|
{ "accent2", "srgbClr", "ED7D31" },
|
|
|
|
{ "accent3", "srgbClr", "A5A5A5" },
|
|
|
|
{ "accent4", "srgbClr", "FFC000" },
|
|
|
|
{ "accent5", "srgbClr", "4472C4" },
|
|
|
|
{ "accent6", "srgbClr", "70AD47" },
|
|
|
|
{ "hlink", "srgbClr", "0563C1" },
|
|
|
|
{ "folHlink", "srgbClr", "954F72" },
|
2016-08-05 13:52:05 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
for (auto element : scheme_elements)
|
|
|
|
{
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().start_element(xmlns_a, element.name);
|
|
|
|
serializer().start_element(xmlns_a, element.sub_element_name);
|
|
|
|
serializer().attribute("val", element.val);
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-09-19 09:49:37 +08:00
|
|
|
if (element.name == "dk1")
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().attribute("lastClr", "000000");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
2016-09-19 09:49:37 +08:00
|
|
|
else if (element.name == "lt1")
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().attribute("lastClr", "FFFFFF");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
2016-09-19 09:49:37 +08:00
|
|
|
|
|
|
|
serializer().end_element(xmlns_a, element.sub_element_name);
|
|
|
|
serializer().end_element(xmlns_a, element.name);
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
2016-09-19 09:49:37 +08:00
|
|
|
|
|
|
|
serializer().end_element(xmlns_a, "clrScheme");
|
2016-08-05 13:52:05 +08:00
|
|
|
|
|
|
|
struct font_scheme
|
|
|
|
{
|
|
|
|
bool typeface;
|
|
|
|
std::string script;
|
|
|
|
std::string major;
|
|
|
|
std::string minor;
|
|
|
|
};
|
|
|
|
|
2016-11-10 08:52:18 +08:00
|
|
|
static const auto font_schemes = new std::vector<font_scheme> {
|
2016-09-19 09:49:37 +08:00
|
|
|
{ true, "latin", "Calibri Light", "Calibri" },
|
|
|
|
{ true, "ea", "", "" },
|
|
|
|
{ true, "cs", "", "" },
|
2016-08-13 11:06:25 +08:00
|
|
|
{ false, "Jpan", "Yu Gothic Light", "Yu Gothic" },
|
2016-08-05 13:52:05 +08:00
|
|
|
{ false, "Hang", "\xeb\xa7\x91\xec\x9d\x80 \xea\xb3\xa0\xeb\x94\x95",
|
|
|
|
"\xeb\xa7\x91\xec\x9d\x80 \xea\xb3\xa0\xeb\x94\x95" },
|
2016-08-13 11:06:25 +08:00
|
|
|
{ false, "Hans", "DengXian Light", "DengXian" },
|
2016-08-05 13:52:05 +08:00
|
|
|
{ false, "Hant", "\xe6\x96\xb0\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94",
|
|
|
|
"\xe6\x96\xb0\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94" },
|
|
|
|
{ false, "Arab", "Times New Roman", "Arial" },
|
|
|
|
{ false, "Hebr", "Times New Roman", "Arial" },
|
|
|
|
{ false, "Thai", "Tahoma", "Tahoma" },
|
|
|
|
{ false, "Ethi", "Nyala", "Nyala" },
|
|
|
|
{ false, "Beng", "Vrinda", "Vrinda" },
|
|
|
|
{ false, "Gujr", "Shruti", "Shruti" },
|
|
|
|
{ false, "Khmr", "MoolBoran", "DaunPenh" },
|
|
|
|
{ false, "Knda", "Tunga", "Tunga" },
|
|
|
|
{ false, "Guru", "Raavi", "Raavi" },
|
|
|
|
{ false, "Cans", "Euphemia", "Euphemia" },
|
|
|
|
{ false, "Cher", "Plantagenet Cherokee", "Plantagenet Cherokee" },
|
|
|
|
{ false, "Yiii", "Microsoft Yi Baiti", "Microsoft Yi Baiti" },
|
|
|
|
{ false, "Tibt", "Microsoft Himalaya", "Microsoft Himalaya" },
|
|
|
|
{ false, "Thaa", "MV Boli", "MV Boli" },
|
|
|
|
{ false, "Deva", "Mangal", "Mangal" },
|
|
|
|
{ false, "Telu", "Gautami", "Gautami" },
|
|
|
|
{ false, "Taml", "Latha", "Latha" },
|
|
|
|
{ false, "Syrc", "Estrangelo Edessa", "Estrangelo Edessa" },
|
|
|
|
{ false, "Orya", "Kalinga", "Kalinga" },
|
|
|
|
{ false, "Mlym", "Kartika", "Kartika" },
|
|
|
|
{ false, "Laoo", "DokChampa", "DokChampa" },
|
|
|
|
{ false, "Sinh", "Iskoola Pota", "Iskoola Pota" },
|
|
|
|
{ false, "Mong", "Mongolian Baiti", "Mongolian Baiti" },
|
|
|
|
{ false, "Viet", "Times New Roman", "Arial" },
|
2016-08-13 11:06:25 +08:00
|
|
|
{ false, "Uigh", "Microsoft Uighur", "Microsoft Uighur" },
|
|
|
|
{ false, "Geor", "Sylfaen", "Sylfaen" }
|
2016-08-05 13:52:05 +08:00
|
|
|
};
|
|
|
|
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().start_element(xmlns_a, "fontScheme");
|
|
|
|
serializer().attribute("name", "Office");
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-09-19 09:49:37 +08:00
|
|
|
for (auto major : {true, false})
|
|
|
|
{
|
|
|
|
serializer().start_element(xmlns_a, major ? "majorFont" : "minorFont");
|
|
|
|
|
2016-11-10 08:52:18 +08:00
|
|
|
for (const auto &scheme : *font_schemes)
|
2016-09-19 09:49:37 +08:00
|
|
|
{
|
|
|
|
const auto scheme_value = major ? scheme.major : scheme.minor;
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-09-19 09:49:37 +08:00
|
|
|
if (scheme.typeface)
|
|
|
|
{
|
|
|
|
serializer().start_element(xmlns_a, scheme.script);
|
|
|
|
serializer().attribute("typeface", scheme_value);
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-09-19 09:49:37 +08:00
|
|
|
if (scheme_value == "Calibri Light")
|
|
|
|
{
|
|
|
|
serializer().attribute("panose", "020F0302020204030204");
|
|
|
|
}
|
|
|
|
else if (scheme_value == "Calibri")
|
|
|
|
{
|
|
|
|
serializer().attribute("panose", "020F0502020204030204");
|
|
|
|
}
|
|
|
|
|
|
|
|
serializer().end_element(xmlns_a, scheme.script);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
serializer().start_element(xmlns_a, "font");
|
|
|
|
serializer().attribute("script", scheme.script);
|
|
|
|
serializer().attribute("typeface", scheme_value);
|
|
|
|
serializer().end_element(xmlns_a, "font");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
serializer().end_element(xmlns_a, major ? "majorFont" : "minorFont");
|
|
|
|
}
|
|
|
|
|
|
|
|
serializer().end_element(xmlns_a, "fontScheme");
|
2016-08-13 11:06:25 +08:00
|
|
|
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().start_element(xmlns_a, "fmtScheme");
|
|
|
|
serializer().attribute("name", "Office");
|
2016-08-13 11:06:25 +08:00
|
|
|
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().start_element(xmlns_a, "fillStyleLst");
|
|
|
|
serializer().start_element(xmlns_a, "solidFill");
|
|
|
|
serializer().start_element(xmlns_a, "schemeClr");
|
|
|
|
serializer().attribute("val", "phClr");
|
|
|
|
serializer().end_element(xmlns_a, "schemeClr");
|
|
|
|
serializer().end_element(xmlns_a, "solidFill");
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().start_element(xmlns_a, "gradFill");
|
|
|
|
serializer().attribute("rotWithShape", "1");
|
|
|
|
serializer().start_element(xmlns_a, "gsLst");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns_a, "gs");
|
|
|
|
serializer().attribute("pos", "0");
|
|
|
|
serializer().start_element(xmlns_a, "schemeClr");
|
|
|
|
serializer().attribute("val", "phClr");
|
|
|
|
serializer().start_element(xmlns_a, "lumMod");
|
|
|
|
serializer().attribute("val", "110000");
|
|
|
|
serializer().end_element(xmlns_a, "lumMod");
|
|
|
|
serializer().start_element(xmlns_a, "satMod");
|
|
|
|
serializer().attribute("val", "105000");
|
|
|
|
serializer().end_element(xmlns_a, "satMod");
|
|
|
|
serializer().start_element(xmlns_a, "tint");
|
|
|
|
serializer().attribute("val", "67000");
|
|
|
|
serializer().end_element(xmlns_a, "tint");
|
|
|
|
serializer().end_element(xmlns_a, "schemeClr");
|
|
|
|
serializer().end_element(xmlns_a, "gs");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns_a, "gs");
|
|
|
|
serializer().attribute("pos", "50000");
|
|
|
|
serializer().start_element(xmlns_a, "schemeClr");
|
|
|
|
serializer().attribute("val", "phClr");
|
|
|
|
serializer().start_element(xmlns_a, "lumMod");
|
|
|
|
serializer().attribute("val", "105000");
|
|
|
|
serializer().end_element(xmlns_a, "lumMod");
|
|
|
|
serializer().start_element(xmlns_a, "satMod");
|
|
|
|
serializer().attribute("val", "103000");
|
|
|
|
serializer().end_element(xmlns_a, "satMod");
|
|
|
|
serializer().start_element(xmlns_a, "tint");
|
|
|
|
serializer().attribute("val", "73000");
|
|
|
|
serializer().end_element(xmlns_a, "tint");
|
|
|
|
serializer().end_element(xmlns_a, "schemeClr");
|
|
|
|
serializer().end_element(xmlns_a, "gs");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns_a, "gs");
|
|
|
|
serializer().attribute("pos", "100000");
|
|
|
|
serializer().start_element(xmlns_a, "schemeClr");
|
|
|
|
serializer().attribute("val", "phClr");
|
|
|
|
serializer().start_element(xmlns_a, "lumMod");
|
|
|
|
serializer().attribute("val", "105000");
|
|
|
|
serializer().end_element(xmlns_a, "lumMod");
|
|
|
|
serializer().start_element(xmlns_a, "satMod");
|
|
|
|
serializer().attribute("val", "109000");
|
|
|
|
serializer().end_element(xmlns_a, "satMod");
|
|
|
|
serializer().start_element(xmlns_a, "tint");
|
|
|
|
serializer().attribute("val", "81000");
|
|
|
|
serializer().end_element(xmlns_a, "tint");
|
|
|
|
serializer().end_element(xmlns_a, "schemeClr");
|
|
|
|
serializer().end_element(xmlns_a, "gs");
|
|
|
|
|
|
|
|
serializer().end_element(xmlns_a, "gsLst");
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().start_element(xmlns_a, "lin");
|
|
|
|
serializer().attribute("ang", "5400000");
|
|
|
|
serializer().attribute("scaled", "0");
|
|
|
|
serializer().end_element(xmlns_a, "lin");
|
|
|
|
|
|
|
|
serializer().end_element(xmlns_a, "gradFill");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns_a, "gradFill");
|
|
|
|
serializer().attribute("rotWithShape", "1");
|
|
|
|
serializer().start_element(xmlns_a, "gsLst");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns_a, "gs");
|
|
|
|
serializer().attribute("pos", "0");
|
|
|
|
serializer().start_element(xmlns_a, "schemeClr");
|
|
|
|
serializer().attribute("val", "phClr");
|
|
|
|
serializer().start_element(xmlns_a, "satMod");
|
|
|
|
serializer().attribute("val", "103000");
|
|
|
|
serializer().end_element(xmlns_a, "satMod");
|
|
|
|
serializer().start_element(xmlns_a, "lumMod");
|
|
|
|
serializer().attribute("val", "102000");
|
|
|
|
serializer().end_element(xmlns_a, "lumMod");
|
|
|
|
serializer().start_element(xmlns_a, "tint");
|
|
|
|
serializer().attribute("val", "94000");
|
|
|
|
serializer().end_element(xmlns_a, "tint");
|
|
|
|
serializer().end_element(xmlns_a, "schemeClr");
|
|
|
|
serializer().end_element(xmlns_a, "gs");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns_a, "gs");
|
|
|
|
serializer().attribute("pos", "50000");
|
|
|
|
serializer().start_element(xmlns_a, "schemeClr");
|
|
|
|
serializer().attribute("val", "phClr");
|
|
|
|
serializer().start_element(xmlns_a, "satMod");
|
|
|
|
serializer().attribute("val", "110000");
|
|
|
|
serializer().end_element(xmlns_a, "satMod");
|
|
|
|
serializer().start_element(xmlns_a, "lumMod");
|
|
|
|
serializer().attribute("val", "100000");
|
|
|
|
serializer().end_element(xmlns_a, "lumMod");
|
|
|
|
serializer().start_element(xmlns_a, "shade");
|
|
|
|
serializer().attribute("val", "100000");
|
|
|
|
serializer().end_element(xmlns_a, "shade");
|
|
|
|
serializer().end_element(xmlns_a, "schemeClr");
|
|
|
|
serializer().end_element(xmlns_a, "gs");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns_a, "gs");
|
|
|
|
serializer().attribute("pos", "100000");
|
|
|
|
serializer().start_element(xmlns_a, "schemeClr");
|
|
|
|
serializer().attribute("val", "phClr");
|
|
|
|
serializer().start_element(xmlns_a, "lumMod");
|
|
|
|
serializer().attribute("val", "99000");
|
|
|
|
serializer().end_element(xmlns_a, "lumMod");
|
|
|
|
serializer().start_element(xmlns_a, "satMod");
|
|
|
|
serializer().attribute("val", "120000");
|
|
|
|
serializer().end_element(xmlns_a, "satMod");
|
|
|
|
serializer().start_element(xmlns_a, "shade");
|
|
|
|
serializer().attribute("val", "78000");
|
|
|
|
serializer().end_element(xmlns_a, "shade");
|
|
|
|
serializer().end_element(xmlns_a, "schemeClr");
|
|
|
|
serializer().end_element(xmlns_a, "gs");
|
|
|
|
|
|
|
|
serializer().end_element(xmlns_a, "gsLst");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns_a, "lin");
|
|
|
|
serializer().attribute("ang", "5400000");
|
|
|
|
serializer().attribute("scaled", "0");
|
|
|
|
serializer().end_element(xmlns_a, "lin");
|
|
|
|
|
|
|
|
serializer().end_element(xmlns_a, "gradFill");
|
|
|
|
serializer().end_element(xmlns_a, "fillStyleLst");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns_a, "lnStyleLst");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns_a, "ln");
|
|
|
|
serializer().attribute("w", "6350");
|
|
|
|
serializer().attribute("cap", "flat");
|
|
|
|
serializer().attribute("cmpd", "sng");
|
|
|
|
serializer().attribute("algn", "ctr");
|
|
|
|
serializer().start_element(xmlns_a, "solidFill");
|
|
|
|
serializer().start_element(xmlns_a, "schemeClr");
|
|
|
|
serializer().attribute("val", "phClr");
|
|
|
|
serializer().end_element(xmlns_a, "schemeClr");
|
|
|
|
serializer().end_element(xmlns_a, "solidFill");
|
|
|
|
serializer().start_element(xmlns_a, "prstDash");
|
|
|
|
serializer().attribute("val", "solid");
|
|
|
|
serializer().end_element(xmlns_a, "prstDash");
|
|
|
|
serializer().start_element(xmlns_a, "miter");
|
|
|
|
serializer().attribute("lim", "800000");
|
|
|
|
serializer().end_element(xmlns_a, "miter");
|
|
|
|
serializer().end_element(xmlns_a, "ln");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns_a, "ln");
|
|
|
|
serializer().attribute("w", "12700");
|
|
|
|
serializer().attribute("cap", "flat");
|
|
|
|
serializer().attribute("cmpd", "sng");
|
|
|
|
serializer().attribute("algn", "ctr");
|
|
|
|
serializer().start_element(xmlns_a, "solidFill");
|
|
|
|
serializer().start_element(xmlns_a, "schemeClr");
|
|
|
|
serializer().attribute("val", "phClr");
|
|
|
|
serializer().end_element(xmlns_a, "schemeClr");
|
|
|
|
serializer().end_element(xmlns_a, "solidFill");
|
|
|
|
serializer().start_element(xmlns_a, "prstDash");
|
|
|
|
serializer().attribute("val", "solid");
|
|
|
|
serializer().end_element(xmlns_a, "prstDash");
|
|
|
|
serializer().start_element(xmlns_a, "miter");
|
|
|
|
serializer().attribute("lim", "800000");
|
|
|
|
serializer().end_element(xmlns_a, "miter");
|
|
|
|
serializer().end_element(xmlns_a, "ln");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns_a, "ln");
|
|
|
|
serializer().attribute("w", "19050");
|
|
|
|
serializer().attribute("cap", "flat");
|
|
|
|
serializer().attribute("cmpd", "sng");
|
|
|
|
serializer().attribute("algn", "ctr");
|
|
|
|
serializer().start_element(xmlns_a, "solidFill");
|
|
|
|
serializer().start_element(xmlns_a, "schemeClr");
|
|
|
|
serializer().attribute("val", "phClr");
|
|
|
|
serializer().end_element(xmlns_a, "schemeClr");
|
|
|
|
serializer().end_element(xmlns_a, "solidFill");
|
|
|
|
serializer().start_element(xmlns_a, "prstDash");
|
|
|
|
serializer().attribute("val", "solid");
|
|
|
|
serializer().end_element(xmlns_a, "prstDash");
|
|
|
|
serializer().start_element(xmlns_a, "miter");
|
|
|
|
serializer().attribute("lim", "800000");
|
|
|
|
serializer().end_element(xmlns_a, "miter");
|
|
|
|
serializer().end_element(xmlns_a, "ln");
|
|
|
|
|
|
|
|
serializer().end_element(xmlns_a, "lnStyleLst");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns_a, "effectStyleLst");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns_a, "effectStyle");
|
|
|
|
serializer().element(xmlns_a, "effectLst", "");
|
|
|
|
serializer().end_element(xmlns_a, "effectStyle");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns_a, "effectStyle");
|
|
|
|
serializer().element(xmlns_a, "effectLst", "");
|
|
|
|
serializer().end_element(xmlns_a, "effectStyle");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns_a, "effectStyle");
|
|
|
|
serializer().start_element(xmlns_a, "effectLst");
|
|
|
|
serializer().start_element(xmlns_a, "outerShdw");
|
|
|
|
serializer().attribute("blurRad", "57150");
|
|
|
|
serializer().attribute("dist", "19050");
|
|
|
|
serializer().attribute("dir", "5400000");
|
|
|
|
serializer().attribute("algn", "ctr");
|
|
|
|
serializer().attribute("rotWithShape", "0");
|
|
|
|
serializer().start_element(xmlns_a, "srgbClr");
|
|
|
|
serializer().attribute("val", "000000");
|
|
|
|
serializer().start_element(xmlns_a, "alpha");
|
|
|
|
serializer().attribute("val", "63000");
|
|
|
|
serializer().end_element(xmlns_a, "alpha");
|
|
|
|
serializer().end_element(xmlns_a, "srgbClr");
|
|
|
|
serializer().end_element(xmlns_a, "outerShdw");
|
|
|
|
serializer().end_element(xmlns_a, "effectLst");
|
|
|
|
serializer().end_element(xmlns_a, "effectStyle");
|
|
|
|
|
|
|
|
serializer().end_element(xmlns_a, "effectStyleLst");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns_a, "bgFillStyleLst");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns_a, "solidFill");
|
|
|
|
serializer().start_element(xmlns_a, "schemeClr");
|
|
|
|
serializer().attribute("val", "phClr");
|
|
|
|
serializer().end_element(xmlns_a, "schemeClr");
|
|
|
|
serializer().end_element(xmlns_a, "solidFill");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns_a, "solidFill");
|
|
|
|
serializer().start_element(xmlns_a, "schemeClr");
|
|
|
|
serializer().attribute("val", "phClr");
|
|
|
|
serializer().start_element(xmlns_a, "tint");
|
|
|
|
serializer().attribute("val", "95000");
|
|
|
|
serializer().end_element(xmlns_a, "tint");
|
|
|
|
serializer().start_element(xmlns_a, "satMod");
|
|
|
|
serializer().attribute("val", "170000");
|
|
|
|
serializer().end_element(xmlns_a, "satMod");
|
|
|
|
serializer().end_element(xmlns_a, "schemeClr");
|
|
|
|
serializer().end_element(xmlns_a, "solidFill");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns_a, "gradFill");
|
|
|
|
serializer().attribute("rotWithShape", "1");
|
|
|
|
serializer().start_element(xmlns_a, "gsLst");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns_a, "gs");
|
|
|
|
serializer().attribute("pos", "0");
|
|
|
|
serializer().start_element(xmlns_a, "schemeClr");
|
|
|
|
serializer().attribute("val", "phClr");
|
|
|
|
serializer().start_element(xmlns_a, "tint");
|
|
|
|
serializer().attribute("val", "93000");
|
|
|
|
serializer().end_element(xmlns_a, "tint");
|
|
|
|
serializer().start_element(xmlns_a, "satMod");
|
|
|
|
serializer().attribute("val", "150000");
|
|
|
|
serializer().end_element(xmlns_a, "satMod");
|
|
|
|
serializer().start_element(xmlns_a, "shade");
|
|
|
|
serializer().attribute("val", "98000");
|
|
|
|
serializer().end_element(xmlns_a, "shade");
|
|
|
|
serializer().start_element(xmlns_a, "lumMod");
|
|
|
|
serializer().attribute("val", "102000");
|
|
|
|
serializer().end_element(xmlns_a, "lumMod");
|
|
|
|
serializer().end_element(xmlns_a, "schemeClr");
|
|
|
|
serializer().end_element(xmlns_a, "gs");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns_a, "gs");
|
|
|
|
serializer().attribute("pos", "50000");
|
|
|
|
serializer().start_element(xmlns_a, "schemeClr");
|
|
|
|
serializer().attribute("val", "phClr");
|
|
|
|
serializer().start_element(xmlns_a, "tint");
|
|
|
|
serializer().attribute("val", "98000");
|
|
|
|
serializer().end_element(xmlns_a, "tint");
|
|
|
|
serializer().start_element(xmlns_a, "satMod");
|
|
|
|
serializer().attribute("val", "130000");
|
|
|
|
serializer().end_element(xmlns_a, "satMod");
|
|
|
|
serializer().start_element(xmlns_a, "shade");
|
|
|
|
serializer().attribute("val", "90000");
|
|
|
|
serializer().end_element(xmlns_a, "shade");
|
|
|
|
serializer().start_element(xmlns_a, "lumMod");
|
|
|
|
serializer().attribute("val", "103000");
|
|
|
|
serializer().end_element(xmlns_a, "lumMod");
|
|
|
|
serializer().end_element(xmlns_a, "schemeClr");
|
|
|
|
serializer().end_element(xmlns_a, "gs");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns_a, "gs");
|
|
|
|
serializer().attribute("pos", "100000");
|
|
|
|
serializer().start_element(xmlns_a, "schemeClr");
|
|
|
|
serializer().attribute("val", "phClr");
|
|
|
|
serializer().start_element(xmlns_a, "shade");
|
|
|
|
serializer().attribute("val", "63000");
|
|
|
|
serializer().end_element(xmlns_a, "shade");
|
|
|
|
serializer().start_element(xmlns_a, "satMod");
|
|
|
|
serializer().attribute("val", "120000");
|
|
|
|
serializer().end_element(xmlns_a, "satMod");
|
|
|
|
serializer().end_element(xmlns_a, "schemeClr");
|
|
|
|
serializer().end_element(xmlns_a, "gs");
|
|
|
|
|
|
|
|
serializer().end_element(xmlns_a, "gsLst");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns_a, "lin");
|
|
|
|
serializer().attribute("ang", "5400000");
|
|
|
|
serializer().attribute("scaled", "0");
|
|
|
|
serializer().end_element(xmlns_a, "lin");
|
|
|
|
|
|
|
|
serializer().end_element(xmlns_a, "gradFill");
|
|
|
|
|
|
|
|
serializer().end_element(xmlns_a, "bgFillStyleLst");
|
|
|
|
serializer().end_element(xmlns_a, "fmtScheme");
|
|
|
|
serializer().end_element(xmlns_a, "themeElements");
|
|
|
|
|
|
|
|
serializer().element(xmlns_a, "objectDefaults", "");
|
|
|
|
serializer().element(xmlns_a, "extraClrSchemeLst", "");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns_a, "extLst");
|
|
|
|
serializer().start_element(xmlns_a, "ext");
|
|
|
|
serializer().attribute("uri", "{05A4C25C-085E-4340-85A3-A5531E510DB2}");
|
|
|
|
serializer().start_element(xmlns_thm15, "themeFamily");
|
|
|
|
serializer().namespace_decl(xmlns_thm15, "thm15");
|
|
|
|
serializer().attribute("name", "Office Theme");
|
|
|
|
serializer().attribute("id", "{62F939B6-93AF-4DB8-9C6B-D6C7DFDC589F}");
|
|
|
|
serializer().attribute("vid", "{4A3C46E8-61CC-4603-A589-7422A47A8E4A}");
|
|
|
|
serializer().end_element(xmlns_thm15, "themeFamily");
|
|
|
|
serializer().end_element(xmlns_a, "ext");
|
|
|
|
serializer().end_element(xmlns_a, "extLst");
|
|
|
|
|
|
|
|
serializer().end_element(xmlns_a, "theme");
|
2016-12-02 21:37:50 +08:00
|
|
|
|
|
|
|
const auto workbook_rel = source_.manifest().relationship(path("/"), relationship_type::office_document);
|
|
|
|
const auto theme_part = source_.manifest().canonicalize({workbook_rel, theme_rel});
|
|
|
|
const auto theme_rels = source_.manifest().relationships(theme_part);
|
|
|
|
|
|
|
|
if (!theme_rels.empty())
|
|
|
|
{
|
|
|
|
write_relationships(theme_rels, theme_part);
|
|
|
|
|
|
|
|
for (auto rel : theme_rels)
|
|
|
|
{
|
|
|
|
if (rel.type() == relationship_type::image)
|
|
|
|
{
|
|
|
|
const auto image_path = source_.manifest().canonicalize({workbook_rel, theme_rel, rel});
|
|
|
|
write_image(image_path);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-11-10 08:52:18 +08:00
|
|
|
void xlsx_producer::write_volatile_dependencies(const relationship &/*rel*/)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-09-18 23:32:59 +08:00
|
|
|
serializer().start_element("volTypes");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-09-18 23:32:59 +08:00
|
|
|
void xlsx_producer::write_worksheet(const relationship &rel)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
static const auto &xmlns = constants::namespace_("spreadsheetml");
|
|
|
|
static const auto &xmlns_r = constants::namespace_("r");
|
2016-10-30 04:31:30 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
auto worksheet_part = rel.source().path().parent().append(rel.target().path());
|
|
|
|
auto worksheet_rels = source_.manifest().relationships(worksheet_part);
|
2016-10-30 04:31:30 +08:00
|
|
|
|
2016-08-06 22:40:17 +08:00
|
|
|
auto title = std::find_if(source_.d_->sheet_title_rel_id_map_.begin(),
|
|
|
|
source_.d_->sheet_title_rel_id_map_.end(),
|
|
|
|
[&](const std::pair<std::string, std::string> &p)
|
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
return p.second == rel.id();
|
2016-08-06 22:40:17 +08:00
|
|
|
})->first;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
auto ws = source_.sheet_by_title(title);
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-09-18 23:32:59 +08:00
|
|
|
serializer().start_element(xmlns, "worksheet");
|
|
|
|
serializer().namespace_decl(xmlns, "");
|
2016-09-19 09:49:37 +08:00
|
|
|
serializer().namespace_decl(xmlns_r, "r");
|
2016-08-14 02:45:26 +08:00
|
|
|
|
|
|
|
if (ws.has_page_setup())
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().start_element(xmlns, "sheetPr");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns, "outlinePr");
|
|
|
|
serializer().attribute("summaryBelow", "1");
|
|
|
|
serializer().attribute("summaryRight", "1");
|
|
|
|
serializer().end_element(xmlns, "outlinePr");
|
2016-08-13 11:06:25 +08:00
|
|
|
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().start_element(xmlns, "pageSetUpPr");
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().attribute("fitToPage", write_bool(ws.page_setup().fit_to_page()));
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().end_element(xmlns, "pageSetUpPr");
|
2016-08-13 11:06:25 +08:00
|
|
|
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().end_element(xmlns, "sheetPr");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-12-10 08:18:50 +08:00
|
|
|
serializer().start_element(xmlns, "dimension");
|
|
|
|
const auto dimension = ws.calculate_dimension();
|
|
|
|
serializer().attribute("ref", dimension.is_single_cell()
|
|
|
|
? dimension.top_left().to_string() : dimension.to_string());
|
|
|
|
serializer().end_element(xmlns, "dimension");
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-08-14 02:45:26 +08:00
|
|
|
if (ws.has_view())
|
|
|
|
{
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().start_element(xmlns, "sheetViews");
|
|
|
|
serializer().start_element(xmlns, "sheetView");
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
const auto view = ws.view();
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().attribute("tabSelected", write_bool(view.id() == 0));
|
|
|
|
serializer().attribute("workbookViewId", view.id());
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-12-23 07:57:22 +08:00
|
|
|
if (view.type() != sheet_view_type::normal)
|
|
|
|
{
|
|
|
|
serializer().attribute("view", view.type() == sheet_view_type::page_break_preview ? "pageBreakPreview" : "pageLayout");
|
|
|
|
}
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (view.has_pane())
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
const auto ¤t_pane = view.pane();
|
|
|
|
serializer().start_element(xmlns, "pane"); // CT_Pane
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (current_pane.top_left_cell.is_set())
|
|
|
|
{
|
|
|
|
serializer().attribute("topLeftCell", current_pane.top_left_cell.get().to_string());
|
|
|
|
}
|
2016-08-14 02:45:26 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().attribute("xSplit", current_pane.x_split.index);
|
|
|
|
serializer().attribute("ySplit", current_pane.y_split);
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (current_pane.active_pane != pane_corner::top_left)
|
|
|
|
{
|
|
|
|
serializer().attribute("activePane", current_pane.active_pane);
|
|
|
|
}
|
2016-08-14 02:45:26 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (current_pane.state != pane_state::split)
|
|
|
|
{
|
|
|
|
serializer().attribute("state", current_pane.state);
|
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().end_element(xmlns, "pane");
|
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
for (const auto ¤t_selection : view.selections())
|
|
|
|
{
|
|
|
|
serializer().start_element(xmlns, "selection"); // CT_Selection
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (current_selection.has_active_cell())
|
2016-08-14 02:45:26 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().attribute("activeCell", current_selection.active_cell().to_string());
|
|
|
|
serializer().attribute("sqref", current_selection.active_cell().to_string());
|
2016-08-14 02:45:26 +08:00
|
|
|
}
|
2016-12-02 21:37:50 +08:00
|
|
|
/*
|
|
|
|
if (current_selection.sqref() != "A1:A1")
|
|
|
|
{
|
|
|
|
serializer().attribute("sqref", current_selection.sqref().to_string());
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
if (current_selection.pane() != pane_corner::top_left)
|
|
|
|
{
|
|
|
|
serializer().attribute("pane", current_selection.pane());
|
|
|
|
}
|
2016-08-13 11:06:25 +08:00
|
|
|
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().end_element(xmlns, "selection");
|
2016-08-13 11:06:25 +08:00
|
|
|
}
|
2016-09-20 06:52:11 +08:00
|
|
|
|
|
|
|
serializer().end_element(xmlns, "sheetView");
|
|
|
|
serializer().end_element(xmlns, "sheetViews");
|
2016-08-13 11:06:25 +08:00
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-12-10 08:18:50 +08:00
|
|
|
serializer().start_element(xmlns, "sheetFormatPr");
|
|
|
|
serializer().attribute("baseColWidth", "10");
|
|
|
|
serializer().attribute("defaultRowHeight", "16");
|
|
|
|
serializer().end_element(xmlns, "sheetFormatPr");
|
2016-08-05 13:52:05 +08:00
|
|
|
|
|
|
|
bool has_column_properties = false;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
for (auto column = ws.lowest_column(); column <= ws.highest_column(); column++)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
if (ws.has_column_properties(column))
|
|
|
|
{
|
|
|
|
has_column_properties = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (has_column_properties)
|
|
|
|
{
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().start_element(xmlns, "cols");
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
for (auto column = ws.lowest_column(); column <= ws.highest_column(); column++)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-09-20 06:52:11 +08:00
|
|
|
if (!ws.has_column_properties(column)) continue;
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
const auto &props = ws.column_properties(column);
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-10-14 08:11:02 +08:00
|
|
|
serializer().start_element(xmlns, "col");
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().attribute("min", column.index);
|
|
|
|
serializer().attribute("max", column.index);
|
2016-12-23 07:57:22 +08:00
|
|
|
|
|
|
|
if (props.width.is_set())
|
|
|
|
{
|
|
|
|
serializer().attribute("width", props.width.get());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (props.custom_width)
|
|
|
|
{
|
|
|
|
serializer().attribute("customWidth", write_bool(true));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (props.style.is_set())
|
|
|
|
{
|
|
|
|
serializer().attribute("style", props.style.get());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (props.hidden)
|
|
|
|
{
|
|
|
|
serializer().attribute("hidden", write_bool(true));
|
|
|
|
}
|
|
|
|
|
2016-10-14 08:11:02 +08:00
|
|
|
serializer().end_element(xmlns, "col");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
2016-09-20 06:52:11 +08:00
|
|
|
|
|
|
|
serializer().end_element(xmlns, "cols");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
const auto hyperlink_rels = source_.manifest().relationships(worksheet_part, relationship_type::hyperlink);
|
|
|
|
std::unordered_map<std::string, std::string> reverse_hyperlink_references;
|
|
|
|
|
|
|
|
for (auto hyperlink_rel : hyperlink_rels)
|
|
|
|
{
|
|
|
|
reverse_hyperlink_references[hyperlink_rel.target().path().string()] = rel.id();
|
|
|
|
}
|
|
|
|
|
2016-08-05 13:52:05 +08:00
|
|
|
std::unordered_map<std::string, std::string> hyperlink_references;
|
|
|
|
|
2016-09-18 23:32:59 +08:00
|
|
|
serializer().start_element(xmlns, "sheetData");
|
2016-12-02 21:37:50 +08:00
|
|
|
const auto &shared_strings = ws.workbook().shared_strings();
|
2016-10-30 04:31:30 +08:00
|
|
|
std::vector<cell_reference> cells_with_comments;
|
2016-09-20 06:52:11 +08:00
|
|
|
|
2016-08-05 13:52:05 +08:00
|
|
|
for (auto row : ws.rows())
|
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
auto min = static_cast<xlnt::row_t>(row.length());
|
2016-08-05 13:52:05 +08:00
|
|
|
xlnt::row_t max = 0;
|
|
|
|
bool any_non_null = false;
|
|
|
|
|
|
|
|
for (auto cell : row)
|
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
min = std::min(min, cell.column().index);
|
|
|
|
max = std::max(max, cell.column().index);
|
2016-08-05 13:52:05 +08:00
|
|
|
|
|
|
|
if (!cell.garbage_collectible())
|
|
|
|
{
|
|
|
|
any_non_null = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!any_non_null)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().start_element(xmlns, "row");
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().attribute("r", row.front().row());
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().attribute("spans", std::to_string(min) + ":" + std::to_string(max));
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (ws.has_row_properties(row.front().row()))
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-12-23 07:57:22 +08:00
|
|
|
const auto &props = ws.row_properties(row.front().row());
|
|
|
|
|
|
|
|
if (props.custom_height)
|
|
|
|
{
|
|
|
|
serializer().attribute("customHeight", write_bool(true));
|
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-12-23 07:57:22 +08:00
|
|
|
if (props.height.is_set())
|
|
|
|
{
|
|
|
|
auto height = props.height.get();
|
|
|
|
|
|
|
|
if (std::fabs(height - std::floor(height)) == 0.0)
|
|
|
|
{
|
|
|
|
serializer().attribute("ht", std::to_string(static_cast<int>(height)) + ".0");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
serializer().attribute("ht", height);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (props.hidden)
|
|
|
|
{
|
|
|
|
serializer().attribute("hidden", write_bool(true));
|
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
for (auto cell : row)
|
|
|
|
{
|
2016-10-30 04:31:30 +08:00
|
|
|
if (cell.has_comment())
|
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
cells_with_comments.push_back(cell.reference());
|
2016-10-30 04:31:30 +08:00
|
|
|
}
|
|
|
|
|
2016-08-05 13:52:05 +08:00
|
|
|
if (!cell.garbage_collectible())
|
|
|
|
{
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().start_element(xmlns, "c");
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().attribute("r", cell.reference().to_string());
|
2016-09-20 06:52:11 +08:00
|
|
|
|
|
|
|
if (cell.has_format())
|
|
|
|
{
|
2016-11-08 10:11:30 +08:00
|
|
|
serializer().attribute("s", cell.format().id());
|
2016-09-20 06:52:11 +08:00
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (cell.has_hyperlink())
|
|
|
|
{
|
|
|
|
hyperlink_references[cell.reference().to_string()] = reverse_hyperlink_references[cell.hyperlink()];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cell.data_type() == cell::type::string)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
if (cell.has_formula())
|
|
|
|
{
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().attribute("t", "str");
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().element(xmlns, "f", cell.formula());
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().element(xmlns, "v", cell.to_string());
|
|
|
|
serializer().end_element(xmlns, "c");
|
2016-08-05 13:52:05 +08:00
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
int match_index = -1;
|
|
|
|
|
|
|
|
for (std::size_t i = 0; i < shared_strings.size(); i++)
|
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
if (shared_strings[i] == cell.value<formatted_text>())
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
match_index = static_cast<int>(i);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (match_index == -1)
|
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
if (cell.value<std::string>().empty())
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().attribute("t", "s");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().attribute("t", "inlineStr");
|
|
|
|
serializer().start_element(xmlns, "is");
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().element(xmlns, "t", cell.value<std::string>());
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().end_element(xmlns, "is");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().attribute("t", "s");
|
|
|
|
serializer().element(xmlns, "v", match_index);
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
if (cell.data_type() != cell::type::null)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
if (cell.data_type() == cell::type::boolean)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().attribute("t", "b");
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().element(xmlns, "v", write_bool(cell.value<bool>()));
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
2016-12-02 21:37:50 +08:00
|
|
|
else if (cell.data_type() == cell::type::numeric)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
if (cell.has_formula())
|
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().element(xmlns, "f", cell.formula());
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().element(xmlns, "v", cell.to_string());
|
|
|
|
serializer().end_element(xmlns, "c");
|
|
|
|
|
2016-08-05 13:52:05 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().attribute("t", "n");
|
|
|
|
serializer().start_element(xmlns, "v");
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (is_integral(cell.value<long double>()))
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().characters(cell.value<long long>());
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
std::stringstream ss;
|
|
|
|
ss.precision(20);
|
2016-12-02 21:37:50 +08:00
|
|
|
ss << cell.value<long double>();
|
2016-08-05 13:52:05 +08:00
|
|
|
ss.str();
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().characters(ss.str());
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
2016-09-20 06:52:11 +08:00
|
|
|
|
|
|
|
serializer().end_element(xmlns, "v");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (cell.has_formula())
|
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().element(xmlns, "f", cell.formula());
|
2016-11-15 10:14:42 +08:00
|
|
|
// todo (but probably not) could calculate the formula and set the value here
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().end_element(xmlns, "c");
|
|
|
|
|
2016-11-15 10:14:42 +08:00
|
|
|
continue;
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
}
|
2016-09-20 06:52:11 +08:00
|
|
|
|
|
|
|
serializer().end_element(xmlns, "c");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
}
|
2016-09-20 06:52:11 +08:00
|
|
|
|
|
|
|
serializer().end_element(xmlns, "row");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
2016-09-20 06:52:11 +08:00
|
|
|
|
|
|
|
serializer().end_element(xmlns, "sheetData");
|
|
|
|
|
2016-08-05 13:52:05 +08:00
|
|
|
if (ws.has_auto_filter())
|
|
|
|
{
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().start_element(xmlns, "autoFilter");
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().attribute("ref", ws.auto_filter().to_string());
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().end_element(xmlns, "autoFilter");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (!ws.merged_ranges().empty())
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().start_element(xmlns, "mergeCells");
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().attribute("count", ws.merged_ranges().size());
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
for (auto merged_range : ws.merged_ranges())
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().start_element(xmlns, "mergeCell");
|
|
|
|
serializer().attribute("ref", merged_range.to_string());
|
|
|
|
serializer().end_element(xmlns, "mergeCell");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
2016-09-20 06:52:11 +08:00
|
|
|
|
|
|
|
serializer().end_element(xmlns, "mergeCells");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (!hyperlink_rels.empty())
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().start_element(xmlns, "hyperlinks");
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
for (const auto &hyperlink : hyperlink_references)
|
|
|
|
{
|
|
|
|
serializer().start_element(xmlns, "hyperlink");
|
|
|
|
serializer().attribute("ref", hyperlink.first);
|
|
|
|
serializer().attribute(xmlns_r, "id", hyperlink.second);
|
|
|
|
serializer().end_element(xmlns, "hyperlink");
|
|
|
|
}
|
|
|
|
|
|
|
|
serializer().end_element(xmlns, "hyperlinks");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-08-14 02:45:26 +08:00
|
|
|
if (ws.has_page_setup())
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().start_element(xmlns, "printOptions");
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().attribute("horizontalCentered", write_bool(ws.page_setup().horizontal_centered()));
|
|
|
|
serializer().attribute("verticalCentered", write_bool(ws.page_setup().vertical_centered()));
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().end_element(xmlns, "printOptions");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-08-14 02:45:26 +08:00
|
|
|
if (ws.has_page_margins())
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().start_element(xmlns, "pageMargins");
|
2016-08-14 02:45:26 +08:00
|
|
|
|
|
|
|
//TODO: there must be a better way to do this
|
|
|
|
auto remove_trailing_zeros = [](const std::string &n)
|
|
|
|
{
|
|
|
|
auto decimal = n.find('.');
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-08-14 02:45:26 +08:00
|
|
|
if (decimal == std::string::npos) return n;
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-08-14 02:45:26 +08:00
|
|
|
auto index = n.size() - 1;
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-08-14 02:45:26 +08:00
|
|
|
while (index >= decimal && n[index] == '0')
|
|
|
|
{
|
|
|
|
index--;
|
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-08-14 02:45:26 +08:00
|
|
|
if (index == decimal)
|
|
|
|
{
|
|
|
|
return n.substr(0, decimal);
|
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-08-14 02:45:26 +08:00
|
|
|
return n.substr(0, index + 1);
|
|
|
|
};
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().attribute("left", remove_trailing_zeros(std::to_string(ws.page_margins().left())));
|
|
|
|
serializer().attribute("right", remove_trailing_zeros(std::to_string(ws.page_margins().right())));
|
|
|
|
serializer().attribute("top", remove_trailing_zeros(std::to_string(ws.page_margins().top())));
|
|
|
|
serializer().attribute("bottom", remove_trailing_zeros(std::to_string(ws.page_margins().bottom())));
|
|
|
|
serializer().attribute("header", remove_trailing_zeros(std::to_string(ws.page_margins().header())));
|
|
|
|
serializer().attribute("footer", remove_trailing_zeros(std::to_string(ws.page_margins().footer())));
|
2016-09-20 06:52:11 +08:00
|
|
|
|
|
|
|
serializer().end_element(xmlns, "pageMargins");
|
2016-08-14 02:45:26 +08:00
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-08-14 02:45:26 +08:00
|
|
|
if (ws.has_page_setup())
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().start_element(xmlns, "pageSetup");
|
|
|
|
serializer().attribute("orientation",
|
2016-12-02 21:37:50 +08:00
|
|
|
ws.page_setup().orientation() == xlnt::orientation::landscape
|
2016-09-20 06:52:11 +08:00
|
|
|
? "landscape" : "portrait");
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().attribute("paperSize", static_cast<std::size_t>(ws.page_setup().paper_size()));
|
|
|
|
serializer().attribute("fitToHeight", write_bool(ws.page_setup().fit_to_height()));
|
|
|
|
serializer().attribute("fitToWidth", write_bool(ws.page_setup().fit_to_width()));
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().end_element(xmlns, "pageSetup");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-12-10 08:18:50 +08:00
|
|
|
if (ws.has_header_footer())
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-12-10 08:18:50 +08:00
|
|
|
const auto hf = ws.header_footer();
|
2016-09-20 06:52:11 +08:00
|
|
|
|
|
|
|
serializer().start_element(xmlns, "headerFooter");
|
2016-12-10 08:18:50 +08:00
|
|
|
|
|
|
|
auto odd_header = std::string();
|
|
|
|
auto odd_footer = std::string();
|
|
|
|
auto even_header = std::string();
|
|
|
|
auto even_footer = std::string();
|
|
|
|
auto first_header = std::string();
|
|
|
|
auto first_footer = std::string();
|
|
|
|
|
|
|
|
const auto encode_text = [](const formatted_text &t, header_footer::location where)
|
|
|
|
{
|
2016-12-14 18:39:59 +08:00
|
|
|
const auto location_code_map = std::unordered_map<header_footer::location, std::string, scoped_enum_hash<header_footer::location>>
|
2016-12-10 08:18:50 +08:00
|
|
|
{
|
2016-12-14 18:39:59 +08:00
|
|
|
{ header_footer::location::left, "&L" },
|
|
|
|
{ header_footer::location::center, "&C" },
|
|
|
|
{ header_footer::location::right, "&R" },
|
2016-12-10 08:18:50 +08:00
|
|
|
};
|
2016-12-14 18:39:59 +08:00
|
|
|
|
2016-12-23 07:57:22 +08:00
|
|
|
auto encoded = location_code_map.at(where);
|
|
|
|
|
|
|
|
for (const auto &run : t.runs())
|
|
|
|
{
|
|
|
|
if (run.string().empty()) continue;
|
|
|
|
|
|
|
|
if (run.has_formatting())
|
|
|
|
{
|
|
|
|
if (run.has_font())
|
|
|
|
{
|
|
|
|
encoded.push_back('&');
|
|
|
|
encoded.push_back('"');
|
|
|
|
encoded.append(run.font());
|
|
|
|
encoded.push_back(',');
|
|
|
|
|
|
|
|
if (run.bold())
|
|
|
|
{
|
|
|
|
encoded.append("Bold");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
encoded.append("Regular");
|
|
|
|
}
|
|
|
|
//todo: BoldItalic?
|
|
|
|
|
|
|
|
encoded.push_back('"');
|
|
|
|
}
|
|
|
|
else if (run.bold())
|
|
|
|
{
|
|
|
|
encoded.append("&B");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (run.has_size())
|
|
|
|
{
|
|
|
|
encoded.push_back('&');
|
|
|
|
encoded.append(std::to_string(run.size()));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (run.has_color())
|
|
|
|
{
|
|
|
|
encoded.push_back('&');
|
|
|
|
encoded.push_back('K');
|
|
|
|
encoded.append(run.color().rgb().hex_string().substr(2));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
encoded.append(run.string());
|
|
|
|
}
|
|
|
|
|
|
|
|
return encoded;
|
2016-12-10 08:18:50 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
const auto locations =
|
|
|
|
{
|
|
|
|
header_footer::location::left,
|
|
|
|
header_footer::location::center,
|
|
|
|
header_footer::location::right
|
|
|
|
};
|
|
|
|
|
|
|
|
for (auto location : locations)
|
|
|
|
{
|
|
|
|
if (hf.different_odd_even())
|
|
|
|
{
|
|
|
|
if (hf.has_odd_even_header(location))
|
|
|
|
{
|
|
|
|
odd_header.append(encode_text(hf.odd_header(location), location));
|
|
|
|
even_header.append(encode_text(hf.even_header(location), location));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hf.has_odd_even_footer(location))
|
|
|
|
{
|
|
|
|
odd_footer.append(encode_text(hf.odd_footer(location), location));
|
|
|
|
even_footer.append(encode_text(hf.even_footer(location), location));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (hf.has_header(location))
|
|
|
|
{
|
|
|
|
odd_header.append(encode_text(hf.header(location), location));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hf.has_footer(location))
|
|
|
|
{
|
|
|
|
odd_footer.append(encode_text(hf.footer(location), location));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hf.different_first())
|
|
|
|
{
|
|
|
|
if (hf.has_first_page_header(location))
|
|
|
|
{
|
|
|
|
first_header.append(encode_text(hf.first_page_header(location), location));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hf.has_first_page_footer(location))
|
|
|
|
{
|
|
|
|
first_footer.append(encode_text(hf.first_page_footer(location), location));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!odd_header.empty())
|
|
|
|
{
|
|
|
|
serializer().element(xmlns, "oddHeader", odd_header);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!odd_footer.empty())
|
|
|
|
{
|
|
|
|
serializer().element(xmlns, "oddFooter", odd_footer);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!even_header.empty())
|
|
|
|
{
|
|
|
|
serializer().element(xmlns, "evenHeader", even_header);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!even_footer.empty())
|
|
|
|
{
|
|
|
|
serializer().element(xmlns, "evenFooter", even_footer);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!first_header.empty())
|
|
|
|
{
|
|
|
|
serializer().element(xmlns, "firstHeader", first_header);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!first_footer.empty())
|
|
|
|
{
|
|
|
|
serializer().element(xmlns, "firstFooter", first_footer);
|
|
|
|
}
|
|
|
|
|
2016-09-20 06:52:11 +08:00
|
|
|
serializer().end_element(xmlns, "headerFooter");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
2016-10-30 04:31:30 +08:00
|
|
|
|
2016-12-23 07:57:22 +08:00
|
|
|
if (!ws.row_breaks().empty())
|
|
|
|
{
|
|
|
|
serializer().start_element(xmlns, "rowBreaks");
|
|
|
|
|
|
|
|
serializer().attribute("count", ws.row_breaks().size());
|
|
|
|
serializer().attribute("manualBreakCount", ws.row_breaks().size());
|
|
|
|
|
|
|
|
for (auto break_id : ws.row_breaks())
|
|
|
|
{
|
|
|
|
serializer().start_element(xmlns, "brk");
|
|
|
|
serializer().attribute("id", break_id);
|
|
|
|
serializer().attribute("max", 16383);
|
|
|
|
serializer().attribute("man", 1);
|
|
|
|
serializer().end_element(xmlns, "brk");
|
|
|
|
}
|
|
|
|
|
|
|
|
serializer().end_element(xmlns, "rowBreaks");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ws.column_breaks().empty())
|
|
|
|
{
|
|
|
|
serializer().start_element(xmlns, "colBreaks");
|
|
|
|
|
|
|
|
serializer().attribute("count", ws.column_breaks().size());
|
|
|
|
serializer().attribute("manualBreakCount", ws.column_breaks().size());
|
|
|
|
|
|
|
|
for (auto break_id : ws.column_breaks())
|
|
|
|
{
|
|
|
|
serializer().start_element(xmlns, "brk");
|
|
|
|
serializer().attribute("id", break_id.index);
|
|
|
|
serializer().attribute("max", 1048575);
|
|
|
|
serializer().attribute("man", 1);
|
|
|
|
serializer().end_element(xmlns, "brk");
|
|
|
|
}
|
|
|
|
|
|
|
|
serializer().end_element(xmlns, "colBreaks");
|
|
|
|
}
|
|
|
|
|
2016-10-30 04:31:30 +08:00
|
|
|
if (!worksheet_rels.empty())
|
|
|
|
{
|
|
|
|
for (const auto &child_rel : worksheet_rels)
|
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
if (child_rel.type() == xlnt::relationship_type::vml_drawing)
|
2016-10-30 04:31:30 +08:00
|
|
|
{
|
|
|
|
serializer().start_element(xmlns, "legacyDrawing");
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().attribute(xml::qname(xmlns_r, "id"), child_rel.id());
|
2016-10-30 04:31:30 +08:00
|
|
|
serializer().end_element(xmlns, "legacyDrawing");
|
|
|
|
|
|
|
|
//todo: there's only one of these per sheet, right?
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-09-17 10:59:13 +08:00
|
|
|
|
2016-10-30 04:31:30 +08:00
|
|
|
serializer().end_element(xmlns, "worksheet");
|
|
|
|
|
|
|
|
if (!worksheet_rels.empty())
|
|
|
|
{
|
|
|
|
write_relationships(worksheet_rels, worksheet_part);
|
|
|
|
|
|
|
|
for (const auto &child_rel : worksheet_rels)
|
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
if (child_rel.target_mode() == target_mode::external) continue;
|
|
|
|
|
|
|
|
// todo: this is ugly
|
|
|
|
path archive_path(worksheet_part.parent().append(child_rel.target().path()));
|
2016-10-30 04:31:30 +08:00
|
|
|
auto split_part_path = archive_path.split();
|
|
|
|
auto part_path_iter = split_part_path.begin();
|
|
|
|
while (part_path_iter != split_part_path.end())
|
|
|
|
{
|
|
|
|
if (*part_path_iter == "..")
|
|
|
|
{
|
|
|
|
part_path_iter = split_part_path.erase(part_path_iter - 1, part_path_iter + 1);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
++part_path_iter;
|
|
|
|
}
|
|
|
|
archive_path = std::accumulate(split_part_path.begin(), split_part_path.end(), path(""),
|
|
|
|
[](const path &a, const std::string &b) { return a.append(b); });
|
2016-10-31 03:48:40 +08:00
|
|
|
|
|
|
|
begin_part(archive_path);
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
switch (child_rel.type())
|
2016-10-31 03:48:40 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::comments:
|
2016-10-31 03:48:40 +08:00
|
|
|
write_comments(child_rel, ws, cells_with_comments);
|
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::vml_drawing:
|
2016-10-31 03:48:40 +08:00
|
|
|
write_vml_drawings(child_rel, ws, cells_with_comments);
|
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::office_document: break;
|
|
|
|
case relationship_type::thumbnail: break;
|
|
|
|
case relationship_type::calculation_chain: break;
|
|
|
|
case relationship_type::extended_properties: break;
|
|
|
|
case relationship_type::core_properties: break;
|
|
|
|
case relationship_type::worksheet: break;
|
|
|
|
case relationship_type::shared_string_table: break;
|
|
|
|
case relationship_type::stylesheet: break;
|
|
|
|
case relationship_type::theme: break;
|
|
|
|
case relationship_type::hyperlink: break;
|
|
|
|
case relationship_type::chartsheet: break;
|
|
|
|
case relationship_type::unknown: break;
|
|
|
|
case relationship_type::custom_properties: break;
|
|
|
|
case relationship_type::printer_settings: break;
|
|
|
|
case relationship_type::connections: break;
|
|
|
|
case relationship_type::custom_property: break;
|
|
|
|
case relationship_type::custom_xml_mappings: break;
|
|
|
|
case relationship_type::dialogsheet: break;
|
|
|
|
case relationship_type::drawings: break;
|
|
|
|
case relationship_type::external_workbook_references: break;
|
|
|
|
case relationship_type::metadata: break;
|
|
|
|
case relationship_type::pivot_table: break;
|
|
|
|
case relationship_type::pivot_table_cache_definition: break;
|
|
|
|
case relationship_type::pivot_table_cache_records: break;
|
|
|
|
case relationship_type::query_table: break;
|
|
|
|
case relationship_type::shared_workbook_revision_headers: 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::volatile_dependencies: break;
|
|
|
|
case relationship_type::image: break;
|
2016-10-31 03:48:40 +08:00
|
|
|
}
|
2016-10-30 04:31:30 +08:00
|
|
|
}
|
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Sheet Relationship Target Parts
|
|
|
|
|
2016-11-10 08:52:18 +08:00
|
|
|
void xlsx_producer::write_comments(const relationship &/*rel*/, worksheet ws,
|
2016-10-30 04:31:30 +08:00
|
|
|
const std::vector<cell_reference> &cells)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
static const auto &xmlns = constants::namespace_("spreadsheetml");
|
2016-10-30 04:31:30 +08:00
|
|
|
|
|
|
|
serializer().start_element(xmlns, "comments");
|
|
|
|
serializer().namespace_decl(xmlns, "");
|
|
|
|
|
|
|
|
if (!cells.empty())
|
|
|
|
{
|
|
|
|
std::unordered_map<std::string, std::size_t> authors;
|
|
|
|
|
|
|
|
for (auto cell_ref : cells)
|
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
auto cell = ws.cell(cell_ref);
|
2016-10-30 04:31:30 +08:00
|
|
|
auto author = cell.comment().author();
|
|
|
|
|
|
|
|
if (authors.find(author) == authors.end())
|
|
|
|
{
|
|
|
|
authors[author] = authors.size();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
serializer().start_element(xmlns, "authors");
|
|
|
|
|
|
|
|
for (const auto &author : authors)
|
|
|
|
{
|
|
|
|
serializer().start_element(xmlns, "author");
|
|
|
|
serializer().characters(author.first);
|
|
|
|
serializer().end_element(xmlns, "author");
|
|
|
|
}
|
|
|
|
|
|
|
|
serializer().end_element(xmlns, "authors");
|
|
|
|
serializer().start_element(xmlns, "commentList");
|
|
|
|
|
|
|
|
for (const auto &cell_ref : cells)
|
|
|
|
{
|
|
|
|
serializer().start_element(xmlns, "comment");
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
auto cell = ws.cell(cell_ref);
|
2016-10-30 04:31:30 +08:00
|
|
|
auto cell_comment = cell.comment();
|
|
|
|
|
|
|
|
serializer().attribute("ref", cell_ref.to_string());
|
|
|
|
auto author_id = authors.at(cell_comment.author());
|
|
|
|
serializer().attribute("authorId", author_id);
|
|
|
|
serializer().start_element(xmlns, "text");
|
|
|
|
|
|
|
|
for (const auto &run : cell_comment.text().runs())
|
|
|
|
{
|
|
|
|
serializer().start_element(xmlns, "r");
|
|
|
|
|
|
|
|
if (run.has_formatting())
|
|
|
|
{
|
|
|
|
serializer().start_element(xmlns, "rPr");
|
|
|
|
|
|
|
|
if (run.has_size())
|
|
|
|
{
|
|
|
|
serializer().start_element(xmlns, "sz");
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().attribute("val", run.size());
|
2016-10-30 04:31:30 +08:00
|
|
|
serializer().end_element(xmlns, "sz");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (run.has_color())
|
|
|
|
{
|
|
|
|
serializer().start_element(xmlns, "color");
|
2016-12-02 21:37:50 +08:00
|
|
|
write_color(run.color());
|
2016-10-30 04:31:30 +08:00
|
|
|
serializer().end_element(xmlns, "color");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (run.has_font())
|
|
|
|
{
|
|
|
|
serializer().start_element(xmlns, "rFont");
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().attribute("val", run.font());
|
2016-10-30 04:31:30 +08:00
|
|
|
serializer().end_element(xmlns, "rFont");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (run.has_family())
|
|
|
|
{
|
|
|
|
serializer().start_element(xmlns, "family");
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().attribute("val", run.family());
|
2016-10-30 04:31:30 +08:00
|
|
|
serializer().end_element(xmlns, "family");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (run.has_scheme())
|
|
|
|
{
|
|
|
|
serializer().start_element(xmlns, "scheme");
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().attribute("val", run.scheme());
|
2016-10-30 04:31:30 +08:00
|
|
|
serializer().end_element(xmlns, "scheme");
|
|
|
|
}
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (run.bold())
|
2016-10-30 04:31:30 +08:00
|
|
|
{
|
|
|
|
serializer().start_element(xmlns, "b");
|
|
|
|
serializer().end_element(xmlns, "b");
|
|
|
|
}
|
|
|
|
|
|
|
|
serializer().end_element(xmlns, "rPr");
|
|
|
|
}
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().element(xmlns, "t", run.string());
|
2016-10-30 04:31:30 +08:00
|
|
|
serializer().end_element(xmlns, "r");
|
|
|
|
}
|
|
|
|
|
|
|
|
serializer().end_element(xmlns, "text");
|
|
|
|
serializer().end_element(xmlns, "comment");
|
|
|
|
}
|
|
|
|
|
|
|
|
serializer().end_element(xmlns, "commentList");
|
|
|
|
}
|
|
|
|
|
|
|
|
serializer().end_element(xmlns, "comments");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-11-01 09:53:22 +08:00
|
|
|
void xlsx_producer::write_vml_drawings(const relationship &rel, worksheet ws,
|
|
|
|
const std::vector<cell_reference> &cells)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-11-13 06:38:29 +08:00
|
|
|
static const auto &xmlns_mv = std::string("http://macVmlSchemaUri");
|
|
|
|
static const auto &xmlns_o = std::string("urn:schemas-microsoft-com:office:office");
|
2016-11-10 08:52:18 +08:00
|
|
|
static const auto &xmlns_v = std::string("urn:schemas-microsoft-com:vml");
|
2016-11-13 06:38:29 +08:00
|
|
|
static const auto &xmlns_x = std::string("urn:schemas-microsoft-com:office:excel");
|
|
|
|
|
|
|
|
serializer().start_element("xml");
|
|
|
|
serializer().namespace_decl(xmlns_v, "v");
|
|
|
|
serializer().namespace_decl(xmlns_o, "o");
|
|
|
|
serializer().namespace_decl(xmlns_x, "x");
|
|
|
|
serializer().namespace_decl(xmlns_mv, "mv");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns_o, "shapelayout");
|
|
|
|
serializer().attribute(xml::qname(xmlns_v, "ext"), "edit");
|
|
|
|
serializer().start_element(xmlns_o, "idmap");
|
|
|
|
serializer().attribute(xml::qname(xmlns_v, "ext"), "edit");
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
auto filename = rel.target().path().split_extension().first;
|
2016-11-13 06:38:29 +08:00
|
|
|
auto index_pos = filename.size() - 1;
|
|
|
|
|
|
|
|
while (filename[index_pos] >= '0' && filename[index_pos] <= '9')
|
|
|
|
{
|
2016-11-27 16:35:21 +08:00
|
|
|
index_pos--;
|
2016-11-13 06:38:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
auto file_index = std::stoull(filename.substr(index_pos + 1));
|
|
|
|
|
|
|
|
serializer().attribute("data", file_index);
|
|
|
|
serializer().end_element(xmlns_o, "idmap");
|
|
|
|
serializer().end_element(xmlns_o, "shapelayout");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns_v, "shapetype");
|
|
|
|
serializer().attribute("id", "_x0000_t202");
|
|
|
|
serializer().attribute("coordsize", "21600,21600");
|
|
|
|
serializer().attribute(xml::qname(xmlns_o, "spt"), "202");
|
|
|
|
serializer().attribute("path", "m0,0l0,21600,21600,21600,21600,0xe");
|
|
|
|
serializer().start_element(xmlns_v, "stroke");
|
|
|
|
serializer().attribute("joinstyle", "miter");
|
|
|
|
serializer().end_element(xmlns_v, "stroke");
|
|
|
|
serializer().start_element(xmlns_v, "path");
|
|
|
|
serializer().attribute("gradientshapeok", "t");
|
|
|
|
serializer().attribute(xml::qname(xmlns_o, "connecttype"), "rect");
|
|
|
|
serializer().end_element(xmlns_v, "path");
|
|
|
|
serializer().end_element(xmlns_v, "shapetype");
|
|
|
|
|
|
|
|
std::size_t comment_index = 0;
|
|
|
|
|
|
|
|
for (const auto &cell_ref : cells)
|
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
auto comment = ws.cell(cell_ref).comment();
|
2016-11-01 10:35:42 +08:00
|
|
|
auto shape_id = 1024 * file_index + 1 + comment_index * 2;
|
2016-11-01 09:53:22 +08:00
|
|
|
|
2016-11-13 06:38:29 +08:00
|
|
|
serializer().start_element(xmlns_v, "shape");
|
|
|
|
serializer().attribute("id", "_x0000_s" + std::to_string(shape_id));
|
|
|
|
serializer().attribute("type", "#_x0000_t202");
|
|
|
|
|
|
|
|
std::vector<std::pair<std::string, std::string>> style;
|
|
|
|
|
|
|
|
style.push_back({"position", "absolute"});
|
|
|
|
style.push_back({"margin-left", std::to_string(comment.left())});
|
|
|
|
style.push_back({"margin-top", std::to_string(comment.top())});
|
|
|
|
style.push_back({"width", std::to_string(comment.width())});
|
|
|
|
style.push_back({"height", std::to_string(comment.height())});
|
|
|
|
style.push_back({"z-index", std::to_string(comment_index + 1)});
|
|
|
|
style.push_back({"visibility", comment.visible() ? "visible" : "hidden"});
|
|
|
|
|
|
|
|
std::string style_string;
|
|
|
|
|
|
|
|
for (auto part : style)
|
|
|
|
{
|
|
|
|
style_string.append(part.first);
|
|
|
|
style_string.append(":");
|
|
|
|
style_string.append(part.second);
|
2016-11-28 01:32:00 +08:00
|
|
|
style_string.append(";");
|
2016-11-13 06:38:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
serializer().attribute("style", style_string);
|
|
|
|
serializer().attribute("fillcolor", "#fbf6d6");
|
|
|
|
serializer().attribute("strokecolor", "#edeaa1");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns_v, "fill");
|
|
|
|
serializer().attribute("color2", "#fbfe82");
|
|
|
|
serializer().attribute("angle", -180);
|
|
|
|
serializer().attribute("type", "gradient");
|
|
|
|
serializer().start_element(xmlns_o, "fill");
|
|
|
|
serializer().attribute(xml::qname(xmlns_v, "ext"), "view");
|
|
|
|
serializer().attribute("type", "gradientUnscaled");
|
|
|
|
serializer().end_element(xmlns_o, "fill");
|
|
|
|
serializer().end_element(xmlns_v, "fill");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns_v, "shadow");
|
|
|
|
serializer().attribute("on", "t");
|
|
|
|
serializer().attribute("obscured", "t");
|
|
|
|
serializer().end_element(xmlns_v, "shadow");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns_v, "path");
|
|
|
|
serializer().attribute(xml::qname(xmlns_o, "connecttype"), "none");
|
|
|
|
serializer().end_element(xmlns_v, "path");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns_v, "textbox");
|
|
|
|
serializer().attribute("style", "mso-direction-alt:auto");
|
|
|
|
serializer().start_element("div");
|
|
|
|
serializer().attribute("style", "text-align:left");
|
|
|
|
serializer().characters("");
|
|
|
|
serializer().end_element("div");
|
|
|
|
serializer().end_element(xmlns_v, "textbox");
|
|
|
|
|
|
|
|
serializer().start_element(xmlns_x, "ClientData");
|
|
|
|
serializer().attribute("ObjectType", "Note");
|
|
|
|
serializer().start_element(xmlns_x, "MoveWithCells");
|
|
|
|
serializer().end_element(xmlns_x, "MoveWithCells");
|
|
|
|
serializer().start_element(xmlns_x, "SizeWithCells");
|
|
|
|
serializer().end_element(xmlns_x, "SizeWithCells");
|
|
|
|
serializer().start_element(xmlns_x, "Anchor");
|
|
|
|
serializer().characters("1, 15, 0, " + std::to_string(2 + comment_index * 4) + ", 2, 54, 4, 14");
|
|
|
|
serializer().end_element(xmlns_x, "Anchor");
|
|
|
|
serializer().start_element(xmlns_x, "AutoFill");
|
|
|
|
serializer().characters("False");
|
|
|
|
serializer().end_element(xmlns_x, "AutoFill");
|
|
|
|
serializer().start_element(xmlns_x, "Row");
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().characters(cell_ref.row() - 1);
|
2016-11-13 06:38:29 +08:00
|
|
|
serializer().end_element(xmlns_x, "Row");
|
|
|
|
serializer().start_element(xmlns_x, "Column");
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().characters(cell_ref.column_index() - 1);
|
2016-11-13 06:38:29 +08:00
|
|
|
serializer().end_element(xmlns_x, "Column");
|
|
|
|
serializer().end_element(xmlns_x, "ClientData");
|
|
|
|
|
|
|
|
serializer().end_element(xmlns_v, "shape");
|
|
|
|
|
|
|
|
++comment_index;
|
|
|
|
}
|
2016-10-30 04:31:30 +08:00
|
|
|
|
2016-11-13 06:38:29 +08:00
|
|
|
serializer().end_element("xml");
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-08-06 22:40:17 +08:00
|
|
|
// Other Parts
|
|
|
|
|
2016-09-18 23:32:59 +08:00
|
|
|
void xlsx_producer::write_custom_property()
|
2016-08-06 22:40:17 +08:00
|
|
|
{
|
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-09-18 23:32:59 +08:00
|
|
|
void xlsx_producer::write_unknown_parts()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-09-18 23:32:59 +08:00
|
|
|
void xlsx_producer::write_unknown_relationships()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
void xlsx_producer::write_image(const path &image_path)
|
2016-08-12 12:22:14 +08:00
|
|
|
{
|
2016-11-01 08:48:43 +08:00
|
|
|
end_part();
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
vector_istreambuf buffer(source_.d_->images_.at(image_path.string()));
|
|
|
|
archive_->open(image_path.string()) << &buffer;
|
2016-08-12 12:22:14 +08:00
|
|
|
}
|
|
|
|
|
2016-09-18 23:32:59 +08:00
|
|
|
xml::serializer &xlsx_producer::serializer()
|
|
|
|
{
|
2016-10-31 03:48:40 +08:00
|
|
|
return *current_part_serializer_;
|
2016-09-18 23:32:59 +08:00
|
|
|
}
|
|
|
|
|
2016-08-18 19:34:18 +08:00
|
|
|
std::string xlsx_producer::write_bool(bool boolean) const
|
|
|
|
{
|
|
|
|
return boolean ? "true" : "false";
|
|
|
|
}
|
|
|
|
|
2016-09-18 23:32:59 +08:00
|
|
|
|
|
|
|
void xlsx_producer::write_relationships(const std::vector<xlnt::relationship> &relationships, const path &part)
|
|
|
|
{
|
|
|
|
path parent = part.parent();
|
|
|
|
|
|
|
|
if (parent.is_absolute())
|
|
|
|
{
|
|
|
|
parent = path(parent.string().substr(1));
|
|
|
|
}
|
|
|
|
|
2016-10-31 03:48:40 +08:00
|
|
|
path rels_path(parent.append("_rels").append(part.filename() + ".rels").string());
|
|
|
|
begin_part(rels_path);
|
2016-09-18 23:32:59 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
const auto xmlns = xlnt::constants::namespace_("relationships");
|
2016-09-18 23:32:59 +08:00
|
|
|
|
2016-10-31 03:48:40 +08:00
|
|
|
serializer().start_element(xmlns, "Relationships");
|
|
|
|
serializer().namespace_decl(xmlns, "");
|
2016-09-18 23:32:59 +08:00
|
|
|
|
|
|
|
for (const auto &relationship : relationships)
|
|
|
|
{
|
2016-10-31 03:48:40 +08:00
|
|
|
serializer().start_element(xmlns, "Relationship");
|
2016-09-18 23:32:59 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
serializer().attribute("Id", relationship.id());
|
|
|
|
serializer().attribute("Type", relationship.type());
|
|
|
|
serializer().attribute("Target", relationship.target().path().string());
|
2016-09-18 23:32:59 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (relationship.target_mode() == xlnt::target_mode::external)
|
2016-09-18 23:32:59 +08:00
|
|
|
{
|
2016-10-31 03:48:40 +08:00
|
|
|
serializer().attribute("TargetMode", "External");
|
2016-09-18 23:32:59 +08:00
|
|
|
}
|
|
|
|
|
2016-10-31 03:48:40 +08:00
|
|
|
serializer().end_element(xmlns, "Relationship");
|
2016-09-18 23:32:59 +08:00
|
|
|
}
|
|
|
|
|
2016-10-31 03:48:40 +08:00
|
|
|
serializer().end_element(xmlns, "Relationships");
|
2016-09-18 23:32:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-19 09:49:37 +08:00
|
|
|
void xlsx_producer::write_color(const xlnt::color &color)
|
2016-09-18 23:32:59 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
if (color.is_auto())
|
|
|
|
{
|
|
|
|
serializer().attribute("auto", write_bool(true));
|
|
|
|
return;
|
|
|
|
}
|
2016-09-18 23:32:59 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
switch (color.type())
|
|
|
|
{
|
|
|
|
case xlnt::color_type::theme:
|
|
|
|
serializer().attribute("theme", color.theme().index());
|
2016-09-18 23:32:59 +08:00
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case xlnt::color_type::indexed:
|
|
|
|
serializer().attribute("indexed", color.indexed().index());
|
2016-11-10 08:52:18 +08:00
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case xlnt::color_type::rgb:
|
|
|
|
serializer().attribute("rgb", color.rgb().hex_string());
|
2016-09-18 23:32:59 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-05 13:52:05 +08:00
|
|
|
} // namespace detail
|
|
|
|
} // namepsace xlnt
|