/* * (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 #include "ChartSerializer.h" #include "../../../XlsxFormat/Chart/ChartSerialize.h" #include "../../../XlsxFormat/Xlsx.h" #include "../../../XlsxFormat/Workbook/Workbook.h" #include "../../../XlsxFormat/SharedStrings/SharedStrings.h" #include "../../../XlsxFormat/Styles/Styles.h" #include "../../../XlsxFormat/Styles/Xfs.h" #include "../../../XlsxFormat/Styles/NumFmts.h" #include "../../../XlsxFormat/Styles/dxf.h" #include "../../../XlsxFormat/Styles/Borders.h" #include "../../../XlsxFormat/Worksheets/Worksheet.h" #define NUMID_START 160 const wchar_t* gc_Cat = L"cat"; const wchar_t* gc_Val = L"val"; const wchar_t* gc_XVal = L"xVal"; const wchar_t* gc_YVal = L"yVal"; const wchar_t* gc_BubbleSize = L"bubbleSize"; #define PARSE_CT_CHART(chart, type) \ {\ for(size_t i = 0; i < chart->m_ser.size();++i)\ {\ type* ser = chart->m_ser[i];\ PARSE_TITLE(ser, true, NULL);\ parseAxDataSource(ser->m_cat, true, gc_Cat);\ parseNumDataSource(ser->m_val, true, gc_Val);\ }\ } #define PARSE_CT_CHART_SCATTER(chart, type) \ {\ for(size_t i = 0; i < chart->m_ser.size();++i)\ {\ type* ser = chart->m_ser[i];\ PARSE_TITLE(ser, true, NULL);\ parseAxDataSource(ser->m_xVal, true, gc_XVal);\ parseNumDataSource(ser->m_yVal, true, gc_YVal);\ }\ } #define PARSE_TRENDLINE(chart, type) \ {\ for(size_t i = 0; i < chart->m_ser.size();++i)\ {\ type* ser = chart->m_ser[i];\ for(size_t j = 0; j < ser->m_trendline.size(); ++j)\ {\ OOX::Spreadsheet::CT_Trendline* pTrendline = ser->m_trendline[j];\ if(NULL != pTrendline->m_trendlineLbl)\ {\ PARSE_TITLE(pTrendline->m_trendlineLbl, false, NULL);\ }\ }\ }\ } #define PARSE_ERRBARS(chart, type) \ {\ for(size_t i = 0; i < chart->m_ser.size();++i)\ {\ type* ser = chart->m_ser[i];\ for(size_t j = 0; j < ser->m_errBars.size(); ++j)\ {\ OOX::Spreadsheet::CT_ErrBars* pErrBars = ser->m_errBars[j];\ parseNumDataSource(pErrBars->m_minus, false, NULL);\ parseNumDataSource(pErrBars->m_plus, false, NULL);\ }\ }\ } #define PARSE_BUBBLE_SIZE(chart, type) \ {\ for(size_t i = 0; i < chart->m_ser.size();++i)\ {\ type* ser = chart->m_ser[i];\ parseNumDataSource(ser->m_bubbleSize, true, gc_BubbleSize);\ }\ } #define PARSE_TITLE(pTitle, bUpdateRange, cRangeName)\ {\ if(NULL != pTitle && NULL != pTitle->m_tx)\ {\ parseStrRef(pTitle->m_tx->m_strRef, bUpdateRange, cRangeName);\ }\ } namespace BinXlsxRW{ ChartWriter::ChartWriter() { 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(0); m_aXfs.push_back(pXfs); m_nRow1 = -1; m_nCol1 = -1; m_nRow2 = -1; m_nCol2 = -1; } ChartWriter::~ChartWriter() { for (std::map*>*>::iterator it = m_mapSheets.begin(); it != m_mapSheets.end(); ++it) { std::map*>* rows = it->second; for(std::map*>::iterator itRow = rows->begin(); itRow != rows->end(); itRow++) { delete itRow->second; } delete it->second; } } void ChartWriter::toXlsx(OOX::Spreadsheet::CXlsx& oXlsx) { std::vector aSharedStrings; oXlsx.CreateWorkbook(); oXlsx.m_pWorkbook->m_oSheets.Init(); int nSheetId = 1; OOX::Spreadsheet::CWorksheet* pFirstWorksheet = NULL; for (std::map*>*>::iterator it = m_mapSheets.begin(); it != m_mapSheets.end(); ++it) { const std::wstring& sSheetName = it->first; //find or generate black worksheet OOX::Spreadsheet::CWorksheet* pWorksheet = toXlsxGetSheet(oXlsx.m_arWorksheets, oXlsx.m_mapWorksheets, sSheetName); //fill data to worksheet toXlsxSheetdata(pWorksheet, *it->second, aSharedStrings); OOX::Spreadsheet::CSheet* pSheet = new OOX::Spreadsheet::CSheet(); pSheet->m_oName = sSheetName; pSheet->m_oSheetId.Init(); pSheet->m_oSheetId->SetValue(nSheetId++); smart_ptr oWorksheetFile = smart_ptr(pWorksheet); const OOX::RId oRId = oXlsx.m_pWorkbook->Add(oWorksheetFile); pSheet->m_oRid.Init(); pSheet->m_oRid->SetValue(oRId.get()); oXlsx.m_pWorkbook->m_oSheets->m_arrItems.push_back(pSheet); if(NULL == pFirstWorksheet) { pFirstWorksheet = pWorksheet; } } //SharedStrings oXlsx.CreateSharedStrings(); for(size_t i = 0; i < aSharedStrings.size(); ++i) { OOX::Spreadsheet::CText* pText = new OOX::Spreadsheet::CText(); pText->m_sText = aSharedStrings[i]; if(std::wstring::npos != pText->m_sText.find(_T(" "))) { pText->m_oSpace.Init(); pText->m_oSpace->SetValue(SimpleTypes::xmlspacePreserve); } OOX::Spreadsheet::CSi* pSi = new OOX::Spreadsheet::CSi(); pSi->m_arrItems.push_back(pText); oXlsx.m_pSharedStrings->AddSi(pSi); } oXlsx.m_pSharedStrings->m_oCount.Init(); oXlsx.m_pSharedStrings->m_oCount->SetValue(oXlsx.m_pSharedStrings->m_nCount); oXlsx.m_pSharedStrings->m_oUniqueCount.Init(); oXlsx.m_pSharedStrings->m_oUniqueCount->SetValue(oXlsx.m_pSharedStrings->m_nCount); //Styles oXlsx.CreateStyles(); oXlsx.m_pStyles->m_oCellXfs.Init(); for(size_t i = 0; i < m_aXfs.size(); ++i) { oXlsx.m_pStyles->m_oCellXfs->m_arrItems.push_back(m_aXfs[i]); } oXlsx.m_pStyles->m_oNumFmts.Init(); for (boost::unordered_map::iterator it = m_mapFormats.begin(); it != m_mapFormats.end(); ++it) { OOX::Spreadsheet::CNumFmt* pNumFmt = new OOX::Spreadsheet::CNumFmt(); pNumFmt->m_oFormatCode = (it->first); pNumFmt->m_oNumFmtId.Init(); pNumFmt->m_oNumFmtId->SetValue(NUMID_START + it->second); oXlsx.m_pStyles->m_oNumFmts->m_arrItems.push_back(pNumFmt); } oXlsx.m_pStyles->m_oNumFmts->m_oCount.Init(); oXlsx.m_pStyles->m_oNumFmts->m_oCount->SetValue(oXlsx.m_pStyles->m_oNumFmts->m_arrItems.size()); oXlsx.m_pStyles->m_oCellXfs->m_oCount.Init(); oXlsx.m_pStyles->m_oCellXfs->m_oCount->SetValue(oXlsx.m_pStyles->m_oCellXfs->m_arrItems.size()); OOX::Spreadsheet::CDxf* pDxf = new OOX::Spreadsheet::CDxf(); pDxf->m_oBorder.Init(); pDxf->m_oBorder->m_oStart.Init(); pDxf->m_oBorder->m_oStart->m_oStyle.Init(); pDxf->m_oBorder->m_oStart->m_oStyle->SetValue(SimpleTypes::Spreadsheet::borderstyleThin); pDxf->m_oBorder->m_oStart->m_oColor.Init(); pDxf->m_oBorder->m_oStart->m_oColor->m_oIndexed.Init(); pDxf->m_oBorder->m_oStart->m_oColor->m_oIndexed->SetValue(12); pDxf->m_oBorder->m_oEnd.Init(); pDxf->m_oBorder->m_oEnd->m_oStyle.Init(); pDxf->m_oBorder->m_oEnd->m_oStyle->SetValue(SimpleTypes::Spreadsheet::borderstyleThin); pDxf->m_oBorder->m_oEnd->m_oColor.Init(); pDxf->m_oBorder->m_oEnd->m_oColor->m_oIndexed.Init(); pDxf->m_oBorder->m_oEnd->m_oColor->m_oIndexed->SetValue(12); pDxf->m_oBorder->m_oTop.Init(); pDxf->m_oBorder->m_oTop->m_oStyle.Init(); pDxf->m_oBorder->m_oTop->m_oStyle->SetValue(SimpleTypes::Spreadsheet::borderstyleThin); pDxf->m_oBorder->m_oTop->m_oColor.Init(); pDxf->m_oBorder->m_oTop->m_oColor->m_oIndexed.Init(); pDxf->m_oBorder->m_oTop->m_oColor->m_oIndexed->SetValue(12); pDxf->m_oBorder->m_oBottom.Init(); pDxf->m_oBorder->m_oBottom->m_oStyle.Init(); pDxf->m_oBorder->m_oBottom->m_oStyle->SetValue(SimpleTypes::Spreadsheet::borderstyleThin); pDxf->m_oBorder->m_oBottom->m_oColor.Init(); pDxf->m_oBorder->m_oBottom->m_oColor->m_oIndexed.Init(); pDxf->m_oBorder->m_oBottom->m_oColor->m_oIndexed->SetValue(12); oXlsx.m_pStyles->m_oDxfs.Init(); oXlsx.m_pStyles->m_oDxfs->m_arrItems.push_back(pDxf); oXlsx.m_pStyles->m_oDxfs->m_oCount.Init(); oXlsx.m_pStyles->m_oDxfs->m_oCount->SetValue(oXlsx.m_pStyles->m_oDxfs->m_arrItems.size()); //Table //todo table в случае нескольких sheet или если серии разнесены по sheet if(m_aTableNames.size() > 0) { OOX::Spreadsheet::CTableFile* pTable = new OOX::Spreadsheet::CTableFile(NULL); pTable->m_oTable.Init(); pTable->m_oTable->m_oDisplayName = L"Table1"; pTable->m_oTable->m_oRef.Init(); pTable->m_oTable->m_oRef->SetValue(OOX::Spreadsheet::CCell::combineRef(m_nRow1 - 1, m_nCol1 - 1) + L":" + OOX::Spreadsheet::CCell::combineRef(m_nRow2 - 1, m_nCol2 - 1)); pTable->m_oTable->m_oTotalsRowCount.Init(); pTable->m_oTable->m_oTotalsRowCount->SetValue(0); pTable->m_oTable->m_oTableBorderDxfId.Init(); pTable->m_oTable->m_oTableBorderDxfId->SetValue(0); pTable->m_oTable->m_oTableStyleInfo.Init(); pTable->m_oTable->m_oTableStyleInfo->m_oShowFirstColumn.Init(); pTable->m_oTable->m_oTableStyleInfo->m_oShowFirstColumn->FromBool(false); pTable->m_oTable->m_oTableStyleInfo->m_oShowLastColumn.Init(); pTable->m_oTable->m_oTableStyleInfo->m_oShowLastColumn->FromBool(false); pTable->m_oTable->m_oTableStyleInfo->m_oShowRowStripes.Init(); pTable->m_oTable->m_oTableStyleInfo->m_oShowRowStripes->FromBool(true); pTable->m_oTable->m_oTableStyleInfo->m_oShowColumnStripes.Init(); pTable->m_oTable->m_oTableStyleInfo->m_oShowColumnStripes->FromBool(false); pTable->m_oTable->m_oTableColumns.Init(); for(size_t i = 0; i < m_aTableNames.size(); ++i) { OOX::Spreadsheet::CTableColumn* pTableColumn = new OOX::Spreadsheet::CTableColumn(); if (!pTableColumn->m_oId.IsInit()) { pTableColumn->m_oId.Init(); pTableColumn->m_oId->SetValue((unsigned int)i + 1); } if (!pTableColumn->m_oName.IsInit()) { pTableColumn->m_oName = m_aTableNames[i]; } pTable->m_oTable->m_oTableColumns->m_arrItems.push_back(pTableColumn); } pTable->m_oTable->m_oTableColumns->m_oCount.Init(); pTable->m_oTable->m_oTableColumns->m_oCount->SetValue(pTable->m_oTable->m_oTableColumns->m_arrItems.size()); //check unique names size_t szTableNames = m_aTableNames.size(); std::sort( m_aTableNames.begin(), m_aTableNames.end() ); m_aTableNames.erase( std::unique( m_aTableNames.begin(), m_aTableNames.end() ), m_aTableNames.end() ); size_t szTableNamesUnique = m_aTableNames.size(); //add to sheet if(szTableNames == szTableNamesUnique) { OOX::Spreadsheet::CTablePart* pTablePart = new OOX::Spreadsheet::CTablePart(); NSCommon::smart_ptr pTableFile(pTable); const OOX::RId oRId = pFirstWorksheet->Add(pTableFile); pTablePart->m_oRId.Init(); pTablePart->m_oRId->SetValue(oRId.get()); pFirstWorksheet->m_oTableParts.Init(); pFirstWorksheet->m_oTableParts->m_arrItems.push_back(pTablePart); pFirstWorksheet->m_oTableParts->m_oCount.Init(); pFirstWorksheet->m_oTableParts->m_oCount->SetValue(pFirstWorksheet->m_oTableParts->m_arrItems.size()); } } } void ChartWriter::parseChart(const OOX::Spreadsheet::CT_Chart* pChart) { if(NULL != pChart) { PARSE_TITLE(pChart->m_title, false, NULL); OOX::Spreadsheet::CT_PlotArea* pPlotArea = pChart->m_plotArea; if(NULL != pPlotArea) { for(size_t i = 0; i < pPlotArea->m_ItemsElementName1.size(); ++i) { OOX::Spreadsheet::ItemsChoiceType6 eType = *pPlotArea->m_ItemsElementName1[i]; void* pItem = pPlotArea->m_Items1[i]; switch(eType) { case OOX::Spreadsheet::itemschoicetype6CATAX: { OOX::Spreadsheet::CT_CatAx* pCatax = static_cast(pItem); PARSE_TITLE(pCatax->m_title, false, NULL); break; } case OOX::Spreadsheet::itemschoicetype6DATEAX: { OOX::Spreadsheet::CT_DateAx* pDateax = static_cast(pItem); PARSE_TITLE(pDateax->m_title, false, NULL); break; } case OOX::Spreadsheet::itemschoicetype6SERAX: { OOX::Spreadsheet::CT_SerAx* pSerax = static_cast(pItem); PARSE_TITLE(pSerax->m_title, false, NULL); break; } case OOX::Spreadsheet::itemschoicetype6VALAX: { OOX::Spreadsheet::CT_ValAx* pValax = static_cast(pItem); PARSE_TITLE(pValax->m_title, false, NULL); if(NULL != pValax->m_dispUnits) { PARSE_TITLE(pValax->m_dispUnits->m_dispUnitsLbl, false, NULL); } break; } } } for(size_t i = 0; i < pPlotArea->m_ItemsElementName0.size(); ++i) { OOX::Spreadsheet::ItemsChoiceType5 eType = *pPlotArea->m_ItemsElementName0[i]; void* pItem = pPlotArea->m_Items[i]; switch(eType) { case OOX::Spreadsheet::itemschoicetype5AREA3DCHART: { OOX::Spreadsheet::CT_Area3DChart* pChart = static_cast(pItem); PARSE_CT_CHART(pChart, OOX::Spreadsheet::CT_AreaSer); break; } case OOX::Spreadsheet::itemschoicetype5AREACHART: { OOX::Spreadsheet::CT_AreaChart* pChart = static_cast(pItem); PARSE_CT_CHART(pChart, OOX::Spreadsheet::CT_AreaSer); PARSE_TRENDLINE(pChart, OOX::Spreadsheet::CT_AreaSer); PARSE_ERRBARS(pChart, OOX::Spreadsheet::CT_AreaSer); break; } case OOX::Spreadsheet::itemschoicetype5BAR3DCHART: { OOX::Spreadsheet::CT_Bar3DChart* pChart = static_cast(pItem); PARSE_CT_CHART(pChart, OOX::Spreadsheet::CT_BarSer); break; } case OOX::Spreadsheet::itemschoicetype5BARCHART: { OOX::Spreadsheet::CT_BarChart* pChart = static_cast(pItem); PARSE_TRENDLINE(pChart, OOX::Spreadsheet::CT_BarSer); PARSE_CT_CHART(pChart, OOX::Spreadsheet::CT_BarSer); break; } case OOX::Spreadsheet::itemschoicetype5BUBBLECHART: { OOX::Spreadsheet::CT_BubbleChart* pChart = static_cast(pItem); PARSE_CT_CHART_SCATTER(pChart, OOX::Spreadsheet::CT_BubbleSer); PARSE_TRENDLINE(pChart, OOX::Spreadsheet::CT_BubbleSer); PARSE_ERRBARS(pChart, OOX::Spreadsheet::CT_BubbleSer); PARSE_BUBBLE_SIZE(pChart, OOX::Spreadsheet::CT_BubbleSer); break; } case OOX::Spreadsheet::itemschoicetype5DOUGHNUTCHART: { OOX::Spreadsheet::CT_DoughnutChart* pChart = static_cast(pItem); PARSE_CT_CHART(pChart, OOX::Spreadsheet::CT_PieSer); break; } case OOX::Spreadsheet::itemschoicetype5LINE3DCHART: { OOX::Spreadsheet::CT_Line3DChart* pChart = static_cast(pItem); PARSE_CT_CHART(pChart, OOX::Spreadsheet::CT_LineSer); break; } case OOX::Spreadsheet::itemschoicetype5LINECHART: { OOX::Spreadsheet::CT_LineChart* pChart = static_cast(pItem); PARSE_CT_CHART(pChart, OOX::Spreadsheet::CT_LineSer); PARSE_TRENDLINE(pChart, OOX::Spreadsheet::CT_LineSer); break; } case OOX::Spreadsheet::itemschoicetype5OFPIECHART: { OOX::Spreadsheet::CT_OfPieChart* pChart = static_cast(pItem); PARSE_CT_CHART(pChart, OOX::Spreadsheet::CT_PieSer); break; } case OOX::Spreadsheet::itemschoicetype5PIE3DCHART: { OOX::Spreadsheet::CT_Pie3DChart* pChart = static_cast(pItem); PARSE_CT_CHART(pChart, OOX::Spreadsheet::CT_PieSer); break; } case OOX::Spreadsheet::itemschoicetype5PIECHART: { OOX::Spreadsheet::CT_PieChart* pChart = static_cast(pItem); PARSE_CT_CHART(pChart, OOX::Spreadsheet::CT_PieSer); break; } case OOX::Spreadsheet::itemschoicetype5RADARCHART: { OOX::Spreadsheet::CT_RadarChart* pChart = static_cast(pItem); PARSE_CT_CHART(pChart, OOX::Spreadsheet::CT_RadarSer); break; } case OOX::Spreadsheet::itemschoicetype5SCATTERCHART: { OOX::Spreadsheet::CT_ScatterChart* pChart = static_cast(pItem); PARSE_CT_CHART_SCATTER(pChart, OOX::Spreadsheet::CT_ScatterSer); PARSE_TRENDLINE(pChart, OOX::Spreadsheet::CT_ScatterSer); PARSE_ERRBARS(pChart, OOX::Spreadsheet::CT_ScatterSer); break; } case OOX::Spreadsheet::itemschoicetype5STOCKCHART: { OOX::Spreadsheet::CT_StockChart* pChart = static_cast(pItem); PARSE_CT_CHART(pChart, OOX::Spreadsheet::CT_LineSer); break; } case OOX::Spreadsheet::itemschoicetype5SURFACE3DCHART: { OOX::Spreadsheet::CT_Surface3DChart* pChart = static_cast(pItem); PARSE_CT_CHART(pChart, OOX::Spreadsheet::CT_SurfaceSer); break; } case OOX::Spreadsheet::itemschoicetype5SURFACECHART: { OOX::Spreadsheet::CT_SurfaceChart* pChart = static_cast(pItem); PARSE_CT_CHART(pChart, OOX::Spreadsheet::CT_SurfaceSer); break; } } } } } //проверяем можем ли создать таблицу if(m_mapSheets.size() > 0 && m_nRow1 > 0 && m_nRow2 > 0 && m_nCol1 > 0 && m_nCol2 > 0 && m_nRow1 < m_nRow2) { std::map*>* rows = m_mapSheets.begin()->second; std::map*>::iterator itRows = rows->find(m_nRow1); if(itRows != rows->end()) { std::map* cells = itRows->second; std::vector aIndexesCell; for(std::map::const_iterator it = cells->begin(); it != cells->end(); ++it) { aIndexesCell.push_back(it->first); } std::sort(aIndexesCell.begin(), aIndexesCell.end()); if(m_nCol2 - m_nCol1 + 1 == aIndexesCell.size() && m_nCol1 == aIndexesCell[0] && m_nCol2 == aIndexesCell[aIndexesCell.size() - 1]) { for(size_t j = 0; j < aIndexesCell.size(); ++j) { int nIndexCell = aIndexesCell[j]; OOX::Spreadsheet::CCell* pCell = cells->at(nIndexCell); //не должно быть ячеек без m_oValue m_aTableNames.push_back(pCell->m_oValue->m_sText); } } } } } OOX::Spreadsheet::CWorksheet* ChartWriter::toXlsxGetSheet(std::vector& arWorksheets, std::map& mapWorksheets, const std::wstring& sName) { OOX::Spreadsheet::CWorksheet* pWorksheet = NULL; std::map::const_iterator pFind = mapWorksheets.find(sName); if (pFind == mapWorksheets.end()) { pWorksheet = new OOX::Spreadsheet::CWorksheet(NULL); pWorksheet->m_oSheetFormatPr.Init(); pWorksheet->m_oSheetFormatPr->m_oDefaultRowHeight = 15.; pWorksheet->m_oPageMargins.Init(); pWorksheet->m_oPageMargins.Init(); pWorksheet->m_oPageMargins->m_oLeft.Init(); pWorksheet->m_oPageMargins->m_oLeft->FromInches(0.7); pWorksheet->m_oPageMargins->m_oRight.Init(); pWorksheet->m_oPageMargins->m_oRight->FromInches(0.7); pWorksheet->m_oPageMargins->m_oTop.Init(); pWorksheet->m_oPageMargins->m_oTop->FromInches(0.75); pWorksheet->m_oPageMargins->m_oBottom.Init(); pWorksheet->m_oPageMargins->m_oBottom->FromInches(0.75); pWorksheet->m_oPageMargins->m_oHeader.Init(); pWorksheet->m_oPageMargins->m_oHeader->FromInches(0.3); pWorksheet->m_oPageMargins->m_oFooter.Init(); pWorksheet->m_oPageMargins->m_oFooter->FromInches(0.3); mapWorksheets[sName] = pWorksheet; arWorksheets.push_back(pWorksheet); } else { pWorksheet = pFind->second; } return pWorksheet; } void ChartWriter::toXlsxSheetdata(OOX::Spreadsheet::CWorksheet* pWorksheet, const std::map*>& rows, std::vector& aSharedStrings) { pWorksheet->m_oSheetData.Init(); std::vector aIndexesRow; for(std::map*>::const_iterator it = rows.begin(); it != rows.end(); ++it) { aIndexesRow.push_back(it->first); } std::sort(aIndexesRow.begin(), aIndexesRow.end()); for(size_t i = 0; i < aIndexesRow.size(); ++i) { int nIndexRow = aIndexesRow[i]; OOX::Spreadsheet::CRow* pRow = new OOX::Spreadsheet::CRow(); pRow->m_oR.Init(); pRow->m_oR->SetValue(nIndexRow); const std::map& cells = *rows.at(nIndexRow); std::vector aIndexesCell; for(std::map::const_iterator it = cells.begin(); it != cells.end(); ++it) { aIndexesCell.push_back(it->first); } std::sort(aIndexesCell.begin(), aIndexesCell.end()); for(size_t j = 0; j < aIndexesCell.size(); ++j) { int nIndexCell = aIndexesCell[j]; OOX::Spreadsheet::CCell* pCell = cells.at(nIndexCell); //SharedStrings if(pCell->m_oValue.IsInit()) { if ((pCell->m_oType.IsInit()) && (pCell->m_oType->GetValue() == SimpleTypes::Spreadsheet::celltypeSharedString)) { aSharedStrings.push_back(pCell->m_oValue->m_sText); pCell->m_oValue->m_sText = std::to_wstring(aSharedStrings.size() - 1); } else if (false == pCell->m_oStyle.IsInit()) { pCell->m_oType.Init(); const std::wstring& val = pCell->m_oValue->m_sText; if(L"TRUE" == val || L"FALSE" == val) { pCell->m_oType->SetValue(SimpleTypes::Spreadsheet::celltypeBool); if(L"TRUE" == val) { pCell->m_oValue->m_sText = L"1"; } else { pCell->m_oValue->m_sText = L"0"; } } else if(L"#NULL!" == val || L"#DIV/0!" == val || L"#VALUE!" == val || L"#REF!" == val || L"#NAME?" == val || L"#NUM!" == val || L"#N/A" == val) { pCell->m_oType->SetValue(SimpleTypes::Spreadsheet::celltypeError); pCell->m_oValue->m_sText = val; } else { //как в CsvReader - подозрительный код WCHAR *pEndPtr; wcstod(val.c_str(), &pEndPtr); if (0 != *pEndPtr) { // Не число aSharedStrings.push_back(val); pCell->m_oType->SetValue(SimpleTypes::Spreadsheet::celltypeSharedString); pCell->m_oValue->m_sText = std::to_wstring((int)aSharedStrings.size() - 1); } else { pCell->m_oValue->m_sText = val; } } } } pRow->m_arrItems.push_back(pCell); } pWorksheet->m_oSheetData->m_arrItems.push_back(pRow); } } void ChartWriter::parseCell(const std::wstring& sheet, const int& nRow, const int& nCol, const std::wstring& val, std::wstring format, bool bAlwaysSharedString) { std::map*>*>::const_iterator itSheets = m_mapSheets.find(sheet); std::map*>* rows = NULL; if(itSheets == m_mapSheets.end()) { rows = new std::map*>(); m_mapSheets.insert(std::make_pair(sheet, rows)); } else { rows = itSheets->second; } std::map*>::const_iterator itRows = rows->find(nRow); std::map* cells = NULL; if(itRows == rows->end()) { cells = new std::map(); rows->insert(std::make_pair(nRow, cells)); } else { cells = itRows->second; } if(cells->find(nCol) == cells->end()) { OOX::Spreadsheet::CCell* pNewCell = parseCreateCell(nRow, nCol, val, format); if (bAlwaysSharedString) { pNewCell->m_oType.Init(); pNewCell->m_oType->SetValue(SimpleTypes::Spreadsheet::ECellTypeType::celltypeSharedString); } cells->insert(std::make_pair(nCol, pNewCell)); } } OOX::Spreadsheet::CCell* ChartWriter::parseCreateCell(const int& nRow, const int& nCol, const std::wstring& val, std::wstring format) { OOX::Spreadsheet::CCell* pNewCell = new OOX::Spreadsheet::CCell(); //пока добавляем как есть, shared string после записи таблицы pNewCell->m_oValue.Init(); pNewCell->m_oValue->m_sText = val; if (!format.empty()) { unsigned int nXfsIndex = m_aXfs.size(); boost::unordered_map::const_iterator itFormat = m_mapFormats.find(format); if(itFormat == m_mapFormats.end()) { m_mapFormats[format] = nXfsIndex; } else { nXfsIndex = itFormat->second; } 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(NUMID_START + nXfsIndex); m_aXfs.push_back(pXfs); pNewCell->m_oStyle = nXfsIndex; } pNewCell->setRowCol(nRow - 1, nCol - 1); return pNewCell; } void ChartWriter::parseStrRef(const OOX::Spreadsheet::CT_StrRef* pStrRef, bool bUpdateRange, const wchar_t* cRangeName) { if(NULL != pStrRef && pStrRef->m_f.IsInit()) { std::wstring wb, sheetFrom, sheetTo; int nRow1, nCol1, nRow2, nCol2; if(OOX::Spreadsheet::CCell::parse3DRef(*pStrRef->m_f, wb, sheetFrom, sheetTo, nRow1, nCol1, nRow2, nCol2) && sheetFrom.length() > 0 && 0 == sheetTo.length() && NULL != pStrRef->m_strCache) { bool bRow = nRow1 == nRow2; if(bUpdateRange) { if(NULL != cRangeName) { if(bRow) { if(nCol1 > 1) { parseCell(sheetFrom, nRow1, nCol1 - 1, std::wstring(cRangeName), L"", true); } } else { if(nRow1 > 1) { parseCell(sheetFrom, nRow1 - 1, nCol1, std::wstring(cRangeName), L"", true); } } } if(-1 == m_nRow1 || m_nRow1 > nRow1) { m_nRow1 = nRow1; } if(-1 == m_nCol1 || m_nCol1 > nCol1) { m_nCol1 = nCol1; } if(-1 == m_nRow2 || m_nRow2 < nRow2) { m_nRow2 = nRow2; } if(-1 == m_nCol2 || m_nCol2 < nCol2) { m_nCol2 = nCol2; } } for(size_t i = 0; i < pStrRef->m_strCache->m_pt.size(); ++i) { OOX::Spreadsheet::CT_StrVal* val = pStrRef->m_strCache->m_pt[i]; if (val->m_idx.IsInit() && val->m_v.IsInit()) { int nRow, nCol; if(bRow) { nRow = nRow1; nCol = nCol1 + *val->m_idx; } else { nRow = nRow1 + *val->m_idx; nCol = nCol1; } parseCell(sheetFrom, nRow, nCol, *val->m_v, L"", true); } } } } } void ChartWriter::parseNumRef(const OOX::Spreadsheet::CT_NumRef* pNumRef, bool bUpdateRange, const wchar_t* cRangeName) { if(NULL != pNumRef && pNumRef->m_f.IsInit()) { std::wstring wb, sheetFrom, sheetTo; int nRow1, nCol1, nRow2, nCol2; if(OOX::Spreadsheet::CCell::parse3DRef(*pNumRef->m_f, wb, sheetFrom, sheetTo, nRow1, nCol1, nRow2, nCol2) && sheetFrom.length() > 0 && 0 == sheetTo.length() && NULL != pNumRef->m_numCache) { bool bRow = nRow1 == nRow2; if(bUpdateRange) { if(NULL != cRangeName) { if(bRow) { if(nCol1 > 1) { parseCell(sheetFrom, nRow1, nCol1 - 1, std::wstring(cRangeName), L""); } } else { if(nRow1 > 1) { parseCell(sheetFrom, nRow1 - 1, nCol1, std::wstring(cRangeName), L""); } } } if(-1 == m_nRow1 || m_nRow1 > nRow1) { m_nRow1 = nRow1; } if(-1 == m_nCol1 || m_nCol1 > nCol1) { m_nCol1 = nCol1; } if(-1 == m_nRow2 || m_nRow2 < nRow2) { m_nRow2 = nRow2; } if(-1 == m_nCol2 || m_nCol2 < nCol2) { m_nCol2 = nCol2; } } std::wstring formatCodeSer = pNumRef->m_numCache->m_formatCode.IsInit() ? *pNumRef->m_numCache->m_formatCode : L""; for(size_t i = 0; i < pNumRef->m_numCache->m_pt.size(); ++i) { OOX::Spreadsheet::CT_NumVal* val = pNumRef->m_numCache->m_pt[i]; if(val->m_idx.IsInit() && val->m_v.IsInit()) { std::wstring formatCode = val->m_formatCode.IsInit() ? *val->m_formatCode : formatCodeSer; int nRow, nCol; if(bRow) { nRow = nRow1; nCol = nCol1 + *val->m_idx; } else { nRow = nRow1 + *val->m_idx; nCol = nCol1; } parseCell(sheetFrom, nRow, nCol, *val->m_v, formatCode); } } } else { //range is defined name } } } void ChartWriter::parseMultiLvlStrRef(const OOX::Spreadsheet::CT_MultiLvlStrRef* pMultiLvlStrRef, bool bUpdateRange, const wchar_t* cRangeName) { //todo нужен пример } void ChartWriter::parseAxDataSource(const OOX::Spreadsheet::CT_AxDataSource* pAxDataSource, bool bUpdateRange, const wchar_t* cRangeName) { if(NULL != pAxDataSource) { parseStrRef(pAxDataSource->m_strRef, bUpdateRange, cRangeName); parseNumRef(pAxDataSource->m_numRef, bUpdateRange, cRangeName); parseMultiLvlStrRef(pAxDataSource->m_multiLvlStrRef, bUpdateRange, cRangeName); } } void ChartWriter::parseNumDataSource(const OOX::Spreadsheet::CT_NumDataSource* pNumDataSource, bool bUpdateRange, const wchar_t* cRangeName) { if(NULL != pNumDataSource) { parseNumRef(pNumDataSource->m_numRef, bUpdateRange, cRangeName); } } };