Bump version to 5.0-14
[LibreOffice.git] / sc / qa / unit / subsequent_export-test.cxx
blobb1db15933e5830472824744bf7ab5556cc9032c8
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include <officecfg/Office/Common.hxx>
11 #include <sal/config.h>
12 #include <rtl/strbuf.hxx>
13 #include <osl/file.hxx>
15 #include <sfx2/app.hxx>
16 #include <sfx2/docfile.hxx>
17 #include <sfx2/frame.hxx>
18 #include <sfx2/sfxmodelfactory.hxx>
19 #include <svl/stritem.hxx>
21 #include "helper/qahelper.hxx"
22 #include "helper/xpath.hxx"
23 #include "helper/shared_test_impl.hxx"
25 #include "userdat.hxx"
26 #include "docsh.hxx"
27 #include "patattr.hxx"
28 #include "scitems.hxx"
29 #include "document.hxx"
30 #include "cellform.hxx"
31 #include "formulacell.hxx"
32 #include "tokenarray.hxx"
33 #include "editutil.hxx"
34 #include "scopetools.hxx"
35 #include "cellvalue.hxx"
36 #include "docfunc.hxx"
37 #include <postit.hxx>
38 #include <tokenstringcontext.hxx>
39 #include <chgtrack.hxx>
40 #include <dpcache.hxx>
41 #include <dpobject.hxx>
42 #include <dpsave.hxx>
43 #include <dputil.hxx>
45 #include <svx/svdoole2.hxx>
46 #include <svx/svdpage.hxx>
47 #include <svx/svdograf.hxx>
48 #include "tabprotection.hxx"
49 #include <editeng/wghtitem.hxx>
50 #include <editeng/postitem.hxx>
51 #include <editeng/editdata.hxx>
52 #include <editeng/eeitem.hxx>
53 #include <editeng/editobj.hxx>
54 #include <editeng/section.hxx>
55 #include <editeng/crossedoutitem.hxx>
56 #include <editeng/borderline.hxx>
57 #include <editeng/fontitem.hxx>
58 #include <editeng/udlnitem.hxx>
59 #include <formula/grammar.hxx>
60 #include <unotools/useroptions.hxx>
61 #include <tools/datetime.hxx>
63 #include <test/xmltesttools.hxx>
64 #include <comphelper/processfactory.hxx>
65 #include <com/sun/star/table/BorderLineStyle.hpp>
66 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
67 #include <com/sun/star/sheet/GeneralFunction.hpp>
68 #include <com/sun/star/drawing/XDrawPage.hpp>
69 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
70 #include <com/sun/star/awt/XBitmap.hpp>
71 #include <com/sun/star/graphic/XGraphic.hpp>
73 using namespace ::com::sun::star;
74 using namespace ::com::sun::star::uno;
76 class ScExportTest : public ScBootstrapFixture, XmlTestTools
78 protected:
79 virtual void registerNamespaces(xmlXPathContextPtr& pXmlXPathCtx) SAL_OVERRIDE;
80 public:
81 ScExportTest();
83 virtual void setUp() SAL_OVERRIDE;
84 virtual void tearDown() SAL_OVERRIDE;
86 #if !defined MACOSX && !defined DRAGONFLY
87 ScDocShellRef saveAndReloadPassword( ScDocShell*, const OUString&, const OUString&, const OUString&, SfxFilterFlags );
88 #endif
90 void test();
91 #if !defined MACOSX && !defined DRAGONFLY
92 void testPasswordExport();
93 #endif
94 void testConditionalFormatExportODS();
95 void testConditionalFormatExportXLSX();
96 void testColorScaleExportODS();
97 void testColorScaleExportXLSX();
98 void testDataBarExportODS();
99 void testDataBarExportXLSX();
100 void testMiscRowHeightExport();
101 void testNamedRangeBugfdo62729();
102 void testRichTextExportODS();
103 void testFormulaRefSheetNameODS();
105 void testCellValuesExportODS();
106 void testCellNoteExportODS();
107 void testCellNoteExportXLS();
108 void testFormatExportODS();
110 void testInlineArrayXLS();
111 void testEmbeddedChartXLS();
112 void testFormulaReferenceXLS();
113 void testSheetProtectionXLSX();
115 void testCellBordersXLS();
116 void testCellBordersXLSX();
117 void testTrackChangesSimpleXLSX();
118 void testSheetTabColorsXLSX();
120 void testSharedFormulaExportXLS();
121 void testSharedFormulaExportXLSX();
122 void testSharedFormulaStringResultExportXLSX();
124 void testFunctionsExcel2010( sal_uLong nFormatType );
125 void testFunctionsExcel2010XLSX();
126 void testFunctionsExcel2010XLS();
127 void testFunctionsExcel2010ODS();
129 void testRelativePaths();
130 void testSheetProtection();
132 void testPivotTableXLSX();
133 void testPivotTableTwoDataFieldsXLSX();
135 void testSwappedOutImageExport();
136 void testLinkedGraphicRT();
137 void testImageWithSpecialID();
139 void testSupBookVirtualPath();
140 void testSheetLocalRangeNameXLS();
141 void testSheetTextBoxHyperlink();
142 void testFontSize();
143 void testSheetCharacterKerningSpace();
144 void testSheetCondensedCharacterSpace();
145 void testTextUnderlineColor();
146 void testSheetRunParagraphProperty();
147 void testHiddenShape();
148 void testMoveCellAnchoredShapes();
149 void testHeaderImage();
150 void testMatrixMultiplication();
151 void testRefStringXLSX();
152 void testRefStringConfigXLSX();
153 void testRefStringUnspecified();
155 CPPUNIT_TEST_SUITE(ScExportTest);
156 CPPUNIT_TEST(test);
157 #if !defined(MACOSX) && !defined(DRAGONFLY)
158 CPPUNIT_TEST(testPasswordExport);
159 #endif
160 CPPUNIT_TEST(testConditionalFormatExportODS);
161 CPPUNIT_TEST(testConditionalFormatExportXLSX);
162 CPPUNIT_TEST(testColorScaleExportODS);
163 CPPUNIT_TEST(testColorScaleExportXLSX);
164 CPPUNIT_TEST(testDataBarExportODS);
165 CPPUNIT_TEST(testDataBarExportXLSX);
166 CPPUNIT_TEST(testMiscRowHeightExport);
167 CPPUNIT_TEST(testNamedRangeBugfdo62729);
168 CPPUNIT_TEST(testRichTextExportODS);
169 CPPUNIT_TEST(testFormulaRefSheetNameODS);
170 CPPUNIT_TEST(testCellValuesExportODS);
171 CPPUNIT_TEST(testCellNoteExportODS);
172 CPPUNIT_TEST(testCellNoteExportXLS);
173 CPPUNIT_TEST(testFormatExportODS);
174 CPPUNIT_TEST(testInlineArrayXLS);
175 CPPUNIT_TEST(testEmbeddedChartXLS);
176 CPPUNIT_TEST(testFormulaReferenceXLS);
177 CPPUNIT_TEST(testSheetProtectionXLSX);
178 CPPUNIT_TEST(testCellBordersXLS);
179 CPPUNIT_TEST(testCellBordersXLSX);
180 CPPUNIT_TEST(testTrackChangesSimpleXLSX);
181 CPPUNIT_TEST(testSheetTabColorsXLSX);
182 CPPUNIT_TEST(testSharedFormulaExportXLS);
183 CPPUNIT_TEST(testSharedFormulaExportXLSX);
184 CPPUNIT_TEST(testSharedFormulaStringResultExportXLSX);
185 CPPUNIT_TEST(testFunctionsExcel2010XLSX);
186 CPPUNIT_TEST(testFunctionsExcel2010XLS);
187 #if !defined(WNT)
188 CPPUNIT_TEST(testRelativePaths);
189 #endif
190 CPPUNIT_TEST(testSheetProtection);
191 CPPUNIT_TEST(testPivotTableXLSX);
192 CPPUNIT_TEST(testPivotTableTwoDataFieldsXLSX);
193 CPPUNIT_TEST(testFunctionsExcel2010ODS);
194 #if !defined(WNT)
195 CPPUNIT_TEST(testSupBookVirtualPath);
196 #endif
197 CPPUNIT_TEST(testSwappedOutImageExport);
198 CPPUNIT_TEST(testLinkedGraphicRT);
199 CPPUNIT_TEST(testImageWithSpecialID);
200 CPPUNIT_TEST(testSheetLocalRangeNameXLS);
201 CPPUNIT_TEST(testSheetTextBoxHyperlink);
202 CPPUNIT_TEST(testFontSize);
203 CPPUNIT_TEST(testSheetCharacterKerningSpace);
204 CPPUNIT_TEST(testSheetCondensedCharacterSpace);
205 CPPUNIT_TEST(testTextUnderlineColor);
206 CPPUNIT_TEST(testSheetRunParagraphProperty);
207 CPPUNIT_TEST(testHiddenShape);
208 CPPUNIT_TEST(testMoveCellAnchoredShapes);
209 CPPUNIT_TEST(testHeaderImage);
210 CPPUNIT_TEST(testMatrixMultiplication);
211 CPPUNIT_TEST(testRefStringXLSX);
212 CPPUNIT_TEST(testRefStringConfigXLSX);
213 CPPUNIT_TEST(testRefStringUnspecified);
215 CPPUNIT_TEST_SUITE_END();
217 private:
218 void testExcelCellBorders( sal_uLong nFormatType );
220 uno::Reference<uno::XInterface> m_xCalcComponent;
224 void ScExportTest::registerNamespaces(xmlXPathContextPtr& pXmlXPathCtx)
226 struct { xmlChar* pPrefix; xmlChar* pURI; } aNamespaces[] =
228 { BAD_CAST("w"), BAD_CAST("http://schemas.openxmlformats.org/wordprocessingml/2006/main") },
229 { BAD_CAST("v"), BAD_CAST("urn:schemas-microsoft-com:vml") },
230 { BAD_CAST("c"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/chart") },
231 { BAD_CAST("a"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/main") },
232 { BAD_CAST("mc"), BAD_CAST("http://schemas.openxmlformats.org/markup-compatibility/2006") },
233 { BAD_CAST("wps"), BAD_CAST("http://schemas.microsoft.com/office/word/2010/wordprocessingShape") },
234 { BAD_CAST("wpg"), BAD_CAST("http://schemas.microsoft.com/office/word/2010/wordprocessingGroup") },
235 { BAD_CAST("wp"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing") },
236 { BAD_CAST("office"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:office:1.0") },
237 { BAD_CAST("table"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:table:1.0") },
238 { BAD_CAST("text"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:text:1.0") },
239 { BAD_CAST("xlink"), BAD_CAST("http://www.w3c.org/1999/xlink") },
240 { BAD_CAST("xdr"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing") },
241 { BAD_CAST("x"), BAD_CAST("http://schemas.openxmlformats.org/spreadsheetml/2006/main") }
243 for(size_t i = 0; i < SAL_N_ELEMENTS(aNamespaces); ++i)
245 xmlXPathRegisterNs(pXmlXPathCtx, aNamespaces[i].pPrefix, aNamespaces[i].pURI );
249 #if !defined MACOSX && !defined DRAGONFLY
250 ScDocShellRef ScExportTest::saveAndReloadPassword(ScDocShell* pShell, const OUString &rFilter,
251 const OUString &rUserData, const OUString& rTypeName, SfxFilterFlags nFormatType)
253 utl::TempFile aTempFile;
254 aTempFile.EnableKillingFile();
255 SfxMedium aStoreMedium( aTempFile.GetURL(), STREAM_STD_WRITE );
256 SotClipboardFormatId nExportFormat = SotClipboardFormatId::NONE;
257 if (nFormatType == ODS_FORMAT_TYPE)
258 nExportFormat = SotClipboardFormatId::STARCHART_8;
259 SfxFilter* pExportFilter = new SfxFilter(
260 rFilter,
261 OUString(), nFormatType, nExportFormat, rTypeName, 0, OUString(),
262 rUserData, OUString("private:factory/scalc*") );
263 pExportFilter->SetVersion(SOFFICE_FILEFORMAT_CURRENT);
264 aStoreMedium.SetFilter(pExportFilter);
265 SfxItemSet* pExportSet = aStoreMedium.GetItemSet();
266 uno::Sequence< beans::NamedValue > aEncryptionData = comphelper::OStorageHelper::CreatePackageEncryptionData( OUString("test") );
267 uno::Any xEncryptionData;
268 xEncryptionData <<= aEncryptionData;
269 pExportSet->Put(SfxUnoAnyItem(SID_ENCRYPTIONDATA, xEncryptionData));
271 uno::Reference< embed::XStorage > xMedStorage = aStoreMedium.GetStorage();
272 ::comphelper::OStorageHelper::SetCommonStorageEncryptionData( xMedStorage, aEncryptionData );
274 pShell->DoSaveAs( aStoreMedium );
275 pShell->DoClose();
277 //std::cout << "File: " << aTempFile.GetURL() << std::endl;
279 SotClipboardFormatId nFormat = SotClipboardFormatId::NONE;
280 if (nFormatType == ODS_FORMAT_TYPE)
281 nFormat = SotClipboardFormatId::STARCALC_8;
283 OUString aPass("test");
284 return load(aTempFile.GetURL(), rFilter, rUserData, rTypeName, nFormatType, nFormat, SOFFICE_FILEFORMAT_CURRENT, &aPass);
286 #endif
288 void ScExportTest::test()
290 ScDocShell* pShell = new ScDocShell(
291 SfxModelFlags::EMBEDDED_OBJECT |
292 SfxModelFlags::DISABLE_EMBEDDED_SCRIPTS |
293 SfxModelFlags::DISABLE_DOCUMENT_RECOVERY);
294 pShell->DoInitNew();
296 ScDocument& rDoc = pShell->GetDocument();
298 rDoc.SetValue(0,0,0, 1.0);
300 ScDocShellRef xDocSh = saveAndReload( pShell, ODS );
302 CPPUNIT_ASSERT(xDocSh.Is());
303 ScDocument& rLoadedDoc = xDocSh->GetDocument();
304 double aVal = rLoadedDoc.GetValue(0,0,0);
305 ASSERT_DOUBLES_EQUAL(aVal, 1.0);
306 xDocSh->DoClose();
309 #if !defined MACOSX && !defined DRAGONFLY
310 void ScExportTest::testPasswordExport()
312 ScDocShell* pShell = new ScDocShell(
313 SfxModelFlags::EMBEDDED_OBJECT |
314 SfxModelFlags::DISABLE_EMBEDDED_SCRIPTS |
315 SfxModelFlags::DISABLE_DOCUMENT_RECOVERY);
316 pShell->DoInitNew();
318 ScDocument& rDoc = pShell->GetDocument();
320 rDoc.SetValue(0,0,0, 1.0);
322 sal_Int32 nFormat = ODS;
323 OUString aFilterName(getFileFormats()[nFormat].pFilterName, strlen(getFileFormats()[nFormat].pFilterName), RTL_TEXTENCODING_UTF8) ;
324 OUString aFilterType(getFileFormats()[nFormat].pTypeName, strlen(getFileFormats()[nFormat].pTypeName), RTL_TEXTENCODING_UTF8);
325 ScDocShellRef xDocSh = saveAndReloadPassword(pShell, aFilterName, OUString(), aFilterType, getFileFormats()[nFormat].nFormatType);
327 CPPUNIT_ASSERT(xDocSh.Is());
328 ScDocument& rLoadedDoc = xDocSh->GetDocument();
329 double aVal = rLoadedDoc.GetValue(0,0,0);
330 ASSERT_DOUBLES_EQUAL(aVal, 1.0);
332 xDocSh->DoClose();
334 #endif
336 void ScExportTest::testConditionalFormatExportODS()
338 ScDocShellRef xShell = loadDoc("new_cond_format_test.", ODS);
339 CPPUNIT_ASSERT(xShell.Is());
341 ScDocShellRef xDocSh = saveAndReload(&(*xShell), ODS);
342 CPPUNIT_ASSERT(xDocSh.Is());
343 ScDocument& rDoc = xDocSh->GetDocument();
344 OUString aCSVFile("new_cond_format_test.");
345 OUString aCSVPath;
346 createCSVPath( aCSVFile, aCSVPath );
347 testCondFile(aCSVPath, &rDoc, 0);
349 xDocSh->DoClose();
352 void ScExportTest::testConditionalFormatExportXLSX()
354 ScDocShellRef xShell = loadDoc("new_cond_format_test.", XLSX);
355 CPPUNIT_ASSERT(xShell.Is());
357 ScDocShellRef xDocSh = saveAndReload(&(*xShell), XLSX);
358 CPPUNIT_ASSERT(xDocSh.Is());
359 ScDocument& rDoc = xDocSh->GetDocument();
361 OUString aCSVFile("new_cond_format_test.");
362 OUString aCSVPath;
363 createCSVPath( aCSVFile, aCSVPath );
364 testCondFile(aCSVPath, &rDoc, 0);
367 OUString aCSVFile("new_cond_format_test_sheet2.");
368 OUString aCSVPath;
369 createCSVPath( aCSVFile, aCSVPath );
370 testCondFile(aCSVPath, &rDoc, 1);
373 xDocSh->DoClose();
376 void ScExportTest::testColorScaleExportODS()
378 ScDocShellRef xShell = loadDoc("colorscale.", ODS);
379 CPPUNIT_ASSERT(xShell.Is());
381 ScDocShellRef xDocSh = saveAndReload(xShell, ODS);
382 CPPUNIT_ASSERT(xDocSh.Is());
384 ScDocument& rDoc = xDocSh->GetDocument();
386 testColorScale2Entry_Impl(rDoc);
387 testColorScale3Entry_Impl(rDoc);
389 xDocSh->DoClose();
392 void ScExportTest::testColorScaleExportXLSX()
394 ScDocShellRef xShell = loadDoc("colorscale.", XLSX);
395 CPPUNIT_ASSERT(xShell.Is());
397 ScDocShellRef xDocSh = saveAndReload(xShell, XLSX);
398 CPPUNIT_ASSERT(xDocSh.Is());
400 ScDocument& rDoc = xDocSh->GetDocument();
402 testColorScale2Entry_Impl(rDoc);
403 testColorScale3Entry_Impl(rDoc);
405 xDocSh->DoClose();
408 void ScExportTest::testDataBarExportODS()
410 ScDocShellRef xShell = loadDoc("databar.", ODS);
411 CPPUNIT_ASSERT(xShell.Is());
413 ScDocShellRef xDocSh = saveAndReload(xShell, ODS);
414 CPPUNIT_ASSERT(xDocSh.Is());
416 ScDocument& rDoc = xDocSh->GetDocument();
418 testDataBar_Impl(rDoc);
420 xDocSh->DoClose();
423 void ScExportTest::testFormatExportODS()
425 ScDocShellRef xShell = loadDoc("formats.", ODS);
426 CPPUNIT_ASSERT(xShell.Is());
428 ScDocShellRef xDocSh = saveAndReload(xShell, ODS);
429 CPPUNIT_ASSERT(xDocSh.Is());
431 ScDocument& rDoc = xDocSh->GetDocument();
433 testFormats(this, &rDoc, ODS);
435 xDocSh->DoClose();
438 void ScExportTest::testDataBarExportXLSX()
440 ScDocShellRef xShell = loadDoc("databar.", XLSX);
441 CPPUNIT_ASSERT(xShell.Is());
443 ScDocShellRef xDocSh = saveAndReload(xShell, XLSX);
444 CPPUNIT_ASSERT(xDocSh.Is());
446 ScDocument& rDoc = xDocSh->GetDocument();
448 testDataBar_Impl(rDoc);
450 xDocSh->DoClose();
453 void ScExportTest::testMiscRowHeightExport()
455 TestParam::RowData DfltRowData[] =
457 { 0, 4, 0, 529, 0, false },
458 { 5, 10, 0, 1058, 0, false },
459 { 17, 20, 0, 1767, 0, false },
460 // check last couple of row in document to ensure
461 // they are 5.29mm ( effective default row xlsx height )
462 { 1048573, 1048575, 0, 529, 0, false },
465 TestParam::RowData EmptyRepeatRowData[] =
467 // rows 0-4, 5-10, 17-20 are all set at various
468 // heights, there is no content in the rows, there
469 // was a bug where only the first row ( of repeated rows )
470 // was set after export
471 { 0, 4, 0, 529, 0, false },
472 { 5, 10, 0, 1058, 0, false },
473 { 17, 20, 0, 1767, 0, false },
476 TestParam aTestValues[] =
478 // Checks that some distributed ( non-empty ) heights remain set after export (roundtrip)
479 // additionally there is effectively a default row height ( 5.29 mm ). So we test the
480 // unset rows at the end of the document to ensure the effective xlsx default height
481 // is set there too.
482 { "miscrowheights.", XLSX, XLSX, SAL_N_ELEMENTS(DfltRowData), DfltRowData },
483 // Checks that some distributed ( non-empty ) heights remain set after export (to xls)
484 { "miscrowheights.", XLSX, XLS, SAL_N_ELEMENTS(DfltRowData), DfltRowData },
485 // Checks that repreated rows ( of various heights ) remain set after export ( to xlsx )
486 { "miscemptyrepeatedrowheights.", ODS, XLSX, SAL_N_ELEMENTS(EmptyRepeatRowData), EmptyRepeatRowData },
487 // Checks that repreated rows ( of various heights ) remain set after export ( to xls )
488 { "miscemptyrepeatedrowheights.", ODS, XLS, SAL_N_ELEMENTS(EmptyRepeatRowData), EmptyRepeatRowData },
490 miscRowHeightsTest( aTestValues, SAL_N_ELEMENTS(aTestValues) );
493 namespace {
495 void setAttribute( ScFieldEditEngine& rEE, sal_Int32 nPara, sal_Int32 nStart, sal_Int32 nEnd, sal_uInt16 nType )
497 ESelection aSel;
498 aSel.nStartPara = aSel.nEndPara = nPara;
499 aSel.nStartPos = nStart;
500 aSel.nEndPos = nEnd;
502 SfxItemSet aItemSet = rEE.GetEmptyItemSet();
503 switch (nType)
505 case EE_CHAR_WEIGHT:
507 SvxWeightItem aWeight(WEIGHT_BOLD, nType);
508 aItemSet.Put(aWeight);
509 rEE.QuickSetAttribs(aItemSet, aSel);
511 break;
512 case EE_CHAR_ITALIC:
514 SvxPostureItem aItalic(ITALIC_NORMAL, nType);
515 aItemSet.Put(aItalic);
516 rEE.QuickSetAttribs(aItemSet, aSel);
518 break;
519 case EE_CHAR_STRIKEOUT:
521 SvxCrossedOutItem aCrossOut(STRIKEOUT_SINGLE, nType);
522 aItemSet.Put(aCrossOut);
523 rEE.QuickSetAttribs(aItemSet, aSel);
525 break;
526 case EE_CHAR_OVERLINE:
528 SvxOverlineItem aItem(UNDERLINE_DOUBLE, nType);
529 aItemSet.Put(aItem);
530 rEE.QuickSetAttribs(aItemSet, aSel);
532 break;
533 case EE_CHAR_UNDERLINE:
535 SvxUnderlineItem aItem(UNDERLINE_DOUBLE, nType);
536 aItemSet.Put(aItem);
537 rEE.QuickSetAttribs(aItemSet, aSel);
539 break;
540 default:
545 void setFont( ScFieldEditEngine& rEE, sal_Int32 nPara, sal_Int32 nStart, sal_Int32 nEnd, const OUString& rFontName )
547 ESelection aSel;
548 aSel.nStartPara = aSel.nEndPara = nPara;
549 aSel.nStartPos = nStart;
550 aSel.nEndPos = nEnd;
552 SfxItemSet aItemSet = rEE.GetEmptyItemSet();
553 SvxFontItem aItem(FAMILY_MODERN, rFontName, "", PITCH_VARIABLE, RTL_TEXTENCODING_UTF8, EE_CHAR_FONTINFO);
554 aItemSet.Put(aItem);
555 rEE.QuickSetAttribs(aItemSet, aSel);
560 void ScExportTest::testNamedRangeBugfdo62729()
562 ScDocShellRef xShell = loadDoc("fdo62729.", ODS);
563 CPPUNIT_ASSERT(xShell.Is());
564 ScDocument& rDoc = xShell->GetDocument();
566 ScRangeName* pNames = rDoc.GetRangeName();
567 //should be just a single named range
568 CPPUNIT_ASSERT(pNames->size() == 1 );
569 rDoc.DeleteTab(0);
570 //should be still a single named range
571 CPPUNIT_ASSERT(pNames->size() == 1 );
572 ScDocShellRef xDocSh = saveAndReload(xShell, ODS);
573 xShell->DoClose();
575 CPPUNIT_ASSERT(xDocSh.Is());
576 ScDocument& rDoc2 = xDocSh->GetDocument();
578 pNames = rDoc2.GetRangeName();
579 //after reload should still have a named range
580 CPPUNIT_ASSERT(pNames->size() == 1 );
582 xDocSh->DoClose();
585 void ScExportTest::testRichTextExportODS()
587 struct
589 static bool isBold(const editeng::Section& rAttr)
591 if (rAttr.maAttributes.empty())
592 return false;
594 std::vector<const SfxPoolItem*>::const_iterator it = rAttr.maAttributes.begin(), itEnd = rAttr.maAttributes.end();
595 for (; it != itEnd; ++it)
597 const SfxPoolItem* p = *it;
598 if (p->Which() != EE_CHAR_WEIGHT)
599 continue;
601 return static_cast<const SvxWeightItem*>(p)->GetWeight() == WEIGHT_BOLD;
603 return false;
606 static bool isItalic(const editeng::Section& rAttr)
608 if (rAttr.maAttributes.empty())
609 return false;
611 std::vector<const SfxPoolItem*>::const_iterator it = rAttr.maAttributes.begin(), itEnd = rAttr.maAttributes.end();
612 for (; it != itEnd; ++it)
614 const SfxPoolItem* p = *it;
615 if (p->Which() != EE_CHAR_ITALIC)
616 continue;
618 return static_cast<const SvxPostureItem*>(p)->GetPosture() == ITALIC_NORMAL;
620 return false;
623 static bool isStrikeOut(const editeng::Section& rAttr)
625 if (rAttr.maAttributes.empty())
626 return false;
628 std::vector<const SfxPoolItem*>::const_iterator it = rAttr.maAttributes.begin(), itEnd = rAttr.maAttributes.end();
629 for (; it != itEnd; ++it)
631 const SfxPoolItem* p = *it;
632 if (p->Which() != EE_CHAR_STRIKEOUT)
633 continue;
635 return static_cast<const SvxCrossedOutItem*>(p)->GetStrikeout() == STRIKEOUT_SINGLE;
637 return false;
640 static bool isOverline(const editeng::Section& rAttr, FontUnderline eStyle)
642 if (rAttr.maAttributes.empty())
643 return false;
645 std::vector<const SfxPoolItem*>::const_iterator it = rAttr.maAttributes.begin(), itEnd = rAttr.maAttributes.end();
646 for (; it != itEnd; ++it)
648 const SfxPoolItem* p = *it;
649 if (p->Which() != EE_CHAR_OVERLINE)
650 continue;
652 return static_cast<const SvxOverlineItem*>(p)->GetLineStyle() == eStyle;
654 return false;
657 static bool isUnderline(const editeng::Section& rAttr, FontUnderline eStyle)
659 if (rAttr.maAttributes.empty())
660 return false;
662 std::vector<const SfxPoolItem*>::const_iterator it = rAttr.maAttributes.begin(), itEnd = rAttr.maAttributes.end();
663 for (; it != itEnd; ++it)
665 const SfxPoolItem* p = *it;
666 if (p->Which() != EE_CHAR_UNDERLINE)
667 continue;
669 return static_cast<const SvxUnderlineItem*>(p)->GetLineStyle() == eStyle;
671 return false;
674 static bool isFont(const editeng::Section& rAttr, const OUString& rFontName)
676 if (rAttr.maAttributes.empty())
677 return false;
679 std::vector<const SfxPoolItem*>::const_iterator it = rAttr.maAttributes.begin(), itEnd = rAttr.maAttributes.end();
680 for (; it != itEnd; ++it)
682 const SfxPoolItem* p = *it;
683 if (p->Which() != EE_CHAR_FONTINFO)
684 continue;
686 return static_cast<const SvxFontItem*>(p)->GetFamilyName() == rFontName;
688 return false;
691 bool checkB2(const EditTextObject* pText) const
693 if (!pText)
694 return false;
696 if (pText->GetParagraphCount() != 1)
697 return false;
699 if (pText->GetText(0) != "Bold and Italic")
700 return false;
702 std::vector<editeng::Section> aSecAttrs;
703 pText->GetAllSections(aSecAttrs);
704 if (aSecAttrs.size() != 3)
705 return false;
707 // Check the first bold section.
708 const editeng::Section* pAttr = &aSecAttrs[0];
709 if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 0 || pAttr->mnEnd != 4)
710 return false;
712 if (pAttr->maAttributes.size() != 1 || !isBold(*pAttr))
713 return false;
715 // The middle section should be unformatted.
716 pAttr = &aSecAttrs[1];
717 if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 4 || pAttr->mnEnd != 9)
718 return false;
720 if (!pAttr->maAttributes.empty())
721 return false;
723 // The last section should be italic.
724 pAttr = &aSecAttrs[2];
725 if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 9 || pAttr->mnEnd != 15)
726 return false;
728 if (pAttr->maAttributes.size() != 1 || !isItalic(*pAttr))
729 return false;
731 return true;
734 bool checkB4(const EditTextObject* pText) const
736 if (!pText)
737 return false;
739 if (pText->GetParagraphCount() != 3)
740 return false;
742 if (pText->GetText(0) != "One")
743 return false;
745 if (pText->GetText(1) != "Two")
746 return false;
748 if (pText->GetText(2) != "Three")
749 return false;
751 return true;
754 bool checkB5(const EditTextObject* pText) const
756 if (!pText)
757 return false;
759 if (pText->GetParagraphCount() != 6)
760 return false;
762 if (!pText->GetText(0).isEmpty())
763 return false;
765 if (pText->GetText(1) != "Two")
766 return false;
768 if (pText->GetText(2) != "Three")
769 return false;
771 if (!pText->GetText(3).isEmpty())
772 return false;
774 if (pText->GetText(4) != "Five")
775 return false;
777 if (!pText->GetText(5).isEmpty())
778 return false;
780 return true;
783 bool checkB6(const EditTextObject* pText) const
785 if (!pText)
786 return false;
788 if (pText->GetParagraphCount() != 1)
789 return false;
791 if (pText->GetText(0) != "Strike Me")
792 return false;
794 std::vector<editeng::Section> aSecAttrs;
795 pText->GetAllSections(aSecAttrs);
796 if (aSecAttrs.size() != 2)
797 return false;
799 // Check the first strike-out section.
800 const editeng::Section* pAttr = &aSecAttrs[0];
801 if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 0 || pAttr->mnEnd != 6)
802 return false;
804 if (pAttr->maAttributes.size() != 1 || !isStrikeOut(*pAttr))
805 return false;
807 // The last section should be unformatted.
808 pAttr = &aSecAttrs[1];
809 if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 6 || pAttr->mnEnd != 9)
810 return false;
812 return true;
815 bool checkB7(const EditTextObject* pText) const
817 if (!pText)
818 return false;
820 if (pText->GetParagraphCount() != 1)
821 return false;
823 if (pText->GetText(0) != "Font1 and Font2")
824 return false;
826 std::vector<editeng::Section> aSecAttrs;
827 pText->GetAllSections(aSecAttrs);
828 if (aSecAttrs.size() != 3)
829 return false;
831 // First section should have "Courier" font applied.
832 const editeng::Section* pAttr = &aSecAttrs[0];
833 if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 0 || pAttr->mnEnd != 5)
834 return false;
836 if (pAttr->maAttributes.size() != 1 || !isFont(*pAttr, "Courier"))
837 return false;
839 // Last section should have "Luxi Mono" applied.
840 pAttr = &aSecAttrs[2];
841 if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 10 || pAttr->mnEnd != 15)
842 return false;
844 if (pAttr->maAttributes.size() != 1 || !isFont(*pAttr, "Luxi Mono"))
845 return false;
847 return true;
850 bool checkB8(const EditTextObject* pText) const
852 if (!pText)
853 return false;
855 if (pText->GetParagraphCount() != 1)
856 return false;
858 if (pText->GetText(0) != "Over and Under")
859 return false;
861 std::vector<editeng::Section> aSecAttrs;
862 pText->GetAllSections(aSecAttrs);
863 if (aSecAttrs.size() != 3)
864 return false;
866 // First section shoul have overline applied.
867 const editeng::Section* pAttr = &aSecAttrs[0];
868 if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 0 || pAttr->mnEnd != 4)
869 return false;
871 if (pAttr->maAttributes.size() != 1 || !isOverline(*pAttr, UNDERLINE_DOUBLE))
872 return false;
874 // Last section should have underline applied.
875 pAttr = &aSecAttrs[2];
876 if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 9 || pAttr->mnEnd != 14)
877 return false;
879 if (pAttr->maAttributes.size() != 1 || !isUnderline(*pAttr, UNDERLINE_DOUBLE))
880 return false;
882 return true;
885 } aCheckFunc;
887 // Start with an empty document, put one edit text cell, and make sure it
888 // survives the save and reload.
889 ScDocShellRef xOrigDocSh = loadDoc("empty.", ODS, true);
890 const EditTextObject* pEditText;
892 ScDocument& rDoc = xOrigDocSh->GetDocument();
893 CPPUNIT_ASSERT_MESSAGE("This document should at least have one sheet.", rDoc.GetTableCount() > 0);
895 // Insert an edit text cell.
896 ScFieldEditEngine* pEE = &rDoc.GetEditEngine();
897 pEE->SetText("Bold and Italic");
898 // Set the 'Bold' part bold.
899 setAttribute(*pEE, 0, 0, 4, EE_CHAR_WEIGHT);
900 // Set the 'Italic' part italic.
901 setAttribute(*pEE, 0, 9, 15, EE_CHAR_ITALIC);
902 ESelection aSel;
903 aSel.nStartPara = aSel.nEndPara = 0;
905 // Set this edit text to cell B2.
906 rDoc.SetEditText(ScAddress(1,1,0), pEE->CreateTextObject());
907 pEditText = rDoc.GetEditText(ScAddress(1,1,0));
908 CPPUNIT_ASSERT_MESSAGE("Incorret B2 value.", aCheckFunc.checkB2(pEditText));
911 // Now, save and reload this document.
912 ScDocShellRef xNewDocSh = saveAndReload(xOrigDocSh, ODS);
914 xOrigDocSh->DoClose();
915 CPPUNIT_ASSERT(xNewDocSh.Is());
916 ScDocument& rDoc2 = xNewDocSh->GetDocument();
917 CPPUNIT_ASSERT_MESSAGE("Reloaded document should at least have one sheet.", rDoc2.GetTableCount() > 0);
918 ScFieldEditEngine* pEE = &rDoc2.GetEditEngine();
920 // Make sure the content of B2 is still intact.
921 CPPUNIT_ASSERT_MESSAGE("Incorret B2 value.", aCheckFunc.checkB2(pEditText));
923 // Insert a multi-line content to B4.
924 pEE->Clear();
925 pEE->SetText("One\nTwo\nThree");
926 rDoc2.SetEditText(ScAddress(1,3,0), pEE->CreateTextObject());
927 pEditText = rDoc2.GetEditText(ScAddress(1,3,0));
928 CPPUNIT_ASSERT_MESSAGE("Incorrect B4 value.", aCheckFunc.checkB4(pEditText));
931 // Reload the doc again, and check the content of B2 and B4.
932 ScDocShellRef xNewDocSh2 = saveAndReload(xNewDocSh, ODS);
934 ScDocument& rDoc3 = xNewDocSh2->GetDocument();
935 ScFieldEditEngine* pEE = &rDoc3.GetEditEngine();
936 xNewDocSh->DoClose();
938 pEditText = rDoc3.GetEditText(ScAddress(1,1,0));
939 CPPUNIT_ASSERT_MESSAGE("B2 should be an edit text.", pEditText);
940 pEditText = rDoc3.GetEditText(ScAddress(1,3,0));
941 CPPUNIT_ASSERT_MESSAGE("Incorrect B4 value.", aCheckFunc.checkB4(pEditText));
943 // Insert a multi-line content to B5, but this time, set some empty paragraphs.
944 pEE->Clear();
945 pEE->SetText("\nTwo\nThree\n\nFive\n");
946 rDoc3.SetEditText(ScAddress(1,4,0), pEE->CreateTextObject());
947 pEditText = rDoc3.GetEditText(ScAddress(1,4,0));
948 CPPUNIT_ASSERT_MESSAGE("Incorrect B5 value.", aCheckFunc.checkB5(pEditText));
950 // Insert a text with strikethrough in B6.
951 pEE->Clear();
952 pEE->SetText("Strike Me");
953 // Set the 'Strike' part strikethrough.
954 setAttribute(*pEE, 0, 0, 6, EE_CHAR_STRIKEOUT);
955 rDoc3.SetEditText(ScAddress(1,5,0), pEE->CreateTextObject());
956 pEditText = rDoc3.GetEditText(ScAddress(1,5,0));
957 CPPUNIT_ASSERT_MESSAGE("Incorrect B6 value.", aCheckFunc.checkB6(pEditText));
959 // Insert a text with different font segments in B7.
960 pEE->Clear();
961 pEE->SetText("Font1 and Font2");
962 setFont(*pEE, 0, 0, 5, "Courier");
963 setFont(*pEE, 0, 10, 15, "Luxi Mono");
964 rDoc3.SetEditText(ScAddress(1,6,0), pEE->CreateTextObject());
965 pEditText = rDoc3.GetEditText(ScAddress(1,6,0));
966 CPPUNIT_ASSERT_MESSAGE("Incorrect B7 value.", aCheckFunc.checkB7(pEditText));
968 // Insert a text with overline and underline in B8.
969 pEE->Clear();
970 pEE->SetText("Over and Under");
971 setAttribute(*pEE, 0, 0, 4, EE_CHAR_OVERLINE);
972 setAttribute(*pEE, 0, 9, 14, EE_CHAR_UNDERLINE);
973 rDoc3.SetEditText(ScAddress(1,7,0), pEE->CreateTextObject());
974 pEditText = rDoc3.GetEditText(ScAddress(1,7,0));
975 CPPUNIT_ASSERT_MESSAGE("Incorrect B8 value.", aCheckFunc.checkB8(pEditText));
978 // Reload the doc again, and check the content of B2, B4, B6 and B7.
979 ScDocShellRef xNewDocSh3 = saveAndReload(xNewDocSh2, ODS);
980 ScDocument& rDoc4 = xNewDocSh3->GetDocument();
981 xNewDocSh2->DoClose();
983 pEditText = rDoc4.GetEditText(ScAddress(1,1,0));
984 CPPUNIT_ASSERT_MESSAGE("Incorrect B2 value after save and reload.", aCheckFunc.checkB2(pEditText));
985 pEditText = rDoc4.GetEditText(ScAddress(1,3,0));
986 CPPUNIT_ASSERT_MESSAGE("Incorrect B4 value after save and reload.", aCheckFunc.checkB4(pEditText));
987 pEditText = rDoc4.GetEditText(ScAddress(1,4,0));
988 CPPUNIT_ASSERT_MESSAGE("Incorrect B5 value after save and reload.", aCheckFunc.checkB5(pEditText));
989 pEditText = rDoc4.GetEditText(ScAddress(1,5,0));
990 CPPUNIT_ASSERT_MESSAGE("Incorrect B6 value after save and reload.", aCheckFunc.checkB6(pEditText));
991 pEditText = rDoc4.GetEditText(ScAddress(1,6,0));
992 CPPUNIT_ASSERT_MESSAGE("Incorrect B7 value after save and reload.", aCheckFunc.checkB7(pEditText));
993 pEditText = rDoc4.GetEditText(ScAddress(1,7,0));
994 CPPUNIT_ASSERT_MESSAGE("Incorrect B8 value after save and reload.", aCheckFunc.checkB8(pEditText));
996 xNewDocSh3->DoClose();
999 void ScExportTest::testFormulaRefSheetNameODS()
1001 ScDocShellRef xDocSh = loadDoc("formula-quote-in-sheet-name.", ODS, true);
1003 ScDocument& rDoc = xDocSh->GetDocument();
1005 sc::AutoCalcSwitch aACSwitch(rDoc, true); // turn on auto calc.
1006 rDoc.SetString(ScAddress(1,1,0), "='90''s Data'.B2");
1007 CPPUNIT_ASSERT_EQUAL(1.1, rDoc.GetValue(ScAddress(1,1,0)));
1008 if (!checkFormula(rDoc, ScAddress(1,1,0), "'90''s Data'.B2"))
1009 CPPUNIT_FAIL("Wrong formula");
1011 // Now, save and reload this document.
1012 ScDocShellRef xNewDocSh = saveAndReload(xDocSh, ODS);
1013 xDocSh->DoClose();
1015 ScDocument& rDoc = xNewDocSh->GetDocument();
1016 rDoc.CalcAll();
1017 CPPUNIT_ASSERT_EQUAL(1.1, rDoc.GetValue(ScAddress(1,1,0)));
1018 if (!checkFormula(rDoc, ScAddress(1,1,0), "'90''s Data'.B2"))
1019 CPPUNIT_FAIL("Wrong formula");
1021 xNewDocSh->DoClose();
1024 void ScExportTest::testCellValuesExportODS()
1026 // Start with an empty document
1027 ScDocShellRef xOrigDocSh = loadDoc("empty.", ODS);
1029 ScDocument& rDoc = xOrigDocSh->GetDocument();
1030 CPPUNIT_ASSERT_MESSAGE("This document should at least have one sheet.", rDoc.GetTableCount() > 0);
1032 // set a value double
1033 rDoc.SetValue(ScAddress(0,0,0), 2.0); // A1
1035 // set a formula
1036 rDoc.SetValue(ScAddress(2,0,0), 3.0); // C1
1037 rDoc.SetValue(ScAddress(3,0,0), 3); // D1
1038 rDoc.SetString(ScAddress(4,0,0), "=10*C1/4"); // E1
1039 rDoc.SetValue(ScAddress(5,0,0), 3.0); // F1
1040 rDoc.SetString(ScAddress(7,0,0), "=SUM(C1:F1)"); //H1
1042 // set a string
1043 rDoc.SetString(ScAddress(0,2,0), "a simple line"); //A3
1045 // set a digit string
1046 rDoc.SetString(ScAddress(0,4,0), "'12"); //A5
1047 // set a contiguous value
1048 rDoc.SetValue(ScAddress(0,5,0), 12.0); //A6
1049 // set acontiguous string
1050 rDoc.SetString(ScAddress(0,6,0), "a string"); //A7
1051 // set a contiguous formula
1052 rDoc.SetString(ScAddress(0,7,0), "=$A$6"); //A8
1054 // save and reload
1055 ScDocShellRef xNewDocSh = saveAndReload(xOrigDocSh, ODS);
1056 xOrigDocSh->DoClose();
1057 CPPUNIT_ASSERT(xNewDocSh.Is());
1058 ScDocument& rDoc = xNewDocSh->GetDocument();
1059 CPPUNIT_ASSERT_MESSAGE("Reloaded document should at least have one sheet.", rDoc.GetTableCount() > 0);
1061 // check value
1062 CPPUNIT_ASSERT_EQUAL(2.0, rDoc.GetValue(0,0,0));
1063 CPPUNIT_ASSERT_EQUAL(3.0, rDoc.GetValue(2,0,0));
1064 CPPUNIT_ASSERT_EQUAL(3.0, rDoc.GetValue(3,0,0));
1065 CPPUNIT_ASSERT_EQUAL(7.5, rDoc.GetValue(4,0,0));
1066 CPPUNIT_ASSERT_EQUAL(3.0, rDoc.GetValue(5,0,0));
1068 // check formula
1069 if (!checkFormula(rDoc, ScAddress(4,0,0), "10*C1/4"))
1070 CPPUNIT_FAIL("Wrong formula =10*C1/4");
1071 if (!checkFormula(rDoc, ScAddress(7,0,0), "SUM(C1:F1)"))
1072 CPPUNIT_FAIL("Wrong formula =SUM(C1:F1)");
1073 CPPUNIT_ASSERT_EQUAL(16.5, rDoc.GetValue(7,0,0));
1075 // check string
1076 ScRefCellValue aCell;
1077 aCell.assign(rDoc, ScAddress(0,2,0));
1078 CPPUNIT_ASSERT_EQUAL( CELLTYPE_STRING, aCell.meType );
1080 // check for an empty cell
1081 aCell.assign(rDoc, ScAddress(0,3,0));
1082 CPPUNIT_ASSERT_EQUAL( CELLTYPE_NONE, aCell.meType);
1084 // check a digit string
1085 aCell.assign(rDoc, ScAddress(0,4,0));
1086 CPPUNIT_ASSERT_EQUAL( CELLTYPE_STRING, aCell.meType);
1088 //check contiguous values
1089 CPPUNIT_ASSERT_EQUAL( 12.0, rDoc.GetValue(0,5,0) );
1090 CPPUNIT_ASSERT_EQUAL( OUString("a string"), rDoc.GetString(0,6,0) );
1091 if (!checkFormula(rDoc, ScAddress(0,7,0), "$A$6"))
1092 CPPUNIT_FAIL("Wrong formula =$A$6");
1093 CPPUNIT_ASSERT_EQUAL( rDoc.GetValue(0,5,0), rDoc.GetValue(0,7,0) );
1095 xNewDocSh->DoClose();
1098 void ScExportTest::testCellNoteExportODS()
1100 ScDocShellRef xOrigDocSh = loadDoc("single-note.", ODS);
1101 ScAddress aPos(0,0,0); // Start with A1.
1103 ScDocument& rDoc = xOrigDocSh->GetDocument();
1105 CPPUNIT_ASSERT_MESSAGE("There should be a note at A1.", rDoc.HasNote(aPos));
1107 aPos.IncRow(); // Move to A2.
1108 ScPostIt* pNote = rDoc.GetOrCreateNote(aPos);
1109 pNote->SetText(aPos, "Note One");
1110 pNote->SetAuthor("Author One");
1111 CPPUNIT_ASSERT_MESSAGE("There should be a note at A2.", rDoc.HasNote(aPos));
1113 // save and reload
1114 ScDocShellRef xNewDocSh = saveAndReload(xOrigDocSh, ODS);
1115 xOrigDocSh->DoClose();
1116 CPPUNIT_ASSERT(xNewDocSh.Is());
1117 ScDocument& rDoc = xNewDocSh->GetDocument();
1119 aPos.SetRow(0); // Move back to A1.
1120 CPPUNIT_ASSERT_MESSAGE("There should be a note at A1.", rDoc.HasNote(aPos));
1121 aPos.IncRow(); // Move to A2.
1122 CPPUNIT_ASSERT_MESSAGE("There should be a note at A2.", rDoc.HasNote(aPos));
1124 xNewDocSh->DoClose();
1127 void ScExportTest::testCellNoteExportXLS()
1129 // Start with an empty document.s
1130 ScDocShellRef xOrigDocSh = loadDoc("notes-on-3-sheets.", ODS);
1132 ScDocument& rDoc = xOrigDocSh->GetDocument();
1133 CPPUNIT_ASSERT_MESSAGE("This document should have 3 sheets.", rDoc.GetTableCount() == 3);
1135 // Check note's presence.
1136 CPPUNIT_ASSERT( rDoc.HasNote(ScAddress(0,0,0)));
1137 CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,1,0)));
1138 CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,2,0)));
1140 CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,0,1)));
1141 CPPUNIT_ASSERT( rDoc.HasNote(ScAddress(0,1,1)));
1142 CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,2,1)));
1144 CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,0,2)));
1145 CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,1,2)));
1146 CPPUNIT_ASSERT( rDoc.HasNote(ScAddress(0,2,2)));
1148 // save and reload as XLS.
1149 ScDocShellRef xNewDocSh = saveAndReload(xOrigDocSh, XLS);
1151 xOrigDocSh->DoClose();
1152 CPPUNIT_ASSERT(xNewDocSh.Is());
1153 ScDocument& rDoc = xNewDocSh->GetDocument();
1154 CPPUNIT_ASSERT_MESSAGE("This document should have 3 sheets.", rDoc.GetTableCount() == 3);
1156 // Check note's presence again.
1157 CPPUNIT_ASSERT( rDoc.HasNote(ScAddress(0,0,0)));
1158 CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,1,0)));
1159 CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,2,0)));
1161 CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,0,1)));
1162 CPPUNIT_ASSERT( rDoc.HasNote(ScAddress(0,1,1)));
1163 CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,2,1)));
1165 CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,0,2)));
1166 CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,1,2)));
1167 CPPUNIT_ASSERT( rDoc.HasNote(ScAddress(0,2,2)));
1169 xNewDocSh->DoClose();
1173 namespace {
1175 void checkMatrixRange(ScDocument& rDoc, const ScRange& rRange)
1177 ScRange aMatRange;
1178 ScAddress aMatOrigin;
1179 for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
1181 for (SCROW nRow = rRange.aStart.Row(); nRow <= rRange.aEnd.Row(); ++nRow)
1183 ScAddress aPos(nCol, nRow, rRange.aStart.Tab());
1184 bool bIsMatrix = rDoc.GetMatrixFormulaRange(aPos, aMatRange);
1185 CPPUNIT_ASSERT_MESSAGE("Matrix expected, but not found.", bIsMatrix);
1186 CPPUNIT_ASSERT_MESSAGE("Wrong matrix range.", rRange == aMatRange);
1187 const ScFormulaCell* pCell = rDoc.GetFormulaCell(aPos);
1188 CPPUNIT_ASSERT_MESSAGE("This must be a formula cell.", pCell);
1190 bIsMatrix = pCell->GetMatrixOrigin(aMatOrigin);
1191 CPPUNIT_ASSERT_MESSAGE("Not a part of matrix formula.", bIsMatrix);
1192 CPPUNIT_ASSERT_MESSAGE("Wrong matrix origin.", aMatOrigin == aMatRange.aStart);
1199 void ScExportTest::testInlineArrayXLS()
1201 ScDocShellRef xShell = loadDoc("inline-array.", XLS);
1202 CPPUNIT_ASSERT(xShell.Is());
1204 ScDocShellRef xDocSh = saveAndReload(xShell, XLS);
1205 xShell->DoClose();
1206 CPPUNIT_ASSERT(xDocSh.Is());
1208 ScDocument& rDoc = xDocSh->GetDocument();
1210 // B2:C3 contains a matrix.
1211 checkMatrixRange(rDoc, ScRange(1,1,0,2,2,0));
1213 // B5:D6 contains a matrix.
1214 checkMatrixRange(rDoc, ScRange(1,4,0,3,5,0));
1216 // B8:C10 as well.
1217 checkMatrixRange(rDoc, ScRange(1,7,0,2,9,0));
1219 xDocSh->DoClose();
1222 void ScExportTest::testEmbeddedChartXLS()
1224 ScDocShellRef xShell = loadDoc("embedded-chart.", XLS);
1225 CPPUNIT_ASSERT(xShell.Is());
1227 ScDocShellRef xDocSh = saveAndReload(xShell, XLS);
1228 xShell->DoClose();
1229 CPPUNIT_ASSERT(xDocSh.Is());
1231 ScDocument& rDoc = xDocSh->GetDocument();
1233 // Make sure the 2nd sheet is named 'Chart1'.
1234 OUString aName;
1235 rDoc.GetName(1, aName);
1236 CPPUNIT_ASSERT_EQUAL(OUString("Chart1"), aName);
1238 const SdrOle2Obj* pOleObj = getSingleChartObject(rDoc, 1);
1239 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve a chart object from the 2nd sheet.", pOleObj);
1241 ScRangeList aRanges = getChartRanges(rDoc, *pOleObj);
1242 CPPUNIT_ASSERT_MESSAGE("Label range (B3:B5) not found.", aRanges.In(ScRange(1,2,1,1,4,1)));
1243 CPPUNIT_ASSERT_MESSAGE("Data label (C2) not found.", aRanges.In(ScAddress(2,1,1)));
1244 CPPUNIT_ASSERT_MESSAGE("Data range (C3:C5) not found.", aRanges.In(ScRange(2,2,1,2,4,1)));
1246 xDocSh->DoClose();
1249 void ScExportTest::testFormulaReferenceXLS()
1251 ScDocShellRef xShell = loadDoc("formula-reference.", XLS);
1252 CPPUNIT_ASSERT(xShell.Is());
1254 ScDocShellRef xDocSh = saveAndReload(xShell, XLS);
1255 xShell->DoClose();
1256 CPPUNIT_ASSERT(xDocSh.Is());
1258 ScDocument& rDoc = xDocSh->GetDocument();
1260 if (!checkFormula(rDoc, ScAddress(3,1,0), "$A$2+$B$2+$C$2"))
1261 CPPUNIT_FAIL("Wrong formula in D2");
1263 if (!checkFormula(rDoc, ScAddress(3,2,0), "A3+B3+C3"))
1264 CPPUNIT_FAIL("Wrong formula in D3");
1266 if (!checkFormula(rDoc, ScAddress(3,5,0), "SUM($A$6:$C$6)"))
1267 CPPUNIT_FAIL("Wrong formula in D6");
1269 if (!checkFormula(rDoc, ScAddress(3,6,0), "SUM(A7:C7)"))
1270 CPPUNIT_FAIL("Wrong formula in D7");
1272 if (!checkFormula(rDoc, ScAddress(3,9,0), "$Two.$A$2+$Two.$B$2+$Two.$C$2"))
1273 CPPUNIT_FAIL("Wrong formula in D10");
1275 if (!checkFormula(rDoc, ScAddress(3,10,0), "$Two.A3+$Two.B3+$Two.C3"))
1276 CPPUNIT_FAIL("Wrong formula in D11");
1278 if (!checkFormula(rDoc, ScAddress(3,13,0), "MIN($Two.$A$2:$C$2)"))
1279 CPPUNIT_FAIL("Wrong formula in D14");
1281 if (!checkFormula(rDoc, ScAddress(3,14,0), "MAX($Two.A3:C3)"))
1282 CPPUNIT_FAIL("Wrong formula in D15");
1284 xDocSh->DoClose();
1287 void ScExportTest::testSheetProtectionXLSX()
1289 ScDocShellRef xShell = loadDoc("ProtecteSheet1234Pass.", XLSX);
1290 CPPUNIT_ASSERT(xShell.Is());
1292 ScDocShellRef xDocSh = saveAndReload(xShell, XLSX);
1293 CPPUNIT_ASSERT(xDocSh.Is());
1295 ScDocument& rDoc = xDocSh->GetDocument();
1296 const ScTableProtection* pTabProtect = rDoc.GetTabProtection(0);
1297 CPPUNIT_ASSERT(pTabProtect);
1298 if ( pTabProtect )
1300 Sequence<sal_Int8> aHash = pTabProtect->getPasswordHash(PASSHASH_XL);
1301 // check has
1302 if (aHash.getLength() >= 2)
1304 CPPUNIT_ASSERT( (sal_uInt8)aHash[0] == 204 );
1305 CPPUNIT_ASSERT( (sal_uInt8)aHash[1] == 61 );
1307 // we could flesh out this check I guess
1308 CPPUNIT_ASSERT ( !pTabProtect->isOptionEnabled( ScTableProtection::OBJECTS ) );
1309 CPPUNIT_ASSERT ( !pTabProtect->isOptionEnabled( ScTableProtection::SCENARIOS ) );
1311 xDocSh->DoClose();
1314 namespace {
1316 const char* toBorderName( sal_Int16 eStyle )
1318 switch (eStyle)
1320 case table::BorderLineStyle::SOLID: return "SOLID";
1321 case table::BorderLineStyle::DOTTED: return "DOTTED";
1322 case table::BorderLineStyle::DASHED: return "DASHED";
1323 case table::BorderLineStyle::DASH_DOT: return "DASH_DOT";
1324 case table::BorderLineStyle::DASH_DOT_DOT: return "DASH_DOT_DOT";
1325 case table::BorderLineStyle::DOUBLE_THIN: return "DOUBLE_THIN";
1326 case table::BorderLineStyle::FINE_DASHED: return "FINE_DASHED";
1327 default:
1331 return "";
1336 void ScExportTest::testExcelCellBorders( sal_uLong nFormatType )
1338 struct
1340 SCROW mnRow;
1341 sal_Int16 mnStyle;
1342 long mnWidth;
1343 } aChecks[] = {
1344 { 1, table::BorderLineStyle::SOLID, 1L }, // hair
1345 { 3, table::BorderLineStyle::DOTTED, 15L }, // dotted
1346 { 5, table::BorderLineStyle::DASH_DOT_DOT, 15L }, // dash dot dot
1347 { 7, table::BorderLineStyle::DASH_DOT, 15L }, // dash dot
1348 { 9, table::BorderLineStyle::FINE_DASHED, 15L }, // dashed
1349 { 11, table::BorderLineStyle::SOLID, 15L }, // thin
1350 { 13, table::BorderLineStyle::DASH_DOT_DOT, 35L }, // medium dash dot dot
1351 { 17, table::BorderLineStyle::DASH_DOT, 35L }, // medium dash dot
1352 { 19, table::BorderLineStyle::DASHED, 35L }, // medium dashed
1353 { 21, table::BorderLineStyle::SOLID, 35L }, // medium
1354 { 23, table::BorderLineStyle::SOLID, 50L }, // thick
1355 { 25, table::BorderLineStyle::DOUBLE_THIN, -1L }, // double (don't check width)
1358 ScDocShellRef xDocSh = loadDoc("cell-borders.", nFormatType);
1359 CPPUNIT_ASSERT_MESSAGE("Failed to load file", xDocSh.Is());
1361 ScDocument& rDoc = xDocSh->GetDocument();
1363 for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
1365 const editeng::SvxBorderLine* pLine = NULL;
1366 rDoc.GetBorderLines(2, aChecks[i].mnRow, 0, NULL, &pLine, NULL, NULL);
1367 CPPUNIT_ASSERT(pLine);
1368 CPPUNIT_ASSERT_EQUAL(toBorderName(aChecks[i].mnStyle), toBorderName(pLine->GetBorderLineStyle()));
1369 if (aChecks[i].mnWidth >= 0)
1370 CPPUNIT_ASSERT_EQUAL(aChecks[i].mnWidth, pLine->GetWidth());
1374 ScDocShellRef xNewDocSh = saveAndReload(xDocSh, nFormatType);
1375 xDocSh->DoClose();
1376 ScDocument& rDoc = xNewDocSh->GetDocument();
1377 for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
1379 const editeng::SvxBorderLine* pLine = NULL;
1380 rDoc.GetBorderLines(2, aChecks[i].mnRow, 0, NULL, &pLine, NULL, NULL);
1381 CPPUNIT_ASSERT(pLine);
1382 CPPUNIT_ASSERT_EQUAL(toBorderName(aChecks[i].mnStyle), toBorderName(pLine->GetBorderLineStyle()));
1383 if (aChecks[i].mnWidth >= 0)
1384 CPPUNIT_ASSERT_EQUAL(aChecks[i].mnWidth, pLine->GetWidth());
1387 xNewDocSh->DoClose();
1390 void ScExportTest::testCellBordersXLS()
1392 testExcelCellBorders(XLS);
1395 void ScExportTest::testCellBordersXLSX()
1397 testExcelCellBorders(XLSX);
1400 OUString toString( const ScBigRange& rRange )
1402 OUStringBuffer aBuf;
1403 aBuf.appendAscii("(columns:");
1404 aBuf.append(rRange.aStart.Col());
1405 aBuf.append('-');
1406 aBuf.append(rRange.aEnd.Col());
1407 aBuf.appendAscii(";rows:");
1408 aBuf.append(rRange.aStart.Row());
1409 aBuf.append('-');
1410 aBuf.append(rRange.aEnd.Row());
1411 aBuf.appendAscii(";sheets:");
1412 aBuf.append(rRange.aStart.Tab());
1413 aBuf.append('-');
1414 aBuf.append(rRange.aEnd.Tab());
1415 aBuf.append(')');
1417 return aBuf.makeStringAndClear();
1420 void ScExportTest::testTrackChangesSimpleXLSX()
1422 struct CheckItem
1424 sal_uLong mnActionId;
1425 ScChangeActionType meType;
1427 sal_Int32 mnStartCol;
1428 sal_Int32 mnStartRow;
1429 sal_Int32 mnStartTab;
1430 sal_Int32 mnEndCol;
1431 sal_Int32 mnEndRow;
1432 sal_Int32 mnEndTab;
1434 bool mbRowInsertedAtBottom;
1437 struct
1439 bool checkRange( ScChangeActionType eType, const ScBigRange& rExpected, const ScBigRange& rActual )
1441 ScBigRange aExpected(rExpected), aActual(rActual);
1443 switch (eType)
1445 case SC_CAT_INSERT_ROWS:
1447 // Ignore columns.
1448 aExpected.aStart.SetCol(0);
1449 aExpected.aEnd.SetCol(0);
1450 aActual.aStart.SetCol(0);
1451 aActual.aEnd.SetCol(0);
1453 break;
1454 default:
1458 return aExpected == aActual;
1461 bool check( ScDocument& rDoc )
1463 CheckItem aChecks[] =
1465 { 1, SC_CAT_CONTENT , 1, 1, 0, 1, 1, 0, false },
1466 { 2, SC_CAT_INSERT_ROWS , 0, 2, 0, 0, 2, 0, true },
1467 { 3, SC_CAT_CONTENT , 1, 2, 0, 1, 2, 0, false },
1468 { 4, SC_CAT_INSERT_ROWS , 0, 3, 0, 0, 3, 0, true },
1469 { 5, SC_CAT_CONTENT , 1, 3, 0, 1, 3, 0, false },
1470 { 6, SC_CAT_INSERT_ROWS , 0, 4, 0, 0, 4, 0, true },
1471 { 7, SC_CAT_CONTENT , 1, 4, 0, 1, 4, 0, false },
1472 { 8, SC_CAT_INSERT_ROWS , 0, 5, 0, 0, 5, 0, true },
1473 { 9, SC_CAT_CONTENT , 1, 5, 0, 1, 5, 0, false },
1474 { 10, SC_CAT_INSERT_ROWS , 0, 6, 0, 0, 6, 0, true },
1475 { 11, SC_CAT_CONTENT , 1, 6, 0, 1, 6, 0, false },
1476 { 12, SC_CAT_INSERT_ROWS , 0, 7, 0, 0, 7, 0, true },
1477 { 13, SC_CAT_CONTENT , 1, 7, 0, 1, 7, 0, false },
1480 ScChangeTrack* pCT = rDoc.GetChangeTrack();
1481 if (!pCT)
1483 cerr << "Change track instance doesn't exist." << endl;
1484 return false;
1487 sal_uLong nActionMax = pCT->GetActionMax();
1488 if (nActionMax != 13)
1490 cerr << "Unexpected highest action ID value." << endl;
1491 return false;
1494 for (size_t i = 0, n = SAL_N_ELEMENTS(aChecks); i < n; ++i)
1496 sal_uInt16 nActId = aChecks[i].mnActionId;
1497 const ScChangeAction* pAction = pCT->GetAction(nActId);
1498 if (!pAction)
1500 cerr << "No action for action number " << nActId << " found." << endl;
1501 return false;
1504 if (pAction->GetType() != aChecks[i].meType)
1506 cerr << "Unexpected action type for action number " << nActId << "." << endl;
1507 return false;
1510 const ScBigRange& rRange = pAction->GetBigRange();
1511 ScBigRange aCheck(aChecks[i].mnStartCol, aChecks[i].mnStartRow, aChecks[i].mnStartTab,
1512 aChecks[i].mnEndCol, aChecks[i].mnEndRow, aChecks[i].mnEndTab);
1514 if (!checkRange(pAction->GetType(), aCheck, rRange))
1516 cerr << "Unexpected range for action number " << nActId
1517 << ": expected=" << toString(aCheck) << " actual=" << toString(rRange) << endl;
1518 return false;
1521 switch (pAction->GetType())
1523 case SC_CAT_INSERT_ROWS:
1525 const ScChangeActionIns* p = static_cast<const ScChangeActionIns*>(pAction);
1526 if (p->IsEndOfList() != aChecks[i].mbRowInsertedAtBottom)
1528 cerr << "Unexpected end-of-list flag for action number " << nActId << "." << endl;
1529 return false;
1532 break;
1533 default:
1538 return true;
1541 bool checkRevisionUserAndTime( ScDocument& rDoc, const OUString& rOwnerName )
1543 ScChangeTrack* pCT = rDoc.GetChangeTrack();
1544 if (!pCT)
1546 cerr << "Change track instance doesn't exist." << endl;
1547 return false;
1550 ScChangeAction* pAction = pCT->GetLast();
1551 if (pAction->GetUser() != "Kohei Yoshida")
1553 cerr << "Wrong user name." << endl;
1554 return false;
1557 DateTime aDT = pAction->GetDateTime();
1558 if (aDT.GetYear() != 2014 || aDT.GetMonth() != 7 || aDT.GetDay() != 11)
1560 cerr << "Wrong time stamp." << endl;
1561 return false;
1564 // Insert a new record to make sure the user and date-time are correct.
1565 rDoc.SetString(ScAddress(1,8,0), "New String");
1566 ScCellValue aEmpty;
1567 pCT->AppendContent(ScAddress(1,8,0), aEmpty);
1568 pAction = pCT->GetLast();
1569 if (!pAction)
1571 cerr << "Failed to retrieve last revision." << endl;
1572 return false;
1575 if (rOwnerName != pAction->GetUser())
1577 cerr << "Wrong user name." << endl;
1578 return false;
1581 DateTime aDTNew = pAction->GetDateTime();
1582 if (aDTNew <= aDT)
1584 cerr << "Time stamp of the new revision should be more recent than that of the last revision." << endl;
1585 return false;
1588 return true;
1591 } aTest;
1593 SvtUserOptions& rUserOpt = SC_MOD()->GetUserOptions();
1594 rUserOpt.SetToken(UserOptToken::FirstName, "Export");
1595 rUserOpt.SetToken(UserOptToken::LastName, "Test");
1597 OUString aOwnerName = rUserOpt.GetFirstName() + " " + rUserOpt.GetLastName();
1599 // First, test the xls variant.
1601 ScDocShellRef xDocSh = loadDoc("track-changes/simple-cell-changes.", XLS);
1602 CPPUNIT_ASSERT(xDocSh.Is());
1603 ScDocument* pDoc = &xDocSh->GetDocument();
1604 bool bGood = aTest.check(*pDoc);
1605 CPPUNIT_ASSERT_MESSAGE("Initial check failed (xls).", bGood);
1607 ScDocShellRef xDocSh2 = saveAndReload(xDocSh, XLS);
1608 xDocSh->DoClose();
1609 pDoc = &xDocSh2->GetDocument();
1610 bGood = aTest.check(*pDoc);
1611 CPPUNIT_ASSERT_MESSAGE("Check after reload failed (xls).", bGood);
1613 // fdo#81445 : Check the blank value string to make sure it's "<empty>".
1614 ScChangeTrack* pCT = pDoc->GetChangeTrack();
1615 CPPUNIT_ASSERT(pCT);
1616 ScChangeAction* pAction = pCT->GetAction(1);
1617 CPPUNIT_ASSERT(pAction);
1618 OUString aDesc;
1619 pAction->GetDescription(aDesc, pDoc);
1620 CPPUNIT_ASSERT_EQUAL(OUString("Cell B2 changed from '<empty>' to '1'"), aDesc);
1622 bGood = aTest.checkRevisionUserAndTime(*pDoc, aOwnerName);
1623 CPPUNIT_ASSERT_MESSAGE("Check revision and time failed after reload (xls).", bGood);
1625 xDocSh2->DoClose();
1627 // Now, test the xlsx variant the same way.
1629 xDocSh = loadDoc("track-changes/simple-cell-changes.", XLSX);
1630 CPPUNIT_ASSERT(xDocSh.Is());
1631 pDoc = &xDocSh->GetDocument();
1632 aTest.check(*pDoc);
1633 CPPUNIT_ASSERT_MESSAGE("Initial check failed (xlsx).", bGood);
1635 xDocSh2 = saveAndReload(xDocSh, XLSX);
1636 xDocSh->DoClose();
1637 pDoc = &xDocSh2->GetDocument();
1638 bGood = aTest.check(*pDoc);
1639 CPPUNIT_ASSERT_MESSAGE("Check after reload failed (xlsx).", bGood);
1641 bGood = aTest.checkRevisionUserAndTime(*pDoc, aOwnerName);
1642 CPPUNIT_ASSERT_MESSAGE("Check revision and time failed after reload (xlsx).", bGood);
1644 xDocSh2->DoClose();
1647 void ScExportTest::testSheetTabColorsXLSX()
1649 struct
1651 bool checkContent( ScDocument& rDoc )
1654 std::vector<OUString> aTabNames = rDoc.GetAllTableNames();
1656 // green, red, blue, yellow (from left to right).
1657 if (aTabNames.size() != 4)
1659 cerr << "There should be exactly 4 sheets." << endl;
1660 return false;
1663 const char* pNames[] = { "Green", "Red", "Blue", "Yellow" };
1664 for (size_t i = 0, n = SAL_N_ELEMENTS(pNames); i < n; ++i)
1666 OUString aExpected = OUString::createFromAscii(pNames[i]);
1667 if (aExpected != aTabNames[i])
1669 cerr << "incorrect sheet name: expected='" << aExpected <<"', actual='" << aTabNames[i] << "'" << endl;
1670 return false;
1674 const ColorData aXclColors[] =
1676 0x0000B050, // green
1677 0x00FF0000, // red
1678 0x000070C0, // blue
1679 0x00FFFF00, // yellow
1682 for (size_t i = 0, n = SAL_N_ELEMENTS(aXclColors); i < n; ++i)
1684 if (aXclColors[i] != rDoc.GetTabBgColor(i).GetColor())
1686 cerr << "wrong sheet color for sheet " << i << endl;
1687 return false;
1691 return true;
1694 } aTest;
1696 ScDocShellRef xDocSh = loadDoc("sheet-tab-color.", XLSX);
1698 CPPUNIT_ASSERT_MESSAGE("Failed to load file.", xDocSh.Is());
1699 ScDocument& rDoc = xDocSh->GetDocument();
1700 bool bRes = aTest.checkContent(rDoc);
1701 CPPUNIT_ASSERT_MESSAGE("Failed on the initial content check.", bRes);
1704 ScDocShellRef xDocSh2 = saveAndReload(xDocSh, XLSX);
1705 CPPUNIT_ASSERT_MESSAGE("Failed to reload file.", xDocSh2.Is());
1706 xDocSh->DoClose();
1707 ScDocument& rDoc = xDocSh2->GetDocument();
1708 bool bRes = aTest.checkContent(rDoc);
1709 CPPUNIT_ASSERT_MESSAGE("Failed on the content check after reload.", bRes);
1711 xDocSh2->DoClose();
1714 void ScExportTest::testSharedFormulaExportXLS()
1716 struct
1718 bool checkContent( ScDocument& rDoc )
1720 formula::FormulaGrammar::Grammar eGram = formula::FormulaGrammar::GRAM_ENGLISH_XL_R1C1;
1721 rDoc.SetGrammar(eGram);
1722 sc::TokenStringContext aCxt(&rDoc, eGram);
1724 // Check the title row.
1726 OUString aActual = rDoc.GetString(0,1,0);
1727 OUString aExpected = "Response";
1728 if (aActual != aExpected)
1730 cerr << "Wrong content in A2: expected='" << aExpected << "', actual='" << aActual << "'" << endl;
1731 return false;
1734 aActual = rDoc.GetString(1,1,0);
1735 aExpected = "Response";
1736 if (aActual != aExpected)
1738 cerr << "Wrong content in B2: expected='" << aExpected << "', actual='" << aActual << "'" << endl;
1739 return false;
1742 // A3:A12 and B3:B12 are numbers from 1 to 10.
1743 for (SCROW i = 0; i <= 9; ++i)
1745 double fExpected = i + 1.0;
1746 ScAddress aPos(0,i+2,0);
1747 double fActual = rDoc.GetValue(aPos);
1748 if (fExpected != fActual)
1750 cerr << "Wrong value in A" << (i+2) << ": expected=" << fExpected << ", actual=" << fActual << endl;
1751 return false;
1754 aPos.IncCol();
1755 ScFormulaCell* pFC = rDoc.GetFormulaCell(aPos);
1756 if (!pFC)
1758 cerr << "B" << (i+2) << " should be a formula cell." << endl;
1759 return false;
1762 OUString aFormula = pFC->GetCode()->CreateString(aCxt, aPos);
1763 aExpected = "Coefficients!RC[-1]";
1764 if (aFormula != aExpected)
1766 cerr << "Wrong formula in B" << (i+2) << ": expected='" << aExpected << "', actual='" << aFormula << "'" << endl;
1767 return false;
1770 fActual = rDoc.GetValue(aPos);
1771 if (fExpected != fActual)
1773 cerr << "Wrong value in B" << (i+2) << ": expected=" << fExpected << ", actual=" << fActual << endl;
1774 return false;
1778 return true;
1781 } aTest;
1783 ScDocShellRef xDocSh = loadDoc("shared-formula/3d-reference.", ODS);
1785 CPPUNIT_ASSERT_MESSAGE("Failed to load file.", xDocSh.Is());
1786 ScDocument& rDoc = xDocSh->GetDocument();
1788 // Check the content of the original.
1789 bool bRes = aTest.checkContent(rDoc);
1790 CPPUNIT_ASSERT_MESSAGE("Content check on the original document failed.", bRes);
1793 ScDocShellRef xDocSh2 = saveAndReload(xDocSh, XLS);
1794 xDocSh->DoClose();
1795 CPPUNIT_ASSERT_MESSAGE("Failed to reload file.", xDocSh2.Is());
1797 ScDocument& rDoc = xDocSh2->GetDocument();
1799 // Check the content of the reloaded. This should be identical.
1800 bool bRes = aTest.checkContent(rDoc);
1801 CPPUNIT_ASSERT_MESSAGE("Content check on the reloaded document failed.", bRes);
1803 xDocSh2->DoClose();
1806 void ScExportTest::testSharedFormulaExportXLSX()
1808 struct
1810 bool checkContent( ScDocument& rDoc )
1812 SCTAB nTabCount = rDoc.GetTableCount();
1813 if (nTabCount != 2)
1815 cerr << "Document should have exactly 2 sheets. " << nTabCount << " found." << endl;
1816 return false;
1819 // Make sure the sheet tab colors are not set.
1820 for (SCROW i = 0; i <= 1; ++i)
1822 Color aTabBgColor = rDoc.GetTabBgColor(i);
1823 if (aTabBgColor != Color(COL_AUTO))
1825 cerr << "The tab color of Sheet " << (i+1) << " should not be explicitly set." << endl;
1826 return false;
1830 // B2:B7 should show 1,2,3,4,5,6.
1831 double fExpected = 1.0;
1832 for (SCROW i = 1; i <= 6; ++i, ++fExpected)
1834 ScAddress aPos(1,i,0);
1835 double fVal = rDoc.GetValue(aPos);
1836 if (fVal != fExpected)
1838 cerr << "Wrong value in B" << (i+1) << ": expected=" << fExpected << ", actual=" << fVal << endl;
1839 return false;
1843 // C2:C7 should show 10,20,....,60.
1844 fExpected = 10.0;
1845 for (SCROW i = 1; i <= 6; ++i, fExpected+=10.0)
1847 ScAddress aPos(2,i,0);
1848 double fVal = rDoc.GetValue(aPos);
1849 if (fVal != fExpected)
1851 cerr << "Wrong value in C" << (i+1) << ": expected=" << fExpected << ", actual=" << fVal << endl;
1852 return false;
1856 // D2:D7 should show 1,2,...,6.
1857 fExpected = 1.0;
1858 for (SCROW i = 1; i <= 6; ++i, ++fExpected)
1860 ScAddress aPos(3,i,0);
1861 double fVal = rDoc.GetValue(aPos);
1862 if (fVal != fExpected)
1864 cerr << "Wrong value in D" << (i+1) << ": expected=" << fExpected << ", actual=" << fVal << endl;
1865 return false;
1869 return true;
1872 } aTest;
1874 ScDocShellRef xDocSh = loadDoc("shared-formula/3d-reference.", XLSX);
1876 CPPUNIT_ASSERT_MESSAGE("Failed to load file.", xDocSh.Is());
1877 ScDocument& rDoc = xDocSh->GetDocument();
1879 bool bRes = aTest.checkContent(rDoc);
1880 CPPUNIT_ASSERT_MESSAGE("Content check on the initial document failed.", bRes);
1882 rDoc.CalcAll(); // Recalculate to flush all cached results.
1883 bRes = aTest.checkContent(rDoc);
1884 CPPUNIT_ASSERT_MESSAGE("Content check on the initial recalculated document failed.", bRes);
1887 // Save and reload, and check the content again.
1888 ScDocShellRef xDocSh2 = saveAndReload(xDocSh, XLSX);
1889 xDocSh->DoClose();
1891 CPPUNIT_ASSERT_MESSAGE("Failed to load file.", xDocSh2.Is());
1892 ScDocument& rDoc = xDocSh2->GetDocument();
1893 rDoc.CalcAll(); // Recalculate to flush all cached results.
1895 bool bRes = aTest.checkContent(rDoc);
1896 CPPUNIT_ASSERT_MESSAGE("Content check on the reloaded document failed.", bRes);
1898 xDocSh2->DoClose();
1901 void ScExportTest::testSharedFormulaStringResultExportXLSX()
1903 struct
1905 bool checkContent( ScDocument& rDoc )
1908 // B2:B7 should show A,B,....,F.
1909 const char* expected[] = { "A", "B", "C", "D", "E", "F" };
1910 for (SCROW i = 0; i <= 5; ++i)
1912 ScAddress aPos(1,i+1,0);
1913 OUString aStr = rDoc.GetString(aPos);
1914 OUString aExpected = OUString::createFromAscii(expected[i]);
1915 if (aStr != aExpected)
1917 cerr << "Wrong value in B" << (i+2) << ": expected='" << aExpected << "', actual='" << aStr << "'" << endl;
1918 return false;
1924 // C2:C7 should show AA,BB,....,FF.
1925 const char* expected[] = { "AA", "BB", "CC", "DD", "EE", "FF" };
1926 for (SCROW i = 0; i <= 5; ++i)
1928 ScAddress aPos(2,i+1,0);
1929 OUString aStr = rDoc.GetString(aPos);
1930 OUString aExpected = OUString::createFromAscii(expected[i]);
1931 if (aStr != aExpected)
1933 cerr << "Wrong value in C" << (i+2) << ": expected='" << aExpected << "', actual='" << aStr << "'" << endl;
1934 return false;
1939 return true;
1942 } aTest;
1944 ScDocShellRef xDocSh = loadDoc("shared-formula/text-results.", XLSX);
1946 CPPUNIT_ASSERT_MESSAGE("Failed to load file.", xDocSh.Is());
1947 ScDocument& rDoc = xDocSh->GetDocument();
1949 // Check content without re-calculation, to test cached formula results.
1950 bool bRes = aTest.checkContent(rDoc);
1951 CPPUNIT_ASSERT_MESSAGE("Content check on the initial document failed.", bRes);
1953 // Now, re-calculate and check the results.
1954 rDoc.CalcAll();
1955 bRes = aTest.checkContent(rDoc);
1956 CPPUNIT_ASSERT_MESSAGE("Content check on the initial recalculated document failed.", bRes);
1958 // Reload and check again.
1959 ScDocShellRef xDocSh2 = saveAndReload(xDocSh, XLSX);
1960 xDocSh->DoClose();
1961 CPPUNIT_ASSERT_MESSAGE("Failed to re-load file.", xDocSh2.Is());
1962 ScDocument& rDoc = xDocSh2->GetDocument();
1964 bool bRes = aTest.checkContent(rDoc);
1965 CPPUNIT_ASSERT_MESSAGE("Content check on the reloaded document failed.", bRes);
1967 xDocSh2->DoClose();
1970 void ScExportTest::testFunctionsExcel2010( sal_uLong nFormatType )
1972 ScDocShellRef xShell = loadDoc("functions-excel-2010.", XLSX);
1973 CPPUNIT_ASSERT_MESSAGE("Failed to load the document.", xShell.Is());
1975 ScDocShellRef xDocSh = saveAndReload(xShell, nFormatType);
1976 ScDocument& rDoc = xDocSh->GetDocument();
1977 rDoc.CalcAll(); // perform hard re-calculation.
1979 testFunctionsExcel2010_Impl(rDoc);
1981 xDocSh->DoClose();
1984 void ScExportTest::testFunctionsExcel2010XLSX()
1986 testFunctionsExcel2010(XLSX);
1989 void ScExportTest::testFunctionsExcel2010XLS()
1991 testFunctionsExcel2010(XLS);
1994 void ScExportTest::testRelativePaths()
1996 ScDocShellRef xDocSh = loadDoc("fdo79305.", ODS);
1997 CPPUNIT_ASSERT(xDocSh.Is());
1999 xmlDocPtr pDoc = XPathHelper::parseExport(&(*xDocSh), m_xSFactory, "content.xml", ODS);
2000 CPPUNIT_ASSERT(pDoc);
2001 OUString aURL = getXPath(pDoc,
2002 "/office:document-content/office:body/office:spreadsheet/table:table/table:table-row[2]/table:table-cell[2]/text:p/text:a", "href");
2003 // make sure that the URL is relative
2004 CPPUNIT_ASSERT(aURL.startsWith(".."));
2007 namespace {
2009 void testSheetProtection_Impl(ScDocument& rDoc)
2011 CPPUNIT_ASSERT(rDoc.IsTabProtected(0));
2012 ScTableProtection* pTabProtection = rDoc.GetTabProtection(0);
2013 CPPUNIT_ASSERT(pTabProtection);
2014 CPPUNIT_ASSERT(pTabProtection->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS));
2015 CPPUNIT_ASSERT(!pTabProtection->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS));
2020 void ScExportTest::testSheetProtection()
2022 ScDocShellRef xDocSh = loadDoc("sheet-protection.", ODS);
2023 CPPUNIT_ASSERT(xDocSh.Is());
2026 ScDocument& rDoc = xDocSh->GetDocument();
2027 testSheetProtection_Impl(rDoc);
2030 ScDocShellRef xDocSh2 = saveAndReload(xDocSh, ODS);
2032 ScDocument& rDoc = xDocSh2->GetDocument();
2033 testSheetProtection_Impl(rDoc);
2036 xDocSh2->DoClose();
2039 void ScExportTest::testPivotTableXLSX()
2041 struct
2043 bool check( const ScDocument& rDoc )
2045 if (!rDoc.HasPivotTable())
2047 cerr << "The document should have pivot table." << endl;
2048 return false;
2051 const ScDPCollection* pDPs = rDoc.GetDPCollection();
2052 if (!pDPs)
2054 cerr << "Pivot table container should exist." << endl;
2055 return false;
2058 ScRange aSrcRange(0,0,0,9,2,0); // A1:J3 on Sheet1.
2059 const ScDPCache* pCache = pDPs->GetSheetCaches().getExistingCache(aSrcRange);
2060 if (!pCache)
2062 cerr << "The document should have a pivot cache for A1:J3 on Sheet1." << endl;
2063 return false;
2066 // Cache should have fields from F1 through F10.
2068 const char* pNames[] = {
2069 "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10"
2072 size_t nCount = pCache->GetFieldCount();
2073 if (nCount != SAL_N_ELEMENTS(pNames))
2075 cout << "Incorrect number of fields in pivot cache." << endl;
2076 return false;
2079 for (size_t i = 0; i < nCount; ++i)
2081 OUString aCacheName = pCache->GetDimensionName(i);
2082 if (aCacheName != OUString::createFromAscii(pNames[i]))
2084 cerr << "Field " << i << " has label '" << aCacheName << "' but expected '" << pNames[i] << "'" << endl;
2085 return false;
2089 const ScDPObject* pDPObj = rDoc.GetDPAtCursor(0,10,0); // A11
2090 if (!pDPObj)
2092 cerr << "A pivot table should exist over A11." << endl;
2093 return false;
2096 // Output range should be A8:D15.
2097 ScRange aOutRange = pDPObj->GetOutRange();
2098 if (ScRange(0,7,0,3,14,0) != aOutRange)
2100 cerr << "Incorrect output range." << endl;
2101 return false;
2104 // Row field - F1
2105 // Column field - F4
2106 // Page fields - F7 and F6
2107 // Data field - F10
2109 const ScDPSaveData* pSaveData = pDPObj->GetSaveData();
2110 if (!pSaveData)
2112 cerr << "Save data should exist in each pivot table object." << endl;
2113 return false;
2116 std::vector<const ScDPSaveDimension*> aDims;
2117 pSaveData->GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_ROW, aDims);
2118 if (aDims.size() != 1 || aDims[0]->GetName() != "F1")
2120 cerr << "Pivot table should have one row field labeld 'F1'" << endl;
2121 return false;
2124 pSaveData->GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_COLUMN, aDims);
2125 if (aDims.size() != 1 || aDims[0]->GetName() != "F4")
2127 cerr << "Pivot table should have one column field labeld 'F4'" << endl;
2128 return false;
2131 pSaveData->GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_PAGE, aDims);
2132 if (aDims.size() != 2 || aDims[0]->GetName() != "F7" || aDims[1]->GetName() != "F6")
2134 cerr << "Pivot table should have two page fields labeld 'F7' and 'F6' in this order." << endl;
2135 return false;
2138 pSaveData->GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_DATA, aDims);
2139 if (aDims.size() != 1 || aDims[0]->GetName() != "F10")
2141 cerr << "Pivot table should have one data field labeld 'F10'" << endl;
2142 return false;
2145 const ScDPSaveDimension* pDim = aDims[0];
2146 if (pDim->GetFunction() != sheet::GeneralFunction_SUM)
2148 cerr << "Data field should have SUM function." << endl;
2149 return false;
2152 return true;
2155 } aTest;
2157 ScDocShellRef xDocSh = loadDoc("pivot-table/many-fields-in-cache.", XLSX);
2158 CPPUNIT_ASSERT(xDocSh.Is());
2159 ScDocument* pDoc = &xDocSh->GetDocument();
2161 // Initial check.
2162 bool bCheck = aTest.check(*pDoc);
2163 CPPUNIT_ASSERT_MESSAGE("Initial check failed.", bCheck);
2165 ScDocShellRef xDocSh2 = saveAndReload(xDocSh, XLSX);
2166 xDocSh->DoClose();
2167 CPPUNIT_ASSERT(xDocSh2.Is());
2168 pDoc = &xDocSh2->GetDocument();
2170 // Reload check.
2171 bCheck = aTest.check(*pDoc);
2172 CPPUNIT_ASSERT_MESSAGE("Reload check failed.", bCheck);
2174 xDocSh2->DoClose();
2177 void ScExportTest::testPivotTableTwoDataFieldsXLSX()
2179 struct
2181 bool check( const ScDocument& rDoc )
2183 if (!rDoc.HasPivotTable())
2185 cerr << "The document should have pivot table." << endl;
2186 return false;
2189 const ScDPCollection* pDPs = rDoc.GetDPCollection();
2190 if (!pDPs)
2192 cerr << "Pivot table container should exist." << endl;
2193 return false;
2196 ScRange aSrcRange(1,1,1,2,8,1); // B2:C9 on the 2nd sheet.
2197 const ScDPCache* pCache = pDPs->GetSheetCaches().getExistingCache(aSrcRange);
2198 if (!pCache)
2200 cerr << "The document should have a pivot cache for B2:C9 on 'Src'." << endl;
2201 return false;
2204 const char* pNames[] = { "Name", "Value" };
2205 (void) pNames;
2207 size_t nCount = pCache->GetFieldCount();
2208 if (nCount != SAL_N_ELEMENTS(pNames))
2210 cout << "Incorrect number of fields in pivot cache." << endl;
2211 return false;
2214 const ScDPObject* pDPObj = rDoc.GetDPAtCursor(0,2,0); // A3
2215 if (!pDPObj)
2217 cerr << "A pivot table should exist over A3." << endl;
2218 return false;
2221 // Output range should be A3:C12.
2222 ScRange aOutRange = pDPObj->GetOutRange();
2223 if (ScRange(0,2,0,2,11,0) != aOutRange)
2225 cerr << "Incorrect output range." << endl;
2226 return false;
2229 const ScDPSaveData* pSaveData = pDPObj->GetSaveData();
2230 if (!pSaveData)
2232 cerr << "Save data should exist in each pivot table object." << endl;
2233 return false;
2236 std::vector<const ScDPSaveDimension*> aDims;
2237 pSaveData->GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_ROW, aDims);
2238 if (aDims.size() != 1 || aDims[0]->GetName() != "Name")
2240 cerr << "Pivot table should have one row field labeld 'Name'" << endl;
2241 return false;
2244 pSaveData->GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_DATA, aDims);
2245 if (aDims.size() != 2 ||
2246 ScDPUtil::getSourceDimensionName(aDims[0]->GetName()) != "Value" ||
2247 ScDPUtil::getSourceDimensionName(aDims[1]->GetName()) != "Value")
2249 cerr << "Pivot table should have two duplicated data fields both of which are named 'Value'." << endl;
2250 return false;
2253 if (aDims[0]->GetFunction() != sheet::GeneralFunction_SUM)
2255 cerr << "First data field should be SUM." << endl;
2256 return false;
2259 if (aDims[1]->GetFunction() != sheet::GeneralFunction_COUNT)
2261 cerr << "First data field should be COUNT." << endl;
2262 return false;
2265 pSaveData->GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_COLUMN, aDims);
2266 if (aDims.size() != 1 || !aDims[0]->IsDataLayout())
2268 cerr << "Pivot table should have one column field which is a data layout field." << endl;
2269 return false;
2272 return true;
2275 } aTest;
2277 ScDocShellRef xDocSh = loadDoc("pivot-table/two-data-fields.", XLSX);
2278 CPPUNIT_ASSERT(xDocSh.Is());
2279 ScDocument* pDoc = &xDocSh->GetDocument();
2281 // Initial check.
2282 bool bCheck = aTest.check(*pDoc);
2283 CPPUNIT_ASSERT_MESSAGE("Initial check failed.", bCheck);
2285 ScDocShellRef xDocSh2 = saveAndReload(xDocSh, XLSX);
2286 xDocSh->DoClose();
2287 CPPUNIT_ASSERT(xDocSh2.Is());
2288 pDoc = &xDocSh2->GetDocument();
2290 // Reload check.
2291 bCheck = aTest.check(*pDoc);
2292 CPPUNIT_ASSERT_MESSAGE("Reload check failed.", bCheck);
2294 xDocSh2->DoClose();
2297 void ScExportTest::testFunctionsExcel2010ODS()
2299 //testFunctionsExcel2010(ODS);
2302 void ScExportTest::testSwappedOutImageExport()
2304 const char* aFilterNames[] = {
2305 "calc8",
2306 "MS Excel 97",
2307 "Calc Office Open XML",
2308 "generic_HTML",
2311 // Set cache size to a very small value to make sure one of the images is swapped out
2312 std::shared_ptr< comphelper::ConfigurationChanges > xBatch(comphelper::ConfigurationChanges::create());
2313 officecfg::Office::Common::Cache::GraphicManager::TotalCacheSize::set(sal_Int32(1), xBatch);
2314 xBatch->commit();
2316 for( size_t nFilter = 0; nFilter < SAL_N_ELEMENTS(aFilterNames); ++nFilter )
2318 // Check whether the export code swaps in the image which was swapped out before.
2319 ScDocShellRef xDocSh = loadDoc("document_with_two_images.", ODS);
2321 const OString sFailedMessage = OString("Failed on filter: ") + aFilterNames[nFilter];
2322 CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xDocSh.Is());
2324 // Export the document and import again for a check
2325 ScDocShellRef xDocSh2 = saveAndReload(xDocSh, nFilter);
2326 xDocSh->DoClose();
2328 // Check whether graphic exported well after it was swapped out
2329 uno::Reference< frame::XModel > xModel = xDocSh2->GetModel();
2330 uno::Reference< sheet::XSpreadsheetDocument > xDoc(xModel, UNO_QUERY_THROW);
2331 uno::Reference< container::XIndexAccess > xIA(xDoc->getSheets(), UNO_QUERY_THROW);
2332 uno::Reference< drawing::XDrawPageSupplier > xDrawPageSupplier( xIA->getByIndex(0), UNO_QUERY_THROW);
2333 uno::Reference< container::XIndexAccess > xDraws(xDrawPageSupplier->getDrawPage(), UNO_QUERY_THROW);
2334 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(2), xDraws->getCount());
2336 uno::Reference<drawing::XShape> xImage(xDraws->getByIndex(0), uno::UNO_QUERY);
2337 uno::Reference< beans::XPropertySet > XPropSet( xImage, uno::UNO_QUERY_THROW );
2338 // Check URL
2340 OUString sURL;
2341 XPropSet->getPropertyValue("GraphicURL") >>= sURL;
2342 CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), sURL != "vnd.sun.star.GraphicObject:00000000000000000000000000000000");
2344 // Check size
2346 uno::Reference<graphic::XGraphic> xGraphic;
2347 XPropSet->getPropertyValue("Graphic") >>= xGraphic;
2348 uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
2349 CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xBitmap.is());
2350 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(610), xBitmap->getSize().Width );
2351 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(381), xBitmap->getSize().Height );
2353 // Second Image
2354 xImage.set(xDraws->getByIndex(1), uno::UNO_QUERY);
2355 XPropSet.set( xImage, uno::UNO_QUERY_THROW );
2356 // Check URL
2358 OUString sURL;
2359 XPropSet->getPropertyValue("GraphicURL") >>= sURL;
2360 CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), sURL != "vnd.sun.star.GraphicObject:00000000000000000000000000000000");
2362 // Check size
2364 uno::Reference<graphic::XGraphic> xGraphic;
2365 XPropSet->getPropertyValue("Graphic") >>= xGraphic;
2366 uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
2367 CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xBitmap.is());
2368 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(900), xBitmap->getSize().Width );
2369 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(600), xBitmap->getSize().Height );
2371 xDocSh2->DoClose();
2375 ScExportTest::ScExportTest()
2376 : ScBootstrapFixture("/sc/qa/unit/data")
2380 void ScExportTest::setUp()
2382 test::BootstrapFixture::setUp();
2384 // This is a bit of a fudge, we do this to ensure that ScGlobals::ensure,
2385 // which is a private symbol to us, gets called
2386 m_xCalcComponent =
2387 getMultiServiceFactory()->createInstance("com.sun.star.comp.Calc.SpreadsheetDocument");
2388 CPPUNIT_ASSERT_MESSAGE("no calc component!", m_xCalcComponent.is());
2391 void ScExportTest::tearDown()
2393 uno::Reference< lang::XComponent >( m_xCalcComponent, UNO_QUERY_THROW )->dispose();
2394 test::BootstrapFixture::tearDown();
2397 void ScExportTest::testSupBookVirtualPath()
2399 ScDocShellRef xShell = loadDoc("external-ref.", XLS);
2400 CPPUNIT_ASSERT(xShell.Is());
2402 ScDocShellRef xDocSh = saveAndReload(xShell, XLS);
2403 xShell->DoClose();
2404 CPPUNIT_ASSERT(xDocSh.Is());
2406 ScDocument& rDoc = xDocSh->GetDocument();
2408 if (!checkFormula(rDoc, ScAddress(0,0,0), "'file:///home/timar/Documents/external.xls'#$Sheet1.A1"))
2409 CPPUNIT_FAIL("Wrong SupBook VirtualPath URL");
2411 xDocSh->DoClose();
2414 void ScExportTest::testLinkedGraphicRT()
2416 // Problem was with linked images
2417 const char* aFilterNames[] = {
2418 "calc8",
2419 "MS Excel 97",
2420 "Calc Office Open XML",
2421 "generic_HTML",
2424 for( size_t nFilter = 0; nFilter < SAL_N_ELEMENTS(aFilterNames); ++nFilter )
2426 // Load the original file with one image
2427 ScDocShellRef xDocSh = loadDoc("document_with_linked_graphic.", ODS);
2428 const OString sFailedMessage = OString("Failed on filter: ") + aFilterNames[nFilter];
2430 // Export the document and import again for a check
2431 ScDocShellRef xDocSh2 = saveAndReload(xDocSh, nFilter);
2432 xDocSh->DoClose();
2434 // Check whether graphic imported well after export
2435 ScDocument& rDoc = xDocSh->GetDocument();
2436 ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
2437 CPPUNIT_ASSERT_MESSAGE( sFailedMessage.getStr(), pDrawLayer != NULL );
2438 const SdrPage *pPage = pDrawLayer->GetPage(0);
2439 CPPUNIT_ASSERT_MESSAGE( sFailedMessage.getStr(), pPage != NULL );
2440 SdrGrafObj* pObject = dynamic_cast<SdrGrafObj*>(pPage->GetObj(0));
2441 CPPUNIT_ASSERT_MESSAGE( sFailedMessage.getStr(), pObject != NULL );
2442 CPPUNIT_ASSERT_MESSAGE( sFailedMessage.getStr(), pObject->IsLinkedGraphic() );
2444 const GraphicObject& rGraphicObj = pObject->GetGraphicObject(true);
2445 CPPUNIT_ASSERT_MESSAGE( sFailedMessage.getStr(), !rGraphicObj.IsSwappedOut());
2446 CPPUNIT_ASSERT_EQUAL_MESSAGE( sFailedMessage.getStr(), GRAPHIC_BITMAP, rGraphicObj.GetGraphic().GetType());
2447 CPPUNIT_ASSERT_EQUAL_MESSAGE( sFailedMessage.getStr(), sal_uLong(864900), rGraphicObj.GetSizeBytes());
2449 xDocSh2->DoClose();
2453 void ScExportTest::testImageWithSpecialID()
2455 const char* aFilterNames[] = {
2456 "calc8",
2457 "MS Excel 97",
2458 "Calc Office Open XML",
2459 "generic_HTML",
2462 // Trigger swap out mechanism to test swapped state factor too.
2463 std::shared_ptr< comphelper::ConfigurationChanges > batch(comphelper::ConfigurationChanges::create());
2464 officecfg::Office::Common::Cache::GraphicManager::TotalCacheSize::set(sal_Int32(1), batch);
2465 batch->commit();
2467 for( size_t nFilter = 0; nFilter < SAL_N_ELEMENTS(aFilterNames); ++nFilter )
2469 ScDocShellRef xDocSh = loadDoc("images_with_special_IDs.", ODS);
2471 const OString sFailedMessage = OString("Failed on filter: ") + aFilterNames[nFilter];
2472 CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xDocSh.Is());
2474 // Export the document and import again for a check
2475 ScDocShellRef xDocSh2 = saveAndReload(xDocSh, nFilter);
2476 xDocSh->DoClose();
2478 // Check whether graphic was exported well
2479 uno::Reference< frame::XModel > xModel = xDocSh2->GetModel();
2480 uno::Reference< sheet::XSpreadsheetDocument > xDoc(xModel, UNO_QUERY_THROW);
2481 uno::Reference< container::XIndexAccess > xIA(xDoc->getSheets(), UNO_QUERY_THROW);
2482 uno::Reference< drawing::XDrawPageSupplier > xDrawPageSupplier( xIA->getByIndex(0), UNO_QUERY_THROW);
2483 uno::Reference< container::XIndexAccess > xDraws(xDrawPageSupplier->getDrawPage(), UNO_QUERY_THROW);
2484 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(2), xDraws->getCount());
2486 uno::Reference<drawing::XShape> xImage(xDraws->getByIndex(0), uno::UNO_QUERY);
2487 uno::Reference< beans::XPropertySet > XPropSet( xImage, uno::UNO_QUERY_THROW );
2488 // Check URL
2490 OUString sURL;
2491 XPropSet->getPropertyValue("GraphicURL") >>= sURL;
2492 CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), sURL != "vnd.sun.star.GraphicObject:00000000000000000000000000000000");
2494 // Check size
2496 uno::Reference<graphic::XGraphic> xGraphic;
2497 XPropSet->getPropertyValue("Graphic") >>= xGraphic;
2498 uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
2499 CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xBitmap.is());
2500 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(610), xBitmap->getSize().Width );
2501 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(381), xBitmap->getSize().Height );
2503 // Second Image
2504 xImage.set(xDraws->getByIndex(1), uno::UNO_QUERY);
2505 XPropSet.set( xImage, uno::UNO_QUERY_THROW );
2506 // Check URL
2508 OUString sURL;
2509 XPropSet->getPropertyValue("GraphicURL") >>= sURL;
2510 CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), sURL != "vnd.sun.star.GraphicObject:00000000000000000000000000000000");
2512 // Check size
2514 uno::Reference<graphic::XGraphic> xGraphic;
2515 XPropSet->getPropertyValue("Graphic") >>= xGraphic;
2516 uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
2517 CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xBitmap.is());
2518 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(900), xBitmap->getSize().Width );
2519 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(600), xBitmap->getSize().Height );
2521 xDocSh2->DoClose();
2525 void ScExportTest::testSheetLocalRangeNameXLS()
2527 ScDocShellRef xDocSh = loadDoc("named-ranges-local.", XLS);
2528 xDocSh->DoHardRecalc(true);
2529 ScDocShellRef xDocSh2 = saveAndReload(xDocSh, XLS);
2530 xDocSh->DoClose();
2531 xDocSh2->DoHardRecalc(true);
2533 ScDocument& rDoc = xDocSh2->GetDocument();
2534 ScRangeName* pRangeName = rDoc.GetRangeName(0);
2535 CPPUNIT_ASSERT(pRangeName);
2536 CPPUNIT_ASSERT_EQUAL(size_t(2), pRangeName->size());
2538 OUString aFormula;
2539 rDoc.GetFormula(3, 11, 0, aFormula);
2540 CPPUNIT_ASSERT_EQUAL(OUString("=SUM(local_name2)"), aFormula);
2541 ASSERT_DOUBLES_EQUAL(14.0, rDoc.GetValue(3, 11, 0));
2543 rDoc.GetFormula(6, 4, 0, aFormula);
2544 CPPUNIT_ASSERT_EQUAL(OUString("=local_name1"), aFormula);
2546 xDocSh2->DoClose();
2549 void ScExportTest::testSheetTextBoxHyperlink()
2551 ScDocShellRef xShell = loadDoc("textbox-hyperlink.", XLSX);
2552 CPPUNIT_ASSERT(xShell.Is());
2554 ScDocShellRef xDocSh = saveAndReload(&(*xShell), XLSX);
2555 CPPUNIT_ASSERT(xDocSh.Is());
2557 xmlDocPtr pDoc = XPathHelper::parseExport(&(*xDocSh), m_xSFactory, "xl/drawings/drawing1.xml", XLSX);
2558 CPPUNIT_ASSERT(pDoc);
2560 assertXPath(pDoc, "/xdr:wsDr[1]/xdr:twoCellAnchor[1]/xdr:sp[1]/xdr:nvSpPr[1]/xdr:cNvPr[1]/a:hlinkClick[1]", 1);
2562 xDocSh->DoClose();
2565 void ScExportTest::testFontSize()
2567 ScDocShellRef xDocSh = loadDoc("fontSize.", XLSX);
2568 CPPUNIT_ASSERT(xDocSh.Is());
2570 xmlDocPtr pDoc = XPathHelper::parseExport(&(*xDocSh), m_xSFactory, "xl/drawings/drawing1.xml", XLSX);
2571 CPPUNIT_ASSERT(pDoc);
2572 OUString fontSize = getXPath(pDoc,
2573 "/xdr:wsDr/xdr:twoCellAnchor/xdr:sp[1]/xdr:txBody/a:p[1]/a:r[1]/a:rPr", "sz");
2574 // make sure that the font size is 18
2575 CPPUNIT_ASSERT_EQUAL(OUString("1800"), fontSize);
2578 void ScExportTest::testSheetCharacterKerningSpace()
2580 ScDocShellRef xShell = loadDoc("textbox-CharKerningSpace.", XLSX);
2581 CPPUNIT_ASSERT(xShell.Is());
2583 ScDocShellRef xDocSh = saveAndReload(&(*xShell), XLSX);
2584 CPPUNIT_ASSERT(xDocSh.Is());
2586 xmlDocPtr pDoc = XPathHelper::parseExport(&(*xDocSh), m_xSFactory, "xl/drawings/drawing1.xml", XLSX);
2587 CPPUNIT_ASSERT(pDoc);
2589 OUString CharKerningSpace = getXPath(pDoc,
2590 "/xdr:wsDr[1]/xdr:twoCellAnchor[1]/xdr:sp[1]/xdr:txBody[1]/a:p[1]/a:r[1]/a:rPr[1]","spc");
2592 // make sure that the CharKerning is 1997.
2593 CPPUNIT_ASSERT_EQUAL(OUString("1997"), CharKerningSpace);
2595 xDocSh->DoClose();
2598 void ScExportTest::testSheetCondensedCharacterSpace()
2600 ScDocShellRef xShell = loadDoc("textbox-CondensedCharacterSpace.", XLSX);
2601 CPPUNIT_ASSERT(xShell.Is());
2603 ScDocShellRef xDocSh = saveAndReload(&(*xShell), XLSX);
2604 CPPUNIT_ASSERT(xDocSh.Is());
2606 xmlDocPtr pDoc = XPathHelper::parseExport(&(*xDocSh), m_xSFactory, "xl/drawings/drawing1.xml", XLSX);
2607 CPPUNIT_ASSERT(pDoc);
2609 OUString CondensedCharSpace = getXPath(pDoc,
2610 "/xdr:wsDr[1]/xdr:twoCellAnchor[1]/xdr:sp[1]/xdr:txBody[1]/a:p[1]/a:r[1]/a:rPr[1]","spc");
2612 // make sure that the CondensedCharSpace is -996.
2613 CPPUNIT_ASSERT_EQUAL(OUString("-996"), CondensedCharSpace);
2615 xDocSh->DoClose();
2618 void ScExportTest::testTextUnderlineColor()
2621 ScDocShellRef xDocSh = loadDoc("underlineColor.", XLSX);
2622 CPPUNIT_ASSERT(xDocSh.Is());
2624 xmlDocPtr pDoc = XPathHelper::parseExport(&(*xDocSh), m_xSFactory, "xl/drawings/drawing1.xml", XLSX);
2625 CPPUNIT_ASSERT(pDoc);
2626 OUString color = getXPath(pDoc,
2627 "/xdr:wsDr/xdr:twoCellAnchor/xdr:sp[1]/xdr:txBody/a:p[1]/a:r[1]/a:rPr/a:uFill/a:solidFill/a:srgbClr", "val");
2628 // make sure that the underline color is RED
2629 CPPUNIT_ASSERT_EQUAL(OUString("ff0000"), color);
2632 void ScExportTest::testSheetRunParagraphProperty()
2634 ScDocShellRef xShell = loadDoc("TextColor.", XLSX);
2635 CPPUNIT_ASSERT(xShell.Is());
2637 ScDocShellRef xDocSh = saveAndReload(&(*xShell), XLSX);
2638 CPPUNIT_ASSERT(xDocSh.Is());
2640 xmlDocPtr pDoc = XPathHelper::parseExport(&(*xDocSh), m_xSFactory, "xl/sharedStrings.xml", XLSX);
2641 CPPUNIT_ASSERT(pDoc);
2643 assertXPath(pDoc, "/x:sst/x:si/x:r[1]/x:rPr[1]", 1);
2645 xDocSh->DoClose();
2648 void ScExportTest::testHiddenShape()
2650 ScDocShellRef xDocSh = loadDoc("hiddenShape.", XLSX);
2651 CPPUNIT_ASSERT(xDocSh.Is());
2653 xmlDocPtr pDoc = XPathHelper::parseExport(&(*xDocSh), m_xSFactory, "xl/drawings/drawing1.xml", XLSX);
2654 CPPUNIT_ASSERT(pDoc);
2655 assertXPath(pDoc, "/xdr:wsDr/xdr:twoCellAnchor/xdr:sp[1]/xdr:nvSpPr/xdr:cNvPr", "hidden", "1");
2658 void ScExportTest::testMoveCellAnchoredShapes()
2660 ScDocShellRef xDocSh = loadDoc("move-cell-anchored-shapes.", ODS);
2661 CPPUNIT_ASSERT_MESSAGE("Failed to load move-cell-anchored-shapes.ods", xDocSh.Is());
2663 // There are two cell-anchored objects on the first sheet.
2664 ScDocument& rDoc = xDocSh->GetDocument();
2666 CPPUNIT_ASSERT_MESSAGE("There should be at least one sheet.", rDoc.GetTableCount() > 0);
2668 ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
2669 SdrPage* pPage = pDrawLayer->GetPage(0);
2670 CPPUNIT_ASSERT_MESSAGE("draw page for sheet 1 should exist.", pPage);
2671 SdrObject* pObj = pPage->GetObj(0);
2672 CPPUNIT_ASSERT_MESSAGE("Failed to get drawing object.", pObj);
2674 // Check cell anchor state
2675 ScAnchorType oldType = ScDrawLayer::GetAnchorType(*pObj);
2676 CPPUNIT_ASSERT_MESSAGE( "Failed to get anchor type", oldType == SCA_CELL );
2678 // Get anchor data
2679 ScDrawObjData* pData = ScDrawLayer::GetObjData(pObj, false);
2680 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData);
2681 CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData->maLastRect.IsEmpty());
2683 ScAddress aDataStart = pData->maStart;
2684 ScAddress aDataEnd = pData->maEnd;
2686 // Get non rotated anchor data
2687 ScDrawObjData* pNData = ScDrawLayer::GetNonRotatedObjData( pObj );
2688 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData);
2689 CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData->maLastRect.IsEmpty());
2691 ScAddress aNDataStart = pNData->maStart;
2692 ScAddress aNDataEnd = pNData->maEnd;
2693 CPPUNIT_ASSERT_EQUAL(aDataStart, aNDataStart);
2694 CPPUNIT_ASSERT_EQUAL(aDataEnd , aNDataEnd);
2696 // Insert 2 rows.
2697 rDoc.InsertRow(ScRange( 0, aDataStart.Row() - 1, 0, MAXCOL, aDataStart.Row(), 0));
2699 // Get anchor data
2700 pData = ScDrawLayer::GetObjData(pObj, false);
2701 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData);
2702 CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData->maLastRect.IsEmpty());
2704 // Get non rotated anchor data
2705 pNData = ScDrawLayer::GetNonRotatedObjData( pObj );
2706 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData);
2707 CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData->maLastRect.IsEmpty());
2709 // Check if data has moved to new rows
2710 CPPUNIT_ASSERT_EQUAL( pData->maStart.Row(), aDataStart.Row() + 2 );
2711 CPPUNIT_ASSERT_EQUAL( pData->maEnd.Row(), aDataEnd.Row() + 2 );
2713 CPPUNIT_ASSERT_EQUAL( pNData->maStart.Row(), aNDataStart.Row() + 2 );
2714 CPPUNIT_ASSERT_EQUAL( pNData->maEnd.Row(), aNDataEnd.Row() + 2 );
2716 // Save the anchor data
2717 aDataStart = pData->maStart;
2718 aDataEnd = pData->maEnd;
2719 aNDataStart = pNData->maStart;
2720 aNDataEnd = pNData->maEnd;
2722 // Save the document and load again to check anchor persist
2723 ScDocShellRef xDocSh1 = saveAndReload(&(*xDocSh), ODS);
2725 // There are two cell-anchored objects on the first sheet.
2726 ScDocument& rDoc1 = xDocSh1->GetDocument();
2728 CPPUNIT_ASSERT_MESSAGE("There should be at least one sheet.", rDoc1.GetTableCount() > 0);
2730 pDrawLayer = rDoc1.GetDrawLayer();
2731 pPage = pDrawLayer->GetPage(0);
2732 CPPUNIT_ASSERT_MESSAGE("draw page for sheet 1 should exist.", pPage);
2733 pObj = pPage->GetObj(0);
2734 CPPUNIT_ASSERT_MESSAGE("Failed to get drawing object.", pObj);
2736 // Check cell anchor state
2737 oldType = ScDrawLayer::GetAnchorType(*pObj);
2738 CPPUNIT_ASSERT_MESSAGE( "Failed to get anchor type", oldType == SCA_CELL );
2740 // Get anchor data
2741 pData = ScDrawLayer::GetObjData(pObj, false);
2742 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData);
2743 CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData->maLastRect.IsEmpty());
2745 // Get non rotated anchor data
2746 pNData = ScDrawLayer::GetNonRotatedObjData( pObj );
2747 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData);
2748 CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData->maLastRect.IsEmpty());
2750 // Check if data after save it
2751 CPPUNIT_ASSERT_EQUAL(pData->maStart, aDataStart);
2752 CPPUNIT_ASSERT_EQUAL(pData->maEnd , aDataEnd);
2754 CPPUNIT_ASSERT_EQUAL(pNData->maStart, aNDataStart);
2755 CPPUNIT_ASSERT_EQUAL(pNData->maEnd , aNDataEnd);
2757 // Insert a column.
2758 rDoc1.InsertCol(ScRange( aDataStart.Col(), 0 , 0 , aDataStart.Col(), MAXROW, 0 ));
2760 // Get anchor data
2761 pData = ScDrawLayer::GetObjData(pObj, false);
2762 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData);
2763 CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData->maLastRect.IsEmpty());
2765 // Get non rotated anchor data
2766 pNData = ScDrawLayer::GetNonRotatedObjData( pObj );
2767 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData);
2768 CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData->maLastRect.IsEmpty());
2770 // Check if data has moved to new rows
2771 CPPUNIT_ASSERT_EQUAL(pData->maStart.Col(), SCCOL(aDataStart.Col() + 1));
2772 CPPUNIT_ASSERT_EQUAL(pData->maEnd.Col() , SCCOL(aDataEnd.Col() + 1));
2774 CPPUNIT_ASSERT_EQUAL(pNData->maStart.Col(), SCCOL(aNDataStart.Col() + 1));
2775 CPPUNIT_ASSERT_EQUAL(pNData->maEnd.Col() , SCCOL(aNDataEnd.Col() + 1));
2777 // Save the anchor data
2778 aDataStart = pData->maStart;
2779 aDataEnd = pData->maEnd;
2780 aNDataStart = pNData->maStart;
2781 aNDataEnd = pNData->maEnd;
2783 // Save the document and load again to check anchor persist
2784 ScDocShellRef xDocSh2 = saveAndReload(&(*xDocSh1), ODS);
2786 // There are two cell-anchored objects on the first sheet.
2787 ScDocument& rDoc2 = xDocSh2->GetDocument();
2789 CPPUNIT_ASSERT_MESSAGE("There should be at least one sheet.", rDoc2.GetTableCount() > 0);
2791 pDrawLayer = rDoc2.GetDrawLayer();
2792 pPage = pDrawLayer->GetPage(0);
2793 CPPUNIT_ASSERT_MESSAGE("draw page for sheet 1 should exist.", pPage);
2794 pObj = pPage->GetObj(0);
2795 CPPUNIT_ASSERT_MESSAGE("Failed to get drawing object.", pObj);
2797 // Check cell anchor state
2798 oldType = ScDrawLayer::GetAnchorType(*pObj);
2799 CPPUNIT_ASSERT_MESSAGE( "Failed to get anchor type", oldType == SCA_CELL );
2801 // Get anchor data
2802 pData = ScDrawLayer::GetObjData(pObj, false);
2803 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData);
2804 CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData->maLastRect.IsEmpty());
2806 // Get non rotated anchor data
2807 pNData = ScDrawLayer::GetNonRotatedObjData( pObj );
2808 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData);
2809 CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData->maLastRect.IsEmpty());
2811 // Check if data after save it
2812 CPPUNIT_ASSERT_EQUAL(pData->maStart, aDataStart);
2813 CPPUNIT_ASSERT_EQUAL(pData->maEnd , aDataEnd);
2815 CPPUNIT_ASSERT_EQUAL(pNData->maStart, aNDataStart);
2816 CPPUNIT_ASSERT_EQUAL(pNData->maEnd , aNDataEnd);
2818 xDocSh2->DoClose();
2821 void ScExportTest::testHeaderImage()
2823 // Graphic as header background was lost on export.
2824 ScDocShellRef xShell = loadDoc("header-image.", ODS);
2825 ScDocShellRef xDocSh = saveAndReload(&(*xShell), ODS);
2826 uno::Reference<style::XStyleFamiliesSupplier> xStyleFamiliesSupplier(xDocSh->GetModel(), uno::UNO_QUERY);
2827 uno::Reference<container::XNameAccess> xStyleFamilies = xStyleFamiliesSupplier->getStyleFamilies();
2828 uno::Reference<container::XNameAccess> xPageStyles(xStyleFamilies->getByName("PageStyles"), uno::UNO_QUERY);
2829 uno::Reference<beans::XPropertySet> xStyle(xPageStyles->getByName("Default"), uno::UNO_QUERY);
2830 OUString aURL;
2831 xStyle->getPropertyValue("HeaderBackGraphicURL") >>= aURL;
2832 CPPUNIT_ASSERT(aURL.startsWith("vnd.sun.star.GraphicObject:"));
2835 void ScExportTest::testMatrixMultiplication()
2837 ScDocShellRef xShell = loadDoc("matrix-multiplication.", XLSX);
2838 CPPUNIT_ASSERT(xShell.Is());
2840 ScDocShellRef xDocSh = saveAndReload(&(*xShell), XLSX);
2841 CPPUNIT_ASSERT(xDocSh.Is());
2843 xmlDocPtr pDoc = XPathHelper::parseExport(&(*xDocSh), m_xSFactory, "xl/worksheets/sheet1.xml", XLSX);
2844 CPPUNIT_ASSERT(pDoc);
2846 OUString CellFormulaRange = getXPath(pDoc,
2847 "/x:worksheet/x:sheetData/x:row[4]/x:c/x:f","ref");
2849 // make sure that the CellFormulaRange is G5:G6.
2850 CPPUNIT_ASSERT_EQUAL(OUString("G5:G6"), CellFormulaRange);
2852 OUString CellFormulaType = getXPath(pDoc,
2853 "/x:worksheet/x:sheetData/x:row[4]/x:c/x:f","t");
2855 // make sure that the CellFormulaType is array.
2856 CPPUNIT_ASSERT_EQUAL(OUString("array"), CellFormulaType);
2858 xDocSh->DoClose();
2861 void ScExportTest::testRefStringXLSX()
2863 ScDocShellRef xDocSh = loadDoc("ref_string.", XLSX);
2864 CPPUNIT_ASSERT_MESSAGE("Failed to open doc", xDocSh.Is());
2866 //make sure ref syntax gets saved for MSO-produced docs
2867 xDocSh = saveAndReload( &(*xDocSh), XLSX);
2868 CPPUNIT_ASSERT_MESSAGE("Failed to reload doc", xDocSh.Is());
2870 ScDocument& rDoc = xDocSh->GetDocument();
2871 ScCalcConfig aCalcConfig = rDoc.GetCalcConfig();
2872 CPPUNIT_ASSERT_EQUAL(formula::FormulaGrammar::CONV_XL_A1, aCalcConfig.meStringRefAddressSyntax);
2874 xDocSh->DoClose();
2877 void ScExportTest::testRefStringConfigXLSX()
2879 // this doc is configured with CalcA1 ref syntax
2880 ScDocShellRef xDocSh = loadDoc("empty.", XLSX);
2881 CPPUNIT_ASSERT_MESSAGE("Failed to open doc", xDocSh.Is());
2883 xDocSh = saveAndReload( &(*xDocSh), XLSX);
2884 CPPUNIT_ASSERT_MESSAGE("Failed to reload doc", xDocSh.Is());
2886 ScDocument& rDoc = xDocSh->GetDocument();
2887 ScCalcConfig aConfig = rDoc.GetCalcConfig();
2888 CPPUNIT_ASSERT_EQUAL_MESSAGE("String ref syntax doesn't match", formula::FormulaGrammar::CONV_OOO,
2889 aConfig.meStringRefAddressSyntax);
2891 // this doc has no entry for ref syntax
2892 xDocSh = loadDoc("empty-noconf.", XLSX);
2893 CPPUNIT_ASSERT_MESSAGE("Failed to open 2nd doc", xDocSh.Is());
2895 ScDocument& rDoc2 = xDocSh->GetDocument();
2896 aConfig = rDoc2.GetCalcConfig();
2897 // therefore after import, ref syntax should be set to CalcA1 | ExcelA1
2898 CPPUNIT_ASSERT_EQUAL_MESSAGE("String ref syntax doesn't match", formula::FormulaGrammar::CONV_A1_XL_A1,
2899 aConfig.meStringRefAddressSyntax);
2901 //set ref syntax to something else than ExcelA1 (native to xlsx format) ...
2902 aConfig.meStringRefAddressSyntax = formula::FormulaGrammar::CONV_XL_R1C1;
2903 rDoc2.SetCalcConfig( aConfig );
2905 ScDocShellRef xNewDocSh = saveAndReload( &(*xDocSh), XLSX);
2906 CPPUNIT_ASSERT_MESSAGE("Failed to reload 2nd doc", xNewDocSh.Is());
2908 // ... and make sure it got saved
2909 ScDocument& rDoc3 = xNewDocSh->GetDocument();
2910 aConfig = rDoc3.GetCalcConfig();
2911 CPPUNIT_ASSERT_EQUAL_MESSAGE("String ref syntax doesn't match", formula::FormulaGrammar::CONV_XL_R1C1,
2912 aConfig.meStringRefAddressSyntax);
2914 xDocSh->DoClose();
2915 xNewDocSh->DoClose();
2918 void ScExportTest::testRefStringUnspecified()
2920 ScDocShell* pShell = new ScDocShell(
2921 SfxModelFlags::EMBEDDED_OBJECT |
2922 SfxModelFlags::DISABLE_EMBEDDED_SCRIPTS |
2923 SfxModelFlags::DISABLE_DOCUMENT_RECOVERY);
2924 pShell->DoInitNew();
2926 ScDocument& rDoc = pShell->GetDocument();
2927 ScCalcConfig aConfig = rDoc.GetCalcConfig();
2928 CPPUNIT_ASSERT_EQUAL_MESSAGE("Default string ref syntax value doesn't match", formula::FormulaGrammar::CONV_UNSPECIFIED,
2929 aConfig.meStringRefAddressSyntax);
2931 // change formula syntax (i.e. not string ref syntax) to ExcelA1
2932 rDoc.SetGrammar( formula::FormulaGrammar::GRAM_NATIVE_XL_A1 );
2934 ScDocShellRef xDocSh = saveAndReload( pShell, ODS );
2935 CPPUNIT_ASSERT_MESSAGE("Failed to reload doc", xDocSh.Is());
2937 // with string ref syntax at its default value, we should've saved ExcelA1
2938 ScDocument& rDoc2 = xDocSh->GetDocument();
2939 aConfig = rDoc2.GetCalcConfig();
2940 CPPUNIT_ASSERT_EQUAL_MESSAGE("String ref syntax doesn't match", formula::FormulaGrammar::CONV_XL_A1,
2941 aConfig.meStringRefAddressSyntax);
2943 xDocSh->DoClose();
2946 CPPUNIT_TEST_SUITE_REGISTRATION(ScExportTest);
2948 CPPUNIT_PLUGIN_IMPLEMENT();
2950 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */