diff --git a/OOXML/Binary/Sheets/Reader/CellFormatController.cpp b/OOXML/Binary/Sheets/Reader/CellFormatController.cpp new file mode 100644 index 0000000000..bc90be547c --- /dev/null +++ b/OOXML/Binary/Sheets/Reader/CellFormatController.cpp @@ -0,0 +1,190 @@ +/* + * (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 "CellFormatController.h" + +#include "../../../XlsxFormat/Styles/NumFmts.h" +#include "../../../XlsxFormat/Styles/Xfs.h" + +CellFormatController::CellFormatController(OOX::Spreadsheet::CStyles *styles): + m_pStyles{styles} +{ + // Добавим стили для wrap-а + m_pStyles->m_oCellXfs.Init(); + m_pStyles->m_oCellXfs->m_oCount.Init(); + m_pStyles->m_oCellXfs->m_oCount->SetValue(2); + + // Normall default + OOX::Spreadsheet::CXfs* pXfs = NULL; + pXfs = new OOX::Spreadsheet::CXfs(); + pXfs->m_oBorderId.Init(); pXfs->m_oBorderId->SetValue(0); + pXfs->m_oFillId.Init(); pXfs->m_oFillId->SetValue(0); + pXfs->m_oFontId.Init(); pXfs->m_oFontId->SetValue(0); + pXfs->m_oNumFmtId.Init(); pXfs->m_oNumFmtId->SetValue(0); + + m_pStyles->m_oCellXfs->m_arrItems.push_back(pXfs); + + // Wrap style + pXfs = new OOX::Spreadsheet::CXfs(); + pXfs->m_oBorderId.Init(); pXfs->m_oBorderId->SetValue(0); + pXfs->m_oFillId.Init(); pXfs->m_oFillId->SetValue(0); + pXfs->m_oFontId.Init(); pXfs->m_oFontId->SetValue(0); + pXfs->m_oNumFmtId.Init(); pXfs->m_oNumFmtId->SetValue(0); + + pXfs->m_oApplyAlignment.Init(); pXfs->m_oApplyAlignment->SetValue(SimpleTypes::onoffTrue); + pXfs->m_oAligment.Init(); pXfs->m_oAligment->m_oWrapText.Init(); + pXfs->m_oAligment->m_oWrapText->SetValue(SimpleTypes::onoffTrue); + + m_pStyles->m_oCellXfs->m_arrItems.push_back(pXfs); +} + +void CellFormatController::ProcessCellType(OOX::Spreadsheet::CCell *pCell, const std::wstring &value, bool bIsWrap) +{ + size_t length = value.length(); + wchar_t *pEndPtr; + double dValue = wcstod(value.c_str(), &pEndPtr); + + if (std::isnan(dValue) || std::isinf(dValue)) + pEndPtr = (wchar_t *)value.c_str(); + + if ((0 == *pEndPtr) || (pEndPtr != value.c_str() && (value.c_str() + length - pEndPtr) < 3)) + { + std::wstring data_format; + std::wstring postfix; + + if (0 != *pEndPtr) + { + size_t sz = length - (pEndPtr - value.c_str()); + + while (sz > 0) + { + if (pEndPtr[sz - 1] != L' ') + break; + sz--; + } + + if (sz > 0) + { + postfix = std::wstring(pEndPtr, sz); + } + } + + size_t pos = value.find(L"."); + if (pos != std::wstring::npos) + { + size_t fraction = value.length() - pos - ((0 != *pEndPtr) ? 2 : 1); + for (size_t i = 0; i < fraction && fraction != std::wstring::npos; ++i) + data_format += L"0"; + } + if (false == data_format.empty()) data_format = L"." + data_format; + + pCell->m_oValue.Init(); + + if (0 != *pEndPtr) + { + if (false == postfix.empty()) + { + if (postfix[0] == L'%') + { + pCell->m_oValue->m_sText = std::to_wstring(dValue / 100.); + } + else + { + pCell->m_oValue->m_sText = value.substr(0, length - 1); + + for (size_t i = 0; i < postfix.size(); ++i) + { + data_format += std::wstring(L"\\") + postfix[i]; + } + } + } + } + else + { + pCell->m_oValue->m_sText = value; + } + if (false == data_format.empty()) + { + data_format = L"0" + data_format; + + std::map::iterator pFind = mapDataNumber.find(data_format); + if (pFind != mapDataNumber.end()) + { + pCell->m_oStyle = pFind->second; + } + else + { + if (!m_pStyles->m_oNumFmts.IsInit()) m_pStyles->m_oNumFmts.Init(); + + m_pStyles->m_oNumFmts->m_arrItems.push_back(new OOX::Spreadsheet::CNumFmt()); + m_pStyles->m_oNumFmts->m_arrItems.back()->m_oFormatCode = data_format; + m_pStyles->m_oNumFmts->m_arrItems.back()->m_oNumFmtId.Init(); + m_pStyles->m_oNumFmts->m_arrItems.back()->m_oNumFmtId->SetValue(164 + m_pStyles->m_oNumFmts->m_arrItems.size()); + + // Normal + data format + OOX::Spreadsheet::CXfs* pXfs = new OOX::Spreadsheet::CXfs(); + + pXfs->m_oBorderId.Init(); pXfs->m_oBorderId->SetValue(0); + pXfs->m_oFillId.Init(); pXfs->m_oFillId->SetValue(0); + pXfs->m_oFontId.Init(); pXfs->m_oFontId->SetValue(0); + pXfs->m_oNumFmtId.Init(); pXfs->m_oNumFmtId->SetValue(m_pStyles->m_oNumFmts->m_arrItems.back()->m_oNumFmtId->GetValue()); + + m_pStyles->m_oCellXfs->m_arrItems.push_back(pXfs); + + pCell->m_oStyle = (unsigned int)(m_pStyles->m_oCellXfs->m_arrItems.size() - 1); + mapDataNumber.insert(std::make_pair(data_format, *pCell->m_oStyle)); + } + } + + } + else + { + if (value[0] == L'='/* && bCalcFormulas*/) + { + pCell->m_oFormula.Init(); + pCell->m_oFormula->m_sText = value; + } + else + { + pCell->m_oType->SetValue(SimpleTypes::Spreadsheet::celltypeInlineStr); + pCell->m_oRichText.Init(); + OOX::Spreadsheet::CText *pText = new OOX::Spreadsheet::CText(); + pText->m_sText = value; + pCell->m_oRichText->m_arrItems.push_back(pText); + } + } + + if (bIsWrap) + { + pCell->m_oStyle = 1; + } +} \ No newline at end of file diff --git a/OOXML/Binary/Sheets/Reader/CellFormatController.h b/OOXML/Binary/Sheets/Reader/CellFormatController.h new file mode 100644 index 0000000000..2c6c1f123c --- /dev/null +++ b/OOXML/Binary/Sheets/Reader/CellFormatController.h @@ -0,0 +1,66 @@ +/* + * (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 "../../../Base/Base.h" +#include "../../../XlsxFormat/Worksheets/Worksheet.h" +#include "../../../XlsxFormat/Styles/Styles.h" + + +/// @brief класс определяющий и корректирующий тип данных, помещаемых в ячейки таблицы +class CellFormatController +{ + +public: + /// @brief конструктор + /// @param styles стили из таблицы + CellFormatController(OOX::Spreadsheet::CStyles *styles); + + /// @brief обрабатывает вставляемые в ячейку таблицы данные, переводя их в нужный тип, и заполняет ими ячейку + /// @param pCell указатель на ячейку + /// @param value вставляемые в ячейку данные в строковом типе + void ProcessCellType(OOX::Spreadsheet::CCell *pCell, const std::wstring &value, bool bIsWrap = false); + +private: + + void processDigitalType(); + + std::wstring *value; + + OOX::Spreadsheet::CCell *pCell; + + std::map mapDataNumber; + + OOX::Spreadsheet::CStyles *m_pStyles; + +}; diff --git a/OOXML/Binary/Sheets/Reader/XMLReader/XLSXTableController.cpp b/OOXML/Binary/Sheets/Reader/XMLReader/XLSXTableController.cpp index a1307350f0..33358eee34 100644 --- a/OOXML/Binary/Sheets/Reader/XMLReader/XLSXTableController.cpp +++ b/OOXML/Binary/Sheets/Reader/XMLReader/XLSXTableController.cpp @@ -42,8 +42,8 @@ constexpr auto SheetName = L"Sheet"; XLSXTableController::XLSXTableController(OOX::Spreadsheet::CXlsx &book) +: book_{&book} { - book_ = &book; book_->CreateWorkbook(); book_->m_pWorkbook->m_oSheets.Init(); tableRows_.push_back(nullptr); @@ -51,35 +51,7 @@ XLSXTableController::XLSXTableController(OOX::Spreadsheet::CXlsx &book) // Создадим стили book_->CreateStyles(); - // Добавим стили для wrap-а - book_->m_pStyles->m_oCellXfs.Init(); - book_->m_pStyles->m_oCellXfs->m_oCount.Init(); - book_->m_pStyles->m_oCellXfs->m_oCount->SetValue(2); - - m_pStyles_ = book_->m_pStyles; - -// Normall default - OOX::Spreadsheet::CXfs* pXfs = NULL; - pXfs = new OOX::Spreadsheet::CXfs(); - pXfs->m_oBorderId.Init(); pXfs->m_oBorderId->SetValue(0); - pXfs->m_oFillId.Init(); pXfs->m_oFillId->SetValue(0); - pXfs->m_oFontId.Init(); pXfs->m_oFontId->SetValue(0); - pXfs->m_oNumFmtId.Init(); pXfs->m_oNumFmtId->SetValue(0); - - book_->m_pStyles->m_oCellXfs->m_arrItems.push_back(pXfs); - -// Wrap style - pXfs = new OOX::Spreadsheet::CXfs(); - pXfs->m_oBorderId.Init(); pXfs->m_oBorderId->SetValue(0); - pXfs->m_oFillId.Init(); pXfs->m_oFillId->SetValue(0); - pXfs->m_oFontId.Init(); pXfs->m_oFontId->SetValue(0); - pXfs->m_oNumFmtId.Init(); pXfs->m_oNumFmtId->SetValue(0); - - pXfs->m_oApplyAlignment.Init(); pXfs->m_oApplyAlignment->SetValue(SimpleTypes::onoffTrue); - pXfs->m_oAligment.Init(); pXfs->m_oAligment->m_oWrapText.Init(); - pXfs->m_oAligment->m_oWrapText->SetValue(SimpleTypes::onoffTrue); - - book_->m_pStyles->m_oCellXfs->m_arrItems.push_back(pXfs); + formates_ = std::make_shared(book_->m_pStyles); } @@ -112,16 +84,10 @@ void XLSXTableController::AddCell(const std::wstring &sText, INT nRow, INT nCol) auto pCell = new OOX::Spreadsheet::CCell(); pCell->m_oType.Init(); - pCell->m_oType->SetValue(SimpleTypes::Spreadsheet::celltypeInlineStr); - pCell->m_oRichText.Init(); - OOX::Spreadsheet::CText *pText = new OOX::Spreadsheet::CText(); - pText->m_sText = sText; - pCell->m_oRichText->m_arrItems.push_back(pText); + formates_->ProcessCellType(pCell, sText); pCell->setRowCol(nRow - 1, nCol); - pCell->m_oStyle = 1; - while(tableRows_.size() - 1 < nRow) { tableRows_.push_back(new OOX::Spreadsheet::CRow); diff --git a/OOXML/Binary/Sheets/Reader/XMLReader/XLSXTableController.h b/OOXML/Binary/Sheets/Reader/XMLReader/XLSXTableController.h index bce27dbb59..8ec5de3d13 100644 --- a/OOXML/Binary/Sheets/Reader/XMLReader/XLSXTableController.h +++ b/OOXML/Binary/Sheets/Reader/XMLReader/XLSXTableController.h @@ -31,6 +31,8 @@ */ #pragma once +#include "../CellFormatController.h" + #include "../../../../Base/Base.h" #include "../../../../XlsxFormat/Worksheets/Worksheet.h" #include "../../../../XlsxFormat/Xlsx.h" @@ -69,7 +71,12 @@ private: /// @param pageNumber номер страницы void addPage(OOX::Spreadsheet::CWorksheet *page, INT pageNumber); + /// @brief документ xlsx OOX::Spreadsheet::CXlsx *book_; + + /// @brief вектор со строками таблицы std::vector tableRows_; - OOX::Spreadsheet::CStyles *m_pStyles_ = NULL; + + /// @brief контроллер форматов + std::shared_ptr formates_; }; \ No newline at end of file diff --git a/OOXML/Projects/Linux/BinDocument/BinDocument.pro b/OOXML/Projects/Linux/BinDocument/BinDocument.pro index 881744f48a..ba8cd7619a 100644 --- a/OOXML/Projects/Linux/BinDocument/BinDocument.pro +++ b/OOXML/Projects/Linux/BinDocument/BinDocument.pro @@ -66,7 +66,8 @@ SOURCES += \ ../../../Binary/Sheets/Reader/XMLReader/columnNameController.cpp \ ../../../Binary/Sheets/Reader/XMLReader/XMLConverter2.cpp \ ../../../Binary/Sheets/Reader/XMLReader/XMLMap.cpp \ - ../../../Binary/Sheets/Reader/XMLReader/XMLReader2.cpp + ../../../Binary/Sheets/Reader/XMLReader/XMLReader2.cpp \ + ../../../Binary/Sheets/Reader/CellFormatController.cpp HEADERS += \ ../../../Binary/Document/DocWrapper/DocxSerializer.h \ @@ -109,4 +110,5 @@ HEADERS += \ ../../../Binary/Sheets/Reader/XMLReader/XLSXTableController.h \ ../../../Binary/Sheets/Reader/XMLReader/columnNameController.h \ ../../../Binary/Sheets/Reader/XMLReader/XMLConverter2.h \ - ../../../Binary/Sheets/Reader/XMLReader/XMLMap.h + ../../../Binary/Sheets/Reader/XMLReader/XMLMap.h \ + ../../../Binary/Sheets/Reader/CellFormatController.h