mirror of
https://github.com/tfussell/xlnt.git
synced 2024-03-22 13:11:17 +08:00
begin refactoring writing code
This commit is contained in:
parent
7316e2184c
commit
6b3781d03b
|
@ -118,5 +118,13 @@ class attribute_error : public std::runtime_error
|
||||||
public:
|
public:
|
||||||
attribute_error();
|
attribute_error();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class value_error : public std::runtime_error
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
value_error() : std::runtime_error("")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace xlnt
|
} // namespace xlnt
|
||||||
|
|
18
include/xlnt/workbook/named_range.hpp
Normal file
18
include/xlnt/workbook/named_range.hpp
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace xlnt {
|
||||||
|
|
||||||
|
class worksheet;
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string, std::string>> split_named_range(const std::string &named_range_string);
|
||||||
|
|
||||||
|
class named_range
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
named_range(const std::string &name, const std::vector<std::pair<worksheet, std::string>> &targets);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -46,6 +46,7 @@ class pattern_fill;
|
||||||
class font;
|
class font;
|
||||||
class protection;
|
class protection;
|
||||||
class color;
|
class color;
|
||||||
|
class named_range;
|
||||||
|
|
||||||
enum class encoding;
|
enum class encoding;
|
||||||
|
|
||||||
|
@ -174,7 +175,18 @@ public:
|
||||||
bool load(const std::istream &stream);
|
bool load(const std::istream &stream);
|
||||||
|
|
||||||
bool operator==(const workbook &rhs) const;
|
bool operator==(const workbook &rhs) const;
|
||||||
|
|
||||||
|
bool operator!=(const workbook &rhs) const
|
||||||
|
{
|
||||||
|
return !(*this == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
bool operator==(std::nullptr_t) const;
|
bool operator==(std::nullptr_t) const;
|
||||||
|
|
||||||
|
bool operator!=(std::nullptr_t) const
|
||||||
|
{
|
||||||
|
return !(*this == std::nullptr_t{});
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<content_type> get_content_types() const;
|
std::vector<content_type> get_content_types() const;
|
||||||
|
|
||||||
|
@ -190,6 +202,13 @@ public:
|
||||||
void add_color(color c);
|
void add_color(color c);
|
||||||
void add_number_format(const std::string &format);
|
void add_number_format(const std::string &format);
|
||||||
|
|
||||||
|
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:
|
private:
|
||||||
static std::size_t index_from_ws_filename(const std::string &ws_filename);
|
static std::size_t index_from_ws_filename(const std::string &ws_filename);
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
struct page_setup
|
struct page_setup
|
||||||
{
|
{
|
||||||
enum class page_break
|
enum class page_break
|
||||||
|
@ -64,12 +64,12 @@ struct page_setup
|
||||||
|
|
||||||
public:
|
public:
|
||||||
page_setup() : default_(true), break_(page_break::none), sheet_state_(sheet_state::visible), paper_size_(paper_size::letter),
|
page_setup() : default_(true), break_(page_break::none), sheet_state_(sheet_state::visible), paper_size_(paper_size::letter),
|
||||||
orientation_(orientation::portrait), fit_to_page_(false), fit_to_height_(false), fit_to_width_(false) {}
|
orientation_(orientation::portrait), fit_to_page_(false), fit_to_height_(false), fit_to_width_(false), horizontal_centered_(false), vertical_centered_(false), scale_(1) {}
|
||||||
bool is_default() const { return default_; }
|
bool is_default() const { return default_; }
|
||||||
page_break get_break() const { return break_; }
|
page_break get_break() const { return break_; }
|
||||||
void set_break(page_break b) { default_ = false; break_ = b; }
|
void set_break(page_break b) { default_ = false; break_ = b; }
|
||||||
sheet_state get_sheet_state() const { return sheet_state_; }
|
sheet_state get_sheet_state() const { return sheet_state_; }
|
||||||
void set_sheet_state(sheet_state sheet_state) { default_ = false; sheet_state_ = sheet_state; }
|
void set_sheet_state(sheet_state sheet_state) { sheet_state_ = sheet_state; }
|
||||||
paper_size get_paper_size() const { return paper_size_; }
|
paper_size get_paper_size() const { return paper_size_; }
|
||||||
void set_paper_size(paper_size paper_size) { default_ = false; paper_size_ = paper_size; }
|
void set_paper_size(paper_size paper_size) { default_ = false; paper_size_ = paper_size; }
|
||||||
orientation get_orientation() const { return orientation_; }
|
orientation get_orientation() const { return orientation_; }
|
||||||
|
@ -80,6 +80,12 @@ public:
|
||||||
void set_fit_to_height(bool fit_to_height) { default_ = false; fit_to_height_ = fit_to_height; }
|
void set_fit_to_height(bool fit_to_height) { default_ = false; fit_to_height_ = fit_to_height; }
|
||||||
bool fit_to_width() const { return fit_to_width_; }
|
bool fit_to_width() const { return fit_to_width_; }
|
||||||
void set_fit_to_width(bool fit_to_width) { default_ = false; fit_to_width_ = fit_to_width; }
|
void set_fit_to_width(bool fit_to_width) { default_ = false; fit_to_width_ = fit_to_width; }
|
||||||
|
void set_horizontal_centered(bool horizontal_centered) { default_ = false; horizontal_centered_ = horizontal_centered; }
|
||||||
|
bool get_horizontal_centered() const { return horizontal_centered_; }
|
||||||
|
void set_vertical_centered(bool vertical_centered) { default_ = false; vertical_centered_ = vertical_centered; }
|
||||||
|
bool get_vertical_centered() const { return vertical_centered_; }
|
||||||
|
void set_scale(double scale) { default_ = false; scale_ = scale; }
|
||||||
|
double get_scale() const { return scale_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool default_;
|
bool default_;
|
||||||
|
@ -90,6 +96,9 @@ private:
|
||||||
bool fit_to_page_;
|
bool fit_to_page_;
|
||||||
bool fit_to_height_;
|
bool fit_to_height_;
|
||||||
bool fit_to_width_;
|
bool fit_to_width_;
|
||||||
|
bool horizontal_centered_;
|
||||||
|
bool vertical_centered_;
|
||||||
|
double scale_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace xlnt
|
} // namespace xlnt
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "page_setup.hpp"
|
||||||
#include "../common/types.hpp"
|
#include "../common/types.hpp"
|
||||||
#include "../common/relationship.hpp"
|
#include "../common/relationship.hpp"
|
||||||
|
|
||||||
|
@ -116,82 +117,6 @@ private:
|
||||||
footer left_footer_, right_footer_, center_footer_;
|
footer left_footer_, right_footer_, center_footer_;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct page_setup
|
|
||||||
{
|
|
||||||
enum class page_break
|
|
||||||
{
|
|
||||||
none = 0,
|
|
||||||
row = 1,
|
|
||||||
column = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class sheet_state
|
|
||||||
{
|
|
||||||
visible,
|
|
||||||
hidden,
|
|
||||||
very_hidden
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class paper_size
|
|
||||||
{
|
|
||||||
letter = 1,
|
|
||||||
letter_small = 2,
|
|
||||||
tabloid = 3,
|
|
||||||
ledger = 4,
|
|
||||||
legal = 5,
|
|
||||||
statement = 6,
|
|
||||||
executive = 7,
|
|
||||||
a3 = 8,
|
|
||||||
a4 = 9,
|
|
||||||
a4_small = 10,
|
|
||||||
a5 = 11
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class orientation
|
|
||||||
{
|
|
||||||
portrait,
|
|
||||||
landscape
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
page_setup() : default_(true), break_(page_break::none), sheet_state_(sheet_state::visible), paper_size_(paper_size::letter),
|
|
||||||
orientation_(orientation::portrait), fit_to_page_(false), fit_to_height_(false), fit_to_width_(false), horizontal_centered_(false), vertical_centered_(false), scale_(1) {}
|
|
||||||
bool is_default() const { return default_; }
|
|
||||||
page_break get_break() const { return break_; }
|
|
||||||
void set_break(page_break b) { default_ = false; break_ = b; }
|
|
||||||
sheet_state get_sheet_state() const { return sheet_state_; }
|
|
||||||
void set_sheet_state(sheet_state sheet_state) { sheet_state_ = sheet_state; }
|
|
||||||
paper_size get_paper_size() const { return paper_size_; }
|
|
||||||
void set_paper_size(paper_size paper_size) { default_ = false; paper_size_ = paper_size; }
|
|
||||||
orientation get_orientation() const { return orientation_; }
|
|
||||||
void set_orientation(orientation orientation) { default_ = false; orientation_ = orientation; }
|
|
||||||
bool fit_to_page() const { return fit_to_page_; }
|
|
||||||
void set_fit_to_page(bool fit_to_page) { default_ = false; fit_to_page_ = fit_to_page; }
|
|
||||||
bool fit_to_height() const { return fit_to_height_; }
|
|
||||||
void set_fit_to_height(bool fit_to_height) { default_ = false; fit_to_height_ = fit_to_height; }
|
|
||||||
bool fit_to_width() const { return fit_to_width_; }
|
|
||||||
void set_fit_to_width(bool fit_to_width) { default_ = false; fit_to_width_ = fit_to_width; }
|
|
||||||
void set_horizontal_centered(bool horizontal_centered) { default_ = false; horizontal_centered_ = horizontal_centered; }
|
|
||||||
bool get_horizontal_centered() const { return horizontal_centered_; }
|
|
||||||
void set_vertical_centered(bool vertical_centered) { default_ = false; vertical_centered_ = vertical_centered; }
|
|
||||||
bool get_vertical_centered() const { return vertical_centered_; }
|
|
||||||
void set_scale(double scale) { default_ = false; scale_ = scale; }
|
|
||||||
double get_scale() const { return scale_; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool default_;
|
|
||||||
page_break break_;
|
|
||||||
sheet_state sheet_state_;
|
|
||||||
paper_size paper_size_;
|
|
||||||
orientation orientation_;
|
|
||||||
bool fit_to_page_;
|
|
||||||
bool fit_to_height_;
|
|
||||||
bool fit_to_width_;
|
|
||||||
bool horizontal_centered_;
|
|
||||||
bool vertical_centered_;
|
|
||||||
double scale_;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct margins
|
struct margins
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -348,6 +273,8 @@ public:
|
||||||
|
|
||||||
std::vector<std::string> get_formula_attributes() const;
|
std::vector<std::string> get_formula_attributes() const;
|
||||||
|
|
||||||
|
void set_sheet_state(page_setup::sheet_state state);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class workbook;
|
friend class workbook;
|
||||||
friend class cell;
|
friend class cell;
|
||||||
|
|
11
include/xlnt/writer/manifest_writer.hpp
Normal file
11
include/xlnt/writer/manifest_writer.hpp
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace xlnt {
|
||||||
|
|
||||||
|
class workbook;
|
||||||
|
|
||||||
|
std::string write_content_types(const workbook &wb, bool as_template);
|
||||||
|
|
||||||
|
};
|
12
include/xlnt/writer/relationship_writer.hpp
Normal file
12
include/xlnt/writer/relationship_writer.hpp
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace xlnt {
|
||||||
|
|
||||||
|
class relationship;
|
||||||
|
|
||||||
|
std::string write_relationships(const std::vector<relationship> &relationships, const std::string &dir);
|
||||||
|
|
||||||
|
} // namespace xlnt
|
|
@ -23,11 +23,11 @@
|
||||||
// @author: see AUTHORS file
|
// @author: see AUTHORS file
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
class theme_writer
|
std::string write_theme();
|
||||||
{
|
//void write_theme(const theme &t);
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace xlnt
|
} // namespace xlnt
|
||||||
|
|
|
@ -23,11 +23,40 @@
|
||||||
// @author: see AUTHORS file
|
// @author: see AUTHORS file
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <xlnt/writer/style_writer.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
class workbook_writer
|
class workbook;
|
||||||
{
|
class zip_file;
|
||||||
|
|
||||||
|
class excel_writer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
excel_writer(workbook &wb);
|
||||||
|
|
||||||
|
void save(const std::string &filename, bool as_template);
|
||||||
|
void write_data(zip_file &archive, bool as_template);
|
||||||
|
void write_string_table(zip_file &archive);
|
||||||
|
void write_images(zip_file &archive);
|
||||||
|
void write_charts(zip_file &archive);
|
||||||
|
void write_chartsheets(zip_file &archive);
|
||||||
|
void write_worksheets(zip_file &archive);
|
||||||
|
void write_external_links(zip_file &archive);
|
||||||
|
|
||||||
|
private:
|
||||||
|
workbook wb_;
|
||||||
|
style_writer style_writer_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
|
||||||
} // namespace xlnt
|
} // namespace xlnt
|
||||||
|
|
|
@ -1,33 +1,2 @@
|
||||||
// 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
|
#pragma once
|
||||||
|
|
||||||
namespace xlnt {
|
|
||||||
|
|
||||||
class worksheet_writer
|
|
||||||
{
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace xlnt
|
|
||||||
|
|
|
@ -38,13 +38,9 @@ class document_properties;
|
||||||
class writer
|
class writer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static std::string write_content_types(const workbook &wb);
|
static std::string write_content_types(const workbook &wb);
|
||||||
|
|
||||||
static std::string write_properties_core(const document_properties &prop);
|
static std::string write_properties_core(const document_properties &prop);
|
||||||
|
|
||||||
static std::string write_properties_app(const workbook &wb);
|
|
||||||
|
|
||||||
static std::string write_workbook(const workbook &wb);
|
|
||||||
|
|
||||||
static std::string write_theme();
|
static std::string write_theme();
|
||||||
|
|
||||||
|
@ -54,14 +50,7 @@ public:
|
||||||
const std::vector<std::string> &string_table = {},
|
const std::vector<std::string> &string_table = {},
|
||||||
const std::unordered_map<std::size_t, std::string> &style_table = {});
|
const std::unordered_map<std::size_t, std::string> &style_table = {});
|
||||||
|
|
||||||
static std::string write_root_rels();
|
|
||||||
|
|
||||||
static std::string write_workbook_rels(const workbook &wb);
|
|
||||||
|
|
||||||
static std::string write_worksheet_rels(worksheet ws);
|
static std::string write_worksheet_rels(worksheet ws);
|
||||||
|
|
||||||
private:
|
|
||||||
static std::string write_relationships(const std::vector<relationship> &relationships, const std::string &dir = "");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace xlnt
|
} // namespace xlnt
|
||||||
|
|
|
@ -50,3 +50,4 @@ const std::string download_url = "https://github.com/tfussell/xlnt/archive/maste
|
||||||
#include "workbook/document_properties.hpp"
|
#include "workbook/document_properties.hpp"
|
||||||
#include "cell/comment.hpp"
|
#include "cell/comment.hpp"
|
||||||
#include "common/encoding.hpp"
|
#include "common/encoding.hpp"
|
||||||
|
#include "workbook/named_range.hpp"
|
||||||
|
|
|
@ -102,13 +102,27 @@ std::pair<std::string, row_t> cell_reference::split_reference(const std::string
|
||||||
throw cell_coordinates_exception(reference_string);
|
throw cell_coordinates_exception(reference_string);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(character == '$')
|
||||||
|
{
|
||||||
|
if(column_part)
|
||||||
|
{
|
||||||
|
if(column_string.empty())
|
||||||
|
{
|
||||||
|
column_string.append(1, upper);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
column_part = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(column_part)
|
if(column_part)
|
||||||
{
|
{
|
||||||
column_part = false;
|
column_part = false;
|
||||||
}
|
}
|
||||||
else if(!(std::isdigit(character, std::locale::classic()) || character == '$'))
|
else if(!std::isdigit(character, std::locale::classic()))
|
||||||
{
|
{
|
||||||
throw cell_coordinates_exception(reference_string);
|
throw cell_coordinates_exception(reference_string);
|
||||||
}
|
}
|
||||||
|
|
10
source/manifest_writer.cpp
Normal file
10
source/manifest_writer.cpp
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#include <xlnt/writer/manifest_writer.hpp>
|
||||||
|
|
||||||
|
namespace xlnt {
|
||||||
|
|
||||||
|
std::string write_content_types(const workbook &wb, bool as_template)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace xlnt
|
73
source/named_range.cpp
Normal file
73
source/named_range.cpp
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
|
||||||
|
#include <xlnt/workbook/named_range.hpp>
|
||||||
|
#include <xlnt/common/exceptions.hpp>
|
||||||
|
#include <xlnt/worksheet/range_reference.hpp>
|
||||||
|
#include <xlnt/worksheet/worksheet.hpp>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return a vector containing string split at each delim.
|
||||||
|
/// </summary>
|
||||||
|
/// <remark>
|
||||||
|
/// This should maybe be in a utility header so it can be used elsewhere.
|
||||||
|
/// </remarks>
|
||||||
|
std::vector<std::string> split_string(const std::string &string, char delim)
|
||||||
|
{
|
||||||
|
std::vector<std::string> split;
|
||||||
|
std::string::size_type previous_index = 0;
|
||||||
|
auto separator_index = string.find(delim);
|
||||||
|
|
||||||
|
while(separator_index != std::string::npos)
|
||||||
|
{
|
||||||
|
auto part = string.substr(previous_index, separator_index - previous_index);
|
||||||
|
split.push_back(part);
|
||||||
|
|
||||||
|
previous_index = separator_index + 1;
|
||||||
|
separator_index = string.find(delim, previous_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
split.push_back(string.substr(previous_index));
|
||||||
|
|
||||||
|
return split;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace xlnt {
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string, std::string>> split_named_range(const std::string &named_range_string)
|
||||||
|
{
|
||||||
|
std::vector<std::pair<std::string, std::string>> final;
|
||||||
|
|
||||||
|
for(auto part : split_string(named_range_string, ','))
|
||||||
|
{
|
||||||
|
auto split = split_string(part, '!');
|
||||||
|
|
||||||
|
if(split[0].front() == '\'' && split[0].back() == '\'')
|
||||||
|
{
|
||||||
|
split[0] = split[0].substr(1, split[0].length() - 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to parse it. Use empty string if it's not a valid range.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
xlnt::range_reference ref(split[1]);
|
||||||
|
}
|
||||||
|
catch(xlnt::cell_coordinates_exception)
|
||||||
|
{
|
||||||
|
split[1] = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
final.push_back({split[0], split[1]});
|
||||||
|
}
|
||||||
|
|
||||||
|
return final;
|
||||||
|
}
|
||||||
|
|
||||||
|
named_range::named_range(const std::string &name, const std::vector<std::pair<worksheet, std::string>> &targets)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace xlnt
|
45
source/relationship_writer.cpp
Normal file
45
source/relationship_writer.cpp
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include <xlnt/common/relationship.hpp>
|
||||||
|
#include <xlnt/writer/relationship_writer.hpp>
|
||||||
|
|
||||||
|
#include "constants.hpp"
|
||||||
|
#include "detail/include_pugixml.hpp"
|
||||||
|
|
||||||
|
namespace xlnt {
|
||||||
|
|
||||||
|
std::string write_relationships(const std::vector<relationship> &relationships, const std::string &dir)
|
||||||
|
{
|
||||||
|
pugi::xml_document doc;
|
||||||
|
|
||||||
|
auto root_node = doc.append_child("Relationships");
|
||||||
|
root_node.append_attribute("xmlns").set_value(constants::Namespaces.at("relationships").c_str());
|
||||||
|
|
||||||
|
for(auto relationship : relationships)
|
||||||
|
{
|
||||||
|
auto target = relationship.get_target_uri();
|
||||||
|
|
||||||
|
if (dir != "" && target.substr(0, dir.size()) == dir)
|
||||||
|
{
|
||||||
|
target = target.substr(dir.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto app_props_node = root_node.append_child("Relationship");
|
||||||
|
|
||||||
|
app_props_node.append_attribute("Id").set_value(relationship.get_id().c_str());
|
||||||
|
app_props_node.append_attribute("Target").set_value(target.c_str());
|
||||||
|
app_props_node.append_attribute("Type").set_value(relationship.get_type_string().c_str());
|
||||||
|
|
||||||
|
if(relationship.get_target_mode() == target_mode::external)
|
||||||
|
{
|
||||||
|
app_props_node.append_attribute("TargetMode").set_value("External");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
|
doc.save(ss);
|
||||||
|
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -8,17 +8,18 @@
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <xlnt/workbook/workbook.hpp>
|
|
||||||
#include <xlnt/common/exceptions.hpp>
|
#include <xlnt/common/exceptions.hpp>
|
||||||
#include <xlnt/drawing/drawing.hpp>
|
|
||||||
#include <xlnt/worksheet/range.hpp>
|
|
||||||
#include <xlnt/reader/reader.hpp>
|
|
||||||
#include <xlnt/common/relationship.hpp>
|
#include <xlnt/common/relationship.hpp>
|
||||||
#include <xlnt/worksheet/worksheet.hpp>
|
|
||||||
#include <xlnt/writer/writer.hpp>
|
|
||||||
#include <xlnt/common/zip_file.hpp>
|
#include <xlnt/common/zip_file.hpp>
|
||||||
|
#include <xlnt/drawing/drawing.hpp>
|
||||||
|
#include <xlnt/reader/reader.hpp>
|
||||||
#include <xlnt/workbook/document_properties.hpp>
|
#include <xlnt/workbook/document_properties.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/style_writer.hpp>
|
||||||
|
#include <xlnt/writer/workbook_writer.hpp>
|
||||||
|
#include <xlnt/writer/writer.hpp>
|
||||||
|
|
||||||
#include "detail/cell_impl.hpp"
|
#include "detail/cell_impl.hpp"
|
||||||
#include "detail/include_pugixml.hpp"
|
#include "detail/include_pugixml.hpp"
|
||||||
|
@ -564,7 +565,7 @@ bool workbook::save(const std::string &filename)
|
||||||
|
|
||||||
f.writestr("[Content_Types].xml", writer::write_content_types(*this));
|
f.writestr("[Content_Types].xml", writer::write_content_types(*this));
|
||||||
|
|
||||||
f.writestr("docProps/app.xml", writer::write_properties_app(*this));
|
f.writestr("docProps/app.xml", write_properties_app(*this));
|
||||||
f.writestr("docProps/core.xml", writer::write_properties_core(get_properties()));
|
f.writestr("docProps/core.xml", writer::write_properties_core(get_properties()));
|
||||||
|
|
||||||
std::set<std::string> shared_strings_set;
|
std::set<std::string> shared_strings_set;
|
||||||
|
@ -589,10 +590,10 @@ bool workbook::save(const std::string &filename)
|
||||||
f.writestr("xl/theme/theme1.xml", writer::write_theme());
|
f.writestr("xl/theme/theme1.xml", writer::write_theme());
|
||||||
f.writestr("xl/styles.xml", style_writer(*this).write_table());
|
f.writestr("xl/styles.xml", style_writer(*this).write_table());
|
||||||
|
|
||||||
f.writestr("_rels/.rels", writer::write_root_rels());
|
f.writestr("_rels/.rels", write_root_rels(*this));
|
||||||
f.writestr("xl/_rels/workbook.xml.rels", writer::write_workbook_rels(*this));
|
f.writestr("xl/_rels/workbook.xml.rels", write_workbook_rels(*this));
|
||||||
|
|
||||||
f.writestr("xl/workbook.xml", writer::write_workbook(*this));
|
f.writestr("xl/workbook.xml", write_workbook(*this));
|
||||||
|
|
||||||
for(auto relationship : d_->relationships_)
|
for(auto relationship : d_->relationships_)
|
||||||
{
|
{
|
||||||
|
@ -741,6 +742,25 @@ std::size_t workbook::index_from_ws_filename(const std::string &ws_filename)
|
||||||
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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool workbook::has_loaded_theme()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string workbook::get_loaded_theme()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
285
source/workbook_writer.cpp
Normal file
285
source/workbook_writer.cpp
Normal file
|
@ -0,0 +1,285 @@
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#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/workbook.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/workbook_writer.hpp>
|
||||||
|
|
||||||
|
#include "constants.hpp"
|
||||||
|
#include "detail/include_pugixml.hpp"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
std::string to_xml(xlnt::document_properties &props)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace xlnt {
|
||||||
|
|
||||||
|
excel_writer::excel_writer(workbook &wb) : wb_(wb), style_writer_(wb_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void excel_writer::save(const std::string &filename, bool as_template)
|
||||||
|
{
|
||||||
|
zip_file archive;
|
||||||
|
write_data(archive, as_template);
|
||||||
|
archive.save(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
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()));
|
||||||
|
|
||||||
|
if(wb_.has_loaded_theme())
|
||||||
|
{
|
||||||
|
archive.writestr(constants::ArcTheme, wb_.get_loaded_theme());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
archive.writestr(constants::ArcTheme, write_theme());
|
||||||
|
}
|
||||||
|
|
||||||
|
archive.writestr(constants::ArcWorkbook, write_workbook(wb_));
|
||||||
|
|
||||||
|
/*
|
||||||
|
if(wb_.has_vba_archive())
|
||||||
|
{
|
||||||
|
auto &vba_archive = wb_.get_vba_archive();
|
||||||
|
|
||||||
|
for(auto name : vba_archive.namelist())
|
||||||
|
{
|
||||||
|
for(auto s : constants::ArcVba)
|
||||||
|
{
|
||||||
|
if(match(s, name))
|
||||||
|
{
|
||||||
|
archive.writestr(name, vba_archive.read(name));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
write_charts(archive);
|
||||||
|
write_images(archive);
|
||||||
|
write_worksheets(archive);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void excel_writer::write_string_table(zip_file &archive)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void excel_writer::write_images(zip_file &archive)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void excel_writer::write_charts(zip_file &archive)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void excel_writer::write_chartsheets(zip_file &archive)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void excel_writer::write_worksheets(zip_file &archive)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void excel_writer::write_external_links(zip_file &archive)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string write_properties_app(const workbook &wb)
|
||||||
|
{
|
||||||
|
pugi::xml_document doc;
|
||||||
|
auto root_node = doc.append_child("Properties");
|
||||||
|
root_node.append_attribute("xmlns").set_value("http://schemas.openxmlformats.org/officeDocument/2006/extended-properties");
|
||||||
|
root_node.append_attribute("xmlns:vt").set_value("http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes");
|
||||||
|
|
||||||
|
root_node.append_child("Application").text().set("Microsoft Excel");
|
||||||
|
root_node.append_child("DocSecurity").text().set("0");
|
||||||
|
root_node.append_child("ScaleCrop").text().set("false");
|
||||||
|
root_node.append_child("Company");
|
||||||
|
root_node.append_child("LinksUpToDate").text().set("false");
|
||||||
|
root_node.append_child("SharedDoc").text().set("false");
|
||||||
|
root_node.append_child("HyperlinksChanged").text().set("false");
|
||||||
|
root_node.append_child("AppVersion").text().set("12.0000");
|
||||||
|
|
||||||
|
auto heading_pairs_node = root_node.append_child("HeadingPairs");
|
||||||
|
auto heading_pairs_vector_node = heading_pairs_node.append_child("vt:vector");
|
||||||
|
heading_pairs_vector_node.append_attribute("baseType").set_value("variant");
|
||||||
|
heading_pairs_vector_node.append_attribute("size").set_value("2");
|
||||||
|
heading_pairs_vector_node.append_child("vt:variant").append_child("vt:lpstr").text().set("Worksheets");
|
||||||
|
heading_pairs_vector_node.append_child("vt:variant").append_child("vt:i4").text().set(std::to_string(wb.get_sheet_names().size()).c_str());
|
||||||
|
|
||||||
|
auto titles_of_parts_node = root_node.append_child("TitlesOfParts");
|
||||||
|
auto titles_of_parts_vector_node = titles_of_parts_node.append_child("vt:vector");
|
||||||
|
titles_of_parts_vector_node.append_attribute("baseType").set_value("lpstr");
|
||||||
|
titles_of_parts_vector_node.append_attribute("size").set_value(std::to_string(wb.get_sheet_names().size()).c_str());
|
||||||
|
|
||||||
|
for(auto ws : wb)
|
||||||
|
{
|
||||||
|
titles_of_parts_vector_node.append_child("vt:lpstr").text().set(ws.get_title().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
|
doc.save(ss);
|
||||||
|
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string write_root_rels(const workbook &)
|
||||||
|
{
|
||||||
|
std::vector<relationship> relationships;
|
||||||
|
|
||||||
|
relationships.push_back(relationship(relationship::type::extended_properties, "rId3", "docProps/app.xml"));
|
||||||
|
relationships.push_back(relationship(relationship::type::core_properties, "rId2", "docProps/core.xml"));
|
||||||
|
relationships.push_back(relationship(relationship::type::office_document, "rId1", "xl/workbook.xml"));
|
||||||
|
|
||||||
|
return write_relationships(relationships, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string write_workbook(const workbook &wb)
|
||||||
|
{
|
||||||
|
std::size_t num_visible = 0;
|
||||||
|
|
||||||
|
for(auto ws : wb)
|
||||||
|
{
|
||||||
|
if(ws.get_page_setup().get_sheet_state() == xlnt::page_setup::sheet_state::visible)
|
||||||
|
{
|
||||||
|
num_visible++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(num_visible == 0)
|
||||||
|
{
|
||||||
|
throw value_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
pugi::xml_document doc;
|
||||||
|
auto root_node = doc.append_child("workbook");
|
||||||
|
root_node.append_attribute("xmlns").set_value("http://schemas.openxmlformats.org/spreadsheetml/2006/main");
|
||||||
|
root_node.append_attribute("xmlns:r").set_value("http://schemas.openxmlformats.org/officeDocument/2006/relationships");
|
||||||
|
|
||||||
|
auto file_version_node = root_node.append_child("fileVersion");
|
||||||
|
file_version_node.append_attribute("appName").set_value("xl");
|
||||||
|
file_version_node.append_attribute("lastEdited").set_value("4");
|
||||||
|
file_version_node.append_attribute("lowestEdited").set_value("4");
|
||||||
|
file_version_node.append_attribute("rupBuild").set_value("4505");
|
||||||
|
|
||||||
|
auto workbook_pr_node = root_node.append_child("workbookPr");
|
||||||
|
workbook_pr_node.append_attribute("codeName").set_value("ThisWorkbook");
|
||||||
|
workbook_pr_node.append_attribute("defaultThemeVersion").set_value("124226");
|
||||||
|
|
||||||
|
auto book_views_node = root_node.append_child("bookViews");
|
||||||
|
auto workbook_view_node = book_views_node.append_child("workbookView");
|
||||||
|
workbook_view_node.append_attribute("activeTab").set_value("0");
|
||||||
|
workbook_view_node.append_attribute("autoFilterDateGrouping").set_value("1");
|
||||||
|
workbook_view_node.append_attribute("firstSheet").set_value("0");
|
||||||
|
workbook_view_node.append_attribute("minimized").set_value("0");
|
||||||
|
workbook_view_node.append_attribute("showHorizontalScroll").set_value("1");
|
||||||
|
workbook_view_node.append_attribute("showSheetTabs").set_value("1");
|
||||||
|
workbook_view_node.append_attribute("showVerticalScroll").set_value("1");
|
||||||
|
workbook_view_node.append_attribute("tabRatio").set_value("600");
|
||||||
|
workbook_view_node.append_attribute("visibility").set_value("visible");
|
||||||
|
|
||||||
|
auto sheets_node = root_node.append_child("sheets");
|
||||||
|
auto defined_names_node = root_node.append_child("definedNames");
|
||||||
|
|
||||||
|
for(auto relationship : wb.get_relationships())
|
||||||
|
{
|
||||||
|
if(relationship.get_type() == relationship::type::worksheet)
|
||||||
|
{
|
||||||
|
std::string sheet_index_string = relationship.get_target_uri();
|
||||||
|
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);
|
||||||
|
std::size_t sheet_index = std::stoi(sheet_index_string) - 1;
|
||||||
|
|
||||||
|
auto ws = wb.get_sheet_by_index(sheet_index);
|
||||||
|
|
||||||
|
auto sheet_node = sheets_node.append_child("sheet");
|
||||||
|
sheet_node.append_attribute("name").set_value(ws.get_title().c_str());
|
||||||
|
sheet_node.append_attribute("r:id").set_value(relationship.get_id().c_str());
|
||||||
|
sheet_node.append_attribute("sheetId").set_value(std::to_string(sheet_index + 1).c_str());
|
||||||
|
|
||||||
|
if(ws.has_auto_filter())
|
||||||
|
{
|
||||||
|
auto defined_name_node = defined_names_node.append_child("definedName");
|
||||||
|
defined_name_node.append_attribute("name").set_value("_xlnm._FilterDatabase");
|
||||||
|
defined_name_node.append_attribute("hidden").set_value(1);
|
||||||
|
defined_name_node.append_attribute("localSheetId").set_value(0);
|
||||||
|
std::string name = "'" + ws.get_title() + "'!" + range_reference::make_absolute(ws.get_auto_filter()).to_string();
|
||||||
|
defined_name_node.text().set(name.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto calc_pr_node = root_node.append_child("calcPr");
|
||||||
|
calc_pr_node.append_attribute("calcId").set_value("124519");
|
||||||
|
calc_pr_node.append_attribute("calcMode").set_value("auto");
|
||||||
|
calc_pr_node.append_attribute("fullCalcOnLoad").set_value("1");
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
|
doc.save(ss);
|
||||||
|
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string write_workbook_rels(const workbook &wb)
|
||||||
|
{
|
||||||
|
return write_relationships(wb.get_relationships(), "xl/");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string write_theme()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool save_workbook(workbook &wb, const std::string &filename, bool as_template)
|
||||||
|
{
|
||||||
|
excel_writer writer(wb);
|
||||||
|
writer.save(filename, as_template);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::uint8_t> save_virtual_workbook(xlnt::workbook &wb, bool as_template)
|
||||||
|
{
|
||||||
|
excel_writer writer(wb);
|
||||||
|
std::vector<std::uint8_t> buffer;
|
||||||
|
zip_file archive(buffer);
|
||||||
|
writer.write_data(archive, as_template);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace xlnt
|
|
@ -699,5 +699,10 @@ cell_reference worksheet::get_point_pos(const std::pair<int, int> &point) const
|
||||||
{
|
{
|
||||||
return get_point_pos(point.first, point.second);
|
return get_point_pos(point.first, point.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void worksheet::set_sheet_state(page_setup::sheet_state state)
|
||||||
|
{
|
||||||
|
get_page_setup().set_sheet_state(state);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace xlnt
|
} // namespace xlnt
|
||||||
|
|
|
@ -5,25 +5,25 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include <pugixml.hpp>
|
|
||||||
|
|
||||||
#include <xlnt/writer/writer.hpp>
|
|
||||||
#include <xlnt/cell/cell.hpp>
|
#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.hpp>
|
||||||
#include <xlnt/worksheet/range_reference.hpp>
|
#include <xlnt/worksheet/range_reference.hpp>
|
||||||
#include <xlnt/worksheet/worksheet.hpp>
|
#include <xlnt/worksheet/worksheet.hpp>
|
||||||
#include <xlnt/workbook/workbook.hpp>
|
#include <xlnt/writer/relationship_writer.hpp>
|
||||||
#include <xlnt/common/relationship.hpp>
|
#include <xlnt/writer/writer.hpp>
|
||||||
#include <xlnt/workbook/document_properties.hpp>
|
|
||||||
|
|
||||||
#include "constants.hpp"
|
#include "constants.hpp"
|
||||||
|
#include "detail/include_pugixml.hpp"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
bool is_integral(long double d)
|
bool is_integral(long double d)
|
||||||
{
|
{
|
||||||
return d == static_cast<long long int>(d);
|
return d == static_cast<long long int>(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
@ -90,129 +90,9 @@ std::string writer::write_properties_core(const document_properties &prop)
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string writer::write_properties_app(const workbook &wb)
|
|
||||||
{
|
|
||||||
pugi::xml_document doc;
|
|
||||||
auto root_node = doc.append_child("Properties");
|
|
||||||
root_node.append_attribute("xmlns").set_value("http://schemas.openxmlformats.org/officeDocument/2006/extended-properties");
|
|
||||||
root_node.append_attribute("xmlns:vt").set_value("http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes");
|
|
||||||
|
|
||||||
root_node.append_child("Application").text().set("Microsoft Excel");
|
|
||||||
root_node.append_child("DocSecurity").text().set("0");
|
|
||||||
root_node.append_child("ScaleCrop").text().set("false");
|
|
||||||
root_node.append_child("Company");
|
|
||||||
root_node.append_child("LinksUpToDate").text().set("false");
|
|
||||||
root_node.append_child("SharedDoc").text().set("false");
|
|
||||||
root_node.append_child("HyperlinksChanged").text().set("false");
|
|
||||||
root_node.append_child("AppVersion").text().set("12.0000");
|
|
||||||
|
|
||||||
auto heading_pairs_node = root_node.append_child("HeadingPairs");
|
|
||||||
auto heading_pairs_vector_node = heading_pairs_node.append_child("vt:vector");
|
|
||||||
heading_pairs_vector_node.append_attribute("baseType").set_value("variant");
|
|
||||||
heading_pairs_vector_node.append_attribute("size").set_value("2");
|
|
||||||
heading_pairs_vector_node.append_child("vt:variant").append_child("vt:lpstr").text().set("Worksheets");
|
|
||||||
heading_pairs_vector_node.append_child("vt:variant").append_child("vt:i4").text().set(std::to_string(wb.get_sheet_names().size()).c_str());
|
|
||||||
|
|
||||||
auto titles_of_parts_node = root_node.append_child("TitlesOfParts");
|
|
||||||
auto titles_of_parts_vector_node = titles_of_parts_node.append_child("vt:vector");
|
|
||||||
titles_of_parts_vector_node.append_attribute("baseType").set_value("lpstr");
|
|
||||||
titles_of_parts_vector_node.append_attribute("size").set_value(std::to_string(wb.get_sheet_names().size()).c_str());
|
|
||||||
|
|
||||||
for(auto ws : wb)
|
|
||||||
{
|
|
||||||
titles_of_parts_vector_node.append_child("vt:lpstr").text().set(ws.get_title().c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::stringstream ss;
|
|
||||||
doc.save(ss);
|
|
||||||
|
|
||||||
return ss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string writer::write_workbook_rels(const workbook &wb)
|
|
||||||
{
|
|
||||||
return write_relationships(wb.get_relationships(), "xl/");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string writer::write_worksheet_rels(worksheet ws)
|
std::string writer::write_worksheet_rels(worksheet ws)
|
||||||
{
|
{
|
||||||
return write_relationships(ws.get_relationships());
|
return write_relationships(ws.get_relationships(), "");
|
||||||
}
|
|
||||||
|
|
||||||
std::string writer::write_workbook(const workbook &wb)
|
|
||||||
{
|
|
||||||
pugi::xml_document doc;
|
|
||||||
auto root_node = doc.append_child("workbook");
|
|
||||||
root_node.append_attribute("xmlns").set_value("http://schemas.openxmlformats.org/spreadsheetml/2006/main");
|
|
||||||
root_node.append_attribute("xmlns:r").set_value("http://schemas.openxmlformats.org/officeDocument/2006/relationships");
|
|
||||||
|
|
||||||
auto file_version_node = root_node.append_child("fileVersion");
|
|
||||||
file_version_node.append_attribute("appName").set_value("xl");
|
|
||||||
file_version_node.append_attribute("lastEdited").set_value("4");
|
|
||||||
file_version_node.append_attribute("lowestEdited").set_value("4");
|
|
||||||
file_version_node.append_attribute("rupBuild").set_value("4505");
|
|
||||||
|
|
||||||
auto workbook_pr_node = root_node.append_child("workbookPr");
|
|
||||||
workbook_pr_node.append_attribute("codeName").set_value("ThisWorkbook");
|
|
||||||
workbook_pr_node.append_attribute("defaultThemeVersion").set_value("124226");
|
|
||||||
|
|
||||||
auto book_views_node = root_node.append_child("bookViews");
|
|
||||||
auto workbook_view_node = book_views_node.append_child("workbookView");
|
|
||||||
workbook_view_node.append_attribute("activeTab").set_value("0");
|
|
||||||
workbook_view_node.append_attribute("autoFilterDateGrouping").set_value("1");
|
|
||||||
workbook_view_node.append_attribute("firstSheet").set_value("0");
|
|
||||||
workbook_view_node.append_attribute("minimized").set_value("0");
|
|
||||||
workbook_view_node.append_attribute("showHorizontalScroll").set_value("1");
|
|
||||||
workbook_view_node.append_attribute("showSheetTabs").set_value("1");
|
|
||||||
workbook_view_node.append_attribute("showVerticalScroll").set_value("1");
|
|
||||||
workbook_view_node.append_attribute("tabRatio").set_value("600");
|
|
||||||
workbook_view_node.append_attribute("visibility").set_value("visible");
|
|
||||||
|
|
||||||
auto sheets_node = root_node.append_child("sheets");
|
|
||||||
auto defined_names_node = root_node.append_child("definedNames");
|
|
||||||
|
|
||||||
for(auto relationship : wb.get_relationships())
|
|
||||||
{
|
|
||||||
if(relationship.get_type() == relationship::type::worksheet)
|
|
||||||
{
|
|
||||||
std::string sheet_index_string = relationship.get_target_uri();
|
|
||||||
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);
|
|
||||||
std::size_t sheet_index = std::stoi(sheet_index_string) - 1;
|
|
||||||
|
|
||||||
auto ws = wb.get_sheet_by_index(sheet_index);
|
|
||||||
|
|
||||||
auto sheet_node = sheets_node.append_child("sheet");
|
|
||||||
sheet_node.append_attribute("name").set_value(ws.get_title().c_str());
|
|
||||||
sheet_node.append_attribute("r:id").set_value(relationship.get_id().c_str());
|
|
||||||
sheet_node.append_attribute("sheetId").set_value(std::to_string(sheet_index + 1).c_str());
|
|
||||||
|
|
||||||
if(ws.has_auto_filter())
|
|
||||||
{
|
|
||||||
auto defined_name_node = defined_names_node.append_child("definedName");
|
|
||||||
defined_name_node.append_attribute("name").set_value("_xlnm._FilterDatabase");
|
|
||||||
defined_name_node.append_attribute("hidden").set_value(1);
|
|
||||||
defined_name_node.append_attribute("localSheetId").set_value(0);
|
|
||||||
std::string name = "'" + ws.get_title() + "'!" + range_reference::make_absolute(ws.get_auto_filter()).to_string();
|
|
||||||
defined_name_node.text().set(name.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto calc_pr_node = root_node.append_child("calcPr");
|
|
||||||
calc_pr_node.append_attribute("calcId").set_value("124519");
|
|
||||||
calc_pr_node.append_attribute("calcMode").set_value("auto");
|
|
||||||
calc_pr_node.append_attribute("fullCalcOnLoad").set_value("1");
|
|
||||||
|
|
||||||
std::stringstream ss;
|
|
||||||
doc.save(ss);
|
|
||||||
|
|
||||||
return ss.str();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
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)
|
||||||
|
@ -571,50 +451,6 @@ std::string writer::write_content_types(const workbook &wb)
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string xlnt::writer::write_root_rels()
|
|
||||||
{
|
|
||||||
std::vector<relationship> relationships;
|
|
||||||
|
|
||||||
relationships.push_back(relationship(relationship::type::extended_properties, "rId3", "docProps/app.xml"));
|
|
||||||
relationships.push_back(relationship(relationship::type::core_properties, "rId2", "docProps/core.xml"));
|
|
||||||
relationships.push_back(relationship(relationship::type::office_document, "rId1", "xl/workbook.xml"));
|
|
||||||
|
|
||||||
return write_relationships(relationships);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string writer::write_relationships(const std::vector<relationship> &relationships, const std::string &dir)
|
|
||||||
{
|
|
||||||
pugi::xml_document doc;
|
|
||||||
|
|
||||||
auto root_node = doc.append_child("Relationships");
|
|
||||||
root_node.append_attribute("xmlns").set_value(constants::Namespaces.at("relationships").c_str());
|
|
||||||
|
|
||||||
for(auto relationship : relationships)
|
|
||||||
{
|
|
||||||
auto target = relationship.get_target_uri();
|
|
||||||
|
|
||||||
if (dir != "" && target.substr(0, dir.size()) == dir)
|
|
||||||
{
|
|
||||||
target = target.substr(dir.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
auto app_props_node = root_node.append_child("Relationship");
|
|
||||||
|
|
||||||
app_props_node.append_attribute("Id").set_value(relationship.get_id().c_str());
|
|
||||||
app_props_node.append_attribute("Target").set_value(target.c_str());
|
|
||||||
app_props_node.append_attribute("Type").set_value(relationship.get_type_string().c_str());
|
|
||||||
|
|
||||||
if(relationship.get_target_mode() == target_mode::external)
|
|
||||||
{
|
|
||||||
app_props_node.append_attribute("TargetMode").set_value("External");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::stringstream ss;
|
|
||||||
doc.save(ss);
|
|
||||||
return ss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string writer::write_theme()
|
std::string writer::write_theme()
|
||||||
{
|
{
|
||||||
pugi::xml_document doc;
|
pugi::xml_document doc;
|
||||||
|
|
|
@ -28,6 +28,11 @@ public:
|
||||||
operator bool() const { return difference == difference_type::equivalent; }
|
operator bool() const { return difference == difference_type::equivalent; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static comparison_result compare_xml(const std::string &left_contents, const std::string &right_contents)
|
||||||
|
{
|
||||||
|
return {difference_type::names_differ,"",""};
|
||||||
|
}
|
||||||
|
|
||||||
static comparison_result compare_xml(const pugi::xml_node &left, const pugi::xml_node &right)
|
static comparison_result compare_xml(const pugi::xml_node &left, const pugi::xml_node &right)
|
||||||
{
|
{
|
||||||
std::string left_temp = left.name();
|
std::string left_temp = left.name();
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#include <mach-o/dyld.h>
|
#include <mach-o/dyld.h>
|
||||||
|
@ -20,6 +22,15 @@
|
||||||
class PathHelper
|
class PathHelper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static std::string read_file(const std::string &filename)
|
||||||
|
{
|
||||||
|
std::ifstream f(filename);
|
||||||
|
std::ostringstream ss;
|
||||||
|
ss << f.rdbuf();
|
||||||
|
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
static std::string WindowsToUniversalPath(const std::string &windows_path)
|
static std::string WindowsToUniversalPath(const std::string &windows_path)
|
||||||
{
|
{
|
||||||
std::string fixed;
|
std::string fixed;
|
||||||
|
|
|
@ -3,14 +3,38 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cxxtest/TestSuite.h>
|
#include <cxxtest/TestSuite.h>
|
||||||
|
|
||||||
#include <xlnt/xlnt.hpp>
|
#include <xlnt/workbook/named_range.hpp>
|
||||||
|
|
||||||
class test_named_range : public CxxTest::TestSuite
|
class test_named_range : public CxxTest::TestSuite
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void test_split()
|
void test_split()
|
||||||
{
|
{
|
||||||
/*TS_ASSERT_EQUALS([("My Sheet", "$D$8"), ], split_named_range(""My Sheet"!$D$8"))*/
|
using string_pair = std::pair<std::string, std::string>;
|
||||||
|
using string_pair_vector = std::vector<string_pair>;
|
||||||
|
using expected_pair = std::pair<std::string, string_pair_vector>;
|
||||||
|
|
||||||
|
std::vector<expected_pair> expected_pairs =
|
||||||
|
{
|
||||||
|
{ "'My Sheet'!$D$8", {{ "My Sheet", "$D$8" }} },
|
||||||
|
{ "Sheet1!$A$1", {{ "Sheet1", "$A$1" }} },
|
||||||
|
{ "[1]Sheet1!$A$1", {{ "[1]Sheet1", "$A$1" }} },
|
||||||
|
{ "[1]!B2range", {{ "[1]", "" }} },
|
||||||
|
{ "Sheet1!$C$5:$C$7,Sheet1!$C$9:$C$11,Sheet1!$E$5:$E$7,Sheet1!$E$9:$E$11,Sheet1!$D$8",
|
||||||
|
{
|
||||||
|
{ "Sheet1", "$C$5:$C$7" },
|
||||||
|
{ "Sheet1", "$C$9:$C$11" },
|
||||||
|
{ "Sheet1", "$E$5:$E$7" },
|
||||||
|
{ "Sheet1", "$E$9:$E$11" },
|
||||||
|
{ "Sheet1", "$D$8" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for(auto pair : expected_pairs)
|
||||||
|
{
|
||||||
|
TS_ASSERT_EQUALS(xlnt::split_named_range(pair.first), pair.second);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_split_no_quotes()
|
void test_split_no_quotes()
|
||||||
|
|
|
@ -1,165 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <cxxtest/TestSuite.h>
|
|
||||||
|
|
||||||
#include <xlnt/xlnt.hpp>
|
|
||||||
|
|
||||||
class test_number_format : public CxxTest::TestSuite
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
test_number_format()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void setup_class(int cls)
|
|
||||||
{
|
|
||||||
//cls.workbook = Workbook()
|
|
||||||
// cls.worksheet = Worksheet(cls.workbook, "Test")
|
|
||||||
// cls.sd = SharedDate()
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_convert_date_to_julian()
|
|
||||||
{
|
|
||||||
//TS_ASSERT_EQUALS(40167, sd.to_julian(2009, 12, 20))
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_convert_date_from_julian()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_date_equal(int julian, int datetime)
|
|
||||||
{
|
|
||||||
//TS_ASSERT_EQUALS(sd.from_julian(julian), datetime);
|
|
||||||
|
|
||||||
//date_pairs = (
|
|
||||||
// (40167, datetime(2009, 12, 20)),
|
|
||||||
// (21980, datetime(1960, 3, 5)),
|
|
||||||
// );
|
|
||||||
|
|
||||||
//for count, dt in date_pairs
|
|
||||||
//{
|
|
||||||
// yield test_date_equal, count, dt;
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_convert_datetime_to_julian()
|
|
||||||
{
|
|
||||||
//TS_ASSERT_EQUALS(40167, sd.datetime_to_julian(datetime(2009, 12, 20)))
|
|
||||||
// TS_ASSERT_EQUALS(40196.5939815, sd.datetime_to_julian(datetime(2010, 1, 18, 14, 15, 20, 1600)))
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_insert_float()
|
|
||||||
{
|
|
||||||
//worksheet.cell("A1").value = 3.14
|
|
||||||
// TS_ASSERT_EQUALS(Cell.TYPE_NUMERIC, worksheet.cell("A1")._data_type)
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_insert_percentage()
|
|
||||||
{
|
|
||||||
//worksheet.cell("A1").value = "3.14%"
|
|
||||||
// TS_ASSERT_EQUALS(Cell.TYPE_NUMERIC, worksheet.cell("A1")._data_type)
|
|
||||||
// assert_almost_equal(0.0314, worksheet.cell("A1").value)
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_insert_datetime()
|
|
||||||
{
|
|
||||||
//worksheet.cell("A1").value = date.today()
|
|
||||||
// TS_ASSERT_EQUALS(Cell.TYPE_NUMERIC, worksheet.cell("A1")._data_type)
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_insert_date()
|
|
||||||
{
|
|
||||||
//worksheet.cell("A1").value = datetime.now()
|
|
||||||
// TS_ASSERT_EQUALS(Cell.TYPE_NUMERIC, worksheet.cell("A1")._data_type)
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_internal_date()
|
|
||||||
{
|
|
||||||
//dt = datetime(2010, 7, 13, 6, 37, 41)
|
|
||||||
// worksheet.cell("A3").value = dt
|
|
||||||
// TS_ASSERT_EQUALS(40372.27616898148, worksheet.cell("A3")._value)
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_datetime_interpretation()
|
|
||||||
{
|
|
||||||
//dt = datetime(2010, 7, 13, 6, 37, 41)
|
|
||||||
// worksheet.cell("A3").value = dt
|
|
||||||
// TS_ASSERT_EQUALS(dt, worksheet.cell("A3").value)
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_date_interpretation()
|
|
||||||
{
|
|
||||||
//dt = date(2010, 7, 13)
|
|
||||||
// worksheet.cell("A3").value = dt
|
|
||||||
// TS_ASSERT_EQUALS(datetime(2010, 7, 13, 0, 0), worksheet.cell("A3").value)
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_number_format_style()
|
|
||||||
{
|
|
||||||
//worksheet.cell("A1").value = "12.6%"
|
|
||||||
// TS_ASSERT_EQUALS(NumberFormat.FORMAT_PERCENTAGE, \
|
|
||||||
// worksheet.cell("A1").style.number_format.format_code)
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_date_format_on_non_date()
|
|
||||||
{
|
|
||||||
//cell = worksheet.cell("A1");
|
|
||||||
}
|
|
||||||
|
|
||||||
void check_date_pair(int count, const std::string &date_string)
|
|
||||||
{
|
|
||||||
//cell.value = strptime(date_string, "%Y-%m-%d");
|
|
||||||
//TS_ASSERT_EQUALS(count, cell._value);
|
|
||||||
|
|
||||||
//date_pairs = (
|
|
||||||
// (15, "1900-01-15"),
|
|
||||||
// (59, "1900-02-28"),
|
|
||||||
// (61, "1900-03-01"),
|
|
||||||
// (367, "1901-01-01"),
|
|
||||||
// (2958465, "9999-12-31"), );
|
|
||||||
//for count, date_string in date_pairs
|
|
||||||
//{
|
|
||||||
// yield check_date_pair, count, date_string;
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_1900_leap_year()
|
|
||||||
{
|
|
||||||
//assert_raises(ValueError, sd.from_julian, 60)
|
|
||||||
// assert_raises(ValueError, sd.to_julian, 1900, 2, 29)
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_bad_date()
|
|
||||||
{
|
|
||||||
//void check_bad_date(year, month, day)
|
|
||||||
//{
|
|
||||||
// assert_raises(ValueError, sd.to_julian, year, month, day)
|
|
||||||
//}
|
|
||||||
|
|
||||||
//bad_dates = ((1776, 7, 4), (1899, 12, 31), )
|
|
||||||
// for year, month, day in bad_dates
|
|
||||||
// {
|
|
||||||
// yield check_bad_date, year, month, day
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_bad_julian_date()
|
|
||||||
{
|
|
||||||
//assert_raises(ValueError, sd.from_julian, -1)
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_mac_date()
|
|
||||||
{
|
|
||||||
// sd.excel_base_date = CALENDAR_MAC_1904
|
|
||||||
|
|
||||||
// datetuple = (2011, 10, 31)
|
|
||||||
|
|
||||||
// dt = date(datetuple[0], datetuple[1], datetuple[2])
|
|
||||||
// julian = sd.to_julian(datetuple[0], datetuple[1], datetuple[2])
|
|
||||||
// reverse = sd.from_julian(julian).date()
|
|
||||||
// TS_ASSERT_EQUALS(dt, reverse)
|
|
||||||
// sd.excel_base_date = CALENDAR_WINDOWS_1900
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -3,7 +3,8 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cxxtest/TestSuite.h>
|
#include <cxxtest/TestSuite.h>
|
||||||
|
|
||||||
#include <xlnt/xlnt.hpp>
|
#include <xlnt/writer/workbook_writer.hpp>
|
||||||
|
|
||||||
#include "helpers/path_helper.hpp"
|
#include "helpers/path_helper.hpp"
|
||||||
#include "helpers/helper.hpp"
|
#include "helpers/helper.hpp"
|
||||||
|
|
||||||
|
@ -69,7 +70,7 @@ public:
|
||||||
xlnt::workbook wb;
|
xlnt::workbook wb;
|
||||||
wb.create_sheet();
|
wb.create_sheet();
|
||||||
wb.create_sheet();
|
wb.create_sheet();
|
||||||
auto content = xlnt::writer::write_properties_app(wb);
|
auto content = xlnt::write_properties_app(wb);
|
||||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/app.xml", content));
|
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/app.xml", content));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -41,7 +41,7 @@ public:
|
||||||
void test_write_workbook_rels()
|
void test_write_workbook_rels()
|
||||||
{
|
{
|
||||||
xlnt::workbook wb;
|
xlnt::workbook wb;
|
||||||
auto content = xlnt::writer::write_workbook_rels(wb);
|
auto content = xlnt::write_workbook_rels(wb);
|
||||||
|
|
||||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/workbook.xml.rels", content));
|
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/workbook.xml.rels", content));
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ public:
|
||||||
void test_write_workbook()
|
void test_write_workbook()
|
||||||
{
|
{
|
||||||
xlnt::workbook wb;
|
xlnt::workbook wb;
|
||||||
auto content = xlnt::writer::write_workbook(wb);
|
auto content = xlnt::write_workbook(wb);
|
||||||
|
|
||||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/workbook.xml", content));
|
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/workbook.xml", content));
|
||||||
}
|
}
|
||||||
|
@ -163,7 +163,7 @@ public:
|
||||||
auto content = xlnt::writer::write_worksheet(ws, {"hello"}, {});
|
auto content = xlnt::writer::write_worksheet(ws, {"hello"}, {});
|
||||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_auto_filter.xml", content));
|
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_auto_filter.xml", content));
|
||||||
|
|
||||||
content = xlnt::writer::write_workbook(wb);
|
content = xlnt::write_workbook(wb);
|
||||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/workbook_auto_filter.xml", content));
|
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/workbook_auto_filter.xml", content));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
175
tests/test_write_workbook.hpp
Normal file
175
tests/test_write_workbook.hpp
Normal file
|
@ -0,0 +1,175 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cxxtest/TestSuite.h>
|
||||||
|
|
||||||
|
#include <xlnt/common/exceptions.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:
|
||||||
|
void test_write_auto_filter()
|
||||||
|
{
|
||||||
|
xlnt::workbook wb;
|
||||||
|
auto ws = wb.create_sheet();
|
||||||
|
ws.get_cell("F42").set_value("hello");
|
||||||
|
ws.get_auto_filter() = "A1:F1";
|
||||||
|
|
||||||
|
auto content = xlnt::write_workbook(wb);
|
||||||
|
auto diff = Helper::compare_xml(PathHelper::read_file("workbook_auto_filter.xml"), content);
|
||||||
|
TS_ASSERT(!diff);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_write_hidden_worksheet()
|
||||||
|
{
|
||||||
|
xlnt::workbook wb;
|
||||||
|
auto ws = wb.create_sheet();
|
||||||
|
ws.set_sheet_state(xlnt::page_setup::sheet_state::hidden);
|
||||||
|
wb.create_sheet();
|
||||||
|
auto xml = xlnt::write_workbook(wb);
|
||||||
|
std::string expected =
|
||||||
|
"<workbook xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">"
|
||||||
|
" <workbookPr/>"
|
||||||
|
" <bookViews>"
|
||||||
|
" <workbookView activeTab=\"0\"/>"
|
||||||
|
" </bookViews>"
|
||||||
|
" <sheets>"
|
||||||
|
" <sheet name=\"Sheet\" sheetId=\"1\" state=\"hidden\" r:id=\"rId1\"/>"
|
||||||
|
" <sheet name=\"Sheet1\" sheetId=\"2\" r:id=\"rId2\"/>"
|
||||||
|
" </sheets>"
|
||||||
|
" <definedNames/>"
|
||||||
|
" <calcPr calcId=\"124519\" fullCalcOnLoad=\"1\"/>"
|
||||||
|
"</workbook>";
|
||||||
|
auto diff = Helper::compare_xml(xml, expected);
|
||||||
|
TS_ASSERT(!diff);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_write_hidden_single_worksheet()
|
||||||
|
{
|
||||||
|
xlnt::workbook wb;
|
||||||
|
auto ws = wb.get_active_sheet();
|
||||||
|
ws.set_sheet_state(xlnt::page_setup::sheet_state::hidden);
|
||||||
|
TS_ASSERT_THROWS(xlnt::write_workbook(wb), xlnt::value_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_write_empty_workbook()
|
||||||
|
{
|
||||||
|
xlnt::workbook wb;
|
||||||
|
std::string dest_filename = "empty_book.xlsx";
|
||||||
|
xlnt::save_workbook(wb, dest_filename);
|
||||||
|
TS_ASSERT(PathHelper::FileExists(dest_filename));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_write_virtual_workbook()
|
||||||
|
{
|
||||||
|
xlnt::workbook old_wb;
|
||||||
|
auto saved_wb = xlnt::save_virtual_workbook(old_wb);
|
||||||
|
auto new_wb = xlnt::load_workbook(saved_wb);
|
||||||
|
TS_ASSERT(new_wb != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_write_workbook_rels()
|
||||||
|
{
|
||||||
|
xlnt::workbook wb;
|
||||||
|
auto content = xlnt::write_workbook_rels(wb);
|
||||||
|
auto filename = "workbook.xml.rels";
|
||||||
|
auto diff = Helper::compare_xml(PathHelper::read_file(filename), content);
|
||||||
|
TS_ASSERT(!diff);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_write_workbook_()
|
||||||
|
{
|
||||||
|
xlnt::workbook wb;
|
||||||
|
auto content = xlnt::write_workbook(wb);
|
||||||
|
auto filename = "workbook.xml";
|
||||||
|
auto diff = Helper::compare_xml(PathHelper::read_file(filename), content);
|
||||||
|
TS_ASSERT(!diff);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_write_named_range()
|
||||||
|
{
|
||||||
|
xlnt::workbook wb;
|
||||||
|
auto ws = wb.create_sheet();
|
||||||
|
xlnt::named_range xlrange("test_range", {{ws, "A1:B5"}});
|
||||||
|
wb.add_named_range(xlrange);
|
||||||
|
auto xml = xlnt::write_defined_names(wb);
|
||||||
|
std::string expected =
|
||||||
|
"<root>"
|
||||||
|
"<s:definedName xmlns:s=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" name=\"test_range\">'Sheet'!$A$1:$B$5</s:definedName>"
|
||||||
|
"</root>";
|
||||||
|
auto diff = Helper::compare_xml(xml, expected);
|
||||||
|
TS_ASSERT(!diff);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_read_workbook_code_name()
|
||||||
|
{
|
||||||
|
// with open(tmpl, "rb") as expected:
|
||||||
|
// TS_ASSERT(read_workbook_code_name(expected.read()) == code_name
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_write_workbook_code_name()
|
||||||
|
{
|
||||||
|
xlnt::workbook wb;
|
||||||
|
wb.set_code_name("MyWB");
|
||||||
|
|
||||||
|
auto content = xlnt::write_workbook(wb);
|
||||||
|
std::string expected =
|
||||||
|
"<workbook xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">"
|
||||||
|
" <workbookPr codeName=\"MyWB\"/>"
|
||||||
|
" <bookViews>"
|
||||||
|
" <workbookView activeTab=\"0\"/>"
|
||||||
|
" </bookViews>"
|
||||||
|
" <sheets>"
|
||||||
|
" <sheet name=\"Sheet\" sheetId=\"1\" r:id=\"rId1\"/>"
|
||||||
|
" </sheets>"
|
||||||
|
" <definedNames/>"
|
||||||
|
" <calcPr calcId=\"124519\" fullCalcOnLoad=\"1\"/>"
|
||||||
|
"</workbook>";
|
||||||
|
auto diff = Helper::compare_xml(content, expected);
|
||||||
|
TS_ASSERT(!diff);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_write_root_rels()
|
||||||
|
{
|
||||||
|
xlnt::workbook wb;
|
||||||
|
auto xml = xlnt::write_root_rels(wb);
|
||||||
|
std::string expected =
|
||||||
|
"<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">"
|
||||||
|
" <Relationship Id=\"rId1\" Target=\"xl/workbook.xml\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument\"/>"
|
||||||
|
" <Relationship Id=\"rId2\" Target=\"docProps/core.xml\" Type=\"http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties\"/>"
|
||||||
|
" <Relationship Id=\"rId3\" Target=\"docProps/app.xml\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties\"/>"
|
||||||
|
"</Relationships>";
|
||||||
|
auto diff = Helper::compare_xml(xml, expected);
|
||||||
|
TS_ASSERT(!diff);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
xlnt::workbook wb_;
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user