summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
authorEike Rathke <erack@redhat.com>2014-08-05 22:51:01 +0200
committerEike Rathke <erack@redhat.com>2014-08-11 20:06:45 +0200
commit8c23a767d926d8d08213f5e2f8e81775c653cbd7 (patch)
tree21eb39564d45a3c4e05c0dc96f913028415427f0 /sc
parent5c37960d9507fac206f0b90d36f778db9fe2b6a5 (diff)
write OOXML externalReferences, externalLinks, fdo#45286
This for the first time writes external references (hopefully) correctly and adds the necessary relationship streams and the externalLink streams with sheetData. At least Excel 2013 loaded the result without complaining, so do we. Change-Id: I3d615490a60c5420ae13c0bfc6297642d86a07b9
Diffstat (limited to 'sc')
-rw-r--r--sc/inc/compiler.hxx7
-rw-r--r--sc/source/core/tool/compiler.cxx85
-rw-r--r--sc/source/core/tool/token.cxx7
-rw-r--r--sc/source/filter/excel/excdoc.cxx3
-rw-r--r--sc/source/filter/excel/xecontent.cxx2
-rw-r--r--sc/source/filter/excel/xelink.cxx293
-rw-r--r--sc/source/filter/inc/xecontent.hxx7
-rw-r--r--sc/source/filter/inc/xelink.hxx3
8 files changed, 364 insertions, 43 deletions
diff --git a/sc/inc/compiler.hxx b/sc/inc/compiler.hxx
index 61008358b235..18d788aab3c4 100644
--- a/sc/inc/compiler.hxx
+++ b/sc/inc/compiler.hxx
@@ -256,15 +256,16 @@ public:
const ::com::sun::star::uno::Sequence<
com::sun::star::sheet::ExternalLinkInfo>* pExternalLinks ) const = 0;
- virtual OUString makeExternalNameStr( const OUString& rFile, const OUString& rName ) const = 0;
+ virtual OUString makeExternalNameStr( sal_uInt16 nFileId, const OUString& rFile,
+ const OUString& rName ) const = 0;
virtual void makeExternalRefStr(
- OUStringBuffer& rBuffer, const ScAddress& rPos, const OUString& rFileName,
+ OUStringBuffer& rBuffer, const ScAddress& rPos, sal_uInt16 nFileId, const OUString& rFileName,
const OUString& rTabName, const ScSingleRefData& rRef ) const = 0;
virtual void makeExternalRefStr(
OUStringBuffer& rBuffer, const ScAddress& rPos,
- const OUString& rFileName, const std::vector<OUString>& rTabNames,
+ sal_uInt16 nFileId, const OUString& rFileName, const std::vector<OUString>& rTabNames,
const OUString& rTabName, const ScComplexRefData& rRef ) const = 0;
enum SpecialSymbolType
diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx
index cec91da3c58c..09ecd1b9b454 100644
--- a/sc/source/core/tool/compiler.cxx
+++ b/sc/source/core/tool/compiler.cxx
@@ -820,7 +820,8 @@ struct ConventionOOO_A1 : public Convention_A1
return lcl_parseExternalName(rSymbol, rFile, rName, '#', pDoc, pExternalLinks);
}
- virtual OUString makeExternalNameStr( const OUString& rFile, const OUString& rName ) const SAL_OVERRIDE
+ virtual OUString makeExternalNameStr( sal_uInt16 /*nFileId*/, const OUString& rFile,
+ const OUString& rName ) const SAL_OVERRIDE
{
return lcl_makeExternalNameStr( rFile, rName, '#', false);
}
@@ -871,7 +872,7 @@ struct ConventionOOO_A1 : public Convention_A1
}
virtual void makeExternalRefStr(
- OUStringBuffer& rBuffer, const ScAddress& rPos, const OUString& rFileName,
+ OUStringBuffer& rBuffer, const ScAddress& rPos, sal_uInt16 /*nFileId*/, const OUString& rFileName,
const OUString& rTabName, const ScSingleRefData& rRef ) const SAL_OVERRIDE
{
makeExternalRefStrImpl(rBuffer, rPos, rFileName, rTabName, rRef, false);
@@ -918,7 +919,7 @@ struct ConventionOOO_A1 : public Convention_A1
}
virtual void makeExternalRefStr(
- OUStringBuffer& rBuffer, const ScAddress& rPos, const OUString& rFileName,
+ OUStringBuffer& rBuffer, const ScAddress& rPos, sal_uInt16 /*nFileId*/, const OUString& rFileName,
const std::vector<OUString>& rTabNames, const OUString& rTabName,
const ScComplexRefData& rRef ) const SAL_OVERRIDE
{
@@ -963,20 +964,21 @@ struct ConventionOOO_A1_ODF : public ConventionOOO_A1
rBuffer.append(']');
}
- virtual OUString makeExternalNameStr( const OUString& rFile, const OUString& rName ) const SAL_OVERRIDE
+ virtual OUString makeExternalNameStr( sal_uInt16 /*nFileId*/, const OUString& rFile,
+ const OUString& rName ) const SAL_OVERRIDE
{
return lcl_makeExternalNameStr( rFile, rName, '#', true);
}
virtual void makeExternalRefStr(
- OUStringBuffer& rBuffer, const ScAddress& rPos, const OUString& rFileName,
+ OUStringBuffer& rBuffer, const ScAddress& rPos, sal_uInt16 /*nFileId*/, const OUString& rFileName,
const OUString& rTabName, const ScSingleRefData& rRef ) const SAL_OVERRIDE
{
makeExternalRefStrImpl(rBuffer, rPos, rFileName, rTabName, rRef, true);
}
virtual void makeExternalRefStr(
- OUStringBuffer& rBuffer, const ScAddress& rPos, const OUString& rFileName,
+ OUStringBuffer& rBuffer, const ScAddress& rPos, sal_uInt16 /*nFileId*/, const OUString& rFileName,
const std::vector<OUString>& rTabNames,
const OUString& rTabName, const ScComplexRefData& rRef ) const SAL_OVERRIDE
{
@@ -1261,13 +1263,14 @@ struct ConventionXL_A1 : public Convention_A1, public ConventionXL
return ConventionXL::parseExternalName( rSymbol, rFile, rName, pDoc, pExternalLinks);
}
- virtual OUString makeExternalNameStr( const OUString& rFile, const OUString& rName ) const SAL_OVERRIDE
+ virtual OUString makeExternalNameStr( sal_uInt16 /*nFileId*/, const OUString& rFile,
+ const OUString& rName ) const SAL_OVERRIDE
{
return ConventionXL::makeExternalNameStr(rFile, rName);
}
virtual void makeExternalRefStr(
- OUStringBuffer& rBuffer, const ScAddress& rPos, const OUString& rFileName,
+ OUStringBuffer& rBuffer, const ScAddress& rPos, sal_uInt16 /*nFileId*/, const OUString& rFileName,
const OUString& rTabName, const ScSingleRefData& rRef ) const SAL_OVERRIDE
{
// ['file:///path/to/file/filename.xls']'Sheet Name'!$A$1
@@ -1284,7 +1287,7 @@ struct ConventionXL_A1 : public Convention_A1, public ConventionXL
}
virtual void makeExternalRefStr(
- OUStringBuffer& rBuffer, const ScAddress& rPos, const OUString& rFileName,
+ OUStringBuffer& rBuffer, const ScAddress& rPos, sal_uInt16 /*nFileId*/, const OUString& rFileName,
const std::vector<OUString>& rTabNames, const OUString& rTabName,
const ScComplexRefData& rRef ) const SAL_OVERRIDE
{
@@ -1306,6 +1309,52 @@ struct ConventionXL_A1 : public Convention_A1, public ConventionXL
struct ConventionXL_OOX : public ConventionXL_A1
{
ConventionXL_OOX() : ConventionXL_A1( FormulaGrammar::CONV_XL_OOX ) { }
+
+ virtual OUString makeExternalNameStr( sal_uInt16 nFileId, const OUString& /*rFile*/,
+ const OUString& rName ) const SAL_OVERRIDE
+ {
+ /* TODO: is this really what Excel writes to OOXML? */
+ return OUString( "[" + OUString::number(nFileId+1) + "]!" + rName );
+ }
+
+ virtual void makeExternalRefStr(
+ OUStringBuffer& rBuffer, const ScAddress& rPos, sal_uInt16 nFileId, const OUString& /*rFileName*/,
+ const OUString& rTabName, const ScSingleRefData& rRef ) const SAL_OVERRIDE
+ {
+ // [N]'Sheet Name'!$A$1
+ // Where N is a 1-based positive integer number of a file name in OOXML
+ // xl/externalLinks/externalLinkN.xml
+
+ ConventionXL_OOX::makeExternalDocStr(rBuffer, nFileId);
+ ScRangeStringConverter::AppendTableName(rBuffer, rTabName);
+ rBuffer.append('!');
+
+ makeSingleCellStr(rBuffer, rRef, rRef.toAbs(rPos));
+ }
+
+ virtual void makeExternalRefStr(
+ OUStringBuffer& rBuffer, const ScAddress& rPos, sal_uInt16 nFileId, const OUString& /*rFileName*/,
+ const std::vector<OUString>& rTabNames, const OUString& rTabName,
+ const ScComplexRefData& rRef ) const SAL_OVERRIDE
+ {
+ ScRange aAbsRef = rRef.toAbs(rPos);
+
+ ConventionXL_OOX::makeExternalDocStr(rBuffer, nFileId);
+ ConventionXL::makeExternalTabNameRange(rBuffer, rTabName, rTabNames, aAbsRef);
+ rBuffer.append('!');
+
+ makeSingleCellStr(rBuffer, rRef.Ref1, aAbsRef.aStart);
+ if (aAbsRef.aStart != aAbsRef.aEnd)
+ {
+ rBuffer.append(':');
+ makeSingleCellStr(rBuffer, rRef.Ref2, aAbsRef.aEnd);
+ }
+ }
+
+ static void makeExternalDocStr( OUStringBuffer& rBuffer, sal_uInt16 nFileId )
+ {
+ rBuffer.append('[').append( OUString::number( nFileId+1)).append(']');
+ }
};
static void
@@ -1435,13 +1484,14 @@ struct ConventionXL_R1C1 : public ScCompiler::Convention, public ConventionXL
return ConventionXL::parseExternalName( rSymbol, rFile, rName, pDoc, pExternalLinks);
}
- virtual OUString makeExternalNameStr( const OUString& rFile, const OUString& rName ) const SAL_OVERRIDE
+ virtual OUString makeExternalNameStr( sal_uInt16 /*nFileId*/, const OUString& rFile,
+ const OUString& rName ) const SAL_OVERRIDE
{
return ConventionXL::makeExternalNameStr(rFile, rName);
}
virtual void makeExternalRefStr(
- OUStringBuffer& rBuffer, const ScAddress& rPos, const OUString& rFileName,
+ OUStringBuffer& rBuffer, const ScAddress& rPos, sal_uInt16 /*nFileId*/, const OUString& rFileName,
const OUString& rTabName, const ScSingleRefData& rRef ) const SAL_OVERRIDE
{
// ['file:///path/to/file/filename.xls']'Sheet Name'!$A$1
@@ -1460,7 +1510,7 @@ struct ConventionXL_R1C1 : public ScCompiler::Convention, public ConventionXL
}
virtual void makeExternalRefStr(
- OUStringBuffer& rBuffer, const ScAddress& rPos, const OUString& rFileName,
+ OUStringBuffer& rBuffer, const ScAddress& rPos, sal_uInt16 /*nFileId*/, const OUString& rFileName,
const std::vector<OUString>& rTabNames, const OUString& rTabName,
const ScComplexRefData& rRef ) const SAL_OVERRIDE
{
@@ -4063,30 +4113,31 @@ bool ScCompiler::IsCharFlagAllConventions(
void ScCompiler::CreateStringFromExternal(OUStringBuffer& rBuffer, FormulaToken* pTokenP) const
{
FormulaToken* t = pTokenP;
+ sal_uInt16 nFileId = t->GetIndex();
ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
- const OUString* pFileName = pRefMgr->getExternalFileName(t->GetIndex());
+ const OUString* pFileName = pRefMgr->getExternalFileName(nFileId);
if (!pFileName)
return;
switch (t->GetType())
{
case svExternalName:
- rBuffer.append(pConv->makeExternalNameStr(*pFileName, t->GetString().getString()));
+ rBuffer.append(pConv->makeExternalNameStr( nFileId, *pFileName, t->GetString().getString()));
break;
case svExternalSingleRef:
pConv->makeExternalRefStr(
- rBuffer, GetPos(), *pFileName, t->GetString().getString(),
+ rBuffer, GetPos(), nFileId, *pFileName, t->GetString().getString(),
static_cast<ScToken*>(t)->GetSingleRef());
break;
case svExternalDoubleRef:
{
vector<OUString> aTabNames;
- pRefMgr->getAllCachedTableNames(t->GetIndex(), aTabNames);
+ pRefMgr->getAllCachedTableNames(nFileId, aTabNames);
if (aTabNames.empty())
return;
pConv->makeExternalRefStr(
- rBuffer, GetPos(), *pFileName, aTabNames, t->GetString().getString(),
+ rBuffer, GetPos(), nFileId, *pFileName, aTabNames, t->GetString().getString(),
static_cast<ScToken*>(t)->GetDoubleRef());
}
break;
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index 080e9588b0c4..34f9a16fdae1 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -3698,11 +3698,11 @@ void appendTokenByType( sc::TokenStringContext& rCxt, OUStringBuffer& rBuf, cons
switch (rToken.GetType())
{
case svExternalName:
- rBuf.append(rCxt.mpRefConv->makeExternalNameStr(aFileName, aTabName));
+ rBuf.append(rCxt.mpRefConv->makeExternalNameStr(nFileId, aFileName, aTabName));
break;
case svExternalSingleRef:
rCxt.mpRefConv->makeExternalRefStr(
- rBuf, rPos, aFileName, aTabName, static_cast<const ScToken&>(rToken).GetSingleRef());
+ rBuf, rPos, nFileId, aFileName, aTabName, static_cast<const ScToken&>(rToken).GetSingleRef());
break;
case svExternalDoubleRef:
{
@@ -3713,7 +3713,8 @@ void appendTokenByType( sc::TokenStringContext& rCxt, OUStringBuffer& rBuf, cons
return;
rCxt.mpRefConv->makeExternalRefStr(
- rBuf, rPos, aFileName, it->second, aTabName, static_cast<const ScToken&>(rToken).GetDoubleRef());
+ rBuf, rPos, nFileId, aFileName, it->second, aTabName,
+ static_cast<const ScToken&>(rToken).GetDoubleRef());
}
break;
default:
diff --git a/sc/source/filter/excel/excdoc.cxx b/sc/source/filter/excel/excdoc.cxx
index 4b60de0238db..8dd2b15fe6bd 100644
--- a/sc/source/filter/excel/excdoc.cxx
+++ b/sc/source/filter/excel/excdoc.cxx
@@ -370,9 +370,12 @@ void ExcTable::FillAsHeader( ExcBoundsheetList& rBoundsheetList )
// COUNTRY - in BIFF8 in workbook globals
Add( new XclExpCountry( GetRoot() ) );
+
+ aRecList.AppendNewRecord( new XclExpXmlStartElementRecord( XML_externalReferences ) );
// link table: SUPBOOK, XCT, CRN, EXTERNNAME, EXTERNSHEET, NAME
aRecList.AppendRecord( CreateRecord( EXC_ID_EXTERNSHEET ) );
aRecList.AppendRecord( CreateRecord( EXC_ID_NAME ) );
+ aRecList.AppendNewRecord( new XclExpXmlEndElementRecord( XML_externalReferences ) );
if( GetOutput() != EXC_OUTPUT_BINARY )
lcl_AddCalcPr( aRecList, *this );
diff --git a/sc/source/filter/excel/xecontent.cxx b/sc/source/filter/excel/xecontent.cxx
index ab47be4d5cce..f0e8a079e502 100644
--- a/sc/source/filter/excel/xecontent.cxx
+++ b/sc/source/filter/excel/xecontent.cxx
@@ -444,7 +444,7 @@ XclExpHyperlink::~XclExpHyperlink()
}
OUString XclExpHyperlink::BuildFileName(
- sal_uInt16& rnLevel, bool& rbRel, const OUString& rUrl, const XclExpRoot& rRoot ) const
+ sal_uInt16& rnLevel, bool& rbRel, const OUString& rUrl, const XclExpRoot& rRoot )
{
OUString aDosName( INetURLObject( rUrl ).getFSysPath( INetURLObject::FSYS_DOS ) );
rnLevel = 0;
diff --git a/sc/source/filter/excel/xelink.cxx b/sc/source/filter/excel/xelink.cxx
index a856cf56b4a2..0a54a6fc65fe 100644
--- a/sc/source/filter/excel/xelink.cxx
+++ b/sc/source/filter/excel/xelink.cxx
@@ -27,6 +27,7 @@
#include "scextopt.hxx"
#include "externalrefmgr.hxx"
#include "tokenarray.hxx"
+#include "xecontent.hxx"
#include <vector>
#include <memory>
@@ -36,6 +37,8 @@ using ::std::find_if;
using ::std::vector;
using ::com::sun::star::uno::Any;
+using namespace oox;
+
// *** Helper classes ***
// External names =============================================================
@@ -158,6 +161,9 @@ public:
/** Returns true, if the passed value could be appended to this record. */
bool InsertValue( SCCOL nScCol, SCROW nScRow, const Any& rValue );
+ /** Writes the row and child elements. */
+ virtual void SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
+
private:
virtual void WriteBody( XclExpStream& rStrm ) SAL_OVERRIDE;
@@ -175,6 +181,8 @@ private:
SCROW mnScRow; /// Row index of the external cells.
};
+namespace { class XclExpCrnList; }
+
/** Represents the record XCT which is the header record of a CRN record list.
*/
class XclExpXct : public XclExpRecordBase, protected XclExpRoot
@@ -196,12 +204,18 @@ public:
/** Writes the XCT and all CRN records. */
virtual void Save( XclExpStream& rStrm ) SAL_OVERRIDE;
+ /** Writes the sheetDataSet and child elements. */
+ virtual void SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
+
private:
ScExternalRefCache::TableTypeRef mxCacheTable;
ScMarkData maUsedCells; /// Contains addresses of all stored cells.
ScRange maBoundRange; /// Bounding box of maUsedCells.
XclExpString maTabName; /// Sheet name of the external sheet.
sal_uInt16 mnSBTab; /// Referred sheet index in SUPBOOK record.
+
+ /** Build the internal representation of records to be saved as BIFF or OOXML. */
+ bool BuildCrnList( XclExpCrnList& rCrnRecs );
};
// External documents (EXTERNSHEET/SUPBOOK), base class =======================
@@ -222,8 +236,10 @@ public:
protected:
/** Creates and returns the list of EXTERNNAME records. */
XclExpExtNameBuffer& GetExtNameBuffer();
- /** Creates and returns the list of EXTERNNAME records. */
+ /** Writes the list of EXTERNNAME records. */
void WriteExtNameBuffer( XclExpStream& rStrm );
+ /** Writes the list of externalName elements. */
+ void WriteExtNameBufferXml( XclExpXmlStream& rStrm );
private:
typedef boost::shared_ptr< XclExpExtNameBuffer > XclExpExtNameBfrRef;
@@ -307,9 +323,21 @@ public:
sal_uInt16 InsertExtName( const OUString& rName, const ScExternalRefCache::TokenArrayRef pArray );
+ /** Get the type of record. */
+ XclSupbookType GetType() const;
+
+ /** For references to an external document, 1-based OOXML file ID. */
+ sal_uInt16 GetFileId() const;
+
+ /** For references to an external document. */
+ const OUString& GetUrl() const;
+
/** Writes the SUPBOOK and all EXTERNNAME, XCT and CRN records. */
virtual void Save( XclExpStream& rStrm ) SAL_OVERRIDE;
+ /** Writes the externalBook and all child elements. */
+ virtual void SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
+
private:
/** Returns the sheet name inside of this SUPBOOK. */
const XclExpString* GetTabName( sal_uInt16 nSBTab ) const;
@@ -327,6 +355,7 @@ private:
XclExpString maUrlEncoded; /// Document name encoded for Excel.
XclSupbookType meType; /// Type of this SUPBOOK record.
sal_uInt16 mnXclTabCount; /// Number of internal sheets.
+ sal_uInt16 mnFileId; /// 1-based external reference file ID for OOXML
};
// All SUPBOOKS in a document =================================================
@@ -401,6 +430,9 @@ public:
/** Writes all SUPBOOK records with their sub records. */
virtual void Save( XclExpStream& rStrm ) SAL_OVERRIDE;
+ /** Writes all externalBook elements with their child elements to OOXML. */
+ virtual void SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
+
struct XclExpSBIndex
{
sal_uInt16 mnSupbook; /// SUPBOOK index for an Excel sheet.
@@ -484,6 +516,9 @@ public:
/** Derived classes write the entire link table to the passed stream. */
virtual void Save( XclExpStream& rStrm ) = 0;
+ /** Derived classes write the entire link table to the passed OOXML stream. */
+ virtual void SaveXml( XclExpXmlStream& rStrm ) = 0;
+
protected:
explicit XclExpLinkManagerImpl( const XclExpRoot& rRoot );
};
@@ -528,6 +563,8 @@ public:
virtual void Save( XclExpStream& rStrm ) SAL_OVERRIDE;
+ virtual void SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
+
private:
typedef XclExpRecordList< XclExpExternSheet > XclExpExtSheetList;
typedef XclExpExtSheetList::RecordRefType XclExpExtSheetRef;
@@ -556,7 +593,7 @@ private:
XclExpCodeMap maCodeMap; /// Maps special external codes to EXTERNSHEET records.
};
-/** Implementation of the link manager for BIFF8. */
+/** Implementation of the link manager for BIFF8 and OOXML. */
class XclExpLinkManagerImpl8 : public XclExpLinkManagerImpl
{
public:
@@ -595,6 +632,8 @@ public:
virtual void Save( XclExpStream& rStrm ) SAL_OVERRIDE;
+ virtual void SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
+
private:
/** Searches for or inserts a new XTI structure.
@return The 0-based list index of the XTI structure. */
@@ -1148,6 +1187,69 @@ void XclExpCrn::WriteEmpty( XclExpStream& rStrm )
rStrm.WriteZeroBytes( 8 );
}
+void XclExpCrn::SaveXml( XclExpXmlStream& rStrm )
+{
+ sax_fastparser::FSHelperPtr pFS = rStrm.GetCurrentStream();
+
+ pFS->startElement( XML_row,
+ XML_r, OString::number( mnScRow + 1 ).getStr(),
+ FSEND);
+
+ ScAddress aAdr( mnScCol, mnScRow, 0); // Tab number doesn't matter
+ for( CachedValues::iterator aIt = maValues.begin(), aEnd = maValues.end(); aIt != aEnd; ++aIt, aAdr.IncCol() )
+ {
+ if( aIt->has< double >() )
+ {
+ double fVal = aIt->get< double >();
+ if (rtl::math::isFinite( fVal))
+ {
+ // t='n' is omitted
+ pFS->startElement( XML_cell,
+ XML_r, XclXmlUtils::ToOString( aAdr),
+ FSEND);
+ pFS->startElement( XML_v, FSEND );
+ pFS->write( fVal );
+ }
+ else
+ {
+ pFS->startElement( XML_cell,
+ XML_r, XclXmlUtils::ToOString( aAdr),
+ XML_t, "e",
+ FSEND);
+ pFS->startElement( XML_v, FSEND );
+ pFS->write( "#VALUE!" ); // OOXTODO: support other error values
+ }
+ }
+ else if( aIt->has< OUString >() )
+ {
+ pFS->startElement( XML_cell,
+ XML_r, XclXmlUtils::ToOString( aAdr),
+ XML_t, "str",
+ FSEND);
+ pFS->startElement( XML_v, FSEND );
+ pFS->write( aIt->get< OUString >() );
+ }
+ else if( aIt->has< bool >() )
+ {
+ pFS->startElement( XML_cell,
+ XML_r, XclXmlUtils::ToOString( aAdr),
+ XML_t, "b",
+ FSEND);
+ pFS->startElement( XML_v, FSEND );
+ pFS->write( aIt->get< bool >() ? "1" : "0" );
+ }
+ // OOXTODO: error type cell t='e'
+ else
+ {
+ // Empty/blank cell not stored, only aAdr is incremented.
+ }
+ pFS->endElement( XML_v );
+ pFS->endElement( XML_cell);
+ }
+
+ pFS->endElement( XML_row);
+}
+
// Cached cells of a sheet ====================================================
XclExpXct::XclExpXct( const XclExpRoot& rRoot, const OUString& rTabName,
@@ -1207,10 +1309,10 @@ bool XclExpCrnList::InsertValue( SCCOL nScCol, SCROW nScRow, const Any& rValue )
} // namespace
-void XclExpXct::Save( XclExpStream& rStrm )
+bool XclExpXct::BuildCrnList( XclExpCrnList& rCrnRecs )
{
if( !mxCacheTable )
- return;
+ return false;
/* Get the range of used rows in the cache table. This may help to
optimize building the CRN record list if the cache table does not
@@ -1218,24 +1320,23 @@ void XclExpXct::Save( XclExpStream& rStrm )
formulas. */
::std::pair< SCROW, SCROW > aRowRange = mxCacheTable->getRowRange();
if( aRowRange.first >= aRowRange.second )
- return;
+ return false;
/* Crop the bounding range of used cells in this table to Excel limits.
Return if there is no external cell inside these limits. */
if( !GetAddressConverter().ValidateRange( maBoundRange, false ) )
- return;
+ return false;
/* Find the resulting row range that needs to be processed. */
SCROW nScRow1 = ::std::max( aRowRange.first, maBoundRange.aStart.Row() );
SCROW nScRow2 = ::std::min( aRowRange.second - 1, maBoundRange.aEnd.Row() );
if( nScRow1 > nScRow2 )
- return;
+ return false;
/* Build and collect all CRN records before writing the XCT record. This
is needed to determine the total number of CRN records which must be
known when writing the XCT record (possibly encrypted, so seeking the
output strem back after writing the CRN records is not an option). */
- XclExpCrnList aCrnRecs;
SvNumberFormatter& rFormatter = GetFormatter();
bool bValid = true;
for( SCROW nScRow = nScRow1; bValid && (nScRow <= nScRow2); ++nScRow )
@@ -1252,13 +1353,13 @@ void XclExpXct::Save( XclExpStream& rStrm )
{
case svDouble:
bValid = (rFormatter.GetType( nScNumFmt ) == NUMBERFORMAT_LOGICAL) ?
- aCrnRecs.InsertValue( nScCol, nScRow, Any( xToken->GetDouble() != 0 ) ) :
- aCrnRecs.InsertValue( nScCol, nScRow, Any( xToken->GetDouble() ) );
+ rCrnRecs.InsertValue( nScCol, nScRow, Any( xToken->GetDouble() != 0 ) ) :
+ rCrnRecs.InsertValue( nScCol, nScRow, Any( xToken->GetDouble() ) );
break;
case svString:
// do not save empty strings (empty cells) to cache
if( !xToken->GetString().isEmpty() )
- bValid = aCrnRecs.InsertValue( nScCol, nScRow, Any( xToken->GetString().getString() ) );
+ bValid = rCrnRecs.InsertValue( nScCol, nScRow, Any( xToken->GetString().getString() ) );
break;
default:
break;
@@ -1266,6 +1367,14 @@ void XclExpXct::Save( XclExpStream& rStrm )
}
}
}
+ return true;
+}
+
+void XclExpXct::Save( XclExpStream& rStrm )
+{
+ XclExpCrnList aCrnRecs;
+ if (!BuildCrnList( aCrnRecs))
+ return;
// write the XCT record and the list of CRN records
rStrm.StartRecord( EXC_ID_XCT, 4 );
@@ -1274,6 +1383,22 @@ void XclExpXct::Save( XclExpStream& rStrm )
aCrnRecs.Save( rStrm );
}
+void XclExpXct::SaveXml( XclExpXmlStream& rStrm )
+{
+ XclExpCrnList aCrnRecs;
+ if (!BuildCrnList( aCrnRecs))
+ return;
+
+ sax_fastparser::FSHelperPtr pFS = rStrm.GetCurrentStream();
+
+ pFS->startElement( XML_sheetData,
+ XML_sheetId, OString::number( mnSBTab).getStr(),
+ FSEND);
+ // row elements
+ aCrnRecs.SaveXml( rStrm );
+ pFS->endElement( XML_sheetData);
+}
+
// External documents (EXTERNSHEET/SUPBOOK), base class =======================
XclExpExternSheetBase::XclExpExternSheetBase( const XclExpRoot& rRoot, sal_uInt16 nRecId, sal_uInt32 nRecSize ) :
@@ -1295,6 +1420,12 @@ void XclExpExternSheetBase::WriteExtNameBuffer( XclExpStream& rStrm )
mxExtNameBfr->Save( rStrm );
}
+void XclExpExternSheetBase::WriteExtNameBufferXml( XclExpXmlStream& rStrm )
+{
+ if( mxExtNameBfr )
+ mxExtNameBfr->SaveXml( rStrm );
+}
+
// External documents (EXTERNSHEET, BIFF5/BIFF7) ==============================
XclExpExternSheet::XclExpExternSheet( const XclExpRoot& rRoot, sal_Unicode cCode ) :
@@ -1345,14 +1476,16 @@ void XclExpExternSheet::WriteBody( XclExpStream& rStrm )
XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, sal_uInt16 nXclTabCount ) :
XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK, 4 ),
meType( EXC_SBTYPE_SELF ),
- mnXclTabCount( nXclTabCount )
+ mnXclTabCount( nXclTabCount ),
+ mnFileId( 0 )
{
}
XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot ) :
XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK, 4 ),
meType( EXC_SBTYPE_ADDIN ),
- mnXclTabCount( 1 )
+ mnXclTabCount( 1 ),
+ mnFileId( 0 )
{
}
@@ -1361,7 +1494,8 @@ XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, const OUString& rUrl, Xcl
maUrl( rUrl ),
maUrlEncoded( rUrl ),
meType( EXC_SBTYPE_EUROTOOL ),
- mnXclTabCount( 0 )
+ mnXclTabCount( 0 ),
+ mnFileId( 0 )
{
SetRecSize( 2 + maUrlEncoded.GetSize() );
}
@@ -1371,13 +1505,15 @@ XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, const OUString& rUrl ) :
maUrl( rUrl ),
maUrlEncoded( XclExpUrlHelper::EncodeUrl( rRoot, rUrl ) ),
meType( EXC_SBTYPE_EXTERN ),
- mnXclTabCount( 0 )
+ mnXclTabCount( 0 ),
+ mnFileId( 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 );
+ mnFileId = nFileId + 1;
ScfStringVec aTabNames;
pRefMgr->getAllCachedTableNames( nFileId, aTabNames );
for( ScfStringVec::const_iterator aBeg = aTabNames.begin(), aIt = aBeg, aEnd = aTabNames.end(); aIt != aEnd; ++aIt )
@@ -1390,7 +1526,8 @@ XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, const OUString& rApplic,
maDdeTopic( rTopic ),
maUrlEncoded( XclExpUrlHelper::EncodeDde( rApplic, rTopic ) ),
meType( EXC_SBTYPE_SPECIAL ),
- mnXclTabCount( 0 )
+ mnXclTabCount( 0 ),
+ mnFileId( 0 )
{
SetRecSize( 2 + maUrlEncoded.GetSize() );
}
@@ -1481,6 +1618,21 @@ sal_uInt16 XclExpSupbook::InsertExtName( const OUString& rName, const ScExternal
return GetExtNameBuffer().InsertExtName(*this, rName, pArray);
}
+XclSupbookType XclExpSupbook::GetType() const
+{
+ return meType;
+}
+
+sal_uInt16 XclExpSupbook::GetFileId() const
+{
+ return mnFileId;
+}
+
+const OUString& XclExpSupbook::GetUrl() const
+{
+ return maUrl;
+}
+
void XclExpSupbook::Save( XclExpStream& rStrm )
{
// SUPBOOK record
@@ -1491,6 +1643,48 @@ void XclExpSupbook::Save( XclExpStream& rStrm )
WriteExtNameBuffer( rStrm );
}
+void XclExpSupbook::SaveXml( XclExpXmlStream& rStrm )
+{
+ sax_fastparser::FSHelperPtr pExternalLink = rStrm.GetCurrentStream();
+
+ // Add relation for this stream, e.g. xl/externalLinks/_rels/externalLink1.xml.rels
+ sal_uInt16 nLevel = 0;
+ bool bRel = true;
+ OUString sId = rStrm.addRelation( pExternalLink->getOutputStream(),
+ "http://schemas.openxmlformats.org/officeDocument/2006/relationships/externalLinkPath",
+ XclExpHyperlink::BuildFileName( nLevel, bRel, maUrl, GetRoot()),
+ true );
+
+ pExternalLink->startElement( XML_externalLink,
+ XML_xmlns, "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
+ FSEND);
+
+ pExternalLink->startElement( XML_externalBook,
+ FSNS(XML_xmlns, XML_r), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
+ FSNS(XML_r, XML_id), XclXmlUtils::ToOString( sId ).getStr(),
+ FSEND);
+
+ pExternalLink->startElement( XML_sheetNames, FSEND);
+ for (size_t nPos = 0, nSize = maXctList.GetSize(); nPos < nSize; ++nPos)
+ {
+ pExternalLink->singleElement( XML_sheetName,
+ XML_val, XclXmlUtils::ToOString( maXctList.GetRecord( nPos )->GetTabName()).getStr(),
+ FSEND);
+ }
+ pExternalLink->endElement( XML_sheetNames);
+
+ pExternalLink->startElement( XML_sheetDataSet, FSEND);
+
+ // sheetData elements
+ maXctList.SaveXml( rStrm );
+ // externalName elements
+ WriteExtNameBufferXml( rStrm );
+
+ pExternalLink->endElement( XML_sheetDataSet);
+ pExternalLink->endElement( XML_externalBook);
+ pExternalLink->endElement( XML_externalLink);
+}
+
const XclExpString* XclExpSupbook::GetTabName( sal_uInt16 nSBTab ) const
{
XclExpXctRef xXct = maXctList.GetRecord( nSBTab );
@@ -1850,6 +2044,48 @@ void XclExpSupbookBuffer::Save( XclExpStream& rStrm )
maSupbookList.Save( rStrm );
}
+void XclExpSupbookBuffer::SaveXml( XclExpXmlStream& rStrm )
+{
+ ::std::map< sal_uInt16, OUString > aMap;
+ for (size_t nPos = 0, nSize = maSupbookList.GetSize(); nPos < nSize; ++nPos)
+ {
+ XclExpSupbookRef xRef( maSupbookList.GetRecord( nPos));
+ if (xRef->GetType() != EXC_SBTYPE_EXTERN)
+ continue; // handle only external reference (for now?)
+
+ sal_uInt16 nId = xRef->GetFileId();
+ const OUString& rUrl = xRef->GetUrl();
+ ::std::pair< ::std::map< sal_uInt16, OUString >::iterator, bool > xInsert(
+ aMap.insert( ::std::make_pair( nId, rUrl)));
+ if (!xInsert.second)
+ {
+ SAL_WARN( "sc.filter", "XclExpSupbookBuffer::SaveXml: file ID already used: " << nId <<
+ " wanted for " << rUrl << " and is " << (*xInsert.first).second <<
+ (rUrl == (*xInsert.first).second ? " multiple Supbook not supported" : ""));
+ continue;
+ }
+
+ OUString sId;
+ sax_fastparser::FSHelperPtr pExternalLink = rStrm.CreateOutputStream(
+ XclXmlUtils::GetStreamName( "xl/", "externalLinks/externalLink", nId),
+ XclXmlUtils::GetStreamName( NULL, "externalLinks/externalLink", nId),
+ rStrm.GetCurrentStream()->getOutputStream(),
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.externalLink+xml",
+ CREATE_OFFICEDOC_RELATION_TYPE("externalLink"),
+ &sId );
+
+ // externalReference entry in workbook externalReferences
+ rStrm.GetCurrentStream()->singleElement( XML_externalReference,
+ FSNS( XML_r, XML_id ), XclXmlUtils::ToOString( sId ).getStr(),
+ FSEND );
+
+ // Each externalBook in a separate stream.
+ rStrm.PushStream( pExternalLink );
+ xRef->SaveXml( rStrm );
+ rStrm.PopStream();
+ }
+}
+
bool XclExpSupbookBuffer::GetSupbookUrl(
XclExpSupbookRef& rxSupbook, sal_uInt16& rnIndex, const OUString& rUrl ) const
{
@@ -1992,6 +2228,11 @@ void XclExpLinkManagerImpl5::Save( XclExpStream& rStrm )
}
}
+void XclExpLinkManagerImpl5::SaveXml( XclExpXmlStream& /*rStrm*/ )
+{
+ // not applicable
+}
+
sal_uInt16 XclExpLinkManagerImpl5::GetExtSheetCount() const
{
return static_cast< sal_uInt16 >( maExtSheetList.GetSize() );
@@ -2209,6 +2450,21 @@ void XclExpLinkManagerImpl8::Save( XclExpStream& rStrm )
}
}
+void XclExpLinkManagerImpl8::SaveXml( XclExpXmlStream& rStrm )
+{
+ if( !maXtiVec.empty() )
+ {
+ // externalLink, externalBook, sheetNames, sheetDataSet, externalName
+ maSBBuffer.SaveXml( rStrm );
+
+ // TODO: equivalent for EXTERNSHEET in OOXML?
+#if 0
+ for( XclExpXtiVec::const_iterator aIt = maXtiVec.begin(), aEnd = maXtiVec.end(); aIt != aEnd; ++aIt )
+ aIt->SaveXml( rStrm );
+#endif
+ }
+}
+
sal_uInt16 XclExpLinkManagerImpl8::InsertXti( const XclExpXti& rXti )
{
for( XclExpXtiVec::const_iterator aIt = maXtiVec.begin(), aEnd = maXtiVec.end(); aIt != aEnd; ++aIt )
@@ -2315,4 +2571,9 @@ void XclExpLinkManager::Save( XclExpStream& rStrm )
mxImpl->Save( rStrm );
}
+void XclExpLinkManager::SaveXml( XclExpXmlStream& rStrm )
+{
+ mxImpl->SaveXml( rStrm );
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/inc/xecontent.hxx b/sc/source/filter/inc/xecontent.hxx
index 0a6705c31f60..214229397860 100644
--- a/sc/source/filter/inc/xecontent.hxx
+++ b/sc/source/filter/inc/xecontent.hxx
@@ -110,13 +110,14 @@ public:
virtual void WriteEmbeddedData( XclExpStream& rStrm );
void SetDisplay( bool bDisplay ) { mbSetDisplay = bDisplay; }
-private:
+
/** Builds file name from the passed file URL. Tries to convert to relative file name.
@param rnLevel (out-param) The parent directory level.
@param rbRel (out-param) true = path is relative. */
- OUString BuildFileName(
+ static OUString BuildFileName(
sal_uInt16& rnLevel, bool& rbRel,
- const OUString& rUrl, const XclExpRoot& rRoot ) const;
+ const OUString& rUrl, const XclExpRoot& rRoot );
+private:
/** Writes the body of the HLINK record. */
virtual void WriteBody( XclExpStream& rStrm ) SAL_OVERRIDE;
diff --git a/sc/source/filter/inc/xelink.hxx b/sc/source/filter/inc/xelink.hxx
index 444192e820fe..89d8b2f17303 100644
--- a/sc/source/filter/inc/xelink.hxx
+++ b/sc/source/filter/inc/xelink.hxx
@@ -200,6 +200,9 @@ public:
/** Writes the entire Link table. */
virtual void Save( XclExpStream& rStrm ) SAL_OVERRIDE;
+ /** Writes the entire Link table to OOXML. */
+ virtual void SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
+
private:
typedef boost::shared_ptr< XclExpLinkManagerImpl > XclExpLinkMgrImplPtr;
XclExpLinkMgrImplPtr mxImpl;