summaryrefslogtreecommitdiff
path: root/sc/source/filter
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/filter')
-rw-r--r--sc/source/filter/excel/xelink.cxx427
-rw-r--r--sc/source/filter/excel/xihelper.cxx4
-rw-r--r--sc/source/filter/excel/xilink.cxx12
-rw-r--r--sc/source/filter/excel/xistyle.cxx67
-rw-r--r--sc/source/filter/excel/xlformula.cxx184
-rw-r--r--sc/source/filter/excel/xltools.cxx108
-rw-r--r--sc/source/filter/inc/xihelper.hxx6
-rw-r--r--sc/source/filter/inc/xistyle.hxx5
-rw-r--r--sc/source/filter/inc/xltools.hxx2
9 files changed, 413 insertions, 402 deletions
diff --git a/sc/source/filter/excel/xelink.cxx b/sc/source/filter/excel/xelink.cxx
index 421a15b6da95..fcf738527025 100644
--- a/sc/source/filter/excel/xelink.cxx
+++ b/sc/source/filter/excel/xelink.cxx
@@ -43,7 +43,8 @@
using ::std::auto_ptr;
using ::std::find_if;
using ::std::vector;
-using namespace formula;
+using ::rtl::OUString;
+using ::com::sun::star::uno::Any;
// ============================================================================
// *** Helper classes ***
@@ -166,105 +167,59 @@ private:
// Cached external cells ======================================================
-/** Base class to store the contents of one external cell (record CRN). */
+/** Stores the contents of a consecutive row of external cells (record CRN). */
class XclExpCrn : public XclExpRecord
{
-protected:
- /** @param nAddSize The size of additional data derived classes will write. */
- explicit XclExpCrn( SCCOL nScCol, SCROW nScRow, sal_uInt8 nId, sal_uInt32 nAddLen = 0 );
-
-private:
- /** Writes the start of the record that is equal in all CRN records and calls WriteAddData(). */
- virtual void WriteBody( XclExpStream& rStrm );
-
- /** Called to write additional data following the common record contents.
- @descr Derived classes should overwrite this function to write their data. */
- virtual void WriteAddData( XclExpStream& rStrm ) = 0;
-
-private:
- sal_uInt16 mnXclCol; /// Column index of the external cell.
- sal_uInt16 mnXclRow; /// Row index of the external cell.
- sal_uInt8 mnId; /// Identifier for data type (EXC_CACHEDVAL_***).
-};
-
-// ----------------------------------------------------------------------------
-
-/** Cached data of an external value cell. */
-class XclExpCrnDouble : public XclExpCrn
-{
public:
- explicit XclExpCrnDouble( SCCOL nScCol, SCROW nScRow, double fVal );
+ explicit XclExpCrn( SCCOL nScCol, SCROW nScRow, const Any& rValue );
-private:
- /** Writes the double value following the common record contents. */
- virtual void WriteAddData( XclExpStream& rStrm );
+ /** Returns true, if the passed value could be appended to this record. */
+ bool InsertValue( SCCOL nScCol, SCROW nScRow, const Any& rValue );
private:
- double mfVal; /// Value of the cached cell.
-};
-
-// ----------------------------------------------------------------------------
+ virtual void WriteBody( XclExpStream& rStrm );
-/** Cached data of an external text cell. */
-class XclExpCrnString : public XclExpCrn
-{
-public:
- explicit XclExpCrnString( SCCOL nScCol, SCROW nScRow, const String& rText );
+ void WriteBool( XclExpStream& rStrm, bool bValue );
+ void WriteDouble( XclExpStream& rStrm, double fValue );
+ void WriteString( XclExpStream& rStrm, const OUString& rValue );
+ void WriteError( XclExpStream& rStrm, sal_uInt8 nErrCode );
+ void WriteEmpty( XclExpStream& rStrm );
private:
- /** Writes the string following the common record contents. */
- virtual void WriteAddData( XclExpStream& rStrm );
+ typedef ::std::vector< Any > CachedValues;
-private:
- XclExpString maText; /// Text of the cached cell.
+ CachedValues maValues; /// All cached values.
+ SCCOL mnScCol; /// Column index of the first external cell.
+ SCROW mnScRow; /// Row index of the external cells.
};
// ----------------------------------------------------------------------------
-/// Cached data of an external Boolean cell. */
-class XclExpCrnBool : public XclExpCrn
-{
-public:
- explicit XclExpCrnBool( SCCOL nScCol, SCROW nScRow, bool bBoolVal );
-
-private:
- /** Writes the Boolean value following the common record contents. */
- virtual void WriteAddData( XclExpStream& rStrm );
-
-private:
- sal_uInt16 mnBool; /// Boolean value of the cached cell.
-};
-
-// Cached cells of a sheet ====================================================
-
-/// Represents the record XCT which is the header record of a CRN record list. */
-class XclExpXct : public XclExpRecord
+/** Represents the record XCT which is the header record of a CRN record list.
+ */
+class XclExpXct : public XclExpRecordBase, protected XclExpRoot
{
public:
- explicit XclExpXct( const String& rTabName, sal_uInt16 nSBTab );
+ explicit XclExpXct( const XclExpRoot& rRoot,
+ const String& rTabName, sal_uInt16 nSBTab,
+ ScExternalRefCache::TableTypeRef xCacheTable );
/** Returns the external sheet name. */
inline const XclExpString& GetTabName() const { return maTabName; }
/** Stores all cells in the given range in the CRN list. */
- void StoreCellRange( const XclExpRoot& rRoot, const ScRange& rRange );
+ void StoreCellRange( const ScRange& rRange );
- void StoreCell( const XclExpRoot& rRoot, const ScAddress& rCell, const formula::FormulaToken& rToken );
- void StoreCellRange( const XclExpRoot& rRoot, const ScRange& rRange, const formula::FormulaToken& rToken );
+ void StoreCell( const ScAddress& rCell, const ::formula::FormulaToken& rToken );
+ void StoreCellRange( const ScRange& rRange, const ::formula::FormulaToken& rToken );
/** Writes the XCT and all CRN records. */
virtual void Save( XclExpStream& rStrm );
private:
- /** Writes the XCT record contents. */
- virtual void WriteBody( XclExpStream& rStrm );
-
-private:
- typedef XclExpRecordList< XclExpCrn > XclExpCrnList;
- typedef XclExpCrnList::RecordRefType XclExpCrnRef;
-
- XclExpCrnList maCrnList; /// CRN records that follow this record.
+ 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.
};
@@ -353,14 +308,14 @@ 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 formula::FormulaToken& rToken );
- void StoreCellRange( sal_uInt16 nSBTab, const ScRange& rRange, const formula::FormulaToken& rToken );
+ void StoreCell( sal_uInt16 nSBTab, const ScAddress& rCell, const ::formula::FormulaToken& rToken );
+ void StoreCellRange( sal_uInt16 nSBTab, const ScRange& rRange, const ::formula::FormulaToken& 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 );
+ sal_uInt16 InsertTabName( const String& rTabName, ScExternalRefCache::TableTypeRef xCacheTable );
/** Finds or inserts an EXTERNNAME record for add-ins.
@return The 1-based EXTERNNAME record index; or 0, if the record list is full. */
sal_uInt16 InsertAddIn( const String& rName );
@@ -1006,6 +961,7 @@ void XclExpExtName::WriteAddData( XclExpStream& rStrm )
// range address. Excel just writes '02 00 1C 17' for all the other types
// of external names.
+ using namespace ::formula;
do
{
if (mpArray->GetLen() != 1)
@@ -1162,209 +1118,200 @@ sal_uInt16 XclExpExtNameBuffer::AppendNew( XclExpExtNameBase* pExtName )
// Cached external cells ======================================================
-XclExpCrn::XclExpCrn( SCCOL nScCol, SCROW nScRow, sal_uInt8 nId, sal_uInt32 nAddLen ) :
- XclExpRecord( EXC_ID_CRN, 5 + nAddLen ),
- mnXclCol( static_cast< sal_uInt16 >( nScCol ) ),
- mnXclRow( static_cast< sal_uInt16 >( nScRow ) ),
- mnId( nId )
+XclExpCrn::XclExpCrn( SCCOL nScCol, SCROW nScRow, const Any& rValue ) :
+ XclExpRecord( EXC_ID_CRN, 4 ),
+ mnScCol( nScCol ),
+ mnScRow( nScRow )
{
+ maValues.push_back( rValue );
}
-void XclExpCrn::WriteBody( XclExpStream& rStrm )
+bool XclExpCrn::InsertValue( SCCOL nScCol, SCROW nScRow, const Any& rValue )
{
- rStrm << static_cast< sal_uInt8 >( mnXclCol )
- << static_cast< sal_uInt8 >( mnXclCol )
- << mnXclRow
- << mnId;
- WriteAddData( rStrm );
+ if( (nScRow != mnScRow) || (nScCol != static_cast< SCCOL >( mnScCol + maValues.size() )) )
+ return false;
+ maValues.push_back( rValue );
+ return true;
}
-// ----------------------------------------------------------------------------
-
-XclExpCrnDouble::XclExpCrnDouble( SCCOL nScCol, SCROW nScRow, double fVal ) :
- XclExpCrn( nScCol, nScRow, EXC_CACHEDVAL_DOUBLE, 8 ),
- mfVal( fVal )
+void XclExpCrn::WriteBody( XclExpStream& rStrm )
{
+ rStrm << static_cast< sal_uInt8 >( mnScCol + maValues.size() - 1 )
+ << static_cast< sal_uInt8 >( mnScCol )
+ << static_cast< sal_uInt16 >( mnScRow );
+ for( CachedValues::iterator aIt = maValues.begin(), aEnd = maValues.end(); aIt != aEnd; ++aIt )
+ {
+ if( aIt->has< bool >() )
+ WriteBool( rStrm, aIt->get< bool >() );
+ else if( aIt->has< double >() )
+ WriteDouble( rStrm, aIt->get< double >() );
+ else if( aIt->has< OUString >() )
+ WriteString( rStrm, aIt->get< OUString >() );
+ else
+ WriteEmpty( rStrm );
+ }
}
-void XclExpCrnDouble::WriteAddData( XclExpStream& rStrm )
+void XclExpCrn::WriteBool( XclExpStream& rStrm, bool bValue )
{
- rStrm << mfVal;
+ rStrm << EXC_CACHEDVAL_BOOL << sal_uInt8( bValue ? 1 : 0);
+ rStrm.WriteZeroBytes( 7 );
}
-// ----------------------------------------------------------------------------
-
-XclExpCrnString::XclExpCrnString( SCCOL nScCol, SCROW nScRow, const String& rText ) :
- XclExpCrn( nScCol, nScRow, EXC_CACHEDVAL_STRING ),
- maText( rText )
+void XclExpCrn::WriteDouble( XclExpStream& rStrm, double fValue )
{
- // set correct size after maText is initialized
- AddRecSize( maText.GetSize() );
+ if( ::rtl::math::isNan( fValue ) )
+ {
+ USHORT nScError = static_cast< USHORT >( reinterpret_cast< const sal_math_Double* >( &fValue )->nan_parts.fraction_lo );
+ WriteError( rStrm, XclTools::GetXclErrorCode( nScError ) );
+ }
+ else
+ {
+ rStrm << EXC_CACHEDVAL_DOUBLE << fValue;
+ }
}
-void XclExpCrnString::WriteAddData( XclExpStream& rStrm )
+void XclExpCrn::WriteString( XclExpStream& rStrm, const OUString& rValue )
{
- rStrm << maText;
+ rStrm << EXC_CACHEDVAL_STRING << XclExpString( rValue );
}
-// ----------------------------------------------------------------------------
-
-XclExpCrnBool::XclExpCrnBool( SCCOL nScCol, SCROW nScRow, bool bBoolVal ) :
- XclExpCrn( nScCol, nScRow, EXC_CACHEDVAL_BOOL, 8 ),
- mnBool( bBoolVal ? 1 : 0 )
+void XclExpCrn::WriteError( XclExpStream& rStrm, sal_uInt8 nErrCode )
{
+ rStrm << EXC_CACHEDVAL_ERROR << nErrCode;
+ rStrm.WriteZeroBytes( 7 );
}
-void XclExpCrnBool::WriteAddData( XclExpStream& rStrm )
+void XclExpCrn::WriteEmpty( XclExpStream& rStrm )
{
- rStrm << mnBool;
- rStrm.WriteZeroBytes( 6 );
+ rStrm << EXC_CACHEDVAL_EMPTY;
+ rStrm.WriteZeroBytes( 8 );
}
// Cached cells of a sheet ====================================================
-XclExpXct::XclExpXct( const String& rTabName, sal_uInt16 nSBTab ) :
- XclExpRecord( EXC_ID_XCT, 4 ),
+XclExpXct::XclExpXct( const XclExpRoot& rRoot, const String& rTabName,
+ sal_uInt16 nSBTab, ScExternalRefCache::TableTypeRef xCacheTable ) :
+ XclExpRoot( rRoot ),
+ mxCacheTable( xCacheTable ),
+ maBoundRange( ScAddress::INITIALIZE_INVALID ),
maTabName( rTabName ),
mnSBTab( nSBTab )
{
}
-void XclExpXct::StoreCellRange( const XclExpRoot& rRoot, const ScRange& rRange )
+void XclExpXct::StoreCellRange( const ScRange& rRange )
{
// #i70418# restrict size of external range to prevent memory overflow
if( (rRange.aEnd.Col() - rRange.aStart.Col()) * (rRange.aEnd.Row() - rRange.aStart.Row()) > 1024 )
return;
- ScDocument& rDoc = rRoot.GetDoc();
- SvNumberFormatter& rFormatter = rRoot.GetFormatter();
- SCTAB nScTab = rRange.aStart.Tab();
- SCCOL nScLastCol = rRange.aEnd.Col();
- SCROW nScLastRow = rRange.aEnd.Row();
+ maUsedCells.SetMultiMarkArea( rRange );
+ maBoundRange.ExtendTo( rRange );
+}
- for( SCROW nScRow = rRange.aStart.Row(); nScRow <= nScLastRow; ++nScRow )
- {
- for( SCCOL nScCol = rRange.aStart.Col(); nScCol <= nScLastCol; ++nScCol )
- {
- if( !maUsedCells.IsCellMarked( nScCol, nScRow, TRUE ) )
- {
- XclExpCrnRef xCrn;
- if( rDoc.HasValueData( nScCol, nScRow, nScTab ) )
- {
- ScAddress aAddr( nScCol, nScRow, nScTab );
- double fVal = rDoc.GetValue( aAddr );
- ULONG nFormat = rDoc.GetNumberFormat( aAddr );
- short nType = rFormatter.GetType( nFormat );
- bool bIsBool = (nType == NUMBERFORMAT_LOGICAL);
-
- if( !bIsBool && ((nFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0) &&
- (rDoc.GetCellType( aAddr ) == CELLTYPE_FORMULA) )
- if( ScFormulaCell* pCell = static_cast< ScFormulaCell* >( rDoc.GetCell( aAddr ) ) )
- bIsBool = (pCell->GetFormatType() == NUMBERFORMAT_LOGICAL);
-
- if( bIsBool && ((fVal == 0.0) || (fVal == 1.0)) )
- xCrn.reset( new XclExpCrnBool( nScCol, nScRow, (fVal == 1.0) ) );
- else
- xCrn.reset( new XclExpCrnDouble( nScCol, nScRow, fVal ) );
- }
- else
- {
- String aText;
- rDoc.GetString( nScCol, nScRow, nScTab, aText );
- xCrn.reset( new XclExpCrnString( nScCol, nScRow, aText ) );
- }
- maCrnList.AppendRecord( xCrn );
- }
- }
- }
+void XclExpXct::StoreCell( const ScAddress& rCell, const ::formula::FormulaToken& rToken )
+{
+ maUsedCells.SetMultiMarkArea( ScRange( rCell ) );
+ maBoundRange.ExtendTo( ScRange( rCell ) );
+ (void)rToken;
+}
+void XclExpXct::StoreCellRange( const ScRange& rRange, const ::formula::FormulaToken& rToken )
+{
maUsedCells.SetMultiMarkArea( rRange );
+ maBoundRange.ExtendTo( rRange );
+ (void)rToken;
}
-void XclExpXct::StoreCell( const XclExpRoot& /*rRoot*/, const ScAddress& rCell, const formula::FormulaToken& rToken )
+namespace {
+
+class XclExpCrnList : public XclExpRecordList< XclExpCrn >
{
- 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
- }
+public:
+ /** Inserts the passed value into an existing or new CRN record.
+ @return True = value inserted successfully, false = CRN list is full. */
+ bool InsertValue( SCCOL nScCol, SCROW nScRow, const Any& rValue );
+};
+
+bool XclExpCrnList::InsertValue( SCCOL nScCol, SCROW nScRow, const Any& rValue )
+{
+ RecordRefType xLastRec = GetLastRecord();
+ if( xLastRec.is() && xLastRec->InsertValue( nScCol, nScRow, rValue ) )
+ return true;
+ if( GetSize() == SAL_MAX_UINT16 )
+ return false;
+ AppendNewRecord( new XclExpCrn( nScCol, nScRow, rValue ) );
+ return true;
}
-void XclExpXct::StoreCellRange( const XclExpRoot& /*rRoot*/, const ScRange& rRange, const formula::FormulaToken& rToken )
+} // namespace
+
+void XclExpXct::Save( XclExpStream& rStrm )
{
- if (rToken.GetType() != svMatrix)
+ if( !mxCacheTable )
return;
- if (rRange.aStart.Tab() != rRange.aEnd.Tab())
- // multi-table range is not supported here.
+ /* 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
+ contain all referred cells, e.g. if big empty ranges are used in the
+ formulas. */
+ ::std::pair< SCROW, SCROW > aRowRange = mxCacheTable->getRowRange();
+ if( aRowRange.first >= aRowRange.second )
return;
- const ScMatrix* pMtx = static_cast<const ScToken*>(&rToken)->GetMatrix();
- if (!pMtx)
+ /* 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;
- 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!
+ /* 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;
- }
- for (SCCOL nCol = 0; nCol < static_cast< SCCOL >( nCols ); ++nCol)
+ /* 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 )
{
- for (SCROW nRow = 0; nRow < static_cast< SCROW >( nRows ); ++nRow)
+ ::std::pair< SCCOL, SCCOL > aColRange = mxCacheTable->getColRange( nScRow );
+ for( SCCOL nScCol = aColRange.first; bValid && (nScCol < aColRange.second); ++nScCol )
{
- if (pMtx->IsString(nCol, nRow))
+ if( maUsedCells.IsCellMarked( nScCol, nScRow, TRUE ) )
{
- 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);
+ sal_uInt32 nScNumFmt = 0;
+ ScExternalRefCache::TokenRef xToken = mxCacheTable->getCell( nScCol, nScRow, &nScNumFmt );
+ using namespace ::formula;
+ if( xToken.get() ) switch( xToken->GetType() )
+ {
+ case svDouble:
+ bValid = (rFormatter.GetType( nScNumFmt ) == NUMBERFORMAT_LOGICAL) ?
+ aCrnRecs.InsertValue( nScCol, nScRow, Any( xToken->GetDouble() != 0 ) ) :
+ aCrnRecs.InsertValue( nScCol, nScRow, Any( xToken->GetDouble() ) );
+ break;
+ case svString:
+ // do not save empty strings (empty cells) to cache
+ if( xToken->GetString().Len() > 0 )
+ bValid = aCrnRecs.InsertValue( nScCol, nScRow, Any( OUString( xToken->GetString() ) ) );
+ break;
+ default:
+ break;
+ }
}
}
}
-}
-void XclExpXct::Save( XclExpStream& rStrm )
-{
- XclExpRecord::Save( rStrm );
- maCrnList.Save( rStrm );
-}
-
-void XclExpXct::WriteBody( XclExpStream& rStrm )
-{
- sal_uInt16 nCount = ulimit_cast< sal_uInt16 >( maCrnList.GetSize() );
- rStrm << nCount << mnSBTab;
+ // write the XCT record and the list of CRN records
+ rStrm.StartRecord( EXC_ID_XCT, 4 );
+ rStrm << static_cast< sal_uInt16 >( aCrnRecs.GetSize() ) << mnSBTab;
+ rStrm.EndRecord();
+ aCrnRecs.Save( rStrm );
}
// External documents (EXTERNSHEET/SUPBOOK), base class =======================
@@ -1471,15 +1418,11 @@ XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, const String& rUrl ) :
// 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);
+ sal_uInt16 nFileId = pRefMgr->getExternalFileId( rUrl );
+ ScfStringVec aTabNames;
+ pRefMgr->getAllCachedTableNames( nFileId, aTabNames );
+ for( ScfStringVec::const_iterator aBeg = aTabNames.begin(), aIt = aBeg, aEnd = aTabNames.end(); aIt != aEnd; ++aIt )
+ InsertTabName( *aIt, pRefMgr->getCacheTable( nFileId, aIt - aBeg ) );
}
XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, const String& rApplic, const String& rTopic ) :
@@ -1513,31 +1456,22 @@ void XclExpSupbook::FillRefLogEntry( XclExpRefLogEntry& rRefLogEntry,
void XclExpSupbook::StoreCellRange( const ScRange& rRange, sal_uInt16 nSBTab )
{
- XclExpXctRef xXct = maXctList.GetRecord( nSBTab );
- if( xXct.is() )
- xXct->StoreCellRange( GetRoot(), rRange );
+ if( XclExpXct* pXct = maXctList.GetRecord( nSBTab ).get() )
+ pXct->StoreCellRange( rRange );
}
void XclExpSupbook::StoreCell( sal_uInt16 nSBTab, const ScAddress& rCell, const formula::FormulaToken& rToken )
{
- XclExpXctRef xXct = maXctList.GetRecord(nSBTab);
- if (!xXct.is())
- return;
-
- xXct->StoreCell(GetRoot(), rCell, rToken);
+ if( XclExpXct* pXct = maXctList.GetRecord( nSBTab ).get() )
+ pXct->StoreCell( rCell, rToken );
}
void XclExpSupbook::StoreCellRange( sal_uInt16 nSBTab, const ScRange& rRange, const formula::FormulaToken& 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);
+ // multi-table range is not allowed!
+ if( rRange.aStart.Tab() == rRange.aEnd.Tab() )
+ if( XclExpXct* pXct = maXctList.GetRecord( nSBTab ).get() )
+ pXct->StoreCellRange( rRange, rToken );
}
sal_uInt16 XclExpSupbook::GetTabIndex( const String& rTabName ) const
@@ -1558,11 +1492,11 @@ sal_uInt16 XclExpSupbook::GetTabCount() const
return ulimit_cast<sal_uInt16>(maXctList.GetSize());
}
-sal_uInt16 XclExpSupbook::InsertTabName( const String& rTabName )
+sal_uInt16 XclExpSupbook::InsertTabName( const String& rTabName, ScExternalRefCache::TableTypeRef xCacheTable )
{
DBG_ASSERT( meType == EXC_SBTYPE_EXTERN, "XclExpSupbook::InsertTabName - don't insert sheet names here" );
sal_uInt16 nSBTab = ulimit_cast< sal_uInt16 >( maXctList.GetSize() );
- XclExpXctRef xXct( new XclExpXct( rTabName, nSBTab ) );
+ XclExpXctRef xXct( new XclExpXct( GetRoot(), rTabName, nSBTab, xCacheTable ) );
AddRecSize( xXct->GetTabName().GetSize() );
maXctList.AppendRecord( xXct );
return nSBTab;
@@ -1786,6 +1720,7 @@ void XclExpSupbookBuffer::StoreCellRange( sal_uInt16 nFileId, const String& rTab
SCTAB nTabCount = rRange.aEnd.Tab() - rRange.aStart.Tab() + 1;
// If this is a multi-table range, get token for each table.
+ using namespace ::formula;
vector<FormulaToken*> aMatrixList;
aMatrixList.reserve(nTabCount);
diff --git a/sc/source/filter/excel/xihelper.cxx b/sc/source/filter/excel/xihelper.cxx
index 1afcba154c4a..ad04a1f3930c 100644
--- a/sc/source/filter/excel/xihelper.cxx
+++ b/sc/source/filter/excel/xihelper.cxx
@@ -837,7 +837,7 @@ XclImpCachedValue::~XclImpCachedValue()
{
}
-USHORT XclImpCachedValue::GetError() const
+USHORT XclImpCachedValue::GetScError() const
{
return (mnType == EXC_CACHEDVAL_ERROR) ? XclTools::GetScErrorCode( mnBoolErr ) : 0;
}
@@ -901,7 +901,7 @@ ScMatrixRef XclImpCachedMatrix::CreateScMatrix() const
xScMatrix->PutBoolean( pValue->GetBool(), nScCol, nScRow );
break;
case EXC_CACHEDVAL_ERROR:
- xScMatrix->PutError( pValue->GetError(), nScCol, nScRow );
+ xScMatrix->PutError( pValue->GetScError(), nScCol, nScRow );
break;
default:
DBG_ERRORFILE( "XclImpCachedMatrix::CreateScMatrix - unknown value type" );
diff --git a/sc/source/filter/excel/xilink.cxx b/sc/source/filter/excel/xilink.cxx
index 1183b077b626..45eed0fd98a9 100644
--- a/sc/source/filter/excel/xilink.cxx
+++ b/sc/source/filter/excel/xilink.cxx
@@ -413,6 +413,11 @@ void XclImpSupbookTab::LoadCachedValues(ScExternalRefCache::TableTypeRef pCacheT
switch (p->GetType())
{
case EXC_CACHEDVAL_BOOL:
+ {
+ bool b = p->GetBool();
+ ScExternalRefCache::TokenRef pToken(new formula::FormulaDoubleToken(b ? 1.0 : 0.0));
+ pCacheTable->setCell(rAddr.mnCol, rAddr.mnRow, pToken);
+ }
break;
case EXC_CACHEDVAL_DOUBLE:
{
@@ -421,9 +426,12 @@ void XclImpSupbookTab::LoadCachedValues(ScExternalRefCache::TableTypeRef pCacheT
pCacheTable->setCell(rAddr.mnCol, rAddr.mnRow, pToken);
}
break;
- case EXC_CACHEDVAL_EMPTY:
- break;
case EXC_CACHEDVAL_ERROR:
+ {
+ double fError = XclTools::ErrorToDouble( p->GetXclError() );
+ ScExternalRefCache::TokenRef pToken(new formula::FormulaDoubleToken(fError));
+ pCacheTable->setCell(rAddr.mnCol, rAddr.mnRow, pToken);
+ }
break;
case EXC_CACHEDVAL_STRING:
{
diff --git a/sc/source/filter/excel/xistyle.cxx b/sc/source/filter/excel/xistyle.cxx
index 4e0ff5079471..1559ef5530f5 100644
--- a/sc/source/filter/excel/xistyle.cxx
+++ b/sc/source/filter/excel/xistyle.cxx
@@ -701,7 +701,6 @@ void XclImpCellAlign::FillToItemSet( SfxItemSet& rItemSet, const XclImpFont* pFo
sal_uInt8 nXclRot = (mnOrient == EXC_ORIENT_NONE) ? mnRotation : XclTools::GetXclRotFromOrient( mnOrient );
bool bStacked = (nXclRot == EXC_ROT_STACKED);
ScfTools::PutItem( rItemSet, SfxBoolItem( ATTR_STACKED, bStacked ), bSkipPoolDefs );
- ScfTools::PutItem( rItemSet, SvxRotateModeItem( SVX_ROTATE_MODE_STANDARD, ATTR_ROTATE_MODE ), bSkipPoolDefs );
// set an angle in the range from -90 to 90 degrees
sal_Int32 nAngle = XclTools::GetScRotation( nXclRot, 0 );
ScfTools::PutItem( rItemSet, SfxInt32Item( ATTR_ROTATE_VALUE, nAngle ), bSkipPoolDefs );
@@ -799,6 +798,15 @@ void XclImpCellBorder::FillFromCF8( sal_uInt16 nLineStyle, sal_uInt32 nLineColor
mbDiagUsed = false;
}
+bool XclImpCellBorder::HasAnyOuterBorder() const
+{
+ return
+ (mbLeftUsed && (mnLeftLine != EXC_LINE_NONE)) ||
+ (mbRightUsed && (mnRightLine != EXC_LINE_NONE)) ||
+ (mbTopUsed && (mnTopLine != EXC_LINE_NONE)) ||
+ (mbBottomUsed && (mnBottomLine != EXC_LINE_NONE));
+}
+
namespace {
/** Converts the passed line style to a SvxBorderLine, or returns false, if style is "no line". */
@@ -1091,13 +1099,32 @@ const ScPatternAttr& XclImpXF::CreatePattern( bool bSkipPoolDefs )
// create new pattern attribute set
mpPattern.reset( new ScPatternAttr( GetDoc().GetPool() ) );
SfxItemSet& rItemSet = mpPattern->GetItemSet();
+ XclImpXF* pParentXF = IsCellXF() ? GetXFBuffer().GetXF( mnParent ) : 0;
// parent cell style
if( IsCellXF() && !mpStyleSheet )
{
mpStyleSheet = GetXFBuffer().CreateStyleSheet( mnParent );
- if( XclImpXF* pParentXF = GetXFBuffer().GetXF( mnParent ) )
- UpdateUsedFlags( *pParentXF );
+
+ /* Enables mb***Used flags, if the formatting attributes differ from
+ the passed XF record. In cell XFs Excel uses the cell attributes,
+ if they differ from the parent style XF.
+ #109899# ...or if the respective flag is not set in parent style XF. */
+ if( pParentXF )
+ {
+ if( !mbProtUsed )
+ mbProtUsed = !pParentXF->mbProtUsed || !(maProtection == pParentXF->maProtection);
+ if( !mbFontUsed )
+ mbFontUsed = !pParentXF->mbFontUsed || (mnXclFont != pParentXF->mnXclFont);
+ if( !mbFmtUsed )
+ mbFmtUsed = !pParentXF->mbFmtUsed || (mnXclNumFmt != pParentXF->mnXclNumFmt);
+ if( !mbAlignUsed )
+ mbAlignUsed = !pParentXF->mbAlignUsed || !(maAlignment == pParentXF->maAlignment);
+ if( !mbBorderUsed )
+ mbBorderUsed = !pParentXF->mbBorderUsed || !(maBorder == pParentXF->maBorder);
+ if( !mbAreaUsed )
+ mbAreaUsed = !pParentXF->mbAreaUsed || !(maArea == pParentXF->maArea);
+ }
}
// cell protection
@@ -1137,6 +1164,20 @@ const ScPatternAttr& XclImpXF::CreatePattern( bool bSkipPoolDefs )
maArea.mnPattern != EXC_PATT_SOLID);
}
+ /* #i38709# Decide which rotation reference mode to use. If any outer
+ border line of the cell is set (either explicitly or via cell style),
+ and the cell contents are rotated, set rotation reference to bottom of
+ cell. This causes the borders to be painted rotated with the text. */
+ if( mbAlignUsed || mbBorderUsed )
+ {
+ SvxRotateMode eRotateMode = SVX_ROTATE_MODE_STANDARD;
+ const XclImpCellAlign* pAlign = mbAlignUsed ? &maAlignment : (pParentXF ? &pParentXF->maAlignment : 0);
+ const XclImpCellBorder* pBorder = mbBorderUsed ? &maBorder : (pParentXF ? &pParentXF->maBorder : 0);
+ if( pAlign && pBorder && (0 < pAlign->mnRotation) && (pAlign->mnRotation <= 180) && pBorder->HasAnyOuterBorder() )
+ eRotateMode = SVX_ROTATE_MODE_BOTTOM;
+ ScfTools::PutItem( rItemSet, SvxRotateModeItem( eRotateMode, ATTR_ROTATE_MODE ), bSkipPoolDefs );
+ }
+
return *mpPattern;
}
@@ -1180,26 +1221,6 @@ void XclImpXF::SetUsedFlags( sal_uInt8 nUsedFlags )
mbAreaUsed = (mbCellXF == ::get_flag( nUsedFlags, EXC_XF_DIFF_AREA ));
}
-void XclImpXF::UpdateUsedFlags( const XclImpXF& rParentXF )
-{
- /* Enables mb***Used flags, if the formatting attributes differ from
- the passed XF record. In cell XFs Excel uses the cell attributes,
- if they differ from the parent style XF.
- #109899# ...or if the respective flag is not set in parent style XF. */
- if( !mbProtUsed )
- mbProtUsed = !rParentXF.mbProtUsed || !(maProtection == rParentXF.maProtection);
- if( !mbFontUsed )
- mbFontUsed = !rParentXF.mbFontUsed || (mnXclFont != rParentXF.mnXclFont);
- if( !mbFmtUsed )
- mbFmtUsed = !rParentXF.mbFmtUsed || (mnXclNumFmt != rParentXF.mnXclNumFmt);
- if( !mbAlignUsed )
- mbAlignUsed = !rParentXF.mbAlignUsed || !(maAlignment == rParentXF.maAlignment);
- if( !mbBorderUsed )
- mbBorderUsed = !rParentXF.mbBorderUsed || !(maBorder == rParentXF.maBorder);
- if( !mbAreaUsed )
- mbAreaUsed = !rParentXF.mbAreaUsed || !(maArea == rParentXF.maArea);
-}
-
// ----------------------------------------------------------------------------
XclImpStyle::XclImpStyle( const XclImpRoot& rRoot ) :
diff --git a/sc/source/filter/excel/xlformula.cxx b/sc/source/filter/excel/xlformula.cxx
index c46df189ab74..d613f1279242 100644
--- a/sc/source/filter/excel/xlformula.cxx
+++ b/sc/source/filter/excel/xlformula.cxx
@@ -68,22 +68,28 @@ const sal_uInt8 A = EXC_TOKCLASS_ARR;
#define VR_E { EXC_PARAM_EXCELONLY, EXC_PARAMCONV_RPT, true }
#define C { EXC_PARAM_CALCONLY, EXC_PARAMCONV_ORG, false }
+const sal_uInt16 NOID = SAL_MAX_UINT16; /// No BIFF/OOBIN function identifier available.
+const sal_uInt8 MX = 30; /// Maximum parameter count.
+
+#define EXC_FUNCNAME( ascii ) "_xlfn." ascii
+#define EXC_FUNCNAME_ODF( ascii ) "_xlfnodf." ascii
+
/** Functions new in BIFF2. */
static const XclFunctionInfo saFuncTable_2[] =
{
- { ocCount, 0, 0, 30, V, { RX }, 0, 0 },
+ { ocCount, 0, 0, MX, V, { RX }, 0, 0 },
{ ocIf, 1, 2, 3, R, { VO, RO }, 0, 0 },
{ ocIsNA, 2, 1, 1, V, { VR }, 0, 0 },
{ ocIsError, 3, 1, 1, V, { VR }, 0, 0 },
- { ocSum, 4, 0, 30, V, { RX }, 0, 0 },
- { ocAverage, 5, 1, 30, V, { RX }, 0, 0 },
- { ocMin, 6, 1, 30, V, { RX }, 0, 0 },
- { ocMax, 7, 1, 30, V, { RX }, 0, 0 },
+ { ocSum, 4, 0, MX, V, { RX }, 0, 0 },
+ { ocAverage, 5, 1, MX, V, { RX }, 0, 0 },
+ { ocMin, 6, 1, MX, V, { RX }, 0, 0 },
+ { ocMax, 7, 1, MX, V, { RX }, 0, 0 },
{ ocRow, 8, 0, 1, V, { RO }, 0, 0 },
{ ocColumn, 9, 0, 1, V, { RO }, 0, 0 },
{ ocNotAvail, 10, 0, 0, V, {}, 0, 0 },
- { ocNPV, 11, 2, 30, V, { VR, RX }, 0, 0 },
- { ocStDev, 12, 1, 30, V, { RX }, 0, 0 },
+ { ocNPV, 11, 2, MX, V, { VR, RX }, 0, 0 },
+ { ocStDev, 12, 1, MX, V, { RX }, 0, 0 },
{ ocCurrency, 13, 1, 2, V, { VR }, 0, 0 },
{ ocFixed, 14, 1, 2, V, { VR, VR, C }, 0, 0 },
{ ocSin, 15, 1, 1, V, { VR }, 0, 0 },
@@ -109,8 +115,8 @@ static const XclFunctionInfo saFuncTable_2[] =
{ ocValue, 33, 1, 1, V, { VR }, 0, 0 },
{ ocTrue, 34, 0, 0, V, {}, 0, 0 },
{ ocFalse, 35, 0, 0, V, {}, 0, 0 },
- { ocAnd, 36, 1, 30, V, { RX }, 0, 0 },
- { ocOr, 37, 1, 30, V, { RX }, 0, 0 },
+ { ocAnd, 36, 1, MX, V, { RX }, 0, 0 },
+ { ocOr, 37, 1, MX, V, { RX }, 0, 0 },
{ ocNot, 38, 1, 1, V, { VR }, 0, 0 },
{ ocMod, 39, 2, 2, V, { VR }, 0, 0 },
{ ocDBCount, 40, 3, 3, V, { RO, RR }, 0, 0 },
@@ -119,7 +125,7 @@ static const XclFunctionInfo saFuncTable_2[] =
{ ocDBMin, 43, 3, 3, V, { RO, RR }, 0, 0 },
{ ocDBMax, 44, 3, 3, V, { RO, RR }, 0, 0 },
{ ocDBStdDev, 45, 3, 3, V, { RO, RR }, 0, 0 },
- { ocVar, 46, 1, 30, V, { RX }, 0, 0 },
+ { ocVar, 46, 1, MX, V, { RX }, 0, 0 },
{ ocDBVar, 47, 3, 3, V, { RO, RR }, 0, 0 },
{ ocText, 48, 2, 2, V, { VR }, 0, 0 },
{ ocRGP, 49, 1, 2, A, { RA, RA, C, C }, 0, 0 },
@@ -155,7 +161,7 @@ static const XclFunctionInfo saFuncTable_2[] =
{ ocArcTan2, 97, 2, 2, V, { VR }, 0, 0 },
{ ocArcSin, 98, 1, 1, V, { VR }, 0, 0 },
{ ocArcCos, 99, 1, 1, V, { VR }, 0, 0 },
- { ocChose, 100, 2, 30, R, { VO, RO }, 0, 0 },
+ { ocChose, 100, 2, MX, R, { VO, RO }, 0, 0 },
{ ocHLookup, 101, 3, 3, V, { VV, RO, RO, C }, 0, 0 },
{ ocVLookup, 102, 3, 3, V, { VV, RO, RO, C }, 0, 0 },
{ ocIsRef, 105, 1, 1, V, { RX }, 0, 0 },
@@ -191,13 +197,13 @@ static const XclFunctionInfo saFuncTable_2[] =
{ ocMatMult, 165, 2, 2, A, { VA }, 0, 0 },
{ ocZinsZ, 167, 4, 6, V, { VR }, 0, 0 },
{ ocKapz, 168, 4, 6, V, { VR }, 0, 0 },
- { ocCount2, 169, 0, 30, V, { RX }, 0, 0 },
- { ocProduct, 183, 0, 30, V, { RX }, 0, 0 },
+ { ocCount2, 169, 0, MX, V, { RX }, 0, 0 },
+ { ocProduct, 183, 0, MX, V, { RX }, 0, 0 },
{ ocFact, 184, 1, 1, V, { VR }, 0, 0 },
{ ocDBProduct, 189, 3, 3, V, { RO, RR }, 0, 0 },
{ ocIsNonString, 190, 1, 1, V, { VR }, 0, 0 },
- { ocStDevP, 193, 1, 30, V, { RX }, 0, 0 },
- { ocVarP, 194, 1, 30, V, { RX }, 0, 0 },
+ { ocStDevP, 193, 1, MX, V, { RX }, 0, 0 },
+ { ocVarP, 194, 1, MX, V, { RX }, 0, 0 },
{ ocDBStdDevP, 195, 3, 3, V, { RO, RR }, 0, 0 },
{ ocDBVarP, 196, 3, 3, V, { RO, RR }, 0, 0 },
{ ocTrunc, 197, 1, 1, V, { VR, C }, 0, 0 },
@@ -206,7 +212,7 @@ static const XclFunctionInfo saFuncTable_2[] =
{ ocCurrency, 204, 1, 2, V, { VR }, EXC_FUNCFLAG_IMPORTONLY, 0 },
{ ocRoundUp, 212, 2, 2, V, { VR }, 0, 0 },
{ ocRoundDown, 213, 2, 2, V, { VR }, 0, 0 },
- { ocExternal, 255, 1, 30, R, { RO_E, RO }, EXC_FUNCFLAG_IMPORTONLY, 0 }
+ { ocExternal, 255, 1, MX, R, { RO_E, RO }, EXC_FUNCFLAG_IMPORTONLY, 0 }
};
/** Functions new in BIFF3. */
@@ -221,8 +227,8 @@ static const XclFunctionInfo saFuncTable_3[] =
{ ocGetDiffDate360, 220, 2, 2, V, { VR, VR, C }, 0, 0 },
{ ocGetActDate, 221, 0, 0, V, {}, EXC_FUNCFLAG_VOLATILE, 0 },
{ ocVBD, 222, 5, 7, V, { VR }, 0, 0 },
- { ocMedian, 227, 1, 30, V, { RX }, 0, 0 },
- { ocSumProduct, 228, 1, 30, V, { VA }, 0, 0 },
+ { ocMedian, 227, 1, MX, V, { RX }, 0, 0 },
+ { ocSumProduct, 228, 1, MX, V, { VA }, 0, 0 },
{ ocSinHyp, 229, 1, 1, V, { VR }, 0, 0 },
{ ocCosHyp, 230, 1, 1, V, { VR }, 0, 0 },
{ ocTanHyp, 231, 1, 1, V, { VR }, 0, 0 },
@@ -245,7 +251,7 @@ static const XclFunctionInfo saFuncTable_4[] =
{ ocGDA2, 247, 4, 5, V, { VR }, 0, 0 },
{ ocFrequency, 252, 2, 2, A, { RA }, 0, 0 },
{ ocErrorType, 261, 1, 1, V, { VR }, 0, 0 },
- { ocAveDev, 269, 1, 30, V, { RX }, 0, 0 },
+ { ocAveDev, 269, 1, MX, V, { RX }, 0, 0 },
{ ocBetaDist, 270, 3, 5, V, { VR }, 0, 0 },
{ ocGammaLn, 271, 1, 1, V, { VR }, 0, 0 },
{ ocBetaInv, 272, 3, 5, V, { VR }, 0, 0 },
@@ -294,19 +300,19 @@ static const XclFunctionInfo saFuncTable_4[] =
{ ocSlope, 315, 2, 2, V, { VA }, 0, 0 },
{ ocTTest, 316, 4, 4, V, { VA, VA, VR }, 0, 0 },
{ ocProb, 317, 3, 4, V, { VA, VA, VR }, 0, 0 },
- { ocDevSq, 318, 1, 30, V, { RX }, 0, 0 },
- { ocGeoMean, 319, 1, 30, V, { RX }, 0, 0 },
- { ocHarMean, 320, 1, 30, V, { RX }, 0, 0 },
- { ocSumSQ, 321, 0, 30, V, { RX }, 0, 0 },
- { ocKurt, 322, 1, 30, V, { RX }, 0, 0 },
- { ocSchiefe, 323, 1, 30, V, { RX }, 0, 0 },
+ { ocDevSq, 318, 1, MX, V, { RX }, 0, 0 },
+ { ocGeoMean, 319, 1, MX, V, { RX }, 0, 0 },
+ { ocHarMean, 320, 1, MX, V, { RX }, 0, 0 },
+ { ocSumSQ, 321, 0, MX, V, { RX }, 0, 0 },
+ { ocKurt, 322, 1, MX, V, { RX }, 0, 0 },
+ { ocSchiefe, 323, 1, MX, V, { RX }, 0, 0 },
{ ocZTest, 324, 2, 3, V, { RX, VR }, 0, 0 },
{ ocLarge, 325, 2, 2, V, { RX, VR }, 0, 0 },
{ ocSmall, 326, 2, 2, V, { RX, VR }, 0, 0 },
{ ocQuartile, 327, 2, 2, V, { RX, VR }, 0, 0 },
{ ocPercentile, 328, 2, 2, V, { RX, VR }, 0, 0 },
{ ocPercentrank, 329, 2, 3, V, { RX, VR, VR_E }, 0, 0 },
- { ocModalValue, 330, 1, 30, V, { VA }, 0, 0 },
+ { ocModalValue, 330, 1, MX, V, { VA }, 0, 0 },
{ ocTrimMean, 331, 2, 2, V, { RX, VR }, 0, 0 },
{ ocTInv, 332, 2, 2, V, { VR }, 0, 0 }
};
@@ -318,13 +324,13 @@ static const XclFunctionInfo saFuncTable_5[] =
{ ocHLookup, 101, 3, 4, V, { VV, RO, RO, VV }, 0, 0 }, // BIFF2-4: 3, BIFF5: 3-4
{ ocVLookup, 102, 3, 4, V, { VV, RO, RO, VV }, 0, 0 }, // BIFF2-4: 3, BIFF5: 3-4
{ ocGetDiffDate360, 220, 2, 3, V, { VR }, 0, 0 }, // BIFF3-4: 2, BIFF5: 2-3
- { ocMacro, 255, 1, 30, R, { RO_E, RO }, EXC_FUNCFLAG_EXPORTONLY, 0 },
- { ocExternal, 255, 1, 30, R, { RO_E, RO }, EXC_FUNCFLAG_EXPORTONLY, 0 },
- { ocConcat, 336, 0, 30, V, { VR }, 0, 0 },
+ { ocMacro, 255, 1, MX, R, { RO_E, RO }, EXC_FUNCFLAG_EXPORTONLY, 0 },
+ { ocExternal, 255, 1, MX, R, { RO_E, RO }, EXC_FUNCFLAG_EXPORTONLY, 0 },
+ { ocConcat, 336, 0, MX, V, { VR }, 0, 0 },
{ ocPower, 337, 2, 2, V, { VR }, 0, 0 },
{ ocRad, 342, 1, 1, V, { VR }, 0, 0 },
{ ocDeg, 343, 1, 1, V, { VR }, 0, 0 },
- { ocSubTotal, 344, 2, 30, V, { VR, RO }, 0, 0 },
+ { ocSubTotal, 344, 2, MX, V, { VR, RO }, 0, 0 },
{ ocSumIf, 345, 2, 3, V, { RO, VR, RO }, 0, 0 },
{ ocCountIf, 346, 2, 2, V, { RO, VR }, 0, 0 },
{ ocCountEmptyCells, 347, 1, 1, V, { RO }, 0, 0 },
@@ -335,66 +341,90 @@ static const XclFunctionInfo saFuncTable_5[] =
{ ocRoman, 354, 1, 2, V, { VR }, 0, 0 }
};
-#define EXC_FUNCNAME_PREFIX "_xlfn."
-
-const sal_Char* const EXC_FUNCNAME_BAHTTEXT = EXC_FUNCNAME_PREFIX "BAHTTEXT";
-
/** Functions new in BIFF8. Unsupported functions: PHONETIC. */
static const XclFunctionInfo saFuncTable_8[] =
{
- { ocGetPivotData, 358, 2, 30, V, { RR, RR, VR }, 0, 0 },
+ { ocGetPivotData, 358, 2, MX, V, { RR, RR, VR }, 0, 0 },
{ ocHyperLink, 359, 1, 2, V, { VV, VO }, 0, 0 },
{ ocNoName, 360, 1, 1, V, { RO }, EXC_FUNCFLAG_IMPORTONLY, 0 }, // PHONETIC
- { ocAverageA, 361, 1, 30, V, { RX }, 0, 0 },
- { ocMaxA, 362, 1, 30, V, { RX }, 0, 0 },
- { ocMinA, 363, 1, 30, V, { RX }, 0, 0 },
- { ocStDevPA, 364, 1, 30, V, { RX }, 0, 0 },
- { ocVarPA, 365, 1, 30, V, { RX }, 0, 0 },
- { ocStDevA, 366, 1, 30, V, { RX }, 0, 0 },
- { ocVarA, 367, 1, 30, V, { RX }, 0, 0 },
- { ocBahtText, 368, 1, 1, V, { VR }, EXC_FUNCFLAG_IMPORTONLY, EXC_FUNCNAME_BAHTTEXT },
- { ocBahtText, 255, 2, 2, V, { RO_E, RO }, EXC_FUNCFLAG_EXPORTONLY, EXC_FUNCNAME_BAHTTEXT },
+ { ocAverageA, 361, 1, MX, V, { RX }, 0, 0 },
+ { ocMaxA, 362, 1, MX, V, { RX }, 0, 0 },
+ { ocMinA, 363, 1, MX, V, { RX }, 0, 0 },
+ { ocStDevPA, 364, 1, MX, V, { RX }, 0, 0 },
+ { ocVarPA, 365, 1, MX, V, { RX }, 0, 0 },
+ { ocStDevA, 366, 1, MX, V, { RX }, 0, 0 },
+ { ocVarA, 367, 1, MX, V, { RX }, 0, 0 },
+ { ocBahtText, 368, 1, 1, V, { VR }, EXC_FUNCFLAG_IMPORTONLY, EXC_FUNCNAME( "BAHTTEXT" ) },
+ { ocBahtText, 255, 2, 2, V, { RO_E, RO }, EXC_FUNCFLAG_EXPORTONLY, EXC_FUNCNAME( "BAHTTEXT" ) },
{ ocEuroConvert, 255, 4, 6, V, { RO_E, RO }, EXC_FUNCFLAG_EXPORTONLY, "EUROCONVERT" }
};
+#define EXC_FUNCENTRY_ODF( opcode, minparam, maxparam, flags, asciiname ) \
+ { opcode, NOID, minparam, maxparam, V, { VR }, EXC_FUNCFLAG_IMPORTONLY|(flags), EXC_FUNCNAME_ODF( asciiname ) }, \
+ { opcode, 255, (minparam)+1, (maxparam)+1, V, { RO_E, RO }, EXC_FUNCFLAG_EXPORTONLY|(flags), EXC_FUNCNAME_ODF( asciiname ) }
+
+/** Functions defined by OpenFormula, but not supported by Calc (ocNoName) or by Excel (defined op-code). */
+static const XclFunctionInfo saFuncTable_Odf[] =
+{
+ EXC_FUNCENTRY_ODF( ocArabic, 1, 1, 0, "ARABIC" ),
+ EXC_FUNCENTRY_ODF( ocB, 3, 4, 0, "B" ),
+ EXC_FUNCENTRY_ODF( ocBase, 2, 3, 0, "BASE" ),
+ EXC_FUNCENTRY_ODF( ocNoName, 2, 2, 0, "BITAND" ),
+ EXC_FUNCENTRY_ODF( ocNoName, 2, 2, 0, "BITLSHIFT" ),
+ EXC_FUNCENTRY_ODF( ocNoName, 2, 2, 0, "BITOR" ),
+ EXC_FUNCENTRY_ODF( ocNoName, 2, 2, 0, "BITRSHIFT" ),
+ EXC_FUNCENTRY_ODF( ocNoName, 2, 2, 0, "BITXOR" ),
+ EXC_FUNCENTRY_ODF( ocChiSqDist, 2, 3, 0, "CHISQDIST" ),
+ EXC_FUNCENTRY_ODF( ocChiSqInv, 2, 2, 0, "CHISQINV" ),
+ EXC_FUNCENTRY_ODF( ocKombin2, 2, 2, 0, "COMBINA" ),
+ EXC_FUNCENTRY_ODF( ocGetDiffDate, 2, 2, 0, "DAYS" ),
+ EXC_FUNCENTRY_ODF( ocDecimal, 2, 2, 0, "DECIMAL" ),
+ EXC_FUNCENTRY_ODF( ocFDist, 3, 4, 0, "FDIST" ),
+ EXC_FUNCENTRY_ODF( ocFInv, 3, 3, 0, "FINV" ),
+ EXC_FUNCENTRY_ODF( ocFormula, 1, 1, 0, "FORMULA" ),
+ EXC_FUNCENTRY_ODF( ocGamma, 1, 1, 0, "GAMMA" ),
+ EXC_FUNCENTRY_ODF( ocGauss, 1, 1, 0, "GAUSS" ),
+ EXC_FUNCENTRY_ODF( ocNoName, 2, 2, 0, "IFNA" ),
+ EXC_FUNCENTRY_ODF( ocIsFormula, 1, 1, 0, "ISFORMULA" ),
+ EXC_FUNCENTRY_ODF( ocWeek, 1, 2, 0, "ISOWEEKNUM" ),
+ EXC_FUNCENTRY_ODF( ocMatrixUnit, 1, 1, 0, "MUNIT" ),
+ EXC_FUNCENTRY_ODF( ocNumberValue, 2, 2, 0, "NUMBERVALUE" ),
+ EXC_FUNCENTRY_ODF( ocLaufz, 3, 3, 0, "PDURATION" ),
+ EXC_FUNCENTRY_ODF( ocVariationen2, 2, 2, 0, "PERMUTATIONA" ),
+ EXC_FUNCENTRY_ODF( ocPhi, 1, 1, 0, "PHI" ),
+ EXC_FUNCENTRY_ODF( ocZGZ, 3, 3, 0, "RRI" ),
+ EXC_FUNCENTRY_ODF( ocTable, 1, 1, 0, "SHEET" ),
+ EXC_FUNCENTRY_ODF( ocTables, 0, 1, 0, "SHEETS" ),
+ EXC_FUNCENTRY_ODF( ocNoName, 1, MX, 0, "SKEWP" ),
+ EXC_FUNCENTRY_ODF( ocUnichar, 1, 1, 0, "UNICHAR" ),
+ EXC_FUNCENTRY_ODF( ocUnicode, 1, 1, 0, "UNICODE" ),
+ EXC_FUNCENTRY_ODF( ocNoName, 1, MX, 0, "XOR" )
+};
+
+#undef EXC_FUNCENTRY_ODF
+
// ----------------------------------------------------------------------------
XclFunctionProvider::XclFunctionProvider( const XclRoot& rRoot )
{
- XclBiff eBiff = rRoot.GetBiff();
+ void (XclFunctionProvider::*pFillFunc)( const XclFunctionInfo*, const XclFunctionInfo* ) =
+ rRoot.IsImport() ? &XclFunctionProvider::FillXclFuncMap : &XclFunctionProvider::FillScFuncMap;
- if( rRoot.IsImport() )
- {
- /* Import: only read functions supported in the current BIFF version.
- Function tables from later BIFF versions may overwrite single
- functions from earlier tables. */
- if( eBiff >= EXC_BIFF2 )
- FillXclFuncMap( saFuncTable_2, STATIC_TABLE_END( saFuncTable_2 ) );
- if( eBiff >= EXC_BIFF3 )
- FillXclFuncMap( saFuncTable_3, STATIC_TABLE_END( saFuncTable_3 ) );
- if( eBiff >= EXC_BIFF4 )
- FillXclFuncMap( saFuncTable_4, STATIC_TABLE_END( saFuncTable_4 ) );
- if( eBiff >= EXC_BIFF5 )
- FillXclFuncMap( saFuncTable_5, STATIC_TABLE_END( saFuncTable_5 ) );
- if( eBiff >= EXC_BIFF8 )
- FillXclFuncMap( saFuncTable_8, STATIC_TABLE_END( saFuncTable_8 ) );
- }
- else
- {
- /* Export: only write functions supported in the current BIFF version.
- Function tables from later BIFF versions may overwrite single
- functions from earlier tables. */
- if( eBiff >= EXC_BIFF2 )
- FillScFuncMap( saFuncTable_2, STATIC_TABLE_END( saFuncTable_2 ) );
- if( eBiff >= EXC_BIFF3 )
- FillScFuncMap( saFuncTable_3, STATIC_TABLE_END( saFuncTable_3 ) );
- if( eBiff >= EXC_BIFF4 )
- FillScFuncMap( saFuncTable_4, STATIC_TABLE_END( saFuncTable_4 ) );
- if( eBiff >= EXC_BIFF5 )
- FillScFuncMap( saFuncTable_5, STATIC_TABLE_END( saFuncTable_5 ) );
- if( eBiff >= EXC_BIFF8 )
- FillScFuncMap( saFuncTable_8, STATIC_TABLE_END( saFuncTable_8 ) );
- }
+ /* Only read/write functions supported in the current BIFF version.
+ Function tables from later BIFF versions may overwrite single functions
+ from earlier tables. */
+ XclBiff eBiff = rRoot.GetBiff();
+ if( eBiff >= EXC_BIFF2 )
+ (this->*pFillFunc)( saFuncTable_2, STATIC_TABLE_END( saFuncTable_2 ) );
+ if( eBiff >= EXC_BIFF3 )
+ (this->*pFillFunc)( saFuncTable_3, STATIC_TABLE_END( saFuncTable_3 ) );
+ if( eBiff >= EXC_BIFF4 )
+ (this->*pFillFunc)( saFuncTable_4, STATIC_TABLE_END( saFuncTable_4 ) );
+ if( eBiff >= EXC_BIFF5 )
+ (this->*pFillFunc)( saFuncTable_5, STATIC_TABLE_END( saFuncTable_5 ) );
+ if( eBiff >= EXC_BIFF8 )
+ (this->*pFillFunc)( saFuncTable_8, STATIC_TABLE_END( saFuncTable_8 ) );
+ (this->*pFillFunc)( saFuncTable_Odf, STATIC_TABLE_END( saFuncTable_Odf ) );
}
const XclFunctionInfo* XclFunctionProvider::GetFuncInfoFromXclFunc( sal_uInt16 nXclFunc ) const
diff --git a/sc/source/filter/excel/xltools.cxx b/sc/source/filter/excel/xltools.cxx
index 926eb3e54fdc..90393ae6a787 100644
--- a/sc/source/filter/excel/xltools.cxx
+++ b/sc/source/filter/excel/xltools.cxx
@@ -113,7 +113,12 @@ const XclGuid XclTools::maGuidFileMoniker(
double XclTools::GetDoubleFromRK( sal_Int32 nRKValue )
{
- double fVal = 0.0;
+ union
+ {
+ double fVal;
+ sal_math_Double smD;
+ };
+ fVal = 0.0;
if( ::get_flag( nRKValue, EXC_RK_INTFLAG ) )
{
@@ -123,8 +128,7 @@ double XclTools::GetDoubleFromRK( sal_Int32 nRKValue )
}
else
{
- sal_math_Double* pDouble = reinterpret_cast< sal_math_Double* >( &fVal );
- pDouble->w32_parts.msw = nRKValue & EXC_RK_VALUEMASK;
+ smD.w32_parts.msw = nRKValue & EXC_RK_VALUEMASK;
}
if( ::get_flag( nRKValue, EXC_RK_100FLAG ) )
@@ -161,50 +165,6 @@ bool XclTools::GetRKFromDouble( sal_Int32& rnRKValue, double fValue )
return false;
}
-
-sal_uInt8 XclTools::GetXclErrorCode( USHORT nScError )
-{
- using namespace ScErrorCodes;
- switch( nScError )
- {
- case errIllegalArgument: return EXC_ERR_VALUE;
- case errIllegalFPOperation: return EXC_ERR_NUM; // maybe DIV/0 or NUM...
- case errDivisionByZero: return EXC_ERR_DIV0;
- case errIllegalParameter: return EXC_ERR_VALUE;
- case errPairExpected: return EXC_ERR_VALUE;
- case errOperatorExpected: return EXC_ERR_VALUE;
- case errVariableExpected: return EXC_ERR_VALUE;
- case errParameterExpected: return EXC_ERR_VALUE;
- case errNoValue: return EXC_ERR_VALUE;
- case errCircularReference: return EXC_ERR_VALUE;
- case errNoCode: return EXC_ERR_NULL;
- case errNoRef: return EXC_ERR_REF;
- case errNoName: return EXC_ERR_NAME;
- case errNoAddin: return EXC_ERR_NAME;
- case errNoMacro: return EXC_ERR_NAME;
- case NOTAVAILABLE: return EXC_ERR_NA;
- }
- return EXC_ERR_NA;
-}
-
-USHORT XclTools::GetScErrorCode( sal_uInt8 nXclError )
-{
- using namespace ScErrorCodes;
- switch( nXclError )
- {
- case EXC_ERR_NULL: return errNoCode;
- case EXC_ERR_DIV0: return errDivisionByZero;
- case EXC_ERR_VALUE: return errNoValue;
- case EXC_ERR_REF: return errNoRef;
- case EXC_ERR_NAME: return errNoName;
- case EXC_ERR_NUM: return errIllegalFPOperation;
- case EXC_ERR_NA: return NOTAVAILABLE;
- default: DBG_ERRORFILE( "XclTools::GetScErrorCode - unknown error code" );
- }
- return NOTAVAILABLE;
-}
-
-
sal_Int32 XclTools::GetScRotation( sal_uInt16 nXclRot, sal_Int32 nRotForStacked )
{
if( nXclRot == EXC_ROT_STACKED )
@@ -252,6 +212,59 @@ sal_uInt8 XclTools::GetXclOrientFromRot( sal_uInt16 nXclRot )
return EXC_ORIENT_NONE;
}
+sal_uInt8 XclTools::GetXclErrorCode( USHORT nScError )
+{
+ using namespace ScErrorCodes;
+ switch( nScError )
+ {
+ case errIllegalArgument: return EXC_ERR_VALUE;
+ case errIllegalFPOperation: return EXC_ERR_NUM; // maybe DIV/0 or NUM...
+ case errDivisionByZero: return EXC_ERR_DIV0;
+ case errIllegalParameter: return EXC_ERR_VALUE;
+ case errPairExpected: return EXC_ERR_VALUE;
+ case errOperatorExpected: return EXC_ERR_VALUE;
+ case errVariableExpected: return EXC_ERR_VALUE;
+ case errParameterExpected: return EXC_ERR_VALUE;
+ case errNoValue: return EXC_ERR_VALUE;
+ case errCircularReference: return EXC_ERR_VALUE;
+ case errNoCode: return EXC_ERR_NULL;
+ case errNoRef: return EXC_ERR_REF;
+ case errNoName: return EXC_ERR_NAME;
+ case errNoAddin: return EXC_ERR_NAME;
+ case errNoMacro: return EXC_ERR_NAME;
+ case NOTAVAILABLE: return EXC_ERR_NA;
+ }
+ return EXC_ERR_NA;
+}
+
+USHORT XclTools::GetScErrorCode( sal_uInt8 nXclError )
+{
+ using namespace ScErrorCodes;
+ switch( nXclError )
+ {
+ case EXC_ERR_NULL: return errNoCode;
+ case EXC_ERR_DIV0: return errDivisionByZero;
+ case EXC_ERR_VALUE: return errNoValue;
+ case EXC_ERR_REF: return errNoRef;
+ case EXC_ERR_NAME: return errNoName;
+ case EXC_ERR_NUM: return errIllegalFPOperation;
+ case EXC_ERR_NA: return NOTAVAILABLE;
+ default: DBG_ERRORFILE( "XclTools::GetScErrorCode - unknown error code" );
+ }
+ return NOTAVAILABLE;
+}
+
+double XclTools::ErrorToDouble( sal_uInt8 nXclError )
+{
+ union
+ {
+ double fVal;
+ sal_math_Double smD;
+ };
+ ::rtl::math::setNan( &fVal );
+ smD.nan_parts.fraction_lo = GetScErrorCode( nXclError );
+ return fVal;
+}
XclBoolError XclTools::ErrorToEnum( double& rfDblValue, sal_uInt8 bErrOrBool, sal_uInt8 nValue )
{
@@ -281,7 +294,6 @@ XclBoolError XclTools::ErrorToEnum( double& rfDblValue, sal_uInt8 bErrOrBool, sa
return eType;
}
-
sal_uInt16 XclTools::GetTwipsFromInch( double fInches )
{
return static_cast< sal_uInt16 >(
diff --git a/sc/source/filter/inc/xihelper.hxx b/sc/source/filter/inc/xihelper.hxx
index 9a836c8844db..05412c306c0c 100644
--- a/sc/source/filter/inc/xihelper.hxx
+++ b/sc/source/filter/inc/xihelper.hxx
@@ -320,13 +320,15 @@ public:
/** Returns the type of the cached value (EXC_CACHEDVAL_*). */
inline sal_uInt8 GetType() const { return mnType; }
/** Returns the cached string value, if this value is a string, else an empty string. */
- inline const String& GetString() const { return mxStr.get() ? *mxStr : EMPTY_STRING; }
+ inline const String& GetString() const { return mxStr.get() ? *mxStr : EMPTY_STRING; }
/** Returns the cached number, if this value has number type, else 0.0. */
inline double GetValue() const { return mfValue; }
/** Returns the cached Boolean value, if this value has Boolean type, else false. */
inline bool GetBool() const { return (mnType == EXC_CACHEDVAL_BOOL) && (mnBoolErr != 0); }
/** Returns the cached Calc error code, if this value has Error type, else 0. */
- USHORT GetError() const;
+ inline sal_uInt8 GetXclError() const { return (mnType == EXC_CACHEDVAL_ERROR) ? mnBoolErr : EXC_ERR_NA; }
+ /** Returns the cached Calc error code, if this value has Error type, else 0. */
+ USHORT GetScError() const;
/** Returns the token array if this is a Boolean value or error value, else 0. */
inline const ScTokenArray* GetBoolErrFmla() const { return mxTokArr.get(); }
diff --git a/sc/source/filter/inc/xistyle.hxx b/sc/source/filter/inc/xistyle.hxx
index 4a347062905c..104002542a17 100644
--- a/sc/source/filter/inc/xistyle.hxx
+++ b/sc/source/filter/inc/xistyle.hxx
@@ -316,6 +316,9 @@ struct XclImpCellBorder : public XclCellBorder
/** Fills this struct with BIFF8 CF (conditional format) record data. */
void FillFromCF8( sal_uInt16 nLineStyle, sal_uInt32 nLineColor, sal_uInt32 nFlags );
+ /** Returns true, if any of the outer border lines is visible. */
+ bool HasAnyOuterBorder() const;
+
/** Inserts a box item representing this border style into the item set.
@param bSkipPoolDefs true = Do not put items equal to pool default; false = Put all items. */
void FillToItemSet(
@@ -423,8 +426,6 @@ private:
@descr In cell XFs, a set bit represents "used", in style XFs it is a cleared bit.
Therefore mbCellXF must be set correctly before calling this method. */
void SetUsedFlags( sal_uInt8 nUsedFlags );
- /** Sets own "attribute used" flags, if attributes are different from passed parent XF. */
- void UpdateUsedFlags( const XclImpXF& rParentXF );
private:
typedef ::std::auto_ptr< ScPatternAttr > ScPatternAttrPtr;
diff --git a/sc/source/filter/inc/xltools.hxx b/sc/source/filter/inc/xltools.hxx
index b2519a51d156..e8ceed8248d6 100644
--- a/sc/source/filter/inc/xltools.hxx
+++ b/sc/source/filter/inc/xltools.hxx
@@ -121,6 +121,8 @@ public:
/** Converts an Excel error code to a Calc error code. */
static USHORT GetScErrorCode( sal_uInt8 nXclError );
+ /** Converts the passed BIFF error to a double containing the respective Calc error code. */
+ static double ErrorToDouble( sal_uInt8 nXclError );
/** Gets a translated error code or Boolean value from Excel error codes.
@param rfDblValue Returns 0.0 for error codes or the value of a Boolean (0.0 or 1.0).
@param bErrorOrBool false = nError is a Boolean value; true = is an error value.