From 5354f99677c6e911b5083c4815bc5524e5b9236c Mon Sep 17 00:00:00 2001 From: "Elena.Subbotina" Date: Thu, 31 Aug 2023 11:19:28 +0300 Subject: [PATCH] fix & update ods filters/sort --- OdfFile/DataTypes/tabledatatype.cpp | 86 ++ OdfFile/DataTypes/tabledatatype.h | 76 ++ OdfFile/DataTypes/tableoperator.cpp | 114 ++ OdfFile/DataTypes/tableoperator.h | 89 ++ OdfFile/Projects/Linux/OdfFormatLib.pro | 6 +- OdfFile/Projects/Linux/odf_datatypes.cpp | 2 + OdfFile/Projects/Windows/cpcommon.vcxproj | 4 + .../Projects/Windows/cpcommon.vcxproj.filters | 12 + OdfFile/Reader/Converter/xlsx_table_state.cpp | 132 +- OdfFile/Reader/Converter/xlsx_table_state.h | 25 +- .../Reader/Converter/xlsx_tablecontext.cpp | 1061 +++++++++-------- OdfFile/Reader/Converter/xlsx_tablecontext.h | 13 +- .../Converter/xlsxconversioncontext.cpp | 29 + .../Reader/Converter/xlsxconversioncontext.h | 1 + .../Reader/Format/table_database_ranges.cpp | 35 +- OdfFile/Reader/Format/table_database_ranges.h | 46 +- OdfFile/Reader/Format/table_xlsx.cpp | 5 +- 17 files changed, 1139 insertions(+), 597 deletions(-) create mode 100644 OdfFile/DataTypes/tabledatatype.cpp create mode 100644 OdfFile/DataTypes/tabledatatype.h create mode 100644 OdfFile/DataTypes/tableoperator.cpp create mode 100644 OdfFile/DataTypes/tableoperator.h diff --git a/OdfFile/DataTypes/tabledatatype.cpp b/OdfFile/DataTypes/tabledatatype.cpp new file mode 100644 index 0000000000..bdb8f2579e --- /dev/null +++ b/OdfFile/DataTypes/tabledatatype.cpp @@ -0,0 +1,86 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2023 + * + * This program is a free software product. You can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License (AGPL) + * version 3 as published by the Free Software Foundation. In accordance with + * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect + * that Ascensio System SIA expressly excludes the warranty of non-infringement + * of any third-party rights. + * + * This program is distributed WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For + * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html + * + * You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish + * street, Riga, Latvia, EU, LV-1050. + * + * The interactive user interfaces in modified source and object code versions + * of the Program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU AGPL version 3. + * + * Pursuant to Section 7(b) of the License you must retain the original Product + * logo when distributing the program. Pursuant to Section 7(e) we decline to + * grant you any rights under trademark law for use of our trademarks. + * + * All the Product's GUI elements, including illustrations and icon sets, as + * well as technical writing content are licensed under the terms of the + * Creative Commons Attribution-ShareAlike 4.0 International. See the License + * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode + * + */ + +#include "tabledatatype.h" + +#include +#include + +namespace cpdoccore { namespace odf_types { + +std::wostream & operator << (std::wostream & _Wostream, const table_data_type& _Val) +{ + switch(_Val.get_type()) + { + case table_data_type::automatic: + _Wostream << L"automatic"; + break; + case table_data_type::text: + _Wostream << L"text"; + break; + case table_data_type::number: + _Wostream << L"number"; + break; + case table_data_type::background_color: + _Wostream << L"background_color"; + break; + case table_data_type::text_color: + _Wostream << L"text_color"; + break; + case table_data_type::user_defined: + _Wostream << _Val.get_user_defined(); + break; + default: + _Wostream << L"text"; + break; + } + return _Wostream; +} +table_data_type table_data_type::parse(const std::wstring & Str) +{ + if (Str == L"automatic") + return table_data_type(automatic); + else if (Str == L"text") + return table_data_type(text); + else if (Str == L"number") + return table_data_type(number); + else if (Str == L"background-color") + return table_data_type(background_color); + else if (Str == L"text-color") + return table_data_type(text_color); + else + { + return table_data_type(user_defined, Str); + } +} + +} } diff --git a/OdfFile/DataTypes/tabledatatype.h b/OdfFile/DataTypes/tabledatatype.h new file mode 100644 index 0000000000..05ec23d17b --- /dev/null +++ b/OdfFile/DataTypes/tabledatatype.h @@ -0,0 +1,76 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2023 + * + * This program is a free software product. You can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License (AGPL) + * version 3 as published by the Free Software Foundation. In accordance with + * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect + * that Ascensio System SIA expressly excludes the warranty of non-infringement + * of any third-party rights. + * + * This program is distributed WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For + * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html + * + * You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish + * street, Riga, Latvia, EU, LV-1050. + * + * The interactive user interfaces in modified source and object code versions + * of the Program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU AGPL version 3. + * + * Pursuant to Section 7(b) of the License you must retain the original Product + * logo when distributing the program. Pursuant to Section 7(e) we decline to + * grant you any rights under trademark law for use of our trademarks. + * + * All the Product's GUI elements, including illustrations and icon sets, as + * well as technical writing content are licensed under the terms of the + * Creative Commons Attribution-ShareAlike 4.0 International. See the License + * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode + * + */ +#pragma once + +#include +#include +#include "odfattributes.h" + + +namespace cpdoccore { namespace odf_types { + +class table_data_type +{ +public: + enum type + { + automatic, + text, + number, + background_color, + text_color, + user_defined + }; + + table_data_type() {} + + table_data_type(type _Type, const std::wstring &user = L"") : type_(_Type), user_defined_(user) + {} + + type get_type() const + { + return type_; + }; + std::wstring get_user_defined() const + { + return user_defined_; + }; + static table_data_type parse(const std::wstring & Str); +private: + type type_; + std::wstring user_defined_; + +}; +std::wostream & operator << (std::wostream & _Wostream, const table_data_type& _Val); +} +APPLY_PARSE_XML_ATTRIBUTES(odf_types::table_data_type); +} diff --git a/OdfFile/DataTypes/tableoperator.cpp b/OdfFile/DataTypes/tableoperator.cpp new file mode 100644 index 0000000000..e6f6ecd74e --- /dev/null +++ b/OdfFile/DataTypes/tableoperator.cpp @@ -0,0 +1,114 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2023 + * + * This program is a free software product. You can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License (AGPL) + * version 3 as published by the Free Software Foundation. In accordance with + * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect + * that Ascensio System SIA expressly excludes the warranty of non-infringement + * of any third-party rights. + * + * This program is distributed WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For + * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html + * + * You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish + * street, Riga, Latvia, EU, LV-1050. + * + * The interactive user interfaces in modified source and object code versions + * of the Program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU AGPL version 3. + * + * Pursuant to Section 7(b) of the License you must retain the original Product + * logo when distributing the program. Pursuant to Section 7(e) we decline to + * grant you any rights under trademark law for use of our trademarks. + * + * All the Product's GUI elements, including illustrations and icon sets, as + * well as technical writing content are licensed under the terms of the + * Creative Commons Attribution-ShareAlike 4.0 International. See the License + * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode + * + */ + +#include "tableoperator.h" + +#include +#include + +namespace cpdoccore { namespace odf_types { + +std::wostream & operator << (std::wostream & _Wostream, const table_operator& _Val) +{ + switch(_Val.get_type()) + { + case table_operator::Equal: _Wostream << L"="; break; + case table_operator::NotEqual: _Wostream << L"!="; break; + case table_operator::LessThan: _Wostream << L"<"; break; + case table_operator::GreaterThan: _Wostream << L">"; break; + case table_operator::LessThanOrEqual: _Wostream << L"<="; break; + case table_operator::GreaterThanOrEqual: _Wostream << L">="; break; + case table_operator::BeginsWith: _Wostream << L"begins"; break; + case table_operator::EndsWith: _Wostream << L"ends"; break; + case table_operator::Contains: _Wostream << L"contains"; break; + case table_operator::NotContains: _Wostream << L"!contains"; break; + case table_operator::NotBeginsWith: _Wostream << L"!begins"; break; + case table_operator::NotEndsWith: _Wostream << L"!ends"; break; + case table_operator::BottomPercent: _Wostream << L"bottom percent"; break; + case table_operator::BottomValues: _Wostream << L"bottom values"; break; + case table_operator::Empty: _Wostream << L"empty"; break; + case table_operator::NonEmpty: _Wostream << L"!empty"; break; + case table_operator::TopPercent: _Wostream << L"top percent"; break; + case table_operator::TopValues: _Wostream << L"top values"; break; + case table_operator::UserDefined: _Wostream << _Val.get_user_defined(); break; + default: + _Wostream << L"text"; + break; + } + return _Wostream; +} + +table_operator table_operator::parse(const std::wstring & Str) +{ + if (Str == L"=") + return table_operator(Equal); + else if (Str == L"!=") + return table_operator(NotEqual); + else if (Str == L"<") + return table_operator(LessThan); + else if (Str == L">") + return table_operator(GreaterThan); + else if (Str == L"<=") + return table_operator(LessThanOrEqual); + else if (Str == L">=") + return table_operator(GreaterThanOrEqual); + else if (Str == L"begins") + return table_operator(BeginsWith); + else if (Str == L"ends") + return table_operator(EndsWith); + else if (Str == L"!begins") + return table_operator(NotBeginsWith); + else if (Str == L"!ends") + return table_operator(NotEndsWith); + else if (Str == L"contains") + return table_operator(Contains); + else if (Str == L"!contains") + return table_operator(NotContains); + else if (Str == L"bottom percent") + return table_operator(BottomPercent); + else if (Str == L"bottom values") + return table_operator(BottomValues); + else if (Str == L"top percent") + return table_operator(TopPercent); + else if (Str == L"top values") + return table_operator(TopValues); + else if (Str == L"empty") + return table_operator(Empty); + else if (Str == L"!empty") + return table_operator(NonEmpty); + else + { + return table_operator(UserDefined, Str); + } +} + +} } diff --git a/OdfFile/DataTypes/tableoperator.h b/OdfFile/DataTypes/tableoperator.h new file mode 100644 index 0000000000..36a1386c87 --- /dev/null +++ b/OdfFile/DataTypes/tableoperator.h @@ -0,0 +1,89 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2023 + * + * This program is a free software product. You can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License (AGPL) + * version 3 as published by the Free Software Foundation. In accordance with + * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect + * that Ascensio System SIA expressly excludes the warranty of non-infringement + * of any third-party rights. + * + * This program is distributed WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For + * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html + * + * You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish + * street, Riga, Latvia, EU, LV-1050. + * + * The interactive user interfaces in modified source and object code versions + * of the Program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU AGPL version 3. + * + * Pursuant to Section 7(b) of the License you must retain the original Product + * logo when distributing the program. Pursuant to Section 7(e) we decline to + * grant you any rights under trademark law for use of our trademarks. + * + * All the Product's GUI elements, including illustrations and icon sets, as + * well as technical writing content are licensed under the terms of the + * Creative Commons Attribution-ShareAlike 4.0 International. See the License + * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode + * + */ +#pragma once + +#include +#include +#include "odfattributes.h" + + +namespace cpdoccore { namespace odf_types { + +class table_operator +{ +public: + enum type + { + Equal, + NotEqual, + LessThan, + GreaterThan, + LessThanOrEqual, + GreaterThanOrEqual, + BeginsWith, + Contains, + NotContains, + EndsWith, + NotBeginsWith, + NotEndsWith, + BottomPercent, + BottomValues, + Empty, + NonEmpty, + TopPercent, + TopValues, + UserDefined + }; + + table_operator() {} + + table_operator(type _Type, const std::wstring &user = L"") : type_(_Type), user_defined_(user) + {} + + type get_type() const + { + return type_; + }; + std::wstring get_user_defined() const + { + return user_defined_; + }; + static table_operator parse(const std::wstring & Str); +private: + type type_; + std::wstring user_defined_; + +}; +std::wostream & operator << (std::wostream & _Wostream, const table_operator& _Val); +} +APPLY_PARSE_XML_ATTRIBUTES(odf_types::table_operator); +} diff --git a/OdfFile/Projects/Linux/OdfFormatLib.pro b/OdfFile/Projects/Linux/OdfFormatLib.pro index 357aaa0dcf..6cd60c4550 100644 --- a/OdfFile/Projects/Linux/OdfFormatLib.pro +++ b/OdfFile/Projects/Linux/OdfFormatLib.pro @@ -137,6 +137,8 @@ SOURCES += \ ../../DataTypes/grandtotal.cpp \ ../../DataTypes/membertype.cpp \ ../../DataTypes/tabletype.cpp \ + ../../DataTypes/tabledatatype.cpp \ + ../../DataTypes/tableoperator.cpp \ ../../DataTypes/tableorientation.cpp \ ../../DataTypes/tablefunction.cpp \ ../../DataTypes/tableorder.cpp \ @@ -533,7 +535,9 @@ HEADERS += \ ../../DataTypes/timeperiod.h \ ../../DataTypes/messagetype.h \ ../../DataTypes/stylecellprotect.h \ - \ + ../../DataTypes/tabledatatype.h \ + ../../DataTypes/tableoperator.h \ + \ ../../Formulas/formulasconvert.h \ ../../Reader/Format/odf_document.h \ ../../Reader/Format/abstract_xml.h \ diff --git a/OdfFile/Projects/Linux/odf_datatypes.cpp b/OdfFile/Projects/Linux/odf_datatypes.cpp index a554438f8c..34c8b84ef5 100644 --- a/OdfFile/Projects/Linux/odf_datatypes.cpp +++ b/OdfFile/Projects/Linux/odf_datatypes.cpp @@ -140,3 +140,5 @@ #include "../../DataTypes/stylecellprotect.cpp" #include "../../DataTypes/mathvariant.cpp" #include "../../DataTypes/sparklines.cpp" +#include "../../DataTypes/tabledatatype.cpp" +#include "../../DataTypes/tableoperator.cpp" diff --git a/OdfFile/Projects/Windows/cpcommon.vcxproj b/OdfFile/Projects/Windows/cpcommon.vcxproj index 339364273f..8761c2330e 100644 --- a/OdfFile/Projects/Windows/cpcommon.vcxproj +++ b/OdfFile/Projects/Windows/cpcommon.vcxproj @@ -270,8 +270,10 @@ + + @@ -387,8 +389,10 @@ + + diff --git a/OdfFile/Projects/Windows/cpcommon.vcxproj.filters b/OdfFile/Projects/Windows/cpcommon.vcxproj.filters index 66bcc111a5..dc5da92819 100644 --- a/OdfFile/Projects/Windows/cpcommon.vcxproj.filters +++ b/OdfFile/Projects/Windows/cpcommon.vcxproj.filters @@ -359,6 +359,12 @@ datatypes odf + + datatypes odf + + + datatypes odf + @@ -696,5 +702,11 @@ datatypes odf + + datatypes odf + + + datatypes odf + \ No newline at end of file diff --git a/OdfFile/Reader/Converter/xlsx_table_state.cpp b/OdfFile/Reader/Converter/xlsx_table_state.cpp index 00426cbfee..1c3249a2d9 100644 --- a/OdfFile/Reader/Converter/xlsx_table_state.cpp +++ b/OdfFile/Reader/Converter/xlsx_table_state.cpp @@ -48,15 +48,17 @@ namespace cpdoccore { namespace oox { -void xlsx_data_range::serialize_autofilter (std::wostream & _Wostream) +void xlsx_data_range::serialize_autofilter(std::wostream& _Wostream) { - if (!filter) return; + if (!filter_button && filter_conditions.empty()) return; CP_XML_WRITER(_Wostream) - { + { CP_XML_NODE(L"autoFilter") { CP_XML_ATTR(L"ref", ref); + + serialize_filterColumn(CP_XML_STREAM(), 0); } } } @@ -64,63 +66,119 @@ void xlsx_data_range::serialize_sort (std::wostream & _Wostream) { if (bySort.empty()) return; - if (byRow) return; - CP_XML_WRITER(_Wostream) { CP_XML_NODE(L"sortState") { CP_XML_ATTR(L"ref", ref); + CP_XML_ATTR(L"xmlns:xlrd2", "http://schemas.microsoft.com/office/spreadsheetml/2017/richdata2"); if (!byRow) CP_XML_ATTR(L"columnSort", true); - for (size_t i = 0 ; i < bySort.size(); i++) + std::wstring ref_base, ref2, ref1; + size_t col_base, row_base, col_2, row_2; + + size_t pos = ref.find(L":"); + if (pos != std::wstring::npos) + { + ref_base = ref.substr(0, pos); + ref2 = ref.substr(pos + 1); + } + bool bSplit = getCellAddressInv(ref_base, col_base, row_base) && getCellAddressInv(ref2, col_2, row_2); + + for (size_t i = 0 ; bSplit && i < bySort.size(); i++) { bool in_range = true; - std::wstring ref1, ref2; - size_t col_1, row_1, col_2, row_2; - - size_t pos = ref.find(L":"); - if (pos != std::wstring::npos) + if (byRow) { - ref1 = ref.substr(0, pos ); - ref2 = ref.substr(pos + 1); + if (col_base + bySort[i].first > col_2) in_range = false; + + ref1 = getCellAddress(col_base + bySort[i].first + (withHeader ? 1 : 0), row_base); + ref2 = getCellAddress(col_base + bySort[i].first + (withHeader ? 1 : 0), row_2); } - - if (getCellAddressInv(ref1, col_1, row_1) && - getCellAddressInv(ref2, col_2, row_2)) + else { - if (byRow) + if ( bySort[i].first > row_2) in_range = false; + + ref1 = getCellAddress(col_base, row_base + bySort[i].first + (withHeader ? 1 : 0)); + ref2 = getCellAddress(col_2, row_base + bySort[i].first + (withHeader ? 1 : 0)); + } + if (in_range) + { + CP_XML_NODE(L"sortCondition") { - if (bySort[i].first < col_1 || bySort[i].first > col_2) in_range = false; + CP_XML_ATTR(L"ref", ref1 + L":" + ref2); - ref1 = getCellAddress(bySort[i].first + (withHeader ? 1 : 0), row_1); - ref2 = getCellAddress(bySort[i].first + (withHeader ? 1 : 0), row_2); + if (bySort[i].second) + CP_XML_ATTR(L"descending", 1); } - else - { - if (bySort[i].first < row_1 || bySort[i].first > row_2) in_range = false; - ref1 = getCellAddress(col_1, bySort[i].first + (withHeader ? 1 : 0)); - ref2 = getCellAddress(col_2, bySort[i].first + (withHeader ? 1 : 0)); - } - if (in_range) - { - CP_XML_NODE(L"sortCondition") - { - CP_XML_ATTR(L"ref", ref1 + L":" + ref2); - - if (bySort[i].second) - CP_XML_ATTR(L"descending", 1); - } - - } } } } } } +void xlsx_data_range::serialize_filterColumn(std::wostream& _Wostream, int indexCol) +{ + CP_XML_WRITER(_Wostream) + { + CP_XML_NODE(L"filterColumn") + { + CP_XML_ATTR(L"colId", indexCol); + if (bFilterAndOr && filter_conditions.size() > 1) + { + CP_XML_NODE(L"customFilters") + { + if (*bFilterAndOr) + CP_XML_ATTR(L"and", 1); + else + CP_XML_ATTR(L"and", 0); + for (size_t i = 0; i < filter_conditions.size(); ++i) + { + CP_XML_NODE(L"customFilter") + { + switch (filter_conditions[i].operator_) + { + case 15: // !empty + case 0: CP_XML_ATTR(L"operator", L"notEqual"); break; + case 14: // empty + case 1: CP_XML_ATTR(L"operator", L"equal"); break; + case 2: CP_XML_ATTR(L"operator", L"LessThan"); break; + case 3: CP_XML_ATTR(L"operator", L"greaterThan"); break; + case 13: // bottom values + case 4: CP_XML_ATTR(L"operator", L"lessThanOrEqual"); break; + case 17: // top values + case 5: CP_XML_ATTR(L"operator", L"greaterThanOrEqual"); break; + } + CP_XML_ATTR(L"val", filter_conditions[i].value); + } + } + } + } + else if (1 == filter_conditions.size()) + { + if (filter_conditions[0].type == 3/*odf_types::table_data_type::background_color*/ || + filter_conditions[0].type == 4/*odf_types::table_data_type::text_color*/) + { + CP_XML_NODE(L"colorFilter") + { + if (filter_conditions[0].type == 3) + CP_XML_ATTR(L"cellColor", L"1"); + CP_XML_ATTR(L"dxfId", filter_conditions[0].value); + } + } + else if (filter_conditions[0].operator_ == 17/*odf_types::table_operator::TopValues*/) + { + CP_XML_NODE(L"top10") + { + CP_XML_ATTR(L"val", filter_conditions[0].value); + } + } + } + } + } +} //------------------------------------------------------------------------------------------------------------------------- xlsx_table_state::xlsx_table_state(xlsx_conversion_context * Context, std::wstring styleName, std::wstring tableName, int tableId) diff --git a/OdfFile/Reader/Converter/xlsx_table_state.h b/OdfFile/Reader/Converter/xlsx_table_state.h index 18ed314f1b..69f48a37b4 100644 --- a/OdfFile/Reader/Converter/xlsx_table_state.h +++ b/OdfFile/Reader/Converter/xlsx_table_state.h @@ -56,8 +56,15 @@ typedef _CP_PTR(xlsx_data_range) xlsx_data_range_ptr; class xlsx_data_range { + struct filter_condition + { + int field_number = 0; + int type = 0; + std::wstring value; + int operator_ = 0; + }; public: - xlsx_data_range() : byRow(true), filter(false), bTablePart(true), withHeader(false), cell_start(0,0), cell_end(0,0) {} + xlsx_data_range() : byRow(true), filter_button(false), bTablePart(true), withHeader(false), cell_start(0,0), cell_end(0,0) {} std::wstring table_name; std::wstring name; @@ -67,16 +74,20 @@ public: std::pair cell_start; std::pair cell_end; - bool bTablePart; - bool byRow; - bool filter; - bool withHeader; + bool bTablePart = true; + bool byRow = true; + bool filter_button = false; + bool withHeader = false; std::vector> bySort; //field + order - void serialize_sort (std::wostream & _Wostream); - void serialize_autofilter (std::wostream & _Wostream); + _CP_OPT(bool) bFilterAndOr; + std::vector filter_conditions; + void serialize_sort (std::wostream & _Wostream); + void serialize_autofilter (std::wostream & _Wostream); + void serialize_filterColumn(std::wostream& _Wostream, int indexCol); + std::vector header_values; void set_header(size_t row, size_t col1, size_t col2) diff --git a/OdfFile/Reader/Converter/xlsx_tablecontext.cpp b/OdfFile/Reader/Converter/xlsx_tablecontext.cpp index 0920ea7e94..3abda5bcd7 100644 --- a/OdfFile/Reader/Converter/xlsx_tablecontext.cpp +++ b/OdfFile/Reader/Converter/xlsx_tablecontext.cpp @@ -49,563 +49,588 @@ namespace cpdoccore { namespace oox { -//----------------------------------------------------------------------------------------------------------------------- + //----------------------------------------------------------------------------------------------------------------------- -xlsx_table_state_ptr xlsx_table_context::state() -{ - if (!xlsx_table_states_.empty()) - return xlsx_table_states_.back(); - else - return xlsx_table_state_ptr(); -} - -bool xlsx_table_context::start_database_range(const std::wstring & name, const std::wstring & ref, bool bNamedRangeOnly) -{ - formulasconvert::odf2oox_converter convert; - std::wstring oox_ref = convert.convert_named_ref(ref); - - std::wstring ref1, ref2; - size_t pos = oox_ref.find(L":"); - - std::wstring xlsx_table_name; - - if (pos != std::wstring::npos) + xlsx_table_state_ptr xlsx_table_context::state() { - ref1 = oox_ref.substr(0, pos ); - ref2 = oox_ref.substr(pos + 1); - - pos = ref1.find(L"!"); - if (pos > 0) - { - xlsx_table_name = ref1.substr(0, pos); - ref1 = ref1.substr(pos + 1); - } - - pos = ref2.find(L"!"); - if (pos > 0) ref2 = ref2.substr(pos + 1); - - size_t col1, col2, row1, row2; - - XmlUtils::replace_all( xlsx_table_name, L"'", L""); - - bool res1 = getCellAddressInv(ref1, col1, row1); - bool res2 = getCellAddressInv(ref2, col2, row2); - - if (!res1) - return false; - - if (!res2) - { - ref2 = ref1; col2 = col1; row2 = row1; - } - - xlsx_data_ranges_.push_back(xlsx_data_range_ptr(new xlsx_data_range())); - - if (/*name.find(L"__Anonymous_Sheet_DB__") != std::wstring::npos ||*/ col1 == col2 || bNamedRangeOnly) - {//check range in pivots - xlsx_data_ranges_.back()->bTablePart = false; - } - xlsx_data_ranges_.back()->name = name; - xlsx_data_ranges_.back()->table_name = xlsx_table_name; - xlsx_data_ranges_.back()->ref = ref1 + L":" + ref2; - xlsx_data_ranges_.back()->cell_start = std::pair(col1, row1); - xlsx_data_ranges_.back()->cell_end = std::pair(col2, row2); - - xlsx_data_ranges_.back()->set_header(row1, col1, col2); + if (!xlsx_table_states_.empty()) + return xlsx_table_states_.back(); + else + return xlsx_table_state_ptr(); } -//----------------------------------------------------------------------- - if (!xlsx_table_name.empty()) + + bool xlsx_table_context::start_database_range(const std::wstring& name, const std::wstring& ref, bool bNamedRangeOnly) { - if (xlsx_data_ranges_.back()->bTablePart) + formulasconvert::odf2oox_converter convert; + std::wstring oox_ref = convert.convert_named_ref(ref); + + std::wstring ref1, ref2; + size_t pos = oox_ref.find(L":"); + + std::wstring xlsx_table_name; + + if (pos != std::wstring::npos) { - std::pair::iterator, std::multimap::iterator> range = xlsx_data_ranges_map_.equal_range(xlsx_table_name); + ref1 = oox_ref.substr(0, pos); + ref2 = oox_ref.substr(pos + 1); - for (std::multimap::iterator it = range.first; it != range.second; ++it) + pos = ref1.find(L"!"); + if (pos > 0) { - if (xlsx_data_ranges_[it->second]->bTablePart) - { - if (std::wstring::npos != xlsx_data_ranges_[it->second]->name.find(L"__Anonymous_Sheet_DB__")) - xlsx_data_ranges_[it->second]->bTablePart = false; - else - xlsx_data_ranges_.back()->bTablePart = false; - break; - } - + xlsx_table_name = ref1.substr(0, pos); + ref1 = ref1.substr(pos + 1); } + + pos = ref2.find(L"!"); + if (pos > 0) ref2 = ref2.substr(pos + 1); + + size_t col1, col2, row1, row2; + + XmlUtils::replace_all(xlsx_table_name, L"'", L""); + + bool res1 = getCellAddressInv(ref1, col1, row1); + bool res2 = getCellAddressInv(ref2, col2, row2); + + if (!res1) + return false; + + if (!res2) + { + ref2 = ref1; col2 = col1; row2 = row1; + } + + xlsx_data_ranges_.push_back(xlsx_data_range_ptr(new xlsx_data_range())); + + if (/*name.find(L"__Anonymous_Sheet_DB__") != std::wstring::npos ||*/ col1 == col2 || bNamedRangeOnly) + {//check range in pivots + xlsx_data_ranges_.back()->bTablePart = false; + } + xlsx_data_ranges_.back()->name = name; + xlsx_data_ranges_.back()->table_name = xlsx_table_name; + xlsx_data_ranges_.back()->ref = ref1 + L":" + ref2; + xlsx_data_ranges_.back()->cell_start = std::pair(col1, row1); + xlsx_data_ranges_.back()->cell_end = std::pair(col2, row2); + + xlsx_data_ranges_.back()->set_header(row1, col1, col2); } //----------------------------------------------------------------------- - xlsx_data_ranges_map_.insert(std::pair (xlsx_table_name, xlsx_data_ranges_.size() - 1)); - } - return true; -} -void xlsx_table_context::set_database_orientation (bool val) -{ - if (xlsx_data_ranges_.empty()) return; - - xlsx_data_ranges_.back()->byRow = val; -} -void xlsx_table_context::set_database_header (bool val) -{ - if (xlsx_data_ranges_.empty()) return; - - xlsx_data_ranges_.back()->withHeader = val; -} -void xlsx_table_context::set_database_filter (bool val) -{ - if (xlsx_data_ranges_.empty()) return; - - xlsx_data_ranges_.back()->filter = val; -} -void xlsx_table_context::end_database_range() -{ - if (!xlsx_data_ranges_.back()->bTablePart && !xlsx_data_ranges_.back()->filter && !xlsx_data_ranges_.back()->table_name.empty()) - { - xlsx_conversion_context_->get_xlsx_defined_names().add(xlsx_data_ranges_.back()->name, - xlsx_data_ranges_.back()->table_name + L"!" + xlsx_data_ranges_.back()->ref, false, -1); - } -} - -void xlsx_table_context::set_database_range_value(int index, const std::wstring& value) -{ - if (index < 0 || index > (int)xlsx_data_ranges_.size()) return; - - size_t col = state()->current_column(); - size_t row = state()->current_row(); - - xlsx_data_ranges_[index]->set_header_value(col, row, value); -} -void xlsx_table_context::check_database_range_intersection(const std::wstring& table_name, const std::wstring& ref) -{ - std::wstring ref1, ref2; - size_t col_1, row_1, col_2, row_2; - - size_t pos = ref.find(L":"); - if (pos != std::wstring::npos) - { - ref1 = ref.substr(0, pos ); - ref2 = ref.substr(pos + 1); - } - if (false == getCellAddressInv(ref1, col_1, row_1) || - false == getCellAddressInv(ref2, col_2, row_2)) return; - - for (size_t i = 0; i < xlsx_data_ranges_.size(); i++) - { - if (xlsx_data_ranges_[i]->table_name != table_name) continue; - - //if ( xlsx_data_ranges_[i]->cell_start.second < row_2 || xlsx_data_ranges_[i]->cell_end.second > row_1 - // || xlsx_data_ranges_[i]->cell_end.first < col_1 || xlsx_data_ranges_[i]->cell_start.first > col_2 ) - - if (((col_1 <= xlsx_data_ranges_[i]->cell_start.first && xlsx_data_ranges_[i]->cell_start.first <= col_2) || - (xlsx_data_ranges_[i]->cell_start.first <= col_1 && col_1 <= xlsx_data_ranges_[i]->cell_end.first)) - && - (( row_1 <= xlsx_data_ranges_[i]->cell_start.second && xlsx_data_ranges_[i]->cell_start.second <= row_2) || - (xlsx_data_ranges_[i]->cell_start.second <= row_1 && row_1 <= xlsx_data_ranges_[i]->cell_end.second ))) + if (!xlsx_table_name.empty()) { - xlsx_data_ranges_[i]->bTablePart = false; - } - } -} -int xlsx_table_context::in_database_range() -{ - int col = state()->current_column(); - int row = state()->current_row(); - - for (size_t i = 0; i < xlsx_data_ranges_.size(); i++) - { - if (xlsx_data_ranges_[i]->table_name != state()->get_table_name()) continue; - - if (/*(xlsx_data_ranges_values_[i]->withHeader || xlsx_data_ranges_values_[i]->filter)&& */ - xlsx_data_ranges_[i]->in_header(col, row)) - { - return (int)i; - } - } - return -1; -} -void xlsx_table_context::add_database_sort(int field_number, int order) -{ - xlsx_data_ranges_.back()->bySort.push_back(std::pair(field_number, order == 1 ? false : true )); -} - - -xlsx_table_context:: -xlsx_table_context(xlsx_conversion_context * Context, xlsx_text_context & textContext): xlsx_conversion_context_(Context), -xlsx_text_context_(textContext) -{ -} - -void xlsx_table_context::start_table(const std::wstring & tableName, const std::wstring & tableStyleName, int id) -{ - xlsx_table_state_ptr state = boost::make_shared(xlsx_conversion_context_, tableStyleName, tableName, id); - xlsx_table_states_.push_back( state); -} -void xlsx_table_context::set_protection(bool val, const std::wstring &key, const std::wstring &algorithm) -{ - xlsx_table_states_.back()->set_protection(val, key, algorithm); -} -void xlsx_table_context::end_table() -{ - xlsx_conversion_context_->get_dataValidations_context().clear(); -} -void xlsx_table_context::start_cell(const std::wstring & formula, size_t columnsSpanned, size_t rowsSpanned) -{ - state()->start_cell(columnsSpanned, rowsSpanned); -} - -void xlsx_table_context::end_cell() -{ - state()->end_cell(); -} - -void xlsx_table_context::set_current_cell_style_id(unsigned int xfId) -{ - return state()->set_current_cell_style_id(xfId); -} - -int xlsx_table_context::get_current_cell_style_id() -{ - return state()->get_current_cell_style_id(); -} - -void xlsx_table_context::start_cell_content() -{ - xlsx_text_context_.start_cell_content(); -} - -int xlsx_table_context::end_cell_content(bool need_cache) -{ - return xlsx_text_context_.end_cell_content(need_cache); -} - -void xlsx_table_context::start_covered_cell() -{ - return state()->start_covered_cell(); -} - -void xlsx_table_context::end_covered_cell() -{ - return state()->end_covered_cell(); -} - -void xlsx_table_context::start_column(unsigned int repeated, const std::wstring & defaultCellStyleName) -{ - return state()->start_column(repeated, defaultCellStyleName); -} - -unsigned int xlsx_table_context::columns_count() -{ - return state()->columns_count(); -} - -void xlsx_table_context::set_header_page(_CP_OPT(double) val) -{ - state()->header_page = val; -} -_CP_OPT(double) xlsx_table_context::get_header_page() -{ - return state()->header_page; -} -void xlsx_table_context::set_footer_page(_CP_OPT(double) val) -{ - state()->footer_page = val; -} -_CP_OPT(double) xlsx_table_context::get_footer_page() -{ - return state()->footer_page; -} - -std::wstring xlsx_table_context::default_row_cell_style() -{ - return state()->default_row_cell_style(); -} - -std::wstring xlsx_table_context::default_column_cell_style() -{ - return state()->default_column_cell_style(); -} - -int xlsx_table_context::current_column() -{ - return state()->current_column(); -} - -int xlsx_table_context::current_row() -{ - return state()->current_row(); -} - - -void xlsx_table_context::serialize_sort(std::wostream & _Wostream) -{ - if (xlsx_data_ranges_.empty()) return; - - std::pair::iterator, std::multimap::iterator> range; - - range = xlsx_data_ranges_map_.equal_range(state()->tableName_); - - for (std::multimap::iterator it = range.first; it != range.second; ++it) - { - if (xlsx_data_ranges_[it->second]->bTablePart) continue; - - xlsx_data_ranges_[it->second]->serialize_sort(_Wostream); - } -} -void xlsx_table_context::serialize_tableParts(std::wostream & _Wostream, rels & Rels) -{ - if (xlsx_data_ranges_.empty()) return; - - std::pair::iterator, std::multimap::iterator> range; - - range = xlsx_data_ranges_map_.equal_range(state()->get_table_name()); - - for (std::multimap::iterator it = range.first; it != range.second; ++it) - { - if (false == xlsx_data_ranges_[it->second]->bTablePart) continue; - -// из за дебелизма мсофис которому ОБЯЗАТЕЛЬНО нужно прописывать имена колонок таблицы (и они должны быть еще -// прописаны и в самих данных таблицы !! - - while (xlsx_data_ranges_[it->second]->header_values.size() > xlsx_data_ranges_[it->second]->cell_end.first - - xlsx_data_ranges_[it->second]->cell_start.first + 1) - { - xlsx_data_ranges_[it->second]->header_values.pop_back(); - } - int i = xlsx_data_ranges_[it->second]->header_values.size() - 1; - for (; i >= 0; i--) - { - if (false == xlsx_data_ranges_[it->second]->header_values[i].empty()) + if (xlsx_data_ranges_.back()->bTablePart) { - break; - } - } + std::pair::iterator, std::multimap::iterator> range = xlsx_data_ranges_map_.equal_range(xlsx_table_name); - if (i == -1) - { - xlsx_data_ranges_[it->second]->bTablePart = false; - continue; - } - else - { - size_t erase = xlsx_data_ranges_[it->second]->header_values.size() - 1 - i; - if (erase > 0) - { - xlsx_data_ranges_[it->second]->header_values.erase(xlsx_data_ranges_[it->second]->header_values.begin() + i + 1, xlsx_data_ranges_[it->second]->header_values.end()); - xlsx_data_ranges_[it->second]->cell_end.first -= erase; - - std::wstring ref1 = getCellAddress(xlsx_data_ranges_[it->second]->cell_start.first, xlsx_data_ranges_[it->second]->cell_start.second); - std::wstring ref2 = getCellAddress(xlsx_data_ranges_[it->second]->cell_end.first, xlsx_data_ranges_[it->second]->cell_end.second); - - xlsx_data_ranges_[it->second]->ref = ref1 + L":" + ref2; - } - } - //-------------------------------------------------------- - - size_t id = xlsx_conversion_context_->get_table_parts_size() + 1; - - std::wstring rId = L"tprtId" + std::to_wstring(id); - std::wstring ref = L"../tables/table" + std::to_wstring(id) + L".xml"; - - CP_XML_WRITER(_Wostream) - { - CP_XML_NODE(L"tablePart") - { - CP_XML_ATTR(L"r:id", rId); - } - } - Rels.add( relationship(rId, L"http://schemas.openxmlformats.org/officeDocument/2006/relationships/table", ref)); -//-------------------------------------------------------- - std::wstringstream strm; - CP_XML_WRITER(strm) - { - CP_XML_NODE(L"table") - { - CP_XML_ATTR(L"xmlns", L"http://schemas.openxmlformats.org/spreadsheetml/2006/main"); - - CP_XML_ATTR(L"id", id); - CP_XML_ATTR(L"name", xlsx_data_ranges_[it->second]->name); - CP_XML_ATTR(L"displayName", xlsx_data_ranges_[it->second]->name); - CP_XML_ATTR(L"ref", xlsx_data_ranges_[it->second]->ref); - - if (xlsx_data_ranges_[it->second]->withHeader == false && - xlsx_data_ranges_[it->second]->filter == false) - CP_XML_ATTR(L"headerRowCount", 0); - - //CP_XML_ATTR(L"totalsRowCount", 0); - CP_XML_ATTR(L"totalsRowShown", 0); - - xlsx_data_ranges_[it->second]->serialize_autofilter(CP_XML_STREAM()); - xlsx_data_ranges_[it->second]->serialize_sort(CP_XML_STREAM()); - - CP_XML_NODE(L"tableColumns") + for (std::multimap::iterator it = range.first; it != range.second; ++it) { - CP_XML_ATTR(L"count", xlsx_data_ranges_[it->second]->cell_end.first - - xlsx_data_ranges_[it->second]->cell_start.first + 1); - - for (int id = 0, i = xlsx_data_ranges_[it->second]->cell_start.first; i <= xlsx_data_ranges_[it->second]->cell_end.first; i++, id++) + if (xlsx_data_ranges_[it->second]->bTablePart) { - CP_XML_NODE(L"tableColumn") + if (std::wstring::npos != xlsx_data_ranges_[it->second]->name.find(L"__Anonymous_Sheet_DB__")) + xlsx_data_ranges_[it->second]->bTablePart = false; + else + xlsx_data_ranges_.back()->bTablePart = false; + break; + } + + } + } + //----------------------------------------------------------------------- + xlsx_data_ranges_map_.insert(std::pair(xlsx_table_name, xlsx_data_ranges_.size() - 1)); + } + return true; + } + void xlsx_table_context::set_database_orientation(bool val) + { + if (xlsx_data_ranges_.empty()) return; + + xlsx_data_ranges_.back()->byRow = val; + } + void xlsx_table_context::set_database_header(bool val) + { + if (xlsx_data_ranges_.empty()) return; + + xlsx_data_ranges_.back()->withHeader = val; + } + void xlsx_table_context::set_database_filter_button(bool val) + { + if (xlsx_data_ranges_.empty()) return; + + xlsx_data_ranges_.back()->filter_button = val; + } + void xlsx_table_context::end_database_range() + { + if (!xlsx_data_ranges_.back()->bTablePart && !xlsx_data_ranges_.back()->filter_button && !xlsx_data_ranges_.back()->table_name.empty()) + { + xlsx_conversion_context_->get_xlsx_defined_names().add(xlsx_data_ranges_.back()->name, + xlsx_data_ranges_.back()->table_name + L"!" + xlsx_data_ranges_.back()->ref, false, -1); + } + } + + void xlsx_table_context::set_database_range_value(int index, const std::wstring& value) + { + if (index < 0 || index >(int)xlsx_data_ranges_.size()) return; + + size_t col = state()->current_column(); + size_t row = state()->current_row(); + + xlsx_data_ranges_[index]->set_header_value(col, row, value); + } + void xlsx_table_context::check_database_range_intersection(const std::wstring& table_name, const std::wstring& ref) + { + std::wstring ref1, ref2; + size_t col_1, row_1, col_2, row_2; + + size_t pos = ref.find(L":"); + if (pos != std::wstring::npos) + { + ref1 = ref.substr(0, pos); + ref2 = ref.substr(pos + 1); + } + if (false == getCellAddressInv(ref1, col_1, row_1) || + false == getCellAddressInv(ref2, col_2, row_2)) return; + + for (size_t i = 0; i < xlsx_data_ranges_.size(); i++) + { + if (xlsx_data_ranges_[i]->table_name != table_name) continue; + + //if ( xlsx_data_ranges_[i]->cell_start.second < row_2 || xlsx_data_ranges_[i]->cell_end.second > row_1 + // || xlsx_data_ranges_[i]->cell_end.first < col_1 || xlsx_data_ranges_[i]->cell_start.first > col_2 ) + + if (((col_1 <= xlsx_data_ranges_[i]->cell_start.first && xlsx_data_ranges_[i]->cell_start.first <= col_2) || + (xlsx_data_ranges_[i]->cell_start.first <= col_1 && col_1 <= xlsx_data_ranges_[i]->cell_end.first)) + && + ((row_1 <= xlsx_data_ranges_[i]->cell_start.second && xlsx_data_ranges_[i]->cell_start.second <= row_2) || + (xlsx_data_ranges_[i]->cell_start.second <= row_1 && row_1 <= xlsx_data_ranges_[i]->cell_end.second))) + { + xlsx_data_ranges_[i]->bTablePart = false; + } + } + } + int xlsx_table_context::in_database_range() + { + int col = state()->current_column(); + int row = state()->current_row(); + + for (size_t i = 0; i < xlsx_data_ranges_.size(); i++) + { + if (xlsx_data_ranges_[i]->table_name != state()->get_table_name()) continue; + + if (/*(xlsx_data_ranges_values_[i]->withHeader || xlsx_data_ranges_values_[i]->filter)&& */ + xlsx_data_ranges_[i]->in_header(col, row)) + { + return (int)i; + } + } + return -1; + } + void xlsx_table_context::add_database_filter_conditional(int field_number, int type, const std::wstring& value, int operator_) + { + xlsx_data_ranges_.back()->filter_conditions.emplace_back(); + xlsx_data_ranges_.back()->filter_conditions.back().field_number = field_number; + xlsx_data_ranges_.back()->filter_conditions.back().type = type; + xlsx_data_ranges_.back()->filter_conditions.back().value = value; + xlsx_data_ranges_.back()->filter_conditions.back().operator_ = operator_; + } + void xlsx_table_context::start_filters_or() + { + xlsx_data_ranges_.back()->bFilterAndOr = true; + } + void xlsx_table_context::start_filters_and() + { + xlsx_data_ranges_.back()->bFilterAndOr = false; + } + void xlsx_table_context::end_filters_or() + { + + } + void xlsx_table_context::end_filters_and() + { + + } + void xlsx_table_context::add_database_sort(int field_number, int order, int type) + { + xlsx_data_ranges_.back()->bySort.push_back(std::pair(field_number, order == 1 ? false : true)); + } + xlsx_table_context::xlsx_table_context(xlsx_conversion_context* Context, xlsx_text_context& textContext) : + xlsx_conversion_context_(Context), xlsx_text_context_(textContext) + { + } + void xlsx_table_context::start_table(const std::wstring& tableName, const std::wstring& tableStyleName, int id) + { + xlsx_table_state_ptr state = boost::make_shared(xlsx_conversion_context_, tableStyleName, tableName, id); + xlsx_table_states_.push_back(state); + } + void xlsx_table_context::set_protection(bool val, const std::wstring& key, const std::wstring& algorithm) + { + xlsx_table_states_.back()->set_protection(val, key, algorithm); + } + void xlsx_table_context::end_table() + { + xlsx_conversion_context_->get_dataValidations_context().clear(); + } + void xlsx_table_context::start_cell(const std::wstring& formula, size_t columnsSpanned, size_t rowsSpanned) + { + state()->start_cell(columnsSpanned, rowsSpanned); + } + + void xlsx_table_context::end_cell() + { + state()->end_cell(); + } + + void xlsx_table_context::set_current_cell_style_id(unsigned int xfId) + { + return state()->set_current_cell_style_id(xfId); + } + + int xlsx_table_context::get_current_cell_style_id() + { + return state()->get_current_cell_style_id(); + } + + void xlsx_table_context::start_cell_content() + { + xlsx_text_context_.start_cell_content(); + } + + int xlsx_table_context::end_cell_content(bool need_cache) + { + return xlsx_text_context_.end_cell_content(need_cache); + } + + void xlsx_table_context::start_covered_cell() + { + return state()->start_covered_cell(); + } + + void xlsx_table_context::end_covered_cell() + { + return state()->end_covered_cell(); + } + + void xlsx_table_context::start_column(unsigned int repeated, const std::wstring& defaultCellStyleName) + { + return state()->start_column(repeated, defaultCellStyleName); + } + + unsigned int xlsx_table_context::columns_count() + { + return state()->columns_count(); + } + + void xlsx_table_context::set_header_page(_CP_OPT(double) val) + { + state()->header_page = val; + } + _CP_OPT(double) xlsx_table_context::get_header_page() + { + return state()->header_page; + } + void xlsx_table_context::set_footer_page(_CP_OPT(double) val) + { + state()->footer_page = val; + } + _CP_OPT(double) xlsx_table_context::get_footer_page() + { + return state()->footer_page; + } + + std::wstring xlsx_table_context::default_row_cell_style() + { + return state()->default_row_cell_style(); + } + + std::wstring xlsx_table_context::default_column_cell_style() + { + return state()->default_column_cell_style(); + } + + int xlsx_table_context::current_column() + { + return state()->current_column(); + } + + int xlsx_table_context::current_row() + { + return state()->current_row(); + } + void xlsx_table_context::serialize_sort(std::wostream& _Wostream) + { + if (xlsx_data_ranges_.empty()) return; + + std::pair::iterator, std::multimap::iterator> range; + + range = xlsx_data_ranges_map_.equal_range(state()->tableName_); + + for (std::multimap::iterator it = range.first; it != range.second; ++it) + { + if (xlsx_data_ranges_[it->second]->bTablePart) continue; + + xlsx_data_ranges_[it->second]->serialize_sort(_Wostream); + } + } + void xlsx_table_context::serialize_tableParts(std::wostream& _Wostream, rels& Rels) + { + if (xlsx_data_ranges_.empty()) return; + + std::pair::iterator, std::multimap::iterator> range; + + range = xlsx_data_ranges_map_.equal_range(state()->get_table_name()); + + for (std::multimap::iterator it = range.first; it != range.second; ++it) + { + if (false == xlsx_data_ranges_[it->second]->bTablePart) continue; + + // из за дебелизма мсофис которому ОБЯЗАТЕЛЬНО нужно прописывать имена колонок таблицы (и они должны быть еще + // прописаны и в самих данных таблицы !! + + while (xlsx_data_ranges_[it->second]->header_values.size() > xlsx_data_ranges_[it->second]->cell_end.first - + xlsx_data_ranges_[it->second]->cell_start.first + 1) + { + xlsx_data_ranges_[it->second]->header_values.pop_back(); + } + int i = xlsx_data_ranges_[it->second]->header_values.size() - 1; + for (; i >= 0; i--) + { + if (false == xlsx_data_ranges_[it->second]->header_values[i].empty()) + { + break; + } + } + + if (i == -1) + { + xlsx_data_ranges_[it->second]->bTablePart = false; + continue; + } + else + { + size_t erase = xlsx_data_ranges_[it->second]->header_values.size() - 1 - i; + if (erase > 0) + { + xlsx_data_ranges_[it->second]->header_values.erase(xlsx_data_ranges_[it->second]->header_values.begin() + i + 1, xlsx_data_ranges_[it->second]->header_values.end()); + xlsx_data_ranges_[it->second]->cell_end.first -= erase; + + std::wstring ref1 = getCellAddress(xlsx_data_ranges_[it->second]->cell_start.first, xlsx_data_ranges_[it->second]->cell_start.second); + std::wstring ref2 = getCellAddress(xlsx_data_ranges_[it->second]->cell_end.first, xlsx_data_ranges_[it->second]->cell_end.second); + + xlsx_data_ranges_[it->second]->ref = ref1 + L":" + ref2; + } + } + //-------------------------------------------------------- + + size_t id = xlsx_conversion_context_->get_table_parts_size() + 1; + + std::wstring rId = L"tprtId" + std::to_wstring(id); + std::wstring ref = L"../tables/table" + std::to_wstring(id) + L".xml"; + + CP_XML_WRITER(_Wostream) + { + CP_XML_NODE(L"tablePart") + { + CP_XML_ATTR(L"r:id", rId); + } + } + Rels.add(relationship(rId, L"http://schemas.openxmlformats.org/officeDocument/2006/relationships/table", ref)); + //-------------------------------------------------------- + std::wstringstream strm; + CP_XML_WRITER(strm) + { + CP_XML_NODE(L"table") + { + CP_XML_ATTR(L"xmlns", L"http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + + CP_XML_ATTR(L"id", id); + CP_XML_ATTR(L"name", xlsx_data_ranges_[it->second]->name); + CP_XML_ATTR(L"displayName", xlsx_data_ranges_[it->second]->name); + CP_XML_ATTR(L"ref", xlsx_data_ranges_[it->second]->ref); + + if (xlsx_data_ranges_[it->second]->withHeader == false && + xlsx_data_ranges_[it->second]->filter_button == false) + CP_XML_ATTR(L"headerRowCount", 0); + + //CP_XML_ATTR(L"totalsRowCount", 0); + CP_XML_ATTR(L"totalsRowShown", 0); + + xlsx_data_ranges_[it->second]->serialize_autofilter(CP_XML_STREAM()); + xlsx_data_ranges_[it->second]->serialize_sort(CP_XML_STREAM()); + + CP_XML_NODE(L"tableColumns") + { + CP_XML_ATTR(L"count", xlsx_data_ranges_[it->second]->cell_end.first - + xlsx_data_ranges_[it->second]->cell_start.first + 1); + + for (int id = 0, i = xlsx_data_ranges_[it->second]->cell_start.first; i <= xlsx_data_ranges_[it->second]->cell_end.first; i++, id++) { - std::wstring column_name = xlsx_data_ranges_[it->second]->header_values[id]; - if (column_name.empty()) + CP_XML_NODE(L"tableColumn") { - column_name = L"Column_" + std::to_wstring(id + 1); + std::wstring column_name = xlsx_data_ranges_[it->second]->header_values[id]; + if (column_name.empty()) + { + column_name = L"Column_" + std::to_wstring(id + 1); + } + CP_XML_ATTR(L"id", id + 1); + CP_XML_ATTR(L"name", column_name); } - CP_XML_ATTR(L"id", id + 1); - CP_XML_ATTR(L"name", column_name); } } - } - CP_XML_NODE(L"tableStyleInfo") - { - CP_XML_ATTR(L"showFirstColumn", 0); - CP_XML_ATTR(L"showLastColumn", 0); - CP_XML_ATTR(L"showRowStripes", 1); - CP_XML_ATTR(L"showColumnStripes", 0); + CP_XML_NODE(L"tableStyleInfo") + { + CP_XML_ATTR(L"showFirstColumn", 0); + CP_XML_ATTR(L"showLastColumn", 0); + CP_XML_ATTR(L"showRowStripes", 1); + CP_XML_ATTR(L"showColumnStripes", 0); + } } } + xlsx_conversion_context_->add_table_part(strm.str()); } - xlsx_conversion_context_->add_table_part(strm.str()); } -} -void xlsx_table_context::serialize_autofilter(std::wostream & _Wostream) -{ - if (xlsx_data_ranges_.empty()) return; - - std::wstring ref; - - std::pair cell_start (-1, -1); - std::pair cell_end (-1, -1); - - std::pair::iterator, std::multimap::iterator> range; - - range = xlsx_data_ranges_map_.equal_range(state()->tableName_); - - for (std::multimap::iterator it = range.first; it != range.second; ++it) + void xlsx_table_context::serialize_autofilter(std::wostream& _Wostream) { - if (xlsx_data_ranges_[it->second]->bTablePart) continue; - if (!xlsx_data_ranges_[it->second]->filter) continue; + if (xlsx_data_ranges_.empty()) return; - if (cell_start.first < 0 || xlsx_data_ranges_[it->second]->cell_start.first < cell_start.first ) - cell_start.first = xlsx_data_ranges_[it->second]->cell_start.first; + std::wstring ref; - if (cell_start.second < 0 || xlsx_data_ranges_[it->second]->cell_start.second < cell_start.second) - cell_start.second = xlsx_data_ranges_[it->second]->cell_start.second; + std::pair cell_start(-1, -1); + std::pair cell_end(-1, -1); - if (cell_end.first < 0 || xlsx_data_ranges_[it->second]->cell_end.first > cell_end.first) - cell_end.first = xlsx_data_ranges_[it->second]->cell_end.first; + std::pair::iterator, std::multimap::iterator> range; - if (cell_end.second < 0 || xlsx_data_ranges_[it->second]->cell_end.second > cell_end.second) - cell_end.second = xlsx_data_ranges_[it->second]->cell_end.second; + range = xlsx_data_ranges_map_.equal_range(state()->tableName_); - ref = xlsx_data_ranges_[it->second]->ref + L";"; - } - if (cell_end.first < 0 || cell_start.first < 0) return; + int ind_filter = -1; - ref.erase(ref.size() - 1, 1); - - CP_XML_WRITER(_Wostream) - { - CP_XML_NODE(L"autoFilter") + for (std::multimap::iterator it = range.first; it != range.second; ++it) { - //в автофильтре тока простые диапазоны .. для сложных - tablePart - CP_XML_ATTR(L"ref", getCellAddress(cell_start.first, cell_start.second) + L":" + getCellAddress(cell_end.first, cell_end.second)); - //CP_XML_ATTR(L"ref", ref); + if (xlsx_data_ranges_[it->second]->bTablePart) continue; + if (!xlsx_data_ranges_[it->second]->filter_button && xlsx_data_ranges_[it->second]->filter_conditions.empty()) continue; + + if (cell_start.first < 0 || xlsx_data_ranges_[it->second]->cell_start.first < cell_start.first) + cell_start.first = xlsx_data_ranges_[it->second]->cell_start.first; + + if (cell_start.second < 0 || xlsx_data_ranges_[it->second]->cell_start.second < cell_start.second) + cell_start.second = xlsx_data_ranges_[it->second]->cell_start.second; + + if (cell_end.first < 0 || xlsx_data_ranges_[it->second]->cell_end.first > cell_end.first) + cell_end.first = xlsx_data_ranges_[it->second]->cell_end.first; + + if (cell_end.second < 0 || xlsx_data_ranges_[it->second]->cell_end.second > cell_end.second) + cell_end.second = xlsx_data_ranges_[it->second]->cell_end.second; + + ref = xlsx_data_ranges_[it->second]->ref + L";"; + if (ind_filter < 0 && !xlsx_data_ranges_[it->second]->filter_conditions.empty()) + ind_filter = it->second; + + } + if (cell_end.first < 0 || cell_start.first < 0) return; + + ref.erase(ref.size() - 1, 1); + + CP_XML_WRITER(_Wostream) + { + CP_XML_NODE(L"autoFilter") + { + //в автофильтре тока простые диапазоны .. для сложных - tablePart + CP_XML_ATTR(L"ref", getCellAddress(cell_start.first, cell_start.second) + L":" + getCellAddress(cell_end.first, cell_end.second)); + //CP_XML_ATTR(L"ref", ref); + if (ind_filter != -1) + xlsx_data_ranges_[ind_filter]->serialize_filterColumn(CP_XML_STREAM(), 0); + } } } -} -void xlsx_table_context::serialize_protection(std::wostream & _Wostream) -{ - return state()->serialize_protection(_Wostream); -} -void xlsx_table_context::serialize_conditionalFormatting(std::wostream & _Wostream) -{ - return state()->serialize_conditionalFormatting(_Wostream); -} -void xlsx_table_context::serialize_merge_cells(std::wostream & _Wostream) -{ - return state()->serialize_merge_cells(_Wostream); -} -void xlsx_table_context::serialize_table_format(std::wostream & _Wostream) -{ - return state()->serialize_table_format(_Wostream); -} -void xlsx_table_context::serialize_page_properties(std::wostream & _Wostream) -{ - return state()->serialize_page_properties(_Wostream); -} -void xlsx_table_context::serialize_header_footer(std::wostream & _Wostream) -{ - return state()->serialize_header_footer(_Wostream); -} -void xlsx_table_context::serialize_background(std::wostream & _Wostream) -{ - return state()->serialize_background(_Wostream); -} -void xlsx_table_context::serialize_data_validation(std::wostream & _Wostream) -{ - return xlsx_conversion_context_->get_dataValidations_context().serialize(_Wostream); -} -void xlsx_table_context::serialize_data_validation_x14(std::wostream & _Wostream) -{ - return xlsx_conversion_context_->get_dataValidations_context().serialize_x14(_Wostream); -} -void xlsx_table_context::serialize_hyperlinks(std::wostream & _Wostream) -{ - return state()->serialize_hyperlinks(_Wostream); -} -void xlsx_table_context::serialize_ole_objects(std::wostream & _Wostream) -{ - return state()->serialize_ole_objects(_Wostream); -} -void xlsx_table_context::serialize_controls(std::wostream & _Wostream) -{ - return state()->serialize_controls(_Wostream); -} -void xlsx_table_context::serialize_breaks(std::wostream & _Wostream) -{ - return state()->serialize_breaks(_Wostream); -} -void xlsx_table_context::dump_rels_hyperlinks(rels & Rels) -{ - return state()->dump_rels_hyperlinks(Rels); -} -void xlsx_table_context::dump_rels_ole_objects(rels & Rels) -{ - return state()->dump_rels_ole_objects(Rels); -} -xlsx_table_metrics & xlsx_table_context::get_table_metrics() -{ - return state()->get_table_metrics(); -} + void xlsx_table_context::serialize_protection(std::wostream& _Wostream) + { + return state()->serialize_protection(_Wostream); + } + void xlsx_table_context::serialize_conditionalFormatting(std::wostream& _Wostream) + { + return state()->serialize_conditionalFormatting(_Wostream); + } + void xlsx_table_context::serialize_merge_cells(std::wostream& _Wostream) + { + return state()->serialize_merge_cells(_Wostream); + } + void xlsx_table_context::serialize_table_format(std::wostream& _Wostream) + { + return state()->serialize_table_format(_Wostream); + } + void xlsx_table_context::serialize_page_properties(std::wostream& _Wostream) + { + return state()->serialize_page_properties(_Wostream); + } + void xlsx_table_context::serialize_header_footer(std::wostream& _Wostream) + { + return state()->serialize_header_footer(_Wostream); + } + void xlsx_table_context::serialize_background(std::wostream& _Wostream) + { + return state()->serialize_background(_Wostream); + } + void xlsx_table_context::serialize_data_validation(std::wostream& _Wostream) + { + return xlsx_conversion_context_->get_dataValidations_context().serialize(_Wostream); + } + void xlsx_table_context::serialize_data_validation_x14(std::wostream& _Wostream) + { + return xlsx_conversion_context_->get_dataValidations_context().serialize_x14(_Wostream); + } + void xlsx_table_context::serialize_hyperlinks(std::wostream& _Wostream) + { + return state()->serialize_hyperlinks(_Wostream); + } + void xlsx_table_context::serialize_ole_objects(std::wostream& _Wostream) + { + return state()->serialize_ole_objects(_Wostream); + } + void xlsx_table_context::serialize_controls(std::wostream& _Wostream) + { + return state()->serialize_controls(_Wostream); + } + void xlsx_table_context::serialize_breaks(std::wostream& _Wostream) + { + return state()->serialize_breaks(_Wostream); + } + void xlsx_table_context::dump_rels_hyperlinks(rels& Rels) + { + return state()->dump_rels_hyperlinks(Rels); + } + void xlsx_table_context::dump_rels_ole_objects(rels& Rels) + { + return state()->dump_rels_ole_objects(Rels); + } + xlsx_table_metrics& xlsx_table_context::get_table_metrics() + { + return state()->get_table_metrics(); + } -xlsx_drawing_context & xlsx_table_context::get_drawing_context() -{ - return state()->get_drawing_context(); -} + xlsx_drawing_context& xlsx_table_context::get_drawing_context() + { + return state()->get_drawing_context(); + } -xlsx_comments_context & xlsx_table_context::get_comments_context() -{ - return state()->get_comments_context(); -} -void xlsx_table_context::table_column_last_width(double w) -{ - return state()->table_column_last_width(w); -} + xlsx_comments_context& xlsx_table_context::get_comments_context() + { + return state()->get_comments_context(); + } + void xlsx_table_context::table_column_last_width(double w) + { + return state()->table_column_last_width(w); + } -double xlsx_table_context::table_column_last_width() -{ - return state()->table_column_last_width(); -} + double xlsx_table_context::table_column_last_width() + { + return state()->table_column_last_width(); + } -void xlsx_table_context::start_hyperlink() -{ - return state()->start_hyperlink(); -} + void xlsx_table_context::start_hyperlink() + { + return state()->start_hyperlink(); + } - std::wstring xlsx_table_context::end_hyperlink(std::wstring const & ref, std::wstring const & href, std::wstring const & display) -{ - return state()->end_hyperlink(ref, href, display); -} + std::wstring xlsx_table_context::end_hyperlink(std::wstring const& ref, std::wstring const& href, std::wstring const& display) + { + return state()->end_hyperlink(ref, href, display); + } } diff --git a/OdfFile/Reader/Converter/xlsx_tablecontext.h b/OdfFile/Reader/Converter/xlsx_tablecontext.h index 0a52ae929c..6c0c29d855 100644 --- a/OdfFile/Reader/Converter/xlsx_tablecontext.h +++ b/OdfFile/Reader/Converter/xlsx_tablecontext.h @@ -118,10 +118,15 @@ public: void dump_rels_ole_objects (rels & Rels); bool start_database_range(const std::wstring &table_name, const std::wstring &ref, bool bNamedRangeOnly); - void set_database_orientation (bool val); - void set_database_header (bool val); - void set_database_filter (bool val); - void add_database_sort (int field_number, int order); + void set_database_orientation (bool val); + void set_database_header (bool val); + void set_database_filter_button(bool val); + void add_database_filter_conditional(int field_number, int type, const std::wstring & value, int operator_); + void add_database_sort (int field_number, int order, int type); + void start_filters_or(); + void start_filters_and(); + void end_filters_or(); + void end_filters_and(); void end_database_range(); int in_database_range(); diff --git a/OdfFile/Reader/Converter/xlsxconversioncontext.cpp b/OdfFile/Reader/Converter/xlsxconversioncontext.cpp index 438fd3350c..eeae1278cd 100644 --- a/OdfFile/Reader/Converter/xlsxconversioncontext.cpp +++ b/OdfFile/Reader/Converter/xlsxconversioncontext.cpp @@ -724,6 +724,35 @@ int xlsx_conversion_context::get_current_cell_style_id() { return get_table_context().get_current_cell_style_id(); } +int xlsx_conversion_context::add_dxfId_style(const std::wstring& color, bool cellColor) +{ + int dxfId = -1; + odf_reader::style_instance* instStyle = + root()->odf_context().styleContainer().style_default_by_type(odf_types::style_family::TableCell); + + if (instStyle) + { + odf_reader::text_format_properties_ptr textFormats = calc_text_properties_content(instStyle); + odf_reader::graphic_format_properties_ptr graphicFormats = calc_graphic_properties_content(instStyle); + odf_reader::style_table_cell_properties_attlist cellFormats = calc_table_cell_properties(instStyle); + + odf_types::color odf_color(color); + if (cellColor) + { + cellFormats.common_background_color_attlist_.fo_background_color_ = odf_color; + } + else + { + if (!textFormats) + textFormats = odf_reader::text_format_properties_ptr(new odf_reader::text_format_properties()); + + textFormats->fo_color_ = odf_color; + } + + dxfId = get_style_manager().dxfId(textFormats, graphicFormats, &cellFormats); + } + return dxfId; +} int xlsx_conversion_context::get_dxfId_style(const std::wstring &style_name) { if (style_name.empty()) return -1; diff --git a/OdfFile/Reader/Converter/xlsxconversioncontext.h b/OdfFile/Reader/Converter/xlsxconversioncontext.h index e36ab636dd..5f92f5a73d 100644 --- a/OdfFile/Reader/Converter/xlsxconversioncontext.h +++ b/OdfFile/Reader/Converter/xlsxconversioncontext.h @@ -134,6 +134,7 @@ public: size_t get_default_cell_style() const { return default_style_; } int get_dxfId_style(const std::wstring &style_name); + int add_dxfId_style(const std::wstring& color, bool cellColor); //------------------------------------------------------------------------------------ void add_pivot_sheet_source (const std::wstring & sheet_name, int index_table_view); diff --git a/OdfFile/Reader/Format/table_database_ranges.cpp b/OdfFile/Reader/Format/table_database_ranges.cpp index c26594a442..9fe8696d68 100644 --- a/OdfFile/Reader/Format/table_database_ranges.cpp +++ b/OdfFile/Reader/Format/table_database_ranges.cpp @@ -105,7 +105,7 @@ void table_database_range::xlsx_convert(oox::xlsx_conversion_context & Context) if (Context.get_table_context().start_database_range(name, *table_target_range_address_, content_.empty())) { if (table_display_filter_buttons_) - Context.get_table_context().set_database_filter(table_display_filter_buttons_->get()); + Context.get_table_context().set_database_filter_button(table_display_filter_buttons_->get()); if (table_orientation_) Context.get_table_context().set_database_orientation(table_orientation_->get_type() == table_orientation::row ? true : false); @@ -142,13 +142,16 @@ void table_sort::xlsx_convert(oox::xlsx_conversion_context & Context) { for (size_t i = 0; i < content_.size(); i++) { - table_sort_by * sort_by = dynamic_cast(content_[i].get()); + table_sort_by *sort_by = dynamic_cast(content_[i].get()); + if (!sort_by) continue; int descending = 1; if ((sort_by->table_order_) && (sort_by->table_order_->get_type() == table_order::descending)) descending = 2; - Context.get_table_context().add_database_sort(sort_by->table_field_number_, descending); + int type = sort_by->table_data_type_ ? sort_by->table_data_type_->get_type() : 0; + + Context.get_table_context().add_database_sort(sort_by->table_field_number_, descending, type); } } //-------------------------------------------------------------------------------------------------- @@ -161,6 +164,10 @@ void table_sort_by::add_attributes(xml::attributes_wc_ptr const & Attributes) CP_APPLY_ATTR(L"table:data-type" , table_data_type_); CP_APPLY_ATTR(L"table:order" , table_order_); + if (!table_data_type_) + { + CP_APPLY_ATTR(L"loext:data-type", table_data_type_); + } } //-------------------------------------------------------------------------------------------------- const wchar_t * table_filter::ns = L"table"; @@ -197,10 +204,12 @@ void table_filter_or::add_child_element( xml::sax * Reader, const std::wstring & void table_filter_or::xlsx_convert(oox::xlsx_conversion_context & Context) { + Context.get_table_context().start_filters_or(); for (size_t i = 0; i < content_.size(); i++) { content_[i]->xlsx_convert(Context); } + Context.get_table_context().end_filters_or(); } //-------------------------------------------------------------------------------------------------- const wchar_t * table_filter_and::ns = L"table"; @@ -213,10 +222,12 @@ void table_filter_and::add_child_element( xml::sax * Reader, const std::wstring void table_filter_and::xlsx_convert(oox::xlsx_conversion_context & Context) { + Context.get_table_context().start_filters_and(); for (size_t i = 0; i < content_.size(); i++) { content_[i]->xlsx_convert(Context); } + Context.get_table_context().end_filters_and(); } //-------------------------------------------------------------------------------------------------- const wchar_t * table_filter_condition::ns = L"table"; @@ -229,6 +240,11 @@ void table_filter_condition::add_attributes(xml::attributes_wc_ptr const & Attri CP_APPLY_ATTR(L"table:field-number", table_field_number_); CP_APPLY_ATTR(L"table:operator", table_operator_); CP_APPLY_ATTR(L"table:value", table_value_); + + if (!table_data_type_) + { + CP_APPLY_ATTR(L"loext:data-type", table_data_type_); + } } void table_filter_condition::add_child_element( xml::sax * Reader, const std::wstring & Ns, const std::wstring & Name) @@ -238,10 +254,19 @@ void table_filter_condition::add_child_element( xml::sax * Reader, const std::ws void table_filter_condition::xlsx_convert(oox::xlsx_conversion_context & Context) { - for (size_t i = 0; i < content_.size(); i++) + int type = table_data_type_ ? table_data_type_->get_type() : 0; + int field_number = table_field_number_.get_value_or(0); + int operator_ = table_operator_ ? table_operator_->get_type() : 0; + + std::wstring value = table_value_.get_value_or(L""); + + if (type == odf_types::table_data_type::background_color || + type == odf_types::table_data_type::text_color) { - content_[i]->xlsx_convert(Context); + int dxfId = Context.add_dxfId_style(value, type == odf_types::table_data_type::background_color); + value = dxfId >= 0 ? std::to_wstring(dxfId) : L""; } + Context.get_table_context().add_database_filter_conditional(field_number, type, value, operator_); } //-------------------------------------------------------------------------------------------------- const wchar_t * table_filter_set_item::ns = L"table"; diff --git a/OdfFile/Reader/Format/table_database_ranges.h b/OdfFile/Reader/Format/table_database_ranges.h index acf4012690..ec3f651f86 100644 --- a/OdfFile/Reader/Format/table_database_ranges.h +++ b/OdfFile/Reader/Format/table_database_ranges.h @@ -39,6 +39,8 @@ #include "../../DataTypes/common_attlists.h" #include "../../DataTypes/tableorientation.h" #include "../../DataTypes/tableorder.h" +#include "../../DataTypes/tabledatatype.h" +#include "../../DataTypes/tableoperator.h" #include "../../Reader/Converter/xlsxconversioncontext.h" @@ -51,7 +53,7 @@ public: static const wchar_t * ns; static const wchar_t * name; static const xml::NodeType xml_type = xml::typeElement; - static const ElementType type = typeTableDatabaseRanges; + static const ElementType type = typeTableDatabaseRanges; CPDOCCORE_DEFINE_VISITABLE() @@ -61,9 +63,7 @@ public: virtual void xlsx_convert(oox::xlsx_conversion_context & Context); office_element_ptr_array content_; - }; - CP_REGISTER_OFFICE_ELEMENT2(table_database_ranges); //------------------------------------------------------------------------------------------------------------- @@ -73,7 +73,7 @@ public: static const wchar_t * ns; static const wchar_t * name; static const xml::NodeType xml_type = xml::typeElement; - static const ElementType type = typeTableDatabaseRange; + static const ElementType type = typeTableDatabaseRange; CPDOCCORE_DEFINE_VISITABLE() @@ -89,7 +89,7 @@ public: _CP_OPT(odf_types::table_orientation) table_orientation_; //table:refresh-delay - office_element_ptr_array content_; + office_element_ptr_array content_; //"table-database-source-sql" //"table-database-source-table" //"table-database-source-query" @@ -104,7 +104,7 @@ public: static const wchar_t * ns; static const wchar_t * name; static const xml::NodeType xml_type = xml::typeElement; - static const ElementType type = typeTableSort; + static const ElementType type = typeTableSort; CPDOCCORE_DEFINE_VISITABLE() @@ -130,16 +130,16 @@ public: static const wchar_t * ns; static const wchar_t * name; static const xml::NodeType xml_type = xml::typeElement; - static const ElementType type = typeTableSortBy; + static const ElementType type = typeTableSortBy; CPDOCCORE_DEFINE_VISITABLE() virtual void add_attributes ( const xml::attributes_wc_ptr & Attributes ); virtual void add_child_element ( xml::sax * Reader, const std::wstring & Ns, const std::wstring & Name){} - int table_field_number_; - _CP_OPT(std::wstring) table_data_type_; - _CP_OPT(odf_types::table_order) table_order_; + int table_field_number_; + _CP_OPT(odf_types::table_data_type) table_data_type_; + _CP_OPT(odf_types::table_order) table_order_; }; CP_REGISTER_OFFICE_ELEMENT2(table_sort_by); @@ -151,7 +151,7 @@ public: static const wchar_t * ns; static const wchar_t * name; static const xml::NodeType xml_type = xml::typeElement; - static const ElementType type = typeTableFilter; + static const ElementType type = typeTableFilter; CPDOCCORE_DEFINE_VISITABLE() @@ -176,7 +176,7 @@ public: static const wchar_t * ns; static const wchar_t * name; static const xml::NodeType xml_type = xml::typeElement; - static const ElementType type = typeTableFilterAnd; + static const ElementType type = typeTableFilterAnd; CPDOCCORE_DEFINE_VISITABLE() @@ -185,7 +185,7 @@ public: virtual void xlsx_convert(oox::xlsx_conversion_context & Context); - office_element_ptr_array content_; + office_element_ptr_array content_; }; CP_REGISTER_OFFICE_ELEMENT2(table_filter_and); //------------------------------------------------------------------------------------------------------------- @@ -196,7 +196,7 @@ public: static const wchar_t * ns; static const wchar_t * name; static const xml::NodeType xml_type = xml::typeElement; - static const ElementType type = typeTableFilterOr; + static const ElementType type = typeTableFilterOr; CPDOCCORE_DEFINE_VISITABLE() @@ -205,7 +205,7 @@ public: virtual void xlsx_convert(oox::xlsx_conversion_context & Context); - office_element_ptr_array content_; + office_element_ptr_array content_; }; CP_REGISTER_OFFICE_ELEMENT2(table_filter_or); //------------------------------------------------------------------------------------------------------------- @@ -216,7 +216,7 @@ public: static const wchar_t * ns; static const wchar_t * name; static const xml::NodeType xml_type = xml::typeElement; - static const ElementType type = typeTableFilterCondition; + static const ElementType type = typeTableFilterCondition; CPDOCCORE_DEFINE_VISITABLE() @@ -225,13 +225,13 @@ public: virtual void xlsx_convert(oox::xlsx_conversion_context & Context); - _CP_OPT(std::wstring) table_case_sensitive_; - _CP_OPT(std::wstring) table_data_type_; - _CP_OPT(unsigned int) table_field_number_; - _CP_OPT(std::wstring) table_operator_; - _CP_OPT(std::wstring) table_value_; + _CP_OPT(std::wstring) table_case_sensitive_; + _CP_OPT(odf_types::table_data_type) table_data_type_; + _CP_OPT(unsigned int) table_field_number_; + _CP_OPT(odf_types::table_operator) table_operator_; + _CP_OPT(std::wstring) table_value_; - office_element_ptr_array content_; + office_element_ptr_array content_; }; CP_REGISTER_OFFICE_ELEMENT2(table_filter_condition); //------------------------------------------------------------------------------------------------------------- @@ -242,7 +242,7 @@ public: static const wchar_t * ns; static const wchar_t * name; static const xml::NodeType xml_type = xml::typeElement; - static const ElementType type = typeTableFilterSetItem; + static const ElementType type = typeTableFilterSetItem; CPDOCCORE_DEFINE_VISITABLE() diff --git a/OdfFile/Reader/Format/table_xlsx.cpp b/OdfFile/Reader/Format/table_xlsx.cpp index e52d9f3950..316141fddf 100644 --- a/OdfFile/Reader/Format/table_xlsx.cpp +++ b/OdfFile/Reader/Format/table_xlsx.cpp @@ -165,6 +165,7 @@ void table_table_row::xlsx_convert(oox::xlsx_conversion_context & Context) int row_current = Context.current_table_row() + 1; bool hidden = attlist_.table_visibility_.get_type() == table_visibility::Collapse; + bool filter = attlist_.table_visibility_.get_type() == table_visibility::Filter; for (unsigned int i = 0; i < attlist_.table_number_rows_repeated_; ++i) { @@ -195,7 +196,7 @@ void table_table_row::xlsx_convert(oox::xlsx_conversion_context & Context) if (Context.get_table_context().state()->group_rows_.back()) hidden = false; } - if (hidden) + if (hidden || filter) { CP_XML_ATTR(L"hidden", 1); } @@ -527,7 +528,7 @@ void table_table_column::xlsx_convert(oox::xlsx_conversion_context & Context) size_t style_ = Context.get_style_manager().xfId(NULL,NULL, &cellFormatProperties, NULL, L"", 0, set_default); //if (set_default) - CP_XML_ATTR(L"style", style_ ); + // CP_XML_ATTR(L"style", style_ ); } } }