diff --git a/include/xlnt/styles/number_format.hpp b/include/xlnt/styles/number_format.hpp index 72433050..50b94700 100644 --- a/include/xlnt/styles/number_format.hpp +++ b/include/xlnt/styles/number_format.hpp @@ -172,7 +172,12 @@ public: /// /// /// - static number_format from_builtin_id(std::size_t builtin_id); + static bool is_builtin_format(std::size_t builtin_id); + + /// + /// + /// + static const number_format &from_builtin_id(std::size_t builtin_id); /// /// diff --git a/include/xlnt/workbook/workbook.hpp b/include/xlnt/workbook/workbook.hpp index fde608c5..c4d731be 100644 --- a/include/xlnt/workbook/workbook.hpp +++ b/include/xlnt/workbook/workbook.hpp @@ -113,22 +113,7 @@ public: /// /// /// - static workbook minimal(); - - /// - /// - /// - static workbook empty_excel(); - - /// - /// - /// - static workbook empty_libre_office(); - - /// - /// - /// - static workbook empty_numbers(); + static workbook empty(); // constructors diff --git a/source/detail/stylesheet.hpp b/source/detail/stylesheet.hpp index cfbf565a..4e757628 100644 --- a/source/detail/stylesheet.hpp +++ b/source/detail/stylesheet.hpp @@ -110,8 +110,13 @@ struct stylesheet } template - 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::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); diff --git a/source/detail/xlsx_consumer.cpp b/source/detail/xlsx_consumer.cpp index acce5f4b..6ff0d2b2 100644 --- a/source/detail/xlsx_consumer.cpp +++ b/source/detail/xlsx_consumer.cpp @@ -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")); diff --git a/source/detail/xlsx_producer.cpp b/source/detail/xlsx_producer.cpp index 0f89aa66..560d3da1 100644 --- a/source/detail/xlsx_producer.cpp +++ b/source/detail/xlsx_producer.cpp @@ -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 ¤t_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 ¤t_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 ¤t_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 ¤t_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 &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()); diff --git a/source/detail/zip.cpp b/source/detail/zip.cpp index 316e5a4c..643159ea 100644 --- a/source/detail/zip.cpp +++ b/source/detail/zip.cpp @@ -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; diff --git a/source/styles/format.cpp b/source/styles/format.cpp index 52e57d37..857eee4a 100644 --- a/source/styles/format.cpp +++ b/source/styles/format.cpp @@ -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) diff --git a/source/styles/number_format.cpp b/source/styles/number_format.cpp index be114430..58d7ee79 100644 --- a/source/styles/number_format.cpp +++ b/source/styles/number_format.cpp @@ -34,23 +34,60 @@ namespace { -const std::unordered_map &builtin_formats() +const std::unordered_map &builtin_formats() { - static const std::unordered_map *formats = - new std::unordered_map( - {{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 *formats = nullptr; + + if (formats == nullptr) + { + const std::unordered_map 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(); + 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; diff --git a/source/workbook/tests/test_consume_xlsx.hpp b/source/workbook/tests/test_consume_xlsx.hpp index ff0d776e..af9c9d91 100644 --- a/source/workbook/tests/test_consume_xlsx.hpp +++ b/source/workbook/tests/test_consume_xlsx.hpp @@ -7,53 +7,37 @@ #include #include -// 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(), "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(), "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(), "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(), "header"); diff --git a/source/workbook/tests/test_produce_xlsx.hpp b/source/workbook/tests/test_produce_xlsx.hpp index 8f719ae7..e42b1f29 100644 --- a/source/workbook/tests/test_produce_xlsx.hpp +++ b/source/workbook/tests/test_produce_xlsx.hpp @@ -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"))); } }; diff --git a/source/workbook/tests/test_round_trip.hpp b/source/workbook/tests/test_round_trip.hpp index 5e9e7c70..81de8fc5 100644 --- a/source/workbook/tests/test_round_trip.hpp +++ b/source/workbook/tests/test_round_trip.hpp @@ -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"); diff --git a/source/workbook/workbook.cpp b/source/workbook/workbook.cpp index 832116af..6f44632d 100644 --- a/source/workbook/workbook.cpp +++ b/source/workbook/workbook.cpp @@ -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; } diff --git a/tests/data/13_all_styles.xlsx b/tests/data/10_all_styles.xlsx similarity index 100% rename from tests/data/13_all_styles.xlsx rename to tests/data/10_all_styles.xlsx diff --git a/tests/data/10_default-libre-office.xlsx b/tests/data/10_default-libre-office.xlsx deleted file mode 100644 index 8da9b54a..00000000 Binary files a/tests/data/10_default-libre-office.xlsx and /dev/null differ diff --git a/tests/data/11_default-numbers.xlsx b/tests/data/11_default-numbers.xlsx deleted file mode 100644 index dc710146..00000000 Binary files a/tests/data/11_default-numbers.xlsx and /dev/null differ diff --git a/tests/data/14_encrypted_excel_2016.xlsx b/tests/data/11_encrypted_excel_2016.xlsx similarity index 100% rename from tests/data/14_encrypted_excel_2016.xlsx rename to tests/data/11_encrypted_excel_2016.xlsx diff --git a/tests/data/15_encrypted_libre_office.xlsx b/tests/data/12_encrypted_libre_office.xlsx similarity index 100% rename from tests/data/15_encrypted_libre_office.xlsx rename to tests/data/12_encrypted_libre_office.xlsx diff --git a/tests/data/16_encrypted_excel_2007.xlsx b/tests/data/13_encrypted_excel_2007.xlsx similarity index 100% rename from tests/data/16_encrypted_excel_2007.xlsx rename to tests/data/13_encrypted_excel_2007.xlsx diff --git a/tests/data/17_encrypted_numbers.xlsx b/tests/data/14_encrypted_numbers.xlsx similarity index 100% rename from tests/data/17_encrypted_numbers.xlsx rename to tests/data/14_encrypted_numbers.xlsx diff --git a/tests/data/18_basic_comments.xlsx b/tests/data/15_basic_comments.xlsx similarity index 100% rename from tests/data/18_basic_comments.xlsx rename to tests/data/15_basic_comments.xlsx diff --git a/tests/data/19_unicode_Λ.xlsx b/tests/data/16_unicode_Λ.xlsx similarity index 100% rename from tests/data/19_unicode_Λ.xlsx rename to tests/data/16_unicode_Λ.xlsx diff --git a/tests/data/20_with_hyperlink.xlsx b/tests/data/17_with_hyperlink.xlsx similarity index 100% rename from tests/data/20_with_hyperlink.xlsx rename to tests/data/17_with_hyperlink.xlsx diff --git a/tests/data/21_headers_and_footers.xlsx b/tests/data/18_headers_and_footers.xlsx similarity index 100% rename from tests/data/21_headers_and_footers.xlsx rename to tests/data/18_headers_and_footers.xlsx diff --git a/tests/data/22_row_and_col_properties.xlsx b/tests/data/19_row_and_col_properties.xlsx similarity index 100% rename from tests/data/22_row_and_col_properties.xlsx rename to tests/data/19_row_and_col_properties.xlsx diff --git a/tests/data/23_page_breaks.xlsx b/tests/data/20_page_breaks.xlsx similarity index 100% rename from tests/data/23_page_breaks.xlsx rename to tests/data/20_page_breaks.xlsx