fix some xlsx consumption and production

This commit is contained in:
Thomas Fussell 2016-10-13 20:11:02 -04:00
parent cf019f6af6
commit 4d20ccaa67
7 changed files with 107 additions and 33 deletions

View File

@ -52,7 +52,7 @@ public:
optional<int> rotation() const;
alignment &rotation(bool text_rotation);
alignment &rotation(int text_rotation);
optional<horizontal_alignment> horizontal() const;

View File

@ -54,6 +54,10 @@ public:
bool bold() const;
font &superscript(bool superscript);
bool superscript() const;
font &italic(bool italic);
bool italic() const;

View File

@ -673,9 +673,11 @@ void xlsx_consumer::read_pivot_table()
void xlsx_consumer::read_shared_string_table()
{
static const auto xmlns = constants::get_namespace("shared-strings");
static const auto xmlns = constants::get_namespace("worksheet");
parser().next_expect(xml::parser::event_type::start_element, xmlns, "sst");
parser().content(xml::content::complex);
std::size_t unique_count = 0;
if (parser().attribute_present("uniqueCount"))
@ -690,12 +692,14 @@ void xlsx_consumer::read_shared_string_table()
if (parser().peek() == xml::parser::event_type::end_element) break;
parser().next_expect(xml::parser::event_type::start_element, xmlns, "si");
parser().content(xml::content::complex);
parser().next_expect(xml::parser::event_type::start_element);
text t;
if (parser().name() == "t")
{
parser().next_expect(xml::parser::event_type::characters);
t.set_plain_string(parser().value());
}
else if (parser().name() == "r") // possible multiple text entities.
@ -705,8 +709,8 @@ void xlsx_consumer::read_shared_string_table()
if (parser().peek() == xml::parser::event_type::end_element) break;
parser().next_expect(xml::parser::event_type::start_element, xmlns, "t");
text_run run;
parser().next_expect(xml::parser::event_type::characters);
text_run run;
run.set_string(parser().value());
if (parser().peek() == xml::parser::event_type::start_element)
@ -740,7 +744,7 @@ void xlsx_consumer::read_shared_string_table()
run.set_scheme(parser().attribute("val"));
}
parser().next_expect(xml::parser::event_type::end_element, parser().qname());
parser().next_expect(xml::parser::event_type::end_element);
}
}
@ -748,6 +752,8 @@ void xlsx_consumer::read_shared_string_table()
}
}
parser().next_expect(xml::parser::event_type::end_element);
parser().next_expect(xml::parser::event_type::end_element);
strings.push_back(t);
}
@ -1022,6 +1028,10 @@ void xlsx_consumer::read_stylesheet()
new_font.bold(true);
}
}
else if (parser().name() == "vertAlign")
{
new_font.superscript(parser().attribute("val") == "superscript");
}
else if (parser().name() == "strike")
{
if (parser().attribute_present("val"))
@ -1127,6 +1137,7 @@ void xlsx_consumer::read_stylesheet()
if (parser().peek() == xml::parser::event_type::end_element) break;
parser().next_expect(xml::parser::event_type::start_element, xmlns, "xf");
parser().content(xml::content::complex);
auto &record = *(!in_style_records
? format_records.emplace(format_records.end())
@ -1179,8 +1190,25 @@ void xlsx_consumer::read_stylesheet()
if (parser().qname() == xml::qname(xmlns, "alignment"))
{
record.alignment.first.wrap(is_true(parser().attribute("wrapText")));
record.alignment.first.shrink(is_true(parser().attribute("shrinkToFit")));
if (parser().attribute_present("wrapText"))
{
record.alignment.first.wrap(is_true(parser().attribute("wrapText")));
}
if (parser().attribute_present("shrinkToFit"))
{
record.alignment.first.shrink(is_true(parser().attribute("shrinkToFit")));
}
if (parser().attribute_present("indent"))
{
record.alignment.first.indent(parser().attribute<int>("indent"));
}
if (parser().attribute_present("textRotation"))
{
record.alignment.first.rotation(parser().attribute<int>("textRotation"));
}
if (parser().attribute_present("vertical"))
{
@ -1462,6 +1490,7 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id)
if (parser().peek() == xml::parser::event_type::end_element) break;
parser().next_expect(xml::parser::event_type::start_element, xmlns, "row");
parser().content(xml::content::complex);
auto row_index = static_cast<row_t>(std::stoull(parser().attribute("r")));
@ -1470,6 +1499,16 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id)
ws.get_row_properties(row_index).height = std::stold(parser().attribute("ht"));
}
if (parser().attribute_present("customHeight"))
{
ws.get_row_properties(row_index).height = std::stold(parser().attribute("customHeight"));
}
if (parser().attribute_present(xml::qname(xmlns_x14ac, "dyDescent")))
{
parser().attribute(xml::qname(xmlns_x14ac, "dyDescent"));
}
std::string span_string = parser().attribute("spans");
auto colon_index = span_string.find(':');
@ -1492,6 +1531,7 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id)
if (parser().peek() == xml::parser::event_type::end_element) break;
parser().next_expect(xml::parser::event_type::start_element, xmlns, "c");
parser().content(xml::content::complex);
auto cell = ws.get_cell(cell_reference(parser().attribute("r")));
auto has_type = parser().attribute_present("t");
@ -1516,22 +1556,26 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id)
if (parser().qname() == xml::qname(xmlns, "v"))
{
has_value = true;
parser().next_expect(xml::parser::event_type::characters);
value_string = parser().value();
}
else if (parser().qname() == xml::qname(xmlns, "f"))
{
has_formula = true;
has_shared_formula = parser().attribute_present("t") && parser().attribute("t") == "shared";
has_shared_formula = parser().attribute_present("t")
&& parser().attribute("t") == "shared";
parser().next_expect(xml::parser::event_type::characters);
formula_value_string = parser().value();
}
else if (parser().qname() == xml::qname(xmlns, "is"))
{
parser().next_expect(xml::parser::event_type::start_element, xmlns, "t");
parser().next_expect(xml::parser::event_type::characters);
value_string = parser().value();
parser().next_expect(xml::parser::event_type::end_element, xmlns, "t");
}
parser().next_expect(xml::parser::event_type::end_element, parser().qname());
parser().next_expect(xml::parser::event_type::end_element);
}
if (has_formula && !has_shared_formula && !ws.get_workbook().get_data_only())
@ -1572,6 +1616,8 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id)
parser().next_expect(xml::parser::event_type::end_element, xmlns, "c");
}
parser().next_expect(xml::parser::event_type::end_element, xmlns, "row");
}
parser().next_expect(xml::parser::event_type::end_element, xmlns, "sheetData");
@ -1602,6 +1648,11 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id)
ws.get_column_properties(min).custom = custom;
}
if (parser().attribute_present("bestFit"))
{
parser().attribute("bestFit");
}
parser().next_expect(xml::parser::event_type::end_element, xmlns, "col");
}

View File

@ -758,9 +758,19 @@ void xlsx_producer::write_styles(const relationship &rel)
serializer().start_element(xmlns, "fonts");
serializer().attribute("count", fonts.size());
auto num_known_fonts = std::count_if(fonts.begin(), fonts.end(), [](const xlnt::font &f)
{
static const auto known_fonts = std::vector<xlnt::font>
{
xlnt::font().color(xlnt::theme_color(1)).scheme("minor").family(2)
};
return std::find(known_fonts.begin(), known_fonts.end(), f) != known_fonts.end();
});
if (source_.x15_enabled())
{
serializer().attribute(xmlns_x14ac, "knownFonts", fonts.size());
serializer().attribute(xmlns_x14ac, "knownFonts", num_known_fonts);
}
for (const auto &current_font : fonts)
@ -999,7 +1009,7 @@ void xlsx_producer::write_styles(const relationship &rel)
{
const auto current_alignment = current_style.alignment();
serializer().start_element("alignment");
serializer().start_element(xmlns, "alignment");
if (current_alignment.vertical())
{
@ -1031,17 +1041,17 @@ void xlsx_producer::write_styles(const relationship &rel)
serializer().attribute("shrinkToFit", write_bool(*current_alignment.shrink()));
}
serializer().end_element("alignment");
serializer().end_element(xmlns, "alignment");
}
if (current_style.protection_applied())
{
const auto current_protection = current_style.protection();
serializer().start_element("protection");
serializer().start_element(xmlns, "protection");
serializer().attribute("locked", write_bool(current_protection.locked()));
serializer().attribute("hidden", write_bool(current_protection.hidden()));
serializer().end_element("protection");
serializer().end_element(xmlns, "protection");
}
serializer().end_element(xmlns, "xf");
@ -1072,11 +1082,18 @@ void xlsx_producer::write_styles(const relationship &rel)
if (current_format.alignment_applied()) serializer().attribute("applyAlignment", write_bool(true));
if (current_format.protection_applied()) serializer().attribute("applyProtection", write_bool(true));
if (current_format.has_style())
{
serializer().attribute("xfId", std::distance(stylesheet.styles.begin(),
std::find_if(stylesheet.styles.begin(), stylesheet.styles.end(),
[&](const xlnt::style &s) { return s.name() == current_format.style().name(); })));
}
if (current_format.alignment_applied())
{
const auto current_alignment = current_format.alignment();
serializer().start_element("alignment");
serializer().start_element(xmlns, "alignment");
if (current_alignment.vertical())
{
@ -1108,24 +1125,17 @@ void xlsx_producer::write_styles(const relationship &rel)
serializer().attribute("shrinkToFit", write_bool(*current_alignment.shrink()));
}
serializer().end_element("alignment");
serializer().end_element(xmlns, "alignment");
}
if (current_format.protection_applied())
{
const auto current_protection = current_format.protection();
serializer().start_element("protection");
serializer().start_element(xmlns, "protection");
serializer().attribute("locked", write_bool(current_protection.locked()));
serializer().attribute("hidden", write_bool(current_protection.hidden()));
serializer().end_element("protection");
}
if (current_format.has_style())
{
serializer().attribute("xfId", std::distance(stylesheet.styles.begin(),
std::find_if(stylesheet.styles.begin(), stylesheet.styles.end(),
[&](const xlnt::style &s) { return s.name() == current_format.style().name(); })));
serializer().end_element(xmlns, "protection");
}
serializer().end_element(xmlns, "xf");
@ -1845,13 +1855,13 @@ void xlsx_producer::write_worksheet(const relationship &rel)
const auto &props = ws.get_column_properties(column);
serializer().end_element(xmlns, "col");
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));
serializer().end_element(xmlns, "cols");
serializer().end_element(xmlns, "col");
}
serializer().end_element(xmlns, "cols");

View File

@ -81,9 +81,9 @@ optional<int> alignment::indent() const
return indent_;
}
alignment &alignment::rotation(bool value)
alignment &alignment::rotation(int value)
{
text_rotation_ = 0;
text_rotation_ = value;
return *this;
}

View File

@ -50,6 +50,17 @@ bool font::bold() const
return bold_;
}
font &font::superscript(bool superscript)
{
superscript_ = superscript;
return *this;
}
bool font::superscript() const
{
return superscript_;
}
font &font::italic(bool italic)
{
italic_ = italic;

View File

@ -93,7 +93,6 @@ public:
void test_round_trip_empty_excel_rw()
{
TS_SKIP("");
auto path = path_helper::get_data_directory("9_default-excel.xlsx");
TS_ASSERT(round_trip_matches_rw(path));
}
@ -107,13 +106,12 @@ public:
void test_round_trip_all_styles_rw()
{
TS_SKIP("");
auto path = path_helper::get_data_directory("13_all_styles.xlsx");
xlnt::workbook original_workbook;
original_workbook.load(path);
std::vector<std::uint8_t> buffer;
original_workbook.save(buffer);
// TS_ASSERT(round_trip_matches_rw(path));
//TS_ASSERT(round_trip_matches_rw(path));
}
};