ooo-build r15074 - in branches/ooo-build-3-0-1: . patches/dev300



Author: kyoshida
Date: Thu Jan 15 02:44:24 2009
New Revision: 15074
URL: http://svn.gnome.org/viewvc/ooo-build?rev=15074&view=rev

Log:
2009-01-14  Kohei Yoshida  <kyoshida novell com>

	* patches/dev300/calc-external-defined-names-officecfg.diff:
	* patches/dev300/calc-external-defined-names-svtools.diff:
	* patches/dev300/calc-external-defined-names-offapi.diff:
	* patches/dev300/calc-external-defined-names-sc.diff:
	* patches/dev300/apply: ported the above patches from trunk, but they 
	are in CalcExperimental section which is disabled by default.


Added:
   branches/ooo-build-3-0-1/patches/dev300/calc-external-defined-names-officecfg.diff
   branches/ooo-build-3-0-1/patches/dev300/calc-external-defined-names-svtools.diff
Modified:
   branches/ooo-build-3-0-1/ChangeLog
   branches/ooo-build-3-0-1/patches/dev300/apply
   branches/ooo-build-3-0-1/patches/dev300/calc-external-defined-names-offapi.diff
   branches/ooo-build-3-0-1/patches/dev300/calc-external-defined-names-sc.diff

Modified: branches/ooo-build-3-0-1/patches/dev300/apply
==============================================================================
--- branches/ooo-build-3-0-1/patches/dev300/apply	(original)
+++ branches/ooo-build-3-0-1/patches/dev300/apply	Thu Jan 15 02:44:24 2009
@@ -30,7 +30,8 @@
 Experimental: VBAUntested, ArkOnlyExperimental, SharedWorksheets, \
 	      UnUsedButNotYetRemovedFromSVN, WebDAVUpstream, \
 	      PostgreSQL, SELinux, VOSremoval, Glib2, \
-	      UnitBootstrap, RadioButtons, UnstableLibwpd, WWInProgress, KDE4
+	      UnitBootstrap, RadioButtons, UnstableLibwpd, WWInProgress, KDE4 \
+          CalcExperimental
 DebianLooseSections: DebianBaseNoHelpContent
 # Optional sections
 Optional : DejaVuFonts, NovellOnlyExtensionFixes, Win32OnlyExtensionFixes, Linux32OnlyExtensionFixes
@@ -1793,10 +1794,6 @@
 # to xls.
 chart-subtitle-xls-export.diff, i#92357, kohei
 
-# Implement external range names.
-#calc-external-defined-names-sc.diff, i#3740, i#4385, n#355685, kohei
-#calc-external-defined-names-offapi.diff, i#3740, i#4385, n#355685, kohei
-
 # fix bug generating a specific Sheet reference
 parse-xla1-bad-3dflag.diff, n#422569, noelpwer
 
@@ -1812,6 +1809,15 @@
 # fix 'Identify Categories' greakage on grouping.
 calc-dp-group-ident-category-fix.diff, n#447182, i#96171, kohei
 
+[ CalcExperimental ]
+
+# Implement external range names.
+calc-external-defined-names-sc.diff, i#3740, i#4385, n#355685, kohei
+calc-external-defined-names-offapi.diff, i#3740, i#4385, n#355685, kohei
+calc-external-defined-names-svtools.diff, i#3740, i#4385, n#355685, kohei
+calc-external-defined-names-officecfg.diff, i#3740, i#4385, n#355685, kohei
+
+
 [ CalcSolver ]
 SectionOwner => kohei
 

Modified: branches/ooo-build-3-0-1/patches/dev300/calc-external-defined-names-offapi.diff
==============================================================================
--- branches/ooo-build-3-0-1/patches/dev300/calc-external-defined-names-offapi.diff	(original)
+++ branches/ooo-build-3-0-1/patches/dev300/calc-external-defined-names-offapi.diff	Thu Jan 15 02:44:24 2009
@@ -1,3 +1,17 @@
+diff --git offapi/com/sun/star/sheet/DatabaseRange.idl offapi/com/sun/star/sheet/DatabaseRange.idl
+index 4bbb5f5..6e66ba4 100644
+--- offapi/com/sun/star/sheet/DatabaseRange.idl
++++ offapi/com/sun/star/sheet/DatabaseRange.idl
+@@ -154,7 +154,8 @@ published service DatabaseRange
+     /** returns the index used to refer to this range in token arrays.
+ 
+         <p>A token describing a database range shall contain the op-code
+-        OPCODE_DB_AREA and this index as data part.</p>
++        obtained from the <const>FormulaMapGroupSpecialOffset::DB_AREA</const>
++        and this index as data part.</p>
+ 
+         @see com::sun::star::sheet::FormulaToken
+         @see com::sun::star::sheet::FormulaMapGroupSpecialOffset::DB_AREA
 diff --git offapi/com/sun/star/sheet/ExternalDocLink.idl offapi/com/sun/star/sheet/ExternalDocLink.idl
 new file mode 100644
 index 0000000..9c7f70d
@@ -284,10 +298,10 @@
 +
 diff --git offapi/com/sun/star/sheet/ExternalReference.idl offapi/com/sun/star/sheet/ExternalReference.idl
 new file mode 100644
-index 0000000..a2bc3c7
+index 0000000..7686310
 --- /dev/null
 +++ offapi/com/sun/star/sheet/ExternalReference.idl
-@@ -0,0 +1,90 @@
+@@ -0,0 +1,99 @@
 +/*************************************************************************
 + *
 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -325,47 +339,56 @@
 +
 +//=============================================================================
 +
-+/** Data structure to store information about an external reference.  An 
++/** Data structure to store information about an external reference.  An
 +    external reference can be either a single cell reference, a cell range
 +    reference, or a named range.
 +
++    @see FormulaMapGroupSpecialOffset::PUSH
++
 +    @since OOo 3.1
 + */
 +struct ExternalReference
 +{
 +    //-------------------------------------------------------------------------
 +
-+    /** Index of an externally linked document.  Each externally-linked document 
++    /** Index of an externally linked document.  Each externally-linked document
 +        has a unique index value.
-+        
-+        <p>You can get the index value of an external document from the 
-+        corresponding <type scope="com::sun::star::sheet">ExternalDocLink</type> 
++
++        <p>You can get the index value of an external document from the
++        corresponding <type scope="com::sun::star::sheet">ExternalDocLink</type>
 +        instance through its attribute <type scope="com::sun::star::sheet::ExternalDocLink">TokenIndex</type>.</p>
 +
 +        @see com::sun::star::sheet::ExternalDocLink
 +        @see com::sun::star::sheet::ExternalDocLink::TokenIndex
 +     */
 +    long Index;
-+    
++
++#if 0
 +    //-------------------------------------------------------------------------
 +
 +    /** Name of the sheet that the external reference points to.
 +
-+        <p>In case of a cell range reference that spans across multiple 
++        <p>In case of a cell range reference that spans across multiple
 +        sheets, this is the name of the first sheet in that range.</p>
 +
-+        <p>Note that an external range name ignores this value at the moment, 
-+        but <i>it may make use of this data in the future when Calc supports a 
++        <p>Note that an external range name ignores this value at the moment,
++        but <i>it may make use of this data in the future when Calc supports a
 +        sheet-specific range name.</i></p>
 +     */
 +    string SheetName;
++#endif
 +
 +    //-------------------------------------------------------------------------
 +
-+    /** Reference data.  This can store either <type scope="com::sun::star::sheet">SingleReference</type>
-+        for a single cell reference, <type scope="com::sun::star::sheet">ComplexReference</type>
-+        for a cell range reference, or simply a <type>string</type> for a range 
-+        name.
++    /** Reference data.
++
++        <p>This can store either <type>SingleReference</type> for a single
++        cell reference, <type>ComplexReference</type> for a cell range
++        reference, or simply a <type>string</type> for a defined name.</p>
++
++        <p>The <member>SingleReference::Sheet</member> member shall contain
++        the index of the external sheet cache containing the values of the
++        externally referenced cells.</p>
 +
 +        @see com::sun::star::sheet::SingleReference
 +        @see com::sun::star::sheet::ComplexReference
@@ -439,25 +462,249 @@
 +}; }; }; };
 +
 +#endif
+diff --git offapi/com/sun/star/sheet/FormulaMapGroup.idl offapi/com/sun/star/sheet/FormulaMapGroup.idl
+index c128585..e846d72 100644
+--- offapi/com/sun/star/sheet/FormulaMapGroup.idl
++++ offapi/com/sun/star/sheet/FormulaMapGroup.idl
+@@ -47,7 +47,10 @@ module com {  module sun {  module star {  module sheet {
+  */
+ constants FormulaMapGroup
+ {
+-    /** Group of op-codes without a string symbol */
++    /** Group of op-codes without a string symbol.
++
++        @see FormulaMapGroupSpecialOffset
++      */
+     const long SPECIAL            = 0;
+ 
+     /** Separators and parentheses */
 diff --git offapi/com/sun/star/sheet/FormulaMapGroupSpecialOffset.idl offapi/com/sun/star/sheet/FormulaMapGroupSpecialOffset.idl
-index 20369b2..6fa02d0 100644
+index 20369b2..7ebfe52 100644
 --- offapi/com/sun/star/sheet/FormulaMapGroupSpecialOffset.idl
 +++ offapi/com/sun/star/sheet/FormulaMapGroupSpecialOffset.idl
-@@ -59,6 +59,8 @@ constants FormulaMapGroupSpecialOffset
+@@ -31,37 +31,182 @@
+ #ifndef __com_sun_star_sheet_FormulaMapGroupSpecialOffset_idl__
+ #define __com_sun_star_sheet_FormulaMapGroupSpecialOffset_idl__
+ 
+-//=============================================================================
++// ===========================================================================
+ 
+ module com {  module sun {  module star {  module sheet {
+ 
+-//=============================================================================
++// ===========================================================================
+ 
+ /** Constants designating the offsets within the sequence returned by
+     <member>XFormurmulaOpCodeMapper::getAvailableMappings</member> when
+-    called for group <type>FormulaMapGroup</type> SPECIAL.
++    called for group <const>FormulaMapGroup::SPECIAL</const>.
+ 
+     The number of constants may grow in future versions!
+  */
+ constants FormulaMapGroupSpecialOffset
+ {
++    // -----------------------------------------------------------------------
++
++    /** Formula tokens containing the op-code obtained from this offset
++        describe a formula operand token that will be pushed onto the formula
++        stack while the formula is interpreted.
++
++        <p>The <member>FormulaToken::Data</member> member shall contain one of
++        the following values:</p>
++
++        <ul>
++        <li>A value of type <atom>double</atom> for literal floating-point
++            constants.</li>
++        <li>A <atom>string</atom> for literal text.</li>
++        <li>A sequence of sequence of <atom>any</atom> for a literal array.
++            The contained values shall be of type <atom>double</atom> or
++            <atom>string</atom>. Floating-point values and strings may occur
++            together in an array.</li>
++        <li>A struct of type <type>SingleReference</type> for a reference to a
++            single cell in the own document.</li>
++        <li>A struct of type <type>ComplexReference</type> for a reference to
++            a range of cells in the own document.</li>
++        <li>A struct of type <type>ExternalReference</type> for a reference to
++            a cell, a range of cells, or a defined name in an external
++            document.</li>
++        </ul>
++     */
+     const long PUSH               = 0;
++
++    // -----------------------------------------------------------------------
++
+     const long CALL               = 1;
++
++    // -----------------------------------------------------------------------
++
++    /** Formula tokens containing the op-code obtained from this offset
++        instruct the formula interpreter to immediately stop interpreting the
++        formula.
++
++        <p>The <member>FormulaToken::Data</member> member is not used
++        and should be empty.</p>
++     */
+     const long STOP               = 2;
++
++    // -----------------------------------------------------------------------
++
++    /** Formula tokens containing the op-code obtained from this offset
++        describe the reference to an external function (e.g. add-in function)
++        used in formulas.
++
++        <p>The <member>FormulaToken::Data</member> member shall contain a
++        <atom>string</atom> with the programmatical name of the function, e.g.
++        "com.sun.star.sheet.addin.Analysis.getEomonth" for the EOMONTH
++        function from the Analsysis add-in.</p>
++     */
+     const long EXTERNAL           = 3;
++
++    // -----------------------------------------------------------------------
++
++    /** Formula tokens containing the op-code obtained from this offset
++        describe the reference to a defined name (also known as named range)
++        used in formulas.
++
++        <p>The <member>FormulaToken::Data</member> member shall contain an
++        integer value of type <atom>long</atom> specifying the index of the
++        defined name. This index can be obtained from the defined name using
++        its <type>NamedRange::TokenIndex</type> property.</p>
++
++        @see  NamedRange
++     */
+     const long NAME               = 4;
++
++    // -----------------------------------------------------------------------
++
++    /** Formula tokens containing the op-code obtained from this offset
++        describe an invalid name that resolves to the #NAME? error in formulas.
++
++        <p>The <member>FormulaToken::Data</member> member is not used
++        and should be empty.</p>
++     */
+     const long NO_NAME            = 5;
++
++    // -----------------------------------------------------------------------
++
++    /** Formula tokens containing the op-code obtained from this offset
++        describe an empty function parameter.
++
++        <p>Example: In the formula =SUM(1;;2) the second parameter is empty
++        and represented by a formula token containing the "empty" op-code.</p>
++
++        <p>The <member>FormulaToken::Data</member> member is not used
++        and should be empty.</p>
++     */
+     const long MISSING            = 6;
++
++    // -----------------------------------------------------------------------
++
++    /** Formula tokens containing the op-code obtained from this offset
++        describe "bad" data in a formula, e.g. data the formula parser was not
++        able to parse.
++
++        <p>The <member>FormulaToken::Data</member> member shall contain a
++        <atom>string</string> with the bad data. This string will be displayed
++        in the formula.</p>
++     */
+     const long BAD                = 7;
++
++    // -----------------------------------------------------------------------
++
++    /** Formula tokens containing the op-code obtained from this offset
++        describe white-space characters within the string representation of a
++        formula.
++
++        <p>White-space characters in formulas are used for readability and do
++        not affect the result of the formula.</p>
++
++        <p>The <member>FormulaToken::Data</member> member shall contain a
++        positive integer value of type <atom>long</atom> specifying the number
++        of space characters.</p>
++
++        <p>Attention: This may change in next versions to support other
++        characters than simple space characters (e.g. line feeds, horizontal
++        tabulators, non-breakable spaces).</p>
++     */
+     const long SPACES             = 8;
++
++    // -----------------------------------------------------------------------
++
+     const long MAT_REF            = 9;
++
++    // -----------------------------------------------------------------------
++
++    /** Formula tokens containing the op-code obtained from this offset
++        describe the reference to a database range used in formulas.
++
++        <p>The <member>FormulaToken::Data</member> member shall contain an
++        integer value of type <atom>long</atom> specifying the index of the
++        database range. This index can be obtained from the database range
++        using its <type>DatabaseRange::TokenIndex</type> property.</p>
++
++        @see  DatabaseRange
++     */
+     const long DB_AREA            = 10;
++
++    // -----------------------------------------------------------------------
++
++    /** Formula tokens containing the op-code obtained from this offset
++        describe the reference to a macro function called in a formula.
++
++        <p>The <member>FormulaToken::Data</member> member shall contain a
++        <atom>string</atom> specifying the name of the macro function.</p>
++     */
      const long MACRO              = 11;
++
++    // -----------------------------------------------------------------------
++
      const long COL_ROW_NAME       = 12;
-     const long COL_ROW_NAME_AUTO  = 13;
-+    /// @since OOo 3.1
-+    const long EXTERNAL_REFERENCE = 14;
+-    const long COL_ROW_NAME_AUTO  = 13;
++
++    // -----------------------------------------------------------------------
++
  };
  
- //=============================================================================
+-//=============================================================================
++// ===========================================================================
+ 
+ }; }; }; };
+ 
+diff --git offapi/com/sun/star/sheet/FormulaToken.idl offapi/com/sun/star/sheet/FormulaToken.idl
+index cec2ea4..c0aff64 100644
+--- offapi/com/sun/star/sheet/FormulaToken.idl
++++ offapi/com/sun/star/sheet/FormulaToken.idl
+@@ -44,6 +44,8 @@ struct FormulaToken
+     //-------------------------------------------------------------------------
+ 
+     /** is the OpCode of the token.
++
++        @see com::sun::star::sheet::XFormulaOpCodeMapper
+      */
+     long OpCode;
+ 
+diff --git offapi/com/sun/star/sheet/NamedRange.idl offapi/com/sun/star/sheet/NamedRange.idl
+index 30af011..c4d79dc 100644
+--- offapi/com/sun/star/sheet/NamedRange.idl
++++ offapi/com/sun/star/sheet/NamedRange.idl
+@@ -77,8 +77,9 @@ published service NamedRange
+ 
+     /** returns the index used to refer to this name in token arrays.
+ 
+-        <p>A token describing a defined name shall contain the op-code
+-        OPCODE_NAME and this index as data part.</p>
++        <p>A token describing a defined name shall contain the op-code obtained
++        from the <const>FormulaMapGroupSpecialOffset::NAME</const> offset and
++        this index as data part.</p>
+ 
+         @see com::sun::star::sheet::FormulaToken
+         @see com::sun::star::sheet::FormulaMapGroupSpecialOffset::NAME
 diff --git offapi/com/sun/star/sheet/XExternalDocLink.idl offapi/com/sun/star/sheet/XExternalDocLink.idl
 new file mode 100644
-index 0000000..0f3e02b
+index 0000000..27a706c
 --- /dev/null
 +++ offapi/com/sun/star/sheet/XExternalDocLink.idl
-@@ -0,0 +1,84 @@
+@@ -0,0 +1,94 @@
 +/*************************************************************************
 + *
 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -491,6 +738,9 @@
 +#ifndef __com_sun_star_sheet_XExternalDocLink_idl__
 +#define __com_sun_star_sheet_XExternalDocLink_idl__
 +
++#include <com/sun/star/container/XEnumerationAccess.idl>
++#include <com/sun/star/container/XIndexAccess.idl>
++#include <com/sun/star/container/XNameAccess.idl>
 +#include <com/sun/star/sheet/XExternalSheetCache.idl>
 +
 +module com {  module sun {  module star {  module sheet {
@@ -505,6 +755,10 @@
 + */
 +interface XExternalDocLink
 +{
++    interface com::sun::star::container::XNameAccess;
++    interface com::sun::star::container::XIndexAccess;
++    interface com::sun::star::container::XEnumerationAccess;
++
 +    //-------------------------------------------------------------------------
 +
 +    /** <p>This method adds a new sheet cache instance to the extternal document 
@@ -526,13 +780,16 @@
 +    
 +        <p>This index value corresponds with the external document 
 +        represented by an instance of 
-+        <type scope="com::sun::star::sheet">ExternalDocLink</type>.  This 
++        <type scope="com::sun::star::sheet">ExternalDocLink</type>.  This
 +        value is stored within a formula token instance.</p>
-+    
-+        <p>Each external document link has a unique index value.</p>
 +
++        <p>Each external document cache instance has a unique index value, and this
++        index value can be used to retrieve the corresponding external document cache
++        from the parent <type scope="com::sun::star::sheet">ExternalDocLinks</type> instance.</p>
++
++        @see com::sun::star::sheet::ExternalDocLinks
 +        @see com::sun::star::sheet::FormulaToken
-+        @see com::sun::star::sheet::FormulaMapGroupSpecialOffset::EXTERNAL_REFERENCE
++        @see com::sun::star::sheet::ExternalReference
 +     */
 +    [attribute, readonly] long TokenIndex;
 +};
@@ -616,10 +873,10 @@
 +#endif
 diff --git offapi/com/sun/star/sheet/XExternalSheetCache.idl offapi/com/sun/star/sheet/XExternalSheetCache.idl
 new file mode 100644
-index 0000000..0c35f7f
+index 0000000..1d91f70
 --- /dev/null
 +++ offapi/com/sun/star/sheet/XExternalSheetCache.idl
-@@ -0,0 +1,84 @@
+@@ -0,0 +1,102 @@
 +/*************************************************************************
 + *
 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -658,7 +915,7 @@
 +module com {  module sun {  module star {  module sheet {
 +
 +/** Primary interface for the <type scope="com::sun::star::sheet">ExternalSheetCache</type> service.
-+   
++
 +    @see com::sun::star::sheet::ExternalSheetCache
 +
 +    @since OOo 3.1.0
@@ -673,15 +930,15 @@
 +        @param nColumn column position (0-based)
 +        @param aValue cell value to be cached
 +     */
-+    void setCellValue( [in] long nRow, [in] long nColumn, [in] any aValue )
++    void setCellValue( [in] long nColumn, [in] long nRow, [in] any aValue )
 +            raises (com::sun::star::lang::IllegalArgumentException);
 +
 +    /** It retrieves a cached value from a specified cell position.  The cached
 +        value can be either <type>string</type> or <type>double</type>.
-+    
++
 +        @return any cached cell value
 +     */
-+    any getCellValue( [in] long nRow, [in] long nColumn )
++    any getCellValue( [in] long nColumn, [in] long nRow )
 +            raises (com::sun::star::lang::IllegalArgumentException);
 +
 +    /** It returns a list of all row numbers where a cached cell or cells exist.
@@ -691,14 +948,32 @@
 +     */
 +    sequence< long > getAllRows();
 +
-+    /** Given a row number, this method returns a list of all columns numbers 
-+        that store cached cell values in that row.  The column numbers are 
++    /** Given a row number, this method returns a list of all columns numbers
++        that store cached cell values in that row.  The column numbers are
 +        sorted in ascending order.
 +
 +        @return sequence<long> list of all columns numbers with cached cell values
 +     */
 +    sequence< long > getAllColumns( [in] long nRow )
 +            raises (com::sun::star::lang::IllegalArgumentException);
++
++    //-------------------------------------------------------------------------
++
++    /** Index corresponding to this instance of an external sheet cache for
++        usage in formula tokens.
++
++        <p>This index to the external sheet cache is expected in the
++        <member>SingleReference::Sheet</member> member if it is part of an
++        external reference token.
++
++        <p>Each external sheet cache has a unique index value inside the
++        <type>ExternalDocLink</type> instance.</p>
++
++        @see FormulaToken
++        @see ExternalReference
++     */
++    [attribute, readonly] long TokenIndex;
++
 +};
 +
 +}; }; }; };

Added: branches/ooo-build-3-0-1/patches/dev300/calc-external-defined-names-officecfg.diff
==============================================================================
--- (empty file)
+++ branches/ooo-build-3-0-1/patches/dev300/calc-external-defined-names-officecfg.diff	Thu Jan 15 02:44:24 2009
@@ -0,0 +1,20 @@
+diff --git officecfg/registry/schema/org/openoffice/Office/Calc.xcs officecfg/registry/schema/org/openoffice/Office/Calc.xcs
+index 7e55cf3..39e4950 100644
+--- officecfg/registry/schema/org/openoffice/Office/Calc.xcs
++++ officecfg/registry/schema/org/openoffice/Office/Calc.xcs
+@@ -785,13 +785,13 @@
+ 							<desc>MAX</desc>
+ 						</info>
+ 					</enumeration>
+-					<enumeration oor:value="5">
++					<enumeration oor:value="6">
+ 						<info>
+ 							<desc>IF</desc>
+ 						</info>
+ 					</enumeration>
+ 				</constraints>
+-				<value>224 226 222 223 5</value>
++				<value>224 226 222 223 6</value>
+ 			</prop>
+ 			<prop oor:name="AutoInput" oor:type="xs:boolean">
+ 				<!-- OldPath: Calc/Input -->

Modified: branches/ooo-build-3-0-1/patches/dev300/calc-external-defined-names-sc.diff
==============================================================================
--- branches/ooo-build-3-0-1/patches/dev300/calc-external-defined-names-sc.diff	(original)
+++ branches/ooo-build-3-0-1/patches/dev300/calc-external-defined-names-sc.diff	Thu Jan 15 02:44:24 2009
@@ -251,7 +251,7 @@
  
      BOOL            IsCorrected() { return bCorrected; }
 diff --git sc/inc/document.hxx sc/inc/document.hxx
-index a01f09b..5d4ca1f 100644
+index 2a27407..414f0c5 100644
 --- sc/inc/document.hxx
 +++ sc/inc/document.hxx
 @@ -93,6 +93,7 @@ class ScDocProtection;
@@ -289,10 +289,10 @@
  
 diff --git sc/inc/externalrefmgr.hxx sc/inc/externalrefmgr.hxx
 new file mode 100644
-index 0000000..91be428
+index 0000000..fa2bd9e
 --- /dev/null
 +++ sc/inc/externalrefmgr.hxx
-@@ -0,0 +1,405 @@
+@@ -0,0 +1,524 @@
 +/*************************************************************************
 + *
 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -332,12 +332,14 @@
 +#include "sfx2/lnkbase.hxx"
 +#include "tools/time.hxx"
 +#include "vcl/timer.hxx"
++#include "svtools/zforlist.hxx"
 +#include "scmatrix.hxx"
 +
 +#include <hash_map>
 +#include <hash_set>
 +#include <boost/shared_ptr.hpp>
 +#include <vector>
++#include <list>
 +
 +class ScDocument;
 +class ScToken;
@@ -375,38 +377,54 @@
 +
 +// ============================================================================
 +
-+/** 
++/**
 + * Cache table for external reference data.
 + */
 +class ScExternalRefCache
 +{
-+    struct RangeHash
-+    {
-+        size_t operator()(const ScRange& rRange) const
-+        {
-+            const ScAddress& s = rRange.aStart;
-+            const ScAddress& e = rRange.aEnd;
-+            return s.Tab() + s.Col() + s.Row() + e.Tab() + e.Col() + e.Row();
-+        }
-+    };
-+
 +public:
-+    
 +    typedef ::boost::shared_ptr<ScToken>            TokenRef;
 +    typedef ::boost::shared_ptr<ScTokenArray>       TokenArrayRef;
-+    typedef ::std::hash_map<SCCOL, TokenRef>        RowDataType;
++
++    struct TableName
++    {
++        String maUpperName;
++        String maRealName;
++
++        explicit TableName(const String& rUppper, const String& rReal);
++    };
++
++    struct CellFormat
++    {
++        bool        mbIsSet;
++        short       mnType;
++        sal_uInt32  mnIndex;
++
++        explicit CellFormat();
++    };
++
++private:
++    /** individual cell within cached external ref table. */
++    struct Cell
++    {
++        TokenRef    mxToken;
++        sal_uInt32  mnFmtIndex;
++    };
++    typedef ::std::hash_map<SCCOL, Cell>            RowDataType;
 +    typedef ::std::hash_map<SCROW, RowDataType>     RowsDataType;
 +
++public:
 +    class Table
 +    {
 +    public:
 +        Table();
 +        ~Table();
 +
-+        void setCell(SCROW nRow, SCCOL nCol, TokenRef pToken);
-+        TokenRef getCell(SCROW nRow, SCCOL nCol) const;
++        void setCell(SCCOL nCol, SCROW nRow, TokenRef pToken, sal_uInt32 nFmtIndex = 0);
++        TokenRef getCell(SCCOL nCol, SCROW nRow, sal_uInt32* pnFmtIndex = NULL) const;
 +        void getAllRows(::std::vector<SCROW>& rRows) const;
 +        void getAllCols(SCROW nRow, ::std::vector<SCCOL>& rCols) const;
++        void getAllNumberFormats(::std::vector<sal_uInt32>& rNumFmts) const;
 +
 +    private:
 +        RowsDataType maRows;
@@ -421,24 +439,26 @@
 +    const String* getRealTableName(sal_uInt16 nFileId, const String& rTabName) const;
 +    const String* getRealRangeName(sal_uInt16 nFileId, const String& rRangeName) const;
 +
-+    /** 
++    /**
 +     * Get a cached cell data at specified cell location.
 +     *
 +     * @param nFileId file ID of an external document
 +     * @param rTabName sheet name
-+     * @param nRow 
-+     * @param nCol 
-+     * 
++     * @param nRow
++     * @param nCol
++     *
 +     * @return pointer to the token instance in the cache.  <i>The caller does
 +     *         not need to delete this instance since its life cycle is
 +     *         managed by this class.</i>
 +     */
-+    ScExternalRefCache::TokenRef getCellData(sal_uInt16 nFileId, const String& rTabName, SCROW nRow, SCCOL nCol);
++    ScExternalRefCache::TokenRef getCellData(
++        sal_uInt16 nFileId, const String& rTabName, SCROW nRow, SCCOL nCol, 
++        sal_uInt32* pnFmtIndex = NULL);
 +
-+    /** 
-+     * Get a cached cell range data. 
-+     *  
-+     * @return a new token array instance.  Note that <i>the caller must 
++    /**
++     * Get a cached cell range data.
++     *
++     * @return a new token array instance.  Note that <i>the caller must
 +     *         manage the life cycle of the returned instance</i>, which is
 +     *         guaranteed if the TokenArrayRef is properly used..
 +     */
@@ -447,7 +467,7 @@
 +    ScExternalRefCache::TokenArrayRef getRangeNameTokens(sal_uInt16 nFileId, const String& rName);
 +    void setRangeNameTokens(sal_uInt16 nFileId, const String& rName, TokenArrayRef pArray);
 +
-+    void setCellData(sal_uInt16 nFileId, const String& rTabName, SCROW nRow, SCCOL nCol, TokenRef pToken);
++    void setCellData(sal_uInt16 nFileId, const String& rTabName, SCROW nRow, SCCOL nCol, TokenRef pToken, sal_uInt32 nFmtIndex);
 +
 +    struct SingleRangeData
 +    {
@@ -460,40 +480,32 @@
 +
 +    bool isDocInitialized(sal_uInt16 nFileId);
 +    void initializeDoc(sal_uInt16 nFileId, const ::std::vector<String>& rTabNames);
++    String getTableName(sal_uInt16 nFileId, size_t nCacheId) const;
 +    void getAllTableNames(sal_uInt16 nFileId, ::std::vector<String>& rTabNames) const;
++    void getAllNumberFormats(::std::vector<sal_uInt32>& rNumFmts) const;
++    bool hasCacheTable(sal_uInt16 nFileId, const String& rTabName) const;
++    size_t getCacheTableCount(sal_uInt16 nFileId) const;
 +
-+    /** 
-+     * Get a cache table instance for specified file and table name.  If the 
-+     * table instance is not already present, it'll instantiate a new one and 
-+     * append it to the end of the table array.  <I>It's important to be 
-+     * aware of this fact especially for multi-table ranges for which 
-+     * table orders are critical.</I> 
-+     *  
-+     * Excel filter calls this method to populate the cache table from the 
-+     * XCT/CRN records. 
-+     *
-+     * @param nFileId file ID
-+     * @param rTabName table name
-+     * 
-+     * @return shared_ptr to the cache table instance
-+     */
-+    ScExternalRefCache::TableTypeRef getCacheTable(sal_uInt16 nFileId, const String& rTabName, bool bCreateNew);
++    ScExternalRefCache::TableTypeRef getCacheTable(sal_uInt16 nFileId, size_t nTabIndex) const;
++    ScExternalRefCache::TableTypeRef getCacheTable(sal_uInt16 nFileId, const String& rTabName, bool bCreateNew, size_t* pnIndex);
 +
 +    void clearCache(sal_uInt16 nFileId);
 +
 +private:
++    struct RangeHash
++    {
++        size_t operator()(const ScRange& rRange) const
++        {
++            const ScAddress& s = rRange.aStart;
++            const ScAddress& e = rRange.aEnd;
++            return s.Tab() + s.Col() + s.Row() + e.Tab() + e.Col() + e.Row();
++        }
++    };
++
 +    typedef ::std::hash_map<String, TokenArrayRef, ScStringHashCode>    RangeNameMap;
 +    typedef ::std::hash_map<ScRange, TokenArrayRef, RangeHash>          RangeArrayMap;
 +    typedef ::std::hash_map<String, String, ScStringHashCode>           NamePairMap;
 +
-+    struct TableName
-+    {
-+        String maUpperName;
-+        String maRealName;
-+
-+        explicit TableName(const String& rUppper, const String& rReal);
-+    };
-+
 +    /** Represents data cached for a single external document. */
 +    struct DocItem
 +    {
@@ -525,16 +537,50 @@
 +
 +class ScExternalRefManager
 +{
-+private:
-+    struct AddressHash
++public:
++    /** 
++     *  Collection of cell addresses that contain external references. This
++     *  data is used for link updates.
++     */
++    class RefCells
 +    {
-+        size_t operator()(const ScAddress& rAddr) const
-+        {
-+            // dumb hashing - how do we properly hash a cell address?
-+            return rAddr.Tab() + rAddr.Col() + rAddr.Row();
-+        }
++    public:
++        RefCells();
++        ~RefCells();
++
++        void insertCell(const ScAddress& rAddr);
++        void removeCell(const ScAddress& rAddr);
++        void moveTable(SCTAB nOldTab, SCTAB nNewTab, bool bCopy);
++        void insertTable(SCTAB nPos);
++        void removeTable(SCTAB nPos);
++        void refreshAllCells(ScExternalRefManager& rRefMgr);
++    private:
++
++        typedef ::std::hash_set<SCROW>              RowSet;
++        typedef ::std::hash_map<SCCOL, RowSet>      ColSet;
++        struct TabItem
++        {
++            SCTAB       mnIndex;
++            ColSet      maCols;
++            explicit TabItem(SCTAB nIndex);
++            explicit TabItem(const TabItem& r);
++        };
++        typedef ::boost::shared_ptr<TabItem>        TabItemRef;
++
++        /** 
++         * Return the position that points either to the specified table 
++         * position or to the position where a new table would be inserted in 
++         * case the specified table is not present.
++         *  
++         * @param nTab index of the desired table 
++         */
++        ::std::list<TabItemRef>::iterator getTabPos(SCTAB nTab);
++
++        // This list must be sorted by the table index at all times.
++        ::std::list<TabItemRef> maTables;
 +    };
 +
++private:
 +    /** Shell instance for a source document. */
 +    struct SrcShell
 +    {
@@ -542,14 +588,11 @@
 +        Time                maLastAccess;
 +    };
 +
-+    typedef ::boost::shared_ptr<ScToken>        TokenRef;
-+    typedef ::boost::shared_ptr<ScTokenArray>   TokenArrayRef;
-+
-+    typedef ::std::hash_map<sal_uInt16, SrcShell>                                   DocShellMap;
-+    typedef ::std::hash_set<sal_uInt16>                                             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;
++    typedef ::std::hash_map<sal_uInt16, RefCells>           RefCellMap;
++    typedef ::std::hash_map<sal_uInt16, SvNumberFormatterMergeMap> NumFmtMap;
 +
 +public:
 +    /** Source document meta-data container. */
@@ -565,35 +608,80 @@
 +    explicit ScExternalRefManager(ScDocument* pDoc);
 +    ~ScExternalRefManager();
 +
-+    ScExternalRefCache::TableTypeRef getCacheTable(sal_uInt16 nFileId, const String& rTabName, bool bCreateNew = true);
-+    void storeRangeNameTokens(sal_uInt16 nFileId, const String& rName, const ScTokenArray& rArray);
++    String getCacheTableName(sal_uInt16 nFileId, size_t nTabIndex) const;
++
++    /**
++     * Get a cache table instance for specified table and table index.  Unlike
++     * the other method that takes a table name, this method does not create a
++     * new table when a table is not available for specified index.
++     *
++     * @param nFileId file ID
++     * @param nTabIndex cache table index
++     *
++     * @return shared_ptr to the cache table instance
++     */
++    ScExternalRefCache::TableTypeRef getCacheTable(sal_uInt16 nFileId, size_t nTabIndex) const;
 +
-+    ScExternalRefCache::TokenRef getSingleRefToken(sal_uInt16 nFileId, const String& rTabName, const ScAddress& rCell, const ScAddress* pCurPos, SCTAB* pTab);
++    /**
++     * Get a cache table instance for specified file and table name.  If the
++     * table instance is not already present, it'll instantiate a new one and
++     * append it to the end of the table array.  <I>It's important to be
++     * aware of this fact especially for multi-table ranges for which
++     * table orders are critical.</I>
++     *
++     * Excel filter calls this method to populate the cache table from the
++     * XCT/CRN records.
++     *
++     * @param nFileId file ID
++     * @param rTabName table name
++     *
++     * @return shared_ptr to the cache table instance
++     */
++    ScExternalRefCache::TableTypeRef getCacheTable(sal_uInt16 nFileId, const String& rTabName, bool bCreateNew, size_t* pnIndex = 0);
++    void getAllCachedTableNames(sal_uInt16 nFileId, ::std::vector<String>& rTabNames) const;
 +
 +    /** 
-+     * Get an array of tokens that consist of the specified external cell 
-+     * range. 
++     * Get all unique number format indices that are used in the cache tables. 
++     * The retrieved indices are sorted in ascending order.
++     *
++     * @param rNumFmts (reference) all unique number format indices.
++     */
++    void getAllCachedNumberFormats(::std::vector<sal_uInt32>& rNumFmts) const;
++
++    bool hasCacheTable(sal_uInt16 nFileId, const String& rTabName) const;
++    size_t getCacheTableCount(sal_uInt16 nFileId) const;
++    sal_uInt16 getExternalFileCount() const;
++
++    void storeRangeNameTokens(sal_uInt16 nFileId, const String& rName, const ScTokenArray& rArray);
++
++    ScExternalRefCache::TokenRef getSingleRefToken(
++        sal_uInt16 nFileId, const String& rTabName, const ScAddress& rCell, 
++        const ScAddress* pCurPos, SCTAB* pTab, ScExternalRefCache::CellFormat* pFmt = NULL);
++
++    /**
++     * Get an array of tokens that consist of the specified external cell
++     * range.
 +     *
 +     * @param nFileId file ID for an external document
 +     * @param rTabName referenced sheet name
 +     * @param rRange referenced cell range
-+     * @param pCurPos current cursor position to keep track of cells that 
++     * @param pCurPos current cursor position to keep track of cells that
 +     *                reference an external data.
-+     * 
-+     * @return shared_ptr to a token array instance.  <i>The caller must not 
++     *
++     * @return shared_ptr to a token array instance.  <i>The caller must not
 +     *         delete the instance returned by this method.</i>
 +     */
 +    ScExternalRefCache::TokenArrayRef getDoubleRefTokens(sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange, const ScAddress* pCurPos);
 +
-+    /** 
-+     * Get an array of tokens corresponding with a specified name in a 
-+     * specified file. 
-+     *  
-+     * @param pCurPos currnet cell address where this name token is used. 
++    /**
++     * Get an array of tokens corresponding with a specified name in a
++     * specified file.
++     *
++     * @param pCurPos currnet cell address where this name token is used.
 +     *                This is purely to keep track of all cells containing
 +     *                external names for refreshing purposes.  If this is
 +     *                NULL, then the cell will not be added to the list.
-+     * 
++     *
 +     * @return shared_ptr to array of tokens composing the name
 +     */
 +    ScExternalRefCache::TokenArrayRef getRangeNameTokens(sal_uInt16 nFileId, const String& rName, const ScAddress* pCurPos = NULL);
@@ -601,34 +689,33 @@
 +    const String& getOwnDocumentName() const;
 +    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:///. 
++    /**
++     * Takes a flat file name, and convert it to an absolute URL path.  An
++     * absolute URL path begines with 'file:///.
 +     *
-+     * @param rFile file name to convert 
++     * @param rFile file name to convert
 +     */
 +    void convertToAbsName(String& rFile) const;
 +    sal_uInt16 getExternalFileId(const String& rFile);
 +    const String* getExternalFileName(sal_uInt16 nFileId) const;
++    bool hasExternalFile(sal_uInt16 nFileId) const;
++    bool hasExternalFile(const String& rFile) const;
 +    const SrcFileData* getExternalFileData(sal_uInt16 nFileId) const;
 +
 +    const String* getRealTableName(sal_uInt16 nFileId, const String& rTabName) const;
 +    const String* getRealRangeName(sal_uInt16 nFileId, const String& rRangeName) const;
-+    void getAllCachedTableNames(sal_uInt16 nFileId, ::std::vector<String>& rTabNames) 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 when the source document ever gets reloaded. 
++    /**
++     * Set the filter name and options if any for a given source document.
++     * These values get reset when the source document ever gets reloaded.
 +     *
-+     * @param nFileId 
-+     * @param rFilterName 
-+     * @param rOptions 
-+     * @return 
++     * @param nFileId
++     * @param rFilterName
++     * @param rOptions
 +     */
 +    void setFilterData(sal_uInt16 nFileId, const String& rFilterName, const String& rOptions);
 +
@@ -637,20 +724,48 @@
 +
 +    bool hasExternalData() const;
 +
-+    /** 
-+     * Re-generates relative names for all stored source files.  This is 
-+     * necessary when exporting to an ods document, to ensure that all source 
++    /**
++     * Re-generates relative names for all stored source files.  This is
++     * necessary when exporting to an ods document, to ensure that all source
 +     * files have their respective relative names for xlink:href export.
 +     */
 +    void resetSrcFileData();
 +
++    /** 
++     * Update a single referencing cell position.
++     *
++     * @param rOldPos old position
++     * @param rNewPos new position
++     */
++    void updateRefCell(const ScAddress& rOldPos, const ScAddress& rNewPos, bool bCopy);
++
++    /** 
++     * Update referencing cells affected by sheet movement.
++     *
++     * @param nOldTab old sheet position
++     * @param nNewTab new sheet position
++     * @param bCopy whether this is a sheet move (false) or sheet copy (true)
++     */
++    void updateRefMoveTable(SCTAB nOldTab, SCTAB nNewTab, bool bCopy);
++
++    /** 
++     * Update referencing cells affected by sheet insertion.
++     *
++     * @param nPos sheet insertion position.  All sheets to the right 
++     *             including the one at the insertion poistion shift to the
++     *             right by one.
++     */
++    void updateRefInsertTable(SCTAB nPos);
++
++    void updateRefDeleteTable(SCTAB nPos);
++
 +private:
 +    ScExternalRefManager();
-+    ScExternalRefManager(const ScExternalRefManager&); 
++    ScExternalRefManager(const ScExternalRefManager&);
 +
-+    void refreshAllReferencingCells(sal_uInt16 nFileId);
++    void refreshAllRefCells(sal_uInt16 nFileId);
 +
-+    void insertReferencingCell(sal_uInt16 nFileId, const ScAddress& rCell);
++    void insertRefCell(sal_uInt16 nFileId, const ScAddress& rCell);
 +
 +    ScDocument* getSrcDocument(sal_uInt16 nFileId);
 +    SfxObjectShellRef loadSrcDocument(sal_uInt16 nFileId, String& rFilter);
@@ -660,22 +775,24 @@
 +
 +    bool compileTokensByCell(const ScAddress& rCell);
 +
-+    /** 
-+     * Purge those source document instances that have not been accessed for 
++    /**
++     * Purge those source document instances that have not been accessed for
 +     * the specified duration.
-+     *  
-+     * @param nTimeOut time out value in 100th of a second 
++     *
++     * @param nTimeOut time out value in 100th of a second
 +     */
 +    void purgeStaleSrcDocument(sal_Int32 nTimeOut);
 +
++    sal_uInt32 getMappedNumberFormat(sal_uInt16 nFileId, sal_uInt32 nNumFmt, ScDocument* pSrcDoc);
++
 +private:
 +    /** cache of referenced ranges and names from source documents. */
 +    ScExternalRefCache maRefCache;
 +
 +    ScDocument* mpDoc;
 +
-+    /** 
-+     * Source document cache.  This stores the original source document shell 
++    /**
++     * Source document cache.  This stores the original source document shell
 +     * instances.  They get purged after a certain period of time.
 +     */
 +    DocShellMap maDocShells;
@@ -683,12 +800,14 @@
 +    /** list of source documents that are managed by the link manager. */
 +    LinkedDocSet maLinkedDocs;
 +
-+    /** 
++    /**
 +     * List of referencing cells that may contain external names.  There is
 +     * one list per source document.
 +     */
 +    RefCellMap maRefCells;
 +
++    NumFmtMap maNumFormatMap;
++
 +    /** original source file index. */
 +    ::std::vector<SrcFileData> maSrcFiles;
 +
@@ -699,7 +818,7 @@
 +
 +#endif
 diff --git sc/inc/linkuno.hxx sc/inc/linkuno.hxx
-index b6fc524..586986e 100644
+index b6fc524..6dd39e8 100644
 --- sc/inc/linkuno.hxx
 +++ sc/inc/linkuno.hxx
 @@ -36,6 +36,9 @@
@@ -728,7 +847,7 @@
  
  class ScAreaLink;
  class ScDocShell;
-@@ -493,8 +501,112 @@ public:
+@@ -493,8 +501,137 @@ public:
  								throw(::com::sun::star::uno::RuntimeException);
  };
  
@@ -737,15 +856,15 @@
 +class ScExternalSheetCacheObj : public cppu::WeakImplHelper1< ::com::sun::star::sheet::XExternalSheetCache >
 +{
 +public:
-+    explicit ScExternalSheetCacheObj(ScExternalRefCache::TableTypeRef pTable);
++    explicit ScExternalSheetCacheObj(ScExternalRefCache::TableTypeRef pTable, size_t nIndex);
 +    ~ScExternalSheetCacheObj();
 +
 +                            // XExternalSheetCache
 +    virtual void SAL_CALL setCellValue(
-+        sal_Int32 nRow, sal_Int32 nCol, const ::com::sun::star::uno::Any& rAny)
++        sal_Int32 nCol, sal_Int32 nRow, const ::com::sun::star::uno::Any& rAny)
 +        throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
 +
-+    virtual ::com::sun::star::uno::Any SAL_CALL getCellValue(sal_Int32 nRow, sal_Int32 nCol)
++    virtual ::com::sun::star::uno::Any SAL_CALL getCellValue(sal_Int32 nCol, sal_Int32 nRow)
 +        throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
 +
 +    virtual ::com::sun::star::uno::Sequence< sal_Int32 > SAL_CALL getAllRows()
@@ -754,16 +873,21 @@
 +    virtual ::com::sun::star::uno::Sequence< sal_Int32 > SAL_CALL getAllColumns(sal_Int32 nRow)
 +        throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
 +
++    // Attributes
++    virtual sal_Int32 SAL_CALL getTokenIndex()
++            throw (::com::sun::star::uno::RuntimeException);
++
 +private:
 +    ScExternalSheetCacheObj();
 +    ScExternalSheetCacheObj(const ScExternalSheetCacheObj&);
 +
 +private:
 +    ScExternalRefCache::TableTypeRef mpTable;
++    size_t mnIndex;
 +};
-+
+ 
 +// ============================================================================
-+
+ 
 +class ScExternalDocLinkObj : public cppu::WeakImplHelper1< ::com::sun::star::sheet::XExternalDocLink >
 +{
 +public:
@@ -771,10 +895,36 @@
 +    ~ScExternalDocLinkObj();
 +
 +                            // XExternalDocLink
-+    virtual ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XExternalSheetCache > 
-+        SAL_CALL addSheetCache( const ::rtl::OUString& aSheetName ) 
++    virtual ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XExternalSheetCache >
++        SAL_CALL addSheetCache( const ::rtl::OUString& aSheetName )
 +            throw (::com::sun::star::uno::RuntimeException);
 +
++                            // XNameAccess
++    virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName )
++                                throw(::com::sun::star::container::NoSuchElementException,
++                                    ::com::sun::star::lang::WrappedTargetException,
++                                    ::com::sun::star::uno::RuntimeException);
++    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames()
++                                throw(::com::sun::star::uno::RuntimeException);
++    virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName )
++                                throw(::com::sun::star::uno::RuntimeException);
++
++                            // XIndexAccess
++    virtual sal_Int32 SAL_CALL getCount() throw(::com::sun::star::uno::RuntimeException);
++    virtual ::com::sun::star::uno::Any SAL_CALL getByIndex( sal_Int32 nIndex )
++                                throw(::com::sun::star::lang::IndexOutOfBoundsException,
++                                    ::com::sun::star::lang::WrappedTargetException,
++                                    ::com::sun::star::uno::RuntimeException);
++
++                            // XEnumerationAccess
++    virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XEnumeration > SAL_CALL
++                            createEnumeration() throw(::com::sun::star::uno::RuntimeException);
++
++                            // XElementAccess
++    virtual ::com::sun::star::uno::Type SAL_CALL getElementType()
++                                throw(::com::sun::star::uno::RuntimeException);
++    virtual sal_Bool SAL_CALL hasElements() throw(::com::sun::star::uno::RuntimeException);
++
 +    // Attributes
 +    virtual sal_Int32 SAL_CALL getTokenIndex()
 +            throw (::com::sun::star::uno::RuntimeException);
@@ -794,47 +944,41 @@
 +    ~ScExternalDocLinksObj();
 +
 +                            // XExternalDocLinks
-+    virtual ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XExternalDocLink > 
-+        SAL_CALL addDocLink( const ::rtl::OUString& aDocName ) 
++    virtual ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XExternalDocLink >
++        SAL_CALL addDocLink( const ::rtl::OUString& aDocName )
 +            throw (::com::sun::star::uno::RuntimeException);
- 
-+							// XNameAccess
-+	virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName )
-+								throw(::com::sun::star::container::NoSuchElementException,
-+									::com::sun::star::lang::WrappedTargetException,
-+									::com::sun::star::uno::RuntimeException);
-+	virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames()
-+								throw(::com::sun::star::uno::RuntimeException);
-+	virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName )
-+								throw(::com::sun::star::uno::RuntimeException);
-+
-+							// XIndexAccess
-+	virtual sal_Int32 SAL_CALL getCount() throw(::com::sun::star::uno::RuntimeException);
-+	virtual ::com::sun::star::uno::Any SAL_CALL getByIndex( sal_Int32 nIndex )
-+								throw(::com::sun::star::lang::IndexOutOfBoundsException,
-+									::com::sun::star::lang::WrappedTargetException,
-+									::com::sun::star::uno::RuntimeException);
-+
-+							// XEnumerationAccess
-+	virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XEnumeration > SAL_CALL
-+							createEnumeration() throw(::com::sun::star::uno::RuntimeException);
-+
-+							// XElementAccess
-+	virtual ::com::sun::star::uno::Type SAL_CALL getElementType()
-+								throw(::com::sun::star::uno::RuntimeException);
-+	virtual sal_Bool SAL_CALL hasElements() throw(::com::sun::star::uno::RuntimeException);
- 
++
++                            // XNameAccess
++    virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName )
++                                throw(::com::sun::star::container::NoSuchElementException,
++                                    ::com::sun::star::lang::WrappedTargetException,
++                                    ::com::sun::star::uno::RuntimeException);
++    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames()
++                                throw(::com::sun::star::uno::RuntimeException);
++    virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName )
++                                throw(::com::sun::star::uno::RuntimeException);
++
++                            // XIndexAccess
++    virtual sal_Int32 SAL_CALL getCount() throw(::com::sun::star::uno::RuntimeException);
++    virtual ::com::sun::star::uno::Any SAL_CALL getByIndex( sal_Int32 nIndex )
++                                throw(::com::sun::star::lang::IndexOutOfBoundsException,
++                                    ::com::sun::star::lang::WrappedTargetException,
++                                    ::com::sun::star::uno::RuntimeException);
++
++                            // XEnumerationAccess
++    virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XEnumeration > SAL_CALL
++                            createEnumeration() throw(::com::sun::star::uno::RuntimeException);
++
++                            // XElementAccess
++    virtual ::com::sun::star::uno::Type SAL_CALL getElementType()
++                                throw(::com::sun::star::uno::RuntimeException);
++    virtual sal_Bool SAL_CALL hasElements() throw(::com::sun::star::uno::RuntimeException);
++
 +private:
 +    ScExternalDocLinksObj();
 +    ScExternalDocLinksObj(const ScExternalDocLinksObj&);
 +
 +private:
-+    typedef ::std::hash_map< 
-+        ::rtl::OUString, 
-+        ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XExternalDocLink >, 
-+        ::rtl::OUStringHash > DocLinkMap;
-+    DocLinkMap                          maDocLinks;
-+    ::std::vector< ::rtl::OUString >    maDocNames;
 +    ScDocShell*                         mpDocShell;
 +    ScExternalRefManager*               mpRefMgr;
 +};
@@ -865,6 +1009,28 @@
  };
  
  inline void SingleRefData::InitAddress( SCCOL nColP, SCROW nRowP, SCTAB nTabP )
+diff --git sc/inc/scmatrix.hxx sc/inc/scmatrix.hxx
+index dbe8bc7..0f2fcb1 100644
+--- sc/inc/scmatrix.hxx
++++ sc/inc/scmatrix.hxx
+@@ -115,11 +115,14 @@ class ScMatrix
+ 
+ public:
+ 
+-    /// The maximum number of elements a matrix may have at runtime
++    /// The maximum number of elements a matrix may have at runtime.
+     inline static size_t GetElementsMax()
+     {
+-        const size_t nMemMax = (((size_t)(~0))-64) / sizeof(ScMatrixValue);
+-        const size_t nArbitraryLimit = 0x80000;  // 512k elements ~= 4MB memory
++        // Roughly 125MB in total, divided by 8+1 per element => 14M elements.
++        const size_t nMemMax = 0x08000000 / (sizeof(ScMatrixValue) + sizeof(ScMatValType));
++        // With MAXROWCOUNT==65536 and 128 columns => 8M elements ~72MB.
++        const size_t nArbitraryLimit = (size_t)MAXROWCOUNT * 128;
++        // Stuffed with a million rows would limit this to 14 columns.
+         return nMemMax < nArbitraryLimit ? nMemMax : nArbitraryLimit;
+     }
+ 
 diff --git sc/inc/token.hxx sc/inc/token.hxx
 index ded3a94..bc7e993 100644
 --- sc/inc/token.hxx
@@ -965,7 +1131,7 @@
      /** Xcl import may play dirty tricks with OpCode!=ocExternal.
          Others don't use! */
 diff --git sc/inc/tokenuno.hxx sc/inc/tokenuno.hxx
-index a03b6ec..5db0e32 100644
+index a03b6ec..f12b484 100644
 --- sc/inc/tokenuno.hxx
 +++ sc/inc/tokenuno.hxx
 @@ -38,9 +38,8 @@
@@ -979,7 +1145,19 @@
  #include <cppuhelper/implbase3.hxx>
  #include <cppuhelper/implbase2.hxx>
  #include "address.hxx"
-@@ -70,6 +69,7 @@ class ScFormulaParserObj : public ::cppu::WeakImplHelper3<
+@@ -54,9 +53,11 @@ class ScTokenConversion
+ {
+ public:
+     static bool ConvertToTokenArray(
++                        ScDocument& rDoc,
+                         ScTokenArray& rTokenArray,
+                         const com::sun::star::uno::Sequence< com::sun::star::sheet::FormulaToken >& rSequence );
+     static bool ConvertToTokenSequence(
++                        ScDocument& rDoc,
+                         com::sun::star::uno::Sequence< com::sun::star::sheet::FormulaToken >& rSequence,
+                         const ScTokenArray& rTokenArray );
+ };
+@@ -70,6 +71,7 @@ class ScFormulaParserObj : public ::cppu::WeakImplHelper3<
  {
  private:
      ::com::sun::star::uno::Sequence< const ::com::sun::star::sheet::FormulaOpCodeMapEntry > maOpCodeMapping;
@@ -988,7 +1166,7 @@
      ScDocShell*         mpDocShell;
      ScAddress           maRefPos;
 diff --git sc/inc/unonames.hxx sc/inc/unonames.hxx
-index b2c45ac..18c858b 100644
+index 8bc928b..3573c7d 100644
 --- sc/inc/unonames.hxx
 +++ sc/inc/unonames.hxx
 @@ -47,6 +47,7 @@
@@ -1025,8 +1203,38 @@
  			{
  				ScRangeData* pRangeData = pDoc->GetRangeName()->FindIndex( t->GetIndex() );
  				if( pRangeData )
+diff --git sc/source/core/data/cell2.cxx sc/source/core/data/cell2.cxx
+index fc6df5f..657ebb8 100644
+--- sc/source/core/data/cell2.cxx
++++ sc/source/core/data/cell2.cxx
+@@ -51,6 +51,7 @@
+ #include "indexmap.hxx"
+ #include "scitems.hxx"
+ #include "patattr.hxx"
++#include "externalrefmgr.hxx"
+ 
+ // STATIC DATA -----------------------------------------------------------
+ 
+@@ -904,6 +905,17 @@ void ScFormulaCell::UpdateReference(UpdateRefMode eUpdateRefMode,
+ 
+         delete pOld;
+     }
++
++    pCode->Reset();
++    for ( ScToken* t = pCode->GetNextReferenceOrName(); t; t = pCode->GetNextReferenceOrName() )
++    {
++        StackVar sv = t->GetType();
++        if (sv == svExternalSingleRef || sv == svExternalDoubleRef || sv == svExternalName)
++        {
++            pDocument->GetExternalRefManager()->updateRefCell(aOldPos, aPos, eUpdateRefMode == URM_COPY);
++            break;
++        }
++    }
+ }
+ 
+ void ScFormulaCell::UpdateInsertTab(SCTAB nTable)
 diff --git sc/source/core/data/documen2.cxx sc/source/core/data/documen2.cxx
-index b75279e..d739a17 100644
+index b75279e..825baf5 100644
 --- sc/source/core/data/documen2.cxx
 +++ sc/source/core/data/documen2.cxx
 @@ -94,6 +94,7 @@
@@ -1057,6 +1265,28 @@
  	ScAddInAsync::RemoveDocument( this );
  	ScAddInListener::RemoveDocument( this );
  	delete pChartListenerCollection;	// vor pBASM wg. evtl. Listener!
+@@ -1429,6 +1436,10 @@ BOOL ScDocument::MoveTab( SCTAB nOldPos, SCTAB nNewPos )
+ 				if (pDrawLayer)
+ 					DrawMovePage( static_cast<sal_uInt16>(nOldPos), static_cast<sal_uInt16>(nNewPos) );
+ 
++                // Update cells containing external references.
++                if (pExternalRefMgr.get())
++                    pExternalRefMgr->updateRefMoveTable(nOldPos, nNewPos, false);
++
+ 				bValid = TRUE;
+ 			}
+ 		}
+@@ -1548,6 +1559,10 @@ BOOL ScDocument::CopyTab( SCTAB nOldPos, SCTAB nNewPos, const ScMarkData* pOnlyM
+ 			DrawCopyPage( static_cast<sal_uInt16>(nOldPos), static_cast<sal_uInt16>(nNewPos) );
+ 
+ 		pTab[nNewPos]->SetPageStyle( pTab[nOldPos]->GetPageStyle() );
++
++        // Update cells containing external references.
++        if (pExternalRefMgr.get())
++            pExternalRefMgr->updateRefMoveTable(nOldPos, nNewPos, true);
+ 	}
+ 	else
+ 		SetAutoCalc( bOldAutoCalc );
 diff --git sc/source/core/data/documen3.cxx sc/source/core/data/documen3.cxx
 index 541e2e4..20dae1e 100644
 --- sc/source/core/data/documen3.cxx
@@ -1141,8 +1371,56 @@
  void ScDocument::UpdateDdeLinks()
  {
      if (pLinkManager)
+diff --git sc/source/core/data/document.cxx sc/source/core/data/document.cxx
+index 886156d..705c73b 100644
+--- sc/source/core/data/document.cxx
++++ sc/source/core/data/document.cxx
+@@ -91,6 +91,7 @@
+ #include "bcaslot.hxx"
+ #include "postit.hxx"
+ #include "tabprotection.hxx"
++#include "externalrefmgr.hxx"
+ 
+ struct ScDefaultAttr
+ {
+@@ -368,6 +369,10 @@ BOOL ScDocument::InsertTab( SCTAB nPos, const String& rName,
+ 				if ( pChartListenerCollection )
+ 					pChartListenerCollection->UpdateScheduledSeriesRanges();
+ 
++				// Update cells containing external references.
++				if (pExternalRefMgr.get())
++					pExternalRefMgr->updateRefInsertTable(nPos);
++
+ 				SetDirty();
+ 				bValid = TRUE;
+ 			}
+@@ -457,6 +462,12 @@ BOOL ScDocument::DeleteTab( SCTAB nTab, ScDocument* pRefUndoDoc )
+ 				}
+ 				// #81844# sheet names of references are not valid until sheet is deleted
+ 				pChartListenerCollection->UpdateScheduledSeriesRanges();
++
++
++                // Update cells containing external references.
++                if (pExternalRefMgr.get())
++                    pExternalRefMgr->updateRefDeleteTable(nTab);
++
+ 				SetAutoCalc( bOldAutoCalc );
+ 				bValid = TRUE;
+ 			}
+diff --git sc/source/core/inc/interpre.hxx sc/source/core/inc/interpre.hxx
+index b9dd766..2035004 100644
+--- sc/source/core/inc/interpre.hxx
++++ sc/source/core/inc/interpre.hxx
+@@ -505,6 +505,7 @@ BOOL SetSbxVariable( SbxVariable* pVar, SCCOL nCol, SCROW nRow, SCTAB nTab );
+ void ScErrorType();
+ void ScDBArea();
+ void ScColRowNameAuto();
++void ScExternalRef();
+ void ScGetPivotData();
+ void ScHyperLink();
+ void ScBahtText();
 diff --git sc/source/core/tool/address.cxx sc/source/core/tool/address.cxx
-index 2cb5dce..4572ccd 100644
+index df51606..5b68bbc 100644
 --- sc/source/core/tool/address.cxx
 +++ sc/source/core/tool/address.cxx
 @@ -35,12 +35,15 @@
@@ -1211,7 +1489,19 @@
  static long int
  sal_Unicode_strtol ( const sal_Unicode*  p,
                       const sal_Unicode** pEnd )
-@@ -102,31 +148,18 @@ sal_Unicode_strtol ( const sal_Unicode*  p,
+@@ -99,34 +145,30 @@ sal_Unicode_strtol ( const sal_Unicode*  p,
+     return is_neg ? -accum : accum;
+ }
+ 
++const sal_Unicode* lcl_eatWhiteSpace( const sal_Unicode* p )
++{
++    if ( p )
++    {
++        while(  *p == ' ' )
++            ++p;
++    }
++    return p;
++}
  // Returns NULL if the string should be a sheet name, but is invalid
  // Returns a pointer to the first character after the sheet name
  static const sal_Unicode *
@@ -1246,7 +1536,7 @@
              return NULL;
      }
      else
-@@ -190,26 +223,7 @@ lcl_XL_ParseSheetRef( const sal_Unicode *start,
+@@ -190,26 +232,7 @@ lcl_XL_ParseSheetRef( const sal_Unicode *start,
          aTabName.Append( start, sal::static_int_cast<xub_StrLen>( p - start ) );
      }
  
@@ -1274,7 +1564,7 @@
      return p;
  }
  
-@@ -220,46 +234,71 @@ lcl_ScRange_Parse_XL_Header( ScRange& r,
+@@ -220,46 +243,71 @@ lcl_ScRange_Parse_XL_Header( ScRange& r,
                               String& rExternDocName,
                               String& rStartTabName,
                               String& rEndTabName,
@@ -1283,7 +1573,7 @@
 +                             const uno::Sequence< const sheet::ExternalLinkInfo > * pExternalLinks )
  {
      const sal_Unicode* startTabs, *start = p;
- 
+     USHORT nSaveFlags = nFlags;
      // Is this an external reference ?
      rStartTabName.Erase();
      rEndTabName.Erase();
@@ -1366,16 +1656,30 @@
      if( NULL == p )
          return start;       // invalid tab
      if( p != startTabs )
-@@ -267,7 +306,7 @@ lcl_ScRange_Parse_XL_Header( ScRange& r,
+@@ -267,9 +315,12 @@ lcl_ScRange_Parse_XL_Header( ScRange& r,
          nFlags |= SCA_VALID_TAB | SCA_TAB_3D | SCA_TAB_ABSOLUTE;
          if( *p == ':' ) // 3d ref
          {
 -            p = lcl_XL_ParseSheetRef( p+1, &r.aEnd, pDoc, rExternDocName, rEndTabName, FALSE );
 +            p = lcl_XL_ParseSheetRef( p+1, rEndTabName, FALSE );
              if( p == NULL )
++            {
++                nFlags = nSaveFlags;    
                  return start; // invalid tab
++            }
              nFlags |= SCA_VALID_TAB2 | SCA_TAB2_3D | SCA_TAB2_ABSOLUTE;
-@@ -289,45 +328,36 @@ lcl_ScRange_Parse_XL_Header( ScRange& r,
+         }
+         else
+@@ -288,6 +339,8 @@ lcl_ScRange_Parse_XL_Header( ScRange& r,
+             nFlags = nSaveFlags;
+             return start;   // syntax error
+         }
++        else
++            p = lcl_eatWhiteSpace( p );
+     }
+     else
+     {
+@@ -295,45 +348,39 @@ lcl_ScRange_Parse_XL_Header( ScRange& r,
          // Use the current tab, it needs to be passed in. : r.aEnd.SetTab( .. );
      }
  
@@ -1399,7 +1703,10 @@
 -                                                   pDoc->GetDocumentShell() );
 +        // Internal reference.
 +        if (!rStartTabName.Len())
++        {
++            nFlags = nSaveFlags;
 +            return start;
++        }
  
 -        String aDocTab;
 -       
@@ -1444,7 +1751,7 @@
  }
  
  
-@@ -427,7 +457,8 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
+@@ -433,7 +480,8 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
                             const sal_Unicode* p,
                             ScDocument* pDoc,
                             const ScAddress::Details& rDetails,
@@ -1454,7 +1761,7 @@
  {
      const sal_Unicode* pTmp = NULL;
      String aExternDocName, aStartTabName, aEndTabName;
-@@ -441,7 +472,19 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
+@@ -447,7 +495,19 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
      }
  #endif
      p = lcl_ScRange_Parse_XL_Header( r, p, pDoc,
@@ -1475,7 +1782,7 @@
      if( NULL == p )
          return 0;
  
-@@ -480,8 +523,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
+@@ -486,8 +546,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
              r.aStart.SetCol( 0 );
              r.aEnd.SetCol( MAXCOL );
  
@@ -1485,7 +1792,7 @@
          }
          else if( NULL == (p = lcl_r1c1_get_col( p, rDetails, &r.aStart, &nFlags )))
              goto failed;
-@@ -501,8 +543,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
+@@ -507,8 +566,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
                  return nFlags;
              }
  
@@ -1495,7 +1802,7 @@
          }
          p = pTmp;
  
-@@ -517,8 +558,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
+@@ -523,8 +581,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
          }
  
          nFlags |= (nFlags2 << 4);
@@ -1505,7 +1812,7 @@
      }
      else if( *p == 'C' || *p == 'c' )   // full col C#
      {
-@@ -550,8 +590,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
+@@ -556,8 +613,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
          r.aStart.SetRow( 0 );
          r.aEnd.SetRow( MAXROW );
  
@@ -1515,7 +1822,7 @@
      }
  
  failed :
-@@ -604,7 +643,9 @@ static USHORT
+@@ -610,7 +666,9 @@ static USHORT
  lcl_ScRange_Parse_XL_A1( ScRange& r,
                           const sal_Unicode* p,
                           ScDocument* pDoc,
@@ -1526,7 +1833,7 @@
  {
      const sal_Unicode* tmp1, *tmp2;
      String aExternDocName, aStartTabName, aEndTabName; // for external link table
-@@ -618,7 +659,19 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
+@@ -629,7 +687,19 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
      }
  #endif
      p = lcl_ScRange_Parse_XL_Header( r, p, pDoc,
@@ -1547,7 +1854,20 @@
      if( NULL == p )
          return 0;
  
-@@ -640,8 +693,7 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
+@@ -640,8 +710,12 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
+             return 0;
+ 
+         tmp1 = lcl_a1_get_row( p, &r.aStart, &nFlags );
++        
++        tmp1 = lcl_eatWhiteSpace( tmp1 );
+         if( !tmp1 || *tmp1++ != ':' ) // Even a singleton requires ':' (eg 2:2)
+             return 0;
++
++        tmp1 = lcl_eatWhiteSpace( tmp1 );
+         tmp2 = lcl_a1_get_row( tmp1, &r.aEnd, &nFlags2 );
+         if( !tmp2 )
+             return 0;
+@@ -651,8 +725,7 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
              SCA_VALID_COL | SCA_VALID_COL2 |
              SCA_COL_ABSOLUTE | SCA_COL2_ABSOLUTE;
          nFlags |= (nFlags2 << 4);
@@ -1557,7 +1877,19 @@
      }
  
      tmp2 = lcl_a1_get_row( tmp1, &r.aStart, &nFlags );
-@@ -661,8 +713,7 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
+@@ -661,8 +734,11 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
+         if( bOnlyAcceptSingle ) // by definition full col refs are ranges
+             return 0;
+ 
++        tmp1 = lcl_eatWhiteSpace( tmp1 );
+         if( *tmp1++ != ':' )    // Even a singleton requires ':' (eg F:F)
+             return 0;
++
++        tmp1 = lcl_eatWhiteSpace( tmp1 );
+         tmp2 = lcl_a1_get_col( tmp1, &r.aEnd, &nFlags2 );
+         if( !tmp2 )
+             return 0;
+@@ -672,8 +748,7 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
              SCA_VALID_ROW | SCA_VALID_ROW2 |
              SCA_ROW_ABSOLUTE | SCA_ROW2_ABSOLUTE;
          nFlags |= (nFlags2 << 4);
@@ -1567,7 +1899,7 @@
      }
  
      // prepare as if it's a singleton, in case we want to fall back */
-@@ -672,8 +723,7 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
+@@ -683,8 +758,7 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
      if ( bOnlyAcceptSingle )
      {
          if ( *tmp2 == 0 )
@@ -1577,9 +1909,21 @@
          else
          {
              // any trailing invalid character must invalidate the address.
-@@ -692,12 +742,11 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
+@@ -693,6 +767,7 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
+         }
+     }
+ 
++    tmp2 = lcl_eatWhiteSpace( tmp2 );
+     if( *tmp2 != ':' )
+     {
+         nFlags &= ~(SCA_VALID | SCA_VALID_COL | SCA_VALID_ROW | SCA_VALID_TAB |
+@@ -701,14 +776,14 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
+     }
+ 
      p = tmp2;
-     tmp1 = lcl_a1_get_col( p+1, &r.aEnd, &nFlags2 );
+-    tmp1 = lcl_a1_get_col( p+1, &r.aEnd, &nFlags2 );
++    p = lcl_eatWhiteSpace( p+1 );
++    tmp1 = lcl_a1_get_col( p, &r.aEnd, &nFlags2 );
      if( !tmp1 ) // strange, but valid singleton
 -        return lcl_XL_LinkSheetRef( r, pDoc,
 -            aExternDocName, aStartTabName, aEndTabName, nFlags );
@@ -1593,7 +1937,7 @@
  
      if ( *tmp2 != 0 )
      {
-@@ -708,45 +757,31 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
+@@ -719,45 +794,31 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
      }
  
      nFlags |= (nFlags2 << 4);
@@ -1652,7 +1996,7 @@
      }
  
      SCCOL   nCol = 0;
-@@ -762,25 +797,11 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
+@@ -773,25 +834,11 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
          if (*p == '$')
              nRes |= SCA_TAB_ABSOLUTE, p++;
  
@@ -1683,7 +2027,7 @@
  
          while (*p)
          {
-@@ -795,35 +816,11 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
+@@ -806,35 +853,11 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
          }
          if( *p++ != '.' )
              nBits = 0;
@@ -1723,7 +2067,7 @@
          }
          else
              nBits = 0;
-@@ -884,16 +881,31 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
+@@ -895,16 +918,31 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
          if( !nBits )
              p = q;
      }
@@ -1761,7 +2105,7 @@
      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 +924,10 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
+@@ -923,9 +961,10 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
  }
  
  static USHORT
@@ -1775,7 +2119,7 @@
  {
      if( !*p )
          return 0;
-@@ -924,20 +937,22 @@ lcl_ScAddress_Parse ( BOOL& bExternal, const sal_Unicode* p,
+@@ -935,20 +974,22 @@ lcl_ScAddress_Parse ( BOOL& bExternal, const sal_Unicode* p,
      default :
      case ScAddress::CONV_OOO:
          {
@@ -1801,7 +2145,7 @@
              rAddr = r.aStart;
              return nFlags;
          }
-@@ -949,9 +964,8 @@ bool ConvertSingleRef( ScDocument* pDoc, const String& rRefString,
+@@ -960,9 +1001,8 @@ bool ConvertSingleRef( ScDocument* pDoc, const String& rRefString,
                         SCTAB nDefTab, ScRefAddress& rRefAddress,
                         const ScAddress::Details& rDetails )
  {
@@ -1812,7 +2156,7 @@
      if( nRes & SCA_VALID )
      {
          rRefAddress.Set( aAddr,
-@@ -988,10 +1002,11 @@ bool ConvertDoubleRef( ScDocument* pDoc, const String& rRefString, SCTAB nDefTab
+@@ -999,10 +1039,11 @@ bool ConvertDoubleRef( ScDocument* pDoc, const String& rRefString, SCTAB nDefTab
  
  
  USHORT ScAddress::Parse( const String& r, ScDocument* pDoc,
@@ -1827,7 +2171,7 @@
  }
  
  
-@@ -1060,7 +1075,7 @@ void ScRange::ExtendTo( const ScRange& rRange )
+@@ -1071,7 +1112,7 @@ void ScRange::ExtendTo( const ScRange& rRange )
  }
  
  static USHORT
@@ -1836,7 +2180,7 @@
  {
      USHORT nRes1 = 0, nRes2 = 0;
      xub_StrLen nTmp = 0;
-@@ -1073,13 +1088,12 @@ lcl_ScRange_Parse_OOo( ScRange &aRange, const String& r, ScDocument* pDoc )
+@@ -1084,13 +1125,12 @@ lcl_ScRange_Parse_OOo( ScRange &aRange, const String& r, ScDocument* pDoc )
          String aTmp( r );
          sal_Unicode* p = aTmp.GetBufferAccess();
          p[ nPos ] = 0;
@@ -1853,7 +2197,7 @@
                      nRes2 &= ~SCA_VALID_TAB;    // #REF!
                  else
                  {
-@@ -1132,7 +1146,9 @@ lcl_ScRange_Parse_OOo( ScRange &aRange, const String& r, ScDocument* pDoc )
+@@ -1143,7 +1183,9 @@ lcl_ScRange_Parse_OOo( ScRange &aRange, const String& r, ScDocument* pDoc )
  }
  
  USHORT ScRange::Parse( const String& r, ScDocument* pDoc,
@@ -1864,7 +2208,7 @@
  {
      if ( r.Len() <= 0 )
          return 0;
-@@ -1141,13 +1157,15 @@ USHORT ScRange::Parse( const String& r, ScDocument* pDoc,
+@@ -1152,13 +1194,15 @@ USHORT ScRange::Parse( const String& r, ScDocument* pDoc,
      {
      default :
      case ScAddress::CONV_OOO:
@@ -1883,7 +2227,7 @@
      }
  }
  
-@@ -1187,6 +1205,7 @@ USHORT ScRange::ParseCols( const String& rStr, ScDocument* pDoc,
+@@ -1198,6 +1242,7 @@ USHORT ScRange::ParseCols( const String& rStr, ScDocument* pDoc,
      default :
      case ScAddress::CONV_OOO: // No full col refs in OOO yet, assume XL notation
      case ScAddress::CONV_XL_A1:
@@ -1891,7 +2235,7 @@
          if (NULL != (p = lcl_a1_get_col( p, &aStart, &ignored ) ) )
          {
              if( p[0] == ':')
-@@ -1245,6 +1264,7 @@ USHORT ScRange::ParseRows( const String& rStr, ScDocument* pDoc,
+@@ -1256,6 +1301,7 @@ USHORT ScRange::ParseRows( const String& rStr, ScDocument* pDoc,
      default :
      case ScAddress::CONV_OOO: // No full row refs in OOO yet, assume XL notation
      case ScAddress::CONV_XL_A1:
@@ -1899,7 +2243,7 @@
          if (NULL != (p = lcl_a1_get_row( p, &aStart, &ignored ) ) )
          {
              if( p[0] == ':')
-@@ -1429,6 +1449,7 @@ void ScAddress::Format( String& r, USHORT nFlags, ScDocument* pDoc,
+@@ -1440,6 +1486,7 @@ void ScAddress::Format( String& r, USHORT nFlags, ScDocument* pDoc,
  
              case CONV_XL_A1:
              case CONV_XL_R1C1:
@@ -1907,7 +2251,7 @@
                  if (aDocName.Len() > 0)
                  {
                      r += '[';
-@@ -1446,6 +1467,7 @@ void ScAddress::Format( String& r, USHORT nFlags, ScDocument* pDoc,
+@@ -1457,6 +1504,7 @@ void ScAddress::Format( String& r, USHORT nFlags, ScDocument* pDoc,
      default :
      case CONV_OOO:
      case CONV_XL_A1:
@@ -1915,7 +2259,7 @@
          if( nFlags & SCA_VALID_COL )
              lcl_a1_append_c ( r, nCol, nFlags & SCA_COL_ABSOLUTE );
          if( nFlags & SCA_VALID_ROW )
-@@ -1565,6 +1587,7 @@ void ScRange::Format( String& r, USHORT nFlags, ScDocument* pDoc,
+@@ -1576,6 +1624,7 @@ void ScRange::Format( String& r, USHORT nFlags, ScDocument* pDoc,
      break;
  
      case ScAddress::CONV_XL_A1:
@@ -1923,7 +2267,7 @@
          lcl_ScRange_Format_XL_Header( r, *this, nFlags, pDoc, rDetails );
          if( aStart.Col() == 0 && aEnd.Col() >= MAXCOL )
          {
-@@ -1688,6 +1711,7 @@ String ScAddress::GetColRowString( bool bAbsolute,
+@@ -1699,6 +1748,7 @@ String ScAddress::GetColRowString( bool bAbsolute,
      default :
      case ScAddress::CONV_OOO:
      case ScAddress::CONV_XL_A1:
@@ -1932,7 +2276,7 @@
          aString.Append( '$' );
  
 diff --git sc/source/core/tool/compiler.cxx sc/source/core/tool/compiler.cxx
-index 918332d..0910e72 100644
+index ae6adef..f815af9 100644
 --- sc/source/core/tool/compiler.cxx
 +++ sc/source/core/tool/compiler.cxx
 @@ -74,9 +74,11 @@
@@ -1984,15 +2328,15 @@
  }
  
  // static
-@@ -737,10 +734,28 @@ void ScCompiler::SetFormulaLanguage( const ScCompiler::OpCodeMapPtr & xMap )
+@@ -737,7 +734,25 @@ void ScCompiler::SetFormulaLanguage( const ScCompiler::OpCodeMapPtr & xMap )
          }
          else
              pCharClass = ScGlobal::pCharClass;
 +        SetGrammarAndRefConvention( mxSymbols->getGrammar(), GetGrammar());
-     }
- }
- 
- 
++    }
++}
++
++
 +void ScCompiler::SetGrammarAndRefConvention(
 +        const ScGrammar::Grammar eNewGrammar, const ScGrammar::Grammar eOldGrammar )
 +{
@@ -2004,16 +2348,13 @@
 +            SetRefConvention( pDoc->GetAddressConvention());
 +        else
 +            SetRefConvention( pConvOOO_A1);
-+    }
+     }
 +    else
 +        SetRefConvention( eConv );
-+}
-+
-+
- //-----------------------------------------------------------------------------
+ }
  
- void ScCompiler::OpCodeMap::putOpCode( const String & rStr, const OpCode eOp )
-@@ -866,20 +881,21 @@ ScCompiler::OpCodeMap::createSequenceOfAvailableMappings( const sal_Int32 nGroup
+ 
+@@ -866,20 +881,19 @@ ScCompiler::OpCodeMap::createSequenceOfAvailableMappings( const sal_Int32 nGroup
              sal_Int32 nOff;
              OpCode    eOp;
          } aMap[] = {
@@ -2031,25 +2372,23 @@
 -            { FormulaMapGroupSpecialOffset::MACRO             , ocMacro }          ,
 -            { FormulaMapGroupSpecialOffset::COL_ROW_NAME      , ocColRowName }     ,
 -            { FormulaMapGroupSpecialOffset::COL_ROW_NAME_AUTO , ocColRowNameAuto }
-+            { FormulaMapGroupSpecialOffset::PUSH               , ocPush }           , 
-+            { FormulaMapGroupSpecialOffset::CALL               , ocCall }           , 
-+            { FormulaMapGroupSpecialOffset::STOP               , ocStop }           , 
-+            { FormulaMapGroupSpecialOffset::EXTERNAL           , ocExternal }       , 
-+            { FormulaMapGroupSpecialOffset::NAME               , ocName }           , 
-+            { FormulaMapGroupSpecialOffset::NO_NAME            , ocNoName }         , 
-+            { FormulaMapGroupSpecialOffset::MISSING            , ocMissing }        , 
-+            { FormulaMapGroupSpecialOffset::BAD                , ocBad }            , 
-+            { FormulaMapGroupSpecialOffset::SPACES             , ocSpaces }         , 
-+            { FormulaMapGroupSpecialOffset::MAT_REF            , ocMatRef }         , 
-+            { FormulaMapGroupSpecialOffset::DB_AREA            , ocDBArea }         , 
-+            { FormulaMapGroupSpecialOffset::MACRO              , ocMacro }          , 
-+            { FormulaMapGroupSpecialOffset::COL_ROW_NAME       , ocColRowName }     , 
-+            { FormulaMapGroupSpecialOffset::COL_ROW_NAME_AUTO  , ocColRowNameAuto } , 
-+            { FormulaMapGroupSpecialOffset::EXTERNAL_REFERENCE , ocExternalRef }
++            { FormulaMapGroupSpecialOffset::PUSH               , ocPush }           ,
++            { FormulaMapGroupSpecialOffset::CALL               , ocCall }           ,
++            { FormulaMapGroupSpecialOffset::STOP               , ocStop }           ,
++            { FormulaMapGroupSpecialOffset::EXTERNAL           , ocExternal }       ,
++            { FormulaMapGroupSpecialOffset::NAME               , ocName }           ,
++            { FormulaMapGroupSpecialOffset::NO_NAME            , ocNoName }         ,
++            { FormulaMapGroupSpecialOffset::MISSING            , ocMissing }        ,
++            { FormulaMapGroupSpecialOffset::BAD                , ocBad }            ,
++            { FormulaMapGroupSpecialOffset::SPACES             , ocSpaces }         ,
++            { FormulaMapGroupSpecialOffset::MAT_REF            , ocMatRef }         ,
++            { FormulaMapGroupSpecialOffset::DB_AREA            , ocDBArea }         ,
++            { FormulaMapGroupSpecialOffset::MACRO              , ocMacro }          ,
++            { FormulaMapGroupSpecialOffset::COL_ROW_NAME       , ocColRowName }
          };
          const size_t nCount = sizeof(aMap)/sizeof(aMap[0]);
          // Preallocate vector elements.
-@@ -1078,7 +1094,7 @@ ScCompiler::Convention::Convention( ScAddress::Convention eConv )
+@@ -1078,7 +1092,7 @@ ScCompiler::Convention::Convention( ScAddress::Convention eConv )
  /*   */     t[32] = SC_COMPILER_C_CHAR_DONTCARE | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
  /* ! */     t[33] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
      if (ScAddress::CONV_ODF == meConv)
@@ -2058,7 +2397,7 @@
  /* " */     t[34] = SC_COMPILER_C_CHAR_STRING | SC_COMPILER_C_STRING_SEP;
  /* # */     t[35] = SC_COMPILER_C_WORD_SEP;
  /* $ */     t[36] = SC_COMPILER_C_CHAR_WORD | SC_COMPILER_C_WORD | SC_COMPILER_C_CHAR_IDENT | SC_COMPILER_C_IDENT;
-@@ -1093,8 +1109,10 @@ ScCompiler::Convention::Convention( ScAddress::Convention eConv )
+@@ -1093,8 +1107,10 @@ ScCompiler::Convention::Convention( ScAddress::Convention eConv )
  /* - */     t[45] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_EXP | SC_COMPILER_C_VALUE_SIGN;
  /* . */     t[46] = SC_COMPILER_C_WORD | SC_COMPILER_C_CHAR_VALUE | SC_COMPILER_C_VALUE | SC_COMPILER_C_IDENT;
  /* / */     t[47] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
@@ -2070,7 +2409,7 @@
  /* : */     t[58] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD;
  /* ; */     t[59] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
  /* < */     t[60] = SC_COMPILER_C_CHAR_BOOL | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
-@@ -1102,8 +1120,10 @@ for (i = 48; i < 58; i++)
+@@ -1102,8 +1118,10 @@ for (i = 48; i < 58; i++)
  /* > */     t[62] = SC_COMPILER_C_CHAR_BOOL | SC_COMPILER_C_BOOL | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
  /* ? */     t[63] = SC_COMPILER_C_CHAR_WORD | SC_COMPILER_C_WORD;
  /* @ */     // FREE
@@ -2082,7 +2421,7 @@
      if (ScAddress::CONV_ODF == meConv)
      {
  /* [ */     t[91] = SC_COMPILER_C_ODF_LBRACKET;
-@@ -1119,14 +1139,17 @@ for (i = 65; i < 91; i++)
+@@ -1119,14 +1137,17 @@ for (i = 65; i < 91; i++)
  /* ^ */     t[94] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
  /* _ */     t[95] = SC_COMPILER_C_CHAR_WORD | SC_COMPILER_C_WORD | SC_COMPILER_C_CHAR_IDENT | SC_COMPILER_C_IDENT;
  /* ` */     // FREE
@@ -2102,7 +2441,7 @@
      {
  /*   */     t[32] |=   SC_COMPILER_C_WORD;
  /* ! */     t[33] |=   SC_COMPILER_C_IDENT | SC_COMPILER_C_WORD;
-@@ -1165,9 +1188,14 @@ for (i = 97; i < 123; i++)
+@@ -1165,9 +1186,14 @@ for (i = 97; i < 123; i++)
  
          if( ScAddress::CONV_XL_R1C1 == meConv )
          {
@@ -2120,7 +2459,7 @@
          }
      }
  }
-@@ -1191,7 +1219,7 @@ static bool lcl_isValidQuotedText( const String& rFormula, xub_StrLen nSrcPos, P
+@@ -1191,7 +1217,7 @@ static bool lcl_isValidQuotedText( const String& rFormula, xub_StrLen nSrcPos, P
                  {
                      rRes.TokenType = KParseType::SINGLE_QUOTE_NAME;
                      rRes.EndPos = nPos+1;
@@ -2129,7 +2468,7 @@
                  }
                  ++nPos;
              }
-@@ -1199,9 +1227,203 @@ static bool lcl_isValidQuotedText( const String& rFormula, xub_StrLen nSrcPos, P
+@@ -1199,9 +1225,203 @@ static bool lcl_isValidQuotedText( const String& rFormula, xub_StrLen nSrcPos, P
          }
      }
  
@@ -2163,7 +2502,7 @@
 +                    if (c == '\'')
 +                    {
 +                        if (j == i)
-+                        {    
++                        {
 +                            // empty quote e.g. (=''!Name)
 +                            return false;
 +                        }
@@ -2196,13 +2535,13 @@
 +                }
 +
 +                if (!bInName)
-+                {    
++                {
 +                    // premature ending of the quoted segment.
 +                    return false;
 +                }
 +
 +                if (c != cSep)
-+                {    
++                {
 +                    // only the separator is allowed after the closing quote.
 +                    return false;
 +                }
@@ -2269,9 +2608,9 @@
 +
 +    rFile = aTmpFile;
 +    rName = aTmpName;
-+    return true;
-+}
-+
+     return true;
+ }
+ 
 +static String lcl_makeExternalNameStr( const String& rFile, const String& rName,
 +        const sal_Unicode cSep, bool bODF )
 +{
@@ -2290,7 +2629,7 @@
 +    return String( aBuf.makeStringAndClear());
 +}
 +
-+static bool lcl_getLastTabName( String& rTabName2, const String& rTabName1, 
++static bool lcl_getLastTabName( String& rTabName2, const String& rTabName1,
 +                                const vector<String>& rTabNames, const ComplRefData& rRef )
 +{
 +    SCsTAB nTabSpan = rRef.Ref2.nTab - rRef.Ref1.nTab;
@@ -2302,7 +2641,7 @@
 +        if (itr == rTabNames.end())
 +        {
 +            rTabName2 = ScGlobal::GetRscString(STR_NO_REF_TABLE);
-+            return false;    
++            return false;
 +        }
 +
 +        size_t nDist = ::std::distance(itrBeg, itr);
@@ -2317,9 +2656,9 @@
 +    else
 +        rTabName2 = rTabName1;
 +
-     return true;
- }
- 
++    return true;
++}
++
 +static void lcl_appendTabName(::rtl::OUStringBuffer& rBuffer, const String& rTabName)
 +{
 +    bool bQuote = (rTabName.Search(sal_Unicode(' '), 0) != STRING_NOTFOUND);
@@ -2333,7 +2672,7 @@
  struct Convention_A1 : public ScCompiler::Convention
  {
      Convention_A1( ScAddress::Convention eConv ) : ScCompiler::Convention( eConv ) { }
-@@ -1215,14 +1437,14 @@ struct Convention_A1 : public ScCompiler::Convention
+@@ -1215,14 +1435,14 @@ struct Convention_A1 : public ScCompiler::Convention
                                 const CharClass* pCharClass) const
      {
          ParseResult aRet;
@@ -2350,7 +2689,7 @@
          return pCharClass->parseAnyToken( rFormula,
                  nSrcPos, nStartFlags, aAddAllowed, nContFlags, aAddAllowed );
      }
-@@ -1405,6 +1627,114 @@ struct ConventionOOO_A1 : public Convention_A1
+@@ -1405,6 +1625,121 @@ struct ConventionOOO_A1 : public Convention_A1
  
          return sal_Unicode(0);
      }
@@ -2365,8 +2704,8 @@
 +        return lcl_makeExternalNameStr( rFile, rName, sal_Unicode('#'), false);
 +    }
 +
-+    bool makeExternalSingleRefStr( ::rtl::OUStringBuffer& rBuffer, sal_uInt16 nFileId, 
-+                                   const String& rTabName, const SingleRefData& rRef, 
++    bool makeExternalSingleRefStr( ::rtl::OUStringBuffer& rBuffer, sal_uInt16 nFileId,
++                                   const String& rTabName, const SingleRefData& rRef,
 +                                   ScExternalRefManager* pRefMgr, bool bDisplayTabName ) const
 +    {
 +        if (bDisplayTabName)
@@ -2376,12 +2715,12 @@
 +            if (p)
 +                aFile = *p;
 +            aFile.SearchAndReplaceAllAscii("'", String::CreateFromAscii("''"));
-+    
++
 +            rBuffer.append(sal_Unicode('\''));
 +            rBuffer.append(aFile);
 +            rBuffer.append(sal_Unicode('\''));
 +            rBuffer.append(sal_Unicode('#'));
-+    
++
 +            // external reference is always 3D and the sheet is absolute.
 +            rBuffer.append(sal_Unicode('$'));
 +            lcl_appendTabName(rBuffer, rTabName);
@@ -2400,7 +2739,7 @@
 +    }
 +
 +    void makeExternalRefStrImpl( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
-+                                     sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef, 
++                                     sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef,
 +                                     ScExternalRefManager* pRefMgr, bool bODF ) const
 +    {
 +        SingleRefData aRef(rRef);
@@ -2414,14 +2753,14 @@
 +    }
 +
 +    virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
-+                                     sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef, 
++                                     sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef,
 +                                     ScExternalRefManager* pRefMgr ) const
 +    {
 +        makeExternalRefStrImpl( rBuffer, rCompiler, nFileId, rTabName, rRef, pRefMgr, false);
 +    }
 +
 +    void makeExternalRefStrImpl( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
-+                                     sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef, 
++                                     sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef,
 +                                     ScExternalRefManager* pRefMgr, bool bODF ) const
 +    {
 +        ComplRefData aRef(rRef);
@@ -2441,23 +2780,30 @@
 +            vector<String> aTabNames;
 +            pRefMgr->getAllCachedTableNames(nFileId, aTabNames);
 +            if (aTabNames.empty())
++            {
++                DBG_ERROR1( "ConventionOOO_A1::makeExternalRefStrImpl: no sheet names for document ID %s", nFileId);
 +                break;
++            }
 +
 +            String aLastTabName;
 +            if (!lcl_getLastTabName(aLastTabName, rTabName, aTabNames, aRef))
 +            {
 +                rBuffer.append(aLastTabName);
++                DBG_ERROR( "ConventionOOO_A1::makeExternalRefStrImpl: sheet name not found");
 +                break;
 +            }
++            bool bDisplayTabName = (aRef.Ref1.nTab != aRef.Ref2.nTab);
++            if (bODF && !bDisplayTabName)
++                rBuffer.append( sal_Unicode('.'));      // need at least the sheet separator in ODF
 +            makeExternalSingleRefStr( rBuffer, nFileId, aLastTabName,
-+                    aRef.Ref2, pRefMgr, (aRef.Ref1.nTab != aRef.Ref2.nTab));
++                    aRef.Ref2, pRefMgr, bDisplayTabName);
 +        } while (0);
 +        if (bODF)
 +            rBuffer.append( sal_Unicode(']'));
 +    }
 +
 +    virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
-+                                     sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef, 
++                                     sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef,
 +                                     ScExternalRefManager* pRefMgr ) const
 +    {
 +        makeExternalRefStrImpl( rBuffer, rCompiler, nFileId, rTabName, rRef, pRefMgr, false);
@@ -2465,7 +2811,7 @@
  };
  
  
-@@ -1423,6 +1753,25 @@ struct ConventionOOO_A1_ODF : public ConventionOOO_A1
+@@ -1423,6 +1758,25 @@ struct ConventionOOO_A1_ODF : public ConventionOOO_A1
      {
          MakeRefStrImpl( rBuffer, rComp, rRef, bSingleRef, true);
      }
@@ -2476,14 +2822,14 @@
 +    }
 +
 +    virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
-+                                     sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef, 
++                                     sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef,
 +                                     ScExternalRefManager* pRefMgr ) const
 +    {
 +        makeExternalRefStrImpl( rBuffer, rCompiler, nFileId, rTabName, rRef, pRefMgr, true);
 +    }
 +
 +    virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
-+                                     sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef, 
++                                     sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef,
 +                                     ScExternalRefManager* pRefMgr ) const
 +    {
 +        makeExternalRefStrImpl( rBuffer, rCompiler, nFileId, rTabName, rRef, pRefMgr, true);
@@ -2491,7 +2837,7 @@
  };
  
  static const ConventionOOO_A1_ODF ConvOOO_A1_ODF;
-@@ -1526,11 +1875,129 @@ struct ConventionXL
+@@ -1526,11 +1880,129 @@ struct ConventionXL
          }
          return sal_Unicode(0);
      }
@@ -2508,11 +2854,11 @@
 +
 +    static void makeExternalDocStr( ::rtl::OUStringBuffer& rBuffer, const String& rFullName )
 +    {
-+        // Format that is easier to deal with inside OOo, because we use file 
++        // Format that is easier to deal with inside OOo, because we use file
 +        // URL, and all characetrs are allowed.  Check if it makes sense to do
 +        // it the way Gnumeric does it.  Gnumeric doesn't use the URL form
 +        // and allows relative file path.
-+        // 
++        //
 +        //   ['file:///path/to/source/filename.xls']
 +
 +        rBuffer.append(sal_Unicode('['));
@@ -2530,14 +2876,14 @@
 +        rBuffer.append(sal_Unicode(']'));
 +    }
 +
-+    static void makeExternalTabNameRange( ::rtl::OUStringBuffer& rBuf, const String& rTabName, 
++    static void makeExternalTabNameRange( ::rtl::OUStringBuffer& rBuf, const String& rTabName,
 +                                          const vector<String>& rTabNames,
 +                                          const ComplRefData& rRef )
 +    {
 +        String aLastTabName;
 +        if (!lcl_getLastTabName(aLastTabName, rTabName, rTabNames, rRef))
 +        {
-+            rBuf.append(aLastTabName);   
++            rBuf.append(aLastTabName);
 +            return;
 +        }
 +
@@ -2572,7 +2918,7 @@
 +            else if (c == '\'')
 +            {
 +                if (cPrev == '\'')
-+                    // two successive single quote is treated as a single 
++                    // two successive single quote is treated as a single
 +                    // valid character.
 +                    c = 'a';
 +            }
@@ -2594,7 +2940,7 @@
 +            {
 +                // any other character
 +                if (i > rSrcPos + 2 && cPrev == '\'')
-+                    // unless it's the 3rd character, a normal character 
++                    // unless it's the 3rd character, a normal character
 +                    // following immediately a single quote is invalid.
 +                    return;
 +            }
@@ -2621,7 +2967,7 @@
      void MakeRefStr( rtl::OUStringBuffer&   rBuf,
                       const ScCompiler&      rComp,
                       const ComplRefData& rRef,
-@@ -1584,22 +2051,11 @@ struct ConventionXL_A1 : public Convention_A1, public ConventionXL
+@@ -1584,22 +2056,11 @@ struct ConventionXL_A1 : public Convention_A1, public ConventionXL
              }
          }
  
@@ -2646,7 +2992,7 @@
          }
      }
  
-@@ -1607,8 +2063,10 @@ struct ConventionXL_A1 : public Convention_A1, public ConventionXL
+@@ -1607,8 +2068,10 @@ struct ConventionXL_A1 : public Convention_A1, public ConventionXL
                                         xub_StrLen nSrcPos,
                                         const CharClass* pCharClass) const
      {
@@ -2658,7 +3004,7 @@
              return aRet;
  
          static const sal_Int32 nStartFlags = KParseTokens::ANY_LETTER_OR_NUMBER |
-@@ -1624,11 +2082,83 @@ struct ConventionXL_A1 : public Convention_A1, public ConventionXL
+@@ -1624,11 +2087,83 @@ struct ConventionXL_A1 : public Convention_A1, public ConventionXL
      {
          return ConventionXL::getSpecialSymbol(eSymType);
      }
@@ -2674,13 +3020,13 @@
 +    }
 +
 +    virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
-+                                     sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef, 
++                                     sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef,
 +                                     ScExternalRefManager* pRefMgr ) const
 +    {
 +        // ['file:///path/to/file/filename.xls']'Sheet Name'!$A$1
 +        // This is a little different from the format Excel uses, as Excel
 +        // puts [] only around the file name.  But we need to enclose the
-+        // whole file path with [] because the file name can contain any 
++        // whole file path with [] because the file name can contain any
 +        // characters.
 +
 +        const String* pFullName = pRefMgr->getExternalFileName(nFileId);
@@ -2698,7 +3044,7 @@
 +    }
 +
 +    virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
-+                                     sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef, 
++                                     sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef,
 +                                     ScExternalRefManager* pRefMgr ) const
 +    {
 +        const String* pFullName = pRefMgr->getExternalFileName(nFileId);
@@ -2742,7 +3088,7 @@
  //-----------------------------------------------------------------------------
  
  static void
-@@ -1733,8 +2263,10 @@ struct ConventionXL_R1C1 : public ScCompiler::Convention, public ConventionXL
+@@ -1733,8 +2268,10 @@ struct ConventionXL_R1C1 : public ScCompiler::Convention, public ConventionXL
                                 xub_StrLen nSrcPos,
                                 const CharClass* pCharClass) const
      {
@@ -2754,7 +3100,7 @@
              return aRet;
  
          static const sal_Int32 nStartFlags = KParseTokens::ANY_LETTER_OR_NUMBER |
-@@ -1751,6 +2283,96 @@ struct ConventionXL_R1C1 : public ScCompiler::Convention, public ConventionXL
+@@ -1751,6 +2288,96 @@ struct ConventionXL_R1C1 : public ScCompiler::Convention, public ConventionXL
      {
          return ConventionXL::getSpecialSymbol(eSymType);
      }
@@ -2770,13 +3116,13 @@
 +    }
 +
 +    virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
-+                                     sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef, 
++                                     sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef,
 +                                     ScExternalRefManager* pRefMgr ) const
 +    {
 +        // ['file:///path/to/file/filename.xls']'Sheet Name'!$A$1
 +        // This is a little different from the format Excel uses, as Excel
 +        // puts [] only around the file name.  But we need to enclose the
-+        // whole file path with [] because the file name can contain any 
++        // whole file path with [] because the file name can contain any
 +        // characters.
 +
 +        const String* pFullName = pRefMgr->getExternalFileName(nFileId);
@@ -2795,7 +3141,7 @@
 +    }
 +
 +    virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
-+                                     sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef, 
++                                     sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef,
 +                                     ScExternalRefManager* pRefMgr ) const
 +    {
 +        const String* pFullName = pRefMgr->getExternalFileName(nFileId);
@@ -2851,7 +3197,7 @@
  };
  
  static const ConventionXL_R1C1 ConvXL_R1C1;
-@@ -1817,13 +2439,15 @@ void ScCompiler::CheckTabQuotes( String& rString,
+@@ -1817,13 +2444,15 @@ void ScCompiler::CheckTabQuotes( String& rString,
          KParseType::IDENTNAME, rString, 0, nStartFlags, EMPTY_STRING, nContFlags, EMPTY_STRING);
      bool bNeedsQuote = !((aRes.TokenType & KParseType::IDENTNAME) && aRes.EndPos == rString.Len());
  
@@ -2868,7 +3214,7 @@
              if( bNeedsQuote )
              {
                  static const String one_quote = static_cast<sal_Unicode>( '\'' );
-@@ -1859,6 +2483,7 @@ void ScCompiler::SetRefConvention( ScAddress::Convention eConv )
+@@ -1859,6 +2488,7 @@ void ScCompiler::SetRefConvention( ScAddress::Convention eConv )
          case ScAddress::CONV_ODF :      SetRefConvention( pConvOOO_A1_ODF ); break;
          case ScAddress::CONV_XL_A1 :    SetRefConvention( pConvXL_A1 );  break;
          case ScAddress::CONV_XL_R1C1 :  SetRefConvention( pConvXL_R1C1 ); break;
@@ -2876,35 +3222,162 @@
      }
  }
  
-@@ -2208,7 +2833,7 @@ xub_StrLen ScCompiler::NextSymbol(bool bInArray)
-                     static const int kQuote = kInc * 2;
-                     static const int kPast = kInc * 3;
+@@ -2191,71 +2821,88 @@ Label_MaskStateMachine:
+                 }
+                 // fall through and follow logic
+             case ssSkipReference:
+-                // ODF reference: [$'Sheet'.A1:.B2] with dots being mandatory
+-                // also if no sheet name.
+-                //
+-                // nRefInSheetName: 0     := not in sheet name yet.
+-                //                    +1  := encountered leading '$'
+-                //                    +2  := encountered opening ''', which
+-                //                           may be after $ or not.
+-                //                  4(+ ) := somewhere in sheet name.
+-                //                  8(+ ) := encountered ''' in sheet name,
+-                //                           will be decremented (-4) again if
+-                //                           double or incremented (+4) again
+-                //                           if not.
+-                //                 12(+ ) := past closing ''' or no sheet name
+-                //                           and past leading '.'
++                // ODF reference: ['External'#$'Sheet'.A1:.B2] with dots being
++                // mandatory also if no sheet name. 'External'# is optional,
++                // sheet name is optional, quotes around sheet name are
++                // optional if no quote contained.
+                 {
+-                    // kOpen can be used in bit tests in this arrangement
+-                    static const int kDollar = 1;
+-                    static const int kOpen = 2;
+-                    static const int kInc = 4;
+-                    static const int kSheet = kInc * 1;
+-                    static const int kQuote = kInc * 2;
+-                    static const int kPast = kInc * 3;
++
++                    // nRefInSheetName: 0 := not in sheet name yet. 'External'
++                    // is parsed as if it was a sheet name and nRefInSheetName
++                    // is reset when # is encountered immediately after closing
++                    // quote.
++
++                    // Encountered leading $.
++                    static const int kDollar = (1 << 1);
++                    // Encountered ' opening quote, which may be after $ or
++                    // not.
++                    static const int kOpen   = (1 << 2);
++                    // Somewhere in sheet name.
++                    static const int kSheet  = (1 << 3);
++                    // Encountered ' in sheet name, will be cleared if double
++                    // or transformed to kClose if not, in which case kOpen is
++                    // cleared.
++                    static const int kQuote  = (1 << 4);
++                    // Past ' closing quote.
++                    static const int kClose  = (1 << 5);
++                    // Past . sheet name separator.
++                    static const int kPast   = (1 << 6);
++
                      bool bAddToSymbol = true;
 -                    if ('.' == c && nRefInSheetName == 0)
 +                    if (cSheetSep == c && nRefInSheetName == 0)
                      {
-                         // eat it, no sheet name
+-                        // eat it, no sheet name
++                        // eat it, no sheet name [.A1]
                          bAddToSymbol = false;
-@@ -2223,7 +2848,7 @@ xub_StrLen ScCompiler::NextSymbol(bool bInArray)
+-                        nRefInSheetName = kPast;
++                        nRefInSheetName |= kPast;
                      }
-                     else if (nRefInSheetName < kPast)
+-                    else if (':' == c && nRefInSheetName < kSheet)
++                    else if (!(nRefInSheetName & kPast))
                      {
+-                        DBG_ERRORFILE("ScCompiler::NextSymbol: reference:"
+-                                "range operator ':' without prior sheet name separator '.' violates ODF spec");
+-                        nRefInSheetName = 0;
+-                        ++mnPredetectedReference;
+-                    }
+-                    else if (nRefInSheetName < kPast)
+-                    {
 -                        if ('$' == c && nRefInSheetName < kDollar)
-+                        if (cSheetPrefix == c && nRefInSheetName < kDollar)
-                             nRefInSheetName += kDollar;
+-                            nRefInSheetName += kDollar;
++                        if (nMask & SC_COMPILER_C_ODF_RBRACKET &&
++                                !(nRefInSheetName & kOpen))
++                        {
++                            DBG_ERRORFILE("ScCompiler::NextSymbol: reference: "
++                                    "closing bracket ']' without prior sheet name separator '.' violates ODF spec");
++                            // eaten, not added to pSym
++                            bAddToSymbol = false;
++                            eState = ssStop;
++                        }
++                        else if (cSheetPrefix == c && nRefInSheetName == 0)
++                            nRefInSheetName |= kDollar;
                          else if ('\'' == c)
                          {
-@@ -2545,7 +3170,8 @@ BOOL ScCompiler::IsDoubleReference( const String& rName )
- {
-     ScRange aRange( aPos, aPos );
-     const ScAddress::Details aDetails( pConv->meConv, aPos );
--    USHORT nFlags = aRange.Parse( rName, pDoc, aDetails );
-+    ScAddress::ExternalInfo aExtInfo;
-+    USHORT nFlags = aRange.Parse( rName, pDoc, aDetails, &aExtInfo, &maExternalLinks );
+-                            if (nRefInSheetName < kSheet)
+-                                nRefInSheetName += kOpen + kSheet;
++                            if (!(nRefInSheetName & kSheet))
++                                nRefInSheetName |= (kOpen | kSheet);
+                             else if (!(nRefInSheetName & kOpen))
+                             {
+-                                DBG_ERRORFILE("ScCompiler::NextSymbol: reference:"
++                                DBG_ERRORFILE("ScCompiler::NextSymbol: reference: "
+                                         "a ''' without the sheet name being enclosed in '...' violates ODF spec");
+                             }
+-                            else if (nRefInSheetName >= kQuote)
++                            else if (nRefInSheetName & kQuote)
+                                 // escaped embedded quote
+-                                nRefInSheetName -= kInc;
++                                nRefInSheetName &= ~kQuote;
+                             else
+                                 // a quote in (or after) sheet name
+-                                nRefInSheetName += kInc;
++                                nRefInSheetName |= kQuote;
+                         }
+-                        else if ('.' == c && !(nRefInSheetName & kOpen))
++                        else if (cSheetSep == c && !(nRefInSheetName & kOpen))
+                             // unquoted sheet name separator
+-                            nRefInSheetName += kPast;
+-                        else if (nRefInSheetName < kSheet)
++                            nRefInSheetName |= kPast;
++                        else if (':' == c && !(nRefInSheetName & kOpen))
++                        {
++                            DBG_ERRORFILE("ScCompiler::NextSymbol: reference: "
++                                    "range operator ':' without prior sheet name separator '.' violates ODF spec");
++                            nRefInSheetName = 0;
++                            ++mnPredetectedReference;
++                        }
++                        else if (!(nRefInSheetName & kSheet))
+                             // start unquoted sheet name
+-                            nRefInSheetName += kSheet;
+-                        else if (nRefInSheetName >= kQuote)
+-                            // quote not followed by quote => past
+-                            nRefInSheetName += kInc;
++                            nRefInSheetName |= kSheet;
++                        else if (nRefInSheetName & kQuote)
++                        {
++                            // quote not followed by quote => close
++                            nRefInSheetName |= kClose;
++                            nRefInSheetName &= ~kOpen;
++                        }
+                     }
+                     else if (':' == c)
+                     {
+@@ -2270,7 +2917,7 @@ Label_MaskStateMachine:
+                         eState = ssStop;
+                     }
+                     if (bAddToSymbol && eState != ssSkipReference)
+-                        *pSym++ = c;    // everything is part of sheet reference
++                        *pSym++ = c;    // everything is part of reference
+                 }
+                 break;
+             case ssStop:
+@@ -2551,7 +3198,8 @@ BOOL ScCompiler::IsDoubleReference( const String& rName )
+ {
+     ScRange aRange( aPos, aPos );
+     const ScAddress::Details aDetails( pConv->meConv, aPos );
+-    USHORT nFlags = aRange.Parse( rName, pDoc, aDetails );
++    ScAddress::ExternalInfo aExtInfo;
++    USHORT nFlags = aRange.Parse( rName, pDoc, aDetails, &aExtInfo, &maExternalLinks );
      if( nFlags & SCA_VALID )
      {
          ScRawToken aToken;
-@@ -2564,7 +3190,17 @@ BOOL ScCompiler::IsDoubleReference( const String& rName )
+@@ -2570,7 +3218,17 @@ BOOL ScCompiler::IsDoubleReference( const String& rName )
              aRef.Ref2.SetTabDeleted( TRUE );        // #REF!
          aRef.Ref2.SetFlag3D( ( nFlags & SCA_TAB2_3D ) != 0 );
          aRef.CalcRelFromAbs( aPos );
@@ -2923,7 +3396,7 @@
          pRawToken = aToken.Clone();
      }
  
-@@ -2576,7 +3212,8 @@ BOOL ScCompiler::IsSingleReference( const String& rName )
+@@ -2582,7 +3240,8 @@ BOOL ScCompiler::IsSingleReference( const String& rName )
  {
      ScAddress aAddr( aPos );
      const ScAddress::Details aDetails( pConv->meConv, aPos );
@@ -2933,7 +3406,7 @@
      // Something must be valid in order to recognize Sheet1.blah or blah.a1
      // as a (wrong) reference.
      if( nFlags & ( SCA_VALID_COL|SCA_VALID_ROW|SCA_VALID_TAB ) )
-@@ -2600,7 +3237,16 @@ BOOL ScCompiler::IsSingleReference( const String& rName )
+@@ -2606,7 +3265,16 @@ BOOL ScCompiler::IsSingleReference( const String& rName )
              nFlags |= SCA_VALID;
          }
          aRef.CalcRelFromAbs( aPos );
@@ -2951,7 +3424,7 @@
          pRawToken = aToken.Clone();
      }
  
-@@ -2708,6 +3354,32 @@ BOOL ScCompiler::IsNamedRange( const String& rUpperName )
+@@ -2714,6 +3382,32 @@ BOOL ScCompiler::IsNamedRange( const String& rUpperName )
          return FALSE;
  }
  
@@ -2984,7 +3457,7 @@
  BOOL ScCompiler::IsDBRange( const String& rName )
  {
      USHORT n;
-@@ -3243,7 +3915,7 @@ BOOL ScCompiler::NextNewToken( bool bInArray )
+@@ -3249,7 +3943,7 @@ BOOL ScCompiler::NextNewToken( bool bInArray )
          if (mnPredetectedReference)
          {
              String aStr( cSymbol);
@@ -2993,7 +3466,7 @@
              {
                  /* TODO: it would be nice to generate a #REF! error here, which
                   * would need an ocBad token with additional error value.
-@@ -3306,6 +3978,7 @@ BOOL ScCompiler::NextNewToken( bool bInArray )
+@@ -3312,6 +4006,7 @@ BOOL ScCompiler::NextNewToken( bool bInArray )
                && !(bAllowBooleans && IsBoolean( aUpper ))
                && !IsValue( aUpper )
                && !IsNamedRange( aUpper )
@@ -3001,7 +3474,7 @@
                && !IsDBRange( aUpper )
                && !IsColRowName( aUpper )
                && !(bMayBeFuncName && IsMacro( aUpper ))
-@@ -3628,9 +4301,9 @@ BOOL ScCompiler::GetToken()
+@@ -3634,9 +4329,9 @@ BOOL ScCompiler::GetToken()
          else
          {
              if ( nWasColRowName >= 2 && pToken->GetOpCode() == ocColRowName )
@@ -3013,86 +3486,58 @@
              }
          }
      }
-@@ -3641,6 +4314,78 @@ BOOL ScCompiler::GetToken()
+@@ -3647,6 +4342,50 @@ BOOL ScCompiler::GetToken()
      }
      if( pToken->GetOpCode() == ocSubTotal )
          glSubTotal = TRUE;
 +    else if ( pToken->GetOpCode() == ocExternalRef )
 +    {
-+        // Handle external single and double references, or names.
-+
-+        ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
-+        const String* pFile = pRefMgr->getExternalFileName(pToken->GetIndex());
-+        if (!pFile)
-+            SetError(errNoName);
-+
++        // Handle external range names.
 +        switch (pToken->GetType())
 +        {
-+            case svExternalName:
-+            {
-+                const String& rName = pToken->GetString();
-+                ScExternalRefCache::TokenArrayRef xNew = pRefMgr->getRangeNameTokens(pToken->GetIndex(), rName, &aPos);
-+                if (xNew.get())
-+                {
-+                    ScTokenArray* pNew = xNew->Clone();
-+                    PushTokenArray(pNew, true);
-+                    pNew->Reset();
-+                    return GetToken();
-+                }
-+            }
-+            break;
 +            case svExternalSingleRef:
++            case svExternalDoubleRef:
++                pArr->nRefs++;
++            break;
++            case svExternalName:
 +            {
-+                SingleRefData aData(pToken->GetSingleRef());
-+                if (aData.IsTabRel())
-+                {
-+                    DBG_ERROR("ScCompiler::GetToken: external single reference must have an absolute table reference!")
-+                    break;
++                ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
++                const String* pFile = pRefMgr->getExternalFileName(pToken->GetIndex());
++                if (!pFile)
++                {    
++                    SetError(errNoName);
++                    return true;
 +                }
 +
-+                aData.CalcAbsIfRel(aPos);
-+                ScAddress aAddr(aData.nCol, aData.nRow, aData.nTab);
-+                ScExternalRefCache::TokenRef xNew = pRefMgr->getSingleRefToken(pToken->GetIndex(), pToken->GetString(), aAddr, &aPos, NULL);
-+                if (xNew.get())
-+                {
-+                    pToken = xNew->Clone();
++                const String& rName = pToken->GetString();
++                ScExternalRefCache::TokenArrayRef xNew = pRefMgr->getRangeNameTokens(
++                    pToken->GetIndex(), rName, &aPos);
++
++                if (!xNew)
++                {    
++                    SetError(errNoName);
 +                    return true;
 +                }
-+            }
-+            break;
-+            case svExternalDoubleRef:
-+            {
-+                ComplRefData aData(pToken->GetDoubleRef());
-+                if (aData.Ref1.IsTabRel() || aData.Ref2.IsTabRel())
-+                {
-+                    DBG_ERROR("ScCompiler::GetToken: external double reference must have an absolute table reference!")
-+                    break;
-+                }
 +
-+                aData.CalcAbsIfRel(aPos);
-+                ScRange aRange(aData.Ref1.nCol, aData.Ref1.nRow, aData.Ref1.nTab, 
-+                               aData.Ref2.nCol, aData.Ref2.nRow, aData.Ref2.nTab);
-+                ScExternalRefCache::TokenArrayRef xNew = pRefMgr->getDoubleRefTokens(pToken->GetIndex(), pToken->GetString(), aRange, &aPos);
-+                if (xNew.get())
++                ScTokenArray* pNew = xNew->Clone();
++                PushTokenArray( pNew, true);
++                if (pNew->GetNextReference() != NULL)
 +                {
-+                    ScTokenArray* pNew = xNew->Clone();
-+                    PushTokenArray(pNew, true);
-+                    pNew->Reset();
-+                    return GetToken();
++                    SetRelNameReference();
++                    MoveRelWrap();
 +                }
++                pNew->Reset();
++                return GetToken();
 +            }
 +            break;
 +            default:
-+            {
 +                DBG_ERROR1( "ScCompiler::GetToken: unhandled ocExternalRef type %d", pToken->GetType());
-+            }
 +        }
-+        SetError(errNoName);
 +    }
      else if( pToken->GetOpCode() == ocName )
      {
          ScRangeData* pRangeData = pDoc->GetRangeName()->FindIndex( pToken->GetIndex() );
-@@ -3796,7 +4541,7 @@ BOOL ScCompiler::GetToken()
+@@ -3802,7 +4541,7 @@ BOOL ScCompiler::GetToken()
                      {   // next defined RowNameRange to the right limits column
                          const ScRange& rRange = pR->GetRange(1);
                          if ( rRange.aStart.Row() <= nRow && nRow <= rRange.aEnd.Row() )
@@ -3101,7 +3546,46 @@
                              SCCOL nTmp = rRange.aStart.Col();
                              if ( nStartCol < nTmp && nTmp <= nMaxCol )
                                  nMaxCol = nTmp - 1;
-@@ -5638,111 +6383,144 @@ ScToken* ScCompiler::CreateStringFromToken( rtl::OUStringBuffer& rBuffer, ScToke
+@@ -4426,6 +5165,11 @@ void ScCompiler::Factor()
+                 bCorrected = TRUE;
+             }
+         }
++        else if ( eOp == ocExternalRef )
++        {
++            PutCode(pToken);
++            eOp = NextToken();
++        }
+         else
+         {
+             SetError( errUnknownToken );
+@@ -4707,7 +5451,7 @@ void ScCompiler::MoveRelWrap()
+     for( ScToken* t = pArr->GetNextReference(); t;
+                   t = pArr->GetNextReference() )
+     {
+-        if ( t->GetType() == svSingleRef )
++        if ( t->GetType() == svSingleRef || t->GetType() == svExternalSingleRef )
+             ScRefUpdate::MoveRelWrap( pDoc, aPos, SingleDoubleRefModifier( t->GetSingleRef() ).Ref() );
+         else
+             ScRefUpdate::MoveRelWrap( pDoc, aPos, t->GetDoubleRef() );
+@@ -4724,7 +5468,7 @@ void ScCompiler::MoveRelWrap( ScTokenArray& rArr, ScDocument* pDoc,
+     for( ScToken* t = rArr.GetNextReference(); t;
+                   t = rArr.GetNextReference() )
+     {
+-        if ( t->GetType() == svSingleRef )
++        if ( t->GetType() == svSingleRef || t->GetType() == svExternalSingleRef )
+             ScRefUpdate::MoveRelWrap( pDoc, rPos, SingleDoubleRefModifier( t->GetSingleRef() ).Ref() );
+         else
+             ScRefUpdate::MoveRelWrap( pDoc, rPos, t->GetDoubleRef() );
+@@ -4836,7 +5580,7 @@ ScRangeData* ScCompiler::UpdateReference(UpdateRefMode eUpdateRefMode,
+             else if( t->GetType() != svIndex )  // it may be a DB area!!!
+             {
+                 t->CalcAbsIfRel( rOldPos );
+-                if ( t->GetType() == svSingleRef )
++                if ( t->GetType() == svSingleRef || t->GetType() == svExternalSingleRef )
+                 {
+                     if ( ScRefUpdate::Update( pDoc, eUpdateRefMode, aPos,
+                             r, nDx, nDy, nDz,
+@@ -5641,111 +6385,144 @@ ScToken* ScCompiler::CreateStringFromToken( rtl::OUStringBuffer& rBuffer, ScToke
          DBG_ERRORFILE("unknown OpCode");
          rBuffer.append(ScGlobal::GetRscString(STR_NO_NAME_REF));
      }
@@ -3332,8 +3816,111 @@
      if( bSpaces )
          rBuffer.append(sal_Unicode(' '));
      if ( bAllowArrAdvance )
+diff --git sc/source/core/tool/interpr4.cxx sc/source/core/tool/interpr4.cxx
+index 5f6faa3..b5f9856 100644
+--- sc/source/core/tool/interpr4.cxx
++++ sc/source/core/tool/interpr4.cxx
+@@ -74,6 +74,7 @@
+ #include "addinlis.hxx"
+ #include "jumpmatrix.hxx"
+ #include "parclass.hxx"
++#include "externalrefmgr.hxx"
+ 
+ using namespace com::sun::star;
+ 
+@@ -2980,6 +2981,82 @@ void ScInterpreter::ScColRowNameAuto()
+         PushError( errNoRef );
+ }
+ 
++void ScInterpreter::ScExternalRef()
++{
++    ScExternalRefManager* pRefMgr = pDok->GetExternalRefManager();
++    const String* pFile = pRefMgr->getExternalFileName(pCur->GetIndex());
++    if (!pFile)
++        PushError(errNoName);
++
++    switch (pCur->GetType())
++    {
++        case svExternalSingleRef:
++        {
++            SingleRefData aData(pCur->GetSingleRef());
++            if (aData.IsTabRel())
++            {
++                DBG_ERROR("ScCompiler::GetToken: external single reference must have an absolute table reference!");
++                break;
++            }
++
++            aData.CalcAbsIfRel(aPos);
++            ScAddress aAddr(aData.nCol, aData.nRow, aData.nTab);
++            ScExternalRefCache::CellFormat aFmt;
++            ScExternalRefCache::TokenRef xNew = pRefMgr->getSingleRefToken(
++                pCur->GetIndex(), pCur->GetString(), aAddr, &aPos, NULL, &aFmt);
++
++            if (!xNew)
++                break;
++
++            PushTempToken( *xNew);      // push a clone
++
++            if (aFmt.mbIsSet)
++            {
++                nFuncFmtType = aFmt.mnType;
++                nFuncFmtIndex = aFmt.mnIndex;
++            }
++            return;
++        }
++        break;
++        case svExternalDoubleRef:
++        {
++            ComplRefData aData(pCur->GetDoubleRef());
++            if (aData.Ref1.IsTabRel() || aData.Ref2.IsTabRel())
++            {
++                DBG_ERROR("ScCompiler::GetToken: external double reference must have an absolute table reference!");
++                break;
++            }
++
++            aData.CalcAbsIfRel(aPos);
++            ScRange aRange(aData.Ref1.nCol, aData.Ref1.nRow, aData.Ref1.nTab,
++                           aData.Ref2.nCol, aData.Ref2.nRow, aData.Ref2.nTab);
++            ScExternalRefCache::TokenArrayRef xNew = pRefMgr->getDoubleRefTokens(
++                pCur->GetIndex(), pCur->GetString(), aRange, &aPos);
++
++            if (!xNew)
++                break;
++
++            ScToken* p = xNew->First();
++            if (p->GetType() != svMatrix)
++                break;
++
++            if (xNew->Next())
++            {
++                // Can't handle more than one matrix per parameter.
++                SetError( errIllegalArgument);
++                break;
++            }
++
++            PushMatrix(p->GetMatrix());
++            return;
++        }
++        break;
++        default:
++            ;
++    }
++    PushError(errNoRef);
++}
++
+ // --- internals ------------------------------------------------------------
+ 
+ 
+@@ -3412,6 +3489,7 @@ StackVar ScInterpreter::Interpret()
+                 case ocDBArea           : ScDBArea();                   break;
+                 case ocColRowNameAuto   : ScColRowNameAuto();           break;
+ // separated    case ocPush             : Push( (ScToken&) *pCur );     break;
++                case ocExternalRef      : ScExternalRef();              break;
+                 case ocIf               : ScIfJump();                   break;
+                 case ocChose            : ScChoseJump();                break;
+                 case ocAdd              : ScAdd();                      break;
 diff --git sc/source/core/tool/refdata.cxx sc/source/core/tool/refdata.cxx
-index 4ac1814..7ec74d8 100644
+index 0d98f15..3a32461 100644
 --- sc/source/core/tool/refdata.cxx
 +++ sc/source/core/tool/refdata.cxx
 @@ -200,6 +200,10 @@ BOOL SingleRefData::operator==( const SingleRefData& r ) const
@@ -3348,7 +3935,7 @@
  static void lcl_putInOrder( SingleRefData & rRef1, SingleRefData & rRef2 )
  {
 diff --git sc/source/core/tool/token.cxx sc/source/core/tool/token.cxx
-index a20cbd5..87f45c3 100644
+index a20cbd5..e7aa461 100644
 --- sc/source/core/tool/token.cxx
 +++ sc/source/core/tool/token.cxx
 @@ -54,6 +54,8 @@
@@ -3360,7 +3947,7 @@
  // ImpTokenIterator wird je Interpreter angelegt, mehrfache auch durch
  // SubCode via ScTokenIterator Push/Pop moeglich
  IMPL_FIXEDMEMPOOL_NEWDEL( ImpTokenIterator, 32, 16 )
-@@ -209,6 +211,48 @@ void ScRawToken::SetName( USHORT n )
+@@ -193,6 +195,48 @@ void ScRawToken::SetDouble(double rVal)
      nRefCnt = 0;
  }
  
@@ -3406,9 +3993,9 @@
 +    extname.cName[n] = 0;
 +}
 +
- ComplRefData& ScRawToken::GetReference()
+ void ScRawToken::SetInt(int rVal)
  {
-     DBG_ASSERT( lcl_IsReference( eOp, GetType() ), "GetReference: no Ref" );
+     eOp   = ocPush;
 @@ -260,22 +304,34 @@ ScRawToken* ScRawToken::Clone() const
          static USHORT nOffset = lcl_ScRawTokenOffset();     // offset of sbyte
          USHORT n = nOffset;
@@ -3885,7 +4472,25 @@
  
  short* ScJumpToken::GetJump() const                     { return pJump; }
  BOOL ScJumpToken::operator==( const ScToken& r ) const
-@@ -1242,6 +1514,9 @@ ScToken* ScTokenArray::GetNextReferenceOrName()
+@@ -1193,6 +1465,8 @@ ScToken* ScTokenArray::GetNextReference()
+         {
+             case svSingleRef:
+             case svDoubleRef:
++            case svExternalSingleRef:
++            case svExternalDoubleRef:
+                 return t;
+             default:
+             {
+@@ -1223,6 +1497,8 @@ ScToken* ScTokenArray::GetNextReferenceRPN()
+         {
+             case svSingleRef:
+             case svDoubleRef:
++            case svExternalSingleRef:
++            case svExternalDoubleRef:
+                 return t;
+             default:
+             {
+@@ -1242,6 +1518,9 @@ ScToken* ScTokenArray::GetNextReferenceOrName()
              case svSingleRef:
              case svDoubleRef:
              case svIndex:
@@ -3895,7 +4500,7 @@
                  return t;
              default:
              {
-@@ -1785,10 +2060,11 @@ ScToken* ScTokenArray::MergeRangeReference( const ScAddress & rPos )
+@@ -1785,10 +2064,11 @@ ScToken* ScTokenArray::MergeRangeReference( const ScAddress & rPos )
      if (!pCode || !nLen)
          return NULL;
      USHORT nIdx = nLen;
@@ -3911,7 +4516,7 @@
      {
          ScTokenRef p = ScToken::ExtendRangeReference( *p1, *p3, rPos, true);
          if (p)
-@@ -1893,6 +2169,21 @@ ScToken* ScTokenArray::AddMatrix( ScMatrix* p )
+@@ -1893,6 +2173,21 @@ ScToken* ScTokenArray::AddMatrix( ScMatrix* p )
      return Add( new ScMatrixToken( p ) );
  }
  
@@ -3960,7 +4565,7 @@
  {
      DBG_ASSERT_BIFF( GetBiff() == EXC_BIFF5 );
 diff --git sc/source/filter/excel/excform8.cxx sc/source/filter/excel/excform8.cxx
-index ebf8543..e0467a0 100644
+index ebf8543..0af6d65 100644
 --- sc/source/filter/excel/excform8.cxx
 +++ sc/source/filter/excel/excform8.cxx
 @@ -41,6 +41,18 @@
@@ -4027,7 +4632,7 @@
 -                            aStack << aPool.Store( ocNoName, pExtName->GetName() );
 -                            GetTracer().TraceFormulaExtName();
 +                            sal_uInt16 nFileId;
-+                            if (!GetExternalFileIdFromXti(nXtiIndex, nFileId))
++                            if (!GetExternalFileIdFromXti(nXtiIndex, nFileId) || !pExtName->HasFormulaTokens())
 +                            {
 +                                aStack << aPool.Store(ocNoName, pExtName->GetName());
 +                                break;
@@ -4245,7 +4850,7 @@
  			}
  				break;
  			default: bError = TRUE;
-@@ -1143,7 +1206,130 @@ ConvErr ExcelToSc8::Convert( _ScRangeListTabs& rRangeList, XclImpStream& aIn, sa
+@@ -1143,7 +1206,152 @@ ConvErr ExcelToSc8::Convert( _ScRangeListTabs& rRangeList, XclImpStream& aIn, sa
  	return eRet;
  }
  
@@ -4287,7 +4892,7 @@
 +        // #98524# always reset flags
 +        aSRD.InitFlags();
 +        aCRD.InitFlags();
-+
+ 
 +        switch( nOp )
 +        {
 +            case 0x1C: // Error Value
@@ -4328,7 +4933,7 @@
 +                ExcRelToScRel8(nRow, nGrbitCol, aSRD, true);
 +                aCRD.Ref1 = aCRD.Ref2 = aSRD;
 +                String aTabName = rTabNames[nExtTab1];
- 
++
 +                if (nExtTab1 == nExtTab2)
 +                {
 +                    // single cell reference
@@ -4342,6 +4947,28 @@
 +                }
 +            }
 +            break;
++            case 0x3B:
++            {
++                // area reference 
++                sal_uInt16 nExtTab1, nExtTab2, nRow1, nRow2, nGrbitCol1, nGrbitCol2;
++                rStrm >> nExtTab1 >> nExtTab2 >> nRow1 >> nRow2 >> nGrbitCol1 >> nGrbitCol2;
++                SingleRefData& rR1 = aCRD.Ref1;
++                SingleRefData& rR2 = aCRD.Ref2;
++
++                rR1.nTab = nExtTab1;
++                rR1.SetFlag3D(true);
++                rR1.SetTabRel(false);
++                ExcRelToScRel8(nRow1, nGrbitCol1, rR1, true);
++
++                rR2.nTab = nExtTab2;
++                rR2.SetFlag3D(true);
++                rR2.SetTabRel(false);
++                ExcRelToScRel8(nRow2, nGrbitCol2, rR2, true);
++
++                String aTabName = rTabNames[nExtTab1];
++                aStack << aPool.StoreExtRef(nFileId, aTabName, aCRD);
++            }
++            break;
 +            default: 
 +                bError = true;
 +        }
@@ -4377,7 +5004,7 @@
  void ExcelToSc8::ExcRelToScRel8( UINT16 nRow, UINT16 nC, SingleRefData &rSRD, const BOOL bName )
  {
 diff --git sc/source/filter/excel/read.cxx sc/source/filter/excel/read.cxx
-index 2cc592c..7f1c44b 100644
+index eea6293..a868e17 100644
 --- sc/source/filter/excel/read.cxx
 +++ sc/source/filter/excel/read.cxx
 @@ -967,7 +967,7 @@ FltError ImportExcel8::Read( void )
@@ -4533,7 +5160,7 @@
  
  
 diff --git sc/source/filter/excel/xeformula.cxx sc/source/filter/excel/xeformula.cxx
-index 3db8da7..6488f69 100644
+index 3db8da7..dd46fd7 100644
 --- sc/source/filter/excel/xeformula.cxx
 +++ sc/source/filter/excel/xeformula.cxx
 @@ -42,6 +42,11 @@
@@ -4614,7 +5241,7 @@
 +    USHORT nFileId = rTokData.mpScToken->GetIndex();
 +    switch (eType)
 +    {
-+        case svSingleRef:
++        case svExternalSingleRef:
 +        {
 +            if (!mpScBasePos)
 +            {
@@ -4650,7 +5277,7 @@
 +            AppendAddress(aXclPos);
 +        }
 +        break;
-+        case svDoubleRef:
++        case svExternalDoubleRef:
 +        {
 +            if (!mpScBasePos)
 +            {
@@ -4768,7 +5395,7 @@
  
  SCTAB XclExpFmlaCompImpl::GetScTab( const SingleRefData& rRefData ) const
 diff --git sc/source/filter/excel/xelink.cxx sc/source/filter/excel/xelink.cxx
-index b1bacad..d929e21 100644
+index b1bacad..b46e813 100644
 --- sc/source/filter/excel/xelink.cxx
 +++ sc/source/filter/excel/xelink.cxx
 @@ -38,6 +38,14 @@
@@ -4914,7 +5541,7 @@
      virtual sal_uInt16  FindExtSheet( sal_Unicode cCode ) = 0;
  
 +    virtual void FindExtSheet( sal_uInt16 nFileId, const String& rTabName, sal_uInt16 nXclTabSpan,
-+                               sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab, 
++                               sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
 +                               XclExpRefLogEntry* pRefLogEntry ) = 0;
 +
      /** Derived classes store all cells in the given range in a CRN record list. */
@@ -4942,7 +5569,7 @@
      virtual sal_uInt16  FindExtSheet( sal_Unicode cCode );
  
 +    virtual void FindExtSheet( sal_uInt16 nFileId, const String& rTabName, sal_uInt16 nXclTabSpan,
-+                               sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab, 
++                               sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
 +                               XclExpRefLogEntry* pRefLogEntry );
 +
      virtual void        StoreCellRange( const SingleRefData& rRef1, const SingleRefData& rRef2 );
@@ -4970,7 +5597,7 @@
      virtual sal_uInt16  FindExtSheet( sal_Unicode cCode );
  
 +    virtual void FindExtSheet( sal_uInt16 nFileId, const String& rTabName, sal_uInt16 nXclTabSpan,
-+                               sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab, 
++                               sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
 +                               XclExpRefLogEntry* pRefLogEntry );
 +
      virtual void        StoreCellRange( const SingleRefData& rRef1, const SingleRefData& rRef2 );
@@ -5009,7 +5636,7 @@
 +
 +void XclExpExtName::WriteAddData( XclExpStream& rStrm )
 +{
-+    // Write only if it only has a single token that is either a cell or cell 
++    // Write only if it only has a single token that is either a cell or cell
 +    // range address.  Excel just writes '02 00 1C 17' for all the other types
 +    // of external names.
 +
@@ -5032,8 +5659,8 @@
 +
 +                bool bColRel = rRef.IsColRel();
 +                bool bRowRel = rRef.IsRowRel();
-+                sal_uInt16 nCol = bColRel ? rRef.nRelCol : rRef.nCol;
-+                sal_uInt16 nRow = bRowRel ? rRef.nRelRow : rRef.nRow;
++                sal_uInt16 nCol = static_cast< sal_uInt16 >( bColRel ? rRef.nRelCol : rRef.nCol );
++                sal_uInt16 nRow = static_cast< sal_uInt16 >( bRowRel ? rRef.nRelRow : rRef.nRow );
 +                if (bColRel) nCol |= 0x4000;
 +                if (bRowRel) nCol |= 0x8000;
 +
@@ -5063,10 +5690,10 @@
 +                bool bCol2Rel = r2.IsColRel();
 +                bool bRow2Rel = r2.IsRowRel();
 +
-+                sal_uInt16 nCol1 = bCol1Rel ? r1.nRelCol : r1.nCol;
-+                sal_uInt16 nCol2 = bCol2Rel ? r2.nRelCol : r2.nCol;
-+                sal_uInt16 nRow1 = bRow1Rel ? r1.nRelRow : r1.nRow;
-+                sal_uInt16 nRow2 = bRow2Rel ? r2.nRelRow : r2.nRow;
++                sal_uInt16 nCol1 = static_cast< sal_uInt16 >( bCol1Rel ? r1.nRelCol : r1.nCol );
++                sal_uInt16 nCol2 = static_cast< sal_uInt16 >( bCol2Rel ? r2.nRelCol : r2.nCol );
++                sal_uInt16 nRow1 = static_cast< sal_uInt16 >( bRow1Rel ? r1.nRelRow : r1.nRow );
++                sal_uInt16 nRow2 = static_cast< sal_uInt16 >( bRow2Rel ? r2.nRelRow : r2.nRow );
 +                if (bCol1Rel) nCol1 |= 0x4000;
 +                if (bRow1Rel) nCol1 |= 0x8000;
 +                if (bCol2Rel) nCol2 |= 0x4000;
@@ -5080,7 +5707,7 @@
 +                // operator token (3B for area reference)
 +                rStrm << static_cast<sal_uInt8>(0x3B);
 +                // range (area) address
-+                sal_uInt16 nSBTab2 = nSBTab + nTab2 - nTab1; 
++                sal_uInt16 nSBTab2 = nSBTab + nTab2 - nTab1;
 +                rStrm << nSBTab << nSBTab2 << nRow1 << nRow2 << nCol1 << nCol2;
 +                return;
 +            }
@@ -5158,16 +5785,16 @@
 +    pMtx->GetDimensions(nCols, nRows);
 +    const ScAddress& s = rRange.aStart;
 +    const ScAddress& e = rRange.aEnd;
-+    if (static_cast<SCCOL>(nCols) != e.Col() - s.Col() + 1 || 
++    if (static_cast<SCCOL>(nCols) != e.Col() - s.Col() + 1 ||
 +        static_cast<SCROW>(nRows) != e.Row() - s.Row() + 1)
 +    {
 +        // size mis-match!
 +        return;
 +    }
 +
-+    for (SCSIZE nCol = 0; nCol < nCols; ++nCol)
++    for (SCCOL nCol = 0; nCol < static_cast< SCCOL >( nCols ); ++nCol)
 +    {
-+        for (SCSIZE nRow = 0; nRow < nRows; ++nRow)
++        for (SCROW nRow = 0; nRow < static_cast< SCROW >( nRows ); ++nRow)
 +        {
 +            if (pMtx->IsString(nCol, nRow))
 +            {
@@ -5664,7 +6291,7 @@
  {
      mxImpl->Save( rStrm );
 diff --git sc/source/filter/excel/xilink.cxx sc/source/filter/excel/xilink.cxx
-index 01932a5..0b79f64 100644
+index 01932a5..f906ef8 100644
 --- sc/source/filter/excel/xilink.cxx
 +++ sc/source/filter/excel/xilink.cxx
 @@ -38,6 +38,13 @@
@@ -5805,13 +6432,15 @@
      if( ::get_flag( nFlags, EXC_EXTN_BUILTIN ) || !::get_flag( nFlags, EXC_EXTN_OLE_OR_DDE ) )
      {
          if( bAddIn )
-@@ -319,6 +317,28 @@ XclImpExtName::XclImpExtName( XclImpStream& rStrm, bool bAddIn )
+@@ -319,6 +317,30 @@ XclImpExtName::XclImpExtName( XclImpStream& rStrm, bool bAddIn )
  
      if( (meType == xlExtDDE) && (rStrm.GetRecLeft() > 1) )
          mxDdeMatrix.reset( new XclImpCachedMatrix( rStrm ) );
 +
 +    if (meType == xlExtName)
 +    {
++        // TODO: For now, only global external names are supported.  In future 
++        // we should extend this to supporting per-sheet external names.
 +        if (mnStorageId == 0)
 +        {
 +            if (pFormulaConv)
@@ -5834,20 +6463,28 @@
  }
  
  XclImpExtName::~XclImpExtName()
-@@ -333,6 +353,12 @@ void XclImpExtName::CreateDdeData( ScDocument& rDoc, const String& rApplic, cons
+@@ -333,6 +355,20 @@ void XclImpExtName::CreateDdeData( ScDocument& rDoc, const String& rApplic, cons
      rDoc.CreateDdeLink( rApplic, rTopic, maName, SC_DDE_DEFAULT, xResults );
  }
  
 +void XclImpExtName::CreateExtNameData( ScDocument& rDoc, sal_uInt16 nFileId ) const
 +{
++    if (!mxArray.get())
++        return;
++
 +    ScExternalRefManager* pRefMgr = rDoc.GetExternalRefManager();
 +    pRefMgr->storeRangeNameTokens(nFileId, maName, *mxArray);
 +}
 +
++bool XclImpExtName::HasFormulaTokens() const
++{
++    return (mxArray.get() != NULL);
++}
++
  // Cached external cells ======================================================
  
  XclImpCrn::XclImpCrn( XclImpStream& rStrm, const XclAddress& rXclPos ) :
-@@ -341,29 +367,9 @@ XclImpCrn::XclImpCrn( XclImpStream& rStrm, const XclAddress& rXclPos ) :
+@@ -341,29 +377,9 @@ XclImpCrn::XclImpCrn( XclImpStream& rStrm, const XclAddress& rXclPos ) :
  {
  }
  
@@ -5879,7 +6516,7 @@
  }
  
  // Sheet in an external document ==============================================
-@@ -383,13 +389,40 @@ void XclImpSupbookTab::ReadCrn( XclImpStream& rStrm, const XclAddress& rXclPos )
+@@ -383,13 +399,40 @@ void XclImpSupbookTab::ReadCrn( XclImpStream& rStrm, const XclAddress& rXclPos )
      maCrnList.Append( new XclImpCrn( rStrm, rXclPos ) );
  }
  
@@ -5905,7 +6542,7 @@
 +            {
 +                double f = p->GetValue();
 +                ScExternalRefCache::TokenRef pToken(new ScDoubleToken(f));
-+                pCacheTable->setCell(rAddr.mnRow, rAddr.mnCol, pToken);
++                pCacheTable->setCell(rAddr.mnCol, rAddr.mnRow, pToken);
 +            }
 +            break;
 +            case EXC_CACHEDVAL_EMPTY:
@@ -5916,7 +6553,7 @@
 +            {
 +                const String& rStr = p->GetString();
 +                ScExternalRefCache::TokenRef pToken(new ScStringToken(rStr));
-+                pCacheTable->setCell(rAddr.mnRow, rAddr.mnCol, pToken);
++                pCacheTable->setCell(rAddr.mnCol, rAddr.mnRow, pToken);
 +            }
 +            break;
 +            default:
@@ -5926,7 +6563,7 @@
  }
  
  // External document (SUPBOOK) ================================================
-@@ -453,25 +486,9 @@ void XclImpSupbook::ReadCrn( XclImpStream& rStrm )
+@@ -453,25 +496,9 @@ void XclImpSupbook::ReadCrn( XclImpStream& rStrm )
      }
  }
  
@@ -5954,7 +6591,7 @@
  }
  
  const XclImpExtName* XclImpSupbook::GetExternName( sal_uInt16 nXclIndex ) const
-@@ -492,20 +509,46 @@ const String& XclImpSupbook::GetMacroName( sal_uInt16 nXclNameIdx ) const
+@@ -492,20 +519,46 @@ const String& XclImpSupbook::GetMacroName( sal_uInt16 nXclNameIdx ) const
      return (pName && pName->IsVBName()) ? pName->GetScName() : EMPTY_STRING;
  }
  
@@ -5985,33 +6622,33 @@
 +{
 +    if (meType != EXC_SBTYPE_EXTERN || GetExtDocOptions().GetDocSettings().mnLinkCnt > 0)
 +        return;
-+
-+    String aAbsUrl( ScGlobal::GetAbsDocName(maXclUrl, GetDocShell()) );
  
 -        // get filter name for external document
 -        if( !maFilterName.Len() )
 -            ScDocumentLoader::GetFilterName( aAbsUrl, maFilterName, maFilterOpt, FALSE, FALSE );
-+    ScExternalRefManager* pRefMgr = GetRoot().GetDoc().GetExternalRefManager();
-+    sal_uInt16 nFileId = pRefMgr->getExternalFileId(aAbsUrl);
++    String aAbsUrl( ScGlobal::GetAbsDocName(maXclUrl, GetDocShell()) );
  
 -        // create tables
 -        for( sal_uInt16 nSBTab = nSBTabFirst; nSBTab <= nSBTabLast; ++nSBTab )
 -            if( XclImpSupbookTab* pSBTab = maSupbTabList.GetObject( nSBTab ) )
 -                pSBTab->CreateAndFillTable( GetRoot(), aAbsUrl, maFilterName, maFilterOpt );
-+    sal_uInt16 nCount = maSupbTabList.Count();
++    ScExternalRefManager* pRefMgr = GetRoot().GetDoc().GetExternalRefManager();
++    sal_uInt16 nFileId = pRefMgr->getExternalFileId(aAbsUrl);
++
++    sal_uInt16 nCount = static_cast< sal_uInt16 >( maSupbTabList.Count() );
 +    for (sal_uInt16 i = 0; i < nCount; ++i)
 +    {
 +        XclImpSupbookTab* pTab = maSupbTabList.GetObject(i);
 +        if (!pTab)
 +            return;
-+        
++
 +        const String& rTabName = pTab->GetTabName();
 +        ScExternalRefCache::TableTypeRef pCacheTable = pRefMgr->getCacheTable(nFileId, rTabName, true);
 +        pTab->LoadCachedValues(pCacheTable);
      }
  }
  
-@@ -531,7 +574,7 @@ void XclImpLinkManagerImpl::ReadExternsheet( XclImpStream& rStrm )
+@@ -531,7 +584,7 @@ void XclImpLinkManagerImpl::ReadExternsheet( XclImpStream& rStrm )
          --nXtiCount;
      }
  
@@ -6020,7 +6657,7 @@
  }
  
  void XclImpLinkManagerImpl::ReadSupbook( XclImpStream& rStrm )
-@@ -551,10 +594,10 @@ void XclImpLinkManagerImpl::ReadCrn( XclImpStream& rStrm )
+@@ -551,10 +604,10 @@ void XclImpLinkManagerImpl::ReadCrn( XclImpStream& rStrm )
          pSupbook->ReadCrn( rStrm );
  }
  
@@ -6033,7 +6670,7 @@
  }
  
  bool XclImpLinkManagerImpl::IsSelfRef( sal_uInt16 nXtiIndex ) const
-@@ -568,10 +611,10 @@ bool XclImpLinkManagerImpl::GetScTabRange(
+@@ -568,10 +621,10 @@ bool XclImpLinkManagerImpl::GetScTabRange(
  {
      if( const XclImpXti* pXti = maXtiList.GetObject( nXtiIndex ) )
      {
@@ -6047,7 +6684,7 @@
              return true;
          }
      }
-@@ -584,6 +627,20 @@ const XclImpExtName* XclImpLinkManagerImpl::GetExternName( sal_uInt16 nXtiIndex,
+@@ -584,6 +637,20 @@ const XclImpExtName* XclImpLinkManagerImpl::GetExternName( sal_uInt16 nXtiIndex,
      return pSupbook ? pSupbook->GetExternName( nExtName ) : 0;
  }
  
@@ -6068,7 +6705,7 @@
  bool XclImpLinkManagerImpl::GetLinkData( String& rApplic, String& rTopic, sal_uInt16 nXtiIndex ) const
  {
      const XclImpSupbook* pSupbook = GetSupbook( nXtiIndex );
-@@ -596,12 +653,6 @@ const String& XclImpLinkManagerImpl::GetMacroName( sal_uInt16 nExtSheet, sal_uIn
+@@ -596,12 +663,6 @@ const String& XclImpLinkManagerImpl::GetMacroName( sal_uInt16 nExtSheet, sal_uIn
      return pSupbook ? pSupbook->GetMacroName( nExtName ) : EMPTY_STRING;
  }
  
@@ -6081,7 +6718,7 @@
  const XclImpSupbook* XclImpLinkManagerImpl::GetSupbook( sal_uInt32 nXtiIndex ) const
  {
      const XclImpXti* pXti = maXtiList.GetObject( nXtiIndex );
-@@ -616,26 +667,17 @@ const XclImpSupbook* XclImpLinkManagerImpl::GetSupbook( const String& rUrl ) con
+@@ -616,26 +677,17 @@ const XclImpSupbook* XclImpLinkManagerImpl::GetSupbook( const String& rUrl ) con
      return 0;
  }
  
@@ -6090,7 +6727,7 @@
  {
 -    DBG_ASSERT( !mbCreated, "XclImpLinkManager::CreateTables - multiple call" );
 -    if( mbCreated ) return;
-+    // Read all CRN records which can be accessed via XclImpSupbook, and store 
++    // Read all CRN records which can be accessed via XclImpSupbook, and store
 +    // the cached values to the external reference manager.
  
 -    sal_uInt16 nSBTabFirst, nSBTabLast;
@@ -6114,7 +6751,7 @@
  }
  
  bool XclImpLinkManagerImpl::FindNextTabRange(
-@@ -686,9 +728,9 @@ void XclImpLinkManager::ReadCrn( XclImpStream& rStrm )
+@@ -686,9 +738,9 @@ void XclImpLinkManager::ReadCrn( XclImpStream& rStrm )
      mxImpl->ReadCrn( rStrm );
  }
  
@@ -6126,7 +6763,7 @@
  }
  
  bool XclImpLinkManager::IsSelfRef( sal_uInt16 nXtiIndex ) const
-@@ -707,6 +749,16 @@ const XclImpExtName* XclImpLinkManager::GetExternName( sal_uInt16 nXtiIndex, sal
+@@ -707,6 +759,16 @@ const XclImpExtName* XclImpLinkManager::GetExternName( sal_uInt16 nXtiIndex, sal
      return mxImpl->GetExternName( nXtiIndex, nExtName );
  }
  
@@ -6143,7 +6780,7 @@
  bool XclImpLinkManager::GetLinkData( String& rApplic, String& rTopic, sal_uInt16 nXtiIndex ) const
  {
      return mxImpl->GetLinkData( rApplic, rTopic, nXtiIndex );
-@@ -717,10 +769,5 @@ const String& XclImpLinkManager::GetMacroName( sal_uInt16 nExtSheet, sal_uInt16
+@@ -717,10 +779,5 @@ const String& XclImpLinkManager::GetMacroName( sal_uInt16 nExtSheet, sal_uInt16
      return mxImpl->GetMacroName( nExtSheet, nExtName );
  }
  
@@ -6382,7 +7019,7 @@
      virtual void        Save( XclExpStream& rStrm );
  
 diff --git sc/source/filter/inc/xilink.hxx sc/source/filter/inc/xilink.hxx
-index 0d547fe..3983e4d 100644
+index 0d547fe..8b74794 100644
 --- sc/source/filter/inc/xilink.hxx
 +++ sc/source/filter/inc/xilink.hxx
 @@ -107,6 +107,8 @@ enum XclImpExtNameType
@@ -6394,7 +7031,7 @@
  
  /** Stores contents of an external name.
      @descr Supported: External defined names, AddIn names, DDE links and OLE objects. */
-@@ -114,21 +116,26 @@ class XclImpExtName
+@@ -114,21 +116,28 @@ class XclImpExtName
  {
  public:
      /** Reads the external name from the stream. */
@@ -6409,6 +7046,8 @@
  
 +    void                CreateExtNameData( ScDocument& rDoc, sal_uInt16 nFileId ) const;
 +
++    bool                HasFormulaTokens() const;
++
      inline XclImpExtNameType GetType() const { return meType; }
      inline const String& GetName() const { return maName; }
      inline sal_uInt32   GetStorageId() const { return mnStorageId; }
@@ -6422,7 +7061,7 @@
      String              maName;             /// The name of the external name.
      sal_uInt32          mnStorageId;        /// Storage ID for OLE object storages.
      XclImpExtNameType   meType;             /// Type of the external name.
-@@ -168,7 +175,7 @@ public:
+@@ -168,7 +177,7 @@ public:
      /** Reads a CRN record and appends it to the current SUPBOOK. */
      void                ReadCrn( XclImpStream& rStrm );
      /** Reads an EXTERNNAME record and appends it to the current SUPBOOK. */
@@ -6431,7 +7070,7 @@
  
      /** Returns true, if the specified XTI entry contains an internal reference. */
      bool                IsSelfRef( sal_uInt16 nXtiIndex ) const;
-@@ -179,6 +186,11 @@ public:
+@@ -179,6 +188,11 @@ public:
                              sal_uInt16 nXtiIndex ) const;
      /** Returns the specified external name or 0 on error. */
      const XclImpExtName* GetExternName( sal_uInt16 nXtiIndex, sal_uInt16 nExtName ) const;
@@ -6443,7 +7082,7 @@
      /** Tries to decode the URL of the specified XTI entry to OLE or DDE link components.
          @descr  For DDE links: Decodes to application name and topic.
          For OLE object links: Decodes to class name and document URL.
-@@ -187,10 +199,6 @@ public:
+@@ -187,10 +201,6 @@ public:
      /** Returns the specified macro name or an empty string on error. */
      const String&       GetMacroName( sal_uInt16 nExtSheet, sal_uInt16 nExtName ) const;
  
@@ -6530,7 +7169,7 @@
  //------------------------------------------------------------------
  
 diff --git sc/source/filter/xml/XMLTableShapeImportHelper.cxx sc/source/filter/xml/XMLTableShapeImportHelper.cxx
-index bb6fe74..219b5cc 100644
+index 57e5464..25f47f9 100644
 --- sc/source/filter/xml/XMLTableShapeImportHelper.cxx
 +++ sc/source/filter/xml/XMLTableShapeImportHelper.cxx
 @@ -49,6 +49,7 @@
@@ -6586,7 +7225,7 @@
  //------------------------------------------------------------------
  
 diff --git sc/source/filter/xml/xmlcelli.cxx sc/source/filter/xml/xmlcelli.cxx
-index 92eb208..a990e54 100644
+index 4788cd1..d8e9363 100644
 --- sc/source/filter/xml/xmlcelli.cxx
 +++ sc/source/filter/xml/xmlcelli.cxx
 @@ -146,185 +146,131 @@ ScXMLTableRowCellContext::ScXMLTableRowCellContext( ScXMLImport& rImport,
@@ -6929,7 +7568,7 @@
  				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
+index 2129837..8c8e895 100644
 --- sc/source/filter/xml/xmldpimp.cxx
 +++ sc/source/filter/xml/xmldpimp.cxx
 @@ -65,6 +65,7 @@
@@ -6941,7 +7580,7 @@
  //------------------------------------------------------------------
  
 diff --git sc/source/filter/xml/xmlexprt.cxx sc/source/filter/xml/xmlexprt.cxx
-index 441f463..119a53f 100644
+index b29578f..155cc6d 100644
 --- sc/source/filter/xml/xmlexprt.cxx
 +++ sc/source/filter/xml/xmlexprt.cxx
 @@ -68,6 +68,7 @@
@@ -6982,7 +7621,82 @@
          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()
+@@ -525,6 +535,15 @@ ScXMLExport::~ScXMLExport()
+ 		delete pNumberFormatAttributesExportHelper;
+ }
+ 
++sal_Int32 ScXMLExport::GetNumberFormatStyleIndex(sal_Int32 nNumFmt) const
++{
++    NumberFormatIndexMap::const_iterator itr = aNumFmtIndexMap.find(nNumFmt);
++    if (itr == aNumFmtIndexMap.end())
++        return -1;
++
++    return itr->second;
++}
++
+ sal_Bool ScXMLExport::HasDrawPages(uno::Reference <sheet::XSpreadsheetDocument>& xDoc)
+ {
+ 	uno::Reference <beans::XPropertySet> xDocProps( xDoc, uno::UNO_QUERY );
+@@ -1019,6 +1038,58 @@ void ScXMLExport::ExportColumns(const sal_Int32 nTable, const table::CellRangeAd
+ 		pGroupColumns->CloseGroups(nColumn - 1);
+ }
+ 
++void ScXMLExport::ExportExternalRefCacheStyles()
++{
++    sal_Int32 nEntryIndex = GetCellStylesPropertySetMapper()->FindEntryIndex(
++        "NumberFormat", XML_NAMESPACE_STYLE, OUString::createFromAscii("data-style-name"));
++
++    if (nEntryIndex < 0)
++        // No entry index for the number format is found.
++        return;
++
++    ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
++    if (!pRefMgr->hasExternalData())
++        // No external reference data cached.
++        return;
++
++    // Export each unique number format used in the external ref cache.
++    vector<sal_uInt32> aNumFmts;
++    pRefMgr->getAllCachedNumberFormats(aNumFmts);
++    const OUString aDefaultStyle = OUString::createFromAscii("Default").intern();
++    for (vector<sal_uInt32>::const_iterator itr = aNumFmts.begin(), itrEnd = aNumFmts.end();
++          itr != itrEnd; ++itr)
++    {
++        sal_Int32 nNumFmt = static_cast<sal_Int32>(*itr);
++
++        addDataStyle(nNumFmt);
++
++        uno::Any aVal;
++        aVal <<= nNumFmt;
++        vector<XMLPropertyState> aProps;
++        aProps.push_back(XMLPropertyState(nEntryIndex, aVal));
++        aVal <<= aDefaultStyle;
++        aProps.push_back(XMLPropertyState(nEntryIndex, aVal));
++
++        OUString aName;
++        sal_Int32 nIndex;
++        if (GetAutoStylePool()->Add(aName, XML_STYLE_FAMILY_TABLE_CELL, aDefaultStyle, aProps))
++        {
++            OUString* pTemp(new OUString(aName));
++            if (!pCellStyles->AddStyleName(pTemp, nIndex, true))
++                delete pTemp;
++        }
++        else
++        {
++            sal_Bool bIsAuto;
++            nIndex = pCellStyles->GetIndexOfStyleName(
++                aName, OUString::createFromAscii(XML_STYLE_FAMILY_TABLE_CELL_STYLES_PREFIX), bIsAuto);
++        }
++
++        // store the number format to index mapping for later use.
++        aNumFmtIndexMap.insert(NumberFormatIndexMap::value_type(nNumFmt, nIndex));
++    }
++}
++
+ void ScXMLExport::WriteRowContent()
+ {
+ 	ScMyRowFormatRange aRange;
+@@ -1422,180 +1493,181 @@ void ScXMLExport::_ExportContent()
  		DBG_ERROR("no shared data setted");
  	}
  	ScXMLExportDatabaseRanges aExportDatabaseRanges(*this);
@@ -7330,7 +8044,16 @@
  }
  
  void ScXMLExport::_ExportStyles( sal_Bool bUsed )
-@@ -2000,6 +2011,15 @@ void ScXMLExport::_ExportAutoStyles()
+@@ -1671,6 +1743,8 @@ void ScXMLExport::_ExportAutoStyles()
+ 			{
+ 				if (getExportFlags() & EXPORT_CONTENT)
+ 				{
++                    ExportExternalRefCacheStyles();
++
+ 					if (!pSharedData)
+ 					{
+ 						sal_Int32 nTableCount(0);
+@@ -2000,6 +2074,15 @@ void ScXMLExport::_ExportAutoStyles()
  
  					GetShapeExport()->exportAutoStyles();
  					GetFormExport()->exportAutoStyles( );
@@ -7346,7 +8069,16 @@
  				}
  				if (getExportFlags() & EXPORT_MASTERSTYLES)
  				{
-@@ -3333,6 +3353,184 @@ void ScXMLExport::WriteNamedExpressions(const com::sun::star::uno::Reference <co
+@@ -3003,7 +3086,7 @@ sal_Bool ScXMLExport::IsCellEqual (ScMyCell& aCell1, ScMyCell& aCell2)
+ 							}
+                             // #i29101# number format may be different from column default styles,
+                             // but can lead to different value types, so it must also be compared
+-                            bIsEqual = (aCell1.nNumberFormat == aCell2.nNumberFormat) && 
++                            bIsEqual = (aCell1.nNumberFormat == aCell2.nNumberFormat) &&
+                                        (aCell1.fValue == aCell2.fValue);
+ 						}
+ 						break;
+@@ -3344,6 +3427,192 @@ void ScXMLExport::WriteNamedExpressions(const com::sun::star::uno::Reference <co
  	}
  }
  
@@ -7357,7 +8089,7 @@
 +
 +    ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
 +    pRefMgr->resetSrcFileData();
-+    sal_uInt16 nCount = pRefMgr->getCachedFileCount();
++    sal_uInt16 nCount = pRefMgr->getExternalFileCount();
 +    for (sal_uInt16 nFileId = 0; nFileId < nCount; ++nFileId)
 +    {
 +        const String* pUrl = pRefMgr->getExternalFileName(nFileId);
@@ -7418,7 +8150,7 @@
 +                if (bFirstRow)
 +                {
 +                    if (nRow > 0)
-+                    {   
++                    {
 +                        if (nRow > 1)
 +                        {
 +                            OUStringBuffer aVal;
@@ -7463,7 +8195,7 @@
 +                    if (bFirstCol)
 +                    {
 +                        if (nCol > 0)
-+                        {   
++                        {
 +                            if (nCol > 1)
 +                            {
 +                                OUStringBuffer aVal;
@@ -7489,10 +8221,18 @@
 +                    }
 +
 +                    // Write out this cell.
-+                    ScExternalRefCache::TokenRef pToken = pTable->getCell(nRow, nCol);
++                    sal_uInt32 nNumFmt = 0;
++                    ScExternalRefCache::TokenRef pToken = pTable->getCell(nCol, nRow, &nNumFmt);
 +                    OUString aStrVal;
 +                    if (pToken.get())
 +                    {
++                        sal_Int32 nIndex = GetNumberFormatStyleIndex(nNumFmt);
++                        if (nIndex >= 0)
++                        {
++                            const OUString aStyleName = *pCellStyles->GetStyleNameByIndex(nIndex, true);
++                            AddAttribute(XML_NAMESPACE_TABLE, XML_STYLE_NAME, aStyleName);
++                        }
++
 +                        switch(pToken->GetType())
 +                        {
 +                            case svDouble:
@@ -7532,10 +8272,28 @@
  void ScXMLExport::WriteConsolidation()
  {
 diff --git sc/source/filter/xml/xmlexprt.hxx sc/source/filter/xml/xmlexprt.hxx
-index 47171b6..e8477e5 100644
+index e4fcc10..a6385f1 100644
 --- sc/source/filter/xml/xmlexprt.hxx
 +++ sc/source/filter/xml/xmlexprt.hxx
-@@ -98,6 +98,7 @@ class ScXMLExport : public SvXMLExport
+@@ -38,6 +38,8 @@
+ #include <com/sun/star/drawing/XShapes.hpp>
+ #include <com/sun/star/table/XCellRange.hpp>
+ 
++#include <hash_map>
++
+ class ScOutlineArray;
+ class SvXMLExportPropertyMapper;
+ class ScMyShapesContainer;
+@@ -80,6 +82,8 @@ class ScXMLExport : public SvXMLExport
+ 	UniReference < SvXMLExportPropertyMapper >	xRowStylesExportPropertySetMapper;
+ 	UniReference < SvXMLExportPropertyMapper >	xTableStylesExportPropertySetMapper;
+ 	XMLNumberFormatAttributesExportHelper* pNumberFormatAttributesExportHelper;
++    typedef ::std::hash_map<sal_Int32, sal_Int32>  NumberFormatIndexMap;
++    NumberFormatIndexMap                aNumFmtIndexMap;
+ 	ScMySharedData*						pSharedData;
+ 	ScColumnStyles*					pColumnStyles;
+ 	ScRowStyles*					pRowStyles;
+@@ -99,6 +103,7 @@ class ScXMLExport : public SvXMLExport
  	ScChangeTrackingExportHelper*	pChangeTrackingExportHelper;
  	const rtl::OUString			sLayerID;
  	const rtl::OUString			sCaptionShape;
@@ -7543,7 +8301,24 @@
      rtl::OUString               sAttrName;
      rtl::OUString               sAttrStyleName;
      rtl::OUString               sAttrColumnsRepeated;
-@@ -195,6 +196,7 @@ class ScXMLExport : public SvXMLExport
+@@ -118,7 +123,7 @@ class ScXMLExport : public SvXMLExport
+ 	sal_Bool					bRowHeaderOpen;
+ 	sal_Bool					mbShowProgress;
+ 
+-
++    sal_Int32       GetNumberFormatStyleIndex(sal_Int32 nNumFmt) const;
+ 	sal_Bool		HasDrawPages(com::sun::star::uno::Reference <com::sun::star::sheet::XSpreadsheetDocument>& xDoc);
+ 	void			CollectSharedData(sal_Int32& nTableCount, sal_Int32& nShapesCount, const sal_Int32 nCellCount);
+ 	void			CollectShapesAutoStyles(const sal_Int32 nTableCount);
+@@ -146,6 +151,7 @@ class ScXMLExport : public SvXMLExport
+ 	void OpenHeaderColumn();
+ 	void CloseHeaderColumn();
+ 	void ExportColumns(const sal_Int32 nTable, const com::sun::star::table::CellRangeAddress& aColumnHeaderRange, const sal_Bool bHasColumnHeader);
++    void ExportExternalRefCacheStyles();
+ 	void ExportFormatRanges(const sal_Int32 nStartCol, const sal_Int32 nStartRow,
+ 		const sal_Int32 nEndCol, const sal_Int32 nEndRow, const sal_Int32 nSheet);
+ 	void WriteRowContent();
+@@ -196,6 +202,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);
@@ -7553,10 +8328,10 @@
  	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..3417206
+index 0000000..f4e42be
 --- /dev/null
 +++ sc/source/filter/xml/xmlexternaltabi.cxx
-@@ -0,0 +1,343 @@
+@@ -0,0 +1,355 @@
 +/*************************************************************************
 + *
 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -7597,6 +8372,7 @@
 +#include "xmlexternaltabi.hxx"
 +#include "xmlimprt.hxx"
 +#include "xmltabi.hxx"
++#include "xmlstyli.hxx"
 +
 +#include "token.hxx"
 +#include "document.hxx"
@@ -7616,10 +8392,10 @@
 +// ============================================================================
 +
 +ScXMLExternalRefTabSourceContext::ScXMLExternalRefTabSourceContext(
-+    ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName, 
++    ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName,
 +    const Reference<XAttributeList>& xAttrList, ScXMLExternalTabData& rRefInfo ) :
 +    SvXMLImportContext( rImport, nPrefix, rLName ),
-+    mrScImport(rImport), 
++    mrScImport(rImport),
 +    mrExternalRefInfo(rRefInfo)
 +{
 +    using namespace ::xmloff::token;
@@ -7673,10 +8449,10 @@
 +// ============================================================================
 +
 +ScXMLExternalRefRowContext::ScXMLExternalRefRowContext(
-+    ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName, 
++    ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName,
 +    const Reference<XAttributeList>& xAttrList, ScXMLExternalTabData& rRefInfo ) :
 +    SvXMLImportContext( rImport, nPrefix, rLName ),
-+    mrScImport(rImport), 
++    mrScImport(rImport),
 +    mrExternalRefInfo(rRefInfo),
 +    mnRepeatRowCount(1)
 +{
@@ -7726,12 +8502,12 @@
 +        for (sal_Int32 j = 0; j < mrExternalRefInfo.mnCol; ++j)
 +        {
 +            ScExternalRefCache::TokenRef pToken = pTab->getCell(
-+                static_cast<SCROW>(mrExternalRefInfo.mnRow), static_cast<SCCOL>(j));
++                static_cast<SCCOL>(j), static_cast<SCROW>(mrExternalRefInfo.mnRow));
 +
 +            if (pToken.get())
 +            {
-+                pTab->setCell(static_cast<SCROW>(
-+                    mrExternalRefInfo.mnRow+i), static_cast<SCCOL>(j), pToken);
++                pTab->setCell(static_cast<SCCOL>(j),
++                              static_cast<SCROW>(mrExternalRefInfo.mnRow+i), pToken);
 +            }
 +        }
 +    }
@@ -7741,13 +8517,14 @@
 +// ============================================================================
 +
 +ScXMLExternalRefCellContext::ScXMLExternalRefCellContext(
-+    ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName, 
++    ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName,
 +    const Reference<XAttributeList>& xAttrList, ScXMLExternalTabData& rRefInfo ) :
 +    SvXMLImportContext( rImport, nPrefix, rLName ),
-+    mrScImport(rImport), 
++    mrScImport(rImport),
 +    mrExternalRefInfo(rRefInfo),
 +    mfCellValue(0.0),
 +    mnRepeatCount(1),
++    mnNumberFormat(-1),
 +    mnCellType(::com::sun::star::util::NumberFormat::UNDEFINED),
 +    mbIsNumeric(false),
 +    mbIsEmpty(true)
@@ -7767,8 +8544,17 @@
 +
 +        switch (nToken)
 +        {
++            case XML_TOK_TABLE_ROW_CELL_ATTR_STYLE_NAME:
++            {
++                XMLTableStylesContext* pStyles = static_cast<XMLTableStylesContext*>(mrScImport.GetAutoStyles());
++                const XMLTableStyleContext* pStyle = static_cast<const XMLTableStyleContext*>(
++                    pStyles->FindStyleChildContext(XML_STYLE_FAMILY_TABLE_CELL, sValue, true));
++                if (pStyle)
++                    mnNumberFormat = const_cast<XMLTableStyleContext*>(pStyle)->GetNumberFormat();
++            }
++            break;
 +            case XML_TOK_TABLE_ROW_CELL_ATTR_REPEATED:
-+            {    
++            {
 +                mnRepeatCount = ::std::max(sValue.toInt32(), static_cast<sal_Int32>(1));
 +            }
 +            break;
@@ -7864,20 +8650,21 @@
 +        else
 +            aToken.reset(new ScStringToken(maCellString));
 +
++        sal_uInt32 nNumFmt = mnNumberFormat >= 0 ? static_cast<sal_uInt32>(mnNumberFormat) : 0;
 +        mrExternalRefInfo.mpCacheTable->setCell(
-+            static_cast<SCROW>(mrExternalRefInfo.mnRow), 
-+            static_cast<SCCOL>(mrExternalRefInfo.mnCol), 
-+            aToken);
++            static_cast<SCCOL>(mrExternalRefInfo.mnCol),
++            static_cast<SCROW>(mrExternalRefInfo.mnRow),
++            aToken, nNumFmt);
 +    }
 +}
 +
 +// ============================================================================
 +
 +ScXMLExternalRefCellTextContext::ScXMLExternalRefCellTextContext(
-+    ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName, 
++    ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName,
 +    const Reference<XAttributeList>& /*xAttrList*/, OUString& rCellString ) :
 +    SvXMLImportContext( rImport, nPrefix, rLName ),
-+    mrScImport(rImport), 
++    mrScImport(rImport),
 +    mrCellString(rCellString)
 +{
 +}
@@ -7902,10 +8689,10 @@
 +}
 diff --git sc/source/filter/xml/xmlexternaltabi.hxx sc/source/filter/xml/xmlexternaltabi.hxx
 new file mode 100644
-index 0000000..6f26789
+index 0000000..2c3f3fb
 --- /dev/null
 +++ sc/source/filter/xml/xmlexternaltabi.hxx
-@@ -0,0 +1,149 @@
+@@ -0,0 +1,150 @@
 +/*************************************************************************
 + *
 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -8022,6 +8809,7 @@
 +    ::rtl::OUString         maCellString;
 +    double                  mfCellValue;
 +    sal_Int32               mnRepeatCount;
++    sal_Int32               mnNumberFormat;
 +    sal_Int16               mnCellType;
 +    bool                    mbIsNumeric;
 +    bool                    mbIsEmpty;
@@ -8056,7 +8844,7 @@
 +
 +#endif
 diff --git sc/source/filter/xml/xmlimprt.cxx sc/source/filter/xml/xmlimprt.cxx
-index 47b26b9..eb74c99 100644
+index c21e3ca..2d876ed 100644
 --- sc/source/filter/xml/xmlimprt.cxx
 +++ sc/source/filter/xml/xmlimprt.cxx
 @@ -104,6 +104,7 @@
@@ -8196,7 +8984,7 @@
  
  //	inline const SvXMLImportItemMapper& GetParaItemMapper() const;
 diff --git sc/source/filter/xml/xmlsceni.cxx sc/source/filter/xml/xmlsceni.cxx
-index cfe859d..f4d6c89 100644
+index 6165d6a..586176f 100644
 --- sc/source/filter/xml/xmlsceni.cxx
 +++ sc/source/filter/xml/xmlsceni.cxx
 @@ -50,6 +50,7 @@
@@ -8208,7 +8996,7 @@
  //------------------------------------------------------------------
  
 diff --git sc/source/filter/xml/xmlstyle.cxx sc/source/filter/xml/xmlstyle.cxx
-index 7aec632..863e82c 100644
+index 9385621..e64fd22 100644
 --- sc/source/filter/xml/xmlstyle.cxx
 +++ sc/source/filter/xml/xmlstyle.cxx
 @@ -65,6 +65,7 @@
@@ -8232,8 +9020,89 @@
  extern const XMLPropertyMapEntry aXMLScCellStylesProperties[];
  extern const XMLPropertyMapEntry aXMLScColumnStylesProperties[];
  extern const XMLPropertyMapEntry aXMLScRowStylesProperties[];
+diff --git sc/source/filter/xml/xmlstyli.cxx sc/source/filter/xml/xmlstyli.cxx
+index 6813d0d..9624740 100644
+--- sc/source/filter/xml/xmlstyli.cxx
++++ sc/source/filter/xml/xmlstyli.cxx
+@@ -584,28 +584,10 @@ void XMLTableStyleContext::FillPropertySet(
+                 AddProperty(CTF_SC_CELLSTYLE, uno::makeAny(GetImport().GetStyleDisplayName( XML_STYLE_FAMILY_TABLE_CELL, GetParentName() )));
+ 				bParentSet = sal_True;
+ 			}
+-			if ((nNumberFormat == -1) && sDataStyleName.getLength())
+-			{
+-				SvXMLNumFormatContext* pStyle((SvXMLNumFormatContext *)pStyles->FindStyleChildContext(
+-					XML_STYLE_FAMILY_DATA_STYLE, sDataStyleName, sal_True));
+-				if (!pStyle)
+-				{
+-					XMLTableStylesContext* pMyStyles((XMLTableStylesContext *)GetScImport().GetStyles());
+-					if (pMyStyles)
+-						pStyle = (SvXMLNumFormatContext *)pMyStyles->
+-							FindStyleChildContext(XML_STYLE_FAMILY_DATA_STYLE, sDataStyleName, sal_True);
+-					else
+-					{
+-						DBG_ERROR("not possible to get style");
+-					}
+-				}
+-				if (pStyle)
+-				{
+-					//rPropSet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_NUMBERFORMAT)), aNumberFormat);
+-					nNumberFormat = pStyle->GetKey();
+-                    AddProperty(CTF_SC_NUMBERFORMAT, uno::makeAny(nNumberFormat));
+-				}
+-			}
++            sal_Int32 nNumFmt = GetNumberFormat();
++            if (nNumFmt >= 0)
++                AddProperty(CTF_SC_NUMBERFORMAT, uno::makeAny(nNumFmt));
++
+ 			if (!bConditionalFormatCreated && (aMaps.size() > 0))
+ 			{
+ 				aConditionalFormat = rPropSet->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_CONDXML)));
+@@ -683,6 +665,30 @@ XMLPropertyState* XMLTableStyleContext::FindProperty(const sal_Int16 nContextID)
+     return pRet;
+ }
+ 
++sal_Int32 XMLTableStyleContext::GetNumberFormat()
++{
++    if (nNumberFormat < 0 && sDataStyleName.getLength())
++    {
++        const SvXMLNumFormatContext* pStyle = static_cast<const SvXMLNumFormatContext*>(
++            pStyles->FindStyleChildContext(XML_STYLE_FAMILY_DATA_STYLE, sDataStyleName, sal_True));
++
++        if (!pStyle)
++        {
++            XMLTableStylesContext* pMyStyles = static_cast<XMLTableStylesContext*>(GetScImport().GetStyles());
++            if (pMyStyles)
++                pStyle = static_cast<const SvXMLNumFormatContext*>(
++                    pMyStyles->FindStyleChildContext(XML_STYLE_FAMILY_DATA_STYLE, sDataStyleName, sal_True));
++            else
++            {
++                DBG_ERROR("not possible to get style");
++            }
++        }
++        if (pStyle)
++            nNumberFormat = const_cast<SvXMLNumFormatContext*>(pStyle)->GetKey();
++    }
++    return nNumberFormat;
++}
++
+ // ----------------------------------------------------------------------------
+ 
+ SvXMLStyleContext *XMLTableStylesContext::CreateStyleStyleChildContext(
+diff --git sc/source/filter/xml/xmlstyli.hxx sc/source/filter/xml/xmlstyli.hxx
+index d1d6166..237e8e3 100644
+--- sc/source/filter/xml/xmlstyli.hxx
++++ sc/source/filter/xml/xmlstyli.hxx
+@@ -154,7 +154,7 @@ public:
+   	void AddProperty(sal_Int16 nContextID, const com::sun::star::uno::Any& aValue);
+     XMLPropertyState* FindProperty(const sal_Int16 nContextID);
+ 
+-	sal_Int32 GetNumberFormat() { return nNumberFormat; }
++	sal_Int32 GetNumberFormat();
+ 
+ private:
+     using XMLPropStyleContext::SetStyle;
 diff --git sc/source/filter/xml/xmltabi.cxx sc/source/filter/xml/xmltabi.cxx
-index 4a0f83e..4dd5a55 100644
+index 6d23650..9137f0f 100644
 --- sc/source/filter/xml/xmltabi.cxx
 +++ sc/source/filter/xml/xmltabi.cxx
 @@ -40,6 +40,7 @@
@@ -8454,7 +9323,7 @@
  // -----------------------------------------------------------------------
  
 diff --git sc/source/ui/docshell/docsh4.cxx sc/source/ui/docshell/docsh4.cxx
-index bc5975d..6701d1c 100644
+index 4894362..857a0dd 100644
 --- sc/source/ui/docshell/docsh4.cxx
 +++ sc/source/ui/docshell/docsh4.cxx
 @@ -123,6 +123,7 @@ using namespace ::com::sun::star;
@@ -8475,10 +9344,10 @@
  
 diff --git sc/source/ui/docshell/externalrefmgr.cxx sc/source/ui/docshell/externalrefmgr.cxx
 new file mode 100644
-index 0000000..20dd943
+index 0000000..9dcb2cc
 --- /dev/null
 +++ sc/source/ui/docshell/externalrefmgr.cxx
-@@ -0,0 +1,1398 @@
+@@ -0,0 +1,1888 @@
 +/*************************************************************************
 + *
 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -8541,6 +9410,7 @@
 +#include "svtools/itemset.hxx"
 +#include "svtools/stritem.hxx"
 +#include "svtools/urihelper.hxx"
++#include "svtools/zformat.hxx"
 +#include "svx/linkmgr.hxx"
 +#include "tools/urlobj.hxx"
 +#include "unotools/ucbhelper.hxx"
@@ -8553,44 +9423,89 @@
 +using ::rtl::OUString;
 +using ::std::vector;
 +using ::std::find;
++using ::std::find_if;
 +using ::std::distance;
++using ::std::pair;
++using ::std::list;
 +
 +#define SRCDOC_LIFE_SPAN     6000       // 1 minute (in 100th of a sec)
 +#define SRCDOC_SCAN_INTERVAL 1000*5     // every 5 seconds (in msec)
 +
-+// ============================================================================
-+
-+ScExternalRefCache::Table::Table()
-+{
-+}
-+
-+ScExternalRefCache::Table::~Table()
-+{
-+}
++namespace {
 +
-+void ScExternalRefCache::Table::setCell(SCROW nRow, SCCOL nCol, TokenRef pToken)
++class TabNameSearchPredicate : ::std::unary_function<bool, ScExternalRefCache::TableName>
 +{
-+    using ::std::pair;
-+    RowsDataType::iterator itrRow = maRows.find(nRow);
-+    if (itrRow == maRows.end())
++public:
++    explicit TabNameSearchPredicate(const String& rSearchName) :
++        maSearchName(ScGlobal::pCharClass->upper(rSearchName))
 +    {
-+        // This row does not exist yet.
-+        pair<RowsDataType::iterator, bool> res = maRows.insert(
-+            RowsDataType::value_type(nRow, RowDataType()));
-+
-+        if (!res.second)
-+            return;
++    }
 +
-+        itrRow = res.first;
++    bool operator()(const ScExternalRefCache::TableName& rTabNameSet) const
++    {
++        // Ok, I'm doing case insensitive search here.
++        return rTabNameSet.maUpperName.Equals(maSearchName);
 +    }
 +
-+    // Insert this token into the specified column location.  I don't need to 
-+    // check for existing data.  Just overwrite it.
-+    RowDataType& rRow = itrRow->second;
-+    rRow.insert(RowDataType::value_type(nCol, pToken));
++private:
++    String maSearchName;
++};
++
++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;
++};
++
++}
++
++// ============================================================================
++
++ScExternalRefCache::Table::Table()
++{
++}
++
++ScExternalRefCache::Table::~Table()
++{
 +}
 +
-+ScExternalRefCache::TokenRef ScExternalRefCache::Table::getCell(SCROW nRow, SCCOL nCol) const
++void ScExternalRefCache::Table::setCell(SCCOL nCol, SCROW nRow, TokenRef pToken, sal_uInt32 nFmtIndex)
++{
++    using ::std::pair;
++    RowsDataType::iterator itrRow = maRows.find(nRow);
++    if (itrRow == maRows.end())
++    {
++        // This row does not exist yet.
++        pair<RowsDataType::iterator, bool> res = maRows.insert(
++            RowsDataType::value_type(nRow, RowDataType()));
++
++        if (!res.second)
++            return;
++
++        itrRow = res.first;
++    }
++
++    // Insert this token into the specified column location.  I don't need to
++    // check for existing data.  Just overwrite it.
++    RowDataType& rRow = itrRow->second;
++    ScExternalRefCache::Cell aCell;
++    aCell.mxToken = pToken;
++    aCell.mnFmtIndex = nFmtIndex;
++    rRow.insert(RowDataType::value_type(nCol, aCell));
++}
++
++ScExternalRefCache::TokenRef ScExternalRefCache::Table::getCell(SCCOL nCol, SCROW nRow, sal_uInt32* pnFmtIndex) const
 +{
 +    RowsDataType::const_iterator itrTable = maRows.find(nRow);
 +    if (itrTable == maRows.end())
@@ -8607,7 +9522,11 @@
 +        return TokenRef();
 +    }
 +
-+    return itrRow->second;
++    const Cell& rCell = itrRow->second;
++    if (pnFmtIndex)
++        *pnFmtIndex = rCell.mnFmtIndex;
++
++    return rCell.mxToken;
 +}
 +
 +void ScExternalRefCache::Table::getAllRows(vector<SCROW>& rRows) const
@@ -8642,6 +9561,21 @@
 +    rCols.swap(aCols);
 +}
 +
++void ScExternalRefCache::Table::getAllNumberFormats(vector<sal_uInt32>& rNumFmts) const
++{
++    RowsDataType::const_iterator itrRow = maRows.begin(), itrRowEnd = maRows.end();
++    for (; itrRow != itrRowEnd; ++itrRow)
++    {
++        const RowDataType& rRowData = itrRow->second;
++        RowDataType::const_iterator itrCol = rRowData.begin(), itrColEnd = rRowData.end();
++        for (; itrCol != itrColEnd; ++itrCol)
++        {
++            const Cell& rCell = itrCol->second;
++            rNumFmts.push_back(rCell.mnFmtIndex);
++        }
++    }
++}
++
 +// ----------------------------------------------------------------------------
 +
 +ScExternalRefCache::TableName::TableName(const String& rUpper, const String& rReal) :
@@ -8651,6 +9585,13 @@
 +
 +// ----------------------------------------------------------------------------
 +
++ScExternalRefCache::CellFormat::CellFormat() :
++    mbIsSet(false), mnType(NUMBERFORMAT_ALL), mnIndex(0)
++{
++}
++
++// ----------------------------------------------------------------------------
++
 +ScExternalRefCache::ScExternalRefCache()
 +{
 +}
@@ -8698,7 +9639,8 @@
 +    return &itr->second;
 +}
 +
-+ScExternalRefCache::TokenRef ScExternalRefCache::getCellData(sal_uInt16 nFileId, const String& rTabName, SCROW nRow, SCCOL nCol)
++ScExternalRefCache::TokenRef ScExternalRefCache::getCellData(
++    sal_uInt16 nFileId, const String& rTabName, SCROW nRow, SCCOL nCol, sal_uInt32* pnFmtIndex)
 +{
 +    DocDataType::const_iterator itrDoc = maDocs.find(nFileId);
 +    if (itrDoc == maDocs.end())
@@ -8722,7 +9664,7 @@
 +        // the table data is not instantiated yet.
 +        return TokenRef();
 +    }
-+    return pTableData->getCell(nRow, nCol);
++    return pTableData->getCell(nCol, nRow, pnFmtIndex);
 +}
 +
 +ScExternalRefCache::TokenArrayRef ScExternalRefCache::getCellRangeData(sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange)
@@ -8774,7 +9716,7 @@
 +        {
 +            for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
 +            {
-+                ScToken* pToken = pTab->getCell(nRow, nCol).get();
++                ScToken* pToken = pTab->getCell(nCol, nRow).get();
 +                if (!pToken)
 +                    return TokenArrayRef();
 +
@@ -8833,7 +9775,8 @@
 +    pDoc->maRealRangeNameMap.insert(NamePairMap::value_type(aUpperName, rName));
 +}
 +
-+void ScExternalRefCache::setCellData(sal_uInt16 nFileId, const String& rTabName, SCROW nRow, SCCOL nCol, TokenRef pToken)
++void ScExternalRefCache::setCellData(sal_uInt16 nFileId, const String& rTabName, SCROW nRow, SCCOL nCol, 
++                                     TokenRef pToken, sal_uInt32 nFmtIndex)
 +{
 +    if (!isDocInitialized(nFileId))
 +        return;
@@ -8844,7 +9787,7 @@
 +        return;
 +
 +    DocItem& rDoc = *pDocItem;
-+    
++
 +    // See if the table by this name already exists.
 +    TableNameIndexMap::iterator itrTabName = rDoc.maTableNameIndex.find(
 +        ScGlobal::pCharClass->upper(rTabName));
@@ -8856,7 +9799,7 @@
 +    if (!pTableData.get())
 +        pTableData.reset(new Table);
 +
-+    pTableData->setCell(nRow, nCol, pToken);
++    pTableData->setCell(nCol, nRow, pToken, nFmtIndex);
 +}
 +
 +void ScExternalRefCache::setCellRangeData(sal_uInt16 nFileId, const ScRange& rRange, const vector<SingleRangeData>& rData,
@@ -8909,7 +9852,7 @@
 +                else
 +                    pToken.reset(new ScEmptyCellToken(false, false));
 +
-+                pTabData->setCell(nRow, nCol, pToken);
++                pTabData->setCell(nCol, nRow, pToken);
 +            }
 +        }
 +    }
@@ -8944,7 +9887,7 @@
 +
 +    size_t n = rTabNames.size();
 +
-+    // table name list - the list must include all table names in the source 
++    // table name list - the list must include all table names in the source
 +    // document and only to be populated when loading the source document, not
 +    // when loading cached data from, say, Excel XCT/CRN records.
 +    vector<TableName> aNewTabNames;
@@ -8956,8 +9899,8 @@
 +        aNewTabNames.push_back(aNameItem);
 +    }
 +    pDoc->maTableNames.swap(aNewTabNames);
-+    
-+    // data tables - preserve any existing data that may have been set during 
++
++    // data tables - preserve any existing data that may have been set during
 +    // file import.
 +    vector<TableTypeRef> aNewTables(n);
 +    for (size_t i = 0; i < n; ++i)
@@ -8979,6 +9922,14 @@
 +    pDoc->mbInitFromSource = true;
 +}
 +
++String ScExternalRefCache::getTableName(sal_uInt16 nFileId, size_t nCacheId) const
++{
++    if( DocItem* pDoc = getDocItem( nFileId ) )
++        if( nCacheId < pDoc->maTableNames.size() )
++            return pDoc->maTableNames[ nCacheId ].maRealName;
++    return EMPTY_STRING;
++}
++
 +void ScExternalRefCache::getAllTableNames(sal_uInt16 nFileId, vector<String>& rTabNames) const
 +{
 +    rTabNames.clear();
@@ -8993,7 +9944,63 @@
 +        rTabNames.push_back(itr->maRealName);
 +}
 +
-+ScExternalRefCache::TableTypeRef ScExternalRefCache::getCacheTable(sal_uInt16 nFileId, const String& rTabName, bool bCreateNew)
++void ScExternalRefCache::getAllNumberFormats(vector<sal_uInt32>& rNumFmts) const
++{
++    using ::std::sort;
++    using ::std::unique;
++
++    vector<sal_uInt32> aNumFmts;
++    for (DocDataType::const_iterator itrDoc = maDocs.begin(), itrDocEnd = maDocs.end();
++          itrDoc != itrDocEnd; ++itrDoc)
++    {
++        const vector<TableTypeRef>& rTables = itrDoc->second.maTables;
++        for (vector<TableTypeRef>::const_iterator itrTab = rTables.begin(), itrTabEnd = rTables.end();
++              itrTab != itrTabEnd; ++itrTab)
++        {
++            TableTypeRef pTab = *itrTab;
++            if (!pTab)
++                continue;
++
++            pTab->getAllNumberFormats(aNumFmts);
++        }
++    }
++
++    // remove duplicates.
++    sort(aNumFmts.begin(), aNumFmts.end());
++    aNumFmts.erase(unique(aNumFmts.begin(), aNumFmts.end()), aNumFmts.end());
++    rNumFmts.swap(aNumFmts);
++}
++
++bool ScExternalRefCache::hasCacheTable(sal_uInt16 nFileId, const String& rTabName) const
++{
++    DocItem* pDoc = getDocItem(nFileId);
++    if (!pDoc)
++        return false;
++
++    String aUpperName = ScGlobal::pCharClass->upper(rTabName);
++    vector<TableName>::const_iterator itrBeg = pDoc->maTableNames.begin(), itrEnd = pDoc->maTableNames.end();
++    vector<TableName>::const_iterator itr = ::std::find_if(
++        itrBeg, itrEnd, TabNameSearchPredicate(aUpperName));
++
++    return itr != itrEnd;
++}
++
++size_t ScExternalRefCache::getCacheTableCount(sal_uInt16 nFileId) const
++{
++    DocItem* pDoc = getDocItem(nFileId);
++    return pDoc ? pDoc->maTables.size() : 0;
++}
++
++ScExternalRefCache::TableTypeRef ScExternalRefCache::getCacheTable(sal_uInt16 nFileId, size_t nTabIndex) const
++{
++    DocItem* pDoc = getDocItem(nFileId);
++    if (!pDoc || nTabIndex >= pDoc->maTables.size())
++        return TableTypeRef();
++
++    return pDoc->maTables[nTabIndex];
++}
++
++ScExternalRefCache::TableTypeRef ScExternalRefCache::getCacheTable(sal_uInt16 nFileId, const String& rTabName, bool bCreateNew, size_t* pnIndex)
 +{
 +    DocItem* pDoc = getDocItem(nFileId);
 +    if (!pDoc)
@@ -9004,18 +10011,23 @@
 +    size_t nIndex;
 +    String aTabNameUpper = ScGlobal::pCharClass->upper(rTabName);
 +    if (lcl_getTableDataIndex(rDoc.maTableNameIndex, aTabNameUpper, nIndex))
++    {
 +        // specified table found.
++        if( pnIndex ) *pnIndex = nIndex;
 +        return rDoc.maTables[nIndex];
++    }
 +
 +    if (!bCreateNew)
 +        return TableTypeRef();
 +
 +    // Specified table doesn't exist yet.  Create one.
++    nIndex = rDoc.maTables.size();
++    if( pnIndex ) *pnIndex = nIndex;
 +    TableTypeRef pTab(new Table);
 +    rDoc.maTables.push_back(pTab);
 +    rDoc.maTableNames.push_back(TableName(aTabNameUpper, rTabName));
 +    rDoc.maTableNameIndex.insert(
-+        TableNameIndexMap::value_type(aTabNameUpper, rDoc.maTables.size()-1));
++        TableNameIndexMap::value_type(aTabNameUpper, nIndex));
 +    return pTab;
 +}
 +
@@ -9109,41 +10121,50 @@
 +
 +static ScToken* lcl_convertToToken(ScBaseCell* pCell)
 +{
-+    if (!pCell)
-+        return NULL;
++    if (!pCell || pCell->HasEmptyData())
++    {
++        bool bInherited = (pCell && pCell->GetCellType() == CELLTYPE_FORMULA);
++        return new ScEmptyCellToken( bInherited, false);
++    }
 +
 +    switch (pCell->GetCellType())
 +    {
++        case CELLTYPE_EDIT:
++        {
++            String aStr;
++            static_cast<ScEditCell*>(pCell)->GetString(aStr);
++            return new ScStringToken(aStr);
++        }
++        break;
 +        case CELLTYPE_STRING:
 +        {
 +            String aStr;
 +            static_cast<ScStringCell*>(pCell)->GetString(aStr);
-+            ScStringToken aToken(aStr);
-+            return aToken.Clone();
++            return new ScStringToken(aStr);
 +        }
 +        break;
 +        case CELLTYPE_VALUE:
 +        {
 +            double fVal = static_cast<ScValueCell*>(pCell)->GetValue();
-+            ScDoubleToken aToken(fVal);
-+            return aToken.Clone();
++            return new ScDoubleToken(fVal);
 +        }
 +        break;
 +        case CELLTYPE_FORMULA:
 +        {
 +            ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell);
-+            if (pFCell->IsValue())
++            USHORT nError = pFCell->GetErrCode();
++            if (nError)
++                return new ScErrorToken( nError);
++            else if (pFCell->IsValue())
 +            {
 +                double fVal = pFCell->GetValue();
-+                ScDoubleToken aToken(fVal);
-+                return aToken.Clone();
++                return new ScDoubleToken(fVal);
 +            }
 +            else
 +            {
 +                String aStr;
 +                pFCell->GetString(aStr);
-+                ScStringToken aToken(aStr);
-+                return aToken.Clone();
++                return new ScStringToken(aStr);
 +            }
 +        }
 +        break;
@@ -9154,7 +10175,7 @@
 +    return NULL;
 +}
 +
-+static ScTokenArray* lcl_convertToTokenArray(ScDocument* pSrcDoc, const ScRange& rRange, 
++static ScTokenArray* lcl_convertToTokenArray(ScDocument* pSrcDoc, const ScRange& rRange,
 +                                             vector<ScExternalRefCache::SingleRangeData>& rCacheData)
 +{
 +    const ScAddress& s = rRange.aStart;
@@ -9164,9 +10185,17 @@
 +    SCCOL nCol1 = s.Col(), nCol2 = e.Col();
 +    SCROW nRow1 = s.Row(), nRow2 = e.Row();
 +
++    if (nTab2 != nTab1)
++        // For now, we don't support multi-sheet ranges intentionally because
++        // we don't have a way to express them in a single token.  In the
++        // future we can introduce a new stack variable type svMatrixList with
++        // a new token type that can store a 3D matrix value and convert a 3D
++        // range to it.
++        return NULL;
++
 +    auto_ptr<ScTokenArray> pArray(new ScTokenArray);
 +    bool bFirstTab = true;
-+    vector<ScExternalRefCache::SingleRangeData>::iterator 
++    vector<ScExternalRefCache::SingleRangeData>::iterator
 +        itrCache = rCacheData.begin(), itrCacheEnd = rCacheData.end();
 +    for (SCTAB nTab = nTab1; nTab <= nTab2 && itrCache != itrCacheEnd; ++nTab, ++itrCache)
 +    {
@@ -9181,10 +10210,19 @@
 +                SCSIZE nC = nCol - nCol1, nR = nRow - nRow1;
 +                ScBaseCell* pCell;
 +                pSrcDoc->GetCell(nCol, nRow, nTab, pCell);
-+                if (pCell)
++                if (!pCell || pCell->HasEmptyData())
++                    xMat->PutEmpty(nC, nR);
++                else
 +                {
 +                    switch (pCell->GetCellType())
 +                    {
++                        case CELLTYPE_EDIT:
++                        {
++                            String aStr;
++                            static_cast<ScEditCell*>(pCell)->GetString(aStr);
++                            xMat->PutString(aStr, nC, nR);
++                        }
++                        break;
 +                        case CELLTYPE_STRING:
 +                        {
 +                            String aStr;
@@ -9201,7 +10239,10 @@
 +                        case CELLTYPE_FORMULA:
 +                        {
 +                            ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell);
-+                            if (pFCell->IsValue())
++                            USHORT nError = pFCell->GetErrCode();
++                            if (nError)
++                                xMat->PutDouble( CreateDoubleError( nError), nC, nR);
++                            else if (pFCell->IsValue())
 +                            {
 +                                double fVal = pFCell->GetValue();
 +                                xMat->PutDouble(fVal, nC, nR);
@@ -9218,10 +10259,6 @@
 +                            DBG_ERROR("attempted to convert an unknown cell type.");
 +                    }
 +                }
-+                else
-+                {
-+                    xMat->PutEmpty(nC, nR);
-+                }
 +            }
 +        }
 +        if (!bFirstTab)
@@ -9250,9 +10287,269 @@
 +    clear();
 +}
 +
-+ScExternalRefCache::TableTypeRef ScExternalRefManager::getCacheTable(sal_uInt16 nFileId, const String& rTabName, bool bCreateNew)
++String ScExternalRefManager::getCacheTableName(sal_uInt16 nFileId, size_t nTabIndex) const
++{
++    return maRefCache.getTableName(nFileId, nTabIndex);
++}
++
++ScExternalRefCache::TableTypeRef ScExternalRefManager::getCacheTable(sal_uInt16 nFileId, size_t nTabIndex) const
++{
++    return maRefCache.getCacheTable(nFileId, nTabIndex);
++}
++
++ScExternalRefCache::TableTypeRef ScExternalRefManager::getCacheTable(sal_uInt16 nFileId, const String& rTabName, bool bCreateNew, size_t* pnIndex)
++{
++    return maRefCache.getCacheTable(nFileId, rTabName, bCreateNew, pnIndex);
++}
++
++// ============================================================================
++
++ScExternalRefManager::RefCells::TabItem::TabItem(SCTAB nIndex) :
++    mnIndex(nIndex)
++{
++}
++
++ScExternalRefManager::RefCells::TabItem::TabItem(const TabItem& r) :
++    mnIndex(r.mnIndex),
++    maCols(r.maCols)
++{
++}
++
++ScExternalRefManager::RefCells::RefCells()
++{
++}
++
++ScExternalRefManager::RefCells::~RefCells()
++{
++}
++
++list<ScExternalRefManager::RefCells::TabItemRef>::iterator ScExternalRefManager::RefCells::getTabPos(SCTAB nTab)
++{
++    list<TabItemRef>::iterator itr = maTables.begin(), itrEnd = maTables.end();
++    for (; itr != itrEnd; ++itr)
++        if ((*itr)->mnIndex >= nTab)
++            return itr;
++    // Not found.  return the end position.
++    return itrEnd;
++}
++
++void ScExternalRefManager::RefCells::insertCell(const ScAddress& rAddr)
++{
++    SCTAB nTab = rAddr.Tab();
++    SCCOL nCol = rAddr.Col();
++    SCROW nRow = rAddr.Row();
++
++    // Search by table index.
++    list<TabItemRef>::iterator itrTab = getTabPos(nTab);
++    TabItemRef xTabRef;
++    if (itrTab == maTables.end())
++    {
++        // All previous tables come before the specificed table.
++        xTabRef.reset(new TabItem(nTab));
++        maTables.push_back(xTabRef);
++    }
++    else if ((*itrTab)->mnIndex > nTab)
++    {
++        // Insert at the current iterator position.
++        xTabRef.reset(new TabItem(nTab));
++        maTables.insert(itrTab, xTabRef);
++    }
++    else if ((*itrTab)->mnIndex == nTab)
++    {
++        // The table found.
++        xTabRef = *itrTab;
++    }
++    ColSet& rCols = xTabRef->maCols;
++
++    // Then by column index.
++    ColSet::iterator itrCol = rCols.find(nCol);
++    if (itrCol == rCols.end())
++    {
++        RowSet aRows;
++        pair<ColSet::iterator, bool> r = rCols.insert(ColSet::value_type(nCol, aRows));
++        if (!r.second)
++            // column insertion failed.
++            return;
++        itrCol = r.first;
++    }
++    RowSet& rRows = itrCol->second;
++
++    // Finally, insert the row index.
++    rRows.insert(nRow);
++}
++
++void ScExternalRefManager::RefCells::removeCell(const ScAddress& rAddr)
 +{
-+    return maRefCache.getCacheTable(nFileId, rTabName, bCreateNew);
++    SCTAB nTab = rAddr.Tab();
++    SCCOL nCol = rAddr.Col();
++    SCROW nRow = rAddr.Row();
++
++    // Search by table index.
++    list<TabItemRef>::iterator itrTab = getTabPos(nTab);
++    if (itrTab == maTables.end() || (*itrTab)->mnIndex != nTab)
++        // No such table.
++        return;
++
++    ColSet& rCols = (*itrTab)->maCols;
++
++    // Then by column index.
++    ColSet::iterator itrCol = rCols.find(nCol);
++    if (itrCol == rCols.end())
++        // No such column
++        return;
++
++    RowSet& rRows = itrCol->second;
++    rRows.erase(nRow);
++}
++
++void ScExternalRefManager::RefCells::moveTable(SCTAB nOldTab, SCTAB nNewTab, bool bCopy)
++{
++    if (nOldTab == nNewTab)
++        // Nothing to do here.
++        return;
++
++    list<TabItemRef>::iterator itrOld = getTabPos(nOldTab);
++    if (itrOld == maTables.end() || (*itrOld)->mnIndex != nOldTab)
++        // No table to move or copy.
++        return;
++
++    list<TabItemRef>::iterator itrNew = getTabPos(nNewTab);
++    if (bCopy)
++    {
++        // Simply make a duplicate of the original table, insert it at the 
++        // new tab position, and increment the table index for all tables
++        // that come after that inserted table.
++
++        TabItemRef xNewTab(new TabItem(*(*itrOld)));
++        xNewTab->mnIndex = nNewTab;
++        maTables.insert(itrNew, xNewTab);
++        list<TabItemRef>::iterator itr = itrNew, itrEnd = maTables.end();
++        for (++itr; itr != itrEnd; ++itr)
++            (*itr)->mnIndex += 1;
++    }
++    else
++    {
++        if (itrOld == itrNew)
++        {
++            // No need to move the table.  Just update the table index.
++            (*itrOld)->mnIndex = nNewTab;
++            return;
++        }
++
++        if (nOldTab < nNewTab)
++        {
++            // Iterate from the old tab position to the new tab position (not
++            // inclusive of the old tab itself), and decrement their tab
++            // index by one.
++            list<TabItemRef>::iterator itr = itrOld;
++            for (++itr; itr != itrNew; ++itr)
++                (*itr)->mnIndex -= 1;
++
++            // Insert a duplicate of the original table.  This does not
++            // invalidate the iterators.
++            (*itrOld)->mnIndex = nNewTab - 1;
++            if (itrNew == maTables.end())
++                maTables.push_back(*itrOld);
++            else
++                maTables.insert(itrNew, *itrOld);
++
++            // Remove the original table.
++            maTables.erase(itrOld);
++        }
++        else
++        {
++            // nNewTab < nOldTab
++
++            // Iterate from the new tab position to the one before the old tab
++            // position, and increment their tab index by one.
++            list<TabItemRef>::iterator itr = itrNew;
++            for (++itr; itr != itrOld; ++itr)
++                (*itr)->mnIndex += 1;
++
++            (*itrOld)->mnIndex = nNewTab;
++            maTables.insert(itrNew, *itrOld);
++
++            // Remove the original table.
++            maTables.erase(itrOld);
++        }
++    }
++}
++
++void ScExternalRefManager::RefCells::insertTable(SCTAB nPos)
++{
++    TabItemRef xNewTab(new TabItem(nPos));
++    list<TabItemRef>::iterator itr = getTabPos(nPos);
++    if (itr == maTables.end())
++        maTables.push_back(xNewTab);
++    else
++        maTables.insert(itr, xNewTab);
++}
++
++void ScExternalRefManager::RefCells::removeTable(SCTAB nPos)
++{
++    list<TabItemRef>::iterator itr = getTabPos(nPos);
++    if (itr == maTables.end())
++        // nothing to remove.
++        return;
++
++    maTables.erase(itr);
++}
++
++void ScExternalRefManager::RefCells::refreshAllCells(ScExternalRefManager& rRefMgr)
++{
++    // Get ALL the cell positions for re-compilation.
++    for (list<TabItemRef>::iterator itrTab = maTables.begin(), itrTabEnd = maTables.end();
++          itrTab != itrTabEnd; ++itrTab)
++    {
++        SCTAB nTab = (*itrTab)->mnIndex;
++        ColSet& rCols = (*itrTab)->maCols;
++        for (ColSet::iterator itrCol = rCols.begin(), itrColEnd = rCols.end(); 
++              itrCol != itrColEnd; ++itrCol)
++        {
++            SCCOL nCol = itrCol->first;
++            RowSet& rRows = itrCol->second;
++            RowSet aNewRows;
++            for (RowSet::iterator itrRow = rRows.begin(), itrRowEnd = rRows.end();
++                  itrRow != itrRowEnd; ++itrRow)
++            {
++                SCROW nRow = *itrRow;
++                ScAddress aCell(nCol, nRow, nTab);
++                if (rRefMgr.compileTokensByCell(aCell))
++                    // This cell still contains an external refernce.
++                    aNewRows.insert(nRow);
++            }
++            // Update the rows so that cells with no external references are 
++            // no longer tracked.
++            rRows.swap(aNewRows);
++        }
++    }
++}
++
++// ----------------------------------------------------------------------------
++
++void ScExternalRefManager::getAllCachedTableNames(sal_uInt16 nFileId, vector<String>& rTabNames) const
++{
++    maRefCache.getAllTableNames(nFileId, rTabNames);
++}
++
++void ScExternalRefManager::getAllCachedNumberFormats(vector<sal_uInt32>& rNumFmts) const
++{
++    maRefCache.getAllNumberFormats(rNumFmts);
++}
++
++bool ScExternalRefManager::hasCacheTable(sal_uInt16 nFileId, const String& rTabName) const
++{
++    return maRefCache.hasCacheTable(nFileId, rTabName);
++}
++
++size_t ScExternalRefManager::getCacheTableCount(sal_uInt16 nFileId) const
++{
++    return maRefCache.getCacheTableCount(nFileId);
++}
++
++sal_uInt16 ScExternalRefManager::getExternalFileCount() const
++{
++    return static_cast< sal_uInt16 >( maSrcFiles.size() );
 +}
 +
 +void ScExternalRefManager::storeRangeNameTokens(sal_uInt16 nFileId, const String& rName, const ScTokenArray& rArray)
@@ -9263,20 +10560,35 @@
 +
 +ScExternalRefCache::TokenRef ScExternalRefManager::getSingleRefToken(
 +    sal_uInt16 nFileId, const String& rTabName, const ScAddress& rCell,
-+    const ScAddress* pCurPos, SCTAB* pTab)
++    const ScAddress* pCurPos, SCTAB* pTab, ScExternalRefCache::CellFormat* pFmt)
 +{
 +    if (pCurPos)
-+        insertReferencingCell(nFileId, *pCurPos);
++        insertRefCell(nFileId, *pCurPos);
 +
 +    maybeLinkExternalFile(nFileId);
 +
 +    if (pTab)
 +        *pTab = -1;
 +
++    if (pFmt)
++        pFmt->mbIsSet = false;
++
 +    // Check if the given table name and the cell position is cached.
-+    ScExternalRefCache::TokenRef pToken = maRefCache.getCellData(nFileId, rTabName, rCell.Row(), rCell.Col());
-+    if (pToken.get())
-+    {
++    sal_uInt32 nFmtIndex = 0;
++    ScExternalRefCache::TokenRef pToken = maRefCache.getCellData(
++        nFileId, rTabName, rCell.Row(), rCell.Col(), &nFmtIndex);
++    if (pToken)
++    {
++        if (pFmt)
++        {
++            short nFmtType = mpDoc->GetFormatTable()->GetType(nFmtIndex);
++            if (nFmtType != NUMBERFORMAT_UNDEFINED)
++            {
++                pFmt->mbIsSet = true;
++                pFmt->mnIndex = nFmtIndex;
++                pFmt->mnType = nFmtType;
++            }
++        }
 +        return pToken;
 +    }
 +
@@ -9299,23 +10611,36 @@
 +        *pTab = nTab;
 +
 +    pSrcDoc->GetCell(rCell.Col(), rCell.Row(), nTab, pCell);
-+    TokenRef pTok(lcl_convertToToken(pCell));
++    ScExternalRefCache::TokenRef pTok(lcl_convertToToken(pCell));
++
++    pSrcDoc->GetNumberFormat(rCell.Col(), rCell.Row(), nTab, nFmtIndex);
++    nFmtIndex = getMappedNumberFormat(nFileId, nFmtIndex, pSrcDoc);
++    if (pFmt)
++    {
++        short nFmtType = mpDoc->GetFormatTable()->GetType(nFmtIndex);
++        if (nFmtType != NUMBERFORMAT_UNDEFINED)
++        {
++            pFmt->mbIsSet = true;
++            pFmt->mnIndex = nFmtIndex;
++            pFmt->mnType = nFmtType;
++        }
++    }
 +
 +    if (!pTok.get())
 +    {
-+        // Cell in the source document is probably empty.
-+        pTok.reset(new ScEmptyCellToken(false, false));
++        // Generate an error for unresolvable cells.
++        pTok.reset( new ScErrorToken( errNoValue));
 +    }
 +
 +    // Now, insert the token into cache table.
-+    maRefCache.setCellData(nFileId, rTabName, rCell.Row(), rCell.Col(), pTok);
++    maRefCache.setCellData(nFileId, rTabName, rCell.Row(), rCell.Col(), pTok, nFmtIndex);
 +    return pTok;
 +}
 +
 +ScExternalRefCache::TokenArrayRef ScExternalRefManager::getDoubleRefTokens(sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange, const ScAddress* pCurPos)
 +{
 +    if (pCurPos)
-+        insertReferencingCell(nFileId, *pCurPos);
++        insertRefCell(nFileId, *pCurPos);
 +
 +    maybeLinkExternalFile(nFileId);
 +
@@ -9358,8 +10683,9 @@
 +    ScExternalRefCache::TokenArrayRef pArray;
 +    pArray.reset(lcl_convertToTokenArray(pSrcDoc, aRange, aCacheData));
 +
-+    // Cache these values.
-+    maRefCache.setCellRangeData(nFileId, rRange, aCacheData, pArray);
++    if (pArray)
++        // Cache these values.
++        maRefCache.setCellRangeData(nFileId, rRange, aCacheData, pArray);
 +
 +    return pArray;
 +}
@@ -9367,7 +10693,7 @@
 +ScExternalRefCache::TokenArrayRef ScExternalRefManager::getRangeNameTokens(sal_uInt16 nFileId, const String& rName, const ScAddress* pCurPos)
 +{
 +    if (pCurPos)
-+        insertReferencingCell(nFileId, *pCurPos);
++        insertRefCell(nFileId, *pCurPos);
 +
 +    maybeLinkExternalFile(nFileId);
 +
@@ -9390,12 +10716,12 @@
 +    if (!pRangeData)
 +        return ScExternalRefCache::TokenArrayRef();
 +
-+    // Parse all tokens in this external range data, and replace each absolute 
++    // Parse all tokens in this external range data, and replace each absolute
 +    // reference token with an external reference token, and cache them.  Also
 +    // register the source document with the link manager if it's a new
 +    // source.
 +
-+    TokenArrayRef pNew(new ScTokenArray);
++    ScExternalRefCache::TokenArrayRef pNew(new ScTokenArray);
 +
 +    ScTokenArray* pCode = pRangeData->GetCode();
 +    for (ScToken* pToken = pCode->First(); pToken; pToken = pCode->Next())
@@ -9426,7 +10752,7 @@
 +            default:
 +                ; // nothing to do
 +        }
-+        
++
 +        if (!bTokenAdded)
 +            pNew->AddToken(*pToken);
 +    }
@@ -9436,22 +10762,14 @@
 +    return pNew;
 +}
 +
-+void ScExternalRefManager::refreshAllReferencingCells(sal_uInt16 nFileId)
++void ScExternalRefManager::refreshAllRefCells(sal_uInt16 nFileId)
 +{
-+    RefCellMap::iterator itr = maRefCells.find(nFileId);
-+    if (itr == maRefCells.end())
++    RefCellMap::iterator itrFile = maRefCells.find(nFileId);
++    if (itrFile == maRefCells.end())
 +        return;
 +
-+    RefCellSet aNewSet;
-+    RefCellSet& rSet = itr->second;
-+    RefCellSet::const_iterator itrSet = rSet.begin(), itrSetEnd = rSet.end();
-+    for (; itrSet != itrSetEnd; ++itrSet)
-+    {
-+        if (compileTokensByCell(*itrSet))
-+            // Cell still contains an external name/ref token.
-+            aNewSet.insert(*itrSet);
-+    }
-+    rSet.swap(aNewSet);
++    RefCells& rRefCells = itrFile->second;
++    rRefCells.refreshAllCells(*this);
 +
 +    ScViewData* pViewData = ScDocShell::GetViewData();
 +    if (!pViewData)
@@ -9467,22 +10785,28 @@
 +    pVShell->PaintGrid();
 +}
 +
-+void ScExternalRefManager::insertReferencingCell(sal_uInt16 nFileId, const ScAddress& rCell)
++void ScExternalRefManager::insertRefCell(sal_uInt16 nFileId, const ScAddress& rCell)
 +{
 +    RefCellMap::iterator itr = maRefCells.find(nFileId);
-+    if (itr != maRefCells.end())
++    if (itr == maRefCells.end())
 +    {
-+        itr->second.insert(rCell);
-+        return;
-+    }
++        RefCells aRefCells;
++        pair<RefCellMap::iterator, bool> r = maRefCells.insert(
++            RefCellMap::value_type(nFileId, aRefCells));
++        if (!r.second)
++            // insertion failed.
++            return;
 +
-+    RefCellSet aSet;
-+    aSet.insert(rCell);
-+    maRefCells.insert(RefCellMap::value_type(nFileId, aSet));
++        itr = r.first;
++    }
++    itr->second.insertCell(rCell);
 +}
 +
 +ScDocument* ScExternalRefManager::getSrcDocument(sal_uInt16 nFileId)
 +{
++    if (!mpDoc->IsExecuteLinkEnabled())
++        return NULL;
++
 +    DocShellMap::iterator itrEnd = maDocShells.end();
 +    DocShellMap::iterator itr = maDocShells.find(nFileId);
 +
@@ -9543,7 +10867,7 @@
 +    String aFile = pFileData->maFileName;
 +    if (!isFileLoadable(aFile))
 +    {
-+        // The original file path is not loadable.  Try the relative path.  
++        // The original file path is not loadable.  Try the relative path.
 +        // Note that the path is relative to the content.xml substream which
 +        // is one-level higher than the file itself.
 +
@@ -9697,30 +11021,8 @@
 +    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<SrcFileData>::const_iterator itrBeg = maSrcFiles.begin(), itrEnd = maSrcFiles.end();
 +    vector<SrcFileData>::const_iterator itr = find_if(itrBeg, itrEnd, FindSrcFileByName(rFile));
 +    if (itr != itrEnd)
@@ -9743,6 +11045,18 @@
 +    return &maSrcFiles[nFileId].maFileName;
 +}
 +
++bool ScExternalRefManager::hasExternalFile(sal_uInt16 nFileId) const
++{
++    return nFileId < maSrcFiles.size();
++}
++
++bool ScExternalRefManager::hasExternalFile(const String& rFile) const
++{
++    vector<SrcFileData>::const_iterator itrBeg = maSrcFiles.begin(), itrEnd = maSrcFiles.end();
++    vector<SrcFileData>::const_iterator itr = find_if(itrBeg, itrEnd, FindSrcFileByName(rFile));
++    return itr != itrEnd;
++}
++
 +const ScExternalRefManager::SrcFileData* ScExternalRefManager::getExternalFileData(sal_uInt16 nFileId) const
 +{
 +    if (nFileId >= maSrcFiles.size())
@@ -9761,16 +11075,6 @@
 +    return maRefCache.getRealRangeName(nFileId, rRangeName);
 +}
 +
-+void ScExternalRefManager::getAllCachedTableNames(sal_uInt16 nFileId, vector<String>& rTabNames) const
-+{
-+    maRefCache.getAllTableNames(nFileId, rTabNames);
-+}
-+
-+sal_uInt16 ScExternalRefManager::getCachedFileCount() const
-+{
-+    return static_cast<sal_uInt16>(maSrcFiles.size());
-+}
-+
 +template<typename MapContainer>
 +static void lcl_removeByFileId(sal_uInt16 nFileId, MapContainer& rMap)
 +{
@@ -9784,7 +11088,7 @@
 +    removeSrcDocument(nFileId, false);
 +
 +    // Update all cells containing names from this source document.
-+    refreshAllReferencingCells(nFileId);
++    refreshAllRefCells(nFileId);
 +}
 +
 +void ScExternalRefManager::switchSrcFile(sal_uInt16 nFileId, const String& rNewFile)
@@ -9852,6 +11156,34 @@
 +    }
 +}
 +
++void ScExternalRefManager::updateRefCell(const ScAddress& rOldPos, const ScAddress& rNewPos, bool bCopy)
++{
++    for (RefCellMap::iterator itr = maRefCells.begin(), itrEnd = maRefCells.end(); itr != itrEnd; ++itr)
++    {
++        if (!bCopy)
++            itr->second.removeCell(rOldPos);
++        itr->second.insertCell(rNewPos);
++    }
++}
++
++void ScExternalRefManager::updateRefMoveTable(SCTAB nOldTab, SCTAB nNewTab, bool bCopy)
++{
++    for (RefCellMap::iterator itr = maRefCells.begin(), itrEnd = maRefCells.end(); itr != itrEnd; ++itr)
++        itr->second.moveTable(nOldTab, nNewTab, bCopy);
++}
++
++void ScExternalRefManager::updateRefInsertTable(SCTAB nPos)
++{
++    for (RefCellMap::iterator itr = maRefCells.begin(), itrEnd = maRefCells.end(); itr != itrEnd; ++itr)
++        itr->second.insertTable(nPos);
++}
++
++void ScExternalRefManager::updateRefDeleteTable(SCTAB nPos)
++{
++    for (RefCellMap::iterator itr = maRefCells.begin(), itrEnd = maRefCells.end(); itr != itrEnd; ++itr)
++        itr->second.removeTable(nPos);
++}
++
 +void ScExternalRefManager::purgeStaleSrcDocument(sal_Int32 nTimeOut)
 +{
 +    DocShellMap aNewDocShells;
@@ -9859,7 +11191,7 @@
 +    for (; itr != itrEnd; ++itr)
 +    {
 +        // in 100th of a second.
-+        sal_Int32 nSinceLastAccess = (Time() - itr->second.maLastAccess).GetTime(); 
++        sal_Int32 nSinceLastAccess = (Time() - itr->second.maLastAccess).GetTime();
 +        if (nSinceLastAccess < nTimeOut)
 +            aNewDocShells.insert(*itr);
 +    }
@@ -9869,6 +11201,33 @@
 +        maSrcDocTimer.Stop();
 +}
 +
++sal_uInt32 ScExternalRefManager::getMappedNumberFormat(sal_uInt16 nFileId, sal_uInt32 nNumFmt, ScDocument* pSrcDoc)
++{
++    NumFmtMap::iterator itr = maNumFormatMap.find(nFileId);
++    if (itr == maNumFormatMap.end())
++    {
++        // Number formatter map is not initialized for this external document.
++        pair<NumFmtMap::iterator, bool> r = maNumFormatMap.insert(
++            NumFmtMap::value_type(nFileId, SvNumberFormatterMergeMap()));
++
++        if (!r.second)
++            // insertion failed.
++            return nNumFmt;
++
++        itr = r.first;
++        mpDoc->GetFormatTable()->MergeFormatter( *pSrcDoc->GetFormatTable());
++        SvNumberFormatterMergeMap aMap = mpDoc->GetFormatTable()->ConvertMergeTableToMap();
++        itr->second.swap(aMap);
++    }
++    const SvNumberFormatterMergeMap& rMap = itr->second;
++    SvNumberFormatterMergeMap::const_iterator itrNumFmt = rMap.find(nNumFmt);
++    if (itrNumFmt != rMap.end())
++        // mapped value found.
++        return itrNumFmt->second;
++
++    return nNumFmt;
++}
++
 +IMPL_LINK(ScExternalRefManager, TimeOutHdl, AutoTimer*, pTimer)
 +{
 +    if (pTimer == &maSrcDocTimer)
@@ -9913,11 +11272,62 @@
          $(SLO)$/tablink.obj   	\
          $(SLO)$/arealink.obj   	\
          $(SLO)$/dbdocfun.obj 	\
+diff --git sc/source/ui/unoobj/cellsuno.cxx sc/source/ui/unoobj/cellsuno.cxx
+index 7e1ec2d..7c0e769 100644
+--- sc/source/ui/unoobj/cellsuno.cxx
++++ sc/source/ui/unoobj/cellsuno.cxx
+@@ -2408,7 +2408,7 @@ void ScCellRangesBase::GetOnePropertyValue( const SfxItemPropertyMap* pMap,
+ 					case ATTR_VALUE_FORMAT:
+ 						{
+ 							ScDocument* pDoc = pDocShell->GetDocument();
+-							
++
+ 							ULONG nOldFormat = ((const SfxUInt32Item&)
+ 									pDataSet->Get( ATTR_VALUE_FORMAT )).GetValue();
+ 							LanguageType eOldLang = ((const SvxLanguageItem&)
+@@ -5176,7 +5176,7 @@ uno::Sequence<sheet::FormulaToken> SAL_CALL ScCellRangeObj::getArrayTokens() thr
+                 {
+                     ScTokenArray* pTokenArray = pFCell1->GetCode();
+                     if ( pTokenArray )
+-                        (void)ScTokenConversion::ConvertToTokenSequence( aSequence, *pTokenArray );
++                        (void)ScTokenConversion::ConvertToTokenSequence( *pDoc, aSequence, *pTokenArray );
+                 }
+             }
+         }
+@@ -5198,8 +5198,9 @@ void SAL_CALL ScCellRangeObj::setArrayTokens( const uno::Sequence<sheet::Formula
+                 throw uno::RuntimeException();
+             }
+ 
++            ScDocument* pDoc = pDocSh->GetDocument();
+             ScTokenArray aTokenArray;
+-            (void)ScTokenConversion::ConvertToTokenArray( aTokenArray, rTokens );
++            (void)ScTokenConversion::ConvertToTokenArray( *pDoc, aTokenArray, rTokens );
+ 
+             // Actually GRAM_PODF_A1 is a don't-care here because of the token
+             // array being set, it fits with other API compatibility grammars
+@@ -6597,7 +6598,7 @@ uno::Sequence<sheet::FormulaToken> SAL_CALL ScCellObj::getTokens() throw(uno::Ru
+         {
+             ScTokenArray* pTokenArray = static_cast<ScFormulaCell*>(pCell)->GetCode();
+             if ( pTokenArray )
+-                (void)ScTokenConversion::ConvertToTokenSequence( aSequence, *pTokenArray );
++                (void)ScTokenConversion::ConvertToTokenSequence( *pDoc, aSequence, *pTokenArray );
+         }
+ 	}
+     return aSequence;
+@@ -6611,7 +6612,7 @@ void SAL_CALL ScCellObj::setTokens( const uno::Sequence<sheet::FormulaToken>& rT
+ 	{
+ 	    ScDocument* pDoc = pDocSh->GetDocument();
+ 	    ScTokenArray aTokenArray;
+-	    (void)ScTokenConversion::ConvertToTokenArray( aTokenArray, rTokens );
++        (void)ScTokenConversion::ConvertToTokenArray( *pDoc, aTokenArray, rTokens );
+ 
+         ScDocFunc aFunc( *pDocSh );
+         ScBaseCell* pNewCell = new ScFormulaCell( pDoc, aCellPos, &aTokenArray );
 diff --git sc/source/ui/unoobj/docuno.cxx sc/source/ui/unoobj/docuno.cxx
-index 5a8c983..6a2fabf 100644
+index 875259a..b2e6ee7 100644
 --- sc/source/ui/unoobj/docuno.cxx
 +++ sc/source/ui/unoobj/docuno.cxx
-@@ -123,6 +123,7 @@ const SfxItemPropertyMap* lcl_GetDocOptPropertyMap()
+@@ -124,6 +124,7 @@ const SfxItemPropertyMap* lcl_GetDocOptPropertyMap()
          {MAP_CHAR_LEN(SC_UNO_COLLABELRNG),       0, &getCppuType((uno::Reference<sheet::XLabelRanges>*)0),    0, 0},
          {MAP_CHAR_LEN(SC_UNO_DDELINKS),          0, &getCppuType((uno::Reference<container::XNameAccess>*)0), 0, 0},
          {MAP_CHAR_LEN(SC_UNO_DEFTABSTOP),        0, &getCppuType((sal_Int16*)0),                              0, 0},
@@ -9925,7 +11335,7 @@
          {MAP_CHAR_LEN(SC_UNO_FORBIDDEN),         0, &getCppuType((uno::Reference<i18n::XForbiddenCharacters>*)0), beans::PropertyAttribute::READONLY, 0},
          {MAP_CHAR_LEN(SC_UNO_HASDRAWPAGES),      0, &getBooleanCppuType(),                                    beans::PropertyAttribute::READONLY, 0},
          {MAP_CHAR_LEN(SC_UNO_IGNORECASE),        0, &getBooleanCppuType(),                                    0, 0},
-@@ -1537,6 +1538,10 @@ uno::Any SAL_CALL ScModelObj::getPropertyValue( const rtl::OUString& aPropertyNa
+@@ -1538,6 +1539,10 @@ uno::Any SAL_CALL ScModelObj::getPropertyValue( const rtl::OUString& aPropertyNa
  		{
  			aRet <<= uno::Reference<container::XNameAccess>(new ScDDELinksObj( pDocShell ));
  		}
@@ -9936,17 +11346,56 @@
  		else if ( aString.EqualsAscii( SC_UNO_SHEETLINKS ) )
  		{
  			aRet <<= uno::Reference<container::XNameAccess>(new ScSheetLinksObj( pDocShell ));
+diff --git sc/source/ui/unoobj/fmtuno.cxx sc/source/ui/unoobj/fmtuno.cxx
+index eb9f55b..c41ebe5 100644
+--- sc/source/ui/unoobj/fmtuno.cxx
++++ sc/source/ui/unoobj/fmtuno.cxx
+@@ -197,14 +197,14 @@ void ScTableConditionalFormat::FillFormat( ScConditionalFormat& rFormat,
+         if ( aData.maTokens1.getLength() )
+         {
+             ScTokenArray aTokenArray;
+-            if ( ScTokenConversion::ConvertToTokenArray(aTokenArray, aData.maTokens1) )
++            if ( ScTokenConversion::ConvertToTokenArray(*pDoc, aTokenArray, aData.maTokens1) )
+                 aCoreEntry.SetFormula1(aTokenArray);
+         }
+ 
+         if ( aData.maTokens2.getLength() )
+         {
+             ScTokenArray aTokenArray;
+-            if ( ScTokenConversion::ConvertToTokenArray(aTokenArray, aData.maTokens2) )
++            if ( ScTokenConversion::ConvertToTokenArray(*pDoc, aTokenArray, aData.maTokens2) )
+                 aCoreEntry.SetFormula2(aTokenArray);
+         }
+         rFormat.AddEntry( aCoreEntry );
+@@ -660,14 +660,14 @@ ScValidationData* ScTableValidationObj::CreateValidationData( ScDocument* pDoc,
+     if ( aTokens1.getLength() )
+     {
+         ScTokenArray aTokenArray;
+-        if ( ScTokenConversion::ConvertToTokenArray(aTokenArray, aTokens1) )
++        if ( ScTokenConversion::ConvertToTokenArray(*pDoc, aTokenArray, aTokens1) )
+             pRet->SetFormula1(aTokenArray);
+     }
+ 
+     if ( aTokens2.getLength() )
+     {
+         ScTokenArray aTokenArray;
+-        if ( ScTokenConversion::ConvertToTokenArray(aTokenArray, aTokens2) )
++        if ( ScTokenConversion::ConvertToTokenArray(*pDoc, aTokenArray, aTokens2) )
+             pRet->SetFormula2(aTokenArray);
+     }
+ 
 diff --git sc/source/ui/unoobj/linkuno.cxx sc/source/ui/unoobj/linkuno.cxx
-index 52a5a62..7fb3e01 100644
+index 52a5a62..7131ed4 100644
 --- sc/source/ui/unoobj/linkuno.cxx
 +++ sc/source/ui/unoobj/linkuno.cxx
-@@ -48,8 +48,20 @@
+@@ -48,8 +48,21 @@
  #include "hints.hxx"
  #include "unonames.hxx"
  #include "rangeseq.hxx"
 +#include "token.hxx"
 +
 +#include <vector>
++#include <climits>
  
  using namespace com::sun::star;
 +using ::com::sun::star::uno::Any;
@@ -9961,15 +11410,16 @@
  
  //------------------------------------------------------------------------
  
-@@ -1480,4 +1492,229 @@ uno::Reference< sheet::XDDELink > ScDDELinksObj::addDDELink(
+@@ -1480,4 +1493,327 @@ uno::Reference< sheet::XDDELink > ScDDELinksObj::addDDELink(
      return xLink;
  }
  
 -//------------------------------------------------------------------------
 +// ============================================================================
 +
-+ScExternalSheetCacheObj::ScExternalSheetCacheObj(ScExternalRefCache::TableTypeRef pTable) :
-+    mpTable(pTable)
++ScExternalSheetCacheObj::ScExternalSheetCacheObj(ScExternalRefCache::TableTypeRef pTable, size_t nIndex) :
++    mpTable(pTable),
++    mnIndex(nIndex)
 +{
 +}
 +
@@ -9977,7 +11427,7 @@
 +{
 +}
 +
-+void SAL_CALL ScExternalSheetCacheObj::setCellValue(sal_Int32 nRow, sal_Int32 nCol, const Any& rValue)
++void SAL_CALL ScExternalSheetCacheObj::setCellValue(sal_Int32 nCol, sal_Int32 nRow, const Any& rValue)
 +    throw (IllegalArgumentException, RuntimeException)
 +{
 +    ScUnoGuard aGuard;
@@ -9995,17 +11445,17 @@
 +        // unidentified value type.
 +        return;
 +
-+    mpTable->setCell(static_cast<SCROW>(nRow), static_cast<SCCOL>(nCol), pToken);
++    mpTable->setCell(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), pToken);
 +}
 +
-+Any SAL_CALL ScExternalSheetCacheObj::getCellValue(sal_Int32 nRow, sal_Int32 nCol)
++Any SAL_CALL ScExternalSheetCacheObj::getCellValue(sal_Int32 nCol, sal_Int32 nRow)
 +    throw (IllegalArgumentException, RuntimeException)
 +{
 +    ScUnoGuard aGuard;
 +    if (nRow < 0 || nCol < 0)
 +        throw IllegalArgumentException();
 +
-+    ScToken* pToken = mpTable->getCell(nRow, nCol).get();
++    ScToken* pToken = mpTable->getCell(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow)).get();
 +    if (!pToken)
 +        throw IllegalArgumentException();
 +
@@ -10061,6 +11511,12 @@
 +    return aColsSeq;
 +}
 +
++sal_Int32 SAL_CALL ScExternalSheetCacheObj::getTokenIndex()
++        throw (RuntimeException)
++{
++    return static_cast< sal_Int32 >( mnIndex );
++}
++
 +// ============================================================================
 +
 +ScExternalDocLinkObj::ScExternalDocLinkObj(ScExternalRefManager* pRefMgr, sal_uInt16 nFileId) :
@@ -10077,11 +11533,98 @@
 +        throw (RuntimeException)
 +{
 +    ScUnoGuard aGuard;
-+    ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, aSheetName, true);
-+    Reference< sheet::XExternalSheetCache > aSheetCache(new ScExternalSheetCacheObj(pTable));
++    size_t nIndex = 0;
++    ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, aSheetName, true, &nIndex);
++    Reference< sheet::XExternalSheetCache > aSheetCache(new ScExternalSheetCacheObj(pTable, nIndex));
 +    return aSheetCache;
 +}
 +
++Any SAL_CALL ScExternalDocLinkObj::getByName(const::rtl::OUString &aName)
++        throw (container::NoSuchElementException, lang::WrappedTargetException, RuntimeException)
++{
++    ScUnoGuard aGuard;
++    size_t nIndex = 0;
++    ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, aName, false, &nIndex);
++    if (!pTable)
++        throw container::NoSuchElementException();
++
++    Reference< sheet::XExternalSheetCache > aSheetCache(new ScExternalSheetCacheObj(pTable, nIndex));
++
++    Any aAny;
++    aAny <<= aSheetCache;
++    return aAny;
++}
++
++Sequence< OUString > SAL_CALL ScExternalDocLinkObj::getElementNames()
++        throw (RuntimeException)
++{
++    ScUnoGuard aGuard;
++    vector<String> aTabNames;
++    mpRefMgr->getAllCachedTableNames(mnFileId, aTabNames);
++    size_t n = aTabNames.size();
++    Sequence<OUString> aSeq(n);
++    for (size_t i = 0; i < n; ++i)
++        aSeq[i] = aTabNames[i];
++    return aSeq;
++}
++
++sal_Bool SAL_CALL ScExternalDocLinkObj::hasByName(const OUString &aName)
++        throw (RuntimeException)
++{
++    ScUnoGuard aGuard;
++    return static_cast<sal_Bool>(mpRefMgr->hasCacheTable(mnFileId, aName));
++}
++
++sal_Int32 SAL_CALL ScExternalDocLinkObj::getCount()
++        throw (RuntimeException)
++{
++    ScUnoGuard aGuard;
++    return static_cast<sal_Int32>(mpRefMgr->getCacheTableCount(mnFileId));
++}
++
++Any SAL_CALL ScExternalDocLinkObj::getByIndex(sal_Int32 nIndex)
++        throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException, RuntimeException)
++{
++    ScUnoGuard aGuard;
++    size_t nTabCount = mpRefMgr->getCacheTableCount(mnFileId);
++    if (nIndex < 0 || nIndex >= static_cast<sal_Int32>(nTabCount))
++        throw lang::IndexOutOfBoundsException();
++
++    ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, static_cast<size_t>(nIndex));
++    if (!pTable)
++        throw lang::IndexOutOfBoundsException();
++
++    Reference< sheet::XExternalSheetCache > aSheetCache(new ScExternalSheetCacheObj(pTable, nIndex));
++
++    Any aAny;
++    aAny <<= aSheetCache;
++    return aAny;
++}
++
++Reference< container::XEnumeration > SAL_CALL ScExternalDocLinkObj::createEnumeration()
++        throw (RuntimeException)
++{
++    ScUnoGuard aGuard;
++    Reference< container::XEnumeration > aRef(
++        new ScIndexEnumeration(this, OUString::createFromAscii(
++            "com.sun.star.sheet.ExternalDocLink")));
++    return aRef;
++}
++
++uno::Type SAL_CALL ScExternalDocLinkObj::getElementType()
++        throw (RuntimeException)
++{
++    ScUnoGuard aGuard;
++    return getCppuType(static_cast<Reference<sheet::XExternalDocLink>*>(0));
++}
++
++sal_Bool SAL_CALL ScExternalDocLinkObj::hasElements()
++        throw (RuntimeException)
++{
++    ScUnoGuard aGuard;
++    return static_cast<sal_Bool>(mpRefMgr->getCacheTableCount(mnFileId) > 0);
++}
++
 +sal_Int32 SAL_CALL ScExternalDocLinkObj::getTokenIndex()
 +        throw (RuntimeException)
 +{
@@ -10107,68 +11650,72 @@
 +    ScUnoGuard aGuard;
 +    sal_uInt16 nFileId = mpRefMgr->getExternalFileId(aDocName);
 +    Reference< sheet::XExternalDocLink > aDocLink(new ScExternalDocLinkObj(mpRefMgr, nFileId));
-+    maDocLinks.insert( DocLinkMap::value_type(aDocName, aDocLink) );
-+    maDocNames.push_back(aDocName);
 +    return aDocLink;
 +}
 +
-+Any SAL_CALL ScExternalDocLinksObj::getByName(const::rtl::OUString &aName) 
++Any SAL_CALL ScExternalDocLinksObj::getByName(const::rtl::OUString &aName)
 +        throw (container::NoSuchElementException, lang::WrappedTargetException, RuntimeException)
 +{
 +    ScUnoGuard aGuard;
-+    DocLinkMap::const_iterator itr = maDocLinks.find(aName);
-+    if (itr == maDocLinks.end())
++    if (!mpRefMgr->hasExternalFile(aName))
 +        throw container::NoSuchElementException();
 +
++    sal_uInt16 nFileId = mpRefMgr->getExternalFileId(aName);
++    Reference< sheet::XExternalDocLink > aDocLink(new ScExternalDocLinkObj(mpRefMgr, nFileId));
++
 +    Any aAny;
-+    aAny <<= itr->second;
++    aAny <<= aDocLink;
 +    return aAny;
 +}
 +
-+Sequence< OUString > SAL_CALL ScExternalDocLinksObj::getElementNames() 
++Sequence< OUString > SAL_CALL ScExternalDocLinksObj::getElementNames()
 +        throw (RuntimeException)
 +{
 +    ScUnoGuard aGuard;
-+    size_t n = maDocNames.size();
++    sal_uInt16 n = mpRefMgr->getExternalFileCount();
 +    Sequence<OUString> aSeq(n);
-+    for (size_t i = 0; i < n; ++i)
-+        aSeq[i] = maDocNames[i];
++    for (sal_uInt16 i = 0; i < n; ++i)
++    {
++        const String* pName = mpRefMgr->getExternalFileName(i);
++        aSeq[i] = pName ? *pName : EMPTY_STRING;
++    }
++
 +    return aSeq;
 +}
 +
-+sal_Bool SAL_CALL ScExternalDocLinksObj::hasByName(const OUString &aName) 
++sal_Bool SAL_CALL ScExternalDocLinksObj::hasByName(const OUString &aName)
 +        throw (RuntimeException)
 +{
 +    ScUnoGuard aGuard;
-+    return static_cast<sal_Bool>(maDocLinks.count(aName) > 0);
++    return mpRefMgr->hasExternalFile(aName);
 +}
 +
-+sal_Int32 SAL_CALL ScExternalDocLinksObj::getCount() 
++sal_Int32 SAL_CALL ScExternalDocLinksObj::getCount()
 +        throw (RuntimeException)
 +{
 +    ScUnoGuard aGuard;
-+    return static_cast<sal_Int32>(maDocLinks.size());
++    return mpRefMgr->getExternalFileCount();
 +}
 +
-+Any SAL_CALL ScExternalDocLinksObj::getByIndex(sal_Int32 nIndex) 
++Any SAL_CALL ScExternalDocLinksObj::getByIndex(sal_Int32 nIndex)
 +        throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException, RuntimeException)
 +{
 +    ScUnoGuard aGuard;
-+    if (nIndex < 0 || nIndex >= static_cast<sal_Int32>(maDocNames.size()))
++    if (nIndex > ::std::numeric_limits<sal_uInt16>::max() || nIndex < ::std::numeric_limits<sal_uInt16>::min())
 +        throw lang::IndexOutOfBoundsException();
 +
-+    const OUString& rDocName = maDocNames[nIndex];
-+    DocLinkMap::const_iterator itr = maDocLinks.find(rDocName);
-+    if (itr == maDocLinks.end())
-+        // This should never happen!
++    sal_uInt16 nFileId = static_cast<sal_uInt16>(nIndex);
++
++    if (!mpRefMgr->hasExternalFile(nFileId))
 +        throw lang::IndexOutOfBoundsException();
 +
++    Reference< sheet::XExternalDocLink > aDocLink(new ScExternalDocLinkObj(mpRefMgr, nFileId));
 +    Any aAny;
-+    aAny <<= itr->second;
++    aAny <<= aDocLink;
 +    return aAny;
 +}
 +
-+Reference< container::XEnumeration >SAL_CALL ScExternalDocLinksObj::createEnumeration() 
++Reference< container::XEnumeration > SAL_CALL ScExternalDocLinksObj::createEnumeration()
 +        throw (RuntimeException)
 +{
 +    ScUnoGuard aGuard;
@@ -10178,25 +11725,87 @@
 +    return aRef;
 +}
 +
-+uno::Type SAL_CALL ScExternalDocLinksObj::getElementType() 
++uno::Type SAL_CALL ScExternalDocLinksObj::getElementType()
 +        throw (RuntimeException)
 +{
 +    ScUnoGuard aGuard;
 +    return getCppuType(static_cast<Reference<sheet::XExternalDocLinks>*>(0));
 +}
 +
-+sal_Bool SAL_CALL ScExternalDocLinksObj::hasElements() 
++sal_Bool SAL_CALL ScExternalDocLinksObj::hasElements()
 +        throw (RuntimeException)
 +{
 +    ScUnoGuard aGuard;
-+    return static_cast<sal_Bool>(!maDocLinks.empty());
++    return mpRefMgr->getExternalFileCount() > 0;
 +}
 +
+diff --git sc/source/ui/unoobj/nameuno.cxx sc/source/ui/unoobj/nameuno.cxx
+index 1335b36..b303be0 100644
+--- sc/source/ui/unoobj/nameuno.cxx
++++ sc/source/ui/unoobj/nameuno.cxx
+@@ -313,11 +313,11 @@ uno::Sequence<sheet::FormulaToken> SAL_CALL ScNamedRangeObj::getTokens() throw(u
+     ScUnoGuard aGuard;
+     uno::Sequence<sheet::FormulaToken> aSequence;
+     ScRangeData* pData = GetRangeData_Impl();
+-    if (pData)
++    if (pData && pDocShell)
+     {
+         ScTokenArray* pTokenArray = pData->GetCode();
+         if ( pTokenArray )
+-            (void)ScTokenConversion::ConvertToTokenSequence( aSequence, *pTokenArray );
++            (void)ScTokenConversion::ConvertToTokenSequence( *pDocShell->GetDocument(), aSequence, *pTokenArray );
+     }
+     return aSequence;
+ }
+@@ -325,10 +325,13 @@ uno::Sequence<sheet::FormulaToken> SAL_CALL ScNamedRangeObj::getTokens() throw(u
+ void SAL_CALL ScNamedRangeObj::setTokens( const uno::Sequence<sheet::FormulaToken>& rTokens ) throw(uno::RuntimeException)
+ {
+     ScUnoGuard aGuard;
+-    ScTokenArray aTokenArray;
+-    (void)ScTokenConversion::ConvertToTokenArray( aTokenArray, rTokens );
+-    // GRAM_PODF_A1 for API compatibility.
+-    Modify_Impl( NULL, &aTokenArray, NULL, NULL, NULL, ScGrammar::GRAM_PODF_A1 );
++    if( pDocShell )
++    {
++        ScTokenArray aTokenArray;
++        (void)ScTokenConversion::ConvertToTokenArray( *pDocShell->GetDocument(), aTokenArray, rTokens );
++        // GRAM_PODF_A1 for API compatibility.
++        Modify_Impl( NULL, &aTokenArray, NULL, NULL, NULL, ScGrammar::GRAM_PODF_A1 );
++    }
+ }
+ 
+ 
 diff --git sc/source/ui/unoobj/tokenuno.cxx sc/source/ui/unoobj/tokenuno.cxx
-index f16b1c5..f968d7b 100644
+index f16b1c5..1435cde 100644
 --- sc/source/ui/unoobj/tokenuno.cxx
 +++ sc/source/ui/unoobj/tokenuno.cxx
-@@ -123,6 +123,8 @@ void ScFormulaParserObj::SetCompilerFlags( ScCompiler& rCompiler ) const
+@@ -31,15 +31,16 @@
+ // MARKER(update_precomp.py): autogen include statement, do not remove
+ #include "precompiled_sc.hxx"
+ 
++#include "tokenuno.hxx"
+ 
+ #include <com/sun/star/sheet/ComplexReference.hpp>
++#include <com/sun/star/sheet/ExternalReference.hpp>
+ #include <com/sun/star/sheet/ReferenceFlags.hpp>
+ #include <com/sun/star/sheet/AddressConvention.hpp>
+ #include <com/sun/star/table/CellAddress.hpp>
+ 
+ #include <svtools/itemprop.hxx>
+ 
+-#include "tokenuno.hxx"
+ #include "miscuno.hxx"
+ #include "convuno.hxx"
+ #include "unonames.hxx"
+@@ -48,6 +49,7 @@
+ #include "tokenarray.hxx"
+ #include "docsh.hxx"
+ #include "rangeseq.hxx"
++#include "externalrefmgr.hxx"
+ 
+ using namespace com::sun::star;
+ 
+@@ -123,6 +125,8 @@ void ScFormulaParserObj::SetCompilerFlags( ScCompiler& rCompiler ) const
          eConv = aConvMap[mnConv];
  
      rCompiler.SetRefConvention( eConv );
@@ -10205,7 +11814,25 @@
  }
  
  uno::Sequence<sheet::FormulaToken> SAL_CALL ScFormulaParserObj::parseFormula( const rtl::OUString& aFormula )
-@@ -220,6 +222,11 @@ void SAL_CALL ScFormulaParserObj::setPropertyValue(
+@@ -138,7 +142,7 @@ uno::Sequence<sheet::FormulaToken> SAL_CALL ScFormulaParserObj::parseFormula( co
+         SetCompilerFlags( aCompiler );
+ 
+         ScTokenArray* pCode = aCompiler.CompileString( aFormula );
+-        (void)ScTokenConversion::ConvertToTokenSequence( aRet, *pCode );
++        (void)ScTokenConversion::ConvertToTokenSequence( *pDoc, aRet, *pCode );
+         delete pCode;
+     }
+ 
+@@ -155,7 +159,7 @@ rtl::OUString SAL_CALL ScFormulaParserObj::printFormula( const uno::Sequence<she
+     {
+         ScDocument* pDoc = mpDocShell->GetDocument();
+         ScTokenArray aCode;
+-        (void)ScTokenConversion::ConvertToTokenArray( aCode, aTokens );
++        (void)ScTokenConversion::ConvertToTokenArray( *pDoc, aCode, aTokens );
+         ScCompiler aCompiler( pDoc, maRefPos, aCode, pDoc->GetGrammar() );
+         SetCompilerFlags( aCompiler );
+ 
+@@ -220,6 +224,11 @@ void SAL_CALL ScFormulaParserObj::setPropertyValue(
          else
              throw lang::IllegalArgumentException();
      }
@@ -10217,7 +11844,7 @@
      else
          throw beans::UnknownPropertyException();
  }
-@@ -253,6 +260,10 @@ uno::Any SAL_CALL ScFormulaParserObj::getPropertyValue( const rtl::OUString& aPr
+@@ -253,6 +262,10 @@ uno::Any SAL_CALL ScFormulaParserObj::getPropertyValue( const rtl::OUString& aPr
      {
          aRet <<= maOpCodeMapping;
      }
@@ -10228,19 +11855,204 @@
      else
          throw beans::UnknownPropertyException();
      return aRet;
-@@ -473,7 +484,12 @@ bool ScTokenConversion::ConvertToTokenSequence( uno::Sequence<sheet::FormulaToke
+@@ -262,6 +275,27 @@ SC_IMPL_DUMMY_PROPERTY_LISTENER( ScFormulaParserObj )
+ 
+ //------------------------------------------------------------------------
+ 
++void lcl_ExternalRefToCalc( SingleRefData& rRef, const sheet::SingleReference& rAPI )
++{
++    rRef.InitFlags();
++
++    rRef.nCol    = static_cast<SCsCOL>(rAPI.Column);
++    rRef.nRow    = static_cast<SCsROW>(rAPI.Row);
++    rRef.nTab    = 0;
++    rRef.nRelCol = static_cast<SCsCOL>(rAPI.RelativeColumn);
++    rRef.nRelRow = static_cast<SCsROW>(rAPI.RelativeRow);
++    rRef.nRelTab = 0;
++
++    rRef.SetColRel(     ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_RELATIVE ) != 0 );
++    rRef.SetRowRel(     ( rAPI.Flags & sheet::ReferenceFlags::ROW_RELATIVE    ) != 0 );
++    rRef.SetTabRel(     false );    // sheet index must be absolute for external refs
++    rRef.SetColDeleted( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_DELETED  ) != 0 );
++    rRef.SetRowDeleted( ( rAPI.Flags & sheet::ReferenceFlags::ROW_DELETED     ) != 0 );
++    rRef.SetTabDeleted( false );    // sheet must not be deleted for external refs
++    rRef.SetFlag3D(     ( rAPI.Flags & sheet::ReferenceFlags::SHEET_3D        ) != 0 );
++    rRef.SetRelName(    false );
++}
++
+ void lcl_SingleRefToCalc( SingleRefData& rRef, const sheet::SingleReference& rAPI )
+ {
+     rRef.InitFlags();
+@@ -283,6 +317,25 @@ void lcl_SingleRefToCalc( SingleRefData& rRef, const sheet::SingleReference& rAP
+     rRef.SetRelName(    ( rAPI.Flags & sheet::ReferenceFlags::RELATIVE_NAME   ) != 0 );
+ }
+ 
++void lcl_ExternalRefToApi( sheet::SingleReference& rAPI, const SingleRefData& rRef )
++{
++    rAPI.Column         = rRef.nCol;
++    rAPI.Row            = rRef.nRow;
++    rAPI.Sheet          = 0;
++    rAPI.RelativeColumn = rRef.nRelCol;
++    rAPI.RelativeRow    = rRef.nRelRow;
++    rAPI.RelativeSheet  = 0;
++
++    sal_Int32 nFlags = 0;
++    if ( rRef.IsColRel() )     nFlags |= sheet::ReferenceFlags::COLUMN_RELATIVE;
++    if ( rRef.IsRowRel() )     nFlags |= sheet::ReferenceFlags::ROW_RELATIVE;
++    if ( rRef.IsColDeleted() ) nFlags |= sheet::ReferenceFlags::COLUMN_DELETED;
++    if ( rRef.IsRowDeleted() ) nFlags |= sheet::ReferenceFlags::ROW_DELETED;
++    if ( rRef.IsFlag3D() )     nFlags |= sheet::ReferenceFlags::SHEET_3D;
++    if ( rRef.IsRelName() )    nFlags |= sheet::ReferenceFlags::RELATIVE_NAME;
++    rAPI.Flags = nFlags;
++}
++
+ void lcl_SingleRefToApi( sheet::SingleReference& rAPI, const SingleRefData& rRef )
+ {
+     rAPI.Column         = rRef.nCol;
+@@ -305,8 +358,8 @@ void lcl_SingleRefToApi( sheet::SingleReference& rAPI, const SingleRefData& rRef
+ }
+ 
+ // static
+-bool ScTokenConversion::ConvertToTokenArray( ScTokenArray& rTokenArray,
+-                        const uno::Sequence<sheet::FormulaToken>& rSequence )
++bool ScTokenConversion::ConvertToTokenArray( ScDocument& rDoc,
++        ScTokenArray& rTokenArray, const uno::Sequence<sheet::FormulaToken>& rSequence )
+ {
+     bool bError = false;
+     sal_Int32 nCount = rSequence.getLength();
+@@ -384,6 +437,59 @@ bool ScTokenConversion::ConvertToTokenArray( ScTokenArray& rTokenArray,
+                         else
+                             bError = true;
+                     }
++                    else if ( aType.equals( cppu::UnoType<sheet::ExternalReference>::get() ) )
++                    {
++                        sheet::ExternalReference aApiExtRef;
++                        if( (eOpCode == ocPush) && (rAPI.Data >>= aApiExtRef) && (0 <= aApiExtRef.Index) && (aApiExtRef.Index <= SAL_MAX_UINT16) )
++                        {
++                            sal_uInt16 nFileId = static_cast< sal_uInt16 >( aApiExtRef.Index );
++                            sheet::SingleReference aApiSRef;
++                            sheet::ComplexReference aApiCRef;
++                            ::rtl::OUString aName;
++                            if( aApiExtRef.Reference >>= aApiSRef )
++                            {
++                                // try to resolve cache index to sheet name
++                                size_t nCacheId = static_cast< size_t >( aApiSRef.Sheet );
++                                String aTabName = rDoc.GetExternalRefManager()->getCacheTableName( nFileId, nCacheId );
++                                if( aTabName.Len() > 0 )
++                                {
++                                    SingleRefData aSingleRef;
++                                    // convert column/row settings, set sheet index to absolute
++                                    lcl_ExternalRefToCalc( aSingleRef, aApiSRef );
++                                    rTokenArray.AddExternalSingleReference( nFileId, aTabName, aSingleRef );
++                                }
++                                else
++                                    bError = true;
++                            }
++                            else if( aApiExtRef.Reference >>= aApiCRef )
++                            {
++                                // try to resolve cache index to sheet name. TODO: second cache index is dropped
++                                size_t nCacheId = static_cast< size_t >( aApiCRef.Reference1.Sheet );
++                                String aTabName = rDoc.GetExternalRefManager()->getCacheTableName( nFileId, nCacheId );
++                                if( aTabName.Len() > 0 )
++                                {
++                                    ComplRefData aComplRef;
++                                    // convert column/row settings, set sheet index to absolute
++                                    lcl_ExternalRefToCalc( aComplRef.Ref1, aApiCRef.Reference1 );
++                                    lcl_ExternalRefToCalc( aComplRef.Ref2, aApiCRef.Reference2 );
++                                    rTokenArray.AddExternalDoubleReference( nFileId, aTabName, aComplRef );
++                                }
++                                else
++                                    bError = true;
++                            }
++                            else if( aApiExtRef.Reference >>= aName )
++                            {
++                                if( aName.getLength() > 0 )
++                                    rTokenArray.AddExternalName( nFileId, aName );
++                                else
++                                    bError = true;
++                            }
++                            else
++                                bError = true;
++                        }
++                        else
++                            bError = true;
++                    }
+                     else
+                         bError = true;      // unknown struct
+                 }
+@@ -414,8 +520,8 @@ bool ScTokenConversion::ConvertToTokenArray( ScTokenArray& rTokenArray,
+ }
+ 
+ // static
+-bool ScTokenConversion::ConvertToTokenSequence( uno::Sequence<sheet::FormulaToken>& rSequence,
+-                        const ScTokenArray& rTokenArray )
++bool ScTokenConversion::ConvertToTokenSequence( ScDocument& rDoc,
++        uno::Sequence<sheet::FormulaToken>& rSequence, const ScTokenArray& rTokenArray )
+ {
+     bool bError = false;
+ 
+@@ -430,7 +536,7 @@ bool ScTokenConversion::ConvertToTokenSequence( uno::Sequence<sheet::FormulaToke
+             sheet::FormulaToken& rAPI = rSequence[nPos];
+ 
+             OpCode eOpCode = rToken.GetOpCode();
+-            rAPI.OpCode = static_cast<sal_Int32>(eOpCode);      //! assuming equal values for the moment
++            // eOpCode may be changed in the following switch/case
+             switch ( rToken.GetType() )
+             {
+                 case svByte:
+@@ -473,9 +579,52 @@ bool ScTokenConversion::ConvertToTokenSequence( uno::Sequence<sheet::FormulaToke
                      if (!ScRangeToSequence::FillMixedArray( rAPI.Data, rToken.GetMatrix(), true))
                          rAPI.Data.clear();
                      break;
 +                case svExternalSingleRef:
++                    {
++                        sheet::SingleReference aSingleRef;
++                        lcl_ExternalRefToApi( aSingleRef, rToken.GetSingleRef() );
++                        size_t nCacheId;
++                        rDoc.GetExternalRefManager()->getCacheTable( rToken.GetIndex(), rToken.GetString(), false, &nCacheId );
++                        aSingleRef.Sheet = static_cast< sal_Int32 >( nCacheId );
++                        sheet::ExternalReference aExtRef;
++                        aExtRef.Index = rToken.GetIndex();
++                        aExtRef.Reference <<= aSingleRef;
++                        rAPI.Data <<= aExtRef;
++                        eOpCode = ocPush;
++                    }
++                    break;
 +                case svExternalDoubleRef:
++                    {
++                        sheet::ComplexReference aComplRef;
++                        lcl_ExternalRefToApi( aComplRef.Reference1, rToken.GetSingleRef() );
++                        lcl_ExternalRefToApi( aComplRef.Reference2, rToken.GetSingleRef2() );
++                        size_t nCacheId;
++                        rDoc.GetExternalRefManager()->getCacheTable( rToken.GetIndex(), rToken.GetString(), false, &nCacheId );
++                        aComplRef.Reference1.Sheet = aComplRef.Reference2.Sheet = static_cast< sal_Int32 >( nCacheId );
++                        sheet::ExternalReference aExtRef;
++                        aExtRef.Index = rToken.GetIndex();
++                        aExtRef.Reference <<= aComplRef;
++                        rAPI.Data <<= aExtRef;
++                        eOpCode = ocPush;
++                    }
++                    break;
 +                case svExternalName:
-+                // FIXME: svExternal... are to be transported via API.
++                    {
++                        sheet::ExternalReference aExtRef;
++                        aExtRef.Index = rToken.GetIndex();
++                        aExtRef.Reference <<= ::rtl::OUString( rToken.GetString() );
++                        rAPI.Data <<= aExtRef;
++                        eOpCode = ocPush;
++                    }
++                    break;
                  default:
 +                    DBG_ERROR1( "ScTokenConversion::ConvertToTokenSequence: unhandled token type SvStackVar %d", rToken.GetType());
++                case svSep:     // occurs with ocSep, ocOpen, ocClose, ocArray*
++                case svJump:    // occurs with ocIf, ocChose
++                case svMissing: // occurs with ocMissing
                      rAPI.Data.clear();      // no data
              }
++            rAPI.OpCode = static_cast<sal_Int32>(eOpCode);      //! assuming equal values for the moment
          }
+     }
+     else
 diff --git sc/source/ui/view/tabvwsh4.cxx sc/source/ui/view/tabvwsh4.cxx
 index 436f0eb..2bf1f26 100644
 --- sc/source/ui/view/tabvwsh4.cxx

Added: branches/ooo-build-3-0-1/patches/dev300/calc-external-defined-names-svtools.diff
==============================================================================
--- (empty file)
+++ branches/ooo-build-3-0-1/patches/dev300/calc-external-defined-names-svtools.diff	Thu Jan 15 02:44:24 2009
@@ -0,0 +1,61 @@
+diff --git svtools/inc/svtools/zforlist.hxx svtools/inc/svtools/zforlist.hxx
+index 20d4752..1e4f122 100644
+--- svtools/inc/svtools/zforlist.hxx
++++ svtools/inc/svtools/zforlist.hxx
+@@ -45,6 +45,8 @@
+ #include <tools/link.hxx>
+ #include <svtools/nfkeytab.hxx>
+ 
++#include <map>
++
+ class Date;
+ class SvStream;
+ class Color;
+@@ -224,6 +226,8 @@ typedef Table SvNumberFormatTable;
+ typedef Table SvNumberFormatterIndexTable;
+ #endif
+ 
++typedef ::std::map< sal_uInt32, sal_uInt32 > SvNumberFormatterMergeMap;
++
+ 
+ /** Language/country dependent currency entries
+  */
+@@ -599,6 +603,11 @@ public:
+ 	/// Return the new format index for an old format index, if a merge table exists
+ 	inline sal_uInt32 GetMergeFmtIndex( sal_uInt32 nOldFmt ) const;
+ 
++    /** Convert the ugly old tools' Table type bloated with new'ed sal_uInt32
++        entries merge table to ::std::map with old index key and new index key.
++        @ATTENTION! Also clears the old table using ClearMergeTable() */
++    SvNumberFormatterMergeMap ConvertMergeTableToMap();
++
+ 	/// Return the last used position ever of a language/country combination
+ 	USHORT GetLastInsertKey(sal_uInt32 CLOffset);
+ 
+diff --git svtools/source/numbers/zforlist.cxx svtools/source/numbers/zforlist.cxx
+index b093e0d..adc7e70 100644
+--- svtools/source/numbers/zforlist.cxx
++++ svtools/source/numbers/zforlist.cxx
+@@ -2914,6 +2914,22 @@ SvNumberFormatterIndexTable* SvNumberFormatter::MergeFormatter(SvNumberFormatter
+ }
+ 
+ 
++SvNumberFormatterMergeMap SvNumberFormatter::ConvertMergeTableToMap()
++{
++    if (!HasMergeFmtTbl())
++        return SvNumberFormatterMergeMap();
++
++    SvNumberFormatterMergeMap aMap;
++    for (sal_uInt32* pIndex = pMergeTable->First(); pIndex; pIndex = pMergeTable->Next())
++    {
++        sal_uInt32 nOldKey = pMergeTable->GetCurKey();
++        aMap.insert( SvNumberFormatterMergeMap::value_type( nOldKey, *pIndex));
++    }
++    ClearMergeTable();
++	return aMap;
++}
++
++
+ sal_uInt32 SvNumberFormatter::GetFormatForLanguageIfBuiltIn( sal_uInt32 nFormat,
+ 		LanguageType eLnge )
+ {



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