summaryrefslogtreecommitdiff
path: root/sc/source
diff options
context:
space:
mode:
authorRĂ¼diger Timm <rt@openoffice.org>2008-12-12 09:38:47 +0000
committerRĂ¼diger Timm <rt@openoffice.org>2008-12-12 09:38:47 +0000
commit47b1cc26c2697d81b44be5fb53598321cbc5d827 (patch)
tree38848d46028498de77cf271535fffac1954ad237 /sc/source
parenta190965485508c4493ee33228dae68e12cd858f9 (diff)
CWS-TOOLING: integrate CWS mooxlsc
2008-12-12 09:32:19 +0100 dr r265390 : #i10000# warning 2008-12-11 14:54:26 +0100 dr r265301 : add strings from dr66 to meet ui freeze 2008-12-11 14:53:20 +0100 dr r265300 : add strings from dr66 to meet ui freeze 2008-12-08 14:43:25 +0100 er r264997 : DBG_... need semicolon 2008-12-04 19:16:50 +0100 er r264872 : DBG_... needs semicolon 2008-12-04 11:09:27 +0100 er r264824 : DBG_ERROR needs semicolon 2008-12-03 13:29:46 +0100 er r264770 : CWS-TOOLING: rebase CWS mooxlsc to trunk@264325 (milestone: DEV300:m36) 2008-12-02 16:49:09 +0100 er r264722 : disable code for named references #i4385# import as long as #i3740# isn't fully implemented 2008-12-02 16:45:04 +0100 er r264721 : some compilers attempt to be too smart; persuade them it's really meant what was written 2008-12-02 16:04:56 +0100 er r264715 : #i3740# no storage in ODF for external name references 2008-11-29 02:20:50 +0100 er r264575 : some huge performance improvement when reading repeated empty rows for the external references cache from ODF, as they often occur in the sparse matrix 2008-11-29 01:14:55 +0100 er r264574 : WriteExternalRefCaches: for table:number-columns-repeated write used columns instead of MAXCOLCOUNT 2008-11-28 18:30:04 +0100 er r264570 : #i3740# write/read external name references as bracketed references, as proposed on the ODFF list 2008-11-27 20:36:54 +0100 er r264521 : merge i95068 from cws calc46 for code correctness 2008-11-21 20:39:34 +0100 kohei r264174 : fixed a crash when importing a BIFF8 document with per-sheet external names. For now, we don't support per-sheet external names. Let's throw in NoName error until they are supported. 2008-11-21 18:47:27 +0100 kohei r264168 : I forgot to process cached range references in the EXTERNNAME record, which prevented cached external names with range references from being imported correctly. P.S. I swear I thought I had covered this.... 2008-11-20 23:07:22 +0100 er r264104 : #i4385# parse external defined names in MOOXML import 2008-11-14 23:18:54 +0100 er r263700 : #i92797# parse external sheet references under aspects of MOOXML import and new ScExternalRefManager 2008-11-14 18:49:48 +0100 er r263696 : remove infinity assertion, leftover from binary file format; coded double error may occur via filter import 2008-11-12 13:29:44 +0100 er r263593 : make references to entire rows/columns, such as A:A or 3:3, actually work in MOOXML import 2008-11-03 12:35:11 +0100 er r263282 : a struct is a struct is a ... 2008-10-31 00:30:59 +0100 er r262843 : aTableRowCellAttrTokenMap needed 2008-10-31 00:26:07 +0100 er r262842 : GetTableRowCellAttrTokenMap() is not unused 2008-10-31 00:13:53 +0100 er r262841 : merge error 2008-10-31 00:05:39 +0100 er r262840 : merge error 2008-10-30 23:17:48 +0100 er r262839 : unresolved merge conflict!?! 2008-10-30 22:59:11 +0100 er r262838 : merge error 2008-10-30 16:31:04 +0100 hr r262833 : CWS-TOOLING: rebase CWS mooxlsc to trunk@262620 (milestone: DEV300:m34) 2008-10-16 21:57:51 +0200 er r262272 : migrate CWS mooxlsc to SVN
Diffstat (limited to 'sc/source')
-rw-r--r--sc/source/core/data/cell.cxx28
-rw-r--r--sc/source/core/data/cell2.cxx13
-rw-r--r--sc/source/core/data/documen2.cxx15
-rw-r--r--sc/source/core/data/documen3.cxx33
-rw-r--r--sc/source/core/data/documen8.cxx28
-rw-r--r--sc/source/core/data/document.cxx11
-rw-r--r--sc/source/core/data/global.cxx70
-rw-r--r--sc/source/core/inc/interpre.hxx3
-rw-r--r--sc/source/core/tool/address.cxx782
-rw-r--r--sc/source/core/tool/compiler.cxx1528
-rw-r--r--sc/source/core/tool/interpr4.cxx80
-rw-r--r--sc/source/core/tool/refdata.cxx4
-rw-r--r--sc/source/core/tool/token.cxx411
-rw-r--r--sc/source/filter/excel/excform.cxx8
-rw-r--r--sc/source/filter/excel/excform8.cxx340
-rw-r--r--sc/source/filter/excel/makefile.mk1
-rw-r--r--sc/source/filter/excel/read.cxx2
-rw-r--r--sc/source/filter/excel/tokstack.cxx115
-rw-r--r--sc/source/filter/excel/xeformula.cxx191
-rw-r--r--sc/source/filter/excel/xelink.cxx650
-rw-r--r--sc/source/filter/excel/xicontent.cxx2
-rw-r--r--sc/source/filter/excel/xilink.cxx293
-rw-r--r--sc/source/filter/excel/xltracer.cxx7
-rw-r--r--sc/source/filter/ftools/ftools.cxx2
-rw-r--r--sc/source/filter/inc/XclImpChangeTrack.hxx6
-rw-r--r--sc/source/filter/inc/excform.hxx27
-rw-r--r--sc/source/filter/inc/tokstack.hxx51
-rw-r--r--sc/source/filter/inc/xelink.hxx15
-rw-r--r--sc/source/filter/inc/xilink.hxx24
-rw-r--r--sc/source/filter/inc/xltracer.hxx1
-rw-r--r--sc/source/filter/xcl97/XclImpChangeTrack.cxx23
-rw-r--r--sc/source/filter/xml/XMLDDELinksContext.cxx3
-rw-r--r--sc/source/filter/xml/XMLTableShapeImportHelper.cxx3
-rw-r--r--sc/source/filter/xml/XMLTrackedChangesContext.cxx3
-rw-r--r--sc/source/filter/xml/makefile.mk4
-rw-r--r--sc/source/filter/xml/xmlbodyi.cxx3
-rw-r--r--sc/source/filter/xml/xmlcelli.cxx284
-rw-r--r--sc/source/filter/xml/xmlcelli.hxx4
-rw-r--r--sc/source/filter/xml/xmldpimp.cxx3
-rw-r--r--sc/source/filter/xml/xmlexprt.cxx586
-rw-r--r--sc/source/filter/xml/xmlexprt.hxx9
-rw-r--r--sc/source/filter/xml/xmlexternaltabi.cxx361
-rw-r--r--sc/source/filter/xml/xmlexternaltabi.hxx150
-rw-r--r--sc/source/filter/xml/xmlimprt.cxx73
-rw-r--r--sc/source/filter/xml/xmlimprt.hxx13
-rw-r--r--sc/source/filter/xml/xmlsceni.cxx3
-rw-r--r--sc/source/filter/xml/xmlstyle.cxx3
-rw-r--r--sc/source/filter/xml/xmlstyle.hxx4
-rw-r--r--sc/source/filter/xml/xmlstyli.cxx52
-rw-r--r--sc/source/filter/xml/xmlstyli.hxx4
-rw-r--r--sc/source/filter/xml/xmltabi.cxx123
-rw-r--r--sc/source/filter/xml/xmltabi.hxx17
-rw-r--r--sc/source/filter/xml/xmlwrap.cxx1
-rw-r--r--sc/source/ui/dbgui/validate.cxx8
-rw-r--r--sc/source/ui/docshell/docsh4.cxx2
-rw-r--r--sc/source/ui/docshell/externalrefmgr.cxx1923
-rw-r--r--sc/source/ui/docshell/makefile.mk6
-rw-r--r--sc/source/ui/src/globstr.src8
-rw-r--r--sc/source/ui/unoobj/cellsuno.cxx11
-rw-r--r--sc/source/ui/unoobj/docuno.cxx5
-rw-r--r--sc/source/ui/unoobj/fmtuno.cxx8
-rw-r--r--sc/source/ui/unoobj/linkuno.cxx340
-rw-r--r--sc/source/ui/unoobj/nameuno.cxx17
-rw-r--r--sc/source/ui/unoobj/tokenuno.cxx171
-rw-r--r--sc/source/ui/view/tabvwsh4.cxx10
65 files changed, 7550 insertions, 1429 deletions
diff --git a/sc/source/core/data/cell.cxx b/sc/source/core/data/cell.cxx
index 92115b6191be..efdbc0bdd849 100644
--- a/sc/source/core/data/cell.cxx
+++ b/sc/source/core/data/cell.cxx
@@ -81,12 +81,6 @@ IMPL_FIXEDMEMPOOL_NEWDEL( ScStringCell, nMemPoolStringCell, nMemPoolStringCell
IMPL_FIXEDMEMPOOL_NEWDEL( ScNoteCell, nMemPoolNoteCell, nMemPoolNoteCell )
#endif
-#ifndef PRODUCT
-static const sal_Char __FAR_DATA msgDbgInfinity[] =
- "Formelzelle INFINITY ohne Err503 !!! (os/2?)\n"
- "NICHTS anruehren und ER bescheid sagen!";
-#endif
-
// -----------------------------------------------------------------------
ScBaseCell::ScBaseCell( CellType eNewType ) :
@@ -683,7 +677,12 @@ ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rNewPos,
for( ScToken* t = pCode->GetNextReferenceOrName(); t && !bCompile;
t = pCode->GetNextReferenceOrName() )
{
- if ( t->GetType() == svIndex )
+ if ( t->GetOpCode() == ocExternalRef )
+ {
+ // External name, cell, and area references.
+ bCompile = true;
+ }
+ else if ( t->GetType() == svIndex )
{
ScRangeData* pRangeData = pDoc->GetRangeName()->FindIndex( t->GetIndex() );
if( pRangeData )
@@ -1540,6 +1539,13 @@ void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam )
if( cMatrixFlag != MM_FORMULA && !pCode->IsHyperLink() )
aResult.SetToken( aResult.GetCellResultToken());
}
+ if ( aResult.IsValue() && !::rtl::math::isFinite( aResult.GetDouble() ) )
+ {
+ // Coded double error may occur via filter import.
+ USHORT nErr = GetDoubleErrorValue( aResult.GetDouble());
+ aResult.SetResultError( nErr);
+ bChanged = true;
+ }
if( bChanged )
{
SetTextWidth( TEXTWIDTH_DIRTY );
@@ -1547,14 +1553,6 @@ void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam )
}
if ( !pCode->IsRecalcModeAlways() )
pDocument->RemoveFromFormulaTree( this );
-#ifndef PRODUCT
- if ( aResult.IsValue() && !p->GetError() && !::rtl::math::isFinite( aResult.GetDouble() ) )
- {
- DBG_ERRORFILE( msgDbgInfinity );
- aResult.SetToken( NULL);
- aResult.SetResultError( errIllegalFPOperation );
- }
-#endif
// FORCED Zellen auch sofort auf Gueltigkeit testen (evtl. Makro starten)
diff --git a/sc/source/core/data/cell2.cxx b/sc/source/core/data/cell2.cxx
index 6a2166507382..606a1eaf089b 100644
--- a/sc/source/core/data/cell2.cxx
+++ b/sc/source/core/data/cell2.cxx
@@ -49,7 +49,7 @@
#include "editutil.hxx"
#include "chgtrack.hxx"
#include "indexmap.hxx"
-
+#include "externalrefmgr.hxx"
// STATIC DATA -----------------------------------------------------------
@@ -758,6 +758,17 @@ void ScFormulaCell::UpdateReference(UpdateRefMode eUpdateRefMode,
delete pOld;
}
+
+ pCode->Reset();
+ for ( ScToken* 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/documen2.cxx b/sc/source/core/data/documen2.cxx
index 818748c4a43b..fe87a8a9868f 100644
--- a/sc/source/core/data/documen2.cxx
+++ b/sc/source/core/data/documen2.cxx
@@ -93,6 +93,7 @@
#include "listenercalls.hxx"
#include "recursionhelper.hxx"
#include "lookupcache.hxx"
+#include "externalrefmgr.hxx"
// pImpl because including lookupcache.hxx in document.hxx isn't wanted, and
// dtor plus helpers are convenient.
@@ -150,6 +151,7 @@ ScDocument::ScDocument( ScDocumentMode eMode,
pChangeViewSettings( NULL ),
pScriptTypeData( NULL ),
pCacheFieldEditEngine( NULL ),
+ pExternalRefMgr( NULL ),
pViewOptions( NULL ),
pDocOptions( NULL ),
pExtDocOptions( NULL ),
@@ -380,6 +382,11 @@ ScDocument::~ScDocument()
pLinkManager->Remove( 0, pLinkManager->GetLinks().Count() );
}
+ if (pExternalRefMgr.get())
+ // Destroy the external ref mgr instance here because it has a timer
+ // which needs to be stopped before the app closes.
+ pExternalRefMgr.reset(NULL);
+
ScAddInAsync::RemoveDocument( this );
ScAddInListener::RemoveDocument( this );
delete pChartListenerCollection; // vor pBASM wg. evtl. Listener!
@@ -798,6 +805,10 @@ 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;
}
}
@@ -919,6 +930,10 @@ BOOL ScDocument::CopyTab( SCTAB nOldPos, SCTAB nNewPos, const ScMarkData* pOnlyM
DrawCopyPage( static_cast<sal_uInt16>(nOldPos), static_cast<sal_uInt16>(nNewPos) );
pTab[nNewPos]->SetPageStyle( pTab[nOldPos]->GetPageStyle() );
+
+ // 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 03c8a848de9e..78f708feae8c 100644
--- a/sc/source/core/data/documen3.cxx
+++ b/sc/source/core/data/documen3.cxx
@@ -61,6 +61,7 @@
#include "brdcst.hxx"
#include "bcaslot.hxx"
#include "tablink.hxx"
+#include "externalrefmgr.hxx"
#include "markdata.hxx"
#include "validat.hxx"
#include "dociter.hxx"
@@ -79,7 +80,10 @@
#include "editutil.hxx" // ScPostIt EditTextObject
#include "postit.hxx"
+#include <memory>
+
using namespace com::sun::star;
+using ::std::auto_ptr;
//------------------------------------------------------------------------
@@ -471,33 +475,12 @@ BOOL ScDocument::LinkExternalTab( SCTAB& rTab, const String& aDocTab,
return TRUE;
}
-BOOL ScDocument::InsertLinkedEmptyTab( SCTAB& rnTab, const String& rFileName,
- const String& rFilterName, const String& rFilterOpt, const String& rTabName )
+ScExternalRefManager* ScDocument::GetExternalRefManager()
{
- DBG_ASSERT( !IsClipboard(), "ScDocument::InsertLinkedEmptyTab - not allowed in clipboard" );
- if( IsClipboard() )
- return FALSE;
-
- String aOwnTabName( ScGlobal::GetDocTabName( rFileName, rTabName ) );
- if( !InsertTab( SC_TAB_APPEND, aOwnTabName, TRUE ) )
- return FALSE;
+ if (!pExternalRefMgr.get())
+ pExternalRefMgr.reset(new ScExternalRefManager(this));
- rnTab = GetTableCount() - 1;
-
- ULONG nRefreshDelay = 0;
- BOOL bWasThere = HasLink( rFileName, rFilterName, rFilterOpt );
- SetLink( rnTab, SC_LINK_VALUE, rFileName, rFilterName, rFilterOpt, rTabName, nRefreshDelay );
- if( !bWasThere ) // insert link into link manager only once per external document
- {
- ScTableLink* pLink = new ScTableLink( pShell, rFileName, rFilterName, rFilterOpt, nRefreshDelay );
- pLink->SetInCreate( TRUE );
- pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, rFileName, &rFilterName );
- pLink->Update();
- pLink->SetInCreate( FALSE );
- if( SfxBindings* pBindings = GetViewBindings() )
- pBindings->Invalidate( SID_LINKS );
- }
- return TRUE;
+ return pExternalRefMgr.get();
}
ScOutlineTable* ScDocument::GetOutlineTable( SCTAB nTab, BOOL bCreate )
diff --git a/sc/source/core/data/documen8.cxx b/sc/source/core/data/documen8.cxx
index 4950af648986..0d12c82dec87 100644
--- a/sc/source/core/data/documen8.cxx
+++ b/sc/source/core/data/documen8.cxx
@@ -91,6 +91,7 @@
#include "markdata.hxx"
#include "scmod.hxx"
#include "printopt.hxx"
+#include "externalrefmgr.hxx"
#include "globstr.hrc"
#include "sc.hrc"
#include "charthelper.hxx"
@@ -1021,6 +1022,33 @@ BOOL ScDocument::IsInLinkUpdate() const
return bInLinkUpdate || IsInDdeLinkUpdate();
}
+void ScDocument::UpdateExternalRefLinks()
+{
+ if (!pLinkManager)
+ return;
+
+ const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
+ USHORT nCount = rLinks.Count();
+
+ bool bAny = false;
+ for (USHORT i = 0; i < nCount; ++i)
+ {
+ ::sfx2::SvBaseLink* pBase = *rLinks[i];
+ ScExternalRefLink* pRefLink = dynamic_cast<ScExternalRefLink*>(pBase);
+ if (pRefLink)
+ {
+ pRefLink->Update();
+ bAny = true;
+ }
+ }
+ if (bAny)
+ {
+ TrackFormulas();
+ pShell->Broadcast( SfxSimpleHint(FID_DATACHANGED) );
+ ResetChanged( ScRange(0, 0, 0, MAXCOL, MAXROW, MAXTAB) );
+ }
+}
+
void ScDocument::UpdateDdeLinks()
{
if (pLinkManager)
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 65d4ea9e5a5e..b399ab669677 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -90,6 +90,7 @@
#include "autonamecache.hxx"
#include "bcaslot.hxx"
#include "postit.hxx"
+#include "externalrefmgr.hxx"
struct ScDefaultAttr
{
@@ -336,6 +337,10 @@ 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;
}
@@ -424,6 +429,12 @@ 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;
}
diff --git a/sc/source/core/data/global.cxx b/sc/source/core/data/global.cxx
index ab86890a6363..63709730cf28 100644
--- a/sc/source/core/data/global.cxx
+++ b/sc/source/core/data/global.cxx
@@ -838,15 +838,79 @@ bool ScGlobal::IsQuoted( const String& rString, sal_Unicode cQuote )
return (rString.Len() >= 2) && (rString.GetChar( 0 ) == cQuote) && (rString.GetChar( rString.Len() - 1 ) == cQuote);
}
-void ScGlobal::AddQuotes( String& rString, sal_Unicode cQuote )
+void ScGlobal::AddQuotes( String& rString, sal_Unicode cQuote, bool bEscapeEmbedded )
{
+ if (bEscapeEmbedded)
+ {
+ sal_Unicode pQ[3];
+ pQ[0] = pQ[1] = cQuote;
+ pQ[2] = 0;
+ String aQuotes( pQ );
+ rString.SearchAndReplaceAll( cQuote, aQuotes);
+ }
rString.Insert( cQuote, 0 ).Append( cQuote );
}
-void ScGlobal::EraseQuotes( String& rString, sal_Unicode /* cQuote */ )
+void ScGlobal::EraseQuotes( String& rString, sal_Unicode cQuote, bool bUnescapeEmbedded )
{
- if( IsQuoted( rString ) )
+ if ( IsQuoted( rString, cQuote ) )
+ {
rString.Erase( rString.Len() - 1 ).Erase( 0, 1 );
+ if (bUnescapeEmbedded)
+ {
+ sal_Unicode pQ[3];
+ pQ[0] = pQ[1] = cQuote;
+ pQ[2] = 0;
+ String aQuotes( pQ );
+ rString.SearchAndReplaceAll( aQuotes, cQuote);
+ }
+ }
+}
+
+xub_StrLen ScGlobal::FindUnquoted( const String& rString, sal_Unicode cChar, xub_StrLen nStart, sal_Unicode cQuote )
+{
+ const sal_Unicode* const pStart = rString.GetBuffer();
+ const sal_Unicode* const pStop = pStart + rString.Len();
+ const sal_Unicode* p = pStart + nStart;
+ bool bQuoted = false;
+ while (p < pStop)
+ {
+ if (*p == cChar && !bQuoted)
+ return p - pStart;
+ else if (*p == cQuote)
+ {
+ if (!bQuoted)
+ bQuoted = true;
+ else if (p < pStop-1 && *(p+1) == cQuote)
+ ++p;
+ else
+ bQuoted = false;
+ }
+ ++p;
+ }
+ return STRING_NOTFOUND;
+}
+
+const sal_Unicode* ScGlobal::FindUnquoted( const sal_Unicode* pString, sal_Unicode cChar, sal_Unicode cQuote )
+{
+ const sal_Unicode* p = pString;
+ bool bQuoted = false;
+ while (*p)
+ {
+ if (*p == cChar && !bQuoted)
+ return p;
+ else if (*p == cQuote)
+ {
+ if (!bQuoted)
+ bQuoted = true;
+ else if (*(p+1) == cQuote)
+ ++p;
+ else
+ bQuoted = false;
+ }
+ ++p;
+ }
+ return NULL;
}
//------------------------------------------------------------------------
diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
index 41cb25db5edb..33be2faec46f 100644
--- a/sc/source/core/inc/interpre.hxx
+++ b/sc/source/core/inc/interpre.hxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: interpre.hxx,v $
- * $Revision: 1.36 $
+ * $Revision: 1.35.44.2 $
*
* This file is part of OpenOffice.org.
*
@@ -505,6 +505,7 @@ BOOL SetSbxVariable( SbxVariable* pVar, SCCOL nCol, SCROW nRow, SCTAB nTab );
void ScErrorType();
void ScDBArea();
void ScColRowNameAuto();
+void ScExternalRef();
void ScGetPivotData();
void ScHyperLink();
void ScBahtText();
diff --git a/sc/source/core/tool/address.cxx b/sc/source/core/tool/address.cxx
index 49e63ce78f34..40ab0df07c96 100644
--- a/sc/source/core/tool/address.cxx
+++ b/sc/source/core/tool/address.cxx
@@ -35,12 +35,15 @@
#include "global.hxx"
#include "compiler.hxx"
#include "document.hxx"
+#include "externalrefmgr.hxx"
#include "globstr.hrc"
#include <sal/alloca.h>
#include <com/sun/star/frame/XModel.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/sheet/ExternalLinkInfo.hpp>
+#include <com/sun/star/sheet/ExternalLinkType.hpp>
#include <sfx2/objsh.hxx>
#include <tools/urlobj.hxx>
using namespace ::com::sun::star;
@@ -68,6 +71,49 @@ void ScAddress::Details::SetPos ( const ScDocument* pDoc,
#include <iostream>
+/**
+ * Parse from the opening single quote to the closing single quote. Inside
+ * the quotes, a single quote character is encoded by double single-quote
+ * characters.
+ *
+ * @param p pointer to the first character to begin parsing.
+ * @param rName (reference) parsed name within the quotes. If the name is
+ * empty, either the parsing failed or it's an empty quote.
+ *
+ * @return pointer to the character immediately after the closing single
+ * quote.
+ */
+static const sal_Unicode* lcl_ParseQuotedName( const sal_Unicode* p, String& rName )
+{
+ rName.Erase();
+ if (*p != '\'')
+ return p;
+
+ const sal_Unicode* pStart = p;
+ sal_Unicode cPrev = 0;
+ for (++p; *p; ++p)
+ {
+ if (*p == '\'')
+ {
+ if (cPrev == '\'')
+ {
+ // double single-quote equals one single quote.
+ rName += *p;
+ cPrev = 0;
+ continue;
+ }
+ }
+ else if (cPrev == '\'')
+ // We are past the closing quote. We're done!
+ return p;
+ else
+ rName += *p;
+ cPrev = *p;
+ }
+ rName.Erase();
+ return pStart;
+}
+
static long int
sal_Unicode_strtol ( const sal_Unicode* p,
const sal_Unicode** pEnd )
@@ -99,34 +145,94 @@ sal_Unicode_strtol ( const sal_Unicode* p,
return is_neg ? -accum : accum;
}
-// Returns NULL if the string should be a sheet name, but is invalid
-// Returns a pointer to the first character after the sheet name
+const sal_Unicode* lcl_eatWhiteSpace( const sal_Unicode* p )
+{
+ if ( p )
+ {
+ while( *p == ' ' )
+ ++p;
+ }
+ return p;
+}
+
+/** Determines the number of sheets an external reference spans and sets
+ rRange.aEnd.nTab accordingly. If a sheet is not found, the corresponding
+ bits in rFlags are cleared. pExtInfo is filled if it wasn't already. If in
+ cached order rStartTabName comes after rEndTabName, pExtInfo->maTabName
+ is set to rEndTabName.
+ @returns <FALSE/> if pExtInfo is already filled and rExternDocName does not
+ result in the identical file ID. Else <TRUE/>.
+ */
+static bool lcl_ScRange_External_TabSpan(
+ ScRange & rRange,
+ USHORT & rFlags,
+ ScAddress::ExternalInfo* pExtInfo,
+ const String & rExternDocName,
+ const String & rStartTabName,
+ const String & rEndTabName,
+ ScDocument* pDoc )
+{
+ if (!rExternDocName.Len())
+ return !pExtInfo || !pExtInfo->mbExternal;
+
+ ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
+ if (pRefMgr->isOwnDocument( rExternDocName))
+ return !pExtInfo || !pExtInfo->mbExternal;
+
+ sal_uInt16 nFileId = pRefMgr->getExternalFileId( rExternDocName);
+
+ if (pExtInfo)
+ {
+ if (pExtInfo->mbExternal)
+ {
+ if (pExtInfo->mnFileId != nFileId)
+ return false;
+ }
+ else
+ {
+ pExtInfo->mbExternal = true;
+ pExtInfo->maTabName = rStartTabName;
+ pExtInfo->mnFileId = nFileId;
+ }
+ }
+
+ if (!rEndTabName.Len() || rStartTabName == rEndTabName)
+ {
+ rRange.aEnd.SetTab( rRange.aStart.Tab());
+ return true;
+ }
+
+ SCsTAB nSpan = pRefMgr->getCachedTabSpan( nFileId, rStartTabName, rEndTabName);
+ if (nSpan == -1)
+ rFlags &= ~(SCA_VALID_TAB | SCA_VALID_TAB2);
+ else if (nSpan == 0)
+ rFlags &= ~SCA_VALID_TAB2;
+ else if (nSpan >= 1)
+ rRange.aEnd.SetTab( rRange.aStart.Tab() + nSpan - 1);
+ else // (nSpan < -1)
+ {
+ rRange.aEnd.SetTab( rRange.aStart.Tab() - nSpan - 1);
+ if (pExtInfo)
+ pExtInfo->maTabName = rEndTabName;
+ }
+ return true;
+}
+
+// Returns NULL if the string should be a sheet name, but is invalid.
+// Returns a pointer to the first character after the sheet name, if there was
+// any, else pointer to start.
static const sal_Unicode *
-lcl_XL_ParseSheetRef( const sal_Unicode *start,
- ScAddress *pAddr,
- const ScDocument* pDoc,
- const String& rDocName,
+lcl_XL_ParseSheetRef( const sal_Unicode* start,
String& rExternTabName,
bool allow_3d )
{
String aTabName;
- SCTAB nTab = 0;
const sal_Unicode *p = start;
- //pAddr->SetTab( 0 );
if( *p == '\'' ) // XL only seems to use single quotes for sheet names
{
- for( p++; *p ; )
- {
- if( *p == '\'' )
- {
- if( p[1] != '\'' ) // end quote
- break;
- p++; // 2 quotes in a row are a quote in a the name
- }
- aTabName += *p++;
- }
- if( *p++ != '\'' )
+ p = lcl_ParseQuotedName(p, aTabName);
+ if (!aTabName.Len())
return NULL;
}
else
@@ -174,7 +280,13 @@ lcl_XL_ParseSheetRef( const sal_Unicode *start,
break;
}
p++;
- } else
+ }
+ else if (uc > 127)
+ {
+ // non ASCII character is allowed.
+ ++p;
+ }
+ else
break;
}
@@ -184,86 +296,99 @@ lcl_XL_ParseSheetRef( const sal_Unicode *start,
aTabName.Append( start, sal::static_int_cast<xub_StrLen>( p - start ) );
}
- if( pDoc )
- {
- if( rDocName.Len() > 0 )
- {
- // This is a simplification of the OOo code which does an
- // optimization to manually construct the DocTab before calling
- // GetDocTabName
- String aDocTab = ScGlobal::GetDocTabName( rDocName, aTabName );
- if( !pDoc->GetTable( aDocTab, nTab ) &&
- pDoc->ValidTabName( aTabName ) &&
- !pDoc->GetTable( aDocTab, nTab ) )
- {
- rExternTabName = aDocTab;
- }
- }
- else if( !pDoc->GetTable( aTabName, nTab ) )
- return start;
- }
-
- pAddr->SetTab( nTab );
+ rExternTabName = aTabName;
return p;
}
-static const sal_Unicode*
-lcl_ScRange_Parse_XL_Header( ScRange& r,
- const sal_Unicode* p,
- const ScDocument* pDoc,
- String& rExternDocName,
- String& rStartTabName,
- String& rEndTabName,
- USHORT& nFlags )
+
+const sal_Unicode* ScRange::Parse_XL_Header(
+ const sal_Unicode* p,
+ const ScDocument* pDoc,
+ String& rExternDocName,
+ String& rStartTabName,
+ String& rEndTabName,
+ USHORT& nFlags,
+ bool bOnlyAcceptSingle,
+ const uno::Sequence< const sheet::ExternalLinkInfo > * pExternalLinks )
{
const sal_Unicode* startTabs, *start = p;
+ USHORT nSaveFlags = nFlags;
// Is this an external reference ?
rStartTabName.Erase();
rEndTabName.Erase();
- if( *p == '[' )
+ rExternDocName.Erase();
+ if (*p == '[')
{
- p++;
- // TODO : Get more detail on how paths are quoted
- // 1) I suspect only single quote is correct
- // 2) check whether this is another doubled quote rather than a
- // backslash
- if( *p == '\'' || *p == '\"' )
+ ++p;
+ // Only single quotes are correct, and a double single quote escapes a
+ // single quote text inside the quoted text.
+ if (*p == '\'')
{
- for( const sal_Unicode cQuote = *p++; *p && *p != cQuote ; )
- {
- if( *p == '\\' && p[1] )
- p++;
- rExternDocName += *p++;
- }
+ p = lcl_ParseQuotedName(p, rExternDocName);
+ if (!*p || *p != ']' || !rExternDocName.Len())
+ return start;
}
else
{
+ // non-quoted file name.
p = ScGlobal::UnicodeStrChr( start+1, ']' );
if( p == NULL )
return start;
rExternDocName.Append( start+1, sal::static_int_cast<xub_StrLen>( p-(start+1) ) );
}
+ ++p;
- rExternDocName = ScGlobal::GetAbsDocName( rExternDocName,
- pDoc->GetDocumentShell() );
- if( *p != ']' )
- return start;
- p++;
+ // 1-based, sequence starts with an empty element.
+ if (pExternalLinks && pExternalLinks->getLength() > 1)
+ {
+ // A numeric "document name" is an index into the sequence.
+ if (CharClass::isAsciiNumeric( rExternDocName))
+ {
+ sal_Int32 i = rExternDocName.ToInt32();
+ if (i <= 0 || i >= pExternalLinks->getLength())
+ return start;
+ const sheet::ExternalLinkInfo & rInfo = (*pExternalLinks)[i];
+ switch (rInfo.Type)
+ {
+ case sheet::ExternalLinkType::DOCUMENT :
+ {
+ rtl::OUString aStr;
+ if (!(rInfo.Data >>= aStr))
+ {
+ DBG_ERROR1( "ScRange::Parse_XL_Header: Data type mismatch for ExternalLinkInfo %d", i);
+ return NULL;
+ }
+ rExternDocName = aStr;
+ }
+ break;
+ default:
+ DBG_ERROR2( "ScRange::Parse_XL_Header: unhandled ExternalLinkType %d for index %d",
+ rInfo.Type, i);
+ return NULL;
+ }
+ }
+ }
+ rExternDocName = ScGlobal::GetAbsDocName(rExternDocName, pDoc->GetDocumentShell());
}
startTabs = p;
- p = lcl_XL_ParseSheetRef( p, &r.aStart, pDoc, rExternDocName, rStartTabName, TRUE );
+ p = lcl_XL_ParseSheetRef( p, rStartTabName, !bOnlyAcceptSingle );
if( NULL == p )
return start; // invalid tab
+ if (bOnlyAcceptSingle && *p == ':')
+ return NULL; // 3D
if( p != startTabs )
{
nFlags |= SCA_VALID_TAB | SCA_TAB_3D | SCA_TAB_ABSOLUTE;
if( *p == ':' ) // 3d ref
{
- p = lcl_XL_ParseSheetRef( p+1, &r.aEnd, pDoc, rExternDocName, rEndTabName, FALSE );
+ p = lcl_XL_ParseSheetRef( p+1, rEndTabName, false );
if( p == NULL )
+ {
+ nFlags = nSaveFlags;
return start; // invalid tab
+ }
nFlags |= SCA_VALID_TAB2 | SCA_TAB2_3D | SCA_TAB2_ABSOLUTE;
}
else
@@ -271,57 +396,56 @@ lcl_ScRange_Parse_XL_Header( ScRange& r,
// If only one sheet is given, the full reference is still valid,
// only the second 3D flag is not set.
nFlags |= SCA_VALID_TAB2 | SCA_TAB2_ABSOLUTE;
- r.aEnd.SetTab( r.aStart.Tab() );
+ aEnd.SetTab( aStart.Tab() );
}
if( *p++ != '!' )
+ {
+ nFlags = nSaveFlags;
return start; // syntax error
+ }
+ else
+ p = lcl_eatWhiteSpace( p );
}
else
{
nFlags |= SCA_VALID_TAB | SCA_VALID_TAB2;
- // Use the current tab, it needs to be passed in. : r.aEnd.SetTab( .. );
+ // Use the current tab, it needs to be passed in. : aEnd.SetTab( .. );
}
- return p;
-}
-
-static USHORT
-lcl_XL_LinkSheetRef( ScRange& r,
- ScDocument* pDoc,
- const String& rExternDocName,
- const String& rStartTabName,
- const String& rEndTabName,
- USHORT nFlags )
-{
- SCTAB nTab;
-
- if( rExternDocName.Len() > 0 )
+ if (!rExternDocName.Len())
{
- String aDocName = ScGlobal::GetAbsDocName( rExternDocName,
- pDoc->GetDocumentShell() );
+ // Internal reference.
+ if (!rStartTabName.Len())
+ {
+ nFlags = nSaveFlags;
+ return start;
+ }
- String aDocTab;
+ SCTAB nTab;
+ if (!pDoc->GetTable(rStartTabName, nTab))
+ {
+ // invalid table name.
+ nFlags &= ~SCA_VALID_TAB;
+ nTab = -1;
+ }
- aDocTab = ScGlobal::GetDocTabName( aDocName, rStartTabName );
- if( !pDoc->LinkExternalTab( nTab, aDocTab, rExternDocName, rStartTabName ) )
- return 0;
- r.aStart.SetTab( nTab );
+ aStart.SetTab(nTab);
+ aEnd.SetTab(nTab);
- if( rEndTabName.Len() > 0 &&
- rStartTabName != rEndTabName )
+ if (rEndTabName.Len())
{
- aDocTab = ScGlobal::GetDocTabName( aDocName, rEndTabName );
- if( !pDoc->LinkExternalTab( nTab, aDocTab, rExternDocName, rEndTabName ) )
+ if (!pDoc->GetTable(rEndTabName, nTab))
{
- DBG_ASSERT( r.IsValid(), "lcl_XL_LinkSheetRef - unable to link endTab of 3d ref" );
- return 0;
+ // invalid table name.
+ nFlags &= ~SCA_VALID_TAB2;
+ nTab = -1;
}
+
+ aEnd.SetTab(nTab);
}
- r.aEnd.SetTab( nTab );
}
-
- return nFlags;
+ return p;
}
@@ -421,7 +545,8 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
const sal_Unicode* p,
ScDocument* pDoc,
const ScAddress::Details& rDetails,
- BOOL bOnlyAcceptSingle )
+ bool bOnlyAcceptSingle,
+ ScAddress::ExternalInfo* pExtInfo )
{
const sal_Unicode* pTmp = NULL;
String aExternDocName, aStartTabName, aEndTabName;
@@ -434,8 +559,13 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
std::cerr << "parse::XL::R1C1 \'" << aStr.GetBuffer() << '\'' << std::endl;
}
#endif
- p = lcl_ScRange_Parse_XL_Header( r, p, pDoc,
- aExternDocName, aStartTabName, aEndTabName, nFlags );
+ p = r.Parse_XL_Header( p, pDoc, aExternDocName, aStartTabName,
+ aEndTabName, nFlags, bOnlyAcceptSingle, NULL );
+
+ if (aExternDocName.Len() > 0)
+ lcl_ScRange_External_TabSpan( r, nFlags, pExtInfo, aExternDocName,
+ aStartTabName, aEndTabName, pDoc);
+
if( NULL == p )
return 0;
@@ -474,8 +604,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
r.aStart.SetCol( 0 );
r.aEnd.SetCol( MAXCOL );
- return bOnlyAcceptSingle ? 0 : lcl_XL_LinkSheetRef( r, pDoc,
- aExternDocName, aStartTabName, aEndTabName, nFlags );
+ return bOnlyAcceptSingle ? 0 : nFlags;
}
else if( NULL == (p = lcl_r1c1_get_col( p, rDetails, &r.aStart, &nFlags )))
goto failed;
@@ -495,8 +624,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
return nFlags;
}
- return bOnlyAcceptSingle ? lcl_XL_LinkSheetRef( r, pDoc,
- aExternDocName, aStartTabName, aEndTabName, nFlags ) : 0;
+ return bOnlyAcceptSingle ? nFlags : 0;
}
p = pTmp;
@@ -511,8 +639,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
}
nFlags |= (nFlags2 << 4);
- return bOnlyAcceptSingle ? 0 : lcl_XL_LinkSheetRef( r, pDoc,
- aExternDocName, aStartTabName, aEndTabName, nFlags );
+ return bOnlyAcceptSingle ? 0 : nFlags;
}
else if( *p == 'C' || *p == 'c' ) // full col C#
{
@@ -544,8 +671,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
r.aStart.SetRow( 0 );
r.aEnd.SetRow( MAXROW );
- return bOnlyAcceptSingle ? 0 : lcl_XL_LinkSheetRef( r, pDoc,
- aExternDocName, aStartTabName, aEndTabName, nFlags );
+ return bOnlyAcceptSingle ? 0 : nFlags;
}
failed :
@@ -598,11 +724,13 @@ static USHORT
lcl_ScRange_Parse_XL_A1( ScRange& r,
const sal_Unicode* p,
ScDocument* pDoc,
- BOOL bOnlyAcceptSingle )
+ bool bOnlyAcceptSingle,
+ ScAddress::ExternalInfo* pExtInfo,
+ const uno::Sequence< const sheet::ExternalLinkInfo > * pExternalLinks )
{
const sal_Unicode* tmp1, *tmp2;
String aExternDocName, aStartTabName, aEndTabName;
- USHORT nFlags = SCA_VALID | SCA_VALID_TAB, nFlags2 = SCA_VALID_TAB2;
+ USHORT nFlags = SCA_VALID | SCA_VALID_TAB, nFlags2 = SCA_VALID_TAB;
#if 0
{
@@ -611,8 +739,13 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
std::cerr << "parse::XL::A1 \'" << aStr.GetBuffer() << '\'' << std::endl;
}
#endif
- p = lcl_ScRange_Parse_XL_Header( r, p, pDoc,
- aExternDocName, aStartTabName, aEndTabName, nFlags );
+ p = r.Parse_XL_Header( p, pDoc, aExternDocName, aStartTabName,
+ aEndTabName, nFlags, bOnlyAcceptSingle, pExternalLinks );
+
+ if (aExternDocName.Len() > 0)
+ lcl_ScRange_External_TabSpan( r, nFlags, pExtInfo, aExternDocName,
+ aStartTabName, aEndTabName, pDoc);
+
if( NULL == p )
return 0;
@@ -623,8 +756,12 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
return 0;
tmp1 = lcl_a1_get_row( p, &r.aStart, &nFlags );
+
+ tmp1 = lcl_eatWhiteSpace( tmp1 );
if( !tmp1 || *tmp1++ != ':' ) // Even a singleton requires ':' (eg 2:2)
return 0;
+
+ tmp1 = lcl_eatWhiteSpace( tmp1 );
tmp2 = lcl_a1_get_row( tmp1, &r.aEnd, &nFlags2 );
if( !tmp2 )
return 0;
@@ -634,8 +771,7 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
SCA_VALID_COL | SCA_VALID_COL2 |
SCA_COL_ABSOLUTE | SCA_COL2_ABSOLUTE;
nFlags |= (nFlags2 << 4);
- return lcl_XL_LinkSheetRef( r, pDoc,
- aExternDocName, aStartTabName, aEndTabName, nFlags );
+ return nFlags;
}
tmp2 = lcl_a1_get_row( tmp1, &r.aStart, &nFlags );
@@ -644,30 +780,31 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
if( bOnlyAcceptSingle ) // by definition full col refs are ranges
return 0;
+ tmp1 = lcl_eatWhiteSpace( tmp1 );
if( *tmp1++ != ':' ) // Even a singleton requires ':' (eg F:F)
return 0;
+
+ tmp1 = lcl_eatWhiteSpace( tmp1 );
tmp2 = lcl_a1_get_col( tmp1, &r.aEnd, &nFlags2 );
if( !tmp2 )
- return 0;
+ return 0;
r.aStart.SetRow( 0 ); r.aEnd.SetRow( MAXROW );
nFlags |=
SCA_VALID_ROW | SCA_VALID_ROW2 |
SCA_ROW_ABSOLUTE | SCA_ROW2_ABSOLUTE;
nFlags |= (nFlags2 << 4);
- return lcl_XL_LinkSheetRef( r, pDoc,
- aExternDocName, aStartTabName, aEndTabName, nFlags );
+ return nFlags;
}
// prepare as if it's a singleton, in case we want to fall back */
r.aEnd.SetCol( r.aStart.Col() );
- r.aEnd.SetRow( r.aStart.Row() ); // don't overwrite sheet number as parsed in lcl_ScRange_Parse_XL_Header
+ r.aEnd.SetRow( r.aStart.Row() ); // don't overwrite sheet number as parsed in Parse_XL_Header()
if ( bOnlyAcceptSingle )
{
if ( *tmp2 == 0 )
- return lcl_XL_LinkSheetRef( r, pDoc,
- aExternDocName, aStartTabName, aEndTabName, nFlags );
+ return nFlags;
else
{
// any trailing invalid character must invalidate the address.
@@ -676,22 +813,34 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
}
}
+ tmp2 = lcl_eatWhiteSpace( tmp2 );
if( *tmp2 != ':' )
{
- nFlags &= ~(SCA_VALID | SCA_VALID_COL | SCA_VALID_ROW | SCA_VALID_TAB |
+ // Sheet1:Sheet2!C4 is a valid range, without a second sheet it is
+ // not. Any trailing invalid character invalidates the range.
+ if (*tmp2 == 0 && (nFlags & SCA_TAB2_3D))
+ {
+ if (nFlags & SCA_COL_ABSOLUTE)
+ nFlags |= SCA_COL2_ABSOLUTE;
+ if (nFlags & SCA_ROW_ABSOLUTE)
+ nFlags |= SCA_ROW2_ABSOLUTE;
+ }
+ else
+ nFlags &= ~(SCA_VALID |
+ SCA_VALID_COL | SCA_VALID_ROW | SCA_VALID_TAB |
SCA_VALID_COL2 | SCA_VALID_ROW2 | SCA_VALID_TAB2);
return nFlags;
}
p = tmp2;
- tmp1 = lcl_a1_get_col( p+1, &r.aEnd, &nFlags2 );
+ p = lcl_eatWhiteSpace( p+1 );
+ tmp1 = lcl_a1_get_col( p, &r.aEnd, &nFlags2 );
if( !tmp1 ) // strange, but valid singleton
- return lcl_XL_LinkSheetRef( r, pDoc,
- aExternDocName, aStartTabName, aEndTabName, nFlags );
+ return nFlags;
+
tmp2 = lcl_a1_get_row( tmp1, &r.aEnd, &nFlags2 );
if( !tmp2 ) // strange, but valid singleton
- return lcl_XL_LinkSheetRef( r, pDoc,
- aExternDocName, aStartTabName, aEndTabName, nFlags );
+ return nFlags;
if ( *tmp2 != 0 )
{
@@ -702,45 +851,42 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
}
nFlags |= (nFlags2 << 4);
- return lcl_XL_LinkSheetRef( r, pDoc,
- aExternDocName, aStartTabName, aEndTabName, nFlags );
+ return nFlags;
}
+/**
+ @param pRange pointer to range where rAddr effectively is *pRange->aEnd,
+ used in conjunction with pExtInfo to determine the tab span
+ of a 3D reference.
+ */
static USHORT
-lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
- ScDocument* pDoc, ScAddress& rAddr )
+lcl_ScAddress_Parse_OOo( const sal_Unicode* p, ScDocument* pDoc, ScAddress& rAddr,
+ ScAddress::ExternalInfo* pExtInfo = NULL, ScRange* pRange = NULL )
{
USHORT nRes = 0;
String aDocName; // der pure Dokumentenname
- String aDocTab; // zusammengesetzt fuer Table
String aTab;
- BOOL bExtDoc = FALSE;
- BOOL bNeedExtTab = FALSE;
+ bool bExtDoc = false;
+ bool bExtDocInherited = false;
+ const ScAddress aCurPos(rAddr);
- // Lets see if this is a reference to something in an external file.
- // A Documentname is always quoted and has a trailing #
- if ( *p == '\'' && ScGlobal::UnicodeStrChr( p, SC_COMPILER_FILE_TAB_SEP ) )
+ // Lets see if this is a reference to something in an external file. A
+ // document name is always quoted and has a trailing #.
+ if (*p == '\'')
{
- const sal_Unicode *pStart = p;
- BOOL bQuote = TRUE; // A Documentname is always quoted
- aDocTab += *p++;
- while ( bQuote && *p )
- {
- if ( *p == '\'' && *(p-1) != '\\' )
- bQuote = FALSE;
- else if( !(*p == '\\' && *(p+1) == '\'') )
- aDocName += *p; // An escaped Quote in the Documentname
- aDocTab += *p++;
- }
- aDocTab += *p; // den SC_COMPILER_FILE_TAB_SEP mitnehmen
- if( *p++ == SC_COMPILER_FILE_TAB_SEP )
- bExtDoc = TRUE;
+ const sal_Unicode* pStart = p;
+ p = lcl_ParseQuotedName(p, aDocName);
+ if (*p++ == SC_COMPILER_FILE_TAB_SEP)
+ bExtDoc = true;
else
- {
- // It wasn't a document after all, reset and continue as normal
+ // This is not a document name. Perhaps a quoted relative table
+ // name.
p = pStart;
- aDocTab = String();
- }
+ }
+ else if (pExtInfo && pExtInfo->mbExternal)
+ {
+ // This is an external reference.
+ bExtDoc = bExtDocInherited = true;
}
SCCOL nCol = 0;
@@ -748,7 +894,7 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
SCTAB nTab = 0;
USHORT nBits = SCA_VALID_TAB;
const sal_Unicode* q;
- if ( ScGlobal::UnicodeStrChr( p, '.') )
+ if ( ScGlobal::FindUnquoted( p, '.') )
{
nRes |= SCA_TAB_3D;
if ( bExtDoc )
@@ -756,76 +902,37 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
if (*p == '$')
nRes |= SCA_TAB_ABSOLUTE, p++;
- // Tokens that start at ' can have anything in them until a final '
- // but '' marks an escaped '
- // We've earlier guaranteed that a string containing '' will be
- // surrounded by '
- if( *p == '\'' )
+ if (*p == '\'')
+ {
+ // Tokens that start at ' can have anything in them until a final
+ // ' but '' marks an escaped '. We've earlier guaranteed that a
+ // string containing '' will be surrounded by '.
+ p = lcl_ParseQuotedName(p, aTab);
+ }
+ else
{
- ++p;
while (*p)
{
- if (*p == '\'')
+ if( *p == '.')
+ break;
+
+ if( *p == '\'' )
{
- if ( (*(p+1) != '\'') )
- break;
- else
- *p++;
+ p++; break;
}
aTab += *p++;
}
}
-
- while (*p)
- {
- if( *p == '.')
- break;
-
- if( *p == '\'' )
- {
- p++; break;
- }
- aTab += *p++;
- }
if( *p++ != '.' )
nBits = 0;
- if ( pDoc )
- {
- if ( bExtDoc )
- {
- bExternal = TRUE;
- aDocTab += aTab; // "'Doc'#Tab"
- if ( !pDoc->GetTable( aDocTab, nTab ) )
- {
- if ( pDoc->ValidTabName( aTab ) )
- {
- aDocName = ScGlobal::GetAbsDocName( aDocName,
- pDoc->GetDocumentShell() );
- aDocTab = ScGlobal::GetDocTabName( aDocName, aTab );
- if ( !pDoc->GetTable( aDocTab, nTab ) )
- {
- // erst einfuegen, wenn Rest der Ref ok
- bNeedExtTab = TRUE;
- nBits = 0;
- }
- }
- else
- nBits = 0;
- }
- }
- else
- {
- if ( !pDoc->GetTable( aTab, nTab ) )
- nBits = 0;
- }
- }
- else
+
+ if (!bExtDoc && (!pDoc || !pDoc->GetTable( aTab, nTab )))
nBits = 0;
}
else
{
- if ( bExtDoc )
- return nRes; // nach Dokument muss Tabelle folgen
+ if (bExtDoc && !bExtDocInherited)
+ return nRes; // After a document a sheet must follow.
nTab = rAddr.Tab();
}
nRes |= nBits;
@@ -878,19 +985,95 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
if( !nBits )
p = q;
}
- if ( bNeedExtTab )
+
+ rAddr.Set( nCol, nRow, nTab );
+
+ if (!*p && bExtDoc)
{
- if ( (nRes & SCA_VALID_ROW) && (nRes & SCA_VALID_COL)
- && pDoc->LinkExternalTab( nTab, aDocTab, aDocName, aTab ) )
+ if (!pDoc)
+ nRes = 0;
+ else
{
- nRes |= SCA_VALID_TAB;
+ ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
+
+ // Need document name if inherited.
+ if (bExtDocInherited)
+ {
+ const String* pFileName = pRefMgr->getExternalFileName( pExtInfo->mnFileId);
+ if (pFileName)
+ aDocName = *pFileName;
+ else
+ nRes = 0;
+ }
+ pRefMgr->convertToAbsName(aDocName);
+
+ if ((!pExtInfo || !pExtInfo->mbExternal) && pRefMgr->isOwnDocument(aDocName))
+ {
+ if (!pDoc->GetTable( aTab, nTab ))
+ nRes = 0;
+ else
+ {
+ rAddr.SetTab( nTab);
+ nRes |= SCA_VALID_TAB;
+ }
+ }
+ else
+ {
+ if (!pExtInfo)
+ nRes = 0;
+ else
+ {
+ if (!pExtInfo->mbExternal)
+ {
+ sal_uInt16 nFileId = pRefMgr->getExternalFileId(aDocName);
+
+ pExtInfo->mbExternal = true;
+ pExtInfo->maTabName = aTab;
+ pExtInfo->mnFileId = nFileId;
+
+ if (pRefMgr->getSingleRefToken(nFileId, aTab,
+ ScAddress(nCol, nRow, 0), NULL,
+ &nTab).get())
+ {
+ rAddr.SetTab( nTab);
+ nRes |= SCA_VALID_TAB;
+ }
+ else
+ nRes = 0;
+ }
+ else
+ {
+ // This is a call for the second part of the reference,
+ // we must have the range to adapt tab span.
+ if (!pRange)
+ nRes = 0;
+ else
+ {
+ USHORT nFlags = nRes | SCA_VALID_TAB2;
+ if (!lcl_ScRange_External_TabSpan( *pRange, nFlags,
+ pExtInfo, aDocName,
+ pExtInfo->maTabName, aTab, pDoc))
+ nRes &= ~SCA_VALID_TAB;
+ else
+ {
+ if (nFlags & SCA_VALID_TAB2)
+ {
+ rAddr.SetTab( pRange->aEnd.Tab());
+ nRes |= SCA_VALID_TAB;
+ }
+ else
+ nRes &= ~SCA_VALID_TAB;
+ }
+ }
+ }
+ }
+ }
}
- else
- nRes = 0; // #NAME? statt #REF!, Dateiname bleibt erhalten
}
+
if ( !(nRes & SCA_VALID_ROW) && (nRes & SCA_VALID_COL)
&& !( (nRes & SCA_TAB_3D) && (nRes & SCA_VALID_TAB)) )
- { // keine Row, keine Tab, aber Col => DM (...), B (...) o.ae.
+ { // no Row, no Tab, but Col => DM (...), B (...) et al
nRes = 0;
}
if( !*p )
@@ -901,14 +1084,14 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
}
else
nRes = 0;
- rAddr.Set( nCol, nRow, nTab );
return nRes;
}
static USHORT
-lcl_ScAddress_Parse ( BOOL& bExternal, const sal_Unicode* p,
- ScDocument* pDoc, ScAddress& rAddr,
- const ScAddress::Details& rDetails )
+lcl_ScAddress_Parse ( const sal_Unicode* p, ScDocument* pDoc, ScAddress& rAddr,
+ const ScAddress::Details& rDetails,
+ ScAddress::ExternalInfo* pExtInfo = NULL,
+ const uno::Sequence< const sheet::ExternalLinkInfo > * pExternalLinks = NULL )
{
if( !*p )
return 0;
@@ -918,20 +1101,22 @@ lcl_ScAddress_Parse ( BOOL& bExternal, const sal_Unicode* p,
default :
case ScAddress::CONV_OOO:
{
- return lcl_ScAddress_Parse_OOo( bExternal, p, pDoc, rAddr );
+ return lcl_ScAddress_Parse_OOo( p, pDoc, rAddr, pExtInfo, NULL );
}
case ScAddress::CONV_XL_A1:
+ case ScAddress::CONV_XL_OOX:
{
ScRange r = rAddr;
- USHORT nFlags = lcl_ScRange_Parse_XL_A1( r, p, pDoc, TRUE );
+ USHORT nFlags = lcl_ScRange_Parse_XL_A1( r, p, pDoc, true, pExtInfo,
+ (rDetails.eConv == ScAddress::CONV_XL_OOX ? pExternalLinks : NULL) );
rAddr = r.aStart;
return nFlags;
}
case ScAddress::CONV_XL_R1C1:
{
ScRange r = rAddr;
- USHORT nFlags = lcl_ScRange_Parse_XL_R1C1( r, p, pDoc, rDetails, TRUE );
+ USHORT nFlags = lcl_ScRange_Parse_XL_R1C1( r, p, pDoc, rDetails, true, pExtInfo );
rAddr = r.aStart;
return nFlags;
}
@@ -943,9 +1128,8 @@ bool ConvertSingleRef( ScDocument* pDoc, const String& rRefString,
SCTAB nDefTab, ScRefAddress& rRefAddress,
const ScAddress::Details& rDetails )
{
- BOOL bExternal = FALSE;
ScAddress aAddr( 0, 0, nDefTab );
- USHORT nRes = lcl_ScAddress_Parse( bExternal, rRefString.GetBuffer(), pDoc, aAddr, rDetails );
+ USHORT nRes = lcl_ScAddress_Parse( rRefString.GetBuffer(), pDoc, aAddr, rDetails, NULL );
if( nRes & SCA_VALID )
{
rRefAddress.Set( aAddr,
@@ -982,10 +1166,11 @@ bool ConvertDoubleRef( ScDocument* pDoc, const String& rRefString, SCTAB nDefTab
USHORT ScAddress::Parse( const String& r, ScDocument* pDoc,
- const Details& rDetails)
+ const Details& rDetails,
+ ExternalInfo* pExtInfo,
+ const uno::Sequence< const sheet::ExternalLinkInfo > * pExternalLinks )
{
- BOOL bExternal = FALSE;
- return lcl_ScAddress_Parse( bExternal, r.GetBuffer(), pDoc, *this, rDetails );
+ return lcl_ScAddress_Parse( r.GetBuffer(), pDoc, *this, rDetails, pExtInfo, pExternalLinks );
}
@@ -1035,66 +1220,56 @@ void ScRange::ExtendTo( const ScRange& rRange )
}
static USHORT
-lcl_ScRange_Parse_OOo( ScRange &aRange, const String& r, ScDocument* pDoc )
+lcl_ScRange_Parse_OOo( ScRange &aRange, const String& r, ScDocument* pDoc, ScAddress::ExternalInfo* pExtInfo = NULL )
{
USHORT nRes1 = 0, nRes2 = 0;
- xub_StrLen nTmp = 0;
- xub_StrLen nPos = STRING_NOTFOUND;
-
- while ( (nTmp = r.Search( ':', nTmp )) != STRING_NOTFOUND )
- nPos = nTmp++; // der letzte zaehlt, koennte 'd:\...'!a1:a2 sein
+ xub_StrLen nPos = ScGlobal::FindUnquoted( r, ':');
if (nPos != STRING_NOTFOUND)
{
String aTmp( r );
sal_Unicode* p = aTmp.GetBufferAccess();
p[ nPos ] = 0;
- BOOL bExternal = FALSE;
- if( (nRes1 = lcl_ScAddress_Parse_OOo( bExternal, p, pDoc, aRange.aStart ) ) != 0 )
+ if( (nRes1 = lcl_ScAddress_Parse_OOo( p, pDoc, aRange.aStart, pExtInfo, NULL ) ) != 0 )
{
- aRange.aEnd = aRange.aStart; // die Tab _muss_ gleich sein, so ist`s weniger Code
- if ( (nRes2 = lcl_ScAddress_Parse_OOo( bExternal, p + nPos+ 1, pDoc, aRange.aEnd ) ) != 0 )
+ aRange.aEnd = aRange.aStart; // sheet must be initialized identical to first sheet
+ if ( (nRes2 = lcl_ScAddress_Parse_OOo( p + nPos+ 1, pDoc, aRange.aEnd, pExtInfo, &aRange ) ) != 0 )
{
- if ( bExternal && aRange.aStart.Tab() != aRange.aEnd.Tab() )
- nRes2 &= ~SCA_VALID_TAB; // #REF!
- else
+ // PutInOrder / Justify
+ USHORT nMask, nBits1, nBits2;
+ SCCOL nTempCol;
+ if ( aRange.aEnd.Col() < (nTempCol = aRange.aStart.Col()) )
{
- // PutInOrder / Justify
- USHORT nMask, nBits1, nBits2;
- SCCOL nTempCol;
- if ( aRange.aEnd.Col() < (nTempCol = aRange.aStart.Col()) )
- {
- aRange.aStart.SetCol(aRange.aEnd.Col()); aRange.aEnd.SetCol(nTempCol);
- nMask = (SCA_VALID_COL | SCA_COL_ABSOLUTE);
- nBits1 = nRes1 & nMask;
- nBits2 = nRes2 & nMask;
- nRes1 = (nRes1 & ~nMask) | nBits2;
- nRes2 = (nRes2 & ~nMask) | nBits1;
- }
- SCROW nTempRow;
- if ( aRange.aEnd.Row() < (nTempRow = aRange.aStart.Row()) )
- {
- aRange.aStart.SetRow(aRange.aEnd.Row()); aRange.aEnd.SetRow(nTempRow);
- nMask = (SCA_VALID_ROW | SCA_ROW_ABSOLUTE);
- nBits1 = nRes1 & nMask;
- nBits2 = nRes2 & nMask;
- nRes1 = (nRes1 & ~nMask) | nBits2;
- nRes2 = (nRes2 & ~nMask) | nBits1;
- }
- SCTAB nTempTab;
- if ( aRange.aEnd.Tab() < (nTempTab = aRange.aStart.Tab()) )
- {
- aRange.aStart.SetTab(aRange.aEnd.Tab()); aRange.aEnd.SetTab(nTempTab);
- nMask = (SCA_VALID_TAB | SCA_TAB_ABSOLUTE | SCA_TAB_3D);
- nBits1 = nRes1 & nMask;
- nBits2 = nRes2 & nMask;
- nRes1 = (nRes1 & ~nMask) | nBits2;
- nRes2 = (nRes2 & ~nMask) | nBits1;
- }
- if ( ((nRes1 & ( SCA_TAB_ABSOLUTE | SCA_TAB_3D ))
- == ( SCA_TAB_ABSOLUTE | SCA_TAB_3D ))
- && !(nRes2 & SCA_TAB_3D) )
- nRes2 |= SCA_TAB_ABSOLUTE;
+ aRange.aStart.SetCol(aRange.aEnd.Col()); aRange.aEnd.SetCol(nTempCol);
+ nMask = (SCA_VALID_COL | SCA_COL_ABSOLUTE);
+ nBits1 = nRes1 & nMask;
+ nBits2 = nRes2 & nMask;
+ nRes1 = (nRes1 & ~nMask) | nBits2;
+ nRes2 = (nRes2 & ~nMask) | nBits1;
+ }
+ SCROW nTempRow;
+ if ( aRange.aEnd.Row() < (nTempRow = aRange.aStart.Row()) )
+ {
+ aRange.aStart.SetRow(aRange.aEnd.Row()); aRange.aEnd.SetRow(nTempRow);
+ nMask = (SCA_VALID_ROW | SCA_ROW_ABSOLUTE);
+ nBits1 = nRes1 & nMask;
+ nBits2 = nRes2 & nMask;
+ nRes1 = (nRes1 & ~nMask) | nBits2;
+ nRes2 = (nRes2 & ~nMask) | nBits1;
}
+ SCTAB nTempTab;
+ if ( aRange.aEnd.Tab() < (nTempTab = aRange.aStart.Tab()) )
+ {
+ aRange.aStart.SetTab(aRange.aEnd.Tab()); aRange.aEnd.SetTab(nTempTab);
+ nMask = (SCA_VALID_TAB | SCA_TAB_ABSOLUTE | SCA_TAB_3D);
+ nBits1 = nRes1 & nMask;
+ nBits2 = nRes2 & nMask;
+ nRes1 = (nRes1 & ~nMask) | nBits2;
+ nRes2 = (nRes2 & ~nMask) | nBits1;
+ }
+ if ( ((nRes1 & ( SCA_TAB_ABSOLUTE | SCA_TAB_3D ))
+ == ( SCA_TAB_ABSOLUTE | SCA_TAB_3D ))
+ && !(nRes2 & SCA_TAB_3D) )
+ nRes2 |= SCA_TAB_ABSOLUTE;
}
else
nRes1 = 0; // #38840# keine Tokens aus halben Sachen
@@ -1107,7 +1282,9 @@ lcl_ScRange_Parse_OOo( ScRange &aRange, const String& r, ScDocument* pDoc )
}
USHORT ScRange::Parse( const String& r, ScDocument* pDoc,
- const ScAddress::Details& rDetails )
+ const ScAddress::Details& rDetails,
+ ScAddress::ExternalInfo* pExtInfo,
+ const uno::Sequence< const sheet::ExternalLinkInfo > * pExternalLinks )
{
if ( r.Len() <= 0 )
return 0;
@@ -1116,13 +1293,15 @@ USHORT ScRange::Parse( const String& r, ScDocument* pDoc,
{
default :
case ScAddress::CONV_OOO:
- return lcl_ScRange_Parse_OOo( *this, r, pDoc );
+ return lcl_ScRange_Parse_OOo( *this, r, pDoc, pExtInfo );
case ScAddress::CONV_XL_A1:
- return lcl_ScRange_Parse_XL_A1( *this, r.GetBuffer(), pDoc, FALSE );
+ case ScAddress::CONV_XL_OOX:
+ return lcl_ScRange_Parse_XL_A1( *this, r.GetBuffer(), pDoc, false, pExtInfo,
+ (rDetails.eConv == ScAddress::CONV_XL_OOX ? pExternalLinks : NULL) );
case ScAddress::CONV_XL_R1C1:
- return lcl_ScRange_Parse_XL_R1C1( *this, r.GetBuffer(), pDoc, rDetails, FALSE );
+ return lcl_ScRange_Parse_XL_R1C1( *this, r.GetBuffer(), pDoc, rDetails, false, pExtInfo );
}
}
@@ -1162,6 +1341,7 @@ USHORT ScRange::ParseCols( const String& rStr, ScDocument* pDoc,
default :
case ScAddress::CONV_OOO: // No full col refs in OOO yet, assume XL notation
case ScAddress::CONV_XL_A1:
+ case ScAddress::CONV_XL_OOX:
if (NULL != (p = lcl_a1_get_col( p, &aStart, &ignored ) ) )
{
if( p[0] == ':')
@@ -1220,6 +1400,7 @@ USHORT ScRange::ParseRows( const String& rStr, ScDocument* pDoc,
default :
case ScAddress::CONV_OOO: // No full row refs in OOO yet, assume XL notation
case ScAddress::CONV_XL_A1:
+ case ScAddress::CONV_XL_OOX:
if (NULL != (p = lcl_a1_get_row( p, &aStart, &ignored ) ) )
{
if( p[0] == ':')
@@ -1367,17 +1548,14 @@ void ScAddress::Format( String& r, USHORT nFlags, ScDocument* pDoc,
{
String aTabName, aDocName;
pDoc->GetName( nTab, aTabName );
- // externe Referenzen (wie in ScCompiler::MakeTabStr)
+ // External Reference, same as in ScCompiler::MakeTabStr()
if( aTabName.GetChar(0) == '\'' )
{ // "'Doc'#Tab"
- xub_StrLen nPos, nLen = 1;
- while( (nPos = aTabName.Search( '\'', nLen ))
- != STRING_NOTFOUND )
- nLen = nPos + 1;
- if( aTabName.GetChar(nLen) == SC_COMPILER_FILE_TAB_SEP )
+ xub_StrLen nPos = ScGlobal::FindUnquoted( aTabName, SC_COMPILER_FILE_TAB_SEP);
+ if (nPos != STRING_NOTFOUND && nPos > 0 && aTabName.GetChar(nPos-1) == '\'')
{
- aDocName = aTabName.Copy( 0, nLen + 1 );
- aTabName.Erase( 0, nLen + 1 );
+ aDocName = aTabName.Copy( 0, nPos + 1 );
+ aTabName.Erase( 0, nPos + 1 );
}
}
else if( nFlags & SCA_FORCE_DOC )
@@ -1404,6 +1582,7 @@ void ScAddress::Format( String& r, USHORT nFlags, ScDocument* pDoc,
case CONV_XL_A1:
case CONV_XL_R1C1:
+ case CONV_XL_OOX:
if (aDocName.Len() > 0)
{
r += '[';
@@ -1421,6 +1600,7 @@ void ScAddress::Format( String& r, USHORT nFlags, ScDocument* pDoc,
default :
case CONV_OOO:
case CONV_XL_A1:
+ case CONV_XL_OOX:
if( nFlags & SCA_VALID_COL )
lcl_a1_append_c ( r, nCol, nFlags & SCA_COL_ABSOLUTE );
if( nFlags & SCA_VALID_ROW )
@@ -1451,16 +1631,14 @@ lcl_Split_DocTab( const ScDocument* pDoc, SCTAB nTab,
std::cerr << "tabname \'" << aStr.GetBuffer() << '\'' << std::endl;
}
#endif
- // externe Referenzen (wie in ScCompiler::MakeTabStr)
+ // External reference, same as in ScCompiler::MakeTabStr()
if ( rTabName.GetChar(0) == '\'' )
{ // "'Doc'#Tab"
- xub_StrLen nPos, nLen = 1;
- while( (nPos = rTabName.Search( '\'', nLen )) != STRING_NOTFOUND )
- nLen = nPos + 1;
- if ( rTabName.GetChar(nLen) == SC_COMPILER_FILE_TAB_SEP )
+ xub_StrLen nPos = ScGlobal::FindUnquoted( rTabName, SC_COMPILER_FILE_TAB_SEP);
+ if (nPos != STRING_NOTFOUND && nPos > 0 && rTabName.GetChar(nPos-1) == '\'')
{
- rDocName = rTabName.Copy( 0, nLen + 1 );
- rTabName.Erase( 0, nLen + 1 );
+ rDocName = rTabName.Copy( 0, nPos + 1 );
+ rTabName.Erase( 0, nPos + 1 );
}
}
else if( nFlags & SCA_FORCE_DOC )
@@ -1540,6 +1718,7 @@ void ScRange::Format( String& r, USHORT nFlags, ScDocument* pDoc,
break;
case ScAddress::CONV_XL_A1:
+ case ScAddress::CONV_XL_OOX:
lcl_ScRange_Format_XL_Header( r, *this, nFlags, pDoc, rDetails );
if( aStart.Col() == 0 && aEnd.Col() >= MAXCOL )
{
@@ -1648,6 +1827,7 @@ String ScAddress::GetColRowString( bool bAbsolute,
default :
case ScAddress::CONV_OOO:
case ScAddress::CONV_XL_A1:
+ case ScAddress::CONV_XL_OOX:
if (bAbsolute)
aString.Append( '$' );
diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx
index 900d2566aed9..6d39951d6553 100644
--- a/sc/source/core/tool/compiler.cxx
+++ b/sc/source/core/tool/compiler.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: compiler.cxx,v $
- * $Revision: 1.83 $
+ * $Revision: 1.82.28.20 $
*
* This file is part of OpenOffice.org.
*
@@ -72,9 +72,11 @@
#include "errorcodes.hxx"
#include "parclass.hxx"
#include "autonamecache.hxx"
+#include "externalrefmgr.hxx"
using namespace ::com::sun::star;
using rtl::OUString;
+using ::std::vector;
#if OSL_DEBUG_LEVEL > 1
// For some unknown reason the identical dbg_dump utilities in
@@ -107,7 +109,7 @@ ScCompiler::NonConstOpCodeMapPtr ScCompiler::mxSymbolsPODF;
ScCompiler::NonConstOpCodeMapPtr ScCompiler::mxSymbolsNative;
ScCompiler::NonConstOpCodeMapPtr ScCompiler::mxSymbolsEnglish;
CharClass* ScCompiler::pCharClassEnglish = NULL;
-const ScCompiler::Convention* ScCompiler::pConventions[ ] = { NULL, NULL, NULL, NULL };
+const ScCompiler::Convention* ScCompiler::pConventions[ ] = { NULL, NULL, NULL, NULL, NULL, NULL };
enum ScanState
{
@@ -664,20 +666,15 @@ void ScCompiler::SetGrammar( const ScGrammar::Grammar eGrammar )
xMap = ScCompiler::GetOpCodeMap( ::com::sun::star::sheet::FormulaLanguage::NATIVE);
eMyGrammar = xMap->getGrammar();
}
- SetFormulaLanguage( xMap);
+ // Save old grammar for call to SetGrammarAndRefConvention().
ScGrammar::Grammar eOldGrammar = GetGrammar();
- meGrammar = eMyGrammar; //! SetRefConvention needs the new grammar set!
- ScAddress::Convention eConv = ScGrammar::extractRefConvention( eMyGrammar);
- if (eConv == ScAddress::CONV_UNSPECIFIED && eOldGrammar == ScGrammar::GRAM_UNSPECIFIED)
- {
- if (NULL != pDoc)
- SetRefConvention( pDoc->GetAddressConvention());
- else
- SetRefConvention( pConvOOO_A1);
- }
- else
- SetRefConvention( eConv );
+ // This also sets the grammar associated with the map!
+ SetFormulaLanguage( xMap);
+
+ // Override if necessary.
+ if (eMyGrammar != GetGrammar())
+ SetGrammarAndRefConvention( eMyGrammar, eOldGrammar);
}
@@ -694,7 +691,25 @@ void ScCompiler::SetFormulaLanguage( const ScCompiler::OpCodeMapPtr & xMap )
}
else
pCharClass = ScGlobal::pCharClass;
+ SetGrammarAndRefConvention( mxSymbols->getGrammar(), GetGrammar());
+ }
+}
+
+
+void ScCompiler::SetGrammarAndRefConvention(
+ const ScGrammar::Grammar eNewGrammar, const ScGrammar::Grammar eOldGrammar )
+{
+ meGrammar = eNewGrammar; //! SetRefConvention needs the new grammar set!
+ ScAddress::Convention eConv = ScGrammar::extractRefConvention( meGrammar);
+ if (eConv == ScAddress::CONV_UNSPECIFIED && eOldGrammar == ScGrammar::GRAM_UNSPECIFIED)
+ {
+ if (pDoc)
+ SetRefConvention( pDoc->GetAddressConvention());
+ else
+ SetRefConvention( pConvOOO_A1);
}
+ else
+ SetRefConvention( eConv );
}
@@ -823,20 +838,19 @@ ScCompiler::OpCodeMap::createSequenceOfAvailableMappings( const sal_Int32 nGroup
sal_Int32 nOff;
OpCode eOp;
} aMap[] = {
- { FormulaMapGroupSpecialOffset::PUSH , ocPush } ,
- { FormulaMapGroupSpecialOffset::CALL , ocCall } ,
- { FormulaMapGroupSpecialOffset::STOP , ocStop } ,
- { FormulaMapGroupSpecialOffset::EXTERNAL , ocExternal } ,
- { FormulaMapGroupSpecialOffset::NAME , ocName } ,
- { FormulaMapGroupSpecialOffset::NO_NAME , ocNoName } ,
- { FormulaMapGroupSpecialOffset::MISSING , ocMissing } ,
- { FormulaMapGroupSpecialOffset::BAD , ocBad } ,
- { FormulaMapGroupSpecialOffset::SPACES , ocSpaces } ,
- { FormulaMapGroupSpecialOffset::MAT_REF , ocMatRef } ,
- { FormulaMapGroupSpecialOffset::DB_AREA , ocDBArea } ,
- { FormulaMapGroupSpecialOffset::MACRO , ocMacro } ,
- { FormulaMapGroupSpecialOffset::COL_ROW_NAME , ocColRowName } ,
- { FormulaMapGroupSpecialOffset::COL_ROW_NAME_AUTO , ocColRowNameAuto }
+ { FormulaMapGroupSpecialOffset::PUSH , ocPush } ,
+ { FormulaMapGroupSpecialOffset::CALL , ocCall } ,
+ { FormulaMapGroupSpecialOffset::STOP , ocStop } ,
+ { FormulaMapGroupSpecialOffset::EXTERNAL , ocExternal } ,
+ { FormulaMapGroupSpecialOffset::NAME , ocName } ,
+ { FormulaMapGroupSpecialOffset::NO_NAME , ocNoName } ,
+ { FormulaMapGroupSpecialOffset::MISSING , ocMissing } ,
+ { FormulaMapGroupSpecialOffset::BAD , ocBad } ,
+ { FormulaMapGroupSpecialOffset::SPACES , ocSpaces } ,
+ { FormulaMapGroupSpecialOffset::MAT_REF , ocMatRef } ,
+ { FormulaMapGroupSpecialOffset::DB_AREA , ocDBArea } ,
+ { FormulaMapGroupSpecialOffset::MACRO , ocMacro } ,
+ { FormulaMapGroupSpecialOffset::COL_ROW_NAME , ocColRowName }
};
const size_t nCount = sizeof(aMap)/sizeof(aMap[0]);
// Preallocate vector elements.
@@ -1035,10 +1049,12 @@ ScCompiler::Convention::Convention( ScAddress::Convention eConv )
/* */ t[32] = SC_COMPILER_C_CHAR_DONTCARE | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
/* ! */ t[33] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
if (ScAddress::CONV_ODF == meConv)
- t[33] |= SC_COMPILER_C_ODF_LABEL_OP;
+/* ! */ t[33] |= SC_COMPILER_C_ODF_LABEL_OP;
/* " */ t[34] = SC_COMPILER_C_CHAR_STRING | SC_COMPILER_C_STRING_SEP;
/* # */ t[35] = SC_COMPILER_C_WORD_SEP;
/* $ */ t[36] = SC_COMPILER_C_CHAR_WORD | SC_COMPILER_C_WORD | SC_COMPILER_C_CHAR_IDENT | SC_COMPILER_C_IDENT;
+ if (ScAddress::CONV_ODF == meConv)
+/* $ */ t[36] |= SC_COMPILER_C_ODF_NAME_MARKER;
/* % */ t[37] = SC_COMPILER_C_VALUE;
/* & */ t[38] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
/* ' */ t[39] = SC_COMPILER_C_NAME_SEP;
@@ -1050,8 +1066,10 @@ ScCompiler::Convention::Convention( ScAddress::Convention eConv )
/* - */ t[45] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_EXP | SC_COMPILER_C_VALUE_SIGN;
/* . */ t[46] = SC_COMPILER_C_WORD | SC_COMPILER_C_CHAR_VALUE | SC_COMPILER_C_VALUE | SC_COMPILER_C_IDENT;
/* / */ t[47] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
-for (i = 48; i < 58; i++)
+
+ for (i = 48; i < 58; i++)
/* 0-9 */ t[i] = SC_COMPILER_C_CHAR_VALUE | SC_COMPILER_C_WORD | SC_COMPILER_C_VALUE | SC_COMPILER_C_VALUE_EXP | SC_COMPILER_C_VALUE_VALUE | SC_COMPILER_C_IDENT;
+
/* : */ t[58] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD;
/* ; */ t[59] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
/* < */ t[60] = SC_COMPILER_C_CHAR_BOOL | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
@@ -1059,8 +1077,10 @@ for (i = 48; i < 58; i++)
/* > */ t[62] = SC_COMPILER_C_CHAR_BOOL | SC_COMPILER_C_BOOL | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
/* ? */ t[63] = SC_COMPILER_C_CHAR_WORD | SC_COMPILER_C_WORD;
/* @ */ // FREE
-for (i = 65; i < 91; i++)
+
+ for (i = 65; i < 91; i++)
/* A-Z */ t[i] = SC_COMPILER_C_CHAR_WORD | SC_COMPILER_C_WORD | SC_COMPILER_C_CHAR_IDENT | SC_COMPILER_C_IDENT;
+
if (ScAddress::CONV_ODF == meConv)
{
/* [ */ t[91] = SC_COMPILER_C_ODF_LBRACKET;
@@ -1076,14 +1096,17 @@ for (i = 65; i < 91; i++)
/* ^ */ t[94] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
/* _ */ t[95] = SC_COMPILER_C_CHAR_WORD | SC_COMPILER_C_WORD | SC_COMPILER_C_CHAR_IDENT | SC_COMPILER_C_IDENT;
/* ` */ // FREE
-for (i = 97; i < 123; i++)
+
+ for (i = 97; i < 123; i++)
/* a-z */ t[i] = SC_COMPILER_C_CHAR_WORD | SC_COMPILER_C_WORD | SC_COMPILER_C_CHAR_IDENT | SC_COMPILER_C_IDENT;
+
/* { */ t[123] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP; // array open
/* | */ t[124] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP; // array row sep (Should be OOo specific)
/* } */ t[125] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP; // array close
/* ~ */ t[126] = SC_COMPILER_C_CHAR; // OOo specific
/* 127 */ // FREE
- if( ScAddress::CONV_XL_A1 == meConv || ScAddress::CONV_XL_R1C1 == meConv )
+
+ if( ScAddress::CONV_XL_A1 == meConv || ScAddress::CONV_XL_R1C1 == meConv || ScAddress::CONV_XL_OOX == meConv )
{
/* */ t[32] |= SC_COMPILER_C_WORD;
/* ! */ t[33] |= SC_COMPILER_C_IDENT | SC_COMPILER_C_WORD;
@@ -1122,9 +1145,14 @@ for (i = 97; i < 123; i++)
if( ScAddress::CONV_XL_R1C1 == meConv )
{
- /* - */ t[45] |= SC_COMPILER_C_IDENT;
- /* [ */ t[91] |= SC_COMPILER_C_IDENT;
- /* ] */ t[93] |= SC_COMPILER_C_IDENT;
+/* - */ t[45] |= SC_COMPILER_C_IDENT;
+/* [ */ t[91] |= SC_COMPILER_C_IDENT;
+/* ] */ t[93] |= SC_COMPILER_C_IDENT;
+ }
+ if( ScAddress::CONV_XL_OOX == meConv )
+ {
+/* [ */ t[91] |= SC_COMPILER_C_CHAR_IDENT;
+/* ] */ t[93] |= SC_COMPILER_C_IDENT;
}
}
}
@@ -1148,7 +1176,7 @@ static bool lcl_isValidQuotedText( const String& rFormula, xub_StrLen nSrcPos, P
{
rRes.TokenType = KParseType::SINGLE_QUOTE_NAME;
rRes.EndPos = nPos+1;
- return false;
+ return true;
}
++nPos;
}
@@ -1156,9 +1184,231 @@ static bool lcl_isValidQuotedText( const String& rFormula, xub_StrLen nSrcPos, P
}
}
+ return false;
+}
+
+static bool lcl_parseExternalName(
+ const String& rSymbol,
+ String& rFile,
+ String& rName,
+ const sal_Unicode cSep,
+ const ScDocument* pDoc = NULL,
+ const uno::Sequence< const sheet::ExternalLinkInfo > * pExternalLinks = NULL )
+{
+ /* TODO: future versions will have to support sheet-local names too, thus
+ * return a possible sheet name as well. */
+ const sal_Unicode* const pStart = rSymbol.GetBuffer();
+ const sal_Unicode* p = pStart;
+ xub_StrLen nLen = rSymbol.Len();
+ sal_Unicode cPrev = 0;
+ String aTmpFile, aTmpName;
+ xub_StrLen i = 0;
+ bool bInName = false;
+ if (cSep == '!')
+ {
+ // For XL use existing parser that resolves bracketed and quoted and
+ // indexed external document names.
+ ScRange aRange;
+ String aStartTabName, aEndTabName;
+ USHORT nFlags = 0;
+ p = aRange.Parse_XL_Header( p, pDoc, aTmpFile, aStartTabName,
+ aEndTabName, nFlags, true, pExternalLinks );
+ if (!p || p == pStart)
+ return false;
+ i = p - pStart;
+ cPrev = *(p-1);
+ }
+ for ( ; i < nLen; ++i, ++p)
+ {
+ sal_Unicode c = *p;
+ if (i == 0)
+ {
+ if (c == '.' || c == cSep)
+ return false;
+
+ if (c == '\'')
+ {
+ // Move to the next chart and loop until the second single
+ // quote.
+ cPrev = c;
+ ++i; ++p;
+ for (xub_StrLen j = i; j < nLen; ++j, ++p)
+ {
+ c = *p;
+ if (c == '\'')
+ {
+ if (j == i)
+ {
+ // empty quote e.g. (=''!Name)
+ return false;
+ }
+
+ if (cPrev == '\'')
+ {
+ // two consecutive quotes equals a single
+ // quote in the file name.
+ aTmpFile.Append(c);
+ cPrev = 'a';
+ }
+ else
+ cPrev = c;
+
+ continue;
+ }
+
+ if (cPrev == '\'' && j != i)
+ {
+ // this is not a quote but the previous one
+ // is. This ends the parsing of the quoted
+ // segment.
+
+ i = j;
+ bInName = true;
+ break;
+ }
+ aTmpFile.Append(c);
+ cPrev = c;
+ }
+
+ if (!bInName)
+ {
+ // premature ending of the quoted segment.
+ return false;
+ }
+
+ if (c != cSep)
+ {
+ // only the separator is allowed after the closing quote.
+ return false;
+ }
+
+ cPrev = c;
+ continue;
+ }
+ }
+
+ if (bInName)
+ {
+ if (c == cSep)
+ {
+ // A second separator ? Not a valid external name.
+ return false;
+ }
+ aTmpName.Append(c);
+ }
+ else
+ {
+ if (c == cSep)
+ {
+ bInName = true;
+ }
+ else
+ {
+ do
+ {
+ if (CharClass::isAsciiAlphaNumeric(c))
+ // allowed.
+ break;
+
+ if (c > 128)
+ // non-ASCII character is allowed.
+ break;
+
+ bool bValid = false;
+ switch (c)
+ {
+ case '_':
+ case '-':
+ case '.':
+ // these special characters are allowed.
+ bValid = true;
+ break;
+ }
+ if (bValid)
+ break;
+
+ return false;
+ }
+ while (false);
+ aTmpFile.Append(c);
+ }
+ }
+ cPrev = c;
+ }
+
+ if (!bInName)
+ {
+ // No name found - most likely the symbol has no '!'s.
+ return false;
+ }
+
+ rFile = aTmpFile;
+ rName = aTmpName;
return true;
}
+static String lcl_makeExternalNameStr( const String& rFile, const String& rName,
+ const sal_Unicode cSep, bool bODF )
+{
+ String aFile( rFile), aName( rName), aEscQuote( RTL_CONSTASCII_USTRINGPARAM("''"));
+ aFile.SearchAndReplaceAllAscii( "'", aEscQuote);
+ if (bODF)
+ aName.SearchAndReplaceAllAscii( "'", aEscQuote);
+ rtl::OUStringBuffer aBuf( aFile.Len() + aName.Len() + 9);
+ if (bODF)
+ aBuf.append( sal_Unicode( '['));
+ aBuf.append( sal_Unicode( '\''));
+ aBuf.append( aFile);
+ aBuf.append( sal_Unicode( '\''));
+ aBuf.append( cSep);
+ if (bODF)
+ aBuf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "$$'"));
+ aBuf.append( aName);
+ if (bODF)
+ aBuf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "']"));
+ return String( aBuf.makeStringAndClear());
+}
+
+static bool lcl_getLastTabName( String& rTabName2, const String& rTabName1,
+ const vector<String>& rTabNames, const ComplRefData& rRef )
+{
+ SCsTAB nTabSpan = rRef.Ref2.nTab - rRef.Ref1.nTab;
+ if (nTabSpan > 0)
+ {
+ size_t nCount = rTabNames.size();
+ vector<String>::const_iterator itrBeg = rTabNames.begin(), itrEnd = rTabNames.end();
+ vector<String>::const_iterator itr = ::std::find(itrBeg, itrEnd, rTabName1);
+ if (itr == rTabNames.end())
+ {
+ rTabName2 = ScGlobal::GetRscString(STR_NO_REF_TABLE);
+ return false;
+ }
+
+ size_t nDist = ::std::distance(itrBeg, itr);
+ if (nDist + static_cast<size_t>(nTabSpan) >= nCount)
+ {
+ rTabName2 = ScGlobal::GetRscString(STR_NO_REF_TABLE);
+ return false;
+ }
+
+ rTabName2 = rTabNames[nDist+nTabSpan];
+ }
+ else
+ rTabName2 = rTabName1;
+
+ return true;
+}
+
+static void lcl_appendTabName(::rtl::OUStringBuffer& rBuffer, const String& rTabName)
+{
+ bool bQuote = (rTabName.Search(sal_Unicode(' '), 0) != STRING_NOTFOUND);
+ if (bQuote)
+ rBuffer.append(sal_Unicode('\''));
+ rBuffer.append(rTabName);
+ if (bQuote)
+ rBuffer.append(sal_Unicode('\''));
+}
+
struct Convention_A1 : public ScCompiler::Convention
{
Convention_A1( ScAddress::Convention eConv ) : ScCompiler::Convention( eConv ) { }
@@ -1170,14 +1420,14 @@ struct Convention_A1 : public ScCompiler::Convention
const CharClass* pCharClass) const
{
ParseResult aRet;
- if ( !lcl_isValidQuotedText(rFormula, nSrcPos, aRet) )
+ if ( lcl_isValidQuotedText(rFormula, nSrcPos, aRet) )
return aRet;
static const sal_Int32 nStartFlags = KParseTokens::ANY_LETTER_OR_NUMBER |
KParseTokens::ASC_UNDERSCORE | KParseTokens::ASC_DOLLAR;
static const sal_Int32 nContFlags = nStartFlags | KParseTokens::ASC_DOT;
// '?' allowed in range names because of Xcl :-/
- static const String aAddAllowed( '?' );
+ static const String aAddAllowed(String::CreateFromAscii("?#"));
return pCharClass->parseAnyToken( rFormula,
nSrcPos, nStartFlags, aAddAllowed, nContFlags, aAddAllowed );
}
@@ -1214,13 +1464,11 @@ struct ConventionOOO_A1 : public Convention_A1
{
if ( aString.GetChar(0) == '\'' )
{ // "'Doc'#Tab"
- xub_StrLen nPos, nLen = 1;
- while( (nPos = aString.Search( '\'', nLen )) != STRING_NOTFOUND )
- nLen = nPos + 1;
- if ( aString.GetChar(nLen) == SC_COMPILER_FILE_TAB_SEP )
+ xub_StrLen nPos = ScGlobal::FindUnquoted( aString, SC_COMPILER_FILE_TAB_SEP);
+ if (nPos != STRING_NOTFOUND && nPos > 0 && aString.GetChar(nPos-1) == '\'')
{
- aDoc = aString.Copy( 0, nLen + 1 );
- aString.Erase( 0, nLen + 1 );
+ aDoc = aString.Copy( 0, nPos + 1 );
+ aString.Erase( 0, nPos + 1 );
aDoc = INetURLObject::decode( aDoc, INET_HEX_ESCAPE,
INetURLObject::DECODE_UNAMBIGUOUS );
}
@@ -1344,6 +1592,124 @@ struct ConventionOOO_A1 : public Convention_A1
return sal_Unicode(0);
}
+
+ virtual bool parseExternalName( const String& rSymbol, String& rFile, String& rName,
+ const ScDocument* pDoc,
+ const ::com::sun::star::uno::Sequence<
+ const ::com::sun::star::sheet::ExternalLinkInfo > * pExternalLinks ) const
+ {
+ return lcl_parseExternalName(rSymbol, rFile, rName, sal_Unicode('#'), pDoc, pExternalLinks);
+ }
+
+ virtual String makeExternalNameStr( const String& rFile, const String& rName ) const
+ {
+ return lcl_makeExternalNameStr( rFile, rName, sal_Unicode('#'), false);
+ }
+
+ bool makeExternalSingleRefStr( ::rtl::OUStringBuffer& rBuffer, sal_uInt16 nFileId,
+ const String& rTabName, const SingleRefData& rRef,
+ ScExternalRefManager* pRefMgr, bool bDisplayTabName ) const
+ {
+ if (bDisplayTabName)
+ {
+ String aFile;
+ const String* p = pRefMgr->getExternalFileName(nFileId);
+ if (p)
+ aFile = *p;
+ aFile.SearchAndReplaceAllAscii("'", String::CreateFromAscii("''"));
+
+ rBuffer.append(sal_Unicode('\''));
+ rBuffer.append(aFile);
+ rBuffer.append(sal_Unicode('\''));
+ rBuffer.append(sal_Unicode('#'));
+
+ // external reference is always 3D and the sheet is absolute.
+ rBuffer.append(sal_Unicode('$'));
+ lcl_appendTabName(rBuffer, rTabName);
+
+ rBuffer.append(sal_Unicode('.'));
+ }
+
+ if (!rRef.IsColRel())
+ rBuffer.append(sal_Unicode('$'));
+ MakeColStr( rBuffer, rRef.nCol);
+ if (!rRef.IsRowRel())
+ rBuffer.append(sal_Unicode('$'));
+ MakeRowStr( rBuffer, rRef.nRow);
+
+ return true;
+ }
+
+ void makeExternalRefStrImpl( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
+ sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef,
+ ScExternalRefManager* pRefMgr, bool bODF ) const
+ {
+ SingleRefData aRef(rRef);
+ aRef.CalcAbsIfRel(rCompiler.GetPos());
+
+ if (bODF)
+ rBuffer.append( sal_Unicode('['));
+ makeExternalSingleRefStr(rBuffer, nFileId, rTabName, aRef, pRefMgr, true);
+ if (bODF)
+ rBuffer.append( sal_Unicode(']'));
+ }
+
+ virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
+ sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef,
+ ScExternalRefManager* pRefMgr ) const
+ {
+ makeExternalRefStrImpl( rBuffer, rCompiler, nFileId, rTabName, rRef, pRefMgr, false);
+ }
+
+ void makeExternalRefStrImpl( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
+ sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef,
+ ScExternalRefManager* pRefMgr, bool bODF ) const
+ {
+ ComplRefData aRef(rRef);
+ aRef.CalcAbsIfRel(rCompiler.GetPos());
+
+ if (bODF)
+ rBuffer.append( sal_Unicode('['));
+ // Ensure that there's always a closing bracket, no premature returns.
+ do
+ {
+ if (!makeExternalSingleRefStr(rBuffer, nFileId, rTabName, aRef.Ref1, pRefMgr, true))
+ break;
+
+ rBuffer.append(sal_Unicode(':'));
+
+ // Get the name of the last table.
+ vector<String> aTabNames;
+ pRefMgr->getAllCachedTableNames(nFileId, aTabNames);
+ if (aTabNames.empty())
+ {
+ DBG_ERROR1( "ConventionOOO_A1::makeExternalRefStrImpl: no sheet names for document ID %s", nFileId);
+ break;
+ }
+
+ String aLastTabName;
+ if (!lcl_getLastTabName(aLastTabName, rTabName, aTabNames, aRef))
+ {
+ rBuffer.append(aLastTabName);
+ DBG_ERROR( "ConventionOOO_A1::makeExternalRefStrImpl: sheet name not found");
+ break;
+ }
+ bool bDisplayTabName = (aRef.Ref1.nTab != aRef.Ref2.nTab);
+ if (bODF && !bDisplayTabName)
+ rBuffer.append( sal_Unicode('.')); // need at least the sheet separator in ODF
+ makeExternalSingleRefStr( rBuffer, nFileId, aLastTabName,
+ aRef.Ref2, pRefMgr, bDisplayTabName);
+ } while (0);
+ if (bODF)
+ rBuffer.append( sal_Unicode(']'));
+ }
+
+ virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
+ sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef,
+ ScExternalRefManager* pRefMgr ) const
+ {
+ makeExternalRefStrImpl( rBuffer, rCompiler, nFileId, rTabName, rRef, pRefMgr, false);
+ }
};
@@ -1362,6 +1728,25 @@ struct ConventionOOO_A1_ODF : public ConventionOOO_A1
{
MakeRefStrImpl( rBuffer, rComp, rRef, bSingleRef, true);
}
+
+ virtual String makeExternalNameStr( const String& rFile, const String& rName ) const
+ {
+ return lcl_makeExternalNameStr( rFile, rName, sal_Unicode('#'), true);
+ }
+
+ virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
+ sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef,
+ ScExternalRefManager* pRefMgr ) const
+ {
+ makeExternalRefStrImpl( rBuffer, rCompiler, nFileId, rTabName, rRef, pRefMgr, true);
+ }
+
+ virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
+ sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef,
+ ScExternalRefManager* pRefMgr ) const
+ {
+ makeExternalRefStrImpl( rBuffer, rCompiler, nFileId, rTabName, rRef, pRefMgr, true);
+ }
};
static const ConventionOOO_A1_ODF ConvOOO_A1_ODF;
@@ -1389,18 +1774,14 @@ struct ConventionXL
// Cheesy hack to unparse the OOO style "'Doc'#Tab"
if ( rTabName.GetChar(0) == '\'' )
{
- xub_StrLen nPos, nLen = 1;
-
- while( (nPos = rTabName.Search( '\'', nLen )) != STRING_NOTFOUND )
- nLen = nPos + 1;
-
- if ( rTabName.GetChar(nLen) == SC_COMPILER_FILE_TAB_SEP )
+ xub_StrLen nPos = ScGlobal::FindUnquoted( rTabName, SC_COMPILER_FILE_TAB_SEP);
+ if (nPos != STRING_NOTFOUND && nPos > 0 && rTabName.GetChar(nPos-1) == '\'')
{
- rDocName = rTabName.Copy( 0, nLen );
+ rDocName = rTabName.Copy( 0, nPos );
// TODO : More research into how XL escapes the doc path
rDocName = INetURLObject::decode( rDocName, INET_HEX_ESCAPE,
INetURLObject::DECODE_UNAMBIGUOUS );
- rTabName.Erase( 0, nLen + 1 );
+ rTabName.Erase( 0, nPos + 1 );
bHasDoc = true;
}
}
@@ -1465,11 +1846,132 @@ struct ConventionXL
}
return sal_Unicode(0);
}
+
+ static bool parseExternalName( const String& rSymbol, String& rFile, String& rName,
+ const ScDocument* pDoc,
+ const ::com::sun::star::uno::Sequence<
+ const ::com::sun::star::sheet::ExternalLinkInfo > * pExternalLinks )
+ {
+ return lcl_parseExternalName( rSymbol, rFile, rName, sal_Unicode('!'), pDoc, pExternalLinks);
+ }
+
+ static String makeExternalNameStr( const String& rFile, const String& rName )
+ {
+ return lcl_makeExternalNameStr( rFile, rName, sal_Unicode('!'), false);
+ }
+
+ static void makeExternalDocStr( ::rtl::OUStringBuffer& rBuffer, const String& rFullName )
+ {
+ // Format that is easier to deal with inside OOo, because we use file
+ // URL, and all characetrs are allowed. Check if it makes sense to do
+ // it the way Gnumeric does it. Gnumeric doesn't use the URL form
+ // and allows relative file path.
+ //
+ // ['file:///path/to/source/filename.xls']
+
+ rBuffer.append(sal_Unicode('['));
+ rBuffer.append(sal_Unicode('\''));
+ const sal_Unicode* pBuf = rFullName.GetBuffer();
+ xub_StrLen nLen = rFullName.Len();
+ for (xub_StrLen i = 0; i < nLen; ++i)
+ {
+ const sal_Unicode c = pBuf[i];
+ if (c == sal_Unicode('\''))
+ rBuffer.append(c);
+ rBuffer.append(c);
+ }
+ rBuffer.append(sal_Unicode('\''));
+ rBuffer.append(sal_Unicode(']'));
+ }
+
+ static void makeExternalTabNameRange( ::rtl::OUStringBuffer& rBuf, const String& rTabName,
+ const vector<String>& rTabNames,
+ const ComplRefData& rRef )
+ {
+ String aLastTabName;
+ if (!lcl_getLastTabName(aLastTabName, rTabName, rTabNames, rRef))
+ {
+ rBuf.append(aLastTabName);
+ return;
+ }
+
+ lcl_appendTabName(rBuf, rTabName);
+ if (rTabName != aLastTabName)
+ {
+ rBuf.append(sal_Unicode(':'));
+ lcl_appendTabName(rBuf, aLastTabName);
+ }
+ }
+
+ static void parseExternalDocName( const String& rFormula, xub_StrLen& rSrcPos )
+ {
+ xub_StrLen nLen = rFormula.Len();
+ const sal_Unicode* p = rFormula.GetBuffer();
+ sal_Unicode cPrev = 0;
+ for (xub_StrLen i = rSrcPos; i < nLen; ++i)
+ {
+ sal_Unicode c = p[i];
+ if (i == rSrcPos)
+ {
+ // first character must be '['.
+ if (c != '[')
+ return;
+ }
+ else if (i == rSrcPos + 1)
+ {
+ // second character must be a single quote.
+ if (c != '\'')
+ return;
+ }
+ else if (c == '\'')
+ {
+ if (cPrev == '\'')
+ // two successive single quote is treated as a single
+ // valid character.
+ c = 'a';
+ }
+ else if (c == ']')
+ {
+ if (cPrev == '\'')
+ {
+ // valid source document path found. Increment the
+ // current position to skip the source path.
+ rSrcPos = i + 1;
+ if (rSrcPos >= nLen)
+ rSrcPos = nLen - 1;
+ return;
+ }
+ else
+ return;
+ }
+ else
+ {
+ // any other character
+ if (i > rSrcPos + 2 && cPrev == '\'')
+ // unless it's the 3rd character, a normal character
+ // following immediately a single quote is invalid.
+ return;
+ }
+ cPrev = c;
+ }
+ }
};
struct ConventionXL_A1 : public Convention_A1, public ConventionXL
{
ConventionXL_A1() : Convention_A1( ScAddress::CONV_XL_A1 ) { }
+ ConventionXL_A1( ScAddress::Convention eConv ) : Convention_A1( eConv ) { }
+
+ void makeSingleCellStr( ::rtl::OUStringBuffer& rBuf, const SingleRefData& rRef ) const
+ {
+ if (!rRef.IsColRel())
+ rBuf.append(sal_Unicode('$'));
+ MakeColStr(rBuf, rRef.nCol);
+ if (!rRef.IsRowRel())
+ rBuf.append(sal_Unicode('$'));
+ MakeRowStr(rBuf, rRef.nRow);
+ }
+
void MakeRefStr( rtl::OUStringBuffer& rBuf,
const ScCompiler& rComp,
const ComplRefData& rRef,
@@ -1523,34 +2025,115 @@ struct ConventionXL_A1 : public Convention_A1, public ConventionXL
}
}
- if (!aRef.Ref1.IsColRel())
- rBuf.append(sal_Unicode('$'));
- MakeColStr(rBuf, aRef.Ref1.nCol );
- if (!aRef.Ref1.IsRowRel())
- rBuf.append(sal_Unicode('$'));
- MakeRowStr( rBuf, aRef.Ref1.nRow );
-
+ makeSingleCellStr(rBuf, aRef.Ref1);
if (!bSingleRef)
{
rBuf.append(sal_Unicode( ':' ));
- if (!aRef.Ref2.IsColRel())
- rBuf.append(sal_Unicode('$'));
- MakeColStr(rBuf, aRef.Ref2.nCol );
- if (!aRef.Ref2.IsRowRel())
- rBuf.append(sal_Unicode('$'));
- MakeRowStr( rBuf, aRef.Ref2.nRow );
+ makeSingleCellStr(rBuf, aRef.Ref2);
}
}
+ virtual ParseResult parseAnyToken( const String& rFormula,
+ xub_StrLen nSrcPos,
+ const CharClass* pCharClass) const
+ {
+ ParseResult aRet;
+ if ( lcl_isValidQuotedText(rFormula, nSrcPos, aRet) )
+ return aRet;
+
+ static const sal_Int32 nStartFlags = KParseTokens::ANY_LETTER_OR_NUMBER |
+ KParseTokens::ASC_UNDERSCORE | KParseTokens::ASC_DOLLAR;
+ static const sal_Int32 nContFlags = nStartFlags | KParseTokens::ASC_DOT;
+ // '?' allowed in range names
+ static const String aAddAllowed = String::CreateFromAscii("?!");
+ return pCharClass->parseAnyToken( rFormula,
+ nSrcPos, nStartFlags, aAddAllowed, nContFlags, aAddAllowed );
+ }
+
virtual sal_Unicode getSpecialSymbol( SpecialSymbolType eSymType ) const
{
return ConventionXL::getSpecialSymbol(eSymType);
}
+
+ virtual bool parseExternalName( const String& rSymbol, String& rFile, String& rName,
+ const ScDocument* pDoc,
+ const ::com::sun::star::uno::Sequence<
+ const ::com::sun::star::sheet::ExternalLinkInfo > * pExternalLinks ) const
+ {
+ return ConventionXL::parseExternalName( rSymbol, rFile, rName, pDoc, pExternalLinks);
+ }
+
+ virtual String makeExternalNameStr( const String& rFile, const String& rName ) const
+ {
+ return ConventionXL::makeExternalNameStr(rFile, rName);
+ }
+
+ virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
+ sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef,
+ ScExternalRefManager* pRefMgr ) const
+ {
+ // ['file:///path/to/file/filename.xls']'Sheet Name'!$A$1
+ // This is a little different from the format Excel uses, as Excel
+ // puts [] only around the file name. But we need to enclose the
+ // whole file path with [] because the file name can contain any
+ // characters.
+
+ const String* pFullName = pRefMgr->getExternalFileName(nFileId);
+ if (!pFullName)
+ return;
+
+ SingleRefData aRef(rRef);
+ aRef.CalcAbsIfRel(rCompiler.GetPos());
+
+ ConventionXL::makeExternalDocStr(rBuffer, *pFullName);
+ lcl_appendTabName(rBuffer, rTabName);
+ rBuffer.append(sal_Unicode('!'));
+
+ makeSingleCellStr(rBuffer, aRef);
+ }
+
+ virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
+ sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef,
+ ScExternalRefManager* pRefMgr ) const
+ {
+ const String* pFullName = pRefMgr->getExternalFileName(nFileId);
+ if (!pFullName)
+ return;
+
+ vector<String> aTabNames;
+ pRefMgr->getAllCachedTableNames(nFileId, aTabNames);
+ if (aTabNames.empty())
+ return;
+
+ ComplRefData aRef(rRef);
+ aRef.CalcAbsIfRel(rCompiler.GetPos());
+
+ ConventionXL::makeExternalDocStr(rBuffer, *pFullName);
+ ConventionXL::makeExternalTabNameRange(rBuffer, rTabName, aTabNames, aRef);
+ rBuffer.append(sal_Unicode('!'));
+
+ makeSingleCellStr(rBuffer, aRef.Ref1);
+ if (aRef.Ref1 != aRef.Ref2)
+ {
+ rBuffer.append(sal_Unicode(':'));
+ makeSingleCellStr(rBuffer, aRef.Ref2);
+ }
+ }
};
static const ConventionXL_A1 ConvXL_A1;
const ScCompiler::Convention * const ScCompiler::pConvXL_A1 = &ConvXL_A1;
+
+struct ConventionXL_OOX : public ConventionXL_A1
+{
+ ConventionXL_OOX() : ConventionXL_A1( ScAddress::CONV_XL_OOX ) { }
+};
+
+static const ConventionXL_OOX ConvXL_OOX;
+const ScCompiler::Convention * const ScCompiler::pConvXL_OOX = &ConvXL_OOX;
+
+
//-----------------------------------------------------------------------------
static void
@@ -1655,15 +2238,17 @@ struct ConventionXL_R1C1 : public ScCompiler::Convention, public ConventionXL
xub_StrLen nSrcPos,
const CharClass* pCharClass) const
{
+ ConventionXL::parseExternalDocName(rFormula, nSrcPos);
+
ParseResult aRet;
- if ( !lcl_isValidQuotedText(rFormula, nSrcPos, aRet) )
+ if ( lcl_isValidQuotedText(rFormula, nSrcPos, aRet) )
return aRet;
static const sal_Int32 nStartFlags = KParseTokens::ANY_LETTER_OR_NUMBER |
KParseTokens::ASC_UNDERSCORE ;
static const sal_Int32 nContFlags = nStartFlags | KParseTokens::ASC_DOT;
- // '?' allowed in range names because of Xcl :-/
- static const String aAddAllowed = String::CreateFromAscii( "?-[]" );
+ // '?' allowed in range names
+ static const String aAddAllowed = String::CreateFromAscii( "?-[]!" );
return pCharClass->parseAnyToken( rFormula,
nSrcPos, nStartFlags, aAddAllowed, nContFlags, aAddAllowed );
@@ -1673,6 +2258,99 @@ struct ConventionXL_R1C1 : public ScCompiler::Convention, public ConventionXL
{
return ConventionXL::getSpecialSymbol(eSymType);
}
+
+ virtual bool parseExternalName( const String& rSymbol, String& rFile, String& rName,
+ const ScDocument* pDoc,
+ const ::com::sun::star::uno::Sequence<
+ const ::com::sun::star::sheet::ExternalLinkInfo > * pExternalLinks ) const
+ {
+ return ConventionXL::parseExternalName( rSymbol, rFile, rName, pDoc, pExternalLinks);
+ }
+
+ virtual String makeExternalNameStr( const String& rFile, const String& rName ) const
+ {
+ return ConventionXL::makeExternalNameStr(rFile, rName);
+ }
+
+ virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
+ sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef,
+ ScExternalRefManager* pRefMgr ) const
+ {
+ // ['file:///path/to/file/filename.xls']'Sheet Name'!$A$1
+ // This is a little different from the format Excel uses, as Excel
+ // puts [] only around the file name. But we need to enclose the
+ // whole file path with [] because the file name can contain any
+ // characters.
+
+ const String* pFullName = pRefMgr->getExternalFileName(nFileId);
+ if (!pFullName)
+ return;
+
+ SingleRefData aRef(rRef);
+ aRef.CalcAbsIfRel(rCompiler.GetPos());
+
+ ConventionXL::makeExternalDocStr(rBuffer, *pFullName);
+ lcl_appendTabName(rBuffer, rTabName);
+ rBuffer.append(sal_Unicode('!'));
+
+ r1c1_add_row(rBuffer, aRef);
+ r1c1_add_col(rBuffer, aRef);
+ }
+
+ virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
+ sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef,
+ ScExternalRefManager* pRefMgr ) const
+ {
+ const String* pFullName = pRefMgr->getExternalFileName(nFileId);
+ if (!pFullName)
+ return;
+
+ vector<String> aTabNames;
+ pRefMgr->getAllCachedTableNames(nFileId, aTabNames);
+ if (aTabNames.empty())
+ return;
+
+ ComplRefData aRef(rRef);
+ aRef.CalcAbsIfRel(rCompiler.GetPos());
+
+ ConventionXL::makeExternalDocStr(rBuffer, *pFullName);
+ ConventionXL::makeExternalTabNameRange(rBuffer, rTabName, aTabNames, aRef);
+ rBuffer.append(sal_Unicode('!'));
+
+ if (aRef.Ref2.IsColDeleted() || aRef.Ref2.IsRowDeleted())
+ {
+ rBuffer.append(ScGlobal::GetRscString(STR_NO_REF_TABLE));
+ return;
+ }
+
+ if (aRef.Ref1.nCol == 0 && aRef.Ref2.nCol >= MAXCOL)
+ {
+ r1c1_add_row(rBuffer, rRef.Ref1);
+ if (rRef.Ref1.nRow != rRef.Ref2.nRow || rRef.Ref1.IsRowRel() != rRef.Ref2.IsRowRel())
+ {
+ rBuffer.append (sal_Unicode(':'));
+ r1c1_add_row(rBuffer, rRef.Ref2);
+ }
+ return;
+ }
+
+ if (aRef.Ref1.nRow == 0 && aRef.Ref2.nRow >= MAXROW)
+ {
+ r1c1_add_col(rBuffer, aRef.Ref1);
+ if (aRef.Ref1.nCol != aRef.Ref2.nCol || aRef.Ref1.IsColRel() != aRef.Ref2.IsColRel())
+ {
+ rBuffer.append (sal_Unicode(':'));
+ r1c1_add_col(rBuffer, aRef.Ref2);
+ }
+ return;
+ }
+
+ r1c1_add_row(rBuffer, aRef.Ref1);
+ r1c1_add_col(rBuffer, aRef.Ref1);
+ rBuffer.append (sal_Unicode (':'));
+ r1c1_add_row(rBuffer, aRef.Ref2);
+ r1c1_add_col(rBuffer, aRef.Ref2);
+ }
};
static const ConventionXL_R1C1 ConvXL_R1C1;
@@ -1739,13 +2417,15 @@ void ScCompiler::CheckTabQuotes( String& rString,
KParseType::IDENTNAME, rString, 0, nStartFlags, EMPTY_STRING, nContFlags, EMPTY_STRING);
bool bNeedsQuote = !((aRes.TokenType & KParseType::IDENTNAME) && aRes.EndPos == rString.Len());
- switch ( eConv ) {
+ switch ( eConv )
+ {
default :
case ScAddress::CONV_UNSPECIFIED :
break;
case ScAddress::CONV_OOO :
case ScAddress::CONV_XL_A1 :
case ScAddress::CONV_XL_R1C1 :
+ case ScAddress::CONV_XL_OOX :
if( bNeedsQuote )
{
static const String one_quote = static_cast<sal_Unicode>( '\'' );
@@ -1781,6 +2461,7 @@ void ScCompiler::SetRefConvention( ScAddress::Convention eConv )
case ScAddress::CONV_ODF : SetRefConvention( pConvOOO_A1_ODF ); break;
case ScAddress::CONV_XL_A1 : SetRefConvention( pConvXL_A1 ); break;
case ScAddress::CONV_XL_R1C1 : SetRefConvention( pConvXL_R1C1 ); break;
+ case ScAddress::CONV_XL_OOX : SetRefConvention( pConvXL_OOX ); break;
}
}
@@ -1853,10 +2534,11 @@ xub_StrLen ScCompiler::NextSymbol()
sal_Unicode* pSym = cSymbol;
const sal_Unicode* const pStart = aFormula.GetBuffer();
const sal_Unicode* pSrc = pStart + nSrcPos;
- BOOL bi18n = FALSE;
+ bool bi18n = false;
sal_Unicode c = *pSrc;
sal_Unicode cLast = 0;
- BOOL bQuote = FALSE;
+ bool bQuote = false;
+ bool bRangeOp = false;
ScanState eState = ssGetChar;
xub_StrLen nSpaces = 0;
sal_Unicode cSep = mxSymbols->getSymbol( ocSep).GetChar(0);
@@ -1869,7 +2551,7 @@ xub_StrLen ScCompiler::NextSymbol()
int nDecSeps = 0;
bool bAutoIntersection = false;
- int nRefInSheetName = 0;
+ int nRefInName = 0;
mnPredetectedReference = 0;
// try to parse simple tokens before calling i18n parser
while ((c != 0) && (eState != ssStop) )
@@ -1933,6 +2615,20 @@ Label_MaskStateMachine:
goto Label_MaskStateMachine;
}
}
+ else if( nMask & SC_COMPILER_C_ODF_NAME_MARKER )
+ {
+ // '$$' defined name marker
+ if (GetCharTableFlags( pSrc[0] ) & SC_COMPILER_C_ODF_NAME_MARKER)
+ {
+ // both eaten, not added to pSym
+ ++pSrc;
+ }
+ else
+ {
+ nMask &= ~SC_COMPILER_C_ODF_NAME_MARKER;
+ goto Label_MaskStateMachine;
+ }
+ }
else if( nMask & SC_COMPILER_C_CHAR )
{
*pSym++ = c;
@@ -1971,7 +2667,7 @@ Label_MaskStateMachine:
}
else
{
- bi18n = TRUE;
+ bi18n = true;
eState = ssStop;
}
}
@@ -1988,11 +2684,24 @@ Label_MaskStateMachine:
else
*pSym++ = c;
}
+ else if (c == ':' && !bRangeOp)
+ {
+ // One range operator may form Sheet1.A:A, which we need to
+ // pass as one entity to IsReference().
+ bRangeOp = true;
+ if( pSym == &cSymbol[ MAXSTRLEN-1 ] )
+ {
+ SetError(errStringOverflow);
+ eState = ssStop;
+ }
+ else
+ *pSym++ = c;
+ }
else if ( 128 <= c || '\'' == c )
{ // High values need reparsing with i18n,
// single quoted $'sheet' names too (otherwise we'd had to
// implement everything twice).
- bi18n = TRUE;
+ bi18n = true;
eState = ssStop;
}
else
@@ -2028,7 +2737,7 @@ Label_MaskStateMachine:
if (++nDecSeps > 1)
{
// reparse with i18n, may be numeric sheet name as well
- bi18n = TRUE;
+ bi18n = true;
eState = ssStop;
}
else
@@ -2048,7 +2757,7 @@ Label_MaskStateMachine:
else
{
// reparse with i18n
- bi18n = TRUE;
+ bi18n = true;
eState = ssStop;
}
}
@@ -2068,7 +2777,7 @@ Label_MaskStateMachine:
else
{
// reparse with i18n
- bi18n = TRUE;
+ bi18n = true;
eState = ssStop;
}
}
@@ -2080,12 +2789,12 @@ Label_MaskStateMachine:
if ( !bQuote )
{
if ( *pSrc == '"' )
- bQuote = TRUE; // "" => literal "
+ bQuote = true; // "" => literal "
else
eState = ssStop;
}
else
- bQuote = FALSE;
+ bQuote = false;
}
if ( !bQuote )
{
@@ -2111,86 +2820,156 @@ Label_MaskStateMachine:
}
// fall through and follow logic
case ssSkipReference:
- // ODF reference: [$'Sheet'.A1:.B2] with dots being mandatory
- // also if no sheet name.
- //
- // nRefInSheetName: 0 := not in sheet name yet.
- // +1 := encountered leading '$'
- // +2 := encountered opening ''', which
- // may be after $ or not.
- // 4(+ ) := somewhere in sheet name.
- // 8(+ ) := encountered ''' in sheet name,
- // will be decremented (-4) again if
- // double or incremented (+4) again
- // if not.
- // 12(+ ) := past closing ''' or no sheet name
- // and past leading '.'
+ // ODF reference: ['External'#$'Sheet'.A1:.B2] with dots being
+ // mandatory also if no sheet name. 'External'# is optional,
+ // sheet name is optional, quotes around sheet name are
+ // optional if no quote contained.
+ // 2nd usage: ['Sheet'.$$'DefinedName']
+ // 3rd usage: ['External'#$$'DefinedName']
+ // 4th usage: ['External'#$'Sheet'.$$'DefinedName']
+ // Also for all these names quotes are optional if no quote
+ // contained.
{
- // kOpen can be used in bit tests in this arrangement
- static const int kDollar = 1;
- static const int kOpen = 2;
- static const int kInc = 4;
- static const int kSheet = kInc * 1;
- static const int kQuote = kInc * 2;
- static const int kPast = kInc * 3;
+
+ // nRefInName: 0 := not in sheet name yet. 'External'
+ // is parsed as if it was a sheet name and nRefInName
+ // is reset when # is encountered immediately after closing
+ // quote. Same with 'DefinedName', nRefInName is cleared
+ // when : is encountered.
+
+ // Encountered leading $ before sheet name.
+ static const int kDollar = (1 << 1);
+ // Encountered ' opening quote, which may be after $ or
+ // not.
+ static const int kOpen = (1 << 2);
+ // Somewhere in name.
+ static const int kName = (1 << 3);
+ // Encountered ' in name, will be cleared if double or
+ // transformed to kClose if not, in which case kOpen is
+ // cleared.
+ static const int kQuote = (1 << 4);
+ // Past ' closing quote.
+ static const int kClose = (1 << 5);
+ // Past . sheet name separator.
+ static const int kPast = (1 << 6);
+ // Marked name $$ follows sheet name separator, detected
+ // while we're still on the separator. Will be cleared when
+ // entering the name.
+ static const int kMarkAhead = (1 << 7);
+ // In marked defined name.
+ static const int kDefName = (1 << 8);
+
bool bAddToSymbol = true;
- if ('.' == c && nRefInSheetName == 0)
+ if ((nMask & SC_COMPILER_C_ODF_RBRACKET) && !(nRefInName & kOpen))
{
- // eat it, no sheet name
+ DBG_ASSERT( nRefInName & (kPast | kDefName),
+ "ScCompiler::NextSymbol: reference: "
+ "closing bracket ']' without prior sheet name separator '.' violates ODF spec");
+ // eaten, not added to pSym
bAddToSymbol = false;
- nRefInSheetName = kPast;
+ eState = ssStop;
}
- else if (':' == c && nRefInSheetName < kSheet)
+ else if (cSheetSep == c && nRefInName == 0)
{
- DBG_ERRORFILE("ScCompiler::NextSymbol: reference:"
- "range operator ':' without prior sheet name separator '.' violates ODF spec");
- nRefInSheetName = 0;
- ++mnPredetectedReference;
+ // eat it, no sheet name [.A1]
+ bAddToSymbol = false;
+ nRefInName |= kPast;
+ if ('$' == pSrc[0] && '$' == pSrc[1])
+ nRefInName |= kMarkAhead;
}
- else if (nRefInSheetName < kPast)
+ else if (!(nRefInName & kPast) || (nRefInName & (kMarkAhead | kDefName)))
{
- if ('$' == c && nRefInSheetName < kDollar)
- nRefInSheetName += kDollar;
+ // Not in col/row yet.
+
+ if ('$' == c && '$' == pSrc[0] && !(nRefInName & kOpen))
+ {
+ nRefInName &= ~kMarkAhead;
+ if (!(nRefInName & kDefName))
+ {
+ // eaten, not added to pSym (2 chars)
+ bAddToSymbol = false;
+ ++pSrc;
+ nRefInName &= kPast;
+ nRefInName |= kDefName;
+ }
+ else
+ {
+ // ScAddress::Parse() will recognize this as
+ // invalid later.
+ if (eState != ssSkipReference)
+ {
+ *pSym++ = c;
+ *pSym++ = *pSrc++;
+ }
+ bAddToSymbol = false;
+ }
+ }
+ else if (cSheetPrefix == c && nRefInName == 0)
+ nRefInName |= kDollar;
else if ('\'' == c)
{
- if (nRefInSheetName < kSheet)
- nRefInSheetName += kOpen + kSheet;
- else if (!(nRefInSheetName & kOpen))
+ // TODO: The conventions' parseExternalName()
+ // should handle quoted names, but as long as they
+ // don't remove non-embedded quotes here.
+ if (!(nRefInName & kName))
+ {
+ nRefInName |= (kOpen | kName);
+ bAddToSymbol = !(nRefInName & kDefName);
+ }
+ else if (!(nRefInName & kOpen))
{
- DBG_ERRORFILE("ScCompiler::NextSymbol: reference:"
- "a ''' without the sheet name being enclosed in '...' violates ODF spec");
+ DBG_ERRORFILE("ScCompiler::NextSymbol: reference: "
+ "a ''' without the name being enclosed in '...' violates ODF spec");
}
- else if (nRefInSheetName >= kQuote)
+ else if (nRefInName & kQuote)
+ {
// escaped embedded quote
- nRefInSheetName -= kInc;
+ nRefInName &= ~kQuote;
+ }
else
- // a quote in (or after) sheet name
- nRefInSheetName += kInc;
+ {
+ if ('\'' == pSrc[0])
+ {
+ // escapes embedded quote
+ nRefInName |= kQuote;
+ }
+ else
+ {
+ // quote not followed by quote => close
+ nRefInName |= kClose;
+ nRefInName &= ~kOpen;
+ }
+ bAddToSymbol = !(nRefInName & kDefName);
+ }
}
- else if ('.' == c && !(nRefInSheetName & kOpen))
+ else if (cSheetSep == c && !(nRefInName & kOpen))
+ {
// unquoted sheet name separator
- nRefInSheetName += kPast;
- else if (nRefInSheetName < kSheet)
- // start unquoted sheet name
- nRefInSheetName += kSheet;
- else if (nRefInSheetName >= kQuote)
- // quote not followed by quote => past
- nRefInSheetName += kInc;
+ nRefInName |= kPast;
+ if ('$' == pSrc[0] && '$' == pSrc[1])
+ nRefInName |= kMarkAhead;
+ }
+ else if (':' == c && !(nRefInName & kOpen))
+ {
+ DBG_ERRORFILE("ScCompiler::NextSymbol: reference: "
+ "range operator ':' without prior sheet name separator '.' violates ODF spec");
+ nRefInName = 0;
+ ++mnPredetectedReference;
+ }
+ else if (!(nRefInName & kName))
+ {
+ // start unquoted name
+ nRefInName |= kName;
+ }
}
else if (':' == c)
{
// range operator
- nRefInSheetName = 0;
+ nRefInName = 0;
++mnPredetectedReference;
}
- else if (nMask & SC_COMPILER_C_ODF_RBRACKET)
- {
- // eaten, not added to pSym
- bAddToSymbol = false;
- eState = ssStop;
- }
if (bAddToSymbol && eState != ssSkipReference)
- *pSym++ = c; // everything is part of sheet reference
+ *pSym++ = c; // everything is part of reference
}
break;
case ssStop:
@@ -2204,10 +2983,11 @@ Label_MaskStateMachine:
{
nSrcPos = sal::static_int_cast<xub_StrLen>( nSrcPos + nSpaces );
String aSymbol;
+ bRangeOp = false;
USHORT nErr = 0;
do
{
- bi18n = FALSE;
+ bi18n = false;
// special case (e.g. $'sheetname' in OOO A1)
if ( pStart[nSrcPos] == cSheetPrefix && pStart[nSrcPos+1] == '\'' )
aSymbol += pStart[nSrcPos++];
@@ -2226,13 +3006,19 @@ Label_MaskStateMachine:
{
aSymbol.Append( pStart + nSrcPos, (xub_StrLen)aRes.EndPos - nSrcPos );
nSrcPos = (xub_StrLen) aRes.EndPos;
+ c = pStart[nSrcPos];
if ( aRes.TokenType & KParseType::SINGLE_QUOTE_NAME )
{ // special cases (e.g. 'sheetname'. or 'filename'# in OOO A1)
- c = pStart[nSrcPos];
bi18n = (c == cSheetSep || c == SC_COMPILER_FILE_TAB_SEP);
- if ( bi18n )
- aSymbol += pStart[nSrcPos++];
}
+ // One range operator restarts parsing for second reference.
+ if (c == ':' && !bRangeOp)
+ {
+ bRangeOp = true;
+ bi18n = true;
+ }
+ if ( bi18n )
+ aSymbol += pStart[nSrcPos++];
}
} while ( bi18n && !nErr );
xub_StrLen nLen = aSymbol.Len();
@@ -2360,24 +3146,35 @@ BOOL ScCompiler::IsValue( const String& rSym )
if (pDoc->GetFormatTable()->IsNumberFormat( rSym, nIndex, fVal ) )
{
USHORT nType = pDoc->GetFormatTable()->GetType(nIndex);
- const sal_Unicode* p = aFormula.GetBuffer() + nSrcPos;
- while( *p == ' ' )
- p++;
- if ( *p == '(' && nType == NUMBERFORMAT_LOGICAL)
- return FALSE;
- else if( aFormula.GetChar(nSrcPos) == '.' )
- // numerical sheet name?
+
+ // Don't accept 3:3 as time, it is a reference to entire row 3 instead.
+ // Dates should never be entered directly and automatically converted
+ // to serial, because the serial would be wrong if null-date changed.
+ // Usually it wouldn't be accepted anyway because the date separator
+ // clashed with other separators or operators.
+ if (nType & (NUMBERFORMAT_TIME | NUMBERFORMAT_DATE))
return FALSE;
- else
+
+ if (nType == NUMBERFORMAT_LOGICAL)
{
- if( nType == NUMBERFORMAT_TEXT )
- // HACK: number too big!
- SetError( errIllegalArgument );
- ScRawToken aToken;
- aToken.SetDouble( fVal );
- pRawToken = aToken.Clone();
- return TRUE;
+ const sal_Unicode* p = aFormula.GetBuffer() + nSrcPos;
+ while( *p == ' ' )
+ p++;
+ if (*p == '(')
+ return FALSE; // Boolean function instead.
}
+
+ if( aFormula.GetChar(nSrcPos) == '.' )
+ // numerical sheet name?
+ return FALSE;
+
+ if( nType == NUMBERFORMAT_TEXT )
+ // HACK: number too big!
+ SetError( errIllegalArgument );
+ ScRawToken aToken;
+ aToken.SetDouble( fVal );
+ pRawToken = aToken.Clone();
+ return TRUE;
}
else
return FALSE;
@@ -2463,7 +3260,8 @@ BOOL ScCompiler::IsDoubleReference( const String& rName )
{
ScRange aRange( aPos, aPos );
const ScAddress::Details aDetails( pConv->meConv, aPos );
- USHORT nFlags = aRange.Parse( rName, pDoc, aDetails );
+ ScAddress::ExternalInfo aExtInfo;
+ USHORT nFlags = aRange.Parse( rName, pDoc, aDetails, &aExtInfo, &maExternalLinks );
if( nFlags & SCA_VALID )
{
ScRawToken aToken;
@@ -2482,7 +3280,17 @@ BOOL ScCompiler::IsDoubleReference( const String& rName )
aRef.Ref2.SetTabDeleted( TRUE ); // #REF!
aRef.Ref2.SetFlag3D( ( nFlags & SCA_TAB2_3D ) != 0 );
aRef.CalcRelFromAbs( aPos );
- aToken.SetDoubleReference( aRef );
+ if (aExtInfo.mbExternal)
+ {
+ ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
+ const String* pRealTab = pRefMgr->getRealTableName(aExtInfo.mnFileId, aExtInfo.maTabName);
+ aToken.SetExternalDoubleRef(
+ aExtInfo.mnFileId, pRealTab ? *pRealTab : aExtInfo.maTabName, aRef);
+ }
+ else
+ {
+ aToken.SetDoubleReference(aRef);
+ }
pRawToken = aToken.Clone();
}
@@ -2494,7 +3302,8 @@ BOOL ScCompiler::IsSingleReference( const String& rName )
{
ScAddress aAddr( aPos );
const ScAddress::Details aDetails( pConv->meConv, aPos );
- USHORT nFlags = aAddr.Parse( rName, pDoc, aDetails );
+ ScAddress::ExternalInfo aExtInfo;
+ USHORT nFlags = aAddr.Parse( rName, pDoc, aDetails, &aExtInfo, &maExternalLinks );
// Something must be valid in order to recognize Sheet1.blah or blah.a1
// as a (wrong) reference.
if( nFlags & ( SCA_VALID_COL|SCA_VALID_ROW|SCA_VALID_TAB ) )
@@ -2518,7 +3327,16 @@ BOOL ScCompiler::IsSingleReference( const String& rName )
nFlags |= SCA_VALID;
}
aRef.CalcRelFromAbs( aPos );
- aToken.SetSingleReference( aRef );
+
+ if (aExtInfo.mbExternal)
+ {
+ ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
+ const String* pRealTab = pRefMgr->getRealTableName(aExtInfo.mnFileId, aExtInfo.maTabName);
+ aToken.SetExternalSingleRef(
+ aExtInfo.mnFileId, pRealTab ? *pRealTab : aExtInfo.maTabName, aRef);
+ }
+ else
+ aToken.SetSingleReference(aRef);
pRawToken = aToken.Clone();
}
@@ -2536,41 +3354,56 @@ BOOL ScCompiler::IsReference( const String& rName )
return FALSE;
// Who was that imbecile introducing '.' as the sheet name separator!?!
if ( CharClass::isAsciiNumeric( ch1 ) )
- { // Numerical sheet name is valid.
+ {
+ // Numerical sheet name is valid.
// But English 1.E2 or 1.E+2 is value 100, 1.E-2 is 0.01
- // Don't create a #REF! of values.
- const xub_StrLen nPos = rName.Search( '.' );
- if ( nPos == STRING_NOTFOUND )
- return FALSE;
- sal_Unicode const * const pTabSep = rName.GetBuffer() + nPos;
- sal_Unicode ch2 = pTabSep[1]; // maybe a column identifier
- if ( !(ch2 == '$' || CharClass::isAsciiAlpha( ch2 )) )
- return FALSE;
- if ( cDecSep == '.' && (ch2 == 'E' || ch2 == 'e') // E + - digit
- && (GetCharTableFlags( pTabSep[2] ) & SC_COMPILER_C_VALUE_EXP) )
- { // #91053#
- // If it is an 1.E2 expression check if "1" is an existent sheet
- // name. If so, a desired value 1.E2 would have to be entered as
- // 1E2 or 1.0E2 or 1.E+2, sorry. Another possibility would be to
- // require numerical sheet names always being entered quoted, which
- // is not desirable (too many 1999, 2000, 2001 sheets in use).
- // Furthermore, XML files created with versions prior to SRC640e
- // wouldn't contain the quotes added by MakeTabStr()/CheckTabQuotes()
- // and would produce wrong formulas if the conditions here are met.
- // If you can live with these restrictions you may remove the
- // check and return an unconditional FALSE.
- String aTabName( rName.Copy( 0, nPos ) );
- SCTAB nTab;
- if ( !pDoc->GetTable( aTabName, nTab ) )
+ // Don't create a #REF! of values. But also do not bail out on
+ // something like 3:3, meaning entire row 3.
+ do
+ {
+ const xub_StrLen nPos = ScGlobal::FindUnquoted( rName, '.');
+ if ( nPos == STRING_NOTFOUND )
+ {
+ if (ScGlobal::FindUnquoted( rName, ':') != STRING_NOTFOUND)
+ break; // may be 3:3, continue as usual
return FALSE;
- // If sheet "1" exists and the expression is 1.E+2 continue as
- // usual, the ScRange/ScAddress parser will take care of it.
- }
+ }
+ sal_Unicode const * const pTabSep = rName.GetBuffer() + nPos;
+ sal_Unicode ch2 = pTabSep[1]; // maybe a column identifier
+ if ( !(ch2 == '$' || CharClass::isAsciiAlpha( ch2 )) )
+ return FALSE;
+ if ( cDecSep == '.' && (ch2 == 'E' || ch2 == 'e') // E + - digit
+ && (GetCharTableFlags( pTabSep[2] ) & SC_COMPILER_C_VALUE_EXP) )
+ { // #91053#
+ // If it is an 1.E2 expression check if "1" is an existent sheet
+ // name. If so, a desired value 1.E2 would have to be entered as
+ // 1E2 or 1.0E2 or 1.E+2, sorry. Another possibility would be to
+ // require numerical sheet names always being entered quoted, which
+ // is not desirable (too many 1999, 2000, 2001 sheets in use).
+ // Furthermore, XML files created with versions prior to SRC640e
+ // wouldn't contain the quotes added by MakeTabStr()/CheckTabQuotes()
+ // and would produce wrong formulas if the conditions here are met.
+ // If you can live with these restrictions you may remove the
+ // check and return an unconditional FALSE.
+ String aTabName( rName.Copy( 0, nPos ) );
+ SCTAB nTab;
+ if ( !pDoc->GetTable( aTabName, nTab ) )
+ return FALSE;
+ // If sheet "1" exists and the expression is 1.E+2 continue as
+ // usual, the ScRange/ScAddress parser will take care of it.
+ }
+ } while(0);
}
- // The range operator is handled explicitly, this is really only about
- // single references.
- return IsSingleReference( rName);
+ if (IsSingleReference( rName))
+ return true;
+
+ // Though the range operator is handled explicitly, when encountering
+ // something like Sheet1.A:A we will have to treat it as one entity if it
+ // doesn't pass as single cell reference.
+ if (ScGlobal::FindUnquoted( rName, ':') != STRING_NOTFOUND)
+ return IsDoubleReference( rName);
+ return false;
}
BOOL ScCompiler::IsMacro( const String& rName )
@@ -2626,6 +3459,43 @@ BOOL ScCompiler::IsNamedRange( const String& rUpperName )
return FALSE;
}
+bool ScCompiler::IsExternalNamedRange( const String& rSymbol )
+{
+ /* FIXME: This code currently (2008-12-02T15:41+0100 in CWS mooxlsc)
+ * correctly parses external named references in OOo, as required per RFE
+ * #i3740#, just that we can't store them in ODF yet. We will need an OASIS
+ * spec first. Until then don't pretend to support external names that
+ * wouldn't survive a save and reload cycle, return false instead. */
+
+#if 0
+ if (!pConv)
+ return false;
+
+ String aFile, aName;
+ if (!pConv->parseExternalName( rSymbol, aFile, aName, pDoc, &maExternalLinks))
+ return false;
+
+ ScRawToken aToken;
+ if (aFile.Len() > MAXSTRLEN || aName.Len() > MAXSTRLEN)
+ return false;
+
+ ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
+ pRefMgr->convertToAbsName(aFile);
+ sal_uInt16 nFileId = pRefMgr->getExternalFileId(aFile);
+ if (!pRefMgr->getRangeNameTokens(nFileId, aName).get())
+ // range name doesn't exist in the source document.
+ return false;
+
+ const String* pRealName = pRefMgr->getRealRangeName(nFileId, aName);
+ aToken.SetExternalName(nFileId, pRealName ? *pRealName : aName);
+ pRawToken = aToken.Clone();
+ return true;
+#else
+ (void)rSymbol;
+ return false;
+#endif
+}
+
BOOL ScCompiler::IsDBRange( const String& rName )
{
USHORT n;
@@ -3160,7 +4030,7 @@ BOOL ScCompiler::NextNewToken( bool bAllowBooleans )
if (mnPredetectedReference)
{
String aStr( cSymbol);
- if (!IsPredetectedReference( aStr))
+ if (!IsPredetectedReference( aStr) && !IsExternalNamedRange( aStr))
{
/* TODO: it would be nice to generate a #REF! error here, which
* would need an ocBad token with additional error value.
@@ -3223,6 +4093,7 @@ BOOL ScCompiler::NextNewToken( bool bAllowBooleans )
&& !(bAllowBooleans && IsBoolean( aUpper ))
&& !IsValue( aUpper )
&& !IsNamedRange( aUpper )
+ && !IsExternalNamedRange(aOrg)
&& !IsDBRange( aUpper )
&& !IsColRowName( aUpper )
&& !(bMayBeFuncName && IsMacro( aUpper ))
@@ -3545,9 +4416,9 @@ BOOL ScCompiler::GetToken()
else
{
if ( nWasColRowName >= 2 && pToken->GetOpCode() == ocColRowName )
- { // aus einem ocSpaces ein ocIntersect im RPN machen
+ { // convert an ocSpaces to ocIntersect in RPN
pToken = new ScByteToken( ocIntersect );
- pArr->nIndex--; // ganz schweinisch..
+ pArr->nIndex--; // we advanced to the second ocColRowName, step back
}
}
}
@@ -3558,6 +4429,50 @@ BOOL ScCompiler::GetToken()
}
if( pToken->GetOpCode() == ocSubTotal )
glSubTotal = TRUE;
+ else if ( pToken->GetOpCode() == ocExternalRef )
+ {
+ // Handle external range names.
+ switch (pToken->GetType())
+ {
+ case svExternalSingleRef:
+ case svExternalDoubleRef:
+ pArr->nRefs++;
+ break;
+ case svExternalName:
+ {
+ ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
+ const String* pFile = pRefMgr->getExternalFileName(pToken->GetIndex());
+ if (!pFile)
+ {
+ SetError(errNoName);
+ return true;
+ }
+
+ const String& rName = pToken->GetString();
+ ScExternalRefCache::TokenArrayRef xNew = pRefMgr->getRangeNameTokens(
+ pToken->GetIndex(), rName, &aPos);
+
+ if (!xNew)
+ {
+ SetError(errNoName);
+ return true;
+ }
+
+ ScTokenArray* pNew = xNew->Clone();
+ PushTokenArray( pNew, true);
+ if (pNew->GetNextReference() != NULL)
+ {
+ SetRelNameReference();
+ MoveRelWrap();
+ }
+ pNew->Reset();
+ return GetToken();
+ }
+ //break; // unreachable, prevent compiler warning
+ default:
+ DBG_ERROR1( "ScCompiler::GetToken: unhandled ocExternalRef type %d", pToken->GetType());
+ }
+ }
else if( pToken->GetOpCode() == ocName )
{
ScRangeData* pRangeData = pDoc->GetRangeName()->FindIndex( pToken->GetIndex() );
@@ -3713,7 +4628,7 @@ BOOL ScCompiler::GetToken()
{ // next defined RowNameRange to the right limits column
const ScRange& rRange = pR->GetRange(1);
if ( rRange.aStart.Row() <= nRow && nRow <= rRange.aEnd.Row() )
- { // gleicher Row Bereich
+ { // identical row range
SCCOL nTmp = rRange.aStart.Col();
if ( nStartCol < nTmp && nTmp <= nMaxCol )
nMaxCol = nTmp - 1;
@@ -4337,6 +5252,11 @@ void ScCompiler::Factor()
bCorrected = TRUE;
}
}
+ else if ( eOp == ocExternalRef )
+ {
+ PutCode(pToken);
+ eOp = NextToken();
+ }
else
{
SetError( errUnknownToken );
@@ -4608,7 +5528,7 @@ void ScCompiler::MoveRelWrap()
for( ScToken* t = pArr->GetNextReference(); t;
t = pArr->GetNextReference() )
{
- if ( t->GetType() == svSingleRef )
+ if ( t->GetType() == svSingleRef || t->GetType() == svExternalSingleRef )
ScRefUpdate::MoveRelWrap( pDoc, aPos, SingleDoubleRefModifier( t->GetSingleRef() ).Ref() );
else
ScRefUpdate::MoveRelWrap( pDoc, aPos, t->GetDoubleRef() );
@@ -4625,7 +5545,7 @@ void ScCompiler::MoveRelWrap( ScTokenArray& rArr, ScDocument* pDoc,
for( ScToken* t = rArr.GetNextReference(); t;
t = rArr.GetNextReference() )
{
- if ( t->GetType() == svSingleRef )
+ if ( t->GetType() == svSingleRef || t->GetType() == svExternalSingleRef )
ScRefUpdate::MoveRelWrap( pDoc, rPos, SingleDoubleRefModifier( t->GetSingleRef() ).Ref() );
else
ScRefUpdate::MoveRelWrap( pDoc, rPos, t->GetDoubleRef() );
@@ -4737,7 +5657,7 @@ ScRangeData* ScCompiler::UpdateReference(UpdateRefMode eUpdateRefMode,
else if( t->GetType() != svIndex ) // it may be a DB area!!!
{
t->CalcAbsIfRel( rOldPos );
- if ( t->GetType() == svSingleRef )
+ if ( t->GetType() == svSingleRef || t->GetType() == svExternalSingleRef )
{
if ( ScRefUpdate::Update( pDoc, eUpdateRefMode, aPos,
r, nDx, nDy, nDz,
@@ -5542,111 +6462,144 @@ ScToken* ScCompiler::CreateStringFromToken( rtl::OUStringBuffer& rBuffer, ScToke
DBG_ERRORFILE("unknown OpCode");
rBuffer.append(ScGlobal::GetRscString(STR_NO_NAME_REF));
}
- if( bNext ) switch( t->GetType() )
+ if (bNext)
{
- case svDouble:
- AppendDouble( rBuffer, t->GetDouble() );
- break;
-
- case svString:
- if( eOp == ocBad )
- rBuffer.append(t->GetString());
- else
- AppendString( rBuffer, t->GetString() );
- break;
- case svSingleRef:
+ if (eOp == ocExternalRef)
{
- SingleRefData& rRef = t->GetSingleRef();
- ComplRefData aRef;
- aRef.Ref1 = aRef.Ref2 = rRef;
- if ( eOp == ocColRowName )
+ ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
+ switch (t->GetType())
{
- rRef.CalcAbsIfRel( aPos );
- if ( pDoc->HasStringData( rRef.nCol, rRef.nRow, rRef.nTab ) )
- {
- String aStr;
- pDoc->GetString( rRef.nCol, rRef.nRow, rRef.nTab, aStr );
- EnQuote( aStr );
- rBuffer.append(aStr);
- }
- else
+ case svExternalName:
{
- rBuffer.append(ScGlobal::GetRscString(STR_NO_NAME_REF));
- pConv->MakeRefStr (rBuffer, *this, aRef, TRUE );
+ const String *pStr = pRefMgr->getExternalFileName(t->GetIndex());
+ String aFileName = pStr ? *pStr : ScGlobal::GetRscString(STR_NO_NAME_REF);
+ rBuffer.append(pConv->makeExternalNameStr(
+ aFileName, t->GetString()));
}
+ break;
+ case svExternalSingleRef:
+ pConv->makeExternalRefStr(
+ rBuffer, *this, t->GetIndex(), t->GetString(), t->GetSingleRef(), pRefMgr);
+ break;
+ case svExternalDoubleRef:
+ pConv->makeExternalRefStr(
+ rBuffer, *this, t->GetIndex(), t->GetString(), t->GetDoubleRef(), pRefMgr);
+ break;
+ default:
+ // warning, not error, otherwise we may end up with a never
+ // ending message box loop if this was the cursor cell to be redrawn.
+ DBG_WARNING("ScCompiler::CreateStringFromToken: unknown type of ocExternalRef");
}
- else
- pConv->MakeRefStr( rBuffer, *this, aRef, TRUE );
}
- break;
- case svDoubleRef:
- pConv->MakeRefStr( rBuffer, *this, t->GetDoubleRef(), FALSE );
- break;
- case svMatrix:
- CreateStringFromScMatrix( rBuffer, t->GetMatrix() );
- break;
-
- case svIndex:
+ else
{
- rtl::OUStringBuffer aBuffer;
- switch ( eOp )
+ switch( t->GetType() )
{
- case ocName:
+ case svDouble:
+ AppendDouble( rBuffer, t->GetDouble() );
+ break;
+
+ case svString:
+ if( eOp == ocBad )
+ rBuffer.append(t->GetString());
+ else
+ AppendString( rBuffer, t->GetString() );
+ break;
+ case svSingleRef:
{
- ScRangeData* pData = pDoc->GetRangeName()->FindIndex(t->GetIndex());
- if (pData)
+ SingleRefData& rRef = t->GetSingleRef();
+ ComplRefData aRef;
+ aRef.Ref1 = aRef.Ref2 = rRef;
+ if ( eOp == ocColRowName )
{
- if (pData->HasType(RT_SHARED))
- pData->UpdateSymbol( aBuffer, aPos, GetGrammar());
+ rRef.CalcAbsIfRel( aPos );
+ if ( pDoc->HasStringData( rRef.nCol, rRef.nRow, rRef.nTab ) )
+ {
+ String aStr;
+ pDoc->GetString( rRef.nCol, rRef.nRow, rRef.nTab, aStr );
+ EnQuote( aStr );
+ rBuffer.append(aStr);
+ }
else
- aBuffer.append(pData->GetName());
+ {
+ rBuffer.append(ScGlobal::GetRscString(STR_NO_NAME_REF));
+ pConv->MakeRefStr (rBuffer, *this, aRef, TRUE );
+ }
}
+ else
+ pConv->MakeRefStr( rBuffer, *this, aRef, TRUE );
}
- break;
- case ocDBArea:
+ break;
+ case svDoubleRef:
+ pConv->MakeRefStr( rBuffer, *this, t->GetDoubleRef(), FALSE );
+ break;
+ case svMatrix:
+ CreateStringFromScMatrix( rBuffer, t->GetMatrix() );
+ break;
+
+ case svIndex:
{
- ScDBData* pDBData = pDoc->GetDBCollection()->FindIndex(t->GetIndex());
- if (pDBData)
- aBuffer.append(pDBData->GetName());
+ rtl::OUStringBuffer aBuffer;
+ switch ( eOp )
+ {
+ case ocName:
+ {
+ ScRangeData* pData = pDoc->GetRangeName()->FindIndex(t->GetIndex());
+ if (pData)
+ {
+ if (pData->HasType(RT_SHARED))
+ pData->UpdateSymbol( aBuffer, aPos, GetGrammar());
+ else
+ aBuffer.append(pData->GetName());
+ }
+ }
+ break;
+ case ocDBArea:
+ {
+ ScDBData* pDBData = pDoc->GetDBCollection()->FindIndex(t->GetIndex());
+ if (pDBData)
+ aBuffer.append(pDBData->GetName());
+ }
+ break;
+ default:
+ ; // nothing
+ }
+ if ( aBuffer.getLength() )
+ rBuffer.append(aBuffer);
+ else
+ rBuffer.append(ScGlobal::GetRscString(STR_NO_NAME_REF));
+ break;
}
- break;
- default:
- ; // nothing
- }
- if ( aBuffer.getLength() )
- rBuffer.append(aBuffer);
- else
- rBuffer.append(ScGlobal::GetRscString(STR_NO_NAME_REF));
- break;
- }
- case svExternal:
- {
- // mapped or translated name of AddIns
- String aAddIn( t->GetExternal() );
- bool bMapped = mxSymbols->isPODF(); // ODF 1.1 directly uses programmatical name
- if (!bMapped && mxSymbols->hasExternals())
- {
- ScExternalHashMap::const_iterator iLook = mxSymbols->getReverseExternalHashMap()->find( aAddIn);
- if (iLook != mxSymbols->getReverseExternalHashMap()->end())
+ case svExternal:
{
- aAddIn = (*iLook).second;
- bMapped = true;
+ // mapped or translated name of AddIns
+ String aAddIn( t->GetExternal() );
+ bool bMapped = mxSymbols->isPODF(); // ODF 1.1 directly uses programmatical name
+ if (!bMapped && mxSymbols->hasExternals())
+ {
+ ScExternalHashMap::const_iterator iLook = mxSymbols->getReverseExternalHashMap()->find( aAddIn);
+ if (iLook != mxSymbols->getReverseExternalHashMap()->end())
+ {
+ aAddIn = (*iLook).second;
+ bMapped = true;
+ }
+ }
+ if (!bMapped && !mxSymbols->isEnglish())
+ ScGlobal::GetAddInCollection()->LocalizeString( aAddIn );
+ rBuffer.append(aAddIn);
}
- }
- if (!bMapped && !mxSymbols->isEnglish())
- ScGlobal::GetAddInCollection()->LocalizeString( aAddIn );
- rBuffer.append(aAddIn);
+ break;
+ case svByte:
+ case svJump:
+ case svFAP:
+ case svMissing:
+ case svSep:
+ break; // Opcodes
+ default:
+ DBG_ERROR("ScCompiler:: GetStringFromToken errUnknownVariable");
+ } // of switch
}
- break;
- case svByte:
- case svJump:
- case svFAP:
- case svMissing:
- case svSep:
- break; // Opcodes
- default:
- DBG_ERROR("ScCompiler:: GetStringFromToken errUnknownVariable");
- } // of switch
+ }
if( bSpaces )
rBuffer.append(sal_Unicode(' '));
if ( bAllowArrAdvance )
@@ -5740,12 +6693,7 @@ void ScCompiler::AppendString( rtl::OUStringBuffer& rBuffer, const String & rStr
else
{
String aStr( rStr );
- xub_StrLen nPos = 0;
- while ( (nPos = aStr.Search( '"', nPos)) != STRING_NOTFOUND )
- {
- aStr.Insert( '"', nPos );
- nPos += 2;
- }
+ aStr.SearchAndReplaceAll( '"', String( RTL_CONSTASCII_USTRINGPARAM( "\"\"")));
rBuffer.append(aStr);
}
rBuffer.append(sal_Unicode('"'));
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index 6d54408d8eaa..549714295899 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: interpr4.cxx,v $
- * $Revision: 1.58 $
+ * $Revision: 1.57.92.5 $
*
* This file is part of OpenOffice.org.
*
@@ -66,6 +66,7 @@
#include "addinlis.hxx"
#include "jumpmatrix.hxx"
#include "parclass.hxx"
+#include "externalrefmgr.hxx"
#include <math.h>
#include <float.h>
@@ -2911,6 +2912,82 @@ void ScInterpreter::ScColRowNameAuto()
PushError( errNoRef );
}
+void ScInterpreter::ScExternalRef()
+{
+ ScExternalRefManager* pRefMgr = pDok->GetExternalRefManager();
+ const String* pFile = pRefMgr->getExternalFileName(pCur->GetIndex());
+ if (!pFile)
+ PushError(errNoName);
+
+ switch (pCur->GetType())
+ {
+ case svExternalSingleRef:
+ {
+ SingleRefData aData(pCur->GetSingleRef());
+ if (aData.IsTabRel())
+ {
+ DBG_ERROR("ScCompiler::GetToken: external single reference must have an absolute table reference!");
+ break;
+ }
+
+ aData.CalcAbsIfRel(aPos);
+ ScAddress aAddr(aData.nCol, aData.nRow, aData.nTab);
+ ScExternalRefCache::CellFormat aFmt;
+ ScExternalRefCache::TokenRef xNew = pRefMgr->getSingleRefToken(
+ pCur->GetIndex(), pCur->GetString(), aAddr, &aPos, NULL, &aFmt);
+
+ if (!xNew)
+ break;
+
+ PushTempToken( *xNew); // push a clone
+
+ if (aFmt.mbIsSet)
+ {
+ nFuncFmtType = aFmt.mnType;
+ nFuncFmtIndex = aFmt.mnIndex;
+ }
+ return;
+ }
+ //break; // unreachable, prevent compiler warning
+ case svExternalDoubleRef:
+ {
+ ComplRefData aData(pCur->GetDoubleRef());
+ if (aData.Ref1.IsTabRel() || aData.Ref2.IsTabRel())
+ {
+ DBG_ERROR("ScCompiler::GetToken: external double reference must have an absolute table reference!");
+ break;
+ }
+
+ aData.CalcAbsIfRel(aPos);
+ ScRange aRange(aData.Ref1.nCol, aData.Ref1.nRow, aData.Ref1.nTab,
+ aData.Ref2.nCol, aData.Ref2.nRow, aData.Ref2.nTab);
+ ScExternalRefCache::TokenArrayRef xNew = pRefMgr->getDoubleRefTokens(
+ pCur->GetIndex(), pCur->GetString(), aRange, &aPos);
+
+ if (!xNew)
+ break;
+
+ ScToken* p = xNew->First();
+ if (p->GetType() != svMatrix)
+ break;
+
+ if (xNew->Next())
+ {
+ // Can't handle more than one matrix per parameter.
+ SetError( errIllegalArgument);
+ break;
+ }
+
+ PushMatrix(p->GetMatrix());
+ return;
+ }
+ //break; // unreachable, prevent compiler warning
+ default:
+ ;
+ }
+ PushError(errNoRef);
+}
+
// --- internals ------------------------------------------------------------
@@ -3343,6 +3420,7 @@ StackVar ScInterpreter::Interpret()
case ocDBArea : ScDBArea(); break;
case ocColRowNameAuto : ScColRowNameAuto(); break;
// separated case ocPush : Push( (ScToken&) *pCur ); break;
+ case ocExternalRef : ScExternalRef(); break;
case ocIf : ScIfJump(); break;
case ocChose : ScChoseJump(); break;
case ocAdd : ScAdd(); break;
diff --git a/sc/source/core/tool/refdata.cxx b/sc/source/core/tool/refdata.cxx
index ec25ba56832c..4a7e07476703 100644
--- a/sc/source/core/tool/refdata.cxx
+++ b/sc/source/core/tool/refdata.cxx
@@ -199,6 +199,10 @@ BOOL SingleRefData::operator==( const SingleRefData& r ) const
(Flags.bTabRel ? nRelTab == r.nRelTab : nTab == r.nTab);
}
+bool SingleRefData::operator!=( const SingleRefData& r ) const
+{
+ return !operator==(r);
+}
static void lcl_putInOrder( SingleRefData & rRef1, SingleRefData & rRef2 )
{
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index 48e6e244d494..86f89f81f446 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -54,6 +54,8 @@
#include "parclass.hxx"
#include "jumpmatrix.hxx"
+using ::std::vector;
+
// ImpTokenIterator wird je Interpreter angelegt, mehrfache auch durch
// SubCode via ScTokenIterator Push/Pop moeglich
IMPL_FIXEDMEMPOOL_NEWDEL( ImpTokenIterator, 32, 16 )
@@ -193,6 +195,48 @@ void ScRawToken::SetName( USHORT n )
nRefCnt = 0;
}
+void ScRawToken::SetExternalSingleRef( sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef )
+{
+ eOp = ocExternalRef;
+ eType = svExternalSingleRef;
+ nRefCnt = 0;
+
+ extref.nFileId = nFileId;
+ extref.aRef.Ref1 =
+ extref.aRef.Ref2 = rRef;
+
+ xub_StrLen n = rTabName.Len();
+ memcpy(extref.cTabName, rTabName.GetBuffer(), n*sizeof(sal_Unicode));
+ extref.cTabName[n] = 0;
+}
+
+void ScRawToken::SetExternalDoubleRef( sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef )
+{
+ eOp = ocExternalRef;
+ eType = svExternalDoubleRef;
+ nRefCnt = 0;
+
+ extref.nFileId = nFileId;
+ extref.aRef = rRef;
+
+ xub_StrLen n = rTabName.Len();
+ memcpy(extref.cTabName, rTabName.GetBuffer(), n*sizeof(sal_Unicode));
+ extref.cTabName[n] = 0;
+}
+
+void ScRawToken::SetExternalName( sal_uInt16 nFileId, const String& rName )
+{
+ eOp = ocExternalRef;
+ eType = svExternalName;
+ nRefCnt = 0;
+
+ extname.nFileId = nFileId;
+
+ xub_StrLen n = rName.Len();
+ memcpy(extname.cName, rName.GetBuffer(), n*sizeof(sal_Unicode));
+ extname.cName[n] = 0;
+}
+
//UNUSED2008-05 void ScRawToken::SetInt(int rVal)
//UNUSED2008-05 {
//UNUSED2008-05 eOp = ocPush;
@@ -260,22 +304,38 @@ ScRawToken* ScRawToken::Clone() const
static USHORT nOffset = lcl_ScRawTokenOffset(); // offset of sbyte
USHORT n = nOffset;
- switch( eType )
+ if (eOp == ocExternalRef)
{
- case svSep: break;
- case svByte: n += sizeof(ScRawToken::sbyte); break;
- case svDouble: n += sizeof(double); break;
- case svString: n = sal::static_int_cast<USHORT>( n + GetStrLenBytes( cStr ) + GetStrLenBytes( 1 ) ); break;
- case svSingleRef:
- case svDoubleRef: n += sizeof(aRef); break;
- case svMatrix: n += sizeof(ScMatrix*); break;
- case svIndex: n += sizeof(USHORT); break;
- case svJump: n += nJump[ 0 ] * 2 + 2; break;
- case svExternal: n = sal::static_int_cast<USHORT>( n + GetStrLenBytes( cStr+1 ) + GetStrLenBytes( 2 ) ); break;
- default:
- {
- DBG_ERROR1( "unknown ScRawToken::Clone() type %d", int(eType));
- }
+ switch (eType)
+ {
+ case svExternalSingleRef:
+ case svExternalDoubleRef: n += sizeof(extref); break;
+ case svExternalName: n += sizeof(extname); break;
+ default:
+ {
+ DBG_ERROR1( "unknown ScRawToken::Clone() external type %d", int(eType));
+ }
+ }
+ }
+ else
+ {
+ switch( eType )
+ {
+ case svSep: break;
+ case svByte: n += sizeof(ScRawToken::sbyte); break;
+ case svDouble: n += sizeof(double); break;
+ case svString: n = sal::static_int_cast<USHORT>( n + GetStrLenBytes( cStr ) + GetStrLenBytes( 1 ) ); break;
+ case svSingleRef:
+ case svDoubleRef: n += sizeof(aRef); break;
+ case svMatrix: n += sizeof(ScMatrix*); break;
+ case svIndex: n += sizeof(USHORT); break;
+ case svJump: n += nJump[ 0 ] * 2 + 2; break;
+ case svExternal: n = sal::static_int_cast<USHORT>( n + GetStrLenBytes( cStr+1 ) + GetStrLenBytes( 2 ) ); break;
+ default:
+ {
+ DBG_ERROR1( "unknown ScRawToken::Clone() type %d", int(eType));
+ }
+ }
}
p = (ScRawToken*) new BYTE[ n ];
memcpy( p, this, n * sizeof(BYTE) );
@@ -297,55 +357,57 @@ ScToken* ScRawToken::CreateToken() const
{
case svByte :
return new ScByteToken( eOp, sbyte.cByte, sbyte.bHasForceArray );
- //break;
case svDouble :
IF_NOT_OPCODE_ERROR( ocPush, ScDoubleToken);
return new ScDoubleToken( nValue );
- //break;
case svString :
if (eOp == ocPush)
return new ScStringToken( String( cStr ) );
else
return new ScStringOpToken( eOp, String( cStr ) );
- //break;
case svSingleRef :
if (eOp == ocPush)
return new ScSingleRefToken( aRef.Ref1 );
else
return new ScSingleRefOpToken( eOp, aRef.Ref1 );
- //break;
case svDoubleRef :
if (eOp == ocPush)
return new ScDoubleRefToken( aRef );
else
return new ScDoubleRefOpToken( eOp, aRef );
- //break;
case svMatrix :
IF_NOT_OPCODE_ERROR( ocPush, ScMatrixToken);
return new ScMatrixToken( pMat );
- //break;
case svIndex :
return new ScIndexToken( eOp, nIndex );
- //break;
+ case svExternalSingleRef:
+ {
+ String aTabName(extref.cTabName);
+ return new ScExternalSingleRefToken(extref.nFileId, aTabName, extref.aRef.Ref1);
+ }
+ case svExternalDoubleRef:
+ {
+ String aTabName(extref.cTabName);
+ return new ScExternalDoubleRefToken(extref.nFileId, aTabName, extref.aRef);
+ }
+ case svExternalName:
+ {
+ String aName(extname.cName);
+ return new ScExternalNameToken( extname.nFileId, aName );
+ }
case svJump :
return new ScJumpToken( eOp, (short*) nJump );
- //break;
case svExternal :
return new ScExternalToken( eOp, sbyte.cByte, String( cStr+1 ) );
- //break;
case svFAP :
return new ScFAPToken( eOp, sbyte.cByte, NULL );
- //break;
case svMissing :
IF_NOT_OPCODE_ERROR( ocMissing, ScMissingToken);
return new ScMissingToken;
- //break;
case svSep :
return new ScOpToken( eOp, svSep );
- //break;
case svUnknown :
return new ScUnknownToken( eOp );
- //break;
default:
{
DBG_ERROR1( "unknown ScRawToken::CreateToken() type %d", int(GetType()));
@@ -478,68 +540,58 @@ BOOL ScToken::IsMatrixFunction() const
ScToken* ScToken::Clone() const
{
+ OpCode nOp = GetOpCode();
switch ( GetType() )
{
case svByte :
return new ScByteToken( *static_cast<const ScByteToken*>(this) );
- //break;
case svDouble :
return new ScDoubleToken( *static_cast<const ScDoubleToken*>(this) );
- //break;
case svString :
- if (GetOpCode() == ocPush)
+ if (nOp == ocPush)
return new ScStringToken( *static_cast<const ScStringToken*>(this) );
else
return new ScStringOpToken( *static_cast<const ScStringOpToken*>(this) );
- //break;
case svSingleRef :
- if (GetOpCode() == ocPush)
+ if (nOp == ocPush)
return new ScSingleRefToken( *static_cast<const ScSingleRefToken*>(this) );
else
return new ScSingleRefOpToken( *static_cast<const ScSingleRefOpToken*>(this) );
- //break;
case svDoubleRef :
- if (GetOpCode() == ocPush)
+ if (nOp == ocPush)
return new ScDoubleRefToken( *static_cast<const ScDoubleRefToken*>(this) );
else
return new ScDoubleRefOpToken( *static_cast<const ScDoubleRefOpToken*>(this) );
- //break;
case svMatrix :
return new ScMatrixToken( *static_cast<const ScMatrixToken*>(this) );
- //break;
case svIndex :
return new ScIndexToken( *static_cast<const ScIndexToken*>(this) );
- //break;
case svJump :
return new ScJumpToken( *static_cast<const ScJumpToken*>(this) );
- //break;
case svJumpMatrix :
return new ScJumpMatrixToken( *static_cast<const ScJumpMatrixToken*>(this) );
- //break;
case svRefList :
return new ScRefListToken( *static_cast<const ScRefListToken*>(this) );
- //break;
case svExternal :
return new ScExternalToken( *static_cast<const ScExternalToken*>(this) );
- //break;
+ case svExternalSingleRef :
+ return new ScExternalSingleRefToken( *static_cast<const ScExternalSingleRefToken*>(this) );
+ case svExternalDoubleRef :
+ return new ScExternalDoubleRefToken( *static_cast<const ScExternalDoubleRefToken*>(this) );
+ case svExternalName :
+ return new ScExternalNameToken( *static_cast<const ScExternalNameToken*>(this) );
case svFAP :
return new ScFAPToken( *static_cast<const ScFAPToken*>(this) );
- //break;
case svMissing :
return new ScMissingToken( *static_cast<const ScMissingToken*>(this) );
- //break;
case svError :
return new ScErrorToken( *static_cast<const ScErrorToken*>(this) );
- //break;
case svEmptyCell :
return new ScEmptyCellToken( *static_cast<const ScEmptyCellToken*>(this) );
- //break;
case svSep :
return new ScOpToken( *static_cast<const ScOpToken*>(this) );
- //break;
case svUnknown :
return new ScUnknownToken( *static_cast<const ScUnknownToken*>(this) );
- //break;
default:
DBG_ERROR1( "unknown ScToken::Clone() type %d", int(GetType()));
return new ScUnknownToken( ocBad );
@@ -655,26 +707,52 @@ ScTokenRef ScToken::ExtendRangeReference( ScToken & rTok1, ScToken & rTok2,
// Doing a RangeOp with RefList is probably utter nonsense, but Xcl
// supports it, so do we.
if (((p1 = &rTok1) == 0) || ((p2 = &rTok2) == 0) ||
- ((sv1 = p1->GetType()) != svSingleRef && sv1 != svDoubleRef && sv1 != svRefList) ||
+ ((sv1 = p1->GetType()) != svSingleRef && sv1 != svDoubleRef && sv1 != svRefList &&
+ sv1 != svExternalSingleRef && sv1 != svExternalDoubleRef) ||
((sv2 = p2->GetType()) != svSingleRef && sv2 != svDoubleRef && sv2 != svRefList))
return NULL;
ScTokenRef xRes;
- if (sv1 == svSingleRef && sv2 == svSingleRef)
+ bool bExternal = (sv1 == svExternalSingleRef);
+ if ((sv1 == svSingleRef || bExternal) && sv2 == svSingleRef)
{
// Range references like Sheet1.A1:A2 are generalized and built by
// first creating a DoubleRef from the first SingleRef, effectively
// generating Sheet1.A1:A1, and then extending that with A2 as if
// Sheet1.A1:A1:A2 was encountered, so the mechanisms to adjust the
// references apply as well.
+
+ /* Given the current structure of external references an external
+ * reference can only be extended if the second reference does not
+ * point to a different sheet. 'file'#Sheet1.A1:A2 is ok,
+ * 'file'#Sheet1.A1:Sheet2.A2 is not. Since we can't determine from a
+ * svSingleRef whether the sheet would be different from the one given
+ * in the external reference, we have to bail out if there is any sheet
+ * specified. NOTE: Xcl does handle external 3D references as in
+ * '[file]Sheet1:Sheet2'!A1:A2
+ *
+ * FIXME: For OOo syntax be smart and remember an external singleref
+ * encountered and if followed by ocRange and singleref, create an
+ * external singleref for the second singleref. Both could then be
+ * merged here. For Xcl syntax already parse an external range
+ * reference entirely, cumbersome. */
+
+ const SingleRefData& rRef2 = p2->GetSingleRef();
+ if (bExternal && rRef2.IsFlag3D())
+ return NULL;
+
ComplRefData aRef;
aRef.Ref1 = aRef.Ref2 = p1->GetSingleRef();
aRef.Ref2.SetFlag3D( false);
- aRef.Extend( p2->GetSingleRef(), rPos);
- xRes = new ScDoubleRefToken( aRef);
+ aRef.Extend( rRef2, rPos);
+ if (bExternal)
+ xRes = new ScExternalDoubleRefToken( p1->GetIndex(), p1->GetString(), aRef);
+ else
+ xRes = new ScDoubleRefToken( aRef);
}
else
{
+ bExternal |= (sv1 == svExternalDoubleRef);
const ScRefList* pRefList = NULL;
if (sv1 == svDoubleRef)
{
@@ -694,6 +772,8 @@ ScTokenRef ScToken::ExtendRangeReference( ScToken & rTok1, ScToken & rTok2,
{
if (!pRefList->size())
return NULL;
+ if (bExternal)
+ return NULL; // external reference list not possible
xRes = new ScDoubleRefToken( (*pRefList)[0] );
}
if (!xRes)
@@ -724,6 +804,18 @@ ScTokenRef ScToken::ExtendRangeReference( ScToken & rTok1, ScToken & rTok2,
}
}
break;
+ case svExternalSingleRef:
+ if (rRef.Ref1.IsFlag3D() || rRef.Ref2.IsFlag3D())
+ return NULL; // no other sheets with external refs
+ else
+ rRef.Extend( pt[i]->GetSingleRef(), rPos);
+ break;
+ case svExternalDoubleRef:
+ if (rRef.Ref1.IsFlag3D() || rRef.Ref2.IsFlag3D())
+ return NULL; // no other sheets with external refs
+ else
+ rRef.Extend( pt[i]->GetDoubleRef(), rPos);
+ break;
default:
; // nothing, prevent compiler warning
}
@@ -1035,6 +1127,190 @@ BOOL ScIndexToken::operator==( const ScToken& r ) const
return ScToken::operator==( r ) && nIndex == r.GetIndex();
}
+// ============================================================================
+
+ScExternalSingleRefToken::ScExternalSingleRefToken( sal_uInt16 nFileId, const String& rTabName, const SingleRefData& r ) :
+ ScOpToken(ocExternalRef, svExternalSingleRef),
+ mnFileId(nFileId),
+ maTabName(rTabName),
+ maSingleRef(r)
+{
+}
+
+ScExternalSingleRefToken::ScExternalSingleRefToken( const ScExternalSingleRefToken& r ) :
+ ScOpToken(r),
+ mnFileId(r.mnFileId),
+ maTabName(r.maTabName),
+ maSingleRef(r.maSingleRef)
+{
+}
+
+ScExternalSingleRefToken::~ScExternalSingleRefToken()
+{
+}
+
+USHORT ScExternalSingleRefToken::GetIndex() const
+{
+ return mnFileId;
+}
+
+const String& ScExternalSingleRefToken::GetString() const
+{
+ return maTabName;
+}
+
+const SingleRefData& ScExternalSingleRefToken::GetSingleRef() const
+{
+ return maSingleRef;
+}
+
+SingleRefData& ScExternalSingleRefToken::GetSingleRef()
+{
+ return maSingleRef;
+}
+
+BOOL ScExternalSingleRefToken::operator ==( const ScToken& r ) const
+{
+ if (!ScToken::operator==(r))
+ return false;
+
+ if (mnFileId != r.GetIndex())
+ return false;
+
+ if (maTabName != r.GetString())
+ return false;
+
+ return maSingleRef == r.GetSingleRef();
+}
+
+// ============================================================================
+
+ScExternalDoubleRefToken::ScExternalDoubleRefToken( sal_uInt16 nFileId, const String& rTabName, const ComplRefData& r ) :
+ ScOpToken(ocExternalRef, svExternalDoubleRef),
+ mnFileId(nFileId),
+ maTabName(rTabName),
+ maDoubleRef(r)
+{
+}
+
+ScExternalDoubleRefToken::ScExternalDoubleRefToken( const ScExternalDoubleRefToken& r ) :
+ ScOpToken(r),
+ mnFileId(r.mnFileId),
+ maTabName(r.maTabName),
+ maDoubleRef(r.maDoubleRef)
+{
+}
+
+ScExternalDoubleRefToken::~ScExternalDoubleRefToken()
+{
+}
+
+USHORT ScExternalDoubleRefToken::GetIndex() const
+{
+ return mnFileId;
+}
+
+const String& ScExternalDoubleRefToken::GetString() const
+{
+ return maTabName;
+}
+
+const SingleRefData& ScExternalDoubleRefToken::GetSingleRef() const
+{
+ return maDoubleRef.Ref1;
+}
+
+SingleRefData& ScExternalDoubleRefToken::GetSingleRef()
+{
+ return maDoubleRef.Ref1;
+}
+
+const SingleRefData& ScExternalDoubleRefToken::GetSingleRef2() const
+{
+ return maDoubleRef.Ref2;
+}
+
+SingleRefData& ScExternalDoubleRefToken::GetSingleRef2()
+{
+ return maDoubleRef.Ref2;
+}
+
+const ComplRefData& ScExternalDoubleRefToken::GetDoubleRef() const
+{
+ return maDoubleRef;
+}
+
+ComplRefData& ScExternalDoubleRefToken::GetDoubleRef()
+{
+ return maDoubleRef;
+}
+
+BOOL ScExternalDoubleRefToken::operator ==( const ScToken& r ) const
+{
+ if (!ScToken::operator==(r))
+ return false;
+
+ if (mnFileId != r.GetIndex())
+ return false;
+
+ if (maTabName != r.GetString())
+ return false;
+
+ return maDoubleRef == r.GetDoubleRef();
+}
+
+// ============================================================================
+
+ScExternalNameToken::ScExternalNameToken( sal_uInt16 nFileId, const String& rName ) :
+ ScOpToken(ocExternalRef, svExternalName),
+ mnFileId(nFileId),
+ maName(rName)
+{
+}
+
+ScExternalNameToken::ScExternalNameToken( const ScExternalNameToken& r ) :
+ ScOpToken(r),
+ mnFileId(r.mnFileId),
+ maName(r.maName)
+{
+}
+
+ScExternalNameToken::~ScExternalNameToken() {}
+
+USHORT ScExternalNameToken::GetIndex() const
+{
+ return mnFileId;
+}
+
+const String& ScExternalNameToken::GetString() const
+{
+ return maName;
+}
+
+BOOL ScExternalNameToken::operator==( const ScToken& r ) const
+{
+ if ( !ScToken::operator==(r) )
+ return false;
+
+ if (mnFileId != r.GetIndex())
+ return false;
+
+ xub_StrLen nLen = maName.Len();
+ const String& rName = r.GetString();
+ if (nLen != rName.Len())
+ return false;
+
+ const sal_Unicode* p1 = maName.GetBuffer();
+ const sal_Unicode* p2 = rName.GetBuffer();
+ for (xub_StrLen j = 0; j < nLen; ++j)
+ {
+ if (p1[j] != p2[j])
+ return false;
+ }
+ return true;
+}
+
+// ============================================================================
short* ScJumpToken::GetJump() const { return pJump; }
BOOL ScJumpToken::operator==( const ScToken& r ) const
@@ -1193,6 +1469,8 @@ ScToken* ScTokenArray::GetNextReference()
{
case svSingleRef:
case svDoubleRef:
+ case svExternalSingleRef:
+ case svExternalDoubleRef:
return t;
default:
{
@@ -1223,6 +1501,8 @@ ScToken* ScTokenArray::GetNextReferenceRPN()
{
case svSingleRef:
case svDoubleRef:
+ case svExternalSingleRef:
+ case svExternalDoubleRef:
return t;
default:
{
@@ -1242,6 +1522,9 @@ ScToken* ScTokenArray::GetNextReferenceOrName()
case svSingleRef:
case svDoubleRef:
case svIndex:
+ case svExternalSingleRef:
+ case svExternalDoubleRef:
+ case svExternalName:
return t;
default:
{
@@ -1785,10 +2068,11 @@ ScToken* ScTokenArray::MergeRangeReference( const ScAddress & rPos )
if (!pCode || !nLen)
return NULL;
USHORT nIdx = nLen;
- ScToken *p1, *p2, *p3;
- if (((p3 = PeekPrev(nIdx)) != 0) && p3->GetType() == svSingleRef &&
- ((p2 = PeekPrev(nIdx)) != 0) && p2->GetOpCode() == ocRange &&
- ((p1 = PeekPrev(nIdx)) != 0) && p1->GetType() == svSingleRef)
+ ScToken *p1, *p2, *p3; // ref, ocRange, ref
+ // The actual types are checked in ExtendRangeReference().
+ if (((p3 = PeekPrev(nIdx)) != 0) &&
+ (((p2 = PeekPrev(nIdx)) != 0) && p2->GetOpCode() == ocRange) &&
+ ((p1 = PeekPrev(nIdx)) != 0))
{
ScTokenRef p = ScToken::ExtendRangeReference( *p1, *p3, rPos, true);
if (p)
@@ -1893,6 +2177,21 @@ ScToken* ScTokenArray::AddMatrix( ScMatrix* p )
return Add( new ScMatrixToken( p ) );
}
+ScToken* ScTokenArray::AddExternalName( sal_uInt16 nFileId, const String& rName )
+{
+ return Add( new ScExternalNameToken(nFileId, rName) );
+}
+
+ScToken* ScTokenArray::AddExternalSingleReference( sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef )
+{
+ return Add( new ScExternalSingleRefToken(nFileId, rTabName, rRef) );
+}
+
+ScToken* ScTokenArray::AddExternalDoubleReference( sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef )
+{
+ return Add( new ScExternalDoubleRefToken(nFileId, rTabName, rRef) );
+}
+
ScToken* ScTokenArray::AddColRowName( const SingleRefData& rRef )
{
return Add( new ScSingleRefOpToken( ocColRowName, rRef ) );
diff --git a/sc/source/filter/excel/excform.cxx b/sc/source/filter/excel/excform.cxx
index 659e39c5ed99..56377ff6ead3 100644
--- a/sc/source/filter/excel/excform.cxx
+++ b/sc/source/filter/excel/excform.cxx
@@ -46,6 +46,7 @@
#include "xilink.hxx"
#include "xiname.hxx"
+using ::std::vector;
const UINT16 ExcelToSc::nRowMask = 0x3FFF;
const UINT16 ExcelToSc::nLastInd = 399;
@@ -1327,6 +1328,13 @@ ConvErr ExcelToSc::Convert( _ScRangeListTabs& rRangeList, XclImpStream& aIn, sal
return eRet;
}
+ConvErr ExcelToSc::ConvertExternName( const ScTokenArray*& /*rpArray*/, XclImpStream& /*rStrm*/, sal_Size /*nFormulaLen*/,
+ const String& /*rUrl*/, const vector<String>& /*rTabNames*/ )
+{
+ // not implemented ...
+ return ConvErrNi;
+}
+
BOOL ExcelToSc::GetAbsRefs( ScRangeList& rRangeList, XclImpStream& rStrm, sal_Size nLen )
{
DBG_ASSERT_BIFF( GetBiff() == EXC_BIFF5 );
diff --git a/sc/source/filter/excel/excform8.cxx b/sc/source/filter/excel/excform8.cxx
index e8550170d300..88c9c798bb0f 100644
--- a/sc/source/filter/excel/excform8.cxx
+++ b/sc/source/filter/excel/excform8.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: excform8.cxx,v $
- * $Revision: 1.47 $
+ * $Revision: 1.47.134.3 $
*
* This file is part of OpenOffice.org.
*
@@ -41,6 +41,18 @@
#include "xilink.hxx"
#include "xiname.hxx"
+#include "externalrefmgr.hxx"
+
+#include <vector>
+
+using ::std::vector;
+
+ExcelToSc8::ExternalTabInfo::ExternalTabInfo() :
+ mnFileId(0), mbExternal(false)
+{
+}
+
+// ============================================================================
ExcelToSc8::ExcelToSc8( const XclImpRoot& rRoot ) :
ExcelToSc( rRoot ),
@@ -53,15 +65,33 @@ ExcelToSc8::~ExcelToSc8()
{
}
+bool ExcelToSc8::GetExternalFileIdFromXti( UINT16 nIxti, sal_uInt16& rFileId ) const
+{
+ const String* pFileUrl = rLinkMan.GetSupbookUrl(nIxti);
+ if (!pFileUrl || pFileUrl->Len() == 0)
+ return false;
+
+ String aFileUrl = ScGlobal::GetAbsDocName(*pFileUrl, GetDocShell());
+ ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
+ rFileId = pRefMgr->getExternalFileId(aFileUrl);
-BOOL ExcelToSc8::Read3DTabReference( XclImpStream& rStrm, SCTAB& rFirstTab, SCTAB& rLastTab )
+ return true;
+}
+
+bool ExcelToSc8::Read3DTabReference( UINT16 nIxti, SCTAB& rFirstTab, SCTAB& rLastTab, ExternalTabInfo& rExtInfo )
{
rFirstTab = rLastTab = 0;
+ rExtInfo.mbExternal = !rLinkMan.IsSelfRef(nIxti);
+ bool bSuccess = rLinkMan.GetScTabRange(rFirstTab, rLastTab, nIxti);
+ if (!bSuccess)
+ return false;
- UINT16 nIxti;
- rStrm >> nIxti;
+ if (!rExtInfo.mbExternal)
+ // This is internal reference. Stop here.
+ return true;
- return rLinkMan.GetScTabRange( rFirstTab, rLastTab, nIxti );
+ rExtInfo.maTabName = rLinkMan.GetSupbookTabName(nIxti, rFirstTab);
+ return GetExternalFileIdFromXti(nIxti, rExtInfo.mnFileId);
}
@@ -608,8 +638,23 @@ ConvErr ExcelToSc8::Convert( const ScTokenArray*& rpTokArray, XclImpStream& aIn,
{
case xlExtName:
{
+ /* FIXME: enable this code for #i4385# once
+ * external name reference can be stored in ODF,
+ * which remains to be done for #i3740#. Until then
+ * create a #NAME? token. */
+#if 0
+ sal_uInt16 nFileId;
+ if (!GetExternalFileIdFromXti(nXtiIndex, nFileId) || !pExtName->HasFormulaTokens())
+ {
+ aStack << aPool.Store(ocNoName, pExtName->GetName());
+ break;
+ }
+
+ aStack << aPool.StoreExtName(nFileId, pExtName->GetName());
+ pExtName->CreateExtNameData(GetDoc(), nFileId);
+#else
aStack << aPool.Store( ocNoName, pExtName->GetName() );
- GetTracer().TraceFormulaExtName();
+#endif
}
break;
@@ -657,30 +702,55 @@ ConvErr ExcelToSc8::Convert( const ScTokenArray*& rpTokArray, XclImpStream& aIn,
case 0x7C:
case 0x3C: // Deleted 3-D Cell Reference [ 277]
{
- UINT16 nRw, nGrbitCol;
+ UINT16 nIxti, nRw, nGrbitCol;
SCTAB nTabFirst, nTabLast;
- BOOL bOK = Read3DTabReference( aIn, nTabFirst, nTabLast );
- aIn >> nRw >> nGrbitCol;
+ aIn >> nIxti >> nRw >> nGrbitCol;
- if( bOK )
+ ExternalTabInfo aExtInfo;
+ if (!Read3DTabReference(nIxti, nTabFirst, nTabLast, aExtInfo))
{
- aSRD.nTab = nTabFirst;
- aSRD.SetFlag3D( TRUE );
- aSRD.SetTabRel( FALSE );
+ aPool << ocBad;
+ aPool >> aStack;
+ break;
+ }
- ExcRelToScRel8( nRw, nGrbitCol, aSRD, bRangeName );
+ aSRD.nTab = nTabFirst;
+ aSRD.SetFlag3D( TRUE );
+ aSRD.SetTabRel( FALSE );
+
+ ExcRelToScRel8( nRw, nGrbitCol, aSRD, bRangeName );
+
+ switch ( nOp )
+ {
+ case 0x5C:
+ case 0x7C:
+ case 0x3C: // Deleted 3-D Cell Reference [ 277]
+ // no information which part is deleted, set both
+ aSRD.SetColDeleted( TRUE );
+ aSRD.SetRowDeleted( TRUE );
+ }
- switch ( nOp )
+ if (aExtInfo.mbExternal)
+ {
+ // nTabFirst and nTabLast are the indices of the refernced
+ // sheets in the SUPBOOK record, hence do not represent
+ // the actual indices of the original sheets since the
+ // SUPBOOK record only stores referenced sheets and skips
+ // the ones that are not referenced.
+
+ if (nTabLast != nTabFirst)
{
- case 0x5C:
- case 0x7C:
- case 0x3C: // Deleted 3-D Cell Reference [ 277]
- // no information which part is deleted, set both
- aSRD.SetColDeleted( TRUE );
- aSRD.SetRowDeleted( TRUE );
+ aCRD.Ref1 = aCRD.Ref2 = aSRD;
+ aCRD.Ref2.nTab = nTabLast;
+ aStack << aPool.StoreExtRef(aExtInfo.mnFileId, aExtInfo.maTabName, aCRD);
}
- if ( !ValidTab(nTabFirst) )
+ else
+ aStack << aPool.StoreExtRef(aExtInfo.mnFileId, aExtInfo.maTabName, aSRD);
+ }
+ else
+ {
+ if ( !ValidTab(nTabFirst))
aSRD.SetTabDeleted( TRUE );
if( nTabLast != nTabFirst )
@@ -693,11 +763,6 @@ ConvErr ExcelToSc8::Convert( const ScTokenArray*& rpTokArray, XclImpStream& aIn,
else
aStack << aPool.Store( aSRD );
}
- else
- {
- aPool << ocBad;
- aPool >> aStack;
- }
}
break;
case 0x5B:
@@ -707,43 +772,54 @@ ConvErr ExcelToSc8::Convert( const ScTokenArray*& rpTokArray, XclImpStream& aIn,
case 0x7D:
case 0x3D: // Deleted 3-D Area Reference [ 277]
{
- UINT16 nRw1, nGrbitCol1, nRw2, nGrbitCol2;
+ UINT16 nIxti, nRw1, nGrbitCol1, nRw2, nGrbitCol2;
SCTAB nTabFirst, nTabLast;
+ aIn >> nIxti >> nRw1 >> nRw2 >> nGrbitCol1 >> nGrbitCol2;
- BOOL bOK = Read3DTabReference( aIn, nTabFirst, nTabLast );
- aIn >> nRw1 >> nRw2 >> nGrbitCol1 >> nGrbitCol2;
-
- if( bOK )
+ ExternalTabInfo aExtInfo;
+ if (!Read3DTabReference(nIxti, nTabFirst, nTabLast, aExtInfo))
{
- SingleRefData &rR1 = aCRD.Ref1;
- SingleRefData &rR2 = aCRD.Ref2;
+ aPool << ocBad;
+ aPool >> aStack;
+ break;
+ }
- rR1.nTab = nTabFirst;
- rR2.nTab = nTabLast;
- rR1.SetFlag3D( TRUE );
- rR1.SetTabRel( FALSE );
- rR2.SetFlag3D( nTabFirst != nTabLast );
- rR2.SetTabRel( FALSE );
+ SingleRefData &rR1 = aCRD.Ref1;
+ SingleRefData &rR2 = aCRD.Ref2;
- ExcRelToScRel8( nRw1, nGrbitCol1, aCRD.Ref1, bRangeName );
- ExcRelToScRel8( nRw2, nGrbitCol2, aCRD.Ref2, bRangeName );
+ rR1.nTab = nTabFirst;
+ rR2.nTab = nTabLast;
+ rR1.SetFlag3D( TRUE );
+ rR1.SetTabRel( FALSE );
+ rR2.SetFlag3D( nTabFirst != nTabLast );
+ rR2.SetTabRel( FALSE );
- if( IsComplColRange( nGrbitCol1, nGrbitCol2 ) )
- SetComplCol( aCRD );
- else if( IsComplRowRange( nRw1, nRw2 ) )
- SetComplRow( aCRD );
+ ExcRelToScRel8( nRw1, nGrbitCol1, aCRD.Ref1, bRangeName );
+ ExcRelToScRel8( nRw2, nGrbitCol2, aCRD.Ref2, bRangeName );
- switch ( nOp )
- {
- case 0x5D:
- case 0x7D:
- case 0x3D: // Deleted 3-D Area Reference [ 277]
- // no information which part is deleted, set all
- rR1.SetColDeleted( TRUE );
- rR1.SetRowDeleted( TRUE );
- rR2.SetColDeleted( TRUE );
- rR2.SetRowDeleted( TRUE );
- }
+ if( IsComplColRange( nGrbitCol1, nGrbitCol2 ) )
+ SetComplCol( aCRD );
+ else if( IsComplRowRange( nRw1, nRw2 ) )
+ SetComplRow( aCRD );
+
+ switch ( nOp )
+ {
+ case 0x5D:
+ case 0x7D:
+ case 0x3D: // Deleted 3-D Area Reference [ 277]
+ // no information which part is deleted, set all
+ rR1.SetColDeleted( TRUE );
+ rR1.SetRowDeleted( TRUE );
+ rR2.SetColDeleted( TRUE );
+ rR2.SetRowDeleted( TRUE );
+ }
+
+ if (aExtInfo.mbExternal)
+ {
+ aStack << aPool.StoreExtRef(aExtInfo.mnFileId, aExtInfo.maTabName, aCRD);
+ }
+ else
+ {
if ( !ValidTab(nTabFirst) )
rR1.SetTabDeleted( TRUE );
if ( !ValidTab(nTabLast) )
@@ -751,11 +827,6 @@ ConvErr ExcelToSc8::Convert( const ScTokenArray*& rpTokArray, XclImpStream& aIn,
aStack << aPool.Store( aCRD );
}
- else
- {
- aPool << ocBad;
- aPool >> aStack;
- }
}
break;
default: bError = TRUE;
@@ -1142,7 +1213,152 @@ ConvErr ExcelToSc8::Convert( _ScRangeListTabs& rRangeList, XclImpStream& aIn, sa
return eRet;
}
+ConvErr ExcelToSc8::ConvertExternName( const ScTokenArray*& rpArray, XclImpStream& rStrm, sal_Size nFormulaLen,
+ const String& rUrl, const vector<String>& rTabNames )
+{
+ String aFileUrl = ScGlobal::GetAbsDocName(rUrl, GetDocShell());
+ sal_uInt8 nOp, nByte;
+ bool bError = false;
+
+ SingleRefData aSRD;
+ ComplRefData aCRD;
+
+ if (eStatus != ConvOK)
+ {
+ rStrm.Ignore(nFormulaLen);
+ return eStatus;
+ }
+
+ if (nFormulaLen == 0)
+ {
+ aPool.Store(CREATE_STRING("-/-"));
+ aPool >> aStack;
+ rpArray = aPool[aStack.Get()];
+ return ConvOK;
+ }
+
+ ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
+ sal_uInt16 nFileId = pRefMgr->getExternalFileId(aFileUrl);
+ sal_uInt16 nTabCount = static_cast< sal_uInt16 >( rTabNames.size() );
+
+ sal_Size nEndPos = rStrm.GetRecPos() + nFormulaLen;
+
+ while( (rStrm.GetRecPos() < nEndPos) && !bError )
+ {
+ rStrm >> nOp;
+
+ // #98524# always reset flags
+ aSRD.InitFlags();
+ aCRD.InitFlags();
+
+ switch( nOp )
+ {
+ case 0x1C: // Error Value
+ {
+ rStrm >> nByte;
+ DefTokenId eOc;
+ switch( nByte )
+ {
+ case EXC_ERR_NULL:
+ case EXC_ERR_DIV0:
+ case EXC_ERR_VALUE:
+ case EXC_ERR_REF:
+ case EXC_ERR_NAME:
+ case EXC_ERR_NUM: eOc = ocStop; break;
+ case EXC_ERR_NA: eOc = ocNotAvail; break;
+ default: eOc = ocNoName;
+ }
+ aPool << eOc;
+ if( eOc != ocStop )
+ aPool << ocOpen << ocClose;
+ aPool >> aStack;
+ }
+ break;
+ case 0x3A:
+ {
+ // cell reference in external range name
+ sal_uInt16 nExtTab1, nExtTab2, nRow, nGrbitCol;
+ rStrm >> nExtTab1 >> nExtTab2 >> nRow >> nGrbitCol;
+ if (nExtTab1 >= nTabCount || nExtTab2 >= nTabCount)
+ {
+ bError = true;
+ break;
+ }
+
+ aSRD.nTab = nExtTab1;
+ aSRD.SetFlag3D(true);
+ aSRD.SetTabRel(false);
+ ExcRelToScRel8(nRow, nGrbitCol, aSRD, true);
+ aCRD.Ref1 = aCRD.Ref2 = aSRD;
+ String aTabName = rTabNames[nExtTab1];
+
+ if (nExtTab1 == nExtTab2)
+ {
+ // single cell reference
+ aStack << aPool.StoreExtRef(nFileId, aTabName, aSRD);
+ }
+ else
+ {
+ // area reference
+ aCRD.Ref2.nTab = nExtTab2;
+ aStack << aPool.StoreExtRef(nFileId, aTabName, aCRD);
+ }
+ }
+ break;
+ case 0x3B:
+ {
+ // area reference
+ sal_uInt16 nExtTab1, nExtTab2, nRow1, nRow2, nGrbitCol1, nGrbitCol2;
+ rStrm >> nExtTab1 >> nExtTab2 >> nRow1 >> nRow2 >> nGrbitCol1 >> nGrbitCol2;
+ SingleRefData& rR1 = aCRD.Ref1;
+ SingleRefData& rR2 = aCRD.Ref2;
+
+ rR1.nTab = nExtTab1;
+ rR1.SetFlag3D(true);
+ rR1.SetTabRel(false);
+ ExcRelToScRel8(nRow1, nGrbitCol1, rR1, true);
+
+ rR2.nTab = nExtTab2;
+ rR2.SetFlag3D(true);
+ rR2.SetTabRel(false);
+ ExcRelToScRel8(nRow2, nGrbitCol2, rR2, true);
+
+ String aTabName = rTabNames[nExtTab1];
+ aStack << aPool.StoreExtRef(nFileId, aTabName, aCRD);
+ }
+ break;
+ default:
+ bError = true;
+ }
+ bError |= !rStrm.IsValid();
+ }
+
+ ConvErr eRet;
+
+ if( bError )
+ {
+ aPool << ocBad;
+ aPool >> aStack;
+ rpArray = aPool[ aStack.Get() ];
+ eRet = ConvErrNi;
+ }
+ else if( rStrm.GetRecPos() != nEndPos )
+ {
+ aPool << ocBad;
+ aPool >> aStack;
+ rpArray = aPool[ aStack.Get() ];
+ eRet = ConvErrCount;
+ }
+ else
+ {
+ rpArray = aPool[ aStack.Get() ];
+ eRet = ConvOK;
+ }
+
+ rStrm.Seek(nEndPos);
+ return eRet;
+}
void ExcelToSc8::ExcRelToScRel8( UINT16 nRow, UINT16 nC, SingleRefData &rSRD, const BOOL bName )
{
diff --git a/sc/source/filter/excel/makefile.mk b/sc/source/filter/excel/makefile.mk
index d7429978d451..ee51c4889ff7 100644
--- a/sc/source/filter/excel/makefile.mk
+++ b/sc/source/filter/excel/makefile.mk
@@ -123,6 +123,7 @@ EXCEPTIONSFILES = \
$(SLO)$/excrecds.obj \
$(SLO)$/expop2.obj \
$(SLO)$/namebuff.obj \
+ $(SLO)$/tokstack.obj \
$(SLO)$/xecontent.obj \
$(SLO)$/xeescher.obj \
$(SLO)$/xeformula.obj \
diff --git a/sc/source/filter/excel/read.cxx b/sc/source/filter/excel/read.cxx
index 9029b5867b6e..f56a00763d4e 100644
--- a/sc/source/filter/excel/read.cxx
+++ b/sc/source/filter/excel/read.cxx
@@ -967,7 +967,7 @@ FltError ImportExcel8::Read( void )
case EXC_ID_SUPBOOK: rLinkMgr.ReadSupbook( maStrm ); break;
case EXC_ID_XCT: rLinkMgr.ReadXct( maStrm ); break;
case EXC_ID_CRN: rLinkMgr.ReadCrn( maStrm ); break;
- case EXC_ID_EXTERNNAME: rLinkMgr.ReadExternname( maStrm ); break;
+ case EXC_ID_EXTERNNAME: rLinkMgr.ReadExternname( maStrm, pFormConv ); break;
case EXC_ID_MSODRAWINGGROUP:rObjMgr.ReadMsoDrawingGroup( maStrm ); break;
diff --git a/sc/source/filter/excel/tokstack.cxx b/sc/source/filter/excel/tokstack.cxx
index c8a2b41b8b34..d413f8f687f7 100644
--- a/sc/source/filter/excel/tokstack.cxx
+++ b/sc/source/filter/excel/tokstack.cxx
@@ -395,6 +395,34 @@ void TokenPool::GetElement( const UINT16 nId )
pScToken->AddMatrix( p );
}
break;
+ case T_ExtName:
+ {
+ UINT16 n = pElement[nId];
+ if (n < maExtNames.size())
+ {
+ const ExtName& r = maExtNames[n];
+ pScToken->AddExternalName(r.mnFileId, r.maName);
+ }
+ }
+ case T_ExtRefC:
+ {
+ UINT16 n = pElement[nId];
+ if (n < maExtCellRefs.size())
+ {
+ const ExtCellRef& r = maExtCellRefs[n];
+ pScToken->AddExternalSingleReference(r.mnFileId, r.maTabName, r.maRef);
+ }
+ }
+ case T_ExtRefA:
+ {
+ UINT16 n = pElement[nId];
+ if (n < maExtAreaRefs.size())
+ {
+ const ExtAreaRef& r = maExtAreaRefs[n];
+ pScToken->AddExternalDoubleReference(r.mnFileId, r.maTabName, r.maRef);
+ }
+ }
+ break;
default:
DBG_ERROR("-TokenPool::GetElement(): Zustand undefiniert!?");
}
@@ -477,6 +505,34 @@ void TokenPool::GetElementRek( const UINT16 nId )
pScToken->AddMatrix( p );
}
break;
+ case T_ExtName:
+ {
+ UINT16 n = pElement[*pAkt];
+ if (n < maExtNames.size())
+ {
+ const ExtName& r = maExtNames[n];
+ pScToken->AddExternalName(r.mnFileId, r.maName);
+ }
+ }
+ case T_ExtRefC:
+ {
+ UINT16 n = pElement[*pAkt];
+ if (n < maExtCellRefs.size())
+ {
+ const ExtCellRef& r = maExtCellRefs[n];
+ pScToken->AddExternalSingleReference(r.mnFileId, r.maTabName, r.maRef);
+ }
+ }
+ case T_ExtRefA:
+ {
+ UINT16 n = pElement[*pAkt];
+ if (n < maExtAreaRefs.size())
+ {
+ const ExtAreaRef& r = maExtAreaRefs[n];
+ pScToken->AddExternalDoubleReference(r.mnFileId, r.maTabName, r.maRef);
+ }
+ }
+ break;
default:
DBG_ERROR("-TokenPool::GetElementRek(): Zustand undefiniert!?");
}
@@ -724,9 +780,68 @@ const TokenId TokenPool::StoreMatrix( SCSIZE nC, SCSIZE nR )
return ( const TokenId ) nElementAkt;
}
+const TokenId TokenPool::StoreExtName( sal_uInt16 nFileId, const String& rName )
+{
+ if ( nElementAkt >= nElement )
+ GrowElement();
+
+ pElement[nElementAkt] = static_cast<UINT16>(maExtNames.size());
+ pType[nElementAkt] = T_ExtName;
+
+ maExtNames.push_back(ExtName());
+ ExtName& r = maExtNames.back();
+ r.mnFileId = nFileId;
+ r.maName = rName;
+
+ ++nElementAkt;
+
+ return static_cast<const TokenId>(nElementAkt);
+}
+
+const TokenId TokenPool::StoreExtRef( sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef )
+{
+ if ( nElementAkt >= nElement )
+ GrowElement();
+
+ pElement[nElementAkt] = static_cast<UINT16>(maExtCellRefs.size());
+ pType[nElementAkt] = T_ExtRefC;
+
+ maExtCellRefs.push_back(ExtCellRef());
+ ExtCellRef& r = maExtCellRefs.back();
+ r.mnFileId = nFileId;
+ r.maTabName = rTabName;
+ r.maRef = rRef;
+
+ ++nElementAkt;
+
+ return static_cast<const TokenId>(nElementAkt);
+}
+
+const TokenId TokenPool::StoreExtRef( sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef )
+{
+ if ( nElementAkt >= nElement )
+ GrowElement();
+
+ pElement[nElementAkt] = static_cast<UINT16>(maExtAreaRefs.size());
+ pType[nElementAkt] = T_ExtRefA;
+
+ maExtAreaRefs.push_back(ExtAreaRef());
+ ExtAreaRef& r = maExtAreaRefs.back();
+ r.mnFileId = nFileId;
+ r.maTabName = rTabName;
+ r.maRef = rRef;
+
+ ++nElementAkt;
+
+ return static_cast<const TokenId>(nElementAkt);
+}
+
void TokenPool::Reset( void )
{
nP_IdAkt = nP_IdLast = nElementAkt = nP_StrAkt = nP_DblAkt = nP_ErrAkt = nP_RefTrAkt = nP_ExtAkt = nP_NlfAkt = nP_MatrixAkt = 0;
+ maExtNames.clear();
+ maExtCellRefs.clear();
+ maExtAreaRefs.clear();
}
diff --git a/sc/source/filter/excel/xeformula.cxx b/sc/source/filter/excel/xeformula.cxx
index ad24d6e59395..bc77cd905ed4 100644
--- a/sc/source/filter/excel/xeformula.cxx
+++ b/sc/source/filter/excel/xeformula.cxx
@@ -42,6 +42,11 @@
#include "xelink.hxx"
#include "xename.hxx"
+#include "document.hxx"
+#include "externalrefmgr.hxx"
+
+#include <memory>
+
// External reference log =====================================================
XclExpRefLogEntry::XclExpRefLogEntry() :
@@ -225,6 +230,32 @@ void XclExpFuncData::IncExpParamClassIdx()
++mnClassIdx;
}
+// reference handling ---------------------------------------------------------
+
+namespace {
+
+inline bool lclIsRefRel2D( const SingleRefData& rRefData )
+{
+ return rRefData.IsColRel() || rRefData.IsRowRel();
+}
+
+inline bool lclIsRefDel2D( const SingleRefData& rRefData )
+{
+ return rRefData.IsColDeleted() || rRefData.IsRowDeleted();
+}
+
+inline bool lclIsRefRel2D( const ComplRefData& rRefData )
+{
+ return lclIsRefRel2D( rRefData.Ref1 ) || lclIsRefRel2D( rRefData.Ref2 );
+}
+
+inline bool lclIsRefDel2D( const ComplRefData& rRefData )
+{
+ return lclIsRefDel2D( rRefData.Ref1 ) || lclIsRefDel2D( rRefData.Ref2 );
+}
+
+} // namespace
+
// ----------------------------------------------------------------------------
/** Implementation class of the export formula compiler. */
@@ -299,6 +330,7 @@ private:
void ProcessBoolean( const XclExpTokenData& rTokData );
void ProcessDdeLink( const XclExpTokenData& rTokData, sal_uInt8 nExpClass );
void ProcessExternal( const XclExpTokenData& rTokData, sal_uInt8 nExpClass );
+ void ProcessExternalName( const XclExpTokenData& rTokData, sal_uInt8 nExpClass );
void ProcessFunction( const XclExpTokenData& rTokData, sal_uInt8 nExpClass );
void PrepareFunction( XclExpFuncData& rFuncData );
@@ -1114,6 +1146,12 @@ XclExpTokenData XclExpFmlaCompImpl::Factor( XclExpTokenData aTokData, sal_uInt8
StackVar eTokType = aTokData.GetType();
OpCode eOpCode = aTokData.GetOpCode();
+ if (eOpCode == ocExternalRef)
+ {
+ ProcessExternalName( aTokData, nExpClass );
+ return GetNextToken();
+ }
+
switch( eTokType )
{
case svUnknown: mbOk = false; break;
@@ -1248,6 +1286,133 @@ void XclExpFmlaCompImpl::ProcessExternal( const XclExpTokenData& rTokData, sal_u
ProcessFunction( rTokData, nExpClass );
}
+void XclExpFmlaCompImpl::ProcessExternalName( const XclExpTokenData& rTokData, sal_uInt8 nExpClass )
+{
+ StackVar eType = rTokData.GetType();
+
+ ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
+ USHORT nFileId = rTokData.mpScToken->GetIndex();
+ switch (eType)
+ {
+ case svExternalSingleRef:
+ {
+ if (!mpScBasePos)
+ {
+ AppendErrorToken(EXC_ERR_REF, rTokData.mnSpaces);
+ break;
+ }
+ SingleRefData aRef(rTokData.mpScToken->GetSingleRef());
+ aRef.CalcAbsIfRel(*mpScBasePos);
+ const String& rTabName = rTokData.mpScToken->GetString();
+ ScExternalRefCache::TokenRef p = pRefMgr->getSingleRefToken(nFileId, rTabName, ScAddress(aRef.nCol, aRef.nRow, aRef.nTab), NULL, NULL);
+ if (!p.get())
+ {
+ AppendErrorToken(EXC_ERR_REF, rTokData.mnSpaces);
+ break;
+ }
+
+ mpLinkMgr->StoreCell(nFileId, rTabName, aRef);
+
+ XclAddress aXclPos(ScAddress::UNINITIALIZED);
+ ConvertRefData(aRef, aXclPos, false, false, false);
+
+ sal_uInt16 nExtSheet, nFirstSBTab, nLastSBTab;
+ mpLinkMgr->FindExtSheet(nFileId, rTabName, 1, nExtSheet, nFirstSBTab, nLastSBTab, GetNewRefLogEntry());
+ sal_uInt8 nBaseId = lclIsRefDel2D(aRef) ? EXC_TOKID_REFERR3D : EXC_TOKID_REF3D;
+ AppendOpTokenId(GetTokenId(nBaseId, EXC_TOKCLASS_REF), nExpClass, rTokData.mnSpaces);
+ Append(nExtSheet);
+ if (meBiff <= EXC_BIFF5)
+ {
+ Append(0, 8);
+ Append(static_cast<sal_uInt16>(nFirstSBTab));
+ Append(static_cast<sal_uInt16>(nFirstSBTab));
+ }
+ AppendAddress(aXclPos);
+ }
+ break;
+ case svExternalDoubleRef:
+ {
+ if (!mpScBasePos)
+ {
+ AppendErrorToken(XclTools::GetXclErrorCode(errNoRef), rTokData.mnSpaces);
+ break;
+ }
+ ComplRefData aRef(rTokData.mpScToken->GetDoubleRef());
+ aRef.CalcAbsIfRel(*mpScBasePos);
+ const String& rTabName = rTokData.mpScToken->GetString();
+ const SingleRefData& r1 = aRef.Ref1;
+ const SingleRefData& r2 = aRef.Ref2;
+ ScRange aRange(r1.nCol, r1.nRow, r1.nTab, r2.nCol, r2.nRow, r2.nTab);
+ ScExternalRefCache::TokenArrayRef pArray = pRefMgr->getDoubleRefTokens(nFileId, rTabName, aRange, NULL);
+ if (!pArray.get())
+ {
+ AppendErrorToken(EXC_ERR_REF, rTokData.mnSpaces);
+ break;
+ }
+
+ mpLinkMgr->StoreCellRange(nFileId, rTabName, aRef);
+ XclRange aXclRange(ScAddress::UNINITIALIZED);
+ ConvertRefData(aRef, aXclRange, false);
+ sal_uInt16 nExtSheet, nFirstSBTab, nLastSBTab;
+ sal_uInt16 nTabSpan = r2.nTab - r1.nTab + 1;
+ mpLinkMgr->FindExtSheet(nFileId, rTabName, nTabSpan, nExtSheet, nFirstSBTab, nLastSBTab, GetNewRefLogEntry());
+
+ sal_uInt8 nBaseId = lclIsRefDel2D(aRef) ? EXC_TOKID_AREAERR3D : EXC_TOKID_AREA3D;
+ AppendOpTokenId(GetTokenId( nBaseId, EXC_TOKCLASS_REF ), nExpClass, rTokData.mnSpaces);
+ Append(nExtSheet);
+ if (meBiff <= EXC_BIFF5)
+ {
+ Append(0, 8);
+ Append(static_cast<sal_uInt16>(nFirstSBTab));
+ Append(static_cast<sal_uInt16>(nLastSBTab));
+ }
+ AppendRange(aXclRange);
+ }
+ break;
+ case svExternalName:
+ {
+ const String& aName = rTokData.mpScToken->GetString();
+ ScExternalRefCache::TokenArrayRef pArray = pRefMgr->getRangeNameTokens(nFileId, aName);
+ if (!pArray.get() || !mpScBasePos)
+ {
+ AppendErrorToken(XclTools::GetXclErrorCode(errNoName), rTokData.mnSpaces);
+ break;
+ }
+
+ // Go through all these tokens to store the external cell/range
+ // references for CRN records.
+ for (ScToken* p = pArray->First(); p; p = pArray->Next())
+ {
+ if (p->GetOpCode() == ocExternalRef)
+ {
+ if (p->GetType() == svExternalSingleRef)
+ {
+ SingleRefData aData(p->GetSingleRef());
+ aData.CalcAbsIfRel(*mpScBasePos);
+ mpLinkMgr->StoreCell(nFileId, p->GetString(), aData);
+ }
+ else if (p->GetType() == svExternalDoubleRef)
+ {
+ ComplRefData aData(p->GetDoubleRef());
+ aData.CalcAbsIfRel(*mpScBasePos);
+ mpLinkMgr->StoreCellRange(nFileId, p->GetString(), aData);
+ }
+ }
+ }
+
+ const String* pFile = pRefMgr->getExternalFileName(nFileId);
+ sal_uInt16 nExtSheet, nExtName;
+ if (mpLinkMgr->InsertExtName(nExtSheet, nExtName, *pFile, aName, pArray))
+ AppendNameXToken(nExtSheet, nExtName, nExpClass, rTokData.mnSpaces);
+ else
+ AppendErrorToken(EXC_ERR_REF, rTokData.mnSpaces);
+ }
+ break;
+ default:
+ ; // nothing
+ }
+}
+
void XclExpFmlaCompImpl::ProcessFunction( const XclExpTokenData& rTokData, sal_uInt8 nExpClass )
{
OpCode eOpCode = rTokData.GetOpCode();
@@ -1623,32 +1788,6 @@ void XclExpFmlaCompImpl::AppendTrailingParam( XclExpFuncData& rFuncData )
}
}
-// reference handling ---------------------------------------------------------
-
-namespace {
-
-inline bool lclIsRefRel2D( const SingleRefData& rRefData )
-{
- return rRefData.IsColRel() || rRefData.IsRowRel();
-}
-
-inline bool lclIsRefDel2D( const SingleRefData& rRefData )
-{
- return rRefData.IsColDeleted() || rRefData.IsRowDeleted();
-}
-
-inline bool lclIsRefRel2D( const ComplRefData& rRefData )
-{
- return lclIsRefRel2D( rRefData.Ref1 ) || lclIsRefRel2D( rRefData.Ref2 );
-}
-
-inline bool lclIsRefDel2D( const ComplRefData& rRefData )
-{
- return lclIsRefDel2D( rRefData.Ref1 ) || lclIsRefDel2D( rRefData.Ref2 );
-}
-
-} // namespace
-
// ----------------------------------------------------------------------------
SCTAB XclExpFmlaCompImpl::GetScTab( const SingleRefData& rRefData ) const
diff --git a/sc/source/filter/excel/xelink.cxx b/sc/source/filter/excel/xelink.cxx
index 9d9f2087a95d..de22ddc21fea 100644
--- a/sc/source/filter/excel/xelink.cxx
+++ b/sc/source/filter/excel/xelink.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: xelink.cxx,v $
- * $Revision: 1.21 $
+ * $Revision: 1.21.134.6 $
*
* This file is part of OpenOffice.org.
*
@@ -38,6 +38,14 @@
#include "document.hxx"
#include "cell.hxx"
#include "scextopt.hxx"
+#include "externalrefmgr.hxx"
+
+#include <vector>
+#include <memory>
+
+using ::std::auto_ptr;
+using ::std::find_if;
+using ::std::vector;
// ============================================================================
// *** Helper classes ***
@@ -102,6 +110,25 @@ private:
XclExpCachedMatRef mxMatrix; /// Cached results of the DDE link.
};
+// ----------------------------------------------------------------------------
+
+class XclExpSupbook;
+
+class XclExpExtName : public XclExpExtNameBase
+{
+public:
+ explicit XclExpExtName( const XclExpRoot& rRoot, const XclExpSupbook& rSupbook, const String& rName,
+ const ScExternalRefCache::TokenArrayRef pArray );
+
+private:
+ /** Writes additional record contents. */
+ virtual void WriteAddData( XclExpStream& rStrm );
+
+private:
+ const XclExpSupbook& mrSupbook;
+ auto_ptr<ScTokenArray> mpArray;
+};
+
// List of external names =====================================================
/** List of all external names of a sheet. */
@@ -117,6 +144,8 @@ public:
@return The 1-based (Excel-like) list index of the DDE link. */
sal_uInt16 InsertDde( const String& rApplic, const String& rTopic, const String& rItem );
+ sal_uInt16 InsertExtName( const XclExpSupbook& rSupbook, const String& rName, const ScExternalRefCache::TokenArrayRef pArray );
+
/** Writes the EXTERNNAME record list. */
virtual void Save( XclExpStream& rStrm );
@@ -220,6 +249,9 @@ public:
/** Stores all cells in the given range in the CRN list. */
void StoreCellRange( const XclExpRoot& rRoot, const ScRange& rRange );
+ void StoreCell( const XclExpRoot& rRoot, const ScAddress& rCell, const ScToken& rToken );
+ void StoreCellRange( const XclExpRoot& rRoot, const ScRange& rRange, const ScToken& rToken );
+
/** Writes the XCT and all CRN records. */
virtual void Save( XclExpStream& rStrm );
@@ -319,6 +351,12 @@ public:
/** Stores all cells in the given range in the CRN list of the specified SUPBOOK sheet. */
void StoreCellRange( const ScRange& rRange, sal_uInt16 nSBTab );
+ void StoreCell( sal_uInt16 nSBTab, const ScAddress& rCell, const ScToken& rToken );
+ void StoreCellRange( sal_uInt16 nSBTab, const ScRange& rRange, const ScToken& rToken );
+
+ sal_uInt16 GetTabIndex( const String& rTabName ) const;
+ sal_uInt16 GetTabCount() const;
+
/** Inserts a new sheet name into the SUPBOOK and returns the SUPBOOK internal sheet index. */
sal_uInt16 InsertTabName( const String& rTabName );
/** Finds or inserts an EXTERNNAME record for add-ins.
@@ -328,6 +366,8 @@ public:
@return The 1-based EXTERNNAME record index; or 0, if the record list is full. */
sal_uInt16 InsertDde( const String& rItem );
+ sal_uInt16 InsertExtName( const String& rName, const ScExternalRefCache::TokenArrayRef pArray );
+
/** Writes the SUPBOOK and all EXTERNNAME, XCT and CRN records. */
virtual void Save( XclExpStream& rStrm );
@@ -394,6 +434,9 @@ public:
/** Stores all cells in the given range in a CRN record list. */
void StoreCellRange( const ScRange& rRange );
+ void StoreCell( sal_uInt16 nFileId, const String& rTabName, const ScAddress& rCell );
+ void StoreCellRange( sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange );
+
/** Finds or inserts an EXTERNNAME record for an add-in function name.
@param rnSupbook Returns the index of the SUPBOOK record which contains the add-in function name.
@param rnExtName Returns the 1-based EXTERNNAME record index. */
@@ -407,9 +450,25 @@ public:
sal_uInt16& rnSupbook, sal_uInt16& rnExtName,
const String& rApplic, const String& rTopic, const String& rItem );
+ bool InsertExtName(
+ sal_uInt16& rnSupbook, sal_uInt16& rnExtName, const String& rUrl,
+ const String& rName, const ScExternalRefCache::TokenArrayRef pArray );
+
+ XclExpXti GetXti( sal_uInt16 nFileId, const String& rTabName, sal_uInt16 nXclTabSpan,
+ XclExpRefLogEntry* pRefLogEntry = NULL );
+
/** Writes all SUPBOOK records with their sub records. */
virtual void Save( XclExpStream& rStrm );
+ struct XclExpSBIndex
+ {
+ sal_uInt16 mnSupbook; /// SUPBOOK index for an Excel sheet.
+ sal_uInt16 mnSBTab; /// Sheet name index in SUPBOOK for an Excel sheet.
+ inline void Set( sal_uInt16 nSupbook, sal_uInt16 nSBTab )
+ { mnSupbook = nSupbook; mnSBTab = nSBTab; }
+ };
+ typedef ::std::vector< XclExpSBIndex > XclExpSBIndexVec;
+
private:
typedef XclExpRecordList< XclExpSupbook > XclExpSupbookList;
typedef XclExpSupbookList::RecordRefType XclExpSupbookRef;
@@ -431,19 +490,8 @@ private:
/** Appends a new SUPBOOK to the list.
@return The list index of the SUPBOOK record. */
sal_uInt16 Append( XclExpSupbookRef xSupbook );
- /** Creates and appends an external SUPBOOK record from the Calc sheet nScTab. */
- void AddExtSupbook( SCTAB nScTab );
private:
- struct XclExpSBIndex
- {
- sal_uInt16 mnSupbook; /// SUPBOOK index for an Excel sheet.
- sal_uInt16 mnSBTab; /// Sheet name in SUPBOOK for an Excel sheet.
- inline void Set( sal_uInt16 nSupbook, sal_uInt16 nSBTab )
- { mnSupbook = nSupbook; mnSBTab = nSBTab; }
- };
- typedef ::std::vector< XclExpSBIndex > XclExpSBIndexVec;
-
XclExpSupbookList maSupbookList; /// List of all SUPBOOK records.
XclExpSBIndexVec maSBIndexVec; /// SUPBOOK and sheet name index for each Excel sheet.
sal_uInt16 mnOwnDocSB; /// Index to SUPBOOK for own document.
@@ -464,9 +512,16 @@ public:
/** Derived classes search for a special EXTERNSHEET index for the own document. */
virtual sal_uInt16 FindExtSheet( sal_Unicode cCode ) = 0;
+ virtual void FindExtSheet( sal_uInt16 nFileId, const String& rTabName, sal_uInt16 nXclTabSpan,
+ sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
+ XclExpRefLogEntry* pRefLogEntry ) = 0;
+
/** Derived classes store all cells in the given range in a CRN record list. */
virtual void StoreCellRange( const SingleRefData& rRef1, const SingleRefData& rRef2 ) = 0;
+ virtual void StoreCell( sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef ) = 0;
+ virtual void StoreCellRange( sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef1, const SingleRefData& rRef2 ) = 0;
+
/** Derived classes find or insert an EXTERNNAME record for an add-in function name. */
virtual bool InsertAddIn(
sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
@@ -476,6 +531,10 @@ public:
sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
const String& rApplic, const String& rTopic, const String& rItem ) = 0;
+ virtual bool InsertExtName(
+ sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const String& rUrl,
+ const String& rName, const ScExternalRefCache::TokenArrayRef pArray ) = 0;
+
/** Derived classes write the entire link table to the passed stream. */
virtual void Save( XclExpStream& rStrm ) = 0;
@@ -497,15 +556,27 @@ public:
XclExpRefLogEntry* pRefLogEntry );
virtual sal_uInt16 FindExtSheet( sal_Unicode cCode );
+ virtual void FindExtSheet( sal_uInt16 nFileId, const String& rTabName, sal_uInt16 nXclTabSpan,
+ sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
+ XclExpRefLogEntry* pRefLogEntry );
+
virtual void StoreCellRange( const SingleRefData& rRef1, const SingleRefData& rRef2 );
+ virtual void StoreCell( sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef );
+ virtual void StoreCellRange( sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef1, const SingleRefData& rRef2 );
+
virtual bool InsertAddIn(
sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
const String& rName );
+
virtual bool InsertDde(
sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
const String& rApplic, const String& rTopic, const String& rItem );
+ virtual bool InsertExtName(
+ sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const String& rUrl,
+ const String& rName, const ScExternalRefCache::TokenArrayRef pArray );
+
virtual void Save( XclExpStream& rStrm );
private:
@@ -550,15 +621,27 @@ public:
XclExpRefLogEntry* pRefLogEntry );
virtual sal_uInt16 FindExtSheet( sal_Unicode cCode );
+ virtual void FindExtSheet( sal_uInt16 nFileId, const String& rTabName, sal_uInt16 nXclTabSpan,
+ sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
+ XclExpRefLogEntry* pRefLogEntry );
+
virtual void StoreCellRange( const SingleRefData& rRef1, const SingleRefData& rRef2 );
+ virtual void StoreCell( sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef );
+ virtual void StoreCellRange( sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef1, const SingleRefData& rRef2 );
+
virtual bool InsertAddIn(
sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
const String& rName );
+
virtual bool InsertDde(
sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
const String& rApplic, const String& rTopic, const String& rItem );
+ virtual bool InsertExtName(
+ sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const String& rUrl,
+ const String& rName, const ScExternalRefCache::TokenArrayRef pArray );
+
virtual void Save( XclExpStream& rStrm );
private:
@@ -885,6 +968,103 @@ void XclExpExtNameDde::WriteAddData( XclExpStream& rStrm )
mxMatrix->Save( rStrm );
}
+// ----------------------------------------------------------------------------
+
+XclExpExtName::XclExpExtName( const XclExpRoot& rRoot, const XclExpSupbook& rSupbook,
+ const String& rName, const ScExternalRefCache::TokenArrayRef pArray ) :
+ XclExpExtNameBase( rRoot, rName ),
+ mrSupbook(rSupbook),
+ mpArray(pArray->Clone())
+{
+}
+
+void XclExpExtName::WriteAddData( XclExpStream& rStrm )
+{
+ // Write only if it only has a single token that is either a cell or cell
+ // range address. Excel just writes '02 00 1C 17' for all the other types
+ // of external names.
+
+ do
+ {
+ if (mpArray->GetLen() != 1)
+ break;
+
+ const ScToken* p = mpArray->First();
+ if (p->GetOpCode() != ocExternalRef)
+ break;
+
+ switch (p->GetType())
+ {
+ case svExternalSingleRef:
+ {
+ const SingleRefData& rRef = p->GetSingleRef();
+ if (rRef.IsTabRel())
+ break;
+
+ bool bColRel = rRef.IsColRel();
+ bool bRowRel = rRef.IsRowRel();
+ sal_uInt16 nCol = static_cast< sal_uInt16 >( bColRel ? rRef.nRelCol : rRef.nCol );
+ sal_uInt16 nRow = static_cast< sal_uInt16 >( bRowRel ? rRef.nRelRow : rRef.nRow );
+ if (bColRel) nCol |= 0x4000;
+ if (bRowRel) nCol |= 0x8000;
+
+ const String& rTabName = p->GetString();
+ sal_uInt16 nSBTab = mrSupbook.GetTabIndex(rTabName);
+
+ // size is always 9
+ rStrm << static_cast<sal_uInt16>(9);
+ // operator token (3A for cell reference)
+ rStrm << static_cast<sal_uInt8>(0x3A);
+ // cell address (Excel's address has 2 sheet IDs.)
+ rStrm << nSBTab << nSBTab << nRow << nCol;
+ return;
+ }
+ case svExternalDoubleRef:
+ {
+ const ComplRefData& rRef = p->GetDoubleRef();
+ const SingleRefData& r1 = rRef.Ref1;
+ const SingleRefData& r2 = rRef.Ref2;
+ if (r1.IsTabRel() || r2.IsTabRel())
+ break;
+
+ sal_uInt16 nTab1 = r1.nTab;
+ sal_uInt16 nTab2 = r2.nTab;
+ bool bCol1Rel = r1.IsColRel();
+ bool bRow1Rel = r1.IsRowRel();
+ bool bCol2Rel = r2.IsColRel();
+ bool bRow2Rel = r2.IsRowRel();
+
+ sal_uInt16 nCol1 = static_cast< sal_uInt16 >( bCol1Rel ? r1.nRelCol : r1.nCol );
+ sal_uInt16 nCol2 = static_cast< sal_uInt16 >( bCol2Rel ? r2.nRelCol : r2.nCol );
+ sal_uInt16 nRow1 = static_cast< sal_uInt16 >( bRow1Rel ? r1.nRelRow : r1.nRow );
+ sal_uInt16 nRow2 = static_cast< sal_uInt16 >( bRow2Rel ? r2.nRelRow : r2.nRow );
+ if (bCol1Rel) nCol1 |= 0x4000;
+ if (bRow1Rel) nCol1 |= 0x8000;
+ if (bCol2Rel) nCol2 |= 0x4000;
+ if (bRow2Rel) nCol2 |= 0x8000;
+
+ const String& rTabName = p->GetString();
+ sal_uInt16 nSBTab = mrSupbook.GetTabIndex(rTabName);
+
+ // size is always 13 (0x0D)
+ rStrm << static_cast<sal_uInt16>(13);
+ // operator token (3B for area reference)
+ rStrm << static_cast<sal_uInt8>(0x3B);
+ // range (area) address
+ sal_uInt16 nSBTab2 = nSBTab + nTab2 - nTab1;
+ rStrm << nSBTab << nSBTab2 << nRow1 << nRow2 << nCol1 << nCol2;
+ return;
+ }
+ default:
+ ; // nothing
+ }
+ }
+ while (false);
+
+ // special value for #REF! (02 00 1C 17)
+ rStrm << static_cast<sal_uInt16>(2) << EXC_TOKID_ERR << EXC_ERR_REF;
+}
+
// List of external names =====================================================
XclExpExtNameBuffer::XclExpExtNameBuffer( const XclExpRoot& rRoot ) :
@@ -920,6 +1100,13 @@ sal_uInt16 XclExpExtNameBuffer::InsertDde(
return nIndex;
}
+sal_uInt16 XclExpExtNameBuffer::InsertExtName( const XclExpSupbook& rSupbook,
+ const String& rName, const ScExternalRefCache::TokenArrayRef pArray )
+{
+ sal_uInt16 nIndex = GetIndex( rName );
+ return nIndex ? nIndex : AppendNew( new XclExpExtName( GetRoot(), rSupbook, rName, pArray ) );
+}
+
void XclExpExtNameBuffer::Save( XclExpStream& rStrm )
{
maNameList.Save( rStrm );
@@ -1066,6 +1253,80 @@ void XclExpXct::StoreCellRange( const XclExpRoot& rRoot, const ScRange& rRange )
maUsedCells.SetMultiMarkArea( rRange );
}
+void XclExpXct::StoreCell( const XclExpRoot& /*rRoot*/, const ScAddress& rCell, const ScToken& rToken )
+{
+ switch (rToken.GetType())
+ {
+ case svString:
+ {
+ XclExpCrnRef xCrn(
+ new XclExpCrnString(rCell.Col(), rCell.Row(), rToken.GetString()));
+ maCrnList.AppendRecord(xCrn);
+ }
+ break;
+ case svDouble:
+ {
+ XclExpCrnRef xCrn(
+ new XclExpCrnDouble(rCell.Col(), rCell.Row(), rToken.GetDouble()));
+ maCrnList.AppendRecord(xCrn);
+ }
+ break;
+ case svEmptyCell:
+ {
+ XclExpCrnRef xCrn(
+ new XclExpCrnDouble(rCell.Col(), rCell.Row(), 0.0));
+ maCrnList.AppendRecord(xCrn);
+ }
+ break;
+ default:
+ ; // nothing
+ }
+}
+
+void XclExpXct::StoreCellRange( const XclExpRoot& /*rRoot*/, const ScRange& rRange, const ScToken& rToken )
+{
+ if (rToken.GetType() != svMatrix)
+ return;
+
+ if (rRange.aStart.Tab() != rRange.aEnd.Tab())
+ // multi-table range is not supported here.
+ return;
+
+ const ScMatrix* pMtx = rToken.GetMatrix();
+ if (!pMtx)
+ return;
+
+ SCSIZE nCols, nRows;
+ pMtx->GetDimensions(nCols, nRows);
+ const ScAddress& s = rRange.aStart;
+ const ScAddress& e = rRange.aEnd;
+ if (static_cast<SCCOL>(nCols) != e.Col() - s.Col() + 1 ||
+ static_cast<SCROW>(nRows) != e.Row() - s.Row() + 1)
+ {
+ // size mis-match!
+ return;
+ }
+
+ for (SCCOL nCol = 0; nCol < static_cast< SCCOL >( nCols ); ++nCol)
+ {
+ for (SCROW nRow = 0; nRow < static_cast< SCROW >( nRows ); ++nRow)
+ {
+ if (pMtx->IsString(nCol, nRow))
+ {
+ XclExpCrnRef xCrn(new XclExpCrnString(
+ s.Col() + nCol, s.Row() + nRow, pMtx->GetString(nCol, nRow)));
+ maCrnList.AppendRecord(xCrn);
+ }
+ else if (pMtx->IsValueOrEmpty(nCol, nRow))
+ {
+ XclExpCrnRef xCrn(new XclExpCrnDouble(
+ s.Col() + nCol, s.Row() + nRow, pMtx->GetDouble(nCol, nRow)));
+ maCrnList.AppendRecord(xCrn);
+ }
+ }
+ }
+}
+
void XclExpXct::Save( XclExpStream& rStrm )
{
XclExpRecord::Save( rStrm );
@@ -1168,6 +1429,18 @@ XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, const String& rUrl ) :
mnXclTabCount( 0 )
{
SetRecSize( 2 + maUrlEncoded.GetSize() );
+
+ // We need to create all tables up front to ensure the correct table order.
+ ScExternalRefManager* pRefMgr = rRoot.GetDoc().GetExternalRefManager();
+ sal_uInt16 nFileId = pRefMgr->getExternalFileId(rUrl);
+ vector<String> aTabNames;
+ pRefMgr->getAllCachedTableNames(nFileId, aTabNames);
+ if (aTabNames.empty())
+ return;
+
+ vector<String>::const_iterator itr = aTabNames.begin(), itrEnd = aTabNames.end();
+ for (; itr != itrEnd; ++itr)
+ InsertTabName(*itr);
}
XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, const String& rApplic, const String& rTopic ) :
@@ -1206,6 +1479,46 @@ void XclExpSupbook::StoreCellRange( const ScRange& rRange, sal_uInt16 nSBTab )
xXct->StoreCellRange( GetRoot(), rRange );
}
+void XclExpSupbook::StoreCell( sal_uInt16 nSBTab, const ScAddress& rCell, const ScToken& rToken )
+{
+ XclExpXctRef xXct = maXctList.GetRecord(nSBTab);
+ if (!xXct.is())
+ return;
+
+ xXct->StoreCell(GetRoot(), rCell, rToken);
+}
+
+void XclExpSupbook::StoreCellRange( sal_uInt16 nSBTab, const ScRange& rRange, const ScToken& rToken )
+{
+ if (rRange.aStart.Tab() != rRange.aEnd.Tab())
+ // multi-table range is not allowed!
+ return;
+
+ XclExpXctRef xXct = maXctList.GetRecord(nSBTab);
+ if (!xXct.is())
+ return;
+
+ xXct->StoreCellRange(GetRoot(), rRange, rToken);
+}
+
+sal_uInt16 XclExpSupbook::GetTabIndex( const String& rTabName ) const
+{
+ XclExpString aXclName(rTabName);
+ size_t nSize = maXctList.GetSize();
+ for (size_t i = 0; i < nSize; ++i)
+ {
+ XclExpXctRef aRec = maXctList.GetRecord(i);
+ if (aXclName == aRec->GetTabName())
+ return ulimit_cast<sal_uInt16>(i);
+ }
+ return EXC_NOTAB;
+}
+
+sal_uInt16 XclExpSupbook::GetTabCount() const
+{
+ return ulimit_cast<sal_uInt16>(maXctList.GetSize());
+}
+
sal_uInt16 XclExpSupbook::InsertTabName( const String& rTabName )
{
DBG_ASSERT( meType == EXC_SBTYPE_EXTERN, "XclExpSupbook::InsertTabName - don't insert sheet names here" );
@@ -1226,6 +1539,11 @@ sal_uInt16 XclExpSupbook::InsertDde( const String& rItem )
return GetExtNameBuffer().InsertDde( maUrl, maDdeTopic, rItem );
}
+sal_uInt16 XclExpSupbook::InsertExtName( const String& rName, const ScExternalRefCache::TokenArrayRef pArray )
+{
+ return GetExtNameBuffer().InsertExtName(*this, rName, pArray);
+}
+
void XclExpSupbook::Save( XclExpStream& rStrm )
{
// SUPBOOK record
@@ -1289,11 +1607,6 @@ XclExpSupbookBuffer::XclExpSupbookBuffer( const XclExpRoot& rRoot ) :
mnOwnDocSB = Append( xSupbook );
for( sal_uInt16 nXclTab = 0; nXclTab < nXclCnt; ++nXclTab )
maSBIndexVec[ nXclTab ].Set( mnOwnDocSB, nXclTab );
-
- // add SUPBOOKs with external references
- for( SCTAB nScTab = 0, nScCnt = rTabInfo.GetScTabCount(); nScTab < nScCnt; ++nScTab )
- if( rTabInfo.IsExternalTab( nScTab ) )
- AddExtSupbook( nScTab );
}
}
@@ -1352,6 +1665,130 @@ void XclExpSupbookBuffer::StoreCellRange( const ScRange& rRange )
}
}
+namespace {
+
+class FindSBIndexEntry
+{
+public:
+ explicit FindSBIndexEntry(sal_uInt16 nSupbookId, sal_uInt16 nTabId) :
+ mnSupbookId(nSupbookId), mnTabId(nTabId) {}
+
+ bool operator()(const XclExpSupbookBuffer::XclExpSBIndex& r) const
+ {
+ return mnSupbookId == r.mnSupbook && mnTabId == r.mnSBTab;
+ }
+
+private:
+ sal_uInt16 mnSupbookId;
+ sal_uInt16 mnTabId;
+};
+
+}
+
+void XclExpSupbookBuffer::StoreCell( sal_uInt16 nFileId, const String& rTabName, const ScAddress& rCell )
+{
+ ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
+ const String* pUrl = pRefMgr->getExternalFileName(nFileId);
+ if (!pUrl)
+ return;
+
+ XclExpSupbookRef xSupbook;
+ sal_uInt16 nSupbookId;
+ if (!GetSupbookUrl(xSupbook, nSupbookId, *pUrl))
+ {
+ xSupbook.reset(new XclExpSupbook(GetRoot(), *pUrl));
+ nSupbookId = Append(xSupbook);
+ }
+
+ ScExternalRefCache::TokenRef pToken = pRefMgr->getSingleRefToken(nFileId, rTabName, rCell, NULL, NULL);
+ if (!pToken.get())
+ return;
+
+ sal_uInt16 nSheetId = xSupbook->GetTabIndex(rTabName);
+ if (nSheetId == EXC_NOTAB)
+ // specified table name not found in this SUPBOOK.
+ return;
+
+ FindSBIndexEntry f(nSupbookId, nSheetId);
+ XclExpSBIndexVec::iterator itrEnd = maSBIndexVec.end();
+ XclExpSBIndexVec::const_iterator itr = find_if(maSBIndexVec.begin(), itrEnd, f);
+ if (itr == itrEnd)
+ {
+ maSBIndexVec.push_back(XclExpSBIndex());
+ XclExpSBIndex& r = maSBIndexVec.back();
+ r.mnSupbook = nSupbookId;
+ r.mnSBTab = nSheetId;
+ }
+
+ xSupbook->StoreCell(nSheetId, rCell, *pToken);
+}
+
+void XclExpSupbookBuffer::StoreCellRange( sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange )
+{
+ ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
+ const String* pUrl = pRefMgr->getExternalFileName(nFileId);
+ if (!pUrl)
+ return;
+
+ XclExpSupbookRef xSupbook;
+ sal_uInt16 nSupbookId;
+ if (!GetSupbookUrl(xSupbook, nSupbookId, *pUrl))
+ {
+ xSupbook.reset(new XclExpSupbook(GetRoot(), *pUrl));
+ nSupbookId = Append(xSupbook);
+ }
+
+ SCTAB nTabCount = rRange.aEnd.Tab() - rRange.aStart.Tab() + 1;
+
+ // If this is a multi-table range, get token for each table.
+ vector<ScToken*> aMatrixList;
+ aMatrixList.reserve(nTabCount);
+
+ // This is a new'ed instance, so we must manage its life cycle here.
+ ScExternalRefCache::TokenArrayRef pArray = pRefMgr->getDoubleRefTokens(nFileId, rTabName, rRange, NULL);
+ if (!pArray.get())
+ return;
+
+ for (ScToken* p = pArray->First(); p; p = pArray->Next())
+ {
+ if (p->GetType() == svMatrix)
+ aMatrixList.push_back(p);
+ else if (p->GetOpCode() != ocSep)
+ {
+ // This is supposed to be ocSep!!!
+ return;
+ }
+ }
+
+ if (aMatrixList.size() != static_cast<size_t>(nTabCount))
+ {
+ // matrix size mis-match !
+ return;
+ }
+
+ sal_uInt16 nFirstSheetId = xSupbook->GetTabIndex(rTabName);
+
+ ScRange aRange(rRange);
+ aRange.aStart.SetTab(0);
+ aRange.aEnd.SetTab(0);
+ for (SCTAB nTab = 0; nTab < nTabCount; ++nTab)
+ {
+ sal_uInt16 nSheetId = nFirstSheetId + static_cast<sal_uInt16>(nTab);
+ FindSBIndexEntry f(nSupbookId, nSheetId);
+ XclExpSBIndexVec::iterator itrEnd = maSBIndexVec.end();
+ XclExpSBIndexVec::const_iterator itr = find_if(maSBIndexVec.begin(), itrEnd, f);
+ if (itr == itrEnd)
+ {
+ maSBIndexVec.push_back(XclExpSBIndex());
+ XclExpSBIndex& r = maSBIndexVec.back();
+ r.mnSupbook = nSupbookId;
+ r.mnSBTab = nSheetId;
+ }
+
+ xSupbook->StoreCellRange(nSheetId, aRange, *aMatrixList[nTab]);
+ }
+}
+
bool XclExpSupbookBuffer::InsertAddIn(
sal_uInt16& rnSupbook, sal_uInt16& rnExtName, const String& rName )
{
@@ -1383,6 +1820,78 @@ bool XclExpSupbookBuffer::InsertDde(
return rnExtName > 0;
}
+bool XclExpSupbookBuffer::InsertExtName(
+ sal_uInt16& rnSupbook, sal_uInt16& rnExtName, const String& rUrl,
+ const String& rName, const ScExternalRefCache::TokenArrayRef pArray )
+{
+ XclExpSupbookRef xSupbook;
+ if (!GetSupbookUrl(xSupbook, rnSupbook, rUrl))
+ {
+ xSupbook.reset( new XclExpSupbook(GetRoot(), rUrl) );
+ rnSupbook = Append(xSupbook);
+ }
+ rnExtName = xSupbook->InsertExtName(rName, pArray);
+ return rnExtName > 0;
+}
+
+XclExpXti XclExpSupbookBuffer::GetXti( sal_uInt16 nFileId, const String& rTabName, sal_uInt16 nXclTabSpan,
+ XclExpRefLogEntry* pRefLogEntry )
+{
+ XclExpXti aXti(0, EXC_NOTAB, EXC_NOTAB);
+ ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
+ const String* pUrl = pRefMgr->getExternalFileName(nFileId);
+ if (!pUrl)
+ return aXti;
+
+ XclExpSupbookRef xSupbook;
+ sal_uInt16 nSupbookId;
+ if (!GetSupbookUrl(xSupbook, nSupbookId, *pUrl))
+ {
+ xSupbook.reset(new XclExpSupbook(GetRoot(), *pUrl));
+ nSupbookId = Append(xSupbook);
+ }
+ aXti.mnSupbook = nSupbookId;
+
+ sal_uInt16 nFirstSheetId = xSupbook->GetTabIndex(rTabName);
+ if (nFirstSheetId == EXC_NOTAB)
+ {
+ // first sheet not found in SUPBOOK.
+ return aXti;
+ }
+ sal_uInt16 nSheetCount = xSupbook->GetTabCount();
+ for (sal_uInt16 i = 0; i < nXclTabSpan; ++i)
+ {
+ sal_uInt16 nSheetId = nFirstSheetId + i;
+ if (nSheetId >= nSheetCount)
+ return aXti;
+
+ FindSBIndexEntry f(nSupbookId, nSheetId);
+ XclExpSBIndexVec::iterator itrEnd = maSBIndexVec.end();
+ XclExpSBIndexVec::const_iterator itr = find_if(maSBIndexVec.begin(), itrEnd, f);
+ if (itr == itrEnd)
+ {
+ maSBIndexVec.push_back(XclExpSBIndex());
+ XclExpSBIndex& r = maSBIndexVec.back();
+ r.mnSupbook = nSupbookId;
+ r.mnSBTab = nSheetId;
+ }
+ if (i == 0)
+ aXti.mnFirstSBTab = nSheetId;
+ if (i == nXclTabSpan - 1)
+ aXti.mnLastSBTab = nSheetId;
+ }
+
+ if (pRefLogEntry)
+ {
+ pRefLogEntry->mnFirstXclTab = 0;
+ pRefLogEntry->mnLastXclTab = 0;
+ if (xSupbook.is())
+ xSupbook->FillRefLogEntry(*pRefLogEntry, aXti.mnFirstSBTab, aXti.mnLastSBTab);
+ }
+
+ return aXti;
+}
+
void XclExpSupbookBuffer::Save( XclExpStream& rStrm )
{
maSupbookList.Save( rStrm );
@@ -1424,27 +1933,6 @@ sal_uInt16 XclExpSupbookBuffer::Append( XclExpSupbookRef xSupbook )
return ulimit_cast< sal_uInt16 >( maSupbookList.GetSize() - 1 );
}
-void XclExpSupbookBuffer::AddExtSupbook( SCTAB nScTab )
-{
- sal_uInt16 nXclTab = GetTabInfo().GetXclTab( nScTab );
- DBG_ASSERT( nXclTab < maSBIndexVec.size(), "XclExpSupbookBuffer::AddExtSupbook - out of range" );
-
- // find ext doc name or append new one, save position in maSBIndexBuffer
- const String& rUrl = GetDoc().GetLinkDoc( nScTab );
- DBG_ASSERT( rUrl.Len(), "XclExpSupbookBuffer::AddExtSupbook - missing external linked sheet" );
- sal_uInt16 nSupbook;
- XclExpSupbookRef xSupbook;
- if( !GetSupbookUrl( xSupbook, nSupbook, rUrl ) )
- {
- xSupbook.reset( new XclExpSupbook( GetRoot(), rUrl ) );
- nSupbook = Append( xSupbook );
- }
-
- // append new sheet name, save SUPBOOK and sheet position in maSBIndexVec
- maSBIndexVec[ nXclTab ].mnSupbook = nSupbook;
- maSBIndexVec[ nXclTab ].mnSBTab = xSupbook->InsertTabName( GetDoc().GetLinkTab( nScTab ) );
-}
-
// Export link manager ========================================================
XclExpLinkManagerImpl::XclExpLinkManagerImpl( const XclExpRoot& rRoot ) :
@@ -1485,11 +1973,29 @@ sal_uInt16 XclExpLinkManagerImpl5::FindExtSheet( sal_Unicode cCode )
return nExtSheet;
}
+void XclExpLinkManagerImpl5::FindExtSheet(
+ sal_uInt16 /*nFileId*/, const String& /*rTabName*/, sal_uInt16 /*nXclTabSpan*/,
+ sal_uInt16& /*rnExtSheet*/, sal_uInt16& /*rnFirstSBTab*/, sal_uInt16& /*rnLastSBTab*/,
+ XclExpRefLogEntry* /*pRefLogEntry*/ )
+{
+ // not implemented
+}
+
void XclExpLinkManagerImpl5::StoreCellRange( const SingleRefData& /*rRef1*/, const SingleRefData& /*rRef2*/ )
{
// not implemented
}
+void XclExpLinkManagerImpl5::StoreCell( sal_uInt16 /*nFileId*/, const String& /*rTabName*/, const SingleRefData& /*rRef*/ )
+{
+ // not implemented
+}
+
+void XclExpLinkManagerImpl5::StoreCellRange( sal_uInt16 /*nFileId*/, const String& /*rTabName*/, const SingleRefData& /*rRef1*/, const SingleRefData& /*rRef2*/ )
+{
+ // not implemented
+}
+
bool XclExpLinkManagerImpl5::InsertAddIn(
sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const String& rName )
{
@@ -1510,6 +2016,14 @@ bool XclExpLinkManagerImpl5::InsertDde(
return false;
}
+bool XclExpLinkManagerImpl5::InsertExtName(
+ sal_uInt16& /*rnExtSheet*/, sal_uInt16& /*rnExtName*/, const String& /*rUrl*/,
+ const String& /*rName*/, const ScExternalRefCache::TokenArrayRef /*pArray*/ )
+{
+ // not implemented
+ return false;
+}
+
void XclExpLinkManagerImpl5::Save( XclExpStream& rStrm )
{
if( sal_uInt16 nExtSheetCount = GetExtSheetCount() )
@@ -1630,6 +2144,17 @@ sal_uInt16 XclExpLinkManagerImpl8::FindExtSheet( sal_Unicode cCode )
return InsertXti( maSBBuffer.GetXti( EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) );
}
+void XclExpLinkManagerImpl8::FindExtSheet(
+ sal_uInt16 nFileId, const String& rTabName, sal_uInt16 nXclTabSpan,
+ sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
+ XclExpRefLogEntry* pRefLogEntry )
+{
+ XclExpXti aXti = maSBBuffer.GetXti(nFileId, rTabName, nXclTabSpan, pRefLogEntry);
+ rnExtSheet = InsertXti(aXti);
+ rnFirstSBTab = aXti.mnFirstSBTab;
+ rnLastSBTab = aXti.mnLastSBTab;
+}
+
void XclExpLinkManagerImpl8::StoreCellRange( const SingleRefData& rRef1, const SingleRefData& rRef2 )
{
if( !rRef1.IsDeleted() && !rRef2.IsDeleted() && (rRef1.nTab >= 0) && (rRef2.nTab >= 0) )
@@ -1652,6 +2177,19 @@ void XclExpLinkManagerImpl8::StoreCellRange( const SingleRefData& rRef1, const S
}
}
+void XclExpLinkManagerImpl8::StoreCell( sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef )
+{
+ ScAddress aAddr(rRef.nCol, rRef.nRow, rRef.nTab);
+ maSBBuffer.StoreCell(nFileId, rTabName, aAddr);
+}
+
+void XclExpLinkManagerImpl8::StoreCellRange( sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef1, const SingleRefData& rRef2 )
+{
+ ScRange aRange(static_cast<SCCOL>(rRef1.nCol), static_cast<SCROW>(rRef1.nRow), static_cast<SCTAB>(rRef1.nTab),
+ static_cast<SCCOL>(rRef2.nCol), static_cast<SCROW>(rRef2.nRow), static_cast<SCTAB>(rRef2.nTab));
+ maSBBuffer.StoreCellRange(nFileId, rTabName, aRange);
+}
+
bool XclExpLinkManagerImpl8::InsertAddIn(
sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const String& rName )
{
@@ -1677,6 +2215,18 @@ bool XclExpLinkManagerImpl8::InsertDde(
return false;
}
+bool XclExpLinkManagerImpl8::InsertExtName( sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
+ const String& rName, const String& rUrl, const ScExternalRefCache::TokenArrayRef pArray )
+{
+ sal_uInt16 nSupbook;
+ if( maSBBuffer.InsertExtName( nSupbook, rnExtName, rUrl, rName, pArray ) )
+ {
+ rnExtSheet = InsertXti( XclExpXti( nSupbook, EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) );
+ return true;
+ }
+ return false;
+}
+
void XclExpLinkManagerImpl8::Save( XclExpStream& rStrm )
{
if( !maXtiVec.empty() )
@@ -1745,6 +2295,13 @@ sal_uInt16 XclExpLinkManager::FindExtSheet( sal_Unicode cCode )
return mxImpl->FindExtSheet( cCode );
}
+void XclExpLinkManager::FindExtSheet( sal_uInt16 nFileId, const String& rTabName, sal_uInt16 nXclTabSpan,
+ sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
+ XclExpRefLogEntry* pRefLogEntry )
+{
+ mxImpl->FindExtSheet( nFileId, rTabName, nXclTabSpan, rnExtSheet, rnFirstSBTab, rnLastSBTab, pRefLogEntry );
+}
+
void XclExpLinkManager::StoreCell( const SingleRefData& rRef )
{
mxImpl->StoreCellRange( rRef, rRef );
@@ -1755,6 +2312,16 @@ void XclExpLinkManager::StoreCellRange( const ComplRefData& rRef )
mxImpl->StoreCellRange( rRef.Ref1, rRef.Ref2 );
}
+void XclExpLinkManager::StoreCell( sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef )
+{
+ mxImpl->StoreCell( nFileId, rTabName, rRef );
+}
+
+void XclExpLinkManager::StoreCellRange( sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef )
+{
+ mxImpl->StoreCellRange( nFileId, rTabName, rRef.Ref1, rRef.Ref2 );
+}
+
bool XclExpLinkManager::InsertAddIn(
sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const String& rName )
{
@@ -1768,6 +2335,13 @@ bool XclExpLinkManager::InsertDde(
return mxImpl->InsertDde( rnExtSheet, rnExtName, rApplic, rTopic, rItem );
}
+bool XclExpLinkManager::InsertExtName(
+ sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const String& rName, const String& rUrl,
+ const ScExternalRefCache::TokenArrayRef pArray )
+{
+ return mxImpl->InsertExtName( rnExtSheet, rnExtName, rUrl, rName, pArray );
+}
+
void XclExpLinkManager::Save( XclExpStream& rStrm )
{
mxImpl->Save( rStrm );
diff --git a/sc/source/filter/excel/xicontent.cxx b/sc/source/filter/excel/xicontent.cxx
index 36b85deab8ed..d4c5ba5a1bcf 100644
--- a/sc/source/filter/excel/xicontent.cxx
+++ b/sc/source/filter/excel/xicontent.cxx
@@ -907,7 +907,7 @@ void XclImpWebQuery::ReadWqtables( XclImpStream& rStrm )
ScGlobal::AddToken( maTables, ScfTools::GetNameFromHTMLIndex( static_cast< sal_uInt32 >( nTabNum ) ), cSep );
else
{
- ScGlobal::EraseQuotes( aToken );
+ ScGlobal::EraseQuotes( aToken, '"', false );
if( aToken.Len() )
ScGlobal::AddToken( maTables, ScfTools::GetNameFromHTMLName( aToken ), cSep );
}
diff --git a/sc/source/filter/excel/xilink.cxx b/sc/source/filter/excel/xilink.cxx
index 8190c2d78f9c..5373be4ae726 100644
--- a/sc/source/filter/excel/xilink.cxx
+++ b/sc/source/filter/excel/xilink.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: xilink.cxx,v $
- * $Revision: 1.25 $
+ * $Revision: 1.25.46.7 $
*
* This file is part of OpenOffice.org.
*
@@ -38,6 +38,13 @@
#include "xistream.hxx"
#include "xihelper.hxx"
#include "xiname.hxx"
+#include "excform.hxx"
+#include "tokenarray.hxx"
+#include "externalrefmgr.hxx"
+
+#include <vector>
+
+using ::std::vector;
// ============================================================================
// *** Helper classes ***
@@ -52,8 +59,7 @@ public:
/** Reads a cached value and stores it with its cell address. */
explicit XclImpCrn( XclImpStream& rStrm, const XclAddress& rXclPos );
- /** Copies the cached value to sheet nTab in the document. */
- void SetCell( const XclImpRoot& rRoot, SCTAB nScTab ) const;
+ const XclAddress& GetAddress() const;
private:
XclAddress maXclPos; /// Excel position of the cached cell.
@@ -71,16 +77,11 @@ public:
~XclImpSupbookTab();
inline const String& GetTabName() const { return maTabName; }
- inline SCTAB GetScTab() const { return mnScTab; }
/** Reads a CRN record (external referenced cell) at the specified address. */
void ReadCrn( XclImpStream& rStrm, const XclAddress& rXclPos );
- /** Creates a new linked table in the passed document and fills it with the cached cells.
- @descr Stores the index of the new sheet, will be accessible with GetScTab(). */
- void CreateAndFillTable(
- const XclImpRoot& rRoot, const String& rAbsUrl,
- const String& rFilterName, const String& rFilterOpt );
+ void LoadCachedValues(ScExternalRefCache::TableTypeRef pCacheTable);
private:
typedef ScfDelList< XclImpCrn > XclImpCrnList;
@@ -105,7 +106,7 @@ public:
/** Reads a CRN record (external referenced cell). */
void ReadCrn( XclImpStream& rStrm );
/** Reads an EXTERNNAME record. */
- void ReadExternname( XclImpStream& rStrm );
+ void ReadExternname( XclImpStream& rStrm, ExcelToSc* pFormulaConv = NULL );
/** Returns the SUPBOOK record type. */
inline XclSupbookType GetType() const { return meType; }
@@ -113,11 +114,6 @@ public:
/** Returns the URL of the external document. */
inline const String& GetXclUrl() const { return maXclUrl; }
- /** Returns Calc sheet index from Excel sheet index. */
- SCTAB GetScTabNum( sal_uInt16 nXclTab ) const;
- /** Returns Calc sheet index from sheet name. */
- SCTAB GetScTabNum( const String& rTabName ) const;
-
/** Returns the external name specified by an index from the Excel document (one-based). */
const XclImpExtName* GetExternName( sal_uInt16 nXclIndex ) const;
/** Tries to decode the URL to OLE or DDE link components.
@@ -128,10 +124,11 @@ public:
/** Returns the specified macro name (1-based) or an empty string on error. */
const String& GetMacroName( sal_uInt16 nXclNameIdx ) const;
- /** Creates all sheets of this external document.
- @param nFirstTab The external Excel index of the first sheet to be created.
- @param nLastTab The external Excel index of the last sheet to be created. */
- void CreateTables( sal_uInt16 nSBTabFirst, sal_uInt16 nSBTabLast );
+ const String& GetTabName( sal_uInt16 nXtiTab ) const;
+
+ sal_uInt16 GetTabCount() const;
+
+ void LoadCachedValues();
private:
typedef ScfDelList< XclImpSupbookTab > XclImpSupbookTabList;
@@ -180,7 +177,7 @@ public:
/** Reads a CRN record and appends it to the current SUPBOOK. */
void ReadCrn( XclImpStream& rStrm );
/** Reads an EXTERNNAME record and appends it to the current SUPBOOK. */
- void ReadExternname( XclImpStream& rStrm );
+ void ReadExternname( XclImpStream& rStrm, ExcelToSc* pFormulaConv = NULL );
/** Returns true, if the specified XTI entry contains an internal reference. */
bool IsSelfRef( sal_uInt16 nXtiIndex ) const;
@@ -191,6 +188,13 @@ public:
sal_uInt16 nXtiIndex ) const;
/** Returns the specified external name or 0 on error. */
const XclImpExtName* GetExternName( sal_uInt16 nXtiIndex, sal_uInt16 nExtName ) const;
+
+ /** Returns the absolute file URL of a supporting workbook specified by
+ the index. */
+ const String* GetSupbookUrl( sal_uInt16 nXtiIndex ) const;
+
+ const String& GetSupbookTabName( sal_uInt16 nXti, sal_uInt16 nXtiTab ) const;
+
/** Tries to decode the URL of the specified XTI entry to OLE or DDE link components.
@descr For DDE links: Decodes to application name and topic.
For OLE object links: Decodes to class name and document URL.
@@ -199,18 +203,13 @@ public:
/** Returns the specified macro name or an empty string on error. */
const String& GetMacroName( sal_uInt16 nExtSheet, sal_uInt16 nExtName ) const;
- /** Returns the Calc sheet index of a table in an external document.
- @return Calc sheet index or EXC_TAB_INVALID on error. */
- SCTAB GetScTab( const String& rUrl, const String& rTabName ) const;
-
private:
/** Returns the specified SUPBOOK (external document). */
const XclImpSupbook* GetSupbook( sal_uInt32 nXtiIndex ) const;
/** Returns the SUPBOOK (external workbook) specified by its URL. */
const XclImpSupbook* GetSupbook( const String& rUrl ) const;
- /** Creates all external sheets in the Calc document. */
- void CreateTables();
+ void LoadCachedValues();
/** Finds the largest range of sheet indexes in a SUPBOOK after a start sheet index.
@param rnSBTabFirst (out-param) The first sheet index of the range in SUPBOOK is returned here.
@@ -290,14 +289,13 @@ sal_uInt16 XclImpTabInfo::GetCurrentIndex( sal_uInt16 nCreatedId, sal_uInt16 nMa
// External names =============================================================
-XclImpExtName::XclImpExtName( XclImpStream& rStrm, bool bAddIn )
+XclImpExtName::XclImpExtName( const XclImpSupbook& rSupbook, XclImpStream& rStrm, bool bAddIn, ExcelToSc* pFormulaConv )
{
sal_uInt16 nFlags;
sal_uInt8 nLen;
rStrm >> nFlags >> mnStorageId >> nLen ;
maName = rStrm.ReadUniString( nLen );
-
if( ::get_flag( nFlags, EXC_EXTN_BUILTIN ) || !::get_flag( nFlags, EXC_EXTN_OLE_OR_DDE ) )
{
if( bAddIn )
@@ -318,6 +316,30 @@ XclImpExtName::XclImpExtName( XclImpStream& rStrm, bool bAddIn )
if( (meType == xlExtDDE) && (rStrm.GetRecLeft() > 1) )
mxDdeMatrix.reset( new XclImpCachedMatrix( rStrm ) );
+
+ if (meType == xlExtName)
+ {
+ // TODO: For now, only global external names are supported. In future
+ // we should extend this to supporting per-sheet external names.
+ if (mnStorageId == 0)
+ {
+ if (pFormulaConv)
+ {
+ const ScTokenArray* pArray = NULL;
+ sal_uInt16 nFmlaLen;
+ rStrm >> nFmlaLen;
+ vector<String> aTabNames;
+ sal_uInt16 nCount = rSupbook.GetTabCount();
+ aTabNames.reserve(nCount);
+ for (sal_uInt16 i = 0; i < nCount; ++i)
+ aTabNames.push_back(rSupbook.GetTabName(i));
+
+ pFormulaConv->ConvertExternName(pArray, rStrm, nFmlaLen, rSupbook.GetXclUrl(), aTabNames);
+ if (pArray)
+ mxArray.reset(pArray->Clone());
+ }
+ }
+ }
}
XclImpExtName::~XclImpExtName()
@@ -332,6 +354,20 @@ void XclImpExtName::CreateDdeData( ScDocument& rDoc, const String& rApplic, cons
rDoc.CreateDdeLink( rApplic, rTopic, maName, SC_DDE_DEFAULT, xResults );
}
+void XclImpExtName::CreateExtNameData( ScDocument& rDoc, sal_uInt16 nFileId ) const
+{
+ if (!mxArray.get())
+ return;
+
+ ScExternalRefManager* pRefMgr = rDoc.GetExternalRefManager();
+ pRefMgr->storeRangeNameTokens(nFileId, maName, *mxArray);
+}
+
+bool XclImpExtName::HasFormulaTokens() const
+{
+ return (mxArray.get() != NULL);
+}
+
// Cached external cells ======================================================
XclImpCrn::XclImpCrn( XclImpStream& rStrm, const XclAddress& rXclPos ) :
@@ -340,29 +376,9 @@ XclImpCrn::XclImpCrn( XclImpStream& rStrm, const XclAddress& rXclPos ) :
{
}
-void XclImpCrn::SetCell( const XclImpRoot& rRoot, SCTAB nScTab ) const
+const XclAddress& XclImpCrn::GetAddress() const
{
- ScAddress aScPos( ScAddress::UNINITIALIZED );
- if( rRoot.GetAddressConverter().ConvertAddress( aScPos, maXclPos, nScTab, false ) )
- {
- switch( GetType() )
- {
- case EXC_CACHEDVAL_DOUBLE:
- rRoot.GetDoc().SetValue( aScPos.Col(), aScPos.Row(), aScPos.Tab(), GetValue() );
- break;
- case EXC_CACHEDVAL_STRING:
- rRoot.GetDoc().PutCell( aScPos, new ScStringCell( GetString() ) );
- break;
- case EXC_CACHEDVAL_BOOL:
- case EXC_CACHEDVAL_ERROR:
- {
- ScFormulaCell* pFmlaCell = new ScFormulaCell( rRoot.GetDocPtr(), aScPos, GetBoolErrFmla() );
- pFmlaCell->SetHybridDouble( GetBool() ? 1.0 : 0.0 ); // GetBool() returns false for error codes
- rRoot.GetDoc().PutCell( aScPos, pFmlaCell );
- }
- break;
- }
- }
+ return maXclPos;
}
// Sheet in an external document ==============================================
@@ -382,13 +398,40 @@ void XclImpSupbookTab::ReadCrn( XclImpStream& rStrm, const XclAddress& rXclPos )
maCrnList.Append( new XclImpCrn( rStrm, rXclPos ) );
}
-void XclImpSupbookTab::CreateAndFillTable( const XclImpRoot& rRoot,
- const String& rAbsUrl, const String& rFilterName, const String& rFilterOpt )
+void XclImpSupbookTab::LoadCachedValues(ScExternalRefCache::TableTypeRef pCacheTable)
{
- if( mnScTab == SCTAB_INVALID )
- if( rRoot.GetDoc().InsertLinkedEmptyTab( mnScTab, rAbsUrl, rFilterName, rFilterOpt, maTabName ) )
- for( const XclImpCrn* pCrn = maCrnList.First(); pCrn; pCrn = maCrnList.Next() )
- pCrn->SetCell( rRoot, mnScTab );
+ if (maCrnList.Empty())
+ return;
+
+ for (XclImpCrn* p = maCrnList.First(); p; p = maCrnList.Next())
+ {
+ const XclAddress& rAddr = p->GetAddress();
+ switch (p->GetType())
+ {
+ case EXC_CACHEDVAL_BOOL:
+ break;
+ case EXC_CACHEDVAL_DOUBLE:
+ {
+ double f = p->GetValue();
+ ScExternalRefCache::TokenRef pToken(new ScDoubleToken(f));
+ pCacheTable->setCell(rAddr.mnCol, rAddr.mnRow, pToken);
+ }
+ break;
+ case EXC_CACHEDVAL_EMPTY:
+ break;
+ case EXC_CACHEDVAL_ERROR:
+ break;
+ case EXC_CACHEDVAL_STRING:
+ {
+ const String& rStr = p->GetString();
+ ScExternalRefCache::TokenRef pToken(new ScStringToken(rStr));
+ pCacheTable->setCell(rAddr.mnCol, rAddr.mnRow, pToken);
+ }
+ break;
+ default:
+ ;
+ }
+ }
}
// External document (SUPBOOK) ================================================
@@ -452,25 +495,9 @@ void XclImpSupbook::ReadCrn( XclImpStream& rStrm )
}
}
-void XclImpSupbook::ReadExternname( XclImpStream& rStrm )
-{
- maExtNameList.Append( new XclImpExtName( rStrm, meType == EXC_SBTYPE_ADDIN ) );
-}
-
-SCTAB XclImpSupbook::GetScTabNum( sal_uInt16 nXclTab ) const
-{
- if( meType == EXC_SBTYPE_SELF )
- return static_cast< SCTAB >( nXclTab );
- const XclImpSupbookTab* pSBTab = maSupbTabList.GetObject( nXclTab );
- return pSBTab ? pSBTab->GetScTab() : SCTAB_INVALID;
-}
-
-SCTAB XclImpSupbook::GetScTabNum( const String& rTabName ) const
+void XclImpSupbook::ReadExternname( XclImpStream& rStrm, ExcelToSc* pFormulaConv )
{
- for( const XclImpSupbookTab* pSBTab = maSupbTabList.First(); pSBTab; pSBTab = maSupbTabList.Next() )
- if( pSBTab->GetTabName() == rTabName )
- return pSBTab->GetScTab();
- return SCTAB_INVALID;
+ maExtNameList.Append( new XclImpExtName( *this, rStrm, meType == EXC_SBTYPE_ADDIN, pFormulaConv ) );
}
const XclImpExtName* XclImpSupbook::GetExternName( sal_uInt16 nXclIndex ) const
@@ -491,20 +518,46 @@ const String& XclImpSupbook::GetMacroName( sal_uInt16 nXclNameIdx ) const
return (pName && pName->IsVBName()) ? pName->GetScName() : EMPTY_STRING;
}
-void XclImpSupbook::CreateTables( sal_uInt16 nSBTabFirst, sal_uInt16 nSBTabLast )
+const String& XclImpSupbook::GetTabName( sal_uInt16 nXtiTab ) const
{
- if( (meType == EXC_SBTYPE_EXTERN) && (GetExtDocOptions().GetDocSettings().mnLinkCnt == 0) && GetDocShell() )
+ if (maSupbTabList.Empty())
+ return EMPTY_STRING;
+
+ sal_uInt16 i = 0;
+ for (XclImpSupbookTab* p = maSupbTabList.First(); p; p = maSupbTabList.Next(), ++i)
{
- String aAbsUrl( ScGlobal::GetAbsDocName( maXclUrl, GetDocShell() ) );
+ if (i == nXtiTab)
+ return p->GetTabName();
+ }
+
+ return EMPTY_STRING;
+}
+
+sal_uInt16 XclImpSupbook::GetTabCount() const
+{
+ return ulimit_cast<sal_uInt16>(maSupbTabList.Count());
+}
+
+void XclImpSupbook::LoadCachedValues()
+{
+ if (meType != EXC_SBTYPE_EXTERN || GetExtDocOptions().GetDocSettings().mnLinkCnt > 0)
+ return;
- // get filter name for external document
- if( !maFilterName.Len() )
- ScDocumentLoader::GetFilterName( aAbsUrl, maFilterName, maFilterOpt, FALSE, FALSE );
+ String aAbsUrl( ScGlobal::GetAbsDocName(maXclUrl, GetDocShell()) );
- // create tables
- for( sal_uInt16 nSBTab = nSBTabFirst; nSBTab <= nSBTabLast; ++nSBTab )
- if( XclImpSupbookTab* pSBTab = maSupbTabList.GetObject( nSBTab ) )
- pSBTab->CreateAndFillTable( GetRoot(), aAbsUrl, maFilterName, maFilterOpt );
+ ScExternalRefManager* pRefMgr = GetRoot().GetDoc().GetExternalRefManager();
+ sal_uInt16 nFileId = pRefMgr->getExternalFileId(aAbsUrl);
+
+ sal_uInt16 nCount = static_cast< sal_uInt16 >( maSupbTabList.Count() );
+ for (sal_uInt16 i = 0; i < nCount; ++i)
+ {
+ XclImpSupbookTab* pTab = maSupbTabList.GetObject(i);
+ if (!pTab)
+ return;
+
+ const String& rTabName = pTab->GetTabName();
+ ScExternalRefCache::TableTypeRef pCacheTable = pRefMgr->getCacheTable(nFileId, rTabName, true);
+ pTab->LoadCachedValues(pCacheTable);
}
}
@@ -530,7 +583,7 @@ void XclImpLinkManagerImpl::ReadExternsheet( XclImpStream& rStrm )
--nXtiCount;
}
- CreateTables();
+ LoadCachedValues();
}
void XclImpLinkManagerImpl::ReadSupbook( XclImpStream& rStrm )
@@ -550,10 +603,10 @@ void XclImpLinkManagerImpl::ReadCrn( XclImpStream& rStrm )
pSupbook->ReadCrn( rStrm );
}
-void XclImpLinkManagerImpl::ReadExternname( XclImpStream& rStrm )
+void XclImpLinkManagerImpl::ReadExternname( XclImpStream& rStrm, ExcelToSc* pFormulaConv )
{
if( XclImpSupbook* pSupbook = maSupbookList.Last() )
- pSupbook->ReadExternname( rStrm );
+ pSupbook->ReadExternname( rStrm, pFormulaConv );
}
bool XclImpLinkManagerImpl::IsSelfRef( sal_uInt16 nXtiIndex ) const
@@ -567,10 +620,10 @@ bool XclImpLinkManagerImpl::GetScTabRange(
{
if( const XclImpXti* pXti = maXtiList.GetObject( nXtiIndex ) )
{
- if( const XclImpSupbook* pSupbook = maSupbookList.GetObject( pXti->mnSupbook ) )
+ if (maSupbookList.GetObject(pXti->mnSupbook))
{
- rnFirstScTab = pSupbook->GetScTabNum( pXti->mnSBTabFirst );
- rnLastScTab = pSupbook->GetScTabNum( pXti->mnSBTabLast );
+ rnFirstScTab = pXti->mnSBTabFirst;
+ rnLastScTab = pXti->mnSBTabLast;
return true;
}
}
@@ -583,6 +636,20 @@ const XclImpExtName* XclImpLinkManagerImpl::GetExternName( sal_uInt16 nXtiIndex,
return pSupbook ? pSupbook->GetExternName( nExtName ) : 0;
}
+const String* XclImpLinkManagerImpl::GetSupbookUrl( sal_uInt16 nXtiIndex ) const
+{
+ const XclImpSupbook* p = GetSupbook( nXtiIndex );
+ if (!p)
+ return NULL;
+ return &p->GetXclUrl();
+}
+
+const String& XclImpLinkManagerImpl::GetSupbookTabName( sal_uInt16 nXti, sal_uInt16 nXtiTab ) const
+{
+ const XclImpSupbook* p = GetSupbook(nXti);
+ return p ? p->GetTabName(nXtiTab) : EMPTY_STRING;
+}
+
bool XclImpLinkManagerImpl::GetLinkData( String& rApplic, String& rTopic, sal_uInt16 nXtiIndex ) const
{
const XclImpSupbook* pSupbook = GetSupbook( nXtiIndex );
@@ -595,12 +662,6 @@ const String& XclImpLinkManagerImpl::GetMacroName( sal_uInt16 nExtSheet, sal_uIn
return pSupbook ? pSupbook->GetMacroName( nExtName ) : EMPTY_STRING;
}
-SCTAB XclImpLinkManagerImpl::GetScTab( const String& rUrl, const String& rTabName ) const
-{
- const XclImpSupbook* pSupbook = GetSupbook( rUrl );
- return pSupbook ? pSupbook->GetScTabNum( rTabName ) : SCTAB_INVALID;
-}
-
const XclImpSupbook* XclImpLinkManagerImpl::GetSupbook( sal_uInt32 nXtiIndex ) const
{
const XclImpXti* pXti = maXtiList.GetObject( nXtiIndex );
@@ -615,26 +676,17 @@ const XclImpSupbook* XclImpLinkManagerImpl::GetSupbook( const String& rUrl ) con
return 0;
}
-void XclImpLinkManagerImpl::CreateTables()
+void XclImpLinkManagerImpl::LoadCachedValues()
{
- DBG_ASSERT( !mbCreated, "XclImpLinkManager::CreateTables - multiple call" );
- if( mbCreated ) return;
+ // Read all CRN records which can be accessed via XclImpSupbook, and store
+ // the cached values to the external reference manager.
- sal_uInt16 nSBTabFirst, nSBTabLast;
sal_uInt32 nCount = maSupbookList.Count();
-
- for( sal_uInt16 nSupbook = 0; nSupbook < nCount; ++nSupbook )
+ for (sal_uInt16 nSupbook = 0; nSupbook < nCount; ++nSupbook)
{
- XclImpSupbook* pSupbook = maSupbookList.GetObject( nSupbook );
- bool bLoop = FindNextTabRange( nSBTabFirst, nSBTabLast, nSupbook, 0 );
- while( bLoop && pSupbook )
- {
- pSupbook->CreateTables( nSBTabFirst, nSBTabLast );
- // #96263# don't search again if last sheet == EXC_NOTAB
- bLoop = (nSBTabLast != EXC_NOTAB) && FindNextTabRange( nSBTabFirst, nSBTabLast, nSupbook, nSBTabLast + 1 );
- }
+ XclImpSupbook* pSupbook = maSupbookList.GetObject(nSupbook);
+ pSupbook->LoadCachedValues();
}
- mbCreated = true;
}
bool XclImpLinkManagerImpl::FindNextTabRange(
@@ -685,9 +737,9 @@ void XclImpLinkManager::ReadCrn( XclImpStream& rStrm )
mxImpl->ReadCrn( rStrm );
}
-void XclImpLinkManager::ReadExternname( XclImpStream& rStrm )
+void XclImpLinkManager::ReadExternname( XclImpStream& rStrm, ExcelToSc* pFormulaConv )
{
- mxImpl->ReadExternname( rStrm );
+ mxImpl->ReadExternname( rStrm, pFormulaConv );
}
bool XclImpLinkManager::IsSelfRef( sal_uInt16 nXtiIndex ) const
@@ -706,6 +758,16 @@ const XclImpExtName* XclImpLinkManager::GetExternName( sal_uInt16 nXtiIndex, sal
return mxImpl->GetExternName( nXtiIndex, nExtName );
}
+const String* XclImpLinkManager::GetSupbookUrl( sal_uInt16 nXtiIndex ) const
+{
+ return mxImpl->GetSupbookUrl(nXtiIndex);
+}
+
+const String& XclImpLinkManager::GetSupbookTabName( sal_uInt16 nXti, sal_uInt16 nXtiTab ) const
+{
+ return mxImpl->GetSupbookTabName(nXti, nXtiTab);
+}
+
bool XclImpLinkManager::GetLinkData( String& rApplic, String& rTopic, sal_uInt16 nXtiIndex ) const
{
return mxImpl->GetLinkData( rApplic, rTopic, nXtiIndex );
@@ -716,10 +778,5 @@ const String& XclImpLinkManager::GetMacroName( sal_uInt16 nExtSheet, sal_uInt16
return mxImpl->GetMacroName( nExtSheet, nExtName );
}
-SCTAB XclImpLinkManager::GetScTab( const String& rUrl, const String& rTabName ) const
-{
- return mxImpl->GetScTab( rUrl, rTabName );
-}
-
// ============================================================================
diff --git a/sc/source/filter/excel/xltracer.cxx b/sc/source/filter/excel/xltracer.cxx
index f4dcc65b940d..48044c8401f4 100644
--- a/sc/source/filter/excel/xltracer.cxx
+++ b/sc/source/filter/excel/xltracer.cxx
@@ -204,13 +204,6 @@ void XclTracer::TraceFillPattern( bool bFillPattern)
ProcessTraceOnce(eFillPattern);
}
-void XclTracer::TraceFormulaExtName( )
-{
- // import cannot access Excel External name ranges in
- // Formulas - see #i3740#.
- ProcessTraceOnce(eFormulaExtName);
-}
-
void XclTracer::TraceFormulaMissingArg()
{
// missing parameter in Formula record
diff --git a/sc/source/filter/ftools/ftools.cxx b/sc/source/filter/ftools/ftools.cxx
index 7f62e2b55277..4b717cc02b0a 100644
--- a/sc/source/filter/ftools/ftools.cxx
+++ b/sc/source/filter/ftools/ftools.cxx
@@ -379,7 +379,7 @@ bool ScfTools::GetHTMLNameFromName( const String& rSource, String& rName )
if( rSource.EqualsIgnoreCaseAscii( GetHTMLNamePrefix(), 0, GetHTMLNamePrefix().Len() ) )
{
rName = rSource.Copy( GetHTMLNamePrefix().Len() );
- ScGlobal::AddQuotes( rName );
+ ScGlobal::AddQuotes( rName, '"', false );
}
else if( rSource.EqualsIgnoreCaseAscii( GetHTMLIndexPrefix(), 0, GetHTMLIndexPrefix().Len() ) )
{
diff --git a/sc/source/filter/inc/XclImpChangeTrack.hxx b/sc/source/filter/inc/XclImpChangeTrack.hxx
index 0f62f7498ab3..65f981fef973 100644
--- a/sc/source/filter/inc/XclImpChangeTrack.hxx
+++ b/sc/source/filter/inc/XclImpChangeTrack.hxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: XclImpChangeTrack.hxx,v $
- * $Revision: 1.21 $
+ * $Revision: 1.21.134.1 $
*
* This file is part of OpenOffice.org.
*
@@ -126,7 +126,7 @@ public:
// reads extended 3D ref info following the formulas, returns sc tab nums
// ( called by XclImpChTrFmlConverter::Read3DTabReference() )
- sal_Bool Read3DTabRefInfo( SCTAB& rFirstTab, SCTAB& rLastTab );
+ sal_Bool Read3DTabRefInfo( SCTAB& rFirstTab, SCTAB& rLastTab, ExcelToSc8::ExternalTabInfo& rExtInfo );
void Apply();
};
@@ -182,7 +182,7 @@ class XclImpChTrFmlConverter : public ExcelToSc8
private:
XclImpChangeTrack& rChangeTrack;
- virtual BOOL Read3DTabReference( XclImpStream& rStrm, SCTAB& rFirstTab, SCTAB& rLastTab );
+ virtual bool Read3DTabReference( UINT16 nIxti, SCTAB& rFirstTab, SCTAB& rLastTab, ExternalTabInfo& rExtInfo );
public:
inline XclImpChTrFmlConverter(
diff --git a/sc/source/filter/inc/excform.hxx b/sc/source/filter/inc/excform.hxx
index 39cd1bec1d0b..4dd9c16f8dcf 100644
--- a/sc/source/filter/inc/excform.hxx
+++ b/sc/source/filter/inc/excform.hxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: excform.hxx,v $
- * $Revision: 1.22 $
+ * $Revision: 1.22.62.2 $
*
* This file is part of OpenOffice.org.
*
@@ -35,6 +35,7 @@
#include "xiroot.hxx"
#include "formel.hxx"
+#include <vector>
class ScRangeList;
@@ -64,6 +65,10 @@ public:
bool bAllowArrays, const FORMULA_TYPE eFT = FT_CellFormula );
virtual ConvErr Convert( _ScRangeListTabs&, XclImpStream& rStrm, sal_Size nFormulaLen, const FORMULA_TYPE eFT = FT_CellFormula );
+
+ virtual ConvErr ConvertExternName( const ScTokenArray*& rpArray, XclImpStream& rStrm, sal_Size nFormulaLen,
+ const String& rUrl, const ::std::vector<String>& rTabNames );
+
virtual BOOL GetAbsRefs( ScRangeList& rRangeList, XclImpStream& rStrm, sal_Size nLen );
void GetDummy( const ScTokenArray*& );
@@ -102,19 +107,32 @@ inline BOOL ExcelToSc::IsComplRowRange( const UINT16 nRow1, const UINT16 nRow2 )
return ( ( nRow1 & 0x3FFF ) == 0x0000 ) && ( ( nRow2 & 0x3FFF ) == 0x3FFF );
}
+// ============================================================================
class XclImpLinkManager;
class ExcelToSc8 : public ExcelToSc
{
+public:
+
+ struct ExternalTabInfo
+ {
+ String maTabName;
+ sal_uInt16 mnFileId;
+ bool mbExternal;
+
+ ExternalTabInfo();
+ };
+
private:
const XclImpLinkManager& rLinkMan;
void ExcRelToScRel8( UINT16 nRow, UINT16 nCol, SingleRefData&,
const BOOL bName );
- // this function must read 2 bytes from stream and adjust <nBytesLeft>
- virtual BOOL Read3DTabReference( XclImpStream& rStrm, SCTAB& rFirstTab, SCTAB& rLastTab );
+ bool GetExternalFileIdFromXti( UINT16 nIxti, sal_uInt16& rFileId ) const;
+
+ virtual bool Read3DTabReference( UINT16 nIxti, SCTAB& rFirstTab, SCTAB& rLastTab, ExternalTabInfo& rExtInfo );
public:
ExcelToSc8( const XclImpRoot& rRoot );
@@ -124,6 +142,9 @@ public:
virtual ConvErr Convert( _ScRangeListTabs&, XclImpStream& rStrm, sal_Size nFormulaLen, const FORMULA_TYPE eFT = FT_CellFormula );
+ virtual ConvErr ConvertExternName( const ScTokenArray*& rpArray, XclImpStream& rStrm, sal_Size nFormulaLen,
+ const String& rUrl, const ::std::vector<String>& rTabNames );
+
static inline BOOL IsComplRowRange( const UINT16 nRow1, const UINT16 nRow2 );
virtual BOOL GetAbsRefs( ScRangeList& rRangeList, XclImpStream& rStrm, sal_Size nLen );
diff --git a/sc/source/filter/inc/tokstack.hxx b/sc/source/filter/inc/tokstack.hxx
index 42e5718ecda4..5d5ec3919f34 100644
--- a/sc/source/filter/inc/tokstack.hxx
+++ b/sc/source/filter/inc/tokstack.hxx
@@ -35,6 +35,8 @@
#include <tools/debug.hxx>
#include "compiler.hxx"
+#include <vector>
+
typedef OpCode DefTokenId;
// in PRODUCT version: ambiguity between OpCode (being USHORT) and UINT16
@@ -78,6 +80,9 @@ enum E_TYPE
T_Ext, // irgendwas Unbekanntes mit Funktionsnamen
T_Nlf, // token for natural language formula
T_Matrix, // token for inline arrays
+ T_ExtName, // token for external names
+ T_ExtRefC,
+ T_ExtRefA,
T_Error // fuer Abfrage im Fehlerfall
};
@@ -134,6 +139,32 @@ class TokenPool
UINT16 nP_Matrix;
UINT16 nP_MatrixAkt;
+ /** for storage of external names */
+ struct ExtName
+ {
+ sal_uInt16 mnFileId;
+ String maName;
+ };
+ ::std::vector<ExtName> maExtNames;
+
+ /** for storage of external cell references */
+ struct ExtCellRef
+ {
+ sal_uInt16 mnFileId;
+ String maTabName;
+ SingleRefData maRef;
+ };
+ ::std::vector<ExtCellRef> maExtCellRefs;
+
+ /** for storage of external area references */
+ struct ExtAreaRef
+ {
+ sal_uInt16 mnFileId;
+ String maTabName;
+ ComplRefData maRef;
+ };
+ ::std::vector<ExtAreaRef> maExtAreaRefs;
+
UINT16* pElement; // Array mit Indizes fuer Elemente
E_TYPE* pType; // ...mit Typ-Info
UINT16* pSize; // ...mit Laengenangabe (Anz. UINT16)
@@ -180,12 +211,14 @@ class TokenPool
// 4 externals (e.g. AddIns, Makros...)
const TokenId StoreNlf( const SingleRefData& rTr );
const TokenId StoreMatrix( SCSIZE nC, SCSIZE nR );
+ const TokenId StoreExtName( sal_uInt16 nFileId, const String& rName );
+ const TokenId StoreExtRef( sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef );
+ const TokenId StoreExtRef( sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef );
inline const TokenId LastId( void ) const;
inline const ScTokenArray* operator []( const TokenId nId );
void Reset( void );
inline E_TYPE GetType( const TokenId& nId ) const;
- inline const SingleRefData* GetSRD( const TokenId& nId ) const;
BOOL IsSingleOp( const TokenId& nId, const DefTokenId eId ) const;
const String* GetExternal( const TokenId& nId ) const;
//UNUSED2008-05 const String* GetString( const TokenId& nId ) const;
@@ -374,21 +407,5 @@ inline E_TYPE TokenPool::GetType( const TokenId& rId ) const
}
-inline const SingleRefData* TokenPool::GetSRD( const TokenId& rId ) const
-{
- SingleRefData* pRet;
-
- UINT16 nId = (UINT16) rId - 1;
-
- if( nId < nElementAkt && pType[ nId ] == T_RefC )
- pRet = ppP_RefTr[ pElement[ nId ] ];
- else
- pRet = NULL;
-
- return pRet;
-}
-
-
-
#endif
diff --git a/sc/source/filter/inc/xelink.hxx b/sc/source/filter/inc/xelink.hxx
index 74b8aa543c02..c131c71a59f9 100644
--- a/sc/source/filter/inc/xelink.hxx
+++ b/sc/source/filter/inc/xelink.hxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: xelink.hxx,v $
- * $Revision: 1.13 $
+ * $Revision: 1.13.134.2 $
*
* This file is part of OpenOffice.org.
*
@@ -36,6 +36,7 @@
#include "xehelper.hxx"
#include "xerecord.hxx"
#include "xeformula.hxx"
+#include "externalrefmgr.hxx"
class ScRange;
struct SingleRefData;
@@ -173,11 +174,19 @@ public:
/** Searches for a special EXTERNSHEET index for the own document. */
sal_uInt16 FindExtSheet( sal_Unicode cCode );
+ void FindExtSheet( sal_uInt16 nFileId, const String& rTabName, sal_uInt16 nXclTabSpan,
+ sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
+ XclExpRefLogEntry* pRefLogEntry = NULL );
+
/** Stores the cell with the given address in a CRN record list. */
void StoreCell( const SingleRefData& rRef );
/** Stores all cells in the given range in a CRN record list. */
void StoreCellRange( const ComplRefData& rRef );
+ void StoreCell( sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef );
+
+ void StoreCellRange( sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef );
+
/** Finds or inserts an EXTERNNAME record for an add-in function name.
@param rnExtSheet (out-param) Returns the index of the EXTSHEET structure for the add-in function name.
@param rnExtName (out-param) Returns the 1-based EXTERNNAME record index.
@@ -193,6 +202,10 @@ public:
sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
const String& rApplic, const String& rTopic, const String& rItem );
+ bool InsertExtName(
+ sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const String& rUrl,
+ const String& rName, const ScExternalRefCache::TokenArrayRef pArray );
+
/** Writes the entire Link table. */
virtual void Save( XclExpStream& rStrm );
diff --git a/sc/source/filter/inc/xilink.hxx b/sc/source/filter/inc/xilink.hxx
index 9996d3e33f29..c4f64700070f 100644
--- a/sc/source/filter/inc/xilink.hxx
+++ b/sc/source/filter/inc/xilink.hxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: xilink.hxx,v $
- * $Revision: 1.14 $
+ * $Revision: 1.14.134.1 $
*
* This file is part of OpenOffice.org.
*
@@ -107,6 +107,8 @@ enum XclImpExtNameType
// ----------------------------------------------------------------------------
class XclImpCachedMatrix;
+class ScTokenArray;
+class XclImpSupbook;
/** Stores contents of an external name.
@descr Supported: External defined names, AddIn names, DDE links and OLE objects. */
@@ -114,21 +116,28 @@ class XclImpExtName
{
public:
/** Reads the external name from the stream. */
- explicit XclImpExtName( XclImpStream& rStrm, bool bAddIn = false );
+ explicit XclImpExtName( const XclImpSupbook& rSupbook, XclImpStream& rStrm, bool bAddIn = false,
+ ExcelToSc* pFormulaConv = NULL );
~XclImpExtName();
/** Create and apply the cached list of this DDE Link to the document. */
void CreateDdeData( ScDocument& rDoc,
const String& rApplc, const String& rExtDoc ) const;
+ void CreateExtNameData( ScDocument& rDoc, sal_uInt16 nFileId ) const;
+
+ bool HasFormulaTokens() const;
+
inline XclImpExtNameType GetType() const { return meType; }
inline const String& GetName() const { return maName; }
inline sal_uInt32 GetStorageId() const { return mnStorageId; }
private:
typedef ::std::auto_ptr< XclImpCachedMatrix > XclImpCachedMatrixPtr;
+ typedef ::std::auto_ptr< ScTokenArray > TokenArrayPtr;
XclImpCachedMatrixPtr mxDdeMatrix; /// Cached results of the DDE link.
+ TokenArrayPtr mxArray; /// Formula tokens for external name.
String maName; /// The name of the external name.
sal_uInt32 mnStorageId; /// Storage ID for OLE object storages.
XclImpExtNameType meType; /// Type of the external name.
@@ -168,7 +177,7 @@ public:
/** Reads a CRN record and appends it to the current SUPBOOK. */
void ReadCrn( XclImpStream& rStrm );
/** Reads an EXTERNNAME record and appends it to the current SUPBOOK. */
- void ReadExternname( XclImpStream& rStrm );
+ void ReadExternname( XclImpStream& rStrm, ExcelToSc* pFormulaConv = NULL );
/** Returns true, if the specified XTI entry contains an internal reference. */
bool IsSelfRef( sal_uInt16 nXtiIndex ) const;
@@ -179,6 +188,11 @@ public:
sal_uInt16 nXtiIndex ) const;
/** Returns the specified external name or 0 on error. */
const XclImpExtName* GetExternName( sal_uInt16 nXtiIndex, sal_uInt16 nExtName ) const;
+
+ const String* GetSupbookUrl( sal_uInt16 nXtiIndex ) const;
+
+ const String& GetSupbookTabName( sal_uInt16 nXti, sal_uInt16 nXtiTab ) const;
+
/** Tries to decode the URL of the specified XTI entry to OLE or DDE link components.
@descr For DDE links: Decodes to application name and topic.
For OLE object links: Decodes to class name and document URL.
@@ -187,10 +201,6 @@ public:
/** Returns the specified macro name or an empty string on error. */
const String& GetMacroName( sal_uInt16 nExtSheet, sal_uInt16 nExtName ) const;
- /** Returns the Calc sheet index of a table in an external document.
- @return Calc sheet index or EXC_TAB_INVALID on error. */
- SCTAB GetScTab( const String& rUrl, const String& rTabName ) const;
-
private:
typedef ::std::auto_ptr< XclImpLinkManagerImpl > XclImpLinkMgrImplPtr;
XclImpLinkMgrImplPtr mxImpl;
diff --git a/sc/source/filter/inc/xltracer.hxx b/sc/source/filter/inc/xltracer.hxx
index 2d3009260140..38dd444b93ac 100644
--- a/sc/source/filter/inc/xltracer.hxx
+++ b/sc/source/filter/inc/xltracer.hxx
@@ -120,7 +120,6 @@ public:
void TraceDates(sal_uInt16 nNumFmt);
void TraceBorderLineStyle(bool bBorderLineStyle);
void TraceFillPattern(bool bFillPattern);
- void TraceFormulaExtName();
void TraceFormulaMissingArg();
void TracePivotDataSource(bool bExternal);
void TracePivotChartExists();
diff --git a/sc/source/filter/xcl97/XclImpChangeTrack.cxx b/sc/source/filter/xcl97/XclImpChangeTrack.cxx
index a268421c4aa1..2f546e323179 100644
--- a/sc/source/filter/xcl97/XclImpChangeTrack.cxx
+++ b/sc/source/filter/xcl97/XclImpChangeTrack.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: XclImpChangeTrack.cxx,v $
- * $Revision: 1.34 $
+ * $Revision: 1.34.48.1 $
*
* This file is part of OpenOffice.org.
*
@@ -40,6 +40,7 @@
#include "chgtrack.hxx"
#include "xihelper.hxx"
#include "xilink.hxx"
+#include "externalrefmgr.hxx"
//___________________________________________________________________
// class XclImpChangeTrack
@@ -153,10 +154,11 @@ sal_Bool XclImpChangeTrack::CheckRecord( sal_uInt16 nOpCode )
return aRecHeader.nIndex != 0;
}
-sal_Bool XclImpChangeTrack::Read3DTabRefInfo( SCTAB& rFirstTab, SCTAB& rLastTab )
+sal_Bool XclImpChangeTrack::Read3DTabRefInfo( SCTAB& rFirstTab, SCTAB& rLastTab, ExcelToSc8::ExternalTabInfo& rExtInfo )
{
if( LookAtuInt8() == 0x01 )
{
+ rExtInfo.mbExternal = false;
// internal ref - read tab num and return sc tab num (position in TABID list)
pStrm->Ignore( 3 );
rFirstTab = static_cast< SCTAB >( GetTabInfo().GetCurrentIndex( pStrm->ReaduInt16(), nTabIdCount ) );
@@ -176,7 +178,13 @@ sal_Bool XclImpChangeTrack::Read3DTabRefInfo( SCTAB& rFirstTab, SCTAB& rLastTab
// - sheet name, always separated from URL
String aTabName( pStrm->ReadUniString() );
pStrm->Ignore( 1 );
- rFirstTab = rLastTab = static_cast<SCTAB>(GetLinkManager().GetScTab( aUrl, aTabName ));
+
+ rExtInfo.mbExternal = true;
+ ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
+ pRefMgr->convertToAbsName(aUrl);
+ rExtInfo.mnFileId = pRefMgr->getExternalFileId(aUrl);
+ rExtInfo.maTabName = aTabName;
+ rFirstTab = rLastTab = 0;
}
return sal_True;
}
@@ -327,7 +335,8 @@ void XclImpChangeTrack::ReadChTrCellContent()
if( CheckRecord( EXC_CHTR_OP_CELL ) )
{
ScAddress aPosition;
- aPosition.SetTab( ReadTabNum() );
+ SCTAB nTab = ReadTabNum();
+ aPosition.SetTab( nTab );
sal_uInt16 nValueType;
*pStrm >> nValueType;
sal_uInt16 nOldValueType = (nValueType >> 3) & EXC_CHTR_TYPE_MASK;
@@ -488,9 +497,9 @@ XclImpChTrFmlConverter::~XclImpChTrFmlConverter()
}
// virtual, called from ExcToSc8::Convert()
-BOOL XclImpChTrFmlConverter::Read3DTabReference( XclImpStream& rStrm, SCTAB& rFirstTab, SCTAB& rLastTab )
+bool XclImpChTrFmlConverter::Read3DTabReference( UINT16 /*nIxti*/, SCTAB& rFirstTab, SCTAB& rLastTab,
+ ExternalTabInfo& rExtInfo )
{
- rStrm.Ignore( 2 );
- return rChangeTrack.Read3DTabRefInfo( rFirstTab, rLastTab );
+ return rChangeTrack.Read3DTabRefInfo( rFirstTab, rLastTab, rExtInfo );
}
diff --git a/sc/source/filter/xml/XMLDDELinksContext.cxx b/sc/source/filter/xml/XMLDDELinksContext.cxx
index 2769b6cbaee0..c0872ae07668 100644
--- a/sc/source/filter/xml/XMLDDELinksContext.cxx
+++ b/sc/source/filter/xml/XMLDDELinksContext.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: XMLDDELinksContext.cxx,v $
- * $Revision: 1.18 $
+ * $Revision: 1.18.134.1 $
*
* This file is part of OpenOffice.org.
*
@@ -46,6 +46,7 @@
using namespace com::sun::star;
using namespace xmloff::token;
+using ::rtl::OUString;
//------------------------------------------------------------------
diff --git a/sc/source/filter/xml/XMLTableShapeImportHelper.cxx b/sc/source/filter/xml/XMLTableShapeImportHelper.cxx
index 28bc37702b21..6673b19697bc 100644
--- a/sc/source/filter/xml/XMLTableShapeImportHelper.cxx
+++ b/sc/source/filter/xml/XMLTableShapeImportHelper.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: XMLTableShapeImportHelper.cxx,v $
- * $Revision: 1.29 $
+ * $Revision: 1.29.134.1 $
*
* This file is part of OpenOffice.org.
*
@@ -49,6 +49,7 @@
using namespace ::com::sun::star;
using namespace xmloff::token;
+using ::rtl::OUString;
XMLTableShapeImportHelper::XMLTableShapeImportHelper(
ScXMLImport& rImp, SvXMLImportPropertyMapper *pImpMapper ) :
diff --git a/sc/source/filter/xml/XMLTrackedChangesContext.cxx b/sc/source/filter/xml/XMLTrackedChangesContext.cxx
index be2ba7c71718..bc76bf2abc9e 100644
--- a/sc/source/filter/xml/XMLTrackedChangesContext.cxx
+++ b/sc/source/filter/xml/XMLTrackedChangesContext.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: XMLTrackedChangesContext.cxx,v $
- * $Revision: 1.32 $
+ * $Revision: 1.32.62.1 $
*
* This file is part of OpenOffice.org.
*
@@ -48,6 +48,7 @@
using namespace com::sun::star;
using namespace xmloff::token;
+using ::rtl::OUString;
//-----------------------------------------------------------------------------
diff --git a/sc/source/filter/xml/makefile.mk b/sc/source/filter/xml/makefile.mk
index da9d349d0a8d..19d8a99f789c 100644
--- a/sc/source/filter/xml/makefile.mk
+++ b/sc/source/filter/xml/makefile.mk
@@ -8,7 +8,7 @@
#
# $RCSfile: makefile.mk,v $
#
-# $Revision: 1.33 $
+# $Revision: 1.33.134.1 $
#
# This file is part of OpenOffice.org.
#
@@ -57,6 +57,7 @@ CXXFILES = \
xmlexprt.cxx \
xmlbodyi.cxx \
xmltabi.cxx \
+ xmlexternaltabi.cxx \
xmlrowi.cxx \
xmlcelli.cxx \
xmlconti.cxx \
@@ -106,6 +107,7 @@ SLOFILES = \
$(SLO)$/xmlexprt.obj \
$(SLO)$/xmlbodyi.obj \
$(SLO)$/xmltabi.obj \
+ $(SLO)$/xmlexternaltabi.obj \
$(SLO)$/xmlrowi.obj \
$(SLO)$/xmlcelli.obj \
$(SLO)$/xmlconti.obj \
diff --git a/sc/source/filter/xml/xmlbodyi.cxx b/sc/source/filter/xml/xmlbodyi.cxx
index 0a8ac2842252..f1e2ccd8ce73 100644
--- a/sc/source/filter/xml/xmlbodyi.cxx
+++ b/sc/source/filter/xml/xmlbodyi.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: xmlbodyi.cxx,v $
- * $Revision: 1.32 $
+ * $Revision: 1.32.28.1 $
*
* This file is part of OpenOffice.org.
*
@@ -64,6 +64,7 @@
using namespace com::sun::star;
using namespace xmloff::token;
+using ::rtl::OUString;
//------------------------------------------------------------------
diff --git a/sc/source/filter/xml/xmlcelli.cxx b/sc/source/filter/xml/xmlcelli.cxx
index d6e88aaed484..7b44a57a926c 100644
--- a/sc/source/filter/xml/xmlcelli.cxx
+++ b/sc/source/filter/xml/xmlcelli.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: xmlcelli.cxx,v $
- * $Revision: 1.96.166.1 $
+ * $Revision: 1.96.134.1 $
*
* This file is part of OpenOffice.org.
*
@@ -146,184 +146,130 @@ ScXMLTableRowCellContext::ScXMLTableRowCellContext( ScXMLImport& rImport,
rtl::OUString aLocalName;
rtl::OUString* pStyleName = NULL;
rtl::OUString* pCurrencySymbol = NULL;
- for( sal_Int16 i=0; i < nAttrCount; ++i )
+ const SvXMLTokenMap& rTokenMap = rImport.GetTableRowCellAttrTokenMap();
+ for (sal_Int16 i = 0; i < nAttrCount; ++i)
{
- sal_uInt16 nPrefix = rXMLImport.GetNamespaceMap().GetKeyByAttrName(
- xAttrList->getNameByIndex( i ), &aLocalName );
- const rtl::OUString& sValue(xAttrList->getValueByIndex( i ));
+ sal_uInt16 nAttrPrefix = rImport.GetNamespaceMap().GetKeyByAttrName(
+ xAttrList->getNameByIndex(i), &aLocalName);
- if (nPrefix == XML_NAMESPACE_TABLE)
+ const rtl::OUString& sValue = xAttrList->getValueByIndex(i);
+ sal_uInt16 nToken = rTokenMap.Get(nAttrPrefix, aLocalName);
+ switch (nToken)
{
- sal_uInt32 nLength(aLocalName.getLength());
-
- switch (nLength)
+ case XML_TOK_TABLE_ROW_CELL_ATTR_STYLE_NAME:
+ pStyleName = new rtl::OUString(sValue);
+ break;
+ case XML_TOK_TABLE_ROW_CELL_ATTR_CONTENT_VALIDATION_NAME:
+ DBG_ASSERT(!pContentValidationName, "here should be only one Validation Name");
+ pContentValidationName = new rtl::OUString(sValue);
+ break;
+ case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_ROWS:
+ bIsMerged = sal_True;
+ nMergedRows = sValue.toInt32();
+ break;
+ case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_COLS:
+ bIsMerged = sal_True;
+ nMergedCols = sValue.toInt32();
+ break;
+ case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_MATRIX_COLS:
+ bIsMatrix = sal_True;
+ nMatrixCols = sValue.toInt32();
+ break;
+ case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_MATRIX_ROWS:
+ bIsMatrix = sal_True;
+ nMatrixRows = sValue.toInt32();
+ break;
+ case XML_TOK_TABLE_ROW_CELL_ATTR_REPEATED:
+ nCellsRepeated = std::max( sValue.toInt32(), (sal_Int32) 1 );
+ break;
+ case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE_TYPE:
+ nCellType = GetScImport().GetCellType(sValue);
+ bIsEmpty = sal_False;
+ break;
+ case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE:
{
- case 7 :
+ if (sValue.getLength())
{
- if (IsXMLToken(aLocalName, XML_FORMULA))
- {
- if (sValue.getLength())
- {
- DBG_ASSERT(!pOUFormula, "here should be only one formula");
- DELETEZ( pOUFormula);
- rtl::OUString sFormula;
- sal_uInt16 nFormulaPrefix = GetImport().GetNamespaceMap().
- _GetKeyByAttrName( sValue, &sFormula, sal_False );
-
- if (ScXMLImport::IsAcceptedFormulaNamespace(
- nFormulaPrefix, sValue, eGrammar,
- eStorageGrammar))
- {
- // Namespaces we accept.
- pOUFormula = new rtl::OUString( sFormula);
- }
- else
- {
- // No namespace => entire string.
- // Also unknown namespace included in formula,
- // so hopefully will result in string or
- // compile error.
- pOUFormula = new rtl::OUString( sValue);
- }
- }
- }
- }
- break;
- case 10 :
- {
- if (IsXMLToken(aLocalName, XML_STYLE_NAME))
- pStyleName = new rtl::OUString(sValue);
- }
- break;
- case 19 :
- {
- if (IsXMLToken(aLocalName, XML_NUMBER_ROWS_SPANNED))
- {
- bIsMerged = sal_True;
- nMergedRows = sValue.toInt32();
- }
- }
- break;
- case 22 :
- {
- if (IsXMLToken(aLocalName, XML_NUMBER_COLUMNS_SPANNED))
- {
- bIsMerged = sal_True;
- nMergedCols = sValue.toInt32();
- }
- }
- break;
- case 23 :
- {
- if (IsXMLToken(aLocalName, XML_NUMBER_COLUMNS_REPEATED))
- nCellsRepeated = std::max( sValue.toInt32(), (sal_Int32) 1 );
- else if (IsXMLToken(aLocalName, XML_CONTENT_VALIDATION_NAME))
- {
- DBG_ASSERT(!pContentValidationName, "here should be only one Validation Name");
- pContentValidationName = new rtl::OUString(sValue);
- }
- }
- break;
- case 26 :
- {
- if (IsXMLToken(aLocalName, XML_NUMBER_MATRIX_ROWS_SPANNED))
- {
- bIsMatrix = sal_True;
- nMatrixRows = sValue.toInt32();
- }
+ rXMLImport.GetMM100UnitConverter().convertDouble(fValue, sValue);
+ bIsEmpty = sal_False;
}
- break;
- case 29 :
+ }
+ break;
+ case XML_TOK_TABLE_ROW_CELL_ATTR_DATE_VALUE:
+ {
+ if (sValue.getLength() && rXMLImport.SetNullDateOnUnitConverter())
{
- if (IsXMLToken(aLocalName, XML_NUMBER_MATRIX_COLUMNS_SPANNED))
- {
- bIsMatrix = sal_True;
- nMatrixCols = sValue.toInt32();
- }
+ rXMLImport.GetMM100UnitConverter().convertDateTime(fValue, sValue);
+ bIsEmpty = sal_False;
}
- break;
}
- }
- else if (nPrefix == XML_NAMESPACE_OFFICE)
- {
- sal_uInt32 nLength(aLocalName.getLength());
-
- switch (nLength)
+ break;
+ case XML_TOK_TABLE_ROW_CELL_ATTR_TIME_VALUE:
{
- case 5 :
+ if (sValue.getLength())
{
- if (IsXMLToken(aLocalName, XML_VALUE))
- {
- if (sValue.getLength())
- {
- rXMLImport.GetMM100UnitConverter().convertDouble(fValue, sValue);
- bIsEmpty = sal_False;
- }
- }
+ rXMLImport.GetMM100UnitConverter().convertTime(fValue, sValue);
+ bIsEmpty = sal_False;
}
- break;
- case 8 :
+ }
+ break;
+ case XML_TOK_TABLE_ROW_CELL_ATTR_STRING_VALUE:
+ {
+ if (sValue.getLength())
{
- if (IsXMLToken(aLocalName, XML_CURRENCY))
- pCurrencySymbol = new rtl::OUString(sValue);
+ DBG_ASSERT(!pOUTextValue, "here should be only one string value");
+ pOUTextValue = new rtl::OUString(sValue);
+ bIsEmpty = sal_False;
}
- break;
- case 10 :
+ }
+ break;
+ case XML_TOK_TABLE_ROW_CELL_ATTR_BOOLEAN_VALUE:
+ {
+ if (sValue.getLength())
{
- if (IsXMLToken(aLocalName, XML_VALUE_TYPE))
- {
- nCellType = GetCellType(sValue);
- bIsEmpty = sal_False;
- }
- else if (IsXMLToken(aLocalName, XML_DATE_VALUE))
- {
- if (sValue.getLength() && rXMLImport.SetNullDateOnUnitConverter())
- {
- rXMLImport.GetMM100UnitConverter().convertDateTime(fValue, sValue);
- bIsEmpty = sal_False;
- }
- }
- else if (IsXMLToken(aLocalName, XML_TIME_VALUE))
- {
- if (sValue.getLength())
- {
- rXMLImport.GetMM100UnitConverter().convertTime(fValue, sValue);
- bIsEmpty = sal_False;
- }
- }
+ if ( IsXMLToken(sValue, XML_TRUE) )
+ fValue = 1.0;
+ else if ( IsXMLToken(sValue, XML_FALSE) )
+ fValue = 0.0;
+ else
+ rXMLImport.GetMM100UnitConverter().convertDouble(fValue, sValue);
+ bIsEmpty = sal_False;
}
- break;
- case 12 :
+ }
+ break;
+ case XML_TOK_TABLE_ROW_CELL_ATTR_FORMULA:
+ {
+ if (sValue.getLength())
{
- if (IsXMLToken(aLocalName, XML_STRING_VALUE))
+ DBG_ASSERT(!pOUFormula, "here should be only one formula");
+ DELETEZ( pOUFormula);
+ rtl::OUString sFormula;
+ sal_uInt16 nFormulaPrefix = GetImport().GetNamespaceMap().
+ _GetKeyByAttrName( sValue, &sFormula, sal_False );
+
+ if (ScXMLImport::IsAcceptedFormulaNamespace(
+ nFormulaPrefix, sValue, eGrammar,
+ eStorageGrammar))
{
- if (sValue.getLength())
- {
- DBG_ASSERT(!pOUTextValue, "here should be only one string value");
- pOUTextValue = new rtl::OUString(sValue);
- bIsEmpty = sal_False;
- }
+ // Namespaces we accept.
+ pOUFormula = new rtl::OUString( sFormula);
}
- }
- break;
- case 13 :
- {
- if (IsXMLToken(aLocalName, XML_BOOLEAN_VALUE))
+ else
{
- if (sValue.getLength())
- {
- if ( IsXMLToken(sValue, XML_TRUE) )
- fValue = 1.0;
- else if ( IsXMLToken(sValue, XML_FALSE) )
- fValue = 0.0;
- else
- rXMLImport.GetMM100UnitConverter().convertDouble(fValue, sValue);
- bIsEmpty = sal_False;
- }
+ // No namespace => entire string.
+ // Also unknown namespace included in formula,
+ // so hopefully will result in string or
+ // compile error.
+ pOUFormula = new rtl::OUString( sValue);
}
}
- break;
}
+ break;
+ case XML_TOK_TABLE_ROW_CELL_ATTR_CURRENCY:
+ pCurrencySymbol = new rtl::OUString(sValue);
+ break;
+ default:
+ ;
}
}
if (pOUFormula)
@@ -335,32 +281,6 @@ ScXMLTableRowCellContext::ScXMLTableRowCellContext( ScXMLImport& rImport,
rXMLImport.GetStylesImportHelper()->SetAttributes(pStyleName, pCurrencySymbol, nCellType);
}
-sal_Int16 ScXMLTableRowCellContext::GetCellType(const rtl::OUString& sOUValue) const
-{
- if (IsXMLToken(sOUValue, XML_FLOAT))
- return util::NumberFormat::NUMBER;
- else
- if (IsXMLToken(sOUValue, XML_STRING))
- return util::NumberFormat::TEXT;
- else
- if (IsXMLToken(sOUValue, XML_TIME))
- return util::NumberFormat::TIME;
- else
- if (IsXMLToken(sOUValue, XML_DATE))
- return util::NumberFormat::DATETIME;
- else
- if (IsXMLToken(sOUValue, XML_PERCENTAGE))
- return util::NumberFormat::PERCENT;
- else
- if (IsXMLToken(sOUValue, XML_CURRENCY))
- return util::NumberFormat::CURRENCY;
- else
- if (IsXMLToken(sOUValue, XML_BOOLEAN))
- return util::NumberFormat::LOGICAL;
- else
- return util::NumberFormat::UNDEFINED;
-}
-
ScXMLTableRowCellContext::~ScXMLTableRowCellContext()
{
if (pOUTextValue)
diff --git a/sc/source/filter/xml/xmlcelli.hxx b/sc/source/filter/xml/xmlcelli.hxx
index 9bfac2d2fa00..7f31fe46a127 100644
--- a/sc/source/filter/xml/xmlcelli.hxx
+++ b/sc/source/filter/xml/xmlcelli.hxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: xmlcelli.hxx,v $
- * $Revision: 1.26 $
+ * $Revision: 1.26.134.1 $
*
* This file is part of OpenOffice.org.
*
@@ -95,8 +95,6 @@ class ScXMLTableRowCellContext : public SvXMLImportContext
const ScXMLImport& GetScImport() const { return (const ScXMLImport&)GetImport(); }
ScXMLImport& GetScImport() { return (ScXMLImport&)GetImport(); }
- sal_Int16 GetCellType(const rtl::OUString& sOUValue) const;
-
sal_Bool IsMerged (const com::sun::star::uno::Reference <com::sun::star::table::XCellRange>& xCellRange,
const sal_Int32 nCol, const sal_Int32 nRow,
com::sun::star::table::CellRangeAddress& aCellAddress) const;
diff --git a/sc/source/filter/xml/xmldpimp.cxx b/sc/source/filter/xml/xmldpimp.cxx
index 53b57cd57611..7c6403d27765 100644
--- a/sc/source/filter/xml/xmldpimp.cxx
+++ b/sc/source/filter/xml/xmldpimp.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: xmldpimp.cxx,v $
- * $Revision: 1.27 $
+ * $Revision: 1.27.134.1 $
*
* This file is part of OpenOffice.org.
*
@@ -65,6 +65,7 @@
using namespace com::sun::star;
using namespace xmloff::token;
+using ::rtl::OUString;
//------------------------------------------------------------------
diff --git a/sc/source/filter/xml/xmlexprt.cxx b/sc/source/filter/xml/xmlexprt.cxx
index af28486efb97..cf2762b4346c 100644
--- a/sc/source/filter/xml/xmlexprt.cxx
+++ b/sc/source/filter/xml/xmlexprt.cxx
@@ -67,6 +67,7 @@
#include "rangeutl.hxx"
#include "convuno.hxx"
#include "postit.hxx"
+#include "externalrefmgr.hxx"
#include <xmloff/xmltoken.hxx>
#include <xmloff/xmlnmspe.hxx>
@@ -128,6 +129,8 @@
#include <sfx2/objsh.hxx>
+#include <vector>
+
//! not found in unonames.hxx
#define SC_STANDARDFORMAT "StandardFormat"
#define SC_LAYERID "LayerID"
@@ -151,6 +154,7 @@
using namespace rtl;
using namespace com::sun::star;
using namespace xmloff::token;
+using ::std::vector;
//----------------------------------------------------------------------------
@@ -478,6 +482,12 @@ ScXMLExport::ScXMLExport(
if( (getExportFlags() & (EXPORT_STYLES|EXPORT_AUTOSTYLES|EXPORT_MASTERSTYLES|EXPORT_CONTENT) ) != 0 )
{
+ // This name is reserved for the external ref cache tables. This
+ // should not conflict with user-defined styles since this name is
+ // used for a table style which is not available in the UI.
+ sExternalRefTabStyleName = rtl::OUString::createFromAscii("ta_extref");
+ GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TABLE_TABLE, sExternalRefTabStyleName);
+
sAttrName = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_NAME));
sAttrStyleName = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_STYLE_NAME));
sAttrColumnsRepeated = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_NUMBER_COLUMNS_REPEATED));
@@ -524,6 +534,15 @@ ScXMLExport::~ScXMLExport()
delete pNumberFormatAttributesExportHelper;
}
+sal_Int32 ScXMLExport::GetNumberFormatStyleIndex(sal_Int32 nNumFmt) const
+{
+ NumberFormatIndexMap::const_iterator itr = aNumFmtIndexMap.find(nNumFmt);
+ if (itr == aNumFmtIndexMap.end())
+ return -1;
+
+ return itr->second;
+}
+
sal_Bool ScXMLExport::HasDrawPages(uno::Reference <sheet::XSpreadsheetDocument>& xDoc)
{
uno::Reference <beans::XPropertySet> xDocProps( xDoc, uno::UNO_QUERY );
@@ -1018,6 +1037,58 @@ void ScXMLExport::ExportColumns(const sal_Int32 nTable, const table::CellRangeAd
pGroupColumns->CloseGroups(nColumn - 1);
}
+void ScXMLExport::ExportExternalRefCacheStyles()
+{
+ sal_Int32 nEntryIndex = GetCellStylesPropertySetMapper()->FindEntryIndex(
+ "NumberFormat", XML_NAMESPACE_STYLE, OUString::createFromAscii("data-style-name"));
+
+ if (nEntryIndex < 0)
+ // No entry index for the number format is found.
+ return;
+
+ ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
+ if (!pRefMgr->hasExternalData())
+ // No external reference data cached.
+ return;
+
+ // Export each unique number format used in the external ref cache.
+ vector<sal_uInt32> aNumFmts;
+ pRefMgr->getAllCachedNumberFormats(aNumFmts);
+ const OUString aDefaultStyle = OUString::createFromAscii("Default").intern();
+ for (vector<sal_uInt32>::const_iterator itr = aNumFmts.begin(), itrEnd = aNumFmts.end();
+ itr != itrEnd; ++itr)
+ {
+ sal_Int32 nNumFmt = static_cast<sal_Int32>(*itr);
+
+ addDataStyle(nNumFmt);
+
+ uno::Any aVal;
+ aVal <<= nNumFmt;
+ vector<XMLPropertyState> aProps;
+ aProps.push_back(XMLPropertyState(nEntryIndex, aVal));
+ aVal <<= aDefaultStyle;
+ aProps.push_back(XMLPropertyState(nEntryIndex, aVal));
+
+ OUString aName;
+ sal_Int32 nIndex;
+ if (GetAutoStylePool()->Add(aName, XML_STYLE_FAMILY_TABLE_CELL, aDefaultStyle, aProps))
+ {
+ OUString* pTemp(new OUString(aName));
+ if (!pCellStyles->AddStyleName(pTemp, nIndex, true))
+ delete pTemp;
+ }
+ else
+ {
+ sal_Bool bIsAuto;
+ nIndex = pCellStyles->GetIndexOfStyleName(
+ aName, OUString::createFromAscii(XML_STYLE_FAMILY_TABLE_CELL_STYLES_PREFIX), bIsAuto);
+ }
+
+ // store the number format to index mapping for later use.
+ aNumFmtIndexMap.insert(NumberFormatIndexMap::value_type(nNumFmt, nIndex));
+ }
+}
+
void ScXMLExport::WriteRowContent()
{
ScMyRowFormatRange aRange;
@@ -1417,176 +1488,177 @@ void ScXMLExport::_ExportContent()
DBG_ERROR("no shared data setted");
}
ScXMLExportDatabaseRanges aExportDatabaseRanges(*this);
- if (GetModel().is())
- {
- uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( GetModel(), uno::UNO_QUERY );
- if ( xSpreadDoc.is() )
- {
- uno::Reference<container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY );
- if ( xIndex.is() )
+ if (!GetModel().is())
+ return;
+
+ uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( GetModel(), uno::UNO_QUERY );
+ if ( !xSpreadDoc.is() )
+ return;
+
+ uno::Reference<container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY );
+ if ( xIndex.is() )
+ {
+ //_GetNamespaceMap().ClearQNamesCache();
+ pChangeTrackingExportHelper->CollectAndWriteChanges();
+ WriteCalculationSettings(xSpreadDoc);
+ sal_Int32 nTableCount(xIndex->getCount());
+ ScMyAreaLinksContainer aAreaLinks;
+ GetAreaLinks( xSpreadDoc, aAreaLinks );
+ ScMyEmptyDatabaseRangesContainer aEmptyRanges(aExportDatabaseRanges.GetEmptyDatabaseRanges());
+ ScMyDetectiveOpContainer aDetectiveOpContainer;
+ GetDetectiveOpList( aDetectiveOpContainer );
+
+ pCellStyles->Sort();
+ pMergedRangesContainer->Sort();
+ pSharedData->GetDetectiveObjContainer()->Sort();
+
+ pCellsItr->Clear();
+ pCellsItr->SetShapes( pSharedData->GetShapesContainer() );
+ pCellsItr->SetNoteShapes( pSharedData->GetNoteShapes() );
+ pCellsItr->SetMergedRanges( pMergedRangesContainer );
+ pCellsItr->SetAreaLinks( &aAreaLinks );
+ pCellsItr->SetEmptyDatabaseRanges( &aEmptyRanges );
+ pCellsItr->SetDetectiveObj( pSharedData->GetDetectiveObjContainer() );
+ pCellsItr->SetDetectiveOp( &aDetectiveOpContainer );
+
+ if (nTableCount > 0)
+ pValidationsContainer->WriteValidations(*this);
+ WriteTheLabelRanges( xSpreadDoc );
+ for (sal_Int32 nTable = 0; nTable < nTableCount; ++nTable)
+ {
+ uno::Reference<sheet::XSpreadsheet> xTable(xIndex->getByIndex(nTable), uno::UNO_QUERY);
+ if (xTable.is())
{
- //_GetNamespaceMap().ClearQNamesCache();
- pChangeTrackingExportHelper->CollectAndWriteChanges();
- WriteCalculationSettings(xSpreadDoc);
- sal_Int32 nTableCount(xIndex->getCount());
- ScMyAreaLinksContainer aAreaLinks;
- GetAreaLinks( xSpreadDoc, aAreaLinks );
- ScMyEmptyDatabaseRangesContainer aEmptyRanges(aExportDatabaseRanges.GetEmptyDatabaseRanges());
- ScMyDetectiveOpContainer aDetectiveOpContainer;
- GetDetectiveOpList( aDetectiveOpContainer );
-
- pCellStyles->Sort();
- pMergedRangesContainer->Sort();
- pSharedData->GetDetectiveObjContainer()->Sort();
-
- pCellsItr->Clear();
- pCellsItr->SetShapes( pSharedData->GetShapesContainer() );
- pCellsItr->SetNoteShapes( pSharedData->GetNoteShapes() );
- pCellsItr->SetMergedRanges( pMergedRangesContainer );
- pCellsItr->SetAreaLinks( &aAreaLinks );
- pCellsItr->SetEmptyDatabaseRanges( &aEmptyRanges );
- pCellsItr->SetDetectiveObj( pSharedData->GetDetectiveObjContainer() );
- pCellsItr->SetDetectiveOp( &aDetectiveOpContainer );
-
- if (nTableCount > 0)
- pValidationsContainer->WriteValidations(*this);
- WriteTheLabelRanges( xSpreadDoc );
- for (sal_Int32 nTable = 0; nTable < nTableCount; ++nTable)
+ xCurrentTable.set(xTable);
+ xCurrentTableCellRange.set(xTable, uno::UNO_QUERY);
+ uno::Reference<container::XNamed> xName (xTable, uno::UNO_QUERY );
+ if ( xName.is() )
{
- uno::Reference<sheet::XSpreadsheet> xTable(xIndex->getByIndex(nTable), uno::UNO_QUERY);
- if (xTable.is())
+ nCurrentTable = sal::static_int_cast<sal_uInt16>( nTable );
+ rtl::OUString sOUTableName(xName->getName());
+ AddAttribute(sAttrName, sOUTableName);
+ AddAttribute(sAttrStyleName, aTableStyles[nTable]);
+ uno::Reference<util::XProtectable> xProtectable (xTable, uno::UNO_QUERY);
+ if (xProtectable.is() && xProtectable->isProtected())
+ {
+ AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTED, XML_TRUE);
+ rtl::OUStringBuffer aBuffer;
+ if (pDoc)
+ SvXMLUnitConverter::encodeBase64(aBuffer, pDoc->GetTabPassword(static_cast<SCTAB>(nTable)));
+ if (aBuffer.getLength())
+ AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY, aBuffer.makeStringAndClear());
+ }
+ rtl::OUString sPrintRanges;
+ table::CellRangeAddress aColumnHeaderRange;
+ sal_Bool bHasColumnHeader;
+ GetColumnRowHeader(bHasColumnHeader, aColumnHeaderRange, bHasRowHeader, aRowHeaderRange, sPrintRanges);
+ if( sPrintRanges.getLength() )
+ AddAttribute( XML_NAMESPACE_TABLE, XML_PRINT_RANGES, sPrintRanges );
+ else if (!pDoc->IsPrintEntireSheet(static_cast<SCTAB>(nTable)))
+ AddAttribute( XML_NAMESPACE_TABLE, XML_PRINT, XML_FALSE);
+ SvXMLElementExport aElemT(*this, sElemTab, sal_True, sal_True);
+ CheckAttrList();
+ WriteTableSource();
+ WriteScenario();
+ uno::Reference<drawing::XDrawPage> xDrawPage;
+ if (pSharedData->HasForm(nTable, xDrawPage) && xDrawPage.is())
{
- xCurrentTable.set(xTable);
- xCurrentTableCellRange.set(xTable, uno::UNO_QUERY);
- uno::Reference<container::XNamed> xName (xTable, uno::UNO_QUERY );
- if ( xName.is() )
+ ::xmloff::OOfficeFormsExport aForms(*this);
+ GetFormExport()->exportForms( xDrawPage );
+ sal_Bool bRet(GetFormExport()->seekPage( xDrawPage ));
+ DBG_ASSERT( bRet, "OFormLayerXMLExport::seekPage failed!" );
+ (void)bRet; // avoid warning in product version
+ }
+ if (pSharedData->HasDrawPage())
+ {
+ GetShapeExport()->seekShapes(uno::Reference<drawing::XShapes>(pSharedData->GetDrawPage(nTable), uno::UNO_QUERY));
+ WriteTableShapes();
+ }
+ table::CellRangeAddress aRange(GetEndAddress(xTable, nTable));
+ pSharedData->SetLastColumn(nTable, aRange.EndColumn);
+ pSharedData->SetLastRow(nTable, aRange.EndRow);
+ pCellsItr->SetCurrentTable(static_cast<SCTAB>(nTable), xCurrentTable);
+ pGroupColumns->NewTable();
+ pGroupRows->NewTable();
+ FillColumnRowGroups();
+ if (bHasColumnHeader)
+ pSharedData->SetLastColumn(nTable, aColumnHeaderRange.EndColumn);
+ bRowHeaderOpen = sal_False;
+ if (bHasRowHeader)
+ pSharedData->SetLastRow(nTable, aRowHeaderRange.EndRow);
+ pDefaults->FillDefaultStyles(nTable, pSharedData->GetLastRow(nTable),
+ pSharedData->GetLastColumn(nTable), pCellStyles, pDoc);
+ pRowFormatRanges->SetRowDefaults(pDefaults->GetRowDefaults());
+ pRowFormatRanges->SetColDefaults(pDefaults->GetColDefaults());
+ pCellStyles->SetRowDefaults(pDefaults->GetRowDefaults());
+ pCellStyles->SetColDefaults(pDefaults->GetColDefaults());
+ ExportColumns(nTable, aColumnHeaderRange, bHasColumnHeader);
+ sal_Bool bIsFirst(sal_True);
+ sal_Int32 nEqualCells(0);
+ ScMyCell aCell;
+ ScMyCell aPrevCell;
+ while(pCellsItr->GetNext(aCell, pCellStyles))
+ {
+ if (bIsFirst)
{
- nCurrentTable = sal::static_int_cast<sal_uInt16>( nTable );
- rtl::OUString sOUTableName(xName->getName());
- AddAttribute(sAttrName, sOUTableName);
- AddAttribute(sAttrStyleName, aTableStyles[nTable]);
- uno::Reference<util::XProtectable> xProtectable (xTable, uno::UNO_QUERY);
- if (xProtectable.is() && xProtectable->isProtected())
- {
- AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTED, XML_TRUE);
- rtl::OUStringBuffer aBuffer;
- if (pDoc)
- SvXMLUnitConverter::encodeBase64(aBuffer, pDoc->GetTabPassword(static_cast<SCTAB>(nTable)));
- if (aBuffer.getLength())
- AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY, aBuffer.makeStringAndClear());
- }
- rtl::OUString sPrintRanges;
- table::CellRangeAddress aColumnHeaderRange;
- sal_Bool bHasColumnHeader;
- GetColumnRowHeader(bHasColumnHeader, aColumnHeaderRange, bHasRowHeader, aRowHeaderRange, sPrintRanges);
- if( sPrintRanges.getLength() )
- AddAttribute( XML_NAMESPACE_TABLE, XML_PRINT_RANGES, sPrintRanges );
- else if (!pDoc->IsPrintEntireSheet(static_cast<SCTAB>(nTable)))
- AddAttribute( XML_NAMESPACE_TABLE, XML_PRINT, XML_FALSE);
- SvXMLElementExport aElemT(*this, sElemTab, sal_True, sal_True);
- CheckAttrList();
- WriteTableSource();
- WriteScenario();
- uno::Reference<drawing::XDrawPage> xDrawPage;
- if (pSharedData->HasForm(nTable, xDrawPage) && xDrawPage.is())
- {
- ::xmloff::OOfficeFormsExport aForms(*this);
- GetFormExport()->exportForms( xDrawPage );
- sal_Bool bRet(GetFormExport()->seekPage( xDrawPage ));
- DBG_ASSERT( bRet, "OFormLayerXMLExport::seekPage failed!" );
- (void)bRet; // avoid warning in product version
- }
- if (pSharedData->HasDrawPage())
- {
- GetShapeExport()->seekShapes(uno::Reference<drawing::XShapes>(pSharedData->GetDrawPage(nTable), uno::UNO_QUERY));
- WriteTableShapes();
- }
- table::CellRangeAddress aRange(GetEndAddress(xTable, nTable));
- pSharedData->SetLastColumn(nTable, aRange.EndColumn);
- pSharedData->SetLastRow(nTable, aRange.EndRow);
- pCellsItr->SetCurrentTable(static_cast<SCTAB>(nTable), xCurrentTable);
- pGroupColumns->NewTable();
- pGroupRows->NewTable();
- FillColumnRowGroups();
- if (bHasColumnHeader)
- pSharedData->SetLastColumn(nTable, aColumnHeaderRange.EndColumn);
- bRowHeaderOpen = sal_False;
- if (bHasRowHeader)
- pSharedData->SetLastRow(nTable, aRowHeaderRange.EndRow);
- pDefaults->FillDefaultStyles(nTable, pSharedData->GetLastRow(nTable),
- pSharedData->GetLastColumn(nTable), pCellStyles, pDoc);
- pRowFormatRanges->SetRowDefaults(pDefaults->GetRowDefaults());
- pRowFormatRanges->SetColDefaults(pDefaults->GetColDefaults());
- pCellStyles->SetRowDefaults(pDefaults->GetRowDefaults());
- pCellStyles->SetColDefaults(pDefaults->GetColDefaults());
- ExportColumns(nTable, aColumnHeaderRange, bHasColumnHeader);
- sal_Bool bIsFirst(sal_True);
- sal_Int32 nEqualCells(0);
- ScMyCell aCell;
- ScMyCell aPrevCell;
- while(pCellsItr->GetNext(aCell, pCellStyles))
+ ExportFormatRanges(0, 0, aCell.aCellAddress.Column - 1, aCell.aCellAddress.Row, nTable);
+ aPrevCell = aCell;
+ bIsFirst = sal_False;
+ }
+ else
+ {
+ if ((aPrevCell.aCellAddress.Row == aCell.aCellAddress.Row) &&
+ (aPrevCell.aCellAddress.Column + nEqualCells + 1 == aCell.aCellAddress.Column))
{
- if (bIsFirst)
- {
- ExportFormatRanges(0, 0, aCell.aCellAddress.Column - 1, aCell.aCellAddress.Row, nTable);
- aPrevCell = aCell;
- bIsFirst = sal_False;
- }
+ if(IsCellEqual(aPrevCell, aCell))
+ ++nEqualCells;
else
{
- if ((aPrevCell.aCellAddress.Row == aCell.aCellAddress.Row) &&
- (aPrevCell.aCellAddress.Column + nEqualCells + 1 == aCell.aCellAddress.Column))
- {
- if(IsCellEqual(aPrevCell, aCell))
- ++nEqualCells;
- else
- {
- SetRepeatAttribute(nEqualCells);
- WriteCell(aPrevCell);
- nEqualCells = 0;
- aPrevCell = aCell;
- }
- }
- else
- {
- SetRepeatAttribute(nEqualCells);
- WriteCell(aPrevCell);
- ExportFormatRanges(aPrevCell.aCellAddress.Column + nEqualCells + 1, aPrevCell.aCellAddress.Row,
- aCell.aCellAddress.Column - 1, aCell.aCellAddress.Row, nTable);
- nEqualCells = 0;
- aPrevCell = aCell;
- }
+ SetRepeatAttribute(nEqualCells);
+ WriteCell(aPrevCell);
+ nEqualCells = 0;
+ aPrevCell = aCell;
}
}
- if (!bIsFirst)
+ else
{
SetRepeatAttribute(nEqualCells);
WriteCell(aPrevCell);
ExportFormatRanges(aPrevCell.aCellAddress.Column + nEqualCells + 1, aPrevCell.aCellAddress.Row,
- pSharedData->GetLastColumn(nTable), pSharedData->GetLastRow(nTable), nTable);
+ aCell.aCellAddress.Column - 1, aCell.aCellAddress.Row, nTable);
+ nEqualCells = 0;
+ aPrevCell = aCell;
}
- else
- ExportFormatRanges(0, 0, pSharedData->GetLastColumn(nTable), pSharedData->GetLastRow(nTable), nTable);
- CloseRow(pSharedData->GetLastRow(nTable));
- nEqualCells = 0;
}
}
- RemoveTempAnnotaionShape(nTable);
-
- IncrementProgressBar(sal_False);
+ if (!bIsFirst)
+ {
+ SetRepeatAttribute(nEqualCells);
+ WriteCell(aPrevCell);
+ ExportFormatRanges(aPrevCell.aCellAddress.Column + nEqualCells + 1, aPrevCell.aCellAddress.Row,
+ pSharedData->GetLastColumn(nTable), pSharedData->GetLastRow(nTable), nTable);
+ }
+ else
+ ExportFormatRanges(0, 0, pSharedData->GetLastColumn(nTable), pSharedData->GetLastRow(nTable), nTable);
+ CloseRow(pSharedData->GetLastRow(nTable));
+ nEqualCells = 0;
}
}
- WriteNamedExpressions(xSpreadDoc);
- aExportDatabaseRanges.WriteDatabaseRanges(xSpreadDoc);
- ScXMLExportDataPilot aExportDataPilot(*this);
- aExportDataPilot.WriteDataPilots(xSpreadDoc);
- WriteConsolidation();
- ScXMLExportDDELinks aExportDDELinks(*this);
- aExportDDELinks.WriteDDELinks(xSpreadDoc);
- IncrementProgressBar(sal_True, 0);
- GetProgressBarHelper()->SetValue(GetProgressBarHelper()->GetReference());
+ RemoveTempAnnotaionShape(nTable);
+
+ IncrementProgressBar(sal_False);
}
}
+ WriteExternalRefCaches();
+ WriteNamedExpressions(xSpreadDoc);
+ aExportDatabaseRanges.WriteDatabaseRanges(xSpreadDoc);
+ ScXMLExportDataPilot aExportDataPilot(*this);
+ aExportDataPilot.WriteDataPilots(xSpreadDoc);
+ WriteConsolidation();
+ ScXMLExportDDELinks aExportDDELinks(*this);
+ aExportDDELinks.WriteDDELinks(xSpreadDoc);
+ IncrementProgressBar(sal_True, 0);
+ GetProgressBarHelper()->SetValue(GetProgressBarHelper()->GetReference());
}
void ScXMLExport::_ExportStyles( sal_Bool bUsed )
@@ -1662,6 +1734,8 @@ void ScXMLExport::_ExportAutoStyles()
{
if (getExportFlags() & EXPORT_CONTENT)
{
+ ExportExternalRefCacheStyles();
+
if (!pSharedData)
{
sal_Int32 nTableCount(0);
@@ -1991,6 +2065,15 @@ void ScXMLExport::_ExportAutoStyles()
GetShapeExport()->exportAutoStyles();
GetFormExport()->exportAutoStyles( );
+
+ {
+ // Special table style for the external ref cache tables.
+ AddAttribute(XML_NAMESPACE_STYLE, XML_NAME, sExternalRefTabStyleName);
+ AddAttribute(XML_NAMESPACE_STYLE, XML_FAMILY, XML_TABLE);
+ SvXMLElementExport aElemStyle(*this, XML_NAMESPACE_STYLE, XML_STYLE, sal_True, sal_True);
+ AddAttribute(XML_NAMESPACE_TABLE, XML_DISPLAY, XML_FALSE);
+ SvXMLElementExport aElemStyleTabProps(*this, XML_NAMESPACE_STYLE, XML_TABLE_PROPERTIES, sal_True, sal_True);
+ }
}
if (getExportFlags() & EXPORT_MASTERSTYLES)
{
@@ -3280,6 +3363,209 @@ void ScXMLExport::WriteNamedExpressions(const com::sun::star::uno::Reference <co
}
}
+void ScXMLExport::WriteExternalRefCaches()
+{
+ if (!pDoc)
+ return;
+
+ ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
+ pRefMgr->resetSrcFileData();
+ sal_uInt16 nCount = pRefMgr->getExternalFileCount();
+ for (sal_uInt16 nFileId = 0; nFileId < nCount; ++nFileId)
+ {
+ const String* pUrl = pRefMgr->getExternalFileName(nFileId);
+ if (!pUrl)
+ continue;
+
+ vector<String> aTabNames;
+ pRefMgr->getAllCachedTableNames(nFileId, aTabNames);
+ if (aTabNames.empty())
+ continue;
+
+ for (vector<String>::const_iterator itr = aTabNames.begin(), itrEnd = aTabNames.end();
+ itr != itrEnd; ++itr)
+ {
+ ScExternalRefCache::TableTypeRef pTable = pRefMgr->getCacheTable(nFileId, *itr, false);
+ if (!pTable.get())
+ continue;
+
+ OUStringBuffer aBuf;
+ aBuf.append(sal_Unicode('\''));
+ aBuf.append(*pUrl);
+ aBuf.append(sal_Unicode('\''));
+ aBuf.append(sal_Unicode('#'));
+ aBuf.append(*itr);
+ AddAttribute(XML_NAMESPACE_TABLE, XML_NAME, aBuf.makeStringAndClear());
+ AddAttribute(XML_NAMESPACE_TABLE, XML_PRINT, GetXMLToken(XML_FALSE));
+ AddAttribute(XML_NAMESPACE_TABLE, XML_STYLE_NAME, sExternalRefTabStyleName);
+ SvXMLElementExport aElemTable(*this, XML_NAMESPACE_TABLE, XML_TABLE, sal_True, sal_True);
+ {
+ const ScExternalRefManager::SrcFileData* pExtFileData = pRefMgr->getExternalFileData(nFileId);
+ if (pExtFileData)
+ {
+ String aRelUrl;
+ if (pExtFileData->maRelativeName.Len())
+ aRelUrl = pExtFileData->maRelativeName;
+ else
+ aRelUrl = GetRelativeReference(pExtFileData->maRelativeName);
+ AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, aRelUrl);
+ AddAttribute(XML_NAMESPACE_TABLE, XML_TABLE_NAME, *itr);
+ if (pExtFileData->maFilterName.Len())
+ AddAttribute(XML_NAMESPACE_TABLE, XML_FILTER_NAME, pExtFileData->maFilterName);
+ if (pExtFileData->maFilterOptions.Len())
+ AddAttribute(XML_NAMESPACE_TABLE, XML_FILTER_OPTIONS, pExtFileData->maFilterOptions);
+ AddAttribute(XML_NAMESPACE_TABLE, XML_MODE, XML_COPY_RESULTS_ONLY);
+ }
+ SvXMLElementExport aElemTableSource(*this, XML_NAMESPACE_TABLE, XML_TABLE_SOURCE, sal_True, sal_True);
+ }
+
+ // Determine maximum column count of used area, for repeated cells.
+ SCCOL nMaxColsUsed = 1; // assume that there is at least one cell somewhere..
+ vector<SCROW> aRows;
+ pTable->getAllRows(aRows);
+ for (vector<SCROW>::const_iterator itrRow = aRows.begin(), itrRowEnd = aRows.end();
+ itrRow != itrRowEnd; ++itrRow)
+ {
+ SCROW nRow = *itrRow;
+ vector<SCCOL> aCols;
+ pTable->getAllCols(nRow, aCols);
+ for (vector<SCCOL>::const_iterator itrCol = aCols.begin(), itrColEnd = aCols.end();
+ itrCol != itrColEnd; ++itrCol)
+ {
+ SCCOL nCol = *itrCol;
+ if (nMaxColsUsed <= nCol)
+ nMaxColsUsed = nCol + 1;
+ }
+ }
+
+ // Write cache content for this table.
+ SCROW nLastRow = 0;
+ bool bFirstRow = true;
+ for (vector<SCROW>::const_iterator itrRow = aRows.begin(), itrRowEnd = aRows.end();
+ itrRow != itrRowEnd; ++itrRow)
+ {
+ SCROW nRow = *itrRow;
+ if (bFirstRow)
+ {
+ if (nRow > 0)
+ {
+ if (nRow > 1)
+ {
+ OUStringBuffer aVal;
+ aVal.append(nRow);
+ AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_REPEATED, aVal.makeStringAndClear());
+ }
+ SvXMLElementExport aElemRow(*this, XML_NAMESPACE_TABLE, XML_TABLE_ROW, sal_True, sal_True);
+ OUStringBuffer aVal;
+ aVal.append(static_cast<sal_Int32>(nMaxColsUsed));
+ AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED, aVal.makeStringAndClear());
+ SvXMLElementExport aElemCell(*this, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True);
+ }
+ }
+ else
+ {
+ SCROW nRowGap = nRow - nLastRow;
+ if (nRowGap > 1)
+ {
+ if (nRowGap > 2)
+ {
+ OUStringBuffer aVal;
+ aVal.append(static_cast<sal_Int32>(nRowGap-1));
+ AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_REPEATED, aVal.makeStringAndClear());
+ }
+ SvXMLElementExport aElemRow(*this, XML_NAMESPACE_TABLE, XML_TABLE_ROW, sal_True, sal_True);
+ OUStringBuffer aVal;
+ aVal.append(static_cast<sal_Int32>(nMaxColsUsed));
+ AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED, aVal.makeStringAndClear());
+ SvXMLElementExport aElemCell(*this, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True);
+ }
+ }
+ SvXMLElementExport aElemRow(*this, XML_NAMESPACE_TABLE, XML_TABLE_ROW, sal_True, sal_True);
+
+ vector<SCCOL> aCols;
+ pTable->getAllCols(nRow, aCols);
+ SCCOL nLastCol = 0;
+ bool bFirstCol = true;
+ for (vector<SCCOL>::const_iterator itrCol = aCols.begin(), itrColEnd = aCols.end();
+ itrCol != itrColEnd; ++itrCol)
+ {
+ SCCOL nCol = *itrCol;
+ if (bFirstCol)
+ {
+ if (nCol > 0)
+ {
+ if (nCol > 1)
+ {
+ OUStringBuffer aVal;
+ aVal.append(static_cast<sal_Int32>(nCol));
+ AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED, aVal.makeStringAndClear());
+ }
+ SvXMLElementExport aElemCell(*this, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True);
+ }
+ }
+ else
+ {
+ SCCOL nColGap = nCol - nLastCol;
+ if (nColGap > 1)
+ {
+ if (nColGap > 2)
+ {
+ OUStringBuffer aVal;
+ aVal.append(static_cast<sal_Int32>(nColGap-1));
+ AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED, aVal.makeStringAndClear());
+ }
+ SvXMLElementExport aElemCell(*this, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True);
+ }
+ }
+
+ // Write out this cell.
+ sal_uInt32 nNumFmt = 0;
+ ScExternalRefCache::TokenRef pToken = pTable->getCell(nCol, nRow, &nNumFmt);
+ OUString aStrVal;
+ if (pToken.get())
+ {
+ sal_Int32 nIndex = GetNumberFormatStyleIndex(nNumFmt);
+ if (nIndex >= 0)
+ {
+ const OUString aStyleName = *pCellStyles->GetStyleNameByIndex(nIndex, true);
+ AddAttribute(XML_NAMESPACE_TABLE, XML_STYLE_NAME, aStyleName);
+ }
+
+ switch(pToken->GetType())
+ {
+ case svDouble:
+ {
+ AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT);
+ OUStringBuffer aVal;
+ aVal.append(pToken->GetDouble());
+ aStrVal = aVal.makeStringAndClear();
+ AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE, aStrVal);
+ }
+ break;
+ case svString:
+ {
+ AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_STRING);
+ aStrVal = pToken->GetString();
+ }
+ break;
+ default:
+ ;
+ }
+ }
+ SvXMLElementExport aElemCell(*this, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True);
+ SvXMLElementExport aElemText(*this, XML_NAMESPACE_TEXT, XML_P, sal_True, sal_False);
+ Characters(aStrVal);
+
+ nLastCol = nCol;
+ bFirstCol = false;
+ }
+ nLastRow = nRow;
+ bFirstRow = false;
+ }
+ }
+ }
+}
+
// core implementation
void ScXMLExport::WriteConsolidation()
{
diff --git a/sc/source/filter/xml/xmlexprt.hxx b/sc/source/filter/xml/xmlexprt.hxx
index 4d452c3f1c0e..1d8e45dc48b6 100644
--- a/sc/source/filter/xml/xmlexprt.hxx
+++ b/sc/source/filter/xml/xmlexprt.hxx
@@ -38,6 +38,8 @@
#include <com/sun/star/drawing/XShapes.hpp>
#include <com/sun/star/table/XCellRange.hpp>
+#include <hash_map>
+
class ScOutlineArray;
class SvXMLExportPropertyMapper;
class ScMyShapesContainer;
@@ -79,6 +81,8 @@ class ScXMLExport : public SvXMLExport
UniReference < SvXMLExportPropertyMapper > xRowStylesExportPropertySetMapper;
UniReference < SvXMLExportPropertyMapper > xTableStylesExportPropertySetMapper;
XMLNumberFormatAttributesExportHelper* pNumberFormatAttributesExportHelper;
+ typedef ::std::hash_map<sal_Int32, sal_Int32> NumberFormatIndexMap;
+ NumberFormatIndexMap aNumFmtIndexMap;
ScMySharedData* pSharedData;
ScColumnStyles* pColumnStyles;
ScRowStyles* pRowStyles;
@@ -98,6 +102,7 @@ class ScXMLExport : public SvXMLExport
ScChangeTrackingExportHelper* pChangeTrackingExportHelper;
const rtl::OUString sLayerID;
const rtl::OUString sCaptionShape;
+ rtl::OUString sExternalRefTabStyleName;
rtl::OUString sAttrName;
rtl::OUString sAttrStyleName;
rtl::OUString sAttrColumnsRepeated;
@@ -117,7 +122,7 @@ class ScXMLExport : public SvXMLExport
sal_Bool bRowHeaderOpen;
sal_Bool mbShowProgress;
-
+ sal_Int32 GetNumberFormatStyleIndex(sal_Int32 nNumFmt) const;
sal_Bool HasDrawPages(com::sun::star::uno::Reference <com::sun::star::sheet::XSpreadsheetDocument>& xDoc);
void CollectSharedData(sal_Int32& nTableCount, sal_Int32& nShapesCount, const sal_Int32 nCellCount);
void CollectShapesAutoStyles(const sal_Int32 nTableCount);
@@ -145,6 +150,7 @@ class ScXMLExport : public SvXMLExport
void OpenHeaderColumn();
void CloseHeaderColumn();
void ExportColumns(const sal_Int32 nTable, const com::sun::star::table::CellRangeAddress& aColumnHeaderRange, const sal_Bool bHasColumnHeader);
+ void ExportExternalRefCacheStyles();
void ExportFormatRanges(const sal_Int32 nStartCol, const sal_Int32 nStartRow,
const sal_Int32 nEndCol, const sal_Int32 nEndRow, const sal_Int32 nSheet);
void WriteRowContent();
@@ -195,6 +201,7 @@ class ScXMLExport : public SvXMLExport
void WriteTheLabelRanges(const com::sun::star::uno::Reference< com::sun::star::sheet::XSpreadsheetDocument >& xSpreadDoc);
void WriteLabelRanges( const com::sun::star::uno::Reference< com::sun::star::container::XIndexAccess >& xRangesIAccess, sal_Bool bColumn );
void WriteNamedExpressions(const com::sun::star::uno::Reference <com::sun::star::sheet::XSpreadsheetDocument>& xSpreadDoc);
+ void WriteExternalRefCaches();
void WriteConsolidation(); // core implementation
void CollectUserDefinedNamespaces(const SfxItemPool* pPool, sal_uInt16 nAttrib);
diff --git a/sc/source/filter/xml/xmlexternaltabi.cxx b/sc/source/filter/xml/xmlexternaltabi.cxx
new file mode 100644
index 000000000000..5149c0ced7ec
--- /dev/null
+++ b/sc/source/filter/xml/xmlexternaltabi.cxx
@@ -0,0 +1,361 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: xmlexternaltabi.cxx,v $
+ * $Revision: 1.1.2.5 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sc.hxx"
+
+
+
+// INCLUDE ---------------------------------------------------------------
+
+#include "xmlexternaltabi.hxx"
+#include "xmlimprt.hxx"
+#include "xmltabi.hxx"
+#include "xmlstyli.hxx"
+
+#include "token.hxx"
+#include "document.hxx"
+
+#include <xmloff/nmspmap.hxx>
+#include <xmloff/xmlnmspe.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <com/sun/star/util/NumberFormat.hpp>
+
+using namespace ::com::sun::star;
+
+using ::rtl::OUString;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::xml::sax::XAttributeList;
+
+// ============================================================================
+
+ScXMLExternalRefTabSourceContext::ScXMLExternalRefTabSourceContext(
+ ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName,
+ const Reference<XAttributeList>& xAttrList, ScXMLExternalTabData& rRefInfo ) :
+ SvXMLImportContext( rImport, nPrefix, rLName ),
+ mrScImport(rImport),
+ mrExternalRefInfo(rRefInfo)
+{
+ using namespace ::xmloff::token;
+
+ sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
+ for (sal_Int16 i = 0; i < nAttrCount; ++i)
+ {
+ const rtl::OUString& sAttrName = xAttrList->getNameByIndex(i);
+ rtl::OUString aLocalName;
+ sal_uInt16 nAttrPrefix = mrScImport.GetNamespaceMap().GetKeyByAttrName(sAttrName, &aLocalName);
+ const rtl::OUString& sValue = xAttrList->getValueByIndex(i);
+ if (nAttrPrefix == XML_NAMESPACE_XLINK)
+ {
+ if (IsXMLToken(aLocalName, XML_HREF))
+ maRelativeUrl = sValue;
+ }
+ else if (nAttrPrefix == XML_NAMESPACE_TABLE)
+ {
+ if (IsXMLToken(aLocalName, XML_TABLE_NAME))
+ maTableName = sValue;
+ else if (IsXMLToken(aLocalName, XML_FILTER_NAME))
+ maFilterName = sValue;
+ else if (IsXMLToken(aLocalName, XML_FILTER_OPTIONS))
+ maFilterOptions = sValue;
+ }
+ }
+}
+
+ScXMLExternalRefTabSourceContext::~ScXMLExternalRefTabSourceContext()
+{
+}
+
+SvXMLImportContext* ScXMLExternalRefTabSourceContext::CreateChildContext(
+ USHORT nPrefix, const OUString& rLocalName, const Reference<XAttributeList>& /*xAttrList*/ )
+{
+ return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
+}
+
+void ScXMLExternalRefTabSourceContext::EndElement()
+{
+ ScDocument* pDoc = mrScImport.GetDocument();
+ if (!pDoc)
+ return;
+
+ ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
+ if (!maRelativeUrl.equals(mrExternalRefInfo.maFileUrl))
+ pRefMgr->setRelativeFileName(mrExternalRefInfo.mnFileId, maRelativeUrl);
+ pRefMgr->setFilterData(mrExternalRefInfo.mnFileId, maFilterName, maFilterOptions);
+}
+
+// ============================================================================
+
+ScXMLExternalRefRowContext::ScXMLExternalRefRowContext(
+ ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName,
+ const Reference<XAttributeList>& xAttrList, ScXMLExternalTabData& rRefInfo ) :
+ SvXMLImportContext( rImport, nPrefix, rLName ),
+ mrScImport(rImport),
+ mrExternalRefInfo(rRefInfo),
+ mnRepeatRowCount(1)
+{
+ mrExternalRefInfo.mnCol = 0;
+
+ sal_Int16 nAttrCount(xAttrList.is() ? xAttrList->getLength() : 0);
+ const SvXMLTokenMap& rAttrTokenMap = mrScImport.GetTableRowAttrTokenMap();
+ for( sal_Int16 i=0; i < nAttrCount; ++i )
+ {
+ const rtl::OUString& sAttrName = xAttrList->getNameByIndex(i);
+ rtl::OUString aLocalName;
+ sal_uInt16 nAttrPrefix = mrScImport.GetNamespaceMap().GetKeyByAttrName(sAttrName, &aLocalName);
+ const rtl::OUString& sValue = xAttrList->getValueByIndex(i);
+
+ switch (rAttrTokenMap.Get(nAttrPrefix, aLocalName))
+ {
+ case XML_TOK_TABLE_ROW_ATTR_REPEATED:
+ {
+ mnRepeatRowCount = std::max(sValue.toInt32(), static_cast<sal_Int32>(1));
+ }
+ break;
+ }
+ }
+}
+
+ScXMLExternalRefRowContext::~ScXMLExternalRefRowContext()
+{
+}
+
+SvXMLImportContext* ScXMLExternalRefRowContext::CreateChildContext(
+ USHORT nPrefix, const OUString& rLocalName, const Reference<XAttributeList>& xAttrList )
+{
+ const SvXMLTokenMap& rTokenMap = mrScImport.GetTableRowElemTokenMap();
+ sal_uInt16 nToken = rTokenMap.Get(nPrefix, rLocalName);
+ if (nToken == XML_TOK_TABLE_ROW_CELL)
+ return new ScXMLExternalRefCellContext(mrScImport, nPrefix, rLocalName, xAttrList, mrExternalRefInfo);
+
+ return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
+}
+
+void ScXMLExternalRefRowContext::EndElement()
+{
+ ScExternalRefCache::TableTypeRef pTab = mrExternalRefInfo.mpCacheTable;
+
+ for (sal_Int32 i = 1; i < mnRepeatRowCount; ++i)
+ {
+ // Performance: duplicates of a non-existent row will still not exist.
+ // Don't find that out that for every cell.
+ // External references often are a sparse matrix.
+ if (i == 1 && !pTab->hasRow( mrExternalRefInfo.mnRow))
+ return;
+
+ for (sal_Int32 j = 0; j < mrExternalRefInfo.mnCol; ++j)
+ {
+ ScExternalRefCache::TokenRef pToken = pTab->getCell(
+ static_cast<SCCOL>(j), static_cast<SCROW>(mrExternalRefInfo.mnRow));
+
+ if (pToken.get())
+ {
+ pTab->setCell(static_cast<SCCOL>(j),
+ static_cast<SCROW>(mrExternalRefInfo.mnRow+i), pToken);
+ }
+ }
+ }
+ mrExternalRefInfo.mnRow += mnRepeatRowCount;
+}
+
+// ============================================================================
+
+ScXMLExternalRefCellContext::ScXMLExternalRefCellContext(
+ ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName,
+ const Reference<XAttributeList>& xAttrList, ScXMLExternalTabData& rRefInfo ) :
+ SvXMLImportContext( rImport, nPrefix, rLName ),
+ mrScImport(rImport),
+ mrExternalRefInfo(rRefInfo),
+ mfCellValue(0.0),
+ mnRepeatCount(1),
+ mnNumberFormat(-1),
+ mnCellType(::com::sun::star::util::NumberFormat::UNDEFINED),
+ mbIsNumeric(false),
+ mbIsEmpty(true)
+{
+ using namespace ::xmloff::token;
+
+ sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
+ const SvXMLTokenMap& rTokenMap = rImport.GetTableRowCellAttrTokenMap();
+ for (sal_Int16 i = 0; i < nAttrCount; ++i)
+ {
+ OUString aLocalName;
+ sal_uInt16 nAttrPrefix = rImport.GetNamespaceMap().GetKeyByAttrName(
+ xAttrList->getNameByIndex(i), &aLocalName);
+
+ const rtl::OUString& sValue = xAttrList->getValueByIndex(i);
+ sal_uInt16 nToken = rTokenMap.Get(nAttrPrefix, aLocalName);
+
+ switch (nToken)
+ {
+ case XML_TOK_TABLE_ROW_CELL_ATTR_STYLE_NAME:
+ {
+ XMLTableStylesContext* pStyles = static_cast<XMLTableStylesContext*>(mrScImport.GetAutoStyles());
+ const XMLTableStyleContext* pStyle = static_cast<const XMLTableStyleContext*>(
+ pStyles->FindStyleChildContext(XML_STYLE_FAMILY_TABLE_CELL, sValue, true));
+ if (pStyle)
+ mnNumberFormat = const_cast<XMLTableStyleContext*>(pStyle)->GetNumberFormat();
+ }
+ break;
+ case XML_TOK_TABLE_ROW_CELL_ATTR_REPEATED:
+ {
+ mnRepeatCount = ::std::max(sValue.toInt32(), static_cast<sal_Int32>(1));
+ }
+ break;
+ case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE_TYPE:
+ {
+ mnCellType = mrScImport.GetCellType(sValue);
+ }
+ break;
+ case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE:
+ {
+ if (sValue.getLength())
+ {
+ mrScImport.GetMM100UnitConverter().convertDouble(mfCellValue, sValue);
+ mbIsNumeric = true;
+ mbIsEmpty = false;
+ }
+ }
+ break;
+ case XML_TOK_TABLE_ROW_CELL_ATTR_DATE_VALUE:
+ {
+ if (sValue.getLength() && mrScImport.SetNullDateOnUnitConverter())
+ {
+ mrScImport.GetMM100UnitConverter().convertDateTime(mfCellValue, sValue);
+ mbIsNumeric = true;
+ mbIsEmpty = false;
+ }
+ }
+ break;
+ case XML_TOK_TABLE_ROW_CELL_ATTR_TIME_VALUE:
+ {
+ if (sValue.getLength())
+ {
+ mrScImport.GetMM100UnitConverter().convertTime(mfCellValue, sValue);
+ mbIsNumeric = true;
+ mbIsEmpty = false;
+ }
+ }
+ break;
+ case XML_TOK_TABLE_ROW_CELL_ATTR_STRING_VALUE:
+ {
+ if (sValue.getLength())
+ {
+ maCellString = sValue;
+ mbIsNumeric = false;
+ mbIsEmpty = false;
+ }
+ }
+ break;
+ case XML_TOK_TABLE_ROW_CELL_ATTR_BOOLEAN_VALUE:
+ {
+ if (sValue.getLength())
+ {
+ mfCellValue = IsXMLToken(sValue, XML_TRUE) ? 1.0 : 0.0;
+ mbIsNumeric = true;
+ mbIsEmpty = false;
+ }
+ }
+ break;
+ default:
+ ;
+ }
+ }
+}
+
+ScXMLExternalRefCellContext::~ScXMLExternalRefCellContext()
+{
+}
+
+SvXMLImportContext* ScXMLExternalRefCellContext::CreateChildContext(
+ USHORT nPrefix, const OUString& rLocalName, const Reference<XAttributeList>& xAttrList )
+{
+ 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 SvXMLImportContext(GetImport(), nPrefix, rLocalName);
+}
+
+void ScXMLExternalRefCellContext::EndElement()
+{
+ if (maCellString.getLength())
+ mbIsEmpty = false;
+
+ for (sal_Int32 i = 0; i < mnRepeatCount; ++i, ++mrExternalRefInfo.mnCol)
+ {
+ if (mbIsEmpty)
+ continue;
+
+ ScExternalRefCache::TokenRef aToken;
+ if (mbIsNumeric)
+ aToken.reset(new ScDoubleToken(mfCellValue));
+ else
+ aToken.reset(new ScStringToken(maCellString));
+
+ sal_uInt32 nNumFmt = mnNumberFormat >= 0 ? static_cast<sal_uInt32>(mnNumberFormat) : 0;
+ mrExternalRefInfo.mpCacheTable->setCell(
+ static_cast<SCCOL>(mrExternalRefInfo.mnCol),
+ static_cast<SCROW>(mrExternalRefInfo.mnRow),
+ aToken, nNumFmt);
+ }
+}
+
+// ============================================================================
+
+ScXMLExternalRefCellTextContext::ScXMLExternalRefCellTextContext(
+ ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName,
+ const Reference<XAttributeList>& /*xAttrList*/, OUString& rCellString ) :
+ SvXMLImportContext( rImport, nPrefix, rLName ),
+ mrScImport(rImport),
+ mrCellString(rCellString)
+{
+}
+
+ScXMLExternalRefCellTextContext::~ScXMLExternalRefCellTextContext()
+{
+}
+
+SvXMLImportContext* ScXMLExternalRefCellTextContext::CreateChildContext(
+ USHORT nPrefix, const OUString& rLocalName, const Reference<XAttributeList>& /*xAttrList*/ )
+{
+ return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
+}
+
+void ScXMLExternalRefCellTextContext::Characters(const OUString& rChar)
+{
+ mrCellString = rChar;
+}
+
+void ScXMLExternalRefCellTextContext::EndElement()
+{
+}
diff --git a/sc/source/filter/xml/xmlexternaltabi.hxx b/sc/source/filter/xml/xmlexternaltabi.hxx
new file mode 100644
index 000000000000..504be153953d
--- /dev/null
+++ b/sc/source/filter/xml/xmlexternaltabi.hxx
@@ -0,0 +1,150 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: xmlexternaltabi.hxx,v $
+ * $Revision: 1.1.2.2 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SC_XMLEXTERNALTABI_HXX
+#define SC_XMLEXTERNALTABI_HXX
+
+#include <xmloff/xmlictxt.hxx>
+
+class ScXMLImport;
+struct ScXMLExternalTabData;
+
+class ScXMLExternalRefTabSourceContext : public SvXMLImportContext
+{
+public:
+ ScXMLExternalRefTabSourceContext( ScXMLImport& rImport, USHORT nPrefix,
+ const ::rtl::OUString& rLName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
+ ScXMLExternalTabData& rRefInfo );
+
+ virtual ~ScXMLExternalRefTabSourceContext();
+
+ virtual SvXMLImportContext *CreateChildContext( USHORT nPrefix,
+ const ::rtl::OUString& rLocalName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList>& xAttrList );
+
+ virtual void EndElement();
+private:
+ ScXMLImport& mrScImport;
+ ScXMLExternalTabData& mrExternalRefInfo;
+
+ ::rtl::OUString maRelativeUrl;
+ ::rtl::OUString maTableName;
+ ::rtl::OUString maFilterName;
+ ::rtl::OUString maFilterOptions;
+};
+
+// ============================================================================
+
+class ScXMLExternalRefRowContext : public SvXMLImportContext
+{
+public:
+ ScXMLExternalRefRowContext( ScXMLImport& rImport, USHORT nPrefix,
+ const ::rtl::OUString& rLName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
+ ScXMLExternalTabData& rRefInfo );
+
+ virtual ~ScXMLExternalRefRowContext();
+
+ virtual SvXMLImportContext *CreateChildContext( USHORT nPrefix,
+ const ::rtl::OUString& rLocalName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList>& xAttrList );
+
+ virtual void EndElement();
+private:
+ ScXMLImport& mrScImport;
+ ScXMLExternalTabData& mrExternalRefInfo;
+ sal_Int32 mnRepeatRowCount;
+};
+
+// ============================================================================
+
+class ScXMLExternalRefCellContext : public SvXMLImportContext
+{
+public:
+ ScXMLExternalRefCellContext( ScXMLImport& rImport, USHORT nPrefix,
+ const ::rtl::OUString& rLName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
+ ScXMLExternalTabData& rRefInfo );
+
+ virtual ~ScXMLExternalRefCellContext();
+
+ virtual SvXMLImportContext *CreateChildContext( USHORT nPrefix,
+ const ::rtl::OUString& rLocalName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList>& xAttrList );
+
+ virtual void EndElement();
+
+private:
+ ScXMLImport& mrScImport;
+ ScXMLExternalTabData& mrExternalRefInfo;
+ ::rtl::OUString maCellString;
+ double mfCellValue;
+ sal_Int32 mnRepeatCount;
+ sal_Int32 mnNumberFormat;
+ sal_Int16 mnCellType;
+ bool mbIsNumeric;
+ bool mbIsEmpty;
+};
+
+// ============================================================================
+
+class ScXMLExternalRefCellTextContext : public SvXMLImportContext
+{
+public:
+ ScXMLExternalRefCellTextContext( ScXMLImport& rImport, USHORT nPrefix,
+ const ::rtl::OUString& rLName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
+ ::rtl::OUString& rCellString );
+
+ virtual ~ScXMLExternalRefCellTextContext();
+
+ virtual SvXMLImportContext *CreateChildContext( USHORT nPrefix,
+ const ::rtl::OUString& rLocalName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList>& xAttrList );
+
+ virtual void Characters(const ::rtl::OUString& rChar);
+
+ virtual void EndElement();
+
+private:
+ ScXMLImport& mrScImport;
+ ::rtl::OUString& mrCellString;
+};
+
+#endif
diff --git a/sc/source/filter/xml/xmlimprt.cxx b/sc/source/filter/xml/xmlimprt.cxx
index 6649e48e17b3..e436349b96c3 100644
--- a/sc/source/filter/xml/xmlimprt.cxx
+++ b/sc/source/filter/xml/xmlimprt.cxx
@@ -104,6 +104,7 @@
using namespace com::sun::star;
using namespace ::xmloff::token;
+using ::rtl::OUString;
OUString SAL_CALL ScXMLImport_getImplementationName() throw()
{
@@ -417,27 +418,25 @@ static __FAR_DATA SvXMLTokenMapEntry aTableRowCellTokenMap[] =
XML_TOKEN_MAP_END
};
-#if 0 // apparently not used - 2008-08-15 (Friday)
static __FAR_DATA SvXMLTokenMapEntry aTableRowCellAttrTokenMap[] =
{
- { XML_NAMESPACE_TABLE, XML_STYLE_NAME, XML_TOK_TABLE_ROW_CELL_ATTR_STYLE_NAME },
- { XML_NAMESPACE_TABLE, XML_CONTENT_VALIDATION_NAME, XML_TOK_TABLE_ROW_CELL_ATTR_CONTENT_VALIDATION_NAME },
- { XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_SPANNED, XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_ROWS },
- { XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_SPANNED, XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_COLS },
- { XML_NAMESPACE_TABLE, XML_NUMBER_MATRIX_COLUMNS_SPANNED, XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_MATRIX_COLS },
- { XML_NAMESPACE_TABLE, XML_NUMBER_MATRIX_ROWS_SPANNED, XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_MATRIX_ROWS },
- { XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED, XML_TOK_TABLE_ROW_CELL_ATTR_REPEATED },
- { XML_NAMESPACE_TABLE, XML_VALUE_TYPE, XML_TOK_TABLE_ROW_CELL_ATTR_VALUE_TYPE },
- { XML_NAMESPACE_TABLE, XML_VALUE, XML_TOK_TABLE_ROW_CELL_ATTR_VALUE },
- { XML_NAMESPACE_TABLE, XML_DATE_VALUE, XML_TOK_TABLE_ROW_CELL_ATTR_DATE_VALUE },
- { XML_NAMESPACE_TABLE, XML_TIME_VALUE, XML_TOK_TABLE_ROW_CELL_ATTR_TIME_VALUE },
- { XML_NAMESPACE_TABLE, XML_STRING_VALUE, XML_TOK_TABLE_ROW_CELL_ATTR_STRING_VALUE },
- { XML_NAMESPACE_TABLE, XML_BOOLEAN_VALUE, XML_TOK_TABLE_ROW_CELL_ATTR_BOOLEAN_VALUE },
- { XML_NAMESPACE_TABLE, XML_FORMULA, XML_TOK_TABLE_ROW_CELL_ATTR_FORMULA },
- { XML_NAMESPACE_TABLE, XML_CURRENCY, XML_TOK_TABLE_ROW_CELL_ATTR_CURRENCY },
+ { XML_NAMESPACE_TABLE, XML_STYLE_NAME, XML_TOK_TABLE_ROW_CELL_ATTR_STYLE_NAME },
+ { XML_NAMESPACE_TABLE, XML_CONTENT_VALIDATION_NAME, XML_TOK_TABLE_ROW_CELL_ATTR_CONTENT_VALIDATION_NAME },
+ { XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_SPANNED, XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_ROWS },
+ { XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_SPANNED, XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_COLS },
+ { XML_NAMESPACE_TABLE, XML_NUMBER_MATRIX_COLUMNS_SPANNED, XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_MATRIX_COLS },
+ { XML_NAMESPACE_TABLE, XML_NUMBER_MATRIX_ROWS_SPANNED, XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_MATRIX_ROWS },
+ { XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED, XML_TOK_TABLE_ROW_CELL_ATTR_REPEATED },
+ { XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_TOK_TABLE_ROW_CELL_ATTR_VALUE_TYPE },
+ { XML_NAMESPACE_OFFICE, XML_VALUE, XML_TOK_TABLE_ROW_CELL_ATTR_VALUE },
+ { XML_NAMESPACE_OFFICE, XML_DATE_VALUE, XML_TOK_TABLE_ROW_CELL_ATTR_DATE_VALUE },
+ { XML_NAMESPACE_OFFICE, XML_TIME_VALUE, XML_TOK_TABLE_ROW_CELL_ATTR_TIME_VALUE },
+ { XML_NAMESPACE_OFFICE, XML_STRING_VALUE, XML_TOK_TABLE_ROW_CELL_ATTR_STRING_VALUE },
+ { XML_NAMESPACE_OFFICE, XML_BOOLEAN_VALUE, XML_TOK_TABLE_ROW_CELL_ATTR_BOOLEAN_VALUE },
+ { XML_NAMESPACE_TABLE, XML_FORMULA, XML_TOK_TABLE_ROW_CELL_ATTR_FORMULA },
+ { XML_NAMESPACE_OFFICE, XML_CURRENCY, XML_TOK_TABLE_ROW_CELL_ATTR_CURRENCY },
XML_TOKEN_MAP_END
};
-#endif
static __FAR_DATA SvXMLTokenMapEntry aTableAnnotationAttrTokenMap[] =
{
@@ -1120,12 +1119,12 @@ const SvXMLTokenMap& ScXMLImport::GetTableRowCellElemTokenMap()
return *pTableRowCellElemTokenMap;
}
-//UNUSED2008-05 const SvXMLTokenMap& ScXMLImport::GetTableRowCellAttrTokenMap()
-//UNUSED2008-05 {
-//UNUSED2008-05 if ( !pTableRowCellAttrTokenMap )
-//UNUSED2008-05 pTableRowCellAttrTokenMap = new SvXMLTokenMap( aTableRowCellAttrTokenMap );
-//UNUSED2008-05 return *pTableRowCellAttrTokenMap;
-//UNUSED2008-05 }
+const SvXMLTokenMap& ScXMLImport::GetTableRowCellAttrTokenMap()
+{
+ if ( !pTableRowCellAttrTokenMap )
+ pTableRowCellAttrTokenMap = new SvXMLTokenMap( aTableRowCellAttrTokenMap );
+ return *pTableRowCellAttrTokenMap;
+}
const SvXMLTokenMap& ScXMLImport::GetTableAnnotationAttrTokenMap()
{
@@ -1564,6 +1563,25 @@ ScXMLImport::ScXMLImport(
GetXMLToken( XML_NP_PRESENTATION ),
GetXMLToken( XML_N_PRESENTATION ),
XML_NAMESPACE_PRESENTATION );
+
+ // initialize cell type map.
+ const struct { XMLTokenEnum _token; sal_Int16 _type; } aCellTypePairs[] =
+ {
+ { XML_FLOAT, util::NumberFormat::NUMBER },
+ { XML_STRING, util::NumberFormat::TEXT },
+ { XML_TIME, util::NumberFormat::TIME },
+ { XML_DATE, util::NumberFormat::DATETIME },
+ { XML_PERCENTAGE, util::NumberFormat::PERCENT },
+ { XML_CURRENCY, util::NumberFormat::CURRENCY },
+ { XML_BOOLEAN, util::NumberFormat::LOGICAL }
+ };
+ size_t n = sizeof(aCellTypePairs)/sizeof(aCellTypePairs[0]);
+ for (size_t i = 0; i < n; ++i)
+ {
+ aCellTypeMap.insert(
+ CellTypeMap::value_type(
+ GetXMLToken(aCellTypePairs[i]._token), aCellTypePairs[i]._type));
+ }
}
ScXMLImport::~ScXMLImport() throw()
@@ -1780,6 +1798,15 @@ void ScXMLImport::SetStatistics(
}
}
+sal_Int16 ScXMLImport::GetCellType(const OUString& rStrValue) const
+{
+ CellTypeMap::const_iterator itr = aCellTypeMap.find(rStrValue);
+ if (itr != aCellTypeMap.end())
+ return itr->second;
+
+ return util::NumberFormat::UNDEFINED;
+}
+
XMLShapeImportHelper* ScXMLImport::CreateShapeImport()
{
/*UniReference < XMLPropertySetMapper > xShapeStylesPropertySetMapper = new XMLPropertySetMapper((XMLPropertyMapEntry*)aXMLScShapeStylesProperties, xScPropHdlFactory);
diff --git a/sc/source/filter/xml/xmlimprt.hxx b/sc/source/filter/xml/xmlimprt.hxx
index 12a737320b4e..bbafdc2a2ea5 100644
--- a/sc/source/filter/xml/xmlimprt.hxx
+++ b/sc/source/filter/xml/xmlimprt.hxx
@@ -40,7 +40,6 @@
#include <com/sun/star/frame/XModel.hpp>
#include <tools/time.hxx>
#include <com/sun/star/util/DateTime.hpp>
-#include <vector>
#include "xmlsubti.hxx"
#include "global.hxx"
#include "grammar.hxx"
@@ -55,12 +54,13 @@
#include <com/sun/star/util/XNumberFormatTypes.hpp>
#include <com/sun/star/sheet/XSheetCellRangeContainer.hpp>
+#include <vector>
+#include <hash_map>
+
class ScRangeList;
class ScMyStyleNumberFormats;
class XMLNumberFormatAttributesExportHelper;
-using namespace rtl;
-
enum ScXMLDocTokens
{
XML_TOK_DOC_FONTDECLS,
@@ -642,6 +642,9 @@ class ScMyStylesImportHelper;
class ScXMLImport: public SvXMLImport
{
+ typedef ::std::hash_map< ::rtl::OUString, sal_Int16, ::rtl::OUStringHash > CellTypeMap;
+ CellTypeMap aCellTypeMap;
+
ScDocument* pDoc;
ScXMLChangeTrackingImportHelper* pChangeTrackingImportHelper;
ScMyViewContextList aViewContextList;
@@ -809,6 +812,8 @@ public:
sal_Bool IsLatinDefaultStyle() const { return bLatinDefaultStyle; }
+ sal_Int16 GetCellType(const ::rtl::OUString& rStrValue) const;
+
// SvI18NMap& GetI18NMap() { return *pI18NMap; }
// inline const SvXMLImportItemMapper& GetParaItemMapper() const;
@@ -848,7 +853,7 @@ public:
const SvXMLTokenMap& GetTableRowElemTokenMap();
const SvXMLTokenMap& GetTableRowAttrTokenMap();
const SvXMLTokenMap& GetTableRowCellElemTokenMap();
-//UNUSED2008-05 const SvXMLTokenMap& GetTableRowCellAttrTokenMap();
+ const SvXMLTokenMap& GetTableRowCellAttrTokenMap();
const SvXMLTokenMap& GetTableAnnotationAttrTokenMap();
const SvXMLTokenMap& GetDetectiveElemTokenMap();
const SvXMLTokenMap& GetDetectiveHighlightedAttrTokenMap();
diff --git a/sc/source/filter/xml/xmlsceni.cxx b/sc/source/filter/xml/xmlsceni.cxx
index 0a171ab4f455..d83a3c7e6c3f 100644
--- a/sc/source/filter/xml/xmlsceni.cxx
+++ b/sc/source/filter/xml/xmlsceni.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: xmlsceni.cxx,v $
- * $Revision: 1.15 $
+ * $Revision: 1.15.134.1 $
*
* This file is part of OpenOffice.org.
*
@@ -50,6 +50,7 @@
using namespace com::sun::star;
using namespace xmloff::token;
+using ::rtl::OUString;
//------------------------------------------------------------------
diff --git a/sc/source/filter/xml/xmlstyle.cxx b/sc/source/filter/xml/xmlstyle.cxx
index a7cba003ba10..55b86403ef25 100644
--- a/sc/source/filter/xml/xmlstyle.cxx
+++ b/sc/source/filter/xml/xmlstyle.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: xmlstyle.cxx,v $
- * $Revision: 1.70 $
+ * $Revision: 1.70.62.1 $
*
* This file is part of OpenOffice.org.
*
@@ -65,6 +65,7 @@
using namespace com::sun::star;
using namespace ::xmloff::token;
+using ::rtl::OUString;
#define MAP(name,prefix,token,type,context) { name, sizeof(name)-1, prefix, token, type, context, SvtSaveOptions::ODFVER_010 }
#define MAP_END() { NULL, 0, 0, XML_TOKEN_INVALID, 0, 0, SvtSaveOptions::ODFVER_010 }
diff --git a/sc/source/filter/xml/xmlstyle.hxx b/sc/source/filter/xml/xmlstyle.hxx
index e9503fbd074c..da1dc8ab4849 100644
--- a/sc/source/filter/xml/xmlstyle.hxx
+++ b/sc/source/filter/xml/xmlstyle.hxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: xmlstyle.hxx,v $
- * $Revision: 1.32 $
+ * $Revision: 1.32.62.1 $
*
* This file is part of OpenOffice.org.
*
@@ -40,8 +40,6 @@
#include <xmloff/xmlexppr.hxx>
#include <xmloff/contextid.hxx>
-using namespace rtl;
-
extern const XMLPropertyMapEntry aXMLScCellStylesProperties[];
extern const XMLPropertyMapEntry aXMLScColumnStylesProperties[];
extern const XMLPropertyMapEntry aXMLScRowStylesProperties[];
diff --git a/sc/source/filter/xml/xmlstyli.cxx b/sc/source/filter/xml/xmlstyli.cxx
index dfcac81e6228..5911d27376b3 100644
--- a/sc/source/filter/xml/xmlstyli.cxx
+++ b/sc/source/filter/xml/xmlstyli.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: xmlstyli.cxx,v $
- * $Revision: 1.63 $
+ * $Revision: 1.63.134.1 $
*
* This file is part of OpenOffice.org.
*
@@ -584,28 +584,10 @@ void XMLTableStyleContext::FillPropertySet(
AddProperty(CTF_SC_CELLSTYLE, uno::makeAny(GetImport().GetStyleDisplayName( XML_STYLE_FAMILY_TABLE_CELL, GetParentName() )));
bParentSet = sal_True;
}
- if ((nNumberFormat == -1) && sDataStyleName.getLength())
- {
- SvXMLNumFormatContext* pStyle((SvXMLNumFormatContext *)pStyles->FindStyleChildContext(
- XML_STYLE_FAMILY_DATA_STYLE, sDataStyleName, sal_True));
- if (!pStyle)
- {
- XMLTableStylesContext* pMyStyles((XMLTableStylesContext *)GetScImport().GetStyles());
- if (pMyStyles)
- pStyle = (SvXMLNumFormatContext *)pMyStyles->
- FindStyleChildContext(XML_STYLE_FAMILY_DATA_STYLE, sDataStyleName, sal_True);
- else
- {
- DBG_ERROR("not possible to get style");
- }
- }
- if (pStyle)
- {
- //rPropSet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_NUMBERFORMAT)), aNumberFormat);
- nNumberFormat = pStyle->GetKey();
- AddProperty(CTF_SC_NUMBERFORMAT, uno::makeAny(nNumberFormat));
- }
- }
+ sal_Int32 nNumFmt = GetNumberFormat();
+ if (nNumFmt >= 0)
+ AddProperty(CTF_SC_NUMBERFORMAT, uno::makeAny(nNumFmt));
+
if (!bConditionalFormatCreated && (aMaps.size() > 0))
{
aConditionalFormat = rPropSet->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_CONDXML)));
@@ -683,6 +665,30 @@ XMLPropertyState* XMLTableStyleContext::FindProperty(const sal_Int16 nContextID)
return pRet;
}
+sal_Int32 XMLTableStyleContext::GetNumberFormat()
+{
+ if (nNumberFormat < 0 && sDataStyleName.getLength())
+ {
+ const SvXMLNumFormatContext* pStyle = static_cast<const SvXMLNumFormatContext*>(
+ pStyles->FindStyleChildContext(XML_STYLE_FAMILY_DATA_STYLE, sDataStyleName, sal_True));
+
+ if (!pStyle)
+ {
+ XMLTableStylesContext* pMyStyles = static_cast<XMLTableStylesContext*>(GetScImport().GetStyles());
+ if (pMyStyles)
+ pStyle = static_cast<const SvXMLNumFormatContext*>(
+ pMyStyles->FindStyleChildContext(XML_STYLE_FAMILY_DATA_STYLE, sDataStyleName, sal_True));
+ else
+ {
+ DBG_ERROR("not possible to get style");
+ }
+ }
+ if (pStyle)
+ nNumberFormat = const_cast<SvXMLNumFormatContext*>(pStyle)->GetKey();
+ }
+ return nNumberFormat;
+}
+
// ----------------------------------------------------------------------------
SvXMLStyleContext *XMLTableStylesContext::CreateStyleStyleChildContext(
diff --git a/sc/source/filter/xml/xmlstyli.hxx b/sc/source/filter/xml/xmlstyli.hxx
index 461f225097e8..09f931c94cf5 100644
--- a/sc/source/filter/xml/xmlstyli.hxx
+++ b/sc/source/filter/xml/xmlstyli.hxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: xmlstyli.hxx,v $
- * $Revision: 1.29 $
+ * $Revision: 1.29.62.1 $
*
* This file is part of OpenOffice.org.
*
@@ -154,7 +154,7 @@ public:
void AddProperty(sal_Int16 nContextID, const com::sun::star::uno::Any& aValue);
XMLPropertyState* FindProperty(const sal_Int16 nContextID);
- sal_Int32 GetNumberFormat() { return nNumberFormat; }
+ sal_Int32 GetNumberFormat();
private:
using XMLPropStyleContext::SetStyle;
diff --git a/sc/source/filter/xml/xmltabi.cxx b/sc/source/filter/xml/xmltabi.cxx
index 608c1ea2ccc0..c75a90815197 100644
--- a/sc/source/filter/xml/xmltabi.cxx
+++ b/sc/source/filter/xml/xmltabi.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: xmltabi.cxx,v $
- * $Revision: 1.40 $
+ * $Revision: 1.40.134.4 $
*
* This file is part of OpenOffice.org.
*
@@ -40,6 +40,7 @@
#include "xmlrowi.hxx"
#include "xmlcoli.hxx"
#include "xmlsceni.hxx"
+#include "xmlexternaltabi.hxx"
#include "document.hxx"
#include "docuno.hxx"
#include "olinetab.hxx"
@@ -48,6 +49,7 @@
#include "XMLTableSourceContext.hxx"
#include "XMLStylesImportHelper.hxx"
#include "rangeutl.hxx"
+#include "externalrefmgr.hxx"
#include <xmloff/xmltkmap.hxx>
#include <xmloff/nmspmap.hxx>
@@ -63,6 +65,77 @@
using namespace com::sun::star;
using namespace xmloff::token;
+/**
+ * Determine whether this table is an external reference cache from its
+ * name. There is currently no way of determining whether a table is a
+ * regular table or an external reference cache other than examining the
+ * name itself. We should probably introduce a new boolean value for
+ * table:table element and use it instead of doing this, to make it more
+ * reliable and future-proof.
+ *
+ * @param rName
+ *
+ * @return
+ */
+static bool lcl_isExternalRefCache(const rtl::OUString& rName, rtl::OUString& rUrl, rtl::OUString& rExtTabName)
+{
+ // 'file:///path/to/file.ods'#MySheet
+ // 'file:///path/to/file.ods'#MySheet with space
+ // 'file:///path/to/file's.ods'#Sheet (Notice the quote in the file name.
+ // That's allowed.)
+
+ static const sal_Unicode aPrefix[] = {
+ '\'', 'f', 'i', 'l', 'e', ':', '/', '/'
+ };
+
+ rtl::OUStringBuffer aUrlBuf, aTabNameBuf;
+ aUrlBuf.appendAscii("file://");
+ sal_Int32 n = rName.getLength();
+ const sal_Unicode* p = rName.getStr();
+
+ bool bInUrl = true;
+ sal_Unicode cPrev = 0;
+ for (sal_Int32 i = 0; i < n; ++i)
+ {
+ const sal_Unicode c = p[i];
+ if (i <= 7)
+ {
+ if (c != aPrefix[i])
+ return false;
+ }
+ else if (c == '#')
+ {
+ if (cPrev != '\'')
+ return false;
+
+ rUrl = aUrlBuf.makeStringAndClear();
+ rUrl = rUrl.copy(0, rUrl.getLength()-1); // remove the trailing single-quote.
+ bInUrl = false;
+ }
+ else if (bInUrl)
+ aUrlBuf.append(c);
+ else
+ aTabNameBuf.append(c);
+
+ cPrev = c;
+ }
+
+ if (bInUrl)
+ return false;
+
+ if (aTabNameBuf.getLength() == 0)
+ return false;
+
+ rExtTabName = aTabNameBuf.makeStringAndClear();
+
+ return true;
+}
+
+ScXMLExternalTabData::ScXMLExternalTabData() :
+ mpCacheTable(), mnRow(0), mnCol(0), mnFileId(0)
+{
+}
+
//------------------------------------------------------------------
ScXMLTableContext::ScXMLTableContext( ScXMLImport& rImport,
@@ -73,6 +146,7 @@ ScXMLTableContext::ScXMLTableContext( ScXMLImport& rImport,
const sal_Bool bTempIsSubTable,
const sal_Int32 nSpannedCols) :
SvXMLImportContext( rImport, nPrfx, rLName ),
+ pExternalRefInfo(NULL),
bStartFormPage(sal_False),
bPrintEntireSheet(sal_True)
{
@@ -117,7 +191,26 @@ ScXMLTableContext::ScXMLTableContext( ScXMLImport& rImport,
break;
}
}
- GetScImport().GetTables().NewSheet(sName, sStyleName, bProtection, sPassword);
+
+ rtl::OUString aExtUrl, aExtTabName;
+ if (lcl_isExternalRefCache(sName, aExtUrl, aExtTabName))
+ {
+ // This is an external ref cache table.
+ pExternalRefInfo.reset(new ScXMLExternalTabData);
+ pExternalRefInfo->maFileUrl = aExtUrl;
+ ScDocument* pDoc = GetScImport().GetDocument();
+ if (pDoc)
+ {
+ ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
+ pExternalRefInfo->mnFileId = pRefMgr->getExternalFileId(aExtUrl);
+ pExternalRefInfo->mpCacheTable = pRefMgr->getCacheTable(pExternalRefInfo->mnFileId, aExtTabName, true);
+ }
+ }
+ else
+ {
+ // This is a regular table.
+ GetScImport().GetTables().NewSheet(sName, sStyleName, bProtection, sPassword);
+ }
}
else
{
@@ -134,10 +227,30 @@ SvXMLImportContext *ScXMLTableContext::CreateChildContext( USHORT nPrefix,
const ::com::sun::star::uno::Reference<
::com::sun::star::xml::sax::XAttributeList>& xAttrList )
{
+ const SvXMLTokenMap& rTokenMap(GetScImport().GetTableElemTokenMap());
+ sal_uInt16 nToken = rTokenMap.Get(nPrefix, rLName);
+ if (pExternalRefInfo.get())
+ {
+ // We only care about the table-row and table-source elements for
+ // external cache data.
+ switch (nToken)
+ {
+ case XML_TOK_TABLE_ROW:
+ return new ScXMLExternalRefRowContext(
+ GetScImport(), nPrefix, rLName, xAttrList, *pExternalRefInfo);
+ case XML_TOK_TABLE_SOURCE:
+ return new ScXMLExternalRefTabSourceContext(
+ GetScImport(), nPrefix, rLName, xAttrList, *pExternalRefInfo);
+ default:
+ ;
+ }
+
+ return new SvXMLImportContext(GetImport(), nPrefix, rLName);
+ }
+
SvXMLImportContext *pContext(0);
- const SvXMLTokenMap& rTokenMap(GetScImport().GetTableElemTokenMap());
- switch( rTokenMap.Get( nPrefix, rLName ) )
+ switch (nToken)
{
case XML_TOK_TABLE_COL_GROUP:
pContext = new ScXMLTableColsContext( GetScImport(), nPrefix,
@@ -195,6 +308,8 @@ SvXMLImportContext *ScXMLTableContext::CreateChildContext( USHORT nPrefix,
pContext = GetScImport().GetFormImport()->createOfficeFormsContext( GetScImport(), nPrefix, rLName );
}
break;
+ default:
+ ;
}
if( !pContext )
diff --git a/sc/source/filter/xml/xmltabi.hxx b/sc/source/filter/xml/xmltabi.hxx
index c50c4fd82fd0..7b8c9878f2d5 100644
--- a/sc/source/filter/xml/xmltabi.hxx
+++ b/sc/source/filter/xml/xmltabi.hxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: xmltabi.hxx,v $
- * $Revision: 1.11 $
+ * $Revision: 1.11.134.2 $
*
* This file is part of OpenOffice.org.
*
@@ -30,13 +30,28 @@
#ifndef SC_XMLTABI_HXX
#define SC_XMLTABI_HXX
+#include "externalrefmgr.hxx"
+
#include <xmloff/xmlictxt.hxx>
+#include <memory>
class ScXMLImport;
+struct ScXMLExternalTabData
+{
+ String maFileUrl;
+ ScExternalRefCache::TableTypeRef mpCacheTable;
+ sal_Int32 mnRow;
+ sal_Int32 mnCol;
+ sal_uInt16 mnFileId;
+
+ ScXMLExternalTabData();
+};
+
class ScXMLTableContext : public SvXMLImportContext
{
rtl::OUString sPrintRanges;
+ ::std::auto_ptr<ScXMLExternalTabData> pExternalRefInfo;
sal_Bool bStartFormPage;
sal_Bool bPrintEntireSheet;
diff --git a/sc/source/filter/xml/xmlwrap.cxx b/sc/source/filter/xml/xmlwrap.cxx
index 88f2bf2ba0a1..960d78ada163 100644
--- a/sc/source/filter/xml/xmlwrap.cxx
+++ b/sc/source/filter/xml/xmlwrap.cxx
@@ -85,6 +85,7 @@
#define MAP_LEN(x) x, sizeof(x) - 1
using namespace com::sun::star;
+using ::rtl::OUString;
// -----------------------------------------------------------------------
diff --git a/sc/source/ui/dbgui/validate.cxx b/sc/source/ui/dbgui/validate.cxx
index e7966e389bba..d547bae25de9 100644
--- a/sc/source/ui/dbgui/validate.cxx
+++ b/sc/source/ui/dbgui/validate.cxx
@@ -172,8 +172,7 @@ void lclGetFormulaFromStringList( String& rFmlaStr, const String& rStringList, s
for( xub_StrLen nToken = 0, nStringIx = 0; nToken < nTokenCnt; ++nToken )
{
String aToken( rStringList.GetToken( 0, '\n', nStringIx ) );
- aToken.SearchAndReplaceAllAscii( "\"", String( RTL_CONSTASCII_USTRINGPARAM( "\"\"" ) ) );
- ScGlobal::AddQuotes( aToken );
+ ScGlobal::AddQuotes( aToken, '"' );
ScGlobal::AddToken( rFmlaStr, aToken, cFmlaSep );
}
if( !rFmlaStr.Len() )
@@ -201,11 +200,10 @@ bool lclGetStringListFromFormula( String& rStringList, const String& rFmlaStr, s
aToken.EraseLeadingAndTrailingChars();
if( aToken.Len() ) // ignore empty tokens, i.e. "a";;"b"
{
- bIsStringList = ScGlobal::IsQuoted( aToken );
+ bIsStringList = ScGlobal::IsQuoted( aToken, '"' );
if( bIsStringList )
{
- ScGlobal::EraseQuotes( aToken );
- aToken.SearchAndReplaceAllAscii( "\"\"", String( '"' ) );
+ ScGlobal::EraseQuotes( aToken, '"' );
ScGlobal::AddToken( rStringList, aToken, '\n', 1, bTokenAdded );
bTokenAdded = true;
}
diff --git a/sc/source/ui/docshell/docsh4.cxx b/sc/source/ui/docshell/docsh4.cxx
index 2f02b03e811a..a7709367a659 100644
--- a/sc/source/ui/docshell/docsh4.cxx
+++ b/sc/source/ui/docshell/docsh4.cxx
@@ -123,6 +123,7 @@ using namespace ::com::sun::star;
#include <com/sun/star/document/UpdateDocMode.hpp>
#include "scresid.hxx" //add by CHINA001
#include "scabstdlg.hxx" //CHINA001
+#include "externalrefmgr.hxx"
#include "sharedocdlg.hxx"
@@ -510,6 +511,7 @@ void ScDocShell::Execute( SfxRequest& rReq )
if (nDlgRet == RET_YES || nSet==LM_ALWAYS)
{
ReloadTabLinks();
+ aDocument.UpdateExternalRefLinks();
aDocument.UpdateDdeLinks();
aDocument.UpdateAreaLinks();
diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx
new file mode 100644
index 000000000000..5b580796458c
--- /dev/null
+++ b/sc/source/ui/docshell/externalrefmgr.cxx
@@ -0,0 +1,1923 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: externalrefmgr.cxx,v $
+ * $Revision: 1.1.2.33 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sc.hxx"
+
+
+
+// INCLUDE ---------------------------------------------------------------
+
+#include "externalrefmgr.hxx"
+#include "document.hxx"
+#include "token.hxx"
+#include "tokenarray.hxx"
+#include "address.hxx"
+#include "tablink.hxx"
+#include "docsh.hxx"
+#include "scextopt.hxx"
+#include "rangenam.hxx"
+#include "cell.hxx"
+#include "viewdata.hxx"
+#include "tabvwsh.hxx"
+#include "sc.hrc"
+
+#include "sfx2/app.hxx"
+#include "sfx2/docfilt.hxx"
+#include "sfx2/docfile.hxx"
+#include "sfx2/fcontnr.hxx"
+#include "sfx2/sfxsids.hrc"
+#include "sfx2/objsh.hxx"
+#include "svtools/broadcast.hxx"
+#include "svtools/smplhint.hxx"
+#include "svtools/itemset.hxx"
+#include "svtools/stritem.hxx"
+#include "svtools/urihelper.hxx"
+#include "svtools/zformat.hxx"
+#include "svx/linkmgr.hxx"
+#include "tools/urlobj.hxx"
+#include "unotools/ucbhelper.hxx"
+
+#include <memory>
+#include <algorithm>
+
+using ::std::auto_ptr;
+using ::com::sun::star::uno::Any;
+using ::rtl::OUString;
+using ::std::vector;
+using ::std::find;
+using ::std::find_if;
+using ::std::distance;
+using ::std::pair;
+using ::std::list;
+
+#define SRCDOC_LIFE_SPAN 6000 // 1 minute (in 100th of a sec)
+#define SRCDOC_SCAN_INTERVAL 1000*5 // every 5 seconds (in msec)
+
+namespace {
+
+class TabNameSearchPredicate : ::std::unary_function<bool, ScExternalRefCache::TableName>
+{
+public:
+ explicit TabNameSearchPredicate(const String& rSearchName) :
+ maSearchName(ScGlobal::pCharClass->upper(rSearchName))
+ {
+ }
+
+ bool operator()(const ScExternalRefCache::TableName& rTabNameSet) const
+ {
+ // Ok, I'm doing case insensitive search here.
+ return rTabNameSet.maUpperName.Equals(maSearchName);
+ }
+
+private:
+ String maSearchName;
+};
+
+class FindSrcFileByName : public ::std::unary_function<ScExternalRefManager::SrcFileData, bool>
+{
+public:
+ FindSrcFileByName(const String& rMatchName) :
+ mrMatchName(rMatchName)
+ {
+ }
+
+ bool operator()(const ScExternalRefManager::SrcFileData& rSrcData) const
+ {
+ return rSrcData.maFileName.Equals(mrMatchName);
+ }
+
+private:
+ const String& mrMatchName;
+};
+
+}
+
+// ============================================================================
+
+ScExternalRefCache::Table::Table()
+{
+}
+
+ScExternalRefCache::Table::~Table()
+{
+}
+
+void ScExternalRefCache::Table::setCell(SCCOL nCol, SCROW nRow, TokenRef pToken, sal_uInt32 nFmtIndex)
+{
+ using ::std::pair;
+ RowsDataType::iterator itrRow = maRows.find(nRow);
+ if (itrRow == maRows.end())
+ {
+ // This row does not exist yet.
+ pair<RowsDataType::iterator, bool> res = maRows.insert(
+ RowsDataType::value_type(nRow, RowDataType()));
+
+ if (!res.second)
+ return;
+
+ itrRow = res.first;
+ }
+
+ // Insert this token into the specified column location. I don't need to
+ // check for existing data. Just overwrite it.
+ RowDataType& rRow = itrRow->second;
+ ScExternalRefCache::Cell aCell;
+ aCell.mxToken = pToken;
+ aCell.mnFmtIndex = nFmtIndex;
+ rRow.insert(RowDataType::value_type(nCol, aCell));
+}
+
+ScExternalRefCache::TokenRef ScExternalRefCache::Table::getCell(SCCOL nCol, SCROW nRow, sal_uInt32* pnFmtIndex) const
+{
+ RowsDataType::const_iterator itrTable = maRows.find(nRow);
+ if (itrTable == maRows.end())
+ {
+ // this table doesn't have the specified row.
+ return TokenRef();
+ }
+
+ const RowDataType& rRowData = itrTable->second;
+ RowDataType::const_iterator itrRow = rRowData.find(nCol);
+ if (itrRow == rRowData.end())
+ {
+ // this row doesn't have the specified column.
+ return TokenRef();
+ }
+
+ const Cell& rCell = itrRow->second;
+ if (pnFmtIndex)
+ *pnFmtIndex = rCell.mnFmtIndex;
+
+ return rCell.mxToken;
+}
+
+bool ScExternalRefCache::Table::hasRow( SCROW nRow ) const
+{
+ RowsDataType::const_iterator itrRow = maRows.find(nRow);
+ return itrRow != maRows.end();
+}
+
+void ScExternalRefCache::Table::getAllRows(vector<SCROW>& rRows) 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);
+
+ // hash map is not ordered, so we need to explicitly sort it.
+ ::std::sort(aRows.begin(), aRows.end());
+ rRows.swap(aRows);
+}
+
+void ScExternalRefCache::Table::getAllCols(SCROW nRow, vector<SCCOL>& rCols) const
+{
+ RowsDataType::const_iterator itrRow = maRows.find(nRow);
+ if (itrRow == maRows.end())
+ // this table doesn't have the specified row.
+ return;
+
+ const RowDataType& rRowData = itrRow->second;
+ vector<SCCOL> aCols;
+ aCols.reserve(rRowData.size());
+ RowDataType::const_iterator itrCol = rRowData.begin(), itrColEnd = rRowData.end();
+ for (; itrCol != itrColEnd; ++itrCol)
+ aCols.push_back(itrCol->first);
+
+ // hash map is not ordered, so we need to explicitly sort it.
+ ::std::sort(aCols.begin(), aCols.end());
+ rCols.swap(aCols);
+}
+
+void ScExternalRefCache::Table::getAllNumberFormats(vector<sal_uInt32>& rNumFmts) const
+{
+ RowsDataType::const_iterator itrRow = maRows.begin(), itrRowEnd = maRows.end();
+ for (; itrRow != itrRowEnd; ++itrRow)
+ {
+ const RowDataType& rRowData = itrRow->second;
+ RowDataType::const_iterator itrCol = rRowData.begin(), itrColEnd = rRowData.end();
+ for (; itrCol != itrColEnd; ++itrCol)
+ {
+ const Cell& rCell = itrCol->second;
+ rNumFmts.push_back(rCell.mnFmtIndex);
+ }
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+ScExternalRefCache::TableName::TableName(const String& rUpper, const String& rReal) :
+ maUpperName(rUpper), maRealName(rReal)
+{
+}
+
+// ----------------------------------------------------------------------------
+
+ScExternalRefCache::CellFormat::CellFormat() :
+ mbIsSet(false), mnType(NUMBERFORMAT_ALL), mnIndex(0)
+{
+}
+
+// ----------------------------------------------------------------------------
+
+ScExternalRefCache::ScExternalRefCache()
+{
+}
+ScExternalRefCache::~ScExternalRefCache()
+{
+}
+
+const String* ScExternalRefCache::getRealTableName(sal_uInt16 nFileId, const String& rTabName) const
+{
+ DocDataType::const_iterator itrDoc = maDocs.find(nFileId);
+ if (itrDoc == maDocs.end())
+ {
+ // specified document is not cached.
+ return NULL;
+ }
+
+ const DocItem& rDoc = itrDoc->second;
+ TableNameIndexMap::const_iterator itrTabId = rDoc.maTableNameIndex.find(
+ ScGlobal::pCharClass->upper(rTabName));
+ if (itrTabId == rDoc.maTableNameIndex.end())
+ {
+ // the specified table is not in cache.
+ return NULL;
+ }
+
+ return &rDoc.maTableNames[itrTabId->second].maRealName;
+}
+
+const String* ScExternalRefCache::getRealRangeName(sal_uInt16 nFileId, const String& rRangeName) const
+{
+ DocDataType::const_iterator itrDoc = maDocs.find(nFileId);
+ if (itrDoc == maDocs.end())
+ {
+ // specified document is not cached.
+ return NULL;
+ }
+
+ const DocItem& rDoc = itrDoc->second;
+ NamePairMap::const_iterator itr = rDoc.maRealRangeNameMap.find(
+ ScGlobal::pCharClass->upper(rRangeName));
+ if (itr == rDoc.maRealRangeNameMap.end())
+ // range name not found.
+ return NULL;
+
+ return &itr->second;
+}
+
+ScExternalRefCache::TokenRef ScExternalRefCache::getCellData(
+ sal_uInt16 nFileId, const String& rTabName, SCROW nRow, SCCOL nCol, sal_uInt32* pnFmtIndex)
+{
+ DocDataType::const_iterator itrDoc = maDocs.find(nFileId);
+ if (itrDoc == maDocs.end())
+ {
+ // specified document is not cached.
+ return TokenRef();
+ }
+
+ const DocItem& rDoc = itrDoc->second;
+ TableNameIndexMap::const_iterator itrTabId = rDoc.maTableNameIndex.find(
+ ScGlobal::pCharClass->upper(rTabName));
+ if (itrTabId == rDoc.maTableNameIndex.end())
+ {
+ // the specified table is not in cache.
+ return TokenRef();
+ }
+
+ const TableTypeRef& pTableData = rDoc.maTables[itrTabId->second];
+ if (!pTableData.get())
+ {
+ // the table data is not instantiated yet.
+ return TokenRef();
+ }
+ return pTableData->getCell(nCol, nRow, pnFmtIndex);
+}
+
+ScExternalRefCache::TokenArrayRef ScExternalRefCache::getCellRangeData(sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange)
+{
+ DocDataType::iterator itrDoc = maDocs.find(nFileId);
+ if (itrDoc == maDocs.end())
+ // specified document is not cached.
+ return TokenArrayRef();
+
+ DocItem& rDoc = itrDoc->second;
+ RangeArrayMap::const_iterator itrRange = rDoc.maRangeArrays.find(rRange);
+ if (itrRange != rDoc.maRangeArrays.end())
+ {
+ return itrRange->second;
+ }
+
+ TableNameIndexMap::iterator itrTabId = rDoc.maTableNameIndex.find(
+ ScGlobal::pCharClass->upper(rTabName));
+ if (itrTabId == rDoc.maTableNameIndex.end())
+ // the specified table is not in cache.
+ return TokenArrayRef();
+
+ const ScAddress& s = rRange.aStart;
+ const ScAddress& e = rRange.aEnd;
+
+ SCTAB nTab1 = s.Tab(), nTab2 = e.Tab();
+ SCCOL nCol1 = s.Col(), nCol2 = e.Col();
+ SCROW nRow1 = s.Row(), nRow2 = e.Row();
+
+ // Make sure I have all the tables cached.
+ size_t nTabFirstId = itrTabId->second;
+ size_t nTabLastId = nTabFirstId + nTab2 - nTab1;
+ if (nTabLastId >= rDoc.maTables.size())
+ // not all tables are cached.
+ return TokenArrayRef();
+
+ TokenArrayRef pArray(new ScTokenArray);
+ bool bFirstTab = true;
+ for (size_t nTab = nTabFirstId; nTab <= nTabLastId; ++nTab)
+ {
+ TableTypeRef pTab = rDoc.maTables[nTab];
+ if (!pTab.get())
+ return TokenArrayRef();
+
+ ScMatrixRef xMat = new ScMatrix(
+ static_cast<SCSIZE>(nCol2-nCol1+1), static_cast<SCSIZE>(nRow2-nRow1+1));
+
+ for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
+ {
+ for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+ {
+ ScToken* pToken = pTab->getCell(nCol, nRow).get();
+ if (!pToken)
+ return TokenArrayRef();
+
+ SCSIZE nC = nCol - nCol1, nR = nRow - nRow1;
+ switch (pToken->GetType())
+ {
+ case svDouble:
+ xMat->PutDouble(pToken->GetDouble(), nC, nR);
+ break;
+ case svString:
+ xMat->PutString(pToken->GetString(), nC, nR);
+ break;
+ default:
+ xMat->PutEmpty(nC, nR);
+ }
+ }
+ }
+
+ if (!bFirstTab)
+ pArray->AddOpCode(ocSep);
+
+ ScMatrix* pMat2 = xMat;
+ ScMatrixToken aToken(pMat2);
+ pArray->AddToken(aToken);
+
+ bFirstTab = false;
+ }
+ rDoc.maRangeArrays.insert(RangeArrayMap::value_type(rRange, pArray));
+ return pArray;
+}
+
+ScExternalRefCache::TokenArrayRef ScExternalRefCache::getRangeNameTokens(sal_uInt16 nFileId, const String& rName)
+{
+ DocItem* pDoc = getDocItem(nFileId);
+ if (!pDoc)
+ return TokenArrayRef();
+
+ RangeNameMap& rMap = pDoc->maRangeNames;
+ RangeNameMap::const_iterator itr = rMap.find(
+ ScGlobal::pCharClass->upper(rName));
+ if (itr == rMap.end())
+ return TokenArrayRef();
+
+ return itr->second;
+}
+
+void ScExternalRefCache::setRangeNameTokens(sal_uInt16 nFileId, const String& rName, TokenArrayRef pArray)
+{
+ DocItem* pDoc = getDocItem(nFileId);
+ if (!pDoc)
+ return;
+
+ String aUpperName = ScGlobal::pCharClass->upper(rName);
+ RangeNameMap& rMap = pDoc->maRangeNames;
+ rMap.insert(RangeNameMap::value_type(aUpperName, pArray));
+ pDoc->maRealRangeNameMap.insert(NamePairMap::value_type(aUpperName, rName));
+}
+
+void ScExternalRefCache::setCellData(sal_uInt16 nFileId, const String& rTabName, SCROW nRow, SCCOL nCol,
+ TokenRef pToken, sal_uInt32 nFmtIndex)
+{
+ if (!isDocInitialized(nFileId))
+ return;
+
+ using ::std::pair;
+ DocItem* pDocItem = getDocItem(nFileId);
+ if (!pDocItem)
+ return;
+
+ DocItem& rDoc = *pDocItem;
+
+ // See if the table by this name already exists.
+ TableNameIndexMap::iterator itrTabName = rDoc.maTableNameIndex.find(
+ ScGlobal::pCharClass->upper(rTabName));
+ if (itrTabName == rDoc.maTableNameIndex.end())
+ // Table not found. Maybe the table name or the file id is wrong ???
+ return;
+
+ TableTypeRef& pTableData = rDoc.maTables[itrTabName->second];
+ if (!pTableData.get())
+ pTableData.reset(new Table);
+
+ pTableData->setCell(nCol, nRow, pToken, nFmtIndex);
+}
+
+void ScExternalRefCache::setCellRangeData(sal_uInt16 nFileId, const ScRange& rRange, const vector<SingleRangeData>& rData,
+ TokenArrayRef pArray)
+{
+ using ::std::pair;
+ if (rData.empty() || !isDocInitialized(nFileId))
+ // nothing to cache
+ return;
+
+ // First, get the document item for the given file ID.
+ DocItem* pDocItem = getDocItem(nFileId);
+ if (!pDocItem)
+ return;
+
+ DocItem& rDoc = *pDocItem;
+
+ // Now, find the table position of the first table to cache.
+ const String& rFirstTabName = rData.front().maTableName;
+ TableNameIndexMap::iterator itrTabName = rDoc.maTableNameIndex.find(
+ ScGlobal::pCharClass->upper(rFirstTabName));
+ if (itrTabName == rDoc.maTableNameIndex.end())
+ {
+ // table index not found.
+ return;
+ }
+
+ size_t nTab1 = itrTabName->second;
+ SCROW nRow1 = rRange.aStart.Row(), nRow2 = rRange.aEnd.Row();
+ SCCOL nCol1 = rRange.aStart.Col(), nCol2 = rRange.aEnd.Col();
+ vector<SingleRangeData>::const_iterator itrDataBeg = rData.begin(), itrDataEnd = rData.end();
+ for (vector<SingleRangeData>::const_iterator itrData = itrDataBeg; itrData != itrDataEnd; ++itrData)
+ {
+ size_t i = nTab1 + ::std::distance(itrDataBeg, itrData);
+ TableTypeRef& pTabData = rDoc.maTables[i];
+ if (!pTabData.get())
+ pTabData.reset(new Table);
+
+ for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
+ {
+ for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+ {
+ SCSIZE nC = nCol - nCol1, nR = nRow - nRow1;
+ TokenRef pToken;
+ const ScMatrixRef& pMat = itrData->mpRangeData;
+ if (pMat->IsValue(nC, nR))
+ pToken.reset(new ScDoubleToken(pMat->GetDouble(nC, nR)));
+ else if (pMat->IsString(nC, nR))
+ pToken.reset(new ScStringToken(pMat->GetString(nC, nR)));
+ else
+ pToken.reset(new ScEmptyCellToken(false, false));
+
+ pTabData->setCell(nCol, nRow, pToken);
+ }
+ }
+ }
+
+ rDoc.maRangeArrays.insert(RangeArrayMap::value_type(rRange, pArray));
+}
+
+bool ScExternalRefCache::isDocInitialized(sal_uInt16 nFileId)
+{
+ DocItem* pDoc = getDocItem(nFileId);
+ if (!pDoc)
+ return false;
+
+ return pDoc->mbInitFromSource;
+}
+
+static bool lcl_getTableDataIndex(const ScExternalRefCache::TableNameIndexMap& rMap, const String& rName, size_t& rIndex)
+{
+ ScExternalRefCache::TableNameIndexMap::const_iterator itr = rMap.find(rName);
+ if (itr == rMap.end())
+ return false;
+
+ rIndex = itr->second;
+ return true;
+}
+
+void ScExternalRefCache::initializeDoc(sal_uInt16 nFileId, const vector<String>& rTabNames)
+{
+ DocItem* pDoc = getDocItem(nFileId);
+ if (!pDoc)
+ return;
+
+ size_t n = rTabNames.size();
+
+ // table name list - the list must include all table names in the source
+ // document and only to be populated when loading the source document, not
+ // when loading cached data from, say, Excel XCT/CRN records.
+ vector<TableName> aNewTabNames;
+ aNewTabNames.reserve(n);
+ for (vector<String>::const_iterator itr = rTabNames.begin(), itrEnd = rTabNames.end();
+ itr != itrEnd; ++itr)
+ {
+ TableName aNameItem(ScGlobal::pCharClass->upper(*itr), *itr);
+ aNewTabNames.push_back(aNameItem);
+ }
+ pDoc->maTableNames.swap(aNewTabNames);
+
+ // data tables - preserve any existing data that may have been set during
+ // file import.
+ vector<TableTypeRef> aNewTables(n);
+ for (size_t i = 0; i < n; ++i)
+ {
+ size_t nIndex;
+ if (lcl_getTableDataIndex(pDoc->maTableNameIndex, pDoc->maTableNames[i].maUpperName, nIndex))
+ {
+ aNewTables[i] = pDoc->maTables[nIndex];
+ }
+ }
+ pDoc->maTables.swap(aNewTables);
+
+ // name index map
+ TableNameIndexMap aNewNameIndex;
+ for (size_t i = 0; i < n; ++i)
+ aNewNameIndex.insert(TableNameIndexMap::value_type(pDoc->maTableNames[i].maUpperName, i));
+ pDoc->maTableNameIndex.swap(aNewNameIndex);
+
+ pDoc->mbInitFromSource = true;
+}
+
+String ScExternalRefCache::getTableName(sal_uInt16 nFileId, size_t nCacheId) const
+{
+ if( DocItem* pDoc = getDocItem( nFileId ) )
+ if( nCacheId < pDoc->maTableNames.size() )
+ return pDoc->maTableNames[ nCacheId ].maRealName;
+ return EMPTY_STRING;
+}
+
+void ScExternalRefCache::getAllTableNames(sal_uInt16 nFileId, vector<String>& rTabNames) const
+{
+ rTabNames.clear();
+ DocItem* pDoc = getDocItem(nFileId);
+ if (!pDoc)
+ return;
+
+ size_t n = pDoc->maTableNames.size();
+ rTabNames.reserve(n);
+ for (vector<TableName>::const_iterator itr = pDoc->maTableNames.begin(), itrEnd = pDoc->maTableNames.end();
+ itr != itrEnd; ++itr)
+ rTabNames.push_back(itr->maRealName);
+}
+
+SCsTAB ScExternalRefCache::getTabSpan( sal_uInt16 nFileId, const String& rStartTabName, const String& rEndTabName ) const
+{
+ DocItem* pDoc = getDocItem(nFileId);
+ if (!pDoc)
+ return -1;
+
+ vector<TableName>::const_iterator itrBeg = pDoc->maTableNames.begin();
+ vector<TableName>::const_iterator itrEnd = pDoc->maTableNames.end();
+
+ vector<TableName>::const_iterator itrStartTab = ::std::find_if( itrBeg, itrEnd,
+ TabNameSearchPredicate( rStartTabName));
+ if (itrStartTab == itrEnd)
+ return -1;
+
+ vector<TableName>::const_iterator itrEndTab = ::std::find_if( itrBeg, itrEnd,
+ TabNameSearchPredicate( rEndTabName));
+ if (itrEndTab == itrEnd)
+ return 0;
+
+ size_t nStartDist = ::std::distance( itrBeg, itrStartTab);
+ size_t nEndDist = ::std::distance( itrBeg, itrEndTab);
+ return nStartDist <= nEndDist ? nEndDist - nStartDist + 1 : -(nStartDist - nEndDist + 1);
+}
+
+void ScExternalRefCache::getAllNumberFormats(vector<sal_uInt32>& rNumFmts) const
+{
+ using ::std::sort;
+ using ::std::unique;
+
+ vector<sal_uInt32> aNumFmts;
+ for (DocDataType::const_iterator itrDoc = maDocs.begin(), itrDocEnd = maDocs.end();
+ itrDoc != itrDocEnd; ++itrDoc)
+ {
+ const vector<TableTypeRef>& rTables = itrDoc->second.maTables;
+ for (vector<TableTypeRef>::const_iterator itrTab = rTables.begin(), itrTabEnd = rTables.end();
+ itrTab != itrTabEnd; ++itrTab)
+ {
+ TableTypeRef pTab = *itrTab;
+ if (!pTab)
+ continue;
+
+ pTab->getAllNumberFormats(aNumFmts);
+ }
+ }
+
+ // remove duplicates.
+ sort(aNumFmts.begin(), aNumFmts.end());
+ aNumFmts.erase(unique(aNumFmts.begin(), aNumFmts.end()), aNumFmts.end());
+ rNumFmts.swap(aNumFmts);
+}
+
+bool ScExternalRefCache::hasCacheTable(sal_uInt16 nFileId, const String& rTabName) const
+{
+ DocItem* pDoc = getDocItem(nFileId);
+ if (!pDoc)
+ return false;
+
+ String aUpperName = ScGlobal::pCharClass->upper(rTabName);
+ vector<TableName>::const_iterator itrBeg = pDoc->maTableNames.begin(), itrEnd = pDoc->maTableNames.end();
+ vector<TableName>::const_iterator itr = ::std::find_if(
+ itrBeg, itrEnd, TabNameSearchPredicate(aUpperName));
+
+ return itr != itrEnd;
+}
+
+size_t ScExternalRefCache::getCacheTableCount(sal_uInt16 nFileId) const
+{
+ DocItem* pDoc = getDocItem(nFileId);
+ return pDoc ? pDoc->maTables.size() : 0;
+}
+
+ScExternalRefCache::TableTypeRef ScExternalRefCache::getCacheTable(sal_uInt16 nFileId, size_t nTabIndex) const
+{
+ DocItem* pDoc = getDocItem(nFileId);
+ if (!pDoc || nTabIndex >= pDoc->maTables.size())
+ return TableTypeRef();
+
+ return pDoc->maTables[nTabIndex];
+}
+
+ScExternalRefCache::TableTypeRef ScExternalRefCache::getCacheTable(sal_uInt16 nFileId, const String& rTabName, bool bCreateNew, size_t* pnIndex)
+{
+ DocItem* pDoc = getDocItem(nFileId);
+ if (!pDoc)
+ return TableTypeRef();
+
+ DocItem& rDoc = *pDoc;
+
+ size_t nIndex;
+ String aTabNameUpper = ScGlobal::pCharClass->upper(rTabName);
+ if (lcl_getTableDataIndex(rDoc.maTableNameIndex, aTabNameUpper, nIndex))
+ {
+ // specified table found.
+ if( pnIndex ) *pnIndex = nIndex;
+ return rDoc.maTables[nIndex];
+ }
+
+ if (!bCreateNew)
+ return TableTypeRef();
+
+ // Specified table doesn't exist yet. Create one.
+ nIndex = rDoc.maTables.size();
+ if( pnIndex ) *pnIndex = nIndex;
+ TableTypeRef pTab(new Table);
+ rDoc.maTables.push_back(pTab);
+ rDoc.maTableNames.push_back(TableName(aTabNameUpper, rTabName));
+ rDoc.maTableNameIndex.insert(
+ TableNameIndexMap::value_type(aTabNameUpper, nIndex));
+ return pTab;
+}
+
+void ScExternalRefCache::clearCache(sal_uInt16 nFileId)
+{
+ maDocs.erase(nFileId);
+}
+
+ScExternalRefCache::DocItem* ScExternalRefCache::getDocItem(sal_uInt16 nFileId) const
+{
+ using ::std::pair;
+ DocDataType::iterator itrDoc = maDocs.find(nFileId);
+ if (itrDoc == maDocs.end())
+ {
+ // specified document is not cached.
+ pair<DocDataType::iterator, bool> res = maDocs.insert(
+ DocDataType::value_type(nFileId, DocItem()));
+
+ if (!res.second)
+ // insertion failed.
+ return NULL;
+
+ itrDoc = res.first;
+ }
+
+ return &itrDoc->second;
+}
+
+// ============================================================================
+
+ScExternalRefLink::ScExternalRefLink(ScDocument* pDoc, sal_uInt16 nFileId, const String& rFilter) :
+ ::sfx2::SvBaseLink(::sfx2::LINKUPDATE_ONCALL, FORMAT_FILE),
+ mnFileId(nFileId),
+ maFilterName(rFilter),
+ mpDoc(pDoc),
+ mbDoRefresh(true)
+{
+}
+
+ScExternalRefLink::~ScExternalRefLink()
+{
+}
+
+void ScExternalRefLink::Closed()
+{
+ ScExternalRefManager* pMgr = mpDoc->GetExternalRefManager();
+ pMgr->removeSrcDocument(mnFileId, true);
+}
+
+void ScExternalRefLink::DataChanged(const String& /*rMimeType*/, const Any& /*rValue*/)
+{
+ if (!mbDoRefresh)
+ return;
+
+ String aFile, aFilter;
+ mpDoc->GetLinkManager()->GetDisplayNames(this, NULL, &aFile, NULL, &aFilter);
+ ScExternalRefManager* pMgr = mpDoc->GetExternalRefManager();
+ const String* pCurFile = pMgr->getExternalFileName(mnFileId);
+ if (!pCurFile)
+ return;
+
+ if (pCurFile->Equals(aFile))
+ {
+ // Refresh the current source document.
+ pMgr->refreshNames(mnFileId);
+ }
+ else
+ {
+ // The source document has changed.
+ pMgr->switchSrcFile(mnFileId, aFile);
+ maFilterName = aFilter;
+ }
+}
+
+void ScExternalRefLink::Edit(Window* pParent, const Link& /*rEndEditHdl*/)
+{
+ SvBaseLink::Edit(pParent, LINK(this, ScExternalRefLink, ExternalRefEndEditHdl));
+}
+
+void ScExternalRefLink::SetDoReferesh(bool b)
+{
+ mbDoRefresh = b;
+}
+
+IMPL_LINK( ScExternalRefLink, ExternalRefEndEditHdl, ::sfx2::SvBaseLink*, EMPTYARG )
+{
+ return 0;
+}
+
+// ============================================================================
+
+static ScToken* lcl_convertToToken(ScBaseCell* pCell)
+{
+ if (!pCell || pCell->HasEmptyData())
+ {
+ bool bInherited = (pCell && pCell->GetCellType() == CELLTYPE_FORMULA);
+ return new ScEmptyCellToken( bInherited, false);
+ }
+
+ switch (pCell->GetCellType())
+ {
+ case CELLTYPE_EDIT:
+ {
+ String aStr;
+ static_cast<ScEditCell*>(pCell)->GetString(aStr);
+ return new ScStringToken(aStr);
+ }
+ //break;
+ case CELLTYPE_STRING:
+ {
+ String aStr;
+ static_cast<ScStringCell*>(pCell)->GetString(aStr);
+ return new ScStringToken(aStr);
+ }
+ //break;
+ case CELLTYPE_VALUE:
+ {
+ double fVal = static_cast<ScValueCell*>(pCell)->GetValue();
+ return new ScDoubleToken(fVal);
+ }
+ //break;
+ case CELLTYPE_FORMULA:
+ {
+ ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell);
+ USHORT nError = pFCell->GetErrCode();
+ if (nError)
+ return new ScErrorToken( nError);
+ else if (pFCell->IsValue())
+ {
+ double fVal = pFCell->GetValue();
+ return new ScDoubleToken(fVal);
+ }
+ else
+ {
+ String aStr;
+ pFCell->GetString(aStr);
+ return new ScStringToken(aStr);
+ }
+ }
+ //break;
+ default:
+ DBG_ERROR("attempted to convert an unknown cell type.");
+ }
+
+ return NULL;
+}
+
+static ScTokenArray* lcl_convertToTokenArray(ScDocument* pSrcDoc, const ScRange& rRange,
+ vector<ScExternalRefCache::SingleRangeData>& rCacheData)
+{
+ const ScAddress& s = rRange.aStart;
+ const ScAddress& e = rRange.aEnd;
+
+ SCTAB nTab1 = s.Tab(), nTab2 = e.Tab();
+ SCCOL nCol1 = s.Col(), nCol2 = e.Col();
+ SCROW nRow1 = s.Row(), nRow2 = e.Row();
+
+ if (nTab2 != nTab1)
+ // For now, we don't support multi-sheet ranges intentionally because
+ // we don't have a way to express them in a single token. In the
+ // future we can introduce a new stack variable type svMatrixList with
+ // a new token type that can store a 3D matrix value and convert a 3D
+ // range to it.
+ return NULL;
+
+ 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)
+ {
+ ScMatrixRef xMat = new ScMatrix(
+ static_cast<SCSIZE>(nCol2-nCol1+1),
+ static_cast<SCSIZE>(nRow2-nRow1+1));
+
+ for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+ {
+ for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
+ {
+ SCSIZE nC = nCol - nCol1, nR = nRow - nRow1;
+ ScBaseCell* pCell;
+ pSrcDoc->GetCell(nCol, nRow, nTab, pCell);
+ if (!pCell || pCell->HasEmptyData())
+ xMat->PutEmpty(nC, nR);
+ else
+ {
+ switch (pCell->GetCellType())
+ {
+ case CELLTYPE_EDIT:
+ {
+ String aStr;
+ static_cast<ScEditCell*>(pCell)->GetString(aStr);
+ xMat->PutString(aStr, nC, nR);
+ }
+ break;
+ case CELLTYPE_STRING:
+ {
+ String aStr;
+ static_cast<ScStringCell*>(pCell)->GetString(aStr);
+ xMat->PutString(aStr, nC, nR);
+ }
+ break;
+ case CELLTYPE_VALUE:
+ {
+ double fVal = static_cast<ScValueCell*>(pCell)->GetValue();
+ xMat->PutDouble(fVal, nC, nR);
+ }
+ break;
+ case CELLTYPE_FORMULA:
+ {
+ ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell);
+ USHORT nError = pFCell->GetErrCode();
+ if (nError)
+ xMat->PutDouble( CreateDoubleError( nError), nC, nR);
+ else if (pFCell->IsValue())
+ {
+ double fVal = pFCell->GetValue();
+ xMat->PutDouble(fVal, nC, nR);
+ }
+ else
+ {
+ String aStr;
+ pFCell->GetString(aStr);
+ xMat->PutString(aStr, nC, nR);
+ }
+ }
+ break;
+ default:
+ DBG_ERROR("attempted to convert an unknown cell type.");
+ }
+ }
+ }
+ }
+ if (!bFirstTab)
+ pArray->AddOpCode(ocSep);
+
+ ScMatrix* pMat2 = xMat;
+ ScMatrixToken aToken(pMat2);
+ pArray->AddToken(aToken);
+
+ itrCache->mpRangeData = xMat;
+
+ bFirstTab = false;
+ }
+ return pArray.release();
+}
+
+ScExternalRefManager::ScExternalRefManager(ScDocument* pDoc) :
+ mpDoc(pDoc)
+{
+ maSrcDocTimer.SetTimeoutHdl( LINK(this, ScExternalRefManager, TimeOutHdl) );
+ maSrcDocTimer.SetTimeout(SRCDOC_SCAN_INTERVAL);
+}
+
+ScExternalRefManager::~ScExternalRefManager()
+{
+ clear();
+}
+
+String ScExternalRefManager::getCacheTableName(sal_uInt16 nFileId, size_t nTabIndex) const
+{
+ return maRefCache.getTableName(nFileId, nTabIndex);
+}
+
+ScExternalRefCache::TableTypeRef ScExternalRefManager::getCacheTable(sal_uInt16 nFileId, size_t nTabIndex) const
+{
+ return maRefCache.getCacheTable(nFileId, nTabIndex);
+}
+
+ScExternalRefCache::TableTypeRef ScExternalRefManager::getCacheTable(sal_uInt16 nFileId, const String& rTabName, bool bCreateNew, size_t* pnIndex)
+{
+ return maRefCache.getCacheTable(nFileId, rTabName, bCreateNew, pnIndex);
+}
+
+// ============================================================================
+
+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();
+ 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)
+{
+ list<TabItemRef>::iterator itr = getTabPos(nPos);
+ if (itr == maTables.end())
+ // nothing to remove.
+ return;
+
+ maTables.erase(itr);
+}
+
+void ScExternalRefManager::RefCells::refreshAllCells(ScExternalRefManager& rRefMgr)
+{
+ // 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);
+ }
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+void ScExternalRefManager::getAllCachedTableNames(sal_uInt16 nFileId, vector<String>& rTabNames) const
+{
+ maRefCache.getAllTableNames(nFileId, rTabNames);
+}
+
+SCsTAB ScExternalRefManager::getCachedTabSpan( sal_uInt16 nFileId, const String& rStartTabName, const String& rEndTabName ) const
+{
+ return maRefCache.getTabSpan( nFileId, rStartTabName, rEndTabName);
+}
+
+void ScExternalRefManager::getAllCachedNumberFormats(vector<sal_uInt32>& rNumFmts) const
+{
+ maRefCache.getAllNumberFormats(rNumFmts);
+}
+
+bool ScExternalRefManager::hasCacheTable(sal_uInt16 nFileId, const String& rTabName) const
+{
+ return maRefCache.hasCacheTable(nFileId, rTabName);
+}
+
+size_t ScExternalRefManager::getCacheTableCount(sal_uInt16 nFileId) const
+{
+ return maRefCache.getCacheTableCount(nFileId);
+}
+
+sal_uInt16 ScExternalRefManager::getExternalFileCount() const
+{
+ return static_cast< sal_uInt16 >( maSrcFiles.size() );
+}
+
+void ScExternalRefManager::storeRangeNameTokens(sal_uInt16 nFileId, const String& rName, const ScTokenArray& rArray)
+{
+ ScExternalRefCache::TokenArrayRef pArray(rArray.Clone());
+ maRefCache.setRangeNameTokens(nFileId, rName, pArray);
+}
+
+ScExternalRefCache::TokenRef ScExternalRefManager::getSingleRefToken(
+ sal_uInt16 nFileId, const String& rTabName, const ScAddress& rCell,
+ const ScAddress* pCurPos, SCTAB* pTab, ScExternalRefCache::CellFormat* pFmt)
+{
+ if (pCurPos)
+ insertRefCell(nFileId, *pCurPos);
+
+ maybeLinkExternalFile(nFileId);
+
+ if (pTab)
+ *pTab = -1;
+
+ if (pFmt)
+ pFmt->mbIsSet = false;
+
+ // Check if the given table name and the cell position is cached.
+ sal_uInt32 nFmtIndex = 0;
+ ScExternalRefCache::TokenRef pToken = maRefCache.getCellData(
+ nFileId, rTabName, rCell.Row(), rCell.Col(), &nFmtIndex);
+ if (pToken)
+ {
+ if (pFmt)
+ {
+ short nFmtType = mpDoc->GetFormatTable()->GetType(nFmtIndex);
+ if (nFmtType != NUMBERFORMAT_UNDEFINED)
+ {
+ pFmt->mbIsSet = true;
+ pFmt->mnIndex = nFmtIndex;
+ pFmt->mnType = nFmtType;
+ }
+ }
+ return pToken;
+ }
+
+ // reference not cached. read from the source document.
+ ScDocument* pSrcDoc = getSrcDocument(nFileId);
+ if (!pSrcDoc)
+ {
+ return ScExternalRefCache::TokenRef();
+ }
+
+ ScBaseCell* pCell = NULL;
+ SCTAB nTab;
+ if (!pSrcDoc->GetTable(rTabName, nTab))
+ {
+ // specified table name doesn't exist in the source document.
+ return ScExternalRefCache::TokenRef();
+ }
+
+ if (pTab)
+ *pTab = nTab;
+
+ pSrcDoc->GetCell(rCell.Col(), rCell.Row(), nTab, pCell);
+ ScExternalRefCache::TokenRef pTok(lcl_convertToToken(pCell));
+
+ pSrcDoc->GetNumberFormat(rCell.Col(), rCell.Row(), nTab, nFmtIndex);
+ nFmtIndex = getMappedNumberFormat(nFileId, nFmtIndex, pSrcDoc);
+ if (pFmt)
+ {
+ short nFmtType = mpDoc->GetFormatTable()->GetType(nFmtIndex);
+ if (nFmtType != NUMBERFORMAT_UNDEFINED)
+ {
+ pFmt->mbIsSet = true;
+ pFmt->mnIndex = nFmtIndex;
+ pFmt->mnType = nFmtType;
+ }
+ }
+
+ if (!pTok.get())
+ {
+ // Generate an error for unresolvable cells.
+ pTok.reset( new ScErrorToken( errNoValue));
+ }
+
+ // Now, insert the token into cache table.
+ maRefCache.setCellData(nFileId, rTabName, rCell.Row(), rCell.Col(), pTok, nFmtIndex);
+ return pTok;
+}
+
+ScExternalRefCache::TokenArrayRef ScExternalRefManager::getDoubleRefTokens(sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange, const ScAddress* pCurPos)
+{
+ if (pCurPos)
+ insertRefCell(nFileId, *pCurPos);
+
+ maybeLinkExternalFile(nFileId);
+
+ // Check if the given table name and the cell position is cached.
+ ScExternalRefCache::TokenArrayRef p = maRefCache.getCellRangeData(nFileId, rTabName, rRange);
+ if (p.get())
+ return p;
+
+ ScDocument* pSrcDoc = getSrcDocument(nFileId);
+ if (!pSrcDoc)
+ return ScExternalRefCache::TokenArrayRef();
+
+ SCTAB nTab1;
+ if (!pSrcDoc->GetTable(rTabName, nTab1))
+ // specified table name doesn't exist in the source document.
+ return ScExternalRefCache::TokenArrayRef();
+
+ ScRange aRange(rRange);
+ SCTAB nTabSpan = aRange.aEnd.Tab() - aRange.aStart.Tab();
+
+ vector<ScExternalRefCache::SingleRangeData> aCacheData;
+ aCacheData.reserve(nTabSpan+1);
+ aCacheData.push_back(ScExternalRefCache::SingleRangeData());
+ aCacheData.back().maTableName = ScGlobal::pCharClass->upper(rTabName);
+
+ for (SCTAB i = 1; i < nTabSpan + 1; ++i)
+ {
+ String aTabName;
+ if (!pSrcDoc->GetName(nTab1 + 1, aTabName))
+ // source document doesn't have any table by the specified name.
+ break;
+
+ aCacheData.push_back(ScExternalRefCache::SingleRangeData());
+ aCacheData.back().maTableName = ScGlobal::pCharClass->upper(aTabName);
+ }
+
+ 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);
+
+ return pArray;
+}
+
+ScExternalRefCache::TokenArrayRef ScExternalRefManager::getRangeNameTokens(sal_uInt16 nFileId, const String& rName, const ScAddress* pCurPos)
+{
+ if (pCurPos)
+ insertRefCell(nFileId, *pCurPos);
+
+ maybeLinkExternalFile(nFileId);
+
+ ScExternalRefCache::TokenArrayRef pArray = maRefCache.getRangeNameTokens(nFileId, rName);
+ if (pArray.get())
+ return pArray;
+
+ ScDocument* pSrcDoc = getSrcDocument(nFileId);
+ if (!pSrcDoc)
+ return ScExternalRefCache::TokenArrayRef();
+
+ ScRangeName* pExtNames = pSrcDoc->GetRangeName();
+ String aUpperName = ScGlobal::pCharClass->upper(rName);
+ USHORT n;
+ bool bRes = pExtNames->SearchNameUpper(aUpperName, n);
+ if (!bRes)
+ return ScExternalRefCache::TokenArrayRef();
+
+ ScRangeData* pRangeData = (*pExtNames)[n];
+ if (!pRangeData)
+ return ScExternalRefCache::TokenArrayRef();
+
+ // Parse all tokens in this external range data, and replace each absolute
+ // reference token with an external reference token, and cache them. Also
+ // register the source document with the link manager if it's a new
+ // source.
+
+ ScExternalRefCache::TokenArrayRef pNew(new ScTokenArray);
+
+ ScTokenArray* pCode = pRangeData->GetCode();
+ for (ScToken* pToken = pCode->First(); pToken; pToken = pCode->Next())
+ {
+ bool bTokenAdded = false;
+ switch (pToken->GetType())
+ {
+ case svSingleRef:
+ {
+ const SingleRefData& rRef = pToken->GetSingleRef();
+ String aTabName;
+ pSrcDoc->GetName(rRef.nTab, aTabName);
+ ScExternalSingleRefToken aNewToken(nFileId, aTabName, pToken->GetSingleRef());
+ pNew->AddToken(aNewToken);
+ bTokenAdded = true;
+ }
+ break;
+ case svDoubleRef:
+ {
+ const SingleRefData& rRef = pToken->GetSingleRef();
+ String aTabName;
+ pSrcDoc->GetName(rRef.nTab, aTabName);
+ ScExternalDoubleRefToken aNewToken(nFileId, aTabName, pToken->GetDoubleRef());
+ pNew->AddToken(aNewToken);
+ bTokenAdded = true;
+ }
+ break;
+ default:
+ ; // nothing
+ }
+
+ if (!bTokenAdded)
+ pNew->AddToken(*pToken);
+ }
+
+ // Make sure to pass the correctly-cased range name here.
+ maRefCache.setRangeNameTokens(nFileId, pRangeData->GetName(), pNew);
+ return pNew;
+}
+
+void ScExternalRefManager::refreshAllRefCells(sal_uInt16 nFileId)
+{
+ RefCellMap::iterator itrFile = maRefCells.find(nFileId);
+ if (itrFile == maRefCells.end())
+ return;
+
+ RefCells& rRefCells = itrFile->second;
+ rRefCells.refreshAllCells(*this);
+
+ ScViewData* pViewData = ScDocShell::GetViewData();
+ if (!pViewData)
+ return;
+
+ ScTabViewShell* pVShell = pViewData->GetViewShell();
+ if (!pVShell)
+ return;
+
+ // Repainting the grid also repaints the texts, but is there a better way
+ // to refresh texts?
+ pVShell->Invalidate(FID_REPAINT);
+ pVShell->PaintGrid();
+}
+
+void ScExternalRefManager::insertRefCell(sal_uInt16 nFileId, const ScAddress& rCell)
+{
+ RefCellMap::iterator itr = maRefCells.find(nFileId);
+ if (itr == maRefCells.end())
+ {
+ RefCells aRefCells;
+ pair<RefCellMap::iterator, bool> r = maRefCells.insert(
+ RefCellMap::value_type(nFileId, aRefCells));
+ if (!r.second)
+ // insertion failed.
+ return;
+
+ itr = r.first;
+ }
+ itr->second.insertCell(rCell);
+}
+
+ScDocument* ScExternalRefManager::getSrcDocument(sal_uInt16 nFileId)
+{
+ if (!mpDoc->IsExecuteLinkEnabled())
+ return NULL;
+
+ DocShellMap::iterator itrEnd = maDocShells.end();
+ DocShellMap::iterator itr = maDocShells.find(nFileId);
+
+ if (itr != itrEnd)
+ {
+ SfxObjectShell* p = itr->second.maShell;
+ itr->second.maLastAccess = Time();
+ return static_cast<ScDocShell*>(p)->GetDocument();
+ }
+
+ const String* pFile = getExternalFileName(nFileId);
+ if (!pFile)
+ // no file name associated with this ID.
+ return NULL;
+
+ String aFilter;
+ SrcShell aSrcDoc;
+ aSrcDoc.maShell = loadSrcDocument(nFileId, aFilter);
+ if (!aSrcDoc.maShell.Is())
+ {
+ // source document could not be loaded.
+ return NULL;
+ }
+
+ if (maDocShells.empty())
+ {
+ // If this is the first source document insertion, start up the timer.
+ maSrcDocTimer.Start();
+ }
+
+ maDocShells.insert(DocShellMap::value_type(nFileId, aSrcDoc));
+ SfxObjectShell* p = aSrcDoc.maShell;
+ ScDocument* pSrcDoc = static_cast<ScDocShell*>(p)->GetDocument();
+
+ SCTAB nTabCount = pSrcDoc->GetTableCount();
+ if (!maRefCache.isDocInitialized(nFileId) && nTabCount)
+ {
+ // Populate the cache with all table names in the source document.
+ vector<String> aTabNames;
+ aTabNames.reserve(nTabCount);
+ for (SCTAB i = 0; i < nTabCount; ++i)
+ {
+ String aName;
+ pSrcDoc->GetName(i, aName);
+ aTabNames.push_back(aName);
+ }
+ maRefCache.initializeDoc(nFileId, aTabNames);
+ }
+ return pSrcDoc;
+}
+
+SfxObjectShellRef ScExternalRefManager::loadSrcDocument(sal_uInt16 nFileId, String& rFilter)
+{
+ const SrcFileData* pFileData = getExternalFileData(nFileId);
+ if (!pFileData)
+ return NULL;
+
+ String aFile = pFileData->maFileName;
+ if (!isFileLoadable(aFile))
+ {
+ // The original file path is not loadable. Try the relative path.
+ // Note that the path is relative to the content.xml substream which
+ // is one-level higher than the file itself.
+
+ if (!pFileData->maRelativeName.Len())
+ return NULL;
+
+ INetURLObject aBaseURL(getOwnDocumentName());
+ aBaseURL.insertName(OUString::createFromAscii("content.xml"));
+ bool bWasAbs = false;
+ aFile = aBaseURL.smartRel2Abs(pFileData->maRelativeName, bWasAbs).GetMainURL(INetURLObject::NO_DECODE);
+ if (!isFileLoadable(aFile))
+ // Ok, I've tried both paths but no success. Bail out.
+ return NULL;
+ }
+
+ String aOptions;
+ ScDocumentLoader::GetFilterName(aFile, rFilter, aOptions, true, false);
+ const SfxFilter* pFilter = ScDocShell::Factory().GetFilterContainer()->GetFilter4FilterName(rFilter);
+
+ if (!pFileData->maRelativeName.Len())
+ {
+ // Generate a relative file path.
+ INetURLObject aBaseURL(getOwnDocumentName());
+ aBaseURL.insertName(OUString::createFromAscii("content.xml"));
+
+ String aStr = URIHelper::simpleNormalizedMakeRelative(
+ aBaseURL.GetMainURL(INetURLObject::NO_DECODE), aFile);
+
+ setRelativeFileName(nFileId, aStr);
+ }
+
+ // Update the filter data now that we are loading it again.
+ setFilterData(nFileId, rFilter, aOptions);
+
+ SfxItemSet* pSet = new SfxAllItemSet(SFX_APP()->GetPool());
+ if (aOptions.Len())
+ pSet->Put(SfxStringItem(SID_FILE_FILTEROPTIONS, aOptions));
+
+ auto_ptr<SfxMedium> pMedium(new SfxMedium(aFile, STREAM_STD_READ, false, pFilter, pSet));
+ if (pMedium->GetError() != ERRCODE_NONE)
+ return NULL;
+
+ pMedium->UseInteractionHandler(false);
+
+ ScDocShell* pNewShell = new ScDocShell(SFX_CREATE_MODE_INTERNAL);
+ SfxObjectShellRef aRef = pNewShell;
+
+ // increment the recursive link count of the source document.
+ ScExtDocOptions* pExtOpt = mpDoc->GetExtDocOptions();
+ sal_uInt32 nLinkCount = pExtOpt ? pExtOpt->GetDocSettings().mnLinkCnt : 0;
+ ScDocument* pSrcDoc = pNewShell->GetDocument();
+ ScExtDocOptions* pExtOptNew = pSrcDoc->GetExtDocOptions();
+ if (!pExtOptNew)
+ {
+ pExtOptNew = new ScExtDocOptions;
+ pSrcDoc->SetExtDocOptions(pExtOptNew);
+ }
+ pExtOptNew->GetDocSettings().mnLinkCnt = nLinkCount + 1;
+
+ pNewShell->DoLoad(pMedium.release());
+ return aRef;
+}
+
+bool ScExternalRefManager::isFileLoadable(const String& rFile) const
+{
+ if (isOwnDocument(rFile))
+ return false;
+
+ if (utl::UCBContentHelper::IsFolder(rFile))
+ return false;
+
+ return utl::UCBContentHelper::Exists(rFile);
+}
+
+void ScExternalRefManager::maybeLinkExternalFile(sal_uInt16 nFileId)
+{
+ if (maLinkedDocs.count(nFileId))
+ // file alerady linked.
+ return;
+
+ // Source document not linked yet. Link it now.
+ const String* pFileName = getExternalFileName(nFileId);
+ if (!pFileName)
+ return;
+
+ String aFilter, aOptions;
+ ScDocumentLoader::GetFilterName(*pFileName, aFilter, aOptions, true, false);
+ SvxLinkManager* pLinkMgr = mpDoc->GetLinkManager();
+ ScExternalRefLink* pLink = new ScExternalRefLink(mpDoc, nFileId, aFilter);
+ DBG_ASSERT(pFileName, "ScExternalRefManager::insertExternalFileLink: file name pointer is NULL");
+ pLinkMgr->InsertFileLink(*pLink, OBJECT_CLIENT_FILE, *pFileName, &aFilter);
+
+ pLink->SetDoReferesh(false);
+ pLink->Update();
+ pLink->SetDoReferesh(true);
+
+ maLinkedDocs.insert(nFileId);
+}
+
+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();
+ if (!pShell)
+ // This should not happen!
+ return EMPTY_STRING;
+
+ SfxMedium* pMed = pShell->GetMedium();
+ if (!pMed)
+ return EMPTY_STRING;
+
+ return pMed->GetName();
+}
+
+bool ScExternalRefManager::isOwnDocument(const String& rFile) const
+{
+ return getOwnDocumentName().Equals(rFile);
+}
+
+void ScExternalRefManager::convertToAbsName(String& rFile) const
+{
+ SfxObjectShell* pDocShell = mpDoc->GetDocumentShell();
+ rFile = ScGlobal::GetAbsDocName(rFile, pDocShell);
+}
+
+sal_uInt16 ScExternalRefManager::getExternalFileId(const String& rFile)
+{
+ vector<SrcFileData>::const_iterator itrBeg = maSrcFiles.begin(), itrEnd = maSrcFiles.end();
+ vector<SrcFileData>::const_iterator itr = find_if(itrBeg, itrEnd, FindSrcFileByName(rFile));
+ if (itr != itrEnd)
+ {
+ size_t nId = distance(itrBeg, itr);
+ return static_cast<sal_uInt16>(nId);
+ }
+
+ SrcFileData aData;
+ aData.maFileName = rFile;
+ maSrcFiles.push_back(aData);
+ return static_cast<sal_uInt16>(maSrcFiles.size() - 1);
+}
+
+const String* ScExternalRefManager::getExternalFileName(sal_uInt16 nFileId) const
+{
+ if (nFileId >= maSrcFiles.size())
+ return NULL;
+
+ return &maSrcFiles[nFileId].maFileName;
+}
+
+bool ScExternalRefManager::hasExternalFile(sal_uInt16 nFileId) const
+{
+ return nFileId < maSrcFiles.size();
+}
+
+bool ScExternalRefManager::hasExternalFile(const String& rFile) const
+{
+ vector<SrcFileData>::const_iterator itrBeg = maSrcFiles.begin(), itrEnd = maSrcFiles.end();
+ vector<SrcFileData>::const_iterator itr = find_if(itrBeg, itrEnd, FindSrcFileByName(rFile));
+ return itr != itrEnd;
+}
+
+const ScExternalRefManager::SrcFileData* ScExternalRefManager::getExternalFileData(sal_uInt16 nFileId) const
+{
+ if (nFileId >= maSrcFiles.size())
+ return NULL;
+
+ return &maSrcFiles[nFileId];
+}
+
+const String* ScExternalRefManager::getRealTableName(sal_uInt16 nFileId, const String& rTabName) const
+{
+ return maRefCache.getRealTableName(nFileId, rTabName);
+}
+
+const String* ScExternalRefManager::getRealRangeName(sal_uInt16 nFileId, const String& rRangeName) const
+{
+ return maRefCache.getRealRangeName(nFileId, rRangeName);
+}
+
+template<typename MapContainer>
+void lcl_removeByFileId(sal_uInt16 nFileId, MapContainer& rMap)
+{
+ typename MapContainer::iterator itr = rMap.find(nFileId);
+ if (itr != rMap.end())
+ rMap.erase(itr);
+}
+
+void ScExternalRefManager::refreshNames(sal_uInt16 nFileId)
+{
+ removeSrcDocument(nFileId, false);
+
+ // Update all cells containing names from this source document.
+ refreshAllRefCells(nFileId);
+}
+
+void ScExternalRefManager::switchSrcFile(sal_uInt16 nFileId, const String& rNewFile)
+{
+ maSrcFiles[nFileId].maFileName = rNewFile;
+ maSrcFiles[nFileId].maRelativeName.Erase();
+ refreshNames(nFileId);
+}
+
+void ScExternalRefManager::setRelativeFileName(sal_uInt16 nFileId, const String& rRelUrl)
+{
+ if (nFileId >= maSrcFiles.size())
+ return;
+ maSrcFiles[nFileId].maRelativeName = rRelUrl;
+}
+
+void ScExternalRefManager::setFilterData(sal_uInt16 nFileId, const String& rFilterName, const String& rOptions)
+{
+ if (nFileId >= maSrcFiles.size())
+ return;
+ maSrcFiles[nFileId].maFilterName = rFilterName;
+ maSrcFiles[nFileId].maFilterOptions = rOptions;
+}
+
+void ScExternalRefManager::removeSrcDocument(sal_uInt16 nFileId, bool bBreakLink)
+{
+ maRefCache.clearCache(nFileId);
+ lcl_removeByFileId(nFileId, maDocShells);
+
+ if (bBreakLink)
+ maLinkedDocs.erase(nFileId);
+
+ if (maDocShells.empty())
+ maSrcDocTimer.Stop();
+}
+
+void ScExternalRefManager::clear()
+{
+ DocShellMap::iterator itrEnd = maDocShells.end();
+ for (DocShellMap::iterator itr = maDocShells.begin(); itr != itrEnd; ++itr)
+ itr->second.maShell->DoClose();
+
+ maDocShells.clear();
+ maSrcDocTimer.Stop();
+}
+
+bool ScExternalRefManager::hasExternalData() const
+{
+ return !maSrcFiles.empty();
+}
+
+void ScExternalRefManager::resetSrcFileData()
+{
+ INetURLObject aBaseURL(getOwnDocumentName());
+ aBaseURL.insertName(OUString::createFromAscii("content.xml"));
+ String aBaseUrlStr = aBaseURL.GetMainURL(INetURLObject::NO_DECODE);
+ for (vector<SrcFileData>::iterator itr = maSrcFiles.begin(), itrEnd = maSrcFiles.end();
+ itr != itrEnd; ++itr)
+ {
+ if (!itr->maRelativeName.Len())
+ {
+ itr->maRelativeName = URIHelper::simpleNormalizedMakeRelative(
+ aBaseUrlStr, itr->maFileName);
+ }
+ }
+}
+
+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)
+{
+ for (RefCellMap::iterator itr = maRefCells.begin(), itrEnd = maRefCells.end(); itr != itrEnd; ++itr)
+ itr->second.removeTable(nPos);
+}
+
+void ScExternalRefManager::purgeStaleSrcDocument(sal_Int32 nTimeOut)
+{
+ DocShellMap aNewDocShells;
+ DocShellMap::iterator itr = maDocShells.begin(), itrEnd = maDocShells.end();
+ for (; itr != itrEnd; ++itr)
+ {
+ // in 100th of a second.
+ sal_Int32 nSinceLastAccess = (Time() - itr->second.maLastAccess).GetTime();
+ if (nSinceLastAccess < nTimeOut)
+ aNewDocShells.insert(*itr);
+ }
+ maDocShells.swap(aNewDocShells);
+
+ if (maDocShells.empty())
+ maSrcDocTimer.Stop();
+}
+
+sal_uInt32 ScExternalRefManager::getMappedNumberFormat(sal_uInt16 nFileId, sal_uInt32 nNumFmt, ScDocument* pSrcDoc)
+{
+ NumFmtMap::iterator itr = maNumFormatMap.find(nFileId);
+ if (itr == maNumFormatMap.end())
+ {
+ // Number formatter map is not initialized for this external document.
+ pair<NumFmtMap::iterator, bool> r = maNumFormatMap.insert(
+ NumFmtMap::value_type(nFileId, SvNumberFormatterMergeMap()));
+
+ if (!r.second)
+ // insertion failed.
+ return nNumFmt;
+
+ itr = r.first;
+ mpDoc->GetFormatTable()->MergeFormatter( *pSrcDoc->GetFormatTable());
+ SvNumberFormatterMergeMap aMap = mpDoc->GetFormatTable()->ConvertMergeTableToMap();
+ itr->second.swap(aMap);
+ }
+ const SvNumberFormatterMergeMap& rMap = itr->second;
+ SvNumberFormatterMergeMap::const_iterator itrNumFmt = rMap.find(nNumFmt);
+ if (itrNumFmt != rMap.end())
+ // mapped value found.
+ return itrNumFmt->second;
+
+ return nNumFmt;
+}
+
+IMPL_LINK(ScExternalRefManager, TimeOutHdl, AutoTimer*, pTimer)
+{
+ if (pTimer == &maSrcDocTimer)
+ purgeStaleSrcDocument(SRCDOC_LIFE_SPAN);
+
+ return 0;
+}
+
diff --git a/sc/source/ui/docshell/makefile.mk b/sc/source/ui/docshell/makefile.mk
index 51cb4a703d73..a5977243f3c2 100644
--- a/sc/source/ui/docshell/makefile.mk
+++ b/sc/source/ui/docshell/makefile.mk
@@ -8,7 +8,7 @@
#
# $RCSfile: makefile.mk,v $
#
-# $Revision: 1.13 $
+# $Revision: 1.13.134.1 $
#
# This file is part of OpenOffice.org.
#
@@ -53,6 +53,7 @@ CXXFILES = \
docsh6.cxx \
docsh7.cxx \
docsh8.cxx \
+ externalrefmgr.cxx \
tablink.cxx \
arealink.cxx \
dbdocfun.cxx \
@@ -79,6 +80,7 @@ SLOFILES = \
$(SLO)$/docsh6.obj \
$(SLO)$/docsh7.obj \
$(SLO)$/docsh8.obj \
+ $(SLO)$/externalrefmgr.obj \
$(SLO)$/tablink.obj \
$(SLO)$/arealink.obj \
$(SLO)$/dbdocfun.obj \
@@ -101,6 +103,7 @@ EXCEPTIONSFILES= \
$(SLO)$/docsh3.obj \
$(SLO)$/docsh4.obj \
$(SLO)$/docsh8.obj \
+ $(SLO)$/externalrefmgr.obj \
$(SLO)$/dbdocimp.obj
SRS1NAME=$(TARGET)
@@ -117,6 +120,7 @@ LIB1OBJFILES = \
$(SLO)$/docsh6.obj \
$(SLO)$/docsh7.obj \
$(SLO)$/docsh8.obj \
+ $(SLO)$/externalrefmgr.obj \
$(SLO)$/tablink.obj \
$(SLO)$/arealink.obj \
$(SLO)$/dbdocfun.obj \
diff --git a/sc/source/ui/src/globstr.src b/sc/source/ui/src/globstr.src
index 0960f1a2cce8..545684424054 100644
--- a/sc/source/ui/src/globstr.src
+++ b/sc/source/ui/src/globstr.src
@@ -302,6 +302,14 @@ Resource RID_GLOBSTR
{
Text [ en-US ] = "Insert Array Formula" ;
};
+ String STR_UNDO_INSERTNOTE
+ {
+ Text [ en-US ] = "Insert Note" ;
+ };
+ String STR_UNDO_DELETENOTE
+ {
+ Text [ en-US ] = "Delete Note" ;
+ };
String STR_UNDO_SHOWNOTE
{
Text [ en-US ] = "Show Note" ;
diff --git a/sc/source/ui/unoobj/cellsuno.cxx b/sc/source/ui/unoobj/cellsuno.cxx
index 29ab226d7d53..34764c2b66a8 100644
--- a/sc/source/ui/unoobj/cellsuno.cxx
+++ b/sc/source/ui/unoobj/cellsuno.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: cellsuno.cxx,v $
- * $Revision: 1.113 $
+ * $Revision: 1.113.132.2 $
*
* This file is part of OpenOffice.org.
*
@@ -5175,7 +5175,7 @@ uno::Sequence<sheet::FormulaToken> SAL_CALL ScCellRangeObj::getArrayTokens() thr
{
ScTokenArray* pTokenArray = pFCell1->GetCode();
if ( pTokenArray )
- (void)ScTokenConversion::ConvertToTokenSequence( aSequence, *pTokenArray );
+ (void)ScTokenConversion::ConvertToTokenSequence( *pDoc, aSequence, *pTokenArray );
}
}
}
@@ -5197,8 +5197,9 @@ void SAL_CALL ScCellRangeObj::setArrayTokens( const uno::Sequence<sheet::Formula
throw uno::RuntimeException();
}
+ ScDocument* pDoc = pDocSh->GetDocument();
ScTokenArray aTokenArray;
- (void)ScTokenConversion::ConvertToTokenArray( aTokenArray, rTokens );
+ (void)ScTokenConversion::ConvertToTokenArray( *pDoc, aTokenArray, rTokens );
// Actually GRAM_PODF_A1 is a don't-care here because of the token
// array being set, it fits with other API compatibility grammars
@@ -6596,7 +6597,7 @@ uno::Sequence<sheet::FormulaToken> SAL_CALL ScCellObj::getTokens() throw(uno::Ru
{
ScTokenArray* pTokenArray = static_cast<ScFormulaCell*>(pCell)->GetCode();
if ( pTokenArray )
- (void)ScTokenConversion::ConvertToTokenSequence( aSequence, *pTokenArray );
+ (void)ScTokenConversion::ConvertToTokenSequence( *pDoc, aSequence, *pTokenArray );
}
}
return aSequence;
@@ -6610,7 +6611,7 @@ void SAL_CALL ScCellObj::setTokens( const uno::Sequence<sheet::FormulaToken>& rT
{
ScDocument* pDoc = pDocSh->GetDocument();
ScTokenArray aTokenArray;
- (void)ScTokenConversion::ConvertToTokenArray( aTokenArray, rTokens );
+ (void)ScTokenConversion::ConvertToTokenArray( *pDoc, aTokenArray, rTokens );
ScDocFunc aFunc( *pDocSh );
ScBaseCell* pNewCell = new ScFormulaCell( pDoc, aCellPos, &aTokenArray );
diff --git a/sc/source/ui/unoobj/docuno.cxx b/sc/source/ui/unoobj/docuno.cxx
index 85fe13c8b71e..812b3b136760 100644
--- a/sc/source/ui/unoobj/docuno.cxx
+++ b/sc/source/ui/unoobj/docuno.cxx
@@ -120,6 +120,7 @@ const SfxItemPropertyMap* lcl_GetDocOptPropertyMap()
{MAP_CHAR_LEN(SC_UNO_COLLABELRNG), 0, &getCppuType((uno::Reference<sheet::XLabelRanges>*)0), 0, 0},
{MAP_CHAR_LEN(SC_UNO_DDELINKS), 0, &getCppuType((uno::Reference<container::XNameAccess>*)0), 0, 0},
{MAP_CHAR_LEN(SC_UNO_DEFTABSTOP), 0, &getCppuType((sal_Int16*)0), 0, 0},
+ {MAP_CHAR_LEN(SC_UNO_EXTERNALDOCLINKS), 0, &getCppuType((uno::Reference<sheet::XExternalDocLinks>*)0), 0, 0},
{MAP_CHAR_LEN(SC_UNO_FORBIDDEN), 0, &getCppuType((uno::Reference<i18n::XForbiddenCharacters>*)0), beans::PropertyAttribute::READONLY, 0},
{MAP_CHAR_LEN(SC_UNO_HASDRAWPAGES), 0, &getBooleanCppuType(), beans::PropertyAttribute::READONLY, 0},
{MAP_CHAR_LEN(SC_UNO_IGNORECASE), 0, &getBooleanCppuType(), 0, 0},
@@ -1509,6 +1510,10 @@ uno::Any SAL_CALL ScModelObj::getPropertyValue( const rtl::OUString& aPropertyNa
{
aRet <<= uno::Reference<container::XNameAccess>(new ScDDELinksObj( pDocShell ));
}
+ else if ( aString.EqualsAscii( SC_UNO_EXTERNALDOCLINKS ) )
+ {
+ aRet <<= uno::Reference<sheet::XExternalDocLinks>(new ScExternalDocLinksObj(pDocShell));
+ }
else if ( aString.EqualsAscii( SC_UNO_SHEETLINKS ) )
{
aRet <<= uno::Reference<container::XNameAccess>(new ScSheetLinksObj( pDocShell ));
diff --git a/sc/source/ui/unoobj/fmtuno.cxx b/sc/source/ui/unoobj/fmtuno.cxx
index 7e4d26b03840..20560509e669 100644
--- a/sc/source/ui/unoobj/fmtuno.cxx
+++ b/sc/source/ui/unoobj/fmtuno.cxx
@@ -197,14 +197,14 @@ void ScTableConditionalFormat::FillFormat( ScConditionalFormat& rFormat,
if ( aData.maTokens1.getLength() )
{
ScTokenArray aTokenArray;
- if ( ScTokenConversion::ConvertToTokenArray(aTokenArray, aData.maTokens1) )
+ if ( ScTokenConversion::ConvertToTokenArray(*pDoc, aTokenArray, aData.maTokens1) )
aCoreEntry.SetFormula1(aTokenArray);
}
if ( aData.maTokens2.getLength() )
{
ScTokenArray aTokenArray;
- if ( ScTokenConversion::ConvertToTokenArray(aTokenArray, aData.maTokens2) )
+ if ( ScTokenConversion::ConvertToTokenArray(*pDoc, aTokenArray, aData.maTokens2) )
aCoreEntry.SetFormula2(aTokenArray);
}
rFormat.AddEntry( aCoreEntry );
@@ -660,14 +660,14 @@ ScValidationData* ScTableValidationObj::CreateValidationData( ScDocument* pDoc,
if ( aTokens1.getLength() )
{
ScTokenArray aTokenArray;
- if ( ScTokenConversion::ConvertToTokenArray(aTokenArray, aTokens1) )
+ if ( ScTokenConversion::ConvertToTokenArray(*pDoc, aTokenArray, aTokens1) )
pRet->SetFormula1(aTokenArray);
}
if ( aTokens2.getLength() )
{
ScTokenArray aTokenArray;
- if ( ScTokenConversion::ConvertToTokenArray(aTokenArray, aTokens2) )
+ if ( ScTokenConversion::ConvertToTokenArray(*pDoc, aTokenArray, aTokens2) )
pRet->SetFormula2(aTokenArray);
}
diff --git a/sc/source/ui/unoobj/linkuno.cxx b/sc/source/ui/unoobj/linkuno.cxx
index 63b1a578f305..39f91e4cc853 100644
--- a/sc/source/ui/unoobj/linkuno.cxx
+++ b/sc/source/ui/unoobj/linkuno.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: linkuno.cxx,v $
- * $Revision: 1.18 $
+ * $Revision: 1.18.134.11 $
*
* This file is part of OpenOffice.org.
*
@@ -48,8 +48,21 @@
#include "hints.hxx"
#include "unonames.hxx"
#include "rangeseq.hxx"
+#include "token.hxx"
+
+#include <vector>
+#include <climits>
using namespace com::sun::star;
+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::lang::IllegalArgumentException;
+using ::com::sun::star::uno::RuntimeException;
+using ::rtl::OUString;
+using ::std::vector;
//------------------------------------------------------------------------
@@ -1480,4 +1493,327 @@ uno::Reference< sheet::XDDELink > ScDDELinksObj::addDDELink(
return xLink;
}
-//------------------------------------------------------------------------
+// ============================================================================
+
+ScExternalSheetCacheObj::ScExternalSheetCacheObj(ScExternalRefCache::TableTypeRef pTable, size_t nIndex) :
+ mpTable(pTable),
+ mnIndex(nIndex)
+{
+}
+
+ScExternalSheetCacheObj::~ScExternalSheetCacheObj()
+{
+}
+
+void SAL_CALL ScExternalSheetCacheObj::setCellValue(sal_Int32 nCol, sal_Int32 nRow, const Any& rValue)
+ throw (IllegalArgumentException, RuntimeException)
+{
+ ScUnoGuard aGuard;
+ if (nRow < 0 || nCol < 0)
+ throw IllegalArgumentException();
+
+ ScExternalRefCache::TokenRef pToken;
+ double fVal;
+ OUString aVal;
+ if (rValue >>= fVal)
+ pToken.reset(new ScDoubleToken(fVal));
+ else if (rValue >>= aVal)
+ pToken.reset(new ScStringToken(aVal));
+ else
+ // unidentified value type.
+ return;
+
+ mpTable->setCell(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), pToken);
+}
+
+Any SAL_CALL ScExternalSheetCacheObj::getCellValue(sal_Int32 nCol, sal_Int32 nRow)
+ throw (IllegalArgumentException, RuntimeException)
+{
+ ScUnoGuard aGuard;
+ if (nRow < 0 || nCol < 0)
+ throw IllegalArgumentException();
+
+ ScToken* pToken = mpTable->getCell(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow)).get();
+ if (!pToken)
+ throw IllegalArgumentException();
+
+ Any aValue;
+ switch (pToken->GetType())
+ {
+ case svDouble:
+ {
+ double fVal = pToken->GetDouble();
+ aValue <<= fVal;
+ }
+ break;
+ case svString:
+ {
+ OUString aVal = pToken->GetString();
+ aValue <<= aVal;
+ }
+ break;
+ default:
+ throw IllegalArgumentException();
+ }
+ return aValue;
+}
+
+Sequence< sal_Int32 > SAL_CALL ScExternalSheetCacheObj::getAllRows()
+ throw (RuntimeException)
+{
+ ScUnoGuard aGuard;
+ vector<SCROW> aRows;
+ mpTable->getAllRows(aRows);
+ size_t nSize = aRows.size();
+ Sequence<sal_Int32> aRowsSeq(nSize);
+ for (size_t i = 0; i < nSize; ++i)
+ aRowsSeq[i] = aRows[i];
+
+ return aRowsSeq;
+}
+
+Sequence< sal_Int32 > SAL_CALL ScExternalSheetCacheObj::getAllColumns(sal_Int32 nRow)
+ throw (IllegalArgumentException, RuntimeException)
+{
+ ScUnoGuard aGuard;
+ if (nRow < 0)
+ throw IllegalArgumentException();
+
+ vector<SCCOL> aCols;
+ mpTable->getAllCols(static_cast<SCROW>(nRow), aCols);
+ size_t nSize = aCols.size();
+ Sequence<sal_Int32> aColsSeq(nSize);
+ for (size_t i = 0; i < nSize; ++i)
+ aColsSeq[i] = aCols[i];
+
+ return aColsSeq;
+}
+
+sal_Int32 SAL_CALL ScExternalSheetCacheObj::getTokenIndex()
+ throw (RuntimeException)
+{
+ return static_cast< sal_Int32 >( mnIndex );
+}
+
+// ============================================================================
+
+ScExternalDocLinkObj::ScExternalDocLinkObj(ScExternalRefManager* pRefMgr, sal_uInt16 nFileId) :
+ mpRefMgr(pRefMgr), mnFileId(nFileId)
+{
+}
+
+ScExternalDocLinkObj::~ScExternalDocLinkObj()
+{
+}
+
+Reference< sheet::XExternalSheetCache > SAL_CALL ScExternalDocLinkObj::addSheetCache(
+ const OUString& aSheetName )
+ throw (RuntimeException)
+{
+ ScUnoGuard aGuard;
+ size_t nIndex = 0;
+ ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, aSheetName, true, &nIndex);
+ Reference< sheet::XExternalSheetCache > aSheetCache(new ScExternalSheetCacheObj(pTable, nIndex));
+ return aSheetCache;
+}
+
+Any SAL_CALL ScExternalDocLinkObj::getByName(const::rtl::OUString &aName)
+ throw (container::NoSuchElementException, lang::WrappedTargetException, RuntimeException)
+{
+ ScUnoGuard aGuard;
+ size_t nIndex = 0;
+ ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, aName, false, &nIndex);
+ if (!pTable)
+ throw container::NoSuchElementException();
+
+ Reference< sheet::XExternalSheetCache > aSheetCache(new ScExternalSheetCacheObj(pTable, nIndex));
+
+ Any aAny;
+ aAny <<= aSheetCache;
+ return aAny;
+}
+
+Sequence< OUString > SAL_CALL ScExternalDocLinkObj::getElementNames()
+ throw (RuntimeException)
+{
+ ScUnoGuard aGuard;
+ vector<String> aTabNames;
+ mpRefMgr->getAllCachedTableNames(mnFileId, aTabNames);
+ size_t n = aTabNames.size();
+ Sequence<OUString> aSeq(n);
+ for (size_t i = 0; i < n; ++i)
+ aSeq[i] = aTabNames[i];
+ return aSeq;
+}
+
+sal_Bool SAL_CALL ScExternalDocLinkObj::hasByName(const OUString &aName)
+ throw (RuntimeException)
+{
+ ScUnoGuard aGuard;
+ return static_cast<sal_Bool>(mpRefMgr->hasCacheTable(mnFileId, aName));
+}
+
+sal_Int32 SAL_CALL ScExternalDocLinkObj::getCount()
+ throw (RuntimeException)
+{
+ ScUnoGuard aGuard;
+ return static_cast<sal_Int32>(mpRefMgr->getCacheTableCount(mnFileId));
+}
+
+Any SAL_CALL ScExternalDocLinkObj::getByIndex(sal_Int32 nIndex)
+ throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException, RuntimeException)
+{
+ ScUnoGuard aGuard;
+ size_t nTabCount = mpRefMgr->getCacheTableCount(mnFileId);
+ if (nIndex < 0 || nIndex >= static_cast<sal_Int32>(nTabCount))
+ throw lang::IndexOutOfBoundsException();
+
+ ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, static_cast<size_t>(nIndex));
+ if (!pTable)
+ throw lang::IndexOutOfBoundsException();
+
+ Reference< sheet::XExternalSheetCache > aSheetCache(new ScExternalSheetCacheObj(pTable, nIndex));
+
+ Any aAny;
+ aAny <<= aSheetCache;
+ return aAny;
+}
+
+Reference< container::XEnumeration > SAL_CALL ScExternalDocLinkObj::createEnumeration()
+ throw (RuntimeException)
+{
+ ScUnoGuard aGuard;
+ Reference< container::XEnumeration > aRef(
+ new ScIndexEnumeration(this, OUString::createFromAscii(
+ "com.sun.star.sheet.ExternalDocLink")));
+ return aRef;
+}
+
+uno::Type SAL_CALL ScExternalDocLinkObj::getElementType()
+ throw (RuntimeException)
+{
+ ScUnoGuard aGuard;
+ return getCppuType(static_cast<Reference<sheet::XExternalDocLink>*>(0));
+}
+
+sal_Bool SAL_CALL ScExternalDocLinkObj::hasElements()
+ throw (RuntimeException)
+{
+ ScUnoGuard aGuard;
+ return static_cast<sal_Bool>(mpRefMgr->getCacheTableCount(mnFileId) > 0);
+}
+
+sal_Int32 SAL_CALL ScExternalDocLinkObj::getTokenIndex()
+ throw (RuntimeException)
+{
+ return static_cast<sal_Int32>(mnFileId);
+}
+
+// ============================================================================
+
+ScExternalDocLinksObj::ScExternalDocLinksObj(ScDocShell* pDocShell) :
+ mpDocShell(pDocShell),
+ mpRefMgr(pDocShell->GetDocument()->GetExternalRefManager())
+{
+}
+
+ScExternalDocLinksObj::~ScExternalDocLinksObj()
+{
+}
+
+Reference< sheet::XExternalDocLink > SAL_CALL ScExternalDocLinksObj::addDocLink(
+ const OUString& aDocName )
+ throw (RuntimeException)
+{
+ ScUnoGuard aGuard;
+ sal_uInt16 nFileId = mpRefMgr->getExternalFileId(aDocName);
+ Reference< sheet::XExternalDocLink > aDocLink(new ScExternalDocLinkObj(mpRefMgr, nFileId));
+ return aDocLink;
+}
+
+Any SAL_CALL ScExternalDocLinksObj::getByName(const::rtl::OUString &aName)
+ throw (container::NoSuchElementException, lang::WrappedTargetException, RuntimeException)
+{
+ ScUnoGuard aGuard;
+ if (!mpRefMgr->hasExternalFile(aName))
+ throw container::NoSuchElementException();
+
+ sal_uInt16 nFileId = mpRefMgr->getExternalFileId(aName);
+ Reference< sheet::XExternalDocLink > aDocLink(new ScExternalDocLinkObj(mpRefMgr, nFileId));
+
+ Any aAny;
+ aAny <<= aDocLink;
+ return aAny;
+}
+
+Sequence< OUString > SAL_CALL ScExternalDocLinksObj::getElementNames()
+ throw (RuntimeException)
+{
+ ScUnoGuard aGuard;
+ sal_uInt16 n = mpRefMgr->getExternalFileCount();
+ Sequence<OUString> aSeq(n);
+ for (sal_uInt16 i = 0; i < n; ++i)
+ {
+ const String* pName = mpRefMgr->getExternalFileName(i);
+ aSeq[i] = pName ? *pName : EMPTY_STRING;
+ }
+
+ return aSeq;
+}
+
+sal_Bool SAL_CALL ScExternalDocLinksObj::hasByName(const OUString &aName)
+ throw (RuntimeException)
+{
+ ScUnoGuard aGuard;
+ return mpRefMgr->hasExternalFile(aName);
+}
+
+sal_Int32 SAL_CALL ScExternalDocLinksObj::getCount()
+ throw (RuntimeException)
+{
+ ScUnoGuard aGuard;
+ return mpRefMgr->getExternalFileCount();
+}
+
+Any SAL_CALL ScExternalDocLinksObj::getByIndex(sal_Int32 nIndex)
+ throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException, RuntimeException)
+{
+ ScUnoGuard aGuard;
+ if (nIndex > ::std::numeric_limits<sal_uInt16>::max() || nIndex < ::std::numeric_limits<sal_uInt16>::min())
+ throw lang::IndexOutOfBoundsException();
+
+ sal_uInt16 nFileId = static_cast<sal_uInt16>(nIndex);
+
+ if (!mpRefMgr->hasExternalFile(nFileId))
+ throw lang::IndexOutOfBoundsException();
+
+ Reference< sheet::XExternalDocLink > aDocLink(new ScExternalDocLinkObj(mpRefMgr, nFileId));
+ Any aAny;
+ aAny <<= aDocLink;
+ return aAny;
+}
+
+Reference< container::XEnumeration > SAL_CALL ScExternalDocLinksObj::createEnumeration()
+ throw (RuntimeException)
+{
+ ScUnoGuard aGuard;
+ Reference< container::XEnumeration > aRef(
+ new ScIndexEnumeration(this, OUString::createFromAscii(
+ "com.sun.star.sheet.ExternalDocLinks")));
+ return aRef;
+}
+
+uno::Type SAL_CALL ScExternalDocLinksObj::getElementType()
+ throw (RuntimeException)
+{
+ ScUnoGuard aGuard;
+ return getCppuType(static_cast<Reference<sheet::XExternalDocLinks>*>(0));
+}
+
+sal_Bool SAL_CALL ScExternalDocLinksObj::hasElements()
+ throw (RuntimeException)
+{
+ ScUnoGuard aGuard;
+ return mpRefMgr->getExternalFileCount() > 0;
+}
+
diff --git a/sc/source/ui/unoobj/nameuno.cxx b/sc/source/ui/unoobj/nameuno.cxx
index a4784d6b0921..4e114b53954d 100644
--- a/sc/source/ui/unoobj/nameuno.cxx
+++ b/sc/source/ui/unoobj/nameuno.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: nameuno.cxx,v $
- * $Revision: 1.21 $
+ * $Revision: 1.21.132.2 $
*
* This file is part of OpenOffice.org.
*
@@ -313,11 +313,11 @@ uno::Sequence<sheet::FormulaToken> SAL_CALL ScNamedRangeObj::getTokens() throw(u
ScUnoGuard aGuard;
uno::Sequence<sheet::FormulaToken> aSequence;
ScRangeData* pData = GetRangeData_Impl();
- if (pData)
+ if (pData && pDocShell)
{
ScTokenArray* pTokenArray = pData->GetCode();
if ( pTokenArray )
- (void)ScTokenConversion::ConvertToTokenSequence( aSequence, *pTokenArray );
+ (void)ScTokenConversion::ConvertToTokenSequence( *pDocShell->GetDocument(), aSequence, *pTokenArray );
}
return aSequence;
}
@@ -325,10 +325,13 @@ uno::Sequence<sheet::FormulaToken> SAL_CALL ScNamedRangeObj::getTokens() throw(u
void SAL_CALL ScNamedRangeObj::setTokens( const uno::Sequence<sheet::FormulaToken>& rTokens ) throw(uno::RuntimeException)
{
ScUnoGuard aGuard;
- ScTokenArray aTokenArray;
- (void)ScTokenConversion::ConvertToTokenArray( aTokenArray, rTokens );
- // GRAM_PODF_A1 for API compatibility.
- Modify_Impl( NULL, &aTokenArray, NULL, NULL, NULL, ScGrammar::GRAM_PODF_A1 );
+ if( pDocShell )
+ {
+ ScTokenArray aTokenArray;
+ (void)ScTokenConversion::ConvertToTokenArray( *pDocShell->GetDocument(), aTokenArray, rTokens );
+ // GRAM_PODF_A1 for API compatibility.
+ Modify_Impl( NULL, &aTokenArray, NULL, NULL, NULL, ScGrammar::GRAM_PODF_A1 );
+ }
}
diff --git a/sc/source/ui/unoobj/tokenuno.cxx b/sc/source/ui/unoobj/tokenuno.cxx
index c121990395fa..0eff6699f268 100644
--- a/sc/source/ui/unoobj/tokenuno.cxx
+++ b/sc/source/ui/unoobj/tokenuno.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: tokenuno.cxx,v $
- * $Revision: 1.6 $
+ * $Revision: 1.6.108.8 $
*
* This file is part of OpenOffice.org.
*
@@ -31,15 +31,16 @@
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"
+#include "tokenuno.hxx"
#include <com/sun/star/sheet/ComplexReference.hpp>
+#include <com/sun/star/sheet/ExternalReference.hpp>
#include <com/sun/star/sheet/ReferenceFlags.hpp>
#include <com/sun/star/sheet/AddressConvention.hpp>
#include <com/sun/star/table/CellAddress.hpp>
#include <svtools/itemprop.hxx>
-#include "tokenuno.hxx"
#include "miscuno.hxx"
#include "convuno.hxx"
#include "unonames.hxx"
@@ -48,6 +49,7 @@
#include "tokenarray.hxx"
#include "docsh.hxx"
#include "rangeseq.hxx"
+#include "externalrefmgr.hxx"
using namespace com::sun::star;
@@ -123,6 +125,8 @@ void ScFormulaParserObj::SetCompilerFlags( ScCompiler& rCompiler ) const
eConv = aConvMap[mnConv];
rCompiler.SetRefConvention( eConv );
+
+ rCompiler.SetExternalLinks( maExternalLinks);
}
uno::Sequence<sheet::FormulaToken> SAL_CALL ScFormulaParserObj::parseFormula( const rtl::OUString& aFormula )
@@ -138,7 +142,7 @@ uno::Sequence<sheet::FormulaToken> SAL_CALL ScFormulaParserObj::parseFormula( co
SetCompilerFlags( aCompiler );
ScTokenArray* pCode = aCompiler.CompileString( aFormula );
- (void)ScTokenConversion::ConvertToTokenSequence( aRet, *pCode );
+ (void)ScTokenConversion::ConvertToTokenSequence( *pDoc, aRet, *pCode );
delete pCode;
}
@@ -155,7 +159,7 @@ rtl::OUString SAL_CALL ScFormulaParserObj::printFormula( const uno::Sequence<she
{
ScDocument* pDoc = mpDocShell->GetDocument();
ScTokenArray aCode;
- (void)ScTokenConversion::ConvertToTokenArray( aCode, aTokens );
+ (void)ScTokenConversion::ConvertToTokenArray( *pDoc, aCode, aTokens );
ScCompiler aCompiler( pDoc, maRefPos, aCode, pDoc->GetGrammar() );
SetCompilerFlags( aCompiler );
@@ -220,6 +224,11 @@ void SAL_CALL ScFormulaParserObj::setPropertyValue(
else
throw lang::IllegalArgumentException();
}
+ else if ( aString.EqualsAscii( SC_UNO_EXTERNALLINKS ) )
+ {
+ if (!(aValue >>= maExternalLinks))
+ throw lang::IllegalArgumentException();
+ }
else
throw beans::UnknownPropertyException();
}
@@ -253,6 +262,10 @@ uno::Any SAL_CALL ScFormulaParserObj::getPropertyValue( const rtl::OUString& aPr
{
aRet <<= maOpCodeMapping;
}
+ else if ( aString.EqualsAscii( SC_UNO_EXTERNALLINKS ) )
+ {
+ aRet <<= maExternalLinks;
+ }
else
throw beans::UnknownPropertyException();
return aRet;
@@ -262,6 +275,27 @@ SC_IMPL_DUMMY_PROPERTY_LISTENER( ScFormulaParserObj )
//------------------------------------------------------------------------
+void lcl_ExternalRefToCalc( SingleRefData& rRef, const sheet::SingleReference& rAPI )
+{
+ rRef.InitFlags();
+
+ rRef.nCol = static_cast<SCsCOL>(rAPI.Column);
+ rRef.nRow = static_cast<SCsROW>(rAPI.Row);
+ rRef.nTab = 0;
+ rRef.nRelCol = static_cast<SCsCOL>(rAPI.RelativeColumn);
+ rRef.nRelRow = static_cast<SCsROW>(rAPI.RelativeRow);
+ rRef.nRelTab = 0;
+
+ rRef.SetColRel( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_RELATIVE ) != 0 );
+ rRef.SetRowRel( ( rAPI.Flags & sheet::ReferenceFlags::ROW_RELATIVE ) != 0 );
+ rRef.SetTabRel( false ); // sheet index must be absolute for external refs
+ rRef.SetColDeleted( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_DELETED ) != 0 );
+ rRef.SetRowDeleted( ( rAPI.Flags & sheet::ReferenceFlags::ROW_DELETED ) != 0 );
+ rRef.SetTabDeleted( false ); // sheet must not be deleted for external refs
+ rRef.SetFlag3D( ( rAPI.Flags & sheet::ReferenceFlags::SHEET_3D ) != 0 );
+ rRef.SetRelName( false );
+}
+
void lcl_SingleRefToCalc( SingleRefData& rRef, const sheet::SingleReference& rAPI )
{
rRef.InitFlags();
@@ -283,6 +317,25 @@ void lcl_SingleRefToCalc( SingleRefData& rRef, const sheet::SingleReference& rAP
rRef.SetRelName( ( rAPI.Flags & sheet::ReferenceFlags::RELATIVE_NAME ) != 0 );
}
+void lcl_ExternalRefToApi( sheet::SingleReference& rAPI, const SingleRefData& rRef )
+{
+ rAPI.Column = rRef.nCol;
+ rAPI.Row = rRef.nRow;
+ rAPI.Sheet = 0;
+ rAPI.RelativeColumn = rRef.nRelCol;
+ rAPI.RelativeRow = rRef.nRelRow;
+ rAPI.RelativeSheet = 0;
+
+ sal_Int32 nFlags = 0;
+ if ( rRef.IsColRel() ) nFlags |= sheet::ReferenceFlags::COLUMN_RELATIVE;
+ if ( rRef.IsRowRel() ) nFlags |= sheet::ReferenceFlags::ROW_RELATIVE;
+ if ( rRef.IsColDeleted() ) nFlags |= sheet::ReferenceFlags::COLUMN_DELETED;
+ if ( rRef.IsRowDeleted() ) nFlags |= sheet::ReferenceFlags::ROW_DELETED;
+ if ( rRef.IsFlag3D() ) nFlags |= sheet::ReferenceFlags::SHEET_3D;
+ if ( rRef.IsRelName() ) nFlags |= sheet::ReferenceFlags::RELATIVE_NAME;
+ rAPI.Flags = nFlags;
+}
+
void lcl_SingleRefToApi( sheet::SingleReference& rAPI, const SingleRefData& rRef )
{
rAPI.Column = rRef.nCol;
@@ -305,8 +358,8 @@ void lcl_SingleRefToApi( sheet::SingleReference& rAPI, const SingleRefData& rRef
}
// static
-bool ScTokenConversion::ConvertToTokenArray( ScTokenArray& rTokenArray,
- const uno::Sequence<sheet::FormulaToken>& rSequence )
+bool ScTokenConversion::ConvertToTokenArray( ScDocument& rDoc,
+ ScTokenArray& rTokenArray, const uno::Sequence<sheet::FormulaToken>& rSequence )
{
bool bError = false;
sal_Int32 nCount = rSequence.getLength();
@@ -384,6 +437,61 @@ bool ScTokenConversion::ConvertToTokenArray( ScTokenArray& rTokenArray,
else
bError = true;
}
+ else if ( aType.equals( cppu::UnoType<sheet::ExternalReference>::get() ) )
+ {
+ sheet::ExternalReference aApiExtRef;
+ if( (eOpCode == ocPush) && (rAPI.Data >>= aApiExtRef) && (0 <= aApiExtRef.Index) && (aApiExtRef.Index <= SAL_MAX_UINT16) )
+ {
+ sal_uInt16 nFileId = static_cast< sal_uInt16 >( aApiExtRef.Index );
+ sheet::SingleReference aApiSRef;
+ sheet::ComplexReference aApiCRef;
+ ::rtl::OUString aName;
+ if( aApiExtRef.Reference >>= aApiSRef )
+ {
+ // try to resolve cache index to sheet name
+ size_t nCacheId = static_cast< size_t >( aApiSRef.Sheet );
+ String aTabName = rDoc.GetExternalRefManager()->getCacheTableName( nFileId, nCacheId );
+ if( aTabName.Len() > 0 )
+ {
+ SingleRefData aSingleRef;
+ // convert column/row settings, set sheet index to absolute
+ lcl_ExternalRefToCalc( aSingleRef, aApiSRef );
+ rTokenArray.AddExternalSingleReference( nFileId, aTabName, aSingleRef );
+ }
+ else
+ bError = true;
+ }
+ else if( aApiExtRef.Reference >>= aApiCRef )
+ {
+ // try to resolve cache index to sheet name.
+ size_t nCacheId = static_cast< size_t >( aApiCRef.Reference1.Sheet );
+ String aTabName = rDoc.GetExternalRefManager()->getCacheTableName( nFileId, nCacheId );
+ if( aTabName.Len() > 0 )
+ {
+ ComplRefData aComplRef;
+ // convert column/row settings, set sheet index to absolute
+ lcl_ExternalRefToCalc( aComplRef.Ref1, aApiCRef.Reference1 );
+ lcl_ExternalRefToCalc( aComplRef.Ref2, aApiCRef.Reference2 );
+ // NOTE: This assumes that cached sheets are in consecutive order!
+ aComplRef.Ref2.nTab = aComplRef.Ref1.nTab + (aApiCRef.Reference2.Sheet - aApiCRef.Reference1.Sheet);
+ rTokenArray.AddExternalDoubleReference( nFileId, aTabName, aComplRef );
+ }
+ else
+ bError = true;
+ }
+ else if( aApiExtRef.Reference >>= aName )
+ {
+ if( aName.getLength() > 0 )
+ rTokenArray.AddExternalName( nFileId, aName );
+ else
+ bError = true;
+ }
+ else
+ bError = true;
+ }
+ else
+ bError = true;
+ }
else
bError = true; // unknown struct
}
@@ -414,8 +522,8 @@ bool ScTokenConversion::ConvertToTokenArray( ScTokenArray& rTokenArray,
}
// static
-bool ScTokenConversion::ConvertToTokenSequence( uno::Sequence<sheet::FormulaToken>& rSequence,
- const ScTokenArray& rTokenArray )
+bool ScTokenConversion::ConvertToTokenSequence( ScDocument& rDoc,
+ uno::Sequence<sheet::FormulaToken>& rSequence, const ScTokenArray& rTokenArray )
{
bool bError = false;
@@ -430,7 +538,7 @@ bool ScTokenConversion::ConvertToTokenSequence( uno::Sequence<sheet::FormulaToke
sheet::FormulaToken& rAPI = rSequence[nPos];
OpCode eOpCode = rToken.GetOpCode();
- rAPI.OpCode = static_cast<sal_Int32>(eOpCode); //! assuming equal values for the moment
+ // eOpCode may be changed in the following switch/case
switch ( rToken.GetType() )
{
case svByte:
@@ -473,9 +581,54 @@ bool ScTokenConversion::ConvertToTokenSequence( uno::Sequence<sheet::FormulaToke
if (!ScRangeToSequence::FillMixedArray( rAPI.Data, rToken.GetMatrix(), true))
rAPI.Data.clear();
break;
+ case svExternalSingleRef:
+ {
+ sheet::SingleReference aSingleRef;
+ lcl_ExternalRefToApi( aSingleRef, rToken.GetSingleRef() );
+ size_t nCacheId;
+ rDoc.GetExternalRefManager()->getCacheTable( rToken.GetIndex(), rToken.GetString(), false, &nCacheId );
+ aSingleRef.Sheet = static_cast< sal_Int32 >( nCacheId );
+ sheet::ExternalReference aExtRef;
+ aExtRef.Index = rToken.GetIndex();
+ aExtRef.Reference <<= aSingleRef;
+ rAPI.Data <<= aExtRef;
+ eOpCode = ocPush;
+ }
+ break;
+ case svExternalDoubleRef:
+ {
+ sheet::ComplexReference aComplRef;
+ lcl_ExternalRefToApi( aComplRef.Reference1, rToken.GetSingleRef() );
+ lcl_ExternalRefToApi( aComplRef.Reference2, rToken.GetSingleRef2() );
+ size_t nCacheId;
+ rDoc.GetExternalRefManager()->getCacheTable( rToken.GetIndex(), rToken.GetString(), false, &nCacheId );
+ aComplRef.Reference1.Sheet = static_cast< sal_Int32 >( nCacheId );
+ // NOTE: This assumes that cached sheets are in consecutive order!
+ aComplRef.Reference2.Sheet = aComplRef.Reference1.Sheet + (rToken.GetSingleRef2().nTab - rToken.GetSingleRef().nTab);
+ sheet::ExternalReference aExtRef;
+ aExtRef.Index = rToken.GetIndex();
+ aExtRef.Reference <<= aComplRef;
+ rAPI.Data <<= aExtRef;
+ eOpCode = ocPush;
+ }
+ break;
+ case svExternalName:
+ {
+ sheet::ExternalReference aExtRef;
+ aExtRef.Index = rToken.GetIndex();
+ aExtRef.Reference <<= ::rtl::OUString( rToken.GetString() );
+ rAPI.Data <<= aExtRef;
+ eOpCode = ocPush;
+ }
+ break;
default:
+ DBG_ERROR1( "ScTokenConversion::ConvertToTokenSequence: unhandled token type SvStackVar %d", rToken.GetType());
+ case svSep: // occurs with ocSep, ocOpen, ocClose, ocArray*
+ case svJump: // occurs with ocIf, ocChose
+ case svMissing: // occurs with ocMissing
rAPI.Data.clear(); // no data
}
+ rAPI.OpCode = static_cast<sal_Int32>(eOpCode); //! assuming equal values for the moment
}
}
else
diff --git a/sc/source/ui/view/tabvwsh4.cxx b/sc/source/ui/view/tabvwsh4.cxx
index c0dc1c97705d..d246b5cf0968 100644
--- a/sc/source/ui/view/tabvwsh4.cxx
+++ b/sc/source/ui/view/tabvwsh4.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: tabvwsh4.cxx,v $
- * $Revision: 1.75.24.3 $
+ * $Revision: 1.76.102.1 $
*
* This file is part of OpenOffice.org.
*
@@ -100,6 +100,7 @@
#include "navsett.hxx"
#include "sc.hrc" //CHINA001
#include "scabstdlg.hxx" //CHINA001
+#include "externalrefmgr.hxx"
void ActivateOlk( ScViewData* pViewData );
void DeActivateOlk( ScViewData* pViewData );
@@ -1817,11 +1818,8 @@ void ScTabViewShell::Construct( BYTE nForceDesignMode )
if ( pDocSh->GetCreateMode() != SFX_CREATE_MODE_INTERNAL &&
pDocSh->IsUpdateEnabled() ) // #105575#; update only in the first creation of the ViewShell
{
- BOOL bLink = FALSE; // Links updaten
- SCTAB nTabCount = pDoc->GetTableCount();
- for (SCTAB i=0; i<nTabCount && !bLink; i++)
- if (pDoc->IsLinked(i))
- bLink = TRUE;
+ // Check if there are any external data.
+ bool bLink = pDoc->GetExternalRefManager()->hasExternalData();
if (!bLink)
if (pDoc->HasDdeLinks() || pDoc->HasAreaLinks())
bLink = TRUE;