summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
authorhg <hg@oosvn01.>2009-10-08 16:03:52 +0000
committerhg <hg@oosvn01.>2009-10-08 16:03:52 +0000
commit90631ceb76c032e182db62df387688a97cf94f12 (patch)
treecae70f92ba9197c61a5e81ae21004fb4f385a124 /sc
parentb88253921c6b484acb2d6f893341e953dcae1cba (diff)
parentbebc983ea6df34dbc310d1dfbb3ca74ea62db830 (diff)
merge with m55
Diffstat (limited to 'sc')
-rw-r--r--sc/inc/address.hxx6
-rw-r--r--sc/inc/cell.hxx9
-rw-r--r--sc/inc/cellsuno.hxx12
-rw-r--r--sc/inc/compiler.hxx13
-rw-r--r--sc/inc/conditio.hxx19
-rw-r--r--sc/inc/datauno.hxx11
-rw-r--r--sc/inc/document.hxx10
-rw-r--r--sc/inc/externalrefmgr.hxx37
-rw-r--r--sc/inc/fmtuno.hxx33
-rw-r--r--sc/inc/formulaparserpool.hxx70
-rw-r--r--sc/inc/global.hxx8
-rw-r--r--sc/inc/pch/precompiled_sc.hxx3
-rw-r--r--sc/inc/progress.hxx11
-rw-r--r--sc/inc/rangenam.hxx10
-rw-r--r--sc/inc/refdata.hxx21
-rw-r--r--sc/inc/table.hxx35
-rw-r--r--sc/inc/tokenuno.hxx20
-rw-r--r--sc/inc/unonames.hxx6
-rw-r--r--sc/inc/validat.hxx4
-rw-r--r--sc/source/core/data/cell.cxx8
-rw-r--r--sc/source/core/data/cell2.cxx274
-rw-r--r--sc/source/core/data/conditio.cxx48
-rw-r--r--sc/source/core/data/documen2.cxx13
-rw-r--r--sc/source/core/data/documen3.cxx10
-rw-r--r--sc/source/core/data/documen4.cxx11
-rw-r--r--sc/source/core/data/document.cxx2
-rw-r--r--sc/source/core/data/table1.cxx10
-rw-r--r--sc/source/core/data/table2.cxx4
-rw-r--r--sc/source/core/data/table3.cxx105
-rw-r--r--sc/source/core/data/validat.cxx5
-rw-r--r--sc/source/core/inc/interpre.hxx26
-rw-r--r--sc/source/core/inc/refupdat.hxx2
-rw-r--r--sc/source/core/tool/address.cxx53
-rw-r--r--sc/source/core/tool/compiler.cxx246
-rw-r--r--sc/source/core/tool/formulaparserpool.cxx171
-rw-r--r--sc/source/core/tool/interpr1.cxx435
-rw-r--r--sc/source/core/tool/interpr4.cxx9
-rw-r--r--sc/source/core/tool/makefile.mk4
-rw-r--r--sc/source/core/tool/progress.cxx2
-rw-r--r--sc/source/core/tool/rangenam.cxx42
-rw-r--r--sc/source/core/tool/reftokenhelper.cxx55
-rw-r--r--sc/source/core/tool/refupdat.cxx10
-rw-r--r--sc/source/filter/excel/excimp8.cxx44
-rw-r--r--sc/source/filter/excel/excrecds.cxx32
-rw-r--r--sc/source/filter/excel/namebuff.cxx3
-rw-r--r--sc/source/filter/excel/xeformula.cxx2
-rw-r--r--sc/source/filter/xml/XMLConverter.cxx302
-rw-r--r--sc/source/filter/xml/XMLConverter.hxx58
-rw-r--r--sc/source/filter/xml/XMLExportDatabaseRanges.cxx50
-rw-r--r--sc/source/filter/xml/XMLExportDatabaseRanges.hxx12
-rw-r--r--sc/source/filter/xml/XMLTrackedChangesContext.cxx24
-rw-r--r--sc/source/filter/xml/xmlcelli.cxx42
-rw-r--r--sc/source/filter/xml/xmlcelli.hxx3
-rw-r--r--sc/source/filter/xml/xmlcvali.cxx289
-rw-r--r--sc/source/filter/xml/xmldrani.cxx5
-rw-r--r--sc/source/filter/xml/xmldrani.hxx6
-rw-r--r--sc/source/filter/xml/xmlfilti.cxx44
-rw-r--r--sc/source/filter/xml/xmlfilti.hxx9
-rw-r--r--sc/source/filter/xml/xmlimprt.cxx81
-rw-r--r--sc/source/filter/xml/xmlimprt.hxx80
-rw-r--r--sc/source/filter/xml/xmlnexpi.cxx15
-rw-r--r--sc/source/filter/xml/xmlstyli.cxx242
-rw-r--r--sc/source/filter/xml/xmlstyli.hxx30
-rw-r--r--sc/source/filter/xml/xmlsubti.cxx15
-rw-r--r--sc/source/filter/xml/xmlsubti.hxx6
-rw-r--r--sc/source/ui/app/inputhdl.cxx5
-rw-r--r--sc/source/ui/docshell/docfunc.cxx38
-rw-r--r--sc/source/ui/docshell/docsh3.cxx4
-rw-r--r--sc/source/ui/docshell/externalrefmgr.cxx96
-rw-r--r--sc/source/ui/formdlg/formula.cxx7
-rw-r--r--sc/source/ui/inc/docfunc.hxx4
-rw-r--r--sc/source/ui/inc/formula.hxx1
-rw-r--r--sc/source/ui/inc/undoblk.hxx30
-rw-r--r--sc/source/ui/inc/viewfunc.hxx1
-rw-r--r--sc/source/ui/src/filter.src64
-rw-r--r--sc/source/ui/undo/undoblk3.cxx93
-rw-r--r--sc/source/ui/unoobj/cellsuno.cxx43
-rw-r--r--sc/source/ui/unoobj/datauno.cxx158
-rw-r--r--sc/source/ui/unoobj/fmtuno.cxx145
-rw-r--r--sc/source/ui/unoobj/tokenuno.cxx51
-rw-r--r--sc/source/ui/vba/vbarange.cxx52
-rw-r--r--sc/source/ui/view/cellsh1.cxx27
-rw-r--r--sc/source/ui/view/viewfun4.cxx128
-rw-r--r--sc/source/ui/view/viewfunc.cxx20
84 files changed, 3214 insertions, 1030 deletions
diff --git a/sc/inc/address.hxx b/sc/inc/address.hxx
index 7ba5aa9c1f32..f1859be15fcf 100644
--- a/sc/inc/address.hxx
+++ b/sc/inc/address.hxx
@@ -791,12 +791,14 @@ template< typename T > void PutInOrder( T& nStart, T& nEnd )
bool ConvertSingleRef( ScDocument* pDoc, const String& rRefString,
SCTAB nDefTab, ScRefAddress& rRefAddress,
- const ScAddress::Details& rDetails = ScAddress::detailsOOOa1);
+ const ScAddress::Details& rDetails = ScAddress::detailsOOOa1,
+ ScAddress::ExternalInfo* pExtInfo = NULL );
bool ConvertDoubleRef(ScDocument* pDoc, const String& rRefString,
SCTAB nDefTab, ScRefAddress& rStartRefAddress,
ScRefAddress& rEndRefAddress,
- const ScAddress::Details& rDetails = ScAddress::detailsOOOa1);
+ const ScAddress::Details& rDetails = ScAddress::detailsOOOa1,
+ ScAddress::ExternalInfo* pExtInfo = NULL );
/// append alpha representation of column to buffer
SC_DLLPUBLIC void ScColToAlpha( rtl::OUStringBuffer& rBuffer, SCCOL nCol);
diff --git a/sc/inc/cell.hxx b/sc/inc/cell.hxx
index e04ec9af50ab..10de035abf7c 100644
--- a/sc/inc/cell.hxx
+++ b/sc/inc/cell.hxx
@@ -387,6 +387,15 @@ public:
inline USHORT GetSeenInIteration() const { return nSeenInIteration; }
BOOL HasOneReference( ScRange& r ) const;
+ /* Checks if the formula contains reference list that can be
+ expressed by one reference (like A1;A2;A3:A5 -> A1:A5). The
+ reference list is not required to be sorted (i.e. A3;A1;A2 is
+ still recognized as A1:A3), but no overlapping is allowed.
+ If one reference is recognized, the rRange is filled.
+
+ It is similar to HasOneReference(), but more general.
+ */
+ bool HasRefListExpressibleAsOneReference(ScRange& rRange) const;
BOOL HasRelNameReference() const;
BOOL HasColRowName() const;
diff --git a/sc/inc/cellsuno.hxx b/sc/inc/cellsuno.hxx
index e73869489ebc..2dd0bd6cc16e 100644
--- a/sc/inc/cellsuno.hxx
+++ b/sc/inc/cellsuno.hxx
@@ -629,9 +629,10 @@ protected:
throw(::com::sun::star::lang::IndexOutOfBoundsException,
::com::sun::star::uno::RuntimeException);
- void SetArrayFormula_Impl( const rtl::OUString& aFormula,
- const formula::FormulaGrammar::Grammar eGrammar )
- throw(::com::sun::star::uno::RuntimeException);
+ void SetArrayFormula_Impl( const rtl::OUString& rFormula,
+ const rtl::OUString& rFormulaNmsp,
+ const formula::FormulaGrammar::Grammar eGrammar )
+ throw(::com::sun::star::uno::RuntimeException);
public:
ScCellRangeObj(ScDocShell* pDocSh, const ScRange& rR);
@@ -650,7 +651,8 @@ public:
virtual void RefChanged();
// via getImplementation()
- virtual void SetArrayFormulaWithGrammar( const ::rtl::OUString& aFormula,
+ virtual void SetArrayFormulaWithGrammar( const ::rtl::OUString& rFormula,
+ const ::rtl::OUString& rFormulaNmsp,
const formula::FormulaGrammar::Grammar )
throw(::com::sun::star::uno::RuntimeException);
@@ -869,7 +871,7 @@ public:
void SetFormulaResultString( const ::rtl::OUString& rResult );
void SetFormulaResultDouble( double fResult );
void SetFormulaWithGrammar( const ::rtl::OUString& rFormula,
- const formula::FormulaGrammar::Grammar );
+ const ::rtl::OUString& rFormulaNmsp, const formula::FormulaGrammar::Grammar );
const ScAddress& GetPosition() const { return aCellPos; }
// XText
diff --git a/sc/inc/compiler.hxx b/sc/inc/compiler.hxx
index 155630a97ac2..76293479660c 100644
--- a/sc/inc/compiler.hxx
+++ b/sc/inc/compiler.hxx
@@ -311,9 +311,11 @@ private:
const CharClass* pCharClass; // which character classification is used for parseAnyToken
USHORT mnPredetectedReference; // reference when reading ODF, 0 (none), 1 (single) or 2 (double)
SCsTAB nMaxTab; // last sheet in document
+ sal_Int32 mnRangeOpPosInSymbol; // if and where a range operator is in symbol
const Convention *pConv;
bool mbCloseBrackets; // whether to close open brackets automatically, default TRUE
bool mbExtendedErrorDetection;
+ bool mbRewind; // whether symbol is to be rewound to some step during lexical analysis
BOOL NextNewToken(bool bInArray = false);
@@ -352,9 +354,9 @@ public:
const formula::FormulaGrammar::AddressConvention eConv = formula::FormulaGrammar::CONV_OOO );
static BOOL EnQuote( String& rStr );
-
sal_Unicode GetNativeAddressSymbol( Convention::SpecialSymbolType eType ) const;
+
// Check if it is a valid english function name
bool IsEnglishSymbol( const String& rName );
@@ -394,6 +396,8 @@ public:
maExternalLinks = rLinks;
}
+ void CreateStringFromXMLTokenArray( String& rFormula, String& rFormulaNmsp );
+
void SetExtendedErrorDetection( bool bVal ) { mbExtendedErrorDetection = bVal; }
BOOL IsCorrected() { return bCorrected; }
@@ -401,12 +405,13 @@ public:
// Use convention from this->aPos by default
ScTokenArray* CompileString( const String& rFormula );
+ ScTokenArray* CompileString( const String& rFormula, const String& rFormulaNmsp );
const ScDocument* GetDoc() const { return pDoc; }
const ScAddress& GetPos() const { return aPos; }
- void MoveRelWrap();
- static void MoveRelWrap( ScTokenArray& rArr, ScDocument* pDoc,
- const ScAddress& rPos );
+ void MoveRelWrap( SCCOL nMaxCol, SCROW nMaxRow );
+ static void MoveRelWrap( ScTokenArray& rArr, ScDocument* pDoc, const ScAddress& rPos,
+ SCCOL nMaxCol, SCROW nMaxRow );
BOOL UpdateNameReference( UpdateRefMode eUpdateRefMode,
const ScRange&,
diff --git a/sc/inc/conditio.hxx b/sc/inc/conditio.hxx
index 42a030b8e809..edb0f9371788 100644
--- a/sc/inc/conditio.hxx
+++ b/sc/inc/conditio.hxx
@@ -84,7 +84,10 @@ class SC_DLLPUBLIC ScConditionEntry
double nVal2;
String aStrVal1; // eingegeben oder berechnet
String aStrVal2;
- formula::FormulaGrammar::Grammar eTempGrammar; // grammar to be used on (re)compilation, e.g. in XML import
+ String aStrNmsp1; // namespace to be used on (re)compilation, e.g. in XML import
+ String aStrNmsp2; // namespace to be used on (re)compilation, e.g. in XML import
+ formula::FormulaGrammar::Grammar eTempGrammar1; // grammar to be used on (re)compilation, e.g. in XML import
+ formula::FormulaGrammar::Grammar eTempGrammar2; // grammar to be used on (re)compilation, e.g. in XML import
BOOL bIsStr1; // um auch leere Strings zu erkennen
BOOL bIsStr2;
ScTokenArray* pFormula1; // eingegebene Formel
@@ -101,7 +104,10 @@ class SC_DLLPUBLIC ScConditionEntry
void MakeCells( const ScAddress& rPos );
void Compile( const String& rExpr1, const String& rExpr2,
- const formula::FormulaGrammar::Grammar eGrammar, BOOL bTextToReal );
+ const String& rExprNmsp1, const String& rExprNmsp2,
+ formula::FormulaGrammar::Grammar eGrammar1,
+ formula::FormulaGrammar::Grammar eGrammar2,
+ BOOL bTextToReal );
void Interpret( const ScAddress& rPos );
BOOL IsValid( double nArg ) const;
@@ -111,7 +117,9 @@ public:
ScConditionEntry( ScConditionMode eOper,
const String& rExpr1, const String& rExpr2,
ScDocument* pDocument, const ScAddress& rPos,
- const formula::FormulaGrammar::Grammar eGrammar );
+ const String& rExprNmsp1, const String& rExprNmsp2,
+ formula::FormulaGrammar::Grammar eGrammar1,
+ formula::FormulaGrammar::Grammar eGrammar2 );
ScConditionEntry( ScConditionMode eOper,
const ScTokenArray* pArr1, const ScTokenArray* pArr2,
ScDocument* pDocument, const ScAddress& rPos );
@@ -174,7 +182,10 @@ public:
const String& rExpr1, const String& rExpr2,
ScDocument* pDocument, const ScAddress& rPos,
const String& rStyle,
- const formula::FormulaGrammar::Grammar eGrammar = formula::FormulaGrammar::GRAM_DEFAULT );
+ const String& rExprNmsp1 = EMPTY_STRING,
+ const String& rExprNmsp2 = EMPTY_STRING,
+ formula::FormulaGrammar::Grammar eGrammar1 = formula::FormulaGrammar::GRAM_DEFAULT,
+ formula::FormulaGrammar::Grammar eGrammar2 = formula::FormulaGrammar::GRAM_DEFAULT );
ScCondFormatEntry( ScConditionMode eOper,
const ScTokenArray* pArr1, const ScTokenArray* pArr2,
ScDocument* pDocument, const ScAddress& rPos,
diff --git a/sc/inc/datauno.hxx b/sc/inc/datauno.hxx
index 405d49e2a6b2..a93bfc341573 100644
--- a/sc/inc/datauno.hxx
+++ b/sc/inc/datauno.hxx
@@ -50,6 +50,7 @@
#include <com/sun/star/lang/XUnoTunnel.hpp>
#include <com/sun/star/container/XNamed.hpp>
#include <com/sun/star/util/XRefreshable.hpp>
+#include <com/sun/star/sheet/XSheetFilterDescriptor2.hpp>
#include <cppuhelper/implbase2.hxx>
#include <cppuhelper/implbase3.hxx>
#include <cppuhelper/implbase4.hxx>
@@ -340,8 +341,9 @@ public:
// to uno, all three look the same
-class ScFilterDescriptorBase : public cppu::WeakImplHelper3<
+class ScFilterDescriptorBase : public cppu::WeakImplHelper4<
com::sun::star::sheet::XSheetFilterDescriptor,
+ com::sun::star::sheet::XSheetFilterDescriptor2,
com::sun::star::beans::XPropertySet,
com::sun::star::lang::XServiceInfo >,
public SfxListener
@@ -368,6 +370,13 @@ public:
::com::sun::star::sheet::TableFilterField >& aFilterFields )
throw(::com::sun::star::uno::RuntimeException);
+ // XSheetFilterDescriptor2
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::sheet::TableFilterField2 > SAL_CALL
+ getFilterFields2() throw(::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL setFilterFields2( const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::sheet::TableFilterField2 >& aFilterFields )
+ throw(::com::sun::star::uno::RuntimeException);
+
// XPropertySet
virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo >
SAL_CALL getPropertySetInfo()
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 17c3234a7723..c8d3751a7aaf 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -139,6 +139,7 @@ class ScTemporaryChartLock;
class ScLookupCache;
struct ScLookupCacheMapImpl;
class SfxUndoManager;
+class ScFormulaParserPool;
namespace com { namespace sun { namespace star {
namespace lang {
@@ -291,6 +292,11 @@ private:
::std::auto_ptr<ScDocProtection> pDocProtection;
::std::auto_ptr<ScExternalRefManager> pExternalRefMgr;
+
+ // mutable for lazy construction
+ mutable ::std::auto_ptr< ScFormulaParserPool >
+ mxFormulaParserPool; /// Pool for all external formula parsers used by this document.
+
String aDocName; // opt: Dokumentname
ScRangePairListRef xColNameRanges;
ScRangePairListRef xRowNameRanges;
@@ -619,6 +625,10 @@ public:
void MarkUsedExternalReferences();
bool MarkUsedExternalReferences( ScTokenArray & rArr );
+ /** Returns the pool containing external formula parsers. Creates the pool
+ on first call. */
+ ScFormulaParserPool& GetFormulaParserPool() const;
+
BOOL HasDdeLinks() const;
BOOL HasAreaLinks() const;
void UpdateExternalRefLinks();
diff --git a/sc/inc/externalrefmgr.hxx b/sc/inc/externalrefmgr.hxx
index 07c8a6a6697f..9b12dba52f1f 100644
--- a/sc/inc/externalrefmgr.hxx
+++ b/sc/inc/externalrefmgr.hxx
@@ -132,15 +132,27 @@ public:
class Table
{
public:
+
+ enum ReferencedFlag
+ {
+ UNREFERENCED,
+ REFERENCED_MARKED, // marked as referenced during store to file
+ REFERENCED_PERMANENT // permanently marked, e.g. from within interpreter
+ };
+
Table();
~Table();
SC_DLLPUBLIC void setCell(SCCOL nCol, SCROW nRow, TokenRef pToken, sal_uInt32 nFmtIndex = 0);
TokenRef getCell(SCCOL nCol, SCROW nRow, sal_uInt32* pnFmtIndex = NULL) const;
bool hasRow( SCROW nRow ) const;
- /// A temporary state used only during store to file.
- bool isReferenced() const;
+ /** Set/clear referenced status flag only if current status is not
+ REFERENCED_PERMANENT. */
void setReferenced( bool bReferenced );
+ /// Unconditionally set the reference status flag.
+ void setReferencedFlag( ReferencedFlag eFlag );
+ ReferencedFlag getReferencedFlag() const;
+ bool isReferenced() const;
/// Obtain a sorted vector of rows.
void getAllRows(::std::vector<SCROW>& rRows) const;
/// Obtain a sorted vector of columns.
@@ -148,8 +160,8 @@ public:
void getAllNumberFormats(::std::vector<sal_uInt32>& rNumFmts) const;
private:
- RowsDataType maRows;
- bool mbReferenced;
+ RowsDataType maRows;
+ ReferencedFlag meReferenced;
};
typedef ::boost::shared_ptr<Table> TableTypeRef;
@@ -219,9 +231,16 @@ public:
* Set a table as referenced, used only during store-to-file.
* @returns <TRUE/> if ALL tables of ALL documents are marked.
*/
- bool setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName );
+ bool setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName, size_t nSheets, bool bPermanent );
void setAllCacheTableReferencedStati( bool bReferenced );
bool areAllCacheTablesReferenced() const;
+
+ /**
+ * Set a table as permanently referenced, to be called if not in
+ * mark-during-store-to-file cycle.
+ */
+ void setCacheTableReferencedPermanently( sal_uInt16 nFileId, const String& rTabName, size_t nSheets );
+
private:
struct ReferencedStatus
{
@@ -497,10 +516,16 @@ public:
* Set a table as referenced, used only during store-to-file.
* @returns <TRUE/> if ALL tables of ALL external documents are marked.
*/
- bool setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName );
+ bool setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName, size_t nSheets );
void setAllCacheTableReferencedStati( bool bReferenced );
/**
+ * Set a table as permanently referenced, to be called if not in
+ * mark-during-store-to-file cycle.
+ */
+ void setCacheTableReferencedPermanently( sal_uInt16 nFileId, const String& rTabName, size_t nSheets );
+
+ /**
* @returns <TRUE/> if setAllCacheTableReferencedStati(false) was called,
* <FALSE/> if setAllCacheTableReferencedStati(true) was called.
*/
diff --git a/sc/inc/fmtuno.hxx b/sc/inc/fmtuno.hxx
index ba4e02041faa..6005a849fb0f 100644
--- a/sc/inc/fmtuno.hxx
+++ b/sc/inc/fmtuno.hxx
@@ -32,7 +32,8 @@
#define SC_FMTUNO_HXX
#include "address.hxx"
-#include "formula/grammar.hxx"
+#include "conditio.hxx"
+#include <formula/grammar.hxx>
#include <tools/list.hxx>
#include <svtools/itemprop.hxx>
#include <com/sun/star/sheet/XSheetConditionalEntries.hpp>
@@ -61,16 +62,19 @@ struct ScCondFormatEntryItem
{
::com::sun::star::uno::Sequence< ::com::sun::star::sheet::FormulaToken > maTokens1;
::com::sun::star::uno::Sequence< ::com::sun::star::sheet::FormulaToken > maTokens2;
- String maExpr1;
- String maExpr2;
- String maPosStr; // formula position as text
- String maStyle; // display name as stored in ScStyleSheet
- ScAddress maPos;
- formula::FormulaGrammar::Grammar meGrammar; // grammar used with maExpr1 and maExpr2
- USHORT mnMode; // stores enum ScConditionMode
+ String maExpr1;
+ String maExpr2;
+ String maExprNmsp1;
+ String maExprNmsp2;
+ String maPosStr; // formula position as text
+ String maStyle; // display name as stored in ScStyleSheet
+ ScAddress maPos;
+ formula::FormulaGrammar::Grammar meGrammar1; // grammar used with maExpr1
+ formula::FormulaGrammar::Grammar meGrammar2; // grammar used with maExpr2
+ ScConditionMode meMode;
// Make sure the grammar is initialized for API calls.
- ScCondFormatEntryItem() : meGrammar( formula::FormulaGrammar::GRAM_UNSPECIFIED ) {}
+ ScCondFormatEntryItem();
};
class ScTableConditionalFormat : public cppu::WeakImplHelper5<
@@ -89,11 +93,11 @@ private:
ScTableConditionalFormat(); // disable
public:
ScTableConditionalFormat(ScDocument* pDoc, ULONG nKey,
- const formula::FormulaGrammar::Grammar eGrammar);
+ formula::FormulaGrammar::Grammar eGrammar);
virtual ~ScTableConditionalFormat();
- void FillFormat( ScConditionalFormat& rFormat,
- ScDocument* pDoc, formula::FormulaGrammar::Grammar eGrammar ) const;
+ void FillFormat( ScConditionalFormat& rFormat, ScDocument* pDoc,
+ formula::FormulaGrammar::Grammar eGrammar) const;
void DataChanged();
// XSheetConditionalEntries
@@ -211,7 +215,10 @@ private:
USHORT nMode; // enum ScConditionMode
String aExpr1;
String aExpr2;
- formula::FormulaGrammar::Grammar meGrammar; // grammar used with aExpr1 and aExpr2
+ String maExprNmsp1;
+ String maExprNmsp2;
+ formula::FormulaGrammar::Grammar meGrammar1; // grammar used with aExpr1 and aExpr2
+ formula::FormulaGrammar::Grammar meGrammar2; // grammar used with aExpr1 and aExpr2
::com::sun::star::uno::Sequence< ::com::sun::star::sheet::FormulaToken > aTokens1;
::com::sun::star::uno::Sequence< ::com::sun::star::sheet::FormulaToken > aTokens2;
ScAddress aSrcPos;
diff --git a/sc/inc/formulaparserpool.hxx b/sc/inc/formulaparserpool.hxx
new file mode 100644
index 000000000000..af6b0ed3ebf1
--- /dev/null
+++ b/sc/inc/formulaparserpool.hxx
@@ -0,0 +1,70 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: formulaparserpool.hxx,v $
+ * $Revision: 1.1 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SC_FORMULAPARSERPOOL_HXX
+#define SC_FORMULAPARSERPOOL_HXX
+
+#include <hash_map>
+#include <com/sun/star/sheet/XFormulaParser.hpp>
+
+class ScDocument;
+
+// ============================================================================
+
+/** Stores the used instances of the FilterFormulaParser service
+ implementations, mapped by the formula namespace they support. */
+class ScFormulaParserPool
+{
+public:
+ explicit ScFormulaParserPool( const ScDocument& rDoc );
+ ~ScFormulaParserPool();
+
+ /** Returns true, if a formula parser is registered for the passed namespace. */
+ bool hasFormulaParser( const ::rtl::OUString& rNamespace );
+
+ /** Returns the formula parser that is registered for the passed namespace. */
+ ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XFormulaParser >
+ getFormulaParser( const ::rtl::OUString& rNamespace );
+
+private:
+ typedef ::std::hash_map<
+ ::rtl::OUString,
+ ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XFormulaParser >,
+ ::rtl::OUStringHash,
+ ::std::equal_to< ::rtl::OUString > > ParserMap;
+
+ const ScDocument& mrDoc;
+ ParserMap maParsers;
+};
+
+// ============================================================================
+
+#endif
+
diff --git a/sc/inc/global.hxx b/sc/inc/global.hxx
index 76f5fd665033..e329f477d824 100644
--- a/sc/inc/global.hxx
+++ b/sc/inc/global.hxx
@@ -728,7 +728,13 @@ enum ScQueryOp
SC_TOPVAL,
SC_BOTVAL,
SC_TOPPERC,
- SC_BOTPERC
+ SC_BOTPERC,
+ SC_CONTAINS,
+ SC_DOES_NOT_CONTAIN,
+ SC_BEGINS_WITH,
+ SC_DOES_NOT_BEGIN_WITH,
+ SC_ENDS_WITH,
+ SC_DOES_NOT_END_WITH
};
// -----------------------------------------------------------------------
diff --git a/sc/inc/pch/precompiled_sc.hxx b/sc/inc/pch/precompiled_sc.hxx
index 1b0f7150c022..956bdaf6994d 100644
--- a/sc/inc/pch/precompiled_sc.hxx
+++ b/sc/inc/pch/precompiled_sc.hxx
@@ -36,6 +36,7 @@
#include <algorithm>
#include <assert.h>
+#include <deque>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
@@ -49,6 +50,8 @@
#include <new>
#include <cfloat>
+#include <boost/bind.hpp>
+
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b3dpolygon.hxx>
#include <basegfx/polygon/b3dpolypolygon.hxx>
diff --git a/sc/inc/progress.hxx b/sc/inc/progress.hxx
index b30cf6d9dc70..c7706c2bc26b 100644
--- a/sc/inc/progress.hxx
+++ b/sc/inc/progress.hxx
@@ -36,6 +36,17 @@
class ScDocument;
+/*
+ * #i102566
+ * Drawing a progress bar update is not cheap, so if we draw it on every
+ * percentage change of 200 calculations we get one progress draw per 2
+ * calculations which is slower than doing the calculations themselves. So as a
+ * rough guide only do an update per MIN_NO_CODES_PER_PROGRESS_UPDATE
+ * calculations
+ */
+#define MIN_NO_CODES_PER_PROGRESS_UPDATE 100
+
+
class SC_DLLPUBLIC ScProgress
{
private:
diff --git a/sc/inc/rangenam.hxx b/sc/inc/rangenam.hxx
index 962aff918e7b..002adf9b77ce 100644
--- a/sc/inc/rangenam.hxx
+++ b/sc/inc/rangenam.hxx
@@ -81,6 +81,11 @@ private:
USHORT nIndex;
BOOL bModified; // wird bei UpdateReference gesetzt/geloescht
+ // max row and column to use for wrapping of references. If -1 use the
+ // application's default.
+ SCROW mnMaxRow;
+ SCCOL mnMaxCol;
+
friend class ScRangeName;
ScRangeData( USHORT nIndex );
public:
@@ -153,6 +158,11 @@ public:
static void MakeValidName( String& rName );
SC_DLLPUBLIC static BOOL IsNameValid( const String& rName, ScDocument* pDoc );
+
+ SC_DLLPUBLIC void SetMaxRow(SCROW nRow);
+ SCROW GetMaxRow() const;
+ SC_DLLPUBLIC void SetMaxCol(SCCOL nCol);
+ SCCOL GetMaxCol() const;
};
inline BOOL ScRangeData::HasType( RangeType nType ) const
diff --git a/sc/inc/refdata.hxx b/sc/inc/refdata.hxx
index 6a51d66fdc07..12f29943fce0 100644
--- a/sc/inc/refdata.hxx
+++ b/sc/inc/refdata.hxx
@@ -109,6 +109,8 @@ struct SC_DLLPUBLIC ScSingleRefData // Single reference (one address) int
inline BOOL IsRelName() const { return Flags.bRelName; }
inline BOOL Valid() const;
+ /// In external references nTab is -1
+ inline bool ValidExternal() const;
void SmartRelAbs( const ScAddress& rPos );
void CalcRelFromAbs( const ScAddress& rPos );
@@ -147,6 +149,13 @@ inline BOOL ScSingleRefData::Valid() const
nTab >= 0 && nTab <= MAXTAB;
}
+inline bool ScSingleRefData::ValidExternal() const
+{
+ return nCol >= 0 && nCol <= MAXCOL &&
+ nRow >= 0 && nRow <= MAXROW &&
+ nTab == -1;
+}
+
struct ScComplexRefData // Complex reference (a range) into the sheet
{
@@ -181,6 +190,10 @@ struct ScComplexRefData // Complex reference (a range) into the sheet
{ return Ref1.IsDeleted() || Ref2.IsDeleted(); }
inline BOOL Valid() const
{ return Ref1.Valid() && Ref2.Valid(); }
+ /** In external references nTab is -1 for the start tab and -1 for the end
+ tab if one sheet, or >=0 if more than one sheets. */
+ inline bool ValidExternal() const;
+
/// Absolute references have to be up-to-date when calling this!
void PutInOrder();
inline BOOL operator==( const ScComplexRefData& r ) const
@@ -192,4 +205,12 @@ struct ScComplexRefData // Complex reference (a range) into the sheet
ScComplexRefData& Extend( const ScComplexRefData & rRef, const ScAddress & rPos );
};
+inline bool ScComplexRefData::ValidExternal() const
+{
+ return Ref1.ValidExternal() &&
+ Ref2.nCol >= 0 && Ref2.nCol <= MAXCOL &&
+ Ref2.nRow >= 0 && Ref2.nRow <= MAXROW &&
+ Ref2.nTab >= Ref1.nTab;
+}
+
#endif
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 7d9bf90a3d81..8b2227d48dbb 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -267,16 +267,28 @@ public:
void GetString( SCCOL nCol, SCROW nRow, String& rString );
void GetInputString( SCCOL nCol, SCROW nRow, String& rString );
double GetValue( const ScAddress& rPos ) const
- { return aCol[rPos.Col()].GetValue( rPos.Row() ); }
+ {
+ return ValidColRow(rPos.Col(),rPos.Row()) ?
+ aCol[rPos.Col()].GetValue( rPos.Row() ) :
+ 0.0;
+ }
double GetValue( SCCOL nCol, SCROW nRow );
void GetFormula( SCCOL nCol, SCROW nRow, String& rFormula,
BOOL bAsciiExport = FALSE );
CellType GetCellType( const ScAddress& rPos ) const
- { return aCol[rPos.Col()].GetCellType( rPos.Row() ); }
+ {
+ return ValidColRow(rPos.Col(),rPos.Row()) ?
+ aCol[rPos.Col()].GetCellType( rPos.Row() ) :
+ CELLTYPE_NONE;
+ }
CellType GetCellType( SCCOL nCol, SCROW nRow ) const;
ScBaseCell* GetCell( const ScAddress& rPos ) const
- { return aCol[rPos.Col()].GetCell( rPos.Row() ); }
+ {
+ return ValidColRow(rPos.Col(),rPos.Row()) ?
+ aCol[rPos.Col()].GetCell( rPos.Row() ) :
+ NULL;
+ }
ScBaseCell* GetCell( SCCOL nCol, SCROW nRow ) const;
void GetLastDataPos(SCCOL& rCol, SCROW& rRow) const;
@@ -378,7 +390,11 @@ public:
SCCOL nEndCol, SCROW nEndRow ) const;
USHORT GetErrCode( const ScAddress& rPos ) const
- { return aCol[rPos.Col()].GetErrCode( rPos.Row() ); }
+ {
+ return ValidColRow(rPos.Col(),rPos.Row()) ?
+ aCol[rPos.Col()].GetErrCode( rPos.Row() ) :
+ 0;
+ }
//UNUSED2008-05 USHORT GetErrCode( SCCOL nCol, SCROW nRow ) const;
void ResetChanged( const ScRange& rRange );
@@ -454,7 +470,11 @@ public:
const ScPatternAttr* GetMostUsedPattern( SCCOL nCol, SCROW nStartRow, SCROW nEndRow ) const;
ULONG GetNumberFormat( const ScAddress& rPos ) const
- { return aCol[rPos.Col()].GetNumberFormat( rPos.Row() ); }
+ {
+ return ValidColRow(rPos.Col(),rPos.Row()) ?
+ aCol[rPos.Col()].GetNumberFormat( rPos.Row() ) :
+ 0;
+ }
ULONG GetNumberFormat( SCCOL nCol, SCROW nRow ) const;
void MergeSelectionPattern( ScMergePatternState& rState,
const ScMarkData& rMark, BOOL bDeep ) const;
@@ -473,7 +493,10 @@ public:
void ApplyPattern( SCCOL nCol, SCROW nRow, const ScPatternAttr& rAttr );
void ApplyPatternArea( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, const ScPatternAttr& rAttr );
void SetPattern( const ScAddress& rPos, const ScPatternAttr& rAttr, BOOL bPutToPool = FALSE )
- { aCol[rPos.Col()].SetPattern( rPos.Row(), rAttr, bPutToPool ); }
+ {
+ if (ValidColRow(rPos.Col(),rPos.Row()))
+ aCol[rPos.Col()].SetPattern( rPos.Row(), rAttr, bPutToPool );
+ }
void SetPattern( SCCOL nCol, SCROW nRow, const ScPatternAttr& rAttr, BOOL bPutToPool = FALSE );
void ApplyPatternIfNumberformatIncompatible( const ScRange& rRange,
const ScPatternAttr& rPattern, short nNewType );
diff --git a/sc/inc/tokenuno.hxx b/sc/inc/tokenuno.hxx
index abb9d1d06a22..bcd3435668be 100644
--- a/sc/inc/tokenuno.hxx
+++ b/sc/inc/tokenuno.hxx
@@ -31,15 +31,14 @@
#ifndef SC_TOKENUNO_HXX
#define SC_TOKENUNO_HXX
-#include <svtools/lstner.hxx>
-#include <com/sun/star/sheet/FormulaToken.hpp>
#include <com/sun/star/uno/Sequence.hxx>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
-#include <com/sun/star/sheet/XFormulaParser.hpp>
-#include <com/sun/star/sheet/XFormulaOpCodeMapper.hpp>
#include <com/sun/star/sheet/FormulaOpCodeMapEntry.hpp>
+#include <com/sun/star/sheet/FormulaToken.hpp>
+#include <com/sun/star/sheet/XFormulaParser.hpp>
#include <cppuhelper/implbase3.hxx>
+#include <svtools/lstner.hxx>
#include <formula/FormulaOpCodeMapperObj.hxx>
#include "address.hxx"
#include "compiler.hxx"
@@ -47,6 +46,7 @@
class ScTokenArray;
class ScDocShell;
+// ============================================================================
class ScTokenConversion
{
@@ -61,6 +61,7 @@ public:
const ScTokenArray& rTokenArray );
};
+// ============================================================================
class ScFormulaParserObj : public ::cppu::WeakImplHelper3<
::com::sun::star::sheet::XFormulaParser,
@@ -73,7 +74,6 @@ private:
::com::sun::star::uno::Sequence< const ::com::sun::star::sheet::ExternalLinkInfo > maExternalLinks;
ScCompiler::OpCodeMapPtr mxOpCodeMap;
ScDocShell* mpDocShell;
- ScAddress maRefPos;
sal_Int16 mnConv;
bool mbEnglish;
bool mbIgnoreSpaces;
@@ -89,10 +89,12 @@ public:
// XFormulaParser
virtual ::com::sun::star::uno::Sequence< ::com::sun::star::sheet::FormulaToken > SAL_CALL parseFormula(
- const ::rtl::OUString& aFormula )
+ const ::rtl::OUString& aFormula,
+ const ::com::sun::star::table::CellAddress& rReferencePos )
throw (::com::sun::star::uno::RuntimeException);
virtual ::rtl::OUString SAL_CALL printFormula( const ::com::sun::star::uno::Sequence<
- ::com::sun::star::sheet::FormulaToken >& aTokens )
+ ::com::sun::star::sheet::FormulaToken >& aTokens,
+ const ::com::sun::star::table::CellAddress& rReferencePos )
throw (::com::sun::star::uno::RuntimeException);
// XPropertySet
@@ -145,11 +147,15 @@ public:
throw(::com::sun::star::uno::RuntimeException);
};
+// ============================================================================
+
class ScFormulaOpCodeMapperObj : public formula::FormulaOpCodeMapperObj
{
public:
ScFormulaOpCodeMapperObj(::std::auto_ptr<formula::FormulaCompiler> _pCompiler);
};
+// ============================================================================
+
#endif
diff --git a/sc/inc/unonames.hxx b/sc/inc/unonames.hxx
index 367e7d7cfe35..010e420feb42 100644
--- a/sc/inc/unonames.hxx
+++ b/sc/inc/unonames.hxx
@@ -318,7 +318,10 @@
#define SC_UNONAME_FORMULA2 "Formula2"
#define SC_UNONAME_SOURCEPOS "SourcePosition"
#define SC_UNONAME_SOURCESTR "SourcePositionAsString" // only for use in XML filter
-#define SC_UNONAME_GRAMMAR "Grammar" // only for use in XML filter
+#define SC_UNONAME_FORMULANMSP1 "FormulaNamespace1" // only for use in XML filter
+#define SC_UNONAME_FORMULANMSP2 "FormulaNamespace2" // only for use in XML filter
+#define SC_UNONAME_GRAMMAR1 "Grammar1" // only for use in XML filter
+#define SC_UNONAME_GRAMMAR2 "Grammar2" // only for use in XML filter
#define SC_UNONAME_STYLENAME "StyleName"
// validation
@@ -599,7 +602,6 @@
// <--
// FormulaParser
-#define SC_UNO_REFERENCEPOS "ReferencePosition"
#define SC_UNO_COMPILEENGLISH "CompileEnglish"
#define SC_UNO_FORMULACONVENTION "FormulaConvention"
#define SC_UNO_IGNORELEADING "IgnoreLeadingSpaces"
diff --git a/sc/inc/validat.hxx b/sc/inc/validat.hxx
index d3588c366a7c..cea9c154f04a 100644
--- a/sc/inc/validat.hxx
+++ b/sc/inc/validat.hxx
@@ -93,7 +93,9 @@ public:
ScValidationData( ScValidationMode eMode, ScConditionMode eOper,
const String& rExpr1, const String& rExpr2,
ScDocument* pDocument, const ScAddress& rPos,
- const formula::FormulaGrammar::Grammar eGrammar = formula::FormulaGrammar::GRAM_DEFAULT );
+ const String& rExprNmsp1 = EMPTY_STRING, const String& rExprNmsp2 = EMPTY_STRING,
+ formula::FormulaGrammar::Grammar eGrammar1 = formula::FormulaGrammar::GRAM_DEFAULT,
+ formula::FormulaGrammar::Grammar eGrammar2 = formula::FormulaGrammar::GRAM_DEFAULT );
ScValidationData( ScValidationMode eMode, ScConditionMode eOper,
const ScTokenArray* pArr1, const ScTokenArray* pArr2,
ScDocument* pDocument, const ScAddress& rPos );
diff --git a/sc/source/core/data/cell.cxx b/sc/source/core/data/cell.cxx
index fe34d185b898..da2de0b68099 100644
--- a/sc/source/core/data/cell.cxx
+++ b/sc/source/core/data/cell.cxx
@@ -1016,15 +1016,15 @@ void ScFormulaCell::CompileXML( ScProgress& rProgress )
ScCompiler aComp( pDocument, aPos, *pCode);
aComp.SetGrammar(eTempGrammar);
- String aFormula;
- aComp.CreateStringFromTokenArray( aFormula );
+ String aFormula, aFormulaNmsp;
+ aComp.CreateStringFromXMLTokenArray( aFormula, aFormulaNmsp );
pDocument->DecXMLImportedFormulaCount( aFormula.Len() );
rProgress.SetStateCountDownOnPercent( pDocument->GetXMLImportedFormulaCount() );
// pCode darf fuer Abfragen noch nicht geloescht, muss aber leer sein
if ( pCode )
pCode->Clear();
ScTokenArray* pCodeOld = pCode;
- pCode = aComp.CompileString( aFormula );
+ pCode = aComp.CompileString( aFormula, aFormulaNmsp );
delete pCodeOld;
if( !pCode->GetCodeError() )
{
@@ -1701,7 +1701,7 @@ void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam )
// Reschedule verlangsamt das ganze erheblich, nur bei Prozentaenderung ausfuehren
ScProgress::GetInterpretProgress()->SetStateCountDownOnPercent(
- pDocument->GetFormulaCodeInTree() );
+ pDocument->GetFormulaCodeInTree()/MIN_NO_CODES_PER_PROGRESS_UPDATE );
}
else
{
diff --git a/sc/source/core/data/cell2.cxx b/sc/source/core/data/cell2.cxx
index 7ef182660656..a0e776458ca2 100644
--- a/sc/source/core/data/cell2.cxx
+++ b/sc/source/core/data/cell2.cxx
@@ -34,6 +34,11 @@
// INCLUDE ---------------------------------------------------------------
+#include <algorithm>
+#include <deque>
+
+#include <boost/bind.hpp>
+
#include <vcl/mapmod.hxx>
#include <svx/editobj.hxx>
#include <svx/editstat.hxx>
@@ -175,6 +180,223 @@ void ScEditCell::SetTextObject( const EditTextObject* pObject,
// ============================================================================
+namespace
+{
+
+using std::deque;
+
+typedef SCCOLROW(*DimensionSelector)(const ScSingleRefData&);
+
+
+static SCCOLROW lcl_GetCol(const ScSingleRefData& rData)
+{
+ return rData.nCol;
+}
+
+
+static SCCOLROW lcl_GetRow(const ScSingleRefData& rData)
+{
+ return rData.nRow;
+}
+
+
+static SCCOLROW lcl_GetTab(const ScSingleRefData& rData)
+{
+ return rData.nTab;
+}
+
+
+/** Check if both references span the same range in selected dimension.
+ */
+static bool
+lcl_checkRangeDimension(
+ const SingleDoubleRefProvider& rRef1,
+ const SingleDoubleRefProvider& rRef2,
+ const DimensionSelector aWhich)
+{
+ return
+ aWhich(rRef1.Ref1) == aWhich(rRef2.Ref1)
+ && aWhich(rRef1.Ref2) == aWhich(rRef2.Ref2);
+}
+
+
+static bool
+lcl_checkRangeDimensions(
+ const SingleDoubleRefProvider& rRef1,
+ const SingleDoubleRefProvider& rRef2,
+ bool& bCol, bool& bRow, bool& bTab)
+{
+ const bool bSameCols(lcl_checkRangeDimension(rRef1, rRef2, lcl_GetCol));
+ const bool bSameRows(lcl_checkRangeDimension(rRef1, rRef2, lcl_GetRow));
+ const bool bSameTabs(lcl_checkRangeDimension(rRef1, rRef2, lcl_GetTab));
+
+ // Test if exactly two dimensions are equal
+ if (!(bSameCols ^ bSameRows ^ bSameTabs)
+ && (bSameCols || bSameRows || bSameTabs))
+ {
+ bCol = !bSameCols;
+ bRow = !bSameRows;
+ bTab = !bSameTabs;
+ return true;
+ }
+ return false;
+}
+
+
+/** Check if references in given reference list can possibly
+ form a range. To do that, two of their dimensions must be the same.
+ */
+static bool
+lcl_checkRangeDimensions(
+ const deque<ScToken*>::const_iterator aBegin,
+ const deque<ScToken*>::const_iterator aEnd,
+ bool& bCol, bool& bRow, bool& bTab)
+{
+ deque<ScToken*>::const_iterator aCur(aBegin);
+ ++aCur;
+ const SingleDoubleRefProvider aRef(**aBegin);
+ bool bOk(false);
+ {
+ const SingleDoubleRefProvider aRefCur(**aCur);
+ bOk = lcl_checkRangeDimensions(aRef, aRefCur, bCol, bRow, bTab);
+ }
+ while (bOk && aCur != aEnd)
+ {
+ const SingleDoubleRefProvider aRefCur(**aCur);
+ bool bColTmp(false);
+ bool bRowTmp(false);
+ bool bTabTmp(false);
+ bOk = lcl_checkRangeDimensions(aRef, aRefCur, bColTmp, bRowTmp, bTabTmp);
+ bOk = bOk && (bCol == bColTmp && bRow == bRowTmp && bTab == bTabTmp);
+ ++aCur;
+ }
+
+ if (bOk && aCur == aEnd)
+ {
+ bCol = bCol;
+ bRow = bRow;
+ bTab = bTab;
+ return true;
+ }
+ return false;
+}
+
+
+bool
+lcl_lessReferenceBy(
+ const ScToken* const pRef1, const ScToken* const pRef2,
+ const DimensionSelector aWhich)
+{
+ const SingleDoubleRefProvider rRef1(*pRef1);
+ const SingleDoubleRefProvider rRef2(*pRef2);
+ return aWhich(rRef1.Ref1) < aWhich(rRef2.Ref1);
+}
+
+
+/** Returns true if range denoted by token pRef2 starts immediately after
+ range denoted by token pRef1. Dimension, in which the comparison takes
+ place, is given by aWhich.
+ */
+bool
+lcl_isImmediatelyFollowing(
+ const ScToken* const pRef1, const ScToken* const pRef2,
+ const DimensionSelector aWhich)
+{
+ const SingleDoubleRefProvider rRef1(*pRef1);
+ const SingleDoubleRefProvider rRef2(*pRef2);
+ return aWhich(rRef2.Ref1) - aWhich(rRef1.Ref2) == 1;
+}
+
+
+static bool
+lcl_checkIfAdjacent(
+ const deque<ScToken*>& rReferences,
+ const DimensionSelector aWhich)
+{
+ typedef deque<ScToken*>::const_iterator Iter;
+ Iter aBegin(rReferences.begin());
+ Iter aEnd(rReferences.end());
+ Iter aBegin1(aBegin);
+ ++aBegin1, --aEnd;
+ return std::equal(
+ aBegin, aEnd, aBegin1,
+ boost::bind(lcl_isImmediatelyFollowing, _1, _2, aWhich));
+}
+
+
+static void
+lcl_fillRangeFromRefList(
+ const deque<ScToken*>& rReferences, ScRange& rRange)
+{
+ const ScSingleRefData aStart(
+ SingleDoubleRefProvider(*rReferences.front()).Ref1);
+ rRange.aStart.Set(aStart.nCol, aStart.nRow, aStart.nTab);
+ const ScSingleRefData aEnd(
+ SingleDoubleRefProvider(*rReferences.back()).Ref2);
+ rRange.aEnd.Set(aEnd.nCol, aEnd.nRow, aEnd.nTab);
+}
+
+
+static bool
+lcl_refListFormsOneRange(
+ const ScAddress& aPos, deque<ScToken*>& rReferences,
+ ScRange& rRange)
+{
+ std::for_each(
+ rReferences.begin(), rReferences.end(),
+ bind(&ScToken::CalcAbsIfRel, _1, aPos))
+ ;
+ if (rReferences.size() == 1) {
+ lcl_fillRangeFromRefList(rReferences, rRange);
+ return true;
+ }
+
+ bool bCell(false);
+ bool bRow(false);
+ bool bTab(false);
+ if (lcl_checkRangeDimensions(rReferences.begin(), rReferences.end(),
+ bCell, bRow, bTab))
+ {
+ DimensionSelector aWhich;
+ if (bCell)
+ {
+ aWhich = lcl_GetCol;
+ }
+ else if (bRow)
+ {
+ aWhich = lcl_GetRow;
+ }
+ else if (bTab)
+ {
+ aWhich = lcl_GetTab;
+ }
+ else
+ {
+ OSL_ENSURE(false, "lcl_checkRangeDimensions shouldn't allow that!");
+ aWhich = lcl_GetRow; // initialize to avoid warning
+ }
+ // Sort the references by start of range
+ std::sort(rReferences.begin(), rReferences.end(),
+ boost::bind(lcl_lessReferenceBy, _1, _2, aWhich));
+ if (lcl_checkIfAdjacent(rReferences, aWhich))
+ {
+ lcl_fillRangeFromRefList(rReferences, rRange);
+ return true;
+ }
+ }
+ return false;
+}
+
+
+bool lcl_isReference(const FormulaToken& rToken)
+{
+ return
+ rToken.GetType() == svSingleRef ||
+ rToken.GetType() == svDoubleRef;
+}
+
+}
+
BOOL ScFormulaCell::IsEmpty()
{
if (IsDirtyOrInTableOpDirty() && pDocument->GetAutoCalc())
@@ -449,6 +671,52 @@ BOOL ScFormulaCell::HasOneReference( ScRange& r ) const
return FALSE;
}
+bool
+ScFormulaCell::HasRefListExpressibleAsOneReference(ScRange& rRange) const
+{
+ /* If there appears just one reference in the formula, it's the same
+ as HasOneReference(). If there are more of them, they can denote
+ one range if they are (sole) arguments of one function.
+ Union of these references must form one range and their
+ intersection must be empty set.
+ */
+ pCode->Reset();
+ // Get first reference, if any
+ ScToken* const pFirstReference(
+ dynamic_cast<ScToken*>(pCode->GetNextReferenceRPN()));
+ if (pFirstReference)
+ {
+ // Collect all consecutive references, starting by the one
+ // already found
+ std::deque<ScToken*> aReferences;
+ aReferences.push_back(pFirstReference);
+ FormulaToken* pToken(pCode->NextRPN());
+ FormulaToken* pFunction(0);
+ while (pToken)
+ {
+ if (lcl_isReference(*pToken))
+ {
+ aReferences.push_back(dynamic_cast<ScToken*>(pToken));
+ pToken = pCode->NextRPN();
+ }
+ else
+ {
+ if (pToken->IsFunction())
+ {
+ pFunction = pToken;
+ }
+ break;
+ }
+ }
+ if (pFunction && !pCode->GetNextReferenceRPN()
+ && (pFunction->GetParamCount() == aReferences.size()))
+ {
+ return lcl_refListFormsOneRange(aPos, aReferences, rRange);
+ }
+ }
+ return false;
+}
+
BOOL ScFormulaCell::HasRelNameReference() const
{
pCode->Reset();
@@ -799,7 +1067,7 @@ void ScFormulaCell::UpdateInsertTab(SCTAB nTable)
pCode = new ScTokenArray( *pRangeData->GetCode() );
ScCompiler aComp2(pDocument, aPos, *pCode);
aComp2.SetGrammar(pDocument->GetGrammar());
- aComp2.MoveRelWrap();
+ aComp2.MoveRelWrap(pRangeData->GetMaxCol(), pRangeData->GetMaxRow());
aComp2.UpdateInsertTab( nTable, FALSE );
// If the shared formula contained a named range/formula containing
// an absolute reference to a sheet, those have to be readjusted.
@@ -835,7 +1103,7 @@ BOOL ScFormulaCell::UpdateDeleteTab(SCTAB nTable, BOOL bIsMove)
ScCompiler aComp2(pDocument, aPos, *pCode);
aComp2.SetGrammar(pDocument->GetGrammar());
aComp2.CompileTokenArray();
- aComp2.MoveRelWrap();
+ aComp2.MoveRelWrap(pRangeData->GetMaxCol(), pRangeData->GetMaxRow());
aComp2.UpdateDeleteTab( nTable, FALSE, FALSE, bRefChanged );
// If the shared formula contained a named range/formula containing
// an absolute reference to a sheet, those have to be readjusted.
@@ -872,7 +1140,7 @@ void ScFormulaCell::UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos, SCTAB nTabNo )
ScCompiler aComp2(pDocument, aPos, *pCode);
aComp2.SetGrammar(pDocument->GetGrammar());
aComp2.CompileTokenArray();
- aComp2.MoveRelWrap();
+ aComp2.MoveRelWrap(pRangeData->GetMaxCol(), pRangeData->GetMaxRow());
aComp2.UpdateMoveTab( nOldPos, nNewPos, TRUE );
bCompile = TRUE;
}
diff --git a/sc/source/core/data/conditio.cxx b/sc/source/core/data/conditio.cxx
index 12dbf77e88e6..3c636d9049d4 100644
--- a/sc/source/core/data/conditio.cxx
+++ b/sc/source/core/data/conditio.cxx
@@ -130,7 +130,10 @@ ScConditionEntry::ScConditionEntry( const ScConditionEntry& r ) :
nVal2(r.nVal2),
aStrVal1(r.aStrVal1),
aStrVal2(r.aStrVal2),
- eTempGrammar(r.eTempGrammar),
+ aStrNmsp1(r.aStrNmsp1),
+ aStrNmsp2(r.aStrNmsp2),
+ eTempGrammar1(r.eTempGrammar1),
+ eTempGrammar2(r.eTempGrammar2),
bIsStr1(r.bIsStr1),
bIsStr2(r.bIsStr2),
pFormula1(NULL),
@@ -161,7 +164,10 @@ ScConditionEntry::ScConditionEntry( ScDocument* pDocument, const ScConditionEntr
nVal2(r.nVal2),
aStrVal1(r.aStrVal1),
aStrVal2(r.aStrVal2),
- eTempGrammar(r.eTempGrammar),
+ aStrNmsp1(r.aStrNmsp1),
+ aStrNmsp2(r.aStrNmsp2),
+ eTempGrammar1(r.eTempGrammar1),
+ eTempGrammar2(r.eTempGrammar2),
bIsStr1(r.bIsStr1),
bIsStr2(r.bIsStr2),
pFormula1(NULL),
@@ -187,14 +193,17 @@ ScConditionEntry::ScConditionEntry( ScDocument* pDocument, const ScConditionEntr
}
ScConditionEntry::ScConditionEntry( ScConditionMode eOper,
- const String& rExpr1, const String& rExpr2,
- ScDocument* pDocument, const ScAddress& rPos,
- const FormulaGrammar::Grammar eGrammar ) :
+ const String& rExpr1, const String& rExpr2, ScDocument* pDocument, const ScAddress& rPos,
+ const String& rExprNmsp1, const String& rExprNmsp2,
+ FormulaGrammar::Grammar eGrammar1, FormulaGrammar::Grammar eGrammar2 ) :
eOp(eOper),
nOptions(0), // spaeter...
nVal1(0.0),
nVal2(0.0),
- eTempGrammar(eGrammar),
+ aStrNmsp1(rExprNmsp1),
+ aStrNmsp2(rExprNmsp2),
+ eTempGrammar1(eGrammar1),
+ eTempGrammar2(eGrammar2),
bIsStr1(FALSE),
bIsStr2(FALSE),
pFormula1(NULL),
@@ -207,7 +216,7 @@ ScConditionEntry::ScConditionEntry( ScConditionMode eOper,
bRelRef2(FALSE),
bFirstRun(TRUE)
{
- Compile( rExpr1, rExpr2, eGrammar, FALSE );
+ Compile( rExpr1, rExpr2, rExprNmsp1, rExprNmsp2, eGrammar1, eGrammar2, FALSE );
// Formelzellen werden erst bei IsValid angelegt
}
@@ -219,7 +228,8 @@ ScConditionEntry::ScConditionEntry( ScConditionMode eOper,
nOptions(0), // spaeter...
nVal1(0.0),
nVal2(0.0),
- eTempGrammar(FormulaGrammar::GRAM_DEFAULT),
+ eTempGrammar1(FormulaGrammar::GRAM_DEFAULT),
+ eTempGrammar2(FormulaGrammar::GRAM_DEFAULT),
bIsStr1(FALSE),
bIsStr2(FALSE),
pFormula1(NULL),
@@ -294,15 +304,16 @@ ScConditionEntry::~ScConditionEntry()
}
void ScConditionEntry::Compile( const String& rExpr1, const String& rExpr2,
- const FormulaGrammar::Grammar eGrammar, BOOL bTextToReal )
+ const String& rExprNmsp1, const String& rExprNmsp2,
+ FormulaGrammar::Grammar eGrammar1, FormulaGrammar::Grammar eGrammar2, BOOL bTextToReal )
{
if ( rExpr1.Len() || rExpr2.Len() )
{
ScCompiler aComp( pDoc, aSrcPos );
- aComp.SetGrammar(eGrammar);
if ( rExpr1.Len() )
{
+ aComp.SetGrammar( eGrammar1 );
if ( pDoc->IsImportingXML() && !bTextToReal )
{
// temporary formula string as string tokens
@@ -313,7 +324,7 @@ void ScConditionEntry::Compile( const String& rExpr1, const String& rExpr2,
}
else
{
- pFormula1 = aComp.CompileString( rExpr1 );
+ pFormula1 = aComp.CompileString( rExpr1, rExprNmsp1 );
if ( pFormula1->GetLen() == 1 )
{
// einzelne (konstante Zahl) ?
@@ -339,6 +350,7 @@ void ScConditionEntry::Compile( const String& rExpr1, const String& rExpr2,
if ( rExpr2.Len() )
{
+ aComp.SetGrammar( eGrammar2 );
if ( pDoc->IsImportingXML() && !bTextToReal )
{
// temporary formula string as string tokens
@@ -349,7 +361,7 @@ void ScConditionEntry::Compile( const String& rExpr1, const String& rExpr2,
}
else
{
- pFormula2 = aComp.CompileString( rExpr2 );
+ pFormula2 = aComp.CompileString( rExpr2, rExprNmsp2 );
if ( pFormula2->GetLen() == 1 )
{
// einzelne (konstante Zahl) ?
@@ -429,9 +441,9 @@ void ScConditionEntry::CompileXML()
// Convert the text tokens that were created during XML import into real tokens.
- Compile( GetExpression(aSrcPos, 0, 0, eTempGrammar),
- GetExpression(aSrcPos, 1, 0, eTempGrammar),
- eTempGrammar, TRUE );
+ Compile( GetExpression(aSrcPos, 0, 0, eTempGrammar1),
+ GetExpression(aSrcPos, 1, 0, eTempGrammar2),
+ aStrNmsp1, aStrNmsp2, eTempGrammar1, eTempGrammar2, TRUE );
}
void ScConditionEntry::SetSrcString( const String& rNew )
@@ -1129,8 +1141,10 @@ ScCondFormatEntry::ScCondFormatEntry( ScConditionMode eOper,
const String& rExpr1, const String& rExpr2,
ScDocument* pDocument, const ScAddress& rPos,
const String& rStyle,
- const FormulaGrammar::Grammar eGrammar ) :
- ScConditionEntry( eOper, rExpr1, rExpr2, pDocument, rPos, eGrammar ),
+ const String& rExprNmsp1, const String& rExprNmsp2,
+ FormulaGrammar::Grammar eGrammar1,
+ FormulaGrammar::Grammar eGrammar2 ) :
+ ScConditionEntry( eOper, rExpr1, rExpr2, pDocument, rPos, rExprNmsp1, rExprNmsp2, eGrammar1, eGrammar2 ),
aStyleName( rStyle ),
pParent( NULL )
{
diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx
index 120ecb20ade4..16613fbcbab4 100644
--- a/sc/source/core/data/documen2.cxx
+++ b/sc/source/core/data/documen2.cxx
@@ -95,6 +95,7 @@
#include "lookupcache.hxx"
#include "externalrefmgr.hxx"
#include "tabprotection.hxx"
+#include "formulaparserpool.hxx"
// pImpl because including lookupcache.hxx in document.hxx isn't wanted, and
// dtor plus helpers are convenient.
@@ -154,7 +155,6 @@ ScDocument::ScDocument( ScDocumentMode eMode,
pScriptTypeData( NULL ),
pCacheFieldEditEngine( NULL ),
pDocProtection( NULL ),
- pExternalRefMgr( NULL ),
pViewOptions( NULL ),
pDocOptions( NULL ),
pExtDocOptions( NULL ),
@@ -384,15 +384,14 @@ ScDocument::~ScDocument()
pLinkManager->Remove( 0, pLinkManager->GetLinks().Count() );
}
- if (pExternalRefMgr.get())
- // Destroy the external ref mgr instance here because it has a timer
- // which needs to be stopped before the app closes.
- pExternalRefMgr.reset(NULL);
+ mxFormulaParserPool.reset();
+ // Destroy the external ref mgr instance here because it has a timer
+ // which needs to be stopped before the app closes.
+ pExternalRefMgr.reset();
ScAddInAsync::RemoveDocument( this );
ScAddInListener::RemoveDocument( this );
- delete pChartListenerCollection; // vor pBASM wg. evtl. Listener!
- pChartListenerCollection = NULL;
+ DELETEZ( pChartListenerCollection); // vor pBASM wg. evtl. Listener!
DELETEZ( pLookupCacheMapImpl); // before pBASM because of listeners
// BroadcastAreas vor allen Zellen zerstoeren um unnoetige
// Einzel-EndListenings der Formelzellen zu vermeiden
diff --git a/sc/source/core/data/documen3.cxx b/sc/source/core/data/documen3.cxx
index b194ecc4aa73..08170fd6cdc9 100644
--- a/sc/source/core/data/documen3.cxx
+++ b/sc/source/core/data/documen3.cxx
@@ -40,6 +40,7 @@
#include <sfx2/bindings.hxx>
#include <sfx2/objsh.hxx>
#include <svtools/zforlist.hxx>
+#include <svtools/PasswordHelper.hxx>
#include <vcl/svapp.hxx>
#include "document.hxx"
#include "attrib.hxx"
@@ -77,8 +78,8 @@
#include "drwlayer.hxx"
#include "unoreflist.hxx"
#include "listenercalls.hxx"
-#include "svtools/PasswordHelper.hxx"
#include "tabprotection.hxx"
+#include "formulaparserpool.hxx"
#include <memory>
@@ -509,6 +510,13 @@ void ScDocument::MarkUsedExternalReferences()
* collecting them during export. */
}
+ScFormulaParserPool& ScDocument::GetFormulaParserPool() const
+{
+ if( !mxFormulaParserPool.get() )
+ mxFormulaParserPool.reset( new ScFormulaParserPool( *this ) );
+ return *mxFormulaParserPool;
+}
+
ScOutlineTable* ScDocument::GetOutlineTable( SCTAB nTab, BOOL bCreate )
{
ScOutlineTable* pVal = NULL;
diff --git a/sc/source/core/data/documen4.cxx b/sc/source/core/data/documen4.cxx
index 3c72baff5ba4..7313ebbf83f5 100644
--- a/sc/source/core/data/documen4.cxx
+++ b/sc/source/core/data/documen4.cxx
@@ -311,9 +311,16 @@ bool ScDocument::MarkUsedExternalReferences( ScTokenArray & rArr )
switch (t->GetType())
{
case svExternalSingleRef:
- case svExternalDoubleRef:
bAllMarked = pRefMgr->setCacheTableReferenced(
- t->GetIndex(), t->GetString());
+ t->GetIndex(), t->GetString(), 1);
+ break;
+ case svExternalDoubleRef:
+ {
+ const ScComplexRefData& rRef = t->GetDoubleRef();
+ size_t nSheets = rRef.Ref2.nTab - rRef.Ref1.nTab + 1;
+ bAllMarked = pRefMgr->setCacheTableReferenced(
+ t->GetIndex(), t->GetString(), nSheets);
+ }
break;
case svExternalName:
/* TODO: external names aren't supported yet, but would
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 90eb1597023d..61cf3ab94b35 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -2484,7 +2484,7 @@ void ScDocument::GetCell( SCCOL nCol, SCROW nRow, SCTAB nTab,
ScBaseCell* ScDocument::GetCell( const ScAddress& rPos ) const
{
SCTAB nTab = rPos.Tab();
- if ( pTab[nTab] )
+ if (ValidTab(nTab) && pTab[nTab])
return pTab[nTab]->GetCell( rPos );
DBG_ERROR("GetCell ohne Tabelle");
diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx
index 09e26c731eb8..38aabaa51a55 100644
--- a/sc/source/core/data/table1.cxx
+++ b/sc/source/core/data/table1.cxx
@@ -870,6 +870,10 @@ BOOL ScTable::ValidNextPos( SCCOL nCol, SCROW nRow, const ScMarkData& rMark,
if (!ValidCol(nCol) || !ValidRow(nRow))
return FALSE;
+ if (pDocument->HasAttrib(nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_OVERLAPPED))
+ // Skip an overlapped cell.
+ return false;
+
if (bMarked && !rMark.IsCellMarked(nCol,nRow))
return FALSE;
@@ -912,7 +916,8 @@ void ScTable::GetNextPos( SCCOL& rCol, SCROW& rRow, SCsCOL nMovX, SCsROW nMovY,
{
BOOL bUp = ( nMovY < 0 );
nRow = rMark.GetNextMarked( nCol, nRow, bUp );
- while ( VALIDROW(nRow) && pRowFlags && (pRowFlags->GetValue(nRow) & CR_HIDDEN) )
+ while ( VALIDROW(nRow) && ((pRowFlags && (pRowFlags->GetValue(nRow) & CR_HIDDEN)) ||
+ pDocument->HasAttrib(nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_OVERLAPPED)) )
{
// #53697# ausgeblendete ueberspringen (s.o.)
nRow += nMovY;
@@ -941,7 +946,8 @@ void ScTable::GetNextPos( SCCOL& rCol, SCROW& rRow, SCsCOL nMovX, SCsROW nMovY,
else if (nRow > MAXROW)
nRow = 0;
nRow = rMark.GetNextMarked( nCol, nRow, bUp );
- while ( VALIDROW(nRow) && pRowFlags && (pRowFlags->GetValue(nRow) & CR_HIDDEN) )
+ while ( VALIDROW(nRow) && ((pRowFlags && (pRowFlags->GetValue(nRow) & CR_HIDDEN)) ||
+ pDocument->HasAttrib(nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_OVERLAPPED)) )
{
// #53697# ausgeblendete ueberspringen (s.o.)
nRow += nMovY;
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index cf204765b3b0..59858796078c 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -2701,7 +2701,7 @@ void ScTable::DoAutoOutline( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SC
pCell = aCol[nCol].GetCell( nRow );
if (pCell)
if ( pCell->GetCellType() == CELLTYPE_FORMULA )
- if (((ScFormulaCell*)pCell)->HasOneReference( aRef ))
+ if (((ScFormulaCell*)pCell)->HasRefListExpressibleAsOneReference( aRef ))
if ( aRef.aStart.Col() == nCol && aRef.aEnd.Col() == nCol &&
aRef.aStart.Tab() == nTab && aRef.aEnd.Tab() == nTab &&
DiffSign( aRef.aStart.Row(), nRow ) ==
@@ -2732,7 +2732,7 @@ void ScTable::DoAutoOutline( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SC
while ( aIter.Next( nRow, pCell ) && !bFound )
{
if ( pCell->GetCellType() == CELLTYPE_FORMULA )
- if (((ScFormulaCell*)pCell)->HasOneReference( aRef ))
+ if (((ScFormulaCell*)pCell)->HasRefListExpressibleAsOneReference( aRef ))
if ( aRef.aStart.Row() == nRow && aRef.aEnd.Row() == nRow &&
aRef.aStart.Tab() == nTab && aRef.aEnd.Tab() == nTab &&
DiffSign( aRef.aStart.Col(), nCol ) ==
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index 74f2a97e9c2e..ae299fdf5fca 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -1022,12 +1022,19 @@ BOOL ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
}
}
else if ( (rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL) ||
+ (rEntry.eOp == SC_CONTAINS || rEntry.eOp == SC_DOES_NOT_CONTAIN ||
+ rEntry.eOp == SC_BEGINS_WITH || rEntry.eOp == SC_ENDS_WITH ||
+ rEntry.eOp == SC_DOES_NOT_BEGIN_WITH || rEntry.eOp == SC_DOES_NOT_END_WITH) ||
(rEntry.bQueryByString && (pCell ? pCell->HasStringData() :
HasStringData(
static_cast<SCCOL>(rEntry.nField),
nRow))))
{ // by String
String aCellStr;
+ if( rEntry.eOp == SC_CONTAINS || rEntry.eOp == SC_DOES_NOT_CONTAIN
+ || rEntry.eOp == SC_BEGINS_WITH || rEntry.eOp == SC_ENDS_WITH
+ || rEntry.eOp == SC_DOES_NOT_BEGIN_WITH || rEntry.eOp == SC_DOES_NOT_END_WITH )
+ bMatchWholeCell = FALSE;
if ( pCell )
{
if (pCell->GetCellType() != CELLTYPE_NOTE)
@@ -1040,7 +1047,10 @@ BOOL ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
GetInputString( static_cast<SCCOL>(rEntry.nField), nRow, aCellStr );
BOOL bRealRegExp = (rParam.bRegExp && ((rEntry.eOp == SC_EQUAL)
- || (rEntry.eOp == SC_NOT_EQUAL)));
+ || (rEntry.eOp == SC_NOT_EQUAL) || (rEntry.eOp == SC_CONTAINS)
+ || (rEntry.eOp == SC_DOES_NOT_CONTAIN) || (rEntry.eOp == SC_BEGINS_WITH)
+ || (rEntry.eOp == SC_ENDS_WITH) || (rEntry.eOp == SC_DOES_NOT_BEGIN_WITH)
+ || (rEntry.eOp == SC_DOES_NOT_END_WITH)));
BOOL bTestRegExp = (pbTestEqualCondition && rParam.bRegExp
&& ((rEntry.eOp == SC_LESS_EQUAL)
|| (rEntry.eOp == SC_GREATER_EQUAL)));
@@ -1048,20 +1058,61 @@ BOOL ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
{
xub_StrLen nStart = 0;
xub_StrLen nEnd = aCellStr.Len();
- BOOL bMatch = (BOOL) rEntry.GetSearchTextPtr( rParam.bCaseSens )
- ->SearchFrwrd( aCellStr, &nStart, &nEnd );
+
// from 614 on, nEnd is behind the found text
+ BOOL bMatch = FALSE;
+ if ( rEntry.eOp == SC_ENDS_WITH || rEntry.eOp == SC_DOES_NOT_END_WITH )
+ {
+ nEnd = 0;
+ nStart = aCellStr.Len();
+ bMatch = (BOOL) rEntry.GetSearchTextPtr( rParam.bCaseSens )
+ ->SearchBkwrd( aCellStr, &nStart, &nEnd );
+ }
+ else
+ {
+ bMatch = (BOOL) rEntry.GetSearchTextPtr( rParam.bCaseSens )
+ ->SearchFrwrd( aCellStr, &nStart, &nEnd );
+ }
if ( bMatch && bMatchWholeCell
&& (nStart != 0 || nEnd != aCellStr.Len()) )
bMatch = FALSE; // RegExp must match entire cell string
if ( bRealRegExp )
- bOk = ((rEntry.eOp == SC_NOT_EQUAL) ? !bMatch : bMatch);
+ switch (rEntry.eOp)
+ {
+ case SC_EQUAL:
+ case SC_CONTAINS:
+ bOk = bMatch;
+ break;
+ case SC_NOT_EQUAL:
+ case SC_DOES_NOT_CONTAIN:
+ bOk = !bMatch;
+ break;
+ case SC_BEGINS_WITH:
+ bOk = ( bMatch && (nStart == 0) );
+ break;
+ case SC_DOES_NOT_BEGIN_WITH:
+ bOk = !( bMatch && (nStart == 0) );
+ break;
+ case SC_ENDS_WITH:
+ bOk = ( bMatch && (nEnd == aCellStr.Len()) );
+ break;
+ case SC_DOES_NOT_END_WITH:
+ bOk = !( bMatch && (nEnd == aCellStr.Len()) );
+ break;
+ default:
+ {
+ // added to avoid warnings
+ }
+ }
else
bTestEqual = bMatch;
}
if ( !bRealRegExp )
{
- if ( rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL )
+ if ( rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL
+ || rEntry.eOp == SC_CONTAINS || rEntry.eOp == SC_DOES_NOT_CONTAIN
+ || rEntry.eOp == SC_BEGINS_WITH || rEntry.eOp == SC_ENDS_WITH
+ || rEntry.eOp == SC_DOES_NOT_BEGIN_WITH || rEntry.eOp == SC_DOES_NOT_END_WITH )
{
if ( !rEntry.bQueryByString && rEntry.pStr->Len() == 0 )
{
@@ -1069,22 +1120,54 @@ BOOL ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
// the query value is assigned directly, and the string is empty. In that case,
// don't find any string (isEqual would find empty string results in formula cells).
bOk = FALSE;
+ if ( rEntry.eOp == SC_NOT_EQUAL )
+ bOk = !bOk;
}
else if ( bMatchWholeCell )
+ {
bOk = pTransliteration->isEqual( aCellStr, *rEntry.pStr );
+ if ( rEntry.eOp == SC_NOT_EQUAL )
+ bOk = !bOk;
+ }
else
{
- ::com::sun::star::uno::Sequence< sal_Int32 > xOff;
String aCell( pTransliteration->transliterate(
aCellStr, ScGlobal::eLnge, 0, aCellStr.Len(),
- &xOff ) );
+ NULL ) );
String aQuer( pTransliteration->transliterate(
*rEntry.pStr, ScGlobal::eLnge, 0, rEntry.pStr->Len(),
- &xOff ) );
- bOk = (aCell.Search( aQuer ) != STRING_NOTFOUND);
+ NULL ) );
+ xub_StrLen nIndex = (rEntry.eOp == SC_ENDS_WITH
+ || rEntry.eOp == SC_DOES_NOT_END_WITH)? (aCell.Len()-aQuer.Len()):0;
+ xub_StrLen nStrPos = aCell.Search( aQuer, nIndex );
+ switch (rEntry.eOp)
+ {
+ case SC_EQUAL:
+ case SC_CONTAINS:
+ bOk = ( nStrPos != STRING_NOTFOUND );
+ break;
+ case SC_NOT_EQUAL:
+ case SC_DOES_NOT_CONTAIN:
+ bOk = ( nStrPos == STRING_NOTFOUND );
+ break;
+ case SC_BEGINS_WITH:
+ bOk = ( nStrPos == 0 );
+ break;
+ case SC_DOES_NOT_BEGIN_WITH:
+ bOk = ( nStrPos != 0 );
+ break;
+ case SC_ENDS_WITH:
+ bOk = ( nStrPos + aQuer.Len() == aCell.Len() );
+ break;
+ case SC_DOES_NOT_END_WITH:
+ bOk = ( nStrPos + aQuer.Len() != aCell.Len() );
+ break;
+ default:
+ {
+ // added to avoid warnings
+ }
+ }
}
- if ( rEntry.eOp == SC_NOT_EQUAL )
- bOk = !bOk;
}
else
{ // use collator here because data was probably sorted
diff --git a/sc/source/core/data/validat.cxx b/sc/source/core/data/validat.cxx
index 0a33ab111f50..9bb8bff1081f 100644
--- a/sc/source/core/data/validat.cxx
+++ b/sc/source/core/data/validat.cxx
@@ -76,8 +76,9 @@ SV_IMPL_OP_PTRARR_SORT( ScValidationEntries_Impl, ScValidationDataPtr );
ScValidationData::ScValidationData( ScValidationMode eMode, ScConditionMode eOper,
const String& rExpr1, const String& rExpr2,
ScDocument* pDocument, const ScAddress& rPos,
- const formula::FormulaGrammar::Grammar eGrammar ) :
- ScConditionEntry( eOper, rExpr1, rExpr2, pDocument, rPos, eGrammar ),
+ const String& rExprNmsp1, const String& rExprNmsp2,
+ FormulaGrammar::Grammar eGrammar1, FormulaGrammar::Grammar eGrammar2 ) :
+ ScConditionEntry( eOper, rExpr1, rExpr2, pDocument, rPos, rExprNmsp1, rExprNmsp2, eGrammar1, eGrammar2 ),
nKey( 0 ),
eDataMode( eMode ),
eErrorStyle( SC_VALERR_STOP ),
diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
index 3d783e74c03d..9fcf743c1e85 100644
--- a/sc/source/core/inc/interpre.hxx
+++ b/sc/source/core/inc/interpre.hxx
@@ -70,6 +70,21 @@ struct ScCompare
}
};
+struct ScCompareOptions
+{
+ ScQueryEntry aQueryEntry;
+ bool bRegEx;
+ bool bMatchWholeCell;
+ bool bIgnoreCase;
+
+ ScCompareOptions( ScDocument* pDoc, const ScQueryEntry& rEntry, bool bReg );
+private:
+ // Not implemented, prevent usage.
+ ScCompareOptions();
+ ScCompareOptions( const ScCompareOptions & );
+ ScCompareOptions& operator=( const ScCompareOptions & );
+};
+
class ScToken;
#define MAXSTACK (4096 / sizeof(formula::FormulaToken*))
@@ -356,9 +371,16 @@ void ScChoseJump();
// Returns true if last jump was executed and result matrix pushed.
bool JumpMatrix( short nStackLevel );
-double CompareFunc( const ScCompare& rComp );
+/** @param pOptions
+ NULL means case sensitivity document option is to be used!
+ */
+double CompareFunc( const ScCompare& rComp, ScCompareOptions* pOptions = NULL );
double Compare();
-ScMatrixRef CompareMat();
+/** @param pOptions
+ NULL means case sensitivity document option is to be used!
+ */
+ScMatrixRef CompareMat( ScCompareOptions* pOptions = NULL );
+ScMatrixRef QueryMat( ScMatrix* pMat, ScCompareOptions& rOptions );
void ScEqual();
void ScNotEqual();
void ScLess();
diff --git a/sc/source/core/inc/refupdat.hxx b/sc/source/core/inc/refupdat.hxx
index 0461578db0a6..2a8b17335fbf 100644
--- a/sc/source/core/inc/refupdat.hxx
+++ b/sc/source/core/inc/refupdat.hxx
@@ -82,7 +82,7 @@ public:
ScComplexRefData& rRef, BOOL bWrap, BOOL bAbsolute );
static void MoveRelWrap( ScDocument* pDoc, const ScAddress& rPos,
- ScComplexRefData& rRef );
+ SCCOL nMaxCol, SCROW nMaxRow, ScComplexRefData& rRef );
/// Before calling, the absolute references must be up-to-date!
static ScRefUpdateRes UpdateTranspose( ScDocument* pDoc,
diff --git a/sc/source/core/tool/address.cxx b/sc/source/core/tool/address.cxx
index 8b13374fe501..b38d5b52e4f5 100644
--- a/sc/source/core/tool/address.cxx
+++ b/sc/source/core/tool/address.cxx
@@ -1126,39 +1126,48 @@ lcl_ScAddress_Parse ( const sal_Unicode* p, ScDocument* pDoc, ScAddress& rAddr,
bool ConvertSingleRef( ScDocument* pDoc, const String& rRefString,
SCTAB nDefTab, ScRefAddress& rRefAddress,
- const ScAddress::Details& rDetails )
+ const ScAddress::Details& rDetails,
+ ScAddress::ExternalInfo* pExtInfo /* = NULL */ )
{
- ScAddress aAddr( 0, 0, nDefTab );
- USHORT nRes = lcl_ScAddress_Parse( rRefString.GetBuffer(), pDoc, aAddr, rDetails, NULL );
- if( nRes & SCA_VALID )
+ bool bRet = false;
+ if (pExtInfo || (ScGlobal::FindUnquoted( rRefString, SC_COMPILER_FILE_TAB_SEP) == STRING_NOTFOUND))
{
- rRefAddress.Set( aAddr,
- ((nRes & SCA_COL_ABSOLUTE) == 0),
- ((nRes & SCA_ROW_ABSOLUTE) == 0),
- ((nRes & SCA_TAB_ABSOLUTE) == 0));
- return TRUE;
+ ScAddress aAddr( 0, 0, nDefTab );
+ USHORT nRes = aAddr.Parse( rRefString, pDoc, rDetails, pExtInfo);
+ if ( nRes & SCA_VALID )
+ {
+ rRefAddress.Set( aAddr,
+ ((nRes & SCA_COL_ABSOLUTE) == 0),
+ ((nRes & SCA_ROW_ABSOLUTE) == 0),
+ ((nRes & SCA_TAB_ABSOLUTE) == 0));
+ bRet = true;
+ }
}
- else
- return FALSE;
+ return bRet;
}
bool ConvertDoubleRef( ScDocument* pDoc, const String& rRefString, SCTAB nDefTab,
ScRefAddress& rStartRefAddress, ScRefAddress& rEndRefAddress,
- const ScAddress::Details& rDetails )
+ const ScAddress::Details& rDetails,
+ ScAddress::ExternalInfo* pExtInfo /* = NULL */ )
{
- BOOL bRet = FALSE;
- // FIXME : This will break for Lotus
- xub_StrLen nPos = rRefString.Search(':');
- if (nPos != STRING_NOTFOUND)
+ bool bRet = false;
+ if (pExtInfo || (ScGlobal::FindUnquoted( rRefString, SC_COMPILER_FILE_TAB_SEP) == STRING_NOTFOUND))
{
- String aTmp( rRefString );
- sal_Unicode* p = aTmp.GetBufferAccess();
- p[ nPos ] = 0;
- if( ConvertSingleRef( pDoc, p, nDefTab, rStartRefAddress, rDetails ) )
+ ScRange aRange( ScAddress( 0, 0, nDefTab));
+ USHORT nRes = aRange.Parse( rRefString, pDoc, rDetails, pExtInfo);
+ if ( nRes & SCA_VALID )
{
- nDefTab = rStartRefAddress.Tab();
- bRet = ConvertSingleRef( pDoc, p + nPos + 1, nDefTab, rEndRefAddress, rDetails );
+ rStartRefAddress.Set( aRange.aStart,
+ ((nRes & SCA_COL_ABSOLUTE) == 0),
+ ((nRes & SCA_ROW_ABSOLUTE) == 0),
+ ((nRes & SCA_TAB_ABSOLUTE) == 0));
+ rEndRefAddress.Set( aRange.aEnd,
+ ((nRes & SCA_COL2_ABSOLUTE) == 0),
+ ((nRes & SCA_ROW2_ABSOLUTE) == 0),
+ ((nRes & SCA_TAB2_ABSOLUTE) == 0));
+ bRet = true;
}
}
return bRet;
diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx
index b0e1dac5062d..bc2266cbd3c8 100644
--- a/sc/source/core/tool/compiler.cxx
+++ b/sc/source/core/tool/compiler.cxx
@@ -68,11 +68,14 @@
#include "cell.hxx"
#include "dociter.hxx"
#include "docoptio.hxx"
-#include "formula/errorcodes.hxx"
+#include <formula/errorcodes.hxx>
#include "parclass.hxx"
#include "autonamecache.hxx"
#include "externalrefmgr.hxx"
#include "rangeutl.hxx"
+#include "convuno.hxx"
+#include "tokenuno.hxx"
+#include "formulaparserpool.hxx"
using namespace formula;
using namespace ::com::sun::star;
@@ -408,28 +411,36 @@ void ScCompiler::InitCharClassEnglish()
void ScCompiler::SetGrammar( const FormulaGrammar::Grammar eGrammar )
{
- DBG_ASSERT( eGrammar != FormulaGrammar::GRAM_UNSPECIFIED, "ScCompiler::SetGrammar: don't passFormulaGrammar::GRAM_UNSPECIFIED");
+ DBG_ASSERT( eGrammar != FormulaGrammar::GRAM_UNSPECIFIED, "ScCompiler::SetGrammar: don't pass FormulaGrammar::GRAM_UNSPECIFIED");
if (eGrammar == GetGrammar())
return; // nothing to be done
- FormulaGrammar::Grammar eMyGrammar = eGrammar;
- const sal_Int32 nFormulaLanguage = FormulaGrammar::extractFormulaLanguage( eMyGrammar);
- OpCodeMapPtr xMap( GetOpCodeMap( nFormulaLanguage));
- DBG_ASSERT( xMap, "ScCompiler::SetGrammar: unknown formula language");
- if (!xMap)
+ if( eGrammar == FormulaGrammar::GRAM_EXTERNAL )
{
- xMap = GetOpCodeMap( ::com::sun::star::sheet::FormulaLanguage::NATIVE);
- eMyGrammar = xMap->getGrammar();
+ meGrammar = eGrammar;
+ mxSymbols = GetOpCodeMap( ::com::sun::star::sheet::FormulaLanguage::NATIVE);
}
+ else
+ {
+ FormulaGrammar::Grammar eMyGrammar = eGrammar;
+ const sal_Int32 nFormulaLanguage = FormulaGrammar::extractFormulaLanguage( eMyGrammar);
+ OpCodeMapPtr xMap = GetOpCodeMap( nFormulaLanguage);
+ DBG_ASSERT( xMap, "ScCompiler::SetGrammar: unknown formula language");
+ if (!xMap)
+ {
+ xMap = GetOpCodeMap( ::com::sun::star::sheet::FormulaLanguage::NATIVE);
+ eMyGrammar = xMap->getGrammar();
+ }
- // Save old grammar for call to SetGrammarAndRefConvention().
- FormulaGrammar::Grammar eOldGrammar = GetGrammar();
- // This also sets the grammar associated with the map!
- SetFormulaLanguage( xMap);
+ // Save old grammar for call to SetGrammarAndRefConvention().
+ FormulaGrammar::Grammar eOldGrammar = GetGrammar();
+ // This also sets the grammar associated with the map!
+ SetFormulaLanguage( xMap);
- // Override if necessary.
- if (eMyGrammar != GetGrammar())
- SetGrammarAndRefConvention( eMyGrammar, eOldGrammar);
+ // Override if necessary.
+ if (eMyGrammar != GetGrammar())
+ SetGrammarAndRefConvention( eMyGrammar, eOldGrammar);
+ }
}
@@ -1811,9 +1822,11 @@ ScCompiler::ScCompiler( ScDocument* pDocument, const ScAddress& rPos,ScTokenArra
aPos( rPos ),
pCharClass( ScGlobal::pCharClass ),
mnPredetectedReference(0),
+ mnRangeOpPosInSymbol(-1),
pConv( pConvOOO_A1 ),
mbCloseBrackets( true ),
- mbExtendedErrorDetection( false )
+ mbExtendedErrorDetection( false ),
+ mbRewind( false )
{
nMaxTab = pDoc ? pDoc->GetTableCount() - 1 : 0;
}
@@ -1824,9 +1837,11 @@ ScCompiler::ScCompiler( ScDocument* pDocument, const ScAddress& rPos)
aPos( rPos ),
pCharClass( ScGlobal::pCharClass ),
mnPredetectedReference(0),
+ mnRangeOpPosInSymbol(-1),
pConv( pConvOOO_A1 ),
mbCloseBrackets( true ),
- mbExtendedErrorDetection( false )
+ mbExtendedErrorDetection( false ),
+ mbRewind( false )
{
nMaxTab = pDoc ? pDoc->GetTableCount() - 1 : 0;
}
@@ -1962,7 +1977,7 @@ xub_StrLen ScCompiler::NextSymbol(bool bInArray)
sal_Unicode c = *pSrc;
sal_Unicode cLast = 0;
bool bQuote = false;
- bool bRangeOp = false;
+ mnRangeOpPosInSymbol = -1;
ScanState eState = ssGetChar;
xub_StrLen nSpaces = 0;
sal_Unicode cSep = mxSymbols->getSymbol( ocSep).GetChar(0);
@@ -2110,11 +2125,11 @@ Label_MaskStateMachine:
else
*pSym++ = c;
}
- else if (c == ':' && !bRangeOp)
+ else if (c == ':' && mnRangeOpPosInSymbol < 0)
{
// One range operator may form Sheet1.A:A, which we need to
// pass as one entity to IsReference().
- bRangeOp = true;
+ mnRangeOpPosInSymbol = pSym - &cSymbol[0];
if( pSym == &cSymbol[ MAXSTRLEN-1 ] )
{
SetError(errStringOverflow);
@@ -2409,7 +2424,7 @@ Label_MaskStateMachine:
{
nSrcPos = sal::static_int_cast<xub_StrLen>( nSrcPos + nSpaces );
String aSymbol;
- bRangeOp = false;
+ mnRangeOpPosInSymbol = -1;
USHORT nErr = 0;
do
{
@@ -2438,9 +2453,9 @@ Label_MaskStateMachine:
bi18n = (c == cSheetSep || c == SC_COMPILER_FILE_TAB_SEP);
}
// One range operator restarts parsing for second reference.
- if (c == ':' && !bRangeOp)
+ if (c == ':' && mnRangeOpPosInSymbol < 0)
{
- bRangeOp = true;
+ mnRangeOpPosInSymbol = aSymbol.Len();
bi18n = true;
}
if ( bi18n )
@@ -2460,6 +2475,14 @@ Label_MaskStateMachine:
nSrcPos = sal::static_int_cast<xub_StrLen>( pSrc - pStart );
*pSym = 0;
}
+ if (mnRangeOpPosInSymbol >= 0 && mnRangeOpPosInSymbol == (pSym-1) - &cSymbol[0])
+ {
+ // This is a trailing range operator, which is nonsense. Will be caught
+ // in next round.
+ mnRangeOpPosInSymbol = -1;
+ *--pSym = 0;
+ --nSrcPos;
+ }
if ( bAutoCorrect )
aCorrectedSymbol = cSymbol;
if (bAutoIntersection && nSpaces > 1)
@@ -2835,8 +2858,21 @@ BOOL ScCompiler::IsReference( const String& rName )
// Though the range operator is handled explicitly, when encountering
// something like Sheet1.A:A we will have to treat it as one entity if it
// doesn't pass as single cell reference.
- if (ScGlobal::FindUnquoted( rName, ':') != STRING_NOTFOUND)
- return IsDoubleReference( rName);
+ if (mnRangeOpPosInSymbol > 0) // ":foo" would be nonsense
+ {
+ if (IsDoubleReference( rName))
+ return true;
+ // Now try with a symbol up to the range operator, rewind source
+ // position.
+ sal_Int32 nLen = mnRangeOpPosInSymbol;
+ while (cSymbol[++nLen])
+ ;
+ cSymbol[mnRangeOpPosInSymbol] = 0;
+ nSrcPos -= static_cast<xub_StrLen>(nLen - mnRangeOpPosInSymbol);
+ mnRangeOpPosInSymbol = -1;
+ mbRewind = true;
+ return true; // end all checks
+ }
return false;
}
@@ -3551,54 +3587,65 @@ BOOL ScCompiler::NextNewToken( bool bInArray )
// #42016# Italian ARCTAN.2 resulted in #REF! => IsOpcode() before
// IsReference().
- const String aOrg( cSymbol );
-
- if (bAsciiNonAlnum && IsOpCode( aOrg, bInArray ))
- return true;
-
String aUpper;
- bool bAsciiUpper = false;
- if (bMayBeFuncName)
+
+ do
{
- bAsciiUpper = lcl_UpperAsciiOrI18n( aUpper, aOrg, meGrammar);
- if (IsOpCode( aUpper, bInArray ))
+ mbRewind = false;
+ const String aOrg( cSymbol );
+
+ if (bAsciiNonAlnum && IsOpCode( aOrg, bInArray ))
return true;
- }
- // Column 'DM' ("Deutsche Mark", German currency) couldn't be
- // referred => IsReference() before IsValue().
- // Preserve case of file names in external references.
- if (IsReference( aOrg ))
- return true;
+ aUpper.Erase();
+ bool bAsciiUpper = false;
+ if (bMayBeFuncName)
+ {
+ bAsciiUpper = lcl_UpperAsciiOrI18n( aUpper, aOrg, meGrammar);
+ if (IsOpCode( aUpper, bInArray ))
+ return true;
+ }
- if (!aUpper.Len())
- bAsciiUpper = lcl_UpperAsciiOrI18n( aUpper, aOrg, meGrammar);
+ // Column 'DM' ("Deutsche Mark", German currency) couldn't be
+ // referred => IsReference() before IsValue().
+ // Preserve case of file names in external references.
+ if (IsReference( aOrg ))
+ {
+ if (mbRewind) // Range operator, but no direct reference.
+ continue; // do; up to range operator.
+ return true;
+ }
- // IsBoolean() before IsValue() to catch inline bools without the kludge
- // for inline arrays.
- if (bAllowBooleans && IsBoolean( aUpper ))
- return true;
+ if (!aUpper.Len())
+ bAsciiUpper = lcl_UpperAsciiOrI18n( aUpper, aOrg, meGrammar);
- if (IsValue( aUpper ))
- return true;
+ // IsBoolean() before IsValue() to catch inline bools without the kludge
+ // for inline arrays.
+ if (bAllowBooleans && IsBoolean( aUpper ))
+ return true;
- // User defined names and such do need i18n upper also in ODF.
- if (bAsciiUpper)
- aUpper = ScGlobal::pCharClass->upper( aOrg );
+ if (IsValue( aUpper ))
+ return true;
- if (IsNamedRange( aUpper ))
- return true;
- // Preserve case of file names in external references.
- if (IsExternalNamedRange( aOrg ))
- return true;
- if (IsDBRange( aUpper ))
- return true;
- if (IsColRowName( aUpper ))
- return true;
- if (bMayBeFuncName && IsMacro( aUpper ))
- return true;
- if (bMayBeFuncName && IsOpCode2( aUpper ))
- return true;
+ // User defined names and such do need i18n upper also in ODF.
+ if (bAsciiUpper)
+ aUpper = ScGlobal::pCharClass->upper( aOrg );
+
+ if (IsNamedRange( aUpper ))
+ return true;
+ // Preserve case of file names in external references.
+ if (IsExternalNamedRange( aOrg ))
+ return true;
+ if (IsDBRange( aUpper ))
+ return true;
+ if (IsColRowName( aUpper ))
+ return true;
+ if (bMayBeFuncName && IsMacro( aUpper ))
+ return true;
+ if (bMayBeFuncName && IsOpCode2( aUpper ))
+ return true;
+
+ } while (mbRewind);
if ( mbExtendedErrorDetection )
{
@@ -3620,6 +3667,21 @@ BOOL ScCompiler::NextNewToken( bool bInArray )
return true;
}
+void ScCompiler::CreateStringFromXMLTokenArray( String& rFormula, String& rFormulaNmsp )
+{
+ bool bExternal = GetGrammar() == FormulaGrammar::GRAM_EXTERNAL;
+ USHORT nExpectedCount = bExternal ? 2 : 1;
+ DBG_ASSERT( pArr->GetLen() == nExpectedCount, "ScCompiler::CreateStringFromXMLTokenArray - wrong number of tokens" );
+ if( pArr->GetLen() == nExpectedCount )
+ {
+ FormulaToken** ppTokens = pArr->GetArray();
+ // string tokens expected, GetString() will assert if token type is wrong
+ rFormula = ppTokens[ 0 ]->GetString();
+ if( bExternal )
+ rFormulaNmsp = ppTokens[ 1 ]->GetString();
+ }
+}
+
ScTokenArray* ScCompiler::CompileString( const String& rFormula )
{
#if 0
@@ -3627,6 +3689,10 @@ ScTokenArray* ScCompiler::CompileString( const String& rFormula )
rtl::OUStringToOString( rFormula, RTL_TEXTENCODING_UTF8 ).getStr() );
#endif
+ OSL_ENSURE( meGrammar != FormulaGrammar::GRAM_EXTERNAL, "ScCompiler::CompileString - unexpected grammar GRAM_EXTERNAL" );
+ if( meGrammar == FormulaGrammar::GRAM_EXTERNAL )
+ SetGrammar( FormulaGrammar::GRAM_PODF );
+
ScTokenArray aArr;
pArr = &aArr;
aFormula = rFormula;
@@ -3829,6 +3895,34 @@ ScTokenArray* ScCompiler::CompileString( const String& rFormula )
}
+ScTokenArray* ScCompiler::CompileString( const String& rFormula, const String& rFormulaNmsp )
+{
+ DBG_ASSERT( (GetGrammar() == FormulaGrammar::GRAM_EXTERNAL) || (rFormulaNmsp.Len() == 0),
+ "ScCompiler::CompileString - unexpected formula namespace for internal grammar" );
+ if( GetGrammar() == FormulaGrammar::GRAM_EXTERNAL ) try
+ {
+ ScFormulaParserPool& rParserPool = pDoc->GetFormulaParserPool();
+ uno::Reference< sheet::XFormulaParser > xParser( rParserPool.getFormulaParser( rFormulaNmsp ), uno::UNO_SET_THROW );
+ table::CellAddress aReferencePos;
+ ScUnoConversion::FillApiAddress( aReferencePos, aPos );
+ uno::Sequence< sheet::FormulaToken > aTokenSeq = xParser->parseFormula( rFormula, aReferencePos );
+ ScTokenArray aTokenArray;
+ if( ScTokenConversion::ConvertToTokenArray( *pDoc, aTokenArray, aTokenSeq ) )
+ {
+ // remember pArr, in case a subsequent CompileTokenArray() is executed.
+ ScTokenArray* pNew = new ScTokenArray( aTokenArray );
+ pArr = pNew;
+ return pNew;
+ }
+ }
+ catch( uno::Exception& )
+ {
+ }
+ // no success - fallback to some internal grammar and hope the best
+ return CompileString( rFormula );
+}
+
+
BOOL ScCompiler::HandleRange()
{
ScRangeData* pRangeData = pDoc->GetRangeName()->FindIndex( pToken->GetIndex() );
@@ -3865,7 +3959,7 @@ BOOL ScCompiler::HandleRange()
if( pRangeData->HasReferences() )
{
SetRelNameReference();
- MoveRelWrap();
+ MoveRelWrap(pRangeData->GetMaxCol(), pRangeData->GetMaxRow());
}
pNew->Reset();
if ( bAddPair )
@@ -3917,7 +4011,7 @@ BOOL ScCompiler::HandleExternalReference(const FormulaToken& _aToken)
if (pNew->GetNextReference() != NULL)
{
SetRelNameReference();
- MoveRelWrap();
+ MoveRelWrap(MAXCOL, MAXROW);
}
pNew->Reset();
return GetToken();
@@ -4012,33 +4106,33 @@ void ScCompiler::SetRelNameReference()
// Wrap-adjust relative references of a RangeName to current position,
// don't call for other token arrays!
-void ScCompiler::MoveRelWrap()
+void ScCompiler::MoveRelWrap( SCCOL nMaxCol, SCROW nMaxRow )
{
pArr->Reset();
for( ScToken* t = static_cast<ScToken*>(pArr->GetNextReference()); t;
t = static_cast<ScToken*>(pArr->GetNextReference()) )
{
if ( t->GetType() == svSingleRef || t->GetType() == svExternalSingleRef )
- ScRefUpdate::MoveRelWrap( pDoc, aPos, SingleDoubleRefModifier( t->GetSingleRef() ).Ref() );
+ ScRefUpdate::MoveRelWrap( pDoc, aPos, nMaxCol, nMaxRow, SingleDoubleRefModifier( t->GetSingleRef() ).Ref() );
else
- ScRefUpdate::MoveRelWrap( pDoc, aPos, t->GetDoubleRef() );
+ ScRefUpdate::MoveRelWrap( pDoc, aPos, nMaxCol, nMaxRow, t->GetDoubleRef() );
}
}
// static
// Wrap-adjust relative references of a RangeName to current position,
// don't call for other token arrays!
-void ScCompiler::MoveRelWrap( ScTokenArray& rArr, ScDocument* pDoc,
- const ScAddress& rPos )
+void ScCompiler::MoveRelWrap( ScTokenArray& rArr, ScDocument* pDoc, const ScAddress& rPos,
+ SCCOL nMaxCol, SCROW nMaxRow )
{
rArr.Reset();
for( ScToken* t = static_cast<ScToken*>(rArr.GetNextReference()); t;
t = static_cast<ScToken*>(rArr.GetNextReference()) )
{
if ( t->GetType() == svSingleRef || t->GetType() == svExternalSingleRef )
- ScRefUpdate::MoveRelWrap( pDoc, rPos, SingleDoubleRefModifier( t->GetSingleRef() ).Ref() );
+ ScRefUpdate::MoveRelWrap( pDoc, rPos, nMaxCol, nMaxRow, SingleDoubleRefModifier( t->GetSingleRef() ).Ref() );
else
- ScRefUpdate::MoveRelWrap( pDoc, rPos, t->GetDoubleRef() );
+ ScRefUpdate::MoveRelWrap( pDoc, rPos, nMaxCol, nMaxRow, t->GetDoubleRef() );
}
}
@@ -4213,7 +4307,7 @@ ScRangeData* ScCompiler::UpdateReference(UpdateRefMode eUpdateRefMode,
SingleDoubleRefModifier aMod( rRef );
if ( rRef.IsRelName() )
{
- ScRefUpdate::MoveRelWrap( pDoc, aPos, aMod.Ref() );
+ ScRefUpdate::MoveRelWrap( pDoc, aPos, MAXCOL, MAXROW, aMod.Ref() );
rChanged = TRUE;
}
else
@@ -4243,7 +4337,7 @@ ScRangeData* ScCompiler::UpdateReference(UpdateRefMode eUpdateRefMode,
SCTAB nTabs = rRef.Ref2.nTab - rRef.Ref1.nTab;
if ( rRef.Ref1.IsRelName() || rRef.Ref2.IsRelName() )
{
- ScRefUpdate::MoveRelWrap( pDoc, aPos, rRef );
+ ScRefUpdate::MoveRelWrap( pDoc, aPos, MAXCOL, MAXROW, rRef );
rChanged = TRUE;
}
else
diff --git a/sc/source/core/tool/formulaparserpool.cxx b/sc/source/core/tool/formulaparserpool.cxx
new file mode 100644
index 000000000000..94259a56d6e2
--- /dev/null
+++ b/sc/source/core/tool/formulaparserpool.cxx
@@ -0,0 +1,171 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: formulaparserpool.cxx,v $
+ * $Revision: 1.1 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sc.hxx"
+
+#include "formulaparserpool.hxx"
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XContentEnumerationAccess.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/lang/XSingleComponentFactory.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/sheet/XFilterFormulaParser.hpp>
+#include <rtl/instance.hxx>
+#include <comphelper/processfactory.hxx>
+#include <sfx2/objsh.hxx>
+#include "document.hxx"
+
+using ::rtl::OUString;
+using ::rtl::OUStringHash;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::sheet;
+using namespace ::com::sun::star::uno;
+
+// ============================================================================
+
+namespace {
+
+class ScParserFactoryMap
+{
+public:
+ explicit ScParserFactoryMap();
+
+ Reference< XFormulaParser > createFormulaParser(
+ const Reference< XComponent >& rxComponent,
+ const OUString& rNamespace );
+
+private:
+ typedef ::std::hash_map<
+ OUString,
+ Reference< XSingleComponentFactory >,
+ OUStringHash,
+ ::std::equal_to< OUString > > FactoryMap;
+
+ Reference< XComponentContext > mxContext; /// Default context of global process factory.
+ FactoryMap maFactories; /// All parser factories, mapped by formula namespace.
+};
+
+ScParserFactoryMap::ScParserFactoryMap()
+{
+ try
+ {
+ // get process factory and default component context
+ Reference< XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory(), UNO_SET_THROW );
+ Reference< XPropertySet > xPropSet( xFactory, UNO_QUERY_THROW );
+ mxContext.set( xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ) ), UNO_QUERY_THROW );
+
+ // enumerate all implementations of the FormulaParser service
+ Reference< XContentEnumerationAccess > xFactoryEA( xFactory, UNO_QUERY_THROW );
+ Reference< XEnumeration > xEnum( xFactoryEA->createContentEnumeration( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sheet.FilterFormulaParser" ) ) ), UNO_SET_THROW );
+ while( xEnum->hasMoreElements() ) try // single try/catch for every element
+ {
+ // create an instance of the formula parser implementation
+ Reference< XSingleComponentFactory > xCompFactory( xEnum->nextElement(), UNO_QUERY_THROW );
+ Reference< XFilterFormulaParser > xParser( xCompFactory->createInstanceWithContext( mxContext ), UNO_QUERY_THROW );
+
+ // store factory in the map
+ OUString aNamespace = xParser->getSupportedNamespace();
+ if( aNamespace.getLength() > 0 )
+ maFactories[ aNamespace ] = xCompFactory;
+ }
+ catch( Exception& )
+ {
+ }
+ }
+ catch( Exception& )
+ {
+ }
+}
+
+Reference< XFormulaParser > ScParserFactoryMap::createFormulaParser(
+ const Reference< XComponent >& rxComponent, const OUString& rNamespace )
+{
+ Reference< XFormulaParser > xParser;
+ FactoryMap::const_iterator aIt = maFactories.find( rNamespace );
+ if( aIt != maFactories.end() ) try
+ {
+ Sequence< Any > aArgs( 1 );
+ aArgs[ 0 ] <<= rxComponent;
+ xParser.set( aIt->second->createInstanceWithArgumentsAndContext( aArgs, mxContext ), UNO_QUERY_THROW );
+ }
+ catch( Exception& )
+ {
+ }
+ return xParser;
+}
+
+struct ScParserFactorySingleton : public ::rtl::Static< ScParserFactoryMap, ScParserFactorySingleton > {};
+
+} // namespace
+
+// ============================================================================
+
+ScFormulaParserPool::ScFormulaParserPool( const ScDocument& rDoc ) :
+ mrDoc( rDoc )
+{
+}
+
+ScFormulaParserPool::~ScFormulaParserPool()
+{
+}
+
+bool ScFormulaParserPool::hasFormulaParser( const OUString& rNamespace )
+{
+ return getFormulaParser( rNamespace ).is();
+}
+
+Reference< XFormulaParser > ScFormulaParserPool::getFormulaParser( const OUString& rNamespace )
+{
+ // try to find an existing parser entry
+ ParserMap::iterator aIt = maParsers.find( rNamespace );
+ if( aIt != maParsers.end() )
+ return aIt->second;
+
+ // always create a new entry in the map (even if the following initialization fails)
+ Reference< XFormulaParser >& rxParser = maParsers[ rNamespace ];
+
+ // try to create a new parser object
+ if( SfxObjectShell* pDocShell = mrDoc.GetDocumentShell() ) try
+ {
+ Reference< XComponent > xComponent( pDocShell->GetModel(), UNO_QUERY_THROW );
+ ScParserFactoryMap& rFactoryMap = ScParserFactorySingleton::get();
+ rxParser = rFactoryMap.createFormulaParser( xComponent, rNamespace );
+ }
+ catch( Exception& )
+ {
+ }
+ return rxParser;
+}
+
+// ============================================================================
+
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index ec4c4c293839..195366271f0d 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -71,6 +71,7 @@
#include "lookupcache.hxx"
#include "rangenam.hxx"
#include "compiler.hxx"
+#include "externalrefmgr.hxx"
#define SC_DOUBLE_MAXVALUE 1.7e307
@@ -626,7 +627,20 @@ bool ScInterpreter::JumpMatrix( short nStackLevel )
}
-double ScInterpreter::CompareFunc( const ScCompare& rComp )
+ScCompareOptions::ScCompareOptions( ScDocument* pDoc, const ScQueryEntry& rEntry, bool bReg ) :
+ aQueryEntry(rEntry),
+ bRegEx(bReg),
+ bMatchWholeCell(pDoc->GetDocOptions().IsMatchWholeCell()),
+ bIgnoreCase(true)
+{
+ bRegEx = (bRegEx && (aQueryEntry.eOp == SC_EQUAL || aQueryEntry.eOp == SC_NOT_EQUAL));
+ // Interpreter functions usually are case insensitive, except the simple
+ // comparison operators, for which these options aren't used. Override in
+ // struct if needed.
+}
+
+
+double ScInterpreter::CompareFunc( const ScCompare& rComp, ScCompareOptions* pOptions )
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::CompareFunc" );
// Keep DoubleError if encountered
@@ -698,7 +712,53 @@ double ScInterpreter::CompareFunc( const ScCompare& rComp )
fRes = 1; // number is less than string
else
{
- if (pDok->GetDocOptions().IsIgnoreCase())
+ // Both strings.
+ if (pOptions)
+ {
+ // All similar to Sctable::ValidQuery(), *rComp.pVal[1] actually
+ // is/must be identical to *rEntry.pStr, which is essential for
+ // regex to work through GetSearchTextPtr().
+ ScQueryEntry& rEntry = pOptions->aQueryEntry;
+ DBG_ASSERT( *rComp.pVal[1] == *rEntry.pStr, "ScInterpreter::CompareFunc: broken options");
+ if (pOptions->bRegEx)
+ {
+ xub_StrLen nStart = 0;
+ xub_StrLen nStop = rComp.pVal[0]->Len();
+ bool bMatch = rEntry.GetSearchTextPtr(
+ !pOptions->bIgnoreCase)->SearchFrwrd( *rComp.pVal[0],
+ &nStart, &nStop);
+ if (bMatch && pOptions->bMatchWholeCell && (nStart != 0 || nStop != rComp.pVal[0]->Len()))
+ bMatch = false; // RegEx must match entire string.
+ fRes = (bMatch ? 0 : 1);
+ }
+ else if (rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL)
+ {
+ ::utl::TransliterationWrapper* pTransliteration =
+ (pOptions->bIgnoreCase ? ScGlobal::pTransliteration :
+ ScGlobal::pCaseTransliteration);
+ bool bMatch;
+ if (pOptions->bMatchWholeCell)
+ bMatch = pTransliteration->isEqual( *rComp.pVal[0], *rComp.pVal[1]);
+ else
+ {
+ String aCell( pTransliteration->transliterate(
+ *rComp.pVal[0], ScGlobal::eLnge, 0,
+ rComp.pVal[0]->Len(), NULL));
+ String aQuer( pTransliteration->transliterate(
+ *rComp.pVal[1], ScGlobal::eLnge, 0,
+ rComp.pVal[1]->Len(), NULL));
+ bMatch = (aCell.Search( aQuer ) != STRING_NOTFOUND);
+ }
+ fRes = (bMatch ? 0 : 1);
+ }
+ else if (pOptions->bIgnoreCase)
+ fRes = (double) ScGlobal::pCollator->compareString(
+ *rComp.pVal[ 0 ], *rComp.pVal[ 1 ] );
+ else
+ fRes = (double) ScGlobal::pCaseCollator->compareString(
+ *rComp.pVal[ 0 ], *rComp.pVal[ 1 ] );
+ }
+ else if (pDok->GetDocOptions().IsIgnoreCase())
fRes = (double) ScGlobal::pCollator->compareString(
*rComp.pVal[ 0 ], *rComp.pVal[ 1 ] );
else
@@ -763,7 +823,7 @@ double ScInterpreter::Compare()
}
-ScMatrixRef ScInterpreter::CompareMat()
+ScMatrixRef ScInterpreter::CompareMat( ScCompareOptions* pOptions )
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::CompareMat" );
String aVal1, aVal2;
@@ -855,7 +915,7 @@ ScMatrixRef ScInterpreter::CompareMat()
aComp.bEmpty[i] = FALSE;
}
}
- pResMat->PutDouble( CompareFunc( aComp ), j,k );
+ pResMat->PutDouble( CompareFunc( aComp, pOptions ), j,k );
}
else
pResMat->PutString( ScGlobal::GetRscString(STR_NO_VALUE), j,k );
@@ -885,7 +945,7 @@ ScMatrixRef ScInterpreter::CompareMat()
*aComp.pVal[i] = pMat[i]->GetString(j);
aComp.bEmpty[i] = pMat[i]->IsEmpty(j);
}
- pResMat->PutDouble( CompareFunc( aComp ), j );
+ pResMat->PutDouble( CompareFunc( aComp, pOptions ), j );
}
}
}
@@ -894,6 +954,52 @@ ScMatrixRef ScInterpreter::CompareMat()
}
+ScMatrixRef ScInterpreter::QueryMat( ScMatrix* pMat, ScCompareOptions& rOptions )
+{
+ short nSaveCurFmtType = nCurFmtType;
+ short nSaveFuncFmtType = nFuncFmtType;
+ PushMatrix( pMat);
+ if (rOptions.aQueryEntry.bQueryByString)
+ PushString( *rOptions.aQueryEntry.pStr);
+ else
+ PushDouble( rOptions.aQueryEntry.nVal);
+ ScMatrixRef pResultMatrix = CompareMat( &rOptions);
+ nCurFmtType = nSaveCurFmtType;
+ nFuncFmtType = nSaveFuncFmtType;
+ if (nGlobalError || !pResultMatrix)
+ {
+ SetError( errIllegalParameter);
+ return pResultMatrix;
+ }
+
+ switch (rOptions.aQueryEntry.eOp)
+ {
+ case SC_EQUAL:
+ pResultMatrix->CompareEqual();
+ break;
+ case SC_LESS:
+ pResultMatrix->CompareLess();
+ break;
+ case SC_GREATER:
+ pResultMatrix->CompareGreater();
+ break;
+ case SC_LESS_EQUAL:
+ pResultMatrix->CompareLessEqual();
+ break;
+ case SC_GREATER_EQUAL:
+ pResultMatrix->CompareGreaterEqual();
+ break;
+ case SC_NOT_EQUAL:
+ pResultMatrix->CompareNotEqual();
+ break;
+ default:
+ SetError( errIllegalArgument);
+ DBG_ERROR1( "ScInterpreter::QueryMat: unhandled comparison operator: %d", (int)rOptions.aQueryEntry.eOp);
+ }
+ return pResultMatrix;
+}
+
+
void ScInterpreter::ScEqual()
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::ScEqual" );
@@ -4310,6 +4416,7 @@ void ScInterpreter::ScCountIf()
SCCOL nCol2;
SCROW nRow2;
SCTAB nTab2;
+ ScMatrixRef pQueryMatrix;
switch ( GetStackType() )
{
case svDoubleRef :
@@ -4326,6 +4433,24 @@ void ScInterpreter::ScCountIf()
nRow2 = nRow1;
nTab2 = nTab1;
break;
+ case svMatrix:
+ {
+ pQueryMatrix = PopMatrix();
+ if (!pQueryMatrix)
+ {
+ PushIllegalParameter();
+ return;
+ }
+ nCol1 = 0;
+ nRow1 = 0;
+ nTab1 = 0;
+ SCSIZE nC, nR;
+ pQueryMatrix->GetDimensions( nC, nR);
+ nCol2 = static_cast<SCCOL>(nC - 1);
+ nRow2 = static_cast<SCROW>(nR - 1);
+ nTab2 = 0;
+ }
+ break;
default:
PushIllegalParameter();
return ;
@@ -4367,15 +4492,37 @@ void ScInterpreter::ScCountIf()
rParam.nCol1 = nCol1;
rParam.nCol2 = nCol2;
rEntry.nField = nCol1;
- ScQueryCellIterator aCellIter(pDok, nTab1, rParam, FALSE);
- // Entry.nField im Iterator bei Spaltenwechsel weiterschalten
- aCellIter.SetAdvanceQueryParamEntryField( TRUE );
- if ( aCellIter.GetFirst() )
+ if (pQueryMatrix)
{
- do
+ // Never case-sensitive.
+ ScCompareOptions aOptions( pDok, rEntry, rParam.bRegExp);
+ ScMatrixRef pResultMatrix = QueryMat( pQueryMatrix, aOptions);
+ if (nGlobalError || !pResultMatrix)
{
- fSum++;
- } while ( aCellIter.GetNext() );
+ PushIllegalParameter();
+ return;
+ }
+
+ SCSIZE nSize = pResultMatrix->GetElementCount();
+ for (SCSIZE nIndex = 0; nIndex < nSize; ++nIndex)
+ {
+ if (pResultMatrix->IsValue( nIndex) &&
+ pResultMatrix->GetDouble( nIndex))
+ ++fSum;
+ }
+ }
+ else
+ {
+ ScQueryCellIterator aCellIter(pDok, nTab1, rParam, FALSE);
+ // Entry.nField im Iterator bei Spaltenwechsel weiterschalten
+ aCellIter.SetAdvanceQueryParamEntryField( TRUE );
+ if ( aCellIter.GetFirst() )
+ {
+ do
+ {
+ fSum++;
+ } while ( aCellIter.GetNext() );
+ }
}
}
else
@@ -4399,6 +4546,7 @@ void ScInterpreter::ScSumIf()
SCROW nRow3 = 0;
SCTAB nTab3 = 0;
+ ScMatrixRef pSumExtraMatrix;
bool bSumExtraRange = (nParamCount == 3);
if (bSumExtraRange)
{
@@ -4423,6 +4571,10 @@ void ScInterpreter::ScSumIf()
case svSingleRef :
PopSingleRef( nCol3, nRow3, nTab3 );
break;
+ case svMatrix:
+ pSumExtraMatrix = PopMatrix();
+ //! nCol3, nRow3, nTab3 remain 0
+ break;
default:
PushIllegalParameter();
return ;
@@ -4498,6 +4650,7 @@ void ScInterpreter::ScSumIf()
SCCOL nCol2;
SCROW nRow2;
SCTAB nTab2;
+ ScMatrixRef pQueryMatrix;
switch ( GetStackType() )
{
case svRefList :
@@ -4522,13 +4675,31 @@ void ScInterpreter::ScSumIf()
nRow2 = nRow1;
nTab2 = nTab1;
break;
+ case svMatrix:
+ {
+ pQueryMatrix = PopMatrix();
+ if (!pQueryMatrix)
+ {
+ PushIllegalParameter();
+ return;
+ }
+ nCol1 = 0;
+ nRow1 = 0;
+ nTab1 = 0;
+ SCSIZE nC, nR;
+ pQueryMatrix->GetDimensions( nC, nR);
+ nCol2 = static_cast<SCCOL>(nC - 1);
+ nRow2 = static_cast<SCROW>(nR - 1);
+ nTab2 = 0;
+ }
+ break;
default:
PushIllegalParameter();
return ;
}
if ( nTab1 != nTab2 )
{
- PushIllegalParameter();
+ PushIllegalArgument();
return;
}
@@ -4544,15 +4715,29 @@ void ScInterpreter::ScSumIf()
// instead of the result range.
SCCOL nColDelta = nCol2 - nCol1;
SCROW nRowDelta = nRow2 - nRow1;
- if (nCol3 + nColDelta > MAXCOL)
+ SCCOL nMaxCol;
+ SCROW nMaxRow;
+ if (pSumExtraMatrix)
{
- SCCOL nNewDelta = MAXCOL - nCol3;
+ SCSIZE nC, nR;
+ pSumExtraMatrix->GetDimensions( nC, nR);
+ nMaxCol = static_cast<SCCOL>(nC - 1);
+ nMaxRow = static_cast<SCROW>(nR - 1);
+ }
+ else
+ {
+ nMaxCol = MAXCOL;
+ nMaxRow = MAXROW;
+ }
+ if (nCol3 + nColDelta > nMaxCol)
+ {
+ SCCOL nNewDelta = nMaxCol - nCol3;
nCol2 = nCol1 + nNewDelta;
}
- if (nRow3 + nRowDelta > MAXROW)
+ if (nRow3 + nRowDelta > nMaxRow)
{
- SCROW nNewDelta = MAXROW - nRow3;
+ SCROW nNewDelta = nMaxRow - nRow3;
nRow2 = nRow1 + nNewDelta;
}
}
@@ -4592,30 +4777,119 @@ void ScInterpreter::ScSumIf()
rParam.nCol1 = nCol1;
rParam.nCol2 = nCol2;
rEntry.nField = nCol1;
- SCCOL nColDiff = nCol3 - nCol1;
- SCROW nRowDiff = nRow3 - nRow1;
- ScQueryCellIterator aCellIter(pDok, nTab1, rParam, FALSE);
- // Increment Entry.nField in iterator when switching to next column.
- aCellIter.SetAdvanceQueryParamEntryField( TRUE );
- if ( aCellIter.GetFirst() )
+ SCsCOL nColDiff = nCol3 - nCol1;
+ SCsROW nRowDiff = nRow3 - nRow1;
+ if (pQueryMatrix)
{
- do
+ // Never case-sensitive.
+ ScCompareOptions aOptions( pDok, rEntry, rParam.bRegExp);
+ ScMatrixRef pResultMatrix = QueryMat( pQueryMatrix, aOptions);
+ if (nGlobalError || !pResultMatrix)
{
- aAdr.SetCol( aCellIter.GetCol() + nColDiff);
- aAdr.SetRow( aCellIter.GetRow() + nRowDiff);
- ScBaseCell* pCell = GetCell( aAdr );
- if ( HasCellValueData(pCell) )
+ PushIllegalParameter();
+ return;
+ }
+
+ if (pSumExtraMatrix)
+ {
+ for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
{
- fVal = GetCellValue( aAdr, pCell );
- if ( bNull && fVal != 0.0 )
+ for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
{
- bNull = FALSE;
- fMem = fVal;
+ if (pResultMatrix->IsValue( nCol, nRow) &&
+ pResultMatrix->GetDouble( nCol, nRow))
+ {
+ SCSIZE nC = nCol + nColDiff;
+ SCSIZE nR = nRow + nRowDiff;
+ if (pSumExtraMatrix->IsValue( nC, nR))
+ {
+ fVal = pSumExtraMatrix->GetDouble( nC, nR);
+ if ( bNull && fVal != 0.0 )
+ {
+ bNull = FALSE;
+ fMem = fVal;
+ }
+ else
+ fSum += fVal;
+ }
+ }
}
- else
- fSum += fVal;
}
- } while ( aCellIter.GetNext() );
+ }
+ else
+ {
+ for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+ {
+ for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
+ {
+ if (pResultMatrix->GetDouble( nCol, nRow))
+ {
+ aAdr.SetCol( nCol + nColDiff);
+ aAdr.SetRow( nRow + nRowDiff);
+ ScBaseCell* pCell = GetCell( aAdr );
+ if ( HasCellValueData(pCell) )
+ {
+ fVal = GetCellValue( aAdr, pCell );
+ if ( bNull && fVal != 0.0 )
+ {
+ bNull = FALSE;
+ fMem = fVal;
+ }
+ else
+ fSum += fVal;
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ ScQueryCellIterator aCellIter(pDok, nTab1, rParam, FALSE);
+ // Increment Entry.nField in iterator when switching to next column.
+ aCellIter.SetAdvanceQueryParamEntryField( TRUE );
+ if ( aCellIter.GetFirst() )
+ {
+ if (pSumExtraMatrix)
+ {
+ do
+ {
+ SCSIZE nC = aCellIter.GetCol() + nColDiff;
+ SCSIZE nR = aCellIter.GetRow() + nRowDiff;
+ if (pSumExtraMatrix->IsValue( nC, nR))
+ {
+ fVal = pSumExtraMatrix->GetDouble( nC, nR);
+ if ( bNull && fVal != 0.0 )
+ {
+ bNull = FALSE;
+ fMem = fVal;
+ }
+ else
+ fSum += fVal;
+ }
+ } while ( aCellIter.GetNext() );
+ }
+ else
+ {
+ do
+ {
+ aAdr.SetCol( aCellIter.GetCol() + nColDiff);
+ aAdr.SetRow( aCellIter.GetRow() + nRowDiff);
+ ScBaseCell* pCell = GetCell( aAdr );
+ if ( HasCellValueData(pCell) )
+ {
+ fVal = GetCellValue( aAdr, pCell );
+ if ( bNull && fVal != 0.0 )
+ {
+ bNull = FALSE;
+ fMem = fVal;
+ }
+ else
+ fSum += fVal;
+ }
+ } while ( aCellIter.GetNext() );
+ }
+ }
}
}
else
@@ -5762,6 +6036,52 @@ void ScInterpreter::ScDBVarP()
}
+ScTokenArray* lcl_CreateExternalRefTokenArray( const ScAddress& rPos, ScDocument* pDoc,
+ const ScAddress::ExternalInfo& rExtInfo, const ScRefAddress& rRefAd1,
+ const ScRefAddress* pRefAd2 )
+{
+ ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
+ size_t nSheets = 1;
+ const String* pRealTab = pRefMgr->getRealTableName( rExtInfo.mnFileId, rExtInfo.maTabName);
+ ScTokenArray* pTokenArray = new ScTokenArray;
+ if (pRefAd2)
+ {
+ ScComplexRefData aRef;
+ aRef.InitRangeRel( ScRange( rRefAd1.GetAddress(), pRefAd2->GetAddress()), rPos);
+ aRef.Ref1.SetColRel( rRefAd1.IsRelCol());
+ aRef.Ref1.SetRowRel( rRefAd1.IsRelRow());
+ aRef.Ref1.SetTabRel( rRefAd1.IsRelTab());
+ aRef.Ref1.SetFlag3D( true);
+ aRef.Ref2.SetColRel( pRefAd2->IsRelCol());
+ aRef.Ref2.SetRowRel( pRefAd2->IsRelRow());
+ aRef.Ref2.SetTabRel( pRefAd2->IsRelTab());
+ nSheets = aRef.Ref2.nTab - aRef.Ref1.nTab + 1;
+ aRef.Ref2.SetFlag3D( nSheets > 1 );
+ pTokenArray->AddExternalDoubleReference( rExtInfo.mnFileId,
+ (pRealTab ? *pRealTab : rExtInfo.maTabName), aRef);
+ }
+ else
+ {
+ ScSingleRefData aRef;
+ aRef.InitAddressRel( rRefAd1.GetAddress(), rPos);
+ aRef.SetColRel( rRefAd1.IsRelCol());
+ aRef.SetRowRel( rRefAd1.IsRelRow());
+ aRef.SetTabRel( rRefAd1.IsRelTab());
+ aRef.SetFlag3D( true);
+ pTokenArray->AddExternalSingleReference( rExtInfo.mnFileId,
+ (pRealTab ? *pRealTab : rExtInfo.maTabName), aRef);
+ }
+ // The indirect usage of the external table can't be detected during the
+ // store-to-file cycle, mark it as permanently referenced so it gets stored
+ // even if not directly referenced anywhere.
+ pRefMgr->setCacheTableReferencedPermanently( rExtInfo.mnFileId,
+ rExtInfo.maTabName, nSheets);
+ ScCompiler aComp( pDoc, rPos, *pTokenArray);
+ aComp.CompileTokenArray();
+ return pTokenArray;
+}
+
+
void ScInterpreter::ScIndirect()
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::ScIndirect" );
@@ -5780,15 +6100,46 @@ void ScInterpreter::ScIndirect()
SCTAB nTab = aPos.Tab();
String sRefStr( GetString() );
ScRefAddress aRefAd, aRefAd2;
- if ( ConvertDoubleRef( pDok, sRefStr, nTab, aRefAd, aRefAd2, aDetails) ||
+ ScAddress::ExternalInfo aExtInfo;
+ if ( ConvertDoubleRef( pDok, sRefStr, nTab, aRefAd, aRefAd2, aDetails, &aExtInfo) ||
(bTryXlA1 && ConvertDoubleRef( pDok, sRefStr, nTab, aRefAd,
- aRefAd2, aDetailsXlA1)))
- PushDoubleRef( aRefAd.Col(), aRefAd.Row(), aRefAd.Tab(),
- aRefAd2.Col(), aRefAd2.Row(), aRefAd2.Tab() );
- else if ( ConvertSingleRef ( pDok, sRefStr, nTab, aRefAd, aDetails) ||
+ aRefAd2, aDetailsXlA1, &aExtInfo)))
+ {
+ if (aExtInfo.mbExternal)
+ {
+ /* TODO: future versions should implement a proper subroutine
+ * token. This procedure here is a minimally invasive fix for
+ * #i101645# in OOo3.1.1 */
+ // Push a subroutine on the instruction code stack that
+ // resolves the external reference as the next instruction.
+ aCode.Push( lcl_CreateExternalRefTokenArray( aPos, pDok,
+ aExtInfo, aRefAd, &aRefAd2));
+ // Signal subroutine call to interpreter.
+ PushTempToken( new FormulaUnknownToken( ocCall));
+ }
+ else
+ PushDoubleRef( aRefAd.Col(), aRefAd.Row(), aRefAd.Tab(),
+ aRefAd2.Col(), aRefAd2.Row(), aRefAd2.Tab() );
+ }
+ else if ( ConvertSingleRef ( pDok, sRefStr, nTab, aRefAd, aDetails, &aExtInfo) ||
(bTryXlA1 && ConvertSingleRef ( pDok, sRefStr, nTab, aRefAd,
- aDetailsXlA1)))
- PushSingleRef( aRefAd.Col(), aRefAd.Row(), aRefAd.Tab() );
+ aDetailsXlA1, &aExtInfo)))
+ {
+ if (aExtInfo.mbExternal)
+ {
+ /* TODO: future versions should implement a proper subroutine
+ * token. This procedure here is a minimally invasive fix for
+ * #i101645# in OOo3.1.1 */
+ // Push a subroutine on the instruction code stack that
+ // resolves the external reference as the next instruction.
+ aCode.Push( lcl_CreateExternalRefTokenArray( aPos, pDok,
+ aExtInfo, aRefAd, NULL));
+ // Signal subroutine call to interpreter.
+ PushTempToken( new FormulaUnknownToken( ocCall));
+ }
+ else
+ PushSingleRef( aRefAd.Col(), aRefAd.Row(), aRefAd.Tab() );
+ }
else
{
do
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index 2722925fc56d..a73fe62998a6 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -3812,6 +3812,15 @@ StackVar ScInterpreter::Interpret()
default : PushError( errUnknownOpCode); break;
}
+ // If the function signalled that it pushed a subroutine on the
+ // instruction code stack instead of a result, continue with
+ // execution of the subroutine.
+ if (sp > nStackBase && pStack[sp-1]->GetOpCode() == ocCall)
+ {
+ Pop();
+ continue; // while( ( pCur = aCode.Next() ) != NULL ...
+ }
+
// Remember result matrix in case it could be reused.
if (pTokenMatrixMap && sp && GetStackType() == svMatrix)
pTokenMatrixMap->insert( ScTokenMatrixMap::value_type( pCur,
diff --git a/sc/source/core/tool/makefile.mk b/sc/source/core/tool/makefile.mk
index 8a4b1b44fd12..ac0aa23fc044 100644
--- a/sc/source/core/tool/makefile.mk
+++ b/sc/source/core/tool/makefile.mk
@@ -1,7 +1,7 @@
#*************************************************************************
#
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
+#
# Copyright 2008 by Sun Microsystems, Inc.
#
# OpenOffice.org - a multi-platform office productivity suite
@@ -78,6 +78,7 @@ SLOFILES = \
$(SLO)$/docoptio.obj \
$(SLO)$/editutil.obj \
$(SLO)$/filtopt.obj \
+ $(SLO)$/formulaparserpool.obj \
$(SLO)$/hints.obj \
$(SLO)$/indexmap.obj \
$(SLO)$/inputopt.obj \
@@ -122,6 +123,7 @@ EXCEPTIONSFILES= \
$(SLO)$/chartlock.obj \
$(SLO)$/chgtrack.obj \
$(SLO)$/compiler.obj \
+ $(SLO)$/formulaparserpool.obj \
$(SLO)$/interpr1.obj \
$(SLO)$/interpr2.obj \
$(SLO)$/interpr3.obj \
diff --git a/sc/source/core/tool/progress.cxx b/sc/source/core/tool/progress.cxx
index fc7a7088d2a9..450736997c2d 100644
--- a/sc/source/core/tool/progress.cxx
+++ b/sc/source/core/tool/progress.cxx
@@ -162,7 +162,7 @@ void ScProgress::CreateInterpretProgress( ScDocument* pDoc, BOOL bWait )
if ( !pGlobalProgress )
pInterpretProgress = new ScProgress( pDoc->GetDocumentShell(),
ScGlobal::GetRscString( STR_PROGRESS_CALCULATING ),
- pDoc->GetFormulaCodeInTree(), FALSE, bWait );
+ pDoc->GetFormulaCodeInTree()/MIN_NO_CODES_PER_PROGRESS_UPDATE, FALSE, bWait );
pInterpretDoc = pDoc;
}
}
diff --git a/sc/source/core/tool/rangenam.cxx b/sc/source/core/tool/rangenam.cxx
index 704c3255486e..4a4683935e99 100644
--- a/sc/source/core/tool/rangenam.cxx
+++ b/sc/source/core/tool/rangenam.cxx
@@ -60,7 +60,7 @@ using namespace formula;
// Interner ctor fuer das Suchen nach einem Index
ScRangeData::ScRangeData( USHORT n )
- : pCode( NULL ), nIndex( n ), bModified( FALSE )
+ : pCode( NULL ), nIndex( n ), bModified( FALSE ), mnMaxRow(-1), mnMaxCol(-1)
{}
ScRangeData::ScRangeData( ScDocument* pDok,
@@ -76,7 +76,9 @@ ScRangeData::ScRangeData( ScDocument* pDok,
eType ( nType ),
pDoc ( pDok ),
nIndex ( 0 ),
- bModified ( FALSE )
+ bModified ( FALSE ),
+ mnMaxRow (-1),
+ mnMaxCol (-1)
{
if (rSymbol.Len() > 0)
{
@@ -122,7 +124,9 @@ ScRangeData::ScRangeData( ScDocument* pDok,
eType ( nType ),
pDoc ( pDok ),
nIndex ( 0 ),
- bModified ( FALSE )
+ bModified ( FALSE ),
+ mnMaxRow (-1),
+ mnMaxCol (-1)
{
if( !pCode->GetCodeError() )
{
@@ -157,7 +161,9 @@ ScRangeData::ScRangeData( ScDocument* pDok,
eType ( RT_NAME ),
pDoc ( pDok ),
nIndex ( 0 ),
- bModified ( FALSE )
+ bModified ( FALSE ),
+ mnMaxRow (-1),
+ mnMaxCol (-1)
{
ScSingleRefData aRefData;
aRefData.InitAddress( rTarget );
@@ -179,7 +185,9 @@ ScRangeData::ScRangeData(const ScRangeData& rScRangeData) :
eType (rScRangeData.eType),
pDoc (rScRangeData.pDoc),
nIndex (rScRangeData.nIndex),
- bModified (rScRangeData.bModified)
+ bModified (rScRangeData.bModified),
+ mnMaxRow (rScRangeData.mnMaxRow),
+ mnMaxCol (rScRangeData.mnMaxCol)
{}
ScRangeData::~ScRangeData()
@@ -247,7 +255,7 @@ void ScRangeData::UpdateSymbol( rtl::OUStringBuffer& rBuffer, const ScAddress& r
::std::auto_ptr<ScTokenArray> pTemp( pCode->Clone() );
ScCompiler aComp( pDoc, rPos, *pTemp.get());
aComp.SetGrammar(eGrammar);
- aComp.MoveRelWrap();
+ aComp.MoveRelWrap(GetMaxCol(), GetMaxRow());
aComp.CreateStringFromTokenArray( rBuffer );
}
@@ -393,7 +401,7 @@ BOOL ScRangeData::IsReference( ScRange& rRange, const ScAddress& rPos ) const
::std::auto_ptr<ScTokenArray> pTemp( pCode->Clone() );
ScCompiler aComp( pDoc, rPos, *pTemp);
aComp.SetGrammar(pDoc->GetGrammar());
- aComp.MoveRelWrap();
+ aComp.MoveRelWrap(MAXCOL, MAXROW);
return pTemp->IsReference( rRange );
}
@@ -520,6 +528,26 @@ BOOL ScRangeData::IsNameValid( const String& rName, ScDocument* pDoc )
return TRUE;
}
+void ScRangeData::SetMaxRow(SCROW nRow)
+{
+ mnMaxRow = nRow;
+}
+
+SCROW ScRangeData::GetMaxRow() const
+{
+ return mnMaxRow >= 0 ? mnMaxRow : MAXROW;
+}
+
+void ScRangeData::SetMaxCol(SCCOL nCol)
+{
+ mnMaxCol = nCol;
+}
+
+SCCOL ScRangeData::GetMaxCol() const
+{
+ return mnMaxCol >= 0 ? mnMaxCol : MAXCOL;
+}
+
USHORT ScRangeData::GetErrCode()
{
diff --git a/sc/source/core/tool/reftokenhelper.cxx b/sc/source/core/tool/reftokenhelper.cxx
index 1e80700b40ec..e129abdcf97f 100644
--- a/sc/source/core/tool/reftokenhelper.cxx
+++ b/sc/source/core/tool/reftokenhelper.cxx
@@ -54,8 +54,9 @@ void ScRefTokenHelper::compileRangeRepresentation(
const sal_Unicode cSep = ';';
const sal_Unicode cQuote = '\'';
+ bool bFailure = false;
sal_Int32 nOffset = 0;
- while (nOffset >= 0)
+ while (nOffset >= 0 && !bFailure)
{
OUString aToken;
ScRangeStringConverter::GetTokenByOffset(aToken, rRangeStr, nOffset, cSep, cQuote);
@@ -66,14 +67,49 @@ void ScRefTokenHelper::compileRangeRepresentation(
aCompiler.SetGrammar(eGrammar);
auto_ptr<ScTokenArray> pArray(aCompiler.CompileString(aToken));
- // There should only be one reference per range token.
- pArray->Reset();
- FormulaToken* p = pArray->GetNextReference();
- if (!p)
- continue;
+ // There MUST be exactly one reference per range token and nothing
+ // else, and it MUST be a valid reference, not some #REF!
+ USHORT nLen = pArray->GetLen();
+ if (!nLen)
+ continue; // Should a missing range really be allowed?
+ if (nLen != 1)
+ bFailure = true;
+ else
+ {
+ pArray->Reset();
+ const FormulaToken* p = pArray->GetNextReference();
+ if (!p)
+ bFailure = true;
+ else
+ {
+ const ScToken* pT = static_cast<const ScToken*>(p);
+ switch (pT->GetType())
+ {
+ case svSingleRef:
+ if (!pT->GetSingleRef().Valid())
+ bFailure = true;
+ break;
+ case svDoubleRef:
+ if (!pT->GetDoubleRef().Valid())
+ bFailure = true;
+ break;
+ case svExternalSingleRef:
+ if (!pT->GetSingleRef().ValidExternal())
+ bFailure = true;
+ break;
+ case svExternalDoubleRef:
+ if (!pT->GetDoubleRef().ValidExternal())
+ bFailure = true;
+ break;
+ default:
+ ;
+ }
+ if (!bFailure)
+ rRefTokens.push_back(
+ ScSharedTokenRef(static_cast<ScToken*>(p->Clone())));
+ }
+ }
- rRefTokens.push_back(
- ScSharedTokenRef(static_cast<ScToken*>(p->Clone())));
#if 0
switch (p->GetType())
{
@@ -93,7 +129,10 @@ void ScRefTokenHelper::compileRangeRepresentation(
;
}
#endif
+
}
+ if (bFailure)
+ rRefTokens.clear();
}
bool ScRefTokenHelper::getRangeFromToken(ScRange& rRange, const ScSharedTokenRef& pToken, bool bExternal)
diff --git a/sc/source/core/tool/refupdat.cxx b/sc/source/core/tool/refupdat.cxx
index d019a6082583..ddb5f3dc0a5c 100644
--- a/sc/source/core/tool/refupdat.cxx
+++ b/sc/source/core/tool/refupdat.cxx
@@ -821,27 +821,27 @@ ScRefUpdateRes ScRefUpdate::Move( ScDocument* pDoc, const ScAddress& rPos,
}
void ScRefUpdate::MoveRelWrap( ScDocument* pDoc, const ScAddress& rPos,
- ScComplexRefData& rRef )
+ SCCOL nMaxCol, SCROW nMaxRow, ScComplexRefData& rRef )
{
if( rRef.Ref1.IsColRel() )
{
rRef.Ref1.nCol = rRef.Ref1.nRelCol + rPos.Col();
- lcl_MoveItWrap( rRef.Ref1.nCol, static_cast<SCsCOL>(0), MAXCOL );
+ lcl_MoveItWrap( rRef.Ref1.nCol, static_cast<SCsCOL>(0), nMaxCol );
}
if( rRef.Ref2.IsColRel() )
{
rRef.Ref2.nCol = rRef.Ref2.nRelCol + rPos.Col();
- lcl_MoveItWrap( rRef.Ref2.nCol, static_cast<SCsCOL>(0), MAXCOL );
+ lcl_MoveItWrap( rRef.Ref2.nCol, static_cast<SCsCOL>(0), nMaxCol );
}
if( rRef.Ref1.IsRowRel() )
{
rRef.Ref1.nRow = rRef.Ref1.nRelRow + rPos.Row();
- lcl_MoveItWrap( rRef.Ref1.nRow, static_cast<SCsROW>(0), MAXROW );
+ lcl_MoveItWrap( rRef.Ref1.nRow, static_cast<SCsROW>(0), nMaxRow );
}
if( rRef.Ref2.IsRowRel() )
{
rRef.Ref2.nRow = rRef.Ref2.nRelRow + rPos.Row();
- lcl_MoveItWrap( rRef.Ref2.nRow, static_cast<SCsROW>(0), MAXROW );
+ lcl_MoveItWrap( rRef.Ref2.nRow, static_cast<SCsROW>(0), nMaxRow );
}
SCsTAB nMaxTab = (SCsTAB) pDoc->GetTableCount() - 1;
if( rRef.Ref1.IsTabRel() )
diff --git a/sc/source/filter/excel/excimp8.cxx b/sc/source/filter/excel/excimp8.cxx
index c4063c74add6..1d209b91bc68 100644
--- a/sc/source/filter/excel/excimp8.cxx
+++ b/sc/source/filter/excel/excimp8.cxx
@@ -427,6 +427,38 @@ void XclImpAutoFilterData::InsertQueryParam()
}
}
+static void ExcelQueryToOooQuery( ScQueryEntry& rEntry )
+{
+ if( ( rEntry.eOp != SC_EQUAL && rEntry.eOp != SC_NOT_EQUAL ) || rEntry.pStr == NULL )
+ return;
+ else
+ {
+ xub_StrLen nLen = rEntry.pStr->Len();
+ sal_Unicode nStart = rEntry.pStr->GetChar( 0 );
+ sal_Unicode nEnd = rEntry.pStr->GetChar( nLen-1 );
+ if( nLen >2 && nStart == '*' && nEnd == '*' )
+ {
+ rEntry.pStr->Erase( nLen-1, 1 );
+ rEntry.pStr->Erase( 0, 1 );
+ rEntry.eOp = ( rEntry.eOp == SC_EQUAL ) ? SC_CONTAINS : SC_DOES_NOT_CONTAIN;
+ }
+ else if( nLen > 1 && nStart == '*' && nEnd != '*' )
+ {
+ rEntry.pStr->Erase( 0, 1 );
+ rEntry.eOp = ( rEntry.eOp == SC_EQUAL ) ? SC_ENDS_WITH : SC_DOES_NOT_END_WITH;
+ }
+ else if( nLen > 1 && nStart != '*' && nEnd == '*' )
+ {
+ rEntry.pStr->Erase( nLen-1, 1 );
+ rEntry.eOp = ( rEntry.eOp == SC_EQUAL ) ? SC_BEGINS_WITH : SC_DOES_NOT_BEGIN_WITH;
+ }
+ else if( nLen == 2 && nStart == '*' && nEnd == '*' )
+ {
+ rEntry.pStr->Erase( 0, 1 );
+ }
+ }
+}
+
void XclImpAutoFilterData::ReadAutoFilter( XclImpStream& rStrm )
{
UINT16 nCol, nFlags;
@@ -464,14 +496,14 @@ void XclImpAutoFilterData::ReadAutoFilter( XclImpStream& rStrm )
BOOL bIgnore;
UINT8 nStrLen[ 2 ] = { 0, 0 };
- String* pEntryStr[ 2 ] = { NULL, NULL };
+ ScQueryEntry *pQueryEntries[ 2 ] = { NULL, NULL };
for( nE = 0; nE < 2; nE++ )
{
if( nFirstEmpty < nCount )
{
ScQueryEntry& aEntry = aParam.GetEntry( nFirstEmpty );
- pEntryStr[ nE ] = aEntry.pStr;
+ pQueryEntries[ nE ] = &aEntry;
bIgnore = FALSE;
rStrm >> nType >> nOper;
@@ -559,8 +591,12 @@ void XclImpAutoFilterData::ReadAutoFilter( XclImpStream& rStrm )
}
for( nE = 0; nE < 2; nE++ )
- if( nStrLen[ nE ] && pEntryStr[ nE ] )
- pEntryStr[ nE ]->Assign( rStrm.ReadUniString( nStrLen[ nE ] ) );
+ if( nStrLen[ nE ] && pQueryEntries[ nE ] )
+ {
+ pQueryEntries[ nE ]->pStr->Assign ( rStrm.ReadUniString( nStrLen[ nE ] ) );
+ ExcelQueryToOooQuery( *pQueryEntries[ nE ] );
+ }
+
}
}
diff --git a/sc/source/filter/excel/excrecds.cxx b/sc/source/filter/excel/excrecds.cxx
index 89a814c8f3c3..0f51bb8f2f1b 100644
--- a/sc/source/filter/excel/excrecds.cxx
+++ b/sc/source/filter/excel/excrecds.cxx
@@ -724,7 +724,31 @@ BOOL XclExpAutofilter::AddEntry( const ScQueryEntry& rEntry )
String sText;
if( rEntry.pStr )
+ {
sText.Assign( *rEntry.pStr );
+ switch( rEntry.eOp )
+ {
+ case SC_CONTAINS:
+ case SC_DOES_NOT_CONTAIN:
+ {
+ sText.InsertAscii( "*" , 0 );
+ sText.AppendAscii( "*" );
+ }
+ break;
+ case SC_BEGINS_WITH:
+ case SC_DOES_NOT_BEGIN_WITH:
+ sText.AppendAscii( "*" );
+ break;
+ case SC_ENDS_WITH:
+ case SC_DOES_NOT_END_WITH:
+ sText.InsertAscii( "*" , 0 );
+ break;
+ default:
+ {
+ //nothing
+ }
+ }
+ }
BOOL bLen = sText.Len() > 0;
@@ -784,6 +808,14 @@ BOOL XclExpAutofilter::AddEntry( const ScQueryEntry& rEntry )
case SC_LESS_EQUAL: nOper = EXC_AFOPER_LESSEQUAL; break;
case SC_GREATER_EQUAL: nOper = EXC_AFOPER_GREATEREQUAL; break;
case SC_NOT_EQUAL: nOper = EXC_AFOPER_NOTEQUAL; break;
+ case SC_CONTAINS:
+ case SC_BEGINS_WITH:
+ case SC_ENDS_WITH:
+ nOper = EXC_AFOPER_EQUAL; break;
+ case SC_DOES_NOT_CONTAIN:
+ case SC_DOES_NOT_BEGIN_WITH:
+ case SC_DOES_NOT_END_WITH:
+ nOper = EXC_AFOPER_NOTEQUAL; break;
default:;
}
bConflict = !AddCondition( rEntry.eConnect, nType, nOper, fVal, pText );
diff --git a/sc/source/filter/excel/namebuff.cxx b/sc/source/filter/excel/namebuff.cxx
index df53c3edcd3c..b01f5a728263 100644
--- a/sc/source/filter/excel/namebuff.cxx
+++ b/sc/source/filter/excel/namebuff.cxx
@@ -127,6 +127,9 @@ void ShrfmlaBuffer::Store( const ScRange& rRange, const ScTokenArray& rToken )
DBG_ASSERT( mnCurrIdx <= 0xFFFF, "*ShrfmlaBuffer::Store(): Gleich wird mir schlecht...!" );
ScRangeData* pData = new ScRangeData( pExcRoot->pIR->GetDocPtr(), aName, rToken, rRange.aStart, RT_SHARED );
+ const ScAddress& rMaxPos = pExcRoot->pIR->GetMaxPos();
+ pData->SetMaxCol(rMaxPos.Col());
+ pData->SetMaxRow(rMaxPos.Row());
pData->SetIndex( static_cast< USHORT >( mnCurrIdx ) );
pExcRoot->pIR->GetNamedRanges().Insert( pData );
index_hash[rRange.aStart] = static_cast< USHORT >( mnCurrIdx );
diff --git a/sc/source/filter/excel/xeformula.cxx b/sc/source/filter/excel/xeformula.cxx
index e065099b2824..457c31d4ab04 100644
--- a/sc/source/filter/excel/xeformula.cxx
+++ b/sc/source/filter/excel/xeformula.cxx
@@ -619,7 +619,7 @@ void XclExpFmlaCompImpl::Init( XclFormulaType eType, const ScTokenArray& rScTokA
DBG_ASSERT( mbOk, "XclExpFmlaCompImpl::Init - missing cell address" );
// clone the passed token array, convert references relative to current cell position
mxOwnScTokArr.reset( rScTokArr.Clone() );
- ScCompiler::MoveRelWrap( *mxOwnScTokArr, GetDocPtr(), *pScBasePos );
+ ScCompiler::MoveRelWrap( *mxOwnScTokArr, GetDocPtr(), *pScBasePos, MAXCOL, MAXROW );
// don't remember pScBasePos in mpScBasePos, shared formulas use real relative refs
break;
default:;
diff --git a/sc/source/filter/xml/XMLConverter.cxx b/sc/source/filter/xml/XMLConverter.cxx
index e0a20ad4353e..84fdba343630 100644
--- a/sc/source/filter/xml/XMLConverter.cxx
+++ b/sc/source/filter/xml/XMLConverter.cxx
@@ -31,20 +31,17 @@
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"
-
-
-
-//___________________________________________________________________
#include "XMLConverter.hxx"
+#include <com/sun/star/util/DateTime.hpp>
+#include <tools/datetime.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
#include "rangelst.hxx"
#include "rangeutl.hxx"
#include "docuno.hxx"
#include "convuno.hxx"
#include "document.hxx"
-#include <tools/datetime.hxx>
-#include <xmloff/xmltoken.hxx>
-#include <xmloff/xmluconv.hxx>
-#include <com/sun/star/util/DateTime.hpp>
+#include "ftools.hxx"
using ::rtl::OUString;
using ::rtl::OUStringBuffer;
@@ -385,3 +382,292 @@ void ScXMLConverter::ConvertAPIToCoreDateTime(const util::DateTime& aDateTime, D
rDateTime = aTempDateTime;
}
+// ============================================================================
+
+namespace {
+
+/** Enumerates different types of condition tokens. */
+enum ScXMLConditionTokenType
+{
+ XML_COND_TYPE_KEYWORD, /// Simple keyword without parentheses, e.g. 'and'.
+ XML_COND_TYPE_COMPARISON, /// Comparison rule, e.g. 'cell-content()<=2'.
+ XML_COND_TYPE_FUNCTION0, /// Function without parameters, e.g. 'cell-content-is-whole-number()'.
+ XML_COND_TYPE_FUNCTION1, /// Function with 1 parameter, e.g. 'is-true-formula(1+1=2)'.
+ XML_COND_TYPE_FUNCTION2 /// Function with 2 parameters, e.g. 'cell-content-is-between(1,2)'.
+};
+
+struct ScXMLConditionInfo
+{
+ ScXMLConditionToken meToken;
+ ScXMLConditionTokenType meType;
+ sheet::ValidationType meValidation;
+ sheet::ConditionOperator meOperator;
+ const sal_Char* mpcIdentifier;
+ sal_Int32 mnIdentLength;
+};
+
+static const ScXMLConditionInfo spConditionInfos[] =
+{
+ { XML_COND_AND, XML_COND_TYPE_KEYWORD, sheet::ValidationType_ANY, sheet::ConditionOperator_NONE, RTL_CONSTASCII_STRINGPARAM( "and" ) },
+ { XML_COND_CELLCONTENT, XML_COND_TYPE_COMPARISON, sheet::ValidationType_ANY, sheet::ConditionOperator_NONE, RTL_CONSTASCII_STRINGPARAM( "cell-content" ) },
+ { XML_COND_ISBETWEEN, XML_COND_TYPE_FUNCTION2, sheet::ValidationType_ANY, sheet::ConditionOperator_BETWEEN, RTL_CONSTASCII_STRINGPARAM( "cell-content-is-between" ) },
+ { XML_COND_ISNOTBETWEEN, XML_COND_TYPE_FUNCTION2, sheet::ValidationType_ANY, sheet::ConditionOperator_NOT_BETWEEN, RTL_CONSTASCII_STRINGPARAM( "cell-content-is-not-between" ) },
+ { XML_COND_ISWHOLENUMBER, XML_COND_TYPE_FUNCTION0, sheet::ValidationType_WHOLE, sheet::ConditionOperator_NONE, RTL_CONSTASCII_STRINGPARAM( "cell-content-is-whole-number" ) },
+ { XML_COND_ISDECIMALNUMBER, XML_COND_TYPE_FUNCTION0, sheet::ValidationType_DECIMAL, sheet::ConditionOperator_NONE, RTL_CONSTASCII_STRINGPARAM( "cell-content-is-decimal-number" ) },
+ { XML_COND_ISDATE, XML_COND_TYPE_FUNCTION0, sheet::ValidationType_DATE, sheet::ConditionOperator_NONE, RTL_CONSTASCII_STRINGPARAM( "cell-content-is-date" ) },
+ { XML_COND_ISTIME, XML_COND_TYPE_FUNCTION0, sheet::ValidationType_TIME, sheet::ConditionOperator_NONE, RTL_CONSTASCII_STRINGPARAM( "cell-content-is-time" ) },
+ { XML_COND_ISINLIST, XML_COND_TYPE_FUNCTION1, sheet::ValidationType_LIST, sheet::ConditionOperator_EQUAL, RTL_CONSTASCII_STRINGPARAM( "cell-content-is-in-list" ) },
+ { XML_COND_TEXTLENGTH, XML_COND_TYPE_COMPARISON, sheet::ValidationType_TEXT_LEN, sheet::ConditionOperator_NONE, RTL_CONSTASCII_STRINGPARAM( "cell-content-text-length" ) },
+ { XML_COND_TEXTLENGTH_ISBETWEEN, XML_COND_TYPE_FUNCTION2, sheet::ValidationType_TEXT_LEN, sheet::ConditionOperator_BETWEEN, RTL_CONSTASCII_STRINGPARAM( "cell-content-text-length-is-between" ) },
+ { XML_COND_TEXTLENGTH_ISNOTBETWEEN, XML_COND_TYPE_FUNCTION2, sheet::ValidationType_TEXT_LEN, sheet::ConditionOperator_NOT_BETWEEN, RTL_CONSTASCII_STRINGPARAM( "cell-content-text-length-is-not-between" ) },
+ { XML_COND_ISTRUEFORMULA, XML_COND_TYPE_FUNCTION1, sheet::ValidationType_CUSTOM, sheet::ConditionOperator_FORMULA, RTL_CONSTASCII_STRINGPARAM( "is-true-formula" ) }
+};
+
+void lclSkipWhitespace( const sal_Unicode*& rpcString, const sal_Unicode* pcEnd )
+{
+ while( (rpcString < pcEnd) && (*rpcString <= ' ') ) ++rpcString;
+}
+
+const ScXMLConditionInfo* lclGetConditionInfo( const sal_Unicode*& rpcString, const sal_Unicode* pcEnd )
+{
+ lclSkipWhitespace( rpcString, pcEnd );
+ /* Search the end of an identifier name; assuming that valid identifiers
+ consist of [a-z-] only. */
+ const sal_Unicode* pcIdStart = rpcString;
+ while( (rpcString < pcEnd) && (((*rpcString >= 'a') && (*rpcString <= 'z')) || (*rpcString == '-')) ) ++rpcString;
+ sal_Int32 nLength = static_cast< sal_Int32 >( rpcString - pcIdStart );
+
+ // search the table for an entry
+ if( nLength > 0 )
+ for( const ScXMLConditionInfo* pInfo = spConditionInfos; pInfo < STATIC_TABLE_END( spConditionInfos ); ++pInfo )
+ if( (nLength == pInfo->mnIdentLength) && (::rtl_ustr_ascii_shortenedCompare_WithLength( pcIdStart, nLength, pInfo->mpcIdentifier, nLength ) == 0) )
+ return pInfo;
+
+ return 0;
+}
+
+sheet::ConditionOperator lclGetConditionOperator( const sal_Unicode*& rpcString, const sal_Unicode* pcEnd )
+{
+ // check for double-char operators
+ if( (rpcString + 1 < pcEnd) && (rpcString[ 1 ] == '=') )
+ {
+ sheet::ConditionOperator eOperator = sheet::ConditionOperator_NONE;
+ switch( *rpcString )
+ {
+ case '!': eOperator = sheet::ConditionOperator_NOT_EQUAL; break;
+ case '<': eOperator = sheet::ConditionOperator_LESS_EQUAL; break;
+ case '>': eOperator = sheet::ConditionOperator_GREATER_EQUAL; break;
+ }
+ if( eOperator != sheet::ConditionOperator_NONE )
+ {
+ rpcString += 2;
+ return eOperator;
+ }
+ }
+
+ // check for single-char operators
+ if( rpcString < pcEnd )
+ {
+ sheet::ConditionOperator eOperator = sheet::ConditionOperator_NONE;
+ switch( *rpcString )
+ {
+ case '=': eOperator = sheet::ConditionOperator_EQUAL; break;
+ case '<': eOperator = sheet::ConditionOperator_LESS; break;
+ case '>': eOperator = sheet::ConditionOperator_GREATER; break;
+ }
+ if( eOperator != sheet::ConditionOperator_NONE )
+ {
+ ++rpcString;
+ return eOperator;
+ }
+ }
+
+ return sheet::ConditionOperator_NONE;
+}
+
+/** Skips a literal string in a formula expression.
+
+ @param rpcString
+ (in-out) On call, must point to the first character of the string
+ following the leading string delimiter character. On return, points to
+ the trailing string delimiter character if existing, otherwise to
+ pcEnd.
+
+ @param pcEnd
+ The end of the string to parse.
+
+ @param cQuoteChar
+ The string delimiter character enclosing the string.
+ */
+void lclSkipExpressionString( const sal_Unicode*& rpcString, const sal_Unicode* pcEnd, sal_Unicode cQuoteChar )
+{
+ if( rpcString < pcEnd )
+ {
+ sal_Int32 nLength = static_cast< sal_Int32 >( pcEnd - rpcString );
+ sal_Int32 nNextQuote = ::rtl_ustr_indexOfChar_WithLength( rpcString, nLength, cQuoteChar );
+ if( nNextQuote >= 0 )
+ rpcString += nNextQuote;
+ else
+ rpcString = pcEnd;
+ }
+}
+
+/** Skips a formula expression. Processes embedded parentheses, braces, and
+ literal strings.
+
+ @param rpcString
+ (in-out) On call, must point to the first character of the expression.
+ On return, points to the passed end character if existing, otherwise to
+ pcEnd.
+
+ @param pcEnd
+ The end of the string to parse.
+
+ @param cEndChar
+ The termination character following the expression.
+ */
+void lclSkipExpression( const sal_Unicode*& rpcString, const sal_Unicode* pcEnd, sal_Unicode cEndChar )
+{
+ while( rpcString < pcEnd )
+ {
+ if( *rpcString == cEndChar )
+ return;
+ switch( *rpcString )
+ {
+ case '(': lclSkipExpression( ++rpcString, pcEnd, ')' ); break;
+ case '{': lclSkipExpression( ++rpcString, pcEnd, '}' ); break;
+ case '"': lclSkipExpressionString( ++rpcString, pcEnd, '"' ); break;
+ case '\'': lclSkipExpressionString( ++rpcString, pcEnd, '\'' ); break;
+ }
+ if( rpcString < pcEnd ) ++rpcString;
+ }
+}
+
+/** Extracts a formula expression. Processes embedded parentheses, braces, and
+ literal strings.
+
+ @param rpcString
+ (in-out) On call, must point to the first character of the expression.
+ On return, points *behind* the passed end character if existing,
+ otherwise to pcEnd.
+
+ @param pcEnd
+ The end of the string to parse.
+
+ @param cEndChar
+ The termination character following the expression.
+ */
+OUString lclGetExpression( const sal_Unicode*& rpcString, const sal_Unicode* pcEnd, sal_Unicode cEndChar )
+{
+ OUString aExp;
+ const sal_Unicode* pcExpStart = rpcString;
+ lclSkipExpression( rpcString, pcEnd, cEndChar );
+ if( rpcString < pcEnd )
+ {
+ aExp = OUString( pcExpStart, static_cast< sal_Int32 >( rpcString - pcExpStart ) ).trim();
+ ++rpcString;
+ }
+ return aExp;
+}
+
+/** Tries to skip an empty pair of parentheses (which may contain whitespace
+ characters).
+
+ @return
+ True on success, rpcString points behind the closing parentheses then.
+ */
+bool lclSkipEmptyParentheses( const sal_Unicode*& rpcString, const sal_Unicode* pcEnd )
+{
+ if( (rpcString < pcEnd) && (*rpcString == '(') )
+ {
+ lclSkipWhitespace( ++rpcString, pcEnd );
+ if( (rpcString < pcEnd) && (*rpcString == ')') )
+ {
+ ++rpcString;
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace
+
+// ----------------------------------------------------------------------------
+
+/*static*/ void ScXMLConditionHelper::parseCondition(
+ ScXMLConditionParseResult& rParseResult, const OUString& rAttribute, sal_Int32 nStartIndex )
+{
+ rParseResult.meToken = XML_COND_INVALID;
+ if( (nStartIndex < 0) || (nStartIndex >= rAttribute.getLength()) ) return;
+
+ // try to find an identifier
+ const sal_Unicode* pcBegin = rAttribute.getStr();
+ const sal_Unicode* pcString = pcBegin + nStartIndex;
+ const sal_Unicode* pcEnd = pcBegin + rAttribute.getLength();
+ if( const ScXMLConditionInfo* pCondInfo = lclGetConditionInfo( pcString, pcEnd ) )
+ {
+ // insert default values into parse result (may be changed below)
+ rParseResult.meValidation = pCondInfo->meValidation;
+ rParseResult.meOperator = pCondInfo->meOperator;
+ // continue parsing dependent on token type
+ switch( pCondInfo->meType )
+ {
+ case XML_COND_TYPE_KEYWORD:
+ // nothing specific has to follow, success
+ rParseResult.meToken = pCondInfo->meToken;
+ break;
+
+ case XML_COND_TYPE_COMPARISON:
+ // format is <condition>()<operator><expression>
+ if( lclSkipEmptyParentheses( pcString, pcEnd ) )
+ {
+ rParseResult.meOperator = lclGetConditionOperator( pcString, pcEnd );
+ if( rParseResult.meOperator != sheet::ConditionOperator_NONE )
+ {
+ lclSkipWhitespace( pcString, pcEnd );
+ if( pcString < pcEnd )
+ {
+ rParseResult.meToken = pCondInfo->meToken;
+ // comparison must be at end of attribute, remaining text is the formula
+ rParseResult.maOperand1 = OUString( pcString, static_cast< sal_Int32 >( pcEnd - pcString ) );
+ }
+ }
+ }
+ break;
+
+ case XML_COND_TYPE_FUNCTION0:
+ // format is <condition>()
+ if( lclSkipEmptyParentheses( pcString, pcEnd ) )
+ rParseResult.meToken = pCondInfo->meToken;
+ break;
+
+ case XML_COND_TYPE_FUNCTION1:
+ // format is <condition>(<expression>)
+ if( (pcString < pcEnd) && (*pcString == '(') )
+ {
+ rParseResult.maOperand1 = lclGetExpression( ++pcString, pcEnd, ')' );
+ if( rParseResult.maOperand1.getLength() > 0 )
+ rParseResult.meToken = pCondInfo->meToken;
+ }
+ break;
+
+ case XML_COND_TYPE_FUNCTION2:
+ // format is <condition>(<expression1>,<expression2>)
+ if( (pcString < pcEnd) && (*pcString == '(') )
+ {
+ rParseResult.maOperand1 = lclGetExpression( ++pcString, pcEnd, ',' );
+ if( rParseResult.maOperand1.getLength() > 0 )
+ {
+ rParseResult.maOperand2 = lclGetExpression( pcString, pcEnd, ')' );
+ if( rParseResult.maOperand2.getLength() > 0 )
+ rParseResult.meToken = pCondInfo->meToken;
+ }
+ }
+ break;
+ }
+ rParseResult.mnEndIndex = static_cast< sal_Int32 >( pcString - pcBegin );
+ }
+}
+
+// ============================================================================
+
diff --git a/sc/source/filter/xml/XMLConverter.hxx b/sc/source/filter/xml/XMLConverter.hxx
index 75254a7b3300..090a3553aa91 100644
--- a/sc/source/filter/xml/XMLConverter.hxx
+++ b/sc/source/filter/xml/XMLConverter.hxx
@@ -36,8 +36,10 @@
#include "detdata.hxx"
#include <rtl/ustrbuf.hxx>
#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/sheet/ConditionOperator.hpp>
#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
#include <com/sun/star/sheet/GeneralFunction.hpp>
+#include <com/sun/star/sheet/ValidationType.hpp>
#include <com/sun/star/util/DateTime.hpp>
class ScDocument;
@@ -117,6 +119,62 @@ public:
static void ConvertAPIToCoreDateTime(const com::sun::star::util::DateTime& aDateTime, DateTime& rDateTime);
};
+// ============================================================================
+
+enum ScXMLConditionToken
+{
+ XML_COND_INVALID, /// Token not recognized.
+ XML_COND_AND, /// The 'and' token.
+ XML_COND_CELLCONTENT, /// The 'cell-content' token.
+ XML_COND_ISBETWEEN, /// The 'cell-content-is-between' token.
+ XML_COND_ISNOTBETWEEN, /// The 'cell-content-is-not-between' token.
+ XML_COND_ISWHOLENUMBER, /// The 'cell-content-is-whole-number' token.
+ XML_COND_ISDECIMALNUMBER, /// The 'cell-content-is-decimal-number' token.
+ XML_COND_ISDATE, /// The 'cell-content-is-date' token.
+ XML_COND_ISTIME, /// The 'cell-content-is-time' token.
+ XML_COND_ISINLIST, /// The 'cell-content-is-in-list' token.
+ XML_COND_TEXTLENGTH, /// The 'cell-content-text-length' token.
+ XML_COND_TEXTLENGTH_ISBETWEEN, /// The 'cell-content-text-length-is-between' token.
+ XML_COND_TEXTLENGTH_ISNOTBETWEEN, /// The 'cell-content-text-length-is-not-between' token.
+ XML_COND_ISTRUEFORMULA /// The 'is-true-formula' token.
+};
+
+// ----------------------------------------------------------------------------
+
+/** Result of an attempt to parse a single condition in a 'condition' attribute
+ value of e.g. conditional formatting or data validation.
+ */
+struct ScXMLConditionParseResult
+{
+ ScXMLConditionToken meToken; /// The leading condition token.
+ ::com::sun::star::sheet::ValidationType
+ meValidation; /// A data validation type if existing.
+ ::com::sun::star::sheet::ConditionOperator
+ meOperator; /// A comparison operator if existing.
+ ::rtl::OUString maOperand1; /// First operand of the token or comparison value.
+ ::rtl::OUString maOperand2; /// Second operand of 'between' conditions.
+ sal_Int32 mnEndIndex; /// Index of first character following the condition.
+};
+
+// ----------------------------------------------------------------------------
+
+class ScXMLConditionHelper
+{
+public:
+ /** Parses the next condition in a 'condition' attribute value of e.g.
+ conditional formatting or data validation.
+ */
+ static void parseCondition(
+ ScXMLConditionParseResult& rParseResult,
+ const ::rtl::OUString& rAttribute,
+ sal_Int32 nStartIndex );
+
+private:
+ ScXMLConditionHelper();
+ ~ScXMLConditionHelper();
+};
+
+// ============================================================================
#endif
diff --git a/sc/source/filter/xml/XMLExportDatabaseRanges.cxx b/sc/source/filter/xml/XMLExportDatabaseRanges.cxx
index 4ca83809843d..b9d9b4936961 100644
--- a/sc/source/filter/xml/XMLExportDatabaseRanges.cxx
+++ b/sc/source/filter/xml/XMLExportDatabaseRanges.cxx
@@ -203,44 +203,56 @@ void ScXMLExportDatabaseRanges::WriteImportDescriptor(const uno::Sequence <beans
}
}
-rtl::OUString ScXMLExportDatabaseRanges::getOperatorXML(const sheet::FilterOperator aFilterOperator, const sal_Bool bUseRegularExpressions) const
+rtl::OUString ScXMLExportDatabaseRanges::getOperatorXML(const long aFilterOperator, const sal_Bool bUseRegularExpressions) const
{
switch (aFilterOperator)
{
- case sheet::FilterOperator_EQUAL :
+ case sheet::FilterOperator2::EQUAL :
{
if (bUseRegularExpressions)
return GetXMLToken(XML_MATCH);
else
return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("="));
}
- case sheet::FilterOperator_NOT_EQUAL :
+ case sheet::FilterOperator2::NOT_EQUAL :
{
if (bUseRegularExpressions)
return GetXMLToken(XML_NOMATCH);
else
return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("!="));
}
- case sheet::FilterOperator_BOTTOM_PERCENT :
+ case sheet::FilterOperator2::BOTTOM_PERCENT :
return GetXMLToken(XML_BOTTOM_PERCENT);
- case sheet::FilterOperator_BOTTOM_VALUES :
+ case sheet::FilterOperator2::BOTTOM_VALUES :
return GetXMLToken(XML_BOTTOM_VALUES);
- case sheet::FilterOperator_EMPTY :
+ case sheet::FilterOperator2::EMPTY :
return GetXMLToken(XML_EMPTY);
- case sheet::FilterOperator_GREATER :
+ case sheet::FilterOperator2::GREATER :
return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(">"));
- case sheet::FilterOperator_GREATER_EQUAL :
+ case sheet::FilterOperator2::GREATER_EQUAL :
return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(">="));
- case sheet::FilterOperator_LESS :
+ case sheet::FilterOperator2::LESS :
return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("<"));
- case sheet::FilterOperator_LESS_EQUAL :
+ case sheet::FilterOperator2::LESS_EQUAL :
return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("<="));
- case sheet::FilterOperator_NOT_EMPTY :
+ case sheet::FilterOperator2::NOT_EMPTY :
return GetXMLToken(XML_NOEMPTY);
- case sheet::FilterOperator_TOP_PERCENT :
+ case sheet::FilterOperator2::TOP_PERCENT :
return GetXMLToken(XML_TOP_PERCENT);
- case sheet::FilterOperator_TOP_VALUES :
+ case sheet::FilterOperator2::TOP_VALUES :
return GetXMLToken(XML_TOP_VALUES);
+ case sheet::FilterOperator2::CONTAINS :
+ return GetXMLToken(XML_CONTAINS);
+ case sheet::FilterOperator2::DOES_NOT_CONTAIN :
+ return GetXMLToken(XML_DOES_NOT_CONTAIN);
+ case sheet::FilterOperator2::BEGINS_WITH :
+ return GetXMLToken(XML_BEGINS_WITH);
+ case sheet::FilterOperator2::DOES_NOT_BEGIN_WITH :
+ return GetXMLToken(XML_DOES_NOT_BEGIN_WITH);
+ case sheet::FilterOperator2::ENDS_WITH :
+ return GetXMLToken(XML_ENDS_WITH);
+ case sheet::FilterOperator2::DOES_NOT_END_WITH :
+ return GetXMLToken(XML_DOES_NOT_END_WITH);
default:
{
// added to avoid warnings
@@ -249,7 +261,7 @@ rtl::OUString ScXMLExportDatabaseRanges::getOperatorXML(const sheet::FilterOpera
return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("="));
}
-void ScXMLExportDatabaseRanges::WriteCondition(const sheet::TableFilterField& aFilterField, sal_Bool bIsCaseSensitive, sal_Bool bUseRegularExpressions)
+void ScXMLExportDatabaseRanges::WriteCondition(const sheet::TableFilterField2& aFilterField, sal_Bool bIsCaseSensitive, sal_Bool bUseRegularExpressions)
{
rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FIELD_NUMBER, rtl::OUString::valueOf(aFilterField.Field));
if (bIsCaseSensitive)
@@ -267,9 +279,9 @@ void ScXMLExportDatabaseRanges::WriteCondition(const sheet::TableFilterField& aF
SvXMLElementExport aElemC(rExport, XML_NAMESPACE_TABLE, XML_FILTER_CONDITION, sal_True, sal_True);
}
-void ScXMLExportDatabaseRanges::WriteFilterDescriptor(const uno::Reference <sheet::XSheetFilterDescriptor>& xSheetFilterDescriptor, const rtl::OUString sDatabaseRangeName)
+void ScXMLExportDatabaseRanges::WriteFilterDescriptor(const uno::Reference <sheet::XSheetFilterDescriptor2>& xSheetFilterDescriptor, const rtl::OUString sDatabaseRangeName)
{
- uno::Sequence <sheet::TableFilterField> aTableFilterFields(xSheetFilterDescriptor->getFilterFields());
+ uno::Sequence< sheet::TableFilterField2 > aTableFilterFields( xSheetFilterDescriptor->getFilterFields2() );
sal_Int32 nTableFilterFields = aTableFilterFields.getLength();
if (nTableFilterFields > 0)
{
@@ -336,7 +348,7 @@ void ScXMLExportDatabaseRanges::WriteFilterDescriptor(const uno::Reference <shee
else
{
SvXMLElementExport aElemC(rExport, XML_NAMESPACE_TABLE, XML_FILTER_OR, sal_True, sal_True);
- sheet::TableFilterField aPrevFilterField = aTableFilterFields[0];
+ sheet::TableFilterField2 aPrevFilterField = aTableFilterFields[0];
sheet::FilterConnection aConnection = aTableFilterFields[1].Connection;
sal_Bool bOpenAndElement;
rtl::OUString aName = rExport.GetNamespaceMap().GetQNameByKey(XML_NAMESPACE_TABLE, GetXMLToken(XML_FILTER_AND));
@@ -632,7 +644,9 @@ void ScXMLExportDatabaseRanges::WriteDatabaseRanges(const com::sun::star::uno::R
if (::cppu::any2bool(xPropertySetDatabaseRange->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_STRIPDAT)))))
rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_HAS_PERSISTENT_DATA, XML_FALSE);
}
- uno::Reference <sheet::XSheetFilterDescriptor> xSheetFilterDescriptor(xDatabaseRange->getFilterDescriptor());
+
+ uno::Reference< sheet::XSheetFilterDescriptor2 > xSheetFilterDescriptor(
+ xDatabaseRange->getFilterDescriptor(), uno::UNO_QUERY );
uno::Sequence <beans::PropertyValue> aSortProperties(xDatabaseRange->getSortDescriptor());
if (xSheetFilterDescriptor.is())
{
diff --git a/sc/source/filter/xml/XMLExportDatabaseRanges.hxx b/sc/source/filter/xml/XMLExportDatabaseRanges.hxx
index c4829ffd3fdd..81d1399e16b3 100644
--- a/sc/source/filter/xml/XMLExportDatabaseRanges.hxx
+++ b/sc/source/filter/xml/XMLExportDatabaseRanges.hxx
@@ -33,9 +33,9 @@
#include <com/sun/star/uno/Sequence.h>
#include <com/sun/star/beans/PropertyValue.hpp>
-#include <com/sun/star/sheet/FilterOperator.hpp>
-#include <com/sun/star/sheet/TableFilterField.hpp>
-#include <com/sun/star/sheet/XSheetFilterDescriptor.hpp>
+#include <com/sun/star/sheet/FilterOperator2.hpp>
+#include <com/sun/star/sheet/TableFilterField2.hpp>
+#include <com/sun/star/sheet/XSheetFilterDescriptor2.hpp>
#include <com/sun/star/sheet/XSubTotalDescriptor.hpp>
#include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
@@ -49,9 +49,9 @@ class ScXMLExportDatabaseRanges
ScDocument* pDoc;
void WriteImportDescriptor(const com::sun::star::uno::Sequence <com::sun::star::beans::PropertyValue> aImportDescriptor);
- rtl::OUString getOperatorXML(const com::sun::star::sheet::FilterOperator aFilterOperator, const sal_Bool bUseRegularExpressions) const;
- void WriteCondition(const com::sun::star::sheet::TableFilterField& aFilterField, sal_Bool bIsCaseSensitive, sal_Bool bUseRegularExpressions);
- void WriteFilterDescriptor(const com::sun::star::uno::Reference <com::sun::star::sheet::XSheetFilterDescriptor>& xSheetFilterDescriptor, const rtl::OUString sDatabaseRangeName);
+ rtl::OUString getOperatorXML(const long aFilterOperator, const sal_Bool bUseRegularExpressions) const;
+ void WriteCondition(const com::sun::star::sheet::TableFilterField2& aFilterField, sal_Bool bIsCaseSensitive, sal_Bool bUseRegularExpressions);
+ void WriteFilterDescriptor(const com::sun::star::uno::Reference <com::sun::star::sheet::XSheetFilterDescriptor2>& xSheetFilterDescriptor, const rtl::OUString sDatabaseRangeName);
void WriteSortDescriptor(const com::sun::star::uno::Sequence <com::sun::star::beans::PropertyValue> aSortProperties);
void WriteSubTotalDescriptor(const com::sun::star::uno::Reference <com::sun::star::sheet::XSubTotalDescriptor> xSubTotalDescriptor, const rtl::OUString sDatabaseRangeName);
public:
diff --git a/sc/source/filter/xml/XMLTrackedChangesContext.cxx b/sc/source/filter/xml/XMLTrackedChangesContext.cxx
index d1320a8c737f..2d8eac1dfc76 100644
--- a/sc/source/filter/xml/XMLTrackedChangesContext.cxx
+++ b/sc/source/filter/xml/XMLTrackedChangesContext.cxx
@@ -109,6 +109,7 @@ class ScXMLCellContentDeletionContext : public SvXMLImportContext
{
rtl::OUString sFormulaAddress;
rtl::OUString sFormula;
+ rtl::OUString sFormulaNmsp;
rtl::OUString sInputString;
ScBigRange aBigRange;
double fValue;
@@ -298,7 +299,8 @@ public:
ScXMLChangeCellContext( ScXMLImport& rImport, USHORT nPrfx, const ::rtl::OUString& rLName,
const ::com::sun::star::uno::Reference<
::com::sun::star::xml::sax::XAttributeList>& xAttrList,
- ScBaseCell*& rOldCell, rtl::OUString& sAddress, rtl::OUString& sFormula,
+ ScBaseCell*& rOldCell, rtl::OUString& sAddress,
+ rtl::OUString& rFormula, rtl::OUString& rFormulaNmsp,
formula::FormulaGrammar::Grammar& rGrammar,
rtl::OUString& rInputString, double& fValue, sal_uInt16& nType,
sal_uInt8& nMatrixFlag, sal_Int32& nMatrixCols, sal_Int32& nMatrixRows);
@@ -322,6 +324,7 @@ class ScXMLPreviousContext : public SvXMLImportContext
{
rtl::OUString sFormulaAddress;
rtl::OUString sFormula;
+ rtl::OUString sFormulaNmsp;
rtl::OUString sInputString;
double fValue;
ScXMLChangeTrackingImportHelper* pChangeTrackingImportHelper;
@@ -329,7 +332,7 @@ class ScXMLPreviousContext : public SvXMLImportContext
sal_uInt32 nID;
sal_Int32 nMatrixCols;
sal_Int32 nMatrixRows;
- formula::FormulaGrammar::Grammar eGrammar;
+ formula::FormulaGrammar::Grammar eGrammar;
sal_uInt16 nType;
sal_uInt8 nMatrixFlag;
@@ -831,7 +834,7 @@ SvXMLImportContext *ScXMLCellContentDeletionContext::CreateChildContext( USHORT
{
bContainsCell = sal_True;
pContext = new ScXMLChangeCellContext(GetScImport(), nPrefix, rLocalName, xAttrList,
- pCell, sFormulaAddress, sFormula, eGrammar, sInputString, fValue, nType, nMatrixFlag, nMatrixCols, nMatrixRows );
+ pCell, sFormulaAddress, sFormula, sFormulaNmsp, eGrammar, sInputString, fValue, nType, nMatrixFlag, nMatrixCols, nMatrixRows );
}
else if (IsXMLToken(rLocalName, XML_CELL_ADDRESS))
{
@@ -1115,7 +1118,8 @@ ScXMLChangeCellContext::ScXMLChangeCellContext( ScXMLImport& rImport,
USHORT nPrfx,
const ::rtl::OUString& rLName,
const uno::Reference<xml::sax::XAttributeList>& xAttrList,
- ScBaseCell*& rTempOldCell, rtl::OUString& rAddress, rtl::OUString& rFormula,
+ ScBaseCell*& rTempOldCell, rtl::OUString& rAddress,
+ rtl::OUString& rFormula, rtl::OUString& rFormulaNmsp,
formula::FormulaGrammar::Grammar& rGrammar,
rtl::OUString& rTempInputString, double& fDateTimeValue, sal_uInt16& nType,
sal_uInt8& nMatrixFlag, sal_Int32& nMatrixCols, sal_Int32& nMatrixRows ) :
@@ -1130,7 +1134,6 @@ ScXMLChangeCellContext::ScXMLChangeCellContext( ScXMLImport& rImport,
bString(sal_True),
bFormula(sal_False)
{
- const formula::FormulaGrammar::Grammar eStorageGrammar = rGrammar = GetScImport().GetDocument()->GetStorageGrammar();
sal_Bool bIsMatrix(sal_False);
sal_Bool bIsCoveredMatrix(sal_False);
sal_Int16 nAttrCount(xAttrList.is() ? xAttrList->getLength() : 0);
@@ -1147,12 +1150,7 @@ ScXMLChangeCellContext::ScXMLChangeCellContext( ScXMLImport& rImport,
if (IsXMLToken(aLocalName, XML_FORMULA))
{
bEmpty = sal_False;
- sal_uInt16 nFormulaPrefix = GetImport().GetNamespaceMap().
- _GetKeyByAttrName( sValue, &rFormula, sal_False );
-
- if (!ScXMLImport::IsAcceptedFormulaNamespace( nFormulaPrefix,
- sValue, rGrammar, eStorageGrammar))
- rFormula = sValue;
+ GetScImport().ExtractFormulaNamespaceGrammar( rFormula, rFormulaNmsp, rGrammar, sValue );
bFormula = sal_True;
}
else if (IsXMLToken(aLocalName, XML_CELL_ADDRESS))
@@ -1339,8 +1337,6 @@ ScXMLPreviousContext::ScXMLPreviousContext( ScXMLImport& rImport,
const uno::Reference<xml::sax::XAttributeList>& xAttrList,
ScXMLChangeTrackingImportHelper* pTempChangeTrackingImportHelper ) :
SvXMLImportContext( rImport, nPrfx, rLName ),
- sFormulaAddress(),
- sFormula(),
pChangeTrackingImportHelper(pTempChangeTrackingImportHelper),
pOldCell(NULL),
nID(0),
@@ -1380,7 +1376,7 @@ SvXMLImportContext *ScXMLPreviousContext::CreateChildContext( USHORT nPrefix,
if ((nPrefix == XML_NAMESPACE_TABLE) && (IsXMLToken(rLocalName, XML_CHANGE_TRACK_TABLE_CELL)))
pContext = new ScXMLChangeCellContext(GetScImport(), nPrefix, rLocalName, xAttrList,
- pOldCell, sFormulaAddress, sFormula, eGrammar, sInputString, fValue, nType, nMatrixFlag, nMatrixCols, nMatrixRows);
+ pOldCell, sFormulaAddress, sFormula, sFormulaNmsp, eGrammar, sInputString, fValue, nType, nMatrixFlag, nMatrixCols, nMatrixRows);
if( !pContext )
pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
diff --git a/sc/source/filter/xml/xmlcelli.cxx b/sc/source/filter/xml/xmlcelli.cxx
index 5c190ca272b3..f0a4569cc86e 100644
--- a/sc/source/filter/xml/xmlcelli.cxx
+++ b/sc/source/filter/xml/xmlcelli.cxx
@@ -129,7 +129,6 @@ ScXMLTableRowCellContext::ScXMLTableRowCellContext( ScXMLImport& rImport,
bSolarMutexLocked(sal_False),
bFormulaTextResult(sal_False)
{
- formula::FormulaGrammar::Grammar eStorageGrammar = eGrammar = GetScImport().GetDocument()->GetStorageGrammar();
rXMLImport.SetRemoveLastChar(sal_False);
rXMLImport.GetTables().AddColumn(bTempIsCovered);
const sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
@@ -232,25 +231,9 @@ ScXMLTableRowCellContext::ScXMLTableRowCellContext( ScXMLImport& rImport,
if (sValue.getLength())
{
DBG_ASSERT(!pOUFormula, "here should be only one formula");
- rtl::OUString sFormula;
- sal_uInt16 nFormulaPrefix = GetImport().GetNamespaceMap().
- _GetKeyByAttrName( sValue, &sFormula, sal_False );
-
- if (ScXMLImport::IsAcceptedFormulaNamespace(
- nFormulaPrefix, sValue, eGrammar,
- eStorageGrammar))
- {
- // Namespaces we accept.
- pOUFormula.reset( sFormula);
- }
- else
- {
- // No namespace => entire string.
- // Also unknown namespace included in formula,
- // so hopefully will result in string or
- // compile error.
- pOUFormula.reset( sValue);
- }
+ rtl::OUString aFormula, aFormulaNmsp;
+ rXMLImport.ExtractFormulaNamespaceGrammar( aFormula, aFormulaNmsp, eGrammar, sValue );
+ pOUFormula.reset( FormulaWithNamespace( aFormula, aFormulaNmsp ) );
}
}
break;
@@ -530,7 +513,7 @@ void ScXMLTableRowCellContext::SetContentValidation(com::sun::star::uno::Referen
if (pContentValidationName)
{
ScMyImportValidation aValidation;
- aValidation.eGrammar = GetScImport().GetDocument()->GetStorageGrammar();
+ aValidation.eGrammar1 = aValidation.eGrammar2 = GetScImport().GetDocument()->GetStorageGrammar();
if (rXMLImport.GetValidation(*pContentValidationName, aValidation))
{
uno::Reference<beans::XPropertySet> xPropertySet(xPropSet->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_VALIXML))), uno::UNO_QUERY);
@@ -559,8 +542,11 @@ void ScXMLTableRowCellContext::SetContentValidation(com::sun::star::uno::Referen
// #b4974740# source position must be set as string, because it may
// refer to a sheet that hasn't been loaded yet.
xPropertySet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_SOURCESTR)), uno::makeAny(aValidation.sBaseCellAddress));
- // Transport grammar.
- xPropertySet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_GRAMMAR)), uno::makeAny(static_cast<sal_Int32>(aValidation.eGrammar)));
+ // Transport grammar and formula namespace
+ xPropertySet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_FORMULANMSP1)), uno::makeAny(aValidation.sFormulaNmsp1));
+ xPropertySet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_FORMULANMSP2)), uno::makeAny(aValidation.sFormulaNmsp2));
+ xPropertySet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_GRAMMAR1)), uno::makeAny(static_cast<sal_Int32>(aValidation.eGrammar1)));
+ xPropertySet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_GRAMMAR2)), uno::makeAny(static_cast<sal_Int32>(aValidation.eGrammar2)));
}
}
xPropSet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_VALIXML)), uno::makeAny(xPropertySet));
@@ -1046,7 +1032,7 @@ void ScXMLTableRowCellContext::EndElement()
//SetType(xTempCell);
}
}
- else
+ else // if ( !pOUFormula )
{
if (CellExists(aCellPos))
{
@@ -1059,7 +1045,7 @@ void ScXMLTableRowCellContext::EndElement()
{
DBG_ERRORFILE("It seems here are to many columns or rows");
}
- if (xCell.is() && pOUFormula)
+ if (xCell.is())
{
SetCellProperties(xCell); // set now only the validation
DBG_ASSERT(((nCellsRepeated == 1) && (nRepeatedRows == 1)), "repeated cells with formula not possible now");
@@ -1072,7 +1058,7 @@ void ScXMLTableRowCellContext::EndElement()
xCell));
if (pCellObj)
{
- pCellObj->SetFormulaWithGrammar( *pOUFormula, eGrammar);
+ pCellObj->SetFormulaWithGrammar( pOUFormula->first, pOUFormula->second, eGrammar);
if (bFormulaTextResult && pOUTextValue && pOUTextValue->getLength())
pCellObj->SetFormulaResultString( *pOUTextValue);
else if (fValue != 0.0)
@@ -1087,7 +1073,7 @@ void ScXMLTableRowCellContext::EndElement()
aCellPos.Column, aCellPos.Row,
aCellPos.Column + nMatrixCols - 1,
aCellPos.Row + nMatrixRows - 1,
- *pOUFormula, eGrammar);
+ pOUFormula->first, pOUFormula->second, eGrammar);
}
}
SetAnnotation( aCellPos );
@@ -1104,7 +1090,7 @@ void ScXMLTableRowCellContext::EndElement()
rXMLImport.SetRangeOverflowType(SCWARN_IMPORT_COLUMN_OVERFLOW);
}
- }
+ } // if ( !pOUFormula )
}
UnlockSolarMutex();
}
diff --git a/sc/source/filter/xml/xmlcelli.hxx b/sc/source/filter/xml/xmlcelli.hxx
index 1a4280af36b2..fe2bfd116348 100644
--- a/sc/source/filter/xml/xmlcelli.hxx
+++ b/sc/source/filter/xml/xmlcelli.hxx
@@ -52,11 +52,12 @@ struct ScXMLAnnotationData;
class ScXMLTableRowCellContext : public SvXMLImportContext
{
+ typedef ::std::pair< ::rtl::OUString, ::rtl::OUString > FormulaWithNamespace;
com::sun::star::uno::Reference<com::sun::star::table::XCell> xBaseCell;
com::sun::star::uno::Reference<com::sun::star::document::XActionLockable> xLockable;
::boost::optional< rtl::OUString > pOUTextValue;
::boost::optional< rtl::OUString > pOUTextContent;
- ::boost::optional< rtl::OUString > pOUFormula;
+ ::boost::optional< FormulaWithNamespace > pOUFormula;
rtl::OUString* pContentValidationName;
::std::auto_ptr< ScXMLAnnotationData > mxAnnotationData;
ScMyImpDetectiveObjVec* pDetectiveObjVec;
diff --git a/sc/source/filter/xml/xmlcvali.cxx b/sc/source/filter/xml/xmlcvali.cxx
index d8d8eb0d7cc2..aeff28f3eed6 100644
--- a/sc/source/filter/xml/xmlcvali.cxx
+++ b/sc/source/filter/xml/xmlcvali.cxx
@@ -51,6 +51,8 @@
using namespace com::sun::star;
using namespace xmloff::token;
+using namespace ::formula;
+using ::rtl::OUString;
class ScXMLContentValidationContext : public SvXMLImportContext
{
@@ -62,7 +64,6 @@ class ScXMLContentValidationContext : public SvXMLImportContext
rtl::OUString sErrorMessageType;
rtl::OUString sBaseCellAddress;
rtl::OUString sCondition;
- formula::FormulaGrammar::Grammar eGrammar;
sal_Int16 nShowList;
sal_Bool bAllowEmptyCell;
sal_Bool bDisplayHelp;
@@ -73,11 +74,10 @@ class ScXMLContentValidationContext : public SvXMLImportContext
const ScXMLImport& GetScImport() const { return (const ScXMLImport&)GetImport(); }
ScXMLImport& GetScImport() { return (ScXMLImport&)GetImport(); }
- void GetAlertStyle(const rtl::OUString& sMessageType, com::sun::star::sheet::ValidationAlertStyle& aAlertStyle);
- void SetFormulas(const rtl::OUString& sFormulas, rtl::OUString& sFormula1, rtl::OUString& sFormula2) const;
- void GetCondition(const rtl::OUString& sCondition, rtl::OUString& sFormula1, rtl::OUString& sFormula2,
- com::sun::star::sheet::ValidationType& aValidationType,
- com::sun::star::sheet::ConditionOperator& aOperator);
+ com::sun::star::sheet::ValidationAlertStyle GetAlertStyle() const;
+ void SetFormula( OUString& rFormula, OUString& rFormulaNmsp, FormulaGrammar::Grammar& reGrammar,
+ const OUString& rCondition, const OUString& rGlobNmsp, FormulaGrammar::Grammar eGlobGrammar, bool bHasNmsp ) const;
+ void GetCondition( ScMyImportValidation& rValidation ) const;
public:
@@ -235,20 +235,11 @@ ScXMLContentValidationContext::ScXMLContentValidationContext( ScXMLImport& rImpo
const ::com::sun::star::uno::Reference<
::com::sun::star::xml::sax::XAttributeList>& xAttrList) :
SvXMLImportContext( rImport, nPrfx, rLName ),
- sName(),
- sHelpTitle(),
- sHelpMessage(),
- sErrorTitle(),
- sErrorMessage(),
- sErrorMessageType(),
- sBaseCellAddress(),
- sCondition(),
nShowList(sheet::TableValidationVisibility::UNSORTED),
bAllowEmptyCell(sal_True),
bDisplayHelp(sal_False),
bDisplayError(sal_False)
{
- const formula::FormulaGrammar::Grammar eStorageGrammar = eGrammar = GetScImport().GetDocument()->GetStorageGrammar();
sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
const SvXMLTokenMap& rAttrTokenMap = GetScImport().GetContentValidationAttrTokenMap();
for( sal_Int16 i=0; i < nAttrCount; ++i )
@@ -265,14 +256,7 @@ ScXMLContentValidationContext::ScXMLContentValidationContext( ScXMLImport& rImpo
sName = sValue;
break;
case XML_TOK_CONTENT_VALIDATION_CONDITION:
- {
- sal_uInt16 nCondPrefix = GetImport().GetNamespaceMap().
- _GetKeyByAttrName( sValue, &sCondition, sal_False );
-
- if (!ScXMLImport::IsAcceptedFormulaNamespace( nCondPrefix,
- sValue, eGrammar, eStorageGrammar))
- sCondition = sValue;
- }
+ sCondition = sValue;
break;
case XML_TOK_CONTENT_VALIDATION_BASE_CELL_ADDRESS:
sBaseCellAddress = sValue;
@@ -336,189 +320,116 @@ SvXMLImportContext *ScXMLContentValidationContext::CreateChildContext( USHORT nP
return pContext;
}
-void ScXMLContentValidationContext::GetAlertStyle(const rtl::OUString& sMessageType, com::sun::star::sheet::ValidationAlertStyle& aAlertStyle)
+sheet::ValidationAlertStyle ScXMLContentValidationContext::GetAlertStyle() const
{
- if (IsXMLToken(sMessageType, XML_MACRO))
- aAlertStyle = sheet::ValidationAlertStyle_MACRO;
- else if (IsXMLToken(sMessageType, XML_STOP))
- aAlertStyle = sheet::ValidationAlertStyle_STOP;
- else if (IsXMLToken(sMessageType, XML_WARNING))
- aAlertStyle = sheet::ValidationAlertStyle_WARNING;
- else if (IsXMLToken(sMessageType, XML_INFORMATION))
- aAlertStyle = sheet::ValidationAlertStyle_INFO;
- else // don't leave uninitialized
- aAlertStyle = sheet::ValidationAlertStyle_STOP;
+ if (IsXMLToken(sErrorMessageType, XML_MACRO))
+ return sheet::ValidationAlertStyle_MACRO;
+ if (IsXMLToken(sErrorMessageType, XML_STOP))
+ return sheet::ValidationAlertStyle_STOP;
+ if (IsXMLToken(sErrorMessageType, XML_WARNING))
+ return sheet::ValidationAlertStyle_WARNING;
+ if (IsXMLToken(sErrorMessageType, XML_INFORMATION))
+ return sheet::ValidationAlertStyle_INFO;
+ // default for unknown
+ return sheet::ValidationAlertStyle_STOP;
}
-void ScXMLContentValidationContext::SetFormulas(const rtl::OUString& sFormulas, rtl::OUString& sFormula1, rtl::OUString& sFormula2) const
+void ScXMLContentValidationContext::SetFormula( OUString& rFormula, OUString& rFormulaNmsp, FormulaGrammar::Grammar& reGrammar,
+ const OUString& rCondition, const OUString& rGlobNmsp, FormulaGrammar::Grammar eGlobGrammar, bool bHasNmsp ) const
{
- sal_Int32 i = 0;
- sal_Bool bString = sal_False;
- sal_Int32 nBrakes = 0;
- while ((sFormulas[i] != ',' || nBrakes > 0 || bString) && i < sFormulas.getLength())
+ reGrammar = FormulaGrammar::GRAM_UNSPECIFIED;
+ if( bHasNmsp )
{
- if (sFormulas[i] == '(')
- ++nBrakes;
- if (sFormulas[i] == ')')
- --nBrakes;
- if (sFormulas[i] == '"')
- bString = !bString;
- ++i;
+ // the entire attribute contains a namespace: internal namespace not allowed
+ rFormula = rCondition;
+ rFormulaNmsp = rGlobNmsp;
+ reGrammar = eGlobGrammar;
}
- if (sFormulas[i] == ',')
+ else
{
- sFormula1 = sFormulas.copy(0, i);
- sFormula2 = sFormulas.copy(i + 1);
+ // the attribute does not contain a namespace: try to find a namespace of an external grammar
+ GetScImport().ExtractFormulaNamespaceGrammar( rFormula, rFormulaNmsp, reGrammar, rCondition, true );
+ if( reGrammar != FormulaGrammar::GRAM_EXTERNAL )
+ reGrammar = eGlobGrammar;
}
}
-void ScXMLContentValidationContext::GetCondition(const rtl::OUString& sTempCondition, rtl::OUString& sFormula1, rtl::OUString& sFormula2,
- com::sun::star::sheet::ValidationType& aValidationType,
- com::sun::star::sheet::ConditionOperator& aOperator)
+void ScXMLContentValidationContext::GetCondition( ScMyImportValidation& rValidation ) const
{
- aValidationType = sheet::ValidationType_ANY; // #b6343997# default if no condition is given
- aOperator = sheet::ConditionOperator_NONE;
+ rValidation.aValidationType = sheet::ValidationType_ANY; // #b6343997# default if no condition is given
+ rValidation.aOperator = sheet::ConditionOperator_NONE;
- rtl::OUString sLocalCondition(sTempCondition);
- if (sLocalCondition.getLength())
+ if( sCondition.getLength() > 0 )
{
- // ToDo: erase all blanks in the condition, but not in formulas or strings
- rtl::OUString scell_content(RTL_CONSTASCII_USTRINGPARAM("cell_content"));
- rtl::OUString scell_content_is_date(RTL_CONSTASCII_USTRINGPARAM("cell-content-is-date"));
- rtl::OUString scell_content_is_time(RTL_CONSTASCII_USTRINGPARAM("cell-content-is-time"));
- rtl::OUString scell_content_is_between(RTL_CONSTASCII_USTRINGPARAM("cell-content-is-between"));
- rtl::OUString scell_content_is_in_list(RTL_CONSTASCII_USTRINGPARAM("cell-content-is-in-list"));
- rtl::OUString scell_content_text_length(RTL_CONSTASCII_USTRINGPARAM("cell-content-text-length"));
- rtl::OUString scell_content_is_not_between(RTL_CONSTASCII_USTRINGPARAM("cell-content-is-not-between"));
- rtl::OUString scell_content_is_whole_number(RTL_CONSTASCII_USTRINGPARAM("cell-content-is-whole-number"));
- rtl::OUString scell_content_is_decimal_number(RTL_CONSTASCII_USTRINGPARAM("cell-content-is-decimal-number"));
- rtl::OUString scell_content_text_length_is_between(RTL_CONSTASCII_USTRINGPARAM("cell-content-text-length-is-between"));
- rtl::OUString scell_content_text_length_is_not_between(RTL_CONSTASCII_USTRINGPARAM("cell-content-text-length-is-not-between"));
- sal_Int32 i = 0;
- sal_Bool bAnd(sal_True);
- while (sLocalCondition[i] != '(' && i < sLocalCondition.getLength())
- ++i;
- if (sLocalCondition[i] == '(')
+ // extract leading namespace from condition string
+ OUString aCondition, aConditionNmsp;
+ FormulaGrammar::Grammar eGrammar = FormulaGrammar::GRAM_UNSPECIFIED;
+ GetScImport().ExtractFormulaNamespaceGrammar( aCondition, aConditionNmsp, eGrammar, sCondition );
+ bool bHasNmsp = aCondition.getLength() < sCondition.getLength();
+
+ // parse a condition from the attribute string
+ ScXMLConditionParseResult aParseResult;
+ ScXMLConditionHelper::parseCondition( aParseResult, aCondition, 0 );
+
+ /* Check the result. A valid value in aParseResult.meToken implies
+ that the other members of aParseResult are filled with valid data
+ for that token. */
+ bool bSecondaryPart = false;
+ switch( aParseResult.meToken )
{
- if (i != scell_content_text_length.getLength() &&
- i != scell_content_text_length_is_between.getLength() &&
- i != scell_content_text_length_is_not_between.getLength() &&
- i != scell_content_is_in_list.getLength())
- {
- if (i == scell_content_is_time.getLength())
- {
- rtl::OUString sTemp = sLocalCondition.copy(0, i);
- if (sTemp == scell_content_is_time)
- aValidationType = sheet::ValidationType_TIME;
- else
- aValidationType = sheet::ValidationType_DATE;
- }
- else if (i == scell_content_is_whole_number.getLength())
- aValidationType = sheet::ValidationType_WHOLE;
- else if (i == scell_content_is_decimal_number.getLength())
- aValidationType = sheet::ValidationType_DECIMAL;
- sLocalCondition = sLocalCondition.copy(i + 2);
- rtl::OUString sTemp = sLocalCondition.copy(0, 5);
- if (sTemp.compareToAscii(" and ") == 0)
- sLocalCondition = sLocalCondition.copy(5);
- else
- bAnd = sal_False;
- }
- if (sLocalCondition.getLength() && bAnd)
+ case XML_COND_TEXTLENGTH: // condition is 'cell-content-text-length()<operator><expression>'
+ case XML_COND_TEXTLENGTH_ISBETWEEN: // condition is 'cell-content-text-length-is-between(<expression1>,<expression2>)'
+ case XML_COND_TEXTLENGTH_ISNOTBETWEEN: // condition is 'cell-content-text-length-is-not-between(<expression1>,<expression2>)'
+ case XML_COND_ISINLIST: // condition is 'cell-content-is-in-list(<expression>)'
+ rValidation.aValidationType = aParseResult.meValidation;
+ rValidation.aOperator = aParseResult.meOperator;
+ break;
+
+ case XML_COND_ISWHOLENUMBER: // condition is 'cell-content-is-whole-number() and <condition>'
+ case XML_COND_ISDECIMALNUMBER: // condition is 'cell-content-is-decimal-number() and <condition>'
+ case XML_COND_ISDATE: // condition is 'cell-content-is-date() and <condition>'
+ case XML_COND_ISTIME: // condition is 'cell-content-is-time() and <condition>'
+ rValidation.aValidationType = aParseResult.meValidation;
+ bSecondaryPart = true;
+ break;
+
+ default:; // unacceptable or unknown condition
+ }
+
+ /* Parse the following 'and <condition>' part of some conditions. This
+ updates the members of aParseResult that will contain the operands
+ and comparison operator then. */
+ if( bSecondaryPart )
+ {
+ ScXMLConditionHelper::parseCondition( aParseResult, aCondition, aParseResult.mnEndIndex );
+ if( aParseResult.meToken == XML_COND_AND )
{
- i = 0;
- while (sLocalCondition[i] != '(' && i < sLocalCondition.getLength())
- ++i;
- if (sLocalCondition[i] == '(')
+ ScXMLConditionHelper::parseCondition( aParseResult, aCondition, aParseResult.mnEndIndex );
+ switch( aParseResult.meToken )
{
- rtl::OUString sTemp = sLocalCondition.copy(0, i);
- sLocalCondition = sLocalCondition.copy(i + 1);
- if (i == scell_content_is_between.getLength() ||
- i == scell_content_text_length_is_between.getLength())
- {
- if (sTemp == scell_content_is_in_list)
- {
- aValidationType = sheet::ValidationType_LIST;
- sFormula1 = sLocalCondition.copy(0, sLocalCondition.getLength() - 1);
- aOperator = sheet::ConditionOperator_EQUAL;
- }
- else
- {
- if (i == scell_content_text_length_is_between.getLength())
- aValidationType = sheet::ValidationType_TEXT_LEN;
- aOperator = sheet::ConditionOperator_BETWEEN;
- sLocalCondition = sLocalCondition.copy(0, sLocalCondition.getLength() - 1);
- SetFormulas(sLocalCondition, sFormula1, sFormula2);
- }
- }
- else if (i == scell_content_is_not_between.getLength() ||
- i == scell_content_text_length_is_not_between.getLength())
- {
- if (i == scell_content_text_length_is_not_between.getLength())
- aValidationType = sheet::ValidationType_TEXT_LEN;
- aOperator = sheet::ConditionOperator_NOT_BETWEEN;
- sLocalCondition = sLocalCondition.copy(0, sLocalCondition.getLength() - 1);
- SetFormulas(sLocalCondition, sFormula1, sFormula2);
- }
- else if (i == scell_content.getLength() ||
- i == scell_content_text_length.getLength())
- {
- if (i == scell_content_text_length.getLength())
- aValidationType = sheet::ValidationType_TEXT_LEN;
- sLocalCondition = sLocalCondition.copy(1);
- switch (sLocalCondition[0])
- {
- case '<' :
- {
- if (sLocalCondition[1] == '=')
- {
- aOperator = sheet::ConditionOperator_LESS_EQUAL;
- sLocalCondition = sLocalCondition.copy(2);
- }
- else
- {
- aOperator = sheet::ConditionOperator_LESS;
- sLocalCondition = sLocalCondition.copy(1);
- }
- }
- break;
- case '>' :
- {
- if (sLocalCondition[1] == '=')
- {
- aOperator = sheet::ConditionOperator_GREATER_EQUAL;
- sLocalCondition = sLocalCondition.copy(2);
- }
- else
- {
- aOperator = sheet::ConditionOperator_GREATER;
- sLocalCondition = sLocalCondition.copy(1);
- }
- }
- break;
- case '=' :
- {
- aOperator = sheet::ConditionOperator_EQUAL;
- sLocalCondition = sLocalCondition.copy(1);
- }
- break;
- case '!' :
- {
- aOperator = sheet::ConditionOperator_NOT_EQUAL;
- sLocalCondition = sLocalCondition.copy(1);
- }
- break;
- }
- sFormula1 = sLocalCondition;
- }
+ case XML_COND_CELLCONTENT: // condition is 'and cell-content()<operator><expression>'
+ case XML_COND_ISBETWEEN: // condition is 'and cell-content-is-between(<expression1>,<expression2>)'
+ case XML_COND_ISNOTBETWEEN: // condition is 'and cell-content-is-not-between(<expression1>,<expression2>)'
+ rValidation.aOperator = aParseResult.meOperator;
+ break;
+ default:; // unacceptable or unknown condition
}
}
}
- }
- // a validation type (date, integer) without a condition isn't possible
- if ( aOperator == sheet::ConditionOperator_NONE )
- aValidationType = sheet::ValidationType_ANY;
+ // a validation type (date, integer) without a condition isn't possible
+ if( rValidation.aOperator == sheet::ConditionOperator_NONE )
+ rValidation.aValidationType = sheet::ValidationType_ANY;
+
+ // parse the formulas
+ if( rValidation.aValidationType != sheet::ValidationType_ANY )
+ {
+ SetFormula( rValidation.sFormula1, rValidation.sFormulaNmsp1, rValidation.eGrammar1,
+ aParseResult.maOperand1, aConditionNmsp, eGrammar, bHasNmsp );
+ SetFormula( rValidation.sFormula2, rValidation.sFormulaNmsp2, rValidation.eGrammar2,
+ aParseResult.maOperand2, aConditionNmsp, eGrammar, bHasNmsp );
+ }
+ }
}
void ScXMLContentValidationContext::EndElement()
@@ -546,15 +457,15 @@ void ScXMLContentValidationContext::EndElement()
}
ScMyImportValidation aValidation;
- aValidation.eGrammar = eGrammar;
+ aValidation.eGrammar1 = aValidation.eGrammar2 = GetScImport().GetDocument()->GetStorageGrammar();
aValidation.sName = sName;
aValidation.sBaseCellAddress = sBaseCellAddress;
aValidation.sImputTitle = sHelpTitle;
aValidation.sImputMessage = sHelpMessage;
aValidation.sErrorTitle = sErrorTitle;
aValidation.sErrorMessage = sErrorMessage;
- GetCondition(sCondition, aValidation.sFormula1, aValidation.sFormula2, aValidation.aValidationType, aValidation.aOperator);
- GetAlertStyle(sErrorMessageType, aValidation.aAlertStyle);
+ GetCondition( aValidation );
+ aValidation.aAlertStyle = GetAlertStyle();
aValidation.bShowErrorMessage = bDisplayError;
aValidation.bShowImputMessage = bDisplayHelp;
aValidation.bIgnoreBlanks = bAllowEmptyCell;
diff --git a/sc/source/filter/xml/xmldrani.cxx b/sc/source/filter/xml/xmldrani.cxx
index e2aa6fcd7504..55a1859211d0 100644
--- a/sc/source/filter/xml/xmldrani.cxx
+++ b/sc/source/filter/xml/xmldrani.cxx
@@ -381,7 +381,8 @@ void ScXMLDatabaseRangeContext::EndElement()
pDBData->SetSortParam(aSortParam);
}
- uno::Reference <sheet::XSheetFilterDescriptor> xSheetFilterDescriptor(xDatabaseRange->getFilterDescriptor());
+ uno::Reference< sheet::XSheetFilterDescriptor2 > xSheetFilterDescriptor(
+ xDatabaseRange->getFilterDescriptor(), uno::UNO_QUERY );
if (xSheetFilterDescriptor.is())
{
uno::Reference <beans::XPropertySet> xFilterPropertySet (xSheetFilterDescriptor, uno::UNO_QUERY);
@@ -396,7 +397,7 @@ void ScXMLDatabaseRangeContext::EndElement()
xFilterPropertySet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_USEREGEX)), uno::makeAny(bFilterUseRegularExpressions));
xFilterPropertySet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_OUTPOS)), uno::makeAny(aFilterOutputPosition));
}
- xSheetFilterDescriptor->setFilterFields(aFilterFields);
+ xSheetFilterDescriptor->setFilterFields2(aFilterFields);
if (bFilterConditionSourceRange)
{
ScRange aAdvSource;
diff --git a/sc/source/filter/xml/xmldrani.hxx b/sc/source/filter/xml/xmldrani.hxx
index 36c668b0f77f..be55e5b143cc 100644
--- a/sc/source/filter/xml/xmldrani.hxx
+++ b/sc/source/filter/xml/xmldrani.hxx
@@ -36,7 +36,7 @@
#include <com/sun/star/sheet/SubTotalColumn.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
-#include <com/sun/star/sheet/TableFilterField.hpp>
+#include <com/sun/star/sheet/TableFilterField2.hpp>
#include <com/sun/star/table/CellAddress.hpp>
#include <com/sun/star/table/CellRangeAddress.hpp>
#include <com/sun/star/table/TableOrientation.hpp>
@@ -79,7 +79,7 @@ class ScXMLDatabaseRangeContext : public SvXMLImportContext
rtl::OUString sDatabaseName;
rtl::OUString sSourceObject;
com::sun::star::uno::Sequence <com::sun::star::beans::PropertyValue> aSortSequence;
- com::sun::star::uno::Sequence <com::sun::star::sheet::TableFilterField> aFilterFields;
+ com::sun::star::uno::Sequence <com::sun::star::sheet::TableFilterField2> aFilterFields;
std::vector < ScSubTotalRule > aSubTotalRules;
com::sun::star::table::CellAddress aFilterOutputPosition;
com::sun::star::table::CellRangeAddress aFilterConditionSourceRangeAddress;
@@ -146,7 +146,7 @@ public:
void SetFilterIsCaseSensitive(const sal_Bool bTemp) { bFilterIsCaseSensitive = bTemp; }
void SetFilterSkipDuplicates(const sal_Bool bTemp) { bFilterSkipDuplicates = bTemp; }
void SetFilterUseRegularExpressions(const sal_Bool bTemp) { bFilterUseRegularExpressions = bTemp; }
- void SetFilterFields(const com::sun::star::uno::Sequence <com::sun::star::sheet::TableFilterField>& aTemp) { aFilterFields = aTemp; }
+ void SetFilterFields(const com::sun::star::uno::Sequence <com::sun::star::sheet::TableFilterField2>& aTemp) { aFilterFields = aTemp; }
void SetFilterOutputPosition(const com::sun::star::table::CellAddress& aTemp) { aFilterOutputPosition = aTemp; }
void SetFilterConditionSourceRangeAddress(const com::sun::star::table::CellRangeAddress& aTemp) { aFilterConditionSourceRangeAddress = aTemp;
bFilterConditionSourceRange = sal_True; }
diff --git a/sc/source/filter/xml/xmlfilti.cxx b/sc/source/filter/xml/xmlfilti.cxx
index 59d53542535a..87bdc748906c 100644
--- a/sc/source/filter/xml/xmlfilti.cxx
+++ b/sc/source/filter/xml/xmlfilti.cxx
@@ -335,48 +335,60 @@ SvXMLImportContext *ScXMLConditionContext::CreateChildContext( USHORT nPrefix,
return new SvXMLImportContext( GetImport(), nPrefix, rLName );
}
-void ScXMLConditionContext::getOperatorXML(const rtl::OUString sTempOperator, sheet::FilterOperator& aFilterOperator, sal_Bool& bUseRegularExpressions) const
+void ScXMLConditionContext::getOperatorXML(const rtl::OUString sTempOperator, sal_Int32& aFilterOperator, sal_Bool& bUseRegularExpressions) const
{
bUseRegularExpressions = sal_False;
if (IsXMLToken(sTempOperator, XML_MATCH))
{
bUseRegularExpressions = sal_True;
- aFilterOperator = sheet::FilterOperator_EQUAL;
+ aFilterOperator = sheet::FilterOperator2::EQUAL;
}
else if (IsXMLToken(sTempOperator, XML_NOMATCH))
{
bUseRegularExpressions = sal_True;
- aFilterOperator = sheet::FilterOperator_NOT_EQUAL;
+ aFilterOperator = sheet::FilterOperator2::NOT_EQUAL;
}
else if (sTempOperator.compareToAscii("=") == 0)
- aFilterOperator = sheet::FilterOperator_EQUAL;
+ aFilterOperator = sheet::FilterOperator2::EQUAL;
else if (sTempOperator.compareToAscii("!=") == 0)
- aFilterOperator = sheet::FilterOperator_NOT_EQUAL;
+ aFilterOperator = sheet::FilterOperator2::NOT_EQUAL;
else if (IsXMLToken(sTempOperator, XML_BOTTOM_PERCENT))
- aFilterOperator = sheet::FilterOperator_BOTTOM_PERCENT;
+ aFilterOperator = sheet::FilterOperator2::BOTTOM_PERCENT;
else if (IsXMLToken(sTempOperator, XML_BOTTOM_VALUES))
- aFilterOperator = sheet::FilterOperator_BOTTOM_VALUES;
+ aFilterOperator = sheet::FilterOperator2::BOTTOM_VALUES;
else if (IsXMLToken(sTempOperator, XML_EMPTY))
- aFilterOperator = sheet::FilterOperator_EMPTY;
+ aFilterOperator = sheet::FilterOperator2::EMPTY;
else if (sTempOperator.compareToAscii(">") == 0)
- aFilterOperator = sheet::FilterOperator_GREATER;
+ aFilterOperator = sheet::FilterOperator2::GREATER;
else if (sTempOperator.compareToAscii(">=") == 0)
- aFilterOperator = sheet::FilterOperator_GREATER_EQUAL;
+ aFilterOperator = sheet::FilterOperator2::GREATER_EQUAL;
else if (sTempOperator.compareToAscii("<") == 0)
- aFilterOperator = sheet::FilterOperator_LESS;
+ aFilterOperator = sheet::FilterOperator2::LESS;
else if (sTempOperator.compareToAscii("<=") == 0)
- aFilterOperator = sheet::FilterOperator_LESS_EQUAL;
+ aFilterOperator = sheet::FilterOperator2::LESS_EQUAL;
else if (IsXMLToken(sTempOperator, XML_NOEMPTY))
- aFilterOperator = sheet::FilterOperator_NOT_EMPTY;
+ aFilterOperator = sheet::FilterOperator2::NOT_EMPTY;
else if (IsXMLToken(sTempOperator, XML_TOP_PERCENT))
- aFilterOperator = sheet::FilterOperator_TOP_PERCENT;
+ aFilterOperator = sheet::FilterOperator2::TOP_PERCENT;
else if (IsXMLToken(sTempOperator, XML_TOP_VALUES))
- aFilterOperator = sheet::FilterOperator_TOP_VALUES;
+ aFilterOperator = sheet::FilterOperator2::TOP_VALUES;
+ else if (IsXMLToken(sTempOperator, XML_CONTAINS))
+ aFilterOperator = sheet::FilterOperator2::CONTAINS;
+ else if (IsXMLToken(sTempOperator, XML_DOES_NOT_CONTAIN))
+ aFilterOperator = sheet::FilterOperator2::DOES_NOT_CONTAIN;
+ else if (IsXMLToken(sTempOperator, XML_BEGINS_WITH))
+ aFilterOperator = sheet::FilterOperator2::BEGINS_WITH;
+ else if (IsXMLToken(sTempOperator, XML_DOES_NOT_BEGIN_WITH))
+ aFilterOperator = sheet::FilterOperator2::DOES_NOT_BEGIN_WITH;
+ else if (IsXMLToken(sTempOperator, XML_ENDS_WITH))
+ aFilterOperator = sheet::FilterOperator2::ENDS_WITH;
+ else if (IsXMLToken(sTempOperator, XML_DOES_NOT_END_WITH))
+ aFilterOperator = sheet::FilterOperator2::DOES_NOT_END_WITH;
}
void ScXMLConditionContext::EndElement()
{
- sheet::TableFilterField aFilterField;
+ sheet::TableFilterField2 aFilterField;
if (pFilterContext->GetConnection())
aFilterField.Connection = sheet::FilterConnection_OR;
else
diff --git a/sc/source/filter/xml/xmlfilti.hxx b/sc/source/filter/xml/xmlfilti.hxx
index f0021e9dda1b..b2b45175c138 100644
--- a/sc/source/filter/xml/xmlfilti.hxx
+++ b/sc/source/filter/xml/xmlfilti.hxx
@@ -36,7 +36,8 @@
#include <com/sun/star/table/CellAddress.hpp>
#include <com/sun/star/table/CellRangeAddress.hpp>
#include <com/sun/star/sheet/FilterOperator.hpp>
-#include <com/sun/star/sheet/TableFilterField.hpp>
+#include <com/sun/star/sheet/FilterOperator2.hpp>
+#include <com/sun/star/sheet/TableFilterField2.hpp>
#include <tools/stack.hxx>
#include "xmldrani.hxx"
@@ -48,7 +49,7 @@ class ScXMLFilterContext : public SvXMLImportContext
{
ScXMLDatabaseRangeContext* pDatabaseRangeContext;
- com::sun::star::uno::Sequence <com::sun::star::sheet::TableFilterField> aFilterFields;
+ com::sun::star::uno::Sequence <com::sun::star::sheet::TableFilterField2> aFilterFields;
com::sun::star::table::CellAddress aOutputPosition;
com::sun::star::table::CellRangeAddress aConditionSourceRangeAddress;
sal_Int16 nUserListIndex;
@@ -89,7 +90,7 @@ public:
aConnectionOrStack.Push(pTemp);}
void CloseConnection() { sal_Bool* pTemp = static_cast <sal_Bool*> (aConnectionOrStack.Pop()); bConnectionOr = *pTemp; bNextConnectionOr = *pTemp; delete pTemp;}
sal_Bool GetConnection() { sal_Bool bTemp = bConnectionOr; bConnectionOr = bNextConnectionOr; return bTemp; }
- void AddFilterField (const com::sun::star::sheet::TableFilterField aFilterField) { aFilterFields.realloc(aFilterFields.getLength() + 1);
+ void AddFilterField(const com::sun::star::sheet::TableFilterField2 aFilterField) { aFilterFields.realloc(aFilterFields.getLength() + 1);
aFilterFields[aFilterFields.getLength() - 1] = aFilterField; }
};
@@ -171,7 +172,7 @@ public:
const ::com::sun::star::uno::Reference<
::com::sun::star::xml::sax::XAttributeList>& xAttrList );
- void getOperatorXML(const rtl::OUString sTempOperator, com::sun::star::sheet::FilterOperator& aFilterOperator, sal_Bool& bUseRegularExpressions) const;
+ void getOperatorXML(const rtl::OUString sTempOperator, sal_Int32& aFilterOperator, sal_Bool& bUseRegularExpressions) const;
virtual void EndElement();
};
diff --git a/sc/source/filter/xml/xmlimprt.cxx b/sc/source/filter/xml/xmlimprt.cxx
index b806ef13561d..200e33743020 100644
--- a/sc/source/filter/xml/xmlimprt.cxx
+++ b/sc/source/filter/xml/xmlimprt.cxx
@@ -74,6 +74,7 @@
#include "unonames.hxx"
#include "rangeutl.hxx"
#include "postit.hxx"
+#include "formulaparserpool.hxx"
#include <comphelper/extract.hxx>
#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
@@ -2887,36 +2888,62 @@ sal_Int32 ScXMLImport::GetVisibleSheet()
return 0;
}
-// static
-bool ScXMLImport::IsAcceptedFormulaNamespace( const sal_uInt16 nFormulaPrefix,
- const rtl::OUString & rValue, formula::FormulaGrammar::Grammar& rGrammar,
- const formula::FormulaGrammar::Grammar eStorageGrammar )
+void ScXMLImport::ExtractFormulaNamespaceGrammar(
+ OUString& rFormula, OUString& rFormulaNmsp, FormulaGrammar::Grammar& reGrammar,
+ const OUString& rAttrValue, bool bRestrictToExternalNmsp ) const
{
- switch (nFormulaPrefix)
+ // parse the attribute value, extract namespace ID, literal namespace, and formula string
+ rFormulaNmsp = OUString();
+ sal_uInt16 nNsId = GetNamespaceMap()._GetKeyByAttrName( rAttrValue, 0, &rFormula, &rFormulaNmsp, sal_False );
+
+ // check if we have an ODF formula namespace
+ if( !bRestrictToExternalNmsp ) switch( nNsId )
{
- case XML_NAMESPACE_OF:
- rGrammar = formula::FormulaGrammar::GRAM_ODFF;
- return true;
- case XML_NAMESPACE_OOOC:
- rGrammar = formula::FormulaGrammar::GRAM_PODF;
- return true;
+ case XML_NAMESPACE_OOOC:
+ rFormulaNmsp = OUString(); // remove namespace string for built-in grammar
+ reGrammar = FormulaGrammar::GRAM_PODF;
+ return;
+ case XML_NAMESPACE_OF:
+ rFormulaNmsp = OUString(); // remove namespace string for built-in grammar
+ reGrammar = FormulaGrammar::GRAM_ODFF;
+ return;
}
- // An invalid namespace can occur from a colon in the formula text if no
- // namespace tag was added. First character in string has to be '=' in that
- // case.
- bool bNoNamespace = (nFormulaPrefix == XML_NAMESPACE_NONE ||
- (nFormulaPrefix == XML_NAMESPACE_UNKNOWN && rValue.toChar() == '='));
-
- if (bNoNamespace && eStorageGrammar == formula::FormulaGrammar::GRAM_PODF)
- // There may be documents in the wild that stored no namespace in ODF 1.x
- rGrammar = formula::FormulaGrammar::GRAM_PODF;
- else if (bNoNamespace)
- // The default for ODF 1.2 and later without namespace is 'of:' ODFF
- rGrammar = formula::FormulaGrammar::GRAM_ODFF;
- else
- // Whatever ...
- rGrammar = eStorageGrammar;
+ /* Find default grammar for formulas without namespace. There may be
+ documents in the wild that stored no namespace in ODF 1.0/1.1. Use
+ GRAM_PODF then (old style ODF 1.0/1.1 formulas). The default for ODF
+ 1.2 and later without namespace is GRAM_ODFF (OpenFormula). */
+ FormulaGrammar::Grammar eDefaultGrammar =
+ (GetDocument()->GetStorageGrammar() == FormulaGrammar::GRAM_PODF) ?
+ FormulaGrammar::GRAM_PODF : FormulaGrammar::GRAM_ODFF;
+
+ /* Check if we have no namespace at all. The value XML_NAMESPACE_NONE
+ indicates that there is no colon. If the first character of the
+ attribute value is the equality sign, the value XML_NAMESPACE_UNKNOWN
+ indicates that there is a colon somewhere in the formula string. */
+ if( (nNsId == XML_NAMESPACE_NONE) || ((nNsId == XML_NAMESPACE_UNKNOWN) && (rAttrValue.toChar() == '=')) )
+ {
+ rFormula = rAttrValue; // return entire string as formula
+ reGrammar = eDefaultGrammar;
+ return;
+ }
- return false;
+ /* Check if a namespace URL could be resolved from the attribute value.
+ Use that namespace only, if the Calc document knows an associated
+ external formula parser. This prevents that the range operator in
+ conjunction with defined names is confused as namespaces prefix, e.g.
+ in the expression 'table:A1' where 'table' is a named reference. */
+ if( ((nNsId & XML_NAMESPACE_UNKNOWN_FLAG) != 0) && (rFormulaNmsp.getLength() > 0) &&
+ GetDocument()->GetFormulaParserPool().hasFormulaParser( rFormulaNmsp ) )
+ {
+ reGrammar = FormulaGrammar::GRAM_EXTERNAL;
+ return;
+ }
+
+ /* All attempts failed (e.g. no namespace and no leading equality sign, or
+ an invalid namespace prefix), continue with the entire attribute value. */
+ rFormula = rAttrValue;
+ rFormulaNmsp = OUString(); // remove any namespace string
+ reGrammar = eDefaultGrammar;
}
+
diff --git a/sc/source/filter/xml/xmlimprt.hxx b/sc/source/filter/xml/xmlimprt.hxx
index 108138c9a016..f96d34c40ca5 100644
--- a/sc/source/filter/xml/xmlimprt.hxx
+++ b/sc/source/filter/xml/xmlimprt.hxx
@@ -598,6 +598,7 @@ struct ScMyNamedExpression
{
rtl::OUString sName;
rtl::OUString sContent;
+ rtl::OUString sContentNmsp;
rtl::OUString sBaseCellAddress;
rtl::OUString sRangeType;
formula::FormulaGrammar::Grammar eGrammar;
@@ -624,11 +625,14 @@ struct ScMyImportValidation
rtl::OUString sErrorMessage;
rtl::OUString sFormula1;
rtl::OUString sFormula2;
+ rtl::OUString sFormulaNmsp1;
+ rtl::OUString sFormulaNmsp2;
rtl::OUString sBaseCellAddress; // #b4974740# string is used directly
com::sun::star::sheet::ValidationAlertStyle aAlertStyle;
com::sun::star::sheet::ValidationType aValidationType;
com::sun::star::sheet::ConditionOperator aOperator;
- formula::FormulaGrammar::Grammar eGrammar;
+ formula::FormulaGrammar::Grammar eGrammar1;
+ formula::FormulaGrammar::Grammar eGrammar2;
sal_Int16 nShowList;
sal_Bool bShowErrorMessage;
sal_Bool bShowImputMessage;
@@ -984,46 +988,42 @@ public:
void AddDefaultNote( const com::sun::star::table::CellAddress& aCell );
sal_Int32 GetVisibleSheet();
-
- /** If namespace prefix is an accepted formula namespace.
-
- For an accepted namespace (return <TRUE/>), the formula text is the
- part without the namespace tag (aFormula of the _GetKeyByAttrName()
- example below).
-
- For an invalid namespace (not defined in the file,
- XML_NAMESPACE_UNKNOWN; may also be the result of no namespace with
- colon in the formula text, in that case text has to start with
- character '=') or no namespace tag (XML_NAMESPACE_NONE) the full text
- (rValue) should be used (return <FALSE/>).
-
- @param nFormulaPrefix
- The result of a _GetKeyByAttrName( rValue, aFormula, sal_False)
- call.
-
- @param rValue
- The attribute's string (formula text) including the namespace, if
- any.
-
- @param rGrammar
- Return value set toformula::FormulaGrammar::GRAM_ODFF orformula::FormulaGrammar::GRAM_PODF or
- eStorageGrammar, according to the namespace or absence thereof
- encountered.
-
- @param eStorageGrammar
- Default storage grammar of the document,formula::FormulaGrammar::GRAM_ODFF for
- ODF 1.2 and later documents,formula::FormulaGrammar::GRAM_PODF for ODF 1.x
- documents.
-
- @return
- <TRUE/> if an accepted namespace (XML_NAMESPACE_OF or
- XML_NAMESPACE_OOOC), else <FALSE/>.
+ /** Extracts the formula string, the formula grammar namespace URL, and a
+ grammar enum value from the passed formula attribute value.
+
+ @param rFormula
+ (out-parameter) Returns the plain formula string with the leading
+ equality sign if existing.
+
+ @param rFormulaNmsp
+ (out-parameter) Returns the URL of the formula grammar namespace if
+ the attribute value contains the prefix of an unknown namespace.
+
+ @param reGrammar
+ (out-parameter) Returns the exact formula grammar if the formula
+ is in a supported ODF format (e.g. FormulaGrammar::GRAM_PODF for
+ ODF 1.0/1.1 formulas, or FormulaGrammar::GRAM_ODFF for ODF 1.2
+ formulas a.k.a. OpenFormula). Returns the default storage grammar,
+ if the attribute value does not contain a namespace prefix. Returns
+ the special value FormulaGrammar::GRAM_EXTERNAL, if an unknown
+ namespace could be extracted from the formula which will be
+ contained in the parameter rFormulaNmsp then.
+
+ @param rAttrValue
+ The value of the processed formula attribute.
+
+ @param bRestrictToExternalNmsp
+ If set to TRUE, only namespaces of external formula grammars will
+ be recognized. Internal namespace prefixes (e.g. 'oooc:' or 'of:'
+ will be considered to be part of the formula, e.g. an expression
+ with range operator.
*/
-
- static bool IsAcceptedFormulaNamespace( const sal_uInt16 nFormulaPrefix,
- const rtl::OUString & rValue, formula::FormulaGrammar::Grammar& rGrammar,
- const formula::FormulaGrammar::Grammar eStorageGrammar );
-
+ void ExtractFormulaNamespaceGrammar(
+ ::rtl::OUString& rFormula,
+ ::rtl::OUString& rFormulaNmsp,
+ ::formula::FormulaGrammar::Grammar& reGrammar,
+ const ::rtl::OUString& rAttrValue,
+ bool bRestrictToExternalNmsp = false ) const;
};
#endif
diff --git a/sc/source/filter/xml/xmlnexpi.cxx b/sc/source/filter/xml/xmlnexpi.cxx
index 3f822d5274c6..9a2a49f0b021 100644
--- a/sc/source/filter/xml/xmlnexpi.cxx
+++ b/sc/source/filter/xml/xmlnexpi.cxx
@@ -196,8 +196,6 @@ ScXMLNamedExpressionContext::ScXMLNamedExpressionContext( ScXMLImport& rImport,
SvXMLImportContext( rImport, nPrfx, rLName )
{
ScMyNamedExpression* pNamedExpression(new ScMyNamedExpression);
- const formula::FormulaGrammar::Grammar eStorageGrammar = pNamedExpression->eGrammar =
- GetScImport().GetDocument()->GetStorageGrammar();
sal_Int16 nAttrCount(xAttrList.is() ? xAttrList->getLength() : 0);
const SvXMLTokenMap& rAttrTokenMap(GetScImport().GetNamedExpressionAttrTokenMap());
for( sal_Int16 i=0; i < nAttrCount; ++i )
@@ -217,16 +215,9 @@ ScXMLNamedExpressionContext::ScXMLNamedExpressionContext( ScXMLImport& rImport,
break;
case XML_TOK_NAMED_EXPRESSION_ATTR_EXPRESSION :
{
- rtl::OUString sFormula;
- sal_uInt16 nFormulaPrefix = GetImport().GetNamespaceMap().
- _GetKeyByAttrName( sValue, &sFormula, sal_False );
-
- if (ScXMLImport::IsAcceptedFormulaNamespace( nFormulaPrefix,
- sValue, pNamedExpression->eGrammar,
- eStorageGrammar))
- pNamedExpression->sContent = sFormula;
- else
- pNamedExpression->sContent = sValue;
+ GetScImport().ExtractFormulaNamespaceGrammar(
+ pNamedExpression->sContent, pNamedExpression->sContentNmsp,
+ pNamedExpression->eGrammar, sValue );
}
break;
case XML_TOK_NAMED_EXPRESSION_ATTR_BASE_CELL_ADDRESS :
diff --git a/sc/source/filter/xml/xmlstyli.cxx b/sc/source/filter/xml/xmlstyli.cxx
index 3b411df8db08..79ba79f0e689 100644
--- a/sc/source/filter/xml/xmlstyli.cxx
+++ b/sc/source/filter/xml/xmlstyli.cxx
@@ -73,6 +73,7 @@ using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::container;
using namespace xmloff::token;
//using namespace ::com::sun::star::text;
+using namespace ::formula;
ScXMLCellImportPropertyMapper::ScXMLCellImportPropertyMapper(
const UniReference< XMLPropertySetMapper >& rMapper,
@@ -285,10 +286,7 @@ public:
ScXMLMapContext::ScXMLMapContext(SvXMLImport& rImport, sal_uInt16 nPrfx,
const OUString& rLName, const uno::Reference< xml::sax::XAttributeList > & xAttrList )
- : SvXMLImportContext( rImport, nPrfx, rLName ),
- sApplyStyle(),
- sCondition(),
- sBaseCell()
+ : SvXMLImportContext( rImport, nPrfx, rLName )
{
sal_Int16 nAttrCount(xAttrList.is() ? xAttrList->getLength() : 0);
for( sal_Int16 i=0; i < nAttrCount; ++i )
@@ -315,200 +313,118 @@ ScXMLMapContext::~ScXMLMapContext()
{
}
-void XMLTableStyleContext::SetOperator(com::sun::star::uno::Sequence<beans::PropertyValue>& aProps,
- const com::sun::star::sheet::ConditionOperator aOp) const
-{
- sal_Int32 nLength(aProps.getLength());
- aProps.realloc(nLength + 1);
- aProps[nLength].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_OPERATOR));
- aProps[nLength].Value <<= aOp;
-}
+namespace {
-void XMLTableStyleContext::SetBaseCellAddress(com::sun::star::uno::Sequence<beans::PropertyValue>& aProps,
- const rtl::OUString& sBaseCell) const
+template< typename Type >
+inline void lclAppendProperty( uno::Sequence< beans::PropertyValue >& rProps, const OUString& rPropName, const Type& rValue )
{
- sal_Int32 nLength(aProps.getLength());
- aProps.realloc(nLength + 1);
-
- // #b4974740# source position must be set as string, because it may
- // refer to a sheet that hasn't been loaded yet.
-
- aProps[nLength].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_SOURCESTR));
- aProps[nLength].Value <<= sBaseCell;
+ sal_Int32 nLength = rProps.getLength();
+ rProps.realloc( nLength + 1 );
+ rProps[ nLength ].Name = rPropName;
+ rProps[ nLength ].Value <<= rValue;
}
-void XMLTableStyleContext::SetStyle(com::sun::star::uno::Sequence<beans::PropertyValue>& aProps,
- const rtl::OUString& sApplyStyle) const
+} // namespace
+
+void XMLTableStyleContext::SetOperator( uno::Sequence< beans::PropertyValue >& rProps, sheet::ConditionOperator eOp ) const
{
- sal_Int32 nLength(aProps.getLength());
- aProps.realloc(nLength + 1);
- aProps[nLength].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_STYLENAME));
- aProps[nLength].Value <<= sApplyStyle;
+ lclAppendProperty( rProps, OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_OPERATOR ) ), eOp );
}
-void XMLTableStyleContext::SetFormula1(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aProps,
- const rtl::OUString& sFormula, bool bPreParse) const
+void XMLTableStyleContext::SetBaseCellAddress( uno::Sequence< beans::PropertyValue >& rProps, const OUString& rBaseCell ) const
{
- sal_Int32 nLength(aProps.getLength());
- aProps.realloc(nLength + 1);
- aProps[nLength].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_FORMULA1));
- if (bPreParse)
- {
- rtl::OUString sRealFormula(sFormula);
- ScXMLConverter::ParseFormula(sRealFormula);
- aProps[nLength].Value <<= sRealFormula;
- }
- else
- aProps[nLength].Value <<= sFormula;
+ /* #b4974740# Source position must be set as string, because it may refer
+ to a sheet that hasn't been loaded yet. */
+ lclAppendProperty( rProps, OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_SOURCESTR ) ), rBaseCell );
}
-void XMLTableStyleContext::SetFormula2(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aProps,
- const rtl::OUString& sFormula) const
+void XMLTableStyleContext::SetStyle( uno::Sequence<beans::PropertyValue>& rProps, const OUString& rApplyStyle ) const
{
- sal_Int32 nLength(aProps.getLength());
- aProps.realloc(nLength + 1);
- aProps[nLength].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_FORMULA2));
- rtl::OUString sRealFormula(sFormula);
- ScXMLConverter::ParseFormula(sRealFormula);
- aProps[nLength].Value <<= sRealFormula;
+ lclAppendProperty( rProps, OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_STYLENAME ) ), rApplyStyle );
}
-void XMLTableStyleContext::SetFormulas(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aProps,
- const rtl::OUString& sFormulas) const
+void XMLTableStyleContext::SetFormula( uno::Sequence< beans::PropertyValue >& rProps,
+ sal_Int32 nFormulaIdx, const OUString& rFormula, const OUString& rFormulaNmsp,
+ FormulaGrammar::Grammar eGrammar, bool bHasNmsp ) const
{
- sal_Int32 i(0);
- sal_Bool bString(sal_False);
- sal_Int32 nBrakes(0);
- while ((sFormulas[i] != ',' || nBrakes > 0 || bString) && i < sFormulas.getLength())
+ OUString aFormula, aFormulaNmsp;
+ FormulaGrammar::Grammar eNewGrammar = FormulaGrammar::GRAM_UNSPECIFIED;
+ if( bHasNmsp )
{
- if (sFormulas[i] == '(')
- ++nBrakes;
- if (sFormulas[i] == ')')
- --nBrakes;
- if (sFormulas[i] == '"')
- bString = !bString;
- ++i;
+ // the entire attribute contains a namespace: internal namespace not allowed
+ aFormula = rFormula;
+ aFormulaNmsp = rFormulaNmsp;
+ eNewGrammar = eGrammar;
}
- if (sFormulas[i] == ',')
+ else
{
- rtl::OUString sFormula1(sFormulas.copy(0, i));
- rtl::OUString sFormula2(sFormulas.copy(i + 1));
- SetFormula1(aProps, sFormula1);
- SetFormula2(aProps, sFormula2);
+ // the attribute does not contain a namespace: try to find a namespace of an external grammar
+ GetScImport().ExtractFormulaNamespaceGrammar( aFormula, aFormulaNmsp, eNewGrammar, rFormula, true );
+ if( eNewGrammar != FormulaGrammar::GRAM_EXTERNAL )
+ eNewGrammar = eGrammar;
}
-}
-void XMLTableStyleContext::SetGrammar(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aProps,
- const formula::FormulaGrammar::Grammar eGrammar) const
-{
- sal_Int32 nLength(aProps.getLength());
- aProps.realloc(nLength + 1);
- aProps[nLength].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_GRAMMAR));
- aProps[nLength].Value <<= static_cast<sal_Int32>(eGrammar);
+ // add formula, formula namespace, and grammar with appropriate property names
+ sal_Int32 nGrammar = static_cast< sal_Int32 >( eNewGrammar );
+ switch( nFormulaIdx )
+ {
+ case 1:
+ lclAppendProperty( rProps, OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_FORMULA1 ) ), aFormula );
+ lclAppendProperty( rProps, OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_FORMULANMSP1 ) ), aFormulaNmsp );
+ lclAppendProperty( rProps, OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_GRAMMAR1 ) ), nGrammar );
+ break;
+ case 2:
+ lclAppendProperty( rProps, OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_FORMULA2 ) ), aFormula );
+ lclAppendProperty( rProps, OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_FORMULANMSP2 ) ), aFormulaNmsp );
+ lclAppendProperty( rProps, OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_GRAMMAR2 ) ), nGrammar );
+ break;
+ default:
+ OSL_ENSURE( false, "XMLTableStyleContext::SetFormula - invalid formula index" );
+ }
}
void XMLTableStyleContext::GetConditionalFormat(uno::Any& aAny,
const rtl::OUString& sTempCondition,
const rtl::OUString& sApplyStyle, const rtl::OUString& sBaseCell) const
{
- rtl::OUString sCondition(sTempCondition);
- if (sCondition.getLength() && sApplyStyle.getLength())
+ if (sTempCondition.getLength() && sApplyStyle.getLength())
{
uno::Reference<sheet::XSheetConditionalEntries> xConditionalEntries(aAny, uno::UNO_QUERY);
if (xConditionalEntries.is())
{
- const formula::FormulaGrammar::Grammar eStorageGrammar = GetScImport().GetDocument()->GetStorageGrammar();
- formula::FormulaGrammar::Grammar eGrammar = eStorageGrammar;
- // ToDo: erase all blanks in the condition, but not in formulas or strings
- rtl::OUString scell_content(RTL_CONSTASCII_USTRINGPARAM("cell_content"));
- rtl::OUString scell_content_is_between(RTL_CONSTASCII_USTRINGPARAM("cell_content_is_between"));
- rtl::OUString scell_content_is_not_between(RTL_CONSTASCII_USTRINGPARAM("cell_content_is_not_between"));
- rtl::OUString sis_true_formula(RTL_CONSTASCII_USTRINGPARAM("is_true_formula"));
uno::Sequence<beans::PropertyValue> aProps;
if (sBaseCell.getLength())
SetBaseCellAddress(aProps, sBaseCell);
SetStyle(aProps, sApplyStyle);
- sal_Int32 i = 0;
- while (sCondition[i] != '(' && i < sCondition.getLength())
- ++i;
- if (sCondition[i] == '(')
+
+ // extract leading namespace from condition string
+ OUString aCondition, aConditionNmsp;
+ FormulaGrammar::Grammar eGrammar = FormulaGrammar::GRAM_UNSPECIFIED;
+ GetScImport().ExtractFormulaNamespaceGrammar( aCondition, aConditionNmsp, eGrammar, sTempCondition );
+ bool bHasNmsp = aCondition.getLength() < sTempCondition.getLength();
+
+ // parse a condition from the attribute string
+ ScXMLConditionParseResult aParseResult;
+ ScXMLConditionHelper::parseCondition( aParseResult, aCondition, 0 );
+
+ /* Check the result. A valid value in aParseResult.meToken implies
+ that the other members of aParseResult are filled with valid
+ data for that token. */
+ switch( aParseResult.meToken )
{
- sCondition = sCondition.copy(i + 1);
- if (i == scell_content.getLength())
- {
- sCondition = sCondition.copy(1);
- switch (sCondition[0])
- {
- case '<' :
- {
- if (sCondition[1] == '=')
- {
- SetOperator(aProps, sheet::ConditionOperator_LESS_EQUAL);
- sCondition = sCondition.copy(2);
- }
- else
- {
- SetOperator(aProps, sheet::ConditionOperator_LESS);
- sCondition = sCondition.copy(1);
- }
- }
- break;
- case '>' :
- {
- if (sCondition[1] == '=')
- {
- SetOperator(aProps, sheet::ConditionOperator_GREATER_EQUAL);
- sCondition = sCondition.copy(2);
- }
- else
- {
- SetOperator(aProps, sheet::ConditionOperator_GREATER);
- sCondition = sCondition.copy(1);
- }
- }
- break;
- case '=' :
- {
- SetOperator(aProps, sheet::ConditionOperator_EQUAL);
- sCondition = sCondition.copy(1);
- }
- break;
- case '!' :
- {
- SetOperator(aProps, sheet::ConditionOperator_NOT_EQUAL);
- sCondition = sCondition.copy(1);
- }
- break;
- }
- SetFormula1(aProps, sCondition);
- }
- else if (i == scell_content_is_between.getLength())
- {
- SetOperator(aProps, sheet::ConditionOperator_BETWEEN);
- sCondition = sCondition.copy(0, sCondition.getLength() - 1);
- SetFormulas(aProps, sCondition);
- }
- else if (i == scell_content_is_not_between.getLength())
- {
- SetOperator(aProps, sheet::ConditionOperator_NOT_BETWEEN);
- sCondition = sCondition.copy(0, sCondition.getLength() - 1);
- SetFormulas(aProps, sCondition);
- }
- else if (i == sis_true_formula.getLength())
- {
- SetOperator(aProps, sheet::ConditionOperator_FORMULA);
- sCondition = sCondition.copy(0, sCondition.getLength() - 1);
- rtl::OUString sFormula;
- sal_uInt16 nFormulaPrefix = GetImport().GetNamespaceMap().
- _GetKeyByAttrName( sCondition, &sFormula, sal_False );
- if (ScXMLImport::IsAcceptedFormulaNamespace( nFormulaPrefix,
- sCondition, eGrammar, eStorageGrammar))
- sCondition = sFormula;
- SetFormula1(aProps, sCondition, false);
- }
+ case XML_COND_CELLCONTENT: // condition is 'cell-content()<operator><expression>'
+ case XML_COND_ISTRUEFORMULA: // condition is 'is-true-formula(<expression>)'
+ case XML_COND_ISBETWEEN: // condition is 'cell-content-is-between(<expression1>,<expression2>)'
+ case XML_COND_ISNOTBETWEEN: // condition is 'cell-content-is-not-between(<expression1>,<expression2>)'
+ SetOperator( aProps, aParseResult.meOperator );
+ SetFormula( aProps, 1, aParseResult.maOperand1, aConditionNmsp, eGrammar, bHasNmsp );
+ SetFormula( aProps, 2, aParseResult.maOperand2, aConditionNmsp, eGrammar, bHasNmsp );
+ break;
+
+ default:; // unacceptable or unknown condition
}
- SetGrammar( aProps, eGrammar);
- xConditionalEntries->addNew(aProps);
+
+ xConditionalEntries->addNew( aProps );
aAny <<= xConditionalEntries;
}
}
diff --git a/sc/source/filter/xml/xmlstyli.hxx b/sc/source/filter/xml/xmlstyli.hxx
index 4d80f5710ac9..272ec0151134 100644
--- a/sc/source/filter/xml/xmlstyli.hxx
+++ b/sc/source/filter/xml/xmlstyli.hxx
@@ -107,20 +107,22 @@ class XMLTableStyleContext : public XMLPropStyleContext
const ScXMLImport& GetScImport() const { return (const ScXMLImport&)GetImport(); }
ScXMLImport& GetScImport() { return (ScXMLImport&)GetImport(); }
- void SetOperator(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aProps,
- const com::sun::star::sheet::ConditionOperator aOp) const;
- void SetBaseCellAddress(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aProps,
- const rtl::OUString& sBaseCell) const;
- void SetStyle(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aProps,
- const rtl::OUString& sApplyStyle) const;
- void SetFormula1(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aProps,
- const rtl::OUString& sFormula, bool bPreParse = true) const;
- void SetFormula2(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aProps,
- const rtl::OUString& sFormula) const;
- void SetFormulas(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aProps,
- const rtl::OUString& sFormulas) const;
- void SetGrammar(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aProps,
- const formula::FormulaGrammar::Grammar eGrammar) const;
+ void SetOperator(
+ ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rProps,
+ ::com::sun::star::sheet::ConditionOperator eOp ) const;
+
+ void SetBaseCellAddress(
+ ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rProps,
+ const ::rtl::OUString& rBaseCell ) const;
+
+ void SetStyle(
+ ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rProps,
+ const ::rtl::OUString& rApplyStyle ) const;
+
+ void SetFormula(
+ ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rProps,
+ sal_Int32 nFormulaIdx, const ::rtl::OUString& rFormula,
+ const ::rtl::OUString& rFormulaNmsp, ::formula::FormulaGrammar::Grammar eGrammar, bool bHasNmsp ) const;
void GetConditionalFormat(
::com::sun::star::uno::Any& aAny, const rtl::OUString& sCondition,
diff --git a/sc/source/filter/xml/xmlsubti.cxx b/sc/source/filter/xml/xmlsubti.cxx
index 0eb74bf11218..231839b9f946 100644
--- a/sc/source/filter/xml/xmlsubti.cxx
+++ b/sc/source/filter/xml/xmlsubti.cxx
@@ -641,7 +641,7 @@ void ScMyTables::DeleteTable()
ScMyMatrixRangeList::iterator aEndItr = aMatrixRangeList.end();
while(aItr != aEndItr)
{
- SetMatrix(aItr->aRange, aItr->sFormula, aItr->eGrammar);
+ SetMatrix(aItr->aRange, aItr->sFormula, aItr->sFormulaNmsp, aItr->eGrammar);
++aItr;
}
aMatrixRangeList.clear();
@@ -755,7 +755,9 @@ void ScMyTables::AddShape(uno::Reference <drawing::XShape>& rShape,
aResizeShapes.AddShape(rShape, pRangeList, rStartAddress, rEndAddress, nEndX, nEndY);
}
-void ScMyTables::AddMatrixRange(sal_Int32 nStartColumn, sal_Int32 nStartRow, sal_Int32 nEndColumn, sal_Int32 nEndRow, const rtl::OUString& rFormula, const formula::FormulaGrammar::Grammar eGrammar)
+void ScMyTables::AddMatrixRange(
+ sal_Int32 nStartColumn, sal_Int32 nStartRow, sal_Int32 nEndColumn, sal_Int32 nEndRow,
+ const rtl::OUString& rFormula, const rtl::OUString& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar)
{
DBG_ASSERT(nEndRow >= nStartRow, "wrong row order");
DBG_ASSERT(nEndColumn >= nStartColumn, "wrong column order");
@@ -765,7 +767,7 @@ void ScMyTables::AddMatrixRange(sal_Int32 nStartColumn, sal_Int32 nStartRow, sal
aRange.EndColumn = nEndColumn;
aRange.EndRow = nEndRow;
aRange.Sheet = sal::static_int_cast<sal_Int16>(nCurrentSheet);
- ScMatrixRange aMRange(aRange, rFormula, eGrammar);
+ ScMatrixRange aMRange(aRange, rFormula, rFormulaNmsp, eGrammar);
aMatrixRangeList.push_back(aMRange);
}
@@ -786,7 +788,7 @@ sal_Bool ScMyTables::IsPartOfMatrix(sal_Int32 nColumn, sal_Int32 nRow)
}
else if ((nRow > aItr->aRange.EndRow) && (nColumn > aItr->aRange.EndColumn))
{
- SetMatrix(aItr->aRange, aItr->sFormula, aItr->eGrammar);
+ SetMatrix(aItr->aRange, aItr->sFormula, aItr->sFormulaNmsp, aItr->eGrammar);
aItr = aMatrixRangeList.erase(aItr);
}
else if (nColumn < aItr->aRange.StartColumn)
@@ -803,7 +805,8 @@ sal_Bool ScMyTables::IsPartOfMatrix(sal_Int32 nColumn, sal_Int32 nRow)
return bResult;
}
-void ScMyTables::SetMatrix(const table::CellRangeAddress& rRange, const rtl::OUString& rFormula, const formula::FormulaGrammar::Grammar eGrammar)
+void ScMyTables::SetMatrix(const table::CellRangeAddress& rRange, const rtl::OUString& rFormula,
+ const rtl::OUString& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar)
{
uno::Reference <table::XCellRange> xMatrixCellRange(
GetCurrentXCellRange()->getCellRangeByPosition(rRange.StartColumn, rRange.StartRow,
@@ -817,7 +820,7 @@ void ScMyTables::SetMatrix(const table::CellRangeAddress& rRange, const rtl::OUS
static_cast<ScCellRangeObj*>(ScCellRangesBase::getImplementation(
xMatrixCellRange));
if (pCellRangeObj)
- pCellRangeObj->SetArrayFormulaWithGrammar( rFormula, eGrammar);
+ pCellRangeObj->SetArrayFormulaWithGrammar( rFormula, rFormulaNmsp, eGrammar);
}
}
}
diff --git a/sc/source/filter/xml/xmlsubti.hxx b/sc/source/filter/xml/xmlsubti.hxx
index 84a07ff90449..c5a16e2c3ef4 100644
--- a/sc/source/filter/xml/xmlsubti.hxx
+++ b/sc/source/filter/xml/xmlsubti.hxx
@@ -97,10 +97,12 @@ public:
struct ScMatrixRange
{
rtl::OUString sFormula;
+ rtl::OUString sFormulaNmsp;
formula::FormulaGrammar::Grammar eGrammar;
com::sun::star::table::CellRangeAddress aRange;
- ScMatrixRange(const com::sun::star::table::CellRangeAddress& rRange, const rtl::OUString& rFormula, const formula::FormulaGrammar::Grammar eGrammarP) :
+ ScMatrixRange(const com::sun::star::table::CellRangeAddress& rRange, const rtl::OUString& rFormula, const rtl::OUString& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammarP) :
sFormula(rFormula),
+ sFormulaNmsp(rFormulaNmsp),
eGrammar(eGrammarP),
aRange(rRange)
{
@@ -181,11 +183,13 @@ public:
sal_Int32 nEndColumn,
sal_Int32 nEndRow,
const rtl::OUString& rFormula,
+ const rtl::OUString& rFormulaNmsp,
const formula::FormulaGrammar::Grammar );
sal_Bool IsPartOfMatrix(sal_Int32 nColumn, sal_Int32 nRow);
void SetMatrix( const com::sun::star::table::CellRangeAddress& rRange,
const rtl::OUString& rFormula,
+ const rtl::OUString& rFormulaNmsp,
const formula::FormulaGrammar::Grammar );
};
diff --git a/sc/source/ui/app/inputhdl.cxx b/sc/source/ui/app/inputhdl.cxx
index 6914d5abfaf3..46987c88636f 100644
--- a/sc/source/ui/app/inputhdl.cxx
+++ b/sc/source/ui/app/inputhdl.cxx
@@ -741,7 +741,7 @@ void ScInputHandler::ShowTipCursor()
nLeftParentPos = lcl_MatchParenthesis( aSelText, aSelText.Len()-1 );
if( nLeftParentPos != STRING_NOTFOUND )
{
- sal_Unicode c = aSelText.GetChar( nLeftParentPos-1 );
+ sal_Unicode c = ( nLeftParentPos > 0 ) ? aSelText.GetChar( nLeftParentPos-1 ) : 0;
if( !((c >= 'A' && c<= 'Z') || (c>= 'a' && c<= 'z' )) )
continue;
nNextFStart = aHelper.GetFunctionStart( aSelText, nLeftParentPos, TRUE);
@@ -983,7 +983,8 @@ void ScInputHandler::UseFormulaData()
if( nLeftParentPos == STRING_NOTFOUND )
break;
- sal_Unicode c = aFormula.GetChar( nLeftParentPos-1 );
+ // #160063# nLeftParentPos can be 0 if a parenthesis is inserted before the formula
+ sal_Unicode c = ( nLeftParentPos > 0 ) ? aFormula.GetChar( nLeftParentPos-1 ) : 0;
if( !((c >= 'A' && c<= 'Z') || (c>= 'a' && c<= 'z') ) )
continue;
nNextFStart = aHelper.GetFunctionStart( aFormula, nLeftParentPos, TRUE);
diff --git a/sc/source/ui/docshell/docfunc.cxx b/sc/source/ui/docshell/docfunc.cxx
index 9820e4a5515e..ebb080a89cfa 100644
--- a/sc/source/ui/docshell/docfunc.cxx
+++ b/sc/source/ui/docshell/docfunc.cxx
@@ -960,16 +960,18 @@ BOOL ScDocFunc::PutData( const ScAddress& rPos, ScEditEngineDefaulter& rEngine,
}
-ScTokenArray* lcl_ScDocFunc_CreateTokenArrayXML( const String& rText )
+ScTokenArray* lcl_ScDocFunc_CreateTokenArrayXML( const String& rText, const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar )
{
ScTokenArray* pCode = new ScTokenArray;
pCode->AddString( rText );
+ if( (eGrammar == formula::FormulaGrammar::GRAM_EXTERNAL) && (rFormulaNmsp.Len() > 0) )
+ pCode->AddString( rFormulaNmsp );
return pCode;
}
ScBaseCell* ScDocFunc::InterpretEnglishString( const ScAddress& rPos,
- const String& rText, const formula::FormulaGrammar::Grammar eGrammar )
+ const String& rText, const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar )
{
ScDocument* pDoc = rDocShell.GetDocument();
ScBaseCell* pNewCell = NULL;
@@ -979,7 +981,7 @@ ScBaseCell* ScDocFunc::InterpretEnglishString( const ScAddress& rPos,
ScTokenArray* pCode;
if ( pDoc->IsImportingXML() )
{ // temporary formula string as string tokens
- pCode = lcl_ScDocFunc_CreateTokenArrayXML( rText );
+ pCode = lcl_ScDocFunc_CreateTokenArrayXML( rText, rFormulaNmsp, eGrammar );
pDoc->IncXMLImportedFormulaCount( rText.Len() );
}
else
@@ -1016,8 +1018,8 @@ ScBaseCell* ScDocFunc::InterpretEnglishString( const ScAddress& rPos,
BOOL ScDocFunc::SetCellText( const ScAddress& rPos, const String& rText,
- BOOL bInterpret, BOOL bEnglish, BOOL bApi,
- const formula::FormulaGrammar::Grammar eGrammar )
+ BOOL bInterpret, BOOL bEnglish, BOOL bApi,
+ const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar )
{
// SetCellText ruft PutCell oder SetNormalString
@@ -1030,12 +1032,15 @@ BOOL ScDocFunc::SetCellText( const ScAddress& rPos, const String& rText,
// code moved to own method InterpretEnglishString because it is also used in
// ScCellRangeObj::setFormulaArray
- pNewCell = InterpretEnglishString( rPos, rText, eGrammar );
+ pNewCell = InterpretEnglishString( rPos, rText, rFormulaNmsp, eGrammar );
}
// sonst Null behalten -> SetString mit lokalen Formeln/Zahlformat
}
else if ( rText.Len() )
+ {
+ OSL_ENSURE( rFormulaNmsp.Len() == 0, "ScDocFunc::SetCellText - formula namespace, but do not interpret?" );
pNewCell = ScBaseCell::CreateTextCell( rText, pDoc ); // immer Text
+ }
if (pNewCell)
return PutCell( rPos, pNewCell, bApi );
@@ -1446,8 +1451,8 @@ BOOL ScDocFunc::InsertCells( const ScRange& rRange, const ScMarkData* pTabMark,
pDoc->ExtendMerge( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i );
pDoc->ExtendOverlapped( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i );
- if(( eCmd == INS_CELLSDOWN && ( nMergeStartX != nMergeTestStartX || nMergeEndX != nMergeTestEndX ))||
- eCmd == INS_CELLSRIGHT && ( nMergeStartY != nMergeTestStartY || nMergeEndY != nMergeTestEndY ) )
+ if(( eCmd == INS_CELLSDOWN && ( nMergeStartX != nMergeTestStartX || nMergeEndX != nMergeTestEndX )) ||
+ (eCmd == INS_CELLSRIGHT && ( nMergeStartY != nMergeTestStartY || nMergeEndY != nMergeTestEndY )) )
{
if (!bApi)
rDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0);
@@ -2073,6 +2078,12 @@ BOOL ScDocFunc::DeleteCells( const ScRange& rRange, const ScMarkData* pTabMark,
nUndoPos ++;
}
}
+
+ if( !bDeletingMerge )
+ {
+ rDocShell.GetUndoManager()->LeaveListAction();
+ }
+
rDocShell.GetUndoManager()->AddUndoAction( new ScUndoDeleteCells(
&rDocShell, ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ),nUndoPos, pTabs, pScenarios,
eCmd, pUndoDoc, pUndoData ) );
@@ -3510,9 +3521,8 @@ BOOL ScDocFunc::AutoFormat( const ScRange& rRange, const ScMarkData* pTabMark,
//------------------------------------------------------------------------
BOOL ScDocFunc::EnterMatrix( const ScRange& rRange, const ScMarkData* pTabMark,
- const ScTokenArray* pTokenArray,
- const String& rString, BOOL bApi, BOOL bEnglish,
- const formula::FormulaGrammar::Grammar eGrammar )
+ const ScTokenArray* pTokenArray, const String& rString, BOOL bApi, BOOL bEnglish,
+ const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar )
{
ScDocShellModificator aModificator( rDocShell );
@@ -3559,7 +3569,7 @@ BOOL ScDocFunc::EnterMatrix( const ScRange& rRange, const ScMarkData* pTabMark,
}
else if ( pDoc->IsImportingXML() )
{
- ScTokenArray* pCode = lcl_ScDocFunc_CreateTokenArrayXML( rString );
+ ScTokenArray* pCode = lcl_ScDocFunc_CreateTokenArrayXML( rString, rFormulaNmsp, eGrammar );
pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow,
aMark, EMPTY_STRING, pCode, eGrammar);
delete pCode;
@@ -4489,11 +4499,11 @@ BOOL ScDocFunc::ResizeMatrix( const ScRange& rOldRange, const ScAddress& rNewEnd
if ( DeleteContents( aMark, IDF_CONTENTS, TRUE, bApi ) )
{
// GRAM_PODF_A1 for API compatibility.
- bRet = EnterMatrix( aNewRange, &aMark, NULL, aFormula, bApi, FALSE,formula::FormulaGrammar::GRAM_PODF_A1 );
+ bRet = EnterMatrix( aNewRange, &aMark, NULL, aFormula, bApi, FALSE, EMPTY_STRING, formula::FormulaGrammar::GRAM_PODF_A1 );
if (!bRet)
{
// versuchen, alten Zustand wiederherzustellen
- EnterMatrix( rOldRange, &aMark, NULL, aFormula, bApi, FALSE,formula::FormulaGrammar::GRAM_PODF_A1 );
+ EnterMatrix( rOldRange, &aMark, NULL, aFormula, bApi, FALSE, EMPTY_STRING, formula::FormulaGrammar::GRAM_PODF_A1 );
}
}
diff --git a/sc/source/ui/docshell/docsh3.cxx b/sc/source/ui/docshell/docsh3.cxx
index fcdfa8612a02..fcbfb648ae14 100644
--- a/sc/source/ui/docshell/docsh3.cxx
+++ b/sc/source/ui/docshell/docsh3.cxx
@@ -1051,8 +1051,8 @@ void ScDocShell::MergeDocument( ScDocument& rOtherDoc, bool bShared, bool bCheck
aValue.Erase( 0, 1 );
aValue.Erase( aValue.Len()-1, 1 );
GetDocFunc().EnterMatrix( aSourceRange,
- NULL, NULL, aValue, FALSE, FALSE,
- formula::FormulaGrammar::GRAM_DEFAULT );
+ NULL, NULL, aValue, FALSE, FALSE,
+ EMPTY_STRING, formula::FormulaGrammar::GRAM_DEFAULT );
}
break;
case MM_REFERENCE : // do nothing
diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx
index ea9f02dcaa4b..9cc0b274028e 100644
--- a/sc/source/ui/docshell/externalrefmgr.cxx
+++ b/sc/source/ui/docshell/externalrefmgr.cxx
@@ -143,7 +143,8 @@ private:
// ============================================================================
ScExternalRefCache::Table::Table()
- : mbReferenced( true) // Prevent accidental data loss due to lack of knowledge.
+ : meReferenced( REFERENCED_MARKED )
+ // Prevent accidental data loss due to lack of knowledge.
{
}
@@ -151,14 +152,25 @@ ScExternalRefCache::Table::~Table()
{
}
+void ScExternalRefCache::Table::setReferencedFlag( ScExternalRefCache::Table::ReferencedFlag eFlag )
+{
+ meReferenced = eFlag;
+}
+
void ScExternalRefCache::Table::setReferenced( bool bReferenced )
{
- mbReferenced = bReferenced;
+ if (meReferenced != REFERENCED_PERMANENT)
+ meReferenced = (bReferenced ? REFERENCED_MARKED : UNREFERENCED);
+}
+
+ScExternalRefCache::Table::ReferencedFlag ScExternalRefCache::Table::getReferencedFlag() const
+{
+ return meReferenced;
}
bool ScExternalRefCache::Table::isReferenced() const
{
- return mbReferenced;
+ return meReferenced != UNREFERENCED;
}
void ScExternalRefCache::Table::setCell(SCCOL nCol, SCROW nRow, TokenRef pToken, sal_uInt32 nFmtIndex)
@@ -737,21 +749,57 @@ bool ScExternalRefCache::setCacheDocReferenced( sal_uInt16 nFileId )
return areAllCacheTablesReferenced();
}
-bool ScExternalRefCache::setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName )
+bool ScExternalRefCache::setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName, size_t nSheets, bool bPermanent )
{
- size_t nIndex = 0;
- TableTypeRef pTab = getCacheTable( nFileId, rTabName, false, &nIndex);
- if (pTab.get())
+ DocItem* pDoc = getDocItem(nFileId);
+ if (pDoc)
{
- if (!pTab->isReferenced())
+ size_t nIndex = 0;
+ String aTabNameUpper = ScGlobal::pCharClass->upper( rTabName);
+ if (lcl_getTableDataIndex( pDoc->maTableNameIndex, aTabNameUpper, nIndex))
{
- pTab->setReferenced( true);
- addCacheTableToReferenced( nFileId, nIndex);
+ size_t nStop = ::std::min( nIndex + nSheets, pDoc->maTables.size());
+ for (size_t i = nIndex; i < nStop; ++i)
+ {
+ TableTypeRef pTab = pDoc->maTables[i];
+ if (pTab.get())
+ {
+ Table::ReferencedFlag eNewFlag = (bPermanent ?
+ Table::REFERENCED_PERMANENT :
+ Table::REFERENCED_MARKED);
+ Table::ReferencedFlag eOldFlag = pTab->getReferencedFlag();
+ if (eOldFlag != Table::REFERENCED_PERMANENT && eNewFlag != eOldFlag)
+ {
+ pTab->setReferencedFlag( eNewFlag);
+ addCacheTableToReferenced( nFileId, i);
+ }
+ }
+ }
}
}
return areAllCacheTablesReferenced();
}
+void ScExternalRefCache::setCacheTableReferencedPermanently( sal_uInt16 nFileId, const String& rTabName, size_t nSheets )
+{
+ DocItem* pDoc = getDocItem(nFileId);
+ if (pDoc)
+ {
+ size_t nIndex = 0;
+ String aTabNameUpper = ScGlobal::pCharClass->upper( rTabName);
+ if (lcl_getTableDataIndex( pDoc->maTableNameIndex, aTabNameUpper, nIndex))
+ {
+ size_t nStop = ::std::min( nIndex + nSheets, pDoc->maTables.size());
+ for (size_t i = nIndex; i < nStop; ++i)
+ {
+ TableTypeRef pTab = pDoc->maTables[i];
+ if (pTab.get())
+ pTab->setReferencedFlag( Table::REFERENCED_PERMANENT);
+ }
+ }
+ }
+}
+
void ScExternalRefCache::setAllCacheTableReferencedStati( bool bReferenced )
{
if (bReferenced)
@@ -791,9 +839,17 @@ void ScExternalRefCache::setAllCacheTableReferencedStati( bool bReferenced )
TableTypeRef & xTab = rDocItem.maTables[i];
if (xTab.get())
{
- xTab->setReferenced( false);
- rDocReferenced.maTables[i] = false;
- rDocReferenced.mbAllTablesReferenced = false;
+ if (xTab->getReferencedFlag() == Table::REFERENCED_PERMANENT)
+ addCacheTableToReferenced( nFileId, i);
+ else
+ {
+ xTab->setReferencedFlag( Table::UNREFERENCED);
+ rDocReferenced.maTables[i] = false;
+ rDocReferenced.mbAllTablesReferenced = false;
+ // An addCacheTableToReferenced() actually may have
+ // resulted in mbAllReferenced been set. Clear it.
+ maReferenced.mbAllReferenced = false;
+ }
}
}
}
@@ -1481,9 +1537,19 @@ bool ScExternalRefManager::setCacheDocReferenced( sal_uInt16 nFileId )
return maRefCache.setCacheDocReferenced( nFileId);
}
-bool ScExternalRefManager::setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName )
+bool ScExternalRefManager::setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName, size_t nSheets )
{
- return maRefCache.setCacheTableReferenced( nFileId, rTabName);
+ return maRefCache.setCacheTableReferenced( nFileId, rTabName, nSheets, false);
+}
+
+void ScExternalRefManager::setCacheTableReferencedPermanently( sal_uInt16 nFileId, const String& rTabName, size_t nSheets )
+{
+ if (isInReferenceMarking())
+ // Do all maintenance work.
+ maRefCache.setCacheTableReferenced( nFileId, rTabName, nSheets, true);
+ else
+ // Set only the permanent flag.
+ maRefCache.setCacheTableReferencedPermanently( nFileId, rTabName, nSheets);
}
void ScExternalRefManager::setAllCacheTableReferencedStati( bool bReferenced )
diff --git a/sc/source/ui/formdlg/formula.cxx b/sc/source/ui/formdlg/formula.cxx
index 4544c1ca0792..8d631a9f0609 100644
--- a/sc/source/ui/formdlg/formula.cxx
+++ b/sc/source/ui/formdlg/formula.cxx
@@ -126,7 +126,6 @@ ScFormulaDlg::ScFormulaDlg( SfxBindings* pB, SfxChildWindow* pCW,
m_xParser.set(ScServiceProvider::MakeInstance(SC_SERVICE_FORMULAPARS,(ScDocShell*)pDoc->GetDocumentShell()),uno::UNO_QUERY);
uno::Reference< beans::XPropertySet> xSet(m_xParser,uno::UNO_QUERY);
xSet->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_COMPILEFAP)),uno::makeAny(sal_True));
- xSet->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_REFERENCEPOS)),uno::makeAny(table::CellAddress(aCursorPos.Tab(),aCursorPos.Col(),aCursorPos.Row())));
m_xOpCodeMapper.set(ScServiceProvider::MakeInstance(SC_SERVICE_OPCODEMAPPER,(ScDocShell*)pDoc->GetDocumentShell()),uno::UNO_QUERY);
@@ -657,6 +656,12 @@ uno::Reference< sheet::XFormulaOpCodeMapper> ScFormulaDlg::getFormulaOpCodeMappe
{
return m_xOpCodeMapper;
}
+
+table::CellAddress ScFormulaDlg::getReferencePosition() const
+{
+ return table::CellAddress(aCursorPos.Tab(),aCursorPos.Col(),aCursorPos.Row());
+}
+
::std::auto_ptr<formula::FormulaTokenArray> ScFormulaDlg::convertToTokenArray(const uno::Sequence< sheet::FormulaToken >& _aTokenList)
{
::std::auto_ptr<formula::FormulaTokenArray> pArray(new ScTokenArray());
diff --git a/sc/source/ui/inc/docfunc.hxx b/sc/source/ui/inc/docfunc.hxx
index 2457dc0611b4..21e295a58fa4 100644
--- a/sc/source/ui/inc/docfunc.hxx
+++ b/sc/source/ui/inc/docfunc.hxx
@@ -89,11 +89,12 @@ public:
BOOL bInterpret, BOOL bApi );
BOOL SetCellText( const ScAddress& rPos, const String& rText,
BOOL bInterpret, BOOL bEnglish, BOOL bApi,
+ const String& rFormulaNmsp,
const formula::FormulaGrammar::Grammar eGrammar );
// creates a new cell for use with PutCell
ScBaseCell* InterpretEnglishString( const ScAddress& rPos, const String& rText,
- const formula::FormulaGrammar::Grammar eGrammar );
+ const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar );
bool ShowNote( const ScAddress& rPos, bool bShow = true );
inline bool HideNote( const ScAddress& rPos ) { return ShowNote( rPos, false ); }
@@ -147,6 +148,7 @@ public:
BOOL EnterMatrix( const ScRange& rRange, const ScMarkData* pTabMark,
const ScTokenArray* pTokenArray,
const String& rString, BOOL bApi, BOOL bEnglish,
+ const String& rFormulaNmsp,
const formula::FormulaGrammar::Grammar );
BOOL TabOp( const ScRange& rRange, const ScMarkData* pTabMark,
diff --git a/sc/source/ui/inc/formula.hxx b/sc/source/ui/inc/formula.hxx
index a40a6092fe26..b25811eb9220 100644
--- a/sc/source/ui/inc/formula.hxx
+++ b/sc/source/ui/inc/formula.hxx
@@ -105,6 +105,7 @@ public:
virtual ::std::auto_ptr<formula::FormulaTokenArray> convertToTokenArray(const ::com::sun::star::uno::Sequence< ::com::sun::star::sheet::FormulaToken >& _aTokenList);
virtual ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XFormulaParser> getFormulaParser() const;
virtual ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XFormulaOpCodeMapper> getFormulaOpCodeMapper() const;
+ virtual ::com::sun::star::table::CellAddress getReferencePosition() const;
virtual BOOL Close();
diff --git a/sc/source/ui/inc/undoblk.hxx b/sc/source/ui/inc/undoblk.hxx
index d357461d0f5e..281f44f4fe82 100644
--- a/sc/source/ui/inc/undoblk.hxx
+++ b/sc/source/ui/inc/undoblk.hxx
@@ -36,6 +36,7 @@
#include "spellparam.hxx"
class ScDocShell;
+class ScBaseCell;
class ScDocument;
class ScOutlineTable;
class ScRangeName;
@@ -592,6 +593,35 @@ private:
void SetChangeTrack();
};
+class ScUndoRefConversion: public ScSimpleUndo
+{
+public:
+ TYPEINFO();
+ ScUndoRefConversion( ScDocShell* pNewDocShell,
+ const ScRange& aMarkRange, const ScMarkData& rMark,
+ ScDocument* pNewUndoDoc, ScDocument* pNewRedoDoc, BOOL bNewMulti, USHORT nNewFlag);
+ virtual ~ScUndoRefConversion();
+
+ virtual void Undo();
+ virtual void Redo();
+ virtual void Repeat(SfxRepeatTarget& rTarget);
+ virtual BOOL CanRepeat(SfxRepeatTarget& rTarget) const;
+
+ virtual String GetComment() const;
+
+private:
+ ScMarkData aMarkData;
+ ScDocument* pUndoDoc;
+ ScDocument* pRedoDoc;
+ ScRange aRange;
+ BOOL bMulti;
+ USHORT nFlags;
+ ULONG nStartChangeAction;
+ ULONG nEndChangeAction;
+
+ void DoChange( ScDocument* pRefDoc);
+ void SetChangeTrack();
+};
class ScUndoListNames: public ScBlockUndo
{
diff --git a/sc/source/ui/inc/viewfunc.hxx b/sc/source/ui/inc/viewfunc.hxx
index a5b044ce4f32..228c4b4c1489 100644
--- a/sc/source/ui/inc/viewfunc.hxx
+++ b/sc/source/ui/inc/viewfunc.hxx
@@ -303,6 +303,7 @@ public:
void SetNoteText( const ScAddress& rPos, const String& rNoteText );
void ReplaceNote( const ScAddress& rPos, const String& rNoteText, const String* pAuthor, const String* pDate );
+ void DoRefConversion( BOOL bRecord = TRUE );
//UNUSED2008-05 void DoSpellingChecker( BOOL bRecord = TRUE );
void DoHangulHanjaConversion( BOOL bRecord = TRUE );
diff --git a/sc/source/ui/src/filter.src b/sc/source/ui/src/filter.src
index 73108b984ebe..2e6a1c330671 100644
--- a/sc/source/ui/src/filter.src
+++ b/sc/source/ui/src/filter.src
@@ -34,7 +34,7 @@ ModelessDialog RID_SCDLG_FILTER
HelpId = SID_FILTER ;
Hide = TRUE ;
SVLook = TRUE ;
- Size = MAP_APPFONT ( 251 , 121 ) ;
+ Size = MAP_APPFONT ( 279 , 121 ) ;
Text [ en-US ] = "Standard Filter" ;
Moveable = TRUE ;
Closeable = FALSE ;
@@ -58,7 +58,7 @@ ModelessDialog RID_SCDLG_FILTER
};
FixedText FT_VAL
{
- Pos = MAP_APPFONT ( 173 , 14 ) ;
+ Pos = MAP_APPFONT ( 201 , 14 ) ;
Size = MAP_APPFONT ( 60 , 8 ) ;
Text [ en-US ] = "Value" ;
};
@@ -150,7 +150,7 @@ ModelessDialog RID_SCDLG_FILTER
{
Border = TRUE ;
Pos = MAP_APPFONT ( 122 , 25 ) ;
- Size = MAP_APPFONT ( 47 , 145 ) ;
+ Size = MAP_APPFONT ( 75 , 145 ) ;
TabStop = TRUE ;
DropDown = TRUE ;
stringlist [ en-US ] =
@@ -165,13 +165,19 @@ ModelessDialog RID_SCDLG_FILTER
< "Smallest" ; Default ; > ;
< "Largest %" ; Default ; > ;
< "Smallest %" ; Default ; > ;
+ < "Contains" ; Default ; > ;
+ < "Does not contain" ; Default ; > ;
+ < "Begins with" ; Default ; > ;
+ < "Does not begin with" ; Default ; > ;
+ < "Ends with" ; Default ; > ;
+ < "Does not end with" ; Default ; > ;
};
};
ListBox LB_COND2
{
Border = TRUE ;
Pos = MAP_APPFONT ( 122 , 41 ) ;
- Size = MAP_APPFONT ( 47 , 145 ) ;
+ Size = MAP_APPFONT ( 75 , 145 ) ;
TabStop = TRUE ;
DropDown = TRUE ;
stringlist [ en-US ] =
@@ -186,13 +192,19 @@ ModelessDialog RID_SCDLG_FILTER
< "Smallest" ; Default ; > ;
< "Largest %" ; Default ; > ;
< "Smallest %" ; Default ; > ;
+ < "Contains" ; Default ; > ;
+ < "Does not contain" ; Default ; > ;
+ < "Begins with" ; Default ; > ;
+ < "Does not begin with" ; Default ; > ;
+ < "Ends with" ; Default ; > ;
+ < "Does not end with" ; Default ; > ;
};
};
ListBox LB_COND3
{
Border = TRUE ;
Pos = MAP_APPFONT ( 122 , 57 ) ;
- Size = MAP_APPFONT ( 47 , 145 ) ;
+ Size = MAP_APPFONT ( 75 , 145 ) ;
TabStop = TRUE ;
DropDown = TRUE ;
stringlist [ en-US ] =
@@ -207,13 +219,19 @@ ModelessDialog RID_SCDLG_FILTER
< "Smallest" ; Default ; > ;
< "Largest %" ; Default ; > ;
< "Smallest %" ; Default ; > ;
+ < "Contains" ; Default ; > ;
+ < "Does not contain" ; Default ; > ;
+ < "Begins with" ; Default ; > ;
+ < "Does not begin with" ; Default ; > ;
+ < "Ends with" ; Default ; > ;
+ < "Does not end with" ; Default ; > ;
};
};
ListBox LB_COND4
{
Border = TRUE ;
Pos = MAP_APPFONT ( 122 , 73 ) ;
- Size = MAP_APPFONT ( 47 , 145 ) ;
+ Size = MAP_APPFONT ( 75 , 145 ) ;
TabStop = TRUE ;
DropDown = TRUE ;
stringlist [ en-US ] =
@@ -228,39 +246,45 @@ ModelessDialog RID_SCDLG_FILTER
< "Smallest" ; Default ; > ;
< "Largest %" ; Default ; > ;
< "Smallest %" ; Default ; > ;
+ < "Contains" ; Default ; > ;
+ < "Does not contain" ; Default ; > ;
+ < "Begins with" ; Default ; > ;
+ < "Does not begin with" ; Default ; > ;
+ < "Ends with" ; Default ; > ;
+ < "Does not end with" ; Default ; > ;
};
};
ComboBox ED_VAL1
{
- Pos = MAP_APPFONT ( 173 , 25 ) ;
+ Pos = MAP_APPFONT ( 201 , 25 ) ;
Size = MAP_APPFONT ( 60 , 90 ) ;
TabStop = TRUE ;
DropDown = TRUE ;
};
ComboBox ED_VAL2
{
- Pos = MAP_APPFONT ( 173 , 41 ) ;
+ Pos = MAP_APPFONT ( 201 , 41 ) ;
Size = MAP_APPFONT ( 60 , 90 ) ;
TabStop = TRUE ;
DropDown = TRUE ;
};
ComboBox ED_VAL3
{
- Pos = MAP_APPFONT ( 173 , 57 ) ;
+ Pos = MAP_APPFONT ( 201 , 57 ) ;
Size = MAP_APPFONT ( 60 , 90 ) ;
TabStop = TRUE ;
DropDown = TRUE ;
};
ComboBox ED_VAL4
{
- Pos = MAP_APPFONT ( 173 , 73 ) ;
+ Pos = MAP_APPFONT ( 201 , 73 ) ;
Size = MAP_APPFONT ( 60 , 90 ) ;
TabStop = TRUE ;
DropDown = TRUE ;
};
ScrollBar LB_SCROLL
{
- Pos = MAP_APPFONT ( 237, 25 ) ;
+ Pos = MAP_APPFONT ( 265, 25 ) ;
Size = MAP_APPFONT ( 8 , 60 ) ;
TabStop = TRUE ;
VScroll = TRUE ;
@@ -269,7 +293,7 @@ ModelessDialog RID_SCDLG_FILTER
FixedLine FL_CRITERIA
{
Pos = MAP_APPFONT ( 6 , 3 ) ;
- Size = MAP_APPFONT ( 275 , 8 ) ;
+ Size = MAP_APPFONT ( 267 , 8 ) ;
Text [ en-US ] = "Filter criteria";
};
CheckBox BTN_CASE
@@ -325,7 +349,7 @@ ModelessDialog RID_SCDLG_FILTER
Border = TRUE ;
Hide = TRUE ;
Pos = MAP_APPFONT ( 21 , 170 ) ;
- Size = MAP_APPFONT ( 90 , 90 ) ;
+ Size = MAP_APPFONT ( 110 , 90 ) ;
TabStop = TRUE ;
DropDown = TRUE ;
};
@@ -333,13 +357,13 @@ ModelessDialog RID_SCDLG_FILTER
{
Border = TRUE ;
Hide = TRUE ;
- Pos = MAP_APPFONT ( 115 , 170 ) ;
- Size = MAP_APPFONT ( 104 , 12 ) ;
+ Pos = MAP_APPFONT ( 136 , 170 ) ;
+ Size = MAP_APPFONT ( 110 , 12 ) ;
TabStop = TRUE ;
};
ImageButton RB_COPY_AREA
{
- Pos = MAP_APPFONT ( 221 , 169 ) ;
+ Pos = MAP_APPFONT ( 248 , 169 ) ;
Size = MAP_APPFONT ( 13 , 15 ) ;
TabStop = FALSE ;
QuickHelpText [ en-US ] = "Shrink" ;
@@ -348,7 +372,7 @@ ModelessDialog RID_SCDLG_FILTER
{
Hide = TRUE ;
Pos = MAP_APPFONT ( 6 , 118 ) ;
- Size = MAP_APPFONT ( 239 , 8 ) ;
+ Size = MAP_APPFONT ( 267 , 8 ) ;
};
FixedText FT_DBAREA
{
@@ -367,14 +391,14 @@ ModelessDialog RID_SCDLG_FILTER
};
OKButton BTN_OK
{
- Pos = MAP_APPFONT ( 141 , 101 ) ;
+ Pos = MAP_APPFONT ( 169 , 101 ) ;
Size = MAP_APPFONT ( 50 , 14 ) ;
TabStop = TRUE ;
DefButton = TRUE ;
};
CancelButton BTN_CANCEL
{
- Pos = MAP_APPFONT ( 195 , 101 ) ;
+ Pos = MAP_APPFONT ( 223 , 101 ) ;
Size = MAP_APPFONT ( 50 , 14 ) ;
TabStop = TRUE ;
};
@@ -395,7 +419,7 @@ ModelessDialog RID_SCDLG_FILTER
FixedLine FL_SEPARATOR
{
Pos = MAP_APPFONT ( 0 , 91 ) ;
- Size = MAP_APPFONT ( 251 , 6 ) ;
+ Size = MAP_APPFONT ( 279 , 6 ) ;
};
};
//============================================================================
diff --git a/sc/source/ui/undo/undoblk3.cxx b/sc/source/ui/undo/undoblk3.cxx
index 335bdf6720ee..ea1e303d6ae3 100644
--- a/sc/source/ui/undo/undoblk3.cxx
+++ b/sc/source/ui/undo/undoblk3.cxx
@@ -74,6 +74,7 @@ TYPEINIT1(ScUndoAutoFormat, SfxUndoAction);
TYPEINIT1(ScUndoReplace, SfxUndoAction);
TYPEINIT1(ScUndoTabOp, SfxUndoAction);
TYPEINIT1(ScUndoConversion, SfxUndoAction);
+TYPEINIT1(ScUndoRefConversion, SfxUndoAction);
TYPEINIT1(ScUndoRefreshLink, SfxUndoAction);
TYPEINIT1(ScUndoInsertAreaLink, SfxUndoAction);
TYPEINIT1(ScUndoRemoveAreaLink, SfxUndoAction);
@@ -1527,6 +1528,98 @@ BOOL ScUndoConversion::CanRepeat(SfxRepeatTarget& rTarget) const
//============================================================================
+// class ScUndoRefConversion
+//
+// cell reference conversion
+
+//----------------------------------------------------------------------------
+
+ScUndoRefConversion::ScUndoRefConversion( ScDocShell* pNewDocShell,
+ const ScRange& aMarkRange, const ScMarkData& rMark,
+ ScDocument* pNewUndoDoc, ScDocument* pNewRedoDoc, BOOL bNewMulti, USHORT nNewFlag) :
+ScSimpleUndo( pNewDocShell ),
+aMarkData ( rMark ),
+pUndoDoc ( pNewUndoDoc ),
+pRedoDoc ( pNewRedoDoc ),
+aRange ( aMarkRange ),
+bMulti ( bNewMulti ),
+nFlags ( nNewFlag )
+{
+ SetChangeTrack();
+}
+
+__EXPORT ScUndoRefConversion::~ScUndoRefConversion()
+{
+ delete pUndoDoc;
+ delete pRedoDoc;
+}
+
+String __EXPORT ScUndoRefConversion::GetComment() const
+{
+ return ScGlobal::GetRscString( STR_UNDO_ENTERDATA ); // "Eingabe"
+}
+
+void ScUndoRefConversion::SetChangeTrack()
+{
+ ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack();
+ if ( pChangeTrack && (nFlags & IDF_FORMULA) )
+ pChangeTrack->AppendContentsIfInRefDoc( pUndoDoc,
+ nStartChangeAction, nEndChangeAction );
+ else
+ nStartChangeAction = nEndChangeAction = 0;
+}
+
+void ScUndoRefConversion::DoChange( ScDocument* pRefDoc)
+{
+ ScDocument* pDoc = pDocShell->GetDocument();
+
+ ShowTable(aRange);
+
+ ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
+ if (pViewShell)
+ pViewShell->SetMarkData( aMarkData );
+
+ ScRange aCopyRange = aRange;
+ SCTAB nTabCount = pDoc->GetTableCount();
+ aCopyRange.aStart.SetTab(0);
+ aCopyRange.aEnd.SetTab(nTabCount-1);
+ pRefDoc->CopyToDocument( aCopyRange, nFlags, bMulti, pDoc, &aMarkData );
+ pDocShell->PostPaint( aRange, PAINT_GRID);
+ pDocShell->PostDataChanged();
+ if (pViewShell)
+ pViewShell->CellContentChanged();
+}
+void __EXPORT ScUndoRefConversion::Undo()
+{
+ BeginUndo();
+ if (pUndoDoc)
+ DoChange(pUndoDoc);
+ ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack();
+ if ( pChangeTrack )
+ pChangeTrack->Undo( nStartChangeAction, nEndChangeAction );
+ EndUndo();
+}
+
+void __EXPORT ScUndoRefConversion::Redo()
+{
+ BeginRedo();
+ if (pRedoDoc)
+ DoChange(pRedoDoc);
+ SetChangeTrack();
+ EndRedo();
+}
+
+void __EXPORT ScUndoRefConversion::Repeat(SfxRepeatTarget& rTarget)
+{
+ if (rTarget.ISA(ScTabViewTarget))
+ ((ScTabViewTarget&)rTarget).GetViewShell()->DoRefConversion();
+}
+
+BOOL __EXPORT ScUndoRefConversion::CanRepeat(SfxRepeatTarget& rTarget) const
+{
+ return (rTarget.ISA(ScTabViewTarget));
+}
+//============================================================================
// class ScUndoRefreshLink
//
// Link aktualisieren / aendern
diff --git a/sc/source/ui/unoobj/cellsuno.cxx b/sc/source/ui/unoobj/cellsuno.cxx
index 7bdb9c7718d2..cfe51aed6edc 100644
--- a/sc/source/ui/unoobj/cellsuno.cxx
+++ b/sc/source/ui/unoobj/cellsuno.cxx
@@ -1170,8 +1170,8 @@ BOOL lcl_PutDataArray( ScDocShell& rDocShell, const ScRange& rRange,
}
BOOL lcl_PutFormulaArray( ScDocShell& rDocShell, const ScRange& rRange,
- const uno::Sequence< uno::Sequence<rtl::OUString> >& aData,
- const formula::FormulaGrammar::Grammar eGrammar )
+ const uno::Sequence< uno::Sequence<rtl::OUString> >& aData,
+ const ::rtl::OUString& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar )
{
// BOOL bApi = TRUE;
@@ -1226,7 +1226,7 @@ BOOL lcl_PutFormulaArray( ScDocShell& rDocShell, const ScRange& rRange,
{
String aText(pColArr[nCol]);
ScAddress aPos( nDocCol, nDocRow, nTab );
- ScBaseCell* pNewCell = aFunc.InterpretEnglishString( aPos, aText, eGrammar );
+ ScBaseCell* pNewCell = aFunc.InterpretEnglishString( aPos, aText, rFormulaNmsp, eGrammar );
pDoc->PutCell( aPos, pNewCell );
++nDocCol;
@@ -5052,15 +5052,14 @@ rtl::OUString SAL_CALL ScCellRangeObj::getArrayFormula() throw(uno::RuntimeExcep
return aFormula;
}
-void ScCellRangeObj::SetArrayFormula_Impl( const rtl::OUString& aFormula,
- const formula::FormulaGrammar::Grammar eGrammar ) throw(uno::RuntimeException)
+void ScCellRangeObj::SetArrayFormula_Impl( const rtl::OUString& rFormula,
+ const rtl::OUString& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar ) throw(uno::RuntimeException)
{
ScDocShell* pDocSh = GetDocShell();
if (pDocSh)
{
- String aString(aFormula);
ScDocFunc aFunc(*pDocSh);
- if ( aString.Len() )
+ if ( rFormula.getLength() )
{
if ( ScTableSheetObj::getImplementation( (cppu::OWeakObject*)this ) )
{
@@ -5068,7 +5067,7 @@ void ScCellRangeObj::SetArrayFormula_Impl( const rtl::OUString& aFormula,
throw uno::RuntimeException();
}
- aFunc.EnterMatrix( aRange, NULL, NULL, aString, TRUE, TRUE, eGrammar );
+ aFunc.EnterMatrix( aRange, NULL, NULL, rFormula, TRUE, TRUE, rFormulaNmsp, eGrammar );
}
else
{
@@ -5086,14 +5085,14 @@ void SAL_CALL ScCellRangeObj::setArrayFormula( const rtl::OUString& aFormula )
{
ScUnoGuard aGuard;
// GRAM_PODF_A1 for API compatibility.
- SetArrayFormula_Impl( aFormula,formula::FormulaGrammar::GRAM_PODF_A1);
+ SetArrayFormula_Impl( aFormula, ::rtl::OUString(), formula::FormulaGrammar::GRAM_PODF_A1);
}
-void ScCellRangeObj::SetArrayFormulaWithGrammar( const rtl::OUString& aFormula,
- const formula::FormulaGrammar::Grammar eGrammar ) throw(uno::RuntimeException)
+void ScCellRangeObj::SetArrayFormulaWithGrammar( const rtl::OUString& rFormula,
+ const rtl::OUString& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar ) throw(uno::RuntimeException)
{
ScUnoGuard aGuard;
- SetArrayFormula_Impl( aFormula, eGrammar);
+ SetArrayFormula_Impl( rFormula, rFormulaNmsp, eGrammar);
}
// XArrayFormulaTokens
@@ -5153,7 +5152,7 @@ void SAL_CALL ScCellRangeObj::setArrayTokens( const uno::Sequence<sheet::Formula
// Actually GRAM_PODF_A1 is a don't-care here because of the token
// array being set, it fits with other API compatibility grammars
// though.
- aFunc.EnterMatrix( aRange, NULL, &aTokenArray, EMPTY_STRING, TRUE, TRUE,formula::FormulaGrammar::GRAM_PODF_A1 );
+ aFunc.EnterMatrix( aRange, NULL, &aTokenArray, EMPTY_STRING, TRUE, TRUE, EMPTY_STRING, formula::FormulaGrammar::GRAM_PODF_A1 );
}
else
{
@@ -5269,7 +5268,7 @@ void SAL_CALL ScCellRangeObj::setFormulaArray(
if (pDocSh)
{
// GRAM_PODF_A1 for API compatibility.
- bDone = lcl_PutFormulaArray( *pDocSh, aRange, aArray,formula::FormulaGrammar::GRAM_PODF_A1 );
+ bDone = lcl_PutFormulaArray( *pDocSh, aRange, aArray, EMPTY_STRING, formula::FormulaGrammar::GRAM_PODF_A1 );
}
if (!bDone)
@@ -5633,7 +5632,15 @@ void SAL_CALL ScCellRangeObj::filter( const uno::Reference<sheet::XSheetFilterDe
ScDocShell* pDocSh = GetDocShell();
ScFilterDescriptor aImpl(pDocSh);
- aImpl.setFilterFields( xDescriptor->getFilterFields() );
+ uno::Reference< sheet::XSheetFilterDescriptor2 > xDescriptor2( xDescriptor, uno::UNO_QUERY );
+ if ( xDescriptor2.is() )
+ {
+ aImpl.setFilterFields2( xDescriptor2->getFilterFields2() );
+ }
+ else
+ {
+ aImpl.setFilterFields( xDescriptor->getFilterFields() );
+ }
// Rest sind jetzt Properties...
uno::Reference<beans::XPropertySet> xPropSet( xDescriptor, uno::UNO_QUERY );
@@ -6198,7 +6205,7 @@ void ScCellObj::SetString_Impl(const String& rString, BOOL bInterpret, BOOL bEng
{
ScDocFunc aFunc(*pDocSh);
// GRAM_PODF_A1 for API compatibility.
- (void)aFunc.SetCellText( aCellPos, rString, bInterpret, bEnglish, TRUE,formula::FormulaGrammar::GRAM_PODF_A1 );
+ (void)aFunc.SetCellText( aCellPos, rString, bInterpret, bEnglish, TRUE, EMPTY_STRING, formula::FormulaGrammar::GRAM_PODF_A1 );
}
}
@@ -6246,13 +6253,13 @@ void ScCellObj::SetFormulaResultDouble( double fResult )
}
void ScCellObj::SetFormulaWithGrammar( const ::rtl::OUString& rFormula,
- const formula::FormulaGrammar::Grammar eGrammar )
+ const ::rtl::OUString& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar )
{
ScDocShell* pDocSh = GetDocShell();
if ( pDocSh )
{
ScDocFunc aFunc(*pDocSh);
- aFunc.SetCellText( aCellPos, String( rFormula), TRUE, TRUE, TRUE, eGrammar);
+ aFunc.SetCellText( aCellPos, rFormula, TRUE, TRUE, TRUE, rFormulaNmsp, eGrammar);
}
}
diff --git a/sc/source/ui/unoobj/datauno.cxx b/sc/source/ui/unoobj/datauno.cxx
index 98a8a8551d6c..13f2c26c6e47 100644
--- a/sc/source/ui/unoobj/datauno.cxx
+++ b/sc/source/ui/unoobj/datauno.cxx
@@ -45,6 +45,8 @@
#include <com/sun/star/table/TableOrientation.hpp>
#include <com/sun/star/table/CellRangeAddress.hpp>
#include <com/sun/star/sheet/DataImportMode.hpp>
+#include <com/sun/star/sheet/FilterOperator2.hpp>
+#include <com/sun/star/sheet/TableFilterField2.hpp>
#include "datauno.hxx"
#include "dapiuno.hxx"
@@ -1106,7 +1108,7 @@ void ScFilterDescriptorBase::Notify( SfxBroadcaster&, const SfxHint& rHint )
}
}
-// XSheetFilterDescriptor
+// XSheetFilterDescriptor and XSheetFilterDescriptor2
uno::Sequence<sheet::TableFilterField> SAL_CALL ScFilterDescriptorBase::getFilterFields()
throw(uno::RuntimeException)
@@ -1177,6 +1179,80 @@ uno::Sequence<sheet::TableFilterField> SAL_CALL ScFilterDescriptorBase::getFilte
return aSeq;
}
+uno::Sequence<sheet::TableFilterField2> SAL_CALL ScFilterDescriptorBase::getFilterFields2()
+throw(uno::RuntimeException)
+{
+ ScUnoGuard aGuard;
+ ScQueryParam aParam;
+ GetData(aParam);
+
+ SCSIZE nEntries = aParam.GetEntryCount(); // allozierte Eintraege im Param
+ SCSIZE nCount = 0; // aktive
+ while ( nCount < nEntries &&
+ aParam.GetEntry(nCount).bDoQuery )
+ ++nCount;
+
+ sheet::TableFilterField2 aField;
+ uno::Sequence<sheet::TableFilterField2> aSeq(static_cast<sal_Int32>(nCount));
+ sheet::TableFilterField2* pAry = aSeq.getArray();
+ for (SCSIZE i=0; i<nCount; i++)
+ {
+ const ScQueryEntry& rEntry = aParam.GetEntry(i);
+
+ rtl::OUString aStringValue;
+ if (rEntry.pStr)
+ aStringValue = *rEntry.pStr;
+
+ aField.Connection = (rEntry.eConnect == SC_AND) ? sheet::FilterConnection_AND : sheet::FilterConnection_OR;
+ aField.Field = rEntry.nField;
+ aField.IsNumeric = !rEntry.bQueryByString;
+ aField.StringValue = aStringValue;
+ aField.NumericValue = rEntry.nVal;
+
+ switch (rEntry.eOp) // ScQueryOp
+ {
+ case SC_EQUAL:
+ {
+ aField.Operator = sheet::FilterOperator2::EQUAL;
+ if (!rEntry.bQueryByString && *rEntry.pStr == EMPTY_STRING)
+ {
+ if (rEntry.nVal == SC_EMPTYFIELDS)
+ {
+ aField.Operator = sheet::FilterOperator2::EMPTY;
+ aField.NumericValue = 0;
+ }
+ else if (rEntry.nVal == SC_NONEMPTYFIELDS)
+ {
+ aField.Operator = sheet::FilterOperator2::NOT_EMPTY;
+ aField.NumericValue = 0;
+ }
+ }
+ }
+ break;
+ case SC_LESS: aField.Operator = sheet::FilterOperator2::LESS; break;
+ case SC_GREATER: aField.Operator = sheet::FilterOperator2::GREATER; break;
+ case SC_LESS_EQUAL: aField.Operator = sheet::FilterOperator2::LESS_EQUAL; break;
+ case SC_GREATER_EQUAL: aField.Operator = sheet::FilterOperator2::GREATER_EQUAL; break;
+ case SC_NOT_EQUAL: aField.Operator = sheet::FilterOperator2::NOT_EQUAL; break;
+ case SC_TOPVAL: aField.Operator = sheet::FilterOperator2::TOP_VALUES; break;
+ case SC_BOTVAL: aField.Operator = sheet::FilterOperator2::BOTTOM_VALUES; break;
+ case SC_TOPPERC: aField.Operator = sheet::FilterOperator2::TOP_PERCENT; break;
+ case SC_BOTPERC: aField.Operator = sheet::FilterOperator2::BOTTOM_PERCENT; break;
+ case SC_CONTAINS: aField.Operator = sheet::FilterOperator2::CONTAINS; break;
+ case SC_DOES_NOT_CONTAIN: aField.Operator = sheet::FilterOperator2::DOES_NOT_CONTAIN; break;
+ case SC_BEGINS_WITH: aField.Operator = sheet::FilterOperator2::BEGINS_WITH; break;
+ case SC_DOES_NOT_BEGIN_WITH: aField.Operator = sheet::FilterOperator2::DOES_NOT_BEGIN_WITH; break;
+ case SC_ENDS_WITH: aField.Operator = sheet::FilterOperator2::ENDS_WITH; break;
+ case SC_DOES_NOT_END_WITH: aField.Operator = sheet::FilterOperator2::DOES_NOT_END_WITH; break;
+ default:
+ DBG_ERROR("Falscher Filter-enum");
+ aField.Operator = sheet::FilterOperator2::EMPTY;
+ }
+ pAry[i] = aField;
+ }
+ return aSeq;
+}
+
void SAL_CALL ScFilterDescriptorBase::setFilterFields(
const uno::Sequence<sheet::TableFilterField>& aFilterFields )
throw(uno::RuntimeException)
@@ -1251,6 +1327,86 @@ void SAL_CALL ScFilterDescriptorBase::setFilterFields(
PutData(aParam);
}
+void SAL_CALL ScFilterDescriptorBase::setFilterFields2(
+ const uno::Sequence<sheet::TableFilterField2>& aFilterFields )
+ throw(uno::RuntimeException)
+{
+ ScUnoGuard aGuard;
+ ScQueryParam aParam;
+ GetData(aParam);
+
+ SCSIZE nCount = static_cast<SCSIZE>(aFilterFields.getLength());
+ DBG_ASSERT( nCount <= MAXQUERY, "setFilterFields: zu viele" );
+
+ aParam.Resize( nCount );
+
+ const sheet::TableFilterField2* pAry = aFilterFields.getConstArray();
+ SCSIZE i;
+ for (i=0; i<nCount; i++)
+ {
+ ScQueryEntry& rEntry = aParam.GetEntry(i);
+ if (!rEntry.pStr)
+ rEntry.pStr = new String; // sollte nicht sein (soll immer initialisiert sein)
+
+ rEntry.bDoQuery = TRUE;
+ rEntry.eConnect = (pAry[i].Connection == sheet::FilterConnection_AND) ? SC_AND : SC_OR;
+ rEntry.nField = pAry[i].Field;
+ rEntry.bQueryByString = !pAry[i].IsNumeric;
+ *rEntry.pStr = String( pAry[i].StringValue );
+ rEntry.nVal = pAry[i].NumericValue;
+
+ if (!rEntry.bQueryByString && pDocSh)
+ {
+ pDocSh->GetDocument()->GetFormatTable()->GetInputLineString(rEntry.nVal, 0, *rEntry.pStr);
+ }
+
+ switch (pAry[i].Operator) // FilterOperator
+ {
+ case sheet::FilterOperator2::EQUAL: rEntry.eOp = SC_EQUAL; break;
+ case sheet::FilterOperator2::LESS: rEntry.eOp = SC_LESS; break;
+ case sheet::FilterOperator2::GREATER: rEntry.eOp = SC_GREATER; break;
+ case sheet::FilterOperator2::LESS_EQUAL: rEntry.eOp = SC_LESS_EQUAL; break;
+ case sheet::FilterOperator2::GREATER_EQUAL: rEntry.eOp = SC_GREATER_EQUAL; break;
+ case sheet::FilterOperator2::NOT_EQUAL: rEntry.eOp = SC_NOT_EQUAL; break;
+ case sheet::FilterOperator2::TOP_VALUES: rEntry.eOp = SC_TOPVAL; break;
+ case sheet::FilterOperator2::BOTTOM_VALUES: rEntry.eOp = SC_BOTVAL; break;
+ case sheet::FilterOperator2::TOP_PERCENT: rEntry.eOp = SC_TOPPERC; break;
+ case sheet::FilterOperator2::BOTTOM_PERCENT: rEntry.eOp = SC_BOTPERC; break;
+ case sheet::FilterOperator2::CONTAINS: rEntry.eOp = SC_CONTAINS; break;
+ case sheet::FilterOperator2::DOES_NOT_CONTAIN: rEntry.eOp = SC_DOES_NOT_CONTAIN; break;
+ case sheet::FilterOperator2::BEGINS_WITH: rEntry.eOp = SC_BEGINS_WITH; break;
+ case sheet::FilterOperator2::DOES_NOT_BEGIN_WITH: rEntry.eOp = SC_DOES_NOT_BEGIN_WITH;break;
+ case sheet::FilterOperator2::ENDS_WITH: rEntry.eOp = SC_ENDS_WITH; break;
+ case sheet::FilterOperator2::DOES_NOT_END_WITH: rEntry.eOp = SC_DOES_NOT_END_WITH; break;
+ case sheet::FilterOperator2::EMPTY:
+ {
+ rEntry.eOp = SC_EQUAL;
+ rEntry.nVal = SC_EMPTYFIELDS;
+ rEntry.bQueryByString = FALSE;
+ *rEntry.pStr = EMPTY_STRING;
+ }
+ break;
+ case sheet::FilterOperator2::NOT_EMPTY:
+ {
+ rEntry.eOp = SC_EQUAL;
+ rEntry.nVal = SC_NONEMPTYFIELDS;
+ rEntry.bQueryByString = FALSE;
+ *rEntry.pStr = EMPTY_STRING;
+ }
+ break;
+ default:
+ DBG_ERROR("Falscher Query-enum");
+ rEntry.eOp = SC_EQUAL;
+ }
+ }
+
+ SCSIZE nParamCount = aParam.GetEntryCount(); // Param wird nicht unter 8 resized
+ for (i=nCount; i<nParamCount; i++)
+ aParam.GetEntry(i).bDoQuery = FALSE; // ueberzaehlige Felder zuruecksetzen
+
+ PutData(aParam);
+}
+
// Rest sind Properties
// XPropertySet
diff --git a/sc/source/ui/unoobj/fmtuno.cxx b/sc/source/ui/unoobj/fmtuno.cxx
index 14fdb958a180..f9407b544f76 100644
--- a/sc/source/ui/unoobj/fmtuno.cxx
+++ b/sc/source/ui/unoobj/fmtuno.cxx
@@ -42,7 +42,6 @@
#include "fmtuno.hxx"
#include "miscuno.hxx"
-#include "conditio.hxx"
#include "validat.hxx"
#include "document.hxx"
#include "unoguard.hxx"
@@ -51,7 +50,8 @@
#include "tokenarray.hxx"
#include "tokenuno.hxx"
-using namespace com::sun::star;
+using namespace ::com::sun::star;
+using namespace ::formula;
//------------------------------------------------------------------------
@@ -130,12 +130,17 @@ ScConditionMode lcl_ConditionOperatorToMode( sheet::ConditionOperator eOper )
//------------------------------------------------------------------------
-//UNUSED2008-05 ScTableConditionalFormat::ScTableConditionalFormat()
-//UNUSED2008-05 {
-//UNUSED2008-05 }
+ScCondFormatEntryItem::ScCondFormatEntryItem() :
+ meGrammar1( FormulaGrammar::GRAM_UNSPECIFIED ),
+ meGrammar2( FormulaGrammar::GRAM_UNSPECIFIED ),
+ meMode( SC_COND_NONE )
+{
+}
+
+//------------------------------------------------------------------------
-ScTableConditionalFormat::ScTableConditionalFormat(ScDocument* pDoc, ULONG nKey,
- const formula::FormulaGrammar::Grammar eGrammar)
+ScTableConditionalFormat::ScTableConditionalFormat(
+ ScDocument* pDoc, ULONG nKey, FormulaGrammar::Grammar eGrammar)
{
// Eintrag aus dem Dokument lesen...
@@ -156,11 +161,11 @@ ScTableConditionalFormat::ScTableConditionalFormat(ScDocument* pDoc, ULONG nKey,
{
ScCondFormatEntryItem aItem;
const ScCondFormatEntry* pFormatEntry = pFormat->GetEntry(i);
- aItem.mnMode = sal::static_int_cast<USHORT>(pFormatEntry->GetOperation());
+ aItem.meMode = pFormatEntry->GetOperation();
aItem.maPos = pFormatEntry->GetValidSrcPos();
aItem.maExpr1 = pFormatEntry->GetExpression(aItem.maPos, 0, 0, eGrammar);
aItem.maExpr2 = pFormatEntry->GetExpression(aItem.maPos, 1, 0, eGrammar);
- aItem.meGrammar = eGrammar;
+ aItem.meGrammar1 = aItem.meGrammar2 = eGrammar;
aItem.maStyle = pFormatEntry->GetStyle();
AddEntry_Impl(aItem);
@@ -170,8 +175,20 @@ ScTableConditionalFormat::ScTableConditionalFormat(ScDocument* pDoc, ULONG nKey,
}
}
+namespace {
+
+FormulaGrammar::Grammar lclResolveGrammar( FormulaGrammar::Grammar eExtGrammar, FormulaGrammar::Grammar eIntGrammar )
+{
+ if( eExtGrammar != FormulaGrammar::GRAM_UNSPECIFIED )
+ return eExtGrammar;
+ OSL_ENSURE( eIntGrammar != FormulaGrammar::GRAM_UNSPECIFIED, "lclResolveGrammar - unspecified grammar, using GRAM_PODF_A1" );
+ return (eIntGrammar == FormulaGrammar::GRAM_UNSPECIFIED) ? FormulaGrammar::GRAM_PODF_A1 : eIntGrammar;
+}
+
+} // namespace
+
void ScTableConditionalFormat::FillFormat( ScConditionalFormat& rFormat,
- ScDocument* pDoc, formula::FormulaGrammar::Grammar eGrammar ) const
+ ScDocument* pDoc, FormulaGrammar::Grammar eGrammar) const
{
// ScConditionalFormat = Core-Struktur, muss leer sein
@@ -185,15 +202,12 @@ void ScTableConditionalFormat::FillFormat( ScConditionalFormat& rFormat,
ScCondFormatEntryItem aData;
pEntry->GetData(aData);
- if (eGrammar == formula::FormulaGrammar::GRAM_UNSPECIFIED)
- eGrammar = aData.meGrammar;
- if (eGrammar == formula::FormulaGrammar::GRAM_UNSPECIFIED)
- {
- DBG_ERRORFILE("FillFormat: unspecified grammar, using GRAM_PODF_A1");
- eGrammar = formula::FormulaGrammar::GRAM_PODF_A1;
- }
- ScCondFormatEntry aCoreEntry( static_cast<ScConditionMode>(aData.mnMode),
- aData.maExpr1, aData.maExpr2, pDoc, aData.maPos, aData.maStyle, eGrammar );
+
+ FormulaGrammar::Grammar eGrammar1 = lclResolveGrammar( eGrammar, aData.meGrammar1 );
+ FormulaGrammar::Grammar eGrammar2 = lclResolveGrammar( eGrammar, aData.meGrammar2 );
+
+ ScCondFormatEntry aCoreEntry( aData.meMode, aData.maExpr1, aData.maExpr2,
+ pDoc, aData.maPos, aData.maStyle, aData.maExprNmsp1, aData.maExprNmsp2, eGrammar1, eGrammar2 );
if ( aData.maPosStr.Len() )
aCoreEntry.SetSrcString( aData.maPosStr );
@@ -248,69 +262,86 @@ void SAL_CALL ScTableConditionalFormat::addNew(
{
ScUnoGuard aGuard;
ScCondFormatEntryItem aEntry;
- aEntry.mnMode = sal::static_int_cast<USHORT>(SC_COND_NONE);
+ aEntry.meMode = SC_COND_NONE;
const beans::PropertyValue* pPropArray = aConditionalEntry.getConstArray();
long nPropCount = aConditionalEntry.getLength();
for (long i = 0; i < nPropCount; i++)
{
const beans::PropertyValue& rProp = pPropArray[i];
- String aPropName(rProp.Name);
- if ( aPropName.EqualsAscii( SC_UNONAME_OPERATOR ) )
+ if ( rProp.Name.equalsAscii( SC_UNONAME_OPERATOR ) )
{
sheet::ConditionOperator eOper = (sheet::ConditionOperator)
ScUnoHelpFunctions::GetEnumFromAny( rProp.Value );
- aEntry.mnMode = sal::static_int_cast<USHORT>(lcl_ConditionOperatorToMode( eOper ));
+ aEntry.meMode = lcl_ConditionOperatorToMode( eOper );
}
- else if ( aPropName.EqualsAscii( SC_UNONAME_FORMULA1 ) )
+ else if ( rProp.Name.equalsAscii( SC_UNONAME_FORMULA1 ) )
{
rtl::OUString aStrVal;
uno::Sequence<sheet::FormulaToken> aTokens;
if ( rProp.Value >>= aStrVal )
- aEntry.maExpr1 = String( aStrVal );
+ aEntry.maExpr1 = aStrVal;
else if ( rProp.Value >>= aTokens )
{
aEntry.maExpr1.Erase();
aEntry.maTokens1 = aTokens;
}
}
- else if ( aPropName.EqualsAscii( SC_UNONAME_FORMULA2 ) )
+ else if ( rProp.Name.equalsAscii( SC_UNONAME_FORMULA2 ) )
{
rtl::OUString aStrVal;
uno::Sequence<sheet::FormulaToken> aTokens;
if ( rProp.Value >>= aStrVal )
- aEntry.maExpr2 = String( aStrVal );
+ aEntry.maExpr2 = aStrVal;
else if ( rProp.Value >>= aTokens )
{
aEntry.maExpr2.Erase();
aEntry.maTokens2 = aTokens;
}
}
- else if ( aPropName.EqualsAscii( SC_UNONAME_SOURCEPOS ) )
+ else if ( rProp.Name.equalsAscii( SC_UNONAME_SOURCEPOS ) )
{
table::CellAddress aAddress;
if ( rProp.Value >>= aAddress )
aEntry.maPos = ScAddress( (SCCOL)aAddress.Column, (SCROW)aAddress.Row, aAddress.Sheet );
}
- else if ( aPropName.EqualsAscii( SC_UNONAME_SOURCESTR ) )
+ else if ( rProp.Name.equalsAscii( SC_UNONAME_SOURCESTR ) )
{
rtl::OUString aStrVal;
if ( rProp.Value >>= aStrVal )
aEntry.maPosStr = String( aStrVal );
}
- else if ( aPropName.EqualsAscii( SC_UNONAME_STYLENAME ) )
+ else if ( rProp.Name.equalsAscii( SC_UNONAME_STYLENAME ) )
{
rtl::OUString aStrVal;
if ( rProp.Value >>= aStrVal )
aEntry.maStyle = ScStyleNameConversion::ProgrammaticToDisplayName(
aStrVal, SFX_STYLE_FAMILY_PARA );
}
- else if ( aPropName.EqualsAscii( SC_UNONAME_GRAMMAR ) )
+ else if ( rProp.Name.equalsAscii( SC_UNONAME_FORMULANMSP1 ) )
+ {
+ rtl::OUString aStrVal;
+ if ( rProp.Value >>= aStrVal )
+ aEntry.maExprNmsp1 = aStrVal;
+ }
+ else if ( rProp.Name.equalsAscii( SC_UNONAME_FORMULANMSP2 ) )
+ {
+ rtl::OUString aStrVal;
+ if ( rProp.Value >>= aStrVal )
+ aEntry.maExprNmsp2 = aStrVal;
+ }
+ else if ( rProp.Name.equalsAscii( SC_UNONAME_GRAMMAR1 ) )
{
sal_Int32 nVal = 0;
if ( rProp.Value >>= nVal )
- aEntry.meGrammar = static_cast<formula::FormulaGrammar::Grammar>(nVal);
+ aEntry.meGrammar1 = static_cast< FormulaGrammar::Grammar >( nVal );
+ }
+ else if ( rProp.Name.equalsAscii( SC_UNONAME_GRAMMAR2 ) )
+ {
+ sal_Int32 nVal = 0;
+ if ( rProp.Value >>= nVal )
+ aEntry.meGrammar2 = static_cast< FormulaGrammar::Grammar >( nVal );
}
else
{
@@ -523,14 +554,14 @@ sheet::ConditionOperator SAL_CALL ScTableConditionalEntry::getOperator()
throw(uno::RuntimeException)
{
ScUnoGuard aGuard;
- return lcl_ConditionModeToOperator( static_cast<ScConditionMode>(aData.mnMode) );
+ return lcl_ConditionModeToOperator( aData.meMode );
}
void SAL_CALL ScTableConditionalEntry::setOperator( sheet::ConditionOperator nOperator )
throw(uno::RuntimeException)
{
ScUnoGuard aGuard;
- aData.mnMode = sal::static_int_cast<USHORT>( lcl_ConditionOperatorToMode( nOperator ) );
+ aData.meMode = lcl_ConditionOperatorToMode( nOperator );
if (pParent)
pParent->DataChanged();
}
@@ -619,7 +650,7 @@ ScTableValidationObj::ScTableValidationObj(ScDocument* pDoc, ULONG nKey,
aSrcPos = pData->GetValidSrcPos(); // #b4974740# valid pos for expressions
aExpr1 = pData->GetExpression( aSrcPos, 0, 0, eGrammar );
aExpr2 = pData->GetExpression( aSrcPos, 1, 0, eGrammar );
- meGrammar = eGrammar;
+ meGrammar1 = meGrammar2 = eGrammar;
nValMode = sal::static_int_cast<USHORT>( pData->GetDataMode() );
bIgnoreBlank = pData->IsIgnoreBlank();
nShowList = pData->GetListType();
@@ -647,18 +678,14 @@ ScValidationData* ScTableValidationObj::CreateValidationData( ScDocument* pDoc,
{
// ScValidationData = Core-Struktur
- if (eGrammar == formula::FormulaGrammar::GRAM_UNSPECIFIED)
- eGrammar = meGrammar;
- if (eGrammar == formula::FormulaGrammar::GRAM_UNSPECIFIED)
- {
- DBG_ERRORFILE("CreateValidationData: unspecified grammar, using GRAM_PODF_A1");
- eGrammar = formula::FormulaGrammar::GRAM_PODF_A1;
- }
+ FormulaGrammar::Grammar eGrammar1 = lclResolveGrammar( eGrammar, meGrammar1 );
+ FormulaGrammar::Grammar eGrammar2 = lclResolveGrammar( eGrammar, meGrammar2 );
ScValidationData* pRet = new ScValidationData( (ScValidationMode)nValMode,
(ScConditionMode)nMode,
aExpr1, aExpr2, pDoc, aSrcPos,
- eGrammar );
+ maExprNmsp1, maExprNmsp2,
+ eGrammar1, eGrammar2 );
pRet->SetIgnoreBlank(bIgnoreBlank);
pRet->SetListType(nShowList);
@@ -702,7 +729,9 @@ void ScTableValidationObj::ClearData_Impl()
aSrcPos.Set(0,0,0);
aExpr1.Erase();
aExpr2.Erase();
- meGrammar = formula::FormulaGrammar::GRAM_UNSPECIFIED; // will be overriden when needed
+ maExprNmsp1.Erase();
+ maExprNmsp2.Erase();
+ meGrammar1 = meGrammar2 = FormulaGrammar::GRAM_UNSPECIFIED; // will be overriden when needed
aInputTitle.Erase();
aInputMessage.Erase();
aErrorTitle.Erase();
@@ -905,13 +934,37 @@ void SAL_CALL ScTableValidationObj::setPropertyValue(
if ( aValue >>= aStrVal )
aPosString = String( aStrVal );
}
- else if ( aString.EqualsAscii( SC_UNONAME_GRAMMAR ) )
+ else if ( aString.EqualsAscii( SC_UNONAME_FORMULANMSP1 ) )
+ {
+ // internal - only for XML filter, not in PropertySetInfo, only set
+
+ rtl::OUString aStrVal;
+ if ( aValue >>= aStrVal )
+ maExprNmsp1 = aStrVal;
+ }
+ else if ( aString.EqualsAscii( SC_UNONAME_FORMULANMSP2 ) )
+ {
+ // internal - only for XML filter, not in PropertySetInfo, only set
+
+ rtl::OUString aStrVal;
+ if ( aValue >>= aStrVal )
+ maExprNmsp2 = aStrVal;
+ }
+ else if ( aString.EqualsAscii( SC_UNONAME_GRAMMAR1 ) )
+ {
+ // internal - only for XML filter, not in PropertySetInfo, only set
+
+ sal_Int32 nVal = 0;
+ if ( aValue >>= nVal )
+ meGrammar1 = static_cast< FormulaGrammar::Grammar >(nVal);
+ }
+ else if ( aString.EqualsAscii( SC_UNONAME_GRAMMAR2 ) )
{
// internal - only for XML filter, not in PropertySetInfo, only set
sal_Int32 nVal = 0;
if ( aValue >>= nVal )
- meGrammar = static_cast<formula::FormulaGrammar::Grammar>(nVal);
+ meGrammar2 = static_cast< FormulaGrammar::Grammar >(nVal);
}
DataChanged();
diff --git a/sc/source/ui/unoobj/tokenuno.cxx b/sc/source/ui/unoobj/tokenuno.cxx
index c543b5880fe7..e6e194d7eb75 100644
--- a/sc/source/ui/unoobj/tokenuno.cxx
+++ b/sc/source/ui/unoobj/tokenuno.cxx
@@ -51,17 +51,16 @@
#include "docsh.hxx"
#include "rangeseq.hxx"
#include "externalrefmgr.hxx"
-using namespace formula;
-using namespace com::sun::star;
+using namespace ::formula;
+using namespace ::com::sun::star;
-//------------------------------------------------------------------------
+// ============================================================================
const SfxItemPropertyMapEntry* lcl_GetFormulaParserMap()
{
static SfxItemPropertyMapEntry aFormulaParserMap_Impl[] =
{
- {MAP_CHAR_LEN(SC_UNO_REFERENCEPOS), 0, &getCppuType((table::CellAddress*)0), 0, 0 },
{MAP_CHAR_LEN(SC_UNO_COMPILEFAP), 0, &getBooleanCppuType(), 0, 0 },
{MAP_CHAR_LEN(SC_UNO_COMPILEENGLISH), 0, &getBooleanCppuType(), 0, 0 },
{MAP_CHAR_LEN(SC_UNO_IGNORELEADING), 0, &getBooleanCppuType(), 0, 0 },
@@ -74,7 +73,7 @@ const SfxItemPropertyMapEntry* lcl_GetFormulaParserMap()
SC_SIMPLE_SERVICE_INFO( ScFormulaParserObj, "ScFormulaParserObj", SC_SERVICENAME_FORMULAPARS )
-//------------------------------------------------------------------------
+// ============================================================================
ScFormulaParserObj::ScFormulaParserObj(ScDocShell* pDocSh) :
mpDocShell( pDocSh ),
@@ -135,7 +134,8 @@ void ScFormulaParserObj::SetCompilerFlags( ScCompiler& rCompiler ) const
rCompiler.SetExternalLinks( maExternalLinks);
}
-uno::Sequence<sheet::FormulaToken> SAL_CALL ScFormulaParserObj::parseFormula( const rtl::OUString& aFormula )
+uno::Sequence<sheet::FormulaToken> SAL_CALL ScFormulaParserObj::parseFormula(
+ const rtl::OUString& aFormula, const table::CellAddress& rReferencePos )
throw (uno::RuntimeException)
{
ScUnoGuard aGuard;
@@ -143,8 +143,10 @@ uno::Sequence<sheet::FormulaToken> SAL_CALL ScFormulaParserObj::parseFormula( co
if (mpDocShell)
{
+ ScAddress aRefPos( ScAddress::UNINITIALIZED );
+ ScUnoConversion::FillScAddress( aRefPos, rReferencePos );
ScDocument* pDoc = mpDocShell->GetDocument();
- ScCompiler aCompiler( pDoc, maRefPos);
+ ScCompiler aCompiler( pDoc, aRefPos);
aCompiler.SetGrammar(pDoc->GetGrammar());
SetCompilerFlags( aCompiler );
@@ -156,7 +158,8 @@ uno::Sequence<sheet::FormulaToken> SAL_CALL ScFormulaParserObj::parseFormula( co
return aRet;
}
-rtl::OUString SAL_CALL ScFormulaParserObj::printFormula( const uno::Sequence<sheet::FormulaToken>& aTokens )
+rtl::OUString SAL_CALL ScFormulaParserObj::printFormula(
+ const uno::Sequence<sheet::FormulaToken>& aTokens, const table::CellAddress& rReferencePos )
throw (uno::RuntimeException)
{
ScUnoGuard aGuard;
@@ -167,7 +170,9 @@ rtl::OUString SAL_CALL ScFormulaParserObj::printFormula( const uno::Sequence<she
ScDocument* pDoc = mpDocShell->GetDocument();
ScTokenArray aCode;
(void)ScTokenConversion::ConvertToTokenArray( *pDoc, aCode, aTokens );
- ScCompiler aCompiler( pDoc, maRefPos, aCode);
+ ScAddress aRefPos( ScAddress::UNINITIALIZED );
+ ScUnoConversion::FillScAddress( aRefPos, rReferencePos );
+ ScCompiler aCompiler( pDoc, aRefPos, aCode);
aCompiler.SetGrammar(pDoc->GetGrammar());
SetCompilerFlags( aCompiler );
@@ -197,13 +202,7 @@ void SAL_CALL ScFormulaParserObj::setPropertyValue(
{
ScUnoGuard aGuard;
String aString(aPropertyName);
- if ( aString.EqualsAscii( SC_UNO_REFERENCEPOS ) )
- {
- table::CellAddress aAddress;
- aValue >>= aAddress;
- ScUnoConversion::FillScAddress( maRefPos, aAddress );
- } // if ( aString.EqualsAscii( SC_UNO_REFERENCEPOS ) )
- else if ( aString.EqualsAscii( SC_UNO_COMPILEFAP ) )
+ if ( aString.EqualsAscii( SC_UNO_COMPILEFAP ) )
{
aValue >>= mbCompileFAP;
}
@@ -218,7 +217,7 @@ void SAL_CALL ScFormulaParserObj::setPropertyValue(
if (mxOpCodeMap.get() && mbEnglish != bOldEnglish)
{
ScDocument* pDoc = mpDocShell->GetDocument();
- ScCompiler aCompiler( pDoc, maRefPos);
+ ScCompiler aCompiler( pDoc, ScAddress());
aCompiler.SetGrammar(pDoc->GetGrammar());
mxOpCodeMap = aCompiler.CreateOpCodeMap( maOpCodeMapping, mbEnglish);
}
@@ -239,7 +238,7 @@ void SAL_CALL ScFormulaParserObj::setPropertyValue(
if (aValue >>= maOpCodeMapping)
{
ScDocument* pDoc = mpDocShell->GetDocument();
- ScCompiler aCompiler( pDoc, maRefPos);
+ ScCompiler aCompiler( pDoc, ScAddress());
aCompiler.SetGrammar(pDoc->GetGrammar());
mxOpCodeMap = aCompiler.CreateOpCodeMap( maOpCodeMapping, mbEnglish);
}
@@ -262,13 +261,7 @@ uno::Any SAL_CALL ScFormulaParserObj::getPropertyValue( const rtl::OUString& aPr
ScUnoGuard aGuard;
uno::Any aRet;
String aString(aPropertyName);
- if ( aString.EqualsAscii( SC_UNO_REFERENCEPOS ) )
- {
- table::CellAddress aAddress;
- ScUnoConversion::FillApiAddress( aAddress, maRefPos );
- aRet <<= aAddress;
- }
- else if ( aString.EqualsAscii( SC_UNO_COMPILEFAP ) )
+ if ( aString.EqualsAscii( SC_UNO_COMPILEFAP ) )
{
aRet <<= mbCompileFAP;
}
@@ -299,7 +292,7 @@ uno::Any SAL_CALL ScFormulaParserObj::getPropertyValue( const rtl::OUString& aPr
SC_IMPL_DUMMY_PROPERTY_LISTENER( ScFormulaParserObj )
-//------------------------------------------------------------------------
+// ============================================================================
void lcl_ExternalRefToApi( sheet::SingleReference& rAPI, const ScSingleRefData& rRef )
{
@@ -463,9 +456,13 @@ bool ScTokenConversion::ConvertToTokenSequence( ScDocument& rDoc,
return !bError;
}
-// -----------------------------------------------------------------------------
+
+// ============================================================================
+
ScFormulaOpCodeMapperObj::ScFormulaOpCodeMapperObj(::std::auto_ptr<formula::FormulaCompiler> _pCompiler)
: formula::FormulaOpCodeMapperObj(_pCompiler)
{
}
+// ============================================================================
+
diff --git a/sc/source/ui/vba/vbarange.cxx b/sc/source/ui/vba/vbarange.cxx
index 5019167b4374..d1ac4504ce96 100644
--- a/sc/source/ui/vba/vbarange.cxx
+++ b/sc/source/ui/vba/vbarange.cxx
@@ -77,7 +77,10 @@
#include <com/sun/star/sheet/XCellRangeMovement.hpp>
#include <com/sun/star/sheet/XCellRangeData.hpp>
#include <com/sun/star/sheet/FormulaResult.hpp>
+#include <com/sun/star/sheet/FilterOperator2.hpp>
#include <com/sun/star/sheet/TableFilterField.hpp>
+#include <com/sun/star/sheet/TableFilterField2.hpp>
+#include <com/sun/star/sheet/XSheetFilterDescriptor2.hpp>
#include <com/sun/star/sheet/XSheetFilterable.hpp>
#include <com/sun/star/sheet/FilterConnection.hpp>
#include <com/sun/star/util/CellProtection.hpp>
@@ -4027,7 +4030,7 @@ void lcl_SetAllQueryForField( ScDocShell* pDocShell, SCCOLROW nField, sal_Int16
}
// Modifies sCriteria, and nOp depending on the value of sCriteria
-void lcl_setTableFieldsFromCriteria( rtl::OUString& sCriteria1, uno::Reference< beans::XPropertySet >& xDescProps, sheet::TableFilterField& rFilterField )
+void lcl_setTableFieldsFromCriteria( rtl::OUString& sCriteria1, uno::Reference< beans::XPropertySet >& xDescProps, sheet::TableFilterField2& rFilterField )
{
// #TODO make this more efficient and cycle through
// sCriteria1 character by character to pick up <,<>,=, * etc.
@@ -4047,10 +4050,10 @@ void lcl_setTableFieldsFromCriteria( rtl::OUString& sCriteria1, uno::Reference<
if ( ( nPos = sCriteria1.indexOf( EQUALS ) ) == 0 )
{
if ( sCriteria1.getLength() == EQUALS.getLength() )
- rFilterField.Operator = sheet::FilterOperator_EMPTY;
+ rFilterField.Operator = sheet::FilterOperator2::EMPTY;
else
{
- rFilterField.Operator = sheet::FilterOperator_EQUAL;
+ rFilterField.Operator = sheet::FilterOperator2::EQUAL;
sCriteria1 = sCriteria1.copy( EQUALS.getLength() );
sCriteria1 = VBAToRegexp( sCriteria1 );
// UseRegularExpressions
@@ -4062,10 +4065,10 @@ void lcl_setTableFieldsFromCriteria( rtl::OUString& sCriteria1, uno::Reference<
else if ( ( nPos = sCriteria1.indexOf( NOTEQUALS ) ) == 0 )
{
if ( sCriteria1.getLength() == NOTEQUALS.getLength() )
- rFilterField.Operator = sheet::FilterOperator_NOT_EMPTY;
+ rFilterField.Operator = sheet::FilterOperator2::NOT_EMPTY;
else
{
- rFilterField.Operator = sheet::FilterOperator_NOT_EQUAL;
+ rFilterField.Operator = sheet::FilterOperator2::NOT_EQUAL;
sCriteria1 = sCriteria1.copy( NOTEQUALS.getLength() );
sCriteria1 = VBAToRegexp( sCriteria1 );
// UseRegularExpressions
@@ -4079,12 +4082,12 @@ void lcl_setTableFieldsFromCriteria( rtl::OUString& sCriteria1, uno::Reference<
if ( ( nPos = sCriteria1.indexOf( GREATERTHANEQUALS ) ) == 0 )
{
sCriteria1 = sCriteria1.copy( GREATERTHANEQUALS.getLength() );
- rFilterField.Operator = sheet::FilterOperator_GREATER_EQUAL;
+ rFilterField.Operator = sheet::FilterOperator2::GREATER_EQUAL;
}
else
{
sCriteria1 = sCriteria1.copy( GREATERTHAN.getLength() );
- rFilterField.Operator = sheet::FilterOperator_GREATER;
+ rFilterField.Operator = sheet::FilterOperator2::GREATER;
}
}
@@ -4094,17 +4097,17 @@ void lcl_setTableFieldsFromCriteria( rtl::OUString& sCriteria1, uno::Reference<
if ( ( nPos = sCriteria1.indexOf( LESSTHANEQUALS ) ) == 0 )
{
sCriteria1 = sCriteria1.copy( LESSTHANEQUALS.getLength() );
- rFilterField.Operator = sheet::FilterOperator_LESS_EQUAL;
+ rFilterField.Operator = sheet::FilterOperator2::LESS_EQUAL;
}
else
{
sCriteria1 = sCriteria1.copy( LESSTHAN.getLength() );
- rFilterField.Operator = sheet::FilterOperator_LESS;
+ rFilterField.Operator = sheet::FilterOperator2::LESS;
}
}
else
- rFilterField.Operator = sheet::FilterOperator_EQUAL;
+ rFilterField.Operator = sheet::FilterOperator2::EQUAL;
if ( bIsNumeric )
{
@@ -4213,13 +4216,16 @@ ScVbaRange::AutoFilter( const uno::Any& Field, const uno::Any& Criteria1, const
bool bAll = false;;
if ( ( Field >>= nField ) )
{
- uno::Sequence< sheet::TableFilterField > sTabFilts;
- uno::Reference< sheet::XSheetFilterDescriptor > xDesc = xDataBaseRange->getFilterDescriptor();
- uno::Reference< beans::XPropertySet > xDescProps( xDesc, uno::UNO_QUERY_THROW );
+ uno::Reference< sheet::XSheetFilterDescriptor2 > xDesc(
+ xDataBaseRange->getFilterDescriptor(), uno::UNO_QUERY );
+ if ( xDesc.is() )
+ {
+ uno::Sequence< sheet::TableFilterField2 > sTabFilts;
+ uno::Reference< beans::XPropertySet > xDescProps( xDesc, uno::UNO_QUERY_THROW );
if ( Criteria1.hasValue() )
{
sTabFilts.realloc( 1 );
- sTabFilts[0].Operator = sheet::FilterOperator_EQUAL;// sensible default
+ sTabFilts[0].Operator = sheet::FilterOperator2::EQUAL;// sensible default
if ( !bCritHasNumericValue )
{
Criteria1 >>= sCriteria1;
@@ -4252,16 +4258,16 @@ ScVbaRange::AutoFilter( const uno::Any& Field, const uno::Any& Criteria1, const
switch ( nOperator )
{
case excel::XlAutoFilterOperator::xlBottom10Items:
- sTabFilts[0].Operator = sheet::FilterOperator_BOTTOM_VALUES;
+ sTabFilts[0].Operator = sheet::FilterOperator2::BOTTOM_VALUES;
break;
case excel::XlAutoFilterOperator::xlBottom10Percent:
- sTabFilts[0].Operator = sheet::FilterOperator_BOTTOM_PERCENT;
+ sTabFilts[0].Operator = sheet::FilterOperator2::BOTTOM_PERCENT;
break;
case excel::XlAutoFilterOperator::xlTop10Items:
- sTabFilts[0].Operator = sheet::FilterOperator_TOP_VALUES;
+ sTabFilts[0].Operator = sheet::FilterOperator2::TOP_VALUES;
break;
case excel::XlAutoFilterOperator::xlTop10Percent:
- sTabFilts[0].Operator = sheet::FilterOperator_TOP_PERCENT;
+ sTabFilts[0].Operator = sheet::FilterOperator2::TOP_PERCENT;
break;
case excel::XlAutoFilterOperator::xlOr:
nConn = sheet::FilterConnection_OR;
@@ -4300,12 +4306,12 @@ ScVbaRange::AutoFilter( const uno::Any& Field, const uno::Any& Criteria1, const
{
Criteria2 >>= sTabFilts[1].NumericValue;
sTabFilts[1].IsNumeric = sal_True;
- sTabFilts[1].Operator = sheet::FilterOperator_EQUAL;
+ sTabFilts[1].Operator = sheet::FilterOperator2::EQUAL;
}
}
}
- xDesc->setFilterFields( sTabFilts );
+ xDesc->setFilterFields2( sTabFilts );
if ( !bAll )
{
xDataBaseRange->refresh();
@@ -4313,6 +4319,7 @@ ScVbaRange::AutoFilter( const uno::Any& Field, const uno::Any& Criteria1, const
else
// was 0 based now seems to be 1
lcl_SetAllQueryForField( pShell, nField, nSheet );
+ }
}
else
{
@@ -4333,7 +4340,10 @@ ScVbaRange::AutoFilter( const uno::Any& Field, const uno::Any& Criteria1, const
lcl_SetAllQueryForField( pShell, rEntry.nField, nSheet );
}
// remove exising filters
- xDataBaseRange->getFilterDescriptor()->setFilterFields( uno::Sequence< sheet::TableFilterField >() );
+ uno::Reference< sheet::XSheetFilterDescriptor2 > xSheetFilterDescriptor(
+ xDataBaseRange->getFilterDescriptor(), uno::UNO_QUERY );
+ if( xSheetFilterDescriptor.is() )
+ xSheetFilterDescriptor->setFilterFields2( uno::Sequence< sheet::TableFilterField2 >() );
}
xDBRangeProps->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("AutoFilter") ), uno::Any(!bHasAuto) );
diff --git a/sc/source/ui/view/cellsh1.cxx b/sc/source/ui/view/cellsh1.cxx
index 94184ad63c7c..e5bb702402d8 100644
--- a/sc/source/ui/view/cellsh1.cxx
+++ b/sc/source/ui/view/cellsh1.cxx
@@ -1709,32 +1709,7 @@ void ScCellShell::ExecuteEdit( SfxRequest& rReq )
break;
case SID_TOGGLE_REL:
- {
- BOOL bOk = FALSE;
- SCCOL nCol = GetViewData()->GetCurX();
- SCROW nRow = GetViewData()->GetCurY();
- SCTAB nTab = GetViewData()->GetTabNo();
- ScDocument* pDoc = GetViewData()->GetDocument();
- CellType eType;
- pDoc->GetCellType( nCol, nRow, nTab, eType );
- if (eType == CELLTYPE_FORMULA)
- {
- String aOld;
- pDoc->GetFormula( nCol, nRow, nTab, aOld );
- xub_StrLen nLen = aOld.Len();
- ScRefFinder aFinder( aOld, pDoc );
- aFinder.ToggleRel( 0, nLen );
- if (aFinder.GetFound())
- {
- String aNew = aFinder.GetText();
- pTabViewShell->EnterData( nCol, nRow, nTab, aNew );
- pTabViewShell->UpdateInputHandler();
- bOk = TRUE;
- }
- }
- if (!bOk)
- pTabViewShell->ErrorMessage(STR_ERR_NOREF);
- }
+ pTabViewShell->DoRefConversion();
break;
case SID_DEC_INDENT:
diff --git a/sc/source/ui/view/viewfun4.cxx b/sc/source/ui/view/viewfun4.cxx
index 57fef68c5f83..0f3a1c812802 100644
--- a/sc/source/ui/view/viewfun4.cxx
+++ b/sc/source/ui/view/viewfun4.cxx
@@ -81,6 +81,9 @@
#include "impex.hxx"
#include "editutil.hxx"
#include "editable.hxx"
+#include "dociter.hxx"
+#include "reffind.hxx"
+#include "compiler.hxx"
using namespace com::sun::star;
@@ -187,7 +190,128 @@ void ScViewFunc::PasteRTF( SCCOL nStartCol, SCROW nStartRow,
ShowAllCursors();
}
}
+void ScViewFunc::DoRefConversion( BOOL bRecord )
+{
+ ScDocument* pDoc = GetViewData()->GetDocument();
+ ScMarkData& rMark = GetViewData()->GetMarkData();
+ SCTAB nTabCount = pDoc->GetTableCount();
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+ ScRange aMarkRange;
+ rMark.MarkToSimple();
+ BOOL bMulti = rMark.IsMultiMarked();
+ if (bMulti)
+ rMark.GetMultiMarkArea( aMarkRange );
+ else if (rMark.IsMarked())
+ rMark.GetMarkArea( aMarkRange );
+ else
+ {
+ aMarkRange = ScRange( GetViewData()->GetCurX(),
+ GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
+ }
+ ScEditableTester aTester( pDoc, aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
+ aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(),rMark );
+ if (!aTester.IsEditable())
+ {
+ ErrorMessage(aTester.GetMessageId());
+ return;
+ }
+
+ ScDocShell* pDocSh = GetViewData()->GetDocShell();
+ BOOL bOk = FALSE;
+
+ ScDocument* pUndoDoc = NULL;
+ if (bRecord)
+ {
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ SCTAB nTab = aMarkRange.aStart.Tab();
+ pUndoDoc->InitUndo( pDoc, nTab, nTab );
+
+ if ( rMark.GetSelectCount() > 1 )
+ {
+ for (SCTAB i=0; i<nTabCount; i++)
+ if ( rMark.GetTableSelect(i) && i != nTab )
+ pUndoDoc->AddUndoTab( i, i );
+ }
+ ScRange aCopyRange = aMarkRange;
+ aCopyRange.aStart.SetTab(0);
+ aCopyRange.aEnd.SetTab(nTabCount-1);
+ pDoc->CopyToDocument( aCopyRange, IDF_ALL, bMulti, pUndoDoc, &rMark );
+ }
+
+ ScRangeListRef xRanges;
+ GetViewData()->GetMultiArea( xRanges );
+ ULONG nCount = xRanges->Count();
+
+ for (SCTAB i=0; i<nTabCount; i++)
+ {
+ if (rMark.GetTableSelect(i))
+ {
+ for (ULONG j=0; j<nCount; j++)
+ {
+ ScRange aRange = *xRanges->GetObject(j);
+ aRange.aStart.SetTab(i);
+ aRange.aEnd.SetTab(i);
+ ScCellIterator aIter( pDoc, aRange );
+ ScBaseCell* pCell = aIter.GetFirst();
+ while ( pCell )
+ {
+ if (pCell->GetCellType() == CELLTYPE_FORMULA)
+ {
+ String aOld;
+ ((ScFormulaCell*)pCell)->GetFormula(aOld);
+ xub_StrLen nLen = aOld.Len();
+ ScRefFinder aFinder( aOld, pDoc );
+ aFinder.ToggleRel( 0, nLen );
+ if (aFinder.GetFound())
+ {
+ ScAddress aPos = ((ScFormulaCell*)pCell)->aPos;
+ String aNew = aFinder.GetText();
+ ScCompiler aComp( pDoc, aPos);
+ aComp.SetGrammar(pDoc->GetGrammar());
+ ScTokenArray* pArr = aComp.CompileString( aNew );
+ ScFormulaCell* pNewCell = new ScFormulaCell( pDoc, aPos,
+ pArr,formula::FormulaGrammar::GRAM_DEFAULT, MM_NONE );
+ pDoc->PutCell( aPos, pNewCell );
+ bOk = TRUE;
+ }
+ }
+ pCell = aIter.GetNext();
+ }
+ }
+ }
+ }
+ if (bRecord)
+ {
+ ScDocument* pRedoDoc = new ScDocument( SCDOCMODE_UNDO );
+ SCTAB nTab = aMarkRange.aStart.Tab();
+ pRedoDoc->InitUndo( pDoc, nTab, nTab );
+
+ if ( rMark.GetSelectCount() > 1 )
+ {
+ for (SCTAB i=0; i<nTabCount; i++)
+ if ( rMark.GetTableSelect(i) && i != nTab )
+ pRedoDoc->AddUndoTab( i, i );
+ }
+ ScRange aCopyRange = aMarkRange;
+ aCopyRange.aStart.SetTab(0);
+ aCopyRange.aEnd.SetTab(nTabCount-1);
+ pDoc->CopyToDocument( aCopyRange, IDF_ALL, bMulti, pRedoDoc, &rMark );
+
+ pDocSh->GetUndoManager()->AddUndoAction(
+ new ScUndoRefConversion( pDocSh,
+ aMarkRange, rMark, pUndoDoc, pRedoDoc, bMulti, IDF_ALL) );
+ }
+
+ pDocSh->PostPaint( aMarkRange, PAINT_GRID );
+ pDocSh->UpdateOle(GetViewData());
+ pDocSh->SetDocumentModified();
+ CellContentChanged();
+
+ if (!bOk)
+ ErrorMessage(STR_ERR_NOREF);
+}
// Thesaurus - Undo ok
void ScViewFunc::DoThesaurus( BOOL bRecord )
{
@@ -537,11 +661,13 @@ BOOL ScViewFunc::PasteFile( const Point& rPos, const String& rFile, BOOL bLink )
SfxDispatcher &rDispatcher = GetViewData()->GetDispatcher();
SfxStringItem aFileNameItem( SID_FILE_NAME, aStrURL );
SfxStringItem aFilterItem( SID_FILTER_NAME, pFlt->GetName() );
+ // #i69524# add target, as in SfxApplication when the Open dialog is used
+ SfxStringItem aTargetItem( SID_TARGETNAME, String::CreateFromAscii("_default") );
// Asynchron oeffnen, kann naemlich auch aus D&D heraus passieren
// und das bekommt dem MAC nicht so gut ...
return BOOL( 0 != rDispatcher.Execute( SID_OPENDOC,
- SFX_CALLMODE_ASYNCHRON, &aFileNameItem, &aFilterItem, 0L) );
+ SFX_CALLMODE_ASYNCHRON, &aFileNameItem, &aFilterItem, &aTargetItem, 0L) );
}
}
diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx
index fe52636c4e37..79343c31f85b 100644
--- a/sc/source/ui/view/viewfunc.cxx
+++ b/sc/source/ui/view/viewfunc.cxx
@@ -599,6 +599,7 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const String& rS
}
else
{
+ DELETEZ(pUndoData);
ScFormulaCell* pCell = new ScFormulaCell( aCell, *pDoc, aPos );
if ( nError )
{
@@ -751,12 +752,13 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const EditTextOb
ScPatternAttr* pCellAttrs = NULL;
EditTextObject* pNewData = NULL;
String aString;
+
+ const ScPatternAttr* pOldPattern = pDoc->GetPattern( nCol, nRow, nTab );
+ ScTabEditEngine aEngine( *pOldPattern, pDoc->GetEnginePool() );
+ aEngine.SetText(*pData);
+
if (bTestSimple) // Testen, ob einfacher String ohne Attribute
{
- const ScPatternAttr* pOldPattern = pDoc->GetPattern( nCol, nRow, nTab );
- ScTabEditEngine aEngine( *pOldPattern, pDoc->GetEnginePool() );
- aEngine.SetText(*pData);
-
ScEditAttrTester aAttrTester( &aEngine );
bSimple = !aAttrTester.NeedsObject();
bCommon = aAttrTester.NeedsCellAttr();
@@ -777,11 +779,11 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const EditTextOb
pCellAttrs->GetFromEditItemSet( &aAttrTester.GetAttribs() );
//! remove common attributes from EditEngine?
}
-
- if (bSimple)
- aString = aEngine.GetText();
}
+ // #i97726# always get text for "repeat" of undo action
+ aString = ScEditUtil::GetSpaceDelimitedString(aEngine);
+
//
// Undo
//
@@ -838,7 +840,7 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const EditTextOb
{ // wg. ChangeTrack erst jetzt
pDocSh->GetUndoManager()->AddUndoAction(
new ScUndoEnterData( pDocSh, nCol, nRow, nTab, nPos, pTabs,
- ppOldCells, NULL, NULL, String(),
+ ppOldCells, NULL, NULL, aString,
pUndoData ) );
}
@@ -924,7 +926,7 @@ void ScViewFunc::EnterMatrix( const String& rString )
if (pData->GetSimpleArea(aRange) == SC_MARK_SIMPLE)
{
ScDocShell* pDocSh = pData->GetDocShell();
- BOOL bSuccess = pDocSh->GetDocFunc().EnterMatrix( aRange, &rMark, NULL, rString, FALSE, FALSE,formula::FormulaGrammar::GRAM_DEFAULT );
+ BOOL bSuccess = pDocSh->GetDocFunc().EnterMatrix( aRange, &rMark, NULL, rString, FALSE, FALSE, EMPTY_STRING, formula::FormulaGrammar::GRAM_DEFAULT );
if (bSuccess)
pDocSh->UpdateOle(GetViewData());
}