Move dubious file: -> smb: conversion from INetURLObject to file UCP
[LibreOffice.git] / sc / qa / unit / subsequent_export-test.cxx
blob1b44d58235c5030d7a73cd7f833d5fda6e3f6480
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
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>
26 #include <docsh.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>
36 #include <postit.hxx>
37 #include <tokenstringcontext.hxx>
38 #include <chgtrack.hxx>
39 #include <validat.hxx>
40 #include <global.hxx>
41 #include <scmod.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
77 protected:
78 virtual void registerNamespaces(xmlXPathContextPtr& pXmlXPathCtx) override;
79 public:
80 ScExportTest();
82 virtual void setUp() override;
83 virtual void tearDown() override;
85 ScDocShellRef saveAndReloadPassword( ScDocShell*, const OUString&, const OUString&, const OUString&, SfxFilterFlags );
87 void test();
88 void testTdf111876();
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();
118 #if HAVE_MORE_FONTS
119 void testCustomColumnWidthExportXLSX();
120 #endif
121 void testXfDefaultValuesXLSX();
122 void testColumnWidthResaveXLSX();
123 #if HAVE_MORE_FONTS
124 void testColumnWidthExportFromODStoXLSX();
125 #endif
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();
163 #if !defined _WIN32
164 void testRelativePathsODS();
165 #endif
166 void testSheetProtectionODS();
168 void testSwappedOutImageExport();
169 void testLinkedGraphicRT();
170 void testImageWithSpecialID();
172 #if !defined _WIN32
173 void testSupBookVirtualPathXLS();
174 #endif
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);
217 CPPUNIT_TEST(test);
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);
246 #if HAVE_MORE_FONTS
247 CPPUNIT_TEST(testCustomColumnWidthExportXLSX);
248 #endif
249 CPPUNIT_TEST(testXfDefaultValuesXLSX);
250 CPPUNIT_TEST(testColumnWidthResaveXLSX);
251 #if HAVE_MORE_FONTS
252 CPPUNIT_TEST(testColumnWidthExportFromODStoXLSX);
253 #endif
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);
282 #if !defined(_WIN32)
283 CPPUNIT_TEST(testRelativePathsODS);
284 #endif
285 CPPUNIT_TEST(testSheetProtectionODS);
286 #if !defined(_WIN32)
287 CPPUNIT_TEST(testSupBookVirtualPathXLS);
288 #endif
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();
335 private:
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(
384 rFilter,
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 );
397 pShell->DoClose();
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);
415 pShell->DoInitNew();
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);
427 xDocSh->DoClose();
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");
447 xDocSh->DoClose();
450 void ScExportTest::testPasswordExportODS()
452 ScDocShell* pShell = new ScDocShell(
453 SfxModelFlags::EMBEDDED_OBJECT |
454 SfxModelFlags::DISABLE_EMBEDDED_SCRIPTS |
455 SfxModelFlags::DISABLE_DOCUMENT_RECOVERY);
456 pShell->DoInitNew();
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);
472 xDocSh->DoClose();
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();
483 OUString aCSVPath;
484 createCSVPath( "new_cond_format_test_export.", aCSVPath );
485 testCondFile(aCSVPath, &rDoc, 0);
487 xDocSh->DoClose();
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();
499 OUString aCSVPath;
500 createCSVPath( "new_cond_format_test_export.", aCSVPath );
501 testCondFile(aCSVPath, &rDoc, 0);
504 OUString aCSVPath;
505 createCSVPath( "new_cond_format_test_sheet2.", aCSVPath );
506 testCondFile(aCSVPath, &rDoc, 1);
509 xDocSh->DoClose();
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());
530 xDocSh->DoClose();
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);
651 xDocSh->DoClose();
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);
667 xDocSh->DoClose();
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);
682 xDocSh->DoClose();
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);
697 xDocSh->DoClose();
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);
762 #if HAVE_MORE_FONTS
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");
854 #endif
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);
917 #if HAVE_MORE_FONTS
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();
958 // Col 1, Tab 0
959 sal_uInt16 nCalcWidth;
960 nCalcWidth = rDoc.GetColWidth(static_cast<SCCOL>(0), static_cast<SCTAB>(0), false);
961 CPPUNIT_ASSERT_EQUAL( nExpectedColumn0Width, nCalcWidth );
963 // Col 2, Tab 0
964 nCalcWidth = rDoc.GetColWidth(static_cast<SCCOL>(1), static_cast<SCTAB>(0), false);
965 CPPUNIT_ASSERT_EQUAL( nExpectedColumn1Width, nCalcWidth );
967 // Col 3, Tab 0
968 nCalcWidth = rDoc.GetColWidth(static_cast<SCCOL>(2), static_cast<SCTAB>(0), false);
969 CPPUNIT_ASSERT_EQUAL( nExpectedColumn2Width, nCalcWidth );
971 // Col 4, Tab 0
972 nCalcWidth = rDoc.GetColWidth(static_cast<SCCOL>(3), static_cast<SCTAB>(0), false);
973 CPPUNIT_ASSERT_EQUAL( nExpectedColumn3Width, nCalcWidth );
975 // Col 5, Tab 0
976 nCalcWidth = rDoc.GetColWidth(static_cast<SCCOL>(4), static_cast<SCTAB>(0), false);
977 CPPUNIT_ASSERT_EQUAL( nExpectedColumn4Width, nCalcWidth );
979 xXlsxDocSh->DoClose();
981 #endif
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);
1191 xDocSh->DoClose();
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) );
1234 namespace {
1236 void setAttribute( ScFieldEditEngine& rEE, sal_Int32 nPara, sal_Int32 nStart, sal_Int32 nEnd, sal_uInt16 nType, Color nColor = COL_BLACK )
1238 ESelection aSel;
1239 aSel.nStartPara = aSel.nEndPara = nPara;
1240 aSel.nStartPos = nStart;
1241 aSel.nEndPos = nEnd;
1243 SfxItemSet aItemSet = rEE.GetEmptyItemSet();
1244 switch (nType)
1246 case EE_CHAR_WEIGHT:
1248 SvxWeightItem aWeight(WEIGHT_BOLD, nType);
1249 aItemSet.Put(aWeight);
1250 rEE.QuickSetAttribs(aItemSet, aSel);
1252 break;
1253 case EE_CHAR_ITALIC:
1255 SvxPostureItem aItalic(ITALIC_NORMAL, nType);
1256 aItemSet.Put(aItalic);
1257 rEE.QuickSetAttribs(aItemSet, aSel);
1259 break;
1260 case EE_CHAR_STRIKEOUT:
1262 SvxCrossedOutItem aCrossOut(STRIKEOUT_SINGLE, nType);
1263 aItemSet.Put(aCrossOut);
1264 rEE.QuickSetAttribs(aItemSet, aSel);
1266 break;
1267 case EE_CHAR_OVERLINE:
1269 SvxOverlineItem aItem(LINESTYLE_DOUBLE, nType);
1270 aItemSet.Put(aItem);
1271 rEE.QuickSetAttribs(aItemSet, aSel);
1273 break;
1274 case EE_CHAR_UNDERLINE:
1276 SvxUnderlineItem aItem(LINESTYLE_DOUBLE, nType);
1277 aItemSet.Put(aItem);
1278 rEE.QuickSetAttribs(aItemSet, aSel);
1280 break;
1281 case EE_CHAR_COLOR:
1283 SvxColorItem aItem(nColor, nType);
1284 aItemSet.Put(aItem);
1285 rEE.QuickSetAttribs(aItemSet, aSel);
1287 break;
1288 default:
1293 void setFont( ScFieldEditEngine& rEE, sal_Int32 nPara, sal_Int32 nStart, sal_Int32 nEnd, const OUString& rFontName )
1295 ESelection aSel;
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 )
1308 ESelection aSel;
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());
1330 rDoc.DeleteTab(0);
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);
1334 xShell->DoClose();
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());
1343 xDocSh->DoClose();
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());
1352 xShell->DoClose();
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);
1369 xDocSh->DoClose();
1372 void ScExportTest::testRichTextExportODS()
1374 struct
1376 static bool isBold(const editeng::Section& rAttr)
1378 if (rAttr.maAttributes.empty())
1379 return false;
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)
1386 continue;
1388 return static_cast<const SvxWeightItem*>(p)->GetWeight() == WEIGHT_BOLD;
1390 return false;
1393 static bool isItalic(const editeng::Section& rAttr)
1395 if (rAttr.maAttributes.empty())
1396 return false;
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)
1403 continue;
1405 return static_cast<const SvxPostureItem*>(p)->GetPosture() == ITALIC_NORMAL;
1407 return false;
1410 static bool isStrikeOut(const editeng::Section& rAttr)
1412 if (rAttr.maAttributes.empty())
1413 return false;
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)
1420 continue;
1422 return static_cast<const SvxCrossedOutItem*>(p)->GetStrikeout() == STRIKEOUT_SINGLE;
1424 return false;
1427 static bool isOverline(const editeng::Section& rAttr, FontLineStyle eStyle)
1429 if (rAttr.maAttributes.empty())
1430 return false;
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)
1437 continue;
1439 return static_cast<const SvxOverlineItem*>(p)->GetLineStyle() == eStyle;
1441 return false;
1444 static bool isUnderline(const editeng::Section& rAttr, FontLineStyle eStyle)
1446 if (rAttr.maAttributes.empty())
1447 return false;
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)
1454 continue;
1456 return static_cast<const SvxUnderlineItem*>(p)->GetLineStyle() == eStyle;
1458 return false;
1461 static bool isFont(const editeng::Section& rAttr, const OUString& rFontName)
1463 if (rAttr.maAttributes.empty())
1464 return false;
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)
1471 continue;
1473 return static_cast<const SvxFontItem*>(p)->GetFamilyName() == rFontName;
1475 return false;
1478 static bool isEscapement(const editeng::Section& rAttr, short nEsc, sal_uInt8 nRelSize)
1480 if (rAttr.maAttributes.empty())
1481 return false;
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)
1488 continue;
1490 const SvxEscapementItem* pItem = static_cast<const SvxEscapementItem*>(p);
1491 return ((pItem->GetEsc() == nEsc) && (pItem->GetProportionalHeight() == nRelSize));
1493 return false;
1496 static bool isColor(const editeng::Section& rAttr, Color nColor)
1498 if (rAttr.maAttributes.empty())
1499 return false;
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)
1506 continue;
1508 return static_cast<const SvxColorItem*>(p)->GetValue() == nColor;
1510 return false;
1513 bool checkB2(const EditTextObject* pText) const
1515 if (!pText)
1516 return false;
1518 if (pText->GetParagraphCount() != 1)
1519 return false;
1521 if (pText->GetText(0) != "Bold and Italic")
1522 return false;
1524 std::vector<editeng::Section> aSecAttrs;
1525 pText->GetAllSections(aSecAttrs);
1526 if (aSecAttrs.size() != 3)
1527 return false;
1529 // Check the first bold section.
1530 const editeng::Section* pAttr = &aSecAttrs[0];
1531 if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 0 || pAttr->mnEnd != 4)
1532 return false;
1534 if (pAttr->maAttributes.size() != 1 || !isBold(*pAttr))
1535 return false;
1537 // The middle section should be unformatted.
1538 pAttr = &aSecAttrs[1];
1539 if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 4 || pAttr->mnEnd != 9)
1540 return false;
1542 if (!pAttr->maAttributes.empty())
1543 return false;
1545 // The last section should be italic.
1546 pAttr = &aSecAttrs[2];
1547 if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 9 || pAttr->mnEnd != 15)
1548 return false;
1550 if (pAttr->maAttributes.size() != 1 || !isItalic(*pAttr))
1551 return false;
1553 return true;
1556 bool checkB4(const EditTextObject* pText) const
1558 if (!pText)
1559 return false;
1561 if (pText->GetParagraphCount() != 3)
1562 return false;
1564 if (pText->GetText(0) != "One")
1565 return false;
1567 if (pText->GetText(1) != "Two")
1568 return false;
1570 if (pText->GetText(2) != "Three")
1571 return false;
1573 return true;
1576 bool checkB5(const EditTextObject* pText) const
1578 if (!pText)
1579 return false;
1581 if (pText->GetParagraphCount() != 6)
1582 return false;
1584 if (!pText->GetText(0).isEmpty())
1585 return false;
1587 if (pText->GetText(1) != "Two")
1588 return false;
1590 if (pText->GetText(2) != "Three")
1591 return false;
1593 if (!pText->GetText(3).isEmpty())
1594 return false;
1596 if (pText->GetText(4) != "Five")
1597 return false;
1599 if (!pText->GetText(5).isEmpty())
1600 return false;
1602 return true;
1605 bool checkB6(const EditTextObject* pText) const
1607 if (!pText)
1608 return false;
1610 if (pText->GetParagraphCount() != 1)
1611 return false;
1613 if (pText->GetText(0) != "Strike Me")
1614 return false;
1616 std::vector<editeng::Section> aSecAttrs;
1617 pText->GetAllSections(aSecAttrs);
1618 if (aSecAttrs.size() != 2)
1619 return false;
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)
1624 return false;
1626 if (pAttr->maAttributes.size() != 1 || !isStrikeOut(*pAttr))
1627 return false;
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
1636 if (!pText)
1637 return false;
1639 if (pText->GetParagraphCount() != 1)
1640 return false;
1642 if (pText->GetText(0) != "Font1 and Font2")
1643 return false;
1645 std::vector<editeng::Section> aSecAttrs;
1646 pText->GetAllSections(aSecAttrs);
1647 if (aSecAttrs.size() != 3)
1648 return false;
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)
1653 return false;
1655 if (pAttr->maAttributes.size() != 1 || !isFont(*pAttr, "Courier"))
1656 return false;
1658 // Last section should have "Luxi Mono" applied.
1659 pAttr = &aSecAttrs[2];
1660 if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 10 || pAttr->mnEnd != 15)
1661 return false;
1663 if (pAttr->maAttributes.size() != 1 || !isFont(*pAttr, "Luxi Mono"))
1664 return false;
1666 return true;
1669 bool checkB8(const EditTextObject* pText) const
1671 if (!pText)
1672 return false;
1674 if (pText->GetParagraphCount() != 1)
1675 return false;
1677 if (pText->GetText(0) != "Over and Under")
1678 return false;
1680 std::vector<editeng::Section> aSecAttrs;
1681 pText->GetAllSections(aSecAttrs);
1682 if (aSecAttrs.size() != 3)
1683 return false;
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)
1688 return false;
1690 if (pAttr->maAttributes.size() != 1 || !isOverline(*pAttr, LINESTYLE_DOUBLE))
1691 return false;
1693 // Last section should have underline applied.
1694 pAttr = &aSecAttrs[2];
1695 if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 9 || pAttr->mnEnd != 14)
1696 return false;
1698 if (pAttr->maAttributes.size() != 1 || !isUnderline(*pAttr, LINESTYLE_DOUBLE))
1699 return false;
1701 return true;
1704 bool checkB9(const EditTextObject* pText) const
1706 if (!pText)
1707 return false;
1709 if (pText->GetParagraphCount() != 1)
1710 return false;
1712 if (pText->GetText(0) != "Sub and Super")
1713 return false;
1715 std::vector<editeng::Section> aSecAttrs;
1716 pText->GetAllSections(aSecAttrs);
1717 if (aSecAttrs.size() != 3)
1718 return false;
1720 // superscript
1721 const editeng::Section* pAttr = &aSecAttrs[0];
1722 if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 0 || pAttr->mnEnd != 3)
1723 return false;
1725 if (pAttr->maAttributes.size() != 1 || !isEscapement(*pAttr, 32, 64))
1726 return false;
1728 // subscript
1729 pAttr = &aSecAttrs[2];
1730 if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 8 || pAttr->mnEnd != 13)
1731 return false;
1733 if (pAttr->maAttributes.size() != 1 || !isEscapement(*pAttr, -32, 66))
1734 return false;
1736 return true;
1739 bool checkB10(const EditTextObject* pText) const
1741 if (!pText)
1742 return false;
1744 if (pText->GetParagraphCount() != 1)
1745 return false;
1747 if (pText->GetText(0) != "BLUE AUTO")
1748 return false;
1750 std::vector<editeng::Section> aSecAttrs;
1751 pText->GetAllSections(aSecAttrs);
1752 if (aSecAttrs.size() != 2)
1753 return false;
1755 // auto color
1756 const editeng::Section* pAttr = &aSecAttrs[1];
1757 if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 5 || pAttr->mnEnd != 9)
1758 return false;
1760 if (pAttr->maAttributes.size() != 1 || !isColor(*pAttr, COL_AUTO))
1761 return false;
1763 return true;
1766 } aCheckFunc;
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);
1783 ESelection aSel;
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.
1805 pEE->Clear();
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.
1825 pEE->Clear();
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.
1832 pEE->Clear();
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.
1841 pEE->Clear();
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.
1850 pEE->Clear();
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));
1858 pEE->Clear();
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);
1870 pEE->Clear();
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");
1932 xDocSh->DoClose();
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);
1948 xDocSh->DoClose();
1950 ScDocument& rDoc = xNewDocSh->GetDocument();
1951 rDoc.CalcAll();
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
1969 // set a formula
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
1976 // set a string
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
1988 // save and reload
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);
1995 // check value
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));
2002 // check formula
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));
2007 // check string
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));
2044 // save and reload
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();
2104 namespace {
2106 void checkMatrixRange(ScDocument& rDoc, const ScRange& rRange)
2108 ScRange aMatRange;
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);
2136 xShell->DoClose();
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));
2147 // B8:C10 as well.
2148 checkMatrixRange(rDoc, ScRange(1,7,0,2,9,0));
2150 xDocSh->DoClose();
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);
2163 assertXPath(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");
2168 xShell->DoClose();
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);
2177 xShell->DoClose();
2178 CPPUNIT_ASSERT(xDocSh.is());
2180 ScDocument& rDoc = xDocSh->GetDocument();
2182 // Make sure the 2nd sheet is named 'Chart1'.
2183 OUString aName;
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)));
2195 xDocSh->DoClose();
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);
2222 xDocSh->DoClose();
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);
2231 xShell->DoClose();
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");
2245 xDocSh->DoClose();
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);
2260 // check has
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 ) );
2269 xDocSh->DoClose();
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 ));
2285 xDocSh->DoClose();
2288 namespace {
2290 const char* toBorderName( SvxBorderLineStyle eStyle )
2292 switch (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";
2301 default:
2305 return "";
2310 void ScExportTest::testExcelCellBorders( sal_uLong nFormatType )
2312 static const struct
2314 SCROW mnRow;
2315 SvxBorderLineStyle mnStyle;
2316 long mnWidth;
2317 } aChecks[] = {
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);
2349 xDocSh->DoClose();
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;
2391 static struct
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 */
2399 /*Width */
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);
2440 continue;
2442 else
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());
2459 xDocSh->DoClose();
2462 static OUString toString( const ScBigRange& rRange )
2464 OUStringBuffer aBuf;
2465 aBuf.append("(columns:");
2466 aBuf.append(rRange.aStart.Col());
2467 aBuf.append('-');
2468 aBuf.append(rRange.aEnd.Col());
2469 aBuf.append(";rows:");
2470 aBuf.append(rRange.aStart.Row());
2471 aBuf.append('-');
2472 aBuf.append(rRange.aEnd.Row());
2473 aBuf.append(";sheets:");
2474 aBuf.append(rRange.aStart.Tab());
2475 aBuf.append('-');
2476 aBuf.append(rRange.aEnd.Tab());
2477 aBuf.append(')');
2479 return aBuf.makeStringAndClear();
2482 void ScExportTest::testTrackChangesSimpleXLSX()
2484 struct CheckItem
2486 sal_uLong mnActionId;
2487 ScChangeActionType meType;
2489 sal_Int32 mnStartCol;
2490 sal_Int32 mnStartRow;
2491 sal_Int32 mnStartTab;
2492 sal_Int32 mnEndCol;
2493 sal_Int32 mnEndRow;
2494 sal_Int32 mnEndTab;
2496 bool mbRowInsertedAtBottom;
2499 struct
2501 bool checkRange( ScChangeActionType eType, const ScBigRange& rExpected, const ScBigRange& rActual )
2503 ScBigRange aExpected(rExpected), aActual(rActual);
2505 switch (eType)
2507 case SC_CAT_INSERT_ROWS:
2509 // Ignore columns.
2510 aExpected.aStart.SetCol(0);
2511 aExpected.aEnd.SetCol(0);
2512 aActual.aStart.SetCol(0);
2513 aActual.aEnd.SetCol(0);
2515 break;
2516 default:
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();
2543 if (!pCT)
2545 cerr << "Change track instance doesn't exist." << endl;
2546 return false;
2549 sal_uLong nActionMax = pCT->GetActionMax();
2550 if (nActionMax != 13)
2552 cerr << "Unexpected highest action ID value." << endl;
2553 return false;
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);
2560 if (!pAction)
2562 cerr << "No action for action number " << nActId << " found." << endl;
2563 return false;
2566 if (pAction->GetType() != aChecks[i].meType)
2568 cerr << "Unexpected action type for action number " << nActId << "." << endl;
2569 return false;
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;
2580 return false;
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;
2591 return false;
2594 break;
2595 default:
2600 return true;
2603 bool checkRevisionUserAndTime( ScDocument& rDoc, const OUString& rOwnerName )
2605 ScChangeTrack* pCT = rDoc.GetChangeTrack();
2606 if (!pCT)
2608 cerr << "Change track instance doesn't exist." << endl;
2609 return false;
2612 ScChangeAction* pAction = pCT->GetLast();
2613 if (pAction->GetUser() != "Kohei Yoshida")
2615 cerr << "Wrong user name." << endl;
2616 return false;
2619 DateTime aDT = pAction->GetDateTime();
2620 if (aDT.GetYear() != 2014 || aDT.GetMonth() != 7 || aDT.GetDay() != 11)
2622 cerr << "Wrong time stamp." << endl;
2623 return false;
2626 // Insert a new record to make sure the user and date-time are correct.
2627 rDoc.SetString(ScAddress(1,8,0), "New String");
2628 ScCellValue aEmpty;
2629 pCT->AppendContent(ScAddress(1,8,0), aEmpty);
2630 pAction = pCT->GetLast();
2631 if (!pAction)
2633 cerr << "Failed to retrieve last revision." << endl;
2634 return false;
2637 if (rOwnerName != pAction->GetUser())
2639 cerr << "Wrong user name." << endl;
2640 return false;
2643 DateTime aDTNew = pAction->GetDateTime();
2644 if (aDTNew <= aDT)
2646 cerr << "Time stamp of the new revision should be more recent than that of the last revision." << endl;
2647 return false;
2650 return true;
2653 } aTest;
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);
2670 xDocSh->DoClose();
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);
2680 OUString aDesc;
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);
2687 xDocSh2->DoClose();
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();
2694 aTest.check(*pDoc);
2695 CPPUNIT_ASSERT_MESSAGE("Initial check failed (xlsx).", bGood);
2697 xDocSh2 = saveAndReload(xDocSh.get(), FORMAT_XLSX);
2698 xDocSh->DoClose();
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);
2706 xDocSh2->DoClose();
2709 void ScExportTest::testSheetTabColorsXLSX()
2711 struct
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;
2722 return false;
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;
2732 return false;
2736 static const Color aXclColors[] =
2738 0x0000B050, // green
2739 0x00FF0000, // red
2740 0x000070C0, // blue
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;
2749 return false;
2753 return true;
2756 } aTest;
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());
2768 xDocSh->DoClose();
2769 ScDocument& rDoc = xDocSh2->GetDocument();
2770 bool bRes = aTest.checkContent(rDoc);
2771 CPPUNIT_ASSERT_MESSAGE("Failed on the content check after reload.", bRes);
2773 xDocSh2->DoClose();
2776 void ScExportTest::testSharedFormulaExportXLS()
2778 struct
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;
2793 return false;
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;
2801 return false;
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;
2813 return false;
2816 aPos.IncCol();
2817 ScFormulaCell* pFC = rDoc.GetFormulaCell(aPos);
2818 if (!pFC)
2820 cerr << "B" << (i+2) << " should be a formula cell." << endl;
2821 return false;
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;
2829 return false;
2832 fActual = rDoc.GetValue(aPos);
2833 if (fExpected != fActual)
2835 cerr << "Wrong value in B" << (i+2) << ": expected=" << fExpected << ", actual=" << fActual << endl;
2836 return false;
2840 return true;
2843 } aTest;
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);
2856 xDocSh->DoClose();
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);
2865 xDocSh2->DoClose();
2868 void ScExportTest::testSharedFormulaExportXLSX()
2870 struct
2872 bool checkContent( const ScDocument& rDoc )
2874 SCTAB nTabCount = rDoc.GetTableCount();
2875 if (nTabCount != 2)
2877 cerr << "Document should have exactly 2 sheets. " << nTabCount << " found." << endl;
2878 return false;
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;
2888 return false;
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;
2901 return false;
2905 // C2:C7 should show 10,20,....,60.
2906 fExpected = 10.0;
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;
2914 return false;
2918 // D2:D7 should show 1,2,...,6.
2919 fExpected = 1.0;
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;
2927 return false;
2931 return true;
2934 } aTest;
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);
2951 xDocSh->DoClose();
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);
2960 xDocSh2->DoClose();
2963 void ScExportTest::testSharedFormulaStringResultExportXLSX()
2965 struct
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;
2980 return false;
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;
2996 return false;
3001 return true;
3004 } aTest;
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.
3016 rDoc.CalcAll();
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);
3022 xDocSh->DoClose();
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);
3029 xDocSh2->DoClose();
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);
3043 xDocSh->DoClose();
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);
3067 xDocSh->DoClose();
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);
3119 #if !defined _WIN32
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(".."));
3132 #endif
3134 namespace {
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);
3163 xDocSh2->DoClose();
3166 void ScExportTest::testFunctionsExcel2010ODS()
3168 //testFunctionsExcel2010(FORMAT_ODS);
3171 void ScExportTest::testSwappedOutImageExport()
3173 const char* aFilterNames[] = {
3174 "calc8",
3175 "MS Excel 97",
3176 "Calc Office Open XML",
3177 "generic_HTML",
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);
3183 xBatch->commit();
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);
3195 xDocSh->DoClose();
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 );
3219 // Second Image
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 );
3234 xDocSh2->DoClose();
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
3249 m_xCalcComponent =
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();
3260 #if !defined _WIN32
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);
3267 xShell->DoClose();
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");
3274 xDocSh->DoClose();
3276 #endif
3278 void ScExportTest::testLinkedGraphicRT()
3280 // Problem was with linked images
3281 const char* aFilterNames[] = {
3282 "calc8",
3283 "MS Excel 97",
3284 "Calc Office Open XML",
3285 "generic_HTML",
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);
3296 xDocSh->DoClose();
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());
3312 xDocSh2->DoClose();
3316 void ScExportTest::testImageWithSpecialID()
3318 const char* aFilterNames[] = {
3319 "calc8",
3320 "MS Excel 97",
3321 "Calc Office Open XML",
3322 "generic_HTML",
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);
3328 batch->commit();
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);
3339 xDocSh->DoClose();
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 );
3363 // Second Image
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 );
3378 xDocSh2->DoClose();
3382 void ScExportTest::testAbsNamedRangeHTML()
3384 ScDocShellRef xDocSh = loadDoc("numberformat.", FORMAT_HTML);
3385 xDocSh->DoHardRecalc();
3386 ScDocShellRef xDocSh2 = saveAndReload(xDocSh.get(), FORMAT_ODS);
3387 xDocSh->DoClose();
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);
3402 xDocSh->DoClose();
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());
3410 OUString aFormula;
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);
3418 xDocSh2->DoClose();
3421 void ScExportTest::testRelativeNamedExpressionsXLS()
3423 ScDocShellRef xDocSh = loadDoc("tdf113991_relativeNamedRanges.", FORMAT_ODS);
3424 xDocSh->DoHardRecalc();
3425 ScDocShellRef xDocSh2 = saveAndReload(xDocSh.get(), FORMAT_XLS);
3426 xDocSh->DoClose();
3427 xDocSh2->DoHardRecalc();
3428 ScDocument& rDoc = xDocSh2->GetDocument();
3430 // Sheet1:G3
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);
3434 // Sheet2:F6
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);
3438 // Sheet2:H3
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);
3442 // Sheet2:H6
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);
3446 xDocSh2->DoClose();
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);
3462 xDocSh->DoClose();
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);
3495 xDocSh->DoClose();
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);
3515 xDocSh->DoClose();
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);
3554 xDocSh->DoClose();
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");
3566 xDocSh->DoClose();
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");
3580 xDocSh->DoClose();
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());
3597 xDocSh->DoClose();
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");
3618 xDocSh->DoClose();
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);
3665 // Get anchor data
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);
3683 // Insert 2 rows.
3684 rDoc.InsertRow(ScRange( 0, aDataStart.Row() - 1, 0, MAXCOL, aDataStart.Row(), 0));
3686 // Get anchor data
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);
3727 // Get anchor data
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);
3744 // Insert a column.
3745 rDoc1.InsertCol(ScRange( aDataStart.Col(), 0 , 0 , aDataStart.Col(), MAXROW, 0 ));
3747 // Get anchor data
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);
3788 // Get anchor data
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);
3805 xDocSh2->DoClose();
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);
3831 xDocSh->DoClose();
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);
3847 xDocSh->DoClose();
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);
3864 xDocSh->DoClose();
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);
3889 xDocSh->DoClose();
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);
3918 xDocSh->DoClose();
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());
3934 xDocSh->DoClose();
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]\\-# #/#####");
4006 xDocSh->DoClose();
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");
4021 xDocSh->DoClose();
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);
4043 xDocSh->DoClose();
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);
4055 // Check export
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");
4065 // Check import
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);
4084 xDocSh->DoClose();
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;
4100 SCROW nLastRow = 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);
4105 xDocSh->DoClose();
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());
4137 xDocSh->DoClose();
4138 xDocSh2->DoClose();
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");
4174 xDocSh->DoClose();
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());
4215 // export only
4216 std::shared_ptr<utl::TempFile> pTemp = saveAs(xDocSh.get(), FORMAT_XLSX);
4218 ScDocument& rDoc = xDocSh->GetDocument();
4219 CPPUNIT_ASSERT(rDoc.HasPivotTable());
4221 // Two pivot tables
4222 ScDPCollection* pDPColl = rDoc.GetDPCollection();
4223 CPPUNIT_ASSERT(pDPColl);
4224 CPPUNIT_ASSERT_EQUAL(size_t(2), pDPColl->GetCount());
4226 // One cache
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);
4236 xDocSh->DoClose();
4239 CPPUNIT_TEST_SUITE_REGISTRATION(ScExportTest);
4241 CPPUNIT_PLUGIN_IMPLEMENT();
4243 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */