summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chart2/source/controller/dialogs/tp_Scale.cxx45
-rw-r--r--chart2/source/controller/dialogs/tp_Scale.hxx2
-rw-r--r--sc/CppunitTest_sc_ucalc.mk13
-rw-r--r--sc/Library_sc.mk1
-rw-r--r--sc/Package_qa_unit.mk44
-rw-r--r--sc/inc/address.hxx2
-rw-r--r--sc/inc/dbcolect.hxx2
-rw-r--r--sc/inc/document.hxx3
-rw-r--r--sc/inc/dpcachetable.hxx20
-rw-r--r--sc/inc/dpobject.hxx80
-rw-r--r--sc/inc/dpoutput.hxx10
-rw-r--r--sc/inc/dpsdbtab.hxx7
-rw-r--r--sc/inc/dpshttab.hxx4
-rw-r--r--sc/inc/dptabdat.hxx3
-rw-r--r--sc/inc/dptablecache.hxx46
-rw-r--r--sc/inc/rangenam.hxx3
-rw-r--r--sc/inc/reffind.hxx5
-rw-r--r--sc/inc/table.hxx4
-rw-r--r--sc/qa/unit/Makefile53
-rw-r--r--sc/qa/unit/ucalc.cxx627
-rw-r--r--sc/source/core/data/conditio.cxx18
-rw-r--r--sc/source/core/data/documen2.cxx50
-rw-r--r--sc/source/core/data/documen3.cxx8
-rw-r--r--sc/source/core/data/documen4.cxx85
-rw-r--r--sc/source/core/data/document.cxx9
-rw-r--r--sc/source/core/data/dpcachetable.cxx72
-rw-r--r--sc/source/core/data/dpobject.cxx197
-rw-r--r--sc/source/core/data/dpoutput.cxx208
-rw-r--r--sc/source/core/data/dpsdbtab.cxx116
-rw-r--r--sc/source/core/data/dpshttab.cxx18
-rw-r--r--sc/source/core/data/dptablecache.cxx95
-rw-r--r--sc/source/core/data/scdpoutputimpl.cxx184
-rw-r--r--sc/source/core/data/scdpoutputimpl.hxx79
-rw-r--r--sc/source/core/data/table1.cxx54
-rw-r--r--sc/source/core/data/table2.cxx60
-rw-r--r--sc/source/core/data/table4.cxx269
-rw-r--r--sc/source/core/inc/interpre.hxx1
-rw-r--r--sc/source/core/tool/compiler.cxx1
-rw-r--r--sc/source/core/tool/dbcolect.cxx29
-rw-r--r--sc/source/core/tool/interpr1.cxx76
-rw-r--r--sc/source/core/tool/interpr4.cxx92
-rw-r--r--sc/source/core/tool/rangenam.cxx17
-rw-r--r--sc/source/core/tool/reffind.cxx196
-rw-r--r--sc/source/filter/excel/excform.cxx19
-rw-r--r--sc/source/filter/excel/excform8.cxx83
-rw-r--r--sc/source/filter/excel/read.cxx4
-rw-r--r--sc/source/filter/excel/xepivot.cxx2
-rw-r--r--sc/source/filter/excel/xilink.cxx234
-rw-r--r--sc/source/filter/excel/xipivot.cxx21
-rw-r--r--sc/source/filter/excel/xistyle.cxx4
-rw-r--r--sc/source/filter/inc/excform.hxx11
-rw-r--r--sc/source/filter/inc/xilink.hxx23
-rw-r--r--sc/source/filter/inc/xipivot.hxx1
-rw-r--r--sc/source/filter/inc/xlstring.hxx2
-rw-r--r--sc/source/filter/xml/XMLExportDataPilot.cxx12
-rw-r--r--sc/source/filter/xml/xmlcelli.cxx2
-rw-r--r--sc/source/ui/app/inputwin.cxx19
-rw-r--r--sc/source/ui/attrdlg/scabstdlg.cxx3
-rw-r--r--sc/source/ui/cctrl/dpcontrol.cxx1
-rw-r--r--sc/source/ui/dbgui/dapidata.cxx2
-rw-r--r--sc/source/ui/dbgui/dpuiglobal.hxx1
-rw-r--r--sc/source/ui/dbgui/fieldwnd.cxx9
-rw-r--r--sc/source/ui/dbgui/pvlaydlg.cxx35
-rw-r--r--sc/source/ui/docshell/docfunc.cxx24
-rw-r--r--sc/source/ui/docshell/docsh5.cxx60
-rw-r--r--sc/source/ui/docshell/externalrefmgr.cxx76
-rw-r--r--sc/source/ui/inc/fieldwnd.hxx1
-rw-r--r--sc/source/ui/inc/output.hxx21
-rw-r--r--sc/source/ui/inc/pvlaydlg.hxx2
-rw-r--r--sc/source/ui/inc/undoblk.hxx4
-rw-r--r--sc/source/ui/src/popup.src2
-rw-r--r--sc/source/ui/undo/undoblk3.cxx50
-rw-r--r--sc/source/ui/vba/excelvbahelper.cxx87
-rw-r--r--sc/source/ui/vba/excelvbahelper.hxx16
-rw-r--r--sc/source/ui/vba/vbaapplication.cxx3
-rw-r--r--sc/source/ui/vba/vbaworkbook.cxx28
-rw-r--r--sc/source/ui/vba/vbaworkbook.hxx4
-rw-r--r--sc/source/ui/vba/vbaworkbooks.cxx82
-rw-r--r--sc/source/ui/vba/vbaworksheet.cxx153
-rw-r--r--sc/source/ui/vba/vbaworksheet.hxx5
-rw-r--r--sc/source/ui/vba/vbaworksheets.cxx70
-rw-r--r--sc/source/ui/vba/vbaworksheets.hxx1
-rw-r--r--sc/source/ui/view/dbfunc3.cxx42
-rw-r--r--sc/source/ui/view/editsh.cxx7
-rw-r--r--sc/source/ui/view/output.cxx10
-rw-r--r--sc/source/ui/view/output2.cxx1104
-rw-r--r--sc/source/ui/view/viewfun4.cxx2
-rw-r--r--sc/source/ui/view/viewfunc.cxx9
88 files changed, 3877 insertions, 1382 deletions
diff --git a/chart2/source/controller/dialogs/tp_Scale.cxx b/chart2/source/controller/dialogs/tp_Scale.cxx
index 0eb9ae7bf047..9e77ad94c35d 100644
--- a/chart2/source/controller/dialogs/tp_Scale.cxx
+++ b/chart2/source/controller/dialogs/tp_Scale.cxx
@@ -183,6 +183,8 @@ ScaleTabPage::ScaleTabPage(Window* pWindow,const SfxItemSet& rInAttrs) :
aFmtFldMax.SetModifyHdl(LINK(this, ScaleTabPage, FmtFieldModifiedHdl));
aFmtFldStepMain.SetModifyHdl(LINK(this, ScaleTabPage, FmtFieldModifiedHdl));
aFmtFldOrigin.SetModifyHdl(LINK(this, ScaleTabPage, FmtFieldModifiedHdl));
+
+ HideAllControls();
}
IMPL_LINK( ScaleTabPage, FmtFieldModifiedHdl, FormattedField*, pFmtFied )
@@ -784,6 +786,49 @@ bool ScaleTabPage::ShowWarning( sal_uInt16 nResIdMessage, Control* pControl /* =
return true;
}
+void ScaleTabPage::HideAllControls()
+{
+ // We need to set these controls invisible when the class is instantiated
+ // since some code in EnableControls() depends on that logic. The real
+ // visibility of these controls depend on axis data type, and are
+ // set in EnableControls().
+
+ m_aTxt_AxisType.Hide();
+ m_aLB_AxisType.Hide();
+
+ aCbxLogarithm.Hide();
+ aTxtMin.Hide();
+ aFmtFldMin.Hide();
+ aCbxAutoMin.Hide();
+ aTxtMax.Hide();
+ aFmtFldMax.Hide();
+ aCbxAutoMax.Hide();
+ aTxtMain.Hide();
+ aFmtFldStepMain.Hide();
+ aCbxAutoStepMain.Hide();
+ aTxtHelp.Hide();
+ aTxtHelpCount.Hide();
+ aMtStepHelp.Hide();
+ aCbxAutoStepHelp.Hide();
+
+ aTxtOrigin.Hide();
+ aFmtFldOrigin.Hide();
+ aCbxAutoOrigin.Hide();
+
+ aTxtHelpCount.Hide();
+ aTxtHelp.Hide();
+
+ m_aTxt_TimeResolution.Hide();
+ m_aLB_TimeResolution.Hide();
+ m_aCbx_AutoTimeResolution.Hide();
+
+ aFmtFldStepMain.Hide();
+ m_aMt_MainDateStep.Hide();
+
+ m_aLB_MainTimeUnit.Hide();
+ m_aLB_HelpTimeUnit.Hide();
+}
+
//.............................................................................
} //namespace chart
//.............................................................................
diff --git a/chart2/source/controller/dialogs/tp_Scale.hxx b/chart2/source/controller/dialogs/tp_Scale.hxx
index f062ed438383..0a56b4f7a0bd 100644
--- a/chart2/source/controller/dialogs/tp_Scale.hxx
+++ b/chart2/source/controller/dialogs/tp_Scale.hxx
@@ -138,6 +138,8 @@ private:
@return false, if nResIdMessage was 0, true otherwise
*/
bool ShowWarning( sal_uInt16 nResIdMessage, Control* pControl = NULL );
+
+ void HideAllControls();
};
//.............................................................................
diff --git a/sc/CppunitTest_sc_ucalc.mk b/sc/CppunitTest_sc_ucalc.mk
index ec8db65901f8..d58b8bdc0b6d 100644
--- a/sc/CppunitTest_sc_ucalc.mk
+++ b/sc/CppunitTest_sc_ucalc.mk
@@ -30,10 +30,23 @@
$(eval $(call gb_CppunitTest_CppunitTest,sc_ucalc))
+$(eval $(call gb_CppunitTest_add_package_headers,sc_ucalc,sc_qa_unit))
+
$(eval $(call gb_CppunitTest_add_exception_objects,sc_ucalc, \
sc/qa/unit/ucalc \
))
+$(eval $(call gb_CppunitTest_set_args,sc_ucalc,\
+ --headless \
+ --invisible \
+ "-env:UNO_TYPES=$(foreach binrdb,udkapi.rdb types.rdb,\
+ file://$(if $(filter WNT,$(OS)),/)$(OUTDIR)/bin/$(binrdb))" \
+ "-env:UNO_SERVICES=$(foreach rdb,$(OUTDIR)/xml/ure/services.rdb $(WORKDIR)/CustomTarget/sc/qa/unit/services.rdb,\
+ file://$(if $(filter WNT,$(OS)),/)$(rdb))" \
+ $(foreach dir,URE_INTERNAL_LIB_DIR OOO_BASE_DIR BRAND_BASE_DIR, \
+ -env:$(dir)=file://$(if $(filter WNT,$(OS)),/$(OUTDIR)/bin,$(OUTDIR)/lib)) \
+))
+
$(eval $(call gb_CppunitTest_add_library_objects,sc_ucalc,sc))
$(eval $(call gb_CppunitTest_add_linked_libs,sc_ucalc, \
diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index 8559cc3d4a22..c57671ed7a12 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -130,7 +130,6 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
sc/source/core/data/pivot2 \
sc/source/core/data/poolhelp \
sc/source/core/data/postit \
- sc/source/core/data/scdpoutputimpl \
sc/source/core/data/segmenttree \
sc/source/core/data/sheetevents \
sc/source/core/data/sortparam \
diff --git a/sc/Package_qa_unit.mk b/sc/Package_qa_unit.mk
new file mode 100644
index 000000000000..8db8cb798f07
--- /dev/null
+++ b/sc/Package_qa_unit.mk
@@ -0,0 +1,44 @@
+# Version: MPL 1.1 / GPLv3+ / LGPLv3+
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Initial Developer of the Original Code is
+# Bjoern Michaelsen <bjoern.michaelsen@canonical.com> (Canonical Ltd.)
+# Portions created by the Initial Developer are Copyright (C) 2011 the
+# Initial Developer. All Rights Reserved.
+#
+# Contributor(s): Bjoern Michaelsen <bjoern.michaelsen@canonical.com> (Canonical Ltd.)
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 3 or later (the "GPLv3+"), or
+# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
+# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
+# instead of those above.
+
+$(eval $(call gb_Package_Package,sc_qa_unit,$(WORKDIR)/CustomTarget/sc/qa/unit))
+$(eval $(call gb_Package_add_customtarget,sc_qa_unit,sc/qa/unit))
+
+# dependencies that cause the CustomTarget Makefile to be called recursively for
+# (re)build
+$(eval $(call gb_CustomTarget_add_outdir_dependencies,sc/qa/unit,\
+ $(foreach newcomponentfile,\
+ framework/util/fwk \
+ sfx2/util/sfx \
+ unoxml/source/service/unoxml,\
+ $(OUTDIR)/xml/component/$(newcomponentfile).component) \
+ $(foreach oldcomponentfile, \
+ i18npool \
+ ucb1 \
+ ucpfile1, \
+ $(OUTDIR)/xml/$(oldcomponentfile).component) \
+))
+
+# vim: set noet sw=4:
diff --git a/sc/inc/address.hxx b/sc/inc/address.hxx
index 96842785c8f3..74920c7575b7 100644
--- a/sc/inc/address.hxx
+++ b/sc/inc/address.hxx
@@ -487,7 +487,7 @@ public:
const ::com::sun::star::uno::Sequence<
const ::com::sun::star::sheet::ExternalLinkInfo > * pExternalLinks = NULL );
- sal_uInt16 ParseAny( const String&, ScDocument* = NULL,
+ SC_DLLPUBLIC sal_uInt16 ParseAny( const String&, ScDocument* = NULL,
const ScAddress::Details& rDetails = ScAddress::detailsOOOa1 );
SC_DLLPUBLIC sal_uInt16 ParseCols( const String&, ScDocument* = NULL,
const ScAddress::Details& rDetails = ScAddress::detailsOOOa1 );
diff --git a/sc/inc/dbcolect.hxx b/sc/inc/dbcolect.hxx
index 8583b710e437..8f26f667f5f8 100644
--- a/sc/inc/dbcolect.hxx
+++ b/sc/inc/dbcolect.hxx
@@ -122,6 +122,7 @@ public:
bool operator== (const ScDBData& rData) const;
+ SCTAB GetTable() const;
const String& GetName() const { return aName; }
void GetName(String& rName) const { rName = aName; }
void SetName(const String& rName) { aName = rName; }
@@ -214,6 +215,7 @@ public:
virtual sal_Bool IsEqual(ScDataObject* pKey1, ScDataObject* pKey2) const;
ScDBData* GetDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, sal_Bool bStartOnly) const;
ScDBData* GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const;
+ ScDBData* GetFilterDBAtTable(SCTAB nTab) const;
ScDBData* GetDBNearCursor(SCCOL nCol, SCROW nRow, SCTAB nTab );
sal_Bool SearchName( const String& rName, sal_uInt16& rIndex ) const;
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 894b2a518728..3c485fd48575 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -484,6 +484,8 @@ public:
ScDBData* GetDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab,
sal_Bool bStartOnly = false) const;
ScDBData* GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const;
+ ScDBData* GetFilterDBAtTable(SCTAB nTab) const;
+
SC_DLLPUBLIC const ScRangeData* GetRangeAtBlock( const ScRange& rBlock, String* pName=NULL ) const;
@@ -1485,7 +1487,6 @@ public:
VirtualDevice* GetVirtualDevice_100th_mm();
SC_DLLPUBLIC OutputDevice* GetRefDevice(); // WYSIWYG: Printer, otherwise VirtualDevice...
- void EraseNonUsedSharedNames(sal_uInt16 nLevel);
sal_Bool GetNextSpellingCell(SCCOL& nCol, SCROW& nRow, SCTAB nTab,
sal_Bool bInSel, const ScMarkData& rMark) const;
diff --git a/sc/inc/dpcachetable.hxx b/sc/inc/dpcachetable.hxx
index 73b3d5e12727..9c6353d0b51a 100644
--- a/sc/inc/dpcachetable.hxx
+++ b/sc/inc/dpcachetable.hxx
@@ -58,6 +58,13 @@ struct ScQueryParam;
class SC_DLLPUBLIC ScDPCacheTable
{
+ struct RowFlag
+ {
+ bool mbShowByFilter:1;
+ bool mbShowByPage:1;
+ bool isActive() const;
+ RowFlag();
+ };
public:
/** individual filter item used in SingleFilter and GroupFilter. */
struct FilterItem
@@ -121,7 +128,7 @@ public:
Criterion();
};
- ScDPCacheTable(ScDPCache* pCache);
+ ScDPCacheTable(const ScDPCache* pCache);
~ScDPCacheTable();
sal_Int32 getRowSize() const;
@@ -169,15 +176,13 @@ public:
SCROW getOrder(long nDim, SCROW nIndex) const;
void clear();
bool empty() const;
- void setCache(ScDPCache* p);
+ void setCache(const ScDPCache* p);
bool hasCache() const;
private:
ScDPCacheTable();
ScDPCacheTable(const ScDPCacheTable&);
- ScDPCache* getCache();
-
/**
* Check if a given row meets all specified criteria.
*
@@ -190,11 +195,10 @@ private:
/** unique field entires for each field (column). */
::std::vector< ::std::vector<SCROW> > maFieldEntries;
- /** used to track visibility of rows. The first row below the header row
- has the index of 0. */
- ::std::vector<bool> maRowsVisible;
+ /** Row flags. The first row below the header row has the index of 0. */
+ ::std::vector<RowFlag> maRowFlags;
- ScDPCache* mpCache;
+ const ScDPCache* mpCache;
};
#endif
diff --git a/sc/inc/dpobject.hxx b/sc/inc/dpobject.hxx
index 59230d833491..d71040906443 100644
--- a/sc/inc/dpobject.hxx
+++ b/sc/inc/dpobject.hxx
@@ -39,6 +39,7 @@
#include <boost/ptr_container/ptr_list.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
+#include <boost/ptr_container/ptr_map.hpp>
#include <boost/shared_ptr.hpp>
namespace com { namespace sun { namespace star { namespace sheet {
@@ -117,7 +118,6 @@ private:
SC_DLLPRIVATE void CreateObjects();
SC_DLLPRIVATE void CreateOutput();
sal_Bool bRefresh;
- long mnCacheId;
public:
ScDPObject(ScDocument* pD);
@@ -257,13 +257,67 @@ public:
class ScDPCollection
{
-private:
- typedef ::boost::ptr_vector<ScDPObject> TablesType;
+public:
- ScDocument* pDoc;
- TablesType maTables;
+ /**
+ * Stores and manages all caches from internal sheets.
+ */
+ class SheetCaches
+ {
+ typedef ::boost::ptr_map<ScRange, ScDPCache> CachesType;
+ CachesType maCaches;
+ ScDocument* mpDoc;
+ public:
+ SheetCaches(ScDocument* pDoc);
+ const ScDPCache* getCache(const ScRange& rRange);
+ void removeCache(const ScRange& rRange);
+ };
+
+ /**
+ * Data caches for range name based source data.
+ */
+ class NameCaches
+ {
+ typedef ::boost::ptr_map<rtl::OUString, ScDPCache> CachesType;
+ CachesType maCaches;
+ ScDocument* mpDoc;
+ public:
+ NameCaches(ScDocument* pDoc);
+ const ScDPCache* getCache(const ::rtl::OUString& rName, const ScRange& rRange);
+ void removeCache(const ::rtl::OUString& rName);
+ };
+
+ /**
+ * Defines connection type to external data source. Used as a key to look
+ * up database cache.
+ */
+ struct DBType
+ {
+ sal_Int32 mnSdbType;
+ ::rtl::OUString maDBName;
+ ::rtl::OUString maCommand;
+ DBType(sal_Int32 nSdbType, const ::rtl::OUString& rDBName, const ::rtl::OUString& rCommand);
+
+ struct less : public ::std::binary_function<DBType, DBType, bool>
+ {
+ bool operator() (const DBType& left, const DBType& right) const;
+ };
+ };
+
+ /**
+ * Data caches for external database sources.
+ */
+ class DBCaches
+ {
+ typedef ::boost::ptr_map<DBType, ScDPCache, DBType::less> CachesType;
+ CachesType maCaches;
+ ScDocument* mpDoc;
+ public:
+ DBCaches(ScDocument* pDoc);
+ const ScDPCache* getCache(sal_Int32 nSdbType, const ::rtl::OUString& rDBName, const ::rtl::OUString& rCommand);
+ void removeCache(sal_Int32 nSdbType, const ::rtl::OUString& rDBName, const ::rtl::OUString& rCommand);
+ };
-public:
ScDPCollection(ScDocument* pDocument);
ScDPCollection(const ScDPCollection& r);
~ScDPCollection();
@@ -296,8 +350,22 @@ public:
SC_DLLPUBLIC bool InsertNewTable(ScDPObject* pDPObj);
bool HasDPTable(SCCOL nCol, SCROW nRow, SCTAB nTab) const;
+
+ SheetCaches& GetSheetCaches();
+ NameCaches& GetNameCaches();
+ DBCaches& GetDBCaches();
+
+private:
+ typedef ::boost::ptr_vector<ScDPObject> TablesType;
+
+ ScDocument* pDoc;
+ TablesType maTables;
+ SheetCaches maSheetCaches;
+ NameCaches maNameCaches;
+ DBCaches maDBCaches;
};
+bool operator<(const ScDPCollection::DBType& left, const ScDPCollection::DBType& right);
#endif
diff --git a/sc/inc/dpoutput.hxx b/sc/inc/dpoutput.hxx
index 99ca1ed82754..d1d07e2c42cb 100644
--- a/sc/inc/dpoutput.hxx
+++ b/sc/inc/dpoutput.hxx
@@ -81,7 +81,7 @@ private:
com::sun::star::uno::Reference<
com::sun::star::sheet::XDimensionsSupplier> xSource;
ScAddress aStartPos;
- sal_Bool bDoFilter;
+ bool bDoFilter;
ScDPOutLevelData* pColFields;
ScDPOutLevelData* pRowFields;
ScDPOutLevelData* pPageFields;
@@ -91,7 +91,7 @@ private:
com::sun::star::uno::Sequence<
com::sun::star::uno::Sequence<
com::sun::star::sheet::DataResult> > aData;
- sal_Bool bResultsError;
+ bool bResultsError;
bool mbHasDataLayout;
String aDataDescription;
@@ -103,8 +103,8 @@ private:
sal_uInt32 nSingleNumFmt;
// Output geometry related parameters
- sal_Bool bSizesValid;
- sal_Bool bSizeOverflow;
+ bool bSizesValid;
+ bool bSizeOverflow;
long nColCount;
long nRowCount;
long nHeaderSize;
@@ -136,7 +136,7 @@ public:
ScDPOutput( ScDocument* pD,
const com::sun::star::uno::Reference<
com::sun::star::sheet::XDimensionsSupplier>& xSrc,
- const ScAddress& rPos, sal_Bool bFilter );
+ const ScAddress& rPos, bool bFilter );
~ScDPOutput();
void SetPosition( const ScAddress& rPos );
diff --git a/sc/inc/dpsdbtab.hxx b/sc/inc/dpsdbtab.hxx
index b86d0869e404..87c3ccd1ec5c 100644
--- a/sc/inc/dpsdbtab.hxx
+++ b/sc/inc/dpsdbtab.hxx
@@ -41,8 +41,8 @@ class ScDocument;
struct ScImportSourceDesc
{
- String aDBName;
- String aObject;
+ ::rtl::OUString aDBName;
+ ::rtl::OUString aObject;
sal_uInt16 nType; // enum DataImportMode
bool bNative;
ScDocument* mpDoc;
@@ -56,7 +56,8 @@ struct ScImportSourceDesc
bNative == rOther.bNative &&
mpDoc == rOther.mpDoc; }
- ScDPCache* CreateCache() const;
+ sal_Int32 GetCommandType() const;
+ const ScDPCache* CreateCache() const;
};
/**
diff --git a/sc/inc/dpshttab.hxx b/sc/inc/dpshttab.hxx
index 9215ef107dfb..505a2758ae78 100644
--- a/sc/inc/dpshttab.hxx
+++ b/sc/inc/dpshttab.hxx
@@ -78,7 +78,7 @@ public:
const ScQueryParam& GetQueryParam() const;
bool operator== ( const ScSheetSourceDesc& rOther ) const;
- SC_DLLPUBLIC ScDPCache* CreateCache() const;
+ SC_DLLPUBLIC const ScDPCache* CreateCache() const;
/**
* Check the sanity of the data source range.
@@ -111,7 +111,7 @@ private:
ScDPCacheTable aCacheTable;
public:
- ScSheetDPData(ScDocument* pD, const ScSheetSourceDesc& rDesc, ScDPCache* pCache);
+ ScSheetDPData(ScDocument* pD, const ScSheetSourceDesc& rDesc, const ScDPCache* pCache);
virtual ~ScSheetDPData();
virtual long GetColumnCount();
diff --git a/sc/inc/dptabdat.hxx b/sc/inc/dptabdat.hxx
index 7b3dde760246..31d32fe25706 100644
--- a/sc/inc/dptabdat.hxx
+++ b/sc/inc/dptabdat.hxx
@@ -39,6 +39,7 @@
#include <set>
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
+#include <boost/noncopyable.hpp>
namespace com { namespace sun { namespace star { namespace sheet {
struct DataPilotFieldFilter;
@@ -91,7 +92,7 @@ class ScDocument;
* Base class that abstracts different data source types of a datapilot
* table.
*/
-class SC_DLLPUBLIC ScDPTableData
+class SC_DLLPUBLIC ScDPTableData : public ::boost::noncopyable
{
// cached data for GetDatePart
long nLastDateVal;
diff --git a/sc/inc/dptablecache.hxx b/sc/inc/dptablecache.hxx
index c1ee4238193c..4bfb14dad727 100644
--- a/sc/inc/dptablecache.hxx
+++ b/sc/inc/dptablecache.hxx
@@ -48,7 +48,6 @@ struct ScQueryParam;
*/
class SC_DLLPUBLIC ScDPCache
{
- friend class ScDPCacheTable;
public:
typedef ::boost::ptr_vector<ScDPItemData> DataListType;
private:
@@ -58,20 +57,41 @@ private:
ScDocument* mpDoc;
long mnColumnCount;
- DataGridType maTableDataValues; // Data Pilot Table's index - value map
- RowGridType maSourceData; // Data Pilot Table's source data
- RowGridType maGlobalOrder; // Sorted members index
- mutable RowGridType maIndexOrder; // Index the sorted numbers
- DataListType maLabelNames; // Source label data
- std::vector<bool> mbEmptyRow; //If empty row?
+ /**
+ * This container stores only the unique instances of item data in each
+ * column. Duplicates are not allowed.
+ */
+ DataGridType maTableDataValues;
+
+ /**
+ * This container stores indices within maTableDataValues pointing to the
+ * data. The order of data are exactly as they appear in the original
+ * data source.
+ */
+ RowGridType maSourceData;
+
+ /**
+ * This container stores indices within maTableDataValues. The order of
+ * indices in each column represents ascending order of the actual data.
+ */
+ RowGridType maGlobalOrder;
+
+ /**
+ * This container stores the ranks of each unique data represented by
+ * their index.
+ */
+ mutable RowGridType maIndexOrder;
+
+ DataListType maLabelNames; // Stores dimension names.
+ std::vector<bool> mbEmptyRow; // Keeps track of empty rows.
mutable ScDPItemDataPool maAdditionalData;
public:
- SCROW GetIdByItemData( long nDim, String sItemData ) const;
+ SCROW GetIdByItemData( long nDim, const String& sItemData ) const;
SCROW GetIdByItemData( long nDim, const ScDPItemData& rData ) const;
- SCROW GetAdditionalItemID ( String sItemData ) const;
+ SCROW GetAdditionalItemID ( const String& sItemData ) const;
SCROW GetAdditionalItemID( const ScDPItemData& rData ) const;
SCCOL GetDimensionIndex( String sName) const;
@@ -81,6 +101,7 @@ public:
bool IsDateDimension( long nDim ) const ;
sal_uLong GetDimNumType( SCCOL nDim) const;
SCROW GetDimMemberCount( SCCOL nDim ) const;
+ SCROW GetOrder( long nDim, SCROW nIndex ) const;
SCROW GetSortedItemDataId( SCCOL nDim, SCROW nOrder ) const;
const DataListType& GetDimMemberValues( SCCOL nDim ) const;
@@ -93,7 +114,7 @@ public:
bool IsEmptyMember( SCROW nRow, sal_uInt16 nColumn ) const;
bool IsRowEmpty( SCROW nRow ) const;
bool IsValid() const;
- bool ValidQuery( SCROW nRow, const ScQueryParam& rQueryParam, bool* pSpecial );
+ bool ValidQuery( SCROW nRow, const ScQueryParam& rQueryParam, bool* pSpecial ) const;
ScDocument* GetDoc() const;//ms-cache-core
long GetColumnCount() const;
@@ -103,12 +124,11 @@ public:
bool operator== ( const ScDPCache& r ) const;
ScDPCache(ScDocument* pDoc);
- virtual ~ScDPCache();
+ ~ScDPCache();
private:
- SCROW GetOrder( long nDim, SCROW nIndex ) const;
void AddLabel( ScDPItemData* pData);
- bool AddData( long nDim, ScDPItemData* itemData );
+ bool AddData(long nDim, ScDPItemData* pData);
};
#endif
diff --git a/sc/inc/rangenam.hxx b/sc/inc/rangenam.hxx
index db50fe0d6aa4..ebf2769e2baf 100644
--- a/sc/inc/rangenam.hxx
+++ b/sc/inc/rangenam.hxx
@@ -176,7 +176,6 @@ class ScRangeName
private:
typedef ::boost::ptr_set<ScRangeData> DataType;
DataType maData;
- sal_uInt16 mnSharedMaxIndex;
public:
/// Map that manages stored ScRangeName instances.
@@ -203,8 +202,6 @@ public:
void UpdateTabRef(SCTAB nTable, sal_uInt16 nFlag, SCTAB nNewTable = 0);
void UpdateTranspose(const ScRange& rSource, const ScAddress& rDest);
void UpdateGrow(const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY);
- sal_uInt16 GetSharedMaxIndex();
- void SetSharedMaxIndex(sal_uInt16 nInd);
SC_DLLPUBLIC const_iterator begin() const;
SC_DLLPUBLIC const_iterator end() const;
diff --git a/sc/inc/reffind.hxx b/sc/inc/reffind.hxx
index cc2f330194e9..63dcf12c65e8 100644
--- a/sc/inc/reffind.hxx
+++ b/sc/inc/reffind.hxx
@@ -42,14 +42,13 @@ private:
String aFormula;
formula::FormulaGrammar::AddressConvention eConv;
ScDocument* pDoc;
+ ScAddress maPos;
xub_StrLen nFound;
xub_StrLen nSelStart;
xub_StrLen nSelEnd;
public:
- static const sal_Unicode pDelimiters[];
-
- ScRefFinder( const String& rFormula,
+ ScRefFinder( const String& rFormula, const ScAddress& rPos,
ScDocument* pDocument = NULL,
formula::FormulaGrammar::AddressConvention eConvP = formula::FormulaGrammar::CONV_OOO );
~ScRefFinder();
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index a1574a2f89ba..56fb749c5273 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -171,7 +171,6 @@ private:
ScSortParam aSortParam;
CollatorWrapper* pSortCollator;
sal_Bool bGlobalKeepQuery;
- sal_Bool bSharedNameInserted;
ScRangeVec aPrintRanges;
bool bPrintEntireSheet;
@@ -688,6 +687,7 @@ public:
/// @return the index of the last changed row (flags and row height, auto pagebreak is ignored).
SCROW GetLastChangedRow() const;
+ bool IsDataFiltered() const;
sal_uInt8 GetColFlags( SCCOL nCol ) const;
sal_uInt8 GetRowFlags( SCROW nRow ) const;
@@ -909,6 +909,8 @@ private:
*/
void MaybeAddExtraColumn(SCCOL& rCol, SCROW nRow, OutputDevice* pDev, double nPPTX, double nPPTY);
+ void CopyPrintRange(const ScTable& rTable);
+
/**
* Use this to iterate through non-empty visible cells in a single column.
*/
diff --git a/sc/qa/unit/Makefile b/sc/qa/unit/Makefile
new file mode 100644
index 000000000000..87694f116f34
--- /dev/null
+++ b/sc/qa/unit/Makefile
@@ -0,0 +1,53 @@
+# Version: MPL 1.1 / GPLv3+ / LGPLv3+
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Initial Developer of the Original Code is
+# Bjoern Michaelsen <bjoern.michaelsen@canonical.com> (Canonical Ltd.)
+# Portions created by the Initial Developer are Copyright (C) 2011 the
+# Initial Developer. All Rights Reserved.
+#
+# Contributor(s): Bjoern Michaelsen <bjoern.michaelsen@canonical.com> (Canonical Ltd.)
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 3 or later (the "GPLv3+"), or
+# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
+# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
+# instead of those above.
+
+MYDIR := $(realpath $(dir $(firstword $(MAKEFILE_LIST))))
+
+all : services.rdb
+
+services.rdb : $(foreach newcomponentfile,\
+ framework/util/fwk \
+ sfx2/util/sfx \
+ unoxml/source/service/unoxml,\
+ $(OUTDIR)/xml/component/$(newcomponentfile).component \
+)
+
+services.rdb : $(foreach oldcomponentfile, \
+ i18npool \
+ ucb1 \
+ ucpfile1, \
+ $(OUTDIR)/xml/$(oldcomponentfile).component \
+)
+
+services.rdb :
+ echo '<?xml version="1.0"?><components xmlns="http://openoffice.org/2010/uno-components">' > $@
+ $(gb_AWK) -- \
+ '/^<\?xml version.*/ { next; } \
+ { gsub(/vnd.sun.star.expand:\$$OOO_BASE_DIR\/program/, "vnd.sun.star.expand:$$OOO_BASE_DIR",$$0); gsub(/vnd.sun.star.expand:\$$BRAND_BASE_DIR\/program/, "vnd.sun.star.expand:$$BRAND_BASE_DIR",$$0); print; }' \
+ $^ >> $@
+ echo '</components>' >> $@
+
+.PHONY : all
+# vim: set noet sw=4 ts=4:
diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index 242a0927ea4d..a27b591724de 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -49,6 +49,8 @@
#include <cppuhelper/bootstrap.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/oslfile2streamwrap.hxx>
+#include <i18npool/mslangid.hxx>
+#include <unotools/syslocaleoptions.hxx>
#include <vcl/svapp.hxx>
#include "scdll.hxx"
@@ -57,6 +59,7 @@
#include "scmatrix.hxx"
#include "drwlayer.hxx"
#include "scitems.hxx"
+#include "reffind.hxx"
#include "docsh.hxx"
#include "funcdesc.hxx"
@@ -224,12 +227,14 @@ public:
void testCollator();
void testInput();
- void testSUM();
+ void testCellFunctions();
void testVolatileFunc();
+ void testFuncParam();
void testNamedRange();
void testCSV();
void testMatrix();
void testDataPilot();
+ void testDataPilotFilters();
void testSheetCopy();
void testExternalRef();
void testDataArea();
@@ -252,15 +257,24 @@ public:
*/
void testCVEs();
+ /**
+ * Test toggling relative/absolute flag of cell and cell range references.
+ * This corresponds with hitting Shift-F4 while the cursor is on a formula
+ * cell.
+ */
+ void testToggleRefFlag();
+
CPPUNIT_TEST_SUITE(Test);
CPPUNIT_TEST(testCollator);
CPPUNIT_TEST(testInput);
- CPPUNIT_TEST(testSUM);
+ CPPUNIT_TEST(testCellFunctions);
CPPUNIT_TEST(testVolatileFunc);
+ CPPUNIT_TEST(testFuncParam);
CPPUNIT_TEST(testNamedRange);
CPPUNIT_TEST(testCSV);
CPPUNIT_TEST(testMatrix);
CPPUNIT_TEST(testDataPilot);
+ CPPUNIT_TEST(testDataPilotFilters);
CPPUNIT_TEST(testSheetCopy);
CPPUNIT_TEST(testExternalRef);
CPPUNIT_TEST(testDataArea);
@@ -270,6 +284,7 @@ public:
#if 0 // Disable because in some cases this test breaks
CPPUNIT_TEST(testCVEs);
#endif
+ CPPUNIT_TEST(testToggleRefFlag);
CPPUNIT_TEST_SUITE_END();
private:
@@ -305,8 +320,19 @@ Test::Test()
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ucb.FileContentProvider"))), uno::UNO_QUERY);
xUcb->registerContentProvider(xFileProvider, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("file")), sal_True);
- InitVCL(xSM);
+ // force locale (and resource files loaded) to en-US
+ const LanguageType eLang=LANGUAGE_ENGLISH_US;
+
+ rtl::OUString aLang, aCountry;
+ MsLangId::convertLanguageToIsoNames(eLang, aLang, aCountry);
+ lang::Locale aLocale(aLang, aCountry, rtl::OUString());
+ ResMgr::SetDefaultLocale( aLocale );
+ SvtSysLocaleOptions aLocalOptions;
+ aLocalOptions.SetUILocaleConfigString(
+ MsLangId::convertLanguageToIsoString( eLang ) );
+
+ InitVCL(xSM);
ScDLL::Init();
oslProcessError err = osl_getProcessWorkingDir(&m_aPWDURL.pData);
@@ -364,11 +390,13 @@ void Test::testInput()
m_pDoc->DeleteTab(0);
}
-void Test::testSUM()
+void Test::testCellFunctions()
{
rtl::OUString aTabName(RTL_CONSTASCII_USTRINGPARAM("foo"));
CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet",
m_pDoc->InsertTab (0, aTabName));
+
+ // SUM
double val = 1;
m_pDoc->SetValue (0, 0, 0, val);
m_pDoc->SetValue (0, 1, 0, val);
@@ -378,6 +406,23 @@ void Test::testSUM()
m_pDoc->GetValue (0, 2, 0, result);
CPPUNIT_ASSERT_MESSAGE ("calculation failed", result == 2.0);
+ // PRODUCT
+ val = 1;
+ m_pDoc->SetValue(0, 0, 0, val);
+ val = 2;
+ m_pDoc->SetValue(0, 1, 0, val);
+ val = 3;
+ m_pDoc->SetValue(0, 2, 0, val);
+ m_pDoc->SetString(0, 3, 0, OUString(RTL_CONSTASCII_USTRINGPARAM("=PRODUCT(A1:A3)")));
+ m_pDoc->CalcAll();
+ m_pDoc->GetValue(0, 3, 0, result);
+ CPPUNIT_ASSERT_MESSAGE("Calculation of PRODUCT failed", result == 6.0);
+
+ m_pDoc->SetString(0, 4, 0, OUString(RTL_CONSTASCII_USTRINGPARAM("=PRODUCT({1;2;3})")));
+ m_pDoc->CalcAll();
+ m_pDoc->GetValue(0, 4, 0, result);
+ CPPUNIT_ASSERT_MESSAGE("Calculation of PRODUCT with inline array failed", result == 6.0);
+
m_pDoc->DeleteTab(0);
}
@@ -411,6 +456,29 @@ void Test::testVolatileFunc()
m_pDoc->DeleteTab(0);
}
+void Test::testFuncParam()
+{
+ rtl::OUString aTabName(RTL_CONSTASCII_USTRINGPARAM("foo"));
+ CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet",
+ m_pDoc->InsertTab (0, aTabName));
+
+ // First, the normal case, with no missing parameters.
+ m_pDoc->SetString(0, 0, 0, OUString(RTL_CONSTASCII_USTRINGPARAM("=AVERAGE(1;2;3)")));
+ m_pDoc->CalcFormulaTree(false, true);
+ double val;
+ m_pDoc->GetValue(0, 0, 0, val);
+ CPPUNIT_ASSERT_MESSAGE("incorrect result", val == 2);
+
+ // Now function with missing parameters. Missing values should be treated
+ // as zeros.
+ m_pDoc->SetString(0, 0, 0, OUString(RTL_CONSTASCII_USTRINGPARAM("=AVERAGE(1;;;)")));
+ m_pDoc->CalcFormulaTree(false, true);
+ m_pDoc->GetValue(0, 0, 0, val);
+ CPPUNIT_ASSERT_MESSAGE("incorrect result", val == 0.25);
+
+ m_pDoc->DeleteTab(0);
+}
+
void Test::testNamedRange()
{
rtl::OUString aTabName(RTL_CONSTASCII_USTRINGPARAM("Sheet1"));
@@ -651,89 +719,66 @@ void Test::testMatrix()
}
}
-void Test::testDataPilot()
-{
- m_pDoc->InsertTab(0, OUString(RTL_CONSTASCII_USTRINGPARAM("Data")));
- m_pDoc->InsertTab(1, OUString(RTL_CONSTASCII_USTRINGPARAM("Table")));
-
- // Dimension definition
- struct {
- const char* pName; sheet::DataPilotFieldOrientation eOrient;
- } aFields[] = {
- { "Name", sheet::DataPilotFieldOrientation_ROW },
- { "Group", sheet::DataPilotFieldOrientation_COLUMN },
- { "Score", sheet::DataPilotFieldOrientation_DATA }
- };
-
- // Raw data
- struct {
- const char* pName; const char* pGroup; int nScore;
- } aData[] = {
- { "Andy", "A", 30 },
- { "Bruce", "A", 20 },
- { "Charlie", "B", 45 },
- { "David", "B", 12 },
- { "Edward", "C", 8 },
- { "Frank", "C", 15 },
- };
-
- // Expected output table content. 0 = empty cell
- const char* aOutputCheck[][5] = {
- { "Sum - Score", "Group", 0, 0, 0 },
- { "Name", "A", "B", "C", "Total Result" },
- { "Andy", "30", 0, 0, "30" },
- { "Bruce", "20", 0, 0, "20" },
- { "Charlie", 0, "45", 0, "45" },
- { "David", 0, "12", 0, "12" },
- { "Edward", 0, 0, "8", "8" },
- { "Frank", 0, 0, "15", "15" },
- { "Total Result", "50", "57", "23", "130" }
- };
-
- sal_uInt32 nFieldCount = SAL_N_ELEMENTS(aFields);
- sal_uInt32 nDataCount = SAL_N_ELEMENTS(aData);
-
- // Insert field names in row 0.
- for (sal_uInt32 i = 0; i < nFieldCount; ++i)
- m_pDoc->SetString(static_cast<SCCOL>(i), 0, 0, OUString(aFields[i].pName, strlen(aFields[i].pName), RTL_TEXTENCODING_UTF8));
-
- // Insert data into row 1 and downward.
- for (sal_uInt32 i = 0; i < nDataCount; ++i)
- {
- SCROW nRow = static_cast<SCROW>(i) + 1;
- m_pDoc->SetString(0, nRow, 0, OUString(aData[i].pName, strlen(aData[i].pName), RTL_TEXTENCODING_UTF8));
- m_pDoc->SetString(1, nRow, 0, OUString(aData[i].pGroup, strlen(aData[i].pGroup), RTL_TEXTENCODING_UTF8));
- m_pDoc->SetValue(2, nRow, 0, aData[i].nScore);
- }
-
- SCROW nRow1 = 0, nRow2 = 0;
- SCCOL nCol1 = 0, nCol2 = 0;
- m_pDoc->GetDataArea(0, nCol1, nRow1, nCol2, nRow2, true, false);
- CPPUNIT_ASSERT_MESSAGE("Data is expected to start from (col=0,row=0).", nCol1 == 0 && nRow1 == 0);
- CPPUNIT_ASSERT_MESSAGE("Unexpected data range.",
- nCol2 == static_cast<SCCOL>(nFieldCount - 1) && nRow2 == static_cast<SCROW>(nDataCount));
+namespace {
- SheetPrinter printer(nRow2 - nRow1 + 1, nCol2 - nCol1 + 1);
- for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
+template<int _Size>
+bool checkDPTableOutput(ScDocument* pDoc, const ScRange& aOutRange, const char* aOutputCheck[][_Size], const char* pCaption)
+{
+ const ScAddress& s = aOutRange.aStart;
+ const ScAddress& e = aOutRange.aEnd;
+ SheetPrinter printer(e.Row() - s.Row() + 1, e.Col() - s.Col() + 1);
+ SCROW nOutRowSize = e.Row() - s.Row() + 1;
+ SCCOL nOutColSize = e.Col() - s.Col() + 1;
+ for (SCROW nRow = 0; nRow < nOutRowSize; ++nRow)
{
- for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+ for (SCCOL nCol = 0; nCol < nOutColSize; ++nCol)
{
- String aVal;
- m_pDoc->GetString(nCol, nRow, 0, aVal);
+ OUString aVal;
+ pDoc->GetString(nCol + s.Col(), nRow + s.Row(), s.Tab(), aVal);
printer.set(nRow, nCol, aVal);
+ const char* p = aOutputCheck[nRow][nCol];
+ if (p)
+ {
+ OUString aCheckVal = OUString::createFromAscii(p);
+ bool bEqual = aCheckVal.equals(aVal);
+ if (!bEqual)
+ {
+ cerr << "Expected: " << aCheckVal << " Actual: " << aVal << endl;
+ return false;
+ }
+ }
+ else if (!aVal.isEmpty())
+ {
+ cerr << "Empty cell expected" << endl;
+ return false;
+ }
}
}
- printer.print("Data sheet content");
- printer.clear();
+ printer.print(pCaption);
+ return true;
+}
+
+struct DPFieldDef
+{
+ const char* pName;
+ sheet::DataPilotFieldOrientation eOrient;
+};
- ScSheetSourceDesc aSheetDesc(m_pDoc);
- aSheetDesc.SetSourceRange(ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0));
- ScDPObject* pDPObj = new ScDPObject(m_pDoc);
+ScDPObject* createDPFromRange(
+ ScDocument* pDoc, const ScRange& rRange, DPFieldDef aFields[], size_t nFieldCount,
+ bool bFilterButton)
+{
+ SCROW nRow1 = rRange.aStart.Row(), nRow2 = rRange.aEnd.Row();
+ SCCOL nCol1 = rRange.aStart.Col();
+
+ ScSheetSourceDesc aSheetDesc(pDoc);
+ aSheetDesc.SetSourceRange(rRange);
+ ScDPObject* pDPObj = new ScDPObject(pDoc);
pDPObj->SetSheetDesc(aSheetDesc);
pDPObj->SetOutRange(ScAddress(0, 0, 1));
ScPivotParam aParam;
pDPObj->FillOldParam(aParam);
- for (sal_uInt32 i = 0; i < nFieldCount; ++i)
+ for (size_t i = 0; i < nFieldCount; ++i)
{
vector<ScDPLabelData::Member> aMembers;
pDPObj->GetMembers(i, 0, aMembers);
@@ -745,7 +790,7 @@ void Test::testDataPilot()
aSaveData.SetRepeatIfEmpty(false);
aSaveData.SetColumnGrand(true);
aSaveData.SetRowGrand(true);
- aSaveData.SetFilterButton(false);
+ aSaveData.SetFilterButton(bFilterButton);
aSaveData.SetDrillDown(true);
// Check the sanity of the source range.
@@ -756,11 +801,11 @@ void Test::testDataPilot()
CPPUNIT_ASSERT_MESSAGE("source range contains no data!", nRow2 - nRow1 > 1);
// Set the dimension information.
- for (sal_uInt32 i = 0; i < nFieldCount; ++i)
+ for (size_t i = 0; i < nFieldCount; ++i)
{
OUString aDimName(aFields[i].pName, strlen(aFields[i].pName), RTL_TEXTENCODING_UTF8);
ScDPSaveDimension* pDim = aSaveData.GetDimensionByName(aDimName);
- pDim->SetOrientation(aFields[i].eOrient);
+ pDim->SetOrientation(static_cast<sal_uInt16>(aFields[i].eOrient));
pDim->SetUsedHierarchy(0);
pDim->SetShowEmpty(true);
@@ -794,7 +839,7 @@ void Test::testDataPilot()
{
SCCOL nCol = nCol1 + static_cast<SCCOL>(i);
String aVal;
- m_pDoc->GetString(nCol, nRow, 0, aVal);
+ pDoc->GetString(nCol, nRow, 0, aVal);
// This call is just to populate the member list for each dimension.
ScDPSaveMember* pMem = pDim->GetMemberByName(aVal);
pMem->SetShowDetails(true);
@@ -809,12 +854,81 @@ void Test::testDataPilot()
pDPObj->SetSaveData(aSaveData);
pDPObj->SetAlive(true);
+ pDPObj->InvalidateData();
+
+ return pDPObj;
+}
+
+}
+
+void Test::testDataPilot()
+{
+ m_pDoc->InsertTab(0, OUString(RTL_CONSTASCII_USTRINGPARAM("Data")));
+ m_pDoc->InsertTab(1, OUString(RTL_CONSTASCII_USTRINGPARAM("Table")));
+
+ // Dimension definition
+ DPFieldDef aFields[] = {
+ { "Name", sheet::DataPilotFieldOrientation_ROW },
+ { "Group", sheet::DataPilotFieldOrientation_COLUMN },
+ { "Score", sheet::DataPilotFieldOrientation_DATA }
+ };
+
+ // Raw data
+ struct {
+ const char* pName; const char* pGroup; int nScore;
+ } aData[] = {
+ { "Andy", "A", 30 },
+ { "Bruce", "A", 20 },
+ { "Charlie", "B", 45 },
+ { "David", "B", 12 },
+ { "Edward", "C", 8 },
+ { "Frank", "C", 15 },
+ };
+
+ size_t nFieldCount = SAL_N_ELEMENTS(aFields);
+ size_t nDataCount = SAL_N_ELEMENTS(aData);
+
+ // Insert field names in row 0.
+ for (size_t i = 0; i < nFieldCount; ++i)
+ m_pDoc->SetString(static_cast<SCCOL>(i), 0, 0, OUString(aFields[i].pName, strlen(aFields[i].pName), RTL_TEXTENCODING_UTF8));
+
+ // Insert data into row 1 and downward.
+ for (size_t i = 0; i < nDataCount; ++i)
+ {
+ SCROW nRow = static_cast<SCROW>(i) + 1;
+ m_pDoc->SetString(0, nRow, 0, OUString(aData[i].pName, strlen(aData[i].pName), RTL_TEXTENCODING_UTF8));
+ m_pDoc->SetString(1, nRow, 0, OUString(aData[i].pGroup, strlen(aData[i].pGroup), RTL_TEXTENCODING_UTF8));
+ m_pDoc->SetValue(2, nRow, 0, aData[i].nScore);
+ }
+
+ SCROW nRow1 = 0, nRow2 = 0;
+ SCCOL nCol1 = 0, nCol2 = 0;
+ m_pDoc->GetDataArea(0, nCol1, nRow1, nCol2, nRow2, true, false);
+ CPPUNIT_ASSERT_MESSAGE("Data is expected to start from (col=0,row=0).", nCol1 == 0 && nRow1 == 0);
+ CPPUNIT_ASSERT_MESSAGE("Unexpected data range.",
+ nCol2 == static_cast<SCCOL>(nFieldCount - 1) && nRow2 == static_cast<SCROW>(nDataCount));
+
+ SheetPrinter printer(nRow2 - nRow1 + 1, nCol2 - nCol1 + 1);
+ for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
+ {
+ for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+ {
+ String aVal;
+ m_pDoc->GetString(nCol, nRow, 0, aVal);
+ printer.set(nRow, nCol, aVal);
+ }
+ }
+ printer.print("Data sheet content");
+ printer.clear();
+
+ ScDPObject* pDPObj = createDPFromRange(
+ m_pDoc, ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0), aFields, nFieldCount, false);
+
ScDPCollection* pDPs = m_pDoc->GetDPCollection();
bool bSuccess = pDPs->InsertNewTable(pDPObj);
CPPUNIT_ASSERT_MESSAGE("failed to insert a new datapilot object into document", bSuccess);
CPPUNIT_ASSERT_MESSAGE("there should be only one data pilot table.",
pDPs->GetCount() == 1);
- pDPObj->InvalidateData();
pDPObj->SetName(pDPs->CreateNewName());
bool bOverFlow = false;
@@ -823,41 +937,261 @@ void Test::testDataPilot()
pDPObj->Output(aOutRange.aStart);
aOutRange = pDPObj->GetOutRange();
- const ScAddress& s = aOutRange.aStart;
- const ScAddress& e = aOutRange.aEnd;
- printer.resize(e.Row() - s.Row() + 1, e.Col() - s.Col() + 1);
- SCROW nOutRowSize = SAL_N_ELEMENTS(aOutputCheck);
- SCCOL nOutColSize = SAL_N_ELEMENTS(aOutputCheck[0]);
- CPPUNIT_ASSERT_MESSAGE("Row size of the table output is not as expected.",
- nOutRowSize == (e.Row()-s.Row()+1));
- CPPUNIT_ASSERT_MESSAGE("Column size of the table output is not as expected.",
- nOutColSize == (e.Col()-s.Col()+1));
- for (SCROW nRow = 0; nRow < nOutRowSize; ++nRow)
{
- for (SCCOL nCol = 0; nCol < nOutColSize; ++nCol)
+ // Expected output table content. 0 = empty cell
+ const char* aOutputCheck[][5] = {
+ { "Sum - Score", "Group", 0, 0, 0 },
+ { "Name", "A", "B", "C", "Total Result" },
+ { "Andy", "30", 0, 0, "30" },
+ { "Bruce", "20", 0, 0, "20" },
+ { "Charlie", 0, "45", 0, "45" },
+ { "David", 0, "12", 0, "12" },
+ { "Edward", 0, 0, "8", "8" },
+ { "Frank", 0, 0, "15", "15" },
+ { "Total Result", "50", "57", "23", "130" }
+ };
+
+ bSuccess = checkDPTableOutput<5>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output");
+ CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
+ }
+
+ // Update the cell values.
+ double aData2[] = { 100, 200, 300, 400, 500, 600 };
+ for (size_t i = 0; i < SAL_N_ELEMENTS(aData2); ++i)
+ {
+ SCROW nRow = i + 1;
+ m_pDoc->SetValue(2, nRow, 0, aData2[i]);
+ }
+
+ printer.resize(nRow2 - nRow1 + 1, nCol2 - nCol1 + 1);
+ for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
+ {
+ for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
{
String aVal;
- m_pDoc->GetString(nCol + s.Col(), nRow + s.Row(), s.Tab(), aVal);
+ m_pDoc->GetString(nCol, nRow, 0, aVal);
+ printer.set(nRow, nCol, aVal);
+ }
+ }
+ printer.print("Data sheet content (modified)");
+ printer.clear();
+
+ // Now, create a copy of the datapilot object for the updated table, but
+ // don't clear the cache which should force the copy to use the old data
+ // from the cache.
+ ScDPObject* pDPObj2 = new ScDPObject(*pDPObj);
+ pDPs->FreeTable(pDPObj);
+ pDPs->InsertNewTable(pDPObj2);
+
+ aOutRange = pDPObj2->GetOutRange();
+ pDPObj2->ClearSource();
+ pDPObj2->Output(aOutRange.aStart);
+ {
+ // Expected output table content. 0 = empty cell
+ const char* aOutputCheck[][5] = {
+ { "Sum - Score", "Group", 0, 0, 0 },
+ { "Name", "A", "B", "C", "Total Result" },
+ { "Andy", "30", 0, 0, "30" },
+ { "Bruce", "20", 0, 0, "20" },
+ { "Charlie", 0, "45", 0, "45" },
+ { "David", 0, "12", 0, "12" },
+ { "Edward", 0, 0, "8", "8" },
+ { "Frank", 0, 0, "15", "15" },
+ { "Total Result", "50", "57", "23", "130" }
+ };
+
+ bSuccess = checkDPTableOutput<5>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output (from old cache)");
+ CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
+ }
+
+ // This time clear the cache to refresh the data from the source range.
+ CPPUNIT_ASSERT_MESSAGE("This datapilot should be based on sheet data.", pDPObj2->IsSheetData());
+ ScDPCollection::SheetCaches& rCaches = pDPs->GetSheetCaches();
+ const ScSheetSourceDesc* pDesc = pDPObj2->GetSheetDesc();
+ rCaches.removeCache(pDesc->GetSourceRange());
+ pDPObj2->ClearSource();
+ pDPObj2->Output(aOutRange.aStart);
+
+ {
+ // Expected output table content. 0 = empty cell
+ const char* aOutputCheck[][5] = {
+ { "Sum - Score", "Group", 0, 0, 0 },
+ { "Name", "A", "B", "C", "Total Result" },
+ { "Andy", "100", 0, 0, "100" },
+ { "Bruce", "200", 0, 0, "200" },
+ { "Charlie", 0, "300", 0, "300" },
+ { "David", 0, "400", 0, "400" },
+ { "Edward", 0, 0, "500", "500" },
+ { "Frank", 0, 0, "600", "600" },
+ { "Total Result", "300", "700", "1100", "2100" }
+ };
+
+ bSuccess = checkDPTableOutput<5>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output (refreshed)");
+ CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
+ }
+
+ pDPs->FreeTable(pDPObj2);
+ CPPUNIT_ASSERT_MESSAGE("There shouldn't be any data pilot table stored with the document.",
+ pDPs->GetCount() == 0);
+
+ m_pDoc->DeleteTab(1);
+ m_pDoc->DeleteTab(0);
+}
+
+void Test::testDataPilotFilters()
+{
+ m_pDoc->InsertTab(0, OUString(RTL_CONSTASCII_USTRINGPARAM("Data")));
+ m_pDoc->InsertTab(1, OUString(RTL_CONSTASCII_USTRINGPARAM("Table")));
+
+ // Dimension definition
+ DPFieldDef aFields[] = {
+ { "Name", sheet::DataPilotFieldOrientation_HIDDEN },
+ { "Group1", sheet::DataPilotFieldOrientation_HIDDEN },
+ { "Group2", sheet::DataPilotFieldOrientation_PAGE },
+ { "Val1", sheet::DataPilotFieldOrientation_DATA },
+ { "Val2", sheet::DataPilotFieldOrientation_DATA }
+ };
+
+ // Raw data
+ const char* aData[][5] = {
+ { "A", "1", "A", "1", "10" },
+ { "B", "1", "A", "1", "10" },
+ { "C", "1", "B", "1", "10" },
+ { "D", "1", "B", "1", "10" },
+ { "E", "2", "A", "1", "10" },
+ { "F", "2", "A", "1", "10" },
+ { "G", "2", "B", "1", "10" },
+ { "H", "2", "B", "1", "10" }
+ };
+
+ size_t nFieldCount = SAL_N_ELEMENTS(aFields);
+ size_t nDataCount = SAL_N_ELEMENTS(aData);
+
+ // Insert field names in row 0.
+ for (size_t i = 0; i < nFieldCount; ++i)
+ m_pDoc->SetString(static_cast<SCCOL>(i), 0, 0, OUString(aFields[i].pName, strlen(aFields[i].pName), RTL_TEXTENCODING_UTF8));
+
+ // Insert data into row 1 and downward.
+ for (size_t i = 0; i < nDataCount; ++i)
+ {
+ SCROW nRow = static_cast<SCROW>(i) + 1;
+ for (size_t j = 0; j < nFieldCount; ++j)
+ {
+ SCCOL nCol = static_cast<SCCOL>(j);
+ m_pDoc->SetString(
+ nCol, nRow, 0, OUString(aData[i][j], strlen(aData[i][j]), RTL_TEXTENCODING_UTF8));
+ }
+ }
+
+ SCROW nRow1 = 0, nRow2 = 0;
+ SCCOL nCol1 = 0, nCol2 = 0;
+ m_pDoc->GetDataArea(0, nCol1, nRow1, nCol2, nRow2, true, false);
+ CPPUNIT_ASSERT_MESSAGE("Data is expected to start from (col=0,row=0).", nCol1 == 0 && nRow1 == 0);
+ CPPUNIT_ASSERT_MESSAGE("Unexpected data range.",
+ nCol2 == static_cast<SCCOL>(nFieldCount - 1) && nRow2 == static_cast<SCROW>(nDataCount));
+
+ SheetPrinter printer(nRow2 - nRow1 + 1, nCol2 - nCol1 + 1);
+ for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
+ {
+ for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+ {
+ String aVal;
+ m_pDoc->GetString(nCol, nRow, 0, aVal);
printer.set(nRow, nCol, aVal);
- const char* p = aOutputCheck[nRow][nCol];
- if (p)
- {
- OUString aCheckVal = OUString::createFromAscii(p);
- bool bEqual = aCheckVal.equals(aVal);
- if (!bEqual)
- {
- cerr << "Expected: " << aCheckVal << " Actual: " << aVal << endl;
-// CPPUNIT_ASSERT_MESSAGE("Unexpected cell content.", false);
- }
- }
- else
- CPPUNIT_ASSERT_MESSAGE("Empty cell expected.", aVal.Len() == 0);
}
}
- printer.print("DataPilot table output");
+ printer.print("Data sheet content");
printer.clear();
- // Now, delete the datapilot object.
+ ScDPObject* pDPObj = createDPFromRange(
+ m_pDoc, ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0), aFields, nFieldCount, true);
+
+ ScDPCollection* pDPs = m_pDoc->GetDPCollection();
+ bool bSuccess = pDPs->InsertNewTable(pDPObj);
+ CPPUNIT_ASSERT_MESSAGE("failed to insert a new datapilot object into document", bSuccess);
+ CPPUNIT_ASSERT_MESSAGE("there should be only one data pilot table.",
+ pDPs->GetCount() == 1);
+ pDPObj->SetName(pDPs->CreateNewName());
+
+ bool bOverFlow = false;
+ ScRange aOutRange = pDPObj->GetNewOutputRange(bOverFlow);
+ CPPUNIT_ASSERT_MESSAGE("Table overflow!?", !bOverFlow);
+
+ pDPObj->Output(aOutRange.aStart);
+ aOutRange = pDPObj->GetOutRange();
+ {
+ // Expected output table content. 0 = empty cell
+ const char* aOutputCheck[][2] = {
+ { "Filter", 0 },
+ { "Group2", "- all -" },
+ { 0, 0 },
+ { "Data", 0 },
+ { "Sum - Val1", "8" },
+ { "Sum - Val2", "80" },
+ { "Total Sum - Val1", "8" },
+ { "Total Sum - Val2", "80" }
+ };
+
+ bSuccess = checkDPTableOutput<2>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output (unfiltered)");
+ CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
+ }
+
+ // Set current page of 'Group2' to 'A'.
+ ScDPSaveData aSaveData(*pDPObj->GetSaveData());
+ ScDPSaveDimension* pDim = aSaveData.GetDimensionByName(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("Group2")));
+ CPPUNIT_ASSERT_MESSAGE("Dimension not found", pDim);
+ OUString aPage(RTL_CONSTASCII_USTRINGPARAM("A"));
+ pDim->SetCurrentPage(&aPage);
+ pDPObj->SetSaveData(aSaveData);
+ pDPObj->Output(aOutRange.aStart);
+ aOutRange = pDPObj->GetOutRange();
+ {
+ // Expected output table content. 0 = empty cell
+ const char* aOutputCheck[][2] = {
+ { "Filter", 0 },
+ { "Group2", "A" },
+ { 0, 0 },
+ { "Data", 0 },
+ { "Sum - Val1", "4" },
+ { "Sum - Val2", "40" },
+ { "Total Sum - Val1", "4" },
+ { "Total Sum - Val2", "40" }
+ };
+
+ bSuccess = checkDPTableOutput<2>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output (filtered by page)");
+ CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
+ }
+
+ // Set query filter.
+ ScSheetSourceDesc aDesc(*pDPObj->GetSheetDesc());
+ ScQueryParam aQueryParam(aDesc.GetQueryParam());
+ CPPUNIT_ASSERT_MESSAGE("There should be at least one query entry.", aQueryParam.GetEntryCount() > 0);
+ ScQueryEntry& rEntry = aQueryParam.GetEntry(0);
+ rEntry.bDoQuery = true;
+ rEntry.nField = 1; // Group1
+ rEntry.nVal = 1;
+ aDesc.SetQueryParam(aQueryParam);
+ pDPObj->SetSheetDesc(aDesc);
+ pDPObj->Output(aOutRange.aStart);
+ aOutRange = pDPObj->GetOutRange();
+ {
+ // Expected output table content. 0 = empty cell
+ const char* aOutputCheck[][2] = {
+ { "Filter", 0 },
+ { "Group2", "A" },
+ { 0, 0 },
+ { "Data", 0 },
+ { "Sum - Val1", "2" },
+ { "Sum - Val2", "20" },
+ { "Total Sum - Val1", "2" },
+ { "Total Sum - Val2", "20" }
+ };
+
+ bSuccess = checkDPTableOutput<2>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output (filtered by query)");
+ CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
+ }
+
pDPs->FreeTable(pDPObj);
CPPUNIT_ASSERT_MESSAGE("There shouldn't be any data pilot table stored with the document.",
pDPs->GetCount() == 0);
@@ -1633,6 +1967,83 @@ void Test::testGraphicsInGroup()
m_pDoc->DeleteTab(0);
}
+void Test::testToggleRefFlag()
+{
+ // In this test, there is no need to insert formula string into a cell in
+ // the document, as ScRefFinder does not depend on the content of the
+ // document except for the sheet names.
+
+ OUString aTabName(RTL_CONSTASCII_USTRINGPARAM("Test"));
+ m_pDoc->InsertTab(0, aTabName);
+
+ {
+ // Calc A1: basic 2D reference
+
+ OUString aFormula(RTL_CONSTASCII_USTRINGPARAM("=B100"));
+ ScAddress aPos(1, 5, 0);
+ ScRefFinder aFinder(aFormula, aPos, m_pDoc, formula::FormulaGrammar::CONV_OOO);
+
+ // Original
+ CPPUNIT_ASSERT_MESSAGE("Does not equal the original text.", aFormula.equals(aFinder.GetText()));
+
+ // column relative / row relative -> column absolute / row absolute
+ aFinder.ToggleRel(0, aFormula.getLength());
+ aFormula = aFinder.GetText();
+ CPPUNIT_ASSERT_MESSAGE("Wrong conversion.", aFormula.equalsAscii("=$B$100"));
+
+ // column absolute / row absolute -> column relative / row absolute
+ aFinder.ToggleRel(0, aFormula.getLength());
+ aFormula = aFinder.GetText();
+ CPPUNIT_ASSERT_MESSAGE("Wrong conversion.", aFormula.equalsAscii("=B$100"));
+
+ // column relative / row absolute -> column absolute / row relative
+ aFinder.ToggleRel(0, aFormula.getLength());
+ aFormula = aFinder.GetText();
+ CPPUNIT_ASSERT_MESSAGE("Wrong conversion.", aFormula.equalsAscii("=$B100"));
+
+ // column absolute / row relative -> column relative / row relative
+ aFinder.ToggleRel(0, aFormula.getLength());
+ aFormula = aFinder.GetText();
+ CPPUNIT_ASSERT_MESSAGE("Wrong conversion.", aFormula.equalsAscii("=B100"));
+ }
+
+ {
+ // Excel R1C1: basic 2D reference
+
+ OUString aFormula(RTL_CONSTASCII_USTRINGPARAM("=R2C1"));
+ ScAddress aPos(3, 5, 0);
+ ScRefFinder aFinder(aFormula, aPos, m_pDoc, formula::FormulaGrammar::CONV_XL_R1C1);
+
+ // Original
+ CPPUNIT_ASSERT_MESSAGE("Does not equal the original text.", aFormula.equals(aFinder.GetText()));
+
+ // column absolute / row absolute -> column relative / row absolute
+ aFinder.ToggleRel(0, aFormula.getLength());
+ aFormula = aFinder.GetText();
+ CPPUNIT_ASSERT_MESSAGE("Wrong conversion.", aFormula.equalsAscii("=R2C[-3]"));
+
+ // column relative / row absolute - > column absolute / row relative
+ aFinder.ToggleRel(0, aFormula.getLength());
+ aFormula = aFinder.GetText();
+ CPPUNIT_ASSERT_MESSAGE("Wrong conversion.", aFormula.equalsAscii("=R[-4]C1"));
+
+ // column absolute / row relative -> column relative / row relative
+ aFinder.ToggleRel(0, aFormula.getLength());
+ aFormula = aFinder.GetText();
+ CPPUNIT_ASSERT_MESSAGE("Wrong conversion.", aFormula.equalsAscii("=R[-4]C[-3]"));
+
+ // column relative / row relative -> column absolute / row absolute
+ aFinder.ToggleRel(0, aFormula.getLength());
+ aFormula = aFinder.GetText();
+ CPPUNIT_ASSERT_MESSAGE("Wrong conversion.", aFormula.equalsAscii("=R2C1"));
+ }
+
+ // TODO: Add more test cases esp. for 3D references, Excel A1 syntax, and
+ // partial selection within formula string.
+
+ m_pDoc->DeleteTab(0);
+}
+
CPPUNIT_TEST_SUITE_REGISTRATION(Test);
}
diff --git a/sc/source/core/data/conditio.cxx b/sc/source/core/data/conditio.cxx
index 40390816128b..2668893ed4d3 100644
--- a/sc/source/core/data/conditio.cxx
+++ b/sc/source/core/data/conditio.cxx
@@ -1270,7 +1270,8 @@ ScConditionalFormat::ScConditionalFormat(const ScConditionalFormat& r) :
pAreas( NULL ),
nKey( r.nKey ),
ppEntries( NULL ),
- nEntryCount( r.nEntryCount )
+ nEntryCount( r.nEntryCount ),
+ pRanges( NULL )
{
if (nEntryCount)
{
@@ -1281,7 +1282,8 @@ ScConditionalFormat::ScConditionalFormat(const ScConditionalFormat& r) :
ppEntries[i]->SetParent(this);
}
}
- pRanges = new ScRangeList( *r.pRanges );
+ if (r.pRanges)
+ pRanges = new ScRangeList( *r.pRanges );
}
ScConditionalFormat* ScConditionalFormat::Clone(ScDocument* pNewDoc) const
@@ -1320,10 +1322,16 @@ sal_Bool ScConditionalFormat::EqualEntries( const ScConditionalFormat& r ) const
if ( ! (*ppEntries[i] == *r.ppEntries[i]) )
return false;
- if( *pRanges != *r.pRanges )
- return false;
+ if (pRanges)
+ {
+ if (r.pRanges)
+ return *pRanges == *r.pRanges;
+ else
+ return false;
+ }
- return true;
+ // pRanges is NULL, which means r.pRanges must be NULL.
+ return r.pRanges.Is() == false;
}
void ScConditionalFormat::AddRangeInfo( const ScRangeListRef& rRanges )
diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx
index ef456e98b123..9afb15ddfdd3 100644
--- a/sc/source/core/data/documen2.cxx
+++ b/sc/source/core/data/documen2.cxx
@@ -904,6 +904,9 @@ sal_Bool ScDocument::CopyTab( SCTAB nOldPos, SCTAB nNewPos, const ScMarkData* pO
pTab[nNewPos]->SetPageStyle( pTab[nOldPos]->GetPageStyle() );
pTab[nNewPos]->SetPendingRowHeights( pTab[nOldPos]->IsPendingRowHeights() );
+
+ // Copy the custom print range if exists.
+ pTab[nNewPos]->CopyPrintRange(*pTab[nOldPos]);
}
else
SetAutoCalc( bOldAutoCalc );
@@ -1127,53 +1130,6 @@ void ScDocument::SetError( SCCOL nCol, SCROW nRow, SCTAB nTab, const sal_uInt16
pTab[nTab]->SetError( nCol, nRow, nError );
}
-namespace {
-
-bool eraseUnusedSharedName(ScRangeName* pRangeName, ScTable* pTab[], sal_uInt16 nLevel)
-{
- if (!pRangeName)
- return false;
-
- ScRangeName::iterator itr = pRangeName->begin(), itrEnd = pRangeName->end();
- for (; itr != itrEnd; ++itr)
- {
- if (!itr->HasType(RT_SHARED))
- continue;
-
- String aName;
- itr->GetName(aName);
- aName.Erase(0, 6); // !!! vgl. Table4, FillFormula !!
- sal_uInt16 nInd = static_cast<sal_uInt16>(aName.ToInt32());
- if (nInd > nLevel)
- continue;
-
- sal_uInt16 nIndex = itr->GetIndex();
-
- bool bInUse = false;
- for (SCTAB j = 0; !bInUse && (j <= MAXTAB); ++j)
- {
- if (pTab[j])
- bInUse = pTab[j]->IsRangeNameInUse(0, 0, MAXCOL-1, MAXROW-1, nIndex);
- }
- if (!bInUse)
- {
- pRangeName->erase(itr);
- return true;
- }
- }
- return false;
-}
-
-}
-
-void ScDocument::EraseNonUsedSharedNames(sal_uInt16 nLevel)
-{
- if (!pRangeName)
- return;
- while (eraseUnusedSharedName(pRangeName, pTab, nLevel))
- ;
-}
-
// ----------------------------------------------------------------------------
void ScDocument::SetConsolidateDlgData( const ScConsolidateParam* pData )
diff --git a/sc/source/core/data/documen3.cxx b/sc/source/core/data/documen3.cxx
index 888b1a16d551..583ea6cc8956 100644
--- a/sc/source/core/data/documen3.cxx
+++ b/sc/source/core/data/documen3.cxx
@@ -238,6 +238,14 @@ ScDBData* ScDocument::GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nC
return NULL;
}
+ScDBData* ScDocument::GetFilterDBAtTable(SCTAB nTab) const
+{
+ if (pDBCollection)
+ return pDBCollection->GetFilterDBAtTable(nTab);
+ else
+ return NULL;
+}
+
ScDPCollection* ScDocument::GetDPCollection()
{
if (!pDPCollection)
diff --git a/sc/source/core/data/documen4.cxx b/sc/source/core/data/documen4.cxx
index 1958bf721a4c..b9c79e1c9ebf 100644
--- a/sc/source/core/data/documen4.cxx
+++ b/sc/source/core/data/documen4.cxx
@@ -296,42 +296,71 @@ void ScDocument::InsertTableOp(const ScTabOpParam& rParam, // Mehrfachopera
pTab[i]->PutCell( j, k, aRefCell.CloneWithoutNote( *this, ScAddress( j, k, i ), SC_CLONECELL_STARTLISTENING ) );
}
+namespace {
+
+bool setCacheTableReferenced(ScToken& rToken, ScExternalRefManager& rRefMgr)
+{
+ switch (rToken.GetType())
+ {
+ case svExternalSingleRef:
+ return rRefMgr.setCacheTableReferenced(
+ rToken.GetIndex(), rToken.GetString(), 1);
+ case svExternalDoubleRef:
+ {
+ const ScComplexRefData& rRef = rToken.GetDoubleRef();
+ size_t nSheets = rRef.Ref2.nTab - rRef.Ref1.nTab + 1;
+ return rRefMgr.setCacheTableReferenced(
+ rToken.GetIndex(), rToken.GetString(), nSheets);
+ }
+ case svExternalName:
+ /* TODO: external names aren't supported yet, but would
+ * have to be marked as well, if so. Mechanism would be
+ * different. */
+ DBG_ERRORFILE("ScDocument::MarkUsedExternalReferences: implement the svExternalName case!");
+ default:
+ ;
+ }
+ return false;
+}
+
+}
+
bool ScDocument::MarkUsedExternalReferences( ScTokenArray & rArr )
{
+ if (!rArr.GetLen())
+ return false;
+
+ ScExternalRefManager* pRefMgr = NULL;
+ rArr.Reset();
+ ScToken* t = NULL;
bool bAllMarked = false;
- if (rArr.GetLen())
+ while (!bAllMarked && (t = static_cast<ScToken*>(rArr.GetNextReferenceOrName())) != NULL)
{
- ScExternalRefManager* pRefMgr = NULL;
- rArr.Reset();
- ScToken* t;
- while (!bAllMarked && (t = static_cast<ScToken*>(rArr.GetNextReferenceOrName())) != NULL)
+ if (t->IsExternalRef())
+ {
+ if (!pRefMgr)
+ pRefMgr = GetExternalRefManager();
+
+ bAllMarked = setCacheTableReferenced(*t, *pRefMgr);
+ }
+ else if (t->GetType() == svIndex)
{
- if (t->IsExternalRef())
+ // this is a named range. Check if the range contains an external
+ // reference.
+ ScRangeData* pRangeData = GetRangeName()->findByIndex(t->GetIndex());
+ if (!pRangeData)
+ continue;
+
+ ScTokenArray* pArray = pRangeData->GetCode();
+ for (t = static_cast<ScToken*>(pArray->First()); t; t = static_cast<ScToken*>(pArray->Next()))
{
+ if (!t->IsExternalRef())
+ continue;
+
if (!pRefMgr)
pRefMgr = GetExternalRefManager();
- switch (t->GetType())
- {
- case svExternalSingleRef:
- bAllMarked = pRefMgr->setCacheTableReferenced(
- 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
- * have to be marked as well, if so. Mechanism would be
- * different. */
- DBG_ERRORFILE("ScDocument::MarkUsedExternalReferences: implement the svExternalName case!");
- break;
- default: break;
- }
+
+ bAllMarked = setCacheTableReferenced(*t, *pRefMgr);
}
}
}
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 8d236383dac2..b8f026503dc4 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -5422,7 +5422,14 @@ void ScDocument::SetSubTotalCellsDirty(const ScRange& rDirtyRange)
void ScDocument::EnableUndo( bool bVal )
{
- GetUndoManager()->EnableUndo(bVal);
+ // The undo manager increases lock count every time undo is disabled.
+ // Because of this, we shouldn't disable undo unless it's currently
+ // enabled, or else re-enabling it may not actually re-enable undo unless
+ // the lock count becomes zero.
+
+ if (bVal != GetUndoManager()->IsUndoEnabled())
+ GetUndoManager()->EnableUndo(bVal);
+
mbUndoEnabled = bVal;
}
diff --git a/sc/source/core/data/dpcachetable.cxx b/sc/source/core/data/dpcachetable.cxx
index 67b55e7f0155..b177acff7be7 100644
--- a/sc/source/core/data/dpcachetable.cxx
+++ b/sc/source/core/data/dpcachetable.cxx
@@ -73,6 +73,17 @@ static sal_Bool lcl_HasQueryEntry( const ScQueryParam& rParam )
// ----------------------------------------------------------------------------
+bool ScDPCacheTable::RowFlag::isActive() const
+{
+ return mbShowByFilter && mbShowByPage;
+}
+
+ScDPCacheTable::RowFlag::RowFlag() :
+ mbShowByFilter(true),
+ mbShowByPage(true)
+{
+}
+
ScDPCacheTable::FilterItem::FilterItem() :
mfValue(0.0),
mbHasValue(false)
@@ -158,14 +169,13 @@ ScDPCacheTable::Criterion::Criterion() :
// ----------------------------------------------------------------------------
-ScDPCacheTable::ScDPCacheTable(ScDPCache* pCache) :
+ScDPCacheTable::ScDPCacheTable(const ScDPCache* pCache) :
mpCache(pCache)
{
}
ScDPCacheTable::~ScDPCacheTable()
{
- delete mpCache;
}
sal_Int32 ScDPCacheTable::getRowSize() const
@@ -181,13 +191,13 @@ sal_Int32 ScDPCacheTable::getColSize() const
void ScDPCacheTable::fillTable(
const ScQueryParam& rQuery, bool* pSpecial, bool bIgnoreEmptyRows, bool bRepeatIfEmpty)
{
- const SCROW nRowCount = getRowSize();
- const SCCOL nColCount = (SCCOL) getColSize();
- if ( nRowCount <= 0 || nColCount <= 0)
+ const SCROW nRowCount = getRowSize();
+ const SCCOL nColCount = (SCCOL) getColSize();
+ if ( nRowCount <= 0 || nColCount <= 0)
return;
- maRowsVisible.clear();
- maRowsVisible.reserve(nRowCount);
+ maRowFlags.clear();
+ maRowFlags.reserve(nRowCount);
// Initialize field entries container.
maFieldEntries.clear();
@@ -199,7 +209,7 @@ void ScDPCacheTable::fillTable(
SCROW nMemCount = getCache()->GetDimMemberCount( nCol );
if ( nMemCount )
{
- std::vector< SCROW > pAdded( nMemCount, -1 );
+ std::vector<SCROW> aAdded( nMemCount, -1 );
for (SCROW nRow = 0; nRow < nRowCount; ++nRow )
{
@@ -207,24 +217,27 @@ void ScDPCacheTable::fillTable(
SCROW nOrder = getOrder( nCol, nIndex );
if ( nCol == 0 )
- maRowsVisible.push_back(false);
+ {
+ maRowFlags.push_back(RowFlag());
+ maRowFlags.back().mbShowByFilter = false;
+ }
if ( lcl_HasQueryEntry(rQuery) &&
!getCache()->ValidQuery( nRow , rQuery, pSpecial ) )
continue;
if ( bIgnoreEmptyRows && getCache()->IsRowEmpty( nRow ) )
continue;
- // Insert a new row into cache table.
+
if ( nCol == 0 )
- maRowsVisible.back() = true;
+ maRowFlags.back().mbShowByFilter = true;
- pAdded[nOrder] = nIndex;
+ aAdded[nOrder] = nIndex;
}
maFieldEntries.push_back( vector<SCROW>() );
for ( SCROW nRow = 0; nRow < nMemCount; nRow++ )
{
- if ( pAdded[nRow] != -1 )
- maFieldEntries.back().push_back( pAdded[nRow] );
+ if ( aAdded[nRow] != -1 )
+ maFieldEntries.back().push_back( aAdded[nRow] );
}
}
}
@@ -237,8 +250,8 @@ void ScDPCacheTable::fillTable()
if ( nRowCount <= 0 || nColCount <= 0)
return;
- maRowsVisible.clear();
- maRowsVisible.reserve(nRowCount);
+ maRowFlags.clear();
+ maRowFlags.reserve(nRowCount);
// Initialize field entries container.
@@ -259,8 +272,10 @@ void ScDPCacheTable::fillTable()
SCROW nOrder = getOrder( nCol, nIndex );
if ( nCol == 0 )
- maRowsVisible.push_back(true);
-
+ {
+ maRowFlags.push_back(RowFlag());
+ maRowFlags.back().mbShowByFilter = true;
+ }
pAdded[nOrder] = nIndex;
}
@@ -276,24 +291,24 @@ void ScDPCacheTable::fillTable()
bool ScDPCacheTable::isRowActive(sal_Int32 nRow) const
{
- if (nRow < 0 || static_cast<size_t>(nRow) >= maRowsVisible.size())
+ if (nRow < 0 || static_cast<size_t>(nRow) >= maRowFlags.size())
// row index out of bound
return false;
- return maRowsVisible[nRow];
+ return maRowFlags[nRow].isActive();
}
void ScDPCacheTable::filterByPageDimension(const vector<Criterion>& rCriteria, const boost::unordered_set<sal_Int32>& rRepeatIfEmptyDims)
{
sal_Int32 nRowSize = getRowSize();
- if (nRowSize != static_cast<sal_Int32>(maRowsVisible.size()))
+ if (nRowSize != static_cast<sal_Int32>(maRowFlags.size()))
{
// sizes of the two tables differ!
return;
}
for (sal_Int32 nRow = 0; nRow < nRowSize; ++nRow)
- maRowsVisible[nRow] = isRowQualified(nRow, rCriteria, rRepeatIfEmptyDims);
+ maRowFlags[nRow].mbShowByPage = isRowQualified(nRow, rCriteria, rRepeatIfEmptyDims);
}
const ScDPItemData* ScDPCacheTable::getCell(SCCOL nCol, SCROW nRow, bool bRepeatIfEmpty) const
@@ -359,7 +374,7 @@ void ScDPCacheTable::filterTable(const vector<Criterion>& rCriteria, Sequence< S
for (sal_Int32 nRow = 0; nRow < nRowSize; ++nRow)
{
- if (!maRowsVisible[nRow])
+ if (!maRowFlags[nRow].isActive())
// This row is filtered out.
continue;
@@ -401,8 +416,7 @@ SCROW ScDPCacheTable::getOrder(long nDim, SCROW nIndex) const
void ScDPCacheTable::clear()
{
maFieldEntries.clear();
- maRowsVisible.clear();
- delete mpCache;
+ maRowFlags.clear();
mpCache = NULL;
}
@@ -411,9 +425,8 @@ bool ScDPCacheTable::empty() const
return mpCache == NULL || maFieldEntries.empty();
}
-void ScDPCacheTable::setCache(ScDPCache* p)
+void ScDPCacheTable::setCache(const ScDPCache* p)
{
- delete mpCache;
mpCache = p;
}
@@ -448,9 +461,4 @@ const ScDPCache* ScDPCacheTable::getCache() const
return mpCache;
}
-ScDPCache* ScDPCacheTable::getCache()
-{
- return mpCache;
-}
-
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx
index 97e2f0db1bbc..7f5abef802ea 100644
--- a/sc/source/core/data/dpobject.cxx
+++ b/sc/source/core/data/dpobject.cxx
@@ -54,6 +54,7 @@
#include "dpglobal.hxx"
#include "globstr.hrc"
#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/sdb/XCompletedExecution.hpp>
#include <com/sun/star/sheet/GeneralFunction.hpp>
#include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
@@ -70,13 +71,15 @@
#include <com/sun/star/sheet/XDrillDownDataSupplier.hpp>
#include <comphelper/processfactory.hxx>
+#include <comphelper/types.hxx>
#include <sal/macros.h>
#include <tools/debug.hxx>
#include <tools/diagnose_ex.h>
#include <svl/zforlist.hxx> // IsNumberFormat
+#include <vcl/msgbox.hxx>
#include <vector>
-#include <stdio.h>
+#include <memory>
using namespace com::sun::star;
using ::std::vector;
@@ -95,6 +98,13 @@ using ::com::sun::star::sheet::XDimensionsSupplier;
using ::com::sun::star::beans::XPropertySet;
using ::rtl::OUString;
+#define SC_SERVICE_ROWSET "com.sun.star.sdb.RowSet"
+#define SC_SERVICE_INTHANDLER "com.sun.star.task.InteractionHandler"
+
+#define SC_DBPROP_DATASOURCENAME "DataSourceName"
+#define SC_DBPROP_COMMAND "Command"
+#define SC_DBPROP_COMMANDTYPE "CommandType"
+
// -----------------------------------------------------------------------
#define SCDPSOURCE_SERVICE "com.sun.star.sheet.DataPilotSource"
@@ -417,7 +427,7 @@ ScDPTableData* ScDPObject::GetTableData()
OSL_FAIL("no source descriptor");
pSheetDesc = new ScSheetSourceDesc(pDoc); // dummy defaults
}
- ScDPCache* pCache = pSheetDesc->CreateCache();
+ const ScDPCache* pCache = pSheetDesc->CreateCache();
if (pCache)
pData.reset(new ScSheetDPData(pDoc, *pSheetDesc, pCache));
}
@@ -1843,17 +1853,20 @@ sal_Bool ScDPObject::FillOldParam(ScPivotParam& rParam) const
rParam.nTab = aOutRange.aStart.Tab();
// ppLabelArr / nLabels is not changed
- SCCOL nColAdd = pSheetDesc->GetSourceRange().aStart.Col();
+ SCCOL nSrcColOffset = 0;
+ if (IsSheetData())
+ // source data column offset is only for internal sheet source.
+ nSrcColOffset = pSheetDesc->GetSourceRange().aStart.Col();
bool bAddData = ( lcl_GetDataGetOrientation( xSource ) == sheet::DataPilotFieldOrientation_HIDDEN );
lcl_FillOldFields(
- rParam.maPageFields, xSource, sheet::DataPilotFieldOrientation_PAGE, nColAdd, false);
+ rParam.maPageFields, xSource, sheet::DataPilotFieldOrientation_PAGE, nSrcColOffset, false);
lcl_FillOldFields(
- rParam.maColFields, xSource, sheet::DataPilotFieldOrientation_COLUMN, nColAdd, bAddData);
+ rParam.maColFields, xSource, sheet::DataPilotFieldOrientation_COLUMN, nSrcColOffset, bAddData);
lcl_FillOldFields(
- rParam.maRowFields, xSource, sheet::DataPilotFieldOrientation_ROW, nColAdd, false);
+ rParam.maRowFields, xSource, sheet::DataPilotFieldOrientation_ROW, nSrcColOffset, false);
lcl_FillOldFields(
- rParam.maDataFields, xSource, sheet::DataPilotFieldOrientation_DATA, nColAdd, false);
+ rParam.maDataFields, xSource, sheet::DataPilotFieldOrientation_DATA, nSrcColOffset, false);
uno::Reference<beans::XPropertySet> xProp( xSource, uno::UNO_QUERY );
if (xProp.is())
@@ -2383,15 +2396,153 @@ uno::Reference<sheet::XDimensionsSupplier> ScDPObject::CreateSource( const ScDPS
return xRet;
}
-// ----------------------------------------------------------------------------
+ScDPCollection::SheetCaches::SheetCaches(ScDocument* pDoc) : mpDoc(pDoc) {}
+
+const ScDPCache* ScDPCollection::SheetCaches::getCache(const ScRange& rRange)
+{
+ CachesType::const_iterator itr = maCaches.find(rRange);
+ if (itr != maCaches.end())
+ // already cached.
+ return itr->second;
+
+ ::std::auto_ptr<ScDPCache> pCache(new ScDPCache(mpDoc));
+ pCache->InitFromDoc(mpDoc, rRange);
+ const ScDPCache* p = pCache.get();
+ maCaches.insert(rRange, pCache);
+ return p;
+}
+
+void ScDPCollection::SheetCaches::removeCache(const ScRange& rRange)
+{
+ CachesType::iterator itr = maCaches.find(rRange);
+ if (itr != maCaches.end())
+ maCaches.erase(itr);
+}
+
+ScDPCollection::NameCaches::NameCaches(ScDocument* pDoc) : mpDoc(pDoc) {}
+
+const ScDPCache* ScDPCollection::NameCaches::getCache(const OUString& rName, const ScRange& rRange)
+{
+ CachesType::const_iterator itr = maCaches.find(rName);
+ if (itr != maCaches.end())
+ // already cached.
+ return itr->second;
+
+ ::std::auto_ptr<ScDPCache> pCache(new ScDPCache(mpDoc));
+ pCache->InitFromDoc(mpDoc, rRange);
+ const ScDPCache* p = pCache.get();
+ maCaches.insert(rName, pCache);
+ return p;
+}
+
+void ScDPCollection::NameCaches::removeCache(const OUString& rName)
+{
+ CachesType::iterator itr = maCaches.find(rName);
+ if (itr != maCaches.end())
+ maCaches.erase(itr);
+}
+
+ScDPCollection::DBType::DBType(sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand) :
+ mnSdbType(nSdbType), maDBName(rDBName), maCommand(rCommand) {}
+
+bool ScDPCollection::DBType::less::operator() (const DBType& left, const DBType& right) const
+{
+ return left < right;
+}
+
+ScDPCollection::DBCaches::DBCaches(ScDocument* pDoc) : mpDoc(pDoc) {}
+
+const ScDPCache* ScDPCollection::DBCaches::getCache(sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand)
+{
+ DBType aType(nSdbType, rDBName, rCommand);
+ CachesType::const_iterator itr = maCaches.find(aType);
+ if (itr != maCaches.end())
+ // already cached.
+ return itr->second;
+
+ uno::Reference<sdbc::XRowSet> xRowSet ;
+ try
+ {
+ xRowSet = uno::Reference<sdbc::XRowSet>(
+ comphelper::getProcessServiceFactory()->createInstance(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( SC_SERVICE_ROWSET )) ),
+ uno::UNO_QUERY);
+ uno::Reference<beans::XPropertySet> xRowProp( xRowSet, uno::UNO_QUERY );
+ DBG_ASSERT( xRowProp.is(), "can't get RowSet" );
+ if ( xRowProp.is() )
+ {
+ //
+ // set source parameters
+ //
+ uno::Any aAny;
+ aAny <<= rDBName;
+ xRowProp->setPropertyValue(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_DBPROP_DATASOURCENAME)), aAny );
+
+ aAny <<= rCommand;
+ xRowProp->setPropertyValue(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_DBPROP_COMMAND)), aAny );
+
+ aAny <<= nSdbType;
+ xRowProp->setPropertyValue(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_DBPROP_COMMANDTYPE)), aAny );
+
+ uno::Reference<sdb::XCompletedExecution> xExecute( xRowSet, uno::UNO_QUERY );
+ if ( xExecute.is() )
+ {
+ uno::Reference<task::XInteractionHandler> xHandler(
+ comphelper::getProcessServiceFactory()->createInstance(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( SC_SERVICE_INTHANDLER )) ),
+ uno::UNO_QUERY);
+ xExecute->executeWithCompletion( xHandler );
+ }
+ else
+ xRowSet->execute();
+ }
+ }
+ catch ( sdbc::SQLException& rError )
+ {
+ //! store error message
+ InfoBox aInfoBox( 0, String(rError.Message) );
+ aInfoBox.Execute();
+ return NULL;
+ }
+ catch ( uno::Exception& )
+ {
+ OSL_FAIL("Unexpected exception in database");
+ return NULL;
+ }
+
+ ::std::auto_ptr<ScDPCache> pCache(new ScDPCache(mpDoc));
+ SvNumberFormatter aFormat(mpDoc->GetServiceManager(), ScGlobal::eLnge);
+ pCache->InitFromDataBase(xRowSet, *aFormat.GetNullDate());
+ ::comphelper::disposeComponent(xRowSet);
+ const ScDPCache* p = pCache.get();
+ maCaches.insert(aType, pCache);
+ return p;
+}
+
+void ScDPCollection::DBCaches::removeCache(sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand)
+{
+ DBType aType(nSdbType, rDBName, rCommand);
+ CachesType::iterator itr = maCaches.find(aType);
+ if (itr != maCaches.end())
+ maCaches.erase(itr);
+}
ScDPCollection::ScDPCollection(ScDocument* pDocument) :
- pDoc( pDocument )
+ pDoc( pDocument ),
+ maSheetCaches(pDocument),
+ maNameCaches(pDocument),
+ maDBCaches(pDocument)
{
}
ScDPCollection::ScDPCollection(const ScDPCollection& r) :
- pDoc(r.pDoc)
+ pDoc(r.pDoc),
+ maSheetCaches(r.pDoc),
+ maNameCaches(r.pDoc),
+ maDBCaches(r.pDoc)
{
}
@@ -2584,4 +2735,30 @@ bool ScDPCollection::HasDPTable(SCCOL nCol, SCROW nRow, SCTAB nTab) const
return pMergeAttr->HasDPTable();
}
+ScDPCollection::SheetCaches& ScDPCollection::GetSheetCaches()
+{
+ return maSheetCaches;
+}
+
+ScDPCollection::NameCaches& ScDPCollection::GetNameCaches()
+{
+ return maNameCaches;
+}
+
+ScDPCollection::DBCaches& ScDPCollection::GetDBCaches()
+{
+ return maDBCaches;
+}
+
+bool operator<(const ScDPCollection::DBType& left, const ScDPCollection::DBType& right)
+{
+ if (left.mnSdbType != right.mnSdbType)
+ return left.mnSdbType < right.mnSdbType;
+
+ if (!left.maDBName.equals(right.maDBName))
+ return left.maDBName < right.maDBName;
+
+ return left.maCommand < right.maCommand;
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/dpoutput.cxx b/sc/source/core/data/dpoutput.cxx
index c0455819285c..8351c2f3dd28 100644
--- a/sc/source/core/data/dpoutput.cxx
+++ b/sc/source/core/data/dpoutput.cxx
@@ -56,7 +56,6 @@
#include "scresid.hxx"
#include "unonames.hxx"
#include "sc.hrc"
-#include "scdpoutputimpl.hxx"
#include "dpglobal.hxx"
#include <com/sun/star/beans/XPropertySet.hpp>
@@ -83,15 +82,16 @@ using ::rtl::OUString;
#define DP_PROP_POSITION "Position"
#define DP_PROP_USEDHIERARCHY "UsedHierarchy"
#define DP_PROP_ISDATALAYOUT "IsDataLayoutDimension"
-#define DP_PROP_NUMBERFORMAT "NumberFormat"
#define DP_PROP_FILTER "Filter"
#define DP_PROP_COLUMNGRAND "ColumnGrand"
#define DP_PROP_ROWGRAND "RowGrand"
#define DP_PROP_SUBTOTALS "SubTotals"
-// -----------------------------------------------------------------------
+#define SC_DP_FRAME_INNER_BOLD 20
+#define SC_DP_FRAME_OUTER_BOLD 40
+
+#define SC_DP_FRAME_COLOR Color(0,0,0) //( 0x20, 0x40, 0x68 )
-//! dynamic!!!
#define SC_DPOUT_MAXLEVELS 256
struct ScDPOutLevelData
@@ -121,7 +121,187 @@ struct ScDPOutLevelData
//! bug (73840) in uno::Sequence - copy and then assign doesn't work!
};
-// -----------------------------------------------------------------------
+namespace {
+
+bool lcl_compareColfuc ( SCCOL i, SCCOL j) { return (i<j); }
+bool lcl_compareRowfuc ( SCROW i, SCROW j) { return (i<j); }
+
+class ScDPOutputImpl
+{
+ ScDocument* mpDoc;
+ sal_uInt16 mnTab;
+ ::std::vector< bool > mbNeedLineCols;
+ ::std::vector< SCCOL > mnCols;
+
+ ::std::vector< bool > mbNeedLineRows;
+ ::std::vector< SCROW > mnRows;
+
+ SCCOL mnTabStartCol;
+ SCROW mnTabStartRow;
+ SCCOL mnMemberStartCol;
+ SCROW mnMemberStartRow;
+
+ SCCOL mnDataStartCol;
+ SCROW mnDataStartRow;
+ SCCOL mnTabEndCol;
+ SCROW mnTabEndRow;
+
+public:
+ ScDPOutputImpl( ScDocument* pDoc, sal_uInt16 nTab,
+ SCCOL nTabStartCol,
+ SCROW nTabStartRow,
+ SCCOL nMemberStartCol,
+ SCROW nMemberStartRow,
+ SCCOL nDataStartCol,
+ SCROW nDataStartRow,
+ SCCOL nTabEndCol,
+ SCROW nTabEndRow );
+ bool AddRow( SCROW nRow );
+ bool AddCol( SCCOL nCol );
+
+ void OutputDataArea();
+ void OutputBlockFrame ( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, bool bHori = false );
+
+};
+
+void ScDPOutputImpl::OutputDataArea()
+{
+ AddRow( mnDataStartRow );
+ AddCol( mnDataStartCol );
+
+ mnCols.push_back( mnTabEndCol+1); //set last row bottom
+ mnRows.push_back( mnTabEndRow+1); //set last col bottom
+
+ bool bAllRows = ( ( mnTabEndRow - mnDataStartRow + 2 ) == (SCROW) mnRows.size() );
+
+ std::sort( mnCols.begin(), mnCols.end(), lcl_compareColfuc );
+ std::sort( mnRows.begin(), mnRows.end(), lcl_compareRowfuc );
+
+ for( SCCOL nCol = 0; nCol < (SCCOL)mnCols.size()-1; nCol ++ )
+ {
+ if ( !bAllRows )
+ {
+ if ( nCol < (SCCOL)mnCols.size()-2)
+ {
+ for ( SCROW i = nCol%2; i < (SCROW)mnRows.size()-2; i +=2 )
+ OutputBlockFrame( mnCols[nCol], mnRows[i], mnCols[nCol+1]-1, mnRows[i+1]-1 );
+ if ( mnRows.size()>=2 )
+ OutputBlockFrame( mnCols[nCol], mnRows[mnRows.size()-2], mnCols[nCol+1]-1, mnRows[mnRows.size()-1]-1 );
+ }
+ else
+ {
+ for ( SCROW i = 0 ; i < (SCROW)mnRows.size()-1; i++ )
+ OutputBlockFrame( mnCols[nCol], mnRows[i], mnCols[nCol+1]-1, mnRows[i+1]-1 );
+ }
+ }
+ else
+ OutputBlockFrame( mnCols[nCol], mnRows.front(), mnCols[nCol+1]-1, mnRows.back()-1, bAllRows );
+ }
+ //out put rows area outer framer
+ if ( mnTabStartCol != mnDataStartCol )
+ {
+ if ( mnTabStartRow != mnDataStartRow )
+ OutputBlockFrame( mnTabStartCol, mnTabStartRow, mnDataStartCol-1, mnDataStartRow-1 );
+ OutputBlockFrame( mnTabStartCol, mnDataStartRow, mnDataStartCol-1, mnTabEndRow );
+ }
+ //out put cols area outer framer
+ OutputBlockFrame( mnDataStartCol, mnTabStartRow, mnTabEndCol, mnDataStartRow-1 );
+}
+
+ScDPOutputImpl::ScDPOutputImpl( ScDocument* pDoc, sal_uInt16 nTab,
+ SCCOL nTabStartCol,
+ SCROW nTabStartRow,
+ SCCOL nMemberStartCol,
+ SCROW nMemberStartRow,
+ SCCOL nDataStartCol,
+ SCROW nDataStartRow,
+ SCCOL nTabEndCol,
+ SCROW nTabEndRow ):
+ mpDoc( pDoc ),
+ mnTab( nTab ),
+ mnTabStartCol( nTabStartCol ),
+ mnTabStartRow( nTabStartRow ),
+ mnMemberStartCol( nMemberStartCol),
+ mnMemberStartRow( nMemberStartRow),
+ mnDataStartCol ( nDataStartCol ),
+ mnDataStartRow ( nDataStartRow ),
+ mnTabEndCol( nTabEndCol ),
+ mnTabEndRow( nTabEndRow )
+{
+ mbNeedLineCols.resize( nTabEndCol-nDataStartCol+1, false );
+ mbNeedLineRows.resize( nTabEndRow-nDataStartRow+1, false );
+
+}
+
+bool ScDPOutputImpl::AddRow( SCROW nRow )
+{
+ if ( !mbNeedLineRows[ nRow - mnDataStartRow ] )
+ {
+ mbNeedLineRows[ nRow - mnDataStartRow ] = true;
+ mnRows.push_back( nRow );
+ return true;
+ }
+ else
+ return false;
+}
+
+bool ScDPOutputImpl::AddCol( SCCOL nCol )
+{
+
+ if ( !mbNeedLineCols[ nCol - mnDataStartCol ] )
+ {
+ mbNeedLineCols[ nCol - mnDataStartCol ] = true;
+ mnCols.push_back( nCol );
+ return true;
+ }
+ else
+ return false;
+}
+
+void ScDPOutputImpl::OutputBlockFrame ( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, bool bHori )
+{
+ Color color = SC_DP_FRAME_COLOR;
+ ::editeng::SvxBorderLine aLine( &color, SC_DP_FRAME_INNER_BOLD );
+ ::editeng::SvxBorderLine aOutLine( &color, SC_DP_FRAME_OUTER_BOLD );
+
+ SvxBoxItem aBox( ATTR_BORDER );
+
+ if ( nStartCol == mnTabStartCol )
+ aBox.SetLine(&aOutLine, BOX_LINE_LEFT);
+ else
+ aBox.SetLine(&aLine, BOX_LINE_LEFT);
+
+ if ( nStartRow == mnTabStartRow )
+ aBox.SetLine(&aOutLine, BOX_LINE_TOP);
+ else
+ aBox.SetLine(&aLine, BOX_LINE_TOP);
+
+ if ( nEndCol == mnTabEndCol ) //bottom row
+ aBox.SetLine(&aOutLine, BOX_LINE_RIGHT);
+ else
+ aBox.SetLine(&aLine, BOX_LINE_RIGHT);
+
+ if ( nEndRow == mnTabEndRow ) //bottom
+ aBox.SetLine(&aOutLine, BOX_LINE_BOTTOM);
+ else
+ aBox.SetLine(&aLine, BOX_LINE_BOTTOM);
+
+
+ SvxBoxInfoItem aBoxInfo( ATTR_BORDER_INNER );
+ aBoxInfo.SetValid(VALID_VERT,false );
+ if ( bHori )
+ {
+ aBoxInfo.SetValid(VALID_HORI,sal_True);
+ aBoxInfo.SetLine( &aLine, BOXINFO_LINE_HORI );
+ }
+ else
+ aBoxInfo.SetValid(VALID_HORI,false );
+
+ aBoxInfo.SetValid(VALID_DISTANCE,false);
+
+ mpDoc->ApplyFrameAreaTab( ScRange( nStartCol, nStartRow, mnTab, nEndCol, nEndRow , mnTab ), &aBox, &aBoxInfo );
+
+}
void lcl_SetStyleById( ScDocument* pDoc, SCTAB nTab,
SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
@@ -214,7 +394,7 @@ void lcl_FillNumberFormats( sal_uInt32*& rFormats, long& rCount,
aDataNames[nDataCount] = String( xDimName->getName() );
long nFormat = ScUnoHelpFunctions::GetLongProperty(
xDimProp,
- rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(DP_PROP_NUMBERFORMAT)) );
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_NUMFMT)) );
nDataFormats[nDataCount] = nFormat;
if ( nFormat != 0 )
bAnySet = sal_True;
@@ -280,7 +460,7 @@ sal_uInt32 lcl_GetFirstNumberFormat( const uno::Reference<container::XIndexAcces
{
long nFormat = ScUnoHelpFunctions::GetLongProperty(
xDimProp,
- rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(DP_PROP_NUMBERFORMAT)) );
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_NUMFMT)) );
return nFormat; // use format from first found data dimension
}
@@ -349,8 +529,10 @@ uno::Sequence<sheet::MemberResult> lcl_GetSelectedPageAsResult( const uno::Refer
return aRet;
}
+}
+
ScDPOutput::ScDPOutput( ScDocument* pD, const uno::Reference<sheet::XDimensionsSupplier>& xSrc,
- const ScAddress& rPos, sal_Bool bFilter ) :
+ const ScAddress& rPos, bool bFilter ) :
pDoc( pD ),
xSource( xSrc ),
aStartPos( rPos ),
@@ -526,7 +708,7 @@ ScDPOutput::ScDPOutput( ScDocument* pD, const uno::Reference<sheet::XDimensionsS
}
catch (uno::RuntimeException&)
{
- bResultsError = sal_True;
+ bResultsError = true;
}
}
@@ -618,7 +800,7 @@ void ScDPOutput::HeaderCell( SCCOL nCol, SCROW nRow, SCTAB nTab,
if ( nFlags & sheet::MemberResultFlags::SUBTOTAL )
{
- OutputImpl outputimp( pDoc, nTab,
+ ScDPOutputImpl outputimp( pDoc, nTab,
nTabStartCol, nTabStartRow, nMemberStartCol, nMemberStartRow,
nDataStartCol, nDataStartRow, nTabEndCol, nTabEndRow );
//! limit frames to horizontal or vertical?
@@ -695,7 +877,7 @@ void ScDPOutput::CalcSizes()
if ( aStartPos.Col() + nRowFieldCount + nColCount - 1 > MAXCOL ||
aStartPos.Row() + nPageSize + nHeaderSize + nColFieldCount + nRowCount > MAXROW )
{
- bSizeOverflow = sal_True;
+ bSizeOverflow = true;
}
nTabStartCol = aStartPos.Col();
@@ -715,7 +897,7 @@ void ScDPOutput::CalcSizes()
nTabEndRow = nDataStartRow + (SCROW)nRowCount - 1;
else
nTabEndRow = nDataStartRow; // single row will remain empty
- bSizesValid = sal_True;
+ bSizesValid = true;
}
}
@@ -838,7 +1020,7 @@ void ScDPOutput::Output()
STR_PIVOT_STYLE_INNER );
// output column headers:
- OutputImpl outputimp( pDoc, nTab,
+ ScDPOutputImpl outputimp( pDoc, nTab,
nTabStartCol, nTabStartRow, nMemberStartCol, nMemberStartRow,
nDataStartCol, nDataStartRow, nTabEndCol, nTabEndRow );
for (nField=0; nField<nColFieldCount; nField++)
diff --git a/sc/source/core/data/dpsdbtab.cxx b/sc/source/core/data/dpsdbtab.cxx
index 7eeb4b93e284..72c0f06911b1 100644
--- a/sc/source/core/data/dpsdbtab.cxx
+++ b/sc/source/core/data/dpsdbtab.cxx
@@ -33,23 +33,6 @@
// INCLUDE --------------------------------------------------------------
-#include <tools/debug.hxx>
-#include <vcl/msgbox.hxx>
-#include <svl/zforlist.hxx>
-#include <comphelper/processfactory.hxx>
-#include <comphelper/types.hxx>
-
-#include <com/sun/star/sheet/DataImportMode.hpp>
-#include <com/sun/star/beans/XPropertySet.hpp>
-#include <com/sun/star/sdb/CommandType.hpp>
-#include <com/sun/star/sdb/XCompletedExecution.hpp>
-#include <com/sun/star/sdbc/DataType.hpp>
-#include <com/sun/star/sdbc/XRow.hpp>
-#include <com/sun/star/sdbc/XRowSet.hpp>
-#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
-#include <com/sun/star/lang/XMultiServiceFactory.hpp>
-#include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
-
#include "dpsdbtab.hxx"
#include "collect.hxx"
#include "global.hxx"
@@ -59,100 +42,41 @@
#include "document.hxx"
#include "dpobject.hxx"
+#include <com/sun/star/sheet/DataImportMode.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+
using namespace com::sun::star;
using ::std::vector;
using ::com::sun::star::uno::Sequence;
-using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Any;
-using ::com::sun::star::uno::UNO_QUERY;
-#define SC_SERVICE_ROWSET "com.sun.star.sdb.RowSet"
-#define SC_SERVICE_INTHANDLER "com.sun.star.task.InteractionHandler"
-
-//! move to a header file?
-#define SC_DBPROP_DATASOURCENAME "DataSourceName"
-#define SC_DBPROP_COMMAND "Command"
-#define SC_DBPROP_COMMANDTYPE "CommandType"
-
-ScDPCache* ScImportSourceDesc::CreateCache() const
+sal_Int32 ScImportSourceDesc::GetCommandType() const
{
- if (!mpDoc)
- return NULL;
-
sal_Int32 nSdbType = -1;
switch ( nType )
{
- case sheet::DataImportMode_SQL: nSdbType = sdb::CommandType::COMMAND; break;
- case sheet::DataImportMode_TABLE: nSdbType = sdb::CommandType::TABLE; break;
- case sheet::DataImportMode_QUERY: nSdbType = sdb::CommandType::QUERY; break;
- default:
- return NULL;
+ case sheet::DataImportMode_SQL: nSdbType = sdb::CommandType::COMMAND; break;
+ case sheet::DataImportMode_TABLE: nSdbType = sdb::CommandType::TABLE; break;
+ case sheet::DataImportMode_QUERY: nSdbType = sdb::CommandType::QUERY; break;
+ default:
+ ;
}
+ return nSdbType;
+}
- ScDPCache* pCache = new ScDPCache(mpDoc);
-
- uno::Reference<sdbc::XRowSet> xRowSet ;
- try
- {
- xRowSet = uno::Reference<sdbc::XRowSet>(
- comphelper::getProcessServiceFactory()->createInstance(
- rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( SC_SERVICE_ROWSET )) ),
- uno::UNO_QUERY);
- uno::Reference<beans::XPropertySet> xRowProp( xRowSet, uno::UNO_QUERY );
- DBG_ASSERT( xRowProp.is(), "can't get RowSet" );
- if ( xRowProp.is() )
- {
- //
- // set source parameters
- //
- uno::Any aAny;
- aAny <<= rtl::OUString( aDBName );
- xRowProp->setPropertyValue(
- rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_DBPROP_DATASOURCENAME)), aAny );
-
- aAny <<= rtl::OUString( aObject );
- xRowProp->setPropertyValue(
- rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_DBPROP_COMMAND)), aAny );
-
- aAny <<= nSdbType;
- xRowProp->setPropertyValue(
- rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_DBPROP_COMMANDTYPE)), aAny );
-
- uno::Reference<sdb::XCompletedExecution> xExecute( xRowSet, uno::UNO_QUERY );
- if ( xExecute.is() )
- {
- uno::Reference<task::XInteractionHandler> xHandler(
- comphelper::getProcessServiceFactory()->createInstance(
- rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( SC_SERVICE_INTHANDLER )) ),
- uno::UNO_QUERY);
- xExecute->executeWithCompletion( xHandler );
- }
- else
- xRowSet->execute();
- SvNumberFormatter aFormat(mpDoc->GetServiceManager(), ScGlobal::eLnge);
- pCache->InitFromDataBase( xRowSet, *aFormat.GetNullDate() );
- }
- }
- catch ( sdbc::SQLException& rError )
- {
- //! store error message
- delete pCache;
- pCache = NULL;
- InfoBox aInfoBox( 0, String(rError.Message) );
- aInfoBox.Execute();
- }
- catch ( uno::Exception& )
- {
- delete pCache;
- pCache = NULL;
- OSL_FAIL("Unexpected exception in database");
- }
+const ScDPCache* ScImportSourceDesc::CreateCache() const
+{
+ if (!mpDoc)
+ return NULL;
+ sal_Int32 nSdbType = GetCommandType();
+ if (nSdbType < 0)
+ return NULL;
- ::comphelper::disposeComponent( xRowSet );
- return pCache;
+ ScDPCollection::DBCaches& rCaches = mpDoc->GetDPCollection()->GetDBCaches();
+ return rCaches.getCache(nSdbType, aDBName, aObject);
}
ScDatabaseDPData::ScDatabaseDPData(ScDocument* pDoc, const ScImportSourceDesc& rImport) :
diff --git a/sc/source/core/data/dpshttab.cxx b/sc/source/core/data/dpshttab.cxx
index e4aca9a45253..cfad761377bc 100644
--- a/sc/source/core/data/dpshttab.cxx
+++ b/sc/source/core/data/dpshttab.cxx
@@ -60,7 +60,7 @@ using ::std::vector;
// -----------------------------------------------------------------------
-ScSheetDPData::ScSheetDPData(ScDocument* pD, const ScSheetSourceDesc& rDesc, ScDPCache* pCache) :
+ScSheetDPData::ScSheetDPData(ScDocument* pD, const ScSheetSourceDesc& rDesc, const ScDPCache* pCache) :
ScDPTableData(pD),
aQuery ( rDesc.GetQueryParam() ),
pSpecial(NULL),
@@ -307,7 +307,7 @@ bool ScSheetSourceDesc::operator== (const ScSheetSourceDesc& rOther) const
maQueryParam == rOther.maQueryParam;
}
-ScDPCache* ScSheetSourceDesc::CreateCache() const
+const ScDPCache* ScSheetSourceDesc::CreateCache() const
{
if (!mpDoc)
return NULL;
@@ -319,9 +319,17 @@ ScDPCache* ScSheetSourceDesc::CreateCache() const
return NULL;
}
- ScDPCache* pCache = new ScDPCache(mpDoc);
- pCache->InitFromDoc(mpDoc, GetSourceRange());
- return pCache;
+ // All cache instances are managed centrally by ScDPCollection.
+ ScDPCollection* pDPs = mpDoc->GetDPCollection();
+ if (HasRangeName())
+ {
+ // Name-based data source.
+ ScDPCollection::NameCaches& rCaches = pDPs->GetNameCaches();
+ return rCaches.getCache(GetRangeName(), GetSourceRange());
+ }
+
+ ScDPCollection::SheetCaches& rCaches = pDPs->GetSheetCaches();
+ return rCaches.getCache(GetSourceRange());
}
long ScSheetSourceDesc::GetCacheId() const
diff --git a/sc/source/core/data/dptablecache.cxx b/sc/source/core/data/dptablecache.cxx
index 008cdfcf3935..35782e05bab7 100644
--- a/sc/source/core/data/dptablecache.cxx
+++ b/sc/source/core/data/dptablecache.cxx
@@ -48,6 +48,8 @@
#include <com/sun/star/sdbc/XResultSetMetaData.hpp>
#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+#include <memory>
+
const double D_TIMEFACTOR = 86400.0;
using namespace ::com::sun::star;
@@ -57,26 +59,37 @@ using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::UNO_QUERY;
using ::com::sun::star::uno::UNO_QUERY_THROW;
using ::std::vector;
+using ::std::auto_ptr;
namespace {
-bool lcl_isDate( sal_uLong nNumType )
+bool isDate( sal_uLong nNumType )
{
return ((nNumType & NUMBERFORMAT_DATE) != 0) ? 1 : 0;
}
-bool lcl_Search( const ScDPCache::DataListType& list, const ::std::vector<SCROW>& rOrder, const ScDPItemData& item, SCROW& rIndex)
+/**
+ * Search for an item in the data array. If it's in the array, return its
+ * index to the caller.
+ *
+ * @param rArray dimension array
+ * @param rOrder global order (what's this?)
+ * @param item item to search for
+ * @param rIndex the index of the found item in the global order.
+ *
+ * @return true if the item is found, or false otherwise.
+ */
+bool hasItemInDimension(const ScDPCache::DataListType& rArray, const ::std::vector<SCROW>& rOrder, const ScDPItemData& item, SCROW& rIndex)
{
- rIndex = list.size();
+ rIndex = rArray.size();
bool bFound = false;
SCROW nLo = 0;
- SCROW nHi = list.size() - 1;
- SCROW nIndex;
+ SCROW nHi = rArray.size() - 1;
long nCompare;
while (nLo <= nHi)
{
- nIndex = (nLo + nHi) / 2;
- nCompare = ScDPItemData::Compare( list[rOrder[nIndex]], item );
+ SCROW nIndex = (nLo + nHi) / 2;
+ nCompare = ScDPItemData::Compare( rArray[rOrder[nIndex]], item );
if (nCompare < 0)
nLo = nIndex + 1;
else
@@ -173,7 +186,7 @@ ScDPItemData* lcl_GetItemValue(
ScDPItemData::ScDPItemData(const String& rS, double fV, bool bHV, const sal_uLong nNumFormatP, bool bData) :
nNumFormat( nNumFormatP ), aString(rS), fValue(fV),
- mbFlag( (MK_VAL*!!bHV) | (MK_DATA*!!bData) | (MK_ERR*!!false) | (MK_DATE*!!lcl_isDate( nNumFormat ) ) )
+ mbFlag( (MK_VAL*!!bHV) | (MK_DATA*!!bData) | (MK_ERR*!!false) | (MK_DATE*!!isDate( nNumFormat ) ) )
{
}
@@ -203,7 +216,7 @@ ScDPItemData::ScDPItemData(ScDocument* pDoc, SCROW nRow, sal_uInt16 nCol, sal_uI
fValue = fVal;
mbFlag |= MK_VAL|MK_DATA;
nNumFormat = pDoc->GetNumberFormat( ScAddress( nCol, nRow, nDocTab ) );
- lcl_isDate( nFormat ) ? ( mbFlag |= MK_DATE ) : (mbFlag &= ~MK_DATE);
+ isDate( nFormat ) ? ( mbFlag |= MK_DATE ) : (mbFlag &= ~MK_DATE);
}
else if ( pDoc->HasData( nCol,nRow, nDocTab ) )
SetString ( aDocStr );
@@ -473,15 +486,12 @@ bool ScDPCache::InitFromDoc(ScDocument* pDoc, const ScRange& rRange)
maIndexOrder.push_back(new vector<SCROW>());
}
//check valid
- for ( SCROW nRow = nStartRow; nRow <= nEndRow; nRow ++ )
+
+ for (sal_uInt16 nCol = nStartCol; nCol <= nEndCol; ++nCol)
{
- for ( sal_uInt16 nCol = nStartCol; nCol <= nEndCol; nCol++ )
- {
- if ( nRow == nStartRow )
- AddLabel( new ScDPItemData( pDoc, nRow, nCol, nDocTab ) );
- else
- AddData( nCol - nStartCol, new ScDPItemData( pDoc, nRow, nCol, nDocTab ) );
- }
+ AddLabel(new ScDPItemData(pDoc, nStartRow, nCol, nDocTab));
+ for (SCROW nRow = nStartRow + 1; nRow <= nEndRow; ++nRow)
+ AddData(nCol - nStartCol, new ScDPItemData(pDoc, nRow, nCol, nDocTab));
}
return true;
}
@@ -489,7 +499,7 @@ bool ScDPCache::InitFromDoc(ScDocument* pDoc, const ScRange& rRange)
bool ScDPCache::InitFromDataBase (const Reference<sdbc::XRowSet>& xRowSet, const Date& rNullDate)
{
if (!xRowSet.is())
- // Dont' even waste time to go any further.
+ // Don't even waste time to go any further.
return false;
try
{
@@ -565,7 +575,7 @@ sal_uLong ScDPCache::GetDimNumType( SCCOL nDim) const
return GetNumType(maTableDataValues[nDim][0].nNumFormat);
}
-bool ScDPCache::ValidQuery( SCROW nRow, const ScQueryParam &rParam, bool *pSpecial)
+bool ScDPCache::ValidQuery( SCROW nRow, const ScQueryParam &rParam, bool *pSpecial) const
{
if (!rParam.GetEntry(0).bDoQuery)
return true;
@@ -787,23 +797,23 @@ bool ScDPCache::IsEmptyMember( SCROW nRow, sal_uInt16 nColumn ) const
return !GetItemDataById( nColumn, GetItemDataId( nColumn, nRow, false ) )->IsHasData();
}
-bool ScDPCache::AddData(long nDim, ScDPItemData* pitemData)
+bool ScDPCache::AddData(long nDim, ScDPItemData* pData)
{
DBG_ASSERT( IsValid(), " IsValid() == false " );
DBG_ASSERT( nDim < mnColumnCount && nDim >=0 , "dimension out of bound" );
- SCROW nIndex = 0;
- bool bInserted = false;
+ // Wrap this instance with scoped pointer to ensure proper deletion.
+ auto_ptr<ScDPItemData> p(pData);
+ pData->SetDate(isDate(GetNumType(pData->nNumFormat)));
- pitemData->SetDate( lcl_isDate( GetNumType( pitemData->nNumFormat ) ) );
-
- if ( !lcl_Search( maTableDataValues[nDim], maGlobalOrder[nDim], *pitemData, nIndex ) )
+ SCROW nIndex = 0;
+ if (!hasItemInDimension(maTableDataValues[nDim], maGlobalOrder[nDim], *pData, nIndex))
{
- maTableDataValues[nDim].push_back( pitemData );
+ // This item doesn't exist in the dimension array yet.
+ maTableDataValues[nDim].push_back(p);
maGlobalOrder[nDim].insert( maGlobalOrder[nDim].begin()+nIndex, maTableDataValues[nDim].size()-1 );
DBG_ASSERT( (size_t) maGlobalOrder[nDim][nIndex] == maTableDataValues[nDim].size()-1 ,"ScDPTableDataCache::AddData ");
maSourceData[nDim].push_back( maTableDataValues[nDim].size()-1 );
- bInserted = true;
}
else
maSourceData[nDim].push_back( maGlobalOrder[nDim][nIndex] );
@@ -813,12 +823,9 @@ bool ScDPCache::AddData(long nDim, ScDPItemData* pitemData)
while ( mbEmptyRow.size() <= nCurRow )
mbEmptyRow.push_back( true );
- if ( pitemData->IsHasData() )
+ if ( pData->IsHasData() )
mbEmptyRow[ nCurRow ] = false;
- if ( !bInserted )
- delete pitemData;
-
return true;
}
@@ -928,10 +935,26 @@ sal_uLong ScDPCache::GetNumberFormat( long nDim ) const
{
if ( nDim >= mnColumnCount )
return 0;
- if ( maTableDataValues[nDim].size()==0 )
+
+ if (maTableDataValues[nDim].empty())
return 0;
- else
- return maTableDataValues[nDim][0].nNumFormat;
+
+ // TODO: This is very ugly, but the best we can do right now. Check the
+ // first 10 dimension members, and take the first non-zero number format,
+ // else return the default number format (of 0). For the long-term, we
+ // need to redo this cache structure to properly indicate empty cells, and
+ // skip them when trying to determine the representative number format for
+ // a dimension.
+ size_t nCount = maTableDataValues[nDim].size();
+ if (nCount > 10)
+ nCount = 10;
+ for (size_t i = 0; i < nCount; ++i)
+ {
+ sal_uLong n = maTableDataValues[nDim][i].nNumFormat;
+ if (n)
+ return n;
+ }
+ return 0;
}
bool ScDPCache::IsDateDimension( long nDim ) const
@@ -967,7 +990,7 @@ SCCOL ScDPCache::GetDimensionIndex(String sName) const
return -1;
}
-SCROW ScDPCache::GetIdByItemData(long nDim, String sItemData ) const
+SCROW ScDPCache::GetIdByItemData(long nDim, const String& sItemData ) const
{
if ( nDim < mnColumnCount && nDim >=0 )
{
@@ -995,7 +1018,7 @@ SCROW ScDPCache::GetIdByItemData( long nDim, const ScDPItemData& rData ) const
return GetRowCount() + maAdditionalData.getDataId(rData);
}
-SCROW ScDPCache::GetAdditionalItemID ( String sItemData ) const
+SCROW ScDPCache::GetAdditionalItemID ( const String& sItemData ) const
{
ScDPItemData rData ( sItemData );
return GetAdditionalItemID( rData );
diff --git a/sc/source/core/data/scdpoutputimpl.cxx b/sc/source/core/data/scdpoutputimpl.cxx
deleted file mode 100644
index ce2201ef872c..000000000000
--- a/sc/source/core/data/scdpoutputimpl.cxx
+++ /dev/null
@@ -1,184 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*************************************************************************
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * Copyright IBM Corporation 2009.
- * Copyright 2009 by Sun Microsystems, Inc.
- *
- * OpenOffice.org - a multi-platform office productivity suite
- *
- * This file is part of OpenOffice.org.
- *
- * OpenOffice.org is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 3
- * only, as published by the Free Software Foundation.
- *
- * OpenOffice.org is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License version 3 for more details
- * (a copy is included in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU Lesser General Public License
- * version 3 along with OpenOffice.org. If not, see
- * <http://www.openoffice.org/license.html>
- * for a copy of the LGPLv3 License.
- *
- ************************************************************************/
-// MARKER(update_precomp.py): autogen include statement, do not remove
-#include "precompiled_sc.hxx"
-
-// INCLUDE ---------------------------------------------------------------
-#include "scdpoutputimpl.hxx"
-#include "scitems.hxx"
-#include <editeng/boxitem.hxx>
-// -----------------------------------------------------------------------
-
-namespace
-{
- bool lcl_compareColfuc ( SCCOL i, SCCOL j) { return (i<j); }
- bool lcl_compareRowfuc ( SCROW i, SCROW j) { return (i<j); }
-}
-
-
-void OutputImpl::OutputDataArea()
-{
- AddRow( mnDataStartRow );
- AddCol( mnDataStartCol );
-
- mnCols.push_back( mnTabEndCol+1); //set last row bottom
- mnRows.push_back( mnTabEndRow+1); //set last col bottom
-
- sal_Bool bAllRows = ( ( mnTabEndRow - mnDataStartRow + 2 ) == (SCROW) mnRows.size() );
-
- std::sort( mnCols.begin(), mnCols.end(), lcl_compareColfuc );
- std::sort( mnRows.begin(), mnRows.end(), lcl_compareRowfuc );
-
- for( SCCOL nCol = 0; nCol < (SCCOL)mnCols.size()-1; nCol ++ )
- {
- if ( !bAllRows )
- {
- if ( nCol < (SCCOL)mnCols.size()-2)
- {
- for ( SCROW i = nCol%2; i < (SCROW)mnRows.size()-2; i +=2 )
- OutputBlockFrame( mnCols[nCol], mnRows[i], mnCols[nCol+1]-1, mnRows[i+1]-1 );
- if ( mnRows.size()>=2 )
- OutputBlockFrame( mnCols[nCol], mnRows[mnRows.size()-2], mnCols[nCol+1]-1, mnRows[mnRows.size()-1]-1 );
- }
- else
- {
- for ( SCROW i = 0 ; i < (SCROW)mnRows.size()-1; i++ )
- OutputBlockFrame( mnCols[nCol], mnRows[i], mnCols[nCol+1]-1, mnRows[i+1]-1 );
- }
- }
- else
- OutputBlockFrame( mnCols[nCol], mnRows.front(), mnCols[nCol+1]-1, mnRows.back()-1, bAllRows );
- }
- //out put rows area outer framer
- if ( mnTabStartCol != mnDataStartCol )
- {
- if ( mnTabStartRow != mnDataStartRow )
- OutputBlockFrame( mnTabStartCol, mnTabStartRow, mnDataStartCol-1, mnDataStartRow-1 );
- OutputBlockFrame( mnTabStartCol, mnDataStartRow, mnDataStartCol-1, mnTabEndRow );
- }
- //out put cols area outer framer
- OutputBlockFrame( mnDataStartCol, mnTabStartRow, mnTabEndCol, mnDataStartRow-1 );
-}
-
-OutputImpl::OutputImpl( ScDocument* pDoc, sal_uInt16 nTab,
- SCCOL nTabStartCol,
- SCROW nTabStartRow,
- SCCOL nMemberStartCol,
- SCROW nMemberStartRow,
- SCCOL nDataStartCol,
- SCROW nDataStartRow,
- SCCOL nTabEndCol,
- SCROW nTabEndRow ):
- mpDoc( pDoc ),
- mnTab( nTab ),
- mnTabStartCol( nTabStartCol ),
- mnTabStartRow( nTabStartRow ),
- mnMemberStartCol( nMemberStartCol),
- mnMemberStartRow( nMemberStartRow),
- mnDataStartCol ( nDataStartCol ),
- mnDataStartRow ( nDataStartRow ),
- mnTabEndCol( nTabEndCol ),
- mnTabEndRow( nTabEndRow )
-{
- mbNeedLineCols.resize( nTabEndCol-nDataStartCol+1, false );
- mbNeedLineRows.resize( nTabEndRow-nDataStartRow+1, false );
-
-}
-
-sal_Bool OutputImpl::AddRow( SCROW nRow )
-{
- if ( !mbNeedLineRows[ nRow - mnDataStartRow ] )
- {
- mbNeedLineRows[ nRow - mnDataStartRow ] = true;
- mnRows.push_back( nRow );
- return sal_True;
- }
- else
- return false;
-}
-
-sal_Bool OutputImpl::AddCol( SCCOL nCol )
-{
-
- if ( !mbNeedLineCols[ nCol - mnDataStartCol ] )
- {
- mbNeedLineCols[ nCol - mnDataStartCol ] = true;
- mnCols.push_back( nCol );
- return sal_True;
- }
- else
- return false;
-}
-
-void OutputImpl::OutputBlockFrame ( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, sal_Bool bHori )
-{
- Color color = SC_DP_FRAME_COLOR;
- ::editeng::SvxBorderLine aLine( &color, SC_DP_FRAME_INNER_BOLD );
- ::editeng::SvxBorderLine aOutLine( &color, SC_DP_FRAME_OUTER_BOLD );
-
- SvxBoxItem aBox( ATTR_BORDER );
-
- if ( nStartCol == mnTabStartCol )
- aBox.SetLine(&aOutLine, BOX_LINE_LEFT);
- else
- aBox.SetLine(&aLine, BOX_LINE_LEFT);
-
- if ( nStartRow == mnTabStartRow )
- aBox.SetLine(&aOutLine, BOX_LINE_TOP);
- else
- aBox.SetLine(&aLine, BOX_LINE_TOP);
-
- if ( nEndCol == mnTabEndCol ) //bottom row
- aBox.SetLine(&aOutLine, BOX_LINE_RIGHT);
- else
- aBox.SetLine(&aLine, BOX_LINE_RIGHT);
-
- if ( nEndRow == mnTabEndRow ) //bottom
- aBox.SetLine(&aOutLine, BOX_LINE_BOTTOM);
- else
- aBox.SetLine(&aLine, BOX_LINE_BOTTOM);
-
-
- SvxBoxInfoItem aBoxInfo( ATTR_BORDER_INNER );
- aBoxInfo.SetValid(VALID_VERT,false );
- if ( bHori )
- {
- aBoxInfo.SetValid(VALID_HORI,sal_True);
- aBoxInfo.SetLine( &aLine, BOXINFO_LINE_HORI );
- }
- else
- aBoxInfo.SetValid(VALID_HORI,false );
-
- aBoxInfo.SetValid(VALID_DISTANCE,false);
-
- mpDoc->ApplyFrameAreaTab( ScRange( nStartCol, nStartRow, mnTab, nEndCol, nEndRow , mnTab ), &aBox, &aBoxInfo );
-
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/scdpoutputimpl.hxx b/sc/source/core/data/scdpoutputimpl.hxx
deleted file mode 100644
index 35a0a65a06fc..000000000000
--- a/sc/source/core/data/scdpoutputimpl.hxx
+++ /dev/null
@@ -1,79 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*************************************************************************
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * Copyright IBM Corporation 2009.
- * Copyright 2009 by Sun Microsystems, Inc.
- *
- * OpenOffice.org - a multi-platform office productivity suite
- *
- * 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 SCDPOUTPUTIMPL_HXX
-#define SCDPOUTPUTIMPL_HXX
-
-#include "document.hxx"
-
-#define SC_DP_FRAME_INNER_BOLD 20
-#define SC_DP_FRAME_OUTER_BOLD 40
-
-#define SC_DP_FRAME_COLOR Color(0,0,0) //( 0x20, 0x40, 0x68 )
-
-class OutputImpl
-{
- ScDocument* mpDoc;
- sal_uInt16 mnTab;
- ::std::vector< bool > mbNeedLineCols;
- ::std::vector< SCCOL > mnCols;
-
- ::std::vector< bool > mbNeedLineRows;
- ::std::vector< SCROW > mnRows;
-
- SCCOL mnTabStartCol;
- SCROW mnTabStartRow;
- SCCOL mnMemberStartCol;
- SCROW mnMemberStartRow;
-
- SCCOL mnDataStartCol;
- SCROW mnDataStartRow;
- SCCOL mnTabEndCol;
- SCROW mnTabEndRow;
-
-public:
- OutputImpl( ScDocument* pDoc, sal_uInt16 nTab,
- SCCOL nTabStartCol,
- SCROW nTabStartRow,
- SCCOL nMemberStartCol,
- SCROW nMemberStartRow,
- SCCOL nDataStartCol,
- SCROW nDataStartRow,
- SCCOL nTabEndCol,
- SCROW nTabEndRow );
- sal_Bool AddRow( SCROW nRow );
- sal_Bool AddCol( SCCOL nCol );
-
- void OutputDataArea();
- void OutputBlockFrame ( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, sal_Bool bHori = false );
-
-};
-
-#endif
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx
index 7100790f8fc6..379bd82613d5 100644
--- a/sc/source/core/data/table1.cxx
+++ b/sc/source/core/data/table1.cxx
@@ -1625,6 +1625,52 @@ void ScTable::MaybeAddExtraColumn(SCCOL& rCol, SCROW nRow, OutputDevice* pDev, d
rCol = nNewCol;
}
+namespace {
+
+class SetTableIndex : public ::std::unary_function<ScRange, void>
+{
+ SCTAB mnTab;
+public:
+ SetTableIndex(SCTAB nTab) : mnTab(nTab) {}
+
+ void operator() (ScRange& rRange) const
+ {
+ rRange.aStart.SetTab(mnTab);
+ rRange.aEnd.SetTab(mnTab);
+ }
+};
+
+}
+
+void ScTable::CopyPrintRange(const ScTable& rTable)
+{
+ // The table index shouldn't be used when the print range is used, but
+ // just in case set the correct table index.
+
+ aPrintRanges = rTable.aPrintRanges;
+ ::std::for_each(aPrintRanges.begin(), aPrintRanges.end(), SetTableIndex(nTab));
+
+ bPrintEntireSheet = rTable.bPrintEntireSheet;
+
+ delete pRepeatColRange;
+ pRepeatColRange = NULL;
+ if (rTable.pRepeatColRange)
+ {
+ pRepeatColRange = new ScRange(*rTable.pRepeatColRange);
+ pRepeatColRange->aStart.SetTab(nTab);
+ pRepeatColRange->aEnd.SetTab(nTab);
+ }
+
+ delete pRepeatRowRange;
+ pRepeatRowRange = NULL;
+ if (rTable.pRepeatRowRange)
+ {
+ pRepeatRowRange = new ScRange(*rTable.pRepeatRowRange);
+ pRepeatRowRange->aStart.SetTab(nTab);
+ pRepeatRowRange->aEnd.SetTab(nTab);
+ }
+}
+
void ScTable::DoColResize( SCCOL nCol1, SCCOL nCol2, SCSIZE nAdd )
{
for (SCCOL nCol=nCol1; nCol<=nCol2; nCol++)
@@ -1648,6 +1694,8 @@ void ScTable::SetRepeatColRange( const ScRange* pNew )
if (IsStreamValid())
SetStreamValid(false);
+
+ InvalidatePageBreaks();
}
void ScTable::SetRepeatRowRange( const ScRange* pNew )
@@ -1656,6 +1704,8 @@ void ScTable::SetRepeatRowRange( const ScRange* pNew )
if (IsStreamValid())
SetStreamValid(false);
+
+ InvalidatePageBreaks();
}
void ScTable::ClearPrintRanges()
@@ -1665,6 +1715,8 @@ void ScTable::ClearPrintRanges()
if (IsStreamValid())
SetStreamValid(false);
+
+ InvalidatePageBreaks();
}
void ScTable::AddPrintRange( const ScRange& rNew )
@@ -1675,6 +1727,8 @@ void ScTable::AddPrintRange( const ScRange& rNew )
if (IsStreamValid())
SetStreamValid(false);
+
+ InvalidatePageBreaks();
}
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index d1caed2fee68..406562d1eaf5 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -157,18 +157,17 @@ void ScTable::InsertRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE
if (!maRowManualBreaks.empty())
{
- std::set<SCROW>::reverse_iterator rit = maRowManualBreaks.rbegin();
- while (rit != maRowManualBreaks.rend())
- {
- SCROW nRow = *rit;
- if (nRow < nStartRow)
- break; // while
- else
- {
- maRowManualBreaks.erase( (++rit).base());
- maRowManualBreaks.insert( static_cast<SCROW>( nRow + nSize));
- }
- }
+ // Copy all breaks up to nStartRow (non-inclusive).
+ ::std::set<SCROW>::iterator itr1 = maRowManualBreaks.lower_bound(nStartRow);
+ ::std::set<SCROW> aNewBreaks(maRowManualBreaks.begin(), itr1);
+
+ // Copy all breaks from nStartRow (inclusive) to the last element,
+ // but add nSize to each value.
+ ::std::set<SCROW>::iterator itr2 = maRowManualBreaks.end();
+ for (; itr1 != itr2; ++itr1)
+ aNewBreaks.insert(static_cast<SCROW>(*itr1 + nSize));
+
+ maRowManualBreaks.swap(aNewBreaks);
}
}
@@ -208,14 +207,21 @@ void ScTable::DeleteRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE
if (!maRowManualBreaks.empty())
{
- std::set<SCROW>::iterator it = maRowManualBreaks.upper_bound( static_cast<SCROW>( nStartRow + nSize - 1));
- maRowManualBreaks.erase( maRowManualBreaks.lower_bound( nStartRow), it);
- while (it != maRowManualBreaks.end())
- {
- SCROW nRow = *it;
- maRowManualBreaks.erase( it++);
- maRowManualBreaks.insert( static_cast<SCROW>( nRow - nSize));
- }
+ // Erase all manual breaks between nStartRow and nStartRow + nSize - 1 (inclusive).
+ std::set<SCROW>::iterator itr1 = maRowManualBreaks.lower_bound(nStartRow);
+ std::set<SCROW>::iterator itr2 = maRowManualBreaks.upper_bound(static_cast<SCROW>(nStartRow + nSize - 1));
+ maRowManualBreaks.erase(itr1, itr2);
+
+ // Copy all breaks from the 1st element up to nStartRow to the new container.
+ itr1 = maRowManualBreaks.lower_bound(nStartRow);
+ ::std::set<SCROW> aNewBreaks(maRowManualBreaks.begin(), itr1);
+
+ // Copy all breaks from nStartRow to the last element, but subtract each value by nSize.
+ itr2 = maRowManualBreaks.end();
+ for (; itr1 != itr2; ++itr1)
+ aNewBreaks.insert(static_cast<SCROW>(*itr1 - nSize));
+
+ maRowManualBreaks.swap(aNewBreaks);
}
}
@@ -2629,6 +2635,20 @@ void ScTable::ShowRows(SCROW nRow1, SCROW nRow2, bool bShow)
DecRecalcLevel();
}
+bool ScTable::IsDataFiltered() const
+{
+ bool bAnyQuery = false;
+ ScDBData* pDBData = pDocument->GetFilterDBAtTable(nTab);
+ if ( pDBData )
+ {
+ ScQueryParam aParam;
+ pDBData->GetQueryParam( aParam );
+ if ( aParam.GetEntry(0).bDoQuery )
+ bAnyQuery = true;
+ }
+ return bAnyQuery;
+}
+
void ScTable::SetColFlags( SCCOL nCol, sal_uInt8 nNewFlags )
{
diff --git a/sc/source/core/data/table4.cxx b/sc/source/core/data/table4.cxx
index e7ba2153a3f1..edba012fadd1 100644
--- a/sc/source/core/data/table4.cxx
+++ b/sc/source/core/data/table4.cxx
@@ -79,6 +79,7 @@
#include "rangenam.hxx"
#include "docpool.hxx"
#include "progress.hxx"
+#include "segmenttree.hxx"
#include <math.h>
@@ -199,7 +200,7 @@ void ScTable::FillAnalyse( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
rMinDigits = 0;
rListData = NULL;
rCmd = FILL_SIMPLE;
- if ( nScFillModeMouseModifier & KEY_MOD1 )
+ if ( (nScFillModeMouseModifier & KEY_MOD1) || IsDataFiltered() )
return ; // Ctrl-Taste: Copy
SCCOL nAddX;
@@ -525,10 +526,15 @@ void ScTable::FillAuto( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
sal_uLong nIMin = nIStart;
sal_uLong nIMax = nIEnd;
PutInOrder(nIMin,nIMax);
- if (bVertical)
- DeleteArea(nCol1, static_cast<SCROW>(nIMin), nCol2, static_cast<SCROW>(nIMax), IDF_AUTOFILL);
- else
- DeleteArea(static_cast<SCCOL>(nIMin), nRow1, static_cast<SCCOL>(nIMax), nRow2, IDF_AUTOFILL);
+ sal_Bool bHasFiltered = IsDataFiltered();
+
+ if (!bHasFiltered)
+ {
+ if (bVertical)
+ DeleteArea(nCol1, static_cast<SCROW>(nIMin), nCol2, static_cast<SCROW>(nIMax), IDF_AUTOFILL);
+ else
+ DeleteArea(static_cast<SCCOL>(nIMin), nRow1, static_cast<SCCOL>(nIMax), nRow2, IDF_AUTOFILL);
+ }
sal_uLong nProgress = rProgress.GetState();
@@ -575,7 +581,7 @@ void ScTable::FillAuto( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
pNewPattern = NULL;
}
- if ( bVertical && nISrcStart == nISrcEnd )
+ if ( bVertical && nISrcStart == nISrcEnd && !bHasFiltered )
{
// Attribute komplett am Stueck setzen
if (pNewPattern || pSrcPattern != pDocument->GetDefPattern())
@@ -593,37 +599,44 @@ void ScTable::FillAuto( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
break; // Schleife abbrechen
}
- if ( pSrcPattern != aCol[nCol].GetPattern( static_cast<SCROW>(nRow) ) )
+ if (!RowFiltered( nRow ))
{
- // Vorlage auch uebernehmen
- //! am AttrArray mit ApplyPattern zusammenfassen ??
- if ( pStyleSheet )
- aCol[nCol].ApplyStyle( static_cast<SCROW>(nRow), *pStyleSheet );
+ if ( bHasFiltered )
+ DeleteArea(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow),
+ static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), IDF_AUTOFILL);
- // ApplyPattern statt SetPattern um alte MergeFlags stehenzulassen
- if ( pNewPattern )
- aCol[nCol].ApplyPattern( static_cast<SCROW>(nRow), *pNewPattern );
- else
- aCol[nCol].ApplyPattern( static_cast<SCROW>(nRow), *pSrcPattern );
- }
+ if ( pSrcPattern != aCol[nCol].GetPattern( static_cast<SCROW>(nRow) ) )
+ {
+ // Vorlage auch uebernehmen
+ //! am AttrArray mit ApplyPattern zusammenfassen ??
+ if ( pStyleSheet )
+ aCol[nCol].ApplyStyle( static_cast<SCROW>(nRow), *pStyleSheet );
- if (nAtSrc==nISrcEnd)
- {
- if ( nAtSrc != nISrcStart )
- { // mehr als eine Source-Zelle
- nAtSrc = nISrcStart;
+ // ApplyPattern statt SetPattern um alte MergeFlags stehenzulassen
+ if ( pNewPattern )
+ aCol[nCol].ApplyPattern( static_cast<SCROW>(nRow), *pNewPattern );
+ else
+ aCol[nCol].ApplyPattern( static_cast<SCROW>(nRow), *pSrcPattern );
+ }
+
+ if (nAtSrc==nISrcEnd)
+ {
+ if ( nAtSrc != nISrcStart )
+ { // mehr als eine Source-Zelle
+ nAtSrc = nISrcStart;
+ bGetPattern = sal_True;
+ }
+ }
+ else if (bPositive)
+ {
+ ++nAtSrc;
+ bGetPattern = sal_True;
+ }
+ else
+ {
+ --nAtSrc;
bGetPattern = sal_True;
}
- }
- else if (bPositive)
- {
- ++nAtSrc;
- bGetPattern = sal_True;
- }
- else
- {
- --nAtSrc;
- bGetPattern = sal_True;
}
if (rInner == nIEnd) break;
@@ -691,7 +704,7 @@ void ScTable::FillAuto( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
{
sal_uLong nSource = nISrcStart;
double nDelta;
- if ( nScFillModeMouseModifier & KEY_MOD1 )
+ if ( (nScFillModeMouseModifier & KEY_MOD1) || bHasFiltered )
nDelta = 0.0;
else if ( bPositive )
nDelta = 1.0;
@@ -708,6 +721,7 @@ void ScTable::FillAuto( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
ScBaseCell* pSrcCell = NULL;
CellType eCellType = CELLTYPE_NONE;
sal_Bool bIsOrdinalSuffix = false;
+ sal_Bool bRowFiltered = false;
rInner = nIStart;
while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
@@ -733,7 +747,7 @@ void ScTable::FillAuto( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
((ScStringCell*)pSrcCell)->GetString( aValue );
else
((ScEditCell*)pSrcCell)->GetString( aValue );
- if ( !(nScFillModeMouseModifier & KEY_MOD1) )
+ if ( !(nScFillModeMouseModifier & KEY_MOD1) && !bHasFiltered )
{
nCellDigits = 0; // look at each source cell individually
nHeadNoneTail = lcl_DecompValueString(
@@ -752,94 +766,103 @@ void ScTable::FillAuto( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
else
eCellType = CELLTYPE_NONE;
}
- switch (eCellType)
- {
- case CELLTYPE_VALUE:
- aCol[nCol].Insert(static_cast<SCROW>(nRow), new ScValueCell(nVal + nDelta));
- break;
- case CELLTYPE_STRING:
- case CELLTYPE_EDIT:
- if ( nHeadNoneTail )
- {
- // #i48009# with the "nStringValue+(long)nDelta" expression within the
- // lcl_ValueString calls, gcc 3.4.1 makes wrong optimizations (ok in 3.4.3),
- // so nNextValue is now calculated ahead.
- sal_Int32 nNextValue = nStringValue+(sal_Int32)nDelta;
- String aStr;
- if ( nHeadNoneTail < 0 )
+ bRowFiltered = mpFilteredRows->getValue(nRow);
+
+ if (!bRowFiltered)
+ {
+ switch (eCellType)
+ {
+ case CELLTYPE_VALUE:
+ aCol[nCol].Insert(static_cast<SCROW>(nRow), new ScValueCell(nVal + nDelta));
+ break;
+ case CELLTYPE_STRING:
+ case CELLTYPE_EDIT:
+ if ( nHeadNoneTail )
{
- aCol[nCol].Insert( static_cast<SCROW>(nRow),
- lcl_getSuffixCell( pDocument,
- nNextValue, nCellDigits, aValue,
- eCellType, bIsOrdinalSuffix));
+ // #i48009# with the "nStringValue+(long)nDelta" expression within the
+ // lcl_ValueString calls, gcc 3.4.1 makes wrong optimizations (ok in 3.4.3),
+ // so nNextValue is now calculated ahead.
+ sal_Int32 nNextValue = nStringValue+(sal_Int32)nDelta;
+
+ String aStr;
+ if ( nHeadNoneTail < 0 )
+ {
+ aCol[nCol].Insert( static_cast<SCROW>(nRow),
+ lcl_getSuffixCell( pDocument,
+ nNextValue, nCellDigits, aValue,
+ eCellType, bIsOrdinalSuffix));
+ }
+ else
+ {
+ aStr = aValue;
+ aStr += lcl_ValueString( nNextValue, nCellDigits );
+ aCol[nCol].Insert( static_cast<SCROW>(nRow),
+ new ScStringCell( aStr));
+ }
}
else
{
- aStr = aValue;
- aStr += lcl_ValueString( nNextValue, nCellDigits );
- aCol[nCol].Insert( static_cast<SCROW>(nRow),
- new ScStringCell( aStr));
- }
- }
- else
- {
- ScAddress aDestPos( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), nTab );
- switch ( eCellType )
- {
- case CELLTYPE_STRING:
- case CELLTYPE_EDIT:
- aCol[nCol].Insert( aDestPos.Row(), pSrcCell->CloneWithoutNote( *pDocument ) );
- break;
- default:
+ ScAddress aDestPos( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), nTab );
+ switch ( eCellType )
{
- // added to avoid warnings
+ case CELLTYPE_STRING:
+ case CELLTYPE_EDIT:
+ aCol[nCol].Insert( aDestPos.Row(), pSrcCell->CloneWithoutNote( *pDocument ) );
+ break;
+ default:
+ {
+ // added to avoid warnings
+ }
}
}
+ break;
+ case CELLTYPE_FORMULA :
+ FillFormula( nFormulaCounter, bFirst,
+ (ScFormulaCell*) pSrcCell,
+ static_cast<SCCOL>(nCol),
+ static_cast<SCROW>(nRow), (rInner == nIEnd) );
+ if (nFormulaCounter - nActFormCnt > nMaxFormCnt)
+ nMaxFormCnt = nFormulaCounter - nActFormCnt;
+ break;
+ default:
+ {
+ // added to avoid warnings
}
- break;
- case CELLTYPE_FORMULA :
- FillFormula( nFormulaCounter, bFirst,
- (ScFormulaCell*) pSrcCell,
- static_cast<SCCOL>(nCol),
- static_cast<SCROW>(nRow), (rInner == nIEnd) );
- if (nFormulaCounter - nActFormCnt > nMaxFormCnt)
- nMaxFormCnt = nFormulaCounter - nActFormCnt;
- break;
- default:
- {
- // added to avoid warnings
}
- }
- if (nSource==nISrcEnd)
- {
- if ( nSource != nISrcStart )
- { // mehr als eine Source-Zelle
- nSource = nISrcStart;
+ if (nSource==nISrcEnd)
+ {
+ if ( nSource != nISrcStart )
+ { // mehr als eine Source-Zelle
+ nSource = nISrcStart;
+ bGetCell = sal_True;
+ }
+ if ( !(nScFillModeMouseModifier & KEY_MOD1) && !bHasFiltered )
+ {
+ if ( bPositive )
+ nDelta += 1.0;
+ else
+ nDelta -= 1.0;
+ }
+ nFormulaCounter = nActFormCnt;
+ bFirst = false;
+ }
+ else if (bPositive)
+ {
+ ++nSource;
bGetCell = sal_True;
}
- if ( !(nScFillModeMouseModifier & KEY_MOD1) )
+ else
{
- if ( bPositive )
- nDelta += 1.0;
- else
- nDelta -= 1.0;
+ --nSource;
+ bGetCell = sal_True;
}
- nFormulaCounter = nActFormCnt;
- bFirst = false;
- }
- else if (bPositive)
- {
- ++nSource;
- bGetCell = sal_True;
- }
- else
- {
- --nSource;
- bGetCell = sal_True;
}
+ if (rInner == nIEnd) break;
+ if (bPositive) ++rInner; else --rInner;
+
// Progress in der inneren Schleife nur bei teuren Zellen,
// und auch dann nicht fuer jede einzelne
@@ -847,8 +870,6 @@ void ScTable::FillAuto( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
if ( eCellType == CELLTYPE_FORMULA || eCellType == CELLTYPE_EDIT )
rProgress.SetStateOnPercent( nProgress );
- if (rInner == nIEnd) break;
- if (bPositive) ++rInner; else --rInner;
}
rProgress.SetStateOnPercent( nProgress );
}
@@ -936,6 +957,30 @@ String ScTable::GetAutoFillPreview( const ScRange& rSource, SCCOL nEndX, SCROW n
}
else if ( eFillCmd == FILL_SIMPLE ) // Auffuellen mit Muster
{
+ if ((eFillDir == FILL_TO_BOTTOM)||(eFillDir == FILL_TO_TOP))
+ {
+ long nBegin = 0;
+ long nEnd = 0;
+ if (nEndY > nRow1)
+ {
+ nBegin = nRow2+1;
+ nEnd = nEndY;
+ }
+ else
+ {
+ nBegin = nEndY;
+ nEnd = nRow1 -1;
+ }
+
+ long nNonFiltered = CountNonFilteredRows(nBegin, nEnd);
+ long nFiltered = nEnd + 1 - nBegin - nNonFiltered;
+
+ if (nIndex > 0)
+ nIndex = nIndex - nFiltered;
+ else
+ nIndex = nIndex + nFiltered;
+ }
+
long nPosIndex = nIndex;
while ( nPosIndex < 0 )
nPosIndex += nSrcCount;
@@ -966,7 +1011,7 @@ String ScTable::GetAutoFillPreview( const ScRange& rSource, SCCOL nEndX, SCROW n
((ScStringCell*)pCell)->GetString( aValue );
else
((ScEditCell*)pCell)->GetString( aValue );
- if ( !(nScFillModeMouseModifier & KEY_MOD1) )
+ if ( !(nScFillModeMouseModifier & KEY_MOD1) && !IsDataFiltered() )
{
sal_Int32 nVal;
sal_uInt16 nCellDigits = 0; // look at each source cell individually
@@ -987,7 +1032,7 @@ String ScTable::GetAutoFillPreview( const ScRange& rSource, SCCOL nEndX, SCROW n
{
// dabei kann's keinen Ueberlauf geben...
double nVal = ((ScValueCell*)pCell)->GetValue();
- if ( !(nScFillModeMouseModifier & KEY_MOD1) )
+ if ( !(nScFillModeMouseModifier & KEY_MOD1) && !IsDataFiltered() )
nVal += (double) nDelta;
Color* pColor;
@@ -1531,17 +1576,11 @@ void ScTable::Fill( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
ScProgress aProgress( pDocument->GetDocumentShell(),
ScGlobal::GetRscString(STR_FILL_SERIES_PROGRESS), nProgCount );
- bSharedNameInserted = false;
-
if (eFillCmd == FILL_AUTO)
FillAuto(nCol1, nRow1, nCol2, nRow2, nFillCount, eFillDir, aProgress);
else
FillSeries(nCol1, nRow1, nCol2, nRow2, nFillCount, eFillDir,
eFillCmd, eFillDateCmd, nStepValue, nMaxValue, 0, sal_True, aProgress);
-
- if (bSharedNameInserted) // Wurde Shared-Name eingefuegt?
- pDocument->GetRangeName()->SetSharedMaxIndex(
- pDocument->GetRangeName()->GetSharedMaxIndex()+1); // dann hochzaehlen
}
diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
index ce59c16ffa20..7caee7518f8b 100644
--- a/sc/source/core/inc/interpre.hxx
+++ b/sc/source/core/inc/interpre.hxx
@@ -316,6 +316,7 @@ void PopExternalSingleRef(ScExternalRefCache::TokenRef& rToken, ScExternalRefCac
void PopExternalDoubleRef(sal_uInt16& rFileId, String& rTabName, ScComplexRefData& rRef);
void PopExternalDoubleRef(ScExternalRefCache::TokenArrayRef& rArray);
void PopExternalDoubleRef(ScMatrixRef& rMat);
+void GetExternalDoubleRef(sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& aData, ScExternalRefCache::TokenArrayRef& rArray);
sal_Bool PopDoubleRefOrSingleRef( ScAddress& rAdr );
void PopDoubleRefPushMatrix();
// If MatrixFormula: convert formula::svDoubleRef to svMatrix, create JumpMatrix.
diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx
index c30f57a03a99..ad3052585784 100644
--- a/sc/source/core/tool/compiler.cxx
+++ b/sc/source/core/tool/compiler.cxx
@@ -3788,6 +3788,7 @@ ScTokenArray* ScCompiler::CompileString( const String& rFormula )
eLastOp == ocArrayColSep ||
eLastOp == ocArrayOpen) &&
(eOp == ocSep ||
+ eOp == ocClose ||
eOp == ocArrayRowSep ||
eOp == ocArrayColSep ||
eOp == ocArrayClose) )
diff --git a/sc/source/core/tool/dbcolect.cxx b/sc/source/core/tool/dbcolect.cxx
index d6d52c4b38bf..4118f9dcd7f9 100644
--- a/sc/source/core/tool/dbcolect.cxx
+++ b/sc/source/core/tool/dbcolect.cxx
@@ -222,6 +222,11 @@ ScDBData& ScDBData::operator= (const ScDBData& rData)
return *this;
}
+SCTAB ScDBData::GetTable() const
+{
+ return nTable;
+}
+
bool ScDBData::operator== (const ScDBData& rData) const
{
// Daten, die nicht in den Params sind
@@ -652,7 +657,7 @@ void ScDBData::UpdateReference(ScDocument* pDoc, UpdateRefMode eUpdateRefMode,
//! Testen, ob mitten aus dem Bereich geloescht/eingefuegt wurde !!!
}
-#include <stdio.h>
+
void ScDBData::ExtendDataArea(ScDocument* pDoc)
{
// Extend the DB area to include data rows immediately below.
@@ -660,7 +665,6 @@ void ScDBData::ExtendDataArea(ScDocument* pDoc)
SCROW nRow1a = nStartRow, nRow2a = nEndRow;
pDoc->GetDataArea(nTable, nCol1a, nRow1a, nCol2a, nRow2a, false, false);
nEndRow = nRow2a;
- fprintf(stdout, "ScDBData::ExtendDataArea: new end row = %"SAL_PRIdINT32"\n", nEndRow);
}
namespace {
@@ -821,6 +825,27 @@ ScDBData* ScDBCollection::GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCO
return NULL;
}
+ScDBData* ScDBCollection::GetFilterDBAtTable(SCTAB nTab) const
+{
+ ScDBData* pDataEmpty = NULL;
+ if (pItems)
+ {
+ for (sal_uInt16 i = 0; i < nCount; i++)
+ {
+ ScDBData* pDBTemp = (ScDBData*)pItems[i];
+ if ( pDBTemp->GetTable() == nTab )
+ {
+ sal_Bool bFilter = pDBTemp->HasAutoFilter() || pDBTemp->HasQueryParam();
+
+ if ( bFilter )
+ return pDBTemp;
+ }
+ }
+ }
+
+ return pDataEmpty;
+}
+
sal_Bool ScDBCollection::SearchName( const String& rName, sal_uInt16& rIndex ) const
{
if (rtl::OUString(rName)==rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(STR_DB_LOCAL_NONAME)))
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 476eb6ef2cb0..c4a8cdd346cd 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -810,6 +810,38 @@ double ScInterpreter::Compare()
}
}
break;
+ case svExternalSingleRef:
+ {
+ ScMatrixRef pMat = GetMatrix();
+ if (!pMat)
+ {
+ SetError( errIllegalParameter);
+ break;
+ }
+
+ SCSIZE nC, nR;
+ pMat->GetDimensions(nC, nR);
+ if (!nC || !nR)
+ {
+ SetError( errIllegalParameter);
+ break;
+ }
+ if (pMat->IsEmpty(0, 0))
+ aComp.bEmpty[i] = true;
+ else if (pMat->IsString(0, 0))
+ {
+ *aComp.pVal[i] = pMat->GetString(0, 0);
+ aComp.bVal[i] = false;
+ }
+ else
+ {
+ aComp.nVal[i] = pMat->GetDouble(0, 0);
+ aComp.bVal[i] = true;
+ }
+ }
+ break;
+ case svExternalDoubleRef:
+ // TODO: Find out how to handle this...
default:
SetError( errIllegalParameter);
break;
@@ -2908,8 +2940,10 @@ void ScInterpreter::ScMin( sal_Bool bTextAsZero )
}
break;
case svMatrix :
+ case svExternalSingleRef:
+ case svExternalDoubleRef:
{
- ScMatrixRef pMat = PopMatrix();
+ ScMatrixRef pMat = GetMatrix();
if (pMat)
{
SCSIZE nC, nR;
@@ -3029,8 +3063,10 @@ void ScInterpreter::ScMax( sal_Bool bTextAsZero )
}
break;
case svMatrix :
+ case svExternalSingleRef:
+ case svExternalDoubleRef:
{
- ScMatrixRef pMat = PopMatrix();
+ ScMatrixRef pMat = GetMatrix();
if (pMat)
{
nFuncFmtType = NUMBERFORMAT_NUMBER;
@@ -4603,7 +4639,9 @@ void ScInterpreter::ScCountIf()
}
}
break;
- case svMatrix :
+ case svMatrix:
+ case svExternalSingleRef:
+ case svExternalDoubleRef:
{
ScMatValType nType = GetDoubleOrStringFromMatrix( fVal,
rString);
@@ -4648,23 +4686,25 @@ void ScInterpreter::ScCountIf()
nTab2 = nTab1;
break;
case svMatrix:
+ case svExternalSingleRef:
+ case svExternalDoubleRef:
+ {
+ pQueryMatrix = GetMatrix();
+ if (!pQueryMatrix)
{
- 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;
+ PushIllegalParameter();
+ return;
}
- break;
+ 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 ;
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index a30ac5507cb9..bfe5b6b632ac 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -238,6 +238,18 @@ double ScInterpreter::GetValueCellValue( const ScAddress& rPos, const ScValueCel
double ScInterpreter::ConvertStringToValue( const String& rStr )
{
+#if 1
+ // We keep this code until we provide a friendly way to convert string
+ // numbers into numbers in the UI.
+ double fValue = 0.0;
+ sal_uInt32 nFIndex = 0;
+ if (!pFormatter->IsNumberFormat(rStr, nFIndex, fValue))
+ {
+ SetError(errNoValue);
+ fValue = 0.0;
+ }
+ return fValue;
+#else
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ConvertStringToValue" );
double fValue = 0.0;
if (mnStringNoValueError == errCellNoValue)
@@ -407,6 +419,7 @@ double ScInterpreter::ConvertStringToValue( const String& rStr )
fValue = 0.0;
}
return fValue;
+#endif
}
@@ -1506,6 +1519,28 @@ void ScInterpreter::PopExternalDoubleRef(ScExternalRefCache::TokenArrayRef& rArr
if (nGlobalError)
return;
+ GetExternalDoubleRef(nFileId, aTabName, aData, rArray);
+ if (nGlobalError)
+ return;
+}
+
+void ScInterpreter::PopExternalDoubleRef(ScMatrixRef& rMat)
+{
+ ScExternalRefCache::TokenArrayRef pArray;
+ PopExternalDoubleRef(pArray);
+ if (nGlobalError)
+ return;
+
+ // For now, we only support single range data for external
+ // references, which means the array should only contain a
+ // single matrix token.
+ ScToken* p = static_cast<ScToken*>(pArray->First());
+ rMat = p->GetMatrix();
+}
+
+void ScInterpreter::GetExternalDoubleRef(
+ sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& rData, ScExternalRefCache::TokenArrayRef& rArray)
+{
ScExternalRefManager* pRefMgr = pDok->GetExternalRefManager();
const String* pFile = pRefMgr->getExternalFileName(nFileId);
if (!pFile)
@@ -1513,18 +1548,19 @@ void ScInterpreter::PopExternalDoubleRef(ScExternalRefCache::TokenArrayRef& rArr
SetError(errNoName);
return;
}
- if (aData.Ref1.IsTabRel() || aData.Ref2.IsTabRel())
+ if (rData.Ref1.IsTabRel() || rData.Ref2.IsTabRel())
{
OSL_FAIL("ScCompiler::GetToken: external double reference must have an absolute table reference!");
SetError(errNoRef);
return;
}
+ ScComplexRefData aData(rData);
aData.CalcAbsIfRel(aPos);
ScRange aRange(aData.Ref1.nCol, aData.Ref1.nRow, aData.Ref1.nTab,
aData.Ref2.nCol, aData.Ref2.nRow, aData.Ref2.nTab);
ScExternalRefCache::TokenArrayRef pArray = pRefMgr->getDoubleRefTokens(
- nFileId, aTabName, aRange, &aPos);
+ nFileId, rTabName, aRange, &aPos);
if (!pArray)
{
@@ -1549,20 +1585,6 @@ void ScInterpreter::PopExternalDoubleRef(ScExternalRefCache::TokenArrayRef& rArr
rArray = pArray;
}
-void ScInterpreter::PopExternalDoubleRef(ScMatrixRef& rMat)
-{
- ScExternalRefCache::TokenArrayRef pArray;
- PopExternalDoubleRef(pArray);
- if (nGlobalError)
- return;
-
- // For now, we only support single range data for external
- // references, which means the array should only contain a
- // single matrix token.
- ScToken* p = static_cast<ScToken*>(pArray->First());
- rMat = p->GetMatrix();
-}
-
sal_Bool ScInterpreter::PopDoubleRefOrSingleRef( ScAddress& rAdr )
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PopDoubleRefOrSingleRef" );
@@ -1630,6 +1652,7 @@ bool ScInterpreter::ConvertMatrixParameters()
case svDouble:
case svString:
case svSingleRef:
+ case svExternalSingleRef:
case svMissing:
case svError:
case svEmptyCell:
@@ -1687,6 +1710,35 @@ bool ScInterpreter::ConvertMatrixParameters()
}
}
break;
+ case svExternalDoubleRef:
+ {
+ ScParameterClassification::Type eType =
+ ScParameterClassification::GetParameterType( pCur, nParams - i);
+ if (eType == ScParameterClassification::Array)
+ {
+ sal_uInt16 nFileId = p->GetIndex();
+ const String& rTabName = p->GetString();
+ const ScComplexRefData& rRef = static_cast<ScToken*>(p)->GetDoubleRef();
+ ScExternalRefCache::TokenArrayRef pArray;
+ GetExternalDoubleRef(nFileId, rTabName, rRef, pArray);
+ if (nGlobalError)
+ break;
+
+ ScToken* pTemp = static_cast<ScToken*>(pArray->First());
+ if (!pTemp)
+ break;
+
+ ScMatrixRef pMat = pTemp->GetMatrix();
+ if (pMat)
+ {
+ ScToken* pNew = new ScMatrixToken( pMat);
+ pNew->IncRef();
+ pStack[ sp - i ] = pNew;
+ p->DecRef(); // p may be dead now!
+ }
+ }
+ }
+ break;
case svRefList:
{
ScParameterClassification::Type eType =
@@ -2337,13 +2389,9 @@ ScMatValType ScInterpreter::GetDoubleOrStringFromMatrix( double& rDouble,
ScMatrixRef pMat;
StackVar eType = GetStackType();
- if (eType == svExternalDoubleRef)
- {
- PopExternalDoubleRef(pMat);
- }
- else if (eType == svMatrix)
+ if (eType == svExternalDoubleRef || eType == svExternalSingleRef || eType == svMatrix)
{
- pMat = PopMatrix();
+ pMat = GetMatrix();
}
else
{
diff --git a/sc/source/core/tool/rangenam.cxx b/sc/source/core/tool/rangenam.cxx
index 440a9598e59e..df5f43617ae1 100644
--- a/sc/source/core/tool/rangenam.cxx
+++ b/sc/source/core/tool/rangenam.cxx
@@ -729,11 +729,10 @@ void ScRangeName::copyLocalNames(const TabNameMap& rNames, TabNameCopyMap& rCopy
}
}
-ScRangeName::ScRangeName() :
- mnSharedMaxIndex(0) {}
+ScRangeName::ScRangeName() {}
ScRangeName::ScRangeName(const ScRangeName& r) :
- maData(r.maData), mnSharedMaxIndex(r.mnSharedMaxIndex) {}
+ maData(r.maData) {}
const ScRangeData* ScRangeName::findByRange(const ScRange& rRange) const
{
@@ -806,16 +805,6 @@ void ScRangeName::UpdateGrow(const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY)
itr->UpdateGrow(rArea, nGrowX, nGrowY);
}
-sal_uInt16 ScRangeName::GetSharedMaxIndex()
-{
- return mnSharedMaxIndex;
-}
-
-void ScRangeName::SetSharedMaxIndex(sal_uInt16 nInd)
-{
- mnSharedMaxIndex = nInd;
-}
-
ScRangeName::const_iterator ScRangeName::begin() const
{
return maData.begin();
@@ -886,7 +875,7 @@ void ScRangeName::clear()
bool ScRangeName::operator== (const ScRangeName& r) const
{
- return maData == r.maData && mnSharedMaxIndex == r.mnSharedMaxIndex;
+ return maData == r.maData;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/tool/reffind.cxx b/sc/source/core/tool/reffind.cxx
index a3b2ce55585d..b6061bc7f230 100644
--- a/sc/source/core/tool/reffind.cxx
+++ b/sc/source/core/tool/reffind.cxx
@@ -42,16 +42,18 @@
// STATIC DATA -----------------------------------------------------------
+namespace {
+
// incl. Doppelpunkt -> Doppelte Referenzen werden einzeln behandelt
-const sal_Unicode ScRefFinder::pDelimiters[] = {
+const sal_Unicode pDelimiters[] = {
'=','(',')','+','-','*','/','^','&',' ','{','}','<','>',':', 0
};
// =======================================================================
-inline sal_Bool IsText( sal_Unicode c )
+inline bool IsText( sal_Unicode c )
{
- bool bFound = ScGlobal::UnicodeStrChr( ScRefFinder::pDelimiters, c );
+ bool bFound = ScGlobal::UnicodeStrChr( pDelimiters, c );
if (bFound)
// This is one of delimiters, therefore not text.
return false;
@@ -61,23 +63,160 @@ inline sal_Bool IsText( sal_Unicode c )
return c != sep;
}
-inline sal_Bool IsText( sal_Bool& bQuote, sal_Unicode c )
+inline bool IsText( bool& bQuote, sal_Unicode c )
{
- if ( c == '\'' )
+ if (c == '\'')
{
bQuote = !bQuote;
- return sal_True;
+ return true;
+ }
+ if (bQuote)
+ return true;
+
+ return IsText(c);
+}
+
+/**
+ * Find first character position that is considered text. A character is
+ * considered a text when it's within the ascii range and when it's not a
+ * delimiter.
+ */
+xub_StrLen FindStartPos(const sal_Unicode* p, xub_StrLen nStartPos, xub_StrLen nEndPos)
+{
+ while (nStartPos <= nEndPos && !IsText(p[nStartPos]))
+ ++nStartPos;
+
+ return nStartPos;
+}
+
+xub_StrLen FindEndPosA1(const sal_Unicode* p, xub_StrLen nStartPos, xub_StrLen nEndPos)
+{
+ bool bQuote = false;
+ xub_StrLen nNewEnd = nStartPos;
+ while (nNewEnd <= nEndPos && IsText(bQuote, p[nNewEnd]))
+ ++nNewEnd;
+
+ return nNewEnd;
+}
+
+xub_StrLen FindEndPosR1C1(const sal_Unicode* p, xub_StrLen nStartPos, xub_StrLen nEndPos)
+{
+ xub_StrLen nNewEnd = nStartPos;
+ p = &p[nStartPos];
+ for (; nNewEnd <= nEndPos; ++p, ++nNewEnd)
+ {
+ if (*p == '\'')
+ {
+ // Skip until the closing quote.
+ for (; nNewEnd <= nEndPos; ++p, ++nNewEnd)
+ if (*p == '\'')
+ break;
+ }
+ else if (*p == '[')
+ {
+ // Skip until the closing braket.
+ for (; nNewEnd <= nEndPos; ++p, ++nNewEnd)
+ if (*p == ']')
+ break;
+ }
+ else if (!IsText(*p))
+ break;
+ }
+
+ return nNewEnd;
+}
+
+/**
+ * Find last character position that is considred text, from the specified
+ * start position.
+ */
+xub_StrLen FindEndPos(const sal_Unicode* p, xub_StrLen nStartPos, xub_StrLen nEndPos,
+ formula::FormulaGrammar::AddressConvention eConv)
+{
+ switch (eConv)
+ {
+ case formula::FormulaGrammar::CONV_XL_R1C1:
+ return FindEndPosR1C1(p, nStartPos, nEndPos);
+ case formula::FormulaGrammar::CONV_OOO:
+ case formula::FormulaGrammar::CONV_XL_A1:
+ default:
+ return FindEndPosA1(p, nStartPos, nEndPos);
}
- if ( bQuote )
- return sal_True;
- return IsText( c );
}
-ScRefFinder::ScRefFinder(const String& rFormula, ScDocument* pDocument,
- formula::FormulaGrammar::AddressConvention eConvP) :
+void ExpandToTextA1(const sal_Unicode* p, xub_StrLen nLen, xub_StrLen& rStartPos, xub_StrLen& rEndPos)
+{
+ while (rStartPos > 0 && IsText(p[rStartPos - 1]) )
+ --rStartPos;
+ if (rEndPos)
+ --rEndPos;
+ while (rEndPos+1 < nLen && IsText(p[rEndPos + 1]) )
+ ++rEndPos;
+}
+
+void ExpandToTextR1C1(const sal_Unicode* p, xub_StrLen nLen, xub_StrLen& rStartPos, xub_StrLen& rEndPos)
+{
+ // move back the start position to the first text character.
+ if (rStartPos > 0)
+ {
+ for (--rStartPos; rStartPos > 0; --rStartPos)
+ {
+ sal_Unicode c = p[rStartPos];
+ if (c == '\'')
+ {
+ // Skip until the opening quote.
+ for (--rStartPos; rStartPos > 0; --rStartPos)
+ {
+ c = p[rStartPos];
+ if (c == '\'')
+ break;
+ }
+ }
+ else if (c == ']')
+ {
+ // Skip until the opening braket.
+ for (--rStartPos; rStartPos > 0; --rStartPos)
+ {
+ if (c == '[')
+ break;
+ }
+ }
+ else if (!IsText(c))
+ {
+ ++rStartPos;
+ break;
+ }
+ }
+ }
+
+ // move forward the end position to the last text character.
+ rEndPos = FindEndPosR1C1(p, rEndPos, nLen-1);
+}
+
+void ExpandToText(const sal_Unicode* p, xub_StrLen nLen, xub_StrLen& rStartPos, xub_StrLen& rEndPos,
+ formula::FormulaGrammar::AddressConvention eConv)
+{
+ switch (eConv)
+ {
+ case formula::FormulaGrammar::CONV_XL_R1C1:
+ ExpandToTextR1C1(p, nLen, rStartPos, rEndPos);
+ break;
+ case formula::FormulaGrammar::CONV_OOO:
+ case formula::FormulaGrammar::CONV_XL_A1:
+ default:
+ ExpandToTextA1(p, nLen, rStartPos, rEndPos);
+ }
+}
+
+}
+
+ScRefFinder::ScRefFinder(
+ const String& rFormula, const ScAddress& rPos,
+ ScDocument* pDocument, formula::FormulaGrammar::AddressConvention eConvP) :
aFormula( rFormula ),
eConv( eConvP ),
- pDoc( pDocument )
+ pDoc( pDocument ),
+ maPos(rPos)
{
nSelStart = nSelEnd = nFound = 0;
}
@@ -107,15 +246,9 @@ void ScRefFinder::ToggleRel( xub_StrLen nStartPos, xub_StrLen nEndPos )
// Selektion erweitern, und statt Selektion Start- und Endindex
if ( nEndPos < nStartPos )
- {
- xub_StrLen nTemp = nStartPos; nStartPos = nEndPos; nEndPos = nTemp;
- }
- while (nStartPos > 0 && IsText(pSource[nStartPos - 1]) )
- --nStartPos;
- if (nEndPos)
- --nEndPos;
- while (nEndPos+1 < nLen && IsText(pSource[nEndPos + 1]) )
- ++nEndPos;
+ ::std::swap(nEndPos, nStartPos);
+
+ ExpandToText(pSource, nLen, nStartPos, nEndPos, eConv);
String aResult;
String aExpr;
@@ -126,27 +259,20 @@ void ScRefFinder::ToggleRel( xub_StrLen nStartPos, xub_StrLen nEndPos )
xub_StrLen nLoopStart = nStartPos;
while ( nLoopStart <= nEndPos )
{
- // Formel zerlegen
-
- xub_StrLen nEStart = nLoopStart;
- while ( nEStart <= nEndPos && !IsText(pSource[nEStart]) )
- ++nEStart;
-
- sal_Bool bQuote = false;
- xub_StrLen nEEnd = nEStart;
- while ( nEEnd <= nEndPos && IsText(bQuote,pSource[nEEnd]) )
- ++nEEnd;
+ // Determine the stard and end positions of a text segment.
+ xub_StrLen nEStart = FindStartPos(pSource, nLoopStart, nEndPos);
+ xub_StrLen nEEnd = FindEndPos(pSource, nEStart, nEndPos, eConv);
aSep = aFormula.Copy( nLoopStart, nEStart-nLoopStart );
aExpr = aFormula.Copy( nEStart, nEEnd-nEStart );
- // Test, ob aExpr eine Referenz ist
-
- sal_uInt16 nResult = aAddr.Parse( aExpr, pDoc, pDoc->GetAddressConvention() );
+ // Check the validity of the expression, and toggle the relative flag.
+ ScAddress::Details aDetails(eConv, maPos.Row(), maPos.Col());
+ sal_uInt16 nResult = aAddr.Parse(aExpr, pDoc, aDetails);
if ( nResult & SCA_VALID )
{
sal_uInt16 nFlags = lcl_NextFlags( nResult );
- aAddr.Format( aExpr, nFlags, pDoc, pDoc->GetAddressConvention() );
+ aAddr.Format(aExpr, nFlags, pDoc, aDetails);
xub_StrLen nAbsStart = nStartPos+aResult.Len()+aSep.Len();
diff --git a/sc/source/filter/excel/excform.cxx b/sc/source/filter/excel/excform.cxx
index 62f3622cd87a..949cb0fb0615 100644
--- a/sc/source/filter/excel/excform.cxx
+++ b/sc/source/filter/excel/excform.cxx
@@ -480,7 +480,7 @@ ConvErr ExcelToSc::Convert( const ScTokenArray*& pErgebnis, XclImpStream& aIn, s
else
aIn >> nXclFunc;
if( const XclFunctionInfo* pFuncInfo = maFuncProv.GetFuncInfoFromXclFunc( nXclFunc ) )
- DoMulArgs( pFuncInfo->meOpCode, pFuncInfo->mnMaxParamCount, pFuncInfo->mnMinParamCount );
+ DoMulArgs( pFuncInfo->meOpCode, pFuncInfo->mnMaxParamCount );
else
DoMulArgs( ocNoName, 0 );
}
@@ -498,7 +498,7 @@ ConvErr ExcelToSc::Convert( const ScTokenArray*& pErgebnis, XclImpStream& aIn, s
else
aIn >> nXclFunc;
if( const XclFunctionInfo* pFuncInfo = maFuncProv.GetFuncInfoFromXclFunc( nXclFunc ) )
- DoMulArgs( pFuncInfo->meOpCode, nParamCount, pFuncInfo->mnMinParamCount );
+ DoMulArgs( pFuncInfo->meOpCode, nParamCount );
else
DoMulArgs( ocNoName, 0 );
}
@@ -1525,7 +1525,7 @@ sal_Bool ExcelToSc::GetAbsRefs( ScRangeList& rRangeList, XclImpStream& rStrm, sa
return !rRangeList.empty();
}
-void ExcelToSc::DoMulArgs( DefTokenId eId, sal_uInt8 nAnz, sal_uInt8 nMinParamCount )
+void ExcelToSc::DoMulArgs( DefTokenId eId, sal_uInt8 nAnz )
{
TokenId eParam[ 256 ];
sal_Int32 nLauf;
@@ -1589,19 +1589,6 @@ void ExcelToSc::DoMulArgs( DefTokenId eId, sal_uInt8 nAnz, sal_uInt8 nMinParamCo
}
}
- // FIXME: ideally we'd want to import all missing args, but this
- // conflicts with lots of fn's understanding of nParams - we need
- // a function table, and pre-call argument normalisation 1st.
- sal_Int16 nLastRemovable = nLast - nMinParamCount;
-
- // skip missing parameters at end of parameter list
- while( nSkipEnd < nLastRemovable &&
- aPool.IsSingleOp( eParam[ nSkipEnd + 1 ], ocMissing ) )
- nSkipEnd++;
-
-// fprintf (stderr, "Fn %d nSkipEnd %d nLast %d nMinParamCnt %d %d\n",
-// eId, nSkipEnd, nLast, nMinParamCount, nLastRemovable);
-
// [Parameter{;Parameter}]
if( nLast > nSkipEnd )
{
diff --git a/sc/source/filter/excel/excform8.cxx b/sc/source/filter/excel/excform8.cxx
index aebb75418f36..f989abc3c196 100644
--- a/sc/source/filter/excel/excform8.cxx
+++ b/sc/source/filter/excel/excform8.cxx
@@ -42,9 +42,51 @@
#include "externalrefmgr.hxx"
#include <vector>
+#include <cstring>
+using ::rtl::OUString;
+using ::rtl::OUStringBuffer;
using ::std::vector;
+namespace {
+
+/**
+ * Extract a file path from OLE link path. An OLE link path is expected to
+ * be in the following format:
+ *
+ * Excel.Sheet.8 \3 [file path]
+ */
+bool extractFilePath(const OUString& rUrl, OUString& rPath)
+{
+ const char* prefix = "Excel.Sheet.8\3";
+ size_t nPrefixLen = ::std::strlen(prefix);
+
+ sal_Int32 n = rUrl.getLength();
+ if (n <= static_cast<sal_Int32>(nPrefixLen))
+ // needs to have the specified prefix.
+ return false;
+
+ OUStringBuffer aBuf;
+ const sal_Unicode* p = rUrl.getStr();
+ for (size_t i = 0; i < static_cast<size_t>(n); ++i, ++p)
+ {
+ if (i < nPrefixLen)
+ {
+ sal_Unicode pc = static_cast<sal_Unicode>(*prefix++);
+ if (pc != *p)
+ return false;
+
+ continue;
+ }
+ aBuf.append(*p);
+ }
+
+ rPath = aBuf.makeStringAndClear();
+ return true;
+}
+
+}
+
ExcelToSc8::ExternalTabInfo::ExternalTabInfo() :
mnFileId(0), mbExternal(false)
{
@@ -92,6 +134,20 @@ bool ExcelToSc8::Read3DTabReference( sal_uInt16 nIxti, SCTAB& rFirstTab, SCTAB&
return GetExternalFileIdFromXti(nIxti, rExtInfo.mnFileId);
}
+bool ExcelToSc8::HandleOleLink(sal_uInt16 nXtiIndex, const XclImpExtName& rExtName, ExternalTabInfo& rExtInfo)
+{
+ const String* pUrl = rLinkMan.GetSupbookUrl(nXtiIndex);
+ if (!pUrl)
+ return false;
+
+ OUString aPath;
+ if (!extractFilePath(*pUrl, aPath))
+ // file path extraction failed.
+ return false;
+
+ OUString aFileUrl = ScGlobal::GetAbsDocName(aPath, GetDocShell());
+ return rExtName.CreateOleData(GetDoc(), aFileUrl, rExtInfo.mnFileId, rExtInfo.maTabName, rExtInfo.maRange);
+}
// if bAllowArrays is false stream seeks to first byte after <nFormulaLen>
// otherwise it will seek to the first byte past additional content after <nFormulaLen>
@@ -419,7 +475,7 @@ ConvErr ExcelToSc8::Convert( const ScTokenArray*& rpTokArray, XclImpStream& aIn,
aIn >> nParamCount >> nXclFunc;
nParamCount &= 0x7F;
if( const XclFunctionInfo* pFuncInfo = maFuncProv.GetFuncInfoFromXclFunc( nXclFunc ) )
- DoMulArgs( pFuncInfo->meOpCode, nParamCount, pFuncInfo->mnMinParamCount );
+ DoMulArgs( pFuncInfo->meOpCode, nParamCount );
else
DoMulArgs( ocNoName, 0 );
}
@@ -682,8 +738,29 @@ ConvErr ExcelToSc8::Convert( const ScTokenArray*& rpTokArray, XclImpStream& aIn,
aStack << aPool.Store( ocEuroConvert, String() );
}
break;
-
- default: // OLE link
+ case xlExtOLE:
+ {
+ ExternalTabInfo aExtInfo;
+ if (HandleOleLink(nXtiIndex, *pExtName, aExtInfo))
+ {
+ if (aExtInfo.maRange.aStart == aExtInfo.maRange.aEnd)
+ {
+ // single cell
+ aSRD.InitAddress(aExtInfo.maRange.aStart);
+ aStack << aPool.StoreExtRef(aExtInfo.mnFileId, aExtInfo.maTabName, aSRD);
+ }
+ else
+ {
+ // range
+ aCRD.InitRange(aExtInfo.maRange);
+ aStack << aPool.StoreExtRef(aExtInfo.mnFileId, aExtInfo.maTabName, aCRD);
+ }
+ }
+ else
+ aStack << aPool.Store(ocNoName, pExtName->GetName());
+ }
+ break;
+ default:
{
aPool << ocBad;
aPool >> aStack;
diff --git a/sc/source/filter/excel/read.cxx b/sc/source/filter/excel/read.cxx
index 70feaa4e4e22..96e68a9df01f 100644
--- a/sc/source/filter/excel/read.cxx
+++ b/sc/source/filter/excel/read.cxx
@@ -1125,8 +1125,8 @@ FltError ImportExcel8::Read( void )
case 0x9D: AutoFilterInfo(); break;// AUTOFILTERINFO
case 0x9E: AutoFilter(); break; // AUTOFILTER
case 0x0208: Row34(); break; // ROW [ 34 ]
- case 0x0021:
- case 0x0221: Array34(); break; // ARRAY [ 34 ]
+ case EXC_ID2_ARRAY:
+ case EXC_ID3_ARRAY: Array34(); break; // ARRAY [ 34 ]
case 0x0225: Defrowheight345();break;//DEFAULTROWHEI[ 345 ]
case 0x04BC: Shrfmla(); break; // SHRFMLA [ 5 ]
case 0x0867: SheetProtection(); break; // SHEETPROTECTION
diff --git a/sc/source/filter/excel/xepivot.cxx b/sc/source/filter/excel/xepivot.cxx
index 8139a25b8b08..be8557eac430 100644
--- a/sc/source/filter/excel/xepivot.cxx
+++ b/sc/source/filter/excel/xepivot.cxx
@@ -538,7 +538,7 @@ void XclExpPCField::InsertNumDateGroupItems( const ScDPObject& rDPObj, const ScD
if( const ScSheetSourceDesc* pSrcDesc = rDPObj.GetSheetDesc() )
{
// get the string collection with original source elements
- ScDPCache* pCache = pSrcDesc->CreateCache();
+ const ScDPCache* pCache = pSrcDesc->CreateCache();
if (!pCache)
return;
diff --git a/sc/source/filter/excel/xilink.cxx b/sc/source/filter/excel/xilink.cxx
index 634a723238a6..492fe5d2033c 100644
--- a/sc/source/filter/excel/xilink.cxx
+++ b/sc/source/filter/excel/xilink.cxx
@@ -44,6 +44,9 @@
#include <boost/ptr_container/ptr_vector.hpp>
using ::std::vector;
+using ::rtl::OUString;
+using ::rtl::OUStringBuffer;
+
// ============================================================================
// *** Helper classes ***
@@ -284,7 +287,61 @@ sal_uInt16 XclImpTabInfo::GetCurrentIndex( sal_uInt16 nCreatedId, sal_uInt16 nMa
// External names =============================================================
-XclImpExtName::XclImpExtName( const XclImpSupbook& rSupbook, XclImpStream& rStrm, XclSupbookType eSubType, ExcelToSc* pFormulaConv )
+XclImpExtName::MOper::MOper(XclImpStream& rStrm) :
+ mxCached(new ScMatrix(0,0))
+{
+ SCSIZE nLastCol = rStrm.ReaduInt8();
+ SCSIZE nLastRow = rStrm.ReaduInt16();
+ mxCached->Resize(nLastCol+1, nLastRow+1);
+ for (SCSIZE nRow = 0; nRow <= nLastRow; ++nRow)
+ {
+ for (SCSIZE nCol = 0; nCol <= nLastCol; ++nCol)
+ {
+ sal_uInt8 nOp;
+ rStrm >> nOp;
+ switch (nOp)
+ {
+ case 0x01:
+ {
+ double fVal = rStrm.ReadDouble();
+ mxCached->PutDouble(fVal, nCol, nRow);
+ }
+ break;
+ case 0x02:
+ {
+ OUString aStr = rStrm.ReadUniString();
+ mxCached->PutString(aStr, nCol, nRow);
+ }
+ break;
+ case 0x04:
+ {
+ bool bVal = rStrm.ReaduInt8();
+ mxCached->PutBoolean(bVal, nCol, nRow);
+ rStrm.Ignore(7);
+ }
+ break;
+ case 0x10:
+ {
+ sal_uInt8 nErr = rStrm.ReaduInt8();
+ // TODO: Map the error code from xls to calc.
+ mxCached->PutError(nErr, nCol, nRow);
+ rStrm.Ignore(7);
+ }
+ break;
+ default:
+ rStrm.Ignore(8);
+ }
+ }
+ }
+}
+
+const ScMatrix& XclImpExtName::MOper::GetCache() const
+{
+ return *mxCached;
+}
+
+XclImpExtName::XclImpExtName( const XclImpSupbook& rSupbook, XclImpStream& rStrm, XclSupbookType eSubType, ExcelToSc* pFormulaConv ) :
+ mpMOper(NULL)
{
sal_uInt16 nFlags;
sal_uInt8 nLen;
@@ -312,36 +369,45 @@ XclImpExtName::XclImpExtName( const XclImpSupbook& rSupbook, XclImpStream& rStrm
meType = ::get_flagvalue( nFlags, EXC_EXTN_OLE, xlExtOLE, xlExtDDE );
}
- if( (meType == xlExtDDE) && (rStrm.GetRecLeft() > 1) )
- mxDdeMatrix.reset( new XclImpCachedMatrix( rStrm ) );
-
- if (meType == xlExtName)
+ switch (meType)
{
- // TODO: For now, only global external names are supported. In future
- // we should extend this to supporting per-sheet external names.
- if (mnStorageId == 0)
- {
- if (pFormulaConv)
+ case xlExtDDE:
+ if (rStrm.GetRecLeft() > 1)
+ mxDdeMatrix.reset(new XclImpCachedMatrix(rStrm));
+ break;
+ case xlExtName:
+ // TODO: For now, only global external names are supported. In future
+ // we should extend this to supporting per-sheet external names.
+ if (mnStorageId == 0)
{
- const ScTokenArray* pArray = NULL;
- sal_uInt16 nFmlaLen;
- rStrm >> nFmlaLen;
- vector<String> aTabNames;
- sal_uInt16 nCount = rSupbook.GetTabCount();
- aTabNames.reserve(nCount);
- for (sal_uInt16 i = 0; i < nCount; ++i)
- aTabNames.push_back(rSupbook.GetTabName(i));
-
- pFormulaConv->ConvertExternName(pArray, rStrm, nFmlaLen, rSupbook.GetXclUrl(), aTabNames);
- if (pArray)
- mxArray.reset(pArray->Clone());
+ if (pFormulaConv)
+ {
+ const ScTokenArray* pArray = NULL;
+ sal_uInt16 nFmlaLen;
+ rStrm >> nFmlaLen;
+ vector<String> aTabNames;
+ sal_uInt16 nCount = rSupbook.GetTabCount();
+ aTabNames.reserve(nCount);
+ for (sal_uInt16 i = 0; i < nCount; ++i)
+ aTabNames.push_back(rSupbook.GetTabName(i));
+
+ pFormulaConv->ConvertExternName(pArray, rStrm, nFmlaLen, rSupbook.GetXclUrl(), aTabNames);
+ if (pArray)
+ mxArray.reset(pArray->Clone());
+ }
}
- }
+ break;
+ case xlExtOLE:
+ mpMOper = new MOper(rStrm);
+ break;
+ default:
+ ;
}
}
XclImpExtName::~XclImpExtName()
{
+ delete mpMOper;
}
void XclImpExtName::CreateDdeData( ScDocument& rDoc, const String& rApplic, const String& rTopic ) const
@@ -361,6 +427,124 @@ void XclImpExtName::CreateExtNameData( ScDocument& rDoc, sal_uInt16 nFileId ) co
pRefMgr->storeRangeNameTokens(nFileId, maName, *mxArray);
}
+namespace {
+
+/**
+ * Decompose the name into sheet name and range name. An OLE link name is
+ * always formatted like this [ !Sheet1!R1C1:R5C2 ] and it always uses R1C1
+ * notation.
+ */
+bool extractSheetAndRange(const OUString& rName, OUString& rSheet, OUString& rRange)
+{
+ sal_Int32 n = rName.getLength();
+ const sal_Unicode* p = rName.getStr();
+ OUStringBuffer aBuf;
+ bool bInSheet = true;
+ for (sal_Int32 i = 0; i < n; ++i, ++p)
+ {
+ if (i == 0)
+ {
+ // first character must be '!'.
+ if (*p != '!')
+ return false;
+ continue;
+ }
+
+ if (*p == '!')
+ {
+ // sheet name to range separator.
+ if (!bInSheet)
+ return false;
+ rSheet = aBuf.makeStringAndClear();
+ bInSheet = false;
+ continue;
+ }
+
+ aBuf.append(*p);
+ }
+
+ rRange = aBuf.makeStringAndClear();
+ return true;
+}
+
+}
+
+bool XclImpExtName::CreateOleData(ScDocument& rDoc, const OUString& rUrl,
+ sal_uInt16& rFileId, OUString& rTabName, ScRange& rRange) const
+{
+ if (!mpMOper)
+ return false;
+
+ OUString aSheet, aRangeStr;
+ if (!extractSheetAndRange(maName, aSheet, aRangeStr))
+ return false;
+
+ ScRange aRange;
+ sal_uInt16 nRes = aRange.ParseAny(aRangeStr, &rDoc, formula::FormulaGrammar::CONV_XL_R1C1);
+ if ((nRes & SCA_VALID) != SCA_VALID)
+ return false;
+
+ if (aRange.aStart.Tab() != aRange.aEnd.Tab())
+ // We don't support multi-sheet range for this.
+ return false;
+
+ const ScMatrix& rCache = mpMOper->GetCache();
+ SCSIZE nC, nR;
+ rCache.GetDimensions(nC, nR);
+ if (!nC || !nR)
+ // cache matrix is empty.
+ return false;
+
+ ScExternalRefManager* pRefMgr = rDoc.GetExternalRefManager();
+ sal_uInt16 nFileId = pRefMgr->getExternalFileId(rUrl);
+ ScExternalRefCache::TableTypeRef xTab = pRefMgr->getCacheTable(nFileId, aSheet, true, NULL);
+ if (!xTab)
+ // cache table creation failed.
+ return false;
+
+ xTab->setWholeTableCached();
+ for (SCSIZE i = 0; i < nR; ++i)
+ {
+ for (SCSIZE j = 0; j < nC; ++j)
+ {
+ SCCOL nCol = aRange.aStart.Col() + j;
+ SCROW nRow = aRange.aStart.Row() + i;
+
+ ScMatrixValue aVal = rCache.Get(j, i);
+ switch (aVal.nType)
+ {
+ case SC_MATVAL_BOOLEAN:
+ {
+ bool b = aVal.GetBoolean();
+ ScExternalRefCache::TokenRef pToken(new formula::FormulaDoubleToken(b ? 1.0 : 0.0));
+ xTab->setCell(nCol, nRow, pToken, 0, false);
+ }
+ break;
+ case SC_MATVAL_VALUE:
+ {
+ ScExternalRefCache::TokenRef pToken(new formula::FormulaDoubleToken(aVal.fVal));
+ xTab->setCell(nCol, nRow, pToken, 0, false);
+ }
+ break;
+ case SC_MATVAL_STRING:
+ {
+ const String& rStr = aVal.GetString();
+ ScExternalRefCache::TokenRef pToken(new formula::FormulaStringToken(rStr));
+ xTab->setCell(nCol, nRow, pToken, 0, false);
+ }
+ break;
+ default:
+ ;
+ }
+ }
+ }
+
+ rFileId = nFileId;
+ rTabName = aSheet;
+ rRange = aRange;
+ return true;
+}
+
bool XclImpExtName::HasFormulaTokens() const
{
return (mxArray.get() != NULL);
@@ -516,9 +700,9 @@ void XclImpSupbook::ReadExternname( XclImpStream& rStrm, ExcelToSc* pFormulaConv
const XclImpExtName* XclImpSupbook::GetExternName( sal_uInt16 nXclIndex ) const
{
DBG_ASSERT( nXclIndex > 0, "XclImpSupbook::GetExternName - index must be >0" );
- if (meType == EXC_SBTYPE_SELF || nXclIndex >= maExtNameList.size())
+ if (meType == EXC_SBTYPE_SELF || nXclIndex > maExtNameList.size())
return NULL;
- return &maExtNameList.at( nXclIndex - 1 );
+ return &maExtNameList[nXclIndex-1];
}
bool XclImpSupbook::GetLinkData( String& rApplic, String& rTopic ) const
diff --git a/sc/source/filter/excel/xipivot.cxx b/sc/source/filter/excel/xipivot.cxx
index 38bfeaacf3d1..a26b132f198d 100644
--- a/sc/source/filter/excel/xipivot.cxx
+++ b/sc/source/filter/excel/xipivot.cxx
@@ -852,6 +852,12 @@ void XclImpPivotCache::ReadPivotCacheStream( XclImpStream& rStrm )
DBG_ASSERT( maPCInfo.mnTotalFields == maFields.size(),
"XclImpPivotCache::ReadPivotCacheStream - field count mismatch" );
+ if (HasCacheRecords())
+ {
+ SCROW nNewEnd = maSrcRange.aStart.Row() + maPCInfo.mnSrcRecs;
+ maSrcRange.aEnd.SetRow(nNewEnd);
+ }
+
// set source range for external source data
if( bGenerateSource && (nFieldScCol > 0) )
{
@@ -864,9 +870,14 @@ void XclImpPivotCache::ReadPivotCacheStream( XclImpStream& rStrm )
}
}
+bool XclImpPivotCache::HasCacheRecords() const
+{
+ return static_cast<bool>(maPCInfo.mnFlags & EXC_SXDB_SAVEDATA);
+}
+
bool XclImpPivotCache::IsRefreshOnLoad() const
{
- return static_cast<bool>(maPCInfo.mnFlags & 0x0004);
+ return static_cast<bool>(maPCInfo.mnFlags & EXC_SXDB_REFRESH_LOAD);
}
bool XclImpPivotCache::IsValid() const
@@ -999,8 +1010,12 @@ void XclImpPTField::ConvertPageField( ScDPSaveData& rSaveData ) const
DBG_ASSERT( maFieldInfo.mnAxes & EXC_SXVD_AXIS_PAGE, "XclImpPTField::ConvertPageField - no page field" );
if( ScDPSaveDimension* pSaveDim = ConvertRCPField( rSaveData ) )
{
- const rtl::OUString aName = *GetItemName( maPageInfo.mnSelItem );
- pSaveDim->SetCurrentPage( &aName );
+ const String* pName = GetItemName( maPageInfo.mnSelItem );
+ if (pName)
+ {
+ const OUString aName(*pName);
+ pSaveDim->SetCurrentPage(&aName);
+ }
}
}
diff --git a/sc/source/filter/excel/xistyle.cxx b/sc/source/filter/excel/xistyle.cxx
index d4eb332b2fb0..11381e54bb4e 100644
--- a/sc/source/filter/excel/xistyle.cxx
+++ b/sc/source/filter/excel/xistyle.cxx
@@ -1321,8 +1321,8 @@ void XclImpXF::ApplyPatternToAttrList(
pPat = static_cast<const ScPatternAttr*>(&aCache.ApplyTo(*pPat, true));
}
-
- if (pPat)
+ // Make sure we skip unnamed styles.
+ if (pPat && pPat->GetStyleName())
{
// Check for a gap between the last entry and this one.
bool bHasGap = false;
diff --git a/sc/source/filter/inc/excform.hxx b/sc/source/filter/inc/excform.hxx
index 0744bdf52c64..ebc3696e9a0f 100644
--- a/sc/source/filter/inc/excform.hxx
+++ b/sc/source/filter/inc/excform.hxx
@@ -52,7 +52,7 @@ protected:
const XclBiff meBiff;
// ---------------------------------------------------------------
- void DoMulArgs( DefTokenId eId, sal_uInt8 nNumArgs, sal_uInt8 mnMinParamCount = 0 );
+ void DoMulArgs( DefTokenId eId, sal_uInt8 nNumArgs );
void ExcRelToScRel( sal_uInt16 nRow, sal_uInt8 nCol, ScSingleRefData&, const sal_Bool bName );
@@ -104,6 +104,7 @@ inline sal_Bool ExcelToSc::IsComplRowRange( const sal_uInt16 nRow1, const sal_uI
// ============================================================================
class XclImpLinkManager;
+class XclImpExtName;
class ExcelToSc8 : public ExcelToSc
{
@@ -111,9 +112,10 @@ public:
struct ExternalTabInfo
{
- String maTabName;
- sal_uInt16 mnFileId;
- bool mbExternal;
+ ScRange maRange;
+ ::rtl::OUString maTabName;
+ sal_uInt16 mnFileId;
+ bool mbExternal;
ExternalTabInfo();
};
@@ -128,6 +130,7 @@ private:
virtual bool Read3DTabReference( sal_uInt16 nIxti, SCTAB& rFirstTab, SCTAB& rLastTab, ExternalTabInfo& rExtInfo );
+ bool HandleOleLink(sal_uInt16 nXtiIndex, const XclImpExtName& rExtName, ExternalTabInfo& rExtInfo);
public:
ExcelToSc8( const XclImpRoot& rRoot );
virtual ~ExcelToSc8();
diff --git a/sc/source/filter/inc/xilink.hxx b/sc/source/filter/inc/xilink.hxx
index 2f06ddb2f7b0..2b2e9ac8a03c 100644
--- a/sc/source/filter/inc/xilink.hxx
+++ b/sc/source/filter/inc/xilink.hxx
@@ -32,6 +32,7 @@
#include <map>
#include "xllink.hxx"
#include "xiroot.hxx"
+#include "scmatrix.hxx"
/* ============================================================================
Classes for import of different kinds of internal/external references.
@@ -113,6 +114,19 @@ class XclImpSupbook;
@descr Supported: External defined names, AddIn names, DDE links and OLE objects. */
class XclImpExtName
{
+ /**
+ * MOper, multiple operands, stores cached values of external range
+ * specified in the record.
+ */
+ class MOper
+ {
+ public:
+ MOper(XclImpStream& rStrm);
+ const ScMatrix& GetCache() const;
+ private:
+ ScMatrixRef mxCached;
+ };
+
public:
/** Reads the external name from the stream. */
explicit XclImpExtName( const XclImpSupbook& rSupbook, XclImpStream& rStrm,
@@ -125,6 +139,14 @@ public:
void CreateExtNameData( ScDocument& rDoc, sal_uInt16 nFileId ) const;
+ /**
+ * Create OLE link data. OLE link data is converted to external
+ * reference, since OLE link doesn't work cross-platform, and is not very
+ * reliable even on Windows.
+ */
+ bool CreateOleData(ScDocument& rDoc, const ::rtl::OUString& rUrl,
+ sal_uInt16& rFileId, ::rtl::OUString& rTabName, ScRange& rRange) const;
+
bool HasFormulaTokens() const;
inline XclImpExtNameType GetType() const { return meType; }
@@ -136,6 +158,7 @@ private:
typedef ::std::auto_ptr< ScTokenArray > TokenArrayPtr;
XclImpCachedMatrixPtr mxDdeMatrix; /// Cached results of the DDE link.
+ MOper* mpMOper; /// Cached values for OLE link
TokenArrayPtr mxArray; /// Formula tokens for external name.
String maName; /// The name of the external name.
sal_uInt32 mnStorageId; /// Storage ID for OLE object storages.
diff --git a/sc/source/filter/inc/xipivot.hxx b/sc/source/filter/inc/xipivot.hxx
index 86fc881d04e7..8a8e6b7696dd 100644
--- a/sc/source/filter/inc/xipivot.hxx
+++ b/sc/source/filter/inc/xipivot.hxx
@@ -190,6 +190,7 @@ public:
/** Reads the entire pivot cache stream. Uses decrypter from passed stream. */
void ReadPivotCacheStream( XclImpStream& rStrm );
+ bool HasCacheRecords() const;
bool IsRefreshOnLoad() const;
bool IsValid() const;
diff --git a/sc/source/filter/inc/xlstring.hxx b/sc/source/filter/inc/xlstring.hxx
index 15adf3f919d9..c431a594ad1a 100644
--- a/sc/source/filter/inc/xlstring.hxx
+++ b/sc/source/filter/inc/xlstring.hxx
@@ -46,7 +46,7 @@ const XclStrFlags EXC_STR_NOHEADER = 0x0010; /// Export: Don't write
// ----------------------------------------------------------------------------
const sal_uInt16 EXC_STR_MAXLEN_8BIT = 0x00FF;
-const sal_uInt16 EXC_STR_MAXLEN = 0xFFFF;
+const sal_uInt16 EXC_STR_MAXLEN = 0x7FFF;
const sal_uInt8 EXC_STRF_16BIT = 0x01;
const sal_uInt8 EXC_STRF_FAREAST = 0x04;
diff --git a/sc/source/filter/xml/XMLExportDataPilot.cxx b/sc/source/filter/xml/XMLExportDataPilot.cxx
index 968c37f0e1b5..d0071a9428b2 100644
--- a/sc/source/filter/xml/XMLExportDataPilot.cxx
+++ b/sc/source/filter/xml/XMLExportDataPilot.cxx
@@ -858,24 +858,24 @@ void ScXMLExportDataPilot::WriteDataPilots(const uno::Reference <sheet::XSpreads
case sheet::DataImportMode_NONE : break;
case sheet::DataImportMode_QUERY :
{
- rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATABASE_NAME, rtl::OUString(pImpSource->aDBName));
- rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_QUERY_NAME, rtl::OUString(pImpSource->aObject));
+ rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATABASE_NAME, pImpSource->aDBName);
+ rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_QUERY_NAME, pImpSource->aObject);
SvXMLElementExport aElemID(rExport, XML_NAMESPACE_TABLE, XML_DATABASE_SOURCE_QUERY, sal_True, sal_True);
rExport.CheckAttrList();
}
break;
case sheet::DataImportMode_TABLE :
{
- rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATABASE_NAME, rtl::OUString(pImpSource->aDBName));
- rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_TABLE_NAME, rtl::OUString(pImpSource->aObject));
+ rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATABASE_NAME, pImpSource->aDBName);
+ rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_TABLE_NAME, pImpSource->aObject);
SvXMLElementExport aElemID(rExport, XML_NAMESPACE_TABLE, XML_DATABASE_SOURCE_TABLE, sal_True, sal_True);
rExport.CheckAttrList();
}
break;
case sheet::DataImportMode_SQL :
{
- rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATABASE_NAME, rtl::OUString(pImpSource->aDBName));
- rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_SQL_STATEMENT, rtl::OUString(pImpSource->aObject));
+ rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATABASE_NAME, pImpSource->aDBName);
+ rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_SQL_STATEMENT, pImpSource->aObject);
if (!pImpSource->bNative)
rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_PARSE_SQL_STATEMENT, XML_TRUE);
SvXMLElementExport aElemID(rExport, XML_NAMESPACE_TABLE, XML_DATABASE_SOURCE_SQL, sal_True, sal_True);
diff --git a/sc/source/filter/xml/xmlcelli.cxx b/sc/source/filter/xml/xmlcelli.cxx
index 06214774a91e..a7755b840bca 100644
--- a/sc/source/filter/xml/xmlcelli.cxx
+++ b/sc/source/filter/xml/xmlcelli.cxx
@@ -1089,7 +1089,7 @@ void ScXMLTableRowCellContext::EndElement()
pCellObj->SetFormulaWithGrammar( pOUFormula->first, pOUFormula->second, eGrammar);
if (bFormulaTextResult && pOUTextValue && pOUTextValue->getLength())
pCellObj->SetFormulaResultString( *pOUTextValue);
- else if (fValue != 0.0)
+ else
pCellObj->SetFormulaResultDouble( fValue);
}
}
diff --git a/sc/source/ui/app/inputwin.cxx b/sc/source/ui/app/inputwin.cxx
index 91809a4f42be..bc3753c90f67 100644
--- a/sc/source/ui/app/inputwin.cxx
+++ b/sc/source/ui/app/inputwin.cxx
@@ -1528,7 +1528,7 @@ ScNameInputType lcl_GetInputType( const String& rText )
sal_Int32 nNumeric;
if ( aRange.Parse( rText, pDoc, eConv ) & SCA_VALID )
- eRet = SC_NAME_INPUT_NAMEDRANGE;
+ eRet = SC_NAME_INPUT_RANGE;
else if ( aAddress.Parse( rText, pDoc, eConv ) & SCA_VALID )
eRet = SC_NAME_INPUT_CELL;
else if ( aRangeUtil.MakeRangeFromName( rText, pDoc, nTab, aRange, RUTL_NAMES, eConv ) )
@@ -1657,6 +1657,10 @@ void ScPosWnd::DoEnter()
ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
if ( pViewSh )
{
+ ScViewData* pViewData = pViewSh->GetViewData();
+ ScDocShell* pDocShell = pViewData->GetDocShell();
+ ScDocument* pDoc = pDocShell->GetDocument();
+
ScNameInputType eType = lcl_GetInputType( aText );
if ( eType == SC_NAME_INPUT_BAD_NAME || eType == SC_NAME_INPUT_BAD_SELECTION )
{
@@ -1665,9 +1669,6 @@ void ScPosWnd::DoEnter()
}
else if ( eType == SC_NAME_INPUT_DEFINE )
{
- ScViewData* pViewData = pViewSh->GetViewData();
- ScDocShell* pDocShell = pViewData->GetDocShell();
- ScDocument* pDoc = pDocShell->GetDocument();
ScRangeName* pNames = pDoc->GetRangeName();
ScRange aSelection;
if ( pNames && !pNames->findByName(aText) &&
@@ -1690,7 +1691,15 @@ void ScPosWnd::DoEnter()
}
else
{
- // for all selection types, excecute the SID_CURRENTCELL slot
+ // for all selection types, excecute the SID_CURRENTCELL slot.
+ if (eType == SC_NAME_INPUT_CELL || eType == SC_NAME_INPUT_RANGE)
+ {
+ // Note that SID_CURRENTCELL always expects address to
+ // be in Calc A1 format. Convert the text.
+ ScRange aRange;
+ aRange.ParseAny(aText, pDoc, pDoc->GetAddressConvention());
+ aRange.Format(aText, SCR_ABS_3D, pDoc, ::formula::FormulaGrammar::CONV_OOO);
+ }
SfxStringItem aPosItem( SID_CURRENTCELL, aText );
SfxBoolItem aUnmarkItem( FN_PARAM_1, sal_True ); // remove existing selection
diff --git a/sc/source/ui/attrdlg/scabstdlg.cxx b/sc/source/ui/attrdlg/scabstdlg.cxx
index 7ab625e03f61..db85484e6228 100644
--- a/sc/source/ui/attrdlg/scabstdlg.cxx
+++ b/sc/source/ui/attrdlg/scabstdlg.cxx
@@ -48,7 +48,8 @@ ScAbstractDialogFactory* ScAbstractDialogFactory::Create()
OUStringBuffer aStrBuf;
aStrBuf.appendAscii( SVLIBRARY("scui") );
- if ( aDialogLibrary.is() || aDialogLibrary.loadRelative( &thisModule, aStrBuf.makeStringAndClear() ) )
+ if ( aDialogLibrary.is() || aDialogLibrary.loadRelative( &thisModule, aStrBuf.makeStringAndClear(),
+ SAL_LOADMODULE_GLOBAL | SAL_LOADMODULE_LAZY ) )
fp = ( ScAbstractDialogFactory* (__LOADONCALLAPI*)() )
aDialogLibrary.getFunctionSymbol( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CreateDialogFactory")) );
if ( fp )
diff --git a/sc/source/ui/cctrl/dpcontrol.cxx b/sc/source/ui/cctrl/dpcontrol.cxx
index 2a5d415410dc..380cdf9cfeef 100644
--- a/sc/source/ui/cctrl/dpcontrol.cxx
+++ b/sc/source/ui/cctrl/dpcontrol.cxx
@@ -1032,6 +1032,7 @@ ScDPFieldPopupWindow::ScDPFieldPopupWindow(Window* pParent, ScDocument* pDoc) :
maChkToggleAll.SetPosSizePixel(aPos, aSize);
maChkToggleAll.SetFont(getLabelFont());
maChkToggleAll.SetText(ScRscStrLoader(RID_POPUP_FILTER, STR_BTN_TOGGLE_ALL).GetString());
+ maChkToggleAll.SetTextColor(rStyle.GetMenuTextColor());
maChkToggleAll.SetControlBackground(rStyle.GetMenuColor());
maChkToggleAll.SetClickHdl( LINK(this, ScDPFieldPopupWindow, TriStateHdl) );
maChkToggleAll.Show();
diff --git a/sc/source/ui/dbgui/dapidata.cxx b/sc/source/ui/dbgui/dapidata.cxx
index 63d11e1141ae..c73d701a6eb9 100644
--- a/sc/source/ui/dbgui/dapidata.cxx
+++ b/sc/source/ui/dbgui/dapidata.cxx
@@ -130,7 +130,7 @@ void ScDataPilotDatabaseDlg::GetValues( ScImportSourceDesc& rDesc )
rDesc.aDBName = aLbDatabase.GetSelectEntry();
rDesc.aObject = aCbObject.GetText();
- if ( !rDesc.aDBName.Len() || !rDesc.aObject.Len() )
+ if (rDesc.aDBName.isEmpty() || rDesc.aObject.isEmpty())
rDesc.nType = sheet::DataImportMode_NONE;
else if ( nSelect == DP_TYPELIST_TABLE )
rDesc.nType = sheet::DataImportMode_TABLE;
diff --git a/sc/source/ui/dbgui/dpuiglobal.hxx b/sc/source/ui/dbgui/dpuiglobal.hxx
index b64875030bcf..d27d8278d83b 100644
--- a/sc/source/ui/dbgui/dpuiglobal.hxx
+++ b/sc/source/ui/dbgui/dpuiglobal.hxx
@@ -33,7 +33,6 @@
#define OUTER_MARGIN_VER 4
#define DATA_FIELD_BTN_GAP 2 // must be an even number
#define ROW_FIELD_BTN_GAP 2 // must be an even number
-#define FIELD_BTN_WIDTH 81
#define FIELD_BTN_HEIGHT 23
#define SELECT_FIELD_BTN_SPACE 2
#define FIELD_AREA_GAP 3 // gap between row/column/data/page areas
diff --git a/sc/source/ui/dbgui/fieldwnd.cxx b/sc/source/ui/dbgui/fieldwnd.cxx
index 32ba4a949769..061900ce5e4d 100644
--- a/sc/source/ui/dbgui/fieldwnd.cxx
+++ b/sc/source/ui/dbgui/fieldwnd.cxx
@@ -611,6 +611,11 @@ void ScDPFieldControlBase::DrawInvertSelection()
InvertTracking(aSel, SHOWTRACK_SMALL | SHOWTRACK_WINDOW);
}
+Size ScDPFieldControlBase::GetStdFieldBtnSize() const
+{
+ return mpDlg->GetStdFieldBtnSize();
+}
+
bool ScDPFieldControlBase::IsShortenedText( size_t nIndex ) const
{
const FieldNames& rFields = GetFieldNames();
@@ -726,7 +731,7 @@ Point ScDPHorFieldControl::GetFieldPosition( size_t nIndex )
Size ScDPHorFieldControl::GetFieldSize() const
{
- return Size(FIELD_BTN_WIDTH, FIELD_BTN_HEIGHT);
+ return GetStdFieldBtnSize();
}
bool ScDPHorFieldControl::GetFieldIndex( const Point& rPos, size_t& rnIndex )
@@ -1032,7 +1037,7 @@ Point ScDPRowFieldControl::GetFieldPosition(size_t nIndex)
Size ScDPRowFieldControl::GetFieldSize() const
{
- return Size(FIELD_BTN_WIDTH, FIELD_BTN_HEIGHT);
+ return GetStdFieldBtnSize();
}
bool ScDPRowFieldControl::GetFieldIndex( const Point& rPos, size_t& rnIndex )
diff --git a/sc/source/ui/dbgui/pvlaydlg.cxx b/sc/source/ui/dbgui/pvlaydlg.cxx
index d7109d1f7315..fa063bcf7ab8 100644
--- a/sc/source/ui/dbgui/pvlaydlg.cxx
+++ b/sc/source/ui/dbgui/pvlaydlg.cxx
@@ -1132,6 +1132,14 @@ void ScDPLayoutDlg::NotifyRemoveField( ScDPFieldType eType, size_t nFieldIndex )
RemoveField( eType, nFieldIndex );
}
+Size ScDPLayoutDlg::GetStdFieldBtnSize() const
+{
+ // This size is static but is platform dependent. The field button size
+ // is calculated relative to the size of the OK button.
+ double w = static_cast<double>(aBtnOk.GetSizePixel().Width()) * 0.70;
+ return Size(static_cast<long>(w), FIELD_BTN_HEIGHT);
+}
+
void ScDPLayoutDlg::Deactivate()
{
/* If the dialog has been deactivated (click into document), the LoseFocus
@@ -1290,10 +1298,18 @@ Point ScDPLayoutDlg::DlgPos2WndPos( const Point& rPt, Window& rWnd )
void ScDPLayoutDlg::CalcWndSizes()
{
+ // The pivot.src file only specifies the positions of the controls. Here,
+ // we calculate appropriate size of each control based on how they are
+ // positioned relative to each other.
+
// row/column/data area sizes
- long nFldW = FIELD_BTN_WIDTH;
- long nFldH = FIELD_BTN_HEIGHT;
- aWndData.SetSizePixel(Size(338, 185));
+ long nFldW = GetStdFieldBtnSize().Width();
+ long nFldH = GetStdFieldBtnSize().Height();
+
+ aWndData.SetSizePixel(
+ Size(aWndSelect.GetPosPixel().X() - aWndData.GetPosPixel().X() - FIELD_AREA_GAP*4,
+ 185));
+
aWndPage.SetSizePixel(
Size(aWndData.GetSizePixel().Width() + 85,
aWndCol.GetPosPixel().Y() - aWndPage.GetPosPixel().Y() - FIELD_AREA_GAP));
@@ -1434,11 +1450,24 @@ void ScDPLayoutDlg::UpdateSrcRange()
switch (eSrcType)
{
case SRC_REF:
+ {
// data source is a range reference.
if (inSheet.GetSourceRange() == aNewRange)
// new range is identical to the current range. Nothing to do.
return;
inSheet.SetSourceRange(aNewRange);
+ sal_uLong nError = inSheet.CheckSourceRange();
+ if (nError)
+ {
+ // The error number corresponds with string ID for the error
+ // message. In the future we should display the error message
+ // somewhere in the dialog to let the user know of the reason
+ // for error.
+ aEdInPos.SetRefValid(false);
+ aBtnOk.Disable();
+ return;
+ }
+ }
break;
case SRC_NAME:
// data source is a range name.
diff --git a/sc/source/ui/docshell/docfunc.cxx b/sc/source/ui/docshell/docfunc.cxx
index e9376dd15668..62ced922b01f 100644
--- a/sc/source/ui/docshell/docfunc.cxx
+++ b/sc/source/ui/docshell/docfunc.cxx
@@ -4023,8 +4023,7 @@ sal_Bool ScDocFunc::FillSimple( const ScRange& rRange, const ScMarkData* pTabMar
{
rDocShell.GetUndoManager()->AddUndoAction(
new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark,
- eDir, FILL_SIMPLE, FILL_DAY, MAXDOUBLE, 1.0, 1e307,
- pDoc->GetRangeName()->GetSharedMaxIndex()+1 ) );
+ eDir, FILL_SIMPLE, FILL_DAY, MAXDOUBLE, 1.0, 1e307) );
}
rDocShell.PostPaintGridAll();
@@ -4143,8 +4142,7 @@ sal_Bool ScDocFunc::FillSeries( const ScRange& rRange, const ScMarkData* pTabMar
{
rDocShell.GetUndoManager()->AddUndoAction(
new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark,
- eDir, eCmd, eDateCmd, fStart, fStep, fMax,
- pDoc->GetRangeName()->GetSharedMaxIndex()+1 ) );
+ eDir, eCmd, eDateCmd, fStart, fStep, fMax) );
}
bSuccess = sal_True;
@@ -4271,8 +4269,7 @@ sal_Bool ScDocFunc::FillAuto( ScRange& rRange, const ScMarkData* pTabMark, FillD
{
rDocShell.GetUndoManager()->AddUndoAction(
new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark,
- eDir, eCmd, eDateCmd, MAXDOUBLE, fStep, fMax,
- pDoc->GetRangeName()->GetSharedMaxIndex()+1 ) );
+ eDir, eCmd, eDateCmd, MAXDOUBLE, fStep, fMax) );
}
rDocShell.PostPaintGridAll();
@@ -4344,17 +4341,14 @@ sal_Bool ScDocFunc::MergeCells( const ScCellMergeOption& rOption, sal_Bool bCont
for( aPos.SetRow( nStartRow ); !bHasNotes && (aPos.Row() <= nEndRow); aPos.IncRow() )
bHasNotes = ((aPos.Col() != nStartCol) || (aPos.Row() != nStartRow)) && (pDoc->GetNote( aPos ) != 0);
- if (bNeedContents || bHasNotes || rOption.mbCenter)
+ if (!pUndoDoc)
{
- if (!pUndoDoc)
- {
- pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
- pUndoDoc->InitUndo(pDoc, nTab1, nTab2);
- }
- // note captions are collected by drawing undo
- pDoc->CopyToDocument( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab,
- IDF_ALL|IDF_NOCAPTIONS, false, pUndoDoc );
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo(pDoc, nTab1, nTab2);
}
+ // note captions are collected by drawing undo
+ pDoc->CopyToDocument( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab,
+ IDF_ALL|IDF_NOCAPTIONS, false, pUndoDoc );
if( bHasNotes )
pDoc->BeginDrawUndo();
}
diff --git a/sc/source/ui/docshell/docsh5.cxx b/sc/source/ui/docshell/docsh5.cxx
index 368a1f39edd3..1bd3bfecbd53 100644
--- a/sc/source/ui/docshell/docsh5.cxx
+++ b/sc/source/ui/docshell/docsh5.cxx
@@ -924,37 +924,37 @@ sal_Bool ScDocShell::MoveTable( SCTAB nSrcTab, SCTAB nDestTab, sal_Bool bCopy, s
}
sal_Bool bVbaEnabled = aDocument.IsInVBAMode();
- if ( bVbaEnabled )
- {
- String aLibName( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) );
- Reference< XLibraryContainer > xLibContainer = GetBasicContainer();
- Reference< XVBACompatibility > xVBACompat( xLibContainer, UNO_QUERY );
-
- if ( xVBACompat.is() )
- {
- aLibName = xVBACompat->getProjectName();
- }
-
- SCTAB nTabToUse = nDestTab;
- if ( nDestTab == SC_TAB_APPEND )
- nTabToUse = aDocument.GetMaxTableNumber() - 1;
- String sCodeName;
- String sSource;
- Reference< XNameContainer > xLib;
- if( xLibContainer.is() )
- {
- com::sun::star::uno::Any aLibAny = xLibContainer->getByName( aLibName );
- aLibAny >>= xLib;
- }
- if( xLib.is() )
- {
- rtl::OUString sRTLSource;
- xLib->getByName( sSrcCodeName ) >>= sRTLSource;
- sSource = sRTLSource;
- }
- VBA_InsertModule( aDocument, nTabToUse, sCodeName, sSource );
- }
+ if ( bVbaEnabled )
+ {
+ String aLibName( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) );
+ Reference< XLibraryContainer > xLibContainer = GetBasicContainer();
+ Reference< XVBACompatibility > xVBACompat( xLibContainer, UNO_QUERY );
+
+ if ( xVBACompat.is() )
+ {
+ aLibName = xVBACompat->getProjectName();
+ }
+
+ SCTAB nTabToUse = nDestTab;
+ if ( nDestTab == SC_TAB_APPEND )
+ nTabToUse = aDocument.GetMaxTableNumber() - 1;
+ String sCodeName;
+ String sSource;
+ Reference< XNameContainer > xLib;
+ if( xLibContainer.is() )
+ {
+ com::sun::star::uno::Any aLibAny = xLibContainer->getByName( aLibName );
+ aLibAny >>= xLib;
+ }
+ if( xLib.is() )
+ {
+ rtl::OUString sRTLSource;
+ xLib->getByName( sSrcCodeName ) >>= sRTLSource;
+ sSource = sRTLSource;
}
+ VBA_InsertModule( aDocument, nTabToUse, sCodeName, sSource );
+ }
+ }
Broadcast( ScTablesHint( SC_TAB_COPIED, nSrcTab, nDestTab ) );
}
else
diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx
index f9de3e8c0c48..1bfdc8b5b88f 100644
--- a/sc/source/ui/docshell/externalrefmgr.cxx
+++ b/sc/source/ui/docshell/externalrefmgr.cxx
@@ -74,6 +74,7 @@ using ::rtl::OUString;
using ::std::vector;
using ::std::find;
using ::std::find_if;
+using ::std::remove_if;
using ::std::distance;
using ::std::pair;
using ::std::list;
@@ -85,7 +86,7 @@ using namespace formula;
namespace {
-class TabNameSearchPredicate : public unary_function<bool, ScExternalRefCache::TableName>
+class TabNameSearchPredicate : public unary_function<ScExternalRefCache::TableName, bool>
{
public:
explicit TabNameSearchPredicate(const String& rSearchName) :
@@ -201,6 +202,56 @@ private:
ScDocument* mpDoc;
};
+/**
+ * Check whether a named range contains an external reference to a
+ * particular document.
+ */
+bool hasRefsToSrcDoc(ScRangeData& rData, sal_uInt16 nFileId)
+{
+ ScTokenArray* pArray = rData.GetCode();
+ if (!pArray)
+ return false;
+
+ pArray->Reset();
+ ScToken* p = static_cast<ScToken*>(pArray->GetNextReference());
+ for (; p; p = static_cast<ScToken*>(pArray->GetNextReference()))
+ {
+ if (!p->IsExternalRef())
+ continue;
+
+ if (p->GetIndex() == nFileId)
+ return true;
+ }
+ return false;
+}
+
+class EraseRangeByIterator : unary_function<ScRangeName::iterator, void>
+{
+ ScRangeName& mrRanges;
+public:
+ EraseRangeByIterator(ScRangeName& rRanges) : mrRanges(rRanges) {}
+ void operator() (const ScRangeName::iterator& itr)
+ {
+ mrRanges.erase(itr);
+ }
+};
+
+/**
+ * Remove all named ranges that contain references to specified source
+ * document.
+ */
+void removeRangeNamesBySrcDoc(ScRangeName& rRanges, sal_uInt16 nFileId)
+{
+ ScRangeName::iterator itr = rRanges.begin(), itrEnd = rRanges.end();
+ vector<ScRangeName::iterator> v;
+ for (; itr != itrEnd; ++itr)
+ {
+ if (hasRefsToSrcDoc(*itr, nFileId))
+ v.push_back(itr);
+ }
+ for_each(v.begin(), v.end(), EraseRangeByIterator(rRanges));
+}
+
}
// ============================================================================
@@ -2358,9 +2409,14 @@ void lcl_removeByFileId(sal_uInt16 nFileId, MapContainer& rMap)
{
typename MapContainer::iterator itr = rMap.find(nFileId);
if (itr != rMap.end())
+ {
+ // Close this document shell.
+ itr->second.maShell->DoClose();
rMap.erase(itr);
+ }
}
+
void ScExternalRefManager::refreshNames(sal_uInt16 nFileId)
{
maRefCache.clearCache(nFileId);
@@ -2389,6 +2445,21 @@ void ScExternalRefManager::breakLink(sal_uInt16 nFileId)
maRefCells.erase(nFileId);
}
+ // Remove all named ranges that reference this document.
+
+ // Global named ranges.
+ ScRangeName* pRanges = mpDoc->GetRangeName();
+ if (pRanges)
+ removeRangeNamesBySrcDoc(*pRanges, nFileId);
+
+ // Sheet-local named ranges.
+ for (SCTAB i = 0, n = mpDoc->GetTableCount(); i < n; ++i)
+ {
+ pRanges = mpDoc->GetRangeName(i);
+ if (pRanges)
+ removeRangeNamesBySrcDoc(*pRanges, nFileId);
+ }
+
lcl_removeByFileId(nFileId, maDocShells);
if (maDocShells.empty())
@@ -2528,6 +2599,9 @@ void ScExternalRefManager::purgeStaleSrcDocument(sal_Int32 nTimeOut)
sal_Int32 nSinceLastAccess = (Time() - itr->second.maLastAccess).GetTime();
if (nSinceLastAccess < nTimeOut)
aNewDocShells.insert(*itr);
+ else
+ // Timed out. Let's close this.
+ itr->second.maShell->DoClose();
}
maDocShells.swap(aNewDocShells);
diff --git a/sc/source/ui/inc/fieldwnd.hxx b/sc/source/ui/inc/fieldwnd.hxx
index 78358557444c..edd8aec6a568 100644
--- a/sc/source/ui/inc/fieldwnd.hxx
+++ b/sc/source/ui/inc/fieldwnd.hxx
@@ -195,6 +195,7 @@ protected:
void AppendPaintable(Window* p);
void DrawPaintables();
void DrawInvertSelection();
+ Size GetStdFieldBtnSize() const;
/** @return The new selection index after moving to the given direction. */
virtual size_t CalcNewFieldIndex( SCsCOL nDX, SCsROW nDY ) const = 0;
diff --git a/sc/source/ui/inc/output.hxx b/sc/source/ui/inc/output.hxx
index 81eee1acabda..d8c9f24731e7 100644
--- a/sc/source/ui/inc/output.hxx
+++ b/sc/source/ui/inc/output.hxx
@@ -116,11 +116,14 @@ private:
explicit DrawEditParam(const ScPatternAttr* pPattern, const SfxItemSet* pCondSet, bool bCellIsValue);
+ bool readCellContent(ScDocument* pDoc, bool bShowNullValues, bool bShowFormulas, bool bSyntaxMode, bool bUseStyleColor, bool bForceAutoColor, bool& rWrapFields);
+ void setPatternToEngine(bool bUseStyleColor);
void calcMargins(long& rTop, long& rLeft, long& rBottom, long& rRight, double nPPTX, double nPPTY) const;
void calcPaperSize(Size& rPaperSize, const Rectangle& rAlignRect, double nPPTX, double nPPTY) const;
void getEngineSize(ScFieldEditEngine* pEngine, long& rWidth, long& rHeight) const;
long getEngineWidth(ScFieldEditEngine* pEngine) const;
bool hasLineBreak() const;
+ bool isHyperlinkCell() const;
/**
* When the text is vertically oriented, the text is either rotated 90
@@ -129,8 +132,20 @@ private:
*/
bool isVerticallyOriented() const;
- void setAlignmentItems(ScFieldEditEngine* pEngine, ScBaseCell* pCell);
+ /**
+ * Calculate offset position for vertically oriented (either
+ * top-bottom or bottom-top orientation) text.
+ *
+ * @param rLogicStart initial position in pixels. When the call is
+ * finished, this parameter will store the new
+ * position.
+ */
+ void calcStartPosForVertical(Point& rLogicStart, long nCellWidth, long nEngineWidth, long nTopM, OutputDevice* pRefDevice);
+
+ void setAlignmentToEngine();
bool adjustHorAlignment(ScFieldEditEngine* pEngine);
+ void adjustForRTL();
+ void adjustForHyperlinkInPDF(Point aURLStart, OutputDevice* pDev);
};
OutputDevice* pDev; // Device
@@ -236,6 +251,10 @@ private:
drawinglayer::processor2d::BaseProcessor2D* CreateProcessor2D( );
void DrawEditStandard(DrawEditParam& rParam);
+ void DrawEditBottomTop(DrawEditParam& rParam);
+ void DrawEditTopBottom(DrawEditParam& rParam);
+ void DrawEditStacked(DrawEditParam& rParam);
+ void DrawEditAsianVertical(DrawEditParam& rParam);
public:
ScOutputData( OutputDevice* pNewDev, ScOutputType eNewType,
diff --git a/sc/source/ui/inc/pvlaydlg.hxx b/sc/source/ui/inc/pvlaydlg.hxx
index 19176e7fdc61..875f25dbcde1 100644
--- a/sc/source/ui/inc/pvlaydlg.hxx
+++ b/sc/source/ui/inc/pvlaydlg.hxx
@@ -104,6 +104,8 @@ public:
void NotifyMoveFieldToEnd ( ScDPFieldType eToType );
void NotifyRemoveField ( ScDPFieldType eType, size_t nFieldIndex );
+ Size GetStdFieldBtnSize() const;
+
protected:
virtual void Deactivate();
diff --git a/sc/source/ui/inc/undoblk.hxx b/sc/source/ui/inc/undoblk.hxx
index d8617490219a..16fc7591ac08 100644
--- a/sc/source/ui/inc/undoblk.hxx
+++ b/sc/source/ui/inc/undoblk.hxx
@@ -421,8 +421,7 @@ public:
ScDocument* pNewUndoDoc, const ScMarkData& rMark,
FillDir eNewFillDir,
FillCmd eNewFillCmd, FillDateCmd eNewFillDateCmd,
- double fNewStartValue, double fNewStepValue, double fNewMaxValue,
- sal_uInt16 nMaxShIndex );
+ double fNewStartValue, double fNewStepValue, double fNewMaxValue );
virtual ~ScUndoAutoFill();
virtual void Undo();
@@ -444,7 +443,6 @@ private:
double fMaxValue;
sal_uLong nStartChangeAction;
sal_uLong nEndChangeAction;
- sal_uInt16 nMaxSharedIndex;
void SetChangeTrack();
};
diff --git a/sc/source/ui/src/popup.src b/sc/source/ui/src/popup.src
index 01b9950183b6..38038897dfb8 100644
--- a/sc/source/ui/src/popup.src
+++ b/sc/source/ui/src/popup.src
@@ -44,7 +44,7 @@ Menu RID_POPUP_CELLS
{
Identifier = SID_CELL_FORMAT_RESET ;
HelpId = CMD_SID_CELL_FORMAT_RESET ;
- Text [ en-US ] = "~Clear Direct Formatting" ;
+ Text [ en-US ] = "Clear ~Direct Formatting" ;
};
//------------------------------
MenuItem { Separator = TRUE ; };
diff --git a/sc/source/ui/undo/undoblk3.cxx b/sc/source/ui/undo/undoblk3.cxx
index 446e3dede1c6..45ea822f2090 100644
--- a/sc/source/ui/undo/undoblk3.cxx
+++ b/sc/source/ui/undo/undoblk3.cxx
@@ -602,8 +602,7 @@ ScUndoAutoFill::ScUndoAutoFill( ScDocShell* pNewDocShell,
const ScRange& rRange, const ScRange& rSourceArea,
ScDocument* pNewUndoDoc, const ScMarkData& rMark,
FillDir eNewFillDir, FillCmd eNewFillCmd, FillDateCmd eNewFillDateCmd,
- double fNewStartValue, double fNewStepValue, double fNewMaxValue,
- sal_uInt16 nMaxShIndex )
+ double fNewStartValue, double fNewStepValue, double fNewMaxValue )
//
: ScBlockUndo( pNewDocShell, rRange, SC_UNDO_AUTOHEIGHT ),
//
@@ -615,8 +614,7 @@ ScUndoAutoFill::ScUndoAutoFill( ScDocShell* pNewDocShell,
eFillDateCmd ( eNewFillDateCmd ),
fStartValue ( fNewStartValue ),
fStepValue ( fNewStepValue ),
- fMaxValue ( fNewMaxValue ),
- nMaxSharedIndex ( nMaxShIndex)
+ fMaxValue ( fNewMaxValue )
{
SetChangeTrack();
}
@@ -626,7 +624,6 @@ ScUndoAutoFill::ScUndoAutoFill( ScDocShell* pNewDocShell,
ScUndoAutoFill::~ScUndoAutoFill()
{
- pDocShell->GetDocument()->EraseNonUsedSharedNames(nMaxSharedIndex);
delete pUndoDoc;
}
@@ -649,26 +646,6 @@ void ScUndoAutoFill::SetChangeTrack()
nStartChangeAction = nEndChangeAction = 0;
}
-namespace {
-
-bool eraseNameContaining(ScRangeName& rNames, const rtl::OUString& rCriteria)
-{
- ScRangeName::iterator itr = rNames.begin(), itrEnd = rNames.end();
- for (; itr != itrEnd; ++itr)
- {
- rtl::OUString aRName = itr->GetName();
- if (aRName.indexOf(rCriteria) >= 0)
- {
- // Criteria found. Erase this.
- rNames.erase(itr);
- return true;
- }
- }
- return false;
-}
-
-}
-
void ScUndoAutoFill::Undo()
{
BeginUndo();
@@ -698,29 +675,6 @@ void ScUndoAutoFill::Undo()
if (pViewShell)
pViewShell->CellContentChanged();
-// Shared-Names loeschen
-// Falls Undo ins Dokument gespeichert
-// => automatisches Loeschen am Ende
-// umarbeiten!!
-
- String aName = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("___SC_"));
- aName += String::CreateFromInt32(nMaxSharedIndex);
- aName += '_';
- ScRangeName* pRangeName = pDoc->GetRangeName();
- bool bHasFound = false;
- // Remove all range names that contain ___SC_...
- while (true)
- {
- bool bErased = eraseNameContaining(*pRangeName, aName);
- if (bErased)
- bHasFound = true;
- else
- break;
- }
-
- if (bHasFound)
- pRangeName->SetSharedMaxIndex(pRangeName->GetSharedMaxIndex()-1);
-
ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
if ( pChangeTrack )
pChangeTrack->Undo( nStartChangeAction, nEndChangeAction );
diff --git a/sc/source/ui/vba/excelvbahelper.cxx b/sc/source/ui/vba/excelvbahelper.cxx
index e7a1c74e9aa9..cbf30eba603d 100644
--- a/sc/source/ui/vba/excelvbahelper.cxx
+++ b/sc/source/ui/vba/excelvbahelper.cxx
@@ -39,6 +39,13 @@
#include "token.hxx"
#include "tokenarray.hxx"
+#include <com/sun/star/script/vba/VBAEventId.hpp>
+#include <com/sun/star/script/vba/XVBACompatibility.hpp>
+#include <com/sun/star/script/vba/XVBAEventProcessor.hpp>
+#include <com/sun/star/script/vba/XVBAModuleInfo.hpp>
+#include <com/sun/star/script/ModuleInfo.hpp>
+#include <com/sun/star/script/ModuleType.hpp>
+
using namespace ::com::sun::star;
using namespace ::ooo::vba;
@@ -457,6 +464,86 @@ getUnoSheetModuleObj( const uno::Reference< frame::XModel >& xModel, SCTAB nTab
return getUnoSheetModuleObj( xSheet );
}
+void setUpDocumentModules( const uno::Reference< sheet::XSpreadsheetDocument >& xDoc )
+{
+ uno::Reference< frame::XModel > xModel( xDoc, uno::UNO_QUERY );
+ ScDocShell* pShell = excel::getDocShell( xModel );
+ if ( pShell )
+ {
+ String aPrjName( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) );
+ pShell->GetBasicManager()->SetName( aPrjName );
+
+ /* Set library container to VBA compatibility mode. This will create
+ the VBA Globals object and store it in the Basic manager of the
+ document. */
+ uno::Reference<script::XLibraryContainer> xLibContainer = pShell->GetBasicContainer();
+ uno::Reference<script::vba::XVBACompatibility> xVBACompat( xLibContainer, uno::UNO_QUERY_THROW );
+ xVBACompat->setVBACompatibilityMode( sal_True );
+
+ if( xLibContainer.is() )
+ {
+ if( !xLibContainer->hasByName( aPrjName ) )
+ xLibContainer->createLibrary( aPrjName );
+ uno::Any aLibAny = xLibContainer->getByName( aPrjName );
+ uno::Reference< container::XNameContainer > xLib;
+ aLibAny >>= xLib;
+ if( xLib.is() )
+ {
+ uno::Reference< script::vba::XVBAModuleInfo > xVBAModuleInfo( xLib, uno::UNO_QUERY_THROW );
+ uno::Reference< lang::XMultiServiceFactory> xSF( pShell->GetModel(), uno::UNO_QUERY_THROW);
+ uno::Reference< container::XNameAccess > xVBACodeNamedObjectAccess( xSF->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.VBAObjectModuleObjectProvider"))), uno::UNO_QUERY_THROW );
+ // set up the module info for the workbook and sheets in the nealy created
+ // spreadsheet
+ ScDocument* pDoc = pShell->GetDocument();
+ String sCodeName = pDoc->GetCodeName();
+ if ( sCodeName.Len() == 0 )
+ {
+ sCodeName = String( RTL_CONSTASCII_USTRINGPARAM("ThisWorkbook") );
+ pDoc->SetCodeName( sCodeName );
+ }
+
+ std::vector< rtl::OUString > sDocModuleNames;
+ sDocModuleNames.push_back( sCodeName );
+
+ for ( SCTAB index = 0; index < pDoc->GetTableCount(); index++)
+ {
+ String aName;
+ pDoc->GetCodeName( index, aName );
+ sDocModuleNames.push_back( aName );
+ }
+
+ std::vector<rtl::OUString>::iterator it_end = sDocModuleNames.end();
+
+ for ( std::vector<rtl::OUString>::iterator it = sDocModuleNames.begin(); it != it_end; ++it )
+ {
+ script::ModuleInfo sModuleInfo;
+
+ uno::Any aName= xVBACodeNamedObjectAccess->getByName( *it );
+ sModuleInfo.ModuleObject.set( aName, uno::UNO_QUERY );
+ sModuleInfo.ModuleType = script::ModuleType::DOCUMENT;
+ xVBAModuleInfo->insertModuleInfo( *it, sModuleInfo );
+ if( xLib->hasByName( *it ) )
+ xLib->replaceByName( *it, uno::makeAny( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Option VBASupport 1\n") ) ) );
+ else
+ xLib->insertByName( *it, uno::makeAny( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Option VBASupport 1\n" ) ) ) );
+ }
+ }
+ }
+
+ /* Trigger the Workbook_Open event, event processor will register
+ itself as listener for specific events. */
+ try
+ {
+ uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents( pShell->GetDocument()->GetVbaEventProcessor(), uno::UNO_SET_THROW );
+ uno::Sequence< uno::Any > aArgs;
+ xVbaEvents->processVbaEvent( script::vba::VBAEventId::WORKBOOK_OPEN, aArgs );
+ }
+ catch( uno::Exception& )
+ {
+ }
+ }
+}
+
SfxItemSet*
ScVbaCellRangeAccess::GetDataSet( ScCellRangesBase* pRangeObj )
{
diff --git a/sc/source/ui/vba/excelvbahelper.hxx b/sc/source/ui/vba/excelvbahelper.hxx
index 13594b74e2b7..1cc0546a4fd7 100644
--- a/sc/source/ui/vba/excelvbahelper.hxx
+++ b/sc/source/ui/vba/excelvbahelper.hxx
@@ -36,6 +36,8 @@
#include <com/sun/star/table/XCellRange.hpp>
#include <com/sun/star/sheet/XSheetCellRangeContainer.hpp>
#include <com/sun/star/sheet/XSpreadsheet.hpp>
+#include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
#include <ooo/vba/XHelperInterface.hpp>
#include <formula/grammar.hxx>
@@ -77,6 +79,7 @@ ScDocShell* GetDocShellFromRange( const css::uno::Reference< css::uno::XInterfac
ScDocShell* GetDocShellFromRanges( const css::uno::Reference< css::sheet::XSheetCellRangeContainer >& xRanges ) throw ( css::uno::RuntimeException );
ScDocument* GetDocumentFromRange( const css::uno::Reference< css::uno::XInterface >& xRange ) throw ( css::uno::RuntimeException );
css::uno::Reference< css::frame::XModel > GetModelFromRange( const css::uno::Reference< css::uno::XInterface >& xRange ) throw ( css::uno::RuntimeException );
+void setUpDocumentModules( const css::uno::Reference< css::sheet::XSpreadsheetDocument >& xDoc );
// ============================================================================
@@ -86,6 +89,19 @@ public:
static SfxItemSet* GetDataSet( ScCellRangesBase* pRangeObj );
};
+// Extracts a implementation object ( via XUnoTunnel ) from an uno object
+// by default will throw if unsuccessful.
+template < typename ImplObject >
+ ImplObject* getImplFromDocModuleWrapper( const css::uno::Reference< css::uno::XInterface >& rxWrapperIf, bool bThrow = true ) throw (css::uno::RuntimeException)
+ {
+ ImplObject* pObj = NULL;
+ css::uno::Reference< css::lang::XUnoTunnel > xTunnel( rxWrapperIf, css::uno::UNO_QUERY );
+ if ( xTunnel.is() )
+ pObj = reinterpret_cast<ImplObject*>( xTunnel->getSomething(ImplObject::getUnoTunnelId()));
+ if ( bThrow && !pObj )
+ throw css::uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Internal error, can't exctract implementation object" ) ), rxWrapperIf );
+ return pObj;
+ }
// ============================================================================
} // namespace excel
diff --git a/sc/source/ui/vba/vbaapplication.cxx b/sc/source/ui/vba/vbaapplication.cxx
index 126b238d1dc5..74d1118c9493 100644
--- a/sc/source/ui/vba/vbaapplication.cxx
+++ b/sc/source/ui/vba/vbaapplication.cxx
@@ -924,8 +924,7 @@ ScVbaApplication::setIteration(sal_Bool bIteration) throw (uno::RuntimeException
uno::Reference< ooo::vba::excel::XWorkbook > xWorkbook;
uno::Any aWorkbook = xWorkbooks->Item(uno::makeAny(i), uno::Any());
aWorkbook >>= xWorkbook;
- ScVbaWorkbook* pWorkbook = static_cast< ScVbaWorkbook* > ( xWorkbook.get() );
-
+ ScVbaWorkbook* pWorkbook = excel::getImplFromDocModuleWrapper<ScVbaWorkbook>( xWorkbook );
uno::Reference< frame::XModel > xModel( pWorkbook->getDocModel(), uno::UNO_QUERY_THROW );
uno::Reference< beans::XPropertySet > xPropertySet( xModel, uno::UNO_QUERY_THROW );
xPropertySet->setPropertyValue( aPropName, aIteration );
diff --git a/sc/source/ui/vba/vbaworkbook.cxx b/sc/source/ui/vba/vbaworkbook.cxx
index bf880e473af3..57037cbbe4fa 100644
--- a/sc/source/ui/vba/vbaworkbook.cxx
+++ b/sc/source/ui/vba/vbaworkbook.cxx
@@ -233,6 +233,23 @@ ScVbaWorkbook::ScVbaWorkbook( uno::Sequence< uno::Any> const & args,
init();
}
+const uno::Sequence<sal_Int8>&
+ScVbaWorkbook::getUnoTunnelId()
+{
+ static uno::Sequence< sal_Int8 > aSeq;
+
+ if( !aSeq.getLength() )
+ {
+ static osl::Mutex aCreateMutex;
+ osl::Guard< osl::Mutex > aGuard( aCreateMutex );
+
+ aSeq.realloc( 16 );
+ rtl_createUuid( reinterpret_cast< sal_uInt8* >( aSeq.getArray() ), 0, sal_True );
+ }
+
+ return aSeq;
+}
+
uno::Reference< excel::XWorksheet >
ScVbaWorkbook::getActiveSheet() throw (uno::RuntimeException)
{
@@ -419,6 +436,17 @@ ScVbaWorkbook::getCodeName() throw (css::uno::RuntimeException)
return xModelProp->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CodeName" ) ) ).get< ::rtl::OUString >();
}
+sal_Int64
+ScVbaWorkbook::getSomething(const uno::Sequence<sal_Int8 >& rId ) throw(css::uno::RuntimeException)
+{
+ if (rId.getLength() == 16 &&
+ 0 == rtl_compareMemory( ScVbaWorksheet::getUnoTunnelId().getConstArray(), rId.getConstArray(), 16 ))
+ {
+ return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this));
+ }
+ return 0;
+}
+
namespace workbook
{
namespace sdecl = comphelper::service_decl;
diff --git a/sc/source/ui/vba/vbaworkbook.hxx b/sc/source/ui/vba/vbaworkbook.hxx
index 3f52e2683f3f..f51ce051d1a7 100644
--- a/sc/source/ui/vba/vbaworkbook.hxx
+++ b/sc/source/ui/vba/vbaworkbook.hxx
@@ -53,6 +53,8 @@ public:
ScVbaWorkbook( css::uno::Sequence< css::uno::Any > const& aArgs, css::uno::Reference< css::uno::XComponentContext >const& xContext );
virtual ~ScVbaWorkbook() {}
+ static const com::sun::star::uno::Sequence<sal_Int8>& getUnoTunnelId();
+
// Attributes
virtual ::sal_Bool SAL_CALL getProtectStructure() throw (css::uno::RuntimeException);
virtual css::uno::Reference< ov::excel::XWorksheet > SAL_CALL getActiveSheet() throw (css::uno::RuntimeException);
@@ -83,6 +85,8 @@ public:
virtual css::uno::Sequence<rtl::OUString> getServiceNames();
virtual css::uno::Reference< css::frame::XModel > getDocModel() { return mxModel; }
+ // XUnoTunnel
+ virtual ::sal_Int64 SAL_CALL getSomething(const css::uno::Sequence<sal_Int8 >& rId ) throw(css::uno::RuntimeException);
};
#endif /* SC_VBA_WORKBOOK_HXX */
diff --git a/sc/source/ui/vba/vbaworkbooks.cxx b/sc/source/ui/vba/vbaworkbooks.cxx
index 86b24c3dec92..39f6f66db091 100644
--- a/sc/source/ui/vba/vbaworkbooks.cxx
+++ b/sc/source/ui/vba/vbaworkbooks.cxx
@@ -70,86 +70,6 @@ using namespace ::com::sun::star;
const sal_Int16 CUSTOM_CHAR = 5;
-void setUpDocumentModules( const uno::Reference< sheet::XSpreadsheetDocument >& xDoc )
-{
- uno::Reference< frame::XModel > xModel( xDoc, uno::UNO_QUERY );
- ScDocShell* pShell = excel::getDocShell( xModel );
- if ( pShell )
- {
- String aPrjName( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) );
- pShell->GetBasicManager()->SetName( aPrjName );
-
- /* Set library container to VBA compatibility mode. This will create
- the VBA Globals object and store it in the Basic manager of the
- document. */
- uno::Reference<script::XLibraryContainer> xLibContainer = pShell->GetBasicContainer();
- uno::Reference<script::vba::XVBACompatibility> xVBACompat( xLibContainer, uno::UNO_QUERY_THROW );
- xVBACompat->setVBACompatibilityMode( sal_True );
-
- if( xLibContainer.is() )
- {
- if( !xLibContainer->hasByName( aPrjName ) )
- xLibContainer->createLibrary( aPrjName );
- uno::Any aLibAny = xLibContainer->getByName( aPrjName );
- uno::Reference< container::XNameContainer > xLib;
- aLibAny >>= xLib;
- if( xLib.is() )
- {
- uno::Reference< script::vba::XVBAModuleInfo > xVBAModuleInfo( xLib, uno::UNO_QUERY_THROW );
- uno::Reference< lang::XMultiServiceFactory> xSF( pShell->GetModel(), uno::UNO_QUERY_THROW);
- uno::Reference< container::XNameAccess > xVBACodeNamedObjectAccess( xSF->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.VBAObjectModuleObjectProvider"))), uno::UNO_QUERY_THROW );
- // set up the module info for the workbook and sheets in the nealy created
- // spreadsheet
- ScDocument* pDoc = pShell->GetDocument();
- String sCodeName = pDoc->GetCodeName();
- if ( sCodeName.Len() == 0 )
- {
- sCodeName = String( RTL_CONSTASCII_USTRINGPARAM("ThisWorkbook") );
- pDoc->SetCodeName( sCodeName );
- }
-
- std::vector< rtl::OUString > sDocModuleNames;
- sDocModuleNames.push_back( sCodeName );
-
- uno::Reference<container::XNameAccess > xSheets( xDoc->getSheets(), uno::UNO_QUERY_THROW );
- uno::Sequence< rtl::OUString > sSheets( xSheets->getElementNames() );
-
- for ( sal_Int32 index=0; index < sSheets.getLength() ; ++index )
- {
- sDocModuleNames.push_back( sSheets[ index ] );
- }
-
- std::vector<rtl::OUString>::iterator it_end = sDocModuleNames.end();
-
- for ( std::vector<rtl::OUString>::iterator it = sDocModuleNames.begin(); it != it_end; ++it )
- {
- script::ModuleInfo sModuleInfo;
-
- sModuleInfo.ModuleObject.set( xVBACodeNamedObjectAccess->getByName( *it ), uno::UNO_QUERY );
- sModuleInfo.ModuleType = script::ModuleType::DOCUMENT;
- xVBAModuleInfo->insertModuleInfo( *it, sModuleInfo );
- if( xLib->hasByName( *it ) )
- xLib->replaceByName( *it, uno::makeAny( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Option VBASupport 1\n") ) ) );
- else
- xLib->insertByName( *it, uno::makeAny( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Option VBASupport 1\n" ) ) ) );
- }
- }
- }
-
- /* Trigger the Workbook_Open event, event processor will register
- itself as listener for specific events. */
- try
- {
- uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents( pShell->GetDocument()->GetVbaEventProcessor(), uno::UNO_SET_THROW );
- uno::Sequence< uno::Any > aArgs;
- xVbaEvents->processVbaEvent( script::vba::VBAEventId::WORKBOOK_OPEN, aArgs );
- }
- catch( uno::Exception& )
- {
- }
- }
-}
-
static uno::Any
getWorkbook( uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< sheet::XSpreadsheetDocument > &xDoc, const uno::Reference< XHelperInterface >& xParent )
{
@@ -254,7 +174,7 @@ ScVbaWorkbooks::Add( const uno::Any& Template ) throw (uno::RuntimeException)
}
// need to set up the document modules ( and vba mode ) here
- setUpDocumentModules( xSpreadDoc );
+ excel::setUpDocumentModules( xSpreadDoc );
if( xSpreadDoc.is() )
return getWorkbook( mxContext, xSpreadDoc, mxParent );
return uno::Any();
diff --git a/sc/source/ui/vba/vbaworksheet.cxx b/sc/source/ui/vba/vbaworksheet.cxx
index e953d56519e5..4152fb0fd412 100644
--- a/sc/source/ui/vba/vbaworksheet.cxx
+++ b/sc/source/ui/vba/vbaworksheet.cxx
@@ -72,6 +72,13 @@
#include <comphelper/processfactory.hxx>
#include <vbahelper/vbashapes.hxx>
+#include <com/sun/star/script/vba/VBAEventId.hpp>
+#include <com/sun/star/script/vba/XVBACompatibility.hpp>
+#include <com/sun/star/script/vba/XVBAEventProcessor.hpp>
+#include <com/sun/star/script/vba/XVBAModuleInfo.hpp>
+#include <com/sun/star/script/ModuleInfo.hpp>
+#include <com/sun/star/script/ModuleType.hpp>
+
#include <tools/string.hxx>
//zhangyun showdataform
@@ -215,6 +222,91 @@ ScVbaWorksheet::~ScVbaWorksheet()
{
}
+const uno::Sequence<sal_Int8>& ScVbaWorksheet::getUnoTunnelId()
+{
+ static uno::Sequence< sal_Int8 > aSeq;
+
+ if( !aSeq.getLength() )
+ {
+ static osl::Mutex aCreateMutex;
+ osl::Guard< osl::Mutex > aGuard( aCreateMutex );
+
+ aSeq.realloc( 16 );
+ rtl_createUuid( reinterpret_cast< sal_uInt8* >( aSeq.getArray() ), 0, sal_True );
+ }
+
+ return aSeq;
+}
+
+uno::Reference< ov::excel::XWorksheet >
+ScVbaWorksheet::createSheetCopyInNewDoc(rtl::OUString aCurrSheetName)
+{
+ uno::Reference< sheet::XSheetCellCursor > xSheetCellCursor = getSheet()->createCursor( );
+ uno::Reference<sheet::XUsedAreaCursor> xUsedCursor(xSheetCellCursor,uno::UNO_QUERY_THROW);
+ uno::Reference< table::XCellRange > xRange1( xSheetCellCursor, uno::UNO_QUERY);
+ uno::Reference<excel::XRange> xRange = new ScVbaRange( this, mxContext, xRange1);
+ if (xRange.is())
+ xRange->Select();
+ excel::implnCopy(mxModel);
+ uno::Reference<frame::XModel> xModel = openNewDoc(aCurrSheetName);
+ if (xModel.is())
+ {
+ excel::implnPaste(xModel);
+ }
+ uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( xModel, uno::UNO_QUERY_THROW );
+ excel::setUpDocumentModules(xSpreadDoc);
+ uno::Reference <sheet::XSpreadsheets> xSheets( xSpreadDoc->getSheets(), uno::UNO_QUERY_THROW );
+ uno::Reference <container::XIndexAccess> xIndex( xSheets, uno::UNO_QUERY_THROW );
+ uno::Reference< sheet::XSpreadsheet > xSheet(xIndex->getByIndex(0), uno::UNO_QUERY_THROW);
+
+ ScDocShell* pShell = excel::getDocShell( xModel );
+ String aCodeName;
+ pShell->GetDocument()->GetCodeName( 0, aCodeName );
+ return uno::Reference< excel::XWorksheet >( getUnoDocModule( aCodeName, pShell ), uno::UNO_QUERY_THROW );
+}
+
+css::uno::Reference< ov::excel::XWorksheet >
+ScVbaWorksheet::createSheetCopy(uno::Reference<excel::XWorksheet> xSheet, bool bAfter)
+{
+ rtl::OUString aCurrSheetName = getName();
+ ScVbaWorksheet* pDestSheet = excel::getImplFromDocModuleWrapper<ScVbaWorksheet>( xSheet );
+
+ uno::Reference <sheet::XSpreadsheetDocument> xDestDoc( pDestSheet->getModel(), uno::UNO_QUERY );
+ uno::Reference <sheet::XSpreadsheetDocument> xSrcDoc( getModel(), uno::UNO_QUERY );
+
+ SCTAB nDest = 0;
+ SCTAB nSrc = 0;
+ rtl::OUString aSheetName = xSheet->getName();
+ bool bSameDoc = ( pDestSheet->getModel() == getModel() );
+ bool bDestSheetExists = ScVbaWorksheets::nameExists (xDestDoc, aSheetName, nDest );
+ bool bSheetExists = ScVbaWorksheets::nameExists (xSrcDoc, aCurrSheetName, nSrc );
+
+ // set sheet name to be newSheet name
+ aSheetName = aCurrSheetName;
+ if ( bSheetExists && bDestSheetExists )
+ {
+ SCTAB nDummy=0;
+ if(bAfter)
+ nDest++;
+ uno::Reference<sheet::XSpreadsheets> xSheets = xDestDoc->getSheets();
+ if ( bSameDoc || ScVbaWorksheets::nameExists( xDestDoc, aCurrSheetName, nDummy ) )
+ getNewSpreadsheetName(aSheetName,aCurrSheetName,xDestDoc);
+ if ( bSameDoc )
+ xSheets->copyByName(aCurrSheetName,aSheetName,nDest);
+ else
+ {
+ ScDocShell* pDestDocShell = excel::getDocShell( pDestSheet->getModel() );
+ ScDocShell* pSrcDocShell = excel::getDocShell( getModel() );
+ if ( pDestDocShell && pSrcDocShell )
+ pDestDocShell->TransferTab( *pSrcDocShell, static_cast<SCTAB>(nSrc), static_cast<SCTAB>(nDest), true, true );
+ }
+ }
+ // return new sheet
+ uno::Reference< excel::XApplication > xApplication( Application(), uno::UNO_QUERY_THROW );
+ uno::Reference< excel::XWorksheet > xNewSheet( xApplication->Worksheets( uno::makeAny( aSheetName ) ), uno::UNO_QUERY_THROW );
+ return xNewSheet;
+}
+
::rtl::OUString
ScVbaWorksheet::getName() throw (uno::RuntimeException)
{
@@ -558,59 +650,13 @@ void
ScVbaWorksheet::Copy( const uno::Any& Before, const uno::Any& After ) throw (uno::RuntimeException)
{
uno::Reference<excel::XWorksheet> xSheet;
- rtl::OUString aCurrSheetName =getName();
if (!(Before >>= xSheet) && !(After >>=xSheet)&& !(Before.hasValue()) && !(After.hasValue()))
{
- uno::Reference< sheet::XSheetCellCursor > xSheetCellCursor = getSheet()->createCursor( );
- uno::Reference<sheet::XUsedAreaCursor> xUsedCursor(xSheetCellCursor,uno::UNO_QUERY_THROW);
- uno::Reference< table::XCellRange > xRange1( xSheetCellCursor, uno::UNO_QUERY);
- uno::Reference<excel::XRange> xRange = new ScVbaRange( this, mxContext, xRange1);
- if (xRange.is())
- xRange->Select();
- excel::implnCopy(mxModel);
- uno::Reference<frame::XModel> xModel = openNewDoc(aCurrSheetName);
- if (xModel.is())
- {
- excel::implnPaste(xModel);
- }
+ createSheetCopyInNewDoc(getName());
return;
}
- ScVbaWorksheet* pDestSheet = static_cast< ScVbaWorksheet* >(xSheet.get());
- uno::Reference <sheet::XSpreadsheetDocument> xDestDoc( pDestSheet->getModel(), uno::UNO_QUERY );
- uno::Reference <sheet::XSpreadsheetDocument> xSrcDoc( getModel(), uno::UNO_QUERY );
-
- SCTAB nDest = 0;
- SCTAB nSrc = 0;
- rtl::OUString aSheetName = xSheet->getName();
- bool bSameDoc = ( pDestSheet->getModel() == getModel() );
- bool bDestSheetExists = ScVbaWorksheets::nameExists (xDestDoc, aSheetName, nDest );
- bool bSheetExists = ScVbaWorksheets::nameExists (xSrcDoc, aCurrSheetName, nSrc );
-
- // set sheet name to be newSheet name
- aSheetName = aCurrSheetName;
- if ( bSheetExists && bDestSheetExists )
- {
- SCTAB nDummy=0;
- sal_Bool bAfter = After.hasValue();
- if(bAfter)
- nDest++;
- uno::Reference<sheet::XSpreadsheets> xSheets = xDestDoc->getSheets();
- if ( bSameDoc || ScVbaWorksheets::nameExists( xDestDoc, aCurrSheetName, nDummy ) )
- getNewSpreadsheetName(aSheetName,aCurrSheetName,xDestDoc);
- if ( bSameDoc )
- xSheets->copyByName(aCurrSheetName,aSheetName,nDest);
- else
- {
- ScDocShell* pDestDocShell = excel::getDocShell( pDestSheet->getModel() );
- ScDocShell* pSrcDocShell = excel::getDocShell( getModel() );
- if ( pDestDocShell && pSrcDocShell )
- pDestDocShell->TransferTab( *pSrcDocShell, static_cast<SCTAB>(nSrc), static_cast<SCTAB>(nDest), true, true );
- }
- }
- // active the new sheet
- uno::Reference< excel::XApplication > xApplication( Application(), uno::UNO_QUERY_THROW );
- uno::Reference< excel::XWorksheet > xNewSheet( xApplication->Worksheets( uno::makeAny( aSheetName ) ), uno::UNO_QUERY_THROW );
+ uno::Reference<excel::XWorksheet> xNewSheet = createSheetCopy(xSheet, After.hasValue());
xNewSheet->Activate();
}
@@ -1121,6 +1167,17 @@ ScVbaWorksheet::PrintOut( const uno::Any& From, const uno::Any& To, const uno::A
PrintOutHelper( excel::getBestViewShell( xModel ), From, To, Copies, Preview, ActivePrinter, PrintToFile, Collate, PrToFileName, bSelection );
}
+sal_Int64 SAL_CALL
+ScVbaWorksheet::getSomething(const uno::Sequence<sal_Int8 > & rId) throw(uno::RuntimeException)
+{
+ if (rId.getLength() == 16 &&
+ 0 == rtl_compareMemory( ScVbaWorksheet::getUnoTunnelId().getConstArray(), rId.getConstArray(), 16 ))
+ {
+ return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this));
+ }
+ return 0;
+}
+
namespace worksheet
{
namespace sdecl = comphelper::service_decl;
diff --git a/sc/source/ui/vba/vbaworksheet.hxx b/sc/source/ui/vba/vbaworksheet.hxx
index 560f41571b41..95c933e0b7c0 100644
--- a/sc/source/ui/vba/vbaworksheet.hxx
+++ b/sc/source/ui/vba/vbaworksheet.hxx
@@ -88,6 +88,9 @@ public:
{ return mxModel; }
virtual css::uno::Reference< css::sheet::XSpreadsheet > getSheet()
{ return mxSheet; }
+ static const com::sun::star::uno::Sequence<sal_Int8>& getUnoTunnelId();
+ css::uno::Reference< ov::excel::XWorksheet > createSheetCopyInNewDoc( rtl::OUString);
+ css::uno::Reference< ov::excel::XWorksheet > createSheetCopy(css::uno::Reference< ov::excel::XWorksheet> xSheet, bool bAfter);
// Attributes
virtual ::rtl::OUString SAL_CALL getName() throw (css::uno::RuntimeException);
@@ -169,6 +172,8 @@ public:
// XHelperInterface
virtual rtl::OUString& getServiceImplName();
virtual css::uno::Sequence<rtl::OUString> getServiceNames();
+ // XUnoTunnel
+ virtual ::sal_Int64 SAL_CALL getSomething(const css::uno::Sequence<sal_Int8 >& rId ) throw(css::uno::RuntimeException);
};
#endif /* SC_VBA_WORKSHEET_HXX */
diff --git a/sc/source/ui/vba/vbaworksheets.cxx b/sc/source/ui/vba/vbaworksheets.cxx
index 680b5ae6b600..e2c436b13966 100644
--- a/sc/source/ui/vba/vbaworksheets.cxx
+++ b/sc/source/ui/vba/vbaworksheets.cxx
@@ -55,6 +55,8 @@
#include "vbaworkbook.hxx"
#include "unonames.hxx"
+#include <vector>
+
using namespace ::ooo::vba;
using namespace ::com::sun::star;
@@ -407,23 +409,60 @@ ScVbaWorksheets::Select( const uno::Any& Replace ) throw (uno::RuntimeException)
for ( sal_Int32 nItem = 1; nItem <= nElems; ++nItem )
{
uno::Reference< excel::XWorksheet > xSheet( Item( uno::makeAny( nItem ), uno::Any() ), uno::UNO_QUERY_THROW );
- ScVbaWorksheet* pSheet = dynamic_cast< ScVbaWorksheet* >( xSheet.get() );
- if ( pSheet )
+ ScVbaWorksheet* pSheet = excel::getImplFromDocModuleWrapper<ScVbaWorksheet>( xSheet );
+ if ( bSelectSingle )
{
- if ( bSelectSingle )
- {
- rMarkData.SelectOneTable( static_cast< SCTAB >( pSheet->getSheetID() ) );
- bSelectSingle = false;
- }
- else
- rMarkData.SelectTable( static_cast< SCTAB >( pSheet->getSheetID() ), sal_True );
-
+ rMarkData.SelectOneTable( static_cast< SCTAB >( pSheet->getSheetID() ) );
+ bSelectSingle = false;
}
+ else
+ rMarkData.SelectTable( static_cast< SCTAB >( pSheet->getSheetID() ), sal_True );
}
}
+void SAL_CALL
+ScVbaWorksheets::Copy ( const uno::Any& Before, const uno::Any& After) throw (css::uno::RuntimeException)
+{
+ uno::Reference<excel::XWorksheet> xSheet;
+ sal_Int32 nElems = getCount();
+ bool bAfter = After.hasValue();
+ std::vector< uno::Reference< excel::XWorksheet > > Sheets;
+ sal_Int32 nItem = 0;
+
+ for ( nItem = 1; nItem <= nElems; ++nItem)
+ {
+ uno::Reference<excel::XWorksheet> xWorksheet(Item( uno::makeAny( nItem ), uno::Any() ), uno::UNO_QUERY_THROW );
+ Sheets.push_back(xWorksheet);
+ }
+ bool bNewDoc = (!(Before >>= xSheet) && !(After >>=xSheet)&& !(Before.hasValue()) && !(After.hasValue()));
+
+ uno::Reference< excel::XWorksheet > xSrcSheet;
+ if ( bNewDoc )
+ {
+ bAfter = true;
+ xSrcSheet = Sheets.at(0);
+ ScVbaWorksheet* pSrcSheet = excel::getImplFromDocModuleWrapper<ScVbaWorksheet>( xSrcSheet );
+ xSheet = pSrcSheet->createSheetCopyInNewDoc(xSrcSheet->getName());
+ nItem = 1;
+ }
+ else
+ {
+ nItem=0;
+ }
+
+ for (; nItem < nElems; ++nItem )
+ {
+ xSrcSheet = Sheets[nItem];
+ ScVbaWorksheet* pSrcSheet = excel::getImplFromDocModuleWrapper<ScVbaWorksheet>( xSrcSheet );
+ if ( bAfter )
+ xSheet = pSrcSheet->createSheetCopy(xSheet, bAfter);
+ else
+ pSrcSheet->createSheetCopy(xSheet, bAfter);
+ }
+}
+
//ScVbaCollectionBaseImpl
uno::Any SAL_CALL
ScVbaWorksheets::Item( const uno::Any& Index, const uno::Any& Index2 ) throw (uno::RuntimeException)
@@ -440,13 +479,10 @@ ScVbaWorksheets::Item( const uno::Any& Index, const uno::Any& Index2 ) throw (u
for( sal_Int32 index = 0; index < nElems; ++index )
{
uno::Reference< excel::XWorksheet > xWorkSheet( ScVbaWorksheets_BASE::Item( sIndices[ index ], Index2 ), uno::UNO_QUERY_THROW );
- ScVbaWorksheet* pWorkSheet = dynamic_cast< ScVbaWorksheet* >( xWorkSheet.get() );
- if ( pWorkSheet )
- {
- uno::Reference< sheet::XSpreadsheet > xSheet( pWorkSheet->getSheet() , uno::UNO_QUERY_THROW );
- uno::Reference< container::XNamed > xName( xSheet, uno::UNO_QUERY_THROW );
- mSheets.push_back( xSheet );
- }
+ ScVbaWorksheet* pWorkSheet = excel::getImplFromDocModuleWrapper<ScVbaWorksheet>( xWorkSheet );
+ uno::Reference< sheet::XSpreadsheet > xSheet( pWorkSheet->getSheet() , uno::UNO_QUERY_THROW );
+ uno::Reference< container::XNamed > xName( xSheet, uno::UNO_QUERY_THROW );
+ mSheets.push_back( xSheet );
}
uno::Reference< container::XIndexAccess > xIndexAccess = new SheetCollectionHelper( mSheets );
uno::Reference< XCollection > xSelectedSheets( new ScVbaWorksheets( this->getParent(), mxContext, xIndexAccess, mxModel ) );
diff --git a/sc/source/ui/vba/vbaworksheets.hxx b/sc/source/ui/vba/vbaworksheets.hxx
index 9854c0447c1d..c15d713e1230 100644
--- a/sc/source/ui/vba/vbaworksheets.hxx
+++ b/sc/source/ui/vba/vbaworksheets.hxx
@@ -72,6 +72,7 @@ public:
virtual void SAL_CALL PrintOut( const css::uno::Any& From, const css::uno::Any& To, const css::uno::Any& Copies, const css::uno::Any& Preview, const css::uno::Any& ActivePrinter, const css::uno::Any& PrintToFile, const css::uno::Any& Collate, const css::uno::Any& PrToFileName ) throw (css::uno::RuntimeException);
virtual css::uno::Any createCollectionObject( const css::uno::Any& aSource );
virtual void SAL_CALL Select( const css::uno::Any& Replace ) throw (css::uno::RuntimeException);
+ virtual void SAL_CALL Copy ( const css::uno::Any& Before, const css::uno::Any& After) throw (css::uno::RuntimeException);
// ScVbaWorksheets_BASE
virtual css::uno::Any SAL_CALL Item( const css::uno::Any& Index1, const css::uno::Any& Index2 ) throw
(css::uno::RuntimeException);
diff --git a/sc/source/ui/view/dbfunc3.cxx b/sc/source/ui/view/dbfunc3.cxx
index d2e185d05b47..e8e5baafb1f7 100644
--- a/sc/source/ui/view/dbfunc3.cxx
+++ b/sc/source/ui/view/dbfunc3.cxx
@@ -72,6 +72,8 @@
#include "dbdocfun.hxx"
#include "dpoutput.hxx"
#include "dptabsrc.hxx"
+#include "dpshttab.hxx"
+#include "dpsdbtab.hxx"
#include "editable.hxx"
#include "docpool.hxx"
#include "patattr.hxx"
@@ -697,13 +699,47 @@ void ScDBFunc::RecalcPivotTable()
ScDocShell* pDocSh = GetViewData()->GetDocShell();
ScDocument* pDoc = GetViewData()->GetDocument();
- // old pivot not used any more
-
+ ScDPCollection* pDPs = pDoc->GetDPCollection();
ScDPObject* pDPObj = pDoc->GetDPAtCursor( GetViewData()->GetCurX(),
GetViewData()->GetCurY(),
GetViewData()->GetTabNo() );
- if ( pDPObj )
+ if (pDPs && pDPObj)
{
+ // Remove existing data cache for the data that this datapilot uses,
+ // to force re-build data cache.
+ if (pDPObj->IsSheetData())
+ {
+ // data source is internal sheet.
+ const ScSheetSourceDesc* pDesc = pDPObj->GetSheetDesc();
+ if (!pDesc)
+ {
+ ErrorMessage(STR_PIVOT_NOTFOUND);
+ return;
+ }
+ if (pDesc->HasRangeName())
+ {
+ ScDPCollection::NameCaches& rCaches = pDPs->GetNameCaches();
+ rCaches.removeCache(pDesc->GetRangeName());
+ }
+ else
+ {
+ ScDPCollection::SheetCaches& rCaches = pDPs->GetSheetCaches();
+ rCaches.removeCache(pDesc->GetSourceRange());
+ }
+ }
+ else if (pDPObj->IsImportData())
+ {
+ // data source is external database.
+ const ScImportSourceDesc* pDesc = pDPObj->GetImportSourceDesc();
+ if (!pDesc)
+ {
+ ErrorMessage(STR_PIVOT_NOTFOUND);
+ return;
+ }
+ ScDPCollection::DBCaches& rCaches = pDPs->GetDBCaches();
+ rCaches.removeCache(pDesc->GetCommandType(), pDesc->aDBName, pDesc->aObject);
+ }
+
ScDBDocFunc aFunc( *pDocSh );
aFunc.DataPilotUpdate( pDPObj, pDPObj, true, false );
CursorPosChanged(); // shells may be switched
diff --git a/sc/source/ui/view/editsh.cxx b/sc/source/ui/view/editsh.cxx
index 515b2fc514a9..5464a0f13f52 100644
--- a/sc/source/ui/view/editsh.cxx
+++ b/sc/source/ui/view/editsh.cxx
@@ -484,13 +484,14 @@ void ScEditShell::Execute( SfxRequest& rReq )
case SID_TOGGLE_REL:
{
- sal_Bool bOk = false;
+ bool bOk = false;
if (pEngine->GetParagraphCount() == 1)
{
String aText = pEngine->GetText();
ESelection aSel = pEditView->GetSelection(); // aktuelle View
- ScRefFinder aFinder( aText, pViewData->GetDocument() );
+ ScDocument* pDoc = pViewData->GetDocument();
+ ScRefFinder aFinder(aText, pViewData->GetCurPos(), pDoc, pDoc->GetAddressConvention());
aFinder.ToggleRel( aSel.nStartPos, aSel.nEndPos );
if (aFinder.GetFound())
{
@@ -503,7 +504,7 @@ void ScEditShell::Execute( SfxRequest& rReq )
pTopView->GetEditEngine()->SetText( aNew );
pTopView->SetSelection( aNewSel );
}
- bOk = sal_True;
+ bOk = true;
// Referenz wird selektiert -> beim Tippen nicht ueberschreiben
bSetSelIsRef = sal_True;
diff --git a/sc/source/ui/view/output.cxx b/sc/source/ui/view/output.cxx
index b1143ced0b10..b69f2ace659a 100644
--- a/sc/source/ui/view/output.cxx
+++ b/sc/source/ui/view/output.cxx
@@ -1222,6 +1222,9 @@ void ScOutputData::DrawFrame()
// draw only rows with set RowInfo::bChanged flag
size_t nRow1 = nFirstRow;
drawinglayer::processor2d::BaseProcessor2D* pProcessor = CreateProcessor2D();
+ if (!pProcessor)
+ return;
+
while( nRow1 <= nLastRow )
{
while( (nRow1 <= nLastRow) && !pRowInfo[ nRow1 ].bChanged ) ++nRow1;
@@ -1631,9 +1634,12 @@ void ScOutputData::DrawRotatedFrame( const Color* pForceColor )
drawinglayer::processor2d::BaseProcessor2D* ScOutputData::CreateProcessor2D( )
{
- basegfx::B2DRange aViewRange;
+ ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
+ if (!pDrawLayer)
+ return NULL;
- SdrPage *pDrawPage = pDoc->GetDrawLayer()->GetPage( static_cast< sal_uInt16 >( nTab ) );
+ basegfx::B2DRange aViewRange;
+ SdrPage *pDrawPage = pDrawLayer->GetPage( static_cast< sal_uInt16 >( nTab ) );
const drawinglayer::geometry::ViewInformation2D aNewViewInfos(
basegfx::B2DHomMatrix( ),
pDev->GetViewTransformation(),
diff --git a/sc/source/ui/view/output2.cxx b/sc/source/ui/view/output2.cxx
index f4605be35595..1a91bfe0c60f 100644
--- a/sc/source/ui/view/output2.cxx
+++ b/sc/source/ui/view/output2.cxx
@@ -2137,6 +2137,99 @@ ScOutputData::DrawEditParam::DrawEditParam(const ScPatternAttr* pPattern, const
mpThisRowInfo(NULL)
{}
+bool ScOutputData::DrawEditParam::readCellContent(
+ ScDocument* pDoc, bool bShowNullValues, bool bShowFormulas, bool bSyntaxMode, bool bUseStyleColor, bool bForceAutoColor, bool& rWrapFields)
+{
+ if (!mpCell)
+ {
+ OSL_FAIL("pCell == NULL");
+ return false;
+ }
+
+ if (mpCell->GetCellType() == CELLTYPE_EDIT)
+ {
+ const EditTextObject* pData;
+ ((ScEditCell*)mpCell)->GetData(pData);
+
+ if (pData)
+ {
+ mpEngine->SetText(*pData);
+
+ if ( mbBreak && !mbAsianVertical && pData->HasField() )
+ {
+ // Fields aren't wrapped, so clipping is enabled to prevent
+ // a field from being drawn beyond the cell size
+
+ rWrapFields = true;
+ }
+ }
+ else
+ {
+ OSL_FAIL("pData == 0");
+ return false;
+ }
+ }
+ else
+ {
+ sal_uLong nFormat = mpPattern->GetNumberFormat(
+ pDoc->GetFormatTable(), mpCondSet );
+ String aString;
+ Color* pColor;
+ ScCellFormat::GetString( mpCell,
+ nFormat,aString, &pColor,
+ *pDoc->GetFormatTable(),
+ bShowNullValues,
+ bShowFormulas,
+ ftCheck );
+
+ mpEngine->SetText(aString);
+ if ( pColor && !bSyntaxMode && !( bUseStyleColor && bForceAutoColor ) )
+ lcl_SetEditColor( *mpEngine, *pColor );
+ }
+ return true;
+}
+
+void ScOutputData::DrawEditParam::setPatternToEngine(bool bUseStyleColor)
+{
+ // syntax highlighting mode is ignored here
+ // StringDiffer doesn't look at hyphenate, language items
+
+ if (mpPattern == mpOldPattern && mpCondSet == mpOldCondSet)
+ return;
+
+ sal_Int32 nConfBackColor = SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor;
+ // SvtAccessibilityOptions::GetIsForBorders is no longer used (always assumed TRUE)
+ bool bCellContrast = bUseStyleColor &&
+ Application::GetSettings().GetStyleSettings().GetHighContrastMode();
+
+ SfxItemSet* pSet = new SfxItemSet( mpEngine->GetEmptyItemSet() );
+ mpPattern->FillEditItemSet( pSet, mpCondSet );
+
+ mpEngine->SetDefaults( pSet );
+ mpOldPattern = mpPattern;
+ mpOldCondSet = mpCondSet;
+
+ sal_uLong nControl = mpEngine->GetControlWord();
+ if (meOrient == SVX_ORIENTATION_STACKED)
+ nControl |= EE_CNTRL_ONECHARPERLINE;
+ else
+ nControl &= ~EE_CNTRL_ONECHARPERLINE;
+ mpEngine->SetControlWord( nControl );
+
+ if ( !mbHyphenatorSet && ((const SfxBoolItem&)pSet->Get(EE_PARA_HYPHENATE)).GetValue() )
+ {
+ // set hyphenator the first time it is needed
+ com::sun::star::uno::Reference<com::sun::star::linguistic2::XHyphenator> xXHyphenator( LinguMgr::GetHyphenator() );
+ mpEngine->SetHyphenator( xXHyphenator );
+ mbHyphenatorSet = true;
+ }
+
+ Color aBackCol = ((const SvxBrushItem&)mpPattern->GetItem( ATTR_BACKGROUND, mpCondSet )).GetColor();
+ if ( bUseStyleColor && ( aBackCol.GetTransparency() > 0 || bCellContrast ) )
+ aBackCol.SetColor( nConfBackColor );
+ mpEngine->SetBackgroundColor( aBackCol );
+}
+
void ScOutputData::DrawEditParam::calcMargins(long& rTopM, long& rLeftM, long& rBottomM, long& rRightM, double nPPTX, double nPPTY) const
{
const SvxMarginItem& rMargin =
@@ -2214,12 +2307,53 @@ bool ScOutputData::DrawEditParam::hasLineBreak() const
return (mbBreak || (meOrient == SVX_ORIENTATION_STACKED) || mbAsianVertical);
}
+bool ScOutputData::DrawEditParam::isHyperlinkCell() const
+{
+ if (!mpCell)
+ return false;
+
+ if (mpCell->GetCellType() != CELLTYPE_FORMULA)
+ return false;
+
+ return static_cast<ScFormulaCell*>(mpCell)->IsHyperLinkCell();
+}
+
bool ScOutputData::DrawEditParam::isVerticallyOriented() const
{
return (meOrient == SVX_ORIENTATION_TOPBOTTOM || meOrient == SVX_ORIENTATION_BOTTOMTOP);
}
-void ScOutputData::DrawEditParam::setAlignmentItems(ScFieldEditEngine* pEngine, ScBaseCell* pCell)
+void ScOutputData::DrawEditParam::calcStartPosForVertical(
+ Point& rLogicStart, long nCellWidth, long nEngineWidth, long nTopM, OutputDevice* pRefDevice)
+{
+ OSL_ENSURE(isVerticallyOriented(), "Use this only for vertically oriented cell!");
+
+ if (mbPixelToLogic)
+ rLogicStart = pRefDevice->PixelToLogic(rLogicStart);
+
+ if (mbBreak)
+ {
+ // vertical adjustment is within the EditEngine
+ if (mbPixelToLogic)
+ rLogicStart.Y() += pRefDevice->PixelToLogic(Size(0,nTopM)).Height();
+ else
+ rLogicStart.Y() += nTopM;
+
+ switch (meHorJust)
+ {
+ case SVX_HOR_JUSTIFY_CENTER:
+ rLogicStart.X() += (nCellWidth - nEngineWidth) / 2;
+ break;
+ case SVX_HOR_JUSTIFY_RIGHT:
+ rLogicStart.X() += nCellWidth - nEngineWidth;
+ break;
+ default:
+ ; // do nothing
+ }
+ }
+}
+
+void ScOutputData::DrawEditParam::setAlignmentToEngine()
{
if (isVerticallyOriented() || mbAsianVertical)
{
@@ -2243,11 +2377,11 @@ void ScOutputData::DrawEditParam::setAlignmentItems(ScFieldEditEngine* pEngine,
break;
}
- pEngine->SetDefaultItem( SvxAdjustItem(eSvxAdjust, EE_PARA_JUST) );
- pEngine->SetDefaultItem( SvxJustifyMethodItem(meVerJustMethod, EE_PARA_JUST_METHOD) );
+ mpEngine->SetDefaultItem( SvxAdjustItem(eSvxAdjust, EE_PARA_JUST) );
+ mpEngine->SetDefaultItem( SvxJustifyMethodItem(meVerJustMethod, EE_PARA_JUST_METHOD) );
if (meHorJust == SVX_HOR_JUSTIFY_BLOCK)
- pEngine->SetDefaultItem( SvxVerJustifyItem(SVX_VER_JUSTIFY_BLOCK, EE_PARA_VER_JUST) );
+ mpEngine->SetDefaultItem( SvxVerJustifyItem(SVX_VER_JUSTIFY_BLOCK, EE_PARA_VER_JUST) );
}
else
{
@@ -2299,29 +2433,29 @@ void ScOutputData::DrawEditParam::setAlignmentItems(ScFieldEditEngine* pEngine,
}
}
- pEngine->SetDefaultItem( SvxAdjustItem(eSvxAdjust, EE_PARA_JUST) );
+ mpEngine->SetDefaultItem( SvxAdjustItem(eSvxAdjust, EE_PARA_JUST) );
if (mbAsianVertical)
{
- pEngine->SetDefaultItem( SvxJustifyMethodItem(meVerJustMethod, EE_PARA_JUST_METHOD) );
+ mpEngine->SetDefaultItem( SvxJustifyMethodItem(meVerJustMethod, EE_PARA_JUST_METHOD) );
if (meHorJust == SVX_HOR_JUSTIFY_BLOCK)
- pEngine->SetDefaultItem( SvxVerJustifyItem(SVX_VER_JUSTIFY_BLOCK, EE_PARA_VER_JUST) );
+ mpEngine->SetDefaultItem( SvxVerJustifyItem(SVX_VER_JUSTIFY_BLOCK, EE_PARA_VER_JUST) );
}
else
{
- pEngine->SetDefaultItem( SvxJustifyMethodItem(meHorJustMethod, EE_PARA_JUST_METHOD) );
+ mpEngine->SetDefaultItem( SvxJustifyMethodItem(meHorJustMethod, EE_PARA_JUST_METHOD) );
if (meVerJust == SVX_VER_JUSTIFY_BLOCK)
- pEngine->SetDefaultItem( SvxVerJustifyItem(SVX_VER_JUSTIFY_BLOCK, EE_PARA_VER_JUST) );
+ mpEngine->SetDefaultItem( SvxVerJustifyItem(SVX_VER_JUSTIFY_BLOCK, EE_PARA_VER_JUST) );
}
}
- pEngine->SetVertical(mbAsianVertical);
- if (pCell && pCell->GetCellType() == CELLTYPE_EDIT)
+ mpEngine->SetVertical(mbAsianVertical);
+ if (mpCell && mpCell->GetCellType() == CELLTYPE_EDIT)
{
// We need to synchronize the vertical mode in the EditTextObject
// instance too. No idea why we keep this state in two separate
// instances.
- ScEditCell* pEditCell = static_cast<ScEditCell*>(pCell);
+ ScEditCell* pEditCell = static_cast<ScEditCell*>(mpCell);
const EditTextObject* pData = pEditCell->GetData();
if (pData)
const_cast<EditTextObject*>(pData)->SetVertical(mbAsianVertical);
@@ -2344,16 +2478,54 @@ bool ScOutputData::DrawEditParam::adjustHorAlignment(ScFieldEditEngine* pEngine)
return false;
}
-void ScOutputData::DrawEditStandard(DrawEditParam& rParam)
+void ScOutputData::DrawEditParam::adjustForRTL()
{
- Size aRefOne = pRefDevice->PixelToLogic(Size(1,1));
+ if (!mpEngine->IsRightToLeft(0))
+ // No RTL mode.
+ return;
- // SvtAccessibilityOptions::GetIsForBorders is no longer used (always assumed TRUE)
- bool bCellContrast = bUseStyleColor &&
- Application::GetSettings().GetStyleSettings().GetHighContrastMode();
+ // For right-to-left, EditEngine always calculates its lines
+ // beginning from the right edge, but EditLine::nStartPosX is
+ // of sal_uInt16 type, so the PaperSize must be limited to USHRT_MAX.
+ Size aLogicPaper = mpEngine->GetPaperSize();
+ if ( aLogicPaper.Width() > USHRT_MAX )
+ {
+ aLogicPaper.Width() = USHRT_MAX;
+ mpEngine->SetPaperSize(aLogicPaper);
+ }
+}
+void ScOutputData::DrawEditParam::adjustForHyperlinkInPDF(Point aURLStart, OutputDevice* pDev)
+{
+ // PDF: whole-cell hyperlink from formula?
vcl::PDFExtOutDevData* pPDFData = PTR_CAST( vcl::PDFExtOutDevData, pDev->GetExtOutDevData() );
- sal_Int32 nConfBackColor = SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor;
+ bool bHasURL = pPDFData && isHyperlinkCell();
+ if (!bHasURL)
+ return;
+
+ long nURLWidth = (long) mpEngine->CalcTextWidth();
+ long nURLHeight = mpEngine->GetTextHeight();
+ if (mbBreak)
+ {
+ Size aPaper = mpEngine->GetPaperSize();
+ if ( mbAsianVertical )
+ nURLHeight = aPaper.Height();
+ else
+ nURLWidth = aPaper.Width();
+ }
+ if (isVerticallyOriented())
+ std::swap( nURLWidth, nURLHeight );
+ else if (mbAsianVertical)
+ aURLStart.X() -= nURLWidth;
+
+ Rectangle aURLRect( aURLStart, Size( nURLWidth, nURLHeight ) );
+ lcl_DoHyperlinkResult( pDev, aURLRect, mpCell );
+}
+
+void ScOutputData::DrawEditStandard(DrawEditParam& rParam)
+{
+ Size aRefOne = pRefDevice->PixelToLogic(Size(1,1));
+
bool bHidden = false;
bool bRepeat = (rParam.meHorJust == SVX_HOR_JUSTIFY_REPEAT && !rParam.mbBreak);
bool bShrink = !rParam.mbBreak && !bRepeat && lcl_GetBoolValue(*rParam.mpPattern, ATTR_SHRINKTOFIT, rParam.mpCondSet);
@@ -2462,89 +2634,15 @@ void ScOutputData::DrawEditStandard(DrawEditParam& rParam)
if ( rParam.mbAsianVertical && rParam.meVerJust == SVX_VER_JUSTIFY_STANDARD )
rParam.meVerJust = SVX_VER_JUSTIFY_TOP;
- // syntax highlighting mode is ignored here
- // StringDiffer doesn't look at hyphenate, language items
- if ( rParam.mpPattern != rParam.mpOldPattern || rParam.mpCondSet != rParam.mpOldCondSet )
- {
- SfxItemSet* pSet = new SfxItemSet( rParam.mpEngine->GetEmptyItemSet() );
- rParam.mpPattern->FillEditItemSet( pSet, rParam.mpCondSet );
-
- rParam.mpEngine->SetDefaults( pSet );
- rParam.mpOldPattern = rParam.mpPattern;
- rParam.mpOldCondSet = rParam.mpCondSet;
-
- sal_uLong nControl = rParam.mpEngine->GetControlWord();
- if (rParam.meOrient==SVX_ORIENTATION_STACKED)
- nControl |= EE_CNTRL_ONECHARPERLINE;
- else
- nControl &= ~EE_CNTRL_ONECHARPERLINE;
- rParam.mpEngine->SetControlWord( nControl );
-
- if ( !rParam.mbHyphenatorSet && ((const SfxBoolItem&)pSet->Get(EE_PARA_HYPHENATE)).GetValue() )
- {
- // set hyphenator the first time it is needed
- com::sun::star::uno::Reference<com::sun::star::linguistic2::XHyphenator> xXHyphenator( LinguMgr::GetHyphenator() );
- rParam.mpEngine->SetHyphenator( xXHyphenator );
- rParam.mbHyphenatorSet = true;
- }
-
- Color aBackCol = ((const SvxBrushItem&)
- rParam.mpPattern->GetItem( ATTR_BACKGROUND, rParam.mpCondSet )).GetColor();
- if ( bUseStyleColor && ( aBackCol.GetTransparency() > 0 || bCellContrast ) )
- aBackCol.SetColor( nConfBackColor );
- rParam.mpEngine->SetBackgroundColor( aBackCol );
- }
-
- rParam.setAlignmentItems(rParam.mpEngine, rParam.mpCell);
+ rParam.setPatternToEngine(bUseStyleColor);
+ rParam.setAlignmentToEngine();
// Read content from cell
bool bWrapFields = false;
- if (!rParam.mpCell)
- {
- OSL_FAIL("pCell == NULL");
+ if (!rParam.readCellContent(pDoc, bShowNullValues, bShowFormulas, bSyntaxMode, bUseStyleColor, bForceAutoColor, bWrapFields))
+ // Failed to read cell content. Bail out.
return;
- }
-
- if (rParam.mpCell->GetCellType() == CELLTYPE_EDIT)
- {
- const EditTextObject* pData;
- ((ScEditCell*)rParam.mpCell)->GetData(pData);
-
- if (pData)
- {
- rParam.mpEngine->SetText(*pData);
-
- if ( rParam.mbBreak && !rParam.mbAsianVertical && pData->HasField() )
- {
- // Fields aren't wrapped, so clipping is enabled to prevent
- // a field from being drawn beyond the cell size
-
- bWrapFields = true;
- }
- }
- else
- {
- OSL_FAIL("pData == 0");
- }
- }
- else
- {
- sal_uLong nFormat = rParam.mpPattern->GetNumberFormat(
- pDoc->GetFormatTable(), rParam.mpCondSet );
- String aString;
- Color* pColor;
- ScCellFormat::GetString( rParam.mpCell,
- nFormat,aString, &pColor,
- *pDoc->GetFormatTable(),
- bShowNullValues,
- bShowFormulas,
- ftCheck );
-
- rParam.mpEngine->SetText(aString);
- if ( pColor && !bSyntaxMode && !( bUseStyleColor && bForceAutoColor ) )
- lcl_SetEditColor( *rParam.mpEngine, *pColor );
- }
if ( bSyntaxMode )
SetEditSyntaxColor( *rParam.mpEngine, rParam.mpCell );
@@ -2802,7 +2900,7 @@ void ScOutputData::DrawEditStandard(DrawEditParam& rParam)
// reset adjustment for the next cell
rParam.mpOldPattern = NULL;
}
- else
+ else if (!rParam.isVerticallyOriented())
{
if (rParam.meHorJust==SVX_HOR_JUSTIFY_RIGHT)
aLogicStart.X() += nAvailWidth - nEngineWidth;
@@ -2918,8 +3016,11 @@ void ScOutputData::DrawEditStandard(DrawEditParam& rParam)
nOriVal = 900;
if (rParam.meHorJust == SVX_HOR_JUSTIFY_BLOCK || rParam.mbBreak)
{
+ Size aPSize = rParam.mpEngine->GetPaperSize();
+ aPSize.Width() = aCellSize.Height();
+ rParam.mpEngine->SetPaperSize(aPSize);
aLogicStart.Y() +=
- rParam.mbBreak ? rParam.mpEngine->GetPaperSize().Width() : nEngineHeight;
+ rParam.mbBreak ? aPSize.Width() : nEngineHeight;
}
else
{
@@ -2976,18 +3077,7 @@ void ScOutputData::DrawEditStandard(DrawEditParam& rParam)
rParam.mpEngine->SetPaperSize(aPaperLogic);
}
- if ( rParam.mpEngine->IsRightToLeft( 0 ) )
- {
- // For right-to-left, EditEngine always calculates its lines
- // beginning from the right edge, but EditLine::nStartPosX is
- // of sal_uInt16 type, so the PaperSize must be limited to USHRT_MAX.
- Size aLogicPaper = rParam.mpEngine->GetPaperSize();
- if ( aLogicPaper.Width() > USHRT_MAX )
- {
- aLogicPaper.Width() = USHRT_MAX;
- rParam.mpEngine->SetPaperSize(aLogicPaper);
- }
- }
+ rParam.adjustForRTL();
// bMoveClipped handling has been replaced by complete alignment
// handling (also extending to the left).
@@ -3020,29 +3110,774 @@ void ScOutputData::DrawEditStandard(DrawEditParam& rParam)
pDev->SetClipRegion();
}
- // PDF: whole-cell hyperlink from formula?
- bool bHasURL = pPDFData && rParam.mpCell && rParam.mpCell->GetCellType() == CELLTYPE_FORMULA &&
- static_cast<ScFormulaCell*>(rParam.mpCell)->IsHyperLinkCell();
- if ( bHasURL )
+ rParam.adjustForHyperlinkInPDF(aURLStart, pDev);
+}
+
+void ScOutputData::DrawEditBottomTop(DrawEditParam& rParam)
+{
+ Size aRefOne = pRefDevice->PixelToLogic(Size(1,1));
+
+ bool bRepeat = (rParam.meHorJust == SVX_HOR_JUSTIFY_REPEAT && !rParam.mbBreak);
+ bool bShrink = !rParam.mbBreak && !bRepeat && lcl_GetBoolValue(*rParam.mpPattern, ATTR_SHRINKTOFIT, rParam.mpCondSet);
+
+ if ( rParam.meHorJust == SVX_HOR_JUSTIFY_REPEAT )
{
- long nURLWidth = (long) rParam.mpEngine->CalcTextWidth();
- long nURLHeight = rParam.mpEngine->GetTextHeight();
- if ( rParam.mbBreak )
+ // ignore orientation/rotation if "repeat" is active
+ rParam.meOrient = SVX_ORIENTATION_STANDARD;
+ DrawEditStandard(rParam);
+ return;
+ }
+
+ SvxCellHorJustify eOutHorJust =
+ ( rParam.meHorJust != SVX_HOR_JUSTIFY_STANDARD ) ? rParam.meHorJust :
+ ( rParam.mbCellIsValue ? SVX_HOR_JUSTIFY_RIGHT : SVX_HOR_JUSTIFY_LEFT );
+
+ if ( eOutHorJust == SVX_HOR_JUSTIFY_BLOCK || eOutHorJust == SVX_HOR_JUSTIFY_REPEAT )
+ eOutHorJust = SVX_HOR_JUSTIFY_LEFT; // repeat is not yet implemented
+
+ //! mirror margin values for RTL?
+ //! move margin down to after final GetOutputArea call
+ long nTopM, nLeftM, nBottomM, nRightM;
+ rParam.calcMargins(nTopM, nLeftM, nBottomM, nRightM, nPPTX, nPPTY);
+
+ SCCOL nXForPos = rParam.mnX;
+ if ( nXForPos < nX1 )
+ {
+ nXForPos = nX1;
+ rParam.mnPosX = rParam.mnInitPosX;
+ }
+ SCSIZE nArrYForPos = rParam.mnArrY;
+ if ( nArrYForPos < 1 )
+ {
+ nArrYForPos = 1;
+ rParam.mnPosY = nScrY;
+ }
+
+ OutputAreaParam aAreaParam;
+
+ //
+ // Initial page size - large for normal text, cell size for automatic line breaks
+ //
+
+ Size aPaperSize = Size( 1000000, 1000000 );
+ if (rParam.mbBreak)
+ {
+ // call GetOutputArea with nNeeded=0, to get only the cell width
+
+ //! handle nArrY == 0
+ GetOutputArea( nXForPos, nArrYForPos, rParam.mnPosX, rParam.mnPosY, rParam.mnCellX, rParam.mnCellY, 0,
+ *rParam.mpPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust),
+ rParam.mbCellIsValue, true, false, aAreaParam );
+
+ //! special ScEditUtil handling if formatting for printer
+ rParam.calcPaperSize(aPaperSize, aAreaParam.maAlignRect, nPPTX, nPPTY);
+ }
+ if (rParam.mbPixelToLogic)
+ {
+ Size aLogicSize = pRefDevice->PixelToLogic(aPaperSize);
+ rParam.mpEngine->SetPaperSize(aLogicSize);
+ }
+ else
+ rParam.mpEngine->SetPaperSize(aPaperSize);
+
+ //
+ // Fill the EditEngine (cell attributes and text)
+ //
+
+ rParam.setPatternToEngine(bUseStyleColor);
+ rParam.setAlignmentToEngine();
+
+ // Read content from cell
+
+ bool bWrapFields = false;
+ if (!rParam.readCellContent(pDoc, bShowNullValues, bShowFormulas, bSyntaxMode, bUseStyleColor, bForceAutoColor, bWrapFields))
+ // Failed to read cell content. Bail out.
+ return;
+
+ if ( bSyntaxMode )
+ SetEditSyntaxColor( *rParam.mpEngine, rParam.mpCell );
+ else if ( bUseStyleColor && bForceAutoColor )
+ lcl_SetEditColor( *rParam.mpEngine, COL_AUTO ); //! or have a flag at EditEngine
+ else
+ {
+ OSL_FAIL("pCell == NULL");
+ }
+
+ rParam.mpEngine->SetUpdateMode( true ); // after SetText, before CalcTextWidth/GetTextHeight
+
+ //
+ // Get final output area using the calculated width
+ //
+
+ long nEngineWidth, nEngineHeight;
+ rParam.getEngineSize(rParam.mpEngine, nEngineWidth, nEngineHeight);
+
+ long nNeededPixel = nEngineWidth;
+ if (rParam.mbPixelToLogic)
+ nNeededPixel = pRefDevice->LogicToPixel(Size(nNeededPixel,0)).Width();
+ nNeededPixel += nLeftM + nRightM;
+
+ if (!rParam.mbBreak || bShrink)
+ {
+ // for break, the first GetOutputArea call is sufficient
+ GetOutputArea( nXForPos, nArrYForPos, rParam.mnPosX, rParam.mnPosY, rParam.mnCellX, rParam.mnCellY, nNeededPixel,
+ *rParam.mpPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust),
+ rParam.mbCellIsValue || bRepeat || bShrink, false, false, aAreaParam );
+
+ if ( bShrink )
+ {
+ ShrinkEditEngine( *rParam.mpEngine, aAreaParam.maAlignRect,
+ nLeftM, nTopM, nRightM, nBottomM, false,
+ sal::static_int_cast<sal_uInt16>(rParam.meOrient), 0, rParam.mbPixelToLogic,
+ nEngineWidth, nEngineHeight, nNeededPixel,
+ aAreaParam.mbLeftClip, aAreaParam.mbRightClip );
+ }
+ if ( bRepeat && !aAreaParam.mbLeftClip && !aAreaParam.mbRightClip && rParam.mpEngine->GetParagraphCount() == 1 )
+ {
+ // First check if twice the space for the formatted text is available
+ // (otherwise just keep it unchanged).
+
+ long nFormatted = nNeededPixel - nLeftM - nRightM; // without margin
+ long nAvailable = aAreaParam.maAlignRect.GetWidth() - nLeftM - nRightM;
+ if ( nAvailable >= 2 * nFormatted )
+ {
+ // "repeat" is handled with unformatted text (for performance reasons)
+ String aCellStr = rParam.mpEngine->GetText();
+ rParam.mpEngine->SetText( aCellStr );
+
+ long nRepeatSize = (long) rParam.mpEngine->CalcTextWidth();
+ if (rParam.mbPixelToLogic)
+ nRepeatSize = pRefDevice->LogicToPixel(Size(nRepeatSize,0)).Width();
+ if ( pFmtDevice != pRefDevice )
+ ++nRepeatSize;
+ if ( nRepeatSize > 0 )
+ {
+ long nRepeatCount = nAvailable / nRepeatSize;
+ if ( nRepeatCount > 1 )
+ {
+ String aRepeated = aCellStr;
+ for ( long nRepeat = 1; nRepeat < nRepeatCount; nRepeat++ )
+ aRepeated.Append( aCellStr );
+ rParam.mpEngine->SetText( aRepeated );
+
+ nEngineHeight = rParam.mpEngine->GetTextHeight();
+ nEngineWidth = (long) rParam.mpEngine->CalcTextWidth();
+ if (rParam.mbPixelToLogic)
+ nNeededPixel = pRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width();
+ else
+ nNeededPixel = nEngineWidth;
+ nNeededPixel += nLeftM + nRightM;
+ }
+ }
+ }
+ }
+
+ if ( rParam.mbCellIsValue && ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip ) )
+ {
+ rParam.mpEngine->SetText( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("###")) );
+ nEngineWidth = (long) rParam.mpEngine->CalcTextWidth();
+ if (rParam.mbPixelToLogic)
+ nNeededPixel = pRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width();
+ else
+ nNeededPixel = nEngineWidth;
+ nNeededPixel += nLeftM + nRightM;
+
+ // No clip marks if "###" doesn't fit (same as in DrawStrings)
+ }
+ }
+
+ long nStartX = aAreaParam.maAlignRect.Left();
+ long nStartY = aAreaParam.maAlignRect.Top();
+ long nCellWidth = aAreaParam.maAlignRect.GetWidth();
+ long nOutWidth = nCellWidth - 1 - nLeftM - nRightM;
+ long nOutHeight = aAreaParam.maAlignRect.GetHeight() - nTopM - nBottomM;
+
+ if (rParam.mbBreak)
+ {
+ // text with automatic breaks is aligned only within the
+ // edit engine's paper size, the output of the whole area
+ // is always left-aligned
+
+ nStartX += nLeftM;
+ }
+ else
+ {
+ if ( eOutHorJust == SVX_HOR_JUSTIFY_RIGHT )
+ nStartX -= nNeededPixel - nCellWidth + nRightM + 1;
+ else if ( eOutHorJust == SVX_HOR_JUSTIFY_CENTER )
+ nStartX -= ( nNeededPixel - nCellWidth + nRightM + 1 - nLeftM ) / 2;
+ else
+ nStartX += nLeftM;
+ }
+
+ bool bOutside = (aAreaParam.maClipRect.Right() < nScrX || aAreaParam.maClipRect.Left() >= nScrX + nScrW);
+ if (bOutside)
+ return;
+
+ if ( aAreaParam.maClipRect.Left() < nScrX )
+ {
+ aAreaParam.maClipRect.Left() = nScrX;
+ aAreaParam.mbLeftClip = true;
+ }
+ if ( aAreaParam.maClipRect.Right() > nScrX + nScrW )
+ {
+ aAreaParam.maClipRect.Right() = nScrX + nScrW; //! minus one?
+ aAreaParam.mbRightClip = true;
+ }
+
+ bool bClip = aAreaParam.mbLeftClip || aAreaParam.mbRightClip;
+ bool bSimClip = false;
+
+ if ( bWrapFields )
+ {
+ // Fields in a cell with automatic breaks: clip to cell width
+ bClip = true;
+ }
+
+ if ( aAreaParam.maClipRect.Top() < nScrY )
+ {
+ aAreaParam.maClipRect.Top() = nScrY;
+ bClip = true;
+ }
+ if ( aAreaParam.maClipRect.Bottom() > nScrY + nScrH )
+ {
+ aAreaParam.maClipRect.Bottom() = nScrY + nScrH; //! minus one?
+ bClip = true;
+ }
+
+ Size aCellSize; // output area, excluding margins, in logical units
+ if (rParam.mbPixelToLogic)
+ aCellSize = pRefDevice->PixelToLogic( Size( nOutWidth, nOutHeight ) );
+ else
+ aCellSize = Size( nOutWidth, nOutHeight );
+
+ if ( nEngineHeight >= aCellSize.Height() + aRefOne.Height() )
+ {
+ const ScMergeAttr* pMerge =
+ (ScMergeAttr*)&rParam.mpPattern->GetItem(ATTR_MERGE);
+ bool bMerged = pMerge->GetColMerge() > 1 || pMerge->GetRowMerge() > 1;
+
+ // Don't clip for text height when printing rows with optimal height,
+ // except when font size is from conditional formatting.
+ //! Allow clipping when vertically merged?
+ if ( eType != OUTTYPE_PRINTER ||
+ ( pDoc->GetRowFlags( rParam.mnCellY, nTab ) & CR_MANUALSIZE ) ||
+ ( rParam.mpCondSet && SFX_ITEM_SET ==
+ rParam.mpCondSet->GetItemState(ATTR_FONT_HEIGHT, true) ) )
+ bClip = true;
+ else
+ bSimClip = true;
+
+ // Show clip marks if height is at least 5pt too small and
+ // there are several lines of text.
+ // Not for asian vertical text, because that would interfere
+ // with the default right position of the text.
+ // Only with automatic line breaks, to avoid having to find
+ // the cells with the horizontal end of the text again.
+ if ( nEngineHeight - aCellSize.Height() > 100 &&
+ rParam.mbBreak && bMarkClipped &&
+ ( rParam.mpEngine->GetParagraphCount() > 1 || rParam.mpEngine->GetLineCount(0) > 1 ) )
+ {
+ CellInfo* pClipMarkCell = NULL;
+ if ( bMerged )
+ {
+ // anywhere in the merged area...
+ SCCOL nClipX = ( rParam.mnX < nX1 ) ? nX1 : rParam.mnX;
+ pClipMarkCell = &pRowInfo[(rParam.mnArrY != 0) ? rParam.mnArrY : 1].pCellInfo[nClipX+1];
+ }
+ else
+ pClipMarkCell = &rParam.mpThisRowInfo->pCellInfo[rParam.mnX+1];
+
+ pClipMarkCell->nClipMark |= SC_CLIPMARK_RIGHT; //! also allow left?
+ bAnyClipped = true;
+
+ long nMarkPixel = (long)( SC_CLIPMARK_SIZE * nPPTX );
+ if ( aAreaParam.maClipRect.Right() - nMarkPixel > aAreaParam.maClipRect.Left() )
+ aAreaParam.maClipRect.Right() -= nMarkPixel;
+ }
+ }
+
+ Rectangle aLogicClip;
+ if (bClip || bSimClip)
+ {
+ // Clip marks are already handled in GetOutputArea
+
+ if (rParam.mbPixelToLogic)
+ aLogicClip = pRefDevice->PixelToLogic( aAreaParam.maClipRect );
+ else
+ aLogicClip = aAreaParam.maClipRect;
+
+ if (bClip) // bei bSimClip nur aClipRect initialisieren
{
- Size aPaper = rParam.mpEngine->GetPaperSize();
- if ( rParam.mbAsianVertical )
- nURLHeight = aPaper.Height();
+ if (bMetaFile)
+ {
+ pDev->Push();
+ pDev->IntersectClipRegion( aLogicClip );
+ }
else
- nURLWidth = aPaper.Width();
+ pDev->SetClipRegion( Region( aLogicClip ) );
+ }
+ }
+
+ Point aLogicStart(nStartX, nStartY);
+ rParam.calcStartPosForVertical(aLogicStart, aCellSize.Width(), nEngineWidth, nTopM, pRefDevice);
+
+ Point aURLStart = aLogicStart; // copy before modifying for orientation
+
+ if (rParam.meHorJust == SVX_HOR_JUSTIFY_BLOCK || rParam.mbBreak)
+ {
+ Size aPSize = rParam.mpEngine->GetPaperSize();
+ aPSize.Width() = aCellSize.Height();
+ rParam.mpEngine->SetPaperSize(aPSize);
+ aLogicStart.Y() +=
+ rParam.mbBreak ? aPSize.Width() : nEngineHeight;
+ }
+ else
+ {
+ // Note that the "paper" is rotated 90 degrees to the left, so
+ // paper's width is in vertical direction. Also, the whole text
+ // is on a single line, as text wrap is not in effect.
+
+ // Set the paper width to be the width of the text.
+ Size aPSize = rParam.mpEngine->GetPaperSize();
+ aPSize.Width() = rParam.mpEngine->CalcTextWidth();
+ rParam.mpEngine->SetPaperSize(aPSize);
+
+ long nGap = 0;
+ long nTopOffset = 0;
+ if (rParam.mbPixelToLogic)
+ {
+ nGap = pRefDevice->LogicToPixel(aCellSize).Height() - pRefDevice->LogicToPixel(aPSize).Width();
+ nGap = pRefDevice->PixelToLogic(Size(0, nGap)).Height();
+ nTopOffset = pRefDevice->PixelToLogic(Size(0,nTopM)).Height();
+ }
+ else
+ {
+ nGap = aCellSize.Height() - aPSize.Width();
+ nTopOffset = nTopM;
}
- if ( rParam.isVerticallyOriented() )
- std::swap( nURLWidth, nURLHeight );
- else if ( rParam.mbAsianVertical )
- aURLStart.X() -= nURLWidth;
- Rectangle aURLRect( aURLStart, Size( nURLWidth, nURLHeight ) );
- lcl_DoHyperlinkResult( pDev, aURLRect, rParam.mpCell );
+ // First, align text to bottom.
+ aLogicStart.Y() += aCellSize.Height();
+ aLogicStart.Y() += nTopOffset;
+
+ switch (rParam.meVerJust)
+ {
+ case SVX_VER_JUSTIFY_STANDARD:
+ case SVX_VER_JUSTIFY_BOTTOM:
+ // align to bottom (do nothing).
+ break;
+ case SVX_VER_JUSTIFY_CENTER:
+ // center it.
+ aLogicStart.Y() -= nGap / 2;
+ break;
+ case SVX_VER_JUSTIFY_BLOCK:
+ case SVX_VER_JUSTIFY_TOP:
+ // align to top
+ aLogicStart.Y() -= nGap;
+ default:
+ ;
+ }
}
+
+ rParam.adjustForRTL();
+ rParam.mpEngine->Draw(pDev, aLogicStart, 900);
+
+ if (bClip)
+ {
+ if (bMetaFile)
+ pDev->Pop();
+ else
+ pDev->SetClipRegion();
+ }
+
+ rParam.adjustForHyperlinkInPDF(aURLStart, pDev);
+}
+
+void ScOutputData::DrawEditTopBottom(DrawEditParam& rParam)
+{
+ Size aRefOne = pRefDevice->PixelToLogic(Size(1,1));
+
+ bool bRepeat = (rParam.meHorJust == SVX_HOR_JUSTIFY_REPEAT && !rParam.mbBreak);
+ bool bShrink = !rParam.mbBreak && !bRepeat && lcl_GetBoolValue(*rParam.mpPattern, ATTR_SHRINKTOFIT, rParam.mpCondSet);
+
+ if ( rParam.meHorJust == SVX_HOR_JUSTIFY_REPEAT )
+ {
+ // ignore orientation/rotation if "repeat" is active
+ rParam.meOrient = SVX_ORIENTATION_STANDARD;
+ DrawEditStandard(rParam);
+ return;
+ }
+
+ SvxCellHorJustify eOutHorJust =
+ ( rParam.meHorJust != SVX_HOR_JUSTIFY_STANDARD ) ? rParam.meHorJust :
+ ( rParam.mbCellIsValue ? SVX_HOR_JUSTIFY_RIGHT : SVX_HOR_JUSTIFY_LEFT );
+
+ if ( eOutHorJust == SVX_HOR_JUSTIFY_BLOCK || eOutHorJust == SVX_HOR_JUSTIFY_REPEAT )
+ eOutHorJust = SVX_HOR_JUSTIFY_LEFT; // repeat is not yet implemented
+
+ //! mirror margin values for RTL?
+ //! move margin down to after final GetOutputArea call
+ long nTopM, nLeftM, nBottomM, nRightM;
+ rParam.calcMargins(nTopM, nLeftM, nBottomM, nRightM, nPPTX, nPPTY);
+
+ SCCOL nXForPos = rParam.mnX;
+ if ( nXForPos < nX1 )
+ {
+ nXForPos = nX1;
+ rParam.mnPosX = rParam.mnInitPosX;
+ }
+ SCSIZE nArrYForPos = rParam.mnArrY;
+ if ( nArrYForPos < 1 )
+ {
+ nArrYForPos = 1;
+ rParam.mnPosY = nScrY;
+ }
+
+ OutputAreaParam aAreaParam;
+
+ //
+ // Initial page size - large for normal text, cell size for automatic line breaks
+ //
+
+ Size aPaperSize = Size( 1000000, 1000000 );
+ if (rParam.hasLineBreak())
+ {
+ // call GetOutputArea with nNeeded=0, to get only the cell width
+
+ //! handle nArrY == 0
+ GetOutputArea( nXForPos, nArrYForPos, rParam.mnPosX, rParam.mnPosY, rParam.mnCellX, rParam.mnCellY, 0,
+ *rParam.mpPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust),
+ rParam.mbCellIsValue, true, false, aAreaParam );
+
+ //! special ScEditUtil handling if formatting for printer
+ rParam.calcPaperSize(aPaperSize, aAreaParam.maAlignRect, nPPTX, nPPTY);
+ }
+ if (rParam.mbPixelToLogic)
+ {
+ Size aLogicSize = pRefDevice->PixelToLogic(aPaperSize);
+ rParam.mpEngine->SetPaperSize(aLogicSize);
+ }
+ else
+ rParam.mpEngine->SetPaperSize(aPaperSize);
+
+ //
+ // Fill the EditEngine (cell attributes and text)
+ //
+
+ rParam.setPatternToEngine(bUseStyleColor);
+ rParam.setAlignmentToEngine();
+
+ // Read content from cell
+
+ bool bWrapFields = false;
+ if (!rParam.readCellContent(pDoc, bShowNullValues, bShowFormulas, bSyntaxMode, bUseStyleColor, bForceAutoColor, bWrapFields))
+ // Failed to read cell content. Bail out.
+ return;
+
+ if ( bSyntaxMode )
+ SetEditSyntaxColor( *rParam.mpEngine, rParam.mpCell );
+ else if ( bUseStyleColor && bForceAutoColor )
+ lcl_SetEditColor( *rParam.mpEngine, COL_AUTO ); //! or have a flag at EditEngine
+ else
+ {
+ OSL_FAIL("pCell == NULL");
+ }
+
+ rParam.mpEngine->SetUpdateMode( true ); // after SetText, before CalcTextWidth/GetTextHeight
+
+ //
+ // Get final output area using the calculated width
+ //
+
+ long nEngineWidth, nEngineHeight;
+ rParam.getEngineSize(rParam.mpEngine, nEngineWidth, nEngineHeight);
+
+ long nNeededPixel = nEngineWidth;
+ if (rParam.mbPixelToLogic)
+ nNeededPixel = pRefDevice->LogicToPixel(Size(nNeededPixel,0)).Width();
+ nNeededPixel += nLeftM + nRightM;
+
+ if (!rParam.mbBreak || bShrink)
+ {
+ // for break, the first GetOutputArea call is sufficient
+ GetOutputArea( nXForPos, nArrYForPos, rParam.mnPosX, rParam.mnPosY, rParam.mnCellX, rParam.mnCellY, nNeededPixel,
+ *rParam.mpPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust),
+ rParam.mbCellIsValue || bRepeat || bShrink, false, false, aAreaParam );
+
+ if ( bShrink )
+ {
+ ShrinkEditEngine( *rParam.mpEngine, aAreaParam.maAlignRect,
+ nLeftM, nTopM, nRightM, nBottomM, false,
+ sal::static_int_cast<sal_uInt16>(rParam.meOrient), 0, rParam.mbPixelToLogic,
+ nEngineWidth, nEngineHeight, nNeededPixel,
+ aAreaParam.mbLeftClip, aAreaParam.mbRightClip );
+ }
+ if ( bRepeat && !aAreaParam.mbLeftClip && !aAreaParam.mbRightClip && rParam.mpEngine->GetParagraphCount() == 1 )
+ {
+ // First check if twice the space for the formatted text is available
+ // (otherwise just keep it unchanged).
+
+ long nFormatted = nNeededPixel - nLeftM - nRightM; // without margin
+ long nAvailable = aAreaParam.maAlignRect.GetWidth() - nLeftM - nRightM;
+ if ( nAvailable >= 2 * nFormatted )
+ {
+ // "repeat" is handled with unformatted text (for performance reasons)
+ String aCellStr = rParam.mpEngine->GetText();
+ rParam.mpEngine->SetText( aCellStr );
+
+ long nRepeatSize = (long) rParam.mpEngine->CalcTextWidth();
+ if (rParam.mbPixelToLogic)
+ nRepeatSize = pRefDevice->LogicToPixel(Size(nRepeatSize,0)).Width();
+ if ( pFmtDevice != pRefDevice )
+ ++nRepeatSize;
+ if ( nRepeatSize > 0 )
+ {
+ long nRepeatCount = nAvailable / nRepeatSize;
+ if ( nRepeatCount > 1 )
+ {
+ String aRepeated = aCellStr;
+ for ( long nRepeat = 1; nRepeat < nRepeatCount; nRepeat++ )
+ aRepeated.Append( aCellStr );
+ rParam.mpEngine->SetText( aRepeated );
+
+ nEngineHeight = rParam.mpEngine->GetTextHeight();
+ nEngineWidth = (long) rParam.mpEngine->CalcTextWidth();
+ if (rParam.mbPixelToLogic)
+ nNeededPixel = pRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width();
+ else
+ nNeededPixel = nEngineWidth;
+ nNeededPixel += nLeftM + nRightM;
+ }
+ }
+ }
+ }
+
+ if ( rParam.mbCellIsValue && ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip ) )
+ {
+ rParam.mpEngine->SetText( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("###")) );
+ nEngineWidth = (long) rParam.mpEngine->CalcTextWidth();
+ if (rParam.mbPixelToLogic)
+ nNeededPixel = pRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width();
+ else
+ nNeededPixel = nEngineWidth;
+ nNeededPixel += nLeftM + nRightM;
+
+ // No clip marks if "###" doesn't fit (same as in DrawStrings)
+ }
+ }
+
+ long nStartX = aAreaParam.maAlignRect.Left();
+ long nStartY = aAreaParam.maAlignRect.Top();
+ long nCellWidth = aAreaParam.maAlignRect.GetWidth();
+ long nOutWidth = nCellWidth - 1 - nLeftM - nRightM;
+ long nOutHeight = aAreaParam.maAlignRect.GetHeight() - nTopM - nBottomM;
+
+ if (rParam.mbBreak)
+ {
+ // text with automatic breaks is aligned only within the
+ // edit engine's paper size, the output of the whole area
+ // is always left-aligned
+
+ nStartX += nLeftM;
+ if (rParam.meHorJust == SVX_HOR_JUSTIFY_BLOCK)
+ nStartX += aPaperSize.Height();
+ }
+ else
+ {
+ if ( eOutHorJust == SVX_HOR_JUSTIFY_RIGHT )
+ nStartX -= nNeededPixel - nCellWidth + nRightM + 1;
+ else if ( eOutHorJust == SVX_HOR_JUSTIFY_CENTER )
+ nStartX -= ( nNeededPixel - nCellWidth + nRightM + 1 - nLeftM ) / 2;
+ else
+ nStartX += nLeftM;
+ }
+
+ bool bOutside = (aAreaParam.maClipRect.Right() < nScrX || aAreaParam.maClipRect.Left() >= nScrX + nScrW);
+ if (bOutside)
+ return;
+
+ if ( aAreaParam.maClipRect.Left() < nScrX )
+ {
+ aAreaParam.maClipRect.Left() = nScrX;
+ aAreaParam.mbLeftClip = true;
+ }
+ if ( aAreaParam.maClipRect.Right() > nScrX + nScrW )
+ {
+ aAreaParam.maClipRect.Right() = nScrX + nScrW; //! minus one?
+ aAreaParam.mbRightClip = true;
+ }
+
+ bool bClip = aAreaParam.mbLeftClip || aAreaParam.mbRightClip;
+ bool bSimClip = false;
+
+ if ( bWrapFields )
+ {
+ // Fields in a cell with automatic breaks: clip to cell width
+ bClip = true;
+ }
+
+ if ( aAreaParam.maClipRect.Top() < nScrY )
+ {
+ aAreaParam.maClipRect.Top() = nScrY;
+ bClip = true;
+ }
+ if ( aAreaParam.maClipRect.Bottom() > nScrY + nScrH )
+ {
+ aAreaParam.maClipRect.Bottom() = nScrY + nScrH; //! minus one?
+ bClip = true;
+ }
+
+ Size aCellSize; // output area, excluding margins, in logical units
+ if (rParam.mbPixelToLogic)
+ aCellSize = pRefDevice->PixelToLogic( Size( nOutWidth, nOutHeight ) );
+ else
+ aCellSize = Size( nOutWidth, nOutHeight );
+
+ if ( nEngineHeight >= aCellSize.Height() + aRefOne.Height() )
+ {
+ const ScMergeAttr* pMerge =
+ (ScMergeAttr*)&rParam.mpPattern->GetItem(ATTR_MERGE);
+ bool bMerged = pMerge->GetColMerge() > 1 || pMerge->GetRowMerge() > 1;
+
+ // Don't clip for text height when printing rows with optimal height,
+ // except when font size is from conditional formatting.
+ //! Allow clipping when vertically merged?
+ if ( eType != OUTTYPE_PRINTER ||
+ ( pDoc->GetRowFlags( rParam.mnCellY, nTab ) & CR_MANUALSIZE ) ||
+ ( rParam.mpCondSet && SFX_ITEM_SET ==
+ rParam.mpCondSet->GetItemState(ATTR_FONT_HEIGHT, true) ) )
+ bClip = true;
+ else
+ bSimClip = true;
+
+ // Show clip marks if height is at least 5pt too small and
+ // there are several lines of text.
+ // Not for asian vertical text, because that would interfere
+ // with the default right position of the text.
+ // Only with automatic line breaks, to avoid having to find
+ // the cells with the horizontal end of the text again.
+ if ( nEngineHeight - aCellSize.Height() > 100 &&
+ rParam.mbBreak && bMarkClipped &&
+ ( rParam.mpEngine->GetParagraphCount() > 1 || rParam.mpEngine->GetLineCount(0) > 1 ) )
+ {
+ CellInfo* pClipMarkCell = NULL;
+ if ( bMerged )
+ {
+ // anywhere in the merged area...
+ SCCOL nClipX = ( rParam.mnX < nX1 ) ? nX1 : rParam.mnX;
+ pClipMarkCell = &pRowInfo[(rParam.mnArrY != 0) ? rParam.mnArrY : 1].pCellInfo[nClipX+1];
+ }
+ else
+ pClipMarkCell = &rParam.mpThisRowInfo->pCellInfo[rParam.mnX+1];
+
+ pClipMarkCell->nClipMark |= SC_CLIPMARK_RIGHT; //! also allow left?
+ bAnyClipped = true;
+
+ long nMarkPixel = (long)( SC_CLIPMARK_SIZE * nPPTX );
+ if ( aAreaParam.maClipRect.Right() - nMarkPixel > aAreaParam.maClipRect.Left() )
+ aAreaParam.maClipRect.Right() -= nMarkPixel;
+ }
+ }
+
+ Rectangle aLogicClip;
+ if (bClip || bSimClip)
+ {
+ // Clip marks are already handled in GetOutputArea
+
+ if (rParam.mbPixelToLogic)
+ aLogicClip = pRefDevice->PixelToLogic( aAreaParam.maClipRect );
+ else
+ aLogicClip = aAreaParam.maClipRect;
+
+ if (bClip) // bei bSimClip nur aClipRect initialisieren
+ {
+ if (bMetaFile)
+ {
+ pDev->Push();
+ pDev->IntersectClipRegion( aLogicClip );
+ }
+ else
+ pDev->SetClipRegion( Region( aLogicClip ) );
+ }
+ }
+
+ Point aLogicStart(nStartX, nStartY);
+ rParam.calcStartPosForVertical(aLogicStart, aCellSize.Width(), nEngineWidth, nTopM, pRefDevice);
+
+ Point aURLStart = aLogicStart; // copy before modifying for orientation
+
+ if (rParam.meHorJust != SVX_HOR_JUSTIFY_BLOCK)
+ {
+ aLogicStart.X() += nEngineWidth;
+ if (!rParam.mbBreak)
+ {
+ // Set the paper width to text size.
+ Size aPSize = rParam.mpEngine->GetPaperSize();
+ aPSize.Width() = rParam.mpEngine->CalcTextWidth();
+ rParam.mpEngine->SetPaperSize(aPSize);
+
+ long nGap = 0;
+ long nTopOffset = 0; // offset by top margin
+ if (rParam.mbPixelToLogic)
+ {
+ nGap = pRefDevice->LogicToPixel(aPSize).Width() - pRefDevice->LogicToPixel(aCellSize).Height();
+ nGap = pRefDevice->PixelToLogic(Size(0, nGap)).Height();
+ nTopOffset = pRefDevice->PixelToLogic(Size(0,nTopM)).Height();
+ }
+ else
+ {
+ nGap = aPSize.Width() - aCellSize.Height();
+ nTopOffset = nTopM;
+ }
+ aLogicStart.Y() += nTopOffset;
+
+ switch (rParam.meVerJust)
+ {
+ case SVX_VER_JUSTIFY_STANDARD:
+ case SVX_VER_JUSTIFY_BOTTOM:
+ // align to bottom
+ aLogicStart.Y() -= nGap;
+ break;
+ case SVX_VER_JUSTIFY_CENTER:
+ // center it.
+ aLogicStart.Y() -= nGap / 2;
+ break;
+ case SVX_VER_JUSTIFY_BLOCK:
+ case SVX_VER_JUSTIFY_TOP:
+ // align to top (do nothing)
+ default:
+ ;
+ }
+ }
+ }
+
+ rParam.adjustForRTL();
+
+ // bMoveClipped handling has been replaced by complete alignment
+ // handling (also extending to the left).
+
+ rParam.mpEngine->Draw(pDev, aLogicStart, 2700);
+
+ if (bClip)
+ {
+ if (bMetaFile)
+ pDev->Pop();
+ else
+ pDev->SetClipRegion();
+ }
+
+ rParam.adjustForHyperlinkInPDF(aURLStart, pDev);
+}
+
+void ScOutputData::DrawEditStacked(DrawEditParam& rParam)
+{
+ DrawEditStandard(rParam);
+}
+
+void ScOutputData::DrawEditAsianVertical(DrawEditParam& rParam)
+{
+ DrawEditStandard(rParam);
}
void ScOutputData::DrawEdit(sal_Bool bPixelToLogic)
@@ -3193,7 +4028,20 @@ void ScOutputData::DrawEdit(sal_Bool bPixelToLogic)
aParam.mpOldPattern = pOldPattern;
aParam.mpOldCondSet = pOldCondSet;
aParam.mpThisRowInfo = pThisRowInfo;
- DrawEditStandard(aParam);
+ switch (aParam.meOrient)
+ {
+ case SVX_ORIENTATION_BOTTOMTOP:
+ DrawEditBottomTop(aParam);
+ break;
+ case SVX_ORIENTATION_TOPBOTTOM:
+ DrawEditTopBottom(aParam);
+ break;
+ case SVX_ORIENTATION_STACKED:
+ DrawEditStacked(aParam);
+ break;
+ default:
+ DrawEditStandard(aParam);
+ }
// Retrieve parameters for next iteration.
pOldPattern = aParam.mpOldPattern;
diff --git a/sc/source/ui/view/viewfun4.cxx b/sc/source/ui/view/viewfun4.cxx
index a9d9364a7208..0ccabacf3e67 100644
--- a/sc/source/ui/view/viewfun4.cxx
+++ b/sc/source/ui/view/viewfun4.cxx
@@ -259,7 +259,7 @@ void ScViewFunc::DoRefConversion( sal_Bool bRecord )
String aOld;
((ScFormulaCell*)pCell)->GetFormula(aOld);
xub_StrLen nLen = aOld.Len();
- ScRefFinder aFinder( aOld, pDoc );
+ ScRefFinder aFinder( aOld, aIter.GetPos(), pDoc, pDoc->GetAddressConvention() );
aFinder.ToggleRel( 0, nLen );
if (aFinder.GetFound())
{
diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx
index 2918410d0923..cc85ef7b7137 100644
--- a/sc/source/ui/view/viewfunc.cxx
+++ b/sc/source/ui/view/viewfunc.cxx
@@ -97,10 +97,13 @@ static void lcl_PostRepaintCondFormat( const ScConditionalFormat *pCondFmt, ScDo
{
if( pCondFmt )
{
- const ScRangeListRef& aRanges = pCondFmt->GetRangeInfo();
- size_t nCount = aRanges->size();
+ const ScRangeListRef& xRanges = pCondFmt->GetRangeInfo();
+ if (!xRanges)
+ return;
+
+ size_t nCount = xRanges->size();
for( size_t n = 0 ; n < nCount; n++ )
- pDocSh->PostPaint( *((*aRanges)[n]), PAINT_ALL );
+ pDocSh->PostPaint( *((*xRanges)[n]), PAINT_ALL );
}
}