Files
Yajbir Singh f1b860b25c
check / markdownlint (push) Has been cancelled
check / spellchecker (push) Has been cancelled
updated
2025-12-11 19:03:17 +05:30

2734 lines
85 KiB
C++

/*
* (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 "XlsConverter.h"
#include "../Format/Binary/CompoundFile.h"
#include "../Format/Binary/CFStreamCacheReader.h"
#include "../Format/Logic/GlobalWorkbookInfo.h"
#include "../Format/Logic/WorkbookStreamObject.h"
#include "../Format/Logic/WorksheetSubstream.h"
#include "../Format/Logic/GlobalsSubstream.h"
#include "../Format/Logic/ChartSheetSubstream.h"
#include "../Format/Logic/MacroSheetSubstream.h"
#include "../Format/Logic/EncryptionStream.h"
#include "../Format/Logic/BinProcessor.h"
#include "../../Common/SummaryInformation/PropertySetStream.h"
#include "../Format/Logic/Biff_unions/FORMATTING.h"
#include "../Format/Logic/Biff_unions/THEME.h"
#include "../Format/Logic/Biff_unions/GLOBALS.h"
#include "../Format/Logic/Biff_unions/COLUMNS.h"
#include "../Format/Logic/Biff_unions/SHAREDSTRINGS.h"
#include "../Format/Logic/Biff_unions/HLINK.h"
#include "../Format/Logic/Biff_unions/LBL.h"
#include "../Format/Logic/Biff_unions/OBJECTS.h"
#include "../Format/Logic/Biff_unions/MSODRAWINGGROUP.h"
#include "../Format/Logic/Biff_unions/OBJ.h"
#include "../Format/Logic/Biff_unions/IMDATAOBJECT.h"
#include "../Format/Logic/Biff_unions/TEXTOBJECT.h"
#include "../Format/Logic/Biff_unions/CHART.h"
#include "../Format/Logic/Biff_unions/BACKGROUND.h"
#include "../Format/Logic/Biff_unions/PIVOTVIEW.h"
#include "../Format/Logic/Biff_unions/PIVOTCACHE.h"
#include "../Format/Logic/Biff_unions/PIVOTCACHEDEFINITION.h"
#include "../Format/Logic/Biff_unions/SUPBOOK.h"
#include "../Format/Logic/Biff_unions/QUERYTABLE.h"
#include "../Format/Logic/Biff_unions/FEAT.h"
#include "../Format/Logic/Biff_unions/FEAT11.h"
#include "../Format/Logic/Biff_records/BkHim.h"
#include "../Format/Logic/Biff_records/HLink.h"
#include "../Format/Logic/Biff_records/MsoDrawingGroup.h"
#include "../Format/Logic/Biff_records/MsoDrawing.h"
#include "../Format/Logic/Biff_records/Obj.h"
#include "../Format/Logic/Biff_records/TxO.h"
#include "../Format/Logic/Biff_records/IMDATA.h"
#include "../Format/Logic/Biff_records/Note.h"
#include "../Format/Logic/Biff_records/WsBool.h"
#include "../Format/Logic/Biff_records/Theme.h"
#include "../Format/Logic/Biff_records/Format.h"
#include "../Format/Logic/Biff_records/CalcMode.h"
#include "../Format/Logic/Biff_structures/URLMoniker.h"
#include "../Format/Logic/Biff_structures/FileMoniker.h"
#include "../Format/Logic/Biff_structures/ODRAW/OfficeArtBStoreContainer.h"
#include "../Format/Logic/Biff_structures/ODRAW/SimpleOfficeArtContainers.h"
#include "../Format/Logic/Biff_structures/ODRAW/OfficeArtFOPT.h"
#include "../Format/Logic/Biff_structures/ODRAW/OfficeArtFOPTE.h"
#include "../Format/Logic/Biff_structures/ODRAW/OfficeArtTertiaryFOPT.h"
#include "../Format/Logic/Biff_structures/ODRAW/OfficeArtFSP.h"
#include "../Format/Logic/Biff_structures/ODRAW/OfficeArtBlip.h"
#include "../Format/Logic/Biff_structures/ODRAW/OfficeArtFSPGR.h"
#include "../Format/Logic/Biff_structures/ODRAW/OfficeArtClientAnchorSheet.h"
#include "../Format/Logic/Biff_structures/ODRAW/OfficeArtClientAnchorHF.h"
#include "xlsx_conversion_context.h"
#include "xlsx_package.h"
#include "../../Common/Utils/simple_xml_writer.h"
#include "../../../OOXML/Base/Unit.h"
#include "../../../DesktopEditor/common/File.h"
#include "../../../DesktopEditor/raster/BgraFrame.h"
#include <boost/make_shared.hpp>
#if !defined(_WIN32) && !defined(_WIN64)
typedef struct tagBITMAPINFOHEADER
{
_UINT32 biSize;
_INT32 biWidth;
_INT32 biHeight;
_UINT16 biPlanes;
_UINT16 biBitCount;
_UINT32 biCompression;
_UINT32 biSizeImage;
_INT32 biXPelsPerMeter;
_INT32 biYPelsPerMeter;
_UINT32 biClrUsed;
_UINT32 biClrImportant;
} BITMAPINFOHEADER;
typedef struct tagBITMAPCOREHEADER {
_UINT32 bcSize; /* used to get to color table */
_UINT16 bcWidth;
_UINT16 bcHeight;
_UINT16 bcPlanes;
_UINT16 bcBitCount;
} BITMAPCOREHEADER;
#endif
XlsConverter::XlsConverter()
{
output_document = NULL;
xlsx_context = NULL;
is_older_version = false;
is_encrypted = false;
}
XlsConverter::XlsConverter(const std::wstring & xlsFileName, const std::wstring & xlsxFilePath, const std::wstring & password, const std::wstring & fontsPath, const std::wstring & tempPath, const int lcid_user, bool & bMacros)
{
xlsx_path = xlsxFilePath;
output_document = NULL;
xlsx_context = NULL;
is_older_version = false;
is_encrypted = false;
output_document = new oox::package::xlsx_document();
_UINT16 workbook_code_page = XLS::WorkbookStreamObject::DefaultCodePage;
try
{
xls_file = boost::shared_ptr<XLS::CompoundFile>(new XLS::CompoundFile(xlsFileName, XLS::CompoundFile::cf_ReadMode));
if (xls_file->isError())
{
xls_global_info = boost::shared_ptr<XLS::GlobalWorkbookInfo>(new XLS::GlobalWorkbookInfo(workbook_code_page, this));
xls_global_info->lcid_user = lcid_user;
xls_global_info->fontsDirectory = fontsPath;
xls_global_info->password = password;
xls_global_info->tempDirectory = tempPath;
xls_global_info->CodePage = 0;
xls_global_info->Version = 0;
XLS::GlobalWorkbookInfo::_sheet_info sheet_info;
xls_global_info->sheets_info.push_back(sheet_info);
XLS::StreamCacheReaderPtr file_reader(new XLS::FileStreamCacheReader(xlsFileName, xls_global_info));
xls_document = boost::shared_ptr<XLS::WorkbookStreamObject>(new XLS::WorkbookStreamObject(workbook_code_page));
XLS::BinReaderProcessor proc(file_reader, xls_document.get(), true);
XLS::BaseObjectPtr stream = XLS::BaseObjectPtr(new XLS::WorksheetSubstream(0));
if (proc.mandatory(*stream.get()))
{
XLS::WorksheetSubstream *worksheet = dynamic_cast<XLS::WorksheetSubstream*>(stream.get());
XLS::WorkbookStreamObject *workbook = dynamic_cast<XLS::WorkbookStreamObject*>(xls_document.get());
if (workbook)
{
workbook->m_arWorksheetSubstream.push_back(stream);
workbook->m_GlobalsSubstream = XLS::BaseObjectPtr(new XLS::GlobalsSubstream(0));
XLS::GlobalsSubstream* globals = dynamic_cast<XLS::GlobalsSubstream*>(workbook->m_GlobalsSubstream.get());
if (globals)
{
globals->m_Formating = worksheet->m_Formating;
globals->UpdateXFC();
}
}
}
else
{
return;
}
}
else
{
OLEPS::PropertySetStream summary_stream;
summary_stream.read(xls_file->getNamedStream(L"SummaryInformation"));
summary_stream.read(xls_file->getNamedStream(L"DocumentSummaryInformation"), true);
workbook_code_page = summary_stream.GetCodePage();
output_document->get_docProps_files().set_app_content(summary_stream.GetApp());
output_document->get_docProps_files().set_core_content(summary_stream.GetCore());
//--------------------------------------------------------------------------------------------------------------------
if( 0/*error*/ == workbook_code_page)//|| 65001 /*UTF-8*/ == workbook_code_page || 1200/* UTF-16 */ == workbook_code_page
{
workbook_code_page = XLS::WorkbookStreamObject::DefaultCodePage;
}
xls_global_info = boost::shared_ptr<XLS::GlobalWorkbookInfo>(new XLS::GlobalWorkbookInfo(workbook_code_page, this));
xls_global_info->lcid_user = lcid_user;
xls_global_info->fontsDirectory = fontsPath;
xls_global_info->password = password;
xls_global_info->tempDirectory = tempPath;
//--------------------------------------------------------------------------------------------------------------------
XLS::StreamCacheReaderPtr workbook_stream(new XLS::CFStreamCacheReader(xls_file->getWorkbookStream(), xls_global_info));
xls_document = boost::shared_ptr<XLS::WorkbookStreamObject>(new XLS::WorkbookStreamObject(workbook_code_page));
XLS::BinReaderProcessor workbook_proc(workbook_stream, xls_document.get() , true);
if (false == workbook_proc.mandatory(*xls_document.get()))
{
// test open list
xls_file->getWorkbookStream()->seekFromBegin(0);
XLS::StreamCacheReaderPtr worksheet_stream(new XLS::CFStreamCacheReader(xls_file->getWorkbookStream(), xls_global_info));
XLS::BaseObjectPtr worksheet_object = XLS::BaseObjectPtr(new XLS::WorksheetSubstream(0));
XLS::BinReaderProcessor worksheet_proc(worksheet_stream, xls_document.get(), true);
if (worksheet_proc.mandatory(*worksheet_object.get()))
{
XLS::WorksheetSubstream* worksheet = dynamic_cast<XLS::WorksheetSubstream*>(worksheet_object.get());
XLS::WorkbookStreamObject* workbook = dynamic_cast<XLS::WorkbookStreamObject*>(xls_document.get());
if (workbook)
{
workbook->m_arWorksheetSubstream.push_back(worksheet_object);
workbook->m_GlobalsSubstream = XLS::BaseObjectPtr(new XLS::GlobalsSubstream(0));
XLS::GlobalsSubstream* globals = dynamic_cast<XLS::GlobalsSubstream*>(workbook->m_GlobalsSubstream.get());
if (globals)
{
globals->m_Formating = worksheet->m_Formating;
globals->UpdateXFC();
}
}
}
else
{
return; //error
}
}
if (xls_global_info->decryptor)
{
is_encrypted = true;
if (xls_global_info->decryptor->IsVerify() == false) return;
}
//--------------------------------------------------------------------------------------------------------------------
XLS::EncryptionSummaryStream encryption_summary(xls_file->getNamedStream(L"encryption"), xls_global_info->decryptor);
//--------------------------------------------------------------------------------------------------------------------
if (xls_file->storage_->isDirectory(L"_SX_DB_CUR"))
{
std::list<std::wstring> listStream = xls_file->storage_->entries(L"_SX_DB_CUR");
int last_index = 0;
for (std::list<std::wstring>::iterator it = listStream.begin(); it != listStream.end(); ++it)
{
XLS::CFStreamPtr pivot_cache_stream = xls_file->getNamedStream(L"_SX_DB_CUR/" + *it);
if (!pivot_cache_stream) continue;
//if (pivot_cache_stream->getStreamSize() < 1) continue;
XLS::StreamCacheReaderPtr pivot_cache_reader(new XLS::CFStreamCacheReader(pivot_cache_stream, xls_global_info));
XLS::BaseObjectPtr pivot_cache = boost::shared_ptr<XLS::PIVOTCACHE>(new XLS::PIVOTCACHE());
XLS::BinReaderProcessor proc(pivot_cache_reader , pivot_cache.get(), true);
proc.mandatory(*pivot_cache.get());
int index = XmlUtils::GetHex(*it); //hexadecimal digits uniquely identifying
xls_global_info->mapPivotCacheStream.insert(std::make_pair(index, pivot_cache));
last_index = index;
}
}
if (bMacros)
{
if (xls_file->storage_->isDirectory(L"_VBA_PROJECT_CUR"))
{
// if false == global_info_->bVbaProjectExist ??
std::wstring xl_path = xlsx_path + FILE_SEPARATOR_STR + L"xl";
NSDirectory::CreateDirectory(xl_path.c_str());
std::wstring sVbaProjectFile = xl_path + FILE_SEPARATOR_STR + L"vbaProject.bin";
POLE::Storage *storageVbaProject = new POLE::Storage(sVbaProjectFile.c_str());
if ((storageVbaProject) && (storageVbaProject->open(true, true)))
{
xls_file->copy(0, L"_VBA_PROJECT_CUR/", storageVbaProject, false);
storageVbaProject->close();
delete storageVbaProject;
output_document->get_xl_files().add_vba_project();
}
}
else if (xls_global_info->bMacrosExist)
output_document->get_xl_files().set_macros_enabled();
else
bMacros = false;
}
XLS::CFStreamPtr controls = xls_file->getNamedStream(L"Ctls");
if(controls)
{
unsigned long size = controls->getStreamSize();
boost::shared_array<BYTE> buffer(new BYTE[size]);
controls->read(buffer.get(), size);
xls_global_info->controls_data = std::make_pair(buffer, size);
}
else
{
xls_global_info->controls_data = encryption_summary.GetStream(L"Ctls");
}
XLS::CFStreamPtr listdata = xls_file->getNamedStream(L"List Data");
if(listdata)
{
unsigned long size = listdata->getStreamSize();
boost::shared_array<BYTE> buffer(new BYTE[size]);
listdata->read(buffer.get(), size);
xls_global_info->listdata_data = std::make_pair(buffer, size);
}
else
{
xls_global_info->listdata_data = encryption_summary.GetStream(L"List Data");
}
if (xls_file->storage_->isDirectory(L"MsoDataStore"))
{
std::list<std::wstring> msoStores = xls_file->storage_->entries(L"MsoDataStore");
int index = 0;
for (std::list<std::wstring>::iterator it = msoStores.begin(); it != msoStores.end(); ++it)
{
XLS::CFStreamPtr item_stream = xls_file->getNamedStream(L"MsoDataStore/" + *it + L"/Item");
XLS::CFStreamPtr props_stream = xls_file->getNamedStream(L"MsoDataStore/" + *it + L"/Properties");
if (!item_stream || !props_stream) continue;
unsigned long item_size = item_stream->getStreamSize();
unsigned long props_size = props_stream->getStreamSize();
oox::package::customXml_content_ptr content = oox::package::customXml_content::create();
char *item_buffer = new char[item_size];
if (item_buffer)
{
item_stream->read(item_buffer, item_size);
content->set_item(item_buffer, item_size);
delete []item_buffer;
}
char *props_buffer = new char[props_size];
if (props_buffer)
{
props_stream->read(props_buffer, props_size);
content->set_props(props_buffer, props_size);
delete []props_buffer;
}
output_document->add_customXml(content);
}
}
XLS::CFStreamPtr toolbar_data = xls_file->getNamedStream(L"XCB");
if(toolbar_data)
{
std::wstring xl_path = xlsx_path + FILE_SEPARATOR_STR + L"xl";
NSDirectory::CreateDirectory(xl_path.c_str());
std::wstring sToolbarsFile = xl_path + FILE_SEPARATOR_STR + L"attachedToolbars.bin";
NSFile::CFileBinary file;
if (file.CreateFileW(sToolbarsFile))
{
unsigned long size = toolbar_data->getStreamSize();
boost::shared_array<BYTE> buffer(new BYTE[size]);
toolbar_data->read(buffer.get(), size);
file.WriteFile(buffer.get(), size);
file.CloseFile();
output_document->get_xl_files().add_attachedToolbars();
}
}
}
}
catch(...)
{
return;
}
if (xls_global_info->Version < 0x0600)
{
std::wstring sVer = STR::int2hex_wstr(xls_global_info->Version);
Log::error("Version xls is old !!! - " + std::string(sVer.begin(), sVer.end()));
is_older_version = true;
}
xlsx_context = new oox::xlsx_conversion_context(output_document);
}
XlsConverter::~XlsConverter()
{
if (xlsx_context) delete xlsx_context;
if (output_document) delete output_document;
}
bool XlsConverter::isError()
{
if (!xlsx_context) return true;
if (!output_document) return true;
return false;
}
void XlsConverter::write()
{
if (!output_document)return;
output_document->write(xlsx_path);
delete output_document; output_document = NULL;
}
void XlsConverter::convertDocument()
{
if (!xls_document) return;
if (!output_document) return;
if (!xlsx_context) return;
xlsx_context->start_document();
convert((XLS::WorkbookStreamObject*)xls_document.get());
xlsx_context->end_document();
}
void XlsConverter::convert(XLS::BaseObject *xls_unknown)
{
if (xls_unknown == NULL) return;
XLS::ElementType type = xls_unknown->get_type();
switch (type)
{
case XLS::typeHLINK:
{
XLS::HLINK * hlink = dynamic_cast<XLS::HLINK*>(xls_unknown);
convert(hlink);
}break;
case XLS::typeLBL:
{
XLS::LBL * lbl = dynamic_cast<XLS::LBL*>(xls_unknown);
convert(lbl);
}break;
case XLS::typeOBJECTS:
{
XLS::OBJECTS * obj = dynamic_cast<XLS::OBJECTS*>(xls_unknown);
convert(obj, NULL);
}break;
case XLS::typeTxO:
{
XLS::TxO * txo = dynamic_cast<XLS::TxO*>(xls_unknown);
convert(txo);
}break;
case XLS::typeObj:
{
XLS::Obj * obj = dynamic_cast<XLS::Obj*>(xls_unknown);
convert(obj);
}break;
case XLS::typeAnyObject:
default:
{
for (std::list<XLS::BaseObjectPtr>::iterator it = xls_unknown->elements_.begin(); it != xls_unknown->elements_.end(); ++it)
{
(*it)->serialize(xlsx_context->current_sheet().sheetData());
}
}
}
}
void XlsConverter::convert(XLS::WorkbookStreamObject* woorkbook)
{
if (woorkbook == NULL) return;
convert(dynamic_cast<XLS::GlobalsSubstream*>(woorkbook->m_GlobalsSubstream.get()));
for (size_t i = 0 ; i < woorkbook->m_arWorksheetSubstream.size(); i++)
{
xlsx_context->start_sheet();
convert(dynamic_cast<XLS::WorksheetSubstream*>(woorkbook->m_arWorksheetSubstream[i].get()));
xlsx_context->end_sheet();
}
for (size_t i = 0 ; i < woorkbook->m_arChartSheetSubstream.size(); i++)
{
xlsx_context->start_sheet();
convert_chart_sheet(dynamic_cast<XLS::ChartSheetSubstream*>(woorkbook->m_arChartSheetSubstream[i].get()));
xlsx_context->end_sheet();
}
for (size_t i = 0 ; i < woorkbook->m_arMacroSheetSubstream.size(); i++)
{
xlsx_context->start_sheet();
convert(dynamic_cast<XLS::MacroSheetSubstream*>(woorkbook->m_arMacroSheetSubstream[i].get()));
xlsx_context->end_sheet();
}
for (std::list<XLS::BaseObjectPtr>::iterator it = woorkbook->elements_.begin(); it != woorkbook->elements_.end(); ++it)
{
convert(it->get());
}
xlsx_context->add_connections(xls_global_info->connections_stream.str());
}
void XlsConverter::convert_common (XLS::CommonSubstream* sheet)
{
if (sheet == NULL) return;
xls_global_info->current_sheet = sheet->ws_index_ + 1;
XLS::GLOBALS *globals = dynamic_cast<XLS::GLOBALS *>(sheet->m_GLOBALS.get());
if (globals)
{
globals->serialize_formatPr(xlsx_context->current_sheet().sheetFormat());
if (xlsx_context->workbook_calcpr().rdbuf()->in_avail() == 0)
globals->serialize_calcPr(xlsx_context->workbook_calcpr());
}
if (!sheet->m_arWINDOW.empty())
{
sheet->m_arWINDOW[0]->serialize(xlsx_context->current_sheet().sheetViews());
}
sheet->serialize_format(xlsx_context->current_sheet().sheetProperties());
if (sheet->m_PROTECTION)
{
sheet->m_PROTECTION->serialize(xlsx_context->current_sheet().protection());
}
if (sheet->m_COLUMNS)
{
sheet->m_COLUMNS->serialize(xlsx_context->current_sheet().cols());
}
if (sheet->m_CELLTABLE)
{
sheet->m_CELLTABLE->serialize(xlsx_context->current_sheet().sheetData());
}
if (sheet->m_SORTANDFILTER)
{
sheet->m_SORTANDFILTER->serialize(xlsx_context->current_sheet().sheetSortAndFilters());
}
if (sheet->m_PAGESETUP)
{
sheet->m_PAGESETUP->serialize(xlsx_context->current_sheet().pageProperties());
}
if (globals)
{
if (globals->m_HorizontalPageBreaks)
{
globals->m_HorizontalPageBreaks->serialize(xlsx_context->current_sheet().pageProperties());
}
if (globals->m_VerticalPageBreaks)
{
globals->m_VerticalPageBreaks->serialize(xlsx_context->current_sheet().pageProperties());
}
//if (globals->m_CalcMode)
//{
// CP_XML_WRITER(xlsx_context->current_sheet().sheetCalcPr())
// {
// CP_XML_NODE(L"sheetCalcPr")
// {
// XLS::CalcMode *calcMode = dynamic_cast<XLS::CalcMode *>(globals->m_CalcMode.get());
// CP_XML_ATTR(L"fullCalcOnLoad", calcMode->nAutoRecalc > 0 ? 1 : 0);
// }
// }
//}
}
if (sheet->m_arCUSTOMVIEW.size() > 0)
{
CP_XML_WRITER(xlsx_context->current_sheet().customViews())
{
CP_XML_NODE(L"customSheetViews")
{
for (size_t i = 0 ; i < sheet->m_arCUSTOMVIEW.size(); i++)
{
sheet->m_arCUSTOMVIEW[i]->serialize(CP_XML_STREAM());
}
}
}
}
if (sheet->m_BACKGROUND)
{
convert(dynamic_cast<XLS::BACKGROUND*>(sheet->m_BACKGROUND.get()));
}
for (size_t i = 0 ; i < sheet->m_arHFPictureDrawing.size(); i++)
{
convert((ODRAW::OfficeArtDgContainer*)sheet->m_arHFPictureDrawing[i].get());
}
//for (size_t i = 0 ; i < sheet->m_arFEAT.size(); i++)
//{
// convert(dynamic_cast<XLS::FEAT*>(sheet->m_arFEAT.get()));
//}
for (size_t i = 0 ; i < sheet->m_arFEAT11.size(); i++)
{
convert(dynamic_cast<XLS::FEAT11*>(sheet->m_arFEAT11[i].get()));
}
}
void XlsConverter::convert (XLS::WorksheetSubstream* sheet)
{
if (sheet == NULL) return;
if (xls_global_info->sheets_info.empty()) return;
std::wstring name = xls_global_info->sheets_info[sheet->ws_index_].name;
if (name.empty())
name = L"Sheet_" + std::to_wstring(sheet->ws_index_ + 1);
xlsx_context->set_sheet_type(1);
xlsx_context->set_sheet_name(name) ;
xlsx_context->set_sheet_id(sheet->ws_index_ + 1);
xlsx_context->set_sheet_state(xls_global_info->sheets_info[sheet->ws_index_].state);
if (sheet->m_GLOBALS)
{
XLS::GLOBALS * globals = dynamic_cast<XLS::GLOBALS *>(sheet->m_GLOBALS.get());
XLS::COLUMNS * columns = dynamic_cast<XLS::COLUMNS *>(sheet->m_COLUMNS.get());
if (columns)
{
globals->m_DefColWidth = columns->m_DefColWidth;
}
globals->m_DxGCol = sheet->m_DxGCol;
if (globals->is_dialog)
xlsx_context->set_sheet_type(2);
}
convert_common(dynamic_cast<XLS::CommonSubstream*>(sheet));
convert((XLS::OBJECTS*)sheet->m_OBJECTS.get(), sheet);
if (sheet->m_Dimensions)
{
sheet->m_Dimensions->serialize(xlsx_context->current_sheet().dimension());
}
if (sheet->m_arMergeCells.size() > 0)
{
CP_XML_WRITER(xlsx_context->current_sheet().mergeCells())
{
CP_XML_NODE(L"mergeCells")
{
for (size_t i = 0 ; i < sheet->m_arMergeCells.size(); i++)
{
sheet->m_arMergeCells[i]->serialize(CP_XML_STREAM());
}
}
}
}
for (size_t i = 0 ; i < sheet->m_arHLINK.size(); i++)
{
convert((XLS::HLINK*)sheet->m_arHLINK[i].get());
}
if (sheet->m_CONDFMTS)
{
sheet->m_CONDFMTS->serialize(xlsx_context->current_sheet().conditionalFormatting());
}
if (sheet->m_DVAL)
{
sheet->m_DVAL->serialize(xlsx_context->current_sheet().dataValidations());
}
if (!sheet->m_arNote.empty() && xls_global_info->Version < 0x0600)
{
xlsx_context->get_drawing_context().start_drawing(0);
for (size_t i = 0 ; i < sheet->m_arNote.size(); i++)
{
xlsx_context->get_drawing_context().start_drawing(0x0019);
convert(dynamic_cast<XLS::Note*>(sheet->m_arNote[i].get()));
xlsx_context->get_drawing_context().end_drawing();
}
xlsx_context->get_drawing_context().end_group();
}
for (size_t i = 0; i < sheet->m_arQUERYTABLE.size(); i++)
{
convert(dynamic_cast<XLS::QUERYTABLE*>(sheet->m_arQUERYTABLE[i].get()));
}
for (size_t i = 0; i < sheet->m_arPIVOTVIEW.size(); i++)
{
convert((XLS::PIVOTVIEW*)sheet->m_arPIVOTVIEW[i].get());
}
}
void XlsConverter::convert (XLS::MacroSheetSubstream* sheet)
{
if (sheet == NULL) return;
xls_global_info->current_sheet = sheet->ws_index_ + 1;
std::wstring name = xls_global_info->sheets_info[sheet->ws_index_].name;
if (name.empty())
name = L"MacroSheet_" + std::to_wstring(sheet->ws_index_ + 1);
xlsx_context->set_sheet_type(4);
xlsx_context->set_sheet_name(name) ;
xlsx_context->set_sheet_id(sheet->ws_index_ + 1);
xlsx_context->set_sheet_state(xls_global_info->sheets_info[sheet->ws_index_].state);
if (sheet->m_GLOBALS)
{
XLS::GLOBALS * globals = dynamic_cast<XLS::GLOBALS *>(sheet->m_GLOBALS.get());
XLS::COLUMNS * columns = dynamic_cast<XLS::COLUMNS *>(sheet->m_COLUMNS.get());
if (columns)
{
globals->m_DefColWidth = columns->m_DefColWidth;
}
globals->m_DxGCol = sheet->m_DxGCol;
if (globals->is_dialog)
xlsx_context->set_sheet_type(2);
}
convert_common(dynamic_cast<XLS::CommonSubstream*>(sheet));
convert((XLS::OBJECTS*)sheet->m_OBJECTS.get(), NULL);
if (sheet->m_Dimensions)
{
sheet->m_Dimensions->serialize(xlsx_context->current_sheet().dimension());
}
if (!sheet->m_arNote.empty() && xls_global_info->Version < 0x0600)
{
xlsx_context->get_drawing_context().start_drawing(0);
for (size_t i = 0 ; i < sheet->m_arNote.size(); i++)
{
xlsx_context->get_drawing_context().start_drawing(0x0019);
convert(dynamic_cast<XLS::Note*>(sheet->m_arNote[i].get()));
xlsx_context->get_drawing_context().end_drawing();
}
xlsx_context->get_drawing_context().end_group();
}
}
void XlsConverter::convert(XLS::GlobalsSubstream* globals)
{
if (globals == NULL) return;
convert_theme();
convert((XLS::FORMATTING*)globals->m_Formating.get());
convert((XLS::SHAREDSTRINGS*)globals->m_SHAREDSTRINGS.get());
for (size_t i = 0 ; i < globals->m_arLBL.size(); i++)
{
convert((XLS::LBL*)globals->m_arLBL[i].get());
}
for (size_t i = 0 ; i < globals->m_arMSODRAWINGGROUP.size(); i++)
{
convert((XLS::MSODRAWINGGROUP*)globals->m_arMSODRAWINGGROUP[i].get());
}
for (size_t i = 0 ; i < globals->m_arHFPictureDrawing.size(); i++)
{
convert((ODRAW::OfficeArtDggContainer*)globals->m_arHFPictureDrawing[i].get());
}
globals->serialize_protection(xlsx_context->workbook_protection());
globals->serialize_format(xlsx_context->workbook_format());
for (size_t i = 0 ; i < globals->m_arWindow1.size(); i++)
{
globals->m_arWindow1[i]->serialize(xlsx_context->workbook_views());
}
for (size_t i = 0 ; i < globals->m_arUserBView.size(); i++)
{
globals->m_arUserBView[i]->serialize(xlsx_context->custom_views());
}
for (size_t i = 0 ; i < globals->m_arSUPBOOK.size(); i++)
{
convert((XLS::SUPBOOK*)globals->m_arSUPBOOK[i].get());
}
for (size_t i = 0 ; i < xls_global_info->arPIVOTCACHEDEFINITION.size(); i++)
{
convert((XLS::PIVOTCACHEDEFINITION*)xls_global_info->arPIVOTCACHEDEFINITION[i].get());
}
}
void XlsConverter::convert_chart_sheet(XLS::ChartSheetSubstream* chartsheet)
{
if (chartsheet == NULL) return;
xls_global_info->current_sheet = chartsheet->ws_index_ + 1;
std::wstring name = xls_global_info->sheets_info[chartsheet->ws_index_].name;
if (name.empty())
name = L"ChartSheet_" + std::to_wstring(chartsheet->ws_index_ + 1);
xlsx_context->set_sheet_type(3);
xlsx_context->set_sheet_name(name) ;
xlsx_context->set_sheet_id(chartsheet->ws_index_ + 1);
xlsx_context->set_sheet_state(xls_global_info->sheets_info[chartsheet->ws_index_].state);
convert_common(dynamic_cast<XLS::CommonSubstream*>(chartsheet));
if (xlsx_context->get_drawing_context().start_drawing(0x0005))
{
xlsx_context->get_drawing_context().set_id(1);
convert(chartsheet);
xlsx_context->get_drawing_context().end_drawing();
}
}
typedef boost::unordered_map<XLS::FillInfo, int> mapFillInfo;
typedef boost::unordered_map<XLS::BorderInfo, int> mapBorderInfo;
typedef boost::unordered_map<XLS::FontInfo, int> mapFontInfo;
void XlsConverter::convert(XLS::FORMATTING* formating)
{
if (formating == NULL) return;
std::wstringstream strm;
CP_XML_WRITER(strm)
{
CP_XML_NODE(L"styleSheet")
{
CP_XML_ATTR(L"xmlns", L"http://schemas.openxmlformats.org/spreadsheetml/2006/main");
CP_XML_ATTR(L"xmlns:mc", L"http://schemas.openxmlformats.org/markup-compatibility/2006");
CP_XML_ATTR(L"mc:Ignorable", L"x14ac x16r2");
CP_XML_ATTR(L"xmlns:x14ac", L"http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac");
CP_XML_ATTR(L"xmlns:x16r2", L"http://schemas.microsoft.com/office/spreadsheetml/2015/02/main");
CP_XML_NODE(L"numFmts")
{
CP_XML_ATTR(L"count", xls_global_info->m_mapNumFormats.size());
for (std::map<_UINT16, XLS::BaseObjectPtr>::iterator it = xls_global_info->m_mapNumFormats.begin(); it != xls_global_info->m_mapNumFormats.end(); ++it)
{
XLS::Format* fmt = dynamic_cast<XLS::Format*>(it->second.get());
if (fmt->ifmt < 5 || (fmt->ifmt > 8 && fmt->ifmt < 23) || (fmt->ifmt > 36 && fmt->ifmt < 41) || (fmt->ifmt > 44 && fmt->ifmt < 50))
continue;
std::map<_UINT16, _UINT16>::iterator pFind = xls_global_info->mapUsedFormatCode.find(fmt->ifmt);
if (pFind != xls_global_info->mapUsedFormatCode.end())
{
CP_XML_STREAM() << L"<numFmt";
{
CP_XML_STREAM() << L" numFmtId=\"" << fmt->ifmt_used << L"\"";
CP_XML_STREAM() << L" formatCode=\"" << fmt->stFormat << L"\"";
}
CP_XML_STREAM() << L"/>";
}
}
}
CP_XML_NODE(L"fonts")
{
std::vector<XLS::FontInfo> fonts_out;
fonts_out.resize(xls_global_info->font_x_ids.size());
for (mapFontInfo::iterator it = xls_global_info->font_x_ids.begin(); it != xls_global_info->font_x_ids.end(); ++it)
{
fonts_out[it->second] = it->first;
}
CP_XML_ATTR(L"count", fonts_out.size());
for (size_t i = 0 ;i < fonts_out.size(); i++)
{
fonts_out[i].serialize(CP_XML_STREAM());
}
}
CP_XML_NODE(L"fills")
{
std::vector<XLS::FillInfo> fills_out;
fills_out.resize(xls_global_info->fill_x_ids.size());
for (mapFillInfo::iterator it = xls_global_info->fill_x_ids.begin(); it != xls_global_info->fill_x_ids.end(); ++it)
{
fills_out[it->second] = it->first;
}
CP_XML_ATTR(L"count", fills_out.size());
for (size_t i = 0 ;i < fills_out.size(); i++)
{
fills_out[i].serialize(CP_XML_STREAM());
}
}
CP_XML_NODE(L"borders")
{
std::vector<XLS::BorderInfo> borders_out;
borders_out.resize(xls_global_info->border_x_ids.size());
for (mapBorderInfo::iterator it = xls_global_info->border_x_ids.begin(); it != xls_global_info->border_x_ids.end(); ++it)
{
borders_out[it->second] = it->first;
}
CP_XML_ATTR(L"count", borders_out.size());
for (size_t i = 0 ;i < borders_out.size(); i++)
{
borders_out[i].serialize(CP_XML_STREAM());
}
}
formating->serialize(CP_XML_STREAM());
}
}
output_document->get_xl_files().set_styles( oox::package::simple_element::create(L"styles.xml", strm.str()) );
}
std::wstring XlsConverter::GetTargetMoniker(XLS::BiffStructure *moniker)
{
if (moniker == NULL) return L"";
if (moniker->getClassName() == "URLMoniker")
{
OSHARED::URLMoniker* urlMoniker = dynamic_cast<OSHARED::URLMoniker* >(moniker);
if (urlMoniker)return urlMoniker->url;
}
else if (moniker->getClassName() == "FileMoniker")
{
OSHARED::FileMoniker* fileMoniker = dynamic_cast<OSHARED::FileMoniker* >(moniker);
if (fileMoniker)
{
if (!fileMoniker->unicodePath.empty()) return fileMoniker->unicodePath;
else return std::wstring(fileMoniker->ansiPath.begin(), fileMoniker->ansiPath.end());//codePage ??? todooo
}
}
return L"";
}
void XlsConverter::convert(XLS::MSODRAWINGGROUP * mso_drawing)
{
if ( mso_drawing == NULL) return;
XLS::MsoDrawingGroup * mso_group = dynamic_cast<XLS::MsoDrawingGroup*>(mso_drawing->m_MsoDrawingGroup.get());
if (mso_group == NULL) return;
//files
convert (dynamic_cast<ODRAW::OfficeArtBStoreContainer*>(mso_group->rgChildRec.m_OfficeArtBStoreContainer.get()));
}
std::wstring XlsConverter::WriteMediaFile(char *data, int size, std::wstring type_ext, int id)
{
if (size < 1 || !data) return L"";
if (id < 0) id = xlsx_context->get_mediaitems().count_image + 1000; // 1000 - встроенные в поток , 3000 - footer/header
xlsx_context->get_mediaitems().create_media_path(xlsx_path);
bool res = false;
std::wstring file_name = L"image" + std::to_wstring(id);
if (type_ext == L"dib_data")
{
bool bPNG = false;
int offset = 0, biSizeImage = 0;
CBgraFrame frame;
BITMAPINFOHEADER * header = (BITMAPINFOHEADER *)data;
if (header->biWidth > 100000 || header->biHeight > 100000)
{
//biff8
//Formulas Matriciais - A Outra Dimensão do Excel.xls 775x20 todoooo найти еще файлы
//Planilha Bastter Blue 7.0 Free.xls 10x3836
//biff 5
//test-picture.xls
offset = 12; //sizeof(BITMAPCOREHEADER)
BITMAPCOREHEADER * header_core = (BITMAPCOREHEADER *)data;
frame.put_Height (header_core->bcHeight );
frame.put_Width (header_core->bcWidth );
int sz_bitmap = header_core->bcHeight * header_core->bcWidth * header_core->bcBitCount/ 8;
//if (header_core->bcWidth % 2 != 0 && sz_bitmap < size - offset)
// header_core->bcWidth++;
///???? todooo непонятно .. в biff5 нужно флипать картинку, в biff8 не ясно ( -
int stride = - (size - offset) / header_core->bcHeight;
frame.put_Stride (stride/*header_core->bcBitCount * header_core->bcWidth /8 */);
biSizeImage = size - offset;
if (-stride >= header_core->bcWidth && header_core->bcBitCount >=24 )
{
bPNG = true;
}
}
else
{
offset = 40; //sizeof(BITMAPINFOHEADER)
frame.put_Height (header->biHeight );
frame.put_Width (header->biWidth );
int sz_bitmap = header->biHeight * header->biWidth * header->biBitCount/ 8;
//if (header->biWidth % 2 != 0 && sz_bitmap < size -offset)
// header->biWidth++;
int stride = -(size - offset) / header->biHeight;
if (-stride >= header->biWidth && header->biBitCount >= 24)
{
bPNG = true;
}
frame.put_Stride (stride/*header->biBitCount * header->biWidth /8*/);
biSizeImage = header->biSizeImage;
}
if (bPNG)
{
frame.put_Data((unsigned char*)data + offset);
file_name += std::wstring(L".png");
res = frame.SaveFile(xlsx_context->get_mediaitems().media_path() + file_name, 4/*CXIMAGE_FORMAT_PNG*/);
frame.put_Data(NULL);
if (res = false)
{
//
}
}
else if (biSizeImage > 0)
{
//тут паттерные картинки
file_name += std::wstring(L".bmp");
NSFile::CFileBinary file;
if (file.CreateFileW(xlsx_context->get_mediaitems().media_path() + file_name))
{
WORD vtType = 0x4D42; file.WriteFile((BYTE*)&vtType, 2);
DWORD dwLen = biSizeImage; file.WriteFile((BYTE*)&dwLen, 4);
DWORD dwRes = 0; file.WriteFile((BYTE*)&dwRes, 4);
DWORD dwOffset = 2; file.WriteFile((BYTE*)&dwOffset, 4);
file.WriteFile((BYTE*)data, size);
file.CloseFile();
res = true;
}
}
}
else if (type_ext == L"pict")
{
//NSFile::CFileBinary file;
//std::wstring tempPICT = file.CreateTempFileWithUniqueName(xls_global_info->tempDirectory, L"pct");
//if (file.CreateFileW(tempPICT))
//{
// file.WriteFile((BYTE*)data, size);
// file.CloseFile();
//}
CBgraFrame bgraFrame;
if (bgraFrame.Decode((BYTE*)data, size))
{
file_name += L".png";
bgraFrame.SaveFile(xlsx_context->get_mediaitems().media_path() + file_name, 4); // png
}
//NSFile::CFileBinary::Remove(tempPICT);
}
else
{
file_name += type_ext;
NSFile::CFileBinary file;
if (file.CreateFileW(xlsx_context->get_mediaitems().media_path() + file_name))
{
file.WriteFile((BYTE*)data, size);
file.CloseFile();
}
}
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
res = true;
if (res)
{
xlsx_context->get_mediaitems().add_image(L"media/" + file_name, id);
return L"media/" + file_name;
}
return L"";
}
void XlsConverter::convert(ODRAW::OfficeArtBStoreContainer* art_bstore, int start_id)
{
if (art_bstore == NULL) return;
if (art_bstore->rgfb.size() < 1) return;
for (size_t i = 0 ; i < art_bstore->rgfb.size(); i++)
{
int bin_id = i + start_id + 1;
WriteMediaFile(art_bstore->rgfb[i]->pict_data, art_bstore->rgfb[i]->pict_size, art_bstore->rgfb[i]->pict_type, bin_id);
}
}
void XlsConverter::convert(XLS::FEAT11 * shared_feature)
{
if (!shared_feature) return;
for (size_t i = 0; i < shared_feature->m_arFEAT.size(); i++)
{
xlsx_context->start_table();
std::wstringstream strm;
shared_feature->serialize(strm, i);
xlsx_context->get_tables_context().add_table(strm.str());
xlsx_context->end_table();
}
}
void XlsConverter::convert(XLS::HLINK * HLINK_)
{
if (!HLINK_) return;
XLS::HLink * hLink = dynamic_cast<XLS::HLink*>(HLINK_->m_HLink.get());
if (!hLink) return;
std::wstring target;
bool bExternal = false;
if (hLink->hyperlink.hlstmfHasMoniker)
{
target = GetTargetMoniker(hLink->hyperlink.oleMoniker.data.get());
bExternal = true;
}
else if (hLink->hyperlink.hlstmfHasLocationStr)
{
target = hLink->hyperlink.location;
}
std::wstring display = hLink->hyperlink.displayName;
if (display.empty()) display = target;
xlsx_context->get_sheet_context().add_hyperlink( hLink->ref8.toString(), target, display, bExternal);
}
void XlsConverter::convert(XLS::LBL * def_name)
{
if (def_name == NULL) return;
def_name->serialize(xlsx_context->defined_names());
}
void XlsConverter::convert(XLS::IMDATA * imdata)
{
if (imdata == NULL) return;
if (imdata->lcb < 1 || imdata->pData == NULL) return;
bool bInternal = false;
std::wstring type_image;
if (imdata->cf == 0x09 && imdata->env == 0x01) type_image = L".wmf";
if ((imdata->cf == 0x09 || imdata->cf == 0x02)
&& imdata->env == 0x02) type_image = L"pict";
if (imdata->cf == 0x09) type_image = L"dib_data";
if (imdata->cf == 0x0e) type_image = L""; //native aka unknown
std::wstring target = WriteMediaFile(imdata->pData.get(), imdata->lcb, type_image);
xlsx_context->get_drawing_context().set_fill_texture(target);
}
void XlsConverter::convert(XLS::BACKGROUND * back)
{
if (back == NULL) return;
XLS::BkHim * bkHim = dynamic_cast<XLS::BkHim*>(back->m_BkHim.get());
if (bkHim->lcb < 1 || bkHim->pData == NULL) return;
bool bInternal = false;
std::wstring target = WriteMediaFile(bkHim->pData.get(), bkHim->lcb, L"dib_data");
std::wstring rId = xlsx_context->get_mediaitems().find_image(target, bInternal);
xlsx_context->current_sheet().sheet_rels().add(oox::relationship(rId, oox::external_items::typeImage, std::wstring(L"../") + target, !bInternal));
if (rId.empty()) return;
CP_XML_WRITER(xlsx_context->current_sheet().picture_background())
{
CP_XML_NODE(L"picture")
{
CP_XML_ATTR(L"r:id", rId);
}
}
}
void XlsConverter::convert_theme()
{
if (xls_global_info->sTheme.empty()) return;
oox::package::theme_content_ptr content =
oox::package::theme_content::create((char*)xls_global_info->sTheme.c_str(), xls_global_info->sTheme.length());
output_document->get_xl_files().add_theme(content);
}
struct _group_object
{
_group_object() {spgr = NULL; ind = count = 0;}
ODRAW::OfficeArtSpgrContainer *spgr;
int ind;
int count;
};
void XlsConverter::convert_old(XLS::OBJECTS* objects, XLS::WorksheetSubstream * sheet)
{
int count = 0;
for ( std::list<XLS::BaseObjectPtr>::iterator elem = objects->elements_.begin(); elem != objects->elements_.end(); elem++)
{
count++;
short type_object = -1;
XLS::OBJ * OBJ = dynamic_cast<XLS::OBJ*> (elem->get());
XLS::IMDATAOBJECT * IMDATAOBJECT = NULL;
XLS::CHART * CHART = NULL;
std::list<XLS::BaseObjectPtr>::iterator elem_next = boost::next(elem);
if ( elem_next !=objects->elements_.end() )
{
IMDATAOBJECT = dynamic_cast<XLS::IMDATAOBJECT*> (elem_next->get());
CHART = dynamic_cast<XLS::CHART*> (elem_next->get());
}
XLS::Obj * obj = OBJ ? dynamic_cast<XLS::Obj *>(OBJ->m_Obj.get()) : NULL;
XLS::IMDATA * image_obj = IMDATAOBJECT ? dynamic_cast<XLS::IMDATA *>(IMDATAOBJECT->m_IMDATA.get()) : NULL;
XLS::ChartSheetSubstream * chart = CHART ? dynamic_cast<XLS::ChartSheetSubstream *>(CHART->m_ChartSheetSubstream.get()) : NULL;
if (!obj)continue;
type_object = obj->cmo.ot;
//-----------------------------------------------------------------------------
if (type_object < 0)continue;
if (type_object == 0)
continue;
if (obj->cmo.fUIObj)
{
continue; // automatically inserted by the application
}
if (xlsx_context->get_drawing_context().start_drawing(type_object))
{
convert(obj->old_version.anchor.get());
if (obj->old_version.bFill)
xlsx_context->get_drawing_context().set_fill_old_version(obj->old_version.fill);
else
xlsx_context->get_drawing_context().set_fill_type(oox::fillNone); //no fill
xlsx_context->get_drawing_context().set_name(obj->old_version.name);
xlsx_context->get_drawing_context().set_line_old_version(obj->old_version.line);
xlsx_context->get_drawing_context().set_flag_old_version(obj->old_version.flag, obj->old_version.flag2);
for (size_t i = 0 ; i < obj->old_version.additional.size(); i++)
{
convert(obj->old_version.additional[i].get());
}
convert(image_obj);
convert(chart);
convert(obj);
xlsx_context->get_drawing_context().end_drawing();
}
if (IMDATAOBJECT || CHART)
{
elem++;
count++;
}
}
}
void XlsConverter::convert(XLS::OBJECTS* objects, XLS::WorksheetSubstream * sheet)
{
if (objects == NULL) return;
if (xls_global_info->Version < 0x0600)
return convert_old(objects, sheet);
std::vector<_group_object> group_objects;
_group_object gr;
gr.spgr = dynamic_cast<ODRAW::OfficeArtSpgrContainer*>(objects->m_MsoDrawing.get()->rgChildRec.m_OfficeArtSpgrContainer.get());
if (gr.spgr == NULL)
return;
gr.count = gr.spgr->child_records.size();
group_objects.push_back(gr);
if ((group_objects.back().spgr) && (group_objects.back().ind < group_objects.back().spgr->child_records.size()))
{
ODRAW::OfficeArtSpContainer *s = dynamic_cast<ODRAW::OfficeArtSpContainer*>(group_objects.back().spgr->child_records[group_objects.back().ind].get());
if (s)
{
ODRAW::OfficeArtFSP *fsp = dynamic_cast<ODRAW::OfficeArtFSP*>(s->m_OfficeArtFSP.get());
if ((fsp) && (fsp->fPatriarch)) group_objects.back().ind++;
}
}
int count = 0;
for ( std::list<XLS::BaseObjectPtr>::iterator elem = objects->elements_.begin(); elem != objects->elements_.end(); elem++)
{
count++;
short type_object = -1;
XLS::OBJ * OBJ = dynamic_cast<XLS::OBJ*> (elem->get());
XLS::TEXTOBJECT * TEXTOBJECT = NULL;
XLS::CHART * CHART = NULL;
std::list<XLS::BaseObjectPtr>::iterator elem_next = boost::next(elem);
if ( elem_next !=objects->elements_.end() )
{
TEXTOBJECT = dynamic_cast<XLS::TEXTOBJECT*>(elem_next->get());
CHART = dynamic_cast<XLS::CHART*> (elem_next->get());
}
XLS::Obj * obj = NULL;
XLS::TxO * text_obj = NULL;
XLS::ChartSheetSubstream * chart = NULL;
if (OBJ) obj = dynamic_cast<XLS::Obj *>(OBJ->m_Obj.get());
if (TEXTOBJECT) text_obj = dynamic_cast<XLS::TxO *>(TEXTOBJECT->m_TxO.get());
if (CHART) chart = dynamic_cast<XLS::ChartSheetSubstream *>(CHART->m_ChartSheetSubstream.get());
if (obj) type_object = obj->cmo.ot;
if (chart) type_object = 0x0005;
if (text_obj)
{
if (type_object < 0) type_object = 0x0006;
}
//-----------------------------------------------------------------------------
if (type_object < 0) continue;
if (group_objects.empty())
break; /// что то с объектами не то ! 2006 02.xls
if (type_object == 0)
{
_group_object gr;
if (group_objects.back().ind < group_objects.back().spgr->child_records.size())
{
gr.spgr = dynamic_cast<ODRAW::OfficeArtSpgrContainer*>(group_objects.back().spgr->child_records[group_objects.back().ind++].get());
gr.count = gr.spgr ? gr.spgr->child_records.size() : 0;
group_objects.push_back(gr);
}
else //сюда попадать не должно !!!!
continue;
}
if (obj->cmo.fUIObj)
{
group_objects.back().ind++;
continue; // automatically inserted by the application
}
ODRAW::OfficeArtSpContainer *sp = NULL;
if ((group_objects.size() > 0) && (group_objects.back().spgr ) && ( group_objects.back().ind < group_objects.back().count))
{
sp = dynamic_cast<ODRAW::OfficeArtSpContainer*>(group_objects.back().spgr->child_records[group_objects.back().ind++].get());
}
if (xlsx_context->get_drawing_context().start_drawing(type_object))
{
convert(sp);
if ((!sp) || (!sp->m_OfficeArtAnchor))
{
if ((group_objects.size() > 0) && (group_objects.back().spgr ) && ( group_objects.back().ind < group_objects.back().count))
{
sp = dynamic_cast<ODRAW::OfficeArtSpContainer*>(group_objects.back().spgr->child_records[group_objects.back().ind++].get());
}
convert(sp, true);
}
if (type_object == 0x19)
{
text_obj->preserve_enabled = true;
for (size_t i = 0 ; sheet && i < sheet->m_arNote.size(); i++)
{
XLS::Note* note = dynamic_cast<XLS::Note*>(sheet->m_arNote[i].get());
if ((note) && (note->note_sh.idObj == obj->cmo.id))
{
convert(note);
break;
}
}
}
convert(text_obj);
convert(chart);
convert(obj);
xlsx_context->get_drawing_context().end_drawing();
}
if (TEXTOBJECT || CHART)
{
elem++;
count++;
}
while ((group_objects.size() >0) && (group_objects.back().ind >= group_objects.back().count))
{
group_objects.back().spgr = NULL;
group_objects.pop_back();
xlsx_context->get_drawing_context().end_group();
}
}
}
void XlsConverter::convert(ODRAW::OfficeArtSpgrContainer * spgr)
{
if (spgr == NULL) return;
if (spgr->anchor_type_ != ODRAW::OfficeArtRecord::CA_HF) return;
for (size_t i = 0; i < spgr->child_records.size(); i++)
{
ODRAW::OfficeArtSpContainer* SpContainer = dynamic_cast<ODRAW::OfficeArtSpContainer*>(spgr->child_records[i].get());
if (SpContainer)
{
ODRAW::OfficeArtFSP* fsp = dynamic_cast<ODRAW::OfficeArtFSP*>(SpContainer->m_OfficeArtFSP.get());
if ((fsp) && (fsp->fHaveSpt))
{
int type_object = 2;//rect
if (xlsx_context->get_drawing_context().start_drawing(type_object))
{
xlsx_context->get_drawing_context().set_mode_HF(true);
convert(spgr->child_records[i].get());
xlsx_context->get_drawing_context().end_drawing();
}
}
}
}
}
void XlsConverter::convert(ODRAW::OfficeArtSpContainer *sp, bool anchor_only)
{
if (sp == NULL) return;
if (!anchor_only)
{
convert(sp->m_OfficeArtFSP.get());
for (size_t i = 0; i < sp->child_records.size(); i++)
{
convert(sp->child_records[i].get());
}
}
convert(sp->m_OfficeArtAnchor.get());
}
void XlsConverter::convert(ODRAW::OfficeArtRecord * art)
{
if (art == NULL) return;
std::wstringstream strm;
switch(art->get_type())
{
case XLS::typeOfficeArtFOPT://properties
{
convert(dynamic_cast<ODRAW::OfficeArtFOPT *>(art));
}break;
case XLS::typeOfficeArtTertiaryFOPT://properties
{
convert(dynamic_cast<ODRAW::OfficeArtTertiaryFOPT *>(art));
}break;
case XLS::typeOfficeArtFSP:
{
convert(dynamic_cast<ODRAW::OfficeArtFSP *>(art));
}break;
case XLS::typeOfficeArtFSPGR:
{
ODRAW::OfficeArtFSPGR * ch = dynamic_cast<ODRAW::OfficeArtFSPGR *>(art);
xlsx_context->get_drawing_context().set_group_anchor(ch->_x, ch->_y, ch->_cx, ch->_cy);
}break;
case XLS::typeOfficeArtClientAnchorHF:
{
ODRAW::OfficeArtClientAnchorHF * hf = dynamic_cast<ODRAW::OfficeArtClientAnchorHF *>(art);
xlsx_context->get_drawing_context().set_child_anchor(0, 0, hf->_cx * 3 / 5, hf->_cy * 3 / 5);
}break;
case XLS::typeOfficeArtChildAnchor:
{
ODRAW::OfficeArtChildAnchor * ch = dynamic_cast<ODRAW::OfficeArtChildAnchor *>(art);
xlsx_context->get_drawing_context().set_child_anchor(ch->_x, ch->_y, ch->_cx, ch->_cy);
}break;
case XLS::typeOfficeArtClientAnchorSheet:
{
ODRAW::OfficeArtClientAnchorSheet * ch = dynamic_cast<ODRAW::OfficeArtClientAnchorSheet *>(art);
ch->calculate();
ch->calculate_1();
if (xlsx_context->get_drawing_context().getType() == oox::external_items::typeGroup &&
xlsx_context->get_drawing_context().getLevel() == 1)
{
xlsx_context->get_drawing_context().set_child_anchor(ch->_x, ch->_y, ch->_cx, ch->_cy);
}
xlsx_context->get_drawing_context().set_sheet_anchor(ch->colL, ch->_dxL, ch->rwT, ch->_dyT, ch->colR, ch->_dxR, ch->rwB, ch->_dyB,
ch->_x, ch->_y, ch->_cx, ch->_cy);
}break;
case XLS::typeOfficeArtBStoreContainer:
{
convert (dynamic_cast<ODRAW::OfficeArtBStoreContainer *>(art), 3000);
}break;
case XLS::typeOfficeArtSpContainer:
{
convert (dynamic_cast<ODRAW::OfficeArtSpContainer *>(art));
}break;
case XLS::typeOfficeArtSpgrContainer:
{
convert (dynamic_cast<ODRAW::OfficeArtSpgrContainer *>(art));
}break;
case XLS::typeOfficeArtDgContainer:
{
ODRAW::OfficeArtDgContainer * dg = dynamic_cast<ODRAW::OfficeArtDgContainer *>(art);
for (size_t i = 0 ; i < dg->child_records.size(); i++) //a-la msodrawing for headers/footers
{
convert(dg->child_records[i].get());
}
for (size_t i = 0; i < dg->m_OfficeArtSpContainer.size(); i++)
{
convert(dg->m_OfficeArtSpContainer[i].get());
}
convert(dg->m_OfficeArtSpgrContainer.get());
}break;
case XLS::typeOfficeArtDggContainer:
{
ODRAW::OfficeArtDggContainer* dg = dynamic_cast<ODRAW::OfficeArtDggContainer*>(art);
convert(dg->m_OfficeArtBStoreContainer.get());
}break;
default:
break;
}
}
void XlsConverter::convert(ODRAW::OfficeArtFSP * fsp)
{
if (fsp == NULL) return;
if (fsp->fFlipH) xlsx_context->get_drawing_context().set_FlipH();
if (fsp->fFlipV) xlsx_context->get_drawing_context().set_FlipV();
xlsx_context->get_drawing_context().set_id(fsp->spid);
xlsx_context->get_drawing_context().set_shape_id(fsp->shape_id);
}
void XlsConverter::convert_fill_style(std::vector<ODRAW::OfficeArtFOPTEPtr> & props)
{
if (props.empty()) return;
for (size_t i = 0 ; i < props.size() ; i++)
{
switch(props[i]->opid)
{
case ODRAW::fillType:
{
switch(props[i]->op)
{
case 1://fillPattern:
{
xlsx_context->get_drawing_context().set_fill_type(oox::fillPattern);
//texture + change black to color2, white to color1
}break;
case 2://fillTexture :
{
xlsx_context->get_drawing_context().set_fill_type(oox::fillTexture);
xlsx_context->get_drawing_context().set_fill_texture_mode(0);
}break;
case 3://fillPicture :
{
xlsx_context->get_drawing_context().set_fill_type(oox::fillTexture);
xlsx_context->get_drawing_context().set_fill_texture_mode(1);
}break;
case 4://fillShadeCenter://1 color
case 5://fillShadeShape:
{
xlsx_context->get_drawing_context().set_fill_type(oox::fillGradientOne);
}break;//
case 6://fillShadeTitle://2 colors and more
case 7://fillShade :
case 8://fillShadeScale:
{
xlsx_context->get_drawing_context().set_fill_type(oox::fillGradient);
}break;
case 9://fillBackground:
{
xlsx_context->get_drawing_context().set_fill_type(oox::fillNone);
}break;
case 0:
default:
{ //undefined
xlsx_context->get_drawing_context().set_fill_type(oox::fillUndefined);
}break;
}
}break;
case ODRAW::fillColor:
case ODRAW::fillColorExt:
{
ODRAW::FillColor * fill = (ODRAW::FillColor *)(props[i].get());
ODRAW::OfficeArtCOLORREF color((_UINT32)fill->op);
if (!color.sColorRGB.empty())
xlsx_context->get_drawing_context().set_fill_color(color.nColorRGB, color.sColorRGB);
else if (color. fPaletteIndex)
{
std::map<int, std::wstring>::iterator it = xls_global_info->colors_palette.find(color.index);
if (it != xls_global_info->colors_palette.end())
{
//убрать 0!!! todooo
xlsx_context->get_drawing_context().set_fill_color(0, it->second);
}
}
else
xlsx_context->get_drawing_context().set_fill_color(color.index, color.fSchemeIndex ? 1 : 3 );
}break;
case ODRAW::fillOpacity:
{
ODRAW::FixedPoint * fixed_point = static_cast<ODRAW::FixedPoint *>(props[i].get());
xlsx_context->get_drawing_context().set_fill_opacity(fixed_point->dVal);
}break;
case ODRAW::fillBackColor:
case ODRAW::fillBackColorExt:
{
ODRAW::FillColor * fill = (ODRAW::FillColor *)(props[i].get());
ODRAW::OfficeArtCOLORREF color((_UINT32)fill->op);
if (!color.sColorRGB.empty())
xlsx_context->get_drawing_context().set_fill_color(color.nColorRGB,color.sColorRGB, true );
else if (color. fPaletteIndex)
{
std::map<int, std::wstring>::iterator it = xls_global_info->colors_palette.find(color.index);
if (it != xls_global_info->colors_palette.end())
{
//todooo убрать 0 !!!
xlsx_context->get_drawing_context().set_fill_color(0, it->second, true );
}
}
else
xlsx_context->get_drawing_context().set_fill_color(color.index, color.fSchemeIndex ? 1 : 3, true );
}break;
case ODRAW::fillBackOpacity:
{
ODRAW::FixedPoint * fixed_point = static_cast<ODRAW::FixedPoint *>(props[i].get());
xlsx_context->get_drawing_context().set_fill_opacity(fixed_point->dVal, true);
}break;
case ODRAW::fillBlip:
{
std::wstring target;
ODRAW::FillBlip *fillBlip = (ODRAW::FillBlip *)(props[i].get());
if ((fillBlip) && (fillBlip->blip))
{
target = WriteMediaFile(fillBlip->blip->pict_data,fillBlip->blip->pict_size, fillBlip->blip->pict_type);
}
else
{
bool isIternal = false;
std::wstring rId = xlsx_context->get_mediaitems().find_image(props[i]->op , target, isIternal);
}
xlsx_context->get_drawing_context().set_fill_texture(target);
}break;
case ODRAW::fillAngle:
{
ODRAW::FillAngle * angle = (ODRAW::FillAngle *)(props[i].get());
xlsx_context->get_drawing_context().set_fill_angle(angle->dVal);
}break;
case ODRAW::fillFocus:
{
xlsx_context->get_drawing_context().set_fill_focus(props[i]->op);
}break;
case ODRAW::fillShadeType:
{
ODRAW::FillShadeType *shadeType = dynamic_cast<ODRAW::FillShadeType*>(props[i].get());
}break;
case ODRAW::fillShadePreset:
{
}break;
case ODRAW::fillShadeColors:
{
ODRAW::FillShadeColors *shadeColors = dynamic_cast<ODRAW::FillShadeColors*>(props[i].get());
for (size_t i = 0 ; (shadeColors) && (i < shadeColors->complex.data.size()); i++)
{
ODRAW::OfficeArtCOLORREF & color = shadeColors->complex.data[i].color;
std::wstring strColor;
if (!color.sColorRGB.empty()) strColor = color.sColorRGB;
else if (color. fPaletteIndex)
{
std::map<int, std::wstring>::iterator it = xls_global_info->colors_palette.find(color.index);
if (it != xls_global_info->colors_palette.end()) strColor = it->second;
}
if (!strColor.empty())
xlsx_context->get_drawing_context().add_fill_colors( shadeColors->complex.data[i].dPosition, strColor);
else
{
xlsx_context->get_drawing_context().add_fill_colors( shadeColors->complex.data[i].dPosition,
color.index, color.fSchemeIndex ? 1 : 3 );
}
}
}break;
case ODRAW::fillStyleBooleanProperties:
{
ODRAW::FillStyleBooleanProperties * bools = (ODRAW::FillStyleBooleanProperties *)(props[i].get());
if (bools)
{
if (bools->fUsefFilled && bools->fFilled == false)
xlsx_context->get_drawing_context().set_fill_type(oox::fillNone);
}
}break;
default:
{
i =i;
}break;
}
}
}
void XlsConverter::convert_line_style(std::vector<ODRAW::OfficeArtFOPTEPtr> & props)
{
if (props.empty()) return;
for (size_t i = 0 ; i < props.size() ; i++)
{
switch(props[i]->opid)
{
case ODRAW::lineColor:
{
ODRAW::OfficeArtCOLORREF color((_UINT32)props[i]->op);
if (!color.sColorRGB.empty())
xlsx_context->get_drawing_context().set_line_color(color.nColorRGB, color.sColorRGB);
else if (color. fPaletteIndex)
{
std::map<int, std::wstring>::iterator it = xls_global_info->colors_palette.find(color.index);
if (it != xls_global_info->colors_palette.end())
{
//todooo убрать 0 !!
xlsx_context->get_drawing_context().set_line_color(0, it->second);
}
}
else
xlsx_context->get_drawing_context().set_line_color(color.index, color.fSchemeIndex ? 1 : 3 );
}break;
case ODRAW::lineType:
{
xlsx_context->get_drawing_context().set_line_type(props[i]->op);
}break;
case ODRAW::lineFillBlip: //blip
{
}break;
case ODRAW::lineWidth:
xlsx_context->get_drawing_context().set_line_width(props[i]->op);
{
}break;
case ODRAW::lineStyle:
{
xlsx_context->get_drawing_context().set_line_style(props[i]->op);
}break;
case ODRAW::lineDashing:
{
xlsx_context->get_drawing_context().set_line_dash(props[i]->op);
}break;
case ODRAW::lineStartArrowhead:
{
xlsx_context->get_drawing_context().set_arrow_start(props[i]->op);
}break;
case ODRAW::lineEndArrowhead:
{
xlsx_context->get_drawing_context().set_arrow_end(props[i]->op);
}break;
case ODRAW::lineStartArrowWidth:
{
xlsx_context->get_drawing_context().set_arrow_start_width(props[i]->op);
}break;
case ODRAW::lineStartArrowLength:
{
xlsx_context->get_drawing_context().set_arrow_start_length(props[i]->op);
}break;
case ODRAW::lineEndArrowWidth:
{
xlsx_context->get_drawing_context().set_arrow_end_width(props[i]->op);
}break;
case ODRAW::lineEndArrowLength:
{
xlsx_context->get_drawing_context().set_arrow_end_length(props[i]->op);
}break;
case ODRAW::lineStyleBooleanProperties:
{
ODRAW::LineStyleBooleanProperties * bools = (ODRAW::LineStyleBooleanProperties *)(props[i].get());
if (bools)
{
if (bools->fUsefLine && bools->fLine == false)
xlsx_context->get_drawing_context().set_line_type(5); //no line
if (bools->fUsefArrowheadsOK && bools->fArrowheadsOK)
{
xlsx_context->get_drawing_context().set_line_arrow(true);
}
}
}break;
case ODRAW::lineMiterLimit:
{
xlsx_context->get_drawing_context().set_line_miter(props[i]->op);
}break;
case ODRAW::lineJoinStyle:
{
xlsx_context->get_drawing_context().set_line_join(props[i]->op);
}break;
case ODRAW::lineEndCapStyle:
{
xlsx_context->get_drawing_context().set_line_endcap(props[i]->op);
}break;
}
}
}
void XlsConverter::convert_blip(std::vector<ODRAW::OfficeArtFOPTEPtr> & props)
{
if (props.empty()) return;
for (size_t i = 0 ; i < props.size() ; i++)
{
switch(props[i]->opid)
{
case ODRAW::cropFromTop:
{
ODRAW::FixedPoint * fixed_point = static_cast<ODRAW::FixedPoint *>(props[i].get());
xlsx_context->get_drawing_context().set_picture_crop_top(fixed_point->dVal * 10);
}break;
case ODRAW::cropFromBottom:
{
ODRAW::FixedPoint * fixed_point = static_cast<ODRAW::FixedPoint *>(props[i].get());
xlsx_context->get_drawing_context().set_picture_crop_bottom(fixed_point->dVal * 10);
}break;
case ODRAW::cropFromLeft:
{
ODRAW::FixedPoint * fixed_point = static_cast<ODRAW::FixedPoint *>(props[i].get());
xlsx_context->get_drawing_context().set_picture_crop_left(fixed_point->dVal * 10);
}break;
case ODRAW::cropFromRight:
{
ODRAW::FixedPoint * fixed_point = static_cast<ODRAW::FixedPoint *>(props[i].get());
xlsx_context->get_drawing_context().set_picture_crop_right(fixed_point->dVal * 10);
}break;
case ODRAW::pib:
{
bool isIternal = false;
std::wstring target;
int id = props[i]->op;
if (xlsx_context->get_drawing_context().get_mode_HF())
id += 3000;
std::wstring rId = xlsx_context->get_mediaitems().find_image(id , target, isIternal);
xlsx_context->get_drawing_context().set_picture(target);
}break;
case ODRAW::pibName:
{
ODRAW::AnyString *str = dynamic_cast<ODRAW::AnyString*>(props[i].get());
xlsx_context->get_drawing_context().set_picture_name(str->string_);
}break;
case ODRAW::pibFlags:
{
}break;
case ODRAW::pictureTransparent:
{
ODRAW::OfficeArtCOLORREF color((_UINT32)props[i]->op);
if (!color.sColorRGB.empty())
xlsx_context->get_drawing_context().set_picture_transparent(color.nColorRGB, color.sColorRGB);
//...
}break;
case ODRAW::pictureContrast:
{
int val = 0;
if (props[i]->op == 0x7FFFFFFF)
{
val = 100;
}
else if (props[i]->op == 0x00010000)
{
val = 0;
}
else if (props[i]->op > 0x00010000)
{
val = 51. / (props[i]->op / 65536.);
val = (50 - val) * 2;
}
else
{
val = (100. * props[i]->op / 65536. + 0.5) - 100;
}
xlsx_context->get_drawing_context().set_picture_contrast(val);
}break;
case ODRAW::pictureBrightness:
{
int val = ((_INT32)props[i]->op * 100. + 0.5) / 0x00008000;
xlsx_context->get_drawing_context().set_picture_brightness(val);
}break;
case ODRAW::pictureGamma:
{
}break;
case ODRAW::pictureId:
{
}break;
case ODRAW::pictureDblCrMod:
{
}break;
case ODRAW::pictureFillCrMod:
{
}break;
case ODRAW::pictureLineCrMod:
{
}break;
case ODRAW::pibPrint:
{
}break;
case ODRAW::pibPrintName:
{
}break;
case ODRAW::pibPrintFlags:
{
}break;
case ODRAW::blipBooleanProperties:
{
ODRAW::BlipBooleanProperties * bools = (ODRAW::BlipBooleanProperties *)(props[i].get());
if (bools)
{
if (bools->fUsefPictureGray && bools->fPictureGray)
xlsx_context->get_drawing_context().set_picture_grayscale(true);
if (bools->fUsefPictureBiLevel && bools->fPictureBiLevel)
xlsx_context->get_drawing_context().set_picture_biLevel(50);
}
}break;
}
}
}
void XlsConverter::convert_geometry(std::vector<ODRAW::OfficeArtFOPTEPtr> & props)
{
if (props.empty()) return;
_CP_OPT(oox::_rect) rect;
std::vector<_CP_OPT(int)> adjustValues(9);
for (size_t i = 0 ; i < props.size() ; i++)
{
switch(props[i]->opid)
{
case ODRAW::geoLeft: if (!rect) rect = oox::_rect(); rect->x = props[i]->op; break;
case ODRAW::geoTop: if (!rect) rect = oox::_rect(); rect->y = props[i]->op; break;
case ODRAW::geoRight: if (!rect) rect = oox::_rect(); rect->cx = props[i]->op; break;
case ODRAW::geoBottom: if (!rect) rect = oox::_rect(); rect->cy = props[i]->op; break;
case ODRAW::shapePath:
xlsx_context->get_drawing_context().set_custom_path(props[i]->op); break;
case ODRAW::pVertices:
{
ODRAW::PVertices * v = (ODRAW::PVertices *)(props[i].get());
xlsx_context->get_drawing_context().set_custom_verticles(v->complex.data);
}break;
case ODRAW::pSegmentInfo:
{
ODRAW::PSegmentInfo * s = (ODRAW::PSegmentInfo *)(props[i].get());
xlsx_context->get_drawing_context().set_custom_segments(s->complex.data);
}break;
case ODRAW::adjustValue: //0x0147
case ODRAW::adjust2Value:
case ODRAW::adjust3Value:
case ODRAW::adjust4Value:
case ODRAW::adjust5Value:
case ODRAW::adjust6Value:
case ODRAW::adjust7Value:
case ODRAW::adjust8Value:
case ODRAW::adjust9Value:
case ODRAW::adjust10Value:
{
adjustValues[props[i]->opid - 0x0147] = props[i]->op ;
}break;
case ODRAW::pConnectionSites:
{
ODRAW::PConnectionSites * a = (ODRAW::PConnectionSites *)(props[i].get());
xlsx_context->get_drawing_context().set_custom_connection(a->complex.data);
}break;
case ODRAW::pConnectionSitesDir:
{
ODRAW::PConnectionSitesDir * a = (ODRAW::PConnectionSitesDir *)(props[i].get());
xlsx_context->get_drawing_context().set_custom_connectionDir(a->complex.data);
}break;
case ODRAW::xLimo:
{
xlsx_context->get_drawing_context().set_custom_x_limo(props[i]->op);
}break;
case ODRAW::yLimo:
{
xlsx_context->get_drawing_context().set_custom_y_limo(props[i]->op);
}break;
case ODRAW::pAdjustHandles:
{
ODRAW::PAdjustHandles * a = (ODRAW::PAdjustHandles *)(props[i].get());
xlsx_context->get_drawing_context().set_custom_adjustHandles(a->complex.data);
}break;
case ODRAW::pGuides:
{
ODRAW::PGuides* s = (ODRAW::PGuides *)(props[i].get());
xlsx_context->get_drawing_context().set_custom_guides(s->complex.data);
}break;
case ODRAW::pInscribe:
{
ODRAW::PInscribe * a = (ODRAW::PInscribe *)(props[i].get());
xlsx_context->get_drawing_context().set_custom_inscribe(a->complex.data);
}break;
//case ODRAW::cxk:
// {
// ODRAW::cxk * a = (ODRAW::cxk *)(props[i].get());
// xlsx_context->get_drawing_context().set_custom_cxk(a->complex.data);
// }break;
}
}
if (rect)
{
rect->cy -= rect->y;
rect->cx -= rect->x;
xlsx_context->get_drawing_context().set_custom_rect(*rect);
}
xlsx_context->get_drawing_context().set_custom_adjustValues(adjustValues);
}
void XlsConverter::convert_geometry_text(std::vector<ODRAW::OfficeArtFOPTEPtr> & props)
{
if (props.empty()) return;
for (size_t i = 0 ; i < props.size() ; i++)
{
switch(props[i]->opid)
{
case ODRAW::gtextUNICODE://word art text
{
ODRAW::AnyString *str = dynamic_cast<ODRAW::AnyString*>(props[i].get());
if (str) xlsx_context->get_drawing_context().set_wordart_text(str->string_);
}break;
case ODRAW::gtextFont:
{
ODRAW::AnyString *str = dynamic_cast<ODRAW::AnyString*>(props[i].get());
if (str)
{
xlsx_context->get_drawing_context().set_wordart_font(str->string_);
}
}break;
case ODRAW::gtextSize:
{
xlsx_context->get_drawing_context().set_wordart_size((INT)((props[i]->op >> 16) & 0x0000FFFF));
}break;
case ODRAW::gtextSpacing:
{
ODRAW::FixedPoint *val = dynamic_cast<ODRAW::FixedPoint*>(props[i].get());
if (val) xlsx_context->get_drawing_context().set_wordart_spacing(val->dVal);
}break;
case ODRAW::gtextAlign:
{
switch (props[i]->op)
{
case ODRAW::alignTextLeft:
xlsx_context->get_drawing_context().set_text_align(1); break;
case ODRAW::alignTextCenter:
xlsx_context->get_drawing_context().set_text_align(2); break;
case ODRAW::alignTextRight:
xlsx_context->get_drawing_context().set_text_align(3); break;
case ODRAW::alignTextWordJust:
xlsx_context->get_drawing_context().set_text_align(4); break;
case ODRAW::alignTextLetterJust:
xlsx_context->get_drawing_context().set_text_align(5); break;
}
}break;
case 0xff:
{
ODRAW::GeometryTextBooleanProperties *bools = dynamic_cast<ODRAW::GeometryTextBooleanProperties*>(props[i].get());
if (bools)
{
if (bools->fUsegFBold && bools->fBold) xlsx_context->get_drawing_context().set_wordart_bold (true);
if (bools->fUsegFItalic && bools->fItalic) xlsx_context->get_drawing_context().set_wordart_italic (true);
if (bools->fUsegFVertical && bools->fVertical) xlsx_context->get_drawing_context().set_wordart_vertical(true);
if (bools->fUsegFUnderline && bools->fUnderline) xlsx_context->get_drawing_context().set_wordart_underline(true);
if (bools->fUsegFStrikethrough && bools->fStrikethrough)xlsx_context->get_drawing_context().set_wordart_strike(true);
//if (bools->fUsegFShrinkFit && bools->fShrinkFit)
}
}break;
}
}
}
void XlsConverter::convert_text(std::vector<ODRAW::OfficeArtFOPTEPtr> & props)
{
if (props.empty()) return;
RECT text_margin = {0x00016530, 0x0000b298, 0x00016530, 0x0000b298};
for (size_t i = 0 ; i < props.size() ; i++)
{
switch(props[i]->opid)
{
case ODRAW::lTxid: break;
case ODRAW::txdir: break;
case ODRAW::dxTextLeft: text_margin.left = props[i]->op; break;
case ODRAW::dxTextRight: text_margin.right = props[i]->op; break;
case ODRAW::dyTextTop: text_margin.top = props[i]->op; break;
case ODRAW::dyTextBottom: text_margin.bottom = props[i]->op; break;
case ODRAW::WrapText:
{
xlsx_context->get_drawing_context().set_text_wrap(props[i]->op);
}break;
case ODRAW::txflTextFlow:
{
xlsx_context->get_drawing_context().set_text_vertical(props[i]->op);
}break;
case ODRAW::textBooleanProperties:
{
ODRAW::TextBooleanProperties *bools = dynamic_cast<ODRAW::TextBooleanProperties*>(props[i].get());
if (bools)
{
if (bools->fUsefFitShapeToText)
{
xlsx_context->get_drawing_context().set_text_fit_shape(bools->fFitShapeToText);
}
if (bools->fUsefAutoTextMargin)
{
}
}
}break;
case ODRAW::anchorText:
{
switch (props[i]->op)
{
case ODRAW::anchorTop:
case ODRAW::anchorTopBaseline:
{
xlsx_context->get_drawing_context().set_text_align (1);
xlsx_context->get_drawing_context().set_text_vert_align (1);
}break;
case ODRAW::anchorMiddle:
{
xlsx_context->get_drawing_context().set_text_align (1);
xlsx_context->get_drawing_context().set_text_vert_align (2);
}break;
case ODRAW::anchorBottom:
case ODRAW::anchorBottomBaseline:
{
xlsx_context->get_drawing_context().set_text_align (1);
xlsx_context->get_drawing_context().set_text_vert_align (3);
}break;
case ODRAW::anchorTopCentered:
case ODRAW::anchorTopCenteredBaseline:
{
xlsx_context->get_drawing_context().set_text_align (2);
xlsx_context->get_drawing_context().set_text_vert_align (1);
}break;
case ODRAW::anchorMiddleCentered:
{
xlsx_context->get_drawing_context().set_text_align (2);
xlsx_context->get_drawing_context().set_text_vert_align (2);
}break;
case ODRAW::anchorBottomCentered:
case ODRAW::anchorBottomCenteredBaseline:
{
xlsx_context->get_drawing_context().set_text_align (2);
xlsx_context->get_drawing_context().set_text_vert_align (3);
}break;
}
}break;
default:
int j = 0;
break;
}
}
xlsx_context->get_drawing_context().set_text_margin(text_margin);
}
void XlsConverter::convert_shadow(std::vector<ODRAW::OfficeArtFOPTEPtr> & props)
{
if (props.empty()) return;
xlsx_context->get_drawing_context().set_shadow_enabled(true);
for (size_t i = 0 ; i < props.size() ; i++)
{
switch(props[i]->opid)
{
case ODRAW::shadowType:
{
xlsx_context->get_drawing_context().set_shadow_type(props[i]->op);
}break;
case ODRAW::shadowColor:
{
ODRAW::OfficeArtCOLORREF color((_UINT32)props[i]->op);
if (!color.sColorRGB.empty())
xlsx_context->get_drawing_context().set_shadow_color(color.nColorRGB, color.sColorRGB);
}break;
case ODRAW::shadowHighlight:
{
ODRAW::OfficeArtCOLORREF color((_UINT32)props[i]->op);
if (!color.sColorRGB.empty())
xlsx_context->get_drawing_context().set_shadow_highlight(color.nColorRGB, color.sColorRGB);
}break;
case ODRAW::shadowCrMod:
{
}break;
case ODRAW::shadowOpacity:
{
ODRAW::FixedPoint * fixed_point = static_cast<ODRAW::FixedPoint *>(props[i].get());
xlsx_context->get_drawing_context().set_shadow_opacity(fixed_point->dVal);
}break;
case ODRAW::shadowOffsetX:
{
xlsx_context->get_drawing_context().set_shadow_offsetX((_INT32)props[i]->op);
}break;
case ODRAW::shadowOffsetY:
{
xlsx_context->get_drawing_context().set_shadow_offsetY((_INT32)props[i]->op);
}break;
//case ODRAW::shadowSecondOffsetX:
//{
//}break;
//case ODRAW::shadowSecondOffsetY:
//{
//}break;
case ODRAW::shadowScaleXToX:
{
ODRAW::FixedPoint * fixed_point = static_cast<ODRAW::FixedPoint *>(props[i].get());
xlsx_context->get_drawing_context().set_shadow_scaleX2X(fixed_point->dVal);
}break;
case ODRAW::shadowScaleYToX:
{
}break;
case ODRAW::shadowScaleXToY:
{
}break;
case ODRAW::shadowScaleYToY:
{
ODRAW::FixedPoint * fixed_point = static_cast<ODRAW::FixedPoint *>(props[i].get());
xlsx_context->get_drawing_context().set_shadow_scaleY2Y(fixed_point->dVal);
}break;
//case ODRAW::shadowPerspectiveX:
//{
//}break;
//case ODRAW::shadowPerspectiveY:
//{
//}break;
//case ODRAW::shadowWeight:
//{
//}break;
case ODRAW::shadowOriginX:
{
ODRAW::FixedPoint * fixed_point = static_cast<ODRAW::FixedPoint *>(props[i].get());
xlsx_context->get_drawing_context().set_shadow_originX(fixed_point->dVal);
}break;
case ODRAW::shadowOriginY:
{
ODRAW::FixedPoint * fixed_point = static_cast<ODRAW::FixedPoint *>(props[i].get());
xlsx_context->get_drawing_context().set_shadow_originY(fixed_point->dVal);
}break;
}
}
}
void XlsConverter::convert_shape(std::vector<ODRAW::OfficeArtFOPTEPtr> & props)
{
if (props.empty()) return;
for (size_t i = 0 ; i < props.size() ; i++)
{
}
}
void XlsConverter::convert_group_shape(std::vector<ODRAW::OfficeArtFOPTEPtr> & props)
{
if (props.empty()) return;
for (size_t i = 0 ; i < props.size() ; i++)
{
switch(props[i]->opid)
{
case 0x380:
{
ODRAW::AnyString *str = dynamic_cast<ODRAW::AnyString*>(props[i].get());
xlsx_context->get_drawing_context().set_name(str->string_);
}break;
case 0x381:
{
ODRAW::AnyString *str = dynamic_cast<ODRAW::AnyString*>(props[i].get());
xlsx_context->get_drawing_context().set_description(str->string_);
}break;
case 0x0382:
{
ODRAW::PihlShape *pihlShape = dynamic_cast<ODRAW::PihlShape*>(props[i].get());
if (pihlShape)
{
std::wstring sTarget;
bool bExternal = false;
if (pihlShape->complex.hyperlink.hlstmfHasMoniker)
{
sTarget = GetTargetMoniker(pihlShape->complex.hyperlink.oleMoniker.data.get());
bExternal = true;
}
else if (pihlShape->complex.hyperlink.hlstmfHasLocationStr)
{
sTarget = pihlShape->complex.hyperlink.location;
}
std::wstring sDisplay = pihlShape->complex.hyperlink.displayName;
if (sDisplay.empty()) sDisplay = sTarget;
xlsx_context->get_drawing_context().set_hyperlink( sTarget, sDisplay, bExternal);
}
}break;
case 0x03A9:
{
ODRAW::MetroBlob *alternative_data = dynamic_cast<ODRAW::MetroBlob*>(props[i].get());
if (alternative_data)
{
xlsx_context->get_drawing_context().set_alternative_drawing( alternative_data->xmlString);
}
}break;
case 0x03BF:
{
ODRAW::GroupShapeBooleanProperties *bools = dynamic_cast<ODRAW::GroupShapeBooleanProperties*>(props[i].get());
if (bools)
{
if (bools->fHidden && bools->fUsefHidden)
xlsx_context->get_drawing_context().set_hidden(true);
}
}break;
}
}
}
void XlsConverter::convert(XLS::Note* note)
{
if (note == NULL) return;
note->note_sh.calculate();
xlsx_context->get_comments_context().set_ref (note->note_sh.ref_, note->note_sh.col, note->note_sh.row);
xlsx_context->get_comments_context().set_author (note->note_sh.stAuthor);
xlsx_context->get_comments_context().set_visibly(note->note_sh.fShow);
xlsx_context->get_drawing_context().set_object_id (xlsx_context->get_comments_context().get_id());
xlsx_context->get_drawing_context().set_object_visible (note->note_sh.fShow);
xlsx_context->get_drawing_context().set_object_anchor (note->note_sh.col, note->note_sh.row);
if (xls_global_info->Version < 0x0600)
{
//todooo размеры произвольные .. можно сделать оценку по размеру строки
xlsx_context->get_drawing_context().set_sheet_anchor(0, 0, 0, 0, 0, 0, 0, 0, note->note_sh.x_, note->note_sh.y_, 120 * 12700., 64 * 12700.);
xlsx_context->get_drawing_context().set_text(std::wstring(L"<t>") + note->note_sh.stText.value() + std::wstring(L"</t>"));
}
}
void XlsConverter::convert_transform(std::vector<ODRAW::OfficeArtFOPTEPtr> & props)
{
for (size_t i = 0 ; i < props.size() ; i++)
{
switch(props[i]->opid)
{
case 0x0004:
{
ODRAW::FixedPoint * fixed_point = static_cast<ODRAW::FixedPoint *>(props[i].get());
xlsx_context->get_drawing_context().set_rotation(fixed_point->dVal);
}break;
}
}
}
void XlsConverter::convert(ODRAW::OfficeArtTertiaryFOPT * fort)
{
if (fort == NULL) return;
convert_shape (fort->fopt.Shape_props);
convert_group_shape (fort->fopt.GroupShape_props);
convert_transform (fort->fopt.Transform_props);
convert_blip (fort->fopt.Blip_props);
convert_geometry (fort->fopt.Geometry_props);
convert_fill_style (fort->fopt.FillStyle_props);
convert_line_style (fort->fopt.LineStyle_props);
convert_shadow (fort->fopt.Shadow_props);
convert_text (fort->fopt.Text_props);
convert_geometry_text (fort->fopt.GeometryText_props);
}
void XlsConverter::convert(ODRAW::OfficeArtFOPT * fort)
{
if (fort == NULL) return;
convert_shape (fort->fopt.Shape_props);
convert_group_shape (fort->fopt.GroupShape_props);
convert_transform (fort->fopt.Transform_props);
convert_geometry (fort->fopt.Geometry_props);
convert_fill_style (fort->fopt.FillStyle_props);
convert_blip (fort->fopt.Blip_props);
convert_line_style (fort->fopt.LineStyle_props);
convert_shadow (fort->fopt.Shadow_props);
convert_text (fort->fopt.Text_props);
convert_geometry_text (fort->fopt.GeometryText_props);
}
void XlsConverter::convert(XLS::SHAREDSTRINGS* sharedstrings)
{
int count = xls_global_info->startAddedSharedStrings + xls_global_info->arAddedSharedStrings.size();
CP_XML_WRITER(xlsx_context->shared_strings())
{
CP_XML_NODE(L"sst")
{
CP_XML_ATTR(L"uniqueCount", count);
CP_XML_ATTR(L"xmlns", "http://schemas.openxmlformats.org/spreadsheetml/2006/main");
if (sharedstrings)
{
for (std::list<XLS::BaseObjectPtr>::iterator it = sharedstrings->elements_.begin(); it != sharedstrings->elements_.end(); ++it)
{
(*it)->serialize(CP_XML_STREAM());
}
}
for (size_t i = 0 ; i < xls_global_info->arAddedSharedStrings.size(); i++)
{
CP_XML_NODE(L"si")
{
CP_XML_NODE(L"t")
{
CP_XML_ATTR(L"xml:space", "preserve");
CP_XML_STREAM() << STR::escape_ST_Xstring(XmlUtils::EncodeXmlString(xls_global_info->arAddedSharedStrings[i]));
}
}
}
}
}
}
void XlsConverter::convert(XLS::TxO * text_obj)
{
if (text_obj == NULL) return;
int rot = text_obj->rot;
if (rot > 0)
{
switch(rot)
{
case 1: //text appears top to bottom; letters are upright
{
xlsx_context->get_drawing_context().set_text_vertical(5);
}break;
case 2: //text is rotated 90 degrees counterclockwise
{
if (text_obj->hAlignment == (unsigned char)1) text_obj->hAlignment = 3;
else if (text_obj->hAlignment == (unsigned char)3) text_obj->hAlignment = 1;
xlsx_context->get_drawing_context().set_text_vertical(2);
}break;
case 3: //text is rotated 90 degrees clockwise
{
if (text_obj->vAlignment == (unsigned char)1) text_obj->vAlignment = 3;
else if (text_obj->vAlignment == (unsigned char)3) text_obj->vAlignment = 1;
xlsx_context->get_drawing_context().set_text_vertical(3);
}break;
}
}
xlsx_context->get_drawing_context().set_text_align (text_obj->hAlignment);
xlsx_context->get_drawing_context().set_text_vert_align (text_obj->vAlignment);
std::wstringstream strm, strm_vml;
text_obj->serialize(strm);
xlsx_context->get_drawing_context().set_text(strm.str());
text_obj->serialize_vml(strm_vml);
xlsx_context->get_drawing_context().set_text_vml(strm_vml.str());
}
void XlsConverter::convert(XLS::Obj * obj)
{
if ( obj == NULL ) return;
//controls & objects
if ( obj->cmo.ot == 8 && obj->pictFmla.fExist && obj->pictFlags.fExist)
{
std::wstring info;
if (obj->pictFmla.fmla.bFmlaExist)
{
if (obj->pictFmla.fmla.bInfoExist)
info = obj->pictFmla.fmla.embedInfo.strClass.value();
}
if (obj->pictFlags.fCtl && obj->pictFlags.fPrstm && xls_global_info->controls_data.first)//Controls Storage
{
//binary data
xlsx_context->get_mediaitems().create_activeX_path(xlsx_path);
std::wstring target_bin;
std::wstring objectId_bin = xlsx_context->get_mediaitems().add_control_activeX(target_bin);
NSFile::CFileBinary file;
if ( file.CreateFileW(xlsx_context->get_mediaitems().activeX_path() + target_bin) )
{
file.WriteFile(xls_global_info->controls_data.first.get() + obj->pictFmla.lPosInCtlStm, obj->pictFmla.cbBufInCtlStm);
file.CloseFile();
}
std::wstring objectId_xml = xlsx_context->start_activeX();
xlsx_context->get_drawing_context().set_control_activeX(objectId_xml);
xlsx_context->current_activeX().setDataBinRid(objectId_bin, target_bin);
xlsx_context->current_activeX().setProgId(info);
xlsx_context->current_activeX().setLicense(obj->pictFmla.key.keyBuf);
}
else if (!obj->pictFlags.fPrstm)
{
std::wstring object_stream;
if (obj->pictFlags.fDde) object_stream = L"LNK";
else object_stream = L"MBD";
object_stream += XmlUtils::ToString(obj->pictFmla.lPosInCtlStm, L"%08X") + L"/";
if (xls_file->storage_->isDirectory(object_stream))
{
xlsx_context->get_mediaitems().create_embeddings_path(xlsx_path);
std::wstring target;
if (xls_file->storage_->exists(object_stream + L"Workbook")) target = L".xls";
if (xls_file->storage_->exists(object_stream + L"WordDocument")) target = L".doc";
std::wstring objectId = xlsx_context->get_mediaitems().add_embedding(target, info);
POLE::Storage *storageOle = new POLE::Storage((xlsx_context->get_mediaitems().embeddings_path() + target).c_str());
if ((storageOle) && (storageOle->open(true, true)))
{
xls_file->copy(0, object_stream, storageOle, false, true);
storageOle->close();
delete storageOle;
}
xlsx_context->current_sheet().sheet_rels().add(oox::relationship(
objectId, L"http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject", L"../embeddings/" + target));
xlsx_context->get_drawing_context().set_ole_object(objectId, info);
}
}
if (obj->pictFmla.key.fmlaLinkedCell.bFmlaExist)
{
std::wstring link = obj->pictFmla.key.fmlaLinkedCell.fmla.getAssembledFormula(true);
xlsx_context->get_drawing_context().set_object_link(link);
}
if (obj->pictFmla.key.fmlaListFillRange.bFmlaExist)
{
std::wstring link = obj->pictFmla.key.fmlaListFillRange.fmla.getAssembledFormula(true);
xlsx_context->get_drawing_context().set_object_fmlaRange(link);
}
}
if (obj->sbs.fExist)
{
xlsx_context->get_drawing_context().set_object_x_val(obj->sbs.iVal);
xlsx_context->get_drawing_context().set_object_x_min(obj->sbs.iMin);
xlsx_context->get_drawing_context().set_object_x_max(obj->sbs.iMax);
xlsx_context->get_drawing_context().set_object_x_inc(obj->sbs.dInc);
xlsx_context->get_drawing_context().set_object_x_page(obj->sbs.dPage);
xlsx_context->get_drawing_context().set_object_3D(!obj->sbs.fNo3d);
xlsx_context->get_drawing_context().set_object_hscroll(obj->sbs.fHoriz);
xlsx_context->get_drawing_context().set_object_dx(obj->sbs.dxScroll);
}
if (obj->list.fExist)
{
xlsx_context->get_drawing_context().set_object_x_sel(obj->list.iSel);
xlsx_context->get_drawing_context().set_object_x_sel_type(obj->list.wListSelType);
xlsx_context->get_drawing_context().set_object_lct(obj->list.lct);
xlsx_context->get_drawing_context().set_object_3D(!obj->list.fNo3d);
if (obj->list.fmla.bFmlaExist)
{
std::wstring link = obj->list.fmla.fmla.getAssembledFormula(true);
xlsx_context->get_drawing_context().set_object_fmlaRange(link);
}
if (obj->list.dropData)
{
xlsx_context->get_drawing_context().set_object_drop_style(obj->list.dropData->wStyle);
xlsx_context->get_drawing_context().set_object_drop_lines(obj->list.dropData->cLine);
}
}
if (obj->checkBox.fExist)
{
xlsx_context->get_drawing_context().set_object_checked(obj->checkBox.fChecked);
xlsx_context->get_drawing_context().set_object_3D(!obj->checkBox.fNo3d);
//unsigned short accel;
}
if (obj->radioButton.fExist)
{
//unsigned short idRadNext;
//Boolean<unsigned short> fFirstBtn;
}
if (obj->edit.fExist)
{
xlsx_context->get_drawing_context().set_object_multiLine(obj->edit.fMultiLine);
xlsx_context->get_drawing_context().set_object_vscroll(obj->edit.fVScroll);
//unsigned short ivtEdit;
//unsigned short id;
}
bool full_ref = false;
if (obj->cmo.ot > 0x06) full_ref = true;
if (obj->linkFmla.fExist && obj->linkFmla.fmla.bFmlaExist)
{
std::wstring link = obj->linkFmla.fmla.fmla.getAssembledFormula(full_ref);
xlsx_context->get_drawing_context().set_object_link(link);
}
if (obj->macro.fExist && obj->macro.fmla.bFmlaExist)
{
std::wstring macro = obj->macro.fmla.fmla.getAssembledFormula(full_ref);
xlsx_context->get_drawing_context().set_macro(macro);
}
}
void XlsConverter::convert(XLS::ChartSheetSubstream* chart)
{
if (chart == NULL) return;
chart->serialize(xlsx_context->current_chart().chartData());
//convert(chart->m_OBJECTSCHART.get());непонятные какие то текстбоксы - пустые и бз привязок
}
void XlsConverter::convert(XLS::PIVOTVIEW* pivot_view)
{
if (pivot_view == NULL) return;
std::wstringstream strm;
pivot_view->serialize(strm);
int index_view = xlsx_context->get_pivots_context().add_view(strm.str(), pivot_view->indexCache);
if (index_view > 0)
{
xlsx_context->current_sheet().sheet_rels().add(oox::relationship(L"pvId" + std::to_wstring(index_view),
L"http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotTable",
L"../pivotTables/pivotTable" + std::to_wstring(index_view) + L".xml"));
}
}
void XlsConverter::convert(XLS::PIVOTCACHEDEFINITION* pivot_cached)
{
if (pivot_cached == NULL) return;
std::wstringstream strmD, strmR;
pivot_cached->serialize_definitions(strmD);
pivot_cached->serialize_records(strmR);
xlsx_context->get_pivots_context().add_cache(strmD.str(), strmR.str());
if (!xls_global_info->mapPivotCacheExternal.empty())
{
xlsx_context->get_pivots_context().add_cache_external(xls_global_info->mapPivotCacheExternal);
}
}
void XlsConverter::convert(XLS::SUPBOOK* external)
{
if (external == NULL) return;
if (external->IsExternal() == false) return;
xlsx_context->start_external();
external->serialize(xlsx_context->current_external().externalData());
if (!external->sExternPathLink.empty()) //???
{
xlsx_context->current_external().add_rels(false, L"rId1", external->sExternPathLink, oox::external_items::typeExternalLink);
}
xlsx_context->end_external();
}
void XlsConverter::convert(XLS::QUERYTABLE* query_table)
{
if (query_table == NULL) return;
std::wstringstream strm;
query_table->serialize(strm);
xlsx_context->add_query_table(strm.str());
}