LCOV - code coverage report
Current view: top level - sc/source/filter/excel - xilink.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 383 0.0 %
Date: 2014-04-14 Functions: 0 73 0.0 %
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             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "xilink.hxx"
      21             : #include "document.hxx"
      22             : #include "formulacell.hxx"
      23             : #include "scextopt.hxx"
      24             : #include "tablink.hxx"
      25             : #include "xistream.hxx"
      26             : #include "xihelper.hxx"
      27             : #include "xiname.hxx"
      28             : #include "excform.hxx"
      29             : #include "tokenarray.hxx"
      30             : #include "externalrefmgr.hxx"
      31             : #include "scmatrix.hxx"
      32             : #include "svl/sharedstringpool.hxx"
      33             : 
      34             : #include <vector>
      35             : #include <boost/ptr_container/ptr_vector.hpp>
      36             : 
      37             : using ::std::vector;
      38             : 
      39             : // *** Helper classes ***
      40             : 
      41             : 
      42             : // Cached external cells ======================================================
      43             : 
      44             : /**
      45             :  * Contains the address and value of an external referenced cell.
      46             :  * Note that this is non-copyable, so cannot be used in most stl/boost containers.
      47             :  */
      48           0 : class XclImpCrn : public XclImpCachedValue
      49             : {
      50             : public:
      51             :     /** Reads a cached value and stores it with its cell address. */
      52             :     explicit            XclImpCrn( XclImpStream& rStrm, const XclAddress& rXclPos );
      53             : 
      54             :     const XclAddress&   GetAddress() const;
      55             : 
      56             : private:
      57             :     XclAddress          maXclPos;       /// Excel position of the cached cell.
      58             : };
      59             : 
      60             : // Sheet in an external document ==============================================
      61             : 
      62             : /** Contains the name and sheet index of one sheet in an external document. */
      63             : class XclImpSupbookTab
      64             : {
      65             : public:
      66             :     /** Stores the sheet name and marks the sheet index as invalid.
      67             :         The sheet index is set while creating the Calc sheet with CreateTable(). */
      68             :     explicit            XclImpSupbookTab( const OUString& rTabName );
      69             :                         ~XclImpSupbookTab();
      70             : 
      71           0 :     inline const OUString& GetTabName() const { return maTabName; }
      72             : 
      73             :     /** Reads a CRN record (external referenced cell) at the specified address. */
      74             :     void                ReadCrn( XclImpStream& rStrm, const XclAddress& rXclPos );
      75             : 
      76             :     void                LoadCachedValues(ScExternalRefCache::TableTypeRef pCacheTable);
      77             : 
      78             : private:
      79             :     typedef boost::shared_ptr< XclImpCrn > XclImpCrnRef;
      80             :     typedef std::vector< XclImpCrnRef > XclImpCrnList;
      81             : 
      82             :     XclImpCrnList       maCrnList;      /// List of CRN records (cached cell values).
      83             :     OUString            maTabName;      /// Name of the external sheet.
      84             : };
      85             : 
      86             : // External document (SUPBOOK) ================================================
      87             : 
      88             : /** This class represents an external linked document (record SUPBOOK).
      89             :     @descr  Contains a list of all referenced sheets in the document. */
      90           0 : class XclImpSupbook : protected XclImpRoot
      91             : {
      92             : public:
      93             :     /** Reads the SUPBOOK record from stream. */
      94             :     explicit            XclImpSupbook( XclImpStream& rStrm );
      95             : 
      96             :     /** Reads an XCT record (count of following CRNs and current sheet). */
      97             :     void                ReadXct( XclImpStream& rStrm );
      98             :     /** Reads a CRN record (external referenced cell). */
      99             :     void                ReadCrn( XclImpStream& rStrm );
     100             :     /** Reads an EXTERNNAME record. */
     101             :     void                ReadExternname( XclImpStream& rStrm, ExcelToSc* pFormulaConv = NULL );
     102             : 
     103             :     /** Returns the SUPBOOK record type. */
     104           0 :     inline XclSupbookType GetType() const { return meType; }
     105             : 
     106             :     /** Returns the URL of the external document. */
     107           0 :     inline const OUString& GetXclUrl() const { return maXclUrl; }
     108             : 
     109             :     /** Returns the external name specified by an index from the Excel document (one-based). */
     110             :     const XclImpExtName* GetExternName( sal_uInt16 nXclIndex ) const;
     111             :     /** Tries to decode the URL to OLE or DDE link components.
     112             :         @descr  For DDE links: Decodes to application name and topic.
     113             :         For OLE object links: Decodes to class name and document URL.
     114             :         @return  true = decoding was successful, returned strings are valid (not empty). */
     115             :     bool                GetLinkData( OUString& rApplic, OUString& rDoc ) const;
     116             :     /** Returns the specified macro name (1-based) or an empty string on error. */
     117             :     const OUString&     GetMacroName( sal_uInt16 nXclNameIdx ) const;
     118             : 
     119             :     const OUString&     GetTabName( sal_uInt16 nXtiTab ) const;
     120             : 
     121             :     sal_uInt16          GetTabCount() const;
     122             : 
     123             :     void                LoadCachedValues();
     124             : 
     125             :     svl::SharedStringPool& GetSharedStringPool();
     126             : 
     127             : private:
     128             :     typedef boost::ptr_vector< XclImpSupbookTab >  XclImpSupbookTabList;
     129             :     typedef boost::ptr_vector< XclImpExtName >     XclImpExtNameList;
     130             : 
     131             :     XclImpSupbookTabList maSupbTabList;     /// All sheet names of the document.
     132             :     XclImpExtNameList   maExtNameList;      /// All external names of the document.
     133             :     OUString            maXclUrl;           /// URL of the external document (Excel mode).
     134             :     OUString            maFilterName;       /// Detected filer name.
     135             :     OUString            maFilterOpt;        /// Detected filer options.
     136             :     XclSupbookType      meType;             /// Type of the supbook record.
     137             :     sal_uInt16          mnSBTab;            /// Current Excel sheet index from SUPBOOK for XCT/CRN records.
     138             : };
     139             : 
     140             : // Import link manager ========================================================
     141             : 
     142             : /** Contains the SUPBOOK index and sheet indexes of an external link.
     143             :     @descr  It is possible to enter a formula like =SUM(Sheet1:Sheet3!A1),
     144             :     therefore here occurs a sheet range. */
     145             : struct XclImpXti
     146             : {
     147             :     sal_uInt16          mnSupbook;      /// Index to SUPBOOK record.
     148             :     sal_uInt16          mnSBTabFirst;   /// Index to the first sheet of the range in the SUPBOOK.
     149             :     sal_uInt16          mnSBTabLast;    /// Index to the last sheet of the range in the SUPBOOK.
     150           0 :     inline explicit     XclImpXti() : mnSupbook( SAL_MAX_UINT16 ), mnSBTabFirst( SAL_MAX_UINT16 ), mnSBTabLast( SAL_MAX_UINT16 ) {}
     151             : };
     152             : 
     153           0 : inline XclImpStream& operator>>( XclImpStream& rStrm, XclImpXti& rXti )
     154             : {
     155           0 :     return rStrm >> rXti.mnSupbook >> rXti.mnSBTabFirst >> rXti.mnSBTabLast;
     156             : }
     157             : 
     158             : /** Implementation of the link manager. */
     159           0 : class XclImpLinkManagerImpl : protected XclImpRoot
     160             : {
     161             : public:
     162             :     explicit            XclImpLinkManagerImpl( const XclImpRoot& rRoot );
     163             : 
     164             :     /** Reads the EXTERNSHEET record. */
     165             :     void                ReadExternsheet( XclImpStream& rStrm );
     166             :     /** Reads a SUPBOOK record. */
     167             :     void                ReadSupbook( XclImpStream& rStrm );
     168             :     /** Reads an XCT record and appends it to the current SUPBOOK. */
     169             :     void                ReadXct( XclImpStream& rStrm );
     170             :     /** Reads a CRN record and appends it to the current SUPBOOK. */
     171             :     void                ReadCrn( XclImpStream& rStrm );
     172             :     /** Reads an EXTERNNAME record and appends it to the current SUPBOOK. */
     173             :     void                ReadExternname( XclImpStream& rStrm, ExcelToSc* pFormulaConv = NULL );
     174             : 
     175             :     /** Returns true, if the specified XTI entry contains an internal reference. */
     176             :     bool                IsSelfRef( sal_uInt16 nXtiIndex ) const;
     177             :     /** Returns the Calc sheet index range of the specified XTI entry.
     178             :         @return  true = XTI data found, returned sheet index range is valid. */
     179             :     bool                GetScTabRange(
     180             :                             SCTAB& rnFirstScTab, SCTAB& rnLastScTab,
     181             :                             sal_uInt16 nXtiIndex ) const;
     182             :     /** Returns the specified external name or 0 on error. */
     183             :     const XclImpExtName* GetExternName( sal_uInt16 nXtiIndex, sal_uInt16 nExtName ) const;
     184             : 
     185             :     /** Returns the absolute file URL of a supporting workbook specified by
     186             :         the index. */
     187             :     const OUString*       GetSupbookUrl( sal_uInt16 nXtiIndex ) const;
     188             : 
     189             :     const OUString&       GetSupbookTabName( sal_uInt16 nXti, sal_uInt16 nXtiTab ) const;
     190             : 
     191             :     /** Tries to decode the URL of the specified XTI entry to OLE or DDE link components.
     192             :         @descr  For DDE links: Decodes to application name and topic.
     193             :         For OLE object links: Decodes to class name and document URL.
     194             :         @return  true = decoding was successful, returned strings are valid (not empty). */
     195             :     bool                GetLinkData( OUString& rApplic, OUString& rTopic, sal_uInt16 nXtiIndex ) const;
     196             :     /** Returns the specified macro name or an empty string on error. */
     197             :     const OUString&     GetMacroName( sal_uInt16 nExtSheet, sal_uInt16 nExtName ) const;
     198             : 
     199             : private:
     200             :     /** Returns the specified XTI (link entry from BIFF8 EXTERNSHEET record). */
     201             :     const XclImpXti*    GetXti( sal_uInt16 nXtiIndex ) const;
     202             :     /** Returns the specified SUPBOOK (external document). */
     203             :     const XclImpSupbook* GetSupbook( sal_uInt16 nXtiIndex ) const;
     204             : 
     205             :     void                LoadCachedValues();
     206             : 
     207             : private:
     208             :     typedef ::std::vector< XclImpXti >  XclImpXtiVector;
     209             :     typedef boost::ptr_vector< XclImpSupbook > XclImpSupbookList;
     210             : 
     211             :     XclImpXtiVector     maXtiList;          /// List of all XTI structures.
     212             :     XclImpSupbookList   maSupbookList;      /// List of external documents.
     213             : };
     214             : 
     215             : 
     216             : // *** Implementation ***
     217             : 
     218             : 
     219             : // Excel sheet indexes ========================================================
     220             : 
     221             : // original Excel sheet names -------------------------------------------------
     222             : 
     223           0 : void XclImpTabInfo::AppendXclTabName( const OUString& rXclTabName, SCTAB nScTab )
     224             : {
     225           0 :     maTabNames[ rXclTabName ] = nScTab;
     226           0 : }
     227             : 
     228           0 : void XclImpTabInfo::InsertScTab( SCTAB nScTab )
     229             : {
     230           0 :     for( XclTabNameMap::iterator aIt = maTabNames.begin(), aEnd = maTabNames.end(); aIt != aEnd; ++aIt )
     231           0 :         if( aIt->second >= nScTab )
     232           0 :             ++aIt->second;
     233           0 : }
     234             : 
     235           0 : SCTAB XclImpTabInfo::GetScTabFromXclName( const OUString& rXclTabName ) const
     236             : {
     237           0 :     XclTabNameMap::const_iterator aIt = maTabNames.find( rXclTabName );
     238           0 :     return (aIt != maTabNames.end()) ? aIt->second : SCTAB_INVALID;
     239             : }
     240             : 
     241             : // record creation order - TABID record ---------------------------------------
     242             : 
     243           0 : void XclImpTabInfo::ReadTabid( XclImpStream& rStrm )
     244             : {
     245             :     OSL_ENSURE_BIFF( rStrm.GetRoot().GetBiff() == EXC_BIFF8 );
     246           0 :     if( rStrm.GetRoot().GetBiff() == EXC_BIFF8 )
     247             :     {
     248           0 :         rStrm.EnableDecryption();
     249           0 :         sal_Size nReadCount = rStrm.GetRecLeft() / 2;
     250             :         OSL_ENSURE( nReadCount <= 0xFFFF, "XclImpTabInfo::ReadTabid - record too long" );
     251           0 :         maTabIdVec.clear();
     252           0 :         maTabIdVec.reserve( nReadCount );
     253           0 :         for( sal_Size nIndex = 0; rStrm.IsValid() && (nIndex < nReadCount); ++nIndex )
     254             :             // zero index is not allowed in BIFF8, but it seems that it occurs in real life
     255           0 :             maTabIdVec.push_back( rStrm.ReaduInt16() );
     256             :     }
     257           0 : }
     258             : 
     259           0 : sal_uInt16 XclImpTabInfo::GetCurrentIndex( sal_uInt16 nCreatedId, sal_uInt16 nMaxTabId ) const
     260             : {
     261           0 :     sal_uInt16 nReturn = 0;
     262           0 :     for( ScfUInt16Vec::const_iterator aIt = maTabIdVec.begin(), aEnd = maTabIdVec.end(); aIt != aEnd; ++aIt )
     263             :     {
     264           0 :         sal_uInt16 nValue = *aIt;
     265           0 :         if( nValue == nCreatedId )
     266           0 :             return nReturn;
     267           0 :         if( nValue <= nMaxTabId )
     268           0 :             ++nReturn;
     269             :     }
     270           0 :     return 0;
     271             : }
     272             : 
     273             : // External names =============================================================
     274             : 
     275           0 : XclImpExtName::MOper::MOper(svl::SharedStringPool& rPool, XclImpStream& rStrm) :
     276           0 :     mxCached(new ScMatrix(0,0))
     277             : {
     278           0 :     SCSIZE nLastCol = rStrm.ReaduInt8();
     279           0 :     SCSIZE nLastRow = rStrm.ReaduInt16();
     280           0 :     mxCached->Resize(nLastCol+1, nLastRow+1);
     281           0 :     for (SCSIZE nRow = 0; nRow <= nLastRow; ++nRow)
     282             :     {
     283           0 :         for (SCSIZE nCol = 0; nCol <= nLastCol; ++nCol)
     284             :         {
     285             :             sal_uInt8 nOp;
     286           0 :             rStrm >> nOp;
     287           0 :             switch (nOp)
     288             :             {
     289             :                 case 0x01:
     290             :                 {
     291           0 :                     double fVal = rStrm.ReadDouble();
     292           0 :                     mxCached->PutDouble(fVal, nCol, nRow);
     293             :                 }
     294           0 :                 break;
     295             :                 case 0x02:
     296             :                 {
     297           0 :                     OUString aStr = rStrm.ReadUniString();
     298           0 :                     mxCached->PutString(rPool.intern(aStr), nCol, nRow);
     299             :                 }
     300           0 :                 break;
     301             :                 case 0x04:
     302             :                 {
     303           0 :                     bool bVal = rStrm.ReaduInt8();
     304           0 :                     mxCached->PutBoolean(bVal, nCol, nRow);
     305           0 :                     rStrm.Ignore(7);
     306             :                 }
     307           0 :                 break;
     308             :                 case 0x10:
     309             :                 {
     310           0 :                     sal_uInt8 nErr = rStrm.ReaduInt8();
     311             :                     // TODO: Map the error code from xls to calc.
     312           0 :                     mxCached->PutError(nErr, nCol, nRow);
     313           0 :                     rStrm.Ignore(7);
     314             :                 }
     315           0 :                 break;
     316             :                 default:
     317           0 :                     rStrm.Ignore(8);
     318             :             }
     319             :         }
     320             :     }
     321           0 : }
     322             : 
     323           0 : const ScMatrix& XclImpExtName::MOper::GetCache() const
     324             : {
     325           0 :     return *mxCached;
     326             : }
     327             : 
     328           0 : XclImpExtName::XclImpExtName( XclImpSupbook& rSupbook, XclImpStream& rStrm, XclSupbookType eSubType, ExcelToSc* pFormulaConv ) :
     329           0 :     mpMOper(NULL)
     330             : {
     331             :     sal_uInt16 nFlags;
     332             :     sal_uInt8 nLen;
     333             : 
     334           0 :     rStrm >> nFlags >> mnStorageId >> nLen ;
     335           0 :     maName = rStrm.ReadUniString( nLen );
     336           0 :     if( ::get_flag( nFlags, EXC_EXTN_BUILTIN ) || !::get_flag( nFlags, EXC_EXTN_OLE_OR_DDE ) )
     337             :     {
     338           0 :         if( eSubType == EXC_SBTYPE_ADDIN )
     339             :         {
     340           0 :             meType = xlExtAddIn;
     341           0 :             maName = rStrm.GetRoot().GetScAddInName( maName );
     342             :         }
     343           0 :         else if ( (eSubType == EXC_SBTYPE_EUROTOOL) &&
     344           0 :                 maName.equalsIgnoreAsciiCase( "EUROCONVERT" ) )
     345           0 :             meType = xlExtEuroConvert;
     346             :         else
     347             :         {
     348           0 :             meType = xlExtName;
     349           0 :             maName = ScfTools::ConvertToScDefinedName( maName );
     350             :         }
     351             :     }
     352             :     else
     353             :     {
     354           0 :         meType = ::get_flagvalue( nFlags, EXC_EXTN_OLE, xlExtOLE, xlExtDDE );
     355             :     }
     356             : 
     357           0 :     switch (meType)
     358             :     {
     359             :         case xlExtDDE:
     360           0 :             if (rStrm.GetRecLeft() > 1)
     361           0 :                 mxDdeMatrix.reset(new XclImpCachedMatrix(rStrm));
     362           0 :         break;
     363             :         case xlExtName:
     364             :             // TODO: For now, only global external names are supported.  In future
     365             :             // we should extend this to supporting per-sheet external names.
     366           0 :             if (mnStorageId == 0)
     367             :             {
     368           0 :                 if (pFormulaConv)
     369             :                 {
     370           0 :                     const ScTokenArray* pArray = NULL;
     371             :                     sal_uInt16 nFmlaLen;
     372           0 :                     rStrm >> nFmlaLen;
     373           0 :                     vector<OUString> aTabNames;
     374           0 :                     sal_uInt16 nCount = rSupbook.GetTabCount();
     375           0 :                     aTabNames.reserve(nCount);
     376           0 :                     for (sal_uInt16 i = 0; i < nCount; ++i)
     377           0 :                         aTabNames.push_back(rSupbook.GetTabName(i));
     378             : 
     379           0 :                     pFormulaConv->ConvertExternName(pArray, rStrm, nFmlaLen, rSupbook.GetXclUrl(), aTabNames);
     380           0 :                     if (pArray)
     381           0 :                         mxArray.reset(pArray->Clone());
     382             :                 }
     383             :             }
     384           0 :         break;
     385             :         case xlExtOLE:
     386           0 :             mpMOper = new MOper(rSupbook.GetSharedStringPool(), rStrm);
     387           0 :         break;
     388             :         default:
     389             :             ;
     390             :     }
     391           0 : }
     392             : 
     393           0 : XclImpExtName::~XclImpExtName()
     394             : {
     395           0 :     delete mpMOper;
     396           0 : }
     397             : 
     398           0 : void XclImpExtName::CreateDdeData( ScDocument& rDoc, const OUString& rApplic, const OUString& rTopic ) const
     399             : {
     400           0 :     ScMatrixRef xResults;
     401           0 :     if( mxDdeMatrix.get() )
     402           0 :         xResults = mxDdeMatrix->CreateScMatrix(rDoc.GetSharedStringPool());
     403           0 :     rDoc.CreateDdeLink( rApplic, rTopic, maName, SC_DDE_DEFAULT, xResults );
     404           0 : }
     405             : 
     406           0 : void XclImpExtName::CreateExtNameData( ScDocument& rDoc, sal_uInt16 nFileId ) const
     407             : {
     408           0 :     if (!mxArray.get())
     409           0 :         return;
     410             : 
     411           0 :     ScExternalRefManager* pRefMgr = rDoc.GetExternalRefManager();
     412           0 :     pRefMgr->storeRangeNameTokens(nFileId, maName, *mxArray);
     413             : }
     414             : 
     415             : namespace {
     416             : 
     417             : /**
     418             :  * Decompose the name into sheet name and range name.  An OLE link name is
     419             :  * always formatted like this [ !Sheet1!R1C1:R5C2 ] and it always uses R1C1
     420             :  * notation.
     421             :  */
     422           0 : bool extractSheetAndRange(const OUString& rName, OUString& rSheet, OUString& rRange)
     423             : {
     424           0 :     sal_Int32 n = rName.getLength();
     425           0 :     const sal_Unicode* p = rName.getStr();
     426           0 :     OUStringBuffer aBuf;
     427           0 :     bool bInSheet = true;
     428           0 :     for (sal_Int32 i = 0; i < n; ++i, ++p)
     429             :     {
     430           0 :         if (i == 0)
     431             :         {
     432             :             // first character must be '!'.
     433           0 :             if (*p != '!')
     434           0 :                 return false;
     435           0 :             continue;
     436             :         }
     437             : 
     438           0 :         if (*p == '!')
     439             :         {
     440             :             // sheet name to range separator.
     441           0 :             if (!bInSheet)
     442           0 :                 return false;
     443           0 :             rSheet = aBuf.makeStringAndClear();
     444           0 :             bInSheet = false;
     445           0 :             continue;
     446             :         }
     447             : 
     448           0 :         aBuf.append(*p);
     449             :     }
     450             : 
     451           0 :     rRange = aBuf.makeStringAndClear();
     452           0 :     return true;
     453             : }
     454             : 
     455             : }
     456             : 
     457           0 : bool XclImpExtName::CreateOleData(ScDocument& rDoc, const OUString& rUrl,
     458             :                                   sal_uInt16& rFileId, OUString& rTabName, ScRange& rRange) const
     459             : {
     460           0 :     if (!mpMOper)
     461           0 :         return false;
     462             : 
     463           0 :     OUString aSheet, aRangeStr;
     464           0 :     if (!extractSheetAndRange(maName, aSheet, aRangeStr))
     465           0 :         return false;
     466             : 
     467           0 :     ScRange aRange;
     468           0 :     sal_uInt16 nRes = aRange.ParseAny(aRangeStr, &rDoc, formula::FormulaGrammar::CONV_XL_R1C1);
     469           0 :     if ((nRes & SCA_VALID) != SCA_VALID)
     470           0 :         return false;
     471             : 
     472           0 :     if (aRange.aStart.Tab() != aRange.aEnd.Tab())
     473             :         // We don't support multi-sheet range for this.
     474           0 :         return false;
     475             : 
     476           0 :     const ScMatrix& rCache = mpMOper->GetCache();
     477             :     SCSIZE nC, nR;
     478           0 :     rCache.GetDimensions(nC, nR);
     479           0 :     if (!nC || !nR)
     480             :         // cache matrix is empty.
     481           0 :         return false;
     482             : 
     483           0 :     ScExternalRefManager* pRefMgr = rDoc.GetExternalRefManager();
     484           0 :     sal_uInt16 nFileId = pRefMgr->getExternalFileId(rUrl);
     485           0 :     ScExternalRefCache::TableTypeRef xTab = pRefMgr->getCacheTable(nFileId, aSheet, true, NULL);
     486           0 :     if (!xTab)
     487             :         // cache table creation failed.
     488           0 :         return false;
     489             : 
     490           0 :     xTab->setWholeTableCached();
     491           0 :     for (SCSIZE i = 0; i < nR; ++i)
     492             :     {
     493           0 :         for (SCSIZE j = 0; j < nC; ++j)
     494             :         {
     495           0 :             SCCOL nCol = aRange.aStart.Col() + j;
     496           0 :             SCROW nRow = aRange.aStart.Row() + i;
     497             : 
     498           0 :             ScMatrixValue aVal = rCache.Get(j, i);
     499           0 :             switch (aVal.nType)
     500             :             {
     501             :                 case SC_MATVAL_BOOLEAN:
     502             :                 {
     503           0 :                     bool b = aVal.GetBoolean();
     504           0 :                     ScExternalRefCache::TokenRef pToken(new formula::FormulaDoubleToken(b ? 1.0 : 0.0));
     505           0 :                     xTab->setCell(nCol, nRow, pToken, 0, false);
     506             :                 }
     507           0 :                 break;
     508             :                 case SC_MATVAL_VALUE:
     509             :                 {
     510           0 :                     ScExternalRefCache::TokenRef pToken(new formula::FormulaDoubleToken(aVal.fVal));
     511           0 :                     xTab->setCell(nCol, nRow, pToken, 0, false);
     512             :                 }
     513           0 :                 break;
     514             :                 case SC_MATVAL_STRING:
     515             :                 {
     516           0 :                     const svl::SharedString aStr( aVal.GetString());
     517           0 :                     ScExternalRefCache::TokenRef pToken(new formula::FormulaStringToken(aStr));
     518           0 :                     xTab->setCell(nCol, nRow, pToken, 0, false);
     519             :                 }
     520           0 :                 break;
     521             :                 default:
     522             :                     ;
     523             :             }
     524           0 :         }
     525             :     }
     526             : 
     527           0 :     rFileId = nFileId;
     528           0 :     rTabName = aSheet;
     529           0 :     rRange = aRange;
     530           0 :     return true;
     531             : }
     532             : 
     533           0 : bool XclImpExtName::HasFormulaTokens() const
     534             : {
     535           0 :     return (mxArray.get() != NULL);
     536             : }
     537             : 
     538             : // Cached external cells ======================================================
     539             : 
     540           0 : XclImpCrn::XclImpCrn( XclImpStream& rStrm, const XclAddress& rXclPos ) :
     541             :     XclImpCachedValue( rStrm ),
     542           0 :     maXclPos( rXclPos )
     543             : {
     544           0 : }
     545             : 
     546           0 : const XclAddress& XclImpCrn::GetAddress() const
     547             : {
     548           0 :     return maXclPos;
     549             : }
     550             : 
     551             : // Sheet in an external document ==============================================
     552             : 
     553           0 : XclImpSupbookTab::XclImpSupbookTab( const OUString& rTabName ) :
     554           0 :     maTabName( rTabName )
     555             : {
     556           0 : }
     557             : 
     558           0 : XclImpSupbookTab::~XclImpSupbookTab()
     559             : {
     560           0 : }
     561             : 
     562           0 : void XclImpSupbookTab::ReadCrn( XclImpStream& rStrm, const XclAddress& rXclPos )
     563             : {
     564           0 :     XclImpCrnRef crnRef( new XclImpCrn(rStrm, rXclPos) );
     565           0 :     maCrnList.push_back( crnRef );
     566           0 : }
     567             : 
     568           0 : void XclImpSupbookTab::LoadCachedValues(ScExternalRefCache::TableTypeRef pCacheTable)
     569             : {
     570           0 :     if (maCrnList.empty())
     571           0 :         return;
     572             : 
     573           0 :     for (XclImpCrnList::iterator itCrnRef = maCrnList.begin(); itCrnRef != maCrnList.end(); ++itCrnRef)
     574             :     {
     575           0 :         const XclImpCrn* const pCrn = itCrnRef->get();
     576           0 :         const XclAddress& rAddr = pCrn->GetAddress();
     577           0 :         switch (pCrn->GetType())
     578             :         {
     579             :             case EXC_CACHEDVAL_BOOL:
     580             :             {
     581           0 :                 bool b = pCrn->GetBool();
     582           0 :                 ScExternalRefCache::TokenRef pToken(new formula::FormulaDoubleToken(b ? 1.0 : 0.0));
     583           0 :                 pCacheTable->setCell(rAddr.mnCol, rAddr.mnRow, pToken, 0, false);
     584             :             }
     585           0 :             break;
     586             :             case EXC_CACHEDVAL_DOUBLE:
     587             :             {
     588           0 :                 double f = pCrn->GetValue();
     589           0 :                 ScExternalRefCache::TokenRef pToken(new formula::FormulaDoubleToken(f));
     590           0 :                 pCacheTable->setCell(rAddr.mnCol, rAddr.mnRow, pToken, 0, false);
     591             :             }
     592           0 :             break;
     593             :             case EXC_CACHEDVAL_ERROR:
     594             :             {
     595           0 :                 double fError = XclTools::ErrorToDouble( pCrn->GetXclError() );
     596           0 :                 ScExternalRefCache::TokenRef pToken(new formula::FormulaDoubleToken(fError));
     597           0 :                 pCacheTable->setCell(rAddr.mnCol, rAddr.mnRow, pToken, 0, false);
     598             :             }
     599           0 :             break;
     600             :             case EXC_CACHEDVAL_STRING:
     601             :             {
     602           0 :                 const OUString& rStr = pCrn->GetString();
     603           0 :                 ScExternalRefCache::TokenRef pToken(new formula::FormulaStringToken(rStr));
     604           0 :                 pCacheTable->setCell(rAddr.mnCol, rAddr.mnRow, pToken, 0, false);
     605             :             }
     606           0 :             break;
     607             :             default:
     608             :                 ;
     609             :         }
     610             :     }
     611             : }
     612             : 
     613             : // External document (SUPBOOK) ================================================
     614             : 
     615           0 : XclImpSupbook::XclImpSupbook( XclImpStream& rStrm ) :
     616           0 :     XclImpRoot( rStrm.GetRoot() ),
     617             :     meType( EXC_SBTYPE_UNKNOWN ),
     618           0 :     mnSBTab( EXC_TAB_DELETED )
     619             : {
     620             :     sal_uInt16 nSBTabCnt;
     621           0 :     rStrm >> nSBTabCnt;
     622             : 
     623           0 :     if( rStrm.GetRecLeft() == 2 )
     624             :     {
     625           0 :         switch( rStrm.ReaduInt16() )
     626             :         {
     627           0 :             case EXC_SUPB_SELF:     meType = EXC_SBTYPE_SELF;   break;
     628           0 :             case EXC_SUPB_ADDIN:    meType = EXC_SBTYPE_ADDIN;  break;
     629             :             default:    OSL_FAIL( "XclImpSupbook::XclImpSupbook - unknown special SUPBOOK type" );
     630             :         }
     631           0 :         return;
     632             :     }
     633             : 
     634           0 :     OUString aEncUrl( rStrm.ReadUniString() );
     635           0 :     bool bSelf = false;
     636           0 :     XclImpUrlHelper::DecodeUrl( maXclUrl, bSelf, GetRoot(), aEncUrl );
     637             : 
     638           0 :     if( maXclUrl.equalsIgnoreAsciiCase( "\010EUROTOOL.XLA" ) )
     639             :     {
     640           0 :         meType = EXC_SBTYPE_EUROTOOL;
     641           0 :         maSupbTabList.push_back( new XclImpSupbookTab( maXclUrl ) );
     642             :     }
     643           0 :     else if( nSBTabCnt )
     644             :     {
     645           0 :         meType = EXC_SBTYPE_EXTERN;
     646           0 :         for( sal_uInt16 nSBTab = 0; nSBTab < nSBTabCnt; ++nSBTab )
     647             :         {
     648           0 :             OUString aTabName( rStrm.ReadUniString() );
     649           0 :             maSupbTabList.push_back( new XclImpSupbookTab( aTabName ) );
     650           0 :         }
     651             :     }
     652             :     else
     653             :     {
     654           0 :         meType = EXC_SBTYPE_SPECIAL;
     655             :         // create dummy list entry
     656           0 :         maSupbTabList.push_back( new XclImpSupbookTab( maXclUrl ) );
     657           0 :     }
     658             : }
     659             : 
     660           0 : void XclImpSupbook::ReadXct( XclImpStream& rStrm )
     661             : {
     662           0 :     rStrm.Ignore( 2 );
     663           0 :     rStrm >> mnSBTab;
     664           0 : }
     665             : 
     666           0 : void XclImpSupbook::ReadCrn( XclImpStream& rStrm )
     667             : {
     668           0 :     if (mnSBTab >= maSupbTabList.size())
     669           0 :         return;
     670           0 :     XclImpSupbookTab& rSbTab = maSupbTabList[mnSBTab];
     671             :     sal_uInt8 nXclColLast, nXclColFirst;
     672             :     sal_uInt16 nXclRow;
     673           0 :     rStrm >> nXclColLast >> nXclColFirst >> nXclRow;
     674             : 
     675           0 :     for( sal_uInt8 nXclCol = nXclColFirst; (nXclCol <= nXclColLast) && (rStrm.GetRecLeft() > 1); ++nXclCol )
     676           0 :         rSbTab.ReadCrn( rStrm, XclAddress( nXclCol, nXclRow ) );
     677             : }
     678             : 
     679           0 : void XclImpSupbook::ReadExternname( XclImpStream& rStrm, ExcelToSc* pFormulaConv )
     680             : {
     681           0 :     maExtNameList.push_back( new XclImpExtName( *this, rStrm, meType, pFormulaConv ) );
     682           0 : }
     683             : 
     684           0 : const XclImpExtName* XclImpSupbook::GetExternName( sal_uInt16 nXclIndex ) const
     685             : {
     686             :     OSL_ENSURE( nXclIndex > 0, "XclImpSupbook::GetExternName - index must be >0" );
     687           0 :     if (meType == EXC_SBTYPE_SELF || nXclIndex > maExtNameList.size())
     688           0 :         return NULL;
     689           0 :     return &maExtNameList[nXclIndex-1];
     690             : }
     691             : 
     692           0 : bool XclImpSupbook::GetLinkData( OUString& rApplic, OUString& rTopic ) const
     693             : {
     694           0 :     return (meType == EXC_SBTYPE_SPECIAL) && XclImpUrlHelper::DecodeLink( rApplic, rTopic, maXclUrl );
     695             : }
     696             : 
     697           0 : const OUString& XclImpSupbook::GetMacroName( sal_uInt16 nXclNameIdx ) const
     698             : {
     699             :     OSL_ENSURE( nXclNameIdx > 0, "XclImpSupbook::GetMacroName - index must be >0" );
     700           0 :     const XclImpName* pName = (meType == EXC_SBTYPE_SELF) ? GetNameManager().GetName( nXclNameIdx ) : 0;
     701           0 :     return (pName && pName->IsVBName()) ? pName->GetScName() : EMPTY_OUSTRING;
     702             : }
     703             : 
     704           0 : const OUString& XclImpSupbook::GetTabName( sal_uInt16 nXtiTab ) const
     705             : {
     706           0 :     if (nXtiTab >= maSupbTabList.size())
     707           0 :         return EMPTY_OUSTRING;
     708           0 :     return maSupbTabList[nXtiTab].GetTabName();
     709             : }
     710             : 
     711           0 : sal_uInt16 XclImpSupbook::GetTabCount() const
     712             : {
     713           0 :     return ulimit_cast<sal_uInt16>(maSupbTabList.size());
     714             : }
     715             : 
     716           0 : void XclImpSupbook::LoadCachedValues()
     717             : {
     718           0 :     if (meType != EXC_SBTYPE_EXTERN || GetExtDocOptions().GetDocSettings().mnLinkCnt > 0 || !GetDocShell())
     719           0 :         return;
     720             : 
     721           0 :     OUString aAbsUrl( ScGlobal::GetAbsDocName(maXclUrl, GetDocShell()) );
     722             : 
     723           0 :     ScExternalRefManager* pRefMgr = GetRoot().GetDoc().GetExternalRefManager();
     724           0 :     sal_uInt16 nFileId = pRefMgr->getExternalFileId(aAbsUrl);
     725             : 
     726           0 :     for (XclImpSupbookTabList::iterator itTab = maSupbTabList.begin(); itTab != maSupbTabList.end(); ++itTab)
     727             :     {
     728           0 :         const OUString& rTabName = itTab->GetTabName();
     729           0 :         ScExternalRefCache::TableTypeRef pCacheTable = pRefMgr->getCacheTable(nFileId, rTabName, true);
     730           0 :         itTab->LoadCachedValues(pCacheTable);
     731           0 :         pCacheTable->setWholeTableCached();
     732           0 :     }
     733             : }
     734             : 
     735           0 : svl::SharedStringPool& XclImpSupbook::GetSharedStringPool()
     736             : {
     737           0 :     return GetDoc().GetSharedStringPool();
     738             : }
     739             : 
     740             : // Import link manager ========================================================
     741             : 
     742           0 : XclImpLinkManagerImpl::XclImpLinkManagerImpl( const XclImpRoot& rRoot ) :
     743           0 :     XclImpRoot( rRoot )
     744             : {
     745           0 : }
     746             : 
     747           0 : void XclImpLinkManagerImpl::ReadExternsheet( XclImpStream& rStrm )
     748             : {
     749             :     sal_uInt16 nXtiCount;
     750           0 :     rStrm >> nXtiCount;
     751             :     OSL_ENSURE( static_cast< sal_Size >( nXtiCount * 6 ) == rStrm.GetRecLeft(), "XclImpLinkManagerImpl::ReadExternsheet - invalid count" );
     752           0 :     nXtiCount = static_cast< sal_uInt16 >( ::std::min< sal_Size >( nXtiCount, rStrm.GetRecLeft() / 6 ) );
     753             : 
     754             :     /*  #i104057# A weird external XLS generator writes multiple EXTERNSHEET
     755             :         records instead of only one as expected. Surprisingly, Excel seems to
     756             :         insert the entries of the second record before the entries of the first
     757             :         record. */
     758           0 :     XclImpXtiVector aNewEntries( nXtiCount );
     759           0 :     for( XclImpXtiVector::iterator aIt = aNewEntries.begin(), aEnd = aNewEntries.end(); rStrm.IsValid() && (aIt != aEnd); ++aIt )
     760           0 :         rStrm >> *aIt;
     761           0 :     maXtiList.insert( maXtiList.begin(), aNewEntries.begin(), aNewEntries.end() );
     762             : 
     763           0 :     LoadCachedValues();
     764           0 : }
     765             : 
     766           0 : void XclImpLinkManagerImpl::ReadSupbook( XclImpStream& rStrm )
     767             : {
     768           0 :     maSupbookList.push_back( new XclImpSupbook( rStrm ) );
     769           0 : }
     770             : 
     771           0 : void XclImpLinkManagerImpl::ReadXct( XclImpStream& rStrm )
     772             : {
     773           0 :     if( !maSupbookList.empty() )
     774           0 :         maSupbookList.back().ReadXct( rStrm );
     775           0 : }
     776             : 
     777           0 : void XclImpLinkManagerImpl::ReadCrn( XclImpStream& rStrm )
     778             : {
     779           0 :     if( !maSupbookList.empty() )
     780           0 :         maSupbookList.back().ReadCrn( rStrm );
     781           0 : }
     782             : 
     783           0 : void XclImpLinkManagerImpl::ReadExternname( XclImpStream& rStrm, ExcelToSc* pFormulaConv )
     784             : {
     785           0 :     if( !maSupbookList.empty() )
     786           0 :         maSupbookList.back().ReadExternname( rStrm, pFormulaConv );
     787           0 : }
     788             : 
     789           0 : bool XclImpLinkManagerImpl::IsSelfRef( sal_uInt16 nXtiIndex ) const
     790             : {
     791           0 :     const XclImpSupbook* pSupbook = GetSupbook( nXtiIndex );
     792           0 :     return pSupbook && (pSupbook->GetType() == EXC_SBTYPE_SELF);
     793             : }
     794             : 
     795           0 : bool XclImpLinkManagerImpl::GetScTabRange(
     796             :         SCTAB& rnFirstScTab, SCTAB& rnLastScTab, sal_uInt16 nXtiIndex ) const
     797             : {
     798           0 :     if( const XclImpXti* pXti = GetXti( nXtiIndex ) )
     799             :     {
     800           0 :         if (!maSupbookList.empty() && (pXti->mnSupbook < maSupbookList.size()) )
     801             :         {
     802           0 :             rnFirstScTab = pXti->mnSBTabFirst;
     803           0 :             rnLastScTab  = pXti->mnSBTabLast;
     804           0 :             return true;
     805             :         }
     806             :     }
     807           0 :     return false;
     808             : }
     809             : 
     810           0 : const XclImpExtName* XclImpLinkManagerImpl::GetExternName( sal_uInt16 nXtiIndex, sal_uInt16 nExtName ) const
     811             : {
     812           0 :     const XclImpSupbook* pSupbook = GetSupbook( nXtiIndex );
     813           0 :     return pSupbook ? pSupbook->GetExternName( nExtName ) : 0;
     814             : }
     815             : 
     816           0 : const OUString* XclImpLinkManagerImpl::GetSupbookUrl( sal_uInt16 nXtiIndex ) const
     817             : {
     818           0 :     const XclImpSupbook* p = GetSupbook( nXtiIndex );
     819           0 :     if (!p)
     820           0 :         return NULL;
     821           0 :     return &p->GetXclUrl();
     822             : }
     823             : 
     824           0 : const OUString& XclImpLinkManagerImpl::GetSupbookTabName( sal_uInt16 nXti, sal_uInt16 nXtiTab ) const
     825             : {
     826           0 :     const XclImpSupbook* p = GetSupbook(nXti);
     827           0 :     return p ? p->GetTabName(nXtiTab) : EMPTY_OUSTRING;
     828             : }
     829             : 
     830           0 : bool XclImpLinkManagerImpl::GetLinkData( OUString& rApplic, OUString& rTopic, sal_uInt16 nXtiIndex ) const
     831             : {
     832           0 :     const XclImpSupbook* pSupbook = GetSupbook( nXtiIndex );
     833           0 :     return pSupbook && pSupbook->GetLinkData( rApplic, rTopic );
     834             : }
     835             : 
     836           0 : const OUString& XclImpLinkManagerImpl::GetMacroName( sal_uInt16 nExtSheet, sal_uInt16 nExtName ) const
     837             : {
     838           0 :     const XclImpSupbook* pSupbook = GetSupbook( nExtSheet );
     839           0 :     return pSupbook ? pSupbook->GetMacroName( nExtName ) : EMPTY_OUSTRING;
     840             : }
     841             : 
     842           0 : const XclImpXti* XclImpLinkManagerImpl::GetXti( sal_uInt16 nXtiIndex ) const
     843             : {
     844           0 :     return (nXtiIndex < maXtiList.size()) ? &maXtiList[ nXtiIndex ] : 0;
     845             : }
     846             : 
     847           0 : const XclImpSupbook* XclImpLinkManagerImpl::GetSupbook( sal_uInt16 nXtiIndex ) const
     848             : {
     849           0 :     if ( maSupbookList.empty() )
     850           0 :         return NULL;
     851           0 :     const XclImpXti* pXti = GetXti( nXtiIndex );
     852           0 :     if (!pXti || pXti->mnSupbook >= maSupbookList.size())
     853           0 :         return NULL;
     854           0 :     return &(maSupbookList.at( pXti->mnSupbook ));
     855             : }
     856             : 
     857           0 : void XclImpLinkManagerImpl::LoadCachedValues()
     858             : {
     859             :     // Read all CRN records which can be accessed via XclImpSupbook, and store
     860             :     // the cached values to the external reference manager.
     861           0 :     for (XclImpSupbookList::iterator itSupbook = maSupbookList.begin(); itSupbook != maSupbookList.end(); ++itSupbook)
     862           0 :         itSupbook->LoadCachedValues();
     863           0 : }
     864             : 
     865           0 : XclImpLinkManager::XclImpLinkManager( const XclImpRoot& rRoot ) :
     866             :     XclImpRoot( rRoot ),
     867           0 :     mxImpl( new XclImpLinkManagerImpl( rRoot ) )
     868             : {
     869           0 : }
     870             : 
     871           0 : XclImpLinkManager::~XclImpLinkManager()
     872             : {
     873           0 : }
     874             : 
     875           0 : void XclImpLinkManager::ReadExternsheet( XclImpStream& rStrm )
     876             : {
     877           0 :     mxImpl->ReadExternsheet( rStrm );
     878           0 : }
     879             : 
     880           0 : void XclImpLinkManager::ReadSupbook( XclImpStream& rStrm )
     881             : {
     882           0 :     mxImpl->ReadSupbook( rStrm );
     883           0 : }
     884             : 
     885           0 : void XclImpLinkManager::ReadXct( XclImpStream& rStrm )
     886             : {
     887           0 :     mxImpl->ReadXct( rStrm );
     888           0 : }
     889             : 
     890           0 : void XclImpLinkManager::ReadCrn( XclImpStream& rStrm )
     891             : {
     892           0 :     mxImpl->ReadCrn( rStrm );
     893           0 : }
     894             : 
     895           0 : void XclImpLinkManager::ReadExternname( XclImpStream& rStrm, ExcelToSc* pFormulaConv )
     896             : {
     897           0 :     mxImpl->ReadExternname( rStrm, pFormulaConv );
     898           0 : }
     899             : 
     900           0 : bool XclImpLinkManager::IsSelfRef( sal_uInt16 nXtiIndex ) const
     901             : {
     902           0 :     return mxImpl->IsSelfRef( nXtiIndex );
     903             : }
     904             : 
     905           0 : bool XclImpLinkManager::GetScTabRange(
     906             :         SCTAB& rnFirstScTab, SCTAB& rnLastScTab, sal_uInt16 nXtiIndex ) const
     907             : {
     908           0 :     return mxImpl->GetScTabRange( rnFirstScTab, rnLastScTab, nXtiIndex );
     909             : }
     910             : 
     911           0 : const XclImpExtName* XclImpLinkManager::GetExternName( sal_uInt16 nXtiIndex, sal_uInt16 nExtName ) const
     912             : {
     913           0 :     return mxImpl->GetExternName( nXtiIndex, nExtName );
     914             : }
     915             : 
     916           0 : const OUString* XclImpLinkManager::GetSupbookUrl( sal_uInt16 nXtiIndex ) const
     917             : {
     918           0 :     return mxImpl->GetSupbookUrl(nXtiIndex);
     919             : }
     920             : 
     921           0 : const OUString& XclImpLinkManager::GetSupbookTabName( sal_uInt16 nXti,  sal_uInt16 nXtiTab ) const
     922             : {
     923           0 :     return mxImpl->GetSupbookTabName(nXti, nXtiTab);
     924             : }
     925             : 
     926           0 : bool XclImpLinkManager::GetLinkData( OUString& rApplic, OUString& rTopic, sal_uInt16 nXtiIndex ) const
     927             : {
     928           0 :     return mxImpl->GetLinkData( rApplic, rTopic, nXtiIndex );
     929             : }
     930             : 
     931           0 : const OUString& XclImpLinkManager::GetMacroName( sal_uInt16 nExtSheet, sal_uInt16 nExtName ) const
     932             : {
     933           0 :     return mxImpl->GetMacroName( nExtSheet, nExtName );
     934             : }
     935             : 
     936             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10