mirror of
https://github.com/tfussell/xlnt.git
synced 2024-03-22 13:11:17 +08:00
implement garbage collection to remove unreferenced formats and constituent parts
This commit is contained in:
parent
1474c8ab82
commit
ca692790fa
|
@ -174,46 +174,37 @@ public:
|
|||
/// </summary>
|
||||
bool has_hyperlink() const;
|
||||
|
||||
// computed format
|
||||
|
||||
/// <summary>
|
||||
/// For each of alignment, border, fill, font, number format, and protection,
|
||||
/// returns a format using the value from the cell format if that value is
|
||||
/// applied, or else the value from the named style if that value is applied,
|
||||
/// or else the default value. This is used to retreive the formatting of the cell
|
||||
/// as it will be displayed in an editing application.
|
||||
/// </summary>
|
||||
base_format get_computed_format() const;
|
||||
// computed formatting
|
||||
|
||||
/// <summary>
|
||||
/// Returns the result of get_computed_format().get_alignment().
|
||||
/// </summary>
|
||||
alignment get_computed_alignment() const;
|
||||
alignment computed_alignment() const;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the result of get_computed_format().get_border().
|
||||
/// </summary>
|
||||
border get_computed_border() const;
|
||||
border computed_border() const;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the result of get_computed_format().get_fill().
|
||||
/// </summary>
|
||||
fill get_computed_fill() const;
|
||||
fill computed_fill() const;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the result of get_computed_format().get_font().
|
||||
/// </summary>
|
||||
font get_computed_font() const;
|
||||
font computed_font() const;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the result of get_computed_format().get_number_format().
|
||||
/// </summary>
|
||||
number_format get_computed_number_format() const;
|
||||
number_format computed_number_format() const;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the result of get_computed_format().get_protection().
|
||||
/// </summary>
|
||||
protection get_computed_protection() const;
|
||||
protection computed_protection() const;
|
||||
|
||||
// format
|
||||
|
||||
|
@ -226,12 +217,12 @@ public:
|
|||
/// Return a reference to the format applied to this cell.
|
||||
/// If this cell has no format, an invalid_attribute exception will be thrown.
|
||||
/// </summary>
|
||||
format get_format() const;
|
||||
const format format() const;
|
||||
|
||||
/// <summary>
|
||||
/// Applies the cell-level formatting of new_format to this cell.
|
||||
/// </summary>
|
||||
void set_format(const format &new_format);
|
||||
void format(const class format new_format);
|
||||
|
||||
/// <summary>
|
||||
/// Remove the cell-level formatting from this cell.
|
||||
|
@ -314,21 +305,21 @@ public:
|
|||
bool has_style() const;
|
||||
|
||||
/// <summary>
|
||||
/// Returns a reference to the named style applied to this cell.
|
||||
/// Returns a wrapper pointing to the named style applied to this cell.
|
||||
/// </summary>
|
||||
style get_style() const;
|
||||
const style style() const;
|
||||
|
||||
/// <summary>
|
||||
/// Equivalent to set_style(new_style.name())
|
||||
/// Equivalent to style(new_style.name())
|
||||
/// </summary>
|
||||
void set_style(const style &new_style);
|
||||
void style(const class style &new_style);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the named style applied to this cell to a style named style_name.
|
||||
/// If this style has not been previously created in the workbook, a
|
||||
/// key_not_found exception will be thrown.
|
||||
/// </summary>
|
||||
void set_style(const std::string &style_name);
|
||||
void style(const std::string &style_name);
|
||||
|
||||
/// <summary>
|
||||
/// Removes the named style from this cell.
|
||||
|
@ -506,13 +497,7 @@ private:
|
|||
/// Returns a non-const reference to the format of this cell.
|
||||
/// This is for internal use only.
|
||||
/// </summary>
|
||||
format &get_format_internal();
|
||||
|
||||
/// <summary>
|
||||
/// Use workbook::create_format() to create a new format then copy
|
||||
/// this cell's formatting to that new format and return it.
|
||||
/// </summary>
|
||||
format &duplicate_format();
|
||||
class format modifiable_format();
|
||||
|
||||
/// <summary>
|
||||
/// Private constructor to create a cell from its implementation.
|
||||
|
|
|
@ -1,94 +0,0 @@
|
|||
// Copyright (c) 2014-2016 Thomas Fussell
|
||||
// Copyright (c) 2010-2015 openpyxl
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, WRISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE
|
||||
//
|
||||
// @license: http://www.opensource.org/licenses/mit-license.php
|
||||
// @author: see AUTHORS file
|
||||
#pragma once
|
||||
|
||||
#include <xlnt/xlnt_config.hpp>
|
||||
#include <xlnt/styles/alignment.hpp>
|
||||
#include <xlnt/styles/border.hpp>
|
||||
#include <xlnt/styles/fill.hpp>
|
||||
#include <xlnt/styles/font.hpp>
|
||||
#include <xlnt/styles/number_format.hpp>
|
||||
#include <xlnt/styles/protection.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
/// <summary>
|
||||
/// Describes the formatting of a particular cell.
|
||||
/// </summary>
|
||||
class XLNT_API base_format
|
||||
{
|
||||
public:
|
||||
// Alignment
|
||||
class alignment &alignment();
|
||||
const class alignment &alignment() const;
|
||||
void alignment(const xlnt::alignment &new_alignment, bool applied);
|
||||
bool alignment_applied() const;
|
||||
|
||||
// Border
|
||||
virtual class border &border();
|
||||
virtual const class border &border() const;
|
||||
virtual void border(const xlnt::border &new_border, bool applied);
|
||||
bool border_applied() const;
|
||||
|
||||
// Fill
|
||||
virtual class fill &fill();
|
||||
virtual const class fill &fill() const;
|
||||
virtual void fill(const xlnt::fill &new_fill, bool applied);
|
||||
bool fill_applied() const;
|
||||
|
||||
// Font
|
||||
virtual class font &font();
|
||||
virtual const class font &font() const;
|
||||
virtual void font(const xlnt::font &new_font, bool applied);
|
||||
bool font_applied() const;
|
||||
|
||||
// Number Format
|
||||
virtual class number_format &number_format();
|
||||
virtual const class number_format &number_format() const;
|
||||
virtual void number_format(const xlnt::number_format &new_number_format, bool applied);
|
||||
bool number_format_applied() const;
|
||||
|
||||
// Protection
|
||||
class protection &protection();
|
||||
const class protection &protection() const;
|
||||
void protection(const xlnt::protection &new_protection, bool applied);
|
||||
bool protection_applied() const;
|
||||
|
||||
protected:
|
||||
class alignment alignment_;
|
||||
class border border_;
|
||||
class fill fill_;
|
||||
class font font_;
|
||||
class number_format number_format_;
|
||||
class protection protection_;
|
||||
|
||||
bool apply_alignment_ = false;
|
||||
bool apply_border_ = false;
|
||||
bool apply_fill_ = false;
|
||||
bool apply_font_ = false;
|
||||
bool apply_number_format_ = false;
|
||||
bool apply_protection_ = false;
|
||||
};
|
||||
|
||||
} // namespace xlnt
|
|
@ -26,7 +26,6 @@
|
|||
#include <string>
|
||||
|
||||
#include <xlnt/xlnt_config.hpp>
|
||||
#include <xlnt/styles/base_format.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
|
@ -46,42 +45,50 @@ struct stylesheet;
|
|||
/// <summary>
|
||||
/// Describes the formatting of a particular cell.
|
||||
/// </summary>
|
||||
class XLNT_API format : public base_format
|
||||
class XLNT_API format
|
||||
{
|
||||
public:
|
||||
std::size_t id() const;
|
||||
|
||||
class alignment &alignment();
|
||||
const class alignment &alignment() const;
|
||||
format alignment(const xlnt::alignment &new_alignment, bool applied);
|
||||
bool alignment_applied() const;
|
||||
|
||||
class border &border();
|
||||
const class border &border() const;
|
||||
format border(const xlnt::border &new_border, bool applied);
|
||||
bool border_applied() const;
|
||||
|
||||
class fill &fill();
|
||||
const class fill &fill() const;
|
||||
format fill(const xlnt::fill &new_fill, bool applied);
|
||||
bool fill_applied() const;
|
||||
|
||||
class font &font();
|
||||
const class font &font() const;
|
||||
format font(const xlnt::font &new_font, bool applied);
|
||||
bool font_applied() const;
|
||||
|
||||
class number_format &number_format();
|
||||
const class number_format &number_format() const;
|
||||
format number_format(const xlnt::number_format &new_number_format, bool applied);
|
||||
bool number_format_applied() const;
|
||||
|
||||
class protection &protection();
|
||||
const class protection &protection() const;
|
||||
format protection(const xlnt::protection &new_protection, bool applied);
|
||||
bool protection_applied() const;
|
||||
|
||||
bool has_style() const;
|
||||
void clear_style();
|
||||
void style(const std::string &name);
|
||||
void style(const xlnt::style &new_style);
|
||||
const class style &style() const;
|
||||
|
||||
class border &border() override;
|
||||
const class border &border() const override;
|
||||
void border(const xlnt::border &new_border, bool applied) override;
|
||||
|
||||
class fill &fill() override;
|
||||
const class fill &fill() const override;
|
||||
void fill(const xlnt::fill &new_fill, bool applied) override;
|
||||
|
||||
class font &font() override;
|
||||
const class font &font() const override;
|
||||
void font(const xlnt::font &new_font, bool applied) override;
|
||||
|
||||
class number_format &number_format() override;
|
||||
const class number_format &number_format() const override;
|
||||
void number_format(const xlnt::number_format &new_number_format, bool applied) override;
|
||||
|
||||
format &alignment_id(std::size_t id);
|
||||
format &border_id(std::size_t id);
|
||||
format &fill_id(std::size_t id);
|
||||
format &font_id(std::size_t id);
|
||||
format &number_format_id(std::size_t id);
|
||||
format &protection_id(std::size_t id);
|
||||
format style(const std::string &name);
|
||||
format style(const xlnt::style &new_style);
|
||||
const class style style() const;
|
||||
|
||||
private:
|
||||
friend struct detail::stylesheet;
|
||||
friend class cell;
|
||||
format(detail::format_impl *d);
|
||||
detail::format_impl *d_;
|
||||
};
|
||||
|
|
|
@ -27,42 +27,75 @@
|
|||
#include <string>
|
||||
|
||||
#include <xlnt/xlnt_config.hpp>
|
||||
#include <xlnt/styles/base_format.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
class alignment;
|
||||
class border;
|
||||
class cell;
|
||||
class fill;
|
||||
class font;
|
||||
class number_format;
|
||||
class protection;
|
||||
|
||||
namespace detail {
|
||||
struct style_impl;
|
||||
struct stylesheet;
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
/// <summary>
|
||||
/// Describes a style which has a name and can be applied to multiple individual
|
||||
/// formats. In Excel this is a "Cell Style".
|
||||
/// </summary>
|
||||
class XLNT_API style : public base_format
|
||||
class XLNT_API style
|
||||
{
|
||||
public:
|
||||
style() = delete;
|
||||
style(const style &other) = default;
|
||||
|
||||
std::string name() const;
|
||||
style &name(const std::string &name);
|
||||
style name(const std::string &name);
|
||||
|
||||
class alignment &alignment();
|
||||
const class alignment &alignment() const;
|
||||
style alignment(const xlnt::alignment &new_alignment, bool applied);
|
||||
bool alignment_applied() const;
|
||||
|
||||
class border &border();
|
||||
const class border &border() const;
|
||||
style border(const xlnt::border &new_border, bool applied);
|
||||
bool border_applied() const;
|
||||
|
||||
class fill &fill();
|
||||
const class fill &fill() const;
|
||||
style fill(const xlnt::fill &new_fill, bool applied);
|
||||
bool fill_applied() const;
|
||||
|
||||
class font &font();
|
||||
const class font &font() const;
|
||||
style font(const xlnt::font &new_font, bool applied);
|
||||
bool font_applied() const;
|
||||
|
||||
class number_format &number_format();
|
||||
const class number_format &number_format() const;
|
||||
style number_format(const xlnt::number_format &new_number_format, bool applied);
|
||||
bool number_format_applied() const;
|
||||
|
||||
class protection &protection();
|
||||
const class protection &protection() const;
|
||||
style protection(const xlnt::protection &new_protection, bool applied);
|
||||
bool protection_applied() const;
|
||||
|
||||
bool hidden() const;
|
||||
style &hidden(bool value);
|
||||
style hidden(bool value);
|
||||
|
||||
optional<bool> custom() const;
|
||||
style &custom(bool value);
|
||||
style custom(bool value);
|
||||
|
||||
optional<std::size_t> builtin_id() const;
|
||||
style &builtin_id(std::size_t builtin_id);
|
||||
style builtin_id(std::size_t builtin_id);
|
||||
|
||||
style &alignment_id(std::size_t id);
|
||||
style &border_id(std::size_t id);
|
||||
style &fill_id(std::size_t id);
|
||||
style &font_id(std::size_t id);
|
||||
style &number_format_id(std::size_t id);
|
||||
style &protection_id(std::size_t id);
|
||||
|
||||
bool operator==(const style &other);
|
||||
bool operator==(const style &other) const;
|
||||
|
||||
private:
|
||||
friend struct detail::stylesheet;
|
||||
|
|
|
@ -78,6 +78,13 @@ public:
|
|||
has_value_ = false;
|
||||
value_ = T();
|
||||
}
|
||||
|
||||
bool operator==(const optional<T> &other) const
|
||||
{
|
||||
return has_value_ == other.has_value_
|
||||
&& (!has_value_
|
||||
|| (has_value_ && value_ == other.value_));
|
||||
}
|
||||
|
||||
private:
|
||||
bool has_value_;
|
||||
|
|
|
@ -278,6 +278,11 @@ public:
|
|||
/// exception to be thrown.
|
||||
/// </summary>
|
||||
const_iterator cend() const;
|
||||
|
||||
/// <summary>
|
||||
/// Apply the function "f" to every non-empty cell in every worksheet in this workbook.
|
||||
/// </summary>
|
||||
void apply_to_cells(std::function<void(cell)> f);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a temporary vector containing the titles of each sheet in the order
|
||||
|
@ -417,17 +422,17 @@ public:
|
|||
|
||||
// formats
|
||||
|
||||
format &get_format(std::size_t format_index);
|
||||
const format &get_format(std::size_t format_index) const;
|
||||
format &create_format();
|
||||
format get_format(std::size_t format_index);
|
||||
const format get_format(std::size_t format_index) const;
|
||||
format create_format();
|
||||
void clear_formats();
|
||||
|
||||
// styles
|
||||
|
||||
bool has_style(const std::string &name) const;
|
||||
style &get_style(const std::string &name);
|
||||
const style &get_style(const std::string &name) const;
|
||||
style &create_style(const std::string &name);
|
||||
class style style(const std::string &name);
|
||||
const class style style(const std::string &name) const;
|
||||
class style create_style(const std::string &name);
|
||||
void clear_styles();
|
||||
|
||||
// manifest
|
||||
|
@ -488,11 +493,6 @@ private:
|
|||
|
||||
const detail::workbook_impl &impl() const;
|
||||
|
||||
/// <summary>
|
||||
/// Apply the function "f" to every cell in every worksheet in this workbook.
|
||||
/// </summary>
|
||||
void apply_to_cells(std::function<void(cell)> f);
|
||||
|
||||
void register_app_properties_in_manifest();
|
||||
|
||||
void register_core_properties_in_manifest();
|
||||
|
|
|
@ -56,7 +56,7 @@ if(MSVC)
|
|||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-unknown-pragmas")
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Weverything -Wno-c++98-compat -Wno-padded")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-padded")
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
|
|
|
@ -30,8 +30,14 @@
|
|||
#include <xlnt/cell/comment.hpp>
|
||||
#include <xlnt/cell/formatted_text.hpp>
|
||||
#include <xlnt/packaging/relationship.hpp>
|
||||
#include <xlnt/styles/alignment.hpp>
|
||||
#include <xlnt/styles/border.hpp>
|
||||
#include <xlnt/styles/color.hpp>
|
||||
#include <xlnt/styles/fill.hpp>
|
||||
#include <xlnt/styles/font.hpp>
|
||||
#include <xlnt/styles/format.hpp>
|
||||
#include <xlnt/styles/number_format.hpp>
|
||||
#include <xlnt/styles/protection.hpp>
|
||||
#include <xlnt/styles/style.hpp>
|
||||
#include <xlnt/utils/date.hpp>
|
||||
#include <xlnt/utils/datetime.hpp>
|
||||
|
@ -119,7 +125,7 @@ std::pair<bool, xlnt::time> cast_time(const std::string &s)
|
|||
result.hour = static_cast<int>(numeric_components[0]);
|
||||
result.minute = static_cast<int>(numeric_components[1]);
|
||||
|
||||
if (result.minute != numeric_components[1])
|
||||
if (std::fabs(static_cast<double>(result.minute) - numeric_components[1]) > std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
result.minute = result.hour;
|
||||
result.hour = 0;
|
||||
|
@ -142,12 +148,18 @@ namespace xlnt {
|
|||
const std::unordered_map<std::string, int> &cell::error_codes()
|
||||
{
|
||||
static const std::unordered_map<std::string, int> *codes =
|
||||
new std::unordered_map<std::string, int>({ { "#NULL!", 0 }, { "#DIV/0!", 1 }, { "#VALUE!", 2 },
|
||||
{ "#REF!", 3 }, { "#NAME?", 4 }, { "#NUM!", 5 },
|
||||
{ "#N/A!", 6 } });
|
||||
new std::unordered_map<std::string, int>({
|
||||
{ "#NULL!", 0 },
|
||||
{ "#DIV/0!", 1 },
|
||||
{ "#VALUE!", 2 },
|
||||
{ "#REF!", 3 },
|
||||
{ "#NAME?", 4 },
|
||||
{ "#NUM!", 5 },
|
||||
{ "#N/A!", 6 }
|
||||
});
|
||||
|
||||
return *codes;
|
||||
};
|
||||
}
|
||||
|
||||
std::string cell::check_string(const std::string &to_check)
|
||||
{
|
||||
|
@ -358,7 +370,7 @@ XLNT_API void cell::set_value(cell c)
|
|||
d_->value_text_ = c.d_->value_text_;
|
||||
d_->hyperlink_ = c.d_->hyperlink_;
|
||||
d_->formula_ = c.d_->formula_;
|
||||
d_->format_id_ = c.d_->format_id_;
|
||||
d_->format_ = c.d_->format_;
|
||||
}
|
||||
|
||||
template <>
|
||||
|
@ -438,7 +450,7 @@ bool cell::operator==(const cell &comparand) const
|
|||
cell &cell::operator=(const cell &rhs)
|
||||
{
|
||||
d_->column_ = rhs.d_->column_;
|
||||
d_->format_id_ = rhs.d_->format_id_;
|
||||
d_->format_ = rhs.d_->format_;
|
||||
d_->formula_ = rhs.d_->formula_;
|
||||
d_->hyperlink_ = rhs.d_->hyperlink_;
|
||||
d_->is_merged_ = rhs.d_->is_merged_;
|
||||
|
@ -608,34 +620,34 @@ void cell::set_data_type(type t)
|
|||
d_->type_ = t;
|
||||
}
|
||||
|
||||
number_format cell::get_computed_number_format() const
|
||||
number_format cell::computed_number_format() const
|
||||
{
|
||||
return get_computed_format().number_format();
|
||||
return xlnt::number_format();
|
||||
}
|
||||
|
||||
font cell::get_computed_font() const
|
||||
font cell::computed_font() const
|
||||
{
|
||||
return get_computed_format().font();
|
||||
return xlnt::font();
|
||||
}
|
||||
|
||||
fill cell::get_computed_fill() const
|
||||
fill cell::computed_fill() const
|
||||
{
|
||||
return get_computed_format().fill();
|
||||
return xlnt::fill();
|
||||
}
|
||||
|
||||
border cell::get_computed_border() const
|
||||
border cell::computed_border() const
|
||||
{
|
||||
return get_computed_format().border();
|
||||
return xlnt::border();
|
||||
}
|
||||
|
||||
alignment cell::get_computed_alignment() const
|
||||
alignment cell::computed_alignment() const
|
||||
{
|
||||
return get_computed_format().alignment();
|
||||
return xlnt::alignment();
|
||||
}
|
||||
|
||||
protection cell::get_computed_protection() const
|
||||
protection cell::computed_protection() const
|
||||
{
|
||||
return get_computed_format().protection();
|
||||
return xlnt::protection();
|
||||
}
|
||||
|
||||
void cell::clear_value()
|
||||
|
@ -649,7 +661,7 @@ void cell::clear_value()
|
|||
template <>
|
||||
XLNT_API bool cell::get_value() const
|
||||
{
|
||||
return d_->value_numeric_ != 0;
|
||||
return d_->value_numeric_ != 0.L;
|
||||
}
|
||||
|
||||
template <>
|
||||
|
@ -758,44 +770,38 @@ XLNT_API timedelta cell::get_value() const
|
|||
|
||||
void cell::set_alignment(const xlnt::alignment &alignment_)
|
||||
{
|
||||
auto &format = duplicate_format();
|
||||
format.alignment(alignment_, true);
|
||||
d_->format_id_ = format.id();
|
||||
auto new_format = has_format() ? modifiable_format() : get_workbook().create_format();
|
||||
format(new_format.alignment(alignment_, true));
|
||||
}
|
||||
|
||||
void cell::set_border(const xlnt::border &border_)
|
||||
{
|
||||
auto &format = duplicate_format();
|
||||
format.border(border_, true);
|
||||
d_->format_id_ = format.id();
|
||||
auto new_format = has_format() ? modifiable_format() : get_workbook().create_format();
|
||||
format(new_format.border(border_, true));
|
||||
}
|
||||
|
||||
void cell::set_fill(const xlnt::fill &fill_)
|
||||
{
|
||||
auto &format = duplicate_format();
|
||||
format.fill(fill_, true);
|
||||
d_->format_id_ = format.id();
|
||||
auto new_format = has_format() ? modifiable_format() : get_workbook().create_format();
|
||||
format(new_format.fill(fill_, true));
|
||||
}
|
||||
|
||||
void cell::set_font(const font &font_)
|
||||
{
|
||||
auto &format = duplicate_format();
|
||||
format.font(font_, true);
|
||||
d_->format_id_ = format.id();
|
||||
auto new_format = has_format() ? modifiable_format() : get_workbook().create_format();
|
||||
format(new_format.font(font_, true));
|
||||
}
|
||||
|
||||
void cell::set_number_format(const number_format &number_format_)
|
||||
{
|
||||
auto &format = duplicate_format();
|
||||
format.number_format(number_format_, true);
|
||||
d_->format_id_ = format.id();
|
||||
auto new_format = has_format() ? modifiable_format() : get_workbook().create_format();
|
||||
format(new_format.number_format(number_format_, true));
|
||||
}
|
||||
|
||||
void cell::set_protection(const xlnt::protection &protection_)
|
||||
{
|
||||
auto &format = duplicate_format();
|
||||
format.protection(protection_, true);
|
||||
d_->format_id_ = format.id();
|
||||
auto new_format = has_format() ? modifiable_format() : get_workbook().create_format();
|
||||
format(new_format.protection(protection_, true));
|
||||
}
|
||||
|
||||
template <>
|
||||
|
@ -817,7 +823,7 @@ bool cell::has_value() const
|
|||
|
||||
std::string cell::to_string() const
|
||||
{
|
||||
auto nf = get_computed_number_format();
|
||||
auto nf = computed_number_format();
|
||||
|
||||
switch (get_data_type())
|
||||
{
|
||||
|
@ -838,12 +844,12 @@ std::string cell::to_string() const
|
|||
|
||||
bool cell::has_format() const
|
||||
{
|
||||
return d_->format_id_.is_set();
|
||||
return d_->format_.is_set();
|
||||
}
|
||||
|
||||
void cell::set_format(const format &new_format)
|
||||
void cell::format(const class format new_format)
|
||||
{
|
||||
d_->format_id_ = new_format.id();
|
||||
d_->format_ = new_format.d_;
|
||||
}
|
||||
|
||||
calendar cell::get_base_date() const
|
||||
|
@ -891,157 +897,91 @@ void cell::guess_type_and_set_value(const std::string &value)
|
|||
|
||||
void cell::clear_format()
|
||||
{
|
||||
d_->format_id_.clear();
|
||||
d_->format_.clear();
|
||||
}
|
||||
|
||||
void cell::clear_style()
|
||||
{
|
||||
if (has_format())
|
||||
{
|
||||
get_format_internal().clear_style();
|
||||
modifiable_format().clear_style();
|
||||
}
|
||||
}
|
||||
|
||||
void cell::set_style(const style &new_style)
|
||||
void cell::style(const class style &new_style)
|
||||
{
|
||||
auto &new_format = duplicate_format();
|
||||
new_format.style(new_style);
|
||||
d_->format_id_ = new_format.id();
|
||||
auto new_format = has_format() ? format() : get_workbook().create_format();
|
||||
format(new_format.style(new_style));
|
||||
}
|
||||
|
||||
void cell::set_style(const std::string &style_name)
|
||||
void cell::style(const std::string &style_name)
|
||||
{
|
||||
auto &new_format = duplicate_format();
|
||||
new_format.style(get_workbook().get_style(style_name).name());
|
||||
d_->format_id_ = new_format.id();
|
||||
style(get_workbook().style(style_name));
|
||||
}
|
||||
|
||||
style cell::get_style() const
|
||||
const style cell::style() const
|
||||
{
|
||||
if (!has_format() || !get_format().has_style())
|
||||
if (!has_format() || !format().has_style())
|
||||
{
|
||||
throw invalid_attribute();
|
||||
}
|
||||
|
||||
return get_format().style();
|
||||
return format().style();
|
||||
}
|
||||
|
||||
bool cell::has_style() const
|
||||
{
|
||||
return has_format() && get_format().has_style();
|
||||
return has_format() && format().has_style();
|
||||
}
|
||||
|
||||
base_format cell::get_computed_format() const
|
||||
format cell::modifiable_format()
|
||||
{
|
||||
base_format result;
|
||||
|
||||
// Check style first
|
||||
|
||||
if (has_style())
|
||||
{
|
||||
style cell_style = get_style();
|
||||
|
||||
if (cell_style.alignment_applied()) result.alignment(cell_style.alignment(), true);
|
||||
if (cell_style.border_applied()) result.border(cell_style.border(), true);
|
||||
if (cell_style.fill_applied()) result.fill(cell_style.fill(), true);
|
||||
if (cell_style.font_applied()) result.font(cell_style.font(), true);
|
||||
if (cell_style.number_format_applied()) result.number_format(cell_style.number_format(), true);
|
||||
if (cell_style.protection_applied()) result.protection(cell_style.protection(), true);
|
||||
}
|
||||
|
||||
// Cell format overrides style
|
||||
|
||||
if (has_format())
|
||||
{
|
||||
format cell_format = get_format();
|
||||
|
||||
if (cell_format.alignment_applied()) result.alignment(cell_format.alignment(), true);
|
||||
if (cell_format.border_applied()) result.border(cell_format.border(), true);
|
||||
if (cell_format.fill_applied()) result.fill(cell_format.fill(), true);
|
||||
if (cell_format.font_applied()) result.font(cell_format.font(), true);
|
||||
if (cell_format.number_format_applied()) result.number_format(cell_format.number_format(), true);
|
||||
if (cell_format.protection_applied()) result.protection(cell_format.protection(), true);
|
||||
}
|
||||
|
||||
// Use defaults for any remaining non-applied components
|
||||
|
||||
if (!result.alignment_applied()) result.alignment(alignment(), true);
|
||||
if (!result.border_applied()) result.border(border(), true);
|
||||
if (!result.fill_applied()) result.fill(fill(), true);
|
||||
if (!result.font_applied()) result.font(font(), true);
|
||||
if (!result.number_format_applied()) result.number_format(number_format(), true);
|
||||
if (!result.protection_applied()) result.protection(protection(), true);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
format &cell::get_format_internal()
|
||||
{
|
||||
if (!d_->format_id_)
|
||||
if (!d_->format_)
|
||||
{
|
||||
throw invalid_attribute();
|
||||
}
|
||||
|
||||
return get_workbook().get_format(*d_->format_id_);
|
||||
return xlnt::format(*d_->format_);
|
||||
}
|
||||
|
||||
format &cell::duplicate_format()
|
||||
const format cell::format() const
|
||||
{
|
||||
auto &new_format = get_workbook().create_format();
|
||||
|
||||
if (has_format())
|
||||
{
|
||||
auto ¤t_format = get_format_internal();
|
||||
|
||||
new_format.alignment(current_format.alignment(), current_format.alignment_applied());
|
||||
new_format.border(current_format.border(), current_format.border_applied());
|
||||
new_format.fill(current_format.fill(), current_format.fill_applied());
|
||||
new_format.font(current_format.font(), current_format.font_applied());
|
||||
new_format.number_format(current_format.number_format(), current_format.number_format_applied());
|
||||
new_format.protection(current_format.protection(), current_format.protection_applied());
|
||||
}
|
||||
|
||||
return new_format;
|
||||
}
|
||||
|
||||
format cell::get_format() const
|
||||
{
|
||||
if (!d_->format_id_)
|
||||
if (!d_->format_)
|
||||
{
|
||||
throw invalid_attribute();
|
||||
}
|
||||
|
||||
return get_workbook().get_format(*d_->format_id_);
|
||||
return xlnt::format(*d_->format_);
|
||||
}
|
||||
|
||||
alignment cell::get_alignment() const
|
||||
{
|
||||
return get_format().alignment();
|
||||
return format().alignment();
|
||||
}
|
||||
|
||||
border cell::get_border() const
|
||||
{
|
||||
return get_format().border();
|
||||
return format().border();
|
||||
}
|
||||
|
||||
fill cell::get_fill() const
|
||||
{
|
||||
return get_format().fill();
|
||||
return format().fill();
|
||||
}
|
||||
|
||||
font cell::get_font() const
|
||||
{
|
||||
return get_format().font();
|
||||
return format().font();
|
||||
}
|
||||
|
||||
number_format cell::get_number_format() const
|
||||
{
|
||||
return get_format().number_format();
|
||||
return format().number_format();
|
||||
}
|
||||
|
||||
protection cell::get_protection() const
|
||||
{
|
||||
return get_format().protection();
|
||||
return format().protection();
|
||||
}
|
||||
|
||||
bool cell::has_hyperlink() const
|
||||
|
@ -1053,7 +993,7 @@ bool cell::has_hyperlink() const
|
|||
|
||||
bool cell::has_comment()
|
||||
{
|
||||
return (bool)d_->comment_;
|
||||
return d_->comment_.is_set();
|
||||
}
|
||||
|
||||
void cell::clear_comment()
|
||||
|
|
|
@ -18,18 +18,6 @@ public:
|
|||
wb_guess_types.set_guess_types(true);
|
||||
}
|
||||
|
||||
void test_temp()
|
||||
{
|
||||
xlnt::workbook wb;
|
||||
auto ws = wb.get_active_sheet();
|
||||
auto cell = ws.get_cell("A1");
|
||||
cell.set_value(3.141592);
|
||||
cell.set_font(xlnt::font().bold(true));
|
||||
cell.set_font(xlnt::font().size(20));
|
||||
wb.save("a.xlsx");
|
||||
wb.load("a.xlsx");
|
||||
}
|
||||
|
||||
void test_infer_numeric()
|
||||
{
|
||||
auto ws = wb_guess_types.create_sheet();
|
||||
|
@ -325,7 +313,7 @@ public:
|
|||
cell.set_font(font);
|
||||
|
||||
TS_ASSERT(cell.has_format());
|
||||
TS_ASSERT(cell.get_format().font_applied());
|
||||
TS_ASSERT(cell.format().font_applied());
|
||||
TS_ASSERT_EQUALS(cell.get_font(), font);
|
||||
}
|
||||
|
||||
|
@ -340,7 +328,7 @@ public:
|
|||
cell.set_fill(fill);
|
||||
|
||||
TS_ASSERT(cell.has_format());
|
||||
TS_ASSERT(cell.get_format().fill_applied());
|
||||
TS_ASSERT(cell.format().fill_applied());
|
||||
TS_ASSERT_EQUALS(cell.get_fill(), fill);
|
||||
}
|
||||
|
||||
|
@ -354,7 +342,7 @@ public:
|
|||
cell.set_border(border);
|
||||
|
||||
TS_ASSERT(cell.has_format());
|
||||
TS_ASSERT(cell.get_format().border_applied());
|
||||
TS_ASSERT(cell.format().border_applied());
|
||||
TS_ASSERT_EQUALS(cell.get_border(), border);
|
||||
}
|
||||
|
||||
|
@ -367,7 +355,7 @@ public:
|
|||
cell.set_number_format(format);
|
||||
|
||||
TS_ASSERT(cell.has_format());
|
||||
TS_ASSERT(cell.get_format().number_format_applied());
|
||||
TS_ASSERT(cell.format().number_format_applied());
|
||||
TS_ASSERT_EQUALS(cell.get_number_format().get_format_string(), "dd--hh--mm");
|
||||
}
|
||||
|
||||
|
@ -382,7 +370,7 @@ public:
|
|||
cell.set_alignment(align);
|
||||
|
||||
TS_ASSERT(cell.has_format());
|
||||
TS_ASSERT(cell.get_format().alignment_applied());
|
||||
TS_ASSERT(cell.format().alignment_applied());
|
||||
TS_ASSERT_EQUALS(cell.get_alignment(), align);
|
||||
}
|
||||
|
||||
|
@ -397,7 +385,7 @@ public:
|
|||
cell.set_protection(protection);
|
||||
|
||||
TS_ASSERT(cell.has_format());
|
||||
TS_ASSERT(cell.get_format().protection_applied());
|
||||
TS_ASSERT(cell.format().protection_applied());
|
||||
TS_ASSERT_EQUALS(cell.get_protection(), protection);
|
||||
|
||||
TS_ASSERT(cell.has_format());
|
||||
|
@ -412,34 +400,34 @@ public:
|
|||
|
||||
TS_ASSERT(!cell.has_style());
|
||||
|
||||
auto &test_style = wb.create_style("test_style");
|
||||
auto test_style = wb.create_style("test_style");
|
||||
test_style.number_format(xlnt::number_format::date_ddmmyyyy(), true);
|
||||
|
||||
cell.set_style(test_style);
|
||||
cell.style(test_style);
|
||||
TS_ASSERT(cell.has_style());
|
||||
TS_ASSERT_EQUALS(cell.get_style().number_format(), xlnt::number_format::date_ddmmyyyy());
|
||||
TS_ASSERT_EQUALS(cell.get_style(), test_style);
|
||||
TS_ASSERT_EQUALS(cell.style().number_format(), xlnt::number_format::date_ddmmyyyy());
|
||||
TS_ASSERT_EQUALS(cell.style(), test_style);
|
||||
|
||||
auto &other_style = wb.create_style("other_style");
|
||||
auto other_style = wb.create_style("other_style");
|
||||
other_style.number_format(xlnt::number_format::date_time2(), true);
|
||||
|
||||
cell.set_style("other_style");
|
||||
TS_ASSERT_EQUALS(cell.get_style().number_format(), xlnt::number_format::date_time2());
|
||||
TS_ASSERT_EQUALS(cell.get_style(), other_style);
|
||||
cell.style("other_style");
|
||||
TS_ASSERT_EQUALS(cell.style().number_format(), xlnt::number_format::date_time2());
|
||||
TS_ASSERT_EQUALS(cell.style(), other_style);
|
||||
|
||||
auto &last_style = wb.create_style("last_style");
|
||||
auto last_style = wb.create_style("last_style");
|
||||
last_style.number_format(xlnt::number_format::percentage(), true);
|
||||
|
||||
cell.set_style(last_style);
|
||||
TS_ASSERT_EQUALS(cell.get_style().number_format(), xlnt::number_format::percentage());
|
||||
TS_ASSERT_EQUALS(cell.get_style(), last_style);
|
||||
cell.style(last_style);
|
||||
TS_ASSERT_EQUALS(cell.style().number_format(), xlnt::number_format::percentage());
|
||||
TS_ASSERT_EQUALS(cell.style(), last_style);
|
||||
|
||||
TS_ASSERT_THROWS(cell.set_style("doesn't exist"), xlnt::key_not_found);
|
||||
TS_ASSERT_THROWS(cell.style("doesn't exist"), xlnt::key_not_found);
|
||||
|
||||
cell.clear_style();
|
||||
|
||||
TS_ASSERT(!cell.has_style());
|
||||
TS_ASSERT_THROWS(cell.get_style(), xlnt::invalid_attribute);
|
||||
TS_ASSERT_THROWS(cell.style(), xlnt::invalid_attribute);
|
||||
}
|
||||
|
||||
void test_print()
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
namespace xlnt {
|
||||
namespace detail {
|
||||
|
||||
struct format_impl;
|
||||
struct worksheet_impl;
|
||||
|
||||
struct cell_impl
|
||||
|
@ -54,7 +55,7 @@ struct cell_impl
|
|||
|
||||
optional<std::string> formula_;
|
||||
optional<std::string> hyperlink_;
|
||||
optional<std::size_t> format_id_;
|
||||
optional<format_impl *> format_;
|
||||
optional<comment> comment_;
|
||||
};
|
||||
|
||||
|
|
|
@ -427,6 +427,6 @@ const std::vector<std::uint8_t> &excel_thumbnail()
|
|||
};
|
||||
|
||||
return *data;
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -30,13 +30,36 @@ struct format_impl
|
|||
std::size_t id;
|
||||
|
||||
optional<std::size_t> alignment_id;
|
||||
bool alignment_applied = false;
|
||||
|
||||
optional<std::size_t> border_id;
|
||||
bool border_applied = false;
|
||||
|
||||
optional<std::size_t> fill_id;
|
||||
bool fill_applied = false;
|
||||
|
||||
optional<std::size_t> font_id;
|
||||
bool font_applied = false;
|
||||
|
||||
optional<std::size_t> number_format_id;
|
||||
bool number_format_applied = false;
|
||||
|
||||
optional<std::size_t> protection_id;
|
||||
bool protection_applied = false;
|
||||
|
||||
optional<std::string> style;
|
||||
|
||||
XLNT_API friend bool operator==(const format_impl &left, const format_impl &right)
|
||||
{
|
||||
return left.parent == right.parent
|
||||
&& left.alignment_id == right.alignment_id
|
||||
&& left.border_id == right.border_id
|
||||
&& left.fill_id == right.fill_id
|
||||
&& left.font_id == right.font_id
|
||||
&& left.number_format_id == right.number_format_id
|
||||
&& left.protection_id == right.protection_id
|
||||
&& left.style == right.style;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
|
|
@ -31,12 +31,23 @@ struct style_impl
|
|||
optional<std::size_t> builtin_id;
|
||||
optional<std::size_t> outline_style;
|
||||
|
||||
optional<class alignment> alignment;
|
||||
optional<class border> border;
|
||||
optional<class fill> fill;
|
||||
optional<class font> font;
|
||||
optional<class number_format> number_format;
|
||||
optional<class protection> protection;
|
||||
optional<std::size_t> alignment_id;
|
||||
bool alignment_applied = false;
|
||||
|
||||
optional<std::size_t> border_id;
|
||||
bool border_applied = false;
|
||||
|
||||
optional<std::size_t> fill_id;
|
||||
bool fill_applied = false;
|
||||
|
||||
optional<std::size_t> font_id;
|
||||
bool font_applied = false;
|
||||
|
||||
optional<std::size_t> number_format_id;
|
||||
bool number_format_applied = false;
|
||||
|
||||
optional<std::size_t> protection_id;
|
||||
bool protection_applied = false;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
|
|
@ -42,66 +42,54 @@ namespace detail {
|
|||
|
||||
struct stylesheet
|
||||
{
|
||||
~stylesheet()
|
||||
{
|
||||
}
|
||||
|
||||
format &create_format()
|
||||
format create_format()
|
||||
{
|
||||
format_impls.push_back(format_impl());
|
||||
auto &impl = format_impls.back();
|
||||
|
||||
impl.parent = this;
|
||||
impl.id = format_impls.size() - 1;
|
||||
|
||||
impl.border_id = 0;
|
||||
impl.fill_id = 0;
|
||||
impl.font_id = 0;
|
||||
impl.number_format_id = 0;
|
||||
|
||||
return format(&impl);
|
||||
}
|
||||
|
||||
format get_format(std::size_t index)
|
||||
{
|
||||
auto iter = format_impls.begin();
|
||||
std::advance(iter, index);
|
||||
return format(&*iter);
|
||||
}
|
||||
|
||||
class style create_style(const std::string &name)
|
||||
{
|
||||
auto &impl = style_impls.emplace(name, style_impl()).first->second;
|
||||
|
||||
impl.parent = this;
|
||||
impl.name = name;
|
||||
|
||||
impl.border_id = 0;
|
||||
impl.fill_id = 0;
|
||||
impl.font_id = 0;
|
||||
impl.number_format_id = 0;
|
||||
|
||||
formats.push_back(format(&impl));
|
||||
auto &format = formats.back();
|
||||
|
||||
return format;
|
||||
style_names.push_back(name);
|
||||
return xlnt::style(&impl);
|
||||
}
|
||||
|
||||
format &get_format(std::size_t index)
|
||||
class style style(const std::string &name)
|
||||
{
|
||||
return formats.at(index);
|
||||
}
|
||||
|
||||
style &create_style()
|
||||
{
|
||||
style_impls.push_back(style_impl());
|
||||
auto &impl = style_impls.back();
|
||||
impl.parent = this;
|
||||
styles.push_back(style(&impl));
|
||||
return styles.back();
|
||||
}
|
||||
|
||||
style &get_style(const std::string &name)
|
||||
{
|
||||
for (auto &s : styles)
|
||||
{
|
||||
if (s.name() == name)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
throw key_not_found();
|
||||
if (!has_style(name)) throw key_not_found();
|
||||
return xlnt::style(&style_impls[name]);
|
||||
}
|
||||
|
||||
bool has_style(const std::string &name)
|
||||
{
|
||||
for (auto &s : styles)
|
||||
{
|
||||
if (s.name() == name)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return style_impls.count(name) > 0;
|
||||
}
|
||||
|
||||
std::size_t next_custom_number_format_id() const
|
||||
|
@ -119,70 +107,290 @@ struct stylesheet
|
|||
return id;
|
||||
}
|
||||
|
||||
std::size_t add_border(const border &new_border)
|
||||
template<typename T, typename C>
|
||||
std::size_t find_or_add(C &container, const T &item)
|
||||
{
|
||||
std::size_t index = 0;
|
||||
std::size_t i = 0;
|
||||
|
||||
for (const border &f : borders)
|
||||
for (auto iter = container.begin(); iter != container.end(); ++iter)
|
||||
{
|
||||
if (f == new_border)
|
||||
if (*iter == item)
|
||||
{
|
||||
return index;
|
||||
return i;
|
||||
}
|
||||
|
||||
++index;
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
borders.push_back(new_border);
|
||||
container.emplace(container.end(), item);
|
||||
|
||||
return index;
|
||||
return container.size() - 1;
|
||||
}
|
||||
|
||||
std::size_t add_fill(const fill &new_fill)
|
||||
template<typename T>
|
||||
std::unordered_map<std::size_t, std::size_t> garbage_collect(
|
||||
const std::unordered_map<std::size_t, std::size_t> &reference_counts,
|
||||
std::vector<T> &container)
|
||||
{
|
||||
std::size_t index = 0;
|
||||
|
||||
for (const fill &f : fills)
|
||||
{
|
||||
if (f == new_fill)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
++index;
|
||||
}
|
||||
|
||||
fills.push_back(new_fill);
|
||||
std::unordered_map<std::size_t, std::size_t> id_map;
|
||||
std::size_t unreferenced = 0;
|
||||
const auto original_size = container.size();
|
||||
|
||||
return index;
|
||||
for (std::size_t i = 0; i < original_size; ++i)
|
||||
{
|
||||
id_map[i] = i - unreferenced;
|
||||
|
||||
if (reference_counts.count(i) == 0 || reference_counts.at(i) == 0)
|
||||
{
|
||||
container.erase(container.begin() + i - unreferenced);
|
||||
unreferenced++;
|
||||
}
|
||||
}
|
||||
|
||||
return id_map;
|
||||
}
|
||||
|
||||
std::size_t add_font(const font &new_font)
|
||||
void garbage_collect(std::size_t new_format, std::size_t old_format)
|
||||
{
|
||||
std::size_t index = 0;
|
||||
if (!garbage_collection_enabled) return;
|
||||
|
||||
std::unordered_map<std::size_t, std::size_t> format_reference_counts;
|
||||
|
||||
for (const font &f : fonts)
|
||||
for (const auto &impl : format_impls)
|
||||
{
|
||||
if (f == new_font)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
++index;
|
||||
format_reference_counts[impl.id] = 0;
|
||||
}
|
||||
|
||||
fonts.push_back(new_font);
|
||||
format_reference_counts[new_format]++;
|
||||
|
||||
parent->apply_to_cells([&format_reference_counts](cell c)
|
||||
{
|
||||
if (c.has_format())
|
||||
{
|
||||
format_reference_counts[c.format().id()]++;
|
||||
}
|
||||
});
|
||||
|
||||
if (format_reference_counts[old_format] > 0)
|
||||
{
|
||||
format_reference_counts[old_format]--;
|
||||
}
|
||||
|
||||
for (const auto &id_count_pair : format_reference_counts)
|
||||
{
|
||||
if (id_count_pair.second != 0) continue;
|
||||
|
||||
return index;
|
||||
auto target_id = id_count_pair.first;
|
||||
auto target = std::find_if(format_impls.begin(), format_impls.end(),
|
||||
[=](const format_impl &impl) { return impl.id == target_id; });
|
||||
format_impls.erase(target);
|
||||
}
|
||||
|
||||
std::size_t new_id = 0;
|
||||
|
||||
std::unordered_map<std::size_t, std::size_t> alignment_reference_counts;
|
||||
std::unordered_map<std::size_t, std::size_t> border_reference_counts;
|
||||
std::unordered_map<std::size_t, std::size_t> fill_reference_counts;
|
||||
std::unordered_map<std::size_t, std::size_t> font_reference_counts;
|
||||
std::unordered_map<std::size_t, std::size_t> number_format_reference_counts;
|
||||
std::unordered_map<std::size_t, std::size_t> protection_reference_counts;
|
||||
|
||||
for (auto &impl : format_impls)
|
||||
{
|
||||
impl.id = new_id++;
|
||||
|
||||
if (impl.alignment_id.is_set())
|
||||
{
|
||||
alignment_reference_counts[impl.alignment_id.get()]++;
|
||||
}
|
||||
|
||||
if (impl.border_id.is_set())
|
||||
{
|
||||
border_reference_counts[impl.border_id.get()]++;
|
||||
}
|
||||
|
||||
if (impl.fill_id.is_set())
|
||||
{
|
||||
fill_reference_counts[impl.fill_id.get()]++;
|
||||
}
|
||||
|
||||
if (impl.font_id.is_set())
|
||||
{
|
||||
font_reference_counts[impl.font_id.get()]++;
|
||||
}
|
||||
|
||||
if (impl.number_format_id.is_set())
|
||||
{
|
||||
number_format_reference_counts[impl.number_format_id.get()]++;
|
||||
}
|
||||
|
||||
if (impl.protection_id.is_set())
|
||||
{
|
||||
protection_reference_counts[impl.protection_id.get()]++;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &name_impl_pair : style_impls)
|
||||
{
|
||||
auto &impl = name_impl_pair.second;
|
||||
|
||||
if (impl.alignment_id.is_set())
|
||||
{
|
||||
alignment_reference_counts[impl.alignment_id.get()]++;
|
||||
}
|
||||
|
||||
if (impl.border_id.is_set())
|
||||
{
|
||||
border_reference_counts[impl.border_id.get()]++;
|
||||
}
|
||||
|
||||
if (impl.fill_id.is_set())
|
||||
{
|
||||
fill_reference_counts[impl.fill_id.get()]++;
|
||||
}
|
||||
|
||||
if (impl.font_id.is_set())
|
||||
{
|
||||
font_reference_counts[impl.font_id.get()]++;
|
||||
}
|
||||
|
||||
if (impl.number_format_id.is_set())
|
||||
{
|
||||
number_format_reference_counts[impl.number_format_id.get()]++;
|
||||
}
|
||||
|
||||
if (impl.protection_id.is_set())
|
||||
{
|
||||
protection_reference_counts[impl.protection_id.get()]++;
|
||||
}
|
||||
}
|
||||
|
||||
auto alignment_id_map = garbage_collect(alignment_reference_counts, alignments);
|
||||
auto border_id_map = garbage_collect(border_reference_counts, borders);
|
||||
auto fill_id_map = garbage_collect(fill_reference_counts, fills);
|
||||
auto font_id_map = garbage_collect(font_reference_counts, fonts);
|
||||
auto number_format_id_map = garbage_collect(number_format_reference_counts, number_formats);
|
||||
auto protection_id_map = garbage_collect(protection_reference_counts, protections);
|
||||
|
||||
for (auto &impl : format_impls)
|
||||
{
|
||||
if (impl.alignment_id.is_set())
|
||||
{
|
||||
impl.alignment_id = alignment_id_map[impl.alignment_id.get()];
|
||||
}
|
||||
|
||||
if (impl.border_id.is_set())
|
||||
{
|
||||
impl.border_id = border_id_map[impl.border_id.get()];
|
||||
}
|
||||
|
||||
if (impl.fill_id.is_set())
|
||||
{
|
||||
impl.fill_id = fill_id_map[impl.fill_id.get()];
|
||||
}
|
||||
|
||||
if (impl.font_id.is_set())
|
||||
{
|
||||
impl.font_id = font_id_map[impl.font_id.get()];
|
||||
}
|
||||
|
||||
if (impl.number_format_id.is_set())
|
||||
{
|
||||
impl.number_format_id = number_format_id_map[impl.number_format_id.get()];
|
||||
}
|
||||
|
||||
if (impl.protection_id.is_set())
|
||||
{
|
||||
impl.protection_id = protection_id_map[impl.protection_id.get()];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
format_impl *find_or_create(const format_impl &pattern)
|
||||
{
|
||||
auto iter = format_impls.begin();
|
||||
auto id = find_or_add(format_impls, pattern);
|
||||
std::advance(iter, id);
|
||||
|
||||
auto &result = *iter;
|
||||
|
||||
result.parent = this;
|
||||
result.id = id;
|
||||
|
||||
if (id != pattern.id)
|
||||
{
|
||||
garbage_collect(id, pattern.id);
|
||||
}
|
||||
|
||||
return &result;
|
||||
}
|
||||
|
||||
format_impl *find_or_create_with(format_impl *pattern, const alignment &new_alignment, bool applied)
|
||||
{
|
||||
format_impl new_format = *pattern;
|
||||
new_format.alignment_id = find_or_add(alignments, new_alignment);
|
||||
new_format.alignment_applied = applied;
|
||||
|
||||
return find_or_create(new_format);
|
||||
}
|
||||
|
||||
format_impl *find_or_create_with(format_impl *pattern, const border &new_border, bool applied)
|
||||
{
|
||||
format_impl new_format = *pattern;
|
||||
new_format.border_id = find_or_add(borders, new_border);
|
||||
new_format.border_applied = applied;
|
||||
|
||||
return find_or_create(new_format);
|
||||
}
|
||||
|
||||
format_impl *find_or_create_with(format_impl *pattern, const fill &new_fill, bool applied)
|
||||
{
|
||||
format_impl new_format = *pattern;
|
||||
new_format.fill_id = find_or_add(fills, new_fill);
|
||||
new_format.fill_applied = applied;
|
||||
|
||||
return find_or_create(new_format);
|
||||
}
|
||||
|
||||
format_impl *find_or_create_with(format_impl *pattern, const font &new_font, bool applied)
|
||||
{
|
||||
format_impl new_format = *pattern;
|
||||
new_format.font_id = find_or_add(fonts, new_font);
|
||||
new_format.font_applied = applied;
|
||||
|
||||
return find_or_create(new_format);
|
||||
}
|
||||
|
||||
format_impl *find_or_create_with(format_impl *pattern, const number_format &new_number_format, bool applied)
|
||||
{
|
||||
format_impl new_format = *pattern;
|
||||
new_format.number_format_id = find_or_add(number_formats, new_number_format);
|
||||
new_format.number_format_applied = applied;
|
||||
|
||||
return find_or_create(new_format);
|
||||
}
|
||||
|
||||
format_impl *find_or_create_with(format_impl *pattern, const protection &new_protection, bool applied)
|
||||
{
|
||||
format_impl new_format = *pattern;
|
||||
new_format.protection_id = find_or_add(protections, new_protection);
|
||||
new_format.protection_applied = applied;
|
||||
|
||||
return find_or_create(new_format);
|
||||
}
|
||||
|
||||
std::size_t style_index(const std::string &name) const
|
||||
{
|
||||
return std::distance(style_names.begin(),
|
||||
std::find(style_names.begin(), style_names.end(), name));
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
format_impls.clear();
|
||||
formats.clear();
|
||||
|
||||
style_impls.clear();
|
||||
styles.clear();
|
||||
style_names.clear();
|
||||
|
||||
alignments.clear();
|
||||
borders.clear();
|
||||
|
@ -193,64 +401,24 @@ struct stylesheet
|
|||
|
||||
colors.clear();
|
||||
}
|
||||
|
||||
format_impl *deduplicate(format_impl *f)
|
||||
|
||||
void enable_garbage_collection()
|
||||
{
|
||||
std::unordered_map<format_impl *, std::size_t> reference_counts;
|
||||
garbage_collection_enabled = true;
|
||||
}
|
||||
|
||||
for (auto ws : *parent)
|
||||
{
|
||||
auto dimension = ws.calculate_dimension();
|
||||
|
||||
for (auto row = dimension.get_top_left().get_row(); row <= dimension.get_bottom_right().get_row(); row++)
|
||||
{
|
||||
for (auto column = dimension.get_top_left().get_column(); column <= dimension.get_bottom_right().get_column(); column++)
|
||||
{
|
||||
if (ws.has_cell(cell_reference(column, row)))
|
||||
{
|
||||
auto cell = ws.get_cell(cell_reference(column, row));
|
||||
|
||||
if (cell.has_format())
|
||||
{
|
||||
reference_counts[formats.at(cell.get_format().id()).d_]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto result = f;
|
||||
|
||||
for (auto &impl : format_impls)
|
||||
{
|
||||
if (reference_counts[&impl] == 0 && &impl != f)
|
||||
{
|
||||
result = &impl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if (result != f)
|
||||
{
|
||||
auto impl_iter = std::find_if(format_impls.begin(), format_impls.end(),
|
||||
[=](const format_impl &impl) { return &impl == f; });
|
||||
auto index = std::distance(format_impls.begin(), impl_iter);
|
||||
formats.erase(formats.begin() + index);
|
||||
format_impls.erase(impl_iter);
|
||||
}
|
||||
*/
|
||||
|
||||
return f;
|
||||
void disable_garbage_collection()
|
||||
{
|
||||
garbage_collection_enabled = false;
|
||||
}
|
||||
|
||||
workbook *parent;
|
||||
|
||||
bool garbage_collection_enabled = true;
|
||||
|
||||
std::list<format_impl> format_impls;
|
||||
std::vector<format> formats;
|
||||
|
||||
std::list<style_impl> style_impls;
|
||||
std::vector<style> styles;
|
||||
std::unordered_map<std::string, style_impl> style_impls;
|
||||
std::vector<std::string> style_names;
|
||||
|
||||
std::vector<alignment> alignments;
|
||||
std::vector<border> borders;
|
||||
|
|
|
@ -1296,13 +1296,16 @@ void xlsx_consumer::read_stylesheet()
|
|||
auto &data = *style_datas.emplace(style_datas.end());
|
||||
|
||||
parser().next_expect(xml::parser::event_type::start_element, xmlns, "cellStyle");
|
||||
|
||||
data.name = parser().attribute("name");
|
||||
data.record_id = parser().attribute<std::size_t>("xfId");
|
||||
data.builtin_id = parser().attribute<std::size_t>("builtinId");
|
||||
|
||||
if (parser().attribute_present("customBuiltin"))
|
||||
{
|
||||
data.custom_builtin = parser().attribute("customBuiltin") == "1";
|
||||
data.custom_builtin = is_true(parser().attribute("customBuiltin"));
|
||||
}
|
||||
|
||||
parser().next_expect(xml::parser::event_type::end_element, xmlns, "cellStyle");
|
||||
}
|
||||
|
||||
|
@ -1530,14 +1533,13 @@ void xlsx_consumer::read_stylesheet()
|
|||
|
||||
for (const auto &record : style_records)
|
||||
{
|
||||
auto &new_style = stylesheet.create_style();
|
||||
auto style_data_iter = std::find_if(style_datas.begin(), style_datas.end(),
|
||||
[&xf_id](const style_data &s) { return s.record_id == xf_id; });
|
||||
++xf_id;
|
||||
|
||||
if (style_data_iter == style_datas.end()) continue;
|
||||
|
||||
new_style.name(style_data_iter->name);
|
||||
auto new_style = stylesheet.create_style(style_data_iter->name);
|
||||
new_style.builtin_id(style_data_iter->builtin_id);
|
||||
|
||||
new_style.alignment(record.alignment.first, record.alignment.second);
|
||||
|
@ -1548,18 +1550,33 @@ void xlsx_consumer::read_stylesheet()
|
|||
new_style.protection(record.protection.first, record.protection.second);
|
||||
}
|
||||
|
||||
std::size_t record_index = 0;
|
||||
|
||||
for (const auto &record : format_records)
|
||||
{
|
||||
auto &new_format = stylesheet.create_format();
|
||||
stylesheet.format_impls.push_back(format_impl());
|
||||
auto &new_format = stylesheet.format_impls.back();
|
||||
|
||||
new_format.style(stylesheet.styles.at(record.style_id.first).name());
|
||||
new_format.id = record_index++;
|
||||
new_format.parent = &stylesheet;
|
||||
|
||||
if (record.style_id.second)
|
||||
{
|
||||
new_format.style = stylesheet.style_names[record.style_id.first];
|
||||
}
|
||||
|
||||
new_format.alignment(record.alignment.first, record.alignment.second);
|
||||
new_format.border(stylesheet.borders.at(record.border_id.first), record.border_id.second);
|
||||
new_format.fill(stylesheet.fills.at(record.fill_id.first), record.fill_id.second);
|
||||
new_format.font(stylesheet.fonts.at(record.font_id.first), record.font_id.second);
|
||||
new_format.number_format(lookup_number_format(record.number_format_id.first), record.number_format_id.second);
|
||||
new_format.protection(record.protection.first, record.protection.second);
|
||||
new_format.alignment_id = stylesheet.find_or_add(stylesheet.alignments, record.alignment.first);
|
||||
new_format.alignment_applied = record.alignment.second;
|
||||
new_format.border_id = record.border_id.first;
|
||||
new_format.border_applied = record.border_id.second;
|
||||
new_format.fill_id = record.fill_id.first;
|
||||
new_format.fill_applied = record.fill_id.second;
|
||||
new_format.font_id = record.font_id.first;
|
||||
new_format.font_applied = record.font_id.second;
|
||||
new_format.number_format_id = record.number_format_id.first;
|
||||
new_format.number_format_applied = record.number_format_id.second;
|
||||
new_format.protection_id = stylesheet.find_or_add(stylesheet.protections, record.protection.first);
|
||||
new_format.protection_applied = record.protection.second;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1845,7 +1862,7 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id)
|
|||
|
||||
if (has_format)
|
||||
{
|
||||
cell.set_format(target_.get_format(format_id));
|
||||
cell.format(target_.get_format(format_id));
|
||||
}
|
||||
|
||||
parser().next_expect(xml::parser::event_type::end_element, xmlns, "c");
|
||||
|
|
|
@ -101,7 +101,7 @@ struct crypto_helper
|
|||
auto decoded = pipe.read_all();
|
||||
|
||||
return std::vector<std::uint8_t>(decoded.begin(), decoded.end());
|
||||
};
|
||||
}
|
||||
|
||||
static std::vector<std::uint8_t> hash(hash_algorithm algorithm,
|
||||
const std::vector<std::uint8_t> &input)
|
||||
|
@ -112,7 +112,7 @@ struct crypto_helper
|
|||
auto hash = pipe.read_all();
|
||||
|
||||
return std::vector<std::uint8_t>(hash.begin(), hash.end());
|
||||
};
|
||||
}
|
||||
|
||||
static std::vector<std::uint8_t> get_file(POLE::Storage &storage, const std::string &name)
|
||||
{
|
||||
|
@ -130,7 +130,7 @@ struct crypto_helper
|
|||
index += sizeof(T);
|
||||
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
struct standard_encryption_info
|
||||
{
|
||||
|
|
|
@ -148,19 +148,14 @@ void xlsx_producer::end_part()
|
|||
{
|
||||
current_part_serializer_.reset();
|
||||
}
|
||||
|
||||
if (current_part_stream_)
|
||||
{
|
||||
current_part_stream_.reset();
|
||||
}
|
||||
|
||||
archive_->close();
|
||||
}
|
||||
|
||||
void xlsx_producer::begin_part(const path &part)
|
||||
{
|
||||
end_part();
|
||||
|
||||
current_part_stream_.reset(archive_->open(part.string()));
|
||||
current_part_serializer_.reset(new xml::serializer(*current_part_stream_, part.string()));
|
||||
current_part_serializer_.reset(new xml::serializer(archive_->open(part.string()), part.string()));
|
||||
}
|
||||
|
||||
// Package Parts
|
||||
|
@ -770,11 +765,15 @@ void xlsx_producer::write_styles(const relationship &rel)
|
|||
{
|
||||
const auto &number_formats = stylesheet.number_formats;
|
||||
|
||||
auto num_custom = std::count_if(number_formats.begin(), number_formats.end(),
|
||||
[](const number_format &nf) { return nf.get_id() >= 164; });
|
||||
|
||||
serializer().start_element(xmlns, "numFmts");
|
||||
serializer().attribute("count", number_formats.size());
|
||||
serializer().attribute("count", num_custom);
|
||||
|
||||
for (const auto &num_fmt : number_formats)
|
||||
{
|
||||
if (num_fmt.get_id() < 164) continue;
|
||||
serializer().start_element(xmlns, "numFmt");
|
||||
serializer().attribute("numFmtId", num_fmt.get_id());
|
||||
serializer().attribute("formatCode", num_fmt.get_format_string());
|
||||
|
@ -1020,68 +1019,90 @@ void xlsx_producer::write_styles(const relationship &rel)
|
|||
// Style XFs
|
||||
|
||||
serializer().start_element(xmlns, "cellStyleXfs");
|
||||
serializer().attribute("count", stylesheet.styles.size());
|
||||
serializer().attribute("count", stylesheet.style_impls.size());
|
||||
|
||||
for (auto ¤t_style : stylesheet.styles)
|
||||
for (auto ¤t_style_name_impl : stylesheet.style_impls)
|
||||
{
|
||||
auto ¤t_style_impl = current_style_name_impl.second;
|
||||
|
||||
serializer().start_element(xmlns, "xf");
|
||||
serializer().attribute("numFmtId", current_style.number_format().get_id());
|
||||
serializer().attribute("fontId", std::distance(stylesheet.fonts.begin(),
|
||||
std::find(stylesheet.fonts.begin(), stylesheet.fonts.end(), current_style.font())));
|
||||
serializer().attribute("fillId", std::distance(stylesheet.fills.begin(),
|
||||
std::find(stylesheet.fills.begin(), stylesheet.fills.end(), current_style.fill())));
|
||||
serializer().attribute("borderId", std::distance(stylesheet.borders.begin(),
|
||||
std::find(stylesheet.borders.begin(), stylesheet.borders.end(), current_style.border())));
|
||||
serializer().attribute("numFmtId", current_style_impl.number_format_id.get());
|
||||
serializer().attribute("fontId", current_style_impl.font_id.get());
|
||||
serializer().attribute("fillId", current_style_impl.fill_id.get());
|
||||
serializer().attribute("borderId", current_style_impl.border_id.get());
|
||||
|
||||
if (current_style.number_format_applied()) serializer().attribute("applyNumberFormat", write_bool(true));
|
||||
if (current_style.fill_applied()) serializer().attribute("applyFill", write_bool(true));
|
||||
if (current_style.font_applied()) serializer().attribute("applyFont", write_bool(true));
|
||||
if (current_style.border_applied()) serializer().attribute("applyBorder", write_bool(true));
|
||||
if (current_style.alignment_applied()) serializer().attribute("applyAlignment", write_bool(true));
|
||||
if (current_style.protection_applied()) serializer().attribute("applyProtection", write_bool(true));
|
||||
if (current_style_impl.number_format_applied)
|
||||
{
|
||||
serializer().attribute("applyNumberFormat", write_bool(true));
|
||||
}
|
||||
|
||||
if (current_style.alignment_applied())
|
||||
if (current_style_impl.fill_applied)
|
||||
{
|
||||
serializer().attribute("applyFill", write_bool(true));
|
||||
}
|
||||
|
||||
if (current_style_impl.font_applied)
|
||||
{
|
||||
serializer().attribute("applyFont", write_bool(true));
|
||||
}
|
||||
|
||||
if (current_style_impl.border_applied)
|
||||
{
|
||||
serializer().attribute("applyBorder", write_bool(true));
|
||||
}
|
||||
|
||||
if (current_style_impl.alignment_applied)
|
||||
{
|
||||
serializer().attribute("applyAlignment", write_bool(true));
|
||||
}
|
||||
|
||||
if (current_style_impl.protection_applied)
|
||||
{
|
||||
serializer().attribute("applyProtection", write_bool(true));
|
||||
}
|
||||
|
||||
if (current_style_impl.alignment_applied)
|
||||
{
|
||||
const auto current_alignment = current_style.alignment();
|
||||
const auto ¤t_alignment = stylesheet.alignments[current_style_impl.alignment_id.get()];
|
||||
|
||||
serializer().start_element(xmlns, "alignment");
|
||||
|
||||
if (current_alignment.vertical())
|
||||
{
|
||||
serializer().attribute("vertical", *current_alignment.vertical());
|
||||
serializer().attribute("vertical", current_alignment.vertical().get());
|
||||
}
|
||||
|
||||
if (current_alignment.horizontal())
|
||||
{
|
||||
serializer().attribute("horizontal", *current_alignment.horizontal());
|
||||
serializer().attribute("horizontal", current_alignment.horizontal().get());
|
||||
}
|
||||
|
||||
if (current_alignment.rotation())
|
||||
{
|
||||
serializer().attribute("textRotation", *current_alignment.rotation());
|
||||
serializer().attribute("textRotation", current_alignment.rotation().get());
|
||||
}
|
||||
|
||||
if (current_alignment.wrap())
|
||||
{
|
||||
serializer().attribute("wrapText", write_bool(*current_alignment.wrap()));
|
||||
serializer().attribute("wrapText", write_bool(current_alignment.wrap().get()));
|
||||
}
|
||||
|
||||
if (current_alignment.indent())
|
||||
{
|
||||
serializer().attribute("indent", *current_alignment.indent());
|
||||
serializer().attribute("indent", current_alignment.indent().get());
|
||||
}
|
||||
|
||||
if (current_alignment.shrink())
|
||||
{
|
||||
serializer().attribute("shrinkToFit", write_bool(*current_alignment.shrink()));
|
||||
serializer().attribute("shrinkToFit", write_bool(current_alignment.shrink().get()));
|
||||
}
|
||||
|
||||
serializer().end_element(xmlns, "alignment");
|
||||
}
|
||||
|
||||
if (current_style.protection_applied())
|
||||
if (current_style_impl.protection_applied)
|
||||
{
|
||||
const auto current_protection = current_style.protection();
|
||||
const auto ¤t_protection = stylesheet.protections[current_style_impl.protection_id.get()];
|
||||
|
||||
serializer().start_element(xmlns, "protection");
|
||||
serializer().attribute("locked", write_bool(current_protection.locked()));
|
||||
|
@ -1097,36 +1118,54 @@ void xlsx_producer::write_styles(const relationship &rel)
|
|||
// Format XFs
|
||||
|
||||
serializer().start_element(xmlns, "cellXfs");
|
||||
serializer().attribute("count", stylesheet.formats.size());
|
||||
serializer().attribute("count", stylesheet.format_impls.size());
|
||||
|
||||
for (auto ¤t_format : stylesheet.formats)
|
||||
for (auto ¤t_format_impl : stylesheet.format_impls)
|
||||
{
|
||||
serializer().start_element(xmlns, "xf");
|
||||
serializer().attribute("numFmtId", current_format.number_format().get_id());
|
||||
serializer().attribute("fontId", std::distance(stylesheet.fonts.begin(),
|
||||
std::find(stylesheet.fonts.begin(), stylesheet.fonts.end(), current_format.font())));
|
||||
serializer().attribute("fillId", std::distance(stylesheet.fills.begin(),
|
||||
std::find(stylesheet.fills.begin(), stylesheet.fills.end(), current_format.fill())));
|
||||
serializer().attribute("borderId", std::distance(stylesheet.borders.begin(),
|
||||
std::find(stylesheet.borders.begin(), stylesheet.borders.end(), current_format.border())));
|
||||
serializer().start_element(xmlns, "xf");
|
||||
serializer().attribute("numFmtId", current_format_impl.number_format_id.get());
|
||||
serializer().attribute("fontId", current_format_impl.font_id.get());
|
||||
serializer().attribute("fillId", current_format_impl.fill_id.get());
|
||||
serializer().attribute("borderId", current_format_impl.border_id.get());
|
||||
|
||||
if (current_format.number_format_applied()) serializer().attribute("applyNumberFormat", write_bool(true));
|
||||
if (current_format.fill_applied()) serializer().attribute("applyFill", write_bool(true));
|
||||
if (current_format.font_applied()) serializer().attribute("applyFont", write_bool(true));
|
||||
if (current_format.border_applied()) serializer().attribute("applyBorder", write_bool(true));
|
||||
if (current_format.alignment_applied()) serializer().attribute("applyAlignment", write_bool(true));
|
||||
if (current_format.protection_applied()) serializer().attribute("applyProtection", write_bool(true));
|
||||
if (current_format_impl.number_format_applied)
|
||||
{
|
||||
serializer().attribute("applyNumberFormat", write_bool(true));
|
||||
}
|
||||
|
||||
if (current_format.has_style())
|
||||
if (current_format_impl.fill_applied)
|
||||
{
|
||||
serializer().attribute("applyFill", write_bool(true));
|
||||
}
|
||||
|
||||
if (current_format_impl.font_applied)
|
||||
{
|
||||
serializer().attribute("applyFont", write_bool(true));
|
||||
}
|
||||
|
||||
if (current_format_impl.border_applied)
|
||||
{
|
||||
serializer().attribute("applyBorder", write_bool(true));
|
||||
}
|
||||
|
||||
if (current_format_impl.alignment_applied)
|
||||
{
|
||||
serializer().attribute("applyAlignment", write_bool(true));
|
||||
}
|
||||
|
||||
if (current_format_impl.protection_applied)
|
||||
{
|
||||
serializer().attribute("applyProtection", write_bool(true));
|
||||
}
|
||||
|
||||
if (current_format_impl.style.is_set())
|
||||
{
|
||||
serializer().attribute("xfId", std::distance(stylesheet.styles.begin(),
|
||||
std::find_if(stylesheet.styles.begin(), stylesheet.styles.end(),
|
||||
[&](const xlnt::style &s) { return s.name() == current_format.style().name(); })));
|
||||
serializer().attribute("xfId", stylesheet.style_index(current_format_impl.style.get()));
|
||||
}
|
||||
|
||||
if (current_format.alignment_applied())
|
||||
if (current_format_impl.alignment_applied)
|
||||
{
|
||||
const auto current_alignment = current_format.alignment();
|
||||
const auto ¤t_alignment = stylesheet.alignments[current_format_impl.alignment_id.get()];
|
||||
|
||||
serializer().start_element(xmlns, "alignment");
|
||||
|
||||
|
@ -1163,9 +1202,9 @@ void xlsx_producer::write_styles(const relationship &rel)
|
|||
serializer().end_element(xmlns, "alignment");
|
||||
}
|
||||
|
||||
if (current_format.protection_applied())
|
||||
if (current_format_impl.protection_applied)
|
||||
{
|
||||
const auto current_protection = current_format.protection();
|
||||
const auto ¤t_protection = stylesheet.protections[current_format_impl.protection_id.get()];
|
||||
|
||||
serializer().start_element(xmlns, "protection");
|
||||
serializer().attribute("locked", write_bool(current_protection.locked()));
|
||||
|
@ -1181,29 +1220,31 @@ void xlsx_producer::write_styles(const relationship &rel)
|
|||
// Styles
|
||||
|
||||
serializer().start_element(xmlns, "cellStyles");
|
||||
serializer().attribute("count", stylesheet.styles.size());
|
||||
serializer().attribute("count", stylesheet.style_impls.size());
|
||||
std::size_t style_index = 0;
|
||||
|
||||
for (auto ¤t_style : stylesheet.styles)
|
||||
for (auto ¤t_style_name : stylesheet.style_names)
|
||||
{
|
||||
const auto ¤t_style = stylesheet.style_impls.at(current_style_name);
|
||||
|
||||
serializer().start_element(xmlns, "cellStyle");
|
||||
|
||||
serializer().attribute("name", current_style.name());
|
||||
serializer().attribute("name", current_style.name);
|
||||
serializer().attribute("xfId", style_index++);
|
||||
|
||||
if (current_style.builtin_id())
|
||||
if (current_style.builtin_id)
|
||||
{
|
||||
serializer().attribute("builtinId", *current_style.builtin_id());
|
||||
serializer().attribute("builtinId", current_style.builtin_id.get());
|
||||
}
|
||||
|
||||
if (current_style.hidden())
|
||||
if (current_style.hidden_style)
|
||||
{
|
||||
serializer().attribute("hidden", write_bool(true));
|
||||
}
|
||||
|
||||
if (current_style.custom())
|
||||
if (current_style.custom_builtin)
|
||||
{
|
||||
serializer().attribute("customBuiltin", write_bool(*current_style.custom()));
|
||||
serializer().attribute("customBuiltin", write_bool(current_style.custom_builtin.get()));
|
||||
}
|
||||
|
||||
serializer().end_element(xmlns, "cellStyle");
|
||||
|
@ -1972,7 +2013,7 @@ void xlsx_producer::write_worksheet(const relationship &rel)
|
|||
|
||||
if (cell.has_format())
|
||||
{
|
||||
serializer().attribute("s", cell.get_format().id());
|
||||
serializer().attribute("s", cell.format().id());
|
||||
}
|
||||
|
||||
if (cell.get_data_type() == cell::type::string)
|
||||
|
@ -2510,9 +2551,8 @@ void xlsx_producer::write_thumbnail(const relationship &rel)
|
|||
end_part();
|
||||
|
||||
const auto &thumbnail = source_.get_thumbnail();
|
||||
current_part_stream_.reset(archive_->open(rel.get_target().get_path().string()));
|
||||
vector_istreambuf thumbnail_buffer(thumbnail);
|
||||
*current_part_stream_ << &thumbnail_buffer;
|
||||
archive_->open(rel.get_target().get_path().string()) << &thumbnail_buffer;
|
||||
}
|
||||
|
||||
xml::serializer &xlsx_producer::serializer()
|
||||
|
|
|
@ -136,7 +136,6 @@ private:
|
|||
const workbook &source_;
|
||||
|
||||
ZipFileWriter *archive_;
|
||||
std::unique_ptr<std::ostream> current_part_stream_;
|
||||
std::unique_ptr<xml::serializer> current_part_serializer_;
|
||||
};
|
||||
|
||||
|
|
|
@ -35,12 +35,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
|||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <iterator> // for std::back_inserter
|
||||
#include <stdexcept>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
extern "C" {
|
||||
|
@ -52,7 +52,7 @@ extern "C" {
|
|||
namespace xlnt {
|
||||
namespace detail {
|
||||
|
||||
template<class T>
|
||||
template <class T>
|
||||
inline T read_int(std::istream &stream)
|
||||
{
|
||||
T value;
|
||||
|
@ -60,7 +60,7 @@ inline T read_int(std::istream &stream)
|
|||
return value;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
template <class T>
|
||||
inline void write_int(std::ostream &stream, T value)
|
||||
{
|
||||
stream.write(reinterpret_cast<char *>(&value), sizeof(T));
|
||||
|
@ -70,24 +70,24 @@ zip_file_header::zip_file_header()
|
|||
{
|
||||
}
|
||||
|
||||
bool zip_file_header::read(std::istream& istream,const bool global)
|
||||
bool zip_file_header::read(std::istream &istream, const bool global)
|
||||
{
|
||||
auto sig = read_int<std::uint32_t>(istream);
|
||||
|
||||
// read and check for local/global magic
|
||||
if(global)
|
||||
if (global)
|
||||
{
|
||||
if(sig!=0x02014b50)
|
||||
if (sig != 0x02014b50)
|
||||
{
|
||||
std::cerr<<"Did not find global header signature"<<std::endl;
|
||||
std::cerr << "Did not find global header signature" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
version = read_int<std::uint16_t>(istream);
|
||||
}
|
||||
else if(sig!=0x04034b50)
|
||||
else if (sig != 0x04034b50)
|
||||
{
|
||||
std::cerr<<"Did not find local header signature"<<std::endl;
|
||||
std::cerr << "Did not find local header signature" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -106,18 +106,18 @@ bool zip_file_header::read(std::istream& istream,const bool global)
|
|||
|
||||
std::uint16_t comment_length = 0;
|
||||
|
||||
if(global)
|
||||
if (global)
|
||||
{
|
||||
comment_length = read_int<std::uint16_t>(istream);
|
||||
/*std::uint16_t disk_number_start = */read_int<std::uint16_t>(istream);
|
||||
/*std::uint16_t int_file_attrib = */read_int<std::uint16_t>(istream);
|
||||
/*std::uint32_t ext_file_attrib = */read_int<std::uint32_t>(istream);
|
||||
/*std::uint16_t disk_number_start = */ read_int<std::uint16_t>(istream);
|
||||
/*std::uint16_t int_file_attrib = */ read_int<std::uint16_t>(istream);
|
||||
/*std::uint32_t ext_file_attrib = */ read_int<std::uint32_t>(istream);
|
||||
header_offset = read_int<std::uint32_t>(istream);
|
||||
}
|
||||
|
||||
filename.resize(filename_length, '\0');
|
||||
istream.read(&filename[0], filename_length);
|
||||
|
||||
|
||||
extra.resize(extra_length, 0);
|
||||
istream.read(reinterpret_cast<char *>(extra.data()), extra_length);
|
||||
|
||||
|
@ -130,259 +130,349 @@ bool zip_file_header::read(std::istream& istream,const bool global)
|
|||
return true;
|
||||
}
|
||||
|
||||
void zip_file_header::Write(std::ostream& ostream,const bool global) const
|
||||
void zip_file_header::Write(std::ostream &ostream, const bool global) const
|
||||
{
|
||||
if(global){
|
||||
write_int(ostream,(unsigned int)0x02014b50); // header sig
|
||||
write_int(ostream,(unsigned short)00);} // version made by
|
||||
else write_int(ostream,(unsigned int)0x04034b50);
|
||||
write_int(ostream,version);
|
||||
write_int(ostream,flags);
|
||||
write_int(ostream,compression_type);
|
||||
write_int(ostream,stamp_date);
|
||||
write_int(ostream,stamp_time);
|
||||
write_int(ostream,crc);
|
||||
write_int(ostream,compressed_size);
|
||||
write_int(ostream,uncompressed_size);
|
||||
write_int(ostream,(unsigned short)filename.length());
|
||||
write_int(ostream,(unsigned short)0); // extra lengthx
|
||||
if(global){
|
||||
write_int(ostream,(unsigned short)0); // filecomment
|
||||
write_int(ostream,(unsigned short)0); // disk# start
|
||||
write_int(ostream,(unsigned short)0); // internal file
|
||||
write_int(ostream,(unsigned int)0); // ext final
|
||||
write_int(ostream,(unsigned int)header_offset);} // rel offset
|
||||
for(unsigned int i=0;i<filename.length();i++) write_int(ostream,filename.c_str()[i]);
|
||||
if (global)
|
||||
{
|
||||
write_int(ostream, static_cast<unsigned int>(0x02014b50)); // header sig
|
||||
write_int(ostream, static_cast<unsigned short>(0)); // version made by
|
||||
}
|
||||
else
|
||||
{
|
||||
write_int(ostream, static_cast<unsigned int>(0x04034b50));
|
||||
}
|
||||
|
||||
write_int(ostream, version);
|
||||
write_int(ostream, flags);
|
||||
write_int(ostream, compression_type);
|
||||
write_int(ostream, stamp_date);
|
||||
write_int(ostream, stamp_time);
|
||||
write_int(ostream, crc);
|
||||
write_int(ostream, compressed_size);
|
||||
write_int(ostream, uncompressed_size);
|
||||
write_int(ostream, static_cast<unsigned short>(filename.length()));
|
||||
write_int(ostream, static_cast<unsigned short>(0)); // extra lengthx
|
||||
|
||||
if (global)
|
||||
{
|
||||
write_int(ostream, static_cast<unsigned short>(0)); // filecomment
|
||||
write_int(ostream, static_cast<unsigned short>(0)); // disk# start
|
||||
write_int(ostream, static_cast<unsigned short>(0)); // internal file
|
||||
write_int(ostream, static_cast<unsigned int>(0)); // ext final
|
||||
write_int(ostream, static_cast<unsigned int>(header_offset)); // rel offset
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < filename.length(); i++)
|
||||
{
|
||||
write_int(ostream, filename.c_str()[i]);
|
||||
}
|
||||
}
|
||||
|
||||
class ZipStreambufDecompress:public std::streambuf
|
||||
class ZipStreambufDecompress : public std::streambuf
|
||||
{
|
||||
static const unsigned int buffer_size=512;
|
||||
std::istream& istream;
|
||||
static const unsigned int buffer_size = 512;
|
||||
std::istream &istream;
|
||||
|
||||
z_stream strm;
|
||||
unsigned char in[buffer_size],out[buffer_size];
|
||||
unsigned char in[buffer_size], out[buffer_size];
|
||||
zip_file_header header;
|
||||
int total_read,total_uncompressed;
|
||||
//bool own_istream;
|
||||
int total_read, total_uncompressed;
|
||||
// bool own_istream;
|
||||
bool valid;
|
||||
bool compressed_data;
|
||||
|
||||
static const unsigned short DEFLATE=8;
|
||||
static const unsigned short UNCOMPRESSED=0;
|
||||
static const unsigned short DEFLATE = 8;
|
||||
static const unsigned short UNCOMPRESSED = 0;
|
||||
|
||||
public:
|
||||
ZipStreambufDecompress(std::istream& stream,zip_file_header central_header)
|
||||
:istream(stream),header(central_header),total_read(0),total_uncompressed(0),valid(true)
|
||||
ZipStreambufDecompress(std::istream &stream, zip_file_header central_header)
|
||||
: istream(stream), header(central_header), total_read(0), total_uncompressed(0), valid(true)
|
||||
{
|
||||
strm.zalloc=Z_NULL;strm.zfree=Z_NULL;strm.opaque=Z_NULL;strm.avail_in=0;strm.next_in=Z_NULL;
|
||||
setg((char*)in,(char*)in,(char*)in);
|
||||
setp(0,0);
|
||||
strm.zalloc = Z_NULL;
|
||||
strm.zfree = Z_NULL;
|
||||
strm.opaque = Z_NULL;
|
||||
strm.avail_in = 0;
|
||||
strm.next_in = Z_NULL;
|
||||
setg((char *)in, (char *)in, (char *)in);
|
||||
setp(0, 0);
|
||||
// skip the header
|
||||
valid=header.read(istream,false);
|
||||
if(header.compression_type==DEFLATE) compressed_data=true;
|
||||
else if(header.compression_type==UNCOMPRESSED) compressed_data=false;
|
||||
else{
|
||||
compressed_data=false;std::cerr<<"ZIP: got unrecognized compressed data (Supported deflate/uncompressed)"<<std::endl;
|
||||
valid=false;}
|
||||
valid = header.read(istream, false);
|
||||
if (header.compression_type == DEFLATE)
|
||||
compressed_data = true;
|
||||
else if (header.compression_type == UNCOMPRESSED)
|
||||
compressed_data = false;
|
||||
else
|
||||
{
|
||||
compressed_data = false;
|
||||
std::cerr << "ZIP: got unrecognized compressed data (Supported deflate/uncompressed)" << std::endl;
|
||||
valid = false;
|
||||
}
|
||||
// initialize the inflate
|
||||
if(compressed_data && valid){
|
||||
int result=inflateInit2(&strm,-MAX_WBITS);
|
||||
if(result!=Z_OK){std::cerr<<"gzip: inflateInit2 did not return Z_OK"<<std::endl;valid=false;}}
|
||||
header = central_header;
|
||||
if (compressed_data && valid)
|
||||
{
|
||||
int result = inflateInit2(&strm, -MAX_WBITS);
|
||||
if (result != Z_OK)
|
||||
{
|
||||
std::cerr << "gzip: inflateInit2 did not return Z_OK" << std::endl;
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
header = central_header;
|
||||
}
|
||||
|
||||
virtual ~ZipStreambufDecompress()
|
||||
{if(compressed_data && valid) inflateEnd(&strm);}
|
||||
{
|
||||
if (compressed_data && valid) inflateEnd(&strm);
|
||||
}
|
||||
|
||||
int process()
|
||||
{if(!valid) return -1;
|
||||
if(compressed_data){
|
||||
strm.avail_out=buffer_size-4;
|
||||
strm.next_out=(Bytef*)(out+4);
|
||||
while(strm.avail_out!=0){
|
||||
if(strm.avail_in==0){ // buffer empty, read some more from file
|
||||
istream.read((char*)in,std::min((unsigned int)buffer_size,header.compressed_size-total_read));
|
||||
strm.avail_in=istream.gcount();
|
||||
total_read+=strm.avail_in;
|
||||
strm.next_in=(Bytef*)in;}
|
||||
int ret=inflate(&strm,Z_NO_FLUSH); // decompress
|
||||
switch(ret){
|
||||
case Z_STREAM_ERROR:
|
||||
std::cerr<<"libz error Z_STREAM_ERROR"<<std::endl;
|
||||
valid=false;return -1;
|
||||
{
|
||||
if (!valid) return -1;
|
||||
if (compressed_data)
|
||||
{
|
||||
strm.avail_out = buffer_size - 4;
|
||||
strm.next_out = (Bytef *)(out + 4);
|
||||
while (strm.avail_out != 0)
|
||||
{
|
||||
if (strm.avail_in == 0)
|
||||
{ // buffer empty, read some more from file
|
||||
istream.read((char *)in, std::min((unsigned int)buffer_size, header.compressed_size - total_read));
|
||||
strm.avail_in = istream.gcount();
|
||||
total_read += strm.avail_in;
|
||||
strm.next_in = (Bytef *)in;
|
||||
}
|
||||
int ret = inflate(&strm, Z_NO_FLUSH); // decompress
|
||||
switch (ret)
|
||||
{
|
||||
case Z_STREAM_ERROR:
|
||||
std::cerr << "libz error Z_STREAM_ERROR" << std::endl;
|
||||
valid = false;
|
||||
return -1;
|
||||
case Z_NEED_DICT:
|
||||
case Z_DATA_ERROR:
|
||||
case Z_MEM_ERROR:
|
||||
std::cerr<<"gzip error "<<strm.msg<<std::endl;
|
||||
valid=false;return -1;}
|
||||
if(ret==Z_STREAM_END) break;}
|
||||
int unzip_count=buffer_size-strm.avail_out-4;
|
||||
total_uncompressed+=unzip_count;
|
||||
return unzip_count;}
|
||||
else{ // uncompressed, so just read
|
||||
istream.read((char*)(out+4),std::min(buffer_size-4,header.uncompressed_size-total_read));
|
||||
int count=istream.gcount();
|
||||
total_read+=count;
|
||||
return count;}
|
||||
return 1;}
|
||||
case Z_MEM_ERROR:
|
||||
std::cerr << "gzip error " << strm.msg << std::endl;
|
||||
valid = false;
|
||||
return -1;
|
||||
}
|
||||
if (ret == Z_STREAM_END) break;
|
||||
}
|
||||
int unzip_count = buffer_size - strm.avail_out - 4;
|
||||
total_uncompressed += unzip_count;
|
||||
return unzip_count;
|
||||
}
|
||||
else
|
||||
{ // uncompressed, so just read
|
||||
istream.read((char *)(out + 4), std::min(buffer_size - 4, header.uncompressed_size - total_read));
|
||||
int count = istream.gcount();
|
||||
total_read += count;
|
||||
return count;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual int underflow()
|
||||
{if(gptr() && (gptr()<egptr())) return traits_type::to_int_type(*gptr()); // if we already have data just use it
|
||||
int put_back_count=gptr()-eback();
|
||||
if(put_back_count>4) put_back_count=4;
|
||||
std::memmove(out+(4-put_back_count),gptr()-put_back_count,put_back_count);
|
||||
int num=process();
|
||||
setg((char*)(out+4-put_back_count),(char*)(out+4),(char*)(out+4+num));
|
||||
if(num<=0) return EOF;
|
||||
return traits_type::to_int_type(*gptr());}
|
||||
{
|
||||
if (gptr() && (gptr() < egptr()))
|
||||
return traits_type::to_int_type(*gptr()); // if we already have data just use it
|
||||
int put_back_count = gptr() - eback();
|
||||
if (put_back_count > 4) put_back_count = 4;
|
||||
std::memmove(out + (4 - put_back_count), gptr() - put_back_count, put_back_count);
|
||||
int num = process();
|
||||
setg((char *)(out + 4 - put_back_count), (char *)(out + 4), (char *)(out + 4 + num));
|
||||
if (num <= 0) return EOF;
|
||||
return traits_type::to_int_type(*gptr());
|
||||
}
|
||||
|
||||
virtual int overflow(int c=EOF)
|
||||
{assert(false);return EOF;}
|
||||
virtual int overflow(int c = EOF)
|
||||
{
|
||||
assert(false);
|
||||
return EOF;
|
||||
}
|
||||
};
|
||||
|
||||
class ZipStreambufCompress:public std::streambuf
|
||||
class ZipStreambufCompress : public std::streambuf
|
||||
{
|
||||
static const int buffer_size=512;
|
||||
std::ostream& ostream; // owned when header==0 (when not part of zip file)
|
||||
static const int buffer_size = 512;
|
||||
std::ostream &ostream; // owned when header==0 (when not part of zip file)
|
||||
|
||||
z_stream strm;
|
||||
unsigned char in[buffer_size],out[buffer_size];
|
||||
unsigned char in[buffer_size], out[buffer_size];
|
||||
|
||||
zip_file_header* header;
|
||||
zip_file_header *header;
|
||||
unsigned int uncompressed_size;
|
||||
unsigned int crc;
|
||||
|
||||
bool valid;
|
||||
|
||||
public:
|
||||
ZipStreambufCompress(zip_file_header* central_header,std::ostream& stream)
|
||||
:ostream(stream),header(central_header),valid(true)
|
||||
ZipStreambufCompress(zip_file_header *central_header, std::ostream &stream)
|
||||
: ostream(stream), header(central_header), valid(true)
|
||||
{
|
||||
strm.zalloc=Z_NULL;strm.zfree=Z_NULL;strm.opaque=Z_NULL;
|
||||
int ret=deflateInit2(&strm,Z_DEFAULT_COMPRESSION,Z_DEFLATED,-MAX_WBITS,8,Z_DEFAULT_STRATEGY);
|
||||
if(ret != Z_OK){std::cerr<<"libz: failed to deflateInit"<<std::endl;valid=false;return;}
|
||||
setg(0,0,0);
|
||||
setp((char*)in,(char*)(in+buffer_size-4)); // we want to be 4 aligned
|
||||
strm.zalloc = Z_NULL;
|
||||
strm.zfree = Z_NULL;
|
||||
strm.opaque = Z_NULL;
|
||||
int ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY);
|
||||
if (ret != Z_OK)
|
||||
{
|
||||
std::cerr << "libz: failed to deflateInit" << std::endl;
|
||||
valid = false;
|
||||
return;
|
||||
}
|
||||
setg(0, 0, 0);
|
||||
setp((char *)in, (char *)(in + buffer_size - 4)); // we want to be 4 aligned
|
||||
// Write appropriate header
|
||||
if(header){header->header_offset=stream.tellp();header->Write(ostream,false);}
|
||||
uncompressed_size=crc=0;
|
||||
if (header)
|
||||
{
|
||||
header->header_offset = stream.tellp();
|
||||
header->Write(ostream, false);
|
||||
}
|
||||
uncompressed_size = crc = 0;
|
||||
}
|
||||
|
||||
virtual ~ZipStreambufCompress()
|
||||
{if(valid){
|
||||
process(true);
|
||||
deflateEnd(&strm);
|
||||
if(header){
|
||||
std::ios::streampos final_position=ostream.tellp();
|
||||
header->uncompressed_size=uncompressed_size;
|
||||
header->crc=crc;
|
||||
ostream.seekp(header->header_offset);
|
||||
header->Write(ostream,false);
|
||||
ostream.seekp(final_position);}
|
||||
else{write_int(ostream,crc);write_int(ostream,uncompressed_size);}}
|
||||
if(!header) delete &ostream;}
|
||||
{
|
||||
if (valid)
|
||||
{
|
||||
process(true);
|
||||
deflateEnd(&strm);
|
||||
if (header)
|
||||
{
|
||||
std::ios::streampos final_position = ostream.tellp();
|
||||
header->uncompressed_size = uncompressed_size;
|
||||
header->crc = crc;
|
||||
ostream.seekp(header->header_offset);
|
||||
header->Write(ostream, false);
|
||||
ostream.seekp(final_position);
|
||||
}
|
||||
else
|
||||
{
|
||||
write_int(ostream, crc);
|
||||
write_int(ostream, uncompressed_size);
|
||||
}
|
||||
}
|
||||
if (!header) delete &ostream;
|
||||
}
|
||||
|
||||
protected:
|
||||
int process(bool flush)
|
||||
{if(!valid) return -1;
|
||||
strm.next_in=(Bytef*)pbase();
|
||||
strm.avail_in=pptr()-pbase();
|
||||
while(strm.avail_in!=0 || flush){
|
||||
strm.avail_out=buffer_size;
|
||||
strm.next_out=(Bytef*)out;
|
||||
int ret=deflate(&strm,flush?Z_FINISH:Z_NO_FLUSH);
|
||||
if(!(ret!=Z_BUF_ERROR && ret!=Z_STREAM_ERROR)){
|
||||
valid=false;
|
||||
std::cerr<<"gzip: gzip error "<<strm.msg<<std::endl;;
|
||||
return -1;}
|
||||
int generated_output=strm.next_out-(Bytef*)out;
|
||||
ostream.write((char*)out,generated_output);
|
||||
if(header) header->compressed_size+=generated_output;
|
||||
if(ret==Z_STREAM_END) break;}
|
||||
// update counts, crc's and buffers
|
||||
int consumed_input=pptr()-pbase();
|
||||
uncompressed_size+=consumed_input;
|
||||
crc=crc32(crc,(Bytef*)in,consumed_input);
|
||||
setp(pbase(),pbase()+buffer_size-4);return 1;}
|
||||
{
|
||||
if (!valid) return -1;
|
||||
strm.next_in = (Bytef *)pbase();
|
||||
strm.avail_in = pptr() - pbase();
|
||||
while (strm.avail_in != 0 || flush)
|
||||
{
|
||||
strm.avail_out = buffer_size;
|
||||
strm.next_out = (Bytef *)out;
|
||||
int ret = deflate(&strm, flush ? Z_FINISH : Z_NO_FLUSH);
|
||||
if (!(ret != Z_BUF_ERROR && ret != Z_STREAM_ERROR))
|
||||
{
|
||||
valid = false;
|
||||
std::cerr << "gzip: gzip error " << strm.msg << std::endl;
|
||||
;
|
||||
return -1;
|
||||
}
|
||||
int generated_output = strm.next_out - (Bytef *)out;
|
||||
ostream.write((char *)out, generated_output);
|
||||
if (header) header->compressed_size += generated_output;
|
||||
if (ret == Z_STREAM_END) break;
|
||||
}
|
||||
// update counts, crc's and buffers
|
||||
int consumed_input = pptr() - pbase();
|
||||
uncompressed_size += consumed_input;
|
||||
crc = crc32(crc, (Bytef *)in, consumed_input);
|
||||
setp(pbase(), pbase() + buffer_size - 4);
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual int sync()
|
||||
{if(pptr() && pptr()>pbase()) return process(false);return 0;}
|
||||
{
|
||||
if (pptr() && pptr() > pbase()) return process(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int underflow()
|
||||
{std::runtime_error("Attempt to read write only ostream");return 0;}
|
||||
|
||||
virtual int overflow(int c=EOF)
|
||||
{if(c!=EOF){*pptr()=c;pbump(1);}
|
||||
if(process(false)==EOF) return EOF;
|
||||
return c;}
|
||||
};
|
||||
|
||||
class ZIP_FILE_ISTREAM:public std::istream
|
||||
{
|
||||
ZipStreambufDecompress buf;
|
||||
|
||||
public:
|
||||
ZIP_FILE_ISTREAM(std::istream& istream,zip_file_header header)
|
||||
:std::istream(&buf),buf(istream,header)
|
||||
{
|
||||
std::runtime_error("Attempt to read write only ostream");
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual ~ZIP_FILE_ISTREAM()
|
||||
virtual int overflow(int c = EOF)
|
||||
{
|
||||
if (c != EOF)
|
||||
{
|
||||
*pptr() = c;
|
||||
pbump(1);
|
||||
}
|
||||
if (process(false) == EOF) return EOF;
|
||||
return c;
|
||||
}
|
||||
};
|
||||
|
||||
class ZIP_FILE_OSTREAM:public std::ostream
|
||||
zip_file_istream::zip_file_istream(std::unique_ptr<std::streambuf> &&buffer)
|
||||
: std::istream(&*buffer)
|
||||
{
|
||||
ZipStreambufCompress buf;
|
||||
buf.swap(buffer);
|
||||
}
|
||||
|
||||
public:
|
||||
ZIP_FILE_OSTREAM(zip_file_header* header,std::ostream& ostream)
|
||||
:std::ostream(&buf),buf(header,ostream)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~ZIP_FILE_OSTREAM()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
ZipFileWriter::ZipFileWriter(std::ostream& stream) : target_stream_(stream)
|
||||
zip_file_istream::~zip_file_istream()
|
||||
{
|
||||
if(!target_stream_) throw std::runtime_error("ZIP: Invalid file handle");
|
||||
}
|
||||
|
||||
zip_file_ostream::zip_file_ostream(std::unique_ptr<std::streambuf> &&buffer)
|
||||
: std::ostream(&*buffer)
|
||||
{
|
||||
buf.swap(buffer);
|
||||
}
|
||||
|
||||
zip_file_ostream::~zip_file_ostream()
|
||||
{
|
||||
}
|
||||
|
||||
ZipFileWriter::ZipFileWriter(std::ostream &stream) : target_stream_(stream)
|
||||
{
|
||||
if (!target_stream_) throw std::runtime_error("ZIP: Invalid file handle");
|
||||
}
|
||||
|
||||
ZipFileWriter::~ZipFileWriter()
|
||||
{
|
||||
// Write all file headers
|
||||
std::ios::streampos final_position=target_stream_.tellp();
|
||||
for(unsigned int i=0;i<file_headers_.size();i++)
|
||||
std::ios::streampos final_position = target_stream_.tellp();
|
||||
for (unsigned int i = 0; i < file_headers_.size(); i++)
|
||||
{
|
||||
file_headers_[i].Write(target_stream_,true);
|
||||
file_headers_[i].Write(target_stream_, true);
|
||||
}
|
||||
std::ios::streampos central_end=target_stream_.tellp();
|
||||
std::ios::streampos central_end = target_stream_.tellp();
|
||||
// Write end of central
|
||||
write_int(target_stream_,(unsigned int)0x06054b50); // end of central
|
||||
write_int(target_stream_,(unsigned short)0); // this disk number
|
||||
write_int(target_stream_,(unsigned short)0); // this disk number
|
||||
write_int(target_stream_,(unsigned short)file_headers_.size()); // one entry in center in this disk
|
||||
write_int(target_stream_,(unsigned short)file_headers_.size()); // one entry in center
|
||||
write_int(target_stream_,(unsigned int)(central_end - final_position)); // size of header
|
||||
write_int(target_stream_,(unsigned int)final_position); // offset to header
|
||||
write_int(target_stream_,(unsigned short)0); // zip comment
|
||||
write_int(target_stream_, (unsigned int)0x06054b50); // end of central
|
||||
write_int(target_stream_, (unsigned short)0); // this disk number
|
||||
write_int(target_stream_, (unsigned short)0); // this disk number
|
||||
write_int(target_stream_, (unsigned short)file_headers_.size()); // one entry in center in this disk
|
||||
write_int(target_stream_, (unsigned short)file_headers_.size()); // one entry in center
|
||||
write_int(target_stream_, (unsigned int)(central_end - final_position)); // size of header
|
||||
write_int(target_stream_, (unsigned int)final_position); // offset to header
|
||||
write_int(target_stream_, (unsigned short)0); // zip comment
|
||||
}
|
||||
|
||||
std::ostream* ZipFileWriter::open(const std::string& filename)
|
||||
std::ostream &ZipFileWriter::open(const std::string &filename)
|
||||
{
|
||||
zip_file_header header;
|
||||
header.filename = filename;
|
||||
file_headers_.push_back(header);
|
||||
return new ZIP_FILE_OSTREAM(&file_headers_.back(),target_stream_);
|
||||
auto streambuf = std::make_unique<ZipStreambufCompress>(&file_headers_.back(), target_stream_);
|
||||
auto stream = new zip_file_ostream(std::move(streambuf));
|
||||
write_stream_.reset(stream);
|
||||
return *write_stream_;
|
||||
}
|
||||
|
||||
void ZipFileWriter::close()
|
||||
{
|
||||
write_stream_.reset(nullptr);
|
||||
}
|
||||
|
||||
ZipFileReader::ZipFileReader(std::istream &stream) : source_stream_(stream)
|
||||
{
|
||||
if(!stream)
|
||||
if (!stream)
|
||||
{
|
||||
throw std::runtime_error("ZIP: Invalid file handle");
|
||||
}
|
||||
|
@ -398,26 +488,30 @@ bool ZipFileReader::read_central_header()
|
|||
{
|
||||
// Find the header
|
||||
// NOTE: this assumes the zip file header is the last thing written to file...
|
||||
source_stream_.seekg(0,std::ios_base::end);
|
||||
std::ios::streampos end_position=source_stream_.tellg();
|
||||
source_stream_.seekg(0, std::ios_base::end);
|
||||
std::ios::streampos end_position = source_stream_.tellg();
|
||||
|
||||
auto max_comment_size = std::uint32_t(0xffff); // max size of header
|
||||
auto read_size_before_comment = std::uint32_t(22);
|
||||
|
||||
std::ios::streamoff read_start=max_comment_size+read_size_before_comment;
|
||||
std::ios::streamoff read_start = max_comment_size + read_size_before_comment;
|
||||
|
||||
if(read_start>end_position) read_start=end_position;
|
||||
source_stream_.seekg(end_position-read_start);
|
||||
if (read_start > end_position) read_start = end_position;
|
||||
source_stream_.seekg(end_position - read_start);
|
||||
std::vector<char> buf(static_cast<std::size_t>(read_start), '\0');
|
||||
if(read_start<=0){std::cerr<<"ZIP: Invalid read buffer size"<<std::endl;return false;}
|
||||
if (read_start <= 0)
|
||||
{
|
||||
std::cerr << "ZIP: Invalid read buffer size" << std::endl;
|
||||
return false;
|
||||
}
|
||||
source_stream_.read(buf.data(), read_start);
|
||||
|
||||
auto found_header = false;
|
||||
std::size_t header_index = 0;
|
||||
|
||||
for(std::size_t i = 0; i < read_start - 3; ++i)
|
||||
for (std::size_t i = 0; i < read_start - 3; ++i)
|
||||
{
|
||||
if(buf[i] == 0x50 && buf[i + 1] == 0x4b && buf[i + 2] == 0x05 && buf[i + 3] == 0x06)
|
||||
if (buf[i] == 0x50 && buf[i + 1] == 0x4b && buf[i + 2] == 0x05 && buf[i + 3] == 0x06)
|
||||
{
|
||||
found_header = true;
|
||||
header_index = i;
|
||||
|
@ -425,35 +519,35 @@ bool ZipFileReader::read_central_header()
|
|||
}
|
||||
}
|
||||
|
||||
if(!found_header)
|
||||
if (!found_header)
|
||||
{
|
||||
std::cerr<<"ZIP: Failed to find zip header"<<std::endl;
|
||||
std::cerr << "ZIP: Failed to find zip header" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// seek to end of central header and read
|
||||
source_stream_.seekg(end_position - (read_start - static_cast<std::ptrdiff_t>(header_index)));
|
||||
|
||||
/*auto word = */read_int<std::uint32_t>(source_stream_);
|
||||
/*auto word = */ read_int<std::uint32_t>(source_stream_);
|
||||
auto disk_number1 = read_int<std::uint16_t>(source_stream_);
|
||||
auto disk_number2 = read_int<std::uint16_t>(source_stream_);
|
||||
|
||||
if(disk_number1 != disk_number2 || disk_number1 != 0)
|
||||
if (disk_number1 != disk_number2 || disk_number1 != 0)
|
||||
{
|
||||
std::cerr<<"ZIP: multiple disk zip files are not supported"<<std::endl;
|
||||
std::cerr << "ZIP: multiple disk zip files are not supported" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto num_files = read_int<std::uint16_t>(source_stream_); // one entry in center in this disk
|
||||
auto num_files_this_disk = read_int<std::uint16_t>(source_stream_); // one entry in center
|
||||
|
||||
if(num_files != num_files_this_disk)
|
||||
if (num_files != num_files_this_disk)
|
||||
{
|
||||
std::cerr<<"ZIP: multi disk zip files are not supported"<<std::endl;
|
||||
std::cerr << "ZIP: multi disk zip files are not supported" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*auto size_of_header = */read_int<std::uint32_t>(source_stream_); // size of header
|
||||
/*auto size_of_header = */ read_int<std::uint32_t>(source_stream_); // size of header
|
||||
auto header_offset = read_int<std::uint32_t>(source_stream_); // offset to header
|
||||
|
||||
// go to header and read all file headers
|
||||
|
@ -481,7 +575,8 @@ std::istream &ZipFileReader::open(const std::string &filename)
|
|||
|
||||
auto header = file_headers_.at(filename);
|
||||
source_stream_.seekg(header.header_offset);
|
||||
read_stream_.reset(new ZIP_FILE_ISTREAM(source_stream_, header));
|
||||
auto streambuf = std::make_unique<ZipStreambufDecompress>(source_stream_, header);
|
||||
read_stream_.reset(new zip_file_istream(std::move(streambuf)));
|
||||
|
||||
return *read_stream_;
|
||||
}
|
||||
|
@ -496,7 +591,7 @@ std::vector<std::string> ZipFileReader::files() const
|
|||
|
||||
bool ZipFileReader::has_file(const std::string &filename) const
|
||||
{
|
||||
return file_headers_.count(filename) != 0;
|
||||
return file_headers_.count(filename) != 0;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
|
|
@ -59,8 +59,28 @@ struct zip_file_header
|
|||
|
||||
zip_file_header();
|
||||
|
||||
bool read(std::istream& istream, const bool global);
|
||||
void Write(std::ostream& ostream, const bool global) const;
|
||||
bool read(std::istream &istream, const bool global);
|
||||
void Write(std::ostream &ostream, const bool global) const;
|
||||
};
|
||||
|
||||
class zip_file_istream : public std::istream
|
||||
{
|
||||
public:
|
||||
zip_file_istream(std::unique_ptr<std::streambuf> &&buf);
|
||||
virtual ~zip_file_istream();
|
||||
|
||||
private:
|
||||
std::unique_ptr<std::streambuf> buf;
|
||||
};
|
||||
|
||||
class zip_file_ostream : public std::ostream
|
||||
{
|
||||
public:
|
||||
zip_file_ostream(std::unique_ptr<std::streambuf> &&buf);
|
||||
virtual ~zip_file_ostream();
|
||||
|
||||
private:
|
||||
std::unique_ptr<std::streambuf> buf;
|
||||
};
|
||||
|
||||
class ZipFileWriter
|
||||
|
@ -68,11 +88,12 @@ class ZipFileWriter
|
|||
public:
|
||||
ZipFileWriter(std::ostream &filename);
|
||||
virtual ~ZipFileWriter();
|
||||
std::ostream* open(const std::string& filename);
|
||||
|
||||
std::ostream &open(const std::string &filename);
|
||||
void close();
|
||||
private:
|
||||
std::ostream &target_stream_;
|
||||
std::vector<zip_file_header> file_headers_;
|
||||
std::ostream &target_stream_;
|
||||
std::unique_ptr<std::ostream> write_stream_;
|
||||
};
|
||||
|
||||
class ZipFileReader
|
||||
|
@ -82,7 +103,7 @@ public:
|
|||
virtual ~ZipFileReader();
|
||||
std::istream &open(const std::string &filename);
|
||||
std::vector<std::string> files() const;
|
||||
bool has_file(const std::string &filename) const;
|
||||
bool has_file(const std::string &filename) const;
|
||||
|
||||
private:
|
||||
bool read_central_header();
|
||||
|
|
|
@ -1,154 +0,0 @@
|
|||
// Copyright (c) 2014-2016 Thomas Fussell
|
||||
// Copyright (c) 2010-2015 openpyxl
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, WRISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE
|
||||
//
|
||||
// @license: http://www.opensource.org/licenses/mit-license.php
|
||||
// @author: see AUTHORS file
|
||||
#include <xlnt/styles/base_format.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
alignment &base_format::alignment()
|
||||
{
|
||||
return alignment_;
|
||||
}
|
||||
|
||||
const alignment &base_format::alignment() const
|
||||
{
|
||||
return alignment_;
|
||||
}
|
||||
|
||||
void base_format::alignment(const xlnt::alignment &new_alignment, bool apply)
|
||||
{
|
||||
alignment_ = new_alignment;
|
||||
apply_alignment_ = apply;
|
||||
}
|
||||
|
||||
number_format &base_format::number_format()
|
||||
{
|
||||
return number_format_;
|
||||
}
|
||||
|
||||
const number_format &base_format::number_format() const
|
||||
{
|
||||
return number_format_;
|
||||
}
|
||||
|
||||
void base_format::number_format(const xlnt::number_format &new_number_format, bool apply)
|
||||
{
|
||||
number_format_ = new_number_format;
|
||||
apply_number_format_ = apply;
|
||||
}
|
||||
|
||||
border &base_format::border()
|
||||
{
|
||||
return border_;
|
||||
}
|
||||
|
||||
const border &base_format::border() const
|
||||
{
|
||||
return border_;
|
||||
}
|
||||
|
||||
void base_format::border(const xlnt::border &new_border, bool apply)
|
||||
{
|
||||
border_ = new_border;
|
||||
apply_border_ = apply;
|
||||
}
|
||||
|
||||
fill &base_format::fill()
|
||||
{
|
||||
return fill_;
|
||||
}
|
||||
|
||||
const fill &base_format::fill() const
|
||||
{
|
||||
return fill_;
|
||||
}
|
||||
|
||||
void base_format::fill(const xlnt::fill &new_fill, bool apply)
|
||||
{
|
||||
fill_ = new_fill;
|
||||
apply_fill_ = apply;
|
||||
}
|
||||
|
||||
font &base_format::font()
|
||||
{
|
||||
return font_;
|
||||
}
|
||||
|
||||
const font &base_format::font() const
|
||||
{
|
||||
return font_;
|
||||
}
|
||||
|
||||
void base_format::font(const xlnt::font &new_font, bool apply)
|
||||
{
|
||||
font_ = new_font;
|
||||
apply_font_ = apply;
|
||||
}
|
||||
|
||||
protection &base_format::protection()
|
||||
{
|
||||
return protection_;
|
||||
}
|
||||
|
||||
const protection &base_format::protection() const
|
||||
{
|
||||
return protection_;
|
||||
}
|
||||
|
||||
void base_format::protection(const xlnt::protection &new_protection, bool apply)
|
||||
{
|
||||
protection_ = new_protection;
|
||||
apply_protection_ = apply;
|
||||
}
|
||||
|
||||
bool base_format::alignment_applied() const
|
||||
{
|
||||
return apply_alignment_;
|
||||
}
|
||||
|
||||
bool base_format::border_applied() const
|
||||
{
|
||||
return apply_border_;
|
||||
}
|
||||
|
||||
bool base_format::fill_applied() const
|
||||
{
|
||||
return apply_fill_;
|
||||
}
|
||||
|
||||
bool base_format::font_applied() const
|
||||
{
|
||||
return apply_font_;
|
||||
}
|
||||
|
||||
bool base_format::number_format_applied() const
|
||||
{
|
||||
return apply_number_format_;
|
||||
}
|
||||
|
||||
bool base_format::protection_applied() const
|
||||
{
|
||||
return apply_protection_;
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
|
@ -43,23 +43,16 @@ void format::clear_style()
|
|||
d_->style.clear();
|
||||
}
|
||||
|
||||
void format::style(const xlnt::style &new_style)
|
||||
format format::style(const xlnt::style &new_style)
|
||||
{
|
||||
d_->style = new_style.name();
|
||||
return format(d_);
|
||||
}
|
||||
|
||||
void format::style(const std::string &new_style)
|
||||
format format::style(const std::string &new_style)
|
||||
{
|
||||
for (auto &style : d_->parent->styles)
|
||||
{
|
||||
if (style.name() == new_style)
|
||||
{
|
||||
d_->style = new_style;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw key_not_found();
|
||||
d_->style = new_style;
|
||||
return format(d_);
|
||||
}
|
||||
|
||||
bool format::has_style() const
|
||||
|
@ -67,76 +60,91 @@ bool format::has_style() const
|
|||
return d_->style;
|
||||
}
|
||||
|
||||
const style &format::style() const
|
||||
const style format::style() const
|
||||
{
|
||||
if (!has_style())
|
||||
{
|
||||
throw invalid_attribute();
|
||||
}
|
||||
|
||||
return d_->parent->get_style(*d_->style);
|
||||
return d_->parent->style(d_->style.get());
|
||||
}
|
||||
|
||||
xlnt::alignment &format::alignment()
|
||||
{
|
||||
return d_->parent->alignments.at(d_->alignment_id.get());
|
||||
}
|
||||
|
||||
const xlnt::alignment &format::alignment() const
|
||||
{
|
||||
return d_->parent->alignments.at(d_->alignment_id.get());
|
||||
}
|
||||
|
||||
format format::alignment(const xlnt::alignment &new_alignment, bool applied)
|
||||
{
|
||||
d_ = d_->parent->find_or_create_with(d_, new_alignment, applied);
|
||||
return format(d_);
|
||||
}
|
||||
|
||||
xlnt::border &format::border()
|
||||
{
|
||||
return base_format::border();
|
||||
return d_->parent->borders.at(d_->border_id.get());
|
||||
}
|
||||
|
||||
const xlnt::border &format::border() const
|
||||
{
|
||||
return base_format::border();
|
||||
return d_->parent->borders.at(d_->border_id.get());
|
||||
}
|
||||
|
||||
void format::border(const xlnt::border &new_border, bool applied)
|
||||
format format::border(const xlnt::border &new_border, bool applied)
|
||||
{
|
||||
border_id(d_->parent->add_border(new_border));
|
||||
base_format::border(new_border, applied);
|
||||
d_ = d_->parent->find_or_create_with(d_, new_border, applied);
|
||||
return format(d_);
|
||||
}
|
||||
|
||||
xlnt::fill &format::fill()
|
||||
{
|
||||
return base_format::fill();
|
||||
return d_->parent->fills.at(d_->fill_id.get());
|
||||
}
|
||||
|
||||
const xlnt::fill &format::fill() const
|
||||
{
|
||||
return base_format::fill();
|
||||
return d_->parent->fills.at(d_->fill_id.get());
|
||||
}
|
||||
|
||||
void format::fill(const xlnt::fill &new_fill, bool applied)
|
||||
format format::fill(const xlnt::fill &new_fill, bool applied)
|
||||
{
|
||||
fill_id(d_->parent->add_fill(new_fill));
|
||||
base_format::fill(new_fill, applied);
|
||||
d_ = d_->parent->find_or_create_with(d_, new_fill, applied);
|
||||
return format(d_);
|
||||
}
|
||||
|
||||
xlnt::font &format::font()
|
||||
{
|
||||
return base_format::font();
|
||||
return d_->parent->fonts.at(d_->font_id.get());
|
||||
}
|
||||
|
||||
const xlnt::font &format::font() const
|
||||
{
|
||||
return base_format::font();
|
||||
return d_->parent->fonts.at(d_->font_id.get());
|
||||
}
|
||||
|
||||
void format::font(const xlnt::font &new_font, bool applied)
|
||||
format format::font(const xlnt::font &new_font, bool applied)
|
||||
{
|
||||
font_id(d_->parent->add_font(new_font));
|
||||
base_format::font(new_font, applied);
|
||||
d_ = d_->parent->deduplicate(d_);
|
||||
d_ = d_->parent->find_or_create_with(d_, new_font, applied);
|
||||
return format(d_);
|
||||
}
|
||||
|
||||
xlnt::number_format &format::number_format()
|
||||
{
|
||||
return base_format::number_format();
|
||||
return d_->parent->number_formats.at(d_->number_format_id.get());
|
||||
}
|
||||
|
||||
const xlnt::number_format &format::number_format() const
|
||||
{
|
||||
return base_format::number_format();
|
||||
return d_->parent->number_formats.at(d_->number_format_id.get());
|
||||
}
|
||||
|
||||
void format::number_format(const xlnt::number_format &new_number_format, bool applied)
|
||||
format format::number_format(const xlnt::number_format &new_number_format, bool applied)
|
||||
{
|
||||
auto copy = new_number_format;
|
||||
|
||||
|
@ -146,25 +154,54 @@ void format::number_format(const xlnt::number_format &new_number_format, bool ap
|
|||
d_->parent->number_formats.push_back(copy);
|
||||
}
|
||||
|
||||
base_format::number_format(copy, applied);
|
||||
d_ = d_->parent->find_or_create_with(d_, copy, applied);
|
||||
return format(d_);
|
||||
}
|
||||
|
||||
format &format::border_id(std::size_t id)
|
||||
xlnt::protection &format::protection()
|
||||
{
|
||||
d_->border_id = id;
|
||||
return *this;
|
||||
return d_->parent->protections.at(d_->protection_id.get());
|
||||
}
|
||||
|
||||
format &format::fill_id(std::size_t id)
|
||||
const xlnt::protection &format::protection() const
|
||||
{
|
||||
d_->fill_id = id;
|
||||
return *this;
|
||||
return d_->parent->protections.at(d_->protection_id.get());
|
||||
}
|
||||
|
||||
format &format::font_id(std::size_t id)
|
||||
format format::protection(const xlnt::protection &new_protection, bool applied)
|
||||
{
|
||||
d_->font_id = id;
|
||||
return *this;
|
||||
d_ = d_->parent->find_or_create_with(d_, new_protection, applied);
|
||||
return format(d_);
|
||||
}
|
||||
|
||||
bool format::alignment_applied() const
|
||||
{
|
||||
return d_->alignment_applied;
|
||||
}
|
||||
|
||||
bool format::border_applied() const
|
||||
{
|
||||
return d_->border_applied;
|
||||
}
|
||||
|
||||
bool format::fill_applied() const
|
||||
{
|
||||
return d_->fill_applied;
|
||||
}
|
||||
|
||||
bool format::font_applied() const
|
||||
{
|
||||
return d_->font_applied;
|
||||
}
|
||||
|
||||
bool format::number_format_applied() const
|
||||
{
|
||||
return d_->number_format_applied;
|
||||
}
|
||||
|
||||
bool format::protection_applied() const
|
||||
{
|
||||
return d_->protection_applied;
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -355,9 +355,7 @@ std::string number_format::format(long double number, calendar base_date) const
|
|||
|
||||
XLNT_API bool operator==(const number_format &left, const number_format &right)
|
||||
{
|
||||
return left.id_set_ == right.id_set_
|
||||
&& left.id_ == right.id_
|
||||
&& left.format_string_ == right.format_string_;
|
||||
return left.format_string_ == right.format_string_;
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -22,13 +22,13 @@
|
|||
// @license: http://www.opensource.org/licenses/mit-license.php
|
||||
// @author: see AUTHORS file
|
||||
|
||||
#include <detail/stylesheet.hpp>
|
||||
#include <xlnt/styles/alignment.hpp>
|
||||
#include <xlnt/styles/border.hpp>
|
||||
#include <xlnt/styles/fill.hpp>
|
||||
#include <xlnt/styles/font.hpp>
|
||||
#include <xlnt/styles/number_format.hpp>
|
||||
#include <xlnt/styles/protection.hpp>
|
||||
#include <detail/style_impl.hpp> // include order is important here
|
||||
#include <xlnt/styles/style.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
|
@ -42,10 +42,10 @@ bool style::hidden() const
|
|||
return d_->hidden_style;
|
||||
}
|
||||
|
||||
style &style::hidden(bool value)
|
||||
style style::hidden(bool value)
|
||||
{
|
||||
d_->hidden_style = value;
|
||||
return *this;
|
||||
return style(d_);
|
||||
}
|
||||
|
||||
optional<std::size_t> style::builtin_id() const
|
||||
|
@ -53,7 +53,7 @@ optional<std::size_t> style::builtin_id() const
|
|||
return d_->builtin_id;
|
||||
}
|
||||
|
||||
style &style::builtin_id(std::size_t builtin_id)
|
||||
style style::builtin_id(std::size_t builtin_id)
|
||||
{
|
||||
d_->builtin_id = builtin_id;
|
||||
return *this;
|
||||
|
@ -64,7 +64,7 @@ std::string style::name() const
|
|||
return d_->name;
|
||||
}
|
||||
|
||||
style &style::name(const std::string &name)
|
||||
style style::name(const std::string &name)
|
||||
{
|
||||
d_->name = name;
|
||||
return *this;
|
||||
|
@ -75,15 +75,167 @@ optional<bool> style::custom() const
|
|||
return d_->custom_builtin;
|
||||
}
|
||||
|
||||
style &style::custom(bool value)
|
||||
style style::custom(bool value)
|
||||
{
|
||||
d_->custom_builtin = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool style::operator==(const style &other)
|
||||
bool style::operator==(const style &other) const
|
||||
{
|
||||
return d_ == other.d_;
|
||||
return name() == other.name();
|
||||
}
|
||||
|
||||
xlnt::alignment &style::alignment()
|
||||
{
|
||||
return d_->parent->alignments.at(d_->alignment_id.get());
|
||||
}
|
||||
|
||||
const xlnt::alignment &style::alignment() const
|
||||
{
|
||||
return d_->parent->alignments.at(d_->alignment_id.get());
|
||||
}
|
||||
|
||||
style style::alignment(const xlnt::alignment &new_alignment, bool applied)
|
||||
{
|
||||
d_->alignment_id = d_->parent->find_or_add(d_->parent->alignments, new_alignment);
|
||||
d_->alignment_applied = applied;
|
||||
return style(d_);
|
||||
}
|
||||
|
||||
xlnt::border &style::border()
|
||||
{
|
||||
return d_->parent->borders.at(d_->border_id.get());
|
||||
}
|
||||
|
||||
const xlnt::border &style::border() const
|
||||
{
|
||||
return d_->parent->borders.at(d_->border_id.get());
|
||||
}
|
||||
|
||||
style style::border(const xlnt::border &new_border, bool applied)
|
||||
{
|
||||
d_->border_id = d_->parent->find_or_add(d_->parent->borders, new_border);
|
||||
d_->border_applied = applied;
|
||||
return style(d_);
|
||||
}
|
||||
|
||||
xlnt::fill &style::fill()
|
||||
{
|
||||
return d_->parent->fills.at(d_->fill_id.get());
|
||||
}
|
||||
|
||||
const xlnt::fill &style::fill() const
|
||||
{
|
||||
return d_->parent->fills.at(d_->fill_id.get());
|
||||
}
|
||||
|
||||
style style::fill(const xlnt::fill &new_fill, bool applied)
|
||||
{
|
||||
d_->fill_id = d_->parent->find_or_add(d_->parent->fills, new_fill);
|
||||
d_->fill_applied = applied;
|
||||
return style(d_);
|
||||
}
|
||||
|
||||
xlnt::font &style::font()
|
||||
{
|
||||
return d_->parent->fonts.at(d_->font_id.get());
|
||||
}
|
||||
|
||||
const xlnt::font &style::font() const
|
||||
{
|
||||
return d_->parent->fonts.at(d_->font_id.get());
|
||||
}
|
||||
|
||||
style style::font(const xlnt::font &new_font, bool applied)
|
||||
{
|
||||
d_->font_id = d_->parent->find_or_add(d_->parent->fonts, new_font);
|
||||
d_->font_applied = applied;
|
||||
return style(d_);
|
||||
}
|
||||
|
||||
xlnt::number_format &style::number_format()
|
||||
{
|
||||
auto target_id = d_->number_format_id.get();
|
||||
return *std::find_if(d_->parent->number_formats.begin(), d_->parent->number_formats.end(),
|
||||
[=](const class number_format &nf) { return nf.get_id() == target_id; });
|
||||
}
|
||||
|
||||
const xlnt::number_format &style::number_format() const
|
||||
{
|
||||
auto target_id = d_->number_format_id.get();
|
||||
return *std::find_if(d_->parent->number_formats.begin(), d_->parent->number_formats.end(),
|
||||
[=](const class number_format &nf) { return nf.get_id() == target_id; });
|
||||
}
|
||||
|
||||
style style::number_format(const xlnt::number_format &new_number_format, bool applied)
|
||||
{
|
||||
auto copy = new_number_format;
|
||||
|
||||
if (!copy.has_id())
|
||||
{
|
||||
copy.set_id(d_->parent->next_custom_number_format_id());
|
||||
d_->parent->number_formats.push_back(copy);
|
||||
}
|
||||
else if (std::find_if(d_->parent->number_formats.begin(),
|
||||
d_->parent->number_formats.end(),
|
||||
[©](const class number_format &nf) { return nf.get_id() == copy.get_id(); })
|
||||
== d_->parent->number_formats.end())
|
||||
{
|
||||
d_->parent->number_formats.push_back(copy);
|
||||
}
|
||||
|
||||
d_->number_format_id = copy.get_id();
|
||||
d_->number_format_applied = applied;
|
||||
|
||||
return style(d_);
|
||||
}
|
||||
|
||||
xlnt::protection &style::protection()
|
||||
{
|
||||
return d_->parent->protections.at(d_->protection_id.get());
|
||||
}
|
||||
|
||||
const xlnt::protection &style::protection() const
|
||||
{
|
||||
return d_->parent->protections.at(d_->protection_id.get());
|
||||
}
|
||||
|
||||
style style::protection(const xlnt::protection &new_protection, bool applied)
|
||||
{
|
||||
d_->protection_id = d_->parent->find_or_add(d_->parent->protections, new_protection);
|
||||
d_->protection_applied = applied;
|
||||
return style(d_);
|
||||
}
|
||||
|
||||
bool style::alignment_applied() const
|
||||
{
|
||||
return d_->alignment_applied;
|
||||
}
|
||||
|
||||
bool style::border_applied() const
|
||||
{
|
||||
return d_->border_applied;
|
||||
}
|
||||
|
||||
bool style::fill_applied() const
|
||||
{
|
||||
return d_->fill_applied;
|
||||
}
|
||||
|
||||
bool style::font_applied() const
|
||||
{
|
||||
return d_->font_applied;
|
||||
}
|
||||
|
||||
bool style::number_format_applied() const
|
||||
{
|
||||
return d_->number_format_applied;
|
||||
}
|
||||
|
||||
bool style::protection_applied() const
|
||||
{
|
||||
return d_->protection_applied;
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -20,12 +20,14 @@ public:
|
|||
{
|
||||
std::vector<std::uint8_t> original_buffer;
|
||||
original.save(original_buffer);
|
||||
original.save("b.xlsx");
|
||||
|
||||
xlnt::workbook resulting_workbook;
|
||||
resulting_workbook.load(original_buffer);
|
||||
|
||||
std::vector<std::uint8_t> resulting_buffer;
|
||||
resulting_workbook.save(resulting_buffer);
|
||||
resulting_workbook.save("a.xlsx");
|
||||
|
||||
return xml_helper::xlsx_archives_match(original_buffer, resulting_buffer);
|
||||
}
|
||||
|
|
|
@ -249,7 +249,7 @@ public:
|
|||
xlnt::workbook wb;
|
||||
xlnt::style s = wb.create_style("s");
|
||||
wb.get_active_sheet().get_cell("B2").set_value("B2");
|
||||
wb.get_active_sheet().get_cell("B2").set_style(s);
|
||||
wb.get_active_sheet().get_cell("B2").style(s);
|
||||
TS_ASSERT(wb.get_active_sheet().get_cell("B2").has_style());
|
||||
wb.clear_styles();
|
||||
TS_ASSERT(!wb.get_active_sheet().get_cell("B2").has_style());
|
||||
|
@ -257,7 +257,7 @@ public:
|
|||
xlnt::font font;
|
||||
font.size(41);
|
||||
format.font(font, true);
|
||||
wb.get_active_sheet().get_cell("B2").set_format(format);
|
||||
wb.get_active_sheet().get_cell("B2").format(format);
|
||||
TS_ASSERT(wb.get_active_sheet().get_cell("B2").has_format());
|
||||
wb.clear_formats();
|
||||
TS_ASSERT(!wb.get_active_sheet().get_cell("B2").has_format());
|
||||
|
@ -280,7 +280,7 @@ public:
|
|||
TS_ASSERT(wb.has_theme());
|
||||
|
||||
wb.create_style("style1");
|
||||
wb.get_style("style1");
|
||||
wb_const.get_style("style1");
|
||||
wb.style("style1");
|
||||
wb_const.style("style1");
|
||||
}
|
||||
};
|
||||
|
|
|
@ -57,6 +57,48 @@
|
|||
#include <xlnt/worksheet/range.hpp>
|
||||
#include <xlnt/worksheet/worksheet.hpp>
|
||||
|
||||
namespace {
|
||||
|
||||
#ifdef WIN32
|
||||
std::wstring utf8_to_utf16(const std::string &utf8_string)
|
||||
{
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t> convert;
|
||||
return convert.from_bytes(utf8_string);
|
||||
}
|
||||
|
||||
void open_stream(std::ifstream &stream, const std::wstring &path)
|
||||
{
|
||||
stream.open(path, std::ios::binary);
|
||||
}
|
||||
|
||||
void open_stream(std::ofstream &stream, const std::wstring &path)
|
||||
{
|
||||
stream.open(path, std::ios::binary);
|
||||
}
|
||||
|
||||
void open_stream(std::ifstream &stream, const std::string &path)
|
||||
{
|
||||
open_stream(stream, utf8_to_utf16(path));
|
||||
}
|
||||
|
||||
void open_stream(std::ofstream &stream, const std::string &path)
|
||||
{
|
||||
stream.open(path, utf8_to_utf16(path));
|
||||
}
|
||||
#else
|
||||
void open_stream(std::ifstream &stream, const std::string &path)
|
||||
{
|
||||
stream.open(path, std::ios::binary);
|
||||
}
|
||||
|
||||
void open_stream(std::ofstream &stream, const std::string &path)
|
||||
{
|
||||
stream.open(path, std::ios::binary);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
workbook workbook::minimal()
|
||||
|
@ -145,12 +187,6 @@ workbook workbook::empty_excel()
|
|||
ws.d_->has_format_properties_ = true;
|
||||
ws.d_->has_view_ = true;
|
||||
|
||||
wb.d_->stylesheet_.fills.push_back(pattern_fill().type(pattern_fill_type::none));
|
||||
wb.d_->stylesheet_.fills.push_back(pattern_fill().type(pattern_fill_type::gray125));
|
||||
|
||||
auto default_font = font().name("Calibri").size(12).scheme("minor").family(2).color(theme_color(1));
|
||||
wb.d_->stylesheet_.fonts.push_back(default_font);
|
||||
|
||||
auto default_border = border().side(border_side::bottom, border::border_property())
|
||||
.side(border_side::top, border::border_property())
|
||||
.side(border_side::start, border::border_property())
|
||||
|
@ -158,14 +194,31 @@ workbook workbook::empty_excel()
|
|||
.side(border_side::diagonal, border::border_property());
|
||||
wb.d_->stylesheet_.borders.push_back(default_border);
|
||||
|
||||
auto &normal_style = wb.create_style("Normal").builtin_id(0);
|
||||
normal_style.font(default_font, false);
|
||||
normal_style.border(default_border, false);
|
||||
auto default_fill = fill(pattern_fill().type(pattern_fill_type::none));
|
||||
wb.d_->stylesheet_.fills.push_back(default_fill);
|
||||
auto gray125_fill = pattern_fill().type(pattern_fill_type::gray125);
|
||||
wb.d_->stylesheet_.fills.push_back(gray125_fill);
|
||||
|
||||
auto &default_format = wb.create_format();
|
||||
default_format.font(default_font, false);
|
||||
default_format.border(default_border, false);
|
||||
default_format.style("Normal");
|
||||
auto default_font = font()
|
||||
.name("Calibri")
|
||||
.size(12)
|
||||
.scheme("minor")
|
||||
.family(2)
|
||||
.color(theme_color(1));
|
||||
wb.d_->stylesheet_.fonts.push_back(default_font);
|
||||
|
||||
wb.create_style("Normal").builtin_id(0)
|
||||
.border(default_border, false)
|
||||
.fill(default_fill, false)
|
||||
.font(default_font, false)
|
||||
.number_format(xlnt::number_format::general(), false);
|
||||
|
||||
wb.create_format()
|
||||
.border(default_border, false)
|
||||
.fill(default_fill, false)
|
||||
.font(default_font, false)
|
||||
.number_format(xlnt::number_format::general(), false)
|
||||
.style("Normal");
|
||||
|
||||
wb.set_theme(theme());
|
||||
|
||||
|
@ -262,59 +315,59 @@ workbook workbook::empty_libre_office()
|
|||
.hidden(false);
|
||||
wb.d_->stylesheet_.protections.push_back(default_protection);
|
||||
|
||||
auto &normal_style = wb.create_style("Normal").builtin_id(0).custom(false);
|
||||
normal_style.alignment(default_alignment, false);
|
||||
normal_style.border(default_border, true);
|
||||
normal_style.fill(default_fill, true);
|
||||
normal_style.font(default_font, true);
|
||||
normal_style.number_format(default_number_format, false);
|
||||
normal_style.protection(default_protection, false);
|
||||
wb.create_style("Normal").builtin_id(0).custom(false)
|
||||
.alignment(default_alignment, false)
|
||||
.border(default_border, true)
|
||||
.fill(default_fill, true)
|
||||
.font(default_font, true)
|
||||
.number_format(default_number_format, false)
|
||||
.protection(default_protection, false);
|
||||
|
||||
auto &comma_style = wb.create_style("Comma").builtin_id(3).custom(false);
|
||||
comma_style.alignment(default_alignment, false);
|
||||
comma_style.border(default_border, true);
|
||||
comma_style.fill(default_fill, true);
|
||||
comma_style.font(second_font, true);
|
||||
comma_style.number_format(number_format::from_builtin_id(43), false);
|
||||
comma_style.protection(default_protection, false);
|
||||
wb.create_style("Comma").builtin_id(3).custom(false)
|
||||
.alignment(default_alignment, false)
|
||||
.border(default_border, true)
|
||||
.fill(default_fill, true)
|
||||
.font(second_font, true)
|
||||
.number_format(number_format::from_builtin_id(43), false)
|
||||
.protection(default_protection, false);
|
||||
|
||||
auto &comma0_style = wb.create_style("Comma [0]").builtin_id(6).custom(false);
|
||||
comma0_style.alignment(default_alignment, false);
|
||||
comma0_style.border(default_border, true);
|
||||
comma0_style.fill(default_fill, true);
|
||||
comma0_style.font(second_font, true);
|
||||
comma0_style.number_format(number_format::from_builtin_id(41), false);
|
||||
comma0_style.protection(default_protection, false);
|
||||
wb.create_style("Comma [0]").builtin_id(6).custom(false)
|
||||
.alignment(default_alignment, false)
|
||||
.border(default_border, true)
|
||||
.fill(default_fill, true)
|
||||
.font(second_font, true)
|
||||
.number_format(number_format::from_builtin_id(41), false)
|
||||
.protection(default_protection, false);
|
||||
|
||||
auto ¤cy_style = wb.create_style("Currency").builtin_id(4).custom(false);
|
||||
currency_style.alignment(default_alignment, false);
|
||||
currency_style.border(default_border, true);
|
||||
currency_style.fill(default_fill, true);
|
||||
currency_style.font(second_font, true);
|
||||
currency_style.number_format(number_format::from_builtin_id(44), false);
|
||||
currency_style.protection(default_protection, false);
|
||||
wb.create_style("Currency").builtin_id(4).custom(false)
|
||||
.alignment(default_alignment, false)
|
||||
.border(default_border, true)
|
||||
.fill(default_fill, true)
|
||||
.font(second_font, true)
|
||||
.number_format(number_format::from_builtin_id(44), false)
|
||||
.protection(default_protection, false);
|
||||
|
||||
auto ¤cy0_style = wb.create_style("Currency [0]").builtin_id(7).custom(false);
|
||||
currency0_style.alignment(default_alignment, false);
|
||||
currency0_style.border(default_border, true);
|
||||
currency0_style.fill(default_fill, true);
|
||||
currency0_style.font(second_font, true);
|
||||
currency0_style.number_format(number_format::from_builtin_id(42), false);
|
||||
currency0_style.protection(default_protection, false);
|
||||
wb.create_style("Currency [0]").builtin_id(7).custom(false)
|
||||
.alignment(default_alignment, false)
|
||||
.border(default_border, true)
|
||||
.fill(default_fill, true)
|
||||
.font(second_font, true)
|
||||
.number_format(number_format::from_builtin_id(42), false)
|
||||
.protection(default_protection, false);
|
||||
|
||||
auto &percent_style = wb.create_style("Percent").builtin_id(5).custom(false);
|
||||
percent_style.alignment(default_alignment, false);
|
||||
percent_style.border(default_border, true);
|
||||
percent_style.fill(default_fill, false);
|
||||
percent_style.font(second_font, true);
|
||||
percent_style.number_format(number_format::percentage(), false);
|
||||
percent_style.protection(default_protection, false);
|
||||
wb.create_style("Percent").builtin_id(5).custom(false)
|
||||
.alignment(default_alignment, false)
|
||||
.border(default_border, true)
|
||||
.fill(default_fill, false)
|
||||
.font(second_font, true)
|
||||
.number_format(number_format::percentage(), false)
|
||||
.protection(default_protection, false);
|
||||
|
||||
auto &format = wb.create_format();
|
||||
format.number_format(default_number_format, true);
|
||||
format.alignment(default_alignment, true);
|
||||
format.protection(default_protection, true);
|
||||
format.style("Normal");
|
||||
wb.create_format()
|
||||
.number_format(default_number_format, true)
|
||||
.alignment(default_alignment, true)
|
||||
.protection(default_protection, true)
|
||||
.style("Normal");
|
||||
|
||||
wb.d_->has_file_version_ = true;
|
||||
wb.d_->file_version_.app_name = "Calc";
|
||||
|
@ -702,7 +755,8 @@ void workbook::load(const std::string &filename)
|
|||
|
||||
void workbook::load(const path &filename)
|
||||
{
|
||||
std::ifstream file_stream(filename.string(), std::ios::binary);
|
||||
std::ifstream file_stream;
|
||||
open_stream(file_stream, filename.string());
|
||||
load(file_stream);
|
||||
}
|
||||
|
||||
|
@ -713,7 +767,8 @@ void workbook::load(const std::string &filename, const std::string &password)
|
|||
|
||||
void workbook::load(const path &filename, const std::string &password)
|
||||
{
|
||||
std::ifstream file_stream(filename.string(), std::iostream::binary);
|
||||
std::ifstream file_stream;
|
||||
open_stream(file_stream, filename.string());
|
||||
return load(file_stream, password);
|
||||
}
|
||||
|
||||
|
@ -745,7 +800,8 @@ void workbook::save(const std::string &filename) const
|
|||
|
||||
void workbook::save(const path &filename) const
|
||||
{
|
||||
std::ofstream file_stream(filename.string(), std::ios::binary);
|
||||
std::ofstream file_stream;
|
||||
open_stream(file_stream, filename.string());
|
||||
save(file_stream);
|
||||
}
|
||||
|
||||
|
@ -758,13 +814,29 @@ void workbook::save(std::ostream &stream) const
|
|||
#ifdef WIN32
|
||||
void workbook::save(const std::wstring &filename)
|
||||
{
|
||||
std::ofstream file_stream(filename, std::ios::binary);
|
||||
std::ofstream file_stream;
|
||||
open_stream(file_stream, filename);
|
||||
save(file_stream);
|
||||
}
|
||||
|
||||
void workbook::save(const std::wstring &filename, const std::string &password)
|
||||
{
|
||||
std::ofstream file_stream;
|
||||
open_stream(file_stream, filename);
|
||||
save(file_stream, password);
|
||||
}
|
||||
|
||||
void workbook::load(const std::wstring &filename)
|
||||
{
|
||||
std::ifstream file_stream(filename, std::ios::binary);
|
||||
std::ifstream file_stream;
|
||||
open_stream(file_stream, filename);
|
||||
load(file_stream);
|
||||
}
|
||||
|
||||
void workbook::load(const std::wstring &filename, const std::string &password)
|
||||
{
|
||||
std::ifstream file_stream;
|
||||
open_stream(file_stream, filename);
|
||||
load(file_stream);
|
||||
}
|
||||
#endif
|
||||
|
@ -1002,7 +1074,7 @@ std::vector<named_range> workbook::get_named_ranges() const
|
|||
return named_ranges;
|
||||
}
|
||||
|
||||
format &workbook::create_format()
|
||||
format workbook::create_format()
|
||||
{
|
||||
register_stylesheet_in_manifest();
|
||||
return d_->stylesheet_.create_format();
|
||||
|
@ -1015,13 +1087,11 @@ bool workbook::has_style(const std::string &name) const
|
|||
|
||||
void workbook::clear_styles()
|
||||
{
|
||||
d_->stylesheet_.styles.clear();
|
||||
apply_to_cells([](cell c) { c.clear_style(); });
|
||||
}
|
||||
|
||||
void workbook::clear_formats()
|
||||
{
|
||||
d_->stylesheet_.formats.clear();
|
||||
apply_to_cells([](cell c) { c.clear_format(); });
|
||||
}
|
||||
|
||||
|
@ -1029,22 +1099,25 @@ void workbook::apply_to_cells(std::function<void(cell)> f)
|
|||
{
|
||||
for (auto ws : *this)
|
||||
{
|
||||
for (auto r : ws.iter_cells(true))
|
||||
for (auto row = ws.get_lowest_row(); row <= ws.get_highest_row(); ++row)
|
||||
{
|
||||
for (auto c : r)
|
||||
for (auto column = ws.get_lowest_column(); column <= ws.get_highest_column(); ++column)
|
||||
{
|
||||
f.operator()(c);
|
||||
if (ws.has_cell(cell_reference(column, row)))
|
||||
{
|
||||
f.operator()(ws.get_cell(cell_reference(column, row)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
format &workbook::get_format(std::size_t format_index)
|
||||
format workbook::get_format(std::size_t format_index)
|
||||
{
|
||||
return d_->stylesheet_.get_format(format_index);
|
||||
}
|
||||
|
||||
const format &workbook::get_format(std::size_t format_index) const
|
||||
const format workbook::get_format(std::size_t format_index) const
|
||||
{
|
||||
return d_->stylesheet_.get_format(format_index);
|
||||
}
|
||||
|
@ -1113,19 +1186,19 @@ const std::vector<std::uint8_t> &workbook::get_thumbnail() const
|
|||
return d_->thumbnail_;
|
||||
}
|
||||
|
||||
style &workbook::create_style(const std::string &name)
|
||||
style workbook::create_style(const std::string &name)
|
||||
{
|
||||
return d_->stylesheet_.create_style().name(name);
|
||||
return d_->stylesheet_.create_style(name);
|
||||
}
|
||||
|
||||
style &workbook::get_style(const std::string &name)
|
||||
style workbook::style(const std::string &name)
|
||||
{
|
||||
return d_->stylesheet_.get_style(name);
|
||||
return d_->stylesheet_.style(name);
|
||||
}
|
||||
|
||||
const style &workbook::get_style(const std::string &name) const
|
||||
const style workbook::style(const std::string &name) const
|
||||
{
|
||||
return d_->stylesheet_.get_style(name);
|
||||
return d_->stylesheet_.style(name);
|
||||
}
|
||||
|
||||
std::string workbook::get_application() const
|
||||
|
|
2
third-party/botan
vendored
2
third-party/botan
vendored
|
@ -1 +1 @@
|
|||
Subproject commit dad94a550613733d8c75b2fbd8db47048dfdaf13
|
||||
Subproject commit 73c2605f50e6192bf6cb560c51d32bc53b4c5597
|
Loading…
Reference in New Issue
Block a user