mirror of
https://github.com/tfussell/xlnt.git
synced 2024-03-22 13:11:17 +08:00
implement app properties reading/writing, case-insenstive border enum->string conversions for some style enums
This commit is contained in:
parent
e7b062bb4c
commit
0c3a167f7c
48
include/xlnt/packaging/app_properties.hpp
Normal file
48
include/xlnt/packaging/app_properties.hpp
Normal file
|
@ -0,0 +1,48 @@
|
|||
// Copyright (c) 2014-2016 Thomas Fussell
|
||||
// Copyright (c) 2010-2015 openpyxl
|
||||
//
|
||||
// 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
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <xlnt/xlnt_config.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
/// <summary>
|
||||
/// High-level properties of the OOXML document regarding the app that created it.
|
||||
/// </summary>
|
||||
class XLNT_CLASS app_properties
|
||||
{
|
||||
public:
|
||||
std::string application = "libxlnt";
|
||||
int doc_security = 0;
|
||||
bool scale_crop = false;
|
||||
std::string company = "";
|
||||
bool links_up_to_date = false;
|
||||
bool shared_doc = false;
|
||||
bool hyperlinks_changed = false;
|
||||
std::string app_version = "0.9";
|
||||
};
|
||||
|
||||
} // namespace xlnt
|
|
@ -35,6 +35,7 @@
|
|||
namespace xlnt {
|
||||
|
||||
class alignment;
|
||||
class app_properties;
|
||||
class border;
|
||||
class color;
|
||||
class const_worksheet_iterator;
|
||||
|
@ -136,6 +137,9 @@ public:
|
|||
document_properties &get_properties();
|
||||
const document_properties &get_properties() const;
|
||||
|
||||
app_properties &get_app_properties();
|
||||
const app_properties &get_app_properties() const;
|
||||
|
||||
// named ranges
|
||||
std::vector<named_range> get_named_ranges() const;
|
||||
void create_named_range(const std::string &name, worksheet worksheet, const range_reference &reference);
|
||||
|
|
|
@ -40,6 +40,7 @@ struct workbook_impl
|
|||
drawings_(other.drawings_),
|
||||
shared_strings_(other.shared_strings_),
|
||||
properties_(other.properties_),
|
||||
app_properties_(other.app_properties_),
|
||||
guess_types_(other.guess_types_),
|
||||
data_only_(other.data_only_),
|
||||
read_only_(other.read_only_),
|
||||
|
@ -68,6 +69,7 @@ struct workbook_impl
|
|||
shared_strings_.clear();
|
||||
std::copy(other.shared_strings_.begin(), other.shared_strings_.end(), std::back_inserter(shared_strings_));
|
||||
properties_ = other.properties_;
|
||||
app_properties_ = other.app_properties_;
|
||||
guess_types_ = other.guess_types_;
|
||||
data_only_ = other.data_only_;
|
||||
read_only_ = other.read_only_;
|
||||
|
@ -90,6 +92,7 @@ struct workbook_impl
|
|||
std::vector<std::string> shared_strings_;
|
||||
|
||||
document_properties properties_;
|
||||
app_properties app_properties_;
|
||||
|
||||
bool guess_types_;
|
||||
bool data_only_;
|
||||
|
|
|
@ -3,13 +3,14 @@
|
|||
#include <iostream>
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include <xlnt/packaging/app_properties.hpp>
|
||||
#include <xlnt/serialization/workbook_serializer.hpp>
|
||||
#include <xlnt/serialization/xml_document.hpp>
|
||||
|
||||
#include <helpers/path_helper.hpp>
|
||||
#include <helpers/helper.hpp>
|
||||
|
||||
class test_props : public CxxTest::TestSuite
|
||||
class test_core : public CxxTest::TestSuite
|
||||
{
|
||||
public:
|
||||
void test_read_properties_core()
|
||||
|
@ -86,6 +87,8 @@ public:
|
|||
void test_write_properties_app()
|
||||
{
|
||||
xlnt::workbook wb;
|
||||
wb.get_app_properties().application = "Microsoft Excel";
|
||||
wb.get_app_properties().app_version = "12.0000";
|
||||
wb.create_sheet();
|
||||
wb.create_sheet();
|
||||
xlnt::workbook_serializer serializer(wb);
|
||||
|
|
|
@ -94,6 +94,14 @@ bool load_workbook(xlnt::zip_file &archive, bool guess_types, bool data_only, xl
|
|||
workbook_serializer_.read_properties_core(core_properties_xml);
|
||||
}
|
||||
|
||||
if(archive.has_file(xlnt::constants::ArcApp()))
|
||||
{
|
||||
xlnt::workbook_serializer workbook_serializer_(wb);
|
||||
xlnt::xml_document app_properties_xml;
|
||||
app_properties_xml.from_string(archive.read(xlnt::constants::ArcApp()));
|
||||
workbook_serializer_.read_properties_app(app_properties_xml);
|
||||
}
|
||||
|
||||
xlnt::relationship_serializer relationship_serializer_(archive);
|
||||
auto workbook_relationships = relationship_serializer_.read_relationships(xlnt::constants::ArcWorkbook());
|
||||
|
||||
|
|
|
@ -34,6 +34,24 @@
|
|||
|
||||
namespace {
|
||||
|
||||
bool equals_case_insensitive(const std::string &left, const std::string &right)
|
||||
{
|
||||
if (left.size() != right.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < left.size(); i++)
|
||||
{
|
||||
if (std::tolower(left[i]) != std::tolower(right[i]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool is_true(const std::string &bool_string)
|
||||
{
|
||||
return bool_string == "1";
|
||||
|
@ -41,11 +59,11 @@ bool is_true(const std::string &bool_string)
|
|||
|
||||
xlnt::protection::type protection_type_from_string(const std::string &type_string)
|
||||
{
|
||||
if (type_string == "true")
|
||||
if (equals_case_insensitive(type_string, "true"))
|
||||
{
|
||||
return xlnt::protection::type::protected_;
|
||||
}
|
||||
else if (type_string == "inherit")
|
||||
else if (equals_case_insensitive(type_string, "inherit"))
|
||||
{
|
||||
return xlnt::protection::type::inherit;
|
||||
}
|
||||
|
@ -55,23 +73,23 @@ xlnt::protection::type protection_type_from_string(const std::string &type_strin
|
|||
|
||||
xlnt::font::underline_style underline_style_from_string(const std::string &underline_string)
|
||||
{
|
||||
if (underline_string == "none")
|
||||
if (equals_case_insensitive(underline_string, "none"))
|
||||
{
|
||||
return xlnt::font::underline_style::none;
|
||||
}
|
||||
else if (underline_string == "single")
|
||||
else if (equals_case_insensitive(underline_string, "single"))
|
||||
{
|
||||
return xlnt::font::underline_style::single;
|
||||
}
|
||||
else if (underline_string == "single-accounting")
|
||||
else if (equals_case_insensitive(underline_string, "single-accounting"))
|
||||
{
|
||||
return xlnt::font::underline_style::single_accounting;
|
||||
}
|
||||
else if (underline_string == "double")
|
||||
else if (equals_case_insensitive(underline_string, "double"))
|
||||
{
|
||||
return xlnt::font::underline_style::double_;
|
||||
}
|
||||
else if (underline_string == "double-accounting")
|
||||
else if (equals_case_insensitive(underline_string, "double-accounting"))
|
||||
{
|
||||
return xlnt::font::underline_style::double_accounting;
|
||||
}
|
||||
|
@ -81,73 +99,75 @@ xlnt::font::underline_style underline_style_from_string(const std::string &under
|
|||
|
||||
xlnt::fill::pattern_type pattern_fill_type_from_string(const std::string &fill_type)
|
||||
{
|
||||
if (fill_type == "none") return xlnt::fill::pattern_type::none;
|
||||
if (fill_type == "solid") return xlnt::fill::pattern_type::solid;
|
||||
if (fill_type == "gray125") return xlnt::fill::pattern_type::gray125;
|
||||
if (equals_case_insensitive(fill_type, "none")) return xlnt::fill::pattern_type::none;
|
||||
if (equals_case_insensitive(fill_type, "solid")) return xlnt::fill::pattern_type::solid;
|
||||
if (equals_case_insensitive(fill_type, "gray125")) return xlnt::fill::pattern_type::gray125;
|
||||
return xlnt::fill::pattern_type::none;
|
||||
};
|
||||
|
||||
xlnt::border_style border_style_from_string(const std::string &border_style_string)
|
||||
{
|
||||
if (border_style_string == "none")
|
||||
if (equals_case_insensitive(border_style_string, "none"))
|
||||
{
|
||||
return xlnt::border_style::none;
|
||||
}
|
||||
else if (border_style_string == "dashdot")
|
||||
else if (equals_case_insensitive(border_style_string, "dashdot"))
|
||||
{
|
||||
return xlnt::border_style::dashdot;
|
||||
}
|
||||
else if (border_style_string == "dashdotdot")
|
||||
else if (equals_case_insensitive(border_style_string, "dashdotdot"))
|
||||
{
|
||||
return xlnt::border_style::dashdotdot;
|
||||
}
|
||||
else if (border_style_string == "dashed")
|
||||
else if (equals_case_insensitive(border_style_string, "dashed"))
|
||||
{
|
||||
return xlnt::border_style::dashed;
|
||||
}
|
||||
else if (border_style_string == "dotted")
|
||||
else if (equals_case_insensitive(border_style_string, "dotted"))
|
||||
{
|
||||
return xlnt::border_style::dotted;
|
||||
}
|
||||
else if (border_style_string == "double")
|
||||
else if (equals_case_insensitive(border_style_string, "double"))
|
||||
{
|
||||
return xlnt::border_style::double_;
|
||||
}
|
||||
else if (border_style_string == "hair")
|
||||
else if (equals_case_insensitive(border_style_string, "hair"))
|
||||
{
|
||||
return xlnt::border_style::hair;
|
||||
}
|
||||
else if (border_style_string == "medium")
|
||||
else if (equals_case_insensitive(border_style_string, "medium"))
|
||||
{
|
||||
return xlnt::border_style::medium;
|
||||
}
|
||||
else if (border_style_string == "mediumdashdot")
|
||||
else if (equals_case_insensitive(border_style_string, "mediumdashdot"))
|
||||
{
|
||||
return xlnt::border_style::mediumdashdot;
|
||||
}
|
||||
else if (border_style_string == "mediumdashdotdot")
|
||||
else if (equals_case_insensitive(border_style_string, "mediumdashdotdot"))
|
||||
{
|
||||
return xlnt::border_style::mediumdashdotdot;
|
||||
}
|
||||
else if (border_style_string == "mediumdashed")
|
||||
else if (equals_case_insensitive(border_style_string, "mediumdashed"))
|
||||
{
|
||||
return xlnt::border_style::mediumdashed;
|
||||
}
|
||||
else if (border_style_string == "slantdashdot")
|
||||
else if (equals_case_insensitive(border_style_string, "slantdashdot"))
|
||||
{
|
||||
return xlnt::border_style::slantdashdot;
|
||||
}
|
||||
else if (border_style_string == "thick")
|
||||
else if (equals_case_insensitive(border_style_string, "thick"))
|
||||
{
|
||||
return xlnt::border_style::thick;
|
||||
}
|
||||
else if (border_style_string == "thin")
|
||||
else if (equals_case_insensitive(border_style_string, "thin"))
|
||||
{
|
||||
return xlnt::border_style::thin;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("unknown border style");
|
||||
std::string message = "unknown border style: ";
|
||||
message.append(border_style_string);
|
||||
throw std::runtime_error(border_style_string);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -696,6 +716,9 @@ xml_document style_serializer::write_stylesheet() const
|
|||
case color::type::indexed:
|
||||
fg_color_node.add_attribute("indexed", std::to_string(fill_.get_foreground_color()->get_index()));
|
||||
break;
|
||||
case color::type::rgb:
|
||||
fg_color_node.add_attribute("rgb", fill_.get_foreground_color()->get_rgb_string());
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("bad type");
|
||||
}
|
||||
|
@ -716,6 +739,9 @@ xml_document style_serializer::write_stylesheet() const
|
|||
case color::type::indexed:
|
||||
bg_color_node.add_attribute("indexed", std::to_string(fill_.get_background_color()->get_index()));
|
||||
break;
|
||||
case color::type::rgb:
|
||||
bg_color_node.add_attribute("rgb", fill_.get_background_color()->get_rgb_string());
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("bad type");
|
||||
}
|
||||
|
@ -846,6 +872,10 @@ xml_document style_serializer::write_stylesheet() const
|
|||
{
|
||||
color_node.add_attribute("theme", std::to_string(current_side->get_color()->get_theme()));
|
||||
}
|
||||
else if (current_side->get_color()->get_type() == color::type::rgb)
|
||||
{
|
||||
color_node.add_attribute("rgb", current_side->get_color()->get_rgb_string());
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("invalid color type");
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
// @author: see AUTHORS file
|
||||
#include <algorithm>
|
||||
|
||||
#include <xlnt/packaging/app_properties.hpp>
|
||||
#include <xlnt/packaging/document_properties.hpp>
|
||||
#include <xlnt/packaging/manifest.hpp>
|
||||
#include <xlnt/packaging/relationship.hpp>
|
||||
|
@ -110,6 +111,52 @@ void workbook_serializer::read_properties_core(const xml_document &xml)
|
|||
}
|
||||
}
|
||||
|
||||
void workbook_serializer::read_properties_app(const xml_document &xml)
|
||||
{
|
||||
auto &props = workbook_.get_app_properties();
|
||||
auto root_node = xml.get_child("Properties");
|
||||
|
||||
if(root_node.has_child("Application"))
|
||||
{
|
||||
props.application = root_node.get_child("Application").get_text();
|
||||
}
|
||||
|
||||
if(root_node.has_child("DocSecurity"))
|
||||
{
|
||||
props.doc_security = std::stoi(root_node.get_child("DocSecurity").get_text());
|
||||
}
|
||||
|
||||
if(root_node.has_child("ScaleCrop"))
|
||||
{
|
||||
props.scale_crop = root_node.get_child("ScaleCrop").get_text() == "true";
|
||||
}
|
||||
|
||||
if(root_node.has_child("Company"))
|
||||
{
|
||||
props.company = root_node.get_child("Company").get_text();
|
||||
}
|
||||
|
||||
if(root_node.has_child("ScaleCrop"))
|
||||
{
|
||||
props.links_up_to_date = root_node.get_child("ScaleCrop").get_text() == "true";
|
||||
}
|
||||
|
||||
if(root_node.has_child("SharedDoc"))
|
||||
{
|
||||
props.shared_doc = root_node.get_child("SharedDoc").get_text() == "true";
|
||||
}
|
||||
|
||||
if(root_node.has_child("HyperlinksChanged"))
|
||||
{
|
||||
props.hyperlinks_changed = root_node.get_child("HyperlinksChanged").get_text() == "true";
|
||||
}
|
||||
|
||||
if(root_node.has_child("AppVersion"))
|
||||
{
|
||||
props.app_version = root_node.get_child("AppVersion").get_text();
|
||||
}
|
||||
}
|
||||
|
||||
xml_document workbook_serializer::write_properties_core() const
|
||||
{
|
||||
auto &props = workbook_.get_properties();
|
||||
|
@ -147,16 +194,27 @@ xml_document workbook_serializer::write_properties_app() const
|
|||
|
||||
xml.add_namespace("", "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties");
|
||||
xml.add_namespace("vt", "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes");
|
||||
|
||||
auto &properties = workbook_.get_app_properties();
|
||||
|
||||
root_node.add_child("Application").set_text("Microsoft Excel");
|
||||
root_node.add_child("DocSecurity").set_text("0");
|
||||
root_node.add_child("ScaleCrop").set_text("false");
|
||||
root_node.add_child("Company");
|
||||
root_node.add_child("LinksUpToDate").set_text("false");
|
||||
root_node.add_child("SharedDoc").set_text("false");
|
||||
root_node.add_child("HyperlinksChanged").set_text("false");
|
||||
root_node.add_child("AppVersion").set_text("12.0000");
|
||||
root_node.add_child("Application").set_text(properties.application);
|
||||
root_node.add_child("DocSecurity").set_text(std::to_string(properties.doc_security));
|
||||
root_node.add_child("ScaleCrop").set_text(properties.scale_crop ? "true" : "false");
|
||||
|
||||
auto company_node = root_node.add_child("Company");
|
||||
|
||||
if (!properties.company.empty())
|
||||
{
|
||||
company_node.set_text(properties.company);
|
||||
}
|
||||
|
||||
root_node.add_child("LinksUpToDate").set_text(properties.links_up_to_date ? "true" : "false");
|
||||
root_node.add_child("SharedDoc").set_text(properties.shared_doc ? "true" : "false");
|
||||
root_node.add_child("HyperlinksChanged").set_text(properties.hyperlinks_changed ? "true" : "false");
|
||||
root_node.add_child("AppVersion").set_text(properties.app_version);
|
||||
|
||||
// TODO what is this stuff?
|
||||
|
||||
auto heading_pairs_node = root_node.add_child("HeadingPairs");
|
||||
auto heading_pairs_vector_node = heading_pairs_node.add_child("vt:vector");
|
||||
heading_pairs_vector_node.add_attribute("baseType", "variant");
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <sstream>
|
||||
|
||||
#include <xlnt/drawing/drawing.hpp>
|
||||
#include <xlnt/packaging/app_properties.hpp>
|
||||
#include <xlnt/packaging/document_properties.hpp>
|
||||
#include <xlnt/packaging/manifest.hpp>
|
||||
#include <xlnt/packaging/relationship.hpp>
|
||||
|
@ -499,6 +500,17 @@ const document_properties &workbook::get_properties() const
|
|||
return d_->properties_;
|
||||
}
|
||||
|
||||
app_properties &workbook::get_app_properties()
|
||||
{
|
||||
return d_->app_properties_;
|
||||
}
|
||||
|
||||
const app_properties &workbook::get_app_properties() const
|
||||
{
|
||||
return d_->app_properties_;
|
||||
}
|
||||
|
||||
|
||||
void swap(workbook &left, workbook &right)
|
||||
{
|
||||
using std::swap;
|
||||
|
|
Loading…
Reference in New Issue
Block a user