[Libreoffice-commits] .: sc/source

Kohei Yoshida kohei at kemper.freedesktop.org
Tue Jan 10 11:29:03 PST 2012


 sc/source/filter/excel/excform8.cxx |    8 +-
 sc/source/filter/excel/read.cxx     |    1 
 sc/source/filter/excel/xiname.cxx   |  125 +++++++++++++++++++++++-------------
 sc/source/filter/inc/xiname.hxx     |   36 ++++++++--
 sc/source/filter/inc/xistream.hxx   |    2 
 5 files changed, 119 insertions(+), 53 deletions(-)

New commits:
commit d041d1469227f5536abba938a21ab7c8e9d35719
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date:   Tue Jan 10 14:26:14 2012 -0500

    fdo#42624: Defer formula token conversion for defined names (xls import).
    
    This is necessary for handling names that cross-reference each other.

diff --git a/sc/source/filter/excel/excform8.cxx b/sc/source/filter/excel/excform8.cxx
index f06f9c8..9693fe8 100644
--- a/sc/source/filter/excel/excform8.cxx
+++ b/sc/source/filter/excel/excform8.cxx
@@ -487,11 +487,11 @@ ConvErr ExcelToSc8::Convert( const ScTokenArray*& rpTokArray, XclImpStream& aIn,
                 const XclImpName* pName = GetNameManager().GetName( nUINT16 );
                 if (pName)
                 {
-                    if (pName->GetScRangeData())
-                        aStack << aPool.StoreName(nUINT16, pName->IsGlobal());
-                    else
-                        // used-defined macro name.
+                    if (pName->IsMacro())
+                        // user-defined macro name.
                         aStack << aPool.Store(ocMacro, pName->GetXclName());
+                    else
+                        aStack << aPool.StoreName(nUINT16, pName->IsGlobal());
                 }
             }
             break;
diff --git a/sc/source/filter/excel/read.cxx b/sc/source/filter/excel/read.cxx
index 81e6f6a..30acae7 100644
--- a/sc/source/filter/excel/read.cxx
+++ b/sc/source/filter/excel/read.cxx
@@ -1001,6 +1001,7 @@ FltError ImportExcel8::Read( void )
                             rNumFmtBfr.CreateScFormats();
                             rXFBfr.CreateUserStyles();
                             rPTableMgr.ReadPivotCaches( maStrm );
+                            rNameMgr.ConvertAllTokens();
                             eAkt = EXC_STATE_BEFORE_SHEET;
                         }
                     break;
diff --git a/sc/source/filter/excel/xiname.cxx b/sc/source/filter/excel/xiname.cxx
index f2f5e8d..9cdfe77 100644
--- a/sc/source/filter/excel/xiname.cxx
+++ b/sc/source/filter/excel/xiname.cxx
@@ -40,19 +40,26 @@
 // *** Implementation ***
 // ============================================================================
 
+XclImpName::TokenStrmData::TokenStrmData( XclImpStream& rStrm ) :
+    mrStrm(rStrm), mnStrmPos(0), mnStrmSize(0) {}
+
 XclImpName::XclImpName( XclImpStream& rStrm, sal_uInt16 nXclNameIdx ) :
     XclImpRoot( rStrm.GetRoot() ),
     mpScData( 0 ),
     mcBuiltIn( EXC_BUILTIN_UNKNOWN ),
     mnScTab( SCTAB_MAX ),
-    mbFunction( false ),
-    mbVBName( false )
+    meNameType( RT_NAME ),
+    mnXclTab( EXC_NAME_GLOBAL ),
+    mnNameIndex( nXclNameIdx ),
+    mbVBName( false ),
+    mbMacro( false ),
+    mpTokensData( NULL )
 {
     ExcelToSc& rFmlaConv = GetOldFmlaConverter();
 
     // 1) *** read data from stream *** ---------------------------------------
 
-    sal_uInt16 nFlags = 0, nFmlaSize = 0, nExtSheet = EXC_NAME_GLOBAL, nXclTab = EXC_NAME_GLOBAL;
+    sal_uInt16 nFlags = 0, nFmlaSize = 0, nExtSheet = EXC_NAME_GLOBAL;
     sal_uInt8 nNameLen = 0, nShortCut;
 
     switch( GetBiff() )
@@ -78,7 +85,7 @@ XclImpName::XclImpName( XclImpStream& rStrm, sal_uInt16 nXclNameIdx ) :
         case EXC_BIFF5:
         case EXC_BIFF8:
         {
-            rStrm >> nFlags >> nShortCut >> nNameLen >> nFmlaSize >> nExtSheet >> nXclTab;
+            rStrm >> nFlags >> nShortCut >> nNameLen >> nFmlaSize >> nExtSheet >> mnXclTab;
             rStrm.Ignore( 4 );
         }
         break;
@@ -94,8 +101,9 @@ XclImpName::XclImpName( XclImpStream& rStrm, sal_uInt16 nXclNameIdx ) :
     // 2) *** convert sheet index and name *** --------------------------------
 
     // functions and VBA
-    mbFunction = ::get_flag( nFlags, EXC_NAME_FUNC );
+    bool bFunction = ::get_flag( nFlags, EXC_NAME_FUNC );
     mbVBName = ::get_flag( nFlags, EXC_NAME_VB );
+    mbMacro = ::get_flag( nFlags, EXC_NAME_PROC );
 
     // get built-in name, or convert characters invalid in Calc
     bool bBuiltIn = ::get_flag( nFlags, EXC_NAME_BUILTIN );
@@ -131,11 +139,9 @@ XclImpName::XclImpName( XclImpStream& rStrm, sal_uInt16 nXclNameIdx ) :
     rtl::OUString aRealOrigName = maScName;
 
     // add index for local names
-    if( nXclTab != EXC_NAME_GLOBAL )
+    if( mnXclTab != EXC_NAME_GLOBAL )
     {
-        sal_uInt16 nUsedTab = (GetBiff() == EXC_BIFF8) ? nXclTab : nExtSheet;
-        // do not rename sheet-local names by default, this breaks VBA scripts
-//        maScName.Append( '_' ).Append( String::CreateFromInt32( nUsedTab ) );
+        sal_uInt16 nUsedTab = (GetBiff() == EXC_BIFF8) ? mnXclTab : nExtSheet;
         // TODO: may not work for BIFF5, handle skipped sheets (all BIFF)
         mnScTab = static_cast< SCTAB >( nUsedTab - 1 );
     }
@@ -144,7 +150,6 @@ XclImpName::XclImpName( XclImpStream& rStrm, sal_uInt16 nXclNameIdx ) :
 
     rFmlaConv.Reset();
     const ScTokenArray* pTokArr = 0; // pointer to token array, owned by rFmlaConv
-    RangeType nNameType = RT_NAME;
 
     if( ::get_flag( nFlags, EXC_NAME_BIG ) )
     {
@@ -153,7 +158,7 @@ XclImpName::XclImpName( XclImpStream& rStrm, sal_uInt16 nXclNameIdx ) :
     }
     else if( bBuiltIn )
     {
-        SCsTAB const nLocalTab = (nXclTab == EXC_NAME_GLOBAL) ? SCTAB_MAX : (nXclTab - 1);
+        SCsTAB const nLocalTab = (mnXclTab == EXC_NAME_GLOBAL) ? SCTAB_MAX : (mnXclTab - 1);
 
         // --- print ranges or title ranges ---
         rStrm.PushPosition();
@@ -161,11 +166,11 @@ XclImpName::XclImpName( XclImpStream& rStrm, sal_uInt16 nXclNameIdx ) :
         {
             case EXC_BUILTIN_PRINTAREA:
                 if( rFmlaConv.Convert( GetPrintAreaBuffer(), rStrm, nFmlaSize, nLocalTab, FT_RangeName ) == ConvOK )
-                    nNameType |= RT_PRINTAREA;
+                    meNameType |= RT_PRINTAREA;
             break;
             case EXC_BUILTIN_PRINTTITLES:
                 if( rFmlaConv.Convert( GetTitleAreaBuffer(), rStrm, nFmlaSize, nLocalTab, FT_RangeName ) == ConvOK )
-                    nNameType |= RT_COLHEADER | RT_ROWHEADER;
+                    meNameType |= RT_COLHEADER | RT_ROWHEADER;
             break;
         }
         rStrm.PopPosition();
@@ -188,7 +193,7 @@ XclImpName::XclImpName( XclImpStream& rStrm, sal_uInt16 nXclNameIdx ) :
                     break;
                     case EXC_BUILTIN_CRITERIA:
                         GetFilterManager().AddAdvancedRange( aRange );
-                        nNameType |= RT_CRITERIA;
+                        meNameType |= RT_CRITERIA;
                     break;
                     case EXC_BUILTIN_EXTRACT:
                         if( pTokArr->IsValidReference( aRange ) )
@@ -200,46 +205,75 @@ XclImpName::XclImpName( XclImpStream& rStrm, sal_uInt16 nXclNameIdx ) :
     }
     else if( nFmlaSize > 0 )
     {
-        // regular defined name
-        rFmlaConv.Convert( pTokArr, rStrm, nFmlaSize, true, FT_RangeName );
+        // Regular defined name.  We need to convert the tokens after all the
+        // names have been registered (for cross-referenced names).
+        mpTokensData.reset(new TokenStrmData(rStrm));
+        mpTokensData->mnStrmPos = rStrm.GetSvStreamPos();
+        rStrm.StorePosition(mpTokensData->maStrmPos);
+        mpTokensData->mnStrmSize = nFmlaSize;
     }
 
-    // 4) *** create a defined name in the Calc document *** ------------------
+    if (pTokArr && !bFunction && !mbVBName)
+        InsertName(pTokArr);
+}
+
+bool XclImpName::IsMacro() const
+{
+    return mbMacro;
+}
+
+void XclImpName::ConvertTokens()
+{
+    if (!mpTokensData)
+        return;
+
+    ExcelToSc& rFmlaConv = GetOldFmlaConverter();
+    rFmlaConv.Reset();
+    const ScTokenArray* pArray = NULL;
+
+    XclImpStreamPos aOldPos;
+    XclImpStream& rStrm = mpTokensData->mrStrm;
+    rStrm.StorePosition(aOldPos);
+    rStrm.RestorePosition(mpTokensData->maStrmPos);
+    rFmlaConv.Convert(pArray, rStrm, mpTokensData->mnStrmSize, true, FT_RangeName);
+    rStrm.RestorePosition(aOldPos);
 
-    // do not ignore hidden names (may be regular names created by VBA scripts)
-    if( pTokArr /*&& (bBuiltIn || !::get_flag( nFlags, EXC_NAME_HIDDEN ))*/ && !mbFunction && !mbVBName )
+    if (pArray)
+        InsertName(pArray);
+}
+
+void XclImpName::InsertName(const ScTokenArray* pArray)
+{
+    // create the Calc name data
+    ScRangeData* pData = new ScRangeData(GetDocPtr(), maScName, *pArray, ScAddress(), meNameType);
+    pData->GuessPosition();             // calculate base position for relative refs
+    pData->SetIndex( mnNameIndex );     // used as unique identifier in formulas
+    if (mnXclTab == EXC_NAME_GLOBAL)
     {
-        // create the Calc name data
-        ScRangeData* pData = new ScRangeData( GetDocPtr(), maScName, *pTokArr, ScAddress(), nNameType );
-        pData->GuessPosition();             // calculate base position for relative refs
-        pData->SetIndex( nXclNameIdx );     // used as unique identifier in formulas
-        if (nXclTab == EXC_NAME_GLOBAL)
+        if (!GetDoc().GetRangeName()->insert(pData))
+            pData = NULL;
+    }
+    else
+    {
+        ScRangeName* pLocalNames = GetDoc().GetRangeName(mnScTab);
+        if (pLocalNames)
         {
-            if (!GetDoc().GetRangeName()->insert(pData))
+            if (!pLocalNames->insert(pData))
                 pData = NULL;
         }
-        else
-        {
-            ScRangeName* pLocalNames = GetDoc().GetRangeName(mnScTab);
-            if (pLocalNames)
-            {
-                if (!pLocalNames->insert(pData))
-                    pData = NULL;
-            }
 
-            if (GetBiff() == EXC_BIFF8 && pData)
+        if (GetBiff() == EXC_BIFF8 && pData)
+        {
+            ScRange aRange;
+            // discard deleted ranges ( for the moment at least )
+            if ( pData->IsValidReference( aRange ) )
             {
-                ScRange aRange;
-                // discard deleted ranges ( for the moment at least )
-                if ( pData->IsValidReference( aRange ) )
-                {
-                    GetExtDocOptions().GetOrCreateTabSettings( nXclTab );
-                }
+                GetExtDocOptions().GetOrCreateTabSettings( mnXclTab );
             }
         }
-        if (pData)
-            mpScData = pData;               // cache for later use
     }
+    if (pData)
+        mpScData = pData;               // cache for later use
 }
 
 // ----------------------------------------------------------------------------
@@ -279,6 +313,13 @@ const XclImpName* XclImpNameManager::GetName( sal_uInt16 nXclNameIdx ) const
     return ( nXclNameIdx > maNameList.size() ) ? NULL : &(maNameList.at( nXclNameIdx - 1 ));
 }
 
+void XclImpNameManager::ConvertAllTokens()
+{
+    XclImpNameList::iterator it = maNameList.begin(), itEnd = maNameList.end();
+    for (; it != itEnd; ++it)
+        it->ConvertTokens();
+}
+
 // ============================================================================
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/inc/xiname.hxx b/sc/source/filter/inc/xiname.hxx
index 8d05d68..f4e55c3 100644
--- a/sc/source/filter/inc/xiname.hxx
+++ b/sc/source/filter/inc/xiname.hxx
@@ -32,17 +32,31 @@
 #include <boost/ptr_container/ptr_vector.hpp>
 #include "xlname.hxx"
 #include "xiroot.hxx"
+#include "xistream.hxx"
 
-//class ScDocument;
-//class ScTokenArray;
+#include "rangenam.hxx"
+
+#include <boost/noncopyable.hpp>
+#include <boost/scoped_ptr.hpp>
 
 // ============================================================================
 
 class ScRangeData;
+class ScTokenArray;
 
 /** Represents a defined name. It may be related to a single sheet or global. */
-class XclImpName : protected XclImpRoot
+class XclImpName : protected XclImpRoot, public boost::noncopyable
 {
+    struct TokenStrmData
+    {
+        XclImpStream& mrStrm;
+        XclImpStreamPos maStrmPos;
+        sal_Size mnStrmPos;
+        sal_Size mnStrmSize;
+
+        TokenStrmData( XclImpStream& rStrm );
+    };
+
 public:
     explicit            XclImpName( XclImpStream& rStrm, sal_uInt16 nXclNameIdx );
 
@@ -51,17 +65,25 @@ public:
     inline SCTAB        GetScTab() const { return mnScTab; }
     inline const ScRangeData* GetScRangeData() const { return mpScData; }
     inline bool         IsGlobal() const { return mnScTab == SCTAB_MAX; }
-    inline bool         IsFunction() const { return mbFunction; }
     inline bool         IsVBName() const { return mbVBName; }
+    bool IsMacro() const;
+    void ConvertTokens();
 
 private:
+    void InsertName(const ScTokenArray* pArray);
+
     String              maXclName;      /// Original name read from the file.
     String              maScName;       /// Name inserted into the Calc document.
     const ScRangeData*  mpScData;       /// Pointer to Calc defined name (no ownership).
     sal_Unicode         mcBuiltIn;      /// Excel built-in name index.
     SCTAB               mnScTab;        /// Calc sheet index of local names.
-    bool                mbFunction;     /// true = Name refers to a function (add-in or VBA).
-    bool                mbVBName;       /// true = Visual Basic procedure or function.
+    RangeType           meNameType;
+    sal_uInt16          mnXclTab;
+    sal_uInt16          mnNameIndex;
+    bool                mbVBName:1;     /// true = Visual Basic procedure or function.
+    bool                mbMacro:1;      /// Whether it's a user-defined macro.
+
+    boost::scoped_ptr<TokenStrmData> mpTokensData;   /// For later conversion of token array.
 };
 
 // ----------------------------------------------------------------------------
@@ -90,6 +112,8 @@ public:
         @return  Pointer to the defined name or 0 on error. */
     const XclImpName*   GetName( sal_uInt16 nXclNameIdx ) const;
 
+    void ConvertAllTokens();
+
 private:
     typedef boost::ptr_vector< XclImpName > XclImpNameList;
     XclImpNameList      maNameList;
diff --git a/sc/source/filter/inc/xistream.hxx b/sc/source/filter/inc/xistream.hxx
index 89dab91..a80e478 100644
--- a/sc/source/filter/inc/xistream.hxx
+++ b/sc/source/filter/inc/xistream.hxx
@@ -436,12 +436,12 @@ public:
     /** Returns the stream size. */
     inline sal_Size     GetSvStreamSize() const { return mnStreamSize; }
 
-private:
     /** Stores current stream position into rPos. */
     void                StorePosition( XclImpStreamPos& rPos );
     /** Restores stream position contained in rPos. */
     void                RestorePosition( const XclImpStreamPos& rPos );
 
+private:
     /** Seeks to next raw record header and reads record ID and size.
         @descr  This is a "raw" function, means that stream members are
         inconsistent after return. Does only change mnRawRecId, mnRawRecSize,


More information about the Libreoffice-commits mailing list