LCOV - code coverage report
Current view: top level - sc/qa/unit - subsequent_export-test.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 1022 1224 83.5 %
Date: 2014-11-03 Functions: 76 78 97.4 %
Legend: Lines: hit not hit

          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 <sal/config.h>
      11             : #include <rtl/strbuf.hxx>
      12             : #include <osl/file.hxx>
      13             : 
      14             : #include <sfx2/app.hxx>
      15             : #include <sfx2/docfile.hxx>
      16             : #include <sfx2/frame.hxx>
      17             : #include <sfx2/sfxmodelfactory.hxx>
      18             : #include <svl/stritem.hxx>
      19             : 
      20             : #include "helper/qahelper.hxx"
      21             : #include "helper/xpath.hxx"
      22             : #include "helper/shared_test_impl.hxx"
      23             : 
      24             : #include "docsh.hxx"
      25             : #include "patattr.hxx"
      26             : #include "scitems.hxx"
      27             : #include "document.hxx"
      28             : #include "cellform.hxx"
      29             : #include "formulacell.hxx"
      30             : #include "tokenarray.hxx"
      31             : #include "editutil.hxx"
      32             : #include "scopetools.hxx"
      33             : #include "cellvalue.hxx"
      34             : #include "docfunc.hxx"
      35             : #include <postit.hxx>
      36             : #include <tokenstringcontext.hxx>
      37             : #include <chgtrack.hxx>
      38             : #include <dpcache.hxx>
      39             : #include <dpobject.hxx>
      40             : #include <dpsave.hxx>
      41             : #include <dputil.hxx>
      42             : 
      43             : #include <svx/svdoole2.hxx>
      44             : #include "tabprotection.hxx"
      45             : #include <editeng/wghtitem.hxx>
      46             : #include <editeng/postitem.hxx>
      47             : #include <editeng/editdata.hxx>
      48             : #include <editeng/eeitem.hxx>
      49             : #include <editeng/editobj.hxx>
      50             : #include <editeng/section.hxx>
      51             : #include <editeng/crossedoutitem.hxx>
      52             : #include <editeng/borderline.hxx>
      53             : #include <editeng/fontitem.hxx>
      54             : #include <editeng/udlnitem.hxx>
      55             : #include <formula/grammar.hxx>
      56             : #include <unotools/useroptions.hxx>
      57             : #include <tools/datetime.hxx>
      58             : 
      59             : #include <test/xmltesttools.hxx>
      60             : 
      61             : #include <com/sun/star/table/BorderLineStyle.hpp>
      62             : #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
      63             : #include <com/sun/star/sheet/GeneralFunction.hpp>
      64             : 
      65             : using namespace ::com::sun::star;
      66             : using namespace ::com::sun::star::uno;
      67             : 
      68         140 : class ScExportTest : public ScBootstrapFixture, XmlTestTools
      69             : {
      70             : protected:
      71             :     virtual void registerNamespaces(xmlXPathContextPtr& pXmlXPathCtx) SAL_OVERRIDE;
      72             : public:
      73             :     ScExportTest();
      74             : 
      75             :     virtual void setUp() SAL_OVERRIDE;
      76             :     virtual void tearDown() SAL_OVERRIDE;
      77             : 
      78             : #if !defined MACOSX && !defined DRAGONFLY
      79             :     ScDocShellRef saveAndReloadPassword( ScDocShell*, const OUString&, const OUString&, const OUString&, sal_uLong );
      80             : #endif
      81             : 
      82             :     void test();
      83             : #if !defined MACOSX && !defined DRAGONFLY
      84             :     void testPasswordExport();
      85             : #endif
      86             :     void testConditionalFormatExportODS();
      87             :     void testConditionalFormatExportXLSX();
      88             :     void testColorScaleExportODS();
      89             :     void testColorScaleExportXLSX();
      90             :     void testDataBarExportODS();
      91             :     void testDataBarExportXLSX();
      92             :     void testMiscRowHeightExport();
      93             :     void testNamedRangeBugfdo62729();
      94             :     void testRichTextExportODS();
      95             :     void testFormulaRefSheetNameODS();
      96             : 
      97             :     void testCellValuesExportODS();
      98             :     void testCellNoteExportODS();
      99             :     void testCellNoteExportXLS();
     100             :     void testFormatExportODS();
     101             : 
     102             :     void testInlineArrayXLS();
     103             :     void testEmbeddedChartXLS();
     104             :     void testFormulaReferenceXLS();
     105             :     void testSheetProtectionXLSX();
     106             : 
     107             :     void testCellBordersXLS();
     108             :     void testCellBordersXLSX();
     109             :     void testTrackChangesSimpleXLSX();
     110             :     void testSheetTabColorsXLSX();
     111             : 
     112             :     void testSharedFormulaExportXLS();
     113             :     void testSharedFormulaExportXLSX();
     114             :     void testSharedFormulaStringResultExportXLSX();
     115             : 
     116             :     void testFunctionsExcel2010( sal_uLong nFormatType );
     117             :     void testFunctionsExcel2010XLSX();
     118             :     void testFunctionsExcel2010XLS();
     119             :     void testFunctionsExcel2010ODS();
     120             : 
     121             :     void testRelativePaths();
     122             :     void testSheetProtection();
     123             : 
     124             :     void testPivotTableXLSX();
     125             :     void testPivotTableTwoDataFieldsXLSX();
     126             : 
     127             :     void testSupBookVirtualPath();
     128             : 
     129           4 :     CPPUNIT_TEST_SUITE(ScExportTest);
     130           2 :     CPPUNIT_TEST(test);
     131             : #if !defined(MACOSX) && !defined(DRAGONFLY)
     132           2 :     CPPUNIT_TEST(testPasswordExport);
     133             : #endif
     134           2 :     CPPUNIT_TEST(testConditionalFormatExportODS);
     135           2 :     CPPUNIT_TEST(testConditionalFormatExportXLSX);
     136           2 :     CPPUNIT_TEST(testColorScaleExportODS);
     137           2 :     CPPUNIT_TEST(testColorScaleExportXLSX);
     138           2 :     CPPUNIT_TEST(testDataBarExportODS);
     139           2 :     CPPUNIT_TEST(testDataBarExportXLSX);
     140           2 :     CPPUNIT_TEST(testMiscRowHeightExport);
     141           2 :     CPPUNIT_TEST(testNamedRangeBugfdo62729);
     142           2 :     CPPUNIT_TEST(testRichTextExportODS);
     143           2 :     CPPUNIT_TEST(testFormulaRefSheetNameODS);
     144           2 :     CPPUNIT_TEST(testCellValuesExportODS);
     145           2 :     CPPUNIT_TEST(testCellNoteExportODS);
     146           2 :     CPPUNIT_TEST(testCellNoteExportXLS);
     147           2 :     CPPUNIT_TEST(testFormatExportODS);
     148           2 :     CPPUNIT_TEST(testInlineArrayXLS);
     149           2 :     CPPUNIT_TEST(testEmbeddedChartXLS);
     150           2 :     CPPUNIT_TEST(testFormulaReferenceXLS);
     151           2 :     CPPUNIT_TEST(testSheetProtectionXLSX);
     152           2 :     CPPUNIT_TEST(testCellBordersXLS);
     153           2 :     CPPUNIT_TEST(testCellBordersXLSX);
     154           2 :     CPPUNIT_TEST(testTrackChangesSimpleXLSX);
     155           2 :     CPPUNIT_TEST(testSheetTabColorsXLSX);
     156           2 :     CPPUNIT_TEST(testSharedFormulaExportXLS);
     157           2 :     CPPUNIT_TEST(testSharedFormulaExportXLSX);
     158           2 :     CPPUNIT_TEST(testSharedFormulaStringResultExportXLSX);
     159           2 :     CPPUNIT_TEST(testFunctionsExcel2010XLSX);
     160           2 :     CPPUNIT_TEST(testFunctionsExcel2010XLS);
     161             : #if !defined(WNT)
     162           2 :     CPPUNIT_TEST(testRelativePaths);
     163             : #endif
     164           2 :     CPPUNIT_TEST(testSheetProtection);
     165           2 :     CPPUNIT_TEST(testPivotTableXLSX);
     166           2 :     CPPUNIT_TEST(testPivotTableTwoDataFieldsXLSX);
     167           2 :     CPPUNIT_TEST(testFunctionsExcel2010ODS);
     168             : #if !defined(WNT)
     169           2 :     CPPUNIT_TEST(testSupBookVirtualPath);
     170             : #endif
     171             : 
     172           4 :     CPPUNIT_TEST_SUITE_END();
     173             : 
     174             : private:
     175             :     void testExcelCellBorders( sal_uLong nFormatType );
     176             : 
     177             :     uno::Reference<uno::XInterface> m_xCalcComponent;
     178             : 
     179             : };
     180             : 
     181           2 : void ScExportTest::registerNamespaces(xmlXPathContextPtr& pXmlXPathCtx)
     182             : {
     183             :     struct { xmlChar* pPrefix; xmlChar* pURI; } aNamespaces[] =
     184             :     {
     185             :         { BAD_CAST("w"), BAD_CAST("http://schemas.openxmlformats.org/wordprocessingml/2006/main") },
     186             :         { BAD_CAST("v"), BAD_CAST("urn:schemas-microsoft-com:vml") },
     187             :         { BAD_CAST("c"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/chart") },
     188             :         { BAD_CAST("a"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/main") },
     189             :         { BAD_CAST("mc"), BAD_CAST("http://schemas.openxmlformats.org/markup-compatibility/2006") },
     190             :         { BAD_CAST("wps"), BAD_CAST("http://schemas.microsoft.com/office/word/2010/wordprocessingShape") },
     191             :         { BAD_CAST("wpg"), BAD_CAST("http://schemas.microsoft.com/office/word/2010/wordprocessingGroup") },
     192             :         { BAD_CAST("wp"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing") },
     193             :         { BAD_CAST("office"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:office:1.0") },
     194             :         { BAD_CAST("table"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:table:1.0") },
     195             :         { BAD_CAST("text"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:text:1.0") },
     196             :         { BAD_CAST("xlink"), BAD_CAST("http://www.w3c.org/1999/xlink") }
     197           2 :     };
     198          26 :     for(size_t i = 0; i < SAL_N_ELEMENTS(aNamespaces); ++i)
     199             :     {
     200          24 :         xmlXPathRegisterNs(pXmlXPathCtx, aNamespaces[i].pPrefix, aNamespaces[i].pURI );
     201             :     }
     202           2 : }
     203             : 
     204             : #if !defined MACOSX && !defined DRAGONFLY
     205           2 : ScDocShellRef ScExportTest::saveAndReloadPassword(ScDocShell* pShell, const OUString &rFilter,
     206             :     const OUString &rUserData, const OUString& rTypeName, sal_uLong nFormatType)
     207             : {
     208           2 :     utl::TempFile aTempFile;
     209           2 :     aTempFile.EnableKillingFile();
     210           4 :     SfxMedium aStoreMedium( aTempFile.GetURL(), STREAM_STD_WRITE );
     211           2 :     sal_uInt32 nExportFormat = 0;
     212           2 :     if (nFormatType == ODS_FORMAT_TYPE)
     213           2 :         nExportFormat = SFX_FILTER_EXPORT | SFX_FILTER_USESOPTIONS;
     214             :     SfxFilter* pExportFilter = new SfxFilter(
     215             :         rFilter,
     216             :         OUString(), nFormatType, nExportFormat, rTypeName, 0, OUString(),
     217           2 :         rUserData, OUString("private:factory/scalc*") );
     218           2 :     pExportFilter->SetVersion(SOFFICE_FILEFORMAT_CURRENT);
     219           2 :     aStoreMedium.SetFilter(pExportFilter);
     220           2 :     SfxItemSet* pExportSet = aStoreMedium.GetItemSet();
     221           4 :     uno::Sequence< beans::NamedValue > aEncryptionData = comphelper::OStorageHelper::CreatePackageEncryptionData( OUString("test") );
     222           4 :     uno::Any xEncryptionData;
     223           2 :     xEncryptionData <<= aEncryptionData;
     224           2 :     pExportSet->Put(SfxUnoAnyItem(SID_ENCRYPTIONDATA, xEncryptionData));
     225             : 
     226           4 :     uno::Reference< embed::XStorage > xMedStorage = aStoreMedium.GetStorage();
     227           2 :     ::comphelper::OStorageHelper::SetCommonStorageEncryptionData( xMedStorage, aEncryptionData );
     228             : 
     229           2 :     pShell->DoSaveAs( aStoreMedium );
     230           2 :     pShell->DoClose();
     231             : 
     232             :     //std::cout << "File: " << aTempFile.GetURL() << std::endl;
     233             : 
     234           2 :     sal_uInt32 nFormat = 0;
     235           2 :     if (nFormatType == ODS_FORMAT_TYPE)
     236           2 :         nFormat = SFX_FILTER_IMPORT | SFX_FILTER_USESOPTIONS;
     237             : 
     238           4 :     OUString aPass("test");
     239           4 :     return load(aTempFile.GetURL(), rFilter, rUserData, rTypeName, nFormatType, nFormat, SOFFICE_FILEFORMAT_CURRENT, &aPass);
     240             : }
     241             : #endif
     242             : 
     243           2 : void ScExportTest::test()
     244             : {
     245             :     ScDocShell* pShell = new ScDocShell(
     246             :         SFXMODEL_STANDARD |
     247             :         SFXMODEL_DISABLE_EMBEDDED_SCRIPTS |
     248           2 :         SFXMODEL_DISABLE_DOCUMENT_RECOVERY);
     249           2 :     pShell->DoInitNew();
     250             : 
     251           2 :     ScDocument& rDoc = pShell->GetDocument();
     252             : 
     253           2 :     rDoc.SetValue(0,0,0, 1.0);
     254             : 
     255           2 :     ScDocShellRef xDocSh = saveAndReload( pShell, ODS );
     256             : 
     257           2 :     CPPUNIT_ASSERT(xDocSh.Is());
     258           2 :     ScDocument& rLoadedDoc = xDocSh->GetDocument();
     259           2 :     double aVal = rLoadedDoc.GetValue(0,0,0);
     260           2 :     ASSERT_DOUBLES_EQUAL(aVal, 1.0);
     261           2 :     xDocSh->DoClose();
     262           2 : }
     263             : 
     264             : #if !defined MACOSX && !defined DRAGONFLY
     265           2 : void ScExportTest::testPasswordExport()
     266             : {
     267             :     ScDocShell* pShell = new ScDocShell(
     268             :         SFXMODEL_STANDARD |
     269             :         SFXMODEL_DISABLE_EMBEDDED_SCRIPTS |
     270           2 :         SFXMODEL_DISABLE_DOCUMENT_RECOVERY);
     271           2 :     pShell->DoInitNew();
     272             : 
     273           2 :     ScDocument& rDoc = pShell->GetDocument();
     274             : 
     275           2 :     rDoc.SetValue(0,0,0, 1.0);
     276             : 
     277           2 :     sal_Int32 nFormat = ODS;
     278           2 :     OUString aFilterName(getFileFormats()[nFormat].pFilterName, strlen(getFileFormats()[nFormat].pFilterName), RTL_TEXTENCODING_UTF8) ;
     279           4 :     OUString aFilterType(getFileFormats()[nFormat].pTypeName, strlen(getFileFormats()[nFormat].pTypeName), RTL_TEXTENCODING_UTF8);
     280           4 :     ScDocShellRef xDocSh = saveAndReloadPassword(pShell, aFilterName, OUString(), aFilterType, getFileFormats()[nFormat].nFormatType);
     281             : 
     282           2 :     CPPUNIT_ASSERT(xDocSh.Is());
     283           2 :     ScDocument& rLoadedDoc = xDocSh->GetDocument();
     284           2 :     double aVal = rLoadedDoc.GetValue(0,0,0);
     285           2 :     ASSERT_DOUBLES_EQUAL(aVal, 1.0);
     286             : 
     287           4 :     xDocSh->DoClose();
     288           2 : }
     289             : #endif
     290             : 
     291           2 : void ScExportTest::testConditionalFormatExportODS()
     292             : {
     293           2 :     ScDocShellRef xShell = loadDoc("new_cond_format_test.", ODS);
     294           2 :     CPPUNIT_ASSERT(xShell.Is());
     295             : 
     296           4 :     ScDocShellRef xDocSh = saveAndReload(&(*xShell), ODS);
     297           2 :     CPPUNIT_ASSERT(xDocSh.Is());
     298           2 :     ScDocument& rDoc = xDocSh->GetDocument();
     299           4 :     OUString aCSVFile("new_cond_format_test.");
     300           4 :     OUString aCSVPath;
     301           2 :     createCSVPath( aCSVFile, aCSVPath );
     302           2 :     testCondFile(aCSVPath, &rDoc, 0);
     303             : 
     304           4 :     xDocSh->DoClose();
     305           2 : }
     306             : 
     307           2 : void ScExportTest::testConditionalFormatExportXLSX()
     308             : {
     309           2 :     ScDocShellRef xShell = loadDoc("new_cond_format_test.", XLSX);
     310           2 :     CPPUNIT_ASSERT(xShell.Is());
     311             : 
     312           4 :     ScDocShellRef xDocSh = saveAndReload(&(*xShell), XLSX);
     313           2 :     CPPUNIT_ASSERT(xDocSh.Is());
     314           2 :     ScDocument& rDoc = xDocSh->GetDocument();
     315             :     {
     316           2 :         OUString aCSVFile("new_cond_format_test.");
     317           4 :         OUString aCSVPath;
     318           2 :         createCSVPath( aCSVFile, aCSVPath );
     319           4 :         testCondFile(aCSVPath, &rDoc, 0);
     320             :     }
     321             :     {
     322           2 :         OUString aCSVFile("new_cond_format_test_sheet2.");
     323           4 :         OUString aCSVPath;
     324           2 :         createCSVPath( aCSVFile, aCSVPath );
     325           4 :         testCondFile(aCSVPath, &rDoc, 1);
     326             :     }
     327             : 
     328           4 :     xDocSh->DoClose();
     329           2 : }
     330             : 
     331           2 : void ScExportTest::testColorScaleExportODS()
     332             : {
     333           2 :     ScDocShellRef xShell = loadDoc("colorscale.", ODS);
     334           2 :     CPPUNIT_ASSERT(xShell.Is());
     335             : 
     336           4 :     ScDocShellRef xDocSh = saveAndReload(xShell, ODS);
     337           2 :     CPPUNIT_ASSERT(xDocSh.Is());
     338             : 
     339           2 :     ScDocument& rDoc = xDocSh->GetDocument();
     340             : 
     341           2 :     testColorScale2Entry_Impl(rDoc);
     342           2 :     testColorScale3Entry_Impl(rDoc);
     343             : 
     344           4 :     xDocSh->DoClose();
     345           2 : }
     346             : 
     347           2 : void ScExportTest::testColorScaleExportXLSX()
     348             : {
     349           2 :     ScDocShellRef xShell = loadDoc("colorscale.", XLSX);
     350           2 :     CPPUNIT_ASSERT(xShell.Is());
     351             : 
     352           4 :     ScDocShellRef xDocSh = saveAndReload(xShell, XLSX);
     353           2 :     CPPUNIT_ASSERT(xDocSh.Is());
     354             : 
     355           2 :     ScDocument& rDoc = xDocSh->GetDocument();
     356             : 
     357           2 :     testColorScale2Entry_Impl(rDoc);
     358           2 :     testColorScale3Entry_Impl(rDoc);
     359             : 
     360           4 :     xDocSh->DoClose();
     361           2 : }
     362             : 
     363           2 : void ScExportTest::testDataBarExportODS()
     364             : {
     365           2 :     ScDocShellRef xShell = loadDoc("databar.", ODS);
     366           2 :     CPPUNIT_ASSERT(xShell.Is());
     367             : 
     368           4 :     ScDocShellRef xDocSh = saveAndReload(xShell, ODS);
     369           2 :     CPPUNIT_ASSERT(xDocSh.Is());
     370             : 
     371           2 :     ScDocument& rDoc = xDocSh->GetDocument();
     372             : 
     373           2 :     testDataBar_Impl(rDoc);
     374             : 
     375           4 :     xDocSh->DoClose();
     376           2 : }
     377             : 
     378           2 : void ScExportTest::testFormatExportODS()
     379             : {
     380           2 :     ScDocShellRef xShell = loadDoc("formats.", ODS);
     381           2 :     CPPUNIT_ASSERT(xShell.Is());
     382             : 
     383           4 :     ScDocShellRef xDocSh = saveAndReload(xShell, ODS);
     384           2 :     CPPUNIT_ASSERT(xDocSh.Is());
     385             : 
     386           2 :     ScDocument& rDoc = xDocSh->GetDocument();
     387             : 
     388           2 :     testFormats(this, &rDoc, ODS);
     389             : 
     390           4 :     xDocSh->DoClose();
     391           2 : }
     392             : 
     393           2 : void ScExportTest::testDataBarExportXLSX()
     394             : {
     395           2 :     ScDocShellRef xShell = loadDoc("databar.", XLSX);
     396           2 :     CPPUNIT_ASSERT(xShell.Is());
     397             : 
     398           4 :     ScDocShellRef xDocSh = saveAndReload(xShell, XLSX);
     399           2 :     CPPUNIT_ASSERT(xDocSh.Is());
     400             : 
     401           2 :     ScDocument& rDoc = xDocSh->GetDocument();
     402             : 
     403           2 :     testDataBar_Impl(rDoc);
     404             : 
     405           4 :     xDocSh->DoClose();
     406           2 : }
     407             : 
     408           2 : void ScExportTest::testMiscRowHeightExport()
     409             : {
     410             :     TestParam::RowData DfltRowData[] =
     411             :     {
     412             :         { 0, 4, 0, 529, 0, false },
     413             :         { 5, 10, 0, 1058, 0, false },
     414             :         { 17, 20, 0, 1767, 0, false },
     415             :         // check last couple of row in document to ensure
     416             :         // they are 5.29mm ( effective default row xlsx height )
     417             :         { 1048573, 1048575, 0, 529, 0, false },
     418           2 :     };
     419             : 
     420             :     TestParam::RowData EmptyRepeatRowData[] =
     421             :     {
     422             :         // rows 0-4, 5-10, 17-20 are all set at various
     423             :         // heights, there is no content in the rows, there
     424             :         // was a bug where only the first row ( of repeated rows )
     425             :         // was set after export
     426             :         { 0, 4, 0, 529, 0, false },
     427             :         { 5, 10, 0, 1058, 0, false },
     428             :         { 17, 20, 0, 1767, 0, false },
     429           2 :     };
     430             : 
     431             :     TestParam aTestValues[] =
     432             :     {
     433             :         // Checks that some distributed ( non-empty ) heights remain set after export (roundtrip)
     434             :         // additionally there is effectively a default row height ( 5.29 mm ). So we test the
     435             :         // unset rows at the end of the document to ensure the effective xlsx default height
     436             :         // is set there too.
     437             :         { "miscrowheights.", XLSX, XLSX, SAL_N_ELEMENTS(DfltRowData), DfltRowData },
     438             :         // Checks that some distributed ( non-empty ) heights remain set after export (to xls)
     439             :         { "miscrowheights.", XLSX, XLS, SAL_N_ELEMENTS(DfltRowData), DfltRowData },
     440             :         // Checks that repreated rows ( of various heights ) remain set after export ( to xlsx )
     441             :         { "miscemptyrepeatedrowheights.", ODS, XLSX, SAL_N_ELEMENTS(EmptyRepeatRowData), EmptyRepeatRowData },
     442             :         // Checks that repreated rows ( of various heights ) remain set after export ( to xls )
     443             :         { "miscemptyrepeatedrowheights.", ODS, XLS, SAL_N_ELEMENTS(EmptyRepeatRowData), EmptyRepeatRowData },
     444           2 :     };
     445           2 :     miscRowHeightsTest( aTestValues, SAL_N_ELEMENTS(aTestValues) );
     446           2 : }
     447             : 
     448             : namespace {
     449             : 
     450          10 : void setAttribute( ScFieldEditEngine& rEE, sal_Int32 nPara, sal_Int32 nStart, sal_Int32 nEnd, sal_uInt16 nType )
     451             : {
     452          10 :     ESelection aSel;
     453          10 :     aSel.nStartPara = aSel.nEndPara = nPara;
     454          10 :     aSel.nStartPos = nStart;
     455          10 :     aSel.nEndPos = nEnd;
     456             : 
     457          10 :     SfxItemSet aItemSet = rEE.GetEmptyItemSet();
     458          10 :     switch (nType)
     459             :     {
     460             :         case EE_CHAR_WEIGHT:
     461             :         {
     462           2 :             SvxWeightItem aWeight(WEIGHT_BOLD, nType);
     463           2 :             aItemSet.Put(aWeight);
     464           2 :             rEE.QuickSetAttribs(aItemSet, aSel);
     465             :         }
     466           2 :         break;
     467             :         case EE_CHAR_ITALIC:
     468             :         {
     469           2 :             SvxPostureItem aItalic(ITALIC_NORMAL, nType);
     470           2 :             aItemSet.Put(aItalic);
     471           2 :             rEE.QuickSetAttribs(aItemSet, aSel);
     472             :         }
     473           2 :         break;
     474             :         case EE_CHAR_STRIKEOUT:
     475             :         {
     476           2 :             SvxCrossedOutItem aCrossOut(STRIKEOUT_SINGLE, nType);
     477           2 :             aItemSet.Put(aCrossOut);
     478           2 :             rEE.QuickSetAttribs(aItemSet, aSel);
     479             :         }
     480           2 :         break;
     481             :         case EE_CHAR_OVERLINE:
     482             :         {
     483           2 :             SvxOverlineItem aItem(UNDERLINE_DOUBLE, nType);
     484           2 :             aItemSet.Put(aItem);
     485           2 :             rEE.QuickSetAttribs(aItemSet, aSel);
     486             :         }
     487           2 :         break;
     488             :         case EE_CHAR_UNDERLINE:
     489             :         {
     490           2 :             SvxUnderlineItem aItem(UNDERLINE_DOUBLE, nType);
     491           2 :             aItemSet.Put(aItem);
     492           2 :             rEE.QuickSetAttribs(aItemSet, aSel);
     493             :         }
     494           2 :         break;
     495             :         default:
     496             :             ;
     497          10 :     }
     498          10 : }
     499             : 
     500           4 : void setFont( ScFieldEditEngine& rEE, sal_Int32 nPara, sal_Int32 nStart, sal_Int32 nEnd, const OUString& rFontName )
     501             : {
     502           4 :     ESelection aSel;
     503           4 :     aSel.nStartPara = aSel.nEndPara = nPara;
     504           4 :     aSel.nStartPos = nStart;
     505           4 :     aSel.nEndPos = nEnd;
     506             : 
     507           4 :     SfxItemSet aItemSet = rEE.GetEmptyItemSet();
     508           8 :     SvxFontItem aItem(FAMILY_MODERN, rFontName, "", PITCH_VARIABLE, RTL_TEXTENCODING_UTF8, EE_CHAR_FONTINFO);
     509           4 :     aItemSet.Put(aItem);
     510           8 :     rEE.QuickSetAttribs(aItemSet, aSel);
     511           4 : }
     512             : 
     513             : }
     514             : 
     515           2 : void ScExportTest::testNamedRangeBugfdo62729()
     516             : {
     517           2 :     ScDocShellRef xShell = loadDoc("fdo62729.", ODS);
     518           2 :     CPPUNIT_ASSERT(xShell.Is());
     519           2 :     ScDocument& rDoc = xShell->GetDocument();
     520             : 
     521           2 :     ScRangeName* pNames = rDoc.GetRangeName();
     522             :     //should be just a single named range
     523           2 :     CPPUNIT_ASSERT(pNames->size() == 1 );
     524           2 :     rDoc.DeleteTab(0);
     525             :     //should be still a single named range
     526           2 :     CPPUNIT_ASSERT(pNames->size() == 1 );
     527           4 :     ScDocShellRef xDocSh = saveAndReload(xShell, ODS);
     528           2 :     xShell->DoClose();
     529             : 
     530           2 :     CPPUNIT_ASSERT(xDocSh.Is());
     531           2 :     ScDocument& rDoc2 = xDocSh->GetDocument();
     532             : 
     533           2 :     pNames = rDoc2.GetRangeName();
     534             :     //after reload should still have a named range
     535           2 :     CPPUNIT_ASSERT(pNames->size() == 1 );
     536             : 
     537           4 :     xDocSh->DoClose();
     538           2 : }
     539             : 
     540           2 : void ScExportTest::testRichTextExportODS()
     541             : {
     542             :     struct
     543             :     {
     544           6 :         static bool isBold(const editeng::Section& rAttr)
     545             :         {
     546           6 :             if (rAttr.maAttributes.empty())
     547           0 :                 return false;
     548             : 
     549           6 :             std::vector<const SfxPoolItem*>::const_iterator it = rAttr.maAttributes.begin(), itEnd = rAttr.maAttributes.end();
     550           6 :             for (; it != itEnd; ++it)
     551             :             {
     552           6 :                 const SfxPoolItem* p = *it;
     553           6 :                 if (p->Which() != EE_CHAR_WEIGHT)
     554           0 :                     continue;
     555             : 
     556           6 :                 return static_cast<const SvxWeightItem*>(p)->GetWeight() == WEIGHT_BOLD;
     557             :             }
     558           0 :             return false;
     559             :         }
     560             : 
     561           6 :         static bool isItalic(const editeng::Section& rAttr)
     562             :         {
     563           6 :             if (rAttr.maAttributes.empty())
     564           0 :                 return false;
     565             : 
     566           6 :             std::vector<const SfxPoolItem*>::const_iterator it = rAttr.maAttributes.begin(), itEnd = rAttr.maAttributes.end();
     567           6 :             for (; it != itEnd; ++it)
     568             :             {
     569           6 :                 const SfxPoolItem* p = *it;
     570           6 :                 if (p->Which() != EE_CHAR_ITALIC)
     571           0 :                     continue;
     572             : 
     573           6 :                 return static_cast<const SvxPostureItem*>(p)->GetPosture() == ITALIC_NORMAL;
     574             :             }
     575           0 :             return false;
     576             :         }
     577             : 
     578           4 :         static bool isStrikeOut(const editeng::Section& rAttr)
     579             :         {
     580           4 :             if (rAttr.maAttributes.empty())
     581           0 :                 return false;
     582             : 
     583           4 :             std::vector<const SfxPoolItem*>::const_iterator it = rAttr.maAttributes.begin(), itEnd = rAttr.maAttributes.end();
     584           4 :             for (; it != itEnd; ++it)
     585             :             {
     586           4 :                 const SfxPoolItem* p = *it;
     587           4 :                 if (p->Which() != EE_CHAR_STRIKEOUT)
     588           0 :                     continue;
     589             : 
     590           4 :                 return static_cast<const SvxCrossedOutItem*>(p)->GetStrikeout() == STRIKEOUT_SINGLE;
     591             :             }
     592           0 :             return false;
     593             :         }
     594             : 
     595           4 :         static bool isOverline(const editeng::Section& rAttr, FontUnderline eStyle)
     596             :         {
     597           4 :             if (rAttr.maAttributes.empty())
     598           0 :                 return false;
     599             : 
     600           4 :             std::vector<const SfxPoolItem*>::const_iterator it = rAttr.maAttributes.begin(), itEnd = rAttr.maAttributes.end();
     601           4 :             for (; it != itEnd; ++it)
     602             :             {
     603           4 :                 const SfxPoolItem* p = *it;
     604           4 :                 if (p->Which() != EE_CHAR_OVERLINE)
     605           0 :                     continue;
     606             : 
     607           4 :                 return static_cast<const SvxOverlineItem*>(p)->GetLineStyle() == eStyle;
     608             :             }
     609           0 :             return false;
     610             :         }
     611             : 
     612           4 :         static bool isUnderline(const editeng::Section& rAttr, FontUnderline eStyle)
     613             :         {
     614           4 :             if (rAttr.maAttributes.empty())
     615           0 :                 return false;
     616             : 
     617           4 :             std::vector<const SfxPoolItem*>::const_iterator it = rAttr.maAttributes.begin(), itEnd = rAttr.maAttributes.end();
     618           4 :             for (; it != itEnd; ++it)
     619             :             {
     620           4 :                 const SfxPoolItem* p = *it;
     621           4 :                 if (p->Which() != EE_CHAR_UNDERLINE)
     622           0 :                     continue;
     623             : 
     624           4 :                 return static_cast<const SvxUnderlineItem*>(p)->GetLineStyle() == eStyle;
     625             :             }
     626           0 :             return false;
     627             :         }
     628             : 
     629           8 :         static bool isFont(const editeng::Section& rAttr, const OUString& rFontName)
     630             :         {
     631           8 :             if (rAttr.maAttributes.empty())
     632           0 :                 return false;
     633             : 
     634           8 :             std::vector<const SfxPoolItem*>::const_iterator it = rAttr.maAttributes.begin(), itEnd = rAttr.maAttributes.end();
     635           8 :             for (; it != itEnd; ++it)
     636             :             {
     637           8 :                 const SfxPoolItem* p = *it;
     638           8 :                 if (p->Which() != EE_CHAR_FONTINFO)
     639           0 :                     continue;
     640             : 
     641           8 :                 return static_cast<const SvxFontItem*>(p)->GetFamilyName() == rFontName;
     642             :             }
     643           0 :             return false;
     644             :         }
     645             : 
     646           6 :         bool checkB2(const EditTextObject* pText) const
     647             :         {
     648           6 :             if (!pText)
     649           0 :                 return false;
     650             : 
     651           6 :             if (pText->GetParagraphCount() != 1)
     652           0 :                 return false;
     653             : 
     654           6 :             if (pText->GetText(0) != "Bold and Italic")
     655           0 :                 return false;
     656             : 
     657           6 :             std::vector<editeng::Section> aSecAttrs;
     658           6 :             pText->GetAllSections(aSecAttrs);
     659           6 :             if (aSecAttrs.size() != 3)
     660           0 :                 return false;
     661             : 
     662             :             // Check the first bold section.
     663           6 :             const editeng::Section* pAttr = &aSecAttrs[0];
     664           6 :             if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 0 || pAttr->mnEnd != 4)
     665           0 :                 return false;
     666             : 
     667           6 :             if (pAttr->maAttributes.size() != 1 || !isBold(*pAttr))
     668           0 :                 return false;
     669             : 
     670             :             // The middle section should be unformatted.
     671           6 :             pAttr = &aSecAttrs[1];
     672           6 :             if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 4 || pAttr->mnEnd != 9)
     673           0 :                 return false;
     674             : 
     675           6 :             if (!pAttr->maAttributes.empty())
     676           0 :                 return false;
     677             : 
     678             :             // The last section should be italic.
     679           6 :             pAttr = &aSecAttrs[2];
     680           6 :             if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 9 || pAttr->mnEnd != 15)
     681           0 :                 return false;
     682             : 
     683           6 :             if (pAttr->maAttributes.size() != 1 || !isItalic(*pAttr))
     684           0 :                 return false;
     685             : 
     686           6 :             return true;
     687             :         }
     688             : 
     689           6 :         bool checkB4(const EditTextObject* pText) const
     690             :         {
     691           6 :             if (!pText)
     692           0 :                 return false;
     693             : 
     694           6 :             if (pText->GetParagraphCount() != 3)
     695           0 :                 return false;
     696             : 
     697           6 :             if (pText->GetText(0) != "One")
     698           0 :                 return false;
     699             : 
     700           6 :             if (pText->GetText(1) != "Two")
     701           0 :                 return false;
     702             : 
     703           6 :             if (pText->GetText(2) != "Three")
     704           0 :                 return false;
     705             : 
     706           6 :             return true;
     707             :         }
     708             : 
     709           4 :         bool checkB5(const EditTextObject* pText) const
     710             :         {
     711           4 :             if (!pText)
     712           0 :                 return false;
     713             : 
     714           4 :             if (pText->GetParagraphCount() != 6)
     715           0 :                 return false;
     716             : 
     717           4 :             if (pText->GetText(0) != "")
     718           0 :                 return false;
     719             : 
     720           4 :             if (pText->GetText(1) != "Two")
     721           0 :                 return false;
     722             : 
     723           4 :             if (pText->GetText(2) != "Three")
     724           0 :                 return false;
     725             : 
     726           4 :             if (pText->GetText(3) != "")
     727           0 :                 return false;
     728             : 
     729           4 :             if (pText->GetText(4) != "Five")
     730           0 :                 return false;
     731             : 
     732           4 :             if (pText->GetText(5) != "")
     733           0 :                 return false;
     734             : 
     735           4 :             return true;
     736             :         }
     737             : 
     738           4 :         bool checkB6(const EditTextObject* pText) const
     739             :         {
     740           4 :             if (!pText)
     741           0 :                 return false;
     742             : 
     743           4 :             if (pText->GetParagraphCount() != 1)
     744           0 :                 return false;
     745             : 
     746           4 :             if (pText->GetText(0) != "Strike Me")
     747           0 :                 return false;
     748             : 
     749           4 :             std::vector<editeng::Section> aSecAttrs;
     750           4 :             pText->GetAllSections(aSecAttrs);
     751           4 :             if (aSecAttrs.size() != 2)
     752           0 :                 return false;
     753             : 
     754             :             // Check the first strike-out section.
     755           4 :             const editeng::Section* pAttr = &aSecAttrs[0];
     756           4 :             if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 0 || pAttr->mnEnd != 6)
     757           0 :                 return false;
     758             : 
     759           4 :             if (pAttr->maAttributes.size() != 1 || !isStrikeOut(*pAttr))
     760           0 :                 return false;
     761             : 
     762             :             // The last section should be unformatted.
     763           4 :             pAttr = &aSecAttrs[1];
     764           4 :             if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 6 || pAttr->mnEnd != 9)
     765           0 :                 return false;
     766             : 
     767           4 :             return true;
     768             :         }
     769             : 
     770           4 :         bool checkB7(const EditTextObject* pText) const
     771             :         {
     772           4 :             if (!pText)
     773           0 :                 return false;
     774             : 
     775           4 :             if (pText->GetParagraphCount() != 1)
     776           0 :                 return false;
     777             : 
     778           4 :             if (pText->GetText(0) != "Font1 and Font2")
     779           0 :                 return false;
     780             : 
     781           4 :             std::vector<editeng::Section> aSecAttrs;
     782           4 :             pText->GetAllSections(aSecAttrs);
     783           4 :             if (aSecAttrs.size() != 3)
     784           0 :                 return false;
     785             : 
     786             :             // First section should have "Courier" font applied.
     787           4 :             const editeng::Section* pAttr = &aSecAttrs[0];
     788           4 :             if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 0 || pAttr->mnEnd != 5)
     789           0 :                 return false;
     790             : 
     791           4 :             if (pAttr->maAttributes.size() != 1 || !isFont(*pAttr, "Courier"))
     792           0 :                 return false;
     793             : 
     794             :             // Last section should have "Luxi Mono" applied.
     795           4 :             pAttr = &aSecAttrs[2];
     796           4 :             if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 10 || pAttr->mnEnd != 15)
     797           0 :                 return false;
     798             : 
     799           4 :             if (pAttr->maAttributes.size() != 1 || !isFont(*pAttr, "Luxi Mono"))
     800           0 :                 return false;
     801             : 
     802           4 :             return true;
     803             :         }
     804             : 
     805           4 :         bool checkB8(const EditTextObject* pText) const
     806             :         {
     807           4 :             if (!pText)
     808           0 :                 return false;
     809             : 
     810           4 :             if (pText->GetParagraphCount() != 1)
     811           0 :                 return false;
     812             : 
     813           4 :             if (pText->GetText(0) != "Over and Under")
     814           0 :                 return false;
     815             : 
     816           4 :             std::vector<editeng::Section> aSecAttrs;
     817           4 :             pText->GetAllSections(aSecAttrs);
     818           4 :             if (aSecAttrs.size() != 3)
     819           0 :                 return false;
     820             : 
     821             :             // First section shoul have overline applied.
     822           4 :             const editeng::Section* pAttr = &aSecAttrs[0];
     823           4 :             if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 0 || pAttr->mnEnd != 4)
     824           0 :                 return false;
     825             : 
     826           4 :             if (pAttr->maAttributes.size() != 1 || !isOverline(*pAttr, UNDERLINE_DOUBLE))
     827           0 :                 return false;
     828             : 
     829             :             // Last section should have underline applied.
     830           4 :             pAttr = &aSecAttrs[2];
     831           4 :             if (pAttr->mnParagraph != 0 ||pAttr->mnStart != 9 || pAttr->mnEnd != 14)
     832           0 :                 return false;
     833             : 
     834           4 :             if (pAttr->maAttributes.size() != 1 || !isUnderline(*pAttr, UNDERLINE_DOUBLE))
     835           0 :                 return false;
     836             : 
     837           4 :             return true;
     838             :         }
     839             : 
     840             :     } aCheckFunc;
     841             : 
     842             :     // Start with an empty document, put one edit text cell, and make sure it
     843             :     // survives the save and reload.
     844           2 :     ScDocShellRef xOrigDocSh = loadDoc("empty.", ODS, true);
     845             :     const EditTextObject* pEditText;
     846             :     {
     847           2 :         ScDocument& rDoc = xOrigDocSh->GetDocument();
     848           2 :         CPPUNIT_ASSERT_MESSAGE("This document should at least have one sheet.", rDoc.GetTableCount() > 0);
     849             : 
     850             :         // Insert an edit text cell.
     851           2 :         ScFieldEditEngine* pEE = &rDoc.GetEditEngine();
     852           2 :         pEE->SetText("Bold and Italic");
     853             :         // Set the 'Bold' part bold.
     854           2 :         setAttribute(*pEE, 0, 0, 4, EE_CHAR_WEIGHT);
     855             :         // Set the 'Italic' part italic.
     856           2 :         setAttribute(*pEE, 0, 9, 15, EE_CHAR_ITALIC);
     857           2 :         ESelection aSel;
     858           2 :         aSel.nStartPara = aSel.nEndPara = 0;
     859             : 
     860             :         // Set this edit text to cell B2.
     861           2 :         rDoc.SetEditText(ScAddress(1,1,0), pEE->CreateTextObject());
     862           2 :         pEditText = rDoc.GetEditText(ScAddress(1,1,0));
     863           2 :         CPPUNIT_ASSERT_MESSAGE("Incorret B2 value.", aCheckFunc.checkB2(pEditText));
     864             :     }
     865             : 
     866             :     // Now, save and reload this document.
     867           4 :     ScDocShellRef xNewDocSh = saveAndReload(xOrigDocSh, ODS);
     868             :     {
     869           2 :         xOrigDocSh->DoClose();
     870           2 :         CPPUNIT_ASSERT(xNewDocSh.Is());
     871           2 :         ScDocument& rDoc2 = xNewDocSh->GetDocument();
     872           2 :         CPPUNIT_ASSERT_MESSAGE("Reloaded document should at least have one sheet.", rDoc2.GetTableCount() > 0);
     873           2 :         ScFieldEditEngine* pEE = &rDoc2.GetEditEngine();
     874             : 
     875             :         // Make sure the content of B2 is still intact.
     876           2 :         CPPUNIT_ASSERT_MESSAGE("Incorret B2 value.", aCheckFunc.checkB2(pEditText));
     877             : 
     878             :         // Insert a multi-line content to B4.
     879           2 :         pEE->Clear();
     880           2 :         pEE->SetText("One\nTwo\nThree");
     881           2 :         rDoc2.SetEditText(ScAddress(1,3,0), pEE->CreateTextObject());
     882           2 :         pEditText = rDoc2.GetEditText(ScAddress(1,3,0));
     883           2 :         CPPUNIT_ASSERT_MESSAGE("Incorrect B4 value.", aCheckFunc.checkB4(pEditText));
     884             :     }
     885             : 
     886             :     // Reload the doc again, and check the content of B2 and B4.
     887           4 :     ScDocShellRef xNewDocSh2 = saveAndReload(xNewDocSh, ODS);
     888             :     {
     889           2 :         ScDocument& rDoc3 = xNewDocSh2->GetDocument();
     890           2 :         ScFieldEditEngine* pEE = &rDoc3.GetEditEngine();
     891           2 :         xNewDocSh->DoClose();
     892             : 
     893           2 :         pEditText = rDoc3.GetEditText(ScAddress(1,1,0));
     894           2 :         CPPUNIT_ASSERT_MESSAGE("B2 should be an edit text.", pEditText);
     895           2 :         pEditText = rDoc3.GetEditText(ScAddress(1,3,0));
     896           2 :         CPPUNIT_ASSERT_MESSAGE("Incorrect B4 value.", aCheckFunc.checkB4(pEditText));
     897             : 
     898             :         // Insert a multi-line content to B5, but this time, set some empty paragraphs.
     899           2 :         pEE->Clear();
     900           2 :         pEE->SetText("\nTwo\nThree\n\nFive\n");
     901           2 :         rDoc3.SetEditText(ScAddress(1,4,0), pEE->CreateTextObject());
     902           2 :         pEditText = rDoc3.GetEditText(ScAddress(1,4,0));
     903           2 :         CPPUNIT_ASSERT_MESSAGE("Incorrect B5 value.", aCheckFunc.checkB5(pEditText));
     904             : 
     905             :         // Insert a text with strikethrough in B6.
     906           2 :         pEE->Clear();
     907           2 :         pEE->SetText("Strike Me");
     908             :         // Set the 'Strike' part strikethrough.
     909           2 :         setAttribute(*pEE, 0, 0, 6, EE_CHAR_STRIKEOUT);
     910           2 :         rDoc3.SetEditText(ScAddress(1,5,0), pEE->CreateTextObject());
     911           2 :         pEditText = rDoc3.GetEditText(ScAddress(1,5,0));
     912           2 :         CPPUNIT_ASSERT_MESSAGE("Incorrect B6 value.", aCheckFunc.checkB6(pEditText));
     913             : 
     914             :         // Insert a text with different font segments in B7.
     915           2 :         pEE->Clear();
     916           2 :         pEE->SetText("Font1 and Font2");
     917           2 :         setFont(*pEE, 0, 0, 5, "Courier");
     918           2 :         setFont(*pEE, 0, 10, 15, "Luxi Mono");
     919           2 :         rDoc3.SetEditText(ScAddress(1,6,0), pEE->CreateTextObject());
     920           2 :         pEditText = rDoc3.GetEditText(ScAddress(1,6,0));
     921           2 :         CPPUNIT_ASSERT_MESSAGE("Incorrect B7 value.", aCheckFunc.checkB7(pEditText));
     922             : 
     923             :         // Insert a text with overline and underline in B8.
     924           2 :         pEE->Clear();
     925           2 :         pEE->SetText("Over and Under");
     926           2 :         setAttribute(*pEE, 0, 0, 4, EE_CHAR_OVERLINE);
     927           2 :         setAttribute(*pEE, 0, 9, 14, EE_CHAR_UNDERLINE);
     928           2 :         rDoc3.SetEditText(ScAddress(1,7,0), pEE->CreateTextObject());
     929           2 :         pEditText = rDoc3.GetEditText(ScAddress(1,7,0));
     930           2 :         CPPUNIT_ASSERT_MESSAGE("Incorrect B8 value.", aCheckFunc.checkB8(pEditText));
     931             :     }
     932             : 
     933             :     // Reload the doc again, and check the content of B2, B4, B6 and B7.
     934           4 :     ScDocShellRef xNewDocSh3 = saveAndReload(xNewDocSh2, ODS);
     935           2 :     ScDocument& rDoc4 = xNewDocSh3->GetDocument();
     936           2 :     xNewDocSh2->DoClose();
     937             : 
     938           2 :     pEditText = rDoc4.GetEditText(ScAddress(1,1,0));
     939           2 :     CPPUNIT_ASSERT_MESSAGE("Incorrect B2 value after save and reload.", aCheckFunc.checkB2(pEditText));
     940           2 :     pEditText = rDoc4.GetEditText(ScAddress(1,3,0));
     941           2 :     CPPUNIT_ASSERT_MESSAGE("Incorrect B4 value after save and reload.", aCheckFunc.checkB4(pEditText));
     942           2 :     pEditText = rDoc4.GetEditText(ScAddress(1,4,0));
     943           2 :     CPPUNIT_ASSERT_MESSAGE("Incorrect B5 value after save and reload.", aCheckFunc.checkB5(pEditText));
     944           2 :     pEditText = rDoc4.GetEditText(ScAddress(1,5,0));
     945           2 :     CPPUNIT_ASSERT_MESSAGE("Incorrect B6 value after save and reload.", aCheckFunc.checkB6(pEditText));
     946           2 :     pEditText = rDoc4.GetEditText(ScAddress(1,6,0));
     947           2 :     CPPUNIT_ASSERT_MESSAGE("Incorrect B7 value after save and reload.", aCheckFunc.checkB7(pEditText));
     948           2 :     pEditText = rDoc4.GetEditText(ScAddress(1,7,0));
     949           2 :     CPPUNIT_ASSERT_MESSAGE("Incorrect B8 value after save and reload.", aCheckFunc.checkB8(pEditText));
     950             : 
     951           4 :     xNewDocSh3->DoClose();
     952           2 : }
     953             : 
     954           2 : void ScExportTest::testFormulaRefSheetNameODS()
     955             : {
     956           2 :     ScDocShellRef xDocSh = loadDoc("formula-quote-in-sheet-name.", ODS, true);
     957             :     {
     958           2 :         ScDocument& rDoc = xDocSh->GetDocument();
     959             : 
     960           2 :         sc::AutoCalcSwitch aACSwitch(rDoc, true); // turn on auto calc.
     961           2 :         rDoc.SetString(ScAddress(1,1,0), "='90''s Data'.B2");
     962           2 :         CPPUNIT_ASSERT_EQUAL(1.1, rDoc.GetValue(ScAddress(1,1,0)));
     963           2 :         if (!checkFormula(rDoc, ScAddress(1,1,0), "'90''s Data'.B2"))
     964           0 :             CPPUNIT_FAIL("Wrong formula");
     965             :     }
     966             :     // Now, save and reload this document.
     967           4 :     ScDocShellRef xNewDocSh = saveAndReload(xDocSh, ODS);
     968           2 :     xDocSh->DoClose();
     969             : 
     970           2 :     ScDocument& rDoc = xNewDocSh->GetDocument();
     971           2 :     rDoc.CalcAll();
     972           2 :     CPPUNIT_ASSERT_EQUAL(1.1, rDoc.GetValue(ScAddress(1,1,0)));
     973           2 :     if (!checkFormula(rDoc, ScAddress(1,1,0), "'90''s Data'.B2"))
     974           0 :         CPPUNIT_FAIL("Wrong formula");
     975             : 
     976           4 :     xNewDocSh->DoClose();
     977           2 : }
     978             : 
     979           2 : void ScExportTest::testCellValuesExportODS()
     980             : {
     981             :     // Start with an empty document
     982           2 :     ScDocShellRef xOrigDocSh = loadDoc("empty.", ODS);
     983             :     {
     984           2 :         ScDocument& rDoc = xOrigDocSh->GetDocument();
     985           2 :         CPPUNIT_ASSERT_MESSAGE("This document should at least have one sheet.", rDoc.GetTableCount() > 0);
     986             : 
     987             :         // set a value double
     988           2 :         rDoc.SetValue(ScAddress(0,0,0), 2.0); // A1
     989             : 
     990             :         // set a formula
     991           2 :         rDoc.SetValue(ScAddress(2,0,0), 3.0); // C1
     992           2 :         rDoc.SetValue(ScAddress(3,0,0), 3); // D1
     993           2 :         rDoc.SetString(ScAddress(4,0,0), "=10*C1/4"); // E1
     994           2 :         rDoc.SetValue(ScAddress(5,0,0), 3.0); // F1
     995           2 :         rDoc.SetString(ScAddress(7,0,0), "=SUM(C1:F1)"); //H1
     996             : 
     997             :         // set a string
     998           2 :         rDoc.SetString(ScAddress(0,2,0), "a simple line"); //A3
     999             : 
    1000             :         // set a digit string
    1001           2 :         rDoc.SetString(ScAddress(0,4,0), "'12"); //A5
    1002             :         // set a contiguous value
    1003           2 :         rDoc.SetValue(ScAddress(0,5,0), 12.0); //A6
    1004             :         // set acontiguous string
    1005           2 :         rDoc.SetString(ScAddress(0,6,0), "a string"); //A7
    1006             :         // set a contiguous formula
    1007           2 :         rDoc.SetString(ScAddress(0,7,0), "=$A$6"); //A8
    1008             :     }
    1009             :     // save and reload
    1010           4 :     ScDocShellRef xNewDocSh = saveAndReload(xOrigDocSh, ODS);
    1011           2 :     xOrigDocSh->DoClose();
    1012           2 :     CPPUNIT_ASSERT(xNewDocSh.Is());
    1013           2 :     ScDocument& rDoc = xNewDocSh->GetDocument();
    1014           2 :     CPPUNIT_ASSERT_MESSAGE("Reloaded document should at least have one sheet.", rDoc.GetTableCount() > 0);
    1015             : 
    1016             :     // check value
    1017           2 :     CPPUNIT_ASSERT_EQUAL(2.0, rDoc.GetValue(0,0,0));
    1018           2 :     CPPUNIT_ASSERT_EQUAL(3.0, rDoc.GetValue(2,0,0));
    1019           2 :     CPPUNIT_ASSERT_EQUAL(3.0, rDoc.GetValue(3,0,0));
    1020           2 :     CPPUNIT_ASSERT_EQUAL(7.5, rDoc.GetValue(4,0,0));
    1021           2 :     CPPUNIT_ASSERT_EQUAL(3.0, rDoc.GetValue(5,0,0));
    1022             : 
    1023             :     // check formula
    1024           2 :     if (!checkFormula(rDoc, ScAddress(4,0,0), "10*C1/4"))
    1025           0 :         CPPUNIT_FAIL("Wrong formula =10*C1/4");
    1026           2 :     if (!checkFormula(rDoc, ScAddress(7,0,0), "SUM(C1:F1)"))
    1027           0 :         CPPUNIT_FAIL("Wrong formula =SUM(C1:F1)");
    1028           2 :     CPPUNIT_ASSERT_EQUAL(16.5, rDoc.GetValue(7,0,0));
    1029             : 
    1030             :     // check string
    1031           4 :     ScRefCellValue aCell;
    1032           2 :     aCell.assign(rDoc, ScAddress(0,2,0));
    1033           2 :     CPPUNIT_ASSERT_EQUAL( CELLTYPE_STRING, aCell.meType );
    1034             : 
    1035             :     // check for an empty cell
    1036           2 :     aCell.assign(rDoc, ScAddress(0,3,0));
    1037           2 :     CPPUNIT_ASSERT_EQUAL( CELLTYPE_NONE, aCell.meType);
    1038             : 
    1039             :     // check a digit string
    1040           2 :     aCell.assign(rDoc, ScAddress(0,4,0));
    1041           2 :     CPPUNIT_ASSERT_EQUAL( CELLTYPE_STRING, aCell.meType);
    1042             : 
    1043             :     //check contiguous values
    1044           2 :     CPPUNIT_ASSERT_EQUAL( 12.0, rDoc.GetValue(0,5,0) );
    1045           2 :     CPPUNIT_ASSERT_EQUAL( OUString("a string"), rDoc.GetString(0,6,0) );
    1046           2 :     if (!checkFormula(rDoc, ScAddress(0,7,0), "$A$6"))
    1047           0 :         CPPUNIT_FAIL("Wrong formula =$A$6");
    1048           2 :     CPPUNIT_ASSERT_EQUAL( rDoc.GetValue(0,5,0), rDoc.GetValue(0,7,0) );
    1049             : 
    1050           4 :     xNewDocSh->DoClose();
    1051           2 : }
    1052             : 
    1053           2 : void ScExportTest::testCellNoteExportODS()
    1054             : {
    1055           2 :     ScDocShellRef xOrigDocSh = loadDoc("single-note.", ODS);
    1056           2 :     ScAddress aPos(0,0,0); // Start with A1.
    1057             :     {
    1058           2 :         ScDocument& rDoc = xOrigDocSh->GetDocument();
    1059             : 
    1060           2 :         CPPUNIT_ASSERT_MESSAGE("There should be a note at A1.", rDoc.HasNote(aPos));
    1061             : 
    1062           2 :         aPos.IncRow(); // Move to A2.
    1063           2 :         ScPostIt* pNote = rDoc.GetOrCreateNote(aPos);
    1064           2 :         pNote->SetText(aPos, "Note One");
    1065           2 :         pNote->SetAuthor("Author One");
    1066           2 :         CPPUNIT_ASSERT_MESSAGE("There should be a note at A2.", rDoc.HasNote(aPos));
    1067             :     }
    1068             :     // save and reload
    1069           4 :     ScDocShellRef xNewDocSh = saveAndReload(xOrigDocSh, ODS);
    1070           2 :     xOrigDocSh->DoClose();
    1071           2 :     CPPUNIT_ASSERT(xNewDocSh.Is());
    1072           2 :     ScDocument& rDoc = xNewDocSh->GetDocument();
    1073             : 
    1074           2 :     aPos.SetRow(0); // Move back to A1.
    1075           2 :     CPPUNIT_ASSERT_MESSAGE("There should be a note at A1.", rDoc.HasNote(aPos));
    1076           2 :     aPos.IncRow(); // Move to A2.
    1077           2 :     CPPUNIT_ASSERT_MESSAGE("There should be a note at A2.", rDoc.HasNote(aPos));
    1078             : 
    1079           4 :     xNewDocSh->DoClose();
    1080           2 : }
    1081             : 
    1082           2 : void ScExportTest::testCellNoteExportXLS()
    1083             : {
    1084             :     // Start with an empty document.s
    1085           2 :     ScDocShellRef xOrigDocSh = loadDoc("notes-on-3-sheets.", ODS);
    1086             :     {
    1087           2 :         ScDocument& rDoc = xOrigDocSh->GetDocument();
    1088           2 :         CPPUNIT_ASSERT_MESSAGE("This document should have 3 sheets.", rDoc.GetTableCount() == 3);
    1089             : 
    1090             :         // Check note's presence.
    1091           2 :         CPPUNIT_ASSERT( rDoc.HasNote(ScAddress(0,0,0)));
    1092           2 :         CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,1,0)));
    1093           2 :         CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,2,0)));
    1094             : 
    1095           2 :         CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,0,1)));
    1096           2 :         CPPUNIT_ASSERT( rDoc.HasNote(ScAddress(0,1,1)));
    1097           2 :         CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,2,1)));
    1098             : 
    1099           2 :         CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,0,2)));
    1100           2 :         CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,1,2)));
    1101           2 :         CPPUNIT_ASSERT( rDoc.HasNote(ScAddress(0,2,2)));
    1102             :     }
    1103             :     // save and reload as XLS.
    1104           4 :     ScDocShellRef xNewDocSh = saveAndReload(xOrigDocSh, XLS);
    1105             :     {
    1106           2 :         xOrigDocSh->DoClose();
    1107           2 :         CPPUNIT_ASSERT(xNewDocSh.Is());
    1108           2 :         ScDocument& rDoc = xNewDocSh->GetDocument();
    1109           2 :         CPPUNIT_ASSERT_MESSAGE("This document should have 3 sheets.", rDoc.GetTableCount() == 3);
    1110             : 
    1111             :         // Check note's presence again.
    1112           2 :         CPPUNIT_ASSERT( rDoc.HasNote(ScAddress(0,0,0)));
    1113           2 :         CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,1,0)));
    1114           2 :         CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,2,0)));
    1115             : 
    1116           2 :         CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,0,1)));
    1117           2 :         CPPUNIT_ASSERT( rDoc.HasNote(ScAddress(0,1,1)));
    1118           2 :         CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,2,1)));
    1119             : 
    1120           2 :         CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,0,2)));
    1121           2 :         CPPUNIT_ASSERT(!rDoc.HasNote(ScAddress(0,1,2)));
    1122           2 :         CPPUNIT_ASSERT( rDoc.HasNote(ScAddress(0,2,2)));
    1123             : 
    1124           2 :         xNewDocSh->DoClose();
    1125           2 :     }
    1126           2 : }
    1127             : 
    1128             : namespace {
    1129             : 
    1130           6 : void checkMatrixRange(ScDocument& rDoc, const ScRange& rRange)
    1131             : {
    1132           6 :     ScRange aMatRange;
    1133           6 :     ScAddress aMatOrigin;
    1134          20 :     for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
    1135             :     {
    1136          46 :         for (SCROW nRow = rRange.aStart.Row(); nRow <= rRange.aEnd.Row(); ++nRow)
    1137             :         {
    1138          32 :             ScAddress aPos(nCol, nRow, rRange.aStart.Tab());
    1139          32 :             bool bIsMatrix = rDoc.GetMatrixFormulaRange(aPos, aMatRange);
    1140          32 :             CPPUNIT_ASSERT_MESSAGE("Matrix expected, but not found.", bIsMatrix);
    1141          32 :             CPPUNIT_ASSERT_MESSAGE("Wrong matrix range.", rRange == aMatRange);
    1142          32 :             const ScFormulaCell* pCell = rDoc.GetFormulaCell(aPos);
    1143          32 :             CPPUNIT_ASSERT_MESSAGE("This must be a formula cell.", pCell);
    1144             : 
    1145          32 :             bIsMatrix = pCell->GetMatrixOrigin(aMatOrigin);
    1146          32 :             CPPUNIT_ASSERT_MESSAGE("Not a part of matrix formula.", bIsMatrix);
    1147          32 :             CPPUNIT_ASSERT_MESSAGE("Wrong matrix origin.", aMatOrigin == aMatRange.aStart);
    1148             :         }
    1149             :     }
    1150           6 : }
    1151             : 
    1152             : }
    1153             : 
    1154           2 : void ScExportTest::testInlineArrayXLS()
    1155             : {
    1156           2 :     ScDocShellRef xShell = loadDoc("inline-array.", XLS);
    1157           2 :     CPPUNIT_ASSERT(xShell.Is());
    1158             : 
    1159           4 :     ScDocShellRef xDocSh = saveAndReload(xShell, XLS);
    1160           2 :     xShell->DoClose();
    1161           2 :     CPPUNIT_ASSERT(xDocSh.Is());
    1162             : 
    1163           2 :     ScDocument& rDoc = xDocSh->GetDocument();
    1164             : 
    1165             :     // B2:C3 contains a matrix.
    1166           2 :     checkMatrixRange(rDoc, ScRange(1,1,0,2,2,0));
    1167             : 
    1168             :     // B5:D6 contains a matrix.
    1169           2 :     checkMatrixRange(rDoc, ScRange(1,4,0,3,5,0));
    1170             : 
    1171             :     // B8:C10 as well.
    1172           2 :     checkMatrixRange(rDoc, ScRange(1,7,0,2,9,0));
    1173             : 
    1174           4 :     xDocSh->DoClose();
    1175           2 : }
    1176             : 
    1177           2 : void ScExportTest::testEmbeddedChartXLS()
    1178             : {
    1179           2 :     ScDocShellRef xShell = loadDoc("embedded-chart.", XLS);
    1180           2 :     CPPUNIT_ASSERT(xShell.Is());
    1181             : 
    1182           4 :     ScDocShellRef xDocSh = saveAndReload(xShell, XLS);
    1183           2 :     xShell->DoClose();
    1184           2 :     CPPUNIT_ASSERT(xDocSh.Is());
    1185             : 
    1186           2 :     ScDocument& rDoc = xDocSh->GetDocument();
    1187             : 
    1188             :     // Make sure the 2nd sheet is named 'Chart1'.
    1189           4 :     OUString aName;
    1190           2 :     rDoc.GetName(1, aName);
    1191           2 :     CPPUNIT_ASSERT_EQUAL(OUString("Chart1"), aName);
    1192             : 
    1193           2 :     const SdrOle2Obj* pOleObj = getSingleChartObject(rDoc, 1);
    1194           2 :     CPPUNIT_ASSERT_MESSAGE("Failed to retrieve a chart object from the 2nd sheet.", pOleObj);
    1195             : 
    1196           4 :     ScRangeList aRanges = getChartRanges(rDoc, *pOleObj);
    1197           2 :     CPPUNIT_ASSERT_MESSAGE("Label range (B3:B5) not found.", aRanges.In(ScRange(1,2,1,1,4,1)));
    1198           2 :     CPPUNIT_ASSERT_MESSAGE("Data label (C2) not found.", aRanges.In(ScAddress(2,1,1)));
    1199           2 :     CPPUNIT_ASSERT_MESSAGE("Data range (C3:C5) not found.", aRanges.In(ScRange(2,2,1,2,4,1)));
    1200             : 
    1201           4 :     xDocSh->DoClose();
    1202           2 : }
    1203             : 
    1204           2 : void ScExportTest::testFormulaReferenceXLS()
    1205             : {
    1206           2 :     ScDocShellRef xShell = loadDoc("formula-reference.", XLS);
    1207           2 :     CPPUNIT_ASSERT(xShell.Is());
    1208             : 
    1209           4 :     ScDocShellRef xDocSh = saveAndReload(xShell, XLS);
    1210           2 :     xShell->DoClose();
    1211           2 :     CPPUNIT_ASSERT(xDocSh.Is());
    1212             : 
    1213           2 :     ScDocument& rDoc = xDocSh->GetDocument();
    1214             : 
    1215           2 :     if (!checkFormula(rDoc, ScAddress(3,1,0), "$A$2+$B$2+$C$2"))
    1216           0 :         CPPUNIT_FAIL("Wrong formula in D2");
    1217             : 
    1218           2 :     if (!checkFormula(rDoc, ScAddress(3,2,0), "A3+B3+C3"))
    1219           0 :         CPPUNIT_FAIL("Wrong formula in D3");
    1220             : 
    1221           2 :     if (!checkFormula(rDoc, ScAddress(3,5,0), "SUM($A$6:$C$6)"))
    1222           0 :         CPPUNIT_FAIL("Wrong formula in D6");
    1223             : 
    1224           2 :     if (!checkFormula(rDoc, ScAddress(3,6,0), "SUM(A7:C7)"))
    1225           0 :         CPPUNIT_FAIL("Wrong formula in D7");
    1226             : 
    1227           2 :     if (!checkFormula(rDoc, ScAddress(3,9,0), "$Two.$A$2+$Two.$B$2+$Two.$C$2"))
    1228           0 :         CPPUNIT_FAIL("Wrong formula in D10");
    1229             : 
    1230           2 :     if (!checkFormula(rDoc, ScAddress(3,10,0), "$Two.A3+$Two.B3+$Two.C3"))
    1231           0 :         CPPUNIT_FAIL("Wrong formula in D11");
    1232             : 
    1233           2 :     if (!checkFormula(rDoc, ScAddress(3,13,0), "MIN($Two.$A$2:$C$2)"))
    1234           0 :         CPPUNIT_FAIL("Wrong formula in D14");
    1235             : 
    1236           2 :     if (!checkFormula(rDoc, ScAddress(3,14,0), "MAX($Two.A3:C3)"))
    1237           0 :         CPPUNIT_FAIL("Wrong formula in D15");
    1238             : 
    1239           4 :     xDocSh->DoClose();
    1240           2 : }
    1241             : 
    1242           2 : void ScExportTest::testSheetProtectionXLSX()
    1243             : {
    1244           2 :     ScDocShellRef xShell = loadDoc("ProtecteSheet1234Pass.", XLSX);
    1245           2 :     CPPUNIT_ASSERT(xShell.Is());
    1246             : 
    1247           4 :     ScDocShellRef xDocSh = saveAndReload(xShell, XLSX);
    1248           2 :     CPPUNIT_ASSERT(xDocSh.Is());
    1249             : 
    1250           2 :     ScDocument& rDoc = xDocSh->GetDocument();
    1251           2 :     const ScTableProtection* pTabProtect = rDoc.GetTabProtection(0);
    1252           2 :     CPPUNIT_ASSERT(pTabProtect);
    1253           2 :     if ( pTabProtect )
    1254             :     {
    1255           2 :         Sequence<sal_Int8> aHash = pTabProtect->getPasswordHash(PASSHASH_XL);
    1256             :         // check has
    1257           2 :         if (aHash.getLength() >= 2)
    1258             :         {
    1259           2 :             CPPUNIT_ASSERT( (sal_uInt8)aHash[0] == 204 );
    1260           2 :             CPPUNIT_ASSERT( (sal_uInt8)aHash[1] == 61 );
    1261             :         }
    1262             :         // we could flesh out this check I guess
    1263           2 :         CPPUNIT_ASSERT ( !pTabProtect->isOptionEnabled( ScTableProtection::OBJECTS ) );
    1264           2 :         CPPUNIT_ASSERT ( !pTabProtect->isOptionEnabled( ScTableProtection::SCENARIOS ) );
    1265             :     }
    1266           4 :     xDocSh->DoClose();
    1267           2 : }
    1268             : 
    1269             : namespace {
    1270             : 
    1271         192 : const char* toBorderName( sal_Int16 eStyle )
    1272             : {
    1273         192 :     switch (eStyle)
    1274             :     {
    1275          64 :         case table::BorderLineStyle::SOLID: return "SOLID";
    1276          16 :         case table::BorderLineStyle::DOTTED: return "DOTTED";
    1277          16 :         case table::BorderLineStyle::DASHED: return "DASHED";
    1278          32 :         case table::BorderLineStyle::DASH_DOT: return "DASH_DOT";
    1279          32 :         case table::BorderLineStyle::DASH_DOT_DOT: return "DASH_DOT_DOT";
    1280          16 :         case table::BorderLineStyle::DOUBLE_THIN: return "DOUBLE_THIN";
    1281          16 :         case table::BorderLineStyle::FINE_DASHED: return "FINE_DASHED";
    1282             :         default:
    1283             :             ;
    1284             :     }
    1285             : 
    1286           0 :     return "";
    1287             : }
    1288             : 
    1289             : }
    1290             : 
    1291           4 : void ScExportTest::testExcelCellBorders( sal_uLong nFormatType )
    1292             : {
    1293             :     struct
    1294             :     {
    1295             :         SCROW mnRow;
    1296             :         sal_Int16 mnStyle;
    1297             :         long mnWidth;
    1298             :     } aChecks[] = {
    1299             :         {  1, table::BorderLineStyle::SOLID,         1L }, // hair
    1300             :         {  3, table::BorderLineStyle::DOTTED,       15L }, // dotted
    1301             :         {  5, table::BorderLineStyle::DASH_DOT_DOT, 15L }, // dash dot dot
    1302             :         {  7, table::BorderLineStyle::DASH_DOT,     15L }, // dash dot
    1303             :         {  9, table::BorderLineStyle::FINE_DASHED,  15L }, // dashed
    1304             :         { 11, table::BorderLineStyle::SOLID,        15L }, // thin
    1305             :         { 13, table::BorderLineStyle::DASH_DOT_DOT, 35L }, // medium dash dot dot
    1306             :         { 17, table::BorderLineStyle::DASH_DOT,     35L }, // medium dash dot
    1307             :         { 19, table::BorderLineStyle::DASHED,       35L }, // medium dashed
    1308             :         { 21, table::BorderLineStyle::SOLID,        35L }, // medium
    1309             :         { 23, table::BorderLineStyle::SOLID,        50L }, // thick
    1310             :         { 25, table::BorderLineStyle::DOUBLE_THIN,  -1L }, // double (don't check width)
    1311           4 :     };
    1312             : 
    1313           4 :     ScDocShellRef xDocSh = loadDoc("cell-borders.", nFormatType);
    1314           4 :     CPPUNIT_ASSERT_MESSAGE("Failed to load file", xDocSh.Is());
    1315             :     {
    1316           4 :         ScDocument& rDoc = xDocSh->GetDocument();
    1317             : 
    1318          52 :         for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
    1319             :         {
    1320          48 :             const editeng::SvxBorderLine* pLine = NULL;
    1321          48 :             rDoc.GetBorderLines(2, aChecks[i].mnRow, 0, NULL, &pLine, NULL, NULL);
    1322          48 :             CPPUNIT_ASSERT(pLine);
    1323          48 :             CPPUNIT_ASSERT_EQUAL(toBorderName(aChecks[i].mnStyle), toBorderName(pLine->GetBorderLineStyle()));
    1324          48 :             if (aChecks[i].mnWidth >= 0)
    1325          44 :                 CPPUNIT_ASSERT_EQUAL(aChecks[i].mnWidth, pLine->GetWidth());
    1326             :         }
    1327             :     }
    1328             : 
    1329           8 :     ScDocShellRef xNewDocSh = saveAndReload(xDocSh, nFormatType);
    1330           4 :     xDocSh->DoClose();
    1331           4 :     ScDocument& rDoc = xNewDocSh->GetDocument();
    1332          52 :     for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
    1333             :     {
    1334          48 :         const editeng::SvxBorderLine* pLine = NULL;
    1335          48 :         rDoc.GetBorderLines(2, aChecks[i].mnRow, 0, NULL, &pLine, NULL, NULL);
    1336          48 :         CPPUNIT_ASSERT(pLine);
    1337          48 :         CPPUNIT_ASSERT_EQUAL(toBorderName(aChecks[i].mnStyle), toBorderName(pLine->GetBorderLineStyle()));
    1338          48 :         if (aChecks[i].mnWidth >= 0)
    1339          44 :             CPPUNIT_ASSERT_EQUAL(aChecks[i].mnWidth, pLine->GetWidth());
    1340             :     }
    1341             : 
    1342           8 :     xNewDocSh->DoClose();
    1343           4 : }
    1344             : 
    1345           2 : void ScExportTest::testCellBordersXLS()
    1346             : {
    1347           2 :     testExcelCellBorders(XLS);
    1348           2 : }
    1349             : 
    1350           2 : void ScExportTest::testCellBordersXLSX()
    1351             : {
    1352           2 :     testExcelCellBorders(XLSX);
    1353           2 : }
    1354             : 
    1355           0 : OUString toString( const ScBigRange& rRange )
    1356             : {
    1357           0 :     OUStringBuffer aBuf;
    1358           0 :     aBuf.appendAscii("(columns:");
    1359           0 :     aBuf.append(rRange.aStart.Col());
    1360           0 :     aBuf.append('-');
    1361           0 :     aBuf.append(rRange.aEnd.Col());
    1362           0 :     aBuf.appendAscii(";rows:");
    1363           0 :     aBuf.append(rRange.aStart.Row());
    1364           0 :     aBuf.append('-');
    1365           0 :     aBuf.append(rRange.aEnd.Row());
    1366           0 :     aBuf.appendAscii(";sheets:");
    1367           0 :     aBuf.append(rRange.aStart.Tab());
    1368           0 :     aBuf.append('-');
    1369           0 :     aBuf.append(rRange.aEnd.Tab());
    1370           0 :     aBuf.append(')');
    1371             : 
    1372           0 :     return aBuf.makeStringAndClear();
    1373             : }
    1374             : 
    1375           2 : void ScExportTest::testTrackChangesSimpleXLSX()
    1376             : {
    1377             :     struct CheckItem
    1378             :     {
    1379             :         sal_uLong mnActionId;
    1380             :         ScChangeActionType meType;
    1381             : 
    1382             :         sal_Int32 mnStartCol;
    1383             :         sal_Int32 mnStartRow;
    1384             :         sal_Int32 mnStartTab;
    1385             :         sal_Int32 mnEndCol;
    1386             :         sal_Int32 mnEndRow;
    1387             :         sal_Int32 mnEndTab;
    1388             : 
    1389             :         bool mbRowInsertedAtBottom;
    1390             :     };
    1391             : 
    1392             :     struct
    1393             :     {
    1394         104 :         bool checkRange( ScChangeActionType eType, const ScBigRange& rExpected, const ScBigRange& rActual )
    1395             :         {
    1396         104 :             ScBigRange aExpected(rExpected), aActual(rActual);
    1397             : 
    1398         104 :             switch (eType)
    1399             :             {
    1400             :                 case SC_CAT_INSERT_ROWS:
    1401             :                 {
    1402             :                     // Ignore columns.
    1403          48 :                     aExpected.aStart.SetCol(0);
    1404          48 :                     aExpected.aEnd.SetCol(0);
    1405          48 :                     aActual.aStart.SetCol(0);
    1406          48 :                     aActual.aEnd.SetCol(0);
    1407             :                 }
    1408          48 :                 break;
    1409             :                 default:
    1410             :                     ;
    1411             :             }
    1412             : 
    1413         104 :             return aExpected == aActual;
    1414             :         }
    1415             : 
    1416           8 :         bool check( ScDocument& rDoc )
    1417             :         {
    1418             :             CheckItem aChecks[] =
    1419             :             {
    1420             :                 {  1, SC_CAT_CONTENT     , 1, 1, 0, 1, 1, 0, false },
    1421             :                 {  2, SC_CAT_INSERT_ROWS , 0, 2, 0, 0, 2, 0, true },
    1422             :                 {  3, SC_CAT_CONTENT     , 1, 2, 0, 1, 2, 0, false },
    1423             :                 {  4, SC_CAT_INSERT_ROWS , 0, 3, 0, 0, 3, 0, true  },
    1424             :                 {  5, SC_CAT_CONTENT     , 1, 3, 0, 1, 3, 0, false },
    1425             :                 {  6, SC_CAT_INSERT_ROWS , 0, 4, 0, 0, 4, 0, true  },
    1426             :                 {  7, SC_CAT_CONTENT     , 1, 4, 0, 1, 4, 0, false },
    1427             :                 {  8, SC_CAT_INSERT_ROWS , 0, 5, 0, 0, 5, 0, true  },
    1428             :                 {  9, SC_CAT_CONTENT     , 1, 5, 0, 1, 5, 0, false },
    1429             :                 { 10, SC_CAT_INSERT_ROWS , 0, 6, 0, 0, 6, 0, true  },
    1430             :                 { 11, SC_CAT_CONTENT     , 1, 6, 0, 1, 6, 0, false },
    1431             :                 { 12, SC_CAT_INSERT_ROWS , 0, 7, 0, 0, 7, 0, true  },
    1432             :                 { 13, SC_CAT_CONTENT     , 1, 7, 0, 1, 7, 0, false },
    1433           8 :             };
    1434             : 
    1435           8 :             ScChangeTrack* pCT = rDoc.GetChangeTrack();
    1436           8 :             if (!pCT)
    1437             :             {
    1438           0 :                 cerr << "Change track instance doesn't exist." << endl;
    1439           0 :                 return false;
    1440             :             }
    1441             : 
    1442           8 :             sal_uLong nActionMax = pCT->GetActionMax();
    1443           8 :             if (nActionMax != 13)
    1444             :             {
    1445           0 :                 cerr << "Unexpected highest action ID value." << endl;
    1446           0 :                 return false;
    1447             :             }
    1448             : 
    1449         224 :             for (size_t i = 0, n = SAL_N_ELEMENTS(aChecks); i < n; ++i)
    1450             :             {
    1451         104 :                 sal_uInt16 nActId = aChecks[i].mnActionId;
    1452         104 :                 const ScChangeAction* pAction = pCT->GetAction(nActId);
    1453         104 :                 if (!pAction)
    1454             :                 {
    1455           0 :                     cerr << "No action for action number " << nActId << " found." << endl;
    1456           0 :                     return false;
    1457             :                 }
    1458             : 
    1459         104 :                 if (pAction->GetType() != aChecks[i].meType)
    1460             :                 {
    1461           0 :                     cerr << "Unexpected action type for action number " << nActId << "." << endl;
    1462           0 :                     return false;
    1463             :                 }
    1464             : 
    1465         104 :                 const ScBigRange& rRange = pAction->GetBigRange();
    1466             :                 ScBigRange aCheck(aChecks[i].mnStartCol, aChecks[i].mnStartRow, aChecks[i].mnStartTab,
    1467         104 :                                   aChecks[i].mnEndCol, aChecks[i].mnEndRow, aChecks[i].mnEndTab);
    1468             : 
    1469         104 :                 if (!checkRange(pAction->GetType(), aCheck, rRange))
    1470             :                 {
    1471           0 :                     cerr << "Unexpected range for action number " << nActId
    1472           0 :                         << ": expected=" << toString(aCheck) << " actual=" << toString(rRange) << endl;
    1473           0 :                     return false;
    1474             :                 }
    1475             : 
    1476         104 :                 switch (pAction->GetType())
    1477             :                 {
    1478             :                     case SC_CAT_INSERT_ROWS:
    1479             :                     {
    1480          48 :                         const ScChangeActionIns* p = static_cast<const ScChangeActionIns*>(pAction);
    1481          48 :                         if (p->IsEndOfList() != aChecks[i].mbRowInsertedAtBottom)
    1482             :                         {
    1483           0 :                             cerr << "Unexpected end-of-list flag for action number " << nActId << "." << endl;
    1484           0 :                             return false;
    1485             :                         }
    1486             :                     }
    1487          48 :                     break;
    1488             :                     default:
    1489             :                         ;
    1490             :                 }
    1491             :             }
    1492             : 
    1493           8 :             return true;
    1494             :         }
    1495             : 
    1496           4 :         bool checkRevisionUserAndTime( ScDocument& rDoc, const OUString& rOwnerName )
    1497             :         {
    1498           4 :             ScChangeTrack* pCT = rDoc.GetChangeTrack();
    1499           4 :             if (!pCT)
    1500             :             {
    1501           0 :                 cerr << "Change track instance doesn't exist." << endl;
    1502           0 :                 return false;
    1503             :             }
    1504             : 
    1505           4 :             ScChangeAction* pAction = pCT->GetLast();
    1506           4 :             if (pAction->GetUser() != "Kohei Yoshida")
    1507             :             {
    1508           0 :                 cerr << "Wrong user name." << endl;
    1509           0 :                 return false;
    1510             :             }
    1511             : 
    1512           4 :             DateTime aDT = pAction->GetDateTime();
    1513           4 :             if (aDT.GetYear() != 2014 || aDT.GetMonth() != 7 || aDT.GetDay() != 11)
    1514             :             {
    1515           0 :                 cerr << "Wrong time stamp." << endl;
    1516           0 :                 return false;
    1517             :             }
    1518             : 
    1519             :             // Insert a new record to make sure the user and date-time are correct.
    1520           4 :             rDoc.SetString(ScAddress(1,8,0), "New String");
    1521           4 :             ScCellValue aEmpty;
    1522           4 :             pCT->AppendContent(ScAddress(1,8,0), aEmpty);
    1523           4 :             pAction = pCT->GetLast();
    1524           4 :             if (!pAction)
    1525             :             {
    1526           0 :                 cerr << "Failed to retrieve last revision." << endl;
    1527           0 :                 return false;
    1528             :             }
    1529             : 
    1530           4 :             if (rOwnerName != pAction->GetUser())
    1531             :             {
    1532           0 :                 cerr << "Wrong user name." << endl;
    1533           0 :                 return false;
    1534             :             }
    1535             : 
    1536           4 :             DateTime aDTNew = pAction->GetDateTime();
    1537           4 :             if (aDTNew <= aDT)
    1538             :             {
    1539           0 :                 cerr << "Time stamp of the new revision should be more recent than that of the last revision." << endl;
    1540           0 :                 return false;
    1541             :             }
    1542             : 
    1543           4 :             return true;
    1544             :         }
    1545             : 
    1546             :     } aTest;
    1547             : 
    1548           2 :     SvtUserOptions& rUserOpt = SC_MOD()->GetUserOptions();
    1549           2 :     rUserOpt.SetToken(USER_OPT_FIRSTNAME, "Export");
    1550           2 :     rUserOpt.SetToken(USER_OPT_LASTNAME, "Test");
    1551             : 
    1552           2 :     OUString aOwnerName = rUserOpt.GetFirstName() + " " + rUserOpt.GetLastName();
    1553             : 
    1554             :     // First, test the xls variant.
    1555             : 
    1556           4 :     ScDocShellRef xDocSh = loadDoc("track-changes/simple-cell-changes.", XLS);
    1557           2 :     CPPUNIT_ASSERT(xDocSh.Is());
    1558           2 :     ScDocument* pDoc = &xDocSh->GetDocument();
    1559           2 :     bool bGood = aTest.check(*pDoc);
    1560           2 :     CPPUNIT_ASSERT_MESSAGE("Initial check failed (xls).", bGood);
    1561             : 
    1562           4 :     ScDocShellRef xDocSh2 = saveAndReload(xDocSh, XLS);
    1563           2 :     xDocSh->DoClose();
    1564           2 :     pDoc = &xDocSh2->GetDocument();
    1565           2 :     bGood = aTest.check(*pDoc);
    1566           2 :     CPPUNIT_ASSERT_MESSAGE("Check after reload failed (xls).", bGood);
    1567             : 
    1568             :     // fdo#81445 : Check the blank value string to make sure it's "<empty>".
    1569           2 :     ScChangeTrack* pCT = pDoc->GetChangeTrack();
    1570           2 :     CPPUNIT_ASSERT(pCT);
    1571           2 :     ScChangeAction* pAction = pCT->GetAction(1);
    1572           2 :     CPPUNIT_ASSERT(pAction);
    1573           4 :     OUString aDesc;
    1574           2 :     pAction->GetDescription(aDesc, pDoc);
    1575           2 :     CPPUNIT_ASSERT_EQUAL(OUString("Cell B2 changed from '<empty>' to '1'"), aDesc);
    1576             : 
    1577           2 :     bGood = aTest.checkRevisionUserAndTime(*pDoc, aOwnerName);
    1578           2 :     CPPUNIT_ASSERT_MESSAGE("Check revision and time failed after reload (xls).", bGood);
    1579             : 
    1580           2 :     xDocSh2->DoClose();
    1581             : 
    1582             :     // Now, test the xlsx variant the same way.
    1583             : 
    1584           2 :     xDocSh = loadDoc("track-changes/simple-cell-changes.", XLSX);
    1585           2 :     CPPUNIT_ASSERT(xDocSh.Is());
    1586           2 :     pDoc = &xDocSh->GetDocument();
    1587           2 :     aTest.check(*pDoc);
    1588           2 :     CPPUNIT_ASSERT_MESSAGE("Initial check failed (xlsx).", bGood);
    1589             : 
    1590           2 :     xDocSh2 = saveAndReload(xDocSh, XLSX);
    1591           2 :     xDocSh->DoClose();
    1592           2 :     pDoc = &xDocSh2->GetDocument();
    1593           2 :     bGood = aTest.check(*pDoc);
    1594           2 :     CPPUNIT_ASSERT_MESSAGE("Check after reload failed (xlsx).", bGood);
    1595             : 
    1596           2 :     bGood = aTest.checkRevisionUserAndTime(*pDoc, aOwnerName);
    1597           2 :     CPPUNIT_ASSERT_MESSAGE("Check revision and time failed after reload (xlsx).", bGood);
    1598             : 
    1599           4 :     xDocSh2->DoClose();
    1600           2 : }
    1601             : 
    1602           2 : void ScExportTest::testSheetTabColorsXLSX()
    1603             : {
    1604             :     struct
    1605             :     {
    1606           4 :         bool checkContent( ScDocument& rDoc )
    1607             :         {
    1608             : 
    1609           4 :             std::vector<OUString> aTabNames = rDoc.GetAllTableNames();
    1610             : 
    1611             :             // green, red, blue, yellow (from left to right).
    1612           4 :             if (aTabNames.size() != 4)
    1613             :             {
    1614           0 :                 cerr << "There should be exactly 4 sheets." << endl;
    1615           0 :                 return false;
    1616             :             }
    1617             : 
    1618           4 :             const char* pNames[] = { "Green", "Red", "Blue", "Yellow" };
    1619          20 :             for (size_t i = 0, n = SAL_N_ELEMENTS(pNames); i < n; ++i)
    1620             :             {
    1621          16 :                 OUString aExpected = OUString::createFromAscii(pNames[i]);
    1622          16 :                 if (aExpected != aTabNames[i])
    1623             :                 {
    1624           0 :                     cerr << "incorrect sheet name: expected='" << aExpected <<"', actual='" << aTabNames[i] << "'" << endl;
    1625           0 :                     return false;
    1626             :                 }
    1627          16 :             }
    1628             : 
    1629             :             const ColorData aXclColors[] =
    1630             :             {
    1631             :                 0x0000B050, // green
    1632             :                 0x00FF0000, // red
    1633             :                 0x000070C0, // blue
    1634             :                 0x00FFFF00, // yellow
    1635           4 :             };
    1636             : 
    1637          20 :             for (size_t i = 0, n = SAL_N_ELEMENTS(aXclColors); i < n; ++i)
    1638             :             {
    1639          16 :                 if (aXclColors[i] != rDoc.GetTabBgColor(i).GetColor())
    1640             :                 {
    1641           0 :                     cerr << "wrong sheet color for sheet " << i << endl;
    1642           0 :                     return false;
    1643             :                 }
    1644             :             }
    1645             : 
    1646           4 :             return true;
    1647             :         }
    1648             : 
    1649             :     } aTest;
    1650             : 
    1651           2 :     ScDocShellRef xDocSh = loadDoc("sheet-tab-color.", XLSX);
    1652             :     {
    1653           2 :         CPPUNIT_ASSERT_MESSAGE("Failed to load file.", xDocSh.Is());
    1654           2 :         ScDocument& rDoc = xDocSh->GetDocument();
    1655           2 :         bool bRes = aTest.checkContent(rDoc);
    1656           2 :         CPPUNIT_ASSERT_MESSAGE("Failed on the initial content check.", bRes);
    1657             :     }
    1658             : 
    1659           4 :     ScDocShellRef xDocSh2 = saveAndReload(xDocSh, XLSX);
    1660           2 :     CPPUNIT_ASSERT_MESSAGE("Failed to reload file.", xDocSh2.Is());
    1661           2 :     xDocSh->DoClose();
    1662           2 :     ScDocument& rDoc = xDocSh2->GetDocument();
    1663           2 :     bool bRes = aTest.checkContent(rDoc);
    1664           2 :     CPPUNIT_ASSERT_MESSAGE("Failed on the content check after reload.", bRes);
    1665             : 
    1666           4 :     xDocSh2->DoClose();
    1667           2 : }
    1668             : 
    1669           2 : void ScExportTest::testSharedFormulaExportXLS()
    1670             : {
    1671             :     struct
    1672             :     {
    1673           4 :         bool checkContent( ScDocument& rDoc )
    1674             :         {
    1675           4 :             formula::FormulaGrammar::Grammar eGram = formula::FormulaGrammar::GRAM_ENGLISH_XL_R1C1;
    1676           4 :             rDoc.SetGrammar(eGram);
    1677           4 :             sc::TokenStringContext aCxt(&rDoc, eGram);
    1678             : 
    1679             :             // Check the title row.
    1680             : 
    1681           8 :             OUString aActual = rDoc.GetString(0,1,0);
    1682           8 :             OUString aExpected = "Response";
    1683           4 :             if (aActual != aExpected)
    1684             :             {
    1685           0 :                 cerr << "Wrong content in A2: expected='" << aExpected << "', actual='" << aActual << "'" << endl;
    1686           0 :                 return false;
    1687             :             }
    1688             : 
    1689           4 :             aActual = rDoc.GetString(1,1,0);
    1690           4 :             aExpected = "Response";
    1691           4 :             if (aActual != aExpected)
    1692             :             {
    1693           0 :                 cerr << "Wrong content in B2: expected='" << aExpected << "', actual='" << aActual << "'" << endl;
    1694           0 :                 return false;
    1695             :             }
    1696             : 
    1697             :             // A3:A12 and B3:B12 are numbers from 1 to 10.
    1698          88 :             for (SCROW i = 0; i <= 9; ++i)
    1699             :             {
    1700          40 :                 double fExpected = i + 1.0;
    1701          40 :                 ScAddress aPos(0,i+2,0);
    1702          40 :                 double fActual = rDoc.GetValue(aPos);
    1703          40 :                 if (fExpected != fActual)
    1704             :                 {
    1705           0 :                     cerr << "Wrong value in A" << (i+2) << ": expected=" << fExpected << ", actual=" << fActual << endl;
    1706           0 :                     return false;
    1707             :                 }
    1708             : 
    1709          40 :                 aPos.IncCol();
    1710          40 :                 ScFormulaCell* pFC = rDoc.GetFormulaCell(aPos);
    1711          40 :                 if (!pFC)
    1712             :                 {
    1713           0 :                     cerr << "B" << (i+2) << " should be a formula cell." << endl;
    1714           0 :                     return false;
    1715             :                 }
    1716             : 
    1717          40 :                 OUString aFormula = pFC->GetCode()->CreateString(aCxt, aPos);
    1718          40 :                 aExpected = "Coefficients!RC[-1]";
    1719          40 :                 if (aFormula != aExpected)
    1720             :                 {
    1721           0 :                     cerr << "Wrong formula in B" << (i+2) << ": expected='" << aExpected << "', actual='" << aFormula << "'" << endl;
    1722           0 :                     return false;
    1723             :                 }
    1724             : 
    1725          40 :                 fActual = rDoc.GetValue(aPos);
    1726          40 :                 if (fExpected != fActual)
    1727             :                 {
    1728           0 :                     cerr << "Wrong value in B" << (i+2) << ": expected=" << fExpected << ", actual=" << fActual << endl;
    1729           0 :                     return false;
    1730             :                 }
    1731          40 :             }
    1732             : 
    1733           8 :             return true;
    1734             :         }
    1735             : 
    1736             :     } aTest;
    1737             : 
    1738           2 :     ScDocShellRef xDocSh = loadDoc("shared-formula/3d-reference.", ODS);
    1739             :     {
    1740           2 :         CPPUNIT_ASSERT_MESSAGE("Failed to load file.", xDocSh.Is());
    1741           2 :         ScDocument& rDoc = xDocSh->GetDocument();
    1742             : 
    1743             :         // Check the content of the original.
    1744           2 :         bool bRes = aTest.checkContent(rDoc);
    1745           2 :         CPPUNIT_ASSERT_MESSAGE("Content check on the original document failed.", bRes);
    1746             :     }
    1747             : 
    1748           4 :     ScDocShellRef xDocSh2 = saveAndReload(xDocSh, XLS);
    1749           2 :     xDocSh->DoClose();
    1750           2 :     CPPUNIT_ASSERT_MESSAGE("Failed to reload file.", xDocSh2.Is());
    1751             : 
    1752           2 :     ScDocument& rDoc = xDocSh2->GetDocument();
    1753             : 
    1754             :     // Check the content of the reloaded. This should be identical.
    1755           2 :     bool bRes = aTest.checkContent(rDoc);
    1756           2 :     CPPUNIT_ASSERT_MESSAGE("Content check on the reloaded document failed.", bRes);
    1757             : 
    1758           4 :     xDocSh2->DoClose();
    1759           2 : }
    1760             : 
    1761           2 : void ScExportTest::testSharedFormulaExportXLSX()
    1762             : {
    1763             :     struct
    1764             :     {
    1765           6 :         bool checkContent( ScDocument& rDoc )
    1766             :         {
    1767           6 :             SCTAB nTabCount = rDoc.GetTableCount();
    1768           6 :             if (nTabCount != 2)
    1769             :             {
    1770           0 :                 cerr << "Document should have exactly 2 sheets.  " << nTabCount << " found." << endl;
    1771           0 :                 return false;
    1772             :             }
    1773             : 
    1774             :             // Make sure the sheet tab colors are not set.
    1775          18 :             for (SCROW i = 0; i <= 1; ++i)
    1776             :             {
    1777          12 :                 Color aTabBgColor = rDoc.GetTabBgColor(i);
    1778          12 :                 if (aTabBgColor != Color(COL_AUTO))
    1779             :                 {
    1780           0 :                     cerr << "The tab color of Sheet " << (i+1) << " should not be explicitly set." << endl;
    1781           0 :                     return false;
    1782             :                 }
    1783             :             }
    1784             : 
    1785             :             // B2:B7 should show 1,2,3,4,5,6.
    1786           6 :             double fExpected = 1.0;
    1787          42 :             for (SCROW i = 1; i <= 6; ++i, ++fExpected)
    1788             :             {
    1789          36 :                 ScAddress aPos(1,i,0);
    1790          36 :                 double fVal = rDoc.GetValue(aPos);
    1791          36 :                 if (fVal != fExpected)
    1792             :                 {
    1793           0 :                     cerr << "Wrong value in B" << (i+1) << ": expected=" << fExpected << ", actual=" << fVal << endl;
    1794           0 :                     return false;
    1795             :                 }
    1796             :             }
    1797             : 
    1798             :             // C2:C7 should show 10,20,....,60.
    1799           6 :             fExpected = 10.0;
    1800          42 :             for (SCROW i = 1; i <= 6; ++i, fExpected+=10.0)
    1801             :             {
    1802          36 :                 ScAddress aPos(2,i,0);
    1803          36 :                 double fVal = rDoc.GetValue(aPos);
    1804          36 :                 if (fVal != fExpected)
    1805             :                 {
    1806           0 :                     cerr << "Wrong value in C" << (i+1) << ": expected=" << fExpected << ", actual=" << fVal << endl;
    1807           0 :                     return false;
    1808             :                 }
    1809             :             }
    1810             : 
    1811             :             // D2:D7 should show 1,2,...,6.
    1812           6 :             fExpected = 1.0;
    1813          42 :             for (SCROW i = 1; i <= 6; ++i, ++fExpected)
    1814             :             {
    1815          36 :                 ScAddress aPos(3,i,0);
    1816          36 :                 double fVal = rDoc.GetValue(aPos);
    1817          36 :                 if (fVal != fExpected)
    1818             :                 {
    1819           0 :                     cerr << "Wrong value in D" << (i+1) << ": expected=" << fExpected << ", actual=" << fVal << endl;
    1820           0 :                     return false;
    1821             :                 }
    1822             :             }
    1823             : 
    1824           6 :             return true;
    1825             :         }
    1826             : 
    1827             :     } aTest;
    1828             : 
    1829           2 :     ScDocShellRef xDocSh = loadDoc("shared-formula/3d-reference.", XLSX);
    1830             :     {
    1831           2 :         CPPUNIT_ASSERT_MESSAGE("Failed to load file.", xDocSh.Is());
    1832           2 :         ScDocument& rDoc = xDocSh->GetDocument();
    1833             : 
    1834           2 :         bool bRes = aTest.checkContent(rDoc);
    1835           2 :         CPPUNIT_ASSERT_MESSAGE("Content check on the initial document failed.", bRes);
    1836             : 
    1837           2 :         rDoc.CalcAll(); // Recalculate to flush all cached results.
    1838           2 :         bRes = aTest.checkContent(rDoc);
    1839           2 :         CPPUNIT_ASSERT_MESSAGE("Content check on the initial recalculated document failed.", bRes);
    1840             :     }
    1841             : 
    1842             :     // Save and reload, and check the content again.
    1843           4 :     ScDocShellRef xDocSh2 = saveAndReload(xDocSh, XLSX);
    1844           2 :     xDocSh->DoClose();
    1845             : 
    1846           2 :     CPPUNIT_ASSERT_MESSAGE("Failed to load file.", xDocSh2.Is());
    1847           2 :     ScDocument& rDoc = xDocSh2->GetDocument();
    1848           2 :     rDoc.CalcAll(); // Recalculate to flush all cached results.
    1849             : 
    1850           2 :     bool bRes = aTest.checkContent(rDoc);
    1851           2 :     CPPUNIT_ASSERT_MESSAGE("Content check on the reloaded document failed.", bRes);
    1852             : 
    1853           4 :     xDocSh2->DoClose();
    1854           2 : }
    1855             : 
    1856           2 : void ScExportTest::testSharedFormulaStringResultExportXLSX()
    1857             : {
    1858             :     struct
    1859             :     {
    1860           6 :         bool checkContent( ScDocument& rDoc )
    1861             :         {
    1862             :             {
    1863             :                 // B2:B7 should show A,B,....,F.
    1864           6 :                 const char* expected[] = { "A", "B", "C", "D", "E", "F" };
    1865          42 :                 for (SCROW i = 0; i <= 5; ++i)
    1866             :                 {
    1867          36 :                     ScAddress aPos(1,i+1,0);
    1868          36 :                     OUString aStr = rDoc.GetString(aPos);
    1869          72 :                     OUString aExpected = OUString::createFromAscii(expected[i]);
    1870          36 :                     if (aStr != aExpected)
    1871             :                     {
    1872           0 :                         cerr << "Wrong value in B" << (i+2) << ": expected='" << aExpected << "', actual='" << aStr << "'" << endl;
    1873           0 :                         return false;
    1874             :                     }
    1875          36 :                 }
    1876             :             }
    1877             : 
    1878             :             {
    1879             :                 // C2:C7 should show AA,BB,....,FF.
    1880           6 :                 const char* expected[] = { "AA", "BB", "CC", "DD", "EE", "FF" };
    1881          42 :                 for (SCROW i = 0; i <= 5; ++i)
    1882             :                 {
    1883          36 :                     ScAddress aPos(2,i+1,0);
    1884          36 :                     OUString aStr = rDoc.GetString(aPos);
    1885          72 :                     OUString aExpected = OUString::createFromAscii(expected[i]);
    1886          36 :                     if (aStr != aExpected)
    1887             :                     {
    1888           0 :                         cerr << "Wrong value in C" << (i+2) << ": expected='" << aExpected << "', actual='" << aStr << "'" << endl;
    1889           0 :                         return false;
    1890             :                     }
    1891          36 :                 }
    1892             :             }
    1893             : 
    1894           6 :             return true;
    1895             :         }
    1896             : 
    1897             :     } aTest;
    1898             : 
    1899           2 :     ScDocShellRef xDocSh = loadDoc("shared-formula/text-results.", XLSX);
    1900             :     {
    1901           2 :         CPPUNIT_ASSERT_MESSAGE("Failed to load file.", xDocSh.Is());
    1902           2 :         ScDocument& rDoc = xDocSh->GetDocument();
    1903             : 
    1904             :         // Check content without re-calculation, to test cached formula results.
    1905           2 :         bool bRes = aTest.checkContent(rDoc);
    1906           2 :         CPPUNIT_ASSERT_MESSAGE("Content check on the initial document failed.", bRes);
    1907             : 
    1908             :         // Now, re-calculate and check the results.
    1909           2 :         rDoc.CalcAll();
    1910           2 :         bRes = aTest.checkContent(rDoc);
    1911           2 :         CPPUNIT_ASSERT_MESSAGE("Content check on the initial recalculated document failed.", bRes);
    1912             :     }
    1913             :     // Reload and check again.
    1914           4 :     ScDocShellRef xDocSh2 = saveAndReload(xDocSh, XLSX);
    1915           2 :     xDocSh->DoClose();
    1916           2 :     CPPUNIT_ASSERT_MESSAGE("Failed to re-load file.", xDocSh2.Is());
    1917           2 :     ScDocument& rDoc = xDocSh2->GetDocument();
    1918             : 
    1919           2 :     bool bRes = aTest.checkContent(rDoc);
    1920           2 :     CPPUNIT_ASSERT_MESSAGE("Content check on the reloaded document failed.", bRes);
    1921             : 
    1922           4 :     xDocSh2->DoClose();
    1923           2 : }
    1924             : 
    1925           4 : void ScExportTest::testFunctionsExcel2010( sal_uLong nFormatType )
    1926             : {
    1927           4 :     ScDocShellRef xShell = loadDoc("functions-excel-2010.", XLSX);
    1928           4 :     CPPUNIT_ASSERT_MESSAGE("Failed to load the document.", xShell.Is());
    1929             : 
    1930           8 :     ScDocShellRef xDocSh = saveAndReload(xShell, nFormatType);
    1931           4 :     ScDocument& rDoc = xDocSh->GetDocument();
    1932           4 :     rDoc.CalcAll(); // perform hard re-calculation.
    1933             : 
    1934           4 :     testFunctionsExcel2010_Impl(rDoc);
    1935             : 
    1936           8 :     xDocSh->DoClose();
    1937           4 : }
    1938             : 
    1939           2 : void ScExportTest::testFunctionsExcel2010XLSX()
    1940             : {
    1941           2 :     testFunctionsExcel2010(XLSX);
    1942           2 : }
    1943             : 
    1944           2 : void ScExportTest::testFunctionsExcel2010XLS()
    1945             : {
    1946           2 :     testFunctionsExcel2010(XLS);
    1947           2 : }
    1948             : 
    1949           2 : void ScExportTest::testRelativePaths()
    1950             : {
    1951           2 :     ScDocShellRef xDocSh = loadDoc("fdo79305.", ODS);
    1952           2 :     CPPUNIT_ASSERT(xDocSh.Is());
    1953             : 
    1954           2 :     xmlDocPtr pDoc = XPathHelper::parseExport(&(*xDocSh), m_xSFactory, "content.xml", ODS);
    1955           2 :     CPPUNIT_ASSERT(pDoc);
    1956             :     OUString aURL = getXPath(pDoc,
    1957           4 :             "/office:document-content/office:body/office:spreadsheet/table:table/table:table-row[2]/table:table-cell[2]/text:p/text:a", "href");
    1958             :     // make sure that the URL is relative
    1959           4 :     CPPUNIT_ASSERT(aURL.startsWith(".."));
    1960           2 : }
    1961             : 
    1962             : namespace {
    1963             : 
    1964           4 : void testSheetProtection_Impl(ScDocument& rDoc)
    1965             : {
    1966           4 :     CPPUNIT_ASSERT(rDoc.IsTabProtected(0));
    1967           4 :     ScTableProtection* pTabProtection = rDoc.GetTabProtection(0);
    1968           4 :     CPPUNIT_ASSERT(pTabProtection);
    1969           4 :     CPPUNIT_ASSERT(pTabProtection->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS));
    1970           4 :     CPPUNIT_ASSERT(!pTabProtection->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS));
    1971           4 : }
    1972             : 
    1973             : }
    1974             : 
    1975           2 : void ScExportTest::testSheetProtection()
    1976             : {
    1977           2 :     ScDocShellRef xDocSh = loadDoc("sheet-protection.", ODS);
    1978           2 :     CPPUNIT_ASSERT(xDocSh.Is());
    1979             : 
    1980             :     {
    1981           2 :         ScDocument& rDoc = xDocSh->GetDocument();
    1982           2 :         testSheetProtection_Impl(rDoc);
    1983             :     }
    1984             : 
    1985           4 :     ScDocShellRef xDocSh2 = saveAndReload(xDocSh, ODS);
    1986             :     {
    1987           2 :         ScDocument& rDoc = xDocSh2->GetDocument();
    1988           2 :         testSheetProtection_Impl(rDoc);
    1989             :     }
    1990             : 
    1991           4 :     xDocSh2->DoClose();
    1992           2 : }
    1993             : 
    1994           2 : void ScExportTest::testPivotTableXLSX()
    1995             : {
    1996             :     struct
    1997             :     {
    1998           4 :         bool check( const ScDocument& rDoc )
    1999             :         {
    2000           4 :             if (!rDoc.HasPivotTable())
    2001             :             {
    2002           0 :                 cerr << "The document should have pivot table." << endl;
    2003           0 :                 return false;
    2004             :             }
    2005             : 
    2006           4 :             const ScDPCollection* pDPs = rDoc.GetDPCollection();
    2007           4 :             if (!pDPs)
    2008             :             {
    2009           0 :                 cerr << "Pivot table container should exist." << endl;
    2010           0 :                 return false;
    2011             :             }
    2012             : 
    2013           4 :             ScRange aSrcRange(0,0,0,9,2,0); // A1:J3 on Sheet1.
    2014           4 :             const ScDPCache* pCache = pDPs->GetSheetCaches().getExistingCache(aSrcRange);
    2015           4 :             if (!pCache)
    2016             :             {
    2017           0 :                 cerr << "The document should have a pivot cache for A1:J3 on Sheet1." << endl;
    2018           0 :                 return false;
    2019             :             }
    2020             : 
    2021             :             // Cache should have fields from F1 through F10.
    2022             : 
    2023             :             const char* pNames[] = {
    2024             :                 "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10"
    2025           4 :             };
    2026             : 
    2027           4 :             size_t nCount = pCache->GetFieldCount();
    2028           4 :             if (nCount != SAL_N_ELEMENTS(pNames))
    2029             :             {
    2030           0 :                 cout << "Incorrect number of fields in pivot cache." << endl;
    2031           0 :                 return false;
    2032             :             }
    2033             : 
    2034          44 :             for (size_t i = 0; i < nCount; ++i)
    2035             :             {
    2036          40 :                 OUString aCacheName = pCache->GetDimensionName(i);
    2037          40 :                 if (aCacheName != OUString::createFromAscii(pNames[i]))
    2038             :                 {
    2039           0 :                     cerr << "Field " << i << " has label '" << aCacheName << "' but expected '" << pNames[i] << "'" << endl;
    2040           0 :                     return false;
    2041             :                 }
    2042          40 :             }
    2043             : 
    2044           4 :             const ScDPObject* pDPObj = rDoc.GetDPAtCursor(0,10,0); // A11
    2045           4 :             if (!pDPObj)
    2046             :             {
    2047           0 :                 cerr << "A pivot table should exist over A11." << endl;
    2048           0 :                 return false;
    2049             :             }
    2050             : 
    2051             :             // Output range should be A8:D15.
    2052           4 :             ScRange aOutRange = pDPObj->GetOutRange();
    2053           4 :             if (ScRange(0,7,0,3,14,0) != aOutRange)
    2054             :             {
    2055           0 :                 cerr << "Incorrect output range." << endl;
    2056           0 :                 return false;
    2057             :             }
    2058             : 
    2059             :             // Row field - F1
    2060             :             // Column field - F4
    2061             :             // Page fields - F7 and F6
    2062             :             // Data field - F10
    2063             : 
    2064           4 :             const ScDPSaveData* pSaveData = pDPObj->GetSaveData();
    2065           4 :             if (!pSaveData)
    2066             :             {
    2067           0 :                 cerr << "Save data should exist in each pivot table object." << endl;
    2068           0 :                 return false;
    2069             :             }
    2070             : 
    2071           4 :             std::vector<const ScDPSaveDimension*> aDims;
    2072           4 :             pSaveData->GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_ROW, aDims);
    2073           4 :             if (aDims.size() != 1 || aDims[0]->GetName() != "F1")
    2074             :             {
    2075           0 :                 cerr << "Pivot table should have one row field labeld 'F1'" << endl;
    2076           0 :                 return false;
    2077             :             }
    2078             : 
    2079           4 :             pSaveData->GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_COLUMN, aDims);
    2080           4 :             if (aDims.size() != 1 || aDims[0]->GetName() != "F4")
    2081             :             {
    2082           0 :                 cerr << "Pivot table should have one column field labeld 'F4'" << endl;
    2083           0 :                 return false;
    2084             :             }
    2085             : 
    2086           4 :             pSaveData->GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_PAGE, aDims);
    2087           4 :             if (aDims.size() != 2 || aDims[0]->GetName() != "F7" || aDims[1]->GetName() != "F6")
    2088             :             {
    2089           0 :                 cerr << "Pivot table should have two page fields labeld 'F7' and 'F6' in this order." << endl;
    2090           0 :                 return false;
    2091             :             }
    2092             : 
    2093           4 :             pSaveData->GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_DATA, aDims);
    2094           4 :             if (aDims.size() != 1 || aDims[0]->GetName() != "F10")
    2095             :             {
    2096           0 :                 cerr << "Pivot table should have one data field labeld 'F10'" << endl;
    2097           0 :                 return false;
    2098             :             }
    2099             : 
    2100           4 :             const ScDPSaveDimension* pDim = aDims[0];
    2101           4 :             if (pDim->GetFunction() != sheet::GeneralFunction_SUM)
    2102             :             {
    2103           0 :                 cerr << "Data field should have SUM function." << endl;
    2104           0 :                 return false;
    2105             :             }
    2106             : 
    2107           4 :             return true;
    2108             :         }
    2109             : 
    2110             :     } aTest;
    2111             : 
    2112           2 :     ScDocShellRef xDocSh = loadDoc("pivot-table/many-fields-in-cache.", XLSX);
    2113           2 :     CPPUNIT_ASSERT(xDocSh.Is());
    2114           2 :     ScDocument* pDoc = &xDocSh->GetDocument();
    2115             : 
    2116             :     // Initial check.
    2117           2 :     bool bCheck = aTest.check(*pDoc);
    2118           2 :     CPPUNIT_ASSERT_MESSAGE("Initial check failed.", bCheck);
    2119             : 
    2120           4 :     ScDocShellRef xDocSh2 = saveAndReload(xDocSh, XLSX);
    2121           2 :     xDocSh->DoClose();
    2122           2 :     CPPUNIT_ASSERT(xDocSh2.Is());
    2123           2 :     pDoc = &xDocSh2->GetDocument();
    2124             : 
    2125             :     // Reload check.
    2126           2 :     bCheck = aTest.check(*pDoc);
    2127           2 :     CPPUNIT_ASSERT_MESSAGE("Reload check failed.", bCheck);
    2128             : 
    2129           4 :     xDocSh2->DoClose();
    2130           2 : }
    2131             : 
    2132           2 : void ScExportTest::testPivotTableTwoDataFieldsXLSX()
    2133             : {
    2134             :     struct
    2135             :     {
    2136           4 :         bool check( const ScDocument& rDoc )
    2137             :         {
    2138           4 :             if (!rDoc.HasPivotTable())
    2139             :             {
    2140           0 :                 cerr << "The document should have pivot table." << endl;
    2141           0 :                 return false;
    2142             :             }
    2143             : 
    2144           4 :             const ScDPCollection* pDPs = rDoc.GetDPCollection();
    2145           4 :             if (!pDPs)
    2146             :             {
    2147           0 :                 cerr << "Pivot table container should exist." << endl;
    2148           0 :                 return false;
    2149             :             }
    2150             : 
    2151           4 :             ScRange aSrcRange(1,1,1,2,8,1); // B2:C9 on the 2nd sheet.
    2152           4 :             const ScDPCache* pCache = pDPs->GetSheetCaches().getExistingCache(aSrcRange);
    2153           4 :             if (!pCache)
    2154             :             {
    2155           0 :                 cerr << "The document should have a pivot cache for B2:C9 on 'Src'." << endl;
    2156           0 :                 return false;
    2157             :             }
    2158             : 
    2159           4 :             const char* pNames[] = { "Name", "Value" };
    2160             :             (void) pNames;
    2161             : 
    2162           4 :             size_t nCount = pCache->GetFieldCount();
    2163           4 :             if (nCount != SAL_N_ELEMENTS(pNames))
    2164             :             {
    2165           0 :                 cout << "Incorrect number of fields in pivot cache." << endl;
    2166           0 :                 return false;
    2167             :             }
    2168             : 
    2169           4 :             const ScDPObject* pDPObj = rDoc.GetDPAtCursor(0,2,0); // A3
    2170           4 :             if (!pDPObj)
    2171             :             {
    2172           0 :                 cerr << "A pivot table should exist over A3." << endl;
    2173           0 :                 return false;
    2174             :             }
    2175             : 
    2176             :             // Output range should be A3:C12.
    2177           4 :             ScRange aOutRange = pDPObj->GetOutRange();
    2178           4 :             if (ScRange(0,2,0,2,11,0) != aOutRange)
    2179             :             {
    2180           0 :                 cerr << "Incorrect output range." << endl;
    2181           0 :                 return false;
    2182             :             }
    2183             : 
    2184           4 :             const ScDPSaveData* pSaveData = pDPObj->GetSaveData();
    2185           4 :             if (!pSaveData)
    2186             :             {
    2187           0 :                 cerr << "Save data should exist in each pivot table object." << endl;
    2188           0 :                 return false;
    2189             :             }
    2190             : 
    2191           4 :             std::vector<const ScDPSaveDimension*> aDims;
    2192           4 :             pSaveData->GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_ROW, aDims);
    2193           4 :             if (aDims.size() != 1 || aDims[0]->GetName() != "Name")
    2194             :             {
    2195           0 :                 cerr << "Pivot table should have one row field labeld 'Name'" << endl;
    2196           0 :                 return false;
    2197             :             }
    2198             : 
    2199           4 :             pSaveData->GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_DATA, aDims);
    2200          20 :             if (aDims.size() != 2 ||
    2201          28 :                 ScDPUtil::getSourceDimensionName(aDims[0]->GetName()) != "Value" ||
    2202          12 :                 ScDPUtil::getSourceDimensionName(aDims[1]->GetName()) != "Value")
    2203             :             {
    2204           0 :                 cerr << "Pivot table should have two duplicated data fields both of which are named 'Value'." << endl;
    2205           0 :                 return false;
    2206             :             }
    2207             : 
    2208           4 :             if (aDims[0]->GetFunction() != sheet::GeneralFunction_SUM)
    2209             :             {
    2210           0 :                 cerr << "First data field should be SUM." << endl;
    2211           0 :                 return false;
    2212             :             }
    2213             : 
    2214           4 :             if (aDims[1]->GetFunction() != sheet::GeneralFunction_COUNT)
    2215             :             {
    2216           0 :                 cerr << "First data field should be COUNT." << endl;
    2217           0 :                 return false;
    2218             :             }
    2219             : 
    2220           4 :             pSaveData->GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_COLUMN, aDims);
    2221           4 :             if (aDims.size() != 1 || !aDims[0]->IsDataLayout())
    2222             :             {
    2223           0 :                 cerr << "Pivot table should have one column field which is a data layout field." << endl;
    2224           0 :                 return false;
    2225             :             }
    2226             : 
    2227           4 :             return true;
    2228             :         }
    2229             : 
    2230             :     } aTest;
    2231             : 
    2232           2 :     ScDocShellRef xDocSh = loadDoc("pivot-table/two-data-fields.", XLSX);
    2233           2 :     CPPUNIT_ASSERT(xDocSh.Is());
    2234           2 :     ScDocument* pDoc = &xDocSh->GetDocument();
    2235             : 
    2236             :     // Initial check.
    2237           2 :     bool bCheck = aTest.check(*pDoc);
    2238           2 :     CPPUNIT_ASSERT_MESSAGE("Initial check failed.", bCheck);
    2239             : 
    2240           4 :     ScDocShellRef xDocSh2 = saveAndReload(xDocSh, XLSX);
    2241           2 :     xDocSh->DoClose();
    2242           2 :     CPPUNIT_ASSERT(xDocSh2.Is());
    2243           2 :     pDoc = &xDocSh2->GetDocument();
    2244             : 
    2245             :     // Reload check.
    2246           2 :     bCheck = aTest.check(*pDoc);
    2247           2 :     CPPUNIT_ASSERT_MESSAGE("Reload check failed.", bCheck);
    2248             : 
    2249           4 :     xDocSh2->DoClose();
    2250           2 : }
    2251             : 
    2252           2 : void ScExportTest::testFunctionsExcel2010ODS()
    2253             : {
    2254             :     //testFunctionsExcel2010(ODS);
    2255           2 : }
    2256             : 
    2257          70 : ScExportTest::ScExportTest()
    2258          70 :       : ScBootstrapFixture("/sc/qa/unit/data")
    2259             : {
    2260          70 : }
    2261             : 
    2262          70 : void ScExportTest::setUp()
    2263             : {
    2264          70 :     test::BootstrapFixture::setUp();
    2265             : 
    2266             :     // This is a bit of a fudge, we do this to ensure that ScGlobals::ensure,
    2267             :     // which is a private symbol to us, gets called
    2268         140 :     m_xCalcComponent =
    2269         210 :         getMultiServiceFactory()->createInstance("com.sun.star.comp.Calc.SpreadsheetDocument");
    2270          70 :     CPPUNIT_ASSERT_MESSAGE("no calc component!", m_xCalcComponent.is());
    2271          70 : }
    2272             : 
    2273          70 : void ScExportTest::tearDown()
    2274             : {
    2275          70 :     uno::Reference< lang::XComponent >( m_xCalcComponent, UNO_QUERY_THROW )->dispose();
    2276          70 :     test::BootstrapFixture::tearDown();
    2277          70 : }
    2278             : 
    2279           2 : void ScExportTest::testSupBookVirtualPath()
    2280             : {
    2281           2 :     ScDocShellRef xShell = loadDoc("external-ref.", XLS);
    2282           2 :     CPPUNIT_ASSERT(xShell.Is());
    2283             : 
    2284           4 :     ScDocShellRef xDocSh = saveAndReload(xShell, XLS);
    2285           2 :     xShell->DoClose();
    2286           2 :     CPPUNIT_ASSERT(xDocSh.Is());
    2287             : 
    2288           2 :     ScDocument& rDoc = xDocSh->GetDocument();
    2289             : 
    2290           2 :     if (!checkFormula(rDoc, ScAddress(0,0,0), "'file:///home/timar/Documents/external.xls'#$Sheet1.A1"))
    2291           0 :         CPPUNIT_FAIL("Wrong SupBook VirtualPath URL");
    2292             : 
    2293           4 :     xDocSh->DoClose();
    2294           2 : }
    2295             : 
    2296           2 : CPPUNIT_TEST_SUITE_REGISTRATION(ScExportTest);
    2297             : 
    2298           8 : CPPUNIT_PLUGIN_IMPLEMENT();
    2299             : 
    2300             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10