Files
DocumentServer-v-9.2.0/core/OOXML/Binary/Document/DocWrapper/XlsxSerializer.cpp
T
Yajbir Singh f1b860b25c
check / markdownlint (push) Has been cancelled
check / spellchecker (push) Has been cancelled
updated
2025-12-11 19:03:17 +05:30

328 lines
14 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 "XlsxSerializer.h"
#include "../../../../DesktopEditor/common/Directory.h"
#include "../../../../DesktopEditor/common/File.h"
#include "../../../../DesktopEditor/common/Path.h"
#include "../../../XlsxFormat/Chart/Chart.h"
#include "../../Sheets/Reader/BinaryWriterS.h"
#include "../../Sheets/Writer/BinaryReaderS.h"
#include "../../Presentation/FontPicker.h"
#include "../../../../OfficeUtils/src/OfficeUtils.h"
#include "ChartSerializer.h"
#include "../BinReader/DefaultThemeWriter.h"
namespace BinXlsxRW{
int g_nCurFormatVersion = 0;
CXlsxSerializer::CXlsxSerializer() : m_bIsMacro(false), m_bIsNoBase64(false)
{
m_pExternalDrawingConverter = NULL;
}
CXlsxSerializer::~CXlsxSerializer()
{
}
void CXlsxSerializer::CreateXlsxFolders(const std::wstring& sXmlOptions, const std::wstring& sDstPath, std::wstring& sMediaPath, std::wstring& sEmbedPath)
{
OOX::CPath pathMediaDir = sDstPath + FILE_SEPARATOR_STR + _T("xl") + FILE_SEPARATOR_STR + _T("media");
OOX::CPath pathEmbedDir = sDstPath + FILE_SEPARATOR_STR + _T("xl") + FILE_SEPARATOR_STR + _T("embeddings");
//создавать папку надо даже при сохранении в csv, потому что когда читаем из бинарника тему, она записывается в файл.
OOX::CPath pathXlDir = sDstPath + FILE_SEPARATOR_STR + _T("xl");
OOX::CPath pathThemeDir = pathXlDir + FILE_SEPARATOR_STR + OOX::FileTypes::Theme.DefaultDirectory().GetPath();
OOX::CPath pathThemeFile = pathThemeDir + FILE_SEPARATOR_STR + OOX::FileTypes::Theme.DefaultFileName().GetPath();
OOX::CPath pathThemeThemeRelsDir = pathThemeDir + FILE_SEPARATOR_STR + _T("_rels");
NSDirectory::CreateDirectory(pathXlDir.GetPath());
NSDirectory::CreateDirectory(pathThemeDir.GetPath());
NSDirectory::CreateDirectory(pathThemeThemeRelsDir.GetPath());
NSDirectory::CreateDirectory(pathMediaDir.GetPath());
NSDirectory::CreateDirectory(pathEmbedDir.GetPath());
//Create Default Theme
{
Writers::DefaultThemeWriter oDefaultThemeWriter;
oDefaultThemeWriter.Write(pathThemeFile.GetPath());
}
sMediaPath = pathMediaDir.GetPath();
sEmbedPath = pathEmbedDir.GetPath();
}
_UINT32 CXlsxSerializer::loadFromFile(const std::wstring& sSrcFileName, const std::wstring& sDstPath, const std::wstring& sXMLOptions, const std::wstring& sMediaDir, const std::wstring& sEmbedDir)
{
std::wstring strFileInDir = NSSystemPath::GetDirectoryName(sSrcFileName);
NSBinPptxRW::CDrawingConverter oDrawingConverter;
oDrawingConverter.SetDstPath(sDstPath + FILE_SEPARATOR_STR + L"xl");
oDrawingConverter.SetSrcPath(strFileInDir, XMLWRITER_DOC_TYPE_XLSX);
oDrawingConverter.SetMediaDstPath(sMediaDir);
oDrawingConverter.SetEmbedDstPath(sEmbedDir);
oDrawingConverter.SetTempPath(m_sTempDir);
BinXlsxRW::BinaryFileReader oBinaryFileReader;
return oBinaryFileReader.ReadFile(sSrcFileName, sDstPath, &oDrawingConverter, sXMLOptions, m_bIsMacro);
}
_UINT32 CXlsxSerializer::saveToFile(const std::wstring& sDstFileName, const std::wstring& sSrcPath, const std::wstring& sXMLOptions)
{
COfficeFontPicker* pFontPicker = new COfficeFontPicker();
pFontPicker->Init(m_sFontDir);
NSFonts::IFontManager* pFontManager = pFontPicker->get_FontManager();
DocWrapper::FontProcessor fp;
fp.setFontManager(pFontManager);
NSFontCutter::CEmbeddedFontsManager* pEmbeddedFontsManager = NULL;
if (false == m_sEmbeddedFontsDir.empty())
{
NSDirectory::CreateDirectory(m_sEmbeddedFontsDir);
pFontPicker->SetEmbeddedFontsDirectory(m_sEmbeddedFontsDir);
pEmbeddedFontsManager = pFontPicker->GetNativeCutter();
//добавим мега шрифт
pEmbeddedFontsManager->CheckFont(_T("Wingdings 3"), pFontManager);
pEmbeddedFontsManager->CheckFont(_T("Arial"), pFontManager);
//pEmbeddedFontsManager добавляются все цифры
//для заголовков
pEmbeddedFontsManager->CheckFont(_T("Calibri"), pFontManager);
pEmbeddedFontsManager->CheckString(std::wstring(_T("ABCDEFGHIJKLMNOPQRSTUVWXYZ")));
//дополнение для ошибок "#NULL!", "#DIV/0!"...
pEmbeddedFontsManager->CheckString(std::wstring(_T("#!/?")));
//дополнение для num форматов по умолчанию с id от 0 до 49
pEmbeddedFontsManager->CheckString(std::wstring(_T(".%E+-():")));
}
NSBinPptxRW::CDrawingConverter oOfficeDrawingConverter;
oOfficeDrawingConverter.SetFontManager(pFontManager);
oOfficeDrawingConverter.SetFontDir(m_sFontDir);
oOfficeDrawingConverter.SetFontPicker(pFontPicker);
BinXlsxRW::BinaryFileWriter oBinaryFileWriter(fp);
_UINT32 result = oBinaryFileWriter.Open(sSrcPath, sDstFileName, pEmbeddedFontsManager, &oOfficeDrawingConverter, sXMLOptions, m_bIsNoBase64);
RELEASEOBJECT(pFontPicker);
return result;
}
_UINT32 CXlsxSerializer::xml2Xlsx(const std::wstring& sSrcFileName, const std::wstring& sDstPath, const std::wstring& sXMLOptions)
{
std::wstring strFileInDir = NSSystemPath::GetDirectoryName(sSrcFileName);
NSBinPptxRW::CDrawingConverter oDrawingConverter;
oDrawingConverter.SetDstPath(sDstPath + FILE_SEPARATOR_STR + L"xl");
oDrawingConverter.SetSrcPath(strFileInDir, XMLWRITER_DOC_TYPE_XLSX);
oDrawingConverter.SetFontDir(m_sFontDir);
BinXlsxRW::BinaryFileReader oBinaryFileReader;
return oBinaryFileReader.Xml2Xlsx(sSrcFileName, sDstPath, &oDrawingConverter, sXMLOptions, m_bIsMacro);
}
bool CXlsxSerializer::saveChart(NSBinPptxRW::CBinaryFileReader* pReader, long lLength, NSCommon::smart_ptr<OOX::File> &file)
{
if (NULL == pReader) return false;
if (NULL == m_pExternalDrawingConverter) return false;
if (false == file.IsInit()) return false;
m_pExternalDrawingConverter->SetDstContentRels();
std::wstring sContentTypePath;
if (pReader->m_nDocumentType == XMLWRITER_DOC_TYPE_DOCX ||
pReader->m_nDocumentType == XMLWRITER_DOC_TYPE_DOCX_GLOSSARY) sContentTypePath = L"/word/charts/";
else if (pReader->m_nDocumentType == XMLWRITER_DOC_TYPE_XLSX) sContentTypePath = L"/xl/charts/";
else sContentTypePath = L"/ppt/charts/";
std::wstring sChartPath = pReader->m_pRels->m_pManager->GetDstCharts();
size_t nIndex = sChartPath.rfind(FILE_SEPARATOR_CHAR);
std::wstring sFilePathDocument = sChartPath;
if (std::wstring::npos != nIndex)
{
sFilePathDocument = sFilePathDocument.substr(0, nIndex + 1);
}
std::wstring sDrawingsPath = sFilePathDocument + L"drawings";
std::wstring sThemePath = sFilePathDocument + L"theme";
std::wstring sEmbedingPath = sFilePathDocument + L"embeddings";
std::wstring sFileName;
BinXlsxRW::SaveParams oSaveParams(sDrawingsPath, sEmbedingPath, sThemePath, m_pExternalDrawingConverter->GetContentTypes(), NULL, true);
BinXlsxRW::BinaryChartReader oBinaryChartReader(*pReader, oSaveParams, m_pExternalDrawingConverter);
bool bResult = false;
int nDocumentTypeOwner = pReader->m_pRels->m_pManager->m_nDocumentType;
pReader->m_pRels->m_pManager->m_nDocumentType = XMLWRITER_DOC_TYPE_XLSX;
NSCommon::smart_ptr<OOX::Spreadsheet::CChartFile> chart_file = file.smart_dynamic_cast<OOX::Spreadsheet::CChartFile>();
if (chart_file.IsInit())
{
sFileName = L"chart" + std::to_wstring(chart_file->GetGlobalNumber()) + L".xml";
bResult = (0 == oBinaryChartReader.ReadCT_ChartFile(lLength, chart_file.GetPointer()));
bool bXlsxPresent = (chart_file->m_oChartSpace.m_externalData) && (chart_file->m_oChartSpace.m_externalData->m_id.IsInit());
if (bResult && pReader->m_nDocumentType != XMLWRITER_DOC_TYPE_XLSX && !sEmbedingPath.empty() && !bXlsxPresent)
{
oSaveParams.bMacroEnabled = false;
std::wstring sXlsxFilename = L"Microsoft_Excel_Worksheet" + std::to_wstring(pReader->m_nCountEmbedded) + L".xlsx";
std::wstring sXlsxPath = sEmbedingPath + FILE_SEPARATOR_STR + sXlsxFilename;
pReader->m_nCountEmbedded++;
if (writeChartXlsx(sXlsxPath, file))
{
pReader->m_pRels->m_pManager->m_pContentTypes->AddDefault(L"xlsx");
std::wstring sChartsWorksheetRelsName = L"../embeddings/" + sXlsxFilename;
unsigned int rId;
std::wstring sChartsWorksheetRelType = OOX::FileTypes::MicrosoftOfficeExcelWorksheet.RelationType();
m_pExternalDrawingConverter->WriteRels(sChartsWorksheetRelType, sChartsWorksheetRelsName, std::wstring(), &rId);
chart_file->m_oChartSpace.m_externalData = new OOX::Spreadsheet::CT_ExternalData();
chart_file->m_oChartSpace.m_externalData->m_id = L"rId" + std::to_wstring(rId);
chart_file->m_oChartSpace.m_externalData->m_autoUpdate = false;
}
}
}
else
{
NSCommon::smart_ptr<OOX::Spreadsheet::CChartExFile> chartEx_file = file.smart_dynamic_cast<OOX::Spreadsheet::CChartExFile>();
if (chartEx_file.IsInit())
{
sFileName = L"chartEx" + std::to_wstring(chartEx_file->GetGlobalNumber()) + L".xml";
bResult = (0 == oBinaryChartReader.ReadCT_ChartExFile(lLength, chartEx_file.GetPointer()));
bool bXlsxPresent = (chartEx_file->m_oChartSpace.m_chartData.m_externalData.IsInit()) &&
(chartEx_file->m_oChartSpace.m_chartData.m_externalData->m_id.IsInit());
}
}
pReader->m_pRels->m_pManager->m_nDocumentType = nDocumentTypeOwner;
if(bResult)
{
if (pReader->m_nDocumentType != XMLWRITER_DOC_TYPE_DOCX && pReader->m_nDocumentType != XMLWRITER_DOC_TYPE_DOCX_GLOSSARY)
{
file->m_sOutputFilename = L"../";
}
file->m_sOutputFilename += L"charts/" + sFileName;
std::wstring sFilePath = sChartPath + FILE_SEPARATOR_STR + sFileName;
file->write(sFilePath, sContentTypePath, *pReader->m_pRels->m_pManager->m_pContentTypes);
OOX::CPath pathRelsDir = sChartPath + FILE_SEPARATOR_STR + _T("_rels");
OOX::CSystemUtility::CreateDirectories(pathRelsDir.GetPath());
OOX::CPath pathRelsFile = pathRelsDir + FILE_SEPARATOR_STR + NSSystemPath::GetFileName(sFilePath) + _T(".rels");
m_pExternalDrawingConverter->SaveDstContentRels(pathRelsFile.GetPath());
}
return bResult;
}
void CXlsxSerializer::setTempDir(const std::wstring& sTempDir)
{
m_sTempDir = sTempDir;
}
void CXlsxSerializer::setFontDir(const std::wstring& sFontDir)
{
m_sFontDir = sFontDir;
}
void CXlsxSerializer::setEmbeddedFontsDir(const std::wstring& sEmbeddedFontsDir)
{
m_sEmbeddedFontsDir = sEmbeddedFontsDir;
}
void CXlsxSerializer::setDrawingConverter(NSBinPptxRW::CDrawingConverter* pDrawingConverter)
{
m_pExternalDrawingConverter = pDrawingConverter;
}
void CXlsxSerializer::setIsNoBase64(bool val)
{
m_bIsNoBase64 = val;
}
void CXlsxSerializer::setMacroEnabled(bool val)
{
m_bIsMacro = val;
}
bool CXlsxSerializer::getMacroEnabled()
{
return m_bIsMacro;
}
bool CXlsxSerializer::writeChartXlsx(const std::wstring& sDstFile, NSCommon::smart_ptr<OOX::File> &file)
{
NSCommon::smart_ptr<OOX::Spreadsheet::CChartFile> oChart = file.smart_dynamic_cast<OOX::Spreadsheet::CChartFile>();
if (oChart.IsInit() == false) return false;
//анализируем chart
BinXlsxRW::ChartWriter helper;
helper.parseChart(oChart->m_oChartSpace.m_chart);
//создаем temp
std::wstring sTempDir = NSSystemPath::GetDirectoryName(sDstFile) + FILE_SEPARATOR_STR + NSSystemPath::GetFileName(sDstFile) + L"_TEMP";
NSDirectory::CreateDirectory(sTempDir);
OOX::CPath oPath(sTempDir.c_str());
//шиблонные папки
std::wstring sXmlOptions = _T("");
std::wstring sMediaPath;// will be filled by 'CreateXlsxFolders' method
std::wstring sEmbedPath; // will be filled by 'CreateXlsxFolders' method
CreateXlsxFolders (sXmlOptions, sTempDir, sMediaPath, sEmbedPath);
//заполняем Xlsx
OOX::Spreadsheet::CXlsx oXlsx;
helper.toXlsx(oXlsx);
//write
OOX::CContentTypes oContentTypes;
bool res = oXlsx.Write(oPath, oContentTypes);
if (res)
{
//zip
COfficeUtils oOfficeUtils(NULL);
oOfficeUtils.CompressFileOrDirectory(sTempDir, sDstFile, true);
}
//clean
NSDirectory::DeleteDirectory(sTempDir);
return res;
}
};