From 008461bf60ad335270d2054fcced74966135e2ef Mon Sep 17 00:00:00 2001 From: Thomas Fussell Date: Thu, 22 Dec 2016 18:57:22 -0500 Subject: [PATCH] finish full header/footer implementation, add support for page breaks, clean up row/column properties interface --- include/xlnt/worksheet/column_properties.hpp | 11 +- include/xlnt/worksheet/row_properties.hpp | 13 +- include/xlnt/worksheet/sheet_view.hpp | 25 + include/xlnt/worksheet/worksheet.hpp | 5 + source/detail/worksheet_impl.hpp | 5 + source/detail/xlsx_consumer.cpp | 592 ++++++++++++++++++- source/detail/xlsx_producer.cpp | 152 ++++- source/workbook/tests/test_consume_xlsx.hpp | 32 + source/workbook/tests/test_round_trip.hpp | 29 +- source/worksheet/header_footer.cpp | 2 +- source/worksheet/worksheet.cpp | 42 +- tests/data/21_headers_and_footers.xlsx | Bin 0 -> 21510 bytes tests/data/22_row_and_col_properties.xlsx | Bin 0 -> 20819 bytes tests/data/23_page_breaks.xlsx | Bin 0 -> 29315 bytes 14 files changed, 848 insertions(+), 60 deletions(-) create mode 100644 tests/data/21_headers_and_footers.xlsx create mode 100644 tests/data/22_row_and_col_properties.xlsx create mode 100644 tests/data/23_page_breaks.xlsx diff --git a/include/xlnt/worksheet/column_properties.hpp b/include/xlnt/worksheet/column_properties.hpp index 3360ad31..aa608464 100644 --- a/include/xlnt/worksheet/column_properties.hpp +++ b/include/xlnt/worksheet/column_properties.hpp @@ -38,17 +38,22 @@ public: /// /// /// - long double width; + optional width; /// /// /// - std::size_t style; + bool custom_width = false; /// /// /// - bool custom; + optional style; + + /// + /// + /// + bool hidden = false; }; } // namespace xlnt diff --git a/include/xlnt/worksheet/row_properties.hpp b/include/xlnt/worksheet/row_properties.hpp index 949e6ada..c817923a 100644 --- a/include/xlnt/worksheet/row_properties.hpp +++ b/include/xlnt/worksheet/row_properties.hpp @@ -37,27 +37,22 @@ public: /// /// /// - long double height; + optional height; /// /// /// - bool visible; + bool custom_height = false; /// /// /// - int outline_level; + bool hidden = false; /// /// /// - bool collapsed; - - /// - /// - /// - int style_index; + optional style; }; } // namespace xlnt diff --git a/include/xlnt/worksheet/sheet_view.hpp b/include/xlnt/worksheet/sheet_view.hpp index 46a07461..43a0800c 100644 --- a/include/xlnt/worksheet/sheet_view.hpp +++ b/include/xlnt/worksheet/sheet_view.hpp @@ -31,6 +31,16 @@ namespace xlnt { +/// +/// +/// +enum class sheet_view_type +{ + normal, + page_break_preview, + page_layout +}; + /// /// Describes a view of a worksheet. /// Worksheets can have multiple views which show the data differently. @@ -166,6 +176,16 @@ public: return default_grid_color_; } + void type(sheet_view_type new_type) + { + type_ = new_type; + } + + sheet_view_type type() const + { + return type_; + } + bool operator==(const sheet_view &rhs) const { return id_ == rhs.id_ && show_grid_lines_ == rhs.show_grid_lines_ @@ -189,6 +209,11 @@ private: /// bool default_grid_color_ = true; + /// + /// + /// + sheet_view_type type_ = sheet_view_type::normal; + /// /// /// diff --git a/include/xlnt/worksheet/worksheet.hpp b/include/xlnt/worksheet/worksheet.hpp index 53e87427..d5c643f7 100644 --- a/include/xlnt/worksheet/worksheet.hpp +++ b/include/xlnt/worksheet/worksheet.hpp @@ -686,6 +686,11 @@ public: /// void add_view(const sheet_view &new_view); + std::vector &row_breaks(); + const std::vector &row_breaks() const; + std::vector &column_breaks(); + const std::vector &column_breaks() const; + private: friend class cell; friend class const_range_iterator; diff --git a/source/detail/worksheet_impl.hpp b/source/detail/worksheet_impl.hpp index 06809c93..9a625944 100644 --- a/source/detail/worksheet_impl.hpp +++ b/source/detail/worksheet_impl.hpp @@ -84,6 +84,8 @@ struct worksheet_impl print_title_rows_ = other.print_title_rows_; print_area_ = other.print_area_; views_ = other.views_; + column_breaks_ = other.column_breaks_; + row_breaks_ = other.row_breaks_; } workbook *parent_; @@ -110,6 +112,9 @@ struct worksheet_impl optional print_area_; std::vector views_; + + std::vector column_breaks_; + std::vector row_breaks_; }; } // namespace detail diff --git a/source/detail/xlsx_consumer.cpp b/source/detail/xlsx_consumer.cpp index 78b65960..69266e9f 100644 --- a/source/detail/xlsx_consumer.cpp +++ b/source/detail/xlsx_consumer.cpp @@ -56,6 +56,398 @@ struct hash namespace { +std::array, 3> parse_header_footer(const std::string &hf_string) +{ + std::array, 3> result; + + if (hf_string.empty()) + { + return result; + } + + enum class hf_code + { + left_section, // &L + center_section, // &C + right_section, // &R + current_page_number, // &P + total_page_number, // &N + font_size, // &# + text_font_color, // &KRRGGBB or &KTTSNN + text_strikethrough, // &S + text_superscript, // &X + text_subscript, // &Y + date, // &D + time, // &T + picture_as_background, // &G + text_single_underline, // &U + text_double_underline, // &E + workbook_file_path, // &Z + workbook_file_name, // &F + sheet_tab_name, // &A + add_to_page_number, // &+ + subtract_from_page_number, // &- + text_font_name, // &"font name,font type" + bold_font_style, // &B + italic_font_style, // &I + outline_style, // &O + shadow_style, // &H + text // everything else + }; + + struct hf_token + { + hf_code code = hf_code::text; + std::string value; + }; + + std::vector tokens; + std::size_t position = 0; + + while (position < hf_string.size()) + { + hf_token token; + + auto next_ampersand = hf_string.find('&', position + 1); + token.value = hf_string.substr(position, next_ampersand - position); + auto next_position = next_ampersand; + + if (hf_string[position] == '&') + { + token.value.clear(); + next_position = position + 2; + auto first_code_char = hf_string[position + 1]; + + if (first_code_char == '"') + { + auto end_quote_index = hf_string.find('"', position + 2); + next_position = end_quote_index + 1; + + token.value = hf_string.substr(position + 2, end_quote_index - position - 2); // remove quotes + token.code = hf_code::text_font_name; + } + else if (first_code_char == '&') + { + token.value = "&&"; // escaped ampersand + } + else if (first_code_char == 'L') + { + token.code = hf_code::left_section; + } + else if (first_code_char == 'C') + { + token.code = hf_code::center_section; + } + else if (first_code_char == 'R') + { + token.code = hf_code::right_section; + } + else if (first_code_char == 'P') + { + token.code = hf_code::current_page_number; + } + else if (first_code_char == 'N') + { + token.code = hf_code::total_page_number; + } + else if (std::string("0123456789").find(hf_string[position + 1]) != std::string::npos) + { + token.code = hf_code::font_size; + next_position = hf_string.find_first_not_of("0123456789", position + 1); + token.value = hf_string.substr(position + 1, next_position - position - 1); + } + else if (first_code_char == 'K') + { + if (hf_string[position + 4] == '+' || hf_string[position + 4] == '-') + { + token.value = hf_string.substr(position + 2, 5); + next_position = position + 7; + } + else + { + token.value = hf_string.substr(position + 2, 6); + next_position = position + 8; + } + + token.code = hf_code::text_font_color; + } + else if (first_code_char == 'S') + { + token.code = hf_code::text_strikethrough; + } + else if (first_code_char == 'X') + { + token.code = hf_code::text_superscript; + } + else if (first_code_char == 'Y') + { + token.code = hf_code::text_subscript; + } + else if (first_code_char == 'D') + { + token.code = hf_code::date; + } + else if (first_code_char == 'T') + { + token.code = hf_code::time; + } + else if (first_code_char == 'G') + { + token.code = hf_code::picture_as_background; + } + else if (first_code_char == 'U') + { + token.code = hf_code::text_single_underline; + } + else if (first_code_char == 'E') + { + token.code = hf_code::text_double_underline; + } + else if (first_code_char == 'Z') + { + token.code = hf_code::workbook_file_path; + } + else if (first_code_char == 'F') + { + token.code = hf_code::workbook_file_name; + } + else if (first_code_char == 'A') + { + token.code = hf_code::sheet_tab_name; + } + else if (first_code_char == '+') + { + token.code = hf_code::add_to_page_number; + } + else if (first_code_char == '-') + { + token.code = hf_code::subtract_from_page_number; + } + else if (first_code_char == 'B') + { + token.code = hf_code::bold_font_style; + } + else if (first_code_char == 'I') + { + token.code = hf_code::italic_font_style; + } + else if (first_code_char == 'O') + { + token.code = hf_code::outline_style; + } + else if (first_code_char == 'H') + { + token.code = hf_code::shadow_style; + } + } + + position = next_position; + tokens.push_back(token); + } + + const auto parse_section = [&tokens,&result](hf_code code) + { + std::vector end_codes + { + hf_code::left_section, + hf_code::center_section, + hf_code::right_section + }; + + end_codes.erase(std::find(end_codes.begin(), end_codes.end(), code)); + + std::size_t start_index = 0; + + while (start_index < tokens.size() && tokens[start_index].code != code) + { + ++start_index; + } + + if (start_index == tokens.size()) + { + return; + } + + ++start_index; // skip the section code + std::size_t end_index = start_index; + + while (end_index < tokens.size() + && std::find(end_codes.begin(), end_codes.end(), tokens[end_index].code) == end_codes.end()) + { + ++end_index; + } + + xlnt::formatted_text current_text; + xlnt::text_run current_run; + + // todo: all this nice parsing and the codes are just being turned back into text representations + // It would be nice to create an interface for the library to read and write these codes + + for (auto i = start_index; i < end_index; ++i) + { + const auto ¤t_token = tokens[i]; + + if (current_token.code == hf_code::text) + { + current_run.string(current_run.string() + current_token.value); + continue; + } + + if (!current_run.string().empty()) + { + current_text.add_run(current_run); + current_run = xlnt::text_run(); + } + + switch (current_token.code) + { + case hf_code::text: + break; // already handled above + + case hf_code::left_section: + break; // used below + + case hf_code::center_section: + break; // used below + + case hf_code::right_section: + break; // used below + + case hf_code::current_page_number: + current_run.string(current_run.string() + "&P"); + break; + + case hf_code::total_page_number: + current_run.string(current_run.string() + "&N"); + break; + + case hf_code::font_size: + current_run.size(static_cast(std::stoi(current_token.value))); + break; + + case hf_code::text_font_color: + if (current_token.value.size() == 6) + { + current_run.color(xlnt::rgb_color(current_token.value)); + } + + break; + + case hf_code::text_strikethrough: + break; + + case hf_code::text_superscript: + break; + + case hf_code::text_subscript: + break; + + case hf_code::date: + current_run.string(current_run.string() + "&D"); + break; + + case hf_code::time: + current_run.string(current_run.string() + "&T"); + break; + + case hf_code::picture_as_background: + current_run.string(current_run.string() + "&G"); + break; + + case hf_code::text_single_underline: + break; + + case hf_code::text_double_underline: + break; + + case hf_code::workbook_file_path: + current_run.string(current_run.string() + "&Z"); + break; + + case hf_code::workbook_file_name: + current_run.string(current_run.string() + "&F"); + break; + + case hf_code::sheet_tab_name: + current_run.string(current_run.string() + "&A"); + break; + + case hf_code::add_to_page_number: + break; + + case hf_code::subtract_from_page_number: + break; + + case hf_code::text_font_name: + { + auto comma_index = current_token.value.find(','); + auto font_name = current_token.value.substr(0, comma_index); + + if (font_name != "-") + { + current_run.font(font_name); + } + + if (comma_index != std::string::npos) + { + auto font_type = current_token.value.substr(comma_index + 1); + + if (font_type == "Bold") + { + current_run.bold(true); + } + else if (font_type == "Italic") + { + } + else if (font_type == "BoldItalic") + { + current_run.bold(true); + } + } + } + + break; + + case hf_code::bold_font_style: + current_run.bold(true); + break; + + case hf_code::italic_font_style: + break; + + case hf_code::outline_style: + break; + + case hf_code::shadow_style: + break; + } + } + + if (!current_run.string().empty()) + { + current_text.add_run(current_run); + } + + auto location_index = static_cast(code == hf_code::left_section ? 0 + : code == hf_code::center_section ? 1 : 2); + + if (!current_text.plain_text().empty()) + { + result[location_index] = current_text; + } + }; + + parse_section(hf_code::left_section); + parse_section(hf_code::center_section); + parse_section(hf_code::right_section); + + return result; +} + +} // namespace + +namespace { + #ifndef NDEBUG #define THROW_ON_INVALID_XML #endif @@ -1504,6 +1896,11 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id) new_view.default_grid_color(is_true(parser().attribute("defaultGridColor"))); } + if (parser().attribute_present("view") && parser().attribute("view") != "normal") + { + new_view.type(parser().attribute("view") == "pageBreakPreview" ?sheet_view_type::page_break_preview : sheet_view_type::page_layout); + } + skip_attributes({"windowProtection", "showFormulas", "showRowColHeaders", "showZeros", "rightToLeft", "tabSelected", "showRuler", "showOutlineSymbols", "showWhiteSpace", "view", "topLeftCell", "colorId", "zoomScale", "zoomScaleNormal", "zoomScaleSheetLayoutView", @@ -1579,16 +1976,29 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id) { expect_start_element(xml::qname(xmlns, "col"), xml::content::simple); - skip_attributes({"bestFit", "collapsed", "hidden", "outlineLevel"}); + skip_attributes({"bestFit", "collapsed", "outlineLevel"}); auto min = static_cast(std::stoull(parser().attribute("min"))); auto max = static_cast(std::stoull(parser().attribute("max"))); - auto width = std::stold(parser().attribute("width")); - auto column_style = parser().attribute_present("style") - ? parser().attribute("style") : static_cast(0); + optional width; + + if (parser().attribute_present("width")) + { + width = parser().attribute("width"); + } + + optional column_style; + + if (parser().attribute_present("style")) + { + column_style = parser().attribute("style"); + } + auto custom = parser().attribute_present("customWidth") ? is_true(parser().attribute("customWidth")) : false; + auto hidden = parser().attribute_present("hidden") + ? is_true(parser().attribute("hidden")) : false; expect_end_element(xml::qname(xmlns, "col")); @@ -1596,10 +2006,18 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id) { column_properties props; - props.width = width; - props.style = column_style; - props.custom = custom; + if (width.is_set()) + { + props.width = width.get(); + } + if (column_style.is_set()) + { + props.style = column_style.get(); + } + + props.hidden = hidden; + props.custom_width = custom; ws.add_column_properties(column, props); } } @@ -1613,13 +2031,22 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id) if (parser().attribute_present("ht")) { - ws.row_properties(row_index).height = parser().attribute("ht"); + ws.row_properties(row_index).height = parser().attribute("ht"); + } + + if (parser().attribute_present("customHeight")) + { + ws.row_properties(row_index).custom_height = is_true(parser().attribute("customHeight")); + } + + if (parser().attribute_present("hidden") && is_true(parser().attribute("hidden"))) + { + ws.row_properties(row_index).hidden = true; } skip_attributes({xml::qname(xmlns_x14ac, "dyDescent")}); - skip_attributes({"customFormat", "s", "customFont", "hidden", - "outlineLevel", "collapsed", "thickTop", "thickBot", "ph", - "spans", "customHeight"}); + skip_attributes({"customFormat", "s", "customFont", "outlineLevel", + "collapsed", "thickTop", "thickBot", "ph", "spans"}); while (in_element(xml::qname(xmlns, "row"))) { @@ -1824,15 +2251,148 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id) } else if (current_worksheet_element == xml::qname(xmlns, "headerFooter")) // CT_HeaderFooter 0-1 { - skip_remaining_content(current_worksheet_element); + header_footer hf; + + hf.align_with_margins(!parser().attribute_present("alignWithMargins") + || is_true(parser().attribute("alignWithMargins"))); + hf.scale_with_doc(!parser().attribute_present("alignWithMargins") + || is_true(parser().attribute("alignWithMargins"))); + auto different_odd_even = parser().attribute_present("differentOddEven") + && is_true(parser().attribute("differentOddEven")); + auto different_first = parser().attribute_present("differentFirst") + && is_true(parser().attribute("differentFirst")); + + optional, 3>> odd_header; + optional, 3>> odd_footer; + optional, 3>> even_header; + optional, 3>> even_footer; + optional, 3>> first_header; + optional, 3>> first_footer; + + while (in_element(current_worksheet_element)) + { + auto current_hf_element = expect_start_element(xml::content::simple); + + if (current_hf_element == xml::qname(xmlns, "oddHeader")) + { + odd_header = parse_header_footer(read_text()); + } + else if (current_hf_element == xml::qname(xmlns, "oddFooter")) + { + odd_footer = parse_header_footer(read_text()); + } + else if (current_hf_element == xml::qname(xmlns, "evenHeader")) + { + even_header = parse_header_footer(read_text()); + } + else if (current_hf_element == xml::qname(xmlns, "evenFooter")) + { + even_footer = parse_header_footer(read_text()); + } + else if (current_hf_element == xml::qname(xmlns, "firstHeader")) + { + first_header = parse_header_footer(read_text()); + } + else if (current_hf_element == xml::qname(xmlns, "firstFooter")) + { + first_footer = parse_header_footer(read_text()); + } + else + { + unexpected_element(current_hf_element); + } + + expect_end_element(current_hf_element); + } + + for (std::size_t i = 0; i < 3; ++i) + { + auto loc = i == 0 ? header_footer::location::left + : i == 1 ? header_footer::location::center + : header_footer::location::right; + + if (different_odd_even) + { + if (odd_header.is_set() && odd_header.get().at(i).is_set() + && even_header.is_set() && even_header.get().at(i).is_set()) + { + hf.odd_even_header(loc, odd_header.get().at(i).get(), even_header.get().at(i).get()); + } + + if (odd_footer.is_set() && odd_footer.get().at(i).is_set() + && even_footer.is_set() && even_footer.get().at(i).is_set()) + { + hf.odd_even_footer(loc, odd_footer.get().at(i).get(), even_footer.get().at(i).get()); + } + } + else + { + if (odd_header.is_set() && odd_header.get().at(i).is_set()) + { + hf.header(loc, odd_header.get().at(i).get()); + } + + if (odd_footer.is_set() && odd_footer.get().at(i).is_set()) + { + hf.footer(loc, odd_footer.get().at(i).get()); + } + } + + if (different_first) + { + + } + } + + ws.header_footer(hf); } else if (current_worksheet_element == xml::qname(xmlns, "rowBreaks")) // CT_PageBreak 0-1 { - skip_remaining_content(current_worksheet_element); + auto count = parser().attribute_present("count") ? parser().attribute("count") : 0; + auto manual_break_count = parser().attribute_present("manualBreakCount") ? parser().attribute("manualBreakCount") : 0; + + while (in_element(xml::qname(xmlns, "rowBreaks"))) + { + expect_start_element(xml::qname(xmlns, "brk"), xml::content::simple); + + if (parser().attribute_present("id")) + { + ws.row_breaks().push_back(parser().attribute("id")); + --count; + } + + if (parser().attribute_present("man") && is_true(parser().attribute("man"))) + { + --manual_break_count; + } + + skip_attributes({"min", "max", "pt"}); + expect_end_element(xml::qname(xmlns, "brk")); + } } else if (current_worksheet_element == xml::qname(xmlns, "colBreaks")) // CT_PageBreak 0-1 { - skip_remaining_content(current_worksheet_element); + auto count = parser().attribute_present("count") ? parser().attribute("count") : 0; + auto manual_break_count = parser().attribute_present("manualBreakCount") ? parser().attribute("manualBreakCount") : 0; + + while (in_element(xml::qname(xmlns, "colBreaks"))) + { + expect_start_element(xml::qname(xmlns, "brk"), xml::content::simple); + + if (parser().attribute_present("id")) + { + ws.column_breaks().push_back(parser().attribute("id")); + --count; + } + + if (parser().attribute_present("man") && is_true(parser().attribute("man"))) + { + --manual_break_count; + } + + skip_attributes({"min", "max", "pt"}); + expect_end_element(xml::qname(xmlns, "brk")); + } } else if (current_worksheet_element == xml::qname(xmlns, "customProperties")) // CT_CustomProperties 0-1 { @@ -1858,6 +2418,10 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id) { skip_remaining_content(current_worksheet_element); } + else if (current_worksheet_element == xml::qname(xmlns, "extLst")) + { + skip_remaining_content(current_worksheet_element); + } else { unexpected_element(current_worksheet_element); diff --git a/source/detail/xlsx_producer.cpp b/source/detail/xlsx_producer.cpp index 0fcde09d..10cac595 100644 --- a/source/detail/xlsx_producer.cpp +++ b/source/detail/xlsx_producer.cpp @@ -1837,6 +1837,11 @@ void xlsx_producer::write_worksheet(const relationship &rel) serializer().attribute("tabSelected", write_bool(view.id() == 0)); serializer().attribute("workbookViewId", view.id()); + if (view.type() != sheet_view_type::normal) + { + serializer().attribute("view", view.type() == sheet_view_type::page_break_preview ? "pageBreakPreview" : "pageLayout"); + } + if (view.has_pane()) { const auto ¤t_pane = view.pane(); @@ -1919,9 +1924,27 @@ void xlsx_producer::write_worksheet(const relationship &rel) serializer().start_element(xmlns, "col"); serializer().attribute("min", column.index); serializer().attribute("max", column.index); - serializer().attribute("width", props.width); - serializer().attribute("style", props.style); - serializer().attribute("customWidth", write_bool(props.custom)); + + 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)); + } + serializer().end_element(xmlns, "col"); } @@ -1971,17 +1994,31 @@ void xlsx_producer::write_worksheet(const relationship &rel) if (ws.has_row_properties(row.front().row())) { - serializer().attribute("customHeight", "1"); - auto height = ws.row_properties(row.front().row()).height; + const auto &props = ws.row_properties(row.front().row()); + + if (props.custom_height) + { + serializer().attribute("customHeight", write_bool(true)); + } - if (std::fabs(height - std::floor(height)) == 0.L) - { - serializer().attribute("ht", std::to_string(static_cast(height)) + ".0"); - } - else - { - serializer().attribute("ht", height); - } + 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(height)) + ".0"); + } + else + { + serializer().attribute("ht", height); + } + } + + if (props.hidden) + { + serializer().attribute("hidden", write_bool(true)); + } } for (auto cell : row) @@ -2222,7 +2259,56 @@ void xlsx_producer::write_worksheet(const relationship &rel) { header_footer::location::right, "&R" }, }; - return location_code_map.at(where) + t.plain_text(); + 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; }; const auto locations = @@ -2308,6 +2394,44 @@ void xlsx_producer::write_worksheet(const relationship &rel) serializer().end_element(xmlns, "headerFooter"); } + 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"); + } + if (!worksheet_rels.empty()) { for (const auto &child_rel : worksheet_rels) diff --git a/source/workbook/tests/test_consume_xlsx.hpp b/source/workbook/tests/test_consume_xlsx.hpp index 3964fe69..ff0d776e 100644 --- a/source/workbook/tests/test_consume_xlsx.hpp +++ b/source/workbook/tests/test_consume_xlsx.hpp @@ -88,4 +88,36 @@ public: TS_ASSERT_EQUALS(wb.active_sheet().cell("A1").hyperlink(), "https://fr.wikipedia.org/wiki/Ille-et-Vilaine"); } + + void test_read_headers_and_footers() + { + xlnt::workbook wb; + wb.load("data/21_headers_and_footers.xlsx"); + auto ws = wb.active_sheet(); + + TS_ASSERT_EQUALS(ws.cell("A1").value(), "header"); + TS_ASSERT_EQUALS(ws.cell("A2").value(), "and"); + TS_ASSERT_EQUALS(ws.cell("A3").value(), "footer"); + TS_ASSERT_EQUALS(ws.cell("A4").value(), "page1"); + TS_ASSERT_EQUALS(ws.cell("A43").value(), "page2"); + + TS_ASSERT(ws.has_header_footer()); + TS_ASSERT(ws.header_footer().align_with_margins()); + TS_ASSERT(ws.header_footer().scale_with_doc()); + TS_ASSERT(!ws.header_footer().different_first()); + TS_ASSERT(!ws.header_footer().different_odd_even()); + + TS_ASSERT(ws.header_footer().has_header(xlnt::header_footer::location::left)); + TS_ASSERT_EQUALS(ws.header_footer().header(xlnt::header_footer::location::left).plain_text(), "left header"); + TS_ASSERT(ws.header_footer().has_header(xlnt::header_footer::location::center)); + TS_ASSERT_EQUALS(ws.header_footer().header(xlnt::header_footer::location::center).plain_text(), "center header"); + TS_ASSERT(ws.header_footer().has_header(xlnt::header_footer::location::right)); + TS_ASSERT_EQUALS(ws.header_footer().header(xlnt::header_footer::location::right).plain_text(), "right header"); + TS_ASSERT(ws.header_footer().has_footer(xlnt::header_footer::location::left)); + TS_ASSERT_EQUALS(ws.header_footer().footer(xlnt::header_footer::location::left).plain_text(), "left && footer"); + TS_ASSERT(ws.header_footer().has_footer(xlnt::header_footer::location::center)); + TS_ASSERT_EQUALS(ws.header_footer().footer(xlnt::header_footer::location::center).plain_text(), "center footer"); + TS_ASSERT(ws.header_footer().has_footer(xlnt::header_footer::location::right)); + TS_ASSERT_EQUALS(ws.header_footer().footer(xlnt::header_footer::location::right).plain_text(), "right footer"); + } }; diff --git a/source/workbook/tests/test_round_trip.hpp b/source/workbook/tests/test_round_trip.hpp index 6dc7cb27..5e9e7c70 100644 --- a/source/workbook/tests/test_round_trip.hpp +++ b/source/workbook/tests/test_round_trip.hpp @@ -20,14 +20,14 @@ public: { std::vector original_buffer; original.save(original_buffer); - original.save("b.xlsx"); + original.save("round_trip_in.xlsx"); xlnt::workbook resulting_workbook; resulting_workbook.load(original_buffer); std::vector resulting_buffer; resulting_workbook.save(resulting_buffer); - resulting_workbook.save("a.xlsx"); + resulting_workbook.save("round_trip_out.xlsx"); return xml_helper::xlsx_archives_match(original_buffer, resulting_buffer); } @@ -52,7 +52,7 @@ public: std::vector buffer; original_workbook.save(buffer); - original_workbook.save("a.xlsx"); + original_workbook.save("round_trip_out.xlsx"); return xml_helper::xlsx_archives_match(original_data, buffer); } @@ -108,11 +108,24 @@ public: void test_round_trip_all_styles_rw() { auto path = path_helper::get_data_directory("13_all_styles.xlsx"); - xlnt::workbook original_workbook; - original_workbook.load(path); - - std::vector buffer; - original_workbook.save(buffer); TS_ASSERT(round_trip_matches_rw(path)); } + + void test_round_trip_headers_footers() + { + auto path = path_helper::get_data_directory("21_headers_and_footers.xlsx"); + TS_ASSERT(round_trip_matches_rw(path)); + } + + void test_round_trip_row_and_col_props() + { + auto path = path_helper::get_data_directory("22_row_and_col_properties.xlsx"); + TS_ASSERT(round_trip_matches_rw(path)); + } + + void test_round_trip_page_breaks() + { + auto path = path_helper::get_data_directory("23_page_breaks.xlsx"); + TS_ASSERT(round_trip_matches_rw(path)); + } }; diff --git a/source/worksheet/header_footer.cpp b/source/worksheet/header_footer.cpp index bb2d1ba0..a5b5c838 100644 --- a/source/worksheet/header_footer.cpp +++ b/source/worksheet/header_footer.cpp @@ -54,7 +54,7 @@ bool header_footer::different_odd_even() const bool header_footer::different_first() const { - return first_headers_.empty() || !first_footers_.empty(); + return !first_headers_.empty() || !first_footers_.empty(); } bool header_footer::scale_with_doc() const diff --git a/source/worksheet/worksheet.cpp b/source/worksheet/worksheet.cpp index 81397582..044d6abb 100644 --- a/source/worksheet/worksheet.cpp +++ b/source/worksheet/worksheet.cpp @@ -815,16 +815,16 @@ std::vector worksheet::formula_attributes() const cell_reference worksheet::point_pos(int left, int top) const { - static const auto DefaultColumnWidth = 51.85L; - static const auto DefaultRowHeight = 15.0L; + static const auto DefaultColumnWidth = 51.85; + static const auto DefaultRowHeight = 15.0; - auto points_to_pixels = [](long double value, long double dpi) + auto points_to_pixels = [](double value, double dpi) { return static_cast(std::ceil(value * dpi / 72)); }; - auto default_height = points_to_pixels(DefaultRowHeight, 96.0L); - auto default_width = points_to_pixels(DefaultColumnWidth, 96.0L); + auto default_height = points_to_pixels(DefaultRowHeight, 96.0); + auto default_width = points_to_pixels(DefaultColumnWidth, 96.0); column_t current_column = 1; row_t current_row = 1; @@ -836,13 +836,13 @@ cell_reference worksheet::point_pos(int left, int top) const { current_column++; - if (has_column_properties(current_column)) + if (has_column_properties(current_column) && column_properties(current_column).width.is_set()) { - auto cdw = column_properties(current_column).width; + auto cdw = column_properties(current_column).width.get(); if (cdw >= 0) { - left_pos += points_to_pixels(cdw, 96.0L); + left_pos += points_to_pixels(cdw, 96.0); continue; } } @@ -854,13 +854,13 @@ cell_reference worksheet::point_pos(int left, int top) const { current_row++; - if (has_row_properties(current_row)) + if (has_row_properties(current_row) && row_properties(current_row).height.is_set()) { - auto cdh = row_properties(current_row).height; + auto cdh = row_properties(current_row).height.get(); if (cdh >= 0) { - top_pos += points_to_pixels(cdh, 96.0L); + top_pos += points_to_pixels(cdh, 96.0); continue; } } @@ -1045,4 +1045,24 @@ void worksheet::header_footer(const class header_footer &hf) d_->header_footer_ = hf; } +std::vector &worksheet::row_breaks() +{ + return d_->row_breaks_; +} + +const std::vector &worksheet::row_breaks() const +{ + return d_->row_breaks_; +} + +std::vector &worksheet::column_breaks() +{ + return d_->column_breaks_; +} + +const std::vector &worksheet::column_breaks() const +{ + return d_->column_breaks_; +} + } // namespace xlnt diff --git a/tests/data/21_headers_and_footers.xlsx b/tests/data/21_headers_and_footers.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..efee434bb2c09732231167fb9963d2ae6a91432d GIT binary patch literal 21510 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

0T7J<+VTpB60SMZ&@En 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 AB>(^b literal 0 HcmV?d00001 diff --git a/tests/data/23_page_breaks.xlsx b/tests/data/23_page_breaks.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..b4eb6f2807a227cdbadd229394b4007430d592ac GIT binary patch literal 29315 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 X)y-J~ToF;@IuxQBXaJW&MF08+ZUC*c literal 0 HcmV?d00001