summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
Diffstat (limited to 'sc')
-rw-r--r--sc/inc/column.hxx1
-rw-r--r--sc/inc/document.hxx2
-rw-r--r--sc/inc/externalrefmgr.hxx180
-rw-r--r--sc/inc/linkuno.hxx2
-rw-r--r--sc/inc/table.hxx3
-rw-r--r--sc/sdi/cellsh.sdi3
-rw-r--r--sc/sdi/drtxtob.sdi5
-rw-r--r--sc/sdi/editsh.sdi4
-rw-r--r--sc/source/core/data/cell.cxx4
-rw-r--r--sc/source/core/data/cell2.cxx11
-rw-r--r--sc/source/core/data/column.cxx16
-rwxr-xr-xsc/source/core/data/documen2.cxx8
-rw-r--r--sc/source/core/data/documen3.cxx7
-rw-r--r--sc/source/core/data/documen5.cxx3
-rw-r--r--sc/source/core/data/document.cxx20
-rw-r--r--sc/source/core/data/table1.cxx2
-rw-r--r--sc/source/core/data/table2.cxx11
-rw-r--r--sc/source/core/tool/queryparam.cxx6
-rw-r--r--sc/source/filter/excel/read.cxx4
-rw-r--r--sc/source/filter/excel/xechart.cxx344
-rw-r--r--sc/source/filter/excel/xeescher.cxx4
-rwxr-xr-x[-rw-r--r--]sc/source/filter/excel/xichart.cxx433
-rw-r--r--sc/source/filter/excel/xilink.cxx1
-rwxr-xr-x[-rw-r--r--]sc/source/filter/excel/xlchart.cxx202
-rw-r--r--sc/source/filter/excel/xlroot.cxx41
-rw-r--r--sc/source/filter/inc/xechart.hxx56
-rw-r--r--sc/source/filter/inc/xichart.hxx57
-rwxr-xr-x[-rw-r--r--]sc/source/filter/inc/xlchart.hxx136
-rw-r--r--sc/source/filter/inc/xlroot.hxx7
-rw-r--r--sc/source/filter/xml/xmlexternaltabi.cxx15
-rw-r--r--sc/source/filter/xml/xmlexternaltabi.hxx9
-rw-r--r--sc/source/filter/xml/xmltabi.cxx23
-rw-r--r--sc/source/ui/docshell/docfunc.cxx6
-rw-r--r--sc/source/ui/docshell/externalrefmgr.cxx735
-rw-r--r--sc/source/ui/drawfunc/drtxtob.cxx46
-rw-r--r--sc/source/ui/unoobj/cellsuno.cxx2
-rw-r--r--sc/source/ui/unoobj/linkuno.cxx6
-rw-r--r--sc/source/ui/unoobj/tokenuno.cxx4
-rw-r--r--sc/source/ui/view/editsh.cxx37
-rw-r--r--sc/source/ui/view/output2.cxx2
-rw-r--r--sc/source/ui/view/viewutil.cxx11
-rw-r--r--sc/uiconfig/scalc/menubar/menubar.xml7
-rw-r--r--sc/uiconfig/scalc/toolbar/findbar.xml8
-rw-r--r--sc/uiconfig/scalc/toolbar/toolbar.xml4
44 files changed, 1547 insertions, 941 deletions
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index c39d0deca0b7..503f0975c5c9 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -275,7 +275,6 @@ public:
void CalcAfterLoad();
void CompileAll();
void CompileXML( ScProgress& rProgress );
- bool MarkUsedExternalReferences();
void ResetChanged( SCROW nStartRow, SCROW nEndRow );
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 02c859723fa2..768dc815a482 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -906,7 +906,7 @@ public:
bool ShrinkToUsedDataArea( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow, bool bColumnsOnly ) const;
void GetDataArea( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow,
- SCCOL& rEndCol, SCROW& rEndRow, BOOL bIncludeOld, bool bOnlyDown );
+ SCCOL& rEndCol, SCROW& rEndRow, BOOL bIncludeOld, bool bOnlyDown ) const;
SC_DLLPUBLIC BOOL GetCellArea( SCTAB nTab, SCCOL& rEndCol, SCROW& rEndRow ) const;
SC_DLLPUBLIC BOOL GetTableArea( SCTAB nTab, SCCOL& rEndCol, SCROW& rEndRow ) const;
SC_DLLPUBLIC BOOL GetPrintArea( SCTAB nTab, SCCOL& rEndCol, SCROW& rEndRow,
diff --git a/sc/inc/externalrefmgr.hxx b/sc/inc/externalrefmgr.hxx
index f47d99097b39..818920885493 100644
--- a/sc/inc/externalrefmgr.hxx
+++ b/sc/inc/externalrefmgr.hxx
@@ -36,12 +36,14 @@
#include "vcl/timer.hxx"
#include "svl/zforlist.hxx"
#include "scmatrix.hxx"
+#include "rangelst.hxx"
#include <hash_map>
#include <hash_set>
#include <boost/shared_ptr.hpp>
#include <vector>
#include <list>
+#include <set>
#include <formula/ExternalReferenceHelper.hxx>
class ScDocument;
@@ -55,6 +57,7 @@ class ScTokenArray;
class String;
class SfxObjectShellRef;
class Window;
+class ScFormulaCell;
class ScExternalRefCache;
@@ -126,6 +129,15 @@ public:
class Table;
friend class ScExternalRefCache::Table;
+ /**
+ * Represents a single cached table in an external document. It only
+ * stores non-empty cells; empty cells should never be stored in the data
+ * cache. Instead, cached ranges should be used to determine whether or
+ * not a cell is empty or needs fetching from the source document. If a
+ * cell's value is not stored but its address is within the cached ranges,
+ * that cell is already queried in the source document and we know it's
+ * empty.
+ */
class Table
{
public:
@@ -140,7 +152,14 @@ public:
Table();
~Table();
- SC_DLLPUBLIC void setCell(SCCOL nCol, SCROW nRow, TokenRef pToken, sal_uInt32 nFmtIndex = 0);
+ /**
+ * Add cell value to the cache.
+ *
+ * @param bSetCacheRange if true, mark this cell 'cached'. This is
+ * false _only when_ adding a range of cell
+ * values, for performance reasons.
+ */
+ SC_DLLPUBLIC void setCell(SCCOL nCol, SCROW nRow, TokenRef pToken, sal_uInt32 nFmtIndex = 0, bool bSetCacheRange = true);
SC_DLLPUBLIC TokenRef getCell(SCCOL nCol, SCROW nRow, sal_uInt32* pnFmtIndex = NULL) const;
bool hasRow( SCROW nRow ) const;
/** Set/clear referenced status flag only if current status is not
@@ -151,18 +170,39 @@ public:
ReferencedFlag getReferencedFlag() const;
bool isReferenced() const;
/// Obtain a sorted vector of rows.
- void getAllRows(::std::vector<SCROW>& rRows) const;
+ void getAllRows(::std::vector<SCROW>& rRows, SCROW nLow = 0, SCROW nHigh = MAXROW) const;
/// Returns the half-open range of used rows in this table. Returns [0,0) if table is empty.
SC_DLLPUBLIC ::std::pair< SCROW, SCROW > getRowRange() const;
/// Obtain a sorted vector of columns.
- void getAllCols(SCROW nRow, ::std::vector<SCCOL>& rCols) const;
+ void getAllCols(SCROW nRow, ::std::vector<SCCOL>& rCols, SCCOL nLow = 0, SCCOL nHigh = MAXCOL) const;
/// Returns the half-open range of used columns in the specified row. Returns [0,0) if row is empty.
SC_DLLPUBLIC ::std::pair< SCCOL, SCCOL > getColRange( SCROW nRow ) const;
void getAllNumberFormats(::std::vector<sal_uInt32>& rNumFmts) const;
+ const ScRangeList& getCachedRanges() const;
+ bool isRangeCached(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const;
+
+ void setCachedCell(SCCOL nCol, SCROW nRow);
+ void setCachedCellRange(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2);
+
+ /**
+ * Call this to mark the entire table "cached". This will prevent all
+ * future attempts to access the source document even when non-cached
+ * cells are queried. In such case, non-cached cells are treated as
+ * empty cells. Useful when loading a document with own external data
+ * cache.
+ */
+ SC_DLLPUBLIC void setWholeTableCached();
+ private:
+ bool isInCachedRanges(SCCOL nCol, SCROW nRow) const;
+ TokenRef getEmptyOrNullToken(SCCOL nCol, SCROW nRow) const;
private:
- RowsDataType maRows;
- ReferencedFlag meReferenced;
+ /** Data cache */
+ RowsDataType maRows;
+ /** Collection of individual cached ranges. The table ranges are
+ * not used & always zero. */
+ ScRangeList maCachedRanges;
+ ReferencedFlag meReferenced;
};
typedef ::boost::shared_ptr<Table> TableTypeRef;
@@ -185,8 +225,7 @@ public:
* @return pointer to the token instance in the cache.
*/
ScExternalRefCache::TokenRef getCellData(
- sal_uInt16 nFileId, const String& rTabName, SCCOL nCol, SCROW nRow,
- bool bEmptyCellOnNull, bool bWriteEmpty, sal_uInt32* pnFmtIndex);
+ sal_uInt16 nFileId, const String& rTabName, SCCOL nCol, SCROW nRow, sal_uInt32* pnFmtIndex);
/**
* Get a cached cell range data.
@@ -196,12 +235,12 @@ public:
* guaranteed if the TokenArrayRef is properly used..
*/
ScExternalRefCache::TokenArrayRef getCellRangeData(
- sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange, bool bEmptyCellOnNull, bool bWriteEmpty);
+ sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange);
ScExternalRefCache::TokenArrayRef getRangeNameTokens(sal_uInt16 nFileId, const String& rName);
void setRangeNameTokens(sal_uInt16 nFileId, const String& rName, TokenArrayRef pArray);
- void setCellData(sal_uInt16 nFileId, const String& rTabName, SCROW nRow, SCCOL nCol, TokenRef pToken, sal_uInt32 nFmtIndex);
+ void setCellData(sal_uInt16 nFileId, const String& rTabName, SCCOL nCol, SCROW nRow, TokenRef pToken, sal_uInt32 nFmtIndex);
struct SingleRangeData
{
@@ -325,58 +364,8 @@ class SC_DLLPUBLIC ScExternalRefManager : public formula::ExternalReferenceHelpe
{
public:
- // SUNWS needs a forward declared friend, otherwise types and members
- // of the outer class are not accessible.
- class RefCells;
- friend class ScExternalRefManager::RefCells;
-
- /**
- * Collection of cell addresses that contain external references. This
- * data is used for link updates.
- */
- class RefCells
- {
- public:
- RefCells();
- ~RefCells();
-
- void insertCell(const ScAddress& rAddr);
- void removeCell(const ScAddress& rAddr);
- void moveTable(SCTAB nOldTab, SCTAB nNewTab, bool bCopy);
- void insertTable(SCTAB nPos);
- void removeTable(SCTAB nPos);
- void refreshAllCells(ScExternalRefManager& rRefMgr);
- private:
-
- typedef ::std::hash_set<SCROW> RowSet;
- typedef ::std::hash_map<SCCOL, RowSet> ColSet;
-
- // SUNWS needs a forward declared friend, otherwise types and members
- // of the outer class are not accessible.
- struct TabItem;
- friend struct ScExternalRefManager::RefCells::TabItem;
-
- struct TabItem
- {
- SCTAB mnIndex;
- ColSet maCols;
- explicit TabItem(SCTAB nIndex);
- explicit TabItem(const TabItem& r);
- };
- typedef ::boost::shared_ptr<TabItem> TabItemRef;
-
- /**
- * Return the position that points either to the specified table
- * position or to the position where a new table would be inserted in
- * case the specified table is not present.
- *
- * @param nTab index of the desired table
- */
- ::std::list<TabItemRef>::iterator getTabPos(SCTAB nTab);
-
- // This list must be sorted by the table index at all times.
- ::std::list<TabItemRef> maTables;
- };
+ typedef ::std::set<ScFormulaCell*> RefCellSet;
+ typedef ::std::hash_map<sal_uInt16, RefCellSet> RefCellMap;
enum LinkUpdateType { LINK_MODIFIED, LINK_BROKEN };
@@ -401,6 +390,21 @@ public:
};
};
+ /**
+ * Use this guard when performing something from the API that might query
+ * values from external references. Interpreting formula strings is one
+ * such example.
+ */
+ class ApiGuard
+ {
+ public:
+ ApiGuard(ScDocument* pDoc);
+ ~ApiGuard();
+ private:
+ ScExternalRefManager* mpMgr;
+ bool mbOldInteractionEnabled;
+ };
+
private:
/** Shell instance for a source document. */
struct SrcShell
@@ -412,7 +416,6 @@ private:
typedef ::std::hash_map<sal_uInt16, SrcShell> DocShellMap;
typedef ::std::hash_map<sal_uInt16, bool> LinkedDocMap;
- typedef ::std::hash_map<sal_uInt16, RefCells> RefCellMap;
typedef ::std::hash_map<sal_uInt16, SvNumberFormatterMergeMap> NumFmtMap;
@@ -516,12 +519,7 @@ public:
*/
bool markUsedByLinkListeners();
- /**
- * Set all tables of a document as referenced, used only during
- * store-to-file.
- * @returns <TRUE/> if ALL tables of ALL external documents are marked.
- */
- bool setCacheDocReferenced( sal_uInt16 nFileId );
+ bool markUsedExternalRefCells();
/**
* Set a table as referenced, used only during store-to-file.
@@ -540,7 +538,7 @@ public:
* @returns <TRUE/> if setAllCacheTableReferencedStati(false) was called,
* <FALSE/> if setAllCacheTableReferencedStati(true) was called.
*/
- bool isInReferenceMarking() const { return bInReferenceMarking; }
+ bool isInReferenceMarking() const { return mbInReferenceMarking; }
void storeRangeNameTokens(sal_uInt16 nFileId, const String& rName, const ScTokenArray& rArray);
@@ -561,7 +559,8 @@ public:
* @return shared_ptr to a token array instance. <i>The caller must not
* delete the instance returned by this method.</i>
*/
- ScExternalRefCache::TokenArrayRef getDoubleRefTokens(sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange, const ScAddress* pCurPos);
+ ScExternalRefCache::TokenArrayRef getDoubleRefTokens(
+ sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange, const ScAddress* pCurPos);
/**
* Get an array of tokens corresponding with a specified name in a
@@ -574,7 +573,8 @@ public:
*
* @return shared_ptr to array of tokens composing the name
*/
- ScExternalRefCache::TokenArrayRef getRangeNameTokens(sal_uInt16 nFileId, const String& rName, const ScAddress* pCurPos = NULL);
+ ScExternalRefCache::TokenArrayRef getRangeNameTokens(
+ sal_uInt16 nFileId, const String& rName, const ScAddress* pCurPos = NULL);
const String& getOwnDocumentName() const;
bool isOwnDocument(const String& rFile) const;
@@ -646,32 +646,12 @@ public:
void resetSrcFileData(const String& rBaseFileUrl);
/**
- * Update a single referencing cell position.
+ * Stop tracking a specific formula cell.
*
- * @param rOldPos old position
- * @param rNewPos new position
+ * @param pCell pointer to cell that formerly contained external
+ * reference.
*/
- void updateRefCell(const ScAddress& rOldPos, const ScAddress& rNewPos, bool bCopy);
-
- /**
- * Update referencing cells affected by sheet movement.
- *
- * @param nOldTab old sheet position
- * @param nNewTab new sheet position
- * @param bCopy whether this is a sheet move (false) or sheet copy (true)
- */
- void updateRefMoveTable(SCTAB nOldTab, SCTAB nNewTab, bool bCopy);
-
- /**
- * Update referencing cells affected by sheet insertion.
- *
- * @param nPos sheet insertion position. All sheets to the right
- * including the one at the insertion poistion shift to the
- * right by one.
- */
- void updateRefInsertTable(SCTAB nPos);
-
- void updateRefDeleteTable(SCTAB nPos);
+ void removeRefCell(ScFormulaCell* pCell);
/**
* Register a new link listener to a specified external document. Note
@@ -723,8 +703,6 @@ private:
*/
void maybeCreateRealFileName(sal_uInt16 nFileId);
- bool compileTokensByCell(const ScAddress& rCell);
-
/**
* Purge those source document instances that have not been accessed for
* the specified duration.
@@ -764,7 +742,13 @@ private:
::std::vector<SrcFileData> maSrcFiles;
/** Status whether in reference marking state. See isInReferenceMarking(). */
- bool bInReferenceMarking;
+ bool mbInReferenceMarking:1;
+
+ /**
+ * Controls whether or not to allow user interaction. We don't want any
+ * user interaction when calling from the API.
+ */
+ bool mbUserInteractionEnabled:1;
AutoTimer maSrcDocTimer;
DECL_LINK(TimeOutHdl, AutoTimer*);
diff --git a/sc/inc/linkuno.hxx b/sc/inc/linkuno.hxx
index 50b33c692752..284d851a45da 100644
--- a/sc/inc/linkuno.hxx
+++ b/sc/inc/linkuno.hxx
@@ -543,7 +543,7 @@ public:
// XExternalDocLink
virtual ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XExternalSheetCache >
- SAL_CALL addSheetCache( const ::rtl::OUString& aSheetName )
+ SAL_CALL addSheetCache( const ::rtl::OUString& aSheetName, sal_Bool bDynamicCache )
throw (::com::sun::star::uno::RuntimeException);
// XNameAccess
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 950f07565e19..aed123bd7a65 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -380,7 +380,7 @@ public:
SCCOL nStartCol, SCROW nStartRow, SCCOL& rEndCol, SCROW nEndRow );
void GetDataArea( SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow,
- BOOL bIncludeOld, bool bOnlyDown ) const;
+ BOOL bIncludeOld, bool bOnlyDown ) const;
bool ShrinkToUsedDataArea( SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow, bool bColumnsOnly ) const;
@@ -419,7 +419,6 @@ public:
void CalcAfterLoad();
void CompileAll();
void CompileXML( ScProgress& rProgress );
- bool MarkUsedExternalReferences();
void UpdateReference( UpdateRefMode eUpdateRefMode, SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
diff --git a/sc/sdi/cellsh.sdi b/sc/sdi/cellsh.sdi
index ed6dc17fb2a0..4c27c656d15c 100644
--- a/sc/sdi/cellsh.sdi
+++ b/sc/sdi/cellsh.sdi
@@ -189,6 +189,9 @@ interface CellSelection
SID_HANGUL_HANJA_CONVERSION [ ExecMethod = ExecuteEdit; StateMethod = GetState; ]
SID_CHINESE_CONVERSION [ ExecMethod = ExecuteEdit; StateMethod = GetState; ]
+ SID_TRANSLITERATE_SENTENCE_CASE [ ExecMethod = ExecuteTrans; StateMethod = GetBlockState; ]
+ SID_TRANSLITERATE_TITLE_CASE [ ExecMethod = ExecuteTrans; StateMethod = GetBlockState; ]
+ SID_TRANSLITERATE_TOGGLE_CASE [ ExecMethod = ExecuteTrans; StateMethod = GetBlockState; ]
SID_TRANSLITERATE_UPPER [ ExecMethod = ExecuteTrans; StateMethod = GetBlockState; ]
SID_TRANSLITERATE_LOWER [ ExecMethod = ExecuteTrans; StateMethod = GetBlockState; ]
SID_TRANSLITERATE_HALFWIDTH [ ExecMethod = ExecuteTrans; StateMethod = GetBlockState; ]
diff --git a/sc/sdi/drtxtob.sdi b/sc/sdi/drtxtob.sdi
index cde7d77753a9..cad53257c136 100644
--- a/sc/sdi/drtxtob.sdi
+++ b/sc/sdi/drtxtob.sdi
@@ -62,6 +62,8 @@ interface TableDrawText
SID_CLIPBOARD_FORMAT_ITEMS [ ExecMethod = Execute; StateMethod = GetClipState; Export = FALSE; ]
SID_SELECTALL [ ExecMethod = Execute; StateMethod = GetState; Export = FALSE; ]
SID_CHARMAP [ ExecMethod = Execute; StateMethod = GetState; Export = FALSE; ]
+ SID_THES [ ExecMethod = Execute; StateMethod = GetState; Export = FALSE; ]
+ SID_THESAURUS [ ExecMethod = Execute; StateMethod = GetState; Export = FALSE; ]
// Attribute: --------------------------------------------------
SID_TEXT_STANDARD [ ExecMethod = ExecuteAttr; StateMethod = GetState; Export = FALSE; ]
SID_DRAWTEXT_ATTR_DLG [ ExecMethod = ExecuteAttr; StateMethod = GetState; Export = FALSE; ]
@@ -126,6 +128,9 @@ interface TableDrawText
SID_VERTICALTEXT_STATE [ StateMethod = GetAttrState ; Export = FALSE; ]
SID_CTLFONT_STATE [ StateMethod = GetAttrState ; Export = FALSE; ]
+ SID_TRANSLITERATE_SENTENCE_CASE [ ExecMethod = ExecuteTrans; StateMethod = GetState; Export = FALSE; ]
+ SID_TRANSLITERATE_TITLE_CASE [ ExecMethod = ExecuteTrans; StateMethod = GetState; Export = FALSE; ]
+ SID_TRANSLITERATE_TOGGLE_CASE [ ExecMethod = ExecuteTrans; StateMethod = GetState; Export = FALSE; ]
SID_TRANSLITERATE_UPPER [ ExecMethod = ExecuteTrans; StateMethod = GetState; Export = FALSE; ]
SID_TRANSLITERATE_LOWER [ ExecMethod = ExecuteTrans; StateMethod = GetState; Export = FALSE; ]
SID_TRANSLITERATE_HALFWIDTH [ ExecMethod = ExecuteTrans; StateMethod = GetState; Export = FALSE; ]
diff --git a/sc/sdi/editsh.sdi b/sc/sdi/editsh.sdi
index ae71120c883e..1d95f2debdc3 100644
--- a/sc/sdi/editsh.sdi
+++ b/sc/sdi/editsh.sdi
@@ -46,6 +46,7 @@ interface TableText
SID_SELECTALL [ ExecMethod = Execute; StateMethod = GetState; Export = FALSE; ]
SID_CHARMAP [ ExecMethod = Execute; StateMethod = GetState; Export = FALSE; ]
FID_INSERT_NAME [ ExecMethod = Execute; StateMethod = GetState; Export = FALSE; ]
+ SID_THES [ ExecMethod = Execute; StateMethod = GetState; Export = FALSE; ]
SID_UNDO [ ExecMethod = ExecuteUndo; StateMethod = GetUndoState; Export = FALSE; ]
SID_REDO [ ExecMethod = ExecuteUndo; StateMethod = GetUndoState; Export = FALSE; ]
@@ -80,6 +81,9 @@ interface TableText
SID_HYPERLINK_GETLINK [ StateMethod = GetState; Export = FALSE; ]
SID_OPEN_HYPERLINK [ ExecMethod = Execute; StateMethod = GetState; Export = FALSE; ]
+ SID_TRANSLITERATE_SENTENCE_CASE [ ExecMethod = ExecuteTrans; StateMethod = GetState; Export = FALSE; ]
+ SID_TRANSLITERATE_TITLE_CASE [ ExecMethod = ExecuteTrans; StateMethod = GetState; Export = FALSE; ]
+ SID_TRANSLITERATE_TOGGLE_CASE [ ExecMethod = ExecuteTrans; StateMethod = GetState; Export = FALSE; ]
SID_TRANSLITERATE_UPPER [ ExecMethod = ExecuteTrans; StateMethod = GetState; Export = FALSE; ]
SID_TRANSLITERATE_LOWER [ ExecMethod = ExecuteTrans; StateMethod = GetState; Export = FALSE; ]
SID_TRANSLITERATE_HALFWIDTH [ ExecMethod = ExecuteTrans; StateMethod = GetState; Export = FALSE; ]
diff --git a/sc/source/core/data/cell.cxx b/sc/source/core/data/cell.cxx
index 56be361f6d38..a70a9b86e186 100644
--- a/sc/source/core/data/cell.cxx
+++ b/sc/source/core/data/cell.cxx
@@ -819,6 +819,10 @@ ScFormulaCell::ScFormulaCell( const ScFormulaCell& rCell, ScDocument& rDoc, cons
ScFormulaCell::~ScFormulaCell()
{
pDocument->RemoveFromFormulaTree( this );
+
+ if (pDocument->HasExternalRefManager())
+ pDocument->GetExternalRefManager()->removeRefCell(this);
+
delete pCode;
#ifdef DBG_UTIL
eCellType = CELLTYPE_DESTROYED;
diff --git a/sc/source/core/data/cell2.cxx b/sc/source/core/data/cell2.cxx
index 4de78c71fe79..1aab26acf3aa 100644
--- a/sc/source/core/data/cell2.cxx
+++ b/sc/source/core/data/cell2.cxx
@@ -1038,17 +1038,6 @@ void ScFormulaCell::UpdateReference(UpdateRefMode eUpdateRefMode,
delete pOld;
}
-
- pCode->Reset();
- for ( formula::FormulaToken* t = pCode->GetNextReferenceOrName(); t; t = pCode->GetNextReferenceOrName() )
- {
- StackVar sv = t->GetType();
- if (sv == svExternalSingleRef || sv == svExternalDoubleRef || sv == svExternalName)
- {
- pDocument->GetExternalRefManager()->updateRefCell(aOldPos, aPos, eUpdateRefMode == URM_COPY);
- break;
- }
- }
}
void ScFormulaCell::UpdateInsertTab(SCTAB nTable)
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index ee670d5ba0ef..6a5fe824197b 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -2100,22 +2100,6 @@ void ScColumn::CalcAfterLoad()
}
-bool ScColumn::MarkUsedExternalReferences()
-{
- bool bAllMarked = false;
- if (pItems)
- {
- for (SCSIZE i = 0; i < nCount && !bAllMarked; ++i)
- {
- ScBaseCell* pCell = pItems[i].pCell;
- if ( pCell->GetCellType() == CELLTYPE_FORMULA )
- bAllMarked = ((ScFormulaCell*)pCell)->MarkUsedExternalReferences();
- }
- }
- return bAllMarked;
-}
-
-
void ScColumn::ResetChanged( SCROW nStartRow, SCROW nEndRow )
{
if (pItems)
diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx
index 138b55f0794c..c5922aa88dcc 100755
--- a/sc/source/core/data/documen2.cxx
+++ b/sc/source/core/data/documen2.cxx
@@ -804,10 +804,6 @@ BOOL ScDocument::MoveTab( SCTAB nOldPos, SCTAB nNewPos )
if (pDrawLayer)
DrawMovePage( static_cast<sal_uInt16>(nOldPos), static_cast<sal_uInt16>(nNewPos) );
- // Update cells containing external references.
- if (pExternalRefMgr.get())
- pExternalRefMgr->updateRefMoveTable(nOldPos, nNewPos, false);
-
bValid = TRUE;
}
}
@@ -925,10 +921,6 @@ BOOL ScDocument::CopyTab( SCTAB nOldPos, SCTAB nNewPos, const ScMarkData* pOnlyM
pTab[nNewPos]->SetPageStyle( pTab[nOldPos]->GetPageStyle() );
pTab[nNewPos]->SetPendingRowHeights( pTab[nOldPos]->IsPendingRowHeights() );
-
- // Update cells containing external references.
- if (pExternalRefMgr.get())
- pExternalRefMgr->updateRefMoveTable(nOldPos, nNewPos, true);
}
else
SetAutoCalc( bOldAutoCalc );
diff --git a/sc/source/core/data/documen3.cxx b/sc/source/core/data/documen3.cxx
index 557f181c9d8f..77f59254e049 100644
--- a/sc/source/core/data/documen3.cxx
+++ b/sc/source/core/data/documen3.cxx
@@ -465,11 +465,8 @@ void ScDocument::MarkUsedExternalReferences()
// Charts.
bool bAllMarked = pExternalRefMgr->markUsedByLinkListeners();
// Formula cells.
- for (SCTAB nTab = 0; !bAllMarked && nTab < nMaxTableNumber; ++nTab)
- {
- if (pTab[nTab])
- bAllMarked = pTab[nTab]->MarkUsedExternalReferences();
- }
+ bAllMarked = pExternalRefMgr->markUsedExternalRefCells();
+
/* NOTE: Conditional formats and validation objects are marked when
* collecting them during export. */
}
diff --git a/sc/source/core/data/documen5.cxx b/sc/source/core/data/documen5.cxx
index d6653402c46a..d86d174ab414 100644
--- a/sc/source/core/data/documen5.cxx
+++ b/sc/source/core/data/documen5.cxx
@@ -705,6 +705,9 @@ void ScDocument::UpdateChartListenerCollection()
SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
DBG_ASSERT(pPage,"Page ?");
+ if (!pPage)
+ continue;
+
SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
SdrObject* pObject = aIter.Next();
while (pObject)
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index ff132a1f204b..7c08c4327183 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -375,10 +375,6 @@ BOOL ScDocument::InsertTab( SCTAB nPos, const String& rName,
if ( pChartListenerCollection )
pChartListenerCollection->UpdateScheduledSeriesRanges();
- // Update cells containing external references.
- if (pExternalRefMgr.get())
- pExternalRefMgr->updateRefInsertTable(nPos);
-
SetDirty();
bValid = TRUE;
}
@@ -467,11 +463,6 @@ BOOL ScDocument::DeleteTab( SCTAB nTab, ScDocument* pRefUndoDoc )
// #81844# sheet names of references are not valid until sheet is deleted
pChartListenerCollection->UpdateScheduledSeriesRanges();
-
- // Update cells containing external references.
- if (pExternalRefMgr.get())
- pExternalRefMgr->updateRefDeleteTable(nTab);
-
SetAutoCalc( bOldAutoCalc );
bValid = TRUE;
}
@@ -694,6 +685,10 @@ bool ScDocument::ShrinkToDataArea(SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow
if (nRow2 < rEndRow)
rEndRow = nRow2;
+ if (rStartCol > rEndCol || rStartRow > rEndRow)
+ // invalid range.
+ return false;
+
return true; // success!
}
@@ -708,11 +703,10 @@ bool ScDocument::ShrinkToUsedDataArea( SCTAB nTab, SCCOL& rStartCol,
// zusammenhaengender Bereich
void ScDocument::GetDataArea( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow,
- SCCOL& rEndCol, SCROW& rEndRow, BOOL bIncludeOld, bool bOnlyDown )
+ SCCOL& rEndCol, SCROW& rEndRow, BOOL bIncludeOld, bool bOnlyDown ) const
{
- if (VALIDTAB(nTab))
- if (pTab[nTab])
- pTab[nTab]->GetDataArea( rStartCol, rStartRow, rEndCol, rEndRow, bIncludeOld, bOnlyDown );
+ if (ValidTab(nTab) && pTab[nTab])
+ pTab[nTab]->GetDataArea( rStartCol, rStartRow, rEndCol, rEndRow, bIncludeOld, bOnlyDown );
}
diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx
index 75b288272c1e..a8b819072c21 100644
--- a/sc/source/core/data/table1.cxx
+++ b/sc/source/core/data/table1.cxx
@@ -678,7 +678,7 @@ BOOL ScTable::GetDataStart( SCCOL& rStartCol, SCROW& rStartRow ) const
}
void ScTable::GetDataArea( SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow,
- BOOL bIncludeOld, bool bOnlyDown ) const
+ BOOL bIncludeOld, bool bOnlyDown ) const
{
BOOL bLeft = FALSE;
BOOL bRight = FALSE;
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index 4dc7dddcaba1..69d16df7be58 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -1119,17 +1119,6 @@ void ScTable::CalcAfterLoad()
}
-bool ScTable::MarkUsedExternalReferences()
-{
- bool bAllMarked = false;
- for (SCCOL i=0; i <= MAXCOL && !bAllMarked; ++i)
- {
- bAllMarked = aCol[i].MarkUsedExternalReferences();
- }
- return bAllMarked;
-}
-
-
void ScTable::ResetChanged( const ScRange& rRange )
{
SCCOL nStartCol = rRange.aStart.Col();
diff --git a/sc/source/core/tool/queryparam.cxx b/sc/source/core/tool/queryparam.cxx
index 47418ec85f4d..5b3b92f78ee4 100644
--- a/sc/source/core/tool/queryparam.cxx
+++ b/sc/source/core/tool/queryparam.cxx
@@ -171,7 +171,11 @@ ScQueryParamTable::~ScQueryParamTable()
ScQueryParam::ScQueryParam() :
ScQueryParamBase(),
- ScQueryParamTable()
+ ScQueryParamTable(),
+ bDestPers(true),
+ nDestTab(0),
+ nDestCol(0),
+ nDestRow(0)
{
Clear();
}
diff --git a/sc/source/filter/excel/read.cxx b/sc/source/filter/excel/read.cxx
index 5b9cc3180699..3aef51d10c54 100644
--- a/sc/source/filter/excel/read.cxx
+++ b/sc/source/filter/excel/read.cxx
@@ -1211,7 +1211,9 @@ FltError ImportExcel8::Read( void )
pProgress.reset();
- AdjustRowHeight();
+ if (pD->IsAdjustHeightEnabled())
+ AdjustRowHeight();
+
PostDocLoad();
pD->CalcAfterLoad();
diff --git a/sc/source/filter/excel/xechart.cxx b/sc/source/filter/excel/xechart.cxx
index 1564b2db834e..b6b136da4b1e 100644
--- a/sc/source/filter/excel/xechart.cxx
+++ b/sc/source/filter/excel/xechart.cxx
@@ -39,6 +39,8 @@
#include <com/sun/star/chart/DataLabelPlacement.hpp>
#include <com/sun/star/chart/ErrorBarStyle.hpp>
#include <com/sun/star/chart/MissingValueTreatment.hpp>
+#include <com/sun/star/chart/XChartDocument.hpp>
+#include <com/sun/star/chart/XDiagramPositioning.hpp>
#include <com/sun/star/chart2/XChartDocument.hpp>
#include <com/sun/star/chart2/XDiagram.hpp>
#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
@@ -52,6 +54,9 @@
#include <com/sun/star/chart2/CurveStyle.hpp>
#include <com/sun/star/chart2/DataPointGeometry3D.hpp>
#include <com/sun/star/chart2/DataPointLabel.hpp>
+#include <com/sun/star/chart2/LegendExpansion.hpp>
+#include <com/sun/star/chart2/LegendPosition.hpp>
+#include <com/sun/star/chart2/RelativePosition.hpp>
#include <com/sun/star/chart2/StackingDirection.hpp>
#include <com/sun/star/chart2/TickmarkStyle.hpp>
@@ -75,38 +80,47 @@ using ::com::sun::star::uno::Any;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Sequence;
using ::com::sun::star::uno::UNO_QUERY;
+using ::com::sun::star::uno::UNO_QUERY_THROW;
+using ::com::sun::star::uno::UNO_SET_THROW;
using ::com::sun::star::uno::Exception;
using ::com::sun::star::beans::XPropertySet;
using ::com::sun::star::i18n::XBreakIterator;
using ::com::sun::star::frame::XModel;
+using ::com::sun::star::drawing::XShape;
using ::com::sun::star::drawing::XShapes;
+
+using ::com::sun::star::chart2::IncrementData;
+using ::com::sun::star::chart2::RelativePosition;
+using ::com::sun::star::chart2::ScaleData;
+using ::com::sun::star::chart2::SubIncrement;
+using ::com::sun::star::chart2::XAxis;
using ::com::sun::star::chart2::XChartDocument;
-using ::com::sun::star::chart2::XDiagram;
-using ::com::sun::star::chart2::XCoordinateSystemContainer;
-using ::com::sun::star::chart2::XCoordinateSystem;
using ::com::sun::star::chart2::XChartTypeContainer;
+using ::com::sun::star::chart2::XColorScheme;
+using ::com::sun::star::chart2::XCoordinateSystem;
+using ::com::sun::star::chart2::XCoordinateSystemContainer;
using ::com::sun::star::chart2::XChartType;
-using ::com::sun::star::chart2::XDataSeriesContainer;
using ::com::sun::star::chart2::XDataSeries;
-using ::com::sun::star::chart2::XRegressionCurveContainer;
+using ::com::sun::star::chart2::XDataSeriesContainer;
+using ::com::sun::star::chart2::XDiagram;
+using ::com::sun::star::chart2::XFormattedString;
+using ::com::sun::star::chart2::XLegend;
using ::com::sun::star::chart2::XRegressionCurve;
-using ::com::sun::star::chart2::XAxis;
+using ::com::sun::star::chart2::XRegressionCurveContainer;
using ::com::sun::star::chart2::XScaling;
-using ::com::sun::star::chart2::ScaleData;
-using ::com::sun::star::chart2::IncrementData;
-using ::com::sun::star::chart2::SubIncrement;
-using ::com::sun::star::chart2::XLegend;
-using ::com::sun::star::chart2::XTitled;
using ::com::sun::star::chart2::XTitle;
-using ::com::sun::star::chart2::XFormattedString;
-using ::com::sun::star::chart2::XColorScheme;
+using ::com::sun::star::chart2::XTitled;
+
+using ::com::sun::star::chart2::data::XDataSequence;
using ::com::sun::star::chart2::data::XDataSource;
using ::com::sun::star::chart2::data::XLabeledDataSequence;
-using ::com::sun::star::chart2::data::XDataSequence;
using ::formula::FormulaGrammar;
using ::formula::FormulaToken;
+namespace cssc = ::com::sun::star::chart;
+namespace cssc2 = ::com::sun::star::chart2;
+
// Helpers ====================================================================
namespace {
@@ -160,13 +174,15 @@ bool lclIsAutoAnyOrGetScaledValue( double& rfValue, const Any& rAny, bool bLogSc
// Common =====================================================================
/** Stores global data needed in various classes of the Chart export filter. */
-class XclExpChRootData : public XclChRootData
+struct XclExpChRootData : public XclChRootData
{
-public:
- explicit XclExpChRootData( XclExpChChart* pChartData );
+ typedef ::std::vector< XclChFrBlock > XclChFrBlockVector;
+
+ XclExpChChart& mrChartData; /// The chart data object.
+ XclChFrBlockVector maWrittenFrBlocks; /// Stack of future record levels already written out.
+ XclChFrBlockVector maUnwrittenFrBlocks; /// Stack of future record levels not yet written out.
- /** Returns a reference to the parent chart data object. */
- inline XclExpChChart& GetChartData() const { return *mpChartData; }
+ inline explicit XclExpChRootData( XclExpChChart& rChartData ) : mrChartData( rChartData ) {}
/** Registers a new future record level. */
void RegisterFutureRecBlock( const XclChFrBlock& rFrBlock );
@@ -174,22 +190,10 @@ public:
void InitializeFutureRecBlock( XclExpStream& rStrm );
/** Finalizes the current future record level (writes CHFRBLOCKEND record if needed). */
void FinalizeFutureRecBlock( XclExpStream& rStrm );
-
-private:
- typedef ::std::vector< XclChFrBlock > XclChFrBlockVector;
-
- XclExpChChart* mpChartData; /// Pointer to the chart data object.
- XclChFrBlockVector maWrittenFrBlocks; /// Stack of future record levels already written out.
- XclChFrBlockVector maUnwrittenFrBlocks; /// Stack of future record levels not yet written out.
};
// ----------------------------------------------------------------------------
-XclExpChRootData::XclExpChRootData( XclExpChChart* pChartData ) :
- mpChartData( pChartData )
-{
-}
-
void XclExpChRootData::RegisterFutureRecBlock( const XclChFrBlock& rFrBlock )
{
maUnwrittenFrBlocks.push_back( rFrBlock );
@@ -238,9 +242,9 @@ void XclExpChRootData::FinalizeFutureRecBlock( XclExpStream& rStrm )
// ----------------------------------------------------------------------------
-XclExpChRoot::XclExpChRoot( const XclExpRoot& rRoot, XclExpChChart* pChartData ) :
+XclExpChRoot::XclExpChRoot( const XclExpRoot& rRoot, XclExpChChart& rChartData ) :
XclExpRoot( rRoot ),
- mxChData( new XclExpChRootData( pChartData ) )
+ mxChData( new XclExpChRootData( rChartData ) )
{
}
@@ -248,29 +252,34 @@ XclExpChRoot::~XclExpChRoot()
{
}
+Reference< XChartDocument > XclExpChRoot::GetChartDocument() const
+{
+ return mxChData->mxChartDoc;
+}
+
XclExpChChart& XclExpChRoot::GetChartData() const
{
- return mxChData->GetChartData();
+ return mxChData->mrChartData;
}
const XclChTypeInfo& XclExpChRoot::GetChartTypeInfo( XclChTypeId eType ) const
{
- return mxChData->GetTypeInfoProvider().GetTypeInfo( eType );
+ return mxChData->mxTypeInfoProv->GetTypeInfo( eType );
}
const XclChTypeInfo& XclExpChRoot::GetChartTypeInfo( const OUString& rServiceName ) const
{
- return mxChData->GetTypeInfoProvider().GetTypeInfoFromService( rServiceName );
+ return mxChData->mxTypeInfoProv->GetTypeInfoFromService( rServiceName );
}
const XclChFormatInfo& XclExpChRoot::GetFormatInfo( XclChObjectType eObjType ) const
{
- return mxChData->GetFormatInfoProvider().GetFormatInfo( eObjType );
+ return mxChData->mxFmtInfoProv->GetFormatInfo( eObjType );
}
-void XclExpChRoot::InitConversion( XChartDocRef xChartDoc ) const
+void XclExpChRoot::InitConversion( XChartDocRef xChartDoc, const Rectangle& rChartRect ) const
{
- mxChData->InitConversion( xChartDoc );
+ mxChData->InitConversion( GetRoot(), xChartDoc, rChartRect );
}
void XclExpChRoot::FinishConversion() const
@@ -291,11 +300,41 @@ void XclExpChRoot::SetSystemColor( Color& rColor, sal_uInt32& rnColorId, sal_uIn
rnColorId = XclExpPalette::GetColorIdFromIndex( nSysColorIdx );
}
+sal_Int32 XclExpChRoot::CalcChartXFromHmm( sal_Int32 nPosX ) const
+{
+ return ::limit_cast< sal_Int32, double >( (nPosX - mxChData->mnBorderGapX) / mxChData->mfUnitSizeX, 0, EXC_CHART_TOTALUNITS );
+}
+
+sal_Int32 XclExpChRoot::CalcChartYFromHmm( sal_Int32 nPosY ) const
+{
+ return ::limit_cast< sal_Int32, double >( (nPosY - mxChData->mnBorderGapY) / mxChData->mfUnitSizeY, 0, EXC_CHART_TOTALUNITS );
+}
+
+XclChRectangle XclExpChRoot::CalcChartRectFromHmm( const ::com::sun::star::awt::Rectangle& rRect ) const
+{
+ XclChRectangle aRect;
+ aRect.mnX = CalcChartXFromHmm( rRect.X );
+ aRect.mnY = CalcChartYFromHmm( rRect.Y );
+ aRect.mnWidth = CalcChartXFromHmm( rRect.Width );
+ aRect.mnHeight = CalcChartYFromHmm( rRect.Height );
+ return aRect;
+}
+
+sal_Int32 XclExpChRoot::CalcChartXFromRelative( double fPosX ) const
+{
+ return CalcChartXFromHmm( static_cast< sal_Int32 >( fPosX * mxChData->maChartRect.GetWidth() + 0.5 ) );
+}
+
+sal_Int32 XclExpChRoot::CalcChartYFromRelative( double fPosY ) const
+{
+ return CalcChartYFromHmm( static_cast< sal_Int32 >( fPosY * mxChData->maChartRect.GetHeight() + 0.5 ) );
+}
+
void XclExpChRoot::ConvertLineFormat( XclChLineFormat& rLineFmt,
const ScfPropertySet& rPropSet, XclChPropertyMode ePropMode ) const
{
GetChartPropSetHelper().ReadLineProperties(
- rLineFmt, mxChData->GetLineDashTable(), rPropSet, ePropMode );
+ rLineFmt, *mxChData->mxLineDashTable, rPropSet, ePropMode );
}
bool XclExpChRoot::ConvertAreaFormat( XclChAreaFormat& rAreaFmt,
@@ -309,7 +348,7 @@ void XclExpChRoot::ConvertEscherFormat(
const ScfPropertySet& rPropSet, XclChPropertyMode ePropMode ) const
{
GetChartPropSetHelper().ReadEscherProperties( rEscherFmt, rPicFmt,
- mxChData->GetGradientTable(), mxChData->GetHatchTable(), mxChData->GetBitmapTable(), rPropSet, ePropMode );
+ *mxChData->mxGradientTable, *mxChData->mxHatchTable, *mxChData->mxBitmapTable, rPropSet, ePropMode );
}
sal_uInt16 XclExpChRoot::ConvertFont( const ScfPropertySet& rPropSet, sal_Int16 nScript ) const
@@ -404,6 +443,20 @@ void XclExpChFutureRecordBase::Save( XclExpStream& rStrm )
// Frame formatting ===========================================================
+XclExpChFramePos::XclExpChFramePos( sal_uInt16 nTLMode, sal_uInt16 nBRMode ) :
+ XclExpRecord( EXC_ID_CHFRAMEPOS, 20 )
+{
+ maData.mnTLMode = nTLMode;
+ maData.mnBRMode = nBRMode;
+}
+
+void XclExpChFramePos::WriteBody( XclExpStream& rStrm )
+{
+ rStrm << maData.mnTLMode << maData.mnBRMode << maData.maRect;
+}
+
+// ----------------------------------------------------------------------------
+
XclExpChLineFormat::XclExpChLineFormat( const XclExpChRoot& rRoot ) :
XclExpRecord( EXC_ID_CHLINEFORMAT, (rRoot.GetBiff() == EXC_BIFF8) ? 12 : 10 ),
mnColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWTEXT ) )
@@ -1118,6 +1171,36 @@ void XclExpChText::ConvertTitle( Reference< XTitle > xTitle, sal_uInt16 nTarget
// rotation
ConvertRotationBase( GetChRoot(), aTitleProp, true );
+
+ // manual text position - only for main title
+ mxFramePos.reset( new XclExpChFramePos( EXC_CHFRAMEPOS_PARENT, EXC_CHFRAMEPOS_PARENT ) );
+ if( nTarget == EXC_CHOBJLINK_TITLE )
+ {
+ Any aRelPos;
+ if( aTitleProp.GetAnyProperty( aRelPos, EXC_CHPROP_RELATIVEPOSITION ) && aRelPos.has< RelativePosition >() ) try
+ {
+ // calculate absolute position for CHTEXT record
+ Reference< cssc::XChartDocument > xChart1Doc( GetChartDocument(), UNO_QUERY_THROW );
+ Reference< XShape > xTitleShape( xChart1Doc->getTitle(), UNO_SET_THROW );
+ ::com::sun::star::awt::Point aPos = xTitleShape->getPosition();
+ ::com::sun::star::awt::Size aSize = xTitleShape->getSize();
+ ::com::sun::star::awt::Rectangle aRect( aPos.X, aPos.Y, aSize.Width, aSize.Height );
+ maData.maRect = CalcChartRectFromHmm( aRect );
+ ::insert_value( maData.mnFlags2, EXC_CHTEXT_POS_MOVED, 0, 4 );
+ // manual title position implies manual plot area
+ GetChartData().SetManualPlotArea();
+ // calculate the default title position in chart units
+ sal_Int32 nDefPosX = ::std::max< sal_Int32 >( (EXC_CHART_TOTALUNITS - maData.maRect.mnWidth) / 2, 0 );
+ sal_Int32 nDefPosY = 85;
+ // set the position relative to the standard position
+ XclChRectangle& rFrameRect = mxFramePos->GetFramePosData().maRect;
+ rFrameRect.mnX = maData.maRect.mnX - nDefPosX;
+ rFrameRect.mnY = maData.maRect.mnY - nDefPosY;
+ }
+ catch( Exception& )
+ {
+ }
+ }
}
else
{
@@ -1137,8 +1220,7 @@ bool XclExpChText::ConvertDataLabel( const ScfPropertySet& rPropSet,
{
SetFutureRecordContext( EXC_CHFRBLOCK_TEXT_DATALABEL, rPointPos.mnPointIdx, rPointPos.mnSeriesIdx );
- namespace cssc = ::com::sun::star::chart2;
- cssc::DataPointLabel aPointLabel;
+ cssc2::DataPointLabel aPointLabel;
if( !rPropSet.GetProperty( aPointLabel, EXC_CHPROP_LABEL ) )
return false;
@@ -1184,31 +1266,33 @@ bool XclExpChText::ConvertDataLabel( const ScfPropertySet& rPropSet,
ConvertRotationBase( GetChRoot(), rPropSet, false );
// label placement
sal_Int32 nPlacement = 0;
+ sal_uInt16 nLabelPos = EXC_CHTEXT_POS_AUTO;
if( rPropSet.GetProperty( nPlacement, EXC_CHPROP_LABELPLACEMENT ) )
{
using namespace ::com::sun::star::chart::DataLabelPlacement;
if( nPlacement == rTypeInfo.mnDefaultLabelPos )
{
- maData.mnPlacement = EXC_CHTEXT_POS_DEFAULT;
+ nLabelPos = EXC_CHTEXT_POS_DEFAULT;
}
else switch( nPlacement )
{
- case AVOID_OVERLAP: maData.mnPlacement = EXC_CHTEXT_POS_AUTO; break;
- case CENTER: maData.mnPlacement = EXC_CHTEXT_POS_CENTER; break;
- case TOP: maData.mnPlacement = EXC_CHTEXT_POS_ABOVE; break;
- case TOP_LEFT: maData.mnPlacement = EXC_CHTEXT_POS_LEFT; break;
- case LEFT: maData.mnPlacement = EXC_CHTEXT_POS_LEFT; break;
- case BOTTOM_LEFT: maData.mnPlacement = EXC_CHTEXT_POS_LEFT; break;
- case BOTTOM: maData.mnPlacement = EXC_CHTEXT_POS_BELOW; break;
- case BOTTOM_RIGHT: maData.mnPlacement = EXC_CHTEXT_POS_RIGHT; break;
- case RIGHT: maData.mnPlacement = EXC_CHTEXT_POS_RIGHT; break;
- case TOP_RIGHT: maData.mnPlacement = EXC_CHTEXT_POS_RIGHT; break;
- case INSIDE: maData.mnPlacement = EXC_CHTEXT_POS_INSIDE; break;
- case OUTSIDE: maData.mnPlacement = EXC_CHTEXT_POS_OUTSIDE; break;
- case NEAR_ORIGIN: maData.mnPlacement = EXC_CHTEXT_POS_AXIS; break;
+ case AVOID_OVERLAP: nLabelPos = EXC_CHTEXT_POS_AUTO; break;
+ case CENTER: nLabelPos = EXC_CHTEXT_POS_CENTER; break;
+ case TOP: nLabelPos = EXC_CHTEXT_POS_ABOVE; break;
+ case TOP_LEFT: nLabelPos = EXC_CHTEXT_POS_LEFT; break;
+ case LEFT: nLabelPos = EXC_CHTEXT_POS_LEFT; break;
+ case BOTTOM_LEFT: nLabelPos = EXC_CHTEXT_POS_LEFT; break;
+ case BOTTOM: nLabelPos = EXC_CHTEXT_POS_BELOW; break;
+ case BOTTOM_RIGHT: nLabelPos = EXC_CHTEXT_POS_RIGHT; break;
+ case RIGHT: nLabelPos = EXC_CHTEXT_POS_RIGHT; break;
+ case TOP_RIGHT: nLabelPos = EXC_CHTEXT_POS_RIGHT; break;
+ case INSIDE: nLabelPos = EXC_CHTEXT_POS_INSIDE; break;
+ case OUTSIDE: nLabelPos = EXC_CHTEXT_POS_OUTSIDE; break;
+ case NEAR_ORIGIN: nLabelPos = EXC_CHTEXT_POS_AXIS; break;
default: DBG_ERRORFILE( "XclExpChText::ConvertDataLabel - unknown label placement type" );
}
}
+ ::insert_value( maData.mnFlags2, nLabelPos, 0, 4 );
// source link (contains number format)
mxSrcLink.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_TITLE ) );
if( bShowValue || bShowPercent )
@@ -1255,6 +1339,8 @@ sal_uInt16 XclExpChText::GetAttLabelFlags() const
void XclExpChText::WriteSubRecords( XclExpStream& rStrm )
{
+ // CHFRAMEPOS record
+ lclSaveRecord( rStrm, mxFramePos );
// CHFONT record
lclSaveRecord( rStrm, mxFont );
// CHSOURCELINK group
@@ -1279,7 +1365,7 @@ void XclExpChText::WriteBody( XclExpStream& rStrm )
if( GetBiff() == EXC_BIFF8 )
{
rStrm << GetPalette().GetColorIndex( mnTextColorId )
- << maData.mnPlacement
+ << maData.mnFlags2
<< maData.mnRotation;
}
}
@@ -1604,7 +1690,6 @@ bool XclExpChSerErrorBar::Convert( XclExpChSourceLink& rValueLink, sal_uInt16& r
bool bOk = rPropSet.GetProperty( nBarStyle, EXC_CHPROP_ERRORBARSTYLE );
if( bOk )
{
- namespace cssc = ::com::sun::star::chart;
switch( nBarStyle )
{
case cssc::ErrorBarStyle::ABSOLUTE:
@@ -2148,12 +2233,66 @@ void XclExpChLegend::Convert( const ScfPropertySet& rPropSet )
// text properties
mxText.reset( new XclExpChText( GetChRoot() ) );
mxText->ConvertLegend( rPropSet );
- // special legend properties
- GetChartPropSetHelper().ReadLegendProperties( maData, rPropSet );
+
+ // legend position
+ Any aRelPosAny;
+ rPropSet.GetAnyProperty( aRelPosAny, EXC_CHPROP_RELATIVEPOSITION );
+ if( aRelPosAny.has< RelativePosition >() )
+ {
+ try
+ {
+ /* The 'RelativePosition' property is used as indicator of manually
+ changed legend position, but due to the different anchor modes
+ used by this property (in the RelativePosition.Anchor member)
+ it cannot be used to calculate the position easily. For this,
+ the Chart1 API will be used instead. */
+ Reference< ::com::sun::star::chart::XChartDocument > xChart1Doc( GetChartDocument(), UNO_QUERY_THROW );
+ Reference< XShape > xChart1Legend( xChart1Doc->getLegend(), UNO_SET_THROW );
+ // coordinates in CHLEGEND record written but not used by Excel
+ mxFramePos.reset( new XclExpChFramePos( EXC_CHFRAMEPOS_CHARTSIZE, EXC_CHFRAMEPOS_PARENT ) );
+ XclChFramePos& rFramePos = mxFramePos->GetFramePosData();
+ rFramePos.maRect.mnX = maData.maRect.mnX = CalcChartXFromHmm( xChart1Legend->getPosition().X );
+ rFramePos.maRect.mnY = maData.maRect.mnY = CalcChartYFromHmm( xChart1Legend->getPosition().Y );
+ // manual legend position implies manual plot area
+ GetChartData().SetManualPlotArea();
+ maData.mnDockMode = EXC_CHLEGEND_NOTDOCKED;
+ }
+ catch( Exception& )
+ {
+ OSL_ENSURE( false, "XclExpChLegend::Convert - cannot get legend shape" );
+ maData.mnDockMode = EXC_CHLEGEND_RIGHT;
+ }
+ }
+ else
+ {
+ cssc2::LegendPosition eApiPos = cssc2::LegendPosition_CUSTOM;
+ rPropSet.GetProperty( eApiPos, EXC_CHPROP_ANCHORPOSITION );
+ switch( eApiPos )
+ {
+ case cssc2::LegendPosition_LINE_START: maData.mnDockMode = EXC_CHLEGEND_LEFT; break;
+ case cssc2::LegendPosition_LINE_END: maData.mnDockMode = EXC_CHLEGEND_RIGHT; break;
+ case cssc2::LegendPosition_PAGE_START: maData.mnDockMode = EXC_CHLEGEND_TOP; break;
+ case cssc2::LegendPosition_PAGE_END: maData.mnDockMode = EXC_CHLEGEND_BOTTOM; break;
+ default:
+ OSL_ENSURE( false, "XclExpChLegend::Convert - unrecognized legend position" );
+ maData.mnDockMode = EXC_CHLEGEND_RIGHT;
+ }
+ }
+
+ // legend expansion
+ cssc2::LegendExpansion eApiExpand = cssc2::LegendExpansion_BALANCED;
+ rPropSet.GetProperty( eApiExpand, EXC_CHPROP_EXPANSION );
+ ::set_flag( maData.mnFlags, EXC_CHLEGEND_STACKED, eApiExpand != cssc2::LegendExpansion_WIDE );
+
+ // other flags
+ ::set_flag( maData.mnFlags, EXC_CHLEGEND_AUTOSERIES );
+ const sal_uInt16 nAutoFlags = EXC_CHLEGEND_DOCKED | EXC_CHLEGEND_AUTOPOSX | EXC_CHLEGEND_AUTOPOSY;
+ ::set_flag( maData.mnFlags, nAutoFlags, maData.mnDockMode != EXC_CHLEGEND_NOTDOCKED );
}
void XclExpChLegend::WriteSubRecords( XclExpStream& rStrm )
{
+ lclSaveRecord( rStrm, mxFramePos );
lclSaveRecord( rStrm, mxText );
lclSaveRecord( rStrm, mxFrame );
}
@@ -2252,13 +2391,12 @@ void XclExpChTypeGroup::ConvertSeries(
{
// stacking direction (stacked/percent/deep 3d) from first series
ScfPropertySet aSeriesProp( aSeriesVec.front() );
- namespace cssc = ::com::sun::star::chart2;
- cssc::StackingDirection eStacking;
+ cssc2::StackingDirection eStacking;
if( !aSeriesProp.GetProperty( eStacking, EXC_CHPROP_STACKINGDIR ) )
- eStacking = cssc::StackingDirection_NO_STACKING;
+ eStacking = cssc2::StackingDirection_NO_STACKING;
// stacked or percent chart
- if( maTypeInfo.mbSupportsStacking && (eStacking == cssc::StackingDirection_Y_STACKING) )
+ if( maTypeInfo.mbSupportsStacking && (eStacking == cssc2::StackingDirection_Y_STACKING) )
{
// percent overrides simple stacking
maType.SetStacked( bPercent );
@@ -2275,7 +2413,7 @@ void XclExpChTypeGroup::ConvertSeries(
}
// deep 3d chart or clustered 3d chart (stacked is not clustered)
- if( (eStacking == cssc::StackingDirection_NO_STACKING) && Is3dWallChart() )
+ if( (eStacking == cssc2::StackingDirection_NO_STACKING) && Is3dWallChart() )
mxChart3d->SetClustered();
// varied point colors
@@ -2396,7 +2534,8 @@ bool XclExpChTypeGroup::CreateStockSeries( Reference< XDataSeries > xDataSeries,
void XclExpChTypeGroup::WriteBody( XclExpStream& rStrm )
{
- rStrm << maData.maRect << maData.mnFlags << maData.mnGroupIdx;
+ rStrm.WriteZeroBytes( 16 );
+ rStrm << maData.mnFlags << maData.mnGroupIdx;
}
// Axes =======================================================================
@@ -2421,7 +2560,6 @@ void XclExpChLabelRange::Convert( const ScaleData& rScaleData, bool bMirrorOrien
void XclExpChLabelRange::ConvertAxisPosition( const ScfPropertySet& rPropSet )
{
- namespace cssc = ::com::sun::star::chart;
cssc::ChartAxisPosition eAxisPos = cssc::ChartAxisPosition_VALUE;
rPropSet.GetProperty( eAxisPos, EXC_CHPROP_CROSSOVERPOSITION );
double fCrossingPos = 1.0;
@@ -2479,13 +2617,11 @@ void XclExpChValueRange::Convert( const ScaleData& rScaleData )
::set_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOMINOR, bAutoMinor );
// reverse order
- namespace cssc = ::com::sun::star::chart2;
- ::set_flag( maData.mnFlags, EXC_CHVALUERANGE_REVERSE, rScaleData.Orientation == cssc::AxisOrientation_REVERSE );
+ ::set_flag( maData.mnFlags, EXC_CHVALUERANGE_REVERSE, rScaleData.Orientation == cssc2::AxisOrientation_REVERSE );
}
void XclExpChValueRange::ConvertAxisPosition( const ScfPropertySet& rPropSet )
{
- namespace cssc = ::com::sun::star::chart;
cssc::ChartAxisPosition eAxisPos = cssc::ChartAxisPosition_VALUE;
double fCrossingPos = 0.0;
if( rPropSet.GetProperty( eAxisPos, EXC_CHPROP_CROSSOVERPOSITION ) && rPropSet.GetProperty( fCrossingPos, EXC_CHPROP_CROSSOVERVALUE ) )
@@ -2569,7 +2705,6 @@ void XclExpChTick::Convert( const ScfPropertySet& rPropSet, const XclChExtTypeIn
}
else
{
- namespace cssc = ::com::sun::star::chart;
cssc::ChartAxisLabelPosition eApiLabelPos = cssc::ChartAxisLabelPosition_NEAR_AXIS;
rPropSet.GetProperty( eApiLabelPos, EXC_CHPROP_LABELPOSITION );
switch( eApiLabelPos )
@@ -2602,9 +2737,9 @@ void XclExpChTick::WriteBody( XclExpStream& rStrm )
rStrm << maData.mnMajor
<< maData.mnMinor
<< maData.mnLabelPos
- << maData.mnBackMode
- << maData.maRect
- << maData.maTextColor
+ << maData.mnBackMode;
+ rStrm.WriteZeroBytes( 16 );
+ rStrm << maData.maTextColor
<< maData.mnFlags;
if( GetBiff() == EXC_BIFF8 )
rStrm << GetPalette().GetColorIndex( mnTextColorId ) << maData.mnRotation;
@@ -2758,7 +2893,8 @@ void XclExpChAxis::WriteSubRecords( XclExpStream& rStrm )
void XclExpChAxis::WriteBody( XclExpStream& rStrm )
{
- rStrm << maData.mnType << maData.maRect;
+ rStrm << maData.mnType;
+ rStrm.WriteZeroBytes( 16 );
}
// ----------------------------------------------------------------------------
@@ -2903,6 +3039,28 @@ sal_uInt16 XclExpChAxesSet::Convert( Reference< XDiagram > xDiagram, sal_uInt16
}
}
+ // inner and outer plot area position and size
+ try
+ {
+ Reference< ::com::sun::star::chart::XChartDocument > xChart1Doc( GetChartDocument(), UNO_QUERY_THROW );
+ Reference< ::com::sun::star::chart::XDiagramPositioning > xPositioning( xChart1Doc->getDiagram(), UNO_QUERY_THROW );
+ // set manual flag in chart data
+ if( !xPositioning->isAutomaticDiagramPositioning() )
+ GetChartData().SetManualPlotArea();
+ // the CHAXESSET record contains the inner plot area
+ maData.maRect = CalcChartRectFromHmm( xPositioning->calculateDiagramPositionExcludingAxes() );
+ // the embedded CHFRAMEPOS record contains the outer plot area
+ mxFramePos.reset( new XclExpChFramePos( EXC_CHFRAMEPOS_PARENT, EXC_CHFRAMEPOS_PARENT ) );
+ // for pie charts, always use inner plot area size to exclude the data labels as Excel does
+ const XclExpChTypeGroup* pFirstTypeGroup = GetFirstTypeGroup().get();
+ bool bPieChart = pFirstTypeGroup && (pFirstTypeGroup->GetTypeInfo().meTypeCateg == EXC_CHTYPECATEG_PIE);
+ mxFramePos->GetFramePosData().maRect = bPieChart ? maData.maRect :
+ CalcChartRectFromHmm( xPositioning->calculateDiagramPositionIncludingAxes() );
+ }
+ catch( Exception& )
+ {
+ }
+
// return first unused chart type group index for next axes set
return nGroupIdx;
}
@@ -2915,14 +3073,7 @@ bool XclExpChAxesSet::Is3dChart() const
void XclExpChAxesSet::WriteSubRecords( XclExpStream& rStrm )
{
- /* Need to set a reasonable size for the plot area, otherwise Excel will
- move away embedded shapes while auto-sizing the plot area. This is just
- a wild guess, but will be fixed with implementing manual positioning of
- chart elements. */
- rStrm.StartRecord( EXC_ID_CHFRAMEPOS, 20 );
- rStrm << sal_uInt16(2) << sal_uInt16(2) << sal_uInt32(66) << sal_uInt32(626) << sal_uInt32(3384) << sal_uInt32(3231);
- rStrm.EndRecord();
-
+ lclSaveRecord( rStrm, mxFramePos );
lclSaveRecord( rStrm, mxXAxis );
lclSaveRecord( rStrm, mxYAxis );
lclSaveRecord( rStrm, mxZAxis );
@@ -2974,10 +3125,10 @@ void XclExpChAxesSet::WriteBody( XclExpStream& rStrm )
// The chart object ===========================================================
XclExpChChart::XclExpChChart( const XclExpRoot& rRoot,
- Reference< XChartDocument > xChartDoc, const Size& rSize ) :
- XclExpChGroupBase( XclExpChRoot( rRoot, this ), EXC_CHFRBLOCK_TYPE_CHART, EXC_ID_CHCHART, 16 )
+ Reference< XChartDocument > xChartDoc, const Rectangle& rChartRect ) :
+ XclExpChGroupBase( XclExpChRoot( rRoot, *this ), EXC_CHFRBLOCK_TYPE_CHART, EXC_ID_CHCHART, 16 )
{
- Size aPtSize = OutputDevice::LogicToLogic( rSize, MapMode( MAP_100TH_MM ), MapMode( MAP_POINT ) );
+ Size aPtSize = OutputDevice::LogicToLogic( rChartRect.GetSize(), MapMode( MAP_100TH_MM ), MapMode( MAP_POINT ) );
// rectangle is stored in 16.16 fixed-point format
maRect.mnX = maRect.mnY = 0;
maRect.mnWidth = static_cast< sal_Int32 >( aPtSize.Width() << 16 );
@@ -3001,8 +3152,8 @@ XclExpChChart::XclExpChChart( const XclExpRoot& rRoot,
bool bIncludeHidden = aDiagramProp.GetBoolProperty( EXC_CHPROP_INCLUDEHIDDENCELLS );
::set_flag( maProps.mnFlags, EXC_CHPROPS_SHOWVISIBLEONLY, !bIncludeHidden );
- // initialize API conversion (remembers xChartDoc internally)
- InitConversion( xChartDoc );
+ // initialize API conversion (remembers xChartDoc and rChartRect internally)
+ InitConversion( xChartDoc, rChartRect );
// chart frame
ScfPropertySet aFrameProp( xChartDoc->getPageBackground() );
@@ -3060,6 +3211,13 @@ void XclExpChChart::SetDataLabel( XclExpChTextRef xText )
maLabels.AppendRecord( xText );
}
+void XclExpChChart::SetManualPlotArea()
+{
+ // this flag does not exist in BIFF5
+ if( GetBiff() == EXC_BIFF8 )
+ ::set_flag( maProps.mnFlags, EXC_CHPROPS_USEMANPLOTAREA );
+}
+
void XclExpChChart::WriteSubRecords( XclExpStream& rStrm )
{
// background format
@@ -3105,7 +3263,7 @@ XclExpChartDrawing::XclExpChartDrawing( const XclExpRoot& rRoot,
/* Create a new independent object manager with own DFF stream for the
DGCONTAINER, pass global manager as parent for shared usage of
global DFF data (picture container etc.). */
- mxObjMgr.reset( new XclExpEmbeddedObjectManager( GetObjectManager(), rChartSize, EXC_CHART_UNIT, EXC_CHART_UNIT ) );
+ mxObjMgr.reset( new XclExpEmbeddedObjectManager( GetObjectManager(), rChartSize, EXC_CHART_TOTALUNITS, EXC_CHART_TOTALUNITS ) );
// initialize the drawing object list
mxObjMgr->StartSheet();
// process the draw page (convert all shapes)
@@ -3128,17 +3286,17 @@ void XclExpChartDrawing::Save( XclExpStream& rStrm )
// ----------------------------------------------------------------------------
-XclExpChart::XclExpChart( const XclExpRoot& rRoot, Reference< XModel > xModel, const Size& rSize ) :
+XclExpChart::XclExpChart( const XclExpRoot& rRoot, Reference< XModel > xModel, const Rectangle& rChartRect ) :
XclExpSubStream( EXC_BOF_CHART ),
XclExpRoot( rRoot )
{
AppendNewRecord( new XclExpChartPageSettings( rRoot ) );
AppendNewRecord( new XclExpBoolRecord( EXC_ID_PROTECT, false ) );
- AppendNewRecord( new XclExpChartDrawing( rRoot, xModel, rSize ) );
+ AppendNewRecord( new XclExpChartDrawing( rRoot, xModel, rChartRect.GetSize() ) );
AppendNewRecord( new XclExpUInt16Record( EXC_ID_CHUNITS, EXC_CHUNITS_TWIPS ) );
Reference< XChartDocument > xChartDoc( xModel, UNO_QUERY );
- AppendNewRecord( new XclExpChChart( rRoot, xChartDoc, rSize ) );
+ AppendNewRecord( new XclExpChChart( rRoot, xChartDoc, rChartRect ) );
}
// ============================================================================
diff --git a/sc/source/filter/excel/xeescher.cxx b/sc/source/filter/excel/xeescher.cxx
index 2df531a9b932..a4b5864668b4 100644
--- a/sc/source/filter/excel/xeescher.cxx
+++ b/sc/source/filter/excel/xeescher.cxx
@@ -956,8 +956,8 @@ XclExpChartObj::XclExpChartObj( XclExpObjectManager& rObjMgr, Reference< XShape
aShapeProp.GetProperty( xModel, CREATE_OUSTRING( "Model" ) );
::com::sun::star::awt::Rectangle aBoundRect;
aShapeProp.GetProperty( aBoundRect, CREATE_OUSTRING( "BoundRect" ) );
- Size aSize( aBoundRect.Width, aBoundRect.Height );
- mxChart.reset( new XclExpChart( GetRoot(), xModel, aSize ) );
+ Rectangle aChartRect( Point( aBoundRect.X, aBoundRect.Y ), Size( aBoundRect.Width, aBoundRect.Height ) );
+ mxChart.reset( new XclExpChart( GetRoot(), xModel, aChartRect ) );
}
XclExpChartObj::~XclExpChartObj()
diff --git a/sc/source/filter/excel/xichart.cxx b/sc/source/filter/excel/xichart.cxx
index 6734f90948e4..428bbe2d4f82 100644..100755
--- a/sc/source/filter/excel/xichart.cxx
+++ b/sc/source/filter/excel/xichart.cxx
@@ -37,12 +37,14 @@
#include <com/sun/star/drawing/Direction3D.hpp>
#include <com/sun/star/drawing/ProjectionMode.hpp>
#include <com/sun/star/drawing/ShadeMode.hpp>
+#include <com/sun/star/drawing/XShape.hpp>
#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
#include <com/sun/star/chart/ChartAxisArrangeOrderType.hpp>
#include <com/sun/star/chart/ChartAxisLabelPosition.hpp>
#include <com/sun/star/chart/ChartAxisMarkPosition.hpp>
#include <com/sun/star/chart/ChartAxisPosition.hpp>
#include <com/sun/star/chart/XChartDocument.hpp>
+#include <com/sun/star/chart/XDiagramPositioning.hpp>
#include <com/sun/star/chart2/XChartDocument.hpp>
#include <com/sun/star/chart2/XDiagram.hpp>
#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
@@ -57,8 +59,11 @@
#include <com/sun/star/chart2/CurveStyle.hpp>
#include <com/sun/star/chart2/DataPointGeometry3D.hpp>
#include <com/sun/star/chart2/DataPointLabel.hpp>
+#include <com/sun/star/chart2/LegendExpansion.hpp>
+#include <com/sun/star/chart2/LegendPosition.hpp>
#include <com/sun/star/chart2/StackingDirection.hpp>
#include <com/sun/star/chart2/TickmarkStyle.hpp>
+#include <com/sun/star/chart2/RelativePosition.hpp>
#include <com/sun/star/chart/DataLabelPlacement.hpp>
#include <com/sun/star/chart/ErrorBarStyle.hpp>
#include <com/sun/star/chart/MissingValueTreatment.hpp>
@@ -98,36 +103,41 @@ using ::com::sun::star::frame::XModel;
using ::com::sun::star::util::XNumberFormatsSupplier;
using ::com::sun::star::drawing::XDrawPage;
using ::com::sun::star::drawing::XDrawPageSupplier;
+using ::com::sun::star::drawing::XShape;
+using ::com::sun::star::chart2::IncrementData;
+using ::com::sun::star::chart2::RelativePosition;
+using ::com::sun::star::chart2::ScaleData;
+using ::com::sun::star::chart2::SubIncrement;
+using ::com::sun::star::chart2::XAxis;
using ::com::sun::star::chart2::XChartDocument;
-using ::com::sun::star::chart2::XDiagram;
-using ::com::sun::star::chart2::XCoordinateSystemContainer;
-using ::com::sun::star::chart2::XCoordinateSystem;
-using ::com::sun::star::chart2::XChartTypeContainer;
using ::com::sun::star::chart2::XChartType;
-using ::com::sun::star::chart2::XDataSeriesContainer;
+using ::com::sun::star::chart2::XChartTypeContainer;
+using ::com::sun::star::chart2::XCoordinateSystem;
+using ::com::sun::star::chart2::XCoordinateSystemContainer;
using ::com::sun::star::chart2::XDataSeries;
+using ::com::sun::star::chart2::XDataSeriesContainer;
+using ::com::sun::star::chart2::XDiagram;
+using ::com::sun::star::chart2::XFormattedString;
+using ::com::sun::star::chart2::XLegend;
using ::com::sun::star::chart2::XRegressionCurve;
using ::com::sun::star::chart2::XRegressionCurveContainer;
-using ::com::sun::star::chart2::XAxis;
using ::com::sun::star::chart2::XScaling;
-using ::com::sun::star::chart2::ScaleData;
-using ::com::sun::star::chart2::IncrementData;
-using ::com::sun::star::chart2::SubIncrement;
-using ::com::sun::star::chart2::XLegend;
-using ::com::sun::star::chart2::XTitled;
using ::com::sun::star::chart2::XTitle;
-using ::com::sun::star::chart2::XFormattedString;
+using ::com::sun::star::chart2::XTitled;
using ::com::sun::star::chart2::data::XDataProvider;
using ::com::sun::star::chart2::data::XDataReceiver;
+using ::com::sun::star::chart2::data::XDataSequence;
using ::com::sun::star::chart2::data::XDataSink;
using ::com::sun::star::chart2::data::XLabeledDataSequence;
-using ::com::sun::star::chart2::data::XDataSequence;
using ::formula::FormulaToken;
using ::formula::StackVar;
+namespace cssc = ::com::sun::star::chart;
+namespace cssc2 = ::com::sun::star::chart2;
+
// Helpers ====================================================================
namespace {
@@ -158,28 +168,18 @@ void lclSetExpValueOrClearAny( Any& rAny, double fValue, bool bLogScale, bool bC
// Common =====================================================================
/** Stores global data needed in various classes of the Chart import filter. */
-class XclImpChRootData : public XclChRootData
+struct XclImpChRootData : public XclChRootData
{
-public:
- explicit XclImpChRootData( XclImpChChart* pChartData );
+ XclImpChChart& mrChartData; /// The chart data object.
- /** Returns a reference to the parent chart data object. */
- inline XclImpChChart& GetChartData() const { return *mpChartData; }
-
-private:
- XclImpChChart* mpChartData; /// Pointer to the chart data object.
+ inline explicit XclImpChRootData( XclImpChChart& rChartData ) : mrChartData( rChartData ) {}
};
-XclImpChRootData::XclImpChRootData( XclImpChChart* pChartData ) :
- mpChartData( pChartData )
-{
-}
-
// ----------------------------------------------------------------------------
-XclImpChRoot::XclImpChRoot( const XclImpRoot& rRoot, XclImpChChart* pChartData ) :
+XclImpChRoot::XclImpChRoot( const XclImpRoot& rRoot, XclImpChChart& rChartData ) :
XclImpRoot( rRoot ),
- mxChData( new XclImpChRootData( pChartData ) )
+ mxChData( new XclImpChRootData( rChartData ) )
{
}
@@ -189,22 +189,22 @@ XclImpChRoot::~XclImpChRoot()
XclImpChChart& XclImpChRoot::GetChartData() const
{
- return mxChData->GetChartData();
+ return mxChData->mrChartData;
}
const XclChTypeInfo& XclImpChRoot::GetChartTypeInfo( XclChTypeId eType ) const
{
- return mxChData->GetTypeInfoProvider().GetTypeInfo( eType );
+ return mxChData->mxTypeInfoProv->GetTypeInfo( eType );
}
const XclChTypeInfo& XclImpChRoot::GetChartTypeInfo( sal_uInt16 nRecId ) const
{
- return mxChData->GetTypeInfoProvider().GetTypeInfoFromRecId( nRecId );
+ return mxChData->mxTypeInfoProv->GetTypeInfoFromRecId( nRecId );
}
const XclChFormatInfo& XclImpChRoot::GetFormatInfo( XclChObjectType eObjType ) const
{
- return mxChData->GetFormatInfoProvider().GetFormatInfo( eObjType );
+ return mxChData->mxFmtInfoProv->GetFormatInfo( eObjType );
}
Color XclImpChRoot::GetFontAutoColor() const
@@ -225,10 +225,10 @@ Color XclImpChRoot::GetSeriesFillAutoColor( sal_uInt16 nFormatIdx ) const
return ScfTools::GetMixedColor( aColor, rPal.GetColor( EXC_COLOR_CHWINDOWBACK ), nTrans );
}
-void XclImpChRoot::InitConversion( Reference< XChartDocument > xChartDoc ) const
+void XclImpChRoot::InitConversion( Reference< XChartDocument > xChartDoc, const Rectangle& rChartRect ) const
{
// create formatting object tables
- mxChData->InitConversion( xChartDoc );
+ mxChData->InitConversion( GetRoot(), xChartDoc, rChartRect );
// lock the model to suppress any internal updates
Reference< XModel > xModel( xChartDoc, UNO_QUERY );
@@ -255,7 +255,7 @@ void XclImpChRoot::FinishConversion( XclImpDffConverter& rDffConv ) const
{
rDffConv.Progress( EXC_CHART_PROGRESS_SIZE );
// unlock the model
- Reference< XModel > xModel( mxChData->GetChartDoc(), UNO_QUERY );
+ Reference< XModel > xModel( mxChData->mxChartDoc, UNO_QUERY );
if( xModel.is() )
xModel->unlockControllers();
rDffConv.Progress( EXC_CHART_PROGRESS_SIZE );
@@ -265,14 +265,48 @@ void XclImpChRoot::FinishConversion( XclImpDffConverter& rDffConv ) const
Reference< XDataProvider > XclImpChRoot::GetDataProvider() const
{
- return mxChData->GetChartDoc()->getDataProvider();
+ return mxChData->mxChartDoc->getDataProvider();
+}
+
+Reference< XShape > XclImpChRoot::GetTitleShape( const XclChTextKey& rTitleKey ) const
+{
+ return mxChData->GetTitleShape( rTitleKey );
+}
+
+sal_Int32 XclImpChRoot::CalcHmmFromChartX( sal_Int32 nPosX ) const
+{
+ return static_cast< sal_Int32 >( mxChData->mfUnitSizeX * nPosX + mxChData->mnBorderGapX + 0.5 );
+}
+
+sal_Int32 XclImpChRoot::CalcHmmFromChartY( sal_Int32 nPosY ) const
+{
+ return static_cast< sal_Int32 >( mxChData->mfUnitSizeY * nPosY + mxChData->mnBorderGapY + 0.5 );
+}
+
+::com::sun::star::awt::Rectangle XclImpChRoot::CalcHmmFromChartRect( const XclChRectangle& rRect ) const
+{
+ return ::com::sun::star::awt::Rectangle(
+ CalcHmmFromChartX( rRect.mnX ),
+ CalcHmmFromChartY( rRect.mnY ),
+ CalcHmmFromChartX( rRect.mnWidth ),
+ CalcHmmFromChartY( rRect.mnHeight ) );
+}
+
+double XclImpChRoot::CalcRelativeFromChartX( sal_Int32 nPosX ) const
+{
+ return static_cast< double >( CalcHmmFromChartX( nPosX ) ) / mxChData->maChartRect.GetWidth();
+}
+
+double XclImpChRoot::CalcRelativeFromChartY( sal_Int32 nPosY ) const
+{
+ return static_cast< double >( CalcHmmFromChartY( nPosY ) ) / mxChData->maChartRect.GetHeight();
}
void XclImpChRoot::ConvertLineFormat( ScfPropertySet& rPropSet,
const XclChLineFormat& rLineFmt, XclChPropertyMode ePropMode ) const
{
GetChartPropSetHelper().WriteLineProperties(
- rPropSet, mxChData->GetLineDashTable(), rLineFmt, ePropMode );
+ rPropSet, *mxChData->mxLineDashTable, rLineFmt, ePropMode );
}
void XclImpChRoot::ConvertAreaFormat( ScfPropertySet& rPropSet,
@@ -286,7 +320,7 @@ void XclImpChRoot::ConvertEscherFormat( ScfPropertySet& rPropSet,
XclChPropertyMode ePropMode ) const
{
GetChartPropSetHelper().WriteEscherProperties( rPropSet,
- mxChData->GetGradientTable(), mxChData->GetHatchTable(), mxChData->GetBitmapTable(),
+ *mxChData->mxGradientTable, *mxChData->mxHatchTable, *mxChData->mxBitmapTable,
rEscherFmt, rPicFmt, ePropMode );
}
@@ -357,7 +391,13 @@ void XclImpChGroupBase::SkipBlock( XclImpStream& rStrm )
void XclImpChFramePos::ReadChFramePos( XclImpStream& rStrm )
{
- rStrm >> maData.mnObjType >> maData.mnSizeMode >> maData.maRect;
+ rStrm >> maData.mnTLMode >> maData.mnBRMode;
+ /* According to the spec, the upper 16 bits of all members in the
+ rectangle are unused and may contain garbage. */
+ maData.maRect.mnX = rStrm.ReadInt16(); rStrm.Ignore( 2 );
+ maData.maRect.mnY = rStrm.ReadInt16(); rStrm.Ignore( 2 );
+ maData.maRect.mnWidth = rStrm.ReadInt16(); rStrm.Ignore( 2 );
+ maData.maRect.mnHeight = rStrm.ReadInt16(); rStrm.Ignore( 2 );
}
// ----------------------------------------------------------------------------
@@ -862,9 +902,7 @@ void XclImpChText::ReadHeaderRecord( XclImpStream& rStrm )
// #116397# BIFF8: index into palette used instead of RGB data
maData.maTextColor = GetPalette().GetColor( rStrm.ReaduInt16() );
// placement and rotation
- rStrm >> maData.mnPlacement >> maData.mnRotation;
- // lower 4 bits used for placement, other bits contain garbage
- maData.mnPlacement &= 0x000F;
+ rStrm >> maData.mnFlags2 >> maData.mnRotation;
}
else
{
@@ -878,6 +916,10 @@ void XclImpChText::ReadSubRecord( XclImpStream& rStrm )
{
switch( rStrm.GetRecId() )
{
+ case EXC_ID_CHFRAMEPOS:
+ mxFramePos.reset( new XclImpChFramePos );
+ mxFramePos->ReadChFramePos( rStrm );
+ break;
case EXC_ID_CHFONT:
mxFont.reset( new XclImpChFont );
mxFont->ReadChFont( rStrm );
@@ -1002,8 +1044,7 @@ void XclImpChText::ConvertDataLabel( ScfPropertySet& rPropSet, const XclChTypeIn
bool bShowSymbol = bShowAny && ::get_flag( maData.mnFlags, EXC_CHTEXT_SHOWSYMBOL );
// create API struct for label values, set API label separator
- namespace cssc = ::com::sun::star::chart2;
- cssc::DataPointLabel aPointLabel( bShowValue, bShowPercent, bShowCateg, bShowSymbol );
+ cssc2::DataPointLabel aPointLabel( bShowValue, bShowPercent, bShowCateg, bShowSymbol );
rPropSet.SetProperty( EXC_CHPROP_LABEL, aPointLabel );
String aSep = mxLabelProps.is() ? mxLabelProps->maSeparator : String( sal_Unicode( '\n' ) );
if( aSep.Len() == 0 )
@@ -1016,9 +1057,9 @@ void XclImpChText::ConvertDataLabel( ScfPropertySet& rPropSet, const XclChTypeIn
ConvertFont( rPropSet );
ConvertRotation( rPropSet, false );
// label placement
- using namespace ::com::sun::star::chart::DataLabelPlacement;
+ using namespace cssc::DataLabelPlacement;
sal_Int32 nPlacement = rTypeInfo.mnDefaultLabelPos;
- switch( maData.mnPlacement )
+ switch( ::extract_value< sal_uInt16 >( maData.mnFlags2, 0, 4 ) )
{
case EXC_CHTEXT_POS_DEFAULT: nPlacement = rTypeInfo.mnDefaultLabelPos; break;
case EXC_CHTEXT_POS_OUTSIDE: nPlacement = OUTSIDE; break;
@@ -1064,6 +1105,62 @@ Reference< XTitle > XclImpChText::CreateTitle() const
return xTitle;
}
+void XclImpChText::ConvertTitlePosition( const XclChTextKey& rTitleKey ) const
+{
+ if( !mxFramePos ) return;
+
+ const XclChFramePos& rPosData = mxFramePos->GetFramePosData();
+ OSL_ENSURE( (rPosData.mnTLMode == EXC_CHFRAMEPOS_PARENT) && (rPosData.mnBRMode == EXC_CHFRAMEPOS_PARENT),
+ "XclImpChText::ConvertTitlePosition - unexpected frame position mode" );
+
+ /* Check if title is moved manually. To get the actual position of the
+ title, we do some kind of hack and use the values from the CHTEXT
+ record, effectively ignoring the contents of the CHFRAMEPOS record
+ which contains the position relative to the default title position
+ (according to the spec, the CHFRAMEPOS supersedes the CHTEXT record).
+ Especially when it comes to axis titles, things would become very
+ complicated here, because the relative title position is stored in a
+ measurement unit that is dependent on the size of the inner plot area,
+ the interpretation of the X and Y coordinate is dependent on the
+ direction of the axis, and in 3D charts, and the title default
+ positions are dependent on the 3D view settings (rotation, elevation,
+ and perspective). Thus, it is easier to assume that the creator has
+ written out the correct absolute position and size of the title in the
+ CHTEXT record. This is assured by checking that the shape size stored
+ in the CHTEXT record is non-zero. */
+ if( (rPosData.mnTLMode == EXC_CHFRAMEPOS_PARENT) &&
+ ((rPosData.maRect.mnX != 0) || (rPosData.maRect.mnY != 0)) &&
+ (maData.maRect.mnWidth > 0) && (maData.maRect.mnHeight > 0) ) try
+ {
+ Reference< XShape > xTitleShape( GetTitleShape( rTitleKey ), UNO_SET_THROW );
+ // the call to XShape.getSize() may recalc the chart view
+ ::com::sun::star::awt::Size aTitleSize = xTitleShape->getSize();
+ // rotated titles need special handling...
+ sal_Int32 nScRot = XclTools::GetScRotation( GetRotation(), 0 );
+ double fRad = nScRot * F_PI18000;
+ double fSin = fabs( sin( fRad ) );
+ double fCos = fabs( cos( fRad ) );
+ ::com::sun::star::awt::Size aBoundSize(
+ static_cast< sal_Int32 >( fCos * aTitleSize.Width + fSin * aTitleSize.Height + 0.5 ),
+ static_cast< sal_Int32 >( fSin * aTitleSize.Width + fCos * aTitleSize.Height + 0.5 ) );
+ // calculate the title position from the values in the CHTEXT record
+ ::com::sun::star::awt::Point aTitlePos(
+ CalcHmmFromChartX( maData.maRect.mnX ),
+ CalcHmmFromChartY( maData.maRect.mnY ) );
+ // add part of height to X direction, if title is rotated down (clockwise)
+ if( nScRot > 18000 )
+ aTitlePos.X += static_cast< sal_Int32 >( fSin * aTitleSize.Height + 0.5 );
+ // add part of width to Y direction, if title is rotated up (counterclockwise)
+ else if( nScRot > 0 )
+ aTitlePos.Y += static_cast< sal_Int32 >( fSin * aTitleSize.Width + 0.5 );
+ // set the resulting position at the title shape
+ xTitleShape->setPosition( aTitlePos );
+ }
+ catch( Exception& )
+ {
+ }
+}
+
void XclImpChText::ReadChFrLabelProps( XclImpStream& rStrm )
{
if( GetBiff() == EXC_BIFF8 )
@@ -1087,12 +1184,14 @@ void lclUpdateText( XclImpChTextRef& rxText, XclImpChTextRef xDefText )
rxText = xDefText;
}
-void lclFinalizeTitle( XclImpChTextRef& rxTitle, XclImpChTextRef xDefText )
+void lclFinalizeTitle( XclImpChTextRef& rxTitle, XclImpChTextRef xDefText, const String& rAutoTitle )
{
/* Do not update a title, if it is not visible (if rxTitle is null).
Existing reference indicates enabled title. */
if( rxTitle.is() )
{
+ if( !rxTitle->HasString() )
+ rxTitle->SetString( rAutoTitle );
if( rxTitle->HasString() )
rxTitle->UpdateText( xDefText.get() );
else
@@ -1544,7 +1643,6 @@ Reference< XPropertySet > XclImpChSerErrorBar::CreateErrorBar( const XclImpChSer
aBarProp.SetBoolProperty( EXC_CHPROP_SHOWNEGATIVEERROR, pNegBar != 0 );
// type of displayed error
- namespace cssc = ::com::sun::star::chart;
switch( pPrimaryBar->maData.mnSourceType )
{
case EXC_CHSERERR_PERCENT:
@@ -2281,6 +2379,10 @@ void XclImpChLegend::ReadSubRecord( XclImpStream& rStrm )
{
switch( rStrm.GetRecId() )
{
+ case EXC_ID_CHFRAMEPOS:
+ mxFramePos.reset( new XclImpChFramePos );
+ mxFramePos->ReadChFramePos( rStrm );
+ break;
case EXC_ID_CHTEXT:
mxText.reset( new XclImpChText( GetChRoot() ) );
mxText->ReadRecordGroup( rStrm );
@@ -2307,6 +2409,7 @@ Reference< XLegend > XclImpChLegend::CreateLegend() const
if( xLegend.is() )
{
ScfPropertySet aLegendProp( xLegend );
+ aLegendProp.SetBoolProperty( EXC_CHPROP_SHOW, true );
// frame properties
if( mxFrame.is() )
@@ -2314,8 +2417,69 @@ Reference< XLegend > XclImpChLegend::CreateLegend() const
// text properties
if( mxText.is() )
mxText->ConvertFont( aLegendProp );
- // special legend properties
- GetChartPropSetHelper().WriteLegendProperties( aLegendProp, maData );
+
+ /* Legend position and size. Default positions are used only if the
+ plot area is positioned automatically (Excel sets the plot area to
+ manual mode, if the legend is moved or resized). With manual plot
+ areas, Excel ignores the value in maData.mnDockMode completely. */
+ cssc2::LegendPosition eApiPos = cssc2::LegendPosition_CUSTOM;
+ cssc2::LegendExpansion eApiExpand = cssc2::LegendExpansion_BALANCED;
+ if( !GetChartData().IsManualPlotArea() ) switch( maData.mnDockMode )
+ {
+ case EXC_CHLEGEND_LEFT: eApiPos = cssc2::LegendPosition_LINE_START; eApiExpand = cssc2::LegendExpansion_HIGH; break;
+ case EXC_CHLEGEND_RIGHT: eApiPos = cssc2::LegendPosition_LINE_END; eApiExpand = cssc2::LegendExpansion_HIGH; break;
+ case EXC_CHLEGEND_TOP: eApiPos = cssc2::LegendPosition_PAGE_START; eApiExpand = cssc2::LegendExpansion_WIDE; break;
+ case EXC_CHLEGEND_BOTTOM: eApiPos = cssc2::LegendPosition_PAGE_END; eApiExpand = cssc2::LegendExpansion_WIDE; break;
+ // top-right not supported
+ case EXC_CHLEGEND_CORNER: eApiPos = cssc2::LegendPosition_LINE_END; eApiExpand = cssc2::LegendExpansion_HIGH; break;
+ }
+
+ // no automatic position: try to find the correct position and size
+ if( eApiPos == cssc2::LegendPosition_CUSTOM )
+ {
+ const XclChFramePos* pFramePos = mxFramePos.is() ? &mxFramePos->GetFramePosData() : 0;
+
+ /* Legend position. Only the settings from the CHFRAMEPOS record
+ are used by Excel, the position in the CHLEGEND record will be
+ ignored. */
+ if( pFramePos )
+ {
+ RelativePosition aRelPos;
+ aRelPos.Primary = CalcRelativeFromChartX( pFramePos->maRect.mnX );
+ aRelPos.Secondary = CalcRelativeFromChartY( pFramePos->maRect.mnY );
+ aRelPos.Anchor = ::com::sun::star::drawing::Alignment_TOP_LEFT;
+ aLegendProp.SetProperty( EXC_CHPROP_RELATIVEPOSITION, aRelPos );
+ }
+ else
+ {
+ // no manual position found, just go for the default
+ eApiPos = cssc2::LegendPosition_LINE_END;
+ }
+
+
+ /* Legend size. #i71697# It is not possible to set the legend size
+ directly in the Chart, do some magic here. */
+ if( !pFramePos || (pFramePos->mnBRMode != EXC_CHFRAMEPOS_ABSSIZE_POINTS) ||
+ (pFramePos->maRect.mnWidth == 0) || (pFramePos->maRect.mnHeight == 0) )
+ {
+ // automatic size: determine entry direction from flags
+ eApiExpand = ::get_flagvalue( maData.mnFlags, EXC_CHLEGEND_STACKED,
+ cssc2::LegendExpansion_HIGH, cssc2::LegendExpansion_WIDE );
+ }
+ else
+ {
+ // legend size is given in points, not in chart units
+ double fRatio = static_cast< double >( pFramePos->maRect.mnWidth ) / pFramePos->maRect.mnHeight;
+ if( fRatio > 1.5 )
+ eApiExpand = cssc2::LegendExpansion_WIDE;
+ else if( fRatio < 0.75 )
+ eApiExpand = cssc2::LegendExpansion_HIGH;
+ else
+ eApiExpand = cssc2::LegendExpansion_BALANCED;
+ }
+ }
+ aLegendProp.SetProperty( EXC_CHPROP_ANCHORPOSITION, eApiPos );
+ aLegendProp.SetProperty( EXC_CHPROP_EXPANSION, eApiExpand );
}
return xLegend;
}
@@ -2358,7 +2522,8 @@ XclImpChTypeGroup::XclImpChTypeGroup( const XclImpChRoot& rRoot ) :
void XclImpChTypeGroup::ReadHeaderRecord( XclImpStream& rStrm )
{
- rStrm >> maData.maRect >> maData.mnFlags >> maData.mnGroupIdx;
+ rStrm.Ignore( 16 );
+ rStrm >> maData.mnFlags >> maData.mnGroupIdx;
}
void XclImpChTypeGroup::ReadSubRecord( XclImpStream& rStrm )
@@ -2548,13 +2713,12 @@ void XclImpChTypeGroup::InsertDataSeries( Reference< XChartType > xChartType,
if( xSeriesCont.is() && xSeries.is() )
{
// series stacking mode
- namespace cssc = ::com::sun::star::chart2;
- cssc::StackingDirection eStacking = cssc::StackingDirection_NO_STACKING;
+ cssc2::StackingDirection eStacking = cssc2::StackingDirection_NO_STACKING;
// stacked overrides deep-3d
if( maType.IsStacked() || maType.IsPercent() )
- eStacking = cssc::StackingDirection_Y_STACKING;
+ eStacking = cssc2::StackingDirection_Y_STACKING;
else if( Is3dDeepChart() )
- eStacking = cssc::StackingDirection_Z_STACKING;
+ eStacking = cssc2::StackingDirection_Z_STACKING;
// additional series properties
ScfPropertySet aSeriesProp( xSeries );
@@ -2674,11 +2838,9 @@ void XclImpChLabelRange::Convert( ScfPropertySet& rPropSet, ScaleData& rScaleDat
// do not break text into several lines unless all labels are visible
rPropSet.SetBoolProperty( EXC_CHPROP_TEXTBREAK, maData.mnLabelFreq == 1 );
// do not stagger labels in two lines
- namespace cssc = ::com::sun::star::chart;
rPropSet.SetProperty( EXC_CHPROP_ARRANGEORDER, cssc::ChartAxisArrangeOrderType_SIDE_BY_SIDE );
// reverse order
- namespace cssc2 = ::com::sun::star::chart2;
bool bReverse = ::get_flag( maData.mnFlags, EXC_CHLABELRANGE_REVERSE ) != bMirrorOrient;
rScaleData.Orientation = bReverse ? cssc2::AxisOrientation_REVERSE : cssc2::AxisOrientation_MATHEMATICAL;
@@ -2692,7 +2854,6 @@ void XclImpChLabelRange::ConvertAxisPosition( ScfPropertySet& rPropSet, bool b3d
But: the Y axis has to be moved to "end", if the X axis is mirrored,
to keep it at the left end of the chart. */
bool bMaxCross = ::get_flag( maData.mnFlags, b3dChart ? EXC_CHLABELRANGE_REVERSE : EXC_CHLABELRANGE_MAXCROSS );
- namespace cssc = ::com::sun::star::chart;
cssc::ChartAxisPosition eAxisPos = bMaxCross ? cssc::ChartAxisPosition_END : cssc::ChartAxisPosition_VALUE;
rPropSet.SetProperty( EXC_CHPROP_CROSSOVERPOSITION, eAxisPos );
@@ -2756,7 +2917,6 @@ void XclImpChValueRange::Convert( ScaleData& rScaleData, bool bMirrorOrient ) co
}
// reverse order
- namespace cssc2 = ::com::sun::star::chart2;
bool bReverse = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_REVERSE ) != bMirrorOrient;
rScaleData.Orientation = bReverse ? cssc2::AxisOrientation_REVERSE : cssc2::AxisOrientation_MATHEMATICAL;
}
@@ -2768,7 +2928,6 @@ void XclImpChValueRange::ConvertAxisPosition( ScfPropertySet& rPropSet ) const
bool bLogScale = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_LOGSCALE );
// crossing mode (max-cross flag overrides other crossing settings)
- namespace cssc = ::com::sun::star::chart;
cssc::ChartAxisPosition eAxisPos = bMaxCross ? cssc::ChartAxisPosition_END : cssc::ChartAxisPosition_VALUE;
rPropSet.SetProperty( EXC_CHPROP_CROSSOVERPOSITION, eAxisPos );
@@ -2791,7 +2950,7 @@ sal_Int32 lclGetApiTickmarks( sal_uInt8 nXclTickPos )
return nApiTickmarks;
}
-::com::sun::star::chart::ChartAxisLabelPosition lclGetApiLabelPosition( sal_Int8 nXclLabelPos )
+cssc::ChartAxisLabelPosition lclGetApiLabelPosition( sal_Int8 nXclLabelPos )
{
using namespace ::com::sun::star::chart;
switch( nXclLabelPos )
@@ -2815,9 +2974,9 @@ void XclImpChTick::ReadChTick( XclImpStream& rStrm )
rStrm >> maData.mnMajor
>> maData.mnMinor
>> maData.mnLabelPos
- >> maData.mnBackMode
- >> maData.maRect
- >> maData.maTextColor
+ >> maData.mnBackMode;
+ rStrm.Ignore( 16 );
+ rStrm >> maData.maTextColor
>> maData.mnFlags;
if( GetBiff() == EXC_BIFF8 )
@@ -2850,7 +3009,7 @@ void XclImpChTick::Convert( ScfPropertySet& rPropSet ) const
rPropSet.SetProperty( EXC_CHPROP_MAJORTICKS, lclGetApiTickmarks( maData.mnMajor ) );
rPropSet.SetProperty( EXC_CHPROP_MINORTICKS, lclGetApiTickmarks( maData.mnMinor ) );
rPropSet.SetProperty( EXC_CHPROP_LABELPOSITION, lclGetApiLabelPosition( maData.mnLabelPos ) );
- rPropSet.SetProperty( EXC_CHPROP_MARKPOSITION, ::com::sun::star::chart::ChartAxisMarkPosition_AT_AXIS );
+ rPropSet.SetProperty( EXC_CHPROP_MARKPOSITION, cssc::ChartAxisMarkPosition_AT_AXIS );
}
// ----------------------------------------------------------------------------
@@ -2864,7 +3023,7 @@ XclImpChAxis::XclImpChAxis( const XclImpChRoot& rRoot, sal_uInt16 nAxisType ) :
void XclImpChAxis::ReadHeaderRecord( XclImpStream& rStrm )
{
- rStrm >> maData.mnType >> maData.maRect;
+ rStrm >> maData.mnType;
}
void XclImpChAxis::ReadSubRecord( XclImpStream& rStrm )
@@ -2941,8 +3100,6 @@ sal_uInt16 XclImpChAxis::GetRotation() const
Reference< XAxis > XclImpChAxis::CreateAxis( const XclImpChTypeGroup& rTypeGroup, const XclImpChAxis* pCrossingAxis ) const
{
- namespace cssc2 = ::com::sun::star::chart2;
-
// create the axis object (always)
Reference< XAxis > xAxis( ScfApiHelper::CreateInstance( SERVICE_CHART2_AXIS ), UNO_QUERY );
if( xAxis.is() )
@@ -3136,8 +3293,8 @@ void XclImpChAxesSet::ReadSubRecord( XclImpStream& rStrm )
switch( rStrm.GetRecId() )
{
case EXC_ID_CHFRAMEPOS:
- mxPos.reset( new XclImpChFramePos );
- mxPos->ReadChFramePos( rStrm );
+ mxFramePos.reset( new XclImpChFramePos );
+ mxFramePos->ReadChFramePos( rStrm );
break;
case EXC_ID_CHAXIS:
ReadChAxis( rStrm );
@@ -3188,9 +3345,10 @@ void XclImpChAxesSet::Finalize()
// finalize axis titles
XclImpChTextRef xDefText = GetChartData().GetDefaultText( EXC_CHTEXTTYPE_AXISTITLE );
- lclFinalizeTitle( mxXAxisTitle, xDefText );
- lclFinalizeTitle( mxYAxisTitle, xDefText );
- lclFinalizeTitle( mxZAxisTitle, xDefText );
+ String aAutoTitle = CREATE_STRING( "Axis Title" );
+ lclFinalizeTitle( mxXAxisTitle, xDefText, aAutoTitle );
+ lclFinalizeTitle( mxYAxisTitle, xDefText, aAutoTitle );
+ lclFinalizeTitle( mxZAxisTitle, xDefText, aAutoTitle );
// #i47745# missing plot frame -> invisible border and area
if( !mxPlotFrame )
@@ -3252,6 +3410,16 @@ void XclImpChAxesSet::Convert( Reference< XDiagram > xDiagram ) const
}
}
+void XclImpChAxesSet::ConvertTitlePositions() const
+{
+ if( mxXAxisTitle.is() )
+ mxXAxisTitle->ConvertTitlePosition( XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE, maData.mnAxesSetId, EXC_CHAXIS_X ) );
+ if( mxYAxisTitle.is() )
+ mxYAxisTitle->ConvertTitlePosition( XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE, maData.mnAxesSetId, EXC_CHAXIS_Y ) );
+ if( mxZAxisTitle.is() )
+ mxZAxisTitle->ConvertTitlePosition( XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE, maData.mnAxesSetId, EXC_CHAXIS_Z ) );
+}
+
void XclImpChAxesSet::ReadChAxis( XclImpStream& rStrm )
{
XclImpChAxisRef xAxis( new XclImpChAxis( GetChRoot() ) );
@@ -3358,11 +3526,15 @@ void XclImpChAxesSet::ConvertAxis(
if( xAxis.is() )
{
// create and attach the axis title
- if( xChAxisTitle.is() )
+ if( xChAxisTitle.is() ) try
{
- Reference< XTitled > xTitled( xAxis, UNO_QUERY );
- if( xTitled.is() )
- xTitled->setTitleObject( xChAxisTitle->CreateTitle() );
+ Reference< XTitled > xTitled( xAxis, UNO_QUERY_THROW );
+ Reference< XTitle > xTitle( xChAxisTitle->CreateTitle(), UNO_SET_THROW );
+ xTitled->setTitleObject( xTitle );
+ }
+ catch( Exception& )
+ {
+ DBG_ERRORFILE( "XclImpChAxesSet::ConvertAxis - cannot set axis title" );
}
// insert axis into coordinate system
@@ -3416,7 +3588,7 @@ void XclImpChAxesSet::ConvertBackground( Reference< XDiagram > xDiagram ) const
// The chart object ===========================================================
XclImpChChart::XclImpChChart( const XclImpRoot& rRoot ) :
- XclImpChRoot( rRoot, this )
+ XclImpChRoot( rRoot, *this )
{
mxPrimAxesSet.reset( new XclImpChAxesSet( GetChRoot(), EXC_CHAXESSET_PRIMARY ) );
mxSecnAxesSet.reset( new XclImpChAxesSet( GetChRoot(), EXC_CHAXESSET_SECONDARY ) );
@@ -3516,23 +3688,34 @@ XclImpChTextRef XclImpChChart::GetDefaultText( XclChTextType eTextType ) const
return maDefTexts.get( nDefTextId );
}
-void XclImpChChart::Convert( Reference< XChartDocument > xChartDoc, XclImpDffConverter& rDffConv, const OUString& rObjName ) const
+bool XclImpChChart::IsManualPlotArea() const
+{
+ // there is no real automatic mode in BIFF5 charts
+ return (GetBiff() <= EXC_BIFF5) || ::get_flag( maProps.mnFlags, EXC_CHPROPS_USEMANPLOTAREA );
+}
+
+void XclImpChChart::Convert( Reference< XChartDocument > xChartDoc,
+ XclImpDffConverter& rDffConv, const OUString& rObjName, const Rectangle& rChartRect ) const
{
// initialize conversion (locks the model to suppress any internal updates)
- InitConversion( xChartDoc );
+ InitConversion( xChartDoc, rChartRect );
- // chart frame and title
+ // chart frame formatting
if( mxFrame.is() )
{
ScfPropertySet aFrameProp( xChartDoc->getPageBackground() );
mxFrame->Convert( aFrameProp );
}
- if( mxTitle.is() )
+
+ // chart title
+ if( mxTitle.is() ) try
+ {
+ Reference< XTitled > xTitled( xChartDoc, UNO_QUERY_THROW );
+ Reference< XTitle > xTitle( mxTitle->CreateTitle(), UNO_SET_THROW );
+ xTitled->setTitleObject( xTitle );
+ }
+ catch( Exception& )
{
- Reference< XTitled > xTitled( xChartDoc, UNO_QUERY );
- Reference< XTitle > xTitle = mxTitle->CreateTitle();
- if( xTitled.is() && xTitle.is() )
- xTitled->setTitleObject( xTitle );
}
/* Create the diagram object and attach it to the chart document. Currently,
@@ -3548,13 +3731,48 @@ void XclImpChChart::Convert( Reference< XChartDocument > xChartDoc, XclImpDffCon
if( xDiagram.is() && mxLegend.is() )
xDiagram->setLegend( mxLegend->CreateLegend() );
- // set the IncludeHiddenCells property via the old API as only this ensures that the data provider and al created sequences get this flag correctly
- Reference< com::sun::star::chart::XChartDocument > xStandardApiChartDoc( xChartDoc, UNO_QUERY );
- if( xStandardApiChartDoc.is() )
+ /* Following all conversions needing the old Chart1 API that involves full
+ initialization of the chart view. */
+ Reference< cssc::XChartDocument > xChart1Doc( xChartDoc, UNO_QUERY );
+ if( xChart1Doc.is() )
{
- ScfPropertySet aDiagramProp( xStandardApiChartDoc->getDiagram() );
- bool bShowVisCells = (maProps.mnFlags & EXC_CHPROPS_SHOWVISIBLEONLY);
- aDiagramProp.SetBoolProperty( EXC_CHPROP_INCLUDEHIDDENCELLS, !bShowVisCells );
+ Reference< cssc::XDiagram > xDiagram1 = xChart1Doc->getDiagram();
+
+ /* Set the 'IncludeHiddenCells' property via the old API as only this
+ ensures that the data provider and all created sequences get this
+ flag correctly. */
+ ScfPropertySet aDiaProp( xDiagram1 );
+ bool bShowVisCells = ::get_flag( maProps.mnFlags, EXC_CHPROPS_SHOWVISIBLEONLY );
+ aDiaProp.SetBoolProperty( EXC_CHPROP_INCLUDEHIDDENCELLS, !bShowVisCells );
+
+ // plot area position and size (there is no real automatic mode in BIFF5 charts)
+ XclImpChFramePosRef xPlotAreaPos = mxPrimAxesSet->GetPlotAreaFramePos();
+ if( IsManualPlotArea() && xPlotAreaPos.is() ) try
+ {
+ const XclChFramePos& rFramePos = xPlotAreaPos->GetFramePosData();
+ if( (rFramePos.mnTLMode == EXC_CHFRAMEPOS_PARENT) && (rFramePos.mnBRMode == EXC_CHFRAMEPOS_PARENT) )
+ {
+ Reference< cssc::XDiagramPositioning > xPositioning( xDiagram1, UNO_QUERY_THROW );
+ ::com::sun::star::awt::Rectangle aDiagramRect = CalcHmmFromChartRect( rFramePos.maRect );
+ // for pie charts, always set inner plot area size to exclude the data labels as Excel does
+ const XclImpChTypeGroup* pFirstTypeGroup = mxPrimAxesSet->GetFirstTypeGroup().get();
+ if( pFirstTypeGroup && (pFirstTypeGroup->GetTypeInfo().meTypeCateg == EXC_CHTYPECATEG_PIE) )
+ xPositioning->setDiagramPositionExcludingAxes( aDiagramRect );
+ else if( pFirstTypeGroup && pFirstTypeGroup->Is3dChart() )
+ xPositioning->setDiagramPositionIncludingAxesAndAxisTitles( aDiagramRect );
+ else
+ xPositioning->setDiagramPositionIncludingAxes( aDiagramRect );
+ }
+ }
+ catch( Exception& )
+ {
+ }
+
+ // positions of all title objects
+ if( mxTitle.is() )
+ mxTitle->ConvertTitlePosition( XclChTextKey( EXC_CHTEXTTYPE_TITLE ) );
+ mxPrimAxesSet->ConvertTitlePositions();
+ mxSecnAxesSet->ConvertTitlePositions();
}
// unlock the model
@@ -3689,21 +3907,24 @@ void XclImpChChart::FinalizeDataFormats()
void XclImpChChart::FinalizeTitle()
{
- if( (!mxTitle || (!mxTitle->IsDeleted() && !mxTitle->HasString())) && !mxSecnAxesSet->IsValidAxesSet() )
+ // special handling for auto-generated title
+ String aAutoTitle;
+ if( !mxTitle || (!mxTitle->IsDeleted() && !mxTitle->HasString()) )
{
- /* Chart title is auto-generated from series title, if there is only
- one series with title in the chart. */
- const String& rSerTitle = mxPrimAxesSet->GetSingleSeriesTitle();
- if( rSerTitle.Len() > 0 )
+ // automatic title from first series name (if there are no series on secondary axes set)
+ if( !mxSecnAxesSet->IsValidAxesSet() )
+ aAutoTitle = mxPrimAxesSet->GetSingleSeriesTitle();
+ if( mxTitle.is() || (aAutoTitle.Len() > 0) )
{
if( !mxTitle )
mxTitle.reset( new XclImpChText( GetChRoot() ) );
- mxTitle->SetString( rSerTitle );
+ if( aAutoTitle.Len() == 0 )
+ aAutoTitle = CREATE_STRING( "Chart Title" );
}
}
- // will reset mxTitle, if it does not contain a string
- lclFinalizeTitle( mxTitle, GetDefaultText( EXC_CHTEXTTYPE_TITLE ) );
+ // will reset mxTitle, if it does not contain a string and no auto title exists
+ lclFinalizeTitle( mxTitle, GetDefaultText( EXC_CHTEXTTYPE_TITLE ), aAutoTitle );
}
Reference< XDiagram > XclImpChChart::CreateDiagram() const
@@ -3715,7 +3936,7 @@ Reference< XDiagram > XclImpChChart::CreateDiagram() const
ScfPropertySet aDiaProp( xDiagram );
// treatment of missing values
- using namespace ::com::sun::star::chart::MissingValueTreatment;
+ using namespace cssc::MissingValueTreatment;
sal_Int32 nMissingValues = LEAVE_GAP;
switch( maProps.mnEmptyMode )
{
@@ -3775,10 +3996,10 @@ Rectangle XclImpChartDrawing::CalcAnchorRect( const XclObjAnchor& rAnchor, bool
in the cell address components of the client anchor. In old BIFF3-BIFF5
objects, the position is stored in the offset components of the anchor. */
Rectangle aRect(
- static_cast< long >( static_cast< double >( bDffAnchor ? rAnchor.maFirst.mnCol : rAnchor.mnLX ) / EXC_CHART_UNIT * maChartRect.GetWidth() + 0.5 ),
- static_cast< long >( static_cast< double >( bDffAnchor ? rAnchor.maFirst.mnRow : rAnchor.mnTY ) / EXC_CHART_UNIT * maChartRect.GetHeight() + 0.5 ),
- static_cast< long >( static_cast< double >( bDffAnchor ? rAnchor.maLast.mnCol : rAnchor.mnRX ) / EXC_CHART_UNIT * maChartRect.GetWidth() + 0.5 ),
- static_cast< long >( static_cast< double >( bDffAnchor ? rAnchor.maLast.mnRow : rAnchor.mnBY ) / EXC_CHART_UNIT * maChartRect.GetHeight() + 0.5 ) );
+ static_cast< long >( static_cast< double >( bDffAnchor ? rAnchor.maFirst.mnCol : rAnchor.mnLX ) / EXC_CHART_TOTALUNITS * maChartRect.GetWidth() + 0.5 ),
+ static_cast< long >( static_cast< double >( bDffAnchor ? rAnchor.maFirst.mnRow : rAnchor.mnTY ) / EXC_CHART_TOTALUNITS * maChartRect.GetHeight() + 0.5 ),
+ static_cast< long >( static_cast< double >( bDffAnchor ? rAnchor.maLast.mnCol : rAnchor.mnRX ) / EXC_CHART_TOTALUNITS * maChartRect.GetWidth() + 0.5 ),
+ static_cast< long >( static_cast< double >( bDffAnchor ? rAnchor.maLast.mnRow : rAnchor.mnBY ) / EXC_CHART_TOTALUNITS * maChartRect.GetHeight() + 0.5 ) );
aRect.Justify();
// move shapes into chart area for sheet charts
if( mbOwnTab )
@@ -3892,7 +4113,7 @@ void XclImpChart::Convert( Reference< XModel > xModel, XclImpDffConverter& rDffC
if( xChartDoc.is() )
{
if( mxChartData.is() )
- mxChartData->Convert( xChartDoc, rDffConv, rObjName );
+ mxChartData->Convert( xChartDoc, rDffConv, rObjName, rChartRect );
if( mxChartDrawing.is() )
mxChartDrawing->ConvertObjects( rDffConv, xModel, rChartRect );
}
diff --git a/sc/source/filter/excel/xilink.cxx b/sc/source/filter/excel/xilink.cxx
index 45eed0fd98a9..dc2234570ea6 100644
--- a/sc/source/filter/excel/xilink.cxx
+++ b/sc/source/filter/excel/xilink.cxx
@@ -575,6 +575,7 @@ void XclImpSupbook::LoadCachedValues()
const String& rTabName = pTab->GetTabName();
ScExternalRefCache::TableTypeRef pCacheTable = pRefMgr->getCacheTable(nFileId, rTabName, true);
pTab->LoadCachedValues(pCacheTable);
+ pCacheTable->setWholeTableCached();
}
}
diff --git a/sc/source/filter/excel/xlchart.cxx b/sc/source/filter/excel/xlchart.cxx
index 41e682f85808..10a0657c7899 100644..100755
--- a/sc/source/filter/excel/xlchart.cxx
+++ b/sc/source/filter/excel/xlchart.cxx
@@ -38,11 +38,13 @@
#include <com/sun/star/drawing/LineStyle.hpp>
#include <com/sun/star/drawing/FillStyle.hpp>
#include <com/sun/star/drawing/BitmapMode.hpp>
-#include <com/sun/star/chart2/RelativePosition.hpp>
-#include <com/sun/star/chart2/LegendPosition.hpp>
-#include <com/sun/star/chart2/LegendExpansion.hpp>
-#include <com/sun/star/chart2/Symbol.hpp>
#include <com/sun/star/chart/DataLabelPlacement.hpp>
+#include <com/sun/star/chart/XAxisXSupplier.hpp>
+#include <com/sun/star/chart/XAxisYSupplier.hpp>
+#include <com/sun/star/chart/XAxisZSupplier.hpp>
+#include <com/sun/star/chart/XChartDocument.hpp>
+#include <com/sun/star/chart/XSecondAxisTitleSupplier.hpp>
+#include <com/sun/star/chart2/Symbol.hpp>
#include <rtl/math.hxx>
#include <svl/itemset.hxx>
@@ -55,9 +57,8 @@
#include <filter/msfilter/escherex.hxx>
#include <editeng/memberids.hrc>
#include "global.hxx"
-#include "xlconst.hxx"
+#include "xlroot.hxx"
#include "xlstyle.hxx"
-#include "xltools.hxx"
using ::rtl::OUString;
using ::com::sun::star::uno::Any;
@@ -66,6 +67,9 @@ using ::com::sun::star::uno::UNO_QUERY;
using ::com::sun::star::uno::Exception;
using ::com::sun::star::lang::XMultiServiceFactory;
using ::com::sun::star::chart2::XChartDocument;
+using ::com::sun::star::drawing::XShape;
+
+namespace cssc = ::com::sun::star::chart;
// Common =====================================================================
@@ -104,8 +108,8 @@ XclChFrBlock::XclChFrBlock( sal_uInt16 nType ) :
// Frame formatting ===========================================================
XclChFramePos::XclChFramePos() :
- mnObjType( EXC_CHFRAMEPOS_ANY ),
- mnSizeMode( EXC_CHFRAMEPOS_AUTOSIZE )
+ mnTLMode( EXC_CHFRAMEPOS_PARENT ),
+ mnBRMode( EXC_CHFRAMEPOS_PARENT )
{
}
@@ -189,7 +193,7 @@ XclChText::XclChText() :
mnVAlign( EXC_CHTEXT_ALIGN_CENTER ),
mnBackMode( EXC_CHTEXT_TRANSPARENT ),
mnFlags( EXC_CHTEXT_AUTOCOLOR | EXC_CHTEXT_AUTOFILL ),
- mnPlacement( EXC_CHTEXT_POS_DEFAULT ),
+ mnFlags2( EXC_CHTEXT_POS_DEFAULT ),
mnRotation( EXC_ROT_NONE )
{
}
@@ -512,7 +516,7 @@ const sal_Char SERVICE_CHART2_SCATTER[] = "com.sun.star.chart2.ScatterChartTyp
const sal_Char SERVICE_CHART2_BUBBLE[] = "com.sun.star.chart2.BubbleChartType";
const sal_Char SERVICE_CHART2_SURFACE[] = "com.sun.star.chart2.ColumnChartType"; // Todo
-namespace csscd = ::com::sun::star::chart::DataLabelPlacement;
+namespace csscd = cssc::DataLabelPlacement;
static const XclChTypeInfo spTypeInfos[] =
{
@@ -680,10 +684,6 @@ const sal_Char* const sppcHatchNamesFilled[] = { "FillStyle", "HatchName", "Colo
/** Property names for bitmap area style. */
const sal_Char* const sppcBitmapNames[] = { "FillStyle", "FillBitmapName", "FillBitmapMode", 0 };
-/** Property names for legend properties. */
-const sal_Char* const sppcLegendNames[] =
- { "Show", "AnchorPosition", "Expansion", "RelativePosition", 0 };
-
} // namespace
// ----------------------------------------------------------------------------
@@ -698,8 +698,7 @@ XclChPropSetHelper::XclChPropSetHelper() :
maGradHlpFilled( sppcGradNamesFilled ),
maHatchHlpCommon( sppcHatchNamesCommon ),
maHatchHlpFilled( sppcHatchNamesFilled ),
- maBitmapHlp( sppcBitmapNames ),
- maLegendHlp( sppcLegendNames )
+ maBitmapHlp( sppcBitmapNames )
{
}
@@ -957,46 +956,6 @@ sal_uInt16 XclChPropSetHelper::ReadRotationProperties( const ScfPropertySet& rPr
XclTools::GetXclRotation( static_cast< sal_Int32 >( fAngle * 100.0 + 0.5 ) );
}
-void XclChPropSetHelper::ReadLegendProperties( XclChLegend& rLegend, const ScfPropertySet& rPropSet )
-{
- namespace cssc = ::com::sun::star::chart2;
- namespace cssd = ::com::sun::star::drawing;
-
- // read the properties
- bool bShow;
- cssc::LegendPosition eApiPos;
- cssc::LegendExpansion eApiExpand;
- Any aRelPosAny;
- maLegendHlp.ReadFromPropertySet( rPropSet );
- maLegendHlp >> bShow >> eApiPos >> eApiExpand >> aRelPosAny;
- DBG_ASSERT( bShow, "XclChPropSetHelper::ReadLegendProperties - legend must be visible" );
-
- // legend position
- switch( eApiPos )
- {
- case cssc::LegendPosition_LINE_START: rLegend.mnDockMode = EXC_CHLEGEND_LEFT; break;
- case cssc::LegendPosition_LINE_END: rLegend.mnDockMode = EXC_CHLEGEND_RIGHT; break;
- case cssc::LegendPosition_PAGE_START: rLegend.mnDockMode = EXC_CHLEGEND_TOP; break;
- case cssc::LegendPosition_PAGE_END: rLegend.mnDockMode = EXC_CHLEGEND_BOTTOM; break;
- default: rLegend.mnDockMode = EXC_CHLEGEND_NOTDOCKED;
- }
- // legend expansion
- ::set_flag( rLegend.mnFlags, EXC_CHLEGEND_STACKED, eApiExpand != cssc::LegendExpansion_WIDE );
- // legend position
- if( rLegend.mnDockMode == EXC_CHLEGEND_NOTDOCKED )
- {
- cssc::RelativePosition aRelPos;
- if( aRelPosAny >>= aRelPos )
- {
- rLegend.maRect.mnX = limit_cast< sal_Int32 >( aRelPos.Primary * EXC_CHART_UNIT, 0, EXC_CHART_UNIT );
- rLegend.maRect.mnY = limit_cast< sal_Int32 >( aRelPos.Secondary * EXC_CHART_UNIT, 0, EXC_CHART_UNIT );
- }
- else
- rLegend.mnDockMode = EXC_CHLEGEND_LEFT;
- }
- ::set_flag( rLegend.mnFlags, EXC_CHLEGEND_DOCKED, rLegend.mnDockMode != EXC_CHLEGEND_NOTDOCKED );
-}
-
// write properties -----------------------------------------------------------
void XclChPropSetHelper::WriteLineProperties(
@@ -1207,51 +1166,6 @@ void XclChPropSetHelper::WriteRotationProperties(
}
}
-void XclChPropSetHelper::WriteLegendProperties(
- ScfPropertySet& rPropSet, const XclChLegend& rLegend )
-{
- namespace cssc = ::com::sun::star::chart2;
- namespace cssd = ::com::sun::star::drawing;
-
- // legend position
- cssc::LegendPosition eApiPos = cssc::LegendPosition_CUSTOM;
- switch( rLegend.mnDockMode )
- {
- case EXC_CHLEGEND_LEFT: eApiPos = cssc::LegendPosition_LINE_START; break;
- case EXC_CHLEGEND_RIGHT: eApiPos = cssc::LegendPosition_LINE_END; break;
- case EXC_CHLEGEND_TOP: eApiPos = cssc::LegendPosition_PAGE_START; break;
- case EXC_CHLEGEND_BOTTOM: eApiPos = cssc::LegendPosition_PAGE_END; break;
- }
- // legend expansion
- cssc::LegendExpansion eApiExpand = ::get_flagvalue(
- rLegend.mnFlags, EXC_CHLEGEND_STACKED, cssc::LegendExpansion_HIGH, cssc::LegendExpansion_WIDE );
- // legend position
- Any aRelPosAny;
- if( eApiPos == cssc::LegendPosition_CUSTOM )
- {
- // #i71697# it is not possible to set the size directly, do some magic here
- double fRatio = ((rLegend.maRect.mnWidth > 0) && (rLegend.maRect.mnHeight > 0)) ?
- (static_cast< double >( rLegend.maRect.mnWidth ) / rLegend.maRect.mnHeight) : 1.0;
- if( fRatio > 1.5 )
- eApiExpand = cssc::LegendExpansion_WIDE;
- else if( fRatio < 0.75 )
- eApiExpand = cssc::LegendExpansion_HIGH;
- else
- eApiExpand = cssc::LegendExpansion_BALANCED;
- // set position
- cssc::RelativePosition aRelPos;
- aRelPos.Primary = static_cast< double >( rLegend.maRect.mnX ) / EXC_CHART_UNIT;
- aRelPos.Secondary = static_cast< double >( rLegend.maRect.mnY ) / EXC_CHART_UNIT;
- aRelPos.Anchor = cssd::Alignment_TOP_LEFT;
- aRelPosAny <<= aRelPos;
- }
-
- // write the properties
- maLegendHlp.InitializeWrite();
- maLegendHlp << true << eApiPos << eApiExpand << aRelPosAny;
- maLegendHlp.WriteToPropertySet( rPropSet );
-}
-
// private --------------------------------------------------------------------
ScfPropSetHelper& XclChPropSetHelper::GetLineHelper( XclChPropertyMode ePropMode )
@@ -1301,27 +1215,81 @@ ScfPropSetHelper& XclChPropSetHelper::GetHatchHelper( XclChPropertyMode ePropMod
// ============================================================================
+namespace {
+
+/* The following local functions implement getting the XShape interface of all
+ supported title objects (chart and axes). This needs some effort due to the
+ design of the old Chart1 API used to access these objects. */
+
+/** A code fragment that returns a shape object from the passed shape supplier
+ using the specified interface function. Checks a boolean property first. */
+#define EXC_FRAGMENT_GETTITLESHAPE( shape_supplier, supplier_func, property_name ) \
+ ScfPropertySet aPropSet( shape_supplier ); \
+ if( shape_supplier.is() && aPropSet.GetBoolProperty( CREATE_OUSTRING( #property_name ) ) ) \
+ return shape_supplier->supplier_func(); \
+ return Reference< XShape >(); \
+
+/** Implements a function returning the drawing shape of an axis title, if
+ existing, using the specified API interface and its function. */
+#define EXC_DEFINEFUNC_GETAXISTITLESHAPE( func_name, interface_type, supplier_func, property_name ) \
+Reference< XShape > func_name( const Reference< cssc::XChartDocument >& rxChart1Doc ) \
+{ \
+ Reference< cssc::interface_type > xAxisSupp( rxChart1Doc->getDiagram(), UNO_QUERY ); \
+ EXC_FRAGMENT_GETTITLESHAPE( xAxisSupp, supplier_func, property_name ) \
+}
+
+/** Returns the drawing shape of the main title, if existing. */
+Reference< XShape > lclGetMainTitleShape( const Reference< cssc::XChartDocument >& rxChart1Doc )
+{
+ EXC_FRAGMENT_GETTITLESHAPE( rxChart1Doc, getTitle, HasMainTitle )
+}
+
+EXC_DEFINEFUNC_GETAXISTITLESHAPE( lclGetXAxisTitleShape, XAxisXSupplier, getXAxisTitle, HasXAxisTitle )
+EXC_DEFINEFUNC_GETAXISTITLESHAPE( lclGetYAxisTitleShape, XAxisYSupplier, getYAxisTitle, HasYAxisTitle )
+EXC_DEFINEFUNC_GETAXISTITLESHAPE( lclGetZAxisTitleShape, XAxisZSupplier, getZAxisTitle, HasZAxisTitle )
+EXC_DEFINEFUNC_GETAXISTITLESHAPE( lclGetSecXAxisTitleShape, XSecondAxisTitleSupplier, getSecondXAxisTitle, HasSecondaryXAxisTitle )
+EXC_DEFINEFUNC_GETAXISTITLESHAPE( lclGetSecYAxisTitleShape, XSecondAxisTitleSupplier, getSecondYAxisTitle, HasSecondaryYAxisTitle )
+
+#undef EXC_DEFINEFUNC_GETAXISTITLESHAPE
+#undef EXC_IMPLEMENT_GETTITLESHAPE
+
+} // namespace
+
+// ----------------------------------------------------------------------------
+
XclChRootData::XclChRootData() :
mxTypeInfoProv( new XclChTypeInfoProvider ),
- mxFmtInfoProv( new XclChFormatInfoProvider )
+ mxFmtInfoProv( new XclChFormatInfoProvider ),
+ mnBorderGapX( 0 ),
+ mnBorderGapY( 0 )
{
+ // remember some title shape getter functions
+ maGetShapeFuncs[ XclChTextKey( EXC_CHTEXTTYPE_TITLE ) ] = lclGetMainTitleShape;
+ maGetShapeFuncs[ XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE, EXC_CHAXESSET_PRIMARY, EXC_CHAXIS_X ) ] = lclGetXAxisTitleShape;
+ maGetShapeFuncs[ XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE, EXC_CHAXESSET_PRIMARY, EXC_CHAXIS_Y ) ] = lclGetYAxisTitleShape;
+ maGetShapeFuncs[ XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE, EXC_CHAXESSET_PRIMARY, EXC_CHAXIS_Z ) ] = lclGetZAxisTitleShape;
+ maGetShapeFuncs[ XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE, EXC_CHAXESSET_SECONDARY, EXC_CHAXIS_X ) ] = lclGetSecXAxisTitleShape;
+ maGetShapeFuncs[ XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE, EXC_CHAXESSET_SECONDARY, EXC_CHAXIS_Y ) ] = lclGetSecYAxisTitleShape;
}
XclChRootData::~XclChRootData()
{
}
-Reference< XChartDocument > XclChRootData::GetChartDoc() const
+void XclChRootData::InitConversion( const XclRoot& rRoot, const Reference< XChartDocument >& rxChartDoc, const Rectangle& rChartRect )
{
- DBG_ASSERT( mxChartDoc.is(), "XclChRootData::GetChartDoc - missing chart document" );
- return mxChartDoc;
-}
+ // remember chart document reference and chart shape position/size
+ DBG_ASSERT( rxChartDoc.is(), "XclChRootData::InitConversion - missing chart document" );
+ mxChartDoc = rxChartDoc;
+ maChartRect = rChartRect;
-void XclChRootData::InitConversion( XChartDocRef xChartDoc )
-{
- // remember chart document reference
- DBG_ASSERT( xChartDoc.is(), "XclChRootData::InitConversion - missing chart document" );
- mxChartDoc = xChartDoc;
+ // Excel excludes a border of 5 pixels in each direction from chart area
+ mnBorderGapX = rRoot.GetHmmFromPixelX( 5.0 );
+ mnBorderGapY = rRoot.GetHmmFromPixelY( 5.0 );
+
+ // size of a chart unit in 1/100 mm
+ mfUnitSizeX = ::std::max< double >( maChartRect.GetWidth() - 2 * mnBorderGapX, mnBorderGapX ) / EXC_CHART_TOTALUNITS;
+ mfUnitSizeY = ::std::max< double >( maChartRect.GetHeight() - 2 * mnBorderGapY, mnBorderGapY ) / EXC_CHART_TOTALUNITS;
// create object tables
Reference< XMultiServiceFactory > xFactory( mxChartDoc, UNO_QUERY );
@@ -1346,5 +1314,15 @@ void XclChRootData::FinishConversion()
mxChartDoc.clear();
}
-// ============================================================================
+Reference< XShape > XclChRootData::GetTitleShape( const XclChTextKey& rTitleKey ) const
+{
+ XclChGetShapeFuncMap::const_iterator aIt = maGetShapeFuncs.find( rTitleKey );
+ OSL_ENSURE( aIt != maGetShapeFuncs.end(), "XclChRootData::GetTitleShape - invalid title key" );
+ Reference< cssc::XChartDocument > xChart1Doc( mxChartDoc, UNO_QUERY );
+ Reference< XShape > xTitleShape;
+ if( xChart1Doc.is() && (aIt != maGetShapeFuncs.end()) )
+ xTitleShape = (aIt->second)( xChart1Doc );
+ return xTitleShape;
+}
+// ============================================================================
diff --git a/sc/source/filter/excel/xlroot.cxx b/sc/source/filter/excel/xlroot.cxx
index 8a22b05828b9..2b2180db5e6a 100644
--- a/sc/source/filter/excel/xlroot.cxx
+++ b/sc/source/filter/excel/xlroot.cxx
@@ -28,7 +28,11 @@
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"
#include "xlroot.hxx"
+#include <com/sun/star/awt/XDevice.hpp>
+#include <com/sun/star/frame/XFrame.hpp>
+#include <com/sun/star/frame/XFramesSupplier.hpp>
#include <com/sun/star/i18n/ScriptType.hpp>
+#include <comphelper/processfactory.hxx>
#include <vcl/svapp.hxx>
#include <svl/stritem.hxx>
#include <svl/languageoptions.hxx>
@@ -57,6 +61,15 @@
namespace ApiScriptType = ::com::sun::star::i18n::ScriptType;
using ::rtl::OUString;
+using ::com::sun::star::uno::Exception;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::UNO_QUERY_THROW;
+using ::com::sun::star::uno::UNO_SET_THROW;
+using ::com::sun::star::awt::XDevice;
+using ::com::sun::star::awt::DeviceInfo;
+using ::com::sun::star::frame::XFrame;
+using ::com::sun::star::frame::XFramesSupplier;
+using ::com::sun::star::lang::XMultiServiceFactory;
// Global data ================================================================
@@ -88,6 +101,8 @@ XclRootData::XclRootData( XclBiff eBiff, SfxMedium& rMedium,
mxFontPropSetHlp( new XclFontPropSetHelper ),
mxChPropSetHlp( new XclChPropSetHelper ),
mxRD( new RootData ),//!
+ mfScreenPixelX( 50.0 ),
+ mfScreenPixelY( 50.0 ),
mnCharWidth( 110 ),
mnScTab( 0 ),
mbExport( bExport )
@@ -129,6 +144,22 @@ XclRootData::XclRootData( XclBiff eBiff, SfxMedium& rMedium,
mxExtDocOpt.reset( new ScExtDocOptions( *pOldDocOpt ) );
else
mxExtDocOpt.reset( new ScExtDocOptions );
+
+ // screen pixel size
+ try
+ {
+ Reference< XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory(), UNO_SET_THROW );
+ Reference< XFramesSupplier > xFramesSupp( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.frame.Desktop" ) ), UNO_QUERY_THROW );
+ Reference< XFrame > xFrame( xFramesSupp->getActiveFrame(), UNO_SET_THROW );
+ Reference< XDevice > xDevice( xFrame->getContainerWindow(), UNO_QUERY_THROW );
+ DeviceInfo aDeviceInfo = xDevice->getInfo();
+ mfScreenPixelX = (aDeviceInfo.PixelPerMeterX > 0) ? (100000.0 / aDeviceInfo.PixelPerMeterX) : 50.0;
+ mfScreenPixelY = (aDeviceInfo.PixelPerMeterY > 0) ? (100000.0 / aDeviceInfo.PixelPerMeterY) : 50.0;
+ }
+ catch( Exception& )
+ {
+ OSL_ENSURE( false, "XclRootData::XclRootData - cannot get output device info" );
+ }
}
XclRootData::~XclRootData()
@@ -199,6 +230,16 @@ void XclRoot::SetCharWidth( const XclFontData& rFontData )
}
}
+sal_Int32 XclRoot::GetHmmFromPixelX( double fPixelX ) const
+{
+ return static_cast< sal_Int32 >( fPixelX * mrData.mfScreenPixelX + 0.5 );
+}
+
+sal_Int32 XclRoot::GetHmmFromPixelY( double fPixelY ) const
+{
+ return static_cast< sal_Int32 >( fPixelY * mrData.mfScreenPixelY + 0.5 );
+}
+
String XclRoot::RequestPassword( ::comphelper::IDocPasswordVerifier& rVerifier ) const
{
::std::vector< OUString > aDefaultPasswords;
diff --git a/sc/source/filter/inc/xechart.hxx b/sc/source/filter/inc/xechart.hxx
index 2cf976b11efe..5bb75e029210 100644
--- a/sc/source/filter/inc/xechart.hxx
+++ b/sc/source/filter/inc/xechart.hxx
@@ -39,6 +39,10 @@
class Size;
namespace com { namespace sun { namespace star {
+ namespace awt
+ {
+ struct Rectangle;
+ }
namespace frame
{
class XModel;
@@ -65,7 +69,7 @@ namespace com { namespace sun { namespace star {
// Common =====================================================================
-class XclExpChRootData;
+struct XclExpChRootData;
class XclExpChChart;
/** Base class for complex chart classes, provides access to other components
@@ -80,11 +84,13 @@ public:
typedef ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartDocument > XChartDocRef;
public:
- explicit XclExpChRoot( const XclExpRoot& rRoot, XclExpChChart* pChartData );
+ explicit XclExpChRoot( const XclExpRoot& rRoot, XclExpChChart& rChartData );
virtual ~XclExpChRoot();
/** Returns this root instance - for code readability in derived classes. */
inline const XclExpChRoot& GetChRoot() const { return *this; }
+ /** Returns the API Chart document model. */
+ XChartDocRef GetChartDocument() const;
/** Returns a reference to the parent chart data object. */
XclExpChChart& GetChartData() const;
/** Returns chart type info for a unique chart type identifier. */
@@ -96,7 +102,7 @@ public:
const XclChFormatInfo& GetFormatInfo( XclChObjectType eObjType ) const;
/** Starts the API chart document conversion. Must be called once before all API conversion. */
- void InitConversion( XChartDocRef xChartDoc ) const;
+ void InitConversion( XChartDocRef xChartDoc, const Rectangle& rChartRect ) const;
/** Finishes the API chart document conversion. Must be called once after all API conversion. */
void FinishConversion() const;
@@ -105,6 +111,18 @@ public:
/** Sets a system color and the respective color identifier. */
void SetSystemColor( Color& rColor, sal_uInt32& rnColorId, sal_uInt16 nSysColorIdx ) const;
+ /** Converts the passed horizontal coordinate from 1/100 mm to Excel chart units. */
+ sal_Int32 CalcChartXFromHmm( sal_Int32 nPosX ) const;
+ /** Converts the passed vertical coordinate from 1/100 mm to Excel chart units. */
+ sal_Int32 CalcChartYFromHmm( sal_Int32 nPosY ) const;
+ /** Converts the passed rectangle from 1/100 mm to Excel chart units. */
+ XclChRectangle CalcChartRectFromHmm( const ::com::sun::star::awt::Rectangle& rRect ) const;
+
+ /** Converts the passed horizontal coordinate from a relative position to Excel chart units. */
+ sal_Int32 CalcChartXFromRelative( double fPosX ) const;
+ /** Converts the passed vertical coordinate from a relative position to Excel chart units. */
+ sal_Int32 CalcChartYFromRelative( double fPosY ) const;
+
/** Reads all line properties from the passed property set. */
void ConvertLineFormat(
XclChLineFormat& rLineFmt,
@@ -191,6 +209,25 @@ public:
// Frame formatting ===========================================================
+class XclExpChFramePos : public XclExpRecord
+{
+public:
+ explicit XclExpChFramePos( sal_uInt16 nTLMode, sal_uInt16 nBRMode );
+
+ /** Returns read/write access to the frame position data. */
+ inline XclChFramePos& GetFramePosData() { return maData; }
+
+private:
+ virtual void WriteBody( XclExpStream& rStrm );
+
+private:
+ XclChFramePos maData; /// Position of the frame.
+};
+
+typedef ScfRef< XclExpChFramePos > XclExpChFramePosRef;
+
+// ----------------------------------------------------------------------------
+
class XclExpChLineFormat : public XclExpRecord
{
public:
@@ -514,6 +551,7 @@ private:
private:
XclChText maData; /// Contents of the CHTEXT record.
+ XclExpChFramePosRef mxFramePos; /// Relative text frame position (CHFRAMEPOS record).
XclExpChSourceLinkRef mxSrcLink; /// Linked data (CHSOURCELINK with CHSTRING record).
XclExpChFrameRef mxFrame; /// Text object frame properties (CHFRAME group).
XclExpChFontRef mxFont; /// Index into font buffer (CHFONT record).
@@ -830,8 +868,8 @@ typedef ScfRef< XclExpChChart3d > XclExpChChart3dRef;
/** Represents the CHLEGEND record group describing the chart legend.
- The CHLEGEND group consists of: CHLEGEND, CHBEGIN, CHFRAME group,
- CHTEXT group, CHEND.
+ The CHLEGEND group consists of: CHLEGEND, CHBEGIN, CHFRAMEPOS, CHFRAME
+ group, CHTEXT group, CHEND.
*/
class XclExpChLegend : public XclExpChGroupBase
{
@@ -849,6 +887,7 @@ private:
private:
XclChLegend maData; /// Contents of the CHLEGEND record.
+ XclExpChFramePosRef mxFramePos; /// Legend frame position (CHFRAMEPOS record).
XclExpChTextRef mxText; /// Legend text format (CHTEXT group).
XclExpChFrameRef mxFrame; /// Legend frame format (CHFRAME group).
};
@@ -1137,6 +1176,7 @@ private:
typedef XclExpRecordList< XclExpChTypeGroup > XclExpChTypeGroupList;
XclChAxesSet maData; /// Contents of the CHAXESSET record.
+ XclExpChFramePosRef mxFramePos; /// Outer plot area position (CHFRAMEPOS record).
XclExpChAxisRef mxXAxis; /// The X axis (CHAXIS group).
XclExpChAxisRef mxYAxis; /// The Y axis (CHAXIS group).
XclExpChAxisRef mxZAxis; /// The Z axis (CHAXIS group).
@@ -1164,7 +1204,7 @@ public:
public:
explicit XclExpChChart( const XclExpRoot& rRoot,
- XChartDocRef xChartDoc, const Size& rSize );
+ XChartDocRef xChartDoc, const Rectangle& rChartRect );
/** Creates, registers and returns a new data series object. */
XclExpChSeriesRef CreateSeries();
@@ -1172,6 +1212,8 @@ public:
void RemoveLastSeries();
/** Stores a CHTEXT group that describes a data point label. */
void SetDataLabel( XclExpChTextRef xText );
+ /** Sets the plot area position and size to manual mode. */
+ void SetManualPlotArea();
/** Writes all embedded records. */
virtual void WriteSubRecords( XclExpStream& rStrm );
@@ -1224,7 +1266,7 @@ public:
public:
explicit XclExpChart( const XclExpRoot& rRoot,
- XModelRef xModel, const Size& rSize );
+ XModelRef xModel, const Rectangle& rChartRect );
};
// ============================================================================
diff --git a/sc/source/filter/inc/xichart.hxx b/sc/source/filter/inc/xichart.hxx
index 5d03c99b124a..d8289b3b671b 100644
--- a/sc/source/filter/inc/xichart.hxx
+++ b/sc/source/filter/inc/xichart.hxx
@@ -43,10 +43,18 @@
#include "xistring.hxx"
namespace com { namespace sun { namespace star {
+ namespace awt
+ {
+ struct Rectangle;
+ }
namespace frame
{
class XModel;
}
+ namespace drawing
+ {
+ class XShape;
+ }
namespace chart2
{
struct ScaleData;
@@ -75,7 +83,7 @@ struct XclObjFillData;
// Common =====================================================================
class ScfProgressBar;
-class XclImpChRootData;
+struct XclImpChRootData;
class XclImpChChart;
class ScTokenArray;
@@ -83,11 +91,10 @@ class ScTokenArray;
class XclImpChRoot : public XclImpRoot
{
public:
- typedef ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartDocument > XChartDocRef;
- typedef ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataProvider > XDataProviderRef;
+ typedef ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartDocument > XChartDocRef;
public:
- explicit XclImpChRoot( const XclImpRoot& rRoot, XclImpChChart* pChartData );
+ explicit XclImpChRoot( const XclImpRoot& rRoot, XclImpChChart& rChartData );
virtual ~XclImpChRoot();
/** Returns this root instance - for code readability in derived classes. */
@@ -109,12 +116,28 @@ public:
Color GetSeriesFillAutoColor( sal_uInt16 nFormatIdx ) const;
/** Starts the API chart document conversion. Must be called once before all API conversion. */
- void InitConversion( XChartDocRef xChartDoc ) const;
+ void InitConversion( XChartDocRef xChartDoc, const Rectangle& rChartRect ) const;
/** Finishes the API chart document conversion. Must be called once after all API conversion. */
void FinishConversion( XclImpDffConverter& rDffConv ) const;
/** Returns the data provider for the chart document. */
- XDataProviderRef GetDataProvider() const;
+ ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataProvider >
+ GetDataProvider() const;
+ /** Returns the drawing shape interface of the specified title object. */
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >
+ GetTitleShape( const XclChTextKey& rTitleKey ) const;
+
+ /** Converts the passed horizontal coordinate from Excel chart units into 1/100 mm. */
+ sal_Int32 CalcHmmFromChartX( sal_Int32 nPosX ) const;
+ /** Converts the passed vertical coordinate from Excel chart units into 1/100 mm. */
+ sal_Int32 CalcHmmFromChartY( sal_Int32 nPosY ) const;
+ /** Converts the passed rectangle from Excel chart units into 1/100 mm. */
+ ::com::sun::star::awt::Rectangle CalcHmmFromChartRect( const XclChRectangle& rRect ) const;
+
+ /** Converts the passed horizontal coordinate from Excel chart units into a relative position. */
+ double CalcRelativeFromChartX( sal_Int32 nPosX ) const;
+ /** Converts the passed vertical coordinate from Excel chart units into a relative position. */
+ double CalcRelativeFromChartY( sal_Int32 nPosY ) const;
/** Writes all line properties to the passed property set. */
void ConvertLineFormat(
@@ -184,6 +207,9 @@ public:
/** Reads the CHFRAMEPOS record (frame position and size). */
void ReadChFramePos( XclImpStream& rStrm );
+ /** Returns read-only access to the imported frame position data. */
+ inline const XclChFramePos& GetFramePosData() const { return maData; }
+
private:
XclChFramePos maData; /// Position of the frame.
};
@@ -506,6 +532,8 @@ public:
void ConvertDataLabel( ScfPropertySet& rPropSet, const XclChTypeInfo& rTypeInfo ) const;
/** Creates a title text object. */
XTitleRef CreateTitle() const;
+ /** Converts the manual position of the specified title */
+ void ConvertTitlePosition( const XclChTextKey& rTitleKey ) const;
private:
using XclImpChRoot::ConvertFont;
@@ -519,6 +547,7 @@ private:
XclChText maData; /// Contents of the CHTEXT record.
XclChObjectLink maObjLink; /// Link target for this text object.
XclFormatRunVec maFormats; /// Formatting runs (CHFORMATRUNS record).
+ XclImpChFramePosRef mxFramePos; /// Relative text frame position (CHFRAMEPOS record).
XclImpChSourceLinkRef mxSrcLink; /// Linked data (CHSOURCELINK with CHSTRING record).
XclImpChFrameRef mxFrame; /// Text object frame properties (CHFRAME group).
XclImpChFontRef mxFont; /// Index into font buffer (CHFONT record).
@@ -922,8 +951,8 @@ typedef ScfRef< XclImpChChart3d > XclImpChChart3dRef;
/** Represents the CHLEGEND record group describing the chart legend.
- The CHLEGEND group consists of: CHLEGEND, CHBEGIN, CHFRAME group,
- CHTEXT group, CHEND.
+ The CHLEGEND group consists of: CHLEGEND, CHBEGIN, CHFRAMEPOS, CHFRAME
+ group, CHTEXT group, CHEND.
*/
class XclImpChLegend : public XclImpChGroupBase, protected XclImpChRoot
{
@@ -945,6 +974,7 @@ public:
private:
XclChLegend maData; /// Contents of the CHLEGEND record.
+ XclImpChFramePosRef mxFramePos; /// Legend frame position (CHFRAMEPOS record).
XclImpChTextRef mxText; /// Legend text format (CHTEXT group).
XclImpChFrameRef mxFrame; /// Legend frame format (CHFRAME group).
};
@@ -1265,6 +1295,8 @@ public:
/** Returns the axes set index used by the chart API. */
inline sal_Int32 GetApiAxesSetIndex() const { return maData.GetApiAxesSetIndex(); }
+ /** Returns the outer plot area position, if existing. */
+ inline XclImpChFramePosRef GetPlotAreaFramePos() const { return mxFramePos; }
/** Returns the specified chart type group. */
inline XclImpChTypeGroupRef GetTypeGroup( sal_uInt16 nGroupIdx ) const { return maTypeGroups.get( nGroupIdx ); }
/** Returns the first chart type group. */
@@ -1276,6 +1308,8 @@ public:
/** Creates a coordinate system and converts all series and axis settings. */
void Convert( XDiagramRef xDiagram ) const;
+ /** Converts the manual positions of all axis titles. */
+ void ConvertTitlePositions() const;
private:
/** Reads a CHAXIS record group containing a single axis. */
@@ -1304,7 +1338,7 @@ private:
typedef ScfRefMap< sal_uInt16, XclImpChTypeGroup > XclImpChTypeGroupMap;
XclChAxesSet maData; /// Contents of the CHAXESSET record.
- XclImpChFramePosRef mxPos; /// Position of the axes set (CHFRAMEPOS record).
+ XclImpChFramePosRef mxFramePos; /// Outer plot area position (CHFRAMEPOS record).
XclImpChAxisRef mxXAxis; /// The X axis (CHAXIS group).
XclImpChAxisRef mxYAxis; /// The Y axis (CHAXIS group).
XclImpChAxisRef mxZAxis; /// The Z axis (CHAXIS group).
@@ -1351,13 +1385,16 @@ public:
XclImpChTypeGroupRef GetTypeGroup( sal_uInt16 nGroupIdx ) const;
/** Returns the specified default text. */
XclImpChTextRef GetDefaultText( XclChTextType eTextType ) const;
+ /** Returns true, if the plot area has benn moved and/or resized manually. */
+ bool IsManualPlotArea() const;
/** Returns the number of units on the progress bar needed for the chart. */
inline sal_Size GetProgressSize() const { return 2 * EXC_CHART_PROGRESS_SIZE; }
/** Converts and writes all properties to the passed chart. */
void Convert( XChartDocRef xChartDoc,
XclImpDffConverter& rDffConv,
- const ::rtl::OUString& rObjName ) const;
+ const ::rtl::OUString& rObjName,
+ const Rectangle& rChartRect ) const;
private:
/** Reads a CHSERIES group (data series source and formatting). */
diff --git a/sc/source/filter/inc/xlchart.hxx b/sc/source/filter/inc/xlchart.hxx
index f6711211bc13..13eda8619cc0 100644..100755
--- a/sc/source/filter/inc/xlchart.hxx
+++ b/sc/source/filter/inc/xlchart.hxx
@@ -34,14 +34,19 @@
#define EXC_CHART2_3DBAR_HAIRLINES_ONLY 1
#include <map>
+#include <tools/gen.hxx>
#include "fapihelper.hxx"
namespace com { namespace sun { namespace star {
namespace container { class XNameContainer; }
namespace lang { class XMultiServiceFactory; }
+ namespace chart { class XChartDocument; }
namespace chart2 { class XChartDocument; }
+ namespace drawing { class XShape; }
} } }
+class XclRoot;
+
// Property names =============================================================
// service names
@@ -72,6 +77,7 @@ namespace com { namespace sun { namespace star {
// property names
#define EXC_CHPROP_ADDITIONALSHAPES CREATE_OUSTRING( "AdditionalShapes" )
+#define EXC_CHPROP_ANCHORPOSITION CREATE_OUSTRING( "AnchorPosition" )
#define EXC_CHPROP_ARRANGEORDER CREATE_OUSTRING( "ArrangeOrder" )
#define EXC_CHPROP_ATTAXISINDEX CREATE_OUSTRING( "AttachedAxisIndex" )
#define EXC_CHPROP_ATTRIBDATAPOINTS CREATE_OUSTRING( "AttributedDataPoints" )
@@ -94,10 +100,12 @@ namespace com { namespace sun { namespace star {
#define EXC_CHPROP_ERRORBARSTYLE CREATE_OUSTRING( "ErrorBarStyle" )
#define EXC_CHPROP_ERRORBARX CREATE_OUSTRING( "ErrorBarX" )
#define EXC_CHPROP_ERRORBARY CREATE_OUSTRING( "ErrorBarY" )
+#define EXC_CHPROP_EXPANSION CREATE_OUSTRING( "Expansion" )
#define EXC_CHPROP_FILLBITMAPMODE CREATE_OUSTRING( "FillBitmapMode" )
#define EXC_CHPROP_FILLSTYLE CREATE_OUSTRING( "FillStyle" )
#define EXC_CHPROP_GAPWIDTHSEQ CREATE_OUSTRING( "GapwidthSequence" )
#define EXC_CHPROP_GEOMETRY3D CREATE_OUSTRING( "Geometry3D" )
+#define EXC_CHPROP_HASMAINTITLE CREATE_OUSTRING( "HasMainTitle" )
#define EXC_CHPROP_INCLUDEHIDDENCELLS CREATE_OUSTRING( "IncludeHiddenCells" )
#define EXC_CHPROP_JAPANESE CREATE_OUSTRING( "Japanese" )
#define EXC_CHPROP_LABEL CREATE_OUSTRING( "Label" )
@@ -116,6 +124,7 @@ namespace com { namespace sun { namespace star {
#define EXC_CHPROP_PERCENTDIAGONAL CREATE_OUSTRING( "PercentDiagonal" )
#define EXC_CHPROP_PERSPECTIVE CREATE_OUSTRING( "Perspective" )
#define EXC_CHPROP_POSITIVEERROR CREATE_OUSTRING( "PositiveError" )
+#define EXC_CHPROP_RELATIVEPOSITION CREATE_OUSTRING( "RelativePosition" )
#define EXC_CHPROP_RIGHTANGLEDAXES CREATE_OUSTRING( "RightAngledAxes" )
#define EXC_CHPROP_ROLE CREATE_OUSTRING( "Role" )
#define EXC_CHPROP_ROTATIONHORIZONTAL CREATE_OUSTRING( "RotationHorizontal" )
@@ -169,7 +178,8 @@ const sal_Int32 EXC_CHART_AXESSET_NONE = -1; /// For internal use
const sal_Int32 EXC_CHART_AXESSET_PRIMARY = 0; /// API primary axes set index.
const sal_Int32 EXC_CHART_AXESSET_SECONDARY = 1; /// API secondary axes set index.
-const sal_Int32 EXC_CHART_UNIT = 4000; /// Chart objects are positioned in 1/4000 of chart area.
+const sal_Int32 EXC_CHART_TOTALUNITS = 4000; /// Most chart objects are positioned in 1/4000 of chart area.
+const sal_Int32 EXC_CHART_PLOTAREAUNITS = 1000; /// For objects that are positioned in 1/1000 of plot area.
// (0x0850) CHFRINFO ----------------------------------------------------------
@@ -604,7 +614,8 @@ const sal_uInt16 EXC_ID_CHPROPERTIES = 0x1044;
const sal_uInt16 EXC_CHPROPS_MANSERIES = 0x0001; /// Manual series allocation.
const sal_uInt16 EXC_CHPROPS_SHOWVISIBLEONLY = 0x0002; /// Show visible cells only.
const sal_uInt16 EXC_CHPROPS_NORESIZE = 0x0004; /// Do not resize chart with window.
-const sal_uInt16 EXC_CHPROPS_MANPLOTAREA = 0x0008; /// Plot area with CHFRAMEPOS records.
+const sal_uInt16 EXC_CHPROPS_MANPLOTAREA = 0x0008; /// Manual plot area mode.
+const sal_uInt16 EXC_CHPROPS_USEMANPLOTAREA = 0x0010; /// Manual plot area layout in CHFRAMEPOS record.
const sal_uInt8 EXC_CHPROPS_EMPTY_SKIP = 0; /// Skip empty values.
const sal_uInt8 EXC_CHPROPS_EMPTY_ZERO = 1; /// Plot empty values as zero.
@@ -643,11 +654,11 @@ const sal_uInt16 EXC_ID_CHFORMAT = 0x104E;
const sal_uInt16 EXC_ID_CHFRAMEPOS = 0x104F;
-const sal_uInt16 EXC_CHFRAMEPOS_ANY = 2;
-const sal_uInt16 EXC_CHFRAMEPOS_LEGEND = 5;
-
-const sal_uInt16 EXC_CHFRAMEPOS_MANUALSIZE = 1;
-const sal_uInt16 EXC_CHFRAMEPOS_AUTOSIZE = 2;
+const sal_uInt16 EXC_CHFRAMEPOS_POINTS = 0;
+const sal_uInt16 EXC_CHFRAMEPOS_ABSSIZE_POINTS = 1;
+const sal_uInt16 EXC_CHFRAMEPOS_PARENT = 2;
+const sal_uInt16 EXC_CHFRAMEPOS_DEFOFFSET_PLOT = 3;
+const sal_uInt16 EXC_CHFRAMEPOS_CHARTSIZE = 5;
// (0x1050) CHFORMATRUNS ------------------------------------------------------
@@ -774,8 +785,8 @@ struct XclChFrBlock
struct XclChFramePos
{
XclChRectangle maRect; /// Object dependent position data.
- sal_uInt16 mnObjType; /// Object type.
- sal_uInt16 mnSizeMode; /// Size mode (manual, automatic).
+ sal_uInt16 mnTLMode; /// Top-left position mode.
+ sal_uInt16 mnBRMode; /// Bottom-right position mode.
explicit XclChFramePos();
};
@@ -885,7 +896,7 @@ struct XclChText
sal_uInt8 mnVAlign; /// Vertical alignment.
sal_uInt16 mnBackMode; /// Background mode: transparent, opaque.
sal_uInt16 mnFlags; /// Additional flags.
- sal_uInt16 mnPlacement; /// Text object placement (BIFF8+).
+ sal_uInt16 mnFlags2; /// Text object placement and text direction (BIFF8+).
sal_uInt16 mnRotation; /// Text object rotation (BIFF8+).
explicit XclChText();
@@ -1013,7 +1024,6 @@ struct XclChLegend
struct XclChTypeGroup
{
- XclChRectangle maRect; /// Position (not used).
sal_uInt16 mnFlags; /// Additional flags.
sal_uInt16 mnGroupIdx; /// Chart type group index.
@@ -1060,7 +1070,6 @@ struct XclChValueRange
struct XclChTick
{
- XclChRectangle maRect; /// Position (not used).
Color maTextColor; /// Tick labels color.
sal_uInt8 mnMajor; /// Type of tick marks of major grid.
sal_uInt8 mnMinor; /// Type of tick marks of minor grid.
@@ -1076,7 +1085,6 @@ struct XclChTick
struct XclChAxis
{
- XclChRectangle maRect; /// Position (not used).
sal_uInt16 mnType; /// Axis type.
explicit XclChAxis();
@@ -1089,7 +1097,7 @@ struct XclChAxis
struct XclChAxesSet
{
- XclChRectangle maRect; /// Position of the axes set.
+ XclChRectangle maRect; /// Position of the axes set (inner plot area).
sal_uInt16 mnAxesSetId; /// Primary/secondary axes set.
explicit XclChAxesSet();
@@ -1158,16 +1166,6 @@ enum XclChFrameType
EXC_CHFRAMETYPE_INVISIBLE /// Missing frame represents invisible formatting.
};
-/** Enumerates different text box types for default text formatting. */
-enum XclChTextType
-{
- EXC_CHTEXTTYPE_TITLE, /// Chart title.
- EXC_CHTEXTTYPE_LEGEND, /// Chart legend.
- EXC_CHTEXTTYPE_AXISTITLE, /// Chart axis titles.
- EXC_CHTEXTTYPE_AXISLABEL, /// Chart axis labels.
- EXC_CHTEXTTYPE_DATALABEL /// Data point labels.
-};
-
/** Contains information about auto formatting of a specific chart object type. */
struct XclChFormatInfo
{
@@ -1298,6 +1296,30 @@ private:
XclChTypeInfoMap maInfoMap; /// Maps chart types to type info data.
};
+// Chart text and title object helpers ========================================
+
+/** Enumerates different text box types for default text formatting and title
+ positioning. */
+enum XclChTextType
+{
+ EXC_CHTEXTTYPE_TITLE, /// Chart title.
+ EXC_CHTEXTTYPE_LEGEND, /// Chart legend.
+ EXC_CHTEXTTYPE_AXISTITLE, /// Chart axis titles.
+ EXC_CHTEXTTYPE_AXISLABEL, /// Chart axis labels.
+ EXC_CHTEXTTYPE_DATALABEL /// Data point labels.
+};
+
+/** A map key for text and title objects. */
+struct XclChTextKey : public ::std::pair< XclChTextType, ::std::pair< sal_uInt16, sal_uInt16 > >
+{
+ inline explicit XclChTextKey( XclChTextType eTextType, sal_uInt16 nMainIdx = 0, sal_uInt16 nSubIdx = 0 )
+ { first = eTextType; second.first = nMainIdx; second.second = nSubIdx; }
+};
+
+/** Function prototype receiving a chart document and returning a title shape. */
+typedef ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >
+ (*XclChGetShapeFunc)( const ::com::sun::star::uno::Reference< ::com::sun::star::chart::XChartDocument >& );
+
// Property helpers ===========================================================
class XclChObjectTable
@@ -1363,10 +1385,6 @@ public:
sal_uInt16 ReadRotationProperties(
const ScfPropertySet& rPropSet,
bool bSupportsStacked );
- /** Reads all legend properties from the passed property set. */
- void ReadLegendProperties(
- XclChLegend& rLegend,
- const ScfPropertySet& rPropSet );
/** Writes all line properties to the passed property set. */
void WriteLineProperties(
@@ -1397,10 +1415,6 @@ public:
ScfPropertySet& rPropSet,
sal_uInt16 nRotation,
bool bSupportsStacked );
- /** Writes all legend properties to the passed property set. */
- void WriteLegendProperties(
- ScfPropertySet& rPropSet,
- const XclChLegend& rLegend );
private:
/** Returns a line property set helper according to the passed property mode. */
@@ -1423,51 +1437,47 @@ private:
ScfPropSetHelper maHatchHlpCommon; /// Properties for hatches in common objects.
ScfPropSetHelper maHatchHlpFilled; /// Properties for hatches in filled series.
ScfPropSetHelper maBitmapHlp; /// Properties for bitmaps.
- ScfPropSetHelper maLegendHlp; /// Properties for legend.
};
// ============================================================================
/** Base struct for internal root data structs for import and export. */
-class XclChRootData
+struct XclChRootData
{
-public:
- typedef ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartDocument > XChartDocRef;
+ typedef ScfRef< XclChTypeInfoProvider > XclChTypeProvRef;
+ typedef ScfRef< XclChFormatInfoProvider > XclChFmtInfoProvRef;
+ typedef ScfRef< XclChObjectTable > XclChObjectTableRef;
+ typedef ::std::map< XclChTextKey, XclChGetShapeFunc > XclChGetShapeFuncMap;
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartDocument >
+ mxChartDoc; /// The chart document.
+ Rectangle maChartRect; /// Position and size of the chart shape.
+ XclChTypeProvRef mxTypeInfoProv; /// Provides info about chart types.
+ XclChFmtInfoProvRef mxFmtInfoProv; /// Provides info about auto formatting.
+ XclChObjectTableRef mxLineDashTable; /// Container for line dash styles.
+ XclChObjectTableRef mxGradientTable; /// Container for gradient fill styles.
+ XclChObjectTableRef mxHatchTable; /// Container for hatch fill styles.
+ XclChObjectTableRef mxBitmapTable; /// Container for bitmap fill styles.
+ XclChGetShapeFuncMap maGetShapeFuncs; /// Maps title shape getter functions.
+ sal_Int32 mnBorderGapX; /// Border gap to chart space in 1/100mm.
+ sal_Int32 mnBorderGapY; /// Border gap to chart space in 1/100mm.
+ double mfUnitSizeX; /// Size of a chart X unit (1/4000 of chart width) in 1/100 mm.
+ double mfUnitSizeY; /// Size of a chart Y unit (1/4000 of chart height) in 1/100 mm.
-public:
explicit XclChRootData();
virtual ~XclChRootData();
- /** Returns the API reference of the chart document. */
- XChartDocRef GetChartDoc() const;
-
- /** Returns the chart type info provider, that contains data about all chart types. */
- inline XclChTypeInfoProvider& GetTypeInfoProvider() const { return *mxTypeInfoProv; }
- /** Returns the chart type info provider, that contains data about all chart types. */
- inline XclChFormatInfoProvider& GetFormatInfoProvider() const { return *mxFmtInfoProv; }
-
- inline XclChObjectTable& GetLineDashTable() const { return *mxLineDashTable; }
- inline XclChObjectTable& GetGradientTable() const { return *mxGradientTable; }
- inline XclChObjectTable& GetHatchTable() const { return *mxHatchTable; }
- inline XclChObjectTable& GetBitmapTable() const { return *mxBitmapTable; }
-
/** Starts the API chart document conversion. Must be called once before any API access. */
- void InitConversion( XChartDocRef xChartDoc );
+ void InitConversion(
+ const XclRoot& rRoot,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartDocument >& rxChartDoc,
+ const Rectangle& rChartRect );
/** Finishes the API chart document conversion. Must be called once before any API access. */
void FinishConversion();
-private:
- typedef ScfRef< XclChTypeInfoProvider > XclChTypeProvRef;
- typedef ScfRef< XclChFormatInfoProvider > XclChFmtInfoProvRef;
- typedef ScfRef< XclChObjectTable > XclChObjectTableRef;
-
- XChartDocRef mxChartDoc; /// The chart document.
- XclChTypeProvRef mxTypeInfoProv; /// Provides info about chart types.
- XclChFmtInfoProvRef mxFmtInfoProv; /// Provides info about auto formatting.
- XclChObjectTableRef mxLineDashTable; /// Container for line dash styles.
- XclChObjectTableRef mxGradientTable; /// Container for gradient fill styles.
- XclChObjectTableRef mxHatchTable; /// Container for hatch fill styles.
- XclChObjectTableRef mxBitmapTable; /// Container for bitmap fill styles.
+ /** Returns the drawing shape interface of the specified title object. */
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >
+ GetTitleShape( const XclChTextKey& rTitleKey ) const;
};
// ============================================================================
diff --git a/sc/source/filter/inc/xlroot.hxx b/sc/source/filter/inc/xlroot.hxx
index f3b0f78a948c..2f029c74baa9 100644
--- a/sc/source/filter/inc/xlroot.hxx
+++ b/sc/source/filter/inc/xlroot.hxx
@@ -113,6 +113,8 @@ struct XclRootData
XclTracerRef mxTracer; /// Filter tracer.
RootDataRef mxRD; /// Old RootData struct. Will be removed.
+ double mfScreenPixelX; /// Width of a screen pixel (1/100 mm).
+ double mfScreenPixelY; /// Height of a screen pixel (1/100 mm).
long mnCharWidth; /// Width of '0' in default font (twips).
SCTAB mnScTab; /// Current Calc sheet index.
const bool mbExport; /// false = Import, true = Export.
@@ -177,6 +179,11 @@ public:
/** Returns the current Calc sheet index. */
inline SCTAB GetCurrScTab() const { return mrData.mnScTab; }
+ /** Calculates the width of the passed number of pixels in 1/100 mm. */
+ sal_Int32 GetHmmFromPixelX( double fPixelX ) const;
+ /** Calculates the height of the passed number of pixels in 1/100 mm. */
+ sal_Int32 GetHmmFromPixelY( double fPixelY ) const;
+
/** Returns the medium to import from. */
inline SfxMedium& GetMedium() const { return mrData.mrMedium; }
/** Returns the document URL of the imported/exported file. */
diff --git a/sc/source/filter/xml/xmlexternaltabi.cxx b/sc/source/filter/xml/xmlexternaltabi.cxx
index ce1f58f5d912..083a73d81872 100644
--- a/sc/source/filter/xml/xmlexternaltabi.cxx
+++ b/sc/source/filter/xml/xmlexternaltabi.cxx
@@ -370,7 +370,7 @@ SvXMLImportContext* ScXMLExternalRefCellContext::CreateChildContext(
const SvXMLTokenMap& rTokenMap = mrScImport.GetTableRowCellElemTokenMap();
sal_uInt16 nToken = rTokenMap.Get(nPrefix, rLocalName);
if (nToken == XML_TOK_TABLE_ROW_CELL_P)
- return new ScXMLExternalRefCellTextContext(mrScImport, nPrefix, rLocalName, xAttrList, maCellString);
+ return new ScXMLExternalRefCellTextContext(mrScImport, nPrefix, rLocalName, xAttrList, *this);
return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
}
@@ -399,14 +399,20 @@ void ScXMLExternalRefCellContext::EndElement()
}
}
+void ScXMLExternalRefCellContext::SetCellString(const OUString& rStr)
+{
+ maCellString = rStr;
+}
+
// ============================================================================
ScXMLExternalRefCellTextContext::ScXMLExternalRefCellTextContext(
ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName,
- const Reference<XAttributeList>& /*xAttrList*/, OUString& rCellString ) :
+ const Reference<XAttributeList>& /*xAttrList*/,
+ ScXMLExternalRefCellContext& rParent ) :
SvXMLImportContext( rImport, nPrefix, rLName ),
mrScImport(rImport),
- mrCellString(rCellString)
+ mrParent(rParent)
{
}
@@ -422,9 +428,10 @@ SvXMLImportContext* ScXMLExternalRefCellTextContext::CreateChildContext(
void ScXMLExternalRefCellTextContext::Characters(const OUString& rChar)
{
- mrCellString = rChar;
+ maCellStrBuf.append(rChar);
}
void ScXMLExternalRefCellTextContext::EndElement()
{
+ mrParent.SetCellString(maCellStrBuf.makeStringAndClear());
}
diff --git a/sc/source/filter/xml/xmlexternaltabi.hxx b/sc/source/filter/xml/xmlexternaltabi.hxx
index 0007a8b29702..6aaff181315e 100644
--- a/sc/source/filter/xml/xmlexternaltabi.hxx
+++ b/sc/source/filter/xml/xmlexternaltabi.hxx
@@ -29,6 +29,7 @@
#define SC_XMLEXTERNALTABI_HXX
#include <xmloff/xmlictxt.hxx>
+#include "rtl/ustrbuf.hxx"
class ScXMLImport;
struct ScXMLExternalTabData;
@@ -129,6 +130,8 @@ public:
virtual void EndElement();
+ void SetCellString(const ::rtl::OUString& rStr);
+
private:
ScXMLImport& mrScImport;
ScXMLExternalTabData& mrExternalRefInfo;
@@ -150,7 +153,7 @@ public:
const ::rtl::OUString& rLName,
const ::com::sun::star::uno::Reference<
::com::sun::star::xml::sax::XAttributeList>& xAttrList,
- ::rtl::OUString& rCellString );
+ ScXMLExternalRefCellContext& rParent );
virtual ~ScXMLExternalRefCellTextContext();
@@ -165,7 +168,9 @@ public:
private:
ScXMLImport& mrScImport;
- ::rtl::OUString& mrCellString;
+ ScXMLExternalRefCellContext& mrParent;
+
+ ::rtl::OUStringBuffer maCellStrBuf;
};
#endif
diff --git a/sc/source/filter/xml/xmltabi.cxx b/sc/source/filter/xml/xmltabi.cxx
index 9afc08308feb..095b6ee6d450 100644
--- a/sc/source/filter/xml/xmltabi.cxx
+++ b/sc/source/filter/xml/xmltabi.cxx
@@ -98,21 +98,27 @@ static bool lcl_isExternalRefCache(const rtl::OUString& rName, rtl::OUString& rU
const sal_Unicode c = p[i];
if (i <= 7)
{
+ // Checking the prefix 'file://'.
if (c != aPrefix[i])
return false;
}
- else if (c == '#')
+ else if (bInUrl)
{
- if (cPrev != '\'')
- return false;
+ // parsing file URL
+ if (c == '#')
+ {
+ if (cPrev != '\'')
+ return false;
- rUrl = aUrlBuf.makeStringAndClear();
- rUrl = rUrl.copy(0, rUrl.getLength()-1); // remove the trailing single-quote.
- bInUrl = false;
+ rUrl = aUrlBuf.makeStringAndClear();
+ rUrl = rUrl.copy(0, rUrl.getLength()-1); // remove the trailing single-quote.
+ bInUrl = false;
+ }
+ else
+ aUrlBuf.append(c);
}
- else if (bInUrl)
- aUrlBuf.append(c);
else
+ // parsing sheet name.
aTabNameBuf.append(c);
cPrev = c;
@@ -206,6 +212,7 @@ ScXMLTableContext::ScXMLTableContext( ScXMLImport& rImport,
ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
pExternalRefInfo->mnFileId = pRefMgr->getExternalFileId(aExtUrl);
pExternalRefInfo->mpCacheTable = pRefMgr->getCacheTable(pExternalRefInfo->mnFileId, aExtTabName, true);
+ pExternalRefInfo->mpCacheTable->setWholeTableCached();
}
}
else
diff --git a/sc/source/ui/docshell/docfunc.cxx b/sc/source/ui/docshell/docfunc.cxx
index 01d03d49b50a..e08c930301cf 100644
--- a/sc/source/ui/docshell/docfunc.cxx
+++ b/sc/source/ui/docshell/docfunc.cxx
@@ -98,9 +98,11 @@
#include "scui_def.hxx" //CHINA001
#include "tabprotection.hxx"
#include "clipparam.hxx"
+#include "externalrefmgr.hxx"
#include <memory>
#include <basic/basmgr.hxx>
+#include <boost/scoped_ptr.hpp>
using namespace com::sun::star;
using ::com::sun::star::uno::Sequence;
@@ -1042,6 +1044,10 @@ BOOL ScDocFunc::SetCellText( const ScAddress& rPos, const String& rText,
{
if ( bEnglish )
{
+ ::boost::scoped_ptr<ScExternalRefManager::ApiGuard> pExtRefGuard;
+ if (bApi)
+ pExtRefGuard.reset(new ScExternalRefManager::ApiGuard(pDoc));
+
// code moved to own method InterpretEnglishString because it is also used in
// ScCellRangeObj::setFormulaArray
diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx
index e7b04afa9c4f..0569e95605b1 100644
--- a/sc/source/ui/docshell/externalrefmgr.cxx
+++ b/sc/source/ui/docshell/externalrefmgr.cxx
@@ -65,6 +65,8 @@
#include <memory>
#include <algorithm>
+#include <boost/scoped_ptr.hpp>
+
using ::std::auto_ptr;
using ::com::sun::star::uno::Any;
using ::rtl::OUString;
@@ -135,6 +137,69 @@ private:
ScExternalRefManager::LinkUpdateType meType;
};
+struct UpdateFormulaCell : public unary_function<ScFormulaCell*, void>
+{
+ void operator() (ScFormulaCell* pCell) const
+ {
+ // Check to make sure the cell really contains ocExternalRef.
+ // External names, external cell and range references all have a
+ // ocExternalRef token.
+ const ScTokenArray* pCode = pCell->GetCode();
+ if (!pCode->HasOpCode( ocExternalRef))
+ return;
+
+ ScTokenArray* pArray = pCell->GetCode();
+ if (pArray)
+ // Clear the error code, or a cell with error won't get re-compiled.
+ pArray->SetCodeError(0);
+
+ pCell->SetCompile(true);
+ pCell->CompileTokenArray();
+ pCell->SetDirty();
+ }
+};
+
+class RemoveFormulaCell : public unary_function<pair<const sal_uInt16, ScExternalRefManager::RefCellSet>, void>
+{
+public:
+ explicit RemoveFormulaCell(ScFormulaCell* p) : mpCell(p) {}
+ void operator() (pair<const sal_uInt16, ScExternalRefManager::RefCellSet>& r) const
+ {
+ r.second.erase(mpCell);
+ }
+private:
+ ScFormulaCell* mpCell;
+};
+
+class ConvertFormulaToStatic : public unary_function<ScFormulaCell*, void>
+{
+public:
+ explicit ConvertFormulaToStatic(ScDocument* pDoc) : mpDoc(pDoc) {}
+ void operator() (ScFormulaCell* pCell) const
+ {
+ ScAddress aPos = pCell->aPos;
+
+ // We don't check for empty cells because empty external cells are
+ // treated as having a value of 0.
+
+ if (pCell->IsValue())
+ {
+ // Turn this into value cell.
+ double fVal = pCell->GetValue();
+ mpDoc->PutCell(aPos, new ScValueCell(fVal));
+ }
+ else
+ {
+ // string cell otherwise.
+ String aVal;
+ pCell->GetString(aVal);
+ mpDoc->PutCell(aPos, new ScStringCell(aVal));
+ }
+ }
+private:
+ ScDocument* mpDoc;
+};
+
}
// ============================================================================
@@ -170,7 +235,7 @@ bool ScExternalRefCache::Table::isReferenced() const
return meReferenced != UNREFERENCED;
}
-void ScExternalRefCache::Table::setCell(SCCOL nCol, SCROW nRow, TokenRef pToken, sal_uInt32 nFmtIndex)
+void ScExternalRefCache::Table::setCell(SCCOL nCol, SCROW nRow, TokenRef pToken, sal_uInt32 nFmtIndex, bool bSetCacheRange)
{
using ::std::pair;
RowsDataType::iterator itrRow = maRows.find(nRow);
@@ -193,6 +258,8 @@ void ScExternalRefCache::Table::setCell(SCCOL nCol, SCROW nRow, TokenRef pToken,
aCell.mxToken = pToken;
aCell.mnFmtIndex = nFmtIndex;
rRow.insert(RowDataType::value_type(nCol, aCell));
+ if (bSetCacheRange)
+ setCachedCell(nCol, nRow);
}
ScExternalRefCache::TokenRef ScExternalRefCache::Table::getCell(SCCOL nCol, SCROW nRow, sal_uInt32* pnFmtIndex) const
@@ -201,7 +268,7 @@ ScExternalRefCache::TokenRef ScExternalRefCache::Table::getCell(SCCOL nCol, SCRO
if (itrTable == maRows.end())
{
// this table doesn't have the specified row.
- return TokenRef();
+ return getEmptyOrNullToken(nCol, nRow);
}
const RowDataType& rRowData = itrTable->second;
@@ -209,7 +276,7 @@ ScExternalRefCache::TokenRef ScExternalRefCache::Table::getCell(SCCOL nCol, SCRO
if (itrRow == rRowData.end())
{
// this row doesn't have the specified column.
- return TokenRef();
+ return getEmptyOrNullToken(nCol, nRow);
}
const Cell& rCell = itrRow->second;
@@ -225,13 +292,14 @@ bool ScExternalRefCache::Table::hasRow( SCROW nRow ) const
return itrRow != maRows.end();
}
-void ScExternalRefCache::Table::getAllRows(vector<SCROW>& rRows) const
+void ScExternalRefCache::Table::getAllRows(vector<SCROW>& rRows, SCROW nLow, SCROW nHigh) const
{
vector<SCROW> aRows;
aRows.reserve(maRows.size());
RowsDataType::const_iterator itr = maRows.begin(), itrEnd = maRows.end();
for (; itr != itrEnd; ++itr)
- aRows.push_back(itr->first);
+ if (nLow <= itr->first && itr->first <= nHigh)
+ aRows.push_back(itr->first);
// hash map is not ordered, so we need to explicitly sort it.
::std::sort(aRows.begin(), aRows.end());
@@ -258,7 +326,7 @@ void ScExternalRefCache::Table::getAllRows(vector<SCROW>& rRows) const
return aRange;
}
-void ScExternalRefCache::Table::getAllCols(SCROW nRow, vector<SCCOL>& rCols) const
+void ScExternalRefCache::Table::getAllCols(SCROW nRow, vector<SCCOL>& rCols, SCCOL nLow, SCCOL nHigh) const
{
RowsDataType::const_iterator itrRow = maRows.find(nRow);
if (itrRow == maRows.end())
@@ -270,7 +338,8 @@ void ScExternalRefCache::Table::getAllCols(SCROW nRow, vector<SCCOL>& rCols) con
aCols.reserve(rRowData.size());
RowDataType::const_iterator itrCol = rRowData.begin(), itrColEnd = rRowData.end();
for (; itrCol != itrColEnd; ++itrCol)
- aCols.push_back(itrCol->first);
+ if (nLow <= itrCol->first && itrCol->first <= nHigh)
+ aCols.push_back(itrCol->first);
// hash map is not ordered, so we need to explicitly sort it.
::std::sort(aCols.begin(), aCols.end());
@@ -319,6 +388,54 @@ void ScExternalRefCache::Table::getAllNumberFormats(vector<sal_uInt32>& rNumFmts
}
}
+const ScRangeList& ScExternalRefCache::Table::getCachedRanges() const
+{
+ return maCachedRanges;
+}
+
+bool ScExternalRefCache::Table::isRangeCached(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const
+{
+ return maCachedRanges.In(ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0));
+}
+
+void ScExternalRefCache::Table::setCachedCell(SCCOL nCol, SCROW nRow)
+{
+ setCachedCellRange(nCol, nRow, nCol, nRow);
+}
+
+void ScExternalRefCache::Table::setCachedCellRange(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
+{
+ ScRange aRange(nCol1, nRow1, 0, nCol2, nRow2, 0);
+ if (!maCachedRanges.Count())
+ maCachedRanges.Append(aRange);
+ else
+ maCachedRanges.Join(aRange);
+
+ String aStr;
+ maCachedRanges.Format(aStr, SCA_VALID);
+}
+
+void ScExternalRefCache::Table::setWholeTableCached()
+{
+ setCachedCellRange(0, 0, MAXCOL, MAXROW);
+}
+
+bool ScExternalRefCache::Table::isInCachedRanges(SCCOL nCol, SCROW nRow) const
+{
+ return maCachedRanges.In(ScRange(nCol, nRow, 0, nCol, nRow, 0));
+}
+
+ScExternalRefCache::TokenRef ScExternalRefCache::Table::getEmptyOrNullToken(
+ SCCOL nCol, SCROW nRow) const
+{
+ if (isInCachedRanges(nCol, nRow))
+ {
+ TokenRef p(new ScEmptyCellToken(false, false));
+ return p;
+ }
+ return TokenRef();
+}
+
// ----------------------------------------------------------------------------
ScExternalRefCache::TableName::TableName(const String& rUpper, const String& rReal) :
@@ -383,8 +500,7 @@ const String* ScExternalRefCache::getRealRangeName(sal_uInt16 nFileId, const Str
}
ScExternalRefCache::TokenRef ScExternalRefCache::getCellData(
- sal_uInt16 nFileId, const String& rTabName, SCCOL nCol, SCROW nRow,
- bool bEmptyCellOnNull, bool bWriteEmpty, sal_uInt32* pnFmtIndex)
+ sal_uInt16 nFileId, const String& rTabName, SCCOL nCol, SCROW nRow, sal_uInt32* pnFmtIndex)
{
DocDataType::const_iterator itrDoc = maDocs.find(nFileId);
if (itrDoc == maDocs.end())
@@ -409,18 +525,11 @@ ScExternalRefCache::TokenRef ScExternalRefCache::getCellData(
return TokenRef();
}
- TokenRef pToken = pTableData->getCell(nCol, nRow, pnFmtIndex);
- if (!pToken && bEmptyCellOnNull)
- {
- pToken.reset(new ScEmptyCellToken(false, false));
- if (bWriteEmpty)
- pTableData->setCell(nCol, nRow, pToken);
- }
- return pToken;
+ return pTableData->getCell(nCol, nRow, pnFmtIndex);
}
ScExternalRefCache::TokenArrayRef ScExternalRefCache::getCellRangeData(
- sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange, bool bEmptyCellOnNull, bool bWriteEmpty)
+ sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange)
{
DocDataType::iterator itrDoc = maDocs.find(nFileId);
if (itrDoc == maDocs.end())
@@ -450,13 +559,14 @@ ScExternalRefCache::TokenArrayRef ScExternalRefCache::getCellRangeData(
return TokenArrayRef();
ScRange aCacheRange( nCol1, nRow1, static_cast<SCTAB>(nTabFirstId), nCol2, nRow2, static_cast<SCTAB>(nTabLastId));
+
RangeArrayMap::const_iterator itrRange = rDoc.maRangeArrays.find( aCacheRange);
if (itrRange != rDoc.maRangeArrays.end())
- {
+ // Cache hit!
return itrRange->second;
- }
- TokenArrayRef pArray(new ScTokenArray);
+ ::boost::scoped_ptr<ScRange> pNewRange;
+ TokenArrayRef pArray;
bool bFirstTab = true;
for (size_t nTab = nTabFirstId; nTab <= nTabLastId; ++nTab)
{
@@ -464,27 +574,72 @@ ScExternalRefCache::TokenArrayRef ScExternalRefCache::getCellRangeData(
if (!pTab.get())
return TokenArrayRef();
+ SCCOL nDataCol1 = nCol1, nDataCol2 = nCol2;
+ SCROW nDataRow1 = nRow1, nDataRow2 = nRow2;
+
+ if (!pTab->isRangeCached(nDataCol1, nDataRow1, nDataCol2, nDataRow2))
+ {
+ // specified range is not entirely within cached ranges.
+ return TokenArrayRef();
+ }
+
ScMatrixRef xMat = new ScMatrix(
- static_cast<SCSIZE>(nCol2-nCol1+1), static_cast<SCSIZE>(nRow2-nRow1+1));
+ static_cast<SCSIZE>(nDataCol2-nDataCol1+1), static_cast<SCSIZE>(nDataRow2-nDataRow1+1));
- for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
+#if 0
+ // TODO: Switch to this code block once we have support for sparsely-filled
+ // matrices in ScMatrix.
+
+ // Only fill non-empty cells, for better performance.
+ vector<SCROW> aRows;
+ pTab->getAllRows(aRows, nDataRow1, nDataRow2);
+ for (vector<SCROW>::const_iterator itr = aRows.begin(), itrEnd = aRows.end(); itr != itrEnd; ++itr)
{
- for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+ SCROW nRow = *itr;
+ vector<SCCOL> aCols;
+ pTab->getAllCols(nRow, aCols, nDataCol1, nDataCol2);
+ for (vector<SCCOL>::const_iterator itrCol = aCols.begin(), itrColEnd = aCols.end(); itrCol != itrColEnd; ++itrCol)
{
+ SCCOL nCol = *itrCol;
TokenRef pToken = pTab->getCell(nCol, nRow);
if (!pToken)
+ // This should never happen!
+ return TokenArrayRef();
+
+ SCSIZE nC = nCol - nDataCol1, nR = nRow - nDataRow1;
+ switch (pToken->GetType())
{
- if (bEmptyCellOnNull)
- {
- pToken.reset(new ScEmptyCellToken(false, false));
- if (bWriteEmpty)
- pTab->setCell(nCol, nRow, pToken);
- }
- else
- return TokenArrayRef();
+ case svDouble:
+ xMat->PutDouble(pToken->GetDouble(), nC, nR);
+ break;
+ case svString:
+ xMat->PutString(pToken->GetString(), nC, nR);
+ break;
+ default:
+ ;
}
+ }
+ }
+#else
+ vector<SCROW> aRows;
+ pTab->getAllRows(aRows, nDataRow1, nDataRow2);
+ if (aRows.empty())
+ // Cache is empty.
+ return TokenArrayRef();
+ else
+ // Trim the column below the last non-empty row.
+ nDataRow2 = aRows.back();
+ // Empty all matrix elements first, and fill only non-empty elements.
+ for (SCROW nRow = nDataRow1; nRow <= nDataRow2; ++nRow)
+ {
+ for (SCCOL nCol = nDataCol1; nCol <= nDataCol2; ++nCol)
+ {
+ TokenRef pToken = pTab->getCell(nCol, nRow);
SCSIZE nC = nCol - nCol1, nR = nRow - nRow1;
+ if (!pToken)
+ return TokenArrayRef();
+
switch (pToken->GetType())
{
case svDouble:
@@ -498,17 +653,27 @@ ScExternalRefCache::TokenArrayRef ScExternalRefCache::getCellRangeData(
}
}
}
+#endif
if (!bFirstTab)
pArray->AddOpCode(ocSep);
ScMatrix* pMat2 = xMat;
ScMatrixToken aToken(pMat2);
+ if (!pArray)
+ pArray.reset(new ScTokenArray);
pArray->AddToken(aToken);
bFirstTab = false;
+
+ if (!pNewRange)
+ pNewRange.reset(new ScRange(nDataCol1, nDataRow1, 0, nDataCol2, nDataRow2, 0));
+ else
+ pNewRange->ExtendTo(ScRange(nDataCol1, nDataRow1, 0, nDataCol2, nDataRow2, 0));
}
- rDoc.maRangeArrays.insert( RangeArrayMap::value_type( aCacheRange, pArray));
+
+ if (pNewRange)
+ rDoc.maRangeArrays.insert( RangeArrayMap::value_type(*pNewRange, pArray));
return pArray;
}
@@ -539,7 +704,7 @@ void ScExternalRefCache::setRangeNameTokens(sal_uInt16 nFileId, const String& rN
pDoc->maRealRangeNameMap.insert(NamePairMap::value_type(aUpperName, rName));
}
-void ScExternalRefCache::setCellData(sal_uInt16 nFileId, const String& rTabName, SCROW nRow, SCCOL nCol,
+void ScExternalRefCache::setCellData(sal_uInt16 nFileId, const String& rTabName, SCCOL nCol, SCROW nRow,
TokenRef pToken, sal_uInt32 nFmtIndex)
{
if (!isDocInitialized(nFileId))
@@ -564,6 +729,7 @@ void ScExternalRefCache::setCellData(sal_uInt16 nFileId, const String& rTabName,
pTableData.reset(new Table);
pTableData->setCell(nCol, nRow, pToken, nFmtIndex);
+ pTableData->setCachedCell(nCol, nRow);
}
void ScExternalRefCache::setCellRangeData(sal_uInt16 nFileId, const ScRange& rRange, const vector<SingleRangeData>& rData,
@@ -609,20 +775,27 @@ void ScExternalRefCache::setCellRangeData(sal_uInt16 nFileId, const ScRange& rRa
SCSIZE nC = nCol - nCol1, nR = nRow - nRow1;
TokenRef pToken;
const ScMatrixRef& pMat = itrData->mpRangeData;
+ if (pMat->IsEmpty(nC, nR))
+ // Don't cache empty cells.
+ continue;
+
if (pMat->IsValue(nC, nR))
pToken.reset(new formula::FormulaDoubleToken(pMat->GetDouble(nC, nR)));
else if (pMat->IsString(nC, nR))
pToken.reset(new formula::FormulaStringToken(pMat->GetString(nC, nR)));
- else
- pToken.reset(new ScEmptyCellToken(false, false));
- pTabData->setCell(nCol, nRow, pToken);
+ if (pToken)
+ // Don't mark this cell 'cached' here, for better performance.
+ pTabData->setCell(nCol, nRow, pToken, 0, false);
}
}
+ // Mark the whole range 'cached'.
+ pTabData->setCachedCellRange(nCol1, nRow1, nCol2, nRow2);
}
size_t nTabLastId = nTabFirstId + rRange.aEnd.Tab() - rRange.aStart.Tab();
ScRange aCacheRange( nCol1, nRow1, static_cast<SCTAB>(nTabFirstId), nCol2, nRow2, static_cast<SCTAB>(nTabLastId));
+
rDoc.maRangeArrays.insert( RangeArrayMap::value_type( aCacheRange, pArray));
}
@@ -1019,6 +1192,9 @@ ScExternalRefCache::TableTypeRef ScExternalRefCache::getCacheTable(sal_uInt16 nF
{
// specified table found.
if( pnIndex ) *pnIndex = nIndex;
+ if (bCreateNew && !rDoc.maTables[nIndex])
+ rDoc.maTables[nIndex].reset(new Table);
+
return rDoc.maTables[nIndex];
}
@@ -1186,11 +1362,11 @@ static FormulaToken* lcl_convertToToken(ScBaseCell* pCell)
return NULL;
}
-static ScTokenArray* lcl_convertToTokenArray(ScDocument* pSrcDoc, const ScRange& rRange,
+static ScTokenArray* lcl_convertToTokenArray(ScDocument* pSrcDoc, ScRange& rRange,
vector<ScExternalRefCache::SingleRangeData>& rCacheData)
{
- const ScAddress& s = rRange.aStart;
- const ScAddress& e = rRange.aEnd;
+ ScAddress& s = rRange.aStart;
+ ScAddress& e = rRange.aEnd;
SCTAB nTab1 = s.Tab(), nTab2 = e.Tab();
SCCOL nCol1 = s.Col(), nCol2 = e.Col();
@@ -1204,19 +1380,35 @@ static ScTokenArray* lcl_convertToTokenArray(ScDocument* pSrcDoc, const ScRange&
// range to it.
return NULL;
+ ::boost::scoped_ptr<ScRange> pUsedRange;
+
auto_ptr<ScTokenArray> pArray(new ScTokenArray);
bool bFirstTab = true;
vector<ScExternalRefCache::SingleRangeData>::iterator
itrCache = rCacheData.begin(), itrCacheEnd = rCacheData.end();
+
for (SCTAB nTab = nTab1; nTab <= nTab2 && itrCache != itrCacheEnd; ++nTab, ++itrCache)
{
+ // Only loop within the data area.
+ SCCOL nDataCol1 = nCol1, nDataCol2 = nCol2;
+ SCROW nDataRow1 = nRow1, nDataRow2 = nRow2;
+ if (!pSrcDoc->ShrinkToDataArea(nTab, nDataCol1, nDataRow1, nDataCol2, nDataRow2))
+ // no data within specified range.
+ continue;
+
+ if (pUsedRange.get())
+ // Make sure the used area only grows, not shrinks.
+ pUsedRange->ExtendTo(ScRange(nDataCol1, nDataRow1, 0, nDataCol2, nDataRow2, 0));
+ else
+ pUsedRange.reset(new ScRange(nDataCol1, nDataRow1, 0, nDataCol2, nDataRow2, 0));
+
ScMatrixRef xMat = new ScMatrix(
- static_cast<SCSIZE>(nCol2-nCol1+1),
- static_cast<SCSIZE>(nRow2-nRow1+1));
+ static_cast<SCSIZE>(nDataCol2-nDataCol1+1),
+ static_cast<SCSIZE>(nDataRow2-nDataRow1+1));
- for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+ for (SCCOL nCol = nDataCol1; nCol <= nDataCol2; ++nCol)
{
- for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
+ for (SCROW nRow = nDataRow1; nRow <= nDataRow2; ++nRow)
{
SCSIZE nC = nCol - nCol1, nR = nRow - nRow1;
ScBaseCell* pCell;
@@ -1283,12 +1475,38 @@ static ScTokenArray* lcl_convertToTokenArray(ScDocument* pSrcDoc, const ScRange&
bFirstTab = false;
}
+
+ if (!pUsedRange.get())
+ return NULL;
+
+ s.SetCol(pUsedRange->aStart.Col());
+ s.SetRow(pUsedRange->aStart.Row());
+ e.SetCol(pUsedRange->aEnd.Col());
+ e.SetRow(pUsedRange->aEnd.Row());
+
+ return pArray.release();
+}
+
+static ScTokenArray* lcl_fillEmptyMatrix(const ScRange& rRange)
+{
+ SCSIZE nC = static_cast<SCSIZE>(rRange.aEnd.Col()-rRange.aStart.Col()+1);
+ SCSIZE nR = static_cast<SCSIZE>(rRange.aEnd.Row()-rRange.aStart.Row()+1);
+ ScMatrixRef xMat = new ScMatrix(nC, nR);
+ for (SCSIZE i = 0; i < nC; ++i)
+ for (SCSIZE j = 0; j < nR; ++j)
+ xMat->PutEmpty(i, j);
+
+ ScMatrix* pMat2 = xMat;
+ ScMatrixToken aToken(pMat2);
+ auto_ptr<ScTokenArray> pArray(new ScTokenArray);
+ pArray->AddToken(aToken);
return pArray.release();
}
ScExternalRefManager::ScExternalRefManager(ScDocument* pDoc) :
mpDoc(pDoc),
- bInReferenceMarking(false)
+ mbInReferenceMarking(false),
+ mbUserInteractionEnabled(true)
{
maSrcDocTimer.SetTimeoutHdl( LINK(this, ScExternalRefManager, TimeOutHdl) );
maSrcDocTimer.SetTimeout(SRCDOC_SCAN_INTERVAL);
@@ -1316,236 +1534,28 @@ ScExternalRefCache::TableTypeRef ScExternalRefManager::getCacheTable(sal_uInt16
// ============================================================================
-ScExternalRefManager::RefCells::TabItem::TabItem(SCTAB nIndex) :
- mnIndex(nIndex)
-{
-}
-
-ScExternalRefManager::RefCells::TabItem::TabItem(const TabItem& r) :
- mnIndex(r.mnIndex),
- maCols(r.maCols)
-{
-}
-
-ScExternalRefManager::RefCells::RefCells()
-{
-}
-
-ScExternalRefManager::RefCells::~RefCells()
-{
-}
-
-list<ScExternalRefManager::RefCells::TabItemRef>::iterator ScExternalRefManager::RefCells::getTabPos(SCTAB nTab)
-{
- list<TabItemRef>::iterator itr = maTables.begin(), itrEnd = maTables.end();
- for (; itr != itrEnd; ++itr)
- if ((*itr)->mnIndex >= nTab)
- return itr;
- // Not found. return the end position.
- return itrEnd;
-}
-
-void ScExternalRefManager::RefCells::insertCell(const ScAddress& rAddr)
-{
- SCTAB nTab = rAddr.Tab();
- SCCOL nCol = rAddr.Col();
- SCROW nRow = rAddr.Row();
-
- // Search by table index.
- list<TabItemRef>::iterator itrTab = getTabPos(nTab);
- TabItemRef xTabRef;
- if (itrTab == maTables.end())
- {
- // All previous tables come before the specificed table.
- xTabRef.reset(new TabItem(nTab));
- maTables.push_back(xTabRef);
- }
- else if ((*itrTab)->mnIndex > nTab)
- {
- // Insert at the current iterator position.
- xTabRef.reset(new TabItem(nTab));
- maTables.insert(itrTab, xTabRef);
- }
- else if ((*itrTab)->mnIndex == nTab)
- {
- // The table found.
- xTabRef = *itrTab;
- }
- ColSet& rCols = xTabRef->maCols;
-
- // Then by column index.
- ColSet::iterator itrCol = rCols.find(nCol);
- if (itrCol == rCols.end())
- {
- RowSet aRows;
- pair<ColSet::iterator, bool> r = rCols.insert(ColSet::value_type(nCol, aRows));
- if (!r.second)
- // column insertion failed.
- return;
- itrCol = r.first;
- }
- RowSet& rRows = itrCol->second;
-
- // Finally, insert the row index.
- rRows.insert(nRow);
-}
-
-void ScExternalRefManager::RefCells::removeCell(const ScAddress& rAddr)
-{
- SCTAB nTab = rAddr.Tab();
- SCCOL nCol = rAddr.Col();
- SCROW nRow = rAddr.Row();
-
- // Search by table index.
- list<TabItemRef>::iterator itrTab = getTabPos(nTab);
- if (itrTab == maTables.end() || (*itrTab)->mnIndex != nTab)
- // No such table.
- return;
-
- ColSet& rCols = (*itrTab)->maCols;
-
- // Then by column index.
- ColSet::iterator itrCol = rCols.find(nCol);
- if (itrCol == rCols.end())
- // No such column
- return;
-
- RowSet& rRows = itrCol->second;
- rRows.erase(nRow);
-}
-
-void ScExternalRefManager::RefCells::moveTable(SCTAB nOldTab, SCTAB nNewTab, bool bCopy)
-{
- if (nOldTab == nNewTab)
- // Nothing to do here.
- return;
-
- list<TabItemRef>::iterator itrOld = getTabPos(nOldTab);
- if (itrOld == maTables.end() || (*itrOld)->mnIndex != nOldTab)
- // No table to move or copy.
- return;
-
- list<TabItemRef>::iterator itrNew = getTabPos(nNewTab);
- if (bCopy)
- {
- // Simply make a duplicate of the original table, insert it at the
- // new tab position, and increment the table index for all tables
- // that come after that inserted table.
-
- TabItemRef xNewTab(new TabItem(*(*itrOld)));
- xNewTab->mnIndex = nNewTab;
- maTables.insert(itrNew, xNewTab);
- list<TabItemRef>::iterator itr = itrNew, itrEnd = maTables.end();
- if (itr != itrEnd) // #i99807# check that itr is not at end already
- for (++itr; itr != itrEnd; ++itr)
- (*itr)->mnIndex += 1;
- }
- else
- {
- if (itrOld == itrNew)
- {
- // No need to move the table. Just update the table index.
- (*itrOld)->mnIndex = nNewTab;
- return;
- }
-
- if (nOldTab < nNewTab)
- {
- // Iterate from the old tab position to the new tab position (not
- // inclusive of the old tab itself), and decrement their tab
- // index by one.
- list<TabItemRef>::iterator itr = itrOld;
- for (++itr; itr != itrNew; ++itr)
- (*itr)->mnIndex -= 1;
-
- // Insert a duplicate of the original table. This does not
- // invalidate the iterators.
- (*itrOld)->mnIndex = nNewTab - 1;
- if (itrNew == maTables.end())
- maTables.push_back(*itrOld);
- else
- maTables.insert(itrNew, *itrOld);
-
- // Remove the original table.
- maTables.erase(itrOld);
- }
- else
- {
- // nNewTab < nOldTab
-
- // Iterate from the new tab position to the one before the old tab
- // position, and increment their tab index by one.
- list<TabItemRef>::iterator itr = itrNew;
- for (++itr; itr != itrOld; ++itr)
- (*itr)->mnIndex += 1;
-
- (*itrOld)->mnIndex = nNewTab;
- maTables.insert(itrNew, *itrOld);
-
- // Remove the original table.
- maTables.erase(itrOld);
- }
- }
-}
-
-void ScExternalRefManager::RefCells::insertTable(SCTAB nPos)
-{
- TabItemRef xNewTab(new TabItem(nPos));
- list<TabItemRef>::iterator itr = getTabPos(nPos);
- if (itr == maTables.end())
- maTables.push_back(xNewTab);
- else
- maTables.insert(itr, xNewTab);
-}
-
-void ScExternalRefManager::RefCells::removeTable(SCTAB nPos)
+ScExternalRefManager::LinkListener::LinkListener()
{
- list<TabItemRef>::iterator itr = getTabPos(nPos);
- if (itr == maTables.end())
- // nothing to remove.
- return;
-
- maTables.erase(itr);
}
-void ScExternalRefManager::RefCells::refreshAllCells(ScExternalRefManager& rRefMgr)
+ScExternalRefManager::LinkListener::~LinkListener()
{
- // Get ALL the cell positions for re-compilation.
- for (list<TabItemRef>::iterator itrTab = maTables.begin(), itrTabEnd = maTables.end();
- itrTab != itrTabEnd; ++itrTab)
- {
- SCTAB nTab = (*itrTab)->mnIndex;
- ColSet& rCols = (*itrTab)->maCols;
- for (ColSet::iterator itrCol = rCols.begin(), itrColEnd = rCols.end();
- itrCol != itrColEnd; ++itrCol)
- {
- SCCOL nCol = itrCol->first;
- RowSet& rRows = itrCol->second;
- RowSet aNewRows;
- for (RowSet::iterator itrRow = rRows.begin(), itrRowEnd = rRows.end();
- itrRow != itrRowEnd; ++itrRow)
- {
- SCROW nRow = *itrRow;
- ScAddress aCell(nCol, nRow, nTab);
- if (rRefMgr.compileTokensByCell(aCell))
- // This cell still contains an external refernce.
- aNewRows.insert(nRow);
- }
- // Update the rows so that cells with no external references are
- // no longer tracked.
- rRows.swap(aNewRows);
- }
- }
}
// ----------------------------------------------------------------------------
-ScExternalRefManager::LinkListener::LinkListener()
+ScExternalRefManager::ApiGuard::ApiGuard(ScDocument* pDoc) :
+ mpMgr(pDoc->GetExternalRefManager()),
+ mbOldInteractionEnabled(mpMgr->mbUserInteractionEnabled)
{
+ // We don't want user interaction handled in the API.
+ mpMgr->mbUserInteractionEnabled = false;
}
-ScExternalRefManager::LinkListener::~LinkListener()
+ScExternalRefManager::ApiGuard::~ApiGuard()
{
+ // Restore old value.
+ mpMgr->mbUserInteractionEnabled = mbOldInteractionEnabled;
}
// ----------------------------------------------------------------------------
@@ -1595,9 +1605,22 @@ bool ScExternalRefManager::markUsedByLinkListeners()
return bAllMarked;
}
-bool ScExternalRefManager::setCacheDocReferenced( sal_uInt16 nFileId )
+bool ScExternalRefManager::markUsedExternalRefCells()
{
- return maRefCache.setCacheDocReferenced( nFileId);
+ RefCellMap::iterator itr = maRefCells.begin(), itrEnd = maRefCells.end();
+ for (; itr != itrEnd; ++itr)
+ {
+ RefCellSet::iterator itrCell = itr->second.begin(), itrCellEnd = itr->second.end();
+ for (; itrCell != itrCellEnd; ++itrCell)
+ {
+ ScFormulaCell* pCell = *itrCell;
+ bool bUsed = pCell->MarkUsedExternalReferences();
+ if (bUsed)
+ // Return true when at least one cell references external docs.
+ return true;
+ }
+ }
+ return false;
}
bool ScExternalRefManager::setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName, size_t nSheets )
@@ -1617,7 +1640,7 @@ void ScExternalRefManager::setCacheTableReferencedPermanently( sal_uInt16 nFileI
void ScExternalRefManager::setAllCacheTableReferencedStati( bool bReferenced )
{
- bInReferenceMarking = !bReferenced;
+ mbInReferenceMarking = !bReferenced;
maRefCache.setAllCacheTableReferencedStati( bReferenced );
}
@@ -1642,20 +1665,13 @@ ScExternalRefCache::TokenRef ScExternalRefManager::getSingleRefToken(
if (pFmt)
pFmt->mbIsSet = false;
- bool bLoading = mpDoc->IsImportingXML();
-
// Check if the given table name and the cell position is cached.
- // #i101304# When loading a file, the saved cache (hidden sheet)
- // is assumed to contain all data for the loaded formulas.
- // No cache entries are created from empty cells in the saved sheet,
- // so they have to be created here (bWriteEmpty parameter).
- // Otherwise, later interpretation of the loaded formulas would
- // load the source document even if the user didn't want to update.
sal_uInt32 nFmtIndex = 0;
ScExternalRefCache::TokenRef pToken = maRefCache.getCellData(
- nFileId, rTabName, rCell.Col(), rCell.Row(), bLoading, bLoading, &nFmtIndex);
+ nFileId, rTabName, rCell.Col(), rCell.Row(), &nFmtIndex);
if (pToken)
{
+ // Cache hit !
if (pFmt)
{
short nFmtType = mpDoc->GetFormatTable()->GetType(nFmtIndex);
@@ -1673,11 +1689,8 @@ ScExternalRefCache::TokenRef ScExternalRefManager::getSingleRefToken(
ScDocument* pSrcDoc = getSrcDocument(nFileId);
if (!pSrcDoc)
{
- // Source document is not reachable. Try to get data from the cache
- // once again, but this time treat a non-cached cell as an empty cell
- // as long as the table itself is cached.
- pToken = maRefCache.getCellData(
- nFileId, rTabName, rCell.Col(), rCell.Row(), true, false, &nFmtIndex);
+ // Source document not reachable. Throw a reference error.
+ pToken.reset(new FormulaErrorToken(errNoRef));
return pToken;
}
@@ -1686,12 +1699,30 @@ ScExternalRefCache::TokenRef ScExternalRefManager::getSingleRefToken(
if (!pSrcDoc->GetTable(rTabName, nTab))
{
// specified table name doesn't exist in the source document.
- return ScExternalRefCache::TokenRef();
+ pToken.reset(new FormulaErrorToken(errNoRef));
+ return pToken;
}
if (pTab)
*pTab = nTab;
+ SCCOL nDataCol1 = 0, nDataCol2 = MAXCOL;
+ SCROW nDataRow1 = 0, nDataRow2 = MAXROW;
+ pSrcDoc->ShrinkToDataArea(nTab, nDataCol1, nDataRow1, nDataCol2, nDataRow2);
+ if (rCell.Col() < nDataCol1 || nDataCol2 < rCell.Col() || rCell.Row() < nDataRow1 || nDataRow2 < rCell.Row())
+ {
+ // requested cell is outside the data area. Don't even bother caching
+ // this data, but add it to the cached range to prevent accessing the
+ // source document time and time again.
+ ScExternalRefCache::TableTypeRef pCacheTab =
+ maRefCache.getCacheTable(nFileId, rTabName, true, NULL);
+ if (pCacheTab)
+ pCacheTab->setCachedCell(rCell.Col(), rCell.Row());
+
+ pToken.reset(new ScEmptyCellToken(false, false));
+ return pToken;
+ }
+
pSrcDoc->GetCell(rCell.Col(), rCell.Row(), nTab, pCell);
ScExternalRefCache::TokenRef pTok(lcl_convertToToken(pCell));
@@ -1714,39 +1745,45 @@ ScExternalRefCache::TokenRef ScExternalRefManager::getSingleRefToken(
pTok.reset( new FormulaErrorToken( errNoValue));
}
- // Now, insert the token into cache table.
- maRefCache.setCellData(nFileId, rTabName, rCell.Row(), rCell.Col(), pTok, nFmtIndex);
+ // Now, insert the token into cache table but don't cache empty cells.
+ if (pTok->GetType() != formula::svEmptyCell)
+ maRefCache.setCellData(nFileId, rTabName, rCell.Col(), rCell.Row(), pTok, nFmtIndex);
+
return pTok;
}
-ScExternalRefCache::TokenArrayRef ScExternalRefManager::getDoubleRefTokens(sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange, const ScAddress* pCurPos)
+ScExternalRefCache::TokenArrayRef ScExternalRefManager::getDoubleRefTokens(
+ sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange, const ScAddress* pCurPos)
{
if (pCurPos)
insertRefCell(nFileId, *pCurPos);
maybeLinkExternalFile(nFileId);
- bool bLoading = mpDoc->IsImportingXML();
-
// Check if the given table name and the cell position is cached.
- // #i101304# When loading, put empty cells into cache, see getSingleRefToken.
- ScExternalRefCache::TokenArrayRef p = maRefCache.getCellRangeData(nFileId, rTabName, rRange, bLoading, bLoading);
- if (p.get())
- return p;
+ ScExternalRefCache::TokenArrayRef pArray =
+ maRefCache.getCellRangeData(nFileId, rTabName, rRange);
+ if (pArray)
+ // Cache hit !
+ return pArray;
ScDocument* pSrcDoc = getSrcDocument(nFileId);
if (!pSrcDoc)
{
- // Source document is not reachable. Try to get data from the cache
- // once again, but this time treat non-cached cells as empty cells as
- // long as the table itself is cached.
- return maRefCache.getCellRangeData(nFileId, rTabName, rRange, true, false);
+ // Source document is not reachable. Throw a reference error.
+ pArray.reset(new ScTokenArray);
+ pArray->AddToken(FormulaErrorToken(errNoRef));
+ return pArray;
}
SCTAB nTab1;
if (!pSrcDoc->GetTable(rTabName, nTab1))
+ {
// specified table name doesn't exist in the source document.
- return ScExternalRefCache::TokenArrayRef();
+ pArray.reset(new ScTokenArray);
+ pArray->AddToken(FormulaErrorToken(errNoRef));
+ return pArray;
+ }
ScRange aRange(rRange);
SCTAB nTabSpan = aRange.aEnd.Tab() - aRange.aStart.Tab();
@@ -1770,12 +1807,24 @@ ScExternalRefCache::TokenArrayRef ScExternalRefManager::getDoubleRefTokens(sal_u
aRange.aStart.SetTab(nTab1);
aRange.aEnd.SetTab(nTab1 + nTabSpan);
- ScExternalRefCache::TokenArrayRef pArray;
pArray.reset(lcl_convertToTokenArray(pSrcDoc, aRange, aCacheData));
if (pArray)
// Cache these values.
- maRefCache.setCellRangeData(nFileId, rRange, aCacheData, pArray);
+ maRefCache.setCellRangeData(nFileId, aRange, aCacheData, pArray);
+ else
+ {
+ // Array is empty. Fill it with an empty matrix of the required size.
+ pArray.reset(lcl_fillEmptyMatrix(rRange));
+
+ // Make sure to set this range 'cached', to prevent unnecessarily
+ // accessing the src document time and time again.
+ ScExternalRefCache::TableTypeRef pCacheTab =
+ maRefCache.getCacheTable(nFileId, rTabName, true, NULL);
+ if (pCacheTab)
+ pCacheTab->setCachedCellRange(
+ rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row());
+ }
return pArray;
}
@@ -1858,8 +1907,8 @@ void ScExternalRefManager::refreshAllRefCells(sal_uInt16 nFileId)
if (itrFile == maRefCells.end())
return;
- RefCells& rRefCells = itrFile->second;
- rRefCells.refreshAllCells(*this);
+ RefCellSet& rRefCells = itrFile->second;
+ for_each(rRefCells.begin(), rRefCells.end(), UpdateFormulaCell());
ScViewData* pViewData = ScDocShell::GetViewData();
if (!pViewData)
@@ -1880,7 +1929,7 @@ void ScExternalRefManager::insertRefCell(sal_uInt16 nFileId, const ScAddress& rC
RefCellMap::iterator itr = maRefCells.find(nFileId);
if (itr == maRefCells.end())
{
- RefCells aRefCells;
+ RefCellSet aRefCells;
pair<RefCellMap::iterator, bool> r = maRefCells.insert(
RefCellMap::value_type(nFileId, aRefCells));
if (!r.second)
@@ -1889,7 +1938,10 @@ void ScExternalRefManager::insertRefCell(sal_uInt16 nFileId, const ScAddress& rC
itr = r.first;
}
- itr->second.insertCell(rCell);
+
+ ScBaseCell* pCell = mpDoc->GetCell(rCell);
+ if (pCell && pCell->GetCellType() == CELLTYPE_FORMULA)
+ itr->second.insert(static_cast<ScFormulaCell*>(pCell));
}
ScDocument* ScExternalRefManager::getSrcDocument(sal_uInt16 nFileId)
@@ -1902,6 +1954,12 @@ ScDocument* ScExternalRefManager::getSrcDocument(sal_uInt16 nFileId)
if (itr != itrEnd)
{
+ // document already loaded.
+
+ // TODO: Find out a way to access a document that's already open in
+ // memory and re-use that instance, instead of loading it from the
+ // disk again.
+
SfxObjectShell* p = itr->second.maShell;
itr->second.maLastAccess = Time();
return static_cast<ScDocShell*>(p)->GetDocument();
@@ -1996,7 +2054,8 @@ SfxObjectShellRef ScExternalRefManager::loadSrcDocument(sal_uInt16 nFileId, Stri
if (pMedium->GetError() != ERRCODE_NONE)
return NULL;
- pMedium->UseInteractionHandler(false);
+ // To load encrypted documents with password, user interaction needs to be enabled.
+ pMedium->UseInteractionHandler(mbUserInteractionEnabled);
ScDocShell* pNewShell = new ScDocShell(SFX_CREATE_MODE_INTERNAL);
SfxObjectShellRef aRef = pNewShell;
@@ -2005,6 +2064,10 @@ SfxObjectShellRef ScExternalRefManager::loadSrcDocument(sal_uInt16 nFileId, Stri
ScExtDocOptions* pExtOpt = mpDoc->GetExtDocOptions();
sal_uInt32 nLinkCount = pExtOpt ? pExtOpt->GetDocSettings().mnLinkCnt : 0;
ScDocument* pSrcDoc = pNewShell->GetDocument();
+ pSrcDoc->EnableExecuteLink(false); // to prevent circular access of external references.
+ pSrcDoc->EnableUndo(false);
+ pSrcDoc->EnableAdjustHeight(false);
+
ScExtDocOptions* pExtOptNew = pSrcDoc->GetExtDocOptions();
if (!pExtOptNew)
{
@@ -2082,35 +2145,6 @@ void ScExternalRefManager::maybeCreateRealFileName(sal_uInt16 nFileId)
maSrcFiles[nFileId].maybeCreateRealFileName(getOwnDocumentName());
}
-bool ScExternalRefManager::compileTokensByCell(const ScAddress& rCell)
-{
- ScBaseCell* pCell;
- mpDoc->GetCell(rCell.Col(), rCell.Row(), rCell.Tab(), pCell);
-
- if (!pCell || pCell->GetCellType() != CELLTYPE_FORMULA)
- return false;
-
- ScFormulaCell* pFC = static_cast<ScFormulaCell*>(pCell);
-
- // Check to make sure the cell really contains ocExternalRef.
- // External names, external cell and range references all have a
- // ocExternalRef token.
- const ScTokenArray* pCode = pFC->GetCode();
- if (!pCode->HasOpCode( ocExternalRef))
- return false;
-
- ScTokenArray* pArray = pFC->GetCode();
- if (pArray)
- // Clear the error code, or a cell with error won't get re-compiled.
- pArray->SetCodeError(0);
-
- pFC->SetCompile(true);
- pFC->CompileTokenArray();
- pFC->SetDirty();
-
- return true;
-}
-
const String& ScExternalRefManager::getOwnDocumentName() const
{
SfxObjectShell* pShell = mpDoc->GetDocumentShell();
@@ -2222,6 +2256,18 @@ void ScExternalRefManager::refreshNames(sal_uInt16 nFileId)
void ScExternalRefManager::breakLink(sal_uInt16 nFileId)
{
+ // Turn all formula cells referencing this external document into static
+ // cells.
+ RefCellMap::iterator itrRefs = maRefCells.find(nFileId);
+ if (itrRefs != maRefCells.end())
+ {
+ // Make a copy because removing the formula cells below will modify
+ // the original container.
+ RefCellSet aSet = itrRefs->second;
+ for_each(aSet.begin(), aSet.end(), ConvertFormulaToStatic(mpDoc));
+ maRefCells.erase(nFileId);
+ }
+
lcl_removeByFileId(nFileId, maDocShells);
if (maDocShells.empty())
@@ -2293,32 +2339,9 @@ void ScExternalRefManager::resetSrcFileData(const String& rBaseFileUrl)
}
}
-void ScExternalRefManager::updateRefCell(const ScAddress& rOldPos, const ScAddress& rNewPos, bool bCopy)
-{
- for (RefCellMap::iterator itr = maRefCells.begin(), itrEnd = maRefCells.end(); itr != itrEnd; ++itr)
- {
- if (!bCopy)
- itr->second.removeCell(rOldPos);
- itr->second.insertCell(rNewPos);
- }
-}
-
-void ScExternalRefManager::updateRefMoveTable(SCTAB nOldTab, SCTAB nNewTab, bool bCopy)
-{
- for (RefCellMap::iterator itr = maRefCells.begin(), itrEnd = maRefCells.end(); itr != itrEnd; ++itr)
- itr->second.moveTable(nOldTab, nNewTab, bCopy);
-}
-
-void ScExternalRefManager::updateRefInsertTable(SCTAB nPos)
-{
- for (RefCellMap::iterator itr = maRefCells.begin(), itrEnd = maRefCells.end(); itr != itrEnd; ++itr)
- itr->second.insertTable(nPos);
-}
-
-void ScExternalRefManager::updateRefDeleteTable(SCTAB nPos)
+void ScExternalRefManager::removeRefCell(ScFormulaCell* pCell)
{
- for (RefCellMap::iterator itr = maRefCells.begin(), itrEnd = maRefCells.end(); itr != itrEnd; ++itr)
- itr->second.removeTable(nPos);
+ for_each(maRefCells.begin(), maRefCells.end(), RemoveFormulaCell(pCell));
}
void ScExternalRefManager::addLinkListener(sal_uInt16 nFileId, LinkListener* pListener)
diff --git a/sc/source/ui/drawfunc/drtxtob.cxx b/sc/source/ui/drawfunc/drtxtob.cxx
index ece7c4ad6c3a..bfbeba2d1302 100644
--- a/sc/source/ui/drawfunc/drtxtob.cxx
+++ b/sc/source/ui/drawfunc/drtxtob.cxx
@@ -32,6 +32,9 @@
//-------------------------------------------------------------------------
+#include <com/sun/star/linguistic2/XThesaurus.hpp>
+#include <com/sun/star/lang/Locale.hpp>
+
#include "scitems.hxx"
#include <editeng/adjitem.hxx>
@@ -46,6 +49,7 @@
#include <svx/hlnkitem.hxx>
#include <editeng/lspcitem.hxx>
#include <svx/svdoutl.hxx>
+#include <editeng/unolingu.hxx>
#include <editeng/outlobj.hxx>
#include <editeng/postitem.hxx>
#include <editeng/scripttypeitem.hxx>
@@ -71,6 +75,7 @@
#include "sc.hrc"
#include "globstr.hrc"
+#include "scmod.hxx"
#include "drtxtob.hxx"
#include "fudraw.hxx"
#include "viewdata.hxx"
@@ -83,6 +88,10 @@
#define ScDrawTextObjectBar
#include "scslots.hxx"
+
+using namespace ::com::sun::star;
+
+
SFX_IMPL_INTERFACE( ScDrawTextObjectBar, SfxShell, ScResId(SCSTR_DRAWTEXTSHELL) )
{
SFX_OBJECTBAR_REGISTRATION( SFX_OBJECTBAR_OBJECT|SFX_VISIBILITY_STANDARD|SFX_VISIBILITY_SERVER,
@@ -363,6 +372,24 @@ void __EXPORT ScDrawTextObjectBar::Execute( SfxRequest &rReq )
ExecuteGlobal( rReq );
break;
#endif
+
+ case SID_THES:
+ {
+ String aReplaceText;
+ SFX_REQUEST_ARG( rReq, pItem2, SfxStringItem, SID_THES, sal_False );
+ if (pItem2)
+ aReplaceText = pItem2->GetValue();
+ if (aReplaceText.Len() > 0)
+ ReplaceTextWithSynonym( pOutView->GetEditView(), aReplaceText );
+ }
+ break;
+
+ case SID_THESAURUS:
+ {
+ pOutView->StartThesaurus();
+ }
+ break;
+
}
}
@@ -454,6 +481,25 @@ void __EXPORT ScDrawTextObjectBar::GetState( SfxItemSet& rSet )
rSet.Put( SfxBoolItem( SID_ENABLE_HYPHENATION, bValue ) );
}
}
+
+ if ( rSet.GetItemState( SID_THES ) != SFX_ITEM_UNKNOWN ||
+ rSet.GetItemState( SID_THESAURUS ) != SFX_ITEM_UNKNOWN )
+ {
+ SdrView * pView = pViewData->GetScDrawView();
+ EditView & rEditView = pView->GetTextEditOutlinerView()->GetEditView();
+
+ String aStatusVal;
+ LanguageType nLang = LANGUAGE_NONE;
+ bool bIsLookUpWord = GetStatusValueForThesaurusFromContext( aStatusVal, nLang, rEditView );
+ rSet.Put( SfxStringItem( SID_THES, aStatusVal ) );
+
+ // disable thesaurus main menu and context menu entry if there is nothing to look up
+ BOOL bCanDoThesaurus = ScModule::HasThesaurusLanguage( nLang );
+ if (!bIsLookUpWord || !bCanDoThesaurus)
+ rSet.DisableItem( SID_THES );
+ if (!bCanDoThesaurus)
+ rSet.DisableItem( SID_THESAURUS );
+ }
}
IMPL_LINK( ScDrawTextObjectBar, ClipboardChanged, TransferableDataHelper*, pDataHelper )
diff --git a/sc/source/ui/unoobj/cellsuno.cxx b/sc/source/ui/unoobj/cellsuno.cxx
index afe29a8309a7..980a73307797 100644
--- a/sc/source/ui/unoobj/cellsuno.cxx
+++ b/sc/source/ui/unoobj/cellsuno.cxx
@@ -5265,6 +5265,8 @@ void SAL_CALL ScCellRangeObj::setFormulaArray(
ScDocShell* pDocSh = GetDocShell();
if (pDocSh)
{
+ ScExternalRefManager::ApiGuard aExtRefGuard(pDocSh->GetDocument());
+
// GRAM_PODF_A1 for API compatibility.
bDone = lcl_PutFormulaArray( *pDocSh, aRange, aArray, EMPTY_STRING, formula::FormulaGrammar::GRAM_PODF_A1 );
}
diff --git a/sc/source/ui/unoobj/linkuno.cxx b/sc/source/ui/unoobj/linkuno.cxx
index 6d9fcd1d23e4..a119eda13a32 100644
--- a/sc/source/ui/unoobj/linkuno.cxx
+++ b/sc/source/ui/unoobj/linkuno.cxx
@@ -1605,12 +1605,16 @@ ScExternalDocLinkObj::~ScExternalDocLinkObj()
}
Reference< sheet::XExternalSheetCache > SAL_CALL ScExternalDocLinkObj::addSheetCache(
- const OUString& aSheetName )
+ const OUString& aSheetName, sal_Bool bDynamicCache )
throw (RuntimeException)
{
ScUnoGuard aGuard;
size_t nIndex = 0;
ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, aSheetName, true, &nIndex);
+ if (!bDynamicCache)
+ // Set the whole table cached to prevent access to the source document.
+ pTable->setWholeTableCached();
+
Reference< sheet::XExternalSheetCache > aSheetCache(new ScExternalSheetCacheObj(pTable, nIndex));
return aSheetCache;
}
diff --git a/sc/source/ui/unoobj/tokenuno.cxx b/sc/source/ui/unoobj/tokenuno.cxx
index fc14b53a6372..5e3b3102e14a 100644
--- a/sc/source/ui/unoobj/tokenuno.cxx
+++ b/sc/source/ui/unoobj/tokenuno.cxx
@@ -140,9 +140,11 @@ uno::Sequence<sheet::FormulaToken> SAL_CALL ScFormulaParserObj::parseFormula(
if (mpDocShell)
{
+ ScDocument* pDoc = mpDocShell->GetDocument();
+ ScExternalRefManager::ApiGuard aExtRefGuard(pDoc);
+
ScAddress aRefPos( ScAddress::UNINITIALIZED );
ScUnoConversion::FillScAddress( aRefPos, rReferencePos );
- ScDocument* pDoc = mpDocShell->GetDocument();
ScCompiler aCompiler( pDoc, aRefPos);
aCompiler.SetGrammar(pDoc->GetGrammar());
SetCompilerFlags( aCompiler );
diff --git a/sc/source/ui/view/editsh.cxx b/sc/source/ui/view/editsh.cxx
index d228a205a5a3..848a0a3c7636 100644
--- a/sc/source/ui/view/editsh.cxx
+++ b/sc/source/ui/view/editsh.cxx
@@ -32,13 +32,16 @@
//------------------------------------------------------------------
+#include <com/sun/star/linguistic2/XThesaurus.hpp>
+
#include "scitems.hxx"
#include <editeng/eeitem.hxx>
#include <svx/clipfmtitem.hxx>
#include <svx/svxdlg.hxx>
#include <editeng/cntritem.hxx>
-//CHINA001 #include <svx/chardlg.hxx>
+#include <editeng/outliner.hxx>
+#include <editeng/unolingu.hxx>
#include <editeng/crsditem.hxx>
#include <editeng/editeng.hxx>
#include <editeng/editview.hxx>
@@ -91,6 +94,11 @@
#include "scui_def.hxx" //CHINA001
#include "scabstdlg.hxx" //CHINA001
+
+
+using namespace ::com::sun::star;
+
+
TYPEINIT1( ScEditShell, SfxShell );
SFX_IMPL_INTERFACE(ScEditShell, SfxShell, ScResId(SCSTR_EDITSHELL))
@@ -213,6 +221,17 @@ void ScEditShell::Execute( SfxRequest& rReq )
}
break;
+ case SID_THES:
+ {
+ String aReplaceText;
+ SFX_REQUEST_ARG( rReq, pItem2, SfxStringItem, SID_THES , sal_False );
+ if (pItem2)
+ aReplaceText = pItem2->GetValue();
+ if (aReplaceText.Len() > 0)
+ ReplaceTextWithSynonym( *pEditView, aReplaceText );
+ }
+ break;
+
case SID_COPY:
pTableView->Copy();
break;
@@ -680,6 +699,22 @@ void __EXPORT ScEditShell::GetState( SfxItemSet& rSet )
case SID_INSERT_ZWSP:
ScViewUtil::HideDisabledSlot( rSet, pViewData->GetBindings(), nWhich );
break;
+
+ case SID_THES:
+ {
+ String aStatusVal;
+ LanguageType nLang = LANGUAGE_NONE;
+ bool bIsLookUpWord = GetStatusValueForThesaurusFromContext( aStatusVal, nLang, *pActiveView );
+ rSet.Put( SfxStringItem( SID_THES, aStatusVal ) );
+
+ // disable thesaurus context menu entry if there is nothing to look up
+ BOOL bCanDoThesaurus = ScModule::HasThesaurusLanguage( nLang );
+ if (!bIsLookUpWord || !bCanDoThesaurus)
+ rSet.DisableItem( SID_THES );
+ }
+ break;
+
+
}
nWhich = aIter.NextWhich();
}
diff --git a/sc/source/ui/view/output2.cxx b/sc/source/ui/view/output2.cxx
index 5a48d0d310d5..37bc941c0f16 100644
--- a/sc/source/ui/view/output2.cxx
+++ b/sc/source/ui/view/output2.cxx
@@ -623,7 +623,7 @@ long ScDrawStringsVars::GetMaxDigitWidth()
return nMaxDigitWidth;
sal_Char cZero = '0';
- for (int i = 0; i < 10; ++i)
+ for (sal_Char i = 0; i < 10; ++i)
{
sal_Char cDigit = cZero + i;
long n = pOutput->pFmtDevice->GetTextWidth(String(cDigit));
diff --git a/sc/source/ui/view/viewutil.cxx b/sc/source/ui/view/viewutil.cxx
index f73346398ea1..d887aec8bc5b 100644
--- a/sc/source/ui/view/viewutil.cxx
+++ b/sc/source/ui/view/viewutil.cxx
@@ -52,6 +52,8 @@
#include <svl/eitem.hxx>
#include <com/sun/star/i18n/TransliterationModules.hpp>
+#include <com/sun/star/i18n/TransliterationModulesExtra.hpp>
+
#include "viewutil.hxx"
#include "global.hxx"
@@ -120,6 +122,15 @@ sal_Int32 ScViewUtil::GetTransliterationType( USHORT nSlotID )
sal_Int32 nType = 0;
switch ( nSlotID )
{
+ case SID_TRANSLITERATE_SENTENCE_CASE:
+ nType = com::sun::star::i18n::TransliterationModulesExtra::SENTENCE_CASE;
+ break;
+ case SID_TRANSLITERATE_TITLE_CASE:
+ nType = com::sun::star::i18n::TransliterationModulesExtra::TITLE_CASE;
+ break;
+ case SID_TRANSLITERATE_TOGGLE_CASE:
+ nType = com::sun::star::i18n::TransliterationModulesExtra::TOGGLE_CASE;
+ break;
case SID_TRANSLITERATE_UPPER:
nType = com::sun::star::i18n::TransliterationModules_LOWERCASE_UPPERCASE;
break;
diff --git a/sc/uiconfig/scalc/menubar/menubar.xml b/sc/uiconfig/scalc/menubar/menubar.xml
index 949b1a10b619..da8e6efdad55 100644
--- a/sc/uiconfig/scalc/menubar/menubar.xml
+++ b/sc/uiconfig/scalc/menubar/menubar.xml
@@ -234,8 +234,11 @@
<menu:menuitem menu:id=".uno:ParagraphDialog"/>
<menu:menu menu:id=".uno:TransliterateMenu">
<menu:menupopup>
- <menu:menuitem menu:id=".uno:ChangeCaseToUpper"/>
+ <menu:menuitem menu:id=".uno:ChangeCaseToSentenceCase"/>
<menu:menuitem menu:id=".uno:ChangeCaseToLower"/>
+ <menu:menuitem menu:id=".uno:ChangeCaseToUpper"/>
+ <menu:menuitem menu:id=".uno:ChangeCaseToTitleCase"/>
+ <menu:menuitem menu:id=".uno:ChangeCaseToToggleCase"/>
<menu:menuitem menu:id=".uno:ChangeCaseToHalfWidth"/>
<menu:menuitem menu:id=".uno:ChangeCaseToFullWidth"/>
<menu:menuitem menu:id=".uno:ChangeCaseToHiragana"/>
@@ -311,7 +314,7 @@
<menu:menupopup>
<menu:menuitem menu:id=".uno:HangulHanjaConversion"/>
<menu:menuitem menu:id=".uno:ChineseConversion"/>
- <menu:menuitem menu:id=".uno:Thesaurus"/>
+ <menu:menuitem menu:id=".uno:ThesaurusDialog"/>
<menu:menuitem menu:id=".uno:Hyphenate"/>
<menu:menuseparator/>
<menu:menuitem menu:id=".uno:MoreDictionaries"/>
diff --git a/sc/uiconfig/scalc/toolbar/findbar.xml b/sc/uiconfig/scalc/toolbar/findbar.xml
new file mode 100644
index 000000000000..9ef9d8a1a78f
--- /dev/null
+++ b/sc/uiconfig/scalc/toolbar/findbar.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE toolbar:toolbar PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "toolbar.dtd">
+<toolbar:toolbar xmlns:toolbar="http://openoffice.org/2001/toolbar" xmlns:xlink="http://www.w3.org/1999/xlink" toolbar:id="toolbar">
+ <toolbar:toolbaritem xlink:href=".uno:FindText" toolbar:helpid="helpid:100105" />
+ <toolbar:toolbaritem xlink:href=".uno:DownSearch" toolbar:helpid="helpid:100105" />
+ <toolbar:toolbaritem xlink:href=".uno:UpSearch" toolbar:helpid="helpid:100105" />
+ <toolbar:toolbaritem xlink:href=".uno:SearchDialog" toolbar:text="Find &amp; Replace" toolbar:visible="false" toolbar:helpid="helpid:100105"/>
+</toolbar:toolbar>
diff --git a/sc/uiconfig/scalc/toolbar/toolbar.xml b/sc/uiconfig/scalc/toolbar/toolbar.xml
index 6a34de3a4ebd..e42964a86b0b 100644
--- a/sc/uiconfig/scalc/toolbar/toolbar.xml
+++ b/sc/uiconfig/scalc/toolbar/toolbar.xml
@@ -8,7 +8,7 @@
<toolbar:toolbarseparator/>
<toolbar:toolbaritem xlink:href=".uno:AutoFormat" toolbar:helpid="helpid:10242" />
<toolbar:toolbaritem xlink:href=".uno:ChooseDesign" toolbar:helpid="helpid:26082" />
- <toolbar:toolbaritem xlink:href=".uno:Thesaurus" toolbar:helpid="helpid:10245" toolbar:visible="false" />
+ <toolbar:toolbaritem xlink:href=".uno:ThesaurusDialog" toolbar:helpid="helpid:10245" toolbar:visible="false" />
<toolbar:toolbarseparator/>
<toolbar:toolbaritem xlink:href=".uno:DataFilterAutoFilter" toolbar:helpid="helpid:26325" />
<toolbar:toolbaritem xlink:href=".uno:DataFilterStandardFilter" toolbar:helpid="helpid:26323" toolbar:visible="false" />
@@ -20,4 +20,4 @@
<toolbar:toolbaritem xlink:href=".uno:GoalSeekDialog" toolbar:helpid="helpid:26153" toolbar:visible="false" />
<toolbar:toolbaritem xlink:href=".uno:Group" toolbar:helpid="helpid:26331" />
<toolbar:toolbaritem xlink:href=".uno:Ungroup" toolbar:helpid="helpid:26332" />
-</toolbar:toolbar> \ No newline at end of file
+</toolbar:toolbar>