diff options
author | Xisco Fauli <xiscofauli@libreoffice.org> | 2023-02-28 16:54:04 +0100 |
---|---|---|
committer | Xisco Fauli <xiscofauli@libreoffice.org> | 2023-03-01 07:47:22 +0000 |
commit | 36cd611e6ff709b3e3645b67ea67ee26cf3d92fc (patch) | |
tree | 134d87c4a64611bb318bd5ba4e9feace790defd5 | |
parent | 5f19b56886db4a99155336f4c467e6ff75339c34 (diff) |
CppunitTest_sc_subsequent_export_test: split in two
it already has 101 tests
Change-Id: I2fb88e41313049fec649e3592d811a36e10440fc
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/148013
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
-rw-r--r-- | sc/CppunitTest_sc_subsequent_export_test3.mk | 12 | ||||
-rw-r--r-- | sc/Module_sc.mk | 1 | ||||
-rw-r--r-- | sc/qa/unit/subsequent_export_test.cxx | 1893 | ||||
-rw-r--r-- | sc/qa/unit/subsequent_export_test3.cxx | 1940 |
4 files changed, 1954 insertions, 1892 deletions
diff --git a/sc/CppunitTest_sc_subsequent_export_test3.mk b/sc/CppunitTest_sc_subsequent_export_test3.mk new file mode 100644 index 000000000000..b46937445470 --- /dev/null +++ b/sc/CppunitTest_sc_subsequent_export_test3.mk @@ -0,0 +1,12 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# 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/. +# + +$(eval $(call sc_subsequent_test,export_test3)) + +# vim: set noet sw=4 ts=4: diff --git a/sc/Module_sc.mk b/sc/Module_sc.mk index ffbe0dafb6c4..c9344df52566 100644 --- a/sc/Module_sc.mk +++ b/sc/Module_sc.mk @@ -87,6 +87,7 @@ $(eval $(call gb_Module_add_slowcheck_targets,sc, \ CppunitTest_sc_subsequent_filters_test3 \ CppunitTest_sc_subsequent_export_test \ CppunitTest_sc_subsequent_export_test2 \ + CppunitTest_sc_subsequent_export_test3 \ CppunitTest_sc_uicalc \ CppunitTest_sc_vba_macro_test \ CppunitTest_sc_a11y \ diff --git a/sc/qa/unit/subsequent_export_test.cxx b/sc/qa/unit/subsequent_export_test.cxx index 0a5e0eddf970..e335211192f5 100644 --- a/sc/qa/unit/subsequent_export_test.cxx +++ b/sc/qa/unit/subsequent_export_test.cxx @@ -17,21 +17,16 @@ #include <userdat.hxx> #include <docpool.hxx> +#include <cellvalue.hxx> #include <scitems.hxx> #include <attrib.hxx> #include <stlpool.hxx> #include <editutil.hxx> #include <scopetools.hxx> #include <postit.hxx> -#include <tokenstringcontext.hxx> -#include <chgtrack.hxx> #include <validat.hxx> -#include <scmod.hxx> #include <svx/svdpage.hxx> -#include <svx/svdograf.hxx> -#include <svl/zformat.hxx> -#include <svl/numformat.hxx> #include <tabprotection.hxx> #include <editeng/wghtitem.hxx> #include <editeng/postitem.hxx> @@ -44,13 +39,6 @@ #include <editeng/fhgtitem.hxx> #include <editeng/udlnitem.hxx> #include <editeng/colritem.hxx> -#include <unotools/tempfile.hxx> -#include <unotools/useroptions.hxx> -#include <tools/datetime.hxx> - -#include <com/sun/star/drawing/XDrawPageSupplier.hpp> -#include <com/sun/star/awt/XBitmap.hpp> -#include <com/sun/star/graphic/GraphicType.hpp> using namespace ::com::sun::star; using namespace ::com::sun::star::uno; @@ -60,8 +48,6 @@ class ScExportTest : public ScModelTestBase protected: virtual void registerNamespaces(xmlXPathContextPtr& pXmlXPathCtx) override; - void testFunctionsExcel2010(const OUString& sFormatType); - void testCeilingFloor(const OUString& sFormatType); void testExcelCellBorders(const OUString& sFormatType); public: @@ -2239,1883 +2225,6 @@ CPPUNIT_TEST_FIXTURE(ScExportTest, testCellBordersXLSX) testExcelCellBorders("Calc Office Open XML"); } -CPPUNIT_TEST_FIXTURE(ScExportTest, testBordersExchangeXLSX) -{ - // Document: sc/qa/unit/data/README.cellborders - - // short name for the table - const SvxBorderLineStyle None = SvxBorderLineStyle::NONE; - const SvxBorderLineStyle Solid = SvxBorderLineStyle::SOLID; - const SvxBorderLineStyle Dotted = SvxBorderLineStyle::DOTTED; - const SvxBorderLineStyle Dashed = SvxBorderLineStyle::DASHED; - const SvxBorderLineStyle FineDash = SvxBorderLineStyle::FINE_DASHED; - const SvxBorderLineStyle DashDot = SvxBorderLineStyle::DASH_DOT; - const SvxBorderLineStyle DashDoDo = SvxBorderLineStyle::DASH_DOT_DOT; - const SvxBorderLineStyle DoubThin = SvxBorderLineStyle::DOUBLE_THIN; - - const size_t nMaxCol = 18; - const size_t nMaxRow = 7; - - static struct - { - SvxBorderLineStyle BorderStyleTop, BorderStyleBottom; - tools::Long WidthTop, WidthBottom; - } aCheckBorderWidth[nMaxCol][nMaxRow] - = { /* Width */ - /* 0,05 */ { { Solid, Solid, 1, 1 }, // SOLID - { Dotted, Dotted, 15, 15 }, // DOTTED - { Dotted, Dotted, 15, 15 }, // DASHED - { FineDash, FineDash, 15, 15 }, // FINE_DASHED - { FineDash, FineDash, 15, 15 }, // DASH_DOT - { FineDash, FineDash, 15, 15 }, // DASH_DOT_DOT - { None, None, 0, 0 } }, // DOUBLE_THIN - /* 0,25 */ - { { Solid, Solid, 1, 1 }, - { Dotted, Dotted, 15, 15 }, - { Dotted, Dotted, 15, 15 }, - { FineDash, FineDash, 15, 15 }, - { FineDash, FineDash, 15, 15 }, - { FineDash, FineDash, 15, 15 }, - { None, None, 0, 0 } }, - /* 0,50 */ - { { Solid, Solid, 1, 1 }, - { Dotted, Dotted, 15, 15 }, - { Dotted, Dotted, 15, 15 }, - { FineDash, FineDash, 15, 15 }, - { FineDash, FineDash, 15, 15 }, - { FineDash, FineDash, 15, 15 }, - { None, None, 0, 0 } }, - /* 0,75 */ - { { Solid, Solid, 15, 15 }, - { Dotted, Dotted, 15, 15 }, - { FineDash, FineDash, 15, 15 }, - { FineDash, FineDash, 15, 15 }, - { DashDot, DashDot, 15, 15 }, - { DashDoDo, DashDoDo, 15, 15 }, - { DoubThin, DoubThin, 35, 35 } }, - /* 1,00 */ - { { Solid, Solid, 15, 15 }, - { Dotted, Dotted, 15, 15 }, - { FineDash, FineDash, 15, 15 }, - { FineDash, FineDash, 15, 15 }, - { DashDot, DashDot, 15, 15 }, - { DashDoDo, DashDoDo, 15, 15 }, - { DoubThin, DoubThin, 35, 35 } }, - /* 1,25 */ - { { Solid, Solid, 15, 15 }, - { Dotted, Dotted, 15, 15 }, - { FineDash, FineDash, 15, 15 }, - { FineDash, FineDash, 15, 15 }, - { DashDot, DashDot, 15, 15 }, - { DashDoDo, DashDoDo, 15, 15 }, - { DoubThin, DoubThin, 35, 35 } }, - /* 1,50 */ - { { Solid, Solid, 15, 15 }, - { Dotted, Dotted, 15, 15 }, - { FineDash, FineDash, 15, 15 }, - { FineDash, FineDash, 15, 15 }, - { DashDot, DashDot, 15, 15 }, - { DashDoDo, DashDoDo, 15, 15 }, - { DoubThin, DoubThin, 35, 35 } }, - - /* 1,75 */ - { { Solid, Solid, 35, 35 }, - { FineDash, FineDash, 35, 35 }, - { Dashed, Dashed, 35, 35 }, - { FineDash, FineDash, 35, 35 }, - { DashDot, DashDot, 35, 35 }, - { DashDoDo, DashDoDo, 35, 35 }, - { DoubThin, DoubThin, 35, 35 } }, - /* 2,00 */ - { { Solid, Solid, 35, 35 }, - { FineDash, FineDash, 35, 35 }, - { Dashed, Dashed, 35, 35 }, - { FineDash, FineDash, 35, 35 }, - { DashDot, DashDot, 35, 35 }, - { DashDoDo, DashDoDo, 35, 35 }, - { DoubThin, DoubThin, 35, 35 } }, - /* 2,25 */ - { { Solid, Solid, 35, 35 }, - { FineDash, FineDash, 35, 35 }, - { Dashed, Dashed, 35, 35 }, - { FineDash, FineDash, 35, 35 }, - { DashDot, DashDot, 35, 35 }, - { DashDoDo, DashDoDo, 35, 35 }, - { DoubThin, DoubThin, 35, 35 } }, - - /* 2,50 */ - { { Solid, Solid, 50, 50 }, - { FineDash, FineDash, 35, 35 }, - { Dashed, Dashed, 35, 35 }, - { FineDash, FineDash, 35, 35 }, - { DashDot, DashDot, 35, 35 }, - { DashDoDo, DashDoDo, 35, 35 }, - { DoubThin, DoubThin, 35, 35 } }, - /* 2,75 */ - { { Solid, Solid, 50, 50 }, - { FineDash, FineDash, 35, 35 }, - { Dashed, Dashed, 35, 35 }, - { FineDash, FineDash, 35, 35 }, - { DashDot, DashDot, 35, 35 }, - { DashDoDo, DashDoDo, 35, 35 }, - { DoubThin, DoubThin, 35, 35 } }, - /* 3,00 */ - { { Solid, Solid, 50, 50 }, - { FineDash, FineDash, 35, 35 }, - { Dashed, Dashed, 35, 35 }, - { FineDash, FineDash, 35, 35 }, - { DashDot, DashDot, 35, 35 }, - { DashDoDo, DashDoDo, 35, 35 }, - { DoubThin, DoubThin, 35, 35 } }, - /* 3,50 */ - { { Solid, Solid, 50, 50 }, - { FineDash, FineDash, 35, 35 }, - { Dashed, Dashed, 35, 35 }, - { FineDash, FineDash, 35, 35 }, - { DashDot, DashDot, 35, 35 }, - { DashDoDo, DashDoDo, 35, 35 }, - { DoubThin, DoubThin, 35, 35 } }, - /* 4,00 */ - { { Solid, Solid, 50, 50 }, - { FineDash, FineDash, 35, 35 }, - { Dashed, Dashed, 35, 35 }, - { FineDash, FineDash, 35, 35 }, - { DashDot, DashDot, 35, 35 }, - { DashDoDo, DashDoDo, 35, 35 }, - { DoubThin, DoubThin, 35, 35 } }, - /* 5,00 */ - { { Solid, Solid, 50, 50 }, - { FineDash, FineDash, 35, 35 }, - { Dashed, Dashed, 35, 35 }, - { FineDash, FineDash, 35, 35 }, - { DashDot, DashDot, 35, 35 }, - { DashDoDo, DashDoDo, 35, 35 }, - { DoubThin, DoubThin, 35, 35 } }, - /* 7,00 */ - { { Solid, Solid, 50, 50 }, - { FineDash, FineDash, 35, 35 }, - { Dashed, Dashed, 35, 35 }, - { FineDash, FineDash, 35, 35 }, - { DashDot, DashDot, 35, 35 }, - { DashDoDo, DashDoDo, 35, 35 }, - { DoubThin, DoubThin, 35, 35 } }, - /* 9,00 */ - { { Solid, Solid, 50, 50 }, - { FineDash, FineDash, 35, 35 }, - { Dashed, Dashed, 35, 35 }, - { FineDash, FineDash, 35, 35 }, - { DashDot, DashDot, 35, 35 }, - { DashDoDo, DashDoDo, 35, 35 }, - { DoubThin, DoubThin, 35, 35 } } - }; - - createScDoc("ods/test_borders_export.ods"); - - saveAndReload("Calc Office Open XML"); - ScDocument* pDoc = getScDoc(); - - for (size_t nCol = 0; nCol < nMaxCol; ++nCol) - { - for (size_t nRow = 0; nRow < nMaxRow; ++nRow) - { - const editeng::SvxBorderLine* pLineTop = nullptr; - const editeng::SvxBorderLine* pLineBottom = nullptr; - pDoc->GetBorderLines(nCol + 2, (nRow * 2) + 8, 0, nullptr, &pLineTop, nullptr, - &pLineBottom); - if ((nCol < 3) && (nRow == 6)) - { // in this range no lines since minimum size to create a double is 0.5 - CPPUNIT_ASSERT(!pLineTop); - CPPUNIT_ASSERT(!pLineBottom); - continue; - } - else - { - CPPUNIT_ASSERT(pLineTop); - CPPUNIT_ASSERT(pLineBottom); - } - - CPPUNIT_ASSERT_EQUAL_MESSAGE("Top Border-Line-Style wrong", - aCheckBorderWidth[nCol][nRow].BorderStyleTop, - pLineTop->GetBorderLineStyle()); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Bottom Border-Line-Style wrong", - aCheckBorderWidth[nCol][nRow].BorderStyleBottom, - pLineBottom->GetBorderLineStyle()); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Top Width-Line wrong", - aCheckBorderWidth[nCol][nRow].WidthTop, - pLineTop->GetWidth()); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Bottom Width-Line wrong", - aCheckBorderWidth[nCol][nRow].WidthBottom, - pLineBottom->GetWidth()); - } - } -} - -static OUString toString(const ScBigRange& rRange) -{ - OUStringBuffer aBuf; - aBuf.append("(columns:"); - aBuf.append(rRange.aStart.Col()); - aBuf.append('-'); - aBuf.append(rRange.aEnd.Col()); - aBuf.append(";rows:"); - aBuf.append(rRange.aStart.Row()); - aBuf.append('-'); - aBuf.append(rRange.aEnd.Row()); - aBuf.append(";sheets:"); - aBuf.append(rRange.aStart.Tab()); - aBuf.append('-'); - aBuf.append(rRange.aEnd.Tab()); - aBuf.append(')'); - - return aBuf.makeStringAndClear(); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testTrackChangesSimpleXLSX) -{ - struct CheckItem - { - sal_uLong mnActionId; - ScChangeActionType meType; - - sal_Int32 mnStartCol; - sal_Int32 mnStartRow; - sal_Int32 mnStartTab; - sal_Int32 mnEndCol; - sal_Int32 mnEndRow; - sal_Int32 mnEndTab; - - bool mbRowInsertedAtBottom; - }; - - struct - { - bool checkRange(ScChangeActionType eType, const ScBigRange& rExpected, - const ScBigRange& rActual) - { - ScBigRange aExpected(rExpected), aActual(rActual); - - switch (eType) - { - case SC_CAT_INSERT_ROWS: - { - // Ignore columns. - aExpected.aStart.SetCol(0); - aExpected.aEnd.SetCol(0); - aActual.aStart.SetCol(0); - aActual.aEnd.SetCol(0); - } - break; - default:; - } - - return aExpected == aActual; - } - - bool check(ScDocument& rDoc) - { - static const CheckItem aChecks[] = { - { 1, SC_CAT_CONTENT, 1, 1, 0, 1, 1, 0, false }, - { 2, SC_CAT_INSERT_ROWS, 0, 2, 0, 0, 2, 0, true }, - { 3, SC_CAT_CONTENT, 1, 2, 0, 1, 2, 0, false }, - { 4, SC_CAT_INSERT_ROWS, 0, 3, 0, 0, 3, 0, true }, - { 5, SC_CAT_CONTENT, 1, 3, 0, 1, 3, 0, false }, - { 6, SC_CAT_INSERT_ROWS, 0, 4, 0, 0, 4, 0, true }, - { 7, SC_CAT_CONTENT, 1, 4, 0, 1, 4, 0, false }, - { 8, SC_CAT_INSERT_ROWS, 0, 5, 0, 0, 5, 0, true }, - { 9, SC_CAT_CONTENT, 1, 5, 0, 1, 5, 0, false }, - { 10, SC_CAT_INSERT_ROWS, 0, 6, 0, 0, 6, 0, true }, - { 11, SC_CAT_CONTENT, 1, 6, 0, 1, 6, 0, false }, - { 12, SC_CAT_INSERT_ROWS, 0, 7, 0, 0, 7, 0, true }, - { 13, SC_CAT_CONTENT, 1, 7, 0, 1, 7, 0, false }, - }; - - ScChangeTrack* pCT = rDoc.GetChangeTrack(); - if (!pCT) - { - cerr << "Change track instance doesn't exist." << endl; - return false; - } - - sal_uLong nActionMax = pCT->GetActionMax(); - if (nActionMax != 13) - { - cerr << "Unexpected highest action ID value." << endl; - return false; - } - - for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i) - { - sal_uInt16 nActId = aChecks[i].mnActionId; - const ScChangeAction* pAction = pCT->GetAction(nActId); - if (!pAction) - { - cerr << "No action for action number " << nActId << " found." << endl; - return false; - } - - if (pAction->GetType() != aChecks[i].meType) - { - cerr << "Unexpected action type for action number " << nActId << "." << endl; - return false; - } - - const ScBigRange& rRange = pAction->GetBigRange(); - ScBigRange aCheck(aChecks[i].mnStartCol, aChecks[i].mnStartRow, - aChecks[i].mnStartTab, aChecks[i].mnEndCol, aChecks[i].mnEndRow, - aChecks[i].mnEndTab); - - if (!checkRange(pAction->GetType(), aCheck, rRange)) - { - cerr << "Unexpected range for action number " << nActId - << ": expected=" << toString(aCheck) << " actual=" << toString(rRange) - << endl; - return false; - } - - switch (pAction->GetType()) - { - case SC_CAT_INSERT_ROWS: - { - const ScChangeActionIns* p = static_cast<const ScChangeActionIns*>(pAction); - if (p->IsEndOfList() != aChecks[i].mbRowInsertedAtBottom) - { - cerr << "Unexpected end-of-list flag for action number " << nActId - << "." << endl; - return false; - } - } - break; - default:; - } - } - - return true; - } - - bool checkRevisionUserAndTime(ScDocument& rDoc, std::u16string_view rOwnerName) - { - ScChangeTrack* pCT = rDoc.GetChangeTrack(); - if (!pCT) - { - cerr << "Change track instance doesn't exist." << endl; - return false; - } - - ScChangeAction* pAction = pCT->GetLast(); - if (pAction->GetUser() != "Kohei Yoshida") - { - cerr << "Wrong user name." << endl; - return false; - } - - DateTime aDT = pAction->GetDateTime(); - if (aDT.GetYear() != 2014 || aDT.GetMonth() != 7 || aDT.GetDay() != 11) - { - cerr << "Wrong time stamp." << endl; - return false; - } - - // Insert a new record to make sure the user and date-time are correct. - rDoc.SetString(ScAddress(1, 8, 0), "New String"); - ScCellValue aEmpty; - pCT->AppendContent(ScAddress(1, 8, 0), aEmpty); - pAction = pCT->GetLast(); - if (!pAction) - { - cerr << "Failed to retrieve last revision." << endl; - return false; - } - - if (rOwnerName != pAction->GetUser()) - { - cerr << "Wrong user name." << endl; - return false; - } - - DateTime aDTNew = pAction->GetDateTime(); - if (aDTNew <= aDT) - { - cerr << "Time stamp of the new revision should be more recent than that of the " - "last revision." - << endl; - return false; - } - - return true; - } - - } aTest; - - SvtUserOptions& rUserOpt = SC_MOD()->GetUserOptions(); - rUserOpt.SetToken(UserOptToken::FirstName, "Export"); - rUserOpt.SetToken(UserOptToken::LastName, "Test"); - - OUString aOwnerName = rUserOpt.GetFirstName() + " " + rUserOpt.GetLastName(); - - // First, test the xls variant. - - createScDoc("xls/track-changes/simple-cell-changes.xls"); - ScDocument* pDoc = getScDoc(); - bool bGood = aTest.check(*pDoc); - CPPUNIT_ASSERT_MESSAGE("Initial check failed (xls).", bGood); - - saveAndReload("MS Excel 97"); - pDoc = getScDoc(); - bGood = aTest.check(*pDoc); - CPPUNIT_ASSERT_MESSAGE("Check after reload failed (xls).", bGood); - - // fdo#81445 : Check the blank value string to make sure it's "<empty>". - ScChangeTrack* pCT = pDoc->GetChangeTrack(); - CPPUNIT_ASSERT(pCT); - ScChangeAction* pAction = pCT->GetAction(1); - CPPUNIT_ASSERT(pAction); - OUString aDesc = pAction->GetDescription(*pDoc); - CPPUNIT_ASSERT_EQUAL(OUString("Cell B2 changed from '<empty>' to '1'"), aDesc); - - pDoc = getScDoc(); - bGood = aTest.checkRevisionUserAndTime(*pDoc, aOwnerName); - CPPUNIT_ASSERT_MESSAGE("Check revision and time failed after reload (xls).", bGood); - - // Now, test the xlsx variant the same way. - - createScDoc("xlsx/track-changes/simple-cell-changes.xlsx"); - pDoc = getScDoc(); - aTest.check(*pDoc); - CPPUNIT_ASSERT_MESSAGE("Initial check failed (xlsx).", bGood); - - saveAndReload("Calc Office Open XML"); - pDoc = getScDoc(); - bGood = aTest.check(*pDoc); - CPPUNIT_ASSERT_MESSAGE("Check after reload failed (xlsx).", bGood); - - bGood = aTest.checkRevisionUserAndTime(*pDoc, aOwnerName); - CPPUNIT_ASSERT_MESSAGE("Check revision and time failed after reload (xlsx).", bGood); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testSheetTabColorsXLSX) -{ - struct - { - bool checkContent(ScDocument& rDoc) - { - std::vector<OUString> aTabNames = rDoc.GetAllTableNames(); - - // green, red, blue, yellow (from left to right). - if (aTabNames.size() != 4) - { - cerr << "There should be exactly 4 sheets." << endl; - return false; - } - - const char* pNames[] = { "Green", "Red", "Blue", "Yellow" }; - for (size_t i = 0; i < SAL_N_ELEMENTS(pNames); ++i) - { - OUString aExpected = OUString::createFromAscii(pNames[i]); - if (aExpected != aTabNames[i]) - { - cerr << "incorrect sheet name: expected='" << aExpected << "', actual='" - << aTabNames[i] << "'" << endl; - return false; - } - } - - static const Color aXclColors[] = { - 0x0000B050, // green - 0x00FF0000, // red - 0x000070C0, // blue - 0x00FFFF00, // yellow - }; - - for (size_t i = 0; i < SAL_N_ELEMENTS(aXclColors); ++i) - { - if (aXclColors[i] != rDoc.GetTabBgColor(i)) - { - cerr << "wrong sheet color for sheet " << i << endl; - return false; - } - } - - return true; - } - - } aTest; - - createScDoc("xlsx/sheet-tab-color.xlsx"); - { - ScDocument* pDoc = getScDoc(); - bool bRes = aTest.checkContent(*pDoc); - CPPUNIT_ASSERT_MESSAGE("Failed on the initial content check.", bRes); - } - - saveAndReload("Calc Office Open XML"); - ScDocument* pDoc = getScDoc(); - bool bRes = aTest.checkContent(*pDoc); - CPPUNIT_ASSERT_MESSAGE("Failed on the content check after reload.", bRes); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testTdf133487) -{ - createScDoc("fods/shapes_foreground_background.fods"); - - save("calc8"); - xmlDocUniquePtr pXmlDoc = parseExport("content.xml"); - CPPUNIT_ASSERT(pXmlDoc); - - // shape in background has lowest index - assertXPath(pXmlDoc, - "/office:document-content/office:body/office:spreadsheet/table:table[1]/" - "table:table-row[1]/table:table-cell[1]/draw:custom-shape", - "z-index", "0"); - assertXPath(pXmlDoc, - "/office:document-content/office:body/office:spreadsheet/table:table[1]/" - "table:table-row[1]/table:table-cell[1]/draw:custom-shape" - "/attribute::table:table-background", - 1); - assertXPath(pXmlDoc, - "/office:document-content/office:body/office:spreadsheet/table:table[1]/" - "table:table-row[1]/table:table-cell[1]/draw:custom-shape", - "table-background", "true"); - // shape in foreground, previously index 1 - assertXPath(pXmlDoc, - "/office:document-content/office:body/office:spreadsheet/table:table[1]/" - "table:table-row[1]/table:table-cell[2]/draw:custom-shape", - "z-index", "2"); - // attribute is only written for value "true" - assertXPath(pXmlDoc, - "/office:document-content/office:body/office:spreadsheet/table:table[1]/" - "table:table-row[1]/table:table-cell[2]/draw:custom-shape" - "/attribute::table:table-background", - 0); - // shape in foreground, previously index 0 - assertXPath(pXmlDoc, - "/office:document-content/office:body/office:spreadsheet/table:table[1]/" - "table:table-row[3]/table:table-cell[1]/draw:custom-shape", - "z-index", "1"); - // attribute is only written for value "true" - assertXPath(pXmlDoc, - "/office:document-content/office:body/office:spreadsheet/table:table[1]/" - "table:table-row[3]/table:table-cell[1]/draw:custom-shape" - "/attribute::table:table-background", - 0); - // shape in foreground, previously index 4 - assertXPath(pXmlDoc, - "/office:document-content/office:body/office:spreadsheet/table:table[1]/" - "table:shapes/draw:custom-shape", - "z-index", "3"); - // attribute is only written for value "true" - assertXPath(pXmlDoc, - "/office:document-content/office:body/office:spreadsheet/table:table[1]/" - "table:shapes/draw:custom-shape" - "/attribute::table:table-background", - 0); - // form control, previously index 3 - assertXPath(pXmlDoc, - "/office:document-content/office:body/office:spreadsheet/table:table[1]/" - "table:shapes/draw:control", - "z-index", "4"); - // attribute is only written for value "true" - assertXPath(pXmlDoc, - "/office:document-content/office:body/office:spreadsheet/table:table[1]/" - "table:shapes/draw:control" - "/attribute::table:table-background", - 0); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testSharedFormulaExportXLS) -{ - struct - { - bool checkContent(ScDocument& rDoc) - { - formula::FormulaGrammar::Grammar eGram = formula::FormulaGrammar::GRAM_ENGLISH_XL_R1C1; - FormulaGrammarSwitch aFGSwitch(&rDoc, eGram); - sc::TokenStringContext aCxt(rDoc, eGram); - - // Check the title row. - - OUString aActual = rDoc.GetString(0, 1, 0); - OUString aExpected = "Response"; - if (aActual != aExpected) - { - cerr << "Wrong content in A2: expected='" << aExpected << "', actual='" << aActual - << "'" << endl; - return false; - } - - aActual = rDoc.GetString(1, 1, 0); - aExpected = "Response"; - if (aActual != aExpected) - { - cerr << "Wrong content in B2: expected='" << aExpected << "', actual='" << aActual - << "'" << endl; - return false; - } - - // A3:A12 and B3:B12 are numbers from 1 to 10. - for (SCROW i = 0; i <= 9; ++i) - { - double fExpected = i + 1.0; - ScAddress aPos(0, i + 2, 0); - double fActual = rDoc.GetValue(aPos); - if (fExpected != fActual) - { - cerr << "Wrong value in A" << (i + 2) << ": expected=" << fExpected - << ", actual=" << fActual << endl; - return false; - } - - aPos.IncCol(); - ScFormulaCell* pFC = rDoc.GetFormulaCell(aPos); - if (!pFC) - { - cerr << "B" << (i + 2) << " should be a formula cell." << endl; - return false; - } - - OUString aFormula = pFC->GetCode()->CreateString(aCxt, aPos); - aExpected = "Coefficients!RC[-1]"; - if (aFormula != aExpected) - { - cerr << "Wrong formula in B" << (i + 2) << ": expected='" << aExpected - << "', actual='" << aFormula << "'" << endl; - return false; - } - - fActual = rDoc.GetValue(aPos); - if (fExpected != fActual) - { - cerr << "Wrong value in B" << (i + 2) << ": expected=" << fExpected - << ", actual=" << fActual << endl; - return false; - } - } - - return true; - } - - } aTest; - - createScDoc("ods/shared-formula/3d-reference.ods"); - { - // Check the content of the original. - ScDocument* pDoc = getScDoc(); - bool bRes = aTest.checkContent(*pDoc); - CPPUNIT_ASSERT_MESSAGE("Content check on the original document failed.", bRes); - } - - saveAndReload("MS Excel 97"); - - // Check the content of the reloaded. This should be identical. - ScDocument* pDoc = getScDoc(); - bool bRes = aTest.checkContent(*pDoc); - CPPUNIT_ASSERT_MESSAGE("Content check on the reloaded document failed.", bRes); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testSharedFormulaExportXLSX) -{ - struct - { - bool checkContent(ScDocument& rDoc) - { - SCTAB nTabCount = rDoc.GetTableCount(); - if (nTabCount != 2) - { - cerr << "Document should have exactly 2 sheets. " << nTabCount << " found." - << endl; - return false; - } - - // Make sure the sheet tab colors are not set. - for (SCROW i = 0; i <= 1; ++i) - { - Color aTabBgColor = rDoc.GetTabBgColor(i); - if (aTabBgColor != COL_AUTO) - { - cerr << "The tab color of Sheet " << (i + 1) << " should not be explicitly set." - << endl; - return false; - } - } - - // B2:B7 should show 1,2,3,4,5,6. - double fExpected = 1.0; - for (SCROW i = 1; i <= 6; ++i, ++fExpected) - { - ScAddress aPos(1, i, 0); - double fVal = rDoc.GetValue(aPos); - if (fVal != fExpected) - { - cerr << "Wrong value in B" << (i + 1) << ": expected=" << fExpected - << ", actual=" << fVal << endl; - return false; - } - } - - // C2:C7 should show 10,20,...,60. - fExpected = 10.0; - for (SCROW i = 1; i <= 6; ++i, fExpected += 10.0) - { - ScAddress aPos(2, i, 0); - double fVal = rDoc.GetValue(aPos); - if (fVal != fExpected) - { - cerr << "Wrong value in C" << (i + 1) << ": expected=" << fExpected - << ", actual=" << fVal << endl; - return false; - } - } - - // D2:D7 should show 1,2,...,6. - fExpected = 1.0; - for (SCROW i = 1; i <= 6; ++i, ++fExpected) - { - ScAddress aPos(3, i, 0); - double fVal = rDoc.GetValue(aPos); - if (fVal != fExpected) - { - cerr << "Wrong value in D" << (i + 1) << ": expected=" << fExpected - << ", actual=" << fVal << endl; - return false; - } - } - - return true; - } - - } aTest; - - createScDoc("xlsx/shared-formula/3d-reference.xlsx"); - { - ScDocument* pDoc = getScDoc(); - bool bRes = aTest.checkContent(*pDoc); - CPPUNIT_ASSERT_MESSAGE("Content check on the initial document failed.", bRes); - - pDoc->CalcAll(); // Recalculate to flush all cached results. - bRes = aTest.checkContent(*pDoc); - CPPUNIT_ASSERT_MESSAGE("Content check on the initial recalculated document failed.", bRes); - } - - // Save and reload, and check the content again. - saveAndReload("Calc Office Open XML"); - - ScDocument* pDoc = getScDoc(); - pDoc->CalcAll(); // Recalculate to flush all cached results. - - bool bRes = aTest.checkContent(*pDoc); - CPPUNIT_ASSERT_MESSAGE("Content check on the reloaded document failed.", bRes); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testSharedFormulaStringResultExportXLSX) -{ - struct - { - bool checkContent(ScDocument& rDoc) - { - { - // B2:B7 should show A,B,...,F. - const char* const expected[] = { "A", "B", "C", "D", "E", "F" }; - for (SCROW i = 0; i <= 5; ++i) - { - ScAddress aPos(1, i + 1, 0); - OUString aStr = rDoc.GetString(aPos); - OUString aExpected = OUString::createFromAscii(expected[i]); - if (aStr != aExpected) - { - cerr << "Wrong value in B" << (i + 2) << ": expected='" << aExpected - << "', actual='" << aStr << "'" << endl; - return false; - } - } - } - - { - // C2:C7 should show AA,BB,...,FF. - const char* const expected[] = { "AA", "BB", "CC", "DD", "EE", "FF" }; - for (SCROW i = 0; i <= 5; ++i) - { - ScAddress aPos(2, i + 1, 0); - OUString aStr = rDoc.GetString(aPos); - OUString aExpected = OUString::createFromAscii(expected[i]); - if (aStr != aExpected) - { - cerr << "Wrong value in C" << (i + 2) << ": expected='" << aExpected - << "', actual='" << aStr << "'" << endl; - return false; - } - } - } - - return true; - } - - } aTest; - - createScDoc("xlsx/shared-formula/text-results.xlsx"); - { - ScDocument* pDoc = getScDoc(); - - // Check content without re-calculation, to test cached formula results. - bool bRes = aTest.checkContent(*pDoc); - CPPUNIT_ASSERT_MESSAGE("Content check on the initial document failed.", bRes); - - // Now, re-calculate and check the results. - pDoc->CalcAll(); - bRes = aTest.checkContent(*pDoc); - CPPUNIT_ASSERT_MESSAGE("Content check on the initial recalculated document failed.", bRes); - } - // Reload and check again. - saveAndReload("Calc Office Open XML"); - ScDocument* pDoc = getScDoc(); - - bool bRes = aTest.checkContent(*pDoc); - CPPUNIT_ASSERT_MESSAGE("Content check on the reloaded document failed.", bRes); -} - -void ScExportTest::testFunctionsExcel2010(const OUString& sFormatType) -{ - createScDoc("xlsx/functions-excel-2010.xlsx"); - - saveAndReload(sFormatType); - ScDocument* pDoc = getScDoc(); - pDoc->CalcAll(); // perform hard re-calculation. - - testFunctionsExcel2010_Impl(*pDoc); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testFunctionsExcel2010XLSX) -{ - testFunctionsExcel2010("Calc Office Open XML"); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testFunctionsExcel2010XLS) -{ - testFunctionsExcel2010("MS Excel 97"); -} - -void ScExportTest::testCeilingFloor(const OUString& sFormatType) -{ - createScDoc("xlsx/ceiling-floor.xlsx"); - - saveAndReload(sFormatType); - ScDocument* pDoc = getScDoc(); - pDoc->CalcAll(); // perform hard re-calculation. - - testCeilingFloor_Impl(*pDoc); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testCeilingFloorXLSX) -{ - testCeilingFloor("Calc Office Open XML"); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testCeilingFloorODSToXLSX) -{ - // tdf#100011 - Cannot open sheet containing FLOOR/CEILING functions by MS Excel, after export to .xlsx - createScDoc("ods/ceiling-floor.ods"); - - save("Calc Office Open XML"); - xmlDocUniquePtr pSheet = parseExport("xl/workbook.xml"); - CPPUNIT_ASSERT(pSheet); - - // there shouldn't be any defined names during export of FLOOR and CEILING functions to .xlsx - assertXPath(pSheet, "/x:workbook/x:definedNames", 0); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testCeilingFloorXLS) { testCeilingFloor("MS Excel 97"); } - -CPPUNIT_TEST_FIXTURE(ScExportTest, testCeilingFloorODS) { testCeilingFloor("calc8"); } - -CPPUNIT_TEST_FIXTURE(ScExportTest, testCustomXml) -{ - // Load document and export it to a temporary file - createScDoc("xlsx/customxml.xlsx"); - - save("Calc Office Open XML"); - xmlDocUniquePtr pXmlDoc = parseExport("customXml/item1.xml"); - CPPUNIT_ASSERT(pXmlDoc); - xmlDocUniquePtr pRelsDoc = parseExport("customXml/_rels/item1.xml.rels"); - CPPUNIT_ASSERT(pRelsDoc); - - // Check there is a relation to itemProps1.xml. - assertXPath(pRelsDoc, "/rels:Relationships/rels:Relationship", 1); - assertXPath(pRelsDoc, "/rels:Relationships/rels:Relationship[@Id='rId1']", "Target", - "itemProps1.xml"); - - std::unique_ptr<SvStream> pStream = parseExportStream(maTempFile.GetURL(), "ddp/ddpfile.xen"); - CPPUNIT_ASSERT(pStream); -} - -#ifdef _WIN32 -static sal_Unicode lcl_getWindowsDrive(const OUString& aURL) -{ - static const sal_Int32 nMinLen = strlen("file:///X:/"); - if (aURL.getLength() <= nMinLen) - return 0; - const OUString aUrlStart = aURL.copy(0, nMinLen); - return (aUrlStart.startsWith("file:///") && aUrlStart.endsWith(":/")) ? aUrlStart[8] : 0; -} -#endif - -CPPUNIT_TEST_FIXTURE(ScExportTest, testRelativePathsODS) -{ - createScDoc("ods/fdo79305.ods"); - - save("calc8"); - xmlDocUniquePtr pDoc = parseExport("content.xml"); - CPPUNIT_ASSERT(pDoc); - OUString aURL = getXPath(pDoc, - "/office:document-content/office:body/office:spreadsheet/table:table/" - "table:table-row[2]/table:table-cell[2]/text:p/text:a", - "href"); -#ifdef _WIN32 - // if the exported document is not on the same drive then the linked document, - // there is no way to get a relative URL for the link, because ../X:/ is undefined. - if (!aURL.startsWith("..")) - { - sal_Unicode aDocDrive = lcl_getWindowsDrive(maTempFile.GetURL()); - sal_Unicode aLinkDrive = lcl_getWindowsDrive(aURL); - CPPUNIT_ASSERT_MESSAGE("document on the same drive but no relative link!", aDocDrive != 0); - CPPUNIT_ASSERT_MESSAGE("document on the same drive but no relative link!", aLinkDrive != 0); - CPPUNIT_ASSERT_MESSAGE("document on the same drive but no relative link!", - aDocDrive != aLinkDrive); - return; - } -#endif - // make sure that the URL is relative - CPPUNIT_ASSERT(aURL.startsWith("..")); -} - -namespace -{ -void testSheetProtection_Impl(ScDocument& rDoc) -{ - CPPUNIT_ASSERT(rDoc.IsTabProtected(0)); - const ScTableProtection* pTabProtection = rDoc.GetTabProtection(0); - CPPUNIT_ASSERT(pTabProtection); - CPPUNIT_ASSERT(pTabProtection->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS)); - CPPUNIT_ASSERT(!pTabProtection->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS)); -} -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testSheetProtectionODS) -{ - createScDoc("ods/sheet-protection.ods"); - - ScDocument* pDoc = getScDoc(); - - testSheetProtection_Impl(*pDoc); - - saveAndReload("calc8"); - - pDoc = getScDoc(); - - testSheetProtection_Impl(*pDoc); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testFunctionsExcel2010ODS) -{ - //testFunctionsExcel2010("calc8"); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testSwappedOutImageExport) -{ - std::vector<OUString> aFilterNames{ "calc8", "MS Excel 97", "Calc Office Open XML" }; - - // Set cache size to a very small value to make sure one of the images is swapped out - std::shared_ptr<comphelper::ConfigurationChanges> xBatch( - comphelper::ConfigurationChanges::create()); - officecfg::Office::Common::Cache::GraphicManager::TotalCacheSize::set(sal_Int32(1), xBatch); - xBatch->commit(); - - for (size_t i = 0; i < aFilterNames.size(); ++i) - { - // Check whether the export code swaps in the image which was swapped out before. - createScDoc("ods/document_with_two_images.ods"); - - const OString sFailedMessage - = OString::Concat("Failed on filter: ") + aFilterNames[i].toUtf8(); - - // Export the document and import again for a check - saveAndReload(aFilterNames[i]); - - // Check whether graphic exported well after it was swapped out - uno::Reference<sheet::XSpreadsheetDocument> xDoc(mxComponent, UNO_QUERY_THROW); - uno::Reference<container::XIndexAccess> xIA(xDoc->getSheets(), UNO_QUERY_THROW); - uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xIA->getByIndex(0), - UNO_QUERY_THROW); - uno::Reference<container::XIndexAccess> xDraws(xDrawPageSupplier->getDrawPage(), - UNO_QUERY_THROW); - CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(2), - xDraws->getCount()); - - uno::Reference<drawing::XShape> xImage(xDraws->getByIndex(0), uno::UNO_QUERY); - uno::Reference<beans::XPropertySet> XPropSet(xImage, uno::UNO_QUERY_THROW); - - // Check Graphic, Size - { - uno::Reference<graphic::XGraphic> xGraphic; - XPropSet->getPropertyValue("Graphic") >>= xGraphic; - CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xGraphic.is()); - CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), - xGraphic->getType() != graphic::GraphicType::EMPTY); - uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY); - CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xBitmap.is()); - CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(610), - xBitmap->getSize().Width); - CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(381), - xBitmap->getSize().Height); - } - // Second Image - xImage.set(xDraws->getByIndex(1), uno::UNO_QUERY); - XPropSet.set(xImage, uno::UNO_QUERY_THROW); - - // Check Graphic, Size - { - uno::Reference<graphic::XGraphic> xGraphic; - XPropSet->getPropertyValue("Graphic") >>= xGraphic; - CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xGraphic.is()); - CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), - xGraphic->getType() != graphic::GraphicType::EMPTY); - uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY); - CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xBitmap.is()); - CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(900), - xBitmap->getSize().Width); - CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(600), - xBitmap->getSize().Height); - } - } -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testSupBookVirtualPathXLS) -{ - createScDoc("xls/external-ref.xls"); - - saveAndReload("MS Excel 97"); - - ScDocument* pDoc = getScDoc(); - - OUString aFormula = pDoc->GetFormula(0, 0, 0); -#ifdef _WIN32 - aFormula = OUString::Concat(aFormula.subView(0, 9)) + aFormula.subView(12); - // strip drive letter, e.g. 'C:/' -#endif - CPPUNIT_ASSERT_EQUAL_MESSAGE( - "Wrong SupBook VirtualPath URL", - OUString("='file:///home/timar/Documents/external.xls'#$Sheet1.A1"), aFormula); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testLinkedGraphicRT) -{ - // Problem was with linked images - std::vector<OUString> aFilterNames{ "calc8", "MS Excel 97", "Calc Office Open XML" }; - - for (size_t i = 0; i < aFilterNames.size(); ++i) - { - // Load the original file with one image - createScDoc("ods/document_with_linked_graphic.ods"); - const OString sFailedMessage - = OString::Concat("Failed on filter: ") + aFilterNames[i].toUtf8(); - - // Export the document and import again for a check - saveAndReload(aFilterNames[i]); - - // Check whether graphic imported well after export - ScDocument* pDoc = getScDoc(); - ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer(); - CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pDrawLayer != nullptr); - const SdrPage* pPage = pDrawLayer->GetPage(0); - CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pPage != nullptr); - SdrGrafObj* pObject = dynamic_cast<SdrGrafObj*>(pPage->GetObj(0)); - CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pObject != nullptr); - if (aFilterNames[i] == "Calc Office Open XML") - { - // FIXME: tdf#152036 - CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), !pObject->IsLinkedGraphic()); - } - else - CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pObject->IsLinkedGraphic()); - - const GraphicObject& rGraphicObj = pObject->GetGraphicObject(true); - CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), int(GraphicType::Bitmap), - int(rGraphicObj.GetGraphic().GetType())); - CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_uLong(864900), - rGraphicObj.GetGraphic().GetSizeBytes()); - } -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testImageWithSpecialID) -{ - std::vector<OUString> aFilterNames{ "calc8", "MS Excel 97", "Calc Office Open XML" }; - - // Trigger swap out mechanism to test swapped state factor too. - std::shared_ptr<comphelper::ConfigurationChanges> batch( - comphelper::ConfigurationChanges::create()); - officecfg::Office::Common::Cache::GraphicManager::TotalCacheSize::set(sal_Int32(1), batch); - batch->commit(); - - for (size_t i = 0; i < aFilterNames.size(); ++i) - { - createScDoc("ods/images_with_special_IDs.ods"); - - const OString sFailedMessage - = OString::Concat("Failed on filter: ") + aFilterNames[i].toUtf8(); - - // Export the document and import again for a check - saveAndReload(aFilterNames[i]); - - // Check whether graphic was exported well - uno::Reference<sheet::XSpreadsheetDocument> xDoc(mxComponent, UNO_QUERY_THROW); - uno::Reference<container::XIndexAccess> xIA(xDoc->getSheets(), UNO_QUERY_THROW); - uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xIA->getByIndex(0), - UNO_QUERY_THROW); - uno::Reference<container::XIndexAccess> xDraws(xDrawPageSupplier->getDrawPage(), - UNO_QUERY_THROW); - CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(2), - xDraws->getCount()); - - uno::Reference<drawing::XShape> xImage(xDraws->getByIndex(0), uno::UNO_QUERY); - uno::Reference<beans::XPropertySet> XPropSet(xImage, uno::UNO_QUERY_THROW); - - // Check Graphic, Size - { - uno::Reference<graphic::XGraphic> xGraphic; - XPropSet->getPropertyValue("Graphic") >>= xGraphic; - CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xGraphic.is()); - CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), - xGraphic->getType() != graphic::GraphicType::EMPTY); - uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY); - CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xBitmap.is()); - CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(610), - xBitmap->getSize().Width); - CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(381), - xBitmap->getSize().Height); - } - // Second Image - xImage.set(xDraws->getByIndex(1), uno::UNO_QUERY); - XPropSet.set(xImage, uno::UNO_QUERY_THROW); - - // Check Graphic, Size - { - uno::Reference<graphic::XGraphic> xGraphic; - XPropSet->getPropertyValue("Graphic") >>= xGraphic; - CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xGraphic.is()); - CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), - xGraphic->getType() != graphic::GraphicType::EMPTY); - uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY); - CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xBitmap.is()); - CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(900), - xBitmap->getSize().Width); - CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(600), - xBitmap->getSize().Height); - } - } -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testAbsNamedRangeHTML) -{ - setImportFilterName("calc_HTML_WebQuery"); - createScDoc("html/numberformat.html"); - ScDocShell* pDocSh = getScDocShell(); - pDocSh->DoHardRecalc(); - - //reset import filter - setImportFilterName("calc8"); - saveAndReload("calc8"); - pDocSh = getScDocShell(); - pDocSh->DoHardRecalc(); - - ScDocument* pDoc = getScDoc(); - ScRangeData* pRangeData = pDoc->GetRangeName()->findByUpperName(OUString("HTML_1")); - ScSingleRefData* pRef = pRangeData->GetCode()->FirstToken()->GetSingleRef(); - // see tdf#119141 for the reason why this isn't Sheet1.HTML_1 - CPPUNIT_ASSERT_MESSAGE("HTML_1 is an absolute reference", !pRef->IsTabRel()); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testTdf80149) -{ - createScDoc("csv/tdf80149.csv"); - ScDocShell* pDocSh = getScDocShell(); - pDocSh->DoHardRecalc(); - saveAndReload("Calc Office Open XML"); - pDocSh = getScDocShell(); - pDocSh->DoHardRecalc(); - - ScDocument* pDoc = getScDoc(); - CPPUNIT_ASSERT_EQUAL(OUString("row 1"), pDoc->GetString(0, 0, 0)); - - // Without the fix in place, this test would have failed with - // - Expected: Character 0x16 is here ->><<-- - // - Actual : - CPPUNIT_ASSERT_EQUAL(OUString("Character 0x16 is here ->><<--"), pDoc->GetString(1, 0, 0)); - CPPUNIT_ASSERT_EQUAL(OUString("File opens in libre office, but can't be saved as xlsx"), - pDoc->GetString(2, 0, 0)); - CPPUNIT_ASSERT_EQUAL(OUString("row 2"), pDoc->GetString(0, 1, 0)); - CPPUNIT_ASSERT_EQUAL(OUString("Subsequent rows get truncated"), pDoc->GetString(1, 1, 0)); - CPPUNIT_ASSERT_EQUAL(OUString("This cell goes missing"), pDoc->GetString(2, 1, 0)); - CPPUNIT_ASSERT_EQUAL(OUString("row 3"), pDoc->GetString(0, 2, 0)); - CPPUNIT_ASSERT_EQUAL(OUString("Subsequent rows get truncated"), pDoc->GetString(1, 2, 0)); - CPPUNIT_ASSERT_EQUAL(OUString("This cell goes missing"), pDoc->GetString(2, 2, 0)); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testSheetLocalRangeNameXLS) -{ - createScDoc("xls/named-ranges-local.xls"); - ScDocShell* pDocSh = getScDocShell(); - pDocSh->DoHardRecalc(); - saveAndReload("MS Excel 97"); - pDocSh = getScDocShell(); - pDocSh->DoHardRecalc(); - - ScDocument* pDoc = getScDoc(); - ScRangeName* pRangeName = pDoc->GetRangeName(0); - CPPUNIT_ASSERT(pRangeName); - CPPUNIT_ASSERT_EQUAL(size_t(2), pRangeName->size()); - - OUString aFormula = pDoc->GetFormula(3, 11, 0); - CPPUNIT_ASSERT_EQUAL(OUString("=SUM(local_name2)"), aFormula); - ASSERT_DOUBLES_EQUAL(14.0, pDoc->GetValue(3, 11, 0)); - - aFormula = pDoc->GetFormula(6, 4, 0); - CPPUNIT_ASSERT_EQUAL(OUString("=local_name1"), aFormula); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testRelativeNamedExpressionsXLS) -{ - createScDoc("ods/tdf113991_relativeNamedRanges.ods"); - ScDocShell* pDocSh = getScDocShell(); - pDocSh->DoHardRecalc(); - saveAndReload("MS Excel 97"); - pDocSh = getScDocShell(); - pDocSh->DoHardRecalc(); - - ScDocument* pDoc = getScDoc(); - // Sheet1:G3 - ScAddress aPos(6, 2, 0); - CPPUNIT_ASSERT_EQUAL(1.0, pDoc->GetValue(aPos)); - CPPUNIT_ASSERT_EQUAL(OUString("=single_cell_A3"), - pDoc->GetFormula(aPos.Col(), aPos.Row(), aPos.Tab())); - // Sheet2:F6 - aPos = ScAddress(5, 5, 1); - CPPUNIT_ASSERT_EQUAL(18.0, pDoc->GetValue(aPos)); - CPPUNIT_ASSERT_EQUAL(OUString("=SUM(test_conflict)"), - pDoc->GetFormula(aPos.Col(), aPos.Row(), aPos.Tab())); - // Sheet2:H3 - aPos = ScAddress(7, 2, 1); - CPPUNIT_ASSERT_EQUAL(10.0, pDoc->GetValue(aPos)); - CPPUNIT_ASSERT_EQUAL(OUString("=single_global_A3"), - pDoc->GetFormula(aPos.Col(), aPos.Row(), aPos.Tab())); - // Sheet2:H6 - aPos = ScAddress(7, 5, 1); - CPPUNIT_ASSERT_EQUAL(75.0, pDoc->GetValue(aPos)); - CPPUNIT_ASSERT_EQUAL(OUString("=SUM(A6:F6)"), - pDoc->GetFormula(aPos.Col(), aPos.Row(), aPos.Tab())); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testSheetTextBoxHyperlinkXLSX) -{ - createScDoc("xlsx/textbox-hyperlink.xlsx"); - - save("Calc Office Open XML"); - xmlDocUniquePtr pDoc = parseExport("xl/drawings/drawing1.xml"); - CPPUNIT_ASSERT(pDoc); - - assertXPath( - pDoc, - "/xdr:wsDr[1]/xdr:twoCellAnchor[1]/xdr:sp[1]/xdr:nvSpPr[1]/xdr:cNvPr[1]/a:hlinkClick[1]", - 1); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testFontSizeXLSX) -{ - createScDoc("xlsx/fontSize.xlsx"); - - save("Calc Office Open XML"); - xmlDocUniquePtr pDoc = parseExport("xl/drawings/drawing1.xml"); - CPPUNIT_ASSERT(pDoc); - OUString fontSize = getXPath( - pDoc, "/xdr:wsDr/xdr:twoCellAnchor/xdr:sp[1]/xdr:txBody/a:p[1]/a:r[1]/a:rPr", "sz"); - // make sure that the font size is 18 - CPPUNIT_ASSERT_EQUAL(OUString("1800"), fontSize); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testSheetCharacterKerningSpaceXLSX) -{ - createScDoc("xlsx/textbox-CharKerningSpace.xlsx"); - - saveAndReload("Calc Office Open XML"); - - save("Calc Office Open XML"); - xmlDocUniquePtr pDoc = parseExport("xl/drawings/drawing1.xml"); - CPPUNIT_ASSERT(pDoc); - - OUString CharKerningSpace = getXPath( - pDoc, "/xdr:wsDr[1]/xdr:twoCellAnchor[1]/xdr:sp[1]/xdr:txBody[1]/a:p[1]/a:r[1]/a:rPr[1]", - "spc"); - - // make sure that the CharKerning is 1997. - CPPUNIT_ASSERT_EQUAL(OUString("1997"), CharKerningSpace); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testSheetCondensedCharacterSpaceXLSX) -{ - createScDoc("xlsx/textbox-CondensedCharacterSpace.xlsx"); - - save("Calc Office Open XML"); - xmlDocUniquePtr pDoc = parseExport("xl/drawings/drawing1.xml"); - CPPUNIT_ASSERT(pDoc); - - OUString CondensedCharSpace = getXPath( - pDoc, "/xdr:wsDr[1]/xdr:twoCellAnchor[1]/xdr:sp[1]/xdr:txBody[1]/a:p[1]/a:r[1]/a:rPr[1]", - "spc"); - - // make sure that the CondensedCharSpace is -1002. - CPPUNIT_ASSERT_EQUAL(OUString("-1002"), CondensedCharSpace); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testTextUnderlineColorXLSX) -{ - createScDoc("xlsx/underlineColor.xlsx"); - - save("Calc Office Open XML"); - xmlDocUniquePtr pDoc = parseExport("xl/drawings/drawing1.xml"); - CPPUNIT_ASSERT(pDoc); - // Make sure the underline type is double line - assertXPath(pDoc, "/xdr:wsDr/xdr:twoCellAnchor[1]/xdr:sp[1]/xdr:txBody/a:p[1]/a:r[1]/a:rPr", - "u", "dbl"); - - assertXPath(pDoc, "/xdr:wsDr/xdr:twoCellAnchor[1]/xdr:sp[1]/xdr:txBody/a:p[1]/a:r[1]/a:rPr", - "b", "1"); - // Make sure that the underline color is RED - assertXPath(pDoc, - "/xdr:wsDr/xdr:twoCellAnchor[1]/xdr:sp[1]/xdr:txBody/a:p[1]/a:r[1]/a:rPr/a:uFill/" - "a:solidFill/a:srgbClr", - "val", "ff0000"); - - // Make sure the underline type is drawn with heavy line - assertXPath(pDoc, "/xdr:wsDr/xdr:twoCellAnchor[2]/xdr:sp[1]/xdr:txBody/a:p[1]/a:r[1]/a:rPr", - "u", "heavy"); - // tdf#104219 Make sure that uFill is not existing and uFillTx is set. - // It mean that color is automatic, should be the same color as the text. - assertXPath( - pDoc, "/xdr:wsDr/xdr:twoCellAnchor[2]/xdr:sp[1]/xdr:txBody/a:p[1]/a:r[1]/a:rPr/a:uFill", 0); - assertXPath(pDoc, - "/xdr:wsDr/xdr:twoCellAnchor[2]/xdr:sp[1]/xdr:txBody/a:p[1]/a:r[1]/a:rPr/a:uFillTx", - 1); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testSheetRunParagraphPropertyXLSX) -{ - createScDoc("xlsx/TextColor.xlsx"); - - save("Calc Office Open XML"); - xmlDocUniquePtr pDoc = parseExport("xl/sharedStrings.xml"); - CPPUNIT_ASSERT(pDoc); - - OUString aColor = getXPath(pDoc, "/x:sst/x:si/x:r[1]/x:rPr[1]/x:color", "rgb"); - CPPUNIT_ASSERT_EQUAL(OUString("FFFF0000"), aColor); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testPreserveTextWhitespaceXLSX) -{ - createScDoc("xlsx/preserve-whitespace.xlsx"); - - save("Calc Office Open XML"); - xmlDocUniquePtr pDoc = parseExport("xl/sharedStrings.xml"); - CPPUNIT_ASSERT(pDoc); - assertXPath(pDoc, "/x:sst/x:si/x:t", "space", "preserve"); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testPreserveTextWhitespace2XLSX) -{ - createScDoc("xlsx/preserve_space.xlsx"); - - save("Calc Office Open XML"); - xmlDocUniquePtr pDoc = parseExport("xl/sharedStrings.xml"); - CPPUNIT_ASSERT(pDoc); - assertXPath(pDoc, "/x:sst/x:si[1]/x:t", "space", "preserve"); - assertXPath(pDoc, "/x:sst/x:si[2]/x:r[1]/x:t", "space", "preserve"); - assertXPath(pDoc, "/x:sst/x:si[2]/x:r[2]/x:t", "space", "preserve"); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testHiddenShapeXLS) -{ - createScDoc("xls/hiddenShape.xls"); - - ScDocument* pDoc = getScDoc(); - CPPUNIT_ASSERT(pDoc->GetTableCount() > 0); - ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer(); - SdrPage* pPage = pDrawLayer->GetPage(0); - CPPUNIT_ASSERT(pPage); - SdrObject* pObj = pPage->GetObj(0); - CPPUNIT_ASSERT(pObj); - CPPUNIT_ASSERT_MESSAGE("Drawing object should not be visible.", !pObj->IsVisible()); - CPPUNIT_ASSERT_MESSAGE("Drawing object should not be printable.", !pObj->IsPrintable()); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testHiddenShapeXLSX) -{ - createScDoc("xlsx/hiddenShape.xlsx"); - - ScDocument* pDoc = getScDoc(); - CPPUNIT_ASSERT(pDoc->GetTableCount() > 0); - ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer(); - SdrPage* pPage = pDrawLayer->GetPage(0); - CPPUNIT_ASSERT(pPage); - SdrObject* pObj = pPage->GetObj(0); - CPPUNIT_ASSERT(pObj); - CPPUNIT_ASSERT_MESSAGE("Drawing object should not be visible.", !pObj->IsVisible()); - CPPUNIT_ASSERT_MESSAGE("Drawing object should not be printable.", !pObj->IsPrintable()); - - save("Calc Office Open XML"); - xmlDocUniquePtr pDocXml = parseExport("xl/drawings/drawing1.xml"); - CPPUNIT_ASSERT(pDocXml); - assertXPath(pDocXml, "/xdr:wsDr/xdr:twoCellAnchor/xdr:sp[1]/xdr:nvSpPr/xdr:cNvPr", "hidden", - "1"); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testShapeAutofitXLSX) -{ - createScDoc("xlsx/testShapeAutofit.xlsx"); - - save("Calc Office Open XML"); - xmlDocUniquePtr pDoc = parseExport("xl/drawings/drawing1.xml"); - CPPUNIT_ASSERT(pDoc); - - // TextAutoGrowHeight --> "Fit height to text" / "Resize shape to fit text" --> true - assertXPath(pDoc, "/xdr:wsDr/xdr:twoCellAnchor[1]/xdr:sp/xdr:txBody/a:bodyPr/a:spAutoFit", 1); - // TextAutoGrowHeight --> "Fit height to text" / "Resize shape to fit text" --> false - assertXPath(pDoc, "/xdr:wsDr/xdr:twoCellAnchor[2]/xdr:sp/xdr:txBody/a:bodyPr/a:noAutofit", 1); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testHyperlinkXLSX) -{ - createScDoc("xlsx/hyperlink.xlsx"); - - save("Calc Office Open XML"); - xmlDocUniquePtr pDoc = parseExport("xl/drawings/_rels/drawing1.xml.rels"); - CPPUNIT_ASSERT(pDoc); - assertXPath(pDoc, "/rels:Relationships/rels:Relationship", "Target", "#Sheet2!A1"); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testMoveCellAnchoredShapesODS) -{ - createScDoc("ods/move-cell-anchored-shapes.ods"); - - // There are two cell-anchored objects on the first sheet. - ScDocument* pDoc = getScDoc(); - - CPPUNIT_ASSERT_MESSAGE("There should be at least one sheet.", pDoc->GetTableCount() > 0); - - ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer(); - SdrPage* pPage = pDrawLayer->GetPage(0); - CPPUNIT_ASSERT_MESSAGE("draw page for sheet 1 should exist.", pPage); - SdrObject* pObj = pPage->GetObj(0); - CPPUNIT_ASSERT_MESSAGE("Failed to get drawing object.", pObj); - - // Check cell anchor state - ScAnchorType oldType = ScDrawLayer::GetAnchorType(*pObj); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Failed to get anchor type", SCA_CELL_RESIZE, oldType); - - // Get anchor data - ScDrawObjData* pData = ScDrawLayer::GetObjData(pObj); - CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData); - CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", - !pData->getShapeRect().IsEmpty()); - - ScAddress aDataStart = pData->maStart; - ScAddress aDataEnd = pData->maEnd; - - // Get non rotated anchor data - ScDrawObjData* pNData = ScDrawLayer::GetNonRotatedObjData(pObj); - CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData); - CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", - !pNData->getShapeRect().IsEmpty()); - - ScAddress aNDataStart = pNData->maStart; - ScAddress aNDataEnd = pNData->maEnd; - CPPUNIT_ASSERT_EQUAL(aDataStart, aNDataStart); - CPPUNIT_ASSERT_EQUAL(aDataEnd, aNDataEnd); - - // Insert 2 rows. - pDoc->InsertRow(ScRange(0, aDataStart.Row() - 1, 0, pDoc->MaxCol(), aDataStart.Row(), 0)); - - // Get anchor data - pData = ScDrawLayer::GetObjData(pObj); - CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData); - CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", - !pData->getShapeRect().IsEmpty()); - - // Get non rotated anchor data - pNData = ScDrawLayer::GetNonRotatedObjData(pObj); - CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData); - CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", - !pNData->getShapeRect().IsEmpty()); - - // Check if data has moved to new rows - CPPUNIT_ASSERT_EQUAL(pData->maStart.Row(), aDataStart.Row() + 2); - CPPUNIT_ASSERT_EQUAL(pData->maEnd.Row(), aDataEnd.Row() + 2); - - CPPUNIT_ASSERT_EQUAL(pNData->maStart.Row(), aNDataStart.Row() + 2); - CPPUNIT_ASSERT_EQUAL(pNData->maEnd.Row(), aNDataEnd.Row() + 2); - - // Save the anchor data - aDataStart = pData->maStart; - aDataEnd = pData->maEnd; - aNDataStart = pNData->maStart; - aNDataEnd = pNData->maEnd; - - // Save the document and load again to check anchor persist - saveAndReload("calc8"); - - // There are two cell-anchored objects on the first sheet. - pDoc = getScDoc(); - - CPPUNIT_ASSERT_MESSAGE("There should be at least one sheet.", pDoc->GetTableCount() > 0); - - pDrawLayer = pDoc->GetDrawLayer(); - pPage = pDrawLayer->GetPage(0); - CPPUNIT_ASSERT_MESSAGE("draw page for sheet 1 should exist.", pPage); - pObj = pPage->GetObj(0); - CPPUNIT_ASSERT_MESSAGE("Failed to get drawing object.", pObj); - - // Check cell anchor state - oldType = ScDrawLayer::GetAnchorType(*pObj); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Failed to get anchor type", SCA_CELL_RESIZE, oldType); - - // Get anchor data - pData = ScDrawLayer::GetObjData(pObj); - CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData); - CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", - !pData->getShapeRect().IsEmpty()); - - // Get non rotated anchor data - pNData = ScDrawLayer::GetNonRotatedObjData(pObj); - CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData); - CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", - !pNData->getShapeRect().IsEmpty()); - - // Check if data after save it - CPPUNIT_ASSERT_EQUAL(pData->maStart, aDataStart); - CPPUNIT_ASSERT_EQUAL(pData->maEnd, aDataEnd); - - CPPUNIT_ASSERT_EQUAL(pNData->maStart, aNDataStart); - CPPUNIT_ASSERT_EQUAL(pNData->maEnd, aNDataEnd); - - // Insert a column. - pDoc->InsertCol(ScRange(aDataStart.Col(), 0, 0, aDataStart.Col(), pDoc->MaxRow(), 0)); - - // Get anchor data - pData = ScDrawLayer::GetObjData(pObj); - CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData); - CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", - !pData->getShapeRect().IsEmpty()); - - // Get non rotated anchor data - pNData = ScDrawLayer::GetNonRotatedObjData(pObj); - CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData); - CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", - !pNData->getShapeRect().IsEmpty()); - - // Check if data has moved to new rows - CPPUNIT_ASSERT_EQUAL(pData->maStart.Col(), SCCOL(aDataStart.Col() + 1)); - CPPUNIT_ASSERT_EQUAL(pData->maEnd.Col(), SCCOL(aDataEnd.Col() + 1)); - - CPPUNIT_ASSERT_EQUAL(pNData->maStart.Col(), SCCOL(aNDataStart.Col() + 1)); - CPPUNIT_ASSERT_EQUAL(pNData->maEnd.Col(), SCCOL(aNDataEnd.Col() + 1)); - - // Save the anchor data - aDataStart = pData->maStart; - aDataEnd = pData->maEnd; - aNDataStart = pNData->maStart; - aNDataEnd = pNData->maEnd; - - // Save the document and load again to check anchor persist - saveAndReload("calc8"); - - // There are two cell-anchored objects on the first sheet. - pDoc = getScDoc(); - - CPPUNIT_ASSERT_MESSAGE("There should be at least one sheet.", pDoc->GetTableCount() > 0); - - pDrawLayer = pDoc->GetDrawLayer(); - pPage = pDrawLayer->GetPage(0); - CPPUNIT_ASSERT_MESSAGE("draw page for sheet 1 should exist.", pPage); - pObj = pPage->GetObj(0); - CPPUNIT_ASSERT_MESSAGE("Failed to get drawing object.", pObj); - - // Check cell anchor state - oldType = ScDrawLayer::GetAnchorType(*pObj); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Failed to get anchor type", SCA_CELL_RESIZE, oldType); - - // Get anchor data - pData = ScDrawLayer::GetObjData(pObj); - CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData); - CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", - !pData->getShapeRect().IsEmpty()); - - // Get non rotated anchor data - pNData = ScDrawLayer::GetNonRotatedObjData(pObj); - CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData); - CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", - !pNData->getShapeRect().IsEmpty()); - - // Check if data after save it - CPPUNIT_ASSERT_EQUAL(pData->maStart, aDataStart); - CPPUNIT_ASSERT_EQUAL(pData->maEnd, aDataEnd); - - CPPUNIT_ASSERT_EQUAL(pNData->maStart, aNDataStart); - CPPUNIT_ASSERT_EQUAL(pNData->maEnd, aNDataEnd); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testConditionalFormatRangeListXLSX) -{ - createScDoc("ods/conditionalformat_rangelist.ods"); - save("Calc Office Open XML"); - xmlDocUniquePtr pDoc = parseExport("xl/worksheets/sheet1.xml"); - CPPUNIT_ASSERT(pDoc); - assertXPath(pDoc, "//x:conditionalFormatting", "sqref", "F4 F10"); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testConditionalFormatContainsTextXLSX) -{ - createScDoc("ods/conditionalformat_containstext.ods"); - save("Calc Office Open XML"); - xmlDocUniquePtr pDoc = parseExport("xl/worksheets/sheet1.xml"); - CPPUNIT_ASSERT(pDoc); - assertXPathContent(pDoc, "//x:conditionalFormatting/x:cfRule/x:formula", - "NOT(ISERROR(SEARCH(\"test\",A1)))"); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testConditionalFormatPriorityCheckXLSX) -{ - createScDoc("xlsx/conditional_fmt_checkpriority.xlsx"); - save("Calc Office Open XML"); - xmlDocUniquePtr pDoc = parseExport("xl/worksheets/sheet1.xml"); - CPPUNIT_ASSERT(pDoc); - constexpr bool bHighPriorityExtensionA1 - = true; // Should A1's extension cfRule has higher priority than normal cfRule ? - constexpr bool bHighPriorityExtensionA3 - = false; // Should A3's extension cfRule has higher priority than normal cfRule ? - size_t nA1NormalPriority = 0; - size_t nA1ExtPriority = 0; - size_t nA3NormalPriority = 0; - size_t nA3ExtPriority = 0; - for (size_t nIdx = 1; nIdx <= 2; ++nIdx) - { - OString aIdx = OString::number(nIdx); - OUString aCellAddr = getXPath(pDoc, "//x:conditionalFormatting[" + aIdx + "]", "sqref"); - OUString aPriority - = getXPath(pDoc, "//x:conditionalFormatting[" + aIdx + "]/x:cfRule", "priority"); - CPPUNIT_ASSERT_MESSAGE("conditionalFormatting sqref must be either A1 or A3", - aCellAddr == "A1" || aCellAddr == "A3"); - if (aCellAddr == "A1") - nA1NormalPriority = aPriority.toUInt32(); - else - nA3NormalPriority = aPriority.toUInt32(); - aCellAddr = getXPathContent( - pDoc, "//x:extLst/x:ext[1]/x14:conditionalFormattings/x14:conditionalFormatting[" + aIdx - + "]/xm:sqref"); - aPriority - = getXPath(pDoc, - "//x:extLst/x:ext[1]/x14:conditionalFormattings/x14:conditionalFormatting[" - + aIdx + "]/x14:cfRule", - "priority"); - CPPUNIT_ASSERT_MESSAGE("x14:conditionalFormatting sqref must be either A1 or A3", - aCellAddr == "A1" || aCellAddr == "A3"); - if (aCellAddr == "A1") - nA1ExtPriority = aPriority.toUInt32(); - else - nA3ExtPriority = aPriority.toUInt32(); - } - CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong priorities for A1", bHighPriorityExtensionA1, - nA1ExtPriority < nA1NormalPriority); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong priorities for A3", bHighPriorityExtensionA3, - nA3ExtPriority < nA3NormalPriority); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testConditionalFormatOriginXLSX) -{ - createScDoc("xlsx/conditional_fmt_origin.xlsx"); - save("Calc Office Open XML"); - xmlDocUniquePtr pDoc = parseExport("xl/worksheets/sheet1.xml"); - CPPUNIT_ASSERT(pDoc); - // tdf#124953 : The range-list is B3:C6 F1:G2, origin address in the formula should be B1, not B3. - OUString aFormula = getXPathContent(pDoc, "//x:conditionalFormatting/x:cfRule/x:formula"); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong origin address in formula", - OUString("NOT(ISERROR(SEARCH(\"BAC\",B1)))"), aFormula); -} - -// FILESAVE: XLSX export with long sheet names (length > 31 characters) -CPPUNIT_TEST_FIXTURE(ScExportTest, testTdf79998) -{ - // check: original document has tab name > 31 characters - createScDoc("ods/tdf79998.ods"); - ScDocument* pDoc = getScDoc(); - const std::vector<OUString> aTabNames1 = pDoc->GetAllTableNames(); - CPPUNIT_ASSERT_EQUAL(OUString("Utilities (FX Kurse, Kreditkarten etc)"), aTabNames1[1]); - - // check: saved XLSX document has truncated tab name - saveAndReload("Calc Office Open XML"); - pDoc = getScDoc(); - const std::vector<OUString> aTabNames2 = pDoc->GetAllTableNames(); - CPPUNIT_ASSERT_EQUAL(OUString("Utilities (FX Kurse, Kreditkart"), aTabNames2[1]); -} - -static void impl_testLegacyCellAnchoredRotatedShape(ScDocument& rDoc, const tools::Rectangle& aRect, - const ScDrawObjData& aAnchor, - tools::Long TOLERANCE = 30 /* 30 hmm */) -{ - ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer(); - CPPUNIT_ASSERT_MESSAGE("No drawing layer.", pDrawLayer); - SdrPage* pPage = pDrawLayer->GetPage(0); - CPPUNIT_ASSERT_MESSAGE("No page instance for the 1st sheet.", pPage); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pPage->GetObjCount()); - - SdrObject* pObj = pPage->GetObj(0); - const tools::Rectangle& aSnap = pObj->GetSnapRect(); - CPPUNIT_ASSERT_DOUBLES_EQUAL(aRect.GetHeight(), aSnap.GetHeight(), TOLERANCE); - CPPUNIT_ASSERT_DOUBLES_EQUAL(aRect.GetWidth(), aSnap.GetWidth(), TOLERANCE); - CPPUNIT_ASSERT_DOUBLES_EQUAL(aRect.Left(), aSnap.Left(), TOLERANCE); - CPPUNIT_ASSERT_DOUBLES_EQUAL(aRect.Top(), aSnap.Top(), TOLERANCE); - - ScDrawObjData* pData = ScDrawLayer::GetObjData(pObj); - CPPUNIT_ASSERT_MESSAGE("expected object meta data", pData); - CPPUNIT_ASSERT_EQUAL(aAnchor.maStart.Row(), pData->maStart.Row()); - CPPUNIT_ASSERT_EQUAL(aAnchor.maStart.Col(), pData->maStart.Col()); - CPPUNIT_ASSERT_EQUAL(aAnchor.maEnd.Row(), pData->maEnd.Row()); - CPPUNIT_ASSERT_EQUAL(aAnchor.maEnd.Col(), pData->maEnd.Col()); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testLegacyCellAnchoredRotatedShape) -{ - { - // This example doc contains cell anchored shape that is rotated, the - // rotated shape is in fact clipped by the sheet boundaries (and thus - // is a good edge case test to see if we import it still correctly) - createScDoc("ods/legacycellanchoredrotatedclippedshape.ods"); - - ScDocument* pDoc = getScDoc(); - // ensure the imported legacy rotated shape is in the expected position - tools::Rectangle aRect(6000, -2000, 8000, 4000); - // ensure the imported ( and converted ) anchor ( note we internally now store the anchor in - // terms of the rotated shape ) is more or less contains the correct info - ScDrawObjData aAnchor; - aAnchor.maStart.SetRow(0); - aAnchor.maStart.SetCol(5); - aAnchor.maEnd.SetRow(3); - aAnchor.maEnd.SetCol(7); - impl_testLegacyCellAnchoredRotatedShape(*pDoc, aRect, aAnchor); - // test save and reload - // for some reason having this test in subsequent_export-test.cxx causes - // a core dump in editeng ( so moved to here ) - saveAndReload("calc8"); - pDoc = getScDoc(); - impl_testLegacyCellAnchoredRotatedShape(*pDoc, aRect, aAnchor); - } - { - // This example doc contains cell anchored shape that is rotated, the - // rotated shape is in fact clipped by the sheet boundaries, additionally - // the shape is completely hidden because the rows the shape occupies - // are hidden - createScDoc("ods/legacycellanchoredrotatedhiddenshape.ods"); - ScDocument* pDoc = getScDoc(); - // ensure the imported legacy rotated shape is in the expected position - tools::Rectangle aRect(6000, -2000, 8000, 4000); - - // ensure the imported (and converted) anchor (note we internally now store the anchor in - // terms of the rotated shape) is more or less contains the correct info - ScDrawObjData aAnchor; - aAnchor.maStart.SetRow(0); - aAnchor.maStart.SetCol(5); - aAnchor.maEnd.SetRow(3); - aAnchor.maEnd.SetCol(7); - pDoc->ShowRows(0, 9, 0, true); // show relevant rows - pDoc->SetDrawPageSize(0); // trigger recalcpos - impl_testLegacyCellAnchoredRotatedShape(*pDoc, aRect, aAnchor); - // test save and reload - saveAndReload("calc8"); - pDoc = getScDoc(); - impl_testLegacyCellAnchoredRotatedShape(*pDoc, aRect, aAnchor); - } - { - // This example doc contains cell anchored shape that is rotated - createScDoc("ods/legacycellanchoredrotatedshape.ods"); - - ScDocument* pDoc = getScDoc(); - // ensure the imported legacy rotated shape is in the expected position - tools::Rectangle aRect(6000, 3000, 8000, 9000); - // ensure the imported (and converted) anchor (note we internally now store the anchor in - // terms of the rotated shape) more or less contains the correct info - - ScDrawObjData aAnchor; - aAnchor.maStart.SetRow(3); - aAnchor.maStart.SetCol(6); - aAnchor.maEnd.SetRow(9); - aAnchor.maEnd.SetCol(8); - // test import - impl_testLegacyCellAnchoredRotatedShape(*pDoc, aRect, aAnchor); - // test save and reload - saveAndReload("calc8"); - pDoc = getScDoc(); - impl_testLegacyCellAnchoredRotatedShape(*pDoc, aRect, aAnchor); - } -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testTdf113646) -{ - createScDoc("ods/tdf113646.ods"); - - save("Calc Office Open XML"); - xmlDocUniquePtr pSheet = parseExport("xl/styles.xml"); - CPPUNIT_ASSERT(pSheet); - - assertXPath(pSheet, "/x:styleSheet/x:dxfs/x:dxf/x:font/x:sz", "val", "36"); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testDateStandardfilterXLSX) -{ - // XLSX Roundtripping standard filter with date - createScDoc("ods/tdf142607.ods"); - - save("Calc Office Open XML"); - xmlDocUniquePtr pDoc = parseExport("xl/worksheets/sheet1.xml"); - CPPUNIT_ASSERT(pDoc); - - assertXPath(pDoc, "//x:autoFilter", "ref", "A1:B6"); - assertXPath(pDoc, "//x:autoFilter/x:filterColumn/x:filters/x:dateGroupItem[1]", "day", "03"); - assertXPath(pDoc, "//x:autoFilter/x:filterColumn/x:filters/x:dateGroupItem[1]", "month", "12"); - assertXPath(pDoc, "//x:autoFilter/x:filterColumn/x:filters/x:dateGroupItem[1]", "year", "2011"); - assertXPath(pDoc, "//x:autoFilter/x:filterColumn/x:filters/x:dateGroupItem[1]", - "dateTimeGrouping", "day"); -} - -CPPUNIT_TEST_FIXTURE(ScExportTest, testNumberFormatODS) -{ - createScDoc("ods/testNumberFormats.ods"); - saveAndReload("calc8"); - ScDocument* pDoc = getScDoc(); - sal_uInt32 nNumberFormat; - const sal_Int32 nCountFormats = 18; - const OUString aExpectedFormatStr[nCountFormats] - = { "\"format=\"000000", "\"format=\"??????", "\"format=\"??0000", - "\"format=\"000,000", "\"format=\"???,???", "\"format=\"??0,000", - "\"format=\"000\" \"?/?", "\"format=\"???\" \"?/?", "\"format=\"?00\" \"?/?", - "\"format=\"0,000\" \"?/?", "\"format=\"?,???\" \"?/?", "\"format=\"?,?00\" \"?/?", - "\"format=\"0.000E+00", "\"format=\"?.###E+00", "\"format=\"?.0##E+00", - "\"format=\"000E+00", "\"format=\"???E+00", "\"format=\"?00E+00" }; - for (sal_Int32 i = 0; i < nCountFormats; i++) - { - nNumberFormat = pDoc->GetNumberFormat(i + 1, 2, 0); - const SvNumberformat* pNumberFormat = pDoc->GetFormatTable()->GetEntry(nNumberFormat); - const OUString& rFormatStr = pNumberFormat->GetFormatstring(); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Number format modified during export/import", - aExpectedFormatStr[i], rFormatStr); - } - OUString aCSVPath = createFilePath(u"contentCSV/testNumberFormats.csv"); - testCondFile(aCSVPath, &*pDoc, 0, - false); // comma is thousand separator and cannot be used as delimiter -} - CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/qa/unit/subsequent_export_test3.cxx b/sc/qa/unit/subsequent_export_test3.cxx new file mode 100644 index 000000000000..8fb8e7da0b95 --- /dev/null +++ b/sc/qa/unit/subsequent_export_test3.cxx @@ -0,0 +1,1940 @@ +/* -*- 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 "helper/debughelper.hxx" + +#include "helper/qahelper.hxx" +#include "helper/shared_test_impl.hxx" + +#include <userdat.hxx> +#include <tokenstringcontext.hxx> +#include <chgtrack.hxx> +#include <scmod.hxx> + +#include <svx/svdpage.hxx> +#include <svx/svdograf.hxx> +#include <svl/zformat.hxx> +#include <svl/numformat.hxx> +#include <tabprotection.hxx> +#include <editeng/borderline.hxx> +#include <unotools/tempfile.hxx> +#include <unotools/useroptions.hxx> +#include <tools/datetime.hxx> + +#include <com/sun/star/drawing/XDrawPageSupplier.hpp> +#include <com/sun/star/awt/XBitmap.hpp> +#include <com/sun/star/graphic/GraphicType.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +class ScExportTest3 : public ScModelTestBase +{ +protected: + virtual void registerNamespaces(xmlXPathContextPtr& pXmlXPathCtx) override; + +public: + ScExportTest3() + : ScModelTestBase("sc/qa/unit/data") + { + } + +protected: + void testCeilingFloor(const OUString& sFormatType); + void testFunctionsExcel2010(const OUString& sFormatType); +}; + +void ScExportTest3::registerNamespaces(xmlXPathContextPtr& pXmlXPathCtx) +{ + XmlTestTools::registerOOXMLNamespaces(pXmlXPathCtx); + XmlTestTools::registerODFNamespaces(pXmlXPathCtx); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testBordersExchangeXLSX) +{ + // Document: sc/qa/unit/data/README.cellborders + + // short name for the table + const SvxBorderLineStyle None = SvxBorderLineStyle::NONE; + const SvxBorderLineStyle Solid = SvxBorderLineStyle::SOLID; + const SvxBorderLineStyle Dotted = SvxBorderLineStyle::DOTTED; + const SvxBorderLineStyle Dashed = SvxBorderLineStyle::DASHED; + const SvxBorderLineStyle FineDash = SvxBorderLineStyle::FINE_DASHED; + const SvxBorderLineStyle DashDot = SvxBorderLineStyle::DASH_DOT; + const SvxBorderLineStyle DashDoDo = SvxBorderLineStyle::DASH_DOT_DOT; + const SvxBorderLineStyle DoubThin = SvxBorderLineStyle::DOUBLE_THIN; + + const size_t nMaxCol = 18; + const size_t nMaxRow = 7; + + static struct + { + SvxBorderLineStyle BorderStyleTop, BorderStyleBottom; + tools::Long WidthTop, WidthBottom; + } aCheckBorderWidth[nMaxCol][nMaxRow] + = { /* Width */ + /* 0,05 */ { { Solid, Solid, 1, 1 }, // SOLID + { Dotted, Dotted, 15, 15 }, // DOTTED + { Dotted, Dotted, 15, 15 }, // DASHED + { FineDash, FineDash, 15, 15 }, // FINE_DASHED + { FineDash, FineDash, 15, 15 }, // DASH_DOT + { FineDash, FineDash, 15, 15 }, // DASH_DOT_DOT + { None, None, 0, 0 } }, // DOUBLE_THIN + /* 0,25 */ + { { Solid, Solid, 1, 1 }, + { Dotted, Dotted, 15, 15 }, + { Dotted, Dotted, 15, 15 }, + { FineDash, FineDash, 15, 15 }, + { FineDash, FineDash, 15, 15 }, + { FineDash, FineDash, 15, 15 }, + { None, None, 0, 0 } }, + /* 0,50 */ + { { Solid, Solid, 1, 1 }, + { Dotted, Dotted, 15, 15 }, + { Dotted, Dotted, 15, 15 }, + { FineDash, FineDash, 15, 15 }, + { FineDash, FineDash, 15, 15 }, + { FineDash, FineDash, 15, 15 }, + { None, None, 0, 0 } }, + /* 0,75 */ + { { Solid, Solid, 15, 15 }, + { Dotted, Dotted, 15, 15 }, + { FineDash, FineDash, 15, 15 }, + { FineDash, FineDash, 15, 15 }, + { DashDot, DashDot, 15, 15 }, + { DashDoDo, DashDoDo, 15, 15 }, + { DoubThin, DoubThin, 35, 35 } }, + /* 1,00 */ + { { Solid, Solid, 15, 15 }, + { Dotted, Dotted, 15, 15 }, + { FineDash, FineDash, 15, 15 }, + { FineDash, FineDash, 15, 15 }, + { DashDot, DashDot, 15, 15 }, + { DashDoDo, DashDoDo, 15, 15 }, + { DoubThin, DoubThin, 35, 35 } }, + /* 1,25 */ + { { Solid, Solid, 15, 15 }, + { Dotted, Dotted, 15, 15 }, + { FineDash, FineDash, 15, 15 }, + { FineDash, FineDash, 15, 15 }, + { DashDot, DashDot, 15, 15 }, + { DashDoDo, DashDoDo, 15, 15 }, + { DoubThin, DoubThin, 35, 35 } }, + /* 1,50 */ + { { Solid, Solid, 15, 15 }, + { Dotted, Dotted, 15, 15 }, + { FineDash, FineDash, 15, 15 }, + { FineDash, FineDash, 15, 15 }, + { DashDot, DashDot, 15, 15 }, + { DashDoDo, DashDoDo, 15, 15 }, + { DoubThin, DoubThin, 35, 35 } }, + + /* 1,75 */ + { { Solid, Solid, 35, 35 }, + { FineDash, FineDash, 35, 35 }, + { Dashed, Dashed, 35, 35 }, + { FineDash, FineDash, 35, 35 }, + { DashDot, DashDot, 35, 35 }, + { DashDoDo, DashDoDo, 35, 35 }, + { DoubThin, DoubThin, 35, 35 } }, + /* 2,00 */ + { { Solid, Solid, 35, 35 }, + { FineDash, FineDash, 35, 35 }, + { Dashed, Dashed, 35, 35 }, + { FineDash, FineDash, 35, 35 }, + { DashDot, DashDot, 35, 35 }, + { DashDoDo, DashDoDo, 35, 35 }, + { DoubThin, DoubThin, 35, 35 } }, + /* 2,25 */ + { { Solid, Solid, 35, 35 }, + { FineDash, FineDash, 35, 35 }, + { Dashed, Dashed, 35, 35 }, + { FineDash, FineDash, 35, 35 }, + { DashDot, DashDot, 35, 35 }, + { DashDoDo, DashDoDo, 35, 35 }, + { DoubThin, DoubThin, 35, 35 } }, + + /* 2,50 */ + { { Solid, Solid, 50, 50 }, + { FineDash, FineDash, 35, 35 }, + { Dashed, Dashed, 35, 35 }, + { FineDash, FineDash, 35, 35 }, + { DashDot, DashDot, 35, 35 }, + { DashDoDo, DashDoDo, 35, 35 }, + { DoubThin, DoubThin, 35, 35 } }, + /* 2,75 */ + { { Solid, Solid, 50, 50 }, + { FineDash, FineDash, 35, 35 }, + { Dashed, Dashed, 35, 35 }, + { FineDash, FineDash, 35, 35 }, + { DashDot, DashDot, 35, 35 }, + { DashDoDo, DashDoDo, 35, 35 }, + { DoubThin, DoubThin, 35, 35 } }, + /* 3,00 */ + { { Solid, Solid, 50, 50 }, + { FineDash, FineDash, 35, 35 }, + { Dashed, Dashed, 35, 35 }, + { FineDash, FineDash, 35, 35 }, + { DashDot, DashDot, 35, 35 }, + { DashDoDo, DashDoDo, 35, 35 }, + { DoubThin, DoubThin, 35, 35 } }, + /* 3,50 */ + { { Solid, Solid, 50, 50 }, + { FineDash, FineDash, 35, 35 }, + { Dashed, Dashed, 35, 35 }, + { FineDash, FineDash, 35, 35 }, + { DashDot, DashDot, 35, 35 }, + { DashDoDo, DashDoDo, 35, 35 }, + { DoubThin, DoubThin, 35, 35 } }, + /* 4,00 */ + { { Solid, Solid, 50, 50 }, + { FineDash, FineDash, 35, 35 }, + { Dashed, Dashed, 35, 35 }, + { FineDash, FineDash, 35, 35 }, + { DashDot, DashDot, 35, 35 }, + { DashDoDo, DashDoDo, 35, 35 }, + { DoubThin, DoubThin, 35, 35 } }, + /* 5,00 */ + { { Solid, Solid, 50, 50 }, + { FineDash, FineDash, 35, 35 }, + { Dashed, Dashed, 35, 35 }, + { FineDash, FineDash, 35, 35 }, + { DashDot, DashDot, 35, 35 }, + { DashDoDo, DashDoDo, 35, 35 }, + { DoubThin, DoubThin, 35, 35 } }, + /* 7,00 */ + { { Solid, Solid, 50, 50 }, + { FineDash, FineDash, 35, 35 }, + { Dashed, Dashed, 35, 35 }, + { FineDash, FineDash, 35, 35 }, + { DashDot, DashDot, 35, 35 }, + { DashDoDo, DashDoDo, 35, 35 }, + { DoubThin, DoubThin, 35, 35 } }, + /* 9,00 */ + { { Solid, Solid, 50, 50 }, + { FineDash, FineDash, 35, 35 }, + { Dashed, Dashed, 35, 35 }, + { FineDash, FineDash, 35, 35 }, + { DashDot, DashDot, 35, 35 }, + { DashDoDo, DashDoDo, 35, 35 }, + { DoubThin, DoubThin, 35, 35 } } + }; + + createScDoc("ods/test_borders_export.ods"); + + saveAndReload("Calc Office Open XML"); + ScDocument* pDoc = getScDoc(); + + for (size_t nCol = 0; nCol < nMaxCol; ++nCol) + { + for (size_t nRow = 0; nRow < nMaxRow; ++nRow) + { + const editeng::SvxBorderLine* pLineTop = nullptr; + const editeng::SvxBorderLine* pLineBottom = nullptr; + pDoc->GetBorderLines(nCol + 2, (nRow * 2) + 8, 0, nullptr, &pLineTop, nullptr, + &pLineBottom); + if ((nCol < 3) && (nRow == 6)) + { // in this range no lines since minimum size to create a double is 0.5 + CPPUNIT_ASSERT(!pLineTop); + CPPUNIT_ASSERT(!pLineBottom); + continue; + } + else + { + CPPUNIT_ASSERT(pLineTop); + CPPUNIT_ASSERT(pLineBottom); + } + + CPPUNIT_ASSERT_EQUAL_MESSAGE("Top Border-Line-Style wrong", + aCheckBorderWidth[nCol][nRow].BorderStyleTop, + pLineTop->GetBorderLineStyle()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Bottom Border-Line-Style wrong", + aCheckBorderWidth[nCol][nRow].BorderStyleBottom, + pLineBottom->GetBorderLineStyle()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Top Width-Line wrong", + aCheckBorderWidth[nCol][nRow].WidthTop, + pLineTop->GetWidth()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Bottom Width-Line wrong", + aCheckBorderWidth[nCol][nRow].WidthBottom, + pLineBottom->GetWidth()); + } + } +} + +static OUString toString(const ScBigRange& rRange) +{ + OUStringBuffer aBuf; + aBuf.append("(columns:"); + aBuf.append(rRange.aStart.Col()); + aBuf.append('-'); + aBuf.append(rRange.aEnd.Col()); + aBuf.append(";rows:"); + aBuf.append(rRange.aStart.Row()); + aBuf.append('-'); + aBuf.append(rRange.aEnd.Row()); + aBuf.append(";sheets:"); + aBuf.append(rRange.aStart.Tab()); + aBuf.append('-'); + aBuf.append(rRange.aEnd.Tab()); + aBuf.append(')'); + + return aBuf.makeStringAndClear(); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testTrackChangesSimpleXLSX) +{ + struct CheckItem + { + sal_uLong mnActionId; + ScChangeActionType meType; + + sal_Int32 mnStartCol; + sal_Int32 mnStartRow; + sal_Int32 mnStartTab; + sal_Int32 mnEndCol; + sal_Int32 mnEndRow; + sal_Int32 mnEndTab; + + bool mbRowInsertedAtBottom; + }; + + struct + { + bool checkRange(ScChangeActionType eType, const ScBigRange& rExpected, + const ScBigRange& rActual) + { + ScBigRange aExpected(rExpected), aActual(rActual); + + switch (eType) + { + case SC_CAT_INSERT_ROWS: + { + // Ignore columns. + aExpected.aStart.SetCol(0); + aExpected.aEnd.SetCol(0); + aActual.aStart.SetCol(0); + aActual.aEnd.SetCol(0); + } + break; + default:; + } + + return aExpected == aActual; + } + + bool check(ScDocument& rDoc) + { + static const CheckItem aChecks[] = { + { 1, SC_CAT_CONTENT, 1, 1, 0, 1, 1, 0, false }, + { 2, SC_CAT_INSERT_ROWS, 0, 2, 0, 0, 2, 0, true }, + { 3, SC_CAT_CONTENT, 1, 2, 0, 1, 2, 0, false }, + { 4, SC_CAT_INSERT_ROWS, 0, 3, 0, 0, 3, 0, true }, + { 5, SC_CAT_CONTENT, 1, 3, 0, 1, 3, 0, false }, + { 6, SC_CAT_INSERT_ROWS, 0, 4, 0, 0, 4, 0, true }, + { 7, SC_CAT_CONTENT, 1, 4, 0, 1, 4, 0, false }, + { 8, SC_CAT_INSERT_ROWS, 0, 5, 0, 0, 5, 0, true }, + { 9, SC_CAT_CONTENT, 1, 5, 0, 1, 5, 0, false }, + { 10, SC_CAT_INSERT_ROWS, 0, 6, 0, 0, 6, 0, true }, + { 11, SC_CAT_CONTENT, 1, 6, 0, 1, 6, 0, false }, + { 12, SC_CAT_INSERT_ROWS, 0, 7, 0, 0, 7, 0, true }, + { 13, SC_CAT_CONTENT, 1, 7, 0, 1, 7, 0, false }, + }; + + ScChangeTrack* pCT = rDoc.GetChangeTrack(); + if (!pCT) + { + cerr << "Change track instance doesn't exist." << endl; + return false; + } + + sal_uLong nActionMax = pCT->GetActionMax(); + if (nActionMax != 13) + { + cerr << "Unexpected highest action ID value." << endl; + return false; + } + + for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i) + { + sal_uInt16 nActId = aChecks[i].mnActionId; + const ScChangeAction* pAction = pCT->GetAction(nActId); + if (!pAction) + { + cerr << "No action for action number " << nActId << " found." << endl; + return false; + } + + if (pAction->GetType() != aChecks[i].meType) + { + cerr << "Unexpected action type for action number " << nActId << "." << endl; + return false; + } + + const ScBigRange& rRange = pAction->GetBigRange(); + ScBigRange aCheck(aChecks[i].mnStartCol, aChecks[i].mnStartRow, + aChecks[i].mnStartTab, aChecks[i].mnEndCol, aChecks[i].mnEndRow, + aChecks[i].mnEndTab); + + if (!checkRange(pAction->GetType(), aCheck, rRange)) + { + cerr << "Unexpected range for action number " << nActId + << ": expected=" << toString(aCheck) << " actual=" << toString(rRange) + << endl; + return false; + } + + switch (pAction->GetType()) + { + case SC_CAT_INSERT_ROWS: + { + const ScChangeActionIns* p = static_cast<const ScChangeActionIns*>(pAction); + if (p->IsEndOfList() != aChecks[i].mbRowInsertedAtBottom) + { + cerr << "Unexpected end-of-list flag for action number " << nActId + << "." << endl; + return false; + } + } + break; + default:; + } + } + + return true; + } + + bool checkRevisionUserAndTime(ScDocument& rDoc, std::u16string_view rOwnerName) + { + ScChangeTrack* pCT = rDoc.GetChangeTrack(); + if (!pCT) + { + cerr << "Change track instance doesn't exist." << endl; + return false; + } + + ScChangeAction* pAction = pCT->GetLast(); + if (pAction->GetUser() != "Kohei Yoshida") + { + cerr << "Wrong user name." << endl; + return false; + } + + DateTime aDT = pAction->GetDateTime(); + if (aDT.GetYear() != 2014 || aDT.GetMonth() != 7 || aDT.GetDay() != 11) + { + cerr << "Wrong time stamp." << endl; + return false; + } + + // Insert a new record to make sure the user and date-time are correct. + rDoc.SetString(ScAddress(1, 8, 0), "New String"); + ScCellValue aEmpty; + pCT->AppendContent(ScAddress(1, 8, 0), aEmpty); + pAction = pCT->GetLast(); + if (!pAction) + { + cerr << "Failed to retrieve last revision." << endl; + return false; + } + + if (rOwnerName != pAction->GetUser()) + { + cerr << "Wrong user name." << endl; + return false; + } + + DateTime aDTNew = pAction->GetDateTime(); + if (aDTNew <= aDT) + { + cerr << "Time stamp of the new revision should be more recent than that of the " + "last revision." + << endl; + return false; + } + + return true; + } + + } aTest; + + SvtUserOptions& rUserOpt = SC_MOD()->GetUserOptions(); + rUserOpt.SetToken(UserOptToken::FirstName, "Export"); + rUserOpt.SetToken(UserOptToken::LastName, "Test"); + + OUString aOwnerName = rUserOpt.GetFirstName() + " " + rUserOpt.GetLastName(); + + // First, test the xls variant. + + createScDoc("xls/track-changes/simple-cell-changes.xls"); + ScDocument* pDoc = getScDoc(); + bool bGood = aTest.check(*pDoc); + CPPUNIT_ASSERT_MESSAGE("Initial check failed (xls).", bGood); + + saveAndReload("MS Excel 97"); + pDoc = getScDoc(); + bGood = aTest.check(*pDoc); + CPPUNIT_ASSERT_MESSAGE("Check after reload failed (xls).", bGood); + + // fdo#81445 : Check the blank value string to make sure it's "<empty>". + ScChangeTrack* pCT = pDoc->GetChangeTrack(); + CPPUNIT_ASSERT(pCT); + ScChangeAction* pAction = pCT->GetAction(1); + CPPUNIT_ASSERT(pAction); + OUString aDesc = pAction->GetDescription(*pDoc); + CPPUNIT_ASSERT_EQUAL(OUString("Cell B2 changed from '<empty>' to '1'"), aDesc); + + pDoc = getScDoc(); + bGood = aTest.checkRevisionUserAndTime(*pDoc, aOwnerName); + CPPUNIT_ASSERT_MESSAGE("Check revision and time failed after reload (xls).", bGood); + + // Now, test the xlsx variant the same way. + + createScDoc("xlsx/track-changes/simple-cell-changes.xlsx"); + pDoc = getScDoc(); + aTest.check(*pDoc); + CPPUNIT_ASSERT_MESSAGE("Initial check failed (xlsx).", bGood); + + saveAndReload("Calc Office Open XML"); + pDoc = getScDoc(); + bGood = aTest.check(*pDoc); + CPPUNIT_ASSERT_MESSAGE("Check after reload failed (xlsx).", bGood); + + bGood = aTest.checkRevisionUserAndTime(*pDoc, aOwnerName); + CPPUNIT_ASSERT_MESSAGE("Check revision and time failed after reload (xlsx).", bGood); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testSheetTabColorsXLSX) +{ + struct + { + bool checkContent(ScDocument& rDoc) + { + std::vector<OUString> aTabNames = rDoc.GetAllTableNames(); + + // green, red, blue, yellow (from left to right). + if (aTabNames.size() != 4) + { + cerr << "There should be exactly 4 sheets." << endl; + return false; + } + + const char* pNames[] = { "Green", "Red", "Blue", "Yellow" }; + for (size_t i = 0; i < SAL_N_ELEMENTS(pNames); ++i) + { + OUString aExpected = OUString::createFromAscii(pNames[i]); + if (aExpected != aTabNames[i]) + { + cerr << "incorrect sheet name: expected='" << aExpected << "', actual='" + << aTabNames[i] << "'" << endl; + return false; + } + } + + static const Color aXclColors[] = { + 0x0000B050, // green + 0x00FF0000, // red + 0x000070C0, // blue + 0x00FFFF00, // yellow + }; + + for (size_t i = 0; i < SAL_N_ELEMENTS(aXclColors); ++i) + { + if (aXclColors[i] != rDoc.GetTabBgColor(i)) + { + cerr << "wrong sheet color for sheet " << i << endl; + return false; + } + } + + return true; + } + + } aTest; + + createScDoc("xlsx/sheet-tab-color.xlsx"); + { + ScDocument* pDoc = getScDoc(); + bool bRes = aTest.checkContent(*pDoc); + CPPUNIT_ASSERT_MESSAGE("Failed on the initial content check.", bRes); + } + + saveAndReload("Calc Office Open XML"); + ScDocument* pDoc = getScDoc(); + bool bRes = aTest.checkContent(*pDoc); + CPPUNIT_ASSERT_MESSAGE("Failed on the content check after reload.", bRes); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testTdf133487) +{ + createScDoc("fods/shapes_foreground_background.fods"); + + save("calc8"); + xmlDocUniquePtr pXmlDoc = parseExport("content.xml"); + CPPUNIT_ASSERT(pXmlDoc); + + // shape in background has lowest index + assertXPath(pXmlDoc, + "/office:document-content/office:body/office:spreadsheet/table:table[1]/" + "table:table-row[1]/table:table-cell[1]/draw:custom-shape", + "z-index", "0"); + assertXPath(pXmlDoc, + "/office:document-content/office:body/office:spreadsheet/table:table[1]/" + "table:table-row[1]/table:table-cell[1]/draw:custom-shape" + "/attribute::table:table-background", + 1); + assertXPath(pXmlDoc, + "/office:document-content/office:body/office:spreadsheet/table:table[1]/" + "table:table-row[1]/table:table-cell[1]/draw:custom-shape", + "table-background", "true"); + // shape in foreground, previously index 1 + assertXPath(pXmlDoc, + "/office:document-content/office:body/office:spreadsheet/table:table[1]/" + "table:table-row[1]/table:table-cell[2]/draw:custom-shape", + "z-index", "2"); + // attribute is only written for value "true" + assertXPath(pXmlDoc, + "/office:document-content/office:body/office:spreadsheet/table:table[1]/" + "table:table-row[1]/table:table-cell[2]/draw:custom-shape" + "/attribute::table:table-background", + 0); + // shape in foreground, previously index 0 + assertXPath(pXmlDoc, + "/office:document-content/office:body/office:spreadsheet/table:table[1]/" + "table:table-row[3]/table:table-cell[1]/draw:custom-shape", + "z-index", "1"); + // attribute is only written for value "true" + assertXPath(pXmlDoc, + "/office:document-content/office:body/office:spreadsheet/table:table[1]/" + "table:table-row[3]/table:table-cell[1]/draw:custom-shape" + "/attribute::table:table-background", + 0); + // shape in foreground, previously index 4 + assertXPath(pXmlDoc, + "/office:document-content/office:body/office:spreadsheet/table:table[1]/" + "table:shapes/draw:custom-shape", + "z-index", "3"); + // attribute is only written for value "true" + assertXPath(pXmlDoc, + "/office:document-content/office:body/office:spreadsheet/table:table[1]/" + "table:shapes/draw:custom-shape" + "/attribute::table:table-background", + 0); + // form control, previously index 3 + assertXPath(pXmlDoc, + "/office:document-content/office:body/office:spreadsheet/table:table[1]/" + "table:shapes/draw:control", + "z-index", "4"); + // attribute is only written for value "true" + assertXPath(pXmlDoc, + "/office:document-content/office:body/office:spreadsheet/table:table[1]/" + "table:shapes/draw:control" + "/attribute::table:table-background", + 0); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testSharedFormulaExportXLS) +{ + struct + { + bool checkContent(ScDocument& rDoc) + { + formula::FormulaGrammar::Grammar eGram = formula::FormulaGrammar::GRAM_ENGLISH_XL_R1C1; + FormulaGrammarSwitch aFGSwitch(&rDoc, eGram); + sc::TokenStringContext aCxt(rDoc, eGram); + + // Check the title row. + + OUString aActual = rDoc.GetString(0, 1, 0); + OUString aExpected = "Response"; + if (aActual != aExpected) + { + cerr << "Wrong content in A2: expected='" << aExpected << "', actual='" << aActual + << "'" << endl; + return false; + } + + aActual = rDoc.GetString(1, 1, 0); + aExpected = "Response"; + if (aActual != aExpected) + { + cerr << "Wrong content in B2: expected='" << aExpected << "', actual='" << aActual + << "'" << endl; + return false; + } + + // A3:A12 and B3:B12 are numbers from 1 to 10. + for (SCROW i = 0; i <= 9; ++i) + { + double fExpected = i + 1.0; + ScAddress aPos(0, i + 2, 0); + double fActual = rDoc.GetValue(aPos); + if (fExpected != fActual) + { + cerr << "Wrong value in A" << (i + 2) << ": expected=" << fExpected + << ", actual=" << fActual << endl; + return false; + } + + aPos.IncCol(); + ScFormulaCell* pFC = rDoc.GetFormulaCell(aPos); + if (!pFC) + { + cerr << "B" << (i + 2) << " should be a formula cell." << endl; + return false; + } + + OUString aFormula = pFC->GetCode()->CreateString(aCxt, aPos); + aExpected = "Coefficients!RC[-1]"; + if (aFormula != aExpected) + { + cerr << "Wrong formula in B" << (i + 2) << ": expected='" << aExpected + << "', actual='" << aFormula << "'" << endl; + return false; + } + + fActual = rDoc.GetValue(aPos); + if (fExpected != fActual) + { + cerr << "Wrong value in B" << (i + 2) << ": expected=" << fExpected + << ", actual=" << fActual << endl; + return false; + } + } + + return true; + } + + } aTest; + + createScDoc("ods/shared-formula/3d-reference.ods"); + { + // Check the content of the original. + ScDocument* pDoc = getScDoc(); + bool bRes = aTest.checkContent(*pDoc); + CPPUNIT_ASSERT_MESSAGE("Content check on the original document failed.", bRes); + } + + saveAndReload("MS Excel 97"); + + // Check the content of the reloaded. This should be identical. + ScDocument* pDoc = getScDoc(); + bool bRes = aTest.checkContent(*pDoc); + CPPUNIT_ASSERT_MESSAGE("Content check on the reloaded document failed.", bRes); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testSharedFormulaExportXLSX) +{ + struct + { + bool checkContent(ScDocument& rDoc) + { + SCTAB nTabCount = rDoc.GetTableCount(); + if (nTabCount != 2) + { + cerr << "Document should have exactly 2 sheets. " << nTabCount << " found." + << endl; + return false; + } + + // Make sure the sheet tab colors are not set. + for (SCROW i = 0; i <= 1; ++i) + { + Color aTabBgColor = rDoc.GetTabBgColor(i); + if (aTabBgColor != COL_AUTO) + { + cerr << "The tab color of Sheet " << (i + 1) << " should not be explicitly set." + << endl; + return false; + } + } + + // B2:B7 should show 1,2,3,4,5,6. + double fExpected = 1.0; + for (SCROW i = 1; i <= 6; ++i, ++fExpected) + { + ScAddress aPos(1, i, 0); + double fVal = rDoc.GetValue(aPos); + if (fVal != fExpected) + { + cerr << "Wrong value in B" << (i + 1) << ": expected=" << fExpected + << ", actual=" << fVal << endl; + return false; + } + } + + // C2:C7 should show 10,20,...,60. + fExpected = 10.0; + for (SCROW i = 1; i <= 6; ++i, fExpected += 10.0) + { + ScAddress aPos(2, i, 0); + double fVal = rDoc.GetValue(aPos); + if (fVal != fExpected) + { + cerr << "Wrong value in C" << (i + 1) << ": expected=" << fExpected + << ", actual=" << fVal << endl; + return false; + } + } + + // D2:D7 should show 1,2,...,6. + fExpected = 1.0; + for (SCROW i = 1; i <= 6; ++i, ++fExpected) + { + ScAddress aPos(3, i, 0); + double fVal = rDoc.GetValue(aPos); + if (fVal != fExpected) + { + cerr << "Wrong value in D" << (i + 1) << ": expected=" << fExpected + << ", actual=" << fVal << endl; + return false; + } + } + + return true; + } + + } aTest; + + createScDoc("xlsx/shared-formula/3d-reference.xlsx"); + { + ScDocument* pDoc = getScDoc(); + bool bRes = aTest.checkContent(*pDoc); + CPPUNIT_ASSERT_MESSAGE("Content check on the initial document failed.", bRes); + + pDoc->CalcAll(); // Recalculate to flush all cached results. + bRes = aTest.checkContent(*pDoc); + CPPUNIT_ASSERT_MESSAGE("Content check on the initial recalculated document failed.", bRes); + } + + // Save and reload, and check the content again. + saveAndReload("Calc Office Open XML"); + + ScDocument* pDoc = getScDoc(); + pDoc->CalcAll(); // Recalculate to flush all cached results. + + bool bRes = aTest.checkContent(*pDoc); + CPPUNIT_ASSERT_MESSAGE("Content check on the reloaded document failed.", bRes); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testSharedFormulaStringResultExportXLSX) +{ + struct + { + bool checkContent(ScDocument& rDoc) + { + { + // B2:B7 should show A,B,...,F. + const char* const expected[] = { "A", "B", "C", "D", "E", "F" }; + for (SCROW i = 0; i <= 5; ++i) + { + ScAddress aPos(1, i + 1, 0); + OUString aStr = rDoc.GetString(aPos); + OUString aExpected = OUString::createFromAscii(expected[i]); + if (aStr != aExpected) + { + cerr << "Wrong value in B" << (i + 2) << ": expected='" << aExpected + << "', actual='" << aStr << "'" << endl; + return false; + } + } + } + + { + // C2:C7 should show AA,BB,...,FF. + const char* const expected[] = { "AA", "BB", "CC", "DD", "EE", "FF" }; + for (SCROW i = 0; i <= 5; ++i) + { + ScAddress aPos(2, i + 1, 0); + OUString aStr = rDoc.GetString(aPos); + OUString aExpected = OUString::createFromAscii(expected[i]); + if (aStr != aExpected) + { + cerr << "Wrong value in C" << (i + 2) << ": expected='" << aExpected + << "', actual='" << aStr << "'" << endl; + return false; + } + } + } + + return true; + } + + } aTest; + + createScDoc("xlsx/shared-formula/text-results.xlsx"); + { + ScDocument* pDoc = getScDoc(); + + // Check content without re-calculation, to test cached formula results. + bool bRes = aTest.checkContent(*pDoc); + CPPUNIT_ASSERT_MESSAGE("Content check on the initial document failed.", bRes); + + // Now, re-calculate and check the results. + pDoc->CalcAll(); + bRes = aTest.checkContent(*pDoc); + CPPUNIT_ASSERT_MESSAGE("Content check on the initial recalculated document failed.", bRes); + } + // Reload and check again. + saveAndReload("Calc Office Open XML"); + ScDocument* pDoc = getScDoc(); + + bool bRes = aTest.checkContent(*pDoc); + CPPUNIT_ASSERT_MESSAGE("Content check on the reloaded document failed.", bRes); +} + +void ScExportTest3::testFunctionsExcel2010(const OUString& sFormatType) +{ + createScDoc("xlsx/functions-excel-2010.xlsx"); + + saveAndReload(sFormatType); + ScDocument* pDoc = getScDoc(); + pDoc->CalcAll(); // perform hard re-calculation. + + testFunctionsExcel2010_Impl(*pDoc); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testFunctionsExcel2010XLSX) +{ + testFunctionsExcel2010("Calc Office Open XML"); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testFunctionsExcel2010XLS) +{ + testFunctionsExcel2010("MS Excel 97"); +} + +void ScExportTest3::testCeilingFloor(const OUString& sFormatType) +{ + createScDoc("xlsx/ceiling-floor.xlsx"); + + saveAndReload(sFormatType); + ScDocument* pDoc = getScDoc(); + pDoc->CalcAll(); // perform hard re-calculation. + + testCeilingFloor_Impl(*pDoc); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testCeilingFloorXLSX) +{ + testCeilingFloor("Calc Office Open XML"); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testCeilingFloorODSToXLSX) +{ + // tdf#100011 - Cannot open sheet containing FLOOR/CEILING functions by MS Excel, after export to .xlsx + createScDoc("ods/ceiling-floor.ods"); + + save("Calc Office Open XML"); + xmlDocUniquePtr pSheet = parseExport("xl/workbook.xml"); + CPPUNIT_ASSERT(pSheet); + + // there shouldn't be any defined names during export of FLOOR and CEILING functions to .xlsx + assertXPath(pSheet, "/x:workbook/x:definedNames", 0); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testCeilingFloorXLS) { testCeilingFloor("MS Excel 97"); } + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testCeilingFloorODS) { testCeilingFloor("calc8"); } + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testCustomXml) +{ + // Load document and export it to a temporary file + createScDoc("xlsx/customxml.xlsx"); + + save("Calc Office Open XML"); + xmlDocUniquePtr pXmlDoc = parseExport("customXml/item1.xml"); + CPPUNIT_ASSERT(pXmlDoc); + xmlDocUniquePtr pRelsDoc = parseExport("customXml/_rels/item1.xml.rels"); + CPPUNIT_ASSERT(pRelsDoc); + + // Check there is a relation to itemProps1.xml. + assertXPath(pRelsDoc, "/rels:Relationships/rels:Relationship", 1); + assertXPath(pRelsDoc, "/rels:Relationships/rels:Relationship[@Id='rId1']", "Target", + "itemProps1.xml"); + + std::unique_ptr<SvStream> pStream = parseExportStream(maTempFile.GetURL(), "ddp/ddpfile.xen"); + CPPUNIT_ASSERT(pStream); +} + +#ifdef _WIN32 +static sal_Unicode lcl_getWindowsDrive(const OUString& aURL) +{ + static const sal_Int32 nMinLen = strlen("file:///X:/"); + if (aURL.getLength() <= nMinLen) + return 0; + const OUString aUrlStart = aURL.copy(0, nMinLen); + return (aUrlStart.startsWith("file:///") && aUrlStart.endsWith(":/")) ? aUrlStart[8] : 0; +} +#endif + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testRelativePathsODS) +{ + createScDoc("ods/fdo79305.ods"); + + save("calc8"); + xmlDocUniquePtr pDoc = parseExport("content.xml"); + CPPUNIT_ASSERT(pDoc); + OUString aURL = getXPath(pDoc, + "/office:document-content/office:body/office:spreadsheet/table:table/" + "table:table-row[2]/table:table-cell[2]/text:p/text:a", + "href"); +#ifdef _WIN32 + // if the exported document is not on the same drive then the linked document, + // there is no way to get a relative URL for the link, because ../X:/ is undefined. + if (!aURL.startsWith("..")) + { + sal_Unicode aDocDrive = lcl_getWindowsDrive(maTempFile.GetURL()); + sal_Unicode aLinkDrive = lcl_getWindowsDrive(aURL); + CPPUNIT_ASSERT_MESSAGE("document on the same drive but no relative link!", aDocDrive != 0); + CPPUNIT_ASSERT_MESSAGE("document on the same drive but no relative link!", aLinkDrive != 0); + CPPUNIT_ASSERT_MESSAGE("document on the same drive but no relative link!", + aDocDrive != aLinkDrive); + return; + } +#endif + // make sure that the URL is relative + CPPUNIT_ASSERT(aURL.startsWith("..")); +} + +namespace +{ +void testSheetProtection_Impl(ScDocument& rDoc) +{ + CPPUNIT_ASSERT(rDoc.IsTabProtected(0)); + const ScTableProtection* pTabProtection = rDoc.GetTabProtection(0); + CPPUNIT_ASSERT(pTabProtection); + CPPUNIT_ASSERT(pTabProtection->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS)); + CPPUNIT_ASSERT(!pTabProtection->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS)); +} +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testSheetProtectionODS) +{ + createScDoc("ods/sheet-protection.ods"); + + ScDocument* pDoc = getScDoc(); + + testSheetProtection_Impl(*pDoc); + + saveAndReload("calc8"); + + pDoc = getScDoc(); + + testSheetProtection_Impl(*pDoc); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testFunctionsExcel2010ODS) +{ + //testFunctionsExcel2010("calc8"); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testSwappedOutImageExport) +{ + std::vector<OUString> aFilterNames{ "calc8", "MS Excel 97", "Calc Office Open XML" }; + + // Set cache size to a very small value to make sure one of the images is swapped out + std::shared_ptr<comphelper::ConfigurationChanges> xBatch( + comphelper::ConfigurationChanges::create()); + officecfg::Office::Common::Cache::GraphicManager::TotalCacheSize::set(sal_Int32(1), xBatch); + xBatch->commit(); + + for (size_t i = 0; i < aFilterNames.size(); ++i) + { + // Check whether the export code swaps in the image which was swapped out before. + createScDoc("ods/document_with_two_images.ods"); + + const OString sFailedMessage + = OString::Concat("Failed on filter: ") + aFilterNames[i].toUtf8(); + + // Export the document and import again for a check + saveAndReload(aFilterNames[i]); + + // Check whether graphic exported well after it was swapped out + uno::Reference<sheet::XSpreadsheetDocument> xDoc(mxComponent, UNO_QUERY_THROW); + uno::Reference<container::XIndexAccess> xIA(xDoc->getSheets(), UNO_QUERY_THROW); + uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xIA->getByIndex(0), + UNO_QUERY_THROW); + uno::Reference<container::XIndexAccess> xDraws(xDrawPageSupplier->getDrawPage(), + UNO_QUERY_THROW); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(2), + xDraws->getCount()); + + uno::Reference<drawing::XShape> xImage(xDraws->getByIndex(0), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> XPropSet(xImage, uno::UNO_QUERY_THROW); + + // Check Graphic, Size + { + uno::Reference<graphic::XGraphic> xGraphic; + XPropSet->getPropertyValue("Graphic") >>= xGraphic; + CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xGraphic.is()); + CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), + xGraphic->getType() != graphic::GraphicType::EMPTY); + uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY); + CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xBitmap.is()); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(610), + xBitmap->getSize().Width); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(381), + xBitmap->getSize().Height); + } + // Second Image + xImage.set(xDraws->getByIndex(1), uno::UNO_QUERY); + XPropSet.set(xImage, uno::UNO_QUERY_THROW); + + // Check Graphic, Size + { + uno::Reference<graphic::XGraphic> xGraphic; + XPropSet->getPropertyValue("Graphic") >>= xGraphic; + CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xGraphic.is()); + CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), + xGraphic->getType() != graphic::GraphicType::EMPTY); + uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY); + CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xBitmap.is()); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(900), + xBitmap->getSize().Width); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(600), + xBitmap->getSize().Height); + } + } +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testSupBookVirtualPathXLS) +{ + createScDoc("xls/external-ref.xls"); + + saveAndReload("MS Excel 97"); + + ScDocument* pDoc = getScDoc(); + + OUString aFormula = pDoc->GetFormula(0, 0, 0); +#ifdef _WIN32 + aFormula = OUString::Concat(aFormula.subView(0, 9)) + aFormula.subView(12); + // strip drive letter, e.g. 'C:/' +#endif + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "Wrong SupBook VirtualPath URL", + OUString("='file:///home/timar/Documents/external.xls'#$Sheet1.A1"), aFormula); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testLinkedGraphicRT) +{ + // Problem was with linked images + std::vector<OUString> aFilterNames{ "calc8", "MS Excel 97", "Calc Office Open XML" }; + + for (size_t i = 0; i < aFilterNames.size(); ++i) + { + // Load the original file with one image + createScDoc("ods/document_with_linked_graphic.ods"); + const OString sFailedMessage + = OString::Concat("Failed on filter: ") + aFilterNames[i].toUtf8(); + + // Export the document and import again for a check + saveAndReload(aFilterNames[i]); + + // Check whether graphic imported well after export + ScDocument* pDoc = getScDoc(); + ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer(); + CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pDrawLayer != nullptr); + const SdrPage* pPage = pDrawLayer->GetPage(0); + CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pPage != nullptr); + SdrGrafObj* pObject = dynamic_cast<SdrGrafObj*>(pPage->GetObj(0)); + CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pObject != nullptr); + if (aFilterNames[i] == "Calc Office Open XML") + { + // FIXME: tdf#152036 + CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), !pObject->IsLinkedGraphic()); + } + else + CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pObject->IsLinkedGraphic()); + + const GraphicObject& rGraphicObj = pObject->GetGraphicObject(true); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), int(GraphicType::Bitmap), + int(rGraphicObj.GetGraphic().GetType())); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_uLong(864900), + rGraphicObj.GetGraphic().GetSizeBytes()); + } +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testImageWithSpecialID) +{ + std::vector<OUString> aFilterNames{ "calc8", "MS Excel 97", "Calc Office Open XML" }; + + // Trigger swap out mechanism to test swapped state factor too. + std::shared_ptr<comphelper::ConfigurationChanges> batch( + comphelper::ConfigurationChanges::create()); + officecfg::Office::Common::Cache::GraphicManager::TotalCacheSize::set(sal_Int32(1), batch); + batch->commit(); + + for (size_t i = 0; i < aFilterNames.size(); ++i) + { + createScDoc("ods/images_with_special_IDs.ods"); + + const OString sFailedMessage + = OString::Concat("Failed on filter: ") + aFilterNames[i].toUtf8(); + + // Export the document and import again for a check + saveAndReload(aFilterNames[i]); + + // Check whether graphic was exported well + uno::Reference<sheet::XSpreadsheetDocument> xDoc(mxComponent, UNO_QUERY_THROW); + uno::Reference<container::XIndexAccess> xIA(xDoc->getSheets(), UNO_QUERY_THROW); + uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xIA->getByIndex(0), + UNO_QUERY_THROW); + uno::Reference<container::XIndexAccess> xDraws(xDrawPageSupplier->getDrawPage(), + UNO_QUERY_THROW); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(2), + xDraws->getCount()); + + uno::Reference<drawing::XShape> xImage(xDraws->getByIndex(0), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> XPropSet(xImage, uno::UNO_QUERY_THROW); + + // Check Graphic, Size + { + uno::Reference<graphic::XGraphic> xGraphic; + XPropSet->getPropertyValue("Graphic") >>= xGraphic; + CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xGraphic.is()); + CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), + xGraphic->getType() != graphic::GraphicType::EMPTY); + uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY); + CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xBitmap.is()); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(610), + xBitmap->getSize().Width); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(381), + xBitmap->getSize().Height); + } + // Second Image + xImage.set(xDraws->getByIndex(1), uno::UNO_QUERY); + XPropSet.set(xImage, uno::UNO_QUERY_THROW); + + // Check Graphic, Size + { + uno::Reference<graphic::XGraphic> xGraphic; + XPropSet->getPropertyValue("Graphic") >>= xGraphic; + CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xGraphic.is()); + CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), + xGraphic->getType() != graphic::GraphicType::EMPTY); + uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY); + CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xBitmap.is()); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(900), + xBitmap->getSize().Width); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(600), + xBitmap->getSize().Height); + } + } +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testAbsNamedRangeHTML) +{ + setImportFilterName("calc_HTML_WebQuery"); + createScDoc("html/numberformat.html"); + ScDocShell* pDocSh = getScDocShell(); + pDocSh->DoHardRecalc(); + + //reset import filter + setImportFilterName("calc8"); + saveAndReload("calc8"); + pDocSh = getScDocShell(); + pDocSh->DoHardRecalc(); + + ScDocument* pDoc = getScDoc(); + ScRangeData* pRangeData = pDoc->GetRangeName()->findByUpperName(OUString("HTML_1")); + ScSingleRefData* pRef = pRangeData->GetCode()->FirstToken()->GetSingleRef(); + // see tdf#119141 for the reason why this isn't Sheet1.HTML_1 + CPPUNIT_ASSERT_MESSAGE("HTML_1 is an absolute reference", !pRef->IsTabRel()); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testTdf80149) +{ + createScDoc("csv/tdf80149.csv"); + ScDocShell* pDocSh = getScDocShell(); + pDocSh->DoHardRecalc(); + saveAndReload("Calc Office Open XML"); + pDocSh = getScDocShell(); + pDocSh->DoHardRecalc(); + + ScDocument* pDoc = getScDoc(); + CPPUNIT_ASSERT_EQUAL(OUString("row 1"), pDoc->GetString(0, 0, 0)); + + // Without the fix in place, this test would have failed with + // - Expected: Character 0x16 is here ->><<-- + // - Actual : + CPPUNIT_ASSERT_EQUAL(OUString("Character 0x16 is here ->><<--"), pDoc->GetString(1, 0, 0)); + CPPUNIT_ASSERT_EQUAL(OUString("File opens in libre office, but can't be saved as xlsx"), + pDoc->GetString(2, 0, 0)); + CPPUNIT_ASSERT_EQUAL(OUString("row 2"), pDoc->GetString(0, 1, 0)); + CPPUNIT_ASSERT_EQUAL(OUString("Subsequent rows get truncated"), pDoc->GetString(1, 1, 0)); + CPPUNIT_ASSERT_EQUAL(OUString("This cell goes missing"), pDoc->GetString(2, 1, 0)); + CPPUNIT_ASSERT_EQUAL(OUString("row 3"), pDoc->GetString(0, 2, 0)); + CPPUNIT_ASSERT_EQUAL(OUString("Subsequent rows get truncated"), pDoc->GetString(1, 2, 0)); + CPPUNIT_ASSERT_EQUAL(OUString("This cell goes missing"), pDoc->GetString(2, 2, 0)); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testSheetLocalRangeNameXLS) +{ + createScDoc("xls/named-ranges-local.xls"); + ScDocShell* pDocSh = getScDocShell(); + pDocSh->DoHardRecalc(); + saveAndReload("MS Excel 97"); + pDocSh = getScDocShell(); + pDocSh->DoHardRecalc(); + + ScDocument* pDoc = getScDoc(); + ScRangeName* pRangeName = pDoc->GetRangeName(0); + CPPUNIT_ASSERT(pRangeName); + CPPUNIT_ASSERT_EQUAL(size_t(2), pRangeName->size()); + + OUString aFormula = pDoc->GetFormula(3, 11, 0); + CPPUNIT_ASSERT_EQUAL(OUString("=SUM(local_name2)"), aFormula); + ASSERT_DOUBLES_EQUAL(14.0, pDoc->GetValue(3, 11, 0)); + + aFormula = pDoc->GetFormula(6, 4, 0); + CPPUNIT_ASSERT_EQUAL(OUString("=local_name1"), aFormula); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testRelativeNamedExpressionsXLS) +{ + createScDoc("ods/tdf113991_relativeNamedRanges.ods"); + ScDocShell* pDocSh = getScDocShell(); + pDocSh->DoHardRecalc(); + saveAndReload("MS Excel 97"); + pDocSh = getScDocShell(); + pDocSh->DoHardRecalc(); + + ScDocument* pDoc = getScDoc(); + // Sheet1:G3 + ScAddress aPos(6, 2, 0); + CPPUNIT_ASSERT_EQUAL(1.0, pDoc->GetValue(aPos)); + CPPUNIT_ASSERT_EQUAL(OUString("=single_cell_A3"), + pDoc->GetFormula(aPos.Col(), aPos.Row(), aPos.Tab())); + // Sheet2:F6 + aPos = ScAddress(5, 5, 1); + CPPUNIT_ASSERT_EQUAL(18.0, pDoc->GetValue(aPos)); + CPPUNIT_ASSERT_EQUAL(OUString("=SUM(test_conflict)"), + pDoc->GetFormula(aPos.Col(), aPos.Row(), aPos.Tab())); + // Sheet2:H3 + aPos = ScAddress(7, 2, 1); + CPPUNIT_ASSERT_EQUAL(10.0, pDoc->GetValue(aPos)); + CPPUNIT_ASSERT_EQUAL(OUString("=single_global_A3"), + pDoc->GetFormula(aPos.Col(), aPos.Row(), aPos.Tab())); + // Sheet2:H6 + aPos = ScAddress(7, 5, 1); + CPPUNIT_ASSERT_EQUAL(75.0, pDoc->GetValue(aPos)); + CPPUNIT_ASSERT_EQUAL(OUString("=SUM(A6:F6)"), + pDoc->GetFormula(aPos.Col(), aPos.Row(), aPos.Tab())); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testSheetTextBoxHyperlinkXLSX) +{ + createScDoc("xlsx/textbox-hyperlink.xlsx"); + + save("Calc Office Open XML"); + xmlDocUniquePtr pDoc = parseExport("xl/drawings/drawing1.xml"); + CPPUNIT_ASSERT(pDoc); + + assertXPath( + pDoc, + "/xdr:wsDr[1]/xdr:twoCellAnchor[1]/xdr:sp[1]/xdr:nvSpPr[1]/xdr:cNvPr[1]/a:hlinkClick[1]", + 1); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testFontSizeXLSX) +{ + createScDoc("xlsx/fontSize.xlsx"); + + save("Calc Office Open XML"); + xmlDocUniquePtr pDoc = parseExport("xl/drawings/drawing1.xml"); + CPPUNIT_ASSERT(pDoc); + OUString fontSize = getXPath( + pDoc, "/xdr:wsDr/xdr:twoCellAnchor/xdr:sp[1]/xdr:txBody/a:p[1]/a:r[1]/a:rPr", "sz"); + // make sure that the font size is 18 + CPPUNIT_ASSERT_EQUAL(OUString("1800"), fontSize); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testSheetCharacterKerningSpaceXLSX) +{ + createScDoc("xlsx/textbox-CharKerningSpace.xlsx"); + + saveAndReload("Calc Office Open XML"); + + save("Calc Office Open XML"); + xmlDocUniquePtr pDoc = parseExport("xl/drawings/drawing1.xml"); + CPPUNIT_ASSERT(pDoc); + + OUString CharKerningSpace = getXPath( + pDoc, "/xdr:wsDr[1]/xdr:twoCellAnchor[1]/xdr:sp[1]/xdr:txBody[1]/a:p[1]/a:r[1]/a:rPr[1]", + "spc"); + + // make sure that the CharKerning is 1997. + CPPUNIT_ASSERT_EQUAL(OUString("1997"), CharKerningSpace); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testSheetCondensedCharacterSpaceXLSX) +{ + createScDoc("xlsx/textbox-CondensedCharacterSpace.xlsx"); + + save("Calc Office Open XML"); + xmlDocUniquePtr pDoc = parseExport("xl/drawings/drawing1.xml"); + CPPUNIT_ASSERT(pDoc); + + OUString CondensedCharSpace = getXPath( + pDoc, "/xdr:wsDr[1]/xdr:twoCellAnchor[1]/xdr:sp[1]/xdr:txBody[1]/a:p[1]/a:r[1]/a:rPr[1]", + "spc"); + + // make sure that the CondensedCharSpace is -1002. + CPPUNIT_ASSERT_EQUAL(OUString("-1002"), CondensedCharSpace); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testTextUnderlineColorXLSX) +{ + createScDoc("xlsx/underlineColor.xlsx"); + + save("Calc Office Open XML"); + xmlDocUniquePtr pDoc = parseExport("xl/drawings/drawing1.xml"); + CPPUNIT_ASSERT(pDoc); + // Make sure the underline type is double line + assertXPath(pDoc, "/xdr:wsDr/xdr:twoCellAnchor[1]/xdr:sp[1]/xdr:txBody/a:p[1]/a:r[1]/a:rPr", + "u", "dbl"); + + assertXPath(pDoc, "/xdr:wsDr/xdr:twoCellAnchor[1]/xdr:sp[1]/xdr:txBody/a:p[1]/a:r[1]/a:rPr", + "b", "1"); + // Make sure that the underline color is RED + assertXPath(pDoc, + "/xdr:wsDr/xdr:twoCellAnchor[1]/xdr:sp[1]/xdr:txBody/a:p[1]/a:r[1]/a:rPr/a:uFill/" + "a:solidFill/a:srgbClr", + "val", "ff0000"); + + // Make sure the underline type is drawn with heavy line + assertXPath(pDoc, "/xdr:wsDr/xdr:twoCellAnchor[2]/xdr:sp[1]/xdr:txBody/a:p[1]/a:r[1]/a:rPr", + "u", "heavy"); + // tdf#104219 Make sure that uFill is not existing and uFillTx is set. + // It mean that color is automatic, should be the same color as the text. + assertXPath( + pDoc, "/xdr:wsDr/xdr:twoCellAnchor[2]/xdr:sp[1]/xdr:txBody/a:p[1]/a:r[1]/a:rPr/a:uFill", 0); + assertXPath(pDoc, + "/xdr:wsDr/xdr:twoCellAnchor[2]/xdr:sp[1]/xdr:txBody/a:p[1]/a:r[1]/a:rPr/a:uFillTx", + 1); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testSheetRunParagraphPropertyXLSX) +{ + createScDoc("xlsx/TextColor.xlsx"); + + save("Calc Office Open XML"); + xmlDocUniquePtr pDoc = parseExport("xl/sharedStrings.xml"); + CPPUNIT_ASSERT(pDoc); + + OUString aColor = getXPath(pDoc, "/x:sst/x:si/x:r[1]/x:rPr[1]/x:color", "rgb"); + CPPUNIT_ASSERT_EQUAL(OUString("FFFF0000"), aColor); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testPreserveTextWhitespaceXLSX) +{ + createScDoc("xlsx/preserve-whitespace.xlsx"); + + save("Calc Office Open XML"); + xmlDocUniquePtr pDoc = parseExport("xl/sharedStrings.xml"); + CPPUNIT_ASSERT(pDoc); + assertXPath(pDoc, "/x:sst/x:si/x:t", "space", "preserve"); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testPreserveTextWhitespace2XLSX) +{ + createScDoc("xlsx/preserve_space.xlsx"); + + save("Calc Office Open XML"); + xmlDocUniquePtr pDoc = parseExport("xl/sharedStrings.xml"); + CPPUNIT_ASSERT(pDoc); + assertXPath(pDoc, "/x:sst/x:si[1]/x:t", "space", "preserve"); + assertXPath(pDoc, "/x:sst/x:si[2]/x:r[1]/x:t", "space", "preserve"); + assertXPath(pDoc, "/x:sst/x:si[2]/x:r[2]/x:t", "space", "preserve"); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testHiddenShapeXLS) +{ + createScDoc("xls/hiddenShape.xls"); + + ScDocument* pDoc = getScDoc(); + CPPUNIT_ASSERT(pDoc->GetTableCount() > 0); + ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer(); + SdrPage* pPage = pDrawLayer->GetPage(0); + CPPUNIT_ASSERT(pPage); + SdrObject* pObj = pPage->GetObj(0); + CPPUNIT_ASSERT(pObj); + CPPUNIT_ASSERT_MESSAGE("Drawing object should not be visible.", !pObj->IsVisible()); + CPPUNIT_ASSERT_MESSAGE("Drawing object should not be printable.", !pObj->IsPrintable()); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testHiddenShapeXLSX) +{ + createScDoc("xlsx/hiddenShape.xlsx"); + + ScDocument* pDoc = getScDoc(); + CPPUNIT_ASSERT(pDoc->GetTableCount() > 0); + ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer(); + SdrPage* pPage = pDrawLayer->GetPage(0); + CPPUNIT_ASSERT(pPage); + SdrObject* pObj = pPage->GetObj(0); + CPPUNIT_ASSERT(pObj); + CPPUNIT_ASSERT_MESSAGE("Drawing object should not be visible.", !pObj->IsVisible()); + CPPUNIT_ASSERT_MESSAGE("Drawing object should not be printable.", !pObj->IsPrintable()); + + save("Calc Office Open XML"); + xmlDocUniquePtr pDocXml = parseExport("xl/drawings/drawing1.xml"); + CPPUNIT_ASSERT(pDocXml); + assertXPath(pDocXml, "/xdr:wsDr/xdr:twoCellAnchor/xdr:sp[1]/xdr:nvSpPr/xdr:cNvPr", "hidden", + "1"); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testShapeAutofitXLSX) +{ + createScDoc("xlsx/testShapeAutofit.xlsx"); + + save("Calc Office Open XML"); + xmlDocUniquePtr pDoc = parseExport("xl/drawings/drawing1.xml"); + CPPUNIT_ASSERT(pDoc); + + // TextAutoGrowHeight --> "Fit height to text" / "Resize shape to fit text" --> true + assertXPath(pDoc, "/xdr:wsDr/xdr:twoCellAnchor[1]/xdr:sp/xdr:txBody/a:bodyPr/a:spAutoFit", 1); + // TextAutoGrowHeight --> "Fit height to text" / "Resize shape to fit text" --> false + assertXPath(pDoc, "/xdr:wsDr/xdr:twoCellAnchor[2]/xdr:sp/xdr:txBody/a:bodyPr/a:noAutofit", 1); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testHyperlinkXLSX) +{ + createScDoc("xlsx/hyperlink.xlsx"); + + save("Calc Office Open XML"); + xmlDocUniquePtr pDoc = parseExport("xl/drawings/_rels/drawing1.xml.rels"); + CPPUNIT_ASSERT(pDoc); + assertXPath(pDoc, "/rels:Relationships/rels:Relationship", "Target", "#Sheet2!A1"); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testMoveCellAnchoredShapesODS) +{ + createScDoc("ods/move-cell-anchored-shapes.ods"); + + // There are two cell-anchored objects on the first sheet. + ScDocument* pDoc = getScDoc(); + + CPPUNIT_ASSERT_MESSAGE("There should be at least one sheet.", pDoc->GetTableCount() > 0); + + ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer(); + SdrPage* pPage = pDrawLayer->GetPage(0); + CPPUNIT_ASSERT_MESSAGE("draw page for sheet 1 should exist.", pPage); + SdrObject* pObj = pPage->GetObj(0); + CPPUNIT_ASSERT_MESSAGE("Failed to get drawing object.", pObj); + + // Check cell anchor state + ScAnchorType oldType = ScDrawLayer::GetAnchorType(*pObj); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Failed to get anchor type", SCA_CELL_RESIZE, oldType); + + // Get anchor data + ScDrawObjData* pData = ScDrawLayer::GetObjData(pObj); + CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData); + CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", + !pData->getShapeRect().IsEmpty()); + + ScAddress aDataStart = pData->maStart; + ScAddress aDataEnd = pData->maEnd; + + // Get non rotated anchor data + ScDrawObjData* pNData = ScDrawLayer::GetNonRotatedObjData(pObj); + CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData); + CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", + !pNData->getShapeRect().IsEmpty()); + + ScAddress aNDataStart = pNData->maStart; + ScAddress aNDataEnd = pNData->maEnd; + CPPUNIT_ASSERT_EQUAL(aDataStart, aNDataStart); + CPPUNIT_ASSERT_EQUAL(aDataEnd, aNDataEnd); + + // Insert 2 rows. + pDoc->InsertRow(ScRange(0, aDataStart.Row() - 1, 0, pDoc->MaxCol(), aDataStart.Row(), 0)); + + // Get anchor data + pData = ScDrawLayer::GetObjData(pObj); + CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData); + CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", + !pData->getShapeRect().IsEmpty()); + + // Get non rotated anchor data + pNData = ScDrawLayer::GetNonRotatedObjData(pObj); + CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData); + CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", + !pNData->getShapeRect().IsEmpty()); + + // Check if data has moved to new rows + CPPUNIT_ASSERT_EQUAL(pData->maStart.Row(), aDataStart.Row() + 2); + CPPUNIT_ASSERT_EQUAL(pData->maEnd.Row(), aDataEnd.Row() + 2); + + CPPUNIT_ASSERT_EQUAL(pNData->maStart.Row(), aNDataStart.Row() + 2); + CPPUNIT_ASSERT_EQUAL(pNData->maEnd.Row(), aNDataEnd.Row() + 2); + + // Save the anchor data + aDataStart = pData->maStart; + aDataEnd = pData->maEnd; + aNDataStart = pNData->maStart; + aNDataEnd = pNData->maEnd; + + // Save the document and load again to check anchor persist + saveAndReload("calc8"); + + // There are two cell-anchored objects on the first sheet. + pDoc = getScDoc(); + + CPPUNIT_ASSERT_MESSAGE("There should be at least one sheet.", pDoc->GetTableCount() > 0); + + pDrawLayer = pDoc->GetDrawLayer(); + pPage = pDrawLayer->GetPage(0); + CPPUNIT_ASSERT_MESSAGE("draw page for sheet 1 should exist.", pPage); + pObj = pPage->GetObj(0); + CPPUNIT_ASSERT_MESSAGE("Failed to get drawing object.", pObj); + + // Check cell anchor state + oldType = ScDrawLayer::GetAnchorType(*pObj); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Failed to get anchor type", SCA_CELL_RESIZE, oldType); + + // Get anchor data + pData = ScDrawLayer::GetObjData(pObj); + CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData); + CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", + !pData->getShapeRect().IsEmpty()); + + // Get non rotated anchor data + pNData = ScDrawLayer::GetNonRotatedObjData(pObj); + CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData); + CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", + !pNData->getShapeRect().IsEmpty()); + + // Check if data after save it + CPPUNIT_ASSERT_EQUAL(pData->maStart, aDataStart); + CPPUNIT_ASSERT_EQUAL(pData->maEnd, aDataEnd); + + CPPUNIT_ASSERT_EQUAL(pNData->maStart, aNDataStart); + CPPUNIT_ASSERT_EQUAL(pNData->maEnd, aNDataEnd); + + // Insert a column. + pDoc->InsertCol(ScRange(aDataStart.Col(), 0, 0, aDataStart.Col(), pDoc->MaxRow(), 0)); + + // Get anchor data + pData = ScDrawLayer::GetObjData(pObj); + CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData); + CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", + !pData->getShapeRect().IsEmpty()); + + // Get non rotated anchor data + pNData = ScDrawLayer::GetNonRotatedObjData(pObj); + CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData); + CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", + !pNData->getShapeRect().IsEmpty()); + + // Check if data has moved to new rows + CPPUNIT_ASSERT_EQUAL(pData->maStart.Col(), SCCOL(aDataStart.Col() + 1)); + CPPUNIT_ASSERT_EQUAL(pData->maEnd.Col(), SCCOL(aDataEnd.Col() + 1)); + + CPPUNIT_ASSERT_EQUAL(pNData->maStart.Col(), SCCOL(aNDataStart.Col() + 1)); + CPPUNIT_ASSERT_EQUAL(pNData->maEnd.Col(), SCCOL(aNDataEnd.Col() + 1)); + + // Save the anchor data + aDataStart = pData->maStart; + aDataEnd = pData->maEnd; + aNDataStart = pNData->maStart; + aNDataEnd = pNData->maEnd; + + // Save the document and load again to check anchor persist + saveAndReload("calc8"); + + // There are two cell-anchored objects on the first sheet. + pDoc = getScDoc(); + + CPPUNIT_ASSERT_MESSAGE("There should be at least one sheet.", pDoc->GetTableCount() > 0); + + pDrawLayer = pDoc->GetDrawLayer(); + pPage = pDrawLayer->GetPage(0); + CPPUNIT_ASSERT_MESSAGE("draw page for sheet 1 should exist.", pPage); + pObj = pPage->GetObj(0); + CPPUNIT_ASSERT_MESSAGE("Failed to get drawing object.", pObj); + + // Check cell anchor state + oldType = ScDrawLayer::GetAnchorType(*pObj); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Failed to get anchor type", SCA_CELL_RESIZE, oldType); + + // Get anchor data + pData = ScDrawLayer::GetObjData(pObj); + CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData); + CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", + !pData->getShapeRect().IsEmpty()); + + // Get non rotated anchor data + pNData = ScDrawLayer::GetNonRotatedObjData(pObj); + CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData); + CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", + !pNData->getShapeRect().IsEmpty()); + + // Check if data after save it + CPPUNIT_ASSERT_EQUAL(pData->maStart, aDataStart); + CPPUNIT_ASSERT_EQUAL(pData->maEnd, aDataEnd); + + CPPUNIT_ASSERT_EQUAL(pNData->maStart, aNDataStart); + CPPUNIT_ASSERT_EQUAL(pNData->maEnd, aNDataEnd); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testConditionalFormatRangeListXLSX) +{ + createScDoc("ods/conditionalformat_rangelist.ods"); + save("Calc Office Open XML"); + xmlDocUniquePtr pDoc = parseExport("xl/worksheets/sheet1.xml"); + CPPUNIT_ASSERT(pDoc); + assertXPath(pDoc, "//x:conditionalFormatting", "sqref", "F4 F10"); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testConditionalFormatContainsTextXLSX) +{ + createScDoc("ods/conditionalformat_containstext.ods"); + save("Calc Office Open XML"); + xmlDocUniquePtr pDoc = parseExport("xl/worksheets/sheet1.xml"); + CPPUNIT_ASSERT(pDoc); + assertXPathContent(pDoc, "//x:conditionalFormatting/x:cfRule/x:formula", + "NOT(ISERROR(SEARCH(\"test\",A1)))"); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testConditionalFormatPriorityCheckXLSX) +{ + createScDoc("xlsx/conditional_fmt_checkpriority.xlsx"); + save("Calc Office Open XML"); + xmlDocUniquePtr pDoc = parseExport("xl/worksheets/sheet1.xml"); + CPPUNIT_ASSERT(pDoc); + constexpr bool bHighPriorityExtensionA1 + = true; // Should A1's extension cfRule has higher priority than normal cfRule ? + constexpr bool bHighPriorityExtensionA3 + = false; // Should A3's extension cfRule has higher priority than normal cfRule ? + size_t nA1NormalPriority = 0; + size_t nA1ExtPriority = 0; + size_t nA3NormalPriority = 0; + size_t nA3ExtPriority = 0; + for (size_t nIdx = 1; nIdx <= 2; ++nIdx) + { + OString aIdx = OString::number(nIdx); + OUString aCellAddr = getXPath(pDoc, "//x:conditionalFormatting[" + aIdx + "]", "sqref"); + OUString aPriority + = getXPath(pDoc, "//x:conditionalFormatting[" + aIdx + "]/x:cfRule", "priority"); + CPPUNIT_ASSERT_MESSAGE("conditionalFormatting sqref must be either A1 or A3", + aCellAddr == "A1" || aCellAddr == "A3"); + if (aCellAddr == "A1") + nA1NormalPriority = aPriority.toUInt32(); + else + nA3NormalPriority = aPriority.toUInt32(); + aCellAddr = getXPathContent( + pDoc, "//x:extLst/x:ext[1]/x14:conditionalFormattings/x14:conditionalFormatting[" + aIdx + + "]/xm:sqref"); + aPriority + = getXPath(pDoc, + "//x:extLst/x:ext[1]/x14:conditionalFormattings/x14:conditionalFormatting[" + + aIdx + "]/x14:cfRule", + "priority"); + CPPUNIT_ASSERT_MESSAGE("x14:conditionalFormatting sqref must be either A1 or A3", + aCellAddr == "A1" || aCellAddr == "A3"); + if (aCellAddr == "A1") + nA1ExtPriority = aPriority.toUInt32(); + else + nA3ExtPriority = aPriority.toUInt32(); + } + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong priorities for A1", bHighPriorityExtensionA1, + nA1ExtPriority < nA1NormalPriority); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong priorities for A3", bHighPriorityExtensionA3, + nA3ExtPriority < nA3NormalPriority); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testConditionalFormatOriginXLSX) +{ + createScDoc("xlsx/conditional_fmt_origin.xlsx"); + save("Calc Office Open XML"); + xmlDocUniquePtr pDoc = parseExport("xl/worksheets/sheet1.xml"); + CPPUNIT_ASSERT(pDoc); + // tdf#124953 : The range-list is B3:C6 F1:G2, origin address in the formula should be B1, not B3. + OUString aFormula = getXPathContent(pDoc, "//x:conditionalFormatting/x:cfRule/x:formula"); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong origin address in formula", + OUString("NOT(ISERROR(SEARCH(\"BAC\",B1)))"), aFormula); +} + +// FILESAVE: XLSX export with long sheet names (length > 31 characters) +CPPUNIT_TEST_FIXTURE(ScExportTest3, testTdf79998) +{ + // check: original document has tab name > 31 characters + createScDoc("ods/tdf79998.ods"); + ScDocument* pDoc = getScDoc(); + const std::vector<OUString> aTabNames1 = pDoc->GetAllTableNames(); + CPPUNIT_ASSERT_EQUAL(OUString("Utilities (FX Kurse, Kreditkarten etc)"), aTabNames1[1]); + + // check: saved XLSX document has truncated tab name + saveAndReload("Calc Office Open XML"); + pDoc = getScDoc(); + const std::vector<OUString> aTabNames2 = pDoc->GetAllTableNames(); + CPPUNIT_ASSERT_EQUAL(OUString("Utilities (FX Kurse, Kreditkart"), aTabNames2[1]); +} + +static void impl_testLegacyCellAnchoredRotatedShape(ScDocument& rDoc, const tools::Rectangle& aRect, + const ScDrawObjData& aAnchor, + tools::Long TOLERANCE = 30 /* 30 hmm */) +{ + ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer(); + CPPUNIT_ASSERT_MESSAGE("No drawing layer.", pDrawLayer); + SdrPage* pPage = pDrawLayer->GetPage(0); + CPPUNIT_ASSERT_MESSAGE("No page instance for the 1st sheet.", pPage); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pPage->GetObjCount()); + + SdrObject* pObj = pPage->GetObj(0); + const tools::Rectangle& aSnap = pObj->GetSnapRect(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(aRect.GetHeight(), aSnap.GetHeight(), TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL(aRect.GetWidth(), aSnap.GetWidth(), TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL(aRect.Left(), aSnap.Left(), TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL(aRect.Top(), aSnap.Top(), TOLERANCE); + + ScDrawObjData* pData = ScDrawLayer::GetObjData(pObj); + CPPUNIT_ASSERT_MESSAGE("expected object meta data", pData); + CPPUNIT_ASSERT_EQUAL(aAnchor.maStart.Row(), pData->maStart.Row()); + CPPUNIT_ASSERT_EQUAL(aAnchor.maStart.Col(), pData->maStart.Col()); + CPPUNIT_ASSERT_EQUAL(aAnchor.maEnd.Row(), pData->maEnd.Row()); + CPPUNIT_ASSERT_EQUAL(aAnchor.maEnd.Col(), pData->maEnd.Col()); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testLegacyCellAnchoredRotatedShape) +{ + { + // This example doc contains cell anchored shape that is rotated, the + // rotated shape is in fact clipped by the sheet boundaries (and thus + // is a good edge case test to see if we import it still correctly) + createScDoc("ods/legacycellanchoredrotatedclippedshape.ods"); + + ScDocument* pDoc = getScDoc(); + // ensure the imported legacy rotated shape is in the expected position + tools::Rectangle aRect(6000, -2000, 8000, 4000); + // ensure the imported ( and converted ) anchor ( note we internally now store the anchor in + // terms of the rotated shape ) is more or less contains the correct info + ScDrawObjData aAnchor; + aAnchor.maStart.SetRow(0); + aAnchor.maStart.SetCol(5); + aAnchor.maEnd.SetRow(3); + aAnchor.maEnd.SetCol(7); + impl_testLegacyCellAnchoredRotatedShape(*pDoc, aRect, aAnchor); + // test save and reload + // for some reason having this test in subsequent_export-test.cxx causes + // a core dump in editeng ( so moved to here ) + saveAndReload("calc8"); + pDoc = getScDoc(); + impl_testLegacyCellAnchoredRotatedShape(*pDoc, aRect, aAnchor); + } + { + // This example doc contains cell anchored shape that is rotated, the + // rotated shape is in fact clipped by the sheet boundaries, additionally + // the shape is completely hidden because the rows the shape occupies + // are hidden + createScDoc("ods/legacycellanchoredrotatedhiddenshape.ods"); + ScDocument* pDoc = getScDoc(); + // ensure the imported legacy rotated shape is in the expected position + tools::Rectangle aRect(6000, -2000, 8000, 4000); + + // ensure the imported (and converted) anchor (note we internally now store the anchor in + // terms of the rotated shape) is more or less contains the correct info + ScDrawObjData aAnchor; + aAnchor.maStart.SetRow(0); + aAnchor.maStart.SetCol(5); + aAnchor.maEnd.SetRow(3); + aAnchor.maEnd.SetCol(7); + pDoc->ShowRows(0, 9, 0, true); // show relevant rows + pDoc->SetDrawPageSize(0); // trigger recalcpos + impl_testLegacyCellAnchoredRotatedShape(*pDoc, aRect, aAnchor); + // test save and reload + saveAndReload("calc8"); + pDoc = getScDoc(); + impl_testLegacyCellAnchoredRotatedShape(*pDoc, aRect, aAnchor); + } + { + // This example doc contains cell anchored shape that is rotated + createScDoc("ods/legacycellanchoredrotatedshape.ods"); + + ScDocument* pDoc = getScDoc(); + // ensure the imported legacy rotated shape is in the expected position + tools::Rectangle aRect(6000, 3000, 8000, 9000); + // ensure the imported (and converted) anchor (note we internally now store the anchor in + // terms of the rotated shape) more or less contains the correct info + + ScDrawObjData aAnchor; + aAnchor.maStart.SetRow(3); + aAnchor.maStart.SetCol(6); + aAnchor.maEnd.SetRow(9); + aAnchor.maEnd.SetCol(8); + // test import + impl_testLegacyCellAnchoredRotatedShape(*pDoc, aRect, aAnchor); + // test save and reload + saveAndReload("calc8"); + pDoc = getScDoc(); + impl_testLegacyCellAnchoredRotatedShape(*pDoc, aRect, aAnchor); + } +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testTdf113646) +{ + createScDoc("ods/tdf113646.ods"); + + save("Calc Office Open XML"); + xmlDocUniquePtr pSheet = parseExport("xl/styles.xml"); + CPPUNIT_ASSERT(pSheet); + + assertXPath(pSheet, "/x:styleSheet/x:dxfs/x:dxf/x:font/x:sz", "val", "36"); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testDateStandardfilterXLSX) +{ + // XLSX Roundtripping standard filter with date + createScDoc("ods/tdf142607.ods"); + + save("Calc Office Open XML"); + xmlDocUniquePtr pDoc = parseExport("xl/worksheets/sheet1.xml"); + CPPUNIT_ASSERT(pDoc); + + assertXPath(pDoc, "//x:autoFilter", "ref", "A1:B6"); + assertXPath(pDoc, "//x:autoFilter/x:filterColumn/x:filters/x:dateGroupItem[1]", "day", "03"); + assertXPath(pDoc, "//x:autoFilter/x:filterColumn/x:filters/x:dateGroupItem[1]", "month", "12"); + assertXPath(pDoc, "//x:autoFilter/x:filterColumn/x:filters/x:dateGroupItem[1]", "year", "2011"); + assertXPath(pDoc, "//x:autoFilter/x:filterColumn/x:filters/x:dateGroupItem[1]", + "dateTimeGrouping", "day"); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testNumberFormatODS) +{ + createScDoc("ods/testNumberFormats.ods"); + saveAndReload("calc8"); + ScDocument* pDoc = getScDoc(); + sal_uInt32 nNumberFormat; + const sal_Int32 nCountFormats = 18; + const OUString aExpectedFormatStr[nCountFormats] + = { "\"format=\"000000", "\"format=\"??????", "\"format=\"??0000", + "\"format=\"000,000", "\"format=\"???,???", "\"format=\"??0,000", + "\"format=\"000\" \"?/?", "\"format=\"???\" \"?/?", "\"format=\"?00\" \"?/?", + "\"format=\"0,000\" \"?/?", "\"format=\"?,???\" \"?/?", "\"format=\"?,?00\" \"?/?", + "\"format=\"0.000E+00", "\"format=\"?.###E+00", "\"format=\"?.0##E+00", + "\"format=\"000E+00", "\"format=\"???E+00", "\"format=\"?00E+00" }; + for (sal_Int32 i = 0; i < nCountFormats; i++) + { + nNumberFormat = pDoc->GetNumberFormat(i + 1, 2, 0); + const SvNumberformat* pNumberFormat = pDoc->GetFormatTable()->GetEntry(nNumberFormat); + const OUString& rFormatStr = pNumberFormat->GetFormatstring(); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Number format modified during export/import", + aExpectedFormatStr[i], rFormatStr); + } + OUString aCSVPath = createFilePath(u"contentCSV/testNumberFormats.csv"); + testCondFile(aCSVPath, &*pDoc, 0, + false); // comma is thousand separator and cannot be used as delimiter +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |