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

Generated by: LCOV version 1.10