diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /sc/qa/unit/subsequent_export_test2.cxx | |
parent | Initial commit. (diff) | |
download | libreoffice-upstream.tar.xz libreoffice-upstream.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sc/qa/unit/subsequent_export_test2.cxx')
-rw-r--r-- | sc/qa/unit/subsequent_export_test2.cxx | 3164 |
1 files changed, 3164 insertions, 0 deletions
diff --git a/sc/qa/unit/subsequent_export_test2.cxx b/sc/qa/unit/subsequent_export_test2.cxx new file mode 100644 index 000000000..ce53077fc --- /dev/null +++ b/sc/qa/unit/subsequent_export_test2.cxx @@ -0,0 +1,3164 @@ + +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <officecfg/Office/Common.hxx> + +#include <sfx2/sfxmodelfactory.hxx> + +#include "helper/qahelper.hxx" +#include "helper/xpath.hxx" + +#include <docsh.hxx> +#include <docpool.hxx> +#include <scitems.hxx> +#include <attrib.hxx> +#include <stlpool.hxx> +#include <formulacell.hxx> +#include <validat.hxx> +#include <global.hxx> +#include <dpcache.hxx> +#include <dpobject.hxx> +#include <clipparam.hxx> +#include <viewopti.hxx> + +#include <editeng/wghtitem.hxx> +#include <editeng/postitem.hxx> +#include <editeng/eeitem.hxx> +#include <editeng/editobj.hxx> +#include <editeng/flditem.hxx> +#include <editeng/justifyitem.hxx> +#include <comphelper/propertyvalue.hxx> +#include <comphelper/scopeguard.hxx> +#include <unotools/syslocaleoptions.hxx> +#include <formula/grammar.hxx> +#include <tools/fldunit.hxx> +#include <svl/numformat.hxx> +#include <svl/zformat.hxx> + +#include <com/sun/star/chart2/XChartDocument.hpp> +#include <com/sun/star/chart2/XChartTypeContainer.hpp> +#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp> +#include <com/sun/star/drawing/XDrawPage.hpp> +#include <com/sun/star/drawing/XDrawPages.hpp> +#include <com/sun/star/drawing/XDrawPagesSupplier.hpp> +#include <com/sun/star/frame/Desktop.hpp> +#include <com/sun/star/packages/zip/ZipFileAccess.hpp> +#include <com/sun/star/sheet/GlobalSheetSettings.hpp> +#include <com/sun/star/sheet/XHeaderFooterContent.hpp> +#include <com/sun/star/text/XTextColumns.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +class ScExportTest2 : public ScBootstrapFixture, public XmlTestTools +{ +protected: + virtual void registerNamespaces(xmlXPathContextPtr& pXmlXPathCtx) override; + +public: + ScExportTest2(); + + virtual void setUp() override; + virtual void tearDown() override; + + void testGroupShape(); + void testMatrixMultiplicationXLSX(); + void testTdf121260(); + void testTextDirectionXLSX(); + void testTdf120168(); + void testTdf66668(); + void testTdf130108(); + void testTdf76949(); + void testTdf107586(); + void testTdf55417(); + void testTdf129985(); + void testTdf73063(); + + xmlDocUniquePtr testTdf95640(std::u16string_view rFileName, sal_Int32 nSourceFormat, + sal_Int32 nDestFormat); + void testTdf95640_ods_to_xlsx(); + void testTdf95640_ods_to_xlsx_with_standard_list(); + void testTdf95640_xlsx_to_xlsx(); + void testDateAutofilterXLSX(); + void testDateAutofilterODS(); + void testAutofilterColorsODF(); + void testAutofilterColorsOOXML(); + void testAutofilterTop10XLSX(); + + void testRefStringXLSX(); + void testRefStringConfigXLSX(); + void testRefStringUnspecified(); + void testHeaderImageODS(); + void testHeaderFooterContentODS(); + + void testTdf88657ODS(); + void testTdf41722(); + void testTdf113621(); + void testEscapeCharInNumberFormatXLSX(); + void testNatNumInNumberFormatXLSX(); + void testExponentWithoutSignFormatXLSX(); + void testExtendedLCIDXLSX(); + + void testHiddenRepeatedRowsODS(); + void testHyperlinkTargetFrameODS(); + void testOpenDocumentAsReadOnly(); + void testKeepSettingsOfBlankRows(); + + void testTdf133595(); + void testTdf134769(); + void testTdf106181(); + void testTdf145057(); + void testTdf105272(); + void testTdf118990(); + void testTdf121612(); + void testTdf112936(); + void testPivotCacheAfterExportXLSX(); + void testTdf114969XLSX(); + void testTdf115192XLSX(); + void testTdf142764(); + void testTdf91634XLSX(); + void testTdf115159(); + void testTdf112567(); + void testTdf122191(); + void testTdf142881(); + void testTdf112567b(); + void testTdf123645XLSX(); + void testTdf125173XLSX(); + void testTdf79972XLSX(); + void testTdf126024XLSX(); + void testTdf126177XLSX(); + void testCommentTextVAlignment(); + void testCommentTextHAlignment(); + void testValidationCopyPaste(); + + void testXltxExport(); + void testRotatedImageODS(); + void testTdf85553(); + void testTdf128976(); + void testTdf143979(); + void testTdf120502(); + void testTdf131372(); + void testTdf81470(); + void testTdf122331(); + void testTdf83779(); + void testTdf121715_FirstPageHeaderFooterXLSX(); + void testTdf121716_ExportEvenHeaderFooterXLSX(); + void testTdf134459_HeaderFooterColorXLSX(); + void testTdf134817_HeaderFooterTextWith2SectionXLSX(); + void testTdf121718_UseFirstPageNumberXLSX(); + void testHeaderFontStyleXLSX(); + void testTdf135828_Shape_Rect(); + void testTdf123139XLSX(); + void testTdf123353(); + void testTdf140098(); + void testTdf133688_precedents(); + void testTdf91251_missingOverflowRoundtrip(); + void testTdf137000_handle_upright(); + void testTdf126305_DataValidatyErrorAlert(); + void testTdf76047_externalLink(); + void testTdf87973_externalLinkSkipUnuseds(); + void testTdf51022_lostPrintRange(); + void testTdf138741_externalLinkSkipUnusedsCrash(); + void testTdf138824_linkToParentDirectory(); + void testTdf129969(); + void testTdf147088(); + void testTdf84874(); + void testTdf136721_paper_size(); + void testTdf139258_rotated_image(); + void testTdf142854_GridVisibilityImportXlsxInHeadlessMode(); + void testTdf144642_RowHeightRounding(); + void testTdf145129_DefaultRowHeightRounding(); + void testTdf151755_stylesLostOnXLSXExport(); + void testTdf140431(); + void testCheckboxFormControlXlsxExport(); + void testButtonFormControlXlsxExport(); + void testTdf142929_filterLessThanXLSX(); + void testInvalidNamedRange(); + void testExternalDefinedNameXLSX(); + void testHyperlinkLocationXLSX(); + void testTdf142264ManyChartsToXLSX(); + void testTdf143929MultiColumnToODS(); + void testTdf142578(); + void testTdf145059(); + void testTdf130104_XLSXIndent(); + void testWholeRowBold(); + void testXlsxRowsOrder(); + void testTdf91286(); + void testTdf148820(); + void testEmbeddedTextInDecimal(); + + CPPUNIT_TEST_SUITE(ScExportTest2); + + CPPUNIT_TEST(testGroupShape); + CPPUNIT_TEST(testMatrixMultiplicationXLSX); + CPPUNIT_TEST(testTdf121260); + CPPUNIT_TEST(testTextDirectionXLSX); + CPPUNIT_TEST(testTdf120168); + CPPUNIT_TEST(testTdf66668); + CPPUNIT_TEST(testTdf130108); + CPPUNIT_TEST(testTdf76949); + CPPUNIT_TEST(testTdf107586); + CPPUNIT_TEST(testTdf55417); + CPPUNIT_TEST(testTdf129985); + CPPUNIT_TEST(testTdf73063); + CPPUNIT_TEST(testTdf95640_ods_to_xlsx); + CPPUNIT_TEST(testTdf95640_ods_to_xlsx_with_standard_list); + CPPUNIT_TEST(testTdf95640_xlsx_to_xlsx); + CPPUNIT_TEST(testDateAutofilterXLSX); + CPPUNIT_TEST(testDateAutofilterODS); + CPPUNIT_TEST(testAutofilterColorsODF); + CPPUNIT_TEST(testAutofilterColorsOOXML); + CPPUNIT_TEST(testAutofilterTop10XLSX); + + CPPUNIT_TEST(testRefStringXLSX); + CPPUNIT_TEST(testRefStringConfigXLSX); + CPPUNIT_TEST(testRefStringUnspecified); + CPPUNIT_TEST(testHeaderImageODS); + CPPUNIT_TEST(testHeaderFooterContentODS); + + CPPUNIT_TEST(testTdf88657ODS); + CPPUNIT_TEST(testTdf41722); + CPPUNIT_TEST(testTdf113621); + CPPUNIT_TEST(testEscapeCharInNumberFormatXLSX); + CPPUNIT_TEST(testNatNumInNumberFormatXLSX); + CPPUNIT_TEST(testExponentWithoutSignFormatXLSX); + CPPUNIT_TEST(testExtendedLCIDXLSX); + + CPPUNIT_TEST(testHiddenRepeatedRowsODS); + CPPUNIT_TEST(testHyperlinkTargetFrameODS); + CPPUNIT_TEST(testOpenDocumentAsReadOnly); + CPPUNIT_TEST(testKeepSettingsOfBlankRows); + + CPPUNIT_TEST(testTdf133595); + CPPUNIT_TEST(testTdf134769); + CPPUNIT_TEST(testTdf106181); + CPPUNIT_TEST(testTdf145057); + CPPUNIT_TEST(testTdf105272); + CPPUNIT_TEST(testTdf118990); + CPPUNIT_TEST(testTdf121612); + CPPUNIT_TEST(testTdf112936); + CPPUNIT_TEST(testPivotCacheAfterExportXLSX); + CPPUNIT_TEST(testTdf114969XLSX); + CPPUNIT_TEST(testTdf115192XLSX); + CPPUNIT_TEST(testTdf142764); + CPPUNIT_TEST(testTdf91634XLSX); + CPPUNIT_TEST(testTdf115159); + CPPUNIT_TEST(testTdf112567); + CPPUNIT_TEST(testTdf122191); + CPPUNIT_TEST(testTdf142881); + CPPUNIT_TEST(testTdf112567b); + CPPUNIT_TEST(testTdf123645XLSX); + CPPUNIT_TEST(testTdf125173XLSX); + CPPUNIT_TEST(testTdf79972XLSX); + CPPUNIT_TEST(testTdf126024XLSX); + CPPUNIT_TEST(testTdf126177XLSX); + CPPUNIT_TEST(testCommentTextVAlignment); + CPPUNIT_TEST(testCommentTextHAlignment); + CPPUNIT_TEST(testValidationCopyPaste); + + CPPUNIT_TEST(testXltxExport); + CPPUNIT_TEST(testRotatedImageODS); + CPPUNIT_TEST(testTdf85553); + CPPUNIT_TEST(testTdf128976); + CPPUNIT_TEST(testTdf143979); + CPPUNIT_TEST(testTdf120502); + CPPUNIT_TEST(testTdf131372); + CPPUNIT_TEST(testTdf81470); + CPPUNIT_TEST(testTdf122331); + CPPUNIT_TEST(testTdf83779); + CPPUNIT_TEST(testTdf121715_FirstPageHeaderFooterXLSX); + CPPUNIT_TEST(testTdf121716_ExportEvenHeaderFooterXLSX); + CPPUNIT_TEST(testTdf134459_HeaderFooterColorXLSX); + CPPUNIT_TEST(testTdf134817_HeaderFooterTextWith2SectionXLSX); + CPPUNIT_TEST(testTdf121718_UseFirstPageNumberXLSX); + CPPUNIT_TEST(testHeaderFontStyleXLSX); + CPPUNIT_TEST(testTdf135828_Shape_Rect); + CPPUNIT_TEST(testTdf123139XLSX); + CPPUNIT_TEST(testTdf123353); + CPPUNIT_TEST(testTdf140098); + CPPUNIT_TEST(testTdf133688_precedents); + CPPUNIT_TEST(testTdf91251_missingOverflowRoundtrip); + CPPUNIT_TEST(testTdf137000_handle_upright); + CPPUNIT_TEST(testTdf126305_DataValidatyErrorAlert); + CPPUNIT_TEST(testTdf76047_externalLink); + CPPUNIT_TEST(testTdf87973_externalLinkSkipUnuseds); + CPPUNIT_TEST(testTdf51022_lostPrintRange); + CPPUNIT_TEST(testTdf138741_externalLinkSkipUnusedsCrash); + CPPUNIT_TEST(testTdf138824_linkToParentDirectory); + CPPUNIT_TEST(testTdf129969); + CPPUNIT_TEST(testTdf147088); + CPPUNIT_TEST(testTdf84874); + CPPUNIT_TEST(testTdf136721_paper_size); + CPPUNIT_TEST(testTdf139258_rotated_image); + CPPUNIT_TEST(testTdf142854_GridVisibilityImportXlsxInHeadlessMode); + CPPUNIT_TEST(testTdf144642_RowHeightRounding); + CPPUNIT_TEST(testTdf145129_DefaultRowHeightRounding); + CPPUNIT_TEST(testTdf151755_stylesLostOnXLSXExport); + CPPUNIT_TEST(testTdf140431); + CPPUNIT_TEST(testCheckboxFormControlXlsxExport); + CPPUNIT_TEST(testButtonFormControlXlsxExport); + CPPUNIT_TEST(testTdf142929_filterLessThanXLSX); + CPPUNIT_TEST(testInvalidNamedRange); + CPPUNIT_TEST(testExternalDefinedNameXLSX); + CPPUNIT_TEST(testHyperlinkLocationXLSX); + CPPUNIT_TEST(testTdf142264ManyChartsToXLSX); + CPPUNIT_TEST(testTdf143929MultiColumnToODS); + CPPUNIT_TEST(testTdf142578); + CPPUNIT_TEST(testTdf145059); + CPPUNIT_TEST(testTdf130104_XLSXIndent); + CPPUNIT_TEST(testWholeRowBold); + CPPUNIT_TEST(testXlsxRowsOrder); + CPPUNIT_TEST(testTdf91286); + CPPUNIT_TEST(testTdf148820); + CPPUNIT_TEST(testEmbeddedTextInDecimal); + + CPPUNIT_TEST_SUITE_END(); + +private: + uno::Reference<uno::XInterface> m_xCalcComponent; +}; + +ScExportTest2::ScExportTest2() + : ScBootstrapFixture("sc/qa/unit/data") +{ +} + +void ScExportTest2::setUp() +{ + test::BootstrapFixture::setUp(); + + // This is a bit of a fudge, we do this to ensure that ScGlobals::ensure, + // which is a private symbol to us, gets called + m_xCalcComponent + = getMultiServiceFactory()->createInstance("com.sun.star.comp.Calc.SpreadsheetDocument"); + CPPUNIT_ASSERT_MESSAGE("no calc component!", m_xCalcComponent.is()); +} + +void ScExportTest2::tearDown() +{ + uno::Reference<lang::XComponent>(m_xCalcComponent, UNO_QUERY_THROW)->dispose(); + test::BootstrapFixture::tearDown(); +} + +void ScExportTest2::registerNamespaces(xmlXPathContextPtr& pXmlXPathCtx) +{ + XmlTestTools::registerOOXMLNamespaces(pXmlXPathCtx); + XmlTestTools::registerODFNamespaces(pXmlXPathCtx); +} + +void ScExportTest2::testGroupShape() +{ + ScDocShellRef xDocSh = loadDoc(u"groupShape.", FORMAT_XLSX); + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xDocSh, FORMAT_XLSX); + + xmlDocUniquePtr pDoc + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/drawings/drawing1.xml"); + CPPUNIT_ASSERT(pDoc); + assertXPath(pDoc, "/xdr:wsDr/xdr:twoCellAnchor/xdr:grpSp/xdr:grpSpPr"); +} + +void ScExportTest2::testMatrixMultiplicationXLSX() +{ + ScDocShellRef xShell = loadDoc(u"matrix-multiplication.", FORMAT_XLSX); + + ScDocShellRef xDocSh = saveAndReload(*xShell, FORMAT_XLSX); + CPPUNIT_ASSERT(xDocSh.is()); + + xmlDocUniquePtr pDoc = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, + "xl/worksheets/sheet1.xml", FORMAT_XLSX); + CPPUNIT_ASSERT(pDoc); + + OUString CellFormulaRange = getXPath(pDoc, "/x:worksheet/x:sheetData/x:row[4]/x:c/x:f", "ref"); + + // make sure that the CellFormulaRange is G5:G6. + CPPUNIT_ASSERT_EQUAL(OUString("G5:G6"), CellFormulaRange); + + OUString CellFormulaType = getXPath(pDoc, "/x:worksheet/x:sheetData/x:row[4]/x:c/x:f", "t"); + + // make sure that the CellFormulaType is array. + CPPUNIT_ASSERT_EQUAL(OUString("array"), CellFormulaType); + + xDocSh->DoClose(); +} + +void ScExportTest2::testRefStringXLSX() +{ + ScDocShellRef xDocSh = loadDoc(u"ref_string.", FORMAT_XLSX); + + //make sure ref syntax gets saved for MSO-produced docs + xDocSh = saveAndReload(*xDocSh, FORMAT_XLSX); + CPPUNIT_ASSERT_MESSAGE("Failed to reload doc", xDocSh.is()); + + ScDocument& rDoc = xDocSh->GetDocument(); + ScCalcConfig aCalcConfig = rDoc.GetCalcConfig(); + CPPUNIT_ASSERT_EQUAL(formula::FormulaGrammar::CONV_XL_A1, aCalcConfig.meStringRefAddressSyntax); + + xDocSh->DoClose(); +} + +void ScExportTest2::testRefStringConfigXLSX() +{ + // this doc is configured with CalcA1 ref syntax + ScDocShellRef xDocSh = loadDoc(u"empty.", FORMAT_XLSX); + + xDocSh = saveAndReload(*xDocSh, FORMAT_XLSX); + CPPUNIT_ASSERT_MESSAGE("Failed to reload doc", xDocSh.is()); + + ScDocument& rDoc = xDocSh->GetDocument(); + ScCalcConfig aConfig = rDoc.GetCalcConfig(); + CPPUNIT_ASSERT_EQUAL_MESSAGE("String ref syntax doesn't match", + formula::FormulaGrammar::CONV_OOO, + aConfig.meStringRefAddressSyntax); + + xDocSh->DoClose(); + + // this doc has no entry for ref syntax + xDocSh = loadDoc(u"empty-noconf.", FORMAT_XLSX); + CPPUNIT_ASSERT_MESSAGE("Failed to open 2nd doc", xDocSh.is()); + + ScDocument& rDoc2 = xDocSh->GetDocument(); + aConfig = rDoc2.GetCalcConfig(); + // therefore after import, ref syntax should be set to CalcA1 | ExcelA1 + CPPUNIT_ASSERT_EQUAL_MESSAGE("String ref syntax doesn't match", + formula::FormulaGrammar::CONV_A1_XL_A1, + aConfig.meStringRefAddressSyntax); + + //set ref syntax to something else than ExcelA1 (native to xlsx format) ... + aConfig.meStringRefAddressSyntax = formula::FormulaGrammar::CONV_XL_R1C1; + rDoc2.SetCalcConfig(aConfig); + + ScDocShellRef xNewDocSh = saveAndReload(*xDocSh, FORMAT_XLSX); + CPPUNIT_ASSERT_MESSAGE("Failed to reload 2nd doc", xNewDocSh.is()); + + // ... and make sure it got saved + ScDocument& rDoc3 = xNewDocSh->GetDocument(); + aConfig = rDoc3.GetCalcConfig(); + CPPUNIT_ASSERT_EQUAL_MESSAGE("String ref syntax doesn't match", + formula::FormulaGrammar::CONV_XL_R1C1, + aConfig.meStringRefAddressSyntax); + + xDocSh->DoClose(); + xNewDocSh->DoClose(); +} + +void ScExportTest2::testRefStringUnspecified() +{ + ScDocShell* pShell + = new ScDocShell(SfxModelFlags::EMBEDDED_OBJECT | SfxModelFlags::DISABLE_EMBEDDED_SCRIPTS + | SfxModelFlags::DISABLE_DOCUMENT_RECOVERY); + pShell->DoInitNew(); + + ScDocument& rDoc = pShell->GetDocument(); + ScCalcConfig aConfig = rDoc.GetCalcConfig(); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Default string ref syntax value doesn't match", + formula::FormulaGrammar::CONV_UNSPECIFIED, + aConfig.meStringRefAddressSyntax); + + // change formula syntax (i.e. not string ref syntax) to ExcelA1 + rDoc.SetGrammar(formula::FormulaGrammar::GRAM_NATIVE_XL_A1); + + ScDocShellRef xDocSh = saveAndReload(*pShell, FORMAT_ODS); + CPPUNIT_ASSERT_MESSAGE("Failed to reload doc", xDocSh.is()); + + // with string ref syntax at its default value, we should've saved ExcelA1 + ScDocument& rDoc2 = xDocSh->GetDocument(); + aConfig = rDoc2.GetCalcConfig(); + CPPUNIT_ASSERT_EQUAL_MESSAGE("String ref syntax doesn't match", + formula::FormulaGrammar::CONV_XL_A1, + aConfig.meStringRefAddressSyntax); + + xDocSh->DoClose(); +} + +void ScExportTest2::testHeaderImageODS() +{ + // Graphic as header background was lost on export. + ScDocShellRef xShell = loadDoc(u"header-image.", FORMAT_ODS); + ScDocShellRef xDocSh = saveAndReload(*xShell, FORMAT_ODS); + uno::Reference<style::XStyleFamiliesSupplier> xStyleFamiliesSupplier(xDocSh->GetModel(), + uno::UNO_QUERY); + uno::Reference<container::XNameAccess> xStyleFamilies + = xStyleFamiliesSupplier->getStyleFamilies(); + uno::Reference<container::XNameAccess> xPageStyles(xStyleFamilies->getByName("PageStyles"), + uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xStyle(xPageStyles->getByName("Default"), uno::UNO_QUERY); + + uno::Reference<graphic::XGraphic> xGraphic; + xStyle->getPropertyValue("HeaderBackGraphic") >>= xGraphic; + CPPUNIT_ASSERT(xGraphic.is()); + xDocSh->DoClose(); +} + +void ScExportTest2::testHeaderFooterContentODS() +{ + ScDocShellRef xShell = loadDoc(u"header-footer-content.", FORMAT_ODS); + ScDocShellRef xDocSh = saveAndReload(*xShell, FORMAT_ODS); + uno::Reference<style::XStyleFamiliesSupplier> xStyleFamiliesSupplier(xDocSh->GetModel(), + uno::UNO_QUERY); + uno::Reference<container::XNameAccess> xStyleFamilies + = xStyleFamiliesSupplier->getStyleFamilies(); + uno::Reference<container::XNameAccess> xPageStyles(xStyleFamilies->getByName("PageStyles"), + uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xStyle(xPageStyles->getByName("Default"), uno::UNO_QUERY); + + uno::Reference<css::sheet::XHeaderFooterContent> xContent; + xStyle->getPropertyValue("RightPageHeaderContent") >>= xContent; + CPPUNIT_ASSERT(xContent.is()); + CPPUNIT_ASSERT_EQUAL(OUString("header"), xContent->getCenterText()->getString()); + + xStyle->getPropertyValue("FirstPageHeaderContent") >>= xContent; + CPPUNIT_ASSERT(xContent.is()); + CPPUNIT_ASSERT_EQUAL(OUString("first page header"), xContent->getCenterText()->getString()); + + xStyle->getPropertyValue("RightPageFooterContent") >>= xContent; + CPPUNIT_ASSERT(xContent.is()); + CPPUNIT_ASSERT_EQUAL(OUString("footer"), xContent->getCenterText()->getString()); + + xStyle->getPropertyValue("FirstPageFooterContent") >>= xContent; + // First page footer content used to be lost upon export. + CPPUNIT_ASSERT(xContent.is()); + CPPUNIT_ASSERT_EQUAL(OUString("first page footer"), xContent->getCenterText()->getString()); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTextDirectionXLSX() +{ + ScDocShellRef xDocSh = loadDoc(u"writingMode.", FORMAT_XLSX); + + xmlDocUniquePtr pDoc + = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, "xl/styles.xml", FORMAT_XLSX); + CPPUNIT_ASSERT(pDoc); + + assertXPath(pDoc, "/x:styleSheet/x:cellXfs/x:xf[2]/x:alignment", "readingOrder", "1"); //LTR + assertXPath(pDoc, "/x:styleSheet/x:cellXfs/x:xf[3]/x:alignment", "readingOrder", "2"); //RTL + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf121260() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf121260.", FORMAT_ODS); + + ScDocument& rDoc = xDocSh->GetDocument(); + // change formula syntax (i.e. not string ref syntax) to ExcelA1 + rDoc.SetGrammar(formula::FormulaGrammar::GRAM_NATIVE_XL_A1); + + xmlDocUniquePtr pChart1 = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, + "xl/charts/chart1.xml", FORMAT_XLSX); + CPPUNIT_ASSERT(pChart1); + + // Without the fix in place, this test would have failed with + // - Expected: Sheet1!$A$1:$A$2 + // - Actual : sheet1 $A$1:$A$2 + assertXPathContent(pChart1, + "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[1]/c:val/c:numRef/c:f", + "Sheet1!$A$1:$A$2"); + assertXPathContent(pChart1, + "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[2]/c:val/c:numRef/c:f", + "Sheet1!$B$1:$B$2"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf120168() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf120168.", FORMAT_XLSX); + + xmlDocUniquePtr pDoc + = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, "xl/styles.xml", FORMAT_XLSX); + CPPUNIT_ASSERT(pDoc); + + // Without the fix in place, this test would have failed with + // - Expected: left + // - Actual : general + assertXPath(pDoc, "/x:styleSheet/x:cellXfs/x:xf[2]/x:alignment", "horizontal", "left"); + assertXPath(pDoc, "/x:styleSheet/x:cellXfs/x:xf[3]/x:alignment", "horizontal", "right"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf66668() +{ + // Would hang on exporting without the fix in place + ScDocShellRef xDocSh = loadDoc(u"tdf66668.", FORMAT_XLSX); + + xmlDocUniquePtr pDoc + = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, "xl/styles.xml", FORMAT_XLSX); + CPPUNIT_ASSERT(pDoc); + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf130108() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf130108.", FORMAT_ODS); + + xmlDocUniquePtr pDoc + = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, "xl/styles.xml", FORMAT_XLSX); + CPPUNIT_ASSERT(pDoc); + + assertXPath(pDoc, "/x:styleSheet/x:dxfs/x:dxf/x:font/x:b", "val", "1"); + assertXPath(pDoc, "/x:styleSheet/x:dxfs/x:dxf/x:font/x:i", "val", "0"); + assertXPath(pDoc, "/x:styleSheet/x:dxfs/x:dxf/x:font/x:color", "rgb", "FFFFFFFF"); + assertXPath(pDoc, "/x:styleSheet/x:dxfs/x:dxf/x:font/x:sz", "val", "10"); + assertXPath(pDoc, "/x:styleSheet/x:dxfs/x:dxf/x:fill/x:patternFill/x:bgColor", "rgb", + "FFCC0000"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf76949() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf76949.", FORMAT_ODS); + + xmlDocUniquePtr pSheet = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, + "xl/worksheets/sheet1.xml", FORMAT_XLSX); + CPPUNIT_ASSERT(pSheet); + + assertXPathContent(pSheet, "/x:worksheet/x:sheetData/x:row/x:c/x:f", "_xlfn.CHISQ.DIST(1,1,1)"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf107586() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf107586.", FORMAT_XLSX); + + xmlDocUniquePtr pSheet = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, + "xl/worksheets/sheet1.xml", FORMAT_XLSX); + CPPUNIT_ASSERT(pSheet); + + // Without the fix in place, this test would have failed with + // XPath '/x:worksheet/x:sheetPr/x:tabColor' number of nodes is incorrect + assertXPath(pSheet, "/x:worksheet/x:sheetPr/x:tabColor", "rgb", "FF9BBB59"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf55417() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf55417.", FORMAT_XLSX); + + xmlDocUniquePtr pDoc + = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, "xl/styles.xml", FORMAT_XLSX); + CPPUNIT_ASSERT(pDoc); + assertXPath(pDoc, "/x:styleSheet/x:cellXfs/x:xf[1]/x:alignment", 1); + assertXPath(pDoc, "/x:styleSheet/x:cellXfs/x:xf[2]/x:alignment", 1); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf129985() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf129985.", FORMAT_XLSX); + + xmlDocUniquePtr pDoc + = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, "xl/styles.xml", FORMAT_XLSX); + CPPUNIT_ASSERT(pDoc); + + assertXPath(pDoc, "/x:styleSheet/x:numFmts/x:numFmt[2]", "formatCode", "m/d/yyyy"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf73063() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf73063.", FORMAT_XLSX); + + xmlDocUniquePtr pDoc + = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, "xl/styles.xml", FORMAT_XLSX); + CPPUNIT_ASSERT(pDoc); + + assertXPath(pDoc, "/x:styleSheet/x:numFmts/x:numFmt[2]", "formatCode", + "[$-1C1A]dddd\", \"d\". \"mmmm\\ yyyy;@"); + + xDocSh->DoClose(); +} + +xmlDocUniquePtr ScExportTest2::testTdf95640(std::u16string_view rFileName, sal_Int32 nSourceFormat, + sal_Int32 nDestFormat) +{ + ScDocShellRef xShell = loadDoc(rFileName, nSourceFormat); + + auto pXPathFile = ScBootstrapFixture::exportTo(*xShell, nDestFormat); + xShell->DoClose(); + + return XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/sheet1.xml"); +} + +void ScExportTest2::testTdf95640_ods_to_xlsx() +{ + // Roundtripping sort options with user defined list to XLSX + xmlDocUniquePtr pDoc = testTdf95640(u"tdf95640.", FORMAT_ODS, FORMAT_XLSX); + + assertXPath(pDoc, "//x:worksheet/x:autoFilter", "ref", "A1:B4"); + + assertXPath(pDoc, "//x:worksheet/x:autoFilter/x:sortState/x:sortCondition", "ref", "A2:A4"); + + assertXPath(pDoc, "//x:worksheet/x:autoFilter/x:sortState/x:sortCondition", "customList", + "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec"); +} + +void ScExportTest2::testTdf95640_ods_to_xlsx_with_standard_list() +{ + // Roundtripping sort options with user defined list to XLSX + xmlDocUniquePtr pDoc = testTdf95640(u"tdf95640_standard_list.", FORMAT_ODS, FORMAT_XLSX); + + assertXPath(pDoc, "//x:worksheet/x:autoFilter", "ref", "A1:B4"); + + assertXPath(pDoc, "//x:worksheet/x:autoFilter/x:sortState/x:sortCondition", "ref", "A2:A4"); + + assertXPath(pDoc, "//x:worksheet/x:autoFilter/x:sortState/x:sortCondition", "customList", + "Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday"); +} + +void ScExportTest2::testTdf95640_xlsx_to_xlsx() +{ + // XLSX Roundtripping sort options with custom sort list - note + // that compared to ODS source documents above, here we _actually_ + // can use custom lists (beyond the global user defines), like + // low, medium, high + xmlDocUniquePtr pDoc = testTdf95640(u"tdf95640.", FORMAT_XLSX, FORMAT_XLSX); + + assertXPath(pDoc, "//x:worksheet/x:autoFilter", "ref", "A1:B4"); + + assertXPath(pDoc, "//x:worksheet/x:autoFilter/x:sortState/x:sortCondition", "ref", "A2:A4"); + + assertXPath(pDoc, "//x:worksheet/x:autoFilter/x:sortState/x:sortCondition", "customList", + "Low,Medium,High"); +} + +void ScExportTest2::testDateAutofilterXLSX() +{ + // XLSX Roundtripping autofilter with date list + ScDocShellRef xDocSh = loadDoc(u"dateAutofilter.", FORMAT_XLSX); + + xmlDocUniquePtr pDoc = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, + "xl/worksheets/sheet1.xml", FORMAT_XLSX); + CPPUNIT_ASSERT(pDoc); + + assertXPath(pDoc, "//x:autoFilter", "ref", "A1:B4"); + assertXPath(pDoc, "//x:autoFilter/x:filterColumn/x:filters/x:dateGroupItem[1]", "day", "02"); + assertXPath(pDoc, "//x:autoFilter/x:filterColumn/x:filters/x:dateGroupItem[1]", "month", "03"); + assertXPath(pDoc, "//x:autoFilter/x:filterColumn/x:filters/x:dateGroupItem[1]", "year", "2017"); + assertXPath(pDoc, "//x:autoFilter/x:filterColumn/x:filters/x:dateGroupItem[1]", + "dateTimeGrouping", "day"); + + assertXPath(pDoc, "//x:autoFilter/x:filterColumn/x:filters/x:dateGroupItem[2]", "day", "01"); + assertXPath(pDoc, "//x:autoFilter/x:filterColumn/x:filters/x:dateGroupItem[2]", "month", "10"); + assertXPath(pDoc, "//x:autoFilter/x:filterColumn/x:filters/x:dateGroupItem[2]", "year", "2014"); + assertXPath(pDoc, "//x:autoFilter/x:filterColumn/x:filters/x:dateGroupItem[2]", + "dateTimeGrouping", "day"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testDateAutofilterODS() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf142231.", FORMAT_ODS); + + xmlDocUniquePtr pDoc + = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, "content.xml", FORMAT_ODS); + CPPUNIT_ASSERT(pDoc); + + assertXPath(pDoc, "//table:filter/table:filter-and/table:filter-condition[1]", "value", "Calc"); + assertXPath(pDoc, "//table:filter/table:filter-and/table:filter-condition[2]", "value", + "2021-05-04"); +} + +void ScExportTest2::testAutofilterColorsODF() +{ + ScDocShellRef xDocSh = loadDoc(u"autofilter-colors.", FORMAT_ODS); + + xmlDocUniquePtr pDoc + = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, "content.xml", FORMAT_ODS); + CPPUNIT_ASSERT(pDoc); + + assertXPath(pDoc, + "//table:database-ranges/table:database-range[1]/table:filter/table:filter-and/" + "table:filter-condition[1]", + "value", "#e8f2a1"); + assertXPath(pDoc, + "//table:database-ranges/table:database-range[1]/table:filter/table:filter-and/" + "table:filter-condition[1][@loext:data-type='background-color']"); + assertXPath(pDoc, + "//table:database-ranges/table:database-range[1]/table:filter/table:filter-and/" + "table:filter-condition[2]", + "value", "#3465a4"); + assertXPath(pDoc, "//table:database-ranges/table:database-range[1]/table:filter/" + "table:filter-and/table:filter-condition[2][@loext:data-type='text-color']"); + + // tdf#142965 Check "none" value when automatic text color / no fill was selected + assertXPath(pDoc, "//table:database-ranges/table:database-range[2]/table:filter/" + "table:filter-and/" + "table:filter-condition[1][@loext:data-type='background-color']"); + assertXPath(pDoc, + "//table:database-ranges/table:database-range[2]/table:filter/table:filter-and/" + "table:filter-condition[1]", + "value", "transparent"); + assertXPath(pDoc, "//table:database-ranges/table:database-range[3]/table:filter/" + "table:filter-and/table:filter-condition[1][@loext:data-type='text-color']"); + assertXPath(pDoc, + "//table:database-ranges/table:database-range[3]/table:filter/table:filter-and/" + "table:filter-condition[1]", + "value", "window-font-color"); +} + +void ScExportTest2::testAutofilterColorsOOXML() +{ + { + ScDocShellRef xDocSh = loadDoc(u"autofilter-colors.", FORMAT_XLSX); + std::shared_ptr<utl::TempFile> pXPathFile + = ScBootstrapFixture::exportTo(*xDocSh, FORMAT_XLSX); + xmlDocUniquePtr pTable1 + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/tables/table1.xml"); + CPPUNIT_ASSERT(pTable1); + sal_Int32 nDxfId + = getXPath(pTable1, "/x:table/x:autoFilter/x:filterColumn/x:colorFilter", "dxfId") + .toInt32() + + 1; + + xmlDocUniquePtr pStyles + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/styles.xml"); + CPPUNIT_ASSERT(pStyles); + OString sDxfXPath("/x:styleSheet/x:dxfs/x:dxf[" + OString::number(nDxfId) + + "]/x:fill/x:patternFill/x:fgColor"); + assertXPath(pStyles, sDxfXPath, "rgb", "FFFFD7D7"); + xDocSh->DoClose(); + } + + { + ScDocShellRef xDocSh = loadDoc(u"autofilter-colors-fg.", FORMAT_XLSX); + std::shared_ptr<utl::TempFile> pXPathFile + = ScBootstrapFixture::exportTo(*xDocSh, FORMAT_XLSX); + xmlDocUniquePtr pTable1 + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/tables/table1.xml"); + CPPUNIT_ASSERT(pTable1); + sal_Int32 nDxfId + = getXPath(pTable1, "/x:table/x:autoFilter/x:filterColumn/x:colorFilter", "dxfId") + .toInt32() + + 1; + + xmlDocUniquePtr pStyles + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/styles.xml"); + CPPUNIT_ASSERT(pStyles); + OString sDxfXPath("/x:styleSheet/x:dxfs/x:dxf[" + OString::number(nDxfId) + + "]/x:fill/x:patternFill/x:fgColor"); + assertXPath(pStyles, sDxfXPath, "rgb", "FF3465A4"); + xDocSh->DoClose(); + } +} + +void ScExportTest2::testAutofilterTop10XLSX() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf143068_top10filter.", FORMAT_XLSX); + + xmlDocUniquePtr pDoc = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, + "xl/worksheets/sheet1.xml", FORMAT_XLSX); + CPPUNIT_ASSERT(pDoc); + assertXPath(pDoc, "//x:autoFilter/x:filterColumn", "colId", "0"); + assertXPath(pDoc, "//x:autoFilter/x:filterColumn/x:top10", "val", "4"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf88657ODS() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf88657.", FORMAT_ODS); + + xmlDocUniquePtr pDoc + = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, "styles.xml", FORMAT_ODS); + CPPUNIT_ASSERT(pDoc); + + assertXPath(pDoc, "//number:fraction", "min-denominator-digits", "3"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf41722() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf41722.", FORMAT_XLSX); + + xmlDocUniquePtr pDoc = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, + "xl/worksheets/sheet1.xml", FORMAT_XLSX); + CPPUNIT_ASSERT(pDoc); + + assertXPath(pDoc, "//x:conditionalFormatting/x:cfRule[1]", "operator", "containsText"); + assertXPath(pDoc, "//x:conditionalFormatting/x:cfRule[2]", "operator", "containsText"); + assertXPath(pDoc, "//x:conditionalFormatting/x:cfRule[3]", "operator", "containsText"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf113621() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf113621.", FORMAT_XLSX); + + xmlDocUniquePtr pDoc = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, + "xl/worksheets/sheet1.xml", FORMAT_XLSX); + CPPUNIT_ASSERT(pDoc); + + assertXPath(pDoc, "//x:conditionalFormatting", "sqref", "A1:A1048576"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testEscapeCharInNumberFormatXLSX() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf81939.", FORMAT_XLSX); + xDocSh = saveAndReload(*xDocSh, FORMAT_XLSX); + CPPUNIT_ASSERT(xDocSh.is()); + + xmlDocUniquePtr pDoc + = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, "xl/styles.xml", FORMAT_XLSX); + CPPUNIT_ASSERT(pDoc); + + const sal_Unicode cEuro(8364); // € symbol + assertXPath(pDoc, "/x:styleSheet/x:numFmts/x:numFmt[2]", "formatCode", + "00\\ 00\\ 00\\ 00\\ 00"); + assertXPath(pDoc, "/x:styleSheet/x:numFmts/x:numFmt[3]", "formatCode", + "00\\.00\\.00\\.000\\.0"); // tdf#81939 + // "_-* #,##0\ _€_-;\-* #,##0\ _€_-;_-* "- "_€_-;_-@_-" // tdf#81222 + OUString rFormatStrExpected("_-* #,##0\\ _" + OUStringChar(cEuro) + "_-;\\-* #,##0\\ _" + + OUStringChar(cEuro) + "_-;_-* \"- \"_" + OUStringChar(cEuro) + + "_-;_-@_-"); + assertXPath(pDoc, "/x:styleSheet/x:numFmts/x:numFmt[4]", "formatCode", rFormatStrExpected); + // "_-* #,##0" €"_-;\-* #,##0" €"_-;_-* "- €"_-;_-@_-"); + rFormatStrExpected = "_-* #,##0\" " + OUStringChar(cEuro) + "\"_-;\\-* #,##0\" " + + OUStringChar(cEuro) + "\"_-;_-* \"- " + OUStringChar(cEuro) + + "\"_-;_-@_-"; + assertXPath(pDoc, "/x:styleSheet/x:numFmts/x:numFmt[5]", "formatCode", rFormatStrExpected); + // remove escape char in fraction + assertXPath(pDoc, "/x:styleSheet/x:numFmts/x:numFmt[6]", "formatCode", + "# ?/?;[RED]\\-# #/#####"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testNatNumInNumberFormatXLSX() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf79398_NatNum5.", FORMAT_ODS); + xDocSh = saveAndReload(*xDocSh, FORMAT_XLSX); // Convert [NatNum5] to [DBNum2] in Chinese + CPPUNIT_ASSERT(xDocSh.is()); + + xmlDocUniquePtr pDoc + = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, "xl/styles.xml", FORMAT_XLSX); + CPPUNIT_ASSERT(pDoc); + + assertXPath(pDoc, "/x:styleSheet/x:numFmts/x:numFmt[3]", "formatCode", + "[DBNum2][$-804]General;[RED][DBNum2][$-804]General"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testExponentWithoutSignFormatXLSX() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf102370_ExponentWithoutSign.", FORMAT_ODS); + xDocSh = saveAndReload(*xDocSh, FORMAT_XLSX); + CPPUNIT_ASSERT(xDocSh.is()); + + xDocSh = saveAndReload(*xDocSh, FORMAT_ODS); + CPPUNIT_ASSERT(xDocSh.is()); + + ScDocument& rDoc = xDocSh->GetDocument(); + sal_uInt32 nNumberFormat = rDoc.GetNumberFormat(0, 0, 0); + const SvNumberformat* pNumberFormat = rDoc.GetFormatTable()->GetEntry(nNumberFormat); + const OUString& rFormatStr = pNumberFormat->GetFormatstring(); + + CPPUNIT_ASSERT_EQUAL_MESSAGE("Number format lost exponent without sign during Excel export", + OUString("0.00E0"), rFormatStr); + + xDocSh->DoClose(); +} + +void ScExportTest2::testExtendedLCIDXLSX() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf36038_ExtendedLCID.", FORMAT_ODS); + xDocSh = saveAndReload(*xDocSh, FORMAT_XLSX); + CPPUNIT_ASSERT(xDocSh.is()); + + xmlDocUniquePtr pDoc + = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, "xl/styles.xml", FORMAT_XLSX); + CPPUNIT_ASSERT(pDoc); + // Check export + assertXPath(pDoc, "/x:styleSheet/x:numFmts/x:numFmt[2]", "formatCode", + "[$-107041E]dd\\-mm\\-yyyy"); + assertXPath(pDoc, "/x:styleSheet/x:numFmts/x:numFmt[3]", "formatCode", + "[$-D07041E]dd\\-mm\\-yyyy"); + assertXPath(pDoc, "/x:styleSheet/x:numFmts/x:numFmt[4]", "formatCode", + "[$-1030411]dd\\-mm\\-ee"); + assertXPath(pDoc, "/x:styleSheet/x:numFmts/x:numFmt[5]", "formatCode", + "[$-1B030411]dd\\-mm\\-ee"); + assertXPath(pDoc, "/x:styleSheet/x:numFmts/x:numFmt[6]", "formatCode", + "[$-108040D]dd\\-mm\\-yyyy"); + //assertXPath(pDoc, "/x:styleSheet/x:numFmts/x:numFmt[7]", "formatCode", "[$-108040D]dd\\-mm\\-yyyy"); + assertXPath(pDoc, "/x:styleSheet/x:numFmts/x:numFmt[7]", "formatCode", + "[$-1060401]dd\\-mm\\-yyyy"); + assertXPath(pDoc, "/x:styleSheet/x:numFmts/x:numFmt[8]", "formatCode", + "[$-2060401]dd\\-mm\\-yyyy"); + + // Check import + ScDocument& rDoc = xDocSh->GetDocument(); + SvNumberFormatter* pNumFormatter = rDoc.GetFormatTable(); + const OUString aLang[5] = { "[$-41E]", "[$-411]", "[$-40D]", "[$-401]", "[$-500]" }; + const OUString aCalendar[5] = { "[~buddhist]DD-MM-YYYY", "DD-MM-EE", "[~jewish]DD-MM-YYYY", + "[~hijri]DD-MM-YYYY", "[~dangi]YYYY/MM/DD" }; + // Note: ja-JP Gengou calendar is an implicit secondary (non-gregorian) + // calendar, the explicit [~gengou] calendar modifier does not need to be + // present, the E and EE keywords are used instead of YY and YYYY. + for (sal_Int16 nCol = 1; nCol <= 2; nCol++) + { + for (sal_Int16 nRow = 1; nRow <= 4; nRow++) + { + sal_uInt32 nNumberFormat = rDoc.GetNumberFormat(nCol, nRow, 0); + const SvNumberformat* pNumberFormat = pNumFormatter->GetEntry(nNumberFormat); + const OUString& rFormatStr = pNumberFormat->GetFormatstring(); + const OUString aExpectedFormatStr + = aLang[nRow - 1] + ((nCol == 2 && nRow != 3) ? OUString("[NatNum1]") : OUString()) + + aCalendar[nRow - 1]; + + CPPUNIT_ASSERT_EQUAL_MESSAGE("Number format lost extended LCID during Excel export", + aExpectedFormatStr, rFormatStr); + } + } + + xDocSh->DoClose(); +} + +void ScExportTest2::testHiddenRepeatedRowsODS() +{ + ScDocShellRef xDocSh = loadEmptyDocument(); + CPPUNIT_ASSERT(xDocSh.is()); + + { + ScDocument& rDoc = xDocSh->GetDocument(); + rDoc.SetRowHidden(0, 20, 0, true); + } + + xDocSh = saveAndReload(*xDocSh, FORMAT_ODS); + ScDocument& rDoc = xDocSh->GetDocument(); + SCROW nFirstRow = 0; + SCROW nLastRow = 0; + bool bHidden = rDoc.RowHidden(0, 0, &nFirstRow, &nLastRow); + CPPUNIT_ASSERT(bHidden); + CPPUNIT_ASSERT_EQUAL(SCROW(0), nFirstRow); + CPPUNIT_ASSERT_EQUAL(SCROW(20), nLastRow); + xDocSh->DoClose(); +} + +void ScExportTest2::testHyperlinkTargetFrameODS() +{ + ScDocShellRef xDocSh = loadDoc(u"hyperlink_frame.", FORMAT_ODS); + + ScDocument& rDoc = xDocSh->GetDocument(); + const EditTextObject* pEditText = rDoc.GetEditText(ScAddress(2, 5, 0)); + CPPUNIT_ASSERT(pEditText); + + const SvxFieldData* pData = pEditText->GetFieldData(0, 0, text::textfield::Type::URL); + CPPUNIT_ASSERT_MESSAGE("Failed to get the URL data.", pData); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Failed to get the URL data.", text::textfield::Type::URL, + pData->GetClassId()); + + const SvxURLField* pURLData = static_cast<const SvxURLField*>(pData); + OUString aTargetFrame = pURLData->GetTargetFrame(); + CPPUNIT_ASSERT_EQUAL(OUString("_blank"), aTargetFrame); + + xmlDocUniquePtr pDoc + = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, "content.xml", FORMAT_ODS); + CPPUNIT_ASSERT(pDoc); + OUString aTargetFrameExport + = getXPath(pDoc, + "/office:document-content/office:body/office:spreadsheet/table:table/" + "table:table-row[2]/table:table-cell[2]/text:p/text:a", + "target-frame-name"); + CPPUNIT_ASSERT_EQUAL(OUString("_blank"), aTargetFrameExport); + + xDocSh->DoClose(); +} + +void ScExportTest2::testOpenDocumentAsReadOnly() +{ + ScDocShellRef xDocSh = loadDoc(u"open-as-read-only.", FORMAT_XLSX); + CPPUNIT_ASSERT(xDocSh->IsSecurityOptOpenReadOnly()); + ScDocShellRef xDocSh2 = saveAndReload(*xDocSh, FORMAT_XLSX); + CPPUNIT_ASSERT(xDocSh2->IsSecurityOptOpenReadOnly()); + xDocSh->DoClose(); + xDocSh2->DoClose(); +} + +void ScExportTest2::testKeepSettingsOfBlankRows() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf41425.", FORMAT_XLSX); + + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xDocSh, FORMAT_XLSX); + xmlDocUniquePtr pSheet + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/sheet1.xml"); + CPPUNIT_ASSERT(pSheet); + + // saved blank row with not default setting in A2 + assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row", 2); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf133595() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf133595.", FORMAT_XLSX); + + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xDocSh, FORMAT_XLSX); + xmlDocUniquePtr pSheet + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/sheet1.xml"); + CPPUNIT_ASSERT(pSheet); + + // without the fix in place, mc:AlternateContent would have been added to sheet1 + assertXPath(pSheet, "/x:worksheet/mc:AlternateContent", 0); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf134769() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf134769.", FORMAT_XLSX); + + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xDocSh, FORMAT_XLSX); + xmlDocUniquePtr pSheet + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/sheet1.xml"); + CPPUNIT_ASSERT(pSheet); + + // without the fix in place, the legacyDrawing would have been exported after the checkbox + // and Excel would have claimed the document is corrupted + // Use their ids to check the order + assertXPath(pSheet, "/x:worksheet/x:drawing", "id", "rId2"); + assertXPath(pSheet, "/x:worksheet/x:legacyDrawing", "id", "rId3"); + assertXPath(pSheet, + "/x:worksheet/mc:AlternateContent/mc:Choice/x:controls/mc:AlternateContent/" + "mc:Choice/x:control", + "id", "rId4"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf106181() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf106181.", FORMAT_ODS); + + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xDocSh, FORMAT_XLSX); + xmlDocUniquePtr pSheet + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/sheet1.xml"); + CPPUNIT_ASSERT(pSheet); + + assertXPath(pSheet, + "/x:worksheet/mc:AlternateContent/mc:Choice/x:controls/mc:AlternateContent/" + "mc:Choice/x:control", + "name", "Check Box"); + assertXPath(pSheet, + "/x:worksheet/mc:AlternateContent/mc:Choice/x:controls/mc:AlternateContent/" + "mc:Choice/x:control/x:controlPr", + "altText", "Check Box 1"); + + xmlDocUniquePtr pDrawing + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/drawings/drawing1.xml"); + CPPUNIT_ASSERT(pDrawing); + + assertXPath( + pDrawing, + "/xdr:wsDr/mc:AlternateContent/mc:Choice/xdr:twoCellAnchor/xdr:sp/xdr:nvSpPr/xdr:cNvPr", + "name", "Check Box 1"); + assertXPath( + pDrawing, + "/xdr:wsDr/mc:AlternateContent/mc:Choice/xdr:twoCellAnchor/xdr:sp/xdr:nvSpPr/xdr:cNvPr", + "descr", "Check Box"); + assertXPath( + pDrawing, + "/xdr:wsDr/mc:AlternateContent/mc:Choice/xdr:twoCellAnchor/xdr:sp/xdr:nvSpPr/xdr:cNvPr", + "hidden", "0"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf145057() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf145057.", FORMAT_XLSX); + xDocSh = saveAndReload(*xDocSh, FORMAT_XLSX); + + xmlDocUniquePtr pDoc = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, + "xl/tables/table1.xml", FORMAT_XLSX); + CPPUNIT_ASSERT(pDoc); + + assertXPath(pDoc, "//x:colorFilter", "dxfId", "1"); +} + +void ScExportTest2::testTdf105272() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf105272.", FORMAT_XLSX); + xDocSh = saveAndReload(*xDocSh, FORMAT_XLSX); + ScDocument& rDoc = xDocSh->GetDocument(); + //without the fix in place,it would fail + //Expected: Table1[[#This Row],[Total]]/Table1[[#This Row],['# Athletes]] + //Actual : table1[[#this row],[total]]/table1[[#this row],['# athletes]] + + ASSERT_FORMULA_EQUAL(rDoc, ScAddress(7, 3, 0), + "Table1[[#This Row],[Total]]/Table1[[#This Row],['# Athletes]]", + "Wrong formula"); +} + +void ScExportTest2::testTdf118990() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf118990.", FORMAT_XLSX); + xDocSh = saveAndReload(*xDocSh, FORMAT_XLSX); + ScDocument& rDoc = xDocSh->GetDocument(); + + // TODO: also test A1, which contains a UNC reference to \\localhost\share\lookupsource.xlsx, + // but currently looses "localhost" part when normalized in INetURLObject, becoming + // file:///share/lookupsource.xlsx - which is incorrect, since it points to local filesystem + // and not to Windows network share. + + ASSERT_FORMULA_EQUAL(rDoc, ScAddress(0, 1, 0), + "VLOOKUP(B1,'file://192.168.1.1/share/lookupsource.xlsx'#$Sheet1.A1:B5,2)", + "Wrong Windows share (using host IP) URL in A2"); + + ASSERT_FORMULA_EQUAL(rDoc, ScAddress(0, 2, 0), + "VLOOKUP(B1,'file://NETWORKHOST/share/lookupsource.xlsx'#$Sheet1.A1:B5,2)", + "Wrong Windows share (using hostname) URL in A3"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf121612() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf121612.", FORMAT_ODS); + xDocSh = saveAndReload(*xDocSh, FORMAT_XLSX); + + ScDocument& rDoc = xDocSh->GetDocument(); + + // There should be a pivot table + CPPUNIT_ASSERT(rDoc.HasPivotTable()); + + // DP collection is not lost after export and has one entry + ScDPCollection* pDPColl = rDoc.GetDPCollection(); + CPPUNIT_ASSERT(pDPColl); + CPPUNIT_ASSERT_EQUAL(size_t(1), pDPColl->GetCount()); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf112936() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf112936.", FORMAT_XLSX); + + xmlDocUniquePtr pDoc = XPathHelper::parseExport2( + *this, *xDocSh, m_xSFactory, "xl/pivotCache/pivotCacheDefinition1.xml", FORMAT_XLSX); + CPPUNIT_ASSERT(pDoc); + + assertXPath(pDoc, "//x:pivotCacheDefinition", "recordCount", "4"); + assertXPath(pDoc, "//x:pivotCacheDefinition", "createdVersion", "3"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testXltxExport() +{ + // Create new document + ScDocShell* pShell + = new ScDocShell(SfxModelFlags::EMBEDDED_OBJECT | SfxModelFlags::DISABLE_EMBEDDED_SCRIPTS + | SfxModelFlags::DISABLE_DOCUMENT_RECOVERY); + pShell->DoInitNew(); + + // Export as template and check content type + xmlDocUniquePtr pDoc = XPathHelper::parseExport2(*this, *pShell, m_xSFactory, + "[Content_Types].xml", FORMAT_XLTX); + CPPUNIT_ASSERT(pDoc); + assertXPath(pDoc, "/ContentType:Types/ContentType:Override[@PartName='/xl/workbook.xml']", + "ContentType", + "application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml"); +} + +void ScExportTest2::testPivotCacheAfterExportXLSX() +{ + ScDocShellRef xDocSh = loadDoc(u"numgroup_example.", FORMAT_ODS); + + // export only + std::shared_ptr<utl::TempFile> pTemp = exportTo(*xDocSh, FORMAT_XLSX); + + ScDocument& rDoc = xDocSh->GetDocument(); + CPPUNIT_ASSERT(rDoc.HasPivotTable()); + + // Two pivot tables + ScDPCollection* pDPColl = rDoc.GetDPCollection(); + CPPUNIT_ASSERT(pDPColl); + CPPUNIT_ASSERT_EQUAL(size_t(2), pDPColl->GetCount()); + + // One cache + ScDPCollection::SheetCaches& rSheetCaches = pDPColl->GetSheetCaches(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rSheetCaches.size()); + const ScDPCache* pCache = rSheetCaches.getExistingCache(ScRange(0, 0, 0, 3, 30, 0)); + CPPUNIT_ASSERT_MESSAGE("Pivot cache is expected for A1:D31 on the first sheet.", pCache); + + // See if XLSX export didn't damage group info of the 1st pivot table + const ScDPNumGroupInfo* pInfo = pCache->GetNumGroupInfo(1); + CPPUNIT_ASSERT_MESSAGE("No number group info :(", pInfo); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf114969XLSX() +{ + ScDocShellRef xDocSh = loadDoc(u"sheet_name_with_dots.", FORMAT_ODS); + + xmlDocUniquePtr pDoc = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, + "xl/worksheets/sheet1.xml", FORMAT_XLSX); + CPPUNIT_ASSERT(pDoc); + assertXPath(pDoc, "/x:worksheet/x:hyperlinks/x:hyperlink[1]", "location", "'1.1.1.1'!C1"); + assertXPath(pDoc, "/x:worksheet/x:hyperlinks/x:hyperlink[2]", "location", "'1.1.1.1'!C2"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf115192XLSX() +{ + ScDocShellRef xDocSh = loadDoc(u"test_115192.", FORMAT_XLSX); + + xmlDocUniquePtr pDoc = XPathHelper::parseExport2( + *this, *xDocSh, m_xSFactory, "xl/drawings/_rels/drawing1.xml.rels", FORMAT_XLSX); + CPPUNIT_ASSERT(pDoc); + assertXPath(pDoc, "/rels:Relationships/rels:Relationship[@Id='rId1']", "TargetMode", + "External"); + assertXPathNoAttribute(pDoc, "/rels:Relationships/rels:Relationship[@Id='rId2']", "TargetMode"); + assertXPath(pDoc, "/rels:Relationships/rels:Relationship[@Id='rId3']", "TargetMode", + "External"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf142764() +{ + ScDocShellRef xShell = loadDoc(u"tdf142764.", FORMAT_ODS); + + auto pXPathFile = ScBootstrapFixture::exportTo(*xShell, FORMAT_XLSX); + + xmlDocUniquePtr pSheet + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/sheet1.xml"); + CPPUNIT_ASSERT(pSheet); + + assertXPath(pSheet, "/x:worksheet/x:headerFooter", "differentOddEven", "true"); + assertXPath(pSheet, "/x:worksheet/x:headerFooter", "differentFirst", "true"); + + xShell->DoClose(); +} + +void ScExportTest2::testTdf91634XLSX() +{ + ScDocShellRef xDocSh = loadDoc(u"image_hyperlink.", FORMAT_XLSX); + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xDocSh, FORMAT_XLSX); + + xmlDocUniquePtr pDoc + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/drawings/drawing1.xml"); + CPPUNIT_ASSERT(pDoc); + assertXPath(pDoc, "/xdr:wsDr/xdr:twoCellAnchor/xdr:pic/xdr:nvPicPr/xdr:cNvPr/a:hlinkClick", 1); + + xmlDocUniquePtr pXmlRels + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/drawings/_rels/drawing1.xml.rels"); + CPPUNIT_ASSERT(pXmlRels); + assertXPath(pXmlRels, "/rels:Relationships/rels:Relationship[@Id='rId1']", "Target", + "https://www.google.com/"); + assertXPath(pXmlRels, "/rels:Relationships/rels:Relationship[@Id='rId1']", "TargetMode", + "External"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testValidationCopyPaste() +{ + ScDocShellRef xDocSh = loadDoc(u"validation-copypaste.", FORMAT_ODS); + ScDocument& rSrcDoc = xDocSh->GetDocument(); + + // Copy B1 from src doc to clip + ScDocument aClipDoc(SCDOCMODE_CLIP); + ScRange aSrcRange(1, 0, 1); + ScClipParam aClipParam(aSrcRange, false); + ScMarkData aMark(rSrcDoc.GetSheetLimits()); + aMark.SetMarkArea(aSrcRange); + rSrcDoc.CopyToClip(aClipParam, &aClipDoc, &aMark, false, false); + + // Create second document, paste B1 from clip + ScDocShell* pShell2 + = new ScDocShell(SfxModelFlags::EMBEDDED_OBJECT | SfxModelFlags::DISABLE_EMBEDDED_SCRIPTS + | SfxModelFlags::DISABLE_DOCUMENT_RECOVERY); + pShell2->DoInitNew(); + ScDocument& rDestDoc = pShell2->GetDocument(); + ScRange aDstRange(1, 0, 0); + ScMarkData aMark2(rDestDoc.GetSheetLimits()); + aMark2.SetMarkArea(aDstRange); + rDestDoc.CopyFromClip(aDstRange, aMark2, InsertDeleteFlags::ALL, nullptr, &aClipDoc); + + // save as XLSX + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*pShell2, FORMAT_XLSX); + + // check validation + xmlDocUniquePtr pDoc + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/sheet1.xml"); + CPPUNIT_ASSERT(pDoc); + assertXPathContent(pDoc, "/x:worksheet/x:dataValidations/x:dataValidation/x:formula1", "#REF!"); +} + +void ScExportTest2::testTdf115159() +{ + ScDocShellRef xShell = loadDoc(u"tdf115159.", FORMAT_XLSX); + ScDocShellRef xDocSh = saveAndReload(*xShell, FORMAT_XLSX); + CPPUNIT_ASSERT(xDocSh.is()); + xShell->DoClose(); + + xmlDocUniquePtr pDoc + = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, "xl/workbook.xml", FORMAT_XLSX); + CPPUNIT_ASSERT(pDoc); + + //assert the existing OOXML built-in name is not duplicated + assertXPath(pDoc, "/x:workbook/x:definedNames/x:definedName", 1); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf112567() +{ + // Set the system locale to Hungarian (a language with different range separator) + SvtSysLocaleOptions aOptions; + OUString sLocaleConfigString = aOptions.GetLanguageTag().getBcp47(); + aOptions.SetLocaleConfigString("hu-HU"); + aOptions.Commit(); + comphelper::ScopeGuard g([&aOptions, &sLocaleConfigString] { + aOptions.SetLocaleConfigString(sLocaleConfigString); + aOptions.Commit(); + }); + + ScDocShellRef xShell = loadDoc(u"tdf112567.", FORMAT_XLSX); + ScDocShellRef xDocSh = saveAndReload(*xShell, FORMAT_XLSX); + CPPUNIT_ASSERT(xDocSh.is()); + xShell->DoClose(); + + xmlDocUniquePtr pDoc + = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, "xl/workbook.xml", FORMAT_XLSX); + CPPUNIT_ASSERT(pDoc); + + //assert the existing OOXML built-in name is not duplicated + assertXPath(pDoc, "/x:workbook/x:definedNames/x:definedName", 1); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf122191() +{ + // Set the system locale to Hungarian + SvtSysLocaleOptions aOptions; + OUString sLocaleConfigString = aOptions.GetLanguageTag().getBcp47(); + aOptions.SetLocaleConfigString("hu-HU"); + aOptions.Commit(); + comphelper::ScopeGuard g([&aOptions, &sLocaleConfigString] { + aOptions.SetLocaleConfigString(sLocaleConfigString); + aOptions.Commit(); + }); + + ScDocShellRef xShell = loadDoc(u"tdf122191.", FORMAT_XLSX); + + ScDocument& rDoc = xShell->GetDocument(); + CPPUNIT_ASSERT_EQUAL(OUString("IGAZ"), rDoc.GetString(0, 0, 0)); + + ScDocShellRef xDocSh = saveAndReload(*xShell, FORMAT_XLSX); + CPPUNIT_ASSERT(xDocSh.is()); + xShell->DoClose(); + + ScDocument& rDoc2 = xDocSh->GetDocument(); + // Without the fix in place, this test would have failed with + // - Expected: IGAZ + // - Actual : BOOL00AN + CPPUNIT_ASSERT_EQUAL(OUString("IGAZ"), rDoc2.GetString(0, 0, 0)); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf142881() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf142881.", FORMAT_XLSX); + + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xDocSh, FORMAT_XLSX); + xmlDocUniquePtr pDrawing1 + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/drawings/drawing1.xml"); + CPPUNIT_ASSERT(pDrawing1); + + // Verify that the shapes are rotated and positioned in the expected way + assertXPathContent(pDrawing1, "/xdr:wsDr/xdr:twoCellAnchor[1]/xdr:from/xdr:col", "11"); + assertXPathContent(pDrawing1, "/xdr:wsDr/xdr:twoCellAnchor[1]/xdr:from/xdr:row", "0"); + assertXPathContent(pDrawing1, "/xdr:wsDr/xdr:twoCellAnchor[1]/xdr:to/xdr:col", "12"); + assertXPathContent(pDrawing1, "/xdr:wsDr/xdr:twoCellAnchor[1]/xdr:to/xdr:row", "19"); + + assertXPathContent(pDrawing1, "/xdr:wsDr/xdr:twoCellAnchor[2]/xdr:from/xdr:col", "2"); + assertXPathContent(pDrawing1, "/xdr:wsDr/xdr:twoCellAnchor[2]/xdr:from/xdr:row", "8"); + assertXPathContent(pDrawing1, "/xdr:wsDr/xdr:twoCellAnchor[2]/xdr:to/xdr:col", "7"); + assertXPathContent(pDrawing1, "/xdr:wsDr/xdr:twoCellAnchor[2]/xdr:to/xdr:row", "10"); + + assertXPathContent(pDrawing1, "/xdr:wsDr/xdr:twoCellAnchor[3]/xdr:from/xdr:col", "10"); + assertXPathContent(pDrawing1, "/xdr:wsDr/xdr:twoCellAnchor[3]/xdr:from/xdr:row", "9"); + assertXPathContent(pDrawing1, "/xdr:wsDr/xdr:twoCellAnchor[3]/xdr:to/xdr:col", "11"); + assertXPathContent(pDrawing1, "/xdr:wsDr/xdr:twoCellAnchor[3]/xdr:to/xdr:row", "26"); + + assertXPathContent(pDrawing1, "/xdr:wsDr/xdr:twoCellAnchor[4]/xdr:from/xdr:col", "2"); + assertXPathContent(pDrawing1, "/xdr:wsDr/xdr:twoCellAnchor[4]/xdr:from/xdr:row", "17"); + assertXPathContent(pDrawing1, "/xdr:wsDr/xdr:twoCellAnchor[4]/xdr:to/xdr:col", "8"); + assertXPathContent(pDrawing1, "/xdr:wsDr/xdr:twoCellAnchor[4]/xdr:to/xdr:row", "19"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf112567b() +{ + // Set the system locale to Hungarian (a language with different range separator) + SvtSysLocaleOptions aOptions; + OUString sLocaleConfigString = aOptions.GetLanguageTag().getBcp47(); + aOptions.SetLocaleConfigString("hu-HU"); + aOptions.Commit(); + comphelper::ScopeGuard g([&aOptions, &sLocaleConfigString] { + aOptions.SetLocaleConfigString(sLocaleConfigString); + aOptions.Commit(); + }); + + ScDocShellRef xShell = loadDoc(u"tdf112567.", FORMAT_ODS); + ScDocShellRef xDocSh = saveAndReload(*xShell, FORMAT_XLSX); + CPPUNIT_ASSERT(xDocSh.is()); + xShell->DoClose(); + + xmlDocUniquePtr pDoc + = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, "xl/workbook.xml", FORMAT_XLSX); + CPPUNIT_ASSERT(pDoc); + + //assert the existing OOXML built-in name is not duplicated + assertXPath(pDoc, "/x:workbook/x:definedNames/x:definedName", 1); + + //and it contains "," instead of ";" + assertXPathContent(pDoc, "/x:workbook/x:definedNames/x:definedName[1]", + "Sheet1!$A:$A,Sheet1!$1:$1"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf123645XLSX() +{ + ScDocShellRef xDocSh = loadDoc(u"chart_hyperlink.", FORMAT_XLSX); + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xDocSh, FORMAT_XLSX); + + xmlDocUniquePtr pDoc + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/drawings/drawing1.xml"); + CPPUNIT_ASSERT(pDoc); + assertXPath(pDoc, + "/xdr:wsDr/xdr:twoCellAnchor[1]/xdr:graphicFrame/xdr:nvGraphicFramePr/xdr:cNvPr/" + "a:hlinkClick", + 1); + assertXPath(pDoc, + "/xdr:wsDr/xdr:twoCellAnchor[2]/xdr:graphicFrame/xdr:nvGraphicFramePr/xdr:cNvPr/" + "a:hlinkClick", + 1); + assertXPath(pDoc, + "/xdr:wsDr/xdr:twoCellAnchor[3]/xdr:graphicFrame/xdr:nvGraphicFramePr/xdr:cNvPr/" + "a:hlinkClick", + 1); + + xmlDocUniquePtr pXmlRels + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/drawings/_rels/drawing1.xml.rels"); + CPPUNIT_ASSERT(pXmlRels); + assertXPath(pXmlRels, "/rels:Relationships/rels:Relationship[@Id='rId1']", "TargetMode", + "External"); + assertXPathNoAttribute(pXmlRels, "/rels:Relationships/rels:Relationship[@Id='rId3']", + "TargetMode"); + assertXPath(pXmlRels, "/rels:Relationships/rels:Relationship[@Id='rId5']", "TargetMode", + "External"); + assertXPath(pXmlRels, "/rels:Relationships/rels:Relationship[@Id='rId1']", "Target", + "file:///C:/TEMP/test.xlsx"); + assertXPath(pXmlRels, "/rels:Relationships/rels:Relationship[@Id='rId3']", "Target", + "#Sheet2!A1"); + assertXPath(pXmlRels, "/rels:Relationships/rels:Relationship[@Id='rId5']", "Target", + "https://bugs.documentfoundation.org/show_bug.cgi?id=123645"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf125173XLSX() +{ + ScDocShellRef xDocSh = loadDoc(u"text_box_hyperlink.", FORMAT_ODS); + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xDocSh, FORMAT_XLSX); + + xmlDocUniquePtr pDoc + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/drawings/drawing1.xml"); + CPPUNIT_ASSERT(pDoc); + assertXPath(pDoc, "/xdr:wsDr/xdr:twoCellAnchor/xdr:sp/xdr:nvSpPr/xdr:cNvPr/a:hlinkClick", 1); + + xmlDocUniquePtr pXmlRels + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/drawings/_rels/drawing1.xml.rels"); + CPPUNIT_ASSERT(pXmlRels); + assertXPath(pXmlRels, "/rels:Relationships/rels:Relationship[@Id='rId1']", "Target", + "http://www.google.com/"); + assertXPath(pXmlRels, "/rels:Relationships/rels:Relationship[@Id='rId1']", "TargetMode", + "External"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf79972XLSX() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf79972.", FORMAT_XLSX); + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xDocSh, FORMAT_XLSX); + + xmlDocUniquePtr pDoc + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/sheet1.xml"); + CPPUNIT_ASSERT(pDoc); + assertXPath(pDoc, "/x:worksheet/x:hyperlinks/x:hyperlink", "ref", "A1"); + + xmlDocUniquePtr pXmlRels + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/_rels/sheet1.xml.rels"); + CPPUNIT_ASSERT(pXmlRels); + assertXPath(pXmlRels, "/rels:Relationships/rels:Relationship", "Target", + "https://bugs.documentfoundation.org/show_bug.cgi?id=79972"); + assertXPath(pXmlRels, "/rels:Relationships/rels:Relationship", "TargetMode", "External"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf126024XLSX() +{ + ScDocShellRef xDocSh = loadDoc(u"hyperlink_formula.", FORMAT_XLSX); + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xDocSh, FORMAT_XLSX); + + xmlDocUniquePtr pDoc + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/sheet1.xml"); + CPPUNIT_ASSERT(pDoc); + assertXPath(pDoc, "/x:worksheet/x:hyperlinks/x:hyperlink", "ref", "A2"); + + xmlDocUniquePtr pXmlRels + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/_rels/sheet1.xml.rels"); + CPPUNIT_ASSERT(pXmlRels); + assertXPath(pXmlRels, "/rels:Relationships/rels:Relationship", "Target", + "https://bugs.documentfoundation.org/"); + assertXPath(pXmlRels, "/rels:Relationships/rels:Relationship", "TargetMode", "External"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf126177XLSX() +{ + ScDocShellRef xDocSh = loadDoc(u"hyperlink_export.", FORMAT_XLSX); + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xDocSh, FORMAT_XLSX); + + xmlDocUniquePtr pDoc + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/sheet1.xml"); + CPPUNIT_ASSERT(pDoc); + assertXPath(pDoc, "/x:worksheet/x:hyperlinks/x:hyperlink", "location", "Munka1!A5"); + + xmlDocUniquePtr pXmlRels + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/_rels/sheet1.xml.rels"); + CPPUNIT_ASSERT(pXmlRels); + OUString aTarget = getXPath(pXmlRels, "/rels:Relationships/rels:Relationship", "Target"); + CPPUNIT_ASSERT(aTarget.endsWith("test.xlsx")); + assertXPath(pXmlRels, "/rels:Relationships/rels:Relationship", "TargetMode", "External"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testCommentTextVAlignment() +{ + // Testing comment text alignments. + ScDocShellRef xShell = loadDoc(u"CommentTextVAlign.", FORMAT_ODS); + + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xShell, FORMAT_XLSX); + + xmlDocUniquePtr pVmlDrawing + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/drawings/vmlDrawing1.vml"); + CPPUNIT_ASSERT(pVmlDrawing); + + assertXPathContent(pVmlDrawing, "/xml/v:shape/xx:ClientData/xx:TextVAlign", "Center"); + + xShell->DoClose(); +} + +void ScExportTest2::testCommentTextHAlignment() +{ + // Testing comment text alignments. + ScDocShellRef xShell = loadDoc(u"CommentTextHAlign.", FORMAT_ODS); + + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xShell, FORMAT_XLSX); + + xmlDocUniquePtr pVmlDrawing + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/drawings/vmlDrawing1.vml"); + CPPUNIT_ASSERT(pVmlDrawing); + + assertXPathContent(pVmlDrawing, "/xml/v:shape/xx:ClientData/xx:TextHAlign", "Center"); + + xShell->DoClose(); +} + +void ScExportTest2::testRotatedImageODS() +{ + // Error was, that the length values in shapes were not + // written in the given unit into the file. + css::uno::Reference<css::sheet::XGlobalSheetSettings> xGlobalSheetSettings + = css::sheet::GlobalSheetSettings::create(comphelper::getProcessComponentContext()); + xGlobalSheetSettings->setMetric(static_cast<sal_Int16>(FieldUnit::MM)); + + ScDocShellRef xDocSh = loadDoc(u"tdf103092_RotatedImage.", FORMAT_ODS, true); + + std::shared_ptr<utl::TempFile> pTemp = exportTo(*xDocSh, FORMAT_ODS); + CPPUNIT_ASSERT(pTemp); + xmlDocUniquePtr pXmlDoc = XPathHelper::parseExport(pTemp, m_xSFactory, "content.xml"); + CPPUNIT_ASSERT(pXmlDoc); + + const OUString sTransform = getXPath(pXmlDoc, + "/office:document-content/office:body/office:spreadsheet/" + "table:table/table:shapes/draw:frame", + "transform"); + // Attribute transform has the structure skew (...) rotate (...) translate (x y) + // parts are separated by blank + OUString sTranslate(sTransform.copy(sTransform.lastIndexOf('('))); + sTranslate = sTranslate.copy(1, sTranslate.getLength() - 2); // remove '(' and ')' + const OUString sX(sTranslate.getToken(0, ' ')); + const OUString sY(sTranslate.getToken(1, ' ')); + CPPUNIT_ASSERT(sX.endsWith("mm")); + CPPUNIT_ASSERT(sY.endsWith("mm")); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf85553() +{ + ScDocShellRef xShell = loadDoc(u"tdf85553.", FORMAT_ODS); + CPPUNIT_ASSERT(xShell.is()); + + ScDocShellRef xDocSh = saveAndReload(*xShell, FORMAT_XLS); + xShell->DoClose(); + CPPUNIT_ASSERT(xDocSh.is()); + + ScDocument& rDoc = xDocSh->GetDocument(); + + // Without the fix in place, this test would have failed with + // - Expected: 4.5 + // - Actual : #N/A + CPPUNIT_ASSERT_EQUAL(OUString("4.5"), rDoc.GetString(ScAddress(2, 2, 0))); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf128976() +{ + ScDocShellRef xShell = loadDoc(u"tdf128976.", FORMAT_XLS); + + ScDocShellRef xDocSh = saveAndReload(*xShell, FORMAT_XLS); + xShell->DoClose(); + CPPUNIT_ASSERT(xDocSh.is()); + + ScDocument& rDoc = xDocSh->GetDocument(); + + // Trying to save very small fractional default column width to XLS (where only integer values + // between 0 and 255 are allowed as default) resulted in negative (-1) value after correction, + // and was written as 65535 (invalid default width). As the result, all columns had large width + // when reopened: 28415 (and Excel warned about invalid format). + const sal_uInt16 nColumn0Width = rDoc.GetColWidth(SCCOL(0), SCTAB(0), false); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(45), nColumn0Width); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf143979() +{ + ScDocShellRef xDocSh = loadEmptyDocument(); + CPPUNIT_ASSERT(xDocSh); + + ScDocument& rDoc = xDocSh->GetDocument(); + + OUString aCode = "YYYY-MM\"\"MMM-DDNN"; + sal_Int32 nCheckPos; + SvNumFormatType nType; + sal_uInt32 nFormat; + SvNumberFormatter* pFormatter = rDoc.GetFormatTable(); + pFormatter->PutEntry(aCode, nCheckPos, nType, nFormat); + + ScPatternAttr aNewAttrs(rDoc.GetPool()); + SfxItemSet& rSet = aNewAttrs.GetItemSet(); + rSet.Put(SfxUInt32Item(ATTR_VALUE_FORMAT, nFormat)); + + rDoc.ApplyPattern(0, 0, 0, aNewAttrs); + + rDoc.SetString(ScAddress(0, 0, 0), "08/30/2021"); + + CPPUNIT_ASSERT_EQUAL(OUString("2021-08Aug-30Mon"), rDoc.GetString(ScAddress(0, 0, 0))); + + ScDocShellRef pDocSh = saveAndReload(*xDocSh, FORMAT_ODS); + CPPUNIT_ASSERT(pDocSh.is()); + + ScDocument& rDoc2 = pDocSh->GetDocument(); + + // Without the fix in place, this test would have failed with + // - Expected: 2021-08Aug-30Mon + // - Actual : 2021-A-30Mon + CPPUNIT_ASSERT_EQUAL(OUString("2021-08Aug-30Mon"), rDoc2.GetString(ScAddress(0, 0, 0))); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf120502() +{ + // Create an empty worksheet; resize last column on its first sheet; export to XLSX, and check + // that the last exported column number is correct + ScDocShellRef xDocSh = loadEmptyDocument(); + CPPUNIT_ASSERT(xDocSh); + + ScDocument& rDoc = xDocSh->GetDocument(); + const SCCOL nMaxCol = rDoc.MaxCol(); // 0-based + + const auto nOldWidth = rDoc.GetColWidth(nMaxCol, 0); + rDoc.SetColWidth(nMaxCol, 0, nOldWidth + 100); + + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xDocSh, FORMAT_XLSX); + xmlDocUniquePtr pSheet1 + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/sheet1.xml"); + CPPUNIT_ASSERT(pSheet1); + + // This was 1025 when nMaxCol+1 was 1024 + assertXPath(pSheet1, "/x:worksheet/x:cols/x:col", "max", OUString::number(nMaxCol + 1)); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf131372() +{ + ScDocShellRef xShell = loadDoc(u"tdf131372.", FORMAT_ODS); + + auto pXPathFile = ScBootstrapFixture::exportTo(*xShell, FORMAT_XLSX); + + xmlDocUniquePtr pSheet + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/sheet1.xml"); + CPPUNIT_ASSERT(pSheet); + + assertXPathContent(pSheet, "/x:worksheet/x:sheetData/x:row/x:c[1]/x:f", "NA()"); + assertXPathContent(pSheet, "/x:worksheet/x:sheetData/x:row/x:c[2]/x:f", "#N/A"); + + xShell->DoClose(); +} +void ScExportTest2::testTdf81470() +{ + ScDocShellRef xShell = loadDoc(u"tdf81470.", FORMAT_XLS); + + //without the fix in place, it would have crashed at export time + auto pXPathFile = ScBootstrapFixture::exportTo(*xShell, FORMAT_XLSX); + + //also check revisions are exported + xmlDocUniquePtr pHeaders + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/revisions/revisionHeaders.xml"); + CPPUNIT_ASSERT(pHeaders); + + assertXPath(pHeaders, "/x:headers/x:header[1]", "dateTime", "2014-07-11T13:46:00.000000000Z"); + assertXPath(pHeaders, "/x:headers/x:header[1]", "userName", "Kohei Yoshida"); + assertXPath(pHeaders, "/x:headers/x:header[2]", "dateTime", "2014-07-11T18:38:00.000000000Z"); + assertXPath(pHeaders, "/x:headers/x:header[2]", "userName", "Kohei Yoshida"); + assertXPath(pHeaders, "/x:headers/x:header[3]", "dateTime", "2014-07-11T18:43:00.000000000Z"); + assertXPath(pHeaders, "/x:headers/x:header[3]", "userName", "Kohei Yoshida"); + + xShell->DoClose(); +} + +void ScExportTest2::testTdf122331() +{ + ScDocShellRef xShell = loadDoc(u"tdf122331.", FORMAT_ODS); + + auto pXPathFile = ScBootstrapFixture::exportTo(*xShell, FORMAT_XLSX); + + xmlDocUniquePtr pSheet + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/sheet1.xml"); + CPPUNIT_ASSERT(pSheet); + + assertXPath(pSheet, "/x:worksheet/x:sheetPr", "filterMode", "true"); + assertXPath(pSheet, "/x:worksheet/x:autoFilter", "ref", "A1:B761"); + assertXPath(pSheet, "/x:worksheet/x:autoFilter/x:filterColumn", "colId", "1"); + + xShell->DoClose(); +} + +void ScExportTest2::testTdf83779() +{ + // Roundtripping TRUE/FALSE constants (not functions) must convert them to functions + ScDocShellRef xShell = loadDoc(u"tdf83779.", FORMAT_XLSX); + + auto pXPathFile = ScBootstrapFixture::exportTo(*xShell, FORMAT_XLSX); + + xmlDocUniquePtr pVmlDrawing + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/sheet1.xml"); + CPPUNIT_ASSERT(pVmlDrawing); + + assertXPathContent(pVmlDrawing, "/x:worksheet/x:sheetData/x:row[1]/x:c/x:f", "FALSE()"); + assertXPathContent(pVmlDrawing, "/x:worksheet/x:sheetData/x:row[2]/x:c/x:f", "TRUE()"); + + xShell->DoClose(); +} + +void ScExportTest2::testTdf121715_FirstPageHeaderFooterXLSX() +{ + // Check if first page header and footer are exported properly + ScDocShellRef xShell = loadDoc(u"tdf121715.", FORMAT_XLSX); + + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xShell, FORMAT_XLSX); + xmlDocUniquePtr pDoc + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/sheet1.xml"); + CPPUNIT_ASSERT(pDoc); + + assertXPath(pDoc, "/x:worksheet/x:headerFooter", "differentFirst", "true"); + assertXPathContent(pDoc, "/x:worksheet/x:headerFooter/x:firstHeader", "&CFirst Page Header"); + assertXPathContent(pDoc, "/x:worksheet/x:headerFooter/x:firstFooter", "&CFirst Page Footer"); + + xShell->DoClose(); +} + +void ScExportTest2::testTdf121716_ExportEvenHeaderFooterXLSX() +{ + // Header and footer on even pages should be exported properly + // If there are separate odd/even header, but only 1 footer for all pages (this is possible only in LibreOffice) + // then the footer will be duplicated to have the same footer separately for even/odd pages + + ScDocShellRef xShell = loadDoc(u"tdf121716_EvenHeaderFooter.", FORMAT_ODS); + + ScDocShellRef xDocSh = saveAndReload(*xShell, FORMAT_XLSX); + CPPUNIT_ASSERT(xDocSh.is()); + + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xDocSh, FORMAT_XLSX); + xmlDocUniquePtr pDoc + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/sheet1.xml"); + CPPUNIT_ASSERT(pDoc); + + assertXPath(pDoc, "/x:worksheet/x:headerFooter", "differentOddEven", "true"); + assertXPathContent(pDoc, "/x:worksheet/x:headerFooter/x:oddHeader", + "&Lodd/right&Cpage&Rheader"); + assertXPathContent(pDoc, "/x:worksheet/x:headerFooter/x:oddFooter", "&Lboth&C&12page&Rfooter"); + assertXPathContent(pDoc, "/x:worksheet/x:headerFooter/x:evenHeader", + "&Lpage&Cheader&Reven/left"); + assertXPathContent(pDoc, "/x:worksheet/x:headerFooter/x:evenFooter", "&Lboth&C&12page&Rfooter"); + + pDoc = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/sheet2.xml"); + CPPUNIT_ASSERT(pDoc); + + assertXPath(pDoc, "/x:worksheet/x:headerFooter", "differentOddEven", "true"); + assertXPathContent(pDoc, "/x:worksheet/x:headerFooter/x:oddHeader", "&Coddh"); + assertXPathContent(pDoc, "/x:worksheet/x:headerFooter/x:oddFooter", "&Coddf"); + assertXPathContent(pDoc, "/x:worksheet/x:headerFooter/x:evenHeader", "&Cevenh"); + assertXPathContent(pDoc, "/x:worksheet/x:headerFooter/x:evenFooter", "&Levenf"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf134459_HeaderFooterColorXLSX() +{ + // Colors in header and footer should be exported, and imported properly + ScDocShellRef xShell = loadDoc(u"tdf134459_HeaderFooterColor.", FORMAT_XLSX); + + ScDocShellRef xDocSh = saveAndReload(*xShell, FORMAT_XLSX); + CPPUNIT_ASSERT(xDocSh.is()); + + xmlDocUniquePtr pDoc = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, + "xl/worksheets/sheet1.xml", FORMAT_XLSX); + CPPUNIT_ASSERT(pDoc); + + assertXPathContent(pDoc, "/x:worksheet/x:headerFooter/x:oddHeader", + "&L&Kc06040l&C&K4c3789c&Rr"); + assertXPathContent(pDoc, "/x:worksheet/x:headerFooter/x:oddFooter", + "&Ll&C&K64cf5fc&R&Kcd15aar"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf134817_HeaderFooterTextWith2SectionXLSX() +{ + // Header/footer text with multiple selection should be exported, and imported properly + ScDocShellRef xShell = loadDoc(u"tdf134817_HeaderFooterTextWith2Section.", FORMAT_XLSX); + + ScDocShellRef xDocSh = saveAndReload(*xShell, FORMAT_XLSX); + CPPUNIT_ASSERT(xDocSh.is()); + + xmlDocUniquePtr pDoc = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, + "xl/worksheets/sheet1.xml", FORMAT_XLSX); + CPPUNIT_ASSERT(pDoc); + + assertXPathContent(pDoc, "/x:worksheet/x:headerFooter/x:oddHeader", + "&L&\"Abadi,Regular\"&11aaa&\"Bembo,Regular\"&20bbb"); + assertXPathContent(pDoc, "/x:worksheet/x:headerFooter/x:oddFooter", + "&R&\"Cambria,Regular\"&14camb&\"Dante,Regular\"&18dant"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf121718_UseFirstPageNumberXLSX() +{ + // If "First page number" is not checked then useFirstPageNumb, and firstPageNumber should not be exported. + ScDocShellRef xShell = loadDoc(u"tdf121718_UseFirstPageNumber.", FORMAT_ODS); + + ScDocShellRef xDocSh = saveAndReload(*xShell, FORMAT_XLSX); + CPPUNIT_ASSERT(xDocSh.is()); + + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xDocSh, FORMAT_XLSX); + xmlDocUniquePtr pDoc + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/sheet1.xml"); + CPPUNIT_ASSERT(pDoc); + + assertXPath(pDoc, "/x:worksheet/x:pageSetup", "useFirstPageNumber", "true"); + assertXPath(pDoc, "/x:worksheet/x:pageSetup", "firstPageNumber", "10"); + + pDoc = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/sheet2.xml"); + CPPUNIT_ASSERT(pDoc); + + assertXPathNoAttribute(pDoc, "/x:worksheet/x:pageSetup", "useFirstPageNumber"); + assertXPathNoAttribute(pDoc, "/x:worksheet/x:pageSetup", "firstPageNumber"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testHeaderFontStyleXLSX() +{ + ScDocShellRef xShell = loadDoc(u"tdf134826.", FORMAT_XLSX); + + ScDocument& rDoc = xShell->GetDocument(); + SfxStyleSheetBase* pStyleSheet + = rDoc.GetStyleSheetPool()->Find(rDoc.GetPageStyle(0), SfxStyleFamily::Page); + const SfxItemSet& rItemSet = pStyleSheet->GetItemSet(); + const ScPageHFItem& rHFItem = rItemSet.Get(ATTR_PAGE_HEADERRIGHT); + const EditTextObject* pTextObj = rHFItem.GetLeftArea(); + + std::vector<EECharAttrib> rLst; + + // first line is bold. + pTextObj->GetCharAttribs(0, rLst); + bool bHasBold = std::any_of(rLst.begin(), rLst.end(), [](const EECharAttrib& rAttrib) { + return rAttrib.pAttr->Which() == EE_CHAR_WEIGHT + && static_cast<const SvxWeightItem&>(*rAttrib.pAttr).GetWeight() == WEIGHT_BOLD; + }); + CPPUNIT_ASSERT_MESSAGE("First line should be bold.", bHasBold); + + // second line is italic. + pTextObj->GetCharAttribs(1, rLst); + bool bHasItalic = std::any_of(rLst.begin(), rLst.end(), [](const EECharAttrib& rAttrib) { + return rAttrib.pAttr->Which() == EE_CHAR_ITALIC + && static_cast<const SvxPostureItem&>(*rAttrib.pAttr).GetPosture() == ITALIC_NORMAL; + }); + CPPUNIT_ASSERT_MESSAGE("Second line should be italic.", bHasItalic); + + xShell->DoClose(); +} + +void ScExportTest2::testTdf135828_Shape_Rect() +{ + if (!IsDefaultDPI()) + return; + // tdf#135828 Check that the width and the height of rectangle of the shape is correct. + // tdf#123613 Check the positioning, and allow massive rounding errors because of the back and + // forth conversion between emu and hmm. + ScDocShellRef xShell = loadDoc(u"tdf135828_Shape_Rect.", FORMAT_XLSX); + + ScDocShellRef xDocSh = saveAndReload(*xShell, FORMAT_XLSX); + CPPUNIT_ASSERT(xDocSh.is()); + + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xDocSh, FORMAT_XLSX); + + xmlDocUniquePtr pDrawing + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/drawings/drawing1.xml"); + CPPUNIT_ASSERT(pDrawing); + + double nXPosOfTopleft + = getXPath(pDrawing, "/xdr:wsDr/xdr:twoCellAnchor/xdr:sp/xdr:spPr/a:xfrm/a:off", "x") + .toDouble(); + double nYPosOfTopleft + = getXPath(pDrawing, "/xdr:wsDr/xdr:twoCellAnchor/xdr:sp/xdr:spPr/a:xfrm/a:off", "y") + .toDouble(); + double nWidth + = getXPath(pDrawing, "/xdr:wsDr/xdr:twoCellAnchor/xdr:sp/xdr:spPr/a:xfrm/a:ext", "cx") + .toDouble(); + double nHeight + = getXPath(pDrawing, "/xdr:wsDr/xdr:twoCellAnchor/xdr:sp/xdr:spPr/a:xfrm/a:ext", "cy") + .toDouble(); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(854640, nXPosOfTopleft, 10000); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-570600, nYPosOfTopleft, 10000); + CPPUNIT_ASSERT_DOUBLES_EQUAL(294840, nWidth, 10000); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1988280, nHeight, 10000); +} + +void ScExportTest2::testTdf123139XLSX() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf123139_applyAlignment.", FORMAT_XLSX); + + ScDocument& rDoc = xDocSh->GetDocument(); + const ScPatternAttr* pAttr = rDoc.GetPattern(0, 0, 0); //A1 + + { + const SvxHorJustifyItem& rJustify = pAttr->GetItem(ATTR_HOR_JUSTIFY); + CPPUNIT_ASSERT_EQUAL(SvxCellHorJustify::Repeat, rJustify.GetValue()); + } + + pAttr = rDoc.GetPattern(0, 1, 0); //A2 + + { + const SfxPoolItem& rItem = pAttr->GetItem(ATTR_HOR_JUSTIFY); + const SvxHorJustifyItem& rJustify = static_cast<const SvxHorJustifyItem&>(rItem); + CPPUNIT_ASSERT_EQUAL(SvxCellHorJustify::Center, rJustify.GetValue()); + } + + { + const ScProtectionAttr& rItem = pAttr->GetItem(ATTR_PROTECTION); + CPPUNIT_ASSERT(rItem.GetProtection()); + CPPUNIT_ASSERT(!rItem.GetHideFormula()); + } + + pAttr = rDoc.GetPattern(2, 0, 0); //C1 + + { + const SfxPoolItem& rItem = pAttr->GetItem(ATTR_HOR_JUSTIFY); + const SvxHorJustifyItem& rJustify = static_cast<const SvxHorJustifyItem&>(rItem); + CPPUNIT_ASSERT_EQUAL(SvxCellHorJustify::Standard, rJustify.GetValue()); + } + + { + const ScProtectionAttr& rItem = pAttr->GetItem(ATTR_PROTECTION); + CPPUNIT_ASSERT(rItem.GetProtection()); + CPPUNIT_ASSERT(rItem.GetHideFormula()); + } + + pAttr = rDoc.GetPattern(2, 1, 0); //C2 + + { + const SfxPoolItem& rItem = pAttr->GetItem(ATTR_HOR_JUSTIFY); + const SvxHorJustifyItem& rJustify = static_cast<const SvxHorJustifyItem&>(rItem); + CPPUNIT_ASSERT_EQUAL(SvxCellHorJustify::Block, rJustify.GetValue()); + } + + { + const ScProtectionAttr& rItem = pAttr->GetItem(ATTR_PROTECTION); + CPPUNIT_ASSERT(!rItem.GetProtection()); + CPPUNIT_ASSERT(!rItem.GetHideFormula()); + } + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf123353() +{ + ScDocShellRef xShell = loadDoc(u"tdf123353.", FORMAT_XLSX); + + ScDocShellRef xDocSh = saveAndReload(*xShell, FORMAT_XLSX); + CPPUNIT_ASSERT(xDocSh.is()); + + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xDocSh, FORMAT_XLSX); + + xmlDocUniquePtr pDoc + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/sheet1.xml"); + CPPUNIT_ASSERT(pDoc); + + assertXPath(pDoc, "/x:worksheet/x:autoFilter/x:filterColumn/x:filters", "blank", "1"); + + xShell->DoClose(); +} + +void ScExportTest2::testTdf140098() +{ + ScDocShellRef xShell = loadDoc(u"tdf140098.", FORMAT_ODS); + + ScDocShellRef xDocSh = saveAndReload(*xShell, FORMAT_XLSX); + CPPUNIT_ASSERT(xDocSh.is()); + + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xDocSh, FORMAT_XLSX); + + xmlDocUniquePtr pDoc + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/sheet1.xml"); + CPPUNIT_ASSERT(pDoc); + + assertXPath(pDoc, "/x:worksheet/x:autoFilter/x:filterColumn/x:filters", "blank", "1"); + + xShell->DoClose(); +} + +void ScExportTest2::testTdf133688_precedents() +{ + // tdf#133688 Check that we do not export detective shapes. + ScDocShellRef xShell = loadDoc(u"tdf133688_dont_save_precedents_to_xlsx.", FORMAT_ODS); + + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xShell, FORMAT_XLSX); + xmlDocUniquePtr pDrawing + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/drawings/drawing1.xml"); + CPPUNIT_ASSERT(pDrawing); + + // We do not export any shapes. + assertXPath(pDrawing, "/xdr:wsDr/xdr:twoCellAnchor[1]", 0); +} + +void ScExportTest2::testTdf91251_missingOverflowRoundtrip() +{ + // tdf#91251 check whether textBox overflow property (horzOverflow and vertOverflow) is + // getting preserved after roundtrip + ScDocShellRef xShell = loadDoc(u"tdf91251_missingOverflowRoundtrip.", FORMAT_XLSX); + + ScDocShellRef xDocSh = saveAndReload(*xShell, FORMAT_XLSX); + CPPUNIT_ASSERT(xDocSh.is()); + + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xDocSh, FORMAT_XLSX); + + xmlDocUniquePtr pDrawing + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/drawings/drawing1.xml"); + CPPUNIT_ASSERT(pDrawing); + + assertXPath(pDrawing, "/xdr:wsDr/xdr:twoCellAnchor/xdr:sp/xdr:txBody/a:bodyPr", "horzOverflow", + "clip"); + assertXPath(pDrawing, "/xdr:wsDr/xdr:twoCellAnchor/xdr:sp/xdr:txBody/a:bodyPr", "horzOverflow", + "clip"); +} + +void ScExportTest2::testTdf137000_handle_upright() +{ + // tdf#106197 When exporting the "upright" attribute, we must set + // TextPreRotateAngle to 0. + // (Upright is an xml attribute of xdr:txBody/a:bodyPr. It is set when + // in a textbox menu we choose: do not rotate this element.) + ScDocShellRef xShell = loadDoc(u"tdf137000_export_upright.", FORMAT_XLSX); + + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xShell, FORMAT_XLSX); + xmlDocUniquePtr pDrawing + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/drawings/drawing1.xml"); + CPPUNIT_ASSERT(pDrawing); + + assertXPath(pDrawing, "/xdr:wsDr/xdr:twoCellAnchor/xdr:sp/xdr:txBody/a:bodyPr", "rot", + "-5400000"); +} + +void ScExportTest2::testTdf126305_DataValidatyErrorAlert() +{ + ScDocShellRef xShell = loadDoc(u"tdf126305.", FORMAT_ODS); + + ScDocShellRef xDocSh = saveAndReload(*xShell, FORMAT_XLSX); + CPPUNIT_ASSERT(xDocSh.is()); + + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xDocSh, FORMAT_XLSX); + xmlDocUniquePtr pDoc + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/sheet1.xml"); + CPPUNIT_ASSERT(pDoc); + + assertXPath(pDoc, "/x:worksheet/x:dataValidations/x:dataValidation[1]", "errorStyle", "stop"); + assertXPath(pDoc, "/x:worksheet/x:dataValidations/x:dataValidation[2]", "errorStyle", + "warning"); + assertXPath(pDoc, "/x:worksheet/x:dataValidations/x:dataValidation[3]", "errorStyle", + "information"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf76047_externalLink() +{ + ScDocShellRef pShell = loadDoc(u"tdf76047_externalLink.", FORMAT_XLSX); + + // load data from external links. (tdf76047_externalLinkSource.ods) + // that file has to be in the same directory as tdf76047_externalLink.xlsx + pShell->ReloadAllLinks(); + ScDocument& rDoc = pShell->GetDocument(); + + // compare the data loaded from external links with the expected result stored in the test file + for (int nCol = 1; nCol <= 5; nCol++) + { + for (int nRow = 3; nRow <= 5; nRow++) + { + OUString aStr1 = rDoc.GetString(ScAddress(nCol, nRow, 0)); + OUString aStr2 = rDoc.GetString(ScAddress(nCol, nRow + 5, 0)); + OUString aStr3 = rDoc.GetString(ScAddress(nCol, nRow + 11, 0)); + + CPPUNIT_ASSERT_EQUAL(aStr1, aStr3); + CPPUNIT_ASSERT_EQUAL(aStr2, aStr3); + } + } +} + +void ScExportTest2::testTdf87973_externalLinkSkipUnuseds() +{ + ScDocShellRef pShell = loadDoc(u"tdf87973_externalLinkSkipUnuseds.", FORMAT_ODS); + + // try to load data from external link: tdf132105_external.ods + // that file has to be in the same directory as tdf87973_externalLinkSkipUnuseds.ods + pShell->ReloadAllLinks(); + ScDocument& rDoc = pShell->GetDocument(); + + // change external link to: 87973_externalSource.ods + OUString aFormula = rDoc.GetFormula(3, 1, 0); + auto nIdxOfFilename = aFormula.indexOf("tdf132105_external.ods"); + aFormula = aFormula.replaceAt(nIdxOfFilename, 22, u"87973_externalSource.ods"); + auto nIdxOfFile = aFormula.indexOf("file"); + + // saveAndReload save the file to a temporary directory + // the link must be changed to point to that directory + utl::TempFile aTempFile; + auto aTempFilename = aTempFile.GetURL(); + auto nIdxOfTmpFile = aTempFilename.lastIndexOf('/'); + aTempFilename = aTempFilename.copy(0, nIdxOfTmpFile + 1); + + aFormula = aFormula.replaceAt(nIdxOfFile, nIdxOfFilename - nIdxOfFile, aTempFilename); + rDoc.SetFormula(ScAddress(3, 1, 0), aFormula, formula::FormulaGrammar::GRAM_NATIVE_UI); + + // tdf#138832: test the same thing with singleref link + aFormula = rDoc.GetFormula(3, 2, 0); + nIdxOfFilename = aFormula.indexOf("tdf132105_external.ods"); + aFormula = aFormula.replaceAt(nIdxOfFilename, 22, u"87973_externalSource.ods"); + nIdxOfFile = aFormula.indexOf("file"); + + aFormula = aFormula.replaceAt(nIdxOfFile, nIdxOfFilename - nIdxOfFile, aTempFilename); + rDoc.SetFormula(ScAddress(3, 2, 0), aFormula, formula::FormulaGrammar::GRAM_NATIVE_UI); + + // save and load back + ScDocShellRef pDocSh = saveAndReload(*pShell, FORMAT_XLSX); + CPPUNIT_ASSERT(pDocSh.is()); + + // check if the new filename is present in the link (and not replaced by '[2]') + ScDocument& rDoc2 = pDocSh->GetDocument(); + OUString aFormula2 = rDoc2.GetFormula(3, 1, 0); + CPPUNIT_ASSERT(aFormula2.indexOf("tdf132105_external.ods") < 0); + CPPUNIT_ASSERT(aFormula2.indexOf("87973_externalSource.ods") >= 0); + aFormula2 = rDoc2.GetFormula(3, 2, 0); + CPPUNIT_ASSERT(aFormula2.indexOf("tdf132105_external.ods") < 0); + CPPUNIT_ASSERT(aFormula2.indexOf("87973_externalSource.ods") >= 0); + + pDocSh->DoClose(); +} + +void ScExportTest2::testTdf51022_lostPrintRange() +{ + ScDocShellRef pShell = loadDoc(u"tdf87973_externalLinkSkipUnuseds.", FORMAT_ODS); + + pShell->ReloadAllLinks(); + ScDocument& rDoc = pShell->GetDocument(); + + //Add print ranges + ScRange aRange1(1, 2, 0, 3, 4, 0); + ScRange aRange2(1, 6, 0, 3, 7, 0); + rDoc.AddPrintRange(0, aRange1); + rDoc.AddPrintRange(0, aRange2); + + // save and load back + ScDocShellRef pDocSh = saveAndReload(*pShell, FORMAT_ODS); + CPPUNIT_ASSERT(pDocSh.is()); + + // check if the same print ranges are present + ScDocument& rDoc2 = pDocSh->GetDocument(); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(2), rDoc2.GetPrintRangeCount(0)); + CPPUNIT_ASSERT_EQUAL(aRange1, *rDoc2.GetPrintRange(0, 0)); + CPPUNIT_ASSERT_EQUAL(aRange2, *rDoc2.GetPrintRange(0, 1)); + + pDocSh->DoClose(); +} + +void ScExportTest2::testTdf138741_externalLinkSkipUnusedsCrash() +{ + ScDocShellRef xShell = loadDoc(u"tdf138741_externalLinkSkipUnusedsCrash.", FORMAT_XLSX); + + //without the fix in place, it would have crashed at export time + ScBootstrapFixture::exportTo(*xShell, FORMAT_XLSX); + + xShell->DoClose(); +} + +void ScExportTest2::testTdf138824_linkToParentDirectory() +{ + ScDocShellRef xShell = loadDoc(u"childDir/tdf138824_linkToParentDirectory.", FORMAT_ODS); + + ScDocument& rDoc = xShell->GetDocument(); + + // saveAndReload save the file to a temporary directory + // the link must be changed to point to that parent directory + utl::TempFile aTempFile; + auto aTempFilename = aTempFile.GetURL(); + auto nIdxOfTmpFile = aTempFilename.lastIndexOf('/'); + nIdxOfTmpFile = aTempFilename.lastIndexOf('/', nIdxOfTmpFile); + aTempFilename = aTempFilename.copy(0, nIdxOfTmpFile + 1); + + // change external link to tmp directory + OUString aFormula = rDoc.GetFormula(3, 1, 0); + auto nIdxOfFilename = aFormula.indexOf("tdf138824_externalSource.ods"); + auto nIdxOfFile = aFormula.indexOf("file"); + + aFormula = aFormula.replaceAt(nIdxOfFile, nIdxOfFilename - nIdxOfFile, aTempFilename); + rDoc.SetFormula(ScAddress(3, 1, 0), aFormula, formula::FormulaGrammar::GRAM_NATIVE_UI); + + ScDocShellRef xDocSh = saveAndReload(*xShell, FORMAT_XLSX); + CPPUNIT_ASSERT(xDocSh.is()); + + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xDocSh, FORMAT_XLSX); + xmlDocUniquePtr pDoc = XPathHelper::parseExport( + pXPathFile, m_xSFactory, "xl/externalLinks/_rels/externalLink1.xml.rels"); + CPPUNIT_ASSERT(pDoc); + + // test also the Linux specific bug tdf#121472 + assertXPath(pDoc, "/rels:Relationships/rels:Relationship", "Target", + "../tdf138824_externalSource.ods"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf129969() +{ + ScDocShellRef xShell = loadDoc(u"external_hyperlink.", FORMAT_ODS); + + ScDocShellRef xDocSh = saveAndReload(*xShell, FORMAT_XLSX); + CPPUNIT_ASSERT(xDocSh.is()); + ScDocument& rDoc = xDocSh->GetDocument(); + ScAddress aPos(0, 0, 0); + const EditTextObject* pEditText = rDoc.GetEditText(aPos); + const SvxFieldData* pData = pEditText->GetFieldData(0, 0, text::textfield::Type::URL); + const SvxURLField* pURLData = static_cast<const SvxURLField*>(pData); + CPPUNIT_ASSERT(pURLData->GetURL().endsWith("/%23folder/test.ods#Sheet2.B10")); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf147088() +{ + ScDocShellRef xShell = loadDoc(u"tdf147088.", FORMAT_FODS); + + ScDocShellRef xDocSh = saveAndReload(*xShell, FORMAT_XLSX); + xShell->DoClose(); + CPPUNIT_ASSERT(xDocSh.is()); + + ScDocument& rDoc = xDocSh->GetDocument(); + + // Without the fix in place, this test would have failed with + // - Expected: _xffff_ + // - Actual : + CPPUNIT_ASSERT_EQUAL(OUString("_xffff_"), rDoc.GetString(0, 0, 0)); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf84874() +{ + ScDocShellRef xShell = loadDoc(u"tdf84874.", FORMAT_ODS); + + ScDocShellRef xDocSh = saveAndReload(*xShell, FORMAT_XLSX); + xShell->DoClose(); + CPPUNIT_ASSERT(xDocSh.is()); + + ScDocument& rDoc = xDocSh->GetDocument(); + + const ScValidationData* pData = rDoc.GetValidationEntry(1); + OUString aTitle, aText; + pData->GetInput(aTitle, aText); + sal_uInt32 nPromptTitleLen = aTitle.getLength(); + sal_uInt32 nPromptTextLen = aText.getLength(); + + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(255), nPromptTitleLen); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(255), nPromptTextLen); + + ScValidErrorStyle eErrStyle = SC_VALERR_STOP; + pData->GetErrMsg(aTitle, aText, eErrStyle); + sal_uInt32 nErrorTitleLen = aTitle.getLength(); + sal_uInt32 nErrorTextLen = aText.getLength(); + + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(255), nErrorTitleLen); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(255), nErrorTextLen); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf136721_paper_size() +{ + ScDocShellRef xShell = loadDoc(u"tdf136721_letter_sized_paper.", FORMAT_XLSX); + + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xShell, FORMAT_XLSX); + xmlDocUniquePtr pDoc + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/sheet1.xml"); + CPPUNIT_ASSERT(pDoc); + + assertXPath(pDoc, "/x:worksheet/x:pageSetup", "paperSize", "70"); +} + +void ScExportTest2::testTdf139258_rotated_image() +{ + // Check that the topleft position of the image is correct. + ScDocShellRef xShell = loadDoc(u"tdf139258_rotated_image.", FORMAT_ODS); + + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xShell, FORMAT_XLSX); + + xmlDocUniquePtr pDrawing + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/drawings/drawing1.xml"); + CPPUNIT_ASSERT(pDrawing); + + assertXPathContent(pDrawing, "/xdr:wsDr/xdr:twoCellAnchor/xdr:from/xdr:col", "1"); + assertXPathContent(pDrawing, "/xdr:wsDr/xdr:twoCellAnchor/xdr:from/xdr:row", "12"); + assertXPathContent(pDrawing, "/xdr:wsDr/xdr:twoCellAnchor/xdr:to/xdr:col", "6"); + assertXPathContent(pDrawing, "/xdr:wsDr/xdr:twoCellAnchor/xdr:to/xdr:row", "25"); +} + +void ScExportTest2::testTdf142854_GridVisibilityImportXlsxInHeadlessMode() +{ + // Tests are running in Headless mode + // Import an ods file with 'Hide' global grid visibility setting. + ScDocShellRef xShell + = loadDocAndSetupModelViewController(u"tdf126541_GridOffGlobally.", FORMAT_ODS); + CPPUNIT_ASSERT(!xShell->GetDocument().GetViewOptions().GetOption(VOPT_GRID)); + + // To avoid regression, in headless mode leave the bug tdf126541 + // It means Sheet based grid line visibility setting will overwrite the global setting. + // If there is only 1 sheet in the document, it will not result visible problems. + xShell = loadDocAndSetupModelViewController(u"tdf126541_GridOff.", FORMAT_XLSX); + CPPUNIT_ASSERT(!xShell->GetDocument().GetViewOptions().GetOption(VOPT_GRID)); +} + +void ScExportTest2::testTdf144642_RowHeightRounding() +{ + // MS Excel round down row heights to 0.75pt + // MS Excel can save a row height of 28.35pt, but will display it as a row height of 27.75pt. + // Calc simulates this roundings but only if the xlsx file was saved in MS Excel. + + ScDocShellRef xShell = loadDoc(u"tdf144642_RowHeight_10mm_SavedByCalc.", FORMAT_XLSX); + ScDocument& rDoc = xShell->GetDocument(); + // 10mm == 567 twips == 28.35pt + CPPUNIT_ASSERT_EQUAL(sal_uInt16(567), rDoc.GetRowHeight(0, 0)); + CPPUNIT_ASSERT_EQUAL(tools::Long(567 * 26), rDoc.GetRowHeight(0, 25, 0, true)); + xShell->DoClose(); + + xShell = loadDoc(u"tdf144642_RowHeight_28.35pt_SavedByExcel.", FORMAT_XLSX); + ScDocument& rDoc2 = xShell->GetDocument(); + // 555twips == 27.75pt == 9.79mm + CPPUNIT_ASSERT_EQUAL(sal_uInt16(555), rDoc2.GetRowHeight(0, 0)); + CPPUNIT_ASSERT_EQUAL(tools::Long(555 * 26), rDoc2.GetRowHeight(0, 25, 0, true)); + xShell->DoClose(); +} + +void ScExportTest2::testTdf145129_DefaultRowHeightRounding() +{ + // MS Excel round down row heights to 0.75pt + // Same as Tdf144642 but with default row height. + + ScDocShellRef xShell + = loadDoc(u"tdf145129_DefaultRowHeight_28.35pt_SavedByExcel.", FORMAT_XLSX); + ScDocument& rDoc = xShell->GetDocument(); + // 555twips == 27.75pt == 9.79mm + CPPUNIT_ASSERT_EQUAL(sal_uInt16(555), rDoc.GetRowHeight(0, 0)); + CPPUNIT_ASSERT_EQUAL(tools::Long(555 * 52), rDoc.GetRowHeight(0, 51, 0, true)); + xShell->DoClose(); +} + +void ScExportTest2::testTdf151755_stylesLostOnXLSXExport() +{ + // Check if empty cells with custom sytle are exported, even if + // there is other empty cells with default style, left of it. + ScDocShellRef xShell = loadDoc(u"tdf151755_stylesLostOnXLSXExport.", FORMAT_XLSX); + + // Resave the xlsx file without any modification. + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xShell, FORMAT_XLSX); + xmlDocUniquePtr pSheet + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/sheet1.xml"); + CPPUNIT_ASSERT(pSheet); + + // Check if all the 3 empty cells with styles are saved, and have the same style id. + assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[4]/x:c", 4); + OUString aCellStyleId = getXPath(pSheet, "/x:worksheet/x:sheetData/x:row[4]/x:c[2]", "s"); + assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[4]/x:c[2]", "s", aCellStyleId); + assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[4]/x:c[3]", "s", aCellStyleId); + assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[4]/x:c[4]", "s", aCellStyleId); +} + +void ScExportTest2::testTdf140431() +{ + ScDocShellRef xShell = loadDoc(u"129969-min.", FORMAT_XLSX); + + ScDocShellRef xDocSh = saveAndReload(*xShell, FORMAT_XLSX); + CPPUNIT_ASSERT(xDocSh.is()); + ScDocument& rDoc = xDocSh->GetDocument(); + ScAddress aPos(0, 2, 0); + const EditTextObject* pEditText = rDoc.GetEditText(aPos); + const SvxFieldData* pData = pEditText->GetFieldData(0, 0, text::textfield::Type::URL); + const SvxURLField* pURLData = static_cast<const SvxURLField*>(pData); + CPPUNIT_ASSERT(pURLData->GetURL().startsWith("file://ndhlis")); + + xDocSh->DoClose(); +} + +void ScExportTest2::testCheckboxFormControlXlsxExport() +{ + if (!IsDefaultDPI()) + return; + // Given a document that has a checkbox form control: + ScDocShellRef xShell = loadDoc(u"checkbox-form-control.", FORMAT_XLSX); + + // When exporting to XLSX: + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xShell, FORMAT_XLSX); + + // Then make sure its VML markup is written and it has a correct position + size: + xmlDocUniquePtr pDoc + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/drawings/vmlDrawing1.vml"); + // Without the fix in place, this test would have failed as there was no such stream. + CPPUNIT_ASSERT(pDoc); + assertXPathContent(pDoc, "/xml/v:shape/xx:ClientData/xx:Anchor", "1, 22, 3, 3, 3, 30, 6, 1"); +} + +void ScExportTest2::testButtonFormControlXlsxExport() +{ + // Given a document that has a checkbox form control: + ScDocShellRef xShell = loadDoc(u"button-form-control.", FORMAT_XLSX); + + // When exporting to XLSX: + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xShell, FORMAT_XLSX); + + // Then make sure its control markup is written and it has a correct position + size: + xmlDocUniquePtr pDoc + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/sheet1.xml"); + CPPUNIT_ASSERT(pDoc); + // Without the fix in place, this test would have failed with: + // - XPath '//x:anchor/x:from/xdr:col' not found + // i.e. the control markup was missing, the button was lost on export. + assertXPathContent(pDoc, "//x:anchor/x:from/xdr:col", "1"); + assertXPathContent(pDoc, "//x:anchor/x:from/xdr:row", "3"); + assertXPathContent(pDoc, "//x:anchor/x:to/xdr:col", "3"); + assertXPathContent(pDoc, "//x:anchor/x:to/xdr:row", "7"); + + // Also make sure that an empty macro attribute is not written. + // Without the fix in place, this test would have failed with: + // - XPath '//x:controlPr' unexpected 'macro' attribute + // i.e. macro in an xlsx file was not omitted, which is considered invalid by Excel. + assertXPathNoAttribute(pDoc, "//x:controlPr", "macro"); +} + +void ScExportTest2::testTdf142929_filterLessThanXLSX() +{ + // Document contains a standard filter with '<' condition. + ScDocShellRef xDocSh = loadDoc(u"tdf142929.", FORMAT_XLSX); + + xmlDocUniquePtr pDoc = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, + "xl/worksheets/sheet1.xml", FORMAT_XLSX); + CPPUNIT_ASSERT(pDoc); + assertXPath(pDoc, "//x:customFilters/x:customFilter", "val", "2"); + assertXPath(pDoc, "//x:customFilters/x:customFilter", "operator", "lessThan"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testInvalidNamedRange() +{ + // Given a document which has a named range (myname) that refers to the "1" external link, but + // the link's type is xlPathMissing, when importing that document: + ScDocShellRef xDocSh = loadDoc(u"invalid-named-range.", FORMAT_XLSX); + + // Then make sure that named range is ignored, as "1" can't be resolved, and exporting it back + // to XLSX (without the xlPathMissing link) would corrupt the document: + uno::Reference<beans::XPropertySet> xDocProps(xDocSh->GetModel(), uno::UNO_QUERY); + uno::Reference<container::XNameAccess> xNamedRanges(xDocProps->getPropertyValue("NamedRanges"), + uno::UNO_QUERY); + // Without the fix in place, this test would have failed, we didn't ignore the problematic named + // range on import. + CPPUNIT_ASSERT(!xNamedRanges->hasByName("myname")); +} + +void ScExportTest2::testExternalDefinedNameXLSX() +{ + ScDocShellRef xShell = loadDoc(u"tdf144397.", FORMAT_XLSX); + ScDocShellRef xDocSh = saveAndReload(*xShell, FORMAT_XLSX); + CPPUNIT_ASSERT(xDocSh.is()); + + xDocSh->ReloadAllLinks(); + ScDocument& rDoc = xDocSh->GetDocument(); + rDoc.CalcAll(); + + // "January" + { + const ScFormulaCell* pFC = rDoc.GetFormulaCell(ScAddress(1, 1, 0)); + sc::FormulaResultValue aRes = pFC->GetResult(); + CPPUNIT_ASSERT_EQUAL(sc::FormulaResultValue::String, aRes.meType); + CPPUNIT_ASSERT_EQUAL(OUString("January"), aRes.maString.getString()); + } + // "March" + { + const ScFormulaCell* pFC = rDoc.GetFormulaCell(ScAddress(1, 3, 0)); + sc::FormulaResultValue aRes = pFC->GetResult(); + CPPUNIT_ASSERT_EQUAL(sc::FormulaResultValue::String, aRes.meType); + CPPUNIT_ASSERT_EQUAL(OUString("March"), aRes.maString.getString()); + } + // "Empty = #N/A" + { + const ScFormulaCell* pFC = rDoc.GetFormulaCell(ScAddress(1, 5, 0)); + sc::FormulaResultValue aRes = pFC->GetResult(); + CPPUNIT_ASSERT_EQUAL(sc::FormulaResultValue::Error, aRes.meType); + CPPUNIT_ASSERT_EQUAL(OUString(""), aRes.maString.getString()); + } + // "June" + { + const ScFormulaCell* pFC = rDoc.GetFormulaCell(ScAddress(1, 6, 0)); + sc::FormulaResultValue aRes = pFC->GetResult(); + CPPUNIT_ASSERT_EQUAL(sc::FormulaResultValue::String, aRes.meType); + CPPUNIT_ASSERT_EQUAL(OUString("June"), aRes.maString.getString()); + } + + xmlDocUniquePtr pDoc = XPathHelper::parseExport2( + *this, *xDocSh, m_xSFactory, "xl/externalLinks/externalLink1.xml", FORMAT_XLSX); + + CPPUNIT_ASSERT(pDoc); + assertXPath(pDoc, "/x:externalLink/x:externalBook/x:sheetNames/x:sheetName", "val", "Munka1"); + assertXPath(pDoc, "/x:externalLink/x:externalBook/x:definedNames/x:definedName", "name", + "MonthNames"); + // TODO: no need for the [1] external document identifier + assertXPath(pDoc, "/x:externalLink/x:externalBook/x:definedNames/x:definedName", "refersTo", + "[1]Munka1!$A$2:$A$13"); + assertXPath(pDoc, "/x:externalLink/x:externalBook/x:sheetDataSet/x:sheetData", "sheetId", "0"); + assertXPath(pDoc, "/x:externalLink/x:externalBook/x:sheetDataSet/x:sheetData/x:row[2]", "r", + "3"); + assertXPathContent( + pDoc, "/x:externalLink/x:externalBook/x:sheetDataSet/x:sheetData/x:row[2]/x:cell/x:v", + "February"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testHyperlinkLocationXLSX() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf143220.", FORMAT_ODS); + + xmlDocUniquePtr pDoc = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, + "xl/worksheets/sheet1.xml", FORMAT_XLSX); + CPPUNIT_ASSERT(pDoc); + + // tdf#143220 link to sheet not valid without cell reference + assertXPath(pDoc, "/x:worksheet/x:hyperlinks/x:hyperlink[@ref='A1']", "location", "Sheet2!A1"); + + // tdf#145079 link with defined name target didn't work because Calc added "A1" at the end + assertXPath(pDoc, "/x:worksheet/x:hyperlinks/x:hyperlink[@ref='A2']", "location", "name"); + assertXPath(pDoc, "/x:worksheet/x:hyperlinks/x:hyperlink[@ref='A3']", "location", "db"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf142264ManyChartsToXLSX() +{ + // The cache size for the test should be small enough, to make sure that some charts get + // unloaded in the process, and then loaded on demand properly (default is currently 200) + comphelper::ScopeGuard g([]() { + std::shared_ptr<comphelper::ConfigurationChanges> pBatch( + comphelper::ConfigurationChanges::create()); + officecfg::Office::Common::Cache::DrawingEngine::OLE_Objects::set(200, pBatch); + return pBatch->commit(); + }); + std::shared_ptr<comphelper::ConfigurationChanges> pBatch( + comphelper::ConfigurationChanges::create()); + officecfg::Office::Common::Cache::DrawingEngine::OLE_Objects::set(20, pBatch); + pBatch->commit(); + + ScDocShellRef xDocSh = loadDoc(u"many_charts.", FORMAT_ODS); + xDocSh = saveAndReload(*xDocSh, FORMAT_XLSX); + CPPUNIT_ASSERT(xDocSh.is()); + + auto xModel = xDocSh->GetModel(); + css::uno::Reference<css::drawing::XDrawPagesSupplier> xSupplier(xModel, + css::uno::UNO_QUERY_THROW); + auto xDrawPages = xSupplier->getDrawPages(); + + // No charts (or other objects) on the first sheet, and resp. first draw page + css::uno::Reference<css::drawing::XDrawPage> xPage(xDrawPages->getByIndex(0), + css::uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xPage->getCount()); + + // 20 charts on the second sheet, and resp. second draw page + xPage.set(xDrawPages->getByIndex(1), css::uno::UNO_QUERY_THROW); + // Without the fix in place, this test would have failed with + // - Expected: 20 + // - Actual : 0 + // Because only the last 20 charts would get exported, all on the third sheet + CPPUNIT_ASSERT_EQUAL(sal_Int32(20), xPage->getCount()); + for (sal_Int32 i = 0; i < xPage->getCount(); ++i) + { + css::uno::Reference<css::beans::XPropertySet> xProps(xPage->getByIndex(i), + css::uno::UNO_QUERY_THROW); + css::uno::Reference<css::chart2::XChartDocument> xChart(xProps->getPropertyValue("Model"), + css::uno::UNO_QUERY_THROW); + const auto xDiagram = xChart->getFirstDiagram(); + CPPUNIT_ASSERT(xDiagram); + + css::uno::Reference<css::chart2::XCoordinateSystemContainer> xCooSysContainer( + xDiagram, uno::UNO_QUERY_THROW); + + const auto xCooSysSeq = xCooSysContainer->getCoordinateSystems(); + for (const auto& rCooSys : xCooSysSeq) + { + css::uno::Reference<css::chart2::XChartTypeContainer> xChartTypeCont( + rCooSys, uno::UNO_QUERY_THROW); + uno::Sequence<uno::Reference<chart2::XChartType>> xChartTypeSeq + = xChartTypeCont->getChartTypes(); + CPPUNIT_ASSERT(xChartTypeSeq.hasElements()); + } + } + + // 20 charts on the third sheet, and resp. third draw page + xPage.set(xDrawPages->getByIndex(2), css::uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT_EQUAL(sal_Int32(20), xPage->getCount()); + for (sal_Int32 i = 0; i < xPage->getCount(); ++i) + { + css::uno::Reference<css::beans::XPropertySet> xProps(xPage->getByIndex(i), + css::uno::UNO_QUERY_THROW); + css::uno::Reference<css::chart2::XChartDocument> xChart(xProps->getPropertyValue("Model"), + css::uno::UNO_QUERY_THROW); + const auto xDiagram = xChart->getFirstDiagram(); + CPPUNIT_ASSERT(xDiagram); + + css::uno::Reference<css::chart2::XCoordinateSystemContainer> xCooSysContainer( + xDiagram, uno::UNO_QUERY_THROW); + + const auto xCooSysSeq = xCooSysContainer->getCoordinateSystems(); + for (const auto& rCooSys : xCooSysSeq) + { + css::uno::Reference<css::chart2::XChartTypeContainer> xChartTypeCont( + rCooSys, uno::UNO_QUERY_THROW); + uno::Sequence<uno::Reference<chart2::XChartType>> xChartTypeSeq + = xChartTypeCont->getChartTypes(); + CPPUNIT_ASSERT(xChartTypeSeq.hasElements()); + } + } + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf143929MultiColumnToODS() +{ + ScDocShellRef xDocSh = loadDoc(u"two-col-shape.", FORMAT_ODS); + + { + css::uno::Reference<css::drawing::XDrawPagesSupplier> xSupplier(xDocSh->GetModel(), + css::uno::UNO_QUERY_THROW); + css::uno::Reference<css::drawing::XDrawPage> xPage(xSupplier->getDrawPages()->getByIndex(0), + css::uno::UNO_QUERY_THROW); + css::uno::Reference<css::container::XIndexAccess> xIndexAccess(xPage, + css::uno::UNO_QUERY_THROW); + css::uno::Reference<css::drawing::XShape> xShape(xIndexAccess->getByIndex(0), + css::uno::UNO_QUERY_THROW); + css::uno::Reference<css::beans::XPropertySet> xProps(xShape, css::uno::UNO_QUERY_THROW); + css::uno::Reference<css::text::XTextColumns> xCols(xProps->getPropertyValue("TextColumns"), + css::uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT_EQUAL(sal_Int16(2), xCols->getColumnCount()); + css::uno::Reference<css::beans::XPropertySet> xColProps(xCols, css::uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT_EQUAL(css::uno::Any(sal_Int32(1000)), + xColProps->getPropertyValue("AutomaticDistance")); + } + + auto tempFile = exportTo(*xDocSh, FORMAT_ODS); + xDocSh = load(tempFile->GetURL(), FORMAT_ODS); + CPPUNIT_ASSERT(xDocSh); + + { + css::uno::Reference<css::drawing::XDrawPagesSupplier> xSupplier(xDocSh->GetModel(), + css::uno::UNO_QUERY_THROW); + css::uno::Reference<css::drawing::XDrawPage> xPage(xSupplier->getDrawPages()->getByIndex(0), + css::uno::UNO_QUERY_THROW); + css::uno::Reference<css::container::XIndexAccess> xIndexAccess(xPage, + css::uno::UNO_QUERY_THROW); + css::uno::Reference<css::drawing::XShape> xShape(xIndexAccess->getByIndex(0), + css::uno::UNO_QUERY_THROW); + css::uno::Reference<css::beans::XPropertySet> xProps(xShape, css::uno::UNO_QUERY_THROW); + + // Without the fix in place, this would have failed with: + // An uncaught exception of type com.sun.star.uno.RuntimeException + // - unsatisfied query for interface of type com.sun.star.text.XTextColumns! + css::uno::Reference<css::text::XTextColumns> xCols(xProps->getPropertyValue("TextColumns"), + css::uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT_EQUAL(sal_Int16(2), xCols->getColumnCount()); + css::uno::Reference<css::beans::XPropertySet> xColProps(xCols, css::uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT_EQUAL(css::uno::Any(sal_Int32(1000)), + xColProps->getPropertyValue("AutomaticDistance")); + } + + xDocSh->DoClose(); + + xmlDocUniquePtr pXmlDoc = XPathHelper::parseExport(tempFile, m_xSFactory, "content.xml"); + CPPUNIT_ASSERT(pXmlDoc); + // Without the fix in place, this would have failed with: + // - Expected: 1 + // - Actual : 0 + // - In <>, XPath '/office:document-content/office:automatic-styles/style:style[@style:family='graphic']/ + // style:graphic-properties/style:columns' number of nodes is incorrect + assertXPath( + pXmlDoc, + "/office:document-content/office:automatic-styles/style:style[@style:family='graphic']/" + "style:graphic-properties/style:columns", + "column-count", "2"); + // Only test that "column-gap" attribute exists, not its value that depends on locale (cm, in) + getXPath( + pXmlDoc, + "/office:document-content/office:automatic-styles/style:style[@style:family='graphic']/" + "style:graphic-properties/style:columns", + "column-gap"); +} + +void ScExportTest2::testTdf142578() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf142578.", FORMAT_ODS); + + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xDocSh, FORMAT_XLSX); + xmlDocUniquePtr pSheet + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/sheet1.xml"); + CPPUNIT_ASSERT(pSheet); + + // Get DxfId for color filter + sal_Int32 nDxfIdColorFilter + = getXPath(pSheet, "/x:worksheet/x:autoFilter/x:filterColumn/x:colorFilter", "dxfId") + .toInt32() + + 1; + + // Get DxfId for conditional formatting + sal_Int32 nDxfIdCondFormat + = getXPath(pSheet, "/x:worksheet/x:conditionalFormatting/x:cfRule", "dxfId").toInt32() + 1; + + // Ensure they are using different dxfs + CPPUNIT_ASSERT_MESSAGE("dxfID's should be different!", nDxfIdColorFilter != nDxfIdCondFormat); + + // Check colors used by these dxfs + xmlDocUniquePtr pStyles = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/styles.xml"); + CPPUNIT_ASSERT(pStyles); + + OString sDxfColorFilterXPath("/x:styleSheet/x:dxfs/x:dxf[" + OString::number(nDxfIdColorFilter) + + "]/x:fill/x:patternFill/x:fgColor"); + assertXPath(pStyles, sDxfColorFilterXPath, "rgb", "FF81D41A"); + + OString sDxfCondFormatXPath("/x:styleSheet/x:dxfs/x:dxf[" + OString::number(nDxfIdCondFormat) + + "]/x:fill/x:patternFill/x:bgColor"); + assertXPath(pStyles, sDxfCondFormatXPath, "rgb", "FFFFCCCC"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf145059() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf145059.", FORMAT_ODS); + + // Export to xlsx. + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xDocSh, FORMAT_XLSX); + xmlDocUniquePtr pSheet + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/sheet1.xml"); + CPPUNIT_ASSERT(pSheet); + xmlDocUniquePtr pStyle = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/styles.xml"); + CPPUNIT_ASSERT(pStyle); + + sal_Int32 nColorFilterDxdId + = getXPath(pSheet, "/x:worksheet/x:autoFilter/x:filterColumn/x:colorFilter", "dxfId") + .toInt32(); + + // Ensure that dxf id is not -1 + CPPUNIT_ASSERT(nColorFilterDxdId >= 0); + + // Find color by this dxfid + OString sDxfIdPath = "/x:styleSheet/x:dxfs/x:dxf[" + OString::number(nColorFilterDxdId + 1) + + "]/x:fill/x:patternFill/x:fgColor"; + assertXPath(pStyle, sDxfIdPath, "rgb", "FF4472C4"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf130104_XLSXIndent() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf130104_indent.", FORMAT_XLSX); + + // Resave the xlsx file without any modification. + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xDocSh, FORMAT_XLSX); + xmlDocUniquePtr pSheet + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/sheet1.xml"); + CPPUNIT_ASSERT(pSheet); + xmlDocUniquePtr pStyle = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/styles.xml"); + CPPUNIT_ASSERT(pStyle); + + // Check to see whether the indents remain the same as the original ones: + + // Get the style index number for cell A1 + sal_Int32 nCellA1StyleIndex + = getXPath(pSheet, "/x:worksheet/x:sheetData/x:row[1]/x:c[1]", "s").toInt32() + 1; + // The indent for cell A1 should be 0 + OString sStyleA1XPath + = "/x:styleSheet/x:cellXfs/x:xf[" + OString::number(nCellA1StyleIndex) + "]/x:alignment"; + // (if this assertion fails, you should first check whether there is no style index set for this cell) + assertXPath(pStyle, sStyleA1XPath, "indent", "0"); + + sal_Int32 nCellA3StyleIndex + = getXPath(pSheet, "/x:worksheet/x:sheetData/x:row[3]/x:c[1]", "s").toInt32() + 1; + // The indent for cell A3 should be 1 + OString sStyleA3XPath + = "/x:styleSheet/x:cellXfs/x:xf[" + OString::number(nCellA3StyleIndex) + "]/x:alignment"; + assertXPath(pStyle, sStyleA3XPath, "indent", "1"); + + sal_Int32 nCellA6StyleIndex + = getXPath(pSheet, "/x:worksheet/x:sheetData/x:row[6]/x:c[1]", "s").toInt32() + 1; + OString sStyleA6XPath + = "/x:styleSheet/x:cellXfs/x:xf[" + OString::number(nCellA6StyleIndex) + "]/x:alignment"; + assertXPath(pStyle, sStyleA6XPath, "indent", "2"); + + sal_Int32 nCellA9StyleIndex + = getXPath(pSheet, "/x:worksheet/x:sheetData/x:row[9]/x:c[1]", "s").toInt32() + 1; + OString sStyleA9XPath + = "/x:styleSheet/x:cellXfs/x:xf[" + OString::number(nCellA9StyleIndex) + "]/x:alignment"; + assertXPath(pStyle, sStyleA9XPath, "indent", "3"); + + sal_Int32 nCellA12StyleIndex + = getXPath(pSheet, "/x:worksheet/x:sheetData/x:row[12]/x:c[1]", "s").toInt32() + 1; + OString sStyleA12XPath + = "/x:styleSheet/x:cellXfs/x:xf[" + OString::number(nCellA12StyleIndex) + "]/x:alignment"; + assertXPath(pStyle, sStyleA12XPath, "indent", "4"); + + sal_Int32 nCellA15StyleIndex + = getXPath(pSheet, "/x:worksheet/x:sheetData/x:row[15]/x:c[1]", "s").toInt32() + 1; + OString sStyleA15XPath + = "/x:styleSheet/x:cellXfs/x:xf[" + OString::number(nCellA15StyleIndex) + "]/x:alignment"; + assertXPath(pStyle, sStyleA15XPath, "indent", "5"); + + sal_Int32 nCellA18StyleIndex + = getXPath(pSheet, "/x:worksheet/x:sheetData/x:row[18]/x:c[1]", "s").toInt32() + 1; + OString sStyleA18XPath + = "/x:styleSheet/x:cellXfs/x:xf[" + OString::number(nCellA18StyleIndex) + "]/x:alignment"; + assertXPath(pStyle, sStyleA18XPath, "indent", "6"); + + sal_Int32 nCellA21StyleIndex + = getXPath(pSheet, "/x:worksheet/x:sheetData/x:row[21]/x:c[1]", "s").toInt32() + 1; + OString sStyleA21XPath + = "/x:styleSheet/x:cellXfs/x:xf[" + OString::number(nCellA21StyleIndex) + "]/x:alignment"; + assertXPath(pStyle, sStyleA21XPath, "indent", "7"); + + sal_Int32 nCellA24StyleIndex + = getXPath(pSheet, "/x:worksheet/x:sheetData/x:row[24]/x:c[1]", "s").toInt32() + 1; + OString sStyleA24XPath + = "/x:styleSheet/x:cellXfs/x:xf[" + OString::number(nCellA24StyleIndex) + "]/x:alignment"; + assertXPath(pStyle, sStyleA24XPath, "indent", "8"); + + sal_Int32 nCellA27StyleIndex + = getXPath(pSheet, "/x:worksheet/x:sheetData/x:row[27]/x:c[1]", "s").toInt32() + 1; + OString sStyleA27XPath + = "/x:styleSheet/x:cellXfs/x:xf[" + OString::number(nCellA27StyleIndex) + "]/x:alignment"; + assertXPath(pStyle, sStyleA27XPath, "indent", "9"); + + sal_Int32 nCellA30StyleIndex + = getXPath(pSheet, "/x:worksheet/x:sheetData/x:row[30]/x:c[1]", "s").toInt32() + 1; + OString sStyleA30XPath + = "/x:styleSheet/x:cellXfs/x:xf[" + OString::number(nCellA30StyleIndex) + "]/x:alignment"; + assertXPath(pStyle, sStyleA30XPath, "indent", "10"); + + xDocSh->DoClose(); +} + +void ScExportTest2::testWholeRowBold() +{ + ScDocShellRef xDocSh1 = loadDoc(u"blank.", FORMAT_ODS); + ScDocument* pDoc = &xDocSh1->GetDocument(); + + // Make entire second row bold. + ScPatternAttr boldAttr(pDoc->GetPool()); + boldAttr.GetItemSet().Put(SvxWeightItem(WEIGHT_BOLD, ATTR_FONT_WEIGHT)); + pDoc->ApplyPatternAreaTab(0, 1, pDoc->MaxCol(), 1, 0, boldAttr); + + ScDocShellRef xDocSh2 = saveAndReload(*xDocSh1, FORMAT_ODS); + CPPUNIT_ASSERT(xDocSh2.is()); + pDoc = &xDocSh2->GetDocument(); + CPPUNIT_ASSERT_EQUAL(SCCOL(INITIALCOLCOUNT), pDoc->GetAllocatedColumnsCount(0)); + vcl::Font aFont; + pDoc->GetPattern(pDoc->MaxCol(), 1, 0)->GetFont(aFont, SC_AUTOCOL_RAW); + CPPUNIT_ASSERT_EQUAL_MESSAGE("font should be bold", WEIGHT_BOLD, aFont.GetWeight()); + + ScDocShellRef xDocSh3 = saveAndReload(*xDocSh2, FORMAT_XLSX); + CPPUNIT_ASSERT(xDocSh3.is()); + pDoc = &xDocSh3->GetDocument(); + CPPUNIT_ASSERT_EQUAL(SCCOL(INITIALCOLCOUNT), pDoc->GetAllocatedColumnsCount(0)); + pDoc->GetPattern(pDoc->MaxCol(), 1, 0)->GetFont(aFont, SC_AUTOCOL_RAW); + CPPUNIT_ASSERT_EQUAL_MESSAGE("font should be bold", WEIGHT_BOLD, aFont.GetWeight()); + + xDocSh1->DoClose(); + xDocSh2->DoClose(); + xDocSh3->DoClose(); +} + +void ScExportTest2::testXlsxRowsOrder() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf58243.", FORMAT_XLSX); + // Make sure code in SheetDataBuffer doesn't assert columns/rows sorting. + ScBootstrapFixture::exportTo(*xDocSh, FORMAT_XLSX); + xDocSh->DoClose(); +} + +void ScExportTest2::testTdf91286() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf91286.", FORMAT_ODS); + std::shared_ptr<utl::TempFile> pTemp = exportTo(*xDocSh, FORMAT_XLSX); + xDocSh->DoClose(); + + Reference<packages::zip::XZipFileAccess2> xNameAccess + = packages::zip::ZipFileAccess::createWithURL(comphelper::getComponentContext(m_xSFactory), + pTemp->GetURL()); + const Sequence<OUString> aNames(xNameAccess->getElementNames()); + int nImageFiles = 0; + for (const auto& rElementName : aNames) + if (rElementName.startsWith("xl/media/image")) + nImageFiles++; + + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 1 + // - Actual : 2 + // i.e. the embedded picture would have been saved twice. + CPPUNIT_ASSERT_EQUAL(1, nImageFiles); +} + +void ScExportTest2::testTdf148820() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf148820.", FORMAT_XLSX); + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xDocSh, FORMAT_XLSX); + xmlDocUniquePtr pSheet + = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/sheet1.xml"); + CPPUNIT_ASSERT(pSheet); + + sal_Int32 nDxfIdCondFormatFirst + = getXPath(pSheet, "/x:worksheet/x:conditionalFormatting[1]/x:cfRule", "dxfId").toInt32() + + 1; + sal_Int32 nDxfIdCondFormatLast + = getXPath(pSheet, "/x:worksheet/x:conditionalFormatting[20]/x:cfRule", "dxfId").toInt32() + + 1; + + xmlDocUniquePtr pStyles = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/styles.xml"); + CPPUNIT_ASSERT(pStyles); + + OString sDxfCondFormatXPath("/x:styleSheet/x:dxfs/x:dxf[" + + OString::number(nDxfIdCondFormatFirst) + + "]/x:fill/x:patternFill/x:bgColor"); + assertXPath(pStyles, sDxfCondFormatXPath, "rgb", "FF53B5A9"); + sDxfCondFormatXPath + = OString("/x:styleSheet/x:dxfs/x:dxf[" + OString::number(nDxfIdCondFormatLast) + + "]/x:fill/x:patternFill/x:bgColor"); + assertXPath(pStyles, sDxfCondFormatXPath, "rgb", "FFA30000"); + + xDocSh->DoClose(); +} + +namespace +{ +void lcl_TestEmbeddedTextInDecimal(ScDocShellRef xDocSh) +{ + CPPUNIT_ASSERT(xDocSh); + ScDocument& rDoc = xDocSh->GetDocument(); + sal_uInt32 nNumberFormat = rDoc.GetNumberFormat(0, 0, 0); + const SvNumberformat* pNumberFormat = rDoc.GetFormatTable()->GetEntry(nNumberFormat); + const OUString& rFormatStr = pNumberFormat->GetFormatstring(); + + CPPUNIT_ASSERT_EQUAL(OUString("#,##0.000\" \"###\" \"###"), rFormatStr); +} +} + +void ScExportTest2::testEmbeddedTextInDecimal() +{ + ScDocShellRef xDocSh = loadDoc(u"embedded-text-in-decimal.", FORMAT_XLSX); + lcl_TestEmbeddedTextInDecimal(xDocSh); + + // save to ODS and reload + xDocSh = saveAndReload(*xDocSh, FORMAT_ODS); + lcl_TestEmbeddedTextInDecimal(xDocSh); + + xDocSh->DoClose(); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(ScExportTest2); + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |