mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-07-11 10:07:28 +08:00
git-svn-id: svn://fileserver/activex/AVS/Sources/TeamlabOffice/trunk/ServerComponents@64388 954022d7-b5bf-4e40-9824-e11837661b57
956 lines
26 KiB
C++
956 lines
26 KiB
C++
#include "XlsConverter.h"
|
|
|
|
#include "../XlsFormat/Binary/CompoundFile.h"
|
|
#include "../XlsFormat/Binary/CFStreamCacheReader.h"
|
|
|
|
#include "../XlsFormat/Logic/GlobalWorkbookInfo.h"
|
|
#include "../XlsFormat/Logic/WorkbookStreamObject.h"
|
|
#include "../XlsFormat/Logic/WorksheetSubstream.h"
|
|
#include "../XlsFormat/Logic/GlobalsSubstream.h"
|
|
#include "../XlsFormat/Logic/ChartSheetSubstream.h"
|
|
|
|
#include "../XlsFormat/Logic/BinProcessor.h"
|
|
#include "../XlsFormat/Logic/SummaryInformationStream/SummaryInformation.h"
|
|
|
|
#include "../XlsFormat/Logic/Biff_unions/FORMATTING.h"
|
|
#include "../XlsFormat/Logic/Biff_unions/THEME.h"
|
|
#include "../XlsFormat/Logic/Biff_unions/GLOBALS.h"
|
|
#include "../XlsFormat/Logic/Biff_unions/COLUMNS.h"
|
|
#include "../XlsFormat/Logic/Biff_unions/SHAREDSTRINGS.h"
|
|
#include "../XlsFormat/Logic/Biff_unions/HLINK.h"
|
|
#include "../XlsFormat/Logic/Biff_unions/LBL.h"
|
|
#include "../XlsFormat/Logic/Biff_unions/OBJECTS.h"
|
|
#include "../XlsFormat/Logic/Biff_unions/MSODRAWINGGROUP.h"
|
|
#include "../XlsFormat/Logic/Biff_unions/OBJ.h"
|
|
#include "../XlsFormat/Logic/Biff_unions/TEXTOBJECT.h"
|
|
#include "../XlsFormat/Logic/Biff_unions/CHART.h"
|
|
|
|
#include <Logic/Biff_records/HLink.h>
|
|
#include <Logic/Biff_records/MsoDrawingGroup.h>
|
|
#include <Logic/Biff_records/MsoDrawing.h>
|
|
#include <Logic/Biff_records/Obj.h>
|
|
#include <Logic/Biff_records/TxO.h>
|
|
|
|
#include <Logic/Biff_structures/URLMoniker.h>
|
|
#include <Logic/Biff_structures/FileMoniker.h>
|
|
|
|
#include <Logic/Biff_structures/ODRAW/OfficeArtBStoreContainer.h>
|
|
#include <Logic/Biff_structures/ODRAW/SimpleOfficeArtContainers.h>
|
|
#include <Logic/Biff_structures/ODRAW/OfficeArtFOPT.h>
|
|
#include <Logic/Biff_structures/ODRAW/OfficeArtFOPTE.h>
|
|
#include <Logic/Biff_structures/ODRAW/OfficeArtFSP.h>
|
|
#include <Logic/Biff_structures/ODRAW/OfficeArtBlip.h>
|
|
|
|
#include "xlsx_conversion_context.h"
|
|
#include "xlsx_package.h"
|
|
|
|
#include <simple_xml_writer.h>
|
|
|
|
#include <boost/lexical_cast.hpp>
|
|
#include <boost/utility.hpp>
|
|
#include "../../../DesktopEditor/common/File.h"
|
|
#include "../../../DesktopEditor/raster/BgraFrame.h"
|
|
|
|
#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;
|
|
#endif
|
|
|
|
XlsConverter::XlsConverter(const std::wstring & xls_file, const std::wstring & _xlsx_path, const ProgressCallback* CallBack)
|
|
{
|
|
xlsx_path = _xlsx_path;
|
|
output_document = NULL;
|
|
xlsx_context = NULL;
|
|
|
|
pCallBack = CallBack;
|
|
bUserStopConvert = false;
|
|
|
|
try{
|
|
XLS::CompoundFile cfile(xls_file, XLS::CompoundFile::cf_ReadMode);
|
|
|
|
XLS::CFStreamPtr summary;
|
|
XLS::CFStreamPtr doc_summary;
|
|
|
|
try
|
|
{
|
|
summary = cfile.getSummaryInformationStream();
|
|
}
|
|
catch (...)
|
|
{
|
|
}
|
|
|
|
try
|
|
{
|
|
doc_summary = cfile.getDocumentSummaryInformationStream();
|
|
}
|
|
catch (...)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_UINT16 workbook_code_page = XLS::WorkbookStreamObject::DefaultCodePage;
|
|
if(summary)
|
|
{
|
|
OLEPS::SummaryInformation summary_info(summary);
|
|
workbook_code_page = summary_info.GetCodePage();
|
|
}
|
|
else if(doc_summary)
|
|
{
|
|
OLEPS::SummaryInformation doc_summary_info(doc_summary);
|
|
workbook_code_page = doc_summary_info.GetCodePage();
|
|
}
|
|
|
|
if(1200/* UTF-16 */ == workbook_code_page || 0/*error*/ == workbook_code_page)
|
|
{
|
|
workbook_code_page = XLS::WorkbookStreamObject::DefaultCodePage;
|
|
}
|
|
|
|
xls_global_info = boost::shared_ptr<XLS::GlobalWorkbookInfo>(new XLS::GlobalWorkbookInfo(workbook_code_page));
|
|
|
|
|
|
XLS::CFStreamCacheReader stream_reader(cfile.getWorkbookStream(), xls_global_info);
|
|
|
|
xls_document = boost::shared_ptr<XLS::WorkbookStreamObject>(new XLS::WorkbookStreamObject(workbook_code_page));
|
|
|
|
XLS::BinReaderProcessor proc(stream_reader , xls_document.get() , true);
|
|
proc.mandatory(*xls_document.get());
|
|
|
|
}
|
|
catch(...)
|
|
{
|
|
return;
|
|
}
|
|
if (UpdateProgress(400000))return;
|
|
|
|
output_document = new oox::package::xlsx_document();
|
|
xlsx_context = new oox::xlsx_conversion_context(output_document);
|
|
}
|
|
|
|
XlsConverter::~XlsConverter()
|
|
{
|
|
if (xlsx_context) delete xlsx_context;
|
|
if (output_document) delete output_document;
|
|
}
|
|
|
|
#define PROGRESSEVENT_ID 0
|
|
|
|
bool XlsConverter::UpdateProgress(long nComplete)
|
|
{
|
|
if (pCallBack)
|
|
{
|
|
pCallBack->OnProgress (pCallBack->caller, PROGRESSEVENT_ID, nComplete);
|
|
|
|
bUserStopConvert = 0;
|
|
pCallBack->OnProgressEx (pCallBack->caller, PROGRESSEVENT_ID, nComplete, &bUserStopConvert);
|
|
|
|
if (bUserStopConvert !=0 ) return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
void XlsConverter::write()
|
|
{
|
|
if (!output_document)return;
|
|
output_document->write(xlsx_path);
|
|
|
|
delete output_document; output_document = NULL;
|
|
|
|
if (UpdateProgress(1000000))return;
|
|
}
|
|
|
|
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());
|
|
|
|
if (UpdateProgress(800000))return;
|
|
|
|
xlsx_context->end_document();
|
|
|
|
if (UpdateProgress(850000))return;
|
|
}
|
|
|
|
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);
|
|
}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((XLS::GlobalsSubstream*)woorkbook->m_GlobalsSubstream.get());
|
|
|
|
for (int i=0 ; i < woorkbook->m_WorksheetSubstream.size(); i++)
|
|
{
|
|
xlsx_context->start_table(xls_global_info->sheets_names[i]);
|
|
|
|
if (woorkbook->m_WorksheetSubstream[i]->get_type() == XLS::typeWorksheetSubstream)
|
|
{
|
|
convert(dynamic_cast<XLS::WorksheetSubstream*>(woorkbook->m_WorksheetSubstream[i].get()));
|
|
}
|
|
else if (woorkbook->m_WorksheetSubstream[i]->get_type() == XLS::typeChartSheetSubstream)
|
|
{
|
|
//в xl\chartsheets
|
|
convert(dynamic_cast<XLS::ChartSheetSubstream*>(woorkbook->m_WorksheetSubstream[i].get()));
|
|
}
|
|
|
|
xlsx_context->end_table();
|
|
}
|
|
|
|
for (std::list<XLS::BaseObjectPtr>::iterator it = woorkbook->elements_.begin(); it != woorkbook->elements_.end(); it++)
|
|
{
|
|
convert(it->get());
|
|
}
|
|
}
|
|
|
|
void XlsConverter::convert(XLS::WorksheetSubstream* sheet)
|
|
{
|
|
if (sheet == NULL) return;
|
|
|
|
if (sheet->m_Dimensions)
|
|
{
|
|
sheet->m_Dimensions->serialize(xlsx_context->current_sheet().dimension());
|
|
}
|
|
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 (globals && columns)
|
|
{
|
|
globals->m_DefColWidth = columns->m_DefColWidth;
|
|
}
|
|
sheet->m_GLOBALS->serialize(xlsx_context->current_sheet().sheetFormat());
|
|
}
|
|
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_MergeCells.size() > 0)
|
|
{
|
|
CP_XML_WRITER(xlsx_context->current_sheet().mergeCells())
|
|
{
|
|
CP_XML_NODE(L"mergeCells")
|
|
{
|
|
for (int i = 0 ; i < sheet->m_MergeCells.size(); i++)
|
|
{
|
|
sheet->m_MergeCells[i]->serialize(CP_XML_STREAM());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (int i = 0 ; i < sheet->m_HLINK.size(); i++)
|
|
{
|
|
convert((XLS::HLINK*)sheet->m_HLINK[i].get());
|
|
}
|
|
convert((XLS::OBJECTS*)sheet->m_OBJECTS.get());
|
|
|
|
if (sheet->m_PAGESETUP)
|
|
{
|
|
sheet->m_PAGESETUP->serialize(xlsx_context->current_sheet().pageProperties());
|
|
}
|
|
}
|
|
|
|
void XlsConverter::convert(XLS::GlobalsSubstream* global)
|
|
{
|
|
if (global == NULL) return;
|
|
|
|
convert((XLS::FORMATTING*)global->m_Formating.get());
|
|
|
|
convert((XLS::THEME*)global->m_Theme.get());
|
|
|
|
convert((XLS::SHAREDSTRINGS*)global->m_SHAREDSTRINGS.get());
|
|
|
|
for (int i = 0 ; i < global->m_LBL.size(); i++)
|
|
{
|
|
convert((XLS::LBL*)global->m_LBL[i].get());
|
|
}
|
|
|
|
for (int i = 0 ; i < global->m_MSODRAWINGGROUP.size(); i++)
|
|
{
|
|
convert((XLS::MSODRAWINGGROUP*)global->m_MSODRAWINGGROUP[i].get());
|
|
}
|
|
}
|
|
|
|
typedef boost::unordered_map<XLS::FillInfo, int> mapFillInfo;
|
|
typedef boost::unordered_map<XLS::BorderInfo, int> mapBorderInfo;
|
|
|
|
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");
|
|
|
|
formating->serialize1(CP_XML_STREAM()); //важен порядок в styles
|
|
|
|
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 (int 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 (int i = 0 ;i < borders_out.size(); i++)
|
|
{
|
|
borders_out[i].serialize(CP_XML_STREAM());
|
|
}
|
|
}
|
|
|
|
formating->serialize2(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()));
|
|
|
|
|
|
}
|
|
|
|
void XlsConverter::convert(ODRAW::OfficeArtBStoreContainer* art_bstore)
|
|
{
|
|
if (art_bstore == NULL) return;
|
|
if (art_bstore->rgfb.size() < 1) return;
|
|
|
|
std::wstring xl_path = xlsx_path + FILE_SEPARATOR_STR + L"xl";
|
|
FileSystem::Directory::CreateDirectory(xl_path.c_str());
|
|
|
|
FileSystem::Directory::CreateDirectory((xl_path + FILE_SEPARATOR_STR + L"media").c_str());
|
|
|
|
for (int i =0 ; i < art_bstore->rgfb.size(); i++)
|
|
{
|
|
int bin_id = i + 1;
|
|
if (art_bstore->rgfb[i]->data_size > 0 && art_bstore->rgfb[i]->pict_data)
|
|
{
|
|
bool res = false;
|
|
std::wstring file_name = L"image" + boost::lexical_cast<std::wstring>(bin_id);
|
|
if (art_bstore->rgfb[i]->pict_type == L"dib_data")
|
|
{
|
|
file_name += std::wstring(L".png");
|
|
|
|
BITMAPINFOHEADER * header = (BITMAPINFOHEADER *)art_bstore->rgfb[i]->pict_data;
|
|
|
|
CBgraFrame frame;
|
|
int offset = art_bstore->rgfb[i]->data_size - header->biSizeImage;
|
|
frame.put_Data((BYTE*)art_bstore->rgfb[i]->pict_data + header->biSize);
|
|
|
|
frame.put_Height(header->biHeight);
|
|
frame.put_Width (header->biWidth);
|
|
frame.put_Stride(-header->biBitCount / 8 * header->biWidth);
|
|
|
|
res = frame.SaveFile(xl_path + FILE_SEPARATOR_STR + L"media" + FILE_SEPARATOR_STR + file_name, 4);
|
|
frame.put_Data(NULL);
|
|
}
|
|
else
|
|
{
|
|
file_name += art_bstore->rgfb[i]->pict_type;
|
|
|
|
NSFile::CFileBinary file;
|
|
if (file.CreateFileW(xl_path + FILE_SEPARATOR_STR + L"media" + FILE_SEPARATOR_STR + file_name))
|
|
{
|
|
file.WriteFile((BYTE*)art_bstore->rgfb[i]->pict_data, art_bstore->rgfb[i]->data_size);
|
|
file.CloseFile();
|
|
res = true;
|
|
}
|
|
}
|
|
|
|
if (res)
|
|
xlsx_context->get_mediaitems().add_image(L"media/" + file_name, bin_id);
|
|
}
|
|
else
|
|
{
|
|
//???
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
void XlsConverter::convert(XLS::HLINK * HLINK_)
|
|
{
|
|
XLS::HLink * hLink = dynamic_cast<XLS::HLink*>(HLINK_->m_HLink.get());
|
|
|
|
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.value();
|
|
}
|
|
|
|
std::wstring display = hLink->hyperlink.displayName;
|
|
|
|
if (display.empty()) display = target;
|
|
|
|
xlsx_context->get_table_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::THEME* theme)
|
|
{
|
|
if (theme == NULL) return;
|
|
}
|
|
|
|
void XlsConverter::convert(XLS::OBJECTS* objects)
|
|
{
|
|
if (objects == NULL) return;
|
|
|
|
ODRAW::OfficeArtSpgrContainer *spgr = dynamic_cast<ODRAW::OfficeArtSpgrContainer*>(objects->m_MsoDrawing.get()->rgChildRec.m_OfficeArtSpgrContainer.get());
|
|
|
|
bool note = false;
|
|
int ind = 0;
|
|
|
|
if ((spgr) && (ind < spgr->child_records.size()))
|
|
{
|
|
ODRAW::OfficeArtSpContainer *s = dynamic_cast<ODRAW::OfficeArtSpContainer*>(spgr->child_records[ind].get());
|
|
if (s)
|
|
{
|
|
ODRAW::OfficeArtFSP *fsp = dynamic_cast<ODRAW::OfficeArtFSP*>(s->m_OfficeArtFSP.get());
|
|
if ((fsp) && (fsp->fPatriarch)) ind++;
|
|
}
|
|
}
|
|
|
|
for ( std::list<XLS::BaseObjectPtr>::iterator elem = objects->elements_.begin(); elem != objects->elements_.end(); elem++)
|
|
{
|
|
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;
|
|
|
|
ODRAW::OfficeArtSpContainer *sp = NULL;
|
|
if (( spgr) && (ind < spgr->child_records.size()))
|
|
{
|
|
sp = dynamic_cast<ODRAW::OfficeArtSpContainer*>(spgr->child_records[ind++].get());
|
|
}
|
|
|
|
if (xlsx_context->get_drawing_context().start_drawing(type_object))
|
|
{
|
|
convert(sp);
|
|
|
|
if (!sp->m_OfficeArtAnchor)
|
|
{
|
|
if (( spgr) && (ind < spgr->child_records.size()))
|
|
{
|
|
sp = dynamic_cast<ODRAW::OfficeArtSpContainer*>(spgr->child_records[ind++].get());
|
|
}
|
|
convert(sp, true);
|
|
}
|
|
|
|
if (text_obj)
|
|
{
|
|
std::wstringstream strm;
|
|
text_obj->serialize(strm);
|
|
|
|
xlsx_context->get_drawing_context().set_text(strm.str());
|
|
}
|
|
if (chart)
|
|
{
|
|
}
|
|
xlsx_context->get_drawing_context().end_drawing();
|
|
}
|
|
|
|
if (TEXTOBJECT || CHART)
|
|
{
|
|
elem++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void XlsConverter::convert(ODRAW::OfficeArtSpContainer *sp, bool anchor_only)
|
|
{
|
|
if (sp == NULL) return;
|
|
|
|
if (!anchor_only)
|
|
{
|
|
convert(sp->m_OfficeArtFSP.get());
|
|
|
|
for (int 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::typeOfficeArtFSP:
|
|
{
|
|
convert(dynamic_cast<ODRAW::OfficeArtFSP *>(art));
|
|
}break;
|
|
case XLS::typeOfficeArtClientAnchorSheet:
|
|
{
|
|
art->serialize(strm);
|
|
xlsx_context->get_drawing_context().set_anchor(strm.str());
|
|
}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)
|
|
{
|
|
for (int i = 0 ; i < props.size() ; i++)
|
|
{
|
|
switch(props[i]->opid)
|
|
{
|
|
case 0x0181:
|
|
{
|
|
ODRAW::fillColor * fill = (ODRAW::fillColor *)(props[i].get());
|
|
ODRAW::OfficeArtCOLORREF color(fill->op);
|
|
if (!color.colorRGB.empty())
|
|
xlsx_context->get_drawing_context().set_fill_color(color.colorRGB);
|
|
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())
|
|
{
|
|
xlsx_context->get_drawing_context().set_fill_color(it->second);
|
|
}
|
|
}
|
|
else
|
|
xlsx_context->get_drawing_context().set_fill_color(color.index, color.fSchemeIndex ? 1 : 3 );
|
|
|
|
}break;
|
|
case 0x0186:
|
|
{
|
|
bool isIternal = false;
|
|
std::wstring target;
|
|
std::wstring rId = xlsx_context->get_mediaitems().find_image(props[i]->op , target, isIternal);
|
|
xlsx_context->get_drawing_context().set_image(target);
|
|
}break;
|
|
case 0x01BF:
|
|
{
|
|
ODRAW::FillStyleBooleanProperties * fill = (ODRAW::FillStyleBooleanProperties *)(props[i].get());
|
|
if (fill)
|
|
{
|
|
if (fill->fFilled == false)
|
|
xlsx_context->get_drawing_context().set_fill_type(0);
|
|
}
|
|
}break;
|
|
|
|
}
|
|
}
|
|
}
|
|
void XlsConverter::convert_line_style(std::vector<ODRAW::OfficeArtFOPTEPtr> & props)
|
|
{
|
|
for (int i = 0 ; i < props.size() ; i++)
|
|
{
|
|
switch(props[i]->opid)
|
|
{
|
|
case 0x01C0:
|
|
{
|
|
ODRAW::OfficeArtCOLORREF color(props[i]->op);
|
|
if (!color.colorRGB.empty())
|
|
xlsx_context->get_drawing_context().set_line_color(color.colorRGB);
|
|
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())
|
|
{
|
|
xlsx_context->get_drawing_context().set_line_color(it->second);
|
|
}
|
|
}
|
|
else
|
|
xlsx_context->get_drawing_context().set_line_color(color.index, color.fSchemeIndex ? 1 : 3 );
|
|
}break;
|
|
case 0x01C4:
|
|
{
|
|
xlsx_context->get_drawing_context().set_line_type(props[i]->op);
|
|
}break;
|
|
case 0x01C5: //blip
|
|
{
|
|
}break;
|
|
case 0x01CB:
|
|
xlsx_context->get_drawing_context().set_line_width(props[i]->op);
|
|
{
|
|
}break;
|
|
case 0x01CD:
|
|
{
|
|
xlsx_context->get_drawing_context().set_line_style(props[i]->op);
|
|
}break;
|
|
}
|
|
}
|
|
}
|
|
void XlsConverter::convert_blip(std::vector<ODRAW::OfficeArtFOPTEPtr> & props)
|
|
{
|
|
for (int i = 0 ; i < props.size() ; i++)
|
|
{
|
|
switch(props[i]->opid)
|
|
{
|
|
case 0x100:
|
|
{
|
|
xlsx_context->get_drawing_context().set_crop_top(props[i]->op);
|
|
}break;
|
|
case 0x101:
|
|
{
|
|
xlsx_context->get_drawing_context().set_crop_bottom(props[i]->op);
|
|
}break;
|
|
case 0x102:
|
|
{
|
|
xlsx_context->get_drawing_context().set_crop_left(props[i]->op);
|
|
}break;
|
|
case 0x103:
|
|
{
|
|
xlsx_context->get_drawing_context().set_crop_right(props[i]->op);
|
|
}break;
|
|
case 0x104:
|
|
{
|
|
bool isIternal = false;
|
|
std::wstring target;
|
|
std::wstring rId = xlsx_context->get_mediaitems().find_image(props[i]->op , target, isIternal);
|
|
xlsx_context->get_drawing_context().set_image(target);
|
|
}break;
|
|
}
|
|
}
|
|
}
|
|
void XlsConverter::convert_geometry(std::vector<ODRAW::OfficeArtFOPTEPtr> & props)
|
|
{
|
|
std::vector<ODRAW::MSOPOINT> points;
|
|
std::vector<ODRAW::MSOPATHINFO> command;
|
|
ODRAW::ShapePath::msoShapePathType shapeType;
|
|
oox::_rect rect;
|
|
|
|
for (int i = 0 ; i < props.size() ; i++)
|
|
{
|
|
switch(props[i]->opid)
|
|
{
|
|
case 0x0140: rect.left = props[i]->op; break;
|
|
case 0x0141: rect.top = props[i]->op; break;
|
|
case 0x0142: rect.right = props[i]->op; break;
|
|
case 0x0143: rect.bottom = props[i]->op; break;
|
|
case 0x0144: shapeType = (ODRAW::ShapePath::msoShapePathType)props[i]->op; break;
|
|
case 0x0145:
|
|
{
|
|
ODRAW::PVertices * v = (ODRAW::PVertices *)(props[i].get());
|
|
points = v->path_complex.data;
|
|
}break;
|
|
case 0x0146:
|
|
{
|
|
ODRAW::PSegmentInfo * s = (ODRAW::PSegmentInfo *)(props[i].get());
|
|
command = s->path_complex.data;
|
|
}break;
|
|
}
|
|
}
|
|
|
|
if (points.size() > 0 || command.size() > 0)
|
|
{
|
|
std::wstringstream strm;
|
|
CP_XML_WRITER(strm)
|
|
{
|
|
if (command.size() == 0)
|
|
{
|
|
for (int i = 0 ; i < points.size(); i++)
|
|
{
|
|
CP_XML_NODE(L"a:lnTo")
|
|
{
|
|
CP_XML_NODE(L"a:pt")
|
|
{
|
|
CP_XML_ATTR(L"x", points[i].x);
|
|
CP_XML_ATTR(L"y", points[i].y);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int ind_point = 0;
|
|
std::wstring comm[] = { L"a:lnTo", L"a:cubicBezTo", L"a:moveTo", L"a:close" };
|
|
int count_point[] = { 1, 3, 1, 0};
|
|
for (int i = 0 ; i < command.size(); i++)
|
|
{
|
|
if (ind_point >= points.size())
|
|
break;
|
|
|
|
//if (command[i].typeSegment == ODRAW::msopathEnd) break;
|
|
if (command[i].typeSegment > 3) continue;
|
|
|
|
CP_XML_NODE(comm[command[i].typeSegment])
|
|
{
|
|
for (int j=0 ; j < count_point[command[i].typeSegment]; j ++)
|
|
{
|
|
if (ind_point < points.size())
|
|
{
|
|
CP_XML_NODE(L"a:pt")
|
|
{
|
|
CP_XML_ATTR(L"x", points[ind_point].x);
|
|
CP_XML_ATTR(L"y", points[ind_point].y);
|
|
ind_point++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CP_XML_NODE(L"a:pt")
|
|
{
|
|
CP_XML_ATTR(L"x", 0);
|
|
CP_XML_ATTR(L"y", 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//xlsx_context->get_drawing_context().set_shapeType
|
|
xlsx_context->get_drawing_context().set_path_rect(rect);
|
|
xlsx_context->get_drawing_context().set_path(strm.str());
|
|
}
|
|
}
|
|
void XlsConverter::convert_geometry_text(std::vector<ODRAW::OfficeArtFOPTEPtr> & props)
|
|
{
|
|
for (int i = 0 ; i < props.size() ; i++)
|
|
{
|
|
}
|
|
}
|
|
void XlsConverter::convert_text(std::vector<ODRAW::OfficeArtFOPTEPtr> & props)
|
|
{
|
|
}
|
|
void XlsConverter::convert_shadow(std::vector<ODRAW::OfficeArtFOPTEPtr> & props)
|
|
{
|
|
for (int i = 0 ; i < props.size() ; i++)
|
|
{
|
|
}
|
|
}
|
|
void XlsConverter::convert_shape(std::vector<ODRAW::OfficeArtFOPTEPtr> & props)
|
|
{
|
|
for (int i = 0 ; i < props.size() ; i++)
|
|
{
|
|
|
|
}
|
|
}
|
|
void XlsConverter::convert_group_shape(std::vector<ODRAW::OfficeArtFOPTEPtr> & props)
|
|
{
|
|
for (int 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 target = GetTargetMoniker(pihlShape->IHlink_complex.hyperlink.oleMoniker.data.get());
|
|
xlsx_context->get_drawing_context().set_hyperlink(target);
|
|
}
|
|
}break;
|
|
}
|
|
}
|
|
}
|
|
void XlsConverter::convert_transform(std::vector<ODRAW::OfficeArtFOPTEPtr> & props)
|
|
{
|
|
for (int i = 0 ; i < props.size() ; i++)
|
|
{
|
|
switch(props[i]->opid)
|
|
{
|
|
case 0x0004:
|
|
{
|
|
double d = props[i]->op / 65536.;
|
|
d *= 60000; //60 000 per 1 gr - 19.5.5 oox
|
|
|
|
xlsx_context->get_drawing_context().set_rotation((int)d);
|
|
}break;
|
|
}
|
|
}
|
|
}
|
|
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_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(XLS::SHAREDSTRINGS* sharedstrings)
|
|
{
|
|
if (sharedstrings == NULL) return;
|
|
|
|
for (std::list<XLS::BaseObjectPtr>::iterator it = sharedstrings->elements_.begin(); it != sharedstrings->elements_.end(); it++)
|
|
{
|
|
(*it)->serialize(xlsx_context->shared_strings());
|
|
}
|
|
}
|