summaryrefslogtreecommitdiff
path: root/sc/source
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@suse.com>2012-01-10 14:26:14 -0500
committerKohei Yoshida <kohei.yoshida@suse.com>2012-01-10 14:27:58 -0500
commit4f888c9c01c77500ca181890f69cbd9883324a74 (patch)
tree1524784c016d16ed590ab81b16c0bc7d7f33e950 /sc/source
parent349701133f09530adc56c51bbfcb5400845ff993 (diff)
fdo#42624: Defer formula token conversion for defined names (xls import).
This is necessary for handling names that cross-reference each other.
Diffstat (limited to 'sc/source')
-rw-r--r--sc/source/filter/excel/excform8.cxx8
-rw-r--r--sc/source/filter/excel/read.cxx1
-rw-r--r--sc/source/filter/excel/xiname.cxx125
-rw-r--r--sc/source/filter/inc/xiname.hxx36
-rw-r--r--sc/source/filter/inc/xistream.hxx2
5 files changed, 119 insertions, 53 deletions
diff --git a/sc/source/filter/excel/excform8.cxx b/sc/source/filter/excel/excform8.cxx
index f06f9c88c93f..9693fe8e58c3 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 81e6f6a039d5..30acae7d36e1 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 f2f5e8d4f20a..9cdfe775f94e 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 8d05d680d690..f4e55c37645b 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 89dab91a7392..a80e478a1d20 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,