ooo-build r13628 - in trunk: . patches/dev300 patches/test



Author: kyoshida
Date: Tue Aug 19 15:10:44 2008
New Revision: 13628
URL: http://svn.gnome.org/viewvc/ooo-build?rev=13628&view=rev

Log:
2008-08-19  Kohei Yoshida  <kyoshida novell com>

	* patches/dev300/calc-external-defined-names.diff: updated the patch 
	with the change introduced by the patch below.

	* patches/test/calc-external-ref-odf-cache.diff: removed as this has
	been combined with the patch above.


Removed:
   trunk/patches/test/calc-external-ref-odf-cache.diff
Modified:
   trunk/ChangeLog
   trunk/patches/dev300/calc-external-defined-names.diff

Modified: trunk/patches/dev300/calc-external-defined-names.diff
==============================================================================
--- trunk/patches/dev300/calc-external-defined-names.diff	(original)
+++ trunk/patches/dev300/calc-external-defined-names.diff	Tue Aug 19 15:10:44 2008
@@ -169,10 +169,10 @@
      BOOL IsColRowName( const String& );
      BOOL IsBoolean( const String& );
 diff --git sc/inc/document.hxx sc/inc/document.hxx
-index 80fc25c..a5c0240 100644
+index 1de31e7..8c50532 100644
 --- sc/inc/document.hxx
 +++ sc/inc/document.hxx
-@@ -93,6 +93,7 @@ class ScDocOptions;
+@@ -93,6 +93,7 @@ class ScDocProtection;
  class ScDocumentPool;
  class ScDrawLayer;
  class ScExtDocOptions;
@@ -207,10 +207,10 @@
  
 diff --git sc/inc/externalrefmgr.hxx sc/inc/externalrefmgr.hxx
 new file mode 100644
-index 0000000..8a11b5d
+index 0000000..7398ed1
 --- /dev/null
 +++ sc/inc/externalrefmgr.hxx
-@@ -0,0 +1,342 @@
+@@ -0,0 +1,373 @@
 +/*************************************************************************
 + *
 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -322,7 +322,9 @@
 +        ~Table();
 +
 +        void setCell(SCROW nRow, SCCOL nCol, TokenRef pToken);
-+        ScToken* getCell(SCROW nRow, SCCOL nCol) const;
++        TokenRef getCell(SCROW nRow, SCCOL nCol) const;
++        void getAllRows(::std::vector<SCROW>& rRows) const;
++        void getAllCols(SCROW nRow, ::std::vector<SCCOL>& rCols) const;
 +
 +    private:
 +        RowsDataType maRows;
@@ -388,7 +390,7 @@
 +     * 
 +     * @return pointer to the cache table instance
 +     */
-+    Table* getCacheTable(sal_uInt16 nFileId, const String& rTabName);
++    Table* getCacheTable(sal_uInt16 nFileId, const String& rTabName, bool bCreateNew = true);
 +
 +    void clearCache(sal_uInt16 nFileId);
 +
@@ -430,7 +432,8 @@
 +        }
 +    };
 +
-+    struct SrcDoc
++    /** Shell instance for a source document. */
++    struct SrcShell
 +    {
 +        SfxObjectShellRef   maShell;
 +        Time                maLastAccess;
@@ -439,13 +442,23 @@
 +    typedef ::boost::shared_ptr<ScToken>        TokenRef;
 +    typedef ::boost::shared_ptr<ScTokenArray>   TokenArrayRef;
 +
-+    typedef ::std::hash_map<sal_uInt16, SrcDoc>                                                 DocShellMap;
-+    typedef ::std::hash_set<sal_uInt16, ScStringHashCode>                                       LinkedDocSet;
++    typedef ::std::hash_map<sal_uInt16, SrcShell>                                   DocShellMap;
++    typedef ::std::hash_set<sal_uInt16>                                             LinkedDocSet;
 +
 +    typedef ::std::hash_set<ScAddress, AddressHash, ::std::equal_to<ScAddress> >    RefCellSet;
 +    typedef ::std::hash_map<sal_uInt16, RefCellSet>                                 RefCellMap;
 +
 +public:
++    /** Source document meta-data container. */
++    struct SrcFileData
++    {
++        String maFileName;
++        String maRelativeName;
++        String maFilterName;
++        String maFilterOptions;
++    };
++
++public:
 +    explicit ScExternalRefManager(ScDocument* pDoc);
 +    ~ScExternalRefManager();
 +
@@ -482,6 +495,8 @@
 +     */
 +    ScTokenArray* getRangeNameTokens(sal_uInt16 nFileId, const String& rName, const ScAddress* pCurPos = NULL);
 +
++    bool isOwnDocument(const String& rFile) const;
++
 +    /** 
 +     * Takes a flat file name, and convert it to an absolute URL path.  An 
 +     * absolute URL path begines with 'file:///. 
@@ -491,9 +506,26 @@
 +    void convertToAbsName(String& rFile) const;
 +    sal_uInt16 getExternalFileId(const String& rFile);
 +    const String* getExternalFileName(sal_uInt16 nFileId) const;
++    const SrcFileData* getExternalFileData(sal_uInt16 nFileId) const;
++
 +    const ::std::vector<String>* getAllCachedTableNames(sal_uInt16 nFileId) const;
++    sal_uInt16 getCachedFileCount() const;
 +    void refreshNames(sal_uInt16 nFileId);
 +    void switchSrcFile(sal_uInt16 nFileId, const String& rNewFile);
++
++    void setRelativeFileName(sal_uInt16 nFileId, const String& rRelUrl);
++
++    /** 
++     * Set the filter name and options if any for a given source document. 
++     * These values get reset whne the source document ever gets reloaded. 
++     *
++     * @param nFileId 
++     * @param rFilterName 
++     * @param rOptions 
++     * @return 
++     */
++    void setFilterData(sal_uInt16 nFileId, const String& rFilterName, const String& rOptions);
++
 +    void removeSrcDocument(sal_uInt16 nFileId, bool bBreakLink);
 +    void clear();
 +
@@ -508,7 +540,7 @@
 +    void insertReferencingCell(sal_uInt16 nFileId, const ScAddress& rCell);
 +
 +    ScDocument* getSrcDocument(sal_uInt16 nFileId);
-+    SfxObjectShellRef loadSrcDocument(const String& rFile, String& rFilter);
++    SfxObjectShellRef loadSrcDocument(sal_uInt16 nFileId, const String& rFile, String& rFilter);
 +
 +    void maybeLinkExternalFile(sal_uInt16 nFileId);
 +
@@ -523,15 +555,14 @@
 +    void purgeStaleSrcDocument(sal_Int32 nTimeOut);
 +
 +private:
-+    /** cache only of referenced ranges and names from source documents. */
++    /** cache of referenced ranges and names from source documents. */
 +    ScExternalRefCache maRefCache;
 +
 +    ScDocument* mpDoc;
 +
 +    /** 
-+     * Source document cache.  This stores the original source document 
-+     * instances.  The source documents get purged after certain period of 
-+     * time. 
++     * Source document cache.  This stores the original source document shell 
++     * instances.  They get purged after a certain period of time.
 +     */
 +    DocShellMap maDocShells;
 +
@@ -545,7 +576,7 @@
 +    RefCellMap maRefCells;
 +
 +    /** original source file index. */
-+    ::std::vector<String> maFileNames;
++    ::std::vector<SrcFileData> maSrcFiles;
 +
 +    AutoTimer maSrcDocTimer;
 +    DECL_LINK(TimeOutHdl, AutoTimer*);
@@ -693,10 +724,10 @@
  				ScRangeData* pRangeData = pDoc->GetRangeName()->FindIndex( t->GetIndex() );
  				if( pRangeData )
 diff --git sc/source/core/data/documen2.cxx sc/source/core/data/documen2.cxx
-index 050e413..d9dccd9 100644
+index b75279e..d739a17 100644
 --- sc/source/core/data/documen2.cxx
 +++ sc/source/core/data/documen2.cxx
-@@ -93,6 +93,7 @@
+@@ -94,6 +94,7 @@
  #include "recursionhelper.hxx"
  #include "lookupcache.hxx"
  #include "tabprotection.hxx"
@@ -704,7 +735,7 @@
  #include <com/sun/star/document/XVbaEventsHelper.hpp>
  
  // pImpl because including lookupcache.hxx in document.hxx isn't wanted, and
-@@ -152,6 +153,7 @@ ScDocument::ScDocument( ScDocumentMode	eMode,
+@@ -153,6 +154,7 @@ ScDocument::ScDocument( ScDocumentMode	eMode,
  		pScriptTypeData( NULL ),
          pCacheFieldEditEngine( NULL ),
          pDocProtection( NULL ),
@@ -712,7 +743,7 @@
  		pViewOptions( NULL ),
  		pDocOptions( NULL ),
  		pExtDocOptions( NULL ),
-@@ -382,6 +384,11 @@ ScDocument::~ScDocument()
+@@ -383,6 +385,11 @@ ScDocument::~ScDocument()
  			pLinkManager->Remove( 0, pLinkManager->GetLinks().Count() );
  	}
  
@@ -809,7 +840,7 @@
  {
      if (pLinkManager)
 diff --git sc/source/core/tool/address.cxx sc/source/core/tool/address.cxx
-index 2cb5dce..80dfb34 100644
+index 2cb5dce..c1906dd 100644
 --- sc/source/core/tool/address.cxx
 +++ sc/source/core/tool/address.cxx
 @@ -35,6 +35,7 @@
@@ -1031,7 +1062,7 @@
  {
      const sal_Unicode* pTmp = NULL;
      String aExternDocName, aStartTabName, aEndTabName;
-@@ -442,6 +439,15 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
+@@ -442,6 +439,18 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
  #endif
      p = lcl_ScRange_Parse_XL_Header( r, p, pDoc,
          aExternDocName, aStartTabName, aEndTabName, nFlags );
@@ -1039,15 +1070,18 @@
 +    if (aExternDocName.Len() > 0)
 +    {
 +        ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
-+        pExtInfo->mbExternal = true;
-+        pExtInfo->maTabName = aStartTabName;
-+        pExtInfo->mnFileId = pRefMgr->getExternalFileId(aExternDocName);
++        if (!pRefMgr->isOwnDocument(aExternDocName))
++        {
++            pExtInfo->mbExternal = true;
++            pExtInfo->maTabName = aStartTabName;
++            pExtInfo->mnFileId = pRefMgr->getExternalFileId(aExternDocName);
++        }
 +    }
 +
      if( NULL == p )
          return 0;
  
-@@ -480,8 +486,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
+@@ -480,8 +489,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
              r.aStart.SetCol( 0 );
              r.aEnd.SetCol( MAXCOL );
  
@@ -1057,7 +1091,7 @@
          }
          else if( NULL == (p = lcl_r1c1_get_col( p, rDetails, &r.aStart, &nFlags )))
              goto failed;
-@@ -501,8 +506,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
+@@ -501,8 +509,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
                  return nFlags;
              }
  
@@ -1067,7 +1101,7 @@
          }
          p = pTmp;
  
-@@ -517,8 +521,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
+@@ -517,8 +524,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
          }
  
          nFlags |= (nFlags2 << 4);
@@ -1077,7 +1111,7 @@
      }
      else if( *p == 'C' || *p == 'c' )   // full col C#
      {
-@@ -550,8 +553,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
+@@ -550,8 +556,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
          r.aStart.SetRow( 0 );
          r.aEnd.SetRow( MAXROW );
  
@@ -1087,7 +1121,7 @@
      }
  
  failed :
-@@ -604,7 +606,8 @@ static USHORT
+@@ -604,7 +609,8 @@ static USHORT
  lcl_ScRange_Parse_XL_A1( ScRange& r,
                           const sal_Unicode* p,
                           ScDocument* pDoc,
@@ -1097,7 +1131,7 @@
  {
      const sal_Unicode* tmp1, *tmp2;
      String aExternDocName, aStartTabName, aEndTabName; // for external link table
-@@ -619,6 +622,15 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
+@@ -619,6 +625,18 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
  #endif
      p = lcl_ScRange_Parse_XL_Header( r, p, pDoc,
          aExternDocName, aStartTabName, aEndTabName, nFlags );
@@ -1105,15 +1139,18 @@
 +    if (aExternDocName.Len() > 0)
 +    {
 +        ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
-+        pExtInfo->mbExternal = true;
-+        pExtInfo->maTabName = aStartTabName;
-+        pExtInfo->mnFileId = pRefMgr->getExternalFileId(aExternDocName);
++        if (!pRefMgr->isOwnDocument(aExternDocName))
++        {
++            pExtInfo->mbExternal = true;
++            pExtInfo->maTabName = aStartTabName;
++            pExtInfo->mnFileId = pRefMgr->getExternalFileId(aExternDocName);
++        }
 +    }
 +
      if( NULL == p )
          return 0;
  
-@@ -640,8 +652,7 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
+@@ -640,8 +658,7 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
              SCA_VALID_COL | SCA_VALID_COL2 |
              SCA_COL_ABSOLUTE | SCA_COL2_ABSOLUTE;
          nFlags |= (nFlags2 << 4);
@@ -1123,7 +1160,7 @@
      }
  
      tmp2 = lcl_a1_get_row( tmp1, &r.aStart, &nFlags );
-@@ -661,8 +672,7 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
+@@ -661,8 +678,7 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
              SCA_VALID_ROW | SCA_VALID_ROW2 |
              SCA_ROW_ABSOLUTE | SCA_ROW2_ABSOLUTE;
          nFlags |= (nFlags2 << 4);
@@ -1133,7 +1170,7 @@
      }
  
      // prepare as if it's a singleton, in case we want to fall back */
-@@ -672,8 +682,7 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
+@@ -672,8 +688,7 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
      if ( bOnlyAcceptSingle )
      {
          if ( *tmp2 == 0 )
@@ -1143,7 +1180,7 @@
          else
          {
              // any trailing invalid character must invalidate the address.
-@@ -692,12 +701,11 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
+@@ -692,12 +707,11 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
      p = tmp2;
      tmp1 = lcl_a1_get_col( p+1, &r.aEnd, &nFlags2 );
      if( !tmp1 ) // strange, but valid singleton
@@ -1159,7 +1196,7 @@
  
      if ( *tmp2 != 0 )
      {
-@@ -708,20 +716,19 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
+@@ -708,20 +722,19 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
      }
  
      nFlags |= (nFlags2 << 4);
@@ -1184,7 +1221,7 @@
  
      // Lets see if this is a reference to something in an external file.
      // A Documentname is always quoted and has a trailing #
-@@ -795,35 +802,11 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
+@@ -795,35 +808,11 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
          }
          if( *p++ != '.' )
              nBits = 0;
@@ -1224,7 +1261,7 @@
          }
          else
              nBits = 0;
-@@ -884,16 +867,30 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
+@@ -884,16 +873,32 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
          if( !nBits )
              p = q;
      }
@@ -1238,28 +1275,32 @@
 +        pRefMgr->convertToAbsName(aDocName);
 +
 +        // TODO: Do we need to check if the document exists before going further?
-+
-+        sal_uInt16 nFileId = pRefMgr->getExternalFileId(aDocName);
-+        if (pExtInfo && !pExtInfo->mbExternal)
-+        {
-+            pExtInfo->mbExternal = true;
-+            pExtInfo->maTabName = aTab;
-+            pExtInfo->mnFileId = nFileId;
-+        }
-+
-+        if (pRefMgr->getSingleRefToken(nFileId, aTab, ScAddress(nCol, nRow, 0), NULL, &nTab))
++        if (!pRefMgr->isOwnDocument(aDocName))
          {
-             nRes |= SCA_VALID_TAB;
+-            nRes |= SCA_VALID_TAB;
++            sal_uInt16 nFileId = pRefMgr->getExternalFileId(aDocName);
++            if (pExtInfo && !pExtInfo->mbExternal)
++            {
++                pExtInfo->mbExternal = true;
++                pExtInfo->maTabName = aTab;
++                pExtInfo->mnFileId = nFileId;
++            }
++    
++            if (pRefMgr->getSingleRefToken(nFileId, aTab, ScAddress(nCol, nRow, 0), NULL, &nTab))
++            {
++                nRes |= SCA_VALID_TAB;
++            }
++            else
++                nRes = 0;
          }
-         else
+-        else
 -            nRes = 0;   // #NAME? statt #REF!, Dateiname bleibt erhalten
-+            nRes = 0;
      }
 +
      if ( !(nRes & SCA_VALID_ROW) && (nRes & SCA_VALID_COL)
              && !( (nRes & SCA_TAB_3D) && (nRes & SCA_VALID_TAB)) )
      {   // keine Row, keine Tab, aber Col => DM (...), B (...) o.ae.
-@@ -912,9 +909,8 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
+@@ -912,9 +917,8 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
  }
  
  static USHORT
@@ -1271,7 +1312,7 @@
  {
      if( !*p )
          return 0;
-@@ -924,20 +920,20 @@ lcl_ScAddress_Parse ( BOOL& bExternal, const sal_Unicode* p,
+@@ -924,20 +928,20 @@ lcl_ScAddress_Parse ( BOOL& bExternal, const sal_Unicode* p,
      default :
      case ScAddress::CONV_OOO:
          {
@@ -1295,7 +1336,7 @@
              rAddr = r.aStart;
              return nFlags;
          }
-@@ -949,9 +945,8 @@ bool ConvertSingleRef( ScDocument* pDoc, const String& rRefString,
+@@ -949,9 +953,8 @@ bool ConvertSingleRef( ScDocument* pDoc, const String& rRefString,
                         SCTAB nDefTab, ScRefAddress& rRefAddress,
                         const ScAddress::Details& rDetails )
  {
@@ -1306,7 +1347,7 @@
      if( nRes & SCA_VALID )
      {
          rRefAddress.Set( aAddr,
-@@ -988,10 +983,9 @@ bool ConvertDoubleRef( ScDocument* pDoc, const String& rRefString, SCTAB nDefTab
+@@ -988,10 +991,9 @@ bool ConvertDoubleRef( ScDocument* pDoc, const String& rRefString, SCTAB nDefTab
  
  
  USHORT ScAddress::Parse( const String& r, ScDocument* pDoc,
@@ -1319,7 +1360,7 @@
  }
  
  
-@@ -1060,7 +1054,7 @@ void ScRange::ExtendTo( const ScRange& rRange )
+@@ -1060,7 +1062,7 @@ void ScRange::ExtendTo( const ScRange& rRange )
  }
  
  static USHORT
@@ -1328,7 +1369,7 @@
  {
      USHORT nRes1 = 0, nRes2 = 0;
      xub_StrLen nTmp = 0;
-@@ -1073,13 +1067,12 @@ lcl_ScRange_Parse_OOo( ScRange &aRange, const String& r, ScDocument* pDoc )
+@@ -1073,13 +1075,12 @@ lcl_ScRange_Parse_OOo( ScRange &aRange, const String& r, ScDocument* pDoc )
          String aTmp( r );
          sal_Unicode* p = aTmp.GetBufferAccess();
          p[ nPos ] = 0;
@@ -1345,7 +1386,7 @@
                      nRes2 &= ~SCA_VALID_TAB;    // #REF!
                  else
                  {
-@@ -1132,7 +1125,7 @@ lcl_ScRange_Parse_OOo( ScRange &aRange, const String& r, ScDocument* pDoc )
+@@ -1132,7 +1133,7 @@ lcl_ScRange_Parse_OOo( ScRange &aRange, const String& r, ScDocument* pDoc )
  }
  
  USHORT ScRange::Parse( const String& r, ScDocument* pDoc,
@@ -1354,7 +1395,7 @@
  {
      if ( r.Len() <= 0 )
          return 0;
-@@ -1141,13 +1134,13 @@ USHORT ScRange::Parse( const String& r, ScDocument* pDoc,
+@@ -1141,13 +1142,13 @@ USHORT ScRange::Parse( const String& r, ScDocument* pDoc,
      {
      default :
      case ScAddress::CONV_OOO:
@@ -2928,10 +2969,10 @@
  {
      DBG_ASSERT_BIFF( GetBiff() == EXC_BIFF5 );
 diff --git sc/source/filter/excel/excform8.cxx sc/source/filter/excel/excform8.cxx
-index ebf8543..46a5163 100644
+index ebf8543..e0467a0 100644
 --- sc/source/filter/excel/excform8.cxx
 +++ sc/source/filter/excel/excform8.cxx
-@@ -41,6 +41,11 @@
+@@ -41,6 +41,18 @@
  #include "xilink.hxx"
  #include "xiname.hxx"
  
@@ -2940,10 +2981,17 @@
 +#include <vector>
 +
 +using ::std::vector;
++
++ExcelToSc8::ExternalTabInfo::ExternalTabInfo() : 
++    mnFileId(0), mbExternal(false)
++{
++}
++
++// ============================================================================
  
  ExcelToSc8::ExcelToSc8( const XclImpRoot& rRoot ) :
      ExcelToSc( rRoot ),
-@@ -53,15 +58,33 @@ ExcelToSc8::~ExcelToSc8()
+@@ -53,15 +65,33 @@ ExcelToSc8::~ExcelToSc8()
  {
  }
  
@@ -2981,7 +3029,7 @@
  }
  
  
-@@ -608,8 +631,15 @@ ConvErr ExcelToSc8::Convert( const ScTokenArray*& rpTokArray, XclImpStream& aIn,
+@@ -608,8 +638,15 @@ ConvErr ExcelToSc8::Convert( const ScTokenArray*& rpTokArray, XclImpStream& aIn,
                      {
                          case xlExtName:
                          {
@@ -2999,7 +3047,7 @@
                          }
                          break;
  
-@@ -657,47 +687,67 @@ ConvErr ExcelToSc8::Convert( const ScTokenArray*& rpTokArray, XclImpStream& aIn,
+@@ -657,47 +694,67 @@ ConvErr ExcelToSc8::Convert( const ScTokenArray*& rpTokArray, XclImpStream& aIn,
  			case 0x7C:
  			case 0x3C: // Deleted 3-D Cell Reference			[    277]
  			{
@@ -3101,7 +3149,7 @@
  			}
  				break;
  			case 0x5B:
-@@ -707,55 +757,61 @@ ConvErr ExcelToSc8::Convert( const ScTokenArray*& rpTokArray, XclImpStream& aIn,
+@@ -707,55 +764,61 @@ ConvErr ExcelToSc8::Convert( const ScTokenArray*& rpTokArray, XclImpStream& aIn,
  			case 0x7D:
  			case 0x3D: // Deleted 3-D Area Reference			[    277]
  			{
@@ -3206,7 +3254,7 @@
  			}
  				break;
  			default: bError = TRUE;
-@@ -1143,7 +1199,130 @@ ConvErr ExcelToSc8::Convert( _ScRangeListTabs& rRangeList, XclImpStream& aIn, sa
+@@ -1143,7 +1206,130 @@ ConvErr ExcelToSc8::Convert( _ScRangeListTabs& rRangeList, XclImpStream& aIn, sa
  	return eRet;
  }
  
@@ -5134,7 +5182,7 @@
  public:
  	inline						XclImpChTrFmlConverter(
 diff --git sc/source/filter/inc/excform.hxx sc/source/filter/inc/excform.hxx
-index 915dd98..279cbbd 100644
+index 915dd98..3059d6d 100644
 --- sc/source/filter/inc/excform.hxx
 +++ sc/source/filter/inc/excform.hxx
 @@ -35,6 +35,7 @@
@@ -5156,7 +5204,13 @@
      virtual BOOL        GetAbsRefs( ScRangeList& rRangeList, XclImpStream& rStrm, sal_Size nLen );
  
  	void				GetDummy( const ScTokenArray*& );
-@@ -107,14 +112,24 @@ class XclImpLinkManager;
+@@ -102,19 +107,32 @@ inline BOOL ExcelToSc::IsComplRowRange( const UINT16 nRow1, const UINT16 nRow2 )
+ 	return ( ( nRow1 & 0x3FFF ) == 0x0000 ) && ( ( nRow2 & 0x3FFF ) == 0x3FFF );
+ }
+ 
++// ============================================================================
+ 
+ class XclImpLinkManager;
  
  class ExcelToSc8 : public ExcelToSc
  {
@@ -5167,6 +5221,8 @@
 +        String      maTabName;
 +        sal_uInt16  mnFileId;
 +        bool        mbExternal;
++
++        ExternalTabInfo();
 +    };
 +
  private:
@@ -5183,7 +5239,7 @@
  
  public:
                          ExcelToSc8( const XclImpRoot& rRoot );
-@@ -124,6 +139,9 @@ public:
+@@ -124,6 +142,9 @@ public:
  
      virtual ConvErr     Convert( _ScRangeListTabs&, XclImpStream& rStrm, sal_Size nFormulaLen, SCsTAB nTab, const FORMULA_TYPE eFT = FT_CellFormula );
  
@@ -5458,68 +5514,2003 @@
 +	return rChangeTrack.Read3DTabRefInfo( rFirstTab, rLastTab, rExtInfo );
  }
  
-diff --git sc/source/ui/docshell/docsh4.cxx sc/source/ui/docshell/docsh4.cxx
-index bc5975d..6701d1c 100644
---- sc/source/ui/docshell/docsh4.cxx
-+++ sc/source/ui/docshell/docsh4.cxx
-@@ -123,6 +123,7 @@ using namespace ::com::sun::star;
- #include <com/sun/star/document/UpdateDocMode.hpp>
- #include "scresid.hxx" //add by CHINA001
- #include "scabstdlg.hxx" //CHINA001
+diff --git sc/source/filter/xml/XMLDDELinksContext.cxx sc/source/filter/xml/XMLDDELinksContext.cxx
+index 81ec1d2..4ab6982 100644
+--- sc/source/filter/xml/XMLDDELinksContext.cxx
++++ sc/source/filter/xml/XMLDDELinksContext.cxx
+@@ -46,6 +46,7 @@
+ 
+ using namespace com::sun::star;
+ using namespace xmloff::token;
++using ::rtl::OUString;
+ 
+ //------------------------------------------------------------------
+ 
+diff --git sc/source/filter/xml/XMLTableShapeImportHelper.cxx sc/source/filter/xml/XMLTableShapeImportHelper.cxx
+index bb6fe74..219b5cc 100644
+--- sc/source/filter/xml/XMLTableShapeImportHelper.cxx
++++ sc/source/filter/xml/XMLTableShapeImportHelper.cxx
+@@ -49,6 +49,7 @@
+ 
+ using namespace ::com::sun::star;
+ using namespace xmloff::token;
++using ::rtl::OUString;
+ 
+ XMLTableShapeImportHelper::XMLTableShapeImportHelper(
+ 		ScXMLImport& rImp, SvXMLImportPropertyMapper *pImpMapper ) :
+diff --git sc/source/filter/xml/XMLTrackedChangesContext.cxx sc/source/filter/xml/XMLTrackedChangesContext.cxx
+index a779ddf..3b2ea17 100644
+--- sc/source/filter/xml/XMLTrackedChangesContext.cxx
++++ sc/source/filter/xml/XMLTrackedChangesContext.cxx
+@@ -48,6 +48,7 @@
+ 
+ using namespace com::sun::star;
+ using namespace xmloff::token;
++using ::rtl::OUString;
+ 
+ //-----------------------------------------------------------------------------
+ 
+diff --git sc/source/filter/xml/makefile.mk sc/source/filter/xml/makefile.mk
+index 68ee10b..d44da6b 100644
+--- sc/source/filter/xml/makefile.mk
++++ sc/source/filter/xml/makefile.mk
+@@ -57,6 +57,7 @@ CXXFILES = \
+ 		xmlexprt.cxx \
+ 		xmlbodyi.cxx \
+ 		xmltabi.cxx \
++		xmlexternaltabi.cxx \
+ 		xmlrowi.cxx \
+ 		xmlcelli.cxx \
+ 		xmlconti.cxx \
+@@ -106,6 +107,7 @@ SLOFILES =  \
+ 		$(SLO)$/xmlexprt.obj \
+ 		$(SLO)$/xmlbodyi.obj \
+ 		$(SLO)$/xmltabi.obj \
++		$(SLO)$/xmlexternaltabi.obj \
+ 		$(SLO)$/xmlrowi.obj \
+ 		$(SLO)$/xmlcelli.obj \
+ 		$(SLO)$/xmlconti.obj \
+diff --git sc/source/filter/xml/xmlbodyi.cxx sc/source/filter/xml/xmlbodyi.cxx
+index 5f3545a..76780d3 100644
+--- sc/source/filter/xml/xmlbodyi.cxx
++++ sc/source/filter/xml/xmlbodyi.cxx
+@@ -67,6 +67,7 @@
+ 
+ using namespace com::sun::star;
+ using namespace xmloff::token;
++using ::rtl::OUString;
+ 
+ //------------------------------------------------------------------
+ 
+diff --git sc/source/filter/xml/xmlcelli.cxx sc/source/filter/xml/xmlcelli.cxx
+index 92eb208..a990e54 100644
+--- sc/source/filter/xml/xmlcelli.cxx
++++ sc/source/filter/xml/xmlcelli.cxx
+@@ -146,185 +146,131 @@ ScXMLTableRowCellContext::ScXMLTableRowCellContext( ScXMLImport& rImport,
+ 	rtl::OUString aLocalName;
+ 	rtl::OUString* pStyleName = NULL;
+ 	rtl::OUString* pCurrencySymbol = NULL;
+-	for( sal_Int16 i=0; i < nAttrCount; ++i )
++    const SvXMLTokenMap& rTokenMap = rImport.GetTableRowCellAttrTokenMap();
++	for (sal_Int16 i = 0; i < nAttrCount; ++i)
+ 	{
+-		sal_uInt16 nPrefix = rXMLImport.GetNamespaceMap().GetKeyByAttrName(
+-											xAttrList->getNameByIndex( i ), &aLocalName );
+-    	const rtl::OUString& sValue(xAttrList->getValueByIndex( i ));
++        sal_uInt16 nAttrPrefix = rImport.GetNamespaceMap().GetKeyByAttrName(
++            xAttrList->getNameByIndex(i), &aLocalName);
+ 
+-		if (nPrefix == XML_NAMESPACE_TABLE)
+-		{
+-            sal_uInt32 nLength(aLocalName.getLength());
+-
+-            switch (nLength)
++        const rtl::OUString& sValue = xAttrList->getValueByIndex(i);
++        sal_uInt16 nToken = rTokenMap.Get(nAttrPrefix, aLocalName);
++        switch (nToken)
++        {
++            case XML_TOK_TABLE_ROW_CELL_ATTR_STYLE_NAME:
++                pStyleName = new rtl::OUString(sValue);
++            break;
++            case XML_TOK_TABLE_ROW_CELL_ATTR_CONTENT_VALIDATION_NAME:
++                DBG_ASSERT(!pContentValidationName, "here should be only one Validation Name");
++                pContentValidationName = new rtl::OUString(sValue);
++            break;
++            case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_ROWS:
++                bIsMerged = sal_True;
++                nMergedRows = sValue.toInt32();
++            break;
++            case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_COLS:
++                bIsMerged = sal_True;
++                nMergedCols = sValue.toInt32();
++            break;
++            case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_MATRIX_COLS:
++                bIsMatrix = sal_True;
++                nMatrixCols = sValue.toInt32();
++            break;
++            case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_MATRIX_ROWS:
++                bIsMatrix = sal_True;
++                nMatrixRows = sValue.toInt32();
++            break;
++            case XML_TOK_TABLE_ROW_CELL_ATTR_REPEATED:
++                nCellsRepeated = std::max( sValue.toInt32(), (sal_Int32) 1 );
++            break;
++            case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE_TYPE:
++                nCellType = GetScImport().GetCellType(sValue);
++                bIsEmpty = sal_False;
++            break;
++            case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE:
+             {
+-            case 7 :
+-                {
+-			        if (IsXMLToken(aLocalName, XML_FORMULA))
+-			        {
+-				        if (sValue.getLength())
+-				        {
+-					        DBG_ASSERT(!pOUFormula, "here should be only one formula");
+-                            DELETEZ( pOUFormula);
+-                            rtl::OUString sFormula;
+-				            sal_uInt16 nFormulaPrefix = GetImport().GetNamespaceMap().
+-						            _GetKeyByAttrName( sValue, &sFormula, sal_False );
+-
+-                            if (ScXMLImport::IsAcceptedFormulaNamespace(
+-                                        nFormulaPrefix, sValue, eGrammar,
+-                                        eStorageGrammar))
+-                            {
+-                                // Namespaces we accept.
+-                                pOUFormula = new rtl::OUString( sFormula);
+-                            }
+-                            else
+-                            {
+-                                // No namespace => entire string.
+-                                // Also unknown namespace included in formula,
+-                                // so hopefully will result in string or
+-                                // compile error.
+-                                pOUFormula = new rtl::OUString( sValue);
+-                            }
+-				        }
+-			        }
+-                }
+-                break;
+-            case 10 :
+-                {
+-			        if (IsXMLToken(aLocalName, XML_STYLE_NAME))
+-				        pStyleName = new rtl::OUString(sValue);
+-                }
+-                break;
+-            case 19 :
++                if (sValue.getLength())
+                 {
+-			        if (IsXMLToken(aLocalName, XML_NUMBER_ROWS_SPANNED))
+-			        {
+-				        bIsMerged = sal_True;
+-				        nMergedRows = sValue.toInt32();
+-			        }
++                    rXMLImport.GetMM100UnitConverter().convertDouble(fValue, sValue);
++                    bIsEmpty = sal_False;
+                 }
+-                break;
+-            case 22 :
+-                {
+-			        if (IsXMLToken(aLocalName, XML_NUMBER_COLUMNS_SPANNED))
+-			        {
+-				        bIsMerged = sal_True;
+-				        nMergedCols = sValue.toInt32();
+-			        }
+-                }
+-                break;
+-            case 23 :
+-                {
+-			        if (IsXMLToken(aLocalName, XML_NUMBER_COLUMNS_REPEATED))
+-                        nCellsRepeated = std::max( sValue.toInt32(), (sal_Int32) 1 );
+-                    else if (IsXMLToken(aLocalName, XML_CONTENT_VALIDATION_NAME))
+-			        {
+-				        DBG_ASSERT(!pContentValidationName, "here should be only one Validation Name");
+-				        pContentValidationName = new rtl::OUString(sValue);
+-			        }
+-                }
+-                break;
+-            case 26 :
+-                {
+-			        if (IsXMLToken(aLocalName, XML_NUMBER_MATRIX_ROWS_SPANNED))
+-			        {
+-				        bIsMatrix = sal_True;
+-				        nMatrixRows = sValue.toInt32();
+-			        }
+-                }
+-                break;
+-            case 29 :
+-                {
+-			        if (IsXMLToken(aLocalName, XML_NUMBER_MATRIX_COLUMNS_SPANNED))
+-			        {
+-				        bIsMatrix = sal_True;
+-				        nMatrixCols = sValue.toInt32();
+-			        }
+-                }
+-                break;
+             }
+-        }
+-		else if (nPrefix == XML_NAMESPACE_OFFICE)
+-		{
+-            sal_uInt32 nLength(aLocalName.getLength());
+-
+-            switch (nLength)
++            break;
++            case XML_TOK_TABLE_ROW_CELL_ATTR_DATE_VALUE:
+             {
+-            case 5 :
++                if (sValue.getLength() && rXMLImport.SetNullDateOnUnitConverter())
+                 {
+-			        if (IsXMLToken(aLocalName, XML_VALUE))
+-			        {
+-				        if (sValue.getLength())
+-				        {
+-					        rXMLImport.GetMM100UnitConverter().convertDouble(fValue, sValue);
+-					        bIsEmpty = sal_False;
+-				        }
+-			        }
++                    rXMLImport.GetMM100UnitConverter().convertDateTime(fValue, sValue);
++                    bIsEmpty = sal_False;
+                 }
+-                break;
+-            case 8 :
++            }
++            break;
++            case XML_TOK_TABLE_ROW_CELL_ATTR_TIME_VALUE:
++            {
++                if (sValue.getLength())
+                 {
+-			        if (IsXMLToken(aLocalName, XML_CURRENCY))
+-				        pCurrencySymbol = new rtl::OUString(sValue);
++                    rXMLImport.GetMM100UnitConverter().convertTime(fValue, sValue);
++                    bIsEmpty = sal_False;
+                 }
+-                break;
+-            case 10 :
++            }
++            break;
++            case XML_TOK_TABLE_ROW_CELL_ATTR_STRING_VALUE:
++            {
++                if (sValue.getLength())
+                 {
+-			        if (IsXMLToken(aLocalName, XML_VALUE_TYPE))
+-			        {
+-				        nCellType = GetCellType(sValue);
+-				        bIsEmpty = sal_False;
+-			        }
+-		            else if (IsXMLToken(aLocalName, XML_DATE_VALUE))
+-		            {
+-			            if (sValue.getLength() && rXMLImport.SetNullDateOnUnitConverter())
+-			            {
+-				            rXMLImport.GetMM100UnitConverter().convertDateTime(fValue, sValue);
+-				            bIsEmpty = sal_False;
+-			            }
+-		            }
+-		            else if (IsXMLToken(aLocalName, XML_TIME_VALUE))
+-		            {
+-			            if (sValue.getLength())
+-			            {
+-				            rXMLImport.GetMM100UnitConverter().convertTime(fValue, sValue);
+-				            bIsEmpty = sal_False;
+-			            }
+-		            }
++                    DBG_ASSERT(!pOUTextValue, "here should be only one string value");
++                    pOUTextValue = new rtl::OUString(sValue);
++                    bIsEmpty = sal_False;
+                 }
+-                break;
+-            case 12 :
++            }
++            break;
++            case XML_TOK_TABLE_ROW_CELL_ATTR_BOOLEAN_VALUE:
++            {
++                if (sValue.getLength())
+                 {
+-			        if (IsXMLToken(aLocalName, XML_STRING_VALUE))
+-			        {
+-				        if (sValue.getLength())
+-				        {
+-					        DBG_ASSERT(!pOUTextValue, "here should be only one string value");
+-					        pOUTextValue = new rtl::OUString(sValue);
+-					        bIsEmpty = sal_False;
+-				        }
+-			        }
++                    if ( IsXMLToken(sValue, XML_TRUE) )
++                        fValue = 1.0;
++                    else if ( IsXMLToken(sValue, XML_FALSE) )
++                        fValue = 0.0;
++                    else
++                        rXMLImport.GetMM100UnitConverter().convertDouble(fValue, sValue);
++                    bIsEmpty = sal_False;
+                 }
+-                break;
+-            case 13 :
++            }
++            break;
++            case XML_TOK_TABLE_ROW_CELL_ATTR_FORMULA:
++            {
++                if (sValue.getLength())
+                 {
+-			        if (IsXMLToken(aLocalName, XML_BOOLEAN_VALUE))
+-			        {
+-				        if (sValue.getLength())
+-				        {
+-					        if ( IsXMLToken(sValue, XML_TRUE) )
+-						        fValue = 1.0;
+-					        else if ( IsXMLToken(sValue, XML_FALSE) )
+-						        fValue = 0.0;
+-                            else
+-                                rXMLImport.GetMM100UnitConverter().convertDouble(fValue, sValue);
+-					        bIsEmpty = sal_False;
+-				        }
+-			        }
++                    DBG_ASSERT(!pOUFormula, "here should be only one formula");
++                    DELETEZ( pOUFormula);
++                    rtl::OUString sFormula;
++                    sal_uInt16 nFormulaPrefix = GetImport().GetNamespaceMap().
++                            _GetKeyByAttrName( sValue, &sFormula, sal_False );
++
++                    if (ScXMLImport::IsAcceptedFormulaNamespace(
++                                nFormulaPrefix, sValue, eGrammar,
++                                eStorageGrammar))
++                    {
++                        // Namespaces we accept.
++                        pOUFormula = new rtl::OUString( sFormula);
++                    }
++                    else
++                    {
++                        // No namespace => entire string.
++                        // Also unknown namespace included in formula,
++                        // so hopefully will result in string or
++                        // compile error.
++                        pOUFormula = new rtl::OUString( sValue);
++                    }
+                 }
+-                break;
+             }
+-		}
++            break;
++            case XML_TOK_TABLE_ROW_CELL_ATTR_CURRENCY:
++                pCurrencySymbol = new rtl::OUString(sValue);
++            break;
++            default:
++                ;
++        }
+ 	}
+ 	if (pOUFormula)
+ 	{
+@@ -335,32 +281,6 @@ ScXMLTableRowCellContext::ScXMLTableRowCellContext( ScXMLImport& rImport,
+ 	rXMLImport.GetStylesImportHelper()->SetAttributes(pStyleName, pCurrencySymbol, nCellType);
+ }
+ 
+-sal_Int16 ScXMLTableRowCellContext::GetCellType(const rtl::OUString& sOUValue) const
+-{
+-	if (IsXMLToken(sOUValue, XML_FLOAT))
+-		return util::NumberFormat::NUMBER;
+-	else
+-		if (IsXMLToken(sOUValue, XML_STRING))
+-			return util::NumberFormat::TEXT;
+-		else
+-			if (IsXMLToken(sOUValue, XML_TIME))
+-				return util::NumberFormat::TIME;
+-			else
+-				if (IsXMLToken(sOUValue, XML_DATE))
+-					return util::NumberFormat::DATETIME;
+-				else
+-					if (IsXMLToken(sOUValue, XML_PERCENTAGE))
+-						return util::NumberFormat::PERCENT;
+-					else
+-						if (IsXMLToken(sOUValue, XML_CURRENCY))
+-							return util::NumberFormat::CURRENCY;
+-						else
+-							if (IsXMLToken(sOUValue, XML_BOOLEAN))
+-								return util::NumberFormat::LOGICAL;
+-							else
+-								return util::NumberFormat::UNDEFINED;
+-}
+-
+ ScXMLTableRowCellContext::~ScXMLTableRowCellContext()
+ {
+ 	if (pOUTextValue)
+diff --git sc/source/filter/xml/xmlcelli.hxx sc/source/filter/xml/xmlcelli.hxx
+index b1de3ee..589077d 100644
+--- sc/source/filter/xml/xmlcelli.hxx
++++ sc/source/filter/xml/xmlcelli.hxx
+@@ -95,8 +95,6 @@ class ScXMLTableRowCellContext : public SvXMLImportContext
+ 	const ScXMLImport& GetScImport() const { return (const ScXMLImport&)GetImport(); }
+ 	ScXMLImport& GetScImport() { return (ScXMLImport&)GetImport(); }
+ 
+-	sal_Int16 GetCellType(const rtl::OUString& sOUValue) const;
+-
+ 	sal_Bool IsMerged (const com::sun::star::uno::Reference <com::sun::star::table::XCellRange>& xCellRange,
+ 				const sal_Int32 nCol, const sal_Int32 nRow,
+ 				com::sun::star::table::CellRangeAddress& aCellAddress) const;
+diff --git sc/source/filter/xml/xmldpimp.cxx sc/source/filter/xml/xmldpimp.cxx
+index e29223a..604e04e 100644
+--- sc/source/filter/xml/xmldpimp.cxx
++++ sc/source/filter/xml/xmldpimp.cxx
+@@ -65,6 +65,7 @@
+ 
+ using namespace com::sun::star;
+ using namespace xmloff::token;
++using ::rtl::OUString;
+ 
+ //------------------------------------------------------------------
+ 
+diff --git sc/source/filter/xml/xmlexprt.cxx sc/source/filter/xml/xmlexprt.cxx
+index 52f5145..38a37d6 100644
+--- sc/source/filter/xml/xmlexprt.cxx
++++ sc/source/filter/xml/xmlexprt.cxx
+@@ -68,6 +68,7 @@
+ #include "convuno.hxx"
+ #include "postit.hxx"
+ #include "tabprotection.hxx"
 +#include "externalrefmgr.hxx"
  
- #include "sharedocdlg.hxx"
+ #include <xmloff/xmltoken.hxx>
+ #include <xmloff/xmlnmspe.hxx>
+@@ -129,6 +130,8 @@
  
-@@ -540,6 +541,7 @@ void ScDocShell::Execute( SfxRequest& rReq )
- 				if (nDlgRet == RET_YES || nSet==LM_ALWAYS)
- 				{
- 					ReloadTabLinks();
-+                    aDocument.UpdateExternalRefLinks();
- 					aDocument.UpdateDdeLinks();
- 					aDocument.UpdateAreaLinks();
+ #include <sfx2/objsh.hxx>
  
-diff --git sc/source/ui/docshell/externalrefmgr.cxx sc/source/ui/docshell/externalrefmgr.cxx
-new file mode 100644
-index 0000000..8b5858d
---- /dev/null
-+++ sc/source/ui/docshell/externalrefmgr.cxx
-@@ -0,0 +1,1161 @@
-+/*************************************************************************
-+ *
-+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-+ * 
-+ * Copyright 2008 by Sun Microsystems, Inc.
-+ *
-+ * OpenOffice.org - a multi-platform office productivity suite
-+ *
-+ * $RCSfile: document.hxx,v $
-+ * $Revision: 1.112 $
-+ *
-+ * This file is part of OpenOffice.org.
-+ *
-+ * OpenOffice.org is free software: you can redistribute it and/or modify
-+ * it under the terms of the GNU Lesser General Public License version 3
-+ * only, as published by the Free Software Foundation.
-+ *
-+ * OpenOffice.org is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU Lesser General Public License version 3 for more details
-+ * (a copy is included in the LICENSE file that accompanied this code).
-+ *
-+ * You should have received a copy of the GNU Lesser General Public License
-+ * version 3 along with OpenOffice.org.  If not, see
-+ * <http://www.openoffice.org/license.html>
-+ * for a copy of the LGPLv3 License.
-+ *
-+ ************************************************************************/
++#include <vector>
 +
-+// MARKER(update_precomp.py): autogen include statement, do not remove
-+#include "precompiled_sc.hxx"
+ //! not found in unonames.hxx
+ #define SC_STANDARDFORMAT "StandardFormat"
+ #define SC_LAYERID "LayerID"
+@@ -152,6 +155,7 @@
+ using namespace rtl;
+ using namespace com::sun::star;
+ using namespace xmloff::token;
++using ::std::vector;
+ 
+ //----------------------------------------------------------------------------
+ 
+@@ -479,6 +483,12 @@ ScXMLExport::ScXMLExport(
+ 
+ 	if( (getExportFlags() & (EXPORT_STYLES|EXPORT_AUTOSTYLES|EXPORT_MASTERSTYLES|EXPORT_CONTENT) ) != 0 )
+     {
++        // This name is reserved for the external ref cache tables.  This
++        // should not conflict with user-defined styles since this name is
++        // used for a table style which is not available in the UI.
++        sExternalRefTabStyleName = rtl::OUString::createFromAscii("ta_extref");
++        GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TABLE_TABLE, sExternalRefTabStyleName);
++
+         sAttrName = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_NAME));
+         sAttrStyleName = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_STYLE_NAME));
+         sAttrColumnsRepeated = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_NUMBER_COLUMNS_REPEATED));
+@@ -1422,180 +1432,181 @@ void ScXMLExport::_ExportContent()
+ 		DBG_ERROR("no shared data setted");
+ 	}
+ 	ScXMLExportDatabaseRanges aExportDatabaseRanges(*this);
+-	if (!GetModel().is())
++    if (!GetModel().is())
+         return;
+ 
+-		uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( GetModel(), uno::UNO_QUERY );
++    uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( GetModel(), uno::UNO_QUERY );
+     if ( !xSpreadDoc.is() )
+         return;
+ 
+-			uno::Reference<container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY );
+-			if ( xIndex.is() )
+-			{
+-				//_GetNamespaceMap().ClearQNamesCache();
+-				pChangeTrackingExportHelper->CollectAndWriteChanges();
+-				WriteCalculationSettings(xSpreadDoc);
+-				sal_Int32 nTableCount(xIndex->getCount());
+-				ScMyAreaLinksContainer aAreaLinks;
+-				GetAreaLinks( xSpreadDoc, aAreaLinks );
+-				ScMyEmptyDatabaseRangesContainer aEmptyRanges(aExportDatabaseRanges.GetEmptyDatabaseRanges());
+-				ScMyDetectiveOpContainer aDetectiveOpContainer;
+-				GetDetectiveOpList( aDetectiveOpContainer );
+-
+-				pCellStyles->Sort();
+-				pMergedRangesContainer->Sort();
+-				pSharedData->GetDetectiveObjContainer()->Sort();
+-
+-				pCellsItr->Clear();
+-				pCellsItr->SetShapes( pSharedData->GetShapesContainer() );
+-				pCellsItr->SetNoteShapes( pSharedData->GetNoteShapes() );
+-				pCellsItr->SetMergedRanges( pMergedRangesContainer );
+-				pCellsItr->SetAreaLinks( &aAreaLinks );
+-				pCellsItr->SetEmptyDatabaseRanges( &aEmptyRanges );
+-				pCellsItr->SetDetectiveObj( pSharedData->GetDetectiveObjContainer() );
+-				pCellsItr->SetDetectiveOp( &aDetectiveOpContainer );
+-
+-				if (nTableCount > 0)
+-					pValidationsContainer->WriteValidations(*this);
+-				WriteTheLabelRanges( xSpreadDoc );
+-				for (sal_Int32 nTable = 0; nTable < nTableCount; ++nTable)
+-				{
+-                    uno::Reference<sheet::XSpreadsheet> xTable(xIndex->getByIndex(nTable), uno::UNO_QUERY);
+-					if (xTable.is())
+-					{
+-						xCurrentTable.set(xTable);
+-                        xCurrentTableCellRange.set(xTable, uno::UNO_QUERY);
+-						uno::Reference<container::XNamed> xName (xTable, uno::UNO_QUERY );
+-						if ( xName.is() )
+-						{
+-                            nCurrentTable = sal::static_int_cast<sal_uInt16>( nTable );
+-							rtl::OUString sOUTableName(xName->getName());
+-							AddAttribute(sAttrName, sOUTableName);
+-							AddAttribute(sAttrStyleName, aTableStyles[nTable]);
+-							uno::Reference<util::XProtectable> xProtectable (xTable, uno::UNO_QUERY);
+-							if (xProtectable.is() && xProtectable->isProtected())
+-							{
+-								AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTED, XML_TRUE);
+-								rtl::OUStringBuffer aBuffer;
+-								if (pDoc)
++    uno::Reference<container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY );
++    if ( xIndex.is() )
++    {
++        //_GetNamespaceMap().ClearQNamesCache();
++        pChangeTrackingExportHelper->CollectAndWriteChanges();
++        WriteCalculationSettings(xSpreadDoc);
++        sal_Int32 nTableCount(xIndex->getCount());
++        ScMyAreaLinksContainer aAreaLinks;
++        GetAreaLinks( xSpreadDoc, aAreaLinks );
++        ScMyEmptyDatabaseRangesContainer aEmptyRanges(aExportDatabaseRanges.GetEmptyDatabaseRanges());
++        ScMyDetectiveOpContainer aDetectiveOpContainer;
++        GetDetectiveOpList( aDetectiveOpContainer );
++
++        pCellStyles->Sort();
++        pMergedRangesContainer->Sort();
++        pSharedData->GetDetectiveObjContainer()->Sort();
++
++        pCellsItr->Clear();
++        pCellsItr->SetShapes( pSharedData->GetShapesContainer() );
++        pCellsItr->SetNoteShapes( pSharedData->GetNoteShapes() );
++        pCellsItr->SetMergedRanges( pMergedRangesContainer );
++        pCellsItr->SetAreaLinks( &aAreaLinks );
++        pCellsItr->SetEmptyDatabaseRanges( &aEmptyRanges );
++        pCellsItr->SetDetectiveObj( pSharedData->GetDetectiveObjContainer() );
++        pCellsItr->SetDetectiveOp( &aDetectiveOpContainer );
++
++        if (nTableCount > 0)
++            pValidationsContainer->WriteValidations(*this);
++        WriteTheLabelRanges( xSpreadDoc );
++        for (sal_Int32 nTable = 0; nTable < nTableCount; ++nTable)
++        {
++            uno::Reference<sheet::XSpreadsheet> xTable(xIndex->getByIndex(nTable), uno::UNO_QUERY);
++            if (xTable.is())
++            {
++                xCurrentTable.set(xTable);
++                xCurrentTableCellRange.set(xTable, uno::UNO_QUERY);
++                uno::Reference<container::XNamed> xName (xTable, uno::UNO_QUERY );
++                if ( xName.is() )
++                {
++                    nCurrentTable = sal::static_int_cast<sal_uInt16>( nTable );
++                    rtl::OUString sOUTableName(xName->getName());
++                    AddAttribute(sAttrName, sOUTableName);
++                    AddAttribute(sAttrStyleName, aTableStyles[nTable]);
++                    uno::Reference<util::XProtectable> xProtectable (xTable, uno::UNO_QUERY);
++                    if (xProtectable.is() && xProtectable->isProtected())
++                    {
++                        AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTED, XML_TRUE);
++                        rtl::OUStringBuffer aBuffer;
++                        if (pDoc)
++                        {
++                            ScTableProtection* pProtect = pDoc->GetTabProtection(static_cast<SCTAB>(nTable));
++                            if (pProtect)
++                                SvXMLUnitConverter::encodeBase64(aBuffer, pProtect->getPasswordHash(PASSHASH_OOO));
++                        }
++                        if (aBuffer.getLength())
++                            AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY, aBuffer.makeStringAndClear());
++                    }
++                    rtl::OUString sPrintRanges;
++                    table::CellRangeAddress aColumnHeaderRange;
++                    sal_Bool bHasColumnHeader;
++                    GetColumnRowHeader(bHasColumnHeader, aColumnHeaderRange, bHasRowHeader, aRowHeaderRange, sPrintRanges);
++                    if( sPrintRanges.getLength() )
++                        AddAttribute( XML_NAMESPACE_TABLE, XML_PRINT_RANGES, sPrintRanges );
++                    else if (!pDoc->IsPrintEntireSheet(static_cast<SCTAB>(nTable)))
++                        AddAttribute( XML_NAMESPACE_TABLE, XML_PRINT, XML_FALSE);
++                    SvXMLElementExport aElemT(*this, sElemTab, sal_True, sal_True);
++                    CheckAttrList();
++                    WriteTableSource();
++                    WriteScenario();
++                    uno::Reference<drawing::XDrawPage> xDrawPage;
++                    if (pSharedData->HasForm(nTable, xDrawPage) && xDrawPage.is())
++                    {
++                        ::xmloff::OOfficeFormsExport aForms(*this);
++                        GetFormExport()->exportForms( xDrawPage );
++                        sal_Bool bRet(GetFormExport()->seekPage( xDrawPage ));
++                        DBG_ASSERT( bRet, "OFormLayerXMLExport::seekPage failed!" );
++                        (void)bRet;     // avoid warning in product version
++                    }
++                    if (pSharedData->HasDrawPage())
++                    {
++                        GetShapeExport()->seekShapes(uno::Reference<drawing::XShapes>(pSharedData->GetDrawPage(nTable), uno::UNO_QUERY));
++                        WriteTableShapes();
++                    }
++                    table::CellRangeAddress aRange(GetEndAddress(xTable, nTable));
++                    pSharedData->SetLastColumn(nTable, aRange.EndColumn);
++                    pSharedData->SetLastRow(nTable, aRange.EndRow);
++                    pCellsItr->SetCurrentTable(static_cast<SCTAB>(nTable), xCurrentTable);
++                    pGroupColumns->NewTable();
++                    pGroupRows->NewTable();
++                    FillColumnRowGroups();
++                    if (bHasColumnHeader)
++                        pSharedData->SetLastColumn(nTable, aColumnHeaderRange.EndColumn);
++                    bRowHeaderOpen = sal_False;
++                    if (bHasRowHeader)
++                        pSharedData->SetLastRow(nTable, aRowHeaderRange.EndRow);
++                    pDefaults->FillDefaultStyles(nTable, pSharedData->GetLastRow(nTable),
++                        pSharedData->GetLastColumn(nTable), pCellStyles, pDoc);
++                    pRowFormatRanges->SetRowDefaults(pDefaults->GetRowDefaults());
++                    pRowFormatRanges->SetColDefaults(pDefaults->GetColDefaults());
++                    pCellStyles->SetRowDefaults(pDefaults->GetRowDefaults());
++                    pCellStyles->SetColDefaults(pDefaults->GetColDefaults());
++                    ExportColumns(nTable, aColumnHeaderRange, bHasColumnHeader);
++                    sal_Bool bIsFirst(sal_True);
++                    sal_Int32 nEqualCells(0);
++                    ScMyCell aCell;
++                    ScMyCell aPrevCell;
++                    while(pCellsItr->GetNext(aCell, pCellStyles))
++                    {
++                        if (bIsFirst)
++                        {
++                            ExportFormatRanges(0, 0, aCell.aCellAddress.Column - 1, aCell.aCellAddress.Row, nTable);
++                            aPrevCell = aCell;
++                            bIsFirst = sal_False;
++                        }
++                        else
++                        {
++                            if ((aPrevCell.aCellAddress.Row == aCell.aCellAddress.Row) &&
++                                (aPrevCell.aCellAddress.Column + nEqualCells + 1 == aCell.aCellAddress.Column))
++                            {
++                                if(IsCellEqual(aPrevCell, aCell))
++                                    ++nEqualCells;
++                                else
+                                 {
+-                                    ScTableProtection* pProtect = pDoc->GetTabProtection(static_cast<SCTAB>(nTable));
+-                                    if (pProtect)
+-                                        SvXMLUnitConverter::encodeBase64(aBuffer, pProtect->getPasswordHash(PASSHASH_OOO));
++                                    SetRepeatAttribute(nEqualCells);
++                                    WriteCell(aPrevCell);
++                                    nEqualCells = 0;
++                                    aPrevCell = aCell;
+                                 }
+-								if (aBuffer.getLength())
+-									AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY, aBuffer.makeStringAndClear());
+-							}
+-							rtl::OUString sPrintRanges;
+-							table::CellRangeAddress aColumnHeaderRange;
+-							sal_Bool bHasColumnHeader;
+-                            GetColumnRowHeader(bHasColumnHeader, aColumnHeaderRange, bHasRowHeader, aRowHeaderRange, sPrintRanges);
+-							if( sPrintRanges.getLength() )
+-								AddAttribute( XML_NAMESPACE_TABLE, XML_PRINT_RANGES, sPrintRanges );
+-                            else if (!pDoc->IsPrintEntireSheet(static_cast<SCTAB>(nTable)))
+-                                AddAttribute( XML_NAMESPACE_TABLE, XML_PRINT, XML_FALSE);
+-							SvXMLElementExport aElemT(*this, sElemTab, sal_True, sal_True);
+-							CheckAttrList();
+-							WriteTableSource();
+-							WriteScenario();
+-							uno::Reference<drawing::XDrawPage> xDrawPage;
+-							if (pSharedData->HasForm(nTable, xDrawPage) && xDrawPage.is())
+-							{
+-								::xmloff::OOfficeFormsExport aForms(*this);
+-								GetFormExport()->exportForms( xDrawPage );
+-								sal_Bool bRet(GetFormExport()->seekPage( xDrawPage ));
+-								DBG_ASSERT( bRet, "OFormLayerXMLExport::seekPage failed!" );
+-                                (void)bRet;     // avoid warning in product version
+-							}
+-							if (pSharedData->HasDrawPage())
+-							{
+-								GetShapeExport()->seekShapes(uno::Reference<drawing::XShapes>(pSharedData->GetDrawPage(nTable), uno::UNO_QUERY));
+-								WriteTableShapes();
+-							}
+-							table::CellRangeAddress aRange(GetEndAddress(xTable, nTable));
+-							pSharedData->SetLastColumn(nTable, aRange.EndColumn);
+-							pSharedData->SetLastRow(nTable, aRange.EndRow);
+-							pCellsItr->SetCurrentTable(static_cast<SCTAB>(nTable), xCurrentTable);
+-							pGroupColumns->NewTable();
+-							pGroupRows->NewTable();
+-							FillColumnRowGroups();
+-							if (bHasColumnHeader)
+-								pSharedData->SetLastColumn(nTable, aColumnHeaderRange.EndColumn);
+-							bRowHeaderOpen = sal_False;
+-							if (bHasRowHeader)
+-								pSharedData->SetLastRow(nTable, aRowHeaderRange.EndRow);
+-							pDefaults->FillDefaultStyles(nTable, pSharedData->GetLastRow(nTable),
+-								pSharedData->GetLastColumn(nTable), pCellStyles, pDoc);
+-							pRowFormatRanges->SetRowDefaults(pDefaults->GetRowDefaults());
+-							pRowFormatRanges->SetColDefaults(pDefaults->GetColDefaults());
+-							pCellStyles->SetRowDefaults(pDefaults->GetRowDefaults());
+-							pCellStyles->SetColDefaults(pDefaults->GetColDefaults());
+-							ExportColumns(nTable, aColumnHeaderRange, bHasColumnHeader);
+-							sal_Bool bIsFirst(sal_True);
+-							sal_Int32 nEqualCells(0);
+-							ScMyCell aCell;
+-							ScMyCell aPrevCell;
+-							while(pCellsItr->GetNext(aCell, pCellStyles))
+-							{
+-								if (bIsFirst)
+-								{
+-									ExportFormatRanges(0, 0, aCell.aCellAddress.Column - 1, aCell.aCellAddress.Row, nTable);
+-									aPrevCell = aCell;
+-									bIsFirst = sal_False;
+-								}
+-								else
+-								{
+-									if ((aPrevCell.aCellAddress.Row == aCell.aCellAddress.Row) &&
+-										(aPrevCell.aCellAddress.Column + nEqualCells + 1 == aCell.aCellAddress.Column))
+-									{
+-										if(IsCellEqual(aPrevCell, aCell))
+-											++nEqualCells;
+-										else
+-										{
+-											SetRepeatAttribute(nEqualCells);
+-											WriteCell(aPrevCell);
+-											nEqualCells = 0;
+-											aPrevCell = aCell;
+-										}
+-									}
+-									else
+-									{
+-										SetRepeatAttribute(nEqualCells);
+-										WriteCell(aPrevCell);
+-										ExportFormatRanges(aPrevCell.aCellAddress.Column + nEqualCells + 1, aPrevCell.aCellAddress.Row,
+-											aCell.aCellAddress.Column - 1, aCell.aCellAddress.Row, nTable);
+-										nEqualCells = 0;
+-										aPrevCell = aCell;
+-									}
+-								}
+-							}
+-							if (!bIsFirst)
+-							{
+-								SetRepeatAttribute(nEqualCells);
+-								WriteCell(aPrevCell);
+-								ExportFormatRanges(aPrevCell.aCellAddress.Column + nEqualCells + 1, aPrevCell.aCellAddress.Row,
+-									pSharedData->GetLastColumn(nTable), pSharedData->GetLastRow(nTable), nTable);
+-							}
+-							else
+-								ExportFormatRanges(0, 0, pSharedData->GetLastColumn(nTable), pSharedData->GetLastRow(nTable), nTable);
+-							CloseRow(pSharedData->GetLastRow(nTable));
+-							nEqualCells = 0;
+-						}
+-					}
+-                    RemoveTempAnnotaionShape(nTable);
++                            }
++                            else
++                            {
++                                SetRepeatAttribute(nEqualCells);
++                                WriteCell(aPrevCell);
++                                ExportFormatRanges(aPrevCell.aCellAddress.Column + nEqualCells + 1, aPrevCell.aCellAddress.Row,
++                                    aCell.aCellAddress.Column - 1, aCell.aCellAddress.Row, nTable);
++                                nEqualCells = 0;
++                                aPrevCell = aCell;
++                            }
++                        }
++                    }
++                    if (!bIsFirst)
++                    {
++                        SetRepeatAttribute(nEqualCells);
++                        WriteCell(aPrevCell);
++                        ExportFormatRanges(aPrevCell.aCellAddress.Column + nEqualCells + 1, aPrevCell.aCellAddress.Row,
++                            pSharedData->GetLastColumn(nTable), pSharedData->GetLastRow(nTable), nTable);
++                    }
++                    else
++                        ExportFormatRanges(0, 0, pSharedData->GetLastColumn(nTable), pSharedData->GetLastRow(nTable), nTable);
++                    CloseRow(pSharedData->GetLastRow(nTable));
++                    nEqualCells = 0;
++                }
++            }
++            RemoveTempAnnotaionShape(nTable);
+ 
+-					IncrementProgressBar(sal_False);
+-				}
+-			}
+-			WriteNamedExpressions(xSpreadDoc);
+-			aExportDatabaseRanges.WriteDatabaseRanges(xSpreadDoc);
+-			ScXMLExportDataPilot aExportDataPilot(*this);
+-			aExportDataPilot.WriteDataPilots(xSpreadDoc);
+-			WriteConsolidation();
+-			ScXMLExportDDELinks aExportDDELinks(*this);
+-			aExportDDELinks.WriteDDELinks(xSpreadDoc);
+-            IncrementProgressBar(sal_True, 0);
+-			GetProgressBarHelper()->SetValue(GetProgressBarHelper()->GetReference());
++            IncrementProgressBar(sal_False);
++        }
++    }
++    WriteExternalRefCaches();
++    WriteNamedExpressions(xSpreadDoc);
++    aExportDatabaseRanges.WriteDatabaseRanges(xSpreadDoc);
++    ScXMLExportDataPilot aExportDataPilot(*this);
++    aExportDataPilot.WriteDataPilots(xSpreadDoc);
++    WriteConsolidation();
++    ScXMLExportDDELinks aExportDDELinks(*this);
++    aExportDDELinks.WriteDDELinks(xSpreadDoc);
++    IncrementProgressBar(sal_True, 0);
++    GetProgressBarHelper()->SetValue(GetProgressBarHelper()->GetReference());
+ }
+ 
+ void ScXMLExport::_ExportStyles( sal_Bool bUsed )
+@@ -2000,6 +2011,15 @@ void ScXMLExport::_ExportAutoStyles()
+ 
+ 					GetShapeExport()->exportAutoStyles();
+ 					GetFormExport()->exportAutoStyles( );
 +
++                    {
++                        // Special table style for the external ref cache tables.
++                        AddAttribute(XML_NAMESPACE_STYLE, XML_NAME, sExternalRefTabStyleName);
++                        AddAttribute(XML_NAMESPACE_STYLE, XML_FAMILY, XML_TABLE);
++                        SvXMLElementExport aElemStyle(*this, XML_NAMESPACE_STYLE, XML_STYLE, sal_True, sal_True);
++                        AddAttribute(XML_NAMESPACE_TABLE,  XML_DISPLAY, XML_FALSE);
++                        SvXMLElementExport aElemStyleTabProps(*this, XML_NAMESPACE_STYLE, XML_TABLE_PROPERTIES, sal_True, sal_True);
++                    }
+ 				}
+ 				if (getExportFlags() & EXPORT_MASTERSTYLES)
+ 				{
+@@ -3316,6 +3336,182 @@ void ScXMLExport::WriteNamedExpressions(const com::sun::star::uno::Reference <co
+ 	}
+ }
+ 
++void ScXMLExport::WriteExternalRefCaches()
++{
++    if (!pDoc)
++        return;
 +
++    ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
++    sal_uInt16 nCount = pRefMgr->getCachedFileCount();
++    for (sal_uInt16 nFileId = 0; nFileId < nCount; ++nFileId)
++    {
++        const String* pUrl = pRefMgr->getExternalFileName(nFileId);
++        if (!pUrl)
++            continue;
 +
-+// INCLUDE ---------------------------------------------------------------
++        const vector<String>* pTabNames = pRefMgr->getAllCachedTableNames(nFileId);
++        if (!pTabNames)
++            continue;
++
++        for (vector<String>::const_iterator itr = pTabNames->begin(), itrEnd = pTabNames->end();
++              itr != itrEnd; ++itr)
++        {
++            ScExternalRefCache::Table* pTable = pRefMgr->getCacheTable(nFileId, *itr);
++            if (!pTable)
++                continue;
++
++            OUStringBuffer aBuf;
++            aBuf.append(sal_Unicode('\''));
++            aBuf.append(*pUrl);
++            aBuf.append(sal_Unicode('\''));
++            aBuf.append(sal_Unicode('#'));
++            aBuf.append(*itr);
++            AddAttribute(XML_NAMESPACE_TABLE, XML_NAME, aBuf.makeStringAndClear());
++            AddAttribute(XML_NAMESPACE_TABLE, XML_PRINT, GetXMLToken(XML_FALSE));
++            AddAttribute(XML_NAMESPACE_TABLE, XML_STYLE_NAME, sExternalRefTabStyleName);
++            SvXMLElementExport aElemTable(*this, XML_NAMESPACE_TABLE, XML_TABLE, sal_True, sal_True);
++            {
++                const ScExternalRefManager::SrcFileData* pExtFileData = pRefMgr->getExternalFileData(nFileId);
++                if (pExtFileData)
++                {
++                    String aRelUrl;
++                    if (pExtFileData->maRelativeName.Len())
++                        aRelUrl = pExtFileData->maRelativeName;
++                    else
++                        aRelUrl = GetRelativeReference(pExtFileData->maRelativeName);
++                    AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, aRelUrl);
++                    AddAttribute(XML_NAMESPACE_TABLE, XML_NAME, *itr);
++                    if (pExtFileData->maFilterName.Len())
++                        AddAttribute(XML_NAMESPACE_TABLE, XML_FILTER_NAME, pExtFileData->maFilterName);
++                    if (pExtFileData->maFilterOptions.Len())
++                        AddAttribute(XML_NAMESPACE_TABLE, XML_FILTER_OPTIONS, pExtFileData->maFilterOptions);
++                    AddAttribute(XML_NAMESPACE_TABLE, XML_MODE, XML_COPY_RESULTS_ONLY);
++                }
++                SvXMLElementExport aElemTableSource(*this, XML_NAMESPACE_TABLE, XML_TABLE_SOURCE, sal_True, sal_True);
++            }
++
++            // Write cache content for this table.
++            vector<SCROW> aRows;
++            pTable->getAllRows(aRows);
++            SCROW nLastRow = 0;
++            bool bFirstRow = true;
++            for (vector<SCROW>::const_iterator itrRow = aRows.begin(), itrRowEnd = aRows.end();
++                  itrRow != itrRowEnd; ++itrRow)
++            {
++                SCROW nRow = *itrRow;
++                if (bFirstRow)
++                {
++                    if (nRow > 0)
++                    {   
++                        if (nRow > 1)
++                        {
++                            OUStringBuffer aVal;
++                            aVal.append(nRow);
++                            AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_REPEATED, aVal.makeStringAndClear());
++                        }
++                        SvXMLElementExport aElemRow(*this, XML_NAMESPACE_TABLE, XML_TABLE_ROW, sal_True, sal_True);
++                        OUStringBuffer aVal;
++                        aVal.append(static_cast<sal_Int32>(MAXCOLCOUNT));
++                        AddAttribute(XML_NAMESPACE_TABLE,  XML_NUMBER_COLUMNS_REPEATED, aVal.makeStringAndClear());
++                        SvXMLElementExport aElemCell(*this, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True);
++                    }
++                }
++                else
++                {
++                    SCROW nRowGap = nRow - nLastRow;
++                    if (nRowGap > 1)
++                    {
++                        if (nRowGap > 2)
++                        {
++                            OUStringBuffer aVal;
++                            aVal.append(static_cast<sal_Int32>(nRowGap-1));
++                            AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_REPEATED, aVal.makeStringAndClear());
++                        }
++                        SvXMLElementExport aElemRow(*this, XML_NAMESPACE_TABLE, XML_TABLE_ROW, sal_True, sal_True);
++                        OUStringBuffer aVal;
++                        aVal.append(static_cast<sal_Int32>(MAXCOLCOUNT));
++                        AddAttribute(XML_NAMESPACE_TABLE,  XML_NUMBER_COLUMNS_REPEATED, aVal.makeStringAndClear());
++                        SvXMLElementExport aElemCell(*this, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True);
++                    }
++                }
++                SvXMLElementExport aElemRow(*this, XML_NAMESPACE_TABLE, XML_TABLE_ROW, sal_True, sal_True);
++
++                vector<SCCOL> aCols;
++                pTable->getAllCols(nRow, aCols);
++                SCCOL nLastCol = 0;
++                bool bFirstCol = true;
++                for (vector<SCCOL>::const_iterator itrCol = aCols.begin(), itrColEnd = aCols.end();
++                      itrCol != itrColEnd; ++itrCol)
++                {
++                    SCCOL nCol = *itrCol;
++                    if (bFirstCol)
++                    {
++                        if (nCol > 0)
++                        {   
++                            if (nCol > 1)
++                            {
++                                OUStringBuffer aVal;
++                                aVal.append(static_cast<sal_Int32>(nCol));
++                                AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED, aVal.makeStringAndClear());
++                            }
++                            SvXMLElementExport aElemCell(*this, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True);
++                        }
++                    }
++                    else
++                    {
++                        SCCOL nColGap = nCol - nLastCol;
++                        if (nColGap > 1)
++                        {
++                            if (nColGap > 2)
++                            {
++                                OUStringBuffer aVal;
++                                aVal.append(static_cast<sal_Int32>(nColGap-1));
++                                AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED, aVal.makeStringAndClear());
++                            }
++                            SvXMLElementExport aElemCell(*this, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True);
++                        }
++                    }
++
++                    // Write out this cell.
++                    ScToken* pToken = pTable->getCell(nRow, nCol).get();
++                    OUString aStrVal;
++                    if (pToken)
++                    {
++                        switch(pToken->GetType())
++                        {
++                            case svDouble:
++                            {
++                                AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT);
++                                OUStringBuffer aVal;
++                                aVal.append(pToken->GetDouble());
++                                aStrVal = aVal.makeStringAndClear();
++                                AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE, aStrVal);
++                            }
++                            break;
++                            case svString:
++                            {
++                                AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_STRING);
++                                aStrVal = pToken->GetString();
++                            }
++                            break;
++                            default:
++                                ;
++                        }
++                    }
++                    SvXMLElementExport aElemCell(*this, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True);
++                    SvXMLElementExport aElemText(*this, XML_NAMESPACE_TEXT, XML_P, sal_True, sal_True);
++                    Characters(aStrVal);
++
++                    nLastCol = nCol;
++                    bFirstCol = false;
++                }
++                nLastRow = nRow;
++                bFirstRow = false;
++            }
++        }
++    }
++}
++
+ // core implementation
+ void ScXMLExport::WriteConsolidation()
+ {
+diff --git sc/source/filter/xml/xmlexprt.hxx sc/source/filter/xml/xmlexprt.hxx
+index 779f94e..6a366f5 100644
+--- sc/source/filter/xml/xmlexprt.hxx
++++ sc/source/filter/xml/xmlexprt.hxx
+@@ -98,6 +98,7 @@ class ScXMLExport : public SvXMLExport
+ 	ScChangeTrackingExportHelper*	pChangeTrackingExportHelper;
+ 	const rtl::OUString			sLayerID;
+ 	const rtl::OUString			sCaptionShape;
++    rtl::OUString               sExternalRefTabStyleName;
+     rtl::OUString               sAttrName;
+     rtl::OUString               sAttrStyleName;
+     rtl::OUString               sAttrColumnsRepeated;
+@@ -194,6 +195,7 @@ class ScXMLExport : public SvXMLExport
+ 	void WriteTheLabelRanges(const com::sun::star::uno::Reference< com::sun::star::sheet::XSpreadsheetDocument >& xSpreadDoc);
+ 	void WriteLabelRanges( const com::sun::star::uno::Reference< com::sun::star::container::XIndexAccess >& xRangesIAccess, sal_Bool bColumn );
+ 	void WriteNamedExpressions(const com::sun::star::uno::Reference <com::sun::star::sheet::XSpreadsheetDocument>& xSpreadDoc);
++    void WriteExternalRefCaches();
+ 	void WriteConsolidation();	// core implementation
+ 
+ 	void CollectUserDefinedNamespaces(const SfxItemPool* pPool, sal_uInt16 nAttrib);
+diff --git sc/source/filter/xml/xmlexternaltabi.cxx sc/source/filter/xml/xmlexternaltabi.cxx
+new file mode 100644
+index 0000000..e1d0ebd
+--- /dev/null
++++ sc/source/filter/xml/xmlexternaltabi.cxx
+@@ -0,0 +1,343 @@
++/*************************************************************************
++ *
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ * 
++ * Copyright 2008 by Sun Microsystems, Inc.
++ *
++ * OpenOffice.org - a multi-platform office productivity suite
++ *
++ * $RCSfile: xmlcoli.hxx,v $
++ * $Revision: 1.9 $
++ *
++ * This file is part of OpenOffice.org.
++ *
++ * OpenOffice.org is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License version 3
++ * only, as published by the Free Software Foundation.
++ *
++ * OpenOffice.org is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU Lesser General Public License version 3 for more details
++ * (a copy is included in the LICENSE file that accompanied this code).
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * version 3 along with OpenOffice.org.  If not, see
++ * <http://www.openoffice.org/license.html>
++ * for a copy of the LGPLv3 License.
++ *
++ ************************************************************************/
++
++// MARKER(update_precomp.py): autogen include statement, do not remove
++#include "precompiled_sc.hxx"
++
++
++
++// INCLUDE ---------------------------------------------------------------
++
++#include "xmlexternaltabi.hxx"
++#include "xmlimprt.hxx"
++#include "xmltabi.hxx"
++
++#include "token.hxx"
++#include "document.hxx"
++
++#include <xmloff/nmspmap.hxx>
++#include <xmloff/xmlnmspe.hxx>
++#include <xmloff/xmltoken.hxx>
++#include <xmloff/xmluconv.hxx>
++#include <com/sun/star/util/NumberFormat.hpp>
++
++using namespace ::com::sun::star;
++
++using ::rtl::OUString;
++using ::com::sun::star::uno::Reference;
++using ::com::sun::star::xml::sax::XAttributeList;
++
++// ============================================================================
++
++ScXMLExternalRefTabSourceContext::ScXMLExternalRefTabSourceContext(
++    ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName, 
++    const Reference<XAttributeList>& xAttrList, ScXMLExternalTabData& rRefInfo ) :
++    SvXMLImportContext( rImport, nPrefix, rLName ),
++    mrScImport(rImport), 
++    mrExternalRefInfo(rRefInfo)
++{
++    using namespace ::xmloff::token;
++
++    sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
++    for (sal_Int16 i = 0; i < nAttrCount; ++i)
++    {
++        const rtl::OUString& sAttrName = xAttrList->getNameByIndex(i);
++        rtl::OUString aLocalName;
++        sal_uInt16 nAttrPrefix = mrScImport.GetNamespaceMap().GetKeyByAttrName(sAttrName, &aLocalName);
++        const rtl::OUString& sValue = xAttrList->getValueByIndex(i);
++        if (nAttrPrefix == XML_NAMESPACE_XLINK)
++        {
++            if (IsXMLToken(aLocalName, XML_HREF))
++                maRelativeUrl = sValue;
++        }
++        else if (nAttrPrefix == XML_NAMESPACE_TABLE)
++        {
++            if (IsXMLToken(aLocalName, XML_TABLE_NAME))
++                maTableName = sValue;
++            else if (IsXMLToken(aLocalName, XML_FILTER_NAME))
++                maFilterName = sValue;
++            else if (IsXMLToken(aLocalName, XML_FILTER_OPTIONS))
++                maFilterOptions = sValue;
++        }
++    }
++}
++
++ScXMLExternalRefTabSourceContext::~ScXMLExternalRefTabSourceContext()
++{
++}
++
++SvXMLImportContext* ScXMLExternalRefTabSourceContext::CreateChildContext(
++    USHORT nPrefix, const OUString& rLocalName, const Reference<XAttributeList>& /*xAttrList*/ )
++{
++    return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
++}
++
++void ScXMLExternalRefTabSourceContext::EndElement()
++{
++    ScDocument* pDoc = mrScImport.GetDocument();
++    if (!pDoc)
++        return;
++
++    ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
++    if (!maRelativeUrl.equals(mrExternalRefInfo.maFileUrl))
++        pRefMgr->setRelativeFileName(mrExternalRefInfo.mnFileId, maRelativeUrl);
++    pRefMgr->setFilterData(mrExternalRefInfo.mnFileId, maFilterName, maFilterOptions);
++}
++
++// ============================================================================
++
++ScXMLExternalRefRowContext::ScXMLExternalRefRowContext(
++    ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName, 
++    const Reference<XAttributeList>& xAttrList, ScXMLExternalTabData& rRefInfo ) :
++    SvXMLImportContext( rImport, nPrefix, rLName ),
++    mrScImport(rImport), 
++    mrExternalRefInfo(rRefInfo),
++    mnRepeatRowCount(1)
++{
++    mrExternalRefInfo.mnCol = 0;
++
++    sal_Int16 nAttrCount(xAttrList.is() ? xAttrList->getLength() : 0);
++    const SvXMLTokenMap& rAttrTokenMap = mrScImport.GetTableRowAttrTokenMap();
++    for( sal_Int16 i=0; i < nAttrCount; ++i )
++    {
++        const rtl::OUString& sAttrName = xAttrList->getNameByIndex(i);
++        rtl::OUString aLocalName;
++        sal_uInt16 nAttrPrefix = mrScImport.GetNamespaceMap().GetKeyByAttrName(sAttrName, &aLocalName);
++        const rtl::OUString& sValue = xAttrList->getValueByIndex(i);
++
++        switch (rAttrTokenMap.Get(nAttrPrefix, aLocalName))
++        {
++            case XML_TOK_TABLE_ROW_ATTR_REPEATED:
++            {
++                mnRepeatRowCount = std::max(sValue.toInt32(), static_cast<sal_Int32>(1));
++            }
++            break;
++        }
++    }
++}
++
++ScXMLExternalRefRowContext::~ScXMLExternalRefRowContext()
++{
++}
++
++SvXMLImportContext* ScXMLExternalRefRowContext::CreateChildContext(
++    USHORT nPrefix, const OUString& rLocalName, const Reference<XAttributeList>& xAttrList )
++{
++    const SvXMLTokenMap& rTokenMap = mrScImport.GetTableRowElemTokenMap();
++    sal_uInt16 nToken = rTokenMap.Get(nPrefix, rLocalName);
++    if (nToken == XML_TOK_TABLE_ROW_CELL)
++        return new ScXMLExternalRefCellContext(mrScImport, nPrefix, rLocalName, xAttrList, mrExternalRefInfo);
++
++    return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
++}
++
++void ScXMLExternalRefRowContext::EndElement()
++{
++    ScExternalRefCache::Table* pTab = mrExternalRefInfo.mpCacheTable;
++
++    for (sal_Int32 i = 1; i < mnRepeatRowCount; ++i)
++    {
++        for (sal_Int32 j = 0; j < mrExternalRefInfo.mnCol; ++j)
++        {
++            ScExternalRefCache::TokenRef pToken = pTab->getCell(
++                static_cast<SCROW>(mrExternalRefInfo.mnRow), static_cast<SCCOL>(j));
++
++            if (pToken.get())
++            {
++                pTab->setCell(static_cast<SCROW>(
++                    mrExternalRefInfo.mnRow+i), static_cast<SCCOL>(j), pToken);
++            }
++        }
++    }
++    mrExternalRefInfo.mnRow += mnRepeatRowCount;
++}
++
++// ============================================================================
++
++ScXMLExternalRefCellContext::ScXMLExternalRefCellContext(
++    ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName, 
++    const Reference<XAttributeList>& xAttrList, ScXMLExternalTabData& rRefInfo ) :
++    SvXMLImportContext( rImport, nPrefix, rLName ),
++    mrScImport(rImport), 
++    mrExternalRefInfo(rRefInfo),
++    mfCellValue(0.0),
++    mnRepeatCount(1),
++    mnCellType(::com::sun::star::util::NumberFormat::UNDEFINED),
++    mbIsNumeric(false),
++    mbIsEmpty(true)
++{
++    using namespace ::xmloff::token;
++
++    sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
++    const SvXMLTokenMap& rTokenMap = rImport.GetTableRowCellAttrTokenMap();
++    for (sal_Int16 i = 0; i < nAttrCount; ++i)
++    {
++        OUString aLocalName;
++        sal_uInt16 nAttrPrefix = rImport.GetNamespaceMap().GetKeyByAttrName(
++            xAttrList->getNameByIndex(i), &aLocalName);
++
++        const rtl::OUString& sValue = xAttrList->getValueByIndex(i);
++        sal_uInt16 nToken = rTokenMap.Get(nAttrPrefix, aLocalName);
++
++        switch (nToken)
++        {
++            case XML_TOK_TABLE_ROW_CELL_ATTR_REPEATED:
++            {    
++                mnRepeatCount = ::std::max(sValue.toInt32(), static_cast<sal_Int32>(1));
++            }
++            break;
++            case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE_TYPE:
++            {
++                mnCellType = mrScImport.GetCellType(sValue);
++            }
++            break;
++            case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE:
++            {
++                if (sValue.getLength())
++                {
++                    mrScImport.GetMM100UnitConverter().convertDouble(mfCellValue, sValue);
++                    mbIsNumeric = true;
++                    mbIsEmpty = false;
++                }
++            }
++            break;
++            case XML_TOK_TABLE_ROW_CELL_ATTR_DATE_VALUE:
++            {
++                if (sValue.getLength() && mrScImport.SetNullDateOnUnitConverter())
++                {
++                    mrScImport.GetMM100UnitConverter().convertDateTime(mfCellValue, sValue);
++                    mbIsNumeric = true;
++                    mbIsEmpty = false;
++                }
++            }
++            break;
++            case XML_TOK_TABLE_ROW_CELL_ATTR_TIME_VALUE:
++            {
++                if (sValue.getLength())
++                {
++                    mrScImport.GetMM100UnitConverter().convertTime(mfCellValue, sValue);
++                    mbIsNumeric = true;
++                    mbIsEmpty = false;
++                }
++            }
++            break;
++            case XML_TOK_TABLE_ROW_CELL_ATTR_STRING_VALUE:
++            {
++                if (sValue.getLength())
++                {
++                    maCellString = sValue;
++                    mbIsNumeric = false;
++                    mbIsEmpty = false;
++                }
++            }
++            break;
++            case XML_TOK_TABLE_ROW_CELL_ATTR_BOOLEAN_VALUE:
++            {
++                if (sValue.getLength())
++                {
++                    mfCellValue = IsXMLToken(sValue, XML_TRUE) ? 1.0 : 0.0;
++                    mbIsNumeric = true;
++                    mbIsEmpty = false;
++                }
++            }
++            break;
++            default:
++                ;
++        }
++    }
++}
++
++ScXMLExternalRefCellContext::~ScXMLExternalRefCellContext()
++{
++}
++
++SvXMLImportContext* ScXMLExternalRefCellContext::CreateChildContext(
++    USHORT nPrefix, const OUString& rLocalName, const Reference<XAttributeList>& xAttrList )
++{
++    const SvXMLTokenMap& rTokenMap = mrScImport.GetTableRowCellElemTokenMap();
++    sal_uInt16 nToken = rTokenMap.Get(nPrefix, rLocalName);
++    if (nToken == XML_TOK_TABLE_ROW_CELL_P)
++        return new ScXMLExternalRefCellTextContext(mrScImport, nPrefix, rLocalName, xAttrList, maCellString);
++
++    return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
++}
++
++void ScXMLExternalRefCellContext::EndElement()
++{
++    if (maCellString.getLength())
++        mbIsEmpty = false;
++
++    for (sal_Int32 i = 0; i < mnRepeatCount; ++i, ++mrExternalRefInfo.mnCol)
++    {
++        if (mbIsEmpty)
++            continue;
++
++        ScExternalRefCache::TokenRef aToken;
++        if (mbIsNumeric)
++            aToken.reset(new ScDoubleToken(mfCellValue));
++        else
++            aToken.reset(new ScStringToken(maCellString));
++
++        mrExternalRefInfo.mpCacheTable->setCell(
++            static_cast<SCROW>(mrExternalRefInfo.mnRow), 
++            static_cast<SCCOL>(mrExternalRefInfo.mnCol), 
++            aToken);
++    }
++}
++
++// ============================================================================
++
++ScXMLExternalRefCellTextContext::ScXMLExternalRefCellTextContext(
++    ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName, 
++    const Reference<XAttributeList>& /*xAttrList*/, OUString& rCellString ) :
++    SvXMLImportContext( rImport, nPrefix, rLName ),
++    mrScImport(rImport), 
++    mrCellString(rCellString)
++{
++}
++
++ScXMLExternalRefCellTextContext::~ScXMLExternalRefCellTextContext()
++{
++}
++
++SvXMLImportContext* ScXMLExternalRefCellTextContext::CreateChildContext(
++    USHORT nPrefix, const OUString& rLocalName, const Reference<XAttributeList>& /*xAttrList*/ )
++{
++    return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
++}
++
++void ScXMLExternalRefCellTextContext::Characters(const OUString& rChar)
++{
++    mrCellString = rChar;
++}
++
++void ScXMLExternalRefCellTextContext::EndElement()
++{
++}
+diff --git sc/source/filter/xml/xmlexternaltabi.hxx sc/source/filter/xml/xmlexternaltabi.hxx
+new file mode 100644
+index 0000000..6f26789
+--- /dev/null
++++ sc/source/filter/xml/xmlexternaltabi.hxx
+@@ -0,0 +1,149 @@
++/*************************************************************************
++ *
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ * 
++ * Copyright 2008 by Sun Microsystems, Inc.
++ *
++ * OpenOffice.org - a multi-platform office productivity suite
++ *
++ * $RCSfile: xmlcoli.hxx,v $
++ * $Revision: 1.9 $
++ *
++ * This file is part of OpenOffice.org.
++ *
++ * OpenOffice.org is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License version 3
++ * only, as published by the Free Software Foundation.
++ *
++ * OpenOffice.org is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU Lesser General Public License version 3 for more details
++ * (a copy is included in the LICENSE file that accompanied this code).
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * version 3 along with OpenOffice.org.  If not, see
++ * <http://www.openoffice.org/license.html>
++ * for a copy of the LGPLv3 License.
++ *
++ ************************************************************************/
++
++#ifndef SC_XMLEXTERNALTABI_HXX
++#define SC_XMLEXTERNALTABI_HXX
++
++#include <xmloff/xmlictxt.hxx>
++
++class ScXMLImport;
++struct ScXMLExternalTabData;
++
++class ScXMLExternalRefTabSourceContext : public SvXMLImportContext
++{
++public:
++    ScXMLExternalRefTabSourceContext( ScXMLImport& rImport, USHORT nPrefix,
++                        const ::rtl::OUString& rLName,
++                        const ::com::sun::star::uno::Reference<
++                                        ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
++                        ScXMLExternalTabData& rRefInfo );
++
++    virtual ~ScXMLExternalRefTabSourceContext();
++
++    virtual SvXMLImportContext *CreateChildContext( USHORT nPrefix,
++                                     const ::rtl::OUString& rLocalName,
++                                     const ::com::sun::star::uno::Reference<
++                                        ::com::sun::star::xml::sax::XAttributeList>& xAttrList );
++
++    virtual void EndElement();
++private:
++    ScXMLImport&            mrScImport;
++    ScXMLExternalTabData&   mrExternalRefInfo;
++
++    ::rtl::OUString         maRelativeUrl;
++    ::rtl::OUString         maTableName;
++    ::rtl::OUString         maFilterName;
++    ::rtl::OUString         maFilterOptions;
++};
++
++// ============================================================================
++
++class ScXMLExternalRefRowContext : public SvXMLImportContext
++{
++public:
++    ScXMLExternalRefRowContext( ScXMLImport& rImport, USHORT nPrefix,
++                        const ::rtl::OUString& rLName,
++                        const ::com::sun::star::uno::Reference<
++                                        ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
++                        ScXMLExternalTabData& rRefInfo );
++
++    virtual ~ScXMLExternalRefRowContext();
++
++    virtual SvXMLImportContext *CreateChildContext( USHORT nPrefix,
++                                     const ::rtl::OUString& rLocalName,
++                                     const ::com::sun::star::uno::Reference<
++                                        ::com::sun::star::xml::sax::XAttributeList>& xAttrList );
++
++    virtual void EndElement();
++private:
++    ScXMLImport&            mrScImport;
++    ScXMLExternalTabData&   mrExternalRefInfo;
++    sal_Int32               mnRepeatRowCount;
++};
++
++// ============================================================================
++
++class ScXMLExternalRefCellContext : public SvXMLImportContext
++{
++public:
++    ScXMLExternalRefCellContext( ScXMLImport& rImport, USHORT nPrefix,
++                        const ::rtl::OUString& rLName,
++                        const ::com::sun::star::uno::Reference<
++                                        ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
++                        ScXMLExternalTabData& rRefInfo );
++
++    virtual ~ScXMLExternalRefCellContext();
++
++    virtual SvXMLImportContext *CreateChildContext( USHORT nPrefix,
++                                     const ::rtl::OUString& rLocalName,
++                                     const ::com::sun::star::uno::Reference<
++                                        ::com::sun::star::xml::sax::XAttributeList>& xAttrList );
++
++    virtual void EndElement();
++
++private:
++    ScXMLImport&            mrScImport;
++    ScXMLExternalTabData&   mrExternalRefInfo;
++    ::rtl::OUString         maCellString;
++    double                  mfCellValue;
++    sal_Int32               mnRepeatCount;
++    sal_Int16               mnCellType;
++    bool                    mbIsNumeric;
++    bool                    mbIsEmpty;
++};
++
++// ============================================================================
++
++class ScXMLExternalRefCellTextContext : public SvXMLImportContext
++{
++public:
++    ScXMLExternalRefCellTextContext( ScXMLImport& rImport, USHORT nPrefix,
++                        const ::rtl::OUString& rLName,
++                        const ::com::sun::star::uno::Reference<
++                                        ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
++                        ::rtl::OUString& rCellString );
++
++    virtual ~ScXMLExternalRefCellTextContext();
++
++    virtual SvXMLImportContext *CreateChildContext( USHORT nPrefix,
++                                     const ::rtl::OUString& rLocalName,
++                                     const ::com::sun::star::uno::Reference<
++                                        ::com::sun::star::xml::sax::XAttributeList>& xAttrList );
++
++    virtual void Characters(const ::rtl::OUString& rChar);
++
++    virtual void EndElement();
++
++private:
++    ScXMLImport&            mrScImport;
++    ::rtl::OUString&        mrCellString;
++};
++
++#endif
+diff --git sc/source/filter/xml/xmlimprt.cxx sc/source/filter/xml/xmlimprt.cxx
+index 47b26b9..3541e45 100644
+--- sc/source/filter/xml/xmlimprt.cxx
++++ sc/source/filter/xml/xmlimprt.cxx
+@@ -104,6 +104,7 @@
+ 
+ using namespace com::sun::star;
+ using namespace ::xmloff::token;
++using ::rtl::OUString;
+ 
+ OUString SAL_CALL ScXMLImport_getImplementationName() throw()
+ {
+@@ -417,22 +418,22 @@ static __FAR_DATA SvXMLTokenMapEntry aTableRowCellTokenMap[] =
+ 
+ static __FAR_DATA SvXMLTokenMapEntry aTableRowCellAttrTokenMap[] =
+ {
+-	{ XML_NAMESPACE_TABLE, XML_STYLE_NAME,						XML_TOK_TABLE_ROW_CELL_ATTR_STYLE_NAME				},
+-	{ XML_NAMESPACE_TABLE, XML_CONTENT_VALIDATION_NAME, 		XML_TOK_TABLE_ROW_CELL_ATTR_CONTENT_VALIDATION_NAME	},
+-	{ XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_SPANNED,  			XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_ROWS			},
+-	{ XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_SPANNED,			XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_COLS			},
+-	{ XML_NAMESPACE_TABLE, XML_NUMBER_MATRIX_COLUMNS_SPANNED,   XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_MATRIX_COLS		},
+-	{ XML_NAMESPACE_TABLE, XML_NUMBER_MATRIX_ROWS_SPANNED,		XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_MATRIX_ROWS		},
+-	{ XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED,		    XML_TOK_TABLE_ROW_CELL_ATTR_REPEATED				},
+-	{ XML_NAMESPACE_TABLE, XML_VALUE_TYPE,						XML_TOK_TABLE_ROW_CELL_ATTR_VALUE_TYPE				},
+-	{ XML_NAMESPACE_TABLE, XML_VALUE,							XML_TOK_TABLE_ROW_CELL_ATTR_VALUE					},
+-	{ XML_NAMESPACE_TABLE, XML_DATE_VALUE,						XML_TOK_TABLE_ROW_CELL_ATTR_DATE_VALUE				},
+-	{ XML_NAMESPACE_TABLE, XML_TIME_VALUE,						XML_TOK_TABLE_ROW_CELL_ATTR_TIME_VALUE				},
+-	{ XML_NAMESPACE_TABLE, XML_STRING_VALUE,					XML_TOK_TABLE_ROW_CELL_ATTR_STRING_VALUE			},
+-	{ XML_NAMESPACE_TABLE, XML_BOOLEAN_VALUE,					XML_TOK_TABLE_ROW_CELL_ATTR_BOOLEAN_VALUE			},
+-	{ XML_NAMESPACE_TABLE, XML_FORMULA, 						XML_TOK_TABLE_ROW_CELL_ATTR_FORMULA					},
+-	{ XML_NAMESPACE_TABLE, XML_CURRENCY,						XML_TOK_TABLE_ROW_CELL_ATTR_CURRENCY				},
+-	XML_TOKEN_MAP_END
++    { XML_NAMESPACE_TABLE,  XML_STYLE_NAME,                     XML_TOK_TABLE_ROW_CELL_ATTR_STYLE_NAME              },
++    { XML_NAMESPACE_TABLE,  XML_CONTENT_VALIDATION_NAME,        XML_TOK_TABLE_ROW_CELL_ATTR_CONTENT_VALIDATION_NAME },
++    { XML_NAMESPACE_TABLE,  XML_NUMBER_ROWS_SPANNED,            XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_ROWS            },
++    { XML_NAMESPACE_TABLE,  XML_NUMBER_COLUMNS_SPANNED,         XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_COLS            },
++    { XML_NAMESPACE_TABLE,  XML_NUMBER_MATRIX_COLUMNS_SPANNED,  XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_MATRIX_COLS     },
++    { XML_NAMESPACE_TABLE,  XML_NUMBER_MATRIX_ROWS_SPANNED,     XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_MATRIX_ROWS     },
++    { XML_NAMESPACE_TABLE,  XML_NUMBER_COLUMNS_REPEATED,        XML_TOK_TABLE_ROW_CELL_ATTR_REPEATED                },
++    { XML_NAMESPACE_OFFICE, XML_VALUE_TYPE,                     XML_TOK_TABLE_ROW_CELL_ATTR_VALUE_TYPE              },
++    { XML_NAMESPACE_OFFICE, XML_VALUE,                          XML_TOK_TABLE_ROW_CELL_ATTR_VALUE                   },
++    { XML_NAMESPACE_OFFICE, XML_DATE_VALUE,                     XML_TOK_TABLE_ROW_CELL_ATTR_DATE_VALUE              },
++    { XML_NAMESPACE_OFFICE, XML_TIME_VALUE,                     XML_TOK_TABLE_ROW_CELL_ATTR_TIME_VALUE              },
++    { XML_NAMESPACE_OFFICE, XML_STRING_VALUE,                   XML_TOK_TABLE_ROW_CELL_ATTR_STRING_VALUE            },
++    { XML_NAMESPACE_OFFICE, XML_BOOLEAN_VALUE,                  XML_TOK_TABLE_ROW_CELL_ATTR_BOOLEAN_VALUE           },
++    { XML_NAMESPACE_OFFICE, XML_FORMULA,                        XML_TOK_TABLE_ROW_CELL_ATTR_FORMULA                 },
++    { XML_NAMESPACE_OFFICE, XML_CURRENCY,                       XML_TOK_TABLE_ROW_CELL_ATTR_CURRENCY                },
++    XML_TOKEN_MAP_END
+ };
+ 
+ static __FAR_DATA SvXMLTokenMapEntry aTableAnnotationAttrTokenMap[] =
+@@ -1561,6 +1562,25 @@ ScXMLImport::ScXMLImport(
+         GetXMLToken( XML_NP_PRESENTATION ),
+         GetXMLToken( XML_N_PRESENTATION ),
+         XML_NAMESPACE_PRESENTATION );
++
++    // initialize cell type map.
++    const struct { XMLTokenEnum  _token; sal_Int16 _type; } aCellTypePairs[] = 
++    {
++        { XML_FLOAT,        util::NumberFormat::NUMBER },
++        { XML_STRING,       util::NumberFormat::TEXT },
++        { XML_TIME,         util::NumberFormat::TIME },
++        { XML_DATE,         util::NumberFormat::DATETIME },
++        { XML_PERCENTAGE,   util::NumberFormat::PERCENT },
++        { XML_CURRENCY,     util::NumberFormat::CURRENCY },
++        { XML_BOOLEAN,      util::NumberFormat::LOGICAL }
++    };
++    size_t n = sizeof(aCellTypePairs)/sizeof(aCellTypePairs[0]);
++    for (size_t i = 0; i < n; ++i)
++    {
++        aCellTypeMap.insert(
++            CellTypeMap::value_type(
++                GetXMLToken(aCellTypePairs[i]._token), aCellTypePairs[i]._type));
++    }
+ }
+ 
+ ScXMLImport::~ScXMLImport() throw()
+@@ -1777,6 +1797,15 @@ void ScXMLImport::SetStatistics(
+ 	}
+ }
+ 
++sal_Int16 ScXMLImport::GetCellType(const OUString& rStrValue) const
++{
++    CellTypeMap::const_iterator itr = aCellTypeMap.find(rStrValue);
++    if (itr != aCellTypeMap.end())
++        return itr->second;
++
++    return util::NumberFormat::UNDEFINED;
++}
++
+ XMLShapeImportHelper* ScXMLImport::CreateShapeImport()
+ {
+ 	/*UniReference < XMLPropertySetMapper > xShapeStylesPropertySetMapper = new XMLPropertySetMapper((XMLPropertyMapEntry*)aXMLScShapeStylesProperties, xScPropHdlFactory);
+diff --git sc/source/filter/xml/xmlimprt.hxx sc/source/filter/xml/xmlimprt.hxx
+index e4fd8a0..cace08e 100644
+--- sc/source/filter/xml/xmlimprt.hxx
++++ sc/source/filter/xml/xmlimprt.hxx
+@@ -40,7 +40,6 @@
+ #include <com/sun/star/frame/XModel.hpp>
+ #include <tools/time.hxx>
+ #include <com/sun/star/util/DateTime.hpp>
+-#include <vector>
+ #include "xmlsubti.hxx"
+ #include "global.hxx"
+ #include "grammar.hxx"
+@@ -55,12 +54,13 @@
+ #include <com/sun/star/util/XNumberFormatTypes.hpp>
+ #include <com/sun/star/sheet/XSheetCellRangeContainer.hpp>
+ 
++#include <vector>
++#include <hash_map>
++
+ class ScRangeList;
+ class ScMyStyleNumberFormats;
+ class XMLNumberFormatAttributesExportHelper;
+ 
+-using namespace rtl;
+-
+ enum ScXMLDocTokens
+ {
+ 	XML_TOK_DOC_FONTDECLS,
+@@ -643,6 +643,9 @@ class ScMyStylesImportHelper;
+ 
+ class ScXMLImport: public SvXMLImport
+ {
++	typedef ::std::hash_map< ::rtl::OUString, sal_Int16, ::rtl::OUStringHash >	CellTypeMap;
++	CellTypeMap				aCellTypeMap;
++
+ 	ScDocument*				pDoc;
+ 	ScXMLChangeTrackingImportHelper*	pChangeTrackingImportHelper;
+ 	ScMyViewContextList					aViewContextList;
+@@ -810,6 +813,8 @@ public:
+ 
+     sal_Bool IsLatinDefaultStyle() const  { return bLatinDefaultStyle; }
+ 
++	sal_Int16 GetCellType(const ::rtl::OUString& rStrValue) const;
++
+ //	SvI18NMap& GetI18NMap() { return *pI18NMap; }
+ 
+ //	inline const SvXMLImportItemMapper& GetParaItemMapper() const;
+diff --git sc/source/filter/xml/xmlsceni.cxx sc/source/filter/xml/xmlsceni.cxx
+index cfe859d..f4d6c89 100644
+--- sc/source/filter/xml/xmlsceni.cxx
++++ sc/source/filter/xml/xmlsceni.cxx
+@@ -50,6 +50,7 @@
+ 
+ using namespace com::sun::star;
+ using namespace xmloff::token;
++using ::rtl::OUString;
+ 
+ //------------------------------------------------------------------
+ 
+diff --git sc/source/filter/xml/xmlstyle.cxx sc/source/filter/xml/xmlstyle.cxx
+index 7aec632..863e82c 100644
+--- sc/source/filter/xml/xmlstyle.cxx
++++ sc/source/filter/xml/xmlstyle.cxx
+@@ -65,6 +65,7 @@
+ 
+ using namespace com::sun::star;
+ using namespace ::xmloff::token;
++using ::rtl::OUString;
+ 
+ #define MAP(name,prefix,token,type,context)  { name, sizeof(name)-1, prefix, token, type, context, SvtSaveOptions::ODFVER_010 }
+ #define MAP_END()	{ NULL, 0, 0, XML_TOKEN_INVALID, 0, 0, SvtSaveOptions::ODFVER_010 }
+diff --git sc/source/filter/xml/xmlstyle.hxx sc/source/filter/xml/xmlstyle.hxx
+index 4d51084..ee9a2ea 100644
+--- sc/source/filter/xml/xmlstyle.hxx
++++ sc/source/filter/xml/xmlstyle.hxx
+@@ -40,8 +40,6 @@
+ #include <xmloff/xmlexppr.hxx>
+ #include <xmloff/contextid.hxx>
+ 
+-using namespace rtl;
+-
+ extern const XMLPropertyMapEntry aXMLScCellStylesProperties[];
+ extern const XMLPropertyMapEntry aXMLScColumnStylesProperties[];
+ extern const XMLPropertyMapEntry aXMLScRowStylesProperties[];
+diff --git sc/source/filter/xml/xmltabi.cxx sc/source/filter/xml/xmltabi.cxx
+index 4a0f83e..af80b31 100644
+--- sc/source/filter/xml/xmltabi.cxx
++++ sc/source/filter/xml/xmltabi.cxx
+@@ -40,6 +40,7 @@
+ #include "xmlrowi.hxx"
+ #include "xmlcoli.hxx"
+ #include "xmlsceni.hxx"
++#include "xmlexternaltabi.hxx"
+ #include "document.hxx"
+ #include "docuno.hxx"
+ #include "olinetab.hxx"
+@@ -48,6 +49,7 @@
+ #include "XMLTableSourceContext.hxx"
+ #include "XMLStylesImportHelper.hxx"
+ #include "rangeutl.hxx"
++#include "externalrefmgr.hxx"
+ 
+ #include <xmloff/xmltkmap.hxx>
+ #include <xmloff/nmspmap.hxx>
+@@ -63,6 +65,78 @@
+ using namespace com::sun::star;
+ using namespace xmloff::token;
+ 
++/** 
++ * Determine whether this table is an external reference cache from its 
++ * name.  There is currently no way of determining whether a table is a
++ * regular table or an external reference cache other than examining the 
++ * name itself.  We should probably introduce a new boolean value for 
++ * table:table element and use it instead of doing this, to make it more 
++ * reliable and future-proof. 
++ *
++ * @param rName 
++ * 
++ * @return 
++ */
++static bool lcl_isExternalRefCache(const rtl::OUString& rName, rtl::OUString& rUrl, rtl::OUString& rExtTabName)
++{
++    // 'file:///path/to/file.ods'#MySheet
++    // 'file:///path/to/file.ods'#MySheet with space
++
++    static const sal_Unicode aPrefix[] = {
++        '\'', 'f', 'i', 'l', 'e', ':', '/', '/'
++    };
++
++    rtl::OUStringBuffer aUrlBuf, aTabNameBuf;
++    aUrlBuf.appendAscii("file://");
++    sal_Int32 n = rName.getLength();
++    const sal_Unicode* p = rName.getStr();
++
++    bool bInUrl = true;
++    sal_Unicode cPrev = 0;
++    for (sal_Int32 i = 0; i < n; ++i)
++    {
++        const sal_Unicode c = p[i];
++        if (i <= 7)
++        {
++            if (c != aPrefix[i])
++                return false;
++        }
++        else if (c == '\'')
++        {
++            if (!bInUrl)
++                return false;
++            bInUrl = false;
++            rUrl = aUrlBuf.makeStringAndClear();
++        }
++        else if (c == '#')
++        {
++            if (cPrev != '\'')
++                return false;
++        }
++        else if (bInUrl)
++            aUrlBuf.append(c);
++        else
++            aTabNameBuf.append(c);
++
++        cPrev = c;
++    }
++
++    if (bInUrl)
++        return false;
++
++    if (aTabNameBuf.getLength() == 0)
++        return false;
++
++    rExtTabName = aTabNameBuf.makeStringAndClear();
++
++    return true;
++}
++
++ScXMLExternalTabData::ScXMLExternalTabData() :
++    mpCacheTable(NULL), mnRow(0), mnCol(0), mnFileId(0)
++{
++}
++
+ //------------------------------------------------------------------
+ 
+ ScXMLTableContext::ScXMLTableContext( ScXMLImport& rImport,
+@@ -73,6 +147,7 @@ ScXMLTableContext::ScXMLTableContext( ScXMLImport& rImport,
+ 									  const sal_Bool bTempIsSubTable,
+ 									  const sal_Int32 nSpannedCols) :
+ 	SvXMLImportContext( rImport, nPrfx, rLName ),
++    pExternalRefInfo(NULL),
+ 	bStartFormPage(sal_False),
+     bPrintEntireSheet(sal_True)
+ {
+@@ -117,7 +192,26 @@ ScXMLTableContext::ScXMLTableContext( ScXMLImport& rImport,
+                     break;
+ 			}
+ 		}
+-		GetScImport().GetTables().NewSheet(sName, sStyleName, bProtection, sPassword);
++
++        rtl::OUString aExtUrl, aExtTabName;
++        if (lcl_isExternalRefCache(sName, aExtUrl, aExtTabName))
++        {
++            // This is an external ref cache table.
++            pExternalRefInfo.reset(new ScXMLExternalTabData);
++            pExternalRefInfo->maFileUrl = aExtUrl;
++            ScDocument* pDoc = GetScImport().GetDocument();
++            if (pDoc)
++            {
++                ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
++                pExternalRefInfo->mnFileId = pRefMgr->getExternalFileId(aExtUrl);
++                pExternalRefInfo->mpCacheTable = pRefMgr->getCacheTable(pExternalRefInfo->mnFileId, aExtTabName);
++            }
++        }
++        else
++        {
++            // This is a regular table.
++            GetScImport().GetTables().NewSheet(sName, sStyleName, bProtection, sPassword);
++        }
+ 	}
+ 	else
+ 	{
+@@ -134,10 +228,30 @@ SvXMLImportContext *ScXMLTableContext::CreateChildContext( USHORT nPrefix,
+ 											const ::com::sun::star::uno::Reference<
+ 									  	::com::sun::star::xml::sax::XAttributeList>& xAttrList )
+ {
++	const SvXMLTokenMap& rTokenMap(GetScImport().GetTableElemTokenMap());
++    sal_uInt16 nToken = rTokenMap.Get(nPrefix, rLName);
++    if (pExternalRefInfo.get())
++    {
++        // We only care about the table-row and table-source elements for 
++        // external cache data.
++        switch (nToken)
++        {
++            case XML_TOK_TABLE_ROW:
++                return new ScXMLExternalRefRowContext(
++                    GetScImport(), nPrefix, rLName, xAttrList, *pExternalRefInfo);
++            case XML_TOK_TABLE_SOURCE:
++                return new ScXMLExternalRefTabSourceContext(
++                    GetScImport(), nPrefix, rLName, xAttrList, *pExternalRefInfo);
++            default:
++                ;
++        }
++
++        return new SvXMLImportContext(GetImport(), nPrefix, rLName);
++    }
++
+ 	SvXMLImportContext *pContext(0);
+ 
+-	const SvXMLTokenMap& rTokenMap(GetScImport().GetTableElemTokenMap());
+-	switch( rTokenMap.Get( nPrefix, rLName ) )
++	switch (nToken)
+ 	{
+ 	case XML_TOK_TABLE_COL_GROUP:
+ 		pContext = new ScXMLTableColsContext( GetScImport(), nPrefix,
+@@ -195,6 +309,8 @@ SvXMLImportContext *ScXMLTableContext::CreateChildContext( USHORT nPrefix,
+ 			pContext = GetScImport().GetFormImport()->createOfficeFormsContext( GetScImport(), nPrefix, rLName );
+ 		}
+ 		break;
++    default:
++        ;
+ 	}
+ 
+ 	if( !pContext )
+diff --git sc/source/filter/xml/xmltabi.hxx sc/source/filter/xml/xmltabi.hxx
+index 687cff8..e2960c2 100644
+--- sc/source/filter/xml/xmltabi.hxx
++++ sc/source/filter/xml/xmltabi.hxx
+@@ -30,13 +30,28 @@
+ #ifndef SC_XMLTABI_HXX
+ #define SC_XMLTABI_HXX
+ 
++#include "externalrefmgr.hxx"
++
+ #include <xmloff/xmlictxt.hxx>
++#include <memory>
+ 
+ class ScXMLImport;
+ 
++struct ScXMLExternalTabData
++{
++    String maFileUrl;
++    ScExternalRefCache::Table* mpCacheTable;
++    sal_Int32 mnRow;
++    sal_Int32 mnCol;
++    sal_uInt16 mnFileId;
++
++    ScXMLExternalTabData();
++};
++
+ class ScXMLTableContext : public SvXMLImportContext
+ {
+ 	rtl::OUString	sPrintRanges;
++    ::std::auto_ptr<ScXMLExternalTabData> pExternalRefInfo;
+ 	sal_Bool		bStartFormPage;
+     sal_Bool        bPrintEntireSheet;
+ 
+diff --git sc/source/filter/xml/xmlwrap.cxx sc/source/filter/xml/xmlwrap.cxx
+index 851d338..035793b 100644
+--- sc/source/filter/xml/xmlwrap.cxx
++++ sc/source/filter/xml/xmlwrap.cxx
+@@ -85,6 +85,7 @@
+ #define MAP_LEN(x) x, sizeof(x) - 1
+ 
+ using namespace com::sun::star;
++using ::rtl::OUString;
+ 
+ // -----------------------------------------------------------------------
+ 
+diff --git sc/source/ui/docshell/docsh4.cxx sc/source/ui/docshell/docsh4.cxx
+index bc5975d..6701d1c 100644
+--- sc/source/ui/docshell/docsh4.cxx
++++ sc/source/ui/docshell/docsh4.cxx
+@@ -123,6 +123,7 @@ using namespace ::com::sun::star;
+ #include <com/sun/star/document/UpdateDocMode.hpp>
+ #include "scresid.hxx" //add by CHINA001
+ #include "scabstdlg.hxx" //CHINA001
++#include "externalrefmgr.hxx"
+ 
+ #include "sharedocdlg.hxx"
+ 
+@@ -540,6 +541,7 @@ void ScDocShell::Execute( SfxRequest& rReq )
+ 				if (nDlgRet == RET_YES || nSet==LM_ALWAYS)
+ 				{
+ 					ReloadTabLinks();
++                    aDocument.UpdateExternalRefLinks();
+ 					aDocument.UpdateDdeLinks();
+ 					aDocument.UpdateAreaLinks();
+ 
+diff --git sc/source/ui/docshell/externalrefmgr.cxx sc/source/ui/docshell/externalrefmgr.cxx
+new file mode 100644
+index 0000000..8f34a8f
+--- /dev/null
++++ sc/source/ui/docshell/externalrefmgr.cxx
+@@ -0,0 +1,1267 @@
++/*************************************************************************
++ *
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ * 
++ * Copyright 2008 by Sun Microsystems, Inc.
++ *
++ * OpenOffice.org - a multi-platform office productivity suite
++ *
++ * $RCSfile: document.hxx,v $
++ * $Revision: 1.112 $
++ *
++ * This file is part of OpenOffice.org.
++ *
++ * OpenOffice.org is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License version 3
++ * only, as published by the Free Software Foundation.
++ *
++ * OpenOffice.org is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU Lesser General Public License version 3 for more details
++ * (a copy is included in the LICENSE file that accompanied this code).
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * version 3 along with OpenOffice.org.  If not, see
++ * <http://www.openoffice.org/license.html>
++ * for a copy of the LGPLv3 License.
++ *
++ ************************************************************************/
++
++// MARKER(update_precomp.py): autogen include statement, do not remove
++#include "precompiled_sc.hxx"
++
++
++
++// INCLUDE ---------------------------------------------------------------
 +
 +#include "externalrefmgr.hxx"
 +#include "document.hxx"
@@ -5549,6 +7540,7 @@
 +#include "unotools/ucbhelper.hxx"
 +
 +#include <memory>
++#include <algorithm>
 +
 +using ::std::auto_ptr;
 +using ::com::sun::star::uno::Any;
@@ -5591,13 +7583,13 @@
 +    rRow.insert(RowDataType::value_type(nCol, pToken));
 +}
 +
-+ScToken* ScExternalRefCache::Table::getCell(SCROW nRow, SCCOL nCol) const
++ScExternalRefCache::TokenRef ScExternalRefCache::Table::getCell(SCROW nRow, SCCOL nCol) const
 +{
 +    RowsDataType::const_iterator itrTable = maRows.find(nRow);
 +    if (itrTable == maRows.end())
 +    {
 +        // this table doesn't have the specified row.
-+        return NULL;
++        return TokenRef();
 +    }
 +
 +    const RowDataType& rRowData = itrTable->second;
@@ -5605,10 +7597,42 @@
 +    if (itrRow == rRowData.end())
 +    {
 +        // this row doesn't have the specified column.
-+        return NULL;
++        return TokenRef();
 +    }
 +
-+    return itrRow->second.get();
++    return itrRow->second;
++}
++
++void ScExternalRefCache::Table::getAllRows(vector<SCROW>& rRows) const
++{
++    vector<SCROW> aRows;
++    aRows.reserve(maRows.size());
++    RowsDataType::const_iterator itr = maRows.begin(), itrEnd = maRows.end();
++    for (; itr != itrEnd; ++itr)
++        aRows.push_back(itr->first);
++
++    // hash map is not ordered, so we need to explicitly sort it.
++    ::std::sort(aRows.begin(), aRows.end());
++    rRows.swap(aRows);
++}
++
++void ScExternalRefCache::Table::getAllCols(SCROW nRow, vector<SCCOL>& rCols) const
++{
++    RowsDataType::const_iterator itrRow = maRows.find(nRow);
++    if (itrRow == maRows.end())
++        // this table doesn't have the specified row.
++        return;
++
++    const RowDataType& rRowData = itrRow->second;
++    vector<SCCOL> aCols;
++    aCols.reserve(rRowData.size());
++    RowDataType::const_iterator itrCol = rRowData.begin(), itrColEnd = rRowData.end();
++    for (; itrCol != itrColEnd; ++itrCol)
++        aCols.push_back(itrCol->first);
++
++    // hash map is not ordered, so we need to explicitly sort it.
++    ::std::sort(aCols.begin(), aCols.end());
++    rCols.swap(aCols);
 +}
 +
 +// ----------------------------------------------------------------------------
@@ -5643,7 +7667,7 @@
 +        // the table data is not instantiated yet.
 +        return NULL;
 +    }
-+    return pTableData->getCell(nRow, nCol);
++    return pTableData->getCell(nRow, nCol).get();
 +}
 +
 +ScTokenArray* ScExternalRefCache::getCellRangeData(sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange)
@@ -5694,7 +7718,7 @@
 +        {
 +            for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
 +            {
-+                ScToken* pToken = pTab->getCell(nRow, nCol);
++                ScToken* pToken = pTab->getCell(nRow, nCol).get();
 +                if (!pToken)
 +                    return NULL;
 +
@@ -5895,7 +7919,7 @@
 +    return &pDoc->maTableNames;
 +}
 +
-+ScExternalRefCache::Table* ScExternalRefCache::getCacheTable(sal_uInt16 nFileId, const String& rTabName)
++ScExternalRefCache::Table* ScExternalRefCache::getCacheTable(sal_uInt16 nFileId, const String& rTabName, bool bCreateNew)
 +{
 +    DocItem* pDoc = getDocItem(nFileId);
 +    if (!pDoc)
@@ -5905,9 +7929,11 @@
 +
 +    size_t nIndex;
 +    if (lcl_getTableDataIndex(rDoc.maTableNameIndex, rTabName, nIndex))
-+    {
++        // specified table found.
 +        return rDoc.maTables[nIndex].get();
-+    }
++
++    if (!bCreateNew)
++        return NULL;
 +
 +    // Specified table doesn't exist yet.  Create one.
 +    TableTypeRef pTab(new Table);
@@ -6321,6 +8347,8 @@
 +                bTokenAdded = true;
 +            }
 +            break;
++            default:
++                ; // nothing to do
 +        }
 +        
 +        if (!bTokenAdded)
@@ -6335,10 +8363,7 @@
 +{
 +    RefCellMap::iterator itr = maRefCells.find(nFileId);
 +    if (itr == maRefCells.end())
-+    {
-+        const String* pFile = getExternalFileName(nFileId);
 +        return;
-+    }
 +
 +    RefCellSet aNewSet;
 +    RefCellSet& rSet = itr->second;
@@ -6397,8 +8422,8 @@
 +        return NULL;
 +
 +    String aFilter;
-+    SrcDoc aSrcDoc;
-+    aSrcDoc.maShell = loadSrcDocument(*pFile, aFilter);
++    SrcShell aSrcDoc;
++    aSrcDoc.maShell = loadSrcDocument(nFileId, *pFile, aFilter);
 +    if (!aSrcDoc.maShell.Is())
 +    {
 +        // source document could not be loaded.
@@ -6432,17 +8457,24 @@
 +    return pSrcDoc;
 +}
 +
-+SfxObjectShellRef ScExternalRefManager::loadSrcDocument(const String& rFile, String& rFilter)
++SfxObjectShellRef ScExternalRefManager::loadSrcDocument(sal_uInt16 nFileId, const String& rFile, String& rFilter)
 +{
 +    // First, make sure the file actually exists at the specified URL.
 +    if (!utl::UCBContentHelper::Exists(rFile) || utl::UCBContentHelper::IsFolder(rFile))
 +        // Either the specified file doesn't exist, or it's a folder.
 +        return NULL;
 +
++    if (isOwnDocument(rFile))
++        // Don't load itself.  That would be asking for trouble.
++        return NULL;
++
 +    String aOptions;
 +    ScDocumentLoader::GetFilterName(rFile, rFilter, aOptions, true, false);
 +    const SfxFilter* pFilter = ScDocShell::Factory().GetFilterContainer()->GetFilter4FilterName(rFilter);
 +
++    // Update the filter data now that we are loading it again.
++    setFilterData(nFileId, rFilter, aOptions);
++
 +    SfxItemSet* pSet = new SfxAllItemSet(SFX_APP()->GetPool());
 +    if (aOptions.Len())
 +        pSet->Put(SfxStringItem(SID_FILE_FILTEROPTIONS, aOptions));
@@ -6536,34 +8568,78 @@
 +    return true;
 +}
 +
++bool ScExternalRefManager::isOwnDocument(const String& rFile) const
++{
++    SfxObjectShell* pShell = mpDoc->GetDocumentShell();
++    if (!pShell)
++        // This should not happen!
++        return true;
++
++    SfxMedium* pMed = pShell->GetMedium();
++    if (!pMed)
++        return false;
++
++    return pMed->GetName().Equals(rFile);
++}
++
 +void ScExternalRefManager::convertToAbsName(String& rFile) const
 +{
 +    SfxObjectShell* pDocShell = mpDoc->GetDocumentShell();
 +    rFile = ScGlobal::GetAbsDocName(rFile, pDocShell);
 +}
 +
++namespace {
++
++class FindSrcFileByName : public ::std::unary_function<ScExternalRefManager::SrcFileData, bool>
++{
++public:
++    FindSrcFileByName(const String& rMatchName) :
++        mrMatchName(rMatchName)
++    {
++    }
++
++    bool operator()(const ScExternalRefManager::SrcFileData& rSrcData) const
++    {
++        return rSrcData.maFileName.Equals(mrMatchName);
++    }
++
++private:
++    const String& mrMatchName;
++};
++
++}
 +sal_uInt16 ScExternalRefManager::getExternalFileId(const String& rFile)
 +{
 +    using namespace std;
 +
-+    vector<String>::const_iterator itrBeg = maFileNames.begin(), itrEnd = maFileNames.end();
-+    vector<String>::const_iterator itr = find(itrBeg, itrEnd, rFile);
++    vector<SrcFileData>::const_iterator itrBeg = maSrcFiles.begin(), itrEnd = maSrcFiles.end();
++    vector<SrcFileData>::const_iterator itr = find_if(itrBeg, itrEnd, FindSrcFileByName(rFile));
 +    if (itr != itrEnd)
 +    {
 +        size_t nId = distance(itrBeg, itr);
 +        return static_cast<sal_uInt16>(nId);
 +    }
 +
-+    maFileNames.push_back(rFile);
-+    return static_cast<sal_uInt16>(maFileNames.size() - 1);
++    SrcFileData aData;
++    aData.maFileName = rFile;
++    maSrcFiles.push_back(aData);
++    return static_cast<sal_uInt16>(maSrcFiles.size() - 1);
 +}
 +
 +const String* ScExternalRefManager::getExternalFileName(sal_uInt16 nFileId) const
 +{
-+    if (nFileId >= maFileNames.size())
++    if (nFileId >= maSrcFiles.size())
 +        return NULL;
 +
-+    return &maFileNames[nFileId];
++    return &maSrcFiles[nFileId].maFileName;
++}
++
++const ScExternalRefManager::SrcFileData* ScExternalRefManager::getExternalFileData(sal_uInt16 nFileId) const
++{
++    if (nFileId >= maSrcFiles.size())
++        return NULL;
++
++    return &maSrcFiles[nFileId];
 +}
 +
 +const vector<String>* ScExternalRefManager::getAllCachedTableNames(sal_uInt16 nFileId) const
@@ -6571,6 +8647,11 @@
 +    return maRefCache.getAllTableNames(nFileId);
 +}
 +
++sal_uInt16 ScExternalRefManager::getCachedFileCount() const
++{
++    return static_cast<sal_uInt16>(maSrcFiles.size());
++}
++
 +template<typename MapContainer>
 +static void lcl_removeByFileId(sal_uInt16 nFileId, MapContainer& rMap)
 +{
@@ -6589,10 +8670,26 @@
 +
 +void ScExternalRefManager::switchSrcFile(sal_uInt16 nFileId, const String& rNewFile)
 +{
-+    maFileNames[nFileId] = rNewFile;
++    maSrcFiles[nFileId].maFileName = rNewFile;
++    maSrcFiles[nFileId].maRelativeName.Erase();
 +    refreshNames(nFileId);
 +}
 +
++void ScExternalRefManager::setRelativeFileName(sal_uInt16 nFileId, const String& rRelUrl)
++{
++    if (nFileId >= maSrcFiles.size())
++        return;
++    maSrcFiles[nFileId].maRelativeName = rRelUrl;
++}
++
++void ScExternalRefManager::setFilterData(sal_uInt16 nFileId, const String& rFilterName, const String& rOptions)
++{
++    if (nFileId >= maSrcFiles.size())
++        return;
++    maSrcFiles[nFileId].maFilterName = rFilterName;
++    maSrcFiles[nFileId].maFilterOptions = rOptions;
++}
++
 +void ScExternalRefManager::removeSrcDocument(sal_uInt16 nFileId, bool bBreakLink)
 +{
 +    maRefCache.clearCache(nFileId);
@@ -6617,7 +8714,7 @@
 +
 +bool ScExternalRefManager::hasExternalData() const
 +{
-+    return !maFileNames.empty();
++    return !maSrcFiles.empty();
 +}
 +
 +void ScExternalRefManager::purgeStaleSrcDocument(sal_Int32 nTimeOut)



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]