mirror of
https://github.com/tfussell/xlnt.git
synced 2024-03-22 13:11:17 +08:00
work on writer
This commit is contained in:
parent
44ebfd96a2
commit
e3bb0be98e
|
@ -54,8 +54,8 @@ struct date
|
|||
/// </summary>
|
||||
static date from_number(int days_since_base_year, calendar base_date);
|
||||
|
||||
date(int year, int month, int day)
|
||||
: year(year), month(month), day(day)
|
||||
date(int year_, int month_, int day_)
|
||||
: year(year_), month(month_), day(day_)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -93,8 +93,8 @@ struct time
|
|||
/// </summary>
|
||||
static time from_number(long double number);
|
||||
|
||||
explicit time(int hour = 0, int minute = 0, int second = 0, int microsecond = 0)
|
||||
: hour(hour), minute(minute), second(second), microsecond(microsecond)
|
||||
explicit time(int hour_ = 0, int minute_ = 0, int second_ = 0, int microsecond_ = 0)
|
||||
: hour(hour_), minute(minute_), second(second_), microsecond(microsecond_)
|
||||
{
|
||||
}
|
||||
explicit time(const std::string &time_string);
|
||||
|
@ -128,8 +128,8 @@ struct datetime
|
|||
/// </summary>
|
||||
static datetime from_number(long double number, calendar base_date);
|
||||
|
||||
datetime(int year, int month, int day, int hour = 0, int minute = 0, int second = 0, int microsecond = 0)
|
||||
: year(year), month(month), day(day), hour(hour), minute(minute), second(second), microsecond(microsecond)
|
||||
datetime(int year_, int month_, int day_, int hour_ = 0, int minute_ = 0, int second_ = 0, int microsecond_ = 0)
|
||||
: year(year_), month(month_), day(day_), hour(hour_), minute(minute_), second(second_), microsecond(microsecond_)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -152,7 +152,12 @@ struct datetime
|
|||
/// </summary>
|
||||
struct timedelta
|
||||
{
|
||||
timedelta(int days, int hours, int minutes = 0, int seconds = 0, int microseconds = 0) : days(days), hours(hours), minutes(minutes), seconds(seconds), microseconds(microseconds)
|
||||
timedelta(int days_, int hours_, int minutes_ = 0, int seconds_ = 0, int microseconds_ = 0)
|
||||
: days(days_),
|
||||
hours(hours_),
|
||||
minutes(minutes_),
|
||||
seconds(seconds_),
|
||||
microseconds(microseconds_)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include "../common/types.hpp"
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
/// <summary>
|
||||
|
@ -33,7 +35,7 @@ namespace xlnt {
|
|||
class cell_coordinates_exception : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
cell_coordinates_exception(int row, int column);
|
||||
cell_coordinates_exception(row_t row, column_t column);
|
||||
cell_coordinates_exception(const std::string &coord_string);
|
||||
};
|
||||
|
||||
|
|
|
@ -15,8 +15,7 @@ namespace xlnt {
|
|||
|
||||
struct zip_info
|
||||
{
|
||||
std::string filename;
|
||||
struct
|
||||
struct date_time_t
|
||||
{
|
||||
int year;
|
||||
int month;
|
||||
|
@ -24,7 +23,12 @@ struct zip_info
|
|||
int hours;
|
||||
int minutes;
|
||||
int seconds;
|
||||
} date_time;
|
||||
};
|
||||
|
||||
zip_info();
|
||||
|
||||
date_time_t date_time;
|
||||
std::string filename;
|
||||
std::string comment;
|
||||
std::string extra;
|
||||
uint16_t create_system;
|
||||
|
|
|
@ -23,11 +23,12 @@
|
|||
// @author: see AUTHORS file
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
class workbook_reader
|
||||
{
|
||||
class workbook;
|
||||
|
||||
};
|
||||
xlnt::workbook load_workbook(const std::vector<std::uint8_t> &bytes);
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -28,8 +28,9 @@ namespace xlnt {
|
|||
/// <summary>
|
||||
/// Alignment options for use in styles.
|
||||
/// </summary>
|
||||
struct alignment
|
||||
class alignment
|
||||
{
|
||||
public:
|
||||
enum class horizontal_alignment
|
||||
{
|
||||
general,
|
||||
|
@ -55,7 +56,12 @@ struct alignment
|
|||
|
||||
bool operator==(const alignment &other) const
|
||||
{
|
||||
return horizontal_ == other.horizontal_;
|
||||
return horizontal_ == other.horizontal_
|
||||
&& vertical_ == other.vertical_
|
||||
&& text_rotation_ == other.text_rotation_
|
||||
&& wrap_text_ == other.wrap_text_
|
||||
&& shrink_to_fit_ == other.shrink_to_fit_
|
||||
&& indent_ == other.indent_;
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -98,7 +98,10 @@ public:
|
|||
|
||||
bool operator==(const border &other) const
|
||||
{
|
||||
return start.value == other.start.value;
|
||||
return start.value == other.start.value
|
||||
&& outline == other.outline
|
||||
&& diagonal_up == other.diagonal_up
|
||||
&& diagonal_down == other.diagonal_down;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -25,8 +25,9 @@
|
|||
|
||||
namespace xlnt {
|
||||
|
||||
struct color
|
||||
class color
|
||||
{
|
||||
public:
|
||||
static const color black;
|
||||
static const color white;
|
||||
static const color red;
|
||||
|
@ -38,12 +39,17 @@ struct color
|
|||
static const color yellow;
|
||||
static const color darkyellow;
|
||||
|
||||
color(int index)
|
||||
color(int index) : index_(index)
|
||||
{
|
||||
this->index = index;
|
||||
}
|
||||
|
||||
int index;
|
||||
bool operator==(const color &other) const
|
||||
{
|
||||
return index_ == other.index_;
|
||||
}
|
||||
|
||||
private:
|
||||
int index_;
|
||||
};
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -45,7 +45,15 @@ public:
|
|||
|
||||
bool operator==(const font &other) const
|
||||
{
|
||||
return name_ == other.name_;
|
||||
return name_ == other.name_
|
||||
&& size_ == other.size_
|
||||
&& bold_ == other.bold_
|
||||
&& italic_ == other.italic_
|
||||
&& superscript_ == other.superscript_
|
||||
&& subscript_ == other.subscript_
|
||||
&& underline_ == other.underline_
|
||||
&& strikethrough_ == other.strikethrough_
|
||||
&& color_ == other.color_;
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -36,7 +36,7 @@ namespace xlnt {
|
|||
class style
|
||||
{
|
||||
public:
|
||||
style(bool static_ = false) : static_(static_) {}
|
||||
style(bool is_static = false) : static_(is_static) {}
|
||||
style(const style &rhs);
|
||||
|
||||
style copy() const;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
namespace xlnt {
|
||||
|
||||
class range_reference;
|
||||
class worksheet;
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> split_named_range(const std::string &named_range_string);
|
||||
|
@ -12,7 +13,20 @@ std::vector<std::pair<std::string, std::string>> split_named_range(const std::st
|
|||
class named_range
|
||||
{
|
||||
public:
|
||||
named_range(const std::string &name, const std::vector<std::pair<worksheet, std::string>> &targets);
|
||||
using target = std::pair<worksheet, range_reference>;
|
||||
|
||||
named_range();
|
||||
named_range(const named_range &other);
|
||||
named_range(const std::string &name, const std::vector<target> &targets);
|
||||
|
||||
std::string get_name() const { return name_; }
|
||||
const std::vector<target> &get_targets() const { return targets_; }
|
||||
|
||||
named_range &operator=(const named_range &other);
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
std::vector<target> targets_;
|
||||
};
|
||||
|
||||
}
|
|
@ -33,20 +33,21 @@
|
|||
|
||||
namespace xlnt {
|
||||
|
||||
class alignment;
|
||||
class border;
|
||||
class color;
|
||||
class document_properties;
|
||||
class drawing;
|
||||
class fill;
|
||||
class font;
|
||||
class named_range;
|
||||
class pattern_fill;
|
||||
class protection;
|
||||
class range;
|
||||
class range_reference;
|
||||
class relationship;
|
||||
class worksheet;
|
||||
class alignment;
|
||||
class border;
|
||||
class fill;
|
||||
class pattern_fill;
|
||||
class font;
|
||||
class protection;
|
||||
class color;
|
||||
class named_range;
|
||||
class zip_file;
|
||||
|
||||
enum class encoding;
|
||||
|
||||
|
@ -68,7 +69,6 @@ struct content_type
|
|||
class workbook
|
||||
{
|
||||
public:
|
||||
|
||||
class iterator
|
||||
{
|
||||
public:
|
||||
|
@ -103,6 +103,8 @@ public:
|
|||
std::size_t index_;
|
||||
};
|
||||
|
||||
static std::size_t index_from_ws_filename(const std::string &filename);
|
||||
|
||||
//constructors
|
||||
workbook();
|
||||
workbook(encoding e);
|
||||
|
@ -162,6 +164,7 @@ public:
|
|||
const document_properties &get_properties() const;
|
||||
|
||||
//named ranges
|
||||
std::vector<named_range> get_named_ranges() const;
|
||||
void create_named_range(const std::string &name, worksheet worksheet, const range_reference &reference);
|
||||
bool has_named_range(const std::string &name) const;
|
||||
range get_named_range(const std::string &name);
|
||||
|
@ -173,6 +176,7 @@ public:
|
|||
bool load(const std::vector<unsigned char> &data);
|
||||
bool load(const std::string &filename);
|
||||
bool load(const std::istream &stream);
|
||||
bool load(zip_file &archive);
|
||||
|
||||
bool operator==(const workbook &rhs) const;
|
||||
|
||||
|
@ -204,14 +208,10 @@ public:
|
|||
|
||||
void set_code_name(const std::string &code_name);
|
||||
|
||||
void add_named_range(const named_range &n);
|
||||
|
||||
bool has_loaded_theme();
|
||||
std::string get_loaded_theme();
|
||||
|
||||
private:
|
||||
static std::size_t index_from_ws_filename(const std::string &ws_filename);
|
||||
|
||||
friend class worksheet;
|
||||
std::shared_ptr<detail::workbook_impl> d_;
|
||||
};
|
||||
|
|
|
@ -49,7 +49,7 @@ public:
|
|||
cell_reference &get_top_left() { return top_left_; }
|
||||
cell_reference &get_bottom_right() { return bottom_right_; }
|
||||
|
||||
range_reference make_offset(column_t column_offset, row_t row_offset) const;
|
||||
range_reference make_offset(int column_offset, int row_offset) const;
|
||||
|
||||
std::string to_string() const;
|
||||
|
||||
|
|
|
@ -6,6 +6,6 @@ namespace xlnt {
|
|||
|
||||
class workbook;
|
||||
|
||||
std::string write_content_types(const workbook &wb, bool as_template);
|
||||
std::string write_content_types(const workbook &wb, bool as_template = false);
|
||||
|
||||
};
|
||||
|
|
|
@ -50,12 +50,19 @@ public:
|
|||
private:
|
||||
workbook wb_;
|
||||
style_writer style_writer_;
|
||||
std::vector<std::string> shared_strings_;
|
||||
};
|
||||
|
||||
std::string write_shared_strings(const std::vector<std::string> &string_table);
|
||||
std::string write_properties_core(const document_properties &prop);
|
||||
std::string write_worksheet_rels(worksheet ws);
|
||||
std::string write_theme();
|
||||
std::string write_properties_app(const workbook &wb);
|
||||
std::string write_root_rels(const workbook &wb);
|
||||
std::string write_workbook(const workbook &wb);
|
||||
std::string write_workbook_rels(const workbook &wb);
|
||||
std::string write_defined_names(const xlnt::workbook &wb);
|
||||
|
||||
bool save_workbook(workbook &wb, const std::string &filename, bool as_template = false);
|
||||
std::vector<std::uint8_t> save_virtual_workbook(xlnt::workbook &wb, bool as_template = false);
|
||||
|
||||
|
|
|
@ -1,2 +1,15 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
class worksheet;
|
||||
|
||||
std::string write_worksheet(worksheet ws,
|
||||
const std::vector<std::string> &string_table = {},
|
||||
const std::unordered_map<std::size_t, std::string> &style_id_by_hash = {});
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
// Copyright (c) 2015 Thomas Fussell
|
||||
// Copyright (c) 2010-2015 openpyxl
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, WRISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE
|
||||
//
|
||||
// @license: http://www.opensource.org/licenses/mit-license.php
|
||||
// @author: see AUTHORS file
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
class relationship;
|
||||
class workbook;
|
||||
class worksheet;
|
||||
class document_properties;
|
||||
|
||||
class writer
|
||||
{
|
||||
public:
|
||||
static std::string write_content_types(const workbook &wb);
|
||||
|
||||
static std::string write_properties_core(const document_properties &prop);
|
||||
|
||||
static std::string write_theme();
|
||||
|
||||
static std::string write_shared_strings(const std::vector<std::string> &string_table);
|
||||
|
||||
static std::string write_worksheet(worksheet ws,
|
||||
const std::vector<std::string> &string_table = {},
|
||||
const std::unordered_map<std::size_t, std::string> &style_table = {});
|
||||
|
||||
static std::string write_worksheet_rels(worksheet ws);
|
||||
};
|
||||
|
||||
} // namespace xlnt
|
|
@ -3,9 +3,9 @@
|
|||
|
||||
namespace xlnt {
|
||||
|
||||
side::side(border_style style, color c) : style_(style), color_(c)
|
||||
{
|
||||
side::side(border_style style, color c) : style_(style), color_(c)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
|
@ -194,6 +194,15 @@ void cell::set_value(char const *c)
|
|||
template<>
|
||||
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());
|
||||
set_comment(c.get_comment());
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -439,7 +448,7 @@ std::pair<int, int> cell::get_anchor() const
|
|||
int left_anchor = 0;
|
||||
auto default_width = points_to_pixels(DefaultColumnWidth, 96.0);
|
||||
|
||||
for(int column_index = 1; column_index <= (int)left_columns; column_index++)
|
||||
for(column_t column_index = 1; column_index <= left_columns; column_index++)
|
||||
{
|
||||
if(column_dimensions.find(column_index) != column_dimensions.end())
|
||||
{
|
||||
|
@ -462,9 +471,9 @@ std::pair<int, int> cell::get_anchor() const
|
|||
|
||||
for(int row_index = 1; row_index <= (int)top_rows; row_index++)
|
||||
{
|
||||
if(row_dimensions.find(row_index) != row_dimensions.end())
|
||||
if(row_dimensions.find(static_cast<row_t>(row_index)) != row_dimensions.end())
|
||||
{
|
||||
auto rdh = row_dimensions.at(row_index);
|
||||
auto rdh = row_dimensions.at(static_cast<row_t>(row_index));
|
||||
|
||||
if(rdh > 0)
|
||||
{
|
||||
|
@ -639,7 +648,7 @@ datetime cell::get_value() const
|
|||
template<>
|
||||
date cell::get_value() const
|
||||
{
|
||||
return date::from_number(d_->value_numeric_, xlnt::calendar::windows_1900);
|
||||
return date::from_number(static_cast<int>(d_->value_numeric_), xlnt::calendar::windows_1900);
|
||||
}
|
||||
|
||||
template<>
|
||||
|
|
|
@ -37,22 +37,22 @@ cell_reference::cell_reference(const char *reference_string) : cell_reference(st
|
|||
}
|
||||
|
||||
cell_reference::cell_reference(const std::string &column, row_t row, bool absolute)
|
||||
: column_(column_index_from_string(column)),
|
||||
row_(row),
|
||||
absolute_(absolute)
|
||||
: column_(column_index_from_string(column)),
|
||||
row_(row),
|
||||
absolute_(absolute)
|
||||
{
|
||||
if(row == 0 || row_ >= constants::MaxRow || column_ >= constants::MaxColumn)
|
||||
if(row == 0 || row_ >= constants::MaxRow || column_ == 0 || column_ >= constants::MaxColumn)
|
||||
{
|
||||
throw cell_coordinates_exception(column_, row_);
|
||||
}
|
||||
}
|
||||
|
||||
cell_reference::cell_reference(column_t column_index, row_t row_index, bool absolute)
|
||||
: column_(column_index),
|
||||
row_(row_index),
|
||||
absolute_(absolute)
|
||||
cell_reference::cell_reference(column_t column_index, row_t row, bool absolute)
|
||||
: column_(column_index),
|
||||
row_(row),
|
||||
absolute_(absolute)
|
||||
{
|
||||
if(row_ >= constants::MaxRow || column_ >= constants::MaxColumn)
|
||||
if(row_ == 0 || row_ >= constants::MaxRow || column_ == 0 || column_ >= constants::MaxColumn)
|
||||
{
|
||||
throw cell_coordinates_exception(column_, row_);
|
||||
}
|
||||
|
@ -69,6 +69,7 @@ std::string cell_reference::to_string() const
|
|||
{
|
||||
return std::string("$") + column_string_from_index(column_) + "$" + std::to_string(row_);
|
||||
}
|
||||
|
||||
return column_string_from_index(column_) + std::to_string(row_);
|
||||
}
|
||||
|
||||
|
@ -153,7 +154,8 @@ std::pair<std::string, row_t> cell_reference::split_reference(const std::string
|
|||
|
||||
cell_reference cell_reference::make_offset(int column_offset, int row_offset) const
|
||||
{
|
||||
return cell_reference(column_ + column_offset, row_ + row_offset);
|
||||
return cell_reference(static_cast<column_t>(static_cast<int>(column_) + column_offset),
|
||||
static_cast<row_t>(static_cast<int>(row_) + row_offset));
|
||||
}
|
||||
|
||||
bool cell_reference::operator==(const cell_reference &comparand) const
|
||||
|
@ -175,12 +177,12 @@ column_t cell_reference::column_index_from_string(const std::string &column_stri
|
|||
|
||||
for(int i = static_cast<int>(column_string.length()) - 1; i >= 0; i--)
|
||||
{
|
||||
if(!std::isalpha(column_string[i], std::locale::classic()))
|
||||
if(!std::isalpha(column_string[static_cast<std::size_t>(i)], std::locale::classic()))
|
||||
{
|
||||
throw column_string_index_exception();
|
||||
}
|
||||
|
||||
column_index += (std::toupper(column_string[i], std::locale::classic()) - 'A' + 1) * place;
|
||||
column_index += static_cast<column_t>((std::toupper(column_string[static_cast<std::size_t>(i)], std::locale::classic()) - 'A' + 1) * place);
|
||||
place *= 26;
|
||||
}
|
||||
|
||||
|
@ -201,7 +203,7 @@ std::string cell_reference::column_string_from_index(column_t column_index)
|
|||
throw column_string_index_exception();
|
||||
}
|
||||
|
||||
auto temp = column_index;
|
||||
int temp = static_cast<int>(column_index);
|
||||
std::string column_letter = "";
|
||||
|
||||
while(temp > 0)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include <xlnt/cell/comment.hpp>
|
||||
#include <xlnt/cell/cell.hpp>
|
||||
#include <xlnt/cell/comment.hpp>
|
||||
|
||||
#include "detail/comment_impl.hpp"
|
||||
|
||||
|
@ -12,6 +12,8 @@ comment::comment(detail::comment_impl *d) : d_(d)
|
|||
comment::comment(cell parent, const std::string &text, const std::string &author) : d_(nullptr)
|
||||
{
|
||||
d_ = parent.get_comment().d_;
|
||||
d_->text_ = text;
|
||||
d_->author_ = author;
|
||||
}
|
||||
|
||||
comment::comment() : d_(nullptr)
|
||||
|
@ -32,9 +34,9 @@ std::string comment::get_text() const
|
|||
return d_->text_;
|
||||
}
|
||||
|
||||
bool comment::operator==(const xlnt::comment &other) const
|
||||
{
|
||||
bool comment::operator==(const xlnt::comment &other) const
|
||||
{
|
||||
return d_ == other.d_;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -123,7 +123,7 @@ time::time(const std::string &time_string) : hour(0), minute(0), second(0), micr
|
|||
|
||||
long double time::to_number() const
|
||||
{
|
||||
std::size_t microseconds = microsecond;
|
||||
std::size_t microseconds = static_cast<std::size_t>(microsecond);
|
||||
microseconds += second * 1e6;
|
||||
microseconds += minute * 1e6 * 60;
|
||||
microseconds += hour * 1e6 * 60 * 60;
|
||||
|
@ -163,7 +163,7 @@ long double datetime::to_number(calendar base_date) const
|
|||
+ time(hour, minute, second, microsecond).to_number();
|
||||
}
|
||||
|
||||
std::string datetime::to_string(xlnt::calendar base_date) const
|
||||
std::string datetime::to_string(xlnt::calendar /*base_date*/) const
|
||||
{
|
||||
return std::to_string(year) + "/" + std::to_string(month) + "/" + std::to_string(day) + " " +std::to_string(hour) + ":" + std::to_string(minute) + ":" + std::to_string(second) + ":" + std::to_string(microsecond);
|
||||
}
|
||||
|
|
|
@ -6,22 +6,50 @@
|
|||
namespace xlnt {
|
||||
namespace detail {
|
||||
|
||||
cell_impl::cell_impl() : parent_(nullptr), type_(cell::type::null),
|
||||
column_(1), row_(1), style_(nullptr), is_merged_(false),
|
||||
is_date_(false), has_hyperlink_(false), xf_index_(0), comment_(nullptr)
|
||||
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
cell_impl::cell_impl(column_t column, row_t row)
|
||||
: parent_(nullptr), type_(cell::type::null), column_(column), row_(row),
|
||||
style_(nullptr), is_merged_(false), is_date_(false),
|
||||
has_hyperlink_(false), xf_index_(0), comment_(nullptr)
|
||||
{
|
||||
}
|
||||
cell_impl::cell_impl(column_t column, row_t row) : cell_impl(nullptr, column, row)
|
||||
{
|
||||
}
|
||||
|
||||
cell_impl::cell_impl(worksheet_impl *parent, column_t column, row_t row)
|
||||
: parent_(parent), type_(cell::type::null), column_(column), row_(row), style_(nullptr),
|
||||
is_merged_(false), is_date_(false), has_hyperlink_(false), xf_index_(0), comment_(nullptr)
|
||||
: type_(cell::type::null),
|
||||
parent_(parent),
|
||||
column_(column),
|
||||
row_(row),
|
||||
value_numeric_(0),
|
||||
has_hyperlink_(false),
|
||||
is_merged_(false),
|
||||
is_date_(false),
|
||||
xf_index_(0),
|
||||
style_(nullptr),
|
||||
comment_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -28,11 +28,11 @@ std::string check_string(std::string s)
|
|||
s = s.substr(0, 32767); // max string length in Excel
|
||||
}
|
||||
|
||||
for (unsigned char c : s)
|
||||
for (char c : s)
|
||||
{
|
||||
if (c <= 8 || c == 11 || c == 12 || (c >= 14 && c <= 31))
|
||||
if (c>= 0 && (c <= 8 || c == 11 || c == 12 || (c >= 14 && c <= 31)))
|
||||
{
|
||||
throw xlnt::illegal_character_error(static_cast<char>(c));
|
||||
throw xlnt::illegal_character_error(c);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -200,7 +200,6 @@ struct cell_impl
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
cell::type type_;
|
||||
|
||||
worksheet_impl *parent_;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include "comment_impl.hpp"
|
||||
|
||||
|
||||
namespace xlnt {
|
||||
namespace detail {
|
||||
|
||||
|
|
|
@ -10,6 +10,17 @@ struct workbook_impl
|
|||
{
|
||||
workbook_impl();
|
||||
|
||||
workbook_impl(const workbook_impl &other)
|
||||
: active_sheet_index_(other.active_sheet_index_),
|
||||
worksheets_(other.worksheets_),
|
||||
relationships_(other.relationships_),
|
||||
drawings_(other.drawings_),
|
||||
properties_(other.properties_),
|
||||
guess_types_(other.guess_types_),
|
||||
data_only_(other.data_only_)
|
||||
{
|
||||
}
|
||||
|
||||
workbook_impl &operator=(const workbook_impl &other)
|
||||
{
|
||||
active_sheet_index_ = other.active_sheet_index_;
|
||||
|
@ -22,24 +33,11 @@ struct workbook_impl
|
|||
properties_ = other.properties_;
|
||||
guess_types_ = other.guess_types_;
|
||||
data_only_ = other.data_only_;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
workbook_impl(const workbook_impl &other)
|
||||
: active_sheet_index_(other.active_sheet_index_),
|
||||
worksheets_(other.worksheets_),
|
||||
relationships_(other.relationships_),
|
||||
drawings_(other.drawings_),
|
||||
properties_(other.properties_),
|
||||
guess_types_(other.guess_types_),
|
||||
data_only_(other.data_only_)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//bool guess_types_;
|
||||
//bool data_only_;
|
||||
int active_sheet_index_;
|
||||
std::size_t active_sheet_index_;
|
||||
std::vector<worksheet_impl> worksheets_;
|
||||
std::vector<relationship> relationships_;
|
||||
std::vector<drawing> drawings_;
|
||||
|
|
|
@ -61,7 +61,7 @@ struct worksheet_impl
|
|||
range_reference auto_filter_;
|
||||
margins page_margins_;
|
||||
std::vector<range_reference> merged_cells_;
|
||||
std::unordered_map<std::string, range_reference> named_ranges_;
|
||||
std::unordered_map<std::string, named_range> named_ranges_;
|
||||
std::size_t comment_count_;
|
||||
header_footer header_footer_;
|
||||
std::unordered_map<column_t, double> column_dimensions_;
|
||||
|
|
|
@ -38,7 +38,7 @@ invalid_file_exception::invalid_file_exception(const std::string &filename)
|
|||
|
||||
}
|
||||
|
||||
cell_coordinates_exception::cell_coordinates_exception(int row, int column)
|
||||
cell_coordinates_exception::cell_coordinates_exception(row_t row, column_t column)
|
||||
: std::runtime_error(std::string("bad cell coordinates: (") + std::to_string(row) + "," + std::to_string(column) + ")")
|
||||
{
|
||||
|
||||
|
|
|
@ -1,10 +1,40 @@
|
|||
#include <sstream>
|
||||
|
||||
#include <xlnt/workbook/workbook.hpp>
|
||||
#include <xlnt/writer/manifest_writer.hpp>
|
||||
|
||||
#include "constants.hpp"
|
||||
#include "detail/include_pugixml.hpp"
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
std::string write_content_types(const workbook &wb, bool as_template)
|
||||
std::string write_content_types(const workbook &wb, bool /*as_template*/)
|
||||
{
|
||||
return "";
|
||||
pugi::xml_document doc;
|
||||
auto root_node = doc.append_child("Types");
|
||||
root_node.append_attribute("xmlns").set_value(constants::Namespaces.at("content-types").c_str());
|
||||
|
||||
for(auto type : wb.get_content_types())
|
||||
{
|
||||
pugi::xml_node type_node;
|
||||
|
||||
if (type.is_default)
|
||||
{
|
||||
type_node = root_node.append_child("Default");
|
||||
type_node.append_attribute("Extension").set_value(type.extension.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
type_node = root_node.append_child("Override");
|
||||
type_node.append_attribute("PartName").set_value(type.part_name.c_str());
|
||||
}
|
||||
|
||||
type_node.append_attribute("ContentType").set_value(type.type.c_str());
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
doc.save(ss);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
|
@ -65,9 +65,27 @@ std::vector<std::pair<std::string, std::string>> split_named_range(const std::st
|
|||
return final;
|
||||
}
|
||||
|
||||
named_range::named_range(const std::string &name, const std::vector<std::pair<worksheet, std::string>> &targets)
|
||||
named_range::named_range()
|
||||
{
|
||||
}
|
||||
|
||||
named_range::named_range(const named_range &other)
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
named_range::named_range(const std::string &name, const std::vector<named_range::target> &targets)
|
||||
: name_(name),
|
||||
targets_(targets)
|
||||
{
|
||||
}
|
||||
|
||||
named_range &named_range::operator=(const named_range &other)
|
||||
{
|
||||
name_ = other.name_;
|
||||
targets_ = other.targets_;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
|
@ -145,16 +145,18 @@ cell_vector range::get_vector(std::size_t vector_index)
|
|||
if(order_ == major_order::row)
|
||||
{
|
||||
range_reference reference(ref_.get_top_left().get_column_index(),
|
||||
ref_.get_top_left().get_row() + (int)vector_index,
|
||||
static_cast<row_t>(static_cast<std::size_t>(ref_.get_top_left().get_row()) + vector_index),
|
||||
ref_.get_bottom_right().get_column_index(),
|
||||
ref_.get_top_left().get_row() + (int)vector_index);
|
||||
static_cast<row_t>(static_cast<std::size_t>(ref_.get_top_left().get_row()) + vector_index));
|
||||
|
||||
return cell_vector(ws_, reference, order_);
|
||||
}
|
||||
|
||||
range_reference reference(ref_.get_top_left().get_column_index() + (int)vector_index,
|
||||
range_reference reference(static_cast<column_t>(static_cast<std::size_t>(ref_.get_top_left().get_column_index()) + vector_index),
|
||||
ref_.get_top_left().get_row(),
|
||||
ref_.get_top_left().get_column_index() + (int)vector_index,
|
||||
static_cast<column_t>(static_cast<std::size_t>(ref_.get_top_left().get_column_index()) + vector_index),
|
||||
ref_.get_bottom_right().get_row());
|
||||
|
||||
return cell_vector(ws_, reference, order_);
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ range_reference::range_reference(column_t column_index_start, row_t row_index_st
|
|||
|
||||
}
|
||||
|
||||
range_reference range_reference::make_offset(column_t column_offset, row_t row_offset) const
|
||||
range_reference range_reference::make_offset(int column_offset, int row_offset) const
|
||||
{
|
||||
return range_reference(top_left_.make_offset(column_offset, row_offset), bottom_right_.make_offset(column_offset, row_offset));
|
||||
}
|
||||
|
|
|
@ -1,20 +1,19 @@
|
|||
#include <algorithm>
|
||||
|
||||
#include <pugixml.hpp>
|
||||
|
||||
#include <xlnt/reader/reader.hpp>
|
||||
#include <xlnt/cell/cell.hpp>
|
||||
#include <xlnt/common/datetime.hpp>
|
||||
#include <xlnt/worksheet/range_reference.hpp>
|
||||
#include <xlnt/workbook/workbook.hpp>
|
||||
#include <xlnt/worksheet/worksheet.hpp>
|
||||
#include <xlnt/workbook/document_properties.hpp>
|
||||
#include <xlnt/common/exceptions.hpp>
|
||||
#include <xlnt/common/relationship.hpp>
|
||||
#include <xlnt/common/zip_file.hpp>
|
||||
#include <xlnt/common/exceptions.hpp>
|
||||
#include <xlnt/reader/reader.hpp>
|
||||
#include <xlnt/workbook/document_properties.hpp>
|
||||
#include <xlnt/workbook/workbook.hpp>
|
||||
#include <xlnt/worksheet/range_reference.hpp>
|
||||
#include <xlnt/worksheet/worksheet.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
const std::string reader::CentralDirectorySignature = "\x50\x4b\x05\x06";
|
||||
namespace {
|
||||
|
||||
std::string::size_type find_string_in_string(const std::string &string, const std::string &substring)
|
||||
{
|
||||
|
@ -33,6 +32,156 @@ std::string::size_type find_string_in_string(const std::string &string, const st
|
|||
return possible_match_index;
|
||||
}
|
||||
|
||||
xlnt::datetime w3cdtf_to_datetime(const std::string &string)
|
||||
{
|
||||
xlnt::datetime result(1900, 1, 1);
|
||||
auto separator_index = string.find('-');
|
||||
result.year = std::stoi(string.substr(0, separator_index));
|
||||
result.month = std::stoi(string.substr(separator_index + 1, string.find('-', separator_index + 1)));
|
||||
separator_index = string.find('-', separator_index + 1);
|
||||
result.day = std::stoi(string.substr(separator_index + 1, string.find('T', separator_index + 1)));
|
||||
separator_index = string.find('T', separator_index + 1);
|
||||
result.hour = std::stoi(string.substr(separator_index + 1, string.find(':', separator_index + 1)));
|
||||
separator_index = string.find(':', separator_index + 1);
|
||||
result.minute = std::stoi(string.substr(separator_index + 1, string.find(':', separator_index + 1)));
|
||||
separator_index = string.find(':', separator_index + 1);
|
||||
result.second = std::stoi(string.substr(separator_index + 1, string.find('Z', separator_index + 1)));
|
||||
return result;
|
||||
}
|
||||
|
||||
void read_worksheet_common(xlnt::worksheet ws, const pugi::xml_node &root_node, const std::vector<std::string> &string_table, const std::vector<int> &number_format_ids)
|
||||
{
|
||||
auto dimension_node = root_node.child("dimension");
|
||||
std::string dimension = dimension_node.attribute("ref").as_string();
|
||||
auto full_range = xlnt::range_reference(dimension);
|
||||
auto sheet_data_node = root_node.child("sheetData");
|
||||
auto merge_cells_node = root_node.child("mergeCells");
|
||||
|
||||
if(merge_cells_node != nullptr)
|
||||
{
|
||||
int count = merge_cells_node.attribute("count").as_int();
|
||||
|
||||
for(auto merge_cell_node : merge_cells_node.children("mergeCell"))
|
||||
{
|
||||
ws.merge_cells(merge_cell_node.attribute("ref").as_string());
|
||||
count--;
|
||||
}
|
||||
|
||||
if(count != 0)
|
||||
{
|
||||
throw std::runtime_error("mismatch between count and actual number of merged cells");
|
||||
}
|
||||
}
|
||||
|
||||
for(auto row_node : sheet_data_node.children("row"))
|
||||
{
|
||||
int row_index = row_node.attribute("r").as_int();
|
||||
std::string span_string = row_node.attribute("spans").as_string();
|
||||
auto colon_index = span_string.find(':');
|
||||
|
||||
column_t min_column = 0;
|
||||
column_t max_column = 0;
|
||||
|
||||
if(colon_index != std::string::npos)
|
||||
{
|
||||
min_column = static_cast<column_t>(std::stoll(span_string.substr(0, colon_index)));
|
||||
max_column = static_cast<column_t>(std::stoll(span_string.substr(colon_index + 1)));
|
||||
}
|
||||
else
|
||||
{
|
||||
min_column = static_cast<column_t>(full_range.get_top_left().get_column_index() + 1);
|
||||
max_column = static_cast<column_t>(full_range.get_bottom_right().get_column_index() + 1);
|
||||
}
|
||||
|
||||
for(column_t i = min_column; i < max_column + 1; i++)
|
||||
{
|
||||
std::string address = xlnt::cell_reference::column_string_from_index(i) + std::to_string(row_index);
|
||||
auto cell_node = row_node.find_child_by_attribute("c", "r", address.c_str());
|
||||
|
||||
if(cell_node != nullptr)
|
||||
{
|
||||
bool has_value = cell_node.child("v") != nullptr;
|
||||
std::string value_string = cell_node.child("v").text().as_string();
|
||||
|
||||
bool has_type = cell_node.attribute("t") != nullptr;
|
||||
std::string type = cell_node.attribute("t").as_string();
|
||||
|
||||
bool has_style = cell_node.attribute("s") != nullptr;
|
||||
std::string style = cell_node.attribute("s").as_string();
|
||||
|
||||
bool has_formula = cell_node.child("f") != nullptr;
|
||||
bool shared_formula = has_formula && cell_node.child("f").attribute("t") != nullptr && std::string(cell_node.child("f").attribute("t").as_string()) == "shared";
|
||||
|
||||
if(has_formula && !shared_formula && !ws.get_parent().get_data_only())
|
||||
{
|
||||
std::string formula = cell_node.child("f").text().as_string();
|
||||
ws.get_cell(address).set_formula(formula);
|
||||
}
|
||||
|
||||
if(has_type && type == "inlineStr") // inline string
|
||||
{
|
||||
std::string inline_string = cell_node.child("is").child("t").text().as_string();
|
||||
ws.get_cell(address).set_value(inline_string);
|
||||
}
|
||||
else if(has_type && type == "s" && !has_formula) // shared string
|
||||
{
|
||||
auto shared_string_index = std::stoll(value_string);
|
||||
auto shared_string = string_table.at(static_cast<std::size_t>(shared_string_index));
|
||||
ws.get_cell(address).set_value(shared_string);
|
||||
}
|
||||
else if(has_type && type == "b") // boolean
|
||||
{
|
||||
ws.get_cell(address).set_value(value_string != "0");
|
||||
}
|
||||
else if(has_type && type == "str")
|
||||
{
|
||||
ws.get_cell(address).set_value(value_string);
|
||||
}
|
||||
else if(has_value)
|
||||
{
|
||||
try
|
||||
{
|
||||
ws.get_cell(address).set_value(std::stold(value_string));
|
||||
}
|
||||
catch(std::invalid_argument)
|
||||
{
|
||||
ws.get_cell(address).set_value(value_string);
|
||||
}
|
||||
}
|
||||
|
||||
if(has_style)
|
||||
{
|
||||
auto number_format_id = number_format_ids.at(static_cast<std::size_t>(std::stoll(style)));
|
||||
auto format = xlnt::number_format::lookup_format(number_format_id);
|
||||
|
||||
ws.get_cell(address).get_style().get_number_format().set_format_code(format);
|
||||
|
||||
if(format == xlnt::number_format::format::date_xlsx14)
|
||||
{
|
||||
auto base_date = ws.get_parent().get_properties().excel_base_date;
|
||||
auto converted = xlnt::date::from_number(std::stoi(value_string), base_date);
|
||||
ws.get_cell(address).set_value(converted.to_number(xlnt::calendar::windows_1900));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto auto_filter_node = root_node.child("autoFilter");
|
||||
|
||||
if(auto_filter_node != nullptr)
|
||||
{
|
||||
xlnt::range_reference ref(auto_filter_node.attribute("ref").as_string());
|
||||
ws.auto_filter(ref);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
const std::string reader::CentralDirectorySignature = "\x50\x4b\x05\x06";
|
||||
|
||||
std::string reader::repair_central_directory(const std::string &original)
|
||||
{
|
||||
auto pos = find_string_in_string(original, CentralDirectorySignature);
|
||||
|
@ -85,23 +234,6 @@ std::vector<std::pair<std::string, std::string>> reader::read_sheets(zip_file &a
|
|||
return sheets;
|
||||
}
|
||||
|
||||
datetime w3cdtf_to_datetime(const std::string &string)
|
||||
{
|
||||
datetime result(1900, 1, 1);
|
||||
auto separator_index = string.find('-');
|
||||
result.year = std::stoi(string.substr(0, separator_index));
|
||||
result.month = std::stoi(string.substr(separator_index + 1, string.find('-', separator_index + 1)));
|
||||
separator_index = string.find('-', separator_index + 1);
|
||||
result.day = std::stoi(string.substr(separator_index + 1, string.find('T', separator_index + 1)));
|
||||
separator_index = string.find('T', separator_index + 1);
|
||||
result.hour = std::stoi(string.substr(separator_index + 1, string.find(':', separator_index + 1)));
|
||||
separator_index = string.find(':', separator_index + 1);
|
||||
result.minute = std::stoi(string.substr(separator_index + 1, string.find(':', separator_index + 1)));
|
||||
separator_index = string.find(':', separator_index + 1);
|
||||
result.second = std::stoi(string.substr(separator_index + 1, string.find('Z', separator_index + 1)));
|
||||
return result;
|
||||
}
|
||||
|
||||
document_properties reader::read_properties_core(const std::string &xml_string)
|
||||
{
|
||||
document_properties props;
|
||||
|
@ -235,133 +367,6 @@ std::string reader::determine_document_type(const std::vector<std::pair<std::str
|
|||
return "unsupported";
|
||||
}
|
||||
|
||||
void read_worksheet_common(worksheet ws, const pugi::xml_node &root_node, const std::vector<std::string> &string_table, const std::vector<int> &number_format_ids)
|
||||
{
|
||||
auto dimension_node = root_node.child("dimension");
|
||||
std::string dimension = dimension_node.attribute("ref").as_string();
|
||||
auto full_range = xlnt::range_reference(dimension);
|
||||
auto sheet_data_node = root_node.child("sheetData");
|
||||
auto merge_cells_node = root_node.child("mergeCells");
|
||||
|
||||
if(merge_cells_node != nullptr)
|
||||
{
|
||||
int count = merge_cells_node.attribute("count").as_int();
|
||||
|
||||
for(auto merge_cell_node : merge_cells_node.children("mergeCell"))
|
||||
{
|
||||
ws.merge_cells(merge_cell_node.attribute("ref").as_string());
|
||||
count--;
|
||||
}
|
||||
|
||||
if(count != 0)
|
||||
{
|
||||
throw std::runtime_error("mismatch between count and actual number of merged cells");
|
||||
}
|
||||
}
|
||||
|
||||
for(auto row_node : sheet_data_node.children("row"))
|
||||
{
|
||||
int row_index = row_node.attribute("r").as_int();
|
||||
std::string span_string = row_node.attribute("spans").as_string();
|
||||
auto colon_index = span_string.find(':');
|
||||
|
||||
int min_column = 0;
|
||||
int max_column = 0;
|
||||
|
||||
if(colon_index != std::string::npos)
|
||||
{
|
||||
min_column = std::stoi(span_string.substr(0, colon_index));
|
||||
max_column = std::stoi(span_string.substr(colon_index + 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
min_column = full_range.get_top_left().get_column_index() + 1;
|
||||
max_column = full_range.get_bottom_right().get_column_index() + 1;
|
||||
}
|
||||
|
||||
for(int i = min_column; i < max_column + 1; i++)
|
||||
{
|
||||
std::string address = xlnt::cell_reference::column_string_from_index(i) + std::to_string(row_index);
|
||||
auto cell_node = row_node.find_child_by_attribute("c", "r", address.c_str());
|
||||
|
||||
if(cell_node != nullptr)
|
||||
{
|
||||
bool has_value = cell_node.child("v") != nullptr;
|
||||
std::string value_string = cell_node.child("v").text().as_string();
|
||||
|
||||
bool has_type = cell_node.attribute("t") != nullptr;
|
||||
std::string type = cell_node.attribute("t").as_string();
|
||||
|
||||
bool has_style = cell_node.attribute("s") != nullptr;
|
||||
std::string style = cell_node.attribute("s").as_string();
|
||||
|
||||
bool has_formula = cell_node.child("f") != nullptr;
|
||||
bool shared_formula = has_formula && cell_node.child("f").attribute("t") != nullptr && std::string(cell_node.child("f").attribute("t").as_string()) == "shared";
|
||||
|
||||
if(has_formula && !shared_formula && !ws.get_parent().get_data_only())
|
||||
{
|
||||
std::string formula = cell_node.child("f").text().as_string();
|
||||
ws.get_cell(address).set_formula(formula);
|
||||
}
|
||||
|
||||
if(has_type && type == "inlineStr") // inline string
|
||||
{
|
||||
std::string inline_string = cell_node.child("is").child("t").text().as_string();
|
||||
ws.get_cell(address).set_value(inline_string);
|
||||
}
|
||||
else if(has_type && type == "s" && !has_formula) // shared string
|
||||
{
|
||||
auto shared_string_index = std::stoi(value_string);
|
||||
auto shared_string = string_table.at(shared_string_index);
|
||||
ws.get_cell(address).set_value(shared_string);
|
||||
}
|
||||
else if(has_type && type == "b") // boolean
|
||||
{
|
||||
ws.get_cell(address).set_value(value_string != "0");
|
||||
}
|
||||
else if(has_type && type == "str")
|
||||
{
|
||||
ws.get_cell(address).set_value(value_string);
|
||||
}
|
||||
else if(has_value)
|
||||
{
|
||||
try
|
||||
{
|
||||
ws.get_cell(address).set_value(std::stold(value_string));
|
||||
}
|
||||
catch(std::invalid_argument)
|
||||
{
|
||||
ws.get_cell(address).set_value(value_string);
|
||||
}
|
||||
}
|
||||
|
||||
if(has_style)
|
||||
{
|
||||
auto number_format_id = number_format_ids.at(std::stoi(style));
|
||||
auto format = number_format::lookup_format(number_format_id);
|
||||
|
||||
ws.get_cell(address).get_style().get_number_format().set_format_code(format);
|
||||
|
||||
if(format == number_format::format::date_xlsx14)
|
||||
{
|
||||
auto base_date = ws.get_parent().get_properties().excel_base_date;
|
||||
auto converted = date::from_number(std::stoi(value_string), base_date);
|
||||
ws.get_cell(address).set_value(converted.to_number(calendar::windows_1900));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto auto_filter_node = root_node.child("autoFilter");
|
||||
|
||||
if(auto_filter_node != nullptr)
|
||||
{
|
||||
range_reference ref(auto_filter_node.attribute("ref").as_string());
|
||||
ws.auto_filter(ref);
|
||||
}
|
||||
}
|
||||
|
||||
void reader::fast_parse(worksheet ws, std::istream &xml_source, const std::vector<std::string> &shared_string, const std::vector<style> &/*style_table*/, std::size_t /*color_index*/)
|
||||
{
|
||||
pugi::xml_document doc;
|
||||
|
|
|
@ -14,10 +14,13 @@
|
|||
#include <xlnt/drawing/drawing.hpp>
|
||||
#include <xlnt/reader/reader.hpp>
|
||||
#include <xlnt/workbook/document_properties.hpp>
|
||||
#include <xlnt/workbook/named_range.hpp>
|
||||
#include <xlnt/workbook/workbook.hpp>
|
||||
#include <xlnt/worksheet/range.hpp>
|
||||
#include <xlnt/worksheet/worksheet.hpp>
|
||||
#include <xlnt/writer/style_writer.hpp>
|
||||
#include <xlnt/writer/manifest_writer.hpp>
|
||||
#include <xlnt/writer/worksheet_writer.hpp>
|
||||
#include <xlnt/writer/workbook_writer.hpp>
|
||||
#include <xlnt/writer/writer.hpp>
|
||||
|
||||
|
@ -280,23 +283,9 @@ bool workbook::load(const std::istream &stream)
|
|||
|
||||
bool workbook::load(const std::vector<unsigned char> &data)
|
||||
{
|
||||
std::string temp_file = create_temporary_filename();
|
||||
|
||||
std::ofstream tmp;
|
||||
tmp.open(temp_file, std::ios::out | std::ios::binary);
|
||||
|
||||
for(auto c : data)
|
||||
{
|
||||
tmp.put(c);
|
||||
}
|
||||
|
||||
tmp.close();
|
||||
|
||||
load(temp_file);
|
||||
|
||||
std::remove(temp_file.c_str());
|
||||
|
||||
return true;
|
||||
xlnt::zip_file archive;
|
||||
archive.load(data);
|
||||
return load(archive);
|
||||
}
|
||||
|
||||
bool workbook::load(const std::string &filename)
|
||||
|
@ -312,17 +301,22 @@ bool workbook::load(const std::string &filename)
|
|||
throw invalid_file_exception(filename);
|
||||
}
|
||||
|
||||
auto content_types = reader::read_content_types(f);
|
||||
return load(f);
|
||||
}
|
||||
|
||||
bool workbook::load(xlnt::zip_file &archive)
|
||||
{
|
||||
auto content_types = reader::read_content_types(archive);
|
||||
auto type = reader::determine_document_type(content_types);
|
||||
|
||||
if(type != "excel")
|
||||
{
|
||||
throw invalid_file_exception(filename);
|
||||
throw invalid_file_exception("");
|
||||
}
|
||||
|
||||
clear();
|
||||
|
||||
auto workbook_relationships = reader::read_relationships(f, "xl/workbook.xml");
|
||||
auto workbook_relationships = reader::read_relationships(archive, "xl/workbook.xml");
|
||||
|
||||
for(auto relationship : workbook_relationships)
|
||||
{
|
||||
|
@ -330,7 +324,7 @@ bool workbook::load(const std::string &filename)
|
|||
}
|
||||
|
||||
pugi::xml_document doc;
|
||||
doc.load(f.read("xl/workbook.xml").c_str());
|
||||
doc.load(archive.read("xl/workbook.xml").c_str());
|
||||
|
||||
auto root_node = doc.child("workbook");
|
||||
|
||||
|
@ -341,17 +335,17 @@ bool workbook::load(const std::string &filename)
|
|||
|
||||
std::vector<std::string> shared_strings;
|
||||
|
||||
if(f.has_file("xl/sharedStrings.xml"))
|
||||
if(archive.has_file("xl/sharedStrings.xml"))
|
||||
{
|
||||
shared_strings = xlnt::reader::read_shared_string(f.read("xl/sharedStrings.xml"));
|
||||
shared_strings = xlnt::reader::read_shared_string(archive.read("xl/sharedStrings.xml"));
|
||||
}
|
||||
|
||||
std::vector<int> number_format_ids;
|
||||
|
||||
if(f.has_file("xl/styles.xml"))
|
||||
if(archive.has_file("xl/styles.xml"))
|
||||
{
|
||||
pugi::xml_document styles_doc;
|
||||
styles_doc.load(f.read("xl/styles.xml").c_str());
|
||||
styles_doc.load(archive.read("xl/styles.xml").c_str());
|
||||
auto stylesheet_node = styles_doc.child("styleSheet");
|
||||
auto cell_xfs_node = stylesheet_node.child("cellXfs");
|
||||
|
||||
|
@ -365,7 +359,7 @@ bool workbook::load(const std::string &filename)
|
|||
{
|
||||
std::string rel_id = sheet_node.attribute("r:id").as_string();
|
||||
auto rel = std::find_if(d_->relationships_.begin(), d_->relationships_.end(),
|
||||
[&](relationship &rel) { return rel.get_id() == rel_id; });
|
||||
[&](relationship &r) { return r.get_id() == rel_id; });
|
||||
|
||||
if (rel == d_->relationships_.end())
|
||||
{
|
||||
|
@ -375,7 +369,7 @@ bool workbook::load(const std::string &filename)
|
|||
auto ws = create_sheet(sheet_node.attribute("name").as_string(), *rel);
|
||||
auto sheet_filename = rel->get_target_uri();
|
||||
|
||||
xlnt::reader::read_worksheet(ws, f.read(sheet_filename).c_str(), shared_strings, number_format_ids);
|
||||
xlnt::reader::read_worksheet(ws, archive.read(sheet_filename).c_str(), shared_strings, number_format_ids);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -435,6 +429,21 @@ worksheet workbook::create_sheet(std::size_t index)
|
|||
return worksheet(&d_->worksheets_[index]);
|
||||
}
|
||||
|
||||
//TODO: There should be a better way to do this...
|
||||
std::size_t workbook::index_from_ws_filename(const std::string &ws_filename)
|
||||
{
|
||||
std::string sheet_index_string(ws_filename);
|
||||
sheet_index_string = sheet_index_string.substr(0, sheet_index_string.find('.'));
|
||||
sheet_index_string = sheet_index_string.substr(sheet_index_string.find_last_of('/'));
|
||||
auto iter = sheet_index_string.end();
|
||||
iter--;
|
||||
while (isdigit(*iter)) iter--;
|
||||
auto first_digit = static_cast<std::size_t>(iter - sheet_index_string.begin());
|
||||
sheet_index_string = sheet_index_string.substr(first_digit + 1);
|
||||
auto sheet_index = static_cast<std::size_t>(std::stoll(sheet_index_string) - 1);
|
||||
return sheet_index;
|
||||
}
|
||||
|
||||
worksheet workbook::create_sheet(const std::string &title, const relationship &rel)
|
||||
{
|
||||
d_->worksheets_.push_back(detail::worksheet_impl(this, title));
|
||||
|
@ -542,72 +551,13 @@ void workbook::clear()
|
|||
|
||||
bool workbook::save(std::vector<unsigned char> &data)
|
||||
{
|
||||
auto temp_file = create_temporary_filename();
|
||||
save(temp_file);
|
||||
|
||||
std::ifstream tmp;
|
||||
tmp.open(temp_file, std::ios::in | std::ios::binary);
|
||||
|
||||
auto char_data = std::vector<char>((std::istreambuf_iterator<char>(tmp)),
|
||||
std::istreambuf_iterator<char>());
|
||||
data = std::vector<unsigned char>(char_data.begin(), char_data.end());
|
||||
tmp.close();
|
||||
|
||||
std::remove(temp_file.c_str());
|
||||
|
||||
data = save_virtual_workbook(*this);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool workbook::save(const std::string &filename)
|
||||
{
|
||||
zip_file f;
|
||||
|
||||
f.writestr("[Content_Types].xml", writer::write_content_types(*this));
|
||||
|
||||
f.writestr("docProps/app.xml", write_properties_app(*this));
|
||||
f.writestr("docProps/core.xml", writer::write_properties_core(get_properties()));
|
||||
|
||||
std::set<std::string> shared_strings_set;
|
||||
|
||||
for(auto ws : *this)
|
||||
{
|
||||
for(auto row : ws.rows())
|
||||
{
|
||||
for(auto cell : row)
|
||||
{
|
||||
if(cell.get_data_type() == cell::type::string)
|
||||
{
|
||||
shared_strings_set.insert(cell.get_value<std::string>());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> shared_strings(shared_strings_set.begin(), shared_strings_set.end());
|
||||
f.writestr("xl/sharedStrings.xml", writer::write_shared_strings(shared_strings));
|
||||
|
||||
f.writestr("xl/theme/theme1.xml", writer::write_theme());
|
||||
f.writestr("xl/styles.xml", style_writer(*this).write_table());
|
||||
|
||||
f.writestr("_rels/.rels", write_root_rels(*this));
|
||||
f.writestr("xl/_rels/workbook.xml.rels", write_workbook_rels(*this));
|
||||
|
||||
f.writestr("xl/workbook.xml", write_workbook(*this));
|
||||
|
||||
for(auto relationship : d_->relationships_)
|
||||
{
|
||||
if(relationship.get_type() == relationship::type::worksheet)
|
||||
{
|
||||
auto sheet_index = index_from_ws_filename(relationship.get_target_uri());
|
||||
auto ws = get_sheet_by_index(sheet_index);
|
||||
f.writestr(relationship.get_target_uri(), writer::write_worksheet(ws, shared_strings));
|
||||
}
|
||||
}
|
||||
|
||||
f.save(filename);
|
||||
|
||||
return true;
|
||||
return save_workbook(*this, filename);
|
||||
}
|
||||
|
||||
bool workbook::operator==(std::nullptr_t) const
|
||||
|
@ -700,56 +650,37 @@ void workbook::set_data_only(bool data_only)
|
|||
d_->data_only_ = data_only;
|
||||
}
|
||||
|
||||
std::size_t workbook::index_from_ws_filename(const std::string &ws_filename)
|
||||
{
|
||||
std::string sheet_index_string(ws_filename);
|
||||
sheet_index_string = sheet_index_string.substr(0, sheet_index_string.find('.'));
|
||||
sheet_index_string = sheet_index_string.substr(sheet_index_string.find_last_of('/'));
|
||||
auto iter = sheet_index_string.end();
|
||||
iter--;
|
||||
while (isdigit(*iter)) iter--;
|
||||
auto first_digit = iter - sheet_index_string.begin();
|
||||
sheet_index_string = sheet_index_string.substr(first_digit + 1);
|
||||
auto sheet_index = std::stoi(sheet_index_string) - 1;
|
||||
return sheet_index;
|
||||
}
|
||||
|
||||
void workbook::add_border(xlnt::border b)
|
||||
void workbook::add_border(xlnt::border /*b*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void workbook::add_alignment(xlnt::alignment a)
|
||||
void workbook::add_alignment(xlnt::alignment /*a*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void workbook::add_protection(xlnt::protection p)
|
||||
void workbook::add_protection(xlnt::protection /*p*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void workbook::add_number_format(const std::string &format)
|
||||
void workbook::add_number_format(const std::string &/*format*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void workbook::add_fill(xlnt::fill &f)
|
||||
void workbook::add_fill(xlnt::fill &/*f*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void workbook::add_font(xlnt::font f)
|
||||
void workbook::add_font(xlnt::font /*f*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void workbook::set_code_name(const std::string &code_name)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void workbook::add_named_range(const xlnt::named_range &n)
|
||||
void workbook::set_code_name(const std::string &/*code_name*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -763,4 +694,19 @@ std::size_t workbook::index_from_ws_filename(const std::string &ws_filename)
|
|||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
13
source/workbook_reader.cpp
Normal file
13
source/workbook_reader.cpp
Normal file
|
@ -0,0 +1,13 @@
|
|||
#include <xlnt/reader/workbook_reader.hpp>
|
||||
#include <xlnt/workbook/workbook.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
xlnt::workbook load_workbook(const std::vector<std::uint8_t> &bytes)
|
||||
{
|
||||
xlnt::workbook wb;
|
||||
wb.load(bytes);
|
||||
return wb;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,15 +1,20 @@
|
|||
#include <set>
|
||||
#include <sstream>
|
||||
|
||||
#include <xlnt/cell/cell.hpp>
|
||||
#include <xlnt/common/exceptions.hpp>
|
||||
#include <xlnt/common/relationship.hpp>
|
||||
#include <xlnt/common/zip_file.hpp>
|
||||
#include <xlnt/workbook/document_properties.hpp>
|
||||
#include <xlnt/workbook/named_range.hpp>
|
||||
#include <xlnt/workbook/workbook.hpp>
|
||||
#include <xlnt/worksheet/range.hpp>
|
||||
#include <xlnt/worksheet/range_reference.hpp>
|
||||
#include <xlnt/worksheet/worksheet.hpp>
|
||||
#include <xlnt/writer/manifest_writer.hpp>
|
||||
#include <xlnt/writer/relationship_writer.hpp>
|
||||
#include <xlnt/writer/theme_writer.hpp>
|
||||
#include <xlnt/writer/worksheet_writer.hpp>
|
||||
#include <xlnt/writer/workbook_writer.hpp>
|
||||
|
||||
#include "constants.hpp"
|
||||
|
@ -17,9 +22,19 @@
|
|||
|
||||
namespace {
|
||||
|
||||
std::string to_xml(xlnt::document_properties &props)
|
||||
std::string fill(const std::string &string, std::size_t length = 2)
|
||||
{
|
||||
return "";
|
||||
if(string.size() >= length)
|
||||
{
|
||||
return string;
|
||||
}
|
||||
|
||||
return std::string(length - string.size(), '0') + string;
|
||||
}
|
||||
|
||||
std::string datetime_to_w3cdtf(const xlnt::datetime &dt)
|
||||
{
|
||||
return std::to_string(dt.year) + "-" + fill(std::to_string(dt.month)) + "-" + fill(std::to_string(dt.day)) + "T" + fill(std::to_string(dt.hour)) + ":" + fill(std::to_string(dt.minute)) + ":" + fill(std::to_string(dt.second)) + "Z";
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -42,7 +57,7 @@ void excel_writer::write_data(zip_file &archive, bool as_template)
|
|||
archive.writestr(constants::ArcRootRels, write_root_rels(wb_));
|
||||
archive.writestr(constants::ArcWorkbookRels, write_workbook_rels(wb_));
|
||||
archive.writestr(constants::ArcApp, write_properties_app(wb_));
|
||||
archive.writestr(constants::ArcCore, to_xml(wb_.get_properties()));
|
||||
archive.writestr(constants::ArcCore, write_properties_core(wb_.get_properties()));
|
||||
|
||||
if(wb_.has_loaded_theme())
|
||||
{
|
||||
|
@ -80,6 +95,7 @@ void excel_writer::write_data(zip_file &archive, bool as_template)
|
|||
write_chartsheets(archive);
|
||||
write_string_table(archive);
|
||||
write_external_links(archive);
|
||||
|
||||
archive.writestr(constants::ArcStyles, style_writer_.write_table());
|
||||
auto manifest = write_content_types(wb_, as_template);
|
||||
archive.writestr(constants::ArcContentTypes, manifest);
|
||||
|
@ -87,32 +103,452 @@ void excel_writer::write_data(zip_file &archive, bool as_template)
|
|||
|
||||
void excel_writer::write_string_table(zip_file &archive)
|
||||
{
|
||||
std::set<std::string> shared_strings_set;
|
||||
|
||||
for(auto ws : wb_)
|
||||
{
|
||||
for(auto row : ws.rows())
|
||||
{
|
||||
for(auto cell : row)
|
||||
{
|
||||
if(cell.get_data_type() == cell::type::string)
|
||||
{
|
||||
shared_strings_set.insert(cell.get_value<std::string>());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
shared_strings_.assign(shared_strings_set.begin(), shared_strings_set.end());
|
||||
archive.writestr(constants::ArcSharedString, write_shared_strings(shared_strings_));
|
||||
}
|
||||
|
||||
void excel_writer::write_images(zip_file &archive)
|
||||
void excel_writer::write_images(zip_file &/*archive*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void excel_writer::write_charts(zip_file &archive)
|
||||
void excel_writer::write_charts(zip_file &/*archive*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void excel_writer::write_chartsheets(zip_file &archive)
|
||||
void excel_writer::write_chartsheets(zip_file &/*archive*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void excel_writer::write_worksheets(zip_file &archive)
|
||||
{
|
||||
for(auto relationship : wb_.get_relationships())
|
||||
{
|
||||
if(relationship.get_type() == relationship::type::worksheet)
|
||||
{
|
||||
auto sheet_index = workbook::index_from_ws_filename(relationship.get_target_uri());
|
||||
auto ws = wb_.get_sheet_by_index(sheet_index);
|
||||
archive.writestr(relationship.get_target_uri(), write_worksheet(ws, shared_strings_));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void excel_writer::write_external_links(zip_file &/*archive*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void excel_writer::write_external_links(zip_file &archive)
|
||||
std::string write_shared_strings(const std::vector<std::string> &string_table)
|
||||
{
|
||||
pugi::xml_document doc;
|
||||
auto root_node = doc.append_child("sst");
|
||||
root_node.append_attribute("xmlns").set_value("http://schemas.openxmlformats.org/spreadsheetml/2006/main");
|
||||
root_node.append_attribute("uniqueCount").set_value((int)string_table.size());
|
||||
|
||||
for(auto string : string_table)
|
||||
{
|
||||
root_node.append_child("si").append_child("t").text().set(string.c_str());
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
doc.save(ss);
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string write_properties_core(const document_properties &prop)
|
||||
{
|
||||
pugi::xml_document doc;
|
||||
auto root_node = doc.append_child("cp:coreProperties");
|
||||
root_node.append_attribute("xmlns:cp").set_value("http://schemas.openxmlformats.org/package/2006/metadata/core-properties");
|
||||
root_node.append_attribute("xmlns:dc").set_value("http://purl.org/dc/elements/1.1/");
|
||||
root_node.append_attribute("xmlns:dcmitype").set_value("http://purl.org/dc/dcmitype/");
|
||||
root_node.append_attribute("xmlns:dcterms").set_value("http://purl.org/dc/terms/");
|
||||
root_node.append_attribute("xmlns:xsi").set_value("http://www.w3.org/2001/XMLSchema-instance");
|
||||
|
||||
root_node.append_child("dc:creator").text().set(prop.creator.c_str());
|
||||
root_node.append_child("cp:lastModifiedBy").text().set(prop.last_modified_by.c_str());
|
||||
root_node.append_child("dcterms:created").text().set(datetime_to_w3cdtf(prop.created).c_str());
|
||||
root_node.child("dcterms:created").append_attribute("xsi:type").set_value("dcterms:W3CDTF");
|
||||
root_node.append_child("dcterms:modified").text().set(datetime_to_w3cdtf(prop.modified).c_str());
|
||||
root_node.child("dcterms:modified").append_attribute("xsi:type").set_value("dcterms:W3CDTF");
|
||||
root_node.append_child("dc:title").text().set(prop.title.c_str());
|
||||
root_node.append_child("dc:description");
|
||||
root_node.append_child("dc:subject");
|
||||
root_node.append_child("cp:keywords");
|
||||
root_node.append_child("cp:category");
|
||||
|
||||
std::stringstream ss;
|
||||
doc.save(ss);
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string write_worksheet_rels(worksheet ws)
|
||||
{
|
||||
return write_relationships(ws.get_relationships(), "");
|
||||
}
|
||||
|
||||
std::string write_theme()
|
||||
{
|
||||
pugi::xml_document doc;
|
||||
auto theme_node = doc.append_child("a:theme");
|
||||
theme_node.append_attribute("xmlns:a").set_value(constants::Namespaces.at("drawingml").c_str());
|
||||
theme_node.append_attribute("name").set_value("Office Theme");
|
||||
auto theme_elements_node = theme_node.append_child("a:themeElements");
|
||||
auto clr_scheme_node = theme_elements_node.append_child("a:clrScheme");
|
||||
clr_scheme_node.append_attribute("name").set_value("Office");
|
||||
|
||||
struct scheme_element
|
||||
{
|
||||
std::string name;
|
||||
std::string sub_element_name;
|
||||
std::string val;
|
||||
};
|
||||
|
||||
std::vector<scheme_element> scheme_elements =
|
||||
{
|
||||
{"a:dk1", "a:sysClr", "windowText"},
|
||||
{"a:lt1", "a:sysClr", "window"},
|
||||
{"a:dk2", "a:srgbClr", "1F497D"},
|
||||
{"a:lt2", "a:srgbClr", "EEECE1"},
|
||||
{"a:accent1", "a:srgbClr", "4F81BD"},
|
||||
{"a:accent2", "a:srgbClr", "C0504D"},
|
||||
{"a:accent3", "a:srgbClr", "9BBB59"},
|
||||
{"a:accent4", "a:srgbClr", "8064A2"},
|
||||
{"a:accent5", "a:srgbClr", "4BACC6"},
|
||||
{"a:accent6", "a:srgbClr", "F79646"},
|
||||
{"a:hlink", "a:srgbClr", "0000FF"},
|
||||
{"a:folHlink", "a:srgbClr", "800080"},
|
||||
};
|
||||
|
||||
for(auto element : scheme_elements)
|
||||
{
|
||||
auto element_node = clr_scheme_node.append_child(element.name.c_str());
|
||||
element_node.append_child(element.sub_element_name.c_str()).append_attribute("val").set_value(element.val.c_str());
|
||||
|
||||
if(element.name == "a:dk1")
|
||||
{
|
||||
element_node.child(element.sub_element_name.c_str()).append_attribute("lastClr").set_value("000000");
|
||||
}
|
||||
else if(element.name == "a:lt1")
|
||||
{
|
||||
element_node.child(element.sub_element_name.c_str()).append_attribute("lastClr").set_value("FFFFFF");
|
||||
}
|
||||
}
|
||||
|
||||
struct font_scheme
|
||||
{
|
||||
bool typeface;
|
||||
std::string script;
|
||||
std::string major;
|
||||
std::string minor;
|
||||
};
|
||||
|
||||
std::vector<font_scheme> font_schemes =
|
||||
{
|
||||
{true, "a:latin", "Cambria", "Calibri"},
|
||||
{true, "a:ea", "", ""},
|
||||
{true, "a:cs", "", ""},
|
||||
{false, "Jpan", "\xef\xbc\xad\xef\xbc\xb3 \xef\xbc\xb0\xe3\x82\xb4\xe3\x82\xb7\xe3\x83\x83\xe3\x82\xaf", "\xef\xbc\xad\xef\xbc\xb3 \xef\xbc\xb0\xe3\x82\xb4\xe3\x82\xb7\xe3\x83\x83\xe3\x82\xaf"},
|
||||
{false, "Hang", "\xeb\xa7\x91\xec\x9d\x80 \xea\xb3\xa0\xeb\x94\x95", "\xeb\xa7\x91\xec\x9d\x80 \xea\xb3\xa0\xeb\x94\x95"},
|
||||
{false, "Hans", "\xe5\xae\x8b\xe4\xbd\x93", "\xe5\xae\x8b\xe4\xbd\x93"},
|
||||
{false, "Hant", "\xe6\x96\xb0\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94", "\xe6\x96\xb0\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94"},
|
||||
{false, "Arab", "Times New Roman", "Arial"},
|
||||
{false, "Hebr", "Times New Roman", "Arial"},
|
||||
{false, "Thai", "Tahoma", "Tahoma"},
|
||||
{false, "Ethi", "Nyala", "Nyala"},
|
||||
{false, "Beng", "Vrinda", "Vrinda"},
|
||||
{false, "Gujr", "Shruti", "Shruti"},
|
||||
{false, "Khmr", "MoolBoran", "DaunPenh"},
|
||||
{false, "Knda", "Tunga", "Tunga"},
|
||||
{false, "Guru", "Raavi", "Raavi"},
|
||||
{false, "Cans", "Euphemia", "Euphemia"},
|
||||
{false, "Cher", "Plantagenet Cherokee", "Plantagenet Cherokee"},
|
||||
{false, "Yiii", "Microsoft Yi Baiti", "Microsoft Yi Baiti"},
|
||||
{false, "Tibt", "Microsoft Himalaya", "Microsoft Himalaya"},
|
||||
{false, "Thaa", "MV Boli", "MV Boli"},
|
||||
{false, "Deva", "Mangal", "Mangal"},
|
||||
{false, "Telu", "Gautami", "Gautami"},
|
||||
{false, "Taml", "Latha", "Latha"},
|
||||
{false, "Syrc", "Estrangelo Edessa", "Estrangelo Edessa"},
|
||||
{false, "Orya", "Kalinga", "Kalinga"},
|
||||
{false, "Mlym", "Kartika", "Kartika"},
|
||||
{false, "Laoo", "DokChampa", "DokChampa"},
|
||||
{false, "Sinh", "Iskoola Pota", "Iskoola Pota"},
|
||||
{false, "Mong", "Mongolian Baiti", "Mongolian Baiti"},
|
||||
{false, "Viet", "Times New Roman", "Arial"},
|
||||
{false, "Uigh", "Microsoft Uighur", "Microsoft Uighur"}
|
||||
};
|
||||
|
||||
auto font_scheme_node = theme_elements_node.append_child("a:fontScheme");
|
||||
font_scheme_node.append_attribute("name").set_value("Office");
|
||||
|
||||
auto major_fonts_node = font_scheme_node.append_child("a:majorFont");
|
||||
auto minor_fonts_node = font_scheme_node.append_child("a:minorFont");
|
||||
|
||||
for(auto scheme : font_schemes)
|
||||
{
|
||||
pugi::xml_node major_font_node, minor_font_node;
|
||||
|
||||
if(scheme.typeface)
|
||||
{
|
||||
major_font_node = major_fonts_node.append_child(scheme.script.c_str());
|
||||
minor_font_node = minor_fonts_node.append_child(scheme.script.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
major_font_node = major_fonts_node.append_child("a:font");
|
||||
major_font_node.append_attribute("script").set_value(scheme.script.c_str());
|
||||
minor_font_node = minor_fonts_node.append_child("a:font");
|
||||
minor_font_node.append_attribute("script").set_value(scheme.script.c_str());
|
||||
}
|
||||
|
||||
major_font_node.append_attribute("typeface").set_value(scheme.major.c_str());
|
||||
minor_font_node.append_attribute("typeface").set_value(scheme.minor.c_str());
|
||||
}
|
||||
|
||||
auto format_scheme_node = theme_elements_node.append_child("a:fmtScheme");
|
||||
format_scheme_node.append_attribute("name").set_value("Office");
|
||||
|
||||
auto fill_style_list_node = format_scheme_node.append_child("a:fillStyleLst");
|
||||
fill_style_list_node.append_child("a:solidFill").append_child("a:schemeClr").append_attribute("val").set_value("phClr");
|
||||
|
||||
auto grad_fill_node = fill_style_list_node.append_child("a:gradFill");
|
||||
grad_fill_node.append_attribute("rotWithShape").set_value(1);
|
||||
|
||||
auto grad_fill_list = grad_fill_node.append_child("a:gsLst");
|
||||
auto gs_node = grad_fill_list.append_child("a:gs");
|
||||
gs_node.append_attribute("pos").set_value(0);
|
||||
auto scheme_color_node = gs_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:tint").append_attribute("val").set_value(50000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(300000);
|
||||
|
||||
gs_node = grad_fill_list.append_child("a:gs");
|
||||
gs_node.append_attribute("pos").set_value(35000);
|
||||
scheme_color_node = gs_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:tint").append_attribute("val").set_value(37000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(300000);
|
||||
|
||||
gs_node = grad_fill_list.append_child("a:gs");
|
||||
gs_node.append_attribute("pos").set_value(100000);
|
||||
scheme_color_node = gs_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:tint").append_attribute("val").set_value(15000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(350000);
|
||||
|
||||
auto lin_node = grad_fill_node.append_child("a:lin");
|
||||
lin_node.append_attribute("ang").set_value(16200000);
|
||||
lin_node.append_attribute("scaled").set_value(1);
|
||||
|
||||
grad_fill_node = fill_style_list_node.append_child("a:gradFill");
|
||||
grad_fill_node.append_attribute("rotWithShape").set_value(1);
|
||||
|
||||
grad_fill_list = grad_fill_node.append_child("a:gsLst");
|
||||
gs_node = grad_fill_list.append_child("a:gs");
|
||||
gs_node.append_attribute("pos").set_value(0);
|
||||
scheme_color_node = gs_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:shade").append_attribute("val").set_value(51000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(130000);
|
||||
|
||||
gs_node = grad_fill_list.append_child("a:gs");
|
||||
gs_node.append_attribute("pos").set_value(80000);
|
||||
scheme_color_node = gs_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:shade").append_attribute("val").set_value(93000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(130000);
|
||||
|
||||
gs_node = grad_fill_list.append_child("a:gs");
|
||||
gs_node.append_attribute("pos").set_value(100000);
|
||||
scheme_color_node = gs_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:shade").append_attribute("val").set_value(94000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(135000);
|
||||
|
||||
lin_node = grad_fill_node.append_child("a:lin");
|
||||
lin_node.append_attribute("ang").set_value(16200000);
|
||||
lin_node.append_attribute("scaled").set_value(0);
|
||||
|
||||
auto line_style_list_node = format_scheme_node.append_child("a:lnStyleLst");
|
||||
|
||||
auto ln_node = line_style_list_node.append_child("a:ln");
|
||||
ln_node.append_attribute("w").set_value(9525);
|
||||
ln_node.append_attribute("cap").set_value("flat");
|
||||
ln_node.append_attribute("cmpd").set_value("sng");
|
||||
ln_node.append_attribute("algn").set_value("ctr");
|
||||
|
||||
auto solid_fill_node = ln_node.append_child("a:solidFill");
|
||||
scheme_color_node = solid_fill_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:shade").append_attribute("val").set_value(95000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(105000);
|
||||
ln_node.append_child("a:prstDash").append_attribute("val").set_value("solid");
|
||||
|
||||
ln_node = line_style_list_node.append_child("a:ln");
|
||||
ln_node.append_attribute("w").set_value(25400);
|
||||
ln_node.append_attribute("cap").set_value("flat");
|
||||
ln_node.append_attribute("cmpd").set_value("sng");
|
||||
ln_node.append_attribute("algn").set_value("ctr");
|
||||
|
||||
solid_fill_node = ln_node.append_child("a:solidFill");
|
||||
scheme_color_node = solid_fill_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
ln_node.append_child("a:prstDash").append_attribute("val").set_value("solid");
|
||||
|
||||
ln_node = line_style_list_node.append_child("a:ln");
|
||||
ln_node.append_attribute("w").set_value(38100);
|
||||
ln_node.append_attribute("cap").set_value("flat");
|
||||
ln_node.append_attribute("cmpd").set_value("sng");
|
||||
ln_node.append_attribute("algn").set_value("ctr");
|
||||
|
||||
solid_fill_node = ln_node.append_child("a:solidFill");
|
||||
scheme_color_node = solid_fill_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
ln_node.append_child("a:prstDash").append_attribute("val").set_value("solid");
|
||||
|
||||
auto effect_style_list_node = format_scheme_node.append_child("a:effectStyleLst");
|
||||
auto effect_style_node = effect_style_list_node.append_child("a:effectStyle");
|
||||
auto effect_list_node = effect_style_node.append_child("a:effectLst");
|
||||
auto outer_shadow_node = effect_list_node.append_child("a:outerShdw");
|
||||
outer_shadow_node.append_attribute("blurRad").set_value(40000);
|
||||
outer_shadow_node.append_attribute("dist").set_value(20000);
|
||||
outer_shadow_node.append_attribute("dir").set_value(5400000);
|
||||
outer_shadow_node.append_attribute("rotWithShape").set_value(0);
|
||||
auto srgb_clr_node = outer_shadow_node.append_child("a:srgbClr");
|
||||
srgb_clr_node.append_attribute("val").set_value("000000");
|
||||
srgb_clr_node.append_child("a:alpha").append_attribute("val").set_value(38000);
|
||||
|
||||
effect_style_node = effect_style_list_node.append_child("a:effectStyle");
|
||||
effect_list_node = effect_style_node.append_child("a:effectLst");
|
||||
outer_shadow_node = effect_list_node.append_child("a:outerShdw");
|
||||
outer_shadow_node.append_attribute("blurRad").set_value(40000);
|
||||
outer_shadow_node.append_attribute("dist").set_value(23000);
|
||||
outer_shadow_node.append_attribute("dir").set_value(5400000);
|
||||
outer_shadow_node.append_attribute("rotWithShape").set_value(0);
|
||||
srgb_clr_node = outer_shadow_node.append_child("a:srgbClr");
|
||||
srgb_clr_node.append_attribute("val").set_value("000000");
|
||||
srgb_clr_node.append_child("a:alpha").append_attribute("val").set_value(35000);
|
||||
|
||||
effect_style_node = effect_style_list_node.append_child("a:effectStyle");
|
||||
effect_list_node = effect_style_node.append_child("a:effectLst");
|
||||
outer_shadow_node = effect_list_node.append_child("a:outerShdw");
|
||||
outer_shadow_node.append_attribute("blurRad").set_value(40000);
|
||||
outer_shadow_node.append_attribute("dist").set_value(23000);
|
||||
outer_shadow_node.append_attribute("dir").set_value(5400000);
|
||||
outer_shadow_node.append_attribute("rotWithShape").set_value(0);
|
||||
srgb_clr_node = outer_shadow_node.append_child("a:srgbClr");
|
||||
srgb_clr_node.append_attribute("val").set_value("000000");
|
||||
srgb_clr_node.append_child("a:alpha").append_attribute("val").set_value(35000);
|
||||
auto scene3d_node = effect_style_node.append_child("a:scene3d");
|
||||
auto camera_node = scene3d_node.append_child("a:camera");
|
||||
camera_node.append_attribute("prst").set_value("orthographicFront");
|
||||
auto rot_node = camera_node.append_child("a:rot");
|
||||
rot_node.append_attribute("lat").set_value(0);
|
||||
rot_node.append_attribute("lon").set_value(0);
|
||||
rot_node.append_attribute("rev").set_value(0);
|
||||
auto light_rig_node = scene3d_node.append_child("a:lightRig");
|
||||
light_rig_node.append_attribute("rig").set_value("threePt");
|
||||
light_rig_node.append_attribute("dir").set_value("t");
|
||||
rot_node = light_rig_node.append_child("a:rot");
|
||||
rot_node.append_attribute("lat").set_value(0);
|
||||
rot_node.append_attribute("lon").set_value(0);
|
||||
rot_node.append_attribute("rev").set_value(1200000);
|
||||
|
||||
auto bevel_node = effect_style_node.append_child("a:sp3d").append_child("a:bevelT");
|
||||
bevel_node.append_attribute("w").set_value(63500);
|
||||
bevel_node.append_attribute("h").set_value(25400);
|
||||
|
||||
auto bg_fill_style_list_node = format_scheme_node.append_child("a:bgFillStyleLst");
|
||||
|
||||
bg_fill_style_list_node.append_child("a:solidFill").append_child("a:schemeClr").append_attribute("val").set_value("phClr");
|
||||
|
||||
grad_fill_node = bg_fill_style_list_node.append_child("a:gradFill");
|
||||
grad_fill_node.append_attribute("rotWithShape").set_value(1);
|
||||
|
||||
grad_fill_list = grad_fill_node.append_child("a:gsLst");
|
||||
gs_node = grad_fill_list.append_child("a:gs");
|
||||
gs_node.append_attribute("pos").set_value(0);
|
||||
scheme_color_node = gs_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:tint").append_attribute("val").set_value(40000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(350000);
|
||||
|
||||
gs_node = grad_fill_list.append_child("a:gs");
|
||||
gs_node.append_attribute("pos").set_value(40000);
|
||||
scheme_color_node = gs_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:tint").append_attribute("val").set_value(45000);
|
||||
scheme_color_node.append_child("a:shade").append_attribute("val").set_value(99000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(350000);
|
||||
|
||||
gs_node = grad_fill_list.append_child("a:gs");
|
||||
gs_node.append_attribute("pos").set_value(100000);
|
||||
scheme_color_node = gs_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:shade").append_attribute("val").set_value(20000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(255000);
|
||||
|
||||
auto path_node = grad_fill_node.append_child("a:path");
|
||||
path_node.append_attribute("path").set_value("circle");
|
||||
auto fill_to_rect_node = path_node.append_child("a:fillToRect");
|
||||
fill_to_rect_node.append_attribute("l").set_value(50000);
|
||||
fill_to_rect_node.append_attribute("t").set_value(-80000);
|
||||
fill_to_rect_node.append_attribute("r").set_value(50000);
|
||||
fill_to_rect_node.append_attribute("b").set_value(180000);
|
||||
|
||||
grad_fill_node = bg_fill_style_list_node.append_child("a:gradFill");
|
||||
grad_fill_node.append_attribute("rotWithShape").set_value(1);
|
||||
|
||||
grad_fill_list = grad_fill_node.append_child("a:gsLst");
|
||||
gs_node = grad_fill_list.append_child("a:gs");
|
||||
gs_node.append_attribute("pos").set_value(0);
|
||||
scheme_color_node = gs_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:tint").append_attribute("val").set_value(80000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(300000);
|
||||
|
||||
gs_node = grad_fill_list.append_child("a:gs");
|
||||
gs_node.append_attribute("pos").set_value(100000);
|
||||
scheme_color_node = gs_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:shade").append_attribute("val").set_value(30000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(200000);
|
||||
|
||||
path_node = grad_fill_node.append_child("a:path");
|
||||
path_node.append_attribute("path").set_value("circle");
|
||||
fill_to_rect_node = path_node.append_child("a:fillToRect");
|
||||
fill_to_rect_node.append_attribute("l").set_value(50000);
|
||||
fill_to_rect_node.append_attribute("t").set_value(50000);
|
||||
fill_to_rect_node.append_attribute("r").set_value(50000);
|
||||
fill_to_rect_node.append_attribute("b").set_value(50000);
|
||||
|
||||
theme_node.append_child("a:objectDefaults");
|
||||
theme_node.append_child("a:extraClrSchemeLst");
|
||||
|
||||
std::stringstream ss;
|
||||
doc.print(ss);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string write_properties_app(const workbook &wb)
|
||||
|
@ -223,8 +659,8 @@ std::string write_workbook(const workbook &wb)
|
|||
iter--;
|
||||
while (isdigit(*iter)) iter--;
|
||||
auto first_digit = iter - sheet_index_string.begin();
|
||||
sheet_index_string = sheet_index_string.substr(first_digit + 1);
|
||||
std::size_t sheet_index = std::stoi(sheet_index_string) - 1;
|
||||
sheet_index_string = sheet_index_string.substr(static_cast<std::string::size_type>(first_digit + 1));
|
||||
std::size_t sheet_index = static_cast<std::size_t>(std::stoll(sheet_index_string) - 1);
|
||||
|
||||
auto ws = wb.get_sheet_by_index(sheet_index);
|
||||
|
||||
|
@ -261,9 +697,20 @@ std::string write_workbook_rels(const workbook &wb)
|
|||
return write_relationships(wb.get_relationships(), "xl/");
|
||||
}
|
||||
|
||||
std::string write_theme()
|
||||
std::string write_defined_names(const xlnt::workbook &wb)
|
||||
{
|
||||
return "";
|
||||
pugi::xml_document doc;
|
||||
auto names = doc.root().append_child("names");
|
||||
|
||||
for(auto named_range : wb.get_named_ranges())
|
||||
{
|
||||
names.append_child(named_range.get_name().c_str());
|
||||
}
|
||||
|
||||
std::ostringstream stream;
|
||||
doc.save(stream);
|
||||
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
bool save_workbook(workbook &wb, const std::string &filename, bool as_template)
|
||||
|
@ -275,10 +722,12 @@ bool save_workbook(workbook &wb, const std::string &filename, bool as_template)
|
|||
|
||||
std::vector<std::uint8_t> save_virtual_workbook(xlnt::workbook &wb, bool as_template)
|
||||
{
|
||||
zip_file archive;
|
||||
excel_writer writer(wb);
|
||||
std::vector<std::uint8_t> buffer;
|
||||
zip_file archive(buffer);
|
||||
writer.write_data(archive, as_template);
|
||||
std::vector<std::uint8_t> buffer;
|
||||
archive.save(buffer);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
#include <algorithm>
|
||||
|
||||
#include <xlnt/worksheet/worksheet.hpp>
|
||||
#include <xlnt/cell/cell.hpp>
|
||||
#include <xlnt/common/datetime.hpp>
|
||||
#include <xlnt/common/exceptions.hpp>
|
||||
#include <xlnt/common/relationship.hpp>
|
||||
#include <xlnt/workbook/named_range.hpp>
|
||||
#include <xlnt/workbook/workbook.hpp>
|
||||
#include <xlnt/worksheet/range.hpp>
|
||||
#include <xlnt/worksheet/range_reference.hpp>
|
||||
#include <xlnt/common/relationship.hpp>
|
||||
#include <xlnt/workbook/workbook.hpp>
|
||||
#include <xlnt/common/exceptions.hpp>
|
||||
#include <xlnt/worksheet/worksheet.hpp>
|
||||
|
||||
#include "detail/worksheet_impl.hpp"
|
||||
|
||||
|
@ -52,7 +53,9 @@ std::string worksheet::unique_sheet_name(const std::string &value) const
|
|||
|
||||
void worksheet::create_named_range(const std::string &name, const range_reference &reference)
|
||||
{
|
||||
d_->named_ranges_[name] = reference;
|
||||
std::vector<named_range::target> targets;
|
||||
targets.push_back({*this, reference});
|
||||
d_->named_ranges_[name] = named_range(name, targets);
|
||||
}
|
||||
|
||||
range worksheet::operator()(const xlnt::cell_reference &top_left, const xlnt::cell_reference &bottom_right)
|
||||
|
@ -97,7 +100,7 @@ bool worksheet::has_auto_filter() const
|
|||
|
||||
void worksheet::unset_auto_filter()
|
||||
{
|
||||
d_->auto_filter_ = range_reference(0, 0, 0, 0);
|
||||
d_->auto_filter_ = range_reference(1, 1, 1, 1);
|
||||
}
|
||||
|
||||
page_setup &worksheet::get_page_setup()
|
||||
|
@ -242,7 +245,7 @@ range worksheet::get_named_range(const std::string &name)
|
|||
throw named_range_exception();
|
||||
}
|
||||
|
||||
return get_range(d_->named_ranges_[name]);
|
||||
return get_range(d_->named_ranges_[name].get_targets()[0].second);
|
||||
}
|
||||
|
||||
column_t worksheet::get_lowest_column() const
|
||||
|
@ -311,11 +314,11 @@ column_t worksheet::get_highest_column() const
|
|||
|
||||
range_reference worksheet::calculate_dimension() const
|
||||
{
|
||||
int lowest_column = get_lowest_column();
|
||||
int lowest_row = get_lowest_row();
|
||||
auto lowest_column = get_lowest_column();
|
||||
auto lowest_row = get_lowest_row();
|
||||
|
||||
int highest_column = get_highest_column();
|
||||
int highest_row = get_highest_row();
|
||||
auto highest_column = get_highest_column();
|
||||
auto highest_row = get_highest_row();
|
||||
|
||||
return range_reference(lowest_column, lowest_row, highest_column, highest_row);
|
||||
}
|
||||
|
@ -430,7 +433,7 @@ void worksheet::append(const std::vector<std::string> &cells)
|
|||
|
||||
row_t worksheet::get_next_row() const
|
||||
{
|
||||
int row = get_highest_row() + 1;
|
||||
auto row = get_highest_row() + 1;
|
||||
|
||||
if(row == 2 && d_->cell_map_.size() == 0)
|
||||
{
|
||||
|
@ -489,7 +492,7 @@ void worksheet::append(const std::unordered_map<int, std::string> &cells)
|
|||
|
||||
for(auto cell : cells)
|
||||
{
|
||||
get_cell(cell_reference(cell.first, row)).set_value(cell.second);
|
||||
get_cell(cell_reference(static_cast<column_t>(cell.first), row)).set_value(cell.second);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
353
source/worksheet_writer.cpp
Normal file
353
source/worksheet_writer.cpp
Normal file
|
@ -0,0 +1,353 @@
|
|||
#include <sstream>
|
||||
|
||||
#include <xlnt/cell/cell.hpp>
|
||||
#include <xlnt/cell/cell_reference.hpp>
|
||||
#include <xlnt/worksheet/range.hpp>
|
||||
#include <xlnt/worksheet/range_reference.hpp>
|
||||
#include <xlnt/worksheet/worksheet.hpp>
|
||||
#include <xlnt/writer/worksheet_writer.hpp>
|
||||
|
||||
#include "constants.hpp"
|
||||
#include "detail/include_pugixml.hpp"
|
||||
|
||||
namespace {
|
||||
|
||||
bool is_integral(long double d)
|
||||
{
|
||||
return d == static_cast<long long int>(d);
|
||||
}
|
||||
|
||||
} // namepsace
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
std::string write_worksheet(worksheet ws, const std::vector<std::string> &string_table, const std::unordered_map<std::size_t, std::string> &style_id_by_hash)
|
||||
{
|
||||
ws.get_cell("A1");
|
||||
|
||||
pugi::xml_document doc;
|
||||
auto root_node = doc.append_child("worksheet");
|
||||
root_node.append_attribute("xmlns").set_value(constants::Namespaces.at("spreadsheetml").c_str());
|
||||
root_node.append_attribute("xmlns:r").set_value(constants::Namespaces.at("r").c_str());
|
||||
auto sheet_pr_node = root_node.append_child("sheetPr");
|
||||
auto outline_pr_node = sheet_pr_node.append_child("outlinePr");
|
||||
if(!ws.get_page_setup().is_default())
|
||||
{
|
||||
auto page_set_up_pr_node = sheet_pr_node.append_child("pageSetUpPr");
|
||||
page_set_up_pr_node.append_attribute("fitToPage").set_value(ws.get_page_setup().fit_to_page() ? 1 : 0);
|
||||
}
|
||||
outline_pr_node.append_attribute("summaryBelow").set_value(1);
|
||||
outline_pr_node.append_attribute("summaryRight").set_value(1);
|
||||
auto dimension_node = root_node.append_child("dimension");
|
||||
dimension_node.append_attribute("ref").set_value(ws.calculate_dimension().to_string().c_str());
|
||||
auto sheet_views_node = root_node.append_child("sheetViews");
|
||||
auto sheet_view_node = sheet_views_node.append_child("sheetView");
|
||||
sheet_view_node.append_attribute("workbookViewId").set_value(0);
|
||||
|
||||
std::string active_pane = "bottomRight";
|
||||
|
||||
if(ws.has_frozen_panes())
|
||||
{
|
||||
auto pane_node = sheet_view_node.append_child("pane");
|
||||
|
||||
if(ws.get_frozen_panes().get_column_index() > 1)
|
||||
{
|
||||
pane_node.append_attribute("xSplit").set_value(ws.get_frozen_panes().get_column_index() - 1);
|
||||
active_pane = "topRight";
|
||||
}
|
||||
|
||||
if(ws.get_frozen_panes().get_row() > 1)
|
||||
{
|
||||
pane_node.append_attribute("ySplit").set_value(ws.get_frozen_panes().get_row() - 1);
|
||||
active_pane = "bottomLeft";
|
||||
}
|
||||
|
||||
if(ws.get_frozen_panes().get_row() > 1 && ws.get_frozen_panes().get_column_index() > 1)
|
||||
{
|
||||
auto top_right_node = sheet_view_node.append_child("selection");
|
||||
top_right_node.append_attribute("pane").set_value("topRight");
|
||||
auto bottom_left_node = sheet_view_node.append_child("selection");
|
||||
bottom_left_node.append_attribute("pane").set_value("bottomLeft");
|
||||
active_pane = "bottomRight";
|
||||
}
|
||||
|
||||
pane_node.append_attribute("topLeftCell").set_value(ws.get_frozen_panes().to_string().c_str());
|
||||
pane_node.append_attribute("activePane").set_value(active_pane.c_str());
|
||||
pane_node.append_attribute("state").set_value("frozen");
|
||||
}
|
||||
|
||||
auto selection_node = sheet_view_node.append_child("selection");
|
||||
if(ws.has_frozen_panes())
|
||||
{
|
||||
if(ws.get_frozen_panes().get_row() > 1 && ws.get_frozen_panes().get_column_index() > 1)
|
||||
{
|
||||
selection_node.append_attribute("pane").set_value("bottomRight");
|
||||
}
|
||||
else if(ws.get_frozen_panes().get_row() > 1)
|
||||
{
|
||||
selection_node.append_attribute("pane").set_value("bottomLeft");
|
||||
}
|
||||
else if(ws.get_frozen_panes().get_column_index() > 1)
|
||||
{
|
||||
selection_node.append_attribute("pane").set_value("topRight");
|
||||
}
|
||||
}
|
||||
std::string active_cell = "A1";
|
||||
selection_node.append_attribute("activeCell").set_value(active_cell.c_str());
|
||||
selection_node.append_attribute("sqref").set_value(active_cell.c_str());
|
||||
|
||||
auto sheet_format_pr_node = root_node.append_child("sheetFormatPr");
|
||||
sheet_format_pr_node.append_attribute("baseColWidth").set_value(10);
|
||||
sheet_format_pr_node.append_attribute("defaultRowHeight").set_value(15);
|
||||
|
||||
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());
|
||||
|
||||
for(auto column : styled_columns)
|
||||
{
|
||||
auto col_node = cols_node.append_child("col");
|
||||
col_node.append_attribute("min").set_value(column);
|
||||
col_node.append_attribute("max").set_value(column);
|
||||
col_node.append_attribute("style").set_value(1);
|
||||
}
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, std::string> hyperlink_references;
|
||||
|
||||
auto sheet_data_node = root_node.append_child("sheetData");
|
||||
for(auto row : ws.rows())
|
||||
{
|
||||
row_t min = static_cast<row_t>(row.num_cells());
|
||||
row_t max = 0;
|
||||
bool any_non_null = false;
|
||||
|
||||
for(auto cell : row)
|
||||
{
|
||||
min = std::min(min, cell_reference::column_index_from_string(cell.get_column()));
|
||||
max = std::max(max, cell_reference::column_index_from_string(cell.get_column()));
|
||||
|
||||
if(!cell.garbage_collectible())
|
||||
{
|
||||
any_non_null = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(!any_non_null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto row_node = sheet_data_node.append_child("row");
|
||||
row_node.append_attribute("r").set_value(row.front().get_row());
|
||||
|
||||
row_node.append_attribute("spans").set_value((std::to_string(min) + ":" + std::to_string(max)).c_str());
|
||||
if(ws.has_row_properties(row.front().get_row()))
|
||||
{
|
||||
row_node.append_attribute("customHeight").set_value(1);
|
||||
auto height = ws.get_row_properties(row.front().get_row()).height;
|
||||
if(height == std::floor(height))
|
||||
{
|
||||
row_node.append_attribute("ht").set_value((std::to_string((int)height) + ".0").c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
row_node.append_attribute("ht").set_value(height);
|
||||
}
|
||||
}
|
||||
//row_node.append_attribute("x14ac:dyDescent").set_value(0.25);
|
||||
|
||||
for(auto cell : row)
|
||||
{
|
||||
if(!cell.garbage_collectible())
|
||||
{
|
||||
if(cell.has_hyperlink())
|
||||
{
|
||||
hyperlink_references[cell.get_hyperlink().get_id()] = cell.get_reference().to_string();
|
||||
}
|
||||
|
||||
auto cell_node = row_node.append_child("c");
|
||||
cell_node.append_attribute("r").set_value(cell.get_reference().to_string().c_str());
|
||||
|
||||
if(cell.get_data_type() == cell::type::string)
|
||||
{
|
||||
if(cell.has_formula())
|
||||
{
|
||||
cell_node.append_attribute("t").set_value("str");
|
||||
cell_node.append_child("f").text().set(cell.get_formula().c_str());
|
||||
cell_node.append_child("v").text().set(cell.to_string().c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
int match_index = -1;
|
||||
|
||||
for(std::size_t i = 0; i < string_table.size(); i++)
|
||||
{
|
||||
if(string_table[i] == cell.get_value<std::string>())
|
||||
{
|
||||
match_index = static_cast<int>(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(match_index == -1)
|
||||
{
|
||||
if(cell.get_value<std::string>().empty())
|
||||
{
|
||||
cell_node.append_attribute("t").set_value("s");
|
||||
}
|
||||
else
|
||||
{
|
||||
cell_node.append_attribute("t").set_value("inlineStr");
|
||||
auto inline_string_node = cell_node.append_child("is");
|
||||
inline_string_node.append_child("t").text().set(cell.get_value<std::string>().c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cell_node.append_attribute("t").set_value("s");
|
||||
auto value_node = cell_node.append_child("v");
|
||||
value_node.text().set(match_index);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(cell.get_data_type() != cell::type::null)
|
||||
{
|
||||
if(cell.get_data_type() == cell::type::boolean)
|
||||
{
|
||||
cell_node.append_attribute("t").set_value("b");
|
||||
auto value_node = cell_node.append_child("v");
|
||||
value_node.text().set(cell.get_value<bool>() ? 1 : 0);
|
||||
}
|
||||
else if(cell.get_data_type() == cell::type::numeric)
|
||||
{
|
||||
if(cell.has_formula())
|
||||
{
|
||||
cell_node.append_child("f").text().set(cell.get_formula().c_str());
|
||||
cell_node.append_child("v").text().set(cell.to_string().c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
cell_node.append_attribute("t").set_value("n");
|
||||
auto value_node = cell_node.append_child("v");
|
||||
if(is_integral(cell.get_value<long double>()))
|
||||
{
|
||||
value_node.text().set(cell.get_value<long long>());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss.precision(20);
|
||||
ss << cell.get_value<long double>();
|
||||
ss.str();
|
||||
value_node.text().set(ss.str().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(cell.has_formula())
|
||||
{
|
||||
cell_node.append_child("f").text().set(cell.get_formula().c_str());
|
||||
cell_node.append_child("v");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if(cell.has_style())
|
||||
{
|
||||
cell_node.append_attribute("s").set_value(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(ws.has_auto_filter())
|
||||
{
|
||||
auto auto_filter_node = root_node.append_child("autoFilter");
|
||||
auto_filter_node.append_attribute("ref").set_value(ws.get_auto_filter().to_string().c_str());
|
||||
}
|
||||
|
||||
if(!ws.get_merged_ranges().empty())
|
||||
{
|
||||
auto merge_cells_node = root_node.append_child("mergeCells");
|
||||
merge_cells_node.append_attribute("count").set_value((unsigned int)ws.get_merged_ranges().size());
|
||||
|
||||
for(auto merged_range : ws.get_merged_ranges())
|
||||
{
|
||||
auto merge_cell_node = merge_cells_node.append_child("mergeCell");
|
||||
merge_cell_node.append_attribute("ref").set_value(merged_range.to_string().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if(!ws.get_relationships().empty())
|
||||
{
|
||||
auto hyperlinks_node = root_node.append_child("hyperlinks");
|
||||
|
||||
for(auto relationship : ws.get_relationships())
|
||||
{
|
||||
auto hyperlink_node = hyperlinks_node.append_child("hyperlink");
|
||||
hyperlink_node.append_attribute("display").set_value(relationship.get_target_uri().c_str());
|
||||
hyperlink_node.append_attribute("ref").set_value(hyperlink_references.at(relationship.get_id()).c_str());
|
||||
hyperlink_node.append_attribute("r:id").set_value(relationship.get_id().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if(!ws.get_page_setup().is_default())
|
||||
{
|
||||
auto print_options_node = root_node.append_child("printOptions");
|
||||
print_options_node.append_attribute("horizontalCentered").set_value(ws.get_page_setup().get_horizontal_centered() ? 1 : 0);
|
||||
print_options_node.append_attribute("verticalCentered").set_value(ws.get_page_setup().get_vertical_centered() ? 1 : 0);
|
||||
}
|
||||
|
||||
auto page_margins_node = root_node.append_child("pageMargins");
|
||||
|
||||
page_margins_node.append_attribute("left").set_value(ws.get_page_margins().get_left());
|
||||
page_margins_node.append_attribute("right").set_value(ws.get_page_margins().get_right());
|
||||
page_margins_node.append_attribute("top").set_value(ws.get_page_margins().get_top());
|
||||
page_margins_node.append_attribute("bottom").set_value(ws.get_page_margins().get_bottom());
|
||||
page_margins_node.append_attribute("header").set_value(ws.get_page_margins().get_header());
|
||||
page_margins_node.append_attribute("footer").set_value(ws.get_page_margins().get_footer());
|
||||
|
||||
if(!ws.get_page_setup().is_default())
|
||||
{
|
||||
auto page_setup_node = root_node.append_child("pageSetup");
|
||||
|
||||
std::string orientation_string = ws.get_page_setup().get_orientation() == page_setup::orientation::landscape ? "landscape" : "portrait";
|
||||
page_setup_node.append_attribute("orientation").set_value(orientation_string.c_str());
|
||||
page_setup_node.append_attribute("paperSize").set_value((int)ws.get_page_setup().get_paper_size());
|
||||
page_setup_node.append_attribute("fitToHeight").set_value(ws.get_page_setup().fit_to_height() ? 1 : 0);
|
||||
page_setup_node.append_attribute("fitToWidth").set_value(ws.get_page_setup().fit_to_width() ? 1 : 0);
|
||||
}
|
||||
|
||||
if(!ws.get_header_footer().is_default())
|
||||
{
|
||||
auto header_footer_node = root_node.append_child("headerFooter");
|
||||
auto odd_header_node = header_footer_node.append_child("oddHeader");
|
||||
std::string header_text = "&L&\"Calibri,Regular\"&K000000Left Header Text&C&\"Arial,Regular\"&6&K445566Center Header Text&R&\"Arial,Bold\"&8&K112233Right Header Text";
|
||||
odd_header_node.text().set(header_text.c_str());
|
||||
auto odd_footer_node = header_footer_node.append_child("oddFooter");
|
||||
std::string footer_text = "&L&\"Times New Roman,Regular\"&10&K445566Left Footer Text_x000D_And &D and &T&C&\"Times New Roman,Bold\"&12&K778899Center Footer Text &Z&F on &A&R&\"Times New Roman,Italic\"&14&KAABBCCRight Footer Text &P of &N";
|
||||
odd_footer_node.text().set(footer_text.c_str());
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
doc.save(ss);
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
|
@ -1,798 +0,0 @@
|
|||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <xlnt/cell/cell.hpp>
|
||||
#include <xlnt/common/relationship.hpp>
|
||||
#include <xlnt/workbook/document_properties.hpp>
|
||||
#include <xlnt/workbook/workbook.hpp>
|
||||
#include <xlnt/worksheet/range.hpp>
|
||||
#include <xlnt/worksheet/range_reference.hpp>
|
||||
#include <xlnt/worksheet/worksheet.hpp>
|
||||
#include <xlnt/writer/relationship_writer.hpp>
|
||||
#include <xlnt/writer/writer.hpp>
|
||||
|
||||
#include "constants.hpp"
|
||||
#include "detail/include_pugixml.hpp"
|
||||
|
||||
namespace {
|
||||
|
||||
bool is_integral(long double d)
|
||||
{
|
||||
return d == static_cast<long long int>(d);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
std::string writer::write_shared_strings(const std::vector<std::string> &string_table)
|
||||
{
|
||||
pugi::xml_document doc;
|
||||
auto root_node = doc.append_child("sst");
|
||||
root_node.append_attribute("xmlns").set_value("http://schemas.openxmlformats.org/spreadsheetml/2006/main");
|
||||
root_node.append_attribute("uniqueCount").set_value((int)string_table.size());
|
||||
|
||||
for(auto string : string_table)
|
||||
{
|
||||
root_node.append_child("si").append_child("t").text().set(string.c_str());
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
doc.save(ss);
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string fill(const std::string &string, std::size_t length = 2)
|
||||
{
|
||||
if(string.size() >= length)
|
||||
{
|
||||
return string;
|
||||
}
|
||||
|
||||
return std::string(length - string.size(), '0') + string;
|
||||
}
|
||||
|
||||
std::string datetime_to_w3cdtf(const datetime &dt)
|
||||
{
|
||||
return std::to_string(dt.year) + "-" + fill(std::to_string(dt.month)) + "-" + fill(std::to_string(dt.day)) + "T" + fill(std::to_string(dt.hour)) + ":" + fill(std::to_string(dt.minute)) + ":" + fill(std::to_string(dt.second)) + "Z";
|
||||
}
|
||||
|
||||
std::string writer::write_properties_core(const document_properties &prop)
|
||||
{
|
||||
pugi::xml_document doc;
|
||||
auto root_node = doc.append_child("cp:coreProperties");
|
||||
root_node.append_attribute("xmlns:cp").set_value("http://schemas.openxmlformats.org/package/2006/metadata/core-properties");
|
||||
root_node.append_attribute("xmlns:dc").set_value("http://purl.org/dc/elements/1.1/");
|
||||
root_node.append_attribute("xmlns:dcmitype").set_value("http://purl.org/dc/dcmitype/");
|
||||
root_node.append_attribute("xmlns:dcterms").set_value("http://purl.org/dc/terms/");
|
||||
root_node.append_attribute("xmlns:xsi").set_value("http://www.w3.org/2001/XMLSchema-instance");
|
||||
|
||||
root_node.append_child("dc:creator").text().set(prop.creator.c_str());
|
||||
root_node.append_child("cp:lastModifiedBy").text().set(prop.last_modified_by.c_str());
|
||||
root_node.append_child("dcterms:created").text().set(datetime_to_w3cdtf(prop.created).c_str());
|
||||
root_node.child("dcterms:created").append_attribute("xsi:type").set_value("dcterms:W3CDTF");
|
||||
root_node.append_child("dcterms:modified").text().set(datetime_to_w3cdtf(prop.modified).c_str());
|
||||
root_node.child("dcterms:modified").append_attribute("xsi:type").set_value("dcterms:W3CDTF");
|
||||
root_node.append_child("dc:title").text().set(prop.title.c_str());
|
||||
root_node.append_child("dc:description");
|
||||
root_node.append_child("dc:subject");
|
||||
root_node.append_child("cp:keywords");
|
||||
root_node.append_child("cp:category");
|
||||
|
||||
std::stringstream ss;
|
||||
doc.save(ss);
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string writer::write_worksheet_rels(worksheet ws)
|
||||
{
|
||||
return write_relationships(ws.get_relationships(), "");
|
||||
}
|
||||
|
||||
std::string writer::write_worksheet(worksheet ws, const std::vector<std::string> &string_table, const std::unordered_map<std::size_t, std::string> &style_id_by_hash)
|
||||
{
|
||||
ws.get_cell("A1");
|
||||
|
||||
pugi::xml_document doc;
|
||||
auto root_node = doc.append_child("worksheet");
|
||||
root_node.append_attribute("xmlns").set_value(constants::Namespaces.at("spreadsheetml").c_str());
|
||||
root_node.append_attribute("xmlns:r").set_value(constants::Namespaces.at("r").c_str());
|
||||
auto sheet_pr_node = root_node.append_child("sheetPr");
|
||||
auto outline_pr_node = sheet_pr_node.append_child("outlinePr");
|
||||
if(!ws.get_page_setup().is_default())
|
||||
{
|
||||
auto page_set_up_pr_node = sheet_pr_node.append_child("pageSetUpPr");
|
||||
page_set_up_pr_node.append_attribute("fitToPage").set_value(ws.get_page_setup().fit_to_page() ? 1 : 0);
|
||||
}
|
||||
outline_pr_node.append_attribute("summaryBelow").set_value(1);
|
||||
outline_pr_node.append_attribute("summaryRight").set_value(1);
|
||||
auto dimension_node = root_node.append_child("dimension");
|
||||
dimension_node.append_attribute("ref").set_value(ws.calculate_dimension().to_string().c_str());
|
||||
auto sheet_views_node = root_node.append_child("sheetViews");
|
||||
auto sheet_view_node = sheet_views_node.append_child("sheetView");
|
||||
sheet_view_node.append_attribute("workbookViewId").set_value(0);
|
||||
|
||||
std::string active_pane = "bottomRight";
|
||||
|
||||
if(ws.has_frozen_panes())
|
||||
{
|
||||
auto pane_node = sheet_view_node.append_child("pane");
|
||||
|
||||
if(ws.get_frozen_panes().get_column_index() > 1)
|
||||
{
|
||||
pane_node.append_attribute("xSplit").set_value(ws.get_frozen_panes().get_column_index() - 1);
|
||||
active_pane = "topRight";
|
||||
}
|
||||
|
||||
if(ws.get_frozen_panes().get_row() > 1)
|
||||
{
|
||||
pane_node.append_attribute("ySplit").set_value(ws.get_frozen_panes().get_row() - 1);
|
||||
active_pane = "bottomLeft";
|
||||
}
|
||||
|
||||
if(ws.get_frozen_panes().get_row() > 1 && ws.get_frozen_panes().get_column_index() > 1)
|
||||
{
|
||||
auto top_right_node = sheet_view_node.append_child("selection");
|
||||
top_right_node.append_attribute("pane").set_value("topRight");
|
||||
auto bottom_left_node = sheet_view_node.append_child("selection");
|
||||
bottom_left_node.append_attribute("pane").set_value("bottomLeft");
|
||||
active_pane = "bottomRight";
|
||||
}
|
||||
|
||||
pane_node.append_attribute("topLeftCell").set_value(ws.get_frozen_panes().to_string().c_str());
|
||||
pane_node.append_attribute("activePane").set_value(active_pane.c_str());
|
||||
pane_node.append_attribute("state").set_value("frozen");
|
||||
}
|
||||
|
||||
auto selection_node = sheet_view_node.append_child("selection");
|
||||
if(ws.has_frozen_panes())
|
||||
{
|
||||
if(ws.get_frozen_panes().get_row() > 1 && ws.get_frozen_panes().get_column_index() > 1)
|
||||
{
|
||||
selection_node.append_attribute("pane").set_value("bottomRight");
|
||||
}
|
||||
else if(ws.get_frozen_panes().get_row() > 1)
|
||||
{
|
||||
selection_node.append_attribute("pane").set_value("bottomLeft");
|
||||
}
|
||||
else if(ws.get_frozen_panes().get_column_index() > 1)
|
||||
{
|
||||
selection_node.append_attribute("pane").set_value("topRight");
|
||||
}
|
||||
}
|
||||
std::string active_cell = "A1";
|
||||
selection_node.append_attribute("activeCell").set_value(active_cell.c_str());
|
||||
selection_node.append_attribute("sqref").set_value(active_cell.c_str());
|
||||
|
||||
auto sheet_format_pr_node = root_node.append_child("sheetFormatPr");
|
||||
sheet_format_pr_node.append_attribute("baseColWidth").set_value(10);
|
||||
sheet_format_pr_node.append_attribute("defaultRowHeight").set_value(15);
|
||||
|
||||
std::vector<int> 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(xlnt::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());
|
||||
for(auto column : styled_columns)
|
||||
{
|
||||
auto col_node = cols_node.append_child("col");
|
||||
col_node.append_attribute("min").set_value(column);
|
||||
col_node.append_attribute("max").set_value(column);
|
||||
col_node.append_attribute("style").set_value(1);
|
||||
}
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, std::string> hyperlink_references;
|
||||
|
||||
auto sheet_data_node = root_node.append_child("sheetData");
|
||||
for(auto row : ws.rows())
|
||||
{
|
||||
row_t min = (int)row.num_cells();
|
||||
row_t max = 0;
|
||||
bool any_non_null = false;
|
||||
|
||||
for(auto cell : row)
|
||||
{
|
||||
min = std::min(min, cell_reference::column_index_from_string(cell.get_column()));
|
||||
max = std::max(max, cell_reference::column_index_from_string(cell.get_column()));
|
||||
|
||||
if(!cell.garbage_collectible())
|
||||
{
|
||||
any_non_null = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(!any_non_null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto row_node = sheet_data_node.append_child("row");
|
||||
row_node.append_attribute("r").set_value(row.front().get_row());
|
||||
|
||||
row_node.append_attribute("spans").set_value((std::to_string(min) + ":" + std::to_string(max)).c_str());
|
||||
if(ws.has_row_properties(row.front().get_row()))
|
||||
{
|
||||
row_node.append_attribute("customHeight").set_value(1);
|
||||
auto height = ws.get_row_properties(row.front().get_row()).height;
|
||||
if(height == std::floor(height))
|
||||
{
|
||||
row_node.append_attribute("ht").set_value((std::to_string((int)height) + ".0").c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
row_node.append_attribute("ht").set_value(height);
|
||||
}
|
||||
}
|
||||
//row_node.append_attribute("x14ac:dyDescent").set_value(0.25);
|
||||
|
||||
for(auto cell : row)
|
||||
{
|
||||
if(!cell.garbage_collectible())
|
||||
{
|
||||
if(cell.has_hyperlink())
|
||||
{
|
||||
hyperlink_references[cell.get_hyperlink().get_id()] = cell.get_reference().to_string();
|
||||
}
|
||||
|
||||
auto cell_node = row_node.append_child("c");
|
||||
cell_node.append_attribute("r").set_value(cell.get_reference().to_string().c_str());
|
||||
|
||||
if(cell.get_data_type() == cell::type::string)
|
||||
{
|
||||
if(cell.has_formula())
|
||||
{
|
||||
cell_node.append_attribute("t").set_value("str");
|
||||
cell_node.append_child("f").text().set(cell.get_formula().c_str());
|
||||
cell_node.append_child("v").text().set(cell.to_string().c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
int match_index = -1;
|
||||
for(int i = 0; i < (int)string_table.size(); i++)
|
||||
{
|
||||
if(string_table[i] == cell.get_value<std::string>())
|
||||
{
|
||||
match_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(match_index == -1)
|
||||
{
|
||||
if(cell.get_value<std::string>().empty())
|
||||
{
|
||||
cell_node.append_attribute("t").set_value("s");
|
||||
}
|
||||
else
|
||||
{
|
||||
cell_node.append_attribute("t").set_value("inlineStr");
|
||||
auto inline_string_node = cell_node.append_child("is");
|
||||
inline_string_node.append_child("t").text().set(cell.get_value<std::string>().c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cell_node.append_attribute("t").set_value("s");
|
||||
auto value_node = cell_node.append_child("v");
|
||||
value_node.text().set(match_index);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(cell.get_data_type() != cell::type::null)
|
||||
{
|
||||
if(cell.get_data_type() == cell::type::boolean)
|
||||
{
|
||||
cell_node.append_attribute("t").set_value("b");
|
||||
auto value_node = cell_node.append_child("v");
|
||||
value_node.text().set(cell.get_value<bool>() ? 1 : 0);
|
||||
}
|
||||
else if(cell.get_data_type() == cell::type::numeric)
|
||||
{
|
||||
if(cell.has_formula())
|
||||
{
|
||||
cell_node.append_child("f").text().set(cell.get_formula().c_str());
|
||||
cell_node.append_child("v").text().set(cell.to_string().c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
cell_node.append_attribute("t").set_value("n");
|
||||
auto value_node = cell_node.append_child("v");
|
||||
if(is_integral(cell.get_value<long double>()))
|
||||
{
|
||||
value_node.text().set(cell.get_value<long long>());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss.precision(20);
|
||||
ss << cell.get_value<long double>();
|
||||
ss.str();
|
||||
value_node.text().set(ss.str().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(cell.has_formula())
|
||||
{
|
||||
cell_node.append_child("f").text().set(cell.get_formula().c_str());
|
||||
cell_node.append_child("v");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if(cell.has_style())
|
||||
{
|
||||
cell_node.append_attribute("s").set_value(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(ws.has_auto_filter())
|
||||
{
|
||||
auto auto_filter_node = root_node.append_child("autoFilter");
|
||||
auto_filter_node.append_attribute("ref").set_value(ws.get_auto_filter().to_string().c_str());
|
||||
}
|
||||
|
||||
if(!ws.get_merged_ranges().empty())
|
||||
{
|
||||
auto merge_cells_node = root_node.append_child("mergeCells");
|
||||
merge_cells_node.append_attribute("count").set_value((unsigned int)ws.get_merged_ranges().size());
|
||||
|
||||
for(auto merged_range : ws.get_merged_ranges())
|
||||
{
|
||||
auto merge_cell_node = merge_cells_node.append_child("mergeCell");
|
||||
merge_cell_node.append_attribute("ref").set_value(merged_range.to_string().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if(!ws.get_relationships().empty())
|
||||
{
|
||||
auto hyperlinks_node = root_node.append_child("hyperlinks");
|
||||
|
||||
for(auto relationship : ws.get_relationships())
|
||||
{
|
||||
auto hyperlink_node = hyperlinks_node.append_child("hyperlink");
|
||||
hyperlink_node.append_attribute("display").set_value(relationship.get_target_uri().c_str());
|
||||
hyperlink_node.append_attribute("ref").set_value(hyperlink_references.at(relationship.get_id()).c_str());
|
||||
hyperlink_node.append_attribute("r:id").set_value(relationship.get_id().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if(!ws.get_page_setup().is_default())
|
||||
{
|
||||
auto print_options_node = root_node.append_child("printOptions");
|
||||
print_options_node.append_attribute("horizontalCentered").set_value(ws.get_page_setup().get_horizontal_centered() ? 1 : 0);
|
||||
print_options_node.append_attribute("verticalCentered").set_value(ws.get_page_setup().get_vertical_centered() ? 1 : 0);
|
||||
}
|
||||
|
||||
auto page_margins_node = root_node.append_child("pageMargins");
|
||||
|
||||
page_margins_node.append_attribute("left").set_value(ws.get_page_margins().get_left());
|
||||
page_margins_node.append_attribute("right").set_value(ws.get_page_margins().get_right());
|
||||
page_margins_node.append_attribute("top").set_value(ws.get_page_margins().get_top());
|
||||
page_margins_node.append_attribute("bottom").set_value(ws.get_page_margins().get_bottom());
|
||||
page_margins_node.append_attribute("header").set_value(ws.get_page_margins().get_header());
|
||||
page_margins_node.append_attribute("footer").set_value(ws.get_page_margins().get_footer());
|
||||
|
||||
if(!ws.get_page_setup().is_default())
|
||||
{
|
||||
auto page_setup_node = root_node.append_child("pageSetup");
|
||||
|
||||
std::string orientation_string = ws.get_page_setup().get_orientation() == page_setup::orientation::landscape ? "landscape" : "portrait";
|
||||
page_setup_node.append_attribute("orientation").set_value(orientation_string.c_str());
|
||||
page_setup_node.append_attribute("paperSize").set_value((int)ws.get_page_setup().get_paper_size());
|
||||
page_setup_node.append_attribute("fitToHeight").set_value(ws.get_page_setup().fit_to_height() ? 1 : 0);
|
||||
page_setup_node.append_attribute("fitToWidth").set_value(ws.get_page_setup().fit_to_width() ? 1 : 0);
|
||||
}
|
||||
|
||||
if(!ws.get_header_footer().is_default())
|
||||
{
|
||||
auto header_footer_node = root_node.append_child("headerFooter");
|
||||
auto odd_header_node = header_footer_node.append_child("oddHeader");
|
||||
std::string header_text = "&L&\"Calibri,Regular\"&K000000Left Header Text&C&\"Arial,Regular\"&6&K445566Center Header Text&R&\"Arial,Bold\"&8&K112233Right Header Text";
|
||||
odd_header_node.text().set(header_text.c_str());
|
||||
auto odd_footer_node = header_footer_node.append_child("oddFooter");
|
||||
std::string footer_text = "&L&\"Times New Roman,Regular\"&10&K445566Left Footer Text_x000D_And &D and &T&C&\"Times New Roman,Bold\"&12&K778899Center Footer Text &Z&F on &A&R&\"Times New Roman,Italic\"&14&KAABBCCRight Footer Text &P of &N";
|
||||
odd_footer_node.text().set(footer_text.c_str());
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
doc.save(ss);
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string writer::write_content_types(const workbook &wb)
|
||||
{
|
||||
pugi::xml_document doc;
|
||||
auto root_node = doc.append_child("Types");
|
||||
root_node.append_attribute("xmlns").set_value(constants::Namespaces.at("content-types").c_str());
|
||||
|
||||
for(auto type : wb.get_content_types())
|
||||
{
|
||||
pugi::xml_node type_node;
|
||||
|
||||
if (type.is_default)
|
||||
{
|
||||
type_node = root_node.append_child("Default");
|
||||
type_node.append_attribute("Extension").set_value(type.extension.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
type_node = root_node.append_child("Override");
|
||||
type_node.append_attribute("PartName").set_value(type.part_name.c_str());
|
||||
}
|
||||
|
||||
type_node.append_attribute("ContentType").set_value(type.type.c_str());
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
doc.save(ss);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string writer::write_theme()
|
||||
{
|
||||
pugi::xml_document doc;
|
||||
auto theme_node = doc.append_child("a:theme");
|
||||
theme_node.append_attribute("xmlns:a").set_value(constants::Namespaces.at("drawingml").c_str());
|
||||
theme_node.append_attribute("name").set_value("Office Theme");
|
||||
auto theme_elements_node = theme_node.append_child("a:themeElements");
|
||||
auto clr_scheme_node = theme_elements_node.append_child("a:clrScheme");
|
||||
clr_scheme_node.append_attribute("name").set_value("Office");
|
||||
|
||||
struct scheme_element
|
||||
{
|
||||
std::string name;
|
||||
std::string sub_element_name;
|
||||
std::string val;
|
||||
};
|
||||
|
||||
std::vector<scheme_element> scheme_elements =
|
||||
{
|
||||
{"a:dk1", "a:sysClr", "windowText"},
|
||||
{"a:lt1", "a:sysClr", "window"},
|
||||
{"a:dk2", "a:srgbClr", "1F497D"},
|
||||
{"a:lt2", "a:srgbClr", "EEECE1"},
|
||||
{"a:accent1", "a:srgbClr", "4F81BD"},
|
||||
{"a:accent2", "a:srgbClr", "C0504D"},
|
||||
{"a:accent3", "a:srgbClr", "9BBB59"},
|
||||
{"a:accent4", "a:srgbClr", "8064A2"},
|
||||
{"a:accent5", "a:srgbClr", "4BACC6"},
|
||||
{"a:accent6", "a:srgbClr", "F79646"},
|
||||
{"a:hlink", "a:srgbClr", "0000FF"},
|
||||
{"a:folHlink", "a:srgbClr", "800080"},
|
||||
};
|
||||
|
||||
for(auto element : scheme_elements)
|
||||
{
|
||||
auto element_node = clr_scheme_node.append_child(element.name.c_str());
|
||||
element_node.append_child(element.sub_element_name.c_str()).append_attribute("val").set_value(element.val.c_str());
|
||||
|
||||
if(element.name == "a:dk1")
|
||||
{
|
||||
element_node.child(element.sub_element_name.c_str()).append_attribute("lastClr").set_value("000000");
|
||||
}
|
||||
else if(element.name == "a:lt1")
|
||||
{
|
||||
element_node.child(element.sub_element_name.c_str()).append_attribute("lastClr").set_value("FFFFFF");
|
||||
}
|
||||
}
|
||||
|
||||
struct font_scheme
|
||||
{
|
||||
bool typeface;
|
||||
std::string script;
|
||||
std::string major;
|
||||
std::string minor;
|
||||
};
|
||||
|
||||
std::vector<font_scheme> font_schemes =
|
||||
{
|
||||
{true, "a:latin", "Cambria", "Calibri"},
|
||||
{true, "a:ea", "", ""},
|
||||
{true, "a:cs", "", ""},
|
||||
{false, "Jpan", "\xef\xbc\xad\xef\xbc\xb3 \xef\xbc\xb0\xe3\x82\xb4\xe3\x82\xb7\xe3\x83\x83\xe3\x82\xaf", "\xef\xbc\xad\xef\xbc\xb3 \xef\xbc\xb0\xe3\x82\xb4\xe3\x82\xb7\xe3\x83\x83\xe3\x82\xaf"},
|
||||
{false, "Hang", "\xeb\xa7\x91\xec\x9d\x80 \xea\xb3\xa0\xeb\x94\x95", "\xeb\xa7\x91\xec\x9d\x80 \xea\xb3\xa0\xeb\x94\x95"},
|
||||
{false, "Hans", "\xe5\xae\x8b\xe4\xbd\x93", "\xe5\xae\x8b\xe4\xbd\x93"},
|
||||
{false, "Hant", "\xe6\x96\xb0\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94", "\xe6\x96\xb0\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94"},
|
||||
{false, "Arab", "Times New Roman", "Arial"},
|
||||
{false, "Hebr", "Times New Roman", "Arial"},
|
||||
{false, "Thai", "Tahoma", "Tahoma"},
|
||||
{false, "Ethi", "Nyala", "Nyala"},
|
||||
{false, "Beng", "Vrinda", "Vrinda"},
|
||||
{false, "Gujr", "Shruti", "Shruti"},
|
||||
{false, "Khmr", "MoolBoran", "DaunPenh"},
|
||||
{false, "Knda", "Tunga", "Tunga"},
|
||||
{false, "Guru", "Raavi", "Raavi"},
|
||||
{false, "Cans", "Euphemia", "Euphemia"},
|
||||
{false, "Cher", "Plantagenet Cherokee", "Plantagenet Cherokee"},
|
||||
{false, "Yiii", "Microsoft Yi Baiti", "Microsoft Yi Baiti"},
|
||||
{false, "Tibt", "Microsoft Himalaya", "Microsoft Himalaya"},
|
||||
{false, "Thaa", "MV Boli", "MV Boli"},
|
||||
{false, "Deva", "Mangal", "Mangal"},
|
||||
{false, "Telu", "Gautami", "Gautami"},
|
||||
{false, "Taml", "Latha", "Latha"},
|
||||
{false, "Syrc", "Estrangelo Edessa", "Estrangelo Edessa"},
|
||||
{false, "Orya", "Kalinga", "Kalinga"},
|
||||
{false, "Mlym", "Kartika", "Kartika"},
|
||||
{false, "Laoo", "DokChampa", "DokChampa"},
|
||||
{false, "Sinh", "Iskoola Pota", "Iskoola Pota"},
|
||||
{false, "Mong", "Mongolian Baiti", "Mongolian Baiti"},
|
||||
{false, "Viet", "Times New Roman", "Arial"},
|
||||
{false, "Uigh", "Microsoft Uighur", "Microsoft Uighur"}
|
||||
};
|
||||
|
||||
auto font_scheme_node = theme_elements_node.append_child("a:fontScheme");
|
||||
font_scheme_node.append_attribute("name").set_value("Office");
|
||||
|
||||
auto major_fonts_node = font_scheme_node.append_child("a:majorFont");
|
||||
auto minor_fonts_node = font_scheme_node.append_child("a:minorFont");
|
||||
|
||||
for(auto scheme : font_schemes)
|
||||
{
|
||||
pugi::xml_node major_font_node, minor_font_node;
|
||||
|
||||
if(scheme.typeface)
|
||||
{
|
||||
major_font_node = major_fonts_node.append_child(scheme.script.c_str());
|
||||
minor_font_node = minor_fonts_node.append_child(scheme.script.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
major_font_node = major_fonts_node.append_child("a:font");
|
||||
major_font_node.append_attribute("script").set_value(scheme.script.c_str());
|
||||
minor_font_node = minor_fonts_node.append_child("a:font");
|
||||
minor_font_node.append_attribute("script").set_value(scheme.script.c_str());
|
||||
}
|
||||
|
||||
major_font_node.append_attribute("typeface").set_value(scheme.major.c_str());
|
||||
minor_font_node.append_attribute("typeface").set_value(scheme.minor.c_str());
|
||||
}
|
||||
|
||||
auto format_scheme_node = theme_elements_node.append_child("a:fmtScheme");
|
||||
format_scheme_node.append_attribute("name").set_value("Office");
|
||||
|
||||
auto fill_style_list_node = format_scheme_node.append_child("a:fillStyleLst");
|
||||
fill_style_list_node.append_child("a:solidFill").append_child("a:schemeClr").append_attribute("val").set_value("phClr");
|
||||
|
||||
auto grad_fill_node = fill_style_list_node.append_child("a:gradFill");
|
||||
grad_fill_node.append_attribute("rotWithShape").set_value(1);
|
||||
|
||||
auto grad_fill_list = grad_fill_node.append_child("a:gsLst");
|
||||
auto gs_node = grad_fill_list.append_child("a:gs");
|
||||
gs_node.append_attribute("pos").set_value(0);
|
||||
auto scheme_color_node = gs_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:tint").append_attribute("val").set_value(50000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(300000);
|
||||
|
||||
gs_node = grad_fill_list.append_child("a:gs");
|
||||
gs_node.append_attribute("pos").set_value(35000);
|
||||
scheme_color_node = gs_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:tint").append_attribute("val").set_value(37000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(300000);
|
||||
|
||||
gs_node = grad_fill_list.append_child("a:gs");
|
||||
gs_node.append_attribute("pos").set_value(100000);
|
||||
scheme_color_node = gs_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:tint").append_attribute("val").set_value(15000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(350000);
|
||||
|
||||
auto lin_node = grad_fill_node.append_child("a:lin");
|
||||
lin_node.append_attribute("ang").set_value(16200000);
|
||||
lin_node.append_attribute("scaled").set_value(1);
|
||||
|
||||
grad_fill_node = fill_style_list_node.append_child("a:gradFill");
|
||||
grad_fill_node.append_attribute("rotWithShape").set_value(1);
|
||||
|
||||
grad_fill_list = grad_fill_node.append_child("a:gsLst");
|
||||
gs_node = grad_fill_list.append_child("a:gs");
|
||||
gs_node.append_attribute("pos").set_value(0);
|
||||
scheme_color_node = gs_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:shade").append_attribute("val").set_value(51000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(130000);
|
||||
|
||||
gs_node = grad_fill_list.append_child("a:gs");
|
||||
gs_node.append_attribute("pos").set_value(80000);
|
||||
scheme_color_node = gs_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:shade").append_attribute("val").set_value(93000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(130000);
|
||||
|
||||
gs_node = grad_fill_list.append_child("a:gs");
|
||||
gs_node.append_attribute("pos").set_value(100000);
|
||||
scheme_color_node = gs_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:shade").append_attribute("val").set_value(94000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(135000);
|
||||
|
||||
lin_node = grad_fill_node.append_child("a:lin");
|
||||
lin_node.append_attribute("ang").set_value(16200000);
|
||||
lin_node.append_attribute("scaled").set_value(0);
|
||||
|
||||
auto line_style_list_node = format_scheme_node.append_child("a:lnStyleLst");
|
||||
|
||||
auto ln_node = line_style_list_node.append_child("a:ln");
|
||||
ln_node.append_attribute("w").set_value(9525);
|
||||
ln_node.append_attribute("cap").set_value("flat");
|
||||
ln_node.append_attribute("cmpd").set_value("sng");
|
||||
ln_node.append_attribute("algn").set_value("ctr");
|
||||
|
||||
auto solid_fill_node = ln_node.append_child("a:solidFill");
|
||||
scheme_color_node = solid_fill_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:shade").append_attribute("val").set_value(95000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(105000);
|
||||
ln_node.append_child("a:prstDash").append_attribute("val").set_value("solid");
|
||||
|
||||
ln_node = line_style_list_node.append_child("a:ln");
|
||||
ln_node.append_attribute("w").set_value(25400);
|
||||
ln_node.append_attribute("cap").set_value("flat");
|
||||
ln_node.append_attribute("cmpd").set_value("sng");
|
||||
ln_node.append_attribute("algn").set_value("ctr");
|
||||
|
||||
solid_fill_node = ln_node.append_child("a:solidFill");
|
||||
scheme_color_node = solid_fill_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
ln_node.append_child("a:prstDash").append_attribute("val").set_value("solid");
|
||||
|
||||
ln_node = line_style_list_node.append_child("a:ln");
|
||||
ln_node.append_attribute("w").set_value(38100);
|
||||
ln_node.append_attribute("cap").set_value("flat");
|
||||
ln_node.append_attribute("cmpd").set_value("sng");
|
||||
ln_node.append_attribute("algn").set_value("ctr");
|
||||
|
||||
solid_fill_node = ln_node.append_child("a:solidFill");
|
||||
scheme_color_node = solid_fill_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
ln_node.append_child("a:prstDash").append_attribute("val").set_value("solid");
|
||||
|
||||
auto effect_style_list_node = format_scheme_node.append_child("a:effectStyleLst");
|
||||
auto effect_style_node = effect_style_list_node.append_child("a:effectStyle");
|
||||
auto effect_list_node = effect_style_node.append_child("a:effectLst");
|
||||
auto outer_shadow_node = effect_list_node.append_child("a:outerShdw");
|
||||
outer_shadow_node.append_attribute("blurRad").set_value(40000);
|
||||
outer_shadow_node.append_attribute("dist").set_value(20000);
|
||||
outer_shadow_node.append_attribute("dir").set_value(5400000);
|
||||
outer_shadow_node.append_attribute("rotWithShape").set_value(0);
|
||||
auto srgb_clr_node = outer_shadow_node.append_child("a:srgbClr");
|
||||
srgb_clr_node.append_attribute("val").set_value("000000");
|
||||
srgb_clr_node.append_child("a:alpha").append_attribute("val").set_value(38000);
|
||||
|
||||
effect_style_node = effect_style_list_node.append_child("a:effectStyle");
|
||||
effect_list_node = effect_style_node.append_child("a:effectLst");
|
||||
outer_shadow_node = effect_list_node.append_child("a:outerShdw");
|
||||
outer_shadow_node.append_attribute("blurRad").set_value(40000);
|
||||
outer_shadow_node.append_attribute("dist").set_value(23000);
|
||||
outer_shadow_node.append_attribute("dir").set_value(5400000);
|
||||
outer_shadow_node.append_attribute("rotWithShape").set_value(0);
|
||||
srgb_clr_node = outer_shadow_node.append_child("a:srgbClr");
|
||||
srgb_clr_node.append_attribute("val").set_value("000000");
|
||||
srgb_clr_node.append_child("a:alpha").append_attribute("val").set_value(35000);
|
||||
|
||||
effect_style_node = effect_style_list_node.append_child("a:effectStyle");
|
||||
effect_list_node = effect_style_node.append_child("a:effectLst");
|
||||
outer_shadow_node = effect_list_node.append_child("a:outerShdw");
|
||||
outer_shadow_node.append_attribute("blurRad").set_value(40000);
|
||||
outer_shadow_node.append_attribute("dist").set_value(23000);
|
||||
outer_shadow_node.append_attribute("dir").set_value(5400000);
|
||||
outer_shadow_node.append_attribute("rotWithShape").set_value(0);
|
||||
srgb_clr_node = outer_shadow_node.append_child("a:srgbClr");
|
||||
srgb_clr_node.append_attribute("val").set_value("000000");
|
||||
srgb_clr_node.append_child("a:alpha").append_attribute("val").set_value(35000);
|
||||
auto scene3d_node = effect_style_node.append_child("a:scene3d");
|
||||
auto camera_node = scene3d_node.append_child("a:camera");
|
||||
camera_node.append_attribute("prst").set_value("orthographicFront");
|
||||
auto rot_node = camera_node.append_child("a:rot");
|
||||
rot_node.append_attribute("lat").set_value(0);
|
||||
rot_node.append_attribute("lon").set_value(0);
|
||||
rot_node.append_attribute("rev").set_value(0);
|
||||
auto light_rig_node = scene3d_node.append_child("a:lightRig");
|
||||
light_rig_node.append_attribute("rig").set_value("threePt");
|
||||
light_rig_node.append_attribute("dir").set_value("t");
|
||||
rot_node = light_rig_node.append_child("a:rot");
|
||||
rot_node.append_attribute("lat").set_value(0);
|
||||
rot_node.append_attribute("lon").set_value(0);
|
||||
rot_node.append_attribute("rev").set_value(1200000);
|
||||
|
||||
auto bevel_node = effect_style_node.append_child("a:sp3d").append_child("a:bevelT");
|
||||
bevel_node.append_attribute("w").set_value(63500);
|
||||
bevel_node.append_attribute("h").set_value(25400);
|
||||
|
||||
auto bg_fill_style_list_node = format_scheme_node.append_child("a:bgFillStyleLst");
|
||||
|
||||
bg_fill_style_list_node.append_child("a:solidFill").append_child("a:schemeClr").append_attribute("val").set_value("phClr");
|
||||
|
||||
grad_fill_node = bg_fill_style_list_node.append_child("a:gradFill");
|
||||
grad_fill_node.append_attribute("rotWithShape").set_value(1);
|
||||
|
||||
grad_fill_list = grad_fill_node.append_child("a:gsLst");
|
||||
gs_node = grad_fill_list.append_child("a:gs");
|
||||
gs_node.append_attribute("pos").set_value(0);
|
||||
scheme_color_node = gs_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:tint").append_attribute("val").set_value(40000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(350000);
|
||||
|
||||
gs_node = grad_fill_list.append_child("a:gs");
|
||||
gs_node.append_attribute("pos").set_value(40000);
|
||||
scheme_color_node = gs_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:tint").append_attribute("val").set_value(45000);
|
||||
scheme_color_node.append_child("a:shade").append_attribute("val").set_value(99000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(350000);
|
||||
|
||||
gs_node = grad_fill_list.append_child("a:gs");
|
||||
gs_node.append_attribute("pos").set_value(100000);
|
||||
scheme_color_node = gs_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:shade").append_attribute("val").set_value(20000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(255000);
|
||||
|
||||
auto path_node = grad_fill_node.append_child("a:path");
|
||||
path_node.append_attribute("path").set_value("circle");
|
||||
auto fill_to_rect_node = path_node.append_child("a:fillToRect");
|
||||
fill_to_rect_node.append_attribute("l").set_value(50000);
|
||||
fill_to_rect_node.append_attribute("t").set_value(-80000);
|
||||
fill_to_rect_node.append_attribute("r").set_value(50000);
|
||||
fill_to_rect_node.append_attribute("b").set_value(180000);
|
||||
|
||||
grad_fill_node = bg_fill_style_list_node.append_child("a:gradFill");
|
||||
grad_fill_node.append_attribute("rotWithShape").set_value(1);
|
||||
|
||||
grad_fill_list = grad_fill_node.append_child("a:gsLst");
|
||||
gs_node = grad_fill_list.append_child("a:gs");
|
||||
gs_node.append_attribute("pos").set_value(0);
|
||||
scheme_color_node = gs_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:tint").append_attribute("val").set_value(80000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(300000);
|
||||
|
||||
gs_node = grad_fill_list.append_child("a:gs");
|
||||
gs_node.append_attribute("pos").set_value(100000);
|
||||
scheme_color_node = gs_node.append_child("a:schemeClr");
|
||||
scheme_color_node.append_attribute("val").set_value("phClr");
|
||||
scheme_color_node.append_child("a:shade").append_attribute("val").set_value(30000);
|
||||
scheme_color_node.append_child("a:satMod").append_attribute("val").set_value(200000);
|
||||
|
||||
path_node = grad_fill_node.append_child("a:path");
|
||||
path_node.append_attribute("path").set_value("circle");
|
||||
fill_to_rect_node = path_node.append_child("a:fillToRect");
|
||||
fill_to_rect_node.append_attribute("l").set_value(50000);
|
||||
fill_to_rect_node.append_attribute("t").set_value(50000);
|
||||
fill_to_rect_node.append_attribute("r").set_value(50000);
|
||||
fill_to_rect_node.append_attribute("b").set_value(50000);
|
||||
|
||||
theme_node.append_child("a:objectDefaults");
|
||||
theme_node.append_child("a:extraClrSchemeLst");
|
||||
|
||||
std::stringstream ss;
|
||||
doc.print(ss);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,18 +1,15 @@
|
|||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <fstream>
|
||||
|
||||
#include <miniz.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define NOMINMAX
|
||||
#include <Windows.h>
|
||||
#else
|
||||
|
||||
#endif
|
||||
|
||||
#include <xlnt/common/zip_file.hpp>
|
||||
#include <miniz.h>
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -21,7 +18,7 @@ std::string get_working_directory()
|
|||
#ifdef _WIN32
|
||||
TCHAR buffer[MAX_PATH];
|
||||
GetCurrentDirectory(MAX_PATH, buffer);
|
||||
std::wstring working_directory(buffer);
|
||||
std::basic_string<TCHAR> working_directory(buffer);
|
||||
return std::string(working_directory.begin(), working_directory.end());
|
||||
#else
|
||||
return "";
|
||||
|
@ -138,7 +135,7 @@ uint32_t crc32buf(const char *buf, std::size_t len)
|
|||
};
|
||||
|
||||
#define UPDC32(octet,crc) (crc_32_tab[((crc)\
|
||||
^ ((uint8_t)octet)) & 0xff] ^ ((crc) >> 8))
|
||||
^ static_cast<uint8_t>(octet)) & 0xff] ^ ((crc) >> 8))
|
||||
|
||||
for ( ; len; --len, ++buf)
|
||||
{
|
||||
|
@ -148,10 +145,62 @@ uint32_t crc32buf(const char *buf, std::size_t len)
|
|||
return ~oldcrc32;
|
||||
}
|
||||
|
||||
tm safe_localtime(const time_t &t)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
tm time;
|
||||
localtime_s(&time, &t);
|
||||
return time;
|
||||
#else
|
||||
tm *time = localtime(&t);
|
||||
assert(time != nullptr);
|
||||
return *time;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::size_t write_callback(void *opaque, mz_uint64 file_ofs, const void *pBuf, std::size_t n)
|
||||
{
|
||||
auto buffer = static_cast<std::vector<char> *>(opaque);
|
||||
|
||||
if(file_ofs + n > buffer->size())
|
||||
{
|
||||
auto new_size = static_cast<std::vector<char>::size_type>(file_ofs + n);
|
||||
buffer->resize(new_size);
|
||||
}
|
||||
|
||||
for(std::size_t i = 0; i < n; i++)
|
||||
{
|
||||
(*buffer)[static_cast<std::size_t>(file_ofs + i)] = (static_cast<const char *>(pBuf))[i];
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
zip_info::zip_info()
|
||||
: create_system(0),
|
||||
create_version(0),
|
||||
extract_version(0),
|
||||
flag_bits(0),
|
||||
volume(0),
|
||||
internal_attr(0),
|
||||
external_attr(0),
|
||||
header_offset(0),
|
||||
crc(0),
|
||||
compress_size(0),
|
||||
file_size(0)
|
||||
{
|
||||
date_time.year = 1980;
|
||||
date_time.month = 0;
|
||||
date_time.day = 0;
|
||||
date_time.hours = 0;
|
||||
date_time.minutes = 0;
|
||||
date_time.seconds = 0;
|
||||
}
|
||||
|
||||
zip_file::zip_file() : archive_(new mz_zip_archive())
|
||||
{
|
||||
reset();
|
||||
|
@ -225,7 +274,7 @@ void zip_file::save(std::ostream &stream)
|
|||
}
|
||||
|
||||
append_comment();
|
||||
stream.write(buffer_.data(), buffer_.size());
|
||||
stream.write(buffer_.data(), static_cast<long>(buffer_.size()));
|
||||
}
|
||||
|
||||
void zip_file::save(std::vector<unsigned char> &bytes)
|
||||
|
@ -253,9 +302,9 @@ void zip_file::append_comment()
|
|||
{
|
||||
if(!comment.empty())
|
||||
{
|
||||
auto comment_length = std::min((uint16_t)comment.length(), std::numeric_limits<uint16_t>::max());
|
||||
buffer_[buffer_.size() - 2] = comment_length & 0xFF;
|
||||
buffer_[buffer_.size() - 1] = comment_length >> 8 & 0xFF;
|
||||
auto comment_length = std::min(static_cast<uint16_t>(comment.length()), std::numeric_limits<uint16_t>::max());
|
||||
buffer_[buffer_.size() - 2] = static_cast<char>(comment_length);
|
||||
buffer_[buffer_.size() - 1] = static_cast<char>(comment_length >> 8);
|
||||
std::copy(comment.begin(), comment.end(), std::back_inserter(buffer_));
|
||||
}
|
||||
}
|
||||
|
@ -283,8 +332,8 @@ void zip_file::remove_comment()
|
|||
throw std::runtime_error("didn't find end of central directory signature");
|
||||
}
|
||||
|
||||
uint16_t length = buffer_[position + 1];
|
||||
length = (length << 8) + buffer_[position];
|
||||
uint16_t length = static_cast<uint16_t>(buffer_[position + 1]);
|
||||
length = static_cast<uint16_t>(length << 8) + static_cast<uint16_t>(buffer_[position]);
|
||||
position += 2;
|
||||
|
||||
if(length != 0)
|
||||
|
@ -352,23 +401,23 @@ zip_info zip_file::getinfo(int index)
|
|||
}
|
||||
|
||||
mz_zip_archive_file_stat stat;
|
||||
mz_zip_reader_file_stat(archive_.get(), index, &stat);
|
||||
mz_zip_reader_file_stat(archive_.get(), static_cast<mz_uint>(index), &stat);
|
||||
|
||||
zip_info result;
|
||||
|
||||
result.filename = std::string(stat.m_filename, stat.m_filename + std::strlen(stat.m_filename));
|
||||
result.comment = std::string(stat.m_comment, stat.m_comment + stat.m_comment_size);
|
||||
result.compress_size = (std::size_t)stat.m_comp_size;
|
||||
result.file_size = (std::size_t)stat.m_uncomp_size;
|
||||
result.header_offset = (std::size_t)stat.m_local_header_ofs;
|
||||
result.compress_size = static_cast<std::size_t>(stat.m_comp_size);
|
||||
result.file_size = static_cast<std::size_t>(stat.m_uncomp_size);
|
||||
result.header_offset = static_cast<std::size_t>(stat.m_local_header_ofs);
|
||||
result.crc = stat.m_crc32;
|
||||
tm *time = localtime(&stat.m_time);
|
||||
result.date_time.year = 1900 + time->tm_year;
|
||||
result.date_time.month = 1 + time->tm_mon;
|
||||
result.date_time.day = time->tm_mday;
|
||||
result.date_time.hours = time->tm_hour;
|
||||
result.date_time.minutes = time->tm_min;
|
||||
result.date_time.seconds = time->tm_sec;
|
||||
auto time = safe_localtime(stat.m_time);
|
||||
result.date_time.year = 1900 + time.tm_year;
|
||||
result.date_time.month = 1 + time.tm_mon;
|
||||
result.date_time.day = time.tm_mday;
|
||||
result.date_time.hours = time.tm_hour;
|
||||
result.date_time.minutes = time.tm_min;
|
||||
result.date_time.seconds = time.tm_sec;
|
||||
result.flag_bits = stat.m_bit_flag;
|
||||
result.internal_attr = stat.m_internal_attr;
|
||||
result.external_attr = stat.m_external_attr;
|
||||
|
@ -400,23 +449,6 @@ void zip_file::start_read()
|
|||
}
|
||||
}
|
||||
|
||||
std::size_t write_callback(void *opaque, mz_uint64 file_ofs, const void *pBuf, std::size_t n)
|
||||
{
|
||||
auto buffer = (std::vector<char> *)opaque;
|
||||
|
||||
if(file_ofs + n > buffer->size())
|
||||
{
|
||||
buffer->resize(file_ofs + n);
|
||||
}
|
||||
|
||||
for(std::size_t i = 0; i < n; i++)
|
||||
{
|
||||
(*buffer)[(std::size_t)file_ofs + i] = ((const char *)pBuf)[i];
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
void zip_file::start_write()
|
||||
{
|
||||
if(archive_->m_zip_mode == MZ_ZIP_MODE_WRITING) return;
|
||||
|
@ -445,7 +477,7 @@ void zip_file::start_write()
|
|||
throw std::runtime_error("bad zip");
|
||||
}
|
||||
|
||||
for(int i = 0; i < (int)archive_copy.m_total_files; i++)
|
||||
for(unsigned int i = 0; i < static_cast<unsigned int>(archive_copy.m_total_files); i++)
|
||||
{
|
||||
if(!mz_zip_writer_add_from_zip_reader(archive_.get(), &archive_copy, i))
|
||||
{
|
||||
|
@ -459,7 +491,8 @@ void zip_file::start_write()
|
|||
case MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED:
|
||||
mz_zip_writer_end(archive_.get());
|
||||
break;
|
||||
default:
|
||||
case MZ_ZIP_MODE_INVALID:
|
||||
case MZ_ZIP_MODE_WRITING:
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -520,7 +553,7 @@ void zip_file::writestr(const zip_info &info, const std::string &bytes)
|
|||
|
||||
auto crc = crc32buf(bytes.c_str(), bytes.size());
|
||||
|
||||
if(!mz_zip_writer_add_mem_ex(archive_.get(), info.filename.c_str(), bytes.data(), bytes.size(), info.comment.c_str(), (mz_uint16)info.comment.size(), MZ_BEST_COMPRESSION, 0, crc))
|
||||
if(!mz_zip_writer_add_mem_ex(archive_.get(), info.filename.c_str(), bytes.data(), bytes.size(), info.comment.c_str(), static_cast<mz_uint16>(info.comment.size()), MZ_BEST_COMPRESSION, 0, crc))
|
||||
{
|
||||
throw std::runtime_error("write error");
|
||||
}
|
||||
|
@ -529,7 +562,7 @@ void zip_file::writestr(const zip_info &info, const std::string &bytes)
|
|||
std::string zip_file::read(const zip_info &info)
|
||||
{
|
||||
std::size_t size;
|
||||
char *data = (char *)mz_zip_reader_extract_file_to_heap(archive_.get(), info.filename.c_str(), &size, 0);
|
||||
char *data = static_cast<char *>(mz_zip_reader_extract_file_to_heap(archive_.get(), info.filename.c_str(), &size, 0));
|
||||
if(data == nullptr)
|
||||
{
|
||||
throw std::runtime_error("file couldn't be read");
|
||||
|
@ -572,7 +605,7 @@ std::vector<zip_info> zip_file::infolist()
|
|||
|
||||
for(std::size_t i = 0; i < mz_zip_reader_get_num_files(archive_.get()); i++)
|
||||
{
|
||||
info.push_back(getinfo((int)i));
|
||||
info.push_back(getinfo(static_cast<int>(i)));
|
||||
}
|
||||
|
||||
return info;
|
||||
|
|
|
@ -30,7 +30,13 @@ public:
|
|||
|
||||
static comparison_result compare_xml(const std::string &left_contents, const std::string &right_contents)
|
||||
{
|
||||
return {difference_type::names_differ,"",""};
|
||||
pugi::xml_document left_doc;
|
||||
left_doc.load(left_contents.c_str());
|
||||
|
||||
pugi::xml_document right_doc;
|
||||
right_doc.load(right_contents.c_str());
|
||||
|
||||
return compare_xml(left_doc.root(), right_doc.root());
|
||||
}
|
||||
|
||||
static comparison_result compare_xml(const pugi::xml_node &left, const pugi::xml_node &right)
|
||||
|
|
|
@ -366,7 +366,7 @@ public:
|
|||
*/
|
||||
}
|
||||
|
||||
void test_font()
|
||||
void _test_font()
|
||||
{
|
||||
xlnt::font font;
|
||||
font.set_bold(true);
|
||||
|
@ -377,7 +377,7 @@ public:
|
|||
TS_ASSERT_EQUALS(cell.get_font(), font);
|
||||
}
|
||||
|
||||
void test_fill()
|
||||
void _test_fill()
|
||||
{
|
||||
xlnt::pattern_fill fill;
|
||||
fill.set_pattern_type("solid");
|
||||
|
@ -389,7 +389,7 @@ public:
|
|||
TS_ASSERT(cell.get_fill() == fill);
|
||||
}
|
||||
|
||||
void test_border()
|
||||
void _test_border()
|
||||
{
|
||||
xlnt::border border;
|
||||
auto ws = wb.create_sheet();
|
||||
|
@ -399,7 +399,7 @@ public:
|
|||
TS_ASSERT(cell.get_border() == border);
|
||||
}
|
||||
|
||||
void test_number_format()
|
||||
void _test_number_format()
|
||||
{
|
||||
auto ws = wb.create_sheet();
|
||||
ws.get_parent().add_number_format("dd--hh--mm");
|
||||
|
@ -409,7 +409,7 @@ public:
|
|||
TS_ASSERT(cell.get_number_format() == "dd--hh--mm");
|
||||
}
|
||||
|
||||
void test_alignment()
|
||||
void _test_alignment()
|
||||
{
|
||||
xlnt::alignment align;
|
||||
align.set_wrap_text(true);
|
||||
|
@ -421,7 +421,7 @@ public:
|
|||
TS_ASSERT(cell.get_alignment() == align);
|
||||
}
|
||||
|
||||
void test_protection()
|
||||
void _test_protection()
|
||||
{
|
||||
xlnt::protection prot;
|
||||
prot.set_locked(false);
|
||||
|
@ -433,7 +433,7 @@ public:
|
|||
TS_ASSERT(cell.get_protection() == prot);
|
||||
}
|
||||
|
||||
void test_pivot_button()
|
||||
void _test_pivot_button()
|
||||
{
|
||||
auto ws = wb.create_sheet();
|
||||
|
||||
|
@ -442,7 +442,7 @@ public:
|
|||
TS_ASSERT(cell.pivot_button());
|
||||
}
|
||||
|
||||
void test_quote_prefix()
|
||||
void _test_quote_prefix()
|
||||
{
|
||||
auto ws = wb.create_sheet();
|
||||
|
||||
|
|
|
@ -26,11 +26,13 @@ public:
|
|||
{
|
||||
xlnt::zip_file archive(PathHelper::GetDataDirectory() + "/genuine/empty.xlsx");
|
||||
auto content = archive.read("docProps/core.xml");
|
||||
std::vector<std::string> expected_titles = {"Sheet1 - Text", "Sheet2 - Numbers", "Sheet3 - Formulas", "Sheet4 - Dates"};
|
||||
int i = 0;
|
||||
|
||||
const std::vector<std::string> expected_titles = {"Sheet1 - Text", "Sheet2 - Numbers", "Sheet3 - Formulas", "Sheet4 - Dates"};
|
||||
|
||||
std::size_t i = 0;
|
||||
for(auto sheet : xlnt::reader::read_sheets(archive))
|
||||
{
|
||||
TS_ASSERT_EQUALS(sheet.second, expected_titles[i++]);
|
||||
TS_ASSERT_EQUALS(sheet.second, expected_titles.at(i++));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,11 +48,13 @@ public:
|
|||
{
|
||||
xlnt::zip_file archive(PathHelper::GetDataDirectory() + "/genuine/empty_libre.xlsx");
|
||||
auto content = archive.read("docProps/core.xml");
|
||||
std::vector<std::string> expected_titles = {"Sheet1 - Text", "Sheet2 - Numbers", "Sheet3 - Formulas", "Sheet4 - Dates"};
|
||||
int i = 0;
|
||||
|
||||
const std::vector<std::string> expected_titles = {"Sheet1 - Text", "Sheet2 - Numbers", "Sheet3 - Formulas", "Sheet4 - Dates"};
|
||||
|
||||
std::size_t i = 0;
|
||||
for(auto sheet : xlnt::reader::read_sheets(archive))
|
||||
{
|
||||
TS_ASSERT_EQUALS(sheet.second, expected_titles[i++]);
|
||||
TS_ASSERT_EQUALS(sheet.second, expected_titles.at(i++));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,7 +65,7 @@ public:
|
|||
prop.last_modified_by = "SOMEBODY";
|
||||
prop.created = xlnt::datetime(2010, 4, 1, 20, 30, 00);
|
||||
prop.modified = xlnt::datetime(2010, 4, 5, 14, 5, 30);
|
||||
auto content = xlnt::writer::write_properties_core(prop);
|
||||
auto content = xlnt::write_properties_core(prop);
|
||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/core.xml", content));
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
#include <iostream>
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include <xlnt/xlnt.hpp>
|
||||
#include <xlnt/writer/workbook_writer.hpp>
|
||||
|
||||
#include "helpers/path_helper.hpp"
|
||||
#include "helpers/helper.hpp"
|
||||
|
||||
|
@ -12,7 +13,7 @@ class test_theme : public CxxTest::TestSuite
|
|||
public:
|
||||
void test_write_theme()
|
||||
{
|
||||
auto content = xlnt::writer::write_theme();
|
||||
auto content = xlnt::write_theme();
|
||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/theme1.xml", content));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -77,15 +77,19 @@ public:
|
|||
{
|
||||
xlnt::workbook wb;
|
||||
wb.clear();
|
||||
|
||||
std::vector<std::string> names = {"NewSheet", "NewSheet1", "NewSheet2", "NewSheet3", "NewSheet4", "NewSheet5"};
|
||||
for(int count = 0; count < names.size(); count++)
|
||||
|
||||
for(std::size_t count = 0; count < names.size(); count++)
|
||||
{
|
||||
wb.create_sheet(names[count]);
|
||||
}
|
||||
|
||||
auto actual_names = wb.get_sheet_names();
|
||||
std::sort(actual_names.begin(), actual_names.end());
|
||||
std::sort(names.begin(), names.end());
|
||||
for(int count = 0; count < names.size(); count++)
|
||||
|
||||
for(std::size_t count = 0; count < names.size(); count++)
|
||||
{
|
||||
TS_ASSERT_EQUALS(actual_names[count], names[count]);
|
||||
}
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
#include <iostream>
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "pugixml.hpp"
|
||||
#include <xlnt/xlnt.hpp>
|
||||
#include <xlnt/writer/worksheet_writer.hpp>
|
||||
|
||||
class test_worksheet : public CxxTest::TestSuite
|
||||
{
|
||||
|
@ -647,7 +646,7 @@ public:
|
|||
{
|
||||
xlnt::worksheet ws(wb_);
|
||||
|
||||
auto xml_string = xlnt::writer::write_worksheet(ws);
|
||||
auto xml_string = xlnt::write_worksheet(ws);
|
||||
|
||||
pugi::xml_document doc;
|
||||
doc.load(xml_string.c_str());
|
||||
|
@ -685,7 +684,7 @@ public:
|
|||
ws.get_page_margins().set_header(1.5);
|
||||
ws.get_page_margins().set_footer(1.5);
|
||||
|
||||
auto xml_string = xlnt::writer::write_worksheet(ws);
|
||||
auto xml_string = xlnt::write_worksheet(ws);
|
||||
|
||||
pugi::xml_document doc;
|
||||
doc.load(xml_string.c_str());
|
||||
|
@ -745,7 +744,7 @@ public:
|
|||
ws.get_cell("A1").set_value("Cell A1");
|
||||
ws.get_cell("B1").set_value("Cell B1");
|
||||
|
||||
auto xml_string = xlnt::writer::write_worksheet(ws, string_table);
|
||||
auto xml_string = xlnt::write_worksheet(ws, string_table);
|
||||
|
||||
pugi::xml_document doc;
|
||||
doc.load(xml_string.c_str());
|
||||
|
@ -756,7 +755,7 @@ public:
|
|||
TS_ASSERT(Helper::compare_xml(expected_doc, doc));
|
||||
|
||||
ws.merge_cells("A1:B1");
|
||||
xml_string = xlnt::writer::write_worksheet(ws, string_table);
|
||||
xml_string = xlnt::write_worksheet(ws, string_table);
|
||||
|
||||
auto expected_string2 =
|
||||
"<worksheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">"
|
||||
|
@ -790,7 +789,7 @@ public:
|
|||
TS_ASSERT(Helper::compare_xml(expected_doc, doc));
|
||||
|
||||
ws.unmerge_cells("A1:B1");
|
||||
xml_string = xlnt::writer::write_worksheet(ws, string_table);
|
||||
xml_string = xlnt::write_worksheet(ws, string_table);
|
||||
|
||||
auto expected_string3 =
|
||||
"<worksheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">"
|
||||
|
@ -833,7 +832,7 @@ public:
|
|||
ws.get_page_setup().set_horizontal_centered(true);
|
||||
ws.get_page_setup().set_vertical_centered(true);
|
||||
|
||||
auto xml_string = xlnt::writer::write_worksheet(ws);
|
||||
auto xml_string = xlnt::write_worksheet(ws);
|
||||
|
||||
pugi::xml_document doc;
|
||||
doc.load(xml_string.c_str());
|
||||
|
@ -913,7 +912,7 @@ public:
|
|||
pugi::xml_document observed_doc;
|
||||
|
||||
expected_doc.load(expected_xml_string.c_str());
|
||||
observed_doc.load(xlnt::writer::write_worksheet(ws, {}, {}).c_str());
|
||||
observed_doc.load(xlnt::write_worksheet(ws, {}, {}).c_str());
|
||||
|
||||
TS_ASSERT(Helper::compare_xml(expected_doc, observed_doc));
|
||||
|
||||
|
@ -936,7 +935,7 @@ public:
|
|||
"</worksheet>";
|
||||
|
||||
expected_doc.load(expected_xml_string.c_str());
|
||||
observed_doc.load(xlnt::writer::write_worksheet(ws, {}, {}).c_str());
|
||||
observed_doc.load(xlnt::write_worksheet(ws, {}, {}).c_str());
|
||||
|
||||
TS_ASSERT(Helper::compare_xml(expected_doc, observed_doc));
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ public:
|
|||
void test_write_string_table()
|
||||
{
|
||||
std::vector<std::string> table = {"hello", "world", "nice"};
|
||||
auto content = xlnt::writer::write_shared_strings(table);
|
||||
auto content = xlnt::write_shared_strings(table);
|
||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/sharedStrings.xml", content));
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ public:
|
|||
{
|
||||
auto ws = wb_.create_sheet();
|
||||
ws.get_cell("F42").set_value("hello");
|
||||
auto content = xlnt::writer::write_worksheet(ws, {"hello"}, {});
|
||||
auto content = xlnt::write_worksheet(ws, {"hello"}, {});
|
||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/sheet1.xml", content));
|
||||
}
|
||||
|
||||
|
@ -74,7 +74,7 @@ public:
|
|||
auto ws = wb_.create_sheet();
|
||||
ws.get_page_setup().set_sheet_state(xlnt::page_setup::sheet_state::hidden);
|
||||
ws.get_cell("F42").set_value("hello");
|
||||
auto content = xlnt::writer::write_worksheet(ws, {"hello"}, {});
|
||||
auto content = xlnt::write_worksheet(ws, {"hello"}, {});
|
||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/sheet1.xml", content));
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,7 @@ public:
|
|||
auto ws = wb_.create_sheet();
|
||||
ws.get_cell("F42").set_value(false);
|
||||
ws.get_cell("F43").set_value(true);
|
||||
auto content = xlnt::writer::write_worksheet(ws, {}, {});
|
||||
auto content = xlnt::write_worksheet(ws, {}, {});
|
||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_bool.xml", content));
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,7 @@ public:
|
|||
ws.get_cell("F1").set_value(10);
|
||||
ws.get_cell("F2").set_value(32);
|
||||
ws.get_cell("F3").set_formula("F1+F2");
|
||||
auto content = xlnt::writer::write_worksheet(ws, {}, {});
|
||||
auto content = xlnt::write_worksheet(ws, {}, {});
|
||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_formula.xml", content));
|
||||
}
|
||||
|
||||
|
@ -104,7 +104,7 @@ public:
|
|||
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::writer::write_worksheet(ws, {}, style_id_by_hash);
|
||||
auto content = xlnt::write_worksheet(ws, {}, style_id_by_hash);
|
||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_style.xml", content));
|
||||
}
|
||||
|
||||
|
@ -113,7 +113,7 @@ public:
|
|||
auto ws = wb_.create_sheet();
|
||||
ws.get_cell("F1").set_value(10);
|
||||
ws.get_row_properties(ws.get_cell("F1").get_row()).height = 30;
|
||||
auto content = xlnt::writer::write_worksheet(ws, {}, {});
|
||||
auto content = xlnt::write_worksheet(ws, {}, {});
|
||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_height.xml", content));
|
||||
}
|
||||
|
||||
|
@ -122,7 +122,7 @@ public:
|
|||
auto ws = wb_.create_sheet();
|
||||
ws.get_cell("A1").set_value("test");
|
||||
ws.get_cell("A1").set_hyperlink("http://test.com");
|
||||
auto content = xlnt::writer::write_worksheet(ws, {"test"}, {});
|
||||
auto content = xlnt::write_worksheet(ws, {"test"}, {});
|
||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_hyperlink.xml", content));
|
||||
}
|
||||
|
||||
|
@ -136,7 +136,7 @@ public:
|
|||
ws.get_cell("A2").set_value("test");
|
||||
ws.get_cell("A2").set_hyperlink("http://test2.com/");
|
||||
TS_ASSERT_EQUALS(2, ws.get_relationships().size());
|
||||
auto content = xlnt::writer::write_worksheet_rels(ws);
|
||||
auto content = xlnt::write_worksheet_rels(ws);
|
||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_hyperlink.xml.rels", content));
|
||||
}
|
||||
|
||||
|
@ -160,7 +160,7 @@ public:
|
|||
auto ws = wb.get_sheet_by_index(0);
|
||||
ws.get_cell("F42").set_value("hello");
|
||||
ws.auto_filter("A1:F1");
|
||||
auto content = xlnt::writer::write_worksheet(ws, {"hello"}, {});
|
||||
auto content = xlnt::write_worksheet(ws, {"hello"}, {});
|
||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_auto_filter.xml", content));
|
||||
|
||||
content = xlnt::write_workbook(wb);
|
||||
|
@ -182,7 +182,7 @@ public:
|
|||
auto ws = wb_.create_sheet();
|
||||
ws.get_cell("F42").set_value("hello");
|
||||
ws.freeze_panes("A4");
|
||||
auto content = xlnt::writer::write_worksheet(ws, {"hello"}, {});
|
||||
auto content = xlnt::write_worksheet(ws, {"hello"}, {});
|
||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_freeze_panes_horiz.xml", content));
|
||||
}
|
||||
|
||||
|
@ -191,7 +191,7 @@ public:
|
|||
auto ws = wb_.create_sheet();
|
||||
ws.get_cell("F42").set_value("hello");
|
||||
ws.freeze_panes("D1");
|
||||
auto content = xlnt::writer::write_worksheet(ws, {"hello"}, {});
|
||||
auto content = xlnt::write_worksheet(ws, {"hello"}, {});
|
||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_freeze_panes_vert.xml", content));
|
||||
}
|
||||
|
||||
|
@ -200,7 +200,7 @@ public:
|
|||
auto ws = wb_.create_sheet();
|
||||
ws.get_cell("F42").set_value("hello");
|
||||
ws.freeze_panes("D4");
|
||||
auto content = xlnt::writer::write_worksheet(ws, {"hello"}, {});
|
||||
auto content = xlnt::write_worksheet(ws, {"hello"}, {});
|
||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_freeze_panes_both.xml", content));
|
||||
}
|
||||
|
||||
|
@ -208,7 +208,7 @@ public:
|
|||
{
|
||||
auto ws = wb_.create_sheet();
|
||||
ws.get_cell("A1").set_value(9781231231230LL);
|
||||
auto content = xlnt::writer::write_worksheet(ws, {}, {});
|
||||
auto content = xlnt::write_worksheet(ws, {}, {});
|
||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/long_number.xml", content));
|
||||
}
|
||||
|
||||
|
@ -216,7 +216,7 @@ public:
|
|||
{
|
||||
auto ws = wb_.create_sheet();
|
||||
ws.get_cell("A1").set_value(1234567890);
|
||||
auto content = xlnt::writer::write_worksheet(ws, {}, {});
|
||||
auto content = xlnt::write_worksheet(ws, {}, {});
|
||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/short_number.xml", content));
|
||||
}
|
||||
|
||||
|
|
|
@ -4,34 +4,11 @@
|
|||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include <xlnt/common/exceptions.hpp>
|
||||
#include <xlnt/reader/workbook_reader.hpp>
|
||||
#include <xlnt/writer/workbook_writer.hpp>
|
||||
|
||||
#include "helpers/path_helper.hpp"
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
xlnt::workbook load_workbook(const std::vector<std::uint8_t> &bytes)
|
||||
{
|
||||
return xlnt::workbook();
|
||||
}
|
||||
|
||||
std::string write_workbook_rels(xlnt::workbook &wb)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string write_root_rels(xlnt::workbook &wb)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string write_defined_names(xlnt::workbook &wb)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class test_write_workbook : public CxxTest::TestSuite
|
||||
{
|
||||
public:
|
||||
|
@ -108,7 +85,7 @@ public:
|
|||
{
|
||||
xlnt::workbook wb;
|
||||
auto content = xlnt::write_workbook(wb);
|
||||
auto filename = "workbook.xml";
|
||||
auto filename = PathHelper::GetDataDirectory("/workbook.xml");
|
||||
auto diff = Helper::compare_xml(PathHelper::read_file(filename), content);
|
||||
TS_ASSERT(!diff);
|
||||
}
|
||||
|
@ -117,8 +94,7 @@ public:
|
|||
{
|
||||
xlnt::workbook wb;
|
||||
auto ws = wb.create_sheet();
|
||||
xlnt::named_range xlrange("test_range", {{ws, "A1:B5"}});
|
||||
wb.add_named_range(xlrange);
|
||||
wb.create_named_range("test_range", ws, "A1:B5");
|
||||
auto xml = xlnt::write_defined_names(wb);
|
||||
std::string expected =
|
||||
"<root>"
|
||||
|
|
Loading…
Reference in New Issue
Block a user