1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <officecfg/Office/Common.hxx>
11 #include <sal/config.h>
12 #include <config_features.h>
14 #include <sfx2/docfile.hxx>
15 #include <sfx2/frame.hxx>
16 #include <sfx2/sfxmodelfactory.hxx>
17 #include <sfx2/sfxsids.hrc>
18 #include <sfx2/docfilt.hxx>
20 #include "helper/debughelper.hxx"
21 #include "helper/qahelper.hxx"
22 #include "helper/xpath.hxx"
23 #include "helper/shared_test_impl.hxx"
25 #include <userdat.hxx>
27 #include <patattr.hxx>
28 #include <docpool.hxx>
29 #include <scitems.hxx>
30 #include <document.hxx>
31 #include <formulacell.hxx>
32 #include <tokenarray.hxx>
33 #include <editutil.hxx>
34 #include <scopetools.hxx>
35 #include <cellvalue.hxx>
37 #include <tokenstringcontext.hxx>
38 #include <chgtrack.hxx>
39 #include <validat.hxx>
42 #include <dpcache.hxx>
43 #include <dpobject.hxx>
45 #include <svx/svdpage.hxx>
46 #include <svx/svdograf.hxx>
47 #include <tabprotection.hxx>
48 #include <editeng/wghtitem.hxx>
49 #include <editeng/postitem.hxx>
50 #include <editeng/editdata.hxx>
51 #include <editeng/eeitem.hxx>
52 #include <editeng/editobj.hxx>
53 #include <editeng/section.hxx>
54 #include <editeng/crossedoutitem.hxx>
55 #include <editeng/borderline.hxx>
56 #include <editeng/escapementitem.hxx>
57 #include <editeng/fontitem.hxx>
58 #include <editeng/udlnitem.hxx>
59 #include <editeng/flditem.hxx>
60 #include <editeng/colritem.hxx>
61 #include <formula/grammar.hxx>
62 #include <unotools/useroptions.hxx>
63 #include <tools/datetime.hxx>
64 #include <svl/zformat.hxx>
66 #include <test/xmltesttools.hxx>
67 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
68 #include <com/sun/star/awt/XBitmap.hpp>
69 #include <com/sun/star/graphic/GraphicType.hpp>
70 #include <comphelper/storagehelper.hxx>
72 using namespace ::com::sun::star
;
73 using namespace ::com::sun::star::uno
;
75 class ScExportTest
: public ScBootstrapFixture
, public XmlTestTools
78 virtual void registerNamespaces(xmlXPathContextPtr
& pXmlXPathCtx
) override
;
82 virtual void setUp() override
;
83 virtual void tearDown() override
;
85 ScDocShellRef
saveAndReloadPassword( ScDocShell
*, const OUString
&, const OUString
&, const OUString
&, SfxFilterFlags
);
89 void testPasswordExportODS();
90 void testConditionalFormatExportODS();
91 void testConditionalFormatExportXLSX();
92 void testTdf99856_dataValidationTest();
93 void testProtectionKeyODS_UTF16LErtlSHA1();
94 void testProtectionKeyODS_UTF8SHA1();
95 void testProtectionKeyODS_UTF8SHA256ODF12();
96 void testProtectionKeyODS_UTF8SHA256W3C();
97 void testProtectionKeyODS_XL_SHA1();
98 void testColorScaleExportODS();
99 void testColorScaleExportXLSX();
100 void testDataBarExportODS();
101 void testDataBarExportXLSX();
102 void testConditionalFormatRangeListXLSX();
103 void testConditionalFormatContainsTextXLSX();
104 void testMiscRowHeightExport();
105 void testNamedRangeBugfdo62729();
106 void testBuiltinRangesXLSX();
107 void testRichTextExportODS();
108 void testRichTextCellFormatXLSX();
109 void testFormulaRefSheetNameODS();
111 void testCellValuesExportODS();
112 void testCellNoteExportODS();
113 void testCellNoteExportXLS();
114 void testFormatExportODS();
116 void testCommentExportXLSX();
117 void testCommentExportXLSX_2_XLSX();
119 void testCustomColumnWidthExportXLSX();
121 void testXfDefaultValuesXLSX();
122 void testColumnWidthResaveXLSX();
124 void testColumnWidthExportFromODStoXLSX();
126 void testOutlineExportXLSX();
127 void testHiddenEmptyRowsXLSX();
128 void testAllRowsHiddenXLSX();
129 void testLandscapeOrientationXLSX();
131 void testInlineArrayXLS();
132 void testEmbeddedChartODS();
133 void testEmbeddedChartXLS();
134 void testCellAnchoredGroupXLS();
136 void testFormulaReferenceXLS();
137 void testSheetProtectionXLSX();
138 void testSheetProtectionXLSB();
140 void testCellBordersXLS();
141 void testCellBordersXLSX();
142 void testBordersExchangeXLSX();
143 void testTrackChangesSimpleXLSX();
144 void testSheetTabColorsXLSX();
146 void testSharedFormulaExportXLS();
147 void testSharedFormulaExportXLSX();
148 void testSharedFormulaStringResultExportXLSX();
150 void testFunctionsExcel2010( sal_uLong nFormatType
);
151 void testFunctionsExcel2010XLSX();
152 void testFunctionsExcel2010XLS();
153 void testFunctionsExcel2010ODS();
155 void testCeilingFloor( sal_uLong nFormatType
);
156 void testCeilingFloorXLSX();
157 void testCeilingFloorODSToXLSX();
158 void testCeilingFloorXLS();
159 void testCeilingFloorODS();
161 void testCustomXml();
164 void testRelativePathsODS();
166 void testSheetProtectionODS();
168 void testSwappedOutImageExport();
169 void testLinkedGraphicRT();
170 void testImageWithSpecialID();
173 void testSupBookVirtualPathXLS();
175 void testAbsNamedRangeHTML();
176 void testSheetLocalRangeNameXLS();
177 void testRelativeNamedExpressionsXLS();
178 void testSheetTextBoxHyperlinkXLSX();
179 void testFontSizeXLSX();
180 void testSheetCharacterKerningSpaceXLSX();
181 void testSheetCondensedCharacterSpaceXLSX();
182 void testTextUnderlineColorXLSX();
183 void testSheetRunParagraphPropertyXLSX();
184 void testHiddenShapeXLS();
185 void testHiddenShapeXLSX();
186 void testShapeAutofitXLSX();
187 void testHyperlinkXLSX();
188 void testMoveCellAnchoredShapesODS();
189 void testMatrixMultiplicationXLSX();
190 void testPreserveTextWhitespaceXLSX();
191 void testPreserveTextWhitespace2XLSX();
192 void testTextDirectionXLSX();
194 void testRefStringXLSX();
195 void testRefStringConfigXLSX();
196 void testRefStringUnspecified();
197 void testHeaderImageODS();
199 void testTdf88657ODS();
200 void testEscapeCharInNumberFormatXLSX();
201 void testNatNumInNumberFormatXLSX();
202 void testExponentWithoutSignFormatXLSX();
203 void testExtendedLCIDXLSX();
205 void testHiddenRepeatedRowsODS();
206 void testHyperlinkTargetFrameODS();
207 void testOpenDocumentAsReadOnly();
208 void testKeepSettingsOfBlankRows();
210 void testTdf118990();
211 void testTdf121612();
212 void testPivotCacheAfterExportXLSX();
214 void testXltxExport();
216 CPPUNIT_TEST_SUITE(ScExportTest
);
218 CPPUNIT_TEST(testTdf111876
);
219 CPPUNIT_TEST(testPasswordExportODS
);
220 CPPUNIT_TEST(testConditionalFormatExportODS
);
221 CPPUNIT_TEST(testConditionalFormatExportXLSX
);
222 CPPUNIT_TEST(testTdf99856_dataValidationTest
);
223 CPPUNIT_TEST(testProtectionKeyODS_UTF16LErtlSHA1
);
224 CPPUNIT_TEST(testProtectionKeyODS_UTF8SHA1
);
225 CPPUNIT_TEST(testProtectionKeyODS_UTF8SHA256ODF12
);
226 CPPUNIT_TEST(testProtectionKeyODS_UTF8SHA256W3C
);
227 CPPUNIT_TEST(testProtectionKeyODS_XL_SHA1
);
228 CPPUNIT_TEST(testColorScaleExportODS
);
229 CPPUNIT_TEST(testColorScaleExportXLSX
);
230 CPPUNIT_TEST(testDataBarExportODS
);
231 CPPUNIT_TEST(testDataBarExportXLSX
);
232 CPPUNIT_TEST(testConditionalFormatRangeListXLSX
);
233 CPPUNIT_TEST(testConditionalFormatContainsTextXLSX
);
234 CPPUNIT_TEST(testMiscRowHeightExport
);
235 CPPUNIT_TEST(testNamedRangeBugfdo62729
);
236 CPPUNIT_TEST(testBuiltinRangesXLSX
);
237 CPPUNIT_TEST(testRichTextExportODS
);
238 CPPUNIT_TEST(testRichTextCellFormatXLSX
);
239 CPPUNIT_TEST(testFormulaRefSheetNameODS
);
240 CPPUNIT_TEST(testCellValuesExportODS
);
241 CPPUNIT_TEST(testCellNoteExportODS
);
242 CPPUNIT_TEST(testCellNoteExportXLS
);
243 CPPUNIT_TEST(testFormatExportODS
);
244 CPPUNIT_TEST(testCommentExportXLSX
);
245 CPPUNIT_TEST(testCommentExportXLSX_2_XLSX
);
247 CPPUNIT_TEST(testCustomColumnWidthExportXLSX
);
249 CPPUNIT_TEST(testXfDefaultValuesXLSX
);
250 CPPUNIT_TEST(testColumnWidthResaveXLSX
);
252 CPPUNIT_TEST(testColumnWidthExportFromODStoXLSX
);
254 CPPUNIT_TEST(testOutlineExportXLSX
);
255 CPPUNIT_TEST(testHiddenEmptyRowsXLSX
);
256 CPPUNIT_TEST(testAllRowsHiddenXLSX
);
257 CPPUNIT_TEST(testLandscapeOrientationXLSX
);
258 CPPUNIT_TEST(testInlineArrayXLS
);
259 CPPUNIT_TEST(testEmbeddedChartODS
);
260 CPPUNIT_TEST(testEmbeddedChartXLS
);
261 CPPUNIT_TEST(testCellAnchoredGroupXLS
);
263 CPPUNIT_TEST(testFormulaReferenceXLS
);
264 CPPUNIT_TEST(testSheetProtectionXLSX
);
265 CPPUNIT_TEST(testSheetProtectionXLSB
);
266 CPPUNIT_TEST(testCellBordersXLS
);
267 CPPUNIT_TEST(testCellBordersXLSX
);
268 CPPUNIT_TEST(testBordersExchangeXLSX
);
269 CPPUNIT_TEST(testTrackChangesSimpleXLSX
);
270 CPPUNIT_TEST(testSheetTabColorsXLSX
);
271 CPPUNIT_TEST(testSharedFormulaExportXLS
);
272 CPPUNIT_TEST(testSharedFormulaExportXLSX
);
273 CPPUNIT_TEST(testSharedFormulaStringResultExportXLSX
);
274 CPPUNIT_TEST(testFunctionsExcel2010XLSX
);
275 CPPUNIT_TEST(testFunctionsExcel2010XLS
);
276 CPPUNIT_TEST(testFunctionsExcel2010ODS
);
277 CPPUNIT_TEST(testCeilingFloorXLSX
);
278 CPPUNIT_TEST(testCeilingFloorODSToXLSX
);
279 CPPUNIT_TEST(testCeilingFloorXLS
);
280 CPPUNIT_TEST(testCeilingFloorODS
);
281 CPPUNIT_TEST(testCustomXml
);
283 CPPUNIT_TEST(testRelativePathsODS
);
285 CPPUNIT_TEST(testSheetProtectionODS
);
287 CPPUNIT_TEST(testSupBookVirtualPathXLS
);
289 CPPUNIT_TEST(testSwappedOutImageExport
);
290 CPPUNIT_TEST(testLinkedGraphicRT
);
291 CPPUNIT_TEST(testImageWithSpecialID
);
292 CPPUNIT_TEST(testPreserveTextWhitespaceXLSX
);
293 CPPUNIT_TEST(testPreserveTextWhitespace2XLSX
);
294 CPPUNIT_TEST(testAbsNamedRangeHTML
);
295 CPPUNIT_TEST(testSheetLocalRangeNameXLS
);
296 CPPUNIT_TEST(testRelativeNamedExpressionsXLS
);
297 CPPUNIT_TEST(testSheetTextBoxHyperlinkXLSX
);
298 CPPUNIT_TEST(testFontSizeXLSX
);
299 CPPUNIT_TEST(testSheetCharacterKerningSpaceXLSX
);
300 CPPUNIT_TEST(testSheetCondensedCharacterSpaceXLSX
);
301 CPPUNIT_TEST(testTextUnderlineColorXLSX
);
302 CPPUNIT_TEST(testSheetRunParagraphPropertyXLSX
);
303 CPPUNIT_TEST(testHiddenShapeXLS
);
304 CPPUNIT_TEST(testHiddenShapeXLSX
);
305 CPPUNIT_TEST(testShapeAutofitXLSX
);
306 CPPUNIT_TEST(testHyperlinkXLSX
);
307 CPPUNIT_TEST(testMoveCellAnchoredShapesODS
);
308 CPPUNIT_TEST(testMatrixMultiplicationXLSX
);
309 CPPUNIT_TEST(testTextDirectionXLSX
);
311 CPPUNIT_TEST(testRefStringXLSX
);
312 CPPUNIT_TEST(testRefStringConfigXLSX
);
313 CPPUNIT_TEST(testRefStringUnspecified
);
314 CPPUNIT_TEST(testHeaderImageODS
);
316 CPPUNIT_TEST(testTdf88657ODS
);
317 CPPUNIT_TEST(testEscapeCharInNumberFormatXLSX
);
318 CPPUNIT_TEST(testNatNumInNumberFormatXLSX
);
319 CPPUNIT_TEST(testExponentWithoutSignFormatXLSX
);
320 CPPUNIT_TEST(testExtendedLCIDXLSX
);
322 CPPUNIT_TEST(testHiddenRepeatedRowsODS
);
323 CPPUNIT_TEST(testHyperlinkTargetFrameODS
);
324 CPPUNIT_TEST(testOpenDocumentAsReadOnly
);
325 CPPUNIT_TEST(testKeepSettingsOfBlankRows
);
327 CPPUNIT_TEST(testTdf118990
);
328 CPPUNIT_TEST(testTdf121612
);
329 CPPUNIT_TEST(testPivotCacheAfterExportXLSX
);
331 CPPUNIT_TEST(testXltxExport
);
333 CPPUNIT_TEST_SUITE_END();
336 void testExcelCellBorders( sal_uLong nFormatType
);
338 uno::Reference
<uno::XInterface
> m_xCalcComponent
;
342 void ScExportTest::registerNamespaces(xmlXPathContextPtr
& pXmlXPathCtx
)
344 static const struct { xmlChar
* pPrefix
; xmlChar
* pURI
; } aNamespaces
[] =
346 { BAD_CAST("w"), BAD_CAST("http://schemas.openxmlformats.org/wordprocessingml/2006/main") },
347 { BAD_CAST("x"), BAD_CAST("http://schemas.openxmlformats.org/spreadsheetml/2006/main") },
348 { BAD_CAST("v"), BAD_CAST("urn:schemas-microsoft-com:vml") },
349 { BAD_CAST("c"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/chart") },
350 { BAD_CAST("a"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/main") },
351 { BAD_CAST("mc"), BAD_CAST("http://schemas.openxmlformats.org/markup-compatibility/2006") },
352 { BAD_CAST("wps"), BAD_CAST("http://schemas.microsoft.com/office/word/2010/wordprocessingShape") },
353 { BAD_CAST("wpg"), BAD_CAST("http://schemas.microsoft.com/office/word/2010/wordprocessingGroup") },
354 { BAD_CAST("wp"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing") },
355 { BAD_CAST("office"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:office:1.0") },
356 { BAD_CAST("table"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:table:1.0") },
357 { BAD_CAST("text"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:text:1.0") },
358 { BAD_CAST("style"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:style:1.0") },
359 { BAD_CAST("draw"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:drawing:1.0") },
360 { BAD_CAST("xlink"), BAD_CAST("http://www.w3c.org/1999/xlink") },
361 { BAD_CAST("xdr"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing") },
362 { BAD_CAST("x"), BAD_CAST("http://schemas.openxmlformats.org/spreadsheetml/2006/main") },
363 { BAD_CAST("r"), BAD_CAST("http://schemas.openxmlformats.org/package/2006/relationships") },
364 { BAD_CAST("number"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0") },
365 { BAD_CAST("loext"), BAD_CAST("urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0") },
366 { BAD_CAST("ContentType"), BAD_CAST("http://schemas.openxmlformats.org/package/2006/content-types") },
368 for(size_t i
= 0; i
< SAL_N_ELEMENTS(aNamespaces
); ++i
)
370 xmlXPathRegisterNs(pXmlXPathCtx
, aNamespaces
[i
].pPrefix
, aNamespaces
[i
].pURI
);
374 ScDocShellRef
ScExportTest::saveAndReloadPassword(ScDocShell
* pShell
, const OUString
&rFilter
,
375 const OUString
&rUserData
, const OUString
& rTypeName
, SfxFilterFlags nFormatType
)
377 utl::TempFile aTempFile
;
378 aTempFile
.EnableKillingFile();
379 SfxMedium
aStoreMedium( aTempFile
.GetURL(), StreamMode::STD_WRITE
);
380 SotClipboardFormatId nExportFormat
= SotClipboardFormatId::NONE
;
381 if (nFormatType
== ODS_FORMAT_TYPE
)
382 nExportFormat
= SotClipboardFormatId::STARCHART_8
;
383 std::shared_ptr
<const SfxFilter
> pExportFilter(new SfxFilter(
385 OUString(), nFormatType
, nExportFormat
, rTypeName
, OUString(),
386 rUserData
, "private:factory/scalc*" ));
387 const_cast<SfxFilter
*>(pExportFilter
.get())->SetVersion(SOFFICE_FILEFORMAT_CURRENT
);
388 aStoreMedium
.SetFilter(pExportFilter
);
389 SfxItemSet
* pExportSet
= aStoreMedium
.GetItemSet();
390 uno::Sequence
< beans::NamedValue
> aEncryptionData
= comphelper::OStorageHelper::CreatePackageEncryptionData( "test" );
391 pExportSet
->Put(SfxUnoAnyItem(SID_ENCRYPTIONDATA
, makeAny(aEncryptionData
)));
393 uno::Reference
< embed::XStorage
> xMedStorage
= aStoreMedium
.GetStorage();
394 ::comphelper::OStorageHelper::SetCommonStorageEncryptionData( xMedStorage
, aEncryptionData
);
396 pShell
->DoSaveAs( aStoreMedium
);
399 //std::cout << "File: " << aTempFile.GetURL() << std::endl;
401 SotClipboardFormatId nFormat
= SotClipboardFormatId::NONE
;
402 if (nFormatType
== ODS_FORMAT_TYPE
)
403 nFormat
= SotClipboardFormatId::STARCALC_8
;
405 OUString
aPass("test");
406 return load(aTempFile
.GetURL(), rFilter
, rUserData
, rTypeName
, nFormatType
, nFormat
, SOFFICE_FILEFORMAT_CURRENT
, &aPass
);
409 void ScExportTest::test()
411 ScDocShell
* pShell
= new ScDocShell(
412 SfxModelFlags::EMBEDDED_OBJECT
|
413 SfxModelFlags::DISABLE_EMBEDDED_SCRIPTS
|
414 SfxModelFlags::DISABLE_DOCUMENT_RECOVERY
);
417 ScDocument
& rDoc
= pShell
->GetDocument();
419 rDoc
.SetValue(0,0,0, 1.0);
421 ScDocShellRef xDocSh
= saveAndReload(pShell
, FORMAT_ODS
);
423 CPPUNIT_ASSERT(xDocSh
.is());
424 ScDocument
& rLoadedDoc
= xDocSh
->GetDocument();
425 double aVal
= rLoadedDoc
.GetValue(0,0,0);
426 ASSERT_DOUBLES_EQUAL(aVal
, 1.0);
430 void ScExportTest::testTdf111876()
432 // DOcument with relative path hyperlink
434 ScDocShellRef xShell
= loadDoc("tdf111876.", FORMAT_XLSX
);
435 CPPUNIT_ASSERT(xShell
.is());
437 ScDocShellRef xDocSh
= saveAndReload(&(*xShell
), FORMAT_XLSX
);
438 CPPUNIT_ASSERT(xDocSh
.is());
440 xmlDocPtr pDoc
= XPathHelper::parseExport2(*this, *xDocSh
, m_xSFactory
, "xl/worksheets/_rels/sheet1.xml.rels", FORMAT_XLSX
);
441 CPPUNIT_ASSERT(pDoc
);
442 OUString sTarget
= getXPath(pDoc
, "/r:Relationships/r:Relationship", "Target");
444 // Document is saved to the temporary directory, relative path should be different than original one
445 CPPUNIT_ASSERT(sTarget
!= "../xls/bug-fixes.xls");
450 void ScExportTest::testPasswordExportODS()
452 ScDocShell
* pShell
= new ScDocShell(
453 SfxModelFlags::EMBEDDED_OBJECT
|
454 SfxModelFlags::DISABLE_EMBEDDED_SCRIPTS
|
455 SfxModelFlags::DISABLE_DOCUMENT_RECOVERY
);
458 ScDocument
& rDoc
= pShell
->GetDocument();
460 rDoc
.SetValue(0, 0, 0, 1.0);
462 sal_Int32 nFormat
= FORMAT_ODS
;
463 OUString
aFilterName(getFileFormats()[nFormat
].pFilterName
, strlen(getFileFormats()[nFormat
].pFilterName
), RTL_TEXTENCODING_UTF8
) ;
464 OUString
aFilterType(getFileFormats()[nFormat
].pTypeName
, strlen(getFileFormats()[nFormat
].pTypeName
), RTL_TEXTENCODING_UTF8
);
465 ScDocShellRef xDocSh
= saveAndReloadPassword(pShell
, aFilterName
, OUString(), aFilterType
, getFileFormats()[nFormat
].nFormatType
);
467 CPPUNIT_ASSERT(xDocSh
.is());
468 ScDocument
& rLoadedDoc
= xDocSh
->GetDocument();
469 double aVal
= rLoadedDoc
.GetValue(0,0,0);
470 ASSERT_DOUBLES_EQUAL(aVal
, 1.0);
475 void ScExportTest::testConditionalFormatExportODS()
477 ScDocShellRef xShell
= loadDoc("new_cond_format_test_export.", FORMAT_ODS
);
478 CPPUNIT_ASSERT(xShell
.is());
480 ScDocShellRef xDocSh
= saveAndReload(&(*xShell
), FORMAT_ODS
);
481 CPPUNIT_ASSERT(xDocSh
.is());
482 ScDocument
& rDoc
= xDocSh
->GetDocument();
484 createCSVPath( "new_cond_format_test_export.", aCSVPath
);
485 testCondFile(aCSVPath
, &rDoc
, 0);
490 void ScExportTest::testConditionalFormatExportXLSX()
492 ScDocShellRef xShell
= loadDoc("new_cond_format_test_export.", FORMAT_XLSX
);
493 CPPUNIT_ASSERT(xShell
.is());
495 ScDocShellRef xDocSh
= saveAndReload(&(*xShell
), FORMAT_XLSX
);
496 CPPUNIT_ASSERT(xDocSh
.is());
497 ScDocument
& rDoc
= xDocSh
->GetDocument();
500 createCSVPath( "new_cond_format_test_export.", aCSVPath
);
501 testCondFile(aCSVPath
, &rDoc
, 0);
505 createCSVPath( "new_cond_format_test_sheet2.", aCSVPath
);
506 testCondFile(aCSVPath
, &rDoc
, 1);
512 void ScExportTest::testTdf99856_dataValidationTest()
514 ScDocShellRef xShell
= loadDoc("tdf99856_dataValidationTest.", FORMAT_ODS
);
515 CPPUNIT_ASSERT_MESSAGE("Failed to load doc", xShell
.is());
517 ScDocShellRef xDocSh
= saveAndReload( xShell
.get(), FORMAT_XLSX
);
518 CPPUNIT_ASSERT_MESSAGE("Failed to reload doc", xDocSh
.is());
520 ScDocument
& rDoc
= xDocSh
->GetDocument();
521 const ScValidationData
* pData
= rDoc
.GetValidationEntry(2);
522 CPPUNIT_ASSERT(pData
);
524 // Excel can't open corrupt file if the list is longer than 255 characters
525 std::vector
<ScTypedStrData
> aList
;
526 pData
->FillSelectionList(aList
, ScAddress(0, 1, 1));
527 CPPUNIT_ASSERT_EQUAL(size_t(18), aList
.size());
528 CPPUNIT_ASSERT_EQUAL(OUString("18 Missis"), aList
[17].GetString());
533 void ScExportTest::testProtectionKeyODS_UTF16LErtlSHA1()
535 OUString
const password("1012345678901234567890123456789012345678901234567890");
537 ScDocShellRef xShell
= loadDoc("protection-key1.", FORMAT_FODS
);
538 CPPUNIT_ASSERT_MESSAGE("Failed to load doc", xShell
.is());
540 ScDocument
& rDoc
= xShell
->GetDocument();
541 ScDocProtection
*const pDocProt(rDoc
.GetDocProtection());
542 CPPUNIT_ASSERT(pDocProt
->verifyPassword(password
));
543 ScTableProtection
*const pTabProt(rDoc
.GetTabProtection(0));
544 CPPUNIT_ASSERT(pTabProt
->verifyPassword(password
));
546 // we can't assume that the user entered the password; check that we
547 // round-trip the password as-is
548 std::shared_ptr
<utl::TempFile
> pXPathFile
= ScBootstrapFixture::exportTo(&(*xShell
), FORMAT_ODS
);
549 xmlDocPtr pXmlDoc
= XPathHelper::parseExport(pXPathFile
, m_xSFactory
, "content.xml");
550 assertXPath(pXmlDoc
, "//office:spreadsheet[@table:structure-protected='true' and @table:protection-key='vbnhxyBKtPHCA1wB21zG1Oha8ZA=' and @table:protection-key-digest-algorithm='http://www.w3.org/2000/09/xmldsig#sha1']");
551 assertXPath(pXmlDoc
, "//table:table[@table:protected='true' and @table:protection-key='vbnhxyBKtPHCA1wB21zG1Oha8ZA=' and @table:protection-key-digest-algorithm='http://www.w3.org/2000/09/xmldsig#sha1']");
554 void ScExportTest::testProtectionKeyODS_UTF8SHA1()
556 OUString
const password("1012345678901234567890123456789012345678901234567890");
558 ScDocShellRef xShell
= loadDoc("protection-key2.", FORMAT_FODS
);
559 CPPUNIT_ASSERT_MESSAGE("Failed to load doc", xShell
.is());
561 ScDocument
& rDoc
= xShell
->GetDocument();
562 ScDocProtection
*const pDocProt(rDoc
.GetDocProtection());
563 CPPUNIT_ASSERT(pDocProt
->verifyPassword(password
));
564 ScTableProtection
*const pTabProt(rDoc
.GetTabProtection(0));
565 CPPUNIT_ASSERT(pTabProt
->verifyPassword(password
));
567 // we can't assume that the user entered the password; check that we
568 // round-trip the password as-is
569 std::shared_ptr
<utl::TempFile
> pXPathFile
= ScBootstrapFixture::exportTo(&(*xShell
), FORMAT_ODS
);
570 xmlDocPtr pXmlDoc
= XPathHelper::parseExport(pXPathFile
, m_xSFactory
, "content.xml");
571 assertXPath(pXmlDoc
, "//office:spreadsheet[@table:structure-protected='true' and @table:protection-key='nLHas0RIwepGDaH4c2hpyIUvIS8=' and @table:protection-key-digest-algorithm='http://www.w3.org/2000/09/xmldsig#sha1']");
572 assertXPath(pXmlDoc
, "//table:table[@table:protected='true' and @table:protection-key='nLHas0RIwepGDaH4c2hpyIUvIS8=' and @table:protection-key-digest-algorithm='http://www.w3.org/2000/09/xmldsig#sha1']");
575 void ScExportTest::testProtectionKeyODS_UTF8SHA256ODF12()
577 OUString
const password("1012345678901234567890123456789012345678901234567890");
579 ScDocShellRef xShell
= loadDoc("protection-key3.", FORMAT_FODS
);
580 CPPUNIT_ASSERT_MESSAGE("Failed to load doc", xShell
.is());
582 ScDocument
& rDoc
= xShell
->GetDocument();
583 ScDocProtection
*const pDocProt(rDoc
.GetDocProtection());
584 CPPUNIT_ASSERT(pDocProt
->verifyPassword(password
));
585 ScTableProtection
*const pTabProt(rDoc
.GetTabProtection(0));
586 CPPUNIT_ASSERT(pTabProt
->verifyPassword(password
));
588 // we can't assume that the user entered the password; check that we
589 // round-trip the password as-is
590 std::shared_ptr
<utl::TempFile
> pXPathFile
= ScBootstrapFixture::exportTo(&(*xShell
), FORMAT_ODS
);
591 xmlDocPtr pXmlDoc
= XPathHelper::parseExport(pXPathFile
, m_xSFactory
, "content.xml");
592 assertXPath(pXmlDoc
, "//office:spreadsheet[@table:structure-protected='true' and @table:protection-key='1tnJohagR2T0yF/v69hLPuumSTsj32CumW97nkKGuSQ=' and @table:protection-key-digest-algorithm='http://www.w3.org/2000/09/xmldsig#sha256']");
593 assertXPath(pXmlDoc
, "//table:table[@table:protected='true' and @table:protection-key='1tnJohagR2T0yF/v69hLPuumSTsj32CumW97nkKGuSQ=' and @table:protection-key-digest-algorithm='http://www.w3.org/2000/09/xmldsig#sha256']");
596 void ScExportTest::testProtectionKeyODS_UTF8SHA256W3C()
598 OUString
const password("1012345678901234567890123456789012345678901234567890");
600 ScDocShellRef xShell
= loadDoc("protection-key4.", FORMAT_FODS
);
601 CPPUNIT_ASSERT_MESSAGE("Failed to load doc", xShell
.is());
603 ScDocument
& rDoc
= xShell
->GetDocument();
604 ScDocProtection
*const pDocProt(rDoc
.GetDocProtection());
605 CPPUNIT_ASSERT(pDocProt
->verifyPassword(password
));
606 ScTableProtection
*const pTabProt(rDoc
.GetTabProtection(0));
607 CPPUNIT_ASSERT(pTabProt
->verifyPassword(password
));
609 // we can't assume that the user entered the password; check that we
610 // round-trip the password as-is
611 std::shared_ptr
<utl::TempFile
> pXPathFile
= ScBootstrapFixture::exportTo(&(*xShell
), FORMAT_ODS
);
612 xmlDocPtr pXmlDoc
= XPathHelper::parseExport(pXPathFile
, m_xSFactory
, "content.xml");
613 assertXPath(pXmlDoc
, "//office:spreadsheet[@table:structure-protected='true' and @table:protection-key='1tnJohagR2T0yF/v69hLPuumSTsj32CumW97nkKGuSQ=' and @table:protection-key-digest-algorithm='http://www.w3.org/2000/09/xmldsig#sha256']");
614 assertXPath(pXmlDoc
, "//table:table[@table:protected='true' and @table:protection-key='1tnJohagR2T0yF/v69hLPuumSTsj32CumW97nkKGuSQ=' and @table:protection-key-digest-algorithm='http://www.w3.org/2000/09/xmldsig#sha256']");
617 void ScExportTest::testProtectionKeyODS_XL_SHA1()
619 OUString
const password("1012345678901234567890123456789012345678901234567890");
621 ScDocShellRef xShell
= loadDoc("protection-key5.", FORMAT_FODS
);
622 CPPUNIT_ASSERT_MESSAGE("Failed to load doc", xShell
.is());
624 ScDocument
& rDoc
= xShell
->GetDocument();
625 ScDocProtection
*const pDocProt(rDoc
.GetDocProtection());
626 CPPUNIT_ASSERT(pDocProt
->verifyPassword(password
));
627 ScTableProtection
*const pTabProt(rDoc
.GetTabProtection(0));
628 CPPUNIT_ASSERT(pTabProt
->verifyPassword(password
));
630 // we can't assume that the user entered the password; check that we
631 // round-trip the password as-is
632 std::shared_ptr
<utl::TempFile
> pXPathFile
= ScBootstrapFixture::exportTo(&(*xShell
), FORMAT_ODS
);
633 xmlDocPtr pXmlDoc
= XPathHelper::parseExport(pXPathFile
, m_xSFactory
, "content.xml");
634 assertXPath(pXmlDoc
, "//office:spreadsheet[@table:structure-protected='true' and @table:protection-key='OX3WkEe79fv1PE+FUmfOLdwVoqI=' and @table:protection-key-digest-algorithm='http://docs.oasis-open.org/office/ns/table/legacy-hash-excel' and @loext:protection-key-digest-algorithm-2='http://www.w3.org/2000/09/xmldsig#sha1']");
635 assertXPath(pXmlDoc
, "//table:table[@table:protected='true' and @table:protection-key='OX3WkEe79fv1PE+FUmfOLdwVoqI=' and @table:protection-key-digest-algorithm='http://docs.oasis-open.org/office/ns/table/legacy-hash-excel' and @loext:protection-key-digest-algorithm-2='http://www.w3.org/2000/09/xmldsig#sha1']");
638 void ScExportTest::testColorScaleExportODS()
640 ScDocShellRef xShell
= loadDoc("colorscale.", FORMAT_ODS
);
641 CPPUNIT_ASSERT(xShell
.is());
643 ScDocShellRef xDocSh
= saveAndReload(xShell
.get(), FORMAT_ODS
);
644 CPPUNIT_ASSERT(xDocSh
.is());
646 ScDocument
& rDoc
= xDocSh
->GetDocument();
648 testColorScale2Entry_Impl(rDoc
);
649 testColorScale3Entry_Impl(rDoc
);
654 void ScExportTest::testColorScaleExportXLSX()
656 ScDocShellRef xShell
= loadDoc("colorscale.", FORMAT_XLSX
);
657 CPPUNIT_ASSERT(xShell
.is());
659 ScDocShellRef xDocSh
= saveAndReload(xShell
.get(), FORMAT_XLSX
);
660 CPPUNIT_ASSERT(xDocSh
.is());
662 ScDocument
& rDoc
= xDocSh
->GetDocument();
664 testColorScale2Entry_Impl(rDoc
);
665 testColorScale3Entry_Impl(rDoc
);
670 void ScExportTest::testDataBarExportODS()
672 ScDocShellRef xShell
= loadDoc("databar.", FORMAT_ODS
);
673 CPPUNIT_ASSERT(xShell
.is());
675 ScDocShellRef xDocSh
= saveAndReload(xShell
.get(), FORMAT_ODS
);
676 CPPUNIT_ASSERT(xDocSh
.is());
678 ScDocument
& rDoc
= xDocSh
->GetDocument();
680 testDataBar_Impl(rDoc
);
685 void ScExportTest::testFormatExportODS()
687 ScDocShellRef xShell
= loadDoc("formats.", FORMAT_ODS
);
688 CPPUNIT_ASSERT(xShell
.is());
690 ScDocShellRef xDocSh
= saveAndReload(xShell
.get(), FORMAT_ODS
);
691 CPPUNIT_ASSERT(xDocSh
.is());
693 ScDocument
& rDoc
= xDocSh
->GetDocument();
695 testFormats(this, &rDoc
, FORMAT_ODS
);
700 void ScExportTest::testCommentExportXLSX()
702 //tdf#104729 FILESAVE OpenOffice do not save author of the comment during export to .xlsx
703 ScDocShellRef xShell
= loadDoc("comment.", FORMAT_ODS
);
704 CPPUNIT_ASSERT(xShell
.is());
706 std::shared_ptr
<utl::TempFile
> pXPathFile
707 = ScBootstrapFixture::exportTo(&(*xShell
), FORMAT_XLSX
);
708 const xmlDocPtr pComments
709 = XPathHelper::parseExport(pXPathFile
, m_xSFactory
, "xl/comments1.xml");
710 CPPUNIT_ASSERT(pComments
);
712 assertXPath(pComments
, "/x:comments/x:authors/x:author[1]", "BAKO");
713 assertXPath(pComments
, "/x:comments/x:authors/x:author", 1);
715 assertXPath(pComments
, "/x:comments/x:commentList/x:comment/x:text/x:r/x:t", "Komentarz");
717 const xmlDocPtr pVmlDrawing
718 = XPathHelper::parseExport(pXPathFile
, m_xSFactory
, "xl/drawings/vmlDrawing1.vml");
719 CPPUNIT_ASSERT(pVmlDrawing
);
721 //assertXPath(pVmlDrawing, "/xml/v:shapetype", "coordsize", "21600,21600");
722 assertXPath(pVmlDrawing
, "/xml/v:shapetype", "spt", "202");
723 assertXPath(pVmlDrawing
, "/xml/v:shapetype/v:stroke", "joinstyle", "miter");
724 const OUString sShapeTypeId
= "#" + getXPath(pVmlDrawing
, "/xml/v:shapetype", "id");
726 assertXPath(pVmlDrawing
, "/xml/v:shape", "type", sShapeTypeId
);
727 assertXPath(pVmlDrawing
, "/xml/v:shape/v:shadow", "color", "black");
728 assertXPath(pVmlDrawing
, "/xml/v:shape/v:shadow", "obscured", "t");
731 void ScExportTest::testCommentExportXLSX_2_XLSX()
733 //tdf#117287 FILESAVE XLSX: Comments always disappear after opening the exported XLSX file with Excel
734 ScDocShellRef xShell
= loadDoc("tdf117287_comment.", FORMAT_XLSX
);
735 CPPUNIT_ASSERT(xShell
.is());
738 ScDocument
& rDoc
= xShell
->GetDocument();
739 ScAddress
aPosC9(2, 8, 0);
740 ScPostIt
*pNote
= rDoc
.GetNote(aPosC9
);
742 CPPUNIT_ASSERT(pNote
);
743 CPPUNIT_ASSERT(!pNote
->IsCaptionShown());
745 pNote
->ShowCaption(aPosC9
, true);
747 std::shared_ptr
<utl::TempFile
> pXPathFile
748 = ScBootstrapFixture::exportTo(&(*xShell
), FORMAT_XLSX
);
749 const xmlDocPtr pComments
750 = XPathHelper::parseExport(pXPathFile
, m_xSFactory
, "xl/comments1.xml");
751 CPPUNIT_ASSERT(pComments
);
753 assertXPath(pComments
, "/x:comments/x:commentList/x:comment/x:text/x:r/x:t", "visible comment");
755 const xmlDocPtr pVmlDrawing
756 = XPathHelper::parseExport(pXPathFile
, m_xSFactory
, "xl/drawings/vmlDrawing1.vml");
757 CPPUNIT_ASSERT(pVmlDrawing
);
759 assertXPath(pVmlDrawing
, "/xml/v:shape/x:ClientData/x:Visible", 0);
763 void ScExportTest::testCustomColumnWidthExportXLSX()
765 //tdf#100946 FILESAVE Excel on macOS ignored column widths in XLSX last saved by LO
766 ScDocShellRef xShell
= loadDoc("custom_column_width.", FORMAT_ODS
);
767 CPPUNIT_ASSERT(xShell
.is());
769 std::shared_ptr
<utl::TempFile
> pXPathFile
= ScBootstrapFixture::exportTo(&(*xShell
), FORMAT_XLSX
);
770 xmlDocPtr pSheet
= XPathHelper::parseExport(pXPathFile
, m_xSFactory
, "xl/worksheets/sheet1.xml");
771 CPPUNIT_ASSERT(pSheet
);
773 // First column, has everything default (width in Calc: 1280)
774 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[1]", "hidden", "false");
775 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[1]", "outlineLevel", "0");
776 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[1]", "customWidth", "false");
777 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[1]", "collapsed", "false");
778 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[1]", "min", "1");
779 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[1]", "max", "1");
781 // Second column, has custom width (width in Calc: 1225)
782 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[2]", "hidden", "false");
783 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[2]", "outlineLevel", "0");
784 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[2]", "customWidth", "true");
785 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[2]", "collapsed", "false");
786 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[2]", "min", "2");
787 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[2]", "max", "2");
789 // Third column, has everything default (width in Calc: 1280)
790 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[3]", "hidden", "false");
791 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[3]", "outlineLevel", "0");
792 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[3]", "customWidth", "false");
793 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[3]", "collapsed", "false");
794 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[3]", "min", "3");
795 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[3]", "max", "3");
797 // Fourth column has custom width. Columns from 4 to 7 are hidden
798 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[4]", "hidden", "true");
799 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[4]", "outlineLevel", "0");
800 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[4]", "customWidth", "true");
801 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[4]", "collapsed", "false");
802 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[4]", "min", "4");
803 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[4]", "max", "4");
805 // 5th column has custom width. Columns from 4 to 7 are hidden
806 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[5]", "hidden", "true");
807 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[5]", "outlineLevel", "0");
808 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[5]", "customWidth", "true");
809 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[5]", "collapsed", "false");
810 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[5]", "min", "5");
811 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[5]", "max", "5");
813 // 6th and 7th columns has default width and it are hidden
814 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[6]", "hidden", "true");
815 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[6]", "outlineLevel", "0");
816 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[6]", "customWidth", "false");
817 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[6]", "collapsed", "false");
818 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[6]", "min", "6");
819 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[6]", "max", "7");
821 // 8th column has everything default
822 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[7]", "hidden", "false");
823 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[7]", "outlineLevel", "0");
824 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[7]", "customWidth", "false");
825 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[7]", "collapsed", "false");
826 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[7]", "min", "8");
827 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[7]", "max", "8");
829 // 9th column has custom width
830 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[8]", "hidden", "false");
831 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[8]", "outlineLevel", "0");
832 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[8]", "customWidth", "true");
833 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[8]", "collapsed", "false");
834 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[8]", "min", "9");
835 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[8]", "max", "9");
837 // Rest of columns are default
838 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[9]", "hidden", "false");
839 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[9]", "outlineLevel", "0");
840 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[9]", "customWidth", "false");
841 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[9]", "collapsed", "false");
842 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[9]", "min", "10");
843 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[9]", "max", "1025");
845 // We expected that exactly 9 unique Nodes will be produced
846 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col", 9);
848 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[1]", "hidden", "false");
849 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[1]", "outlineLevel", "0");
850 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[1]", "collapsed", "false");
851 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[1]", "customFormat", "false");
852 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[1]", "customHeight", "false");
856 void ScExportTest::testXfDefaultValuesXLSX()
858 //tdf#70565 FORMATTING: User Defined Custom Formatting is not applied during importing XLSX documents
859 ScDocShellRef xShell
= loadDoc("xf_default_values.", FORMAT_XLSX
);
860 CPPUNIT_ASSERT(xShell
.is());
862 std::shared_ptr
<utl::TempFile
> pXPathFile
= ScBootstrapFixture::exportTo(&(*xShell
), FORMAT_XLSX
);
863 xmlDocPtr pSheet
= XPathHelper::parseExport(pXPathFile
, m_xSFactory
, "xl/styles.xml");
864 CPPUNIT_ASSERT(pSheet
);
866 // cellStyleXfs don't need xfId, so we need to make sure it is not saved
867 assertXPathNoAttribute(pSheet
, "/x:styleSheet/x:cellStyleXfs/x:xf[1]", "xfId");
869 // Because numFmtId fontId fillId borderId xfId are not existing during import
870 // it should be created during export, with values set to "0"
871 assertXPath(pSheet
, "/x:styleSheet/x:cellXfs/x:xf[1]", "xfId", "0");
872 assertXPath(pSheet
, "/x:styleSheet/x:cellXfs/x:xf[2]", "xfId", "0");
873 assertXPath(pSheet
, "/x:styleSheet/x:cellXfs/x:xf[3]", "xfId", "0");
874 assertXPath(pSheet
, "/x:styleSheet/x:cellXfs/x:xf[4]", "xfId", "0");
876 // We expected that exactly 15 cellXfs:xf Nodes will be produced
877 assertXPath(pSheet
, "/x:styleSheet/x:cellXfs/x:xf", 14);
880 void ScExportTest::testColumnWidthResaveXLSX()
882 // tdf#91475 FILESAVE: Column width is not preserved in XLSX / after round trip.
883 // Test if after resave .xlsx file, columns width is identical with previous one
884 ScDocShellRef xShell
= loadDoc("different-column-width-excel2010.", FORMAT_XLSX
);
885 CPPUNIT_ASSERT(xShell
.is());
887 std::shared_ptr
<utl::TempFile
> pXPathFile
= ScBootstrapFixture::exportTo(&(*xShell
), FORMAT_XLSX
);
888 xmlDocPtr pSheet
= XPathHelper::parseExport(pXPathFile
, m_xSFactory
, "xl/worksheets/sheet1.xml");
889 CPPUNIT_ASSERT(pSheet
);
891 // In original Excel document the width is "24"
892 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[1]", "width", "24");
893 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[1]", "customWidth", "true");
895 // In original Excel document the width is "12"
896 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[2]", "width", "12");
897 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[2]", "customWidth", "true");
899 // In original Excel document the width is "6"
900 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[3]", "width", "6");
901 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[3]", "customWidth", "true");
903 // In original Excel document the width is "1"
904 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[4]", "width", "1");
905 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[4]", "customWidth", "true");
907 // In original Excel document the width is "250"
908 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[5]", "width", "250");
909 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[5]", "customWidth", "true");
911 // The last column [6] is not existing in Excel sheet, and it is added only by LibreOffice.
912 // This column width is default and it is depended on operating system.
914 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col", 6);
918 void ScExportTest::testColumnWidthExportFromODStoXLSX()
920 // tdf#91475 FILESAVE: Column width is not preserved in XLSX / after round trip.
921 // Test if after export .ods to .xlsx format, displayed columns width
922 // is identical with previous (.ods) one
924 ScDocShellRef xShell
= loadDoc("different-column-width.", FORMAT_ODS
);
926 CPPUNIT_ASSERT( xShell
.is() );
928 ScDocument
& rOdsDoc
= xShell
->GetDocument();
930 // Col 1, Tab 0 (Column width 2.00 in)
931 sal_uInt16 nExpectedColumn0Width
= rOdsDoc
.GetColWidth(static_cast<SCCOL
>(0), static_cast<SCTAB
>(0), false);
932 CPPUNIT_ASSERT_EQUAL( static_cast< sal_uInt16
>( 2880 ), nExpectedColumn0Width
);
934 // Col 2, Tab 0 (Column width 1.00 in)
935 sal_uInt16 nExpectedColumn1Width
= rOdsDoc
.GetColWidth(static_cast<SCCOL
>(1), static_cast<SCTAB
>(0), false);
936 CPPUNIT_ASSERT_EQUAL( static_cast< sal_uInt16
>( 1440 ), nExpectedColumn1Width
);
938 // Col 3, Tab 0 (Column width 0.50 in)
939 sal_uInt16 nExpectedColumn2Width
= rOdsDoc
.GetColWidth(static_cast<SCCOL
>(2), static_cast<SCTAB
>(0), false);
940 CPPUNIT_ASSERT_EQUAL( static_cast< sal_uInt16
>( 720 ), nExpectedColumn2Width
);
942 // Col 4, Tab 0 (Column width 0.25 in)
943 sal_uInt16 nExpectedColumn3Width
= rOdsDoc
.GetColWidth(static_cast<SCCOL
>(3), static_cast<SCTAB
>(0), false);
944 CPPUNIT_ASSERT_EQUAL( static_cast< sal_uInt16
>( 360 ), nExpectedColumn3Width
);
946 // Col 5, Tab 0 (Column width 13.57 in)
947 sal_uInt16 nExpectedColumn4Width
= rOdsDoc
.GetColWidth(static_cast<SCCOL
>(4), static_cast<SCTAB
>(0), false);
948 CPPUNIT_ASSERT_EQUAL( static_cast< sal_uInt16
>( 19539 ), nExpectedColumn4Width
);
950 // Export to .xlsx and compare column width with the .ods
951 // We expect that column width from .ods will be exactly the same as imported from .xlsx
953 ScDocShellRef xXlsxDocSh
= saveAndReload( xShell
.get(), FORMAT_XLSX
);
954 CPPUNIT_ASSERT( xXlsxDocSh
.is() );
956 ScDocument
& rDoc
= xXlsxDocSh
->GetDocument();
959 sal_uInt16 nCalcWidth
;
960 nCalcWidth
= rDoc
.GetColWidth(static_cast<SCCOL
>(0), static_cast<SCTAB
>(0), false);
961 CPPUNIT_ASSERT_EQUAL( nExpectedColumn0Width
, nCalcWidth
);
964 nCalcWidth
= rDoc
.GetColWidth(static_cast<SCCOL
>(1), static_cast<SCTAB
>(0), false);
965 CPPUNIT_ASSERT_EQUAL( nExpectedColumn1Width
, nCalcWidth
);
968 nCalcWidth
= rDoc
.GetColWidth(static_cast<SCCOL
>(2), static_cast<SCTAB
>(0), false);
969 CPPUNIT_ASSERT_EQUAL( nExpectedColumn2Width
, nCalcWidth
);
972 nCalcWidth
= rDoc
.GetColWidth(static_cast<SCCOL
>(3), static_cast<SCTAB
>(0), false);
973 CPPUNIT_ASSERT_EQUAL( nExpectedColumn3Width
, nCalcWidth
);
976 nCalcWidth
= rDoc
.GetColWidth(static_cast<SCCOL
>(4), static_cast<SCTAB
>(0), false);
977 CPPUNIT_ASSERT_EQUAL( nExpectedColumn4Width
, nCalcWidth
);
979 xXlsxDocSh
->DoClose();
983 void ScExportTest::testOutlineExportXLSX()
985 //tdf#100347 FILESAVE FILEOPEN after exporting to .xlsx format grouping are lost
986 //tdf#51524 FILESAVE .xlsx and.xls looses width information for hidden/collapsed grouped columns
987 ScDocShellRef xShell
= loadDoc("outline.", FORMAT_ODS
);
988 CPPUNIT_ASSERT(xShell
.is());
990 std::shared_ptr
<utl::TempFile
> pXPathFile
= ScBootstrapFixture::exportTo(&(*xShell
), FORMAT_XLSX
);
991 xmlDocPtr pSheet
= XPathHelper::parseExport(pXPathFile
, m_xSFactory
, "xl/worksheets/sheet1.xml");
992 CPPUNIT_ASSERT(pSheet
);
994 // Maximum Outline Row is 4 for this document
995 assertXPath(pSheet
, "/x:worksheet/x:sheetFormatPr", "outlineLevelRow", "4");
996 // Maximum Outline Column is 4 for this document
997 assertXPath(pSheet
, "/x:worksheet/x:sheetFormatPr", "outlineLevelCol", "4");
999 // First XML node, creates two columns (from min=1 to max=2)
1000 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[1]", "hidden", "false");
1001 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[1]", "outlineLevel", "1");
1002 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[1]", "collapsed", "false");
1003 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[1]", "min", "1");
1004 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[1]", "max", "2");
1006 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[2]", "hidden", "true");
1007 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[2]", "outlineLevel", "2");
1008 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[2]", "collapsed", "false");
1009 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[2]", "min", "3");
1010 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[2]", "max", "3");
1012 // Column 4 has custom width and it is hidden. We need to make sure that it is created
1013 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[3]", "hidden", "true");
1014 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[3]", "outlineLevel", "2");
1015 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[3]", "collapsed", "false");
1016 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[3]", "min", "4");
1017 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[3]", "max", "4");
1019 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[4]", "hidden", "true");
1020 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[4]", "outlineLevel", "3");
1021 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[4]", "collapsed", "false");
1022 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[4]", "min", "5");
1023 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[4]", "max", "6");
1025 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[5]", "hidden", "true");
1026 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[5]", "outlineLevel", "4");
1027 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[5]", "collapsed", "false");
1028 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[5]", "min", "7");
1029 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[5]", "max", "7");
1031 // Column 8 has custom width and it is hidden. We need to make sure that it is created
1032 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[6]", "hidden", "true");
1033 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[6]", "outlineLevel", "4");
1034 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[6]", "collapsed", "false");
1035 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[6]", "min", "8");
1036 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[6]", "max", "8");
1038 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[7]", "hidden", "true");
1039 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[7]", "outlineLevel", "4");
1040 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[7]", "collapsed", "false");
1041 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[7]", "min", "9");
1042 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[7]", "max", "19");
1044 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[8]", "hidden", "true");
1045 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[8]", "outlineLevel", "3");
1046 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[8]", "collapsed", "true");
1047 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[8]", "min", "20");
1048 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[8]", "max", "20");
1050 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[9]", "hidden", "true");
1051 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[9]", "outlineLevel", "3");
1052 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[9]", "collapsed", "false");
1053 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[9]", "min", "21");
1054 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[9]", "max", "21");
1056 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[10]", "hidden", "true");
1057 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[10]", "outlineLevel", "2");
1058 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[10]", "collapsed", "false");
1059 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[10]", "min", "22");
1060 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[10]", "max", "23");
1062 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[11]", "hidden", "false");
1063 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[11]", "outlineLevel", "1");
1064 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[11]", "collapsed", "true");
1065 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[11]", "min", "24");
1066 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[11]", "max", "24");
1068 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[12]", "hidden", "false");
1069 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[12]", "outlineLevel", "1");
1070 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[12]", "collapsed", "false");
1071 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[12]", "min", "25");
1072 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[12]", "max", "26");
1074 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[13]", "hidden", "false");
1075 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[13]", "outlineLevel", "0");
1076 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[13]", "collapsed", "false");
1077 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col[13]", "min", "27");
1079 // We expected that exactly 13 unique Nodes will be produced
1080 assertXPath(pSheet
, "/x:worksheet/x:cols/x:col", 13);
1082 // First row is empty and default so it is not written into XML file
1083 // so we need to save 29 rows, as it provides information about outLineLevel
1084 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[1]", "r", "2");
1085 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[1]", "hidden", "false");
1086 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[1]", "outlineLevel", "1");
1087 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[1]", "collapsed", "false");
1088 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[2]", "r", "3");
1089 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[2]", "hidden", "false");
1090 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[2]", "outlineLevel", "2");
1091 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[2]", "collapsed", "false");
1092 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[3]", "r", "4");
1093 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[3]", "hidden", "false");
1094 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[3]", "outlineLevel", "2");
1095 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[3]", "collapsed", "false");
1096 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[4]", "r", "5");
1097 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[4]", "hidden", "false");
1098 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[4]", "outlineLevel", "3");
1099 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[4]", "collapsed", "false");
1100 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[5]", "r", "6");
1101 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[5]", "hidden", "false");
1102 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[5]", "outlineLevel", "3");
1103 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[5]", "collapsed", "false");
1104 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[6]", "r", "7");
1105 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[6]", "hidden", "true");
1106 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[6]", "outlineLevel", "4");
1107 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[6]", "collapsed", "false");
1108 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[7]", "r", "8");
1109 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[7]", "hidden", "true");
1110 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[7]", "outlineLevel", "4");
1111 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[7]", "collapsed", "false");
1112 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[8]", "r", "9");
1113 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[8]", "hidden", "true");
1114 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[8]", "outlineLevel", "4");
1115 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[8]", "collapsed", "false");
1116 // Next rows are the same as the previous one but it needs to bre preserved,
1117 // as they contain information about outlineLevel
1118 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[20]", "r", "21");
1119 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[20]", "hidden", "true");
1120 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[20]", "outlineLevel", "4");
1121 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[20]", "collapsed", "false");
1122 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[21]", "r", "22");
1123 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[21]", "hidden", "false");
1124 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[21]", "outlineLevel", "3");
1125 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[21]", "collapsed", "true");
1126 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[22]", "r", "23");
1127 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[22]", "hidden", "false");
1128 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[22]", "outlineLevel", "3");
1129 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[22]", "collapsed", "false");
1131 // We expected that exactly 29 Row Nodes will be produced
1132 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row", 29);
1135 void ScExportTest::testAllRowsHiddenXLSX()
1137 ScDocShellRef xOrigDocSh
= loadDoc("tdf105840_allRowsHidden.", FORMAT_XLSX
);
1138 CPPUNIT_ASSERT(xOrigDocSh
.is());
1140 std::shared_ptr
<utl::TempFile
> pXPathFile
= ScBootstrapFixture::exportTo(&(*xOrigDocSh
), FORMAT_XLSX
);
1141 xmlDocPtr pSheet
= XPathHelper::parseExport(pXPathFile
, m_xSFactory
, "xl/worksheets/sheet1.xml");
1142 CPPUNIT_ASSERT(pSheet
);
1143 assertXPath(pSheet
, "/x:worksheet/x:sheetFormatPr", "zeroHeight", "true" );
1144 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row", 0);
1147 void ScExportTest::testHiddenEmptyRowsXLSX()
1149 //tdf#98106 FILESAVE: Hidden and empty rows became visible when export to .XLSX
1150 ScDocShellRef xShell
= loadDoc("hidden-empty-rows.", FORMAT_ODS
);
1151 CPPUNIT_ASSERT(xShell
.is());
1153 std::shared_ptr
<utl::TempFile
> pXPathFile
= ScBootstrapFixture::exportTo(&(*xShell
), FORMAT_XLSX
);
1154 xmlDocPtr pSheet
= XPathHelper::parseExport(pXPathFile
, m_xSFactory
, "xl/worksheets/sheet1.xml");
1155 CPPUNIT_ASSERT(pSheet
);
1157 assertXPath(pSheet
, "/x:worksheet/x:sheetFormatPr", "zeroHeight", "false" );
1158 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[1]", "hidden", "true");
1159 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[2]", "hidden", "true");
1160 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[3]", "hidden", "true");
1161 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[4]", "hidden", "false");
1164 void ScExportTest::testLandscapeOrientationXLSX()
1166 //tdf#48767 - Landscape page orientation is not loaded from .xlsx format with MS Excel, after export with Libre Office
1167 ScDocShellRef xShell
= loadDoc("hidden-empty-rows.", FORMAT_ODS
);
1168 CPPUNIT_ASSERT(xShell
.is());
1170 std::shared_ptr
<utl::TempFile
> pXPathFile
= ScBootstrapFixture::exportTo(&(*xShell
), FORMAT_XLSX
);
1171 xmlDocPtr pSheet
= XPathHelper::parseExport(pXPathFile
, m_xSFactory
, "xl/worksheets/sheet1.xml");
1172 CPPUNIT_ASSERT(pSheet
);
1174 // the usePrinterDefaults cannot be saved to allow opening sheets in Landscape mode via MS Excel
1175 assertXPathNoAttribute(pSheet
, "/x:worksheet/x:pageSetup", "usePrinterDefaults");
1176 assertXPath(pSheet
, "/x:worksheet/x:pageSetup", "orientation", "landscape");
1179 void ScExportTest::testDataBarExportXLSX()
1181 ScDocShellRef xShell
= loadDoc("databar.", FORMAT_XLSX
);
1182 CPPUNIT_ASSERT(xShell
.is());
1184 ScDocShellRef xDocSh
= saveAndReload(xShell
.get(), FORMAT_XLSX
);
1185 CPPUNIT_ASSERT(xDocSh
.is());
1187 ScDocument
& rDoc
= xDocSh
->GetDocument();
1189 testDataBar_Impl(rDoc
);
1194 void ScExportTest::testMiscRowHeightExport()
1196 static const TestParam::RowData DfltRowData
[] =
1198 { 0, 4, 0, 529, 0, false },
1199 { 5, 10, 0, 1058, 0, false },
1200 { 17, 20, 0, 1767, 0, false },
1201 // check last couple of row in document to ensure
1202 // they are 5.29mm ( effective default row xlsx height )
1203 { 1048573, 1048575, 0, 529, 0, false },
1206 static const TestParam::RowData EmptyRepeatRowData
[] =
1208 // rows 0-4, 5-10, 17-20 are all set at various
1209 // heights, there is no content in the rows, there
1210 // was a bug where only the first row ( of repeated rows )
1211 // was set after export
1212 { 0, 4, 0, 529, 0, false },
1213 { 5, 10, 0, 1058, 0, false },
1214 { 17, 20, 0, 1767, 0, false },
1217 TestParam aTestValues
[] =
1219 // Checks that some distributed ( non-empty ) heights remain set after export (roundtrip)
1220 // additionally there is effectively a default row height ( 5.29 mm ). So we test the
1221 // unset rows at the end of the document to ensure the effective xlsx default height
1222 // is set there too.
1223 { "miscrowheights.", FORMAT_XLSX
, FORMAT_XLSX
, SAL_N_ELEMENTS(DfltRowData
), DfltRowData
},
1224 // Checks that some distributed ( non-empty ) heights remain set after export (to xls)
1225 { "miscrowheights.", FORMAT_XLSX
, FORMAT_XLS
, SAL_N_ELEMENTS(DfltRowData
), DfltRowData
},
1226 // Checks that repreated rows ( of various heights ) remain set after export ( to xlsx )
1227 { "miscemptyrepeatedrowheights.", FORMAT_ODS
, FORMAT_XLSX
, SAL_N_ELEMENTS(EmptyRepeatRowData
), EmptyRepeatRowData
},
1228 // Checks that repreated rows ( of various heights ) remain set after export ( to xls )
1229 { "miscemptyrepeatedrowheights.", FORMAT_ODS
, FORMAT_XLS
, SAL_N_ELEMENTS(EmptyRepeatRowData
), EmptyRepeatRowData
},
1231 miscRowHeightsTest( aTestValues
, SAL_N_ELEMENTS(aTestValues
) );
1236 void setAttribute( ScFieldEditEngine
& rEE
, sal_Int32 nPara
, sal_Int32 nStart
, sal_Int32 nEnd
, sal_uInt16 nType
, Color nColor
= COL_BLACK
)
1239 aSel
.nStartPara
= aSel
.nEndPara
= nPara
;
1240 aSel
.nStartPos
= nStart
;
1241 aSel
.nEndPos
= nEnd
;
1243 SfxItemSet aItemSet
= rEE
.GetEmptyItemSet();
1246 case EE_CHAR_WEIGHT
:
1248 SvxWeightItem
aWeight(WEIGHT_BOLD
, nType
);
1249 aItemSet
.Put(aWeight
);
1250 rEE
.QuickSetAttribs(aItemSet
, aSel
);
1253 case EE_CHAR_ITALIC
:
1255 SvxPostureItem
aItalic(ITALIC_NORMAL
, nType
);
1256 aItemSet
.Put(aItalic
);
1257 rEE
.QuickSetAttribs(aItemSet
, aSel
);
1260 case EE_CHAR_STRIKEOUT
:
1262 SvxCrossedOutItem
aCrossOut(STRIKEOUT_SINGLE
, nType
);
1263 aItemSet
.Put(aCrossOut
);
1264 rEE
.QuickSetAttribs(aItemSet
, aSel
);
1267 case EE_CHAR_OVERLINE
:
1269 SvxOverlineItem
aItem(LINESTYLE_DOUBLE
, nType
);
1270 aItemSet
.Put(aItem
);
1271 rEE
.QuickSetAttribs(aItemSet
, aSel
);
1274 case EE_CHAR_UNDERLINE
:
1276 SvxUnderlineItem
aItem(LINESTYLE_DOUBLE
, nType
);
1277 aItemSet
.Put(aItem
);
1278 rEE
.QuickSetAttribs(aItemSet
, aSel
);
1283 SvxColorItem
aItem(nColor
, nType
);
1284 aItemSet
.Put(aItem
);
1285 rEE
.QuickSetAttribs(aItemSet
, aSel
);
1293 void setFont( ScFieldEditEngine
& rEE
, sal_Int32 nPara
, sal_Int32 nStart
, sal_Int32 nEnd
, const OUString
& rFontName
)
1296 aSel
.nStartPara
= aSel
.nEndPara
= nPara
;
1297 aSel
.nStartPos
= nStart
;
1298 aSel
.nEndPos
= nEnd
;
1300 SfxItemSet aItemSet
= rEE
.GetEmptyItemSet();
1301 SvxFontItem
aItem(FAMILY_MODERN
, rFontName
, "", PITCH_VARIABLE
, RTL_TEXTENCODING_UTF8
, EE_CHAR_FONTINFO
);
1302 aItemSet
.Put(aItem
);
1303 rEE
.QuickSetAttribs(aItemSet
, aSel
);
1306 void setEscapement( ScFieldEditEngine
& rEE
, sal_Int32 nPara
, sal_Int32 nStart
, sal_Int32 nEnd
, short nEsc
, sal_uInt8 nRelSize
)
1309 aSel
.nStartPara
= aSel
.nEndPara
= nPara
;
1310 aSel
.nStartPos
= nStart
;
1311 aSel
.nEndPos
= nEnd
;
1313 SfxItemSet aItemSet
= rEE
.GetEmptyItemSet();
1314 SvxEscapementItem
aItem(nEsc
, nRelSize
, EE_CHAR_ESCAPEMENT
);
1315 aItemSet
.Put(aItem
);
1316 rEE
.QuickSetAttribs(aItemSet
, aSel
);
1321 void ScExportTest::testNamedRangeBugfdo62729()
1323 ScDocShellRef xShell
= loadDoc("fdo62729.", FORMAT_ODS
);
1324 CPPUNIT_ASSERT(xShell
.is());
1325 ScDocument
& rDoc
= xShell
->GetDocument();
1327 ScRangeName
* pNames
= rDoc
.GetRangeName();
1328 //should be just a single named range
1329 CPPUNIT_ASSERT_EQUAL(size_t(1), pNames
->size());
1331 //should be still a single named range
1332 CPPUNIT_ASSERT_EQUAL(size_t(1), pNames
->size());
1333 ScDocShellRef xDocSh
= saveAndReload(xShell
.get(), FORMAT_ODS
);
1336 CPPUNIT_ASSERT(xDocSh
.is());
1337 ScDocument
& rDoc2
= xDocSh
->GetDocument();
1339 pNames
= rDoc2
.GetRangeName();
1340 //after reload should still have a named range
1341 CPPUNIT_ASSERT_EQUAL(size_t(1), pNames
->size());
1346 void ScExportTest::testBuiltinRangesXLSX()
1348 ScDocShellRef xShell
= loadDoc("built-in_ranges.", FORMAT_XLSX
);
1349 CPPUNIT_ASSERT(xShell
.is());
1350 ScDocShellRef xDocSh
= saveAndReload(xShell
.get(), FORMAT_XLSX
);
1351 CPPUNIT_ASSERT(xDocSh
.is());
1354 xmlDocPtr pDoc
= XPathHelper::parseExport2(*this, *xDocSh
, m_xSFactory
, "xl/workbook.xml", FORMAT_XLSX
);
1355 CPPUNIT_ASSERT(pDoc
);
1357 //assert the existing OOXML built-in names are still there
1358 assertXPathContent(pDoc
, "/x:workbook/x:definedNames/x:definedName[@name='_xlnm._FilterDatabase'][@localSheetId='0']", "'Sheet1 Test'!$A$1:$A$5");
1359 assertXPathContent(pDoc
, "/x:workbook/x:definedNames/x:definedName[@name='_xlnm._FilterDatabase'][@localSheetId='1']", "'Sheet2 Test'!$K$10:$K$14");
1360 assertXPathContent(pDoc
, "/x:workbook/x:definedNames/x:definedName[@name='_xlnm.Print_Area'][@localSheetId='0']", "'Sheet1 Test'!$A$1:$A$5");
1361 assertXPathContent(pDoc
, "/x:workbook/x:definedNames/x:definedName[@name='_xlnm.Print_Area'][@localSheetId='1']", "'Sheet2 Test'!$K$10:$M$18");
1363 //...and that no extra ones are added (see tdf#112571)
1364 assertXPath(pDoc
, "/x:workbook/x:definedNames/x:definedName[@name='_xlnm._FilterDatabase_0'][@localSheetId='0']", 0);
1365 assertXPath(pDoc
, "/x:workbook/x:definedNames/x:definedName[@name='_xlnm._FilterDatabase_0'][@localSheetId='1']", 0);
1366 assertXPath(pDoc
, "/x:workbook/x:definedNames/x:definedName[@name='_xlnm.Print_Area_0'][@localSheetId='0']", 0);
1367 assertXPath(pDoc
, "/x:workbook/x:definedNames/x:definedName[@name='_xlnm.Print_Area_0'][@localSheetId='1']", 0);
1372 void ScExportTest::testRichTextExportODS()
1376 static bool isBold(const editeng::Section
& rAttr
)
1378 if (rAttr
.maAttributes
.empty())
1381 std::vector
<const SfxPoolItem
*>::const_iterator it
= rAttr
.maAttributes
.begin(), itEnd
= rAttr
.maAttributes
.end();
1382 for (; it
!= itEnd
; ++it
)
1384 const SfxPoolItem
* p
= *it
;
1385 if (p
->Which() != EE_CHAR_WEIGHT
)
1388 return static_cast<const SvxWeightItem
*>(p
)->GetWeight() == WEIGHT_BOLD
;
1393 static bool isItalic(const editeng::Section
& rAttr
)
1395 if (rAttr
.maAttributes
.empty())
1398 std::vector
<const SfxPoolItem
*>::const_iterator it
= rAttr
.maAttributes
.begin(), itEnd
= rAttr
.maAttributes
.end();
1399 for (; it
!= itEnd
; ++it
)
1401 const SfxPoolItem
* p
= *it
;
1402 if (p
->Which() != EE_CHAR_ITALIC
)
1405 return static_cast<const SvxPostureItem
*>(p
)->GetPosture() == ITALIC_NORMAL
;
1410 static bool isStrikeOut(const editeng::Section
& rAttr
)
1412 if (rAttr
.maAttributes
.empty())
1415 std::vector
<const SfxPoolItem
*>::const_iterator it
= rAttr
.maAttributes
.begin(), itEnd
= rAttr
.maAttributes
.end();
1416 for (; it
!= itEnd
; ++it
)
1418 const SfxPoolItem
* p
= *it
;
1419 if (p
->Which() != EE_CHAR_STRIKEOUT
)
1422 return static_cast<const SvxCrossedOutItem
*>(p
)->GetStrikeout() == STRIKEOUT_SINGLE
;
1427 static bool isOverline(const editeng::Section
& rAttr
, FontLineStyle eStyle
)
1429 if (rAttr
.maAttributes
.empty())
1432 std::vector
<const SfxPoolItem
*>::const_iterator it
= rAttr
.maAttributes
.begin(), itEnd
= rAttr
.maAttributes
.end();
1433 for (; it
!= itEnd
; ++it
)
1435 const SfxPoolItem
* p
= *it
;
1436 if (p
->Which() != EE_CHAR_OVERLINE
)
1439 return static_cast<const SvxOverlineItem
*>(p
)->GetLineStyle() == eStyle
;
1444 static bool isUnderline(const editeng::Section
& rAttr
, FontLineStyle eStyle
)
1446 if (rAttr
.maAttributes
.empty())
1449 std::vector
<const SfxPoolItem
*>::const_iterator it
= rAttr
.maAttributes
.begin(), itEnd
= rAttr
.maAttributes
.end();
1450 for (; it
!= itEnd
; ++it
)
1452 const SfxPoolItem
* p
= *it
;
1453 if (p
->Which() != EE_CHAR_UNDERLINE
)
1456 return static_cast<const SvxUnderlineItem
*>(p
)->GetLineStyle() == eStyle
;
1461 static bool isFont(const editeng::Section
& rAttr
, const OUString
& rFontName
)
1463 if (rAttr
.maAttributes
.empty())
1466 std::vector
<const SfxPoolItem
*>::const_iterator it
= rAttr
.maAttributes
.begin(), itEnd
= rAttr
.maAttributes
.end();
1467 for (; it
!= itEnd
; ++it
)
1469 const SfxPoolItem
* p
= *it
;
1470 if (p
->Which() != EE_CHAR_FONTINFO
)
1473 return static_cast<const SvxFontItem
*>(p
)->GetFamilyName() == rFontName
;
1478 static bool isEscapement(const editeng::Section
& rAttr
, short nEsc
, sal_uInt8 nRelSize
)
1480 if (rAttr
.maAttributes
.empty())
1483 std::vector
<const SfxPoolItem
*>::const_iterator it
= rAttr
.maAttributes
.begin(), itEnd
= rAttr
.maAttributes
.end();
1484 for (; it
!= itEnd
; ++it
)
1486 const SfxPoolItem
* p
= *it
;
1487 if (p
->Which() != EE_CHAR_ESCAPEMENT
)
1490 const SvxEscapementItem
* pItem
= static_cast<const SvxEscapementItem
*>(p
);
1491 return ((pItem
->GetEsc() == nEsc
) && (pItem
->GetProportionalHeight() == nRelSize
));
1496 static bool isColor(const editeng::Section
& rAttr
, Color nColor
)
1498 if (rAttr
.maAttributes
.empty())
1501 std::vector
<const SfxPoolItem
*>::const_iterator it
= rAttr
.maAttributes
.begin(), itEnd
= rAttr
.maAttributes
.end();
1502 for (; it
!= itEnd
; ++it
)
1504 const SfxPoolItem
* p
= *it
;
1505 if (p
->Which() != EE_CHAR_COLOR
)
1508 return static_cast<const SvxColorItem
*>(p
)->GetValue() == nColor
;
1513 bool checkB2(const EditTextObject
* pText
) const
1518 if (pText
->GetParagraphCount() != 1)
1521 if (pText
->GetText(0) != "Bold and Italic")
1524 std::vector
<editeng::Section
> aSecAttrs
;
1525 pText
->GetAllSections(aSecAttrs
);
1526 if (aSecAttrs
.size() != 3)
1529 // Check the first bold section.
1530 const editeng::Section
* pAttr
= &aSecAttrs
[0];
1531 if (pAttr
->mnParagraph
!= 0 ||pAttr
->mnStart
!= 0 || pAttr
->mnEnd
!= 4)
1534 if (pAttr
->maAttributes
.size() != 1 || !isBold(*pAttr
))
1537 // The middle section should be unformatted.
1538 pAttr
= &aSecAttrs
[1];
1539 if (pAttr
->mnParagraph
!= 0 ||pAttr
->mnStart
!= 4 || pAttr
->mnEnd
!= 9)
1542 if (!pAttr
->maAttributes
.empty())
1545 // The last section should be italic.
1546 pAttr
= &aSecAttrs
[2];
1547 if (pAttr
->mnParagraph
!= 0 ||pAttr
->mnStart
!= 9 || pAttr
->mnEnd
!= 15)
1550 if (pAttr
->maAttributes
.size() != 1 || !isItalic(*pAttr
))
1556 bool checkB4(const EditTextObject
* pText
) const
1561 if (pText
->GetParagraphCount() != 3)
1564 if (pText
->GetText(0) != "One")
1567 if (pText
->GetText(1) != "Two")
1570 if (pText
->GetText(2) != "Three")
1576 bool checkB5(const EditTextObject
* pText
) const
1581 if (pText
->GetParagraphCount() != 6)
1584 if (!pText
->GetText(0).isEmpty())
1587 if (pText
->GetText(1) != "Two")
1590 if (pText
->GetText(2) != "Three")
1593 if (!pText
->GetText(3).isEmpty())
1596 if (pText
->GetText(4) != "Five")
1599 if (!pText
->GetText(5).isEmpty())
1605 bool checkB6(const EditTextObject
* pText
) const
1610 if (pText
->GetParagraphCount() != 1)
1613 if (pText
->GetText(0) != "Strike Me")
1616 std::vector
<editeng::Section
> aSecAttrs
;
1617 pText
->GetAllSections(aSecAttrs
);
1618 if (aSecAttrs
.size() != 2)
1621 // Check the first strike-out section.
1622 const editeng::Section
* pAttr
= &aSecAttrs
[0];
1623 if (pAttr
->mnParagraph
!= 0 ||pAttr
->mnStart
!= 0 || pAttr
->mnEnd
!= 6)
1626 if (pAttr
->maAttributes
.size() != 1 || !isStrikeOut(*pAttr
))
1629 // The last section should be unformatted.
1630 pAttr
= &aSecAttrs
[1];
1631 return pAttr
->mnParagraph
== 0 && pAttr
->mnStart
== 6 && pAttr
->mnEnd
== 9;
1634 bool checkB7(const EditTextObject
* pText
) const
1639 if (pText
->GetParagraphCount() != 1)
1642 if (pText
->GetText(0) != "Font1 and Font2")
1645 std::vector
<editeng::Section
> aSecAttrs
;
1646 pText
->GetAllSections(aSecAttrs
);
1647 if (aSecAttrs
.size() != 3)
1650 // First section should have "Courier" font applied.
1651 const editeng::Section
* pAttr
= &aSecAttrs
[0];
1652 if (pAttr
->mnParagraph
!= 0 ||pAttr
->mnStart
!= 0 || pAttr
->mnEnd
!= 5)
1655 if (pAttr
->maAttributes
.size() != 1 || !isFont(*pAttr
, "Courier"))
1658 // Last section should have "Luxi Mono" applied.
1659 pAttr
= &aSecAttrs
[2];
1660 if (pAttr
->mnParagraph
!= 0 ||pAttr
->mnStart
!= 10 || pAttr
->mnEnd
!= 15)
1663 if (pAttr
->maAttributes
.size() != 1 || !isFont(*pAttr
, "Luxi Mono"))
1669 bool checkB8(const EditTextObject
* pText
) const
1674 if (pText
->GetParagraphCount() != 1)
1677 if (pText
->GetText(0) != "Over and Under")
1680 std::vector
<editeng::Section
> aSecAttrs
;
1681 pText
->GetAllSections(aSecAttrs
);
1682 if (aSecAttrs
.size() != 3)
1685 // First section shoul have overline applied.
1686 const editeng::Section
* pAttr
= &aSecAttrs
[0];
1687 if (pAttr
->mnParagraph
!= 0 ||pAttr
->mnStart
!= 0 || pAttr
->mnEnd
!= 4)
1690 if (pAttr
->maAttributes
.size() != 1 || !isOverline(*pAttr
, LINESTYLE_DOUBLE
))
1693 // Last section should have underline applied.
1694 pAttr
= &aSecAttrs
[2];
1695 if (pAttr
->mnParagraph
!= 0 ||pAttr
->mnStart
!= 9 || pAttr
->mnEnd
!= 14)
1698 if (pAttr
->maAttributes
.size() != 1 || !isUnderline(*pAttr
, LINESTYLE_DOUBLE
))
1704 bool checkB9(const EditTextObject
* pText
) const
1709 if (pText
->GetParagraphCount() != 1)
1712 if (pText
->GetText(0) != "Sub and Super")
1715 std::vector
<editeng::Section
> aSecAttrs
;
1716 pText
->GetAllSections(aSecAttrs
);
1717 if (aSecAttrs
.size() != 3)
1721 const editeng::Section
* pAttr
= &aSecAttrs
[0];
1722 if (pAttr
->mnParagraph
!= 0 ||pAttr
->mnStart
!= 0 || pAttr
->mnEnd
!= 3)
1725 if (pAttr
->maAttributes
.size() != 1 || !isEscapement(*pAttr
, 32, 64))
1729 pAttr
= &aSecAttrs
[2];
1730 if (pAttr
->mnParagraph
!= 0 ||pAttr
->mnStart
!= 8 || pAttr
->mnEnd
!= 13)
1733 if (pAttr
->maAttributes
.size() != 1 || !isEscapement(*pAttr
, -32, 66))
1739 bool checkB10(const EditTextObject
* pText
) const
1744 if (pText
->GetParagraphCount() != 1)
1747 if (pText
->GetText(0) != "BLUE AUTO")
1750 std::vector
<editeng::Section
> aSecAttrs
;
1751 pText
->GetAllSections(aSecAttrs
);
1752 if (aSecAttrs
.size() != 2)
1756 const editeng::Section
* pAttr
= &aSecAttrs
[1];
1757 if (pAttr
->mnParagraph
!= 0 ||pAttr
->mnStart
!= 5 || pAttr
->mnEnd
!= 9)
1760 if (pAttr
->maAttributes
.size() != 1 || !isColor(*pAttr
, COL_AUTO
))
1768 // Start with an empty document, put one edit text cell, and make sure it
1769 // survives the save and reload.
1770 ScDocShellRef xOrigDocSh
= loadDoc("empty.", FORMAT_ODS
, true);
1771 const EditTextObject
* pEditText
;
1773 ScDocument
& rDoc
= xOrigDocSh
->GetDocument();
1774 CPPUNIT_ASSERT_MESSAGE("This document should at least have one sheet.", rDoc
.GetTableCount() > 0);
1776 // Insert an edit text cell.
1777 ScFieldEditEngine
* pEE
= &rDoc
.GetEditEngine();
1778 pEE
->SetText("Bold and Italic");
1779 // Set the 'Bold' part bold.
1780 setAttribute(*pEE
, 0, 0, 4, EE_CHAR_WEIGHT
);
1781 // Set the 'Italic' part italic.
1782 setAttribute(*pEE
, 0, 9, 15, EE_CHAR_ITALIC
);
1784 aSel
.nStartPara
= aSel
.nEndPara
= 0;
1786 // Set this edit text to cell B2.
1787 rDoc
.SetEditText(ScAddress(1,1,0), pEE
->CreateTextObject());
1788 pEditText
= rDoc
.GetEditText(ScAddress(1,1,0));
1789 CPPUNIT_ASSERT_MESSAGE("Incorrect B2 value.", aCheckFunc
.checkB2(pEditText
));
1792 // Now, save and reload this document.
1793 ScDocShellRef xNewDocSh
= saveAndReload(xOrigDocSh
.get(), FORMAT_ODS
);
1795 xOrigDocSh
->DoClose();
1796 CPPUNIT_ASSERT(xNewDocSh
.is());
1797 ScDocument
& rDoc2
= xNewDocSh
->GetDocument();
1798 CPPUNIT_ASSERT_MESSAGE("Reloaded document should at least have one sheet.", rDoc2
.GetTableCount() > 0);
1799 ScFieldEditEngine
* pEE
= &rDoc2
.GetEditEngine();
1801 // Make sure the content of B2 is still intact.
1802 CPPUNIT_ASSERT_MESSAGE("Incorrect B2 value.", aCheckFunc
.checkB2(pEditText
));
1804 // Insert a multi-line content to B4.
1806 pEE
->SetText("One\nTwo\nThree");
1807 rDoc2
.SetEditText(ScAddress(1,3,0), pEE
->CreateTextObject());
1808 pEditText
= rDoc2
.GetEditText(ScAddress(1,3,0));
1809 CPPUNIT_ASSERT_MESSAGE("Incorrect B4 value.", aCheckFunc
.checkB4(pEditText
));
1812 // Reload the doc again, and check the content of B2 and B4.
1813 ScDocShellRef xNewDocSh2
= saveAndReload(xNewDocSh
.get(), FORMAT_ODS
);
1815 ScDocument
& rDoc3
= xNewDocSh2
->GetDocument();
1816 ScFieldEditEngine
* pEE
= &rDoc3
.GetEditEngine();
1817 xNewDocSh
->DoClose();
1819 pEditText
= rDoc3
.GetEditText(ScAddress(1,1,0));
1820 CPPUNIT_ASSERT_MESSAGE("B2 should be an edit text.", pEditText
);
1821 pEditText
= rDoc3
.GetEditText(ScAddress(1,3,0));
1822 CPPUNIT_ASSERT_MESSAGE("Incorrect B4 value.", aCheckFunc
.checkB4(pEditText
));
1824 // Insert a multi-line content to B5, but this time, set some empty paragraphs.
1826 pEE
->SetText("\nTwo\nThree\n\nFive\n");
1827 rDoc3
.SetEditText(ScAddress(1,4,0), pEE
->CreateTextObject());
1828 pEditText
= rDoc3
.GetEditText(ScAddress(1,4,0));
1829 CPPUNIT_ASSERT_MESSAGE("Incorrect B5 value.", aCheckFunc
.checkB5(pEditText
));
1831 // Insert a text with strikethrough in B6.
1833 pEE
->SetText("Strike Me");
1834 // Set the 'Strike' part strikethrough.
1835 setAttribute(*pEE
, 0, 0, 6, EE_CHAR_STRIKEOUT
);
1836 rDoc3
.SetEditText(ScAddress(1,5,0), pEE
->CreateTextObject());
1837 pEditText
= rDoc3
.GetEditText(ScAddress(1,5,0));
1838 CPPUNIT_ASSERT_MESSAGE("Incorrect B6 value.", aCheckFunc
.checkB6(pEditText
));
1840 // Insert a text with different font segments in B7.
1842 pEE
->SetText("Font1 and Font2");
1843 setFont(*pEE
, 0, 0, 5, "Courier");
1844 setFont(*pEE
, 0, 10, 15, "Luxi Mono");
1845 rDoc3
.SetEditText(ScAddress(1,6,0), pEE
->CreateTextObject());
1846 pEditText
= rDoc3
.GetEditText(ScAddress(1,6,0));
1847 CPPUNIT_ASSERT_MESSAGE("Incorrect B7 value.", aCheckFunc
.checkB7(pEditText
));
1849 // Insert a text with overline and underline in B8.
1851 pEE
->SetText("Over and Under");
1852 setAttribute(*pEE
, 0, 0, 4, EE_CHAR_OVERLINE
);
1853 setAttribute(*pEE
, 0, 9, 14, EE_CHAR_UNDERLINE
);
1854 rDoc3
.SetEditText(ScAddress(1,7,0), pEE
->CreateTextObject());
1855 pEditText
= rDoc3
.GetEditText(ScAddress(1,7,0));
1856 CPPUNIT_ASSERT_MESSAGE("Incorrect B8 value.", aCheckFunc
.checkB8(pEditText
));
1859 pEE
->SetText("Sub and Super");
1860 setEscapement(*pEE
, 0, 0, 3, 32, 64);
1861 setEscapement(*pEE
, 0, 8, 13, -32, 66);
1862 rDoc3
.SetEditText(ScAddress(1,8,0), pEE
->CreateTextObject());
1863 pEditText
= rDoc3
.GetEditText(ScAddress(1,8,0));
1864 CPPUNIT_ASSERT_MESSAGE("Incorrect B9 value.", aCheckFunc
.checkB9(pEditText
));
1866 ScPatternAttr
aCellFontColor(rDoc3
.GetPool());
1867 aCellFontColor
.GetItemSet().Put(SvxColorItem(COL_BLUE
, ATTR_FONT_COLOR
));
1868 // Set font color of B10 to blue.
1869 rDoc3
.ApplyPattern(1, 9, 0, aCellFontColor
);
1871 pEE
->SetText("BLUE AUTO");
1872 // Set the color of the string "AUTO" to automatic color.
1873 setAttribute(*pEE
, 0, 5, 9, EE_CHAR_COLOR
, COL_AUTO
);
1874 rDoc3
.SetEditText(ScAddress(1, 9, 0), pEE
->CreateTextObject());
1875 pEditText
= rDoc3
.GetEditText(ScAddress(1, 9, 0));
1876 CPPUNIT_ASSERT_MESSAGE("Incorrect B10 value.", aCheckFunc
.checkB10(pEditText
));
1879 // Reload the doc again, and check the content of B2, B4, B6 and B7.
1880 ScDocShellRef xNewDocSh3
= saveAndReload(xNewDocSh2
.get(), FORMAT_ODS
);
1881 ScDocument
& rDoc4
= xNewDocSh3
->GetDocument();
1882 xNewDocSh2
->DoClose();
1884 pEditText
= rDoc4
.GetEditText(ScAddress(1,1,0));
1885 CPPUNIT_ASSERT_MESSAGE("Incorrect B2 value after save and reload.", aCheckFunc
.checkB2(pEditText
));
1886 pEditText
= rDoc4
.GetEditText(ScAddress(1,3,0));
1887 CPPUNIT_ASSERT_MESSAGE("Incorrect B4 value after save and reload.", aCheckFunc
.checkB4(pEditText
));
1888 pEditText
= rDoc4
.GetEditText(ScAddress(1,4,0));
1889 CPPUNIT_ASSERT_MESSAGE("Incorrect B5 value after save and reload.", aCheckFunc
.checkB5(pEditText
));
1890 pEditText
= rDoc4
.GetEditText(ScAddress(1,5,0));
1891 CPPUNIT_ASSERT_MESSAGE("Incorrect B6 value after save and reload.", aCheckFunc
.checkB6(pEditText
));
1892 pEditText
= rDoc4
.GetEditText(ScAddress(1,6,0));
1893 CPPUNIT_ASSERT_MESSAGE("Incorrect B7 value after save and reload.", aCheckFunc
.checkB7(pEditText
));
1894 pEditText
= rDoc4
.GetEditText(ScAddress(1,7,0));
1895 CPPUNIT_ASSERT_MESSAGE("Incorrect B8 value after save and reload.", aCheckFunc
.checkB8(pEditText
));
1896 pEditText
= rDoc4
.GetEditText(ScAddress(1,9,0));
1897 CPPUNIT_ASSERT_MESSAGE("Incorrect B10 value after save and reload.", aCheckFunc
.checkB10(pEditText
));
1899 xNewDocSh3
->DoClose();
1902 void ScExportTest::testRichTextCellFormatXLSX()
1904 ScDocShellRef xDocSh
= loadDoc("cellformat.", FORMAT_XLS
);
1905 CPPUNIT_ASSERT(xDocSh
.is());
1907 std::shared_ptr
<utl::TempFile
> pXPathFile
= ScBootstrapFixture::exportTo(&(*xDocSh
), FORMAT_XLSX
);
1908 xmlDocPtr pSheet
= XPathHelper::parseExport(pXPathFile
, m_xSFactory
, "xl/worksheets/sheet1.xml");
1909 CPPUNIT_ASSERT(pSheet
);
1911 // make sure the only cell in this doc is assigned some formatting record
1912 OUString aCellFormat
= getXPath(pSheet
, "/x:worksheet/x:sheetData/x:row/x:c", "s");
1913 CPPUNIT_ASSERT_MESSAGE("Cell format is missing", !aCellFormat
.isEmpty());
1915 xmlDocPtr pStyles
= XPathHelper::parseExport(pXPathFile
, m_xSFactory
, "xl/styles.xml");
1916 CPPUNIT_ASSERT(pStyles
);
1918 OString nFormatIdx
= OString::number( aCellFormat
.toInt32() + 1 );
1919 const OString
aXPath1( "/x:styleSheet/x:cellXfs/x:xf[" + nFormatIdx
+ "]/x:alignment" );
1920 // formatting record is set to wrap text
1921 assertXPath(pStyles
, aXPath1
, "wrapText", "true");
1923 // see what font it references
1924 const OString
aXPath2( "/x:styleSheet/x:cellXfs/x:xf[" + nFormatIdx
+"]" );
1925 OUString aFontId
= getXPath(pStyles
, aXPath2
, "fontId");
1926 OString nFontIdx
= OString::number( aFontId
.toInt32() + 1 );
1928 // that font should be bold
1929 const OString
aXPath3("/x:styleSheet/x:fonts/x:font[" + nFontIdx
+ "]/x:b");
1930 assertXPath(pStyles
, aXPath3
, "val", "true");
1935 void ScExportTest::testFormulaRefSheetNameODS()
1937 ScDocShellRef xDocSh
= loadDoc("formula-quote-in-sheet-name.", FORMAT_ODS
, true);
1939 ScDocument
& rDoc
= xDocSh
->GetDocument();
1941 sc::AutoCalcSwitch
aACSwitch(rDoc
, true); // turn on auto calc.
1942 rDoc
.SetString(ScAddress(1,1,0), "='90''s Data'.B2");
1943 CPPUNIT_ASSERT_EQUAL(1.1, rDoc
.GetValue(ScAddress(1,1,0)));
1944 ASSERT_FORMULA_EQUAL(rDoc
, ScAddress(1,1,0), "'90''s Data'.B2", "Wrong formula");
1946 // Now, save and reload this document.
1947 ScDocShellRef xNewDocSh
= saveAndReload(xDocSh
.get(), FORMAT_ODS
);
1950 ScDocument
& rDoc
= xNewDocSh
->GetDocument();
1952 CPPUNIT_ASSERT_EQUAL(1.1, rDoc
.GetValue(ScAddress(1,1,0)));
1953 ASSERT_FORMULA_EQUAL(rDoc
, ScAddress(1,1,0), "'90''s Data'.B2", "Wrong formula");
1955 xNewDocSh
->DoClose();
1958 void ScExportTest::testCellValuesExportODS()
1960 // Start with an empty document
1961 ScDocShellRef xOrigDocSh
= loadDoc("empty.", FORMAT_ODS
);
1963 ScDocument
& rDoc
= xOrigDocSh
->GetDocument();
1964 CPPUNIT_ASSERT_MESSAGE("This document should at least have one sheet.", rDoc
.GetTableCount() > 0);
1966 // set a value double
1967 rDoc
.SetValue(ScAddress(0,0,0), 2.0); // A1
1970 rDoc
.SetValue(ScAddress(2,0,0), 3.0); // C1
1971 rDoc
.SetValue(ScAddress(3,0,0), 3); // D1
1972 rDoc
.SetString(ScAddress(4,0,0), "=10*C1/4"); // E1
1973 rDoc
.SetValue(ScAddress(5,0,0), 3.0); // F1
1974 rDoc
.SetString(ScAddress(7,0,0), "=SUM(C1:F1)"); //H1
1977 rDoc
.SetString(ScAddress(0,2,0), "a simple line"); //A3
1979 // set a digit string
1980 rDoc
.SetString(ScAddress(0,4,0), "'12"); //A5
1981 // set a contiguous value
1982 rDoc
.SetValue(ScAddress(0,5,0), 12.0); //A6
1983 // set a contiguous string
1984 rDoc
.SetString(ScAddress(0,6,0), "a string"); //A7
1985 // set a contiguous formula
1986 rDoc
.SetString(ScAddress(0,7,0), "=$A$6"); //A8
1989 ScDocShellRef xNewDocSh
= saveAndReload(xOrigDocSh
.get(), FORMAT_ODS
);
1990 xOrigDocSh
->DoClose();
1991 CPPUNIT_ASSERT(xNewDocSh
.is());
1992 ScDocument
& rDoc
= xNewDocSh
->GetDocument();
1993 CPPUNIT_ASSERT_MESSAGE("Reloaded document should at least have one sheet.", rDoc
.GetTableCount() > 0);
1996 CPPUNIT_ASSERT_EQUAL(2.0, rDoc
.GetValue(0,0,0));
1997 CPPUNIT_ASSERT_EQUAL(3.0, rDoc
.GetValue(2,0,0));
1998 CPPUNIT_ASSERT_EQUAL(3.0, rDoc
.GetValue(3,0,0));
1999 CPPUNIT_ASSERT_EQUAL(7.5, rDoc
.GetValue(4,0,0));
2000 CPPUNIT_ASSERT_EQUAL(3.0, rDoc
.GetValue(5,0,0));
2003 ASSERT_FORMULA_EQUAL(rDoc
, ScAddress(4,0,0), "10*C1/4", "Wrong formula =10*C1/4");
2004 ASSERT_FORMULA_EQUAL(rDoc
, ScAddress(7,0,0), "SUM(C1:F1)", "Wrong formula =SUM(C1:F1)");
2005 CPPUNIT_ASSERT_EQUAL(16.5, rDoc
.GetValue(7,0,0));
2008 ScRefCellValue aCell
;
2009 aCell
.assign(rDoc
, ScAddress(0,2,0));
2010 CPPUNIT_ASSERT_EQUAL( CELLTYPE_STRING
, aCell
.meType
);
2012 // check for an empty cell
2013 aCell
.assign(rDoc
, ScAddress(0,3,0));
2014 CPPUNIT_ASSERT_EQUAL( CELLTYPE_NONE
, aCell
.meType
);
2016 // check a digit string
2017 aCell
.assign(rDoc
, ScAddress(0,4,0));
2018 CPPUNIT_ASSERT_EQUAL( CELLTYPE_STRING
, aCell
.meType
);
2020 //check contiguous values
2021 CPPUNIT_ASSERT_EQUAL( 12.0, rDoc
.GetValue(0,5,0) );
2022 CPPUNIT_ASSERT_EQUAL( OUString("a string"), rDoc
.GetString(0,6,0) );
2023 ASSERT_FORMULA_EQUAL(rDoc
, ScAddress(0,7,0), "$A$6", "Wrong formula =$A$6");
2024 CPPUNIT_ASSERT_EQUAL( rDoc
.GetValue(0,5,0), rDoc
.GetValue(0,7,0) );
2026 xNewDocSh
->DoClose();
2029 void ScExportTest::testCellNoteExportODS()
2031 ScDocShellRef xOrigDocSh
= loadDoc("single-note.", FORMAT_ODS
);
2032 ScAddress
aPos(0,0,0); // Start with A1.
2034 ScDocument
& rDoc
= xOrigDocSh
->GetDocument();
2036 CPPUNIT_ASSERT_MESSAGE("There should be a note at A1.", rDoc
.HasNote(aPos
));
2038 aPos
.IncRow(); // Move to A2.
2039 ScPostIt
* pNote
= rDoc
.GetOrCreateNote(aPos
);
2040 pNote
->SetText(aPos
, "Note One");
2041 pNote
->SetAuthor("Author One");
2042 CPPUNIT_ASSERT_MESSAGE("There should be a note at A2.", rDoc
.HasNote(aPos
));
2045 ScDocShellRef xNewDocSh
= saveAndReload(xOrigDocSh
.get(), FORMAT_ODS
);
2046 xOrigDocSh
->DoClose();
2047 CPPUNIT_ASSERT(xNewDocSh
.is());
2048 ScDocument
& rDoc
= xNewDocSh
->GetDocument();
2050 aPos
.SetRow(0); // Move back to A1.
2051 CPPUNIT_ASSERT_MESSAGE("There should be a note at A1.", rDoc
.HasNote(aPos
));
2052 aPos
.IncRow(); // Move to A2.
2053 CPPUNIT_ASSERT_MESSAGE("There should be a note at A2.", rDoc
.HasNote(aPos
));
2055 xNewDocSh
->DoClose();
2058 void ScExportTest::testCellNoteExportXLS()
2060 // Start with an empty document.s
2061 ScDocShellRef xOrigDocSh
= loadDoc("notes-on-3-sheets.", FORMAT_ODS
);
2063 ScDocument
& rDoc
= xOrigDocSh
->GetDocument();
2064 CPPUNIT_ASSERT_EQUAL_MESSAGE("This document should have 3 sheets.", SCTAB(3), rDoc
.GetTableCount());
2066 // Check note's presence.
2067 CPPUNIT_ASSERT( rDoc
.HasNote(ScAddress(0,0,0)));
2068 CPPUNIT_ASSERT(!rDoc
.HasNote(ScAddress(0,1,0)));
2069 CPPUNIT_ASSERT(!rDoc
.HasNote(ScAddress(0,2,0)));
2071 CPPUNIT_ASSERT(!rDoc
.HasNote(ScAddress(0,0,1)));
2072 CPPUNIT_ASSERT( rDoc
.HasNote(ScAddress(0,1,1)));
2073 CPPUNIT_ASSERT(!rDoc
.HasNote(ScAddress(0,2,1)));
2075 CPPUNIT_ASSERT(!rDoc
.HasNote(ScAddress(0,0,2)));
2076 CPPUNIT_ASSERT(!rDoc
.HasNote(ScAddress(0,1,2)));
2077 CPPUNIT_ASSERT( rDoc
.HasNote(ScAddress(0,2,2)));
2079 // save and reload as XLS.
2080 ScDocShellRef xNewDocSh
= saveAndReload(xOrigDocSh
.get(), FORMAT_XLS
);
2082 xOrigDocSh
->DoClose();
2083 CPPUNIT_ASSERT(xNewDocSh
.is());
2084 ScDocument
& rDoc
= xNewDocSh
->GetDocument();
2085 CPPUNIT_ASSERT_EQUAL_MESSAGE("This document should have 3 sheets.", SCTAB(3), rDoc
.GetTableCount());
2087 // Check note's presence again.
2088 CPPUNIT_ASSERT( rDoc
.HasNote(ScAddress(0,0,0)));
2089 CPPUNIT_ASSERT(!rDoc
.HasNote(ScAddress(0,1,0)));
2090 CPPUNIT_ASSERT(!rDoc
.HasNote(ScAddress(0,2,0)));
2092 CPPUNIT_ASSERT(!rDoc
.HasNote(ScAddress(0,0,1)));
2093 CPPUNIT_ASSERT( rDoc
.HasNote(ScAddress(0,1,1)));
2094 CPPUNIT_ASSERT(!rDoc
.HasNote(ScAddress(0,2,1)));
2096 CPPUNIT_ASSERT(!rDoc
.HasNote(ScAddress(0,0,2)));
2097 CPPUNIT_ASSERT(!rDoc
.HasNote(ScAddress(0,1,2)));
2098 CPPUNIT_ASSERT( rDoc
.HasNote(ScAddress(0,2,2)));
2100 xNewDocSh
->DoClose();
2106 void checkMatrixRange(ScDocument
& rDoc
, const ScRange
& rRange
)
2109 ScAddress aMatOrigin
;
2110 for (SCCOL nCol
= rRange
.aStart
.Col(); nCol
<= rRange
.aEnd
.Col(); ++nCol
)
2112 for (SCROW nRow
= rRange
.aStart
.Row(); nRow
<= rRange
.aEnd
.Row(); ++nRow
)
2114 ScAddress
aPos(nCol
, nRow
, rRange
.aStart
.Tab());
2115 bool bIsMatrix
= rDoc
.GetMatrixFormulaRange(aPos
, aMatRange
);
2116 CPPUNIT_ASSERT_MESSAGE("Matrix expected, but not found.", bIsMatrix
);
2117 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong matrix range.", rRange
, aMatRange
);
2118 const ScFormulaCell
* pCell
= rDoc
.GetFormulaCell(aPos
);
2119 CPPUNIT_ASSERT_MESSAGE("This must be a formula cell.", pCell
);
2121 bIsMatrix
= pCell
->GetMatrixOrigin(aMatOrigin
);
2122 CPPUNIT_ASSERT_MESSAGE("Not a part of matrix formula.", bIsMatrix
);
2123 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong matrix origin.", aMatRange
.aStart
, aMatOrigin
);
2130 void ScExportTest::testInlineArrayXLS()
2132 ScDocShellRef xShell
= loadDoc("inline-array.", FORMAT_XLS
);
2133 CPPUNIT_ASSERT(xShell
.is());
2135 ScDocShellRef xDocSh
= saveAndReload(xShell
.get(), FORMAT_XLS
);
2137 CPPUNIT_ASSERT(xDocSh
.is());
2139 ScDocument
& rDoc
= xDocSh
->GetDocument();
2141 // B2:C3 contains a matrix.
2142 checkMatrixRange(rDoc
, ScRange(1,1,0,2,2,0));
2144 // B5:D6 contains a matrix.
2145 checkMatrixRange(rDoc
, ScRange(1,4,0,3,5,0));
2148 checkMatrixRange(rDoc
, ScRange(1,7,0,2,9,0));
2153 void ScExportTest::testEmbeddedChartODS()
2155 ScDocShellRef xShell
= loadDoc("embedded-chart.", FORMAT_XLS
);
2156 CPPUNIT_ASSERT(xShell
.is());
2158 std::shared_ptr
<utl::TempFile
> pTempFile(
2159 ScBootstrapFixture::exportTo(xShell
.get(), FORMAT_ODS
));
2161 xmlDocPtr pDoc
= XPathHelper::parseExport(pTempFile
, m_xSFactory
, "content.xml");
2162 CPPUNIT_ASSERT(pDoc
);
2164 "/office:document-content/office:body/office:spreadsheet/table:table[2]/table:table-row[7]/table:table-cell[2]/draw:frame/draw:object",
2165 "notify-on-update-of-ranges",
2166 "Chart1.B3:Chart1.B5 Chart1.C2:Chart1.C2 Chart1.C3:Chart1.C5");
2171 void ScExportTest::testEmbeddedChartXLS()
2173 ScDocShellRef xShell
= loadDoc("embedded-chart.", FORMAT_XLS
);
2174 CPPUNIT_ASSERT(xShell
.is());
2176 ScDocShellRef xDocSh
= saveAndReload(xShell
.get(), FORMAT_XLS
);
2178 CPPUNIT_ASSERT(xDocSh
.is());
2180 ScDocument
& rDoc
= xDocSh
->GetDocument();
2182 // Make sure the 2nd sheet is named 'Chart1'.
2184 rDoc
.GetName(1, aName
);
2185 CPPUNIT_ASSERT_EQUAL(OUString("Chart1"), aName
);
2187 const SdrOle2Obj
* pOleObj
= getSingleChartObject(rDoc
, 1);
2188 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve a chart object from the 2nd sheet.", pOleObj
);
2190 ScRangeList aRanges
= getChartRanges(rDoc
, *pOleObj
);
2191 CPPUNIT_ASSERT_MESSAGE("Label range (B3:B5) not found.", aRanges
.In(ScRange(1,2,1,1,4,1)));
2192 CPPUNIT_ASSERT_MESSAGE("Data label (C2) not found.", aRanges
.In(ScAddress(2,1,1)));
2193 CPPUNIT_ASSERT_MESSAGE("Data range (C3:C5) not found.", aRanges
.In(ScRange(2,2,1,2,4,1)));
2198 void ScExportTest::testCellAnchoredGroupXLS()
2200 ScDocShellRef xDocSh_in
= loadDoc("cell-anchored-group.", FORMAT_XLS
);
2201 CPPUNIT_ASSERT_MESSAGE("Failed to load cell-anchored-group.xls", xDocSh_in
.is());
2203 ScDocShellRef xDocSh
= saveAndReload(&(*xDocSh_in
), FORMAT_ODS
);
2204 CPPUNIT_ASSERT_MESSAGE("Failed to save and reload cell-anchored-group.ods", xDocSh
.is());
2206 // the document contains a group anchored on the first cell, make sure it's there in the right place
2207 ScDocument
& rDoc
= xDocSh
->GetDocument();
2208 CPPUNIT_ASSERT_MESSAGE("There should be at least one sheet.", rDoc
.GetTableCount() > 0);
2209 ScDrawLayer
* pDrawLayer
= rDoc
.GetDrawLayer();
2210 SdrPage
* pPage
= pDrawLayer
->GetPage(0);
2211 CPPUNIT_ASSERT_MESSAGE("draw page for sheet 1 should exist.", pPage
);
2212 const size_t nCount
= pPage
->GetObjCount();
2213 CPPUNIT_ASSERT_EQUAL_MESSAGE(
2214 "There should be 1 objects.", static_cast<size_t>(1), nCount
);
2216 SdrObject
* pObj
= pPage
->GetObj(0);
2217 CPPUNIT_ASSERT_MESSAGE("Failed to get drawing object.", pObj
);
2218 ScDrawObjData
* pData
= ScDrawLayer::GetObjData(pObj
);
2219 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData
);
2220 CPPUNIT_ASSERT_MESSAGE("Upper left of bounding rectangle should be nonnegative.",
2221 pData
->getShapeRect().Left() >= 0 || pData
->getShapeRect().Top() >= 0);
2225 void ScExportTest::testFormulaReferenceXLS()
2227 ScDocShellRef xShell
= loadDoc("formula-reference.", FORMAT_XLS
);
2228 CPPUNIT_ASSERT(xShell
.is());
2230 ScDocShellRef xDocSh
= saveAndReload(xShell
.get(), FORMAT_XLS
);
2232 CPPUNIT_ASSERT(xDocSh
.is());
2234 ScDocument
& rDoc
= xDocSh
->GetDocument();
2236 ASSERT_FORMULA_EQUAL(rDoc
, ScAddress(3,1,0), "$A$2+$B$2+$C$2", "Wrong formula in D2");
2237 ASSERT_FORMULA_EQUAL(rDoc
, ScAddress(3,2,0), "A3+B3+C3", "Wrong formula in D3");
2238 ASSERT_FORMULA_EQUAL(rDoc
, ScAddress(3,5,0), "SUM($A$6:$C$6)", "Wrong formula in D6");
2239 ASSERT_FORMULA_EQUAL(rDoc
, ScAddress(3,6,0), "SUM(A7:C7)", "Wrong formula in D7");
2240 ASSERT_FORMULA_EQUAL(rDoc
, ScAddress(3,9,0), "$Two.$A$2+$Two.$B$2+$Two.$C$2", "Wrong formula in D10");
2241 ASSERT_FORMULA_EQUAL(rDoc
, ScAddress(3,10,0), "$Two.A3+$Two.B3+$Two.C3", "Wrong formula in D11");
2242 ASSERT_FORMULA_EQUAL(rDoc
, ScAddress(3,13,0), "MIN($Two.$A$2:$C$2)", "Wrong formula in D14");
2243 ASSERT_FORMULA_EQUAL(rDoc
, ScAddress(3,14,0), "MAX($Two.A3:C3)", "Wrong formula in D15");
2248 void ScExportTest::testSheetProtectionXLSX()
2250 ScDocShellRef xShell
= loadDoc("ProtecteSheet1234Pass.", FORMAT_XLSX
);
2251 CPPUNIT_ASSERT(xShell
.is());
2253 ScDocShellRef xDocSh
= saveAndReload(xShell
.get(), FORMAT_XLSX
);
2254 CPPUNIT_ASSERT(xDocSh
.is());
2256 ScDocument
& rDoc
= xDocSh
->GetDocument();
2257 const ScTableProtection
* pTabProtect
= rDoc
.GetTabProtection(0);
2258 CPPUNIT_ASSERT(pTabProtect
);
2259 Sequence
<sal_Int8
> aHash
= pTabProtect
->getPasswordHash(PASSHASH_XL
);
2261 if (aHash
.getLength() >= 2)
2263 CPPUNIT_ASSERT_EQUAL(sal_uInt8(204), static_cast<sal_uInt8
>(aHash
[0]));
2264 CPPUNIT_ASSERT_EQUAL(sal_uInt8(61), static_cast<sal_uInt8
>(aHash
[1]));
2266 // we could flesh out this check I guess
2267 CPPUNIT_ASSERT ( !pTabProtect
->isOptionEnabled( ScTableProtection::OBJECTS
) );
2268 CPPUNIT_ASSERT ( !pTabProtect
->isOptionEnabled( ScTableProtection::SCENARIOS
) );
2272 void ScExportTest::testSheetProtectionXLSB()
2274 ScDocShellRef xShell
= loadDoc("tdf108017_calcProtection.", FORMAT_XLSB
);
2275 CPPUNIT_ASSERT(xShell
.is());
2277 ScDocShellRef xDocSh
= saveAndReload(xShell
.get(), FORMAT_XLSX
);
2278 CPPUNIT_ASSERT(xDocSh
.is());
2280 ScDocument
& rDoc
= xDocSh
->GetDocument();
2281 const ScTableProtection
* pTabProtect
= rDoc
.GetTabProtection(0);
2282 CPPUNIT_ASSERT(pTabProtect
);
2283 CPPUNIT_ASSERT(pTabProtect
->isOptionEnabled( ScTableProtection::SELECT_UNLOCKED_CELLS
));
2284 CPPUNIT_ASSERT(!pTabProtect
->isOptionEnabled( ScTableProtection::SELECT_LOCKED_CELLS
));
2290 const char* toBorderName( SvxBorderLineStyle eStyle
)
2294 case SvxBorderLineStyle::SOLID
: return "SOLID";
2295 case SvxBorderLineStyle::DOTTED
: return "DOTTED";
2296 case SvxBorderLineStyle::DASHED
: return "DASHED";
2297 case SvxBorderLineStyle::DASH_DOT
: return "DASH_DOT";
2298 case SvxBorderLineStyle::DASH_DOT_DOT
: return "DASH_DOT_DOT";
2299 case SvxBorderLineStyle::DOUBLE_THIN
: return "DOUBLE_THIN";
2300 case SvxBorderLineStyle::FINE_DASHED
: return "FINE_DASHED";
2310 void ScExportTest::testExcelCellBorders( sal_uLong nFormatType
)
2315 SvxBorderLineStyle mnStyle
;
2318 { 1, SvxBorderLineStyle::SOLID
, 1 }, // hair
2319 { 3, SvxBorderLineStyle::DOTTED
, 15 }, // dotted
2320 { 5, SvxBorderLineStyle::DASH_DOT_DOT
, 15 }, // dash dot dot
2321 { 7, SvxBorderLineStyle::DASH_DOT
, 15 }, // dash dot
2322 { 9, SvxBorderLineStyle::FINE_DASHED
, 15 }, // dashed
2323 { 11, SvxBorderLineStyle::SOLID
, 15 }, // thin
2324 { 13, SvxBorderLineStyle::DASH_DOT_DOT
, 35 }, // medium dash dot dot
2325 { 17, SvxBorderLineStyle::DASH_DOT
, 35 }, // medium dash dot
2326 { 19, SvxBorderLineStyle::DASHED
, 35 }, // medium dashed
2327 { 21, SvxBorderLineStyle::SOLID
, 35 }, // medium
2328 { 23, SvxBorderLineStyle::SOLID
, 50 }, // thick
2329 { 25, SvxBorderLineStyle::DOUBLE_THIN
, -1 }, // double (don't check width)
2332 ScDocShellRef xDocSh
= loadDoc("cell-borders.", nFormatType
);
2333 CPPUNIT_ASSERT_MESSAGE("Failed to load file", xDocSh
.is());
2335 ScDocument
& rDoc
= xDocSh
->GetDocument();
2337 for (size_t i
= 0; i
< SAL_N_ELEMENTS(aChecks
); ++i
)
2339 const editeng::SvxBorderLine
* pLine
= nullptr;
2340 rDoc
.GetBorderLines(2, aChecks
[i
].mnRow
, 0, nullptr, &pLine
, nullptr, nullptr);
2341 CPPUNIT_ASSERT(pLine
);
2342 CPPUNIT_ASSERT_EQUAL(toBorderName(aChecks
[i
].mnStyle
), toBorderName(pLine
->GetBorderLineStyle()));
2343 if (aChecks
[i
].mnWidth
>= 0)
2344 CPPUNIT_ASSERT_EQUAL(aChecks
[i
].mnWidth
, pLine
->GetWidth());
2348 ScDocShellRef xNewDocSh
= saveAndReload(xDocSh
.get(), nFormatType
);
2350 ScDocument
& rDoc
= xNewDocSh
->GetDocument();
2351 for (size_t i
= 0; i
< SAL_N_ELEMENTS(aChecks
); ++i
)
2353 const editeng::SvxBorderLine
* pLine
= nullptr;
2354 rDoc
.GetBorderLines(2, aChecks
[i
].mnRow
, 0, nullptr, &pLine
, nullptr, nullptr);
2355 CPPUNIT_ASSERT(pLine
);
2356 CPPUNIT_ASSERT_EQUAL(toBorderName(aChecks
[i
].mnStyle
), toBorderName(pLine
->GetBorderLineStyle()));
2357 if (aChecks
[i
].mnWidth
>= 0)
2358 CPPUNIT_ASSERT_EQUAL(aChecks
[i
].mnWidth
, pLine
->GetWidth());
2361 xNewDocSh
->DoClose();
2364 void ScExportTest::testCellBordersXLS()
2366 testExcelCellBorders(FORMAT_XLS
);
2369 void ScExportTest::testCellBordersXLSX()
2371 testExcelCellBorders(FORMAT_XLSX
);
2374 void ScExportTest::testBordersExchangeXLSX()
2376 // Document: sc/qa/unit/data/README.cellborders
2378 // short name for the table
2379 const SvxBorderLineStyle None
= SvxBorderLineStyle::NONE
;
2380 const SvxBorderLineStyle Solid
= SvxBorderLineStyle::SOLID
;
2381 const SvxBorderLineStyle Dotted
= SvxBorderLineStyle::DOTTED
;
2382 const SvxBorderLineStyle Dashed
= SvxBorderLineStyle::DASHED
;
2383 const SvxBorderLineStyle FineDash
= SvxBorderLineStyle::FINE_DASHED
;
2384 const SvxBorderLineStyle DashDot
= SvxBorderLineStyle::DASH_DOT
;
2385 const SvxBorderLineStyle DashDoDo
= SvxBorderLineStyle::DASH_DOT_DOT
;
2386 const SvxBorderLineStyle DoubThin
= SvxBorderLineStyle::DOUBLE_THIN
;
2388 const size_t nMaxCol
= 18;
2389 const size_t nMaxRow
= 7;
2393 SvxBorderLineStyle BorderStyleTop
, BorderStyleBottom
;
2394 long WidthTop
, WidthBottom
;
2395 } aCheckBorderWidth
[nMaxCol
][nMaxRow
] =
2397 /* Line 1 2 3 4 5 6 7
2398 SOLID DOTTED DASHED FINE_DASHED DASH_DOT DASH_DOT_DOT DOUBLE_THIN */
2400 /* 0,05 */ {{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}},
2401 /* 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}},
2402 /* 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}},
2403 /* 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}},
2404 /* 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}},
2405 /* 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}},
2406 /* 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}},
2408 /* 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}},
2409 /* 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}},
2410 /* 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}},
2412 /* 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}},
2413 /* 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}},
2414 /* 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}},
2415 /* 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}},
2416 /* 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}},
2417 /* 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}},
2418 /* 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}},
2419 /* 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}}
2422 ScDocShellRef xShell
= loadDoc("test_borders_export.", FORMAT_ODS
); // load the ods with our Borders
2423 CPPUNIT_ASSERT(xShell
.is());
2425 ScDocShellRef xDocSh
= saveAndReload(&(*xShell
), FORMAT_XLSX
); // save the ods to xlsx and load xlsx
2426 CPPUNIT_ASSERT(xDocSh
.is());
2427 ScDocument
& rDoc
= xDocSh
->GetDocument();
2429 for (size_t nCol
= 0; nCol
< nMaxCol
; ++nCol
)
2431 for (size_t nRow
= 0; nRow
< nMaxRow
; ++nRow
)
2433 const editeng::SvxBorderLine
* pLineTop
= nullptr;
2434 const editeng::SvxBorderLine
* pLineBottom
= nullptr;
2435 rDoc
.GetBorderLines(nCol
+ 2, (nRow
* 2) + 8, 0, nullptr, &pLineTop
, nullptr, &pLineBottom
);
2436 if((nCol
< 3) && (nRow
== 6))
2437 { // in this range no lines since minimum size to create a double is 0.5
2438 CPPUNIT_ASSERT(!pLineTop
);
2439 CPPUNIT_ASSERT(!pLineBottom
);
2444 CPPUNIT_ASSERT(pLineTop
);
2445 CPPUNIT_ASSERT(pLineBottom
);
2448 CPPUNIT_ASSERT_EQUAL_MESSAGE("Top Border-Line-Style wrong", aCheckBorderWidth
[nCol
][nRow
].BorderStyleTop
,
2449 pLineTop
->GetBorderLineStyle());
2450 CPPUNIT_ASSERT_EQUAL_MESSAGE("Bottom Border-Line-Style wrong", aCheckBorderWidth
[nCol
][nRow
].BorderStyleBottom
,
2451 pLineBottom
->GetBorderLineStyle());
2452 CPPUNIT_ASSERT_EQUAL_MESSAGE("Top Width-Line wrong", aCheckBorderWidth
[nCol
][nRow
].WidthTop
,
2453 pLineTop
->GetWidth());
2454 CPPUNIT_ASSERT_EQUAL_MESSAGE("Bottom Width-Line wrong", aCheckBorderWidth
[nCol
][nRow
].WidthBottom
,
2455 pLineBottom
->GetWidth());
2462 static OUString
toString( const ScBigRange
& rRange
)
2464 OUStringBuffer aBuf
;
2465 aBuf
.append("(columns:");
2466 aBuf
.append(rRange
.aStart
.Col());
2468 aBuf
.append(rRange
.aEnd
.Col());
2469 aBuf
.append(";rows:");
2470 aBuf
.append(rRange
.aStart
.Row());
2472 aBuf
.append(rRange
.aEnd
.Row());
2473 aBuf
.append(";sheets:");
2474 aBuf
.append(rRange
.aStart
.Tab());
2476 aBuf
.append(rRange
.aEnd
.Tab());
2479 return aBuf
.makeStringAndClear();
2482 void ScExportTest::testTrackChangesSimpleXLSX()
2486 sal_uLong mnActionId
;
2487 ScChangeActionType meType
;
2489 sal_Int32 mnStartCol
;
2490 sal_Int32 mnStartRow
;
2491 sal_Int32 mnStartTab
;
2496 bool mbRowInsertedAtBottom
;
2501 bool checkRange( ScChangeActionType eType
, const ScBigRange
& rExpected
, const ScBigRange
& rActual
)
2503 ScBigRange
aExpected(rExpected
), aActual(rActual
);
2507 case SC_CAT_INSERT_ROWS
:
2510 aExpected
.aStart
.SetCol(0);
2511 aExpected
.aEnd
.SetCol(0);
2512 aActual
.aStart
.SetCol(0);
2513 aActual
.aEnd
.SetCol(0);
2520 return aExpected
== aActual
;
2523 bool check( const ScDocument
& rDoc
)
2525 static const CheckItem aChecks
[] =
2527 { 1, SC_CAT_CONTENT
, 1, 1, 0, 1, 1, 0, false },
2528 { 2, SC_CAT_INSERT_ROWS
, 0, 2, 0, 0, 2, 0, true },
2529 { 3, SC_CAT_CONTENT
, 1, 2, 0, 1, 2, 0, false },
2530 { 4, SC_CAT_INSERT_ROWS
, 0, 3, 0, 0, 3, 0, true },
2531 { 5, SC_CAT_CONTENT
, 1, 3, 0, 1, 3, 0, false },
2532 { 6, SC_CAT_INSERT_ROWS
, 0, 4, 0, 0, 4, 0, true },
2533 { 7, SC_CAT_CONTENT
, 1, 4, 0, 1, 4, 0, false },
2534 { 8, SC_CAT_INSERT_ROWS
, 0, 5, 0, 0, 5, 0, true },
2535 { 9, SC_CAT_CONTENT
, 1, 5, 0, 1, 5, 0, false },
2536 { 10, SC_CAT_INSERT_ROWS
, 0, 6, 0, 0, 6, 0, true },
2537 { 11, SC_CAT_CONTENT
, 1, 6, 0, 1, 6, 0, false },
2538 { 12, SC_CAT_INSERT_ROWS
, 0, 7, 0, 0, 7, 0, true },
2539 { 13, SC_CAT_CONTENT
, 1, 7, 0, 1, 7, 0, false },
2542 ScChangeTrack
* pCT
= rDoc
.GetChangeTrack();
2545 cerr
<< "Change track instance doesn't exist." << endl
;
2549 sal_uLong nActionMax
= pCT
->GetActionMax();
2550 if (nActionMax
!= 13)
2552 cerr
<< "Unexpected highest action ID value." << endl
;
2556 for (size_t i
= 0; i
< SAL_N_ELEMENTS(aChecks
); ++i
)
2558 sal_uInt16 nActId
= aChecks
[i
].mnActionId
;
2559 const ScChangeAction
* pAction
= pCT
->GetAction(nActId
);
2562 cerr
<< "No action for action number " << nActId
<< " found." << endl
;
2566 if (pAction
->GetType() != aChecks
[i
].meType
)
2568 cerr
<< "Unexpected action type for action number " << nActId
<< "." << endl
;
2572 const ScBigRange
& rRange
= pAction
->GetBigRange();
2573 ScBigRange
aCheck(aChecks
[i
].mnStartCol
, aChecks
[i
].mnStartRow
, aChecks
[i
].mnStartTab
,
2574 aChecks
[i
].mnEndCol
, aChecks
[i
].mnEndRow
, aChecks
[i
].mnEndTab
);
2576 if (!checkRange(pAction
->GetType(), aCheck
, rRange
))
2578 cerr
<< "Unexpected range for action number " << nActId
2579 << ": expected=" << toString(aCheck
) << " actual=" << toString(rRange
) << endl
;
2583 switch (pAction
->GetType())
2585 case SC_CAT_INSERT_ROWS
:
2587 const ScChangeActionIns
* p
= static_cast<const ScChangeActionIns
*>(pAction
);
2588 if (p
->IsEndOfList() != aChecks
[i
].mbRowInsertedAtBottom
)
2590 cerr
<< "Unexpected end-of-list flag for action number " << nActId
<< "." << endl
;
2603 bool checkRevisionUserAndTime( ScDocument
& rDoc
, const OUString
& rOwnerName
)
2605 ScChangeTrack
* pCT
= rDoc
.GetChangeTrack();
2608 cerr
<< "Change track instance doesn't exist." << endl
;
2612 ScChangeAction
* pAction
= pCT
->GetLast();
2613 if (pAction
->GetUser() != "Kohei Yoshida")
2615 cerr
<< "Wrong user name." << endl
;
2619 DateTime aDT
= pAction
->GetDateTime();
2620 if (aDT
.GetYear() != 2014 || aDT
.GetMonth() != 7 || aDT
.GetDay() != 11)
2622 cerr
<< "Wrong time stamp." << endl
;
2626 // Insert a new record to make sure the user and date-time are correct.
2627 rDoc
.SetString(ScAddress(1,8,0), "New String");
2629 pCT
->AppendContent(ScAddress(1,8,0), aEmpty
);
2630 pAction
= pCT
->GetLast();
2633 cerr
<< "Failed to retrieve last revision." << endl
;
2637 if (rOwnerName
!= pAction
->GetUser())
2639 cerr
<< "Wrong user name." << endl
;
2643 DateTime aDTNew
= pAction
->GetDateTime();
2646 cerr
<< "Time stamp of the new revision should be more recent than that of the last revision." << endl
;
2655 SvtUserOptions
& rUserOpt
= SC_MOD()->GetUserOptions();
2656 rUserOpt
.SetToken(UserOptToken::FirstName
, "Export");
2657 rUserOpt
.SetToken(UserOptToken::LastName
, "Test");
2659 OUString aOwnerName
= rUserOpt
.GetFirstName() + " " + rUserOpt
.GetLastName();
2661 // First, test the xls variant.
2663 ScDocShellRef xDocSh
= loadDoc("track-changes/simple-cell-changes.", FORMAT_XLS
);
2664 CPPUNIT_ASSERT(xDocSh
.is());
2665 ScDocument
* pDoc
= &xDocSh
->GetDocument();
2666 bool bGood
= aTest
.check(*pDoc
);
2667 CPPUNIT_ASSERT_MESSAGE("Initial check failed (xls).", bGood
);
2669 ScDocShellRef xDocSh2
= saveAndReload(xDocSh
.get(), FORMAT_XLS
);
2671 pDoc
= &xDocSh2
->GetDocument();
2672 bGood
= aTest
.check(*pDoc
);
2673 CPPUNIT_ASSERT_MESSAGE("Check after reload failed (xls).", bGood
);
2675 // fdo#81445 : Check the blank value string to make sure it's "<empty>".
2676 ScChangeTrack
* pCT
= pDoc
->GetChangeTrack();
2677 CPPUNIT_ASSERT(pCT
);
2678 ScChangeAction
* pAction
= pCT
->GetAction(1);
2679 CPPUNIT_ASSERT(pAction
);
2681 pAction
->GetDescription(aDesc
, pDoc
);
2682 CPPUNIT_ASSERT_EQUAL(OUString("Cell B2 changed from '<empty>' to '1'"), aDesc
);
2684 bGood
= aTest
.checkRevisionUserAndTime(*pDoc
, aOwnerName
);
2685 CPPUNIT_ASSERT_MESSAGE("Check revision and time failed after reload (xls).", bGood
);
2689 // Now, test the xlsx variant the same way.
2691 xDocSh
= loadDoc("track-changes/simple-cell-changes.", FORMAT_XLSX
);
2692 CPPUNIT_ASSERT(xDocSh
.is());
2693 pDoc
= &xDocSh
->GetDocument();
2695 CPPUNIT_ASSERT_MESSAGE("Initial check failed (xlsx).", bGood
);
2697 xDocSh2
= saveAndReload(xDocSh
.get(), FORMAT_XLSX
);
2699 pDoc
= &xDocSh2
->GetDocument();
2700 bGood
= aTest
.check(*pDoc
);
2701 CPPUNIT_ASSERT_MESSAGE("Check after reload failed (xlsx).", bGood
);
2703 bGood
= aTest
.checkRevisionUserAndTime(*pDoc
, aOwnerName
);
2704 CPPUNIT_ASSERT_MESSAGE("Check revision and time failed after reload (xlsx).", bGood
);
2709 void ScExportTest::testSheetTabColorsXLSX()
2713 bool checkContent( const ScDocument
& rDoc
)
2716 std::vector
<OUString
> aTabNames
= rDoc
.GetAllTableNames();
2718 // green, red, blue, yellow (from left to right).
2719 if (aTabNames
.size() != 4)
2721 cerr
<< "There should be exactly 4 sheets." << endl
;
2725 const char* pNames
[] = { "Green", "Red", "Blue", "Yellow" };
2726 for (size_t i
= 0; i
< SAL_N_ELEMENTS(pNames
); ++i
)
2728 OUString aExpected
= OUString::createFromAscii(pNames
[i
]);
2729 if (aExpected
!= aTabNames
[i
])
2731 cerr
<< "incorrect sheet name: expected='" << aExpected
<<"', actual='" << aTabNames
[i
] << "'" << endl
;
2736 static const Color aXclColors
[] =
2738 0x0000B050, // green
2741 0x00FFFF00, // yellow
2744 for (size_t i
= 0; i
< SAL_N_ELEMENTS(aXclColors
); ++i
)
2746 if (aXclColors
[i
] != rDoc
.GetTabBgColor(i
))
2748 cerr
<< "wrong sheet color for sheet " << i
<< endl
;
2758 ScDocShellRef xDocSh
= loadDoc("sheet-tab-color.", FORMAT_XLSX
);
2760 CPPUNIT_ASSERT_MESSAGE("Failed to load file.", xDocSh
.is());
2761 ScDocument
& rDoc
= xDocSh
->GetDocument();
2762 bool bRes
= aTest
.checkContent(rDoc
);
2763 CPPUNIT_ASSERT_MESSAGE("Failed on the initial content check.", bRes
);
2766 ScDocShellRef xDocSh2
= saveAndReload(xDocSh
.get(), FORMAT_XLSX
);
2767 CPPUNIT_ASSERT_MESSAGE("Failed to reload file.", xDocSh2
.is());
2769 ScDocument
& rDoc
= xDocSh2
->GetDocument();
2770 bool bRes
= aTest
.checkContent(rDoc
);
2771 CPPUNIT_ASSERT_MESSAGE("Failed on the content check after reload.", bRes
);
2776 void ScExportTest::testSharedFormulaExportXLS()
2780 bool checkContent( ScDocument
& rDoc
)
2782 formula::FormulaGrammar::Grammar eGram
= formula::FormulaGrammar::GRAM_ENGLISH_XL_R1C1
;
2783 rDoc
.SetGrammar(eGram
);
2784 sc::TokenStringContext
aCxt(&rDoc
, eGram
);
2786 // Check the title row.
2788 OUString aActual
= rDoc
.GetString(0,1,0);
2789 OUString aExpected
= "Response";
2790 if (aActual
!= aExpected
)
2792 cerr
<< "Wrong content in A2: expected='" << aExpected
<< "', actual='" << aActual
<< "'" << endl
;
2796 aActual
= rDoc
.GetString(1,1,0);
2797 aExpected
= "Response";
2798 if (aActual
!= aExpected
)
2800 cerr
<< "Wrong content in B2: expected='" << aExpected
<< "', actual='" << aActual
<< "'" << endl
;
2804 // A3:A12 and B3:B12 are numbers from 1 to 10.
2805 for (SCROW i
= 0; i
<= 9; ++i
)
2807 double fExpected
= i
+ 1.0;
2808 ScAddress
aPos(0,i
+2,0);
2809 double fActual
= rDoc
.GetValue(aPos
);
2810 if (fExpected
!= fActual
)
2812 cerr
<< "Wrong value in A" << (i
+2) << ": expected=" << fExpected
<< ", actual=" << fActual
<< endl
;
2817 ScFormulaCell
* pFC
= rDoc
.GetFormulaCell(aPos
);
2820 cerr
<< "B" << (i
+2) << " should be a formula cell." << endl
;
2824 OUString aFormula
= pFC
->GetCode()->CreateString(aCxt
, aPos
);
2825 aExpected
= "Coefficients!RC[-1]";
2826 if (aFormula
!= aExpected
)
2828 cerr
<< "Wrong formula in B" << (i
+2) << ": expected='" << aExpected
<< "', actual='" << aFormula
<< "'" << endl
;
2832 fActual
= rDoc
.GetValue(aPos
);
2833 if (fExpected
!= fActual
)
2835 cerr
<< "Wrong value in B" << (i
+2) << ": expected=" << fExpected
<< ", actual=" << fActual
<< endl
;
2845 ScDocShellRef xDocSh
= loadDoc("shared-formula/3d-reference.", FORMAT_ODS
);
2847 CPPUNIT_ASSERT_MESSAGE("Failed to load file.", xDocSh
.is());
2848 ScDocument
& rDoc
= xDocSh
->GetDocument();
2850 // Check the content of the original.
2851 bool bRes
= aTest
.checkContent(rDoc
);
2852 CPPUNIT_ASSERT_MESSAGE("Content check on the original document failed.", bRes
);
2855 ScDocShellRef xDocSh2
= saveAndReload(xDocSh
.get(), FORMAT_XLS
);
2857 CPPUNIT_ASSERT_MESSAGE("Failed to reload file.", xDocSh2
.is());
2859 ScDocument
& rDoc
= xDocSh2
->GetDocument();
2861 // Check the content of the reloaded. This should be identical.
2862 bool bRes
= aTest
.checkContent(rDoc
);
2863 CPPUNIT_ASSERT_MESSAGE("Content check on the reloaded document failed.", bRes
);
2868 void ScExportTest::testSharedFormulaExportXLSX()
2872 bool checkContent( const ScDocument
& rDoc
)
2874 SCTAB nTabCount
= rDoc
.GetTableCount();
2877 cerr
<< "Document should have exactly 2 sheets. " << nTabCount
<< " found." << endl
;
2881 // Make sure the sheet tab colors are not set.
2882 for (SCROW i
= 0; i
<= 1; ++i
)
2884 Color aTabBgColor
= rDoc
.GetTabBgColor(i
);
2885 if (aTabBgColor
!= COL_AUTO
)
2887 cerr
<< "The tab color of Sheet " << (i
+1) << " should not be explicitly set." << endl
;
2892 // B2:B7 should show 1,2,3,4,5,6.
2893 double fExpected
= 1.0;
2894 for (SCROW i
= 1; i
<= 6; ++i
, ++fExpected
)
2896 ScAddress
aPos(1,i
,0);
2897 double fVal
= rDoc
.GetValue(aPos
);
2898 if (fVal
!= fExpected
)
2900 cerr
<< "Wrong value in B" << (i
+1) << ": expected=" << fExpected
<< ", actual=" << fVal
<< endl
;
2905 // C2:C7 should show 10,20,....,60.
2907 for (SCROW i
= 1; i
<= 6; ++i
, fExpected
+=10.0)
2909 ScAddress
aPos(2,i
,0);
2910 double fVal
= rDoc
.GetValue(aPos
);
2911 if (fVal
!= fExpected
)
2913 cerr
<< "Wrong value in C" << (i
+1) << ": expected=" << fExpected
<< ", actual=" << fVal
<< endl
;
2918 // D2:D7 should show 1,2,...,6.
2920 for (SCROW i
= 1; i
<= 6; ++i
, ++fExpected
)
2922 ScAddress
aPos(3,i
,0);
2923 double fVal
= rDoc
.GetValue(aPos
);
2924 if (fVal
!= fExpected
)
2926 cerr
<< "Wrong value in D" << (i
+1) << ": expected=" << fExpected
<< ", actual=" << fVal
<< endl
;
2936 ScDocShellRef xDocSh
= loadDoc("shared-formula/3d-reference.", FORMAT_XLSX
);
2938 CPPUNIT_ASSERT_MESSAGE("Failed to load file.", xDocSh
.is());
2939 ScDocument
& rDoc
= xDocSh
->GetDocument();
2941 bool bRes
= aTest
.checkContent(rDoc
);
2942 CPPUNIT_ASSERT_MESSAGE("Content check on the initial document failed.", bRes
);
2944 rDoc
.CalcAll(); // Recalculate to flush all cached results.
2945 bRes
= aTest
.checkContent(rDoc
);
2946 CPPUNIT_ASSERT_MESSAGE("Content check on the initial recalculated document failed.", bRes
);
2949 // Save and reload, and check the content again.
2950 ScDocShellRef xDocSh2
= saveAndReload(xDocSh
.get(), FORMAT_XLSX
);
2953 CPPUNIT_ASSERT_MESSAGE("Failed to load file.", xDocSh2
.is());
2954 ScDocument
& rDoc
= xDocSh2
->GetDocument();
2955 rDoc
.CalcAll(); // Recalculate to flush all cached results.
2957 bool bRes
= aTest
.checkContent(rDoc
);
2958 CPPUNIT_ASSERT_MESSAGE("Content check on the reloaded document failed.", bRes
);
2963 void ScExportTest::testSharedFormulaStringResultExportXLSX()
2967 bool checkContent( const ScDocument
& rDoc
)
2970 // B2:B7 should show A,B,....,F.
2971 const char* const expected
[] = { "A", "B", "C", "D", "E", "F" };
2972 for (SCROW i
= 0; i
<= 5; ++i
)
2974 ScAddress
aPos(1,i
+1,0);
2975 OUString aStr
= rDoc
.GetString(aPos
);
2976 OUString aExpected
= OUString::createFromAscii(expected
[i
]);
2977 if (aStr
!= aExpected
)
2979 cerr
<< "Wrong value in B" << (i
+2) << ": expected='" << aExpected
<< "', actual='" << aStr
<< "'" << endl
;
2986 // C2:C7 should show AA,BB,....,FF.
2987 const char* const expected
[] = { "AA", "BB", "CC", "DD", "EE", "FF" };
2988 for (SCROW i
= 0; i
<= 5; ++i
)
2990 ScAddress
aPos(2,i
+1,0);
2991 OUString aStr
= rDoc
.GetString(aPos
);
2992 OUString aExpected
= OUString::createFromAscii(expected
[i
]);
2993 if (aStr
!= aExpected
)
2995 cerr
<< "Wrong value in C" << (i
+2) << ": expected='" << aExpected
<< "', actual='" << aStr
<< "'" << endl
;
3006 ScDocShellRef xDocSh
= loadDoc("shared-formula/text-results.", FORMAT_XLSX
);
3008 CPPUNIT_ASSERT_MESSAGE("Failed to load file.", xDocSh
.is());
3009 ScDocument
& rDoc
= xDocSh
->GetDocument();
3011 // Check content without re-calculation, to test cached formula results.
3012 bool bRes
= aTest
.checkContent(rDoc
);
3013 CPPUNIT_ASSERT_MESSAGE("Content check on the initial document failed.", bRes
);
3015 // Now, re-calculate and check the results.
3017 bRes
= aTest
.checkContent(rDoc
);
3018 CPPUNIT_ASSERT_MESSAGE("Content check on the initial recalculated document failed.", bRes
);
3020 // Reload and check again.
3021 ScDocShellRef xDocSh2
= saveAndReload(xDocSh
.get(), FORMAT_XLSX
);
3023 CPPUNIT_ASSERT_MESSAGE("Failed to re-load file.", xDocSh2
.is());
3024 ScDocument
& rDoc
= xDocSh2
->GetDocument();
3026 bool bRes
= aTest
.checkContent(rDoc
);
3027 CPPUNIT_ASSERT_MESSAGE("Content check on the reloaded document failed.", bRes
);
3032 void ScExportTest::testFunctionsExcel2010( sal_uLong nFormatType
)
3034 ScDocShellRef xShell
= loadDoc("functions-excel-2010.", FORMAT_XLSX
);
3035 CPPUNIT_ASSERT_MESSAGE("Failed to load the document.", xShell
.is());
3037 ScDocShellRef xDocSh
= saveAndReload(xShell
.get(), nFormatType
);
3038 ScDocument
& rDoc
= xDocSh
->GetDocument();
3039 rDoc
.CalcAll(); // perform hard re-calculation.
3041 testFunctionsExcel2010_Impl(rDoc
);
3046 void ScExportTest::testFunctionsExcel2010XLSX()
3048 testFunctionsExcel2010(FORMAT_XLSX
);
3051 void ScExportTest::testFunctionsExcel2010XLS()
3053 testFunctionsExcel2010(FORMAT_XLS
);
3056 void ScExportTest::testCeilingFloor( sal_uLong nFormatType
)
3058 ScDocShellRef xShell
= loadDoc("ceiling-floor.", FORMAT_XLSX
);
3059 CPPUNIT_ASSERT_MESSAGE("Failed to load the document.", xShell
.is());
3061 ScDocShellRef xDocSh
= saveAndReload(xShell
.get(), nFormatType
);
3062 ScDocument
& rDoc
= xDocSh
->GetDocument();
3063 rDoc
.CalcAll(); // perform hard re-calculation.
3065 testCeilingFloor_Impl(rDoc
);
3070 void ScExportTest::testCeilingFloorXLSX()
3072 testCeilingFloor(FORMAT_XLSX
);
3075 void ScExportTest::testCeilingFloorODSToXLSX()
3077 // tdf#100011 - Cannot open sheet containing FLOOR/CEILING functions by MS Excel, after export to .xlsx
3078 ScDocShellRef xShell
= loadDoc("ceiling-floor.", FORMAT_ODS
);
3079 CPPUNIT_ASSERT_MESSAGE("Failed to load the document.", xShell
.is());
3081 std::shared_ptr
<utl::TempFile
> pXPathFile
= ScBootstrapFixture::exportTo(&(*xShell
), FORMAT_XLSX
);
3082 xmlDocPtr pSheet
= XPathHelper::parseExport(pXPathFile
, m_xSFactory
, "xl/workbook.xml");
3083 CPPUNIT_ASSERT(pSheet
);
3085 // there shouldn't be any defined names during export of FLOOR and CEILING functions to .xlsx
3086 assertXPath(pSheet
, "/x:workbook/x:definedNames", 0);
3089 void ScExportTest::testCeilingFloorXLS()
3091 testCeilingFloor(FORMAT_XLS
);
3094 void ScExportTest::testCeilingFloorODS()
3096 testCeilingFloor(FORMAT_ODS
);
3099 void ScExportTest::testCustomXml()
3101 // Load document and export it to a temporary file
3102 ScDocShellRef xShell
= loadDoc("customxml.", FORMAT_XLSX
);
3103 CPPUNIT_ASSERT_MESSAGE("Failed to load the document.", xShell
.is());
3105 std::shared_ptr
<utl::TempFile
> pXPathFile
= ScBootstrapFixture::exportTo(&(*xShell
), FORMAT_XLSX
);
3106 xmlDocPtr pXmlDoc
= XPathHelper::parseExport(pXPathFile
, m_xSFactory
, "customXml/item1.xml");
3107 CPPUNIT_ASSERT(pXmlDoc
);
3108 xmlDocPtr pRelsDoc
= XPathHelper::parseExport(pXPathFile
, m_xSFactory
, "customXml/_rels/item1.xml.rels");
3109 CPPUNIT_ASSERT(pRelsDoc
);
3111 // Check there is a relation to itemProps1.xml.
3112 assertXPath(pRelsDoc
, "/r:Relationships/r:Relationship", 1);
3113 assertXPath(pRelsDoc
, "/r:Relationships/r:Relationship[@Id='rId1']", "Target", "itemProps1.xml");
3115 std::shared_ptr
<SvStream
> pStream
= XPathHelper::parseExportStream(pXPathFile
, m_xSFactory
, "ddp/ddpfile.xen");
3116 CPPUNIT_ASSERT(pStream
);
3120 void ScExportTest::testRelativePathsODS()
3122 ScDocShellRef xDocSh
= loadDoc("fdo79305.", FORMAT_ODS
);
3123 CPPUNIT_ASSERT(xDocSh
.is());
3125 xmlDocPtr pDoc
= XPathHelper::parseExport2(*this, *xDocSh
, m_xSFactory
, "content.xml", FORMAT_ODS
);
3126 CPPUNIT_ASSERT(pDoc
);
3127 OUString aURL
= getXPath(pDoc
,
3128 "/office:document-content/office:body/office:spreadsheet/table:table/table:table-row[2]/table:table-cell[2]/text:p/text:a", "href");
3129 // make sure that the URL is relative
3130 CPPUNIT_ASSERT(aURL
.startsWith(".."));
3136 void testSheetProtection_Impl(const ScDocument
& rDoc
)
3138 CPPUNIT_ASSERT(rDoc
.IsTabProtected(0));
3139 ScTableProtection
* pTabProtection
= rDoc
.GetTabProtection(0);
3140 CPPUNIT_ASSERT(pTabProtection
);
3141 CPPUNIT_ASSERT(pTabProtection
->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS
));
3142 CPPUNIT_ASSERT(!pTabProtection
->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS
));
3147 void ScExportTest::testSheetProtectionODS()
3149 ScDocShellRef xDocSh
= loadDoc("sheet-protection.", FORMAT_ODS
);
3150 CPPUNIT_ASSERT(xDocSh
.is());
3153 ScDocument
& rDoc
= xDocSh
->GetDocument();
3154 testSheetProtection_Impl(rDoc
);
3157 ScDocShellRef xDocSh2
= saveAndReload(xDocSh
.get(), FORMAT_ODS
);
3159 ScDocument
& rDoc
= xDocSh2
->GetDocument();
3160 testSheetProtection_Impl(rDoc
);
3166 void ScExportTest::testFunctionsExcel2010ODS()
3168 //testFunctionsExcel2010(FORMAT_ODS);
3171 void ScExportTest::testSwappedOutImageExport()
3173 const char* aFilterNames
[] = {
3176 "Calc Office Open XML",
3180 // Set cache size to a very small value to make sure one of the images is swapped out
3181 std::shared_ptr
< comphelper::ConfigurationChanges
> xBatch(comphelper::ConfigurationChanges::create());
3182 officecfg::Office::Common::Cache::GraphicManager::TotalCacheSize::set(sal_Int32(1), xBatch
);
3185 for( size_t nFilter
= 0; nFilter
< SAL_N_ELEMENTS(aFilterNames
); ++nFilter
)
3187 // Check whether the export code swaps in the image which was swapped out before.
3188 ScDocShellRef xDocSh
= loadDoc("document_with_two_images.", FORMAT_ODS
);
3190 const OString sFailedMessage
= OString("Failed on filter: ") + aFilterNames
[nFilter
];
3191 CPPUNIT_ASSERT_MESSAGE(sFailedMessage
.getStr(), xDocSh
.is());
3193 // Export the document and import again for a check
3194 ScDocShellRef xDocSh2
= saveAndReload(xDocSh
.get(), nFilter
);
3197 // Check whether graphic exported well after it was swapped out
3198 uno::Reference
< frame::XModel
> xModel
= xDocSh2
->GetModel();
3199 uno::Reference
< sheet::XSpreadsheetDocument
> xDoc(xModel
, UNO_QUERY_THROW
);
3200 uno::Reference
< container::XIndexAccess
> xIA(xDoc
->getSheets(), UNO_QUERY_THROW
);
3201 uno::Reference
< drawing::XDrawPageSupplier
> xDrawPageSupplier( xIA
->getByIndex(0), UNO_QUERY_THROW
);
3202 uno::Reference
< container::XIndexAccess
> xDraws(xDrawPageSupplier
->getDrawPage(), UNO_QUERY_THROW
);
3203 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage
.getStr(), static_cast<sal_Int32
>(2), xDraws
->getCount());
3205 uno::Reference
<drawing::XShape
> xImage(xDraws
->getByIndex(0), uno::UNO_QUERY
);
3206 uno::Reference
< beans::XPropertySet
> XPropSet( xImage
, uno::UNO_QUERY_THROW
);
3208 // Check Graphic, Size
3210 uno::Reference
<graphic::XGraphic
> xGraphic
;
3211 XPropSet
->getPropertyValue("Graphic") >>= xGraphic
;
3212 CPPUNIT_ASSERT_MESSAGE(sFailedMessage
.getStr(), xGraphic
.is());
3213 CPPUNIT_ASSERT_MESSAGE(sFailedMessage
.getStr(), xGraphic
->getType() != graphic::GraphicType::EMPTY
);
3214 uno::Reference
<awt::XBitmap
> xBitmap(xGraphic
, uno::UNO_QUERY
);
3215 CPPUNIT_ASSERT_MESSAGE(sFailedMessage
.getStr(), xBitmap
.is());
3216 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage
.getStr(), static_cast<sal_Int32
>(610), xBitmap
->getSize().Width
);
3217 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage
.getStr(), static_cast<sal_Int32
>(381), xBitmap
->getSize().Height
);
3220 xImage
.set(xDraws
->getByIndex(1), uno::UNO_QUERY
);
3221 XPropSet
.set( xImage
, uno::UNO_QUERY_THROW
);
3223 // Check Graphic, Size
3225 uno::Reference
<graphic::XGraphic
> xGraphic
;
3226 XPropSet
->getPropertyValue("Graphic") >>= xGraphic
;
3227 CPPUNIT_ASSERT_MESSAGE(sFailedMessage
.getStr(), xGraphic
.is());
3228 CPPUNIT_ASSERT_MESSAGE(sFailedMessage
.getStr(), xGraphic
->getType() != graphic::GraphicType::EMPTY
);
3229 uno::Reference
<awt::XBitmap
> xBitmap(xGraphic
, uno::UNO_QUERY
);
3230 CPPUNIT_ASSERT_MESSAGE(sFailedMessage
.getStr(), xBitmap
.is());
3231 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage
.getStr(), static_cast<sal_Int32
>(900), xBitmap
->getSize().Width
);
3232 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage
.getStr(), static_cast<sal_Int32
>(600), xBitmap
->getSize().Height
);
3238 ScExportTest::ScExportTest()
3239 : ScBootstrapFixture("sc/qa/unit/data")
3243 void ScExportTest::setUp()
3245 test::BootstrapFixture::setUp();
3247 // This is a bit of a fudge, we do this to ensure that ScGlobals::ensure,
3248 // which is a private symbol to us, gets called
3250 getMultiServiceFactory()->createInstance("com.sun.star.comp.Calc.SpreadsheetDocument");
3251 CPPUNIT_ASSERT_MESSAGE("no calc component!", m_xCalcComponent
.is());
3254 void ScExportTest::tearDown()
3256 uno::Reference
< lang::XComponent
>( m_xCalcComponent
, UNO_QUERY_THROW
)->dispose();
3257 test::BootstrapFixture::tearDown();
3261 void ScExportTest::testSupBookVirtualPathXLS()
3263 ScDocShellRef xShell
= loadDoc("external-ref.", FORMAT_XLS
);
3264 CPPUNIT_ASSERT(xShell
.is());
3266 ScDocShellRef xDocSh
= saveAndReload(xShell
.get(), FORMAT_XLS
);
3268 CPPUNIT_ASSERT(xDocSh
.is());
3270 ScDocument
& rDoc
= xDocSh
->GetDocument();
3272 ASSERT_FORMULA_EQUAL(rDoc
, ScAddress(0,0,0), "'file:///home/timar/Documents/external.xls'#$Sheet1.A1", "Wrong SupBook VirtualPath URL");
3278 void ScExportTest::testLinkedGraphicRT()
3280 // Problem was with linked images
3281 const char* aFilterNames
[] = {
3284 "Calc Office Open XML",
3288 for( size_t nFilter
= 0; nFilter
< SAL_N_ELEMENTS(aFilterNames
); ++nFilter
)
3290 // Load the original file with one image
3291 ScDocShellRef xDocSh
= loadDoc("document_with_linked_graphic.", FORMAT_ODS
);
3292 const OString sFailedMessage
= OString("Failed on filter: ") + aFilterNames
[nFilter
];
3294 // Export the document and import again for a check
3295 ScDocShellRef xDocSh2
= saveAndReload(xDocSh
.get(), nFilter
);
3298 // Check whether graphic imported well after export
3299 ScDocument
& rDoc
= xDocSh
->GetDocument();
3300 ScDrawLayer
* pDrawLayer
= rDoc
.GetDrawLayer();
3301 CPPUNIT_ASSERT_MESSAGE( sFailedMessage
.getStr(), pDrawLayer
!= nullptr );
3302 const SdrPage
*pPage
= pDrawLayer
->GetPage(0);
3303 CPPUNIT_ASSERT_MESSAGE( sFailedMessage
.getStr(), pPage
!= nullptr );
3304 SdrGrafObj
* pObject
= dynamic_cast<SdrGrafObj
*>(pPage
->GetObj(0));
3305 CPPUNIT_ASSERT_MESSAGE( sFailedMessage
.getStr(), pObject
!= nullptr );
3306 CPPUNIT_ASSERT_MESSAGE( sFailedMessage
.getStr(), pObject
->IsLinkedGraphic() );
3308 const GraphicObject
& rGraphicObj
= pObject
->GetGraphicObject(true);
3309 CPPUNIT_ASSERT_EQUAL_MESSAGE( sFailedMessage
.getStr(), int(GraphicType::Bitmap
), int(rGraphicObj
.GetGraphic().GetType()));
3310 CPPUNIT_ASSERT_EQUAL_MESSAGE( sFailedMessage
.getStr(), sal_uLong(864900), rGraphicObj
.GetGraphic().GetSizeBytes());
3316 void ScExportTest::testImageWithSpecialID()
3318 const char* aFilterNames
[] = {
3321 "Calc Office Open XML",
3325 // Trigger swap out mechanism to test swapped state factor too.
3326 std::shared_ptr
< comphelper::ConfigurationChanges
> batch(comphelper::ConfigurationChanges::create());
3327 officecfg::Office::Common::Cache::GraphicManager::TotalCacheSize::set(sal_Int32(1), batch
);
3330 for( size_t nFilter
= 0; nFilter
< SAL_N_ELEMENTS(aFilterNames
); ++nFilter
)
3332 ScDocShellRef xDocSh
= loadDoc("images_with_special_IDs.", FORMAT_ODS
);
3334 const OString sFailedMessage
= OString("Failed on filter: ") + aFilterNames
[nFilter
];
3335 CPPUNIT_ASSERT_MESSAGE(sFailedMessage
.getStr(), xDocSh
.is());
3337 // Export the document and import again for a check
3338 ScDocShellRef xDocSh2
= saveAndReload(xDocSh
.get(), nFilter
);
3341 // Check whether graphic was exported well
3342 uno::Reference
< frame::XModel
> xModel
= xDocSh2
->GetModel();
3343 uno::Reference
< sheet::XSpreadsheetDocument
> xDoc(xModel
, UNO_QUERY_THROW
);
3344 uno::Reference
< container::XIndexAccess
> xIA(xDoc
->getSheets(), UNO_QUERY_THROW
);
3345 uno::Reference
< drawing::XDrawPageSupplier
> xDrawPageSupplier( xIA
->getByIndex(0), UNO_QUERY_THROW
);
3346 uno::Reference
< container::XIndexAccess
> xDraws(xDrawPageSupplier
->getDrawPage(), UNO_QUERY_THROW
);
3347 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage
.getStr(), static_cast<sal_Int32
>(2), xDraws
->getCount());
3349 uno::Reference
<drawing::XShape
> xImage(xDraws
->getByIndex(0), uno::UNO_QUERY
);
3350 uno::Reference
< beans::XPropertySet
> XPropSet( xImage
, uno::UNO_QUERY_THROW
);
3352 // Check Graphic, Size
3354 uno::Reference
<graphic::XGraphic
> xGraphic
;
3355 XPropSet
->getPropertyValue("Graphic") >>= xGraphic
;
3356 CPPUNIT_ASSERT_MESSAGE(sFailedMessage
.getStr(), xGraphic
.is());
3357 CPPUNIT_ASSERT_MESSAGE(sFailedMessage
.getStr(), xGraphic
->getType() != graphic::GraphicType::EMPTY
);
3358 uno::Reference
<awt::XBitmap
> xBitmap(xGraphic
, uno::UNO_QUERY
);
3359 CPPUNIT_ASSERT_MESSAGE(sFailedMessage
.getStr(), xBitmap
.is());
3360 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage
.getStr(), static_cast<sal_Int32
>(610), xBitmap
->getSize().Width
);
3361 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage
.getStr(), static_cast<sal_Int32
>(381), xBitmap
->getSize().Height
);
3364 xImage
.set(xDraws
->getByIndex(1), uno::UNO_QUERY
);
3365 XPropSet
.set( xImage
, uno::UNO_QUERY_THROW
);
3367 // Check Graphic, Size
3369 uno::Reference
<graphic::XGraphic
> xGraphic
;
3370 XPropSet
->getPropertyValue("Graphic") >>= xGraphic
;
3371 CPPUNIT_ASSERT_MESSAGE(sFailedMessage
.getStr(), xGraphic
.is());
3372 CPPUNIT_ASSERT_MESSAGE(sFailedMessage
.getStr(), xGraphic
->getType() != graphic::GraphicType::EMPTY
);
3373 uno::Reference
<awt::XBitmap
> xBitmap(xGraphic
, uno::UNO_QUERY
);
3374 CPPUNIT_ASSERT_MESSAGE(sFailedMessage
.getStr(), xBitmap
.is());
3375 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage
.getStr(), static_cast<sal_Int32
>(900), xBitmap
->getSize().Width
);
3376 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage
.getStr(), static_cast<sal_Int32
>(600), xBitmap
->getSize().Height
);
3382 void ScExportTest::testAbsNamedRangeHTML()
3384 ScDocShellRef xDocSh
= loadDoc("numberformat.", FORMAT_HTML
);
3385 xDocSh
->DoHardRecalc();
3386 ScDocShellRef xDocSh2
= saveAndReload(xDocSh
.get(), FORMAT_ODS
);
3388 xDocSh2
->DoHardRecalc();
3390 ScDocument
& rDoc
= xDocSh2
->GetDocument();
3391 ScRangeData
* pRangeData
= rDoc
.GetRangeName()->findByUpperName(OUString("HTML_1"));
3392 ScSingleRefData
* pRef
= pRangeData
->GetCode()->FirstToken()->GetSingleRef();
3393 // see tdf#119141 for the reason why this isn't Sheet1.HTML_1
3394 CPPUNIT_ASSERT_MESSAGE("HTML_1 is an absolute reference",!pRef
->IsTabRel());
3397 void ScExportTest::testSheetLocalRangeNameXLS()
3399 ScDocShellRef xDocSh
= loadDoc("named-ranges-local.", FORMAT_XLS
);
3400 xDocSh
->DoHardRecalc();
3401 ScDocShellRef xDocSh2
= saveAndReload(xDocSh
.get(), FORMAT_XLS
);
3403 xDocSh2
->DoHardRecalc();
3405 ScDocument
& rDoc
= xDocSh2
->GetDocument();
3406 ScRangeName
* pRangeName
= rDoc
.GetRangeName(0);
3407 CPPUNIT_ASSERT(pRangeName
);
3408 CPPUNIT_ASSERT_EQUAL(size_t(2), pRangeName
->size());
3411 rDoc
.GetFormula(3, 11, 0, aFormula
);
3412 CPPUNIT_ASSERT_EQUAL(OUString("=SUM(local_name2)"), aFormula
);
3413 ASSERT_DOUBLES_EQUAL(14.0, rDoc
.GetValue(3, 11, 0));
3415 rDoc
.GetFormula(6, 4, 0, aFormula
);
3416 CPPUNIT_ASSERT_EQUAL(OUString("=local_name1"), aFormula
);
3421 void ScExportTest::testRelativeNamedExpressionsXLS()
3423 ScDocShellRef xDocSh
= loadDoc("tdf113991_relativeNamedRanges.", FORMAT_ODS
);
3424 xDocSh
->DoHardRecalc();
3425 ScDocShellRef xDocSh2
= saveAndReload(xDocSh
.get(), FORMAT_XLS
);
3427 xDocSh2
->DoHardRecalc();
3428 ScDocument
& rDoc
= xDocSh2
->GetDocument();
3431 ScAddress
aPos(6,2,0);
3432 CPPUNIT_ASSERT_EQUAL(1.0, rDoc
.GetValue(aPos
));
3433 ASSERT_FORMULA_EQUAL(rDoc
, aPos
, "single_cell_A3", nullptr);
3435 aPos
= ScAddress(5,5,1);
3436 CPPUNIT_ASSERT_EQUAL(18.0, rDoc
.GetValue(aPos
));
3437 ASSERT_FORMULA_EQUAL(rDoc
, aPos
, "SUM(test_conflict)", nullptr);
3439 aPos
= ScAddress(7,2,1);
3440 CPPUNIT_ASSERT_EQUAL(10.0, rDoc
.GetValue(aPos
));
3441 ASSERT_FORMULA_EQUAL(rDoc
, aPos
, "single_global_A3", nullptr);
3443 aPos
= ScAddress(7,5,1);
3444 CPPUNIT_ASSERT_EQUAL(75.0, rDoc
.GetValue(aPos
));
3445 ASSERT_FORMULA_EQUAL(rDoc
, aPos
, "SUM(A6:F6)", nullptr);
3449 void ScExportTest::testSheetTextBoxHyperlinkXLSX()
3451 ScDocShellRef xShell
= loadDoc("textbox-hyperlink.", FORMAT_XLSX
);
3452 CPPUNIT_ASSERT(xShell
.is());
3454 ScDocShellRef xDocSh
= saveAndReload(&(*xShell
), FORMAT_XLSX
);
3455 CPPUNIT_ASSERT(xDocSh
.is());
3457 xmlDocPtr pDoc
= XPathHelper::parseExport2(*this, *xDocSh
, m_xSFactory
, "xl/drawings/drawing1.xml", FORMAT_XLSX
);
3458 CPPUNIT_ASSERT(pDoc
);
3460 assertXPath(pDoc
, "/xdr:wsDr[1]/xdr:twoCellAnchor[1]/xdr:sp[1]/xdr:nvSpPr[1]/xdr:cNvPr[1]/a:hlinkClick[1]", 1);
3465 void ScExportTest::testFontSizeXLSX()
3467 ScDocShellRef xDocSh
= loadDoc("fontSize.", FORMAT_XLSX
);
3468 CPPUNIT_ASSERT(xDocSh
.is());
3470 xmlDocPtr pDoc
= XPathHelper::parseExport2(*this, *xDocSh
, m_xSFactory
, "xl/drawings/drawing1.xml", FORMAT_XLSX
);
3471 CPPUNIT_ASSERT(pDoc
);
3472 OUString fontSize
= getXPath(pDoc
,
3473 "/xdr:wsDr/xdr:twoCellAnchor/xdr:sp[1]/xdr:txBody/a:p[1]/a:r[1]/a:rPr", "sz");
3474 // make sure that the font size is 18
3475 CPPUNIT_ASSERT_EQUAL(OUString("1800"), fontSize
);
3478 void ScExportTest::testSheetCharacterKerningSpaceXLSX()
3480 ScDocShellRef xShell
= loadDoc("textbox-CharKerningSpace.", FORMAT_XLSX
);
3481 CPPUNIT_ASSERT(xShell
.is());
3483 ScDocShellRef xDocSh
= saveAndReload(&(*xShell
), FORMAT_XLSX
);
3484 CPPUNIT_ASSERT(xDocSh
.is());
3486 xmlDocPtr pDoc
= XPathHelper::parseExport2(*this, *xDocSh
, m_xSFactory
, "xl/drawings/drawing1.xml", FORMAT_XLSX
);
3487 CPPUNIT_ASSERT(pDoc
);
3489 OUString CharKerningSpace
= getXPath(pDoc
,
3490 "/xdr:wsDr[1]/xdr:twoCellAnchor[1]/xdr:sp[1]/xdr:txBody[1]/a:p[1]/a:r[1]/a:rPr[1]","spc");
3492 // make sure that the CharKerning is 1997.
3493 CPPUNIT_ASSERT_EQUAL(OUString("1997"), CharKerningSpace
);
3498 void ScExportTest::testSheetCondensedCharacterSpaceXLSX()
3500 ScDocShellRef xShell
= loadDoc("textbox-CondensedCharacterSpace.", FORMAT_XLSX
);
3501 CPPUNIT_ASSERT(xShell
.is());
3503 ScDocShellRef xDocSh
= saveAndReload(&(*xShell
), FORMAT_XLSX
);
3504 CPPUNIT_ASSERT(xDocSh
.is());
3506 xmlDocPtr pDoc
= XPathHelper::parseExport2(*this, *xDocSh
, m_xSFactory
, "xl/drawings/drawing1.xml", FORMAT_XLSX
);
3507 CPPUNIT_ASSERT(pDoc
);
3509 OUString CondensedCharSpace
= getXPath(pDoc
,
3510 "/xdr:wsDr[1]/xdr:twoCellAnchor[1]/xdr:sp[1]/xdr:txBody[1]/a:p[1]/a:r[1]/a:rPr[1]","spc");
3512 // make sure that the CondensedCharSpace is -1002.
3513 CPPUNIT_ASSERT_EQUAL(OUString("-1002"), CondensedCharSpace
);
3518 void ScExportTest::testTextUnderlineColorXLSX()
3520 ScDocShellRef xDocSh
= loadDoc("underlineColor.", FORMAT_XLSX
);
3521 CPPUNIT_ASSERT(xDocSh
.is());
3523 xmlDocPtr pDoc
= XPathHelper::parseExport2(*this, *xDocSh
, m_xSFactory
, "xl/drawings/drawing1.xml", FORMAT_XLSX
);
3524 CPPUNIT_ASSERT(pDoc
);
3525 // Make sure the underline type is double line
3526 assertXPath(pDoc
, "/xdr:wsDr/xdr:twoCellAnchor[1]/xdr:sp[1]/xdr:txBody/a:p[1]/a:r[1]/a:rPr", "u", "dbl");
3528 assertXPath(pDoc
, "/xdr:wsDr/xdr:twoCellAnchor[1]/xdr:sp[1]/xdr:txBody/a:p[1]/a:r[1]/a:rPr", "b", "1");
3529 // Make sure that the underline color is RED
3530 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");
3532 // Make sure the underline type is drawn with heavy line
3533 assertXPath(pDoc
, "/xdr:wsDr/xdr:twoCellAnchor[2]/xdr:sp[1]/xdr:txBody/a:p[1]/a:r[1]/a:rPr", "u", "heavy");
3534 // tdf#104219 Make sure that uFill is not existing and uFillTx is set.
3535 // It mean that color is automatic, should be the same color as the text.
3536 assertXPath(pDoc
, "/xdr:wsDr/xdr:twoCellAnchor[2]/xdr:sp[1]/xdr:txBody/a:p[1]/a:r[1]/a:rPr/a:uFill", 0);
3537 assertXPath(pDoc
, "/xdr:wsDr/xdr:twoCellAnchor[2]/xdr:sp[1]/xdr:txBody/a:p[1]/a:r[1]/a:rPr/a:uFillTx", 1);
3540 void ScExportTest::testSheetRunParagraphPropertyXLSX()
3542 ScDocShellRef xShell
= loadDoc("TextColor.", FORMAT_XLSX
);
3543 CPPUNIT_ASSERT(xShell
.is());
3545 ScDocShellRef xDocSh
= saveAndReload(&(*xShell
), FORMAT_XLSX
);
3546 CPPUNIT_ASSERT(xDocSh
.is());
3548 xmlDocPtr pDoc
= XPathHelper::parseExport2(*this, *xDocSh
, m_xSFactory
, "xl/sharedStrings.xml", FORMAT_XLSX
);
3549 CPPUNIT_ASSERT(pDoc
);
3551 OUString aColor
= getXPath(pDoc
, "/x:sst/x:si/x:r[1]/x:rPr[1]/x:color", "rgb");
3552 CPPUNIT_ASSERT_EQUAL(OUString("FFFF0000"), aColor
);
3557 void ScExportTest::testPreserveTextWhitespaceXLSX()
3559 ScDocShellRef xShell
= loadDoc("preserve-whitespace.", FORMAT_XLSX
);
3560 ScDocShellRef xDocSh
= saveAndReload(&(*xShell
), FORMAT_XLSX
);
3561 CPPUNIT_ASSERT(xDocSh
.is());
3563 xmlDocPtr pDoc
= XPathHelper::parseExport2(*this, *xDocSh
, m_xSFactory
, "xl/sharedStrings.xml", FORMAT_XLSX
);
3564 CPPUNIT_ASSERT(pDoc
);
3565 assertXPath(pDoc
, "/x:sst/x:si/x:t", "space", "preserve");
3569 void ScExportTest::testPreserveTextWhitespace2XLSX()
3571 ScDocShellRef xShell
= loadDoc("preserve_space.", FORMAT_XLSX
);
3572 ScDocShellRef xDocSh
= saveAndReload(&(*xShell
), FORMAT_XLSX
);
3573 CPPUNIT_ASSERT(xDocSh
.is());
3575 xmlDocPtr pDoc
= XPathHelper::parseExport2(*this, *xDocSh
, m_xSFactory
, "xl/sharedStrings.xml", FORMAT_XLSX
);
3576 CPPUNIT_ASSERT(pDoc
);
3577 assertXPath(pDoc
, "/x:sst/x:si[1]/x:t", "space", "preserve");
3578 assertXPath(pDoc
, "/x:sst/x:si[2]/x:r[1]/x:t", "space", "preserve");
3579 assertXPath(pDoc
, "/x:sst/x:si[2]/x:r[2]/x:t", "space", "preserve");
3583 void ScExportTest::testHiddenShapeXLS()
3585 ScDocShellRef xDocSh
= loadDoc("hiddenShape.", FORMAT_XLS
);
3586 CPPUNIT_ASSERT(xDocSh
.is());
3588 ScDocument
& rDoc
= xDocSh
->GetDocument();
3589 CPPUNIT_ASSERT(rDoc
.GetTableCount() > 0);
3590 ScDrawLayer
* pDrawLayer
= rDoc
.GetDrawLayer();
3591 SdrPage
* pPage
= pDrawLayer
->GetPage(0);
3592 CPPUNIT_ASSERT(pPage
);
3593 SdrObject
* pObj
= pPage
->GetObj(0);
3594 CPPUNIT_ASSERT(pObj
);
3595 CPPUNIT_ASSERT_MESSAGE("Drawing object should not be visible.", !pObj
->IsVisible());
3596 CPPUNIT_ASSERT_MESSAGE("Drawing object should not be printable.", !pObj
->IsPrintable());
3600 void ScExportTest::testHiddenShapeXLSX()
3602 ScDocShellRef xDocSh
= loadDoc("hiddenShape.", FORMAT_XLSX
);
3603 CPPUNIT_ASSERT(xDocSh
.is());
3605 ScDocument
& rDoc
= xDocSh
->GetDocument();
3606 CPPUNIT_ASSERT(rDoc
.GetTableCount() > 0);
3607 ScDrawLayer
* pDrawLayer
= rDoc
.GetDrawLayer();
3608 SdrPage
* pPage
= pDrawLayer
->GetPage(0);
3609 CPPUNIT_ASSERT(pPage
);
3610 SdrObject
* pObj
= pPage
->GetObj(0);
3611 CPPUNIT_ASSERT(pObj
);
3612 CPPUNIT_ASSERT_MESSAGE("Drawing object should not be visible.", !pObj
->IsVisible());
3613 CPPUNIT_ASSERT_MESSAGE("Drawing object should not be printable.", !pObj
->IsPrintable());
3615 xmlDocPtr pDoc
= XPathHelper::parseExport2(*this, *xDocSh
, m_xSFactory
, "xl/drawings/drawing1.xml", FORMAT_XLSX
);
3616 CPPUNIT_ASSERT(pDoc
);
3617 assertXPath(pDoc
, "/xdr:wsDr/xdr:twoCellAnchor/xdr:sp[1]/xdr:nvSpPr/xdr:cNvPr", "hidden", "1");
3621 void ScExportTest::testShapeAutofitXLSX()
3623 ScDocShellRef xDocSh
= loadDoc("testShapeAutofit.", FORMAT_XLSX
);
3624 CPPUNIT_ASSERT(xDocSh
.is());
3626 xmlDocPtr pDoc
= XPathHelper::parseExport2(*this, *xDocSh
, m_xSFactory
, "xl/drawings/drawing1.xml", FORMAT_XLSX
);
3627 CPPUNIT_ASSERT(pDoc
);
3629 // TextAutoGrowHeight --> "Fit height to text" / "Resize shape to fit text" --> true
3630 assertXPath(pDoc
, "/xdr:wsDr/xdr:twoCellAnchor[1]/xdr:sp/xdr:txBody/a:bodyPr/a:spAutoFit", 1);
3631 // TextAutoGrowHeight --> "Fit height to text" / "Resize shape to fit text" --> false
3632 assertXPath(pDoc
, "/xdr:wsDr/xdr:twoCellAnchor[2]/xdr:sp/xdr:txBody/a:bodyPr/a:noAutofit", 1);
3635 void ScExportTest::testHyperlinkXLSX()
3637 ScDocShellRef xDocSh
= loadDoc("hyperlink.", FORMAT_XLSX
);
3638 CPPUNIT_ASSERT(xDocSh
.is());
3640 xmlDocPtr pDoc
= XPathHelper::parseExport2(*this, *xDocSh
, m_xSFactory
, "xl/drawings/_rels/drawing1.xml.rels", FORMAT_XLSX
);
3641 CPPUNIT_ASSERT(pDoc
);
3642 assertXPath(pDoc
, "/r:Relationships/r:Relationship", "Target", "#Sheet2!A1");
3645 void ScExportTest::testMoveCellAnchoredShapesODS()
3647 ScDocShellRef xDocSh
= loadDoc("move-cell-anchored-shapes.", FORMAT_ODS
);
3648 CPPUNIT_ASSERT_MESSAGE("Failed to load move-cell-anchored-shapes.ods", xDocSh
.is());
3650 // There are two cell-anchored objects on the first sheet.
3651 ScDocument
& rDoc
= xDocSh
->GetDocument();
3653 CPPUNIT_ASSERT_MESSAGE("There should be at least one sheet.", rDoc
.GetTableCount() > 0);
3655 ScDrawLayer
* pDrawLayer
= rDoc
.GetDrawLayer();
3656 SdrPage
* pPage
= pDrawLayer
->GetPage(0);
3657 CPPUNIT_ASSERT_MESSAGE("draw page for sheet 1 should exist.", pPage
);
3658 SdrObject
* pObj
= pPage
->GetObj(0);
3659 CPPUNIT_ASSERT_MESSAGE("Failed to get drawing object.", pObj
);
3661 // Check cell anchor state
3662 ScAnchorType oldType
= ScDrawLayer::GetAnchorType(*pObj
);
3663 CPPUNIT_ASSERT_EQUAL_MESSAGE( "Failed to get anchor type", SCA_CELL_RESIZE
, oldType
);
3666 ScDrawObjData
* pData
= ScDrawLayer::GetObjData(pObj
);
3667 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData
);
3668 CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData
->getShapeRect().IsEmpty());
3670 ScAddress aDataStart
= pData
->maStart
;
3671 ScAddress aDataEnd
= pData
->maEnd
;
3673 // Get non rotated anchor data
3674 ScDrawObjData
* pNData
= ScDrawLayer::GetNonRotatedObjData( pObj
);
3675 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData
);
3676 CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData
->getShapeRect().IsEmpty());
3678 ScAddress aNDataStart
= pNData
->maStart
;
3679 ScAddress aNDataEnd
= pNData
->maEnd
;
3680 CPPUNIT_ASSERT_EQUAL(aDataStart
, aNDataStart
);
3681 CPPUNIT_ASSERT_EQUAL(aDataEnd
, aNDataEnd
);
3684 rDoc
.InsertRow(ScRange( 0, aDataStart
.Row() - 1, 0, MAXCOL
, aDataStart
.Row(), 0));
3687 pData
= ScDrawLayer::GetObjData(pObj
);
3688 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData
);
3689 CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData
->getShapeRect().IsEmpty());
3691 // Get non rotated anchor data
3692 pNData
= ScDrawLayer::GetNonRotatedObjData( pObj
);
3693 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData
);
3694 CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData
->getShapeRect().IsEmpty());
3696 // Check if data has moved to new rows
3697 CPPUNIT_ASSERT_EQUAL( pData
->maStart
.Row(), aDataStart
.Row() + 2 );
3698 CPPUNIT_ASSERT_EQUAL( pData
->maEnd
.Row(), aDataEnd
.Row() + 2 );
3700 CPPUNIT_ASSERT_EQUAL( pNData
->maStart
.Row(), aNDataStart
.Row() + 2 );
3701 CPPUNIT_ASSERT_EQUAL( pNData
->maEnd
.Row(), aNDataEnd
.Row() + 2 );
3703 // Save the anchor data
3704 aDataStart
= pData
->maStart
;
3705 aDataEnd
= pData
->maEnd
;
3706 aNDataStart
= pNData
->maStart
;
3707 aNDataEnd
= pNData
->maEnd
;
3709 // Save the document and load again to check anchor persist
3710 ScDocShellRef xDocSh1
= saveAndReload(&(*xDocSh
), FORMAT_ODS
);
3712 // There are two cell-anchored objects on the first sheet.
3713 ScDocument
& rDoc1
= xDocSh1
->GetDocument();
3715 CPPUNIT_ASSERT_MESSAGE("There should be at least one sheet.", rDoc1
.GetTableCount() > 0);
3717 pDrawLayer
= rDoc1
.GetDrawLayer();
3718 pPage
= pDrawLayer
->GetPage(0);
3719 CPPUNIT_ASSERT_MESSAGE("draw page for sheet 1 should exist.", pPage
);
3720 pObj
= pPage
->GetObj(0);
3721 CPPUNIT_ASSERT_MESSAGE("Failed to get drawing object.", pObj
);
3723 // Check cell anchor state
3724 oldType
= ScDrawLayer::GetAnchorType(*pObj
);
3725 CPPUNIT_ASSERT_EQUAL_MESSAGE( "Failed to get anchor type", SCA_CELL_RESIZE
, oldType
);
3728 pData
= ScDrawLayer::GetObjData(pObj
);
3729 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData
);
3730 CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData
->getShapeRect().IsEmpty());
3732 // Get non rotated anchor data
3733 pNData
= ScDrawLayer::GetNonRotatedObjData( pObj
);
3734 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData
);
3735 CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData
->getShapeRect().IsEmpty());
3737 // Check if data after save it
3738 CPPUNIT_ASSERT_EQUAL(pData
->maStart
, aDataStart
);
3739 CPPUNIT_ASSERT_EQUAL(pData
->maEnd
, aDataEnd
);
3741 CPPUNIT_ASSERT_EQUAL(pNData
->maStart
, aNDataStart
);
3742 CPPUNIT_ASSERT_EQUAL(pNData
->maEnd
, aNDataEnd
);
3745 rDoc1
.InsertCol(ScRange( aDataStart
.Col(), 0 , 0 , aDataStart
.Col(), MAXROW
, 0 ));
3748 pData
= ScDrawLayer::GetObjData(pObj
);
3749 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData
);
3750 CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData
->getShapeRect().IsEmpty());
3752 // Get non rotated anchor data
3753 pNData
= ScDrawLayer::GetNonRotatedObjData( pObj
);
3754 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData
);
3755 CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData
->getShapeRect().IsEmpty());
3757 // Check if data has moved to new rows
3758 CPPUNIT_ASSERT_EQUAL(pData
->maStart
.Col(), SCCOL(aDataStart
.Col() + 1));
3759 CPPUNIT_ASSERT_EQUAL(pData
->maEnd
.Col() , SCCOL(aDataEnd
.Col() + 1));
3761 CPPUNIT_ASSERT_EQUAL(pNData
->maStart
.Col(), SCCOL(aNDataStart
.Col() + 1));
3762 CPPUNIT_ASSERT_EQUAL(pNData
->maEnd
.Col() , SCCOL(aNDataEnd
.Col() + 1));
3764 // Save the anchor data
3765 aDataStart
= pData
->maStart
;
3766 aDataEnd
= pData
->maEnd
;
3767 aNDataStart
= pNData
->maStart
;
3768 aNDataEnd
= pNData
->maEnd
;
3770 // Save the document and load again to check anchor persist
3771 ScDocShellRef xDocSh2
= saveAndReload(&(*xDocSh1
), FORMAT_ODS
);
3773 // There are two cell-anchored objects on the first sheet.
3774 ScDocument
& rDoc2
= xDocSh2
->GetDocument();
3776 CPPUNIT_ASSERT_MESSAGE("There should be at least one sheet.", rDoc2
.GetTableCount() > 0);
3778 pDrawLayer
= rDoc2
.GetDrawLayer();
3779 pPage
= pDrawLayer
->GetPage(0);
3780 CPPUNIT_ASSERT_MESSAGE("draw page for sheet 1 should exist.", pPage
);
3781 pObj
= pPage
->GetObj(0);
3782 CPPUNIT_ASSERT_MESSAGE("Failed to get drawing object.", pObj
);
3784 // Check cell anchor state
3785 oldType
= ScDrawLayer::GetAnchorType(*pObj
);
3786 CPPUNIT_ASSERT_EQUAL_MESSAGE( "Failed to get anchor type", SCA_CELL_RESIZE
, oldType
);
3789 pData
= ScDrawLayer::GetObjData(pObj
);
3790 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData
);
3791 CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData
->getShapeRect().IsEmpty());
3793 // Get non rotated anchor data
3794 pNData
= ScDrawLayer::GetNonRotatedObjData( pObj
);
3795 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData
);
3796 CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData
->getShapeRect().IsEmpty());
3798 // Check if data after save it
3799 CPPUNIT_ASSERT_EQUAL(pData
->maStart
, aDataStart
);
3800 CPPUNIT_ASSERT_EQUAL(pData
->maEnd
, aDataEnd
);
3802 CPPUNIT_ASSERT_EQUAL(pNData
->maStart
, aNDataStart
);
3803 CPPUNIT_ASSERT_EQUAL(pNData
->maEnd
, aNDataEnd
);
3808 void ScExportTest::testMatrixMultiplicationXLSX()
3810 ScDocShellRef xShell
= loadDoc("matrix-multiplication.", FORMAT_XLSX
);
3811 CPPUNIT_ASSERT(xShell
.is());
3813 ScDocShellRef xDocSh
= saveAndReload(&(*xShell
), FORMAT_XLSX
);
3814 CPPUNIT_ASSERT(xDocSh
.is());
3816 xmlDocPtr pDoc
= XPathHelper::parseExport2(*this, *xDocSh
, m_xSFactory
, "xl/worksheets/sheet1.xml", FORMAT_XLSX
);
3817 CPPUNIT_ASSERT(pDoc
);
3819 OUString CellFormulaRange
= getXPath(pDoc
,
3820 "/x:worksheet/x:sheetData/x:row[4]/x:c/x:f","ref");
3822 // make sure that the CellFormulaRange is G5:G6.
3823 CPPUNIT_ASSERT_EQUAL(OUString("G5:G6"), CellFormulaRange
);
3825 OUString CellFormulaType
= getXPath(pDoc
,
3826 "/x:worksheet/x:sheetData/x:row[4]/x:c/x:f","t");
3828 // make sure that the CellFormulaType is array.
3829 CPPUNIT_ASSERT_EQUAL(OUString("array"), CellFormulaType
);
3834 void ScExportTest::testRefStringXLSX()
3836 ScDocShellRef xDocSh
= loadDoc("ref_string.", FORMAT_XLSX
);
3837 CPPUNIT_ASSERT_MESSAGE("Failed to open doc", xDocSh
.is());
3839 //make sure ref syntax gets saved for MSO-produced docs
3840 xDocSh
= saveAndReload( &(*xDocSh
), FORMAT_XLSX
);
3841 CPPUNIT_ASSERT_MESSAGE("Failed to reload doc", xDocSh
.is());
3843 ScDocument
& rDoc
= xDocSh
->GetDocument();
3844 ScCalcConfig aCalcConfig
= rDoc
.GetCalcConfig();
3845 CPPUNIT_ASSERT_EQUAL(formula::FormulaGrammar::CONV_XL_A1
, aCalcConfig
.meStringRefAddressSyntax
);
3850 void ScExportTest::testRefStringConfigXLSX()
3852 // this doc is configured with CalcA1 ref syntax
3853 ScDocShellRef xDocSh
= loadDoc("empty.", FORMAT_XLSX
);
3854 CPPUNIT_ASSERT_MESSAGE("Failed to open doc", xDocSh
.is());
3856 xDocSh
= saveAndReload( &(*xDocSh
), FORMAT_XLSX
);
3857 CPPUNIT_ASSERT_MESSAGE("Failed to reload doc", xDocSh
.is());
3859 ScDocument
& rDoc
= xDocSh
->GetDocument();
3860 ScCalcConfig aConfig
= rDoc
.GetCalcConfig();
3861 CPPUNIT_ASSERT_EQUAL_MESSAGE("String ref syntax doesn't match", formula::FormulaGrammar::CONV_OOO
,
3862 aConfig
.meStringRefAddressSyntax
);
3866 // this doc has no entry for ref syntax
3867 xDocSh
= loadDoc("empty-noconf.", FORMAT_XLSX
);
3868 CPPUNIT_ASSERT_MESSAGE("Failed to open 2nd doc", xDocSh
.is());
3870 ScDocument
& rDoc2
= xDocSh
->GetDocument();
3871 aConfig
= rDoc2
.GetCalcConfig();
3872 // therefore after import, ref syntax should be set to CalcA1 | ExcelA1
3873 CPPUNIT_ASSERT_EQUAL_MESSAGE("String ref syntax doesn't match", formula::FormulaGrammar::CONV_A1_XL_A1
,
3874 aConfig
.meStringRefAddressSyntax
);
3876 //set ref syntax to something else than ExcelA1 (native to xlsx format) ...
3877 aConfig
.meStringRefAddressSyntax
= formula::FormulaGrammar::CONV_XL_R1C1
;
3878 rDoc2
.SetCalcConfig( aConfig
);
3880 ScDocShellRef xNewDocSh
= saveAndReload( &(*xDocSh
), FORMAT_XLSX
);
3881 CPPUNIT_ASSERT_MESSAGE("Failed to reload 2nd doc", xNewDocSh
.is());
3883 // ... and make sure it got saved
3884 ScDocument
& rDoc3
= xNewDocSh
->GetDocument();
3885 aConfig
= rDoc3
.GetCalcConfig();
3886 CPPUNIT_ASSERT_EQUAL_MESSAGE("String ref syntax doesn't match", formula::FormulaGrammar::CONV_XL_R1C1
,
3887 aConfig
.meStringRefAddressSyntax
);
3890 xNewDocSh
->DoClose();
3893 void ScExportTest::testRefStringUnspecified()
3895 ScDocShell
* pShell
= new ScDocShell(
3896 SfxModelFlags::EMBEDDED_OBJECT
|
3897 SfxModelFlags::DISABLE_EMBEDDED_SCRIPTS
|
3898 SfxModelFlags::DISABLE_DOCUMENT_RECOVERY
);
3899 pShell
->DoInitNew();
3901 ScDocument
& rDoc
= pShell
->GetDocument();
3902 ScCalcConfig aConfig
= rDoc
.GetCalcConfig();
3903 CPPUNIT_ASSERT_EQUAL_MESSAGE("Default string ref syntax value doesn't match", formula::FormulaGrammar::CONV_UNSPECIFIED
,
3904 aConfig
.meStringRefAddressSyntax
);
3906 // change formula syntax (i.e. not string ref syntax) to ExcelA1
3907 rDoc
.SetGrammar( formula::FormulaGrammar::GRAM_NATIVE_XL_A1
);
3909 ScDocShellRef xDocSh
= saveAndReload(pShell
, FORMAT_ODS
);
3910 CPPUNIT_ASSERT_MESSAGE("Failed to reload doc", xDocSh
.is());
3912 // with string ref syntax at its default value, we should've saved ExcelA1
3913 ScDocument
& rDoc2
= xDocSh
->GetDocument();
3914 aConfig
= rDoc2
.GetCalcConfig();
3915 CPPUNIT_ASSERT_EQUAL_MESSAGE("String ref syntax doesn't match", formula::FormulaGrammar::CONV_XL_A1
,
3916 aConfig
.meStringRefAddressSyntax
);
3921 void ScExportTest::testHeaderImageODS()
3923 // Graphic as header background was lost on export.
3924 ScDocShellRef xShell
= loadDoc("header-image.", FORMAT_ODS
);
3925 ScDocShellRef xDocSh
= saveAndReload(&(*xShell
), FORMAT_ODS
);
3926 uno::Reference
<style::XStyleFamiliesSupplier
> xStyleFamiliesSupplier(xDocSh
->GetModel(), uno::UNO_QUERY
);
3927 uno::Reference
<container::XNameAccess
> xStyleFamilies
= xStyleFamiliesSupplier
->getStyleFamilies();
3928 uno::Reference
<container::XNameAccess
> xPageStyles(xStyleFamilies
->getByName("PageStyles"), uno::UNO_QUERY
);
3929 uno::Reference
<beans::XPropertySet
> xStyle(xPageStyles
->getByName("Default"), uno::UNO_QUERY
);
3931 uno::Reference
<graphic::XGraphic
> xGraphic
;
3932 xStyle
->getPropertyValue("HeaderBackGraphic") >>= xGraphic
;
3933 CPPUNIT_ASSERT(xGraphic
.is());
3937 void ScExportTest::testTextDirectionXLSX()
3939 ScDocShellRef xDocSh
= loadDoc("writingMode.", FORMAT_XLSX
);
3940 CPPUNIT_ASSERT(xDocSh
.is());
3942 xmlDocPtr pDoc
= XPathHelper::parseExport2(*this, *xDocSh
, m_xSFactory
, "xl/styles.xml", FORMAT_XLSX
);
3943 CPPUNIT_ASSERT(pDoc
);
3945 assertXPath(pDoc
, "/x:styleSheet/x:cellXfs/x:xf[2]/x:alignment", "readingOrder", "1");//LTR
3946 assertXPath(pDoc
, "/x:styleSheet/x:cellXfs/x:xf[3]/x:alignment", "readingOrder", "2");//RTL
3949 void ScExportTest::testTdf88657ODS()
3951 ScDocShellRef xDocSh
= loadDoc("tdf88657.", FORMAT_ODS
);
3952 CPPUNIT_ASSERT(xDocSh
.is());
3954 xmlDocPtr pDoc
= XPathHelper::parseExport2(*this, *xDocSh
, m_xSFactory
, "styles.xml", FORMAT_ODS
);
3955 CPPUNIT_ASSERT(pDoc
);
3957 assertXPath(pDoc
, "//number:fraction", "min-denominator-digits", "3");
3960 void ScExportTest::testConditionalFormatRangeListXLSX()
3962 ScDocShellRef xDocSh
= loadDoc("conditionalformat_rangelist.", FORMAT_ODS
);
3963 CPPUNIT_ASSERT(xDocSh
.is());
3965 xmlDocPtr pDoc
= XPathHelper::parseExport2(*this, *xDocSh
, m_xSFactory
, "xl/worksheets/sheet1.xml", FORMAT_XLSX
);
3966 CPPUNIT_ASSERT(pDoc
);
3968 assertXPath(pDoc
, "//x:conditionalFormatting", "sqref", "F4 F10");
3971 void ScExportTest::testConditionalFormatContainsTextXLSX()
3973 ScDocShellRef xDocSh
= loadDoc("conditionalformat_containstext.", FORMAT_ODS
);
3974 CPPUNIT_ASSERT(xDocSh
.is());
3976 xmlDocPtr pDoc
= XPathHelper::parseExport2(*this, *xDocSh
, m_xSFactory
, "xl/worksheets/sheet1.xml", FORMAT_XLSX
);
3977 CPPUNIT_ASSERT(pDoc
);
3979 assertXPathContent(pDoc
, "//x:conditionalFormatting/x:cfRule/x:formula", "NOT(ISERROR(SEARCH(\"test\",A1)))");
3982 void ScExportTest::testEscapeCharInNumberFormatXLSX()
3984 ScDocShellRef xDocSh
= loadDoc("tdf81939.", FORMAT_XLSX
);
3985 CPPUNIT_ASSERT( xDocSh
.is() );
3986 xDocSh
= saveAndReload( &(*xDocSh
), FORMAT_XLSX
);
3987 CPPUNIT_ASSERT( xDocSh
.is() );
3989 xmlDocPtr pDoc
= XPathHelper::parseExport2(*this, *xDocSh
, m_xSFactory
, "xl/styles.xml", FORMAT_XLSX
);
3990 CPPUNIT_ASSERT(pDoc
);
3992 const sal_Unicode
cEuro (8364); // € symbol
3993 assertXPath(pDoc
, "/x:styleSheet/x:numFmts/x:numFmt[2]", "formatCode", "00\\ 00\\ 00\\ 00\\ 00");
3994 assertXPath(pDoc
, "/x:styleSheet/x:numFmts/x:numFmt[3]", "formatCode", "00\\.00\\.00\\.000\\.0"); // tdf#81939
3995 // "_-* #,##0\ _€_-;\-* #,##0\ _€_-;_-* "- "_€_-;_-@_-" // tdf#81222
3996 OUString
rFormatStrExpected ( "_-* #,##0\\ _" + OUStringLiteral1(cEuro
) + "_-;\\-* #,##0\\ _" +
3997 OUStringLiteral1(cEuro
) + "_-;_-* \"- \"_" + OUStringLiteral1(cEuro
) + "_-;_-@_-" );
3998 assertXPath(pDoc
, "/x:styleSheet/x:numFmts/x:numFmt[4]", "formatCode", rFormatStrExpected
);
3999 // "_-* #,##0" €"_-;\-* #,##0" €"_-;_-* "- €"_-;_-@_-");
4000 rFormatStrExpected
= "_-* #,##0\" " + OUStringLiteral1(cEuro
) + "\"_-;\\-* #,##0\" " +
4001 OUStringLiteral1(cEuro
) + "\"_-;_-* \"- " + OUStringLiteral1(cEuro
) + "\"_-;_-@_-";
4002 assertXPath(pDoc
, "/x:styleSheet/x:numFmts/x:numFmt[5]", "formatCode", rFormatStrExpected
);
4003 // remove escape char in fraction
4004 assertXPath(pDoc
, "/x:styleSheet/x:numFmts/x:numFmt[6]", "formatCode", "# ?/?;[RED]\\-# #/#####");
4009 void ScExportTest::testNatNumInNumberFormatXLSX()
4011 ScDocShellRef xDocSh
= loadDoc("tdf79398_NatNum5.", FORMAT_ODS
);
4012 CPPUNIT_ASSERT( xDocSh
.is() );
4013 xDocSh
= saveAndReload( &(*xDocSh
), FORMAT_XLSX
); // Convert [NatNum5] to [DBNum2] in Chinese
4014 CPPUNIT_ASSERT( xDocSh
.is() );
4016 xmlDocPtr pDoc
= XPathHelper::parseExport2(*this, *xDocSh
, m_xSFactory
, "xl/styles.xml", FORMAT_XLSX
);
4017 CPPUNIT_ASSERT(pDoc
);
4019 assertXPath(pDoc
, "/x:styleSheet/x:numFmts/x:numFmt[3]", "formatCode", "[DBNum2][$-804]General;[RED][DBNum2][$-804]General");
4024 void ScExportTest::testExponentWithoutSignFormatXLSX()
4026 ScDocShellRef xDocSh
= loadDoc("tdf102370_ExponentWithoutSign.", FORMAT_ODS
);
4027 CPPUNIT_ASSERT( xDocSh
.is() );
4028 xDocSh
= saveAndReload( &(*xDocSh
), FORMAT_XLSX
);
4029 CPPUNIT_ASSERT( xDocSh
.is() );
4031 xDocSh
= saveAndReload( &(*xDocSh
), FORMAT_ODS
);
4032 CPPUNIT_ASSERT(xDocSh
.is());
4034 ScDocument
& rDoc
= xDocSh
->GetDocument();
4035 sal_uInt32 nNumberFormat
;
4036 rDoc
.GetNumberFormat(0, 0, 0, nNumberFormat
);
4037 const SvNumberformat
* pNumberFormat
= rDoc
.GetFormatTable()->GetEntry(nNumberFormat
);
4038 const OUString
& rFormatStr
= pNumberFormat
->GetFormatstring();
4039 const OUString aExpectedFormatStr
= "0.00E0";
4041 CPPUNIT_ASSERT_EQUAL_MESSAGE("Number format lost exponent without sign during Excel export", aExpectedFormatStr
, rFormatStr
);
4046 void ScExportTest::testExtendedLCIDXLSX()
4048 ScDocShellRef xDocSh
= loadDoc("tdf36038_ExtendedLCID.", FORMAT_ODS
);
4049 CPPUNIT_ASSERT( xDocSh
.is() );
4050 xDocSh
= saveAndReload( &(*xDocSh
), FORMAT_XLSX
);
4051 CPPUNIT_ASSERT( xDocSh
.is() );
4053 xmlDocPtr pDoc
= XPathHelper::parseExport2(*this, *xDocSh
, m_xSFactory
, "xl/styles.xml", FORMAT_XLSX
);
4054 CPPUNIT_ASSERT(pDoc
);
4056 assertXPath(pDoc
, "/x:styleSheet/x:numFmts/x:numFmt[2]", "formatCode", "[$-107041E]DD\\-MM\\-YYYY");
4057 assertXPath(pDoc
, "/x:styleSheet/x:numFmts/x:numFmt[3]", "formatCode", "[$-D07041E]DD\\-MM\\-YYYY");
4058 assertXPath(pDoc
, "/x:styleSheet/x:numFmts/x:numFmt[4]", "formatCode", "[$-1030411]DD\\-MM\\-EE");
4059 assertXPath(pDoc
, "/x:styleSheet/x:numFmts/x:numFmt[5]", "formatCode", "[$-1B030411]DD\\-MM\\-EE");
4060 assertXPath(pDoc
, "/x:styleSheet/x:numFmts/x:numFmt[6]", "formatCode", "[$-108040D]DD\\-MM\\-YYYY");
4061 //assertXPath(pDoc, "/x:styleSheet/x:numFmts/x:numFmt[7]", "formatCode", "[$-108040D]DD\\-MM\\-YYYY");
4062 assertXPath(pDoc
, "/x:styleSheet/x:numFmts/x:numFmt[7]", "formatCode", "[$-1060401]DD\\-MM\\-YYYY");
4063 assertXPath(pDoc
, "/x:styleSheet/x:numFmts/x:numFmt[8]", "formatCode", "[$-2060401]DD\\-MM\\-YYYY");
4066 ScDocument
& rDoc
= xDocSh
->GetDocument();
4067 SvNumberFormatter
* pNumFormatter
= rDoc
.GetFormatTable();
4068 sal_uInt32 nNumberFormat
;
4069 const OUString aLang
[4] = { "[$-41E]", "[$-411]", "[$-40D]", "[$-401]" };
4070 const OUString aCalendar
[4] = { "[~buddhist]DD-MM-YYYY", "[~gengou]DD-MM-EE", "[~jewish]DD-MM-YYYY", "[~hijri]DD-MM-YYYY" };
4071 for ( sal_Int16 nCol
= 1; nCol
<= 2; nCol
++ )
4073 for ( sal_Int16 nRow
= 1; nRow
<= 4; nRow
++ )
4075 rDoc
.GetNumberFormat(nCol
, nRow
, 0, nNumberFormat
);
4076 const SvNumberformat
* pNumberFormat
= pNumFormatter
->GetEntry(nNumberFormat
);
4077 const OUString
& rFormatStr
= pNumberFormat
->GetFormatstring();
4078 const OUString aExpectedFormatStr
= aLang
[nRow
-1] + ( (nCol
==2 && nRow
!=3) ? OUString("[NatNum1]") : OUString() ) + aCalendar
[nRow
-1];
4080 CPPUNIT_ASSERT_EQUAL_MESSAGE("Number format lost extended LCID during Excel export", aExpectedFormatStr
, rFormatStr
);
4087 void ScExportTest::testHiddenRepeatedRowsODS()
4089 ScDocShellRef xDocSh
= loadDoc("empty.", FORMAT_ODS
);
4090 CPPUNIT_ASSERT( xDocSh
.is() );
4093 ScDocument
& rDoc
= xDocSh
->GetDocument();
4094 rDoc
.SetRowHidden(0, 20, 0, true);
4097 xDocSh
= saveAndReload( &(*xDocSh
), FORMAT_ODS
);
4098 ScDocument
& rDoc
= xDocSh
->GetDocument();
4099 SCROW nFirstRow
= 0;
4101 bool bHidden
= rDoc
.RowHidden(0, 0, &nFirstRow
, &nLastRow
);
4102 CPPUNIT_ASSERT(bHidden
);
4103 CPPUNIT_ASSERT_EQUAL(SCROW(0), nFirstRow
);
4104 CPPUNIT_ASSERT_EQUAL(SCROW(20), nLastRow
);
4108 void ScExportTest::testHyperlinkTargetFrameODS()
4110 ScDocShellRef xDocSh
= loadDoc("hyperlink_frame.", FORMAT_ODS
);
4111 CPPUNIT_ASSERT(xDocSh
.is());
4113 ScDocument
& rDoc
= xDocSh
->GetDocument();
4114 const EditTextObject
* pEditText
= rDoc
.GetEditText(ScAddress(2, 5, 0));
4115 CPPUNIT_ASSERT(pEditText
);
4117 const SvxFieldData
* pData
= pEditText
->GetFieldData(0, 0, text::textfield::Type::URL
);
4118 CPPUNIT_ASSERT_MESSAGE("Failed to get the URL data.", pData
&& pData
->GetClassId() == text::textfield::Type::URL
);
4120 const SvxURLField
* pURLData
= static_cast<const SvxURLField
*>(pData
);
4121 OUString aTargetFrame
= pURLData
->GetTargetFrame();
4122 CPPUNIT_ASSERT_EQUAL(OUString("_blank"), aTargetFrame
);
4124 xmlDocPtr pDoc
= XPathHelper::parseExport2(*this, *xDocSh
, m_xSFactory
, "content.xml", FORMAT_ODS
);
4125 CPPUNIT_ASSERT(pDoc
);
4126 OUString aTargetFrameExport
= getXPath(pDoc
,
4127 "/office:document-content/office:body/office:spreadsheet/table:table/table:table-row[2]/table:table-cell[2]/text:p/text:a", "target-frame-name");
4128 CPPUNIT_ASSERT_EQUAL(OUString("_blank"), aTargetFrameExport
);
4131 void ScExportTest::testOpenDocumentAsReadOnly()
4133 ScDocShellRef xDocSh
= loadDoc("open-as-read-only.", FORMAT_XLSX
);
4134 CPPUNIT_ASSERT(xDocSh
->IsSecurityOptOpenReadOnly());
4135 ScDocShellRef xDocSh2
= saveAndReload(xDocSh
.get(), FORMAT_XLSX
);
4136 CPPUNIT_ASSERT(xDocSh2
->IsSecurityOptOpenReadOnly());
4141 void ScExportTest::testKeepSettingsOfBlankRows()
4143 ScDocShellRef xDocSh
= loadDoc("tdf41425.", FORMAT_XLSX
);
4144 CPPUNIT_ASSERT(xDocSh
.is());
4146 std::shared_ptr
<utl::TempFile
> pXPathFile
= ScBootstrapFixture::exportTo(&(*xDocSh
), FORMAT_XLSX
);
4147 xmlDocPtr pSheet
= XPathHelper::parseExport(pXPathFile
, m_xSFactory
, "xl/worksheets/sheet1.xml");
4148 CPPUNIT_ASSERT(pSheet
);
4150 // saved blank row with not default setting in A2
4151 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row", 2);
4154 void ScExportTest::testTdf118990()
4156 ScDocShellRef xDocSh
= loadDoc("tdf118990.", FORMAT_XLSX
);
4157 CPPUNIT_ASSERT(xDocSh
.is());
4158 xDocSh
= saveAndReload(xDocSh
.get(), FORMAT_XLSX
);
4159 ScDocument
& rDoc
= xDocSh
->GetDocument();
4161 // TODO: also test A1, which contains a UNC reference to \\localhost\share\lookupsource.xlsx,
4162 // but currently looses "localhost" part when normalized in INetURLObject, becoming
4163 // file:///share/lookupsource.xlsx - which is incorrect, since it points to local filesystem
4164 // and not to Windows network share.
4166 ASSERT_FORMULA_EQUAL(rDoc
, ScAddress(0, 1, 0),
4167 "VLOOKUP(B1,'file://192.168.1.1/share/lookupsource.xlsx'#$Sheet1.A1:B5,2)",
4168 "Wrong Windows share (using host IP) URL in A2");
4170 ASSERT_FORMULA_EQUAL(rDoc
, ScAddress(0, 2, 0),
4171 "VLOOKUP(B1,'file://NETWORKHOST/share/lookupsource.xlsx'#$Sheet1.A1:B5,2)",
4172 "Wrong Windows share (using hostname) URL in A3");
4177 void ScExportTest::testTdf121612()
4179 ScDocShellRef xDocSh
= loadDoc("tdf121612.", FORMAT_ODS
);
4180 CPPUNIT_ASSERT(xDocSh
.is());
4181 xDocSh
= saveAndReload(xDocSh
.get(), FORMAT_XLSX
);
4183 ScDocument
& rDoc
= xDocSh
->GetDocument();
4185 // There should be a pivot table
4186 CPPUNIT_ASSERT(rDoc
.HasPivotTable());
4188 // DP collection is not lost after export and has one entry
4189 ScDPCollection
* pDPColl
= rDoc
.GetDPCollection();
4190 CPPUNIT_ASSERT(pDPColl
);
4191 CPPUNIT_ASSERT_EQUAL(size_t(1), pDPColl
->GetCount());
4194 void ScExportTest::testXltxExport()
4196 // Create new document
4197 ScDocShell
* pShell
= new ScDocShell(
4198 SfxModelFlags::EMBEDDED_OBJECT
|
4199 SfxModelFlags::DISABLE_EMBEDDED_SCRIPTS
|
4200 SfxModelFlags::DISABLE_DOCUMENT_RECOVERY
);
4201 pShell
->DoInitNew();
4203 // Export as template and check content type
4204 xmlDocPtr pDoc
= XPathHelper::parseExport2(*this, *pShell
, m_xSFactory
, "[Content_Types].xml", FORMAT_XLTX
);
4205 CPPUNIT_ASSERT(pDoc
);
4206 assertXPath(pDoc
, "/ContentType:Types/ContentType:Override[@PartName='/xl/workbook.xml']",
4207 "ContentType", "application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml");
4210 void ScExportTest::testPivotCacheAfterExportXLSX()
4212 ScDocShellRef xDocSh
= loadDoc("numgroup_example.", FORMAT_ODS
);
4213 CPPUNIT_ASSERT(xDocSh
.is());
4216 std::shared_ptr
<utl::TempFile
> pTemp
= saveAs(xDocSh
.get(), FORMAT_XLSX
);
4218 ScDocument
& rDoc
= xDocSh
->GetDocument();
4219 CPPUNIT_ASSERT(rDoc
.HasPivotTable());
4222 ScDPCollection
* pDPColl
= rDoc
.GetDPCollection();
4223 CPPUNIT_ASSERT(pDPColl
);
4224 CPPUNIT_ASSERT_EQUAL(size_t(2), pDPColl
->GetCount());
4227 ScDPCollection::SheetCaches
& rSheetCaches
= pDPColl
->GetSheetCaches();
4228 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rSheetCaches
.size());
4229 const ScDPCache
* pCache
= rSheetCaches
.getExistingCache(ScRange(0, 0, 0, 3, 30, 0));
4230 CPPUNIT_ASSERT_MESSAGE("Pivot cache is expected for A1:D31 on the first sheet.", pCache
);
4232 // See if XLSX export didn't damage group info of the 1st pivot table
4233 const ScDPNumGroupInfo
* pInfo
= pCache
->GetNumGroupInfo(1);
4234 CPPUNIT_ASSERT_MESSAGE("No number group info :(", pInfo
);
4239 CPPUNIT_TEST_SUITE_REGISTRATION(ScExportTest
);
4241 CPPUNIT_PLUGIN_IMPLEMENT();
4243 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */