2017-01-03 09:35:18 +08:00
|
|
|
// Copyright (c) 2014-2017 Thomas Fussell
|
2016-10-25 10:09:15 +08:00
|
|
|
//
|
|
|
|
// 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
|
2016-10-31 03:48:40 +08:00
|
|
|
|
2016-08-05 13:52:05 +08:00
|
|
|
#include <cctype>
|
2016-10-29 22:23:04 +08:00
|
|
|
#include <numeric> // for std::accumulate
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-08-18 19:34:18 +08:00
|
|
|
#include <xlnt/cell/cell.hpp>
|
2016-08-05 13:52:05 +08:00
|
|
|
#include <xlnt/packaging/manifest.hpp>
|
2016-11-20 06:19:38 +08:00
|
|
|
#include <xlnt/utils/path.hpp>
|
2016-08-05 13:52:05 +08:00
|
|
|
#include <xlnt/workbook/const_worksheet_iterator.hpp>
|
|
|
|
#include <xlnt/workbook/workbook.hpp>
|
|
|
|
#include <xlnt/worksheet/worksheet.hpp>
|
2016-12-24 23:04:57 +08:00
|
|
|
#include <detail/constants.hpp>
|
|
|
|
#include <detail/custom_value_traits.hpp>
|
|
|
|
#include <detail/vector_streambuf.hpp>
|
|
|
|
#include <detail/workbook_impl.hpp>
|
|
|
|
#include <detail/xlsx_consumer.hpp>
|
2017-01-05 08:02:31 +08:00
|
|
|
#include <detail/zstream.hpp>
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-11-20 05:42:16 +08:00
|
|
|
namespace std {
|
|
|
|
|
2016-11-25 21:13:55 +08:00
|
|
|
/// <summary>
|
|
|
|
/// Allows xml::qname to be used as a key in a std::unordered_map.
|
|
|
|
/// </summary>
|
2016-11-20 05:42:16 +08:00
|
|
|
template <>
|
|
|
|
struct hash<xml::qname>
|
|
|
|
{
|
2016-11-20 06:19:38 +08:00
|
|
|
std::size_t operator()(const xml::qname &k) const
|
2016-11-20 05:42:16 +08:00
|
|
|
{
|
|
|
|
static std::hash<std::string> hasher;
|
|
|
|
return hasher(k.string());
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace std
|
|
|
|
|
2016-08-05 13:52:05 +08:00
|
|
|
namespace {
|
|
|
|
|
2016-12-23 19:51:30 +08:00
|
|
|
std::array<xlnt::optional<xlnt::rich_text>, 3> parse_header_footer(const std::string &hf_string)
|
2016-12-23 07:57:22 +08:00
|
|
|
{
|
2016-12-23 19:51:30 +08:00
|
|
|
std::array<xlnt::optional<xlnt::rich_text>, 3> result;
|
2016-12-23 07:57:22 +08:00
|
|
|
|
|
|
|
if (hf_string.empty())
|
|
|
|
{
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
enum class hf_code
|
|
|
|
{
|
|
|
|
left_section, // &L
|
|
|
|
center_section, // &C
|
|
|
|
right_section, // &R
|
|
|
|
current_page_number, // &P
|
|
|
|
total_page_number, // &N
|
|
|
|
font_size, // &#
|
|
|
|
text_font_color, // &KRRGGBB or &KTTSNN
|
|
|
|
text_strikethrough, // &S
|
|
|
|
text_superscript, // &X
|
|
|
|
text_subscript, // &Y
|
|
|
|
date, // &D
|
|
|
|
time, // &T
|
|
|
|
picture_as_background, // &G
|
|
|
|
text_single_underline, // &U
|
|
|
|
text_double_underline, // &E
|
|
|
|
workbook_file_path, // &Z
|
|
|
|
workbook_file_name, // &F
|
|
|
|
sheet_tab_name, // &A
|
|
|
|
add_to_page_number, // &+
|
|
|
|
subtract_from_page_number, // &-
|
|
|
|
text_font_name, // &"font name,font type"
|
|
|
|
bold_font_style, // &B
|
|
|
|
italic_font_style, // &I
|
|
|
|
outline_style, // &O
|
|
|
|
shadow_style, // &H
|
|
|
|
text // everything else
|
|
|
|
};
|
|
|
|
|
|
|
|
struct hf_token
|
|
|
|
{
|
|
|
|
hf_code code = hf_code::text;
|
|
|
|
std::string value;
|
|
|
|
};
|
|
|
|
|
|
|
|
std::vector<hf_token> tokens;
|
|
|
|
std::size_t position = 0;
|
|
|
|
|
|
|
|
while (position < hf_string.size())
|
|
|
|
{
|
|
|
|
hf_token token;
|
|
|
|
|
|
|
|
auto next_ampersand = hf_string.find('&', position + 1);
|
|
|
|
token.value = hf_string.substr(position, next_ampersand - position);
|
|
|
|
auto next_position = next_ampersand;
|
|
|
|
|
|
|
|
if (hf_string[position] == '&')
|
|
|
|
{
|
|
|
|
token.value.clear();
|
|
|
|
next_position = position + 2;
|
|
|
|
auto first_code_char = hf_string[position + 1];
|
|
|
|
|
|
|
|
if (first_code_char == '"')
|
|
|
|
{
|
|
|
|
auto end_quote_index = hf_string.find('"', position + 2);
|
|
|
|
next_position = end_quote_index + 1;
|
|
|
|
|
|
|
|
token.value = hf_string.substr(position + 2, end_quote_index - position - 2); // remove quotes
|
|
|
|
token.code = hf_code::text_font_name;
|
|
|
|
}
|
|
|
|
else if (first_code_char == '&')
|
|
|
|
{
|
|
|
|
token.value = "&&"; // escaped ampersand
|
|
|
|
}
|
|
|
|
else if (first_code_char == 'L')
|
|
|
|
{
|
|
|
|
token.code = hf_code::left_section;
|
|
|
|
}
|
|
|
|
else if (first_code_char == 'C')
|
|
|
|
{
|
|
|
|
token.code = hf_code::center_section;
|
|
|
|
}
|
|
|
|
else if (first_code_char == 'R')
|
|
|
|
{
|
|
|
|
token.code = hf_code::right_section;
|
|
|
|
}
|
|
|
|
else if (first_code_char == 'P')
|
|
|
|
{
|
|
|
|
token.code = hf_code::current_page_number;
|
|
|
|
}
|
|
|
|
else if (first_code_char == 'N')
|
|
|
|
{
|
|
|
|
token.code = hf_code::total_page_number;
|
|
|
|
}
|
|
|
|
else if (std::string("0123456789").find(hf_string[position + 1]) != std::string::npos)
|
|
|
|
{
|
|
|
|
token.code = hf_code::font_size;
|
|
|
|
next_position = hf_string.find_first_not_of("0123456789", position + 1);
|
|
|
|
token.value = hf_string.substr(position + 1, next_position - position - 1);
|
|
|
|
}
|
|
|
|
else if (first_code_char == 'K')
|
|
|
|
{
|
|
|
|
if (hf_string[position + 4] == '+' || hf_string[position + 4] == '-')
|
|
|
|
{
|
|
|
|
token.value = hf_string.substr(position + 2, 5);
|
|
|
|
next_position = position + 7;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
token.value = hf_string.substr(position + 2, 6);
|
|
|
|
next_position = position + 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
token.code = hf_code::text_font_color;
|
|
|
|
}
|
|
|
|
else if (first_code_char == 'S')
|
|
|
|
{
|
|
|
|
token.code = hf_code::text_strikethrough;
|
|
|
|
}
|
|
|
|
else if (first_code_char == 'X')
|
|
|
|
{
|
|
|
|
token.code = hf_code::text_superscript;
|
|
|
|
}
|
|
|
|
else if (first_code_char == 'Y')
|
|
|
|
{
|
|
|
|
token.code = hf_code::text_subscript;
|
|
|
|
}
|
|
|
|
else if (first_code_char == 'D')
|
|
|
|
{
|
|
|
|
token.code = hf_code::date;
|
|
|
|
}
|
|
|
|
else if (first_code_char == 'T')
|
|
|
|
{
|
|
|
|
token.code = hf_code::time;
|
|
|
|
}
|
|
|
|
else if (first_code_char == 'G')
|
|
|
|
{
|
|
|
|
token.code = hf_code::picture_as_background;
|
|
|
|
}
|
|
|
|
else if (first_code_char == 'U')
|
|
|
|
{
|
|
|
|
token.code = hf_code::text_single_underline;
|
|
|
|
}
|
|
|
|
else if (first_code_char == 'E')
|
|
|
|
{
|
|
|
|
token.code = hf_code::text_double_underline;
|
|
|
|
}
|
|
|
|
else if (first_code_char == 'Z')
|
|
|
|
{
|
|
|
|
token.code = hf_code::workbook_file_path;
|
|
|
|
}
|
|
|
|
else if (first_code_char == 'F')
|
|
|
|
{
|
|
|
|
token.code = hf_code::workbook_file_name;
|
|
|
|
}
|
|
|
|
else if (first_code_char == 'A')
|
|
|
|
{
|
|
|
|
token.code = hf_code::sheet_tab_name;
|
|
|
|
}
|
|
|
|
else if (first_code_char == '+')
|
|
|
|
{
|
|
|
|
token.code = hf_code::add_to_page_number;
|
|
|
|
}
|
|
|
|
else if (first_code_char == '-')
|
|
|
|
{
|
|
|
|
token.code = hf_code::subtract_from_page_number;
|
|
|
|
}
|
|
|
|
else if (first_code_char == 'B')
|
|
|
|
{
|
|
|
|
token.code = hf_code::bold_font_style;
|
|
|
|
}
|
|
|
|
else if (first_code_char == 'I')
|
|
|
|
{
|
|
|
|
token.code = hf_code::italic_font_style;
|
|
|
|
}
|
|
|
|
else if (first_code_char == 'O')
|
|
|
|
{
|
|
|
|
token.code = hf_code::outline_style;
|
|
|
|
}
|
|
|
|
else if (first_code_char == 'H')
|
|
|
|
{
|
|
|
|
token.code = hf_code::shadow_style;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
position = next_position;
|
|
|
|
tokens.push_back(token);
|
|
|
|
}
|
|
|
|
|
2017-03-21 07:22:46 +08:00
|
|
|
const auto parse_section = [&tokens, &result](hf_code code)
|
|
|
|
{
|
2016-12-24 23:04:57 +08:00
|
|
|
std::vector<hf_code> end_codes{hf_code::left_section, hf_code::center_section, hf_code::right_section};
|
2016-12-23 07:57:22 +08:00
|
|
|
end_codes.erase(std::find(end_codes.begin(), end_codes.end(), code));
|
|
|
|
|
|
|
|
std::size_t start_index = 0;
|
|
|
|
|
|
|
|
while (start_index < tokens.size() && tokens[start_index].code != code)
|
|
|
|
{
|
|
|
|
++start_index;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (start_index == tokens.size())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
++start_index; // skip the section code
|
|
|
|
std::size_t end_index = start_index;
|
|
|
|
|
|
|
|
while (end_index < tokens.size()
|
|
|
|
&& std::find(end_codes.begin(), end_codes.end(), tokens[end_index].code) == end_codes.end())
|
|
|
|
{
|
|
|
|
++end_index;
|
|
|
|
}
|
|
|
|
|
2016-12-23 19:51:30 +08:00
|
|
|
xlnt::rich_text current_text;
|
|
|
|
xlnt::rich_text_run current_run;
|
2016-12-23 07:57:22 +08:00
|
|
|
|
|
|
|
// todo: all this nice parsing and the codes are just being turned back into text representations
|
|
|
|
// It would be nice to create an interface for the library to read and write these codes
|
|
|
|
|
|
|
|
for (auto i = start_index; i < end_index; ++i)
|
|
|
|
{
|
|
|
|
const auto ¤t_token = tokens[i];
|
|
|
|
|
|
|
|
if (current_token.code == hf_code::text)
|
|
|
|
{
|
2016-12-23 19:51:30 +08:00
|
|
|
current_run.first = current_run.first + current_token.value;
|
2016-12-23 07:57:22 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2016-12-23 19:51:30 +08:00
|
|
|
if (!current_run.first.empty())
|
2016-12-23 07:57:22 +08:00
|
|
|
{
|
|
|
|
current_text.add_run(current_run);
|
2016-12-23 19:51:30 +08:00
|
|
|
current_run = xlnt::rich_text_run();
|
2016-12-23 07:57:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (current_token.code)
|
|
|
|
{
|
|
|
|
case hf_code::text:
|
2017-03-21 07:22:46 +08:00
|
|
|
{
|
|
|
|
break; // already handled above
|
|
|
|
}
|
2016-12-23 07:57:22 +08:00
|
|
|
|
|
|
|
case hf_code::left_section:
|
2017-03-21 07:22:46 +08:00
|
|
|
{
|
|
|
|
break; // used below
|
|
|
|
}
|
2016-12-23 07:57:22 +08:00
|
|
|
|
|
|
|
case hf_code::center_section:
|
2017-03-21 07:22:46 +08:00
|
|
|
{
|
|
|
|
break; // used below
|
|
|
|
}
|
2016-12-23 07:57:22 +08:00
|
|
|
|
|
|
|
case hf_code::right_section:
|
2017-03-21 07:22:46 +08:00
|
|
|
{
|
|
|
|
break; // used below
|
|
|
|
}
|
2016-12-23 07:57:22 +08:00
|
|
|
|
|
|
|
case hf_code::current_page_number:
|
2017-03-21 07:22:46 +08:00
|
|
|
{
|
|
|
|
current_run.first = current_run.first + "&P";
|
|
|
|
break;
|
|
|
|
}
|
2016-12-23 07:57:22 +08:00
|
|
|
|
|
|
|
case hf_code::total_page_number:
|
2016-12-23 19:51:30 +08:00
|
|
|
{
|
2017-03-21 07:22:46 +08:00
|
|
|
current_run.first = current_run.first + "&N";
|
|
|
|
break;
|
2016-12-23 19:51:30 +08:00
|
|
|
}
|
2016-12-23 07:57:22 +08:00
|
|
|
|
2017-03-21 07:22:46 +08:00
|
|
|
case hf_code::font_size:
|
2016-12-23 07:57:22 +08:00
|
|
|
{
|
2016-12-23 19:51:30 +08:00
|
|
|
if (!current_run.second.is_set())
|
|
|
|
{
|
|
|
|
current_run.second = xlnt::font();
|
|
|
|
}
|
2017-03-21 07:22:46 +08:00
|
|
|
|
|
|
|
current_run.second.get().size(std::stod(current_token.value));
|
|
|
|
|
|
|
|
break;
|
2016-12-23 07:57:22 +08:00
|
|
|
}
|
|
|
|
|
2017-03-21 07:22:46 +08:00
|
|
|
case hf_code::text_font_color:
|
|
|
|
{
|
|
|
|
if (current_token.value.size() == 6)
|
|
|
|
{
|
|
|
|
if (!current_run.second.is_set())
|
|
|
|
{
|
|
|
|
current_run.second = xlnt::font();
|
|
|
|
}
|
|
|
|
|
|
|
|
current_run.second.get().color(xlnt::rgb_color(current_token.value));
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2016-12-23 07:57:22 +08:00
|
|
|
|
|
|
|
case hf_code::text_strikethrough:
|
2017-03-21 07:22:46 +08:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2016-12-23 07:57:22 +08:00
|
|
|
|
|
|
|
case hf_code::text_superscript:
|
2017-03-21 07:22:46 +08:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2016-12-23 07:57:22 +08:00
|
|
|
|
|
|
|
case hf_code::text_subscript:
|
2017-03-21 07:22:46 +08:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2016-12-23 07:57:22 +08:00
|
|
|
|
|
|
|
case hf_code::date:
|
2017-03-21 07:22:46 +08:00
|
|
|
{
|
|
|
|
current_run.first = current_run.first + "&D";
|
|
|
|
break;
|
|
|
|
}
|
2016-12-23 07:57:22 +08:00
|
|
|
|
|
|
|
case hf_code::time:
|
2017-03-21 07:22:46 +08:00
|
|
|
{
|
|
|
|
current_run.first = current_run.first + "&T";
|
|
|
|
break;
|
|
|
|
}
|
2016-12-23 07:57:22 +08:00
|
|
|
|
|
|
|
case hf_code::picture_as_background:
|
2017-03-21 07:22:46 +08:00
|
|
|
{
|
|
|
|
current_run.first = current_run.first + "&G";
|
|
|
|
break;
|
|
|
|
}
|
2016-12-23 07:57:22 +08:00
|
|
|
|
|
|
|
case hf_code::text_single_underline:
|
2017-03-21 07:22:46 +08:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2016-12-23 07:57:22 +08:00
|
|
|
|
|
|
|
case hf_code::text_double_underline:
|
2017-03-21 07:22:46 +08:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2016-12-23 07:57:22 +08:00
|
|
|
|
|
|
|
case hf_code::workbook_file_path:
|
2017-03-21 07:22:46 +08:00
|
|
|
{
|
|
|
|
current_run.first = current_run.first + "&Z";
|
|
|
|
break;
|
|
|
|
}
|
2016-12-23 07:57:22 +08:00
|
|
|
|
|
|
|
case hf_code::workbook_file_name:
|
2017-03-21 07:22:46 +08:00
|
|
|
{
|
|
|
|
current_run.first = current_run.first + "&F";
|
|
|
|
break;
|
|
|
|
}
|
2016-12-23 07:57:22 +08:00
|
|
|
|
|
|
|
case hf_code::sheet_tab_name:
|
2017-03-21 07:22:46 +08:00
|
|
|
{
|
|
|
|
current_run.first = current_run.first + "&A";
|
|
|
|
break;
|
|
|
|
}
|
2016-12-23 07:57:22 +08:00
|
|
|
|
|
|
|
case hf_code::add_to_page_number:
|
|
|
|
{
|
2017-03-21 07:22:46 +08:00
|
|
|
break;
|
2016-12-24 23:04:57 +08:00
|
|
|
}
|
2016-12-23 07:57:22 +08:00
|
|
|
|
2017-03-21 07:22:46 +08:00
|
|
|
case hf_code::subtract_from_page_number:
|
2016-12-24 23:04:57 +08:00
|
|
|
{
|
2017-03-21 07:22:46 +08:00
|
|
|
break;
|
2016-12-24 23:04:57 +08:00
|
|
|
}
|
|
|
|
|
2017-03-21 07:22:46 +08:00
|
|
|
case hf_code::text_font_name:
|
2016-12-24 23:04:57 +08:00
|
|
|
{
|
2017-03-21 07:22:46 +08:00
|
|
|
auto comma_index = current_token.value.find(',');
|
|
|
|
auto font_name = current_token.value.substr(0, comma_index);
|
2016-12-24 23:04:57 +08:00
|
|
|
|
2017-03-21 07:22:46 +08:00
|
|
|
if (!current_run.second.is_set())
|
2016-12-23 19:51:30 +08:00
|
|
|
{
|
2017-03-21 07:22:46 +08:00
|
|
|
current_run.second = xlnt::font();
|
2016-12-23 19:51:30 +08:00
|
|
|
}
|
2017-03-21 07:22:46 +08:00
|
|
|
|
|
|
|
if (font_name != "-")
|
2016-12-23 07:57:22 +08:00
|
|
|
{
|
2017-03-21 07:22:46 +08:00
|
|
|
current_run.second.get().name(font_name);
|
2016-12-23 07:57:22 +08:00
|
|
|
}
|
2017-03-21 07:22:46 +08:00
|
|
|
|
|
|
|
if (comma_index != std::string::npos)
|
2016-12-23 07:57:22 +08:00
|
|
|
{
|
2017-03-21 07:22:46 +08:00
|
|
|
auto font_type = current_token.value.substr(comma_index + 1);
|
|
|
|
|
|
|
|
if (font_type == "Bold")
|
|
|
|
{
|
|
|
|
current_run.second.get().bold(true);
|
|
|
|
}
|
|
|
|
else if (font_type == "Italic")
|
|
|
|
{
|
|
|
|
// TODO
|
|
|
|
}
|
|
|
|
else if (font_type == "BoldItalic")
|
|
|
|
{
|
|
|
|
current_run.second.get().bold(true);
|
|
|
|
}
|
2016-12-23 07:57:22 +08:00
|
|
|
}
|
|
|
|
|
2017-03-21 07:22:46 +08:00
|
|
|
break;
|
|
|
|
}
|
2016-12-23 07:57:22 +08:00
|
|
|
|
|
|
|
case hf_code::bold_font_style:
|
2016-12-23 19:51:30 +08:00
|
|
|
{
|
2017-03-21 07:22:46 +08:00
|
|
|
if (!current_run.second.is_set())
|
|
|
|
{
|
|
|
|
current_run.second = xlnt::font();
|
|
|
|
}
|
|
|
|
|
|
|
|
current_run.second.get().bold(true);
|
|
|
|
|
|
|
|
break;
|
2016-12-23 19:51:30 +08:00
|
|
|
}
|
2016-12-23 07:57:22 +08:00
|
|
|
|
|
|
|
case hf_code::italic_font_style:
|
2017-03-21 07:22:46 +08:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2016-12-23 07:57:22 +08:00
|
|
|
|
|
|
|
case hf_code::outline_style:
|
2017-03-21 07:22:46 +08:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2016-12-23 07:57:22 +08:00
|
|
|
|
|
|
|
case hf_code::shadow_style:
|
2017-03-21 07:22:46 +08:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2016-12-23 07:57:22 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-23 19:51:30 +08:00
|
|
|
if (!current_run.first.empty())
|
2016-12-23 07:57:22 +08:00
|
|
|
{
|
|
|
|
current_text.add_run(current_run);
|
|
|
|
}
|
|
|
|
|
2016-12-24 23:04:57 +08:00
|
|
|
auto location_index =
|
|
|
|
static_cast<std::size_t>(code == hf_code::left_section ? 0 : code == hf_code::center_section ? 1 : 2);
|
2016-12-23 07:57:22 +08:00
|
|
|
|
|
|
|
if (!current_text.plain_text().empty())
|
|
|
|
{
|
|
|
|
result[location_index] = current_text;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
parse_section(hf_code::left_section);
|
|
|
|
parse_section(hf_code::center_section);
|
|
|
|
parse_section(hf_code::right_section);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
xml::qname qn(const std::string &namespace_, const std::string &name)
|
|
|
|
{
|
|
|
|
return xml::qname(xlnt::constants::ns(namespace_), name);
|
|
|
|
}
|
|
|
|
|
2016-12-23 07:57:22 +08:00
|
|
|
} // namespace
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
2016-11-30 07:31:06 +08:00
|
|
|
#ifndef NDEBUG
|
2016-11-25 21:13:55 +08:00
|
|
|
#define THROW_ON_INVALID_XML
|
2016-11-30 07:31:06 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef THROW_ON_INVALID_XML
|
|
|
|
#define unexpected_element(element) throw xlnt::exception(element.string());
|
|
|
|
#else
|
|
|
|
#define unexpected_element(element) skip_remaining_content(element);
|
|
|
|
#endif
|
2016-11-25 21:13:55 +08:00
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Returns true if bool_string represents a true xsd:boolean.
|
|
|
|
/// </summary>
|
2016-08-05 13:52:05 +08:00
|
|
|
bool is_true(const std::string &bool_string)
|
|
|
|
{
|
2016-11-25 21:13:55 +08:00
|
|
|
if (bool_string == "1" || bool_string == "true")
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef THROW_ON_INVALID_XML
|
|
|
|
if (bool_string == "0" || bool_string == "false")
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
throw xlnt::exception("xsd:boolean should be one of: 0, 1, true, or false, found " + bool_string);
|
|
|
|
#else
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-11-30 07:31:06 +08:00
|
|
|
return false;
|
2016-08-05 13:52:05 +08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-11-30 07:31:06 +08:00
|
|
|
/// <summary>
|
|
|
|
/// Helper template function that returns true if element is in container.
|
|
|
|
/// </summary>
|
2016-12-24 23:04:57 +08:00
|
|
|
template <typename T>
|
2016-11-30 07:31:06 +08:00
|
|
|
bool contains(const std::vector<T> &container, const T &element)
|
2016-11-25 21:13:55 +08:00
|
|
|
{
|
2016-11-30 07:31:06 +08:00
|
|
|
return std::find(container.begin(), container.end(), element) != container.end();
|
2016-11-25 21:13:55 +08:00
|
|
|
}
|
|
|
|
|
2016-08-05 13:52:05 +08:00
|
|
|
} // namespace
|
|
|
|
|
2016-12-11 03:46:21 +08:00
|
|
|
/*
|
|
|
|
class parsing_context
|
|
|
|
{
|
|
|
|
public:
|
2016-12-24 23:04:57 +08:00
|
|
|
parsing_context(xlnt::detail::zip_file_reader &archive, const std::string &filename)
|
2016-12-11 03:46:21 +08:00
|
|
|
: parser_(stream_, filename)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
xml::parser &parser();
|
|
|
|
|
|
|
|
private:
|
|
|
|
std::istream stream_;
|
|
|
|
xml::parser parser_;
|
|
|
|
};
|
|
|
|
*/
|
|
|
|
|
2016-08-05 13:52:05 +08:00
|
|
|
namespace xlnt {
|
|
|
|
namespace detail {
|
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
xlsx_consumer::xlsx_consumer(workbook &target)
|
2017-01-11 09:25:59 +08:00
|
|
|
: target_(target),
|
|
|
|
parser_(nullptr)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void xlsx_consumer::read(std::istream &source)
|
|
|
|
{
|
2017-01-05 08:02:31 +08:00
|
|
|
archive_.reset(new izstream(source));
|
2016-11-20 06:19:38 +08:00
|
|
|
populate_workbook();
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
xml::parser &xlsx_consumer::parser()
|
|
|
|
{
|
2016-11-20 06:19:38 +08:00
|
|
|
return *parser_;
|
2016-10-12 11:16:14 +08:00
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-11-25 21:13:55 +08:00
|
|
|
std::vector<relationship> xlsx_consumer::read_relationships(const path &part)
|
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
const auto part_rels_path = part.parent().append("_rels")
|
|
|
|
.append(part.filename() + ".rels").relative_to(path("/"));
|
2016-12-02 21:37:50 +08:00
|
|
|
|
2016-11-25 21:13:55 +08:00
|
|
|
std::vector<xlnt::relationship> relationships;
|
2016-12-24 23:04:57 +08:00
|
|
|
if (!archive_->has_file(part_rels_path)) return relationships;
|
2016-11-25 21:13:55 +08:00
|
|
|
|
2016-12-24 23:04:57 +08:00
|
|
|
auto rels_streambuf = archive_->open(part_rels_path);
|
|
|
|
std::istream rels_stream(rels_streambuf.get());
|
2016-12-02 21:37:50 +08:00
|
|
|
xml::parser parser(rels_stream, part_rels_path.string());
|
2016-11-25 21:13:55 +08:00
|
|
|
parser_ = &parser;
|
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_start_element(qn("relationships", "Relationships"), xml::content::complex);
|
2016-11-25 21:13:55 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
while (in_element(qn("relationships", "Relationships")))
|
2016-11-25 21:13:55 +08:00
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_start_element(qn("relationships", "Relationship"), xml::content::simple);
|
2016-11-30 08:05:47 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
const auto target_mode = parser.attribute_present("TargetMode")
|
|
|
|
? parser.attribute<xlnt::target_mode>("TargetMode")
|
|
|
|
: xlnt::target_mode::internal;
|
|
|
|
relationships.emplace_back(parser.attribute("Id"),
|
|
|
|
parser.attribute<xlnt::relationship_type>("Type"),
|
|
|
|
xlnt::uri(part.string()), xlnt::uri(parser.attribute("Target")),
|
|
|
|
target_mode);
|
2016-12-02 21:37:50 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_end_element(qn("relationships", "Relationship"));
|
2016-11-25 21:13:55 +08:00
|
|
|
}
|
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_end_element(qn("relationships", "Relationships"));
|
2016-11-25 21:13:55 +08:00
|
|
|
parser_ = nullptr;
|
|
|
|
|
|
|
|
return relationships;
|
|
|
|
}
|
|
|
|
|
2016-11-20 05:42:16 +08:00
|
|
|
void xlsx_consumer::read_part(const std::vector<relationship> &rel_chain)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
const auto &manifest = target_.manifest();
|
2017-01-11 09:25:59 +08:00
|
|
|
const auto part_path = manifest.canonicalize(rel_chain);
|
2016-12-24 23:04:57 +08:00
|
|
|
auto part_streambuf = archive_->open(part_path);
|
|
|
|
std::istream part_stream(part_streambuf.get());
|
2017-01-11 09:25:59 +08:00
|
|
|
xml::parser parser(part_stream, part_path.string());
|
2016-11-20 05:42:16 +08:00
|
|
|
parser_ = &parser;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
switch (rel_chain.back().type())
|
2016-11-20 05:42:16 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::core_properties:
|
2017-01-17 02:05:19 +08:00
|
|
|
read_core_properties();
|
2016-11-20 06:19:38 +08:00
|
|
|
break;
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::extended_properties:
|
2017-01-17 02:05:19 +08:00
|
|
|
read_extended_properties();
|
2016-11-20 06:19:38 +08:00
|
|
|
break;
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::custom_properties:
|
2017-01-17 02:05:19 +08:00
|
|
|
read_custom_properties();
|
2016-11-20 06:19:38 +08:00
|
|
|
break;
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::office_document:
|
|
|
|
read_office_document(manifest.content_type(part_path));
|
2016-11-20 06:19:38 +08:00
|
|
|
break;
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::connections:
|
2016-11-20 06:19:38 +08:00
|
|
|
read_connections();
|
|
|
|
break;
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::custom_xml_mappings:
|
2016-11-20 06:19:38 +08:00
|
|
|
read_custom_xml_mappings();
|
|
|
|
break;
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::external_workbook_references:
|
2016-11-20 06:19:38 +08:00
|
|
|
read_external_workbook_references();
|
|
|
|
break;
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::pivot_table:
|
2016-11-20 06:19:38 +08:00
|
|
|
read_pivot_table();
|
|
|
|
break;
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::shared_workbook_revision_headers:
|
2016-11-20 06:19:38 +08:00
|
|
|
read_shared_workbook_revision_headers();
|
|
|
|
break;
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::volatile_dependencies:
|
2016-11-20 06:19:38 +08:00
|
|
|
read_volatile_dependencies();
|
|
|
|
break;
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::shared_string_table:
|
2016-11-20 06:19:38 +08:00
|
|
|
read_shared_string_table();
|
|
|
|
break;
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::stylesheet:
|
2016-11-20 06:19:38 +08:00
|
|
|
read_stylesheet();
|
|
|
|
break;
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::theme:
|
2016-11-20 06:19:38 +08:00
|
|
|
read_theme();
|
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::chartsheet:
|
|
|
|
read_chartsheet(rel_chain.back().id());
|
2016-11-20 06:19:38 +08:00
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::dialogsheet:
|
|
|
|
read_dialogsheet(rel_chain.back().id());
|
2016-11-20 06:19:38 +08:00
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::worksheet:
|
|
|
|
read_worksheet(rel_chain.back().id());
|
2016-11-20 06:19:38 +08:00
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::thumbnail:
|
|
|
|
read_image(part_path);
|
2016-11-20 06:19:38 +08:00
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::calculation_chain:
|
2016-11-20 06:19:38 +08:00
|
|
|
read_calculation_chain();
|
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::hyperlink:
|
2016-11-20 06:19:38 +08:00
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::comments:
|
2016-11-20 06:19:38 +08:00
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::vml_drawing:
|
2016-11-20 06:19:38 +08:00
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::unknown:
|
2016-11-20 06:19:38 +08:00
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::printer_settings:
|
2016-11-20 06:19:38 +08:00
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::custom_property:
|
2016-11-20 06:19:38 +08:00
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::drawings:
|
2016-11-20 06:19:38 +08:00
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::pivot_table_cache_definition:
|
2016-11-20 06:19:38 +08:00
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::pivot_table_cache_records:
|
2016-11-20 06:19:38 +08:00
|
|
|
break;
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::query_table:
|
2016-11-20 06:19:38 +08:00
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::shared_workbook:
|
2016-11-20 06:19:38 +08:00
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::revision_log:
|
2016-11-20 06:19:38 +08:00
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::shared_workbook_user_data:
|
2016-11-20 06:19:38 +08:00
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::single_cell_table_definitions:
|
2016-11-20 06:19:38 +08:00
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::table_definition:
|
2016-11-20 06:19:38 +08:00
|
|
|
break;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
case relationship_type::image:
|
|
|
|
read_image(part_path);
|
2016-11-20 06:19:38 +08:00
|
|
|
break;
|
2016-11-20 05:42:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-11-20 05:42:16 +08:00
|
|
|
parser_ = nullptr;
|
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-11-20 05:42:16 +08:00
|
|
|
void xlsx_consumer::populate_workbook()
|
|
|
|
{
|
2016-11-20 06:19:38 +08:00
|
|
|
target_.clear();
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
read_content_types();
|
|
|
|
const auto root_path = path("/");
|
2016-11-20 05:42:16 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
for (const auto &package_rel : read_relationships(root_path))
|
2016-11-20 05:42:16 +08:00
|
|
|
{
|
2016-12-04 20:29:10 +08:00
|
|
|
manifest().register_relationship(package_rel);
|
2016-11-20 06:19:38 +08:00
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
for (auto package_rel : manifest().relationships(root_path))
|
2016-11-20 05:42:16 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
if (package_rel.type() == relationship_type::office_document)
|
2016-11-20 05:42:16 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
// Read the workbook after all the other package parts
|
|
|
|
continue;
|
2016-11-20 05:42:16 +08:00
|
|
|
}
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
read_part({package_rel});
|
|
|
|
}
|
2016-11-20 05:42:16 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
for (const auto &relationship_source_string : archive_->files())
|
2016-11-20 05:42:16 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
for (const auto &part_rel : read_relationships(path(relationship_source_string)))
|
2016-11-20 05:42:16 +08:00
|
|
|
{
|
2016-12-04 20:29:10 +08:00
|
|
|
manifest().register_relationship(part_rel);
|
2016-11-20 05:42:16 +08:00
|
|
|
}
|
|
|
|
}
|
2016-12-02 21:37:50 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
read_part({ manifest().relationship(root_path,
|
|
|
|
relationship_type::office_document) });
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Package Parts
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
void xlsx_consumer::read_content_types()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
auto &manifest = target_.manifest();
|
2016-12-24 23:04:57 +08:00
|
|
|
auto content_types_streambuf = archive_->open(path("[Content_Types].xml"));
|
|
|
|
std::istream content_types_stream(content_types_streambuf.get());
|
|
|
|
xml::parser parser(content_types_stream, "[Content_Types].xml");
|
2016-11-25 21:13:55 +08:00
|
|
|
parser_ = &parser;
|
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_start_element(qn("content-types", "Types"), xml::content::complex);
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
while (in_element(qn("content-types", "Types")))
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
2016-11-25 21:13:55 +08:00
|
|
|
auto current_element = expect_start_element(xml::content::complex);
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
if (current_element == qn("content-types", "Default"))
|
2016-09-17 10:59:13 +08:00
|
|
|
{
|
2016-11-20 06:19:38 +08:00
|
|
|
auto extension = parser.attribute("Extension");
|
|
|
|
auto content_type = parser.attribute("ContentType");
|
|
|
|
manifest.register_default_type(extension, content_type);
|
2016-09-17 10:59:13 +08:00
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_element == qn("content-types", "Override"))
|
2016-09-17 10:59:13 +08:00
|
|
|
{
|
2016-11-20 06:19:38 +08:00
|
|
|
auto part_name = parser.attribute("PartName");
|
|
|
|
auto content_type = parser.attribute("ContentType");
|
|
|
|
manifest.register_override_type(path(part_name), content_type);
|
2016-09-17 10:59:13 +08:00
|
|
|
}
|
2016-11-25 21:13:55 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
unexpected_element(current_element);
|
|
|
|
}
|
|
|
|
|
|
|
|
expect_end_element(current_element);
|
2016-11-20 06:19:38 +08:00
|
|
|
}
|
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_end_element(qn("content-types", "Types"));
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2017-01-17 02:05:19 +08:00
|
|
|
void xlsx_consumer::read_core_properties()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2017-01-17 02:05:19 +08:00
|
|
|
//qn("extended-properties", "Properties");
|
|
|
|
//qn("custom-properties", "Properties");
|
|
|
|
expect_start_element(qn("core-properties", "coreProperties"), xml::content::complex);
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-01-17 02:05:19 +08:00
|
|
|
while (in_element(qn("core-properties", "coreProperties")))
|
2016-11-20 05:42:16 +08:00
|
|
|
{
|
2017-01-17 02:05:19 +08:00
|
|
|
const auto property_element = expect_start_element(xml::content::simple);
|
|
|
|
const auto prop = detail::from_string<core_property>(property_element.name());
|
|
|
|
if (prop == core_property::created || prop == core_property::modified)
|
2017-01-03 06:42:16 +08:00
|
|
|
{
|
2017-01-17 02:05:19 +08:00
|
|
|
skip_attribute(qn("xsi", "type"));
|
2017-01-03 06:42:16 +08:00
|
|
|
}
|
2017-01-17 02:05:19 +08:00
|
|
|
target_.core_property(prop, read_text());
|
|
|
|
expect_end_element(property_element);
|
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-01-17 02:05:19 +08:00
|
|
|
expect_end_element(qn("core-properties", "coreProperties"));
|
|
|
|
}
|
|
|
|
|
|
|
|
void xlsx_consumer::read_extended_properties()
|
|
|
|
{
|
|
|
|
expect_start_element(qn("extended-properties", "Properties"), xml::content::complex);
|
|
|
|
|
|
|
|
while (in_element(qn("extended-properties", "Properties")))
|
|
|
|
{
|
|
|
|
const auto property_element = expect_start_element(xml::content::mixed);
|
|
|
|
const auto prop = detail::from_string<extended_property>(property_element.name());
|
|
|
|
target_.extended_property(prop, read_variant());
|
2016-11-25 21:13:55 +08:00
|
|
|
expect_end_element(property_element);
|
2016-11-20 06:19:38 +08:00
|
|
|
}
|
|
|
|
|
2017-01-17 02:05:19 +08:00
|
|
|
expect_end_element(qn("extended-properties", "Properties"));
|
|
|
|
}
|
|
|
|
|
|
|
|
void xlsx_consumer::read_custom_properties()
|
|
|
|
{
|
|
|
|
expect_start_element(qn("custom-properties", "Properties"), xml::content::complex);
|
2017-01-03 06:42:16 +08:00
|
|
|
|
2017-01-17 02:05:19 +08:00
|
|
|
while (in_element(qn("custom-properties", "Properties")))
|
2017-01-03 06:42:16 +08:00
|
|
|
{
|
2017-01-17 02:05:19 +08:00
|
|
|
const auto property_element = expect_start_element(xml::content::complex);
|
|
|
|
const auto prop = parser().attribute("name");
|
|
|
|
const auto format_id = parser().attribute("fmtid");
|
|
|
|
const auto property_id = parser().attribute("pid");
|
|
|
|
target_.custom_property(prop, read_variant());
|
|
|
|
expect_end_element(property_element);
|
2017-01-03 06:42:16 +08:00
|
|
|
}
|
2017-01-17 02:05:19 +08:00
|
|
|
|
|
|
|
expect_end_element(qn("custom-properties", "Properties"));
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-12-11 03:46:21 +08:00
|
|
|
void xlsx_consumer::read_office_document(const std::string &content_type) // CT_Workbook
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
if (content_type != "application/vnd."
|
|
|
|
"openxmlformats-officedocument.spreadsheetml.sheet.main+xml"
|
|
|
|
&& content_type != "application/vnd."
|
|
|
|
"openxmlformats-officedocument.spreadsheetml.template.main+xml")
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
throw xlnt::invalid_file(content_type);
|
2016-11-20 06:19:38 +08:00
|
|
|
}
|
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_start_element(qn("workbook", "workbook"), xml::content::complex);
|
|
|
|
skip_attribute(qn("mc", "Ignorable"));
|
2016-12-02 21:37:50 +08:00
|
|
|
read_namespaces();
|
2016-08-14 07:44:45 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
while (in_element(qn("workbook", "workbook")))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-11-25 21:13:55 +08:00
|
|
|
auto current_workbook_element = expect_start_element(xml::content::complex);
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
if (current_workbook_element == qn("workbook", "fileVersion")) // CT_FileVersion 0-1
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
detail::workbook_impl::file_version_t file_version;
|
|
|
|
|
|
|
|
if (parser().attribute_present("appName"))
|
|
|
|
{
|
|
|
|
file_version.app_name = parser().attribute("appName");
|
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
if (parser().attribute_present("lastEdited"))
|
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
file_version.last_edited = parser().attribute<std::size_t>("lastEdited");
|
2016-10-25 10:09:15 +08:00
|
|
|
}
|
2016-11-25 21:13:55 +08:00
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
if (parser().attribute_present("lowestEdited"))
|
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
file_version.lowest_edited = parser().attribute<std::size_t>("lowestEdited");
|
2016-10-25 10:09:15 +08:00
|
|
|
}
|
2016-11-25 21:13:55 +08:00
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
if (parser().attribute_present("lowestEdited"))
|
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
file_version.rup_build = parser().attribute<std::size_t>("rupBuild");
|
2016-10-25 10:09:15 +08:00
|
|
|
}
|
2016-12-02 21:37:50 +08:00
|
|
|
|
|
|
|
skip_attribute("codeName");
|
|
|
|
|
|
|
|
target_.d_->file_version_ = file_version;
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_workbook_element == qn("workbook", "fileSharing")) // CT_FileSharing 0-1
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-12-11 03:46:21 +08:00
|
|
|
skip_remaining_content(current_workbook_element);
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_workbook_element == qn("workbook", "workbookPr")) // CT_WorkbookPr 0-1
|
2016-12-11 03:46:21 +08:00
|
|
|
{
|
|
|
|
if (parser().attribute_present("date1904"))
|
|
|
|
{
|
2016-12-24 23:04:57 +08:00
|
|
|
target_.base_date(
|
|
|
|
is_true(parser().attribute("date1904")) ? calendar::mac_1904 : calendar::windows_1900);
|
2016-12-11 03:46:21 +08:00
|
|
|
}
|
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
skip_attributes({"codeName", "defaultThemeVersion",
|
|
|
|
"backupFile", "showObjects", "filterPrivacy", "dateCompatibility"});
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_workbook_element == qn("workbook", "workbookProtection")) // CT_WorkbookProtection 0-1
|
2016-12-11 03:46:21 +08:00
|
|
|
{
|
|
|
|
skip_remaining_content(current_workbook_element);
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_workbook_element == qn("workbook", "bookViews")) // CT_BookViews 0-1
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
while (in_element(qn("workbook", "bookViews")))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_start_element(qn("workbook", "workbookView"), xml::content::simple);
|
|
|
|
skip_attributes({"activeTab", "firstSheet",
|
|
|
|
"showHorizontalScroll", "showSheetTabs", "showVerticalScroll"});
|
2016-09-22 07:04:16 +08:00
|
|
|
|
|
|
|
workbook_view view;
|
2016-11-30 07:31:06 +08:00
|
|
|
view.x_window = parser().attribute<std::size_t>("xWindow");
|
|
|
|
view.y_window = parser().attribute<std::size_t>("yWindow");
|
|
|
|
view.window_width = parser().attribute<std::size_t>("windowWidth");
|
|
|
|
view.window_height = parser().attribute<std::size_t>("windowHeight");
|
2016-11-20 06:19:38 +08:00
|
|
|
|
|
|
|
if (parser().attribute_present("tabRatio"))
|
|
|
|
{
|
2016-11-30 07:31:06 +08:00
|
|
|
view.tab_ratio = parser().attribute<std::size_t>("tabRatio");
|
2016-11-20 06:19:38 +08:00
|
|
|
}
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
target_.view(view);
|
2017-01-11 09:25:59 +08:00
|
|
|
|
|
|
|
skip_attributes();
|
|
|
|
expect_end_element(qn("workbook", "workbookView"));
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_workbook_element == qn("workbook", "sheets")) // CT_Sheets 1
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
|
|
|
std::size_t index = 0;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
while (in_element(qn("workbook", "sheets")))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_start_element(qn("spreadsheetml", "sheet"), xml::content::simple);
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2016-11-25 21:13:55 +08:00
|
|
|
auto title = parser().attribute("name");
|
2016-12-02 21:37:50 +08:00
|
|
|
skip_attribute("state");
|
2016-09-22 07:04:16 +08:00
|
|
|
|
|
|
|
sheet_title_index_map_[title] = index++;
|
2016-11-30 07:31:06 +08:00
|
|
|
sheet_title_id_map_[title] = parser().attribute<std::size_t>("sheetId");
|
2017-01-11 09:25:59 +08:00
|
|
|
target_.d_->sheet_title_rel_id_map_[title] = parser().attribute(qn("r", "id"));
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_end_element(qn("spreadsheetml", "sheet"));
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_workbook_element == qn("workbook", "functionGroups")) // CT_FunctionGroups 0-1
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
skip_remaining_content(current_workbook_element);
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_workbook_element == qn("workbook", "externalReferences")) // CT_ExternalReferences 0-1
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
skip_remaining_content(current_workbook_element);
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_workbook_element == qn("workbook", "definedNames")) // CT_DefinedNames 0-1
|
2016-10-25 10:09:15 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
skip_remaining_content(current_workbook_element);
|
2016-11-25 21:13:55 +08:00
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_workbook_element == qn("workbook", "calcPr")) // CT_CalcPr 0-1
|
2016-12-11 03:46:21 +08:00
|
|
|
{
|
|
|
|
skip_remaining_content(current_workbook_element);
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_workbook_element == qn("workbook", "oleSize")) // CT_OleSize 0-1
|
2016-12-11 03:46:21 +08:00
|
|
|
{
|
|
|
|
skip_remaining_content(current_workbook_element);
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_workbook_element == qn("workbook", "customWorkbookViews")) // CT_CustomWorkbookViews 0-1
|
2016-12-11 03:46:21 +08:00
|
|
|
{
|
|
|
|
skip_remaining_content(current_workbook_element);
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_workbook_element == qn("workbook", "pivotCaches")) // CT_PivotCaches 0-1
|
2016-12-11 03:46:21 +08:00
|
|
|
{
|
|
|
|
skip_remaining_content(current_workbook_element);
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_workbook_element == qn("workbook", "smartTagPr")) // CT_SmartTagPr 0-1
|
2016-12-11 03:46:21 +08:00
|
|
|
{
|
|
|
|
skip_remaining_content(current_workbook_element);
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_workbook_element == qn("workbook", "smartTagTypes")) // CT_SmartTagTypes 0-1
|
2016-12-11 03:46:21 +08:00
|
|
|
{
|
|
|
|
skip_remaining_content(current_workbook_element);
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_workbook_element == qn("workbook", "webPublishing")) // CT_WebPublishing 0-1
|
2016-12-11 03:46:21 +08:00
|
|
|
{
|
|
|
|
skip_remaining_content(current_workbook_element);
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_workbook_element == qn("workbook", "fileRecoveryPr")) // CT_FileRecoveryPr 0+
|
2016-12-11 03:46:21 +08:00
|
|
|
{
|
|
|
|
skip_remaining_content(current_workbook_element);
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_workbook_element == qn("workbook", "webPublishObjects")) // CT_WebPublishObjects 0-1
|
2016-12-11 03:46:21 +08:00
|
|
|
{
|
|
|
|
skip_remaining_content(current_workbook_element);
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_workbook_element == qn("workbook", "extLst")) // CT_ExtensionList 0-1
|
2016-12-11 03:46:21 +08:00
|
|
|
{
|
|
|
|
skip_remaining_content(current_workbook_element);
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_workbook_element == qn("mc", "AlternateContent"))
|
2016-12-11 03:46:21 +08:00
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
skip_remaining_content(current_workbook_element);
|
2016-12-11 03:46:21 +08:00
|
|
|
}
|
2016-11-25 21:13:55 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
unexpected_element(current_workbook_element);
|
2016-10-25 10:09:15 +08:00
|
|
|
}
|
2016-11-25 21:13:55 +08:00
|
|
|
|
|
|
|
expect_end_element(current_workbook_element);
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 05:42:16 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_end_element(qn("workbook", "workbook"));
|
2016-12-02 21:37:50 +08:00
|
|
|
|
|
|
|
auto workbook_rel = manifest().relationship(path("/"), relationship_type::office_document);
|
|
|
|
auto workbook_path = workbook_rel.target().path();
|
|
|
|
|
|
|
|
if (manifest().has_relationship(workbook_path, relationship_type::shared_string_table))
|
|
|
|
{
|
|
|
|
read_part({workbook_rel, manifest().relationship(workbook_path, relationship_type::shared_string_table)});
|
|
|
|
}
|
|
|
|
|
|
|
|
if (manifest().has_relationship(workbook_path, relationship_type::stylesheet))
|
|
|
|
{
|
|
|
|
read_part({workbook_rel, manifest().relationship(workbook_path, relationship_type::stylesheet)});
|
|
|
|
}
|
|
|
|
|
|
|
|
if (manifest().has_relationship(workbook_path, relationship_type::theme))
|
|
|
|
{
|
|
|
|
read_part({workbook_rel, manifest().relationship(workbook_path, relationship_type::theme)});
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto worksheet_rel : manifest().relationships(workbook_path, relationship_type::worksheet))
|
|
|
|
{
|
|
|
|
read_part({workbook_rel, worksheet_rel});
|
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Write Workbook Relationship Target Parts
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_calculation_chain()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
void xlsx_consumer::read_chartsheet(const std::string & /*title*/)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_connections()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_custom_property()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_custom_xml_mappings()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
void xlsx_consumer::read_dialogsheet(const std::string & /*title*/)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_external_workbook_references()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_pivot_table()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_shared_string_table()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_start_element(qn("spreadsheetml", "sst"), xml::content::complex);
|
2016-11-25 21:13:55 +08:00
|
|
|
skip_attributes({"count"});
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
bool has_unique_count = false;
|
2016-11-20 06:19:38 +08:00
|
|
|
std::size_t unique_count = 0;
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
if (parser().attribute_present("uniqueCount"))
|
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
has_unique_count = true;
|
2016-11-30 07:31:06 +08:00
|
|
|
unique_count = parser().attribute<std::size_t>("uniqueCount");
|
2016-11-20 06:19:38 +08:00
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
auto &strings = target_.shared_strings();
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
while (in_element(qn("spreadsheetml", "sst")))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_start_element(qn("spreadsheetml", "si"), xml::content::complex);
|
|
|
|
strings.push_back(read_rich_text(qn("spreadsheetml", "si")));
|
|
|
|
expect_end_element(qn("spreadsheetml", "si"));
|
2016-11-20 06:19:38 +08:00
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_end_element(qn("spreadsheetml", "sst"));
|
2016-11-25 21:13:55 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (has_unique_count && unique_count != strings.size())
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
|
|
|
throw invalid_file("sizes don't match");
|
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_shared_workbook_revision_headers()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_shared_workbook()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_shared_workbook_user_data()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_stylesheet()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
target_.impl().stylesheet_ = detail::stylesheet();
|
|
|
|
auto &stylesheet = target_.impl().stylesheet_.get();
|
2016-12-24 23:04:57 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_start_element(qn("spreadsheetml", "styleSheet"), xml::content::complex);
|
|
|
|
skip_attributes({qn("mc", "Ignorable")});
|
2016-12-02 21:37:50 +08:00
|
|
|
read_namespaces();
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
std::vector<std::pair<style_impl, std::size_t>> styles;
|
|
|
|
std::vector<std::pair<format_impl, std::size_t>> format_records;
|
|
|
|
std::vector<std::pair<format_impl, std::size_t>> style_records;
|
|
|
|
|
|
|
|
while (in_element(qn("spreadsheetml", "styleSheet")))
|
2016-11-25 21:13:55 +08:00
|
|
|
{
|
|
|
|
auto current_style_element = expect_start_element(xml::content::complex);
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
if (current_style_element == qn("spreadsheetml", "borders"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
auto &borders = stylesheet.borders;
|
2016-10-12 11:16:14 +08:00
|
|
|
auto count = parser().attribute<std::size_t>("count");
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
while (in_element(qn("spreadsheetml", "borders")))
|
2016-09-10 22:05:06 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
borders.push_back(xlnt::border());
|
|
|
|
auto &border = borders.back();
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_start_element(qn("spreadsheetml", "border"), xml::content::complex);
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
auto diagonal = diagonal_direction::neither;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
if (parser().attribute_present("diagonalDown") && parser().attribute("diagonalDown") == "1")
|
|
|
|
{
|
|
|
|
diagonal = diagonal_direction::down;
|
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
if (parser().attribute_present("diagonalUp") && parser().attribute("diagonalUp") == "1")
|
|
|
|
{
|
|
|
|
diagonal = diagonal == diagonal_direction::down ? diagonal_direction::both : diagonal_direction::up;
|
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
if (diagonal != diagonal_direction::neither)
|
|
|
|
{
|
|
|
|
border.diagonal(diagonal);
|
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
while (in_element(qn("spreadsheetml", "border")))
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
2016-11-25 21:13:55 +08:00
|
|
|
auto current_side_element = expect_start_element(xml::content::complex);
|
2016-10-25 10:09:15 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
xlnt::border::border_property side;
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
if (parser().attribute_present("style"))
|
|
|
|
{
|
|
|
|
side.style(parser().attribute<xlnt::border_style>("style"));
|
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-11-25 21:13:55 +08:00
|
|
|
if (in_element(current_side_element))
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_start_element(qn("spreadsheetml", "color"), xml::content::complex);
|
2016-11-30 07:31:06 +08:00
|
|
|
side.color(read_color());
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_end_element(qn("spreadsheetml", "color"));
|
2016-11-20 06:19:38 +08:00
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-11-25 21:13:55 +08:00
|
|
|
expect_end_element(current_side_element);
|
|
|
|
|
|
|
|
auto side_type = xml::value_traits<xlnt::border_side>::parse(current_side_element.name(), parser());
|
2016-11-20 06:19:38 +08:00
|
|
|
border.side(side_type, side);
|
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_end_element(qn("spreadsheetml", "border"));
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (count != borders.size())
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-11-25 21:13:55 +08:00
|
|
|
throw xlnt::exception("border counts don't match");
|
2016-09-10 22:05:06 +08:00
|
|
|
}
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_style_element == qn("spreadsheetml", "fills"))
|
2016-09-10 22:05:06 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
auto &fills = stylesheet.fills;
|
2016-10-12 11:16:14 +08:00
|
|
|
auto count = parser().attribute<std::size_t>("count");
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
while (in_element(qn("spreadsheetml", "fills")))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
fills.push_back(xlnt::fill());
|
|
|
|
auto &new_fill = fills.back();
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_start_element(qn("spreadsheetml", "fill"), xml::content::complex);
|
2016-11-30 07:31:06 +08:00
|
|
|
auto fill_element = expect_start_element(xml::content::complex);
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
if (fill_element == qn("spreadsheetml", "patternFill"))
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
|
|
|
xlnt::pattern_fill pattern;
|
|
|
|
|
|
|
|
if (parser().attribute_present("patternType"))
|
|
|
|
{
|
|
|
|
pattern.type(parser().attribute<xlnt::pattern_fill_type>("patternType"));
|
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
while (in_element(qn("spreadsheetml", "patternFill")))
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
2016-11-30 07:31:06 +08:00
|
|
|
auto pattern_type_element = expect_start_element(xml::content::complex);
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
if (pattern_type_element == qn("spreadsheetml", "fgColor"))
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
2016-11-30 07:31:06 +08:00
|
|
|
pattern.foreground(read_color());
|
2016-11-20 06:19:38 +08:00
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (pattern_type_element == qn("spreadsheetml", "bgColor"))
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
2016-11-30 07:31:06 +08:00
|
|
|
pattern.background(read_color());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
unexpected_element(pattern_type_element);
|
2016-11-20 06:19:38 +08:00
|
|
|
}
|
|
|
|
|
2016-11-30 07:31:06 +08:00
|
|
|
expect_end_element(pattern_type_element);
|
2016-11-20 06:19:38 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
new_fill = pattern;
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (fill_element == qn("spreadsheetml", "gradientFill"))
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
|
|
|
xlnt::gradient_fill gradient;
|
|
|
|
|
|
|
|
if (parser().attribute_present("type"))
|
|
|
|
{
|
|
|
|
gradient.type(parser().attribute<xlnt::gradient_fill_type>("type"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gradient.type(xlnt::gradient_fill_type::linear);
|
|
|
|
}
|
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
while (in_element(qn("spreadsheetml", "gradientFill")))
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_start_element(qn("spreadsheetml", "stop"), xml::content::complex);
|
2016-11-20 06:19:38 +08:00
|
|
|
auto position = parser().attribute<double>("position");
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_start_element(qn("spreadsheetml", "color"), xml::content::complex);
|
2016-11-30 07:31:06 +08:00
|
|
|
auto color = read_color();
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_end_element(qn("spreadsheetml", "color"));
|
|
|
|
expect_end_element(qn("spreadsheetml", "stop"));
|
2016-11-20 06:19:38 +08:00
|
|
|
|
|
|
|
gradient.add_stop(position, color);
|
|
|
|
}
|
|
|
|
|
|
|
|
new_fill = gradient;
|
|
|
|
}
|
2016-11-30 07:31:06 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
unexpected_element(fill_element);
|
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-11-30 07:31:06 +08:00
|
|
|
expect_end_element(fill_element);
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_end_element(qn("spreadsheetml", "fill"));
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (count != fills.size())
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
|
|
|
throw xlnt::exception("counts don't match");
|
|
|
|
}
|
2016-09-10 22:05:06 +08:00
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_style_element == qn("spreadsheetml", "fonts"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
auto &fonts = stylesheet.fonts;
|
2016-10-12 11:16:14 +08:00
|
|
|
auto count = parser().attribute<std::size_t>("count");
|
2017-01-11 09:25:59 +08:00
|
|
|
skip_attributes({qn("x14ac", "knownFonts")});
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
while (in_element(qn("spreadsheetml", "fonts")))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
fonts.push_back(xlnt::font());
|
2016-11-20 06:19:38 +08:00
|
|
|
auto &new_font = stylesheet.fonts.back();
|
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_start_element(qn("spreadsheetml", "font"), xml::content::complex);
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
while (in_element(qn("spreadsheetml", "font")))
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
2016-11-30 07:31:06 +08:00
|
|
|
auto font_property_element = expect_start_element(xml::content::simple);
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
if (font_property_element == qn("spreadsheetml", "sz"))
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
2016-12-26 22:38:26 +08:00
|
|
|
new_font.size(parser().attribute<double>("val"));
|
2016-11-20 06:19:38 +08:00
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (font_property_element == qn("spreadsheetml", "name"))
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
|
|
|
new_font.name(parser().attribute("val"));
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (font_property_element == qn("spreadsheetml", "color"))
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
2016-11-30 07:31:06 +08:00
|
|
|
new_font.color(read_color());
|
2016-11-20 06:19:38 +08:00
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (font_property_element == qn("spreadsheetml", "family"))
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
2016-11-30 07:31:06 +08:00
|
|
|
new_font.family(parser().attribute<std::size_t>("val"));
|
2016-11-20 06:19:38 +08:00
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (font_property_element == qn("spreadsheetml", "scheme"))
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
|
|
|
new_font.scheme(parser().attribute("val"));
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (font_property_element == qn("spreadsheetml", "b"))
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
|
|
|
if (parser().attribute_present("val"))
|
|
|
|
{
|
|
|
|
new_font.bold(is_true(parser().attribute("val")));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
new_font.bold(true);
|
|
|
|
}
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (font_property_element == qn("spreadsheetml", "vertAlign"))
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
|
|
|
new_font.superscript(parser().attribute("val") == "superscript");
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (font_property_element == qn("spreadsheetml", "strike"))
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
|
|
|
if (parser().attribute_present("val"))
|
|
|
|
{
|
|
|
|
new_font.strikethrough(is_true(parser().attribute("val")));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
new_font.strikethrough(true);
|
|
|
|
}
|
|
|
|
}
|
2017-02-07 06:00:45 +08:00
|
|
|
else if (font_property_element == qn("spreadsheetml", "outline"))
|
|
|
|
{
|
|
|
|
if (parser().attribute_present("val"))
|
|
|
|
{
|
2017-02-11 12:22:38 +08:00
|
|
|
new_font.outline(is_true(parser().attribute("val")));
|
2017-02-07 06:00:45 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-02-11 12:22:38 +08:00
|
|
|
new_font.outline(true);
|
2017-02-07 06:00:45 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (font_property_element == qn("spreadsheetml", "shadow"))
|
|
|
|
{
|
|
|
|
if (parser().attribute_present("val"))
|
|
|
|
{
|
2017-02-11 12:22:38 +08:00
|
|
|
new_font.shadow(is_true(parser().attribute("val")));
|
2017-02-07 06:00:45 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-02-11 12:22:38 +08:00
|
|
|
new_font.shadow(true);
|
2017-02-07 06:00:45 +08:00
|
|
|
}
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (font_property_element == qn("spreadsheetml", "i"))
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
|
|
|
if (parser().attribute_present("val"))
|
|
|
|
{
|
|
|
|
new_font.italic(is_true(parser().attribute("val")));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
new_font.italic(true);
|
|
|
|
}
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (font_property_element == qn("spreadsheetml", "u"))
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
|
|
|
if (parser().attribute_present("val"))
|
|
|
|
{
|
|
|
|
new_font.underline(parser().attribute<xlnt::font::underline_style>("val"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
new_font.underline(xlnt::font::underline_style::single);
|
|
|
|
}
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (font_property_element == qn("spreadsheetml", "charset"))
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
|
|
|
if (parser().attribute_present("val"))
|
|
|
|
{
|
|
|
|
parser().attribute("val");
|
|
|
|
}
|
|
|
|
}
|
2016-11-30 07:31:06 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
unexpected_element(font_property_element);
|
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2016-11-30 07:31:06 +08:00
|
|
|
expect_end_element(font_property_element);
|
2016-11-20 06:19:38 +08:00
|
|
|
}
|
2016-10-12 11:16:14 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_end_element(qn("spreadsheetml", "font"));
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
if (count != stylesheet.fonts.size())
|
|
|
|
{
|
|
|
|
throw xlnt::exception("counts don't match");
|
|
|
|
}
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_style_element == qn("spreadsheetml", "numFmts"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
auto &number_formats = stylesheet.number_formats;
|
2016-10-25 10:09:15 +08:00
|
|
|
auto count = parser().attribute<std::size_t>("count");
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
while (in_element(qn("spreadsheetml", "numFmts")))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_start_element(qn("spreadsheetml", "numFmt"), xml::content::simple);
|
2016-10-25 10:09:15 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
auto format_string = parser().attribute("formatCode");
|
2016-09-22 07:04:16 +08:00
|
|
|
|
|
|
|
if (format_string == "GENERAL")
|
|
|
|
{
|
|
|
|
format_string = "General";
|
|
|
|
}
|
|
|
|
|
|
|
|
xlnt::number_format nf;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
nf.format_string(format_string);
|
|
|
|
nf.id(parser().attribute<std::size_t>("numFmtId"));
|
2016-11-30 07:31:06 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_end_element(qn("spreadsheetml", "numFmt"));
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
number_formats.push_back(nf);
|
2016-10-25 10:09:15 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (count != number_formats.size())
|
2016-10-25 10:09:15 +08:00
|
|
|
{
|
|
|
|
throw xlnt::exception("counts don't match");
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_style_element == qn("spreadsheetml", "cellStyles"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
auto count = parser().attribute<std::size_t>("count");
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
while (in_element(qn("spreadsheetml", "cellStyles")))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
auto &data = *styles.emplace(styles.end());
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_start_element(qn("spreadsheetml", "cellStyle"), xml::content::simple);
|
2016-11-08 10:11:30 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
data.first.name = parser().attribute("name");
|
|
|
|
data.second = parser().attribute<std::size_t>("xfId");
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-11-15 21:09:17 +08:00
|
|
|
if (parser().attribute_present("builtinId"))
|
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
data.first.builtin_id = parser().attribute<std::size_t>("builtinId");
|
2016-11-15 21:09:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (parser().attribute_present("hidden"))
|
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
data.first.hidden_style = is_true(parser().attribute("hidden"));
|
2016-11-15 21:09:17 +08:00
|
|
|
}
|
2016-11-08 10:11:30 +08:00
|
|
|
|
2016-10-25 10:09:15 +08:00
|
|
|
if (parser().attribute_present("customBuiltin"))
|
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
data.first.custom_builtin = is_true(parser().attribute("customBuiltin"));
|
2016-10-25 10:09:15 +08:00
|
|
|
}
|
2016-11-08 10:11:30 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_end_element(qn("spreadsheetml", "cellStyle"));
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
if (count != styles.size())
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
|
|
|
throw xlnt::exception("counts don't match");
|
|
|
|
}
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_style_element == qn("spreadsheetml", "cellStyleXfs")
|
|
|
|
|| current_style_element == qn("spreadsheetml", "cellXfs"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-11-25 21:13:55 +08:00
|
|
|
auto in_style_records = current_style_element.name() == "cellStyleXfs";
|
2016-10-12 11:16:14 +08:00
|
|
|
auto count = parser().attribute<std::size_t>("count");
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-11-25 21:13:55 +08:00
|
|
|
while (in_element(current_style_element))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_start_element(qn("spreadsheetml", "xf"), xml::content::complex);
|
2017-02-15 05:02:51 +08:00
|
|
|
|
2016-12-30 07:36:29 +08:00
|
|
|
auto &record = *(!in_style_records
|
|
|
|
? format_records.emplace(format_records.end())
|
|
|
|
: style_records.emplace(style_records.end()));
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
record.first.border_applied = parser().attribute_present("applyBorder")
|
|
|
|
&& is_true(parser().attribute("applyBorder"));
|
|
|
|
record.first.border_id = parser().attribute_present("borderId")
|
|
|
|
? parser().attribute<std::size_t>("borderId") : 0;
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
record.first.fill_applied = parser().attribute_present("applyFill")
|
|
|
|
&& is_true(parser().attribute("applyFill"));
|
|
|
|
record.first.fill_id = parser().attribute_present("fillId")
|
|
|
|
? parser().attribute<std::size_t>("fillId") : 0;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
record.first.font_applied = parser().attribute_present("applyFont")
|
|
|
|
&& is_true(parser().attribute("applyFont"));
|
|
|
|
record.first.font_id = parser().attribute_present("fontId")
|
|
|
|
? parser().attribute<std::size_t>("fontId") : 0;
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
record.first.number_format_applied = parser().attribute_present("applyNumberFormat")
|
|
|
|
&& is_true(parser().attribute("applyNumberFormat"));
|
|
|
|
record.first.number_format_id = parser().attribute_present("numFmtId")
|
|
|
|
? parser().attribute<std::size_t>("numFmtId") : 0;
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
auto apply_alignment_present = parser().attribute_present("applyAlignment");
|
|
|
|
record.first.alignment_applied = apply_alignment_present
|
|
|
|
&& is_true(parser().attribute("applyAlignment"));
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
auto apply_protection_present = parser().attribute_present("applyProtection");
|
2017-01-11 09:25:59 +08:00
|
|
|
record.first.protection_applied = apply_protection_present
|
|
|
|
&& is_true(parser().attribute("applyProtection"));
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2017-02-19 10:33:59 +08:00
|
|
|
record.first.pivot_button_ = parser().attribute_present("pivotButton")
|
2017-02-15 05:02:51 +08:00
|
|
|
&& is_true(parser().attribute("pivotButton"));
|
2017-02-19 10:33:59 +08:00
|
|
|
record.first.quote_prefix_ = parser().attribute_present("quotePrefix")
|
2017-02-15 05:02:51 +08:00
|
|
|
&& is_true(parser().attribute("quotePrefix"));
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().attribute_present("xfId") && parser().name() == "cellXfs")
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
record.second = parser().attribute<std::size_t>("xfId");
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
while (in_element(qn("spreadsheetml", "xf")))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-11-30 07:31:06 +08:00
|
|
|
auto xf_child_element = expect_start_element(xml::content::simple);
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
if (xf_child_element == qn("spreadsheetml", "alignment"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
record.first.alignment_id = stylesheet.alignments.size();
|
|
|
|
auto &alignment = *stylesheet.alignments.emplace(stylesheet.alignments.end());
|
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
if (parser().attribute_present("wrapText"))
|
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
alignment.wrap(is_true(parser().attribute("wrapText")));
|
2016-11-20 06:19:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (parser().attribute_present("shrinkToFit"))
|
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
alignment.shrink(is_true(parser().attribute("shrinkToFit")));
|
2016-11-20 06:19:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (parser().attribute_present("indent"))
|
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
alignment.indent(parser().attribute<int>("indent"));
|
2016-11-20 06:19:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (parser().attribute_present("textRotation"))
|
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
alignment.rotation(parser().attribute<int>("textRotation"));
|
2016-11-20 06:19:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (parser().attribute_present("vertical"))
|
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
alignment.vertical(parser().attribute<xlnt::vertical_alignment>("vertical"));
|
2016-11-20 06:19:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (parser().attribute_present("horizontal"))
|
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
alignment.horizontal(parser().attribute<xlnt::horizontal_alignment>("horizontal"));
|
2016-11-20 06:19:38 +08:00
|
|
|
}
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (xf_child_element == qn("spreadsheetml", "protection"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
record.first.protection_id = stylesheet.protections.size();
|
|
|
|
auto &protection = *stylesheet.protections.emplace(stylesheet.protections.end());
|
|
|
|
|
|
|
|
protection.locked(parser().attribute_present("locked")
|
2017-01-03 07:32:10 +08:00
|
|
|
&& is_true(parser().attribute("locked")));
|
2017-01-11 09:25:59 +08:00
|
|
|
protection.hidden(parser().attribute_present("hidden")
|
2017-01-03 07:32:10 +08:00
|
|
|
&& is_true(parser().attribute("hidden")));
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-30 07:31:06 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
unexpected_element(xf_child_element);
|
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-11-30 07:31:06 +08:00
|
|
|
expect_end_element(xf_child_element);
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_end_element(qn("spreadsheetml", "xf"));
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-12-24 23:04:57 +08:00
|
|
|
if ((in_style_records && count != style_records.size())
|
|
|
|
|| (!in_style_records && count != format_records.size()))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
|
|
|
throw xlnt::exception("counts don't match");
|
|
|
|
}
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_style_element == qn("spreadsheetml", "dxfs"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
auto count = parser().attribute<std::size_t>("count");
|
2016-09-22 07:04:16 +08:00
|
|
|
std::size_t processed = 0;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-02-07 06:00:45 +08:00
|
|
|
while (in_element(current_style_element))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2017-02-07 06:00:45 +08:00
|
|
|
auto current_element = expect_start_element(xml::content::mixed);
|
2016-11-25 21:13:55 +08:00
|
|
|
skip_remaining_content(current_element);
|
2017-02-07 06:00:45 +08:00
|
|
|
expect_end_element(current_element);
|
2016-11-25 21:13:55 +08:00
|
|
|
++processed;
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
if (count != processed)
|
|
|
|
{
|
|
|
|
throw xlnt::exception("counts don't match");
|
|
|
|
}
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_style_element == qn("spreadsheetml", "tableStyles"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
skip_attribute("defaultTableStyle");
|
|
|
|
skip_attribute("defaultPivotStyle");
|
2016-11-25 21:13:55 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
auto count = parser().attribute<std::size_t>("count");
|
2016-09-22 07:04:16 +08:00
|
|
|
std::size_t processed = 0;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
while (in_element(qn("spreadsheetml", "tableStyles")))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-11-25 21:13:55 +08:00
|
|
|
auto current_element = expect_start_element(xml::content::complex);
|
|
|
|
skip_remaining_content(current_element);
|
2017-02-07 06:00:45 +08:00
|
|
|
expect_end_element(current_element);
|
2016-11-25 21:13:55 +08:00
|
|
|
++processed;
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
if (count != processed)
|
|
|
|
{
|
|
|
|
throw xlnt::exception("counts don't match");
|
|
|
|
}
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_style_element == qn("spreadsheetml", "extLst"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-11-30 07:31:06 +08:00
|
|
|
skip_remaining_content(current_style_element);
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_style_element == qn("spreadsheetml", "colors")) // CT_Colors 0-1
|
2016-11-25 21:13:55 +08:00
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
while (in_element(qn("spreadsheetml", "colors")))
|
2016-12-02 21:37:50 +08:00
|
|
|
{
|
|
|
|
auto colors_child_element = expect_start_element(xml::content::complex);
|
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
if (colors_child_element == qn("spreadsheetml", "indexedColors")) // CT_IndexedColors 0-1
|
2016-12-02 21:37:50 +08:00
|
|
|
{
|
|
|
|
while (in_element(colors_child_element))
|
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_start_element(qn("spreadsheetml", "rgbColor"), xml::content::simple);
|
2016-12-02 21:37:50 +08:00
|
|
|
stylesheet.colors.push_back(read_color());
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_end_element(qn("spreadsheetml", "rgbColor"));
|
2016-12-02 21:37:50 +08:00
|
|
|
}
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (colors_child_element == qn("spreadsheetml", "mruColors")) // CT_MRUColors
|
2016-12-02 21:37:50 +08:00
|
|
|
{
|
|
|
|
skip_remaining_content(colors_child_element);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
unexpected_element(colors_child_element);
|
|
|
|
}
|
|
|
|
|
|
|
|
expect_end_element(colors_child_element);
|
|
|
|
}
|
2016-11-25 21:13:55 +08:00
|
|
|
}
|
|
|
|
else
|
2016-10-25 10:09:15 +08:00
|
|
|
{
|
2016-11-25 21:13:55 +08:00
|
|
|
unexpected_element(current_style_element);
|
2016-10-25 10:09:15 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-11-25 21:13:55 +08:00
|
|
|
expect_end_element(current_style_element);
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_end_element(qn("spreadsheetml", "styleSheet"));
|
|
|
|
/*
|
2016-12-24 23:04:57 +08:00
|
|
|
auto lookup_number_format = [&](std::size_t number_format_id) {
|
2016-09-22 07:04:16 +08:00
|
|
|
auto result = number_format::general();
|
2016-09-10 22:05:06 +08:00
|
|
|
bool is_custom_number_format = false;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-10 22:05:06 +08:00
|
|
|
for (const auto &nf : stylesheet.number_formats)
|
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
if (nf.id() == number_format_id)
|
2016-09-10 22:05:06 +08:00
|
|
|
{
|
2016-11-03 10:04:51 +08:00
|
|
|
result = nf;
|
2016-09-10 22:05:06 +08:00
|
|
|
is_custom_number_format = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2016-09-10 22:05:06 +08:00
|
|
|
if (number_format_id < 164 && !is_custom_number_format)
|
|
|
|
{
|
2016-09-22 07:04:16 +08:00
|
|
|
result = number_format::from_builtin_id(number_format_id);
|
2016-09-10 22:05:06 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
return result;
|
|
|
|
};
|
2017-01-11 09:25:59 +08:00
|
|
|
*/
|
2017-01-15 03:09:01 +08:00
|
|
|
/*
|
|
|
|
std::size_t xf_id = 0;
|
2017-02-07 06:00:45 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
for (const auto &record : style_records)
|
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
auto style_iter = std::find_if(styles.begin(), styles.end(),
|
2017-01-15 03:09:01 +08:00
|
|
|
[&xf_id](const std::pair<style_impl, std::size_t> &s) { return s.second == xf_id; });
|
2016-10-25 10:09:15 +08:00
|
|
|
++xf_id;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
if (style_iter == styles.end()) continue;
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
auto new_style = stylesheet.create_style(style_iter->first.name);
|
|
|
|
*new_style.d_ = style_iter->first;
|
2017-01-15 03:09:01 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
(void)record;
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2017-01-15 03:09:01 +08:00
|
|
|
*/
|
2016-11-08 10:11:30 +08:00
|
|
|
std::size_t record_index = 0;
|
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
for (const auto &record : format_records)
|
|
|
|
{
|
2016-11-08 10:11:30 +08:00
|
|
|
stylesheet.format_impls.push_back(format_impl());
|
|
|
|
auto &new_format = stylesheet.format_impls.back();
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-11-08 10:11:30 +08:00
|
|
|
new_format.id = record_index++;
|
|
|
|
new_format.parent = &stylesheet;
|
2016-11-10 08:52:18 +08:00
|
|
|
|
|
|
|
++new_format.references;
|
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
new_format.alignment_id = record.first.alignment_id;
|
|
|
|
new_format.alignment_applied = record.first.alignment_applied;
|
|
|
|
new_format.border_id = record.first.border_id;
|
|
|
|
new_format.border_applied = record.first.border_applied;
|
|
|
|
new_format.fill_id = record.first.fill_id;
|
|
|
|
new_format.fill_applied = record.first.fill_applied;
|
|
|
|
new_format.font_id = record.first.font_id;
|
|
|
|
new_format.font_applied = record.first.font_applied;
|
|
|
|
new_format.number_format_id = record.first.number_format_id;
|
|
|
|
new_format.number_format_applied = record.first.number_format_applied;
|
|
|
|
new_format.protection_id = record.first.protection_id;
|
|
|
|
new_format.protection_applied = record.first.protection_applied;
|
2017-02-19 10:33:59 +08:00
|
|
|
new_format.pivot_button_ = record.first.pivot_button_;
|
|
|
|
new_format.quote_prefix_ = record.first.quote_prefix_;
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_theme()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
auto workbook_rel = manifest().relationship(path("/"), relationship_type::office_document);
|
|
|
|
auto theme_rel = manifest().relationship(workbook_rel.target().path(), relationship_type::theme);
|
|
|
|
auto theme_path = manifest().canonicalize({workbook_rel, theme_rel});
|
|
|
|
|
|
|
|
target_.theme(theme());
|
|
|
|
|
|
|
|
if (manifest().has_relationship(theme_path, relationship_type::image))
|
|
|
|
{
|
|
|
|
read_part({workbook_rel, theme_rel, manifest().relationship(theme_path, relationship_type::image)});
|
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_volatile_dependencies()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-11-25 21:13:55 +08:00
|
|
|
// CT_Worksheet
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_worksheet(const std::string &rel_id)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
/*
|
2016-12-02 21:37:50 +08:00
|
|
|
static const auto &xmlns = constants::namespace_("spreadsheetml");
|
|
|
|
static const auto &xmlns_mc = constants::namespace_("mc");
|
|
|
|
static const auto &xmlns_x14ac = constants::namespace_("x14ac");
|
|
|
|
static const auto &xmlns_r = constants::namespace_("r");
|
2017-01-11 09:25:59 +08:00
|
|
|
*/
|
|
|
|
auto title = std::find_if(target_.d_->sheet_title_rel_id_map_.begin(),
|
|
|
|
target_.d_->sheet_title_rel_id_map_.end(),
|
2016-12-24 23:04:57 +08:00
|
|
|
[&](const std::pair<std::string, std::string> &p) {
|
|
|
|
return p.second == rel_id;
|
|
|
|
})->first;
|
2016-08-06 22:40:17 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
auto id = sheet_title_id_map_[title];
|
|
|
|
auto index = sheet_title_index_map_[title];
|
2016-08-06 22:40:17 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
auto insertion_iter = target_.d_->worksheets_.begin();
|
2016-12-24 23:04:57 +08:00
|
|
|
while (insertion_iter != target_.d_->worksheets_.end() && sheet_title_index_map_[insertion_iter->title_] < index)
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
|
|
|
++insertion_iter;
|
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
target_.d_->worksheets_.emplace(insertion_iter, &target_, id, title);
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
auto ws = target_.sheet_by_id(id);
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_start_element(qn("spreadsheetml", "worksheet"), xml::content::complex); // CT_Worksheet
|
|
|
|
skip_attributes({qn("mc", "Ignorable")});
|
2016-12-02 21:37:50 +08:00
|
|
|
read_namespaces();
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-11-20 06:19:38 +08:00
|
|
|
xlnt::range_reference full_range;
|
2016-11-30 08:05:47 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
const auto &shared_strings = target_.shared_strings();
|
|
|
|
auto &manifest = target_.manifest();
|
2016-11-30 08:05:47 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
const auto workbook_rel = manifest.relationship(path("/"), relationship_type::office_document);
|
|
|
|
const auto sheet_rel = manifest.relationship(workbook_rel.target().path(), rel_id);
|
|
|
|
path sheet_path(sheet_rel.source().path().parent().append(sheet_rel.target().path()));
|
|
|
|
auto hyperlinks = manifest.relationships(sheet_path, xlnt::relationship_type::hyperlink);
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
while (in_element(qn("spreadsheetml", "worksheet")))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-11-25 21:13:55 +08:00
|
|
|
auto current_worksheet_element = expect_start_element(xml::content::complex);
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
if (current_worksheet_element == qn("spreadsheetml", "sheetPr")) // CT_SheetPr 0-1
|
2016-11-25 21:13:55 +08:00
|
|
|
{
|
2016-12-10 08:18:50 +08:00
|
|
|
while (in_element(current_worksheet_element))
|
|
|
|
{
|
|
|
|
auto sheet_pr_child_element = expect_start_element(xml::content::simple);
|
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
if (sheet_pr_child_element == qn("spreadsheetml", "tabColor")) // CT_Color 0-1
|
2016-12-10 08:18:50 +08:00
|
|
|
{
|
|
|
|
read_color();
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (sheet_pr_child_element == qn("spreadsheetml", "outlinePr")) // CT_OutlinePr 0-1
|
2016-12-10 08:18:50 +08:00
|
|
|
{
|
|
|
|
skip_attribute("applyStyles"); // optional, boolean, false
|
|
|
|
skip_attribute("summaryBelow"); // optional, boolean, true
|
|
|
|
skip_attribute("summaryRight"); // optional, boolean, true
|
|
|
|
skip_attribute("showOutlineSymbols"); // optional, boolean, true
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (sheet_pr_child_element == qn("spreadsheetml", "pageSetUpPr")) // CT_PageSetUpPr 0-1
|
2016-12-10 08:18:50 +08:00
|
|
|
{
|
|
|
|
skip_attribute("autoPageBreaks"); // optional, boolean, true
|
|
|
|
skip_attribute("fitToPage"); // optional, boolean, false
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
unexpected_element(sheet_pr_child_element);
|
|
|
|
}
|
|
|
|
|
|
|
|
expect_end_element(sheet_pr_child_element);
|
|
|
|
}
|
|
|
|
|
|
|
|
skip_attribute("syncHorizontal"); // optional, boolean, false
|
|
|
|
skip_attribute("syncVertical"); // optional, boolean, false
|
|
|
|
skip_attribute("syncRef"); // optional, ST_Ref, false
|
|
|
|
skip_attribute("transitionEvaluation"); // optional, boolean, false
|
|
|
|
skip_attribute("transitionEntry"); // optional, boolean, false
|
|
|
|
skip_attribute("published"); // optional, boolean, true
|
|
|
|
skip_attribute("codeName"); // optional, string
|
|
|
|
skip_attribute("filterMode"); // optional, boolean, false
|
|
|
|
skip_attribute("enableFormatConditionsCalculation"); // optional, boolean, true
|
2016-11-25 21:13:55 +08:00
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_worksheet_element == qn("spreadsheetml", "dimension")) // CT_SheetDimension 0-1
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-10-12 11:16:14 +08:00
|
|
|
full_range = xlnt::range_reference(parser().attribute("ref"));
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_worksheet_element == qn("spreadsheetml", "sheetViews")) // CT_SheetViews 0-1
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
while (in_element(current_worksheet_element))
|
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_start_element(qn("spreadsheetml", "sheetView"), xml::content::complex); // CT_SheetView 1+
|
2016-12-02 21:37:50 +08:00
|
|
|
|
|
|
|
sheet_view new_view;
|
|
|
|
new_view.id(parser().attribute<std::size_t>("workbookViewId"));
|
|
|
|
|
|
|
|
if (parser().attribute_present("showGridLines")) // default="true"
|
|
|
|
{
|
|
|
|
new_view.show_grid_lines(is_true(parser().attribute("showGridLines")));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parser().attribute_present("defaultGridColor")) // default="true"
|
|
|
|
{
|
|
|
|
new_view.default_grid_color(is_true(parser().attribute("defaultGridColor")));
|
|
|
|
}
|
|
|
|
|
2016-12-23 07:57:22 +08:00
|
|
|
if (parser().attribute_present("view") && parser().attribute("view") != "normal")
|
|
|
|
{
|
2016-12-24 23:04:57 +08:00
|
|
|
new_view.type(parser().attribute("view") == "pageBreakPreview" ? sheet_view_type::page_break_preview
|
|
|
|
: sheet_view_type::page_layout);
|
2016-12-23 07:57:22 +08:00
|
|
|
}
|
|
|
|
|
2016-12-24 23:04:57 +08:00
|
|
|
skip_attributes({"windowProtection", "showFormulas", "showRowColHeaders", "showZeros", "rightToLeft",
|
|
|
|
"tabSelected", "showRuler", "showOutlineSymbols", "showWhiteSpace", "view", "topLeftCell",
|
|
|
|
"colorId", "zoomScale", "zoomScaleNormal", "zoomScaleSheetLayoutView", "zoomScalePageLayoutView"});
|
2016-12-02 21:37:50 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
while (in_element(qn("spreadsheetml", "sheetView")))
|
2016-12-02 21:37:50 +08:00
|
|
|
{
|
|
|
|
auto sheet_view_child_element = expect_start_element(xml::content::simple);
|
2016-12-24 23:04:57 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
if (sheet_view_child_element == qn("spreadsheetml", "pane")) // CT_Pane 0-1
|
2016-12-02 21:37:50 +08:00
|
|
|
{
|
|
|
|
pane new_pane;
|
2016-12-24 23:04:57 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (parser().attribute_present("topLeftCell"))
|
|
|
|
{
|
|
|
|
new_pane.top_left_cell = cell_reference(parser().attribute("topLeftCell"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parser().attribute_present("xSplit"))
|
|
|
|
{
|
|
|
|
new_pane.x_split = parser().attribute<column_t::index_t>("xSplit");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parser().attribute_present("ySplit"))
|
|
|
|
{
|
|
|
|
new_pane.y_split = parser().attribute<row_t>("ySplit");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parser().attribute_present("activePane"))
|
|
|
|
{
|
|
|
|
new_pane.active_pane = parser().attribute<pane_corner>("activePane");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parser().attribute_present("state"))
|
|
|
|
{
|
|
|
|
new_pane.state = parser().attribute<pane_state>("state");
|
|
|
|
}
|
|
|
|
|
|
|
|
new_view.pane(new_pane);
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (sheet_view_child_element == qn("spreadsheetml", "selection")) // CT_Selection 0-4
|
2016-12-02 21:37:50 +08:00
|
|
|
{
|
|
|
|
skip_remaining_content(sheet_view_child_element);
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (sheet_view_child_element == qn("spreadsheetml", "pivotSelection")) // CT_PivotSelection 0-4
|
2016-12-02 21:37:50 +08:00
|
|
|
{
|
|
|
|
skip_remaining_content(sheet_view_child_element);
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (sheet_view_child_element == qn("spreadsheetml", "extLst")) // CT_ExtensionList 0-1
|
2016-12-02 21:37:50 +08:00
|
|
|
{
|
|
|
|
skip_remaining_content(sheet_view_child_element);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
unexpected_element(sheet_view_child_element);
|
|
|
|
}
|
|
|
|
|
|
|
|
expect_end_element(sheet_view_child_element);
|
|
|
|
}
|
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_end_element(qn("spreadsheetml", "sheetView"));
|
2016-12-02 21:37:50 +08:00
|
|
|
|
|
|
|
ws.d_->views_.push_back(new_view);
|
|
|
|
}
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_worksheet_element == qn("spreadsheetml", "sheetFormatPr")) // CT_SheetFormatPr 0-1
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-11-25 21:13:55 +08:00
|
|
|
skip_remaining_content(current_worksheet_element);
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_worksheet_element == qn("spreadsheetml", "cols")) // CT_Cols 0+
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
while (in_element(qn("spreadsheetml", "cols")))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_start_element(qn("spreadsheetml", "col"), xml::content::simple);
|
2016-08-05 13:52:05 +08:00
|
|
|
|
2016-12-23 07:57:22 +08:00
|
|
|
skip_attributes({"bestFit", "collapsed", "outlineLevel"});
|
2016-08-14 07:44:45 +08:00
|
|
|
|
2016-11-25 21:13:55 +08:00
|
|
|
auto min = static_cast<column_t::index_t>(std::stoull(parser().attribute("min")));
|
|
|
|
auto max = static_cast<column_t::index_t>(std::stoull(parser().attribute("max")));
|
2016-08-14 07:44:45 +08:00
|
|
|
|
2016-12-23 07:57:22 +08:00
|
|
|
optional<double> width;
|
|
|
|
|
|
|
|
if (parser().attribute_present("width"))
|
|
|
|
{
|
|
|
|
width = parser().attribute<double>("width");
|
|
|
|
}
|
|
|
|
|
|
|
|
optional<std::size_t> column_style;
|
2016-12-24 23:04:57 +08:00
|
|
|
|
2016-12-23 07:57:22 +08:00
|
|
|
if (parser().attribute_present("style"))
|
|
|
|
{
|
|
|
|
column_style = parser().attribute<std::size_t>("style");
|
|
|
|
}
|
2016-12-24 23:04:57 +08:00
|
|
|
|
|
|
|
auto custom =
|
|
|
|
parser().attribute_present("customWidth") ? is_true(parser().attribute("customWidth")) : false;
|
|
|
|
auto hidden = parser().attribute_present("hidden") ? is_true(parser().attribute("hidden")) : false;
|
2016-11-25 21:13:55 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_end_element(qn("spreadsheetml", "col"));
|
2016-11-25 21:13:55 +08:00
|
|
|
|
|
|
|
for (auto column = min; column <= max; column++)
|
|
|
|
{
|
|
|
|
column_properties props;
|
|
|
|
|
2016-12-23 07:57:22 +08:00
|
|
|
if (width.is_set())
|
|
|
|
{
|
|
|
|
props.width = width.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (column_style.is_set())
|
|
|
|
{
|
|
|
|
props.style = column_style.get();
|
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-12-23 07:57:22 +08:00
|
|
|
props.hidden = hidden;
|
|
|
|
props.custom_width = custom;
|
2016-11-25 21:13:55 +08:00
|
|
|
ws.add_column_properties(column, props);
|
|
|
|
}
|
|
|
|
}
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_worksheet_element == qn("spreadsheetml", "sheetData")) // CT_SheetData 1
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
while (in_element(qn("spreadsheetml", "sheetData")))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_start_element(qn("spreadsheetml", "row"), xml::content::complex); // CT_Row
|
2016-12-02 21:37:50 +08:00
|
|
|
auto row_index = parser().attribute<row_t>("r");
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
if (parser().attribute_present("ht"))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-12-23 07:57:22 +08:00
|
|
|
ws.row_properties(row_index).height = parser().attribute<double>("ht");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parser().attribute_present("customHeight"))
|
|
|
|
{
|
|
|
|
ws.row_properties(row_index).custom_height = is_true(parser().attribute("customHeight"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parser().attribute_present("hidden") && is_true(parser().attribute("hidden")))
|
|
|
|
{
|
|
|
|
ws.row_properties(row_index).hidden = true;
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
skip_attributes({qn("x14ac", "dyDescent")});
|
|
|
|
skip_attributes({"customFormat", "s", "customFont",
|
|
|
|
"outlineLevel", "collapsed", "thickTop", "thickBot",
|
2016-12-24 23:04:57 +08:00
|
|
|
"ph", "spans"});
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
while (in_element(qn("spreadsheetml", "row")))
|
2016-11-20 06:19:38 +08:00
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_start_element(qn("spreadsheetml", "c"), xml::content::complex);
|
2016-12-02 21:37:50 +08:00
|
|
|
auto cell = ws.cell(cell_reference(parser().attribute("r")));
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
auto has_type = parser().attribute_present("t");
|
2017-01-01 09:05:10 +08:00
|
|
|
auto type = has_type ? parser().attribute("t") : "n";
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
auto has_format = parser().attribute_present("s");
|
|
|
|
auto format_id = static_cast<std::size_t>(has_format ? std::stoull(parser().attribute("s")) : 0LL);
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
auto has_value = false;
|
|
|
|
auto value_string = std::string();
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-09-22 07:04:16 +08:00
|
|
|
auto has_formula = false;
|
|
|
|
auto has_shared_formula = false;
|
|
|
|
auto formula_value_string = std::string();
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
while (in_element(qn("spreadsheetml", "c")))
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-11-25 21:13:55 +08:00
|
|
|
auto current_element = expect_start_element(xml::content::mixed);
|
2016-12-24 23:04:57 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
if (current_element == qn("spreadsheetml", "v")) // s:ST_Xstring
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
|
|
|
has_value = true;
|
2016-11-21 08:38:58 +08:00
|
|
|
value_string = read_text();
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_element == qn("spreadsheetml", "f")) // CT_CellFormula
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
|
|
|
has_formula = true;
|
2016-11-27 16:41:03 +08:00
|
|
|
|
|
|
|
if (parser().attribute_present("t"))
|
|
|
|
{
|
|
|
|
has_shared_formula = parser().attribute("t") == "shared";
|
|
|
|
}
|
|
|
|
|
2016-12-24 23:04:57 +08:00
|
|
|
skip_attributes(
|
|
|
|
{"aca", "ref", "dt2D", "dtr", "del1", "del2", "r1", "r2", "ca", "si", "bx"});
|
2016-11-27 16:41:03 +08:00
|
|
|
|
2016-11-21 08:38:58 +08:00
|
|
|
formula_value_string = read_text();
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_element == qn("spreadsheetml", "is")) // CT_Rst
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_start_element(qn("spreadsheetml", "t"), xml::content::simple);
|
2016-11-21 08:38:58 +08:00
|
|
|
value_string = read_text();
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_end_element(qn("spreadsheetml", "t"));
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-25 21:13:55 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
unexpected_element(current_element);
|
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-11-30 07:31:06 +08:00
|
|
|
expect_end_element(current_element);
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_end_element(qn("spreadsheetml", "c"));
|
2016-11-25 21:13:55 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (has_formula && !has_shared_formula)
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
cell.formula(formula_value_string);
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
|
|
|
|
2017-01-01 09:05:10 +08:00
|
|
|
if (has_value)
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2017-01-01 09:05:10 +08:00
|
|
|
if (type == "inlineStr" || type == "str")
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2017-01-01 09:05:10 +08:00
|
|
|
cell.value(value_string);
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2017-01-01 09:05:10 +08:00
|
|
|
else if (type == "s" && !has_formula)
|
|
|
|
{
|
|
|
|
auto shared_string_index = static_cast<std::size_t>(std::stoull(value_string));
|
|
|
|
auto shared_string = shared_strings.at(shared_string_index);
|
|
|
|
cell.value(shared_string);
|
|
|
|
}
|
|
|
|
else if (type == "b") // boolean
|
|
|
|
{
|
|
|
|
cell.value(is_true(value_string));
|
|
|
|
}
|
|
|
|
else if (type == "n") // numeric
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
cell.value(std::stold(value_string));
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2017-01-01 09:05:10 +08:00
|
|
|
else if (!value_string.empty() && value_string[0] == '#')
|
|
|
|
{
|
|
|
|
cell.error(value_string);
|
|
|
|
}
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (has_format)
|
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
cell.format(target_.format(format_id));
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
|
|
|
}
|
2016-10-14 08:11:02 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_end_element(qn("spreadsheetml", "row"));
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_worksheet_element == qn("spreadsheetml", "sheetCalcPr")) // CT_SheetCalcPr 0-1
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-11-25 21:13:55 +08:00
|
|
|
skip_remaining_content(current_worksheet_element);
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_worksheet_element == qn("spreadsheetml", "sheetProtection")) // CT_SheetProtection 0-1
|
2016-11-25 21:13:55 +08:00
|
|
|
{
|
|
|
|
skip_remaining_content(current_worksheet_element);
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_worksheet_element == qn("spreadsheetml", "protectedRanges")) // CT_ProtectedRanges 0-1
|
2016-11-25 21:13:55 +08:00
|
|
|
{
|
|
|
|
skip_remaining_content(current_worksheet_element);
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_worksheet_element == qn("spreadsheetml", "scenarios")) // CT_Scenarios 0-1
|
2016-11-25 21:13:55 +08:00
|
|
|
{
|
|
|
|
skip_remaining_content(current_worksheet_element);
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_worksheet_element == qn("spreadsheetml", "autoFilter")) // CT_AutoFilter 0-1
|
2016-11-25 21:13:55 +08:00
|
|
|
{
|
|
|
|
ws.auto_filter(xlnt::range_reference(parser().attribute("ref")));
|
2017-02-15 05:11:31 +08:00
|
|
|
// auto filter complex
|
|
|
|
skip_remaining_content(current_worksheet_element);
|
2016-11-25 21:13:55 +08:00
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_worksheet_element == qn("spreadsheetml", "sortState")) // CT_SortState 0-1
|
2016-11-25 21:13:55 +08:00
|
|
|
{
|
|
|
|
skip_remaining_content(current_worksheet_element);
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_worksheet_element == qn("spreadsheetml", "dataConsolidate")) // CT_DataConsolidate 0-1
|
2016-11-25 21:13:55 +08:00
|
|
|
{
|
|
|
|
skip_remaining_content(current_worksheet_element);
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_worksheet_element == qn("spreadsheetml", "customSheetViews")) // CT_CustomSheetViews 0-1
|
2016-11-25 21:13:55 +08:00
|
|
|
{
|
|
|
|
skip_remaining_content(current_worksheet_element);
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_worksheet_element == qn("spreadsheetml", "mergeCells")) // CT_MergeCells 0-1
|
2016-11-25 21:13:55 +08:00
|
|
|
{
|
|
|
|
auto count = std::stoull(parser().attribute("count"));
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
while (in_element(qn("spreadsheetml", "mergeCells")))
|
2016-11-25 21:13:55 +08:00
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_start_element(qn("spreadsheetml", "mergeCell"), xml::content::simple);
|
2016-11-25 21:13:55 +08:00
|
|
|
ws.merge_cells(range_reference(parser().attribute("ref")));
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_end_element(qn("spreadsheetml", "mergeCell"));
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-11-25 21:13:55 +08:00
|
|
|
count--;
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-11-25 21:13:55 +08:00
|
|
|
if (count != 0)
|
|
|
|
{
|
|
|
|
throw invalid_file("sizes don't match");
|
|
|
|
}
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_worksheet_element == qn("spreadsheetml", "phoneticPr")) // CT_PhoneticPr 0-1
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
2016-11-25 21:13:55 +08:00
|
|
|
skip_remaining_content(current_worksheet_element);
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_worksheet_element == qn("spreadsheetml", "conditionalFormatting")) // CT_ConditionalFormatting 0+
|
2016-11-25 21:13:55 +08:00
|
|
|
{
|
|
|
|
skip_remaining_content(current_worksheet_element);
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_worksheet_element == qn("spreadsheetml", "dataValidations")) // CT_DataValidations 0-1
|
2016-11-25 21:13:55 +08:00
|
|
|
{
|
|
|
|
skip_remaining_content(current_worksheet_element);
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_worksheet_element == qn("spreadsheetml", "hyperlinks")) // CT_Hyperlinks 0-1
|
2016-11-25 21:13:55 +08:00
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
while (in_element(qn("spreadsheetml", "hyperlinks")))
|
2016-11-30 08:05:47 +08:00
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_start_element(qn("spreadsheetml", "hyperlink"), xml::content::simple);
|
2016-11-30 08:05:47 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
auto cell = ws.cell(parser().attribute("ref"));
|
2016-11-30 08:05:47 +08:00
|
|
|
|
2017-01-22 08:12:26 +08:00
|
|
|
if (parser().attribute_present(qn("r", "id")))
|
2016-11-30 08:05:47 +08:00
|
|
|
{
|
2017-01-22 08:12:26 +08:00
|
|
|
auto hyperlink_rel_id = parser().attribute(qn("r", "id"));
|
|
|
|
auto hyperlink_rel = std::find_if(hyperlinks.begin(), hyperlinks.end(),
|
|
|
|
[&](const relationship &r) { return r.id() == hyperlink_rel_id; });
|
|
|
|
|
|
|
|
if (hyperlink_rel != hyperlinks.end())
|
|
|
|
{
|
|
|
|
cell.hyperlink(hyperlink_rel->target().path().string());
|
|
|
|
}
|
2016-11-30 08:05:47 +08:00
|
|
|
}
|
|
|
|
|
2017-01-22 08:12:26 +08:00
|
|
|
skip_attributes({"location", "tooltip", "display"});
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_end_element(qn("spreadsheetml", "hyperlink"));
|
2016-11-30 08:05:47 +08:00
|
|
|
}
|
2016-11-25 21:13:55 +08:00
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_worksheet_element == qn("spreadsheetml", "printOptions")) // CT_PrintOptions 0-1
|
2016-11-25 21:13:55 +08:00
|
|
|
{
|
|
|
|
skip_remaining_content(current_worksheet_element);
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_worksheet_element == qn("spreadsheetml", "pageMargins")) // CT_PageMargins 0-1
|
2016-09-22 07:04:16 +08:00
|
|
|
{
|
|
|
|
page_margins margins;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
margins.top(parser().attribute<double>("top"));
|
|
|
|
margins.bottom(parser().attribute<double>("bottom"));
|
|
|
|
margins.left(parser().attribute<double>("left"));
|
|
|
|
margins.right(parser().attribute<double>("right"));
|
|
|
|
margins.header(parser().attribute<double>("header"));
|
|
|
|
margins.footer(parser().attribute<double>("footer"));
|
2016-09-22 07:04:16 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
ws.page_margins(margins);
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_worksheet_element == qn("spreadsheetml", "pageSetup")) // CT_PageSetup 0-1
|
2016-10-25 10:09:15 +08:00
|
|
|
{
|
2016-11-25 21:13:55 +08:00
|
|
|
skip_remaining_content(current_worksheet_element);
|
2016-10-25 10:09:15 +08:00
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_worksheet_element == qn("spreadsheetml", "headerFooter")) // CT_HeaderFooter 0-1
|
2016-10-25 10:09:15 +08:00
|
|
|
{
|
2016-12-23 07:57:22 +08:00
|
|
|
header_footer hf;
|
|
|
|
|
2016-12-24 23:04:57 +08:00
|
|
|
hf.align_with_margins(
|
|
|
|
!parser().attribute_present("alignWithMargins") || is_true(parser().attribute("alignWithMargins")));
|
|
|
|
hf.scale_with_doc(
|
|
|
|
!parser().attribute_present("alignWithMargins") || is_true(parser().attribute("alignWithMargins")));
|
|
|
|
auto different_odd_even =
|
|
|
|
parser().attribute_present("differentOddEven") && is_true(parser().attribute("differentOddEven"));
|
|
|
|
auto different_first =
|
|
|
|
parser().attribute_present("differentFirst") && is_true(parser().attribute("differentFirst"));
|
2016-12-23 07:57:22 +08:00
|
|
|
|
2016-12-23 19:51:30 +08:00
|
|
|
optional<std::array<optional<rich_text>, 3>> odd_header;
|
|
|
|
optional<std::array<optional<rich_text>, 3>> odd_footer;
|
|
|
|
optional<std::array<optional<rich_text>, 3>> even_header;
|
|
|
|
optional<std::array<optional<rich_text>, 3>> even_footer;
|
|
|
|
optional<std::array<optional<rich_text>, 3>> first_header;
|
|
|
|
optional<std::array<optional<rich_text>, 3>> first_footer;
|
2016-12-23 07:57:22 +08:00
|
|
|
|
|
|
|
while (in_element(current_worksheet_element))
|
|
|
|
{
|
|
|
|
auto current_hf_element = expect_start_element(xml::content::simple);
|
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
if (current_hf_element == qn("spreadsheetml", "oddHeader"))
|
2016-12-23 07:57:22 +08:00
|
|
|
{
|
|
|
|
odd_header = parse_header_footer(read_text());
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_hf_element == qn("spreadsheetml", "oddFooter"))
|
2016-12-23 07:57:22 +08:00
|
|
|
{
|
|
|
|
odd_footer = parse_header_footer(read_text());
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_hf_element == qn("spreadsheetml", "evenHeader"))
|
2016-12-23 07:57:22 +08:00
|
|
|
{
|
|
|
|
even_header = parse_header_footer(read_text());
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_hf_element == qn("spreadsheetml", "evenFooter"))
|
2016-12-23 07:57:22 +08:00
|
|
|
{
|
|
|
|
even_footer = parse_header_footer(read_text());
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_hf_element == qn("spreadsheetml", "firstHeader"))
|
2016-12-23 07:57:22 +08:00
|
|
|
{
|
|
|
|
first_header = parse_header_footer(read_text());
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_hf_element == qn("spreadsheetml", "firstFooter"))
|
2016-12-23 07:57:22 +08:00
|
|
|
{
|
|
|
|
first_footer = parse_header_footer(read_text());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
unexpected_element(current_hf_element);
|
|
|
|
}
|
|
|
|
|
|
|
|
expect_end_element(current_hf_element);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (std::size_t i = 0; i < 3; ++i)
|
|
|
|
{
|
|
|
|
auto loc = i == 0 ? header_footer::location::left
|
2016-12-24 23:04:57 +08:00
|
|
|
: i == 1 ? header_footer::location::center : header_footer::location::right;
|
2016-12-23 07:57:22 +08:00
|
|
|
|
|
|
|
if (different_odd_even)
|
|
|
|
{
|
2016-12-24 23:04:57 +08:00
|
|
|
if (odd_header.is_set() && odd_header.get().at(i).is_set() && even_header.is_set()
|
|
|
|
&& even_header.get().at(i).is_set())
|
2016-12-23 07:57:22 +08:00
|
|
|
{
|
|
|
|
hf.odd_even_header(loc, odd_header.get().at(i).get(), even_header.get().at(i).get());
|
|
|
|
}
|
|
|
|
|
2016-12-24 23:04:57 +08:00
|
|
|
if (odd_footer.is_set() && odd_footer.get().at(i).is_set() && even_footer.is_set()
|
|
|
|
&& even_footer.get().at(i).is_set())
|
2016-12-23 07:57:22 +08:00
|
|
|
{
|
|
|
|
hf.odd_even_footer(loc, odd_footer.get().at(i).get(), even_footer.get().at(i).get());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (odd_header.is_set() && odd_header.get().at(i).is_set())
|
|
|
|
{
|
|
|
|
hf.header(loc, odd_header.get().at(i).get());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (odd_footer.is_set() && odd_footer.get().at(i).is_set())
|
|
|
|
{
|
|
|
|
hf.footer(loc, odd_footer.get().at(i).get());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (different_first)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ws.header_footer(hf);
|
2016-10-25 10:09:15 +08:00
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_worksheet_element == qn("spreadsheetml", "rowBreaks")) // CT_PageBreak 0-1
|
2016-10-25 10:09:15 +08:00
|
|
|
{
|
2016-12-23 07:57:22 +08:00
|
|
|
auto count = parser().attribute_present("count") ? parser().attribute<std::size_t>("count") : 0;
|
2016-12-24 23:04:57 +08:00
|
|
|
auto manual_break_count = parser().attribute_present("manualBreakCount")
|
2017-01-11 09:25:59 +08:00
|
|
|
? parser().attribute<std::size_t>("manualBreakCount") : 0;
|
2016-12-23 07:57:22 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
while (in_element(qn("spreadsheetml", "rowBreaks")))
|
2016-12-23 07:57:22 +08:00
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_start_element(qn("spreadsheetml", "brk"), xml::content::simple);
|
2016-12-23 07:57:22 +08:00
|
|
|
|
|
|
|
if (parser().attribute_present("id"))
|
|
|
|
{
|
2016-12-24 23:04:57 +08:00
|
|
|
ws.page_break_at_row(parser().attribute<row_t>("id"));
|
2016-12-23 07:57:22 +08:00
|
|
|
--count;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parser().attribute_present("man") && is_true(parser().attribute("man")))
|
|
|
|
{
|
|
|
|
--manual_break_count;
|
|
|
|
}
|
2016-12-24 23:04:57 +08:00
|
|
|
|
2016-12-23 07:57:22 +08:00
|
|
|
skip_attributes({"min", "max", "pt"});
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_end_element(qn("spreadsheetml", "brk"));
|
2016-12-23 07:57:22 +08:00
|
|
|
}
|
2016-10-25 10:09:15 +08:00
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_worksheet_element == qn("spreadsheetml", "colBreaks")) // CT_PageBreak 0-1
|
2016-10-25 10:09:15 +08:00
|
|
|
{
|
2016-12-23 07:57:22 +08:00
|
|
|
auto count = parser().attribute_present("count") ? parser().attribute<std::size_t>("count") : 0;
|
2016-12-24 23:04:57 +08:00
|
|
|
auto manual_break_count = parser().attribute_present("manualBreakCount")
|
|
|
|
? parser().attribute<std::size_t>("manualBreakCount")
|
|
|
|
: 0;
|
2016-12-23 07:57:22 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
while (in_element(qn("spreadsheetml", "colBreaks")))
|
2016-12-23 07:57:22 +08:00
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_start_element(qn("spreadsheetml", "brk"), xml::content::simple);
|
2016-12-23 07:57:22 +08:00
|
|
|
|
|
|
|
if (parser().attribute_present("id"))
|
|
|
|
{
|
2016-12-24 23:04:57 +08:00
|
|
|
ws.page_break_at_column(parser().attribute<column_t::index_t>("id"));
|
2016-12-23 07:57:22 +08:00
|
|
|
--count;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parser().attribute_present("man") && is_true(parser().attribute("man")))
|
|
|
|
{
|
|
|
|
--manual_break_count;
|
|
|
|
}
|
|
|
|
|
|
|
|
skip_attributes({"min", "max", "pt"});
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_end_element(qn("spreadsheetml", "brk"));
|
2016-12-23 07:57:22 +08:00
|
|
|
}
|
2016-10-25 10:09:15 +08:00
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_worksheet_element == qn("spreadsheetml", "customProperties")) // CT_CustomProperties 0-1
|
2016-10-25 10:09:15 +08:00
|
|
|
{
|
2016-11-25 21:13:55 +08:00
|
|
|
skip_remaining_content(current_worksheet_element);
|
2016-10-25 10:09:15 +08:00
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_worksheet_element == qn("spreadsheetml", "cellWatches")) // CT_CellWatches 0-1
|
2016-10-29 22:23:04 +08:00
|
|
|
{
|
2016-11-25 21:13:55 +08:00
|
|
|
skip_remaining_content(current_worksheet_element);
|
2016-11-15 21:09:17 +08:00
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_worksheet_element == qn("spreadsheetml", "ignoredErrors")) // CT_IgnoredErrors 0-1
|
2016-11-15 21:09:17 +08:00
|
|
|
{
|
2016-11-25 21:13:55 +08:00
|
|
|
skip_remaining_content(current_worksheet_element);
|
2016-11-21 14:45:38 +08:00
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_worksheet_element == qn("spreadsheetml", "smartTags")) // CT_SmartTags 0-1
|
2016-11-21 14:45:38 +08:00
|
|
|
{
|
2016-11-25 21:13:55 +08:00
|
|
|
skip_remaining_content(current_worksheet_element);
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_worksheet_element == qn("spreadsheetml", "drawing")) // CT_Drawing 0-1
|
2016-11-25 21:13:55 +08:00
|
|
|
{
|
|
|
|
skip_remaining_content(current_worksheet_element);
|
2016-11-15 21:09:17 +08:00
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_worksheet_element == qn("spreadsheetml", "legacyDrawing"))
|
2016-11-25 21:13:55 +08:00
|
|
|
{
|
|
|
|
skip_remaining_content(current_worksheet_element);
|
|
|
|
}
|
2017-01-11 09:25:59 +08:00
|
|
|
else if (current_worksheet_element == qn("spreadsheetml", "extLst"))
|
2016-12-23 07:57:22 +08:00
|
|
|
{
|
|
|
|
skip_remaining_content(current_worksheet_element);
|
|
|
|
}
|
2016-11-25 21:13:55 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
unexpected_element(current_worksheet_element);
|
|
|
|
}
|
|
|
|
|
2016-11-30 07:31:06 +08:00
|
|
|
expect_end_element(current_worksheet_element);
|
2016-09-22 07:04:16 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_end_element(qn("spreadsheetml", "worksheet"));
|
2016-10-29 22:23:04 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (manifest.has_relationship(sheet_path, xlnt::relationship_type::comments))
|
2016-10-29 22:23:04 +08:00
|
|
|
{
|
2016-11-20 06:19:38 +08:00
|
|
|
auto comments_part = manifest.canonicalize(
|
2016-12-02 21:37:50 +08:00
|
|
|
{workbook_rel, sheet_rel, manifest.relationship(sheet_path, xlnt::relationship_type::comments)});
|
2016-10-31 03:48:40 +08:00
|
|
|
|
2016-10-29 22:23:04 +08:00
|
|
|
auto receive = xml::parser::receive_default;
|
2016-12-24 23:04:57 +08:00
|
|
|
auto comments_part_streambuf = archive_->open(comments_part);
|
|
|
|
std::istream comments_part_stream(comments_part_streambuf.get());
|
|
|
|
xml::parser parser(comments_part_stream, comments_part.string(), receive);
|
2016-10-29 22:23:04 +08:00
|
|
|
parser_ = &parser;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-11-14 00:52:39 +08:00
|
|
|
read_comments(ws);
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (manifest.has_relationship(sheet_path, xlnt::relationship_type::vml_drawing))
|
2016-10-29 22:23:04 +08:00
|
|
|
{
|
2016-12-24 23:04:57 +08:00
|
|
|
auto vml_drawings_part = manifest.canonicalize(
|
|
|
|
{workbook_rel, sheet_rel, manifest.relationship(sheet_path, xlnt::relationship_type::vml_drawing)});
|
2016-10-29 22:23:04 +08:00
|
|
|
|
2016-12-24 23:04:57 +08:00
|
|
|
auto vml_drawings_part_streambuf = archive_->open(comments_part);
|
|
|
|
std::istream vml_drawings_part_stream(comments_part_streambuf.get());
|
|
|
|
xml::parser vml_parser(vml_drawings_part_stream, vml_drawings_part.string(), receive);
|
2016-11-21 00:06:52 +08:00
|
|
|
parser_ = &vml_parser;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2016-11-14 00:52:39 +08:00
|
|
|
read_vml_drawings(ws);
|
|
|
|
}
|
2016-10-29 22:23:04 +08:00
|
|
|
}
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Sheet Relationship Target Parts
|
|
|
|
|
2016-12-24 23:04:57 +08:00
|
|
|
void xlsx_consumer::read_vml_drawings(worksheet /*ws*/)
|
2016-11-14 00:52:39 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-10-29 22:23:04 +08:00
|
|
|
void xlsx_consumer::read_comments(worksheet ws)
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
2016-10-29 22:23:04 +08:00
|
|
|
std::vector<std::string> authors;
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_start_element(qn("spreadsheetml", "comments"), xml::content::complex);
|
2017-02-25 18:50:45 +08:00
|
|
|
// name space can be ignored
|
|
|
|
skip_attribute(qn("mc","Ignorable"));
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_start_element(qn("spreadsheetml", "authors"), xml::content::complex);
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
while (in_element(qn("spreadsheetml", "authors")))
|
2016-10-29 22:23:04 +08:00
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_start_element(qn("spreadsheetml", "author"), xml::content::simple);
|
2016-11-25 21:13:55 +08:00
|
|
|
authors.push_back(read_text());
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_end_element(qn("spreadsheetml", "author"));
|
2016-10-29 22:23:04 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_end_element(qn("spreadsheetml", "authors"));
|
|
|
|
expect_start_element(qn("spreadsheetml", "commentList"), xml::content::complex);
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
while (in_element(xml::qname(qn("spreadsheetml", "commentList"))))
|
2016-10-29 22:23:04 +08:00
|
|
|
{
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_start_element(qn("spreadsheetml", "comment"), xml::content::complex);
|
2016-10-29 22:23:04 +08:00
|
|
|
|
2017-02-07 22:13:34 +08:00
|
|
|
skip_attribute("shapeId");
|
2017-02-19 10:33:59 +08:00
|
|
|
auto cell_ref = parser().attribute("ref");
|
2016-10-29 22:23:04 +08:00
|
|
|
auto author_id = parser().attribute<std::size_t>("authorId");
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_start_element(qn("spreadsheetml", "text"), xml::content::complex);
|
2016-10-29 22:23:04 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
ws.cell(cell_ref).comment(comment(read_rich_text(qn("spreadsheetml", "text")), authors.at(author_id)));
|
2016-10-30 04:31:30 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_end_element(qn("spreadsheetml", "text"));
|
2017-03-10 10:35:36 +08:00
|
|
|
|
|
|
|
if (in_element(xml::qname(qn("spreadsheetml", "comment"))))
|
|
|
|
{
|
|
|
|
expect_start_element(qn("mc", "AlternateContent"), xml::content::complex);
|
|
|
|
skip_remaining_content(qn("mc", "AlternateContent"));
|
|
|
|
expect_end_element(qn("mc", "AlternateContent"));
|
|
|
|
}
|
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_end_element(qn("spreadsheetml", "comment"));
|
2016-10-29 22:23:04 +08:00
|
|
|
}
|
2016-11-20 06:19:38 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
expect_end_element(qn("spreadsheetml", "commentList"));
|
|
|
|
expect_end_element(qn("spreadsheetml", "comments"));
|
2016-08-05 13:52:05 +08:00
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_drawings()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
// Unknown Parts
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_unknown_parts()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-10-12 11:16:14 +08:00
|
|
|
void xlsx_consumer::read_unknown_relationships()
|
2016-08-05 13:52:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
void xlsx_consumer::read_image(const xlnt::path &image_path)
|
|
|
|
{
|
2016-12-24 23:04:57 +08:00
|
|
|
auto image_streambuf = archive_->open(image_path);
|
2016-12-02 21:37:50 +08:00
|
|
|
vector_ostreambuf buffer(target_.d_->images_[image_path.string()]);
|
|
|
|
std::ostream out_stream(&buffer);
|
2016-12-24 23:04:57 +08:00
|
|
|
out_stream << image_streambuf.get();
|
2016-12-02 21:37:50 +08:00
|
|
|
}
|
|
|
|
|
2016-11-20 05:42:16 +08:00
|
|
|
std::string xlsx_consumer::read_text()
|
|
|
|
{
|
|
|
|
auto text = std::string();
|
|
|
|
|
|
|
|
while (parser().peek() == xml::parser::event_type::characters)
|
|
|
|
{
|
|
|
|
parser().next_expect(xml::parser::event_type::characters);
|
|
|
|
text.append(parser().value());
|
|
|
|
}
|
|
|
|
|
|
|
|
return text;
|
|
|
|
}
|
|
|
|
|
2017-01-17 02:05:19 +08:00
|
|
|
variant xlsx_consumer::read_variant()
|
|
|
|
{
|
|
|
|
auto value = variant(read_text());
|
|
|
|
|
|
|
|
if (in_element(stack_.back()))
|
|
|
|
{
|
|
|
|
auto element = expect_start_element(xml::content::mixed);
|
|
|
|
auto text = read_text();
|
|
|
|
|
|
|
|
if (element == qn("vt", "lpwstr") || element == qn("vt", "lpstr"))
|
|
|
|
{
|
|
|
|
value = variant(text);
|
|
|
|
}
|
|
|
|
if (element == qn("vt", "i4"))
|
|
|
|
{
|
|
|
|
value = variant(std::stoi(text));
|
|
|
|
}
|
2017-01-23 02:34:40 +08:00
|
|
|
if (element == qn("vt", "bool"))
|
|
|
|
{
|
2017-02-15 05:33:54 +08:00
|
|
|
value = variant(is_true(text));
|
2017-01-23 02:34:40 +08:00
|
|
|
}
|
2017-01-17 02:05:19 +08:00
|
|
|
else if (element == qn("vt", "vector"))
|
|
|
|
{
|
|
|
|
auto size = parser().attribute<std::size_t>("size");
|
|
|
|
auto base_type = parser().attribute("baseType");
|
|
|
|
|
|
|
|
std::vector<variant> vector;
|
|
|
|
|
|
|
|
for (auto i = std::size_t(0); i < size; ++i)
|
|
|
|
{
|
|
|
|
if (base_type == "variant")
|
|
|
|
{
|
|
|
|
expect_start_element(qn("vt", "variant"), xml::content::complex);
|
|
|
|
}
|
|
|
|
|
|
|
|
vector.push_back(read_variant());
|
|
|
|
|
|
|
|
if (base_type == "variant")
|
|
|
|
{
|
|
|
|
expect_end_element(qn("vt", "variant"));
|
|
|
|
read_text();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
value = variant(vector);
|
|
|
|
}
|
|
|
|
|
|
|
|
expect_end_element(element);
|
|
|
|
read_text();
|
|
|
|
}
|
|
|
|
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
2016-11-25 21:13:55 +08:00
|
|
|
void xlsx_consumer::skip_attributes(const std::vector<std::string> &names)
|
2016-11-20 05:42:16 +08:00
|
|
|
{
|
2016-11-25 21:13:55 +08:00
|
|
|
for (const auto &name : names)
|
2016-11-20 05:42:16 +08:00
|
|
|
{
|
2016-11-25 21:13:55 +08:00
|
|
|
if (parser().attribute_present(name))
|
|
|
|
{
|
|
|
|
parser().attribute(name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-11-20 05:42:16 +08:00
|
|
|
|
2016-11-25 21:13:55 +08:00
|
|
|
void xlsx_consumer::skip_attributes(const std::vector<xml::qname> &names)
|
|
|
|
{
|
|
|
|
for (const auto &name : names)
|
|
|
|
{
|
|
|
|
if (parser().attribute_present(name))
|
2016-11-20 05:42:16 +08:00
|
|
|
{
|
2016-11-25 21:13:55 +08:00
|
|
|
parser().attribute(name);
|
2016-11-20 05:42:16 +08:00
|
|
|
}
|
2016-11-25 21:13:55 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void xlsx_consumer::skip_attributes()
|
|
|
|
{
|
|
|
|
parser().attribute_map();
|
|
|
|
}
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
void xlsx_consumer::skip_attribute(const xml::qname &name)
|
|
|
|
{
|
|
|
|
if (parser().attribute_present(name))
|
|
|
|
{
|
|
|
|
parser().attribute(name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void xlsx_consumer::skip_attribute(const std::string &name)
|
|
|
|
{
|
|
|
|
if (parser().attribute_present(name))
|
|
|
|
{
|
|
|
|
parser().attribute(name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-25 21:13:55 +08:00
|
|
|
void xlsx_consumer::skip_remaining_content(const xml::qname &name)
|
|
|
|
{
|
|
|
|
// start by assuming we've already parsed the opening tag
|
|
|
|
|
|
|
|
skip_attributes();
|
2016-11-30 07:31:06 +08:00
|
|
|
read_namespaces();
|
2016-11-25 21:13:55 +08:00
|
|
|
read_text();
|
|
|
|
|
|
|
|
// continue until the closing tag is reached
|
|
|
|
while (in_element(name))
|
|
|
|
{
|
2016-11-30 07:31:06 +08:00
|
|
|
auto child_element = expect_start_element(xml::content::mixed);
|
|
|
|
skip_remaining_content(child_element);
|
|
|
|
expect_end_element(child_element);
|
|
|
|
read_text(); // trailing character content (usually whitespace)
|
2016-11-25 21:13:55 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<std::string> xlsx_consumer::read_namespaces()
|
|
|
|
{
|
|
|
|
std::vector<std::string> namespaces;
|
|
|
|
|
|
|
|
while (parser().peek() == xml::parser::event_type::start_namespace_decl)
|
|
|
|
{
|
|
|
|
parser().next_expect(xml::parser::event_type::start_namespace_decl);
|
2016-11-30 07:31:06 +08:00
|
|
|
namespaces.push_back(parser().namespace_());
|
|
|
|
|
|
|
|
if (parser().peek() == xml::parser::event_type::end_namespace_decl)
|
|
|
|
{
|
|
|
|
parser().next_expect(xml::parser::event_type::end_namespace_decl);
|
|
|
|
}
|
2016-11-25 21:13:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return namespaces;
|
|
|
|
}
|
2016-11-20 05:42:16 +08:00
|
|
|
|
2016-11-30 07:31:06 +08:00
|
|
|
bool xlsx_consumer::in_element(const xml::qname &name)
|
2016-11-25 21:13:55 +08:00
|
|
|
{
|
2017-02-15 05:33:54 +08:00
|
|
|
return parser().peek() != xml::parser::event_type::end_element
|
|
|
|
&& stack_.back() == name;
|
2016-11-25 21:13:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
xml::qname xlsx_consumer::expect_start_element(xml::content content)
|
|
|
|
{
|
|
|
|
parser().next_expect(xml::parser::event_type::start_element);
|
|
|
|
parser().content(content);
|
2016-11-30 07:31:06 +08:00
|
|
|
stack_.push_back(parser().qname());
|
2016-11-25 21:13:55 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
const auto xml_space = qn("xml", "space");
|
2016-12-24 23:04:57 +08:00
|
|
|
preserve_space_ = parser().attribute_present(xml_space) ? parser().attribute(xml_space) == "preserve" : false;
|
2016-12-14 15:23:49 +08:00
|
|
|
|
2016-11-30 07:31:06 +08:00
|
|
|
return stack_.back();
|
2016-11-25 21:13:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void xlsx_consumer::expect_start_element(const xml::qname &name, xml::content content)
|
|
|
|
{
|
|
|
|
parser().next_expect(xml::parser::event_type::start_element, name);
|
|
|
|
parser().content(content);
|
2016-11-30 07:31:06 +08:00
|
|
|
stack_.push_back(name);
|
2016-12-14 15:23:49 +08:00
|
|
|
|
2017-01-11 09:25:59 +08:00
|
|
|
const auto xml_space = qn("xml", "space");
|
2016-12-24 23:04:57 +08:00
|
|
|
preserve_space_ = parser().attribute_present(xml_space) ? parser().attribute(xml_space) == "preserve" : false;
|
2016-11-20 05:42:16 +08:00
|
|
|
}
|
|
|
|
|
2016-11-25 21:13:55 +08:00
|
|
|
void xlsx_consumer::expect_end_element(const xml::qname &name)
|
2016-11-21 07:36:52 +08:00
|
|
|
{
|
2016-11-25 21:13:55 +08:00
|
|
|
parser().next_expect(xml::parser::event_type::end_element, name);
|
|
|
|
|
|
|
|
while (parser().peek() == xml::parser::event_type::end_namespace_decl)
|
|
|
|
{
|
|
|
|
parser().next_expect(xml::parser::event_type::end_namespace_decl);
|
|
|
|
}
|
2016-11-30 07:31:06 +08:00
|
|
|
|
|
|
|
stack_.pop_back();
|
2016-11-25 21:13:55 +08:00
|
|
|
}
|
|
|
|
|
2016-12-23 19:51:30 +08:00
|
|
|
rich_text xlsx_consumer::read_rich_text(const xml::qname &parent)
|
2016-11-25 21:13:55 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
const auto &xmlns = parent.namespace_();
|
2016-12-23 19:51:30 +08:00
|
|
|
rich_text t;
|
2016-11-25 21:13:55 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
while (in_element(parent))
|
2016-11-25 21:13:55 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
auto text_element = expect_start_element(xml::content::mixed);
|
|
|
|
skip_attributes();
|
|
|
|
auto text = read_text();
|
2016-11-25 21:13:55 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (text_element == xml::qname(xmlns, "t"))
|
2016-11-25 21:13:55 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
t.plain_text(text);
|
|
|
|
}
|
|
|
|
else if (text_element == xml::qname(xmlns, "r"))
|
|
|
|
{
|
2016-12-23 19:51:30 +08:00
|
|
|
rich_text_run run;
|
2016-11-25 21:13:55 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
while (in_element(xml::qname(xmlns, "r")))
|
|
|
|
{
|
|
|
|
auto run_element = expect_start_element(xml::content::mixed);
|
|
|
|
auto run_text = read_text();
|
2016-12-24 23:04:57 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (run_element == xml::qname(xmlns, "rPr"))
|
2016-11-25 21:13:55 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
while (in_element(xml::qname(xmlns, "rPr")))
|
2016-11-30 07:31:06 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
auto current_run_property_element = expect_start_element(xml::content::simple);
|
2016-11-25 21:13:55 +08:00
|
|
|
|
2016-12-23 19:51:30 +08:00
|
|
|
run.second = xlnt::font();
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (current_run_property_element == xml::qname(xmlns, "sz"))
|
|
|
|
{
|
2016-12-26 22:38:26 +08:00
|
|
|
run.second.get().size(parser().attribute<double>("val"));
|
2016-12-02 21:37:50 +08:00
|
|
|
}
|
|
|
|
else if (current_run_property_element == xml::qname(xmlns, "rFont"))
|
|
|
|
{
|
2016-12-23 19:51:30 +08:00
|
|
|
run.second.get().name(parser().attribute("val"));
|
2016-12-02 21:37:50 +08:00
|
|
|
}
|
|
|
|
else if (current_run_property_element == xml::qname(xmlns, "color"))
|
|
|
|
{
|
2016-12-23 19:51:30 +08:00
|
|
|
run.second.get().color(read_color());
|
2016-12-02 21:37:50 +08:00
|
|
|
}
|
|
|
|
else if (current_run_property_element == xml::qname(xmlns, "family"))
|
|
|
|
{
|
2016-12-23 19:51:30 +08:00
|
|
|
run.second.get().family(parser().attribute<std::size_t>("val"));
|
2016-12-02 21:37:50 +08:00
|
|
|
}
|
2017-02-07 06:00:45 +08:00
|
|
|
else if (current_run_property_element == xml::qname(xmlns, "charset"))
|
|
|
|
{
|
|
|
|
run.second.get().charset(parser().attribute<std::size_t>("val"));
|
|
|
|
}
|
2016-12-02 21:37:50 +08:00
|
|
|
else if (current_run_property_element == xml::qname(xmlns, "scheme"))
|
|
|
|
{
|
2016-12-23 19:51:30 +08:00
|
|
|
run.second.get().scheme(parser().attribute("val"));
|
2016-12-02 21:37:50 +08:00
|
|
|
}
|
|
|
|
else if (current_run_property_element == xml::qname(xmlns, "b"))
|
|
|
|
{
|
2017-02-15 05:33:54 +08:00
|
|
|
run.second.get().bold(parser().attribute_present("val")
|
2017-02-19 10:33:59 +08:00
|
|
|
? is_true(parser().attribute("val")) : true);
|
2016-12-02 21:37:50 +08:00
|
|
|
}
|
2017-02-07 06:00:45 +08:00
|
|
|
else if (current_run_property_element == xml::qname(xmlns, "i"))
|
|
|
|
{
|
2017-02-15 05:45:44 +08:00
|
|
|
run.second.get().italic(parser().attribute_present("val")
|
2017-02-19 10:33:59 +08:00
|
|
|
? is_true(parser().attribute("val")) : true);
|
2017-02-07 06:00:45 +08:00
|
|
|
}
|
2016-12-02 21:37:50 +08:00
|
|
|
else if (current_run_property_element == xml::qname(xmlns, "u"))
|
|
|
|
{
|
|
|
|
if (parser().attribute_present("val"))
|
|
|
|
{
|
2016-12-23 19:51:30 +08:00
|
|
|
run.second.get().underline(parser().attribute<font::underline_style>("val"));
|
2016-12-02 21:37:50 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-12-23 19:51:30 +08:00
|
|
|
run.second.get().underline(font::underline_style::single);
|
2016-12-02 21:37:50 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
unexpected_element(current_run_property_element);
|
|
|
|
}
|
|
|
|
|
|
|
|
expect_end_element(current_run_property_element);
|
|
|
|
read_text();
|
|
|
|
}
|
2016-11-25 21:13:55 +08:00
|
|
|
}
|
2016-12-02 21:37:50 +08:00
|
|
|
else if (run_element == xml::qname(xmlns, "t"))
|
|
|
|
{
|
2016-12-23 19:51:30 +08:00
|
|
|
run.first = run_text;
|
2016-12-02 21:37:50 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
unexpected_element(run_element);
|
|
|
|
}
|
|
|
|
|
|
|
|
read_text();
|
|
|
|
expect_end_element(run_element);
|
|
|
|
read_text();
|
2016-11-30 07:31:06 +08:00
|
|
|
}
|
2016-12-24 23:04:57 +08:00
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
t.add_run(run);
|
|
|
|
}
|
|
|
|
else if (text_element == xml::qname(xmlns, "rPh"))
|
|
|
|
{
|
|
|
|
skip_remaining_content(text_element);
|
|
|
|
}
|
|
|
|
else if (text_element == xml::qname(xmlns, "phoneticPr"))
|
|
|
|
{
|
|
|
|
skip_remaining_content(text_element);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
unexpected_element(text_element);
|
2016-11-25 21:13:55 +08:00
|
|
|
}
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
read_text();
|
|
|
|
expect_end_element(text_element);
|
|
|
|
}
|
2016-11-25 21:13:55 +08:00
|
|
|
|
|
|
|
return t;
|
2016-11-21 07:36:52 +08:00
|
|
|
}
|
|
|
|
|
2016-11-30 07:31:06 +08:00
|
|
|
xlnt::color xlsx_consumer::read_color()
|
|
|
|
{
|
|
|
|
xlnt::color result;
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
if (parser().attribute_present("auto") && is_true(parser().attribute("auto")))
|
2016-11-30 07:31:06 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
result.auto_(true);
|
2016-11-30 07:31:06 +08:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parser().attribute_present("rgb"))
|
|
|
|
{
|
|
|
|
result = xlnt::rgb_color(parser().attribute("rgb"));
|
|
|
|
}
|
|
|
|
else if (parser().attribute_present("theme"))
|
|
|
|
{
|
|
|
|
result = xlnt::theme_color(parser().attribute<std::size_t>("theme"));
|
|
|
|
}
|
|
|
|
else if (parser().attribute_present("indexed"))
|
|
|
|
{
|
|
|
|
result = xlnt::indexed_color(parser().attribute<std::size_t>("indexed"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parser().attribute_present("tint"))
|
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
result.tint(parser().attribute("tint", 0.0));
|
2016-11-30 07:31:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2016-12-02 21:37:50 +08:00
|
|
|
manifest &xlsx_consumer::manifest()
|
2016-11-30 07:31:06 +08:00
|
|
|
{
|
2016-12-02 21:37:50 +08:00
|
|
|
return target_.manifest();
|
2016-11-30 07:31:06 +08:00
|
|
|
}
|
|
|
|
|
2016-08-05 13:52:05 +08:00
|
|
|
} // namespace detail
|
|
|
|
} // namepsace xlnt
|