/* * (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 "ChartSheetSubstream.h" #include "Biff_records/WriteProtect.h" #include "Biff_records/SheetExt.h" #include "Biff_records/WebPub.h" #include "Biff_records/HFPicture.h" #include "Biff_records/PrintSize.h" #include "Biff_records/Fbi.h" #include "Biff_records/Fbi2.h" #include "Biff_records/ClrtClient.h" #include "Biff_records/Palette.h" #include "Biff_records/SXViewLink.h" #include "Biff_records/PivotChartBits.h" #include "Biff_records/SBaseRef.h" #include "Biff_records/MsoDrawingGroup.h" #include "Biff_records/Units.h" #include "Biff_records/CodeName.h" #include "Biff_records/EOF.h" #include "Biff_records/BOF.h" #include "Biff_records/AreaFormat.h" #include "Biff_records/SerToCrt.h" #include "Biff_records/AxisParent.h" #include "Biff_records/Series.h" #include "Biff_records/BRAI.h" #include "Biff_records/SIIndex.h" #include "Biff_records/DataFormat.h" #include "Biff_records/Text.h" #include "Biff_records/Pos.h" #include "Biff_records/Pie.h" #include "Biff_records/ShtProps.h" #include "Biff_records/Chart3d.h" #include "Biff_records/ChartFormat.h" #include "Biff_records/Legend.h" #include "Biff_records/AttachedLabel.h" #include "Biff_records/DataLabExtContents.h" #include "Biff_records/CrtLine.h" #include "Biff_records/Dat.h" #include "Biff_records/Chart.h" #include "Biff_records/ExternSheet.h" #include "Biff_records/FrtFontList.h" #include "Biff_records/ChartFrtInfo.h" #include "Biff_records/SerParent.h" #include "Biff_unions/FONTLIST.h" #include "Biff_unions/PAGESETUP.h" #include "Biff_unions/BACKGROUND.h" #include "Biff_unions/PROTECTION_COMMON.h" #include "Biff_unions/OBJECTS.h" #include "Biff_unions/CHARTFOMATS.h" #include "Biff_unions/SERIESDATA.h" #include "Biff_unions/WINDOW.h" #include "Biff_unions/CUSTOMVIEW.h" #include "Biff_unions/CRTMLFRT.h" #include "Biff_unions/FRAME.h" #include "Biff_unions/ATTACHEDLABEL.h" #include "Biff_unions/SERIESFORMAT.h" #include "Biff_unions/CRT.h" #include "Biff_unions/AXISPARENT.h" #include "Biff_unions/AXES.h" #include "Biff_unions/SS.h" #include "Biff_unions/AI.h" #include "Biff_unions/LD.h" #include "Biff_unions/DAT.h" #include "Biff_unions/PIVOTVIEW.h" #include "Biff_unions/RECORD12.h" #include "Biff_unions/ATTACHEDLABEL.h" #include "Biff_unions/DFTTEXT.h" #include "../../Converter/XlsConverter.h" #include "../../Converter/xlsx_conversion_context.h" namespace XLS {; ChartSheetSubstream::ChartSheetSubstream(const size_t ws_index) : CommonSubstream(ws_index) { } ChartSheetSubstream::~ChartSheetSubstream() { } BaseObjectPtr ChartSheetSubstream::clone() { return BaseObjectPtr(new ChartSheetSubstream(*this)); } /* CHARTSHEET = BOF CHARTSHEETCONTENT CHARTSHEETCONTENT = [WriteProtect] [SheetExt] [WebPub] *HFPicture PAGESETUP PrintSize [HeaderFooter] [BACKGROUND] *Fbi *Fbi2 [ClrtClient] [PROTECTION] [Palette] [SXViewLink] [PivotChartBits] [SBaseRef] [MsoDrawingGroup] OBJECTS Units CHARTFOMATS SERIESDATA *WINDOW *CUSTOMVIEW [CodeName] [CRTMLFRT] EOF */ const bool ChartSheetSubstream::loadContent(BinProcessor& proc) { global_info_ = proc.getGlobalWorkbookInfo(); global_info_->current_sheet = ws_index_ + 1; int count = 0 ; if(!proc.mandatory()) { return false; } while (true) { CFRecordType::TypeId type = proc.getNextRecordType(); //Log::warning(CFRecordType::getStringById(type)); if (type == rt_NONE || proc.isBOF(type)) break; if (type == rt_EOF) { proc.mandatory(); break; } switch(type) { case rt_WriteProtect: { if (proc.optional()) { m_WriteProtect = elements_.back(); elements_.pop_back(); } }break; case rt_SheetExt: { if (proc.optional()) { m_SheetExt = elements_.back(); elements_.pop_back(); } }break; case rt_WebPub: proc.optional(); break; case rt_HFPicture: { count = proc.repeated(0, 0); while(count > 0) { m_arHFPicture.insert(m_arHFPicture.begin(), elements_.back()); elements_.pop_back(); count--; } }break; case rt_Header: case rt_Footer: case rt_BottomMargin: case rt_TopMargin: case rt_LeftMargin: case rt_RightMargin: { if (proc.mandatory()) { m_PAGESETUP = elements_.back(); elements_.pop_back(); } }break; case rt_PrintSize: { if (proc.mandatory()) { m_PrintSize = elements_.back(); elements_.pop_back(); } }break; case rt_HeaderFooter: { count = proc.repeated (0, 0); while(count > 0) { m_arRECORD12.insert(m_arRECORD12.begin(), elements_.back()); elements_.pop_back(); count--; } }break; case rt_BkHim: { if (proc.optional()) { m_BACKGROUND = elements_.back(); elements_.pop_back(); } }break; case rt_Fbi: { count = proc.repeated(0, 0); while(count > 0) { m_arFbi.insert(m_arFbi.begin(), elements_.back()); elements_.pop_back(); count--; } }break; case rt_Fbi2: { count = proc.repeated(0, 0); while(count > 0 && m_arFbi.empty())//??? split { m_arFbi.insert(m_arFbi.begin(), elements_.back()); elements_.pop_back(); count--; } } case rt_ClrtClient: proc.optional(); break; case rt_Protect: case rt_ScenarioProtect: case rt_ObjProtect: case rt_Password: { if (proc.optional()) { m_PROTECTION = elements_.back(); elements_.pop_back(); } }break; case rt_Palette: { if (proc.optional()) { m_Palette = elements_.back(); elements_.pop_back(); } }break; case rt_SXViewLink: { if (proc.optional()) { m_SXViewLink = elements_.back(); elements_.pop_back(); } }break; case rt_PivotChartBits: { if (proc.optional()) { m_PivotChartBits = elements_.back(); elements_.pop_back(); } }break; case rt_SBaseRef: { if (proc.optional()) { m_SBaseRef = elements_.back(); elements_.pop_back(); } }break; case rt_Obj: case rt_MsoDrawing: { MsoDrawingGroup mso_drawing_group(true); proc.optional(mso_drawing_group); OBJECTS objects(true); if (proc.mandatory(objects)) { m_OBJECTS = elements_.back(); elements_.pop_back(); } }break; case rt_ExternSheet: { if (proc.optional()) { m_ExternSheet = elements_.back(); elements_.pop_back(); } }break; case rt_Units: { if (proc.mandatory()) { m_Units = elements_.back(); elements_.pop_back(); } }break; case rt_Chart: { if ( proc.mandatory() ) { m_CHARTFORMATS = elements_.back(); elements_.pop_back(); recalc((CHARTFORMATS*)m_CHARTFORMATS.get()); } }break; case rt_Dimensions: case rt_SIIndex: { if ( proc.mandatory() ) { m_SERIESDATA = elements_.back(); elements_.pop_back(); recalc((SERIESDATA*)m_SERIESDATA.get()); } }break; case rt_Window2: { count = proc.repeated(0, 0); while(count > 0) { m_arWINDOW.insert(m_arWINDOW.begin(), elements_.back()); elements_.pop_back(); count--; } }break; case rt_UserSViewBegin: { count = proc.repeated(0, 0); while(count > 0) { m_arCUSTOMVIEW.insert(m_arCUSTOMVIEW.begin(), elements_.back()); elements_.pop_back(); count--; } }break; case rt_CodeName: { if (proc.optional()) { m_CodeName = elements_.back(); elements_.pop_back(); } }break; case rt_CrtMlFrt: { if (proc.optional()) { m_CRTMLFRT = elements_.back(); elements_.pop_back(); } }break; case rt_FrtFontList: //error in stream !! { count = proc.repeated(0, 0); while(count > 0) { elements_.pop_back(); count--; } }break; case rt_ChartFrtInfo: { //skipped record count = proc.repeated(0, 0); }break; default://unknown .... skip { proc.SkipRecord(); }break; } } LoadHFPicture(); return true; } const bool ChartSheetSubstream::saveContent(BinProcessor& proc) { auto globInfo = proc.getGlobalWorkbookInfo(); { if(separate && globInfo->sheets_info.size() > globInfo->current_sheet) globInfo->sheets_info.at(globInfo->current_sheet).StreamPos = proc.GetRecordPosition(); BOF bof; bof.dt= 0x0020; proc.mandatory(bof); } if(m_WriteProtect != nullptr) proc.mandatory(*m_WriteProtect); if(m_SheetExt != nullptr) proc.mandatory(*m_SheetExt); for(auto i : m_arHFPicture) if(i != nullptr) proc.mandatory(*i); if(m_PAGESETUP != nullptr) proc.mandatory(*m_PAGESETUP); if(m_PrintSize != nullptr) proc.mandatory(*m_PrintSize); else proc.mandatory(); if(!m_arRECORD12.empty()) if(m_arRECORD12[0] != nullptr) proc.mandatory(*m_arRECORD12[0]); if(m_BACKGROUND != nullptr) proc.mandatory(*m_BACKGROUND); for(auto i : m_arFbi) if(i != nullptr) proc.mandatory(*i); if(m_PROTECTION != nullptr) proc.mandatory(*m_PROTECTION); if(m_Palette != nullptr) proc.mandatory(*m_Palette); if(m_SXViewLink != nullptr) proc.mandatory(*m_SXViewLink); if(m_PivotChartBits != nullptr) proc.mandatory(*m_PivotChartBits); if(m_SBaseRef != nullptr) proc.mandatory(*m_SBaseRef); if(m_OBJECTS != nullptr) proc.mandatory(*m_OBJECTS); proc.mandatory(); if(m_CHARTFORMATS != nullptr) proc.mandatory(*m_CHARTFORMATS); if(m_SERIESDATA != nullptr) proc.mandatory(*m_SERIESDATA); for(auto i : m_arWINDOW) if(i != nullptr) proc.mandatory(*i); for(auto i : m_arCUSTOMVIEW) if(i != nullptr) proc.mandatory(*i); if(m_CodeName != nullptr) proc.mandatory(*m_CodeName); proc.mandatory(); return true; } void ChartSheetSubstream::recalc(CHARTFORMATS* charts) { if (charts == NULL) return; if (charts->m_arAXISPARENT.empty()) return; int ind_AXIS = 0; AXISPARENT* parent0 = dynamic_cast(charts->m_arAXISPARENT[ind_AXIS].get()); int iCrt = -1; for (size_t i = 0; i < parent0->m_arCRT.size(); i++) { CRT* crt= dynamic_cast(parent0->m_arCRT[i].get()); if (crt) { parent0->m_mapCRTIndex.insert(std::make_pair(crt->m_indexCrt, i)); } } for (size_t i = 0 ; i < charts->m_arSERIESFORMAT.size(); i++) { SERIESFORMAT * series = dynamic_cast(charts->m_arSERIESFORMAT[i].get()); if (series == NULL) continue; SerParent *parent = dynamic_cast(series->m_SerParent.get()); if ( (parent) && (parent->series > 0 && parent->series <= charts->m_arSERIESFORMAT.size())) { SERIESFORMAT *series_owner = dynamic_cast(charts->m_arSERIESFORMAT[parent->series - 1].get()); if (series_owner) { series_owner->m_arSERIESFORMAT_ext.push_back(charts->m_arSERIESFORMAT[i]); charts->m_arSERIESFORMAT[i] = BaseObjectPtr(); } } } for (size_t i = 0 ; i < charts->m_arSERIESFORMAT.size(); i++) { SERIESFORMAT * series = dynamic_cast(charts->m_arSERIESFORMAT[i].get()); if (series == NULL) continue; SerToCrt * serCrt = dynamic_cast(series->m_SerToCrt.get()); if ( serCrt == NULL) continue; iCrt = serCrt->id; while ((parent0->m_arCRT.size() <= iCrt) && (ind_AXIS < charts->m_arAXISPARENT.size()) && (charts->m_arAXISPARENT.size() > 1)) { parent0 = dynamic_cast(charts->m_arAXISPARENT[++ind_AXIS].get()); } if (iCrt >= parent0->m_arCRT.size() || iCrt < 0) continue; CRT * crt = dynamic_cast(parent0->m_arCRT[iCrt].get()); std::unordered_map>::iterator it = m_mapTypeChart.find(iCrt); if (it == m_mapTypeChart.end()) { std::vector ser; ser.push_back(i); m_mapTypeChart.insert(std::make_pair(iCrt, ser)); } else { it->second.push_back(i); } } for (size_t i = 0; i < parent0->m_arCRT.size(); i++) { std::unordered_map>::iterator it = m_mapTypeChart.find(i); if (it == m_mapTypeChart.end()) { std::vector ser; m_mapTypeChart.insert(std::make_pair(i, ser)); } } } void ChartSheetSubstream::recalc(SERIESDATA* data) { } int ChartSheetSubstream::serialize(std::wostream & _stream) { CHARTFORMATS *chart_formats = dynamic_cast(m_CHARTFORMATS.get()); if (!chart_formats) return 0; AreaFormat *chart_area_format = NULL; FRAME *chart_frame = dynamic_cast(chart_formats->m_FRAME.get()); if (chart_frame) chart_area_format = dynamic_cast(chart_frame->m_AreaFormat.get()); ShtProps *sht_props = dynamic_cast(chart_formats->m_ShtProps.get()); Chart *chart_rect = dynamic_cast(chart_formats->m_ChartRect.get()); DFTTEXT *default_text = (false == chart_formats->m_arDFTTEXT.empty()) ? dynamic_cast(chart_formats->m_arDFTTEXT[0].get()) : NULL; std::wstring namePivotTable; CP_XML_WRITER(_stream) { CP_XML_NODE(L"c:lang") { CP_XML_ATTR(L"val",L"en-US"); } CP_XML_NODE(L"c:roundedCorners") { if ((chart_area_format) && (chart_area_format->fInvertNeg)) CP_XML_ATTR(L"val", 1); //???? else CP_XML_ATTR(L"val", 0); } if (m_SXViewLink) { SXViewLink *link = dynamic_cast(m_SXViewLink.get()); CP_XML_NODE(L"c:pivotSource") { CP_XML_NODE(L"c:name") { std::wstring name = link->stPivotTable.value(); std::wstring::size_type pos = name.find(L"]"); std::wstring::size_type pos1 = name.find(L"!", pos); if (std::wstring::npos != pos1) namePivotTable = name.substr(pos1 + 1); if (std::wstring::npos != pos) name = L"[]" + name.substr(pos + 1); CP_XML_STREAM() << name; } CP_XML_NODE(L"c:fmtId") { CP_XML_ATTR(L"val", 0); } } } CP_XML_NODE(L"c:chart") { if (false == namePivotTable.empty()) { std::map::iterator pFindTable = global_info_->mapPivotTableViews.find(namePivotTable); if (pFindTable != global_info_->mapPivotTableViews.end()) { } //CP_XML_NODE(L"c:pivotFmts") //{ // CP_XML_NODE(L"c:pivotFmt") // { // CP_XML_NODE(L"c:idx") // { // CP_XML_ATTR(L"val", 0); // // // } // } //} } serialize_title (CP_XML_STREAM()); serialize_3D (CP_XML_STREAM()); serialize_plot_area (CP_XML_STREAM()); if (sht_props) { if (sht_props->fPlotVisOnly == true) { CP_XML_NODE(L"c:plotVisOnly") { CP_XML_ATTR(L"val", sht_props->fPlotVisOnly); } } CP_XML_NODE(L"c:dispBlanksAs") { switch(sht_props->mdBlank) { case 0: CP_XML_ATTR(L"val", L"gap"); break; case 1: CP_XML_ATTR(L"val", L"zero"); break; case 2: CP_XML_ATTR(L"val", L"span"); break; } } } } if (chart_frame) chart_frame->serialize(_stream); else { CP_XML_NODE(L"c:spPr") { CP_XML_NODE(L"a:noFill"); CP_XML_NODE(L"a:ln") { CP_XML_NODE(L"a:noFill"); } } } if ((default_text) && (default_text->m_ATTACHEDLABEL)) { ATTACHEDLABEL* attach_lablel = dynamic_cast(default_text->m_ATTACHEDLABEL.get()); attach_lablel->serialize_txPr(_stream); } if (m_SXViewLink) { CP_XML_NODE(L"c:extLst") { CP_XML_NODE(L"c:ext") { CP_XML_ATTR(L"uri", L"{781A3756-C4B2-4CAC-9D66-4F8BD8637D16}"); CP_XML_ATTR(L"xmlns:c14", L"http://schemas.microsoft.com/office/drawing/2007/8/2/chart"); CP_XML_NODE(L"c14:pivotOptions") { CP_XML_NODE(L"c14:dropZoneFilter") { CP_XML_ATTR(L"val", 1); } CP_XML_NODE(L"c14:dropZoneCategories") { CP_XML_ATTR(L"val", 1); } CP_XML_NODE(L"c14:dropZoneData") { CP_XML_ATTR(L"val", 1); } CP_XML_NODE(L"c14:dropZoneSeries") { CP_XML_ATTR(L"val", 1); } CP_XML_NODE(L"c14:dropZonesVisible") { CP_XML_ATTR(L"val", 1); } } } } } } if (chart_rect) { global_info_->xls_converter->xlsx_context->get_drawing_context().set_absolute_anchor( 0, 0, chart_rect->dx.dVal, chart_rect->dy.dVal); } return 0; } int ChartSheetSubstream::serialize_3D (std::wostream & _stream) { CHARTFORMATS *chart_formats = dynamic_cast(m_CHARTFORMATS.get()); if (!chart_formats) return 0; Chart3d *chart3D = NULL; BaseObjectPtr wallSpPr; BaseObjectPtr floorSpPr; for (size_t i = 0; i < chart_formats->m_arAXISPARENT.size(); i++) { AXISPARENT* parent = dynamic_cast (chart_formats->m_arAXISPARENT[i].get()); AxisParent* ax_parent = dynamic_cast (parent->m_AxisParent.get()); if (ax_parent->iax == 0) //primary axes { for (size_t i = 0 ; i < parent->m_arCRT.size() ; i++) { CRT* crt = dynamic_cast(parent->m_arCRT[i].get()); if((crt) && (crt->m_Chart3d)) { chart3D = dynamic_cast(crt->m_Chart3d.get()); break; } } AXES * axes = dynamic_cast (parent->m_AXES.get()); if (axes) { wallSpPr = axes->m_Wall_FRAME; floorSpPr = axes->m_Floor_FRAME; } } } if (!chart3D) return 0; CP_XML_WRITER(_stream) { CP_XML_NODE(L"c:view3D") { if (chart3D->anElev != 0) { CP_XML_NODE(L"c:rotX") { CP_XML_ATTR (L"val" , chart3D->anElev); } } if (chart3D->pcHeight3D != 100 && chart3D->pcHeight3D >= 5 && chart3D->pcHeight3D <= 500) { CP_XML_NODE(L"c:hPercent") { CP_XML_ATTR (L"val" , chart3D->pcHeight3D); } } if (chart3D->anRot != 0) { CP_XML_NODE(L"c:rotY") { CP_XML_ATTR (L"val" , chart3D->anRot); } } CP_XML_NODE(L"c:depthPercent") { CP_XML_ATTR (L"val" , chart3D->pcDepth); } if (chart3D->fPerspective == false) { CP_XML_NODE(L"c:rAngAx") { CP_XML_ATTR (L"val" , L"1"); } } else { CP_XML_NODE(L"c:rAngAx") { CP_XML_ATTR (L"val" , L"0"); } CP_XML_NODE(L"c:perspective") { CP_XML_ATTR (L"val" , chart3D->pcDist); } } } CP_XML_NODE(L"c:floor") { if (floorSpPr) { CP_XML_NODE(L"c:spPr") { floorSpPr->serialize(CP_XML_STREAM()); } } } CP_XML_NODE(L"c:sideWall") { if (wallSpPr) { CP_XML_NODE(L"c:spPr") { wallSpPr->serialize(CP_XML_STREAM()); } } } CP_XML_NODE(L"c:backWall") { if (wallSpPr) { CP_XML_NODE(L"c:spPr") { wallSpPr->serialize(CP_XML_STREAM()); } } } } return 0; } int ChartSheetSubstream::serialize_title (std::wostream & _stream) { CHARTFORMATS *chart_formats = dynamic_cast(m_CHARTFORMATS.get()); if (!chart_formats) return 0; BaseObjectPtr attached_label = chart_formats->find_label(1, 0xffff); //BaseObjectPtr dft_text = chart_formats->find_default_text(2); ATTACHEDLABEL * title_label = dynamic_cast(attached_label.get()); if (title_label == NULL) return 0; AI* title_text = dynamic_cast(title_label->m_AI.get()); if (title_text == NULL) return 0; if (title_text->empty()) return 0; CP_XML_WRITER(_stream) { CP_XML_NODE(L"c:title") { attached_label->serialize(CP_XML_STREAM()); } if (!title_text->m_SeriesText) { CP_XML_NODE(L"c:autoTitleDeleted") { CP_XML_ATTR (L"val" , 0); } } } return 0; } int ChartSheetSubstream::serialize_legend (std::wostream & _stream, const std::wstring & legend_entries) { CHARTFORMATS *chart_formats = dynamic_cast(m_CHARTFORMATS.get()); if (!chart_formats) return 0; AXISPARENT* parent0 = dynamic_cast(chart_formats->m_arAXISPARENT[0].get()); if (parent0 == NULL) return 0; if (parent0->m_arCRT.size() < 1) return 0; //DAT* DAT_ = dynamic_cast(chart_formats->m_DAT.get()); //Dat *dat_legend = NULL; //LD *dat_ld = NULL; //if (DAT_) //{ // dat_legend = dynamic_cast(DAT_->m_Dat.get()); // dat_ld = dynamic_cast(DAT_->m_LD.get()); //} //todooo figure out different types in one chart.. count number of series?? std::unordered_map< int, std::vector>::iterator it = m_mapTypeChart.begin(); while (it != m_mapTypeChart.end()) { CRT * crt = dynamic_cast(parent0->m_arCRT[it->first].get()); if (crt == NULL) { ++it; continue; } LD * ld = dynamic_cast(crt->m_LD.get()); if (ld == NULL) { ++it; continue; } CP_XML_WRITER(_stream) { CP_XML_NODE(L"c:legend") { ld->m_countSeries = it->second.size(); ld->serialize(CP_XML_STREAM(), legend_entries); } } break; } return 0; } int ChartSheetSubstream::serialize_plot_area (std::wostream & _stream) { CHARTFORMATS *chart_formats = dynamic_cast(m_CHARTFORMATS.get()); if (!chart_formats) return 0; if (chart_formats->m_arAXISPARENT.empty()) return 0; AXISPARENT* parent0 = dynamic_cast(chart_formats->m_arAXISPARENT[0].get()); if (parent0 == NULL) return 0; FRAME *PlotAreaFRAME = NULL; Pos *PlotAreaPos = NULL; AxisParent* ax_parent = dynamic_cast (parent0->m_AxisParent.get()); AXES* axes = dynamic_cast (parent0->m_AXES.get()); if ((ax_parent->iax == 0) && axes) //primary axes { PlotAreaFRAME = dynamic_cast (axes->m_PlotArea_FRAME.get()); PlotAreaPos = dynamic_cast (parent0->m_Pos.get()); //outer plot area if (PlotAreaPos && !parent0->m_arCRT.empty()) { CRT * crt = dynamic_cast(parent0->m_arCRT[0].get()); if ((crt) && ( crt->m_iChartType == CHART_TYPE_Radar || crt->m_iChartType == CHART_TYPE_RadarArea || crt->m_iChartType == CHART_TYPE_Scatter))//more? { PlotAreaPos->m_iLayoutTarget = 2; //inner } } if (PlotAreaPos && PlotAreaFRAME) { //FRAME *FRAME_ = dynamic_cast (chart_formats->m_FRAME.get()); PlotAreaPos->m_Frame = PlotAreaFRAME->m_Frame;//FRAME_->m_Frame; } } ShtProps *sht_props = dynamic_cast(chart_formats->m_ShtProps.get()); std::wstringstream stream_legend_entries; CP_XML_WRITER(_stream) { CP_XML_NODE(L"c:plotArea") { if ((sht_props) && (sht_props->fAlwaysAutoPlotArea != false)) { if (chart_formats->m_CrtLayout12A) { chart_formats->m_CrtLayout12A->serialize(CP_XML_STREAM()); } else if (PlotAreaPos) { PlotAreaPos->serialize(CP_XML_STREAM()); } } int series_order = 0; for (std::unordered_map>::iterator it = m_mapTypeChart.begin(); it != m_mapTypeChart.end(); ++it) { std::map::iterator pFindIndexCrt = parent0->m_mapCRTIndex.find(it->first); if (pFindIndexCrt == parent0->m_mapCRTIndex.end()) continue; CRT * crt = dynamic_cast(parent0->m_arCRT[pFindIndexCrt->second].get()); ChartFormat *format = dynamic_cast(crt->m_ChartFormat.get()); AXISPARENT *parent = dynamic_cast(chart_formats->m_arAXISPARENT[crt->m_indAXISPARENT].get()); CP_XML_NODE(crt->getOoxChartType()) { crt->m_ChartType->serialize_attribute( CP_GET_XML_NODE()); if (crt->m_iChartType == CHART_TYPE_Scatter) { serialize_scatter_style(CP_XML_STREAM(), crt); } else if (crt->m_iChartType != CHART_TYPE_Stock) { crt->m_ChartType->serialize(CP_XML_STREAM()); } format->serialize(CP_XML_STREAM()); for (size_t i = 0 ; i < it->second.size(); i++) { SERIESFORMAT * series = dynamic_cast(chart_formats->m_arSERIESFORMAT[it->second[i]].get()); if (series == NULL) continue; SS * series_ss = dynamic_cast(series->m_SS.get()); if (series_ss == NULL) continue; series_ss->apply_crt_ss(crt->m_SS); series_ss->m_is3D = crt->m_bIs3D; if (crt->m_iChartType == CHART_TYPE_Pie || crt->m_iChartType == CHART_TYPE_BopPop || crt->m_iChartType == CHART_TYPE_Doughnut || crt->m_iChartType == CHART_TYPE_Surf ) series_ss->m_isVaried = format->fVaried; DataFormat * series_data_format = dynamic_cast(series_ss->m_DataFormat.get()); int series_id = series_data_format->iss; Series * ser = dynamic_cast(series->m_Series.get()); CP_XML_NODE(L"c:ser") { CP_XML_NODE(L"c:idx") { CP_XML_ATTR (L"val" , series_id); } CP_XML_NODE(L"c:order") { CP_XML_ATTR (L"val" , series_order++); } if (!series->m_arAI.empty()) { series->m_arAI[0]->serialize(CP_XML_STREAM()); } series_ss->serialize(CP_XML_STREAM(), crt->m_iChartType, -1); serialize_dPt(CP_XML_STREAM(), it->second[i], crt, (std::max)(ser->cValx, ser->cValy));//+bubbles /* if (arPivotData.empty() == false) { series->set_ref(arPivotData, i * 2); }*/ if (series->m_arAI.size() > 1) { if (crt->m_iChartType == CHART_TYPE_Scatter || crt->m_iChartType == CHART_TYPE_Bubble) { serialize_ser(L"c:xVal", CP_XML_STREAM(), series_id, series->m_arAI[2], ser->sdtX, ser->cValx); serialize_ser(L"c:yVal", CP_XML_STREAM(), series_id, series->m_arAI[1], ser->sdtY, ser->cValy); if (crt->m_iChartType == CHART_TYPE_Bubble && series->m_arAI.size() > 2) serialize_ser(L"c:bubbleSize", CP_XML_STREAM(), series_id, series->m_arAI[3], ser->sdtBSize, ser->cValBSize); } else { serialize_ser(L"c:cat", CP_XML_STREAM(), series_id, series->m_arAI[2], ser->sdtX, ser->cValx); serialize_ser(L"c:val", CP_XML_STREAM(), series_id, series->m_arAI[1], ser->sdtY, ser->cValy); } } //----------------------------------------------------------------------------------------------------------------------------------------- series->serialize_parent(CP_XML_STREAM(), chart_formats); //----------------------------------------------------------------------------------------------------------------------------------------- std::wstringstream stream_dLbls; serialize_dLbls(stream_dLbls, it->second[i], crt); if (stream_dLbls.str().empty() == false) { CP_XML_NODE(L"c:dLbls") { CP_XML_STREAM() << stream_dLbls.str(); } } series_ss->serialize2(CP_XML_STREAM(), crt->m_iChartType); //xlsx specifics ( } series->serialize_legend(stream_legend_entries, it->second[i]); } for (size_t i = 0 ; i < crt->m_arCrtLine.size(); i++) { CrtLine* crtLine = dynamic_cast(crt->m_arCrtLine[i].get()); if (crtLine == NULL) continue; if (crtLine->id == 3) continue; // leaderLines in dLbls crtLine->m_iChartType = crt->m_iChartType; crtLine->serialize(CP_XML_STREAM()); } if (crt->m_DROPBAR[0] || crt->m_DROPBAR[1]) { CP_XML_NODE(L"c:upDownBars") { if (crt->m_DROPBAR[0]) { CP_XML_NODE(L"c:upBars") { crt->m_DROPBAR[0]->serialize(CP_XML_STREAM()); } } if (crt->m_DROPBAR[1]) { CP_XML_NODE(L"c:downBars") { crt->m_DROPBAR[1]->serialize(CP_XML_STREAM()); } } } } AXES * axes = dynamic_cast(parent->m_AXES.get()); if (axes) { for (size_t a = 0 ; a < axes->m_arAxesId.size(); a++) { CP_XML_NODE(L"c:axId") { CP_XML_ATTR(L"val", axes->m_arAxesId[a].first); } } } //else error complex_29s.xls } } for (size_t i = 0; i < chart_formats->m_arAXISPARENT.size(); i++) { AXISPARENT* parent = dynamic_cast (chart_formats->m_arAXISPARENT[i].get()); AxisParent* ax_parent = parent ? dynamic_cast(parent->m_AxisParent.get()) : NULL; AXES* axes = parent ? dynamic_cast(parent->m_AXES.get()) : NULL; if (axes) { axes->serialize(CP_XML_STREAM(), ax_parent ? (ax_parent->iax != 0) : false); //secondary } //else error complex_29s.xls } if (PlotAreaFRAME) PlotAreaFRAME->serialize(CP_XML_STREAM()); } serialize_legend (_stream, stream_legend_entries.str()); } return 0; } int ChartSheetSubstream::serialize_scatter_style(std::wostream & _stream, CRT *crt) { bool bMarker = true, bSmooth = false, bLine = true;//todooo - since there are separate settings CP_XML_WRITER(_stream) { CP_XML_NODE(L"c:scatterStyle") { if (bLine) { if (bSmooth && bMarker) CP_XML_ATTR (L"val" , L"smoothMarker"); else if (bSmooth) CP_XML_ATTR (L"val" , L"smooth"); else if (bMarker) CP_XML_ATTR (L"val" , L"lineMarker"); else CP_XML_ATTR (L"val" , L"line"); } else { if (bMarker) CP_XML_ATTR (L"val" , L"marker"); else CP_XML_ATTR (L"val" , L"none"); } } } return 0; } int ChartSheetSubstream::serialize_dPt(std::wostream & _stream, int id, CRT *crt, int count_point) { if (crt == NULL) return 0;//1 (318).xls CHARTFORMATS *chart_formats = dynamic_cast(m_CHARTFORMATS.get()); SERIESFORMAT *series = dynamic_cast(chart_formats->m_arSERIESFORMAT[id].get()); ChartFormat *format = dynamic_cast(crt->m_ChartFormat.get()); std::map present_idx; CP_XML_WRITER(_stream) { for (size_t i = 0 ; i < series->m_arPtSS.size(); i++) { CP_XML_NODE(L"c:dPt") { SS * series_ss = dynamic_cast(series->m_arPtSS[i].get()); DataFormat * series_data_format = dynamic_cast(series_ss->m_DataFormat.get()); series_ss->m_is3D = crt->m_bIs3D; if (crt->m_iChartType == CHART_TYPE_Pie || crt->m_iChartType == CHART_TYPE_BopPop || crt->m_iChartType == CHART_TYPE_Doughnut || crt->m_iChartType == CHART_TYPE_Surf ) series_ss->m_isVaried = format->fVaried; CP_XML_NODE(L"c:idx") { CP_XML_ATTR(L"val", series_data_format->xi); if (format->fVaried) present_idx.insert(std::make_pair(series_data_format->xi, true)); } series_ss->serialize (CP_XML_STREAM(), crt->m_iChartType, series_data_format->xi); //series_ss->serialize2 (CP_XML_STREAM(), crt->m_iChartType); // 3d shape box not needed - Book 78 3D.xls } } bool varied = false; if (crt->m_iChartType == CHART_TYPE_Pie || crt->m_iChartType == CHART_TYPE_BopPop || crt->m_iChartType == CHART_TYPE_Doughnut || crt->m_iChartType == CHART_TYPE_Surf ) varied = format->fVaried; if (varied && present_idx.size() < count_point) { SS * series_ss = dynamic_cast(series->m_SS.get()); int vari_color = 0; for (int i = 0 ; i < count_point; i++) { std::map::iterator it = present_idx.find(i); if (it == present_idx.end()) { CP_XML_NODE(L"c:dPt") { CP_XML_NODE(L"c:idx") { CP_XML_ATTR(L"val", i ); } series_ss->serialize_default(CP_XML_STREAM(), crt->m_iChartType, i/*vari_color++*/); } } } } } return 0; } int ChartSheetSubstream::serialize_dLbls (std::wostream & _stream, int id, CRT *crt) { CHARTFORMATS *chart_formats = dynamic_cast(m_CHARTFORMATS.get()); SERIESFORMAT *series = dynamic_cast(chart_formats->m_arSERIESFORMAT[id].get()); SS *series_ss = dynamic_cast(series->m_SS.get()); DataFormat *series_df = dynamic_cast(series_ss->m_DataFormat.get()); bool is_area = (crt->m_iChartType == CHART_TYPE_Area || crt->m_iChartType == CHART_TYPE_RadarArea || crt->m_iChartType == CHART_TYPE_Bar); int series_id = series_df->iss; std::vector> labels = chart_formats->find_labels ( 4, id); bool add_labels = false; bool need_add_labels = false; CP_XML_WRITER(_stream) { Text * text = NULL; AttachedLabel * att_label = dynamic_cast(series_ss->m_AttachedLabel.get()); ATTACHEDLABEL * AT_LABEL = dynamic_cast(chart_formats->find_label(4, id).get()); if (AT_LABEL) text = dynamic_cast (AT_LABEL->m_TextProperties.get()); if (att_label) { att_label->is_area = is_area; series_ss->m_AttachedLabel->serialize(_stream); add_labels = true; } else { if ((AT_LABEL) && (AT_LABEL->m_FRAME)) { AT_LABEL->m_FRAME->serialize(_stream); add_labels = true; } DataLabExtContents * data_ext_cont = NULL; if (!data_ext_cont && AT_LABEL) data_ext_cont = dynamic_cast(AT_LABEL->m_DataLabExtContents.get()); if (!data_ext_cont && crt) data_ext_cont = dynamic_cast(crt->m_DataLabExtContents.get()); if (data_ext_cont) { data_ext_cont->is_area = is_area; data_ext_cont->serialize(_stream); add_labels = true; } else if (text) { text->is_area = is_area; text->serialize(_stream); add_labels = true; } else if (!labels.empty()) {//there are labels for individual points, but general ones are not marked need_add_labels = true; } } Pie *pie = dynamic_cast(crt->m_ChartType.get()); if (text) { if (text->dlp > 0 && text->dlp < 9 && !crt->m_Chart3d) { CP_XML_NODE(L"c:dLblPos") { switch(text->dlp) { case 1: CP_XML_ATTR(L"val", L"outEnd"); break; case 2: CP_XML_ATTR(L"val", L"inEnd"); break; case 3: CP_XML_ATTR(L"val", L"ctr"); break; case 4: CP_XML_ATTR(L"val", L"inBase"); break; case 5: CP_XML_ATTR(L"val", L"t"); break; case 6: CP_XML_ATTR(L"val", L"b"); break; case 7: CP_XML_ATTR(L"val", L"l"); break; case 8: CP_XML_ATTR(L"val", L"r"); break; } } } CP_XML_NODE(L"c:showLegendKey") {CP_XML_ATTR(L"val", text->fShowKey);} need_add_labels = true; } if ( (pie) && (pie->fShowLdrLines) ) { CP_XML_NODE(L"c:showLeaderLines") {CP_XML_ATTR(L"val", pie->fShowLdrLines);} need_add_labels = true; } if (!add_labels && need_add_labels) { CP_XML_NODE(L"c:showLegendKey") { CP_XML_ATTR (L"val" , 0); } CP_XML_NODE(L"c:showVal") { CP_XML_ATTR (L"val" , 0); } CP_XML_NODE(L"c:showPercent") { CP_XML_ATTR (L"val" , 0); } CP_XML_NODE(L"c:showBubbleSize"){ CP_XML_ATTR (L"val" , 0); } CP_XML_NODE(L"c:showCatName") { CP_XML_ATTR (L"val" , 0); } CP_XML_NODE(L"c:showSerName") { CP_XML_ATTR (L"val" , 0); } } //labels for points (individual) for (size_t i = 0; i < labels.size(); i++) { CP_XML_NODE(L"c:dLbl") { CP_XML_NODE(L"c:idx") {CP_XML_ATTR(L"val", labels[i].first);} Text * text = NULL; ATTACHEDLABEL* AT_LABEL = dynamic_cast(labels[i].second.get()); if (AT_LABEL) { //if (AT_LABEL->m_CrtLayout12) AT_LABEL->m_CrtLayout12->serialize(_stream); //else //if (AT_LABEL->m_Pos) AT_LABEL->m_Pos->serialize(_stream); text = dynamic_cast (AT_LABEL->m_TextProperties.get()); if (AT_LABEL->m_FRAME) AT_LABEL->m_FRAME->serialize(_stream); AT_LABEL->serialize_txPr(CP_XML_STREAM()); if (text) { CP_XML_NODE(L"c:showLegendKey") {CP_XML_ATTR(L"val", text->fShowKey);} } else CP_XML_NODE(L"c:showLegendKey") {CP_XML_ATTR(L"val", 0);} } DataLabExtContents * data_ext_cont = dynamic_cast(crt->m_DataLabExtContents.get()); if (!data_ext_cont && AT_LABEL) data_ext_cont = dynamic_cast(AT_LABEL->m_DataLabExtContents.get()); if (data_ext_cont) { data_ext_cont->is_area = is_area; data_ext_cont->serialize(_stream); } else if (text) { text->is_area = is_area; text->serialize(_stream); } } } for (size_t i = 0 ; i < crt->m_arCrtLine.size(); i++) { CrtLine* crtLine = dynamic_cast(crt->m_arCrtLine[i].get()); if (crtLine == NULL) continue; if (crtLine->id != 3) continue; // only leaderLines in dLbls crtLine->m_iChartType = crt->m_iChartType; crtLine->serialize(_stream); } } return 0; } int ChartSheetSubstream::serialize_ser (std::wstring sNodeSer, std::wostream & _stream, int series_id, const BaseObjectPtr & ai_, int type, int count) { int result = 0; AI * ai = dynamic_cast(ai_.get()); BRAI * brai = dynamic_cast(ai->m_BRAI.get()); std::wstring formula = brai->formula.getAssembledFormula(true); int rt = brai->rt; bool b = brai->fUnlinkedIfmt; int fmt = brai->ifmt; //id // 0 - name // 1 - val || yVal // 2 - cat || xVal // 3 - bubble size SERIESDATA * series_data = dynamic_cast(m_SERIESDATA.get()); SIIndex * series_cash = NULL; int type_val = 0; for (size_t i = 0; (series_data) && (i < series_data->m_arSIIndex.size()); i++) { SIIndex * si_in = dynamic_cast(series_data->m_arSIIndex[i].get()); int a1 = si_in->numIndex; int a2 = brai->id; if (a1 == a2) { if (si_in->m_arData.empty() == false) { switch(si_in->m_arData[0]->get_type()) { case typeNumber: type_val = 1; break; case typeBoolErr: type_val = 2; break; case typeBlank: type_val = 3; break; case typeLabel: type_val = 4; break; default: break; } series_cash = si_in; } break; } } std::wstringstream _stream_cash; int count_found = 0; if ((series_cash) && (!series_cash->m_arData.empty())) { for (int i =0; i < count; i++) { CellRef ref( i, series_id , true, true); if (series_cash->serialize(_stream_cash, i, ref.toString()) == 1) count_found++; } } if ((formula.empty()) && count_found > 0) { std::wstring sNodeLit; if (type == 1 ) sNodeLit = L"c:numLit"; if (type == 3 ) sNodeLit = L"c:strLit"; CP_XML_WRITER(_stream) { CP_XML_NODE(sNodeSer) { CP_XML_NODE(sNodeLit) { //CP_XML_NODE(L"c:formatCode") { CP_XML_STREAM() << L"General"; } CP_XML_NODE(L"c:ptCount") { CP_XML_ATTR(L"val", count); // cannot use count_found - must be maximum of all report points } CP_XML_STREAM() << _stream_cash.str(); result = 1; } } } } else if (!formula.empty()) { std::wstring sNodeRef; if (type == 1) sNodeRef = L"c:numRef"; if (type == 3) sNodeRef = L"c:strRef"; CP_XML_WRITER(_stream) { CP_XML_NODE(sNodeSer) { CP_XML_NODE(sNodeRef) { //CP_XML_NODE(L"c:formatCode") { CP_XML_STREAM() << L"General"; } CP_XML_NODE(L"c:f") { CP_XML_STREAM() << formula; } if (count_found > 0) { if (type == 1) sNodeRef = L"c:numCache"; if (type == 3) sNodeRef = L"c:strCache"; CP_XML_NODE(sNodeRef) { CP_XML_NODE(L"c:ptCount") { CP_XML_ATTR(L"val", count); // cannot use count_found - must be maximum of all report points } CP_XML_STREAM() << _stream_cash.str(); } } result = 1; } } } } return result; } } // namespace XLS