Version 7.5.1.1, tag libreoffice-7.5.1.1
[LibreOffice.git] / sc / qa / unit / subsequent_export_test.cxx
bloba010a9820ea4acc170a465ded48845dc65661173
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 <config_fonts.h>
13 #include "helper/debughelper.hxx"
15 #include "helper/qahelper.hxx"
16 #include "helper/shared_test_impl.hxx"
18 #include <userdat.hxx>
19 #include <docpool.hxx>
20 #include <scitems.hxx>
21 #include <attrib.hxx>
22 #include <stlpool.hxx>
23 #include <editutil.hxx>
24 #include <scopetools.hxx>
25 #include <postit.hxx>
26 #include <tokenstringcontext.hxx>
27 #include <chgtrack.hxx>
28 #include <validat.hxx>
29 #include <scmod.hxx>
31 #include <svx/svdpage.hxx>
32 #include <svx/svdograf.hxx>
33 #include <tabprotection.hxx>
34 #include <editeng/wghtitem.hxx>
35 #include <editeng/postitem.hxx>
36 #include <editeng/eeitem.hxx>
37 #include <editeng/section.hxx>
38 #include <editeng/crossedoutitem.hxx>
39 #include <editeng/borderline.hxx>
40 #include <editeng/escapementitem.hxx>
41 #include <editeng/fontitem.hxx>
42 #include <editeng/fhgtitem.hxx>
43 #include <editeng/udlnitem.hxx>
44 #include <editeng/colritem.hxx>
45 #include <unotools/tempfile.hxx>
46 #include <unotools/useroptions.hxx>
47 #include <tools/datetime.hxx>
49 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
50 #include <com/sun/star/awt/XBitmap.hpp>
51 #include <com/sun/star/graphic/GraphicType.hpp>
53 using namespace ::com::sun::star;
54 using namespace ::com::sun::star::uno;
56 class ScExportTest : public ScModelTestBase
58 protected:
59 virtual void registerNamespaces(xmlXPathContextPtr& pXmlXPathCtx) override;
61 public:
62 ScExportTest()
63 : ScModelTestBase("sc/qa/unit/data")
67 void test();
68 void testDefaultFontHeight();
69 void testTdf139167();
70 void testTdf113271();
71 void testTdf139394();
72 void testExtCondFormatXLSX();
73 void testTdf90104();
74 void testTdf111876();
75 void testPasswordExport();
76 void testTdf134332();
77 void testConditionalFormatExportODS();
78 void testConditionalFormatExportXLSX();
79 void testCondFormatExportCellIs();
80 void testTdf99856_dataValidationTest();
81 void testProtectionKeyODS_UTF16LErtlSHA1();
82 void testProtectionKeyODS_UTF8SHA1();
83 void testProtectionKeyODS_UTF8SHA256ODF12();
84 void testProtectionKeyODS_UTF8SHA256W3C();
85 void testProtectionKeyODS_XL_SHA1();
86 void testColorScaleExportODS();
87 void testColorScaleExportXLSX();
88 void testDataBarExportODS();
89 void testDataBarExportXLSX();
90 void testConditionalFormatRangeListXLSX();
91 void testConditionalFormatContainsTextXLSX();
92 void testConditionalFormatPriorityCheckXLSX();
93 void testConditionalFormatOriginXLSX();
94 void testTdf79998();
95 void testLegacyCellAnchoredRotatedShape();
96 void testMiscRowHeightExport();
97 void testNamedRangeBugfdo62729();
98 void testBuiltinRangesXLSX();
99 void testRichTextExportODS();
100 void testRichTextCellFormatXLSX();
101 void testFormulaRefSheetNameODS();
103 void testCellValuesExportODS();
104 void testCellNoteExportODS();
105 void testCellNoteExportXLS();
106 void testFormatExportODS();
108 void testCommentExportXLSX();
109 void testCommentExportXLSX_2_XLSX();
110 #if HAVE_MORE_FONTS
111 void testCustomColumnWidthExportXLSX();
112 #endif
113 void testXfDefaultValuesXLSX();
114 void testODF13();
115 void testColumnWidthResaveXLSX();
116 #if HAVE_MORE_FONTS
117 void testColumnWidthExportFromODStoXLSX();
118 #endif
119 void testOutlineExportXLSX();
120 void testHiddenEmptyRowsXLSX();
121 void testHiddenEmptyColsODS();
122 void testAllRowsHiddenXLSX();
123 void testLandscapeOrientationXLSX();
125 void testInlineArrayXLS();
126 void testEmbeddedChartODS();
127 void testEmbeddedChartXLS();
128 void testCellAnchoredGroupXLS();
130 void testFormulaReferenceXLS();
131 void testSheetProtectionXLSX();
132 void testSheetProtectionXLSB();
134 void testCellBordersXLS();
135 void testCellBordersXLSX();
136 void testBordersExchangeXLSX();
137 void testTrackChangesSimpleXLSX();
138 void testSheetTabColorsXLSX();
140 void testTdf133487();
142 void testSharedFormulaExportXLS();
143 void testSharedFormulaExportXLSX();
144 void testSharedFormulaStringResultExportXLSX();
146 void testFunctionsExcel2010(const OUString& sFormatType);
147 void testFunctionsExcel2010XLSX();
148 void testFunctionsExcel2010XLS();
149 void testFunctionsExcel2010ODS();
151 void testCeilingFloor(const OUString& sFormatType);
152 void testCeilingFloorXLSX();
153 void testCeilingFloorODSToXLSX();
154 void testCeilingFloorXLS();
155 void testCeilingFloorODS();
157 void testCustomXml();
159 void testRelativePathsODS();
160 void testSheetProtectionODS();
162 void testSwappedOutImageExport();
163 void testLinkedGraphicRT();
164 void testImageWithSpecialID();
166 void testSupBookVirtualPathXLS();
167 void testAbsNamedRangeHTML();
168 void testTdf80149();
169 void testSheetLocalRangeNameXLS();
170 void testRelativeNamedExpressionsXLS();
171 void testSheetTextBoxHyperlinkXLSX();
172 void testFontSizeXLSX();
173 void testSheetCharacterKerningSpaceXLSX();
174 void testSheetCondensedCharacterSpaceXLSX();
175 void testTextUnderlineColorXLSX();
176 void testSheetRunParagraphPropertyXLSX();
177 void testHiddenShapeXLS();
178 void testHiddenShapeXLSX();
179 void testShapeAutofitXLSX();
180 void testHyperlinkXLSX();
181 void testMoveCellAnchoredShapesODS();
182 void testPreserveTextWhitespaceXLSX();
183 void testPreserveTextWhitespace2XLSX();
184 void testTdf113646();
185 void testDateStandardfilterXLSX();
187 CPPUNIT_TEST_SUITE(ScExportTest);
188 CPPUNIT_TEST(test);
189 CPPUNIT_TEST(testDefaultFontHeight);
190 CPPUNIT_TEST(testTdf139167);
191 CPPUNIT_TEST(testTdf113271);
192 CPPUNIT_TEST(testTdf139394);
193 CPPUNIT_TEST(testExtCondFormatXLSX);
194 CPPUNIT_TEST(testTdf90104);
195 CPPUNIT_TEST(testTdf111876);
196 CPPUNIT_TEST(testPasswordExport);
197 CPPUNIT_TEST(testTdf134332);
198 CPPUNIT_TEST(testConditionalFormatExportODS);
199 CPPUNIT_TEST(testCondFormatExportCellIs);
200 CPPUNIT_TEST(testConditionalFormatExportXLSX);
201 CPPUNIT_TEST(testTdf99856_dataValidationTest);
202 CPPUNIT_TEST(testProtectionKeyODS_UTF16LErtlSHA1);
203 CPPUNIT_TEST(testProtectionKeyODS_UTF8SHA1);
204 CPPUNIT_TEST(testProtectionKeyODS_UTF8SHA256ODF12);
205 CPPUNIT_TEST(testProtectionKeyODS_UTF8SHA256W3C);
206 CPPUNIT_TEST(testProtectionKeyODS_XL_SHA1);
207 CPPUNIT_TEST(testColorScaleExportODS);
208 CPPUNIT_TEST(testColorScaleExportXLSX);
209 CPPUNIT_TEST(testDataBarExportODS);
210 CPPUNIT_TEST(testDataBarExportXLSX);
211 CPPUNIT_TEST(testConditionalFormatRangeListXLSX);
212 CPPUNIT_TEST(testConditionalFormatContainsTextXLSX);
213 CPPUNIT_TEST(testConditionalFormatPriorityCheckXLSX);
214 CPPUNIT_TEST(testConditionalFormatOriginXLSX);
215 CPPUNIT_TEST(testTdf79998);
216 CPPUNIT_TEST(testLegacyCellAnchoredRotatedShape);
217 CPPUNIT_TEST(testMiscRowHeightExport);
218 CPPUNIT_TEST(testNamedRangeBugfdo62729);
219 CPPUNIT_TEST(testBuiltinRangesXLSX);
220 CPPUNIT_TEST(testRichTextExportODS);
221 CPPUNIT_TEST(testRichTextCellFormatXLSX);
222 CPPUNIT_TEST(testFormulaRefSheetNameODS);
223 CPPUNIT_TEST(testCellValuesExportODS);
224 CPPUNIT_TEST(testCellNoteExportODS);
225 CPPUNIT_TEST(testCellNoteExportXLS);
226 CPPUNIT_TEST(testFormatExportODS);
227 CPPUNIT_TEST(testCommentExportXLSX);
228 CPPUNIT_TEST(testCommentExportXLSX_2_XLSX);
229 #if HAVE_MORE_FONTS
230 CPPUNIT_TEST(testCustomColumnWidthExportXLSX);
231 #endif
232 CPPUNIT_TEST(testXfDefaultValuesXLSX);
233 CPPUNIT_TEST(testODF13);
234 CPPUNIT_TEST(testColumnWidthResaveXLSX);
235 #if HAVE_MORE_FONTS
236 CPPUNIT_TEST(testColumnWidthExportFromODStoXLSX);
237 #endif
238 CPPUNIT_TEST(testOutlineExportXLSX);
239 CPPUNIT_TEST(testHiddenEmptyRowsXLSX);
240 CPPUNIT_TEST(testHiddenEmptyColsODS);
241 CPPUNIT_TEST(testAllRowsHiddenXLSX);
242 CPPUNIT_TEST(testLandscapeOrientationXLSX);
243 CPPUNIT_TEST(testInlineArrayXLS);
244 CPPUNIT_TEST(testEmbeddedChartODS);
245 CPPUNIT_TEST(testEmbeddedChartXLS);
246 CPPUNIT_TEST(testCellAnchoredGroupXLS);
248 CPPUNIT_TEST(testFormulaReferenceXLS);
249 CPPUNIT_TEST(testSheetProtectionXLSX);
250 CPPUNIT_TEST(testSheetProtectionXLSB);
251 CPPUNIT_TEST(testCellBordersXLS);
252 CPPUNIT_TEST(testCellBordersXLSX);
253 CPPUNIT_TEST(testBordersExchangeXLSX);
254 CPPUNIT_TEST(testTrackChangesSimpleXLSX);
255 CPPUNIT_TEST(testSheetTabColorsXLSX);
256 CPPUNIT_TEST(testTdf133487);
257 CPPUNIT_TEST(testSharedFormulaExportXLS);
258 CPPUNIT_TEST(testSharedFormulaExportXLSX);
259 CPPUNIT_TEST(testSharedFormulaStringResultExportXLSX);
260 CPPUNIT_TEST(testFunctionsExcel2010XLSX);
261 CPPUNIT_TEST(testFunctionsExcel2010XLS);
262 CPPUNIT_TEST(testFunctionsExcel2010ODS);
263 CPPUNIT_TEST(testCeilingFloorXLSX);
264 CPPUNIT_TEST(testCeilingFloorODSToXLSX);
265 CPPUNIT_TEST(testCeilingFloorXLS);
266 CPPUNIT_TEST(testCeilingFloorODS);
267 CPPUNIT_TEST(testCustomXml);
268 CPPUNIT_TEST(testRelativePathsODS);
269 CPPUNIT_TEST(testSheetProtectionODS);
270 CPPUNIT_TEST(testSupBookVirtualPathXLS);
271 CPPUNIT_TEST(testSwappedOutImageExport);
272 CPPUNIT_TEST(testLinkedGraphicRT);
273 CPPUNIT_TEST(testImageWithSpecialID);
274 CPPUNIT_TEST(testPreserveTextWhitespaceXLSX);
275 CPPUNIT_TEST(testPreserveTextWhitespace2XLSX);
276 CPPUNIT_TEST(testAbsNamedRangeHTML);
277 CPPUNIT_TEST(testTdf80149);
278 CPPUNIT_TEST(testSheetLocalRangeNameXLS);
279 CPPUNIT_TEST(testRelativeNamedExpressionsXLS);
280 CPPUNIT_TEST(testSheetTextBoxHyperlinkXLSX);
281 CPPUNIT_TEST(testFontSizeXLSX);
282 CPPUNIT_TEST(testSheetCharacterKerningSpaceXLSX);
283 CPPUNIT_TEST(testSheetCondensedCharacterSpaceXLSX);
284 CPPUNIT_TEST(testTextUnderlineColorXLSX);
285 CPPUNIT_TEST(testSheetRunParagraphPropertyXLSX);
286 CPPUNIT_TEST(testHiddenShapeXLS);
287 CPPUNIT_TEST(testHiddenShapeXLSX);
288 CPPUNIT_TEST(testShapeAutofitXLSX);
289 CPPUNIT_TEST(testHyperlinkXLSX);
290 CPPUNIT_TEST(testMoveCellAnchoredShapesODS);
291 CPPUNIT_TEST(testTdf113646);
292 CPPUNIT_TEST(testDateStandardfilterXLSX);
293 CPPUNIT_TEST_SUITE_END();
295 private:
296 void testExcelCellBorders(const OUString& sFormatType);
299 void ScExportTest::registerNamespaces(xmlXPathContextPtr& pXmlXPathCtx)
301 XmlTestTools::registerOOXMLNamespaces(pXmlXPathCtx);
302 XmlTestTools::registerODFNamespaces(pXmlXPathCtx);
305 void ScExportTest::test()
307 createScDoc();
309 ScDocument* pDoc = getScDoc();
311 pDoc->SetValue(0, 0, 0, 1.0);
313 saveAndReload("calc8");
315 pDoc = getScDoc();
316 double aVal = pDoc->GetValue(0, 0, 0);
317 ASSERT_DOUBLES_EQUAL(aVal, 1.0);
320 void ScExportTest::testDefaultFontHeight()
322 createScDoc();
324 ScDocument* pDoc = getScDoc();
325 ScDocumentPool* pPool = pDoc->GetPool();
326 pPool->SetPoolDefaultItem(SvxFontHeightItem(400, 100, ATTR_FONT_HEIGHT));
327 pPool->SetPoolDefaultItem(SvxFontHeightItem(400, 100, ATTR_CJK_FONT_HEIGHT));
328 pPool->SetPoolDefaultItem(SvxFontHeightItem(400, 100, ATTR_CTL_FONT_HEIGHT));
330 saveAndReload("calc8");
332 pDoc = getScDoc();
333 pPool = pDoc->GetPool();
334 const SvxFontHeightItem& rItem = pPool->GetDefaultItem(ATTR_FONT_HEIGHT);
335 CPPUNIT_ASSERT_EQUAL(sal_uInt32(400), rItem.GetHeight());
336 const SvxFontHeightItem& rCJKItem = pPool->GetDefaultItem(ATTR_CJK_FONT_HEIGHT);
337 CPPUNIT_ASSERT_EQUAL(sal_uInt32(400), rCJKItem.GetHeight());
338 const SvxFontHeightItem& rCTLItem = pPool->GetDefaultItem(ATTR_CTL_FONT_HEIGHT);
339 CPPUNIT_ASSERT_EQUAL(sal_uInt32(400), rCTLItem.GetHeight());
342 void ScExportTest::testTdf139167()
344 createScDoc("xlsx/tdf139167.xlsx");
346 save("Calc Office Open XML");
347 xmlDocUniquePtr pDoc = parseExport("xl/styles.xml");
348 CPPUNIT_ASSERT(pDoc);
350 assertXPath(pDoc, "/x:styleSheet/x:cellStyles", "count", "6");
351 assertXPath(pDoc, "/x:styleSheet/x:dxfs/x:dxf/x:fill/x:patternFill/x:bgColor", "rgb",
352 "FFFFFF00");
355 void ScExportTest::testTdf113271()
357 createScDoc("xlsx/tdf113271.xlsx");
359 save("Calc Office Open XML");
360 xmlDocUniquePtr pDoc = parseExport("xl/styles.xml");
361 CPPUNIT_ASSERT(pDoc);
363 assertXPath(pDoc, "/x:styleSheet/x:fonts", "count", "6");
365 // Without the fix in place, this test would have failed with
366 // - Expected: FF000000
367 // - Actual : FFFFFFFF
368 assertXPath(pDoc, "/x:styleSheet/x:fonts/x:font[1]/x:color", "rgb", "FF000000");
369 assertXPath(pDoc, "/x:styleSheet/x:fonts/x:font[1]/x:name", "val", "Calibri");
372 void ScExportTest::testTdf139394()
374 createScDoc("xlsx/tdf139394.xlsx");
376 save("Calc Office Open XML");
377 xmlDocUniquePtr pDoc = parseExport("xl/worksheets/sheet1.xml");
378 CPPUNIT_ASSERT(pDoc);
380 assertXPathContent(
381 pDoc,
382 "/x:worksheet/x:extLst/x:ext/x14:conditionalFormattings/x14:conditionalFormatting[1]/"
383 "x14:cfRule/xm:f",
384 "LEFT(A1,LEN(\"+\"))=\"+\"");
385 assertXPathContent(
386 pDoc,
387 "/x:worksheet/x:extLst/x:ext/x14:conditionalFormattings/x14:conditionalFormatting[2]/"
388 "x14:cfRule/xm:f",
389 "RIGHT(A2,LEN(\"-\"))=\"-\"");
390 assertXPathContent(
391 pDoc,
392 "/x:worksheet/x:extLst/x:ext/x14:conditionalFormattings/x14:conditionalFormatting[3]/"
393 "x14:cfRule/xm:f",
394 "LEFT(A3,LEN($B$3))=$B$3");
397 void ScExportTest::testExtCondFormatXLSX()
399 createScDoc("xlsx/tdf139021.xlsx");
401 save("Calc Office Open XML");
402 xmlDocUniquePtr pDoc = parseExport("xl/worksheets/sheet1.xml");
403 CPPUNIT_ASSERT(pDoc);
405 assertXPath(
406 pDoc,
407 "/x:worksheet/x:extLst/x:ext/x14:conditionalFormattings/x14:conditionalFormatting[1]/"
408 "x14:cfRule",
409 "type", "containsText");
410 assertXPathContent(
411 pDoc,
412 "/x:worksheet/x:extLst/x:ext/x14:conditionalFormattings/x14:conditionalFormatting[1]/"
413 "x14:cfRule/xm:f[1]",
414 "NOT(ISERROR(SEARCH($B$1,A1)))");
415 assertXPathContent(
416 pDoc,
417 "/x:worksheet/x:extLst/x:ext/x14:conditionalFormattings/x14:conditionalFormatting[1]/"
418 "x14:cfRule/xm:f[2]",
419 "$B$1");
420 assertXPath(
421 pDoc,
422 "/x:worksheet/x:extLst/x:ext/x14:conditionalFormattings/x14:conditionalFormatting[2]/"
423 "x14:cfRule",
424 "type", "notContainsText");
425 assertXPathContent(
426 pDoc,
427 "/x:worksheet/x:extLst/x:ext/x14:conditionalFormattings/x14:conditionalFormatting[2]/"
428 "x14:cfRule/xm:f[1]",
429 "ISERROR(SEARCH($B$2,A2))");
430 assertXPathContent(
431 pDoc,
432 "/x:worksheet/x:extLst/x:ext/x14:conditionalFormattings/x14:conditionalFormatting[2]/"
433 "x14:cfRule/xm:f[2]",
434 "$B$2");
437 void ScExportTest::testTdf90104()
439 createScDoc("xlsx/tdf90104.xlsx");
441 save("Calc Office Open XML");
443 xmlDocUniquePtr pDoc = parseExport("xl/worksheets/sheet1.xml");
444 CPPUNIT_ASSERT(pDoc);
446 assertXPathContent(pDoc,
447 "/x:worksheet/x:dataValidations/x:dataValidation/mc:AlternateContent"
448 "/mc:Choice/x12ac:list",
449 "1,\"2,3\",4,\"5,6\"");
450 assertXPathContent(pDoc,
451 "/x:worksheet/x:dataValidations/x:dataValidation/mc:AlternateContent"
452 "/mc:Fallback/x:formula1",
453 "\"1,2,3,4,5,6\"");
456 void ScExportTest::testTdf111876()
458 // Document with relative path hyperlink
460 createScDoc("xlsx/tdf111876.xlsx");
462 save("Calc Office Open XML");
463 xmlDocUniquePtr pDoc = parseExport("xl/worksheets/_rels/sheet1.xml.rels");
464 CPPUNIT_ASSERT(pDoc);
465 OUString sTarget = getXPath(pDoc, "/rels:Relationships/rels:Relationship", "Target");
467 // Document is saved to the temporary directory, relative path should be different than original one
468 CPPUNIT_ASSERT(sTarget != "../xls/bug-fixes.xls");
471 void ScExportTest::testPasswordExport()
473 std::vector<OUString> aFilterNames{ "calc8", "MS Excel 97", "Calc Office Open XML" };
475 for (size_t i = 0; i < aFilterNames.size(); ++i)
477 createScDoc();
479 ScDocument* pDoc = getScDoc();
481 pDoc->SetValue(0, 0, 0, 1.0);
483 saveAndReload(aFilterNames[i], /*pPassword*/ "test");
485 pDoc = getScDoc();
486 double aVal = pDoc->GetValue(0, 0, 0);
487 ASSERT_DOUBLES_EQUAL(aVal, 1.0);
491 void ScExportTest::testTdf134332()
493 createScDoc("ods/tdf134332.ods");
495 ScDocument* pDoc = getScDoc();
497 ASSERT_DOUBLES_EQUAL(190.0, pDoc->GetValue(ScAddress(0, 0, 0)));
499 ASSERT_DOUBLES_EQUAL(238.0, pDoc->GetValue(ScAddress(0, 10144, 0)));
501 saveAndReload("calc8", /*pPassword*/ "test");
503 // Without the fixes in place, it would have failed here
504 pDoc = getScDoc();
505 ASSERT_DOUBLES_EQUAL(190.0, pDoc->GetValue(ScAddress(0, 0, 0)));
507 ASSERT_DOUBLES_EQUAL(238.0, pDoc->GetValue(ScAddress(0, 10144, 0)));
510 void ScExportTest::testConditionalFormatExportODS()
512 createScDoc("ods/new_cond_format_test_export.ods");
514 saveAndReload("calc8");
515 ScDocument* pDoc = getScDoc();
516 OUString aCSVPath = createFilePath(u"contentCSV/new_cond_format_test_export.csv");
517 testCondFile(aCSVPath, &*pDoc, 0);
520 void ScExportTest::testCondFormatExportCellIs()
522 createScDoc("xlsx/condFormat_cellis.xlsx");
523 saveAndReload("Calc Office Open XML");
525 ScDocument* pDoc = getScDoc();
526 CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetCondFormList(0)->size());
528 ScConditionalFormat* pFormat = pDoc->GetCondFormat(0, 0, 0);
529 CPPUNIT_ASSERT(pFormat);
531 const ScFormatEntry* pEntry = pFormat->GetEntry(0);
532 CPPUNIT_ASSERT(pEntry);
533 CPPUNIT_ASSERT_EQUAL(ScFormatEntry::Type::ExtCondition, pEntry->GetType());
535 const ScCondFormatEntry* pCondition = static_cast<const ScCondFormatEntry*>(pEntry);
536 CPPUNIT_ASSERT_EQUAL(ScConditionMode::Equal, pCondition->GetOperation());
538 OUString aStr = pCondition->GetExpression(ScAddress(0, 0, 0), 0);
539 CPPUNIT_ASSERT_EQUAL(OUString("$Sheet2.$A$2"), aStr);
541 pEntry = pFormat->GetEntry(1);
542 CPPUNIT_ASSERT(pEntry);
543 CPPUNIT_ASSERT_EQUAL(ScFormatEntry::Type::ExtCondition, pEntry->GetType());
545 pCondition = static_cast<const ScCondFormatEntry*>(pEntry);
546 CPPUNIT_ASSERT_EQUAL(ScConditionMode::Equal, pCondition->GetOperation());
548 aStr = pCondition->GetExpression(ScAddress(0, 0, 0), 0);
549 CPPUNIT_ASSERT_EQUAL(OUString("$Sheet2.$A$1"), aStr);
552 void ScExportTest::testConditionalFormatExportXLSX()
554 createScDoc("xlsx/new_cond_format_test_export.xlsx");
556 saveAndReload("Calc Office Open XML");
557 ScDocument* pDoc = getScDoc();
559 OUString aCSVPath = createFilePath(u"contentCSV/new_cond_format_test_export.csv");
560 testCondFile(aCSVPath, &*pDoc, 0);
563 OUString aCSVPath = createFilePath(u"contentCSV/new_cond_format_test_sheet2.csv");
564 testCondFile(aCSVPath, &*pDoc, 1);
568 void ScExportTest::testTdf99856_dataValidationTest()
570 createScDoc("ods/tdf99856_dataValidationTest.ods");
572 saveAndReload("Calc Office Open XML");
574 ScDocument* pDoc = getScDoc();
575 const ScValidationData* pData = pDoc->GetValidationEntry(2);
576 CPPUNIT_ASSERT(pData);
578 // Excel can't open corrupt file if the list is longer than 255 characters
579 std::vector<ScTypedStrData> aList;
580 pData->FillSelectionList(aList, ScAddress(0, 1, 1));
581 CPPUNIT_ASSERT_EQUAL(size_t(18), aList.size());
582 CPPUNIT_ASSERT_EQUAL(OUString("18 Missis"), aList[17].GetString());
585 void ScExportTest::testProtectionKeyODS_UTF16LErtlSHA1()
587 OUString const password("1012345678901234567890123456789012345678901234567890");
589 createScDoc("fods/protection-key1.fods");
591 ScDocument* pDoc = getScDoc();
592 ScDocProtection* const pDocProt(pDoc->GetDocProtection());
593 CPPUNIT_ASSERT(pDocProt->verifyPassword(password));
594 const ScTableProtection* const pTabProt(pDoc->GetTabProtection(0));
595 CPPUNIT_ASSERT(pTabProt->verifyPassword(password));
597 // we can't assume that the user entered the password; check that we
598 // round-trip the password as-is
599 save("calc8");
600 xmlDocUniquePtr pXmlDoc = parseExport("content.xml");
601 assertXPath(pXmlDoc,
602 "//office:spreadsheet[@table:structure-protected='true' and "
603 "@table:protection-key='vbnhxyBKtPHCA1wB21zG1Oha8ZA=' and "
604 "@table:protection-key-digest-algorithm='http://www.w3.org/2000/09/xmldsig#sha1']");
605 assertXPath(pXmlDoc,
606 "//table:table[@table:protected='true' and "
607 "@table:protection-key='vbnhxyBKtPHCA1wB21zG1Oha8ZA=' and "
608 "@table:protection-key-digest-algorithm='http://www.w3.org/2000/09/xmldsig#sha1']");
611 void ScExportTest::testProtectionKeyODS_UTF8SHA1()
613 OUString const password("1012345678901234567890123456789012345678901234567890");
615 createScDoc("fods/protection-key2.fods");
617 ScDocument* pDoc = getScDoc();
618 ScDocProtection* const pDocProt(pDoc->GetDocProtection());
619 CPPUNIT_ASSERT(pDocProt->verifyPassword(password));
620 const ScTableProtection* const pTabProt(pDoc->GetTabProtection(0));
621 CPPUNIT_ASSERT(pTabProt->verifyPassword(password));
623 // we can't assume that the user entered the password; check that we
624 // round-trip the password as-is
625 save("calc8");
626 xmlDocUniquePtr pXmlDoc = parseExport("content.xml");
627 assertXPath(pXmlDoc,
628 "//office:spreadsheet[@table:structure-protected='true' and "
629 "@table:protection-key='nLHas0RIwepGDaH4c2hpyIUvIS8=' and "
630 "@table:protection-key-digest-algorithm='http://www.w3.org/2000/09/xmldsig#sha1']");
631 assertXPath(pXmlDoc,
632 "//table:table[@table:protected='true' and "
633 "@table:protection-key='nLHas0RIwepGDaH4c2hpyIUvIS8=' and "
634 "@table:protection-key-digest-algorithm='http://www.w3.org/2000/09/xmldsig#sha1']");
637 void ScExportTest::testProtectionKeyODS_UTF8SHA256ODF12()
639 OUString const password("1012345678901234567890123456789012345678901234567890");
641 createScDoc("fods/protection-key3.fods");
643 ScDocument* pDoc = getScDoc();
644 ScDocProtection* const pDocProt(pDoc->GetDocProtection());
645 CPPUNIT_ASSERT(pDocProt->verifyPassword(password));
646 const ScTableProtection* const pTabProt(pDoc->GetTabProtection(0));
647 CPPUNIT_ASSERT(pTabProt->verifyPassword(password));
649 // we can't assume that the user entered the password; check that we
650 // round-trip the password as-is
651 save("calc8");
652 xmlDocUniquePtr pXmlDoc = parseExport("content.xml");
653 assertXPath(
654 pXmlDoc,
655 "//office:spreadsheet[@table:structure-protected='true' and "
656 "@table:protection-key='1tnJohagR2T0yF/v69hLPuumSTsj32CumW97nkKGuSQ=' and "
657 "@table:protection-key-digest-algorithm='http://www.w3.org/2000/09/xmldsig#sha256']");
658 assertXPath(
659 pXmlDoc,
660 "//table:table[@table:protected='true' and "
661 "@table:protection-key='1tnJohagR2T0yF/v69hLPuumSTsj32CumW97nkKGuSQ=' and "
662 "@table:protection-key-digest-algorithm='http://www.w3.org/2000/09/xmldsig#sha256']");
665 void ScExportTest::testProtectionKeyODS_UTF8SHA256W3C()
667 OUString const password("1012345678901234567890123456789012345678901234567890");
669 createScDoc("fods/protection-key4.fods");
671 ScDocument* pDoc = getScDoc();
672 ScDocProtection* const pDocProt(pDoc->GetDocProtection());
673 CPPUNIT_ASSERT(pDocProt->verifyPassword(password));
674 const ScTableProtection* const pTabProt(pDoc->GetTabProtection(0));
675 CPPUNIT_ASSERT(pTabProt->verifyPassword(password));
677 // we can't assume that the user entered the password; check that we
678 // round-trip the password as-is
679 save("calc8");
680 xmlDocUniquePtr pXmlDoc = parseExport("content.xml");
681 assertXPath(
682 pXmlDoc,
683 "//office:spreadsheet[@table:structure-protected='true' and "
684 "@table:protection-key='1tnJohagR2T0yF/v69hLPuumSTsj32CumW97nkKGuSQ=' and "
685 "@table:protection-key-digest-algorithm='http://www.w3.org/2000/09/xmldsig#sha256']");
686 assertXPath(
687 pXmlDoc,
688 "//table:table[@table:protected='true' and "
689 "@table:protection-key='1tnJohagR2T0yF/v69hLPuumSTsj32CumW97nkKGuSQ=' and "
690 "@table:protection-key-digest-algorithm='http://www.w3.org/2000/09/xmldsig#sha256']");
693 void ScExportTest::testProtectionKeyODS_XL_SHA1()
695 OUString const password("1012345678901234567890123456789012345678901234567890");
697 createScDoc("fods/protection-key5.fods");
699 ScDocument* pDoc = getScDoc();
700 ScDocProtection* const pDocProt(pDoc->GetDocProtection());
701 CPPUNIT_ASSERT(pDocProt->verifyPassword(password));
702 const ScTableProtection* const pTabProt(pDoc->GetTabProtection(0));
703 CPPUNIT_ASSERT(pTabProt->verifyPassword(password));
705 // we can't assume that the user entered the password; check that we
706 // round-trip the password as-is
707 save("calc8");
708 xmlDocUniquePtr pXmlDoc = parseExport("content.xml");
709 assertXPath(
710 pXmlDoc,
711 "//office:spreadsheet[@table:structure-protected='true' and "
712 "@table:protection-key='OX3WkEe79fv1PE+FUmfOLdwVoqI=' and "
713 "@table:protection-key-digest-algorithm='http://docs.oasis-open.org/office/ns/table/"
714 "legacy-hash-excel' and "
715 "@loext:protection-key-digest-algorithm-2='http://www.w3.org/2000/09/xmldsig#sha1']");
716 assertXPath(
717 pXmlDoc,
718 "//table:table[@table:protected='true' and "
719 "@table:protection-key='OX3WkEe79fv1PE+FUmfOLdwVoqI=' and "
720 "@table:protection-key-digest-algorithm='http://docs.oasis-open.org/office/ns/table/"
721 "legacy-hash-excel' and "
722 "@loext:protection-key-digest-algorithm-2='http://www.w3.org/2000/09/xmldsig#sha1']");
725 void ScExportTest::testColorScaleExportODS()
727 createScDoc("ods/colorscale.ods");
729 saveAndReload("calc8");
731 ScDocument* pDoc = getScDoc();
733 testColorScale2Entry_Impl(*pDoc);
734 testColorScale3Entry_Impl(*pDoc);
737 void ScExportTest::testColorScaleExportXLSX()
739 createScDoc("xlsx/colorscale.xlsx");
741 saveAndReload("Calc Office Open XML");
743 ScDocument* pDoc = getScDoc();
745 testColorScale2Entry_Impl(*pDoc);
746 testColorScale3Entry_Impl(*pDoc);
749 void ScExportTest::testDataBarExportODS()
751 createScDoc("ods/databar.ods");
753 saveAndReload("calc8");
755 ScDocument* pDoc = getScDoc();
757 testDataBar_Impl(*pDoc);
760 void ScExportTest::testFormatExportODS()
762 createScDoc("ods/formats.ods");
764 saveAndReload("calc8");
766 ScDocument* pDoc = getScDoc();
768 testFormats(pDoc, u"calc8");
771 void ScExportTest::testCommentExportXLSX()
773 //tdf#104729 FILESAVE OpenOffice do not save author of the comment during export to .xlsx
774 createScDoc("ods/comment.ods");
776 save("Calc Office Open XML");
777 xmlDocUniquePtr pComments = parseExport("xl/comments1.xml");
778 CPPUNIT_ASSERT(pComments);
780 assertXPathContent(pComments, "/x:comments/x:authors/x:author[1]", "BAKO");
781 assertXPath(pComments, "/x:comments/x:authors/x:author", 1);
783 assertXPathContent(pComments, "/x:comments/x:commentList/x:comment/x:text/x:r/x:t",
784 "Komentarz");
786 xmlDocUniquePtr pVmlDrawing = parseExport("xl/drawings/vmlDrawing1.vml");
787 CPPUNIT_ASSERT(pVmlDrawing);
789 //assertXPath(pVmlDrawing, "/xml/v:shapetype", "coordsize", "21600,21600");
790 assertXPath(pVmlDrawing, "/xml/v:shapetype", "spt", "202");
791 assertXPath(pVmlDrawing, "/xml/v:shapetype/v:stroke", "joinstyle", "miter");
792 const OUString sShapeTypeId = "#" + getXPath(pVmlDrawing, "/xml/v:shapetype", "id");
794 assertXPath(pVmlDrawing, "/xml/v:shape", "type", sShapeTypeId);
795 assertXPath(pVmlDrawing, "/xml/v:shape/v:shadow", "color", "black");
796 assertXPath(pVmlDrawing, "/xml/v:shape/v:shadow", "obscured", "t");
798 //tdf#117274 fix MSO interoperability with the secret VML shape type id
799 assertXPath(pVmlDrawing, "/xml/v:shapetype", "id", "_x0000_t202");
800 assertXPath(pVmlDrawing, "/xml/v:shape", "type", "#_x0000_t202");
803 void ScExportTest::testCommentExportXLSX_2_XLSX()
805 //tdf#117287 FILESAVE XLSX: Comments always disappear after opening the exported XLSX file with Excel
806 createScDoc("xlsx/tdf117287_comment.xlsx");
808 ScDocument* pDoc = getScDoc();
809 ScAddress aPosC9(2, 8, 0);
810 ScPostIt* pNote = pDoc->GetNote(aPosC9);
812 CPPUNIT_ASSERT(pNote);
813 CPPUNIT_ASSERT(!pNote->IsCaptionShown());
815 pNote->ShowCaption(aPosC9, true);
817 save("Calc Office Open XML");
818 xmlDocUniquePtr pComments = parseExport("xl/comments1.xml");
819 CPPUNIT_ASSERT(pComments);
821 assertXPathContent(pComments, "/x:comments/x:commentList/x:comment/x:text/x:r/x:t",
822 "visible comment");
824 xmlDocUniquePtr pVmlDrawing = parseExport("xl/drawings/vmlDrawing1.vml");
825 CPPUNIT_ASSERT(pVmlDrawing);
827 assertXPath(pVmlDrawing, "/xml/v:shape/x:ClientData/x:Visible", 0);
830 #if HAVE_MORE_FONTS
831 void ScExportTest::testCustomColumnWidthExportXLSX()
833 //tdf#100946 FILESAVE Excel on macOS ignored column widths in XLSX last saved by LO
834 createScDoc("ods/custom_column_width.ods");
836 save("Calc Office Open XML");
837 xmlDocUniquePtr pSheet = parseExport("xl/worksheets/sheet1.xml");
838 CPPUNIT_ASSERT(pSheet);
840 // tdf#124741: check that we export default width, otherwise the skipped columns would have
841 // wrong width. Previously defaultColWidth attribute was missing
842 double nDefWidth
843 = getXPath(pSheet, "/x:worksheet/x:sheetFormatPr", "defaultColWidth").toDouble();
844 CPPUNIT_ASSERT_DOUBLES_EQUAL(11.53515625, nDefWidth, 0.01);
846 // First column, has everything default (width in Calc: 1280), skipped
848 // Second column, has custom width (width in Calc: 1225)
849 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[1]", "hidden", "false");
850 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[1]", "outlineLevel", "0");
851 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[1]", "customWidth", "true");
852 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[1]", "collapsed", "false");
853 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[1]", "min", "2");
854 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[1]", "max", "2");
856 // Third column, has everything default (width in Calc: 1280), skipped
858 // Fourth column has custom width. Columns from 4 to 7 are hidden
859 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[2]", "hidden", "true");
860 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[2]", "outlineLevel", "0");
861 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[2]", "customWidth", "true");
862 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[2]", "collapsed", "false");
863 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[2]", "min", "4");
864 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[2]", "max", "4");
866 // 5th column has custom width. Columns from 4 to 7 are hidden
867 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[3]", "hidden", "true");
868 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[3]", "outlineLevel", "0");
869 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[3]", "customWidth", "true");
870 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[3]", "collapsed", "false");
871 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[3]", "min", "5");
872 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[3]", "max", "5");
874 // 6th and 7th columns have default width and they are hidden
875 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[4]", "hidden", "true");
876 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[4]", "outlineLevel", "0");
877 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[4]", "customWidth", "false");
878 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[4]", "collapsed", "false");
879 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[4]", "min", "6");
880 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[4]", "max", "7");
882 // 8th column has everything default - skipped
884 // 9th column has custom width
885 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[5]", "hidden", "false");
886 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[5]", "outlineLevel", "0");
887 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[5]", "customWidth", "true");
888 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[5]", "collapsed", "false");
889 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[5]", "min", "9");
890 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[5]", "max", "9");
892 // We expected that exactly 5 unique Nodes will be produced
893 assertXPath(pSheet, "/x:worksheet/x:cols/x:col", 5);
895 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[1]", "hidden", "false");
896 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[1]", "outlineLevel", "0");
897 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[1]", "collapsed", "false");
898 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[1]", "customFormat", "false");
899 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[1]", "customHeight", "false");
901 #endif
903 void ScExportTest::testXfDefaultValuesXLSX()
905 //tdf#70565 FORMATTING: User Defined Custom Formatting is not applied during importing XLSX documents
906 createScDoc("xlsx/xf_default_values.xlsx");
908 save("Calc Office Open XML");
909 xmlDocUniquePtr pSheet = parseExport("xl/styles.xml");
910 CPPUNIT_ASSERT(pSheet);
912 // cellStyleXfs don't need xfId, so we need to make sure it is not saved
913 assertXPathNoAttribute(pSheet, "/x:styleSheet/x:cellStyleXfs/x:xf[1]", "xfId");
915 // Because numFmtId fontId fillId borderId xfId are not existing during import
916 // it should be created during export, with values set to "0"
917 assertXPath(pSheet, "/x:styleSheet/x:cellXfs/x:xf[1]", "xfId", "0");
918 assertXPath(pSheet, "/x:styleSheet/x:cellXfs/x:xf[2]", "xfId", "0");
919 assertXPath(pSheet, "/x:styleSheet/x:cellXfs/x:xf[3]", "xfId", "0");
920 assertXPath(pSheet, "/x:styleSheet/x:cellXfs/x:xf[4]", "xfId", "0");
922 // We expected that exactly 15 cellXfs:xf Nodes will be produced
923 assertXPath(pSheet, "/x:styleSheet/x:cellXfs/x:xf", 14);
926 static auto verifySpreadsheet13(char const* const pTestName, ScDocument& rDoc) -> void
928 // OFFICE-2173 table:tab-color
929 CPPUNIT_ASSERT_EQUAL_MESSAGE(pTestName, Color(0xff3838), rDoc.GetTabBgColor(0));
930 // OFFICE-3857 table:scale-to-X/table:scale-to-Y
931 OUString styleName = rDoc.GetPageStyle(0);
932 ScStyleSheetPool* pStylePool = rDoc.GetStyleSheetPool();
933 SfxStyleSheetBase* pStyleSheet = pStylePool->Find(styleName, SfxStyleFamily::Page);
934 CPPUNIT_ASSERT_MESSAGE(pTestName, pStyleSheet);
936 SfxItemSet const& rSet = pStyleSheet->GetItemSet();
937 ScPageScaleToItem const& rItem(rSet.Get(ATTR_PAGE_SCALETO));
938 CPPUNIT_ASSERT_EQUAL_MESSAGE(pTestName, sal_uInt16(2), rItem.GetWidth());
939 CPPUNIT_ASSERT_EQUAL_MESSAGE(pTestName, sal_uInt16(3), rItem.GetHeight());
942 void ScExportTest::testODF13()
944 // import
945 createScDoc("ods/spreadsheet13e.ods");
946 ScDocument* pDoc = getScDoc();
948 // check model
949 verifySpreadsheet13("import", *pDoc);
951 Resetter _([]() {
952 std::shared_ptr<comphelper::ConfigurationChanges> pBatch(
953 comphelper::ConfigurationChanges::create());
954 officecfg::Office::Common::Save::ODF::DefaultVersion::set(3, pBatch);
955 return pBatch->commit();
959 // export ODF 1.3
960 std::shared_ptr<comphelper::ConfigurationChanges> pBatch(
961 comphelper::ConfigurationChanges::create());
962 officecfg::Office::Common::Save::ODF::DefaultVersion::set(10, pBatch);
963 pBatch->commit();
965 // FIXME: Error: unexpected attribute "loext:scale-to-X"
966 skipValidation();
968 saveAndReload("calc8");
969 pDoc = getScDoc();
971 // check XML
972 xmlDocUniquePtr pContentXml = parseExport("content.xml");
973 assertXPath(pContentXml, "/office:document-content/office:automatic-styles/style:style/"
974 "style:table-properties[@table:tab-color='#ff3838']");
975 xmlDocUniquePtr pStylesXml = parseExport("styles.xml");
976 assertXPath(pStylesXml, "/office:document-styles/office:automatic-styles/style:page-layout/"
977 "style:page-layout-properties[@style:scale-to-X='2']");
978 assertXPath(pStylesXml, "/office:document-styles/office:automatic-styles/style:page-layout/"
979 "style:page-layout-properties[@style:scale-to-Y='3']");
981 // check model
982 verifySpreadsheet13("1.3 reload", *pDoc);
985 // export ODF 1.2 Extended
986 std::shared_ptr<comphelper::ConfigurationChanges> pBatch(
987 comphelper::ConfigurationChanges::create());
988 officecfg::Office::Common::Save::ODF::DefaultVersion::set(9, pBatch);
989 pBatch->commit();
991 saveAndReload("calc8");
992 pDoc = getScDoc();
994 // check XML
995 xmlDocUniquePtr pContentXml = parseExport("content.xml");
996 assertXPath(pContentXml, "/office:document-content/office:automatic-styles/style:style/"
997 "style:table-properties[@tableooo:tab-color='#ff3838']");
998 xmlDocUniquePtr pStylesXml = parseExport("styles.xml");
999 assertXPath(pStylesXml, "/office:document-styles/office:automatic-styles/style:page-layout/"
1000 "style:page-layout-properties[@loext:scale-to-X='2']");
1001 assertXPath(pStylesXml, "/office:document-styles/office:automatic-styles/style:page-layout/"
1002 "style:page-layout-properties[@loext:scale-to-Y='3']");
1004 // check model
1005 verifySpreadsheet13("1.2 Extended reload", *pDoc);
1008 // export ODF 1.2
1009 std::shared_ptr<comphelper::ConfigurationChanges> pBatch(
1010 comphelper::ConfigurationChanges::create());
1011 officecfg::Office::Common::Save::ODF::DefaultVersion::set(4, pBatch);
1012 pBatch->commit();
1014 save("calc8");
1016 // check XML
1017 xmlDocUniquePtr pContentXml = parseExport("content.xml");
1018 assertXPathNoAttribute(
1019 pContentXml,
1020 "/office:document-content/office:automatic-styles/style:style/style:table-properties",
1021 "tab-color");
1022 xmlDocUniquePtr pStylesXml = parseExport("styles.xml");
1023 assertXPathNoAttribute(pStylesXml,
1024 "/office:document-styles/office:automatic-styles/"
1025 "style:page-layout[1]/style:page-layout-properties",
1026 "scale-to-X");
1027 assertXPathNoAttribute(pStylesXml,
1028 "/office:document-styles/office:automatic-styles/"
1029 "style:page-layout[1]/style:page-layout-properties",
1030 "scale-to-Y");
1032 // don't reload - no point
1036 void ScExportTest::testColumnWidthResaveXLSX()
1038 // tdf#91475 FILESAVE: Column width is not preserved in XLSX / after round trip.
1039 // Test if after resave .xlsx file, columns width is identical with previous one
1040 createScDoc("xlsx/different-column-width-excel2010.xlsx");
1042 save("Calc Office Open XML");
1043 xmlDocUniquePtr pSheet = parseExport("xl/worksheets/sheet1.xml");
1044 CPPUNIT_ASSERT(pSheet);
1046 // In original Excel document the width is "24"
1047 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[1]", "width", "24");
1048 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[1]", "customWidth", "true");
1050 // In original Excel document the width is "12"
1051 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[2]", "width", "12");
1052 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[2]", "customWidth", "true");
1054 // In original Excel document the width is "6"
1055 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[3]", "width", "6");
1056 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[3]", "customWidth", "true");
1058 // In original Excel document the width is "1"
1059 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[4]", "width", "1");
1060 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[4]", "customWidth", "true");
1062 // In original Excel document the width is "250"
1063 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[5]", "width", "250");
1064 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[5]", "customWidth", "true");
1066 assertXPath(pSheet, "/x:worksheet/x:cols/x:col", 5);
1069 #if HAVE_MORE_FONTS
1070 void ScExportTest::testColumnWidthExportFromODStoXLSX()
1072 // tdf#91475 FILESAVE: Column width is not preserved in XLSX / after round trip.
1073 // Test if after export .ods to .xlsx format, displayed columns width
1074 // is identical with previous (.ods) one
1076 createScDoc("ods/different-column-width.ods");
1078 ScDocument* pDoc = getScDoc();
1080 // Col 1, Tab 0 (Column width 2.00 in)
1081 sal_uInt16 nExpectedColumn0Width
1082 = pDoc->GetColWidth(static_cast<SCCOL>(0), static_cast<SCTAB>(0), false);
1083 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(2880), nExpectedColumn0Width);
1085 // Col 2, Tab 0 (Column width 1.00 in)
1086 sal_uInt16 nExpectedColumn1Width
1087 = pDoc->GetColWidth(static_cast<SCCOL>(1), static_cast<SCTAB>(0), false);
1088 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(1440), nExpectedColumn1Width);
1090 // Col 3, Tab 0 (Column width 0.50 in)
1091 sal_uInt16 nExpectedColumn2Width
1092 = pDoc->GetColWidth(static_cast<SCCOL>(2), static_cast<SCTAB>(0), false);
1093 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(720), nExpectedColumn2Width);
1095 // Col 4, Tab 0 (Column width 0.25 in)
1096 sal_uInt16 nExpectedColumn3Width
1097 = pDoc->GetColWidth(static_cast<SCCOL>(3), static_cast<SCTAB>(0), false);
1098 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(360), nExpectedColumn3Width);
1100 // Col 5, Tab 0 (Column width 13.57 in)
1101 sal_uInt16 nExpectedColumn4Width
1102 = pDoc->GetColWidth(static_cast<SCCOL>(4), static_cast<SCTAB>(0), false);
1103 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(19539), nExpectedColumn4Width);
1105 // Export to .xlsx and compare column width with the .ods
1106 // We expect that column width from .ods will be exactly the same as imported from .xlsx
1108 saveAndReload("Calc Office Open XML");
1110 pDoc = getScDoc();
1112 // Col 1, Tab 0
1113 sal_uInt16 nCalcWidth;
1114 nCalcWidth = pDoc->GetColWidth(static_cast<SCCOL>(0), static_cast<SCTAB>(0), false);
1115 CPPUNIT_ASSERT_EQUAL(nExpectedColumn0Width, nCalcWidth);
1117 // Col 2, Tab 0
1118 nCalcWidth = pDoc->GetColWidth(static_cast<SCCOL>(1), static_cast<SCTAB>(0), false);
1119 CPPUNIT_ASSERT_EQUAL(nExpectedColumn1Width, nCalcWidth);
1121 // Col 3, Tab 0
1122 nCalcWidth = pDoc->GetColWidth(static_cast<SCCOL>(2), static_cast<SCTAB>(0), false);
1123 CPPUNIT_ASSERT_EQUAL(nExpectedColumn2Width, nCalcWidth);
1125 // Col 4, Tab 0
1126 nCalcWidth = pDoc->GetColWidth(static_cast<SCCOL>(3), static_cast<SCTAB>(0), false);
1127 CPPUNIT_ASSERT_EQUAL(nExpectedColumn3Width, nCalcWidth);
1129 // Col 5, Tab 0
1130 nCalcWidth = pDoc->GetColWidth(static_cast<SCCOL>(4), static_cast<SCTAB>(0), false);
1131 CPPUNIT_ASSERT_EQUAL(nExpectedColumn4Width, nCalcWidth);
1133 #endif
1135 void ScExportTest::testOutlineExportXLSX()
1137 //tdf#100347 FILESAVE FILEOPEN after exporting to .xlsx format grouping are lost
1138 //tdf#51524 FILESAVE .xlsx and.xls looses width information for hidden/collapsed grouped columns
1139 createScDoc("ods/outline.ods");
1141 save("Calc Office Open XML");
1142 xmlDocUniquePtr pSheet = parseExport("xl/worksheets/sheet1.xml");
1143 CPPUNIT_ASSERT(pSheet);
1145 // Maximum Outline Row is 4 for this document
1146 assertXPath(pSheet, "/x:worksheet/x:sheetFormatPr", "outlineLevelRow", "4");
1147 // Maximum Outline Column is 4 for this document
1148 assertXPath(pSheet, "/x:worksheet/x:sheetFormatPr", "outlineLevelCol", "4");
1150 // First XML node, creates two columns (from min=1 to max=2)
1151 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[1]", "hidden", "false");
1152 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[1]", "outlineLevel", "1");
1153 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[1]", "collapsed", "false");
1154 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[1]", "min", "1");
1155 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[1]", "max", "2");
1157 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[2]", "hidden", "true");
1158 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[2]", "outlineLevel", "2");
1159 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[2]", "collapsed", "false");
1160 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[2]", "min", "3");
1161 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[2]", "max", "3");
1163 // Column 4 has custom width and it is hidden. We need to make sure that it is created
1164 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[3]", "hidden", "true");
1165 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[3]", "outlineLevel", "2");
1166 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[3]", "collapsed", "false");
1167 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[3]", "min", "4");
1168 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[3]", "max", "4");
1170 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[4]", "hidden", "true");
1171 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[4]", "outlineLevel", "3");
1172 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[4]", "collapsed", "false");
1173 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[4]", "min", "5");
1174 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[4]", "max", "6");
1176 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[5]", "hidden", "true");
1177 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[5]", "outlineLevel", "4");
1178 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[5]", "collapsed", "false");
1179 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[5]", "min", "7");
1180 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[5]", "max", "7");
1182 // Column 8 has custom width and it is hidden. We need to make sure that it is created
1183 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[6]", "hidden", "true");
1184 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[6]", "outlineLevel", "4");
1185 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[6]", "collapsed", "false");
1186 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[6]", "min", "8");
1187 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[6]", "max", "8");
1189 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[7]", "hidden", "true");
1190 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[7]", "outlineLevel", "4");
1191 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[7]", "collapsed", "false");
1192 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[7]", "min", "9");
1193 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[7]", "max", "19");
1195 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[8]", "hidden", "true");
1196 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[8]", "outlineLevel", "3");
1197 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[8]", "collapsed", "true");
1198 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[8]", "min", "20");
1199 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[8]", "max", "20");
1201 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[9]", "hidden", "true");
1202 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[9]", "outlineLevel", "3");
1203 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[9]", "collapsed", "false");
1204 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[9]", "min", "21");
1205 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[9]", "max", "21");
1207 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[10]", "hidden", "true");
1208 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[10]", "outlineLevel", "2");
1209 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[10]", "collapsed", "false");
1210 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[10]", "min", "22");
1211 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[10]", "max", "23");
1213 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[11]", "hidden", "false");
1214 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[11]", "outlineLevel", "1");
1215 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[11]", "collapsed", "true");
1216 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[11]", "min", "24");
1217 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[11]", "max", "24");
1219 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[12]", "hidden", "false");
1220 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[12]", "outlineLevel", "1");
1221 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[12]", "collapsed", "false");
1222 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[12]", "min", "25");
1223 assertXPath(pSheet, "/x:worksheet/x:cols/x:col[12]", "max", "26");
1225 // We expected that exactly 12 unique Nodes will be produced
1226 assertXPath(pSheet, "/x:worksheet/x:cols/x:col", 12);
1228 // First row is empty and default so it is not written into XML file
1229 // so we need to save 29 rows, as it provides information about outLineLevel
1230 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[1]", "r", "2");
1231 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[1]", "hidden", "false");
1232 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[1]", "outlineLevel", "1");
1233 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[1]", "collapsed", "false");
1234 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[2]", "r", "3");
1235 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[2]", "hidden", "false");
1236 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[2]", "outlineLevel", "2");
1237 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[2]", "collapsed", "false");
1238 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[3]", "r", "4");
1239 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[3]", "hidden", "false");
1240 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[3]", "outlineLevel", "2");
1241 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[3]", "collapsed", "false");
1242 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[4]", "r", "5");
1243 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[4]", "hidden", "false");
1244 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[4]", "outlineLevel", "3");
1245 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[4]", "collapsed", "false");
1246 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[5]", "r", "6");
1247 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[5]", "hidden", "false");
1248 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[5]", "outlineLevel", "3");
1249 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[5]", "collapsed", "false");
1250 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[6]", "r", "7");
1251 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[6]", "hidden", "true");
1252 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[6]", "outlineLevel", "4");
1253 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[6]", "collapsed", "false");
1254 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[7]", "r", "8");
1255 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[7]", "hidden", "true");
1256 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[7]", "outlineLevel", "4");
1257 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[7]", "collapsed", "false");
1258 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[8]", "r", "9");
1259 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[8]", "hidden", "true");
1260 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[8]", "outlineLevel", "4");
1261 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[8]", "collapsed", "false");
1262 // Next rows are the same as the previous one but it needs to be preserved,
1263 // as they contain information about outlineLevel
1264 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[20]", "r", "21");
1265 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[20]", "hidden", "true");
1266 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[20]", "outlineLevel", "4");
1267 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[20]", "collapsed", "false");
1268 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[21]", "r", "22");
1269 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[21]", "hidden", "false");
1270 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[21]", "outlineLevel", "3");
1271 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[21]", "collapsed", "true");
1272 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[22]", "r", "23");
1273 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[22]", "hidden", "false");
1274 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[22]", "outlineLevel", "3");
1275 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[22]", "collapsed", "false");
1277 // We expected that exactly 29 Row Nodes will be produced
1278 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row", 29);
1281 void ScExportTest::testAllRowsHiddenXLSX()
1283 createScDoc("xlsx/tdf105840_allRowsHidden.xlsx");
1285 save("Calc Office Open XML");
1286 xmlDocUniquePtr pSheet = parseExport("xl/worksheets/sheet1.xml");
1287 CPPUNIT_ASSERT(pSheet);
1288 assertXPath(pSheet, "/x:worksheet/x:sheetFormatPr", "zeroHeight", "true");
1289 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row", 0);
1292 void ScExportTest::testHiddenEmptyRowsXLSX()
1294 //tdf#98106 FILESAVE: Hidden and empty rows became visible when export to .XLSX
1295 createScDoc("ods/hidden-empty-rows.ods");
1297 save("Calc Office Open XML");
1298 xmlDocUniquePtr pSheet = parseExport("xl/worksheets/sheet1.xml");
1299 CPPUNIT_ASSERT(pSheet);
1301 assertXPath(pSheet, "/x:worksheet/x:sheetFormatPr", "zeroHeight", "false");
1302 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[1]", "hidden", "true");
1303 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[2]", "hidden", "true");
1304 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[3]", "hidden", "true");
1305 assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[4]", "hidden", "false");
1308 void ScExportTest::testHiddenEmptyColsODS()
1310 //tdf#98106 FILESAVE: Hidden and empty rows became visible when export to .XLSX
1311 createScDoc("ods/tdf128895_emptyHiddenCols.ods");
1313 save("calc8");
1314 xmlDocUniquePtr pSheet = parseExport("content.xml");
1315 CPPUNIT_ASSERT(pSheet);
1316 assertXPath(pSheet, "//table:table/table:table-column[2]");
1317 assertXPath(pSheet, "//table:table/table:table-column[2]", "number-columns-repeated", "1017");
1320 void ScExportTest::testLandscapeOrientationXLSX()
1322 //tdf#48767 - Landscape page orientation is not loaded from .xlsx format with MS Excel, after export with Libre Office
1323 createScDoc("ods/hidden-empty-rows.ods");
1325 save("Calc Office Open XML");
1326 xmlDocUniquePtr pSheet = parseExport("xl/worksheets/sheet1.xml");
1327 CPPUNIT_ASSERT(pSheet);
1329 // the usePrinterDefaults cannot be saved to allow opening sheets in Landscape mode via MS Excel
1330 assertXPathNoAttribute(pSheet, "/x:worksheet/x:pageSetup", "usePrinterDefaults");
1331 assertXPath(pSheet, "/x:worksheet/x:pageSetup", "orientation", "landscape");
1334 void ScExportTest::testDataBarExportXLSX()
1336 createScDoc("xlsx/databar.xlsx");
1338 saveAndReload("Calc Office Open XML");
1340 ScDocument* pDoc = getScDoc();
1342 testDataBar_Impl(*pDoc);
1345 void ScExportTest::testMiscRowHeightExport()
1347 static const TestParam::RowData DfltRowData[] = {
1348 { 0, 4, 0, 529, 0, false },
1349 { 5, 10, 0, 1058, 0, false },
1350 { 17, 20, 0, 1746, 0, false },
1351 // check last couple of row in document to ensure
1352 // they are 5.29mm ( effective default row xlsx height )
1353 { 1048573, 1048575, 0, 529, 0, false },
1356 static const TestParam::RowData EmptyRepeatRowData[] = {
1357 // rows 0-4, 5-10, 17-20 are all set at various
1358 // heights, there is no content in the rows, there
1359 // was a bug where only the first row ( of repeated rows )
1360 // was set after export
1361 { 0, 4, 0, 529, 0, false },
1362 { 5, 10, 0, 1058, 0, false },
1363 { 17, 20, 0, 1767, 0, false },
1366 TestParam aTestValues[] = {
1367 // Checks that some distributed ( non-empty ) heights remain set after export (roundtrip)
1368 // additionally there is effectively a default row height ( 5.29 mm ). So we test the
1369 // unset rows at the end of the document to ensure the effective xlsx default height
1370 // is set there too.
1371 { u"xlsx/miscrowheights.xlsx", "Calc Office Open XML", SAL_N_ELEMENTS(DfltRowData),
1372 DfltRowData },
1373 // Checks that some distributed ( non-empty ) heights remain set after export (to xls)
1374 { u"xlsx/miscrowheights.xlsx", "MS Excel 97", SAL_N_ELEMENTS(DfltRowData), DfltRowData },
1375 // Checks that repreated rows ( of various heights ) remain set after export ( to xlsx )
1376 { u"ods/miscemptyrepeatedrowheights.ods", "Calc Office Open XML",
1377 SAL_N_ELEMENTS(EmptyRepeatRowData), EmptyRepeatRowData },
1378 // Checks that repreated rows ( of various heights ) remain set after export ( to xls )
1379 { u"ods/miscemptyrepeatedrowheights.ods", "MS Excel 97", SAL_N_ELEMENTS(EmptyRepeatRowData),
1380 EmptyRepeatRowData },
1382 miscRowHeightsTest(aTestValues, SAL_N_ELEMENTS(aTestValues));
1385 namespace
1387 void setAttribute(ScFieldEditEngine& rEE, sal_Int32 nPara, sal_Int32 nStart, sal_Int32 nEnd,
1388 sal_uInt16 nType, Color nColor = COL_BLACK)
1390 ESelection aSel;
1391 aSel.nStartPara = aSel.nEndPara = nPara;
1392 aSel.nStartPos = nStart;
1393 aSel.nEndPos = nEnd;
1395 SfxItemSet aItemSet = rEE.GetEmptyItemSet();
1396 switch (nType)
1398 case EE_CHAR_WEIGHT:
1400 SvxWeightItem aWeight(WEIGHT_BOLD, nType);
1401 aItemSet.Put(aWeight);
1402 rEE.QuickSetAttribs(aItemSet, aSel);
1404 break;
1405 case EE_CHAR_ITALIC:
1407 SvxPostureItem aItalic(ITALIC_NORMAL, nType);
1408 aItemSet.Put(aItalic);
1409 rEE.QuickSetAttribs(aItemSet, aSel);
1411 break;
1412 case EE_CHAR_STRIKEOUT:
1414 SvxCrossedOutItem aCrossOut(STRIKEOUT_SINGLE, nType);
1415 aItemSet.Put(aCrossOut);
1416 rEE.QuickSetAttribs(aItemSet, aSel);
1418 break;
1419 case EE_CHAR_OVERLINE:
1421 SvxOverlineItem aItem(LINESTYLE_DOUBLE, nType);
1422 aItemSet.Put(aItem);
1423 rEE.QuickSetAttribs(aItemSet, aSel);
1425 break;
1426 case EE_CHAR_UNDERLINE:
1428 SvxUnderlineItem aItem(LINESTYLE_DOUBLE, nType);
1429 aItemSet.Put(aItem);
1430 rEE.QuickSetAttribs(aItemSet, aSel);
1432 break;
1433 case EE_CHAR_COLOR:
1435 SvxColorItem aItem(nColor, nType);
1436 aItemSet.Put(aItem);
1437 rEE.QuickSetAttribs(aItemSet, aSel);
1439 break;
1440 default:;
1444 void setFont(ScFieldEditEngine& rEE, sal_Int32 nPara, sal_Int32 nStart, sal_Int32 nEnd,
1445 const OUString& rFontName)
1447 ESelection aSel;
1448 aSel.nStartPara = aSel.nEndPara = nPara;
1449 aSel.nStartPos = nStart;
1450 aSel.nEndPos = nEnd;
1452 SfxItemSet aItemSet = rEE.GetEmptyItemSet();
1453 SvxFontItem aItem(FAMILY_MODERN, rFontName, "", PITCH_VARIABLE, RTL_TEXTENCODING_UTF8,
1454 EE_CHAR_FONTINFO);
1455 aItemSet.Put(aItem);
1456 rEE.QuickSetAttribs(aItemSet, aSel);
1459 void setEscapement(ScFieldEditEngine& rEE, sal_Int32 nPara, sal_Int32 nStart, sal_Int32 nEnd,
1460 short nEsc, sal_uInt8 nRelSize)
1462 ESelection aSel;
1463 aSel.nStartPara = aSel.nEndPara = nPara;
1464 aSel.nStartPos = nStart;
1465 aSel.nEndPos = nEnd;
1467 SfxItemSet aItemSet = rEE.GetEmptyItemSet();
1468 SvxEscapementItem aItem(nEsc, nRelSize, EE_CHAR_ESCAPEMENT);
1469 aItemSet.Put(aItem);
1470 rEE.QuickSetAttribs(aItemSet, aSel);
1474 void ScExportTest::testNamedRangeBugfdo62729()
1476 #if !defined(MACOSX) // FIXME: infinite loop on jenkins' mac
1477 createScDoc("ods/fdo62729.ods");
1478 ScDocument* pDoc = getScDoc();
1480 ScRangeName* pNames = pDoc->GetRangeName();
1481 //should be just a single named range
1482 CPPUNIT_ASSERT_EQUAL(size_t(1), pNames->size());
1483 pDoc->DeleteTab(0);
1484 //should be still a single named range
1485 CPPUNIT_ASSERT_EQUAL(size_t(1), pNames->size());
1486 saveAndReload("calc8");
1488 pDoc = getScDoc();
1490 pNames = pDoc->GetRangeName();
1491 //after reload should still have a named range
1492 CPPUNIT_ASSERT_EQUAL(size_t(1), pNames->size());
1493 #endif
1496 void ScExportTest::testBuiltinRangesXLSX()
1498 createScDoc("xlsx/built-in_ranges.xlsx");
1500 save("Calc Office Open XML");
1501 xmlDocUniquePtr pDoc = parseExport("xl/workbook.xml");
1502 CPPUNIT_ASSERT(pDoc);
1504 //assert the existing OOXML built-in names are still there
1505 assertXPathContent(pDoc,
1506 "/x:workbook/x:definedNames/"
1507 "x:definedName[@name='_xlnm._FilterDatabase'][@localSheetId='0']",
1508 "'Sheet1 Test'!$A$1:$A$5");
1509 assertXPathContent(pDoc,
1510 "/x:workbook/x:definedNames/"
1511 "x:definedName[@name='_xlnm._FilterDatabase'][@localSheetId='1']",
1512 "'Sheet2 Test'!$K$10:$K$14");
1513 assertXPathContent(
1514 pDoc,
1515 "/x:workbook/x:definedNames/x:definedName[@name='_xlnm.Print_Area'][@localSheetId='0']",
1516 "'Sheet1 Test'!$A$1:$A$5");
1517 assertXPathContent(
1518 pDoc,
1519 "/x:workbook/x:definedNames/x:definedName[@name='_xlnm.Print_Area'][@localSheetId='1']",
1520 "'Sheet2 Test'!$K$10:$M$18");
1522 //...and that no extra ones are added (see tdf#112571)
1523 assertXPath(pDoc,
1524 "/x:workbook/x:definedNames/"
1525 "x:definedName[@name='_xlnm._FilterDatabase_0'][@localSheetId='0']",
1527 assertXPath(pDoc,
1528 "/x:workbook/x:definedNames/"
1529 "x:definedName[@name='_xlnm._FilterDatabase_0'][@localSheetId='1']",
1531 assertXPath(
1532 pDoc,
1533 "/x:workbook/x:definedNames/x:definedName[@name='_xlnm.Print_Area_0'][@localSheetId='0']",
1535 assertXPath(
1536 pDoc,
1537 "/x:workbook/x:definedNames/x:definedName[@name='_xlnm.Print_Area_0'][@localSheetId='1']",
1541 void ScExportTest::testRichTextExportODS()
1543 struct
1545 static bool isBold(const editeng::Section& rAttr)
1547 return std::any_of(
1548 rAttr.maAttributes.begin(), rAttr.maAttributes.end(), [](const SfxPoolItem* p) {
1549 return p->Which() == EE_CHAR_WEIGHT
1550 && static_cast<const SvxWeightItem*>(p)->GetWeight() == WEIGHT_BOLD;
1554 static bool isItalic(const editeng::Section& rAttr)
1556 return std::any_of(
1557 rAttr.maAttributes.begin(), rAttr.maAttributes.end(), [](const SfxPoolItem* p) {
1558 return p->Which() == EE_CHAR_ITALIC
1559 && static_cast<const SvxPostureItem*>(p)->GetPosture() == ITALIC_NORMAL;
1563 static bool isStrikeOut(const editeng::Section& rAttr)
1565 return std::any_of(
1566 rAttr.maAttributes.begin(), rAttr.maAttributes.end(), [](const SfxPoolItem* p) {
1567 return p->Which() == EE_CHAR_STRIKEOUT
1568 && static_cast<const SvxCrossedOutItem*>(p)->GetStrikeout()
1569 == STRIKEOUT_SINGLE;
1573 static bool isOverline(const editeng::Section& rAttr, FontLineStyle eStyle)
1575 return std::any_of(rAttr.maAttributes.begin(), rAttr.maAttributes.end(),
1576 [&eStyle](const SfxPoolItem* p) {
1577 return p->Which() == EE_CHAR_OVERLINE
1578 && static_cast<const SvxOverlineItem*>(p)->GetLineStyle()
1579 == eStyle;
1583 static bool isUnderline(const editeng::Section& rAttr, FontLineStyle eStyle)
1585 return std::any_of(rAttr.maAttributes.begin(), rAttr.maAttributes.end(),
1586 [&eStyle](const SfxPoolItem* p) {
1587 return p->Which() == EE_CHAR_UNDERLINE
1588 && static_cast<const SvxUnderlineItem*>(p)->GetLineStyle()
1589 == eStyle;
1593 static bool isFont(const editeng::Section& rAttr, const OUString& rFontName)
1595 return std::any_of(rAttr.maAttributes.begin(), rAttr.maAttributes.end(),
1596 [&rFontName](const SfxPoolItem* p) {
1597 return p->Which() == EE_CHAR_FONTINFO
1598 && static_cast<const SvxFontItem*>(p)->GetFamilyName()
1599 == rFontName;
1603 static bool isEscapement(const editeng::Section& rAttr, short nEsc, sal_uInt8 nRelSize)
1605 return std::any_of(rAttr.maAttributes.begin(), rAttr.maAttributes.end(),
1606 [&nEsc, &nRelSize](const SfxPoolItem* p) {
1607 if (p->Which() != EE_CHAR_ESCAPEMENT)
1608 return false;
1609 const SvxEscapementItem* pItem
1610 = static_cast<const SvxEscapementItem*>(p);
1611 return ((pItem->GetEsc() == nEsc)
1612 && (pItem->GetProportionalHeight() == nRelSize));
1616 static bool isColor(const editeng::Section& rAttr, Color nColor)
1618 return std::any_of(rAttr.maAttributes.begin(), rAttr.maAttributes.end(),
1619 [&nColor](const SfxPoolItem* p) {
1620 return p->Which() == EE_CHAR_COLOR
1621 && static_cast<const SvxColorItem*>(p)->GetValue()
1622 == nColor;
1626 bool checkB2(const EditTextObject* pText) const
1628 if (!pText)
1629 return false;
1631 if (pText->GetParagraphCount() != 1)
1632 return false;
1634 if (pText->GetText(0) != "Bold and Italic")
1635 return false;
1637 std::vector<editeng::Section> aSecAttrs;
1638 pText->GetAllSections(aSecAttrs);
1639 if (aSecAttrs.size() != 3)
1640 return false;
1642 // Check the first bold section.
1643 const editeng::Section* pAttr = aSecAttrs.data();
1644 if (pAttr->mnParagraph != 0 || pAttr->mnStart != 0 || pAttr->mnEnd != 4)
1645 return false;
1647 if (pAttr->maAttributes.size() != 1 || !isBold(*pAttr))
1648 return false;
1650 // The middle section should be unformatted.
1651 pAttr = &aSecAttrs[1];
1652 if (pAttr->mnParagraph != 0 || pAttr->mnStart != 4 || pAttr->mnEnd != 9)
1653 return false;
1655 if (!pAttr->maAttributes.empty())
1656 return false;
1658 // The last section should be italic.
1659 pAttr = &aSecAttrs[2];
1660 if (pAttr->mnParagraph != 0 || pAttr->mnStart != 9 || pAttr->mnEnd != 15)
1661 return false;
1663 if (pAttr->maAttributes.size() != 1 || !isItalic(*pAttr))
1664 return false;
1666 return true;
1669 bool checkB4(const EditTextObject* pText) const
1671 if (!pText)
1672 return false;
1674 if (pText->GetParagraphCount() != 3)
1675 return false;
1677 if (pText->GetText(0) != "One")
1678 return false;
1680 if (pText->GetText(1) != "Two")
1681 return false;
1683 if (pText->GetText(2) != "Three")
1684 return false;
1686 return true;
1689 bool checkB5(const EditTextObject* pText) const
1691 if (!pText)
1692 return false;
1694 if (pText->GetParagraphCount() != 6)
1695 return false;
1697 if (!pText->GetText(0).isEmpty())
1698 return false;
1700 if (pText->GetText(1) != "Two")
1701 return false;
1703 if (pText->GetText(2) != "Three")
1704 return false;
1706 if (!pText->GetText(3).isEmpty())
1707 return false;
1709 if (pText->GetText(4) != "Five")
1710 return false;
1712 if (!pText->GetText(5).isEmpty())
1713 return false;
1715 return true;
1718 bool checkB6(const EditTextObject* pText) const
1720 if (!pText)
1721 return false;
1723 if (pText->GetParagraphCount() != 1)
1724 return false;
1726 if (pText->GetText(0) != "Strike Me")
1727 return false;
1729 std::vector<editeng::Section> aSecAttrs;
1730 pText->GetAllSections(aSecAttrs);
1731 if (aSecAttrs.size() != 2)
1732 return false;
1734 // Check the first strike-out section.
1735 const editeng::Section* pAttr = aSecAttrs.data();
1736 if (pAttr->mnParagraph != 0 || pAttr->mnStart != 0 || pAttr->mnEnd != 6)
1737 return false;
1739 if (pAttr->maAttributes.size() != 1 || !isStrikeOut(*pAttr))
1740 return false;
1742 // The last section should be unformatted.
1743 pAttr = &aSecAttrs[1];
1744 return pAttr->mnParagraph == 0 && pAttr->mnStart == 6 && pAttr->mnEnd == 9;
1747 bool checkB7(const EditTextObject* pText) const
1749 if (!pText)
1750 return false;
1752 if (pText->GetParagraphCount() != 1)
1753 return false;
1755 if (pText->GetText(0) != "Font1 and Font2")
1756 return false;
1758 std::vector<editeng::Section> aSecAttrs;
1759 pText->GetAllSections(aSecAttrs);
1760 if (aSecAttrs.size() != 3)
1761 return false;
1763 // First section should have "Courier" font applied.
1764 const editeng::Section* pAttr = aSecAttrs.data();
1765 if (pAttr->mnParagraph != 0 || pAttr->mnStart != 0 || pAttr->mnEnd != 5)
1766 return false;
1768 if (pAttr->maAttributes.size() != 1 || !isFont(*pAttr, "Courier"))
1769 return false;
1771 // Last section should have "Luxi Mono" applied.
1772 pAttr = &aSecAttrs[2];
1773 if (pAttr->mnParagraph != 0 || pAttr->mnStart != 10 || pAttr->mnEnd != 15)
1774 return false;
1776 if (pAttr->maAttributes.size() != 1 || !isFont(*pAttr, "Luxi Mono"))
1777 return false;
1779 return true;
1782 bool checkB8(const EditTextObject* pText) const
1784 if (!pText)
1785 return false;
1787 if (pText->GetParagraphCount() != 1)
1788 return false;
1790 if (pText->GetText(0) != "Over and Under")
1791 return false;
1793 std::vector<editeng::Section> aSecAttrs;
1794 pText->GetAllSections(aSecAttrs);
1795 if (aSecAttrs.size() != 3)
1796 return false;
1798 // First section should have overline applied.
1799 const editeng::Section* pAttr = aSecAttrs.data();
1800 if (pAttr->mnParagraph != 0 || pAttr->mnStart != 0 || pAttr->mnEnd != 4)
1801 return false;
1803 if (pAttr->maAttributes.size() != 1 || !isOverline(*pAttr, LINESTYLE_DOUBLE))
1804 return false;
1806 // Last section should have underline applied.
1807 pAttr = &aSecAttrs[2];
1808 if (pAttr->mnParagraph != 0 || pAttr->mnStart != 9 || pAttr->mnEnd != 14)
1809 return false;
1811 if (pAttr->maAttributes.size() != 1 || !isUnderline(*pAttr, LINESTYLE_DOUBLE))
1812 return false;
1814 return true;
1817 bool checkB9(const EditTextObject* pText) const
1819 if (!pText)
1820 return false;
1822 if (pText->GetParagraphCount() != 1)
1823 return false;
1825 if (pText->GetText(0) != "Sub and Super")
1826 return false;
1828 std::vector<editeng::Section> aSecAttrs;
1829 pText->GetAllSections(aSecAttrs);
1830 if (aSecAttrs.size() != 3)
1831 return false;
1833 // superscript
1834 const editeng::Section* pAttr = aSecAttrs.data();
1835 if (pAttr->mnParagraph != 0 || pAttr->mnStart != 0 || pAttr->mnEnd != 3)
1836 return false;
1838 if (pAttr->maAttributes.size() != 1 || !isEscapement(*pAttr, 32, 64))
1839 return false;
1841 // subscript
1842 pAttr = &aSecAttrs[2];
1843 if (pAttr->mnParagraph != 0 || pAttr->mnStart != 8 || pAttr->mnEnd != 13)
1844 return false;
1846 if (pAttr->maAttributes.size() != 1 || !isEscapement(*pAttr, -32, 66))
1847 return false;
1849 return true;
1852 bool checkB10(const EditTextObject* pText) const
1854 if (!pText)
1855 return false;
1857 if (pText->GetParagraphCount() != 1)
1858 return false;
1860 if (pText->GetText(0) != "BLUE AUTO")
1861 return false;
1863 std::vector<editeng::Section> aSecAttrs;
1864 pText->GetAllSections(aSecAttrs);
1865 if (aSecAttrs.size() != 2)
1866 return false;
1868 // auto color
1869 const editeng::Section* pAttr = &aSecAttrs[1];
1870 if (pAttr->mnParagraph != 0 || pAttr->mnStart != 5 || pAttr->mnEnd != 9)
1871 return false;
1873 if (pAttr->maAttributes.size() != 1 || !isColor(*pAttr, COL_AUTO))
1874 return false;
1876 return true;
1879 } aCheckFunc;
1881 // Start with an empty document, put one edit text cell, and make sure it
1882 // survives the save and reload.
1883 createScDoc();
1884 const EditTextObject* pEditText;
1886 ScDocument* pDoc = getScDoc();
1887 CPPUNIT_ASSERT_MESSAGE("This document should at least have one sheet.",
1888 pDoc->GetTableCount() > 0);
1890 // Insert an edit text cell.
1891 ScFieldEditEngine* pEE = &pDoc->GetEditEngine();
1892 pEE->SetTextCurrentDefaults("Bold and Italic");
1893 // Set the 'Bold' part bold.
1894 setAttribute(*pEE, 0, 0, 4, EE_CHAR_WEIGHT);
1895 // Set the 'Italic' part italic.
1896 setAttribute(*pEE, 0, 9, 15, EE_CHAR_ITALIC);
1897 ESelection aSel;
1898 aSel.nStartPara = aSel.nEndPara = 0;
1900 // Set this edit text to cell B2.
1901 pDoc->SetEditText(ScAddress(1, 1, 0), pEE->CreateTextObject());
1902 pEditText = pDoc->GetEditText(ScAddress(1, 1, 0));
1903 CPPUNIT_ASSERT_MESSAGE("Incorrect B2 value.", aCheckFunc.checkB2(pEditText));
1906 // Now, save and reload this document.
1907 saveAndReload("calc8");
1909 ScDocument* pDoc = getScDoc();
1910 CPPUNIT_ASSERT_MESSAGE("Reloaded document should at least have one sheet.",
1911 pDoc->GetTableCount() > 0);
1912 ScFieldEditEngine* pEE = &pDoc->GetEditEngine();
1913 pEditText = pDoc->GetEditText(ScAddress(1, 1, 0));
1915 // Make sure the content of B2 is still intact.
1916 CPPUNIT_ASSERT_MESSAGE("Incorrect B2 value.", aCheckFunc.checkB2(pEditText));
1918 // Insert a multi-line content to B4.
1919 pEE->Clear();
1920 pEE->SetTextCurrentDefaults("One\nTwo\nThree");
1921 pDoc->SetEditText(ScAddress(1, 3, 0), pEE->CreateTextObject());
1922 pEditText = pDoc->GetEditText(ScAddress(1, 3, 0));
1923 CPPUNIT_ASSERT_MESSAGE("Incorrect B4 value.", aCheckFunc.checkB4(pEditText));
1926 // Reload the doc again, and check the content of B2 and B4.
1927 saveAndReload("calc8");
1929 ScDocument* pDoc = getScDoc();
1930 ScFieldEditEngine* pEE = &pDoc->GetEditEngine();
1932 pEditText = pDoc->GetEditText(ScAddress(1, 1, 0));
1933 CPPUNIT_ASSERT_MESSAGE("B2 should be an edit text.", pEditText);
1934 pEditText = pDoc->GetEditText(ScAddress(1, 3, 0));
1935 CPPUNIT_ASSERT_MESSAGE("Incorrect B4 value.", aCheckFunc.checkB4(pEditText));
1937 // Insert a multi-line content to B5, but this time, set some empty paragraphs.
1938 pEE->Clear();
1939 pEE->SetTextCurrentDefaults("\nTwo\nThree\n\nFive\n");
1940 pDoc->SetEditText(ScAddress(1, 4, 0), pEE->CreateTextObject());
1941 pEditText = pDoc->GetEditText(ScAddress(1, 4, 0));
1942 CPPUNIT_ASSERT_MESSAGE("Incorrect B5 value.", aCheckFunc.checkB5(pEditText));
1944 // Insert a text with strikethrough in B6.
1945 pEE->Clear();
1946 pEE->SetTextCurrentDefaults("Strike Me");
1947 // Set the 'Strike' part strikethrough.
1948 setAttribute(*pEE, 0, 0, 6, EE_CHAR_STRIKEOUT);
1949 pDoc->SetEditText(ScAddress(1, 5, 0), pEE->CreateTextObject());
1950 pEditText = pDoc->GetEditText(ScAddress(1, 5, 0));
1951 CPPUNIT_ASSERT_MESSAGE("Incorrect B6 value.", aCheckFunc.checkB6(pEditText));
1953 // Insert a text with different font segments in B7.
1954 pEE->Clear();
1955 pEE->SetTextCurrentDefaults("Font1 and Font2");
1956 setFont(*pEE, 0, 0, 5, "Courier");
1957 setFont(*pEE, 0, 10, 15, "Luxi Mono");
1958 pDoc->SetEditText(ScAddress(1, 6, 0), pEE->CreateTextObject());
1959 pEditText = pDoc->GetEditText(ScAddress(1, 6, 0));
1960 CPPUNIT_ASSERT_MESSAGE("Incorrect B7 value.", aCheckFunc.checkB7(pEditText));
1962 // Insert a text with overline and underline in B8.
1963 pEE->Clear();
1964 pEE->SetTextCurrentDefaults("Over and Under");
1965 setAttribute(*pEE, 0, 0, 4, EE_CHAR_OVERLINE);
1966 setAttribute(*pEE, 0, 9, 14, EE_CHAR_UNDERLINE);
1967 pDoc->SetEditText(ScAddress(1, 7, 0), pEE->CreateTextObject());
1968 pEditText = pDoc->GetEditText(ScAddress(1, 7, 0));
1969 CPPUNIT_ASSERT_MESSAGE("Incorrect B8 value.", aCheckFunc.checkB8(pEditText));
1971 pEE->Clear();
1972 pEE->SetTextCurrentDefaults("Sub and Super");
1973 setEscapement(*pEE, 0, 0, 3, 32, 64);
1974 setEscapement(*pEE, 0, 8, 13, -32, 66);
1975 pDoc->SetEditText(ScAddress(1, 8, 0), pEE->CreateTextObject());
1976 pEditText = pDoc->GetEditText(ScAddress(1, 8, 0));
1977 CPPUNIT_ASSERT_MESSAGE("Incorrect B9 value.", aCheckFunc.checkB9(pEditText));
1979 ScPatternAttr aCellFontColor(pDoc->GetPool());
1980 aCellFontColor.GetItemSet().Put(SvxColorItem(COL_BLUE, ATTR_FONT_COLOR));
1981 // Set font color of B10 to blue.
1982 pDoc->ApplyPattern(1, 9, 0, aCellFontColor);
1983 pEE->Clear();
1984 pEE->SetTextCurrentDefaults("BLUE AUTO");
1985 // Set the color of the string "AUTO" to automatic color.
1986 setAttribute(*pEE, 0, 5, 9, EE_CHAR_COLOR, COL_AUTO);
1987 pDoc->SetEditText(ScAddress(1, 9, 0), pEE->CreateTextObject());
1988 pEditText = pDoc->GetEditText(ScAddress(1, 9, 0));
1989 CPPUNIT_ASSERT_MESSAGE("Incorrect B10 value.", aCheckFunc.checkB10(pEditText));
1992 // Reload the doc again, and check the content of B2, B4, B6 and B7.
1993 saveAndReload("calc8");
1994 ScDocument* pDoc = getScDoc();
1996 pEditText = pDoc->GetEditText(ScAddress(1, 1, 0));
1997 CPPUNIT_ASSERT_MESSAGE("Incorrect B2 value after save and reload.",
1998 aCheckFunc.checkB2(pEditText));
1999 pEditText = pDoc->GetEditText(ScAddress(1, 3, 0));
2000 CPPUNIT_ASSERT_MESSAGE("Incorrect B4 value after save and reload.",
2001 aCheckFunc.checkB4(pEditText));
2002 pEditText = pDoc->GetEditText(ScAddress(1, 4, 0));
2003 CPPUNIT_ASSERT_MESSAGE("Incorrect B5 value after save and reload.",
2004 aCheckFunc.checkB5(pEditText));
2005 pEditText = pDoc->GetEditText(ScAddress(1, 5, 0));
2006 CPPUNIT_ASSERT_MESSAGE("Incorrect B6 value after save and reload.",
2007 aCheckFunc.checkB6(pEditText));
2008 pEditText = pDoc->GetEditText(ScAddress(1, 6, 0));
2009 CPPUNIT_ASSERT_MESSAGE("Incorrect B7 value after save and reload.",
2010 aCheckFunc.checkB7(pEditText));
2011 pEditText = pDoc->GetEditText(ScAddress(1, 7, 0));
2012 CPPUNIT_ASSERT_MESSAGE("Incorrect B8 value after save and reload.",
2013 aCheckFunc.checkB8(pEditText));
2014 pEditText = pDoc->GetEditText(ScAddress(1, 9, 0));
2015 CPPUNIT_ASSERT_MESSAGE("Incorrect B10 value after save and reload.",
2016 aCheckFunc.checkB10(pEditText));
2019 void ScExportTest::testRichTextCellFormatXLSX()
2021 createScDoc("xls/cellformat.xls");
2023 save("Calc Office Open XML");
2024 xmlDocUniquePtr pSheet = parseExport("xl/worksheets/sheet1.xml");
2025 CPPUNIT_ASSERT(pSheet);
2027 // make sure the only cell in this doc is assigned some formatting record
2028 OUString aCellFormat = getXPath(pSheet, "/x:worksheet/x:sheetData/x:row/x:c", "s");
2029 CPPUNIT_ASSERT_MESSAGE("Cell format is missing", !aCellFormat.isEmpty());
2031 xmlDocUniquePtr pStyles = parseExport("xl/styles.xml");
2032 CPPUNIT_ASSERT(pStyles);
2034 OString nFormatIdx = OString::number(aCellFormat.toInt32() + 1);
2035 const OString aXPath1("/x:styleSheet/x:cellXfs/x:xf[" + nFormatIdx + "]/x:alignment");
2036 // formatting record is set to wrap text
2037 assertXPath(pStyles, aXPath1, "wrapText", "true");
2039 // see what font it references
2040 const OString aXPath2("/x:styleSheet/x:cellXfs/x:xf[" + nFormatIdx + "]");
2041 OUString aFontId = getXPath(pStyles, aXPath2, "fontId");
2042 OString nFontIdx = OString::number(aFontId.toInt32() + 1);
2044 // that font should be bold
2045 const OString aXPath3("/x:styleSheet/x:fonts/x:font[" + nFontIdx + "]/x:b");
2046 assertXPath(pStyles, aXPath3, "val", "true");
2049 void ScExportTest::testFormulaRefSheetNameODS()
2051 createScDoc("ods/formula-quote-in-sheet-name.ods");
2053 ScDocument* pDoc = getScDoc();
2055 sc::AutoCalcSwitch aACSwitch(*pDoc, true); // turn on auto calc.
2056 pDoc->SetString(ScAddress(1, 1, 0), "='90''s Data'.B2");
2057 CPPUNIT_ASSERT_EQUAL(1.1, pDoc->GetValue(ScAddress(1, 1, 0)));
2058 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula", OUString("='90''s Data'.B2"),
2059 pDoc->GetFormula(1, 1, 0));
2061 // Now, save and reload this document.
2062 saveAndReload("calc8");
2064 ScDocument* pDoc = getScDoc();
2065 pDoc->CalcAll();
2066 CPPUNIT_ASSERT_EQUAL(1.1, pDoc->GetValue(ScAddress(1, 1, 0)));
2067 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula", OUString("='90''s Data'.B2"),
2068 pDoc->GetFormula(1, 1, 0));
2071 void ScExportTest::testCellValuesExportODS()
2073 // Start with an empty document
2074 createScDoc();
2076 ScDocument* pDoc = getScDoc();
2077 CPPUNIT_ASSERT_MESSAGE("This document should at least have one sheet.",
2078 pDoc->GetTableCount() > 0);
2080 // set a value double
2081 pDoc->SetValue(ScAddress(0, 0, 0), 2.0); // A1
2083 // set a formula
2084 pDoc->SetValue(ScAddress(2, 0, 0), 3.0); // C1
2085 pDoc->SetValue(ScAddress(3, 0, 0), 3); // D1
2086 pDoc->SetString(ScAddress(4, 0, 0), "=10*C1/4"); // E1
2087 pDoc->SetValue(ScAddress(5, 0, 0), 3.0); // F1
2088 pDoc->SetString(ScAddress(7, 0, 0), "=SUM(C1:F1)"); //H1
2090 // set a string
2091 pDoc->SetString(ScAddress(0, 2, 0), "a simple line"); //A3
2093 // set a digit string
2094 pDoc->SetString(ScAddress(0, 4, 0), "'12"); //A5
2095 // set a contiguous value
2096 pDoc->SetValue(ScAddress(0, 5, 0), 12.0); //A6
2097 // set a contiguous string
2098 pDoc->SetString(ScAddress(0, 6, 0), "a string"); //A7
2099 // set a contiguous formula
2100 pDoc->SetString(ScAddress(0, 7, 0), "=$A$6"); //A8
2102 // save and reload
2103 saveAndReload("calc8");
2104 ScDocument* pDoc = getScDoc();
2105 CPPUNIT_ASSERT_MESSAGE("Reloaded document should at least have one sheet.",
2106 pDoc->GetTableCount() > 0);
2108 // check value
2109 CPPUNIT_ASSERT_EQUAL(2.0, pDoc->GetValue(0, 0, 0));
2110 CPPUNIT_ASSERT_EQUAL(3.0, pDoc->GetValue(2, 0, 0));
2111 CPPUNIT_ASSERT_EQUAL(3.0, pDoc->GetValue(3, 0, 0));
2112 CPPUNIT_ASSERT_EQUAL(7.5, pDoc->GetValue(4, 0, 0));
2113 CPPUNIT_ASSERT_EQUAL(3.0, pDoc->GetValue(5, 0, 0));
2115 // check formula
2116 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula =10*C1/4", OUString("=10*C1/4"),
2117 pDoc->GetFormula(4, 0, 0));
2118 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula =SUM(C1:F1)", OUString("=SUM(C1:F1)"),
2119 pDoc->GetFormula(7, 0, 0));
2120 CPPUNIT_ASSERT_EQUAL(16.5, pDoc->GetValue(7, 0, 0));
2122 // check string
2123 ScRefCellValue aCell;
2124 aCell.assign(*pDoc, ScAddress(0, 2, 0));
2125 CPPUNIT_ASSERT_EQUAL(CELLTYPE_STRING, aCell.getType());
2127 // check for an empty cell
2128 aCell.assign(*pDoc, ScAddress(0, 3, 0));
2129 CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE, aCell.getType());
2131 // check a digit string
2132 aCell.assign(*pDoc, ScAddress(0, 4, 0));
2133 CPPUNIT_ASSERT_EQUAL(CELLTYPE_STRING, aCell.getType());
2135 //check contiguous values
2136 CPPUNIT_ASSERT_EQUAL(12.0, pDoc->GetValue(0, 5, 0));
2137 CPPUNIT_ASSERT_EQUAL(OUString("a string"), pDoc->GetString(0, 6, 0));
2138 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula =$A$6", OUString("=$A$6"),
2139 pDoc->GetFormula(0, 7, 0));
2140 CPPUNIT_ASSERT_EQUAL(pDoc->GetValue(0, 5, 0), pDoc->GetValue(0, 7, 0));
2143 void ScExportTest::testCellNoteExportODS()
2145 createScDoc("ods/single-note.ods");
2146 ScAddress aPos(0, 0, 0); // Start with A1.
2148 ScDocument* pDoc = getScDoc();
2150 CPPUNIT_ASSERT_MESSAGE("There should be a note at A1.", pDoc->HasNote(aPos));
2152 aPos.IncRow(); // Move to A2.
2153 ScPostIt* pNote = pDoc->GetOrCreateNote(aPos);
2154 pNote->SetText(aPos, "Note One");
2155 pNote->SetAuthor("Author One");
2156 CPPUNIT_ASSERT_MESSAGE("There should be a note at A2.", pDoc->HasNote(aPos));
2158 // save and reload
2159 saveAndReload("calc8");
2160 ScDocument* pDoc = getScDoc();
2162 aPos.SetRow(0); // Move back to A1.
2163 CPPUNIT_ASSERT_MESSAGE("There should be a note at A1.", pDoc->HasNote(aPos));
2164 aPos.IncRow(); // Move to A2.
2165 CPPUNIT_ASSERT_MESSAGE("There should be a note at A2.", pDoc->HasNote(aPos));
2168 void ScExportTest::testCellNoteExportXLS()
2170 // Start with an empty document.s
2171 createScDoc("ods/notes-on-3-sheets.ods");
2173 ScDocument* pDoc = getScDoc();
2174 CPPUNIT_ASSERT_EQUAL_MESSAGE("This document should have 3 sheets.", SCTAB(3),
2175 pDoc->GetTableCount());
2177 // Check note's presence.
2178 CPPUNIT_ASSERT(pDoc->HasNote(ScAddress(0, 0, 0)));
2179 CPPUNIT_ASSERT(!pDoc->HasNote(ScAddress(0, 1, 0)));
2180 CPPUNIT_ASSERT(!pDoc->HasNote(ScAddress(0, 2, 0)));
2182 CPPUNIT_ASSERT(!pDoc->HasNote(ScAddress(0, 0, 1)));
2183 CPPUNIT_ASSERT(pDoc->HasNote(ScAddress(0, 1, 1)));
2184 CPPUNIT_ASSERT(!pDoc->HasNote(ScAddress(0, 2, 1)));
2186 CPPUNIT_ASSERT(!pDoc->HasNote(ScAddress(0, 0, 2)));
2187 CPPUNIT_ASSERT(!pDoc->HasNote(ScAddress(0, 1, 2)));
2188 CPPUNIT_ASSERT(pDoc->HasNote(ScAddress(0, 2, 2)));
2190 // save and reload as XLS.
2191 saveAndReload("MS Excel 97");
2193 ScDocument* pDoc = getScDoc();
2194 CPPUNIT_ASSERT_EQUAL_MESSAGE("This document should have 3 sheets.", SCTAB(3),
2195 pDoc->GetTableCount());
2197 // Check note's presence again.
2198 CPPUNIT_ASSERT(pDoc->HasNote(ScAddress(0, 0, 0)));
2199 CPPUNIT_ASSERT(!pDoc->HasNote(ScAddress(0, 1, 0)));
2200 CPPUNIT_ASSERT(!pDoc->HasNote(ScAddress(0, 2, 0)));
2202 CPPUNIT_ASSERT(!pDoc->HasNote(ScAddress(0, 0, 1)));
2203 CPPUNIT_ASSERT(pDoc->HasNote(ScAddress(0, 1, 1)));
2204 CPPUNIT_ASSERT(!pDoc->HasNote(ScAddress(0, 2, 1)));
2206 CPPUNIT_ASSERT(!pDoc->HasNote(ScAddress(0, 0, 2)));
2207 CPPUNIT_ASSERT(!pDoc->HasNote(ScAddress(0, 1, 2)));
2208 CPPUNIT_ASSERT(pDoc->HasNote(ScAddress(0, 2, 2)));
2212 namespace
2214 void checkMatrixRange(ScDocument& rDoc, const ScRange& rRange)
2216 ScRange aMatRange;
2217 ScAddress aMatOrigin;
2218 for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
2220 for (SCROW nRow = rRange.aStart.Row(); nRow <= rRange.aEnd.Row(); ++nRow)
2222 ScAddress aPos(nCol, nRow, rRange.aStart.Tab());
2223 bool bIsMatrix = rDoc.GetMatrixFormulaRange(aPos, aMatRange);
2224 CPPUNIT_ASSERT_MESSAGE("Matrix expected, but not found.", bIsMatrix);
2225 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong matrix range.", rRange, aMatRange);
2226 const ScFormulaCell* pCell = rDoc.GetFormulaCell(aPos);
2227 CPPUNIT_ASSERT_MESSAGE("This must be a formula cell.", pCell);
2229 bIsMatrix = pCell->GetMatrixOrigin(rDoc, aMatOrigin);
2230 CPPUNIT_ASSERT_MESSAGE("Not a part of matrix formula.", bIsMatrix);
2231 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong matrix origin.", aMatRange.aStart, aMatOrigin);
2237 void ScExportTest::testInlineArrayXLS()
2239 createScDoc("xls/inline-array.xls");
2241 saveAndReload("MS Excel 97");
2243 ScDocument* pDoc = getScDoc();
2245 // B2:C3 contains a matrix.
2246 checkMatrixRange(*pDoc, ScRange(1, 1, 0, 2, 2, 0));
2248 // B5:D6 contains a matrix.
2249 checkMatrixRange(*pDoc, ScRange(1, 4, 0, 3, 5, 0));
2251 // B8:C10 as well.
2252 checkMatrixRange(*pDoc, ScRange(1, 7, 0, 2, 9, 0));
2255 void ScExportTest::testEmbeddedChartODS()
2257 createScDoc("xls/embedded-chart.xls");
2259 save("calc8");
2261 xmlDocUniquePtr pDoc = parseExport("content.xml");
2262 CPPUNIT_ASSERT(pDoc);
2263 assertXPath(pDoc,
2264 "/office:document-content/office:body/office:spreadsheet/table:table[2]/"
2265 "table:table-row[7]/table:table-cell[2]/draw:frame/draw:object",
2266 "notify-on-update-of-ranges",
2267 "Chart1.B3:Chart1.B5 Chart1.C2:Chart1.C2 Chart1.C3:Chart1.C5");
2270 void ScExportTest::testEmbeddedChartXLS()
2272 createScDoc("xls/embedded-chart.xls");
2274 saveAndReload("MS Excel 97");
2276 ScDocument* pDoc = getScDoc();
2278 // Make sure the 2nd sheet is named 'Chart1'.
2279 OUString aName;
2280 pDoc->GetName(1, aName);
2281 CPPUNIT_ASSERT_EQUAL(OUString("Chart1"), aName);
2283 const SdrOle2Obj* pOleObj = getSingleChartObject(*pDoc, 1);
2284 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve a chart object from the 2nd sheet.", pOleObj);
2286 ScRangeList aRanges = getChartRanges(*pDoc, *pOleObj);
2287 CPPUNIT_ASSERT_MESSAGE("Label range (B3:B5) not found.",
2288 aRanges.Contains(ScRange(1, 2, 1, 1, 4, 1)));
2289 CPPUNIT_ASSERT_MESSAGE("Data label (C2) not found.", aRanges.Contains(ScAddress(2, 1, 1)));
2290 CPPUNIT_ASSERT_MESSAGE("Data range (C3:C5) not found.",
2291 aRanges.Contains(ScRange(2, 2, 1, 2, 4, 1)));
2294 void ScExportTest::testCellAnchoredGroupXLS()
2296 createScDoc("xls/cell-anchored-group.xls");
2298 saveAndReload("calc8");
2300 // the document contains a group anchored on the first cell, make sure it's there in the right place
2301 ScDocument* pDoc = getScDoc();
2302 CPPUNIT_ASSERT_MESSAGE("There should be at least one sheet.", pDoc->GetTableCount() > 0);
2303 ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
2304 SdrPage* pPage = pDrawLayer->GetPage(0);
2305 CPPUNIT_ASSERT_MESSAGE("draw page for sheet 1 should exist.", pPage);
2306 const size_t nCount = pPage->GetObjCount();
2307 CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be 1 objects.", static_cast<size_t>(1), nCount);
2309 SdrObject* pObj = pPage->GetObj(0);
2310 CPPUNIT_ASSERT_MESSAGE("Failed to get drawing object.", pObj);
2311 ScDrawObjData* pData = ScDrawLayer::GetObjData(pObj);
2312 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData);
2313 CPPUNIT_ASSERT_MESSAGE("Upper left of bounding rectangle should be nonnegative.",
2314 pData->getShapeRect().Left() >= 0 || pData->getShapeRect().Top() >= 0);
2317 void ScExportTest::testFormulaReferenceXLS()
2319 createScDoc("xls/formula-reference.xls");
2321 saveAndReload("MS Excel 97");
2323 ScDocument* pDoc = getScDoc();
2325 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula in D2", OUString("=$A$2+$B$2+$C$2"),
2326 pDoc->GetFormula(3, 1, 0));
2327 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula in D3", OUString("=A3+B3+C3"),
2328 pDoc->GetFormula(3, 2, 0));
2329 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula in D6", OUString("=SUM($A$6:$C$6)"),
2330 pDoc->GetFormula(3, 5, 0));
2331 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula in D7", OUString("=SUM(A7:C7)"),
2332 pDoc->GetFormula(3, 6, 0));
2333 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula in D10", OUString("=$Two.$A$2+$Two.$B$2+$Two.$C$2"),
2334 pDoc->GetFormula(3, 9, 0));
2335 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula in D11", OUString("=$Two.A3+$Two.B3+$Two.C3"),
2336 pDoc->GetFormula(3, 10, 0));
2337 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula in D14", OUString("=MIN($Two.$A$2:$C$2)"),
2338 pDoc->GetFormula(3, 13, 0));
2339 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula in D15", OUString("=MAX($Two.A3:C3)"),
2340 pDoc->GetFormula(3, 14, 0));
2343 void ScExportTest::testSheetProtectionXLSX()
2345 createScDoc("xlsx/ProtecteSheet1234Pass.xlsx");
2347 saveAndReload("Calc Office Open XML");
2349 ScDocument* pDoc = getScDoc();
2350 const ScTableProtection* pTabProtect = pDoc->GetTabProtection(0);
2351 CPPUNIT_ASSERT(pTabProtect);
2352 Sequence<sal_Int8> aHash = pTabProtect->getPasswordHash(PASSHASH_XL);
2353 // check has
2354 if (aHash.getLength() >= 2)
2356 CPPUNIT_ASSERT_EQUAL(sal_uInt8(204), static_cast<sal_uInt8>(aHash[0]));
2357 CPPUNIT_ASSERT_EQUAL(sal_uInt8(61), static_cast<sal_uInt8>(aHash[1]));
2359 // we could flesh out this check I guess
2360 CPPUNIT_ASSERT(!pTabProtect->isOptionEnabled(ScTableProtection::OBJECTS));
2361 CPPUNIT_ASSERT(!pTabProtect->isOptionEnabled(ScTableProtection::SCENARIOS));
2364 void ScExportTest::testSheetProtectionXLSB()
2366 createScDoc("xlsb/tdf108017_calcProtection.xlsb");
2368 saveAndReload("Calc Office Open XML");
2370 ScDocument* pDoc = getScDoc();
2371 const ScTableProtection* pTabProtect = pDoc->GetTabProtection(0);
2372 CPPUNIT_ASSERT(pTabProtect);
2373 CPPUNIT_ASSERT(pTabProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS));
2374 CPPUNIT_ASSERT(!pTabProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS));
2377 namespace
2379 const char* toBorderName(SvxBorderLineStyle eStyle)
2381 switch (eStyle)
2383 case SvxBorderLineStyle::SOLID:
2384 return "SOLID";
2385 case SvxBorderLineStyle::DOTTED:
2386 return "DOTTED";
2387 case SvxBorderLineStyle::DASHED:
2388 return "DASHED";
2389 case SvxBorderLineStyle::DASH_DOT:
2390 return "DASH_DOT";
2391 case SvxBorderLineStyle::DASH_DOT_DOT:
2392 return "DASH_DOT_DOT";
2393 case SvxBorderLineStyle::DOUBLE_THIN:
2394 return "DOUBLE_THIN";
2395 case SvxBorderLineStyle::FINE_DASHED:
2396 return "FINE_DASHED";
2397 default:;
2400 return "";
2404 void ScExportTest::testExcelCellBorders(const OUString& sFormatType)
2406 static const struct
2408 SCROW mnRow;
2409 SvxBorderLineStyle mnStyle;
2410 tools::Long mnWidth;
2411 } aChecks[] = {
2412 { 1, SvxBorderLineStyle::SOLID, 1 }, // hair
2413 { 3, SvxBorderLineStyle::DOTTED, 15 }, // dotted
2414 { 5, SvxBorderLineStyle::DASH_DOT_DOT, 15 }, // dash dot dot
2415 { 7, SvxBorderLineStyle::DASH_DOT, 15 }, // dash dot
2416 { 9, SvxBorderLineStyle::FINE_DASHED, 15 }, // dashed
2417 { 11, SvxBorderLineStyle::SOLID, 15 }, // thin
2418 { 13, SvxBorderLineStyle::DASH_DOT_DOT, 35 }, // medium dash dot dot
2419 { 17, SvxBorderLineStyle::DASH_DOT, 35 }, // medium dash dot
2420 { 19, SvxBorderLineStyle::DASHED, 35 }, // medium dashed
2421 { 21, SvxBorderLineStyle::SOLID, 35 }, // medium
2422 { 23, SvxBorderLineStyle::SOLID, 50 }, // thick
2423 { 25, SvxBorderLineStyle::DOUBLE_THIN, -1 }, // double (don't check width)
2427 ScDocument* pDoc = getScDoc();
2429 for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
2431 const editeng::SvxBorderLine* pLine = nullptr;
2432 pDoc->GetBorderLines(2, aChecks[i].mnRow, 0, nullptr, &pLine, nullptr, nullptr);
2433 CPPUNIT_ASSERT(pLine);
2434 CPPUNIT_ASSERT_EQUAL(toBorderName(aChecks[i].mnStyle),
2435 toBorderName(pLine->GetBorderLineStyle()));
2436 if (aChecks[i].mnWidth >= 0)
2437 CPPUNIT_ASSERT_EQUAL(aChecks[i].mnWidth, pLine->GetWidth());
2441 saveAndReload(sFormatType);
2442 ScDocument* pDoc = getScDoc();
2443 for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
2445 const editeng::SvxBorderLine* pLine = nullptr;
2446 pDoc->GetBorderLines(2, aChecks[i].mnRow, 0, nullptr, &pLine, nullptr, nullptr);
2447 CPPUNIT_ASSERT(pLine);
2448 CPPUNIT_ASSERT_EQUAL(toBorderName(aChecks[i].mnStyle),
2449 toBorderName(pLine->GetBorderLineStyle()));
2450 if (aChecks[i].mnWidth >= 0)
2451 CPPUNIT_ASSERT_EQUAL(aChecks[i].mnWidth, pLine->GetWidth());
2455 void ScExportTest::testCellBordersXLS()
2457 createScDoc("xls/cell-borders.xls");
2458 testExcelCellBorders("MS Excel 97");
2461 void ScExportTest::testCellBordersXLSX()
2463 createScDoc("xlsx/cell-borders.xlsx");
2464 testExcelCellBorders("Calc Office Open XML");
2467 void ScExportTest::testBordersExchangeXLSX()
2469 // Document: sc/qa/unit/data/README.cellborders
2471 // short name for the table
2472 const SvxBorderLineStyle None = SvxBorderLineStyle::NONE;
2473 const SvxBorderLineStyle Solid = SvxBorderLineStyle::SOLID;
2474 const SvxBorderLineStyle Dotted = SvxBorderLineStyle::DOTTED;
2475 const SvxBorderLineStyle Dashed = SvxBorderLineStyle::DASHED;
2476 const SvxBorderLineStyle FineDash = SvxBorderLineStyle::FINE_DASHED;
2477 const SvxBorderLineStyle DashDot = SvxBorderLineStyle::DASH_DOT;
2478 const SvxBorderLineStyle DashDoDo = SvxBorderLineStyle::DASH_DOT_DOT;
2479 const SvxBorderLineStyle DoubThin = SvxBorderLineStyle::DOUBLE_THIN;
2481 const size_t nMaxCol = 18;
2482 const size_t nMaxRow = 7;
2484 static struct
2486 SvxBorderLineStyle BorderStyleTop, BorderStyleBottom;
2487 tools::Long WidthTop, WidthBottom;
2488 } aCheckBorderWidth[nMaxCol][nMaxRow]
2489 = { /* Width */
2490 /* 0,05 */ { { Solid, Solid, 1, 1 }, // SOLID
2491 { Dotted, Dotted, 15, 15 }, // DOTTED
2492 { Dotted, Dotted, 15, 15 }, // DASHED
2493 { FineDash, FineDash, 15, 15 }, // FINE_DASHED
2494 { FineDash, FineDash, 15, 15 }, // DASH_DOT
2495 { FineDash, FineDash, 15, 15 }, // DASH_DOT_DOT
2496 { None, None, 0, 0 } }, // DOUBLE_THIN
2497 /* 0,25 */
2498 { { Solid, Solid, 1, 1 },
2499 { Dotted, Dotted, 15, 15 },
2500 { Dotted, Dotted, 15, 15 },
2501 { FineDash, FineDash, 15, 15 },
2502 { FineDash, FineDash, 15, 15 },
2503 { FineDash, FineDash, 15, 15 },
2504 { None, None, 0, 0 } },
2505 /* 0,50 */
2506 { { Solid, Solid, 1, 1 },
2507 { Dotted, Dotted, 15, 15 },
2508 { Dotted, Dotted, 15, 15 },
2509 { FineDash, FineDash, 15, 15 },
2510 { FineDash, FineDash, 15, 15 },
2511 { FineDash, FineDash, 15, 15 },
2512 { None, None, 0, 0 } },
2513 /* 0,75 */
2514 { { Solid, Solid, 15, 15 },
2515 { Dotted, Dotted, 15, 15 },
2516 { FineDash, FineDash, 15, 15 },
2517 { FineDash, FineDash, 15, 15 },
2518 { DashDot, DashDot, 15, 15 },
2519 { DashDoDo, DashDoDo, 15, 15 },
2520 { DoubThin, DoubThin, 35, 35 } },
2521 /* 1,00 */
2522 { { Solid, Solid, 15, 15 },
2523 { Dotted, Dotted, 15, 15 },
2524 { FineDash, FineDash, 15, 15 },
2525 { FineDash, FineDash, 15, 15 },
2526 { DashDot, DashDot, 15, 15 },
2527 { DashDoDo, DashDoDo, 15, 15 },
2528 { DoubThin, DoubThin, 35, 35 } },
2529 /* 1,25 */
2530 { { Solid, Solid, 15, 15 },
2531 { Dotted, Dotted, 15, 15 },
2532 { FineDash, FineDash, 15, 15 },
2533 { FineDash, FineDash, 15, 15 },
2534 { DashDot, DashDot, 15, 15 },
2535 { DashDoDo, DashDoDo, 15, 15 },
2536 { DoubThin, DoubThin, 35, 35 } },
2537 /* 1,50 */
2538 { { Solid, Solid, 15, 15 },
2539 { Dotted, Dotted, 15, 15 },
2540 { FineDash, FineDash, 15, 15 },
2541 { FineDash, FineDash, 15, 15 },
2542 { DashDot, DashDot, 15, 15 },
2543 { DashDoDo, DashDoDo, 15, 15 },
2544 { DoubThin, DoubThin, 35, 35 } },
2546 /* 1,75 */
2547 { { Solid, Solid, 35, 35 },
2548 { FineDash, FineDash, 35, 35 },
2549 { Dashed, Dashed, 35, 35 },
2550 { FineDash, FineDash, 35, 35 },
2551 { DashDot, DashDot, 35, 35 },
2552 { DashDoDo, DashDoDo, 35, 35 },
2553 { DoubThin, DoubThin, 35, 35 } },
2554 /* 2,00 */
2555 { { Solid, Solid, 35, 35 },
2556 { FineDash, FineDash, 35, 35 },
2557 { Dashed, Dashed, 35, 35 },
2558 { FineDash, FineDash, 35, 35 },
2559 { DashDot, DashDot, 35, 35 },
2560 { DashDoDo, DashDoDo, 35, 35 },
2561 { DoubThin, DoubThin, 35, 35 } },
2562 /* 2,25 */
2563 { { Solid, Solid, 35, 35 },
2564 { FineDash, FineDash, 35, 35 },
2565 { Dashed, Dashed, 35, 35 },
2566 { FineDash, FineDash, 35, 35 },
2567 { DashDot, DashDot, 35, 35 },
2568 { DashDoDo, DashDoDo, 35, 35 },
2569 { DoubThin, DoubThin, 35, 35 } },
2571 /* 2,50 */
2572 { { Solid, Solid, 50, 50 },
2573 { FineDash, FineDash, 35, 35 },
2574 { Dashed, Dashed, 35, 35 },
2575 { FineDash, FineDash, 35, 35 },
2576 { DashDot, DashDot, 35, 35 },
2577 { DashDoDo, DashDoDo, 35, 35 },
2578 { DoubThin, DoubThin, 35, 35 } },
2579 /* 2,75 */
2580 { { Solid, Solid, 50, 50 },
2581 { FineDash, FineDash, 35, 35 },
2582 { Dashed, Dashed, 35, 35 },
2583 { FineDash, FineDash, 35, 35 },
2584 { DashDot, DashDot, 35, 35 },
2585 { DashDoDo, DashDoDo, 35, 35 },
2586 { DoubThin, DoubThin, 35, 35 } },
2587 /* 3,00 */
2588 { { Solid, Solid, 50, 50 },
2589 { FineDash, FineDash, 35, 35 },
2590 { Dashed, Dashed, 35, 35 },
2591 { FineDash, FineDash, 35, 35 },
2592 { DashDot, DashDot, 35, 35 },
2593 { DashDoDo, DashDoDo, 35, 35 },
2594 { DoubThin, DoubThin, 35, 35 } },
2595 /* 3,50 */
2596 { { Solid, Solid, 50, 50 },
2597 { FineDash, FineDash, 35, 35 },
2598 { Dashed, Dashed, 35, 35 },
2599 { FineDash, FineDash, 35, 35 },
2600 { DashDot, DashDot, 35, 35 },
2601 { DashDoDo, DashDoDo, 35, 35 },
2602 { DoubThin, DoubThin, 35, 35 } },
2603 /* 4,00 */
2604 { { Solid, Solid, 50, 50 },
2605 { FineDash, FineDash, 35, 35 },
2606 { Dashed, Dashed, 35, 35 },
2607 { FineDash, FineDash, 35, 35 },
2608 { DashDot, DashDot, 35, 35 },
2609 { DashDoDo, DashDoDo, 35, 35 },
2610 { DoubThin, DoubThin, 35, 35 } },
2611 /* 5,00 */
2612 { { Solid, Solid, 50, 50 },
2613 { FineDash, FineDash, 35, 35 },
2614 { Dashed, Dashed, 35, 35 },
2615 { FineDash, FineDash, 35, 35 },
2616 { DashDot, DashDot, 35, 35 },
2617 { DashDoDo, DashDoDo, 35, 35 },
2618 { DoubThin, DoubThin, 35, 35 } },
2619 /* 7,00 */
2620 { { Solid, Solid, 50, 50 },
2621 { FineDash, FineDash, 35, 35 },
2622 { Dashed, Dashed, 35, 35 },
2623 { FineDash, FineDash, 35, 35 },
2624 { DashDot, DashDot, 35, 35 },
2625 { DashDoDo, DashDoDo, 35, 35 },
2626 { DoubThin, DoubThin, 35, 35 } },
2627 /* 9,00 */
2628 { { Solid, Solid, 50, 50 },
2629 { FineDash, FineDash, 35, 35 },
2630 { Dashed, Dashed, 35, 35 },
2631 { FineDash, FineDash, 35, 35 },
2632 { DashDot, DashDot, 35, 35 },
2633 { DashDoDo, DashDoDo, 35, 35 },
2634 { DoubThin, DoubThin, 35, 35 } }
2637 createScDoc("ods/test_borders_export.ods");
2639 saveAndReload("Calc Office Open XML");
2640 ScDocument* pDoc = getScDoc();
2642 for (size_t nCol = 0; nCol < nMaxCol; ++nCol)
2644 for (size_t nRow = 0; nRow < nMaxRow; ++nRow)
2646 const editeng::SvxBorderLine* pLineTop = nullptr;
2647 const editeng::SvxBorderLine* pLineBottom = nullptr;
2648 pDoc->GetBorderLines(nCol + 2, (nRow * 2) + 8, 0, nullptr, &pLineTop, nullptr,
2649 &pLineBottom);
2650 if ((nCol < 3) && (nRow == 6))
2651 { // in this range no lines since minimum size to create a double is 0.5
2652 CPPUNIT_ASSERT(!pLineTop);
2653 CPPUNIT_ASSERT(!pLineBottom);
2654 continue;
2656 else
2658 CPPUNIT_ASSERT(pLineTop);
2659 CPPUNIT_ASSERT(pLineBottom);
2662 CPPUNIT_ASSERT_EQUAL_MESSAGE("Top Border-Line-Style wrong",
2663 aCheckBorderWidth[nCol][nRow].BorderStyleTop,
2664 pLineTop->GetBorderLineStyle());
2665 CPPUNIT_ASSERT_EQUAL_MESSAGE("Bottom Border-Line-Style wrong",
2666 aCheckBorderWidth[nCol][nRow].BorderStyleBottom,
2667 pLineBottom->GetBorderLineStyle());
2668 CPPUNIT_ASSERT_EQUAL_MESSAGE("Top Width-Line wrong",
2669 aCheckBorderWidth[nCol][nRow].WidthTop,
2670 pLineTop->GetWidth());
2671 CPPUNIT_ASSERT_EQUAL_MESSAGE("Bottom Width-Line wrong",
2672 aCheckBorderWidth[nCol][nRow].WidthBottom,
2673 pLineBottom->GetWidth());
2678 static OUString toString(const ScBigRange& rRange)
2680 OUStringBuffer aBuf;
2681 aBuf.append("(columns:");
2682 aBuf.append(rRange.aStart.Col());
2683 aBuf.append('-');
2684 aBuf.append(rRange.aEnd.Col());
2685 aBuf.append(";rows:");
2686 aBuf.append(rRange.aStart.Row());
2687 aBuf.append('-');
2688 aBuf.append(rRange.aEnd.Row());
2689 aBuf.append(";sheets:");
2690 aBuf.append(rRange.aStart.Tab());
2691 aBuf.append('-');
2692 aBuf.append(rRange.aEnd.Tab());
2693 aBuf.append(')');
2695 return aBuf.makeStringAndClear();
2698 void ScExportTest::testTrackChangesSimpleXLSX()
2700 struct CheckItem
2702 sal_uLong mnActionId;
2703 ScChangeActionType meType;
2705 sal_Int32 mnStartCol;
2706 sal_Int32 mnStartRow;
2707 sal_Int32 mnStartTab;
2708 sal_Int32 mnEndCol;
2709 sal_Int32 mnEndRow;
2710 sal_Int32 mnEndTab;
2712 bool mbRowInsertedAtBottom;
2715 struct
2717 bool checkRange(ScChangeActionType eType, const ScBigRange& rExpected,
2718 const ScBigRange& rActual)
2720 ScBigRange aExpected(rExpected), aActual(rActual);
2722 switch (eType)
2724 case SC_CAT_INSERT_ROWS:
2726 // Ignore columns.
2727 aExpected.aStart.SetCol(0);
2728 aExpected.aEnd.SetCol(0);
2729 aActual.aStart.SetCol(0);
2730 aActual.aEnd.SetCol(0);
2732 break;
2733 default:;
2736 return aExpected == aActual;
2739 bool check(ScDocument& rDoc)
2741 static const CheckItem aChecks[] = {
2742 { 1, SC_CAT_CONTENT, 1, 1, 0, 1, 1, 0, false },
2743 { 2, SC_CAT_INSERT_ROWS, 0, 2, 0, 0, 2, 0, true },
2744 { 3, SC_CAT_CONTENT, 1, 2, 0, 1, 2, 0, false },
2745 { 4, SC_CAT_INSERT_ROWS, 0, 3, 0, 0, 3, 0, true },
2746 { 5, SC_CAT_CONTENT, 1, 3, 0, 1, 3, 0, false },
2747 { 6, SC_CAT_INSERT_ROWS, 0, 4, 0, 0, 4, 0, true },
2748 { 7, SC_CAT_CONTENT, 1, 4, 0, 1, 4, 0, false },
2749 { 8, SC_CAT_INSERT_ROWS, 0, 5, 0, 0, 5, 0, true },
2750 { 9, SC_CAT_CONTENT, 1, 5, 0, 1, 5, 0, false },
2751 { 10, SC_CAT_INSERT_ROWS, 0, 6, 0, 0, 6, 0, true },
2752 { 11, SC_CAT_CONTENT, 1, 6, 0, 1, 6, 0, false },
2753 { 12, SC_CAT_INSERT_ROWS, 0, 7, 0, 0, 7, 0, true },
2754 { 13, SC_CAT_CONTENT, 1, 7, 0, 1, 7, 0, false },
2757 ScChangeTrack* pCT = rDoc.GetChangeTrack();
2758 if (!pCT)
2760 cerr << "Change track instance doesn't exist." << endl;
2761 return false;
2764 sal_uLong nActionMax = pCT->GetActionMax();
2765 if (nActionMax != 13)
2767 cerr << "Unexpected highest action ID value." << endl;
2768 return false;
2771 for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
2773 sal_uInt16 nActId = aChecks[i].mnActionId;
2774 const ScChangeAction* pAction = pCT->GetAction(nActId);
2775 if (!pAction)
2777 cerr << "No action for action number " << nActId << " found." << endl;
2778 return false;
2781 if (pAction->GetType() != aChecks[i].meType)
2783 cerr << "Unexpected action type for action number " << nActId << "." << endl;
2784 return false;
2787 const ScBigRange& rRange = pAction->GetBigRange();
2788 ScBigRange aCheck(aChecks[i].mnStartCol, aChecks[i].mnStartRow,
2789 aChecks[i].mnStartTab, aChecks[i].mnEndCol, aChecks[i].mnEndRow,
2790 aChecks[i].mnEndTab);
2792 if (!checkRange(pAction->GetType(), aCheck, rRange))
2794 cerr << "Unexpected range for action number " << nActId
2795 << ": expected=" << toString(aCheck) << " actual=" << toString(rRange)
2796 << endl;
2797 return false;
2800 switch (pAction->GetType())
2802 case SC_CAT_INSERT_ROWS:
2804 const ScChangeActionIns* p = static_cast<const ScChangeActionIns*>(pAction);
2805 if (p->IsEndOfList() != aChecks[i].mbRowInsertedAtBottom)
2807 cerr << "Unexpected end-of-list flag for action number " << nActId
2808 << "." << endl;
2809 return false;
2812 break;
2813 default:;
2817 return true;
2820 bool checkRevisionUserAndTime(ScDocument& rDoc, std::u16string_view rOwnerName)
2822 ScChangeTrack* pCT = rDoc.GetChangeTrack();
2823 if (!pCT)
2825 cerr << "Change track instance doesn't exist." << endl;
2826 return false;
2829 ScChangeAction* pAction = pCT->GetLast();
2830 if (pAction->GetUser() != "Kohei Yoshida")
2832 cerr << "Wrong user name." << endl;
2833 return false;
2836 DateTime aDT = pAction->GetDateTime();
2837 if (aDT.GetYear() != 2014 || aDT.GetMonth() != 7 || aDT.GetDay() != 11)
2839 cerr << "Wrong time stamp." << endl;
2840 return false;
2843 // Insert a new record to make sure the user and date-time are correct.
2844 rDoc.SetString(ScAddress(1, 8, 0), "New String");
2845 ScCellValue aEmpty;
2846 pCT->AppendContent(ScAddress(1, 8, 0), aEmpty);
2847 pAction = pCT->GetLast();
2848 if (!pAction)
2850 cerr << "Failed to retrieve last revision." << endl;
2851 return false;
2854 if (rOwnerName != pAction->GetUser())
2856 cerr << "Wrong user name." << endl;
2857 return false;
2860 DateTime aDTNew = pAction->GetDateTime();
2861 if (aDTNew <= aDT)
2863 cerr << "Time stamp of the new revision should be more recent than that of the "
2864 "last revision."
2865 << endl;
2866 return false;
2869 return true;
2872 } aTest;
2874 SvtUserOptions& rUserOpt = SC_MOD()->GetUserOptions();
2875 rUserOpt.SetToken(UserOptToken::FirstName, "Export");
2876 rUserOpt.SetToken(UserOptToken::LastName, "Test");
2878 OUString aOwnerName = rUserOpt.GetFirstName() + " " + rUserOpt.GetLastName();
2880 // First, test the xls variant.
2882 createScDoc("xls/track-changes/simple-cell-changes.xls");
2883 ScDocument* pDoc = getScDoc();
2884 bool bGood = aTest.check(*pDoc);
2885 CPPUNIT_ASSERT_MESSAGE("Initial check failed (xls).", bGood);
2887 saveAndReload("MS Excel 97");
2888 pDoc = getScDoc();
2889 bGood = aTest.check(*pDoc);
2890 CPPUNIT_ASSERT_MESSAGE("Check after reload failed (xls).", bGood);
2892 // fdo#81445 : Check the blank value string to make sure it's "<empty>".
2893 ScChangeTrack* pCT = pDoc->GetChangeTrack();
2894 CPPUNIT_ASSERT(pCT);
2895 ScChangeAction* pAction = pCT->GetAction(1);
2896 CPPUNIT_ASSERT(pAction);
2897 OUString aDesc = pAction->GetDescription(*pDoc);
2898 CPPUNIT_ASSERT_EQUAL(OUString("Cell B2 changed from '<empty>' to '1'"), aDesc);
2900 pDoc = getScDoc();
2901 bGood = aTest.checkRevisionUserAndTime(*pDoc, aOwnerName);
2902 CPPUNIT_ASSERT_MESSAGE("Check revision and time failed after reload (xls).", bGood);
2904 // Now, test the xlsx variant the same way.
2906 createScDoc("xlsx/track-changes/simple-cell-changes.xlsx");
2907 pDoc = getScDoc();
2908 aTest.check(*pDoc);
2909 CPPUNIT_ASSERT_MESSAGE("Initial check failed (xlsx).", bGood);
2911 saveAndReload("Calc Office Open XML");
2912 pDoc = getScDoc();
2913 bGood = aTest.check(*pDoc);
2914 CPPUNIT_ASSERT_MESSAGE("Check after reload failed (xlsx).", bGood);
2916 bGood = aTest.checkRevisionUserAndTime(*pDoc, aOwnerName);
2917 CPPUNIT_ASSERT_MESSAGE("Check revision and time failed after reload (xlsx).", bGood);
2920 void ScExportTest::testSheetTabColorsXLSX()
2922 struct
2924 bool checkContent(ScDocument& rDoc)
2926 std::vector<OUString> aTabNames = rDoc.GetAllTableNames();
2928 // green, red, blue, yellow (from left to right).
2929 if (aTabNames.size() != 4)
2931 cerr << "There should be exactly 4 sheets." << endl;
2932 return false;
2935 const char* pNames[] = { "Green", "Red", "Blue", "Yellow" };
2936 for (size_t i = 0; i < SAL_N_ELEMENTS(pNames); ++i)
2938 OUString aExpected = OUString::createFromAscii(pNames[i]);
2939 if (aExpected != aTabNames[i])
2941 cerr << "incorrect sheet name: expected='" << aExpected << "', actual='"
2942 << aTabNames[i] << "'" << endl;
2943 return false;
2947 static const Color aXclColors[] = {
2948 0x0000B050, // green
2949 0x00FF0000, // red
2950 0x000070C0, // blue
2951 0x00FFFF00, // yellow
2954 for (size_t i = 0; i < SAL_N_ELEMENTS(aXclColors); ++i)
2956 if (aXclColors[i] != rDoc.GetTabBgColor(i))
2958 cerr << "wrong sheet color for sheet " << i << endl;
2959 return false;
2963 return true;
2966 } aTest;
2968 createScDoc("xlsx/sheet-tab-color.xlsx");
2970 ScDocument* pDoc = getScDoc();
2971 bool bRes = aTest.checkContent(*pDoc);
2972 CPPUNIT_ASSERT_MESSAGE("Failed on the initial content check.", bRes);
2975 saveAndReload("Calc Office Open XML");
2976 ScDocument* pDoc = getScDoc();
2977 bool bRes = aTest.checkContent(*pDoc);
2978 CPPUNIT_ASSERT_MESSAGE("Failed on the content check after reload.", bRes);
2981 void ScExportTest::testTdf133487()
2983 createScDoc("fods/shapes_foreground_background.fods");
2985 save("calc8");
2986 xmlDocUniquePtr pXmlDoc = parseExport("content.xml");
2987 CPPUNIT_ASSERT(pXmlDoc);
2989 // shape in background has lowest index
2990 assertXPath(pXmlDoc,
2991 "/office:document-content/office:body/office:spreadsheet/table:table[1]/"
2992 "table:table-row[1]/table:table-cell[1]/draw:custom-shape",
2993 "z-index", "0");
2994 assertXPath(pXmlDoc,
2995 "/office:document-content/office:body/office:spreadsheet/table:table[1]/"
2996 "table:table-row[1]/table:table-cell[1]/draw:custom-shape"
2997 "/attribute::table:table-background",
2999 assertXPath(pXmlDoc,
3000 "/office:document-content/office:body/office:spreadsheet/table:table[1]/"
3001 "table:table-row[1]/table:table-cell[1]/draw:custom-shape",
3002 "table-background", "true");
3003 // shape in foreground, previously index 1
3004 assertXPath(pXmlDoc,
3005 "/office:document-content/office:body/office:spreadsheet/table:table[1]/"
3006 "table:table-row[1]/table:table-cell[2]/draw:custom-shape",
3007 "z-index", "2");
3008 // attribute is only written for value "true"
3009 assertXPath(pXmlDoc,
3010 "/office:document-content/office:body/office:spreadsheet/table:table[1]/"
3011 "table:table-row[1]/table:table-cell[2]/draw:custom-shape"
3012 "/attribute::table:table-background",
3014 // shape in foreground, previously index 0
3015 assertXPath(pXmlDoc,
3016 "/office:document-content/office:body/office:spreadsheet/table:table[1]/"
3017 "table:table-row[3]/table:table-cell[1]/draw:custom-shape",
3018 "z-index", "1");
3019 // attribute is only written for value "true"
3020 assertXPath(pXmlDoc,
3021 "/office:document-content/office:body/office:spreadsheet/table:table[1]/"
3022 "table:table-row[3]/table:table-cell[1]/draw:custom-shape"
3023 "/attribute::table:table-background",
3025 // shape in foreground, previously index 4
3026 assertXPath(pXmlDoc,
3027 "/office:document-content/office:body/office:spreadsheet/table:table[1]/"
3028 "table:shapes/draw:custom-shape",
3029 "z-index", "3");
3030 // attribute is only written for value "true"
3031 assertXPath(pXmlDoc,
3032 "/office:document-content/office:body/office:spreadsheet/table:table[1]/"
3033 "table:shapes/draw:custom-shape"
3034 "/attribute::table:table-background",
3036 // form control, previously index 3
3037 assertXPath(pXmlDoc,
3038 "/office:document-content/office:body/office:spreadsheet/table:table[1]/"
3039 "table:shapes/draw:control",
3040 "z-index", "4");
3041 // attribute is only written for value "true"
3042 assertXPath(pXmlDoc,
3043 "/office:document-content/office:body/office:spreadsheet/table:table[1]/"
3044 "table:shapes/draw:control"
3045 "/attribute::table:table-background",
3049 void ScExportTest::testSharedFormulaExportXLS()
3051 struct
3053 bool checkContent(ScDocument& rDoc)
3055 formula::FormulaGrammar::Grammar eGram = formula::FormulaGrammar::GRAM_ENGLISH_XL_R1C1;
3056 rDoc.SetGrammar(eGram);
3057 sc::TokenStringContext aCxt(rDoc, eGram);
3059 // Check the title row.
3061 OUString aActual = rDoc.GetString(0, 1, 0);
3062 OUString aExpected = "Response";
3063 if (aActual != aExpected)
3065 cerr << "Wrong content in A2: expected='" << aExpected << "', actual='" << aActual
3066 << "'" << endl;
3067 return false;
3070 aActual = rDoc.GetString(1, 1, 0);
3071 aExpected = "Response";
3072 if (aActual != aExpected)
3074 cerr << "Wrong content in B2: expected='" << aExpected << "', actual='" << aActual
3075 << "'" << endl;
3076 return false;
3079 // A3:A12 and B3:B12 are numbers from 1 to 10.
3080 for (SCROW i = 0; i <= 9; ++i)
3082 double fExpected = i + 1.0;
3083 ScAddress aPos(0, i + 2, 0);
3084 double fActual = rDoc.GetValue(aPos);
3085 if (fExpected != fActual)
3087 cerr << "Wrong value in A" << (i + 2) << ": expected=" << fExpected
3088 << ", actual=" << fActual << endl;
3089 return false;
3092 aPos.IncCol();
3093 ScFormulaCell* pFC = rDoc.GetFormulaCell(aPos);
3094 if (!pFC)
3096 cerr << "B" << (i + 2) << " should be a formula cell." << endl;
3097 return false;
3100 OUString aFormula = pFC->GetCode()->CreateString(aCxt, aPos);
3101 aExpected = "Coefficients!RC[-1]";
3102 if (aFormula != aExpected)
3104 cerr << "Wrong formula in B" << (i + 2) << ": expected='" << aExpected
3105 << "', actual='" << aFormula << "'" << endl;
3106 return false;
3109 fActual = rDoc.GetValue(aPos);
3110 if (fExpected != fActual)
3112 cerr << "Wrong value in B" << (i + 2) << ": expected=" << fExpected
3113 << ", actual=" << fActual << endl;
3114 return false;
3118 return true;
3121 } aTest;
3123 createScDoc("ods/shared-formula/3d-reference.ods");
3125 // Check the content of the original.
3126 ScDocument* pDoc = getScDoc();
3127 bool bRes = aTest.checkContent(*pDoc);
3128 CPPUNIT_ASSERT_MESSAGE("Content check on the original document failed.", bRes);
3131 saveAndReload("MS Excel 97");
3133 // Check the content of the reloaded. This should be identical.
3134 ScDocument* pDoc = getScDoc();
3135 bool bRes = aTest.checkContent(*pDoc);
3136 CPPUNIT_ASSERT_MESSAGE("Content check on the reloaded document failed.", bRes);
3139 void ScExportTest::testSharedFormulaExportXLSX()
3141 struct
3143 bool checkContent(ScDocument& rDoc)
3145 SCTAB nTabCount = rDoc.GetTableCount();
3146 if (nTabCount != 2)
3148 cerr << "Document should have exactly 2 sheets. " << nTabCount << " found."
3149 << endl;
3150 return false;
3153 // Make sure the sheet tab colors are not set.
3154 for (SCROW i = 0; i <= 1; ++i)
3156 Color aTabBgColor = rDoc.GetTabBgColor(i);
3157 if (aTabBgColor != COL_AUTO)
3159 cerr << "The tab color of Sheet " << (i + 1) << " should not be explicitly set."
3160 << endl;
3161 return false;
3165 // B2:B7 should show 1,2,3,4,5,6.
3166 double fExpected = 1.0;
3167 for (SCROW i = 1; i <= 6; ++i, ++fExpected)
3169 ScAddress aPos(1, i, 0);
3170 double fVal = rDoc.GetValue(aPos);
3171 if (fVal != fExpected)
3173 cerr << "Wrong value in B" << (i + 1) << ": expected=" << fExpected
3174 << ", actual=" << fVal << endl;
3175 return false;
3179 // C2:C7 should show 10,20,...,60.
3180 fExpected = 10.0;
3181 for (SCROW i = 1; i <= 6; ++i, fExpected += 10.0)
3183 ScAddress aPos(2, i, 0);
3184 double fVal = rDoc.GetValue(aPos);
3185 if (fVal != fExpected)
3187 cerr << "Wrong value in C" << (i + 1) << ": expected=" << fExpected
3188 << ", actual=" << fVal << endl;
3189 return false;
3193 // D2:D7 should show 1,2,...,6.
3194 fExpected = 1.0;
3195 for (SCROW i = 1; i <= 6; ++i, ++fExpected)
3197 ScAddress aPos(3, i, 0);
3198 double fVal = rDoc.GetValue(aPos);
3199 if (fVal != fExpected)
3201 cerr << "Wrong value in D" << (i + 1) << ": expected=" << fExpected
3202 << ", actual=" << fVal << endl;
3203 return false;
3207 return true;
3210 } aTest;
3212 createScDoc("xlsx/shared-formula/3d-reference.xlsx");
3214 ScDocument* pDoc = getScDoc();
3215 bool bRes = aTest.checkContent(*pDoc);
3216 CPPUNIT_ASSERT_MESSAGE("Content check on the initial document failed.", bRes);
3218 pDoc->CalcAll(); // Recalculate to flush all cached results.
3219 bRes = aTest.checkContent(*pDoc);
3220 CPPUNIT_ASSERT_MESSAGE("Content check on the initial recalculated document failed.", bRes);
3223 // Save and reload, and check the content again.
3224 saveAndReload("Calc Office Open XML");
3226 ScDocument* pDoc = getScDoc();
3227 pDoc->CalcAll(); // Recalculate to flush all cached results.
3229 bool bRes = aTest.checkContent(*pDoc);
3230 CPPUNIT_ASSERT_MESSAGE("Content check on the reloaded document failed.", bRes);
3233 void ScExportTest::testSharedFormulaStringResultExportXLSX()
3235 struct
3237 bool checkContent(ScDocument& rDoc)
3240 // B2:B7 should show A,B,...,F.
3241 const char* const expected[] = { "A", "B", "C", "D", "E", "F" };
3242 for (SCROW i = 0; i <= 5; ++i)
3244 ScAddress aPos(1, i + 1, 0);
3245 OUString aStr = rDoc.GetString(aPos);
3246 OUString aExpected = OUString::createFromAscii(expected[i]);
3247 if (aStr != aExpected)
3249 cerr << "Wrong value in B" << (i + 2) << ": expected='" << aExpected
3250 << "', actual='" << aStr << "'" << endl;
3251 return false;
3257 // C2:C7 should show AA,BB,...,FF.
3258 const char* const expected[] = { "AA", "BB", "CC", "DD", "EE", "FF" };
3259 for (SCROW i = 0; i <= 5; ++i)
3261 ScAddress aPos(2, i + 1, 0);
3262 OUString aStr = rDoc.GetString(aPos);
3263 OUString aExpected = OUString::createFromAscii(expected[i]);
3264 if (aStr != aExpected)
3266 cerr << "Wrong value in C" << (i + 2) << ": expected='" << aExpected
3267 << "', actual='" << aStr << "'" << endl;
3268 return false;
3273 return true;
3276 } aTest;
3278 createScDoc("xlsx/shared-formula/text-results.xlsx");
3280 ScDocument* pDoc = getScDoc();
3282 // Check content without re-calculation, to test cached formula results.
3283 bool bRes = aTest.checkContent(*pDoc);
3284 CPPUNIT_ASSERT_MESSAGE("Content check on the initial document failed.", bRes);
3286 // Now, re-calculate and check the results.
3287 pDoc->CalcAll();
3288 bRes = aTest.checkContent(*pDoc);
3289 CPPUNIT_ASSERT_MESSAGE("Content check on the initial recalculated document failed.", bRes);
3291 // Reload and check again.
3292 saveAndReload("Calc Office Open XML");
3293 ScDocument* pDoc = getScDoc();
3295 bool bRes = aTest.checkContent(*pDoc);
3296 CPPUNIT_ASSERT_MESSAGE("Content check on the reloaded document failed.", bRes);
3299 void ScExportTest::testFunctionsExcel2010(const OUString& sFormatType)
3301 createScDoc("xlsx/functions-excel-2010.xlsx");
3303 saveAndReload(sFormatType);
3304 ScDocument* pDoc = getScDoc();
3305 pDoc->CalcAll(); // perform hard re-calculation.
3307 testFunctionsExcel2010_Impl(*pDoc);
3310 void ScExportTest::testFunctionsExcel2010XLSX() { testFunctionsExcel2010("Calc Office Open XML"); }
3312 void ScExportTest::testFunctionsExcel2010XLS() { testFunctionsExcel2010("MS Excel 97"); }
3314 void ScExportTest::testCeilingFloor(const OUString& sFormatType)
3316 createScDoc("xlsx/ceiling-floor.xlsx");
3318 saveAndReload(sFormatType);
3319 ScDocument* pDoc = getScDoc();
3320 pDoc->CalcAll(); // perform hard re-calculation.
3322 testCeilingFloor_Impl(*pDoc);
3325 void ScExportTest::testCeilingFloorXLSX() { testCeilingFloor("Calc Office Open XML"); }
3327 void ScExportTest::testCeilingFloorODSToXLSX()
3329 // tdf#100011 - Cannot open sheet containing FLOOR/CEILING functions by MS Excel, after export to .xlsx
3330 createScDoc("ods/ceiling-floor.ods");
3332 save("Calc Office Open XML");
3333 xmlDocUniquePtr pSheet = parseExport("xl/workbook.xml");
3334 CPPUNIT_ASSERT(pSheet);
3336 // there shouldn't be any defined names during export of FLOOR and CEILING functions to .xlsx
3337 assertXPath(pSheet, "/x:workbook/x:definedNames", 0);
3340 void ScExportTest::testCeilingFloorXLS() { testCeilingFloor("MS Excel 97"); }
3342 void ScExportTest::testCeilingFloorODS() { testCeilingFloor("calc8"); }
3344 void ScExportTest::testCustomXml()
3346 // Load document and export it to a temporary file
3347 createScDoc("xlsx/customxml.xlsx");
3349 save("Calc Office Open XML");
3350 xmlDocUniquePtr pXmlDoc = parseExport("customXml/item1.xml");
3351 CPPUNIT_ASSERT(pXmlDoc);
3352 xmlDocUniquePtr pRelsDoc = parseExport("customXml/_rels/item1.xml.rels");
3353 CPPUNIT_ASSERT(pRelsDoc);
3355 // Check there is a relation to itemProps1.xml.
3356 assertXPath(pRelsDoc, "/rels:Relationships/rels:Relationship", 1);
3357 assertXPath(pRelsDoc, "/rels:Relationships/rels:Relationship[@Id='rId1']", "Target",
3358 "itemProps1.xml");
3360 std::unique_ptr<SvStream> pStream = parseExportStream(maTempFile.GetURL(), "ddp/ddpfile.xen");
3361 CPPUNIT_ASSERT(pStream);
3364 #ifdef _WIN32
3365 static sal_Unicode lcl_getWindowsDrive(const OUString& aURL)
3367 static const sal_Int32 nMinLen = strlen("file:///X:/");
3368 if (aURL.getLength() <= nMinLen)
3369 return 0;
3370 const OUString aUrlStart = aURL.copy(0, nMinLen);
3371 return (aUrlStart.startsWith("file:///") && aUrlStart.endsWith(":/")) ? aUrlStart[8] : 0;
3373 #endif
3375 void ScExportTest::testRelativePathsODS()
3377 createScDoc("ods/fdo79305.ods");
3379 save("calc8");
3380 xmlDocUniquePtr pDoc = parseExport("content.xml");
3381 CPPUNIT_ASSERT(pDoc);
3382 OUString aURL = getXPath(pDoc,
3383 "/office:document-content/office:body/office:spreadsheet/table:table/"
3384 "table:table-row[2]/table:table-cell[2]/text:p/text:a",
3385 "href");
3386 #ifdef _WIN32
3387 // if the exported document is not on the same drive then the linked document,
3388 // there is no way to get a relative URL for the link, because ../X:/ is undefined.
3389 if (!aURL.startsWith(".."))
3391 sal_Unicode aDocDrive = lcl_getWindowsDrive(maTempFile.GetURL());
3392 sal_Unicode aLinkDrive = lcl_getWindowsDrive(aURL);
3393 CPPUNIT_ASSERT_MESSAGE("document on the same drive but no relative link!", aDocDrive != 0);
3394 CPPUNIT_ASSERT_MESSAGE("document on the same drive but no relative link!", aLinkDrive != 0);
3395 CPPUNIT_ASSERT_MESSAGE("document on the same drive but no relative link!",
3396 aDocDrive != aLinkDrive);
3397 return;
3399 #endif
3400 // make sure that the URL is relative
3401 CPPUNIT_ASSERT(aURL.startsWith(".."));
3404 namespace
3406 void testSheetProtection_Impl(ScDocument& rDoc)
3408 CPPUNIT_ASSERT(rDoc.IsTabProtected(0));
3409 const ScTableProtection* pTabProtection = rDoc.GetTabProtection(0);
3410 CPPUNIT_ASSERT(pTabProtection);
3411 CPPUNIT_ASSERT(pTabProtection->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS));
3412 CPPUNIT_ASSERT(!pTabProtection->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS));
3416 void ScExportTest::testSheetProtectionODS()
3418 createScDoc("ods/sheet-protection.ods");
3420 ScDocument* pDoc = getScDoc();
3422 testSheetProtection_Impl(*pDoc);
3424 saveAndReload("calc8");
3426 pDoc = getScDoc();
3428 testSheetProtection_Impl(*pDoc);
3431 void ScExportTest::testFunctionsExcel2010ODS()
3433 //testFunctionsExcel2010("calc8");
3436 void ScExportTest::testSwappedOutImageExport()
3438 std::vector<OUString> aFilterNames{ "calc8", "MS Excel 97", "Calc Office Open XML" };
3440 // Set cache size to a very small value to make sure one of the images is swapped out
3441 std::shared_ptr<comphelper::ConfigurationChanges> xBatch(
3442 comphelper::ConfigurationChanges::create());
3443 officecfg::Office::Common::Cache::GraphicManager::TotalCacheSize::set(sal_Int32(1), xBatch);
3444 xBatch->commit();
3446 for (size_t i = 0; i < aFilterNames.size(); ++i)
3448 // Check whether the export code swaps in the image which was swapped out before.
3449 createScDoc("ods/document_with_two_images.ods");
3451 const OString sFailedMessage
3452 = OString::Concat("Failed on filter: ") + aFilterNames[i].toUtf8();
3454 // Export the document and import again for a check
3455 saveAndReload(aFilterNames[i]);
3457 // Check whether graphic exported well after it was swapped out
3458 uno::Reference<sheet::XSpreadsheetDocument> xDoc(mxComponent, UNO_QUERY_THROW);
3459 uno::Reference<container::XIndexAccess> xIA(xDoc->getSheets(), UNO_QUERY_THROW);
3460 uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xIA->getByIndex(0),
3461 UNO_QUERY_THROW);
3462 uno::Reference<container::XIndexAccess> xDraws(xDrawPageSupplier->getDrawPage(),
3463 UNO_QUERY_THROW);
3464 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(2),
3465 xDraws->getCount());
3467 uno::Reference<drawing::XShape> xImage(xDraws->getByIndex(0), uno::UNO_QUERY);
3468 uno::Reference<beans::XPropertySet> XPropSet(xImage, uno::UNO_QUERY_THROW);
3470 // Check Graphic, Size
3472 uno::Reference<graphic::XGraphic> xGraphic;
3473 XPropSet->getPropertyValue("Graphic") >>= xGraphic;
3474 CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xGraphic.is());
3475 CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(),
3476 xGraphic->getType() != graphic::GraphicType::EMPTY);
3477 uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
3478 CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xBitmap.is());
3479 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(610),
3480 xBitmap->getSize().Width);
3481 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(381),
3482 xBitmap->getSize().Height);
3484 // Second Image
3485 xImage.set(xDraws->getByIndex(1), uno::UNO_QUERY);
3486 XPropSet.set(xImage, uno::UNO_QUERY_THROW);
3488 // Check Graphic, Size
3490 uno::Reference<graphic::XGraphic> xGraphic;
3491 XPropSet->getPropertyValue("Graphic") >>= xGraphic;
3492 CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xGraphic.is());
3493 CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(),
3494 xGraphic->getType() != graphic::GraphicType::EMPTY);
3495 uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
3496 CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xBitmap.is());
3497 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(900),
3498 xBitmap->getSize().Width);
3499 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(600),
3500 xBitmap->getSize().Height);
3505 void ScExportTest::testSupBookVirtualPathXLS()
3507 createScDoc("xls/external-ref.xls");
3509 saveAndReload("MS Excel 97");
3511 ScDocument* pDoc = getScDoc();
3513 OUString aFormula = pDoc->GetFormula(0, 0, 0);
3514 #ifdef _WIN32
3515 aFormula = OUString::Concat(aFormula.subView(0, 9)) + aFormula.subView(12);
3516 // strip drive letter, e.g. 'C:/'
3517 #endif
3518 CPPUNIT_ASSERT_EQUAL_MESSAGE(
3519 "Wrong SupBook VirtualPath URL",
3520 OUString("='file:///home/timar/Documents/external.xls'#$Sheet1.A1"), aFormula);
3523 void ScExportTest::testLinkedGraphicRT()
3525 // Problem was with linked images
3526 std::vector<OUString> aFilterNames{ "calc8", "MS Excel 97", "Calc Office Open XML" };
3528 for (size_t i = 0; i < aFilterNames.size(); ++i)
3530 // Load the original file with one image
3531 createScDoc("ods/document_with_linked_graphic.ods");
3532 const OString sFailedMessage
3533 = OString::Concat("Failed on filter: ") + aFilterNames[i].toUtf8();
3535 // Export the document and import again for a check
3536 saveAndReload(aFilterNames[i]);
3538 // Check whether graphic imported well after export
3539 ScDocument* pDoc = getScDoc();
3540 ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
3541 CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pDrawLayer != nullptr);
3542 const SdrPage* pPage = pDrawLayer->GetPage(0);
3543 CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pPage != nullptr);
3544 SdrGrafObj* pObject = dynamic_cast<SdrGrafObj*>(pPage->GetObj(0));
3545 CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pObject != nullptr);
3546 if (aFilterNames[i] == "Calc Office Open XML")
3548 // FIXME: tdf#152036
3549 CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), !pObject->IsLinkedGraphic());
3551 else
3552 CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pObject->IsLinkedGraphic());
3554 const GraphicObject& rGraphicObj = pObject->GetGraphicObject(true);
3555 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), int(GraphicType::Bitmap),
3556 int(rGraphicObj.GetGraphic().GetType()));
3557 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_uLong(864900),
3558 rGraphicObj.GetGraphic().GetSizeBytes());
3562 void ScExportTest::testImageWithSpecialID()
3564 std::vector<OUString> aFilterNames{ "calc8", "MS Excel 97", "Calc Office Open XML" };
3566 // Trigger swap out mechanism to test swapped state factor too.
3567 std::shared_ptr<comphelper::ConfigurationChanges> batch(
3568 comphelper::ConfigurationChanges::create());
3569 officecfg::Office::Common::Cache::GraphicManager::TotalCacheSize::set(sal_Int32(1), batch);
3570 batch->commit();
3572 for (size_t i = 0; i < aFilterNames.size(); ++i)
3574 createScDoc("ods/images_with_special_IDs.ods");
3576 const OString sFailedMessage
3577 = OString::Concat("Failed on filter: ") + aFilterNames[i].toUtf8();
3579 // Export the document and import again for a check
3580 saveAndReload(aFilterNames[i]);
3582 // Check whether graphic was exported well
3583 uno::Reference<sheet::XSpreadsheetDocument> xDoc(mxComponent, UNO_QUERY_THROW);
3584 uno::Reference<container::XIndexAccess> xIA(xDoc->getSheets(), UNO_QUERY_THROW);
3585 uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xIA->getByIndex(0),
3586 UNO_QUERY_THROW);
3587 uno::Reference<container::XIndexAccess> xDraws(xDrawPageSupplier->getDrawPage(),
3588 UNO_QUERY_THROW);
3589 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(2),
3590 xDraws->getCount());
3592 uno::Reference<drawing::XShape> xImage(xDraws->getByIndex(0), uno::UNO_QUERY);
3593 uno::Reference<beans::XPropertySet> XPropSet(xImage, uno::UNO_QUERY_THROW);
3595 // Check Graphic, Size
3597 uno::Reference<graphic::XGraphic> xGraphic;
3598 XPropSet->getPropertyValue("Graphic") >>= xGraphic;
3599 CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xGraphic.is());
3600 CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(),
3601 xGraphic->getType() != graphic::GraphicType::EMPTY);
3602 uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
3603 CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xBitmap.is());
3604 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(610),
3605 xBitmap->getSize().Width);
3606 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(381),
3607 xBitmap->getSize().Height);
3609 // Second Image
3610 xImage.set(xDraws->getByIndex(1), uno::UNO_QUERY);
3611 XPropSet.set(xImage, uno::UNO_QUERY_THROW);
3613 // Check Graphic, Size
3615 uno::Reference<graphic::XGraphic> xGraphic;
3616 XPropSet->getPropertyValue("Graphic") >>= xGraphic;
3617 CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xGraphic.is());
3618 CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(),
3619 xGraphic->getType() != graphic::GraphicType::EMPTY);
3620 uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
3621 CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xBitmap.is());
3622 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(900),
3623 xBitmap->getSize().Width);
3624 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(600),
3625 xBitmap->getSize().Height);
3630 void ScExportTest::testAbsNamedRangeHTML()
3632 setImportFilterName("calc_HTML_WebQuery");
3633 createScDoc("html/numberformat.html");
3634 ScDocShell* pDocSh = getScDocShell();
3635 pDocSh->DoHardRecalc();
3637 //reset import filter
3638 setImportFilterName("calc8");
3639 saveAndReload("calc8");
3640 pDocSh = getScDocShell();
3641 pDocSh->DoHardRecalc();
3643 ScDocument* pDoc = getScDoc();
3644 ScRangeData* pRangeData = pDoc->GetRangeName()->findByUpperName(OUString("HTML_1"));
3645 ScSingleRefData* pRef = pRangeData->GetCode()->FirstToken()->GetSingleRef();
3646 // see tdf#119141 for the reason why this isn't Sheet1.HTML_1
3647 CPPUNIT_ASSERT_MESSAGE("HTML_1 is an absolute reference", !pRef->IsTabRel());
3650 void ScExportTest::testTdf80149()
3652 createScDoc("csv/tdf80149.csv");
3653 ScDocShell* pDocSh = getScDocShell();
3654 pDocSh->DoHardRecalc();
3655 saveAndReload("Calc Office Open XML");
3656 pDocSh = getScDocShell();
3657 pDocSh->DoHardRecalc();
3659 ScDocument* pDoc = getScDoc();
3660 CPPUNIT_ASSERT_EQUAL(OUString("row 1"), pDoc->GetString(0, 0, 0));
3662 // Without the fix in place, this test would have failed with
3663 // - Expected: Character 0x16 is here ->>\x16<<--
3664 // - Actual :
3665 CPPUNIT_ASSERT_EQUAL(OUString("Character 0x16 is here ->>\x16<<--"), pDoc->GetString(1, 0, 0));
3666 CPPUNIT_ASSERT_EQUAL(OUString("File opens in libre office, but can't be saved as xlsx"),
3667 pDoc->GetString(2, 0, 0));
3668 CPPUNIT_ASSERT_EQUAL(OUString("row 2"), pDoc->GetString(0, 1, 0));
3669 CPPUNIT_ASSERT_EQUAL(OUString("Subsequent rows get truncated"), pDoc->GetString(1, 1, 0));
3670 CPPUNIT_ASSERT_EQUAL(OUString("This cell goes missing"), pDoc->GetString(2, 1, 0));
3671 CPPUNIT_ASSERT_EQUAL(OUString("row 3"), pDoc->GetString(0, 2, 0));
3672 CPPUNIT_ASSERT_EQUAL(OUString("Subsequent rows get truncated"), pDoc->GetString(1, 2, 0));
3673 CPPUNIT_ASSERT_EQUAL(OUString("This cell goes missing"), pDoc->GetString(2, 2, 0));
3676 void ScExportTest::testSheetLocalRangeNameXLS()
3678 createScDoc("xls/named-ranges-local.xls");
3679 ScDocShell* pDocSh = getScDocShell();
3680 pDocSh->DoHardRecalc();
3681 saveAndReload("MS Excel 97");
3682 pDocSh = getScDocShell();
3683 pDocSh->DoHardRecalc();
3685 ScDocument* pDoc = getScDoc();
3686 ScRangeName* pRangeName = pDoc->GetRangeName(0);
3687 CPPUNIT_ASSERT(pRangeName);
3688 CPPUNIT_ASSERT_EQUAL(size_t(2), pRangeName->size());
3690 OUString aFormula = pDoc->GetFormula(3, 11, 0);
3691 CPPUNIT_ASSERT_EQUAL(OUString("=SUM(local_name2)"), aFormula);
3692 ASSERT_DOUBLES_EQUAL(14.0, pDoc->GetValue(3, 11, 0));
3694 aFormula = pDoc->GetFormula(6, 4, 0);
3695 CPPUNIT_ASSERT_EQUAL(OUString("=local_name1"), aFormula);
3698 void ScExportTest::testRelativeNamedExpressionsXLS()
3700 createScDoc("ods/tdf113991_relativeNamedRanges.ods");
3701 ScDocShell* pDocSh = getScDocShell();
3702 pDocSh->DoHardRecalc();
3703 saveAndReload("MS Excel 97");
3704 pDocSh = getScDocShell();
3705 pDocSh->DoHardRecalc();
3707 ScDocument* pDoc = getScDoc();
3708 // Sheet1:G3
3709 ScAddress aPos(6, 2, 0);
3710 CPPUNIT_ASSERT_EQUAL(1.0, pDoc->GetValue(aPos));
3711 CPPUNIT_ASSERT_EQUAL(OUString("=single_cell_A3"),
3712 pDoc->GetFormula(aPos.Col(), aPos.Row(), aPos.Tab()));
3713 // Sheet2:F6
3714 aPos = ScAddress(5, 5, 1);
3715 CPPUNIT_ASSERT_EQUAL(18.0, pDoc->GetValue(aPos));
3716 CPPUNIT_ASSERT_EQUAL(OUString("=SUM(test_conflict)"),
3717 pDoc->GetFormula(aPos.Col(), aPos.Row(), aPos.Tab()));
3718 // Sheet2:H3
3719 aPos = ScAddress(7, 2, 1);
3720 CPPUNIT_ASSERT_EQUAL(10.0, pDoc->GetValue(aPos));
3721 CPPUNIT_ASSERT_EQUAL(OUString("=single_global_A3"),
3722 pDoc->GetFormula(aPos.Col(), aPos.Row(), aPos.Tab()));
3723 // Sheet2:H6
3724 aPos = ScAddress(7, 5, 1);
3725 CPPUNIT_ASSERT_EQUAL(75.0, pDoc->GetValue(aPos));
3726 CPPUNIT_ASSERT_EQUAL(OUString("=SUM(A6:F6)"),
3727 pDoc->GetFormula(aPos.Col(), aPos.Row(), aPos.Tab()));
3730 void ScExportTest::testSheetTextBoxHyperlinkXLSX()
3732 createScDoc("xlsx/textbox-hyperlink.xlsx");
3734 save("Calc Office Open XML");
3735 xmlDocUniquePtr pDoc = parseExport("xl/drawings/drawing1.xml");
3736 CPPUNIT_ASSERT(pDoc);
3738 assertXPath(
3739 pDoc,
3740 "/xdr:wsDr[1]/xdr:twoCellAnchor[1]/xdr:sp[1]/xdr:nvSpPr[1]/xdr:cNvPr[1]/a:hlinkClick[1]",
3744 void ScExportTest::testFontSizeXLSX()
3746 createScDoc("xlsx/fontSize.xlsx");
3748 save("Calc Office Open XML");
3749 xmlDocUniquePtr pDoc = parseExport("xl/drawings/drawing1.xml");
3750 CPPUNIT_ASSERT(pDoc);
3751 OUString fontSize = getXPath(
3752 pDoc, "/xdr:wsDr/xdr:twoCellAnchor/xdr:sp[1]/xdr:txBody/a:p[1]/a:r[1]/a:rPr", "sz");
3753 // make sure that the font size is 18
3754 CPPUNIT_ASSERT_EQUAL(OUString("1800"), fontSize);
3757 void ScExportTest::testSheetCharacterKerningSpaceXLSX()
3759 createScDoc("xlsx/textbox-CharKerningSpace.xlsx");
3761 saveAndReload("Calc Office Open XML");
3763 save("Calc Office Open XML");
3764 xmlDocUniquePtr pDoc = parseExport("xl/drawings/drawing1.xml");
3765 CPPUNIT_ASSERT(pDoc);
3767 OUString CharKerningSpace = getXPath(
3768 pDoc, "/xdr:wsDr[1]/xdr:twoCellAnchor[1]/xdr:sp[1]/xdr:txBody[1]/a:p[1]/a:r[1]/a:rPr[1]",
3769 "spc");
3771 // make sure that the CharKerning is 1997.
3772 CPPUNIT_ASSERT_EQUAL(OUString("1997"), CharKerningSpace);
3775 void ScExportTest::testSheetCondensedCharacterSpaceXLSX()
3777 createScDoc("xlsx/textbox-CondensedCharacterSpace.xlsx");
3779 save("Calc Office Open XML");
3780 xmlDocUniquePtr pDoc = parseExport("xl/drawings/drawing1.xml");
3781 CPPUNIT_ASSERT(pDoc);
3783 OUString CondensedCharSpace = getXPath(
3784 pDoc, "/xdr:wsDr[1]/xdr:twoCellAnchor[1]/xdr:sp[1]/xdr:txBody[1]/a:p[1]/a:r[1]/a:rPr[1]",
3785 "spc");
3787 // make sure that the CondensedCharSpace is -1002.
3788 CPPUNIT_ASSERT_EQUAL(OUString("-1002"), CondensedCharSpace);
3791 void ScExportTest::testTextUnderlineColorXLSX()
3793 createScDoc("xlsx/underlineColor.xlsx");
3795 save("Calc Office Open XML");
3796 xmlDocUniquePtr pDoc = parseExport("xl/drawings/drawing1.xml");
3797 CPPUNIT_ASSERT(pDoc);
3798 // Make sure the underline type is double line
3799 assertXPath(pDoc, "/xdr:wsDr/xdr:twoCellAnchor[1]/xdr:sp[1]/xdr:txBody/a:p[1]/a:r[1]/a:rPr",
3800 "u", "dbl");
3802 assertXPath(pDoc, "/xdr:wsDr/xdr:twoCellAnchor[1]/xdr:sp[1]/xdr:txBody/a:p[1]/a:r[1]/a:rPr",
3803 "b", "1");
3804 // Make sure that the underline color is RED
3805 assertXPath(pDoc,
3806 "/xdr:wsDr/xdr:twoCellAnchor[1]/xdr:sp[1]/xdr:txBody/a:p[1]/a:r[1]/a:rPr/a:uFill/"
3807 "a:solidFill/a:srgbClr",
3808 "val", "ff0000");
3810 // Make sure the underline type is drawn with heavy line
3811 assertXPath(pDoc, "/xdr:wsDr/xdr:twoCellAnchor[2]/xdr:sp[1]/xdr:txBody/a:p[1]/a:r[1]/a:rPr",
3812 "u", "heavy");
3813 // tdf#104219 Make sure that uFill is not existing and uFillTx is set.
3814 // It mean that color is automatic, should be the same color as the text.
3815 assertXPath(
3816 pDoc, "/xdr:wsDr/xdr:twoCellAnchor[2]/xdr:sp[1]/xdr:txBody/a:p[1]/a:r[1]/a:rPr/a:uFill", 0);
3817 assertXPath(pDoc,
3818 "/xdr:wsDr/xdr:twoCellAnchor[2]/xdr:sp[1]/xdr:txBody/a:p[1]/a:r[1]/a:rPr/a:uFillTx",
3822 void ScExportTest::testSheetRunParagraphPropertyXLSX()
3824 createScDoc("xlsx/TextColor.xlsx");
3826 save("Calc Office Open XML");
3827 xmlDocUniquePtr pDoc = parseExport("xl/sharedStrings.xml");
3828 CPPUNIT_ASSERT(pDoc);
3830 OUString aColor = getXPath(pDoc, "/x:sst/x:si/x:r[1]/x:rPr[1]/x:color", "rgb");
3831 CPPUNIT_ASSERT_EQUAL(OUString("FFFF0000"), aColor);
3834 void ScExportTest::testPreserveTextWhitespaceXLSX()
3836 createScDoc("xlsx/preserve-whitespace.xlsx");
3838 save("Calc Office Open XML");
3839 xmlDocUniquePtr pDoc = parseExport("xl/sharedStrings.xml");
3840 CPPUNIT_ASSERT(pDoc);
3841 assertXPath(pDoc, "/x:sst/x:si/x:t", "space", "preserve");
3844 void ScExportTest::testPreserveTextWhitespace2XLSX()
3846 createScDoc("xlsx/preserve_space.xlsx");
3848 save("Calc Office Open XML");
3849 xmlDocUniquePtr pDoc = parseExport("xl/sharedStrings.xml");
3850 CPPUNIT_ASSERT(pDoc);
3851 assertXPath(pDoc, "/x:sst/x:si[1]/x:t", "space", "preserve");
3852 assertXPath(pDoc, "/x:sst/x:si[2]/x:r[1]/x:t", "space", "preserve");
3853 assertXPath(pDoc, "/x:sst/x:si[2]/x:r[2]/x:t", "space", "preserve");
3856 void ScExportTest::testHiddenShapeXLS()
3858 createScDoc("xls/hiddenShape.xls");
3860 ScDocument* pDoc = getScDoc();
3861 CPPUNIT_ASSERT(pDoc->GetTableCount() > 0);
3862 ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
3863 SdrPage* pPage = pDrawLayer->GetPage(0);
3864 CPPUNIT_ASSERT(pPage);
3865 SdrObject* pObj = pPage->GetObj(0);
3866 CPPUNIT_ASSERT(pObj);
3867 CPPUNIT_ASSERT_MESSAGE("Drawing object should not be visible.", !pObj->IsVisible());
3868 CPPUNIT_ASSERT_MESSAGE("Drawing object should not be printable.", !pObj->IsPrintable());
3871 void ScExportTest::testHiddenShapeXLSX()
3873 createScDoc("xlsx/hiddenShape.xlsx");
3875 ScDocument* pDoc = getScDoc();
3876 CPPUNIT_ASSERT(pDoc->GetTableCount() > 0);
3877 ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
3878 SdrPage* pPage = pDrawLayer->GetPage(0);
3879 CPPUNIT_ASSERT(pPage);
3880 SdrObject* pObj = pPage->GetObj(0);
3881 CPPUNIT_ASSERT(pObj);
3882 CPPUNIT_ASSERT_MESSAGE("Drawing object should not be visible.", !pObj->IsVisible());
3883 CPPUNIT_ASSERT_MESSAGE("Drawing object should not be printable.", !pObj->IsPrintable());
3885 save("Calc Office Open XML");
3886 xmlDocUniquePtr pDocXml = parseExport("xl/drawings/drawing1.xml");
3887 CPPUNIT_ASSERT(pDocXml);
3888 assertXPath(pDocXml, "/xdr:wsDr/xdr:twoCellAnchor/xdr:sp[1]/xdr:nvSpPr/xdr:cNvPr", "hidden",
3889 "1");
3892 void ScExportTest::testShapeAutofitXLSX()
3894 createScDoc("xlsx/testShapeAutofit.xlsx");
3896 save("Calc Office Open XML");
3897 xmlDocUniquePtr pDoc = parseExport("xl/drawings/drawing1.xml");
3898 CPPUNIT_ASSERT(pDoc);
3900 // TextAutoGrowHeight --> "Fit height to text" / "Resize shape to fit text" --> true
3901 assertXPath(pDoc, "/xdr:wsDr/xdr:twoCellAnchor[1]/xdr:sp/xdr:txBody/a:bodyPr/a:spAutoFit", 1);
3902 // TextAutoGrowHeight --> "Fit height to text" / "Resize shape to fit text" --> false
3903 assertXPath(pDoc, "/xdr:wsDr/xdr:twoCellAnchor[2]/xdr:sp/xdr:txBody/a:bodyPr/a:noAutofit", 1);
3906 void ScExportTest::testHyperlinkXLSX()
3908 createScDoc("xlsx/hyperlink.xlsx");
3910 save("Calc Office Open XML");
3911 xmlDocUniquePtr pDoc = parseExport("xl/drawings/_rels/drawing1.xml.rels");
3912 CPPUNIT_ASSERT(pDoc);
3913 assertXPath(pDoc, "/rels:Relationships/rels:Relationship", "Target", "#Sheet2!A1");
3916 void ScExportTest::testMoveCellAnchoredShapesODS()
3918 createScDoc("ods/move-cell-anchored-shapes.ods");
3920 // There are two cell-anchored objects on the first sheet.
3921 ScDocument* pDoc = getScDoc();
3923 CPPUNIT_ASSERT_MESSAGE("There should be at least one sheet.", pDoc->GetTableCount() > 0);
3925 ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
3926 SdrPage* pPage = pDrawLayer->GetPage(0);
3927 CPPUNIT_ASSERT_MESSAGE("draw page for sheet 1 should exist.", pPage);
3928 SdrObject* pObj = pPage->GetObj(0);
3929 CPPUNIT_ASSERT_MESSAGE("Failed to get drawing object.", pObj);
3931 // Check cell anchor state
3932 ScAnchorType oldType = ScDrawLayer::GetAnchorType(*pObj);
3933 CPPUNIT_ASSERT_EQUAL_MESSAGE("Failed to get anchor type", SCA_CELL_RESIZE, oldType);
3935 // Get anchor data
3936 ScDrawObjData* pData = ScDrawLayer::GetObjData(pObj);
3937 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData);
3938 CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.",
3939 !pData->getShapeRect().IsEmpty());
3941 ScAddress aDataStart = pData->maStart;
3942 ScAddress aDataEnd = pData->maEnd;
3944 // Get non rotated anchor data
3945 ScDrawObjData* pNData = ScDrawLayer::GetNonRotatedObjData(pObj);
3946 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData);
3947 CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.",
3948 !pNData->getShapeRect().IsEmpty());
3950 ScAddress aNDataStart = pNData->maStart;
3951 ScAddress aNDataEnd = pNData->maEnd;
3952 CPPUNIT_ASSERT_EQUAL(aDataStart, aNDataStart);
3953 CPPUNIT_ASSERT_EQUAL(aDataEnd, aNDataEnd);
3955 // Insert 2 rows.
3956 pDoc->InsertRow(ScRange(0, aDataStart.Row() - 1, 0, pDoc->MaxCol(), aDataStart.Row(), 0));
3958 // Get anchor data
3959 pData = ScDrawLayer::GetObjData(pObj);
3960 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData);
3961 CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.",
3962 !pData->getShapeRect().IsEmpty());
3964 // Get non rotated anchor data
3965 pNData = ScDrawLayer::GetNonRotatedObjData(pObj);
3966 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData);
3967 CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.",
3968 !pNData->getShapeRect().IsEmpty());
3970 // Check if data has moved to new rows
3971 CPPUNIT_ASSERT_EQUAL(pData->maStart.Row(), aDataStart.Row() + 2);
3972 CPPUNIT_ASSERT_EQUAL(pData->maEnd.Row(), aDataEnd.Row() + 2);
3974 CPPUNIT_ASSERT_EQUAL(pNData->maStart.Row(), aNDataStart.Row() + 2);
3975 CPPUNIT_ASSERT_EQUAL(pNData->maEnd.Row(), aNDataEnd.Row() + 2);
3977 // Save the anchor data
3978 aDataStart = pData->maStart;
3979 aDataEnd = pData->maEnd;
3980 aNDataStart = pNData->maStart;
3981 aNDataEnd = pNData->maEnd;
3983 // Save the document and load again to check anchor persist
3984 saveAndReload("calc8");
3986 // There are two cell-anchored objects on the first sheet.
3987 pDoc = getScDoc();
3989 CPPUNIT_ASSERT_MESSAGE("There should be at least one sheet.", pDoc->GetTableCount() > 0);
3991 pDrawLayer = pDoc->GetDrawLayer();
3992 pPage = pDrawLayer->GetPage(0);
3993 CPPUNIT_ASSERT_MESSAGE("draw page for sheet 1 should exist.", pPage);
3994 pObj = pPage->GetObj(0);
3995 CPPUNIT_ASSERT_MESSAGE("Failed to get drawing object.", pObj);
3997 // Check cell anchor state
3998 oldType = ScDrawLayer::GetAnchorType(*pObj);
3999 CPPUNIT_ASSERT_EQUAL_MESSAGE("Failed to get anchor type", SCA_CELL_RESIZE, oldType);
4001 // Get anchor data
4002 pData = ScDrawLayer::GetObjData(pObj);
4003 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData);
4004 CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.",
4005 !pData->getShapeRect().IsEmpty());
4007 // Get non rotated anchor data
4008 pNData = ScDrawLayer::GetNonRotatedObjData(pObj);
4009 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData);
4010 CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.",
4011 !pNData->getShapeRect().IsEmpty());
4013 // Check if data after save it
4014 CPPUNIT_ASSERT_EQUAL(pData->maStart, aDataStart);
4015 CPPUNIT_ASSERT_EQUAL(pData->maEnd, aDataEnd);
4017 CPPUNIT_ASSERT_EQUAL(pNData->maStart, aNDataStart);
4018 CPPUNIT_ASSERT_EQUAL(pNData->maEnd, aNDataEnd);
4020 // Insert a column.
4021 pDoc->InsertCol(ScRange(aDataStart.Col(), 0, 0, aDataStart.Col(), pDoc->MaxRow(), 0));
4023 // Get anchor data
4024 pData = ScDrawLayer::GetObjData(pObj);
4025 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData);
4026 CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.",
4027 !pData->getShapeRect().IsEmpty());
4029 // Get non rotated anchor data
4030 pNData = ScDrawLayer::GetNonRotatedObjData(pObj);
4031 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData);
4032 CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.",
4033 !pNData->getShapeRect().IsEmpty());
4035 // Check if data has moved to new rows
4036 CPPUNIT_ASSERT_EQUAL(pData->maStart.Col(), SCCOL(aDataStart.Col() + 1));
4037 CPPUNIT_ASSERT_EQUAL(pData->maEnd.Col(), SCCOL(aDataEnd.Col() + 1));
4039 CPPUNIT_ASSERT_EQUAL(pNData->maStart.Col(), SCCOL(aNDataStart.Col() + 1));
4040 CPPUNIT_ASSERT_EQUAL(pNData->maEnd.Col(), SCCOL(aNDataEnd.Col() + 1));
4042 // Save the anchor data
4043 aDataStart = pData->maStart;
4044 aDataEnd = pData->maEnd;
4045 aNDataStart = pNData->maStart;
4046 aNDataEnd = pNData->maEnd;
4048 // Save the document and load again to check anchor persist
4049 saveAndReload("calc8");
4051 // There are two cell-anchored objects on the first sheet.
4052 pDoc = getScDoc();
4054 CPPUNIT_ASSERT_MESSAGE("There should be at least one sheet.", pDoc->GetTableCount() > 0);
4056 pDrawLayer = pDoc->GetDrawLayer();
4057 pPage = pDrawLayer->GetPage(0);
4058 CPPUNIT_ASSERT_MESSAGE("draw page for sheet 1 should exist.", pPage);
4059 pObj = pPage->GetObj(0);
4060 CPPUNIT_ASSERT_MESSAGE("Failed to get drawing object.", pObj);
4062 // Check cell anchor state
4063 oldType = ScDrawLayer::GetAnchorType(*pObj);
4064 CPPUNIT_ASSERT_EQUAL_MESSAGE("Failed to get anchor type", SCA_CELL_RESIZE, oldType);
4066 // Get anchor data
4067 pData = ScDrawLayer::GetObjData(pObj);
4068 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData);
4069 CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.",
4070 !pData->getShapeRect().IsEmpty());
4072 // Get non rotated anchor data
4073 pNData = ScDrawLayer::GetNonRotatedObjData(pObj);
4074 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData);
4075 CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.",
4076 !pNData->getShapeRect().IsEmpty());
4078 // Check if data after save it
4079 CPPUNIT_ASSERT_EQUAL(pData->maStart, aDataStart);
4080 CPPUNIT_ASSERT_EQUAL(pData->maEnd, aDataEnd);
4082 CPPUNIT_ASSERT_EQUAL(pNData->maStart, aNDataStart);
4083 CPPUNIT_ASSERT_EQUAL(pNData->maEnd, aNDataEnd);
4086 void ScExportTest::testConditionalFormatRangeListXLSX()
4088 createScDoc("ods/conditionalformat_rangelist.ods");
4089 save("Calc Office Open XML");
4090 xmlDocUniquePtr pDoc = parseExport("xl/worksheets/sheet1.xml");
4091 CPPUNIT_ASSERT(pDoc);
4092 assertXPath(pDoc, "//x:conditionalFormatting", "sqref", "F4 F10");
4095 void ScExportTest::testConditionalFormatContainsTextXLSX()
4097 createScDoc("ods/conditionalformat_containstext.ods");
4098 save("Calc Office Open XML");
4099 xmlDocUniquePtr pDoc = parseExport("xl/worksheets/sheet1.xml");
4100 CPPUNIT_ASSERT(pDoc);
4101 assertXPathContent(pDoc, "//x:conditionalFormatting/x:cfRule/x:formula",
4102 "NOT(ISERROR(SEARCH(\"test\",A1)))");
4105 void ScExportTest::testConditionalFormatPriorityCheckXLSX()
4107 createScDoc("xlsx/conditional_fmt_checkpriority.xlsx");
4108 save("Calc Office Open XML");
4109 xmlDocUniquePtr pDoc = parseExport("xl/worksheets/sheet1.xml");
4110 CPPUNIT_ASSERT(pDoc);
4111 constexpr bool bHighPriorityExtensionA1
4112 = true; // Should A1's extension cfRule has higher priority than normal cfRule ?
4113 constexpr bool bHighPriorityExtensionA3
4114 = false; // Should A3's extension cfRule has higher priority than normal cfRule ?
4115 size_t nA1NormalPriority = 0;
4116 size_t nA1ExtPriority = 0;
4117 size_t nA3NormalPriority = 0;
4118 size_t nA3ExtPriority = 0;
4119 for (size_t nIdx = 1; nIdx <= 2; ++nIdx)
4121 OString aIdx = OString::number(nIdx);
4122 OUString aCellAddr = getXPath(pDoc, "//x:conditionalFormatting[" + aIdx + "]", "sqref");
4123 OUString aPriority
4124 = getXPath(pDoc, "//x:conditionalFormatting[" + aIdx + "]/x:cfRule", "priority");
4125 CPPUNIT_ASSERT_MESSAGE("conditionalFormatting sqref must be either A1 or A3",
4126 aCellAddr == "A1" || aCellAddr == "A3");
4127 if (aCellAddr == "A1")
4128 nA1NormalPriority = aPriority.toUInt32();
4129 else
4130 nA3NormalPriority = aPriority.toUInt32();
4131 aCellAddr = getXPathContent(
4132 pDoc, "//x:extLst/x:ext[1]/x14:conditionalFormattings/x14:conditionalFormatting[" + aIdx
4133 + "]/xm:sqref");
4134 aPriority
4135 = getXPath(pDoc,
4136 "//x:extLst/x:ext[1]/x14:conditionalFormattings/x14:conditionalFormatting["
4137 + aIdx + "]/x14:cfRule",
4138 "priority");
4139 CPPUNIT_ASSERT_MESSAGE("x14:conditionalFormatting sqref must be either A1 or A3",
4140 aCellAddr == "A1" || aCellAddr == "A3");
4141 if (aCellAddr == "A1")
4142 nA1ExtPriority = aPriority.toUInt32();
4143 else
4144 nA3ExtPriority = aPriority.toUInt32();
4146 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong priorities for A1", bHighPriorityExtensionA1,
4147 nA1ExtPriority < nA1NormalPriority);
4148 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong priorities for A3", bHighPriorityExtensionA3,
4149 nA3ExtPriority < nA3NormalPriority);
4152 void ScExportTest::testConditionalFormatOriginXLSX()
4154 createScDoc("xlsx/conditional_fmt_origin.xlsx");
4155 save("Calc Office Open XML");
4156 xmlDocUniquePtr pDoc = parseExport("xl/worksheets/sheet1.xml");
4157 CPPUNIT_ASSERT(pDoc);
4158 // tdf#124953 : The range-list is B3:C6 F1:G2, origin address in the formula should be B1, not B3.
4159 OUString aFormula = getXPathContent(pDoc, "//x:conditionalFormatting/x:cfRule/x:formula");
4160 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong origin address in formula",
4161 OUString("NOT(ISERROR(SEARCH(\"BAC\",B1)))"), aFormula);
4164 // FILESAVE: XLSX export with long sheet names (length > 31 characters)
4165 void ScExportTest::testTdf79998()
4167 // check: original document has tab name > 31 characters
4168 createScDoc("ods/tdf79998.ods");
4169 ScDocument* pDoc = getScDoc();
4170 const std::vector<OUString> aTabNames1 = pDoc->GetAllTableNames();
4171 CPPUNIT_ASSERT_EQUAL(OUString("Utilities (FX Kurse, Kreditkarten etc)"), aTabNames1[1]);
4173 // check: saved XLSX document has truncated tab name
4174 saveAndReload("Calc Office Open XML");
4175 pDoc = getScDoc();
4176 const std::vector<OUString> aTabNames2 = pDoc->GetAllTableNames();
4177 CPPUNIT_ASSERT_EQUAL(OUString("Utilities (FX Kurse, Kreditkart"), aTabNames2[1]);
4180 static void impl_testLegacyCellAnchoredRotatedShape(ScDocument& rDoc, const tools::Rectangle& aRect,
4181 const ScDrawObjData& aAnchor,
4182 tools::Long TOLERANCE = 30 /* 30 hmm */)
4184 ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
4185 CPPUNIT_ASSERT_MESSAGE("No drawing layer.", pDrawLayer);
4186 SdrPage* pPage = pDrawLayer->GetPage(0);
4187 CPPUNIT_ASSERT_MESSAGE("No page instance for the 1st sheet.", pPage);
4188 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pPage->GetObjCount());
4190 SdrObject* pObj = pPage->GetObj(0);
4191 const tools::Rectangle& aSnap = pObj->GetSnapRect();
4192 CPPUNIT_ASSERT_DOUBLES_EQUAL(aRect.GetHeight(), aSnap.GetHeight(), TOLERANCE);
4193 CPPUNIT_ASSERT_DOUBLES_EQUAL(aRect.GetWidth(), aSnap.GetWidth(), TOLERANCE);
4194 CPPUNIT_ASSERT_DOUBLES_EQUAL(aRect.Left(), aSnap.Left(), TOLERANCE);
4195 CPPUNIT_ASSERT_DOUBLES_EQUAL(aRect.Top(), aSnap.Top(), TOLERANCE);
4197 ScDrawObjData* pData = ScDrawLayer::GetObjData(pObj);
4198 CPPUNIT_ASSERT_MESSAGE("expected object meta data", pData);
4199 CPPUNIT_ASSERT_EQUAL(aAnchor.maStart.Row(), pData->maStart.Row());
4200 CPPUNIT_ASSERT_EQUAL(aAnchor.maStart.Col(), pData->maStart.Col());
4201 CPPUNIT_ASSERT_EQUAL(aAnchor.maEnd.Row(), pData->maEnd.Row());
4202 CPPUNIT_ASSERT_EQUAL(aAnchor.maEnd.Col(), pData->maEnd.Col());
4205 void ScExportTest::testLegacyCellAnchoredRotatedShape()
4208 // This example doc contains cell anchored shape that is rotated, the
4209 // rotated shape is in fact clipped by the sheet boundaries (and thus
4210 // is a good edge case test to see if we import it still correctly)
4211 createScDoc("ods/legacycellanchoredrotatedclippedshape.ods");
4213 ScDocument* pDoc = getScDoc();
4214 // ensure the imported legacy rotated shape is in the expected position
4215 tools::Rectangle aRect(6000, -2000, 8000, 4000);
4216 // ensure the imported ( and converted ) anchor ( note we internally now store the anchor in
4217 // terms of the rotated shape ) is more or less contains the correct info
4218 ScDrawObjData aAnchor;
4219 aAnchor.maStart.SetRow(0);
4220 aAnchor.maStart.SetCol(5);
4221 aAnchor.maEnd.SetRow(3);
4222 aAnchor.maEnd.SetCol(7);
4223 impl_testLegacyCellAnchoredRotatedShape(*pDoc, aRect, aAnchor);
4224 // test save and reload
4225 // for some reason having this test in subsequent_export-test.cxx causes
4226 // a core dump in editeng ( so moved to here )
4227 saveAndReload("calc8");
4228 pDoc = getScDoc();
4229 impl_testLegacyCellAnchoredRotatedShape(*pDoc, aRect, aAnchor);
4232 // This example doc contains cell anchored shape that is rotated, the
4233 // rotated shape is in fact clipped by the sheet boundaries, additionally
4234 // the shape is completely hidden because the rows the shape occupies
4235 // are hidden
4236 createScDoc("ods/legacycellanchoredrotatedhiddenshape.ods");
4237 ScDocument* pDoc = getScDoc();
4238 // ensure the imported legacy rotated shape is in the expected position
4239 tools::Rectangle aRect(6000, -2000, 8000, 4000);
4241 // ensure the imported (and converted) anchor (note we internally now store the anchor in
4242 // terms of the rotated shape) is more or less contains the correct info
4243 ScDrawObjData aAnchor;
4244 aAnchor.maStart.SetRow(0);
4245 aAnchor.maStart.SetCol(5);
4246 aAnchor.maEnd.SetRow(3);
4247 aAnchor.maEnd.SetCol(7);
4248 pDoc->ShowRows(0, 9, 0, true); // show relevant rows
4249 pDoc->SetDrawPageSize(0); // trigger recalcpos
4250 impl_testLegacyCellAnchoredRotatedShape(*pDoc, aRect, aAnchor);
4251 // test save and reload
4252 saveAndReload("calc8");
4253 pDoc = getScDoc();
4254 impl_testLegacyCellAnchoredRotatedShape(*pDoc, aRect, aAnchor);
4257 // This example doc contains cell anchored shape that is rotated
4258 createScDoc("ods/legacycellanchoredrotatedshape.ods");
4260 ScDocument* pDoc = getScDoc();
4261 // ensure the imported legacy rotated shape is in the expected position
4262 tools::Rectangle aRect(6000, 3000, 8000, 9000);
4263 // ensure the imported (and converted) anchor (note we internally now store the anchor in
4264 // terms of the rotated shape) more or less contains the correct info
4266 ScDrawObjData aAnchor;
4267 aAnchor.maStart.SetRow(3);
4268 aAnchor.maStart.SetCol(6);
4269 aAnchor.maEnd.SetRow(9);
4270 aAnchor.maEnd.SetCol(8);
4271 // test import
4272 impl_testLegacyCellAnchoredRotatedShape(*pDoc, aRect, aAnchor);
4273 // test save and reload
4274 saveAndReload("calc8");
4275 pDoc = getScDoc();
4276 impl_testLegacyCellAnchoredRotatedShape(*pDoc, aRect, aAnchor);
4280 void ScExportTest::testTdf113646()
4282 createScDoc("ods/tdf113646.ods");
4284 save("Calc Office Open XML");
4285 xmlDocUniquePtr pSheet = parseExport("xl/styles.xml");
4286 CPPUNIT_ASSERT(pSheet);
4288 assertXPath(pSheet, "/x:styleSheet/x:dxfs/x:dxf/x:font/x:sz", "val", "36");
4291 void ScExportTest::testDateStandardfilterXLSX()
4293 // XLSX Roundtripping standard filter with date
4294 createScDoc("ods/tdf142607.ods");
4296 save("Calc Office Open XML");
4297 xmlDocUniquePtr pDoc = parseExport("xl/worksheets/sheet1.xml");
4298 CPPUNIT_ASSERT(pDoc);
4300 assertXPath(pDoc, "//x:autoFilter", "ref", "A1:B6");
4301 assertXPath(pDoc, "//x:autoFilter/x:filterColumn/x:filters/x:dateGroupItem[1]", "day", "03");
4302 assertXPath(pDoc, "//x:autoFilter/x:filterColumn/x:filters/x:dateGroupItem[1]", "month", "12");
4303 assertXPath(pDoc, "//x:autoFilter/x:filterColumn/x:filters/x:dateGroupItem[1]", "year", "2011");
4304 assertXPath(pDoc, "//x:autoFilter/x:filterColumn/x:filters/x:dateGroupItem[1]",
4305 "dateTimeGrouping", "day");
4308 CPPUNIT_TEST_SUITE_REGISTRATION(ScExportTest);
4310 CPPUNIT_PLUGIN_IMPLEMENT();
4312 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */