mirror of
https://github.com/tfussell/xlnt.git
synced 2024-03-22 13:11:17 +08:00
almost done. phew...
This commit is contained in:
parent
84e9dd099e
commit
9dce7b8f0c
|
@ -30,21 +30,20 @@
|
|||
|
||||
namespace xlnt {
|
||||
|
||||
class xml_node;
|
||||
class xml_document;
|
||||
|
||||
class comment_serializer
|
||||
{
|
||||
comment_serializer(worksheet sheet);
|
||||
|
||||
void read_comments(const xml_node &xml);
|
||||
void read_comments_vml(const xml_node &xml);
|
||||
void read_comments(const xml_document &xml);
|
||||
void read_comments_vml(const xml_document &xml);
|
||||
|
||||
xml_node write_comments();
|
||||
xml_node write_comments_vml();
|
||||
xml_document write_comments() const;
|
||||
xml_document write_comments_vml() const;
|
||||
|
||||
private:
|
||||
worksheet sheet_;
|
||||
std::vector<comment> comments_;
|
||||
};
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -34,41 +34,148 @@ namespace xlnt {
|
|||
|
||||
class workbook;
|
||||
|
||||
/// <summary>
|
||||
/// Handles reading and writing workbooks from an actual XLSX archive
|
||||
/// using other serializers.
|
||||
/// </summary>
|
||||
class excel_serializer
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
static const std::string central_directory_signature();
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
static std::string repair_central_directory(const std::string &original);
|
||||
|
||||
/// <summary>
|
||||
/// Construct an excel_serializer which operates on wb.
|
||||
/// </summary>
|
||||
excel_serializer(workbook &wb);
|
||||
|
||||
/// <summary>
|
||||
/// Create a ZIP file in memory, load archive from filename, then populate workbook
|
||||
/// with data from archive.
|
||||
/// </summary>
|
||||
bool load_workbook(const std::string &filename, bool guess_types = false, bool data_only = false);
|
||||
bool load_stream_workbook(std::istream &stream, bool guess_types = false, bool data_only = false);
|
||||
bool load_virtual_workbook(const std::vector<std::uint8_t> &bytes, bool guess_types = false, bool data_only = false);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create a ZIP file in memory, load archive from stream, then populate workbook
|
||||
/// with data from archive.
|
||||
/// </summary>
|
||||
bool load_stream_workbook(std::istream &stream, bool guess_types = false, bool data_only = false);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create a ZIP file in memory, load archive from bytes, then populate workbook
|
||||
/// with data from archive.
|
||||
/// </summary>
|
||||
bool load_virtual_workbook(const std::vector<std::uint8_t> &bytes, bool guess_types = false, bool data_only = false);
|
||||
|
||||
/// <summary>
|
||||
/// Create a ZIP file in memory, save workbook to this archive, then save archive
|
||||
/// to filename.
|
||||
/// </summary>
|
||||
bool save_workbook(const std::string &filename, bool as_template = false);
|
||||
|
||||
/// <summary>
|
||||
/// Create a ZIP file in memory, save workbook to this archive, then assign ZIP file
|
||||
/// binary data to bytes.
|
||||
/// </summary>
|
||||
bool save_virtual_workbook(std::vector<std::uint8_t> &bytes, bool as_template = false);
|
||||
|
||||
/// <summary>
|
||||
/// Create a ZIP file in memory, save workbook to this archive, then copy ZIP file
|
||||
/// binary data to stream.
|
||||
/// </summary>
|
||||
bool save_stream_workbook(std::ostream &stream, bool as_template = false);
|
||||
|
||||
private:
|
||||
/// <summary>
|
||||
/// Reads all files in archive and populates workbook with associated data
|
||||
/// using other appropriate serializers such as workbook_serializer.
|
||||
/// </summary>
|
||||
void read_data(bool guess_types, bool data_only);
|
||||
|
||||
/// <summary>
|
||||
/// Read xl/sharedStrings.xml from internal archive and add shared strings to workbook.
|
||||
/// </summary>
|
||||
void read_shared_strings();
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void read_images();
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void read_charts();
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void read_chartsheets();
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void read_worksheets();
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void read_external_links();
|
||||
|
||||
/// <summary>
|
||||
/// Write all files needed to create a valid XLSX file which represents all
|
||||
/// data contained in workbook.
|
||||
/// </summary>
|
||||
void write_data(bool as_template);
|
||||
|
||||
/// <summary>
|
||||
/// Write xl/sharedStrings.xml to internal archive based on shared strings in workbook.
|
||||
/// </summary>
|
||||
void write_shared_strings();
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void write_images();
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void write_charts();
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void write_chartsheets();
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void write_worksheets();
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void write_external_links();
|
||||
|
||||
workbook &wb_;
|
||||
std::vector<std::string> shared_strings_;
|
||||
/// <summary>
|
||||
/// A reference to the workbook which is the object of read/write operations.
|
||||
/// </summary>
|
||||
workbook &workbook_;
|
||||
|
||||
/// <summary>
|
||||
/// The internal archive which holds files representing workbook_ during
|
||||
/// read/write operations.
|
||||
/// </summary>
|
||||
zip_file archive_;
|
||||
};
|
||||
|
||||
|
|
|
@ -5,17 +5,17 @@
|
|||
namespace xlnt {
|
||||
|
||||
class manifest;
|
||||
class workbook;
|
||||
class xml_document;
|
||||
class zip_file;
|
||||
|
||||
class manifest_serializer
|
||||
{
|
||||
public:
|
||||
manifest_serializer(manifest &m);
|
||||
|
||||
bool read_manifest(const xml_document &xml);
|
||||
bool write_manifest(xml_document &xml);
|
||||
void read_manifest(const xml_document &xml);
|
||||
xml_document write_manifest() const;
|
||||
|
||||
std::string determine_document_type() const;
|
||||
|
||||
private:
|
||||
manifest &manifest_;
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
namespace xlnt {
|
||||
|
||||
class relationship;
|
||||
class xml_document;
|
||||
class zip_file;
|
||||
|
||||
class relationship_serializer
|
||||
{
|
||||
public:
|
||||
static bool read_relationships(const xml_document &xml, const std::string &dir, std::vector<relationship> &relationships);
|
||||
static bool write_relationships(const std::vector<relationship> &relationships, const std::string &dir, xml_document &xml);
|
||||
static std::vector<relationship> read_relationships(zip_file &archive, const std::string &target);
|
||||
static bool write_relationships(const std::vector<relationship> &relationships, const std::string &target, zip_file &archive);
|
||||
};
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -33,8 +33,8 @@ class xml_document;
|
|||
class shared_strings_serializer
|
||||
{
|
||||
public:
|
||||
bool read_strings(const xml_document &xml, std::vector<std::string> &strings);
|
||||
bool write_strings(const std::vector<std::string> &strings, xml_document &xml);
|
||||
static bool read_shared_strings(const xml_document &xml, std::vector<std::string> &strings);
|
||||
static xml_document write_shared_strings(const std::vector<std::string> &strings);
|
||||
};
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -56,6 +56,10 @@ public:
|
|||
/// with styles from an existing styles.xml.
|
||||
style_serializer(workbook &wb);
|
||||
|
||||
//
|
||||
// Primary methods
|
||||
//
|
||||
|
||||
/// <summary>
|
||||
/// Load all styles from xml_document into workbook given in constructor.
|
||||
/// </summary>
|
||||
|
@ -65,28 +69,118 @@ public:
|
|||
/// Populate parameter xml with an XML tree representing the styles contained in the workbook
|
||||
/// given in the constructor.
|
||||
/// </summary>
|
||||
bool write_stylesheet(xml_document &xml) const;
|
||||
xml_document write_stylesheet() const;
|
||||
|
||||
private:
|
||||
/// <summary>
|
||||
/// Read a single style from the given node. In styles.xml, this is an "xf" element.
|
||||
/// A style has an optional border id, fill id, font id, and number format id where
|
||||
/// each id is an index in the corresponding list of borders, etc. A style also has
|
||||
/// optional alignment and protection children. A style also defines whether each of
|
||||
/// these is "applied". For example, a style with a defined font id, font=# but with
|
||||
/// "applyFont=0" will not use the font in formatting.
|
||||
/// </summary>
|
||||
style read_style(const xml_node &style_node) const;
|
||||
//TODO: These need to be public for unit tests. Could also make test class a friend?
|
||||
//private:
|
||||
|
||||
//
|
||||
// Static element readers (i.e. readers that don't use internal state)
|
||||
//
|
||||
|
||||
/// <summary>
|
||||
/// Read and return an alignment from alignment_node.
|
||||
/// </summary>
|
||||
alignment read_alignment(const xml_node &alignment_node) const;
|
||||
static alignment read_alignment(const xml_node &alignment_node);
|
||||
|
||||
/// <summary>
|
||||
/// Read and return a border side from side_node.
|
||||
/// </summary>
|
||||
side read_side(const xml_node &side_node) const;
|
||||
static side read_side(const xml_node &side_node);
|
||||
|
||||
/// <summary>
|
||||
/// Read and return a border from border_node.
|
||||
/// </summary>
|
||||
static border read_border(const xml_node &border_node);
|
||||
|
||||
/// <summary>
|
||||
/// Read and return a fill from fill_node.
|
||||
/// </summary>
|
||||
static fill read_fill(const xml_node &fill_node);
|
||||
|
||||
/// <summary>
|
||||
/// Read and return a font from font_node.
|
||||
/// </summary>
|
||||
static font read_font(const xml_node &font_node);
|
||||
|
||||
/// <summary>
|
||||
/// Read and return a number format from number_format_node.
|
||||
/// </summary>
|
||||
static number_format read_number_format(const xml_node &number_format_node);
|
||||
|
||||
/// <summary>
|
||||
/// Read and return a protection from protection_node.
|
||||
/// </summary>
|
||||
static protection read_protection(const xml_node &protection_node);
|
||||
|
||||
/// <summary>
|
||||
/// Read and return all indexed colors from indexed_colors_node.
|
||||
/// </summary>
|
||||
static std::vector<color> read_indexed_colors(const xml_node &indexed_colors_node);
|
||||
|
||||
/// <summary>
|
||||
/// Read and return a color from color_node.
|
||||
/// </summary>
|
||||
static color read_color(const xml_node &color_node);
|
||||
|
||||
/// <summary>
|
||||
/// Read and return a conditional format, dxf, from conditional_format_node.
|
||||
/// </summary>
|
||||
static conditional_format read_conditional_format(const xml_node &conditional_formats_node);
|
||||
|
||||
/// <summary>
|
||||
/// Read and return a pair containing a name and corresponding style from named_style_node.
|
||||
/// </summary>
|
||||
static std::pair<std::string, style> read_named_style(const xml_node &named_style_node);
|
||||
|
||||
//
|
||||
// Static element writers (i.e. writers that don't use internal state)
|
||||
//
|
||||
|
||||
/// <summary>
|
||||
/// Build and return an xml tree representing alignment_.
|
||||
/// </summary>
|
||||
static xml_node write_alignment(const alignment &alignment_);
|
||||
|
||||
/// <summary>
|
||||
/// Build and return an xml tree representing border_.
|
||||
/// </summary>
|
||||
static xml_node write_border(const border &border_);
|
||||
|
||||
/// <summary>
|
||||
/// Build and return an xml tree representing conditional_format_.
|
||||
/// </summary>
|
||||
static xml_node write_conditional_format(const conditional_format &conditional_format_);
|
||||
|
||||
/// <summary>
|
||||
/// Build and return an xml tree representing fill_.
|
||||
/// </summary>
|
||||
static xml_node write_fill(const fill &fill_);
|
||||
|
||||
/// <summary>
|
||||
/// Build and return an xml tree representing font_.
|
||||
/// </summary>
|
||||
static xml_node write_font(const font &font_);
|
||||
|
||||
/// <summary>
|
||||
/// Build and return two xml trees, first=cell style and second=named style, representing named_style_.
|
||||
/// </summary>
|
||||
static std::pair<xml_node, xml_node> write_named_style(const named_style &named_style_);
|
||||
|
||||
/// <summary>
|
||||
/// Build an xml tree representing all named styles in workbook into named_styles_node and cell_styles_node.
|
||||
/// Returns true on success.
|
||||
/// </summary>
|
||||
static std::pair<xml_node, xml_node> write_named_styles();
|
||||
|
||||
/// <summary>
|
||||
/// Build and return an xml tree representing number_format_.
|
||||
/// </summary>
|
||||
static xml_node write_number_format(const number_format &number_format_);
|
||||
|
||||
//
|
||||
// Non-static element readers (i.e. readers that modify internal state)
|
||||
//
|
||||
|
||||
/// <summary>
|
||||
/// Read all borders from borders_node and add them to workbook.
|
||||
|
@ -94,70 +188,24 @@ private:
|
|||
/// </summary>
|
||||
bool read_borders(const xml_node &borders_node);
|
||||
|
||||
/// <summary>
|
||||
/// Read and return a border from border_node.
|
||||
/// </summary>
|
||||
border read_border(const xml_node &border_node) const;
|
||||
|
||||
/// <summary>
|
||||
/// Read all fills from fills_node and add them to workbook.
|
||||
/// Return true on success.
|
||||
/// </summary>
|
||||
bool read_fills(const xml_node &fills_node);
|
||||
|
||||
/// <summary>
|
||||
/// Read and return a fill from fill_node.
|
||||
/// </summary>
|
||||
fill read_fill(const xml_node &fill_node) const;
|
||||
|
||||
/// <summary>
|
||||
/// Read all fonts from fonts_node and add them to workbook.
|
||||
/// Return true on success.
|
||||
/// </summary>
|
||||
bool read_fonts(const xml_node &fonts_node);
|
||||
|
||||
/// <summary>
|
||||
/// Read and return a font from font_node.
|
||||
/// </summary>
|
||||
font read_font(const xml_node &font_node) const;
|
||||
|
||||
/// <summary>
|
||||
/// Read all borders from number_formats_node and add them to workbook.
|
||||
/// Return true on success.
|
||||
/// </summary>
|
||||
bool read_number_formats(const xml_node &number_formats_node);
|
||||
|
||||
/// <summary>
|
||||
/// Read and return a number format from number_format_node.
|
||||
/// </summary>
|
||||
number_format read_number_format(const xml_node &number_format_node) const;
|
||||
|
||||
/// <summary>
|
||||
/// Read and return a protection from protection_node.
|
||||
/// </summary>
|
||||
protection read_protection(const xml_node &protection_node) const;
|
||||
|
||||
/// <summary>
|
||||
/// Read all colors from colors_node and add them to workbook.
|
||||
/// Return true on success.
|
||||
/// </summary>
|
||||
bool read_colors(const xml_node &colors_node);
|
||||
|
||||
/// <summary>
|
||||
/// Read and return all indexed colors from indexed_colors_node.
|
||||
/// </summary>
|
||||
std::vector<color> read_indexed_colors(const xml_node &indexed_colors_node) const;
|
||||
|
||||
/// <summary>
|
||||
/// Read and return a color from color_node.
|
||||
/// </summary>
|
||||
color read_color(const xml_node &color_node) const;
|
||||
|
||||
/// <summary>
|
||||
/// Read and return a conditional format, dxf, from conditional_format_node.
|
||||
/// </summary>
|
||||
conditional_format read_conditional_format(const xml_node &conditional_formats_node) const;
|
||||
|
||||
/// <summary>
|
||||
/// Read all named styles from named_style_node and cell_styles_node and add them to workbook.
|
||||
/// Return true on success.
|
||||
|
@ -165,19 +213,24 @@ private:
|
|||
bool read_named_styles(const xml_node &named_styles_node);
|
||||
|
||||
/// <summary>
|
||||
/// Read and return a pair containing a name and corresponding style from named_style_node.
|
||||
/// Read all borders from number_formats_node and add them to workbook.
|
||||
/// Return true on success.
|
||||
/// </summary>
|
||||
std::pair<std::string, style> read_named_style(const xml_node &named_style_node) const;
|
||||
bool read_number_formats(const xml_node &number_formats_node);
|
||||
|
||||
/// <summary>
|
||||
/// Build and return an xml tree representing alignment_.
|
||||
/// Read a single style from the given node. In styles.xml, this is an "xf" element.
|
||||
/// A style has an optional border id, fill id, font id, and number format id where
|
||||
/// each id is an index in the corresponding list of borders, etc. A style also has
|
||||
/// optional alignment and protection children. A style also defines whether each of
|
||||
/// these is "applied". For example, a style with a defined font id, font=# but with
|
||||
/// "applyFont=0" will not use the font in formatting.
|
||||
/// </summary>
|
||||
xml_node write_alignment(const alignment &alignment_) const;
|
||||
style read_style(const xml_node &style_node);
|
||||
|
||||
/// <summary>
|
||||
/// Build and return an xml tree representing border_.
|
||||
/// </summary>
|
||||
xml_node write_border(const border &border_) const;
|
||||
//
|
||||
// Non-static element writers (i.e. writers that modify internal workbook)
|
||||
//
|
||||
|
||||
/// <summary>
|
||||
/// Build an xml tree representing all borders in workbook into borders_node.
|
||||
|
@ -186,9 +239,10 @@ private:
|
|||
bool write_borders(xml_node &borders_node) const;
|
||||
|
||||
/// <summary>
|
||||
/// Build and return an xml tree representing fill_.
|
||||
/// Build an xml tree representing all conditional formats in workbook into conditional_formats_node.
|
||||
/// Returns true on success.
|
||||
/// </summary>
|
||||
xml_node write_fill(const fill &fill_) const;
|
||||
bool write_conditional_formats(xml_node &conditional_formats_node) const;
|
||||
|
||||
/// <summary>
|
||||
/// Build an xml tree representing all fills in workbook into fills_node.
|
||||
|
@ -196,38 +250,17 @@ private:
|
|||
/// </summary>
|
||||
bool write_fills(xml_node &fills_node) const;
|
||||
|
||||
/// <summary>
|
||||
/// Build and return an xml tree representing font_.
|
||||
/// </summary>
|
||||
xml_node write_font(const font &font_) const;
|
||||
|
||||
/// <summary>
|
||||
/// Build an xml tree representing all fonts in workbook into fonts_node.
|
||||
/// Returns true on success.
|
||||
/// </summary>
|
||||
bool write_fonts(xml_node &fonts_node) const;
|
||||
|
||||
/// <summary>
|
||||
/// Build and return an xml tree representing number_format_.
|
||||
/// </summary>
|
||||
xml_node write_number_format(const number_format &number_format_) const;
|
||||
|
||||
/// <summary>
|
||||
/// Build an xml tree representing all number formats in workbook into number_formats_node.
|
||||
/// Returns true on success.
|
||||
/// </summary>
|
||||
bool write_number_formats(xml_node &fonts_node) const;
|
||||
|
||||
/// <summary>
|
||||
/// Build and return two xml trees, first=cell style and second=named style, representing named_style_.
|
||||
/// </summary>
|
||||
std::pair<xml_node, xml_node> write_named_style(const named_style &named_style_) const;
|
||||
|
||||
/// <summary>
|
||||
/// Build an xml tree representing all named styles in workbook into named_styles_node and cell_styles_node.
|
||||
/// Returns true on success.
|
||||
/// </summary>
|
||||
void write_named_styles(xml_node &named_styles_node, xml_node &cell_styles_node) const;
|
||||
bool write_number_formats(xml_node fonts_node) const;
|
||||
|
||||
/// <summary>
|
||||
/// Build an xml tree representing the given style into style_node.
|
||||
|
@ -235,21 +268,11 @@ private:
|
|||
/// </summary>
|
||||
bool write_style(const style &style_, xml_node &style_node) const;
|
||||
|
||||
/// <summary>
|
||||
/// Build and return an xml tree representing conditional_format_.
|
||||
/// </summary>
|
||||
xml_node write_conditional_format(const conditional_format &conditional_format_) const;
|
||||
|
||||
/// <summary>
|
||||
/// Build an xml tree representing all conditional formats in workbook into conditional_formats_node.
|
||||
/// Returns true on success.
|
||||
/// </summary>
|
||||
bool write_conditional_formats(xml_node &conditional_formats_node) const;
|
||||
|
||||
private:
|
||||
/// <summary>
|
||||
/// Set in the constructor, this workbook is used as the source or target for all writing or reading, respectively.
|
||||
/// </summary>
|
||||
workbook &wb_;
|
||||
workbook &workbook_;
|
||||
};
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -33,8 +33,10 @@ class xml_document;
|
|||
class theme_serializer
|
||||
{
|
||||
public:
|
||||
//theme read_theme(const xml_document &xml);
|
||||
xml_document write_theme(const theme &theme_);
|
||||
bool read_theme(const xml_document &xml, theme &t);
|
||||
xml_document write_theme(const theme &t) const;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -40,8 +40,7 @@ class xml_node;
|
|||
class workbook_serializer
|
||||
{
|
||||
public:
|
||||
//TODO: does this go here?
|
||||
static std::string determine_document_type(const manifest &manifest_);
|
||||
using string_pair = std::pair<std::string, std::string>;
|
||||
|
||||
workbook_serializer(workbook &wb);
|
||||
|
||||
|
@ -53,15 +52,13 @@ public:
|
|||
xml_document write_properties_app() const;
|
||||
xml_document write_properties_core() const;
|
||||
|
||||
using string_pair = std::pair<std::string, std::string>;
|
||||
|
||||
std::vector<string_pair> read_sheets();
|
||||
std::vector<string_pair> detect_worksheets();
|
||||
|
||||
bool write_named_ranges(xml_node &named_ranges_node);
|
||||
xml_node write_named_ranges() const;
|
||||
|
||||
private:
|
||||
workbook &wb_;
|
||||
workbook &workbook_;
|
||||
};
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -34,15 +34,14 @@ class relationship;
|
|||
class workbook;
|
||||
class worksheet;
|
||||
class xml_document;
|
||||
class xml_node;
|
||||
|
||||
class worksheet_serializer
|
||||
{
|
||||
public:
|
||||
worksheet_serializer(worksheet sheet);
|
||||
|
||||
bool read_worksheet(const xml_document &xml, const std::vector<std::string> &shared_strings, const relationship &rel);
|
||||
bool write_worksheet(const std::vector<std::string> &string_table, xml_document &xml);
|
||||
bool read_worksheet(const xml_document &xml);
|
||||
xml_document write_worksheet() const;
|
||||
|
||||
private:
|
||||
worksheet sheet_;
|
||||
|
|
|
@ -1,25 +1,48 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <xlnt/s11n/xml_node.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
namespace detail {
|
||||
struct xml_document_impl;
|
||||
} // namespace detail
|
||||
|
||||
class xml_node;
|
||||
class xml_serializer;
|
||||
|
||||
class xml_document
|
||||
{
|
||||
public:
|
||||
using string_pair = std::pair<std::string, std::string>;
|
||||
|
||||
xml_document();
|
||||
xml_document(const xml_document &other);
|
||||
xml_document(xml_document &&other);
|
||||
~xml_document();
|
||||
|
||||
xml_document &operator=(const xml_document &other);
|
||||
xml_document &operator=(xml_document &&other);
|
||||
|
||||
void set_encoding(const std::string &encoding);
|
||||
void add_namespace(const std::string &id, const std::string &uri);
|
||||
|
||||
xml_node &root();
|
||||
const xml_node &root() const;
|
||||
xml_node add_child(const xml_node &child);
|
||||
xml_node add_child(const std::string &child_name);
|
||||
|
||||
xml_node get_root();
|
||||
const xml_node get_root() const;
|
||||
|
||||
xml_node get_child(const std::string &child_name);
|
||||
const xml_node get_child(const std::string &child_name) const;
|
||||
|
||||
std::string to_string() const;
|
||||
xml_document &from_string(const std::string &xml_string);
|
||||
|
||||
private:
|
||||
xml_node root_;
|
||||
std::string encoding_;
|
||||
std::vector<string_pair> namespaces_;
|
||||
friend class xml_serializer;
|
||||
std::unique_ptr<detail::xml_document_impl> d_;
|
||||
};
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -1,17 +1,26 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
using string_pair = std::pair<std::string, std::string>;
|
||||
|
||||
namespace detail {
|
||||
struct xml_node_impl;
|
||||
} // namespace detail
|
||||
|
||||
class xml_document;
|
||||
|
||||
class xml_node
|
||||
{
|
||||
public:
|
||||
using string_pair = std::pair<std::string, std::string>;
|
||||
|
||||
xml_node();
|
||||
explicit xml_node(const std::string &name);
|
||||
xml_node(const xml_node &other);
|
||||
~xml_node();
|
||||
|
||||
xml_node &operator=(const xml_node &other);
|
||||
|
||||
std::string get_name() const;
|
||||
void set_name(const std::string &name);
|
||||
|
@ -20,24 +29,25 @@ public:
|
|||
std::string get_text() const;
|
||||
void set_text(const std::string &text);
|
||||
|
||||
const std::vector<xml_node> &get_children() const;
|
||||
const std::vector<xml_node> get_children() const;
|
||||
bool has_child(const std::string &child_name) const;
|
||||
xml_node &get_child(const std::string &child_name);
|
||||
const xml_node &get_child(const std::string &child_name) const;
|
||||
xml_node &add_child(const xml_node &child);
|
||||
xml_node &add_child(const std::string &child_name);
|
||||
xml_node get_child(const std::string &child_name);
|
||||
const xml_node get_child(const std::string &child_name) const;
|
||||
xml_node add_child(const xml_node &child);
|
||||
xml_node add_child(const std::string &child_name);
|
||||
|
||||
const std::vector<string_pair> &get_attributes() const;
|
||||
const std::vector<string_pair> get_attributes() const;
|
||||
bool has_attribute(const std::string &attribute_name) const;
|
||||
std::string get_attribute(const std::string &attribute_name) const;
|
||||
void add_attribute(const std::string &name, const std::string &value);
|
||||
|
||||
std::string to_string() const;
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
bool has_text_ = false;
|
||||
std::string text_;
|
||||
std::vector<string_pair> attributes_;
|
||||
std::vector<xml_node> children_;
|
||||
friend class xml_document;
|
||||
friend class xml_serializer;
|
||||
xml_node(const detail::xml_node_impl &d);
|
||||
std::unique_ptr<detail::xml_node_impl> d_;
|
||||
};
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -3,14 +3,17 @@
|
|||
#include <string>
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
|
||||
class xml_document;
|
||||
class xml_node;
|
||||
|
||||
class xml_serializer
|
||||
{
|
||||
public:
|
||||
static std::string serialize(const xml_document &xml);
|
||||
static xml_document deserialize(const std::string &xml_string);
|
||||
|
||||
static std::string serialize_node(const xml_node &xml);
|
||||
};
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -118,7 +118,7 @@ public:
|
|||
{
|
||||
if(type_ != type::rgb)
|
||||
{
|
||||
throw std::runtime_error("not theme color");
|
||||
throw std::runtime_error("not rgb color");
|
||||
}
|
||||
|
||||
return rgb_string_;
|
||||
|
|
|
@ -248,7 +248,11 @@ public:
|
|||
const manifest &get_manifest() const;
|
||||
|
||||
const std::vector<relationship> &get_root_relationships() const;
|
||||
|
||||
|
||||
void add_shared_string(const std::string &shared);
|
||||
std::vector<std::string> &get_shared_strings();
|
||||
const std::vector<std::string> &get_shared_strings() const;
|
||||
|
||||
private:
|
||||
friend class worksheet;
|
||||
std::shared_ptr<detail::workbook_impl> d_;
|
||||
|
|
|
@ -361,7 +361,7 @@ section parse_section(const std::string §ion_string)
|
|||
|
||||
static const std::vector<std::string> bracket_times = { "h", "hh", "m", "mm", "s", "ss" };
|
||||
|
||||
for(int i = 0; i < section_string.size(); i++)
|
||||
for(std::size_t i = 0; i < section_string.size(); i++)
|
||||
{
|
||||
if(!in_quotes && section_string[i] == '"')
|
||||
{
|
||||
|
|
|
@ -15,7 +15,8 @@ struct workbook_impl
|
|||
worksheets_(other.worksheets_),
|
||||
relationships_(other.relationships_),
|
||||
root_relationships_(other.root_relationships_),
|
||||
drawings_(other.drawings_),
|
||||
drawings_(other.drawings_),
|
||||
shared_strings_(other.shared_strings_),
|
||||
properties_(other.properties_),
|
||||
guess_types_(other.guess_types_),
|
||||
data_only_(other.data_only_),
|
||||
|
@ -40,6 +41,8 @@ struct workbook_impl
|
|||
std::copy(other.root_relationships_.begin(), other.root_relationships_.end(), std::back_inserter(root_relationships_));
|
||||
drawings_.clear();
|
||||
std::copy(other.drawings_.begin(), other.drawings_.end(), back_inserter(drawings_));
|
||||
shared_strings_.clear();
|
||||
std::copy(other.shared_strings_.begin(), other.shared_strings_.end(), std::back_inserter(shared_strings_));
|
||||
properties_ = other.properties_;
|
||||
guess_types_ = other.guess_types_;
|
||||
data_only_ = other.data_only_;
|
||||
|
@ -59,6 +62,7 @@ struct workbook_impl
|
|||
std::vector<relationship> relationships_;
|
||||
std::vector<relationship> root_relationships_;
|
||||
std::vector<drawing> drawings_;
|
||||
std::vector<std::string> shared_strings_;
|
||||
|
||||
document_properties properties_;
|
||||
|
||||
|
|
17
source/detail/xml_document_impl.hpp
Normal file
17
source/detail/xml_document_impl.hpp
Normal file
|
@ -0,0 +1,17 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <detail/include_pugixml.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
namespace detail {
|
||||
|
||||
struct xml_document_impl
|
||||
{
|
||||
std::string encoding;
|
||||
pugi::xml_document doc;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace xlnt
|
16
source/detail/xml_node_impl.hpp
Normal file
16
source/detail/xml_node_impl.hpp
Normal file
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
#include <detail/include_pugixml.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
namespace detail {
|
||||
|
||||
struct xml_node_impl
|
||||
{
|
||||
xml_node_impl() {}
|
||||
explicit xml_node_impl(pugi::xml_node n) : node(n) {}
|
||||
pugi::xml_node node;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace xlnt
|
|
@ -8,6 +8,7 @@
|
|||
#include <xlnt/s11n/workbook_serializer.hpp>
|
||||
#include <xlnt/s11n/worksheet_serializer.hpp>
|
||||
#include <xlnt/s11n/xml_document.hpp>
|
||||
#include <xlnt/s11n/xml_node.hpp>
|
||||
#include <xlnt/s11n/xml_serializer.hpp>
|
||||
#include <xlnt/workbook/document_properties.hpp>
|
||||
#include <xlnt/workbook/manifest.hpp>
|
||||
|
@ -43,44 +44,49 @@ bool load_workbook(xlnt::zip_file &archive, bool guess_types, bool data_only, xl
|
|||
xlnt::manifest_serializer ms(wb.get_manifest());
|
||||
ms.read_manifest(xlnt::xml_serializer::deserialize(archive.read(xlnt::constants::ArcContentTypes)));
|
||||
|
||||
if(xlnt::workbook_serializer::determine_document_type(wb.get_manifest()) != "excel")
|
||||
if(ms.determine_document_type() != "excel")
|
||||
{
|
||||
throw xlnt::invalid_file_exception("");
|
||||
}
|
||||
|
||||
wb.clear();
|
||||
|
||||
std::vector<xlnt::relationship> workbook_relationships;
|
||||
xlnt::relationship_serializer::read_relationships(xlnt::xml_serializer::deserialize(archive.read("xl/_rels/workbook.xml.rels")), "", workbook_relationships);
|
||||
auto workbook_relationships = xlnt::relationship_serializer::read_relationships(archive, xlnt::constants::ArcWorkbook);
|
||||
|
||||
for(auto relationship : workbook_relationships)
|
||||
for(const auto &relationship : workbook_relationships)
|
||||
{
|
||||
wb.create_relationship(relationship.get_id(), relationship.get_target_uri(), relationship.get_type());
|
||||
}
|
||||
|
||||
auto xml = xlnt::xml_serializer::deserialize(archive.read(xlnt::constants::ArcWorkbook));
|
||||
|
||||
auto &root_node = xml.root();
|
||||
auto root_node = xml.get_child("workbook");
|
||||
|
||||
auto &workbook_pr_node = root_node.get_child("workbookPr");
|
||||
auto workbook_pr_node = root_node.get_child("workbookPr");
|
||||
wb.get_properties().excel_base_date = (workbook_pr_node.has_attribute("date1904") && workbook_pr_node.get_attribute("date1904") != "0") ? xlnt::calendar::mac_1904 : xlnt::calendar::windows_1900;
|
||||
|
||||
xlnt::shared_strings_serializer shared_strings_serializer_;
|
||||
std::vector<std::string> shared_strings;
|
||||
shared_strings_serializer_.read_strings(xlnt::xml_serializer::deserialize(archive.read(xlnt::constants::ArcSharedString)), shared_strings);
|
||||
shared_strings_serializer_.read_shared_strings(xlnt::xml_serializer::deserialize(archive.read(xlnt::constants::ArcSharedString)), shared_strings);
|
||||
|
||||
for(auto shared_string : shared_strings)
|
||||
{
|
||||
wb.add_shared_string(shared_string);
|
||||
}
|
||||
|
||||
xlnt::style_serializer style_reader_(wb);
|
||||
style_reader_.read_stylesheet(xlnt::xml_serializer::deserialize(archive.read(xlnt::constants::ArcStyles)));
|
||||
|
||||
auto &sheets_node = root_node.get_child("sheets");
|
||||
auto sheets_node = root_node.get_child("sheets");
|
||||
|
||||
for(auto sheet_node : sheets_node.get_children())
|
||||
{
|
||||
auto rel = wb.get_relationship(sheet_node.get_attribute("r:id"));
|
||||
auto ws = wb.create_sheet(sheet_node.get_attribute("name"), rel);
|
||||
auto ws_filename = "xl/" + rel.get_target_uri();
|
||||
|
||||
xlnt::worksheet_serializer worksheet_serializer(ws);
|
||||
worksheet_serializer.read_worksheet(xlnt::xml_serializer::deserialize(archive.read(rel.get_target_uri())), shared_strings, rel);
|
||||
worksheet_serializer.read_worksheet(xlnt::xml_serializer::deserialize(archive.read(ws_filename)));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -126,52 +132,45 @@ bool excel_serializer::load_workbook(const std::string &filename, bool guess_typ
|
|||
throw invalid_file_exception(filename);
|
||||
}
|
||||
|
||||
return ::load_workbook(archive_, guess_types, data_only, wb_);
|
||||
return ::load_workbook(archive_, guess_types, data_only, workbook_);
|
||||
}
|
||||
|
||||
bool excel_serializer::load_virtual_workbook(const std::vector<std::uint8_t> &bytes, bool guess_types, bool data_only)
|
||||
{
|
||||
archive_.load(bytes);
|
||||
|
||||
return ::load_workbook(archive_, guess_types, data_only, wb_);
|
||||
return ::load_workbook(archive_, guess_types, data_only, workbook_);
|
||||
}
|
||||
|
||||
excel_serializer::excel_serializer(workbook &wb) : wb_(wb)
|
||||
excel_serializer::excel_serializer(workbook &wb) : workbook_(wb)
|
||||
{
|
||||
}
|
||||
|
||||
void excel_serializer::write_data(bool as_template)
|
||||
void excel_serializer::write_data(bool /*as_template*/)
|
||||
{
|
||||
relationship_serializer relationship_serializer_;
|
||||
|
||||
xlnt::xml_document root_rels_xml;
|
||||
relationship_serializer_.write_relationships(wb_.get_root_relationships(), "", root_rels_xml);
|
||||
archive_.writestr(constants::ArcRootRels, xml_serializer::serialize(root_rels_xml));
|
||||
|
||||
xml_document workbook_rels_xml;
|
||||
relationship_serializer_.write_relationships(wb_.get_relationships(), "", workbook_rels_xml);
|
||||
archive_.writestr(constants::ArcWorkbookRels, xml_serializer::serialize(workbook_rels_xml));
|
||||
relationship_serializer_.write_relationships(workbook_.get_root_relationships(), "", archive_);
|
||||
relationship_serializer_.write_relationships(workbook_.get_relationships(), constants::ArcWorkbook, archive_);
|
||||
|
||||
xml_document properties_app_xml;
|
||||
workbook_serializer workbook_serializer_(wb_);
|
||||
workbook_serializer workbook_serializer_(workbook_);
|
||||
archive_.writestr(constants::ArcApp, xml_serializer::serialize(workbook_serializer_.write_properties_app()));
|
||||
archive_.writestr(constants::ArcCore, xml_serializer::serialize(workbook_serializer_.write_properties_core()));
|
||||
|
||||
theme_serializer theme_serializer_;
|
||||
xml_document theme_xml = theme_serializer_.write_theme(wb_.get_loaded_theme());
|
||||
archive_.writestr(constants::ArcTheme, xml_serializer::serialize(theme_xml));
|
||||
archive_.writestr(constants::ArcTheme, theme_serializer_.write_theme(workbook_.get_loaded_theme()).to_string());
|
||||
|
||||
xlnt::shared_strings_serializer shared_strings_serializer_;
|
||||
archive_.writestr(constants::ArcSharedString, xml_serializer::serialize(shared_strings_serializer_.write_shared_strings(workbook_.get_shared_strings())));
|
||||
|
||||
archive_.writestr(constants::ArcWorkbook, xml_serializer::serialize(workbook_serializer_.write_workbook()));
|
||||
|
||||
style_serializer style_serializer_(wb_);
|
||||
xml_document style_xml;
|
||||
style_serializer_.write_stylesheet(style_xml);
|
||||
archive_.writestr(constants::ArcStyles, xml_serializer::serialize(style_xml));
|
||||
style_serializer style_serializer_(workbook_);
|
||||
archive_.writestr(constants::ArcStyles, style_serializer_.write_stylesheet().to_string());
|
||||
|
||||
manifest_serializer manifest_serializer_(wb_.get_manifest());
|
||||
xml_document manifest_xml;
|
||||
manifest_serializer_.write_manifest(manifest_xml);
|
||||
archive_.writestr(constants::ArcContentTypes, xml_serializer::serialize(manifest_xml));
|
||||
manifest_serializer manifest_serializer_(workbook_.get_manifest());
|
||||
archive_.writestr(constants::ArcContentTypes, manifest_serializer_.write_manifest().to_string());
|
||||
|
||||
write_worksheets();
|
||||
}
|
||||
|
@ -180,17 +179,16 @@ void excel_serializer::write_worksheets()
|
|||
{
|
||||
std::size_t index = 0;
|
||||
|
||||
for(auto ws : wb_)
|
||||
for(auto ws : workbook_)
|
||||
{
|
||||
for(auto relationship : wb_.get_relationships())
|
||||
for(auto relationship : workbook_.get_relationships())
|
||||
{
|
||||
if(relationship.get_type() == relationship::type::worksheet &&
|
||||
workbook::index_from_ws_filename(relationship.get_target_uri()) == index)
|
||||
{
|
||||
worksheet_serializer serializer_(ws);
|
||||
xml_document xml;
|
||||
serializer_.write_worksheet(shared_strings_, xml);
|
||||
archive_.writestr(relationship.get_target_uri(), xml_serializer::serialize(xml));
|
||||
std::string ws_filename = "xl/" + relationship.get_target_uri();
|
||||
archive_.writestr(ws_filename, serializer_.write_worksheet().to_string());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,33 +1,81 @@
|
|||
#include <xlnt/s11n/manifest_serializer.hpp>
|
||||
#include <xlnt/s11n/xml_document.hpp>
|
||||
#include <xlnt/s11n/xml_node.hpp>
|
||||
#include <xlnt/workbook/manifest.hpp>
|
||||
|
||||
#include "detail/constants.hpp"
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
bool manifest_serializer::write_manifest(xml_document &xml)
|
||||
manifest_serializer::manifest_serializer(manifest &m) : manifest_(m)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void manifest_serializer::read_manifest(const xml_document &xml)
|
||||
{
|
||||
const auto root_node = xml.get_child("Types");
|
||||
|
||||
for(const auto child : root_node.get_children())
|
||||
{
|
||||
if(child.get_name() == "Default")
|
||||
{
|
||||
manifest_.add_default_type(child.get_attribute("Extension"), child.get_attribute("ContentType"));
|
||||
}
|
||||
else if(child.get_name() == "Override")
|
||||
{
|
||||
manifest_.add_override_type(child.get_attribute("PartName"), child.get_attribute("ContentType"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xml_document manifest_serializer::write_manifest() const
|
||||
{
|
||||
xml_document xml;
|
||||
|
||||
auto root_node = xml.add_child("Types");
|
||||
xml.add_namespace("", constants::Namespaces.at("content-types"));
|
||||
|
||||
auto root_node = xml.root();
|
||||
root_node.set_name("Types");
|
||||
|
||||
for(const auto &default_type : manifest_.get_default_types())
|
||||
for(const auto default_type : manifest_.get_default_types())
|
||||
{
|
||||
auto type_node = root_node.add_child("Default");
|
||||
type_node.add_attribute("Extension", default_type.get_extension());
|
||||
type_node.add_attribute("ContentType", default_type.get_extension());
|
||||
type_node.add_attribute("ContentType", default_type.get_content_type());
|
||||
}
|
||||
|
||||
for(const auto &override_type : manifest_.get_override_types())
|
||||
for(const auto override_type : manifest_.get_override_types())
|
||||
{
|
||||
auto type_node = root_node.add_child("Override");
|
||||
type_node.add_attribute("PartName", override_type.get_part_name());
|
||||
type_node.add_attribute("ContentType", override_type.get_content_type());
|
||||
}
|
||||
|
||||
return true;
|
||||
return xml;
|
||||
}
|
||||
|
||||
std::string manifest_serializer::determine_document_type() const
|
||||
{
|
||||
if(!manifest_.has_override_type(constants::ArcWorkbook))
|
||||
{
|
||||
return "unsupported";
|
||||
}
|
||||
|
||||
std::string type = manifest_.get_override_type(constants::ArcWorkbook);
|
||||
|
||||
if(type == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml")
|
||||
{
|
||||
return "excel";
|
||||
}
|
||||
else if(type == "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml")
|
||||
{
|
||||
return "powerpoint";
|
||||
}
|
||||
else if(type == "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml")
|
||||
{
|
||||
return "word";
|
||||
}
|
||||
|
||||
return "unsupported";
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -1,17 +1,42 @@
|
|||
#include <xlnt/s11n/relationship_serializer.hpp>
|
||||
|
||||
#include <xlnt/common/relationship.hpp>
|
||||
#include <xlnt/common/zip_file.hpp>
|
||||
#include <xlnt/s11n/xml_document.hpp>
|
||||
#include <xlnt/s11n/xml_node.hpp>
|
||||
|
||||
#include "detail/constants.hpp"
|
||||
|
||||
namespace {
|
||||
|
||||
std::string make_rels_name(const std::string &target)
|
||||
{
|
||||
const char sep = '/';
|
||||
|
||||
if(target.empty() || target.back() == sep)
|
||||
{
|
||||
return target + "_rels/.rels";
|
||||
}
|
||||
|
||||
auto sep_pos = target.find_last_of(sep);
|
||||
auto first_part = target.substr(0, sep_pos + 1);
|
||||
auto last_part = target.substr(sep_pos + 1);
|
||||
|
||||
return first_part + "_rels/" + last_part + ".rels";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
bool relationship_serializer::read_relationships(const xml_document &xml, const std::string &dir, std::vector<relationship> &relationships)
|
||||
std::vector<relationship> relationship_serializer::read_relationships(zip_file &archive, const std::string &target)
|
||||
{
|
||||
auto root_node = xml.root();
|
||||
root_node.set_name("Relationships");
|
||||
xml_document xml;
|
||||
xml.from_string(archive.read(make_rels_name(target)));
|
||||
|
||||
auto root_node = xml.get_child("Relationships");
|
||||
|
||||
std::vector<relationship> relationships;
|
||||
|
||||
for(auto relationship_node : root_node.get_children())
|
||||
{
|
||||
|
@ -27,25 +52,21 @@ bool relationship_serializer::read_relationships(const xml_document &xml, const
|
|||
relationships.push_back(xlnt::relationship(type, id, target));
|
||||
}
|
||||
|
||||
return true;
|
||||
return relationships;
|
||||
}
|
||||
|
||||
bool relationship_serializer::write_relationships(const std::vector<relationship> &relationships, const std::string &dir, xml_document &xml)
|
||||
bool relationship_serializer::write_relationships(const std::vector<relationship> &relationships, const std::string &target, zip_file &archive)
|
||||
{
|
||||
xml.add_namespace("", constants::Namespaces.at("relationships"));
|
||||
xml_document xml;
|
||||
|
||||
auto root_node = xml.root();
|
||||
root_node.set_name("Relationships");
|
||||
auto root_node = xml.add_child("Relationships");
|
||||
|
||||
xml.add_namespace("", constants::Namespaces.at("relationships"));
|
||||
|
||||
for(const auto &relationship : relationships)
|
||||
{
|
||||
auto target = relationship.get_target_uri();
|
||||
|
||||
if (dir != "" && target.substr(0, dir.size()) == dir)
|
||||
{
|
||||
target = target.substr(dir.size());
|
||||
}
|
||||
|
||||
auto relationship_node = root_node.add_child("Relationship");
|
||||
|
||||
relationship_node.add_attribute("Id", relationship.get_id());
|
||||
|
@ -58,6 +79,8 @@ bool relationship_serializer::write_relationships(const std::vector<relationship
|
|||
}
|
||||
}
|
||||
|
||||
archive.writestr(make_rels_name(target), xml.to_string());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,19 +3,48 @@
|
|||
#include <xlnt/s11n/xml_node.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
xml_document shared_strings_serializer::write_shared_strings(const std::vector<std::string> &strings)
|
||||
{
|
||||
xml_document xml;
|
||||
|
||||
auto root_node = xml.add_child("sst");
|
||||
|
||||
xml.add_namespace("", "http://schemas.openxmlformats.org/spreadsheetml/2006/main");
|
||||
|
||||
root_node.add_attribute("uniqueCount", std::to_string(strings.size()));
|
||||
|
||||
for(const auto &string : strings)
|
||||
{
|
||||
root_node.add_child("si").add_child("t").set_text(string);
|
||||
}
|
||||
|
||||
return xml;
|
||||
}
|
||||
|
||||
bool shared_strings_serializer::read_strings(const xml_document &xml, std::vector<std::string> &strings)
|
||||
bool shared_strings_serializer::read_shared_strings(const xml_document &xml, std::vector<std::string> &strings)
|
||||
{
|
||||
strings.clear();
|
||||
|
||||
auto root_node = xml.root();
|
||||
root_node.set_name("sst");
|
||||
auto root_node = xml.get_child("sst");
|
||||
|
||||
auto unique_count = std::stoull(root_node.get_attribute("uniqueCount"));
|
||||
|
||||
for(const auto &si_node : root_node.get_children())
|
||||
{
|
||||
strings.push_back(si_node.get_child("t").get_text());
|
||||
if(si_node.get_name() != "si")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(si_node.has_child("t"))
|
||||
{
|
||||
strings.push_back(si_node.get_child("t").get_text());
|
||||
}
|
||||
else if(si_node.has_child("r"))
|
||||
{
|
||||
strings.push_back(si_node.get_child("r").get_child("t").get_text());
|
||||
}
|
||||
}
|
||||
|
||||
if(unique_count != strings.size())
|
||||
|
|
|
@ -132,11 +132,11 @@ xlnt::border_style border_style_from_string(const std::string &border_style_stri
|
|||
|
||||
namespace xlnt {
|
||||
|
||||
style_serializer::style_serializer(workbook &wb) : wb_(wb)
|
||||
style_serializer::style_serializer(workbook &wb) : workbook_(wb)
|
||||
{
|
||||
}
|
||||
|
||||
protection style_serializer::read_protection(const xml_node &protection_node) const
|
||||
protection style_serializer::read_protection(const xml_node &protection_node)
|
||||
{
|
||||
protection prot;
|
||||
|
||||
|
@ -146,7 +146,7 @@ protection style_serializer::read_protection(const xml_node &protection_node) co
|
|||
return prot;
|
||||
}
|
||||
|
||||
alignment style_serializer::read_alignment(const xml_node &alignment_node) const
|
||||
alignment style_serializer::read_alignment(const xml_node &alignment_node)
|
||||
{
|
||||
alignment align;
|
||||
|
||||
|
@ -219,7 +219,7 @@ alignment style_serializer::read_alignment(const xml_node &alignment_node) const
|
|||
return align;
|
||||
}
|
||||
|
||||
style style_serializer::read_style(const xml_node &style_node) const
|
||||
style style_serializer::read_style(const xml_node &style_node)
|
||||
{
|
||||
style s;
|
||||
|
||||
|
@ -228,9 +228,9 @@ style style_serializer::read_style(const xml_node &style_node) const
|
|||
|
||||
bool builtin_format = true;
|
||||
|
||||
for(auto num_fmt : wb_.get_number_formats())
|
||||
for(auto num_fmt : workbook_.get_number_formats())
|
||||
{
|
||||
if(num_fmt.get_id() == s.get_number_format_id())
|
||||
if(static_cast<std::size_t>(num_fmt.get_id()) == s.get_number_format_id())
|
||||
{
|
||||
s.number_format_ = num_fmt;
|
||||
builtin_format = false;
|
||||
|
@ -245,15 +245,15 @@ style style_serializer::read_style(const xml_node &style_node) const
|
|||
|
||||
s.apply_font(is_true(style_node.get_attribute("applyFont")));
|
||||
s.font_id_ = style_node.has_attribute("fontId") ? std::stoull(style_node.get_attribute("fontId")) : 0;
|
||||
s.font_ = wb_.get_font(s.font_id_);
|
||||
s.font_ = workbook_.get_font(s.font_id_);
|
||||
|
||||
s.apply_fill(is_true(style_node.get_attribute("applyFill")));
|
||||
s.fill_id_ = style_node.has_attribute("fillId") ? std::stoull(style_node.get_attribute("fillId")) : 0;
|
||||
s.fill_ = wb_.get_fill(s.fill_id_);
|
||||
s.fill_ = workbook_.get_fill(s.fill_id_);
|
||||
|
||||
s.apply_border(is_true(style_node.get_attribute("applyBorder")));
|
||||
s.border_id_ = style_node.has_attribute("borderId") ? std::stoull(style_node.get_attribute("borderId")) : 0;
|
||||
s.border_ = wb_.get_border(s.border_id_);
|
||||
s.border_ = workbook_.get_border(s.border_id_);
|
||||
|
||||
s.apply_protection(style_node.has_attribute("protection"));
|
||||
|
||||
|
@ -276,7 +276,7 @@ style style_serializer::read_style(const xml_node &style_node) const
|
|||
|
||||
bool style_serializer::read_stylesheet(const xml_document &xml)
|
||||
{
|
||||
auto stylesheet_node = xml.root();
|
||||
auto stylesheet_node = xml.get_child("styleSheet");
|
||||
|
||||
read_borders(stylesheet_node.get_child("borders"));
|
||||
read_fills(stylesheet_node.get_child("fills"));
|
||||
|
@ -293,7 +293,7 @@ bool style_serializer::read_stylesheet(const xml_document &xml)
|
|||
continue;
|
||||
}
|
||||
|
||||
wb_.add_style(read_style(xf_node));
|
||||
workbook_.add_style(read_style(xf_node));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -320,7 +320,7 @@ bool style_serializer::read_number_formats(const xml_node &number_formats_node)
|
|||
nf.set_format_string(format_string);
|
||||
nf.set_id(std::stoull(num_fmt_node.get_attribute("numFmtId")));
|
||||
|
||||
wb_.add_number_format(nf);
|
||||
workbook_.add_number_format(nf);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -330,13 +330,13 @@ bool style_serializer::read_fonts(const xml_node &fonts_node)
|
|||
{
|
||||
for(auto font_node : fonts_node.get_children())
|
||||
{
|
||||
wb_.add_font(read_font(font_node));
|
||||
workbook_.add_font(read_font(font_node));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
font style_serializer::read_font(const xlnt::xml_node &font_node) const
|
||||
font style_serializer::read_font(const xlnt::xml_node &font_node)
|
||||
{
|
||||
font new_font;
|
||||
|
||||
|
@ -390,7 +390,7 @@ bool style_serializer::read_colors(const xml_node &colors_node)
|
|||
|
||||
for(const auto &indexed_color : indexed_colors)
|
||||
{
|
||||
wb_.add_color(indexed_color);
|
||||
workbook_.add_color(indexed_color);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -401,13 +401,13 @@ bool style_serializer::read_fills(const xml_node &fills_node)
|
|||
{
|
||||
for(auto fill_node : fills_node.get_children())
|
||||
{
|
||||
wb_.add_fill(read_fill(fill_node));
|
||||
workbook_.add_fill(read_fill(fill_node));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
fill style_serializer::read_fill(const xml_node &fill_node) const
|
||||
fill style_serializer::read_fill(const xml_node &fill_node)
|
||||
{
|
||||
fill new_fill;
|
||||
|
||||
|
@ -432,7 +432,7 @@ fill style_serializer::read_fill(const xml_node &fill_node) const
|
|||
return new_fill;
|
||||
}
|
||||
|
||||
side style_serializer::read_side(const xml_node &side_node) const
|
||||
side style_serializer::read_side(const xml_node &side_node)
|
||||
{
|
||||
side new_side;
|
||||
|
||||
|
@ -453,13 +453,13 @@ bool style_serializer::read_borders(const xml_node &borders_node)
|
|||
{
|
||||
for(auto border_node : borders_node.get_children())
|
||||
{
|
||||
wb_.add_border(read_border(border_node));
|
||||
workbook_.add_border(read_border(border_node));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
border style_serializer::read_border(const xml_node &border_node) const
|
||||
border style_serializer::read_border(const xml_node &border_node)
|
||||
{
|
||||
border new_border;
|
||||
|
||||
|
@ -520,21 +520,56 @@ border style_serializer::read_border(const xml_node &border_node) const
|
|||
return new_border;
|
||||
}
|
||||
|
||||
bool style_serializer::write_stylesheet(xlnt::xml_document &xml) const
|
||||
std::vector<color> style_serializer::read_indexed_colors(const xml_node &indexed_colors_node)
|
||||
{
|
||||
std::vector<color> colors;
|
||||
|
||||
for(auto color_node : indexed_colors_node.get_children())
|
||||
{
|
||||
colors.push_back(read_color(color_node));
|
||||
}
|
||||
|
||||
return colors;
|
||||
}
|
||||
|
||||
color style_serializer::read_color(const xml_node &color_node)
|
||||
{
|
||||
if(color_node.has_attribute("rgb"))
|
||||
{
|
||||
return color(color::type::rgb, color_node.get_attribute("rgb"));
|
||||
}
|
||||
else if(color_node.has_attribute("theme"))
|
||||
{
|
||||
return color(color::type::theme, std::stoull(color_node.get_attribute("theme")));
|
||||
}
|
||||
else if(color_node.has_attribute("indexed"))
|
||||
{
|
||||
return color(color::type::indexed, std::stoull(color_node.get_attribute("indexed")));
|
||||
}
|
||||
else if(color_node.has_attribute("auto"))
|
||||
{
|
||||
return color(color::type::auto_, std::stoull(color_node.get_attribute("auto")));
|
||||
}
|
||||
|
||||
throw std::runtime_error("bad color");
|
||||
return color();
|
||||
}
|
||||
|
||||
xml_document style_serializer::write_stylesheet() const
|
||||
{
|
||||
xml_document xml;
|
||||
|
||||
auto style_sheet_node = xml.add_child("styleSheet");
|
||||
xml.add_namespace("", "http://schemas.openxmlformats.org/spreadsheetml/2006/main");
|
||||
xml.add_namespace("mc", "http://schemas.openxmlformats.org/markup-compatibility/2006");
|
||||
style_sheet_node.add_attribute("mc:Ignorable", "x14ac");
|
||||
xml.add_namespace("x14ac", "http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac");
|
||||
|
||||
auto &style_sheet_node = xml.root();
|
||||
style_sheet_node.set_name("styleSheet");
|
||||
style_sheet_node.add_attribute("mc:Ignorable", "x14ac");
|
||||
|
||||
auto num_fmts_node = style_sheet_node.add_child("numFmts");
|
||||
auto num_fmts = wb_.get_number_formats();
|
||||
auto num_fmts = workbook_.get_number_formats();
|
||||
num_fmts_node.add_attribute("count", std::to_string(num_fmts.size()));
|
||||
|
||||
for(auto &num_fmt : num_fmts)
|
||||
for(const auto &num_fmt : num_fmts)
|
||||
{
|
||||
auto num_fmt_node = num_fmts_node.add_child("numFmt");
|
||||
num_fmt_node.add_attribute("numFmtId", std::to_string(num_fmt.get_id()));
|
||||
|
@ -542,7 +577,7 @@ bool style_serializer::write_stylesheet(xlnt::xml_document &xml) const
|
|||
}
|
||||
|
||||
auto fonts_node = style_sheet_node.add_child("fonts");
|
||||
auto fonts = wb_.get_fonts();
|
||||
auto fonts = workbook_.get_fonts();
|
||||
|
||||
if(fonts.empty())
|
||||
{
|
||||
|
@ -620,7 +655,7 @@ bool style_serializer::write_stylesheet(xlnt::xml_document &xml) const
|
|||
}
|
||||
|
||||
auto fills_node = style_sheet_node.add_child("fills");
|
||||
const auto &fills = wb_.get_fills();
|
||||
const auto &fills = workbook_.get_fills();
|
||||
fills_node.add_attribute("count", std::to_string(fills.size()));
|
||||
|
||||
for(auto &fill_ : fills)
|
||||
|
@ -635,7 +670,7 @@ bool style_serializer::write_stylesheet(xlnt::xml_document &xml) const
|
|||
|
||||
if(fill_.has_foreground_color())
|
||||
{
|
||||
auto &fg_color_node = pattern_fill_node.add_child("fgColor");
|
||||
auto fg_color_node = pattern_fill_node.add_child("fgColor");
|
||||
|
||||
switch(fill_.get_foreground_color().get_type())
|
||||
{
|
||||
|
@ -689,7 +724,7 @@ bool style_serializer::write_stylesheet(xlnt::xml_document &xml) const
|
|||
}
|
||||
|
||||
auto borders_node = style_sheet_node.add_child("borders");
|
||||
const auto &borders = wb_.get_borders();
|
||||
const auto &borders = workbook_.get_borders();
|
||||
borders_node.add_attribute("count", std::to_string(borders.size()));
|
||||
|
||||
for(const auto &border_ : borders)
|
||||
|
@ -764,17 +799,17 @@ bool style_serializer::write_stylesheet(xlnt::xml_document &xml) const
|
|||
}
|
||||
}
|
||||
|
||||
auto &cell_style_xfs_node = style_sheet_node.add_child("cellStyleXfs");
|
||||
auto cell_style_xfs_node = style_sheet_node.add_child("cellStyleXfs");
|
||||
cell_style_xfs_node.add_attribute("count", "1");
|
||||
|
||||
auto &style_xf_node = cell_style_xfs_node.add_child("xf");
|
||||
auto style_xf_node = cell_style_xfs_node.add_child("xf");
|
||||
style_xf_node.add_attribute("numFmtId", "0");
|
||||
style_xf_node.add_attribute("fontId", "0");
|
||||
style_xf_node.add_attribute("fillId", "0");
|
||||
style_xf_node.add_attribute("borderId", "0");
|
||||
|
||||
auto cell_xfs_node = style_sheet_node.add_child("cellXfs");
|
||||
const auto &styles = wb_.get_styles();
|
||||
const auto &styles = workbook_.get_styles();
|
||||
cell_xfs_node.add_attribute("count", std::to_string(styles.size()));
|
||||
|
||||
for(auto &style : styles)
|
||||
|
@ -876,7 +911,7 @@ bool style_serializer::write_stylesheet(xlnt::xml_document &xml) const
|
|||
auto colors_node = style_sheet_node.add_child("colors");
|
||||
auto indexed_colors_node = colors_node.add_child("indexedColors");
|
||||
|
||||
for(auto &c : wb_.get_colors())
|
||||
for(auto &c : workbook_.get_colors())
|
||||
{
|
||||
indexed_colors_node.add_child("rgbColor").add_attribute("rgb", c.get_rgb_string());
|
||||
}
|
||||
|
@ -887,16 +922,16 @@ bool style_serializer::write_stylesheet(xlnt::xml_document &xml) const
|
|||
ext_node.add_attribute("xmlns:x14", "http://schemas.microsoft.com/office/spreadsheetml/2009/9/main");
|
||||
ext_node.add_child("x14:slicerStyles").add_attribute("defaultSlicerStyle", "SlicerStyleLight1");
|
||||
|
||||
return true;
|
||||
return xml;
|
||||
}
|
||||
|
||||
bool style_serializer::write_number_formats(xml_node &number_formats_node) const
|
||||
bool style_serializer::write_number_formats(xml_node number_formats_node) const
|
||||
{
|
||||
number_formats_node.add_attribute("count", std::to_string(wb_.get_number_formats().size()));
|
||||
number_formats_node.add_attribute("count", std::to_string(workbook_.get_number_formats().size()));
|
||||
|
||||
for(const auto &num_fmt : wb_.get_number_formats())
|
||||
for(const auto &num_fmt : workbook_.get_number_formats())
|
||||
{
|
||||
auto &num_fmt_node = number_formats_node.add_child("numFmt");
|
||||
auto num_fmt_node = number_formats_node.add_child("numFmt");
|
||||
num_fmt_node.add_attribute("numFmtId", std::to_string(num_fmt.get_id()));
|
||||
num_fmt_node.add_attribute("formatCode", num_fmt.get_format_string());
|
||||
}
|
||||
|
|
|
@ -7,17 +7,16 @@
|
|||
namespace xlnt {
|
||||
|
||||
//I have no idea what this stuff is. I hope it was worth it.
|
||||
xml_document theme_serializer::write_theme(const theme &theme_)
|
||||
xml_document theme_serializer::write_theme(const theme &) const
|
||||
{
|
||||
xml_document xml;
|
||||
|
||||
auto theme_node = xml.add_child("a:theme");
|
||||
xml.add_namespace("a", constants::Namespaces.at("drawingml"));
|
||||
|
||||
auto &theme_node = xml.root();
|
||||
theme_node.set_name("a:theme");
|
||||
theme_node.add_attribute("name", "Office Theme");
|
||||
auto &theme_elements_node = theme_node.add_child("a:themeElements");
|
||||
auto &clr_scheme_node = theme_elements_node.add_child("a:clrScheme");
|
||||
|
||||
auto theme_elements_node = theme_node.add_child("a:themeElements");
|
||||
auto clr_scheme_node = theme_elements_node.add_child("a:clrScheme");
|
||||
clr_scheme_node.add_attribute("name", "Office");
|
||||
|
||||
struct scheme_element
|
||||
|
@ -112,19 +111,19 @@ xml_document theme_serializer::write_theme(const theme &theme_)
|
|||
{
|
||||
if(scheme.typeface)
|
||||
{
|
||||
auto &major_font_node = major_fonts_node.add_child(scheme.script);
|
||||
auto major_font_node = major_fonts_node.add_child(scheme.script);
|
||||
major_font_node.add_attribute("typeface", scheme.major);
|
||||
|
||||
auto &minor_font_node = minor_fonts_node.add_child(scheme.script);
|
||||
auto minor_font_node = minor_fonts_node.add_child(scheme.script);
|
||||
minor_font_node.add_attribute("typeface", scheme.minor);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto &major_font_node = major_fonts_node.add_child("a:font");
|
||||
auto major_font_node = major_fonts_node.add_child("a:font");
|
||||
major_font_node.add_attribute("script", scheme.script);
|
||||
major_font_node.add_attribute("typeface", scheme.major);
|
||||
|
||||
auto &minor_font_node = minor_fonts_node.add_child("a:font");
|
||||
auto minor_font_node = minor_fonts_node.add_child("a:font");
|
||||
minor_font_node.add_attribute("script", scheme.script);
|
||||
minor_font_node.add_attribute("typeface", scheme.minor);
|
||||
}
|
||||
|
@ -141,7 +140,7 @@ xml_document theme_serializer::write_theme(const theme &theme_)
|
|||
|
||||
auto grad_fill_list = grad_fill_node.add_child("a:gsLst");
|
||||
auto gs_node = grad_fill_list.add_child("a:gs");
|
||||
gs_node.add_attribute("pos", 0);
|
||||
gs_node.add_attribute("pos", "0");
|
||||
auto scheme_color_node = gs_node.add_child("a:schemeClr");
|
||||
scheme_color_node.add_attribute("val", "phClr");
|
||||
scheme_color_node.add_child("a:tint").add_attribute("val", "50000");
|
||||
|
|
|
@ -50,10 +50,14 @@ std::string datetime_to_w3cdtf(const xlnt::datetime &dt)
|
|||
} // namespace
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
/*
|
||||
std::vector<std::pair<std::string, std::string>> workbook_serializer::read_sheets(zip_file &archive)
|
||||
|
||||
workbook_serializer::workbook_serializer(workbook &wb) : workbook_(wb)
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<workbook_serializer::string_pair> workbook_serializer::read_sheets()
|
||||
{
|
||||
/*
|
||||
std::string ns;
|
||||
|
||||
for(auto child : doc.children())
|
||||
|
@ -72,9 +76,9 @@ std::vector<std::pair<std::string, std::string>> workbook_serializer::read_sheet
|
|||
|
||||
auto root_node = doc.get_child(with_ns("workbook"));
|
||||
auto sheets_node = root_node.get_child(with_ns("sheets"));
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> sheets;
|
||||
|
||||
*/
|
||||
std::vector<string_pair> sheets;
|
||||
/*
|
||||
// store temp because pugixml iteration uses the internal char array multiple times
|
||||
auto sheet_element_name = with_ns("sheet");
|
||||
|
||||
|
@ -84,15 +88,14 @@ std::vector<std::pair<std::string, std::string>> workbook_serializer::read_sheet
|
|||
std::string name = sheet_node.attribute("name").as_string();
|
||||
sheets.push_back(std::make_pair(id, name));
|
||||
}
|
||||
|
||||
*/
|
||||
return sheets;
|
||||
}
|
||||
*/
|
||||
|
||||
void workbook_serializer::read_properties_core(const xml_document &xml)
|
||||
{
|
||||
auto &props = wb_.get_properties();
|
||||
auto root_node = xml.root();
|
||||
auto &props = workbook_.get_properties();
|
||||
auto root_node = xml.get_child("dc:coreProperties");
|
||||
|
||||
props.excel_base_date = calendar::windows_1900;
|
||||
|
||||
|
@ -116,44 +119,19 @@ void workbook_serializer::read_properties_core(const xml_document &xml)
|
|||
}
|
||||
}
|
||||
|
||||
std::string workbook_serializer::determine_document_type(const manifest &manifest)
|
||||
{
|
||||
if(!manifest.has_override_type(constants::ArcWorkbook))
|
||||
{
|
||||
return "unsupported";
|
||||
}
|
||||
|
||||
std::string type = manifest.get_override_type(constants::ArcWorkbook);
|
||||
|
||||
if(type == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml")
|
||||
{
|
||||
return "excel";
|
||||
}
|
||||
else if(type == "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml")
|
||||
{
|
||||
return "powerpoint";
|
||||
}
|
||||
else if(type == "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml")
|
||||
{
|
||||
return "word";
|
||||
}
|
||||
|
||||
return "unsupported";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a list of worksheets.
|
||||
/// content types has a list of paths but no titles
|
||||
/// workbook has a list of titles and relIds but no paths
|
||||
/// workbook_rels has a list of relIds and paths but no titles
|
||||
/// </summary>
|
||||
std::vector<string_pair> workbook_serializer::detect_worksheets()
|
||||
std::vector<workbook_serializer::string_pair> workbook_serializer::detect_worksheets()
|
||||
{
|
||||
static const std::string ValidWorksheet = "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml";
|
||||
|
||||
std::vector<std::string> valid_sheets;
|
||||
|
||||
for(const auto &content_type : wb_.get_manifest().get_override_types())
|
||||
for(const auto &content_type : workbook_.get_manifest().get_override_types())
|
||||
{
|
||||
if(content_type.get_content_type() == ValidWorksheet)
|
||||
{
|
||||
|
@ -161,7 +139,7 @@ std::vector<string_pair> workbook_serializer::detect_worksheets()
|
|||
}
|
||||
}
|
||||
|
||||
auto &workbook_relationships = wb_.get_relationships();
|
||||
auto &workbook_relationships = workbook_.get_relationships();
|
||||
std::vector<std::pair<std::string, std::string>> result;
|
||||
|
||||
for(const auto &ws : read_sheets())
|
||||
|
@ -180,19 +158,18 @@ std::vector<string_pair> workbook_serializer::detect_worksheets()
|
|||
|
||||
xml_document workbook_serializer::write_properties_core() const
|
||||
{
|
||||
auto &props = wb_.get_properties();
|
||||
auto &props = workbook_.get_properties();
|
||||
|
||||
xml_document xml;
|
||||
|
||||
auto root_node = xml.add_child("cp:coreProperties");
|
||||
|
||||
xml.add_namespace("cp", "http://schemas.openxmlformats.org/package/2006/metadata/core-properties");
|
||||
xml.add_namespace("dc", "http://purl.org/dc/elements/1.1/");
|
||||
xml.add_namespace("dcmitype", "http://purl.org/dc/dcmitype/");
|
||||
xml.add_namespace("dcterms", "http://purl.org/dc/terms/");
|
||||
xml.add_namespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
|
||||
|
||||
auto &root_node = xml.root();
|
||||
root_node.set_name("cp:coreProperties");
|
||||
|
||||
root_node.add_child("dc:creator").set_text(props.creator);
|
||||
root_node.add_child("cp:lastModifiedBy").set_text(props.last_modified_by);
|
||||
root_node.add_child("dcterms:created").set_text(datetime_to_w3cdtf(props.created));
|
||||
|
@ -212,11 +189,10 @@ xml_document workbook_serializer::write_properties_app() const
|
|||
{
|
||||
xml_document xml;
|
||||
|
||||
xml.add_namespace("xmlns", "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties");
|
||||
xml.add_namespace("xmlns:vt", "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes");
|
||||
auto root_node = xml.add_child("Properties");
|
||||
|
||||
auto &root_node = xml.root();
|
||||
root_node.set_name("Properties");
|
||||
xml.add_namespace("", "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties");
|
||||
xml.add_namespace("vt", "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes");
|
||||
|
||||
root_node.add_child("Application").set_text("Microsoft Excel");
|
||||
root_node.add_child("DocSecurity").set_text("0");
|
||||
|
@ -232,14 +208,14 @@ xml_document workbook_serializer::write_properties_app() const
|
|||
heading_pairs_vector_node.add_attribute("baseType", "variant");
|
||||
heading_pairs_vector_node.add_attribute("size", "2");
|
||||
heading_pairs_vector_node.add_child("vt:variant").add_child("vt:lpstr").set_text("Worksheets");
|
||||
heading_pairs_vector_node.add_child("vt:variant").add_child("vt:i4").set_text(std::to_string(wb_.get_sheet_names().size()));
|
||||
heading_pairs_vector_node.add_child("vt:variant").add_child("vt:i4").set_text(std::to_string(workbook_.get_sheet_names().size()));
|
||||
|
||||
auto titles_of_parts_node = root_node.add_child("TitlesOfParts");
|
||||
auto titles_of_parts_vector_node = titles_of_parts_node.add_child("vt:vector");
|
||||
titles_of_parts_vector_node.add_attribute("baseType", "lpstr");
|
||||
titles_of_parts_vector_node.add_attribute("size", std::to_string(wb_.get_sheet_names().size()));
|
||||
titles_of_parts_vector_node.add_attribute("size", std::to_string(workbook_.get_sheet_names().size()));
|
||||
|
||||
for(auto ws : wb_)
|
||||
for(auto ws : workbook_)
|
||||
{
|
||||
titles_of_parts_vector_node.add_child("vt:lpstr").set_text(ws.get_title());
|
||||
}
|
||||
|
@ -251,7 +227,7 @@ xml_document workbook_serializer::write_workbook() const
|
|||
{
|
||||
std::size_t num_visible = 0;
|
||||
|
||||
for(auto ws : wb_)
|
||||
for(auto ws : workbook_)
|
||||
{
|
||||
if(ws.get_page_setup().get_sheet_state() == xlnt::page_setup::sheet_state::visible)
|
||||
{
|
||||
|
@ -266,22 +242,21 @@ xml_document workbook_serializer::write_workbook() const
|
|||
|
||||
xml_document xml;
|
||||
|
||||
xml.add_namespace("xmlns", "http://schemas.openxmlformats.org/spreadsheetml/2006/main");
|
||||
xml.add_namespace("xmlns:r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships");
|
||||
auto root_node = xml.add_child("workbook");
|
||||
|
||||
auto &root_node = xml.root();
|
||||
root_node.set_name("workbook");
|
||||
xml.add_namespace("", "http://schemas.openxmlformats.org/spreadsheetml/2006/main");
|
||||
xml.add_namespace("r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships");
|
||||
|
||||
auto &file_version_node = root_node.add_child("fileVersion");
|
||||
auto file_version_node = root_node.add_child("fileVersion");
|
||||
file_version_node.add_attribute("appName", "xl");
|
||||
file_version_node.add_attribute("lastEdited", "4");
|
||||
file_version_node.add_attribute("lowestEdited", "4");
|
||||
file_version_node.add_attribute("rupBuild", "4505");
|
||||
|
||||
auto &workbook_pr_node = root_node.add_child("workbookPr");
|
||||
auto workbook_pr_node = root_node.add_child("workbookPr");
|
||||
workbook_pr_node.add_attribute("codeName", "ThisWorkbook");
|
||||
workbook_pr_node.add_attribute("defaultThemeVersion", "124226");
|
||||
workbook_pr_node.add_attribute("date1904", wb_.get_properties().excel_base_date == calendar::mac_1904 ? "1" : "0");
|
||||
workbook_pr_node.add_attribute("date1904", workbook_.get_properties().excel_base_date == calendar::mac_1904 ? "1" : "0");
|
||||
|
||||
auto book_views_node = root_node.add_child("bookViews");
|
||||
auto workbook_view_node = book_views_node.add_child("workbookView");
|
||||
|
@ -298,10 +273,11 @@ xml_document workbook_serializer::write_workbook() const
|
|||
auto sheets_node = root_node.add_child("sheets");
|
||||
auto defined_names_node = root_node.add_child("definedNames");
|
||||
|
||||
for(auto relationship : wb_.get_relationships())
|
||||
for(const auto &relationship : workbook_.get_relationships())
|
||||
{
|
||||
if(relationship.get_type() == relationship::type::worksheet)
|
||||
{
|
||||
//TODO: this is ugly
|
||||
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('/'));
|
||||
|
@ -312,16 +288,16 @@ xml_document workbook_serializer::write_workbook() const
|
|||
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);
|
||||
auto ws = workbook_.get_sheet_by_index(sheet_index);
|
||||
|
||||
auto sheet_node = sheets_node.add_child("sheet");
|
||||
sheet_node.add_attribute("name", ws.get_title());
|
||||
sheet_node.add_attribute("r:id", relationship.get_id());
|
||||
sheet_node.add_attribute("sheetId", std::to_string(sheet_index + 1));
|
||||
sheet_node.add_attribute("r:id", relationship.get_id());
|
||||
|
||||
if(ws.has_auto_filter())
|
||||
{
|
||||
auto &defined_name_node = defined_names_node.add_child("definedName");
|
||||
auto defined_name_node = defined_names_node.add_child("definedName");
|
||||
defined_name_node.add_attribute("name", "_xlnm._FilterDatabase");
|
||||
defined_name_node.add_attribute("hidden", "1");
|
||||
defined_name_node.add_attribute("localSheetId", "0");
|
||||
|
@ -339,14 +315,16 @@ xml_document workbook_serializer::write_workbook() const
|
|||
return xml;
|
||||
}
|
||||
|
||||
bool workbook_serializer::write_named_ranges(xlnt::xml_node &named_ranges_node)
|
||||
xml_node workbook_serializer::write_named_ranges() const
|
||||
{
|
||||
for(auto &named_range : wb_.get_named_ranges())
|
||||
xlnt::xml_node named_ranges_node;
|
||||
|
||||
for(auto &named_range : workbook_.get_named_ranges())
|
||||
{
|
||||
named_ranges_node.add_child(named_range.get_name());
|
||||
}
|
||||
|
||||
return true;
|
||||
return named_ranges_node;
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -21,10 +21,14 @@ bool is_integral(long double d)
|
|||
} // namepsace
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
bool worksheet_serializer::read_worksheet(const xml_document &xml, const std::vector<std::string> &string_table, const relationship &rel)
|
||||
|
||||
worksheet_serializer::worksheet_serializer(worksheet sheet) : sheet_(sheet)
|
||||
{
|
||||
auto &root_node = xml.root();
|
||||
}
|
||||
|
||||
bool worksheet_serializer::read_worksheet(const xml_document &xml)
|
||||
{
|
||||
auto &root_node = xml.get_child("worksheet");
|
||||
|
||||
auto &dimension_node = root_node.get_child("dimension");
|
||||
std::string dimension = dimension_node.get_attribute("ref");
|
||||
|
@ -53,6 +57,8 @@ bool worksheet_serializer::read_worksheet(const xml_document &xml, const std::ve
|
|||
}
|
||||
}
|
||||
|
||||
auto &shared_strings = sheet_.get_parent().get_shared_strings();
|
||||
|
||||
for(auto row_node : sheet_data_node.get_children())
|
||||
{
|
||||
if(row_node.get_name() != "row")
|
||||
|
@ -62,7 +68,7 @@ bool worksheet_serializer::read_worksheet(const xml_document &xml, const std::ve
|
|||
|
||||
auto row_index = static_cast<row_t>(std::stoull(row_node.get_attribute("r")));
|
||||
|
||||
if(row_node.get_attribute("ht") != nullptr)
|
||||
if(row_node.has_attribute("ht"))
|
||||
{
|
||||
sheet_.get_row_properties(row_index).height = std::stold(row_node.get_attribute("ht"));
|
||||
}
|
||||
|
@ -111,10 +117,10 @@ bool worksheet_serializer::read_worksheet(const xml_document &xml, const std::ve
|
|||
bool has_value = cell_node.has_child("v");
|
||||
std::string value_string = has_value ? cell_node.get_child("v").get_text() : "";
|
||||
|
||||
bool has_type = cell_node.get_attribute("t") != nullptr;
|
||||
bool has_type = cell_node.has_attribute("t");
|
||||
std::string type = has_type ? cell_node.get_attribute("t") : "";
|
||||
|
||||
bool has_style = cell_node.get_attribute("s") != nullptr;
|
||||
bool has_style = cell_node.has_attribute("s");
|
||||
int style_id = has_style ? std::stoull(cell_node.get_attribute("s")) : 0;
|
||||
|
||||
bool has_formula = cell_node.has_child("f");
|
||||
|
@ -136,7 +142,7 @@ bool worksheet_serializer::read_worksheet(const xml_document &xml, const std::ve
|
|||
else if(has_type && type == "s" && !has_formula) // shared string
|
||||
{
|
||||
auto shared_string_index = std::stoull(value_string);
|
||||
auto shared_string = string_table.at(shared_string_index);
|
||||
auto shared_string = shared_strings.at(shared_string_index);
|
||||
cell.set_value(shared_string);
|
||||
}
|
||||
else if(has_type && type == "b") // boolean
|
||||
|
@ -205,34 +211,35 @@ bool worksheet_serializer::read_worksheet(const xml_document &xml, const std::ve
|
|||
return true;
|
||||
}
|
||||
|
||||
bool worksheet_serializer::write_worksheet(const std::vector<std::string> &string_table, xml_document &xml)
|
||||
xml_document worksheet_serializer::write_worksheet() const
|
||||
{
|
||||
sheet_.get_cell("A1");
|
||||
|
||||
xml_document xml;
|
||||
|
||||
auto root_node = xml.add_child("worksheet");
|
||||
|
||||
xml.add_namespace("", constants::Namespaces.at("spreadsheetml"));
|
||||
xml.add_namespace("r", constants::Namespaces.at("r"));
|
||||
|
||||
auto &root_node = xml.root();
|
||||
root_node.set_name("worksheet");
|
||||
|
||||
auto &sheet_pr_node = root_node.add_child("sheetPr");
|
||||
auto sheet_pr_node = root_node.add_child("sheetPr");
|
||||
|
||||
if(!sheet_.get_page_setup().is_default())
|
||||
{
|
||||
auto &page_set_up_pr_node = sheet_pr_node.add_child("pageSetUpPr");
|
||||
auto page_set_up_pr_node = sheet_pr_node.add_child("pageSetUpPr");
|
||||
page_set_up_pr_node.add_attribute("fitToPage", sheet_.get_page_setup().fit_to_page() ? "1" : "0");
|
||||
}
|
||||
|
||||
auto &outline_pr_node = sheet_pr_node.add_child("outlinePr");
|
||||
auto outline_pr_node = sheet_pr_node.add_child("outlinePr");
|
||||
|
||||
outline_pr_node.add_attribute("summaryBelow", "1");
|
||||
outline_pr_node.add_attribute("summaryRight", "1");
|
||||
|
||||
auto &dimension_node = root_node.add_child("dimension");
|
||||
auto dimension_node = root_node.add_child("dimension");
|
||||
dimension_node.add_attribute("ref", sheet_.calculate_dimension().to_string());
|
||||
|
||||
auto &sheet_views_node = root_node.add_child("sheetViews");
|
||||
auto &sheet_view_node = sheet_views_node.add_child("sheetView");
|
||||
auto sheet_views_node = root_node.add_child("sheetViews");
|
||||
auto sheet_view_node = sheet_views_node.add_child("sheetView");
|
||||
sheet_view_node.add_attribute("workbookViewId", "0");
|
||||
|
||||
std::string active_pane = "bottomRight";
|
||||
|
@ -325,6 +332,7 @@ bool worksheet_serializer::write_worksheet(const std::vector<std::string> &strin
|
|||
std::unordered_map<std::string, std::string> hyperlink_references;
|
||||
|
||||
auto sheet_data_node = root_node.add_child("sheetData");
|
||||
const auto &shared_strings = sheet_.get_parent().get_shared_strings();
|
||||
|
||||
for(auto row : sheet_.rows())
|
||||
{
|
||||
|
@ -395,9 +403,9 @@ bool worksheet_serializer::write_worksheet(const std::vector<std::string> &strin
|
|||
|
||||
int match_index = -1;
|
||||
|
||||
for(std::size_t i = 0; i < string_table.size(); i++)
|
||||
for(std::size_t i = 0; i < shared_strings.size(); i++)
|
||||
{
|
||||
if(string_table[i] == cell.get_value<std::string>())
|
||||
if(shared_strings[i] == cell.get_value<std::string>())
|
||||
{
|
||||
match_index = static_cast<int>(i);
|
||||
break;
|
||||
|
@ -545,7 +553,7 @@ bool worksheet_serializer::write_worksheet(const std::vector<std::string> &strin
|
|||
odd_footer_node.set_text(footer_text);
|
||||
}
|
||||
|
||||
return true;
|
||||
return xml;
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -1,25 +1,78 @@
|
|||
#include <xlnt/s11n/xml_document.hpp>
|
||||
#include <xlnt/s11n/xml_node.hpp>
|
||||
#include <xlnt/s11n/xml_serializer.hpp>
|
||||
|
||||
#include <detail/xml_document_impl.hpp>
|
||||
#include <detail/xml_node_impl.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
xml_document::xml_document() : d_(new detail::xml_document_impl())
|
||||
{
|
||||
}
|
||||
|
||||
xml_document::xml_document(const xml_document &other) : xml_document()
|
||||
{
|
||||
d_->doc.append_copy(other.d_->doc.root());
|
||||
}
|
||||
|
||||
xml_document::~xml_document()
|
||||
{
|
||||
}
|
||||
|
||||
void xml_document::set_encoding(const std::string &encoding)
|
||||
{
|
||||
|
||||
d_->encoding = encoding;
|
||||
}
|
||||
|
||||
void xml_document::add_namespace(const std::string &id, const std::string &uri)
|
||||
{
|
||||
d_->doc.first_child().append_attribute((id.empty() ? "xmlns" : "xmlns:" + id).c_str()).set_value(uri.c_str());
|
||||
}
|
||||
|
||||
xml_node xml_document::add_child(const xml_node &child)
|
||||
{
|
||||
auto child_node = d_->doc.root().append_copy(child.d_->node);
|
||||
return xml_node(detail::xml_node_impl(child_node));
|
||||
}
|
||||
|
||||
xml_node xml_document::add_child(const std::string &child_name)
|
||||
{
|
||||
auto child = d_->doc.root().append_child(child_name.c_str());
|
||||
return xml_node(detail::xml_node_impl(child));
|
||||
}
|
||||
|
||||
xml_node xml_document::get_root()
|
||||
{
|
||||
return xml_node(detail::xml_node_impl(d_->doc.root()));
|
||||
}
|
||||
|
||||
const xml_node xml_document::get_root() const
|
||||
{
|
||||
return xml_node(detail::xml_node_impl(d_->doc.root()));
|
||||
}
|
||||
|
||||
std::string xml_document::to_string() const
|
||||
{
|
||||
return xml_serializer::serialize(*this);
|
||||
}
|
||||
|
||||
xml_document &xml_document::from_string(const std::string &xml_string)
|
||||
{
|
||||
auto doc = xml_serializer::deserialize(xml_string);
|
||||
std::swap(doc.d_, d_);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
xml_node &xml_document::root()
|
||||
xml_node xml_document::get_child(const std::string &child_name)
|
||||
{
|
||||
return root_;
|
||||
return xml_node(detail::xml_node_impl(d_->doc.child(child_name.c_str())));
|
||||
}
|
||||
|
||||
const xml_node &xml_document::root() const
|
||||
const xml_node xml_document::get_child(const std::string &child_name) const
|
||||
{
|
||||
return root_;
|
||||
return xml_node(detail::xml_node_impl(d_->doc.child(child_name.c_str())));
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
|
@ -1,120 +1,139 @@
|
|||
#include <xlnt/s11n/xml_node.hpp>
|
||||
#include <xlnt/s11n/xml_serializer.hpp>
|
||||
|
||||
#include <detail/xml_node_impl.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
xml_node::xml_node()
|
||||
xml_node::xml_node() : d_(new detail::xml_node_impl)
|
||||
{
|
||||
}
|
||||
|
||||
xml_node::xml_node(const std::string &name)
|
||||
xml_node::xml_node(const detail::xml_node_impl &d) : xml_node()
|
||||
{
|
||||
set_name(name);
|
||||
d_->node = d.node;
|
||||
}
|
||||
|
||||
xml_node::~xml_node()
|
||||
{
|
||||
}
|
||||
|
||||
xml_node::xml_node(const xml_node &other) : xml_node()
|
||||
{
|
||||
d_->node = other.d_->node;
|
||||
}
|
||||
|
||||
xml_node &xml_node::operator=(const xlnt::xml_node &other)
|
||||
{
|
||||
d_->node = other.d_->node;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::string xml_node::get_name() const
|
||||
{
|
||||
return name_;
|
||||
return d_->node.name();
|
||||
}
|
||||
|
||||
void xml_node::set_name(const std::string &name)
|
||||
{
|
||||
name_ = name;
|
||||
d_->node.set_name(name.c_str());
|
||||
}
|
||||
|
||||
bool xml_node::has_text() const
|
||||
{
|
||||
return has_text_;
|
||||
return d_->node.text() != nullptr;
|
||||
}
|
||||
|
||||
std::string xml_node::get_text() const
|
||||
{
|
||||
return text_;
|
||||
return d_->node.text().as_string();
|
||||
}
|
||||
|
||||
void xml_node::set_text(const std::string &text)
|
||||
{
|
||||
text_ = text;
|
||||
has_text_ = true;
|
||||
d_->node.text().set(text.c_str());
|
||||
}
|
||||
|
||||
const std::vector<xml_node> &xml_node::get_children() const
|
||||
const std::vector<xml_node> xml_node::get_children() const
|
||||
{
|
||||
return children_;
|
||||
}
|
||||
|
||||
xml_node &xml_node::add_child(const xml_node &child)
|
||||
{
|
||||
has_text_ = false;
|
||||
text_.clear();
|
||||
std::vector<xml_node> children;
|
||||
|
||||
children_.push_back(child);
|
||||
return children_.back();
|
||||
for(auto child : d_->node.children())
|
||||
{
|
||||
children.push_back(xml_node(detail::xml_node_impl(child)));
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
xml_node &xml_node::add_child(const std::string &child_name)
|
||||
xml_node xml_node::add_child(const xml_node &child)
|
||||
{
|
||||
return add_child(xml_node(child_name));
|
||||
auto child_node = xml_node(detail::xml_node_impl(d_->node.append_child(child.get_name().c_str())));
|
||||
|
||||
for(auto attr : child.get_attributes())
|
||||
{
|
||||
child_node.add_attribute(attr.first, attr.second);
|
||||
}
|
||||
|
||||
for(auto child_child : child.get_children())
|
||||
{
|
||||
child_node.add_child(child_child);
|
||||
}
|
||||
|
||||
return child_node;
|
||||
}
|
||||
|
||||
const std::vector<string_pair> &xml_node::get_attributes() const
|
||||
xml_node xml_node::add_child(const std::string &child_name)
|
||||
{
|
||||
return attributes_;
|
||||
return xml_node(detail::xml_node_impl(d_->node.append_child(child_name.c_str())));
|
||||
}
|
||||
|
||||
const std::vector<xml_node::string_pair> xml_node::get_attributes() const
|
||||
{
|
||||
std::vector<string_pair> attributes;
|
||||
|
||||
for(auto attr : d_->node.attributes())
|
||||
{
|
||||
attributes.push_back(std::make_pair<std::string, std::string>(attr.name(), attr.value()));
|
||||
}
|
||||
|
||||
return attributes;
|
||||
}
|
||||
|
||||
void xml_node::add_attribute(const std::string &name, const std::string &value)
|
||||
{
|
||||
attributes_.push_back(std::make_pair(name, value));
|
||||
d_->node.append_attribute(name.c_str()).set_value(value.c_str());
|
||||
}
|
||||
|
||||
bool xml_node::has_attribute(const std::string &attribute_name) const
|
||||
{
|
||||
return std::find_if(attributes_.begin(), attributes_.end(),
|
||||
[&](const string_pair &p) { return p.first == attribute_name; }) != attributes_.end();
|
||||
return d_->node.attribute(attribute_name.c_str()) != nullptr;
|
||||
}
|
||||
|
||||
std::string xml_node::get_attribute(const std::string &attribute_name) const
|
||||
{
|
||||
auto match = std::find_if(attributes_.begin(), attributes_.end(),
|
||||
[&](const string_pair &p) { return p.first == attribute_name; });
|
||||
|
||||
if(match == attributes_.end())
|
||||
{
|
||||
throw std::runtime_error("attribute doesn't exist: " + attribute_name);
|
||||
}
|
||||
|
||||
return match->second;
|
||||
return d_->node.attribute(attribute_name.c_str()).value();
|
||||
}
|
||||
|
||||
bool xml_node::has_child(const std::string &child_name) const
|
||||
{
|
||||
return std::find_if(children_.begin(), children_.end(),
|
||||
[&](const xml_node &n) { return n.get_name() == child_name; }) != children_.end();
|
||||
return d_->node.child(child_name.c_str()) != nullptr;
|
||||
}
|
||||
|
||||
xml_node &xml_node::get_child(const std::string &child_name)
|
||||
xml_node xml_node::get_child(const std::string &child_name)
|
||||
{
|
||||
auto match = std::find_if(children_.begin(), children_.end(),
|
||||
[&](const xml_node &n) { return n.get_name() == child_name; });
|
||||
|
||||
if(match == children_.end())
|
||||
{
|
||||
throw std::runtime_error("child doesn't exist: " + child_name);
|
||||
}
|
||||
|
||||
return *match;
|
||||
return xml_node(detail::xml_node_impl(d_->node.child(child_name.c_str())));
|
||||
}
|
||||
|
||||
const xml_node &xml_node::get_child(const std::string &child_name) const
|
||||
const xml_node xml_node::get_child(const std::string &child_name) const
|
||||
{
|
||||
auto match = std::find_if(children_.begin(), children_.end(),
|
||||
[&](const xml_node &n) { return n.get_name() == child_name; });
|
||||
return xml_node(detail::xml_node_impl(d_->node.child(child_name.c_str())));
|
||||
}
|
||||
|
||||
if(match == children_.end())
|
||||
{
|
||||
throw std::runtime_error("child doesn't exist: " + child_name);
|
||||
}
|
||||
|
||||
return *match;
|
||||
std::string xml_node::to_string() const
|
||||
{
|
||||
return xml_serializer::serialize_node(*this);
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -5,65 +5,31 @@
|
|||
#include <xlnt/s11n/xml_node.hpp>
|
||||
|
||||
#include "detail/include_pugixml.hpp"
|
||||
|
||||
namespace {
|
||||
|
||||
void serialize_node(const xlnt::xml_node &source, pugi::xml_node node)
|
||||
{
|
||||
for(const auto &attribute : source.get_attributes())
|
||||
{
|
||||
node.append_attribute(attribute.first.c_str()).set_value(attribute.second.c_str());
|
||||
}
|
||||
|
||||
if(source.has_text())
|
||||
{
|
||||
node.text().set(source.get_text().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
for(const auto &child : source.get_children())
|
||||
{
|
||||
pugi::xml_node child_node = node.append_child(child.get_name().c_str());
|
||||
serialize_node(child, child_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xlnt::xml_node deserialize_node(const pugi::xml_node source)
|
||||
{
|
||||
xlnt::xml_node node(source.name());
|
||||
|
||||
for(const auto attribute : source.attributes())
|
||||
{
|
||||
node.add_attribute(attribute.name(), attribute.as_string());
|
||||
}
|
||||
|
||||
if(source.text() != nullptr)
|
||||
{
|
||||
node.set_text(source.text().as_string());
|
||||
}
|
||||
else
|
||||
{
|
||||
for(const auto child : source.children())
|
||||
{
|
||||
node.add_child(deserialize_node(child));
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
#include "detail/xml_document_impl.hpp"
|
||||
#include "detail/xml_node_impl.hpp"
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
std::string xml_serializer::serialize(const xml_document &xml)
|
||||
{
|
||||
pugi::xml_document doc;
|
||||
std::ostringstream ss;
|
||||
xml.d_->doc.save(ss, " ", pugi::format_default, pugi::encoding_utf8);
|
||||
|
||||
auto root = doc.root();
|
||||
root.set_name(xml.root().get_name().c_str());
|
||||
serialize_node(xml.root(), root);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
xml_document xml_serializer::deserialize(const std::string &xml_string)
|
||||
{
|
||||
xml_document doc;
|
||||
doc.d_->doc.load(xml_string.c_str());
|
||||
|
||||
return doc;
|
||||
}
|
||||
|
||||
std::string xml_serializer::serialize_node(const xml_node &xml)
|
||||
{
|
||||
pugi::xml_document doc;
|
||||
doc.append_copy(xml.d_->node);
|
||||
|
||||
std::ostringstream ss;
|
||||
doc.save(ss);
|
||||
|
@ -71,15 +37,4 @@ std::string xml_serializer::serialize(const xml_document &xml)
|
|||
return ss.str();
|
||||
}
|
||||
|
||||
xml_document xml_serializer::deserialize(const std::string &xml_string)
|
||||
{
|
||||
pugi::xml_document doc;
|
||||
doc.load(xml_string.c_str());
|
||||
|
||||
xml_document result;
|
||||
result.root() = deserialize_node(doc.root());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -1,7 +1,78 @@
|
|||
#include <xlnt/workbook/manifest.hpp>
|
||||
|
||||
namespace {
|
||||
|
||||
bool match_path(const std::string &path, const std::string &comparand)
|
||||
{
|
||||
if(path == comparand)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if(path[0] != '/' && path[0] != '.' && comparand[0] == '/')
|
||||
{
|
||||
return match_path("/" + path, comparand);
|
||||
}
|
||||
else if(comparand[0] != '/' && comparand[0] != '.' && path[0] == '/')
|
||||
{
|
||||
return match_path(path, "/" + comparand);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
default_type::default_type()
|
||||
{
|
||||
}
|
||||
|
||||
default_type::default_type(const std::string &extension, const std::string &content_type) :
|
||||
extension_(extension),
|
||||
content_type_(content_type)
|
||||
{
|
||||
}
|
||||
|
||||
default_type::default_type(const default_type &other) :
|
||||
extension_(other.extension_),
|
||||
content_type_(other.content_type_)
|
||||
{
|
||||
}
|
||||
|
||||
default_type &default_type::operator=(const default_type &other)
|
||||
{
|
||||
extension_ = other.extension_;
|
||||
content_type_ = other.content_type_;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
override_type::override_type()
|
||||
{
|
||||
}
|
||||
|
||||
override_type::override_type(const std::string &part_name, const std::string &content_type) :
|
||||
part_name_(part_name),
|
||||
content_type_(content_type)
|
||||
{
|
||||
}
|
||||
|
||||
override_type::override_type(const override_type &other) :
|
||||
part_name_(other.part_name_),
|
||||
content_type_(other.content_type_)
|
||||
{
|
||||
}
|
||||
|
||||
override_type &override_type::operator=(const override_type &other)
|
||||
{
|
||||
part_name_ = other.part_name_;
|
||||
content_type_ = other.content_type_;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool manifest::has_default_type(const std::string &extension) const
|
||||
{
|
||||
return std::find_if(default_types_.begin(), default_types_.end(),
|
||||
|
@ -11,7 +82,17 @@ bool manifest::has_default_type(const std::string &extension) const
|
|||
bool manifest::has_override_type(const std::string &part_name) const
|
||||
{
|
||||
return std::find_if(override_types_.begin(), override_types_.end(),
|
||||
[&](const override_type &d) { return d.get_part_name() == part_name; }) != override_types_.end();
|
||||
[&](const override_type &d) { return match_path(d.get_part_name(), part_name); }) != override_types_.end();
|
||||
}
|
||||
|
||||
void manifest::add_default_type(const std::string &extension, const std::string &content_type)
|
||||
{
|
||||
default_types_.push_back(default_type(extension, content_type));
|
||||
}
|
||||
|
||||
void manifest::add_override_type(const std::string &part_name, const std::string &content_type)
|
||||
{
|
||||
override_types_.push_back(override_type(part_name, content_type));
|
||||
}
|
||||
|
||||
std::string manifest::get_default_type(const std::string &extension) const
|
||||
|
@ -30,7 +111,7 @@ std::string manifest::get_default_type(const std::string &extension) const
|
|||
std::string manifest::get_override_type(const std::string &part_name) const
|
||||
{
|
||||
auto match = std::find_if(override_types_.begin(), override_types_.end(),
|
||||
[&](const override_type &d) { return d.get_part_name() == part_name; });
|
||||
[&](const override_type &d) { return match_path(d.get_part_name(), part_name); });
|
||||
|
||||
if(match == override_types_.end())
|
||||
{
|
||||
|
|
|
@ -619,7 +619,7 @@ const number_format &workbook::get_number_format(std::size_t style_id) const
|
|||
|
||||
for(const auto &number_format_ : d_->number_formats_)
|
||||
{
|
||||
if(number_format_.get_id() == number_format_id)
|
||||
if(static_cast<std::size_t>(number_format_.get_id()) == number_format_id)
|
||||
{
|
||||
return number_format_;
|
||||
}
|
||||
|
@ -631,15 +631,15 @@ const number_format &workbook::get_number_format(std::size_t style_id) const
|
|||
return d_->number_formats_.back();
|
||||
}
|
||||
|
||||
const font &workbook::get_font(std::size_t style_id) const
|
||||
const font &workbook::get_font(std::size_t font_id) const
|
||||
{
|
||||
return d_->fonts_[d_->styles_[style_id].font_id_];
|
||||
return d_->fonts_[font_id];
|
||||
}
|
||||
|
||||
std::size_t workbook::set_font(const font &font_, std::size_t style_id)
|
||||
{
|
||||
auto match = std::find(d_->fonts_.begin(), d_->fonts_.end(), font_);
|
||||
auto font_index = 0;
|
||||
std::size_t font_index = 0;
|
||||
|
||||
if(match == d_->fonts_.end())
|
||||
{
|
||||
|
@ -674,22 +674,22 @@ std::size_t workbook::set_font(const font &font_, std::size_t style_id)
|
|||
return d_->styles_.size() - 1;
|
||||
}
|
||||
|
||||
const fill &workbook::get_fill(std::size_t style_id) const
|
||||
const fill &workbook::get_fill(std::size_t fill_id) const
|
||||
{
|
||||
return d_->fills_[d_->styles_[style_id].fill_id_];
|
||||
return d_->fills_[fill_id];
|
||||
}
|
||||
|
||||
std::size_t workbook::set_fill(const fill &fill_, std::size_t style_id)
|
||||
std::size_t workbook::set_fill(const fill &/*fill_*/, std::size_t style_id)
|
||||
{
|
||||
return style_id;
|
||||
}
|
||||
|
||||
const border &workbook::get_border(std::size_t style_id) const
|
||||
const border &workbook::get_border(std::size_t border_id) const
|
||||
{
|
||||
return d_->borders_[d_->styles_[style_id].border_id_];
|
||||
return d_->borders_[border_id];
|
||||
}
|
||||
|
||||
std::size_t workbook::set_border(const border &border_, std::size_t style_id)
|
||||
std::size_t workbook::set_border(const border &/*border_*/, std::size_t style_id)
|
||||
{
|
||||
return style_id;
|
||||
}
|
||||
|
@ -699,7 +699,7 @@ const alignment &workbook::get_alignment(std::size_t style_id) const
|
|||
return d_->styles_[style_id].alignment_;
|
||||
}
|
||||
|
||||
std::size_t workbook::set_alignment(const alignment &alignment_, std::size_t style_id)
|
||||
std::size_t workbook::set_alignment(const alignment &/*alignment_*/, std::size_t style_id)
|
||||
{
|
||||
return style_id;
|
||||
}
|
||||
|
@ -709,7 +709,7 @@ const protection &workbook::get_protection(std::size_t style_id) const
|
|||
return d_->styles_[style_id].protection_;
|
||||
}
|
||||
|
||||
std::size_t workbook::set_protection(const protection &protection_, std::size_t style_id)
|
||||
std::size_t workbook::set_protection(const protection &/*protection_*/, std::size_t style_id)
|
||||
{
|
||||
return style_id;
|
||||
}
|
||||
|
@ -861,12 +861,27 @@ const std::vector<relationship> &workbook::get_root_relationships() const
|
|||
{
|
||||
if(d_->root_relationships_.empty())
|
||||
{
|
||||
d_->root_relationships_.push_back(relationship(relationship::type::extended_properties, "rId3", "docProps/app.xml"));
|
||||
d_->root_relationships_.push_back(relationship(relationship::type::core_properties, "rId2", "docProps/core.xml"));
|
||||
d_->root_relationships_.push_back(relationship(relationship::type::office_document, "rId1", "xl/workbook.xml"));
|
||||
d_->root_relationships_.push_back(relationship(relationship::type::core_properties, "rId1", "docProps/core.xml"));
|
||||
d_->root_relationships_.push_back(relationship(relationship::type::extended_properties, "rId2", "docProps/app.xml"));
|
||||
d_->root_relationships_.push_back(relationship(relationship::type::office_document, "rId3", "xl/workbook.xml"));
|
||||
}
|
||||
|
||||
return d_->root_relationships_;
|
||||
}
|
||||
|
||||
std::vector<std::string> &workbook::get_shared_strings()
|
||||
{
|
||||
return d_->shared_strings_;
|
||||
}
|
||||
|
||||
const std::vector<std::string> &workbook::get_shared_strings() const
|
||||
{
|
||||
return d_->shared_strings_;
|
||||
}
|
||||
|
||||
void workbook::add_shared_string(const std::string &shared)
|
||||
{
|
||||
d_->shared_strings_.push_back(shared);
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -83,4 +83,10 @@ bool range_reference::operator==(const range_reference &comparand) const
|
|||
&& comparand.bottom_right_ == bottom_right_;
|
||||
}
|
||||
|
||||
bool range_reference::operator!=(const range_reference &comparand) const
|
||||
{
|
||||
return comparand.top_left_ != top_left_
|
||||
|| comparand.bottom_right_ != bottom_right_;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -73,6 +73,11 @@ std::vector<range_reference> worksheet::get_merged_ranges() const
|
|||
return d_->merged_cells_;
|
||||
}
|
||||
|
||||
margins &worksheet::get_page_margins()
|
||||
{
|
||||
return d_->page_margins_;
|
||||
}
|
||||
|
||||
const margins &worksheet::get_page_margins() const
|
||||
{
|
||||
return d_->page_margins_;
|
||||
|
@ -103,6 +108,11 @@ void worksheet::unset_auto_filter()
|
|||
d_->auto_filter_ = range_reference(1, 1, 1, 1);
|
||||
}
|
||||
|
||||
page_setup &worksheet::get_page_setup()
|
||||
{
|
||||
return d_->page_setup_;
|
||||
}
|
||||
|
||||
const page_setup &worksheet::get_page_setup() const
|
||||
{
|
||||
return d_->page_setup_;
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
#include <xlnt/cell/cell.hpp>
|
||||
#include <xlnt/cell/cell_reference.hpp>
|
||||
#include <xlnt/common/zip_file.hpp>
|
||||
#include <xlnt/styles/number_format.hpp>
|
||||
#include <xlnt/workbook/workbook.hpp>
|
||||
#include <xlnt/worksheet/range_reference.hpp>
|
||||
#include <xlnt/worksheet/worksheet.hpp>
|
||||
|
||||
#include "detail/include_pugixml.hpp"
|
||||
|
||||
namespace {
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace xlnt {
|
||||
} // namespace xlnt
|
|
@ -31,15 +31,27 @@ public:
|
|||
operator bool() const { return difference == difference_type::equivalent; }
|
||||
};
|
||||
|
||||
static comparison_result compare_xml(const xlnt::xml_document &expected, const xlnt::xml_document &observed)
|
||||
{
|
||||
return compare_xml(expected.get_root(), observed.get_root());
|
||||
}
|
||||
|
||||
static comparison_result compare_xml(const std::string &expected, const xlnt::xml_document &observed)
|
||||
{
|
||||
std::ifstream f(expected);
|
||||
std::ostringstream s;
|
||||
f >> s.rdbuf();
|
||||
std::string expected_contents = expected;
|
||||
|
||||
auto expected_xml = xlnt::xml_serializer::deserialize(s.str());
|
||||
if(PathHelper::FileExists(expected))
|
||||
{
|
||||
std::ifstream f(expected);
|
||||
std::ostringstream s;
|
||||
f >> s.rdbuf();
|
||||
|
||||
expected_contents = s.str();
|
||||
}
|
||||
|
||||
return compare_xml(expected_xml.root(), observed.root());
|
||||
auto expected_xml = xlnt::xml_serializer::deserialize(expected_contents);
|
||||
|
||||
return compare_xml(expected_xml.get_root(), observed.get_root());
|
||||
}
|
||||
|
||||
static comparison_result compare_xml(const std::string &left_contents, const std::string &right_contents)
|
||||
|
@ -47,7 +59,7 @@ public:
|
|||
auto left_doc = xlnt::xml_serializer::deserialize(left_contents);
|
||||
auto right_doc = xlnt::xml_serializer::deserialize(right_contents);
|
||||
|
||||
return compare_xml(left_doc.root(), right_doc.root());
|
||||
return compare_xml(left_doc.get_root(), right_doc.get_root());
|
||||
}
|
||||
|
||||
static comparison_result compare_xml(const xlnt::xml_node &left, const xlnt::xml_node &right)
|
||||
|
@ -100,13 +112,14 @@ public:
|
|||
return {difference_type::text_values_differ, "((empty))", right_temp};
|
||||
}
|
||||
|
||||
auto right_child_iter = right.get_children().begin();
|
||||
auto right_children = right.get_children();
|
||||
auto right_child_iter = right_children.begin();
|
||||
|
||||
for(auto left_child : left.get_children())
|
||||
{
|
||||
left_temp = left_child.get_name();
|
||||
|
||||
if(right_child_iter == right.get_children().end())
|
||||
if(right_child_iter == right_children.end())
|
||||
{
|
||||
return {difference_type::child_order_differs, left_temp, "((end))"};
|
||||
}
|
||||
|
@ -122,7 +135,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
if(right_child_iter != right.get_children().end())
|
||||
if(right_child_iter != right_children.end())
|
||||
{
|
||||
right_temp = right_child_iter->get_name();
|
||||
return {difference_type::child_order_differs, "((end))", right_temp};
|
||||
|
|
|
@ -83,6 +83,8 @@ 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);
|
||||
TS_FAIL("");
|
||||
return;
|
||||
xlnt::workbook_serializer serializer(wb);
|
||||
xlnt::xml_document xml = serializer.write_properties_core();
|
||||
TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/core.xml", xml));
|
||||
|
@ -95,6 +97,8 @@ public:
|
|||
wb.create_sheet();
|
||||
xlnt::workbook_serializer serializer(wb);
|
||||
xlnt::xml_document xml = serializer.write_properties_app();
|
||||
TS_FAIL("");
|
||||
return;
|
||||
TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/app.xml", xml));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include <xlnt/s11n/excel_serializer.hpp>
|
||||
#include <xlnt/s11n/manifest_serializer.hpp>
|
||||
#include <xlnt/s11n/relationship_serializer.hpp>
|
||||
#include <xlnt/s11n/workbook_serializer.hpp>
|
||||
#include <xlnt/s11n/xml_serializer.hpp>
|
||||
#include <xlnt/workbook/manifest.hpp>
|
||||
|
@ -331,11 +332,15 @@ public:
|
|||
{
|
||||
auto path = PathHelper::GetDataDirectory("/reader/bug137.xlsx");
|
||||
xlnt::zip_file archive(path);
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> expected =
|
||||
{
|
||||
{"xl/worksheets/sheet1.xml", "Sheet1"}
|
||||
};
|
||||
TS_ASSERT_EQUALS(xlnt::detect_worksheets(archive), expected);
|
||||
|
||||
xlnt::workbook wb;
|
||||
xlnt::workbook_serializer serializer(wb);
|
||||
TS_ASSERT_EQUALS(serializer.detect_worksheets(), expected);
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -348,7 +353,9 @@ public:
|
|||
{"xl/worksheets/sheet2.xml", "moredata"}
|
||||
};
|
||||
|
||||
TS_ASSERT_EQUALS(xlnt::detect_worksheets(archive), expected);
|
||||
xlnt::workbook wb;
|
||||
xlnt::workbook_serializer serializer(wb);
|
||||
TS_ASSERT_EQUALS(serializer.detect_worksheets(), expected);
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -362,7 +369,9 @@ public:
|
|||
{"xl/worksheets/sheet.xml", "Sheet3"}
|
||||
};
|
||||
|
||||
TS_ASSERT_EQUALS(xlnt::detect_worksheets(archive), expected);
|
||||
xlnt::workbook wb;
|
||||
xlnt::workbook_serializer serializer(wb);
|
||||
TS_ASSERT_EQUALS(serializer.detect_worksheets(), expected);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -381,7 +390,7 @@ public:
|
|||
auto path = PathHelper::GetDataDirectory("/reader/bug137.xlsx");
|
||||
xlnt::zip_file archive(path);
|
||||
|
||||
TS_ASSERT_EQUALS(xlnt::read_relationships(archive, "xl/workbook.xml"), expected);
|
||||
TS_ASSERT_EQUALS(xlnt::relationship_serializer::read_relationships(archive, "xl/workbook.xml"), expected);
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -400,7 +409,7 @@ public:
|
|||
auto path = PathHelper::GetDataDirectory("/reader/bug304.xlsx");
|
||||
xlnt::zip_file archive(path);
|
||||
|
||||
TS_ASSERT_EQUALS(xlnt::read_relationships(archive, "xl/workbook.xml"), expected);
|
||||
TS_ASSERT_EQUALS(xlnt::relationship_serializer::read_relationships(archive, "xl/workbook.xml"), expected);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,14 +13,15 @@ public:
|
|||
xlnt::workbook wb;
|
||||
wb.add_number_format(xlnt::number_format("YYYY"));
|
||||
xlnt::style_serializer writer(wb);
|
||||
auto xml = writer.write_number_formats();
|
||||
xlnt::xml_document observed;
|
||||
writer.write_number_formats(observed.add_child("numFmts"));
|
||||
std::string expected =
|
||||
"<styleSheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\">"
|
||||
" <numFmts count=\"1\">"
|
||||
" <numFmt formatCode=\"YYYY\" numFmtId=\"164\"></numFmt>"
|
||||
" </numFmts>"
|
||||
"</styleSheet>";
|
||||
auto diff = Helper::compare_xml(xml, expected);
|
||||
auto diff = Helper::compare_xml(expected, observed);
|
||||
TS_ASSERT(diff);
|
||||
}
|
||||
/*
|
||||
|
|
|
@ -14,9 +14,9 @@ class test_theme : public CxxTest::TestSuite
|
|||
public:
|
||||
void test_write_theme()
|
||||
{
|
||||
xlnt::theme_serializer serializer;
|
||||
xlnt::workbook wb;
|
||||
auto content = serializer.write_theme(wb.get_loaded_theme());
|
||||
TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/theme1.xml", content));
|
||||
xlnt::theme_serializer serializer;
|
||||
auto xml = serializer.write_theme(wb.get_loaded_theme());
|
||||
TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/theme1.xml", xml));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <iostream>
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include <xlnt/s11n/worksheet_serializer.hpp>
|
||||
#include <xlnt/worksheet/worksheet.hpp>
|
||||
|
||||
class test_worksheet : public CxxTest::TestSuite
|
||||
|
@ -639,10 +640,8 @@ public:
|
|||
{
|
||||
xlnt::worksheet ws(wb_);
|
||||
|
||||
auto xml_string = xlnt::write_worksheet(ws, {});
|
||||
|
||||
pugi::xml_document doc;
|
||||
doc.load(xml_string.c_str());
|
||||
xlnt::worksheet_serializer serializer(ws);
|
||||
auto observed = serializer.write_worksheet();
|
||||
|
||||
auto expected_string =
|
||||
"<worksheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">"
|
||||
|
@ -660,10 +659,10 @@ public:
|
|||
" <pageMargins left=\"0.75\" right=\"0.75\" top=\"1\" bottom=\"1\" header=\"0.5\" footer=\"0.5\"/>"
|
||||
"</worksheet>";
|
||||
|
||||
pugi::xml_document expected_doc;
|
||||
expected_doc.load(expected_string);
|
||||
xlnt::xml_document expected;
|
||||
expected.from_string(expected_string);
|
||||
|
||||
TS_ASSERT(Helper::compare_xml(expected_doc, doc));
|
||||
TS_ASSERT(Helper::compare_xml(expected, observed));
|
||||
}
|
||||
|
||||
void test_page_margins()
|
||||
|
@ -677,10 +676,8 @@ public:
|
|||
ws.get_page_margins().set_header(1.5);
|
||||
ws.get_page_margins().set_footer(1.5);
|
||||
|
||||
auto xml_string = xlnt::write_worksheet(ws, {});
|
||||
|
||||
pugi::xml_document doc;
|
||||
doc.load(xml_string.c_str());
|
||||
xlnt::worksheet_serializer serializer(ws);
|
||||
auto observed = serializer.write_worksheet();
|
||||
|
||||
auto expected_string =
|
||||
"<worksheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">"
|
||||
|
@ -698,10 +695,10 @@ public:
|
|||
" <pageMargins left=\"2\" right=\"2\" top=\"2\" bottom=\"2\" header=\"1.5\" footer=\"1.5\"/>"
|
||||
"</worksheet>";
|
||||
|
||||
pugi::xml_document expected_doc;
|
||||
expected_doc.load(expected_string);
|
||||
|
||||
TS_ASSERT(Helper::compare_xml(expected_doc, doc));
|
||||
xlnt::xml_document expected;
|
||||
expected.from_string(expected_string);
|
||||
|
||||
TS_ASSERT(Helper::compare_xml(expected, observed));
|
||||
}
|
||||
|
||||
void test_merge()
|
||||
|
@ -737,18 +734,17 @@ public:
|
|||
ws.get_cell("A1").set_value("Cell A1");
|
||||
ws.get_cell("B1").set_value("Cell B1");
|
||||
|
||||
auto xml_string = xlnt::write_worksheet(ws, string_table);
|
||||
{
|
||||
xlnt::worksheet_serializer serializer(ws);
|
||||
auto observed = serializer.write_worksheet();
|
||||
|
||||
pugi::xml_document doc;
|
||||
doc.load(xml_string.c_str());
|
||||
|
||||
pugi::xml_document expected_doc;
|
||||
expected_doc.load(expected_string1);
|
||||
|
||||
TS_ASSERT(Helper::compare_xml(expected_doc, doc));
|
||||
xlnt::xml_document expected;
|
||||
expected.from_string(expected_string1);
|
||||
|
||||
TS_ASSERT(Helper::compare_xml(expected, observed));
|
||||
}
|
||||
|
||||
ws.merge_cells("A1:B1");
|
||||
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\">"
|
||||
|
@ -776,13 +772,17 @@ public:
|
|||
" <pageMargins left=\"0.75\" right=\"0.75\" top=\"1\" bottom=\"1\" header=\"0.5\" footer=\"0.5\"/>"
|
||||
"</worksheet>";
|
||||
|
||||
doc.load(xml_string.c_str());
|
||||
expected_doc.load(expected_string2);
|
||||
|
||||
TS_ASSERT(Helper::compare_xml(expected_doc, doc));
|
||||
{
|
||||
xlnt::worksheet_serializer serializer(ws);
|
||||
auto observed = serializer.write_worksheet();
|
||||
|
||||
xlnt::xml_document expected;
|
||||
expected.from_string(expected_string2);
|
||||
|
||||
TS_ASSERT(Helper::compare_xml(expected, observed));
|
||||
}
|
||||
|
||||
ws.unmerge_cells("A1:B1");
|
||||
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\">"
|
||||
|
@ -807,10 +807,15 @@ public:
|
|||
" <pageMargins left=\"0.75\" right=\"0.75\" top=\"1\" bottom=\"1\" header=\"0.5\" footer=\"0.5\"/>"
|
||||
"</worksheet>";
|
||||
|
||||
doc.load(xml_string.c_str());
|
||||
expected_doc.load(expected_string3);
|
||||
|
||||
TS_ASSERT(Helper::compare_xml(expected_doc, doc));
|
||||
{
|
||||
xlnt::worksheet_serializer serializer(ws);
|
||||
auto observed = serializer.write_worksheet();
|
||||
|
||||
xlnt::xml_document expected;
|
||||
expected.from_string(expected_string3);
|
||||
|
||||
TS_ASSERT(Helper::compare_xml(expected, observed));
|
||||
}
|
||||
}
|
||||
|
||||
void test_printer_settings()
|
||||
|
@ -825,11 +830,9 @@ public:
|
|||
ws.get_page_setup().set_horizontal_centered(true);
|
||||
ws.get_page_setup().set_vertical_centered(true);
|
||||
|
||||
auto xml_string = xlnt::write_worksheet(ws, {});
|
||||
xlnt::worksheet_serializer serializer(ws);
|
||||
auto observed = serializer.write_worksheet();
|
||||
|
||||
pugi::xml_document doc;
|
||||
doc.load(xml_string.c_str());
|
||||
|
||||
auto expected_string =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||
"<worksheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">"
|
||||
|
@ -850,10 +853,10 @@ public:
|
|||
" <pageSetup orientation=\"landscape\" paperSize=\"3\" fitToHeight=\"0\" fitToWidth=\"1\" />"
|
||||
"</worksheet>";
|
||||
|
||||
pugi::xml_document expected_doc;
|
||||
expected_doc.load(expected_string);
|
||||
xlnt::xml_document expected;
|
||||
expected.from_string(expected_string);
|
||||
|
||||
TS_ASSERT(Helper::compare_xml(expected_doc, doc));
|
||||
TS_ASSERT(Helper::compare_xml(expected, observed));
|
||||
}
|
||||
|
||||
void test_header_footer()
|
||||
|
@ -901,13 +904,15 @@ public:
|
|||
" </headerFooter>"
|
||||
"</worksheet>";
|
||||
|
||||
pugi::xml_document expected_doc;
|
||||
pugi::xml_document observed_doc;
|
||||
xlnt::xml_document expected;
|
||||
expected.from_string(expected_xml_string);
|
||||
|
||||
expected_doc.load(expected_xml_string.c_str());
|
||||
observed_doc.load(xlnt::write_worksheet(ws, {}).c_str());
|
||||
|
||||
TS_ASSERT(Helper::compare_xml(expected_doc, observed_doc));
|
||||
{
|
||||
xlnt::worksheet_serializer serializer(ws);
|
||||
auto observed = serializer.write_worksheet();
|
||||
|
||||
TS_ASSERT(Helper::compare_xml(expected, observed));
|
||||
}
|
||||
|
||||
ws = wb_.create_sheet();
|
||||
|
||||
|
@ -927,10 +932,12 @@ public:
|
|||
" <pageMargins left=\"0.75\" right=\"0.75\" top=\"1\" bottom=\"1\" header=\"0.5\" footer=\"0.5\"/>"
|
||||
"</worksheet>";
|
||||
|
||||
expected_doc.load(expected_xml_string.c_str());
|
||||
observed_doc.load(xlnt::write_worksheet(ws, {}).c_str());
|
||||
|
||||
TS_ASSERT(Helper::compare_xml(expected_doc, observed_doc));
|
||||
{
|
||||
xlnt::worksheet_serializer serializer(ws);
|
||||
auto observed = serializer.write_worksheet();
|
||||
|
||||
TS_ASSERT(Helper::compare_xml(expected, observed));
|
||||
}
|
||||
}
|
||||
|
||||
void test_page_setup()
|
||||
|
|
|
@ -3,7 +3,12 @@
|
|||
#include <iostream>
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include <xlnt/xlnt.hpp>
|
||||
#include <xlnt/s11n/relationship_serializer.hpp>
|
||||
#include <xlnt/s11n/shared_strings_serializer.hpp>
|
||||
#include <xlnt/s11n/workbook_serializer.hpp>
|
||||
#include <xlnt/s11n/worksheet_serializer.hpp>
|
||||
#include <xlnt/workbook/workbook.hpp>
|
||||
|
||||
#include "helpers/temporary_file.hpp"
|
||||
#include "helpers/path_helper.hpp"
|
||||
#include "helpers/helper.hpp"
|
||||
|
@ -41,32 +46,45 @@ public:
|
|||
void test_write_workbook_rels()
|
||||
{
|
||||
xlnt::workbook wb;
|
||||
auto content = xlnt::write_workbook_rels(wb);
|
||||
xlnt::zip_file archive;
|
||||
xlnt::relationship_serializer::write_relationships(wb.get_relationships(), "xl/workbook.xml", archive);
|
||||
auto content = xlnt::xml_serializer::deserialize(archive.read("xl/_rels/workbook.xml.rels"));
|
||||
|
||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/workbook.xml.rels", content));
|
||||
TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/workbook.xml.rels", content));
|
||||
}
|
||||
|
||||
void test_write_workbook()
|
||||
{
|
||||
xlnt::workbook wb;
|
||||
auto content = xlnt::write_workbook(wb);
|
||||
xlnt::workbook_serializer serializer(wb);
|
||||
auto content = serializer.write_workbook();
|
||||
|
||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/workbook.xml", content));
|
||||
TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/workbook.xml", content));
|
||||
}
|
||||
|
||||
void test_write_string_table()
|
||||
{
|
||||
std::vector<std::string> table = {"hello", "world", "nice"};
|
||||
auto content = xlnt::write_shared_strings(table);
|
||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/sharedStrings.xml", content));
|
||||
xlnt::workbook wb;
|
||||
auto ws = wb.get_active_sheet();
|
||||
|
||||
ws.get_cell("A1").set_value("hello");
|
||||
ws.get_cell("A2").set_value("world");
|
||||
ws.get_cell("A3").set_value("nice");
|
||||
|
||||
auto content = xlnt::shared_strings_serializer::write_shared_strings(wb.get_shared_strings());
|
||||
|
||||
TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sharedStrings.xml", content));
|
||||
}
|
||||
|
||||
void test_write_worksheet()
|
||||
{
|
||||
auto ws = wb_.create_sheet();
|
||||
ws.get_cell("F42").set_value("hello");
|
||||
auto content = xlnt::write_worksheet(ws, {"hello"});
|
||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/sheet1.xml", content));
|
||||
|
||||
xlnt::worksheet_serializer serializer(ws);
|
||||
auto observed = serializer.write_worksheet();
|
||||
|
||||
TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sheet1.xml", observed));
|
||||
}
|
||||
|
||||
void test_write_hidden_worksheet()
|
||||
|
@ -74,8 +92,11 @@ 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::write_worksheet(ws, {"hello"});
|
||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/sheet1.xml", content));
|
||||
|
||||
xlnt::worksheet_serializer serializer(ws);
|
||||
auto observed = serializer.write_worksheet();
|
||||
|
||||
TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sheet1.xml", observed));
|
||||
}
|
||||
|
||||
void test_write_bool()
|
||||
|
@ -83,8 +104,11 @@ public:
|
|||
auto ws = wb_.create_sheet();
|
||||
ws.get_cell("F42").set_value(false);
|
||||
ws.get_cell("F43").set_value(true);
|
||||
auto content = xlnt::write_worksheet(ws, {});
|
||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_bool.xml", content));
|
||||
|
||||
xlnt::worksheet_serializer serializer(ws);
|
||||
auto observed = serializer.write_worksheet();
|
||||
|
||||
TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_bool.xml", observed));
|
||||
}
|
||||
|
||||
void test_write_formula()
|
||||
|
@ -93,8 +117,11 @@ 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::write_worksheet(ws, {});
|
||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_formula.xml", content));
|
||||
|
||||
xlnt::worksheet_serializer serializer(ws);
|
||||
auto observed = serializer.write_worksheet();
|
||||
|
||||
TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_formula.xml", observed));
|
||||
}
|
||||
|
||||
void test_write_height()
|
||||
|
@ -102,8 +129,11 @@ 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::write_worksheet(ws, {});
|
||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_height.xml", content));
|
||||
|
||||
xlnt::worksheet_serializer serializer(ws);
|
||||
auto observed = serializer.write_worksheet();
|
||||
|
||||
TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_height.xml", observed));
|
||||
}
|
||||
|
||||
void test_write_hyperlink()
|
||||
|
@ -111,8 +141,11 @@ 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::write_worksheet(ws, {"test"});
|
||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_hyperlink.xml", content));
|
||||
|
||||
xlnt::worksheet_serializer serializer(ws);
|
||||
auto observed = serializer.write_worksheet();
|
||||
|
||||
TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_hyperlink.xml", observed));
|
||||
}
|
||||
|
||||
void test_write_hyperlink_rels()
|
||||
|
@ -125,8 +158,12 @@ 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::write_worksheet_rels(ws);
|
||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_hyperlink.xml.rels", content));
|
||||
|
||||
xlnt::zip_file archive;
|
||||
xlnt::relationship_serializer::write_relationships(ws.get_relationships(), "xl/worksheets/sheet1.xml", archive);
|
||||
auto content = xlnt::xml_serializer::deserialize(archive.read("xl/worksheets/_rels/sheet1.xml.rels"));
|
||||
|
||||
TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_hyperlink.xml.rels", content));
|
||||
}
|
||||
|
||||
void _test_write_hyperlink_image_rels()
|
||||
|
@ -149,11 +186,16 @@ public:
|
|||
auto ws = wb.get_sheet_by_index(0);
|
||||
ws.get_cell("F42").set_value("hello");
|
||||
ws.auto_filter("A1:F1");
|
||||
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);
|
||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/workbook_auto_filter.xml", content));
|
||||
xlnt::worksheet_serializer ws_serializer(ws);
|
||||
auto observed = ws_serializer.write_worksheet();
|
||||
|
||||
TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_auto_filter.xml", observed));
|
||||
|
||||
xlnt::workbook_serializer wb_serializer(wb);
|
||||
auto observed2 = wb_serializer.write_workbook();
|
||||
|
||||
TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/workbook_auto_filter.xml", observed2));
|
||||
}
|
||||
|
||||
void test_write_auto_filter_filter_column()
|
||||
|
@ -171,8 +213,11 @@ public:
|
|||
auto ws = wb_.create_sheet();
|
||||
ws.get_cell("F42").set_value("hello");
|
||||
ws.freeze_panes("A4");
|
||||
auto content = xlnt::write_worksheet(ws, {"hello"});
|
||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_freeze_panes_horiz.xml", content));
|
||||
|
||||
xlnt::worksheet_serializer serializer(ws);
|
||||
auto observed = serializer.write_worksheet();
|
||||
|
||||
TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_freeze_panes_horiz.xml", observed));
|
||||
}
|
||||
|
||||
void test_freeze_panes_vert()
|
||||
|
@ -180,8 +225,11 @@ public:
|
|||
auto ws = wb_.create_sheet();
|
||||
ws.get_cell("F42").set_value("hello");
|
||||
ws.freeze_panes("D1");
|
||||
auto content = xlnt::write_worksheet(ws, {"hello"});
|
||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_freeze_panes_vert.xml", content));
|
||||
|
||||
xlnt::worksheet_serializer serializer(ws);
|
||||
auto observed = serializer.write_worksheet();
|
||||
|
||||
TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_freeze_panes_vert.xml", observed));
|
||||
}
|
||||
|
||||
void test_freeze_panes_both()
|
||||
|
@ -189,24 +237,33 @@ public:
|
|||
auto ws = wb_.create_sheet();
|
||||
ws.get_cell("F42").set_value("hello");
|
||||
ws.freeze_panes("D4");
|
||||
auto content = xlnt::write_worksheet(ws, {"hello"});
|
||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_freeze_panes_both.xml", content));
|
||||
|
||||
xlnt::worksheet_serializer serializer(ws);
|
||||
auto observed = serializer.write_worksheet();
|
||||
|
||||
TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_freeze_panes_both.xml", observed));
|
||||
}
|
||||
|
||||
void test_long_number()
|
||||
{
|
||||
auto ws = wb_.create_sheet();
|
||||
ws.get_cell("A1").set_value(9781231231230LL);
|
||||
auto content = xlnt::write_worksheet(ws, {});
|
||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/long_number.xml", content));
|
||||
|
||||
xlnt::worksheet_serializer serializer(ws);
|
||||
auto observed = serializer.write_worksheet();
|
||||
|
||||
TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/long_number.xml", observed));
|
||||
}
|
||||
|
||||
void test_short_number()
|
||||
{
|
||||
auto ws = wb_.create_sheet();
|
||||
ws.get_cell("A1").set_value(1234567890);
|
||||
auto content = xlnt::write_worksheet(ws, {});
|
||||
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/short_number.xml", content));
|
||||
|
||||
xlnt::worksheet_serializer serializer(ws);
|
||||
auto observed = serializer.write_worksheet();
|
||||
|
||||
TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/short_number.xml", observed));
|
||||
}
|
||||
|
||||
void _test_write_images()
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include <xlnt/common/exceptions.hpp>
|
||||
#include <xlnt/reader/workbook_reader.hpp>
|
||||
#include <xlnt/writer/workbook_writer.hpp>
|
||||
#include <xlnt/s11n/workbook_serializer.hpp>
|
||||
|
||||
#include "helpers/path_helper.hpp"
|
||||
|
||||
|
@ -19,8 +18,10 @@ public:
|
|||
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);
|
||||
xlnt::workbook_serializer serializer(wb);
|
||||
auto observed = serializer.write_workbook();
|
||||
|
||||
auto diff = Helper::compare_xml(PathHelper::read_file("workbook_auto_filter.xml"), observed);
|
||||
TS_ASSERT(!diff);
|
||||
}
|
||||
|
||||
|
@ -30,8 +31,11 @@ public:
|
|||
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 =
|
||||
|
||||
xlnt::workbook_serializer serializer(wb);
|
||||
auto observed = serializer.write_workbook();
|
||||
|
||||
std::string expected_string =
|
||||
"<workbook xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">"
|
||||
" <workbookPr/>"
|
||||
" <bookViews>"
|
||||
|
@ -44,7 +48,11 @@ public:
|
|||
" <definedNames/>"
|
||||
" <calcPr calcId=\"124519\" fullCalcOnLoad=\"1\"/>"
|
||||
"</workbook>";
|
||||
auto diff = Helper::compare_xml(xml, expected);
|
||||
|
||||
xlnt::xml_document expected;
|
||||
expected.from_string(expected_string);
|
||||
|
||||
auto diff = Helper::compare_xml(expected, observed);
|
||||
TS_ASSERT(!diff);
|
||||
}
|
||||
|
||||
|
@ -53,40 +61,56 @@ public:
|
|||
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);
|
||||
|
||||
xlnt::workbook_serializer serializer(wb);
|
||||
|
||||
TS_ASSERT_THROWS(serializer.write_workbook(), xlnt::value_error);
|
||||
}
|
||||
|
||||
void test_write_empty_workbook()
|
||||
{
|
||||
xlnt::workbook wb;
|
||||
TemporaryFile file;
|
||||
xlnt::save_workbook(wb, file.GetFilename());
|
||||
|
||||
xlnt::excel_serializer serializer(wb);
|
||||
serializer.save_workbook(file.GetFilename());
|
||||
|
||||
TS_ASSERT(PathHelper::FileExists(file.GetFilename()));
|
||||
}
|
||||
|
||||
void test_write_virtual_workbook()
|
||||
{
|
||||
xlnt::workbook old_wb;
|
||||
auto saved_wb = xlnt::save_virtual_workbook(old_wb);
|
||||
auto new_wb = xlnt::excel_reader::load_workbook(saved_wb);
|
||||
xlnt::workbook old_wb, new_wb;
|
||||
|
||||
xlnt::excel_serializer serializer(old_wb);
|
||||
std::vector<std::uint8_t> wb_bytes;
|
||||
serializer.save_virtual_workbook(wb_bytes);
|
||||
|
||||
xlnt::excel_serializer deserializer(new_wb);
|
||||
deserializer.load_virtual_workbook(wb_bytes);
|
||||
|
||||
TS_ASSERT(new_wb != nullptr);
|
||||
}
|
||||
|
||||
void test_write_workbook_rels()
|
||||
{
|
||||
xlnt::workbook wb;
|
||||
auto content = xlnt::write_workbook_rels(wb);
|
||||
xlnt::zip_file archive;
|
||||
xlnt::relationship_serializer::write_relationships(wb.get_relationships(), "xl/workbook.xml", archive);
|
||||
xlnt::xml_document observed;
|
||||
observed.from_string(archive.read("xl/workbook/_rels/workbook.xml.rels"));
|
||||
auto filename = "workbook.xml.rels";
|
||||
auto diff = Helper::compare_xml(PathHelper::read_file(filename), content);
|
||||
auto diff = Helper::compare_xml(PathHelper::read_file(filename), observed);
|
||||
TS_ASSERT(!diff);
|
||||
}
|
||||
|
||||
void test_write_workbook_()
|
||||
{
|
||||
xlnt::workbook wb;
|
||||
auto content = xlnt::write_workbook(wb);
|
||||
xlnt::workbook_serializer serializer(wb);
|
||||
auto observed = serializer.write_workbook();
|
||||
auto filename = PathHelper::GetDataDirectory("/workbook.xml");
|
||||
auto diff = Helper::compare_xml(PathHelper::read_file(filename), content);
|
||||
auto diff = Helper::compare_xml(PathHelper::read_file(filename), observed);
|
||||
TS_ASSERT(!diff);
|
||||
}
|
||||
|
||||
|
@ -95,12 +119,15 @@ public:
|
|||
xlnt::workbook wb;
|
||||
auto ws = wb.create_sheet();
|
||||
wb.create_named_range("test_range", ws, "A1:B5");
|
||||
auto xml = xlnt::write_defined_names(wb);
|
||||
xlnt::workbook_serializer serializer(wb);
|
||||
auto observed_node = serializer.write_named_ranges();
|
||||
xlnt::xml_document observed;
|
||||
observed.add_child(observed_node);
|
||||
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);
|
||||
auto diff = Helper::compare_xml(expected, observed);
|
||||
TS_ASSERT(!diff);
|
||||
}
|
||||
|
||||
|
@ -115,7 +142,9 @@ public:
|
|||
xlnt::workbook wb;
|
||||
wb.set_code_name("MyWB");
|
||||
|
||||
auto content = xlnt::write_workbook(wb);
|
||||
xlnt::workbook_serializer serializer(wb);
|
||||
auto observed = serializer.write_workbook();
|
||||
|
||||
std::string expected =
|
||||
"<workbook xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">"
|
||||
" <workbookPr codeName=\"MyWB\"/>"
|
||||
|
@ -128,21 +157,26 @@ public:
|
|||
" <definedNames/>"
|
||||
" <calcPr calcId=\"124519\" fullCalcOnLoad=\"1\"/>"
|
||||
"</workbook>";
|
||||
auto diff = Helper::compare_xml(content, expected);
|
||||
auto diff = Helper::compare_xml(expected, observed);
|
||||
TS_ASSERT(!diff);
|
||||
}
|
||||
|
||||
void test_write_root_rels()
|
||||
{
|
||||
xlnt::workbook wb;
|
||||
auto xml = xlnt::write_root_rels(wb);
|
||||
xlnt::zip_file archive;
|
||||
xlnt::relationship_serializer::write_relationships(wb.get_root_relationships(), "", archive);
|
||||
xlnt::xml_document observed;
|
||||
observed.from_string(archive.read("_rels/.rels"));
|
||||
|
||||
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);
|
||||
|
||||
auto diff = Helper::compare_xml(expected, observed);
|
||||
TS_ASSERT(!diff);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user