stop trying to produce non-excel style xlsx files

pull/108/head
Thomas Fussell 2016-12-29 18:36:29 -05:00
parent c637f412b6
commit 66b5187e73
25 changed files with 178 additions and 402 deletions

View File

@ -172,7 +172,12 @@ public:
/// <summary>
///
/// </summary>
static number_format from_builtin_id(std::size_t builtin_id);
static bool is_builtin_format(std::size_t builtin_id);
/// <summary>
///
/// </summary>
static const number_format &from_builtin_id(std::size_t builtin_id);
/// <summary>
///

View File

@ -113,22 +113,7 @@ public:
/// <summary>
///
/// </summary>
static workbook minimal();
/// <summary>
///
/// </summary>
static workbook empty_excel();
/// <summary>
///
/// </summary>
static workbook empty_libre_office();
/// <summary>
///
/// </summary>
static workbook empty_numbers();
static workbook empty();
// constructors

View File

@ -110,8 +110,13 @@ struct stylesheet
}
template<typename T, typename C>
std::size_t find_or_add(C &container, const T &item)
std::size_t find_or_add(C &container, const T &item, bool *added = nullptr)
{
if (added != nullptr)
{
*added = false;
}
std::size_t i = 0;
for (auto iter = container.begin(); iter != container.end(); ++iter)
@ -123,7 +128,12 @@ struct stylesheet
++i;
}
if (added != nullptr)
{
*added = true;
}
container.emplace(container.end(), item);
return container.size() - 1;
@ -322,18 +332,24 @@ struct stylesheet
format_impl *find_or_create(format_impl &pattern)
{
auto iter = format_impls.begin();
auto id = find_or_add(format_impls, pattern);
bool added = false;
auto id = find_or_add(format_impls, pattern, &added);
std::advance(iter, static_cast<std::list<format_impl>::difference_type>(id));
auto &result = *iter;
if (added)
{
result.references = 0;
}
result.parent = this;
result.id = id;
result.references++;
if (id != pattern.id)
{
pattern.references -= pattern.references > 0 ? 1 : 0;
++result.references;
garbage_collect();
}
@ -387,7 +403,11 @@ struct stylesheet
format_impl *find_or_create_with(format_impl *pattern, const number_format &new_number_format, bool applied)
{
format_impl new_format = *pattern;
new_format.number_format_id = find_or_add(number_formats, new_number_format);
if (new_number_format.id() >= 164)
{
find_or_add(number_formats, new_number_format);
}
new_format.number_format_id = new_number_format.id();
new_format.number_format_applied = applied;
return find_or_create(new_format);

View File

@ -1499,8 +1499,9 @@ void xlsx_consumer::read_stylesheet()
{
expect_start_element(xml::qname(xmlns, "xf"), xml::content::complex);
auto &record = *(!in_style_records ? format_records.emplace(format_records.end())
: style_records.emplace(style_records.end()));
auto &record = *(!in_style_records
? format_records.emplace(format_records.end())
: style_records.emplace(style_records.end()));
auto apply_alignment_present = parser().attribute_present("applyAlignment");
auto alignment_applied = apply_alignment_present && is_true(parser().attribute("applyAlignment"));

View File

@ -798,6 +798,12 @@ void xlsx_producer::write_shared_string_table(const relationship & /*rel*/)
{
serializer().start_element(xmlns, "rPr");
if (run.second.get().bold())
{
serializer().start_element(xmlns, "b");
serializer().end_element(xmlns, "b");
}
if (run.second.get().has_size())
{
serializer().start_element(xmlns, "sz");
@ -833,12 +839,6 @@ void xlsx_producer::write_shared_string_table(const relationship & /*rel*/)
serializer().end_element(xmlns, "scheme");
}
if (run.second.get().bold())
{
serializer().start_element(xmlns, "b");
serializer().end_element(xmlns, "b");
}
serializer().end_element(xmlns, "rPr");
}
@ -1083,11 +1083,11 @@ void xlsx_producer::write_styles(const relationship & /*rel*/)
{
auto up = *current_border.diagonal() == diagonal_direction::both
|| *current_border.diagonal() == diagonal_direction::up;
serializer().attribute("diagonalUp", up ? "true" : "false");
serializer().attribute("diagonalUp", write_bool(up));
auto down = *current_border.diagonal() == diagonal_direction::both
|| *current_border.diagonal() == diagonal_direction::down;
serializer().attribute("diagonalDown", down ? "true" : "false");
serializer().attribute("diagonalDown", write_bool(down));
}
for (const auto &side : xlnt::border::all_sides())
@ -1166,7 +1166,7 @@ void xlsx_producer::write_styles(const relationship & /*rel*/)
serializer().attribute("applyProtection", write_bool(true));
}
if (current_style_impl.alignment_applied)
if (current_style_impl.alignment_id.is_set())
{
const auto &current_alignment = stylesheet.alignments[current_style_impl.alignment_id.get()];
@ -1205,7 +1205,7 @@ void xlsx_producer::write_styles(const relationship & /*rel*/)
serializer().end_element(xmlns, "alignment");
}
if (current_style_impl.protection_applied)
if (current_style_impl.protection_id.is_set())
{
const auto &current_protection = stylesheet.protections[current_style_impl.protection_id.get()];
@ -1278,7 +1278,7 @@ void xlsx_producer::write_styles(const relationship & /*rel*/)
serializer().attribute("xfId", stylesheet.style_index(current_format_impl.style.get()));
}
if (current_format_impl.alignment_applied)
if (current_format_impl.alignment_id.is_set())
{
const auto &current_alignment = stylesheet.alignments[current_format_impl.alignment_id.get()];
@ -1286,38 +1286,38 @@ void xlsx_producer::write_styles(const relationship & /*rel*/)
if (current_alignment.vertical())
{
serializer().attribute("vertical", *current_alignment.vertical());
serializer().attribute("vertical", current_alignment.vertical().get());
}
if (current_alignment.horizontal())
{
serializer().attribute("horizontal", *current_alignment.horizontal());
serializer().attribute("horizontal", current_alignment.horizontal().get());
}
if (current_alignment.rotation())
{
serializer().attribute("textRotation", *current_alignment.rotation());
serializer().attribute("textRotation", current_alignment.rotation().get());
}
if (current_alignment.wrap())
{
serializer().attribute("wrapText", write_bool(*current_alignment.wrap()));
serializer().attribute("wrapText", write_bool(current_alignment.wrap().get()));
}
if (current_alignment.indent())
{
serializer().attribute("indent", *current_alignment.indent());
serializer().attribute("indent", current_alignment.indent().get());
}
if (current_alignment.shrink())
{
serializer().attribute("shrinkToFit", write_bool(*current_alignment.shrink()));
serializer().attribute("shrinkToFit", write_bool(current_alignment.shrink().get()));
}
serializer().end_element(xmlns, "alignment");
}
if (current_format_impl.protection_applied)
if (current_format_impl.protection_id.is_set())
{
const auto &current_protection = stylesheet.protections[current_format_impl.protection_id.get()];
@ -2685,6 +2685,12 @@ void xlsx_producer::write_comments(const relationship & /*rel*/, worksheet ws, c
{
serializer().start_element(xmlns, "rPr");
if (run.second.get().bold())
{
serializer().start_element(xmlns, "b");
serializer().end_element(xmlns, "b");
}
if (run.second.get().has_size())
{
serializer().start_element(xmlns, "sz");
@ -2720,12 +2726,6 @@ void xlsx_producer::write_comments(const relationship & /*rel*/, worksheet ws, c
serializer().end_element(xmlns, "scheme");
}
if (run.second.get().bold())
{
serializer().start_element(xmlns, "b");
serializer().end_element(xmlns, "b");
}
serializer().end_element(xmlns, "rPr");
}
@ -2929,8 +2929,12 @@ void xlsx_producer::write_relationships(const std::vector<xlnt::relationship> &r
serializer().start_element(xmlns, "Relationships");
serializer().namespace_decl(xmlns, "");
for (const auto &relationship : relationships)
for (std::size_t i = 1; i <= relationships.size(); ++i)
{
auto rel_iter = std::find_if(relationships.begin(), relationships.end(),
[&i](const relationship &r) { return r.id() == "rId" + std::to_string(i); });
auto relationship = *rel_iter;
serializer().start_element(xmlns, "Relationship");
serializer().attribute("Id", relationship.id());

View File

@ -216,8 +216,7 @@ public:
else
{
compressed_data = false;
std::cerr << "ZIP: got unrecognized compressed data (Supported deflate/uncompressed)" << std::endl;
valid = false;
throw xlnt::exception("unsupported compression type, should be DEFLATE or uncompressed");
}
// initialize the inflate
@ -230,8 +229,7 @@ public:
if (result != Z_OK)
{
std::cerr << "gzip: inflateInit2 did not return Z_OK" << std::endl;
valid = false;
throw xlnt::exception("couldn't inflate ZIP, possibly corrupted");
}
}
@ -272,15 +270,10 @@ public:
switch (ret)
{
case Z_STREAM_ERROR:
std::cerr << "libz error Z_STREAM_ERROR" << std::endl;
valid = false;
return -1;
case Z_NEED_DICT:
case Z_DATA_ERROR:
case Z_MEM_ERROR:
std::cerr << "gzip error " << strm.msg << std::endl;
valid = false;
return -1;
throw xlnt::exception("couldn't inflate ZIP, possibly corrupted");
}
if (ret == Z_STREAM_END) break;

View File

@ -142,7 +142,13 @@ xlnt::number_format &format::number_format()
const xlnt::number_format &format::number_format() const
{
return d_->parent->number_formats.at(d_->number_format_id.get());
if (number_format::is_builtin_format(d_->number_format_id.get()))
{
return number_format::from_builtin_id(d_->number_format_id.get());
}
return *std::find_if(d_->parent->number_formats.begin(), d_->parent->number_formats.end(),
[&](const xlnt::number_format nf) { return nf.id() == d_->number_format_id.get(); });
}
format format::number_format(const xlnt::number_format &new_number_format, bool applied)

View File

@ -34,23 +34,60 @@
namespace {
const std::unordered_map<std::size_t, std::string> &builtin_formats()
const std::unordered_map<std::size_t, xlnt::number_format> &builtin_formats()
{
static const std::unordered_map<std::size_t, std::string> *formats =
new std::unordered_map<std::size_t, std::string>(
{{0, "General"}, {1, "0"}, {2, "0.00"}, {3, "#,##0"}, {4, "#,##0.00"}, {9, "0%"}, {10, "0.00%"},
{11, "0.00E+00"}, {12, "# ?/?"}, {13, "# \?\?/??"}, // escape trigraph
{14, "mm-dd-yy"}, {15, "d-mmm-yy"}, {16, "d-mmm"}, {17, "mmm-yy"}, {18, "h:mm AM/PM"},
{19, "h:mm:ss AM/PM"}, {20, "h:mm"}, {21, "h:mm:ss"}, {22, "m/d/yy h:mm"}, {37, "#,##0 ;(#,##0)"},
{38, "#,##0 ;[Red](#,##0)"}, {39, "#,##0.00;(#,##0.00)"}, {40, "#,##0.00;[Red](#,##0.00)"},
static std::unordered_map<std::size_t, xlnt::number_format> *formats = nullptr;
if (formats == nullptr)
{
const std::unordered_map<std::size_t, std::string> format_strings
{
{0, "General"},
{1, "0"},
{2, "0.00"},
{3, "#,##0"},
{4, "#,##0.00"},
{9, "0%"},
{10, "0.00%"},
{11, "0.00E+00"},
{12, "# ?/?"},
{13, "# \?\?/??"}, // escape trigraph
{14, "mm-dd-yy"},
{15, "d-mmm-yy"},
{16, "d-mmm"},
{17, "mmm-yy"},
{18, "h:mm AM/PM"},
{19, "h:mm:ss AM/PM"},
{20, "h:mm"},
{21, "h:mm:ss"},
{22, "m/d/yy h:mm"},
{37, "#,##0 ;(#,##0)"},
{38, "#,##0 ;[Red](#,##0)"},
{39, "#,##0.00;(#,##0.00)"},
{40, "#,##0.00;[Red](#,##0.00)"},
// 41-44 aren't in the ECMA 376 v4 standard, but Libre Office uses them
{41, "_(* #,##0_);_(* \\(#,##0\\);_(* \"-\"_);_(@_)"},
{42, "_(\"$\"* #,##0_);_(\"$\"* \\(#,##0\\);_(\"$\"* \"-\"_);_(@_)"},
{43, "_(* #,##0.00_);_(* \\(#,##0.00\\);_(* \"-\"??_);_(@_)"},
{44, "_(\"$\"* #,##0.00_)_(\"$\"* \\(#,##0.00\\)_(\"$\"* \"-\"??_)_(@_)"},
// 41-44 aren't in the ECMA 376 v4 standard, but Libre Office uses them
{41, "_(* #,##0_);_(* \\(#,##0\\);_(* \"-\"_);_(@_)"},
{42, "_(\"$\"* #,##0_);_(\"$\"* \\(#,##0\\);_(\"$\"* \"-\"_);_(@_)"},
{43, "_(* #,##0.00_);_(* \\(#,##0.00\\);_(* \"-\"??_);_(@_)"},
{44, "_(\"$\"* #,##0.00_)_(\"$\"* \\(#,##0.00\\)_(\"$\"* \"-\"??_)_(@_)"},
{45, "mm:ss"}, {46, "[h]:mm:ss"}, {47, "mmss.0"}, {48, "##0.0E+0"}, {49, "@"}});
{45, "mm:ss"},
{46, "[h]:mm:ss"},
{47, "mmss.0"},
{48, "##0.0E+0"},
{49, "@"}
};
formats = new std::unordered_map<std::size_t, xlnt::number_format>();
auto &formats_ref = *formats;
for (auto format_string_pair : format_strings)
{
formats_ref[format_string_pair.first] =
xlnt::number_format(format_string_pair.second, format_string_pair.first);
}
}
return *formats;
}
@ -61,44 +98,37 @@ namespace xlnt {
const number_format number_format::general()
{
static const number_format *format = new number_format(builtin_formats().at(0), 0);
return *format;
return builtin_formats().at(0);
}
const number_format number_format::text()
{
static const number_format *format = new number_format(builtin_formats().at(49), 49);
return *format;
return builtin_formats().at(49);
}
const number_format number_format::number()
{
static const number_format *format = new number_format(builtin_formats().at(1), 1);
return *format;
return builtin_formats().at(1);
}
const number_format number_format::number_00()
{
static const number_format *format = new number_format(builtin_formats().at(2), 2);
return *format;
return builtin_formats().at(2);
}
const number_format number_format::number_comma_separated1()
{
static const number_format *format = new number_format(builtin_formats().at(4), 4);
return *format;
return builtin_formats().at(4);
}
const number_format number_format::percentage()
{
static const number_format *format = new number_format(builtin_formats().at(9), 9);
return *format;
return builtin_formats().at(9);
}
const number_format number_format::percentage_00()
{
static const number_format *format = new number_format(builtin_formats().at(10), 10);
return *format;
return builtin_formats().at(10);
}
const number_format number_format::date_yyyymmdd2()
@ -145,32 +175,27 @@ const number_format number_format::date_myminus()
const number_format number_format::date_xlsx14()
{
static const number_format *format = new number_format(builtin_formats().at(14), 14);
return *format;
return builtin_formats().at(14);
}
const number_format number_format::date_xlsx15()
{
static const number_format *format = new number_format(builtin_formats().at(15), 15);
return *format;
return builtin_formats().at(15);
}
const number_format number_format::date_xlsx16()
{
static const number_format *format = new number_format(builtin_formats().at(16), 16);
return *format;
return builtin_formats().at(16);
}
const number_format number_format::date_xlsx17()
{
static const number_format *format = new number_format(builtin_formats().at(17), 17);
return *format;
return builtin_formats().at(17);
}
const number_format number_format::date_xlsx22()
{
static const number_format *format = new number_format(builtin_formats().at(22), 22);
return *format;
return builtin_formats().at(22);
}
const number_format number_format::date_datetime()
@ -181,42 +206,35 @@ const number_format number_format::date_datetime()
const number_format number_format::date_time1()
{
static const number_format *format = new number_format(builtin_formats().at(18), 18);
return *format;
return builtin_formats().at(18);
}
const number_format number_format::date_time2()
{
static const number_format *format = new number_format(builtin_formats().at(19), 19);
return *format;
return builtin_formats().at(19);
}
const number_format number_format::date_time3()
{
static const number_format *format = new number_format(builtin_formats().at(20), 20);
return *format;
return builtin_formats().at(20);
}
const number_format number_format::date_time4()
{
static const number_format *format = new number_format(builtin_formats().at(21), 21);
return *format;
return builtin_formats().at(21);
}
const number_format number_format::date_time5()
{
static const number_format *format = new number_format(builtin_formats().at(45), 45);
return *format;
return builtin_formats().at(45);
}
const number_format number_format::date_time6()
{
static const number_format *format = new number_format(builtin_formats().at(21), 21);
return *format;
return builtin_formats().at(21);
}
number_format::number_format()
: number_format(general())
number_format::number_format() : number_format("General", 0)
{
}
@ -237,15 +255,19 @@ number_format::number_format(const std::string &format_string, std::size_t id)
this->format_string(format_string, id);
}
number_format number_format::from_builtin_id(std::size_t builtin_id)
bool number_format::is_builtin_format(std::size_t builtin_id)
{
if (builtin_formats().find(builtin_id) == builtin_formats().end())
return builtin_formats().find(builtin_id) != builtin_formats().end();
}
const number_format &number_format::from_builtin_id(std::size_t builtin_id)
{
if (!is_builtin_format(builtin_id))
{
throw invalid_parameter(); //("unknown id: " + std::to_string(builtin_id));
throw invalid_parameter();
}
auto format_string = builtin_formats().at(builtin_id);
return number_format(format_string, builtin_id);
return builtin_formats().at(builtin_id);
}
std::string number_format::format_string() const
@ -261,7 +283,7 @@ void number_format::format_string(const std::string &format_string)
for (const auto &pair : builtin_formats())
{
if (pair.second == format_string)
if (pair.second.format_string() == format_string)
{
id_ = pair.first;
id_set_ = true;

View File

@ -7,53 +7,37 @@
#include <helpers/path_helper.hpp>
#include <xlnt/workbook/workbook.hpp>
// Cryptographic key generation can take a few seconds, particularly in unoptomized builds.
// Set this to false to skip those tests that use cryptography.
#define TEST_CRYPTO true
#ifndef TEST_CRYPTO
#define TEST_CRYPTO false
#endif
class test_consume_xlsx : public CxxTest::TestSuite
{
public:
void test_decrypt_agile()
{
xlnt::workbook wb;
#if TEST_CRYPTO
wb.load(path_helper::get_data_directory("14_encrypted_excel_2016.xlsx"), "secret");
#endif
wb.load(path_helper::get_data_directory("11_encrypted_excel_2016.xlsx"), "secret");
}
void test_decrypt_libre_office()
{
xlnt::workbook wb;
#if TEST_CRYPTO
wb.load(path_helper::get_data_directory("15_encrypted_libre_office.xlsx"), "secret");
#endif
wb.load(path_helper::get_data_directory("12_encrypted_libre_office.xlsx"), "secret");
}
void test_decrypt_standard()
{
xlnt::workbook wb;
#if TEST_CRYPTO
wb.load(path_helper::get_data_directory("16_encrypted_excel_2007.xlsx"), "password");
#endif
wb.load(path_helper::get_data_directory("13_encrypted_excel_2007.xlsx"), "password");
}
void test_decrypt_numbers()
{
xlnt::workbook wb;
#if TEST_CRYPTO
wb.load(path_helper::get_data_directory("17_encrypted_numbers.xlsx"), "secret");
#endif
wb.load(path_helper::get_data_directory("14_encrypted_numbers.xlsx"), "secret");
}
void test_comments()
{
xlnt::workbook wb;
wb.load("data/18_basic_comments.xlsx");
wb.load("data/15_basic_comments.xlsx");
auto sheet1 = wb[0];
TS_ASSERT_EQUALS(sheet1.cell("A1").value<std::string>(), "Sheet1!A1");
@ -70,12 +54,12 @@ public:
{
#ifdef _MSC_VER
xlnt::workbook wb;
wb.load(L"data\\19_unicode_Λ.xlsx");
wb.load(L"data\\16_unicode_Λ.xlsx");
TS_ASSERT_EQUALS(wb.active_sheet().cell("A1").value<std::string>(), "unicode!");
#endif
#ifndef __MINGW32__
xlnt::workbook wb2;
wb2.load(u8"data/19_unicode_Λ.xlsx");
wb2.load(u8"data/16_unicode_Λ.xlsx");
TS_ASSERT_EQUALS(wb2.active_sheet().cell("A1").value<std::string>(), "unicode!");
#endif
}
@ -83,7 +67,7 @@ public:
void test_read_hyperlink()
{
xlnt::workbook wb;
wb.load("data/20_with_hyperlink.xlsx");
wb.load("data/17_with_hyperlink.xlsx");
TS_ASSERT(wb.active_sheet().cell("A1").has_hyperlink());
TS_ASSERT_EQUALS(wb.active_sheet().cell("A1").hyperlink(),
"https://fr.wikipedia.org/wiki/Ille-et-Vilaine");
@ -92,7 +76,7 @@ public:
void test_read_headers_and_footers()
{
xlnt::workbook wb;
wb.load("data/21_headers_and_footers.xlsx");
wb.load("data/18_headers_and_footers.xlsx");
auto ws = wb.active_sheet();
TS_ASSERT_EQUALS(ws.cell("A1").value<std::string>(), "header");

View File

@ -29,27 +29,15 @@ public:
return xml_helper::xlsx_archives_match(wb_data, file_data);
}
void test_produce_minimal()
void test_produce_empty()
{
xlnt::workbook wb = xlnt::workbook::minimal();
TS_ASSERT(workbook_matches_file(wb, path_helper::get_data_directory("8_minimal.xlsx")));
}
void test_produce_default_excel()
{
xlnt::workbook wb = xlnt::workbook::empty_excel();
xlnt::workbook wb = xlnt::workbook::empty();
TS_ASSERT(workbook_matches_file(wb, path_helper::get_data_directory("9_default-excel.xlsx")));
}
void test_produce_default_libre_office()
{
xlnt::workbook wb = xlnt::workbook::empty_libre_office();
TS_ASSERT(workbook_matches_file(wb, path_helper::get_data_directory("10_default-libre-office.xlsx")));
}
void test_produce_simple_excel()
{
xlnt::workbook wb = xlnt::workbook::empty_excel();
xlnt::workbook wb;
auto ws = wb.active_sheet();
auto bold_font = xlnt::font().bold(true);
@ -164,6 +152,6 @@ public:
sheet2.cell("A2").value("Sheet2!A2");
sheet2.cell("A2").comment("Sheet2 comment2", comment_font, "Microsoft Office User");
TS_ASSERT(workbook_matches_file(wb, xlnt::path("data/18_basic_comments.xlsx")));
TS_ASSERT(workbook_matches_file(wb, xlnt::path("data/15_basic_comments.xlsx")));
}
};

View File

@ -57,54 +57,18 @@ public:
return xml_helper::xlsx_archives_match(original_data, buffer);
}
void test_round_trip_minimal_wrw()
void test_round_trip_empty_wrw()
{
xlnt::workbook wb = xlnt::workbook::minimal();
xlnt::workbook wb = xlnt::workbook::empty();
TS_ASSERT(round_trip_matches_wrw(wb));
}
void test_round_trip_empty_excel_wrw()
{
xlnt::workbook wb = xlnt::workbook::empty_excel();
TS_ASSERT(round_trip_matches_wrw(wb));
}
void test_round_trip_empty_libre_office_wrw()
{
xlnt::workbook wb = xlnt::workbook::empty_libre_office();
TS_ASSERT(round_trip_matches_wrw(wb));
}
void test_round_trip_empty_numbers_wrw()
{
xlnt::workbook wb = xlnt::workbook::empty_numbers();
TS_ASSERT(round_trip_matches_wrw(wb));
}
void test_round_trip_minimal_rw()
{
auto path = path_helper::get_data_directory("8_minimal.xlsx");
TS_ASSERT(round_trip_matches_rw(path));
}
void test_round_trip_empty_excel_rw()
{
auto path = path_helper::get_data_directory("9_default-excel.xlsx");
TS_ASSERT(round_trip_matches_rw(path));
}
void test_round_trip_empty_libre_rw()
{
auto path = path_helper::get_data_directory("10_default-libre-office.xlsx");
TS_ASSERT(round_trip_matches_rw(path));
}
void test_round_trip_empty_numbers_rw()
{
auto path = path_helper::get_data_directory("11_default-numbers.xlsx");
TS_ASSERT(round_trip_matches_rw(path));
}
void test_round_trip_all_styles_rw()
{
auto path = path_helper::get_data_directory("13_all_styles.xlsx");

View File

@ -165,31 +165,7 @@ std::string workbook::extended_property(const std::string &property_name) const
return d_->extended_properties_.at(property_name);
}
workbook workbook::minimal()
{
auto impl = new detail::workbook_impl();
workbook wb(impl);
wb.d_->manifest_.register_default_type("rels", "application/vnd.openxmlformats-package.relationships+xml");
wb.d_->manifest_.register_relationship(uri("/"),
relationship_type::office_document, uri("workbook.xml"), target_mode::internal);
auto title = std::string("1");
wb.d_->worksheets_.push_back(detail::worksheet_impl(&wb, 1, title));
auto ws_rel = wb.d_->manifest_.register_relationship(uri("workbook.xml"),
relationship_type::worksheet, uri("sheet1.xml"), target_mode::internal);
wb.d_->sheet_title_rel_id_map_[title] = ws_rel;
wb.d_->manifest_.register_override_type(path("/workbook.xml"),
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml");
wb.d_->manifest_.register_override_type(path("/sheet1.xml"),
"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml");
return wb;
}
workbook workbook::empty_excel()
workbook workbook::empty()
{
auto impl = new detail::workbook_impl();
workbook wb(impl);
@ -257,13 +233,14 @@ workbook workbook::empty_excel()
wb.d_->stylesheet_ = detail::stylesheet();
auto &stylesheet = wb.d_->stylesheet_.get();
stylesheet.parent = &wb;
auto default_border = border()
.side(border_side::bottom, border::border_property())
.side(border_side::top, border::border_property())
.side(border_side::start, border::border_property())
.side(border_side::end, border::border_property())
.side(border_side::diagonal, border::border_property());
.side(border_side::bottom, border::border_property())
.side(border_side::top, border::border_property())
.side(border_side::start, border::border_property())
.side(border_side::end, border::border_property())
.side(border_side::diagonal, border::border_property());
wb.d_->stylesheet_.get().borders.push_back(default_border);
auto default_fill = fill(pattern_fill().type(pattern_fill_type::none));
@ -296,182 +273,9 @@ workbook workbook::empty_excel()
return wb;
}
workbook workbook::empty_libre_office()
{
auto impl = new detail::workbook_impl();
workbook wb(impl);
wb.d_->manifest_.register_override_type(
path("xl/workbook.xml"), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml");
wb.d_->manifest_.register_relationship(
uri("/"), relationship_type::office_document, uri("xl/workbook.xml"), target_mode::internal);
wb.d_->manifest_.register_override_type(
path("docProps/core.xml"), "application/vnd.openxmlformats-package.core-properties+xml");
wb.d_->manifest_.register_relationship(
uri("/"), relationship_type::core_properties, uri("docProps/core.xml"), target_mode::internal);
wb.d_->manifest_.register_override_type(
path("docProps/app.xml"), "application/vnd.openxmlformats-officedocument.extended-properties+xml");
wb.d_->manifest_.register_relationship(
uri("/"), relationship_type::extended_properties, uri("docProps/app.xml"), target_mode::internal);
wb.d_->manifest_.register_override_type(
path("_rels/.rels"), "application/vnd.openxmlformats-package.relationships+xml");
wb.d_->manifest_.register_override_type(
path("xl/_rels/workbook.xml.rels"), "application/vnd.openxmlformats-package.relationships+xml");
std::string title("Sheet1");
wb.d_->worksheets_.push_back(detail::worksheet_impl(&wb, 1, title));
wb.d_->manifest_.register_override_type(path("xl/worksheets/sheet1.xml"),
"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml");
auto ws_rel = wb.d_->manifest_.register_relationship(uri("xl/workbook.xml"),
relationship_type::worksheet, uri("worksheets/sheet1.xml"), target_mode::internal);
wb.d_->sheet_title_rel_id_map_[title] = ws_rel;
auto ws = wb.sheet_by_index(0);
sheet_view view;
ws.add_view(view);
page_margins margins;
margins.left(0.7875);
margins.right(0.7875);
margins.top(1.05277777777778);
margins.bottom(1.05277777777778);
margins.header(0.7875);
margins.footer(0.7875);
ws.page_margins(margins);
ws.page_setup(page_setup());
ws.header_footer(xlnt::header_footer()
.header(header_footer::location::center,
rich_text(rich_text_run{"&A", font().name("Times New Roman").size(12)}))
.footer(header_footer::location::center,
rich_text(rich_text_run{"Page &B", font().name("Times New Roman").size(12)})));
ws.add_column_properties(1, column_properties());
wb.d_->stylesheet_ = detail::stylesheet();
auto &stylesheet = wb.d_->stylesheet_.get();
auto default_alignment = xlnt::alignment()
.horizontal(horizontal_alignment::general)
.vertical(vertical_alignment::bottom)
.rotation(0)
.wrap(false)
.indent(0)
.shrink(false);
stylesheet.alignments.push_back(default_alignment);
auto default_border = border()
.side(border_side::bottom, border::border_property())
.side(border_side::top, border::border_property())
.side(border_side::start, border::border_property())
.side(border_side::end, border::border_property())
.side(border_side::diagonal, border::border_property())
.diagonal(diagonal_direction::neither);
stylesheet.borders.push_back(default_border);
auto default_fill = xlnt::fill(xlnt::pattern_fill().type(pattern_fill_type::none));
stylesheet.fills.push_back(default_fill);
auto gray125_fill = xlnt::fill(xlnt::pattern_fill().type(pattern_fill_type::gray125));
stylesheet.fills.push_back(gray125_fill);
auto default_font = font().name("Arial").size(10).family(2);
stylesheet.fonts.push_back(default_font);
auto second_font = font().name("Arial").size(10).family(0);
stylesheet.fonts.push_back(second_font);
auto default_number_format = xlnt::number_format();
default_number_format.format_string("General");
default_number_format.id(164);
stylesheet.number_formats.push_back(default_number_format);
auto default_protection = xlnt::protection().locked(true).hidden(false);
stylesheet.protections.push_back(default_protection);
wb.create_style("Normal")
.builtin_id(0)
.custom(false)
.alignment(default_alignment, false)
.border(default_border, true)
.fill(default_fill, true)
.font(default_font, true)
.number_format(default_number_format, false)
.protection(default_protection, false);
wb.create_style("Comma")
.builtin_id(3)
.custom(false)
.alignment(default_alignment, false)
.border(default_border, true)
.fill(default_fill, true)
.font(second_font, true)
.number_format(number_format::from_builtin_id(43), false)
.protection(default_protection, false);
wb.create_style("Comma [0]")
.builtin_id(6)
.custom(false)
.alignment(default_alignment, false)
.border(default_border, true)
.fill(default_fill, true)
.font(second_font, true)
.number_format(number_format::from_builtin_id(41), false)
.protection(default_protection, false);
wb.create_style("Currency")
.builtin_id(4)
.custom(false)
.alignment(default_alignment, false)
.border(default_border, true)
.fill(default_fill, true)
.font(second_font, true)
.number_format(number_format::from_builtin_id(44), false)
.protection(default_protection, false);
wb.create_style("Currency [0]")
.builtin_id(7)
.custom(false)
.alignment(default_alignment, false)
.border(default_border, true)
.fill(default_fill, true)
.font(second_font, true)
.number_format(number_format::from_builtin_id(42), false)
.protection(default_protection, false);
wb.create_style("Percent")
.builtin_id(5)
.custom(false)
.alignment(default_alignment, false)
.border(default_border, true)
.fill(default_fill, false)
.font(second_font, true)
.number_format(number_format::percentage(), false)
.protection(default_protection, false);
wb.create_format()
.number_format(default_number_format, true)
.alignment(default_alignment, true)
.protection(default_protection, true)
.style("Normal");
wb.extended_property("Application",
"LibreOffice/5.1.4.2$Windows_x86 LibreOffice_project/f99d75f39f1c57ebdd7ffc5f42867c12031db97a");
return wb;
}
workbook workbook::empty_numbers()
{
return empty_excel();
}
workbook::workbook()
{
auto wb_template = empty_excel();
auto wb_template = empty();
swap(*this, wb_template);
}
@ -1110,7 +914,7 @@ void swap(workbook &left, workbook &right)
ws.parent(right);
}
if (left.d_->stylesheet_.is_set())
if (right.d_->stylesheet_.is_set())
{
right.d_->stylesheet_->parent = &right;
}

Binary file not shown.