Merge branch 'tasmail-master-shared-strings-performance' into dev

remove less than comparators

fix conflicts
This commit is contained in:
Thomas Fussell 2018-07-22 23:51:33 -04:00
commit 0af7ad88e1
15 changed files with 542 additions and 252 deletions

View File

@ -22,7 +22,9 @@
// @author: see AUTHORS file // @author: see AUTHORS file
#include <chrono> #include <chrono>
#include <string>
#include <iostream> #include <iostream>
#include <sstream>
#include <iterator> #include <iterator>
#include <random> #include <random>
@ -41,119 +43,135 @@ std::size_t random_index(std::size_t max)
return dis(gen); return dis(gen);
} }
std::vector<xlnt::style> generate_all_styles(xlnt::workbook &wb) void generate_all_formats(xlnt::workbook &wb, std::vector<xlnt::format>& formats)
{ {
std::vector<xlnt::style> styles; const auto vertical_alignments = std::vector<xlnt::vertical_alignment>
{
xlnt::vertical_alignment::center,
xlnt::vertical_alignment::justify,
xlnt::vertical_alignment::top,
xlnt::vertical_alignment::bottom
};
const auto vertical_alignments = std::vector<xlnt::vertical_alignment> const auto horizontal_alignments = std::vector<xlnt::horizontal_alignment>
{ {
xlnt::vertical_alignment::center, xlnt::horizontal_alignment::center,
xlnt::vertical_alignment::justify, xlnt::horizontal_alignment::center_continuous,
xlnt::vertical_alignment::top, xlnt::horizontal_alignment::general,
xlnt::vertical_alignment::bottom xlnt::horizontal_alignment::justify,
}; xlnt::horizontal_alignment::left,
xlnt::horizontal_alignment::right
};
const auto horizontal_alignments = std::vector<xlnt::horizontal_alignment> const auto font_names = std::vector<std::string>
{ {
xlnt::horizontal_alignment::center, "Calibri",
xlnt::horizontal_alignment::center_continuous, "Tahoma",
xlnt::horizontal_alignment::general, "Arial",
xlnt::horizontal_alignment::justify, "Times New Roman"
xlnt::horizontal_alignment::left, };
xlnt::horizontal_alignment::right
};
const auto font_names = std::vector<std::string> const auto font_sizes = std::vector<double>
{ {
"Calibri", 11.,
"Tahoma", 13.,
"Arial", 15.,
"Times New Roman" 17.,
}; 19.,
21.,
23.,
25.,
27.,
29.,
31.,
33.,
35.
};
const auto font_sizes = std::vector<double> const auto underline_options = std::vector<xlnt::font::underline_style>
{ {
11., xlnt::font::underline_style::single,
13., xlnt::font::underline_style::none
15., };
17.,
19.,
21.,
23.,
25.,
27.,
29.,
31.,
33.,
35.
};
const auto underline_options = std::vector<xlnt::font::underline_style> for (auto vertical_alignment : vertical_alignments)
{ {
xlnt::font::underline_style::single, for (auto horizontal_alignment : horizontal_alignments)
xlnt::font::underline_style::none {
}; for (auto name : font_names)
{
for (auto size : font_sizes)
{
for (auto bold : { true, false })
{
for (auto underline : underline_options)
{
for (auto italic : { true, false })
{
auto fmt = wb.create_format();
std::size_t index = 0; xlnt::font f;
f.name(name);
f.size(size);
f.italic(italic);
f.underline(underline);
f.bold(bold);
fmt.font(f);
for (auto vertical_alignment : vertical_alignments) xlnt::alignment a;
{ a.vertical(vertical_alignment);
for (auto horizontal_alignment : horizontal_alignments) a.horizontal(horizontal_alignment);
{ fmt.alignment(a);
for (auto name : font_names)
{
for (auto size : font_sizes)
{
for (auto bold : { true, false })
{
for (auto underline : underline_options)
{
for (auto italic : { true, false })
{
auto s = wb.create_style(std::to_string(index++));
xlnt::font f; formats.push_back(fmt);
f.name(name); }
f.size(size); }
f.italic(italic); }
f.underline(underline); }
f.bold(bold); }
s.font(f); }
}
xlnt::alignment a;
a.vertical(vertical_alignment);
a.horizontal(horizontal_alignment);
s.alignment(a);
styles.push_back(s);
}
}
}
}
}
}
}
return styles;
} }
xlnt::workbook non_optimized_workbook(int n)
xlnt::workbook non_optimized_workbook_formats(int rows_number, int columns_number)
{ {
xlnt::workbook wb; using xlnt::benchmarks::current_time;
auto styles = generate_all_styles(wb);
for(int idx = 1; idx < n; idx++) xlnt::workbook wb;
{ std::vector<xlnt::format> formats;
auto worksheet = wb[random_index(wb.sheet_count())]; auto start = current_time();
auto cell = worksheet.cell(xlnt::cell_reference(1, (xlnt::row_t)idx));
cell.value(0);
cell.style(styles.at(random_index(styles.size())));
}
return wb; generate_all_formats(wb, formats);
auto elapsed = current_time() - start;
std::cout << "elapsed " << elapsed / 1000.0 << ". generate_all_formats. number of unique formats " << formats.size() << std::endl;
start = current_time();
auto worksheet = wb[random_index(wb.sheet_count())];
auto cells_proceeded = 0;
for (int row_idx = 1; row_idx <= rows_number; row_idx++)
{
for (int col_idx = 1; col_idx <= columns_number; col_idx++)
{
auto cell = worksheet.cell(xlnt::cell_reference((xlnt::column_t)col_idx, (xlnt::row_t)row_idx));
std::ostringstream string_stm;
string_stm << "Col: " << col_idx << "Row: " << row_idx;
cell.value(string_stm.str());
cell.format(formats.at(random_index(formats.size())));
cells_proceeded++;
}
}
elapsed = current_time() - start;
std::cout << "elapsed " << elapsed / 1000.0 << ". set values and formats for cells. cells proceeded " << cells_proceeded << std::endl;
return wb;
} }
void to_profile(xlnt::workbook &wb, const std::string &f, int n) void to_save_profile(xlnt::workbook &wb, const std::string &f)
{ {
using xlnt::benchmarks::current_time; using xlnt::benchmarks::current_time;
@ -161,17 +179,72 @@ void to_profile(xlnt::workbook &wb, const std::string &f, int n)
wb.save(f); wb.save(f);
auto elapsed = current_time() - start; auto elapsed = current_time() - start;
std::cout << "took " << elapsed / 1000.0 << "s for " << n << " styles" << std::endl; std::cout << "elapsed " << elapsed / 1000.0 << ". save workbook." << std::endl;
}
void to_load_profile(xlnt::workbook &wb, const std::string &f)
{
using xlnt::benchmarks::current_time;
auto start = current_time();
wb.load(f);
auto elapsed = current_time() - start;
std::cout << "elapsed " << elapsed / 1000.0 << ". load workbook." << std::endl;
}
void read_formats_profile(xlnt::workbook &wb, int rows_number, int columns_number)
{
using xlnt::benchmarks::current_time;
std::vector<std::string> values;
std::vector<xlnt::format> formats;
auto start = current_time();
auto worksheet = wb[random_index(wb.sheet_count())];
for (int row_idx = 1; row_idx <= rows_number; row_idx++)
{
for (int col_idx = 1; col_idx <= columns_number; col_idx++)
{
auto cell = worksheet.cell(xlnt::cell_reference((xlnt::column_t)col_idx, (xlnt::row_t)row_idx));
values.push_back(cell.value<std::string>());
formats.push_back(cell.format());
}
}
auto elapsed = current_time() - start;
std::cout << "elapsed " << elapsed / 1000.0 << ". read values and formats for cells. values count " << values.size()
<< ". formats count " << formats.size() << std::endl;
} }
} // namespace } // namespace
int main() int main(int argc, char * argv[])
{ {
int n = 10000; int rows_number = 1000;
auto wb = non_optimized_workbook(n); int columns_number = 10;
std::string f = "temp.xlsx";
to_profile(wb, f, n); try
{
if (argc > 1)
rows_number = std::stoi(argv[1]);
if (argc > 2)
columns_number = std::stoi(argv[2]);
std::cout << "started. number of rows " << rows_number << ", number of columns " << columns_number << std::endl;
auto wb = non_optimized_workbook_formats(rows_number, columns_number);
auto f = "temp-formats.xlsx";
to_save_profile(wb, f);
xlnt::workbook load_formats_wb;
to_load_profile(load_formats_wb, f);
read_formats_profile(load_formats_wb, rows_number, columns_number);
}
catch(std::exception& ex)
{
std::cout << "failed. " << ex.what() << std::endl;
}
return 0; return 0;
} }

View File

@ -48,6 +48,11 @@ public:
/// </summary> /// </summary>
rich_text(const std::string &plain_text); rich_text(const std::string &plain_text);
/// <summary>
/// Constructs a rich text object from other
/// </summary>
rich_text(const rich_text &other);
/// <summary> /// <summary>
/// Constructs a rich text object with the given text and font. /// Constructs a rich text object with the given text and font.
/// </summary> /// </summary>
@ -89,6 +94,11 @@ public:
/// </summary> /// </summary>
void add_run(const rich_text_run &t); void add_run(const rich_text_run &t);
/// <summary>
/// Copies rich text object from other
/// </summary>
rich_text& operator=(const rich_text &rhs);
/// <summary> /// <summary>
/// Returns true if the runs that make up this text are identical to those in rhs. /// Returns true if the runs that make up this text are identical to those in rhs.
/// </summary> /// </summary>
@ -97,7 +107,7 @@ public:
/// <summary> /// <summary>
/// Returns true if the runs that make up this text are identical to those in rhs. /// Returns true if the runs that make up this text are identical to those in rhs.
/// </summary> /// </summary>
bool operator!=(const rich_text &rhs) const; bool operator!=(const rich_text &rhs) const;
/// <summary> /// <summary>
/// Returns true if this text has a single unformatted run with text equal to rhs. /// Returns true if this text has a single unformatted run with text equal to rhs.
@ -116,4 +126,20 @@ private:
std::vector<rich_text_run> runs_; std::vector<rich_text_run> runs_;
}; };
class XLNT_API rich_text_hash
{
public:
std::size_t operator()(const rich_text& k) const
{
std::size_t res = 0;
for (auto r : k.runs())
{
res ^= std::hash<std::string>()(r.first);
}
return res;
}
};
} // namespace xlnt } // namespace xlnt

View File

@ -101,7 +101,7 @@ public:
/// <summary> /// <summary>
/// Constructs an RGB color from red, green, and blue values in the range 0 to 255 /// Constructs an RGB color from red, green, and blue values in the range 0 to 255
/// plus an optional alpha which defaults to fully opaque. /// plus an optional alpha which defaults to fully opaque.
/// </summary> /// </summary>
rgb_color(std::uint8_t r, std::uint8_t g, std::uint8_t b, std::uint8_t a = 255); rgb_color(std::uint8_t r, std::uint8_t g, std::uint8_t b, std::uint8_t a = 255);
@ -116,17 +116,17 @@ public:
std::uint8_t red() const; std::uint8_t red() const;
/// <summary> /// <summary>
/// Returns a byte representing the red component of this color /// Returns a byte representing the red component of this color
/// </summary> /// </summary>
std::uint8_t green() const; std::uint8_t green() const;
/// <summary> /// <summary>
/// Returns a byte representing the blue component of this color /// Returns a byte representing the blue component of this color
/// </summary> /// </summary>
std::uint8_t blue() const; std::uint8_t blue() const;
/// <summary> /// <summary>
/// Returns a byte representing the alpha component of this color /// Returns a byte representing the alpha component of this color
/// </summary> /// </summary>
std::uint8_t alpha() const; std::uint8_t alpha() const;
@ -136,7 +136,7 @@ public:
std::array<std::uint8_t, 3> rgb() const; std::array<std::uint8_t, 3> rgb() const;
/// <summary> /// <summary>
/// Returns the red, green, blue, and alpha components of this color separately in an array in that order. /// Returns the red, green, blue, and alpha components of this color separately in an array in that order.
/// </summary> /// </summary>
std::array<std::uint8_t, 4> rgba() const; std::array<std::uint8_t, 4> rgba() const;
@ -174,42 +174,42 @@ public:
static const color white(); static const color white();
/// <summary> /// <summary>
/// Returns the color \#ff0000 /// Returns the color \#ff0000
/// </summary> /// </summary>
static const color red(); static const color red();
/// <summary> /// <summary>
/// Returns the color \#8b0000 /// Returns the color \#8b0000
/// </summary> /// </summary>
static const color darkred(); static const color darkred();
/// <summary> /// <summary>
/// Returns the color \#00ff00 /// Returns the color \#00ff00
/// </summary> /// </summary>
static const color blue(); static const color blue();
/// <summary> /// <summary>
/// Returns the color \#008b00 /// Returns the color \#008b00
/// </summary> /// </summary>
static const color darkblue(); static const color darkblue();
/// <summary> /// <summary>
/// Returns the color \#0000ff /// Returns the color \#0000ff
/// </summary> /// </summary>
static const color green(); static const color green();
/// <summary> /// <summary>
/// Returns the color \#00008b /// Returns the color \#00008b
/// </summary> /// </summary>
static const color darkgreen(); static const color darkgreen();
/// <summary> /// <summary>
/// Returns the color \#ffff00 /// Returns the color \#ffff00
/// </summary> /// </summary>
static const color yellow(); static const color yellow();
/// <summary> /// <summary>
/// Returns the color \#cccc00 /// Returns the color \#cccc00
/// </summary> /// </summary>
static const color darkyellow(); static const color darkyellow();
@ -249,8 +249,8 @@ public:
void auto_(bool value); void auto_(bool value);
/// <summary> /// <summary>
/// Returns the internal indexed color representing this color. If this is not an RGB color, /// Returns the internal indexed color representing this color. If this is not an RGB color,
/// an invalid_attribute exception will be thrown. /// an invalid_attribute exception will be thrown.
/// </summary> /// </summary>
const rgb_color& rgb() const; const rgb_color& rgb() const;
@ -262,7 +262,7 @@ public:
/// <summary> /// <summary>
/// Returns the internal indexed color representing this color. If this is not an indexed color, /// Returns the internal indexed color representing this color. If this is not an indexed color,
/// an invalid_attribute exception will be thrown. /// an invalid_attribute exception will be thrown.
/// </summary> /// </summary>
const indexed_color& indexed() const; const indexed_color& indexed() const;
@ -273,8 +273,8 @@ public:
indexed_color &indexed(); indexed_color &indexed();
/// <summary> /// <summary>
/// Returns the internal indexed color representing this color. If this is not a theme color, /// Returns the internal indexed color representing this color. If this is not a theme color,
/// an invalid_attribute exception will be thrown. /// an invalid_attribute exception will be thrown.
/// </summary> /// </summary>
const theme_color& theme() const; const theme_color& theme() const;
@ -294,15 +294,15 @@ public:
/// </summary> /// </summary>
void tint(double tint); void tint(double tint);
/// <summary> /// <summary>
/// Returns true if this color is equivalent to other /// Returns true if this color is equivalent to other
/// </summary> /// </summary>
bool operator==(const color &other) const; bool operator==(const color &other) const;
/// <summary> /// <summary>
/// Returns true if this color is not equivalent to other /// Returns true if this color is not equivalent to other
/// </summary> /// </summary>
bool operator!=(const color &other) const; bool operator!=(const color &other) const;
private: private:
/// <summary> /// <summary>
@ -321,12 +321,12 @@ private:
rgb_color rgb_; rgb_color rgb_;
/// <summary> /// <summary>
/// The internal RGB color. Only valid when this color has a type of indexed /// The internal RGB color. Only valid when this color has a type of indexed
/// </summary> /// </summary>
indexed_color indexed_; indexed_color indexed_;
/// <summary> /// <summary>
/// The internal RGB color. Only valid when this color has a type of theme /// The internal RGB color. Only valid when this color has a type of theme
/// </summary> /// </summary>
theme_color theme_; theme_color theme_;

View File

@ -314,4 +314,4 @@ private:
#undef XLNT_NOEXCEPT_VALUE_COMPAT #undef XLNT_NOEXCEPT_VALUE_COMPAT
#endif #endif
} // namespace xlnt } // namespace xlnt

View File

@ -33,6 +33,7 @@
#include <vector> #include <vector>
#include <xlnt/xlnt_config.hpp> #include <xlnt/xlnt_config.hpp>
#include <xlnt/cell/rich_text.hpp>
namespace xlnt { namespace xlnt {
@ -700,10 +701,10 @@ public:
/// </summary> /// </summary>
class style create_style(const std::string &name); class style create_style(const std::string &name);
/// <summary> /// <summary>
/// Creates a new style and returns it. /// Creates a new style and returns it.
/// </summary> /// </summary>
class style create_builtin_style(std::size_t builtin_id); class style create_builtin_style(std::size_t builtin_id);
/// <summary> /// <summary>
/// Clear all named styles from cells and remove the styles from /// Clear all named styles from cells and remove the styles from
@ -759,17 +760,27 @@ public:
/// </summary> /// </summary>
std::size_t add_shared_string(const rich_text &shared, bool allow_duplicates = false); std::size_t add_shared_string(const rich_text &shared, bool allow_duplicates = false);
/// <summary> /// <summary>
/// Returns a reference to the shared strings being used by cells /// Returns a reference to the shared string ordered by id
/// in this workbook. /// </summary>
/// </summary> const std::unordered_map<std::size_t, rich_text> &shared_strings_by_id() const;
std::vector<rich_text> &shared_strings();
/// <summary>
/// Returns a reference to the shared string related to the specified index
/// </summary>
const rich_text &shared_strings(std::size_t index) const;
/// <summary> /// <summary>
/// Returns a reference to the shared strings being used by cells /// Returns a reference to the shared strings being used by cells
/// in this workbook. /// in this workbook.
/// </summary> /// </summary>
const std::vector<rich_text> &shared_strings() const; std::unordered_map<rich_text, std::size_t, rich_text_hash> &shared_strings();
/// <summary>
/// Returns a reference to the shared strings being used by cells
/// in this workbook.
/// </summary>
const std::unordered_map<rich_text, std::size_t, rich_text_hash> &shared_strings() const;
// Thumbnail // Thumbnail

View File

@ -704,7 +704,7 @@ XLNT_API rich_text cell::value() const
{ {
if (data_type() == cell::type::shared_string) if (data_type() == cell::type::shared_string)
{ {
return workbook().shared_strings().at(static_cast<std::size_t>(d_->value_numeric_)); return workbook().shared_strings(static_cast<std::size_t>(d_->value_numeric_));
} }
return d_->value_text_; return d_->value_text_;
@ -861,19 +861,19 @@ style cell::style()
throw invalid_attribute(); throw invalid_attribute();
} }
auto f = format(); auto f = format();
return f.style(); return f.style();
} }
const style cell::style() const const style cell::style() const
{ {
if (!has_format() || !format().has_style()) if (!has_format() || !format().has_style())
{ {
throw invalid_attribute(); throw invalid_attribute();
} }
return format().style(); return format().style();
} }
bool cell::has_style() const bool cell::has_style() const

View File

@ -45,6 +45,18 @@ rich_text::rich_text(const std::string &plain_text, const class font &text_font)
{ {
} }
rich_text::rich_text(const rich_text &other)
{
*this = other;
}
rich_text &rich_text::operator=(const rich_text &rhs)
{
runs_.clear();
runs_ = rhs.runs_;
return *this;
}
rich_text::rich_text(const rich_text_run &single_run) rich_text::rich_text(const rich_text_run &single_run)
{ {
add_run(single_run); add_run(single_run);
@ -63,6 +75,11 @@ void rich_text::plain_text(const std::string &s, bool preserve_space = false)
std::string rich_text::plain_text() const std::string rich_text::plain_text() const
{ {
if (runs_.size() == 1)
{
return runs_.begin()->first;
}
return std::accumulate(runs_.begin(), runs_.end(), std::string(), return std::accumulate(runs_.begin(), runs_.end(), std::string(),
[](const std::string &a, const rich_text_run &run) { return a + run.first; }); [](const std::string &a, const rich_text_run &run) { return a + run.first; });
} }

View File

@ -547,7 +547,6 @@ std::string encode_header_footer(const rich_text &t, header_footer::location whe
case font::underline_style::double_accounting: case font::underline_style::double_accounting:
encoded.append("&E"); encoded.append("&E");
break; break;
default:
case font::underline_style::none: case font::underline_style::none:
break; break;
} }

View File

@ -47,14 +47,15 @@ struct worksheet_impl;
struct workbook_impl struct workbook_impl
{ {
workbook_impl() : base_date_(calendar::windows_1900) workbook_impl() : base_date_(calendar::windows_1900)
{ {
} }
workbook_impl(const workbook_impl &other) workbook_impl(const workbook_impl &other)
: active_sheet_index_(other.active_sheet_index_), : active_sheet_index_(other.active_sheet_index_),
worksheets_(other.worksheets_), worksheets_(other.worksheets_),
shared_strings_(other.shared_strings_), shared_strings_ids_(other.shared_strings_ids_),
shared_strings_values_(other.shared_strings_values_),
stylesheet_(other.stylesheet_), stylesheet_(other.stylesheet_),
manifest_(other.manifest_), manifest_(other.manifest_),
theme_(other.theme_), theme_(other.theme_),
@ -72,15 +73,15 @@ struct workbook_impl
active_sheet_index_ = other.active_sheet_index_; active_sheet_index_ = other.active_sheet_index_;
worksheets_.clear(); worksheets_.clear();
std::copy(other.worksheets_.begin(), other.worksheets_.end(), back_inserter(worksheets_)); std::copy(other.worksheets_.begin(), other.worksheets_.end(), back_inserter(worksheets_));
shared_strings_.clear(); shared_strings_ids_ = other.shared_strings_ids_;
std::copy(other.shared_strings_.begin(), other.shared_strings_.end(), std::back_inserter(shared_strings_)); shared_strings_values_ = other.shared_strings_values_;
theme_ = other.theme_; theme_ = other.theme_;
manifest_ = other.manifest_; manifest_ = other.manifest_;
sheet_title_rel_id_map_ = other.sheet_title_rel_id_map_; sheet_title_rel_id_map_ = other.sheet_title_rel_id_map_;
view_ = other.view_; view_ = other.view_;
code_name_ = other.code_name_; code_name_ = other.code_name_;
file_version_ = other.file_version_; file_version_ = other.file_version_;
core_properties_ = other.core_properties_; core_properties_ = other.core_properties_;
extended_properties_ = other.extended_properties_; extended_properties_ = other.extended_properties_;
@ -116,13 +117,14 @@ struct workbook_impl
optional<std::size_t> active_sheet_index_; optional<std::size_t> active_sheet_index_;
std::list<worksheet_impl> worksheets_; std::list<worksheet_impl> worksheets_;
std::vector<rich_text> shared_strings_; std::unordered_map<rich_text, std::size_t, rich_text_hash> shared_strings_ids_;
std::unordered_map<std::size_t, rich_text> shared_strings_values_;
optional<stylesheet> stylesheet_; optional<stylesheet> stylesheet_;
calendar base_date_; calendar base_date_;
optional<std::string> title_; optional<std::string> title_;
manifest manifest_; manifest manifest_;
optional<theme> theme_; optional<theme> theme_;
std::unordered_map<std::string, std::vector<std::uint8_t>> images_; std::unordered_map<std::string, std::vector<std::uint8_t>> images_;
@ -131,11 +133,12 @@ struct workbook_impl
std::vector<std::pair<xlnt::extended_property, variant>> extended_properties_; std::vector<std::pair<xlnt::extended_property, variant>> extended_properties_;
std::vector<std::pair<std::string, variant>> custom_properties_; std::vector<std::pair<std::string, variant>> custom_properties_;
std::unordered_map<std::string, std::string> sheet_title_rel_id_map_; std::unordered_map<std::string, std::string> sheet_title_rel_id_map_;
optional<workbook_view> view_; optional<workbook_view> view_;
optional<std::string> code_name_; optional<std::string> code_name_;
<<<<<<< Updated upstream
struct file_version_t struct file_version_t
{ {
std::string app_name; std::string app_name;
@ -152,6 +155,16 @@ struct workbook_impl
} }
}; };
=======
struct file_version_t
{
std::string app_name;
std::size_t last_edited;
std::size_t lowest_edited;
std::size_t rup_build;
};
>>>>>>> Stashed changes
optional<file_version_t> file_version_; optional<file_version_t> file_version_;
optional<calculation_properties> calculation_properties_; optional<calculation_properties> calculation_properties_;
optional<std::string> abs_path_; optional<std::string> abs_path_;

View File

@ -246,7 +246,11 @@ cell xlsx_consumer::read_cell()
if (parser().attribute_present("s")) if (parser().attribute_present("s"))
{ {
<<<<<<< Updated upstream
cell.format(target_.format(static_cast<std::size_t>(std::stoull(parser().attribute("s"))))); cell.format(target_.format(static_cast<std::size_t>(std::stoull(parser().attribute("s")))));
=======
cell.format(target_.format(std::stoull(parser().attribute("s"))));
>>>>>>> Stashed changes
} }
auto has_value = false; auto has_value = false;
@ -536,12 +540,15 @@ std::string xlsx_consumer::read_worksheet_begin(const std::string &rel_id)
current_selection.active_cell(parser().attribute("activeCell")); current_selection.active_cell(parser().attribute("activeCell"));
} }
<<<<<<< Updated upstream
if (parser().attribute_present("sqref")) if (parser().attribute_present("sqref"))
{ {
const auto sqref = range_reference(parser().attribute("sqref")); const auto sqref = range_reference(parser().attribute("sqref"));
current_selection.sqref(sqref); current_selection.sqref(sqref);
} }
=======
>>>>>>> Stashed changes
current_selection.pane(pane_corner::top_left); current_selection.pane(pane_corner::top_left);
new_view.add_selection(current_selection); new_view.add_selection(current_selection);
@ -727,7 +734,11 @@ void xlsx_consumer::read_worksheet_sheetdata()
if (parser().attribute_present("s")) if (parser().attribute_present("s"))
{ {
<<<<<<< Updated upstream
cell.format(target_.format(static_cast<std::size_t>(std::stoull(parser().attribute("s"))))); cell.format(target_.format(static_cast<std::size_t>(std::stoull(parser().attribute("s")))));
=======
cell.format(target_.format(std::stoull(parser().attribute("s"))));
>>>>>>> Stashed changes
} }
auto has_value = false; auto has_value = false;
@ -1021,14 +1032,14 @@ worksheet xlsx_consumer::read_worksheet_end(const std::string &rel_id)
{ {
header_footer hf; header_footer hf;
hf.align_with_margins( hf.align_with_margins(!parser().attribute_present("alignWithMargins")
!parser().attribute_present("alignWithMargins") || is_true(parser().attribute("alignWithMargins"))); || is_true(parser().attribute("alignWithMargins")));
hf.scale_with_doc( hf.scale_with_doc(!parser().attribute_present("alignWithMargins")
!parser().attribute_present("alignWithMargins") || is_true(parser().attribute("alignWithMargins"))); || is_true(parser().attribute("alignWithMargins")));
auto different_odd_even = auto different_odd_even = parser().attribute_present("differentOddEven")
parser().attribute_present("differentOddEven") && is_true(parser().attribute("differentOddEven")); && is_true(parser().attribute("differentOddEven"));
auto different_first = auto different_first = parser().attribute_present("differentFirst")
parser().attribute_present("differentFirst") && is_true(parser().attribute("differentFirst")); && is_true(parser().attribute("differentFirst"));
optional<std::array<optional<rich_text>, 3>> odd_header; optional<std::array<optional<rich_text>, 3>> odd_header;
optional<std::array<optional<rich_text>, 3>> odd_footer; optional<std::array<optional<rich_text>, 3>> odd_footer;
@ -1082,13 +1093,17 @@ worksheet xlsx_consumer::read_worksheet_end(const std::string &rel_id)
if (different_odd_even) if (different_odd_even)
{ {
if (odd_header.is_set() && odd_header.get().at(i).is_set() && even_header.is_set() if (odd_header.is_set()
&& odd_header.get().at(i).is_set()
&& even_header.is_set()
&& even_header.get().at(i).is_set()) && even_header.get().at(i).is_set())
{ {
hf.odd_even_header(loc, odd_header.get().at(i).get(), even_header.get().at(i).get()); hf.odd_even_header(loc, odd_header.get().at(i).get(), even_header.get().at(i).get());
} }
if (odd_footer.is_set() && odd_footer.get().at(i).is_set() && even_footer.is_set() if (odd_footer.is_set()
&& odd_footer.get().at(i).is_set()
&& even_footer.is_set()
&& even_footer.get().at(i).is_set()) && even_footer.get().at(i).is_set())
{ {
hf.odd_even_footer(loc, odd_footer.get().at(i).get(), even_footer.get().at(i).get()); hf.odd_even_footer(loc, odd_footer.get().at(i).get(), even_footer.get().at(i).get());
@ -1915,18 +1930,17 @@ void xlsx_consumer::read_shared_string_table()
unique_count = parser().attribute<std::size_t>("uniqueCount"); unique_count = parser().attribute<std::size_t>("uniqueCount");
} }
auto &strings = target_.shared_strings();
while (in_element(qn("spreadsheetml", "sst"))) while (in_element(qn("spreadsheetml", "sst")))
{ {
expect_start_element(qn("spreadsheetml", "si"), xml::content::complex); expect_start_element(qn("spreadsheetml", "si"), xml::content::complex);
strings.push_back(read_rich_text(qn("spreadsheetml", "si"))); auto rt = read_rich_text(qn("spreadsheetml", "si"));
target_.add_shared_string(rt);
expect_end_element(qn("spreadsheetml", "si")); expect_end_element(qn("spreadsheetml", "si"));
} }
expect_end_element(qn("spreadsheetml", "sst")); expect_end_element(qn("spreadsheetml", "sst"));
if (has_unique_count && unique_count != strings.size()) if (has_unique_count && unique_count != target_.shared_strings().size())
{ {
throw invalid_file("sizes don't match"); throw invalid_file("sizes don't match");
} }

View File

@ -850,15 +850,17 @@ void xlsx_producer::write_shared_string_table(const relationship & /*rel*/)
#pragma clang diagnostic pop #pragma clang diagnostic pop
write_attribute("count", string_count); write_attribute("count", string_count);
write_attribute("uniqueCount", source_.shared_strings().size()); write_attribute("uniqueCount", source_.shared_strings_by_id().size());
for (const auto &string : source_.shared_strings()) for (const auto &string : source_.shared_strings_by_id())
{ {
if (string.runs().size() == 1 && !string.runs().at(0).second.is_set()) if (string.second.runs().size() == 1 && !string.second.runs().at(0).second.is_set())
{ {
write_start_element(xmlns, "si"); write_start_element(xmlns, "si");
write_start_element(xmlns, "t"); write_start_element(xmlns, "t");
write_characters(string.plain_text(), string.runs().front().preserve_space);
write_characters(string.second.plain_text(), string.second.runs().front().preserve_space);
write_end_element(xmlns, "t"); write_end_element(xmlns, "t");
write_end_element(xmlns, "si"); write_end_element(xmlns, "si");
@ -867,7 +869,7 @@ void xlsx_producer::write_shared_string_table(const relationship & /*rel*/)
write_start_element(xmlns, "si"); write_start_element(xmlns, "si");
for (const auto &run : string.runs()) for (const auto &run : string.second.runs())
{ {
write_start_element(xmlns, "r"); write_start_element(xmlns, "r");
@ -2164,7 +2166,7 @@ void xlsx_producer::write_worksheet(const relationship &rel)
})->first; })->first;
auto ws = source_.sheet_by_title(title); auto ws = source_.sheet_by_title(title);
write_start_element(xmlns, "worksheet"); write_start_element(xmlns, "worksheet");
write_namespace(xmlns, ""); write_namespace(xmlns, "");
write_namespace(xmlns_r, "r"); write_namespace(xmlns_r, "r");
@ -2372,7 +2374,7 @@ void xlsx_producer::write_worksheet(const relationship &rel)
for (auto column = first_column; column <= last_column; column++) for (auto column = first_column; column <= last_column; column++)
{ {
if (!ws.has_column_properties(column)) continue; if (!ws.has_column_properties(column)) continue;
if(!has_column_properties) if(!has_column_properties)
{ {
write_start_element(xmlns, "cols"); write_start_element(xmlns, "cols");

View File

@ -32,14 +32,14 @@ namespace {
std::array<std::uint8_t, 4> decode_hex_string(const std::string &hex_string) std::array<std::uint8_t, 4> decode_hex_string(const std::string &hex_string)
{ {
auto x = std::strtoul(hex_string.c_str(), nullptr, 16); auto x = std::strtoul(hex_string.c_str(), nullptr, 16);
auto a = static_cast<std::uint8_t>(x >> 24); auto a = static_cast<std::uint8_t>(x >> 24);
auto r = static_cast<std::uint8_t>((x >> 16) & 0xff); auto r = static_cast<std::uint8_t>((x >> 16) & 0xff);
auto g = static_cast<std::uint8_t>((x >> 8) & 0xff); auto g = static_cast<std::uint8_t>((x >> 8) & 0xff);
auto b = static_cast<std::uint8_t>(x & 0xff); auto b = static_cast<std::uint8_t>(x & 0xff);
return { { r, g, b, a } }; return { { r, g, b, a } };
} }
} // namespace } // namespace
@ -54,7 +54,7 @@ indexed_color::indexed_color(std::size_t index) : index_(index)
std::size_t indexed_color::index() const std::size_t indexed_color::index() const
{ {
return index_; return index_;
} }
void indexed_color::index(std::size_t index) void indexed_color::index(std::size_t index)
@ -70,7 +70,7 @@ theme_color::theme_color(std::size_t index) : index_(index)
std::size_t theme_color::index() const std::size_t theme_color::index() const
{ {
return index_; return index_;
} }
void theme_color::index(std::size_t index) void theme_color::index(std::size_t index)
@ -110,84 +110,84 @@ rgb_color::rgb_color(std::uint8_t r, std::uint8_t g, std::uint8_t b, std::uint8_
std::uint8_t rgb_color::red() const std::uint8_t rgb_color::red() const
{ {
return rgba_[0]; return rgba_[0];
} }
std::uint8_t rgb_color::green() const std::uint8_t rgb_color::green() const
{ {
return rgba_[1]; return rgba_[1];
} }
std::uint8_t rgb_color::blue() const std::uint8_t rgb_color::blue() const
{ {
return rgba_[2]; return rgba_[2];
} }
std::uint8_t rgb_color::alpha() const std::uint8_t rgb_color::alpha() const
{ {
return rgba_[3]; return rgba_[3];
} }
std::array<std::uint8_t, 3> rgb_color::rgb() const std::array<std::uint8_t, 3> rgb_color::rgb() const
{ {
return {{red(), green(), blue()}}; return {{red(), green(), blue()}};
} }
std::array<std::uint8_t, 4> rgb_color::rgba() const std::array<std::uint8_t, 4> rgb_color::rgba() const
{ {
return rgba_; return rgba_;
} }
// color implementation // color implementation
const color color::black() const color color::black()
{ {
return color(rgb_color("ff000000")); return color(rgb_color("ff000000"));
} }
const color color::white() const color color::white()
{ {
return color(rgb_color("ffffffff")); return color(rgb_color("ffffffff"));
} }
const color color::red() const color color::red()
{ {
return color(rgb_color("ffff0000")); return color(rgb_color("ffff0000"));
} }
const color color::darkred() const color color::darkred()
{ {
return color(rgb_color("ff8b0000")); return color(rgb_color("ff8b0000"));
} }
const color color::blue() const color color::blue()
{ {
return color(rgb_color("ff0000ff")); return color(rgb_color("ff0000ff"));
} }
const color color::darkblue() const color color::darkblue()
{ {
return color(rgb_color("ff00008b")); return color(rgb_color("ff00008b"));
} }
const color color::green() const color color::green()
{ {
return color(rgb_color("ff00ff00")); return color(rgb_color("ff00ff00"));
} }
const color color::darkgreen() const color color::darkgreen()
{ {
return color(rgb_color("ff008b00")); return color(rgb_color("ff008b00"));
} }
const color color::yellow() const color color::yellow()
{ {
return color(rgb_color("ffffff00")); return color(rgb_color("ffffff00"));
} }
const color color::darkyellow() const color color::darkyellow()
{ {
return color(rgb_color("ffcccc00")); return color(rgb_color("ffcccc00"));
} }
color::color() : color(indexed_color(0)) color::color() : color(indexed_color(0))
@ -195,48 +195,48 @@ color::color() : color(indexed_color(0))
} }
color::color(const rgb_color &rgb) color::color(const rgb_color &rgb)
: type_(color_type::rgb), : type_(color_type::rgb),
rgb_(rgb), rgb_(rgb),
indexed_(0), indexed_(0),
theme_(0) theme_(0)
{ {
} }
color::color(const indexed_color &indexed) color::color(const indexed_color &indexed)
: type_(color_type::indexed), : type_(color_type::indexed),
rgb_(rgb_color(0, 0, 0, 0)), rgb_(rgb_color(0, 0, 0, 0)),
indexed_(indexed), indexed_(indexed),
theme_(0) theme_(0)
{ {
} }
color::color(const theme_color &theme) color::color(const theme_color &theme)
: type_(color_type::theme), : type_(color_type::theme),
rgb_(rgb_color(0, 0, 0, 0)), rgb_(rgb_color(0, 0, 0, 0)),
indexed_(0), indexed_(0),
theme_(theme) theme_(theme)
{ {
} }
color_type color::type() const color_type color::type() const
{ {
return type_; return type_;
} }
bool color::auto_() const bool color::auto_() const
{ {
return auto__; return auto__;
} }
void color::auto_(bool value) void color::auto_(bool value)
{ {
auto__ = value; auto__ = value;
} }
const indexed_color& color::indexed() const const indexed_color& color::indexed() const
{ {
assert_type(color_type::indexed); assert_type(color_type::indexed);
return indexed_; return indexed_;
} }
indexed_color &color::indexed() indexed_color &color::indexed()
@ -247,8 +247,8 @@ indexed_color &color::indexed()
const theme_color& color::theme() const const theme_color& color::theme() const
{ {
assert_type(color_type::theme); assert_type(color_type::theme);
return theme_; return theme_;
} }
theme_color &color::theme() theme_color &color::theme()
@ -276,7 +276,7 @@ void color::tint(double tint)
double color::tint() const double color::tint() const
{ {
return tint_; return tint_;
} }
void color::assert_type(color_type t) const void color::assert_type(color_type t) const
@ -309,7 +309,7 @@ bool color::operator==(const xlnt::color &other) const
bool color::operator!=(const color &other) const bool color::operator!=(const color &other) const
{ {
return !(*this == other); return !(*this == other);
} }
} // namespace xlnt } // namespace xlnt

View File

@ -23,6 +23,8 @@
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
#include <algorithm>
#include <iterator>
#include <sys/stat.h> #include <sys/stat.h>
#ifdef __APPLE__ #ifdef __APPLE__
@ -137,8 +139,8 @@ path::path()
} }
path::path(const std::string &path_string) path::path(const std::string &path_string)
: internal_(path_string)
{ {
std::remove_copy(path_string.begin(), path_string.end(), std::back_inserter(internal_), '\"');
} }
path::path(const std::string &path_string, char sep) path::path(const std::string &path_string, char sep)

View File

@ -473,11 +473,15 @@ workbook workbook::empty()
.color(theme_color(1)); .color(theme_color(1));
stylesheet.fonts.push_back(default_font); stylesheet.fonts.push_back(default_font);
<<<<<<< Updated upstream
wb.create_builtin_style(0) wb.create_builtin_style(0)
.border(default_border) .border(default_border)
.fill(default_fill) .fill(default_fill)
.font(default_font) .font(default_font)
.number_format(xlnt::number_format::general()); .number_format(xlnt::number_format::general());
=======
wb.create_builtin_style(0);
>>>>>>> Stashed changes
wb.create_format(true) wb.create_format(true)
.border(default_border) .border(default_border)
@ -1017,8 +1021,8 @@ void workbook::load(const std::wstring &filename, const std::string &password)
void workbook::remove_sheet(worksheet ws) void workbook::remove_sheet(worksheet ws)
{ {
auto match_iter = std::find_if( auto match_iter = std::find_if(d_->worksheets_.begin(), d_->worksheets_.end(),
d_->worksheets_.begin(), d_->worksheets_.end(), [=](detail::worksheet_impl &comp) { return &comp == ws.d_; }); [=](detail::worksheet_impl &comp) { return &comp == ws.d_; });
if (match_iter == d_->worksheets_.end()) if (match_iter == d_->worksheets_.end())
{ {
@ -1071,10 +1075,10 @@ worksheet workbook::create_sheet_with_rel(const std::string &title, const relati
auto workbook_rel = d_->manifest_.relationship(path("/"), relationship_type::office_document); auto workbook_rel = d_->manifest_.relationship(path("/"), relationship_type::office_document);
auto sheet_absoulute_path = workbook_rel.target().path().parent().append(rel.target().path()); auto sheet_absoulute_path = workbook_rel.target().path().parent().append(rel.target().path());
d_->manifest_.register_override_type( d_->manifest_.register_override_type(sheet_absoulute_path,
sheet_absoulute_path, "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"); "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml");
auto ws_rel = d_->manifest_.register_relationship( auto ws_rel = d_->manifest_.register_relationship(workbook_rel.target(),
workbook_rel.target(), relationship_type::worksheet, rel.target(), target_mode::internal); relationship_type::worksheet, rel.target(), target_mode::internal);
d_->sheet_title_rel_id_map_[title] = ws_rel; d_->sheet_title_rel_id_map_[title] = ws_rel;
update_sheet_properties(); update_sheet_properties();
@ -1332,39 +1336,53 @@ const manifest &workbook::manifest() const
return d_->manifest_; return d_->manifest_;
} }
std::vector<rich_text> &workbook::shared_strings() const std::unordered_map<std::size_t, rich_text> &workbook::shared_strings_by_id() const
{ {
return d_->shared_strings_; return d_->shared_strings_values_;
} }
const std::vector<rich_text> &workbook::shared_strings() const const rich_text& workbook::shared_strings(std::size_t index) const
{ {
return d_->shared_strings_; auto it = d_->shared_strings_values_.find(index);
if (it != d_->shared_strings_values_.end())
{
return it->second;
}
static rich_text empty;
return empty;
}
std::unordered_map<rich_text, std::size_t, rich_text_hash> &workbook::shared_strings()
{
return d_->shared_strings_ids_;
}
const std::unordered_map<rich_text, std::size_t, rich_text_hash> &workbook::shared_strings() const
{
return d_->shared_strings_ids_;
} }
std::size_t workbook::add_shared_string(const rich_text &shared, bool allow_duplicates) std::size_t workbook::add_shared_string(const rich_text &shared, bool allow_duplicates)
{ {
register_workbook_part(relationship_type::shared_string_table); register_workbook_part(relationship_type::shared_string_table);
auto index = std::size_t(0);
if (!allow_duplicates) if (!allow_duplicates)
{ {
// TODO: inefficient, use a set or something? auto it = d_->shared_strings_ids_.find(shared);
for (auto &s : d_->shared_strings_)
{
if (s == shared)
{
return index;
}
++index; if (it != d_->shared_strings_ids_.end())
{
return it->second;
} }
} }
d_->shared_strings_.push_back(shared); auto sz = d_->shared_strings_ids_.size();
d_->shared_strings_ids_[shared] = sz;
d_->shared_strings_values_[sz] = shared;
return index; return sz;
} }
bool workbook::contains(const std::string &sheet_title) const bool workbook::contains(const std::string &sheet_title) const

View File

@ -110,6 +110,7 @@ public:
const auto path = path_helper::test_file("3_default.xlsx"); const auto path = path_helper::test_file("3_default.xlsx");
xlnt_assert(workbook_matches_file(wb, path)); xlnt_assert(workbook_matches_file(wb, path));
} }
<<<<<<< Updated upstream:tests/workbook/serialization_test_suite.cpp
void test_produce_simple_excel() void test_produce_simple_excel()
{ {
@ -245,6 +246,103 @@ public:
sheet1.cell("A5").hyperlink("https://google.com/"); sheet1.cell("A5").hyperlink("https://google.com/");
sheet1.cell("A5").format(hyperlink_format); sheet1.cell("A5").format(hyperlink_format);
=======
void test_produce_simple_excel()
{
xlnt::workbook wb;
auto ws = wb.active_sheet();
auto bold_font = xlnt::font().bold(true);
ws.cell("A1").value("Type");
ws.cell("A1").font(bold_font);
ws.cell("B1").value("Value");
ws.cell("B1").font(bold_font);
ws.cell("A2").value("null");
ws.cell("B2").value(nullptr);
ws.cell("A3").value("bool (true)");
ws.cell("B3").value(true);
ws.cell("A4").value("bool (false)");
ws.cell("B4").value(false);
ws.cell("A5").value("number (int)");
ws.cell("B5").value(std::numeric_limits<int>::max());
ws.cell("A5").value("number (unsigned int)");
ws.cell("B5").value(std::numeric_limits<unsigned int>::max());
ws.cell("A6").value("number (long long int)");
ws.cell("B6").value(std::numeric_limits<long long int>::max());
ws.cell("A6").value("number (unsigned long long int)");
ws.cell("B6").value(std::numeric_limits<unsigned long long int>::max());
ws.cell("A13").value("number (float)");
ws.cell("B13").value(std::numeric_limits<float>::max());
ws.cell("A14").value("number (double)");
ws.cell("B14").value(std::numeric_limits<double>::max());
ws.cell("A16").value("text (char *)");
ws.cell("B16").value("string");
ws.cell("A17").value("text (std::string)");
ws.cell("B17").value(std::string("string"));
ws.cell("A18").value("date");
ws.cell("B18").value(xlnt::date(2016, 2, 3));
ws.cell("A19").value("time");
ws.cell("B19").value(xlnt::time(1, 2, 3, 4));
ws.cell("A20").value("datetime");
ws.cell("B20").value(xlnt::datetime(2016, 2, 3, 1, 2, 3, 4));
ws.cell("A21").value("timedelta");
ws.cell("B21").value(xlnt::timedelta(1, 2, 3, 4, 5));
ws.freeze_panes("B2");
std::vector<std::uint8_t> temp_buffer;
wb.save(temp_buffer);
xlnt_assert(!temp_buffer.empty());
}
void test_save_after_sheet_deletion()
{
xlnt::workbook workbook;
xlnt_assert_equals(workbook.sheet_titles().size(), 1);
auto sheet = workbook.create_sheet();
sheet.title("XXX1");
xlnt_assert_equals(workbook.sheet_titles().size(), 2);
workbook.remove_sheet(workbook.sheet_by_title("XXX1"));
xlnt_assert_equals(workbook.sheet_titles().size(), 1);
std::vector<std::uint8_t> temp_buffer;
xlnt_assert_throws_nothing(workbook.save(temp_buffer));
xlnt_assert(!temp_buffer.empty());
}
void test_write_comments_hyperlinks_formulae()
{
xlnt::workbook wb;
auto sheet1 = wb.active_sheet();
auto comment_font = xlnt::font().bold(true).size(10).color(xlnt::indexed_color(81)).name("Calibri");
sheet1.cell("A1").value("Sheet1!A1");
sheet1.cell("A1").comment("Sheet1 comment", comment_font, "Microsoft Office User");
sheet1.cell("A2").value("Sheet1!A2");
sheet1.cell("A2").comment("Sheet1 comment2", comment_font, "Microsoft Office User");
>>>>>>> Stashed changes:tests/workbook/serialization_test_suite.hpp
sheet1.cell("A6").hyperlink(sheet1.cell("A1")); sheet1.cell("A6").hyperlink(sheet1.cell("A1"));
sheet1.cell("A6").format(hyperlink_format); sheet1.cell("A6").format(hyperlink_format);
@ -257,6 +355,7 @@ public:
sheet1.cell("C2").value("a"); sheet1.cell("C2").value("a");
sheet1.cell("C3").value("b"); sheet1.cell("C3").value("b");
<<<<<<< Updated upstream:tests/workbook/serialization_test_suite.cpp
for (auto i = 1; i <= 7; ++i) for (auto i = 1; i <= 7; ++i)
{ {
sheet1.row_properties(i).dy_descent = 0.2; sheet1.row_properties(i).dy_descent = 0.2;
@ -270,6 +369,11 @@ public:
// comments // comments
sheet2.cell("A1").value("Sheet2!A1"); sheet2.cell("A1").value("Sheet2!A1");
sheet2.cell("A1").comment("Sheet2 comment", comment_font, "Microsoft Office User"); sheet2.cell("A1").comment("Sheet2 comment", comment_font, "Microsoft Office User");
=======
auto sheet2 = wb.create_sheet();
sheet2.cell("A1").value("Sheet2!A1");
sheet2.cell("A2").comment("Sheet2 comment", comment_font, "Microsoft Office User");
>>>>>>> Stashed changes:tests/workbook/serialization_test_suite.hpp
sheet2.cell("A2").value("Sheet2!A2"); sheet2.cell("A2").value("Sheet2!A2");
sheet2.cell("A2").comment("Sheet2 comment2", comment_font, "Microsoft Office User"); sheet2.cell("A2").comment("Sheet2 comment2", comment_font, "Microsoft Office User");
@ -360,11 +464,17 @@ public:
{ {
#ifdef _MSC_VER #ifdef _MSC_VER
xlnt::workbook wb; xlnt::workbook wb;
<<<<<<< Updated upstream:tests/workbook/serialization_test_suite.cpp
// L"/9_unicode_Λ.xlsx" doesn't use wchar_t(0x039B) for the capital lambda... // L"/9_unicode_Λ.xlsx" doesn't use wchar_t(0x039B) for the capital lambda...
// L"/9_unicode_\u039B.xlsx" gives the corrct output // L"/9_unicode_\u039B.xlsx" gives the corrct output
const auto path = LSTRING_LITERAL(XLNT_TEST_DATA_DIR) L"/9_unicode_\u039B.xlsx"; // L"/9_unicode_Λ.xlsx" const auto path = LSTRING_LITERAL(XLNT_TEST_DATA_DIR) L"/9_unicode_\u039B.xlsx"; // L"/9_unicode_Λ.xlsx"
wb.load(path); wb.load(path);
xlnt_assert_equals(wb.active_sheet().cell("A1").value<std::string>(), u8"un\u00EFc\u00F4d\u0117!"); // u8"unïcôdė!" xlnt_assert_equals(wb.active_sheet().cell("A1").value<std::string>(), u8"un\u00EFc\u00F4d\u0117!"); // u8"unïcôdė!"
=======
std::wstring path = LSTRING_LITERAL(XLNT_TEST_DATA_DIR) L"/9_unicode_Λ.xlsx";
wb.load(path_normalized);
xlnt_assert_equals(wb.active_sheet().cell("A1").value<std::string>(), u8"unicodê!");
>>>>>>> Stashed changes:tests/workbook/serialization_test_suite.hpp
#endif #endif
#ifndef __MINGW32__ #ifndef __MINGW32__
@ -560,8 +670,13 @@ public:
ws.column_properties("E").width = width; ws.column_properties("E").width = width;
ws.column_properties("E").custom_width = true; ws.column_properties("E").custom_width = true;
<<<<<<< Updated upstream:tests/workbook/serialization_test_suite.cpp
xlnt_assert(workbook_matches_file(wb, xlnt_assert(workbook_matches_file(wb,
path_helper::test_file("13_custom_heights_widths.xlsx"))); path_helper::test_file("13_custom_heights_widths.xlsx")));
=======
wb.save("temp.xlsx");
xlnt_assert(workbook_matches_file(wb, path_helper::test_file("13_custom_heights_widths.xlsx")));
>>>>>>> Stashed changes:tests/workbook/serialization_test_suite.hpp
} }
/// <summary> /// <summary>
@ -709,4 +824,4 @@ public:
c3.value("C3!"); c3.value("C3!");
} }
}; };
static serialization_test_suite x; static serialization_test_suite x;