diff options
Diffstat (limited to 'sc/source/filter')
-rw-r--r-- | sc/source/filter/excel/xelink.cxx | 427 | ||||
-rw-r--r-- | sc/source/filter/excel/xihelper.cxx | 4 | ||||
-rw-r--r-- | sc/source/filter/excel/xilink.cxx | 12 | ||||
-rw-r--r-- | sc/source/filter/excel/xistyle.cxx | 67 | ||||
-rw-r--r-- | sc/source/filter/excel/xlformula.cxx | 184 | ||||
-rw-r--r-- | sc/source/filter/excel/xltools.cxx | 108 | ||||
-rw-r--r-- | sc/source/filter/inc/xihelper.hxx | 6 | ||||
-rw-r--r-- | sc/source/filter/inc/xistyle.hxx | 5 | ||||
-rw-r--r-- | sc/source/filter/inc/xltools.hxx | 2 |
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. |