mirror of
https://github.com/tfussell/xlnt.git
synced 2024-03-22 13:11:17 +08:00
start implementing complex number formats, test builtin formats
This commit is contained in:
parent
627e6d438e
commit
9f1ac60d20
|
@ -36,28 +36,21 @@ namespace xlnt {
|
||||||
class XLNT_CLASS protection : public hashable
|
class XLNT_CLASS protection : public hashable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum class type
|
|
||||||
{
|
|
||||||
inherit,
|
|
||||||
protected_,
|
|
||||||
unprotected
|
|
||||||
};
|
|
||||||
|
|
||||||
protection();
|
protection();
|
||||||
protection(type locked);
|
protection(bool locked, bool hidden);
|
||||||
|
|
||||||
type get_locked() const;
|
bool get_locked() const;
|
||||||
void set_locked(type locked_type);
|
void set_locked(bool locked);
|
||||||
|
|
||||||
type get_hidden() const;
|
bool get_hidden() const;
|
||||||
void set_hidden(type hidden_type);
|
void set_hidden(bool hidden);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::string to_hash_string() const override;
|
std::string to_hash_string() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
type locked_;
|
bool locked_;
|
||||||
type hidden_;
|
bool hidden_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace xlnt
|
} // namespace xlnt
|
||||||
|
|
|
@ -420,14 +420,11 @@ public:
|
||||||
|
|
||||||
TS_ASSERT(!cell.has_format());
|
TS_ASSERT(!cell.has_format());
|
||||||
|
|
||||||
xlnt::protection prot;
|
cell.set_protection(xlnt::protection(false, true));
|
||||||
prot.set_locked(xlnt::protection::type::protected_);
|
|
||||||
|
|
||||||
cell.set_protection(prot);
|
|
||||||
|
|
||||||
TS_ASSERT(cell.has_format());
|
TS_ASSERT(cell.has_format());
|
||||||
TS_ASSERT(cell.get_format().protection_applied());
|
TS_ASSERT(cell.get_format().protection_applied());
|
||||||
TS_ASSERT_EQUALS(cell.get_protection(), prot);
|
TS_ASSERT_EQUALS(cell.get_protection(), xlnt::protection(false, true));
|
||||||
|
|
||||||
TS_ASSERT(cell.has_format());
|
TS_ASSERT(cell.has_format());
|
||||||
cell.clear_format();
|
cell.clear_format();
|
||||||
|
|
|
@ -465,10 +465,40 @@ void number_format_parser::finalize()
|
||||||
bool leading_zero = false;
|
bool leading_zero = false;
|
||||||
std::size_t minutes_index = 0;
|
std::size_t minutes_index = 0;
|
||||||
|
|
||||||
|
bool integer_part = false;
|
||||||
|
bool fractional_part = false;
|
||||||
|
std::size_t integer_part_index = 0;
|
||||||
|
|
||||||
|
bool percentage = false;
|
||||||
|
|
||||||
|
bool exponent = false;
|
||||||
|
std::size_t exponent_index = 0;
|
||||||
|
|
||||||
for (std::size_t i = 0; i < code.parts.size(); ++i)
|
for (std::size_t i = 0; i < code.parts.size(); ++i)
|
||||||
{
|
{
|
||||||
const auto &part = code.parts[i];
|
const auto &part = code.parts[i];
|
||||||
|
|
||||||
|
if (part.placeholders.type == format_placeholders::placeholders_type::integer_part)
|
||||||
|
{
|
||||||
|
integer_part = true;
|
||||||
|
integer_part_index = i;
|
||||||
|
}
|
||||||
|
else if (part.placeholders.type == format_placeholders::placeholders_type::fractional_part)
|
||||||
|
{
|
||||||
|
fractional_part = true;
|
||||||
|
}
|
||||||
|
else if (part.placeholders.type == format_placeholders::placeholders_type::scientific_exponent_plus
|
||||||
|
|| part.placeholders.type == format_placeholders::placeholders_type::scientific_exponent_minus)
|
||||||
|
{
|
||||||
|
exponent = true;
|
||||||
|
exponent_index = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (part.placeholders.percentage)
|
||||||
|
{
|
||||||
|
percentage = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (part.type == template_part::template_type::month_number
|
if (part.type == template_part::template_type::month_number
|
||||||
|| part.type == template_part::template_type::month_number_leading_zero)
|
|| part.type == template_part::template_type::month_number_leading_zero)
|
||||||
{
|
{
|
||||||
|
@ -514,6 +544,30 @@ void number_format_parser::finalize()
|
||||||
template_part::template_type::minute_leading_zero :
|
template_part::template_type::minute_leading_zero :
|
||||||
template_part::template_type::minute;
|
template_part::template_type::minute;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (integer_part && !fractional_part)
|
||||||
|
{
|
||||||
|
code.parts[integer_part_index].placeholders.type = format_placeholders::placeholders_type::integer_only;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (integer_part && fractional_part && percentage)
|
||||||
|
{
|
||||||
|
code.parts[integer_part_index].placeholders.percentage = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exponent)
|
||||||
|
{
|
||||||
|
const auto &next = code.parts[exponent_index + 1];
|
||||||
|
auto temp = code.parts[exponent_index].placeholders.type;
|
||||||
|
code.parts[exponent_index].placeholders = next.placeholders;
|
||||||
|
code.parts[exponent_index].placeholders.type = temp;
|
||||||
|
code.parts.erase(code.parts.begin() + exponent_index + 1);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < code.parts.size(); ++i)
|
||||||
|
{
|
||||||
|
code.parts[i].placeholders.scientific = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
validate();
|
validate();
|
||||||
|
@ -608,15 +662,18 @@ number_format_token number_format_parser::parse_next_token()
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
token.string.push_back(current_char);
|
token.string.push_back(current_char);
|
||||||
current_char = format_string_[position_];
|
current_char = format_string_[position_++];
|
||||||
|
|
||||||
if (current_char != '.')
|
|
||||||
{
|
|
||||||
++position_;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
while (current_char == '0' || current_char == '#' || current_char == '?' || current_char == ',');
|
while (current_char == '0' || current_char == '#' || current_char == '?' || current_char == ',');
|
||||||
|
|
||||||
|
--position_;
|
||||||
|
|
||||||
|
if (current_char == '%')
|
||||||
|
{
|
||||||
|
token.string.push_back('%');
|
||||||
|
++position_;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'y':
|
case 'y':
|
||||||
|
@ -693,6 +750,17 @@ number_format_token number_format_parser::parse_next_token()
|
||||||
token.string.push_back(current_char);
|
token.string.push_back(current_char);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'E':
|
||||||
|
token.type = number_format_token::token_type::number;
|
||||||
|
token.string.push_back(current_char);
|
||||||
|
current_char = format_string_[position_++];
|
||||||
|
|
||||||
|
if (current_char == '+' || current_char == '-')
|
||||||
|
{
|
||||||
|
token.string.push_back(current_char);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("unexpected character");
|
throw std::runtime_error("unexpected character");
|
||||||
}
|
}
|
||||||
|
@ -736,6 +804,22 @@ format_placeholders number_format_parser::parse_placeholders(const std::string &
|
||||||
{
|
{
|
||||||
p.type = format_placeholders::placeholders_type::fractional_part;
|
p.type = format_placeholders::placeholders_type::fractional_part;
|
||||||
}
|
}
|
||||||
|
else if (placeholders_string.front() == 'E')
|
||||||
|
{
|
||||||
|
p.type = placeholders_string[1] == '+'
|
||||||
|
? format_placeholders::placeholders_type::scientific_exponent_plus
|
||||||
|
: format_placeholders::placeholders_type::scientific_exponent_minus;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p.type = format_placeholders::placeholders_type::integer_part;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (placeholders_string.back() == '%')
|
||||||
|
{
|
||||||
|
p.percentage = true;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::size_t> comma_indices;
|
std::vector<std::size_t> comma_indices;
|
||||||
|
|
||||||
|
@ -983,10 +1067,28 @@ std::string number_formatter::fill_placeholders(const format_placeholders &p, lo
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p.percentage)
|
||||||
|
{
|
||||||
|
number *= 100;
|
||||||
|
}
|
||||||
|
|
||||||
auto integer_part = static_cast<int>(number);
|
auto integer_part = static_cast<int>(number);
|
||||||
|
|
||||||
if (p.type != format_placeholders::placeholders_type::fractional_part)
|
if (p.type == format_placeholders::placeholders_type::integer_only
|
||||||
|
|| p.type == format_placeholders::placeholders_type::integer_part)
|
||||||
{
|
{
|
||||||
|
if (p.scientific)
|
||||||
|
{
|
||||||
|
auto fractional_part = number;
|
||||||
|
|
||||||
|
while (fractional_part > 10)
|
||||||
|
{
|
||||||
|
fractional_part /= 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
integer_part = static_cast<int>(fractional_part);
|
||||||
|
}
|
||||||
|
|
||||||
auto result = std::to_string(integer_part);
|
auto result = std::to_string(integer_part);
|
||||||
|
|
||||||
while (result.size() < p.num_zeros)
|
while (result.size() < p.num_zeros)
|
||||||
|
@ -1017,14 +1119,32 @@ std::string number_formatter::fill_placeholders(const format_placeholders &p, lo
|
||||||
result = std::string(temp.rbegin(), temp.rend());
|
result = std::string(temp.rbegin(), temp.rend());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p.percentage && p.type == format_placeholders::placeholders_type::integer_only)
|
||||||
|
{
|
||||||
|
result.push_back('%');
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
else
|
else if (p.type == format_placeholders::placeholders_type::fractional_part)
|
||||||
{
|
{
|
||||||
auto fractional_part = number - integer_part;
|
auto fractional_part = number - integer_part;
|
||||||
auto result = std::to_string(fractional_part).substr(1);
|
|
||||||
|
|
||||||
while (result.back() == '0')
|
if (p.scientific)
|
||||||
|
{
|
||||||
|
fractional_part = number;
|
||||||
|
|
||||||
|
while (fractional_part > 10)
|
||||||
|
{
|
||||||
|
fractional_part /= 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
fractional_part -= static_cast<int>(fractional_part);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result = fractional_part == 0 ? std::string(".") : std::to_string(fractional_part).substr(1);
|
||||||
|
|
||||||
|
while (result.back() == '0' || result.size() > (p.num_zeros + p.num_optionals + 1))
|
||||||
{
|
{
|
||||||
result.pop_back();
|
result.pop_back();
|
||||||
}
|
}
|
||||||
|
@ -1039,8 +1159,45 @@ std::string number_formatter::fill_placeholders(const format_placeholders &p, lo
|
||||||
result.push_back(' ');
|
result.push_back(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p.percentage)
|
||||||
|
{
|
||||||
|
result.push_back('%');
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
else if (p.type == format_placeholders::placeholders_type::scientific_exponent_minus
|
||||||
|
|| p.type == format_placeholders::placeholders_type::scientific_exponent_plus)
|
||||||
|
{
|
||||||
|
auto exponent = number != 0 ? static_cast<int>(std::log10(integer_part)) : 0;
|
||||||
|
auto result = std::to_string(exponent);
|
||||||
|
|
||||||
|
while (result.back() == '0' || result.size() > (p.num_zeros + p.num_optionals))
|
||||||
|
{
|
||||||
|
result.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (result.size() < p.num_zeros)
|
||||||
|
{
|
||||||
|
result = "0" + result;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (result.size() < p.num_zeros + p.num_spaces)
|
||||||
|
{
|
||||||
|
result = " " + result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p.percentage)
|
||||||
|
{
|
||||||
|
result.push_back('%');
|
||||||
|
}
|
||||||
|
|
||||||
|
result = (p.type == format_placeholders::placeholders_type::scientific_exponent_plus ? "E+" : "E") + result;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string number_formatter::format_number(const format_code &format, long double number)
|
std::string number_formatter::format_number(const format_code &format, long double number)
|
||||||
|
@ -1188,6 +1345,7 @@ std::string number_formatter::format_number(const format_code &format, long doub
|
||||||
std::string number_formatter::format_text(const format_code &format, const std::string &text)
|
std::string number_formatter::format_text(const format_code &format, const std::string &text)
|
||||||
{
|
{
|
||||||
std::string result;
|
std::string result;
|
||||||
|
bool any_text_part = false;
|
||||||
|
|
||||||
for (const auto &part : format.parts)
|
for (const auto &part : format.parts)
|
||||||
{
|
{
|
||||||
|
@ -1195,6 +1353,7 @@ std::string number_formatter::format_text(const format_code &format, const std::
|
||||||
{
|
{
|
||||||
case template_part::template_type::text:
|
case template_part::template_type::text:
|
||||||
result.append(part.string);
|
result.append(part.string);
|
||||||
|
any_text_part = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case template_part::template_type::general:
|
case template_part::template_type::general:
|
||||||
|
@ -1202,6 +1361,7 @@ std::string number_formatter::format_text(const format_code &format, const std::
|
||||||
|| part.placeholders.type == format_placeholders::placeholders_type::text)
|
|| part.placeholders.type == format_placeholders::placeholders_type::text)
|
||||||
{
|
{
|
||||||
result.append(text);
|
result.append(text);
|
||||||
|
any_text_part = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -1211,6 +1371,11 @@ std::string number_formatter::format_text(const format_code &format, const std::
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!format.parts.empty() && !any_text_part)
|
||||||
|
{
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -236,16 +236,20 @@ struct format_placeholders
|
||||||
bad,
|
bad,
|
||||||
general,
|
general,
|
||||||
text,
|
text,
|
||||||
fractional_part,
|
integer_only,
|
||||||
integer_part,
|
integer_part,
|
||||||
|
fractional_part,
|
||||||
fraction_integer,
|
fraction_integer,
|
||||||
fraction_numerator,
|
fraction_numerator,
|
||||||
fraction_denominator,
|
fraction_denominator,
|
||||||
scientific_significand,
|
scientific_significand,
|
||||||
scientific_exponent
|
scientific_exponent_plus,
|
||||||
|
scientific_exponent_minus
|
||||||
} type = placeholders_type::bad;
|
} type = placeholders_type::bad;
|
||||||
|
|
||||||
bool use_comma_separator = false;
|
bool use_comma_separator = false;
|
||||||
|
bool percentage = false;
|
||||||
|
bool scientific = false;
|
||||||
|
|
||||||
std::size_t num_zeros = 0; // 0
|
std::size_t num_zeros = 0; // 0
|
||||||
std::size_t num_optionals = 0; // #
|
std::size_t num_optionals = 0; // #
|
||||||
|
|
|
@ -93,36 +93,6 @@ std::size_t string_to_size_t(const std::string &s)
|
||||||
// enum serialization
|
// enum serialization
|
||||||
//
|
//
|
||||||
|
|
||||||
// protection::type serialization
|
|
||||||
|
|
||||||
xlnt::protection::type protection_type_from_string(const std::string &type_string)
|
|
||||||
{
|
|
||||||
auto lower = string_lower(type_string);
|
|
||||||
|
|
||||||
if (lower == "inherit") return xlnt::protection::type::inherit;
|
|
||||||
if (is_true(lower)) return xlnt::protection::type::protected_;
|
|
||||||
|
|
||||||
if (!is_false(lower))
|
|
||||||
{
|
|
||||||
throw std::runtime_error("bad enum " + type_string);
|
|
||||||
}
|
|
||||||
|
|
||||||
return xlnt::protection::type::unprotected;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::string protection_type_to_string(xlnt::protection::type type)
|
|
||||||
{
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case xlnt::protection::type::inherit: return "inherit";
|
|
||||||
case xlnt::protection::type::protected_: return "true";
|
|
||||||
case xlnt::protection::type::unprotected: return "false";
|
|
||||||
}
|
|
||||||
|
|
||||||
throw std::runtime_error("bad enum " + std::to_string(static_cast<std::size_t>(type)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// font::underline_style serialization
|
// font::underline_style serialization
|
||||||
|
|
||||||
const std::unordered_map<std::string, xlnt::font::underline_style> &get_string_underline_style_map()
|
const std::unordered_map<std::string, xlnt::font::underline_style> &get_string_underline_style_map()
|
||||||
|
@ -398,10 +368,25 @@ xlnt::protection read_protection(const pugi::xml_node protection_node)
|
||||||
{
|
{
|
||||||
xlnt::protection prot;
|
xlnt::protection prot;
|
||||||
|
|
||||||
prot.set_locked(protection_type_from_string(protection_node.attribute("locked").value()));
|
if (is_true(protection_node.attribute("locked").value()))
|
||||||
prot.set_hidden(protection_type_from_string(protection_node.attribute("hidden").value()));
|
{
|
||||||
|
prot.set_locked(true);
|
||||||
|
}
|
||||||
|
else if (!is_false(protection_node.attribute("locked").value()))
|
||||||
|
{
|
||||||
|
throw std::runtime_error("bad protection value");
|
||||||
|
}
|
||||||
|
|
||||||
return std::move(prot);
|
if (is_true(protection_node.attribute("hidden").value()))
|
||||||
|
{
|
||||||
|
prot.set_hidden(true);
|
||||||
|
}
|
||||||
|
else if (!is_false(protection_node.attribute("hidden").value()))
|
||||||
|
{
|
||||||
|
throw std::runtime_error("bad protection value");
|
||||||
|
}
|
||||||
|
|
||||||
|
return prot;
|
||||||
}
|
}
|
||||||
|
|
||||||
xlnt::alignment read_alignment(const pugi::xml_node alignment_node)
|
xlnt::alignment read_alignment(const pugi::xml_node alignment_node)
|
||||||
|
@ -1030,12 +1015,14 @@ bool write_base_format(const xlnt::base_format &xf, const xlnt::detail::styleshe
|
||||||
|
|
||||||
if (xf.get_alignment().has_vertical())
|
if (xf.get_alignment().has_vertical())
|
||||||
{
|
{
|
||||||
alignment_node.append_attribute("vertical").set_value(vertical_alignment_to_string(xf.get_alignment().get_vertical()).c_str());
|
auto vertical = vertical_alignment_to_string(xf.get_alignment().get_vertical());
|
||||||
|
alignment_node.append_attribute("vertical").set_value(vertical.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xf.get_alignment().has_horizontal())
|
if (xf.get_alignment().has_horizontal())
|
||||||
{
|
{
|
||||||
alignment_node.append_attribute("horizontal").set_value(horizontal_alignment_to_string(xf.get_alignment().get_horizontal()).c_str());
|
auto horizontal = horizontal_alignment_to_string(xf.get_alignment().get_horizontal());
|
||||||
|
alignment_node.append_attribute("horizontal").set_value(horizontal.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xf.get_alignment().get_wrap_text())
|
if (xf.get_alignment().get_wrap_text())
|
||||||
|
@ -1052,9 +1039,8 @@ bool write_base_format(const xlnt::base_format &xf, const xlnt::detail::styleshe
|
||||||
if (xf.protection_applied())
|
if (xf.protection_applied())
|
||||||
{
|
{
|
||||||
auto protection_node = xf_node.append_child("protection");
|
auto protection_node = xf_node.append_child("protection");
|
||||||
|
protection_node.append_attribute("locked").set_value(xf.get_protection().get_locked() ? "1" : "0");
|
||||||
protection_node.append_attribute("locked").set_value(protection_type_to_string(xf.get_protection().get_locked()).c_str());
|
protection_node.append_attribute("hidden").set_value(xf.get_protection().get_hidden() ? "1" : "0");
|
||||||
protection_node.append_attribute("hidden").set_value(protection_type_to_string(xf.get_protection().get_hidden()).c_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -1139,17 +1125,6 @@ bool write_colors(const std::vector<xlnt::color> &colors, pugi::xml_node &colors
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool write_ext_list(pugi::xml_node &ext_list_node)
|
|
||||||
{
|
|
||||||
auto ext_node = ext_list_node.append_child("ext");
|
|
||||||
|
|
||||||
ext_node.append_attribute("uri").set_value("{EB79DEF2-80B8-43e5-95BD-54CBDDF9020C}");
|
|
||||||
ext_node.append_attribute("xmlns:x14").set_value("http://schemas.microsoft.com/office/spreadsheetml/2009/9/main");
|
|
||||||
ext_node.append_child("x14:slicerStyles").append_attribute("defaultSlicerStyle").set_value("SlicerStyleLight1");
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool write_number_formats(const std::vector<xlnt::number_format> &number_formats, pugi::xml_node &number_formats_node)
|
bool write_number_formats(const std::vector<xlnt::number_format> &number_formats, pugi::xml_node &number_formats_node)
|
||||||
{
|
{
|
||||||
number_formats_node.append_attribute("count").set_value(std::to_string(number_formats.size()).c_str());
|
number_formats_node.append_attribute("count").set_value(std::to_string(number_formats.size()).c_str());
|
||||||
|
@ -1239,9 +1214,6 @@ bool style_serializer::write_stylesheet(pugi::xml_document &doc)
|
||||||
write_colors(stylesheet_.colors, colors_node);
|
write_colors(stylesheet_.colors, colors_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ext_list_node = root_node.append_child("extLst");
|
|
||||||
write_ext_list(ext_list_node);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,7 @@ struct stylesheet
|
||||||
}
|
}
|
||||||
|
|
||||||
formats.push_back(f);
|
formats.push_back(f);
|
||||||
format_styles.push_back("");
|
format_styles.push_back("Normal");
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -162,8 +162,11 @@ const protection &base_format::get_protection() const
|
||||||
|
|
||||||
void base_format::set_protection(const xlnt::protection &new_protection)
|
void base_format::set_protection(const xlnt::protection &new_protection)
|
||||||
{
|
{
|
||||||
|
if (!new_protection.get_locked() || new_protection.get_hidden())
|
||||||
|
{
|
||||||
protection_ = new_protection;
|
protection_ = new_protection;
|
||||||
protection_applied(true);
|
protection_applied(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string base_format::to_hash_string() const
|
std::string base_format::to_hash_string() const
|
||||||
|
|
|
@ -44,10 +44,10 @@ const std::unordered_map<std::size_t, std::string> &builtin_formats()
|
||||||
{ 2, "0.00" },
|
{ 2, "0.00" },
|
||||||
{ 3, "#,##0" },
|
{ 3, "#,##0" },
|
||||||
{ 4, "#,##0.00" },
|
{ 4, "#,##0.00" },
|
||||||
{ 5, "\"$\"#,##0_);(\"$\"#,##0)" },
|
{ 5, "#,##0;-#,##0" },
|
||||||
{ 6, "\"$\"#,##0_);[Red](\"$\"#,##0)" },
|
{ 6, "#,##0;[Red]-#,##0" },
|
||||||
{ 7, "\"$\"#,##0.00_);(\"$\"#,##0.00)" },
|
{ 7, "#,##0.00;-#,##0.00" },
|
||||||
{ 8, "\"$\"#,##0.00_);[Red](\"$\"#,##0.00)" },
|
{ 8, "#,##0.00;[Red]-#,##0.00" },
|
||||||
{ 9, "0%" },
|
{ 9, "0%" },
|
||||||
{ 10, "0.00%" },
|
{ 10, "0.00%" },
|
||||||
{ 11, "0.00E+00" },
|
{ 11, "0.00E+00" },
|
||||||
|
|
|
@ -26,41 +26,42 @@
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
protection::protection() : protection(type::unprotected)
|
protection::protection() : protection(true, false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protection::protection(type t) : locked_(t), hidden_(type::unprotected)
|
protection::protection(bool locked, bool hidden)
|
||||||
|
: locked_(locked),
|
||||||
|
hidden_(hidden)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protection::type protection::get_locked() const
|
bool protection::get_locked() const
|
||||||
{
|
{
|
||||||
return locked_;
|
return locked_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void protection::set_locked(type locked_type)
|
void protection::set_locked(bool locked)
|
||||||
{
|
{
|
||||||
locked_ = locked_type;
|
locked_ = locked;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool protection::get_hidden() const
|
||||||
protection::type protection::get_hidden() const
|
|
||||||
{
|
{
|
||||||
return hidden_;
|
return hidden_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void protection::set_hidden(type hidden_type)
|
void protection::set_hidden(bool hidden)
|
||||||
{
|
{
|
||||||
hidden_ = hidden_type;
|
hidden_ = hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string protection::to_hash_string() const
|
std::string protection::to_hash_string() const
|
||||||
{
|
{
|
||||||
std::string hash_string = "protection";
|
std::string hash_string = "protection";
|
||||||
|
|
||||||
hash_string.append(std::to_string(static_cast<std::size_t>(locked_)));
|
hash_string.append(locked_ ? "1" : "0");
|
||||||
hash_string.append(std::to_string(static_cast<std::size_t>(hidden_)));
|
hash_string.append(hidden_ ? "1" : "0");
|
||||||
|
|
||||||
return hash_string;
|
return hash_string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -364,45 +364,154 @@ public:
|
||||||
TS_ASSERT_THROWS(nf.format(1.2, xlnt::calendar::windows_1900), std::runtime_error);
|
TS_ASSERT_THROWS(nf.format(1.2, xlnt::calendar::windows_1900), std::runtime_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_builtin_formats()
|
void format_and_test(const xlnt::number_format &nf, const std::array<std::string, 4> &expect)
|
||||||
{
|
{
|
||||||
TS_ASSERT_EQUALS(xlnt::number_format::text().format("a"), "a");
|
long double positive = 42503.1234;
|
||||||
TS_ASSERT_EQUALS(xlnt::number_format::number().format(1, xlnt::calendar::windows_1900), "1");
|
long double negative = -1 * positive;
|
||||||
TS_ASSERT_EQUALS(xlnt::number_format::number_comma_separated1().format(12345.67, xlnt::calendar::windows_1900), "12,345.67");
|
long double zero = 0;
|
||||||
|
const std::string text = "text";
|
||||||
|
xlnt::calendar calendar = xlnt::calendar::windows_1900;
|
||||||
|
|
||||||
/*
|
TS_ASSERT_EQUALS(nf.format(positive, calendar), expect[0]);
|
||||||
auto datetime = xlnt::datetime(2016, 6, 24, 0, 45, 58);
|
TS_ASSERT_EQUALS(nf.format(negative, calendar), expect[1]);
|
||||||
auto datetime_number = datetime.to_number(xlnt::calendar::windows_1900);
|
TS_ASSERT_EQUALS(nf.format(zero, calendar), expect[2]);
|
||||||
|
TS_ASSERT_EQUALS(nf.format(text), expect[3]);
|
||||||
|
}
|
||||||
|
|
||||||
TS_ASSERT_EQUALS(xlnt::number_format::percentage().format(datetime_number, xlnt::calendar::windows_1900), "1");
|
// General
|
||||||
TS_ASSERT_EQUALS(xlnt::number_format::percentage_00().format(datetime_number, xlnt::calendar::windows_1900), "1");
|
void test_builtin_format_0()
|
||||||
TS_ASSERT_EQUALS(xlnt::number_format::date_yyyymmdd2().format(datetime_number, xlnt::calendar::windows_1900), "1");
|
{
|
||||||
TS_ASSERT_EQUALS(xlnt::number_format::date_yyyymmdd().format(datetime_number, xlnt::calendar::windows_1900), "1");
|
format_and_test(xlnt::number_format::general(), {{"42503.1234", "-42503.1234", "0", "text"}});
|
||||||
TS_ASSERT_EQUALS(xlnt::number_format::date_ddmmyyyy().format(datetime_number, xlnt::calendar::windows_1900), "1");
|
}
|
||||||
TS_ASSERT_EQUALS(xlnt::number_format::date_dmyslash().format(datetime_number, xlnt::calendar::windows_1900), "1");
|
|
||||||
TS_ASSERT_EQUALS(xlnt::number_format::date_dmyminus().format(datetime_number, xlnt::calendar::windows_1900), "1");
|
|
||||||
TS_ASSERT_EQUALS(xlnt::number_format::date_dmminus().format(datetime_number, xlnt::calendar::windows_1900), "1");
|
|
||||||
TS_ASSERT_EQUALS(xlnt::number_format::date_myminus().format(datetime_number, xlnt::calendar::windows_1900), "1");
|
|
||||||
TS_ASSERT_EQUALS(xlnt::number_format::date_xlsx14().format(datetime_number, xlnt::calendar::windows_1900), "1");
|
|
||||||
TS_ASSERT_EQUALS(xlnt::number_format::date_xlsx15().format(datetime_number, xlnt::calendar::windows_1900), "1");
|
|
||||||
TS_ASSERT_EQUALS(xlnt::number_format::date_xlsx16().format(datetime_number, xlnt::calendar::windows_1900), "1");
|
|
||||||
TS_ASSERT_EQUALS(xlnt::number_format::date_xlsx17().format(datetime_number, xlnt::calendar::windows_1900), "1");
|
|
||||||
TS_ASSERT_EQUALS(xlnt::number_format::date_xlsx22().format(datetime_number, xlnt::calendar::windows_1900), "1");
|
|
||||||
TS_ASSERT_EQUALS(xlnt::number_format::date_datetime().format(datetime_number, xlnt::calendar::windows_1900), "1");
|
|
||||||
TS_ASSERT_EQUALS(xlnt::number_format::date_time1().format(datetime_number, xlnt::calendar::windows_1900), "1");
|
|
||||||
TS_ASSERT_EQUALS(xlnt::number_format::date_time2().format(datetime_number, xlnt::calendar::windows_1900), "1");
|
|
||||||
TS_ASSERT_EQUALS(xlnt::number_format::date_time3().format(datetime_number, xlnt::calendar::windows_1900), "1");
|
|
||||||
TS_ASSERT_EQUALS(xlnt::number_format::date_time4().format(datetime_number, xlnt::calendar::windows_1900), "1");
|
|
||||||
TS_ASSERT_EQUALS(xlnt::number_format::date_time5().format(datetime_number, xlnt::calendar::windows_1900), "1");
|
|
||||||
TS_ASSERT_EQUALS(xlnt::number_format::date_time6().format(datetime_number, xlnt::calendar::windows_1900), "1");
|
|
||||||
TS_ASSERT_EQUALS(xlnt::number_format::date_time7().format(datetime_number, xlnt::calendar::windows_1900), "1");
|
|
||||||
TS_ASSERT_EQUALS(xlnt::number_format::date_time8().format(datetime_number, xlnt::calendar::windows_1900), "1");
|
|
||||||
TS_ASSERT_EQUALS(xlnt::number_format::date_timedelta().format(datetime_number, xlnt::calendar::windows_1900), "1");
|
|
||||||
TS_ASSERT_EQUALS(xlnt::number_format::date_yyyymmddslash().format(datetime_number, xlnt::calendar::windows_1900), "1");
|
|
||||||
|
|
||||||
TS_ASSERT_EQUALS(xlnt::number_format::currency_usd_simple().format(1.23, xlnt::calendar::windows_1900), "1");
|
// 0
|
||||||
TS_ASSERT_EQUALS(xlnt::number_format::currency_usd().format(1.23, xlnt::calendar::windows_1900), "1");
|
void test_builtin_format_1()
|
||||||
TS_ASSERT_EQUALS(xlnt::number_format::currency_eur_simple().format(1.23, xlnt::calendar::windows_1900), "1");
|
{
|
||||||
*/
|
format_and_test(xlnt::number_format::number(), {{"42503", "-42503", "0", "text"}});
|
||||||
|
}
|
||||||
|
// 0.00
|
||||||
|
void test_builtin_format_2()
|
||||||
|
{
|
||||||
|
format_and_test(xlnt::number_format::number_00(), {{"42503.12", "-42503.12", "0.00", "text"}});
|
||||||
|
}
|
||||||
|
|
||||||
|
// #,##0
|
||||||
|
void test_builtin_format_3()
|
||||||
|
{
|
||||||
|
format_and_test(xlnt::number_format::from_builtin_id(3), {{"42,503", "-42,503", "0", "text"}});
|
||||||
|
}
|
||||||
|
|
||||||
|
// #,##0.00
|
||||||
|
void test_builtin_format_4()
|
||||||
|
{
|
||||||
|
format_and_test(xlnt::number_format::from_builtin_id(4), {{"42,503.12", "-42,503.12", "0.00", "text"}});
|
||||||
|
}
|
||||||
|
|
||||||
|
// #,##0;-#,##0
|
||||||
|
void test_builtin_format_5()
|
||||||
|
{
|
||||||
|
format_and_test(xlnt::number_format::from_builtin_id(5), {{"42,503", "-42,503", "0", "text"}});
|
||||||
|
}
|
||||||
|
|
||||||
|
// #,##0;[Red]-#,##0
|
||||||
|
void test_builtin_format_6()
|
||||||
|
{
|
||||||
|
format_and_test(xlnt::number_format::from_builtin_id(6), {{"42,503", "-42,503", "0", "text"}});
|
||||||
|
}
|
||||||
|
|
||||||
|
// #,##0.00;-#,##0.00
|
||||||
|
void test_builtin_format_7()
|
||||||
|
{
|
||||||
|
format_and_test(xlnt::number_format::from_builtin_id(7), {{"42,503.12", "-42,503.12", "0.00", "text"}});
|
||||||
|
}
|
||||||
|
|
||||||
|
// #,##0.00;[Red]-#,##0.00
|
||||||
|
void test_builtin_format_8()
|
||||||
|
{
|
||||||
|
format_and_test(xlnt::number_format::from_builtin_id(8), {{"42,503.12", "-42,503.12", "0.00", "text"}});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 0%
|
||||||
|
void test_builtin_format_9()
|
||||||
|
{
|
||||||
|
format_and_test(xlnt::number_format::percentage(), {{"4250312%", "-4250312%", "0%", "text"}});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 0.00%
|
||||||
|
void test_builtin_format_10()
|
||||||
|
{
|
||||||
|
format_and_test(xlnt::number_format::percentage_00(), {{"4250312.34%", "-4250312.34%", "0.00%", "text"}});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 0.00E+00
|
||||||
|
void test_builtin_format_11()
|
||||||
|
{
|
||||||
|
format_and_test(xlnt::number_format::from_builtin_id(11), {{"4.25E+04", "-4.25E+04", "0.00E+00", "text"}});
|
||||||
|
}
|
||||||
|
|
||||||
|
// # ?/?
|
||||||
|
void _test_builtin_format_12()
|
||||||
|
{
|
||||||
|
format_and_test(xlnt::number_format::from_builtin_id(12), {{"42503 1/8", "-42503 1/8", "0", "text"}});
|
||||||
|
}
|
||||||
|
|
||||||
|
// # ??/??
|
||||||
|
void _test_builtin_format_13()
|
||||||
|
{
|
||||||
|
format_and_test(xlnt::number_format::from_builtin_id(13), {{"42503 10/81", "-42503 10/81", "0", "text"}});
|
||||||
|
}
|
||||||
|
|
||||||
|
// mm-dd-yy
|
||||||
|
void _test_builtin_format_14()
|
||||||
|
{
|
||||||
|
format_and_test(xlnt::number_format::from_builtin_id(14), {{"05-13-16", "###########", "01-00-00", "text"}});
|
||||||
|
}
|
||||||
|
|
||||||
|
// d-mmm-yy
|
||||||
|
void _test_builtin_format_15()
|
||||||
|
{
|
||||||
|
format_and_test(xlnt::number_format::from_builtin_id(15), {{"13-May-16", "###########", "0-Jan-00", "text"}});
|
||||||
|
}
|
||||||
|
|
||||||
|
// d-mmm
|
||||||
|
void _test_builtin_format_16()
|
||||||
|
{
|
||||||
|
format_and_test(xlnt::number_format::from_builtin_id(16), {{"13-May", "###########", "0-Jan", "text"}});
|
||||||
|
}
|
||||||
|
|
||||||
|
// mmm-yy
|
||||||
|
void _test_builtin_format_17()
|
||||||
|
{
|
||||||
|
format_and_test(xlnt::number_format::from_builtin_id(17), {{"May-16", "###########", "Jan-00", "text"}});
|
||||||
|
}
|
||||||
|
|
||||||
|
// h:mm AM/PM
|
||||||
|
void _test_builtin_format_18()
|
||||||
|
{
|
||||||
|
format_and_test(xlnt::number_format::from_builtin_id(18), {{"2:57 AM", "###########", "12:00 AM", "text"}});
|
||||||
|
}
|
||||||
|
|
||||||
|
// h:mm:ss AM/PM
|
||||||
|
void _test_builtin_format_19()
|
||||||
|
{
|
||||||
|
format_and_test(xlnt::number_format::from_builtin_id(19), {{"2:57:42 AM", "###########", "12:00:00 AM", "text"}});
|
||||||
|
}
|
||||||
|
|
||||||
|
// h:mm
|
||||||
|
void _test_builtin_format_20()
|
||||||
|
{
|
||||||
|
format_and_test(xlnt::number_format::from_builtin_id(20), {{"2:57", "###########", "0:00", "text"}});
|
||||||
|
}
|
||||||
|
|
||||||
|
// h:mm:ss
|
||||||
|
void _test_builtin_format_21()
|
||||||
|
{
|
||||||
|
format_and_test(xlnt::number_format::from_builtin_id(21), {{"2:57:42", "###########", "0:00:00", "text"}});
|
||||||
|
}
|
||||||
|
|
||||||
|
// m/d/yy h:mm
|
||||||
|
void _test_builtin_format_22()
|
||||||
|
{
|
||||||
|
format_and_test(xlnt::number_format::from_builtin_id(22), {{"5/13/16 2:57", "###########", "1/0/00 0:00", "text"}});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,65 +14,6 @@
|
||||||
class test_stylesheet : public CxxTest::TestSuite
|
class test_stylesheet : public CxxTest::TestSuite
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void test_ctor()
|
|
||||||
{
|
|
||||||
xlnt::workbook wb;
|
|
||||||
xlnt::excel_serializer excel_serializer(wb);
|
|
||||||
xlnt::style_serializer style_serializer(excel_serializer.get_stylesheet());
|
|
||||||
xlnt::zip_file archive;
|
|
||||||
pugi::xml_document stylesheet_doc;
|
|
||||||
style_serializer.write_stylesheet(stylesheet_doc);
|
|
||||||
std::ostringstream ss;
|
|
||||||
stylesheet_doc.save(ss);
|
|
||||||
auto stylesheet_xml = ss.str();
|
|
||||||
|
|
||||||
const std::string expected =
|
|
||||||
"<styleSheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" xmlns:x14ac=\"http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac\" mc:Ignorable=\"x14ac\">"
|
|
||||||
" <fonts count=\"1\">"
|
|
||||||
" <font>"
|
|
||||||
" <sz val=\"12\"/>"
|
|
||||||
" <color theme=\"1\"/>"
|
|
||||||
" <name val=\"Calibri\"/>"
|
|
||||||
" <family val=\"2\"/>"
|
|
||||||
" <scheme val=\"minor\"/>"
|
|
||||||
" </font>"
|
|
||||||
" </fonts>"
|
|
||||||
" <fills count=\"1\">"
|
|
||||||
" <fill>"
|
|
||||||
" <patternFill patternType=\"none\"/>"
|
|
||||||
" </fill>"
|
|
||||||
" </fills>"
|
|
||||||
" <borders count=\"1\">"
|
|
||||||
" <border>"
|
|
||||||
" <left/>"
|
|
||||||
" <right/>"
|
|
||||||
" <top/>"
|
|
||||||
" <bottom/>"
|
|
||||||
" <diagonal/>"
|
|
||||||
" </border>"
|
|
||||||
" </borders>"
|
|
||||||
" <cellStyleXfs count=\"1\">"
|
|
||||||
" <xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\"/>"
|
|
||||||
" </cellStyleXfs>"
|
|
||||||
" <cellXfs count=\"1\">"
|
|
||||||
" <xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\"/>"
|
|
||||||
" </cellXfs>"
|
|
||||||
" <cellStyles count=\"1\">"
|
|
||||||
" <cellStyle name=\"Normal\" xfId=\"0\" builtinId=\"0\"/>"
|
|
||||||
" </cellStyles>"
|
|
||||||
" <dxfs count=\"0\"/>"
|
|
||||||
" <tableStyles count=\"0\" defaultTableStyle=\"TableStyleMedium9\" defaultPivotStyle=\"PivotStyleMedium7\"/>"
|
|
||||||
" <extLst>"
|
|
||||||
" <ext xmlns:x14=\"http://schemas.microsoft.com/office/spreadsheetml/2009/9/main\" uri=\"{EB79DEF2-80B8-43e5-95BD-54CBDDF9020C}\">"
|
|
||||||
" <x14:slicerStyles defaultSlicerStyle=\"SlicerStyleLight1\"/>"
|
|
||||||
" </ext>"
|
|
||||||
" </extLst>"
|
|
||||||
"</styleSheet>";
|
|
||||||
|
|
||||||
TS_ASSERT(Helper::compare_xml(expected, stylesheet_xml));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void test_from_simple()
|
void test_from_simple()
|
||||||
{
|
{
|
||||||
pugi::xml_document doc;
|
pugi::xml_document doc;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <detail/style_serializer.hpp>
|
#include <detail/style_serializer.hpp>
|
||||||
#include <detail/stylesheet.hpp>
|
#include <detail/stylesheet.hpp>
|
||||||
#include <detail/workbook_impl.hpp>
|
#include <detail/workbook_impl.hpp>
|
||||||
|
#include <helpers/path_helper.hpp>
|
||||||
|
|
||||||
class test_style_writer : public CxxTest::TestSuite
|
class test_style_writer : public CxxTest::TestSuite
|
||||||
{
|
{
|
||||||
|
@ -27,262 +28,80 @@ public:
|
||||||
auto diff = Helper::compare_xml(expected_doc.child("numFmts"), observed.child("styleSheet").child("numFmts"));
|
auto diff = Helper::compare_xml(expected_doc.child("numFmts"), observed.child("styleSheet").child("numFmts"));
|
||||||
TS_ASSERT(diff);
|
TS_ASSERT(diff);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
class TestStyleWriter(object):
|
|
||||||
|
|
||||||
void setup(self):
|
void test_simple_styles()
|
||||||
self.workbook = Workbook()
|
{
|
||||||
self.worksheet = self.workbook.create_sheet()
|
xlnt::workbook wb;
|
||||||
|
wb.set_guess_types(true);
|
||||||
|
auto ws = wb.get_active_sheet();
|
||||||
|
ws.get_cell("A1").set_value("12.34%");
|
||||||
|
auto now = xlnt::date::today();
|
||||||
|
ws.get_cell("A2").set_value(now);
|
||||||
|
ws.get_cell("A3").set_value("This is a test");
|
||||||
|
ws.get_cell("A4").set_value("31.31415");
|
||||||
|
ws.get_cell("A5");
|
||||||
|
|
||||||
void _test_no_style(self):
|
ws.get_cell("D9").set_number_format(xlnt::number_format::number_00());
|
||||||
w = StyleWriter(self.workbook)
|
xlnt::protection locked(true, false);
|
||||||
assert len(w.wb._cell_styles) == 1 # there is always the empty (defaul) style
|
ws.get_cell("D9").set_protection(locked);
|
||||||
|
xlnt::protection hidden(true, true);
|
||||||
|
ws.get_cell("E1").set_protection(hidden);
|
||||||
|
|
||||||
void _test_nb_style(self):
|
xlnt::excel_serializer e(wb);
|
||||||
for i in range(1, 6):
|
xlnt::style_serializer serializer(e.get_stylesheet());
|
||||||
cell = self.worksheet.cell(row=1, column=i)
|
pugi::xml_document xml;
|
||||||
cell.font = Font(size=i)
|
serializer.write_stylesheet(xml);
|
||||||
_ = cell.style_id
|
|
||||||
w = StyleWriter(self.workbook)
|
|
||||||
assert len(w.wb._cell_styles) == 6 # 5 + the default
|
|
||||||
|
|
||||||
cell = self.worksheet.cell('A10')
|
TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory("/writer/expected/simple-styles.xml"), xml));
|
||||||
cell.border=Border(top=Side(border_style=borders.BORDER_THIN))
|
}
|
||||||
_ = cell.style_id
|
|
||||||
w = StyleWriter(self.workbook)
|
|
||||||
assert len(w.wb._cell_styles) == 7
|
|
||||||
|
|
||||||
|
void test_empty_workbook()
|
||||||
void _test_default_xfs(self):
|
{
|
||||||
w = StyleWriter(self.workbook)
|
xlnt::workbook wb;
|
||||||
fonts = nft = borders = fills = DummyElement()
|
xlnt::excel_serializer e(wb);
|
||||||
w._write_cell_styles()
|
xlnt::style_serializer serializer(e.get_stylesheet());
|
||||||
xml = tostring(w._root)
|
auto expected =
|
||||||
expected = """
|
"<styleSheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" xmlns:x14ac=\"http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac\" mc:Ignorable=\"x14ac\">"
|
||||||
<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
|
" <fonts count=\"1\">"
|
||||||
<cellXfs count="1">
|
" <font>"
|
||||||
<xf borderId="0" fillId="0" fontId="0" numFmtId="0" xfId="0"/>
|
" <sz val=\"12\"/>"
|
||||||
</cellXfs>
|
" <color theme=\"1\"/>"
|
||||||
</styleSheet>
|
" <name val=\"Calibri\"/>"
|
||||||
"""
|
" <family val=\"2\"/>"
|
||||||
diff = compare_xml(xml, expected)
|
" <scheme val=\"minor\"/>"
|
||||||
assert diff is None, diff
|
" </font>"
|
||||||
|
" </fonts>"
|
||||||
|
" <fills count=\"2\">"
|
||||||
void _test_xfs_number_format(self):
|
" <fill>"
|
||||||
for idx, nf in enumerate(["0.0%", "0.00%", "0.000%"], 1):
|
" <patternFill patternType=\"none\"/>"
|
||||||
cell = self.worksheet.cell(row=idx, column=1)
|
" </fill>"
|
||||||
cell.number_format = nf
|
" <fill>"
|
||||||
_ = cell.style_id # add to workbook styles
|
" <patternFill patternType=\"gray125\"/>"
|
||||||
w = StyleWriter(self.workbook)
|
" </fill>"
|
||||||
w._write_cell_styles()
|
" </fills>"
|
||||||
|
" <borders count=\"1\">"
|
||||||
expected = """
|
" <border>"
|
||||||
<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
|
" <left/>"
|
||||||
<cellXfs count="4">
|
" <right/>"
|
||||||
<xf borderId="0" fillId="0" fontId="0" numFmtId="0" xfId="0"/>
|
" <top/>"
|
||||||
<xf borderId="0" fillId="0" fontId="0" numFmtId="164" xfId="0"/>
|
" <bottom/>"
|
||||||
<xf borderId="0" fillId="0" fontId="0" numFmtId="10" xfId="0"/>
|
" <diagonal/>"
|
||||||
<xf borderId="0" fillId="0" fontId="0" numFmtId="165" xfId="0"/>
|
" </border>"
|
||||||
</cellXfs>
|
" </borders>"
|
||||||
</styleSheet>
|
" <cellStyleXfs count=\"1\">"
|
||||||
"""
|
" <xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\"/>"
|
||||||
|
" </cellStyleXfs>"
|
||||||
xml = tostring(w._root)
|
" <cellXfs count=\"1\">"
|
||||||
diff = compare_xml(xml, expected)
|
" <xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\"/>"
|
||||||
assert diff is None, diff
|
" </cellXfs>"
|
||||||
|
" <cellStyles count=\"1\">"
|
||||||
|
" <cellStyle name=\"Normal\" xfId=\"0\" builtinId=\"0\"/>"
|
||||||
void _test_xfs_fonts(self):
|
" </cellStyles>"
|
||||||
cell = self.worksheet.cell('A1')
|
" <dxfs count=\"0\"/>"
|
||||||
cell.font = Font(size=12, bold=True)
|
" <tableStyles count=\"0\" defaultTableStyle=\"TableStyleMedium9\" defaultPivotStyle=\"PivotStyleMedium7\"/>"
|
||||||
_ = cell.style_id # update workbook styles
|
"</styleSheet>";
|
||||||
w = StyleWriter(self.workbook)
|
pugi::xml_document xml;
|
||||||
|
serializer.write_stylesheet(xml);
|
||||||
w._write_cell_styles()
|
TS_ASSERT(Helper::compare_xml(expected, xml));
|
||||||
xml = tostring(w._root)
|
}
|
||||||
|
|
||||||
expected = """
|
|
||||||
<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
|
|
||||||
<cellXfs count="2">
|
|
||||||
<xf borderId="0" fillId="0" fontId="0" numFmtId="0" xfId="0"/>
|
|
||||||
<xf borderId="0" fillId="0" fontId="1" numFmtId="0" xfId="0"/>
|
|
||||||
</cellXfs>
|
|
||||||
</styleSheet>
|
|
||||||
"""
|
|
||||||
diff = compare_xml(xml, expected)
|
|
||||||
assert diff is None, diff
|
|
||||||
|
|
||||||
|
|
||||||
void _test_xfs_fills(self):
|
|
||||||
cell = self.worksheet.cell('A1')
|
|
||||||
cell.fill = fill=PatternFill(fill_type='solid',
|
|
||||||
start_color=Color(colors.DARKYELLOW))
|
|
||||||
_ = cell.style_id # update workbook styles
|
|
||||||
w = StyleWriter(self.workbook)
|
|
||||||
w._write_cell_styles()
|
|
||||||
|
|
||||||
xml = tostring(w._root)
|
|
||||||
expected = """
|
|
||||||
<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
|
|
||||||
<cellXfs count="2">
|
|
||||||
<xf borderId="0" fillId="0" fontId="0" numFmtId="0" xfId="0"/>
|
|
||||||
<xf borderId="0" fillId="2" fontId="0" numFmtId="0" xfId="0"/>
|
|
||||||
</cellXfs>
|
|
||||||
</styleSheet>
|
|
||||||
"""
|
|
||||||
diff = compare_xml(xml, expected)
|
|
||||||
assert diff is None, diff
|
|
||||||
|
|
||||||
|
|
||||||
void _test_xfs_borders(self):
|
|
||||||
cell = self.worksheet.cell('A1')
|
|
||||||
cell.border=Border(top=Side(border_style=borders.BORDER_THIN,
|
|
||||||
color=Color(colors.DARKYELLOW)))
|
|
||||||
_ = cell.style_id # update workbook styles
|
|
||||||
|
|
||||||
w = StyleWriter(self.workbook)
|
|
||||||
w._write_cell_styles()
|
|
||||||
|
|
||||||
xml = tostring(w._root)
|
|
||||||
expected = """
|
|
||||||
<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
|
|
||||||
<cellXfs count="2">
|
|
||||||
<xf borderId="0" fillId="0" fontId="0" numFmtId="0" xfId="0"/>
|
|
||||||
<xf borderId="1" fillId="0" fontId="0" numFmtId="0" xfId="0"/>
|
|
||||||
</cellXfs>
|
|
||||||
</styleSheet>
|
|
||||||
"""
|
|
||||||
diff = compare_xml(xml, expected)
|
|
||||||
assert diff is None, diff
|
|
||||||
|
|
||||||
|
|
||||||
void _test_protection(self):
|
|
||||||
cell = self.worksheet.cell('A1')
|
|
||||||
cell.protection = Protection(locked=True, hidden=True)
|
|
||||||
_ = cell.style_id
|
|
||||||
|
|
||||||
w = StyleWriter(self.workbook)
|
|
||||||
w._write_cell_styles()
|
|
||||||
xml = tostring(w._root)
|
|
||||||
expected = """
|
|
||||||
<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
|
|
||||||
<cellXfs count="2">
|
|
||||||
<xf borderId="0" fillId="0" fontId="0" numFmtId="0" xfId="0"/>
|
|
||||||
<xf applyProtection="1" borderId="0" fillId="0" fontId="0" numFmtId="0" xfId="0">
|
|
||||||
<protection hidden="1" locked="1"/>
|
|
||||||
</xf>
|
|
||||||
</cellXfs>
|
|
||||||
</styleSheet>
|
|
||||||
"""
|
|
||||||
diff = compare_xml(xml, expected)
|
|
||||||
assert diff is None, diff
|
|
||||||
|
|
||||||
|
|
||||||
void _test_named_styles(self):
|
|
||||||
writer = StyleWriter(self.workbook)
|
|
||||||
writer._write_named_styles()
|
|
||||||
xml = tostring(writer._root)
|
|
||||||
expected = """
|
|
||||||
<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
|
|
||||||
<cellStyleXfs count="1">
|
|
||||||
<xf borderId="0" fillId="0" fontId="0" numFmtId="0"></xf>
|
|
||||||
</cellStyleXfs>
|
|
||||||
</styleSheet>
|
|
||||||
"""
|
|
||||||
diff = compare_xml(xml, expected)
|
|
||||||
assert diff is None, diff
|
|
||||||
|
|
||||||
|
|
||||||
void _test_style_names(self):
|
|
||||||
writer = StyleWriter(self.workbook)
|
|
||||||
writer._write_style_names()
|
|
||||||
xml = tostring(writer._root)
|
|
||||||
expected = """
|
|
||||||
<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
|
|
||||||
<cellStyles count="1">
|
|
||||||
<cellStyle name="Normal" xfId="0" builtinId="0" hidden="0"/>
|
|
||||||
</cellStyles>
|
|
||||||
</styleSheet>
|
|
||||||
"""
|
|
||||||
diff = compare_xml(xml, expected)
|
|
||||||
assert diff is None, diff
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void _test_simple_styles(datadir):
|
|
||||||
wb = Workbook(guess_types=True)
|
|
||||||
ws = wb.active
|
|
||||||
now = datetime.datetime.now()
|
|
||||||
for idx, v in enumerate(['12.34%', now, 'This is a test', '31.31415', None], 1):
|
|
||||||
ws.append([v])
|
|
||||||
_ = ws.cell(column=1, row=idx).style_id
|
|
||||||
|
|
||||||
# set explicit formats
|
|
||||||
ws['D9'].number_format = numbers.FORMAT_NUMBER_00
|
|
||||||
ws['D9'].protection = Protection(locked=True)
|
|
||||||
ws['D9'].style_id
|
|
||||||
ws['E1'].protection = Protection(hidden=True)
|
|
||||||
ws['E1'].style_id
|
|
||||||
|
|
||||||
assert len(wb._cell_styles) == 5
|
|
||||||
writer = StyleWriter(wb)
|
|
||||||
|
|
||||||
datadir.chdir()
|
|
||||||
with open('simple-styles.xml') as reference_file:
|
|
||||||
expected = reference_file.read()
|
|
||||||
xml = writer.write_table()
|
|
||||||
diff = compare_xml(xml, expected)
|
|
||||||
assert diff is None, diff
|
|
||||||
|
|
||||||
|
|
||||||
void _test_empty_workbook():
|
|
||||||
wb = Workbook()
|
|
||||||
writer = StyleWriter(wb)
|
|
||||||
expected = """
|
|
||||||
<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
|
|
||||||
<numFmts count="0"/>
|
|
||||||
<fonts count="1">
|
|
||||||
<font>
|
|
||||||
<name val="Calibri"/>
|
|
||||||
<family val="2"/>
|
|
||||||
<color theme="1"/>
|
|
||||||
<sz val="11"/>
|
|
||||||
<scheme val="minor"/>
|
|
||||||
</font>
|
|
||||||
</fonts>
|
|
||||||
<fills count="2">
|
|
||||||
<fill>
|
|
||||||
<patternFill />
|
|
||||||
</fill>
|
|
||||||
<fill>
|
|
||||||
<patternFill patternType="gray125"/>
|
|
||||||
</fill>
|
|
||||||
</fills>
|
|
||||||
<borders count="1">
|
|
||||||
<border>
|
|
||||||
<left/>
|
|
||||||
<right/>
|
|
||||||
<top/>
|
|
||||||
<bottom/>
|
|
||||||
<diagonal/>
|
|
||||||
</border>
|
|
||||||
</borders>
|
|
||||||
<cellStyleXfs count="1">
|
|
||||||
<xf borderId="0" fillId="0" fontId="0" numFmtId="0"/>
|
|
||||||
</cellStyleXfs>
|
|
||||||
<cellXfs count="1">
|
|
||||||
<xf borderId="0" fillId="0" fontId="0" numFmtId="0" xfId="0"/>
|
|
||||||
</cellXfs>
|
|
||||||
<cellStyles count="1">
|
|
||||||
<cellStyle builtinId="0" name="Normal" xfId="0" hidden="0"/>
|
|
||||||
</cellStyles>
|
|
||||||
<dxfs count="0"/>
|
|
||||||
<tableStyles count="0" defaultPivotStyle="PivotStyleLight16" defaultTableStyle="TableStyleMedium9"/>
|
|
||||||
</styleSheet>
|
|
||||||
"""
|
|
||||||
xml = writer.write_table()
|
|
||||||
diff = compare_xml(xml, expected)
|
|
||||||
assert diff is None, diff
|
|
||||||
*/
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -91,6 +91,11 @@ workbook::workbook() : d_(new detail::workbook_impl())
|
||||||
add_format(format());
|
add_format(format());
|
||||||
create_style("Normal");
|
create_style("Normal");
|
||||||
d_->stylesheet_.format_styles.front() = "Normal";
|
d_->stylesheet_.format_styles.front() = "Normal";
|
||||||
|
|
||||||
|
xlnt::fill gray125;
|
||||||
|
gray125.set_type(xlnt::fill::type::pattern);
|
||||||
|
gray125.set_pattern_type(xlnt::fill::pattern_type::gray125);
|
||||||
|
d_->stylesheet_.fills.push_back(gray125);
|
||||||
}
|
}
|
||||||
|
|
||||||
workbook::workbook(encoding e) : workbook()
|
workbook::workbook(encoding e) : workbook()
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0" ?>
|
||||||
<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
|
<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x14ac" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac">
|
||||||
<numFmts count="1">
|
<numFmts count="1">
|
||||||
<numFmt formatCode="yyyy-mm-dd" numFmtId="165"/>
|
<numFmt numFmtId="164" formatCode="yyyy-mm-dd"/>
|
||||||
</numFmts>
|
</numFmts>
|
||||||
<fonts count="1">
|
<fonts count="1">
|
||||||
<font>
|
<font>
|
||||||
<sz val="11"/>
|
<sz val="12" />
|
||||||
<color theme="1"/>
|
<color theme="1" />
|
||||||
<name val="Calibri"/>
|
<name val="Calibri" />
|
||||||
<family val="2"/>
|
<family val="2" />
|
||||||
<scheme val="minor"/>
|
<scheme val="minor" />
|
||||||
</font>
|
</font>
|
||||||
</fonts>
|
</fonts>
|
||||||
<fills count="2">
|
<fills count="2">
|
||||||
|
@ -30,22 +30,20 @@
|
||||||
</border>
|
</border>
|
||||||
</borders>
|
</borders>
|
||||||
<cellStyleXfs count="1">
|
<cellStyleXfs count="1">
|
||||||
<xf borderId="0" fillId="0" fontId="0" numFmtId="0"/>
|
<xf numFmtId="0" fontId="0" fillId="0" borderId="0"/>
|
||||||
</cellStyleXfs>
|
</cellStyleXfs>
|
||||||
<cellXfs count="6">
|
<cellXfs count="5">
|
||||||
<xf borderId="0" fillId="0" fontId="0" numFmtId="0" xfId="0"/>
|
<xf borderId="0" fillId="0" fontId="0" numFmtId="0" xfId="0"/>
|
||||||
<xf applyNumberFormat="1" borderId="0" fillId="0" fontId="0" numFmtId="9" xfId="0"/>
|
<xf borderId="0" fillId="0" fontId="0" numFmtId="9" xfId="0"/>
|
||||||
<xf applyNumberFormat="1" borderId="0" fillId="0" fontId="0" numFmtId="165" xfId="0"/>
|
<xf borderId="0" fillId="0" fontId="0" numFmtId="164" xfId="0"/>
|
||||||
<xf applyNumberFormat="1" applyProtection="1" borderId="0" fillId="0" fontId="0" numFmtId="2" xfId="0">
|
<xf borderId="0" fillId="0" fontId="0" numFmtId="2" xfId="0"/>
|
||||||
<protection locked="0"/>
|
|
||||||
</xf>
|
|
||||||
<xf applyProtection="1" borderId="0" fillId="0" fontId="0" numFmtId="0" xfId="0">
|
<xf applyProtection="1" borderId="0" fillId="0" fontId="0" numFmtId="0" xfId="0">
|
||||||
<protection hidden="0"/>
|
<protection hidden="1" locked="1"/>
|
||||||
</xf>
|
</xf>
|
||||||
</cellXfs>
|
</cellXfs>
|
||||||
<cellStyles count="1">
|
<cellStyles count="1">
|
||||||
<cellStyle builtinId="0" name="Normal" xfId="0"/>
|
<cellStyle name="Normal" xfId="0" builtinId="0"/>
|
||||||
</cellStyles>
|
</cellStyles>
|
||||||
<dxfs count="0"/>
|
<dxfs count="0" />
|
||||||
<tableStyles count="0" defaultPivotStyle="PivotStyleLight16" defaultTableStyle="TableStyleMedium9"/>
|
<tableStyles count="0" defaultTableStyle="TableStyleMedium9" defaultPivotStyle="PivotStyleLight16"/>
|
||||||
</styleSheet>
|
</styleSheet>
|
Loading…
Reference in New Issue
Block a user