continue implementing styles

pull/16/head
Thomas Fussell 2015-10-18 15:30:46 -04:00
parent d1ea08fd13
commit 2f07e0ae62
27 changed files with 934 additions and 501 deletions

View File

@ -32,6 +32,8 @@
namespace xlnt {
enum class calendar;
class cell_reference;
class comment;
class relationship;
@ -107,28 +109,22 @@ public:
bool has_hyperlink() const;
// style
bool has_style() const;
style &get_style();
const style &get_style() const;
void set_style(const style &s);
// style shortcuts
std::string get_number_format();
std::string get_number_format() const;
void set_number_format(const std::string &format_code, int index = -1);
font &get_font();
std::size_t get_style_id() const;
const number_format &get_number_format() const;
void set_number_format(const number_format &format);
const font &get_font() const;
fill &get_fill();
void set_font(const font &font_);
const fill &get_fill() const;
border &get_border();
void set_fill(const fill &fill_);
const border &get_border() const;
alignment &get_alignment();
void set_border(const border &border_);
const alignment &get_alignment() const;
protection &get_protection();
void set_alignment(const alignment &alignment_);
const protection &get_protection() const;
bool pivot_button();
void set_protection(const protection &protection_);
void set_pivot_button(bool b);
bool pivot_button() const;
bool quote_prefix();
void set_quote_prefix(bool b);
bool quote_prefix() const;
// comment
@ -168,6 +164,8 @@ public:
worksheet get_parent();
const worksheet get_parent() const;
calendar get_base_date() const;
// operators
cell &operator=(const cell &rhs);
@ -178,8 +176,10 @@ public:
friend bool operator<(cell left, cell right);
private:
void set_value_guess_type(const std::string &s);
friend class worksheet;
friend struct detail::cell_impl;
friend class style;
cell(detail::cell_impl *d);
detail::cell_impl *d_;
};

View File

@ -152,6 +152,8 @@ struct datetime
/// </summary>
struct timedelta
{
static timedelta from_number(long double number);
timedelta(int days_, int hours_, int minutes_ = 0, int seconds_ = 0, int microseconds_ = 0)
: days(days_),
hours(hours_),

View File

@ -31,5 +31,6 @@ namespace xlnt {
class workbook;
xlnt::workbook load_workbook(const std::vector<std::uint8_t> &bytes);
xlnt::workbook load_workbook(const std::string &filename);
} // namespace xlnt

View File

@ -64,6 +64,8 @@ public:
&& indent_ == other.indent_;
}
std::size_t hash() const { return 0; }
private:
horizontal_alignment horizontal_ = horizontal_alignment::general;
vertical_alignment vertical_ = vertical_alignment::bottom;

View File

@ -23,6 +23,8 @@
// @author: see AUTHORS file
#pragma once
#include <cstddef>
#include <xlnt/styles/color.hpp>
namespace xlnt {
@ -103,6 +105,8 @@ public:
&& diagonal_up == other.diagonal_up
&& diagonal_down == other.diagonal_down;
}
std::size_t hash() const { return 0; }
};
} // namespace xlnt

View File

@ -60,10 +60,12 @@ public:
color start_color = color::white;
color end_color = color::black;
bool operator==(const fill &other) const
virtual bool operator==(const fill &other) const
{
return type_ == other.type_;
}
virtual std::size_t hash() const { return 0; }
};
class pattern_fill : public fill
@ -72,6 +74,8 @@ public:
void set_pattern_type(const std::string &type) { type_ = type; }
void set_foreground_color(const std::string &hex) { foreground_color_ = hex; }
std::size_t hash() const override { return 0; }
private:
std::string type_;
std::string foreground_color_;

View File

@ -28,6 +28,8 @@
#include <xlnt/styles/color.hpp>
namespace xlnt {
class style;
class font
{
@ -56,7 +58,15 @@ public:
&& color_ == other.color_;
}
int get_size() const { return size_; }
std::string get_name() const { return name_; }
bool is_bold() const { return bole_; }
std::size_t hash() const { return 0; }
private:
friend class style;
std::string name_ = "Calibri";
int size_ = 11;
bool bold_ = false;

View File

@ -86,55 +86,27 @@ public:
static std::string builtin_format_code(int index);
static format lookup_format(int code);
static bool is_date_format(const std::string &format);
static bool is_builtin(const std::string &format);
number_format() : format_code_(format::general), format_index_(0) {}
number_format(format code) : format_code_(code), format_index_(reversed_builtin_formats().at(format_strings().at(code))) {}
number_format();
number_format(format code);
number_format(const std::string &code);
format get_format_code() const { return format_code_; }
format get_format_code() const;
void set_format_code(format format_code, int index = -1)
{
format_code_ = format_code;
if(format_code_ != format::unknown)
{
set_format_code_string(format_strings().at(format_code), index);
}
}
void set_format_code(format format_code);
void set_format_code_string(const std::string &format_code, int index)
{
custom_format_code_ = format_code;
format_index_ = index;
const auto &reversed = reversed_builtin_formats();
auto match = reversed.find(format_code);
format_code_ = format::unknown;
if(match != reversed.end())
{
format_index_ = match->second;
for(const auto &p : format_strings())
{
if(p.second == format_code)
{
format_code_ = p.first;
break;
}
}
}
}
std::string get_format_code_string() const;
void set_format_string(const std::string &format_code);
std::string get_format_string() const;
int get_format_index() const { return format_index_; }
std::size_t hash() const;
private:
std::string custom_format_code_ = "";
format format_code_ = format::general;
int format_index_ = 0;
format format_code_;
int format_index_;
std::string format_string_;
};
} // namespace xlnt

View File

@ -23,6 +23,8 @@
// @author: see AUTHORS file
#pragma once
#include <cstddef>
namespace xlnt {
class protection
@ -48,6 +50,8 @@ public:
return locked_ == other.locked_ && hidden_ == other.hidden_;
}
std::size_t hash() const { return 0; }
private:
type locked_;
type hidden_;

View File

@ -23,64 +23,55 @@
// @author: see AUTHORS file
#pragma once
#include "font.hpp"
#include "fill.hpp"
#include "borders.hpp"
#include "alignment.hpp"
#include "color.hpp"
#include "number_format.hpp"
#include "protection.hpp"
namespace xlnt {
namespace detail {
struct cell_impl;
} // namespace detail
class alignment;
class border;
class font;
class fill;
class number_format;
class protection;
class cell;
class style
{
public:
style(bool is_static = false) : static_(is_static) {}
const style default_style();
style();
style(const style &rhs);
style &operator=(const style &rhs);
style copy() const;
font &get_font();
std::size_t hash() const;
const font &get_font() const;
void set_font(font font);
fill &get_fill();
const fill &get_fill() const;
void set_fill(fill &fill);
border &get_border();
const border &get_border() const;
void set_border(border borders);
alignment &get_alignment();
const alignment get_alignment() const;
void set_alignment(alignment alignment);
number_format &get_number_format() { return number_format_; }
const number_format &get_number_format() const { return number_format_; }
void set_number_format(number_format number_format);
protection &get_protection();
const alignment &get_alignment() const;
const number_format &get_number_format() const;
const protection &get_protection() const;
void set_protection(protection protection);
bool pivot_button();
void set_pivot_button(bool pivot);
bool quote_prefix();
void set_quote_prefix(bool quote);
bool pivot_button() const;
bool quote_prefix() const;
private:
bool static_ = false;
font font_;
fill fill_;
border border_;
alignment alignment_;
number_format number_format_;
protection protection_;
bool pivot_button_;
bool quote_prefix_;
cell get_parent();
const cell get_parent() const;
detail::cell_impl *parent_;
std::size_t font_id_;
std::size_t fill_id_;
std::size_t border_id_;
std::size_t alignment_id_;
std::size_t number_format_id_;
std::size_t protection_id_;
std::size_t style_id_;
};
} // namespace xlnt

View File

@ -41,11 +41,13 @@ class drawing;
class fill;
class font;
class named_range;
class number_format;
class pattern_fill;
class protection;
class range;
class range_reference;
class relationship;
class style;
class worksheet;
class zip_file;
@ -206,11 +208,36 @@ public:
void add_color(color c);
void add_number_format(const std::string &format);
const std::unordered_map<std::size_t, alignment> &get_alignments() const;
const std::unordered_map<std::size_t, border> &get_borders() const;
const std::unordered_map<std::size_t, fill> &get_fills() const;
const std::unordered_map<std::size_t, font> &get_fonts() const;
const std::unordered_map<std::size_t, number_format> &get_number_formats() const;
const std::unordered_map<std::size_t, protection> &get_protections() const;
const number_format &get_number_format(std::size_t style_id) const;
std::size_t set_number_format(const number_format &format, std::size_t style_id);
const font &get_font(std::size_t style_id) const;
std::size_t set_font(const font &font_, std::size_t style_id);
const fill &get_fill(std::size_t style_id) const;
std::size_t set_fill(const fill &fill_, std::size_t style_id);
const border &get_border(std::size_t style_id) const;
std::size_t set_border(const border &border_, std::size_t style_id);
const alignment &get_alignment(std::size_t style_id) const;
std::size_t set_alignment(const alignment &alignment_, std::size_t style_id);
const protection &get_protection(std::size_t style_id) const;
std::size_t set_protection(const protection &protection_, std::size_t style_id);
bool get_pivot_button(std::size_t style_id) const;
bool get_quote_prefix(std::size_t style_id) const;
void set_code_name(const std::string &code_name);
bool has_loaded_theme();
std::string get_loaded_theme();
style get_style(std::size_t style_id);
std::size_t add_style(style style_);
private:
friend class worksheet;
std::shared_ptr<detail::workbook_impl> d_;

View File

@ -39,10 +39,8 @@ public:
style_writer(workbook &wb);
style_writer(const style_writer &);
style_writer &operator=(const style_writer &);
std::unordered_map<std::size_t, std::string> get_style_by_hash() const;
std::string write_table() const;
std::vector<style> get_styles() const;
std::string write_table() const;
std::string write_number_formats();
private:
@ -56,7 +54,6 @@ private:
void write_dxfs();
void write_table_styles();
std::vector<style> style_list_;
workbook &wb_;
};

View File

@ -6,12 +6,12 @@
#include <xlnt/cell/cell_reference.hpp>
#include <xlnt/cell/comment.hpp>
#include <xlnt/common/datetime.hpp>
#include <xlnt/common/relationship.hpp>
#include <xlnt/worksheet/worksheet.hpp>
#include <xlnt/common/exceptions.hpp>
#include <xlnt/common/relationship.hpp>
#include <xlnt/workbook/workbook.hpp>
#include <xlnt/workbook/document_properties.hpp>
#include <xlnt/common/exceptions.hpp>
#include <xlnt/worksheet/worksheet.hpp>
#include <xlnt/styles/color.hpp>
#include "detail/cell_impl.hpp"
#include "detail/comment_impl.hpp"
@ -87,6 +87,36 @@ std::vector<std::string> split_string(const std::string &string, char delim)
return split;
}
std::vector<std::string> split_string_any(const std::string &string, const std::string &delims)
{
std::vector<std::string> split;
std::string::size_type previous_index = 0;
auto separator_index = string.find_first_of(delims);
while(separator_index != std::string::npos)
{
auto part = string.substr(previous_index, separator_index - previous_index);
if(!part.empty())
{
split.push_back(part);
}
previous_index = separator_index + 1;
separator_index = string.find_first_of(delims, previous_index);
}
split.push_back(string.substr(previous_index));
return split;
}
bool is_date_format(const std::string &format_string)
{
auto not_in = format_string.find_first_not_of("/-:, mMyYdDhHsS");
return not_in == std::string::npos;
}
bool is_valid_color(const std::string &color)
{
static const std::vector<std::string> colors = { "Black", "Green"
@ -288,14 +318,180 @@ format_sections parse_format_sections(const std::string &combined)
return result;
}
std::string format_section(long double number, const section &format)
const std::vector<std::string> MonthNames =
{
if(number == static_cast<long long int>(number))
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
};
std::string format_section(long double number, const section &format, xlnt::calendar base_date)
{
const std::string unquoted = "$+(:^'{<=-/)!&~}> ";
std::string result;
if(is_date_format(format.value))
{
return std::to_string(static_cast<long long int>(number));
const std::string date_unquoted = ",-/: ";
const std::vector<std::string> dates =
{
"m",
"mm",
"mmm",
"mmmmm",
"mmmmmm",
"d",
"dd",
"ddd",
"dddd",
"yy",
"yyyy"
"h",
"[h]",
"hh",
"m",
"[m]",
"mm",
"s",
"[s]",
"ss",
"AM/PM",
"am/pm",
"A/P",
"a/p"
};
auto split = split_string_any(format.value, date_unquoted);
std::string::size_type index = 0, prev = 0;
auto d = xlnt::datetime::from_number(number, base_date);
bool processed_month = false;
for(auto part : split)
{
while(format.value.substr(index, part.size()) != part)
{
index++;
}
auto between = format.value.substr(prev, index - prev);
result.append(between);
if(part == "m" && !processed_month)
{
result.append(std::to_string(d.month));
processed_month = true;
}
if(part == "mm" && !processed_month)
{
if(d.month < 10)
{
result.append("0");
}
result.append(std::to_string(d.month));
processed_month = true;
}
if(part == "mmm" && !processed_month)
{
result.append(MonthNames.at(d.month - 1).substr(0, 3));
processed_month = true;
}
if(part == "mmmm" && !processed_month)
{
result.append(MonthNames.at(d.month - 1));
processed_month = true;
}
if(part == "d")
{
result.append(std::to_string(d.day));
}
if(part == "dd")
{
if(d.day < 10)
{
result.append("0");
}
result.append(std::to_string(d.day));
}
if(part == "yyyy")
{
result.append(std::to_string(d.year));
}
if(part == "h")
{
result.append(std::to_string(d.hour));
processed_month = true;
}
if(part == "hh")
{
if(d.hour < 10)
{
result.append("0");
}
result.append(std::to_string(d.hour));
processed_month = true;
}
if(part == "m")
{
result.append(std::to_string(d.minute));
}
if(part == "mm")
{
if(d.minute < 10)
{
result.append("0");
}
result.append(std::to_string(d.minute));
}
if(part == "s")
{
result.append(std::to_string(d.second));
}
if(part == "ss")
{
if(d.second < 10)
{
result.append("0");
}
result.append(std::to_string(d.second));
}
index += part.size();
prev = index;
}
if(index < format.value.size())
{
result.append(format.value.substr(index));
}
}
else if(number == static_cast<long long int>(number))
{
result = std::to_string(static_cast<long long int>(number));
}
else
{
result = std::to_string(number);
}
return std::to_string(number);
return result;
}
std::string format_section(const std::string &text, const section &format)
@ -334,21 +530,21 @@ std::string format_section(const std::string &text, const section &format)
return first_part + middle_part + last_part;
}
std::string format_number(long double number, const std::string &format)
std::string format_number(long double number, const std::string &format, xlnt::calendar base_date)
{
auto sections = parse_format_sections(format);
if(number > 0)
{
return format_section(number, sections.first);
return format_section(number, sections.first, base_date);
}
else if(number < 0)
{
return format_section(number, sections.second);
return format_section(number, sections.second, base_date);
}
// number == 0
return format_section(number, sections.third);
return format_section(number, sections.third, base_date);
}
std::string format_text(const std::string &text, const std::string &format)
@ -358,12 +554,6 @@ std::string format_text(const std::string &text, const std::string &format)
return format_section(text, sections.fourth);
}
bool is_date_format(const std::string &format_string)
{
auto not_in = format_string.find_first_not_of("/-:, mMyYdDhHsS");
return not_in == std::string::npos;
}
}
namespace xlnt {
@ -411,7 +601,6 @@ bool cell::garbage_collectible() const
template<>
void cell::set_value(bool b)
{
d_->is_date_ = false;
d_->value_numeric_ = b ? 1 : 0;
d_->type_ = type::boolean;
}
@ -419,7 +608,6 @@ void cell::set_value(bool b)
template<>
void cell::set_value(std::int8_t i)
{
d_->is_date_ = false;
d_->value_numeric_ = static_cast<long double>(i);
d_->type_ = type::numeric;
}
@ -427,7 +615,6 @@ void cell::set_value(std::int8_t i)
template<>
void cell::set_value(std::int16_t i)
{
d_->is_date_ = false;
d_->value_numeric_ = static_cast<long double>(i);
d_->type_ = type::numeric;
}
@ -435,7 +622,6 @@ void cell::set_value(std::int16_t i)
template<>
void cell::set_value(std::int32_t i)
{
d_->is_date_ = false;
d_->value_numeric_ = static_cast<long double>(i);
d_->type_ = type::numeric;
}
@ -443,7 +629,6 @@ void cell::set_value(std::int32_t i)
template<>
void cell::set_value(std::int64_t i)
{
d_->is_date_ = false;
d_->value_numeric_ = static_cast<long double>(i);
d_->type_ = type::numeric;
}
@ -451,7 +636,6 @@ void cell::set_value(std::int64_t i)
template<>
void cell::set_value(std::uint8_t i)
{
d_->is_date_ = false;
d_->value_numeric_ = static_cast<long double>(i);
d_->type_ = type::numeric;
}
@ -459,7 +643,6 @@ void cell::set_value(std::uint8_t i)
template<>
void cell::set_value(std::uint16_t i)
{
d_->is_date_ = false;
d_->value_numeric_ = static_cast<long double>(i);
d_->type_ = type::numeric;
}
@ -467,7 +650,6 @@ void cell::set_value(std::uint16_t i)
template<>
void cell::set_value(std::uint32_t i)
{
d_->is_date_ = false;
d_->value_numeric_ = static_cast<long double>(i);
d_->type_ = type::numeric;
}
@ -475,7 +657,6 @@ void cell::set_value(std::uint32_t i)
template<>
void cell::set_value(std::uint64_t i)
{
d_->is_date_ = false;
d_->value_numeric_ = static_cast<long double>(i);
d_->type_ = type::numeric;
}
@ -484,7 +665,6 @@ void cell::set_value(std::uint64_t i)
template<>
void cell::set_value(unsigned long i)
{
d_->is_date_ = false;
d_->value_numeric_ = static_cast<long double>(i);
d_->type_ = type::numeric;
}
@ -494,7 +674,6 @@ void cell::set_value(unsigned long i)
template<>
void cell::set_value(long long i)
{
d_->is_date_ = false;
d_->value_numeric_ = static_cast<long double>(i);
d_->type_ = type::numeric;
}
@ -502,7 +681,6 @@ void cell::set_value(long long i)
template<>
void cell::set_value(unsigned long long i)
{
d_->is_date_ = false;
d_->value_numeric_ = static_cast<long double>(i);
d_->type_ = type::numeric;
}
@ -511,7 +689,6 @@ void cell::set_value(unsigned long long i)
template<>
void cell::set_value(float f)
{
d_->is_date_ = false;
d_->value_numeric_ = static_cast<long double>(f);
d_->type_ = type::numeric;
}
@ -519,7 +696,6 @@ void cell::set_value(float f)
template<>
void cell::set_value(double d)
{
d_->is_date_ = false;
d_->value_numeric_ = static_cast<long double>(d);
d_->type_ = type::numeric;
}
@ -527,7 +703,6 @@ void cell::set_value(double d)
template<>
void cell::set_value(long double d)
{
d_->is_date_ = false;
d_->value_numeric_ = static_cast<long double>(d);
d_->type_ = type::numeric;
}
@ -550,44 +725,43 @@ void cell::set_value(cell c)
d_->type_ = c.d_->type_;
d_->value_numeric_ = c.d_->value_numeric_;
d_->value_string_ = c.d_->value_string_;
d_->is_date_ = c.d_->is_date_;
d_->hyperlink_ = c.d_->hyperlink_;
d_->has_hyperlink_ = c.d_->has_hyperlink_;
d_->formula_ = c.d_->formula_;
set_style(c.get_style());
d_->style_id_ = c.d_->style_id_;
set_comment(c.get_comment());
}
template<>
void cell::set_value(date d)
{
auto base_date = get_parent().get_parent().get_properties().excel_base_date;
d_->set_date(d.to_number(base_date), xlnt::number_format::format::date_yyyymmdd2);
d_->type_ = type::numeric;
d_->value_numeric_ = d.to_number(get_base_date());
set_number_format(number_format(number_format::format::date_yyyymmdd2));
}
template<>
void cell::set_value(datetime d)
{
auto base_date = get_parent().get_parent().get_properties().excel_base_date;
d_->set_date(d.to_number(base_date), xlnt::number_format::format::date_datetime);
d_->type_ = type::numeric;
d_->value_numeric_ = d.to_number(get_base_date());
set_number_format(number_format(number_format::format::date_datetime));
}
template<>
void cell::set_value(time t)
{
d_->set_date(t.to_number(), xlnt::number_format::format::date_time6);
d_->type_ = type::numeric;
d_->value_numeric_ = t.to_number();
set_number_format(number_format(number_format::format::date_time6));
}
template<>
void cell::set_value(timedelta t)
{
d_->set_date(t.to_number(), xlnt::number_format::format::date_timedelta);
d_->is_date_ = false; // a timedelta isn't actually a date, still uses mostly the same code
}
bool cell::has_style() const
{
return d_->style_ != nullptr;
d_->type_ = type::numeric;
d_->value_numeric_ = t.to_number();
set_number_format(number_format(number_format::format::date_timedelta));
}
row_t cell::get_row() const
@ -612,9 +786,9 @@ bool cell::is_merged() const
bool cell::is_date() const
{
if(get_data_type() == type::numeric && has_style())
if(get_data_type() == type::numeric)
{
auto number_format = get_style().get_number_format().get_format_code_string();
auto number_format = get_number_format().get_format_string();
if(number_format != "General")
{
@ -648,21 +822,6 @@ bool cell::operator==(const cell &comparand) const
return d_ == comparand.d_;
}
style &cell::get_style()
{
return d_->get_style(true);
}
const style &cell::get_style() const
{
return d_->get_style();
}
void cell::set_style(const xlnt::style &s)
{
get_style() = s;
}
cell &cell::operator=(const cell &rhs)
{
*d_ = *rhs.d_;
@ -874,54 +1033,44 @@ std::size_t cell::get_xf_index() const
return d_->xf_index_;
}
std::string cell::get_number_format()
const number_format &cell::get_number_format() const
{
return get_style().get_number_format().get_format_code_string();
return get_parent().get_parent().get_number_format(d_->style_id_);
}
std::string cell::get_number_format() const
const font &cell::get_font() const
{
return get_style().get_number_format().get_format_code_string();
}
font &cell::get_font()
{
return get_style().get_font();
return get_parent().get_parent().get_font(d_->style_id_);
}
fill &cell::get_fill()
{
return get_style().get_fill();
}
const fill &cell::get_fill() const
{
return get_style().get_fill();
return get_parent().get_parent().get_fill(d_->style_id_);
}
border &cell::get_border()
const border &cell::get_border() const
{
return get_style().get_border();
return get_parent().get_parent().get_border(d_->style_id_);
}
alignment &cell::get_alignment()
const alignment &cell::get_alignment() const
{
return get_style().get_alignment();
return get_parent().get_parent().get_alignment(d_->style_id_);
}
protection &cell::get_protection()
const protection &cell::get_protection() const
{
return get_style().get_protection();
return get_parent().get_parent().get_protection(d_->style_id_);
}
bool cell::pivot_button()
bool cell::pivot_button() const
{
return get_style().pivot_button();
return get_parent().get_parent().get_pivot_button(d_->style_id_);
}
bool cell::quote_prefix()
bool cell::quote_prefix() const
{
return get_style().quote_prefix();
return get_parent().get_parent().get_quote_prefix(d_->style_id_);
}
void cell::clear_value()
@ -1021,25 +1170,24 @@ time cell::get_value() const
template<>
datetime cell::get_value() const
{
return datetime::from_number(d_->value_numeric_, xlnt::calendar::windows_1900);
return datetime::from_number(d_->value_numeric_, get_base_date());
}
template<>
date cell::get_value() const
{
return date::from_number(static_cast<int>(d_->value_numeric_), xlnt::calendar::windows_1900);
return date::from_number(static_cast<int>(d_->value_numeric_), get_base_date());
}
template<>
timedelta cell::get_value() const
{
return timedelta(0, 0);
//return timedelta::from_number(d_->value_numeric_);
return timedelta::from_number(d_->value_numeric_);
}
void cell::set_number_format(const std::string &format_string, int index)
void cell::set_number_format(const number_format &number_format_)
{
get_style().get_number_format().set_format_code_string(format_string, index);
d_->style_id_ = get_parent().get_parent().set_number_format(number_format_, d_->style_id_);
}
template<>
@ -1055,28 +1203,33 @@ bool cell::has_value() const
std::string cell::to_string() const
{
std::string number_format = "General";
if(has_style())
{
number_format = get_style().get_number_format().get_format_code_string();
}
auto nf = get_number_format();
switch(get_data_type())
{
case cell::type::null:
return "";
case cell::type::numeric:
return format_number(get_value<long double>(), number_format);
return format_number(get_value<long double>(), nf.get_format_string(), get_base_date());
case cell::type::string:
case cell::type::formula:
case cell::type::error:
return format_text(get_value<std::string>(), number_format);
return format_text(get_value<std::string>(), nf.get_format_string());
case cell::type::boolean:
return get_value<long double>() == 0 ? "FALSE" : "TRUE";
default:
return "";
}
}
std::size_t cell::get_style_id() const
{
return d_->style_id_;
}
calendar cell::get_base_date() const
{
return get_parent().get_parent().get_properties().excel_base_date;
}
} // namespace xlnt

View File

@ -186,5 +186,10 @@ double timedelta::to_number() const
{
return days + hours / 24.0;
}
timedelta timedelta::from_number(long double number)
{
return timedelta(static_cast<long long int>(number), 0);
}
} // namespace xlnt

View File

@ -5,30 +5,6 @@
namespace xlnt {
namespace detail {
cell::type type_;
worksheet_impl *parent_;
column_t column_;
row_t row_;
std::string value_string_;
long double value_numeric_;
std::string formula_;
bool has_hyperlink_;
relationship hyperlink_;
bool is_merged_;
bool is_date_;
std::size_t xf_index_;
std::unique_ptr<style> style_;
std::unique_ptr<comment_impl> comment_;
cell_impl::cell_impl() : cell_impl(1, 1)
{
@ -46,9 +22,8 @@ cell_impl::cell_impl(worksheet_impl *parent, column_t column, row_t row)
value_numeric_(0),
has_hyperlink_(false),
is_merged_(false),
is_date_(false),
xf_index_(0),
style_(nullptr),
style_id_(1),
comment_(nullptr)
{
}
@ -68,14 +43,9 @@ cell_impl &cell_impl::operator=(const cell_impl &rhs)
column_ = rhs.column_;
row_ = rhs.row_;
is_merged_ = rhs.is_merged_;
is_date_ = rhs.is_date_;
has_hyperlink_ = rhs.has_hyperlink_;
type_ = rhs.type_;
if(rhs.style_ != nullptr)
{
style_.reset(new style(*rhs.style_));
}
style_id_ = rhs.style_id_;
if(rhs.comment_ != nullptr)
{

View File

@ -8,6 +8,7 @@
#include <xlnt/common/datetime.hpp>
#include <xlnt/common/types.hpp>
#include <xlnt/common/relationship.hpp>
#include <xlnt/styles/number_format.hpp>
#include "comment_impl.hpp"
@ -123,37 +124,13 @@ struct cell_impl
cell_impl(const cell_impl &rhs);
cell_impl &operator=(const cell_impl &rhs);
style &get_style(bool create_if_null)
cell self()
{
if(style_ == nullptr && create_if_null)
{
style_.reset(new style());
}
return *style_;
}
const style &get_style() const
{
if(style_ == nullptr)
{
throw std::runtime_error("call has_style to check if const cell has a style before accessing it");
}
return *style_;
}
void set_date(long double number, xlnt::number_format::format format_code)
{
is_date_ = true;
get_style(true).get_number_format().set_format_code(format_code);
value_numeric_ = number;
type_ = cell::type::numeric;
return xlnt::cell(this);
}
void set_string(const std::string &s, bool guess_types)
{
is_date_ = false;
value_string_ = check_string(s);
type_ = cell::type::string;
@ -175,7 +152,7 @@ struct cell_impl
{
value_numeric_ = percentage.second;
type_ = cell::type::numeric;
get_style(true).get_number_format().set_format_code(xlnt::number_format::format::percentage);
self().set_number_format(xlnt::number_format(xlnt::number_format::format::percentage));
}
else
{
@ -183,7 +160,9 @@ struct cell_impl
if (time.first)
{
set_date(time.second.to_number(), xlnt::number_format::format::date_time6);
type_ = cell::type::numeric;
self().set_number_format(xlnt::number_format(number_format::format::date_time6));
value_numeric_ = time.second.to_number();
}
else
{
@ -215,11 +194,10 @@ struct cell_impl
relationship hyperlink_;
bool is_merged_;
bool is_date_;
std::size_t xf_index_;
std::size_t style_id_;
std::unique_ptr<style> style_;
std::unique_ptr<comment_impl> comment_;
};

View File

@ -17,7 +17,22 @@ struct workbook_impl
drawings_(other.drawings_),
properties_(other.properties_),
guess_types_(other.guess_types_),
data_only_(other.data_only_)
data_only_(other.data_only_),
next_style_id_(other.next_style_id_),
alignments_(other.alignments_),
borders_(other.borders_),
fills_(other.fills_),
fonts_(other.fonts_),
number_formats_(other.number_formats_),
protections_(other.protections_),
style_alignment_(other.style_alignment_),
style_border_(other.style_border_),
style_fill_(other.style_fill_),
style_font_(other.style_font_),
style_number_format_(other.style_number_format_),
style_protection_(other.style_protection_),
style_pivot_button_(other.style_pivot_button_),
style_quote_prefix_(other.style_quote_prefix_)
{
}
@ -33,6 +48,21 @@ struct workbook_impl
properties_ = other.properties_;
guess_types_ = other.guess_types_;
data_only_ = other.data_only_;
next_style_id_ = other.next_style_id_;
alignments_ = other.alignments_;
borders_ = other.borders_;
fills_ = other.fills_;
fonts_ = other.fonts_;
number_formats_ = other.number_formats_;
protections_ = other.protections_;
style_alignment_ = other.style_alignment_;
style_border_ = other.style_border_;
style_fill_ = other.style_fill_;
style_font_ = other.style_font_;
style_number_format_ = other.style_number_format_;
style_protection_ = other.style_protection_;
style_pivot_button_ = other.style_pivot_button_;
style_quote_prefix_ = other.style_quote_prefix_;
return *this;
}
@ -44,6 +74,22 @@ struct workbook_impl
document_properties properties_;
bool guess_types_;
bool data_only_;
std::size_t next_style_id_;
std::unordered_map<std::size_t, alignment> alignments_;
std::unordered_map<std::size_t, border> borders_;
std::unordered_map<std::size_t, fill> fills_;
std::unordered_map<std::size_t, font> fonts_;
std::unordered_map<std::size_t, number_format> number_formats_;
std::unordered_map<std::size_t, protection> protections_;
std::unordered_map<std::size_t, std::size_t> style_alignment_;
std::unordered_map<std::size_t, std::size_t> style_border_;
std::unordered_map<std::size_t, std::size_t> style_fill_;
std::unordered_map<std::size_t, std::size_t> style_font_;
std::unordered_map<std::size_t, std::size_t> style_number_format_;
std::unordered_map<std::size_t, std::size_t> style_protection_;
std::unordered_map<std::size_t, bool> style_pivot_button_;
std::unordered_map<std::size_t, bool> style_quote_prefix_;
};
} // namespace detail

View File

@ -123,7 +123,21 @@ const std::unordered_map<std::string, int> &number_format::reversed_builtin_form
return formats;
}
number_format::number_format() : number_format(format::general)
{
}
number_format::number_format(format code) : format_code_(code), format_index_(0)
{
set_format_code(code);
}
number_format::number_format(const std::string &format_string) : number_format(format::general)
{
set_format_string(format_string);
}
number_format::format number_format::lookup_format(int code)
{
if(builtin_formats().find(code) == builtin_formats().end())
@ -142,14 +156,58 @@ number_format::format number_format::lookup_format(int code)
return match->first;
}
std::string number_format::get_format_code_string() const
std::string number_format::get_format_string() const
{
if(builtin_formats().find(format_index_) == builtin_formats().end())
{
return custom_format_code_;
}
return format_string_;
}
number_format::format number_format::get_format_code() const
{
return format_code_;
}
std::size_t number_format::hash() const
{
std::hash<std::string> hasher;
return hasher(format_string_);
}
return builtin_formats().at(format_index_);
void number_format::set_format_string(const std::string &format_string)
{
format_string_ = format_string;
format_index_ = -1;
format_code_ = format::unknown;
const auto &reversed = reversed_builtin_formats();
if(reversed.find(format_string) != reversed.end())
{
format_index_ = reversed.at(format_string);
for(const auto &pair : format_strings())
{
if(pair.second == format_string)
{
format_code_ = pair.first;
break;
}
}
}
}
void number_format::set_format_code(xlnt::number_format::format format_code)
{
format_code_ = format_code;
format_string_ = format_strings().at(format_code);
try
{
format_index_ = reversed_builtin_formats().at(format_string_);
}
catch(std::out_of_range)
{
format_index_ = -1;
}
}
} // namespace xlnt

View File

@ -12,6 +12,7 @@
#include <xlnt/workbook/workbook.hpp>
#include <xlnt/worksheet/range_reference.hpp>
#include <xlnt/worksheet/worksheet.hpp>
#include <xlnt/styles/number_format.hpp>
namespace {
@ -164,20 +165,16 @@ void read_worksheet_common(xlnt::worksheet ws, const pugi::xml_node &root_node,
if(match != custom_number_formats.end())
{
ws.get_cell(address).get_style().get_number_format().set_format_code_string(match->second, number_format_id);
xlnt::number_format nf(match->second);
auto cell = ws.get_cell(address);
cell.set_number_format(nf);
}
}
else
{
ws.get_cell(address).get_style().get_number_format().set_format_code(format);
}
//TODO: this is bad
if(ws.get_cell(address).get_style().get_number_format().get_format_code_string().find_first_of("mdyhs") != std::string::npos)
{
auto base_date = ws.get_parent().get_properties().excel_base_date;
auto converted = xlnt::datetime::from_number(std::stold(value_string), base_date);
ws.get_cell(address).set_value(converted.to_number(xlnt::calendar::windows_1900));
xlnt::number_format nf(format);
auto cell = ws.get_cell(address);
cell.set_number_format(nf);
}
}
}

View File

@ -1,69 +1,92 @@
#include <xlnt/cell/cell.hpp>
#include <xlnt/styles/style.hpp>
#include "font.hpp"
#include "number_format.hpp"
#include "protection.hpp"
namespace {
template <class T>
void hash_combine(std::size_t& seed, const T& v)
{
std::hash<T> hasher;
seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
}
}
namespace xlnt {
style::style(const style &rhs) : number_format_(rhs.number_format_), protection_(rhs.protection_)
style::style()
{
}
void style::set_protection(xlnt::protection protection)
style::style(const style &other)
{
protection_ = protection;
}
const cell style::get_parent() const
{
return cell(parent_);
}
std::size_t style::hash() const
{
std::size_t seed = 100;
std::hash<std::string> string_hash;
auto font_ = get_font();
hash_combine(seed, string_hash(font_.name_));
hash_combine(seed, font_.size_);
hash_combine(seed, static_cast<std::size_t>(font_.underline_));
std::size_t bools = font_.bold_;
bools = bools << 1 & font_.italic_;
bools = bools << 1 & font_.strikethrough_;
bools = bools << 1 & font_.superscript_;
bools = bools << 1 & font_.subscript_;
hash_combine(seed, bools);
return seed;
}
const number_format &style::get_number_format() const
{
return get_parent().get_number_format();
}
const border &style::get_border() const
{
return get_parent().get_border();
}
const alignment &style::get_alignment() const
{
return get_parent().get_alignment();
}
void style::set_number_format(xlnt::number_format format)
{
number_format_ = format;
}
border &style::get_border()
{
return border_;
}
bool style::pivot_button()
{
return pivot_button_;
}
bool style::quote_prefix()
{
return quote_prefix_;
}
alignment &style::get_alignment()
{
return alignment_;
}
fill &style::get_fill()
{
return fill_;
}
const fill &style::get_fill() const
{
return fill_;
return get_parent().get_fill();
}
font &style::get_font()
const font &style::get_font() const
{
return font_;
return get_parent().get_font();
}
protection &style::get_protection()
const protection &style::get_protection() const
{
return protection_;
return get_parent().get_protection();
}
void style::set_pivot_button(bool pivot)
bool style::pivot_button() const
{
pivot_button_ = pivot;
return get_parent().pivot_button();
}
void style::set_quote_prefix(bool quote)
bool style::quote_prefix() const
{
quote_prefix_ = quote;
return get_parent().quote_prefix();
}
} // namespace xlnt

View File

@ -1,6 +1,12 @@
#include <sstream>
#include <pugixml.hpp>
#include <xlnt/styles/alignment.hpp>
#include <xlnt/styles/borders.hpp>
#include <xlnt/styles/fill.hpp>
#include <xlnt/styles/font.hpp>
#include <xlnt/styles/number_format.hpp>
#include <xlnt/styles/protection.hpp>
#include <xlnt/writer/style_writer.hpp>
#include <xlnt/workbook/workbook.hpp>
#include <xlnt/worksheet/worksheet.hpp>
@ -14,46 +20,6 @@ style_writer::style_writer(xlnt::workbook &wb) : wb_(wb)
}
std::unordered_map<std::size_t, std::string> style_writer::get_style_by_hash() const
{
std::unordered_map<std::size_t, std::string> styles;
for(auto ws : wb_)
{
for(auto row : ws.rows())
{
for(auto cell : row)
{
if(cell.has_style())
{
styles[1] = "style";
}
}
}
}
return styles;
}
std::vector<style> style_writer::get_styles() const
{
std::vector<style> styles;
for(auto ws : wb_)
{
for(auto row : ws.rows())
{
for(auto cell : row)
{
if(cell.has_style())
{
styles.push_back(cell.get_style());
}
}
}
}
return styles;
}
std::string style_writer::write_table() const
{
pugi::xml_document doc;
@ -62,36 +28,53 @@ std::string style_writer::write_table() const
style_sheet_node.append_attribute("xmlns:mc").set_value("http://schemas.openxmlformats.org/markup-compatibility/2006");
style_sheet_node.append_attribute("mc:Ignorable").set_value("x14ac");
style_sheet_node.append_attribute("xmlns:x14ac").set_value("http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac");
std::vector<style> custom_styles;
for(auto style : get_styles())
auto num_fmts_node = style_sheet_node.append_child("numFmts");
auto &num_fmts = wb_.get_number_formats();
num_fmts_node.append_attribute("count").set_value(static_cast<int>(num_fmts.size()));
int custom_index = 164;
for(auto &num_fmt : num_fmts)
{
if((int)style.get_number_format().get_format_code() > 163)
auto num_fmt_node = num_fmts_node.append_child("numFmt");
if(num_fmt.second.get_format_code() == number_format::format::unknown)
{
custom_styles.push_back(style);
num_fmt_node.append_attribute("numFmtId").set_value(custom_index++);
}
}
if(!custom_styles.empty())
{
else
{
num_fmt_node.append_attribute("numFmtId").set_value(num_fmt.second.get_format_index());
}
num_fmt_node.append_attribute("formatCode").set_value("General");
}
auto fonts_node = style_sheet_node.append_child("fonts");
fonts_node.append_attribute("count").set_value(1);
auto &fonts = wb_.get_fonts();
fonts_node.append_attribute("count").set_value(static_cast<int>(fonts.size()));
fonts_node.append_attribute("x14ac:knownFonts").set_value(1);
auto font_node = fonts_node.append_child("font");
auto size_node = font_node.append_child("sz");
size_node.append_attribute("val").set_value(11);
auto color_node = font_node.append_child("color");
color_node.append_attribute("theme").set_value(1);
auto name_node = font_node.append_child("name");
name_node.append_attribute("val").set_value("Calibri");
auto family_node = font_node.append_child("family");
family_node.append_attribute("val").set_value(2);
auto scheme_node = font_node.append_child("scheme");
scheme_node.append_attribute("val").set_value("minor");
for(auto &f : fonts)
{
auto font_node = fonts_node.append_child("font");
auto size_node = font_node.append_child("sz");
size_node.append_attribute("val").set_value(f.second.get_size());
auto color_node = font_node.append_child("color");
color_node.append_attribute("theme").set_value(1);
auto name_node = font_node.append_child("name");
name_node.append_attribute("val").set_value(f.second.get_name().c_str());
auto family_node = font_node.append_child("family");
family_node.append_attribute("val").set_value(2);
auto scheme_node = font_node.append_child("scheme");
scheme_node.append_attribute("val").set_value("minor");
if(f.second.is_bold())
{
auto bold_node = font_node.append_child("b");
bold_node.append_attribute("val").set_value(1);
}
}
auto fills_node = style_sheet_node.append_child("fills");
fills_node.append_attribute("count").set_value(2);

View File

@ -13,6 +13,12 @@
#include <xlnt/common/zip_file.hpp>
#include <xlnt/drawing/drawing.hpp>
#include <xlnt/reader/reader.hpp>
#include <xlnt/styles/alignment.hpp>
#include <xlnt/styles/borders.hpp>
#include <xlnt/styles/fill.hpp>
#include <xlnt/styles/font.hpp>
#include <xlnt/styles/number_format.hpp>
#include <xlnt/styles/protection.hpp>
#include <xlnt/workbook/document_properties.hpp>
#include <xlnt/workbook/named_range.hpp>
#include <xlnt/workbook/workbook.hpp>
@ -56,9 +62,8 @@ static std::string create_temporary_filename()
namespace xlnt {
namespace detail {
workbook_impl::workbook_impl() : active_sheet_index_(0), guess_types_(false), data_only_(false)
workbook_impl::workbook_impl() : active_sheet_index_(0), guess_types_(false), data_only_(false), next_style_id_(0)
{
}
} // namespace detail
@ -69,6 +74,14 @@ workbook::workbook() : d_(new detail::workbook_impl())
create_relationship("rId2", "sharedStrings.xml", relationship::type::shared_strings);
create_relationship("rId3", "styles.xml", relationship::type::styles);
create_relationship("rId4", "theme/theme1.xml", relationship::type::theme);
set_alignment(alignment(), 1);
set_border(border(), 1);
set_fill(fill(), 1);
set_font(font(), 1);
set_number_format(number_format(), 1);
set_protection(protection(), 1);
d_->style_pivot_button_[1] = false;
d_->style_quote_prefix_[1] = false;
}
workbook::iterator::iterator(workbook &wb, std::size_t index) : wb_(wb), index_(index)
@ -657,64 +670,242 @@ void workbook::set_data_only(bool data_only)
{
d_->data_only_ = data_only;
}
void workbook::add_border(xlnt::border /*b*/)
{
void workbook::add_border(xlnt::border /*b*/)
{
}
void workbook::add_alignment(xlnt::alignment /*a*/)
{
}
void workbook::add_protection(xlnt::protection /*p*/)
{
}
void workbook::add_number_format(const std::string &/*format*/)
{
}
void workbook::add_fill(xlnt::fill &/*f*/)
{
}
void workbook::add_font(xlnt::font /*f*/)
{
}
void workbook::set_code_name(const std::string &/*code_name*/)
{
}
bool workbook::has_loaded_theme()
{
return false;
}
std::string workbook::get_loaded_theme()
{
return "";
}
std::vector<named_range> workbook::get_named_ranges() const
{
std::vector<named_range> named_ranges;
for(auto ws : *this)
{
for(auto &ws_named_range : ws.d_->named_ranges_)
{
named_ranges.push_back(ws_named_range.second);
}
}
return named_ranges;
}
}
void workbook::add_alignment(xlnt::alignment /*a*/)
{
}
void workbook::add_protection(xlnt::protection /*p*/)
{
}
void workbook::add_number_format(const std::string &/*format*/)
{
}
void workbook::add_fill(xlnt::fill &/*f*/)
{
}
void workbook::add_font(xlnt::font /*f*/)
{
}
void workbook::set_code_name(const std::string &/*code_name*/)
{
}
bool workbook::has_loaded_theme()
{
return false;
}
std::string workbook::get_loaded_theme()
{
return "";
}
std::vector<named_range> workbook::get_named_ranges() const
{
std::vector<named_range> named_ranges;
for(auto ws : *this)
{
for(auto &ws_named_range : ws.d_->named_ranges_)
{
named_ranges.push_back(ws_named_range.second);
}
}
return named_ranges;
}
std::size_t workbook::add_style(xlnt::style style_)
{
return 1;
}
const number_format &workbook::get_number_format(std::size_t style_id) const
{
return d_->number_formats_[d_->style_number_format_[style_id]];
}
const font &workbook::get_font(std::size_t style_id) const
{
return d_->fonts_[d_->style_font_[style_id]];
}
std::size_t workbook::set_font(const font &font_, std::size_t style_id)
{
auto hash = font_.hash();
if(d_->number_formats_.find(hash) == d_->number_formats_.end())
{
d_->fonts_[hash] = font_;
}
d_->style_font_[d_->next_style_id_] = hash;
d_->style_alignment_[d_->next_style_id_] = d_->style_alignment_[style_id];
d_->style_border_[d_->next_style_id_] = d_->style_border_[style_id];
d_->style_fill_[d_->next_style_id_] = d_->style_fill_[style_id];
d_->style_number_format_[d_->next_style_id_] = d_->style_number_format_[style_id];
d_->style_protection_[d_->next_style_id_] = d_->style_protection_[style_id];
d_->style_pivot_button_[d_->next_style_id_] = d_->style_pivot_button_[style_id];
d_->style_quote_prefix_[d_->next_style_id_] = d_->style_quote_prefix_[style_id];
return d_->next_style_id_++;
}
const fill &workbook::get_fill(std::size_t style_id) const
{
return d_->fills_[d_->style_fill_[style_id]];
}
std::size_t workbook::set_fill(const fill &fill_, std::size_t style_id)
{
auto hash = fill_.hash();
if(d_->fills_.find(hash) == d_->fills_.end())
{
d_->fills_[hash] = fill_;
}
d_->style_fill_[d_->next_style_id_] = hash;
d_->style_alignment_[d_->next_style_id_] = d_->style_alignment_[style_id];
d_->style_border_[d_->next_style_id_] = d_->style_border_[style_id];
d_->style_font_[d_->next_style_id_] = d_->style_font_[style_id];
d_->style_number_format_[d_->next_style_id_] = d_->style_number_format_[style_id];
d_->style_protection_[d_->next_style_id_] = d_->style_protection_[style_id];
d_->style_pivot_button_[d_->next_style_id_] = d_->style_pivot_button_[style_id];
d_->style_quote_prefix_[d_->next_style_id_] = d_->style_quote_prefix_[style_id];
return d_->next_style_id_++;
}
const border &workbook::get_border(std::size_t style_id) const
{
return d_->borders_[d_->style_border_[style_id]];
}
std::size_t workbook::set_border(const border &border_, std::size_t style_id)
{
auto hash = border_.hash();
if(d_->borders_.find(hash) == d_->borders_.end())
{
d_->borders_[hash] = border_;
}
d_->style_border_[d_->next_style_id_] = hash;
d_->style_alignment_[d_->next_style_id_] = d_->style_alignment_[style_id];
d_->style_font_[d_->next_style_id_] = d_->style_font_[style_id];
d_->style_fill_[d_->next_style_id_] = d_->style_fill_[style_id];
d_->style_number_format_[d_->next_style_id_] = d_->style_number_format_[style_id];
d_->style_protection_[d_->next_style_id_] = d_->style_protection_[style_id];
d_->style_pivot_button_[d_->next_style_id_] = d_->style_pivot_button_[style_id];
d_->style_quote_prefix_[d_->next_style_id_] = d_->style_quote_prefix_[style_id];
return d_->next_style_id_++;
}
const alignment &workbook::get_alignment(std::size_t style_id) const
{
return d_->alignments_[d_->style_alignment_[style_id]];
}
std::size_t workbook::set_alignment(const alignment &alignment_, std::size_t style_id)
{
auto hash = alignment_.hash();
if(d_->alignments_.find(hash) == d_->alignments_.end())
{
d_->alignments_[hash] = alignment_;
}
d_->style_alignment_[d_->next_style_id_] = hash;
d_->style_border_[d_->next_style_id_] = d_->style_border_[style_id];
d_->style_font_[d_->next_style_id_] = d_->style_font_[style_id];
d_->style_fill_[d_->next_style_id_] = d_->style_fill_[style_id];
d_->style_number_format_[d_->next_style_id_] = d_->style_number_format_[style_id];
d_->style_protection_[d_->next_style_id_] = d_->style_protection_[style_id];
d_->style_pivot_button_[d_->next_style_id_] = d_->style_pivot_button_[style_id];
d_->style_quote_prefix_[d_->next_style_id_] = d_->style_quote_prefix_[style_id];
return d_->next_style_id_++;
}
const protection &workbook::get_protection(std::size_t style_id) const
{
return d_->protections_[d_->style_protection_[style_id]];
}
std::size_t workbook::set_protection(const protection &protection_, std::size_t style_id)
{
auto hash = protection_.hash();
if(d_->protections_.find(hash) == d_->protections_.end())
{
d_->protections_[hash] = protection_;
}
d_->style_protection_[d_->next_style_id_] = hash;
d_->style_alignment_[d_->next_style_id_] = d_->style_alignment_[style_id];
d_->style_border_[d_->next_style_id_] = d_->style_border_[style_id];
d_->style_font_[d_->next_style_id_] = d_->style_font_[style_id];
d_->style_fill_[d_->next_style_id_] = d_->style_fill_[style_id];
d_->style_number_format_[d_->next_style_id_] = d_->style_number_format_[style_id];
d_->style_pivot_button_[d_->next_style_id_] = d_->style_pivot_button_[style_id];
d_->style_quote_prefix_[d_->next_style_id_] = d_->style_quote_prefix_[style_id];
return d_->next_style_id_++;
}
bool workbook::get_pivot_button(std::size_t style_id) const
{
return d_->style_pivot_button_[style_id];
}
bool workbook::get_quote_prefix(std::size_t style_id) const
{
return d_->style_quote_prefix_[style_id];
}
std::size_t workbook::set_number_format(const xlnt::number_format &format, std::size_t style_id)
{
auto hash = format.hash();
if(d_->number_formats_.find(hash) == d_->number_formats_.end())
{
d_->number_formats_[hash] = format;
}
d_->style_number_format_[d_->next_style_id_] = hash;
d_->style_alignment_[d_->next_style_id_] = d_->style_alignment_[style_id];
d_->style_border_[d_->next_style_id_] = d_->style_border_[style_id];
d_->style_font_[d_->next_style_id_] = d_->style_font_[style_id];
d_->style_fill_[d_->next_style_id_] = d_->style_fill_[style_id];
d_->style_protection_[d_->next_style_id_] = d_->style_protection_[style_id];
d_->style_pivot_button_[d_->next_style_id_] = d_->style_pivot_button_[style_id];
d_->style_quote_prefix_[d_->next_style_id_] = d_->style_quote_prefix_[style_id];
return d_->next_style_id_++;
}
} // namespace xlnt

View File

@ -7,6 +7,15 @@ xlnt::workbook load_workbook(const std::vector<std::uint8_t> &bytes)
{
xlnt::workbook wb;
wb.load(bytes);
return wb;
}
xlnt::workbook load_workbook(const std::string &filename)
{
xlnt::workbook wb;
wb.load(filename);
return wb;
}

View File

@ -104,18 +104,7 @@ std::string write_worksheet(worksheet ws, const std::vector<std::string> &string
std::vector<column_t> styled_columns;
if(!style_id_by_hash.empty())
{
for(auto row : ws.rows())
{
for(auto cell : row)
{
if(cell.has_style())
{
styled_columns.push_back(cell_reference::column_index_from_string(cell.get_column()));
}
}
}
{
auto cols_node = root_node.append_child("cols");
std::sort(styled_columns.begin(), styled_columns.end());
@ -268,10 +257,8 @@ std::string write_worksheet(worksheet ws, const std::vector<std::string> &string
}
}
if(cell.has_style())
{
cell_node.append_attribute("s").set_value(1);
}
auto style_id = cell.get_style_id();
cell_node.append_attribute("s").set_value((unsigned int)style_id);
}
}
}

View File

@ -4,8 +4,21 @@
#include <iostream>
#include <cxxtest/TestSuite.h>
#include <xlnt/xlnt.hpp>
#include <xlnt/reader/reader.hpp>
#include <xlnt/cell/cell.hpp>
#include <xlnt/cell/cell_reference.hpp>
#include <xlnt/cell/comment.hpp>
#include <xlnt/common/datetime.hpp>
#include <xlnt/common/exceptions.hpp>
#include <xlnt/reader/workbook_reader.hpp>
#include <xlnt/styles/alignment.hpp>
#include <xlnt/styles/borders.hpp>
#include <xlnt/styles/font.hpp>
#include <xlnt/styles/fill.hpp>
#include <xlnt/styles/number_format.hpp>
#include <xlnt/styles/protection.hpp>
#include <xlnt/worksheet/range.hpp>
#include <xlnt/worksheet/worksheet.hpp>
#include <xlnt/workbook/workbook.hpp>
class test_cell : public CxxTest::TestSuite
{
@ -18,6 +31,23 @@ public:
wb_guess_types.set_guess_types(true);
}
void test_debug()
{
xlnt::workbook wb = xlnt::load_workbook("/Users/thomas/Development/xlnt/samples/sample1.xlsx");
for(auto ws : wb)
{
for(auto row : ws.rows())
{
for(auto cell : row)
{
std::cout << cell << ", ";
}
std::cout << std::endl;
}
}
}
void test_infer_numeric()
{
auto ws = wb_guess_types.create_sheet();
@ -171,7 +201,7 @@ public:
TS_ASSERT(cell.get_data_type() == xlnt::cell::type::numeric);
TS_ASSERT(cell.get_value<long double>() == 40372.27616898148L);
TS_ASSERT(cell.is_date());
TS_ASSERT(cell.get_number_format() == "yyyy-mm-dd h:mm:ss");
TS_ASSERT(cell.get_number_format().get_format_string() == "yyyy-mm-dd h:mm:ss");
}
void test_insert_date()
@ -183,7 +213,7 @@ public:
TS_ASSERT(cell.get_data_type() == xlnt::cell::type::numeric);
TS_ASSERT(cell.get_value<long double>() == 40372.L);
TS_ASSERT(cell.is_date());
TS_ASSERT(cell.get_number_format() == "yyyy-mm-dd");
TS_ASSERT(cell.get_number_format().get_format_string() == "yyyy-mm-dd");
}
void test_insert_time()
@ -195,7 +225,7 @@ public:
TS_ASSERT(cell.get_data_type() == xlnt::cell::type::numeric);
TS_ASSERT(cell.get_value<long double>() == 0.04375L);
TS_ASSERT(cell.is_date());
TS_ASSERT(cell.get_number_format() == "h:mm:ss");
TS_ASSERT(cell.get_number_format().get_format_string() == "h:mm:ss");
}
void test_cell_formatted_as_date1()
@ -279,7 +309,7 @@ public:
TS_ASSERT(cell.get_value<long double>() == 1.125);
TS_ASSERT(cell.get_data_type() == xlnt::cell::type::numeric);
TS_ASSERT(!cell.is_date());
TS_ASSERT(cell.get_number_format() == "[hh]:mm:ss");
TS_ASSERT(cell.get_number_format().get_format_string() == "[hh]:mm:ss");
}
void test_repr()
@ -406,8 +436,8 @@ public:
ws.get_parent().add_number_format("dd--hh--mm");
xlnt::cell cell(ws, "A1");
cell.set_number_format("dd--hh--mm");
TS_ASSERT(cell.get_number_format() == "dd--hh--mm");
cell.set_number_format(xlnt::number_format("dd--hh--mm"));
TS_ASSERT(cell.get_number_format().get_format_string() == "dd--hh--mm");
}
void _test_alignment()
@ -439,7 +469,7 @@ public:
auto ws = wb.create_sheet();
xlnt::cell cell(ws, "A1");
cell.get_style().set_pivot_button(true);
cell.set_pivot_button(true);
TS_ASSERT(cell.pivot_button());
}
@ -448,7 +478,7 @@ public:
auto ws = wb.create_sheet();
xlnt::cell cell(ws, "A1");
cell.get_style().set_quote_prefix(true);
cell.set_quote_prefix(true);
TS_ASSERT(cell.quote_prefix());
}
};

View File

@ -93,7 +93,7 @@ public:
{
auto wb = workbook_with_styles();
auto ws = wb["Sheet1"];
auto code = ws.get_cell("A1").get_style().get_number_format().get_format_code();
auto code = ws.get_cell("A1").get_number_format().get_format_code();
auto expected = xlnt::number_format::format::general;
TS_ASSERT_EQUALS(code, expected);
}
@ -102,7 +102,7 @@ public:
{
auto wb = workbook_with_styles();
auto ws = wb["Sheet1"];
auto code = ws.get_cell("A2").get_style().get_number_format().get_format_code();
auto code = ws.get_cell("A2").get_number_format().get_format_code();
auto expected = xlnt::number_format::format::date_xlsx14;
TS_ASSERT_EQUALS(code, expected);
}
@ -111,7 +111,7 @@ public:
{
auto wb = workbook_with_styles();
auto ws = wb["Sheet1"];
auto code = ws.get_cell("A3").get_style().get_number_format().get_format_code();
auto code = ws.get_cell("A3").get_number_format().get_format_code();
auto expected = xlnt::number_format::format::number_00;
TS_ASSERT_EQUALS(code, expected);
}
@ -120,7 +120,7 @@ public:
{
auto wb = workbook_with_styles();
auto ws = wb["Sheet1"];
auto code = ws.get_cell("A4").get_style().get_number_format().get_format_code();
auto code = ws.get_cell("A4").get_number_format().get_format_code();
auto expected = xlnt::number_format::format::date_time3;
TS_ASSERT_EQUALS(code, expected);
}
@ -129,7 +129,7 @@ public:
{
auto wb = workbook_with_styles();
auto ws = wb["Sheet1"];
auto code = ws.get_cell("A5").get_style().get_number_format().get_format_code();
auto code = ws.get_cell("A5").get_number_format().get_format_code();
auto expected = xlnt::number_format::format::percentage_00;
TS_ASSERT_EQUALS(code, expected);
}
@ -162,14 +162,14 @@ public:
{
auto wb = date_std_1900();
auto ws = wb["Sheet1"];
TS_ASSERT_EQUALS(ws.get_cell("A1").get_style().get_number_format().get_format_code(), xlnt::number_format::format::date_xlsx14);
TS_ASSERT_EQUALS(ws.get_cell("A1").get_number_format().get_format_code(), xlnt::number_format::format::date_xlsx14);
}
void test_read_date_style_mac()
{
auto wb = date_mac_1904();
auto ws = wb["Sheet1"];
TS_ASSERT_EQUALS(ws.get_cell("A1").get_style().get_number_format().get_format_code(), xlnt::number_format::format::date_xlsx14);
TS_ASSERT_EQUALS(ws.get_cell("A1").get_number_format().get_format_code(), xlnt::number_format::format::date_xlsx14);
}
void test_read_compare_mac_win_dates()

View File

@ -16,7 +16,7 @@ public:
xlnt::workbook wbk;
wbk.get_active_sheet().get_cell("A2").set_value("xlnt");
wbk.get_active_sheet().get_cell("B5").set_value(88);
wbk.get_active_sheet().get_cell("B5").get_style().set_number_format(xlnt::number_format(xlnt::number_format::format::percentage_00));
wbk.get_active_sheet().get_cell("B5").set_number_format(xlnt::number_format(xlnt::number_format::format::percentage_00));
wbk.save(temp_file.GetFilename());
if(PathHelper::FileExists(temp_file.GetFilename()))
@ -97,17 +97,6 @@ public:
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_formula.xml", content));
}
void test_write_style()
{
xlnt::workbook wb_guess_types;
wb_guess_types.set_guess_types(true);
auto ws = wb_guess_types.create_sheet();
ws.get_cell("F1").set_value("13%");
auto style_id_by_hash = xlnt::style_writer(wb_guess_types).get_style_by_hash();
auto content = xlnt::write_worksheet(ws, {}, style_id_by_hash);
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_style.xml", content));
}
void test_write_height()
{
auto ws = wb_.create_sheet();