summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Rentz <dr@openoffice.org>2010-01-27 17:41:29 +0100
committerDaniel Rentz <dr@openoffice.org>2010-01-27 17:41:29 +0100
commit42babf975a2369372124fa0e97796c2950b7b47b (patch)
tree649335710e95fba36f737e2c307d4f0cbfb9cd99
parent60fdd54890f04949f1b82d4f7a4903e65f165a7c (diff)
parent9d2aea11389d86aa97eba7015509be90a2c1f9fb (diff)
dr75: rebase merge
-rw-r--r--sc/inc/chgtrack.hxx2
-rw-r--r--sc/inc/externalrefmgr.hxx13
-rw-r--r--sc/source/filter/excel/xelink.cxx425
-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/xltools.cxx98
-rw-r--r--sc/source/filter/inc/xihelper.hxx6
-rw-r--r--sc/source/filter/inc/xltools.hxx2
-rw-r--r--sc/source/ui/dbgui/pvfundlg.src4
-rw-r--r--sc/source/ui/docshell/docsh3.cxx10
-rw-r--r--sc/source/ui/docshell/externalrefmgr.cxx50
-rw-r--r--sc/source/ui/view/cellsh3.cxx2
12 files changed, 326 insertions, 302 deletions
diff --git a/sc/inc/chgtrack.hxx b/sc/inc/chgtrack.hxx
index 0018f8b2ac3c..805591e2f7ea 100644
--- a/sc/inc/chgtrack.hxx
+++ b/sc/inc/chgtrack.hxx
@@ -311,7 +311,6 @@ protected:
GetDeletedInAddress(), p );
}
BOOL RemoveDeletedIn( const ScChangeAction* );
- void RemoveAllDeletedIn();
void SetDeletedIn( ScChangeAction* );
ScChangeActionLinkEntry* AddDeleted( ScChangeAction* p )
@@ -417,6 +416,7 @@ public:
{ return IsDeleteType() || IsDeletedIn(); }
BOOL IsDeletedIn( const ScChangeAction* ) const;
BOOL IsDeletedInDelType( ScChangeActionType ) const;
+ void RemoveAllDeletedIn();
const ScChangeActionLinkEntry* GetFirstDeletedEntry() const
{ return pLinkDeleted; }
diff --git a/sc/inc/externalrefmgr.hxx b/sc/inc/externalrefmgr.hxx
index 90adedd6d346..1b1e043de050 100644
--- a/sc/inc/externalrefmgr.hxx
+++ b/sc/inc/externalrefmgr.hxx
@@ -144,7 +144,7 @@ public:
~Table();
SC_DLLPUBLIC void setCell(SCCOL nCol, SCROW nRow, TokenRef pToken, sal_uInt32 nFmtIndex = 0);
- TokenRef getCell(SCCOL nCol, SCROW nRow, sal_uInt32* pnFmtIndex = NULL) const;
+ SC_DLLPUBLIC TokenRef getCell(SCCOL nCol, SCROW nRow, sal_uInt32* pnFmtIndex = NULL) const;
bool hasRow( SCROW nRow ) const;
/** Set/clear referenced status flag only if current status is not
REFERENCED_PERMANENT. */
@@ -155,8 +155,12 @@ public:
bool isReferenced() const;
/// Obtain a sorted vector of rows.
void getAllRows(::std::vector<SCROW>& rRows) const;
+ /// Returns the half-open range of used rows in this table. Returns [0,0) if table is empty.
+ SC_DLLPUBLIC ::std::pair< SCROW, SCROW > getRowRange() const;
/// Obtain a sorted vector of columns.
void getAllCols(SCROW nRow, ::std::vector<SCCOL>& rCols) const;
+ /// Returns the half-open range of used columns in the specified row. Returns [0,0) if row is empty.
+ SC_DLLPUBLIC ::std::pair< SCCOL, SCCOL > getColRange( SCROW nRow ) const;
void getAllNumberFormats(::std::vector<sal_uInt32>& rNumFmts) const;
private:
@@ -470,6 +474,13 @@ public:
* @return shared_ptr to the cache table instance
*/
ScExternalRefCache::TableTypeRef getCacheTable(sal_uInt16 nFileId, const String& rTabName, bool bCreateNew, size_t* pnIndex = 0);
+
+ /** Returns a vector containing all (real) table names and cache tables of
+ the specified file.
+
+ The index in the returned vector corresponds to the table index used to
+ access the cache table, e.g. in getCacheTable().
+ */
void getAllCachedTableNames(sal_uInt16 nFileId, ::std::vector<String>& rTabNames) const;
/**
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) == '-' ) )
{