diff options
author | Daniel Rentz <dr@openoffice.org> | 2010-01-27 17:41:29 +0100 |
---|---|---|
committer | Daniel Rentz <dr@openoffice.org> | 2010-01-27 17:41:29 +0100 |
commit | 42babf975a2369372124fa0e97796c2950b7b47b (patch) | |
tree | 649335710e95fba36f737e2c307d4f0cbfb9cd99 /sc/source | |
parent | 60fdd54890f04949f1b82d4f7a4903e65f165a7c (diff) | |
parent | 9d2aea11389d86aa97eba7015509be90a2c1f9fb (diff) |
dr75: rebase merge
Diffstat (limited to 'sc/source')
-rw-r--r-- | sc/source/filter/excel/xelink.cxx | 425 | ||||
-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/xltools.cxx | 98 | ||||
-rw-r--r-- | sc/source/filter/inc/xihelper.hxx | 6 | ||||
-rw-r--r-- | sc/source/filter/inc/xltools.hxx | 2 | ||||
-rw-r--r-- | sc/source/ui/dbgui/pvfundlg.src | 4 | ||||
-rw-r--r-- | sc/source/ui/docshell/docsh3.cxx | 10 | ||||
-rw-r--r-- | sc/source/ui/docshell/externalrefmgr.cxx | 50 | ||||
-rw-r--r-- | sc/source/ui/view/cellsh3.cxx | 2 |
10 files changed, 313 insertions, 300 deletions
diff --git a/sc/source/filter/excel/xelink.cxx b/sc/source/filter/excel/xelink.cxx index 46fcd166ecf1..796276fc8e3f 100644 --- a/sc/source/filter/excel/xelink.cxx +++ b/sc/source/filter/excel/xelink.cxx @@ -46,7 +46,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 *** @@ -169,105 +170,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. }; @@ -356,14 +311,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 ); @@ -1009,6 +964,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) @@ -1165,209 +1121,198 @@ 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; + } } } } -} -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 ======================= @@ -1474,15 +1419,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 ) : @@ -1516,31 +1457,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 @@ -1561,11 +1493,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; @@ -1789,6 +1721,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 99dd5632443b..cb66aa8fb636 100644 --- a/sc/source/filter/excel/xihelper.cxx +++ b/sc/source/filter/excel/xihelper.cxx @@ -840,7 +840,7 @@ XclImpCachedValue::~XclImpCachedValue() { } -USHORT XclImpCachedValue::GetError() const +USHORT XclImpCachedValue::GetScError() const { return (mnType == EXC_CACHEDVAL_ERROR) ? XclTools::GetScErrorCode( mnBoolErr ) : 0; } @@ -904,7 +904,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 00268215a5dc..0625d77f9457 100644 --- a/sc/source/filter/excel/xilink.cxx +++ b/sc/source/filter/excel/xilink.cxx @@ -416,6 +416,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: { @@ -424,9 +429,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/xltools.cxx b/sc/source/filter/excel/xltools.cxx index 4aa46c2ebed9..91f0f1a963d5 100644 --- a/sc/source/filter/excel/xltools.cxx +++ b/sc/source/filter/excel/xltools.cxx @@ -164,50 +164,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 ) @@ -255,6 +211,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 ) { @@ -284,7 +293,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 a46d473f02a9..1d42d0e1141d 100644 --- a/sc/source/filter/inc/xihelper.hxx +++ b/sc/source/filter/inc/xihelper.hxx @@ -323,13 +323,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/xltools.hxx b/sc/source/filter/inc/xltools.hxx index 392b0a2ae1fc..7b55817cbd27 100644 --- a/sc/source/filter/inc/xltools.hxx +++ b/sc/source/filter/inc/xltools.hxx @@ -124,6 +124,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. diff --git a/sc/source/ui/dbgui/pvfundlg.src b/sc/source/ui/dbgui/pvfundlg.src index 5aa547ff951e..797b2990272f 100644 --- a/sc/source/ui/dbgui/pvfundlg.src +++ b/sc/source/ui/dbgui/pvfundlg.src @@ -230,8 +230,8 @@ ModalDialog RID_SCDLG_PIVOTSUBT }; CheckBox CB_SHOWALL { - Pos = MAP_APPFONT ( 12 , 127 ) ; - Size = MAP_APPFONT ( 140 , 10 ) ; + Pos = MAP_APPFONT ( 6 , 127 ) ; + Size = MAP_APPFONT ( 152 , 10 ) ; Text [ en-US ] = "Show it~ems without data"; TabStop = TRUE ; }; diff --git a/sc/source/ui/docshell/docsh3.cxx b/sc/source/ui/docshell/docsh3.cxx index 1416c57f1165..59ab20fb2545 100644 --- a/sc/source/ui/docshell/docsh3.cxx +++ b/sc/source/ui/docshell/docsh3.cxx @@ -1091,6 +1091,16 @@ void ScDocShell::MergeDocument( ScDocument& rOtherDoc, bool bShared, bool bCheck { aSourceRange = pDel->GetOverAllRange().MakeRange(); GetDocFunc().DeleteCells( aSourceRange, NULL, DEL_DELROWS, TRUE, FALSE ); + + // #i101099# [Collaboration] Changes are not correctly shown + if ( bShared ) + { + ScChangeAction* pAct = pThisTrack->GetLast(); + if ( pAct && pAct->GetType() == eSourceType && pAct->IsDeletedIn() && !pSourceAction->IsDeletedIn() ) + { + pAct->RemoveAllDeletedIn(); + } + } } } break; diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx index e18ef20d96b9..51857285e5f8 100644 --- a/sc/source/ui/docshell/externalrefmgr.cxx +++ b/sc/source/ui/docshell/externalrefmgr.cxx @@ -241,6 +241,26 @@ void ScExternalRefCache::Table::getAllRows(vector<SCROW>& rRows) const rRows.swap(aRows); } +::std::pair< SCROW, SCROW > ScExternalRefCache::Table::getRowRange() const +{ + ::std::pair< SCROW, SCROW > aRange( 0, 0 ); + if( !maRows.empty() ) + { + // iterate over entire container (hash map is not sorted by key) + RowsDataType::const_iterator itr = maRows.begin(), itrEnd = maRows.end(); + aRange.first = itr->first; + aRange.second = itr->first + 1; + while( ++itr != itrEnd ) + { + if( itr->first < aRange.first ) + aRange.first = itr->first; + else if( itr->first >= aRange.second ) + aRange.second = itr->first + 1; + } + } + return aRange; +} + void ScExternalRefCache::Table::getAllCols(SCROW nRow, vector<SCCOL>& rCols) const { RowsDataType::const_iterator itrRow = maRows.find(nRow); @@ -260,6 +280,33 @@ void ScExternalRefCache::Table::getAllCols(SCROW nRow, vector<SCCOL>& rCols) con rCols.swap(aCols); } +::std::pair< SCCOL, SCCOL > ScExternalRefCache::Table::getColRange( SCROW nRow ) const +{ + ::std::pair< SCCOL, SCCOL > aRange( 0, 0 ); + + RowsDataType::const_iterator itrRow = maRows.find( nRow ); + if (itrRow == maRows.end()) + // this table doesn't have the specified row. + return aRange; + + const RowDataType& rRowData = itrRow->second; + if( !rRowData.empty() ) + { + // iterate over entire container (hash map is not sorted by key) + RowDataType::const_iterator itr = rRowData.begin(), itrEnd = rRowData.end(); + aRange.first = itr->first; + aRange.second = itr->first + 1; + while( ++itr != itrEnd ) + { + if( itr->first < aRange.first ) + aRange.first = itr->first; + else if( itr->first >= aRange.second ) + aRange.second = itr->first + 1; + } + } + return aRange; +} + void ScExternalRefCache::Table::getAllNumberFormats(vector<sal_uInt32>& rNumFmts) const { RowsDataType::const_iterator itrRow = maRows.begin(), itrRowEnd = maRows.end(); @@ -1942,6 +1989,9 @@ SfxObjectShellRef ScExternalRefManager::loadSrcDocument(sal_uInt16 nFileId, Stri if (aOptions.Len()) pSet->Put(SfxStringItem(SID_FILE_FILTEROPTIONS, aOptions)); + // make medium hidden to prevent assertion from progress bar + pSet->Put( SfxBoolItem( SID_HIDDEN, TRUE ) ); + auto_ptr<SfxMedium> pMedium(new SfxMedium(aFile, STREAM_STD_READ, false, pFilter, pSet)); if (pMedium->GetError() != ERRCODE_NONE) return NULL; diff --git a/sc/source/ui/view/cellsh3.cxx b/sc/source/ui/view/cellsh3.cxx index 2f96aec815fb..ba1d24de55d9 100644 --- a/sc/source/ui/view/cellsh3.cxx +++ b/sc/source/ui/view/cellsh3.cxx @@ -247,7 +247,7 @@ void ScCellShell::Execute( SfxRequest& rReq ) { if (nSlot == FID_INPUTLINE_BLOCK) { - pTabViewShell->EnterBlock( String(), pData ); + pTabViewShell->EnterBlock( aString, pData ); } else if ( aString.Len() > 0 && ( aString.GetChar(0) == '=' || aString.GetChar(0) == '+' || aString.GetChar(0) == '-' ) ) { |