Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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 : */
9 :
10 : #include <officecfg/Office/Common.hxx>
11 : #include <sal/config.h>
12 : #include <rtl/strbuf.hxx>
13 : #include <osl/file.hxx>
14 :
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>
20 :
21 : #include "helper/qahelper.hxx"
22 : #include "helper/xpath.hxx"
23 : #include "helper/shared_test_impl.hxx"
24 :
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>
44 :
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>
62 :
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>
72 :
73 : using namespace ::com::sun::star;
74 : using namespace ::com::sun::star::uno;
75 :
76 96 : class ScExportTest : public ScBootstrapFixture, XmlTestTools
77 : {
78 : protected:
79 : virtual void registerNamespaces(xmlXPathContextPtr& pXmlXPathCtx) SAL_OVERRIDE;
80 : public:
81 : ScExportTest();
82 :
83 : virtual void setUp() SAL_OVERRIDE;
84 : virtual void tearDown() SAL_OVERRIDE;
85 :
86 : #if !defined MACOSX && !defined DRAGONFLY
87 : ScDocShellRef saveAndReloadPassword( ScDocShell*, const OUString&, const OUString&, const OUString&, SfxFilterFlags );
88 : #endif
89 :
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();
104 :
105 : void testCellValuesExportODS();
106 : void testCellNoteExportODS();
107 : void testCellNoteExportXLS();
108 : void testFormatExportODS();
109 :
110 : void testInlineArrayXLS();
111 : void testEmbeddedChartXLS();
112 : void testFormulaReferenceXLS();
113 : void testSheetProtectionXLSX();
114 :
115 : void testCellBordersXLS();
116 : void testCellBordersXLSX();
117 : void testTrackChangesSimpleXLSX();
118 : void testSheetTabColorsXLSX();
119 :
120 : void testSharedFormulaExportXLS();
121 : void testSharedFormulaExportXLSX();
122 : void testSharedFormulaStringResultExportXLSX();
123 :
124 : void testFunctionsExcel2010( sal_uLong nFormatType );
125 : void testFunctionsExcel2010XLSX();
126 : void testFunctionsExcel2010XLS();
127 : void testFunctionsExcel2010ODS();
128 :
129 : void testRelativePaths();
130 : void testSheetProtection();
131 :
132 : void testPivotTableXLSX();
133 : void testPivotTableTwoDataFieldsXLSX();
134 :
135 : void testSwappedOutImageExport();
136 : void testLinkedGraphicRT();
137 : void testImageWithSpecialID();
138 :
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 testHyperlinkXLSX();
149 : void testMoveCellAnchoredShapes();
150 :
151 2 : CPPUNIT_TEST_SUITE(ScExportTest);
152 1 : CPPUNIT_TEST(test);
153 : #if !defined(MACOSX) && !defined(DRAGONFLY)
154 1 : CPPUNIT_TEST(testPasswordExport);
155 : #endif
156 1 : CPPUNIT_TEST(testConditionalFormatExportODS);
157 1 : CPPUNIT_TEST(testConditionalFormatExportXLSX);
158 1 : CPPUNIT_TEST(testColorScaleExportODS);
159 1 : CPPUNIT_TEST(testColorScaleExportXLSX);
160 1 : CPPUNIT_TEST(testDataBarExportODS);
161 1 : CPPUNIT_TEST(testDataBarExportXLSX);
162 1 : CPPUNIT_TEST(testMiscRowHeightExport);
163 1 : CPPUNIT_TEST(testNamedRangeBugfdo62729);
164 1 : CPPUNIT_TEST(testRichTextExportODS);
165 1 : CPPUNIT_TEST(testFormulaRefSheetNameODS);
166 1 : CPPUNIT_TEST(testCellValuesExportODS);
167 1 : CPPUNIT_TEST(testCellNoteExportODS);
168 1 : CPPUNIT_TEST(testCellNoteExportXLS);
169 1 : CPPUNIT_TEST(testFormatExportODS);
170 1 : CPPUNIT_TEST(testInlineArrayXLS);
171 1 : CPPUNIT_TEST(testEmbeddedChartXLS);
172 1 : CPPUNIT_TEST(testFormulaReferenceXLS);
173 1 : CPPUNIT_TEST(testSheetProtectionXLSX);
174 1 : CPPUNIT_TEST(testCellBordersXLS);
175 1 : CPPUNIT_TEST(testCellBordersXLSX);
176 1 : CPPUNIT_TEST(testTrackChangesSimpleXLSX);
177 1 : CPPUNIT_TEST(testSheetTabColorsXLSX);
178 1 : CPPUNIT_TEST(testSharedFormulaExportXLS);
179 1 : CPPUNIT_TEST(testSharedFormulaExportXLSX);
180 1 : CPPUNIT_TEST(testSharedFormulaStringResultExportXLSX);
181 1 : CPPUNIT_TEST(testFunctionsExcel2010XLSX);
182 1 : CPPUNIT_TEST(testFunctionsExcel2010XLS);
183 : #if !defined(WNT)
184 1 : CPPUNIT_TEST(testRelativePaths);
185 : #endif
186 1 : CPPUNIT_TEST(testSheetProtection);
187 1 : CPPUNIT_TEST(testPivotTableXLSX);
188 1 : CPPUNIT_TEST(testPivotTableTwoDataFieldsXLSX);
189 1 : CPPUNIT_TEST(testFunctionsExcel2010ODS);
190 : #if !defined(WNT)
191 1 : CPPUNIT_TEST(testSupBookVirtualPath);
192 : #endif
193 1 : CPPUNIT_TEST(testSwappedOutImageExport);
194 1 : CPPUNIT_TEST(testLinkedGraphicRT);
195 1 : CPPUNIT_TEST(testImageWithSpecialID);
196 1 : CPPUNIT_TEST(testSheetLocalRangeNameXLS);
197 1 : CPPUNIT_TEST(testSheetTextBoxHyperlink);
198 1 : CPPUNIT_TEST(testFontSize);
199 1 : CPPUNIT_TEST(testSheetCharacterKerningSpace);
200 1 : CPPUNIT_TEST(testSheetCondensedCharacterSpace);
201 1 : CPPUNIT_TEST(testTextUnderlineColor);
202 1 : CPPUNIT_TEST(testSheetRunParagraphProperty);
203 1 : CPPUNIT_TEST(testHiddenShape);
204 1 : CPPUNIT_TEST(testHyperlinkXLSX);
205 1 : CPPUNIT_TEST(testMoveCellAnchoredShapes);
206 :
207 5 : CPPUNIT_TEST_SUITE_END();
208 :
209 : private:
210 : void testExcelCellBorders( sal_uLong nFormatType );
211 :
212 : uno::Reference<uno::XInterface> m_xCalcComponent;
213 :
214 : };
215 :
216 9 : void ScExportTest::registerNamespaces(xmlXPathContextPtr& pXmlXPathCtx)
217 : {
218 : struct { xmlChar* pPrefix; xmlChar* pURI; } aNamespaces[] =
219 : {
220 : { BAD_CAST("w"), BAD_CAST("http://schemas.openxmlformats.org/wordprocessingml/2006/main") },
221 : { BAD_CAST("v"), BAD_CAST("urn:schemas-microsoft-com:vml") },
222 : { BAD_CAST("c"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/chart") },
223 : { BAD_CAST("a"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/main") },
224 : { BAD_CAST("mc"), BAD_CAST("http://schemas.openxmlformats.org/markup-compatibility/2006") },
225 : { BAD_CAST("wps"), BAD_CAST("http://schemas.microsoft.com/office/word/2010/wordprocessingShape") },
226 : { BAD_CAST("wpg"), BAD_CAST("http://schemas.microsoft.com/office/word/2010/wordprocessingGroup") },
227 : { BAD_CAST("wp"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing") },
228 : { BAD_CAST("office"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:office:1.0") },
229 : { BAD_CAST("table"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:table:1.0") },
230 : { BAD_CAST("text"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:text:1.0") },
231 : { BAD_CAST("xlink"), BAD_CAST("http://www.w3c.org/1999/xlink") },
232 : { BAD_CAST("xdr"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing") },
233 : { BAD_CAST("x"), BAD_CAST("http://schemas.openxmlformats.org/spreadsheetml/2006/main") },
234 : { BAD_CAST("r"), BAD_CAST("http://schemas.openxmlformats.org/package/2006/relationships") }
235 9 : };
236 144 : for(size_t i = 0; i < SAL_N_ELEMENTS(aNamespaces); ++i)
237 : {
238 135 : xmlXPathRegisterNs(pXmlXPathCtx, aNamespaces[i].pPrefix, aNamespaces[i].pURI );
239 : }
240 9 : }
241 :
242 : #if !defined MACOSX && !defined DRAGONFLY
243 1 : ScDocShellRef ScExportTest::saveAndReloadPassword(ScDocShell* pShell, const OUString &rFilter,
244 : const OUString &rUserData, const OUString& rTypeName, SfxFilterFlags nFormatType)
245 : {
246 1 : utl::TempFile aTempFile;
247 1 : aTempFile.EnableKillingFile();
248 2 : SfxMedium aStoreMedium( aTempFile.GetURL(), STREAM_STD_WRITE );
249 1 : SotClipboardFormatId nExportFormat = SotClipboardFormatId::NONE;
250 1 : if (nFormatType == ODS_FORMAT_TYPE)
251 1 : nExportFormat = SotClipboardFormatId::STARCHART_8;
252 : SfxFilter* pExportFilter = new SfxFilter(
253 : rFilter,
254 : OUString(), nFormatType, nExportFormat, rTypeName, 0, OUString(),
255 1 : rUserData, OUString("private:factory/scalc*") );
256 1 : pExportFilter->SetVersion(SOFFICE_FILEFORMAT_CURRENT);
257 1 : aStoreMedium.SetFilter(pExportFilter);
258 1 : SfxItemSet* pExportSet = aStoreMedium.GetItemSet();
259 2 : uno::Sequence< beans::NamedValue > aEncryptionData = comphelper::OStorageHelper::CreatePackageEncryptionData( OUString("test") );
260 2 : uno::Any xEncryptionData;
261 1 : xEncryptionData <<= aEncryptionData;
262 1 : pExportSet->Put(SfxUnoAnyItem(SID_ENCRYPTIONDATA, xEncryptionData));
263 :
264 2 : uno::Reference< embed::XStorage > xMedStorage = aStoreMedium.GetStorage();
265 1 : ::comphelper::OStorageHelper::SetCommonStorageEncryptionData( xMedStorage, aEncryptionData );
266 :
267 1 : pShell->DoSaveAs( aStoreMedium );
268 1 : pShell->DoClose();
269 :
270 : //std::cout << "File: " << aTempFile.GetURL() << std::endl;
271 :
272 1 : SotClipboardFormatId nFormat = SotClipboardFormatId::NONE;
273 1 : if (nFormatType == ODS_FORMAT_TYPE)
274 1 : nFormat = SotClipboardFormatId::STARCALC_8;
275 :
276 2 : OUString aPass("test");
277 2 : return load(aTempFile.GetURL(), rFilter, rUserData, rTypeName, nFormatType, nFormat, SOFFICE_FILEFORMAT_CURRENT, &aPass);
278 : }
279 : #endif
280 :
281 1 : void ScExportTest::test()
282 : {
283 : ScDocShell* pShell = new ScDocShell(
284 : SfxModelFlags::EMBEDDED_OBJECT |
285 2 : SfxModelFlags::DISABLE_EMBEDDED_SCRIPTS |
286 2 : SfxModelFlags::DISABLE_DOCUMENT_RECOVERY);
287 1 : pShell->DoInitNew();
288 :
289 1 : ScDocument& rDoc = pShell->GetDocument();
290 :
291 1 : rDoc.SetValue(0,0,0, 1.0);
292 :
293 1 : ScDocShellRef xDocSh = saveAndReload( pShell, ODS );
294 :
295 1 : CPPUNIT_ASSERT(xDocSh.Is());
296 1 : ScDocument& rLoadedDoc = xDocSh->GetDocument();
297 1 : double aVal = rLoadedDoc.GetValue(0,0,0);
298 1 : ASSERT_DOUBLES_EQUAL(aVal, 1.0);
299 1 : xDocSh->DoClose();
300 1 : }
301 :
302 : #if !defined MACOSX && !defined DRAGONFLY
303 1 : void ScExportTest::testPasswordExport()
304 : {
305 : ScDocShell* pShell = new ScDocShell(
306 : SfxModelFlags::EMBEDDED_OBJECT |
307 2 : SfxModelFlags::DISABLE_EMBEDDED_SCRIPTS |
308 2 : SfxModelFlags::DISABLE_DOCUMENT_RECOVERY);
309 1 : pShell->DoInitNew();
310 :
311 1 : ScDocument& rDoc = pShell->GetDocument();
312 :
313 1 : rDoc.SetValue(0,0,0, 1.0);
314 :
315 1 : sal_Int32 nFormat = ODS;
316 1 : OUString aFilterName(getFileFormats()[nFormat].pFilterName, strlen(getFileFormats()[nFormat].pFilterName), RTL_TEXTENCODING_UTF8) ;
317 2 : OUString aFilterType(getFileFormats()[nFormat].pTypeName, strlen(getFileFormats()[nFormat].pTypeName), RTL_TEXTENCODING_UTF8);
318 2 : ScDocShellRef xDocSh = saveAndReloadPassword(pShell, aFilterName, OUString(), aFilterType, getFileFormats()[nFormat].nFormatType);
319 :
320 1 : CPPUNIT_ASSERT(xDocSh.Is());
321 1 : ScDocument& rLoadedDoc = xDocSh->GetDocument();
322 1 : double aVal = rLoadedDoc.GetValue(0,0,0);
323 1 : ASSERT_DOUBLES_EQUAL(aVal, 1.0);
324 :
325 2 : xDocSh->DoClose();
326 1 : }
327 : #endif
328 :
329 1 : void ScExportTest::testConditionalFormatExportODS()
330 : {
331 1 : ScDocShellRef xShell = loadDoc("new_cond_format_test.", ODS);
332 1 : CPPUNIT_ASSERT(xShell.Is());
333 :
334 2 : ScDocShellRef xDocSh = saveAndReload(&(*xShell), ODS);
335 1 : CPPUNIT_ASSERT(xDocSh.Is());
336 1 : ScDocument& rDoc = xDocSh->GetDocument();
337 2 : OUString aCSVFile("new_cond_format_test.");
338 2 : OUString aCSVPath;
339 1 : createCSVPath( aCSVFile, aCSVPath );
340 1 : testCondFile(aCSVPath, &rDoc, 0);
341 :
342 2 : xDocSh->DoClose();
343 1 : }
344 :
345 1 : void ScExportTest::testConditionalFormatExportXLSX()
346 : {
347 1 : ScDocShellRef xShell = loadDoc("new_cond_format_test.", XLSX);
348 1 : CPPUNIT_ASSERT(xShell.Is());
349 :
350 2 : ScDocShellRef xDocSh = saveAndReload(&(*xShell), XLSX);
351 1 : CPPUNIT_ASSERT(xDocSh.Is());
352 1 : ScDocument& rDoc = xDocSh->GetDocument();
353 : {
354 1 : OUString aCSVFile("new_cond_format_test.");
355 2 : OUString aCSVPath;
356 1 : createCSVPath( aCSVFile, aCSVPath );
357 2 : testCondFile(aCSVPath, &rDoc, 0);
358 : }
359 : {
360 1 : OUString aCSVFile("new_cond_format_test_sheet2.");
361 2 : OUString aCSVPath;
362 1 : createCSVPath( aCSVFile, aCSVPath );
363 2 : testCondFile(aCSVPath, &rDoc, 1);
364 : }
365 :
366 2 : xDocSh->DoClose();
367 1 : }
368 :
369 1 : void ScExportTest::testColorScaleExportODS()
370 : {
371 1 : ScDocShellRef xShell = loadDoc("colorscale.", ODS);
372 1 : CPPUNIT_ASSERT(xShell.Is());
373 :
374 2 : ScDocShellRef xDocSh = saveAndReload(xShell, ODS);
375 1 : CPPUNIT_ASSERT(xDocSh.Is());
376 :
377 1 : ScDocument& rDoc = xDocSh->GetDocument();
378 :
379 1 : testColorScale2Entry_Impl(rDoc);
380 1 : testColorScale3Entry_Impl(rDoc);
381 :
382 2 : xDocSh->DoClose();
383 1 : }
384 :
385 1 : void ScExportTest::testColorScaleExportXLSX()
386 : {
387 1 : ScDocShellRef xShell = loadDoc("colorscale.", XLSX);
388 1 : CPPUNIT_ASSERT(xShell.Is());
389 :
390 2 : ScDocShellRef xDocSh = saveAndReload(xShell, XLSX);
391 1 : CPPUNIT_ASSERT(xDocSh.Is());
392 :
393 1 : ScDocument& rDoc = xDocSh->GetDocument();
394 :
395 1 : testColorScale2Entry_Impl(rDoc);
396 1 : testColorScale3Entry_Impl(rDoc);
397 :
398 2 : xDocSh->DoClose();
399 1 : }
400 :
401 1 : void ScExportTest::testDataBarExportODS()
402 : {
403 1 : ScDocShellRef xShell = loadDoc("databar.", ODS);
404 1 : CPPUNIT_ASSERT(xShell.Is());
405 :
406 2 : ScDocShellRef xDocSh = saveAndReload(xShell, ODS);
407 1 : CPPUNIT_ASSERT(xDocSh.Is());
408 :
409 1 : ScDocument& rDoc = xDocSh->GetDocument();
410 :
411 1 : testDataBar_Impl(rDoc);
412 :
413 2 : xDocSh->DoClose();
414 1 : }
415 :
416 1 : void ScExportTest::testFormatExportODS()
417 : {
418 1 : ScDocShellRef xShell = loadDoc("formats.", ODS);
419 1 : CPPUNIT_ASSERT(xShell.Is());
420 :
421 2 : ScDocShellRef xDocSh = saveAndReload(xShell, ODS);
422 1 : CPPUNIT_ASSERT(xDocSh.Is());
423 :
424 1 : ScDocument& rDoc = xDocSh->GetDocument();
425 :
426 1 : testFormats(this, &rDoc, ODS);
427 :
428 2 : xDocSh->DoClose();
429 1 : }
430 :
431 1 : void ScExportTest::testDataBarExportXLSX()
432 : {
433 1 : ScDocShellRef xShell = loadDoc("databar.", XLSX);
434 1 : CPPUNIT_ASSERT(xShell.Is());
435 :
436 2 : ScDocShellRef xDocSh = saveAndReload(xShell, XLSX);
437 1 : CPPUNIT_ASSERT(xDocSh.Is());
438 :
439 1 : ScDocument& rDoc = xDocSh->GetDocument();
440 :
441 1 : testDataBar_Impl(rDoc);
442 :
443 2 : xDocSh->DoClose();
444 1 : }
445 :
446 1 : void ScExportTest::testMiscRowHeightExport()
447 : {
448 : TestParam::RowData DfltRowData[] =
449 : {
450 : { 0, 4, 0, 529, 0, false },
451 : { 5, 10, 0, 1058, 0, false },
452 : { 17, 20, 0, 1767, 0, false },
453 : // check last couple of row in document to ensure
454 : // they are 5.29mm ( effective default row xlsx height )
455 : { 1048573, 1048575, 0, 529, 0, false },
456 1 : };
457 :
458 : TestParam::RowData EmptyRepeatRowData[] =
459 : {
460 : // rows 0-4, 5-10, 17-20 are all set at various
461 : // heights, there is no content in the rows, there
462 : // was a bug where only the first row ( of repeated rows )
463 : // was set after export
464 : { 0, 4, 0, 529, 0, false },
465 : { 5, 10, 0, 1058, 0, false },
466 : { 17, 20, 0, 1767, 0, false },
467 1 : };
468 :
469 : TestParam aTestValues[] =
470 : {
471 : // Checks that some distributed ( non-empty ) heights remain set after export (roundtrip)
472 : // additionally there is effectively a default row height ( 5.29 mm ). So we test the
473 : // unset rows at the end of the document to ensure the effective xlsx default height
474 : // is set there too.
475 : { "miscrowheights.", XLSX, XLSX, SAL_N_ELEMENTS(DfltRowData), DfltRowData },
476 : // Checks that some distributed ( non-empty ) heights remain set after export (to xls)
477 : { "miscrowheights.", XLSX, XLS, SAL_N_ELEMENTS(DfltRowData), DfltRowData },
478 : // Checks that repreated rows ( of various heights ) remain set after export ( to xlsx )
479 : { "miscemptyrepeatedrowheights.", ODS, XLSX, SAL_N_ELEMENTS(EmptyRepeatRowData), EmptyRepeatRowData },
480 : // Checks that repreated rows ( of various heights ) remain set after export ( to xls )
481 : { "miscemptyrepeatedrowheights.", ODS, XLS, SAL_N_ELEMENTS(EmptyRepeatRowData), EmptyRepeatRowData },
482 1 : };
483 1 : miscRowHeightsTest( aTestValues, SAL_N_ELEMENTS(aTestValues) );
484 1 : }
485 :
486 : namespace {
487 :
488 5 : void setAttribute( ScFieldEditEngine& rEE, sal_Int32 nPara, sal_Int32 nStart, sal_Int32 nEnd, sal_uInt16 nType )
489 : {
490 5 : ESelection aSel;
491 5 : aSel.nStartPara = aSel.nEndPara = nPara;
492 5 : aSel.nStartPos = nStart;
493 5 : aSel.nEndPos = nEnd;
494 :
495 5 : SfxItemSet aItemSet = rEE.GetEmptyItemSet();
496 5 : switch (nType)
497 : {
498 : case EE_CHAR_WEIGHT:
499 : {
500 1 : SvxWeightItem aWeight(WEIGHT_BOLD, nType);
501 1 : aItemSet.Put(aWeight);
502 1 : rEE.QuickSetAttribs(aItemSet, aSel);
503 : }
504 1 : break;
505 : case EE_CHAR_ITALIC:
506 : {
507 1 : SvxPostureItem aItalic(ITALIC_NORMAL, nType);
508 1 : aItemSet.Put(aItalic);
509 1 : rEE.QuickSetAttribs(aItemSet, aSel);
510 : }
511 1 : break;
512 : case EE_CHAR_STRIKEOUT:
513 : {
514 1 : SvxCrossedOutItem aCrossOut(STRIKEOUT_SINGLE, nType);
515 1 : aItemSet.Put(aCrossOut);
516 1 : rEE.QuickSetAttribs(aItemSet, aSel);
517 : }
518 1 : break;
519 : case EE_CHAR_OVERLINE:
520 : {
521 1 : SvxOverlineItem aItem(UNDERLINE_DOUBLE, nType);
522 1 : aItemSet.Put(aItem);
523 1 : rEE.QuickSetAttribs(aItemSet, aSel);
524 : }
525 1 : break;
526 : case EE_CHAR_UNDERLINE:
527 : {
528 1 : SvxUnderlineItem aItem(UNDERLINE_DOUBLE, nType);
529 1 : aItemSet.Put(aItem);
530 1 : rEE.QuickSetAttribs(aItemSet, aSel);
531 : }
532 1 : break;
533 : default:
534 : ;
535 5 : }
536 5 : }
537 :
538 2 : void setFont( ScFieldEditEngine& rEE, sal_Int32 nPara, sal_Int32 nStart, sal_Int32 nEnd, const OUString& rFontName )
539 : {
540 2 : ESelection aSel;
541 2 : aSel.nStartPara = aSel.nEndPara = nPara;
542 2 : aSel.nStartPos = nStart;
543 2 : aSel.nEndPos = nEnd;
544 :
545 2 : SfxItemSet aItemSet = rEE.GetEmptyItemSet();
546 4 : SvxFontItem aItem(FAMILY_MODERN, rFontName, "", PITCH_VARIABLE, RTL_TEXTENCODING_UTF8, EE_CHAR_FONTINFO);
547 2 : aItemSet.Put(aItem);
548 4 : rEE.QuickSetAttribs(aItemSet, aSel);
549 2 : }
550 :
551 : }
552 :
553 1 : void ScExportTest::testNamedRangeBugfdo62729()
554 : {
555 1 : ScDocShellRef xShell = loadDoc("fdo62729.", ODS);
556 1 : CPPUNIT_ASSERT(xShell.Is());
557 1 : ScDocument& rDoc = xShell->GetDocument();
558 :
559 1 : ScRangeName* pNames = rDoc.GetRangeName();
560 : //should be just a single named range
561 1 : CPPUNIT_ASSERT(pNames->size() == 1 );
562 1 : rDoc.DeleteTab(0);
563 : //should be still a single named range
564 1 : CPPUNIT_ASSERT(pNames->size() == 1 );
565 2 : ScDocShellRef xDocSh = saveAndReload(xShell, ODS);
566 1 : xShell->DoClose();
567 :
568 1 : CPPUNIT_ASSERT(xDocSh.Is());
569 1 : ScDocument& rDoc2 = xDocSh->GetDocument();
570 :
571 1 : pNames = rDoc2.GetRangeName();
572 : //after reload should still have a named range
573 1 : CPPUNIT_ASSERT(pNames->size() == 1 );
574 :
575 2 : xDocSh->DoClose();
576 1 : }
577 :
578 1 : void ScExportTest::testRichTextExportODS()
579 : {
580 : struct
581 : {
582 3 : static bool isBold(const editeng::Section& rAttr)
583 : {
584 3 : if (rAttr.maAttributes.empty())
585 0 : return false;
586 :
587 3 : std::vector<const SfxPoolItem*>::const_iterator it = rAttr.maAttributes.begin(), itEnd = rAttr.maAttributes.end();
588 3 : for (; it != itEnd; ++it)
589 : {
590 3 : const SfxPoolItem* p = *it;
591 3 : if (p->Which() != EE_CHAR_WEIGHT)
592 0 : continue;
593 :
594 3 : return static_cast<const SvxWeightItem*>(p)->GetWeight() == WEIGHT_BOLD;
595 : }
596 0 : return false;
597 : }
598 :
599 3 : static bool isItalic(const editeng::Section& rAttr)
600 : {
601 3 : if (rAttr.maAttributes.empty())
602 0 : return false;
603 :
604 3 : std::vector<const SfxPoolItem*>::const_iterator it = rAttr.maAttributes.begin(), itEnd = rAttr.maAttributes.end();
605 3 : for (; it != itEnd; ++it)
606 : {
607 3 : const SfxPoolItem* p = *it;
608 3 : if (p->Which() != EE_CHAR_ITALIC)
609 0 : continue;
610 :
611 3 : return static_cast<const SvxPostureItem*>(p)->GetPosture() == ITALIC_NORMAL;
612 : }
613 0 : return false;
614 : }
615 :
616 2 : static bool isStrikeOut(const editeng::Section& rAttr)
617 : {
618 2 : if (rAttr.maAttributes.empty())
619 0 : return false;
620 :
621 2 : std::vector<const SfxPoolItem*>::const_iterator it = rAttr.maAttributes.begin(), itEnd = rAttr.maAttributes.end();
622 2 : for (; it != itEnd; ++it)
623 : {
624 2 : const SfxPoolItem* p = *it;
625 2 : if (p->Which() != EE_CHAR_STRIKEOUT)
626 0 : continue;
627 :
628 2 : return static_cast<const SvxCrossedOutItem*>(p)->GetStrikeout() == STRIKEOUT_SINGLE;
629 : }
630 0 : return false;
631 : }
632 :
633 2 : static bool isOverline(const editeng::Section& rAttr, FontUnderline eStyle)
634 : {
635 2 : if (rAttr.maAttributes.empty())
636 0 : return false;
637 :
638 2 : std::vector<const SfxPoolItem*>::const_iterator it = rAttr.maAttributes.begin(), itEnd = rAttr.maAttributes.end();
639 2 : for (; it != itEnd; ++it)
640 : {
641 2 : const SfxPoolItem* p = *it;
642 2 : if (p->Which() != EE_CHAR_OVERLINE)
643 0 : continue;
644 :
645 2 : return static_cast<const SvxOverlineItem*>(p)->GetLineStyle() == eStyle;
646 : }
647 0 : return false;
648 : }
649 :
650 2 : static bool isUnderline(const editeng::Section& rAttr, FontUnderline eStyle)
651 : {
652 2 : if (rAttr.maAttributes.empty())
653 0 : return false;
654 :
655 2 : std::vector<const SfxPoolItem*>::const_iterator it = rAttr.maAttributes.begin(), itEnd = rAttr.maAttributes.end();
656 2 : for (; it != itEnd; ++it)
657 : {
658 2 : const SfxPoolItem* p = *it;
659 2 : if (p->Which() != EE_CHAR_UNDERLINE)
660 0 : continue;
661 :
662 2 : return static_cast<const SvxUnderlineItem*>(p)->GetLineStyle() == eStyle;
663 : }
664 0 : return false;
665 : }
666 :
667 4 : static bool isFont(const editeng::Section& rAttr, const OUString& rFontName)
668 : {
669 4 : if (rAttr.maAttributes.empty())
670 0 : return false;
671 :
672 4 : std::vector<const SfxPoolItem*>::const_iterator it = rAttr.maAttributes.begin(), itEnd = rAttr.maAttributes.end();
673 4 : for (; it != itEnd; ++it)
674 : {
675 4 : const SfxPoolItem* p = *it;
676 4 : if (p->Which() != EE_CHAR_FONTINFO)
677 0 : continue;
678 :
679 4 : return static_cast<const SvxFontItem*>(p)->GetFamilyName() == rFontName;
680 : }
681 0 : return false;
682 : }
683 :
684 3 : bool checkB2(const EditTextObject* pText) const
685 : {
686 3 : if (!pText)
687 0 : return false;
688 :
689 3 : if (pText->GetParagraphCount() != 1)
690 0 : return false;
691 :
692 3 : if (pText->GetText(0) != "Bold and Italic")
693 0 : return false;
694 :
695 3 : std::vector<editeng::Section> aSecAttrs;
696 3 : pText->GetAllSections(aSecAttrs);
697 3 : if (aSecAttrs.size() != 3)
698 0 : return false;
699 :
700 : // Check the first bold section.
701 3 : const editeng::Section* pAttr = &aSecAttrs[0];
702 3 : if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 0 || pAttr->mnEnd != 4)
703 0 : return false;
704 :
705 3 : if (pAttr->maAttributes.size() != 1 || !isBold(*pAttr))
706 0 : return false;
707 :
708 : // The middle section should be unformatted.
709 3 : pAttr = &aSecAttrs[1];
710 3 : if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 4 || pAttr->mnEnd != 9)
711 0 : return false;
712 :
713 3 : if (!pAttr->maAttributes.empty())
714 0 : return false;
715 :
716 : // The last section should be italic.
717 3 : pAttr = &aSecAttrs[2];
718 3 : if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 9 || pAttr->mnEnd != 15)
719 0 : return false;
720 :
721 3 : if (pAttr->maAttributes.size() != 1 || !isItalic(*pAttr))
722 0 : return false;
723 :
724 3 : return true;
725 : }
726 :
727 3 : bool checkB4(const EditTextObject* pText) const
728 : {
729 3 : if (!pText)
730 0 : return false;
731 :
732 3 : if (pText->GetParagraphCount() != 3)
733 0 : return false;
734 :
735 3 : if (pText->GetText(0) != "One")
736 0 : return false;
737 :
738 3 : if (pText->GetText(1) != "Two")
739 0 : return false;
740 :
741 3 : if (pText->GetText(2) != "Three")
742 0 : return false;
743 :
744 3 : return true;
745 : }
746 :
747 2 : bool checkB5(const EditTextObject* pText) const
748 : {
749 2 : if (!pText)
750 0 : return false;
751 :
752 2 : if (pText->GetParagraphCount() != 6)
753 0 : return false;
754 :
755 2 : if (!pText->GetText(0).isEmpty())
756 0 : return false;
757 :
758 2 : if (pText->GetText(1) != "Two")
759 0 : return false;
760 :
761 2 : if (pText->GetText(2) != "Three")
762 0 : return false;
763 :
764 2 : if (!pText->GetText(3).isEmpty())
765 0 : return false;
766 :
767 2 : if (pText->GetText(4) != "Five")
768 0 : return false;
769 :
770 2 : if (!pText->GetText(5).isEmpty())
771 0 : return false;
772 :
773 2 : return true;
774 : }
775 :
776 2 : bool checkB6(const EditTextObject* pText) const
777 : {
778 2 : if (!pText)
779 0 : return false;
780 :
781 2 : if (pText->GetParagraphCount() != 1)
782 0 : return false;
783 :
784 2 : if (pText->GetText(0) != "Strike Me")
785 0 : return false;
786 :
787 2 : std::vector<editeng::Section> aSecAttrs;
788 2 : pText->GetAllSections(aSecAttrs);
789 2 : if (aSecAttrs.size() != 2)
790 0 : return false;
791 :
792 : // Check the first strike-out section.
793 2 : const editeng::Section* pAttr = &aSecAttrs[0];
794 2 : if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 0 || pAttr->mnEnd != 6)
795 0 : return false;
796 :
797 2 : if (pAttr->maAttributes.size() != 1 || !isStrikeOut(*pAttr))
798 0 : return false;
799 :
800 : // The last section should be unformatted.
801 2 : pAttr = &aSecAttrs[1];
802 2 : if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 6 || pAttr->mnEnd != 9)
803 0 : return false;
804 :
805 2 : return true;
806 : }
807 :
808 2 : bool checkB7(const EditTextObject* pText) const
809 : {
810 2 : if (!pText)
811 0 : return false;
812 :
813 2 : if (pText->GetParagraphCount() != 1)
814 0 : return false;
815 :
816 2 : if (pText->GetText(0) != "Font1 and Font2")
817 0 : return false;
818 :
819 2 : std::vector<editeng::Section> aSecAttrs;
820 2 : pText->GetAllSections(aSecAttrs);
821 2 : if (aSecAttrs.size() != 3)
822 0 : return false;
823 :
824 : // First section should have "Courier" font applied.
825 2 : const editeng::Section* pAttr = &aSecAttrs[0];
826 2 : if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 0 || pAttr->mnEnd != 5)
827 0 : return false;
828 :
829 2 : if (pAttr->maAttributes.size() != 1 || !isFont(*pAttr, "Courier"))
830 0 : return false;
831 :
832 : // Last section should have "Luxi Mono" applied.
833 2 : pAttr = &aSecAttrs[2];
834 2 : if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 10 || pAttr->mnEnd != 15)
835 0 : return false;
836 :
837 2 : if (pAttr->maAttributes.size() != 1 || !isFont(*pAttr, "Luxi Mono"))
838 0 : return false;
839 :
840 2 : return true;
841 : }
842 :
843 2 : bool checkB8(const EditTextObject* pText) const
844 : {
845 2 : if (!pText)
846 0 : return false;
847 :
848 2 : if (pText->GetParagraphCount() != 1)
849 0 : return false;
850 :
851 2 : if (pText->GetText(0) != "Over and Under")
852 0 : return false;
853 :
854 2 : std::vector<editeng::Section> aSecAttrs;
855 2 : pText->GetAllSections(aSecAttrs);
856 2 : if (aSecAttrs.size() != 3)
857 0 : return false;
858 :
859 : // First section shoul have overline applied.
860 2 : const editeng::Section* pAttr = &aSecAttrs[0];
861 2 : if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 0 || pAttr->mnEnd != 4)
862 0 : return false;
863 :
864 2 : if (pAttr->maAttributes.size() != 1 || !isOverline(*pAttr, UNDERLINE_DOUBLE))
865 0 : return false;
866 :
867 : // Last section should have underline applied.
868 2 : pAttr = &aSecAttrs[2];
869 2 : if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 9 || pAttr->mnEnd != 14)
870 0 : return false;
871 :
872 2 : if (pAttr->maAttributes.size() != 1 || !isUnderline(*pAttr, UNDERLINE_DOUBLE))
873 0 : return false;
874 :
875 2 : return true;
876 : }
877 :
878 : } aCheckFunc;
879 :
880 : // Start with an empty document, put one edit text cell, and make sure it
881 : // survives the save and reload.
882 1 : ScDocShellRef xOrigDocSh = loadDoc("empty.", ODS, true);
883 : const EditTextObject* pEditText;
884 : {
885 1 : ScDocument& rDoc = xOrigDocSh->GetDocument();
886 1 : CPPUNIT_ASSERT_MESSAGE("This document should at least have one sheet.", rDoc.GetTableCount() > 0);
887 :
888 : // Insert an edit text cell.
889 1 : ScFieldEditEngine* pEE = &rDoc.GetEditEngine();
890 1 : pEE->SetText("Bold and Italic");
891 : // Set the 'Bold' part bold.
892 1 : setAttribute(*pEE, 0, 0, 4, EE_CHAR_WEIGHT);
893 : // Set the 'Italic' part italic.
894 1 : setAttribute(*pEE, 0, 9, 15, EE_CHAR_ITALIC);
895 1 : ESelection aSel;
896 1 : aSel.nStartPara = aSel.nEndPara = 0;
897 :
898 : // Set this edit text to cell B2.
899 1 : rDoc.SetEditText(ScAddress(1,1,0), pEE->CreateTextObject());
900 1 : pEditText = rDoc.GetEditText(ScAddress(1,1,0));
901 1 : CPPUNIT_ASSERT_MESSAGE("Incorret B2 value.", aCheckFunc.checkB2(pEditText));
902 : }
903 :
904 : // Now, save and reload this document.
905 2 : ScDocShellRef xNewDocSh = saveAndReload(xOrigDocSh, ODS);
906 : {
907 1 : xOrigDocSh->DoClose();
908 1 : CPPUNIT_ASSERT(xNewDocSh.Is());
909 1 : ScDocument& rDoc2 = xNewDocSh->GetDocument();
910 1 : CPPUNIT_ASSERT_MESSAGE("Reloaded document should at least have one sheet.", rDoc2.GetTableCount() > 0);
911 1 : ScFieldEditEngine* pEE = &rDoc2.GetEditEngine();
912 :
913 : // Make sure the content of B2 is still intact.
914 1 : CPPUNIT_ASSERT_MESSAGE("Incorret B2 value.", aCheckFunc.checkB2(pEditText));
915 :
916 : // Insert a multi-line content to B4.
917 1 : pEE->Clear();
918 1 : pEE->SetText("One\nTwo\nThree");
919 1 : rDoc2.SetEditText(ScAddress(1,3,0), pEE->CreateTextObject());
920 1 : pEditText = rDoc2.GetEditText(ScAddress(1,3,0));
921 1 : CPPUNIT_ASSERT_MESSAGE("Incorrect B4 value.", aCheckFunc.checkB4(pEditText));
922 : }
923 :
924 : // Reload the doc again, and check the content of B2 and B4.
925 2 : ScDocShellRef xNewDocSh2 = saveAndReload(xNewDocSh, ODS);
926 : {
927 1 : ScDocument& rDoc3 = xNewDocSh2->GetDocument();
928 1 : ScFieldEditEngine* pEE = &rDoc3.GetEditEngine();
929 1 : xNewDocSh->DoClose();
930 :
931 1 : pEditText = rDoc3.GetEditText(ScAddress(1,1,0));
932 1 : CPPUNIT_ASSERT_MESSAGE("B2 should be an edit text.", pEditText);
933 1 : pEditText = rDoc3.GetEditText(ScAddress(1,3,0));
934 1 : CPPUNIT_ASSERT_MESSAGE("Incorrect B4 value.", aCheckFunc.checkB4(pEditText));
935 :
936 : // Insert a multi-line content to B5, but this time, set some empty paragraphs.
937 1 : pEE->Clear();
938 1 : pEE->SetText("\nTwo\nThree\n\nFive\n");
939 1 : rDoc3.SetEditText(ScAddress(1,4,0), pEE->CreateTextObject());
940 1 : pEditText = rDoc3.GetEditText(ScAddress(1,4,0));
941 1 : CPPUNIT_ASSERT_MESSAGE("Incorrect B5 value.", aCheckFunc.checkB5(pEditText));
942 :
943 : // Insert a text with strikethrough in B6.
944 1 : pEE->Clear();
945 1 : pEE->SetText("Strike Me");
946 : // Set the 'Strike' part strikethrough.
947 1 : setAttribute(*pEE, 0, 0, 6, EE_CHAR_STRIKEOUT);
948 1 : rDoc3.SetEditText(ScAddress(1,5,0), pEE->CreateTextObject());
949 1 : pEditText = rDoc3.GetEditText(ScAddress(1,5,0));
950 1 : CPPUNIT_ASSERT_MESSAGE("Incorrect B6 value.", aCheckFunc.checkB6(pEditText));
951 :
952 : // Insert a text with different font segments in B7.
953 1 : pEE->Clear();
954 1 : pEE->SetText("Font1 and Font2");
955 1 : setFont(*pEE, 0, 0, 5, "Courier");
956 1 : setFont(*pEE, 0, 10, 15, "Luxi Mono");
957 1 : rDoc3.SetEditText(ScAddress(1,6,0), pEE->CreateTextObject());
958 1 : pEditText = rDoc3.GetEditText(ScAddress(1,6,0));
959 1 : CPPUNIT_ASSERT_MESSAGE("Incorrect B7 value.", aCheckFunc.checkB7(pEditText));
960 :
961 : // Insert a text with overline and underline in B8.
962 1 : pEE->Clear();
963 1 : pEE->SetText("Over and Under");
964 1 : setAttribute(*pEE, 0, 0, 4, EE_CHAR_OVERLINE);
965 1 : setAttribute(*pEE, 0, 9, 14, EE_CHAR_UNDERLINE);
966 1 : rDoc3.SetEditText(ScAddress(1,7,0), pEE->CreateTextObject());
967 1 : pEditText = rDoc3.GetEditText(ScAddress(1,7,0));
968 1 : CPPUNIT_ASSERT_MESSAGE("Incorrect B8 value.", aCheckFunc.checkB8(pEditText));
969 : }
970 :
971 : // Reload the doc again, and check the content of B2, B4, B6 and B7.
972 2 : ScDocShellRef xNewDocSh3 = saveAndReload(xNewDocSh2, ODS);
973 1 : ScDocument& rDoc4 = xNewDocSh3->GetDocument();
974 1 : xNewDocSh2->DoClose();
975 :
976 1 : pEditText = rDoc4.GetEditText(ScAddress(1,1,0));
977 1 : CPPUNIT_ASSERT_MESSAGE("Incorrect B2 value after save and reload.", aCheckFunc.checkB2(pEditText));
978 1 : pEditText = rDoc4.GetEditText(ScAddress(1,3,0));
979 1 : CPPUNIT_ASSERT_MESSAGE("Incorrect B4 value after save and reload.", aCheckFunc.checkB4(pEditText));
980 1 : pEditText = rDoc4.GetEditText(ScAddress(1,4,0));
981 1 : CPPUNIT_ASSERT_MESSAGE("Incorrect B5 value after save and reload.", aCheckFunc.checkB5(pEditText));
982 1 : pEditText = rDoc4.GetEditText(ScAddress(1,5,0));
983 1 : CPPUNIT_ASSERT_MESSAGE("Incorrect B6 value after save and reload.", aCheckFunc.checkB6(pEditText));
984 1 : pEditText = rDoc4.GetEditText(ScAddress(1,6,0));
985 1 : CPPUNIT_ASSERT_MESSAGE("Incorrect B7 value after save and reload.", aCheckFunc.checkB7(pEditText));
986 1 : pEditText = rDoc4.GetEditText(ScAddress(1,7,0));
987 1 : CPPUNIT_ASSERT_MESSAGE("Incorrect B8 value after save and reload.", aCheckFunc.checkB8(pEditText));
988 :
989 2 : xNewDocSh3->DoClose();
990 1 : }
991 :
992 1 : void ScExportTest::testFormulaRefSheetNameODS()
993 : {
994 1 : ScDocShellRef xDocSh = loadDoc("formula-quote-in-sheet-name.", ODS, true);
995 : {
996 1 : ScDocument& rDoc = xDocSh->GetDocument();
997 :
998 1 : sc::AutoCalcSwitch aACSwitch(rDoc, true); // turn on auto calc.
999 1 : rDoc.SetString(ScAddress(1,1,0), "='90''s Data'.B2");
1000 1 : CPPUNIT_ASSERT_EQUAL(1.1, rDoc.GetValue(ScAddress(1,1,0)));
1001 1 : if (!checkFormula(rDoc, ScAddress(1,1,0), "'90''s Data'.B2"))
1002 0 : CPPUNIT_FAIL("Wrong formula");
1003 : }
1004 : // Now, save and reload this document.
1005 2 : ScDocShellRef xNewDocSh = saveAndReload(xDocSh, ODS);
1006 1 : xDocSh->DoClose();
1007 :
1008 1 : ScDocument& rDoc = xNewDocSh->GetDocument();
1009 1 : rDoc.CalcAll();
1010 1 : CPPUNIT_ASSERT_EQUAL(1.1, rDoc.GetValue(ScAddress(1,1,0)));
1011 1 : if (!checkFormula(rDoc, ScAddress(1,1,0), "'90''s Data'.B2"))
1012 0 : CPPUNIT_FAIL("Wrong formula");
1013 :
1014 2 : xNewDocSh->DoClose();
1015 1 : }
1016 :
1017 1 : void ScExportTest::testCellValuesExportODS()
1018 : {
1019 : // Start with an empty document
1020 1 : ScDocShellRef xOrigDocSh = loadDoc("empty.", ODS);
1021 : {
1022 1 : ScDocument& rDoc = xOrigDocSh->GetDocument();
1023 1 : CPPUNIT_ASSERT_MESSAGE("This document should at least have one sheet.", rDoc.GetTableCount() > 0);
1024 :
1025 : // set a value double
1026 1 : rDoc.SetValue(ScAddress(0,0,0), 2.0); // A1
1027 :
1028 : // set a formula
1029 1 : rDoc.SetValue(ScAddress(2,0,0), 3.0); // C1
1030 1 : rDoc.SetValue(ScAddress(3,0,0), 3); // D1
1031 1 : rDoc.SetString(ScAddress(4,0,0), "=10*C1/4"); // E1
1032 1 : rDoc.SetValue(ScAddress(5,0,0), 3.0); // F1
1033 1 : rDoc.SetString(ScAddress(7,0,0), "=SUM(C1:F1)"); //H1
1034 :
1035 : // set a string
1036 1 : rDoc.SetString(ScAddress(0,2,0), "a simple line"); //A3
1037 :
1038 : // set a digit string
1039 1 : rDoc.SetString(ScAddress(0,4,0), "'12"); //A5
1040 : // set a contiguous value
1041 1 : rDoc.SetValue(ScAddress(0,5,0), 12.0); //A6
1042 : // set acontiguous string
1043 1 : rDoc.SetString(ScAddress(0,6,0), "a string"); //A7
1044 : // set a contiguous formula
1045 1 : rDoc.SetString(ScAddress(0,7,0), "=$A$6"); //A8
1046 : }
1047 : // save and reload
1048 2 : ScDocShellRef xNewDocSh = saveAndReload(xOrigDocSh, ODS);
1049 1 : xOrigDocSh->DoClose();
1050 1 : CPPUNIT_ASSERT(xNewDocSh.Is());
1051 1 : ScDocument& rDoc = xNewDocSh->GetDocument();
1052 1 : CPPUNIT_ASSERT_MESSAGE("Reloaded document should at least have one sheet.", rDoc.GetTableCount() > 0);
1053 :
1054 : // check value
1055 1 : CPPUNIT_ASSERT_EQUAL(2.0, rDoc.GetValue(0,0,0));
1056 1 : CPPUNIT_ASSERT_EQUAL(3.0, rDoc.GetValue(2,0,0));
1057 1 : CPPUNIT_ASSERT_EQUAL(3.0, rDoc.GetValue(3,0,0));
1058 1 : CPPUNIT_ASSERT_EQUAL(7.5, rDoc.GetValue(4,0,0));
1059 1 : CPPUNIT_ASSERT_EQUAL(3.0, rDoc.GetValue(5,0,0));
1060 :
1061 : // check formula
1062 1 : if (!checkFormula(rDoc, ScAddress(4,0,0), "10*C1/4"))
1063 0 : CPPUNIT_FAIL("Wrong formula =10*C1/4");
1064 1 : if (!checkFormula(rDoc, ScAddress(7,0,0), "SUM(C1:F1)"))
1065 0 : CPPUNIT_FAIL("Wrong formula =SUM(C1:F1)");
1066 1 : CPPUNIT_ASSERT_EQUAL(16.5, rDoc.GetValue(7,0,0));
1067 :
1068 : // check string
1069 2 : ScRefCellValue aCell;
1070 1 : aCell.assign(rDoc, ScAddress(0,2,0));
1071 1 : CPPUNIT_ASSERT_EQUAL( CELLTYPE_STRING, aCell.meType );
1072 :
1073 : // check for an empty cell
1074 1 : aCell.assign(rDoc, ScAddress(0,3,0));
1075 1 : CPPUNIT_ASSERT_EQUAL( CELLTYPE_NONE, aCell.meType);
1076 :
1077 : // check a digit string
1078 1 : aCell.assign(rDoc, ScAddress(0,4,0));
1079 1 : CPPUNIT_ASSERT_EQUAL( CELLTYPE_STRING, aCell.meType);
1080 :
1081 : //check contiguous values
1082 1 : CPPUNIT_ASSERT_EQUAL( 12.0, rDoc.GetValue(0,5,0) );
1083 1 : CPPUNIT_ASSERT_EQUAL( OUString("a string"), rDoc.GetString(0,6,0) );
1084 1 : if (!checkFormula(rDoc, ScAddress(0,7,0), "$A$6"))
1085 0 : CPPUNIT_FAIL("Wrong formula =$A$6");
1086 1 : CPPUNIT_ASSERT_EQUAL( rDoc.GetValue(0,5,0), rDoc.GetValue(0,7,0) );
1087 :
1088 2 : xNewDocSh->DoClose();
1089 1 : }
1090 :
1091 1 : void ScExportTest::testCellNoteExportODS()
1092 : {
1093 1 : ScDocShellRef xOrigDocSh = loadDoc("single-note.", ODS);
1094 1 : ScAddress aPos(0,0,0); // Start with A1.
1095 : {
1096 1 : ScDocument& rDoc = xOrigDocSh->GetDocument();
1097 :
1098 1 : CPPUNIT_ASSERT_MESSAGE("There should be a note at A1.", rDoc.HasNote(aPos));
1099 :
1100 1 : aPos.IncRow(); // Move to A2.
1101 1 : ScPostIt* pNote = rDoc.GetOrCreateNote(aPos);
1102 1 : pNote->SetText(aPos, "Note One");
1103 1 : pNote->SetAuthor("Author One");
1104 1 : CPPUNIT_ASSERT_MESSAGE("There should be a note at A2.", rDoc.HasNote(aPos));
1105 : }
1106 : // save and reload
1107 2 : ScDocShellRef xNewDocSh = saveAndReload(xOrigDocSh, ODS);
1108 1 : xOrigDocSh->DoClose();
1109 1 : CPPUNIT_ASSERT(xNewDocSh.Is());
1110 1 : ScDocument& rDoc = xNewDocSh->GetDocument();
1111 :
1112 1 : aPos.SetRow(0); // Move back to A1.
1113 1 : CPPUNIT_ASSERT_MESSAGE("There should be a note at A1.", rDoc.HasNote(aPos));
1114 1 : aPos.IncRow(); // Move to A2.
1115 1 : CPPUNIT_ASSERT_MESSAGE("There should be a note at A2.", rDoc.HasNote(aPos));
1116 :
1117 2 : xNewDocSh->DoClose();
1118 1 : }
1119 :
1120 1 : void ScExportTest::testCellNoteExportXLS()
1121 : {
1122 : // Start with an empty document.s
1123 1 : ScDocShellRef xOrigDocSh = loadDoc("notes-on-3-sheets.", ODS);
1124 : {
1125 1 : ScDocument& rDoc = xOrigDocSh->GetDocument();
1126 1 : CPPUNIT_ASSERT_MESSAGE("This document should have 3 sheets.", rDoc.GetTableCount() == 3);
1127 :
1128 : // Check note's presence.
1129 1 : CPPUNIT_ASSERT( rDoc.HasNote(ScAddress(0,0,0)));
1130 1 : CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,1,0)));
1131 1 : CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,2,0)));
1132 :
1133 1 : CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,0,1)));
1134 1 : CPPUNIT_ASSERT( rDoc.HasNote(ScAddress(0,1,1)));
1135 1 : CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,2,1)));
1136 :
1137 1 : CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,0,2)));
1138 1 : CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,1,2)));
1139 1 : CPPUNIT_ASSERT( rDoc.HasNote(ScAddress(0,2,2)));
1140 : }
1141 : // save and reload as XLS.
1142 2 : ScDocShellRef xNewDocSh = saveAndReload(xOrigDocSh, XLS);
1143 : {
1144 1 : xOrigDocSh->DoClose();
1145 1 : CPPUNIT_ASSERT(xNewDocSh.Is());
1146 1 : ScDocument& rDoc = xNewDocSh->GetDocument();
1147 1 : CPPUNIT_ASSERT_MESSAGE("This document should have 3 sheets.", rDoc.GetTableCount() == 3);
1148 :
1149 : // Check note's presence again.
1150 1 : CPPUNIT_ASSERT( rDoc.HasNote(ScAddress(0,0,0)));
1151 1 : CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,1,0)));
1152 1 : CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,2,0)));
1153 :
1154 1 : CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,0,1)));
1155 1 : CPPUNIT_ASSERT( rDoc.HasNote(ScAddress(0,1,1)));
1156 1 : CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,2,1)));
1157 :
1158 1 : CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,0,2)));
1159 1 : CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,1,2)));
1160 1 : CPPUNIT_ASSERT( rDoc.HasNote(ScAddress(0,2,2)));
1161 :
1162 1 : xNewDocSh->DoClose();
1163 1 : }
1164 1 : }
1165 :
1166 : namespace {
1167 :
1168 3 : void checkMatrixRange(ScDocument& rDoc, const ScRange& rRange)
1169 : {
1170 3 : ScRange aMatRange;
1171 3 : ScAddress aMatOrigin;
1172 10 : for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
1173 : {
1174 23 : for (SCROW nRow = rRange.aStart.Row(); nRow <= rRange.aEnd.Row(); ++nRow)
1175 : {
1176 16 : ScAddress aPos(nCol, nRow, rRange.aStart.Tab());
1177 16 : bool bIsMatrix = rDoc.GetMatrixFormulaRange(aPos, aMatRange);
1178 16 : CPPUNIT_ASSERT_MESSAGE("Matrix expected, but not found.", bIsMatrix);
1179 16 : CPPUNIT_ASSERT_MESSAGE("Wrong matrix range.", rRange == aMatRange);
1180 16 : const ScFormulaCell* pCell = rDoc.GetFormulaCell(aPos);
1181 16 : CPPUNIT_ASSERT_MESSAGE("This must be a formula cell.", pCell);
1182 :
1183 16 : bIsMatrix = pCell->GetMatrixOrigin(aMatOrigin);
1184 16 : CPPUNIT_ASSERT_MESSAGE("Not a part of matrix formula.", bIsMatrix);
1185 16 : CPPUNIT_ASSERT_MESSAGE("Wrong matrix origin.", aMatOrigin == aMatRange.aStart);
1186 : }
1187 : }
1188 3 : }
1189 :
1190 : }
1191 :
1192 1 : void ScExportTest::testInlineArrayXLS()
1193 : {
1194 1 : ScDocShellRef xShell = loadDoc("inline-array.", XLS);
1195 1 : CPPUNIT_ASSERT(xShell.Is());
1196 :
1197 2 : ScDocShellRef xDocSh = saveAndReload(xShell, XLS);
1198 1 : xShell->DoClose();
1199 1 : CPPUNIT_ASSERT(xDocSh.Is());
1200 :
1201 1 : ScDocument& rDoc = xDocSh->GetDocument();
1202 :
1203 : // B2:C3 contains a matrix.
1204 1 : checkMatrixRange(rDoc, ScRange(1,1,0,2,2,0));
1205 :
1206 : // B5:D6 contains a matrix.
1207 1 : checkMatrixRange(rDoc, ScRange(1,4,0,3,5,0));
1208 :
1209 : // B8:C10 as well.
1210 1 : checkMatrixRange(rDoc, ScRange(1,7,0,2,9,0));
1211 :
1212 2 : xDocSh->DoClose();
1213 1 : }
1214 :
1215 1 : void ScExportTest::testEmbeddedChartXLS()
1216 : {
1217 1 : ScDocShellRef xShell = loadDoc("embedded-chart.", XLS);
1218 1 : CPPUNIT_ASSERT(xShell.Is());
1219 :
1220 2 : ScDocShellRef xDocSh = saveAndReload(xShell, XLS);
1221 1 : xShell->DoClose();
1222 1 : CPPUNIT_ASSERT(xDocSh.Is());
1223 :
1224 1 : ScDocument& rDoc = xDocSh->GetDocument();
1225 :
1226 : // Make sure the 2nd sheet is named 'Chart1'.
1227 2 : OUString aName;
1228 1 : rDoc.GetName(1, aName);
1229 1 : CPPUNIT_ASSERT_EQUAL(OUString("Chart1"), aName);
1230 :
1231 1 : const SdrOle2Obj* pOleObj = getSingleChartObject(rDoc, 1);
1232 1 : CPPUNIT_ASSERT_MESSAGE("Failed to retrieve a chart object from the 2nd sheet.", pOleObj);
1233 :
1234 2 : ScRangeList aRanges = getChartRanges(rDoc, *pOleObj);
1235 1 : CPPUNIT_ASSERT_MESSAGE("Label range (B3:B5) not found.", aRanges.In(ScRange(1,2,1,1,4,1)));
1236 1 : CPPUNIT_ASSERT_MESSAGE("Data label (C2) not found.", aRanges.In(ScAddress(2,1,1)));
1237 1 : CPPUNIT_ASSERT_MESSAGE("Data range (C3:C5) not found.", aRanges.In(ScRange(2,2,1,2,4,1)));
1238 :
1239 2 : xDocSh->DoClose();
1240 1 : }
1241 :
1242 1 : void ScExportTest::testFormulaReferenceXLS()
1243 : {
1244 1 : ScDocShellRef xShell = loadDoc("formula-reference.", XLS);
1245 1 : CPPUNIT_ASSERT(xShell.Is());
1246 :
1247 2 : ScDocShellRef xDocSh = saveAndReload(xShell, XLS);
1248 1 : xShell->DoClose();
1249 1 : CPPUNIT_ASSERT(xDocSh.Is());
1250 :
1251 1 : ScDocument& rDoc = xDocSh->GetDocument();
1252 :
1253 1 : if (!checkFormula(rDoc, ScAddress(3,1,0), "$A$2+$B$2+$C$2"))
1254 0 : CPPUNIT_FAIL("Wrong formula in D2");
1255 :
1256 1 : if (!checkFormula(rDoc, ScAddress(3,2,0), "A3+B3+C3"))
1257 0 : CPPUNIT_FAIL("Wrong formula in D3");
1258 :
1259 1 : if (!checkFormula(rDoc, ScAddress(3,5,0), "SUM($A$6:$C$6)"))
1260 0 : CPPUNIT_FAIL("Wrong formula in D6");
1261 :
1262 1 : if (!checkFormula(rDoc, ScAddress(3,6,0), "SUM(A7:C7)"))
1263 0 : CPPUNIT_FAIL("Wrong formula in D7");
1264 :
1265 1 : if (!checkFormula(rDoc, ScAddress(3,9,0), "$Two.$A$2+$Two.$B$2+$Two.$C$2"))
1266 0 : CPPUNIT_FAIL("Wrong formula in D10");
1267 :
1268 1 : if (!checkFormula(rDoc, ScAddress(3,10,0), "$Two.A3+$Two.B3+$Two.C3"))
1269 0 : CPPUNIT_FAIL("Wrong formula in D11");
1270 :
1271 1 : if (!checkFormula(rDoc, ScAddress(3,13,0), "MIN($Two.$A$2:$C$2)"))
1272 0 : CPPUNIT_FAIL("Wrong formula in D14");
1273 :
1274 1 : if (!checkFormula(rDoc, ScAddress(3,14,0), "MAX($Two.A3:C3)"))
1275 0 : CPPUNIT_FAIL("Wrong formula in D15");
1276 :
1277 2 : xDocSh->DoClose();
1278 1 : }
1279 :
1280 1 : void ScExportTest::testSheetProtectionXLSX()
1281 : {
1282 1 : ScDocShellRef xShell = loadDoc("ProtecteSheet1234Pass.", XLSX);
1283 1 : CPPUNIT_ASSERT(xShell.Is());
1284 :
1285 2 : ScDocShellRef xDocSh = saveAndReload(xShell, XLSX);
1286 1 : CPPUNIT_ASSERT(xDocSh.Is());
1287 :
1288 1 : ScDocument& rDoc = xDocSh->GetDocument();
1289 1 : const ScTableProtection* pTabProtect = rDoc.GetTabProtection(0);
1290 1 : CPPUNIT_ASSERT(pTabProtect);
1291 1 : if ( pTabProtect )
1292 : {
1293 1 : Sequence<sal_Int8> aHash = pTabProtect->getPasswordHash(PASSHASH_XL);
1294 : // check has
1295 1 : if (aHash.getLength() >= 2)
1296 : {
1297 1 : CPPUNIT_ASSERT( (sal_uInt8)aHash[0] == 204 );
1298 1 : CPPUNIT_ASSERT( (sal_uInt8)aHash[1] == 61 );
1299 : }
1300 : // we could flesh out this check I guess
1301 1 : CPPUNIT_ASSERT ( !pTabProtect->isOptionEnabled( ScTableProtection::OBJECTS ) );
1302 1 : CPPUNIT_ASSERT ( !pTabProtect->isOptionEnabled( ScTableProtection::SCENARIOS ) );
1303 : }
1304 2 : xDocSh->DoClose();
1305 1 : }
1306 :
1307 : namespace {
1308 :
1309 96 : const char* toBorderName( sal_Int16 eStyle )
1310 : {
1311 96 : switch (eStyle)
1312 : {
1313 32 : case table::BorderLineStyle::SOLID: return "SOLID";
1314 8 : case table::BorderLineStyle::DOTTED: return "DOTTED";
1315 8 : case table::BorderLineStyle::DASHED: return "DASHED";
1316 16 : case table::BorderLineStyle::DASH_DOT: return "DASH_DOT";
1317 16 : case table::BorderLineStyle::DASH_DOT_DOT: return "DASH_DOT_DOT";
1318 8 : case table::BorderLineStyle::DOUBLE_THIN: return "DOUBLE_THIN";
1319 8 : case table::BorderLineStyle::FINE_DASHED: return "FINE_DASHED";
1320 : default:
1321 : ;
1322 : }
1323 :
1324 0 : return "";
1325 : }
1326 :
1327 : }
1328 :
1329 2 : void ScExportTest::testExcelCellBorders( sal_uLong nFormatType )
1330 : {
1331 : struct
1332 : {
1333 : SCROW mnRow;
1334 : sal_Int16 mnStyle;
1335 : long mnWidth;
1336 : } aChecks[] = {
1337 : { 1, table::BorderLineStyle::SOLID, 1L }, // hair
1338 : { 3, table::BorderLineStyle::DOTTED, 15L }, // dotted
1339 : { 5, table::BorderLineStyle::DASH_DOT_DOT, 15L }, // dash dot dot
1340 : { 7, table::BorderLineStyle::DASH_DOT, 15L }, // dash dot
1341 : { 9, table::BorderLineStyle::FINE_DASHED, 15L }, // dashed
1342 : { 11, table::BorderLineStyle::SOLID, 15L }, // thin
1343 : { 13, table::BorderLineStyle::DASH_DOT_DOT, 35L }, // medium dash dot dot
1344 : { 17, table::BorderLineStyle::DASH_DOT, 35L }, // medium dash dot
1345 : { 19, table::BorderLineStyle::DASHED, 35L }, // medium dashed
1346 : { 21, table::BorderLineStyle::SOLID, 35L }, // medium
1347 : { 23, table::BorderLineStyle::SOLID, 50L }, // thick
1348 : { 25, table::BorderLineStyle::DOUBLE_THIN, -1L }, // double (don't check width)
1349 2 : };
1350 :
1351 2 : ScDocShellRef xDocSh = loadDoc("cell-borders.", nFormatType);
1352 2 : CPPUNIT_ASSERT_MESSAGE("Failed to load file", xDocSh.Is());
1353 : {
1354 2 : ScDocument& rDoc = xDocSh->GetDocument();
1355 :
1356 26 : for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
1357 : {
1358 24 : const editeng::SvxBorderLine* pLine = NULL;
1359 24 : rDoc.GetBorderLines(2, aChecks[i].mnRow, 0, NULL, &pLine, NULL, NULL);
1360 24 : CPPUNIT_ASSERT(pLine);
1361 24 : CPPUNIT_ASSERT_EQUAL(toBorderName(aChecks[i].mnStyle), toBorderName(pLine->GetBorderLineStyle()));
1362 24 : if (aChecks[i].mnWidth >= 0)
1363 22 : CPPUNIT_ASSERT_EQUAL(aChecks[i].mnWidth, pLine->GetWidth());
1364 : }
1365 : }
1366 :
1367 4 : ScDocShellRef xNewDocSh = saveAndReload(xDocSh, nFormatType);
1368 2 : xDocSh->DoClose();
1369 2 : ScDocument& rDoc = xNewDocSh->GetDocument();
1370 26 : for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
1371 : {
1372 24 : const editeng::SvxBorderLine* pLine = NULL;
1373 24 : rDoc.GetBorderLines(2, aChecks[i].mnRow, 0, NULL, &pLine, NULL, NULL);
1374 24 : CPPUNIT_ASSERT(pLine);
1375 24 : CPPUNIT_ASSERT_EQUAL(toBorderName(aChecks[i].mnStyle), toBorderName(pLine->GetBorderLineStyle()));
1376 24 : if (aChecks[i].mnWidth >= 0)
1377 22 : CPPUNIT_ASSERT_EQUAL(aChecks[i].mnWidth, pLine->GetWidth());
1378 : }
1379 :
1380 4 : xNewDocSh->DoClose();
1381 2 : }
1382 :
1383 1 : void ScExportTest::testCellBordersXLS()
1384 : {
1385 1 : testExcelCellBorders(XLS);
1386 1 : }
1387 :
1388 1 : void ScExportTest::testCellBordersXLSX()
1389 : {
1390 1 : testExcelCellBorders(XLSX);
1391 1 : }
1392 :
1393 0 : OUString toString( const ScBigRange& rRange )
1394 : {
1395 0 : OUStringBuffer aBuf;
1396 0 : aBuf.appendAscii("(columns:");
1397 0 : aBuf.append(rRange.aStart.Col());
1398 0 : aBuf.append('-');
1399 0 : aBuf.append(rRange.aEnd.Col());
1400 0 : aBuf.appendAscii(";rows:");
1401 0 : aBuf.append(rRange.aStart.Row());
1402 0 : aBuf.append('-');
1403 0 : aBuf.append(rRange.aEnd.Row());
1404 0 : aBuf.appendAscii(";sheets:");
1405 0 : aBuf.append(rRange.aStart.Tab());
1406 0 : aBuf.append('-');
1407 0 : aBuf.append(rRange.aEnd.Tab());
1408 0 : aBuf.append(')');
1409 :
1410 0 : return aBuf.makeStringAndClear();
1411 : }
1412 :
1413 1 : void ScExportTest::testTrackChangesSimpleXLSX()
1414 : {
1415 : struct CheckItem
1416 : {
1417 : sal_uLong mnActionId;
1418 : ScChangeActionType meType;
1419 :
1420 : sal_Int32 mnStartCol;
1421 : sal_Int32 mnStartRow;
1422 : sal_Int32 mnStartTab;
1423 : sal_Int32 mnEndCol;
1424 : sal_Int32 mnEndRow;
1425 : sal_Int32 mnEndTab;
1426 :
1427 : bool mbRowInsertedAtBottom;
1428 : };
1429 :
1430 : struct
1431 : {
1432 52 : bool checkRange( ScChangeActionType eType, const ScBigRange& rExpected, const ScBigRange& rActual )
1433 : {
1434 52 : ScBigRange aExpected(rExpected), aActual(rActual);
1435 :
1436 52 : switch (eType)
1437 : {
1438 : case SC_CAT_INSERT_ROWS:
1439 : {
1440 : // Ignore columns.
1441 24 : aExpected.aStart.SetCol(0);
1442 24 : aExpected.aEnd.SetCol(0);
1443 24 : aActual.aStart.SetCol(0);
1444 24 : aActual.aEnd.SetCol(0);
1445 : }
1446 24 : break;
1447 : default:
1448 : ;
1449 : }
1450 :
1451 52 : return aExpected == aActual;
1452 : }
1453 :
1454 4 : bool check( ScDocument& rDoc )
1455 : {
1456 : CheckItem aChecks[] =
1457 : {
1458 : { 1, SC_CAT_CONTENT , 1, 1, 0, 1, 1, 0, false },
1459 : { 2, SC_CAT_INSERT_ROWS , 0, 2, 0, 0, 2, 0, true },
1460 : { 3, SC_CAT_CONTENT , 1, 2, 0, 1, 2, 0, false },
1461 : { 4, SC_CAT_INSERT_ROWS , 0, 3, 0, 0, 3, 0, true },
1462 : { 5, SC_CAT_CONTENT , 1, 3, 0, 1, 3, 0, false },
1463 : { 6, SC_CAT_INSERT_ROWS , 0, 4, 0, 0, 4, 0, true },
1464 : { 7, SC_CAT_CONTENT , 1, 4, 0, 1, 4, 0, false },
1465 : { 8, SC_CAT_INSERT_ROWS , 0, 5, 0, 0, 5, 0, true },
1466 : { 9, SC_CAT_CONTENT , 1, 5, 0, 1, 5, 0, false },
1467 : { 10, SC_CAT_INSERT_ROWS , 0, 6, 0, 0, 6, 0, true },
1468 : { 11, SC_CAT_CONTENT , 1, 6, 0, 1, 6, 0, false },
1469 : { 12, SC_CAT_INSERT_ROWS , 0, 7, 0, 0, 7, 0, true },
1470 : { 13, SC_CAT_CONTENT , 1, 7, 0, 1, 7, 0, false },
1471 4 : };
1472 :
1473 4 : ScChangeTrack* pCT = rDoc.GetChangeTrack();
1474 4 : if (!pCT)
1475 : {
1476 0 : cerr << "Change track instance doesn't exist." << endl;
1477 0 : return false;
1478 : }
1479 :
1480 4 : sal_uLong nActionMax = pCT->GetActionMax();
1481 4 : if (nActionMax != 13)
1482 : {
1483 0 : cerr << "Unexpected highest action ID value." << endl;
1484 0 : return false;
1485 : }
1486 :
1487 112 : for (size_t i = 0, n = SAL_N_ELEMENTS(aChecks); i < n; ++i)
1488 : {
1489 52 : sal_uInt16 nActId = aChecks[i].mnActionId;
1490 52 : const ScChangeAction* pAction = pCT->GetAction(nActId);
1491 52 : if (!pAction)
1492 : {
1493 0 : cerr << "No action for action number " << nActId << " found." << endl;
1494 0 : return false;
1495 : }
1496 :
1497 52 : if (pAction->GetType() != aChecks[i].meType)
1498 : {
1499 0 : cerr << "Unexpected action type for action number " << nActId << "." << endl;
1500 0 : return false;
1501 : }
1502 :
1503 52 : const ScBigRange& rRange = pAction->GetBigRange();
1504 : ScBigRange aCheck(aChecks[i].mnStartCol, aChecks[i].mnStartRow, aChecks[i].mnStartTab,
1505 52 : aChecks[i].mnEndCol, aChecks[i].mnEndRow, aChecks[i].mnEndTab);
1506 :
1507 52 : if (!checkRange(pAction->GetType(), aCheck, rRange))
1508 : {
1509 0 : cerr << "Unexpected range for action number " << nActId
1510 0 : << ": expected=" << toString(aCheck) << " actual=" << toString(rRange) << endl;
1511 0 : return false;
1512 : }
1513 :
1514 52 : switch (pAction->GetType())
1515 : {
1516 : case SC_CAT_INSERT_ROWS:
1517 : {
1518 24 : const ScChangeActionIns* p = static_cast<const ScChangeActionIns*>(pAction);
1519 24 : if (p->IsEndOfList() != aChecks[i].mbRowInsertedAtBottom)
1520 : {
1521 0 : cerr << "Unexpected end-of-list flag for action number " << nActId << "." << endl;
1522 0 : return false;
1523 : }
1524 : }
1525 24 : break;
1526 : default:
1527 : ;
1528 : }
1529 : }
1530 :
1531 4 : return true;
1532 : }
1533 :
1534 2 : bool checkRevisionUserAndTime( ScDocument& rDoc, const OUString& rOwnerName )
1535 : {
1536 2 : ScChangeTrack* pCT = rDoc.GetChangeTrack();
1537 2 : if (!pCT)
1538 : {
1539 0 : cerr << "Change track instance doesn't exist." << endl;
1540 0 : return false;
1541 : }
1542 :
1543 2 : ScChangeAction* pAction = pCT->GetLast();
1544 2 : if (pAction->GetUser() != "Kohei Yoshida")
1545 : {
1546 0 : cerr << "Wrong user name." << endl;
1547 0 : return false;
1548 : }
1549 :
1550 2 : DateTime aDT = pAction->GetDateTime();
1551 2 : if (aDT.GetYear() != 2014 || aDT.GetMonth() != 7 || aDT.GetDay() != 11)
1552 : {
1553 0 : cerr << "Wrong time stamp." << endl;
1554 0 : return false;
1555 : }
1556 :
1557 : // Insert a new record to make sure the user and date-time are correct.
1558 2 : rDoc.SetString(ScAddress(1,8,0), "New String");
1559 2 : ScCellValue aEmpty;
1560 2 : pCT->AppendContent(ScAddress(1,8,0), aEmpty);
1561 2 : pAction = pCT->GetLast();
1562 2 : if (!pAction)
1563 : {
1564 0 : cerr << "Failed to retrieve last revision." << endl;
1565 0 : return false;
1566 : }
1567 :
1568 2 : if (rOwnerName != pAction->GetUser())
1569 : {
1570 0 : cerr << "Wrong user name." << endl;
1571 0 : return false;
1572 : }
1573 :
1574 2 : DateTime aDTNew = pAction->GetDateTime();
1575 2 : if (aDTNew <= aDT)
1576 : {
1577 0 : cerr << "Time stamp of the new revision should be more recent than that of the last revision." << endl;
1578 0 : return false;
1579 : }
1580 :
1581 2 : return true;
1582 : }
1583 :
1584 : } aTest;
1585 :
1586 1 : SvtUserOptions& rUserOpt = SC_MOD()->GetUserOptions();
1587 1 : rUserOpt.SetToken(UserOptToken::FirstName, "Export");
1588 1 : rUserOpt.SetToken(UserOptToken::LastName, "Test");
1589 :
1590 1 : OUString aOwnerName = rUserOpt.GetFirstName() + " " + rUserOpt.GetLastName();
1591 :
1592 : // First, test the xls variant.
1593 :
1594 2 : ScDocShellRef xDocSh = loadDoc("track-changes/simple-cell-changes.", XLS);
1595 1 : CPPUNIT_ASSERT(xDocSh.Is());
1596 1 : ScDocument* pDoc = &xDocSh->GetDocument();
1597 1 : bool bGood = aTest.check(*pDoc);
1598 1 : CPPUNIT_ASSERT_MESSAGE("Initial check failed (xls).", bGood);
1599 :
1600 2 : ScDocShellRef xDocSh2 = saveAndReload(xDocSh, XLS);
1601 1 : xDocSh->DoClose();
1602 1 : pDoc = &xDocSh2->GetDocument();
1603 1 : bGood = aTest.check(*pDoc);
1604 1 : CPPUNIT_ASSERT_MESSAGE("Check after reload failed (xls).", bGood);
1605 :
1606 : // fdo#81445 : Check the blank value string to make sure it's "<empty>".
1607 1 : ScChangeTrack* pCT = pDoc->GetChangeTrack();
1608 1 : CPPUNIT_ASSERT(pCT);
1609 1 : ScChangeAction* pAction = pCT->GetAction(1);
1610 1 : CPPUNIT_ASSERT(pAction);
1611 2 : OUString aDesc;
1612 1 : pAction->GetDescription(aDesc, pDoc);
1613 1 : CPPUNIT_ASSERT_EQUAL(OUString("Cell B2 changed from '<empty>' to '1'"), aDesc);
1614 :
1615 1 : bGood = aTest.checkRevisionUserAndTime(*pDoc, aOwnerName);
1616 1 : CPPUNIT_ASSERT_MESSAGE("Check revision and time failed after reload (xls).", bGood);
1617 :
1618 1 : xDocSh2->DoClose();
1619 :
1620 : // Now, test the xlsx variant the same way.
1621 :
1622 1 : xDocSh = loadDoc("track-changes/simple-cell-changes.", XLSX);
1623 1 : CPPUNIT_ASSERT(xDocSh.Is());
1624 1 : pDoc = &xDocSh->GetDocument();
1625 1 : aTest.check(*pDoc);
1626 1 : CPPUNIT_ASSERT_MESSAGE("Initial check failed (xlsx).", bGood);
1627 :
1628 1 : xDocSh2 = saveAndReload(xDocSh, XLSX);
1629 1 : xDocSh->DoClose();
1630 1 : pDoc = &xDocSh2->GetDocument();
1631 1 : bGood = aTest.check(*pDoc);
1632 1 : CPPUNIT_ASSERT_MESSAGE("Check after reload failed (xlsx).", bGood);
1633 :
1634 1 : bGood = aTest.checkRevisionUserAndTime(*pDoc, aOwnerName);
1635 1 : CPPUNIT_ASSERT_MESSAGE("Check revision and time failed after reload (xlsx).", bGood);
1636 :
1637 2 : xDocSh2->DoClose();
1638 1 : }
1639 :
1640 1 : void ScExportTest::testSheetTabColorsXLSX()
1641 : {
1642 : struct
1643 : {
1644 2 : bool checkContent( ScDocument& rDoc )
1645 : {
1646 :
1647 2 : std::vector<OUString> aTabNames = rDoc.GetAllTableNames();
1648 :
1649 : // green, red, blue, yellow (from left to right).
1650 2 : if (aTabNames.size() != 4)
1651 : {
1652 0 : cerr << "There should be exactly 4 sheets." << endl;
1653 0 : return false;
1654 : }
1655 :
1656 2 : const char* pNames[] = { "Green", "Red", "Blue", "Yellow" };
1657 10 : for (size_t i = 0, n = SAL_N_ELEMENTS(pNames); i < n; ++i)
1658 : {
1659 8 : OUString aExpected = OUString::createFromAscii(pNames[i]);
1660 8 : if (aExpected != aTabNames[i])
1661 : {
1662 0 : cerr << "incorrect sheet name: expected='" << aExpected <<"', actual='" << aTabNames[i] << "'" << endl;
1663 0 : return false;
1664 : }
1665 8 : }
1666 :
1667 : const ColorData aXclColors[] =
1668 : {
1669 : 0x0000B050, // green
1670 : 0x00FF0000, // red
1671 : 0x000070C0, // blue
1672 : 0x00FFFF00, // yellow
1673 2 : };
1674 :
1675 10 : for (size_t i = 0, n = SAL_N_ELEMENTS(aXclColors); i < n; ++i)
1676 : {
1677 8 : if (aXclColors[i] != rDoc.GetTabBgColor(i).GetColor())
1678 : {
1679 0 : cerr << "wrong sheet color for sheet " << i << endl;
1680 0 : return false;
1681 : }
1682 : }
1683 :
1684 2 : return true;
1685 : }
1686 :
1687 : } aTest;
1688 :
1689 1 : ScDocShellRef xDocSh = loadDoc("sheet-tab-color.", XLSX);
1690 : {
1691 1 : CPPUNIT_ASSERT_MESSAGE("Failed to load file.", xDocSh.Is());
1692 1 : ScDocument& rDoc = xDocSh->GetDocument();
1693 1 : bool bRes = aTest.checkContent(rDoc);
1694 1 : CPPUNIT_ASSERT_MESSAGE("Failed on the initial content check.", bRes);
1695 : }
1696 :
1697 2 : ScDocShellRef xDocSh2 = saveAndReload(xDocSh, XLSX);
1698 1 : CPPUNIT_ASSERT_MESSAGE("Failed to reload file.", xDocSh2.Is());
1699 1 : xDocSh->DoClose();
1700 1 : ScDocument& rDoc = xDocSh2->GetDocument();
1701 1 : bool bRes = aTest.checkContent(rDoc);
1702 1 : CPPUNIT_ASSERT_MESSAGE("Failed on the content check after reload.", bRes);
1703 :
1704 2 : xDocSh2->DoClose();
1705 1 : }
1706 :
1707 1 : void ScExportTest::testSharedFormulaExportXLS()
1708 : {
1709 : struct
1710 : {
1711 2 : bool checkContent( ScDocument& rDoc )
1712 : {
1713 2 : formula::FormulaGrammar::Grammar eGram = formula::FormulaGrammar::GRAM_ENGLISH_XL_R1C1;
1714 2 : rDoc.SetGrammar(eGram);
1715 2 : sc::TokenStringContext aCxt(&rDoc, eGram);
1716 :
1717 : // Check the title row.
1718 :
1719 4 : OUString aActual = rDoc.GetString(0,1,0);
1720 4 : OUString aExpected = "Response";
1721 2 : if (aActual != aExpected)
1722 : {
1723 0 : cerr << "Wrong content in A2: expected='" << aExpected << "', actual='" << aActual << "'" << endl;
1724 0 : return false;
1725 : }
1726 :
1727 2 : aActual = rDoc.GetString(1,1,0);
1728 2 : aExpected = "Response";
1729 2 : if (aActual != aExpected)
1730 : {
1731 0 : cerr << "Wrong content in B2: expected='" << aExpected << "', actual='" << aActual << "'" << endl;
1732 0 : return false;
1733 : }
1734 :
1735 : // A3:A12 and B3:B12 are numbers from 1 to 10.
1736 44 : for (SCROW i = 0; i <= 9; ++i)
1737 : {
1738 20 : double fExpected = i + 1.0;
1739 20 : ScAddress aPos(0,i+2,0);
1740 20 : double fActual = rDoc.GetValue(aPos);
1741 20 : if (fExpected != fActual)
1742 : {
1743 0 : cerr << "Wrong value in A" << (i+2) << ": expected=" << fExpected << ", actual=" << fActual << endl;
1744 0 : return false;
1745 : }
1746 :
1747 20 : aPos.IncCol();
1748 20 : ScFormulaCell* pFC = rDoc.GetFormulaCell(aPos);
1749 20 : if (!pFC)
1750 : {
1751 0 : cerr << "B" << (i+2) << " should be a formula cell." << endl;
1752 0 : return false;
1753 : }
1754 :
1755 20 : OUString aFormula = pFC->GetCode()->CreateString(aCxt, aPos);
1756 20 : aExpected = "Coefficients!RC[-1]";
1757 20 : if (aFormula != aExpected)
1758 : {
1759 0 : cerr << "Wrong formula in B" << (i+2) << ": expected='" << aExpected << "', actual='" << aFormula << "'" << endl;
1760 0 : return false;
1761 : }
1762 :
1763 20 : fActual = rDoc.GetValue(aPos);
1764 20 : if (fExpected != fActual)
1765 : {
1766 0 : cerr << "Wrong value in B" << (i+2) << ": expected=" << fExpected << ", actual=" << fActual << endl;
1767 0 : return false;
1768 : }
1769 20 : }
1770 :
1771 4 : return true;
1772 : }
1773 :
1774 : } aTest;
1775 :
1776 1 : ScDocShellRef xDocSh = loadDoc("shared-formula/3d-reference.", ODS);
1777 : {
1778 1 : CPPUNIT_ASSERT_MESSAGE("Failed to load file.", xDocSh.Is());
1779 1 : ScDocument& rDoc = xDocSh->GetDocument();
1780 :
1781 : // Check the content of the original.
1782 1 : bool bRes = aTest.checkContent(rDoc);
1783 1 : CPPUNIT_ASSERT_MESSAGE("Content check on the original document failed.", bRes);
1784 : }
1785 :
1786 2 : ScDocShellRef xDocSh2 = saveAndReload(xDocSh, XLS);
1787 1 : xDocSh->DoClose();
1788 1 : CPPUNIT_ASSERT_MESSAGE("Failed to reload file.", xDocSh2.Is());
1789 :
1790 1 : ScDocument& rDoc = xDocSh2->GetDocument();
1791 :
1792 : // Check the content of the reloaded. This should be identical.
1793 1 : bool bRes = aTest.checkContent(rDoc);
1794 1 : CPPUNIT_ASSERT_MESSAGE("Content check on the reloaded document failed.", bRes);
1795 :
1796 2 : xDocSh2->DoClose();
1797 1 : }
1798 :
1799 1 : void ScExportTest::testSharedFormulaExportXLSX()
1800 : {
1801 : struct
1802 : {
1803 3 : bool checkContent( ScDocument& rDoc )
1804 : {
1805 3 : SCTAB nTabCount = rDoc.GetTableCount();
1806 3 : if (nTabCount != 2)
1807 : {
1808 0 : cerr << "Document should have exactly 2 sheets. " << nTabCount << " found." << endl;
1809 0 : return false;
1810 : }
1811 :
1812 : // Make sure the sheet tab colors are not set.
1813 9 : for (SCROW i = 0; i <= 1; ++i)
1814 : {
1815 6 : Color aTabBgColor = rDoc.GetTabBgColor(i);
1816 6 : if (aTabBgColor != Color(COL_AUTO))
1817 : {
1818 0 : cerr << "The tab color of Sheet " << (i+1) << " should not be explicitly set." << endl;
1819 0 : return false;
1820 : }
1821 : }
1822 :
1823 : // B2:B7 should show 1,2,3,4,5,6.
1824 3 : double fExpected = 1.0;
1825 21 : for (SCROW i = 1; i <= 6; ++i, ++fExpected)
1826 : {
1827 18 : ScAddress aPos(1,i,0);
1828 18 : double fVal = rDoc.GetValue(aPos);
1829 18 : if (fVal != fExpected)
1830 : {
1831 0 : cerr << "Wrong value in B" << (i+1) << ": expected=" << fExpected << ", actual=" << fVal << endl;
1832 0 : return false;
1833 : }
1834 : }
1835 :
1836 : // C2:C7 should show 10,20,....,60.
1837 3 : fExpected = 10.0;
1838 21 : for (SCROW i = 1; i <= 6; ++i, fExpected+=10.0)
1839 : {
1840 18 : ScAddress aPos(2,i,0);
1841 18 : double fVal = rDoc.GetValue(aPos);
1842 18 : if (fVal != fExpected)
1843 : {
1844 0 : cerr << "Wrong value in C" << (i+1) << ": expected=" << fExpected << ", actual=" << fVal << endl;
1845 0 : return false;
1846 : }
1847 : }
1848 :
1849 : // D2:D7 should show 1,2,...,6.
1850 3 : fExpected = 1.0;
1851 21 : for (SCROW i = 1; i <= 6; ++i, ++fExpected)
1852 : {
1853 18 : ScAddress aPos(3,i,0);
1854 18 : double fVal = rDoc.GetValue(aPos);
1855 18 : if (fVal != fExpected)
1856 : {
1857 0 : cerr << "Wrong value in D" << (i+1) << ": expected=" << fExpected << ", actual=" << fVal << endl;
1858 0 : return false;
1859 : }
1860 : }
1861 :
1862 3 : return true;
1863 : }
1864 :
1865 : } aTest;
1866 :
1867 1 : ScDocShellRef xDocSh = loadDoc("shared-formula/3d-reference.", XLSX);
1868 : {
1869 1 : CPPUNIT_ASSERT_MESSAGE("Failed to load file.", xDocSh.Is());
1870 1 : ScDocument& rDoc = xDocSh->GetDocument();
1871 :
1872 1 : bool bRes = aTest.checkContent(rDoc);
1873 1 : CPPUNIT_ASSERT_MESSAGE("Content check on the initial document failed.", bRes);
1874 :
1875 1 : rDoc.CalcAll(); // Recalculate to flush all cached results.
1876 1 : bRes = aTest.checkContent(rDoc);
1877 1 : CPPUNIT_ASSERT_MESSAGE("Content check on the initial recalculated document failed.", bRes);
1878 : }
1879 :
1880 : // Save and reload, and check the content again.
1881 2 : ScDocShellRef xDocSh2 = saveAndReload(xDocSh, XLSX);
1882 1 : xDocSh->DoClose();
1883 :
1884 1 : CPPUNIT_ASSERT_MESSAGE("Failed to load file.", xDocSh2.Is());
1885 1 : ScDocument& rDoc = xDocSh2->GetDocument();
1886 1 : rDoc.CalcAll(); // Recalculate to flush all cached results.
1887 :
1888 1 : bool bRes = aTest.checkContent(rDoc);
1889 1 : CPPUNIT_ASSERT_MESSAGE("Content check on the reloaded document failed.", bRes);
1890 :
1891 2 : xDocSh2->DoClose();
1892 1 : }
1893 :
1894 1 : void ScExportTest::testSharedFormulaStringResultExportXLSX()
1895 : {
1896 : struct
1897 : {
1898 3 : bool checkContent( ScDocument& rDoc )
1899 : {
1900 : {
1901 : // B2:B7 should show A,B,....,F.
1902 3 : const char* expected[] = { "A", "B", "C", "D", "E", "F" };
1903 21 : for (SCROW i = 0; i <= 5; ++i)
1904 : {
1905 18 : ScAddress aPos(1,i+1,0);
1906 18 : OUString aStr = rDoc.GetString(aPos);
1907 36 : OUString aExpected = OUString::createFromAscii(expected[i]);
1908 18 : if (aStr != aExpected)
1909 : {
1910 0 : cerr << "Wrong value in B" << (i+2) << ": expected='" << aExpected << "', actual='" << aStr << "'" << endl;
1911 0 : return false;
1912 : }
1913 18 : }
1914 : }
1915 :
1916 : {
1917 : // C2:C7 should show AA,BB,....,FF.
1918 3 : const char* expected[] = { "AA", "BB", "CC", "DD", "EE", "FF" };
1919 21 : for (SCROW i = 0; i <= 5; ++i)
1920 : {
1921 18 : ScAddress aPos(2,i+1,0);
1922 18 : OUString aStr = rDoc.GetString(aPos);
1923 36 : OUString aExpected = OUString::createFromAscii(expected[i]);
1924 18 : if (aStr != aExpected)
1925 : {
1926 0 : cerr << "Wrong value in C" << (i+2) << ": expected='" << aExpected << "', actual='" << aStr << "'" << endl;
1927 0 : return false;
1928 : }
1929 18 : }
1930 : }
1931 :
1932 3 : return true;
1933 : }
1934 :
1935 : } aTest;
1936 :
1937 1 : ScDocShellRef xDocSh = loadDoc("shared-formula/text-results.", XLSX);
1938 : {
1939 1 : CPPUNIT_ASSERT_MESSAGE("Failed to load file.", xDocSh.Is());
1940 1 : ScDocument& rDoc = xDocSh->GetDocument();
1941 :
1942 : // Check content without re-calculation, to test cached formula results.
1943 1 : bool bRes = aTest.checkContent(rDoc);
1944 1 : CPPUNIT_ASSERT_MESSAGE("Content check on the initial document failed.", bRes);
1945 :
1946 : // Now, re-calculate and check the results.
1947 1 : rDoc.CalcAll();
1948 1 : bRes = aTest.checkContent(rDoc);
1949 1 : CPPUNIT_ASSERT_MESSAGE("Content check on the initial recalculated document failed.", bRes);
1950 : }
1951 : // Reload and check again.
1952 2 : ScDocShellRef xDocSh2 = saveAndReload(xDocSh, XLSX);
1953 1 : xDocSh->DoClose();
1954 1 : CPPUNIT_ASSERT_MESSAGE("Failed to re-load file.", xDocSh2.Is());
1955 1 : ScDocument& rDoc = xDocSh2->GetDocument();
1956 :
1957 1 : bool bRes = aTest.checkContent(rDoc);
1958 1 : CPPUNIT_ASSERT_MESSAGE("Content check on the reloaded document failed.", bRes);
1959 :
1960 2 : xDocSh2->DoClose();
1961 1 : }
1962 :
1963 2 : void ScExportTest::testFunctionsExcel2010( sal_uLong nFormatType )
1964 : {
1965 2 : ScDocShellRef xShell = loadDoc("functions-excel-2010.", XLSX);
1966 2 : CPPUNIT_ASSERT_MESSAGE("Failed to load the document.", xShell.Is());
1967 :
1968 4 : ScDocShellRef xDocSh = saveAndReload(xShell, nFormatType);
1969 2 : ScDocument& rDoc = xDocSh->GetDocument();
1970 2 : rDoc.CalcAll(); // perform hard re-calculation.
1971 :
1972 2 : testFunctionsExcel2010_Impl(rDoc);
1973 :
1974 4 : xDocSh->DoClose();
1975 2 : }
1976 :
1977 1 : void ScExportTest::testFunctionsExcel2010XLSX()
1978 : {
1979 1 : testFunctionsExcel2010(XLSX);
1980 1 : }
1981 :
1982 1 : void ScExportTest::testFunctionsExcel2010XLS()
1983 : {
1984 1 : testFunctionsExcel2010(XLS);
1985 1 : }
1986 :
1987 1 : void ScExportTest::testRelativePaths()
1988 : {
1989 1 : ScDocShellRef xDocSh = loadDoc("fdo79305.", ODS);
1990 1 : CPPUNIT_ASSERT(xDocSh.Is());
1991 :
1992 1 : xmlDocPtr pDoc = XPathHelper::parseExport(&(*xDocSh), m_xSFactory, "content.xml", ODS);
1993 1 : CPPUNIT_ASSERT(pDoc);
1994 : OUString aURL = getXPath(pDoc,
1995 2 : "/office:document-content/office:body/office:spreadsheet/table:table/table:table-row[2]/table:table-cell[2]/text:p/text:a", "href");
1996 : // make sure that the URL is relative
1997 2 : CPPUNIT_ASSERT(aURL.startsWith(".."));
1998 1 : }
1999 :
2000 : namespace {
2001 :
2002 2 : void testSheetProtection_Impl(ScDocument& rDoc)
2003 : {
2004 2 : CPPUNIT_ASSERT(rDoc.IsTabProtected(0));
2005 2 : ScTableProtection* pTabProtection = rDoc.GetTabProtection(0);
2006 2 : CPPUNIT_ASSERT(pTabProtection);
2007 2 : CPPUNIT_ASSERT(pTabProtection->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS));
2008 2 : CPPUNIT_ASSERT(!pTabProtection->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS));
2009 2 : }
2010 :
2011 : }
2012 :
2013 1 : void ScExportTest::testSheetProtection()
2014 : {
2015 1 : ScDocShellRef xDocSh = loadDoc("sheet-protection.", ODS);
2016 1 : CPPUNIT_ASSERT(xDocSh.Is());
2017 :
2018 : {
2019 1 : ScDocument& rDoc = xDocSh->GetDocument();
2020 1 : testSheetProtection_Impl(rDoc);
2021 : }
2022 :
2023 2 : ScDocShellRef xDocSh2 = saveAndReload(xDocSh, ODS);
2024 : {
2025 1 : ScDocument& rDoc = xDocSh2->GetDocument();
2026 1 : testSheetProtection_Impl(rDoc);
2027 : }
2028 :
2029 2 : xDocSh2->DoClose();
2030 1 : }
2031 :
2032 1 : void ScExportTest::testPivotTableXLSX()
2033 : {
2034 : struct
2035 : {
2036 2 : bool check( const ScDocument& rDoc )
2037 : {
2038 2 : if (!rDoc.HasPivotTable())
2039 : {
2040 0 : cerr << "The document should have pivot table." << endl;
2041 0 : return false;
2042 : }
2043 :
2044 2 : const ScDPCollection* pDPs = rDoc.GetDPCollection();
2045 2 : if (!pDPs)
2046 : {
2047 0 : cerr << "Pivot table container should exist." << endl;
2048 0 : return false;
2049 : }
2050 :
2051 2 : ScRange aSrcRange(0,0,0,9,2,0); // A1:J3 on Sheet1.
2052 2 : const ScDPCache* pCache = pDPs->GetSheetCaches().getExistingCache(aSrcRange);
2053 2 : if (!pCache)
2054 : {
2055 0 : cerr << "The document should have a pivot cache for A1:J3 on Sheet1." << endl;
2056 0 : return false;
2057 : }
2058 :
2059 : // Cache should have fields from F1 through F10.
2060 :
2061 : const char* pNames[] = {
2062 : "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10"
2063 2 : };
2064 :
2065 2 : size_t nCount = pCache->GetFieldCount();
2066 2 : if (nCount != SAL_N_ELEMENTS(pNames))
2067 : {
2068 0 : cout << "Incorrect number of fields in pivot cache." << endl;
2069 0 : return false;
2070 : }
2071 :
2072 22 : for (size_t i = 0; i < nCount; ++i)
2073 : {
2074 20 : OUString aCacheName = pCache->GetDimensionName(i);
2075 20 : if (aCacheName != OUString::createFromAscii(pNames[i]))
2076 : {
2077 0 : cerr << "Field " << i << " has label '" << aCacheName << "' but expected '" << pNames[i] << "'" << endl;
2078 0 : return false;
2079 : }
2080 20 : }
2081 :
2082 2 : const ScDPObject* pDPObj = rDoc.GetDPAtCursor(0,10,0); // A11
2083 2 : if (!pDPObj)
2084 : {
2085 0 : cerr << "A pivot table should exist over A11." << endl;
2086 0 : return false;
2087 : }
2088 :
2089 : // Output range should be A8:D15.
2090 2 : ScRange aOutRange = pDPObj->GetOutRange();
2091 2 : if (ScRange(0,7,0,3,14,0) != aOutRange)
2092 : {
2093 0 : cerr << "Incorrect output range." << endl;
2094 0 : return false;
2095 : }
2096 :
2097 : // Row field - F1
2098 : // Column field - F4
2099 : // Page fields - F7 and F6
2100 : // Data field - F10
2101 :
2102 2 : const ScDPSaveData* pSaveData = pDPObj->GetSaveData();
2103 2 : if (!pSaveData)
2104 : {
2105 0 : cerr << "Save data should exist in each pivot table object." << endl;
2106 0 : return false;
2107 : }
2108 :
2109 2 : std::vector<const ScDPSaveDimension*> aDims;
2110 2 : pSaveData->GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_ROW, aDims);
2111 2 : if (aDims.size() != 1 || aDims[0]->GetName() != "F1")
2112 : {
2113 0 : cerr << "Pivot table should have one row field labeld 'F1'" << endl;
2114 0 : return false;
2115 : }
2116 :
2117 2 : pSaveData->GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_COLUMN, aDims);
2118 2 : if (aDims.size() != 1 || aDims[0]->GetName() != "F4")
2119 : {
2120 0 : cerr << "Pivot table should have one column field labeld 'F4'" << endl;
2121 0 : return false;
2122 : }
2123 :
2124 2 : pSaveData->GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_PAGE, aDims);
2125 2 : if (aDims.size() != 2 || aDims[0]->GetName() != "F7" || aDims[1]->GetName() != "F6")
2126 : {
2127 0 : cerr << "Pivot table should have two page fields labeld 'F7' and 'F6' in this order." << endl;
2128 0 : return false;
2129 : }
2130 :
2131 2 : pSaveData->GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_DATA, aDims);
2132 2 : if (aDims.size() != 1 || aDims[0]->GetName() != "F10")
2133 : {
2134 0 : cerr << "Pivot table should have one data field labeld 'F10'" << endl;
2135 0 : return false;
2136 : }
2137 :
2138 2 : const ScDPSaveDimension* pDim = aDims[0];
2139 2 : if (pDim->GetFunction() != sheet::GeneralFunction_SUM)
2140 : {
2141 0 : cerr << "Data field should have SUM function." << endl;
2142 0 : return false;
2143 : }
2144 :
2145 2 : return true;
2146 : }
2147 :
2148 : } aTest;
2149 :
2150 1 : ScDocShellRef xDocSh = loadDoc("pivot-table/many-fields-in-cache.", XLSX);
2151 1 : CPPUNIT_ASSERT(xDocSh.Is());
2152 1 : ScDocument* pDoc = &xDocSh->GetDocument();
2153 :
2154 : // Initial check.
2155 1 : bool bCheck = aTest.check(*pDoc);
2156 1 : CPPUNIT_ASSERT_MESSAGE("Initial check failed.", bCheck);
2157 :
2158 2 : ScDocShellRef xDocSh2 = saveAndReload(xDocSh, XLSX);
2159 1 : xDocSh->DoClose();
2160 1 : CPPUNIT_ASSERT(xDocSh2.Is());
2161 1 : pDoc = &xDocSh2->GetDocument();
2162 :
2163 : // Reload check.
2164 1 : bCheck = aTest.check(*pDoc);
2165 1 : CPPUNIT_ASSERT_MESSAGE("Reload check failed.", bCheck);
2166 :
2167 2 : xDocSh2->DoClose();
2168 1 : }
2169 :
2170 1 : void ScExportTest::testPivotTableTwoDataFieldsXLSX()
2171 : {
2172 : struct
2173 : {
2174 2 : bool check( const ScDocument& rDoc )
2175 : {
2176 2 : if (!rDoc.HasPivotTable())
2177 : {
2178 0 : cerr << "The document should have pivot table." << endl;
2179 0 : return false;
2180 : }
2181 :
2182 2 : const ScDPCollection* pDPs = rDoc.GetDPCollection();
2183 2 : if (!pDPs)
2184 : {
2185 0 : cerr << "Pivot table container should exist." << endl;
2186 0 : return false;
2187 : }
2188 :
2189 2 : ScRange aSrcRange(1,1,1,2,8,1); // B2:C9 on the 2nd sheet.
2190 2 : const ScDPCache* pCache = pDPs->GetSheetCaches().getExistingCache(aSrcRange);
2191 2 : if (!pCache)
2192 : {
2193 0 : cerr << "The document should have a pivot cache for B2:C9 on 'Src'." << endl;
2194 0 : return false;
2195 : }
2196 :
2197 2 : const char* pNames[] = { "Name", "Value" };
2198 : (void) pNames;
2199 :
2200 2 : size_t nCount = pCache->GetFieldCount();
2201 2 : if (nCount != SAL_N_ELEMENTS(pNames))
2202 : {
2203 0 : cout << "Incorrect number of fields in pivot cache." << endl;
2204 0 : return false;
2205 : }
2206 :
2207 2 : const ScDPObject* pDPObj = rDoc.GetDPAtCursor(0,2,0); // A3
2208 2 : if (!pDPObj)
2209 : {
2210 0 : cerr << "A pivot table should exist over A3." << endl;
2211 0 : return false;
2212 : }
2213 :
2214 : // Output range should be A3:C12.
2215 2 : ScRange aOutRange = pDPObj->GetOutRange();
2216 2 : if (ScRange(0,2,0,2,11,0) != aOutRange)
2217 : {
2218 0 : cerr << "Incorrect output range." << endl;
2219 0 : return false;
2220 : }
2221 :
2222 2 : const ScDPSaveData* pSaveData = pDPObj->GetSaveData();
2223 2 : if (!pSaveData)
2224 : {
2225 0 : cerr << "Save data should exist in each pivot table object." << endl;
2226 0 : return false;
2227 : }
2228 :
2229 2 : std::vector<const ScDPSaveDimension*> aDims;
2230 2 : pSaveData->GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_ROW, aDims);
2231 2 : if (aDims.size() != 1 || aDims[0]->GetName() != "Name")
2232 : {
2233 0 : cerr << "Pivot table should have one row field labeld 'Name'" << endl;
2234 0 : return false;
2235 : }
2236 :
2237 2 : pSaveData->GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_DATA, aDims);
2238 10 : if (aDims.size() != 2 ||
2239 14 : ScDPUtil::getSourceDimensionName(aDims[0]->GetName()) != "Value" ||
2240 6 : ScDPUtil::getSourceDimensionName(aDims[1]->GetName()) != "Value")
2241 : {
2242 0 : cerr << "Pivot table should have two duplicated data fields both of which are named 'Value'." << endl;
2243 0 : return false;
2244 : }
2245 :
2246 2 : if (aDims[0]->GetFunction() != sheet::GeneralFunction_SUM)
2247 : {
2248 0 : cerr << "First data field should be SUM." << endl;
2249 0 : return false;
2250 : }
2251 :
2252 2 : if (aDims[1]->GetFunction() != sheet::GeneralFunction_COUNT)
2253 : {
2254 0 : cerr << "First data field should be COUNT." << endl;
2255 0 : return false;
2256 : }
2257 :
2258 2 : pSaveData->GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_COLUMN, aDims);
2259 2 : if (aDims.size() != 1 || !aDims[0]->IsDataLayout())
2260 : {
2261 0 : cerr << "Pivot table should have one column field which is a data layout field." << endl;
2262 0 : return false;
2263 : }
2264 :
2265 2 : return true;
2266 : }
2267 :
2268 : } aTest;
2269 :
2270 1 : ScDocShellRef xDocSh = loadDoc("pivot-table/two-data-fields.", XLSX);
2271 1 : CPPUNIT_ASSERT(xDocSh.Is());
2272 1 : ScDocument* pDoc = &xDocSh->GetDocument();
2273 :
2274 : // Initial check.
2275 1 : bool bCheck = aTest.check(*pDoc);
2276 1 : CPPUNIT_ASSERT_MESSAGE("Initial check failed.", bCheck);
2277 :
2278 2 : ScDocShellRef xDocSh2 = saveAndReload(xDocSh, XLSX);
2279 1 : xDocSh->DoClose();
2280 1 : CPPUNIT_ASSERT(xDocSh2.Is());
2281 1 : pDoc = &xDocSh2->GetDocument();
2282 :
2283 : // Reload check.
2284 1 : bCheck = aTest.check(*pDoc);
2285 1 : CPPUNIT_ASSERT_MESSAGE("Reload check failed.", bCheck);
2286 :
2287 2 : xDocSh2->DoClose();
2288 1 : }
2289 :
2290 1 : void ScExportTest::testFunctionsExcel2010ODS()
2291 : {
2292 : //testFunctionsExcel2010(ODS);
2293 1 : }
2294 :
2295 1 : void ScExportTest::testSwappedOutImageExport()
2296 : {
2297 : const char* aFilterNames[] = {
2298 : "calc8",
2299 : "MS Excel 97",
2300 : "Calc Office Open XML",
2301 : "generic_HTML",
2302 1 : };
2303 :
2304 : // Set cache size to a very small value to make sure one of the images is swapped out
2305 1 : std::shared_ptr< comphelper::ConfigurationChanges > xBatch(comphelper::ConfigurationChanges::create());
2306 1 : officecfg::Office::Common::Cache::GraphicManager::TotalCacheSize::set(sal_Int32(1), xBatch);
2307 1 : xBatch->commit();
2308 :
2309 5 : for( size_t nFilter = 0; nFilter < SAL_N_ELEMENTS(aFilterNames); ++nFilter )
2310 : {
2311 : // Check whether the export code swaps in the image which was swapped out before.
2312 4 : ScDocShellRef xDocSh = loadDoc("document_with_two_images.", ODS);
2313 :
2314 8 : const OString sFailedMessage = OString("Failed on filter: ") + aFilterNames[nFilter];
2315 4 : CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xDocSh.Is());
2316 :
2317 : // Export the document and import again for a check
2318 8 : ScDocShellRef xDocSh2 = saveAndReload(xDocSh, nFilter);
2319 4 : xDocSh->DoClose();
2320 :
2321 : // Check whether graphic exported well after it was swapped out
2322 8 : uno::Reference< frame::XModel > xModel = xDocSh2->GetModel();
2323 8 : uno::Reference< sheet::XSpreadsheetDocument > xDoc(xModel, UNO_QUERY_THROW);
2324 8 : uno::Reference< container::XIndexAccess > xIA(xDoc->getSheets(), UNO_QUERY_THROW);
2325 8 : uno::Reference< drawing::XDrawPageSupplier > xDrawPageSupplier( xIA->getByIndex(0), UNO_QUERY_THROW);
2326 8 : uno::Reference< container::XIndexAccess > xDraws(xDrawPageSupplier->getDrawPage(), UNO_QUERY_THROW);
2327 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(2), xDraws->getCount());
2328 :
2329 8 : uno::Reference<drawing::XShape> xImage(xDraws->getByIndex(0), uno::UNO_QUERY);
2330 8 : uno::Reference< beans::XPropertySet > XPropSet( xImage, uno::UNO_QUERY_THROW );
2331 : // Check URL
2332 : {
2333 4 : OUString sURL;
2334 4 : XPropSet->getPropertyValue("GraphicURL") >>= sURL;
2335 4 : CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), sURL != "vnd.sun.star.GraphicObject:00000000000000000000000000000000");
2336 : }
2337 : // Check size
2338 : {
2339 4 : uno::Reference<graphic::XGraphic> xGraphic;
2340 4 : XPropSet->getPropertyValue("Graphic") >>= xGraphic;
2341 8 : uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
2342 4 : CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xBitmap.is());
2343 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(610), xBitmap->getSize().Width );
2344 8 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(381), xBitmap->getSize().Height );
2345 : }
2346 : // Second Image
2347 4 : xImage.set(xDraws->getByIndex(1), uno::UNO_QUERY);
2348 4 : XPropSet.set( xImage, uno::UNO_QUERY_THROW );
2349 : // Check URL
2350 : {
2351 4 : OUString sURL;
2352 4 : XPropSet->getPropertyValue("GraphicURL") >>= sURL;
2353 4 : CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), sURL != "vnd.sun.star.GraphicObject:00000000000000000000000000000000");
2354 : }
2355 : // Check size
2356 : {
2357 4 : uno::Reference<graphic::XGraphic> xGraphic;
2358 4 : XPropSet->getPropertyValue("Graphic") >>= xGraphic;
2359 8 : uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
2360 4 : CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xBitmap.is());
2361 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(900), xBitmap->getSize().Width );
2362 8 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(600), xBitmap->getSize().Height );
2363 : }
2364 4 : xDocSh2->DoClose();
2365 5 : }
2366 1 : }
2367 :
2368 48 : ScExportTest::ScExportTest()
2369 48 : : ScBootstrapFixture("/sc/qa/unit/data")
2370 : {
2371 48 : }
2372 :
2373 48 : void ScExportTest::setUp()
2374 : {
2375 48 : test::BootstrapFixture::setUp();
2376 :
2377 : // This is a bit of a fudge, we do this to ensure that ScGlobals::ensure,
2378 : // which is a private symbol to us, gets called
2379 96 : m_xCalcComponent =
2380 144 : getMultiServiceFactory()->createInstance("com.sun.star.comp.Calc.SpreadsheetDocument");
2381 48 : CPPUNIT_ASSERT_MESSAGE("no calc component!", m_xCalcComponent.is());
2382 48 : }
2383 :
2384 48 : void ScExportTest::tearDown()
2385 : {
2386 48 : uno::Reference< lang::XComponent >( m_xCalcComponent, UNO_QUERY_THROW )->dispose();
2387 48 : test::BootstrapFixture::tearDown();
2388 48 : }
2389 :
2390 1 : void ScExportTest::testSupBookVirtualPath()
2391 : {
2392 1 : ScDocShellRef xShell = loadDoc("external-ref.", XLS);
2393 1 : CPPUNIT_ASSERT(xShell.Is());
2394 :
2395 2 : ScDocShellRef xDocSh = saveAndReload(xShell, XLS);
2396 1 : xShell->DoClose();
2397 1 : CPPUNIT_ASSERT(xDocSh.Is());
2398 :
2399 1 : ScDocument& rDoc = xDocSh->GetDocument();
2400 :
2401 1 : if (!checkFormula(rDoc, ScAddress(0,0,0), "'file:///home/timar/Documents/external.xls'#$Sheet1.A1"))
2402 0 : CPPUNIT_FAIL("Wrong SupBook VirtualPath URL");
2403 :
2404 2 : xDocSh->DoClose();
2405 1 : }
2406 :
2407 1 : void ScExportTest::testLinkedGraphicRT()
2408 : {
2409 : // Problem was with linked images
2410 : const char* aFilterNames[] = {
2411 : "calc8",
2412 : "MS Excel 97",
2413 : "Calc Office Open XML",
2414 : "generic_HTML",
2415 1 : };
2416 :
2417 5 : for( size_t nFilter = 0; nFilter < SAL_N_ELEMENTS(aFilterNames); ++nFilter )
2418 : {
2419 : // Load the original file with one image
2420 4 : ScDocShellRef xDocSh = loadDoc("document_with_linked_graphic.", ODS);
2421 8 : const OString sFailedMessage = OString("Failed on filter: ") + aFilterNames[nFilter];
2422 :
2423 : // Export the document and import again for a check
2424 8 : ScDocShellRef xDocSh2 = saveAndReload(xDocSh, nFilter);
2425 4 : xDocSh->DoClose();
2426 :
2427 : // Check whether graphic imported well after export
2428 4 : ScDocument& rDoc = xDocSh->GetDocument();
2429 4 : ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
2430 4 : CPPUNIT_ASSERT_MESSAGE( sFailedMessage.getStr(), pDrawLayer != NULL );
2431 4 : const SdrPage *pPage = pDrawLayer->GetPage(0);
2432 4 : CPPUNIT_ASSERT_MESSAGE( sFailedMessage.getStr(), pPage != NULL );
2433 4 : SdrGrafObj* pObject = dynamic_cast<SdrGrafObj*>(pPage->GetObj(0));
2434 4 : CPPUNIT_ASSERT_MESSAGE( sFailedMessage.getStr(), pObject != NULL );
2435 4 : CPPUNIT_ASSERT_MESSAGE( sFailedMessage.getStr(), pObject->IsLinkedGraphic() );
2436 :
2437 4 : const GraphicObject& rGraphicObj = pObject->GetGraphicObject(true);
2438 4 : CPPUNIT_ASSERT_MESSAGE( sFailedMessage.getStr(), !rGraphicObj.IsSwappedOut());
2439 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE( sFailedMessage.getStr(), GRAPHIC_BITMAP, rGraphicObj.GetGraphic().GetType());
2440 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE( sFailedMessage.getStr(), sal_uLong(864900), rGraphicObj.GetSizeBytes());
2441 :
2442 4 : xDocSh2->DoClose();
2443 4 : }
2444 1 : }
2445 :
2446 1 : void ScExportTest::testImageWithSpecialID()
2447 : {
2448 : const char* aFilterNames[] = {
2449 : "calc8",
2450 : "MS Excel 97",
2451 : "Calc Office Open XML",
2452 : "generic_HTML",
2453 1 : };
2454 :
2455 : // Trigger swap out mechanism to test swapped state factor too.
2456 1 : std::shared_ptr< comphelper::ConfigurationChanges > batch(comphelper::ConfigurationChanges::create());
2457 1 : officecfg::Office::Common::Cache::GraphicManager::TotalCacheSize::set(sal_Int32(1), batch);
2458 1 : batch->commit();
2459 :
2460 5 : for( size_t nFilter = 0; nFilter < SAL_N_ELEMENTS(aFilterNames); ++nFilter )
2461 : {
2462 4 : ScDocShellRef xDocSh = loadDoc("images_with_special_IDs.", ODS);
2463 :
2464 8 : const OString sFailedMessage = OString("Failed on filter: ") + aFilterNames[nFilter];
2465 4 : CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xDocSh.Is());
2466 :
2467 : // Export the document and import again for a check
2468 8 : ScDocShellRef xDocSh2 = saveAndReload(xDocSh, nFilter);
2469 4 : xDocSh->DoClose();
2470 :
2471 : // Check whether graphic was exported well
2472 8 : uno::Reference< frame::XModel > xModel = xDocSh2->GetModel();
2473 8 : uno::Reference< sheet::XSpreadsheetDocument > xDoc(xModel, UNO_QUERY_THROW);
2474 8 : uno::Reference< container::XIndexAccess > xIA(xDoc->getSheets(), UNO_QUERY_THROW);
2475 8 : uno::Reference< drawing::XDrawPageSupplier > xDrawPageSupplier( xIA->getByIndex(0), UNO_QUERY_THROW);
2476 8 : uno::Reference< container::XIndexAccess > xDraws(xDrawPageSupplier->getDrawPage(), UNO_QUERY_THROW);
2477 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(2), xDraws->getCount());
2478 :
2479 8 : uno::Reference<drawing::XShape> xImage(xDraws->getByIndex(0), uno::UNO_QUERY);
2480 8 : uno::Reference< beans::XPropertySet > XPropSet( xImage, uno::UNO_QUERY_THROW );
2481 : // Check URL
2482 : {
2483 4 : OUString sURL;
2484 4 : XPropSet->getPropertyValue("GraphicURL") >>= sURL;
2485 4 : CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), sURL != "vnd.sun.star.GraphicObject:00000000000000000000000000000000");
2486 : }
2487 : // Check size
2488 : {
2489 4 : uno::Reference<graphic::XGraphic> xGraphic;
2490 4 : XPropSet->getPropertyValue("Graphic") >>= xGraphic;
2491 8 : uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
2492 4 : CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xBitmap.is());
2493 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(610), xBitmap->getSize().Width );
2494 8 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(381), xBitmap->getSize().Height );
2495 : }
2496 : // Second Image
2497 4 : xImage.set(xDraws->getByIndex(1), uno::UNO_QUERY);
2498 4 : XPropSet.set( xImage, uno::UNO_QUERY_THROW );
2499 : // Check URL
2500 : {
2501 4 : OUString sURL;
2502 4 : XPropSet->getPropertyValue("GraphicURL") >>= sURL;
2503 4 : CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), sURL != "vnd.sun.star.GraphicObject:00000000000000000000000000000000");
2504 : }
2505 : // Check size
2506 : {
2507 4 : uno::Reference<graphic::XGraphic> xGraphic;
2508 4 : XPropSet->getPropertyValue("Graphic") >>= xGraphic;
2509 8 : uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
2510 4 : CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xBitmap.is());
2511 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(900), xBitmap->getSize().Width );
2512 8 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(600), xBitmap->getSize().Height );
2513 : }
2514 4 : xDocSh2->DoClose();
2515 5 : }
2516 1 : }
2517 :
2518 1 : void ScExportTest::testSheetLocalRangeNameXLS()
2519 : {
2520 1 : ScDocShellRef xDocSh = loadDoc("named-ranges-local.", XLS);
2521 1 : xDocSh->DoHardRecalc(true);
2522 2 : ScDocShellRef xDocSh2 = saveAndReload(xDocSh, XLS);
2523 1 : xDocSh->DoClose();
2524 1 : xDocSh2->DoHardRecalc(true);
2525 :
2526 1 : ScDocument& rDoc = xDocSh2->GetDocument();
2527 1 : ScRangeName* pRangeName = rDoc.GetRangeName(0);
2528 1 : CPPUNIT_ASSERT(pRangeName);
2529 1 : CPPUNIT_ASSERT_EQUAL(size_t(2), pRangeName->size());
2530 :
2531 2 : OUString aFormula;
2532 1 : rDoc.GetFormula(3, 11, 0, aFormula);
2533 1 : CPPUNIT_ASSERT_EQUAL(OUString("=SUM(local_name2)"), aFormula);
2534 1 : ASSERT_DOUBLES_EQUAL(14.0, rDoc.GetValue(3, 11, 0));
2535 :
2536 1 : rDoc.GetFormula(6, 4, 0, aFormula);
2537 1 : CPPUNIT_ASSERT_EQUAL(OUString("=local_name1"), aFormula);
2538 :
2539 2 : xDocSh2->DoClose();
2540 1 : }
2541 :
2542 1 : void ScExportTest::testSheetTextBoxHyperlink()
2543 : {
2544 1 : ScDocShellRef xShell = loadDoc("textbox-hyperlink.", XLSX);
2545 1 : CPPUNIT_ASSERT(xShell.Is());
2546 :
2547 2 : ScDocShellRef xDocSh = saveAndReload(&(*xShell), XLSX);
2548 1 : CPPUNIT_ASSERT(xDocSh.Is());
2549 :
2550 1 : xmlDocPtr pDoc = XPathHelper::parseExport(&(*xDocSh), m_xSFactory, "xl/drawings/drawing1.xml", XLSX);
2551 1 : CPPUNIT_ASSERT(pDoc);
2552 :
2553 1 : assertXPath(pDoc, "/xdr:wsDr[1]/xdr:twoCellAnchor[1]/xdr:sp[1]/xdr:nvSpPr[1]/xdr:cNvPr[1]/a:hlinkClick[1]", 1);
2554 :
2555 2 : xDocSh->DoClose();
2556 1 : }
2557 :
2558 1 : void ScExportTest::testFontSize()
2559 : {
2560 1 : ScDocShellRef xDocSh = loadDoc("fontSize.", XLSX);
2561 1 : CPPUNIT_ASSERT(xDocSh.Is());
2562 :
2563 1 : xmlDocPtr pDoc = XPathHelper::parseExport(&(*xDocSh), m_xSFactory, "xl/drawings/drawing1.xml", XLSX);
2564 1 : CPPUNIT_ASSERT(pDoc);
2565 : OUString fontSize = getXPath(pDoc,
2566 2 : "/xdr:wsDr/xdr:twoCellAnchor/xdr:sp[1]/xdr:txBody/a:p[1]/a:r[1]/a:rPr", "sz");
2567 : // make sure that the font size is 18
2568 2 : CPPUNIT_ASSERT_EQUAL(OUString("1800"), fontSize);
2569 1 : }
2570 :
2571 1 : void ScExportTest::testSheetCharacterKerningSpace()
2572 : {
2573 1 : ScDocShellRef xShell = loadDoc("textbox-CharKerningSpace.", XLSX);
2574 1 : CPPUNIT_ASSERT(xShell.Is());
2575 :
2576 2 : ScDocShellRef xDocSh = saveAndReload(&(*xShell), XLSX);
2577 1 : CPPUNIT_ASSERT(xDocSh.Is());
2578 :
2579 1 : xmlDocPtr pDoc = XPathHelper::parseExport(&(*xDocSh), m_xSFactory, "xl/drawings/drawing1.xml", XLSX);
2580 1 : CPPUNIT_ASSERT(pDoc);
2581 :
2582 : OUString CharKerningSpace = getXPath(pDoc,
2583 2 : "/xdr:wsDr[1]/xdr:twoCellAnchor[1]/xdr:sp[1]/xdr:txBody[1]/a:p[1]/a:r[1]/a:rPr[1]","spc");
2584 :
2585 : // make sure that the CharKerning is 1997.
2586 1 : CPPUNIT_ASSERT_EQUAL(OUString("1997"), CharKerningSpace);
2587 :
2588 2 : xDocSh->DoClose();
2589 1 : }
2590 :
2591 1 : void ScExportTest::testSheetCondensedCharacterSpace()
2592 : {
2593 1 : ScDocShellRef xShell = loadDoc("textbox-CondensedCharacterSpace.", XLSX);
2594 1 : CPPUNIT_ASSERT(xShell.Is());
2595 :
2596 2 : ScDocShellRef xDocSh = saveAndReload(&(*xShell), XLSX);
2597 1 : CPPUNIT_ASSERT(xDocSh.Is());
2598 :
2599 1 : xmlDocPtr pDoc = XPathHelper::parseExport(&(*xDocSh), m_xSFactory, "xl/drawings/drawing1.xml", XLSX);
2600 1 : CPPUNIT_ASSERT(pDoc);
2601 :
2602 : OUString CondensedCharSpace = getXPath(pDoc,
2603 2 : "/xdr:wsDr[1]/xdr:twoCellAnchor[1]/xdr:sp[1]/xdr:txBody[1]/a:p[1]/a:r[1]/a:rPr[1]","spc");
2604 :
2605 : // make sure that the CondensedCharSpace is -996.
2606 1 : CPPUNIT_ASSERT_EQUAL(OUString("-996"), CondensedCharSpace);
2607 :
2608 2 : xDocSh->DoClose();
2609 1 : }
2610 :
2611 1 : void ScExportTest::testTextUnderlineColor()
2612 : {
2613 :
2614 1 : ScDocShellRef xDocSh = loadDoc("underlineColor.", XLSX);
2615 1 : CPPUNIT_ASSERT(xDocSh.Is());
2616 :
2617 1 : xmlDocPtr pDoc = XPathHelper::parseExport(&(*xDocSh), m_xSFactory, "xl/drawings/drawing1.xml", XLSX);
2618 1 : CPPUNIT_ASSERT(pDoc);
2619 : OUString color = getXPath(pDoc,
2620 2 : "/xdr:wsDr/xdr:twoCellAnchor/xdr:sp[1]/xdr:txBody/a:p[1]/a:r[1]/a:rPr/a:uFill/a:solidFill/a:srgbClr", "val");
2621 : // make sure that the underline color is RED
2622 2 : CPPUNIT_ASSERT_EQUAL(OUString("ff0000"), color);
2623 1 : }
2624 :
2625 1 : void ScExportTest::testSheetRunParagraphProperty()
2626 : {
2627 1 : ScDocShellRef xShell = loadDoc("TextColor.", XLSX);
2628 1 : CPPUNIT_ASSERT(xShell.Is());
2629 :
2630 2 : ScDocShellRef xDocSh = saveAndReload(&(*xShell), XLSX);
2631 1 : CPPUNIT_ASSERT(xDocSh.Is());
2632 :
2633 1 : xmlDocPtr pDoc = XPathHelper::parseExport(&(*xDocSh), m_xSFactory, "xl/sharedStrings.xml", XLSX);
2634 1 : CPPUNIT_ASSERT(pDoc);
2635 :
2636 1 : assertXPath(pDoc, "/x:sst/x:si/x:r[1]/x:rPr[1]", 1);
2637 :
2638 2 : xDocSh->DoClose();
2639 1 : }
2640 :
2641 1 : void ScExportTest::testHiddenShape()
2642 : {
2643 1 : ScDocShellRef xDocSh = loadDoc("hiddenShape.", XLSX);
2644 1 : CPPUNIT_ASSERT(xDocSh.Is());
2645 :
2646 1 : xmlDocPtr pDoc = XPathHelper::parseExport(&(*xDocSh), m_xSFactory, "xl/drawings/drawing1.xml", XLSX);
2647 1 : CPPUNIT_ASSERT(pDoc);
2648 1 : assertXPath(pDoc, "/xdr:wsDr/xdr:twoCellAnchor/xdr:sp[1]/xdr:nvSpPr/xdr:cNvPr", "hidden", "1");
2649 1 : }
2650 :
2651 1 : void ScExportTest::testHyperlinkXLSX()
2652 : {
2653 1 : ScDocShellRef xDocSh = loadDoc("hyperlink.", XLSX);
2654 1 : CPPUNIT_ASSERT(xDocSh.Is());
2655 :
2656 1 : xmlDocPtr pDoc = XPathHelper::parseExport(&(*xDocSh), m_xSFactory, "xl/drawings/_rels/drawing1.xml.rels", XLSX);
2657 1 : CPPUNIT_ASSERT(pDoc);
2658 1 : assertXPath(pDoc, "/r:Relationships/r:Relationship", "Target", "#Sheet2!A1");
2659 1 : }
2660 :
2661 1 : void ScExportTest::testMoveCellAnchoredShapes()
2662 : {
2663 1 : ScDocShellRef xDocSh = loadDoc("move-cell-anchored-shapes.", ODS);
2664 1 : CPPUNIT_ASSERT_MESSAGE("Failed to load move-cell-anchored-shapes.ods", xDocSh.Is());
2665 :
2666 : // There are two cell-anchored objects on the first sheet.
2667 1 : ScDocument& rDoc = xDocSh->GetDocument();
2668 :
2669 1 : CPPUNIT_ASSERT_MESSAGE("There should be at least one sheet.", rDoc.GetTableCount() > 0);
2670 :
2671 1 : ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
2672 1 : SdrPage* pPage = pDrawLayer->GetPage(0);
2673 1 : CPPUNIT_ASSERT_MESSAGE("draw page for sheet 1 should exist.", pPage);
2674 1 : SdrObject* pObj = pPage->GetObj(0);
2675 1 : CPPUNIT_ASSERT_MESSAGE("Failed to get drawing object.", pObj);
2676 :
2677 : // Check cell anchor state
2678 1 : ScAnchorType oldType = ScDrawLayer::GetAnchorType(*pObj);
2679 1 : CPPUNIT_ASSERT_MESSAGE( "Failed to get anchor type", oldType == SCA_CELL );
2680 :
2681 : // Get anchor data
2682 1 : ScDrawObjData* pData = ScDrawLayer::GetObjData(pObj, false);
2683 1 : CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData);
2684 1 : CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData->maLastRect.IsEmpty());
2685 :
2686 1 : ScAddress aDataStart = pData->maStart;
2687 1 : ScAddress aDataEnd = pData->maEnd;
2688 :
2689 : // Get non rotated anchor data
2690 1 : ScDrawObjData* pNData = ScDrawLayer::GetNonRotatedObjData( pObj );
2691 1 : CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData);
2692 1 : CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData->maLastRect.IsEmpty());
2693 :
2694 1 : ScAddress aNDataStart = pNData->maStart;
2695 1 : ScAddress aNDataEnd = pNData->maEnd;
2696 1 : CPPUNIT_ASSERT_EQUAL(aDataStart, aNDataStart);
2697 1 : CPPUNIT_ASSERT_EQUAL(aDataEnd , aNDataEnd);
2698 :
2699 : // Insert 2 rows.
2700 1 : rDoc.InsertRow(ScRange( 0, aDataStart.Row() - 1, 0, MAXCOL, aDataStart.Row(), 0));
2701 :
2702 : // Get anchor data
2703 1 : pData = ScDrawLayer::GetObjData(pObj, false);
2704 1 : CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData);
2705 1 : CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData->maLastRect.IsEmpty());
2706 :
2707 : // Get non rotated anchor data
2708 1 : pNData = ScDrawLayer::GetNonRotatedObjData( pObj );
2709 1 : CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData);
2710 1 : CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData->maLastRect.IsEmpty());
2711 :
2712 : // Check if data has moved to new rows
2713 1 : CPPUNIT_ASSERT_EQUAL( pData->maStart.Row(), aDataStart.Row() + 2 );
2714 1 : CPPUNIT_ASSERT_EQUAL( pData->maEnd.Row(), aDataEnd.Row() + 2 );
2715 :
2716 1 : CPPUNIT_ASSERT_EQUAL( pNData->maStart.Row(), aNDataStart.Row() + 2 );
2717 1 : CPPUNIT_ASSERT_EQUAL( pNData->maEnd.Row(), aNDataEnd.Row() + 2 );
2718 :
2719 : // Save the anchor data
2720 1 : aDataStart = pData->maStart;
2721 1 : aDataEnd = pData->maEnd;
2722 1 : aNDataStart = pNData->maStart;
2723 1 : aNDataEnd = pNData->maEnd;
2724 :
2725 : // Save the document and load again to check anchor persist
2726 2 : ScDocShellRef xDocSh1 = saveAndReload(&(*xDocSh), ODS);
2727 :
2728 : // There are two cell-anchored objects on the first sheet.
2729 1 : ScDocument& rDoc1 = xDocSh1->GetDocument();
2730 :
2731 1 : CPPUNIT_ASSERT_MESSAGE("There should be at least one sheet.", rDoc1.GetTableCount() > 0);
2732 :
2733 1 : pDrawLayer = rDoc1.GetDrawLayer();
2734 1 : pPage = pDrawLayer->GetPage(0);
2735 1 : CPPUNIT_ASSERT_MESSAGE("draw page for sheet 1 should exist.", pPage);
2736 1 : pObj = pPage->GetObj(0);
2737 1 : CPPUNIT_ASSERT_MESSAGE("Failed to get drawing object.", pObj);
2738 :
2739 : // Check cell anchor state
2740 1 : oldType = ScDrawLayer::GetAnchorType(*pObj);
2741 1 : CPPUNIT_ASSERT_MESSAGE( "Failed to get anchor type", oldType == SCA_CELL );
2742 :
2743 : // Get anchor data
2744 1 : pData = ScDrawLayer::GetObjData(pObj, false);
2745 1 : CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData);
2746 1 : CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData->maLastRect.IsEmpty());
2747 :
2748 : // Get non rotated anchor data
2749 1 : pNData = ScDrawLayer::GetNonRotatedObjData( pObj );
2750 1 : CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData);
2751 1 : CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData->maLastRect.IsEmpty());
2752 :
2753 : // Check if data after save it
2754 1 : CPPUNIT_ASSERT_EQUAL(pData->maStart, aDataStart);
2755 1 : CPPUNIT_ASSERT_EQUAL(pData->maEnd , aDataEnd);
2756 :
2757 1 : CPPUNIT_ASSERT_EQUAL(pNData->maStart, aNDataStart);
2758 1 : CPPUNIT_ASSERT_EQUAL(pNData->maEnd , aNDataEnd);
2759 :
2760 : // Insert a column.
2761 1 : rDoc1.InsertCol(ScRange( aDataStart.Col(), 0 , 0 , aDataStart.Col(), MAXROW, 0 ));
2762 :
2763 : // Get anchor data
2764 1 : pData = ScDrawLayer::GetObjData(pObj, false);
2765 1 : CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData);
2766 1 : CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData->maLastRect.IsEmpty());
2767 :
2768 : // Get non rotated anchor data
2769 1 : pNData = ScDrawLayer::GetNonRotatedObjData( pObj );
2770 1 : CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData);
2771 1 : CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData->maLastRect.IsEmpty());
2772 :
2773 : // Check if data has moved to new rows
2774 1 : CPPUNIT_ASSERT_EQUAL(pData->maStart.Col(), SCCOL(aDataStart.Col() + 1));
2775 1 : CPPUNIT_ASSERT_EQUAL(pData->maEnd.Col() , SCCOL(aDataEnd.Col() + 1));
2776 :
2777 1 : CPPUNIT_ASSERT_EQUAL(pNData->maStart.Col(), SCCOL(aNDataStart.Col() + 1));
2778 1 : CPPUNIT_ASSERT_EQUAL(pNData->maEnd.Col() , SCCOL(aNDataEnd.Col() + 1));
2779 :
2780 : // Save the anchor data
2781 1 : aDataStart = pData->maStart;
2782 1 : aDataEnd = pData->maEnd;
2783 1 : aNDataStart = pNData->maStart;
2784 1 : aNDataEnd = pNData->maEnd;
2785 :
2786 : // Save the document and load again to check anchor persist
2787 2 : ScDocShellRef xDocSh2 = saveAndReload(&(*xDocSh1), ODS);
2788 :
2789 : // There are two cell-anchored objects on the first sheet.
2790 1 : ScDocument& rDoc2 = xDocSh2->GetDocument();
2791 :
2792 1 : CPPUNIT_ASSERT_MESSAGE("There should be at least one sheet.", rDoc2.GetTableCount() > 0);
2793 :
2794 1 : pDrawLayer = rDoc2.GetDrawLayer();
2795 1 : pPage = pDrawLayer->GetPage(0);
2796 1 : CPPUNIT_ASSERT_MESSAGE("draw page for sheet 1 should exist.", pPage);
2797 1 : pObj = pPage->GetObj(0);
2798 1 : CPPUNIT_ASSERT_MESSAGE("Failed to get drawing object.", pObj);
2799 :
2800 : // Check cell anchor state
2801 1 : oldType = ScDrawLayer::GetAnchorType(*pObj);
2802 1 : CPPUNIT_ASSERT_MESSAGE( "Failed to get anchor type", oldType == SCA_CELL );
2803 :
2804 : // Get anchor data
2805 1 : pData = ScDrawLayer::GetObjData(pObj, false);
2806 1 : CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData);
2807 1 : CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData->maLastRect.IsEmpty());
2808 :
2809 : // Get non rotated anchor data
2810 1 : pNData = ScDrawLayer::GetNonRotatedObjData( pObj );
2811 1 : CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData);
2812 1 : CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData->maLastRect.IsEmpty());
2813 :
2814 : // Check if data after save it
2815 1 : CPPUNIT_ASSERT_EQUAL(pData->maStart, aDataStart);
2816 1 : CPPUNIT_ASSERT_EQUAL(pData->maEnd , aDataEnd);
2817 :
2818 1 : CPPUNIT_ASSERT_EQUAL(pNData->maStart, aNDataStart);
2819 1 : CPPUNIT_ASSERT_EQUAL(pNData->maEnd , aNDataEnd);
2820 :
2821 2 : xDocSh2->DoClose();
2822 1 : }
2823 :
2824 1 : CPPUNIT_TEST_SUITE_REGISTRATION(ScExportTest);
2825 :
2826 4 : CPPUNIT_PLUGIN_IMPLEMENT();
2827 :
2828 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|