summaryrefslogtreecommitdiffstats
path: root/oox/source/xls
diff options
context:
space:
mode:
authorJan Holesovsky <kendy@suse.cz>2011-05-27 20:45:30 +0200
committerJan Holesovsky <kendy@suse.cz>2011-05-27 20:45:30 +0200
commite959581b2d44bff812ffddd34b750e4f9f29e187 (patch)
tree257c72d3fd2bc409f391bc26892f5653241455bc /oox/source/xls
parentcan only be true with unsigned values (diff)
parentFix post-merge (diff)
downloadcore-e959581b2d44bff812ffddd34b750e4f9f29e187.tar.gz
core-e959581b2d44bff812ffddd34b750e4f9f29e187.zip
Merge remote-tracking branch 'origin/integration/dev300_m106'
Conflicts: filter/source/graphicfilter/epict/epict.cxx filter/source/svg/svgexport.cxx filter/source/svg/svgfontexport.cxx filter/source/svg/svgwriter.cxx lotuswordpro/source/filter/lwpchartstreamtools.cxx lotuswordpro/source/filter/lwpfrib.cxx lotuswordpro/source/filter/lwpgrfobj.cxx lotuswordpro/source/filter/lwpidxmgr.cxx lotuswordpro/source/filter/lwpobjid.cxx lotuswordpro/source/filter/lwpparaproperty.cxx lotuswordpro/util/makefile.mk oox/prj/d.lst oox/source/drawingml/chart/chartdrawingfragment.cxx oox/source/drawingml/makefile.mk oox/source/drawingml/shape.cxx oox/source/ppt/slidepersist.cxx oox/source/token/namespaces.hxx.tail oox/source/xls/drawingfragment.cxx oox/source/xls/excelfilter.cxx oox/source/xls/makefile.mk oox/source/xls/workbookhelper.cxx writerfilter/source/ooxml/makefile.mk writerfilter/source/resourcemodel/makefile.mk
Diffstat (limited to 'oox/source/xls')
-rw-r--r--oox/source/xls/addressconverter.cxx4
-rw-r--r--oox/source/xls/autofilterbuffer.cxx2
-rw-r--r--oox/source/xls/biffdetector.cxx7
-rw-r--r--oox/source/xls/biffhelper.cxx15
-rw-r--r--oox/source/xls/biffinputstream.cxx137
-rw-r--r--oox/source/xls/biffoutputstream.cxx92
-rw-r--r--oox/source/xls/chartsheetfragment.cxx10
-rw-r--r--oox/source/xls/commentsbuffer.cxx179
-rw-r--r--oox/source/xls/condformatbuffer.cxx38
-rw-r--r--oox/source/xls/defnamesbuffer.cxx184
-rwxr-xr-xoox/source/xls/drawingbase.cxx325
-rw-r--r--oox/source/xls/drawingfragment.cxx354
-rwxr-xr-xoox/source/xls/drawingmanager.cxx1414
-rw-r--r--oox/source/xls/excelchartconverter.cxx11
-rw-r--r--oox/source/xls/excelfilter.cxx51
-rw-r--r--oox/source/xls/excelhandlers.cxx81
-rw-r--r--oox/source/xls/externallinkbuffer.cxx10
-rw-r--r--oox/source/xls/formulabase.cxx91
-rw-r--r--oox/source/xls/formulaparser.cxx323
-rw-r--r--oox/source/xls/numberformatsbuffer.cxx2
-rw-r--r--oox/source/xls/ooxformulaparser.cxx20
-rw-r--r--oox/source/xls/pagesettings.cxx3
-rw-r--r--oox/source/xls/pivotcachebuffer.cxx79
-rw-r--r--oox/source/xls/pivotcachefragment.cxx49
-rw-r--r--oox/source/xls/richstring.cxx109
-rw-r--r--oox/source/xls/sharedformulabuffer.cxx2
-rw-r--r--oox/source/xls/sharedstringsbuffer.cxx6
-rwxr-xr-xoox/source/xls/sheetdatabuffer.cxx935
-rw-r--r--oox/source/xls/sheetdatacontext.cxx871
-rw-r--r--oox/source/xls/stylesbuffer.cxx35
-rw-r--r--oox/source/xls/viewsettings.cxx4
-rw-r--r--oox/source/xls/workbookfragment.cxx102
-rw-r--r--oox/source/xls/workbookhelper.cxx247
-rw-r--r--oox/source/xls/workbooksettings.cxx2
-rw-r--r--oox/source/xls/worksheetfragment.cxx104
-rw-r--r--oox/source/xls/worksheethelper.cxx1309
36 files changed, 4549 insertions, 2658 deletions
diff --git a/oox/source/xls/addressconverter.cxx b/oox/source/xls/addressconverter.cxx
index 595c73a04c46..fd7217afac89 100644
--- a/oox/source/xls/addressconverter.cxx
+++ b/oox/source/xls/addressconverter.cxx
@@ -99,12 +99,12 @@ const sal_Unicode BIFF_DCON_ENCODED = '\x01'; /// First character of an en
const sal_Unicode BIFF_DCON_INTERN = '\x02'; /// First character of an encoded sheet name from DCON* records.
-inline sal_uInt16 lclGetBiffAddressSize( bool bCol16Bit, bool bRow32Bit )
+inline sal_uInt8 lclGetBiffAddressSize( bool bCol16Bit, bool bRow32Bit )
{
return (bCol16Bit ? 2 : 1) + (bRow32Bit ? 4 : 2);
}
-inline sal_uInt16 lclGetBiffRangeSize( bool bCol16Bit, bool bRow32Bit )
+inline sal_uInt8 lclGetBiffRangeSize( bool bCol16Bit, bool bRow32Bit )
{
return 2 * lclGetBiffAddressSize( bCol16Bit, bRow32Bit );
}
diff --git a/oox/source/xls/autofilterbuffer.cxx b/oox/source/xls/autofilterbuffer.cxx
index e7b6f321f9b0..987e7bcf7604 100644
--- a/oox/source/xls/autofilterbuffer.cxx
+++ b/oox/source/xls/autofilterbuffer.cxx
@@ -841,7 +841,7 @@ bool AutoFilterBuffer::finalizeImport( const Reference< XDatabaseRange >& rxData
AutoFilter* AutoFilterBuffer::getActiveAutoFilter()
{
// Excel expects not more than one auto filter per sheet or table
- OSL_ENSURE( maAutoFilters.size() == 1, "AutoFilterBuffer::getActiveAutoFilter - too many auto filters" );
+ OSL_ENSURE( maAutoFilters.size() <= 1, "AutoFilterBuffer::getActiveAutoFilter - too many auto filters" );
// stick to the last imported auto filter
return maAutoFilters.empty() ? 0 : maAutoFilters.back().get();
}
diff --git a/oox/source/xls/biffdetector.cxx b/oox/source/xls/biffdetector.cxx
index 0c6ea2fa4c39..d55a2b3d0715 100644
--- a/oox/source/xls/biffdetector.cxx
+++ b/oox/source/xls/biffdetector.cxx
@@ -83,14 +83,14 @@ BiffDetector::~BiffDetector()
/*static*/ BiffType BiffDetector::detectStreamBiffVersion( BinaryInputStream& rInStream )
{
BiffType eBiff = BIFF_UNKNOWN;
- if( !rInStream.isEof() && rInStream.isSeekable() && (rInStream.getLength() > 4) )
+ if( !rInStream.isEof() && rInStream.isSeekable() && (rInStream.size() > 4) )
{
sal_Int64 nOldPos = rInStream.tell();
rInStream.seekToStart();
sal_uInt16 nBofId, nBofSize;
rInStream >> nBofId >> nBofSize;
- if( (4 <= nBofSize) && (nBofSize <= 16) && (rInStream.tell() + nBofSize <= rInStream.getLength()) )
+ if( (4 <= nBofSize) && (nBofSize <= 16) && (rInStream.tell() + nBofSize <= rInStream.size()) )
{
switch( nBofId )
{
@@ -207,9 +207,8 @@ OUString SAL_CALL BiffDetector::detect( Sequence< PropertyValue >& rDescriptor )
MediaDescriptor aDescriptor( rDescriptor );
aDescriptor.addInputStream();
- Reference< XMultiServiceFactory > xFactory( mxContext->getServiceManager(), UNO_QUERY_THROW );
Reference< XInputStream > xInStrm( aDescriptor[ MediaDescriptor::PROP_INPUTSTREAM() ], UNO_QUERY_THROW );
- StorageRef xStorage( new ::oox::ole::OleStorage( xFactory, xInStrm, true ) );
+ StorageRef xStorage( new ::oox::ole::OleStorage( mxContext, xInStrm, true ) );
OUString aWorkbookName;
switch( detectStorageBiffVersion( aWorkbookName, xStorage ) )
diff --git a/oox/source/xls/biffhelper.cxx b/oox/source/xls/biffhelper.cxx
index 6e8da4ef3b39..f1a54e0fe589 100644
--- a/oox/source/xls/biffhelper.cxx
+++ b/oox/source/xls/biffhelper.cxx
@@ -270,7 +270,7 @@ void lclImportImgDataDib( StreamDataSequence& orDataSeq, BiffInputStream& rStrm,
// BIFF12 import --------------------------------------------------------------
-/*static*/ OUString BiffHelper::readString( SequenceInputStream& rStrm, bool b32BitLen )
+/*static*/ OUString BiffHelper::readString( SequenceInputStream& rStrm, bool b32BitLen, bool bAllowNulChars )
{
OUString aString;
if( !rStrm.isEof() )
@@ -280,16 +280,9 @@ void lclImportImgDataDib( StreamDataSequence& orDataSeq, BiffInputStream& rStrm,
OSL_ENSURE( !rStrm.isEof() && (nCharCount >= -1), "BiffHelper::readString - invalid string length" );
if( !rStrm.isEof() && (nCharCount > 0) )
{
- ::std::vector< sal_Unicode > aBuffer;
- aBuffer.reserve( getLimitedValue< size_t, sal_Int32 >( nCharCount + 1, 0, 0xFFFF ) );
- for( sal_Int32 nCharIdx = 0; !rStrm.isEof() && (nCharIdx < nCharCount); ++nCharIdx )
- {
- sal_uInt16 nChar;
- rStrm.readValue( nChar );
- aBuffer.push_back( static_cast< sal_Unicode >( nChar ) );
- }
- aBuffer.push_back( 0 );
- aString = OUString( &aBuffer.front() );
+ // SequenceInputStream always supports getRemaining()
+ nCharCount = ::std::min( nCharCount, static_cast< sal_Int32 >( rStrm.getRemaining() / 2 ) );
+ aString = rStrm.readUnicodeArray( nCharCount, bAllowNulChars );
}
}
return aString;
diff --git a/oox/source/xls/biffinputstream.cxx b/oox/source/xls/biffinputstream.cxx
index c8cb3f24f5d6..5634ae421898 100644
--- a/oox/source/xls/biffinputstream.cxx
+++ b/oox/source/xls/biffinputstream.cxx
@@ -88,7 +88,7 @@ void BiffInputRecordBuffer::enableDecoder( bool bEnable )
bool BiffInputRecordBuffer::startRecord( sal_Int64 nHeaderPos )
{
- mbValidHeader = (0 <= nHeaderPos) && (nHeaderPos + 4 <= mrInStrm.getLength());
+ mbValidHeader = (0 <= nHeaderPos) && (nHeaderPos + 4 <= mrInStrm.size());
if( mbValidHeader )
{
mnHeaderPos = nHeaderPos;
@@ -96,7 +96,7 @@ bool BiffInputRecordBuffer::startRecord( sal_Int64 nHeaderPos )
mrInStrm >> mnRecId >> mnRecSize;
mnBodyPos = mrInStrm.tell();
mnNextHeaderPos = mnBodyPos + mnRecSize;
- mbValidHeader = !mrInStrm.isEof() && (mnNextHeaderPos <= mrInStrm.getLength());
+ mbValidHeader = !mrInStrm.isEof() && (mnNextHeaderPos <= mrInStrm.size());
}
if( !mbValidHeader )
{
@@ -117,7 +117,7 @@ bool BiffInputRecordBuffer::startNextRecord()
sal_uInt16 BiffInputRecordBuffer::getNextRecId()
{
sal_uInt16 nRecId = BIFF_ID_UNKNOWN;
- if( mbValidHeader && (mnNextHeaderPos + 4 <= mrInStrm.getLength()) )
+ if( mbValidHeader && (mnNextHeaderPos + 4 <= mrInStrm.size()) )
{
mrInStrm.seek( mnNextHeaderPos );
mrInStrm >> nRecId;
@@ -170,6 +170,7 @@ void BiffInputRecordBuffer::updateDecoded()
// ============================================================================
BiffInputStream::BiffInputStream( BinaryInputStream& rInStream, bool bContLookup ) :
+ BinaryStreamBase( true ),
maRecBuffer( rInStream ),
mnRecHandle( -1 ),
mnRecId( BIFF_ID_UNKNOWN ),
@@ -258,9 +259,11 @@ sal_uInt16 BiffInputStream::getNextRecId()
// BinaryStreamBase interface (seeking) ---------------------------------------
-bool BiffInputStream::isSeekable() const
+sal_Int64 BiffInputStream::size() const
{
- return true;
+ if( !mbHasComplRec )
+ const_cast< BiffInputStream* >( this )->calcRecordLength();
+ return mnComplRecSize;
}
sal_Int64 BiffInputStream::tell() const
@@ -268,13 +271,6 @@ sal_Int64 BiffInputStream::tell() const
return mbEof ? -1 : (mnCurrRecSize - maRecBuffer.getRecLeft());
}
-sal_Int64 BiffInputStream::getLength() const
-{
- if( !mbHasComplRec )
- const_cast< BiffInputStream* >( this )->calcRecordLength();
- return mnComplRecSize;
-}
-
void BiffInputStream::seek( sal_Int64 nRecPos )
{
if( isInRecord() )
@@ -286,35 +282,35 @@ void BiffInputStream::seek( sal_Int64 nRecPos )
}
}
+void BiffInputStream::close()
+{
+}
+
sal_Int64 BiffInputStream::tellBase() const
{
return maRecBuffer.getBaseStream().tell();
}
-sal_Int64 BiffInputStream::getBaseLength() const
+sal_Int64 BiffInputStream::sizeBase() const
{
- return maRecBuffer.getBaseStream().getLength();
+ return maRecBuffer.getBaseStream().size();
}
// BinaryInputStream interface (stream read access) ---------------------------
-sal_Int32 BiffInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes )
+sal_Int32 BiffInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t nAtomSize )
{
sal_Int32 nRet = 0;
if( !mbEof )
{
orData.realloc( ::std::max< sal_Int32 >( nBytes, 0 ) );
if( nBytes > 0 )
- {
- nRet = readMemory( orData.getArray(), nBytes );
- if( nRet < nBytes )
- orData.realloc( nRet );
- }
+ nRet = readMemory( orData.getArray(), nBytes, nAtomSize );
}
return nRet;
}
-sal_Int32 BiffInputStream::readMemory( void* opMem, sal_Int32 nBytes )
+sal_Int32 BiffInputStream::readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize )
{
sal_Int32 nRet = 0;
if( !mbEof && opMem && (nBytes > 0) )
@@ -324,7 +320,7 @@ sal_Int32 BiffInputStream::readMemory( void* opMem, sal_Int32 nBytes )
while( !mbEof && (nBytesLeft > 0) )
{
- sal_uInt16 nReadSize = getMaxRawReadSize( nBytesLeft );
+ sal_uInt16 nReadSize = getMaxRawReadSize( nBytesLeft, nAtomSize );
// check nReadSize, stream may already be located at end of a raw record
if( nReadSize > 0 )
{
@@ -341,12 +337,12 @@ sal_Int32 BiffInputStream::readMemory( void* opMem, sal_Int32 nBytes )
return nRet;
}
-void BiffInputStream::skip( sal_Int32 nBytes )
+void BiffInputStream::skip( sal_Int32 nBytes, size_t nAtomSize )
{
sal_Int32 nBytesLeft = nBytes;
while( !mbEof && (nBytesLeft > 0) )
{
- sal_uInt16 nSkipSize = getMaxRawReadSize( nBytesLeft );
+ sal_uInt16 nSkipSize = getMaxRawReadSize( nBytesLeft, nAtomSize );
// check nSkipSize, stream may already be located at end of a raw record
if( nSkipSize > 0 )
{
@@ -384,28 +380,22 @@ OUString BiffInputStream::readUniStringChars( sal_uInt16 nChars, bool b16BitChar
OUStringBuffer aBuffer;
aBuffer.ensureCapacity( nChars );
- /* This function has to react on CONTINUE records to read the repeated
- flags field, so readUnicodeArray() cannot be used here. */
- sal_uInt16 nCharsLeft = nChars;
+ /* This function has to react on CONTINUE records which repeat the flags
+ field in their first byte and may change the 8bit/16bit character mode,
+ thus a plain call to readCompressedUnicodeArray() cannot be used here. */
+ sal_Int32 nCharsLeft = nChars;
while( !mbEof && (nCharsLeft > 0) )
{
- sal_uInt16 nPortionCount = 0;
- if( b16BitChars )
- {
- nPortionCount = ::std::min< sal_uInt16 >( nCharsLeft, maRecBuffer.getRecLeft() / 2 );
- OSL_ENSURE( (nPortionCount <= nCharsLeft) || ((maRecBuffer.getRecLeft() & 1) == 0),
- "BiffInputStream::readUniStringChars - missing a byte" );
- }
- else
- {
- nPortionCount = getMaxRawReadSize( nCharsLeft );
- }
-
- // read the character array
- appendUnicodeArray( aBuffer, nPortionCount, b16BitChars, bAllowNulChars );
-
- // prepare for next CONTINUE record
- nCharsLeft = nCharsLeft - nPortionCount;
+ /* Read the character array from the remaining part of the current raw
+ record. First, calculate the maximum number of characters that can
+ be read without triggering to start a following CONTINUE record. */
+ sal_Int32 nRawChars = b16BitChars ? (getMaxRawReadSize( nCharsLeft * 2, 2 ) / 2) : getMaxRawReadSize( nCharsLeft, 1 );
+ aBuffer.append( readCompressedUnicodeArray( nRawChars, !b16BitChars, bAllowNulChars ) );
+
+ /* Prepare for next CONTINUE record. Calling jumpToNextStringContinue()
+ reads the leading byte in the following CONTINUE record and updates
+ the b16BitChars flag. */
+ nCharsLeft -= nRawChars;
if( nCharsLeft > 0 )
jumpToNextStringContinue( b16BitChars );
}
@@ -430,25 +420,15 @@ OUString BiffInputStream::readUniString( bool bAllowNulChars )
void BiffInputStream::skipUniStringChars( sal_uInt16 nChars, bool b16BitChars )
{
- sal_uInt16 nCharsLeft = nChars;
+ sal_Int32 nCharsLeft = nChars;
while( !mbEof && (nCharsLeft > 0) )
{
- sal_uInt16 nPortionCount;
- if( b16BitChars )
- {
- nPortionCount = ::std::min< sal_uInt16 >( nCharsLeft, maRecBuffer.getRecLeft() / 2 );
- OSL_ENSURE( (nPortionCount <= nCharsLeft) || ((maRecBuffer.getRecLeft() & 1) == 0),
- "BiffInputStream::skipUniStringChars - missing a byte" );
- skip( 2 * nPortionCount );
- }
- else
- {
- nPortionCount = getMaxRawReadSize( nCharsLeft );
- skip( nPortionCount );
- }
+ // skip the character array
+ sal_Int32 nSkipSize = b16BitChars ? getMaxRawReadSize( 2 * nCharsLeft, 2 ) : getMaxRawReadSize( nCharsLeft, 1 );
+ skip( nSkipSize );
// prepare for next CONTINUE record
- nCharsLeft = nCharsLeft - nPortionCount;
+ nCharsLeft -= (b16BitChars ? (nSkipSize / 2) : nSkipSize);
if( nCharsLeft > 0 )
jumpToNextStringContinue( b16BitChars );
}
@@ -470,13 +450,6 @@ void BiffInputStream::skipUniString()
// private --------------------------------------------------------------------
-void BiffInputStream::readAtom( void* opMem, sal_uInt8 nSize )
-{
- // byte swapping is done in calling BinaryInputStream::readValue() template function
- if( ensureRawReadSize( nSize ) )
- maRecBuffer.read( opMem, nSize );
-}
-
void BiffInputStream::setupRecord()
{
// initialize class members
@@ -530,7 +503,7 @@ bool BiffInputStream::jumpToNextContinue()
bool BiffInputStream::jumpToNextStringContinue( bool& rb16BitChars )
{
- OSL_ENSURE( maRecBuffer.getRecLeft() == 0, "BiffInputStream::jumpToNextStringContinue - unexpected garbage" );
+ OSL_ENSURE( maRecBuffer.getRecLeft() == 0, "BiffInputStream::jumpToNextStringContinue - alignment error" );
if( mbCont && (getRemaining() > 0) )
{
@@ -562,31 +535,17 @@ void BiffInputStream::calcRecordLength()
seek( nCurrPos ); // restore position, seek() resets old mbValid state
}
-bool BiffInputStream::ensureRawReadSize( sal_uInt16 nBytes )
-{
- if( !mbEof && (nBytes > 0) )
- {
- while( !mbEof && (maRecBuffer.getRecLeft() == 0) ) jumpToNextContinue();
- mbEof = mbEof || (nBytes > maRecBuffer.getRecLeft());
- OSL_ENSURE( !mbEof, "BiffInputStream::ensureRawReadSize - record overread" );
- }
- return !mbEof;
-}
-
-sal_uInt16 BiffInputStream::getMaxRawReadSize( sal_Int32 nBytes ) const
-{
- return getLimitedValue< sal_uInt16, sal_Int32 >( nBytes, 0, maRecBuffer.getRecLeft() );
-}
-
-void BiffInputStream::appendUnicodeArray( OUStringBuffer& orBuffer, sal_uInt16 nChars, bool b16BitChars, bool bAllowNulChars )
+sal_uInt16 BiffInputStream::getMaxRawReadSize( sal_Int32 nBytes, size_t nAtomSize ) const
{
- orBuffer.ensureCapacity( orBuffer.getLength() + nChars );
- sal_uInt16 nChar;
- for( sal_uInt16 nCharIdx = 0; !mbEof && (nCharIdx < nChars); ++nCharIdx )
+ sal_uInt16 nMaxSize = getLimitedValue< sal_uInt16, sal_Int32 >( nBytes, 0, maRecBuffer.getRecLeft() );
+ if( (0 < nMaxSize) && (nMaxSize < nBytes) && (nAtomSize > 1) )
{
- if( b16BitChars ) readValue( nChar ); else nChar = readuInt8();
- orBuffer.append( static_cast< sal_Unicode >( (!bAllowNulChars && (nChar == 0)) ? '?' : nChar ) );
+ // check that remaining data in record buffer is a multiple of the passed atom size
+ sal_uInt16 nPadding = static_cast< sal_uInt16 >( nMaxSize % nAtomSize );
+ OSL_ENSURE( nPadding == 0, "BiffInputStream::getMaxRawReadSize - alignment error" );
+ nMaxSize = nMaxSize - nPadding;
}
+ return nMaxSize;
}
void BiffInputStream::readUniStringHeader( bool& orb16BitChars, sal_Int32& ornAddSize )
diff --git a/oox/source/xls/biffoutputstream.cxx b/oox/source/xls/biffoutputstream.cxx
index 5e87e683e075..df28b6e27379 100644
--- a/oox/source/xls/biffoutputstream.cxx
+++ b/oox/source/xls/biffoutputstream.cxx
@@ -86,6 +86,7 @@ void BiffOutputRecordBuffer::fill( sal_uInt8 nValue, sal_uInt16 nBytes )
// ============================================================================
BiffOutputStream::BiffOutputStream( BinaryOutputStream& rOutStream, sal_uInt16 nMaxRecSize ) :
+ BinaryStreamBase( true ),
maRecBuffer( rOutStream, nMaxRecSize ),
mnPortionSize( 0 ),
mnPortionPos( 0 )
@@ -97,19 +98,19 @@ BiffOutputStream::BiffOutputStream( BinaryOutputStream& rOutStream, sal_uInt16 n
void BiffOutputStream::startRecord( sal_uInt16 nRecId )
{
maRecBuffer.startRecord( nRecId );
- setPortionSize( 0 );
+ setPortionSize( 1 );
}
void BiffOutputStream::endRecord()
{
- setPortionSize( 0 );
+ setPortionSize( 1 );
maRecBuffer.endRecord();
}
-void BiffOutputStream::setPortionSize( sal_uInt16 nSize )
+void BiffOutputStream::setPortionSize( sal_uInt8 nSize )
{
OSL_ENSURE( mnPortionPos == 0, "BiffOutputStream::setPortionSize - block operation inside portion" );
- mnPortionSize = nSize;
+ mnPortionSize = ::std::max< sal_uInt8 >( nSize, 1 );
mnPortionPos = 0;
}
@@ -120,20 +121,20 @@ sal_Int64 BiffOutputStream::tellBase() const
return maRecBuffer.getBaseStream().tell();
}
-sal_Int64 BiffOutputStream::getBaseLength() const
+sal_Int64 BiffOutputStream::sizeBase() const
{
- return maRecBuffer.getBaseStream().getLength();
+ return maRecBuffer.getBaseStream().size();
}
// BinaryOutputStream interface (stream write access) -------------------------
-void BiffOutputStream::writeData( const StreamDataSequence& rData )
+void BiffOutputStream::writeData( const StreamDataSequence& rData, size_t nAtomSize )
{
if( rData.hasElements() )
- writeMemory( rData.getConstArray(), rData.getLength() );
+ writeMemory( rData.getConstArray(), rData.getLength(), nAtomSize );
}
-void BiffOutputStream::writeMemory( const void* pMem, sal_Int32 nBytes )
+void BiffOutputStream::writeMemory( const void* pMem, sal_Int32 nBytes, size_t nAtomSize )
{
if( pMem && (nBytes > 0) )
{
@@ -141,7 +142,7 @@ void BiffOutputStream::writeMemory( const void* pMem, sal_Int32 nBytes )
sal_Int32 nBytesLeft = nBytes;
while( nBytesLeft > 0 )
{
- sal_uInt16 nBlockSize = prepareRawBlock( nBytesLeft );
+ sal_uInt16 nBlockSize = prepareWriteBlock( nBytesLeft, nAtomSize );
maRecBuffer.write( pnBuffer, nBlockSize );
pnBuffer += nBlockSize;
nBytesLeft -= nBlockSize;
@@ -149,59 +150,60 @@ void BiffOutputStream::writeMemory( const void* pMem, sal_Int32 nBytes )
}
}
-void BiffOutputStream::fill( sal_uInt8 nValue, sal_Int32 nBytes )
+void BiffOutputStream::fill( sal_uInt8 nValue, sal_Int32 nBytes, size_t nAtomSize )
{
sal_Int32 nBytesLeft = nBytes;
while( nBytesLeft > 0 )
{
- sal_uInt16 nBlockSize = prepareRawBlock( nBytesLeft );
+ sal_uInt16 nBlockSize = prepareWriteBlock( nBytesLeft, nAtomSize );
maRecBuffer.fill( nValue, nBlockSize );
nBytesLeft -= nBlockSize;
}
}
-void BiffOutputStream::writeBlock( const void* pMem, sal_uInt16 nBytes )
-{
- ensureRawBlock( nBytes );
- maRecBuffer.write( pMem, nBytes );
-}
-
// private --------------------------------------------------------------------
-void BiffOutputStream::writeAtom( const void* pMem, sal_uInt8 nSize )
-{
- // byte swapping is done in calling BinaryOutputStream::writeValue() template function
- writeBlock( pMem, nSize );
-}
-
-void BiffOutputStream::ensureRawBlock( sal_uInt16 nSize )
+sal_uInt16 BiffOutputStream::prepareWriteBlock( sal_Int32 nTotalSize, size_t nAtomSize )
{
- if( (maRecBuffer.getRecLeft() < nSize) ||
- ((mnPortionSize > 0) && (mnPortionPos == 0) && (maRecBuffer.getRecLeft() < mnPortionSize)) )
+ sal_uInt16 nRecLeft = maRecBuffer.getRecLeft();
+ if( mnPortionSize <= 1 )
{
- maRecBuffer.endRecord();
- maRecBuffer.startRecord( BIFF_ID_CONT );
+ // no portions: restrict remaining record size to entire atoms
+ nRecLeft = static_cast< sal_uInt16 >( (nRecLeft / nAtomSize) * nAtomSize );
}
- if( mnPortionSize > 0 )
+ else
{
- OSL_ENSURE( mnPortionPos + nSize <= mnPortionSize, "BiffOutputStream::ensureRawBlock - portion overflow" );
- mnPortionPos = (mnPortionPos + nSize) % mnPortionSize; // prevent compiler warning, do not use operator+=, operator%=
+ sal_Int32 nPortionLeft = mnPortionSize - mnPortionPos;
+ if( nTotalSize <= nPortionLeft )
+ {
+ // block fits into the current portion
+ OSL_ENSURE( nPortionLeft <= nRecLeft, "BiffOutputStream::prepareWriteBlock - portion exceeds record" );
+ mnPortionPos = static_cast< sal_uInt8 >( (mnPortionPos + nTotalSize) % mnPortionSize );
+ }
+ else
+ {
+ // restrict remaining record size to entire portions
+ OSL_ENSURE( mnPortionPos == 0, "BiffOutputStream::prepareWriteBlock - writing over multiple portions starts inside portion" );
+ mnPortionPos = 0;
+ // check that atom size matches portion size
+ OSL_ENSURE( mnPortionSize % nAtomSize == 0, "BiffOutputStream::prepareWriteBlock - atom size does not match portion size" );
+ sal_uInt8 nPortionSize = static_cast< sal_uInt8 >( (mnPortionSize / nAtomSize) * nAtomSize );
+ // restrict remaining record size to entire portions
+ nRecLeft = (nRecLeft / nPortionSize) * nPortionSize;
+ }
}
-}
-sal_uInt16 BiffOutputStream::prepareRawBlock( sal_Int32 nTotalSize )
-{
- sal_uInt16 nRecLeft = maRecBuffer.getRecLeft();
- if( mnPortionSize > 0 )
- {
- OSL_ENSURE( mnPortionPos == 0, "BiffOutputStream::prepareRawBlock - block operation inside portion" );
- OSL_ENSURE( nTotalSize % mnPortionSize == 0, "BiffOutputStream::prepareRawBlock - portion size does not match block size" );
- nRecLeft = (nRecLeft / mnPortionSize) * mnPortionSize;
- }
- sal_uInt16 nSize = getLimitedValue< sal_uInt16, sal_Int32 >( nTotalSize, 0, nRecLeft );
- ensureRawBlock( nSize );
- return nSize;
+ // current record has space for some data: return size of available space
+ if( nRecLeft > 0 )
+ return getLimitedValue< sal_uInt16, sal_Int32 >( nTotalSize, 0, nRecLeft );
+
+ // finish current record and start a new CONTINUE record
+ maRecBuffer.endRecord();
+ maRecBuffer.startRecord( BIFF_ID_CONT );
+ mnPortionPos = 0;
+ return prepareWriteBlock( nTotalSize, nAtomSize );
}
+
// ============================================================================
} // namespace xls
diff --git a/oox/source/xls/chartsheetfragment.cxx b/oox/source/xls/chartsheetfragment.cxx
index 0cdb37fecc2e..3cf8114e08b3 100644
--- a/oox/source/xls/chartsheetfragment.cxx
+++ b/oox/source/xls/chartsheetfragment.cxx
@@ -46,9 +46,8 @@ using ::rtl::OUString;
// ============================================================================
-ChartsheetFragment::ChartsheetFragment( const WorkbookHelper& rHelper,
- const OUString& rFragmentPath, const ISegmentProgressBarRef& rxProgressBar, sal_Int16 nSheet ) :
- WorksheetFragmentBase( rHelper, rFragmentPath, rxProgressBar, SHEETTYPE_CHARTSHEET, nSheet )
+ChartsheetFragment::ChartsheetFragment( const WorksheetHelper& rHelper, const OUString& rFragmentPath ) :
+ WorksheetFragmentBase( rHelper, rFragmentPath )
{
}
@@ -180,9 +179,8 @@ void ChartsheetFragment::importDrawing( SequenceInputStream& rStrm )
// ============================================================================
-BiffChartsheetFragment::BiffChartsheetFragment( const BiffWorkbookFragmentBase& rParent,
- const ISegmentProgressBarRef& rxProgressBar, sal_Int16 nSheet ) :
- BiffWorksheetFragmentBase( rParent, rxProgressBar, SHEETTYPE_CHARTSHEET, nSheet )
+BiffChartsheetFragment::BiffChartsheetFragment( const WorksheetHelper& rHelper, const BiffWorkbookFragmentBase& rParent ) :
+ BiffWorksheetFragmentBase( rHelper, rParent )
{
}
diff --git a/oox/source/xls/commentsbuffer.cxx b/oox/source/xls/commentsbuffer.cxx
index 34cc33476649..06a77df7685d 100644
--- a/oox/source/xls/commentsbuffer.cxx
+++ b/oox/source/xls/commentsbuffer.cxx
@@ -38,9 +38,11 @@
#include "oox/helper/attributelist.hxx"
#include "oox/vml/vmlshape.hxx"
#include "oox/xls/addressconverter.hxx"
+#include "oox/xls/biffinputstream.hxx"
#include "oox/xls/drawingfragment.hxx"
#include "svx/sdtaitm.hxx"
#include "oox/xls/unitconverter.hxx"
+#include "oox/xls/drawingmanager.hxx"
#include <com/sun/star/text/XText.hpp>
#include <com/sun/star/text/XTextRange.hpp>
@@ -58,6 +60,7 @@ namespace xls {
using namespace ::com::sun::star::drawing;
using namespace ::com::sun::star::sheet;
using namespace ::com::sun::star::table;
+using namespace ::com::sun::star::text;
using namespace ::com::sun::star::uno;
using ::rtl::OUString;
@@ -96,8 +99,18 @@ static sal_Int32 lcl_ToVertAlign( sal_Int32 nAlign )
// ============================================================================
+namespace {
+
+const sal_uInt16 BIFF_NOTE_VISIBLE = 0x0002;
+
+} // namespace
+
+// ============================================================================
+
CommentModel::CommentModel() :
- mnAuthorId( -1 )
+ mnAuthorId( -1 ),
+ mnObjId( BIFF_OBJ_INVALID_ID ),
+ mbVisible( false )
{
}
@@ -178,6 +191,35 @@ void Comment::importComment( SequenceInputStream& rStrm )
getAddressConverter().convertToCellRangeUnchecked( maModel.maRange, aBinRange, getSheetIndex() );
}
+void Comment::importNote( BiffInputStream& rStrm )
+{
+ BinAddress aBinAddr;
+ rStrm >> aBinAddr;
+ // cell range will be checked while inserting the comment into the document
+ getAddressConverter().convertToCellRangeUnchecked( maModel.maRange, BinRange( aBinAddr ), getSheetIndex() );
+
+ // remaining record data is BIFF dependent
+ switch( getBiff() )
+ {
+ case BIFF2:
+ case BIFF3:
+ importNoteBiff2( rStrm );
+ break;
+ case BIFF4:
+ case BIFF5:
+ importNoteBiff2( rStrm );
+ // in BIFF4 and BIFF5, comments can have an associated sound
+ if( (rStrm.getNextRecId() == BIFF_ID_NOTESOUND) && rStrm.startNextRecord() )
+ importNoteSound( rStrm );
+ break;
+ case BIFF8:
+ importNoteBiff8( rStrm );
+ break;
+ case BIFF_UNKNOWN:
+ break;
+ }
+}
+
RichStringRef Comment::createText()
{
maModel.mxText.reset( new RichString( *this ) );
@@ -193,53 +235,110 @@ void Comment::finalizeImport()
CellAddress aNotePos( maModel.maRange.Sheet, maModel.maRange.StartColumn, maModel.maRange.StartRow );
if( getAddressConverter().checkCellAddress( aNotePos, true ) && maModel.mxText.get() ) try
{
- maModel.mxText->finalizeImport();
- OUString aNoteText = maModel.mxText->getPlainText();
- // non-empty string required by note implementation
- if( aNoteText.getLength() > 0 )
+ Reference< XSheetAnnotationsSupplier > xAnnosSupp( getSheet(), UNO_QUERY_THROW );
+ Reference< XSheetAnnotations > xAnnos( xAnnosSupp->getAnnotations(), UNO_SET_THROW );
+ // non-empty string required by note implementation (real text will be added below)
+ xAnnos->insertNew( aNotePos, OUString( sal_Unicode( ' ' ) ) );
+
+ // receive created note from cell (insertNew does not return the note)
+ Reference< XSheetAnnotationAnchor > xAnnoAnchor( getCell( aNotePos ), UNO_QUERY_THROW );
+ Reference< XSheetAnnotation > xAnno( xAnnoAnchor->getAnnotation(), UNO_SET_THROW );
+ Reference< XSheetAnnotationShapeSupplier > xAnnoShapeSupp( xAnno, UNO_QUERY_THROW );
+ Reference< XShape > xAnnoShape( xAnnoShapeSupp->getAnnotationShape(), UNO_SET_THROW );
+
+ // convert shape formatting and visibility
+ sal_Bool bVisible = sal_True;
+ switch( getFilterType() )
{
- Reference< XSheetAnnotationsSupplier > xAnnosSupp( getSheet(), UNO_QUERY_THROW );
- Reference< XSheetAnnotations > xAnnos( xAnnosSupp->getAnnotations(), UNO_SET_THROW );
- xAnnos->insertNew( aNotePos, aNoteText );
- // receive craeted note from cell (insertNew does not return the note)
- Reference< XSheetAnnotationAnchor > xAnnoAnchor( getCell( aNotePos ), UNO_QUERY_THROW );
- Reference< XSheetAnnotation > xAnno( xAnnoAnchor->getAnnotation(), UNO_SET_THROW );
- Reference< XSheetAnnotationShapeSupplier > xAnnoShapeSupp( xAnno, UNO_QUERY_THROW );
- Reference< XShape > xAnnoShape( xAnnoShapeSupp->getAnnotationShape(), UNO_SET_THROW );
- Reference <XText> xText( xAnnoShape, UNO_QUERY_THROW );
- Reference <XTextRange> xTextRange( xText, UNO_QUERY_THROW );
- xTextRange->setString( OUString() ); // Clear contents
- maModel.mxText->convert( xText, -1 );
-
- // Add shape formatting properties (autoFill, colHidden and rowHidden are dropped)
- PropertySet aCommentPr( xAnnoShape );
- aCommentPr.setProperty( PROP_TextFitToSize, maModel.mbAutoScale );
- aCommentPr.setProperty( PROP_MoveProtect, maModel.mbLocked );
- aCommentPr.setProperty( PROP_TextHorizontalAdjust, lcl_ToHorizAlign( maModel.mnTHA ) );
- aCommentPr.setProperty( PROP_TextVerticalAdjust, lcl_ToVertAlign( maModel.mnTVA ) );
- if( maModel.maAnchor.Width > 0 && maModel.maAnchor.Height > 0 )
- {
- xAnnoShape->setPosition( Point( maModel.maAnchor.X, maModel.maAnchor.Y ) );
- xAnnoShape->setSize( Size( maModel.maAnchor.Width, maModel.maAnchor.Height ) );
- }
-
-
- // convert shape formatting
- if( const ::oox::vml::ShapeBase* pNoteShape = getVmlDrawing().getNoteShape( aNotePos ) )
- {
- // position and formatting
- pNoteShape->convertFormatting( xAnnoShape );
- // visibility
- const ::oox::vml::ClientData* pClientData = pNoteShape->getClientData();
- xAnno->setIsVisible( pClientData && pClientData->mbVisible );
- }
+ case FILTER_OOXML:
+ {
+ // Add shape formatting properties (autoFill, colHidden and rowHidden are dropped)
+ PropertySet aCommentPr( xAnnoShape );
+ aCommentPr.setProperty( PROP_TextFitToSize, maModel.mbAutoScale );
+ aCommentPr.setProperty( PROP_MoveProtect, maModel.mbLocked );
+ aCommentPr.setProperty( PROP_TextHorizontalAdjust, lcl_ToHorizAlign( maModel.mnTHA ) );
+ aCommentPr.setProperty( PROP_TextVerticalAdjust, lcl_ToVertAlign( maModel.mnTVA ) );
+ if( maModel.maAnchor.Width > 0 && maModel.maAnchor.Height > 0 )
+ {
+ xAnnoShape->setPosition( Point( maModel.maAnchor.X, maModel.maAnchor.Y ) );
+ xAnnoShape->setSize( Size( maModel.maAnchor.Width, maModel.maAnchor.Height ) );
+ }
+
+ // convert shape formatting
+ if( const ::oox::vml::ShapeBase* pNoteShape = getVmlDrawing().getNoteShape( aNotePos ) )
+ {
+ // position and formatting
+ pNoteShape->convertFormatting( xAnnoShape );
+ // visibility
+ const ::oox::vml::ClientData* pClientData = pNoteShape->getClientData();
+ xAnno->setIsVisible( pClientData && pClientData->mbVisible );
+ }
+ }
+ break;
+ case FILTER_BIFF:
+ bVisible = maModel.mbVisible;
+ break;
+ case FILTER_UNKNOWN:
+ break;
}
+ xAnno->setIsVisible( bVisible );
+
+ // insert text and convert text formatting
+ maModel.mxText->finalizeImport();
+ Reference< XText > xAnnoText( xAnnoShape, UNO_QUERY_THROW );
+ maModel.mxText->convert( xAnnoText );
}
catch( Exception& )
{
}
}
+// private --------------------------------------------------------------------
+
+void Comment::importNoteBiff2( BiffInputStream& rStrm )
+{
+ sal_uInt16 nTotalLen;
+ rStrm >> nTotalLen;
+ sal_uInt16 nPartLen = ::std::min( nTotalLen, static_cast< sal_uInt16 >( rStrm.getRemaining() ) );
+ RichStringRef xNoteText = createText();
+ xNoteText->importCharArray( rStrm, nPartLen, getTextEncoding() );
+
+ nTotalLen = nTotalLen - nPartLen; // operator-=() gives compiler warning
+ while( (nTotalLen > 0) && (rStrm.getNextRecId() == BIFF_ID_NOTE) && rStrm.startNextRecord() )
+ {
+ sal_uInt16 nMarker;
+ rStrm >> nMarker;
+ rStrm.skip( 2 );
+ rStrm >> nPartLen;
+ OSL_ENSURE( nMarker == 0xFFFF, "Comment::importNoteBiff2 - missing continuation NOTE record" );
+ if( nMarker == 0xFFFF )
+ {
+ OSL_ENSURE( nPartLen <= nTotalLen, "Comment::importNoteBiff2 - string too long" );
+ // call to RichString::importCharArray() appends new text portion
+ xNoteText->importCharArray( rStrm, nPartLen, getTextEncoding() );
+ nTotalLen = nTotalLen - ::std::min( nTotalLen, nPartLen );
+ }
+ else
+ {
+ // seems to be a new note, rewind record, so worksheet fragment loop will find it
+ rStrm.rewindRecord();
+ nTotalLen = 0;
+ }
+ }
+}
+
+void Comment::importNoteBiff8( BiffInputStream& rStrm )
+{
+ sal_uInt16 nFlags;
+ rStrm >> nFlags >> maModel.mnObjId;
+ maModel.maAuthor = rStrm.readUniString();
+ maModel.mbVisible = getFlag( nFlags, BIFF_NOTE_VISIBLE );
+}
+
+void Comment::importNoteSound( BiffInputStream& /*rStrm*/ )
+{
+}
+
// ============================================================================
CommentsBuffer::CommentsBuffer( const WorksheetHelper& rHelper ) :
diff --git a/oox/source/xls/condformatbuffer.cxx b/oox/source/xls/condformatbuffer.cxx
index 3f03bc51dc96..26355dc2a1c2 100644
--- a/oox/source/xls/condformatbuffer.cxx
+++ b/oox/source/xls/condformatbuffer.cxx
@@ -194,10 +194,9 @@ void CondFormatRule::importCfRule( const AttributeList& rAttribs )
void CondFormatRule::appendFormula( const OUString& rFormula )
{
- TokensFormulaContext aContext( true, false );
- aContext.setBaseAddress( mrCondFormat.getRanges().getBaseAddress() );
- getFormulaParser().importFormula( aContext, rFormula );
- maModel.maFormulas.push_back( aContext );
+ CellAddress aBaseAddr = mrCondFormat.getRanges().getBaseAddress();
+ ApiTokenSequence aTokens = getFormulaParser().importFormula( aBaseAddr, rFormula );
+ maModel.maFormulas.push_back( aTokens );
}
void CondFormatRule::importCfRule( SequenceInputStream& rStrm )
@@ -217,25 +216,24 @@ void CondFormatRule::importCfRule( SequenceInputStream& rStrm )
OSL_ENSURE( (nFmla1Size > 0) == (rStrm.getRemaining() >= 8), "CondFormatRule::importCfRule - formula size mismatch" );
if( rStrm.getRemaining() >= 8 )
{
- TokensFormulaContext aContext( true, false );
- aContext.setBaseAddress( mrCondFormat.getRanges().getBaseAddress() );
- getFormulaParser().importFormula( aContext, rStrm );
- maModel.maFormulas.push_back( aContext );
+ CellAddress aBaseAddr = mrCondFormat.getRanges().getBaseAddress();
+ ApiTokenSequence aTokens = getFormulaParser().importFormula( aBaseAddr, FORMULATYPE_CONDFORMAT, rStrm );
+ maModel.maFormulas.push_back( aTokens );
// second formula
OSL_ENSURE( (nFmla2Size >= 0) || (nFmla3Size == 0), "CondFormatRule::importCfRule - missing second formula" );
OSL_ENSURE( (nFmla2Size > 0) == (rStrm.getRemaining() >= 8), "CondFormatRule::importCfRule - formula size mismatch" );
if( rStrm.getRemaining() >= 8 )
{
- getFormulaParser().importFormula( aContext, rStrm );
- maModel.maFormulas.push_back( aContext );
+ aTokens = getFormulaParser().importFormula( aBaseAddr, FORMULATYPE_CONDFORMAT, rStrm );
+ maModel.maFormulas.push_back( aTokens );
// third formula
OSL_ENSURE( (nFmla3Size > 0) == (rStrm.getRemaining() >= 8), "CondFormatRule::importCfRule - formula size mismatch" );
if( rStrm.getRemaining() >= 8 )
{
- getFormulaParser().importFormula( aContext, rStrm );
- maModel.maFormulas.push_back( aContext );
+ aTokens = getFormulaParser().importFormula( aBaseAddr, FORMULATYPE_CONDFORMAT, rStrm );
+ maModel.maFormulas.push_back( aTokens );
}
}
}
@@ -420,14 +418,13 @@ void CondFormatRule::importCfRule( BiffInputStream& rStrm, sal_Int32 nPriority )
OSL_ENSURE( (nFmla1Size > 0) || (nFmla2Size == 0), "CondFormatRule::importCfRule - missing first formula" );
if( nFmla1Size > 0 )
{
- TokensFormulaContext aContext( true, false );
- aContext.setBaseAddress( mrCondFormat.getRanges().getBaseAddress() );
- getFormulaParser().importFormula( aContext, rStrm, &nFmla1Size );
- maModel.maFormulas.push_back( aContext );
+ CellAddress aBaseAddr = mrCondFormat.getRanges().getBaseAddress();
+ ApiTokenSequence aTokens = getFormulaParser().importFormula( aBaseAddr, FORMULATYPE_CONDFORMAT, rStrm, &nFmla1Size );
+ maModel.maFormulas.push_back( aTokens );
if( nFmla2Size > 0 )
{
- getFormulaParser().importFormula( aContext, rStrm, &nFmla2Size );
- maModel.maFormulas.push_back( aContext );
+ aTokens = getFormulaParser().importFormula( aBaseAddr, FORMULATYPE_CONDFORMAT, rStrm, &nFmla2Size );
+ maModel.maFormulas.push_back( aTokens );
}
}
}
@@ -605,9 +602,9 @@ void CondFormatRule::finalizeImport( const Reference< XSheetConditionalEntries >
::std::vector< PropertyValue > aProps;
// create condition properties
lclAppendProperty( aProps, CREATE_OUSTRING( "Operator" ), eOperator );
- lclAppendProperty( aProps, CREATE_OUSTRING( "Formula1" ), maModel.maFormulas[ 0 ].getTokens() );
+ lclAppendProperty( aProps, CREATE_OUSTRING( "Formula1" ), maModel.maFormulas[ 0 ] );
if( maModel.maFormulas.size() >= 2 )
- lclAppendProperty( aProps, CREATE_OUSTRING( "Formula2" ), maModel.maFormulas[ 1 ].getTokens() );
+ lclAppendProperty( aProps, CREATE_OUSTRING( "Formula2" ), maModel.maFormulas[ 1 ] );
// style name for the formatting attributes
OUString aStyleName = getStyles().createDxfStyle( maModel.mnDxfId );
@@ -750,7 +747,6 @@ void CondFormatBuffer::finalizeImport()
sal_Int32 CondFormatBuffer::convertToApiOperator( sal_Int32 nToken )
{
- using namespace ::com::sun::star::sheet;
switch( nToken )
{
case XML_between: return ConditionOperator2::BETWEEN;
diff --git a/oox/source/xls/defnamesbuffer.cxx b/oox/source/xls/defnamesbuffer.cxx
index 73383862176d..fce1bfb589ef 100644
--- a/oox/source/xls/defnamesbuffer.cxx
+++ b/oox/source/xls/defnamesbuffer.cxx
@@ -190,32 +190,32 @@ void lclConvertRefFlags( sal_Int32& ornFlags, sal_Int32& ornAbsPos, sal_Int32& o
}
}
-void lclConvertSingleRefFlags( SingleReference& orApiRef, const CellAddress& rBaseAddress, bool bColRel, bool bRowRel )
+void lclConvertSingleRefFlags( SingleReference& orApiRef, const CellAddress& rBaseAddr, bool bColRel, bool bRowRel )
{
using namespace ::com::sun::star::sheet::ReferenceFlags;
lclConvertRefFlags(
orApiRef.Flags, orApiRef.Column, orApiRef.RelativeColumn,
- rBaseAddress.Column, COLUMN_RELATIVE, bColRel );
+ rBaseAddr.Column, COLUMN_RELATIVE, bColRel );
lclConvertRefFlags(
orApiRef.Flags, orApiRef.Row, orApiRef.RelativeRow,
- rBaseAddress.Row, ROW_RELATIVE, bRowRel );
+ rBaseAddr.Row, ROW_RELATIVE, bRowRel );
}
-Any lclConvertReference( const Any& rRefAny, const CellAddress& rBaseAddress, sal_uInt16 nRelFlags )
+Any lclConvertReference( const Any& rRefAny, const CellAddress& rBaseAddr, sal_uInt16 nRelFlags )
{
if( rRefAny.has< SingleReference >() && !getFlag( nRelFlags, BIFF_REFFLAG_COL2REL ) && !getFlag( nRelFlags, BIFF_REFFLAG_ROW2REL ) )
{
SingleReference aApiRef;
rRefAny >>= aApiRef;
- lclConvertSingleRefFlags( aApiRef, rBaseAddress, getFlag( nRelFlags, BIFF_REFFLAG_COL1REL ), getFlag( nRelFlags, BIFF_REFFLAG_ROW1REL ) );
+ lclConvertSingleRefFlags( aApiRef, rBaseAddr, getFlag( nRelFlags, BIFF_REFFLAG_COL1REL ), getFlag( nRelFlags, BIFF_REFFLAG_ROW1REL ) );
return Any( aApiRef );
}
if( rRefAny.has< ComplexReference >() )
{
ComplexReference aApiRef;
rRefAny >>= aApiRef;
- lclConvertSingleRefFlags( aApiRef.Reference1, rBaseAddress, getFlag( nRelFlags, BIFF_REFFLAG_COL1REL ), getFlag( nRelFlags, BIFF_REFFLAG_ROW1REL ) );
- lclConvertSingleRefFlags( aApiRef.Reference2, rBaseAddress, getFlag( nRelFlags, BIFF_REFFLAG_COL2REL ), getFlag( nRelFlags, BIFF_REFFLAG_ROW2REL ) );
+ lclConvertSingleRefFlags( aApiRef.Reference1, rBaseAddr, getFlag( nRelFlags, BIFF_REFFLAG_COL1REL ), getFlag( nRelFlags, BIFF_REFFLAG_ROW1REL ) );
+ lclConvertSingleRefFlags( aApiRef.Reference2, rBaseAddr, getFlag( nRelFlags, BIFF_REFFLAG_COL2REL ), getFlag( nRelFlags, BIFF_REFFLAG_ROW2REL ) );
return Any( aApiRef );
}
return Any();
@@ -249,7 +249,7 @@ const OUString& DefinedNameBase::getUpcaseModelName() const
return maUpModelName;
}
-Any DefinedNameBase::getReference( const CellAddress& rBaseAddress ) const
+Any DefinedNameBase::getReference( const CellAddress& rBaseAddr ) const
{
if( maRefAny.hasValue() && (maModel.maName.getLength() >= 2) && (maModel.maName[ 0 ] == '\x01') )
{
@@ -261,7 +261,7 @@ Any DefinedNameBase::getReference( const CellAddress& rBaseAddress ) const
{
ExternalReference aApiExtRef;
maRefAny >>= aApiExtRef;
- Any aRefAny = lclConvertReference( aApiExtRef.Reference, rBaseAddress, nRelFlags );
+ Any aRefAny = lclConvertReference( aApiExtRef.Reference, rBaseAddr, nRelFlags );
if( aRefAny.hasValue() )
{
aApiExtRef.Reference <<= aRefAny;
@@ -270,37 +270,30 @@ Any DefinedNameBase::getReference( const CellAddress& rBaseAddress ) const
}
else
{
- return lclConvertReference( maRefAny, rBaseAddress, nRelFlags );
+ return lclConvertReference( maRefAny, rBaseAddr, nRelFlags );
}
}
}
return Any();
}
-void DefinedNameBase::importOoxFormula( FormulaContext& rContext, sal_Int16 nBaseSheet )
+ApiTokenSequence DefinedNameBase::importOoxFormula( sal_Int16 nBaseSheet )
{
- if( maModel.maFormula.getLength() > 0 )
- {
- rContext.setBaseAddress( CellAddress( nBaseSheet, 0, 0 ) );
- getFormulaParser().importFormula( rContext, maModel.maFormula );
- }
- else
- getFormulaParser().convertErrorToFormula( rContext, BIFF_ERR_NAME );
+ return (maModel.maFormula.getLength() > 0) ?
+ getFormulaParser().importFormula( CellAddress( nBaseSheet, 0, 0 ), maModel.maFormula ) :
+ getFormulaParser().convertErrorToFormula( BIFF_ERR_NAME );
}
-void DefinedNameBase::importBiff12Formula( FormulaContext& rContext, sal_Int16 nBaseSheet, SequenceInputStream& rStrm )
+ApiTokenSequence DefinedNameBase::importBiff12Formula( sal_Int16 nBaseSheet, SequenceInputStream& rStrm )
{
- rContext.setBaseAddress( CellAddress( nBaseSheet, 0, 0 ) );
- getFormulaParser().importFormula( rContext, rStrm );
+ return getFormulaParser().importFormula( CellAddress( nBaseSheet, 0, 0 ), FORMULATYPE_DEFINEDNAME, rStrm );
}
-void DefinedNameBase::importBiffFormula( FormulaContext& rContext, sal_Int16 nBaseSheet, BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize )
+ApiTokenSequence DefinedNameBase::importBiffFormula( sal_Int16 nBaseSheet, BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize )
{
- rContext.setBaseAddress( CellAddress( nBaseSheet, 0, 0 ) );
- if( !pnFmlaSize || (*pnFmlaSize > 0) )
- getFormulaParser().importFormula( rContext, rStrm, pnFmlaSize );
- else
- getFormulaParser().convertErrorToFormula( rContext, BIFF_ERR_NAME );
+ return (!pnFmlaSize || (*pnFmlaSize > 0)) ?
+ getFormulaParser().importFormula( CellAddress( nBaseSheet, 0, 0 ), FORMULATYPE_DEFINEDNAME, rStrm, pnFmlaSize ) :
+ getFormulaParser().convertErrorToFormula( BIFF_ERR_NAME );
}
void DefinedNameBase::extractReference( const ApiTokenSequence& rTokens )
@@ -468,9 +461,8 @@ void DefinedName::importDefinedName( BiffInputStream& rStrm, sal_Int16 nCalcShee
these names contain a simple cell reference or range reference.
Other regular defined names and external names rely on existence of
this reference. */
- TokensFormulaContext aContext( true, true );
- importBiffFormula( aContext, mnCalcSheet, rStrm, &mnFmlaSize );
- extractReference( aContext.getTokens() );
+ ApiTokenSequence aTokens = importBiffFormula( mnCalcSheet, rStrm, &mnFmlaSize );
+ extractReference( aTokens );
}
else
{
@@ -489,6 +481,10 @@ void DefinedName::createNameObject()
if( /*maModel.mbHidden ||*/ maModel.mbFunction || maModel.mbVBName )
return;
+ // skip BIFF names without stream position (e.g. BIFF3-BIFF4 internal 3D references)
+ if( (getFilterType() == FILTER_BIFF) && !mxBiffStrm.get() )
+ return;
+
// convert original name to final Calc name (TODO: filter invalid characters from model name)
maCalcName = isBuiltinName() ? lclGetPrefixedName( mcBuiltinId ) : maModel.maName;
@@ -520,69 +516,83 @@ void DefinedName::createNameObject()
void DefinedName::convertFormula()
{
Reference< XFormulaTokens > xTokens( mxNamedRange, UNO_QUERY );
- if( xTokens.is() )
+ if( !xTokens.is() )
+ return;
+
+ // convert and set formula of the defined name
+ ApiTokenSequence aTokens;
+ switch( getFilterType() )
{
- // convert and set formula of the defined name
- switch( getFilterType() )
+ case FILTER_OOXML:
{
- case FILTER_OOXML:
+ if( mxFormula.get() )
{
- SimpleFormulaContext aContext( xTokens, true, false );
- implImportOoxFormula( aContext );
+ SequenceInputStream aStrm( *mxFormula );
+ aTokens = importBiff12Formula( mnCalcSheet, aStrm );
}
- break;
- case FILTER_BIFF:
+ else
+ aTokens = importOoxFormula( mnCalcSheet );
+ }
+ break;
+ case FILTER_BIFF:
+ {
+ OSL_ENSURE( mxBiffStrm.get(), "DefinedName::convertFormula - missing BIFF stream" );
+ if( mxBiffStrm.get() )
{
- SimpleFormulaContext aContext( xTokens, true, getBiff() <= BIFF4 );
- implImportBiffFormula( aContext );
+ BiffInputStream& rStrm = mxBiffStrm->getStream();
+ BiffInputStreamPosGuard aStrmGuard( rStrm );
+ if( mxBiffStrm->restorePosition() )
+ aTokens = importBiffFormula( mnCalcSheet, rStrm, &mnFmlaSize );
}
- break;
- case FILTER_UNKNOWN: break;
}
+ break;
+ case FILTER_UNKNOWN:
+ break;
+ }
+ xTokens->setTokens( aTokens );
- // set built-in names (print ranges, repeated titles, filter ranges)
- if( !isGlobalName() ) switch( mcBuiltinId )
+ // set built-in names (print ranges, repeated titles, filter ranges)
+ if( !isGlobalName() ) switch( mcBuiltinId )
+ {
+ case BIFF_DEFNAME_PRINTAREA:
{
- case BIFF_DEFNAME_PRINTAREA:
- {
- Reference< XPrintAreas > xPrintAreas( getSheetFromDoc( mnCalcSheet ), UNO_QUERY );
- ApiCellRangeList aPrintRanges;
- getFormulaParser().extractCellRangeList( aPrintRanges, xTokens->getTokens(), false, mnCalcSheet );
- if( xPrintAreas.is() && !aPrintRanges.empty() )
- xPrintAreas->setPrintAreas( ContainerHelper::vectorToSequence( aPrintRanges ) );
- }
- break;
- case BIFF_DEFNAME_PRINTTITLES:
+ Reference< XPrintAreas > xPrintAreas( getSheetFromDoc( mnCalcSheet ), UNO_QUERY );
+ ApiCellRangeList aPrintRanges;
+ getFormulaParser().extractCellRangeList( aPrintRanges, xTokens->getTokens(), false, mnCalcSheet );
+ if( xPrintAreas.is() && !aPrintRanges.empty() )
+ xPrintAreas->setPrintAreas( ContainerHelper::vectorToSequence( aPrintRanges ) );
+ }
+ break;
+ case BIFF_DEFNAME_PRINTTITLES:
+ {
+ Reference< XPrintAreas > xPrintAreas( getSheetFromDoc( mnCalcSheet ), UNO_QUERY );
+ ApiCellRangeList aTitleRanges;
+ getFormulaParser().extractCellRangeList( aTitleRanges, xTokens->getTokens(), false, mnCalcSheet );
+ if( xPrintAreas.is() && !aTitleRanges.empty() )
{
- Reference< XPrintAreas > xPrintAreas( getSheetFromDoc( mnCalcSheet ), UNO_QUERY );
- ApiCellRangeList aTitleRanges;
- getFormulaParser().extractCellRangeList( aTitleRanges, xTokens->getTokens(), false, mnCalcSheet );
- if( xPrintAreas.is() && !aTitleRanges.empty() )
+ bool bHasRowTitles = false;
+ bool bHasColTitles = false;
+ const CellAddress& rMaxPos = getAddressConverter().getMaxAddress();
+ for( ApiCellRangeList::const_iterator aIt = aTitleRanges.begin(), aEnd = aTitleRanges.end(); (aIt != aEnd) && (!bHasRowTitles || !bHasColTitles); ++aIt )
{
- bool bHasRowTitles = false;
- bool bHasColTitles = false;
- const CellAddress& rMaxPos = getAddressConverter().getMaxAddress();
- for( ApiCellRangeList::const_iterator aIt = aTitleRanges.begin(), aEnd = aTitleRanges.end(); (aIt != aEnd) && (!bHasRowTitles || !bHasColTitles); ++aIt )
+ bool bFullRow = (aIt->StartColumn == 0) && (aIt->EndColumn >= rMaxPos.Column);
+ bool bFullCol = (aIt->StartRow == 0) && (aIt->EndRow >= rMaxPos.Row);
+ if( !bHasRowTitles && bFullRow && !bFullCol )
{
- bool bFullRow = (aIt->StartColumn == 0) && (aIt->EndColumn >= rMaxPos.Column);
- bool bFullCol = (aIt->StartRow == 0) && (aIt->EndRow >= rMaxPos.Row);
- if( !bHasRowTitles && bFullRow && !bFullCol )
- {
- xPrintAreas->setTitleRows( *aIt );
- xPrintAreas->setPrintTitleRows( sal_True );
- bHasRowTitles = true;
- }
- else if( !bHasColTitles && bFullCol && !bFullRow )
- {
- xPrintAreas->setTitleColumns( *aIt );
- xPrintAreas->setPrintTitleColumns( sal_True );
- bHasColTitles = true;
- }
+ xPrintAreas->setTitleRows( *aIt );
+ xPrintAreas->setPrintTitleRows( sal_True );
+ bHasRowTitles = true;
+ }
+ else if( !bHasColTitles && bFullCol && !bFullRow )
+ {
+ xPrintAreas->setTitleColumns( *aIt );
+ xPrintAreas->setPrintTitleColumns( sal_True );
+ bHasColTitles = true;
}
}
}
- break;
}
+ break;
}
}
@@ -594,26 +604,6 @@ bool DefinedName::getAbsoluteRange( CellRangeAddress& orRange ) const
return xTokens.is() && getFormulaParser().extractCellRange( orRange, xTokens->getTokens(), false );
}
-void DefinedName::implImportOoxFormula( FormulaContext& rContext )
-{
- if( mxFormula.get() )
- {
- SequenceInputStream aStrm( *mxFormula );
- importBiff12Formula( rContext, mnCalcSheet, aStrm );
- }
- else
- importOoxFormula( rContext, mnCalcSheet );
-}
-
-void DefinedName::implImportBiffFormula( FormulaContext& rContext )
-{
- OSL_ENSURE( mxBiffStrm.get(), "DefinedName::implImportBiffFormula - missing BIFF stream" );
- BiffInputStream& rStrm = mxBiffStrm->getStream();
- BiffInputStreamPosGuard aStrmGuard( rStrm );
- if( mxBiffStrm->restorePosition() )
- importBiffFormula( rContext, mnCalcSheet, rStrm, &mnFmlaSize );
-}
-
// ============================================================================
DefinedNamesBuffer::DefinedNamesBuffer( const WorkbookHelper& rHelper ) :
diff --git a/oox/source/xls/drawingbase.cxx b/oox/source/xls/drawingbase.cxx
new file mode 100755
index 000000000000..a8629d3c0a54
--- /dev/null
+++ b/oox/source/xls/drawingbase.cxx
@@ -0,0 +1,325 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "oox/xls/drawingbase.hxx"
+
+#include <com/sun/star/awt/Rectangle.hpp>
+#include "oox/helper/attributelist.hxx"
+#include "oox/helper/binaryinputstream.hxx"
+#include "oox/xls/unitconverter.hxx"
+
+namespace oox {
+namespace xls {
+
+// ============================================================================
+
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::table;
+using namespace ::oox::drawingml;
+
+using ::rtl::OUString;
+
+// ============================================================================
+
+namespace {
+
+/** Converts the passed 32-bit integer value from 1/100 mm to EMUs. */
+inline sal_Int64 lclHmmToEmu( sal_Int32 nValue )
+{
+ return (nValue < 0) ? -1 : convertHmmToEmu( nValue );
+}
+
+/** Converts the passed 64-bit integer value from EMUs to 1/100 mm. */
+inline sal_Int32 lclEmuToHmm( sal_Int64 nValue )
+{
+ return (nValue < 0) ? -1 : convertEmuToHmm( nValue );
+}
+
+/** Reads the cell anchor model from a BIFF or DFF stream. */
+BinaryInputStream& operator>>( BinaryInputStream& rStrm, CellAnchorModel& rModel )
+{
+ // all members are given as 16-bit unsigned values
+ rModel.mnCol = rStrm.readuInt16();
+ rModel.mnColOffset = rStrm.readuInt16();
+ rModel.mnRow = rStrm.readuInt16();
+ rModel.mnRowOffset = rStrm.readuInt16();
+ return rStrm;
+}
+
+} // namespace
+
+// ============================================================================
+
+CellAnchorModel::CellAnchorModel() :
+ mnCol( -1 ),
+ mnRow( -1 ),
+ mnColOffset( 0 ),
+ mnRowOffset( 0 )
+{
+}
+
+// ----------------------------------------------------------------------------
+
+AnchorClientDataModel::AnchorClientDataModel() :
+ mbLocksWithSheet( true ),
+ mbPrintsWithSheet( true )
+{
+}
+
+// ============================================================================
+
+ShapeAnchor::ShapeAnchor( const WorksheetHelper& rHelper ) :
+ WorksheetHelper( rHelper ),
+ meAnchorType( ANCHOR_INVALID ),
+ meCellAnchorType( CELLANCHOR_EMU ),
+ mnEditAs( XML_twoCell )
+{
+}
+
+void ShapeAnchor::importAnchor( sal_Int32 nElement, const AttributeList& rAttribs )
+{
+ switch( nElement )
+ {
+ case XDR_TOKEN( absoluteAnchor ):
+ meAnchorType = ANCHOR_ABSOLUTE;
+ break;
+ case XDR_TOKEN( oneCellAnchor ):
+ meAnchorType = ANCHOR_ONECELL;
+ break;
+ case XDR_TOKEN( twoCellAnchor ):
+ meAnchorType = ANCHOR_TWOCELL;
+ mnEditAs = rAttribs.getToken( XML_editAs, XML_twoCell );
+ break;
+ default:
+ OSL_ENSURE( false, "ShapeAnchor::importAnchor - unexpected element" );
+ }
+ meCellAnchorType = CELLANCHOR_EMU;
+}
+
+void ShapeAnchor::importPos( const AttributeList& rAttribs )
+{
+ OSL_ENSURE( meAnchorType == ANCHOR_ABSOLUTE, "ShapeAnchor::importPos - unexpected 'xdr:pos' element" );
+ maPos.X = rAttribs.getHyper( XML_x, 0 );
+ maPos.Y = rAttribs.getHyper( XML_y, 0 );
+}
+
+void ShapeAnchor::importExt( const AttributeList& rAttribs )
+{
+ OSL_ENSURE( (meAnchorType == ANCHOR_ABSOLUTE) || (meAnchorType == ANCHOR_ONECELL), "ShapeAnchor::importExt - unexpected 'xdr:ext' element" );
+ maSize.Width = rAttribs.getHyper( XML_cx, 0 );
+ maSize.Height = rAttribs.getHyper( XML_cy, 0 );
+}
+
+void ShapeAnchor::importClientData( const AttributeList& rAttribs )
+{
+ maClientData.mbLocksWithSheet = rAttribs.getBool( XML_fLocksWithSheet, true );
+ maClientData.mbPrintsWithSheet = rAttribs.getBool( XML_fPrintsWithSheet, true );
+}
+
+void ShapeAnchor::setCellPos( sal_Int32 nElement, sal_Int32 nParentContext, const OUString& rValue )
+{
+ CellAnchorModel* pCellAnchor = 0;
+ switch( nParentContext )
+ {
+ case XDR_TOKEN( from ):
+ OSL_ENSURE( (meAnchorType == ANCHOR_ONECELL) || (meAnchorType == ANCHOR_TWOCELL), "ShapeAnchor::setCellPos - unexpected 'xdr:from' element" );
+ pCellAnchor = &maFrom;
+ break;
+ case XDR_TOKEN( to ):
+ OSL_ENSURE( meAnchorType == ANCHOR_TWOCELL, "ShapeAnchor::setCellPos - unexpected 'xdr:to' element" );
+ pCellAnchor = &maTo;
+ break;
+ default:
+ OSL_ENSURE( false, "ShapeAnchor::setCellPos - unexpected parent element" );
+ }
+ if( pCellAnchor ) switch( nElement )
+ {
+ case XDR_TOKEN( col ): pCellAnchor->mnCol = rValue.toInt32(); break;
+ case XDR_TOKEN( row ): pCellAnchor->mnRow = rValue.toInt32(); break;
+ case XDR_TOKEN( colOff ): pCellAnchor->mnColOffset = rValue.toInt64(); break;
+ case XDR_TOKEN( rowOff ): pCellAnchor->mnRowOffset = rValue.toInt64(); break;
+ default: OSL_ENSURE( false, "ShapeAnchor::setCellPos - unexpected element" );
+ }
+}
+
+void ShapeAnchor::importVmlAnchor( const OUString& rAnchor )
+{
+ meAnchorType = ANCHOR_VML;
+
+ ::std::vector< OUString > aTokens;
+ sal_Int32 nIndex = 0;
+ while( nIndex >= 0 )
+ aTokens.push_back( rAnchor.getToken( 0, ',', nIndex ).trim() );
+
+ OSL_ENSURE( aTokens.size() >= 8, "ShapeAnchor::importVmlAnchor - missing anchor tokens" );
+ if( aTokens.size() >= 8 )
+ {
+ maFrom.mnCol = aTokens[ 0 ].toInt32();
+ maFrom.mnColOffset = aTokens[ 1 ].toInt32();
+ maFrom.mnRow = aTokens[ 2 ].toInt32();
+ maFrom.mnRowOffset = aTokens[ 3 ].toInt32();
+ maTo.mnCol = aTokens[ 4 ].toInt32();
+ maTo.mnColOffset = aTokens[ 5 ].toInt32();
+ maTo.mnRow = aTokens[ 6 ].toInt32();
+ maTo.mnRowOffset = aTokens[ 7 ].toInt32();
+ }
+}
+
+void ShapeAnchor::importBiffAnchor( BinaryInputStream& rStrm )
+{
+ meAnchorType = ANCHOR_TWOCELL; /// BIFF/DFF use two-cell anchors only
+ meCellAnchorType = CELLANCHOR_COLROW; /// BIFF/DFF use fraction of column/row for offset values
+ rStrm >> maFrom >> maTo;
+}
+
+EmuRectangle ShapeAnchor::calcAnchorRectEmu( const Size& rPageSizeHmm ) const
+{
+ AddressConverter& rAddrConv = getAddressConverter();
+ EmuSize aPageSize( lclHmmToEmu( rPageSizeHmm.Width ), lclHmmToEmu( rPageSizeHmm.Height ) );
+ EmuRectangle aAnchorRect( -1, -1, -1, -1 );
+
+ // calculate shape position
+ switch( meAnchorType )
+ {
+ case ANCHOR_ABSOLUTE:
+ OSL_ENSURE( maPos.isValid(), "ShapeAnchor::calcAnchorRectEmu - invalid position" );
+ if( maPos.isValid() && (maPos.X < aPageSize.Width) && (maPos.Y < aPageSize.Height) )
+ aAnchorRect.setPos( maPos );
+ break;
+ case ANCHOR_ONECELL:
+ case ANCHOR_TWOCELL:
+ case ANCHOR_VML:
+ OSL_ENSURE( maFrom.isValid(), "ShapeAnchor::calcAnchorRectEmu - invalid position" );
+ if( maFrom.isValid() && rAddrConv.checkCol( maFrom.mnCol, true ) && rAddrConv.checkRow( maFrom.mnRow, true ) )
+ {
+ EmuPoint aPoint = calcCellAnchorEmu( maFrom );
+ if( (aPoint.X < aPageSize.Width) && (aPoint.Y < aPageSize.Height) )
+ aAnchorRect.setPos( aPoint );
+ }
+ break;
+ case ANCHOR_INVALID:
+ OSL_ENSURE( false, "ShapeAnchor::calcAnchorRectEmu - invalid anchor" );
+ break;
+ }
+
+ // calculate shape size
+ if( (aAnchorRect.X >= 0) && (aAnchorRect.Y >= 0) ) switch( meAnchorType )
+ {
+ case ANCHOR_ABSOLUTE:
+ case ANCHOR_ONECELL:
+ OSL_ENSURE( maSize.isValid(), "ShapeAnchor::calcAnchorRectEmu - invalid size" );
+ if( maSize.isValid() )
+ {
+ aAnchorRect.Width = ::std::min< sal_Int64 >( maSize.Width, aPageSize.Width - aAnchorRect.X );
+ aAnchorRect.Height = ::std::min< sal_Int64 >( maSize.Height, aPageSize.Height - aAnchorRect.Y );
+ }
+ break;
+ case ANCHOR_TWOCELL:
+ case ANCHOR_VML:
+ OSL_ENSURE( maTo.isValid(), "ShapeAnchor::calcAnchorRectEmu - invalid position" );
+ if( maTo.isValid() )
+ {
+ /* Pass a valid cell address to calcCellAnchorEmu(), otherwise
+ nothing useful is returned, even if either row or column is valid. */
+ CellAddress aToCell = rAddrConv.createValidCellAddress( BinAddress( maTo.mnCol, maTo.mnRow ), getSheetIndex(), true );
+ CellAnchorModel aValidTo = maTo;
+ aValidTo.mnCol = aToCell.Column;
+ aValidTo.mnRow = aToCell.Row;
+ EmuPoint aPoint = calcCellAnchorEmu( aValidTo );
+ // width (if column index is valid, use the calculated offset, otherwise stretch to maximum available X position)
+ aAnchorRect.Width = aPageSize.Width - aAnchorRect.X;
+ if( aToCell.Column == maTo.mnCol )
+ aAnchorRect.Width = ::std::min< sal_Int64 >( aPoint.X - aAnchorRect.X + 1, aAnchorRect.Width );
+ // height (if row index is valid, use the calculated offset, otherwise stretch to maximum available Y position)
+ aAnchorRect.Height = aPageSize.Height - aAnchorRect.Y;
+ if( aToCell.Row == maTo.mnRow )
+ aAnchorRect.Height = ::std::min< sal_Int64 >( aPoint.Y - aAnchorRect.Y + 1, aAnchorRect.Height );
+ }
+ break;
+ case ANCHOR_INVALID:
+ break;
+ }
+
+ // add 0.75 mm (27,000 EMUs) in X direction to correct display error
+ if( aAnchorRect.X >= 0 )
+ aAnchorRect.X += 27000;
+ // remove 0.25 mm (9,000 EMUs) in Y direction to correct display error
+ if( aAnchorRect.Y >= 9000 )
+ aAnchorRect.Y -= 9000;
+
+ return aAnchorRect;
+}
+
+Rectangle ShapeAnchor::calcAnchorRectHmm( const Size& rPageSizeHmm ) const
+{
+ EmuRectangle aAnchorRect = calcAnchorRectEmu( rPageSizeHmm );
+ return Rectangle( lclEmuToHmm( aAnchorRect.X ), lclEmuToHmm( aAnchorRect.Y ), lclEmuToHmm( aAnchorRect.Width ), lclEmuToHmm( aAnchorRect.Height ) );
+}
+
+// private --------------------------------------------------------------------
+
+EmuPoint ShapeAnchor::calcCellAnchorEmu( const CellAnchorModel& rModel ) const
+{
+ // calculate position of top-left edge of the cell
+ Point aPoint = getCellPosition( rModel.mnCol, rModel.mnRow );
+ EmuPoint aEmuPoint( lclHmmToEmu( aPoint.X ), lclHmmToEmu( aPoint.Y ) );
+
+ // add the offset inside the cell
+ switch( meCellAnchorType )
+ {
+ case CELLANCHOR_EMU:
+ aEmuPoint.X += rModel.mnColOffset;
+ aEmuPoint.Y += rModel.mnRowOffset;
+ break;
+
+ case CELLANCHOR_PIXEL:
+ {
+ const UnitConverter& rUnitConv = getUnitConverter();
+ aEmuPoint.X += static_cast< sal_Int64 >( rUnitConv.scaleValue( static_cast< double >( rModel.mnColOffset ), UNIT_SCREENX, UNIT_EMU ) );
+ aEmuPoint.Y += static_cast< sal_Int64 >( rUnitConv.scaleValue( static_cast< double >( rModel.mnRowOffset ), UNIT_SCREENY, UNIT_EMU ) );
+ }
+ break;
+
+ case CELLANCHOR_COLROW:
+ {
+ Size aCellSize = getCellSize( rModel.mnCol, rModel.mnRow );
+ EmuSize aEmuSize( lclHmmToEmu( aCellSize.Width ), lclHmmToEmu( aCellSize.Height ) );
+ // X offset is given in 1/1024 of column width
+ aEmuPoint.X += static_cast< sal_Int64 >( aEmuSize.Width * getLimitedValue< double >( static_cast< double >( rModel.mnColOffset ) / 1024.0, 0.0, 1.0 ) + 0.5 );
+ // Y offset is given in 1/256 of row height
+ aEmuPoint.Y += static_cast< sal_Int64 >( aEmuSize.Height * getLimitedValue< double >( static_cast< double >( rModel.mnRowOffset ) / 256.0, 0.0, 1.0 ) + 0.5 );
+ }
+ break;
+ }
+
+ return aEmuPoint;
+}
+
+// ============================================================================
+
+} // namespace xls
+} // namespace oox
diff --git a/oox/source/xls/drawingfragment.cxx b/oox/source/xls/drawingfragment.cxx
index ba3bd444bbeb..248677573421 100644
--- a/oox/source/xls/drawingfragment.cxx
+++ b/oox/source/xls/drawingfragment.cxx
@@ -88,329 +88,6 @@ sal_Int64 lclCalcEmu( const UnitConverter& rUnitConv, sal_Int64 nValue, Unit eFr
// ============================================================================
-AnchorCellModel::AnchorCellModel() :
- mnCol( -1 ),
- mnRow( -1 ),
- mnColOffset( 0 ),
- mnRowOffset( 0 )
-{
-}
-
-// ----------------------------------------------------------------------------
-
-AnchorClientDataModel::AnchorClientDataModel() :
- mbLocksWithSheet( true ),
- mbPrintsWithSheet( true )
-{
-}
-
-// ============================================================================
-
-ShapeAnchor::ShapeAnchor( const WorksheetHelper& rHelper ) :
- WorksheetHelper( rHelper ),
- meType( ANCHOR_INVALID ),
- mnEditAs( XML_twoCell )
-{
-}
-
-void ShapeAnchor::importAnchor( sal_Int32 nElement, const AttributeList& rAttribs )
-{
- switch( nElement )
- {
- case XDR_TOKEN( absoluteAnchor ):
- meType = ANCHOR_ABSOLUTE;
- break;
- case XDR_TOKEN( oneCellAnchor ):
- meType = ANCHOR_ONECELL;
- break;
- case XDR_TOKEN( twoCellAnchor ):
- meType = ANCHOR_TWOCELL;
- mnEditAs = rAttribs.getToken( XML_editAs, XML_twoCell );
- break;
- default:
- OSL_FAIL( "ShapeAnchor::importAnchor - unexpected element" );
- }
-}
-
-void ShapeAnchor::importPos( const AttributeList& rAttribs )
-{
- OSL_ENSURE( meType == ANCHOR_ABSOLUTE, "ShapeAnchor::importPos - unexpected 'xdr:pos' element" );
- maPos.X = rAttribs.getHyper( XML_x, 0 );
- maPos.Y = rAttribs.getHyper( XML_y, 0 );
-}
-
-void ShapeAnchor::importExt( const AttributeList& rAttribs )
-{
- OSL_ENSURE( (meType == ANCHOR_ABSOLUTE) || (meType == ANCHOR_ONECELL), "ShapeAnchor::importExt - unexpected 'xdr:ext' element" );
- maSize.Width = rAttribs.getHyper( XML_cx, 0 );
- maSize.Height = rAttribs.getHyper( XML_cy, 0 );
-}
-
-void ShapeAnchor::importClientData( const AttributeList& rAttribs )
-{
- maClientData.mbLocksWithSheet = rAttribs.getBool( XML_fLocksWithSheet, true );
- maClientData.mbPrintsWithSheet = rAttribs.getBool( XML_fPrintsWithSheet, true );
-}
-
-void ShapeAnchor::setCellPos( sal_Int32 nElement, sal_Int32 nParentContext, const OUString& rValue )
-{
- AnchorCellModel* pAnchorCell = 0;
- switch( nParentContext )
- {
- case XDR_TOKEN( from ):
- OSL_ENSURE( (meType == ANCHOR_ONECELL) || (meType == ANCHOR_TWOCELL), "ShapeAnchor::setCellPos - unexpected 'xdr:from' element" );
- pAnchorCell = &maFrom;
- break;
- case XDR_TOKEN( to ):
- OSL_ENSURE( meType == ANCHOR_TWOCELL, "ShapeAnchor::setCellPos - unexpected 'xdr:to' element" );
- pAnchorCell = &maTo;
- break;
- default:
- OSL_FAIL( "ShapeAnchor::setCellPos - unexpected parent element" );
- }
- if( pAnchorCell ) switch( nElement )
- {
- case XDR_TOKEN( col ): pAnchorCell->mnCol = rValue.toInt32(); break;
- case XDR_TOKEN( row ): pAnchorCell->mnRow = rValue.toInt32(); break;
- case XDR_TOKEN( colOff ): pAnchorCell->mnColOffset = rValue.toInt64(); break;
- case XDR_TOKEN( rowOff ): pAnchorCell->mnRowOffset = rValue.toInt64(); break;
- default: OSL_FAIL( "ShapeAnchor::setCellPos - unexpected element" );
- }
-}
-
-void ShapeAnchor::importVmlAnchor( const OUString& rAnchor )
-{
- meType = ANCHOR_VML;
-
- ::std::vector< OUString > aTokens;
- sal_Int32 nIndex = 0;
- while( nIndex >= 0 )
- aTokens.push_back( rAnchor.getToken( 0, ',', nIndex ).trim() );
-
- OSL_ENSURE( aTokens.size() >= 8, "ShapeAnchor::importVmlAnchor - missing anchor tokens" );
- if( aTokens.size() >= 8 )
- {
- maFrom.mnCol = aTokens[ 0 ].toInt32();
- maFrom.mnColOffset = aTokens[ 1 ].toInt32();
- maFrom.mnRow = aTokens[ 2 ].toInt32();
- maFrom.mnRowOffset = aTokens[ 3 ].toInt32();
- maTo.mnCol = aTokens[ 4 ].toInt32();
- maTo.mnColOffset = aTokens[ 5 ].toInt32();
- maTo.mnRow = aTokens[ 6 ].toInt32();
- maTo.mnRowOffset = aTokens[ 7 ].toInt32();
- }
-}
-
-bool ShapeAnchor::isValidAnchor() const
-{
- bool bValid = false;
- switch( meType )
- {
- case ANCHOR_ABSOLUTE:
- OSL_ENSURE( maPos.isValid(), "ShapeAnchor::isValidAnchor - invalid position" );
- OSL_ENSURE( maSize.isValid(), "ShapeAnchor::isValidAnchor - invalid size" );
- bValid = maPos.isValid() && maSize.isValid() && (maSize.Width > 0) && (maSize.Height > 0);
- break;
- case ANCHOR_ONECELL:
- OSL_ENSURE( maFrom.isValid(), "ShapeAnchor::isValidAnchor - invalid from position" );
- OSL_ENSURE( maSize.isValid(), "ShapeAnchor::isValidAnchor - invalid size" );
- bValid = maFrom.isValid() && maSize.isValid() && (maSize.Width > 0) && (maSize.Height > 0);
- break;
- case ANCHOR_TWOCELL:
- case ANCHOR_VML:
- OSL_ENSURE( maFrom.isValid(), "ShapeAnchor::isValidAnchor - invalid from position" );
- OSL_ENSURE( maTo.isValid(), "ShapeAnchor::isValidAnchor - invalid to position" );
- bValid = maFrom.isValid() && maTo.isValid() &&
- ((maFrom.mnCol < maTo.mnCol) || ((maFrom.mnCol == maTo.mnCol) && (maFrom.mnColOffset < maTo.mnColOffset))) &&
- ((maFrom.mnRow < maTo.mnRow) || ((maFrom.mnRow == maTo.mnRow) && (maFrom.mnRowOffset < maTo.mnRowOffset)));
- break;
- case ANCHOR_INVALID:
- OSL_FAIL( "ShapeAnchor::isValidAnchor - invalid anchor" );
- break;
- }
- return bValid;
-}
-
-Rectangle ShapeAnchor::calcApiLocation( const Size& rApiSheetSize, const AnchorSizeModel& rEmuSheetSize ) const
-{
- AddressConverter& rAddrConv = getAddressConverter();
- UnitConverter& rUnitConv = getUnitConverter();
- Rectangle aApiLoc( -1, -1, -1, -1 );
- Unit eUnitX = (meType == ANCHOR_VML) ? UNIT_SCREENX : UNIT_EMU;
- Unit eUnitY = (meType == ANCHOR_VML) ? UNIT_SCREENY : UNIT_EMU;
-
- // calculate shape position
- switch( meType )
- {
- case ANCHOR_ABSOLUTE:
- OSL_ENSURE( maPos.isValid(), "ShapeAnchor::calcApiLocation - invalid position" );
- if( maPos.isValid() && (maPos.X < rEmuSheetSize.Width) && (maPos.Y < rEmuSheetSize.Height) )
- {
- aApiLoc.X = rUnitConv.scaleToMm100( static_cast< double >( maPos.X ), UNIT_EMU );
- aApiLoc.Y = rUnitConv.scaleToMm100( static_cast< double >( maPos.Y ), UNIT_EMU );
- }
- break;
- case ANCHOR_ONECELL:
- case ANCHOR_TWOCELL:
- case ANCHOR_VML:
- OSL_ENSURE( maFrom.isValid(), "ShapeAnchor::calcApiLocation - invalid position" );
- if( maFrom.isValid() && rAddrConv.checkCol( maFrom.mnCol, true ) && rAddrConv.checkRow( maFrom.mnRow, true ) )
- {
- Point aPoint = getCellPosition( maFrom.mnCol, maFrom.mnRow );
- aApiLoc.X = aPoint.X + rUnitConv.scaleToMm100( static_cast< double >( maFrom.mnColOffset ), eUnitX );
- aApiLoc.Y = aPoint.Y + rUnitConv.scaleToMm100( static_cast< double >( maFrom.mnRowOffset ), eUnitY );
- }
- break;
- case ANCHOR_INVALID:
- OSL_FAIL( "ShapeAnchor::calcApiLocation - invalid anchor" );
- break;
- }
-
- // calculate shape size
- if( (aApiLoc.X >= 0) && (aApiLoc.Y >= 0) ) switch( meType )
- {
- case ANCHOR_ABSOLUTE:
- case ANCHOR_ONECELL:
- OSL_ENSURE( maSize.isValid(), "ShapeAnchor::calcApiLocation - invalid size" );
- if( maSize.isValid() )
- {
- aApiLoc.Width = ::std::min< sal_Int32 >(
- rUnitConv.scaleToMm100( static_cast< double >( maSize.Width ), UNIT_EMU ),
- rApiSheetSize.Width - aApiLoc.X );
- aApiLoc.Height = ::std::min< sal_Int32 >(
- rUnitConv.scaleToMm100( static_cast< double >( maSize.Height ), UNIT_EMU ),
- rApiSheetSize.Height - aApiLoc.Y );
- }
- break;
- case ANCHOR_TWOCELL:
- case ANCHOR_VML:
- OSL_ENSURE( maTo.isValid(), "ShapeAnchor::calcApiLocation - invalid position" );
- if( maTo.isValid() )
- {
- /* Pass a valid cell address to getCellPosition(), otherwise
- nothing is returned, even if either row or column is valid. */
- CellAddress aToCell = rAddrConv.createValidCellAddress( BinAddress( maTo.mnCol, maTo.mnRow ), getSheetIndex(), true );
- Point aPoint = getCellPosition( aToCell.Column, aToCell.Row );
- // width
- aApiLoc.Width = rApiSheetSize.Width - aApiLoc.X;
- if( aToCell.Column == maTo.mnCol )
- {
- aPoint.X += rUnitConv.scaleToMm100( static_cast< double >( maTo.mnColOffset ), eUnitX );
- aApiLoc.Width = ::std::min< sal_Int32 >( aPoint.X - aApiLoc.X + 1, aApiLoc.Width );
- }
- // height
- aApiLoc.Height = rApiSheetSize.Height - aApiLoc.Y;
- if( aToCell.Row == maTo.mnRow )
- {
- aPoint.Y += rUnitConv.scaleToMm100( static_cast< double >( maTo.mnRowOffset ), eUnitY );
- aApiLoc.Height = ::std::min< sal_Int32 >( aPoint.Y - aApiLoc.Y + 1, aApiLoc.Height );
- }
- }
- break;
- case ANCHOR_INVALID:
- break;
- }
-
- return aApiLoc;
-}
-
-Rectangle ShapeAnchor::calcEmuLocation( const AnchorSizeModel& rEmuSheetSize ) const
-{
- AddressConverter& rAddrConv = getAddressConverter();
- UnitConverter& rUnitConv = getUnitConverter();
-
- Size aSheetSize(
- getLimitedValue< sal_Int32, sal_Int64 >( rEmuSheetSize.Width, 0, SAL_MAX_INT32 ),
- getLimitedValue< sal_Int32, sal_Int64 >( rEmuSheetSize.Height, 0, SAL_MAX_INT32 ) );
- Rectangle aLoc( -1, -1, -1, -1 );
- Unit eUnitX = (meType == ANCHOR_VML) ? UNIT_SCREENX : UNIT_EMU;
- Unit eUnitY = (meType == ANCHOR_VML) ? UNIT_SCREENY : UNIT_EMU;
-
- // calculate shape position
- switch( meType )
- {
- case ANCHOR_ABSOLUTE:
- OSL_ENSURE( maPos.isValid(), "ShapeAnchor::calcEmuLocation - invalid position" );
- if( maPos.isValid() && (maPos.X < aSheetSize.Width) && (maPos.Y < aSheetSize.Height) )
- {
- aLoc.X = static_cast< sal_Int32 >( maPos.X );
- aLoc.Y = static_cast< sal_Int32 >( maPos.Y );
- }
- break;
- case ANCHOR_ONECELL:
- case ANCHOR_TWOCELL:
- case ANCHOR_VML:
- OSL_ENSURE( maFrom.isValid(), "ShapeAnchor::calcEmuLocation - invalid position" );
- if( maFrom.isValid() && rAddrConv.checkCol( maFrom.mnCol, true ) && rAddrConv.checkRow( maFrom.mnRow, true ) )
- {
- Point aPoint = getCellPosition( maFrom.mnCol, maFrom.mnRow );
- sal_Int64 nX = static_cast< sal_Int64 >( rUnitConv.scaleFromMm100( aPoint.X, UNIT_EMU ) ) + lclCalcEmu( rUnitConv, maFrom.mnColOffset, eUnitX );
- sal_Int64 nY = static_cast< sal_Int64 >( rUnitConv.scaleFromMm100( aPoint.Y, UNIT_EMU ) ) + lclCalcEmu( rUnitConv, maFrom.mnRowOffset, eUnitY );
- if( (nX < aSheetSize.Width) && (nY < aSheetSize.Height) )
- {
- aLoc.X = static_cast< sal_Int32 >( nX );
- aLoc.Y = static_cast< sal_Int32 >( nY );
- }
- }
- break;
- case ANCHOR_INVALID:
- OSL_FAIL( "ShapeAnchor::calcEmuLocation - invalid anchor" );
- break;
- }
-
- // calculate shape size
- if( (aLoc.X >= 0) && (aLoc.Y >= 0) ) switch( meType )
- {
- case ANCHOR_ABSOLUTE:
- case ANCHOR_ONECELL:
- OSL_ENSURE( maSize.isValid(), "ShapeAnchor::calcEmuLocation - invalid size" );
- if( maSize.isValid() )
- {
- aLoc.Width = static_cast< sal_Int32 >( ::std::min< sal_Int64 >( maSize.Width, aSheetSize.Width - aLoc.X ) );
- aLoc.Height = static_cast< sal_Int32 >( ::std::min< sal_Int64 >( maSize.Height, aSheetSize.Height - aLoc.Y ) );
- }
- break;
- case ANCHOR_TWOCELL:
- case ANCHOR_VML:
- OSL_ENSURE( maTo.isValid(), "ShapeAnchor::calcEmuLocation - invalid position" );
- if( maTo.isValid() )
- {
- /* Pass a valid cell address to getCellPosition(), otherwise
- nothing is returned, even if either row or column is valid. */
- CellAddress aToCell = rAddrConv.createValidCellAddress( BinAddress( maTo.mnCol, maTo.mnRow ), getSheetIndex(), true );
- Point aPoint = getCellPosition( aToCell.Column, aToCell.Row );
- sal_Int64 nX = static_cast< sal_Int64 >( rUnitConv.scaleFromMm100( aPoint.X, UNIT_EMU ) );
- sal_Int64 nY = static_cast< sal_Int64 >( rUnitConv.scaleFromMm100( aPoint.Y, UNIT_EMU ) );
- // width
- aLoc.Width = aSheetSize.Width - aLoc.X;
- if( aToCell.Column == maTo.mnCol )
- {
- nX += lclCalcEmu( rUnitConv, maTo.mnColOffset, eUnitX );
- aLoc.Width = static_cast< sal_Int32 >( ::std::min< sal_Int64 >( nX - aLoc.X + 1, aLoc.Width ) );
- }
- // height
- aLoc.Height = aSheetSize.Height - aLoc.Y;
- if( aToCell.Row == maTo.mnRow )
- {
- nY += lclCalcEmu( rUnitConv, maTo.mnRowOffset, eUnitY );
- aLoc.Height = static_cast< sal_Int32 >( ::std::min< sal_Int64 >( nY - aLoc.Y + 1, aLoc.Height ) );
- }
- }
- break;
- case ANCHOR_INVALID:
- break;
- }
-
- // add 0.75 mm (27,000 EMUs) in X direction to correct display error
- if( aLoc.X >= 0 )
- aLoc.X += 27000;
- // remove 0.25 mm (9,000 EMUs) in Y direction to correct display error
- if( aLoc.Y >= 9000 )
- aLoc.Y -= 9000;
-
- return aLoc;
-}
-
// ============================================================================
ShapeMacroAttacher::ShapeMacroAttacher( const OUString& rMacroName, const Reference< XShape >& rxShape ) :
@@ -521,9 +198,6 @@ DrawingFragment::DrawingFragment( const WorksheetHelper& rHelper, const OUString
mxDrawPage( rHelper.getDrawPage(), UNO_QUERY )
{
OSL_ENSURE( mxDrawPage.is(), "DrawingFragment::DrawingFragment - missing drawing page" );
- maApiSheetSize = getDrawPageSize();
- maEmuSheetSize.Width = static_cast< sal_Int64 >( getUnitConverter().scaleFromMm100( maApiSheetSize.Width, UNIT_EMU ) );
- maEmuSheetSize.Height = static_cast< sal_Int64 >( getUnitConverter().scaleFromMm100( maApiSheetSize.Height, UNIT_EMU ) );
}
ContextHandlerRef DrawingFragment::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
@@ -598,22 +272,22 @@ void DrawingFragment::onEndElement()
case XDR_TOKEN( absoluteAnchor ):
case XDR_TOKEN( oneCellAnchor ):
case XDR_TOKEN( twoCellAnchor ):
- if( mxDrawPage.is() && mxShape.get() && mxAnchor.get() && mxAnchor->isValidAnchor() )
+ if( mxDrawPage.is() && mxShape.get() && mxAnchor.get() )
{
- Rectangle aShapeRect = mxAnchor->calcEmuLocation( maEmuSheetSize );
- if( (aShapeRect.X >= 0) && (aShapeRect.Y >= 0) && (aShapeRect.Width >= 0) && (aShapeRect.Height >= 0) )
+ EmuRectangle aShapeRectEmu = mxAnchor->calcAnchorRectEmu( getDrawPageSize() );
+ if( (aShapeRectEmu.X >= 0) && (aShapeRectEmu.Y >= 0) && (aShapeRectEmu.Width >= 0) && (aShapeRectEmu.Height >= 0) )
{
+ // TODO: DrawingML implementation expects 32-bit coordinates for EMU rectangles (change that to EmuRectangle)
+ Rectangle aShapeRectEmu32(
+ getLimitedValue< sal_Int32, sal_Int64 >( aShapeRectEmu.X, 0, SAL_MAX_INT32 ),
+ getLimitedValue< sal_Int32, sal_Int64 >( aShapeRectEmu.Y, 0, SAL_MAX_INT32 ),
+ getLimitedValue< sal_Int32, sal_Int64 >( aShapeRectEmu.Width, 0, SAL_MAX_INT32 ),
+ getLimitedValue< sal_Int32, sal_Int64 >( aShapeRectEmu.Height, 0, SAL_MAX_INT32 ) );
basegfx::B2DHomMatrix aTransformation;
- mxShape->addShape( getOoxFilter(), &getTheme(), mxDrawPage, aTransformation, &aShapeRect );
- /* Collect all shape positions in the WorksheetHelper base
- class. But first, scale EMUs to 1/100 mm. */
- const UnitConverter& rUnitConv = getUnitConverter();
- Rectangle aShapeRectHmm(
- rUnitConv.scaleToMm100( aShapeRect.X, UNIT_EMU ),
- rUnitConv.scaleToMm100( aShapeRect.Y, UNIT_EMU ),
- rUnitConv.scaleToMm100( aShapeRect.Width, UNIT_EMU ),
- rUnitConv.scaleToMm100( aShapeRect.Height, UNIT_EMU ) );
- extendShapeBoundingBox( aShapeRectHmm );
+ mxShape->addShape( getOoxFilter(), &getTheme(), mxDrawPage, aTransformation, &aShapeRectEmu32 );
+
+ // collect all shape positions in the WorksheetHelper base class
+ extendShapeBoundingBox( aShapeRectEmu32 );
}
}
mxShape.reset();
@@ -774,7 +448,7 @@ bool VmlDrawing::convertClientAnchor( Rectangle& orShapeRect, const OUString& rS
return false;
ShapeAnchor aAnchor( *this );
aAnchor.importVmlAnchor( rShapeAnchor );
- orShapeRect = aAnchor.calcApiLocation( getDrawPageSize(), AnchorSizeModel() );
+ orShapeRect = aAnchor.calcAnchorRectHmm( getDrawPageSize() );
return (orShapeRect.Width >= 0) && (orShapeRect.Height >= 0);
}
diff --git a/oox/source/xls/drawingmanager.cxx b/oox/source/xls/drawingmanager.cxx
new file mode 100755
index 000000000000..efba6824c8ac
--- /dev/null
+++ b/oox/source/xls/drawingmanager.cxx
@@ -0,0 +1,1414 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "oox/xls/drawingmanager.hxx"
+
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <com/sun/star/drawing/CircleKind.hpp>
+#include <com/sun/star/drawing/PointSequenceSequence.hpp>
+#include <com/sun/star/drawing/PolygonKind.hpp>
+#include <com/sun/star/drawing/XShapes.hpp>
+#include "oox/core/filterbase.hxx"
+#include "oox/drawingml/fillproperties.hxx"
+#include "oox/drawingml/lineproperties.hxx"
+#include "oox/drawingml/shapepropertymap.hxx"
+#include "oox/helper/containerhelper.hxx"
+#include "oox/token/tokens.hxx"
+#include "oox/xls/biffinputstream.hxx"
+#include "oox/xls/unitconverter.hxx"
+
+namespace oox {
+namespace xls {
+
+// ============================================================================
+
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::drawing;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+using namespace ::oox::drawingml;
+
+using ::rtl::OUString;
+
+// ============================================================================
+
+namespace {
+
+// OBJ record -----------------------------------------------------------------
+
+const sal_uInt16 BIFF_OBJTYPE_GROUP = 0;
+const sal_uInt16 BIFF_OBJTYPE_LINE = 1;
+const sal_uInt16 BIFF_OBJTYPE_RECTANGLE = 2;
+const sal_uInt16 BIFF_OBJTYPE_OVAL = 3;
+const sal_uInt16 BIFF_OBJTYPE_ARC = 4;
+const sal_uInt16 BIFF_OBJTYPE_CHART = 5;
+const sal_uInt16 BIFF_OBJTYPE_TEXT = 6;
+const sal_uInt16 BIFF_OBJTYPE_BUTTON = 7;
+const sal_uInt16 BIFF_OBJTYPE_PICTURE = 8;
+const sal_uInt16 BIFF_OBJTYPE_POLYGON = 9; // new in BIFF4
+const sal_uInt16 BIFF_OBJTYPE_CHECKBOX = 11; // new in BIFF5
+const sal_uInt16 BIFF_OBJTYPE_OPTIONBUTTON = 12;
+const sal_uInt16 BIFF_OBJTYPE_EDIT = 13;
+const sal_uInt16 BIFF_OBJTYPE_LABEL = 14;
+const sal_uInt16 BIFF_OBJTYPE_DIALOG = 15;
+const sal_uInt16 BIFF_OBJTYPE_SPIN = 16;
+const sal_uInt16 BIFF_OBJTYPE_SCROLLBAR = 17;
+const sal_uInt16 BIFF_OBJTYPE_LISTBOX = 18;
+const sal_uInt16 BIFF_OBJTYPE_GROUPBOX = 19;
+const sal_uInt16 BIFF_OBJTYPE_DROPDOWN = 20;
+const sal_uInt16 BIFF_OBJTYPE_NOTE = 25; // new in BIFF8
+const sal_uInt16 BIFF_OBJTYPE_DRAWING = 30;
+const sal_uInt16 BIFF_OBJTYPE_UNKNOWN = 0xFFFF; // for internal use only
+
+const sal_uInt16 BIFF_OBJ_HIDDEN = 0x0100;
+const sal_uInt16 BIFF_OBJ_VISIBLE = 0x0200;
+const sal_uInt16 BIFF_OBJ_PRINTABLE = 0x0400;
+
+// line formatting ------------------------------------------------------------
+
+const sal_uInt8 BIFF_OBJ_LINE_AUTOCOLOR = 64;
+
+const sal_uInt8 BIFF_OBJ_LINE_SOLID = 0;
+const sal_uInt8 BIFF_OBJ_LINE_DASH = 1;
+const sal_uInt8 BIFF_OBJ_LINE_DOT = 2;
+const sal_uInt8 BIFF_OBJ_LINE_DASHDOT = 3;
+const sal_uInt8 BIFF_OBJ_LINE_DASHDOTDOT = 4;
+const sal_uInt8 BIFF_OBJ_LINE_MEDTRANS = 5;
+const sal_uInt8 BIFF_OBJ_LINE_DARKTRANS = 6;
+const sal_uInt8 BIFF_OBJ_LINE_LIGHTTRANS = 7;
+const sal_uInt8 BIFF_OBJ_LINE_NONE = 255;
+
+const sal_uInt8 BIFF_OBJ_LINE_HAIR = 0;
+const sal_uInt8 BIFF_OBJ_LINE_THIN = 1;
+const sal_uInt8 BIFF_OBJ_LINE_MEDIUM = 2;
+const sal_uInt8 BIFF_OBJ_LINE_THICK = 3;
+
+const sal_uInt8 BIFF_OBJ_LINE_AUTO = 0x01;
+
+const sal_uInt8 BIFF_OBJ_ARROW_NONE = 0;
+const sal_uInt8 BIFF_OBJ_ARROW_OPEN = 1;
+const sal_uInt8 BIFF_OBJ_ARROW_FILLED = 2;
+const sal_uInt8 BIFF_OBJ_ARROW_OPENBOTH = 3;
+const sal_uInt8 BIFF_OBJ_ARROW_FILLEDBOTH = 4;
+
+const sal_uInt8 BIFF_OBJ_ARROW_NARROW = 0;
+const sal_uInt8 BIFF_OBJ_ARROW_MEDIUM = 1;
+const sal_uInt8 BIFF_OBJ_ARROW_WIDE = 2;
+
+const sal_uInt8 BIFF_OBJ_LINE_TL = 0;
+const sal_uInt8 BIFF_OBJ_LINE_TR = 1;
+const sal_uInt8 BIFF_OBJ_LINE_BR = 2;
+const sal_uInt8 BIFF_OBJ_LINE_BL = 3;
+
+const sal_uInt8 BIFF_OBJ_ARC_TR = 0;
+const sal_uInt8 BIFF_OBJ_ARC_TL = 1;
+const sal_uInt8 BIFF_OBJ_ARC_BL = 2;
+const sal_uInt8 BIFF_OBJ_ARC_BR = 3;
+
+const sal_uInt16 BIFF_OBJ_POLY_CLOSED = 0x0100;
+
+// fill formatting ------------------------------------------------------------
+
+const sal_uInt8 BIFF_OBJ_FILL_AUTOCOLOR = 65;
+
+const sal_uInt8 BIFF_OBJ_PATT_NONE = 0;
+const sal_uInt8 BIFF_OBJ_PATT_SOLID = 1;
+
+const sal_uInt8 BIFF_OBJ_FILL_AUTO = 0x01;
+
+// text formatting ------------------------------------------------------------
+
+const sal_uInt8 BIFF_OBJ_HOR_LEFT = 1;
+const sal_uInt8 BIFF_OBJ_HOR_CENTER = 2;
+const sal_uInt8 BIFF_OBJ_HOR_RIGHT = 3;
+const sal_uInt8 BIFF_OBJ_HOR_JUSTIFY = 4;
+
+const sal_uInt8 BIFF_OBJ_VER_TOP = 1;
+const sal_uInt8 BIFF_OBJ_VER_CENTER = 2;
+const sal_uInt8 BIFF_OBJ_VER_BOTTOM = 3;
+const sal_uInt8 BIFF_OBJ_VER_JUSTIFY = 4;
+
+const sal_uInt16 BIFF_OBJ_ORIENT_NONE = 0;
+const sal_uInt16 BIFF_OBJ_ORIENT_STACKED = 1; /// Stacked top to bottom.
+const sal_uInt16 BIFF_OBJ_ORIENT_90CCW = 2; /// 90 degr. counterclockwise.
+const sal_uInt16 BIFF_OBJ_ORIENT_90CW = 3; /// 90 degr. clockwise.
+
+const sal_uInt16 BIFF_OBJ_TEXT_AUTOSIZE = 0x0080;
+const sal_uInt16 BIFF_OBJ_TEXT_LOCKED = 0x0200;
+
+const sal_Int32 BIFF_OBJ_TEXT_MARGIN = 20000; /// Automatic text margin (EMUs).
+
+// BIFF8 OBJ sub records ------------------------------------------------------
+
+const sal_uInt16 BIFF_OBJCMO_PRINTABLE = 0x0010; /// Object printable.
+const sal_uInt16 BIFF_OBJCMO_AUTOLINE = 0x2000; /// Automatic line formatting.
+const sal_uInt16 BIFF_OBJCMO_AUTOFILL = 0x4000; /// Automatic fill formatting.
+
+// ----------------------------------------------------------------------------
+
+inline BiffInputStream& operator>>( BiffInputStream& rStrm, ShapeAnchor& rAnchor )
+{
+ rAnchor.importBiffAnchor( rStrm );
+ return rStrm;
+}
+
+} // namespace
+
+// ============================================================================
+// Model structures for BIFF OBJ record data
+// ============================================================================
+
+BiffObjLineModel::BiffObjLineModel() :
+ mnColorIdx( BIFF_OBJ_LINE_AUTOCOLOR ),
+ mnStyle( BIFF_OBJ_LINE_SOLID ),
+ mnWidth( BIFF_OBJ_LINE_HAIR ),
+ mbAuto( true )
+{
+}
+
+bool BiffObjLineModel::isVisible() const
+{
+ return mbAuto || (mnStyle != BIFF_OBJ_LINE_NONE);
+}
+
+BiffInputStream& operator>>( BiffInputStream& rStrm, BiffObjLineModel& rModel )
+{
+ sal_uInt8 nFlags;
+ rStrm >> rModel.mnColorIdx >> rModel.mnStyle >> rModel.mnWidth >> nFlags;
+ rModel.mbAuto = getFlag( nFlags, BIFF_OBJ_LINE_AUTO );
+ return rStrm;
+}
+
+// ============================================================================
+
+BiffObjFillModel::BiffObjFillModel() :
+ mnBackColorIdx( BIFF_OBJ_LINE_AUTOCOLOR ),
+ mnPattColorIdx( BIFF_OBJ_FILL_AUTOCOLOR ),
+ mnPattern( BIFF_OBJ_PATT_SOLID ),
+ mbAuto( true )
+{
+}
+
+bool BiffObjFillModel::isFilled() const
+{
+ return mbAuto || (mnPattern != BIFF_OBJ_PATT_NONE);
+}
+
+BiffInputStream& operator>>( BiffInputStream& rStrm, BiffObjFillModel& rModel )
+{
+ sal_uInt8 nFlags;
+ rStrm >> rModel.mnBackColorIdx >> rModel.mnPattColorIdx >> rModel.mnPattern >> nFlags;
+ rModel.mbAuto = getFlag( nFlags, BIFF_OBJ_FILL_AUTO );
+ return rStrm;
+}
+
+// ============================================================================
+
+BiffObjTextModel::BiffObjTextModel() :
+ mnTextLen( 0 ),
+ mnFormatSize( 0 ),
+ mnLinkSize( 0 ),
+ mnDefFontId( 0 ),
+ mnFlags( 0 ),
+ mnOrientation( BIFF_OBJ_ORIENT_NONE ),
+ mnButtonFlags( 0 ),
+ mnShortcut( 0 ),
+ mnShortcutEA( 0 )
+{
+}
+
+void BiffObjTextModel::readObj3( BiffInputStream& rStrm )
+{
+ rStrm >> mnTextLen;
+ rStrm.skip( 2 );
+ rStrm >> mnFormatSize >> mnDefFontId;
+ rStrm.skip( 2 );
+ rStrm >> mnFlags >> mnOrientation;
+ rStrm.skip( 8 );
+}
+
+void BiffObjTextModel::readObj5( BiffInputStream& rStrm )
+{
+ rStrm >> mnTextLen;
+ rStrm.skip( 2 );
+ rStrm >> mnFormatSize >> mnDefFontId;
+ rStrm.skip( 2 );
+ rStrm >> mnFlags >> mnOrientation;
+ rStrm.skip( 2 );
+ rStrm >> mnLinkSize;
+ rStrm.skip( 2 );
+ rStrm >> mnButtonFlags >> mnShortcut >> mnShortcutEA;
+}
+
+void BiffObjTextModel::readTxo8( BiffInputStream& rStrm )
+{
+ rStrm >> mnFlags >> mnOrientation >> mnButtonFlags >> mnShortcut >> mnShortcutEA >> mnTextLen >> mnFormatSize;
+}
+
+sal_uInt8 BiffObjTextModel::getHorAlign() const
+{
+ return extractValue< sal_uInt8 >( mnFlags, 1, 3 );
+}
+
+sal_uInt8 BiffObjTextModel::getVerAlign() const
+{
+ return extractValue< sal_uInt8 >( mnFlags, 4, 3 );
+}
+
+// ============================================================================
+// BIFF drawing objects
+// ============================================================================
+
+BiffDrawingObjectContainer::BiffDrawingObjectContainer()
+{
+}
+
+void BiffDrawingObjectContainer::append( const BiffDrawingObjectRef& rxDrawingObj )
+{
+ maObjects.push_back( rxDrawingObj );
+}
+
+void BiffDrawingObjectContainer::insertGrouped( const BiffDrawingObjectRef& rxDrawingObj )
+{
+ if( !maObjects.empty() )
+ if( BiffGroupObject* pGroupObj = dynamic_cast< BiffGroupObject* >( maObjects.back().get() ) )
+ if( pGroupObj->tryInsert( rxDrawingObj ) )
+ return;
+ maObjects.push_back( rxDrawingObj );
+}
+
+void BiffDrawingObjectContainer::convertAndInsert( BiffDrawingBase& rDrawing, const Reference< XShapes >& rxShapes, const Rectangle* pParentRect ) const
+{
+ maObjects.forEachMem( &BiffDrawingObjectBase::convertAndInsert, ::boost::ref( rDrawing ), ::boost::cref( rxShapes ), pParentRect );
+}
+
+// ============================================================================
+
+BiffDrawingObjectBase::BiffDrawingObjectBase( const WorksheetHelper& rHelper ) :
+ WorksheetHelper( rHelper ),
+ maAnchor( rHelper ),
+ mnDffShapeId( 0 ),
+ mnDffFlags( 0 ),
+ mnObjId( BIFF_OBJ_INVALID_ID ),
+ mnObjType( BIFF_OBJTYPE_UNKNOWN ),
+ mbHasAnchor( false ),
+ mbHidden( false ),
+ mbVisible( true ),
+ mbPrintable( true ),
+ mbAreaObj( false ),
+ mbAutoMargin( true ),
+ mbSimpleMacro( true ),
+ mbProcessShape( true ),
+ mbInsertShape( true ),
+ mbCustomDff( false )
+{
+}
+
+BiffDrawingObjectBase::~BiffDrawingObjectBase()
+{
+}
+
+/*static*/ BiffDrawingObjectRef BiffDrawingObjectBase::importObjBiff3( const WorksheetHelper& rHelper, BiffInputStream& rStrm )
+{
+ BiffDrawingObjectRef xDrawingObj;
+
+ if( rStrm.getRemaining() >= 30 )
+ {
+ sal_uInt16 nObjType;
+ rStrm.skip( 4 );
+ rStrm >> nObjType;
+ switch( nObjType )
+ {
+ case BIFF_OBJTYPE_GROUP: xDrawingObj.reset( new BiffGroupObject( rHelper ) ); break;
+ case BIFF_OBJTYPE_LINE: xDrawingObj.reset( new BiffLineObject( rHelper ) ); break;
+ case BIFF_OBJTYPE_RECTANGLE: xDrawingObj.reset( new BiffRectObject( rHelper ) ); break;
+ case BIFF_OBJTYPE_OVAL: xDrawingObj.reset( new BiffOvalObject( rHelper ) ); break;
+ case BIFF_OBJTYPE_ARC: xDrawingObj.reset( new BiffArcObject( rHelper ) ); break;
+#if 0
+ case BIFF_OBJTYPE_CHART: xDrawingObj.reset( new XclImpChartObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_TEXT: xDrawingObj.reset( new XclImpTextObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_BUTTON: xDrawingObj.reset( new XclImpButtonObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_PICTURE: xDrawingObj.reset( new XclImpPictureObj( rHelper ) ); break;
+#endif
+ default:
+#if 0
+ OSL_ENSURE( false, "BiffDrawingObjectBase::importObjBiff3 - unknown object type" );
+#endif
+ xDrawingObj.reset( new BiffPlaceholderObject( rHelper ) );
+ }
+ }
+
+ xDrawingObj->importObjBiff3( rStrm );
+ return xDrawingObj;
+}
+
+/*static*/ BiffDrawingObjectRef BiffDrawingObjectBase::importObjBiff4( const WorksheetHelper& rHelper, BiffInputStream& rStrm )
+{
+ BiffDrawingObjectRef xDrawingObj;
+
+ if( rStrm.getRemaining() >= 30 )
+ {
+ sal_uInt16 nObjType;
+ rStrm.skip( 4 );
+ rStrm >> nObjType;
+ switch( nObjType )
+ {
+ case BIFF_OBJTYPE_GROUP: xDrawingObj.reset( new BiffGroupObject( rHelper ) ); break;
+ case BIFF_OBJTYPE_LINE: xDrawingObj.reset( new BiffLineObject( rHelper ) ); break;
+ case BIFF_OBJTYPE_RECTANGLE: xDrawingObj.reset( new BiffRectObject( rHelper ) ); break;
+ case BIFF_OBJTYPE_OVAL: xDrawingObj.reset( new BiffOvalObject( rHelper ) ); break;
+ case BIFF_OBJTYPE_ARC: xDrawingObj.reset( new BiffArcObject( rHelper ) ); break;
+ case BIFF_OBJTYPE_POLYGON: xDrawingObj.reset( new BiffPolygonObject( rHelper ) ); break;
+#if 0
+ case BIFF_OBJTYPE_CHART: xDrawingObj.reset( new XclImpChartObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_TEXT: xDrawingObj.reset( new XclImpTextObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_BUTTON: xDrawingObj.reset( new XclImpButtonObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_PICTURE: xDrawingObj.reset( new XclImpPictureObj( rHelper ) ); break;
+#endif
+ default:
+#if 0
+ OSL_ENSURE( false, "BiffDrawingObjectBase::importObjBiff4 - unknown object type" );
+#endif
+ xDrawingObj.reset( new BiffPlaceholderObject( rHelper ) );
+ }
+ }
+
+ xDrawingObj->importObjBiff4( rStrm );
+ return xDrawingObj;
+}
+
+/*static*/ BiffDrawingObjectRef BiffDrawingObjectBase::importObjBiff5( const WorksheetHelper& rHelper, BiffInputStream& rStrm )
+{
+ BiffDrawingObjectRef xDrawingObj;
+
+ if( rStrm.getRemaining() >= 34 )
+ {
+ sal_uInt16 nObjType;
+ rStrm.skip( 4 );
+ rStrm >> nObjType;
+ switch( nObjType )
+ {
+ case BIFF_OBJTYPE_GROUP: xDrawingObj.reset( new BiffGroupObject( rHelper ) ); break;
+ case BIFF_OBJTYPE_LINE: xDrawingObj.reset( new BiffLineObject( rHelper ) ); break;
+ case BIFF_OBJTYPE_RECTANGLE: xDrawingObj.reset( new BiffRectObject( rHelper ) ); break;
+ case BIFF_OBJTYPE_OVAL: xDrawingObj.reset( new BiffOvalObject( rHelper ) ); break;
+ case BIFF_OBJTYPE_ARC: xDrawingObj.reset( new BiffArcObject( rHelper ) ); break;
+ case BIFF_OBJTYPE_POLYGON: xDrawingObj.reset( new BiffPolygonObject( rHelper ) ); break;
+#if 0
+ case BIFF_OBJTYPE_CHART: xDrawingObj.reset( new XclImpChartObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_TEXT: xDrawingObj.reset( new XclImpTextObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_BUTTON: xDrawingObj.reset( new XclImpButtonObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_PICTURE: xDrawingObj.reset( new XclImpPictureObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_CHECKBOX: xDrawingObj.reset( new XclImpCheckBoxObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_OPTIONBUTTON: xDrawingObj.reset( new XclImpOptionButtonObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_EDIT: xDrawingObj.reset( new XclImpEditObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_LABEL: xDrawingObj.reset( new XclImpLabelObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_DIALOG: xDrawingObj.reset( new XclImpDialogObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_SPIN: xDrawingObj.reset( new XclImpSpinButtonObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_SCROLLBAR: xDrawingObj.reset( new XclImpScrollBarObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_LISTBOX: xDrawingObj.reset( new XclImpListBoxObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_GROUPBOX: xDrawingObj.reset( new XclImpGroupBoxObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_DROPDOWN: xDrawingObj.reset( new XclImpDropDownObj( rHelper ) ); break;
+#endif
+ default:
+#if 0
+ OSL_ENSURE( false, "BiffDrawingObjectBase::importObjBiff5 - unknown object type" );
+#endif
+ xDrawingObj.reset( new BiffPlaceholderObject( rHelper ) );
+ }
+ }
+
+ xDrawingObj->importObjBiff5( rStrm );
+ return xDrawingObj;
+}
+
+/*static*/ BiffDrawingObjectRef BiffDrawingObjectBase::importObjBiff8( const WorksheetHelper& rHelper, BiffInputStream& rStrm )
+{
+ BiffDrawingObjectRef xDrawingObj;
+
+ if( rStrm.getRemaining() >= 10 )
+ {
+ sal_uInt16 nSubRecId, nSubRecSize, nObjType;
+ rStrm >> nSubRecId >> nSubRecSize >> nObjType;
+ OSL_ENSURE( nSubRecId == BIFF_ID_OBJCMO, "BiffDrawingObjectBase::importObjBiff8 - OBJCMO subrecord expected" );
+ if( (nSubRecId == BIFF_ID_OBJCMO) && (nSubRecSize >= 6) )
+ {
+ switch( nObjType )
+ {
+#if 0
+ // in BIFF8, all simple objects support text
+ case BIFF_OBJTYPE_LINE:
+ case BIFF_OBJTYPE_ARC:
+ xDrawingObj.reset( new XclImpTextObj( rHelper ) );
+ // lines and arcs may be 2-dimensional
+ xDrawingObj->setAreaObj( false );
+ break;
+
+ // in BIFF8, all simple objects support text
+ case BIFF_OBJTYPE_RECTANGLE:
+ case BIFF_OBJTYPE_OVAL:
+ case BIFF_OBJTYPE_POLYGON:
+ case BIFF_OBJTYPE_DRAWING:
+ case BIFF_OBJTYPE_TEXT:
+ xDrawingObj.reset( new XclImpTextObj( rHelper ) );
+ break;
+#endif
+
+ case BIFF_OBJTYPE_GROUP: xDrawingObj.reset( new BiffGroupObject( rHelper ) ); break;
+#if 0
+ case BIFF_OBJTYPE_CHART: xDrawingObj.reset( new XclImpChartObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_BUTTON: xDrawingObj.reset( new XclImpButtonObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_PICTURE: xDrawingObj.reset( new XclImpPictureObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_CHECKBOX: xDrawingObj.reset( new XclImpCheckBoxObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_OPTIONBUTTON: xDrawingObj.reset( new XclImpOptionButtonObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_EDIT: xDrawingObj.reset( new XclImpEditObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_LABEL: xDrawingObj.reset( new XclImpLabelObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_DIALOG: xDrawingObj.reset( new XclImpDialogObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_SPIN: xDrawingObj.reset( new XclImpSpinButtonObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_SCROLLBAR: xDrawingObj.reset( new XclImpScrollBarObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_LISTBOX: xDrawingObj.reset( new XclImpListBoxObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_GROUPBOX: xDrawingObj.reset( new XclImpGroupBoxObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_DROPDOWN: xDrawingObj.reset( new XclImpDropDownObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_NOTE: xDrawingObj.reset( new XclImpNoteObj( rHelper ) ); break;
+#endif
+
+ default:
+#if 0
+ OSL_ENSURE( false, "BiffDrawingObjectBase::importObjBiff8 - unknown object type" );
+#endif
+ xDrawingObj.reset( new BiffPlaceholderObject( rHelper ) );
+ }
+ }
+ }
+
+ xDrawingObj->importObjBiff8( rStrm );
+ return xDrawingObj;
+}
+
+Reference< XShape > BiffDrawingObjectBase::convertAndInsert( BiffDrawingBase& rDrawing,
+ const Reference< XShapes >& rxShapes, const Rectangle* pParentRect ) const
+{
+ Reference< XShape > xShape;
+ if( rxShapes.is() && mbProcessShape && !mbHidden ) // TODO: support for hidden objects?
+ {
+ // base class 'ShapeAnchor' calculates the shape rectangle in 1/100 mm
+ // in BIFF3-BIFF5, all shapes have absolute anchor (also children of group shapes)
+ Rectangle aShapeRect = maAnchor.calcAnchorRectHmm( getDrawPageSize() );
+
+ // convert the shape, if the calculated rectangle is not empty
+ bool bHasWidth = aShapeRect.Width > 0;
+ bool bHasHeight = aShapeRect.Height > 0;
+ if( mbAreaObj ? (bHasWidth && bHasHeight) : (bHasWidth || bHasHeight) )
+ {
+ xShape = implConvertAndInsert( rDrawing, rxShapes, aShapeRect );
+ /* Notify the drawing that a new shape has been inserted (but not
+ for children of group shapes). For convenience, pass the
+ rectangle that contains position and size of the shape. */
+ if( !pParentRect && xShape.is() )
+ rDrawing.notifyShapeInserted( xShape, aShapeRect );
+ }
+ }
+ return xShape;
+}
+
+// protected ------------------------------------------------------------------
+
+void BiffDrawingObjectBase::readNameBiff5( BiffInputStream& rStrm, sal_uInt16 nNameLen )
+{
+ maObjName = OUString();
+ if( nNameLen > 0 )
+ {
+ // name length field is repeated before the name
+ maObjName = rStrm.readByteStringUC( false, getTextEncoding() );
+ // skip padding byte for word boundaries
+ rStrm.alignToBlock( 2 );
+ }
+}
+
+void BiffDrawingObjectBase::readMacroBiff3( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
+{
+ maMacroName = OUString();
+ rStrm.skip( nMacroSize );
+ // skip padding byte for word boundaries, not contained in nMacroSize
+ rStrm.alignToBlock( 2 );
+}
+
+void BiffDrawingObjectBase::readMacroBiff4( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
+{
+ maMacroName = OUString();
+ rStrm.skip( nMacroSize );
+}
+
+void BiffDrawingObjectBase::readMacroBiff5( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
+{
+ maMacroName = OUString();
+ rStrm.skip( nMacroSize );
+}
+
+void BiffDrawingObjectBase::readMacroBiff8( BiffInputStream& rStrm )
+{
+ maMacroName = OUString();
+ if( rStrm.getRemaining() > 6 )
+ {
+ // macro is stored in a tNameXR token containing a link to a defined name
+ sal_uInt16 nFmlaSize;
+ rStrm >> nFmlaSize;
+ rStrm.skip( 4 );
+ OSL_ENSURE( nFmlaSize == 7, "BiffDrawingObjectBase::readMacroBiff8 - unexpected formula size" );
+ if( nFmlaSize == 7 )
+ {
+ sal_uInt8 nTokenId;
+ sal_uInt16 nExtLinkId, nExtNameId;
+ rStrm >> nTokenId >> nExtLinkId >> nExtNameId;
+#if 0
+ OSL_ENSURE( nTokenId == XclTokenArrayHelper::GetTokenId( EXC_TOKID_NAMEX, EXC_TOKCLASS_REF ),
+ "BiffDrawingObjectBase::readMacroBiff8 - tNameXR token expected" );
+ if( nTokenId == XclTokenArrayHelper::GetTokenId( EXC_TOKID_NAMEX, EXC_TOKCLASS_REF ) )
+ maMacroName = GetLinkManager().GetMacroName( nExtLinkId, nExtNameId );
+#endif
+ }
+ }
+}
+
+void BiffDrawingObjectBase::convertLineProperties( ShapePropertyMap& rPropMap, const BiffObjLineModel& rLineModel, sal_uInt16 nArrows ) const
+{
+ if( rLineModel.mbAuto )
+ {
+ BiffObjLineModel aAutoModel;
+ aAutoModel.mbAuto = false;
+ convertLineProperties( rPropMap, aAutoModel, nArrows );
+ return;
+ }
+
+ /* Convert line formatting to DrawingML line formatting and let the
+ DrawingML code do the hard work. */
+ LineProperties aLineProps;
+
+ if( rLineModel.mnStyle == BIFF_OBJ_LINE_NONE )
+ {
+ aLineProps.maLineFill.moFillType = XML_noFill;
+ }
+ else
+ {
+ aLineProps.maLineFill.moFillType = XML_solidFill;
+ aLineProps.maLineFill.maFillColor.setPaletteClr( rLineModel.mnColorIdx );
+ aLineProps.moLineCompound = XML_sng;
+ aLineProps.moLineCap = XML_flat;
+ aLineProps.moLineJoint = XML_round;
+
+ // line width: use 0.35 mm per BIFF line width step
+ sal_Int32 nLineWidth = 0;
+ switch( rLineModel.mnWidth )
+ {
+ default:
+ case BIFF_OBJ_LINE_HAIR: nLineWidth = 0; break;
+ case BIFF_OBJ_LINE_THIN: nLineWidth = 20; break;
+ case BIFF_OBJ_LINE_MEDIUM: nLineWidth = 40; break;
+ case BIFF_OBJ_LINE_THICK: nLineWidth = 60; break;
+ }
+ aLineProps.moLineWidth = getLimitedValue< sal_Int32, sal_Int64 >( convertHmmToEmu( nLineWidth ), 0, SAL_MAX_INT32 );
+
+ // dash style and transparency
+ switch( rLineModel.mnStyle )
+ {
+ default:
+ case BIFF_OBJ_LINE_SOLID:
+ aLineProps.moPresetDash = XML_solid;
+ break;
+ case BIFF_OBJ_LINE_DASH:
+ aLineProps.moPresetDash = XML_lgDash;
+ break;
+ case BIFF_OBJ_LINE_DOT:
+ aLineProps.moPresetDash = XML_dot;
+ break;
+ case BIFF_OBJ_LINE_DASHDOT:
+ aLineProps.moPresetDash = XML_lgDashDot;
+ break;
+ case BIFF_OBJ_LINE_DASHDOTDOT:
+ aLineProps.moPresetDash = XML_lgDashDotDot;
+ break;
+ case BIFF_OBJ_LINE_MEDTRANS:
+ aLineProps.moPresetDash = XML_solid;
+ aLineProps.maLineFill.maFillColor.addTransformation( XML_alpha, 50 * PER_PERCENT );
+ break;
+ case BIFF_OBJ_LINE_DARKTRANS:
+ aLineProps.moPresetDash = XML_solid;
+ aLineProps.maLineFill.maFillColor.addTransformation( XML_alpha, 75 * PER_PERCENT );
+ break;
+ case BIFF_OBJ_LINE_LIGHTTRANS:
+ aLineProps.moPresetDash = XML_solid;
+ aLineProps.maLineFill.maFillColor.addTransformation( XML_alpha, 25 * PER_PERCENT );
+ break;
+ }
+
+ // line ends
+ bool bLineStart = false;
+ bool bLineEnd = false;
+ bool bFilled = false;
+ switch( extractValue< sal_uInt8 >( nArrows, 0, 4 ) )
+ {
+ case BIFF_OBJ_ARROW_OPEN: bLineStart = false; bLineEnd = true; bFilled = false; break;
+ case BIFF_OBJ_ARROW_OPENBOTH: bLineStart = true; bLineEnd = true; bFilled = false; break;
+ case BIFF_OBJ_ARROW_FILLED: bLineStart = false; bLineEnd = true; bFilled = true; break;
+ case BIFF_OBJ_ARROW_FILLEDBOTH: bLineStart = true; bLineEnd = true; bFilled = true; break;
+ }
+ if( bLineStart || bLineEnd )
+ {
+ // arrow type (open or closed)
+ sal_Int32 nArrowType = bFilled ? XML_triangle : XML_arrow;
+ aLineProps.maStartArrow.moArrowType = bLineStart ? nArrowType : XML_none;
+ aLineProps.maEndArrow.moArrowType = bLineEnd ? nArrowType : XML_none;
+
+ // arrow width
+ sal_Int32 nArrowWidth = XML_med;
+ switch( extractValue< sal_uInt8 >( nArrows, 4, 4 ) )
+ {
+ case BIFF_OBJ_ARROW_NARROW: nArrowWidth = XML_sm; break;
+ case BIFF_OBJ_ARROW_MEDIUM: nArrowWidth = XML_med; break;
+ case BIFF_OBJ_ARROW_WIDE: nArrowWidth = XML_lg; break;
+ }
+ aLineProps.maStartArrow.moArrowWidth = aLineProps.maEndArrow.moArrowWidth = nArrowWidth;
+
+ // arrow length
+ sal_Int32 nArrowLength = XML_med;
+ switch( extractValue< sal_uInt8 >( nArrows, 8, 4 ) )
+ {
+ case BIFF_OBJ_ARROW_NARROW: nArrowLength = XML_sm; break;
+ case BIFF_OBJ_ARROW_MEDIUM: nArrowLength = XML_med; break;
+ case BIFF_OBJ_ARROW_WIDE: nArrowLength = XML_lg; break;
+ }
+ aLineProps.maStartArrow.moArrowLength = aLineProps.maEndArrow.moArrowLength = nArrowLength;
+ }
+ }
+
+ aLineProps.pushToPropMap( rPropMap, getBaseFilter().getGraphicHelper() );
+}
+
+void BiffDrawingObjectBase::convertFillProperties( ShapePropertyMap& rPropMap, const BiffObjFillModel& rFillModel ) const
+{
+ if( rFillModel.mbAuto )
+ {
+ BiffObjFillModel aAutoModel;
+ aAutoModel.mbAuto = false;
+ convertFillProperties( rPropMap, aAutoModel );
+ return;
+ }
+
+ /* Convert fill formatting to DrawingML fill formatting and let the
+ DrawingML code do the hard work. */
+ FillProperties aFillProps;
+
+ if( rFillModel.mnPattern == BIFF_OBJ_PATT_NONE )
+ {
+ aFillProps.moFillType = XML_noFill;
+ }
+ else
+ {
+ const sal_Int32 spnPatternPresets[] = {
+ XML_TOKEN_INVALID, XML_TOKEN_INVALID, XML_pct50, XML_pct50, XML_pct25,
+ XML_dkHorz, XML_dkVert, XML_dkDnDiag, XML_dkUpDiag, XML_smCheck, XML_trellis,
+ XML_ltHorz, XML_ltVert, XML_ltDnDiag, XML_ltUpDiag, XML_smGrid, XML_diagCross,
+ XML_pct20, XML_pct10 };
+ sal_Int32 nPatternPreset = STATIC_ARRAY_SELECT( spnPatternPresets, rFillModel.mnPattern, XML_TOKEN_INVALID );
+ if( nPatternPreset == XML_TOKEN_INVALID )
+ {
+ aFillProps.moFillType = XML_solidFill;
+ aFillProps.maFillColor.setPaletteClr( rFillModel.mnPattColorIdx );
+ }
+ else
+ {
+ aFillProps.moFillType = XML_pattFill;
+ aFillProps.maPatternProps.maPattFgColor.setPaletteClr( rFillModel.mnPattColorIdx );
+ aFillProps.maPatternProps.maPattBgColor.setPaletteClr( rFillModel.mnBackColorIdx );
+ aFillProps.maPatternProps.moPattPreset = nPatternPreset;
+ }
+#if 0
+ static const sal_uInt8 sppnPatterns[][ 8 ] =
+ {
+ { 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55 },
+ { 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD },
+ { 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22 },
+ { 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00 },
+ { 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC },
+ { 0x33, 0x66, 0xCC, 0x99, 0x33, 0x66, 0xCC, 0x99 },
+ { 0xCC, 0x66, 0x33, 0x99, 0xCC, 0x66, 0x33, 0x99 },
+ { 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33 },
+ { 0xCC, 0xFF, 0x33, 0xFF, 0xCC, 0xFF, 0x33, 0xFF },
+ { 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00 },
+ { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88 },
+ { 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88 },
+ { 0x88, 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11 },
+ { 0xFF, 0x11, 0x11, 0x11, 0xFF, 0x11, 0x11, 0x11 },
+ { 0xAA, 0x44, 0xAA, 0x11, 0xAA, 0x44, 0xAA, 0x11 },
+ { 0x88, 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00 },
+ { 0x80, 0x00, 0x08, 0x00, 0x80, 0x00, 0x08, 0x00 }
+ };
+ const sal_uInt8* const pnPattern = sppnPatterns[ ::std::min< size_t >( rFillData.mnPattern - 2, STATIC_ARRAY_SIZE( sppnPatterns ) ) ];
+ // create 2-colored 8x8 DIB
+ SvMemoryStream aMemStrm;
+// { 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00 }
+ aMemStrm << sal_uInt32( 12 ) << sal_Int16( 8 ) << sal_Int16( 8 ) << sal_uInt16( 1 ) << sal_uInt16( 1 );
+ aMemStrm << sal_uInt8( 0xFF ) << sal_uInt8( 0xFF ) << sal_uInt8( 0xFF );
+ aMemStrm << sal_uInt8( 0x00 ) << sal_uInt8( 0x00 ) << sal_uInt8( 0x00 );
+ for( size_t nIdx = 0; nIdx < 8; ++nIdx )
+ aMemStrm << sal_uInt32( pnPattern[ nIdx ] ); // 32-bit little-endian
+ aMemStrm.Seek( STREAM_SEEK_TO_BEGIN );
+ Bitmap aBitmap;
+ aBitmap.Read( aMemStrm, FALSE );
+ XOBitmap aXOBitmap( aBitmap );
+ aXOBitmap.Bitmap2Array();
+ aXOBitmap.SetBitmapType( XBITMAP_8X8 );
+ if( aXOBitmap.GetBackgroundColor().GetColor() == COL_BLACK )
+ ::std::swap( aPattColor, aBackColor );
+ aXOBitmap.SetPixelColor( aPattColor );
+ aXOBitmap.SetBackgroundColor( aBackColor );
+ rSdrObj.SetMergedItem( XFillStyleItem( XFILL_BITMAP ) );
+ rSdrObj.SetMergedItem( XFillBitmapItem( EMPTY_STRING, aXOBitmap ) );
+#endif
+ }
+
+ aFillProps.pushToPropMap( rPropMap, getBaseFilter().getGraphicHelper() );
+}
+
+void BiffDrawingObjectBase::convertFrameProperties( ShapePropertyMap& /*rPropMap*/, sal_uInt16 /*nFrameFlags*/ ) const
+{
+}
+
+void BiffDrawingObjectBase::implReadObjBiff3( BiffInputStream& /*rStrm*/, sal_uInt16 /*nMacroSize*/ )
+{
+}
+
+void BiffDrawingObjectBase::implReadObjBiff4( BiffInputStream& /*rStrm*/, sal_uInt16 /*nMacroSize*/ )
+{
+}
+
+void BiffDrawingObjectBase::implReadObjBiff5( BiffInputStream& /*rStrm*/, sal_uInt16 /*nNameLen*/, sal_uInt16 /*nMacroSize*/ )
+{
+}
+
+void BiffDrawingObjectBase::implReadObjBiff8SubRec( BiffInputStream& /*rStrm*/, sal_uInt16 /*nSubRecId*/, sal_uInt16 /*nSubRecSize*/ )
+{
+}
+
+// private --------------------------------------------------------------------
+
+void BiffDrawingObjectBase::importObjBiff3( BiffInputStream& rStrm )
+{
+ // back to offset 4 (ignore object count field)
+ rStrm.seek( 4 );
+
+ sal_uInt16 nObjFlags, nMacroSize;
+ rStrm >> mnObjType >> mnObjId >> nObjFlags >> maAnchor >> nMacroSize;
+ rStrm.skip( 2 );
+
+ mbHasAnchor = true;
+ mbHidden = getFlag( nObjFlags, BIFF_OBJ_HIDDEN );
+ mbVisible = getFlag( nObjFlags, BIFF_OBJ_VISIBLE );
+ implReadObjBiff3( rStrm, nMacroSize );
+}
+
+void BiffDrawingObjectBase::importObjBiff4( BiffInputStream& rStrm )
+{
+ // back to offset 4 (ignore object count field)
+ rStrm.seek( 4 );
+
+ sal_uInt16 nObjFlags, nMacroSize;
+ rStrm >> mnObjType >> mnObjId >> nObjFlags >> maAnchor >> nMacroSize;
+ rStrm.skip( 2 );
+
+ mbHasAnchor = true;
+ mbHidden = getFlag( nObjFlags, BIFF_OBJ_HIDDEN );
+ mbVisible = getFlag( nObjFlags, BIFF_OBJ_VISIBLE );
+ mbPrintable = getFlag( nObjFlags, BIFF_OBJ_PRINTABLE );
+ implReadObjBiff4( rStrm, nMacroSize );
+}
+
+void BiffDrawingObjectBase::importObjBiff5( BiffInputStream& rStrm )
+{
+ // back to offset 4 (ignore object count field)
+ rStrm.seek( 4 );
+
+ sal_uInt16 nObjFlags, nMacroSize, nNameLen;
+ rStrm >> mnObjType >> mnObjId >> nObjFlags >> maAnchor >> nMacroSize;
+ rStrm.skip( 2 );
+ rStrm >> nNameLen;
+ rStrm.skip( 2 );
+
+ mbHasAnchor = true;
+ mbHidden = getFlag( nObjFlags, BIFF_OBJ_HIDDEN );
+ mbVisible = getFlag( nObjFlags, BIFF_OBJ_VISIBLE );
+ mbPrintable = getFlag( nObjFlags, BIFF_OBJ_PRINTABLE );
+ implReadObjBiff5( rStrm, nNameLen, nMacroSize );
+}
+
+void BiffDrawingObjectBase::importObjBiff8( BiffInputStream& rStrm )
+{
+ // back to beginning
+ rStrm.seekToStart();
+
+ bool bLoop = true;
+ while( bLoop && (rStrm.getRemaining() >= 4) )
+ {
+ sal_uInt16 nSubRecId, nSubRecSize;
+ rStrm >> nSubRecId >> nSubRecSize;
+ sal_Int64 nStrmPos = rStrm.tell();
+ // sometimes the last subrecord has an invalid length (OBJLBSDATA) -> min()
+ nSubRecSize = static_cast< sal_uInt16 >( ::std::min< sal_Int64 >( nSubRecSize, rStrm.getRemaining() ) );
+
+ switch( nSubRecId )
+ {
+ case BIFF_ID_OBJCMO:
+ OSL_ENSURE( rStrm.tell() == 4, "BiffDrawingObjectBase::importObjBiff8 - unexpected OBJCMO subrecord" );
+ if( (rStrm.tell() == 4) && (nSubRecSize >= 6) )
+ {
+ sal_uInt16 nObjFlags;
+ rStrm >> mnObjType >> mnObjId >> nObjFlags;
+ mbPrintable = getFlag( nObjFlags, BIFF_OBJCMO_PRINTABLE );
+ }
+ break;
+ case BIFF_ID_OBJMACRO:
+ readMacroBiff8( rStrm );
+ break;
+ case BIFF_ID_OBJEND:
+ bLoop = false;
+ break;
+ default:
+ implReadObjBiff8SubRec( rStrm, nSubRecId, nSubRecSize );
+ }
+
+ // seek to end of subrecord
+ rStrm.seek( nStrmPos + nSubRecSize );
+ }
+
+ /* Call doReadObj8SubRec() with BIFF_ID_OBJEND for further stream
+ processing (e.g. charts), even if the OBJEND subrecord is missing. */
+ implReadObjBiff8SubRec( rStrm, BIFF_ID_OBJEND, 0 );
+
+ /* Pictures that Excel reads from BIFF5 and writes to BIFF8 still have the
+ IMGDATA record following the OBJ record (but they use the image data
+ stored in DFF). The IMGDATA record may be continued by several CONTINUE
+ records. But the last CONTINUE record may be in fact an MSODRAWING
+ record that contains the DFF data of the next drawing object! So we
+ have to skip just enough CONTINUE records to look at the next
+ MSODRAWING/CONTINUE record. */
+ if( (rStrm.getNextRecId() == BIFF3_ID_IMGDATA) && rStrm.startNextRecord() )
+ {
+ rStrm.skip( 4 );
+ sal_Int64 nDataSize = rStrm.readuInt32();
+ nDataSize -= rStrm.getRemaining();
+ // skip following CONTINUE records until IMGDATA ends
+ while( (nDataSize > 0) && (rStrm.getNextRecId() == BIFF_ID_CONT) && rStrm.startNextRecord() )
+ {
+ OSL_ENSURE( nDataSize >= rStrm.getRemaining(), "BiffDrawingObjectBase::importObjBiff8 - CONTINUE too long" );
+ nDataSize -= ::std::min( rStrm.getRemaining(), nDataSize );
+ }
+ OSL_ENSURE( nDataSize == 0, "BiffDrawingObjectBase::importObjBiff8 - missing CONTINUE records" );
+ // next record may be MSODRAWING or CONTINUE or anything else
+ }
+}
+
+// ============================================================================
+
+BiffPlaceholderObject::BiffPlaceholderObject( const WorksheetHelper& rHelper ) :
+ BiffDrawingObjectBase( rHelper )
+{
+ setProcessShape( false );
+}
+
+Reference< XShape > BiffPlaceholderObject::implConvertAndInsert( BiffDrawingBase& /*rDrawing*/,
+ const Reference< XShapes >& /*rxShapes*/, const Rectangle& /*rShapeRect*/ ) const
+{
+ return Reference< XShape >();
+}
+
+// ============================================================================
+
+BiffGroupObject::BiffGroupObject( const WorksheetHelper& rHelper ) :
+ BiffDrawingObjectBase( rHelper ),
+ mnFirstUngrouped( BIFF_OBJ_INVALID_ID )
+{
+}
+
+bool BiffGroupObject::tryInsert( const BiffDrawingObjectRef& rxDrawingObj )
+{
+ if( rxDrawingObj->getObjId() == mnFirstUngrouped )
+ return false;
+ // insert into own list or into nested group
+ maChildren.insertGrouped( rxDrawingObj );
+ return true;
+}
+
+void BiffGroupObject::implReadObjBiff3( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
+{
+ rStrm.skip( 4 );
+ rStrm >> mnFirstUngrouped;
+ rStrm.skip( 16 );
+ readMacroBiff3( rStrm, nMacroSize );
+}
+
+void BiffGroupObject::implReadObjBiff4( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
+{
+ rStrm.skip( 4 );
+ rStrm >> mnFirstUngrouped;
+ rStrm.skip( 16 );
+ readMacroBiff4( rStrm, nMacroSize );
+}
+
+void BiffGroupObject::implReadObjBiff5( BiffInputStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
+{
+ rStrm.skip( 4 );
+ rStrm >> mnFirstUngrouped;
+ rStrm.skip( 16 );
+ readNameBiff5( rStrm, nNameLen );
+ readMacroBiff5( rStrm, nMacroSize );
+}
+
+Reference< XShape > BiffGroupObject::implConvertAndInsert( BiffDrawingBase& rDrawing,
+ const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
+{
+ Reference< XShape > xGroupShape;
+ if( !maChildren.empty() ) try
+ {
+ xGroupShape = rDrawing.createAndInsertXShape( CREATE_OUSTRING( "com.sun.star.drawing.GroupShape" ), rxShapes, rShapeRect );
+ Reference< XShapes > xChildShapes( xGroupShape, UNO_QUERY_THROW );
+ maChildren.convertAndInsert( rDrawing, xChildShapes, &rShapeRect );
+ // no child shape has been created - delete the group shape
+ if( !xChildShapes->hasElements() )
+ {
+ rxShapes->remove( xGroupShape );
+ xGroupShape.clear();
+ }
+ }
+ catch( Exception& )
+ {
+ }
+ return xGroupShape;
+}
+
+// ============================================================================
+
+BiffLineObject::BiffLineObject( const WorksheetHelper& rHelper ) :
+ BiffDrawingObjectBase( rHelper ),
+ mnArrows( 0 ),
+ mnStartPoint( BIFF_OBJ_LINE_TL )
+{
+ setAreaObj( false );
+}
+
+void BiffLineObject::implReadObjBiff3( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
+{
+ rStrm >> maLineModel >> mnArrows >> mnStartPoint;
+ rStrm.skip( 1 );
+ readMacroBiff3( rStrm, nMacroSize );
+}
+
+void BiffLineObject::implReadObjBiff4( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
+{
+ rStrm >> maLineModel >> mnArrows >> mnStartPoint;
+ rStrm.skip( 1 );
+ readMacroBiff4( rStrm, nMacroSize );
+}
+
+void BiffLineObject::implReadObjBiff5( BiffInputStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
+{
+ rStrm >> maLineModel >> mnArrows >> mnStartPoint;
+ rStrm.skip( 1 );
+ readNameBiff5( rStrm, nNameLen );
+ readMacroBiff5( rStrm, nMacroSize );
+}
+
+Reference< XShape > BiffLineObject::implConvertAndInsert( BiffDrawingBase& rDrawing,
+ const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
+{
+ ShapePropertyMap aPropMap( getBaseFilter().getModelObjectHelper() );
+ convertLineProperties( aPropMap, maLineModel, mnArrows );
+
+ // create the line polygon
+ PointSequenceSequence aPoints( 1 );
+ aPoints[ 0 ].realloc( 2 );
+ Point& rBeg = aPoints[ 0 ][ 0 ];
+ Point& rEnd = aPoints[ 0 ][ 1 ];
+ sal_Int32 nL = rShapeRect.X;
+ sal_Int32 nT = rShapeRect.Y;
+ sal_Int32 nR = rShapeRect.X + ::std::max< sal_Int32 >( rShapeRect.Width - 1, 0 );
+ sal_Int32 nB = rShapeRect.Y + ::std::max< sal_Int32 >( rShapeRect.Height - 1, 0 );
+ switch( mnStartPoint )
+ {
+ default:
+ case BIFF_OBJ_LINE_TL: rBeg.X = nL; rBeg.Y = nT; rEnd.X = nR; rEnd.Y = nB; break;
+ case BIFF_OBJ_LINE_TR: rBeg.X = nR; rBeg.Y = nT; rEnd.X = nL; rEnd.Y = nB; break;
+ case BIFF_OBJ_LINE_BR: rBeg.X = nR; rBeg.Y = nB; rEnd.X = nL; rEnd.Y = nT; break;
+ case BIFF_OBJ_LINE_BL: rBeg.X = nL; rBeg.Y = nB; rEnd.X = nR; rEnd.Y = nT; break;
+ }
+ aPropMap.setProperty( PROP_PolyPolygon, aPoints );
+ aPropMap.setProperty( PROP_PolygonKind, PolygonKind_LINE );
+
+ // create the shape
+ Reference< XShape > xShape = rDrawing.createAndInsertXShape( CREATE_OUSTRING( "com.sun.star.drawing.LineShape" ), rxShapes, rShapeRect );
+ PropertySet( xShape ).setProperties( aPropMap );
+ return xShape;
+}
+
+// ============================================================================
+
+BiffRectObject::BiffRectObject( const WorksheetHelper& rHelper ) :
+ BiffDrawingObjectBase( rHelper ),
+ mnFrameFlags( 0 )
+{
+ setAreaObj( true );
+}
+
+void BiffRectObject::readFrameData( BiffInputStream& rStrm )
+{
+ rStrm >> maFillModel >> maLineModel >> mnFrameFlags;
+}
+
+void BiffRectObject::convertRectProperties( ShapePropertyMap& rPropMap ) const
+{
+ convertLineProperties( rPropMap, maLineModel );
+ convertFillProperties( rPropMap, maFillModel );
+ convertFrameProperties( rPropMap, mnFrameFlags );
+}
+
+void BiffRectObject::implReadObjBiff3( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
+{
+ readFrameData( rStrm );
+ readMacroBiff3( rStrm, nMacroSize );
+}
+
+void BiffRectObject::implReadObjBiff4( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
+{
+ readFrameData( rStrm );
+ readMacroBiff4( rStrm, nMacroSize );
+}
+
+void BiffRectObject::implReadObjBiff5( BiffInputStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
+{
+ readFrameData( rStrm );
+ readNameBiff5( rStrm, nNameLen );
+ readMacroBiff5( rStrm, nMacroSize );
+}
+
+Reference< XShape > BiffRectObject::implConvertAndInsert( BiffDrawingBase& rDrawing,
+ const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
+{
+ ShapePropertyMap aPropMap( getBaseFilter().getModelObjectHelper() );
+ convertRectProperties( aPropMap );
+
+ Reference< XShape > xShape = rDrawing.createAndInsertXShape( CREATE_OUSTRING( "com.sun.star.drawing.RectangleShape" ), rxShapes, rShapeRect );
+ PropertySet( xShape ).setProperties( aPropMap );
+ return xShape;
+}
+
+// ============================================================================
+
+BiffOvalObject::BiffOvalObject( const WorksheetHelper& rHelper ) :
+ BiffRectObject( rHelper )
+{
+}
+
+Reference< XShape > BiffOvalObject::implConvertAndInsert( BiffDrawingBase& rDrawing,
+ const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
+{
+ ShapePropertyMap aPropMap( getBaseFilter().getModelObjectHelper() );
+ convertRectProperties( aPropMap );
+
+ Reference< XShape > xShape = rDrawing.createAndInsertXShape( CREATE_OUSTRING( "com.sun.star.drawing.EllipseShape" ), rxShapes, rShapeRect );
+ PropertySet( xShape ).setProperties( aPropMap );
+ return xShape;
+}
+
+// ============================================================================
+
+BiffArcObject::BiffArcObject( const WorksheetHelper& rHelper ) :
+ BiffDrawingObjectBase( rHelper ),
+ mnQuadrant( BIFF_OBJ_ARC_TR )
+{
+ setAreaObj( false ); // arc may be 2-dimensional
+}
+
+void BiffArcObject::implReadObjBiff3( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
+{
+ rStrm >> maFillModel >> maLineModel >> mnQuadrant;
+ rStrm.skip( 1 );
+ readMacroBiff3( rStrm, nMacroSize );
+}
+
+void BiffArcObject::implReadObjBiff4( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
+{
+ rStrm >> maFillModel >> maLineModel >> mnQuadrant;
+ rStrm.skip( 1 );
+ readMacroBiff4( rStrm, nMacroSize );
+}
+
+void BiffArcObject::implReadObjBiff5( BiffInputStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
+{
+ rStrm >> maFillModel >> maLineModel >> mnQuadrant;
+ rStrm.skip( 1 );
+ readNameBiff5( rStrm, nNameLen );
+ readMacroBiff5( rStrm, nMacroSize );
+}
+
+Reference< XShape > BiffArcObject::implConvertAndInsert( BiffDrawingBase& rDrawing,
+ const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
+{
+ ShapePropertyMap aPropMap( getBaseFilter().getModelObjectHelper() );
+ convertLineProperties( aPropMap, maLineModel );
+ convertFillProperties( aPropMap, maFillModel );
+
+ /* Simulate arc objects with ellipse sections. While the original arc
+ object uses the entire object rectangle, only one quarter of the
+ ellipse shape will be visible. Thus, the size of the ellipse shape
+ needs to be extended and its position adjusted according to the visible
+ quadrant. */
+ Rectangle aNewRect( rShapeRect.X, rShapeRect.Y, rShapeRect.Width * 2, rShapeRect.Height * 2 );
+ long nStartAngle = 0;
+ switch( mnQuadrant )
+ {
+ default:
+ case BIFF_OBJ_ARC_TR: nStartAngle = 0; aNewRect.X -= rShapeRect.Width; break;
+ case BIFF_OBJ_ARC_TL: nStartAngle = 9000; break;
+ case BIFF_OBJ_ARC_BL: nStartAngle = 18000; aNewRect.Y -= rShapeRect.Height; break;
+ case BIFF_OBJ_ARC_BR: nStartAngle = 27000; aNewRect.X -= rShapeRect.Width; aNewRect.Y -= rShapeRect.Height; break;
+ }
+ long nEndAngle = (nStartAngle + 9000) % 36000;
+ aPropMap.setProperty( PROP_CircleKind, maFillModel.isFilled() ? CircleKind_SECTION : CircleKind_ARC );
+ aPropMap.setProperty( PROP_CircleStartAngle, nStartAngle );
+ aPropMap.setProperty( PROP_CircleEndAngle, nEndAngle );
+
+ // create the shape
+ Reference< XShape > xShape = rDrawing.createAndInsertXShape( CREATE_OUSTRING( "com.sun.star.drawing.EllipseShape" ), rxShapes, aNewRect );
+ PropertySet( xShape ).setProperties( aPropMap );
+ return xShape;
+}
+
+// ============================================================================
+
+BiffPolygonObject::BiffPolygonObject( const WorksheetHelper& rHelper ) :
+ BiffRectObject( rHelper ),
+ mnPolyFlags( 0 ),
+ mnPointCount( 0 )
+{
+ setAreaObj( false ); // polygon may be 2-dimensional
+}
+
+void BiffPolygonObject::implReadObjBiff4( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
+{
+ readFrameData( rStrm );
+ rStrm >> mnPolyFlags;
+ rStrm.skip( 10 );
+ rStrm >> mnPointCount;
+ rStrm.skip( 8 );
+ readMacroBiff4( rStrm, nMacroSize );
+ importCoordList( rStrm );
+}
+
+void BiffPolygonObject::implReadObjBiff5( BiffInputStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
+{
+ readFrameData( rStrm );
+ rStrm >> mnPolyFlags;
+ rStrm.skip( 10 );
+ rStrm >> mnPointCount;
+ rStrm.skip( 8 );
+ readNameBiff5( rStrm, nNameLen );
+ readMacroBiff5( rStrm, nMacroSize );
+ importCoordList( rStrm );
+}
+
+namespace {
+
+Point lclGetPolyPoint( const Rectangle& rAnchorRect, const Point& rPoint )
+{
+ // polygon coordinates are given in 1/16384 of shape size
+ return Point(
+ rAnchorRect.X + static_cast< sal_Int32 >( rAnchorRect.Width * getLimitedValue< double >( static_cast< double >( rPoint.X ) / 16384.0, 0.0, 1.0 ) + 0.5 ),
+ rAnchorRect.Y + static_cast< sal_Int32 >( rAnchorRect.Height * getLimitedValue< double >( static_cast< double >( rPoint.Y ) / 16384.0, 0.0, 1.0 ) + 0.5 ) );
+}
+
+} // namespace
+
+Reference< XShape > BiffPolygonObject::implConvertAndInsert( BiffDrawingBase& rDrawing,
+ const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
+{
+ Reference< XShape > xShape;
+ if( maCoords.size() >= 2 )
+ {
+ ShapePropertyMap aPropMap( getBaseFilter().getModelObjectHelper() );
+ convertRectProperties( aPropMap );
+
+ // create the polygon
+ PointVector aPolygon;
+ for( PointVector::const_iterator aIt = maCoords.begin(), aEnd = maCoords.end(); aIt != aEnd; ++aIt )
+ aPolygon.push_back( lclGetPolyPoint( rShapeRect, *aIt ) );
+ // close polygon if specified
+ if( getFlag( mnPolyFlags, BIFF_OBJ_POLY_CLOSED ) && ((maCoords.front().X != maCoords.back().X) || (maCoords.front().Y != maCoords.back().Y)) )
+ aPolygon.push_back( aPolygon.front() );
+ PointSequenceSequence aPoints( 1 );
+ aPoints[ 0 ] = ContainerHelper::vectorToSequence( aPolygon );
+ aPropMap.setProperty( PROP_PolyPolygon, aPoints );
+
+ // create the shape
+ OUString aService = maFillModel.isFilled() ?
+ CREATE_OUSTRING( "com.sun.star.drawing.PolyPolygonShape" ) :
+ CREATE_OUSTRING( "com.sun.star.drawing.PolyLineShape" );
+ xShape = rDrawing.createAndInsertXShape( aService, rxShapes, rShapeRect );
+ PropertySet( xShape ).setProperties( aPropMap );
+ }
+ return xShape;
+}
+
+void BiffPolygonObject::importCoordList( BiffInputStream& rStrm )
+{
+ if( (rStrm.getNextRecId() == BIFF_ID_COORDLIST) && rStrm.startNextRecord() )
+ {
+ OSL_ENSURE( rStrm.getRemaining() / 4 == mnPointCount, "BiffPolygonObject::importCoordList - wrong polygon point count" );
+ while( rStrm.getRemaining() >= 4 )
+ {
+ sal_uInt16 nX, nY;
+ rStrm >> nX >> nY;
+ maCoords.push_back( Point( nX, nY ) );
+ }
+ }
+}
+
+// ============================================================================
+// BIFF drawing page
+// ============================================================================
+
+BiffDrawingBase::BiffDrawingBase( const WorksheetHelper& rHelper, const Reference< XDrawPage >& rxDrawPage ) :
+ WorksheetHelper( rHelper ),
+ mxDrawPage( rxDrawPage )
+{
+}
+
+void BiffDrawingBase::importObj( BiffInputStream& rStrm )
+{
+ BiffDrawingObjectRef xDrawingObj;
+
+#if 0
+ /* #i61786# In BIFF8 streams, OBJ records may occur without MSODRAWING
+ records. In this case, the OBJ records are in BIFF5 format. Do a sanity
+ check here that there is no DFF data loaded before. */
+ DBG_ASSERT( maDffStrm.Tell() == 0, "BiffDrawingBase::importObj - unexpected DFF stream data, OBJ will be ignored" );
+ if( maDffStrm.Tell() == 0 ) switch( GetBiff() )
+#else
+ switch( getBiff() )
+#endif
+ {
+ case BIFF3:
+ xDrawingObj = BiffDrawingObjectBase::importObjBiff3( *this, rStrm );
+ break;
+ case BIFF4:
+ xDrawingObj = BiffDrawingObjectBase::importObjBiff4( *this, rStrm );
+ break;
+ case BIFF5:
+// TODO: add BIFF8 when DFF is supported
+// case BIFF8:
+ xDrawingObj = BiffDrawingObjectBase::importObjBiff5( *this, rStrm );
+ break;
+ default:;
+ }
+
+ if( xDrawingObj.get() )
+ {
+ // insert into maRawObjs or into the last open group object
+ maRawObjs.insertGrouped( xDrawingObj );
+ // to be able to find objects by ID
+ maObjMapId[ xDrawingObj->getObjId() ] = xDrawingObj;
+ }
+}
+
+void BiffDrawingBase::setSkipObj( sal_uInt16 nObjId )
+{
+ /* Store identifiers of objects to be skipped in a separate list (the OBJ
+ record may not be read yet). In the finalization phase, all objects
+ registered here will be skipped. */
+ maSkipObjs.push_back( nObjId );
+}
+
+void BiffDrawingBase::finalizeImport()
+{
+ Reference< XShapes > xShapes( mxDrawPage, UNO_QUERY );
+ OSL_ENSURE( xShapes.is(), "BiffDrawingBase::finalizeImport - no shapes container" );
+ if( !xShapes.is() )
+ return;
+
+ // process list of objects to be skipped
+ for( BiffObjIdVector::const_iterator aIt = maSkipObjs.begin(), aEnd = maSkipObjs.end(); aIt != aEnd; ++aIt )
+ if( BiffDrawingObjectBase* pDrawingObj = maObjMapId.get( *aIt ).get() )
+ pDrawingObj->setProcessShape( false );
+
+ // process drawing objects without DFF data
+ maRawObjs.convertAndInsert( *this, xShapes );
+}
+
+Reference< XShape > BiffDrawingBase::createAndInsertXShape( const OUString& rService,
+ const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
+{
+ OSL_ENSURE( rService.getLength() > 0, "BiffDrawingBase::createAndInsertXShape - missing UNO shape service name" );
+ OSL_ENSURE( rxShapes.is(), "BiffDrawingBase::createAndInsertXShape - missing XShapes container" );
+ Reference< XShape > xShape;
+ if( (rService.getLength() > 0) && rxShapes.is() ) try
+ {
+ xShape.set( getBaseFilter().getModelFactory()->createInstance( rService ), UNO_QUERY_THROW );
+ // insert shape into passed shape collection (maybe drawpage or group shape)
+ rxShapes->add( xShape );
+ xShape->setPosition( Point( rShapeRect.X, rShapeRect.Y ) );
+ xShape->setSize( Size( rShapeRect.Width, rShapeRect.Height ) );
+ }
+ catch( Exception& )
+ {
+ }
+ OSL_ENSURE( xShape.is(), "BiffDrawingBase::createAndInsertXShape - cannot instanciate shape object" );
+ return xShape;
+}
+
+// protected ------------------------------------------------------------------
+
+void BiffDrawingBase::appendRawObject( const BiffDrawingObjectRef& rxDrawingObj )
+{
+ OSL_ENSURE( rxDrawingObj.get(), "BiffDrawingBase::appendRawObject - unexpected empty object reference" );
+ maRawObjs.append( rxDrawingObj );
+}
+
+// ============================================================================
+
+BiffSheetDrawing::BiffSheetDrawing( const WorksheetHelper& rHelper ) :
+ BiffDrawingBase( rHelper, rHelper.getDrawPage() )
+{
+}
+
+void BiffSheetDrawing::notifyShapeInserted( const Reference< XShape >& /*rxShape*/, const Rectangle& rShapeRect )
+{
+ // collect all shape positions in the WorksheetHelper base class
+ extendShapeBoundingBox( rShapeRect );
+}
+
+// ============================================================================
+
+} // namespace xls
+} // namespace oox
diff --git a/oox/source/xls/excelchartconverter.cxx b/oox/source/xls/excelchartconverter.cxx
index 96d00d1a2ec4..5c63ee5ee701 100644
--- a/oox/source/xls/excelchartconverter.cxx
+++ b/oox/source/xls/excelchartconverter.cxx
@@ -31,6 +31,7 @@
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/chart2/data/XDataProvider.hpp>
#include <com/sun/star/chart2/data/XDataReceiver.hpp>
+#include "oox/core/filterbase.hxx"
#include "oox/drawingml/chart/datasourcemodel.hxx"
#include "oox/helper/containerhelper.hxx"
#include "oox/xls/formulaparser.hxx"
@@ -65,8 +66,7 @@ void ExcelChartConverter::createDataProvider( const Reference< XChartDocument >&
try
{
Reference< XDataReceiver > xDataRec( rxChartDoc, UNO_QUERY_THROW );
- Reference< XMultiServiceFactory > xFactory( getDocument(), UNO_QUERY_THROW );
- Reference< XDataProvider > xDataProv( xFactory->createInstance(
+ Reference< XDataProvider > xDataProv( getBaseFilter().getModelFactory()->createInstance(
CREATE_OUSTRING( "com.sun.star.chart2.data.DataProvider" ) ), UNO_QUERY_THROW );
xDataRec->attachDataProvider( xDataProv );
}
@@ -86,13 +86,12 @@ Reference< XDataSequence > ExcelChartConverter::createDataSequence(
{
// parse the formula string, create a token sequence
FormulaParser& rParser = getFormulaParser();
- TokensFormulaContext aContext( true, true );
- aContext.setBaseAddress( CellAddress( getCurrentSheetIndex(), 0, 0 ) );
- rParser.importFormula( aContext, rDataSeq.maFormula );
+ CellAddress aBaseAddr( getCurrentSheetIndex(), 0, 0 );
+ ApiTokenSequence aTokens = rParser.importFormula( aBaseAddr, rDataSeq.maFormula );
// create a range list from the token sequence
ApiCellRangeList aRanges;
- rParser.extractCellRangeList( aRanges, aContext.getTokens(), false );
+ rParser.extractCellRangeList( aRanges, aTokens, false );
aRangeRep = rParser.generateApiRangeListString( aRanges );
}
else if( !rDataSeq.maData.empty() )
diff --git a/oox/source/xls/excelfilter.cxx b/oox/source/xls/excelfilter.cxx
index 5683fd55c14b..9dd3c9f979fc 100644
--- a/oox/source/xls/excelfilter.cxx
+++ b/oox/source/xls/excelfilter.cxx
@@ -57,29 +57,29 @@ using ::oox::drawingml::table::TableStyleListPtr;
// ============================================================================
ExcelFilterBase::ExcelFilterBase() :
- mpData( 0 )
+ mpBookGlob( 0 )
{
}
ExcelFilterBase::~ExcelFilterBase()
{
- OSL_ENSURE( !mpData, "ExcelFilterBase::~ExcelFilterBase - workbook data not cleared" );
+ OSL_ENSURE( !mpBookGlob, "ExcelFilterBase::~ExcelFilterBase - workbook data not cleared" );
}
-void ExcelFilterBase::registerWorkbookData( WorkbookData& rData )
+void ExcelFilterBase::registerWorkbookGlobals( WorkbookGlobals& rBookGlob )
{
- mpData = &rData;
+ mpBookGlob = &rBookGlob;
}
-WorkbookData& ExcelFilterBase::getWorkbookData() const
+WorkbookGlobals& ExcelFilterBase::getWorkbookGlobals() const
{
- OSL_ENSURE( mpData, "ExcelFilterBase::getWorkbookData - missing workbook data" );
- return *mpData;
+ OSL_ENSURE( mpBookGlob, "ExcelFilterBase::getWorkbookGlobals - missing workbook data" );
+ return *mpBookGlob;
}
-void ExcelFilterBase::unregisterWorkbookData()
+void ExcelFilterBase::unregisterWorkbookGlobals()
{
- mpData = 0;
+ mpBookGlob = 0;
}
// ============================================================================
@@ -126,8 +126,11 @@ bool ExcelFilter::importDocument() throw()
if( aWorkbookPath.getLength() == 0 )
return false;
- WorkbookHelperRoot aHelper( *this );
- if( aHelper.isValid() && importFragment( new WorkbookFragment( aHelper, aWorkbookPath ) ) )
+ /* Construct the WorkbookGlobals object referred to by every instance of
+ the class WorkbookHelper, and execute the import filter by constructing
+ an instance of WorkbookFragment and loading the file. */
+ WorkbookGlobalsRef xBookGlob = WorkbookHelper::constructGlobals( *this );
+ if ( xBookGlob.get() && importFragment( new WorkbookFragment( *xBookGlob, aWorkbookPath ) ) )
{
importDocumentProperties();
return true;
@@ -142,7 +145,7 @@ bool ExcelFilter::exportDocument() throw()
const ::oox::drawingml::Theme* ExcelFilter::getCurrentTheme() const
{
- return &WorkbookHelper( getWorkbookData() ).getTheme();
+ return &WorkbookHelper( getWorkbookGlobals() ).getTheme();
}
::oox::vml::Drawing* ExcelFilter::getVmlDrawing()
@@ -157,12 +160,12 @@ const TableStyleListPtr ExcelFilter::getTableStyles()
::oox::drawingml::chart::ChartConverter& ExcelFilter::getChartConverter()
{
- return WorkbookHelper( getWorkbookData() ).getChartConverter();
+ return WorkbookHelper( getWorkbookGlobals() ).getChartConverter();
}
GraphicHelper* ExcelFilter::implCreateGraphicHelper() const
{
- return new ExcelGraphicHelper( getWorkbookData() );
+ return new ExcelGraphicHelper( getWorkbookGlobals() );
}
::oox::ole::VbaProject* ExcelFilter::implCreateVbaProject() const
@@ -258,8 +261,11 @@ bool ExcelBiffFilter::importDocument() throw()
if( eBiff == BIFF_UNKNOWN )
return false;
- WorkbookHelperRoot aHelper( *this, eBiff );
- return aHelper.isValid() && BiffWorkbookFragment( aHelper, aWorkbookName ).importFragment();
+ /* Construct the WorkbookGlobals object referred to by every instance of
+ the class WorkbookHelper, and execute the import filter by constructing
+ an instance of BiffWorkbookFragment and loading the file. */
+ WorkbookGlobalsRef xBookGlob = WorkbookHelper::constructGlobals( *this, eBiff );
+ return xBookGlob.get() && BiffWorkbookFragment( *xBookGlob, aWorkbookName ).importFragment();
}
bool ExcelBiffFilter::exportDocument() throw()
@@ -269,7 +275,7 @@ bool ExcelBiffFilter::exportDocument() throw()
GraphicHelper* ExcelBiffFilter::implCreateGraphicHelper() const
{
- return new ExcelGraphicHelper( getWorkbookData() );
+ return new ExcelGraphicHelper( getWorkbookGlobals() );
}
::oox::ole::VbaProject* ExcelBiffFilter::implCreateVbaProject() const
@@ -322,11 +328,16 @@ bool ExcelVbaProjectFilter::importDocument() throw()
if( !xVbaPrjStrg || !xVbaPrjStrg->isStorage() )
return false;
- WorkbookHelperRoot aHelper( *this, eBiff );
+ /* Construct the WorkbookGlobals object referred to by every instance of
+ the class WorkbookHelper. */
+ WorkbookGlobalsRef xBookGlob = WorkbookHelper::constructGlobals( *this, eBiff );
+ if( !xBookGlob.get() )
+ return false;
+
// set palette colors passed in service constructor
Any aPalette = getArgument( CREATE_OUSTRING( "ColorPalette" ) );
- aHelper.getStyles().importPalette( aPalette );
- // import the VBA project
+ WorkbookHelper( *xBookGlob ).getStyles().importPalette( aPalette );
+ // import the VBA project (getVbaProject() implemented in base class)
getVbaProject().importVbaProject( *xVbaPrjStrg, getGraphicHelper() );
return true;
}
diff --git a/oox/source/xls/excelhandlers.cxx b/oox/source/xls/excelhandlers.cxx
index 19169398d0a0..a2019edef585 100644
--- a/oox/source/xls/excelhandlers.cxx
+++ b/oox/source/xls/excelhandlers.cxx
@@ -52,17 +52,10 @@ WorkbookFragmentBase::WorkbookFragmentBase(
// ============================================================================
-WorksheetFragmentBase::WorksheetFragmentBase( const WorkbookHelper& rHelper,
- const OUString& rFragmentPath, const ISegmentProgressBarRef& rxProgressBar, WorksheetType eSheetType, sal_Int16 nSheet ) :
- FragmentHandler2( rHelper.getOoxFilter(), rFragmentPath ),
- WorksheetHelperRoot( rHelper, rxProgressBar, eSheetType, nSheet )
-{
-}
-
WorksheetFragmentBase::WorksheetFragmentBase(
const WorksheetHelper& rHelper, const OUString& rFragmentPath ) :
FragmentHandler2( rHelper.getOoxFilter(), rFragmentPath ),
- WorksheetHelperRoot( rHelper )
+ WorksheetHelper( rHelper )
{
}
@@ -82,14 +75,8 @@ BiffWorkbookContextBase::BiffWorkbookContextBase( const WorkbookHelper& rHelper
// ----------------------------------------------------------------------------
-BiffWorksheetContextBase::BiffWorksheetContextBase( const WorkbookHelper& rHelper,
- const ISegmentProgressBarRef& rxProgressBar, WorksheetType eSheetType, sal_Int16 nSheet ) :
- WorksheetHelperRoot( rHelper, rxProgressBar, eSheetType, nSheet )
-{
-}
-
BiffWorksheetContextBase::BiffWorksheetContextBase( const WorksheetHelper& rHelper ) :
- WorksheetHelperRoot( rHelper )
+ WorksheetHelper( rHelper )
{
}
@@ -104,17 +91,33 @@ const sal_uInt16 BIFF_BOF_CHART = 0x0020; /// BIFF2-BIFF8 chart sh
const sal_uInt16 BIFF_BOF_MACRO = 0x0040; /// BIFF4-BIFF8 macro sheet.
const sal_uInt16 BIFF_BOF_WORKSPACE = 0x0100; /// BIFF3-BIFF8 workspace.
-BiffFragmentType lclStartFragment( BiffInputStream& rStrm, BiffType eBiff )
+} // namespace
+
+// ----------------------------------------------------------------------------
+
+BiffFragmentHandler::BiffFragmentHandler( const FilterBase& rFilter, const OUString& rStrmName )
+{
+ // do not automatically close the root stream (indicated by empty stream name)
+ bool bRootStrm = rStrmName.getLength() == 0;
+ mxXInStrm.reset( new BinaryXInputStream( rFilter.openInputStream( rStrmName ), !bRootStrm ) );
+ mxBiffStrm.reset( new BiffInputStream( *mxXInStrm ) );
+}
+
+BiffFragmentHandler::~BiffFragmentHandler()
+{
+}
+
+BiffFragmentType BiffFragmentHandler::startFragment( BiffType eBiff )
{
BiffFragmentType eFragment = BIFF_FRAGMENT_UNKNOWN;
/* #i23425# Don't rely on BOF record ID to read BOF contents, but on
the detected BIFF version. */
- if( BiffHelper::isBofRecord( rStrm ) )
+ if( mxBiffStrm->startNextRecord() && BiffHelper::isBofRecord( *mxBiffStrm ) )
{
// BOF is always written unencrypted
- rStrm.enableDecoder( false );
- rStrm.skip( 2 );
- sal_uInt16 nType = rStrm.readuInt16();
+ mxBiffStrm->enableDecoder( false );
+ mxBiffStrm->skip( 2 );
+ sal_uInt16 nType = mxBiffStrm->readuInt16();
// decide which fragment types are valid for current BIFF version
switch( eBiff )
@@ -167,32 +170,6 @@ BiffFragmentType lclStartFragment( BiffInputStream& rStrm, BiffType eBiff )
return eFragment;
}
-} // namespace
-
-// ----------------------------------------------------------------------------
-
-BiffFragmentHandler::BiffFragmentHandler( const FilterBase& rFilter, const OUString& rStrmName )
-{
- // do not automatically close the root stream (indicated by empty stream name)
- bool bRootStrm = rStrmName.getLength() == 0;
- mxXInStrm.reset( new BinaryXInputStream( rFilter.openInputStream( rStrmName ), !bRootStrm ) );
- mxBiffStrm.reset( new BiffInputStream( *mxXInStrm ) );
-}
-
-BiffFragmentHandler::~BiffFragmentHandler()
-{
-}
-
-BiffFragmentType BiffFragmentHandler::startFragment( BiffType eBiff )
-{
- return mxBiffStrm->startNextRecord() ? lclStartFragment( *mxBiffStrm, eBiff ) : BIFF_FRAGMENT_UNKNOWN;
-}
-
-BiffFragmentType BiffFragmentHandler::startFragment( BiffType eBiff, sal_Int64 nRecHandle )
-{
- return mxBiffStrm->startRecordByHandle( nRecHandle ) ? lclStartFragment( *mxBiffStrm, eBiff ) : BIFF_FRAGMENT_UNKNOWN;
-}
-
bool BiffFragmentHandler::skipFragment()
{
while( mxBiffStrm->startNextRecord() && (mxBiffStrm->getRecId() != BIFF_ID_EOF) )
@@ -201,7 +178,7 @@ bool BiffFragmentHandler::skipFragment()
return !mxBiffStrm->isEof() && (mxBiffStrm->getRecId() == BIFF_ID_EOF);
}
-// ----------------------------------------------------------------------------
+// ============================================================================
BiffWorkbookFragmentBase::BiffWorkbookFragmentBase( const WorkbookHelper& rHelper, const OUString& rStrmName, bool bCloneDecoder ) :
BiffFragmentHandler( rHelper.getBaseFilter(), rStrmName ),
@@ -213,18 +190,16 @@ BiffWorkbookFragmentBase::BiffWorkbookFragmentBase( const WorkbookHelper& rHelpe
// ----------------------------------------------------------------------------
-BiffWorksheetFragmentBase::BiffWorksheetFragmentBase( const BiffWorkbookFragmentBase& rParent,
- const ISegmentProgressBarRef& rxProgressBar, WorksheetType eSheetType, sal_Int16 nSheet ) :
+BiffWorksheetFragmentBase::BiffWorksheetFragmentBase( const WorksheetHelper& rHelper, const BiffWorkbookFragmentBase& rParent ) :
BiffFragmentHandler( rParent ),
- WorksheetHelperRoot( rParent, rxProgressBar, eSheetType, nSheet )
+ WorksheetHelper( rHelper )
{
}
// ----------------------------------------------------------------------------
-BiffSkipWorksheetFragment::BiffSkipWorksheetFragment( const BiffWorkbookFragmentBase& rParent,
- const ISegmentProgressBarRef& rxProgressBar, sal_Int16 nSheet ) :
- BiffWorksheetFragmentBase( rParent, rxProgressBar, SHEETTYPE_EMPTYSHEET, nSheet )
+BiffSkipWorksheetFragment::BiffSkipWorksheetFragment( const WorksheetHelper& rHelper, const BiffWorkbookFragmentBase& rParent ) :
+ BiffWorksheetFragmentBase( rHelper, rParent )
{
}
diff --git a/oox/source/xls/externallinkbuffer.cxx b/oox/source/xls/externallinkbuffer.cxx
index de8ae0dcdd63..df5eccff2bf8 100644
--- a/oox/source/xls/externallinkbuffer.cxx
+++ b/oox/source/xls/externallinkbuffer.cxx
@@ -243,9 +243,8 @@ void ExternalName::importExternalName( BiffInputStream& rStrm )
// cell references to other internal sheets are stored in hidden external names
if( bHiddenRef && (getBiff() == BIFF4) && isWorkbookFile() )
{
- TokensFormulaContext aContext( true, true );
- importBiffFormula( aContext, mrParentLink.getCalcSheetIndex(), rStrm );
- extractReference( aContext.getTokens() );
+ ApiTokenSequence aTokens = importBiffFormula( mrParentLink.getCalcSheetIndex(), rStrm );
+ extractReference( aTokens );
}
break;
@@ -253,9 +252,8 @@ void ExternalName::importExternalName( BiffInputStream& rStrm )
// cell references to other documents are stored in hidden external names
if( bHiddenRef )
{
- TokensFormulaContext aContext( true, true );
- importBiffFormula( aContext, 0, rStrm );
- extractExternalReference( aContext.getTokens() );
+ ApiTokenSequence aTokens = importBiffFormula( 0, rStrm );
+ extractExternalReference( aTokens );
}
break;
diff --git a/oox/source/xls/formulabase.cxx b/oox/source/xls/formulabase.cxx
index 6f4be0d023e5..abdfbf3ba1bb 100644
--- a/oox/source/xls/formulabase.cxx
+++ b/oox/source/xls/formulabase.cxx
@@ -40,7 +40,6 @@
#include <com/sun/star/sheet/FormulaMapGroupSpecialOffset.hpp>
#include <com/sun/star/sheet/XFormulaOpCodeMapper.hpp>
#include <com/sun/star/sheet/XFormulaParser.hpp>
-#include <com/sun/star/sheet/XFormulaTokens.hpp>
#include <rtl/strbuf.hxx>
#include <rtl/ustrbuf.hxx>
#include "oox/core/filterbase.hxx"
@@ -228,8 +227,10 @@ const sal_uInt16 FUNCFLAG_MACROCMD = 0x0080; /// Function is a macro-
const sal_uInt16 FUNCFLAG_ALWAYSVAR = 0x0100; /// Function is always represented by a tFuncVar token.
const sal_uInt16 FUNCFLAG_PARAMPAIRS = 0x0200; /// Optional parameters are expected to appear in pairs.
-const sal_uInt16 FUNCFLAG_FUNCLIBMASK = 0xF000; /// Mask for function library bits.
-const sal_uInt16 FUNCFLAG_EUROTOOL = 0x1000; /// Function is part of the EuroTool add-in.
+/// Converts a function library index (value of enum FunctionLibraryType) to function flags.
+#define FUNCLIB_TO_FUNCFLAGS( funclib_index ) static_cast< sal_uInt16 >( static_cast< sal_uInt8 >( funclib_index ) << 12 )
+/// Extracts a function library index (value of enum FunctionLibraryType) from function flags.
+#define FUNCFLAGS_TO_FUNCLIB( func_flags ) extractValue< FunctionLibraryType >( func_flags, 12, 4 )
typedef ::boost::shared_ptr< FunctionInfo > FunctionInfoRef;
@@ -299,7 +300,9 @@ static const FunctionData saFuncTableBiff2[] =
{ "DOLLAR", "DOLLAR", 13, 13, 1, 2, V, { VR }, 0 },
{ "FIXED", "FIXED", 14, 14, 1, 2, V, { VR, VR, C }, 0 },
{ "SIN", "SIN", 15, 15, 1, 1, V, { VR }, 0 },
+ { "CSC", "SIN", 15, 15, 1, 1, V, { VR }, FUNCFLAG_EXPORTONLY },
{ "COS", "COS", 16, 16, 1, 1, V, { VR }, 0 },
+ { "SEC", "COS", 16, 16, 1, 1, V, { VR }, FUNCFLAG_EXPORTONLY },
{ "TAN", "TAN", 17, 17, 1, 1, V, { VR }, 0 },
{ "COT", "TAN", 17, 17, 1, 1, V, { VR }, FUNCFLAG_EXPORTONLY },
{ "ATAN", "ATAN", 18, 18, 1, 1, V, { VR }, 0 },
@@ -459,7 +462,9 @@ static const FunctionData saFuncTableBiff3[] =
{ "MEDIAN", "MEDIAN", 227, 227, 1, MX, V, { RX }, 0 },
{ "SUMPRODUCT", "SUMPRODUCT", 228, 228, 1, MX, V, { VA }, 0 },
{ "SINH", "SINH", 229, 229, 1, 1, V, { VR }, 0 },
+ { "CSCH", "SINH", 229, 229, 1, 1, V, { VR }, FUNCFLAG_EXPORTONLY },
{ "COSH", "COSH", 230, 230, 1, 1, V, { VR }, 0 },
+ { "SECH", "COSH", 230, 230, 1, 1, V, { VR }, FUNCFLAG_EXPORTONLY },
{ "TANH", "TANH", 231, 231, 1, 1, V, { VR }, 0 },
{ "COTH", "TANH", 231, 231, 1, 1, V, { VR }, FUNCFLAG_EXPORTONLY },
{ "ASINH", "ASINH", 232, 232, 1, 1, V, { VR }, 0 },
@@ -675,7 +680,7 @@ static const FunctionData saFuncTableBiff5[] =
// *** EuroTool add-in ***
- { "EUROCONVERT", "EUROCONVERT", NOID, NOID, 3, 5, V, { VR }, FUNCFLAG_EUROTOOL },
+ { "EUROCONVERT", "EUROCONVERT", NOID, NOID, 3, 5, V, { VR }, FUNCLIB_TO_FUNCFLAGS( FUNCLIB_EUROTOOL ) },
// *** macro sheet commands ***
@@ -912,12 +917,7 @@ void FunctionProviderImpl::initFunc( const FunctionData& rFuncData, sal_uInt8 nM
xFuncInfo->maBiffMacroName = CREATE_OUSTRING( "_xlfnodf." ) + xFuncInfo->maOdfFuncName;
}
- switch( rFuncData.mnFlags & FUNCFLAG_FUNCLIBMASK )
- {
- case FUNCFLAG_EUROTOOL: xFuncInfo->meFuncLibType = FUNCLIB_EUROTOOL; break;
- default: xFuncInfo->meFuncLibType = FUNCLIB_UNKNOWN;
- }
-
+ xFuncInfo->meFuncLibType = FUNCFLAGS_TO_FUNCLIB( rFuncData.mnFlags );
xFuncInfo->mnApiOpCode = -1;
xFuncInfo->mnBiff12FuncId = rFuncData.mnBiff12FuncId;
xFuncInfo->mnBiffFuncId = rFuncData.mnBiffFuncId;
@@ -1025,7 +1025,7 @@ struct OpCodeProviderImpl : public ApiOpCodes
explicit OpCodeProviderImpl(
const FunctionInfoVector& rFuncInfos,
- const Reference< XMultiServiceFactory >& rxFactory );
+ const Reference< XMultiServiceFactory >& rxModelFactory );
private:
typedef ::std::map< OUString, ApiToken > ApiTokenMap;
@@ -1047,11 +1047,11 @@ private:
// ----------------------------------------------------------------------------
OpCodeProviderImpl::OpCodeProviderImpl( const FunctionInfoVector& rFuncInfos,
- const Reference< XMultiServiceFactory >& rxFactory )
+ const Reference< XMultiServiceFactory >& rxModelFactory )
{
- if( rxFactory.is() ) try
+ if( rxModelFactory.is() ) try
{
- Reference< XFormulaOpCodeMapper > xMapper( rxFactory->createInstance(
+ Reference< XFormulaOpCodeMapper > xMapper( rxModelFactory->createInstance(
CREATE_OUSTRING( "com.sun.star.sheet.FormulaOpCodeMapper" ) ), UNO_QUERY_THROW );
// op-codes provided as attributes
@@ -1295,10 +1295,10 @@ bool OpCodeProviderImpl::initFuncOpCodes( const ApiTokenMap& rIntFuncTokenMap, c
// ----------------------------------------------------------------------------
-OpCodeProvider::OpCodeProvider( const Reference< XMultiServiceFactory >& rxFactory,
+OpCodeProvider::OpCodeProvider( const Reference< XMultiServiceFactory >& rxModelFactory,
FilterType eFilter, BiffType eBiff, bool bImportFilter ) :
FunctionProvider( eFilter, eBiff, bImportFilter ),
- mxOpCodeImpl( new OpCodeProviderImpl( getFuncs(), rxFactory ) )
+ mxOpCodeImpl( new OpCodeProviderImpl( getFuncs(), rxModelFactory ) )
{
}
@@ -1333,12 +1333,12 @@ Sequence< FormulaOpCodeMapEntry > OpCodeProvider::getOoxParserMap() const
// API formula parser wrapper =================================================
ApiParserWrapper::ApiParserWrapper(
- const Reference< XMultiServiceFactory >& rxFactory, const OpCodeProvider& rOpCodeProv ) :
+ const Reference< XMultiServiceFactory >& rxModelFactory, const OpCodeProvider& rOpCodeProv ) :
OpCodeProvider( rOpCodeProv )
{
- if( rxFactory.is() ) try
+ if( rxModelFactory.is() ) try
{
- mxParser.set( rxFactory->createInstance( CREATE_OUSTRING( "com.sun.star.sheet.FormulaParser" ) ), UNO_QUERY_THROW );
+ mxParser.set( rxModelFactory->createInstance( CREATE_OUSTRING( "com.sun.star.sheet.FormulaParser" ) ), UNO_QUERY_THROW );
}
catch( Exception& )
{
@@ -1364,51 +1364,6 @@ ApiTokenSequence ApiParserWrapper::parseFormula( const OUString& rFormula, const
return aTokenSeq;
}
-// formula contexts ===========================================================
-
-FormulaContext::FormulaContext( bool bRelativeAsOffset, bool b2dRefsAs3dRefs, bool bAllowNulChars ) :
- maBaseAddress( 0, 0, 0 ),
- mbRelativeAsOffset( bRelativeAsOffset ),
- mb2dRefsAs3dRefs( b2dRefsAs3dRefs ),
- mbAllowNulChars( bAllowNulChars )
-{
-}
-
-FormulaContext::~FormulaContext()
-{
-}
-
-void FormulaContext::setSharedFormula( const CellAddress& )
-{
-}
-
-// ----------------------------------------------------------------------------
-
-TokensFormulaContext::TokensFormulaContext( bool bRelativeAsOffset, bool b2dRefsAs3dRefs, bool bAllowNulChars ) :
- FormulaContext( bRelativeAsOffset, b2dRefsAs3dRefs, bAllowNulChars )
-{
-}
-
-void TokensFormulaContext::setTokens( const ApiTokenSequence& rTokens )
-{
- maTokens = rTokens;
-}
-
-// ----------------------------------------------------------------------------
-
-SimpleFormulaContext::SimpleFormulaContext( const Reference< XFormulaTokens >& rxTokens,
- bool bRelativeAsOffset, bool b2dRefsAs3dRefs, bool bAllowNulChars ) :
- FormulaContext( bRelativeAsOffset, b2dRefsAs3dRefs, bAllowNulChars ),
- mxTokens( rxTokens )
-{
- OSL_ENSURE( mxTokens.is(), "SimpleFormulaContext::SimpleFormulaContext - missing XFormulaTokens interface" );
-}
-
-void SimpleFormulaContext::setTokens( const ApiTokenSequence& rTokens )
-{
- mxTokens->setTokens( rTokens );
-}
-
// formula parser/printer base class for filters ==============================
namespace {
@@ -1481,7 +1436,7 @@ TokenToRangeListState lclProcessClose( sal_Int32& ornParenLevel )
// ----------------------------------------------------------------------------
FormulaProcessorBase::FormulaProcessorBase( const WorkbookHelper& rHelper ) :
- OpCodeProvider( rHelper.getDocumentFactory(), rHelper.getFilterType(), rHelper.getBiff(), rHelper.getBaseFilter().isImportFilter() ),
+ OpCodeProvider( rHelper.getBaseFilter().getModelFactory(), rHelper.getFilterType(), rHelper.getBiff(), rHelper.getBaseFilter().isImportFilter() ),
ApiOpCodes( getOpCodes() ),
WorkbookHelper( rHelper )
{
@@ -1706,6 +1661,12 @@ bool FormulaProcessorBase::extractString( OUString& orString, const ApiTokenSequ
return aTokenIt.is() && (aTokenIt->OpCode == OPCODE_PUSH) && (aTokenIt->Data >>= orString) && !(++aTokenIt).is();
}
+bool FormulaProcessorBase::extractSpecialTokenInfo( ApiSpecialTokenInfo& orTokenInfo, const ApiTokenSequence& rTokens ) const
+{
+ ApiTokenIterator aTokenIt( rTokens, OPCODE_SPACES, true );
+ return aTokenIt.is() && (aTokenIt->OpCode == OPCODE_BAD) && (aTokenIt->Data >>= orTokenInfo);
+}
+
void FormulaProcessorBase::convertStringToStringList(
ApiTokenSequence& orTokens, sal_Unicode cStringSep, bool bTrimLeadingSpaces ) const
{
diff --git a/oox/source/xls/formulaparser.cxx b/oox/source/xls/formulaparser.cxx
index 2543ef6dc910..688c45b1cf3a 100644
--- a/oox/source/xls/formulaparser.cxx
+++ b/oox/source/xls/formulaparser.cxx
@@ -120,7 +120,6 @@ const FunctionInfo* FormulaFinalizer::getFunctionInfo( ApiToken& orFuncToken )
// no success - return null
return 0;
-
}
const FunctionInfo* FormulaFinalizer::getExternCallInfo( ApiToken& orFuncToken, const ApiToken& rECToken )
@@ -242,17 +241,29 @@ const ApiToken* FormulaFinalizer::processParameters(
if( !aParamInfoIt.isExcelOnlyParam() )
{
- // replace empty second and third parameter in IF function with zeros
- if( (pRealFuncInfo->mnBiff12FuncId == BIFF_FUNC_IF) && ((nParam == 1) || (nParam == 2)) && bIsEmpty )
+ // handle empty parameters
+ if( bIsEmpty )
{
- maTokens.append< double >( OPCODE_PUSH, 0.0 );
- bIsEmpty = false;
+ // append leading space tokens from original token array
+ while( (pParamBegin < pParamEnd) && (pParamBegin->OpCode == OPCODE_SPACES) )
+ maTokens.push_back( *pParamBegin++ );
+ // add default values for some empty parameters, or the OPCODE_MISSING token
+ appendEmptyParameter( *pRealFuncInfo, nParam );
+ // reset bIsEmpty flag, if something has been appended in appendEmptyParameter()
+ bIsEmpty = maTokens.back().OpCode == OPCODE_MISSING;
+ // skip OPCODE_MISSING token in the original token array
+ OSL_ENSURE( (pParamBegin == pParamEnd) || (pParamBegin->OpCode == OPCODE_MISSING), "FormulaFinalizer::processParameters - OPCODE_MISSING expected" );
+ if( pParamBegin < pParamEnd ) ++pParamBegin;
+ // append trailing space tokens from original token array
+ while( (pParamBegin < pParamEnd) && (pParamBegin->OpCode == OPCODE_SPACES) )
+ maTokens.push_back( *pParamBegin++ );
}
else
{
- // process all tokens of the parameter
+ // if parameter is not empty, process all tokens of the parameter
processTokens( pParamBegin, pParamEnd );
}
+
// append parameter separator token
maTokens.append( OPCODE_SEP );
}
@@ -359,6 +370,25 @@ const ApiToken* FormulaFinalizer::findParameters( ParameterPosVector& rParams,
return (pToken < pTokenEnd) ? (pToken + 1) : pTokenEnd;
}
+void FormulaFinalizer::appendEmptyParameter( const FunctionInfo& rFuncInfo, size_t nParam )
+{
+ // remeber old size of the token array
+ size_t nTokenArraySize = maTokens.size();
+
+ switch( rFuncInfo.mnBiff12FuncId )
+ {
+ case BIFF_FUNC_IF:
+ if( (nParam == 1) || (nParam == 2) )
+ maTokens.append< double >( OPCODE_PUSH, 0.0 );
+ break;
+ default:;
+ }
+
+ // if no token has been added, append a OPCODE_MISSING token
+ if( nTokenArraySize == maTokens.size() )
+ maTokens.append( OPCODE_MISSING );
+}
+
void FormulaFinalizer::appendCalcOnlyParameter( const FunctionInfo& rFuncInfo, size_t nParam )
{
(void)nParam; // prevent 'unused' warning
@@ -411,27 +441,23 @@ class FormulaParserImpl : public FormulaFinalizer, public WorkbookHelper
public:
explicit FormulaParserImpl( const FormulaParser& rParent );
- /** Converts an XML formula string. */
- virtual void importOoxFormula(
- FormulaContext& rContext,
+ /** Converts an OOXML formula string. */
+ virtual ApiTokenSequence importOoxFormula(
+ const CellAddress& rBaseAddress,
const OUString& rFormulaString );
/** Imports and converts a BIFF12 token array from the passed stream. */
- virtual void importBiff12Formula(
- FormulaContext& rContext,
+ virtual ApiTokenSequence importBiff12Formula(
+ const CellAddress& rBaseAddress,
+ FormulaType eType,
SequenceInputStream& rStrm );
/** Imports and converts a BIFF2-BIFF8 token array from the passed stream. */
- virtual void importBiffFormula(
- FormulaContext& rContext,
+ virtual ApiTokenSequence importBiffFormula(
+ const CellAddress& rBaseAddress,
+ FormulaType eType,
BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize );
- /** Finalizes the passed token array after import (e.g. adjusts function
- parameters) and sets the formula using the passed context. */
- void setFormula(
- FormulaContext& rContext,
- const ApiTokenSequence& rTokens );
-
/** Tries to resolve the passed ref-id to an OLE target URL. */
OUString resolveOleTarget( sal_Int32 nRefId, bool bUseRefSheets ) const;
@@ -439,18 +465,10 @@ protected:
typedef ::std::pair< sal_Int32, bool > WhiteSpace;
typedef ::std::vector< WhiteSpace > WhiteSpaceVec;
- /** Sets the current formula context used for import. */
- inline FormulaContext& getFormulaContext() const { return *mpContext; }
-
- /** Sets the current formula context used for import. */
- void initializeImport( FormulaContext& rContext );
- /** Finalizes the passed token array after import. */
- void finalizeImport( const ApiTokenSequence& rTokens );
+ /** Initializes the formula parser before importing a formula. */
+ void initializeImport( const CellAddress& rBaseAddress, FormulaType eType );
/** Finalizes the internal token storage after import. */
- void finalizeImport();
-
- /** Inserts a shared formula using the current formula context and passed base address. */
- void setSharedFormula( const BinAddress& rBaseAddr );
+ ApiTokenSequence finalizeImport();
// token array ------------------------------------------------------------
@@ -513,6 +531,7 @@ protected:
bool pushExternalFuncOperand( const FunctionInfo& rFuncInfo );
bool pushDdeLinkOperand( const OUString& rDdeServer, const OUString& rDdeTopic, const OUString& rDdeItem );
bool pushExternalNameOperand( const ExternalNameRef& rxExtName, const ExternalLink& rExtLink );
+ bool pushSpecialTokenOperand( const BinAddress& rBaseAddr, bool bTable );
bool pushUnaryPreOperator( sal_Int32 nOpCode );
bool pushUnaryPostOperator( sal_Int32 nOpCode );
@@ -546,6 +565,12 @@ protected:
const sal_Int32 mnMaxXlsCol; /// Maximum column index in imported document.
const sal_Int32 mnMaxXlsRow; /// Maximum row index in imported document.
+ CellAddress maBaseAddr; /// Base address for relative references.
+ bool mbRelativeAsOffset; /// True = relative row/column index is (signed) offset, false = explicit index.
+ bool mb2dRefsAs3dRefs; /// True = convert all 2D references to 3D references in sheet specified by base address.
+ bool mbSpecialTokens; /// True = special handling for tExp and tTbl tokens, false = exit with error.
+ bool mbAllowNulChars; /// True = keep NUL characters in string tokens.
+
private:
typedef ::std::vector< size_t > SizeTypeVector;
@@ -555,7 +580,6 @@ private:
WhiteSpaceVec maLeadingSpaces; /// List of whitespaces before next token.
WhiteSpaceVec maOpeningSpaces; /// List of whitespaces before opening parenthesis.
WhiteSpaceVec maClosingSpaces; /// List of whitespaces before closing parenthesis.
- FormulaContext* mpContext; /// Current formula context.
};
// ----------------------------------------------------------------------------
@@ -567,7 +591,9 @@ FormulaParserImpl::FormulaParserImpl( const FormulaParser& rParent ) :
mnMaxApiRow( rParent.getAddressConverter().getMaxApiAddress().Row ),
mnMaxXlsCol( rParent.getAddressConverter().getMaxXlsAddress().Column ),
mnMaxXlsRow( rParent.getAddressConverter().getMaxXlsAddress().Row ),
- mpContext( 0 )
+ mbRelativeAsOffset( false ),
+ mb2dRefsAs3dRefs( false ),
+ mbAllowNulChars( false )
{
// reserve enough space to make resize(), push_back() etc. cheap
maTokenStorage.reserve( 0x2000 );
@@ -578,25 +604,22 @@ FormulaParserImpl::FormulaParserImpl( const FormulaParser& rParent ) :
maClosingSpaces.reserve( 256 );
}
-void FormulaParserImpl::importOoxFormula( FormulaContext&, const OUString& )
+ApiTokenSequence FormulaParserImpl::importOoxFormula( const CellAddress&, const OUString& )
{
OSL_FAIL( "FormulaParserImpl::importOoxFormula - not implemented" );
+ return ApiTokenSequence();
}
-void FormulaParserImpl::importBiff12Formula( FormulaContext&, SequenceInputStream& )
+ApiTokenSequence FormulaParserImpl::importBiff12Formula( const CellAddress&, FormulaType, SequenceInputStream& )
{
- OSL_FAIL( "FormulaParserImpl::importOobFormula - not implemented" );
+ OSL_FAIL( "FormulaParserImpl::importBiff12Formula - not implemented" );
+ return ApiTokenSequence();
}
-void FormulaParserImpl::importBiffFormula( FormulaContext&, BiffInputStream&, const sal_uInt16* )
+ApiTokenSequence FormulaParserImpl::importBiffFormula( const CellAddress&, FormulaType, BiffInputStream&, const sal_uInt16* )
{
OSL_FAIL( "FormulaParserImpl::importBiffFormula - not implemented" );
-}
-
-void FormulaParserImpl::setFormula( FormulaContext& rContext, const ApiTokenSequence& rTokens )
-{
- initializeImport( rContext );
- finalizeImport( rTokens );
+ return ApiTokenSequence();
}
OUString FormulaParserImpl::resolveOleTarget( sal_Int32 nRefId, bool bUseRefSheets ) const
@@ -608,22 +631,41 @@ OUString FormulaParserImpl::resolveOleTarget( sal_Int32 nRefId, bool bUseRefShee
return OUString();
}
-void FormulaParserImpl::initializeImport( FormulaContext& rContext )
+void FormulaParserImpl::initializeImport( const CellAddress& rBaseAddr, FormulaType eType )
{
+ maBaseAddr = rBaseAddr;
+ mbRelativeAsOffset = mb2dRefsAs3dRefs = mbSpecialTokens = mbAllowNulChars = false;
+ switch( eType )
+ {
+ case FORMULATYPE_CELL:
+ mbSpecialTokens = true;
+ break;
+ case FORMULATYPE_ARRAY:
+ break;
+ case FORMULATYPE_SHAREDFORMULA:
+ mbRelativeAsOffset = true;
+ break;
+ case FORMULATYPE_CONDFORMAT:
+ mbRelativeAsOffset = true;
+ break;
+ case FORMULATYPE_VALIDATION:
+ mbRelativeAsOffset = true;
+ // enable NUL characters in BIFF import, string list is single tStr token with NUL separators
+ mbAllowNulChars = getFilterType() == FILTER_BIFF;
+ break;
+ case FORMULATYPE_DEFINEDNAME:
+ mbRelativeAsOffset = true;
+ // BIFF2-BIFF4: convert 2D referebces to absolute 3D references
+ mb2dRefsAs3dRefs = (getFilterType() == FILTER_BIFF) && (getBiff() <= BIFF4);
+ break;
+ }
+
maTokenStorage.clear();
maTokenIndexes.clear();
maOperandSizeStack.clear();
- mpContext = &rContext;
}
-void FormulaParserImpl::finalizeImport( const ApiTokenSequence& rTokens )
-{
- ApiTokenSequence aFinalTokens = finalizeTokenArray( rTokens );
- if( aFinalTokens.hasElements() )
- mpContext->setTokens( aFinalTokens );
-}
-
-void FormulaParserImpl::finalizeImport()
+ApiTokenSequence FormulaParserImpl::finalizeImport()
{
ApiTokenSequence aTokens( static_cast< sal_Int32 >( maTokenIndexes.size() ) );
if( aTokens.hasElements() )
@@ -632,14 +674,7 @@ void FormulaParserImpl::finalizeImport()
for( SizeTypeVector::const_iterator aIt = maTokenIndexes.begin(), aEnd = maTokenIndexes.end(); aIt != aEnd; ++aIt, ++pToken )
*pToken = maTokenStorage[ *aIt ];
}
- finalizeImport( aTokens );
-}
-
-void FormulaParserImpl::setSharedFormula( const BinAddress& rBaseAddr )
-{
- CellAddress aApiBaseAddr;
- if( getAddressConverter().convertToCellAddress( aApiBaseAddr, rBaseAddr, mpContext->getBaseAddress().Sheet, false ) )
- mpContext->setSharedFormula( aApiBaseAddr );
+ return finalizeTokenArray( aTokens );
}
// token array ----------------------------------------------------------------
@@ -989,7 +1024,7 @@ bool FormulaParserImpl::pushNlrOperand( const BinSingleRef2d& rRef )
bool FormulaParserImpl::pushEmbeddedRefOperand( const DefinedNameBase& rName, bool bPushBadToken )
{
- Any aRefAny = rName.getReference( mpContext->getBaseAddress() );
+ Any aRefAny = rName.getReference( maBaseAddr );
if( aRefAny.hasValue() )
return pushAnyOperand( aRefAny, OPCODE_PUSH );
if( bPushBadToken && (rName.getModelName().getLength() > 0) && (rName.getModelName()[ 0 ] >= ' ') )
@@ -1059,6 +1094,13 @@ bool FormulaParserImpl::pushExternalNameOperand( const ExternalNameRef& rxExtNam
return pushBiffErrorOperand( BIFF_ERR_NAME );
}
+bool FormulaParserImpl::pushSpecialTokenOperand( const BinAddress& rBaseAddr, bool bTable )
+{
+ CellAddress aBaseAddr( maBaseAddr.Sheet, rBaseAddr.mnCol, rBaseAddr.mnRow );
+ ApiSpecialTokenInfo aTokenInfo( aBaseAddr, bTable );
+ return mbSpecialTokens && (getFormulaSize() == 0) && pushValueOperand( aTokenInfo, OPCODE_BAD );
+}
+
bool FormulaParserImpl::pushUnaryPreOperator( sal_Int32 nOpCode )
{
return pushUnaryPreOperatorToken( nOpCode, &maLeadingSpaces ) && resetSpaces();
@@ -1093,15 +1135,15 @@ bool FormulaParserImpl::pushFunctionOperator( const FunctionInfo& rFuncInfo, siz
void FormulaParserImpl::initReference2d( SingleReference& orApiRef ) const
{
- if( mpContext->is2dRefsAs3dRefs() )
+ if( mb2dRefsAs3dRefs )
{
- initReference3d( orApiRef, mpContext->getBaseAddress().Sheet, false );
+ initReference3d( orApiRef, maBaseAddr.Sheet, false );
}
else
{
orApiRef.Flags = SHEET_RELATIVE;
// #i10184# absolute sheet index needed for relative references in shared formulas
- orApiRef.Sheet = mpContext->getBaseAddress().Sheet;
+ orApiRef.Sheet = maBaseAddr.Sheet;
orApiRef.RelativeSheet = 0;
}
}
@@ -1146,9 +1188,9 @@ void FormulaParserImpl::convertReference( SingleReference& orApiRef, const BinSi
if( !bRelativeAsOffset )
{
if( rRef.mbColRel )
- orApiRef.RelativeColumn -= mpContext->getBaseAddress().Column;
+ orApiRef.RelativeColumn -= maBaseAddr.Column;
if( rRef.mbRowRel )
- orApiRef.RelativeRow -= mpContext->getBaseAddress().Row;
+ orApiRef.RelativeRow -= maBaseAddr.Row;
}
}
}
@@ -1235,12 +1277,13 @@ class OoxFormulaParserImpl : public FormulaParserImpl
public:
explicit OoxFormulaParserImpl( const FormulaParser& rParent );
- virtual void importOoxFormula(
- FormulaContext& rContext,
+ virtual ApiTokenSequence importOoxFormula(
+ const CellAddress& rBaseAddr,
const OUString& rFormulaString );
- virtual void importBiff12Formula(
- FormulaContext& rContext,
+ virtual ApiTokenSequence importBiff12Formula(
+ const CellAddress& rBaseAddr,
+ FormulaType eType,
SequenceInputStream& rStrm );
private:
@@ -1284,26 +1327,25 @@ private:
OoxFormulaParserImpl::OoxFormulaParserImpl( const FormulaParser& rParent ) :
FormulaParserImpl( rParent ),
- maApiParser( rParent.getDocumentFactory(), rParent ),
+ maApiParser( rParent.getBaseFilter().getModelFactory(), rParent ),
mnAddDataPos( 0 ),
mbNeedExtRefs( true )
{
}
-void OoxFormulaParserImpl::importOoxFormula( FormulaContext& rContext, const OUString& rFormulaString )
+ApiTokenSequence OoxFormulaParserImpl::importOoxFormula( const CellAddress& rBaseAddr, const OUString& rFormulaString )
{
if( mbNeedExtRefs )
{
maApiParser.getParserProperties().setProperty( PROP_ExternalLinks, getExternalLinks().getLinkInfos() );
mbNeedExtRefs = false;
}
- initializeImport( rContext );
- finalizeImport( maApiParser.parseFormula( rFormulaString, rContext.getBaseAddress() ) );
+ return finalizeTokenArray( maApiParser.parseFormula( rFormulaString, rBaseAddr ) );
}
-void OoxFormulaParserImpl::importBiff12Formula( FormulaContext& rContext, SequenceInputStream& rStrm )
+ApiTokenSequence OoxFormulaParserImpl::importBiff12Formula( const CellAddress& rBaseAddr, FormulaType eType, SequenceInputStream& rStrm )
{
- initializeImport( rContext );
+ initializeImport( rBaseAddr, eType );
sal_Int32 nFmlaSize = rStrm.readInt32();
sal_Int64 nFmlaPos = rStrm.tell();
@@ -1316,7 +1358,7 @@ void OoxFormulaParserImpl::importBiff12Formula( FormulaContext& rContext, Sequen
rStrm.seek( nFmlaPos );
bool bOk = (nFmlaSize >= 0) && (nAddDataSize >= 0);
- bool bRelativeAsOffset = getFormulaContext().isRelativeAsOffset();
+ bool bRelativeAsOffset = mbRelativeAsOffset;
while( bOk && !rStrm.isEof() && (rStrm.tell() < nFmlaEndPos) )
{
@@ -1393,12 +1435,16 @@ void OoxFormulaParserImpl::importBiff12Formula( FormulaContext& rContext, Sequen
}
// build and finalize the token sequence
+ ApiTokenSequence aFinalTokens;
if( bOk && (rStrm.tell() == nFmlaEndPos) && (mnAddDataPos == nAddDataEndPos) )
- finalizeImport();
+ aFinalTokens = finalizeImport();
// seek behind token array
if( (nFmlaSize >= 0) && (nAddDataSize >= 0) )
rStrm.seek( nAddDataEndPos );
+
+ // return the final token sequence
+ return aFinalTokens;
}
// import token contents and create API formula token -------------------------
@@ -1542,7 +1588,7 @@ bool OoxFormulaParserImpl::importTableToken( SequenceInputStream& rStrm )
}
else if( bThisRow )
{
- nStartRow = nEndRow = getFormulaContext().getBaseAddress().Row - xTable->getRange().StartRow;
+ nStartRow = nEndRow = maBaseAddr.Row - xTable->getRange().StartRow;
bFixedHeight = true;
}
else
@@ -1721,9 +1767,7 @@ bool OoxFormulaParserImpl::importExpToken( SequenceInputStream& rStrm )
swapStreamPosition( rStrm );
rStrm >> aBaseAddr.mnCol;
swapStreamPosition( rStrm );
- setSharedFormula( aBaseAddr );
- // formula has been set, exit parser by returning false
- return false;
+ return pushSpecialTokenOperand( aBaseAddr, false );
}
LinkSheetRange OoxFormulaParserImpl::readSheetRange( SequenceInputStream& rStrm )
@@ -1838,8 +1882,9 @@ class BiffFormulaParserImpl : public FormulaParserImpl
public:
explicit BiffFormulaParserImpl( const FormulaParser& rParent );
- virtual void importBiffFormula(
- FormulaContext& rContext,
+ virtual ApiTokenSequence importBiffFormula(
+ const CellAddress& rBaseAddr,
+ FormulaType eType,
BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize );
private:
@@ -1875,7 +1920,8 @@ private:
bool importFuncVarToken2( BiffInputStream& rStrm );
bool importFuncVarToken4( BiffInputStream& rStrm );
bool importFuncCEToken( BiffInputStream& rStrm );
- bool importExpToken5( BiffInputStream& rStrm );
+ bool importExpToken( BiffInputStream& rStrm );
+ bool importTblToken( BiffInputStream& rStrm );
bool importNlrAddrToken( BiffInputStream& rStrm, bool bRow );
bool importNlrRangeToken( BiffInputStream& rStrm );
@@ -1924,7 +1970,6 @@ private:
ImportTokenFunc mpImportFuncToken; /// Pointer to tFunc import function (function with fixed parameter count).
ImportTokenFunc mpImportFuncVarToken; /// Pointer to tFuncVar import function (function with variable parameter count).
ImportTokenFunc mpImportFuncCEToken; /// Pointer to tFuncCE import function (command macro call).
- ImportTokenFunc mpImportExpToken; /// Pointer to tExp import function (array/shared formula).
sal_Int64 mnAddDataPos; /// Current stream position for additional data (tArray, tMemArea, tNlr).
sal_Int32 mnCurrRefId; /// Current ref-id from tSheet token (BIFF2-BIFF4 only).
sal_uInt16 mnAttrDataSize; /// Size of one tAttr data element.
@@ -1958,7 +2003,6 @@ BiffFormulaParserImpl::BiffFormulaParserImpl( const FormulaParser& rParent ) :
mpImportFuncToken = &BiffFormulaParserImpl::importFuncToken2;
mpImportFuncVarToken = &BiffFormulaParserImpl::importFuncVarToken2;
mpImportFuncCEToken = &BiffFormulaParserImpl::importFuncCEToken;
- mpImportExpToken = &BiffFormulaParserImpl::importTokenNotAvailable;
mnAttrDataSize = 1;
mnArraySize = 6;
mnNameSize = 5;
@@ -1980,7 +2024,6 @@ BiffFormulaParserImpl::BiffFormulaParserImpl( const FormulaParser& rParent ) :
mpImportFuncToken = &BiffFormulaParserImpl::importFuncToken2;
mpImportFuncVarToken = &BiffFormulaParserImpl::importFuncVarToken2;
mpImportFuncCEToken = &BiffFormulaParserImpl::importFuncCEToken;
- mpImportExpToken = &BiffFormulaParserImpl::importTokenNotAvailable;
mnAttrDataSize = 2;
mnArraySize = 7;
mnNameSize = 8;
@@ -2002,7 +2045,6 @@ BiffFormulaParserImpl::BiffFormulaParserImpl( const FormulaParser& rParent ) :
mpImportFuncToken = &BiffFormulaParserImpl::importFuncToken4;
mpImportFuncVarToken = &BiffFormulaParserImpl::importFuncVarToken4;
mpImportFuncCEToken = &BiffFormulaParserImpl::importTokenNotAvailable;
- mpImportExpToken = &BiffFormulaParserImpl::importTokenNotAvailable;
mnAttrDataSize = 2;
mnArraySize = 7;
mnNameSize = 8;
@@ -2024,7 +2066,6 @@ BiffFormulaParserImpl::BiffFormulaParserImpl( const FormulaParser& rParent ) :
mpImportFuncToken = &BiffFormulaParserImpl::importFuncToken4;
mpImportFuncVarToken = &BiffFormulaParserImpl::importFuncVarToken4;
mpImportFuncCEToken = &BiffFormulaParserImpl::importTokenNotAvailable;
- mpImportExpToken = &BiffFormulaParserImpl::importExpToken5;
mnAttrDataSize = 2;
mnArraySize = 7;
mnNameSize = 12;
@@ -2046,7 +2087,6 @@ BiffFormulaParserImpl::BiffFormulaParserImpl( const FormulaParser& rParent ) :
mpImportFuncToken = &BiffFormulaParserImpl::importFuncToken4;
mpImportFuncVarToken = &BiffFormulaParserImpl::importFuncVarToken4;
mpImportFuncCEToken = &BiffFormulaParserImpl::importTokenNotAvailable;
- mpImportExpToken = &BiffFormulaParserImpl::importExpToken5;
mnAttrDataSize = 2;
mnArraySize = 7;
mnNameSize = 2;
@@ -2058,15 +2098,14 @@ BiffFormulaParserImpl::BiffFormulaParserImpl( const FormulaParser& rParent ) :
}
}
-void BiffFormulaParserImpl::importBiffFormula( FormulaContext& rContext,
- BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize )
+ApiTokenSequence BiffFormulaParserImpl::importBiffFormula( const CellAddress& rBaseAddr,
+ FormulaType eType, BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize )
{
- initializeImport( rContext );
+ initializeImport( rBaseAddr, eType );
mnCurrRefId = 0;
sal_uInt16 nFmlaSize = lclReadFmlaSize( rStrm, getBiff(), pnFmlaSize );
sal_Int64 nEndPos = mnAddDataPos = rStrm.tell() + nFmlaSize;
- bool bRelativeAsOffset = getFormulaContext().isRelativeAsOffset();
bool bOk = true;
while( bOk && !rStrm.isEof() && (rStrm.tell() < nEndPos) )
@@ -2084,8 +2123,8 @@ void BiffFormulaParserImpl::importBiffFormula( FormulaContext& rContext,
// base tokens
switch( nBaseId )
{
- case BIFF_TOKID_EXP: bOk = (this->*mpImportExpToken)( rStrm ); break;
- case BIFF_TOKID_TBL: bOk = false; /* multiple op. will be set externally */ break;
+ case BIFF_TOKID_EXP: bOk = importExpToken( rStrm ); break;
+ case BIFF_TOKID_TBL: bOk = importTblToken( rStrm ); break;
case BIFF_TOKID_ADD: bOk = pushBinaryOperator( OPCODE_ADD ); break;
case BIFF_TOKID_SUB: bOk = pushBinaryOperator( OPCODE_SUB ); break;
case BIFF_TOKID_MUL: bOk = pushBinaryOperator( OPCODE_MULT ); break;
@@ -2141,10 +2180,10 @@ void BiffFormulaParserImpl::importBiffFormula( FormulaContext& rContext,
case BIFF_TOKID_MEMNOMEMN: bOk = importMemFuncToken( rStrm ); break;
case BIFF_TOKID_FUNCCE: bOk = (this->*mpImportFuncCEToken)( rStrm ); break;
case BIFF_TOKID_NAMEX: bOk = (this->*mpImportNameXToken)( rStrm ); break;
- case BIFF_TOKID_REF3D: bOk = (this->*mpImportRef3dToken)( rStrm, false, bRelativeAsOffset ); break;
- case BIFF_TOKID_AREA3D: bOk = (this->*mpImportArea3dToken)( rStrm, false, bRelativeAsOffset ); break;
- case BIFF_TOKID_REFERR3D: bOk = (this->*mpImportRef3dToken)( rStrm, true, bRelativeAsOffset ); break;
- case BIFF_TOKID_AREAERR3D: bOk = (this->*mpImportArea3dToken)( rStrm, true, bRelativeAsOffset ); break;
+ case BIFF_TOKID_REF3D: bOk = (this->*mpImportRef3dToken)( rStrm, false, mbRelativeAsOffset ); break;
+ case BIFF_TOKID_AREA3D: bOk = (this->*mpImportArea3dToken)( rStrm, false, mbRelativeAsOffset ); break;
+ case BIFF_TOKID_REFERR3D: bOk = (this->*mpImportRef3dToken)( rStrm, true, mbRelativeAsOffset ); break;
+ case BIFF_TOKID_AREAERR3D: bOk = (this->*mpImportArea3dToken)( rStrm, true, mbRelativeAsOffset ); break;
default: bOk = false;
}
}
@@ -2152,11 +2191,15 @@ void BiffFormulaParserImpl::importBiffFormula( FormulaContext& rContext,
}
// build and finalize the token sequence
+ ApiTokenSequence aFinalTokens;
if( bOk && (rStrm.tell() == nEndPos) )
- finalizeImport();
+ aFinalTokens = finalizeImport();
// seek behind additional token data of tArray, tMemArea, tNlr tokens
rStrm.seek( mnAddDataPos );
+
+ // return the final token sequence
+ return aFinalTokens;
}
// import token contents and create API formula token -------------------------
@@ -2175,13 +2218,13 @@ bool BiffFormulaParserImpl::importRefTokenNotAvailable( BiffInputStream&, bool,
bool BiffFormulaParserImpl::importStrToken2( BiffInputStream& rStrm )
{
- return pushValueOperand( rStrm.readByteStringUC( false, getTextEncoding(), getFormulaContext().isNulCharsAllowed() ) );
+ return pushValueOperand( rStrm.readByteStringUC( false, getTextEncoding(), mbAllowNulChars ) );
}
bool BiffFormulaParserImpl::importStrToken8( BiffInputStream& rStrm )
{
// read flags field for empty strings also
- return pushValueOperand( rStrm.readUniStringBody( rStrm.readuInt8(), getFormulaContext().isNulCharsAllowed() ) );
+ return pushValueOperand( rStrm.readUniStringBody( rStrm.readuInt8(), mbAllowNulChars ) );
}
bool BiffFormulaParserImpl::importAttrToken( BiffInputStream& rStrm )
@@ -2311,7 +2354,6 @@ bool BiffFormulaParserImpl::importArrayToken( BiffInputStream& rStrm )
size_t nOpSize = popOperandSize();
size_t nOldArraySize = getFormulaSize();
bool bBiff8 = getBiff() == BIFF8;
- bool bNulChars = getFormulaContext().isNulCharsAllowed();
// read array size
swapStreamPosition( rStrm );
@@ -2340,8 +2382,8 @@ bool BiffFormulaParserImpl::importArrayToken( BiffInputStream& rStrm )
break;
case BIFF_DATATYPE_STRING:
appendRawToken( OPCODE_PUSH ) <<= bBiff8 ?
- rStrm.readUniString( bNulChars ) :
- rStrm.readByteStringUC( false, getTextEncoding(), bNulChars );
+ rStrm.readUniString( mbAllowNulChars ) :
+ rStrm.readByteStringUC( false, getTextEncoding(), mbAllowNulChars );
break;
case BIFF_DATATYPE_BOOL:
appendRawToken( OPCODE_PUSH ) <<= static_cast< double >( (rStrm.readuInt8() == BIFF_TOK_BOOL_FALSE) ? 0.0 : 1.0 );
@@ -2490,13 +2532,18 @@ bool BiffFormulaParserImpl::importFuncCEToken( BiffInputStream& rStrm )
return pushBiffFunction( nCmdId, nParamCount );
}
-bool BiffFormulaParserImpl::importExpToken5( BiffInputStream& rStrm )
+bool BiffFormulaParserImpl::importExpToken( BiffInputStream& rStrm )
{
BinAddress aBaseAddr;
aBaseAddr.read( rStrm );
- setSharedFormula( aBaseAddr );
- // formula has been set, exit parser by returning false
- return false;
+ return pushSpecialTokenOperand( aBaseAddr, false );
+}
+
+bool BiffFormulaParserImpl::importTblToken( BiffInputStream& rStrm )
+{
+ BinAddress aBaseAddr;
+ aBaseAddr.read( rStrm );
+ return pushSpecialTokenOperand( aBaseAddr, true );
}
bool BiffFormulaParserImpl::importNlrAddrToken( BiffInputStream& rStrm, bool bRow )
@@ -2766,22 +2813,35 @@ FormulaParser::~FormulaParser()
{
}
-void FormulaParser::importFormula( FormulaContext& rContext, const OUString& rFormulaString ) const
+ApiTokenSequence FormulaParser::importFormula( const CellAddress& rBaseAddress, const OUString& rFormulaString ) const
{
- mxImpl->importOoxFormula( rContext, rFormulaString );
+ return mxImpl->importOoxFormula( rBaseAddress, rFormulaString );
}
-void FormulaParser::importFormula( FormulaContext& rContext, SequenceInputStream& rStrm ) const
+ApiTokenSequence FormulaParser::importFormula( const CellAddress& rBaseAddress, FormulaType eType, SequenceInputStream& rStrm ) const
{
- mxImpl->importBiff12Formula( rContext, rStrm );
+ return mxImpl->importBiff12Formula( rBaseAddress, eType, rStrm );
}
-void FormulaParser::importFormula( FormulaContext& rContext, BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize ) const
+ApiTokenSequence FormulaParser::importFormula( const CellAddress& rBaseAddress, FormulaType eType, BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize ) const
{
- mxImpl->importBiffFormula( rContext, rStrm, pnFmlaSize );
+ return mxImpl->importBiffFormula( rBaseAddress, eType, rStrm, pnFmlaSize );
+}
+
+ApiTokenSequence FormulaParser::convertBoolToFormula( bool bValue ) const
+{
+ if( const FunctionInfo* pFuncInfo = getFuncInfoFromBiffFuncId( bValue ? BIFF_FUNC_TRUE : BIFF_FUNC_FALSE ) )
+ {
+ ApiTokenSequence aTokens( 3 );
+ aTokens[ 0 ].OpCode = pFuncInfo->mnApiOpCode;
+ aTokens[ 1 ].OpCode = OPCODE_OPEN;
+ aTokens[ 2 ].OpCode = OPCODE_CLOSE;
+ return aTokens;
+ }
+ return ApiTokenSequence();
}
-void FormulaParser::convertErrorToFormula( FormulaContext& rContext, sal_uInt8 nErrorCode ) const
+ApiTokenSequence FormulaParser::convertErrorToFormula( sal_uInt8 nErrorCode ) const
{
ApiTokenSequence aTokens( 3 );
// HACK: enclose all error codes into an 1x1 matrix
@@ -2789,26 +2849,24 @@ void FormulaParser::convertErrorToFormula( FormulaContext& rContext, sal_uInt8 n
aTokens[ 1 ].OpCode = OPCODE_PUSH;
aTokens[ 1 ].Data <<= BiffHelper::calcDoubleFromError( nErrorCode );
aTokens[ 2 ].OpCode = OPCODE_ARRAY_CLOSE;
- mxImpl->setFormula( rContext, aTokens );
+ return aTokens;
}
-void FormulaParser::convertNameToFormula( FormulaContext& rContext, sal_Int32 nTokenIndex ) const
+ApiTokenSequence FormulaParser::convertNameToFormula( sal_Int32 nTokenIndex ) const
{
- if( nTokenIndex >= 0 )
- {
- ApiTokenSequence aTokens( 1 );
- aTokens[ 0 ].OpCode = OPCODE_NAME;
- aTokens[ 0 ].Data <<= nTokenIndex;
- mxImpl->setFormula( rContext, aTokens );
- }
- else
- convertErrorToFormula( rContext, BIFF_ERR_REF );
+ if( nTokenIndex < 0 )
+ return convertErrorToFormula( BIFF_ERR_REF );
+
+ ApiTokenSequence aTokens( 1 );
+ aTokens[ 0 ].OpCode = OPCODE_NAME;
+ aTokens[ 0 ].Data <<= nTokenIndex;
+ return aTokens;
}
-void FormulaParser::convertNumberToHyperlink( FormulaContext& rContext, const OUString& rUrl, double fValue ) const
+ApiTokenSequence FormulaParser::convertNumberToHyperlink( const OUString& rUrl, double fValue ) const
{
OSL_ENSURE( rUrl.getLength() > 0, "FormulaParser::convertNumberToHyperlink - missing URL" );
- if( const FunctionInfo* pFuncInfo = getFuncInfoFromBiff12FuncId( BIFF_FUNC_HYPERLINK ) )
+ if( const FunctionInfo* pFuncInfo = getFuncInfoFromBiffFuncId( BIFF_FUNC_HYPERLINK ) )
{
ApiTokenSequence aTokens( 6 );
aTokens[ 0 ].OpCode = pFuncInfo->mnApiOpCode;
@@ -2819,8 +2877,9 @@ void FormulaParser::convertNumberToHyperlink( FormulaContext& rContext, const OU
aTokens[ 4 ].OpCode = OPCODE_PUSH;
aTokens[ 4 ].Data <<= fValue;
aTokens[ 5 ].OpCode = OPCODE_CLOSE;
- mxImpl->setFormula( rContext, aTokens );
+ return aTokens;
}
+ return ApiTokenSequence();
}
OUString FormulaParser::importOleTargetLink( const OUString& rFormulaString )
diff --git a/oox/source/xls/numberformatsbuffer.cxx b/oox/source/xls/numberformatsbuffer.cxx
index c2022fa28a26..cde00392917c 100644
--- a/oox/source/xls/numberformatsbuffer.cxx
+++ b/oox/source/xls/numberformatsbuffer.cxx
@@ -1949,7 +1949,7 @@ NumberFormatsBuffer::NumberFormatsBuffer( const WorkbookHelper& rHelper ) :
// get the current locale
try
{
- Reference< XMultiServiceFactory > xConfigProv( getGlobalFactory()->createInstance(
+ Reference< XMultiServiceFactory > xConfigProv( getBaseFilter().getServiceFactory()->createInstance(
CREATE_OUSTRING( "com.sun.star.configuration.ConfigurationProvider" ) ), UNO_QUERY_THROW );
// try user-defined locale setting
diff --git a/oox/source/xls/ooxformulaparser.cxx b/oox/source/xls/ooxformulaparser.cxx
index 5504a33a9dfe..3363a654c4d0 100644
--- a/oox/source/xls/ooxformulaparser.cxx
+++ b/oox/source/xls/ooxformulaparser.cxx
@@ -48,7 +48,7 @@ using ::rtl::OUString;
class OOXMLFormulaParserImpl : private FormulaFinalizer
{
public:
- explicit OOXMLFormulaParserImpl( const Reference< XMultiServiceFactory >& rxFactory );
+ explicit OOXMLFormulaParserImpl( const Reference< XMultiServiceFactory >& rxModelFactory );
Sequence< FormulaToken > parseFormula( const OUString& rFormula, const CellAddress& rReferencePos );
@@ -61,9 +61,9 @@ private:
// ----------------------------------------------------------------------------
-OOXMLFormulaParserImpl::OOXMLFormulaParserImpl( const Reference< XMultiServiceFactory >& rxFactory ) :
- FormulaFinalizer( OpCodeProvider( rxFactory, FILTER_OOXML, BIFF_UNKNOWN, true ) ),
- maApiParser( rxFactory, *this )
+OOXMLFormulaParserImpl::OOXMLFormulaParserImpl( const Reference< XMultiServiceFactory >& rxModelFactory ) :
+ FormulaFinalizer( OpCodeProvider( rxModelFactory, FILTER_OOXML, BIFF_UNKNOWN, true ) ),
+ maApiParser( rxModelFactory, *this )
{
}
@@ -116,7 +116,7 @@ const FunctionInfo* OOXMLFormulaParserImpl::resolveBadFuncName( const OUString&
class OOXMLFormulaPrinterImpl : public OpCodeProvider
{
public:
- explicit OOXMLFormulaPrinterImpl( const Reference< XMultiServiceFactory >& rxFactory );
+ explicit OOXMLFormulaPrinterImpl( const Reference< XMultiServiceFactory >& rxModelFactory );
private:
ApiParserWrapper maApiParser;
@@ -124,9 +124,9 @@ private:
// ----------------------------------------------------------------------------
-OOXMLFormulaPrinterImpl::OOXMLFormulaPrinterImpl( const Reference< XMultiServiceFactory >& rxFactory ) :
- OpCodeProvider( rxFactory, FILTER_OOXML, BIFF_UNKNOWN, false ),
- maApiParser( rxFactory, *this )
+OOXMLFormulaPrinterImpl::OOXMLFormulaPrinterImpl( const Reference< XMultiServiceFactory >& rxModelFactory ) :
+ OpCodeProvider( rxModelFactory, FILTER_OOXML, BIFF_UNKNOWN, false ),
+ maApiParser( rxModelFactory, *this )
{
}
@@ -203,8 +203,8 @@ Sequence< FormulaToken > SAL_CALL OOXMLFormulaParser::parseFormula(
{
if( !mxParserImpl )
{
- Reference< XMultiServiceFactory > xFactory( mxComponent, UNO_QUERY_THROW );
- mxParserImpl.reset( new OOXMLFormulaParserImpl( xFactory ) );
+ Reference< XMultiServiceFactory > xModelFactory( mxComponent, UNO_QUERY_THROW );
+ mxParserImpl.reset( new OOXMLFormulaParserImpl( xModelFactory ) );
}
return mxParserImpl->parseFormula( rFormula, rReferencePos );
}
diff --git a/oox/source/xls/pagesettings.cxx b/oox/source/xls/pagesettings.cxx
index 8fc018d60f5b..9082c7342af6 100644
--- a/oox/source/xls/pagesettings.cxx
+++ b/oox/source/xls/pagesettings.cxx
@@ -918,8 +918,7 @@ Reference< XTextContent > HeaderFooterParser::createField( const OUString& rServ
Reference< XTextContent > xContent;
try
{
- Reference< XMultiServiceFactory > xFactory( getDocument(), UNO_QUERY_THROW );
- xContent.set( xFactory->createInstance( rServiceName ), UNO_QUERY_THROW );
+ xContent.set( getBaseFilter().getModelFactory()->createInstance( rServiceName ), UNO_QUERY_THROW );
}
catch( Exception& )
{
diff --git a/oox/source/xls/pivotcachebuffer.cxx b/oox/source/xls/pivotcachebuffer.cxx
index d8b8083831f6..49652dafe34a 100644
--- a/oox/source/xls/pivotcachebuffer.cxx
+++ b/oox/source/xls/pivotcachebuffer.cxx
@@ -35,7 +35,6 @@
#include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
#include <com/sun/star/sheet/DataPilotFieldGroupInfo.hpp>
#include <com/sun/star/sheet/XDataPilotFieldGrouping.hpp>
-#include <com/sun/star/table/XCell.hpp>
#include <rtl/ustrbuf.hxx>
#include "oox/core/filterbase.hxx"
#include "oox/helper/attributelist.hxx"
@@ -45,6 +44,7 @@
#include "oox/xls/defnamesbuffer.hxx"
#include "oox/xls/excelhandlers.hxx"
#include "oox/xls/pivotcachefragment.hxx"
+#include "oox/xls/sheetdatabuffer.hxx"
#include "oox/xls/tablebuffer.hxx"
#include "oox/xls/unitconverter.hxx"
#include "oox/xls/worksheetbuffer.hxx"
@@ -738,7 +738,7 @@ void PivotCacheField::importPCDFRangePr( BiffInputStream& rStrm )
void PivotCacheField::importPCDFDiscretePr( BiffInputStream& rStrm )
{
- sal_Int32 nCount = static_cast< sal_Int32 >( rStrm.getLength() / 2 );
+ sal_Int32 nCount = static_cast< sal_Int32 >( rStrm.size() / 2 );
for( sal_Int32 nIndex = 0; !rStrm.isEof() && (nIndex < nCount); ++nIndex )
maDiscreteItems.push_back( rStrm.readuInt16() );
}
@@ -937,7 +937,9 @@ OUString PivotCacheField::createParentGroupField( const Reference< XDataPilotFie
void PivotCacheField::writeSourceHeaderCell( WorksheetHelper& rSheetHelper, sal_Int32 nCol, sal_Int32 nRow ) const
{
- rSheetHelper.setStringCell( rSheetHelper.getCell( CellAddress( rSheetHelper.getSheetIndex(), nCol, nRow ) ), maFieldModel.maName );
+ CellModel aModel;
+ aModel.maCellAddr = CellAddress( rSheetHelper.getSheetIndex(), nCol, nRow );
+ rSheetHelper.getSheetData().setStringCell( aModel, maFieldModel.maName );
}
void PivotCacheField::writeSourceDataCell( WorksheetHelper& rSheetHelper, sal_Int32 nCol, sal_Int32 nRow, const PivotCacheItem& rItem ) const
@@ -983,15 +985,17 @@ void PivotCacheField::writeItemToSourceDataCell( WorksheetHelper& rSheetHelper,
{
if( rItem.getType() != XML_m )
{
- Reference< XCell > xCell = rSheetHelper.getCell( CellAddress( rSheetHelper.getSheetIndex(), nCol, nRow ) );
- if( xCell.is() ) switch( rItem.getType() )
+ CellModel aModel;
+ aModel.maCellAddr = CellAddress( rSheetHelper.getSheetIndex(), nCol, nRow );
+ SheetDataBuffer& rSheetData = rSheetHelper.getSheetData();
+ switch( rItem.getType() )
{
- case XML_s: rSheetHelper.setStringCell( xCell, rItem.getValue().get< OUString >() ); break;
- case XML_n: xCell->setValue( rItem.getValue().get< double >() ); break;
- case XML_i: xCell->setValue( rItem.getValue().get< sal_Int16 >() ); break;
- case XML_d: rSheetHelper.setDateTimeCell( xCell, rItem.getValue().get< DateTime >() ); break;
- case XML_b: rSheetHelper.setBooleanCell( xCell, rItem.getValue().get< bool >() ); break;
- case XML_e: rSheetHelper.setErrorCell( xCell, static_cast< sal_uInt8 >( rItem.getValue().get< sal_Int32 >() ) ); break;
+ case XML_s: rSheetData.setStringCell( aModel, rItem.getValue().get< OUString >() ); break;
+ case XML_n: rSheetData.setValueCell( aModel, rItem.getValue().get< double >() ); break;
+ case XML_i: rSheetData.setValueCell( aModel, rItem.getValue().get< sal_Int16 >() ); break;
+ case XML_d: rSheetData.setDateTimeCell( aModel, rItem.getValue().get< DateTime >() ); break;
+ case XML_b: rSheetData.setBooleanCell( aModel, rItem.getValue().get< bool >() ); break;
+ case XML_e: rSheetData.setErrorCell( aModel, static_cast< sal_uInt8 >( rItem.getValue().get< sal_Int32 >() ) ); break;
default: OSL_FAIL( "PivotCacheField::writeItemToSourceDataCell - unexpected item data type" );
}
}
@@ -1043,6 +1047,7 @@ PCWorksheetSourceModel::PCWorksheetSourceModel()
PivotCache::PivotCache( const WorkbookHelper& rHelper ) :
WorkbookHelper( rHelper ),
+ mnCurrRow( -1 ),
mbValidSource( false ),
mbDummySheet( false )
{
@@ -1275,34 +1280,39 @@ void PivotCache::writeSourceHeaderCells( WorksheetHelper& rSheetHelper ) const
sal_Int32 nCol = maSheetSrcModel.maRange.StartColumn;
sal_Int32 nMaxCol = getAddressConverter().getMaxApiAddress().Column;
sal_Int32 nRow = maSheetSrcModel.maRange.StartRow;
+ mnCurrRow = -1;
+ updateSourceDataRow( rSheetHelper, nRow );
for( PivotCacheFieldVector::const_iterator aIt = maDatabaseFields.begin(), aEnd = maDatabaseFields.end(); (aIt != aEnd) && (nCol <= nMaxCol); ++aIt, ++nCol )
(*aIt)->writeSourceHeaderCell( rSheetHelper, nCol, nRow );
}
-void PivotCache::writeSourceDataCell( WorksheetHelper& rSheetHelper, sal_Int32 nCol, sal_Int32 nRow, const PivotCacheItem& rItem ) const
+void PivotCache::writeSourceDataCell( WorksheetHelper& rSheetHelper, sal_Int32 nColIdx, sal_Int32 nRowIdx, const PivotCacheItem& rItem ) const
{
- OSL_ENSURE( (0 <= nCol) && (nCol <= maSheetSrcModel.maRange.EndColumn - maSheetSrcModel.maRange.StartColumn), "PivotCache::writeSourceDataCell - invalid column index" );
- OSL_ENSURE( (0 < nRow) && (nRow <= maSheetSrcModel.maRange.EndRow - maSheetSrcModel.maRange.StartRow), "PivotCache::writeSourceDataCell - invalid row index" );
- if( const PivotCacheField* pCacheField = maDatabaseFields.get( nCol ).get() )
- pCacheField->writeSourceDataCell( rSheetHelper, maSheetSrcModel.maRange.StartColumn + nCol, maSheetSrcModel.maRange.StartRow + nRow, rItem );
+ sal_Int32 nCol = maSheetSrcModel.maRange.StartColumn + nColIdx;
+ OSL_ENSURE( (maSheetSrcModel.maRange.StartColumn <= nCol) && (nCol <= maSheetSrcModel.maRange.EndColumn), "PivotCache::writeSourceDataCell - invalid column index" );
+ sal_Int32 nRow = maSheetSrcModel.maRange.StartRow + nRowIdx;
+ OSL_ENSURE( (maSheetSrcModel.maRange.StartRow < nRow) && (nRow <= maSheetSrcModel.maRange.EndRow), "PivotCache::writeSourceDataCell - invalid row index" );
+ updateSourceDataRow( rSheetHelper, nRow );
+ if( const PivotCacheField* pCacheField = maDatabaseFields.get( nColIdx ).get() )
+ pCacheField->writeSourceDataCell( rSheetHelper, nCol, nRow, rItem );
}
-void PivotCache::importPCRecord( SequenceInputStream& rStrm, WorksheetHelper& rSheetHelper, sal_Int32 nRow ) const
+void PivotCache::importPCRecord( SequenceInputStream& rStrm, WorksheetHelper& rSheetHelper, sal_Int32 nRowIdx ) const
{
- OSL_ENSURE( (0 < nRow) && (nRow <= maSheetSrcModel.maRange.EndRow - maSheetSrcModel.maRange.StartRow), "PivotCache::importPCRecord - invalid row index" );
+ sal_Int32 nRow = maSheetSrcModel.maRange.StartRow + nRowIdx;
+ OSL_ENSURE( (maSheetSrcModel.maRange.StartRow < nRow) && (nRow <= maSheetSrcModel.maRange.EndRow), "PivotCache::importPCRecord - invalid row index" );
sal_Int32 nCol = maSheetSrcModel.maRange.StartColumn;
sal_Int32 nMaxCol = getAddressConverter().getMaxApiAddress().Column;
- nRow += maSheetSrcModel.maRange.StartRow;
for( PivotCacheFieldVector::const_iterator aIt = maDatabaseFields.begin(), aEnd = maDatabaseFields.end(); !rStrm.isEof() && (aIt != aEnd) && (nCol <= nMaxCol); ++aIt, ++nCol )
(*aIt)->importPCRecordItem( rStrm, rSheetHelper, nCol, nRow );
}
-void PivotCache::importPCItemIndexList( BiffInputStream& rStrm, WorksheetHelper& rSheetHelper, sal_Int32 nRow ) const
+void PivotCache::importPCItemIndexList( BiffInputStream& rStrm, WorksheetHelper& rSheetHelper, sal_Int32 nRowIdx ) const
{
- OSL_ENSURE( (0 < nRow) && (nRow <= maSheetSrcModel.maRange.EndRow - maSheetSrcModel.maRange.StartRow), "PivotCache::importPCItemIndexList - invalid row index" );
+ sal_Int32 nRow = maSheetSrcModel.maRange.StartRow + nRowIdx;
+ OSL_ENSURE( (maSheetSrcModel.maRange.StartRow < nRow) && (nRow <= maSheetSrcModel.maRange.EndRow), "PivotCache::importPCItemIndexList - invalid row index" );
sal_Int32 nCol = maSheetSrcModel.maRange.StartColumn;
sal_Int32 nMaxCol = getAddressConverter().getMaxApiAddress().Column;
- nRow += maSheetSrcModel.maRange.StartRow;
for( PivotCacheFieldVector::const_iterator aIt = maDatabaseFields.begin(), aEnd = maDatabaseFields.end(); !rStrm.isEof() && (aIt != aEnd) && (nCol <= nMaxCol); ++aIt, ++nCol )
if( (*aIt)->hasSharedItems() )
(*aIt)->importPCItemIndex( rStrm, rSheetHelper, nCol, nRow );
@@ -1416,17 +1426,28 @@ void PivotCache::finalizeExternalSheetSource()
void PivotCache::prepareSourceDataSheet()
{
+ CellRangeAddress& rRange = maSheetSrcModel.maRange;
// data will be inserted in top-left cell, sheet index is still set to 0 (will be set below)
- maSheetSrcModel.maRange.EndColumn -= maSheetSrcModel.maRange.StartColumn;
- maSheetSrcModel.maRange.StartColumn = 0;
- maSheetSrcModel.maRange.EndRow -= maSheetSrcModel.maRange.StartRow;
- maSheetSrcModel.maRange.StartRow = 0;
+ rRange.EndColumn -= rRange.StartColumn;
+ rRange.StartColumn = 0;
+ rRange.EndRow -= rRange.StartRow;
+ rRange.StartRow = 0;
// check range location, do not allow ranges that overflow the sheet partly
- if( getAddressConverter().checkCellRange( maSheetSrcModel.maRange, false, true ) )
+ if( getAddressConverter().checkCellRange( rRange, false, true ) )
{
+ maColSpans.insert( ValueRange( rRange.StartColumn, rRange.EndColumn ) );
OUString aSheetName = CREATE_OUSTRING( "DPCache_" ) + maSheetSrcModel.maSheet;
- maSheetSrcModel.maRange.Sheet = getWorksheets().insertEmptySheet( aSheetName, false );
- mbValidSource = mbDummySheet = maSheetSrcModel.maRange.Sheet >= 0;
+ rRange.Sheet = getWorksheets().insertEmptySheet( aSheetName, false );
+ mbValidSource = mbDummySheet = rRange.Sheet >= 0;
+ }
+}
+
+void PivotCache::updateSourceDataRow( WorksheetHelper& rSheetHelper, sal_Int32 nRow ) const
+{
+ if( mnCurrRow != nRow )
+ {
+ rSheetHelper.getSheetData().setColSpans( nRow, maColSpans );
+ mnCurrRow = nRow;
}
}
diff --git a/oox/source/xls/pivotcachefragment.cxx b/oox/source/xls/pivotcachefragment.cxx
index b0d03674769a..d86a15851735 100644
--- a/oox/source/xls/pivotcachefragment.cxx
+++ b/oox/source/xls/pivotcachefragment.cxx
@@ -209,18 +209,23 @@ void PivotCacheDefinitionFragment::finalizeImport()
{
OUString aRecFragmentPath = getRelations().getFragmentPathFromRelId( mrPivotCache.getRecordsRelId() );
if( aRecFragmentPath.getLength() > 0 )
- importOoxFragment( new PivotCacheRecordsFragment( *this, aRecFragmentPath, mrPivotCache ) );
+ {
+ sal_Int16 nSheet = mrPivotCache.getSourceRange().Sheet;
+ WorksheetGlobalsRef xSheetGlob = WorksheetHelper::constructGlobals( *this, ISegmentProgressBarRef(), SHEETTYPE_WORKSHEET, nSheet );
+ if( xSheetGlob.get() )
+ importOoxFragment( new PivotCacheRecordsFragment( *xSheetGlob, aRecFragmentPath, mrPivotCache ) );
+ }
}
}
// ============================================================================
-PivotCacheRecordsFragment::PivotCacheRecordsFragment( const WorkbookHelper& rHelper,
+PivotCacheRecordsFragment::PivotCacheRecordsFragment( const WorksheetHelper& rHelper,
const OUString& rFragmentPath, const PivotCache& rPivotCache ) :
- WorksheetFragmentBase( rHelper, rFragmentPath, ISegmentProgressBarRef(), SHEETTYPE_WORKSHEET, rPivotCache.getSourceRange().Sheet ),
+ WorksheetFragmentBase( rHelper, rFragmentPath ),
mrPivotCache( rPivotCache ),
- mnCol( 0 ),
- mnRow( 0 ),
+ mnColIdx( 0 ),
+ mnRowIdx( 0 ),
mbInRecord( false )
{
// prepare sheet: insert column header names into top row
@@ -253,8 +258,8 @@ ContextHandlerRef PivotCacheRecordsFragment::onCreateContext( sal_Int32 nElement
case XLS_TOKEN( x ): aItem.readIndex( rAttribs ); break;
default: OSL_FAIL( "OoxPivotCacheRecordsFragment::onCreateContext - unexpected element" );
}
- mrPivotCache.writeSourceDataCell( *this, mnCol, mnRow, aItem );
- ++mnCol;
+ mrPivotCache.writeSourceDataCell( *this, mnColIdx, mnRowIdx, aItem );
+ ++mnColIdx;
}
break;
}
@@ -295,15 +300,15 @@ const RecordInfo* PivotCacheRecordsFragment::getRecordInfos() const
void PivotCacheRecordsFragment::startCacheRecord()
{
- mnCol = 0;
- ++mnRow;
+ mnColIdx = 0;
+ ++mnRowIdx;
mbInRecord = true;
}
void PivotCacheRecordsFragment::importPCRecord( SequenceInputStream& rStrm )
{
startCacheRecord();
- mrPivotCache.importPCRecord( rStrm, *this, mnRow );
+ mrPivotCache.importPCRecord( rStrm, *this, mnRowIdx );
mbInRecord = false;
}
@@ -323,8 +328,8 @@ void PivotCacheRecordsFragment::importPCRecordItem( sal_Int32 nRecId, SequenceIn
case BIFF12_ID_PCITEM_INDEX: aItem.readIndex( rStrm ); break;
default: OSL_FAIL( "OoxPivotCacheRecordsFragment::importPCRecordItem - unexpected record" );
}
- mrPivotCache.writeSourceDataCell( *this, mnCol, mnRow, aItem );
- ++mnCol;
+ mrPivotCache.writeSourceDataCell( *this, mnColIdx, mnRowIdx, aItem );
+ ++mnColIdx;
}
}
@@ -374,10 +379,14 @@ bool BiffPivotCacheFragment::importFragment()
{
/* Last call of lclSeekToPCDField() failed and kept stream position
unchanged. Stream should point to source data table now. */
- BiffPivotCacheRecordsContext aContext( *this, mrPivotCache );
- if( aContext.isValidSheet() )
+ sal_Int16 nSheet = mrPivotCache.getSourceRange().Sheet;
+ WorksheetGlobalsRef xSheetGlob = WorksheetHelper::constructGlobals( *this, ISegmentProgressBarRef(), SHEETTYPE_WORKSHEET, nSheet );
+ if( xSheetGlob.get() )
+ {
+ BiffPivotCacheRecordsContext aContext( *xSheetGlob, mrPivotCache );
while( rStrm.startNextRecord() && (rStrm.getRecId() != BIFF_ID_EOF) )
aContext.importRecord( rStrm );
+ }
}
}
@@ -386,11 +395,11 @@ bool BiffPivotCacheFragment::importFragment()
// ============================================================================
-BiffPivotCacheRecordsContext::BiffPivotCacheRecordsContext( const WorkbookHelper& rHelper, const PivotCache& rPivotCache ) :
- BiffWorksheetContextBase( rHelper, ISegmentProgressBarRef(), SHEETTYPE_WORKSHEET, rPivotCache.getSourceRange().Sheet ),
+BiffPivotCacheRecordsContext::BiffPivotCacheRecordsContext( const WorksheetHelper& rHelper, const PivotCache& rPivotCache ) :
+ BiffWorksheetContextBase( rHelper ),
mrPivotCache( rPivotCache ),
mnColIdx( 0 ),
- mnRow( 0 ),
+ mnRowIdx( 0 ),
mbHasShared( false ),
mbInRow( false )
{
@@ -419,7 +428,7 @@ void BiffPivotCacheRecordsContext::importRecord( BiffInputStream& rStrm )
OSL_ENSURE( mbHasShared, "BiffPivotCacheRecordsContext::importRecord - unexpected PCITEM_INDEXLIST record" );
// PCITEM_INDEXLIST record always in front of a new data row
startNextRow();
- mrPivotCache.importPCItemIndexList( rStrm, *this, mnRow );
+ mrPivotCache.importPCItemIndexList( rStrm, *this, mnRowIdx );
mbInRow = !maUnsharedCols.empty(); // mbInRow remains true, if unshared items are expected
return;
}
@@ -450,14 +459,14 @@ void BiffPivotCacheRecordsContext::importRecord( BiffInputStream& rStrm )
// write the item data to the sheet cell
OSL_ENSURE( mnColIdx < maUnsharedCols.size(), "BiffPivotCacheRecordsContext::importRecord - invalid column index" );
if( mnColIdx < maUnsharedCols.size() )
- mrPivotCache.writeSourceDataCell( *this, maUnsharedCols[ mnColIdx ], mnRow, aItem );
+ mrPivotCache.writeSourceDataCell( *this, maUnsharedCols[ mnColIdx ], mnRowIdx, aItem );
++mnColIdx;
}
void BiffPivotCacheRecordsContext::startNextRow()
{
mnColIdx = 0;
- ++mnRow;
+ ++mnRowIdx;
mbInRow = true;
}
diff --git a/oox/source/xls/richstring.cxx b/oox/source/xls/richstring.cxx
index b9876a660113..6a2bbd9eab1a 100644
--- a/oox/source/xls/richstring.cxx
+++ b/oox/source/xls/richstring.cxx
@@ -53,6 +53,11 @@ namespace {
const sal_uInt8 BIFF12_STRINGFLAG_FONTS = 0x01;
const sal_uInt8 BIFF12_STRINGFLAG_PHONETICS = 0x02;
+inline bool lclNeedsRichTextFormat( const Font* pFont )
+{
+ return pFont && pFont->needsRichTextFormat();
+}
+
} // namespace
// ============================================================================
@@ -87,18 +92,27 @@ void RichStringPortion::finalizeImport()
mxFont = getStyles().getFont( mnFontId );
}
-void RichStringPortion::convert( const Reference< XText >& rxText, sal_Int32 nXfId )
+void RichStringPortion::convert( const Reference< XText >& rxText, const Font* pFont, bool bReplace )
{
- Reference< XTextRange > xRange = rxText->getEnd();
- xRange->setString( maText );
- if( mxFont.get() )
- {
- PropertySet aPropSet( xRange );
- mxFont->writeToPropertySet( aPropSet, FONT_PROPTYPE_TEXT );
- }
- if( const Font* pFont = getStyles().getFontFromCellXf( nXfId ).get() )
+ Reference< XTextRange > xRange;
+ if( bReplace )
+ xRange.set( rxText, UNO_QUERY );
+ else
+ xRange = rxText->getEnd();
+ OSL_ENSURE( xRange.is(), "RichStringPortion::convert - cannot get text range interface" );
+
+ if( xRange.is() )
{
- if( pFont->needsRichTextFormat() )
+ xRange->setString( maText );
+ if( mxFont.get() )
+ {
+ PropertySet aPropSet( xRange );
+ mxFont->writeToPropertySet( aPropSet, FONT_PROPTYPE_TEXT );
+ }
+
+ /* Some font attributes cannot be set to cell formattiing in Calc but
+ require to use rich formatting, e.g. font escapement. */
+ if( lclNeedsRichTextFormat( pFont ) )
{
PropertySet aPropSet( xRange );
pFont->writeToPropertySet( aPropSet, FONT_PROPTYPE_TEXT );
@@ -106,18 +120,15 @@ void RichStringPortion::convert( const Reference< XText >& rxText, sal_Int32 nXf
}
}
-void RichStringPortion::writeFontProperties( const Reference<XText>& rxText, sal_Int32 nXfId ) const
+void RichStringPortion::writeFontProperties( const Reference<XText>& rxText, const Font* pFont ) const
{
PropertySet aPropSet(rxText);
if (mxFont.get())
mxFont->writeToPropertySet(aPropSet, FONT_PROPTYPE_TEXT);
- if (const Font* pFont = getStyles().getFontFromCellXf(nXfId).get())
- {
- if (pFont->needsRichTextFormat())
- pFont->writeToPropertySet(aPropSet, FONT_PROPTYPE_TEXT);
- }
+ if (lclNeedsRichTextFormat(pFont))
+ pFont->writeToPropertySet(aPropSet, FONT_PROPTYPE_TEXT);
}
// ----------------------------------------------------------------------------
@@ -406,7 +417,7 @@ void RichString::importString( SequenceInputStream& rStrm, bool bRich )
{
FontPortionModelList aPortions;
aPortions.importPortions( rStrm );
- createFontPortions( aBaseText, aPortions );
+ createTextPortions( aBaseText, aPortions );
}
else
{
@@ -423,7 +434,12 @@ void RichString::importString( SequenceInputStream& rStrm, bool bRich )
}
}
-void RichString::importByteString( BiffInputStream& rStrm, rtl_TextEncoding eDefaultTextEnc, BiffStringFlags nFlags )
+void RichString::importCharArray( BiffInputStream& rStrm, sal_uInt16 nChars, rtl_TextEncoding eTextEnc )
+{
+ createPortion()->setText( rStrm.readCharArrayUC( nChars, eTextEnc ) );
+}
+
+void RichString::importByteString( BiffInputStream& rStrm, rtl_TextEncoding eTextEnc, BiffStringFlags nFlags )
{
OSL_ENSURE( !getFlag( nFlags, BIFF_STR_KEEPFONTS ), "RichString::importString - keep fonts not implemented" );
OSL_ENSURE( !getFlag( nFlags, static_cast< BiffStringFlags >( ~(BIFF_STR_8BITLENGTH | BIFF_STR_EXTRAFONTS) ) ), "RichString::importByteString - unknown flag" );
@@ -435,11 +451,11 @@ void RichString::importByteString( BiffInputStream& rStrm, rtl_TextEncoding eDef
{
FontPortionModelList aPortions;
aPortions.importPortions( rStrm, false );
- createFontPortions( aBaseText, eDefaultTextEnc, aPortions );
+ createTextPortions( aBaseText, eTextEnc, aPortions );
}
else
{
- createPortion()->setText( OStringToOUString( aBaseText, eDefaultTextEnc ) );
+ createPortion()->setText( OStringToOUString( aBaseText, eTextEnc ) );
}
}
@@ -469,7 +485,7 @@ void RichString::importUniString( BiffInputStream& rStrm, BiffStringFlags nFlags
{
FontPortionModelList aPortions;
aPortions.importPortions( rStrm, nFontCount, BIFF_FONTPORTION_16BIT );
- createFontPortions( aBaseText, aPortions );
+ createTextPortions( aBaseText, aPortions );
}
else
{
@@ -503,33 +519,44 @@ void RichString::importUniString( BiffInputStream& rStrm, BiffStringFlags nFlags
void RichString::finalizeImport()
{
- maFontPortions.forEachMem( &RichStringPortion::finalizeImport );
+ maTextPortions.forEachMem( &RichStringPortion::finalizeImport );
}
-OUString RichString::getPlainText() const
+bool RichString::extractPlainString( OUString& orString, const Font* pFirstPortionFont ) const
{
- OUStringBuffer aBuffer;
- for( PortionVec::const_iterator aIt = maFontPortions.begin(), aEnd = maFontPortions.end(); aIt != aEnd; ++aIt )
- aBuffer.append( (*aIt)->getText() );
- return aBuffer.makeStringAndClear();
+ if( !maPhonPortions.empty() )
+ return false;
+ if( maTextPortions.empty() )
+ {
+ orString = OUString();
+ return true;
+ }
+ if( (maTextPortions.size() == 1) && !maTextPortions.front()->hasFont() && !lclNeedsRichTextFormat( pFirstPortionFont ) )
+ {
+ orString = maTextPortions.front()->getText();
+ return true;
+ }
+ return false;
}
-void RichString::convert( const Reference< XText >& rxText, sal_Int32 nXfId ) const
+void RichString::convert( const Reference< XText >& rxText, const Font* pFirstPortionFont ) const
{
- if (maFontPortions.size() == 1)
+ if (maTextPortions.size() == 1)
{
// Set text directly to the cell when the string has only one portion.
// It's much faster this way.
- RichStringPortion& rPtn = *maFontPortions.front();
+ RichStringPortion& rPtn = *maTextPortions.front();
rxText->setString(rPtn.getText());
- rPtn.writeFontProperties(rxText, nXfId);
+ rPtn.writeFontProperties(rxText, pFirstPortionFont);
return;
}
- for( PortionVec::const_iterator aIt = maFontPortions.begin(), aEnd = maFontPortions.end(); aIt != aEnd; ++aIt )
+ bool bReplace = true;
+ for( PortionVector::const_iterator aIt = maTextPortions.begin(), aEnd = maTextPortions.end(); aIt != aEnd; ++aIt )
{
- (*aIt)->convert( rxText, nXfId );
- nXfId = -1; // use passed XF identifier for first portion only
+ (*aIt)->convert( rxText, pFirstPortionFont, bReplace );
+ pFirstPortionFont = 0; // use passed font for first portion only
+ bReplace = false; // do not replace first portion text with following portions
}
}
@@ -538,7 +565,7 @@ void RichString::convert( const Reference< XText >& rxText, sal_Int32 nXfId ) co
RichStringPortionRef RichString::createPortion()
{
RichStringPortionRef xPortion( new RichStringPortion( *this ) );
- maFontPortions.push_back( xPortion );
+ maTextPortions.push_back( xPortion );
return xPortion;
}
@@ -549,9 +576,9 @@ RichStringPhoneticRef RichString::createPhonetic()
return xPhonetic;
}
-void RichString::createFontPortions( const OString& rText, rtl_TextEncoding eDefaultTextEnc, FontPortionModelList& rPortions )
+void RichString::createTextPortions( const OString& rText, rtl_TextEncoding eTextEnc, FontPortionModelList& rPortions )
{
- maFontPortions.clear();
+ maTextPortions.clear();
sal_Int32 nStrLen = rText.getLength();
if( nStrLen > 0 )
{
@@ -569,8 +596,8 @@ void RichString::createFontPortions( const OString& rText, rtl_TextEncoding eDef
{
// convert byte string to unicode string, using current font encoding
FontRef xFont = getStyles().getFont( aIt->mnFontId );
- rtl_TextEncoding eTextEnc = xFont.get() ? xFont->getFontEncoding() : eDefaultTextEnc;
- OUString aUniStr = OStringToOUString( rText.copy( aIt->mnPos, nPortionLen ), eTextEnc );
+ rtl_TextEncoding eFontEnc = xFont.get() ? xFont->getFontEncoding() : eTextEnc;
+ OUString aUniStr = OStringToOUString( rText.copy( aIt->mnPos, nPortionLen ), eFontEnc );
// create string portion
RichStringPortionRef xPortion = createPortion();
xPortion->setText( aUniStr );
@@ -580,9 +607,9 @@ void RichString::createFontPortions( const OString& rText, rtl_TextEncoding eDef
}
}
-void RichString::createFontPortions( const OUString& rText, FontPortionModelList& rPortions )
+void RichString::createTextPortions( const OUString& rText, FontPortionModelList& rPortions )
{
- maFontPortions.clear();
+ maTextPortions.clear();
sal_Int32 nStrLen = rText.getLength();
if( nStrLen > 0 )
{
diff --git a/oox/source/xls/sharedformulabuffer.cxx b/oox/source/xls/sharedformulabuffer.cxx
index 0135709263ac..b2861800f2dc 100644
--- a/oox/source/xls/sharedformulabuffer.cxx
+++ b/oox/source/xls/sharedformulabuffer.cxx
@@ -26,8 +26,6 @@
*
************************************************************************/
-#include "oox/xls/sharedformulabuffer.hxx"
-
#include <com/sun/star/sheet/XFormulaTokens.hpp>
#include <rtl/ustrbuf.hxx>
#include "oox/helper/propertyset.hxx"
diff --git a/oox/source/xls/sharedstringsbuffer.cxx b/oox/source/xls/sharedstringsbuffer.cxx
index 738b1d7eae27..eee6a2bf8471 100644
--- a/oox/source/xls/sharedstringsbuffer.cxx
+++ b/oox/source/xls/sharedstringsbuffer.cxx
@@ -74,11 +74,9 @@ void SharedStringsBuffer::finalizeImport()
maStrings.forEachMem( &RichString::finalizeImport );
}
-void SharedStringsBuffer::convertString( const Reference< XText >& rxText, sal_Int32 nStringId, sal_Int32 nXfId ) const
+RichStringRef SharedStringsBuffer::getString( sal_Int32 nStringId ) const
{
- if( rxText.is() )
- if( const RichString* pString = maStrings.get( nStringId ).get() )
- pString->convert( rxText, nXfId );
+ return maStrings.get( nStringId );
}
// ============================================================================
diff --git a/oox/source/xls/sheetdatabuffer.cxx b/oox/source/xls/sheetdatabuffer.cxx
new file mode 100755
index 000000000000..8bdcccca10cf
--- /dev/null
+++ b/oox/source/xls/sheetdatabuffer.cxx
@@ -0,0 +1,935 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "oox/xls/sheetdatabuffer.hxx"
+
+#include <algorithm>
+#include <com/sun/star/sheet/XArrayFormulaTokens.hpp>
+#include <com/sun/star/sheet/XCellRangeData.hpp>
+#include <com/sun/star/sheet/XFormulaTokens.hpp>
+#include <com/sun/star/sheet/XMultipleOperation.hpp>
+#include <com/sun/star/table/XCell.hpp>
+#include <com/sun/star/text/XText.hpp>
+#include <com/sun/star/util/DateTime.hpp>
+#include <com/sun/star/util/NumberFormat.hpp>
+#include <com/sun/star/util/XMergeable.hpp>
+#include <com/sun/star/util/XNumberFormatTypes.hpp>
+#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
+#include <rtl/ustrbuf.hxx>
+#include "oox/helper/containerhelper.hxx"
+#include "oox/helper/propertymap.hxx"
+#include "oox/helper/propertyset.hxx"
+#include "oox/token/tokens.hxx"
+#include "oox/xls/addressconverter.hxx"
+#include "oox/xls/biffinputstream.hxx"
+#include "oox/xls/formulaparser.hxx"
+#include "oox/xls/sharedstringsbuffer.hxx"
+#include "oox/xls/unitconverter.hxx"
+
+namespace oox {
+namespace xls {
+
+// ============================================================================
+
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::sheet;
+using namespace ::com::sun::star::table;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::util;
+
+using ::rtl::OUString;
+using ::rtl::OUStringBuffer;
+
+// ============================================================================
+
+CellModel::CellModel() :
+ mnCellType( XML_TOKEN_INVALID ),
+ mnXfId( -1 ),
+ mbShowPhonetic( false )
+{
+}
+
+// ----------------------------------------------------------------------------
+
+CellFormulaModel::CellFormulaModel() :
+ mnFormulaType( XML_TOKEN_INVALID ),
+ mnSharedId( -1 )
+{
+}
+
+bool CellFormulaModel::isValidArrayRef( const CellAddress& rCellAddr )
+{
+ return
+ (maFormulaRef.Sheet == rCellAddr.Sheet) &&
+ (maFormulaRef.StartColumn == rCellAddr.Column) &&
+ (maFormulaRef.StartRow == rCellAddr.Row);
+}
+
+bool CellFormulaModel::isValidSharedRef( const CellAddress& rCellAddr )
+{
+ return
+ (maFormulaRef.Sheet == rCellAddr.Sheet) &&
+ (maFormulaRef.StartColumn <= rCellAddr.Column) && (rCellAddr.Column <= maFormulaRef.EndColumn) &&
+ (maFormulaRef.StartRow <= rCellAddr.Row) && (rCellAddr.Row <= maFormulaRef.EndRow);
+}
+
+// ----------------------------------------------------------------------------
+
+DataTableModel::DataTableModel() :
+ mb2dTable( false ),
+ mbRowTable( false ),
+ mbRef1Deleted( false ),
+ mbRef2Deleted( false )
+{
+}
+
+// ============================================================================
+
+namespace {
+
+const sal_Int32 CELLBLOCK_MAXROWS = 16; /// Number of rows in a cell block.
+
+} // namespace
+
+CellBlock::CellBlock( const WorksheetHelper& rHelper, const ValueRange& rColSpan, sal_Int32 nRow ) :
+ WorksheetHelper( rHelper ),
+ maRange( rHelper.getSheetIndex(), rColSpan.mnFirst, nRow, rColSpan.mnLast, nRow ),
+ mnRowLength( rColSpan.mnLast - rColSpan.mnFirst + 1 ),
+ mnFirstFreeIndex( 0 )
+{
+ maCellArray.realloc( 1 );
+ maCellArray[ 0 ].realloc( mnRowLength );
+ mpCurrCellRow = maCellArray[ 0 ].getArray();
+}
+
+bool CellBlock::isExpandable( const ValueRange& rColSpan ) const
+{
+ return (maRange.StartColumn == rColSpan.mnFirst) && (maRange.EndColumn == rColSpan.mnLast);
+}
+
+bool CellBlock::isBefore( const ValueRange& rColSpan ) const
+{
+ return (maRange.EndColumn < rColSpan.mnLast) ||
+ ((maRange.EndColumn == rColSpan.mnLast) && (maRange.StartColumn != rColSpan.mnFirst));
+}
+
+bool CellBlock::contains( sal_Int32 nCol ) const
+{
+ return (maRange.StartColumn <= nCol) && (nCol <= maRange.EndColumn);
+}
+
+void CellBlock::insertRichString( const CellAddress& rAddress, const RichStringRef& rxString, const Font* pFirstPortionFont )
+{
+ maRichStrings.push_back( RichStringCell( rAddress, rxString, pFirstPortionFont ) );
+}
+
+void CellBlock::startNextRow()
+{
+ // fill last cells in current row with empty strings (placeholder for empty cells)
+ fillUnusedCells( mnRowLength );
+ // flush if the cell block reaches maximum size
+ if( maCellArray.getLength() == CELLBLOCK_MAXROWS )
+ {
+ finalizeImport();
+ maRange.StartRow = ++maRange.EndRow;
+ maCellArray.realloc( 1 );
+ mpCurrCellRow = maCellArray[ 0 ].getArray();
+ }
+ else
+ {
+ // prepare next row
+ ++maRange.EndRow;
+ sal_Int32 nRowCount = maCellArray.getLength();
+ maCellArray.realloc( nRowCount + 1 );
+ maCellArray[ nRowCount ].realloc( mnRowLength );
+ mpCurrCellRow = maCellArray[ nRowCount ].getArray();
+ }
+ mnFirstFreeIndex = 0;
+}
+
+Any& CellBlock::getCellAny( sal_Int32 nCol )
+{
+ OSL_ENSURE( contains( nCol ), "CellBlock::getCellAny - invalid column" );
+ // fill cells before passed column with empty strings (the placeholder for empty cells)
+ sal_Int32 nIndex = nCol - maRange.StartColumn;
+ fillUnusedCells( nIndex );
+ mnFirstFreeIndex = nIndex + 1;
+ return mpCurrCellRow[ nIndex ];
+}
+
+void CellBlock::finalizeImport()
+{
+ // fill last cells in last row with empty strings (placeholder for empty cells)
+ fillUnusedCells( mnRowLength );
+ // insert all buffered cells into the Calc sheet
+ try
+ {
+ Reference< XCellRangeData > xRangeData( getCellRange( maRange ), UNO_QUERY_THROW );
+ xRangeData->setDataArray( maCellArray );
+ }
+ catch( Exception& )
+ {
+ }
+ // insert uncacheable cells separately
+ for( RichStringCellList::const_iterator aIt = maRichStrings.begin(), aEnd = maRichStrings.end(); aIt != aEnd; ++aIt )
+ putRichString( aIt->maCellAddr, *aIt->mxString, aIt->mpFirstPortionFont );
+}
+
+// private --------------------------------------------------------------------
+
+CellBlock::RichStringCell::RichStringCell( const CellAddress& rCellAddr, const RichStringRef& rxString, const Font* pFirstPortionFont ) :
+ maCellAddr( rCellAddr ),
+ mxString( rxString ),
+ mpFirstPortionFont( pFirstPortionFont )
+{
+}
+
+void CellBlock::fillUnusedCells( sal_Int32 nIndex )
+{
+ if( mnFirstFreeIndex < nIndex )
+ {
+ Any* pCellEnd = mpCurrCellRow + nIndex;
+ for( Any* pCell = mpCurrCellRow + mnFirstFreeIndex; pCell < pCellEnd; ++pCell )
+ *pCell <<= OUString();
+ }
+}
+
+// ============================================================================
+
+CellBlockBuffer::CellBlockBuffer( const WorksheetHelper& rHelper ) :
+ WorksheetHelper( rHelper ),
+ mnCurrRow( -1 )
+{
+ maCellBlockIt = maCellBlocks.end();
+}
+
+void CellBlockBuffer::setColSpans( sal_Int32 nRow, const ValueRangeSet& rColSpans )
+{
+ OSL_ENSURE( maColSpans.count( nRow ) == 0, "CellBlockBuffer::setColSpans - multiple column spans for the same row" );
+ OSL_ENSURE( (mnCurrRow < nRow) && (maColSpans.empty() || (maColSpans.rbegin()->first < nRow)), "CellBlockBuffer::setColSpans - rows are unsorted" );
+ if( (mnCurrRow < nRow) && (maColSpans.count( nRow ) == 0) )
+ maColSpans[ nRow ] = rColSpans.getRanges();
+}
+
+CellBlock* CellBlockBuffer::getCellBlock( const CellAddress& rCellAddr )
+{
+ OSL_ENSURE( rCellAddr.Row >= mnCurrRow, "CellBlockBuffer::getCellBlock - passed row out of order" );
+ // prepare cell blocks, if row changes
+ if( rCellAddr.Row != mnCurrRow )
+ {
+ // find colspans for the new row
+ ColSpanVectorMap::iterator aIt = maColSpans.find( rCellAddr.Row );
+
+ /* Gap between rows, or rows out of order, or no colspan
+ information for the new row found: flush all open cell blocks. */
+ if( (aIt == maColSpans.end()) || (rCellAddr.Row != mnCurrRow + 1) )
+ {
+ finalizeImport();
+ maCellBlocks.clear();
+ maCellBlockIt = maCellBlocks.end();
+ }
+
+ /* Prepare matching cell blocks, create new cell blocks, finalize
+ unmatching cell blocks, if colspan information is available. */
+ if( aIt != maColSpans.end() )
+ {
+ /* The colspan vector aIt points to is sorted by columns, as well
+ as the cell block map. In the folloing, this vector and the
+ list of cell blocks can be iterated simultanously. */
+ CellBlockMap::iterator aMIt = maCellBlocks.begin();
+ const ValueRangeVector& rColRanges = aIt->second;
+ for( ValueRangeVector::const_iterator aVIt = rColRanges.begin(), aVEnd = rColRanges.end(); aVIt != aVEnd; ++aVIt, ++aMIt )
+ {
+ const ValueRange& rColSpan = *aVIt;
+ /* Finalize and remove all cell blocks up to end of the column
+ range (cell blocks are keyed by end column index).
+ CellBlock::isBefore() returns true, if the end index of the
+ passed colspan is greater than the column end index of the
+ cell block, or if the passed range has the same end index
+ but the start indexes do not match. */
+ while( (aMIt != maCellBlocks.end()) && aMIt->second->isBefore( rColSpan ) )
+ {
+ aMIt->second->finalizeImport();
+ maCellBlocks.erase( aMIt++ );
+ }
+ /* If the current cell block (aMIt) fits to the colspan, start
+ a new row there, otherwise create and insert a new cell block. */
+ if( (aMIt != maCellBlocks.end()) && aMIt->second->isExpandable( rColSpan ) )
+ aMIt->second->startNextRow();
+ else
+ aMIt = maCellBlocks.insert( aMIt, CellBlockMap::value_type( rColSpan.mnLast,
+ CellBlockMap::mapped_type( new CellBlock( *this, rColSpan, rCellAddr.Row ) ) ) );
+ }
+ // finalize and remove all remaining cell blocks
+ CellBlockMap::iterator aMEnd = maCellBlocks.end();
+ for( CellBlockMap::iterator aMIt2 = aMIt; aMIt2 != aMEnd; ++aMIt2 )
+ aMIt2->second->finalizeImport();
+ maCellBlocks.erase( aMIt, aMEnd );
+
+ // remove cached colspan information (including current one aIt points to)
+ maColSpans.erase( maColSpans.begin(), ++aIt );
+ }
+ maCellBlockIt = maCellBlocks.begin();
+ mnCurrRow = rCellAddr.Row;
+ }
+
+ // try to find a valid cell block (update maCellBlockIt)
+ if( ((maCellBlockIt != maCellBlocks.end()) && maCellBlockIt->second->contains( rCellAddr.Column )) ||
+ (((maCellBlockIt = maCellBlocks.lower_bound( rCellAddr.Column )) != maCellBlocks.end()) && maCellBlockIt->second->contains( rCellAddr.Column )) )
+ {
+ // maCellBlockIt points to valid cell block
+ return maCellBlockIt->second.get();
+ }
+
+ // no valid cell block found
+ return 0;
+}
+
+void CellBlockBuffer::finalizeImport()
+{
+ maCellBlocks.forEachMem( &CellBlock::finalizeImport );
+}
+
+// ============================================================================
+
+SheetDataBuffer::SheetDataBuffer( const WorksheetHelper& rHelper ) :
+ WorksheetHelper( rHelper ),
+ maCellBlocks( rHelper ),
+ mbPendingSharedFmla( false )
+{
+}
+
+void SheetDataBuffer::setColSpans( sal_Int32 nRow, const ValueRangeSet& rColSpans )
+{
+ maCellBlocks.setColSpans( nRow, rColSpans );
+}
+
+void SheetDataBuffer::setBlankCell( const CellModel& rModel )
+{
+ setCellFormat( rModel );
+}
+
+void SheetDataBuffer::setValueCell( const CellModel& rModel, double fValue )
+{
+ if( CellBlock* pCellBlock = maCellBlocks.getCellBlock( rModel.maCellAddr ) )
+ pCellBlock->getCellAny( rModel.maCellAddr.Column ) <<= fValue;
+ else
+ putValue( rModel.maCellAddr, fValue );
+ setCellFormat( rModel );
+}
+
+void SheetDataBuffer::setStringCell( const CellModel& rModel, const OUString& rText )
+{
+ if( CellBlock* pCellBlock = maCellBlocks.getCellBlock( rModel.maCellAddr ) )
+ pCellBlock->getCellAny( rModel.maCellAddr.Column ) <<= rText;
+ else
+ putString( rModel.maCellAddr, rText );
+ setCellFormat( rModel );
+}
+
+void SheetDataBuffer::setStringCell( const CellModel& rModel, const RichStringRef& rxString )
+{
+ OSL_ENSURE( rxString.get(), "SheetDataBuffer::setStringCell - missing rich string object" );
+ const Font* pFirstPortionFont = getStyles().getFontFromCellXf( rModel.mnXfId ).get();
+ OUString aText;
+ if( rxString->extractPlainString( aText, pFirstPortionFont ) )
+ {
+ setStringCell( rModel, aText );
+ }
+ else
+ {
+ if( CellBlock* pCellBlock = maCellBlocks.getCellBlock( rModel.maCellAddr ) )
+ pCellBlock->insertRichString( rModel.maCellAddr, rxString, pFirstPortionFont );
+ else
+ putRichString( rModel.maCellAddr, *rxString, pFirstPortionFont );
+ setCellFormat( rModel );
+ }
+}
+
+void SheetDataBuffer::setStringCell( const CellModel& rModel, sal_Int32 nStringId )
+{
+ RichStringRef xString = getSharedStrings().getString( nStringId );
+ if( xString.get() )
+ setStringCell( rModel, xString );
+ else
+ setBlankCell( rModel );
+}
+
+void SheetDataBuffer::setDateTimeCell( const CellModel& rModel, const DateTime& rDateTime )
+{
+ // write serial date/time value into the cell
+ double fSerial = getUnitConverter().calcSerialFromDateTime( rDateTime );
+ setValueCell( rModel, fSerial );
+ // set appropriate number format
+ using namespace ::com::sun::star::util::NumberFormat;
+ sal_Int16 nStdFmt = (fSerial < 1.0) ? TIME : (((rDateTime.Hours > 0) || (rDateTime.Minutes > 0) || (rDateTime.Seconds > 0)) ? DATETIME : DATE);
+ setStandardNumFmt( rModel.maCellAddr, nStdFmt );
+}
+
+void SheetDataBuffer::setBooleanCell( const CellModel& rModel, bool bValue )
+{
+ setCellFormula( rModel.maCellAddr, getFormulaParser().convertBoolToFormula( bValue ) );
+ // #108770# set 'Standard' number format for all Boolean cells
+ setCellFormat( rModel, 0 );
+}
+
+void SheetDataBuffer::setErrorCell( const CellModel& rModel, const OUString& rErrorCode )
+{
+ setErrorCell( rModel, getUnitConverter().calcBiffErrorCode( rErrorCode ) );
+}
+
+void SheetDataBuffer::setErrorCell( const CellModel& rModel, sal_uInt8 nErrorCode )
+{
+ setCellFormula( rModel.maCellAddr, getFormulaParser().convertErrorToFormula( nErrorCode ) );
+ setCellFormat( rModel );
+}
+
+void SheetDataBuffer::setFormulaCell( const CellModel& rModel, const ApiTokenSequence& rTokens )
+{
+ mbPendingSharedFmla = false;
+ ApiTokenSequence aTokens;
+
+ /* Detect special token passed as placeholder for array formulas, shared
+ formulas, and table operations. In BIFF, these formulas are represented
+ by a single tExp resp. tTbl token. If the formula parser finds these
+ tokens, it puts a single OPCODE_BAD token with the base address and
+ formula type into the token sequence. This information will be
+ extracted here, and in case of a shared formula, the shared formula
+ buffer will generate the resulting formula token array. */
+ ApiSpecialTokenInfo aTokenInfo;
+ if( rTokens.hasElements() && getFormulaParser().extractSpecialTokenInfo( aTokenInfo, rTokens ) )
+ {
+ /* The second member of the token info is set to true, if the formula
+ represents a table operation, which will be skipped. In BIFF12 it
+ is not possible to distinguish array and shared formulas
+ (BIFF5/BIFF8 provide this information with a special flag in the
+ FORMULA record). */
+ if( !aTokenInfo.Second )
+ {
+ /* Construct the token array representing the shared formula. If
+ the returned sequence is empty, the definition of the shared
+ formula has not been loaded yet, or the cell is part of an
+ array formula. In this case, the cell will be remembered. After
+ reading the formula definition it will be retried to insert the
+ formula via retryPendingSharedFormulaCell(). */
+ BinAddress aBaseAddr( aTokenInfo.First );
+ aTokens = resolveSharedFormula( aBaseAddr );
+ if( !aTokens.hasElements() )
+ {
+ maSharedFmlaAddr = rModel.maCellAddr;
+ maSharedBaseAddr = aBaseAddr;
+ mbPendingSharedFmla = true;
+ }
+ }
+ }
+ else
+ {
+ // simple formula, use the passed token array
+ aTokens = rTokens;
+ }
+
+ setCellFormula( rModel.maCellAddr, aTokens );
+ setCellFormat( rModel );
+}
+
+void SheetDataBuffer::setFormulaCell( const CellModel& rModel, sal_Int32 nSharedId )
+{
+ setCellFormula( rModel.maCellAddr, resolveSharedFormula( BinAddress( nSharedId, 0 ) ) );
+ setCellFormat( rModel );
+}
+
+void SheetDataBuffer::createArrayFormula( const CellRangeAddress& rRange, const ApiTokenSequence& rTokens )
+{
+ /* Array formulas will be inserted later in finalizeImport(). This is
+ needed to not disturb collecting all the cells, which will be put into
+ the sheet in large blocks to increase performance. */
+ maArrayFormulas.push_back( ArrayFormula( rRange, rTokens ) );
+}
+
+void SheetDataBuffer::createTableOperation( const CellRangeAddress& rRange, const DataTableModel& rModel )
+{
+ /* Table operations will be inserted later in finalizeImport(). This is
+ needed to not disturb collecting all the cells, which will be put into
+ the sheet in large blocks to increase performance. */
+ maTableOperations.push_back( TableOperation( rRange, rModel ) );
+}
+
+void SheetDataBuffer::createSharedFormula( sal_Int32 nSharedId, const ApiTokenSequence& rTokens )
+{
+ createSharedFormula( BinAddress( nSharedId, 0 ), rTokens );
+}
+
+void SheetDataBuffer::createSharedFormula( const CellAddress& rCellAddr, const ApiTokenSequence& rTokens )
+{
+ createSharedFormula( BinAddress( rCellAddr ), rTokens );
+}
+
+void SheetDataBuffer::setRowFormat( sal_Int32 nRow, sal_Int32 nXfId, bool bCustomFormat )
+{
+ // set row formatting
+ if( bCustomFormat )
+ {
+ // try to expand cached row range, if formatting is equal
+ if( (maXfIdRowRange.maRowRange.mnLast < 0) || !maXfIdRowRange.tryExpand( nRow, nXfId ) )
+ {
+ writeXfIdRowRangeProperties( maXfIdRowRange );
+ maXfIdRowRange.set( nRow, nXfId );
+ }
+ }
+ else if( maXfIdRowRange.maRowRange.mnLast >= 0 )
+ {
+ // finish last cached row range
+ writeXfIdRowRangeProperties( maXfIdRowRange );
+ maXfIdRowRange.set( -1, -1 );
+ }
+}
+
+void SheetDataBuffer::setMergedRange( const CellRangeAddress& rRange )
+{
+ maMergedRanges.push_back( MergedRange( rRange ) );
+}
+
+void SheetDataBuffer::setStandardNumFmt( const CellAddress& rCellAddr, sal_Int16 nStdNumFmt )
+{
+ try
+ {
+ Reference< XNumberFormatsSupplier > xNumFmtsSupp( getDocument(), UNO_QUERY_THROW );
+ Reference< XNumberFormatTypes > xNumFmtTypes( xNumFmtsSupp->getNumberFormats(), UNO_QUERY_THROW );
+ sal_Int32 nIndex = xNumFmtTypes->getStandardFormat( nStdNumFmt, Locale() );
+ PropertySet aPropSet( getCell( rCellAddr ) );
+ aPropSet.setProperty( PROP_NumberFormat, nIndex );
+ }
+ catch( Exception& )
+ {
+ }
+}
+
+void SheetDataBuffer::finalizeImport()
+{
+ // insert all cells of all open cell blocks
+ maCellBlocks.finalizeImport();
+
+ // create all array formulas
+ for( ArrayFormulaList::iterator aIt = maArrayFormulas.begin(), aEnd = maArrayFormulas.end(); aIt != aEnd; ++aIt )
+ finalizeArrayFormula( aIt->first, aIt->second );
+
+ // create all table operations
+ for( TableOperationList::iterator aIt = maTableOperations.begin(), aEnd = maTableOperations.end(); aIt != aEnd; ++aIt )
+ finalizeTableOperation( aIt->first, aIt->second );
+
+ // write default formatting of remaining row range
+ writeXfIdRowRangeProperties( maXfIdRowRange );
+
+ // try to merge remaining inserted ranges
+ mergeXfIdRanges();
+ // write all formatting
+ for( XfIdRangeMap::const_iterator aIt = maXfIdRanges.begin(), aEnd = maXfIdRanges.end(); aIt != aEnd; ++aIt )
+ writeXfIdRangeProperties( aIt->second );
+
+ // merge all cached merged ranges and update right/bottom cell borders
+ for( MergedRangeList::iterator aIt = maMergedRanges.begin(), aEnd = maMergedRanges.end(); aIt != aEnd; ++aIt )
+ finalizeMergedRange( aIt->maRange );
+ for( MergedRangeList::iterator aIt = maCenterFillRanges.begin(), aEnd = maCenterFillRanges.end(); aIt != aEnd; ++aIt )
+ finalizeMergedRange( aIt->maRange );
+}
+
+// private --------------------------------------------------------------------
+
+SheetDataBuffer::XfIdRowRange::XfIdRowRange() :
+ maRowRange( -1 ),
+ mnXfId( -1 )
+{
+}
+
+bool SheetDataBuffer::XfIdRowRange::intersects( const CellRangeAddress& rRange ) const
+{
+ return (rRange.StartRow <= maRowRange.mnLast) && (maRowRange.mnFirst <= rRange.EndRow);
+}
+
+void SheetDataBuffer::XfIdRowRange::set( sal_Int32 nRow, sal_Int32 nXfId )
+{
+ maRowRange = ValueRange( nRow );
+ mnXfId = nXfId;
+}
+
+bool SheetDataBuffer::XfIdRowRange::tryExpand( sal_Int32 nRow, sal_Int32 nXfId )
+{
+ if( mnXfId == nXfId )
+ {
+ if( maRowRange.mnLast + 1 == nRow )
+ {
+ ++maRowRange.mnLast;
+ return true;
+ }
+ if( maRowRange.mnFirst == nRow + 1 )
+ {
+ --maRowRange.mnFirst;
+ return true;
+ }
+ }
+ return false;
+}
+
+void SheetDataBuffer::XfIdRange::set( const CellAddress& rCellAddr, sal_Int32 nXfId, sal_Int32 nNumFmtId )
+{
+ maRange.Sheet = rCellAddr.Sheet;
+ maRange.StartColumn = maRange.EndColumn = rCellAddr.Column;
+ maRange.StartRow = maRange.EndRow = rCellAddr.Row;
+ mnXfId = nXfId;
+ mnNumFmtId = nNumFmtId;
+}
+
+bool SheetDataBuffer::XfIdRange::tryExpand( const CellAddress& rCellAddr, sal_Int32 nXfId, sal_Int32 nNumFmtId )
+{
+ if( (mnXfId == nXfId) && (mnNumFmtId == nNumFmtId) &&
+ (maRange.StartRow == rCellAddr.Row) &&
+ (maRange.EndRow == rCellAddr.Row) &&
+ (maRange.EndColumn + 1 == rCellAddr.Column) )
+ {
+ ++maRange.EndColumn;
+ return true;
+ }
+ return false;
+}
+
+bool SheetDataBuffer::XfIdRange::tryMerge( const XfIdRange& rXfIdRange )
+{
+ if( (mnXfId == rXfIdRange.mnXfId) &&
+ (mnNumFmtId == rXfIdRange.mnNumFmtId) &&
+ (maRange.EndRow + 1 == rXfIdRange.maRange.StartRow) &&
+ (maRange.StartColumn == rXfIdRange.maRange.StartColumn) &&
+ (maRange.EndColumn == rXfIdRange.maRange.EndColumn) )
+ {
+ maRange.EndRow = rXfIdRange.maRange.EndRow;
+ return true;
+ }
+ return false;
+}
+
+
+SheetDataBuffer::MergedRange::MergedRange( const CellRangeAddress& rRange ) :
+ maRange( rRange ),
+ mnHorAlign( XML_TOKEN_INVALID )
+{
+}
+
+SheetDataBuffer::MergedRange::MergedRange( const CellAddress& rAddress, sal_Int32 nHorAlign ) :
+ maRange( rAddress.Sheet, rAddress.Column, rAddress.Row, rAddress.Column, rAddress.Row ),
+ mnHorAlign( nHorAlign )
+{
+}
+
+bool SheetDataBuffer::MergedRange::tryExpand( const CellAddress& rAddress, sal_Int32 nHorAlign )
+{
+ if( (mnHorAlign == nHorAlign) && (maRange.StartRow == rAddress.Row) &&
+ (maRange.EndRow == rAddress.Row) && (maRange.EndColumn + 1 == rAddress.Column) )
+ {
+ ++maRange.EndColumn;
+ return true;
+ }
+ return false;
+}
+
+// ----------------------------------------------------------------------------
+
+void SheetDataBuffer::setCellFormula( const CellAddress& rCellAddr, const ApiTokenSequence& rTokens )
+{
+ if( rTokens.hasElements() )
+ {
+ if( CellBlock* pCellBlock = maCellBlocks.getCellBlock( rCellAddr ) )
+ pCellBlock->getCellAny( rCellAddr.Column ) <<= rTokens;
+ else
+ putFormulaTokens( rCellAddr, rTokens );
+ }
+}
+
+void SheetDataBuffer::createSharedFormula( const BinAddress& rMapKey, const ApiTokenSequence& rTokens )
+{
+ // create the defined name that will represent the shared formula
+ OUString aName = OUStringBuffer().appendAscii( RTL_CONSTASCII_STRINGPARAM( "__shared_" ) ).
+ append( static_cast< sal_Int32 >( getSheetIndex() + 1 ) ).
+ append( sal_Unicode( '_' ) ).append( rMapKey.mnRow ).
+ append( sal_Unicode( '_' ) ).append( rMapKey.mnCol ).makeStringAndClear();
+ Reference< XNamedRange > xNamedRange = createNamedRangeObject( aName );
+ OSL_ENSURE( xNamedRange.is(), "SheetDataBuffer::createSharedFormula - cannot create shared formula" );
+ PropertySet aNameProps( xNamedRange );
+ aNameProps.setProperty( PROP_IsSharedFormula, true );
+
+ // get and store the token index of the defined name
+ OSL_ENSURE( maSharedFormulas.count( rMapKey ) == 0, "SheetDataBuffer::createSharedFormula - shared formula exists already" );
+ sal_Int32 nTokenIndex = 0;
+ if( aNameProps.getProperty( nTokenIndex, PROP_TokenIndex ) && (nTokenIndex >= 0) ) try
+ {
+ // store the token index in the map
+ maSharedFormulas[ rMapKey ] = nTokenIndex;
+ // set the formula definition
+ Reference< XFormulaTokens > xTokens( xNamedRange, UNO_QUERY_THROW );
+ xTokens->setTokens( rTokens );
+ // retry to insert a pending shared formula cell
+ if( mbPendingSharedFmla )
+ setCellFormula( maSharedFmlaAddr, resolveSharedFormula( maSharedBaseAddr ) );
+ }
+ catch( Exception& )
+ {
+ }
+ mbPendingSharedFmla = false;
+}
+
+ApiTokenSequence SheetDataBuffer::resolveSharedFormula( const BinAddress& rMapKey ) const
+{
+ sal_Int32 nTokenIndex = ContainerHelper::getMapElement( maSharedFormulas, rMapKey, -1 );
+ return (nTokenIndex >= 0) ? getFormulaParser().convertNameToFormula( nTokenIndex ) : ApiTokenSequence();
+}
+
+void SheetDataBuffer::finalizeArrayFormula( const CellRangeAddress& rRange, const ApiTokenSequence& rTokens ) const
+{
+ Reference< XArrayFormulaTokens > xTokens( getCellRange( rRange ), UNO_QUERY );
+ OSL_ENSURE( xTokens.is(), "SheetDataBuffer::finalizeArrayFormula - missing formula token interface" );
+ if( xTokens.is() )
+ xTokens->setArrayTokens( rTokens );
+}
+
+void SheetDataBuffer::finalizeTableOperation( const CellRangeAddress& rRange, const DataTableModel& rModel ) const
+{
+ sal_Int16 nSheet = getSheetIndex();
+ bool bOk = false;
+ if( !rModel.mbRef1Deleted && (rModel.maRef1.getLength() > 0) && (rRange.StartColumn > 0) && (rRange.StartRow > 0) )
+ {
+ CellRangeAddress aOpRange = rRange;
+ CellAddress aRef1;
+ if( getAddressConverter().convertToCellAddress( aRef1, rModel.maRef1, nSheet, true ) ) try
+ {
+ if( rModel.mb2dTable )
+ {
+ CellAddress aRef2;
+ if( !rModel.mbRef2Deleted && getAddressConverter().convertToCellAddress( aRef2, rModel.maRef2, nSheet, true ) )
+ {
+ // API call expects input values inside operation range
+ --aOpRange.StartColumn;
+ --aOpRange.StartRow;
+ // formula range is top-left cell of operation range
+ CellRangeAddress aFormulaRange( nSheet, aOpRange.StartColumn, aOpRange.StartRow, aOpRange.StartColumn, aOpRange.StartRow );
+ // set multiple operation
+ Reference< XMultipleOperation > xMultOp( getCellRange( aOpRange ), UNO_QUERY_THROW );
+ xMultOp->setTableOperation( aFormulaRange, TableOperationMode_BOTH, aRef2, aRef1 );
+ bOk = true;
+ }
+ }
+ else if( rModel.mbRowTable )
+ {
+ // formula range is column to the left of operation range
+ CellRangeAddress aFormulaRange( nSheet, aOpRange.StartColumn - 1, aOpRange.StartRow, aOpRange.StartColumn - 1, aOpRange.EndRow );
+ // API call expects input values (top row) inside operation range
+ --aOpRange.StartRow;
+ // set multiple operation
+ Reference< XMultipleOperation > xMultOp( getCellRange( aOpRange ), UNO_QUERY_THROW );
+ xMultOp->setTableOperation( aFormulaRange, TableOperationMode_ROW, aRef1, aRef1 );
+ bOk = true;
+ }
+ else
+ {
+ // formula range is row above operation range
+ CellRangeAddress aFormulaRange( nSheet, aOpRange.StartColumn, aOpRange.StartRow - 1, aOpRange.EndColumn, aOpRange.StartRow - 1 );
+ // API call expects input values (left column) inside operation range
+ --aOpRange.StartColumn;
+ // set multiple operation
+ Reference< XMultipleOperation > xMultOp( getCellRange( aOpRange ), UNO_QUERY_THROW );
+ xMultOp->setTableOperation( aFormulaRange, TableOperationMode_COLUMN, aRef1, aRef1 );
+ bOk = true;
+ }
+ }
+ catch( Exception& )
+ {
+ }
+ }
+
+ // on error: fill cell range with #REF! error codes
+ if( !bOk ) try
+ {
+ Reference< XCellRangeData > xCellRangeData( getCellRange( rRange ), UNO_QUERY_THROW );
+ size_t nWidth = static_cast< size_t >( rRange.EndColumn - rRange.StartColumn + 1 );
+ size_t nHeight = static_cast< size_t >( rRange.EndRow - rRange.StartRow + 1 );
+ Matrix< Any > aErrorCells( nWidth, nHeight, Any( getFormulaParser().convertErrorToFormula( BIFF_ERR_REF ) ) );
+ xCellRangeData->setDataArray( ContainerHelper::matrixToSequenceSequence( aErrorCells ) );
+ }
+ catch( Exception& )
+ {
+ }
+}
+
+void SheetDataBuffer::setCellFormat( const CellModel& rModel, sal_Int32 nNumFmtId )
+{
+ if( (rModel.mnXfId >= 0) || (nNumFmtId >= 0) )
+ {
+ // try to merge existing ranges and to write some formatting properties
+ if( !maXfIdRanges.empty() )
+ {
+ // get row index of last inserted cell
+ sal_Int32 nLastRow = maXfIdRanges.rbegin()->second.maRange.StartRow;
+ // row changed - try to merge ranges of last row with existing ranges
+ if( rModel.maCellAddr.Row != nLastRow )
+ {
+ mergeXfIdRanges();
+ // write format properties of all ranges above last row and remove them
+ XfIdRangeMap::iterator aIt = maXfIdRanges.begin(), aEnd = maXfIdRanges.end();
+ while( aIt != aEnd )
+ {
+ // check that range cannot be merged with current row, and that range is not in cached row range
+ if( (aIt->second.maRange.EndRow < nLastRow) && !maXfIdRowRange.intersects( aIt->second.maRange ) )
+ {
+ writeXfIdRangeProperties( aIt->second );
+ maXfIdRanges.erase( aIt++ );
+ }
+ else
+ ++aIt;
+ }
+ }
+ }
+
+ // try to expand last existing range, or create new range entry
+ if( maXfIdRanges.empty() || !maXfIdRanges.rbegin()->second.tryExpand( rModel.maCellAddr, rModel.mnXfId, nNumFmtId ) )
+ maXfIdRanges[ BinAddress( rModel.maCellAddr ) ].set( rModel.maCellAddr, rModel.mnXfId, nNumFmtId );
+
+ // update merged ranges for 'center across selection' and 'fill'
+ if( const Xf* pXf = getStyles().getCellXf( rModel.mnXfId ).get() )
+ {
+ sal_Int32 nHorAlign = pXf->getAlignment().getModel().mnHorAlign;
+ if( (nHorAlign == XML_centerContinuous) || (nHorAlign == XML_fill) )
+ {
+ /* start new merged range, if cell is not empty (#108781#),
+ or try to expand last range with empty cell */
+ if( rModel.mnCellType != XML_TOKEN_INVALID )
+ maCenterFillRanges.push_back( MergedRange( rModel.maCellAddr, nHorAlign ) );
+ else if( !maCenterFillRanges.empty() )
+ maCenterFillRanges.rbegin()->tryExpand( rModel.maCellAddr, nHorAlign );
+ }
+ }
+ }
+}
+
+void SheetDataBuffer::writeXfIdRowRangeProperties( const XfIdRowRange& rXfIdRowRange ) const
+{
+ if( (rXfIdRowRange.maRowRange.mnLast >= 0) && (rXfIdRowRange.mnXfId >= 0) )
+ {
+ AddressConverter& rAddrConv = getAddressConverter();
+ CellRangeAddress aRange( getSheetIndex(), 0, rXfIdRowRange.maRowRange.mnFirst, rAddrConv.getMaxApiAddress().Column, rXfIdRowRange.maRowRange.mnLast );
+ if( rAddrConv.validateCellRange( aRange, true, false ) )
+ {
+ PropertySet aPropSet( getCellRange( aRange ) );
+ getStyles().writeCellXfToPropertySet( aPropSet, rXfIdRowRange.mnXfId );
+ }
+ }
+}
+
+void SheetDataBuffer::writeXfIdRangeProperties( const XfIdRange& rXfIdRange ) const
+{
+ StylesBuffer& rStyles = getStyles();
+ PropertyMap aPropMap;
+ if( rXfIdRange.mnXfId >= 0 )
+ rStyles.writeCellXfToPropertyMap( aPropMap, rXfIdRange.mnXfId );
+ if( rXfIdRange.mnNumFmtId >= 0 )
+ rStyles.writeNumFmtToPropertyMap( aPropMap, rXfIdRange.mnNumFmtId );
+ PropertySet aPropSet( getCellRange( rXfIdRange.maRange ) );
+ aPropSet.setProperties( aPropMap );
+}
+
+void SheetDataBuffer::mergeXfIdRanges()
+{
+ if( !maXfIdRanges.empty() )
+ {
+ // get row index of last range
+ sal_Int32 nLastRow = maXfIdRanges.rbegin()->second.maRange.StartRow;
+ // process all ranges located in the same row of the last range
+ XfIdRangeMap::iterator aMergeIt = maXfIdRanges.end();
+ while( (aMergeIt != maXfIdRanges.begin()) && ((--aMergeIt)->second.maRange.StartRow == nLastRow) )
+ {
+ const XfIdRange& rMergeXfIdRange = aMergeIt->second;
+ // try to find a range that can be merged with rMergeRange
+ bool bFound = false;
+ for( XfIdRangeMap::iterator aIt = maXfIdRanges.begin(); !bFound && (aIt != aMergeIt); ++aIt )
+ if( (bFound = aIt->second.tryMerge( rMergeXfIdRange )) == true )
+ maXfIdRanges.erase( aMergeIt++ );
+ }
+ }
+}
+
+void SheetDataBuffer::finalizeMergedRange( const CellRangeAddress& rRange )
+{
+ bool bMultiCol = rRange.StartColumn < rRange.EndColumn;
+ bool bMultiRow = rRange.StartRow < rRange.EndRow;
+
+ if( bMultiCol || bMultiRow ) try
+ {
+ // merge the cell range
+ Reference< XMergeable > xMerge( getCellRange( rRange ), UNO_QUERY_THROW );
+ xMerge->merge( sal_True );
+
+ // if merging this range worked (no overlapping merged ranges), update cell borders
+ Reference< XCell > xTopLeft( getCell( CellAddress( getSheetIndex(), rRange.StartColumn, rRange.StartRow ) ), UNO_SET_THROW );
+ PropertySet aTopLeftProp( xTopLeft );
+
+ // copy right border of top-right cell to right border of top-left cell
+ if( bMultiCol )
+ {
+ PropertySet aTopRightProp( getCell( CellAddress( getSheetIndex(), rRange.EndColumn, rRange.StartRow ) ) );
+ BorderLine aLine;
+ if( aTopRightProp.getProperty( aLine, PROP_RightBorder ) )
+ aTopLeftProp.setProperty( PROP_RightBorder, aLine );
+ }
+
+ // copy bottom border of bottom-left cell to bottom border of top-left cell
+ if( bMultiRow )
+ {
+ PropertySet aBottomLeftProp( getCell( CellAddress( getSheetIndex(), rRange.StartColumn, rRange.EndRow ) ) );
+ BorderLine aLine;
+ if( aBottomLeftProp.getProperty( aLine, PROP_BottomBorder ) )
+ aTopLeftProp.setProperty( PROP_BottomBorder, aLine );
+ }
+
+ // #i93609# merged range in a single row: test if manual row height is needed
+ if( !bMultiRow )
+ {
+ bool bTextWrap = aTopLeftProp.getBoolProperty( PROP_IsTextWrapped );
+ if( !bTextWrap && (xTopLeft->getType() == CellContentType_TEXT) )
+ {
+ Reference< XText > xText( xTopLeft, UNO_QUERY );
+ bTextWrap = xText.is() && (xText->getString().indexOf( '\x0A' ) >= 0);
+ }
+ if( bTextWrap )
+ setManualRowHeight( rRange.StartRow );
+ }
+ }
+ catch( Exception& )
+ {
+ }
+}
+
+// ============================================================================
+
+} // namespace xls
+} // namespace oox
diff --git a/oox/source/xls/sheetdatacontext.cxx b/oox/source/xls/sheetdatacontext.cxx
index c6c68dd6897c..569126e0ebad 100644
--- a/oox/source/xls/sheetdatacontext.cxx
+++ b/oox/source/xls/sheetdatacontext.cxx
@@ -28,8 +28,6 @@
#include "oox/xls/sheetdatacontext.hxx"
-#include <com/sun/star/sheet/XArrayFormulaTokens.hpp>
-#include <com/sun/star/sheet/XFormulaTokens.hpp>
#include <com/sun/star/table/CellContentType.hpp>
#include <com/sun/star/table/XCell.hpp>
#include <com/sun/star/table/XCellRange.hpp>
@@ -40,7 +38,6 @@
#include "oox/xls/biffinputstream.hxx"
#include "oox/xls/formulaparser.hxx"
#include "oox/xls/richstringcontext.hxx"
-#include "oox/xls/sharedformulabuffer.hxx"
#include "oox/xls/unitconverter.hxx"
namespace oox {
@@ -99,64 +96,31 @@ const sal_uInt32 BIFF_ROW_THICKTOP = 0x10000000;
const sal_uInt32 BIFF_ROW_THICKBOTTOM = 0x20000000;
const sal_uInt32 BIFF_ROW_SHOWPHONETIC = 0x40000000;
-const sal_Int32 BIFF2_XF_EXTENDED_IDS = 63;
-const sal_uInt8 BIFF2_XF_MASK = 0x3F;
+const sal_Int32 BIFF2_CELL_USEIXFE = 63;
-// ----------------------------------------------------------------------------
-
-/** Formula context for cell formulas. */
-class CellFormulaContext : public SimpleFormulaContext
-{
-public:
- explicit CellFormulaContext(
- const Reference< XFormulaTokens >& rxTokens,
- const CellAddress& rCellPos );
-};
-
-CellFormulaContext::CellFormulaContext( const Reference< XFormulaTokens >& rxTokens, const CellAddress& rCellPos ) :
- SimpleFormulaContext( rxTokens, false, false )
-{
- setBaseAddress( rCellPos );
-}
-
-// ----------------------------------------------------------------------------
-
-/** Uses the XArrayFormulaTokens interface to set a token sequence. */
-class ArrayFormulaContext : public FormulaContext
-{
-public:
- explicit ArrayFormulaContext(
- const Reference< XArrayFormulaTokens >& rxTokens,
- const CellRangeAddress& rArrayRange );
-
- virtual void setTokens( const ApiTokenSequence& rTokens );
+} // namespace
-private:
- Reference< XArrayFormulaTokens > mxTokens;
-};
+// ============================================================================
-ArrayFormulaContext::ArrayFormulaContext(
- const Reference< XArrayFormulaTokens >& rxTokens, const CellRangeAddress& rArrayRange ) :
- FormulaContext( false, false ),
- mxTokens( rxTokens )
+SheetDataContextBase::SheetDataContextBase( const WorksheetHelper& rHelper ) :
+ mrAddressConv( rHelper.getAddressConverter() ),
+ mrFormulaParser( rHelper.getFormulaParser() ),
+ mrSheetData( rHelper.getSheetData() ),
+ mnSheet( rHelper.getSheetIndex() )
{
- OSL_ENSURE( mxTokens.is(), "ArrayFormulaContext::ArrayFormulaContext - missing XArrayFormulaTokens interface" );
- setBaseAddress( CellAddress( rArrayRange.Sheet, rArrayRange.StartColumn, rArrayRange.StartRow ) );
}
-void ArrayFormulaContext::setTokens( const ApiTokenSequence& rTokens )
+SheetDataContextBase::~SheetDataContextBase()
{
- mxTokens->setArrayTokens( rTokens );
}
-// ----------------------------------------------------------------------------
-
-} // namespace
-
// ============================================================================
SheetDataContext::SheetDataContext( WorksheetFragmentBase& rFragment ) :
- WorksheetContextBase( rFragment )
+ WorksheetContextBase( rFragment ),
+ SheetDataContextBase( rFragment ),
+ mbHasFormula( false ),
+ mbValidRange( false )
{
}
@@ -169,20 +133,22 @@ ContextHandlerRef SheetDataContext::onCreateContext( sal_Int32 nElement, const A
break;
case XLS_TOKEN( row ):
- if( nElement == XLS_TOKEN( c ) ) { importCell( rAttribs ); return this; }
+ // do not process cell elements with invalid (out-of-range) address
+ if( nElement == XLS_TOKEN( c ) && importCell( rAttribs ) )
+ return this;
break;
case XLS_TOKEN( c ):
- if( maCurrCell.mxCell.is() ) switch( nElement )
+ switch( nElement )
{
case XLS_TOKEN( is ):
mxInlineStr.reset( new RichString( *this ) );
return new RichStringContext( *this, mxInlineStr );
case XLS_TOKEN( v ):
- return this;
+ return this; // characters contain cell value
case XLS_TOKEN( f ):
importFormula( rAttribs );
- return this;
+ return this; // characters contain formula string
}
break;
}
@@ -194,94 +160,86 @@ void SheetDataContext::onCharacters( const OUString& rChars )
switch( getCurrentElement() )
{
case XLS_TOKEN( v ):
- maCurrCell.maValueStr = rChars;
- maCurrCell.mbHasValueStr = true;
+ maCellValue = rChars;
break;
-
case XLS_TOKEN( f ):
- if( maCurrCell.mxCell.is() ) try
- {
- switch( maCurrCell.mnFormulaType )
- {
- case XML_normal:
- if( rChars.getLength() > 0 )
- {
- Reference< XFormulaTokens > xTokens( maCurrCell.mxCell, UNO_QUERY_THROW );
- CellFormulaContext aContext( xTokens, maCurrCell.maAddress );
- getFormulaParser().importFormula( aContext, rChars );
- }
- break;
-
- case XML_array:
- if( (maCurrCell.maFormulaRef.getLength() > 0) && (rChars.getLength() > 0) )
- {
- CellRangeAddress aArrayRange;
- Reference< XArrayFormulaTokens > xTokens( getCellRange( maCurrCell.maFormulaRef, &aArrayRange ), UNO_QUERY_THROW );
- ArrayFormulaContext aContext( xTokens, aArrayRange );
- getFormulaParser().importFormula( aContext, rChars );
- }
- break;
-
- case XML_shared:
- if( maCurrCell.mnSharedId >= 0 )
- {
- if( rChars.getLength() > 0 )
- getSharedFormulas().importSharedFmla( rChars, maCurrCell.maFormulaRef, maCurrCell.mnSharedId, maCurrCell.maAddress );
- Reference< XFormulaTokens > xTokens( maCurrCell.mxCell, UNO_QUERY_THROW );
- ExtCellFormulaContext aContext( *this, xTokens, maCurrCell.maAddress );
- getSharedFormulas().setSharedFormulaCell( aContext, maCurrCell.mnSharedId );
- }
- break;
-
- case XML_dataTable:
- if( maCurrCell.maFormulaRef.getLength() > 0 )
- {
- CellRangeAddress aTableRange;
- if( getAddressConverter().convertToCellRange( aTableRange, maCurrCell.maFormulaRef, getSheetIndex(), true, true ) )
- setTableOperation( aTableRange, maTableData );
- }
- break;
-
- default:
- OSL_FAIL( "SheetDataContext::onEndElement - unknown formula type" );
- }
- }
- catch( Exception& )
- {
- }
+ if( maFmlaData.mnFormulaType != XML_TOKEN_INVALID )
+ maTokens = mrFormulaParser.importFormula( maCellData.maCellAddr, rChars );
break;
}
}
void SheetDataContext::onEndElement()
{
- if( isCurrentElement( XLS_TOKEN( c ) ) && maCurrCell.mxCell.is() )
+ if( getCurrentElement() == XLS_TOKEN( c ) )
{
- if( maCurrCell.mxCell->getType() == CellContentType_EMPTY )
+ // try to create a formula cell
+ if( mbHasFormula ) switch( maFmlaData.mnFormulaType )
+ {
+ case XML_normal:
+ mrSheetData.setFormulaCell( maCellData, maTokens );
+ break;
+ case XML_shared:
+ if( maFmlaData.mnSharedId >= 0 )
+ {
+ if( mbValidRange && maFmlaData.isValidSharedRef( maCellData.maCellAddr ) )
+ mrSheetData.createSharedFormula( maFmlaData.mnSharedId, maTokens );
+ mrSheetData.setFormulaCell( maCellData, maFmlaData.mnSharedId );
+ }
+ else
+ // no success, set plain cell value and formatting below
+ mbHasFormula = false;
+ break;
+ case XML_array:
+ if( mbValidRange && maFmlaData.isValidArrayRef( maCellData.maCellAddr ) )
+ mrSheetData.createArrayFormula( maFmlaData.maFormulaRef, maTokens );
+ // set cell formatting, but do not set result as cell value
+ mrSheetData.setBlankCell( maCellData );
+ break;
+ case XML_dataTable:
+ if( mbValidRange )
+ mrSheetData.createTableOperation( maFmlaData.maFormulaRef, maTableData );
+ // set cell formatting, but do not set result as cell value
+ mrSheetData.setBlankCell( maCellData );
+ break;
+ default:
+ OSL_ENSURE( maFmlaData.mnFormulaType == XML_TOKEN_INVALID, "SheetDataContext::onEndElement - unknown formula type" );
+ mbHasFormula = false;
+ }
+
+ if( !mbHasFormula )
{
- if( maCurrCell.mbHasValueStr )
+ // no formula created: try to set the cell value
+ if( maCellValue.getLength() > 0 ) switch( maCellData.mnCellType )
{
- // implemented in WorksheetHelper class
- setCell( maCurrCell );
+ case XML_n:
+ mrSheetData.setValueCell( maCellData, maCellValue.toDouble() );
+ break;
+ case XML_b:
+ mrSheetData.setBooleanCell( maCellData, maCellValue.toDouble() != 0.0 );
+ break;
+ case XML_e:
+ mrSheetData.setErrorCell( maCellData, maCellValue );
+ break;
+ case XML_str:
+ mrSheetData.setStringCell( maCellData, maCellValue );
+ break;
+ case XML_s:
+ mrSheetData.setStringCell( maCellData, maCellValue.toInt32() );
+ break;
}
- else if( (maCurrCell.mnCellType == XML_inlineStr) && mxInlineStr.get() )
+ else if( (maCellData.mnCellType == XML_inlineStr) && mxInlineStr.get() )
{
- // convert font settings
mxInlineStr->finalizeImport();
- // write string to cell
- Reference< XText > xText( maCurrCell.mxCell, UNO_QUERY );
- if( xText.is() )
- mxInlineStr->convert( xText, maCurrCell.mnXfId );
+ mrSheetData.setStringCell( maCellData, mxInlineStr );
}
else
{
// empty cell, update cell type
- maCurrCell.mnCellType = XML_TOKEN_INVALID;
+ maCellData.mnCellType = XML_TOKEN_INVALID;
+ mrSheetData.setBlankCell( maCellData );
}
}
-
- // store the cell formatting data
- setCellFormat( maCurrCell );
}
}
@@ -290,10 +248,7 @@ ContextHandlerRef SheetDataContext::onCreateRecordContext( sal_Int32 nRecId, Seq
switch( getCurrentElement() )
{
case BIFF12_ID_SHEETDATA:
- switch( nRecId )
- {
- case BIFF12_ID_ROW: importRow( rStrm ); return this;
- }
+ if( nRecId == BIFF12_ID_ROW ) { importRow( rStrm ); return this; }
break;
case BIFF12_ID_ROW:
@@ -333,7 +288,7 @@ ContextHandlerRef SheetDataContext::onCreateRecordContext( sal_Int32 nRecId, Seq
void SheetDataContext::importRow( const AttributeList& rAttribs )
{
RowModel aModel;
- aModel.mnFirstRow = aModel.mnLastRow = rAttribs.getInteger( XML_r, -1 );
+ aModel.mnRow = rAttribs.getInteger( XML_r, -1 );
aModel.mfHeight = rAttribs.getDouble( XML_ht, -1.0 );
aModel.mnXfId = rAttribs.getInteger( XML_s, -1 );
aModel.mnLevel = rAttribs.getInteger( XML_outlineLevel, 0 );
@@ -344,41 +299,106 @@ void SheetDataContext::importRow( const AttributeList& rAttribs )
aModel.mbCollapsed = rAttribs.getBool( XML_collapsed, false );
aModel.mbThickTop = rAttribs.getBool( XML_thickTop, false );
aModel.mbThickBottom = rAttribs.getBool( XML_thickBot, false );
+
+ // decode the column spans (space-separated list of colon-separated integer pairs)
+ OUString aColSpansText = rAttribs.getString( XML_spans, OUString() );
+ sal_Int32 nMaxCol = mrAddressConv.getMaxApiAddress().Column;
+ sal_Int32 nIndex = 0;
+ while( nIndex >= 0 )
+ {
+ OUString aColSpanToken = aColSpansText.getToken( 0, ' ', nIndex );
+ sal_Int32 nSepPos = aColSpanToken.indexOf( ':' );
+ if( (0 < nSepPos) && (nSepPos + 1 < aColSpanToken.getLength()) )
+ {
+ // OOXML uses 1-based integer column indexes, row model expects 0-based colspans
+ sal_Int32 nLastCol = ::std::min( aColSpanToken.copy( nSepPos + 1 ).toInt32() - 1, nMaxCol );
+ aModel.insertColSpan( ValueRange( aColSpanToken.copy( 0, nSepPos ).toInt32() - 1, nLastCol ) );
+ }
+ }
+
// set row properties in the current sheet
setRowModel( aModel );
}
-void SheetDataContext::importCell( const AttributeList& rAttribs )
+bool SheetDataContext::importCell( const AttributeList& rAttribs )
{
- maCurrCell.reset();
- maCurrCell.mxCell = getCell( rAttribs.getString( XML_r, OUString() ), &maCurrCell.maAddress );
- maCurrCell.mnCellType = rAttribs.getToken( XML_t, XML_n );
- maCurrCell.mnXfId = rAttribs.getInteger( XML_s, -1 );
- maCurrCell.mbShowPhonetic = rAttribs.getBool( XML_ph, false );
- mxInlineStr.reset();
+ bool bValidAddr = mrAddressConv.convertToCellAddress( maCellData.maCellAddr, rAttribs.getString( XML_r, OUString() ), mnSheet, true );
+ if( bValidAddr )
+ {
+ maCellData.mnCellType = rAttribs.getToken( XML_t, XML_n );
+ maCellData.mnXfId = rAttribs.getInteger( XML_s, -1 );
+ maCellData.mbShowPhonetic = rAttribs.getBool( XML_ph, false );
- // update used area of the sheet
- if( maCurrCell.mxCell.is() )
- extendUsedArea( maCurrCell.maAddress );
+ // reset cell value, formula settings, and inline string
+ maCellValue = OUString();
+ mxInlineStr.reset();
+ mbHasFormula = false;
+
+ // update used area of the sheet
+ extendUsedArea( maCellData.maCellAddr );
+ }
+ return bValidAddr;
}
void SheetDataContext::importFormula( const AttributeList& rAttribs )
{
- maCurrCell.maFormulaRef = rAttribs.getString( XML_ref, OUString() );
- maCurrCell.mnFormulaType = rAttribs.getToken( XML_t, XML_normal );
- maCurrCell.mnSharedId = rAttribs.getInteger( XML_si, -1 );
- maTableData.maRef1 = rAttribs.getString( XML_r1, OUString() );
- maTableData.maRef2 = rAttribs.getString( XML_r2, OUString() );
- maTableData.mb2dTable = rAttribs.getBool( XML_dt2D, false );
- maTableData.mbRowTable = rAttribs.getBool( XML_dtr, false );
- maTableData.mbRef1Deleted = rAttribs.getBool( XML_del1, false );
- maTableData.mbRef2Deleted = rAttribs.getBool( XML_del2, false );
+ mbHasFormula = true;
+ mbValidRange = mrAddressConv.convertToCellRange( maFmlaData.maFormulaRef, rAttribs.getString( XML_ref, OUString() ), mnSheet, true, true );
+
+ maFmlaData.mnFormulaType = rAttribs.getToken( XML_t, XML_normal );
+ maFmlaData.mnSharedId = rAttribs.getInteger( XML_si, -1 );
+
+ if( maFmlaData.mnFormulaType == XML_dataTable )
+ {
+ maTableData.maRef1 = rAttribs.getString( XML_r1, OUString() );
+ maTableData.maRef2 = rAttribs.getString( XML_r2, OUString() );
+ maTableData.mb2dTable = rAttribs.getBool( XML_dt2D, false );
+ maTableData.mbRowTable = rAttribs.getBool( XML_dtr, false );
+ maTableData.mbRef1Deleted = rAttribs.getBool( XML_del1, false );
+ maTableData.mbRef2Deleted = rAttribs.getBool( XML_del2, false );
+ }
+
+ // clear token array, will be regenerated from element text
+ maTokens = ApiTokenSequence();
}
-void SheetDataContext::importCellHeader( SequenceInputStream& rStrm, CellType eCellType )
+void SheetDataContext::importRow( SequenceInputStream& rStrm )
{
- maCurrCell.reset();
+ RowModel aModel;
+ sal_Int32 nSpanCount;
+ sal_uInt16 nHeight, nFlags1;
+ sal_uInt8 nFlags2;
+ rStrm >> maCurrPos.mnRow >> aModel.mnXfId >> nHeight >> nFlags1 >> nFlags2 >> nSpanCount;
+ maCurrPos.mnCol = 0;
+
+ // row index is 0-based in BIFF12, but RowModel expects 1-based
+ aModel.mnRow = maCurrPos.mnRow + 1;
+ // row height is in twips in BIFF12, convert to points
+ aModel.mfHeight = nHeight / 20.0;
+ aModel.mnLevel = extractValue< sal_Int32 >( nFlags1, 8, 3 );
+ aModel.mbCustomHeight = getFlag( nFlags1, BIFF12_ROW_CUSTOMHEIGHT );
+ aModel.mbCustomFormat = getFlag( nFlags1, BIFF12_ROW_CUSTOMFORMAT );
+ aModel.mbShowPhonetic = getFlag( nFlags2, BIFF12_ROW_SHOWPHONETIC );
+ aModel.mbHidden = getFlag( nFlags1, BIFF12_ROW_HIDDEN );
+ aModel.mbCollapsed = getFlag( nFlags1, BIFF12_ROW_COLLAPSED );
+ aModel.mbThickTop = getFlag( nFlags1, BIFF12_ROW_THICKTOP );
+ aModel.mbThickBottom = getFlag( nFlags1, BIFF12_ROW_THICKBOTTOM );
+
+ // read the column spans
+ sal_Int32 nMaxCol = mrAddressConv.getMaxApiAddress().Column;
+ for( sal_Int32 nSpanIdx = 0; (nSpanIdx < nSpanCount) && !rStrm.isEof(); ++nSpanIdx )
+ {
+ sal_Int32 nFirstCol, nLastCol;
+ rStrm >> nFirstCol >> nLastCol;
+ aModel.insertColSpan( ValueRange( nFirstCol, ::std::min( nLastCol, nMaxCol ) ) );
+ }
+
+ // set row properties in the current sheet
+ setRowModel( aModel );
+}
+bool SheetDataContext::readCellHeader( SequenceInputStream& rStrm, CellType eCellType )
+{
switch( eCellType )
{
case CELLTYPE_VALUE:
@@ -389,200 +409,157 @@ void SheetDataContext::importCellHeader( SequenceInputStream& rStrm, CellType eC
sal_uInt32 nXfId;
rStrm >> nXfId;
- maCurrCell.mxCell = getCell( maCurrPos, &maCurrCell.maAddress );
- maCurrCell.mnXfId = extractValue< sal_Int32 >( nXfId, 0, 24 );
- maCurrCell.mbShowPhonetic = getFlag( nXfId, BIFF12_CELL_SHOWPHONETIC );
+ bool bValidAddr = mrAddressConv.convertToCellAddress( maCellData.maCellAddr, maCurrPos, mnSheet, true );
+ maCellData.mnXfId = extractValue< sal_Int32 >( nXfId, 0, 24 );
+ maCellData.mbShowPhonetic = getFlag( nXfId, BIFF12_CELL_SHOWPHONETIC );
// update used area of the sheet
- if( maCurrCell.mxCell.is() )
- extendUsedArea( maCurrCell.maAddress );
+ if( bValidAddr )
+ extendUsedArea( maCellData.maCellAddr );
+ return bValidAddr;
+}
+
+ApiTokenSequence SheetDataContext::readCellFormula( SequenceInputStream& rStrm )
+{
+ rStrm.skip( 2 );
+ return mrFormulaParser.importFormula( maCellData.maCellAddr, FORMULATYPE_CELL, rStrm );
+}
+
+bool SheetDataContext::readFormulaRef( SequenceInputStream& rStrm )
+{
+ BinRange aRange;
+ rStrm >> aRange;
+ return mrAddressConv.convertToCellRange( maFmlaData.maFormulaRef, aRange, mnSheet, true, true );
}
void SheetDataContext::importCellBool( SequenceInputStream& rStrm, CellType eCellType )
{
- importCellHeader( rStrm, eCellType );
- maCurrCell.mnCellType = XML_b;
- if( maCurrCell.mxCell.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) )
+ if( readCellHeader( rStrm, eCellType ) )
{
+ maCellData.mnCellType = XML_b;
bool bValue = rStrm.readuInt8() != 0;
if( eCellType == CELLTYPE_FORMULA )
- {
- importCellFormula( rStrm );
- }
+ mrSheetData.setFormulaCell( maCellData, readCellFormula( rStrm ) );
else
- {
- setBooleanCell( maCurrCell.mxCell, bValue );
- // #108770# set 'Standard' number format for all Boolean cells
- maCurrCell.mnNumFmtId = 0;
- }
+ mrSheetData.setBooleanCell( maCellData, bValue );
}
- setCellFormat( maCurrCell );
}
void SheetDataContext::importCellBlank( SequenceInputStream& rStrm, CellType eCellType )
{
OSL_ENSURE( eCellType != CELLTYPE_FORMULA, "SheetDataContext::importCellBlank - no formula cells supported" );
- importCellHeader( rStrm, eCellType );
- setCellFormat( maCurrCell );
+ if( readCellHeader( rStrm, eCellType ) )
+ mrSheetData.setBlankCell( maCellData );
}
void SheetDataContext::importCellDouble( SequenceInputStream& rStrm, CellType eCellType )
{
- importCellHeader( rStrm, eCellType );
- maCurrCell.mnCellType = XML_n;
- if( maCurrCell.mxCell.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) )
+ if( readCellHeader( rStrm, eCellType ) )
{
+ maCellData.mnCellType = XML_n;
double fValue = rStrm.readDouble();
if( eCellType == CELLTYPE_FORMULA )
- importCellFormula( rStrm );
+ mrSheetData.setFormulaCell( maCellData, readCellFormula( rStrm ) );
else
- maCurrCell.mxCell->setValue( fValue );
+ mrSheetData.setValueCell( maCellData, fValue );
}
- setCellFormat( maCurrCell );
}
void SheetDataContext::importCellError( SequenceInputStream& rStrm, CellType eCellType )
{
- importCellHeader( rStrm, eCellType );
- maCurrCell.mnCellType = XML_e;
- if( maCurrCell.mxCell.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) )
+ if( readCellHeader( rStrm, eCellType ) )
{
+ maCellData.mnCellType = XML_e;
sal_uInt8 nErrorCode = rStrm.readuInt8();
if( eCellType == CELLTYPE_FORMULA )
- importCellFormula( rStrm );
+ mrSheetData.setFormulaCell( maCellData, readCellFormula( rStrm ) );
else
- setErrorCell( maCurrCell.mxCell, nErrorCode );
+ mrSheetData.setErrorCell( maCellData, nErrorCode );
}
- setCellFormat( maCurrCell );
}
void SheetDataContext::importCellRk( SequenceInputStream& rStrm, CellType eCellType )
{
OSL_ENSURE( eCellType != CELLTYPE_FORMULA, "SheetDataContext::importCellRk - no formula cells supported" );
- importCellHeader( rStrm, eCellType );
- maCurrCell.mnCellType = XML_n;
- if( maCurrCell.mxCell.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) )
- maCurrCell.mxCell->setValue( BiffHelper::calcDoubleFromRk( rStrm.readInt32() ) );
- setCellFormat( maCurrCell );
+ if( readCellHeader( rStrm, eCellType ) )
+ {
+ maCellData.mnCellType = XML_n;
+ mrSheetData.setValueCell( maCellData, BiffHelper::calcDoubleFromRk( rStrm.readInt32() ) );
+ }
}
void SheetDataContext::importCellRString( SequenceInputStream& rStrm, CellType eCellType )
{
OSL_ENSURE( eCellType != CELLTYPE_FORMULA, "SheetDataContext::importCellRString - no formula cells supported" );
- importCellHeader( rStrm, eCellType );
- maCurrCell.mnCellType = XML_inlineStr;
- Reference< XText > xText( maCurrCell.mxCell, UNO_QUERY );
- if( xText.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) )
+ if( readCellHeader( rStrm, eCellType ) )
{
- RichString aString( *this );
- aString.importString( rStrm, true );
- aString.finalizeImport();
- aString.convert( xText, maCurrCell.mnXfId );
+ maCellData.mnCellType = XML_inlineStr;
+ RichStringRef xString( new RichString( *this ) );
+ xString->importString( rStrm, true );
+ xString->finalizeImport();
+ mrSheetData.setStringCell( maCellData, xString );
}
- setCellFormat( maCurrCell );
}
void SheetDataContext::importCellSi( SequenceInputStream& rStrm, CellType eCellType )
{
OSL_ENSURE( eCellType != CELLTYPE_FORMULA, "SheetDataContext::importCellSi - no formula cells supported" );
- importCellHeader( rStrm, eCellType );
- maCurrCell.mnCellType = XML_s;
- if( maCurrCell.mxCell.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) )
- setSharedStringCell( maCurrCell.mxCell, rStrm.readInt32(), maCurrCell.mnXfId );
- setCellFormat( maCurrCell );
+ if( readCellHeader( rStrm, eCellType ) )
+ {
+ maCellData.mnCellType = XML_s;
+ mrSheetData.setStringCell( maCellData, rStrm.readInt32() );
+ }
}
void SheetDataContext::importCellString( SequenceInputStream& rStrm, CellType eCellType )
{
- importCellHeader( rStrm, eCellType );
- maCurrCell.mnCellType = XML_inlineStr;
- Reference< XText > xText( maCurrCell.mxCell, UNO_QUERY );
- if( xText.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) )
+ if( readCellHeader( rStrm, eCellType ) )
{
- RichString aString( *this );
- aString.importString( rStrm, false );
- aString.finalizeImport();
+ maCellData.mnCellType = XML_inlineStr;
+ // always import the string, stream will point to formula afterwards, if existing
+ RichStringRef xString( new RichString( *this ) );
+ xString->importString( rStrm, false );
+ xString->finalizeImport();
if( eCellType == CELLTYPE_FORMULA )
- importCellFormula( rStrm );
+ mrSheetData.setFormulaCell( maCellData, readCellFormula( rStrm ) );
else
- aString.convert( xText, maCurrCell.mnXfId );
- }
- setCellFormat( maCurrCell );
-}
-
-void SheetDataContext::importCellFormula( SequenceInputStream& rStrm )
-{
- rStrm.skip( 2 );
- Reference< XFormulaTokens > xTokens( maCurrCell.mxCell, UNO_QUERY );
- if( xTokens.is() )
- {
- ExtCellFormulaContext aContext( *this, xTokens, maCurrCell.maAddress );
- getFormulaParser().importFormula( aContext, rStrm );
+ mrSheetData.setStringCell( maCellData, xString );
}
}
-void SheetDataContext::importRow( SequenceInputStream& rStrm )
-{
- RowModel aModel;
-
- sal_uInt16 nHeight, nFlags1;
- sal_uInt8 nFlags2;
- rStrm >> maCurrPos.mnRow >> aModel.mnXfId >> nHeight >> nFlags1 >> nFlags2;
-
- // row index is 0-based in BIFF12, but RowModel expects 1-based
- aModel.mnFirstRow = aModel.mnLastRow = maCurrPos.mnRow + 1;
- // row height is in twips in BIFF12, convert to points
- aModel.mfHeight = nHeight / 20.0;
- aModel.mnLevel = extractValue< sal_Int32 >( nFlags1, 8, 3 );
- aModel.mbCustomHeight = getFlag( nFlags1, BIFF12_ROW_CUSTOMHEIGHT );
- aModel.mbCustomFormat = getFlag( nFlags1, BIFF12_ROW_CUSTOMFORMAT );
- aModel.mbShowPhonetic = getFlag( nFlags2, BIFF12_ROW_SHOWPHONETIC );
- aModel.mbHidden = getFlag( nFlags1, BIFF12_ROW_HIDDEN );
- aModel.mbCollapsed = getFlag( nFlags1, BIFF12_ROW_COLLAPSED );
- aModel.mbThickTop = getFlag( nFlags1, BIFF12_ROW_THICKTOP );
- aModel.mbThickBottom = getFlag( nFlags1, BIFF12_ROW_THICKBOTTOM );
- // set row properties in the current sheet
- setRowModel( aModel );
-}
-
void SheetDataContext::importArray( SequenceInputStream& rStrm )
{
- BinRange aRange;
- rStrm >> aRange;
- CellRangeAddress aArrayRange;
- Reference< XCellRange > xRange = getCellRange( aRange, &aArrayRange );
- Reference< XArrayFormulaTokens > xTokens( xRange, UNO_QUERY );
- if( xRange.is() && xTokens.is() )
+ if( readFormulaRef( rStrm ) && maFmlaData.isValidArrayRef( maCellData.maCellAddr ) )
{
rStrm.skip( 1 );
- ArrayFormulaContext aContext( xTokens, aArrayRange );
- getFormulaParser().importFormula( aContext, rStrm );
+ ApiTokenSequence aTokens = mrFormulaParser.importFormula( maCellData.maCellAddr, FORMULATYPE_ARRAY, rStrm );
+ mrSheetData.createArrayFormula( maFmlaData.maFormulaRef, aTokens );
}
}
-void SheetDataContext::importSharedFmla( SequenceInputStream& rStrm )
-{
- getSharedFormulas().importSharedFmla( rStrm, maCurrCell.maAddress );
-}
-
void SheetDataContext::importDataTable( SequenceInputStream& rStrm )
{
- BinRange aRange;
- rStrm >> aRange;
- CellRangeAddress aTableRange;
- if( getAddressConverter().convertToCellRange( aTableRange, aRange, getSheetIndex(), true, true ) )
+ if( readFormulaRef( rStrm ) )
{
- DataTableModel aModel;
BinAddress aRef1, aRef2;
sal_uInt8 nFlags;
rStrm >> aRef1 >> aRef2 >> nFlags;
- aModel.maRef1 = FormulaProcessorBase::generateAddress2dString( aRef1, false );
- aModel.maRef2 = FormulaProcessorBase::generateAddress2dString( aRef2, false );
- aModel.mbRowTable = getFlag( nFlags, BIFF12_DATATABLE_ROW );
- aModel.mb2dTable = getFlag( nFlags, BIFF12_DATATABLE_2D );
- aModel.mbRef1Deleted = getFlag( nFlags, BIFF12_DATATABLE_REF1DEL );
- aModel.mbRef2Deleted = getFlag( nFlags, BIFF12_DATATABLE_REF2DEL );
- setTableOperation( aTableRange, aModel );
+ maTableData.maRef1 = FormulaProcessorBase::generateAddress2dString( aRef1, false );
+ maTableData.maRef2 = FormulaProcessorBase::generateAddress2dString( aRef2, false );
+ maTableData.mbRowTable = getFlag( nFlags, BIFF12_DATATABLE_ROW );
+ maTableData.mb2dTable = getFlag( nFlags, BIFF12_DATATABLE_2D );
+ maTableData.mbRef1Deleted = getFlag( nFlags, BIFF12_DATATABLE_REF1DEL );
+ maTableData.mbRef2Deleted = getFlag( nFlags, BIFF12_DATATABLE_REF2DEL );
+ mrSheetData.createTableOperation( maFmlaData.maFormulaRef, maTableData );
+ }
+}
+
+void SheetDataContext::importSharedFmla( SequenceInputStream& rStrm )
+{
+ if( readFormulaRef( rStrm ) && maFmlaData.isValidSharedRef( maCellData.maCellAddr ) )
+ {
+ ApiTokenSequence aTokens = mrFormulaParser.importFormula( maCellData.maCellAddr, FORMULATYPE_SHAREDFORMULA, rStrm );
+ mrSheetData.createSharedFormula( maCellData.maCellAddr, aTokens );
}
}
@@ -590,26 +567,27 @@ void SheetDataContext::importDataTable( SequenceInputStream& rStrm )
BiffSheetDataContext::BiffSheetDataContext( const WorksheetHelper& rHelper ) :
BiffWorksheetContextBase( rHelper ),
+ SheetDataContextBase( rHelper ),
mnBiff2XfId( 0 )
{
- mnArrayIgnoreSize = (getBiff() == BIFF2) ? 1 : ((getBiff() <= BIFF4) ? 2 : 6);
switch( getBiff() )
{
case BIFF2:
- mnFormulaIgnoreSize = 9; // double formula result, 1 byte flags
- mnArrayIgnoreSize = 1; // recalc-always flag
+ mnFormulaSkipSize = 9; // double formula result, 1 byte flags
+ mnArraySkipSize = 1; // recalc-always flag
break;
case BIFF3:
case BIFF4:
- mnFormulaIgnoreSize = 10; // double formula result, 2 byte flags
- mnArrayIgnoreSize = 2; // 2 byte flags
+ mnFormulaSkipSize = 10; // double formula result, 2 byte flags
+ mnArraySkipSize = 2; // 2 byte flags
break;
case BIFF5:
case BIFF8:
- mnFormulaIgnoreSize = 14; // double formula result, 2 byte flags, 4 bytes nothing
- mnArrayIgnoreSize = 6; // 2 byte flags, 4 bytes nothing
+ mnFormulaSkipSize = 14; // double formula result, 2 byte flags, 4 bytes nothing
+ mnArraySkipSize = 6; // 2 byte flags, 4 bytes nothing
+ break;
+ case BIFF_UNKNOWN:
break;
- case BIFF_UNKNOWN: break;
}
}
@@ -690,258 +668,285 @@ void BiffSheetDataContext::importRecord( BiffInputStream& rStrm )
}
break;
- case BIFF_UNKNOWN: break;
+ case BIFF_UNKNOWN:
+ break;
}
}
}
// private --------------------------------------------------------------------
-void BiffSheetDataContext::setCurrCell( const BinAddress& rAddr )
-{
- maCurrCell.reset();
- maCurrCell.mxCell = getCell( rAddr, &maCurrCell.maAddress );
- // update used area of the sheet
- if( maCurrCell.mxCell.is() )
- extendUsedArea( maCurrCell.maAddress );
-}
-
-void BiffSheetDataContext::importXfId( BiffInputStream& rStrm, bool bBiff2 )
+void BiffSheetDataContext::importRow( BiffInputStream& rStrm )
{
- if( bBiff2 )
+ RowModel aModel;
+ sal_uInt16 nRow, nFirstUsedCol, nFirstFreeCol, nHeight;
+ rStrm >> nRow >> nFirstUsedCol >> nFirstFreeCol >> nHeight;
+ if( getBiff() == BIFF2 )
{
- sal_uInt8 nBiff2XfId;
- rStrm >> nBiff2XfId;
rStrm.skip( 2 );
- maCurrCell.mnXfId = nBiff2XfId & BIFF2_XF_MASK;
- if( maCurrCell.mnXfId == BIFF2_XF_EXTENDED_IDS )
- maCurrCell.mnXfId = mnBiff2XfId;
+ aModel.mbCustomFormat = rStrm.readuInt8() == BIFF2_ROW_CUSTOMFORMAT;
+ if( aModel.mbCustomFormat )
+ {
+ rStrm.skip( 5 );
+ aModel.mnXfId = rStrm.readuInt16();
+ }
}
else
{
- maCurrCell.mnXfId = rStrm.readuInt16();
+ rStrm.skip( 4 );
+ sal_uInt32 nFlags = rStrm.readuInt32();
+ aModel.mnXfId = extractValue< sal_Int32 >( nFlags, 16, 12 );
+ aModel.mnLevel = extractValue< sal_Int32 >( nFlags, 0, 3 );
+ aModel.mbCustomFormat = getFlag( nFlags, BIFF_ROW_CUSTOMFORMAT );
+ aModel.mbCustomHeight = getFlag( nFlags, BIFF_ROW_CUSTOMHEIGHT );
+ aModel.mbShowPhonetic = getFlag( nFlags, BIFF_ROW_SHOWPHONETIC );
+ aModel.mbHidden = getFlag( nFlags, BIFF_ROW_HIDDEN );
+ aModel.mbCollapsed = getFlag( nFlags, BIFF_ROW_COLLAPSED );
+ aModel.mbThickTop = getFlag( nFlags, BIFF_ROW_THICKTOP );
+ aModel.mbThickBottom = getFlag( nFlags, BIFF_ROW_THICKBOTTOM );
+ }
+
+ // row index is 0-based in BIFF, but RowModel expects 1-based
+ aModel.mnRow = static_cast< sal_Int32 >( nRow ) + 1;
+ // row height is in twips in BIFF, convert to points
+ aModel.mfHeight = (nHeight & BIFF_ROW_HEIGHTMASK) / 20.0;
+ // set column spans
+ if( nFirstUsedCol < nFirstFreeCol )
+ {
+ sal_Int32 nLastCol = ::std::min< sal_Int32 >( nFirstFreeCol - 1, mrAddressConv.getMaxApiAddress().Column );
+ aModel.insertColSpan( ValueRange( nFirstUsedCol, nLastCol ) );
+ }
+
+ // set row properties in the current sheet
+ setRowModel( aModel );
+}
+
+bool BiffSheetDataContext::readCellXfId( BiffInputStream& rStrm, const BinAddress& rAddr, bool bBiff2 )
+{
+ bool bValidAddr = mrAddressConv.convertToCellAddress( maCellData.maCellAddr, rAddr, mnSheet, true );
+ if( bValidAddr )
+ {
+ // update used area of the sheet
+ extendUsedArea( maCellData.maCellAddr );
+
+ // load the XF identifier according to current BIFF version
+ if( bBiff2 )
+ {
+ /* #i71453# On first call, check if the file contains XF records
+ (by trying to access the first XF with index 0). If there are
+ no XFs, the explicit formatting information contained in each
+ cell record will be used instead. */
+ if( !mobBiff2HasXfs )
+ mobBiff2HasXfs = getStyles().getCellXf( 0 ).get() != 0;
+ // read formatting information (includes the XF identifier)
+ sal_uInt8 nFlags1, nFlags2, nFlags3;
+ rStrm >> nFlags1 >> nFlags2 >> nFlags3;
+ /* If the file contains XFs, extract and set the XF identifier,
+ otherwise get the explicit formatting. */
+ if( mobBiff2HasXfs.get() )
+ {
+ maCellData.mnXfId = extractValue< sal_Int32 >( nFlags1, 0, 6 );
+ /* If the identifier is equal to 63, then the real identifier
+ is contained in the preceding IXFE record (stored in the
+ class member mnBiff2XfId). */
+ if( maCellData.mnXfId == BIFF2_CELL_USEIXFE )
+ maCellData.mnXfId = mnBiff2XfId;
+ }
+ else
+ {
+ /* Let the Xf class do the API conversion. Keeping the member
+ maCellData.mnXfId untouched will prevent to trigger the
+ usual XF formatting conversion later on. */
+ PropertySet aPropSet( getCell( maCellData.maCellAddr ) );
+ Xf::writeBiff2CellFormatToPropertySet( *this, aPropSet, nFlags1, nFlags2, nFlags3 );
+ }
+ }
+ else
+ {
+ // BIFF3-BIFF8: 16-bit XF identifier
+ maCellData.mnXfId = rStrm.readuInt16();
+ }
}
+ return bValidAddr;
}
-void BiffSheetDataContext::importCellHeader( BiffInputStream& rStrm, bool bBiff2 )
+bool BiffSheetDataContext::readCellHeader( BiffInputStream& rStrm, bool bBiff2 )
{
BinAddress aAddr;
rStrm >> aAddr;
- setCurrCell( aAddr );
- importXfId( rStrm, bBiff2 );
+ return readCellXfId( rStrm, aAddr, bBiff2 );
+}
+
+bool BiffSheetDataContext::readFormulaRef( BiffInputStream& rStrm )
+{
+ BinRange aRange;
+ aRange.read( rStrm, false ); // columns always 8-bit
+ return mrAddressConv.convertToCellRange( maFmlaData.maFormulaRef, aRange, mnSheet, true, true );
}
void BiffSheetDataContext::importBlank( BiffInputStream& rStrm )
{
- importCellHeader( rStrm, rStrm.getRecId() == BIFF2_ID_BLANK );
- setCellFormat( maCurrCell );
+ if( readCellHeader( rStrm, rStrm.getRecId() == BIFF2_ID_BLANK ) )
+ mrSheetData.setBlankCell( maCellData );
}
void BiffSheetDataContext::importBoolErr( BiffInputStream& rStrm )
{
- importCellHeader( rStrm, rStrm.getRecId() == BIFF2_ID_BOOLERR );
- if( maCurrCell.mxCell.is() )
+ if( readCellHeader( rStrm, rStrm.getRecId() == BIFF2_ID_BOOLERR ) )
{
sal_uInt8 nValue, nType;
rStrm >> nValue >> nType;
switch( nType )
{
case BIFF_BOOLERR_BOOL:
- maCurrCell.mnCellType = XML_b;
- setBooleanCell( maCurrCell.mxCell, nValue != 0 );
- // #108770# set 'Standard' number format for all Boolean cells
- maCurrCell.mnNumFmtId = 0;
+ maCellData.mnCellType = XML_b;
+ mrSheetData.setBooleanCell( maCellData, nValue != 0 );
break;
case BIFF_BOOLERR_ERROR:
- maCurrCell.mnCellType = XML_e;
- setErrorCell( maCurrCell.mxCell, nValue );
+ maCellData.mnCellType = XML_e;
+ mrSheetData.setErrorCell( maCellData, nValue );
break;
default:
OSL_FAIL( "BiffSheetDataContext::importBoolErr - unknown cell type" );
+ maCellData.mnCellType = XML_TOKEN_INVALID;
+ mrSheetData.setBlankCell( maCellData );
+ break;
}
}
- setCellFormat( maCurrCell );
}
void BiffSheetDataContext::importFormula( BiffInputStream& rStrm )
{
- importCellHeader( rStrm, getBiff() == BIFF2 );
- maCurrCell.mnCellType = XML_n;
- Reference< XFormulaTokens > xTokens( maCurrCell.mxCell, UNO_QUERY );
- if( xTokens.is() )
+ if( readCellHeader( rStrm, getBiff() == BIFF2 ) )
{
- rStrm.skip( mnFormulaIgnoreSize );
- ExtCellFormulaContext aContext( *this, xTokens, maCurrCell.maAddress );
- getFormulaParser().importFormula( aContext, rStrm );
+ maCellData.mnCellType = XML_n;
+ rStrm.skip( mnFormulaSkipSize );
+ ApiTokenSequence aTokens = mrFormulaParser.importFormula( maCellData.maCellAddr, FORMULATYPE_CELL, rStrm );
+ mrSheetData.setFormulaCell( maCellData, aTokens );
}
- setCellFormat( maCurrCell );
}
void BiffSheetDataContext::importInteger( BiffInputStream& rStrm )
{
- importCellHeader( rStrm, true );
- maCurrCell.mnCellType = XML_n;
- if( maCurrCell.mxCell.is() )
- maCurrCell.mxCell->setValue( rStrm.readuInt16() );
- setCellFormat( maCurrCell );
+ if( readCellHeader( rStrm, true ) )
+ {
+ maCellData.mnCellType = XML_n;
+ mrSheetData.setValueCell( maCellData, rStrm.readuInt16() );
+ }
}
void BiffSheetDataContext::importLabel( BiffInputStream& rStrm )
{
+ /* the deep secrets of BIFF type and record identifier...
+ record id BIFF -> XF type String type
+ 0x0004 2-7 -> 3 byte 8-bit length, byte string
+ 0x0004 8 -> 3 byte 16-bit length, unicode string
+ 0x0204 2-7 -> 2 byte 16-bit length, byte string
+ 0x0204 8 -> 2 byte 16-bit length, unicode string
+ */
bool bBiff2Xf = rStrm.getRecId() == BIFF2_ID_LABEL;
- importCellHeader( rStrm, bBiff2Xf );
- maCurrCell.mnCellType = XML_inlineStr;
- Reference< XText > xText( maCurrCell.mxCell, UNO_QUERY );
- if( xText.is() )
- {
- /* the deep secrets of BIFF type and record identifier...
- record id BIFF -> XF type String type
- 0x0004 2-7 -> 3 byte 8-bit length, byte string
- 0x0004 8 -> 3 byte 16-bit length, unicode string
- 0x0204 2-7 -> 2 byte 16-bit length, byte string
- 0x0204 8 -> 2 byte 16-bit length, unicode string */
-
- RichString aString( *this );
+ if( readCellHeader( rStrm, bBiff2Xf ) )
+ {
+ maCellData.mnCellType = XML_inlineStr;
if( getBiff() == BIFF8 )
{
- aString.importUniString( rStrm );
+ // string may contain rich-text formatting
+ RichStringRef xString( new RichString( *this ) );
+ xString->importUniString( rStrm );
+ xString->finalizeImport();
+ mrSheetData.setStringCell( maCellData, xString );
}
else
{
// #i63105# use text encoding from FONT record
rtl_TextEncoding eTextEnc = getTextEncoding();
- if( const Font* pFont = getStyles().getFontFromCellXf( maCurrCell.mnXfId ).get() )
+ if( const Font* pFont = getStyles().getFontFromCellXf( maCellData.mnXfId ).get() )
eTextEnc = pFont->getFontEncoding();
- BiffStringFlags nFlags = bBiff2Xf ? BIFF_STR_8BITLENGTH : BIFF_STR_DEFAULT;
- setFlag( nFlags, BIFF_STR_EXTRAFONTS, rStrm.getRecId() == BIFF_ID_RSTRING );
- aString.importByteString( rStrm, eTextEnc, nFlags );
+ // RSTRING record contains rich-text formatting
+ if( rStrm.getRecId() == BIFF_ID_RSTRING )
+ {
+ BiffStringFlags nFlags = BIFF_STR_EXTRAFONTS;
+ // BIFF2 record identifier: 8-bit string length (see above)
+ setFlag( nFlags, BIFF_STR_8BITLENGTH, bBiff2Xf );
+ RichStringRef xString( new RichString( *this ) );
+ xString->importByteString( rStrm, eTextEnc, nFlags );
+ xString->finalizeImport();
+ mrSheetData.setStringCell( maCellData, xString );
+ }
+ else
+ {
+ // BIFF2 record identifier: 8-bit string length (see above)
+ OUString aText = rStrm.readByteStringUC( !bBiff2Xf, eTextEnc );
+ mrSheetData.setStringCell( maCellData, aText );
+ }
}
- aString.finalizeImport();
- aString.convert( xText, maCurrCell.mnXfId );
}
- setCellFormat( maCurrCell );
}
void BiffSheetDataContext::importLabelSst( BiffInputStream& rStrm )
{
- importCellHeader( rStrm, false );
- maCurrCell.mnCellType = XML_s;
- if( maCurrCell.mxCell.is() )
- setSharedStringCell( maCurrCell.mxCell, rStrm.readInt32(), maCurrCell.mnXfId );
- setCellFormat( maCurrCell );
+ if( readCellHeader( rStrm, false ) )
+ {
+ maCellData.mnCellType = XML_s;
+ mrSheetData.setStringCell( maCellData, rStrm.readInt32() );
+ }
}
void BiffSheetDataContext::importMultBlank( BiffInputStream& rStrm )
{
BinAddress aAddr;
- for( rStrm >> aAddr; rStrm.getRemaining() > 2; ++aAddr.mnCol )
- {
- setCurrCell( aAddr );
- importXfId( rStrm, false );
- setCellFormat( maCurrCell );
- }
+ bool bValidAddr = true;
+ for( rStrm >> aAddr; bValidAddr && (rStrm.getRemaining() > 2); ++aAddr.mnCol )
+ if( (bValidAddr = readCellXfId( rStrm, aAddr, false )) == true )
+ mrSheetData.setBlankCell( maCellData );
}
void BiffSheetDataContext::importMultRk( BiffInputStream& rStrm )
{
BinAddress aAddr;
- for( rStrm >> aAddr; rStrm.getRemaining() > 2; ++aAddr.mnCol )
+ bool bValidAddr = true;
+ for( rStrm >> aAddr; bValidAddr && (rStrm.getRemaining() > 2); ++aAddr.mnCol )
{
- setCurrCell( aAddr );
- maCurrCell.mnCellType = XML_n;
- importXfId( rStrm, false );
- sal_Int32 nRkValue = rStrm.readInt32();
- if( maCurrCell.mxCell.is() )
- maCurrCell.mxCell->setValue( BiffHelper::calcDoubleFromRk( nRkValue ) );
- setCellFormat( maCurrCell );
+ if( (bValidAddr = readCellXfId( rStrm, aAddr, false )) == true )
+ {
+ maCellData.mnCellType = XML_n;
+ sal_Int32 nRkValue = rStrm.readInt32();
+ mrSheetData.setValueCell( maCellData, BiffHelper::calcDoubleFromRk( nRkValue ) );
+ }
}
}
void BiffSheetDataContext::importNumber( BiffInputStream& rStrm )
{
- importCellHeader( rStrm, rStrm.getRecId() == BIFF2_ID_NUMBER );
- maCurrCell.mnCellType = XML_n;
- if( maCurrCell.mxCell.is() )
- maCurrCell.mxCell->setValue( rStrm.readDouble() );
- setCellFormat( maCurrCell );
+ if( readCellHeader( rStrm, rStrm.getRecId() == BIFF2_ID_NUMBER ) )
+ {
+ maCellData.mnCellType = XML_n;
+ mrSheetData.setValueCell( maCellData, rStrm.readDouble() );
+ }
}
void BiffSheetDataContext::importRk( BiffInputStream& rStrm )
{
- importCellHeader( rStrm, false );
- maCurrCell.mnCellType = XML_n;
- if( maCurrCell.mxCell.is() )
- maCurrCell.mxCell->setValue( BiffHelper::calcDoubleFromRk( rStrm.readInt32() ) );
- setCellFormat( maCurrCell );
-}
-
-void BiffSheetDataContext::importRow( BiffInputStream& rStrm )
-{
- RowModel aModel;
-
- sal_uInt16 nRow, nHeight;
- rStrm >> nRow;
- rStrm.skip( 4 );
- rStrm >> nHeight;
- if( getBiff() == BIFF2 )
+ if( readCellHeader( rStrm, false ) )
{
- rStrm.skip( 2 );
- aModel.mbCustomFormat = rStrm.readuInt8() == BIFF2_ROW_CUSTOMFORMAT;
- if( aModel.mbCustomFormat )
- {
- rStrm.skip( 5 );
- aModel.mnXfId = rStrm.readuInt16();
- }
+ maCellData.mnCellType = XML_n;
+ mrSheetData.setValueCell( maCellData, BiffHelper::calcDoubleFromRk( rStrm.readInt32() ) );
}
- else
- {
- rStrm.skip( 4 );
- sal_uInt32 nFlags = rStrm.readuInt32();
- aModel.mnXfId = extractValue< sal_Int32 >( nFlags, 16, 12 );
- aModel.mnLevel = extractValue< sal_Int32 >( nFlags, 0, 3 );
- aModel.mbCustomFormat = getFlag( nFlags, BIFF_ROW_CUSTOMFORMAT );
- aModel.mbCustomHeight = getFlag( nFlags, BIFF_ROW_CUSTOMHEIGHT );
- aModel.mbShowPhonetic = getFlag( nFlags, BIFF_ROW_SHOWPHONETIC );
- aModel.mbHidden = getFlag( nFlags, BIFF_ROW_HIDDEN );
- aModel.mbCollapsed = getFlag( nFlags, BIFF_ROW_COLLAPSED );
- aModel.mbThickTop = getFlag( nFlags, BIFF_ROW_THICKTOP );
- aModel.mbThickBottom = getFlag( nFlags, BIFF_ROW_THICKBOTTOM );
- }
-
- // row index is 0-based in BIFF, but RowModel expects 1-based
- aModel.mnFirstRow = aModel.mnLastRow = nRow + 1;
- // row height is in twips in BIFF, convert to points
- aModel.mfHeight = (nHeight & BIFF_ROW_HEIGHTMASK) / 20.0;
- // set row properties in the current sheet
- setRowModel( aModel );
}
void BiffSheetDataContext::importArray( BiffInputStream& rStrm )
{
- BinRange aRange;
- aRange.read( rStrm, false ); // columns always 8-bit
- CellRangeAddress aArrayRange;
- Reference< XCellRange > xRange = getCellRange( aRange, &aArrayRange );
- Reference< XArrayFormulaTokens > xTokens( xRange, UNO_QUERY );
- if( xRange.is() && xTokens.is() )
+ if( readFormulaRef( rStrm ) && maFmlaData.isValidArrayRef( maCellData.maCellAddr ) )
{
- rStrm.skip( mnArrayIgnoreSize );
- ArrayFormulaContext aContext( xTokens, aArrayRange );
- getFormulaParser().importFormula( aContext, rStrm );
+ rStrm.skip( mnArraySkipSize );
+ ApiTokenSequence aTokens = mrFormulaParser.importFormula( maCellData.maCellAddr, FORMULATYPE_ARRAY, rStrm );
+ mrSheetData.createArrayFormula( maFmlaData.maFormulaRef, aTokens );
}
}
-void BiffSheetDataContext::importSharedFmla( BiffInputStream& rStrm )
-{
- getSharedFormulas().importSharedFmla( rStrm, maCurrCell.maAddress );
-}
-
void BiffSheetDataContext::importDataTable( BiffInputStream& rStrm )
{
- BinRange aRange;
- aRange.read( rStrm, false ); // columns always 8-bit
- CellRangeAddress aTableRange;
- if( getAddressConverter().convertToCellRange( aTableRange, aRange, getSheetIndex(), true, true ) )
+ if( readFormulaRef( rStrm ) )
{
DataTableModel aModel;
BinAddress aRef1, aRef2;
@@ -973,7 +978,17 @@ void BiffSheetDataContext::importDataTable( BiffInputStream& rStrm )
}
aModel.maRef1 = FormulaProcessorBase::generateAddress2dString( aRef1, false );
aModel.maRef2 = FormulaProcessorBase::generateAddress2dString( aRef2, false );
- setTableOperation( aTableRange, aModel );
+ mrSheetData.createTableOperation( maFmlaData.maFormulaRef, aModel );
+ }
+}
+
+void BiffSheetDataContext::importSharedFmla( BiffInputStream& rStrm )
+{
+ if( readFormulaRef( rStrm ) && maFmlaData.isValidSharedRef( maCellData.maCellAddr ) )
+ {
+ rStrm.skip( 2 ); // flags
+ ApiTokenSequence aTokens = mrFormulaParser.importFormula( maCellData.maCellAddr, FORMULATYPE_SHAREDFORMULA, rStrm );
+ mrSheetData.createSharedFormula( maCellData.maCellAddr, aTokens );
}
}
diff --git a/oox/source/xls/stylesbuffer.cxx b/oox/source/xls/stylesbuffer.cxx
index e7967b785449..5daf7cebb9ef 100644
--- a/oox/source/xls/stylesbuffer.cxx
+++ b/oox/source/xls/stylesbuffer.cxx
@@ -2540,6 +2540,41 @@ void Xf::writeToPropertySet( PropertySet& rPropSet ) const
rPropSet.setProperties( aPropMap );
}
+/*static*/ void Xf::writeBiff2CellFormatToPropertySet( const WorkbookHelper& rHelper,
+ PropertySet& rPropSet, sal_uInt8 nFlags1, sal_uInt8 nFlags2, sal_uInt8 nFlags3 )
+{
+ /* Create an XF object and let it do the work. We will have access to its
+ private members here. Also, create temporary border and fill objects,
+ this prevents polluting the border and fill buffers with new temporary
+ objects per imported cell. */
+ Xf aXf( rHelper );
+ Border aBorder( rHelper, false );
+ Fill aFill( rHelper, false );
+
+ // no used flags available in BIFF2 (always true)
+ aXf.setAllUsedFlags( true );
+
+ // set the attributes
+ aXf.maModel.mnFontId = extractValue< sal_Int32 >( nFlags2, 6, 2 );
+ aXf.maModel.mnNumFmtId = extractValue< sal_Int32 >( nFlags2, 0, 6 );
+ aXf.maAlignment.setBiff2Data( nFlags3 );
+ aXf.maProtection.setBiff2Data( nFlags1 );
+ aBorder.setBiff2Data( nFlags3 );
+ aFill.setBiff2Data( nFlags3 );
+
+ // finalize the objects (convert model to API attributes)
+ aXf.finalizeImport();
+ aBorder.finalizeImport();
+ aFill.finalizeImport();
+
+ // write the properties to the property set
+ PropertyMap aPropMap;
+ aXf.writeToPropertyMap( aPropMap );
+ aBorder.writeToPropertyMap( aPropMap );
+ aFill.writeToPropertyMap( aPropMap );
+ rPropSet.setProperties( aPropMap );
+}
+
void Xf::setBiffUsedFlags( sal_uInt8 nUsedFlags )
{
/* Notes about finding the used flags:
diff --git a/oox/source/xls/viewsettings.cxx b/oox/source/xls/viewsettings.cxx
index c4ed0aa765eb..1eb07c76afc8 100644
--- a/oox/source/xls/viewsettings.cxx
+++ b/oox/source/xls/viewsettings.cxx
@@ -735,7 +735,7 @@ void ViewSettings::finalizeImport()
sal_Int16 nShowMode = getWorkbookSettings().getApiShowObjectMode();
// view settings for all sheets
- Reference< XNameContainer > xSheetsNC = ContainerHelper::createNameContainer( getGlobalFactory() );
+ Reference< XNameContainer > xSheetsNC = ContainerHelper::createNameContainer( getBaseFilter().getComponentContext() );
if( !xSheetsNC.is() ) return;
for( SheetPropertiesMap::const_iterator aIt = maSheetProps.begin(), aEnd = maSheetProps.end(); aIt != aEnd; ++aIt )
ContainerHelper::insertByName( xSheetsNC, rWorksheets.getCalcSheetName( aIt->first ), aIt->second );
@@ -747,7 +747,7 @@ void ViewSettings::finalizeImport()
if( !rxActiveSheetView )
rxActiveSheetView.reset( new SheetViewModel );
- Reference< XIndexContainer > xContainer = ContainerHelper::createIndexContainer( getGlobalFactory() );
+ Reference< XIndexContainer > xContainer = ContainerHelper::createIndexContainer( getBaseFilter().getComponentContext() );
if( xContainer.is() ) try
{
PropertyMap aPropMap;
diff --git a/oox/source/xls/workbookfragment.cxx b/oox/source/xls/workbookfragment.cxx
index 96e41e5c6d26..96fd34f0c100 100644
--- a/oox/source/xls/workbookfragment.cxx
+++ b/oox/source/xls/workbookfragment.cxx
@@ -223,8 +223,10 @@ void WorkbookFragment::finalizeImport()
/* Create fragments for all sheets, before importing them. Needed to do
some preprocessing in the fragment constructors, e.g. loading the table
fragments for all sheets that are needed before the cell formulas are
- loaded. */
- typedef ::std::vector< FragmentHandlerRef > SheetFragmentVector;
+ loaded. Additionally, the instances of the WorkbookGlobals structures
+ have to be stored for every sheet. */
+ typedef ::std::pair< WorksheetGlobalsRef, FragmentHandlerRef > SheetFragmentHandler;
+ typedef ::std::vector< SheetFragmentHandler > SheetFragmentVector;
SheetFragmentVector aSheetFragments;
WorksheetBuffer& rWorksheets = getWorksheets();
sal_Int32 nWorksheetCount = rWorksheets.getWorksheetCount();
@@ -239,34 +241,49 @@ void WorkbookFragment::finalizeImport()
OSL_ENSURE( aFragmentPath.getLength() > 0, "WorkbookFragment::finalizeImport - cannot access sheet fragment" );
if( aFragmentPath.getLength() > 0 )
{
- ::rtl::Reference< WorksheetFragmentBase > xFragment;
double fSegmentLength = getProgressBar().getFreeLength() / (nWorksheetCount - nWorksheet);
ISegmentProgressBarRef xSheetSegment = getProgressBar().createSegment( fSegmentLength );
- // create the fragment according to the sheet type
+ // get the sheet type according to the relations type
+ WorksheetType eSheetType = SHEETTYPE_EMPTYSHEET;
if( pRelation->maType == CREATE_OFFICEDOC_RELATION_TYPE( "worksheet" ) )
- {
- xFragment.set( new WorksheetFragment( *this, aFragmentPath, xSheetSegment, SHEETTYPE_WORKSHEET, nCalcSheet ) );
- }
+ eSheetType = SHEETTYPE_WORKSHEET;
else if( pRelation->maType == CREATE_OFFICEDOC_RELATION_TYPE( "chartsheet" ) )
- {
- xFragment.set( new ChartsheetFragment( *this, aFragmentPath, xSheetSegment, nCalcSheet ) );
- }
+ eSheetType = SHEETTYPE_CHARTSHEET;
else if( (pRelation->maType == CREATE_MSOFFICE_RELATION_TYPE( "xlMacrosheet" )) ||
(pRelation->maType == CREATE_MSOFFICE_RELATION_TYPE( "xlIntlMacrosheet" )) )
- {
- xFragment.set( new WorksheetFragment( *this, aFragmentPath, xSheetSegment, SHEETTYPE_MACROSHEET, nCalcSheet ) );
- }
+ eSheetType = SHEETTYPE_MACROSHEET;
else if( pRelation->maType == CREATE_OFFICEDOC_RELATION_TYPE( "dialogsheet" ) )
+ eSheetType = SHEETTYPE_DIALOGSHEET;
+ OSL_ENSURE( eSheetType != SHEETTYPE_EMPTYSHEET, "WorkbookFragment::finalizeImport - unknown sheet type" );
+ if( eSheetType != SHEETTYPE_EMPTYSHEET )
{
- xFragment.set( new WorksheetFragment( *this, aFragmentPath, xSheetSegment, SHEETTYPE_DIALOGSHEET, nCalcSheet ) );
+ // create the WorksheetGlobals object
+ WorksheetGlobalsRef xSheetGlob = WorksheetHelper::constructGlobals( *this, xSheetSegment, eSheetType, nCalcSheet );
+ OSL_ENSURE( xSheetGlob.get(), "WorkbookFragment::finalizeImport - missing sheet in document" );
+ if( xSheetGlob.get() )
+ {
+ // create the sheet fragment handler
+ ::rtl::Reference< WorksheetFragmentBase > xFragment;
+ switch( eSheetType )
+ {
+ case SHEETTYPE_WORKSHEET:
+ case SHEETTYPE_MACROSHEET:
+ case SHEETTYPE_DIALOGSHEET:
+ xFragment.set( new WorksheetFragment( *xSheetGlob, aFragmentPath ) );
+ break;
+ case SHEETTYPE_CHARTSHEET:
+ xFragment.set( new ChartsheetFragment( *xSheetGlob, aFragmentPath ) );
+ break;
+ default:
+ OSL_ENSURE( false, "WorkbookFragment::finalizeImport - unexpected sheet type" );
+ }
+
+ // insert the fragment into the map
+ if( xFragment.is() )
+ aSheetFragments.push_back( SheetFragmentHandler( xSheetGlob, xFragment.get() ) );
+ }
}
-
- // insert the fragment into the map
- OSL_ENSURE( xFragment.is(), "WorkbookFragment::finalizeImport - unknown sheet type" );
- OSL_ENSURE( !xFragment.is() || xFragment->isValidSheet(), "WorkbookFragment::finalizeImport - missing sheet in document" );
- if( xFragment.is() && xFragment->isValidSheet() )
- aSheetFragments.push_back( xFragment.get() );
}
}
}
@@ -279,9 +296,10 @@ void WorkbookFragment::finalizeImport()
for( SheetFragmentVector::iterator aIt = aSheetFragments.begin(), aEnd = aSheetFragments.end(); aIt != aEnd; ++aIt )
{
// import the sheet fragment
- importOoxFragment( *aIt );
- // delete fragment object, will free all allocated sheet buffers
- aIt->clear();
+ importOoxFragment( aIt->second );
+ // delete fragment object and WorkbookGlobals object, will free all allocated sheet buffers
+ aIt->second.clear();
+ aIt->first.reset();
}
// open the VBA project storage
@@ -290,7 +308,7 @@ void WorkbookFragment::finalizeImport()
{
Reference< XInputStream > xInStrm = getBaseFilter().openInputStream( aVbaFragmentPath );
if( xInStrm.is() )
- setVbaProjectStorage( StorageRef( new ::oox::ole::OleStorage( getGlobalFactory(), xInStrm, false ) ) );
+ setVbaProjectStorage( StorageRef( new ::oox::ole::OleStorage( getBaseFilter().getComponentContext(), xInStrm, false ) ) );
}
// final conversions, e.g. calculation settings and view settings
@@ -359,6 +377,7 @@ bool BiffWorkbookFragment::importFragment()
{
case BIFF_FRAGMENT_GLOBALS:
{
+ BiffInputStream& rStrm = getInputStream();
// import workbook globals fragment and create sheets in document
ISegmentProgressBarRef xGlobalsProgress = getProgressBar().createSegment( PROGRESS_LENGTH_GLOBALS );
bRet = importGlobalsFragment( *xGlobalsProgress );
@@ -367,10 +386,25 @@ bool BiffWorkbookFragment::importFragment()
bool bNextSheet = bRet;
for( sal_Int32 nWorksheet = 0, nWorksheetCount = rWorksheets.getWorksheetCount(); bNextSheet && (nWorksheet < nWorksheetCount); ++nWorksheet )
{
- // try to start a new sheet fragment
+ // calculate progress size for the sheet
double fSegmentLength = getProgressBar().getFreeLength() / (nWorksheetCount - nWorksheet);
ISegmentProgressBarRef xSheetProgress = getProgressBar().createSegment( fSegmentLength );
- BiffFragmentType eSheetFragment = startFragment( getBiff(), rWorksheets.getBiffRecordHandle( nWorksheet ) );
+ /* Try to start a new sheet fragment. The SHEET records point to the
+ first record of the sheet fragment which is usually a BOF record. */
+ BiffFragmentType eSheetFragment = BIFF_FRAGMENT_UNKNOWN;
+ sal_Int64 nRecHandle = rWorksheets.getBiffRecordHandle( nWorksheet );
+ if( rStrm.startRecordByHandle( nRecHandle ) )
+ {
+ /* #i109800# Stream may point to any record of the sheet fragment.
+ Check the record identifier before calling startFragment(). */
+ bool bIsBofRec = BiffHelper::isBofRecord( rStrm );
+ /* Rewind the record. If it is the BOF record, it will be read in
+ startFragment(). In every case, stream will point before the
+ first available non-BOF record. */
+ rStrm.rewindRecord();
+ // if the BOF record is missing, a regular worksheet will be assumed
+ eSheetFragment = bIsBofRec ? startFragment( getBiff() ) : BIFF_FRAGMENT_WORKSHEET;
+ }
sal_Int16 nCalcSheet = rWorksheets.getCalcSheetIndex( nWorksheet );
bNextSheet = importSheetFragment( *xSheetProgress, eSheetFragment, nCalcSheet );
}
@@ -700,26 +734,32 @@ bool BiffWorkbookFragment::importSheetFragment( ISegmentProgressBar& rProgressBa
break;
}
- // create the worksheet fragment
+ // create the WorksheetGlobals object
ISegmentProgressBarRef xSheetProgress = rProgressBar.createSegment( rProgressBar.getFreeLength() );
+ WorksheetGlobalsRef xSheetGlob = WorksheetHelper::constructGlobals( *this, xSheetProgress, eSheetType, nCalcSheet );
+ OSL_ENSURE( xSheetGlob.get(), "BiffWorkbookFragment::importSheetFragment - missing sheet in document" );
+ if( !xSheetGlob.get() )
+ return false;
+
+ // create the worksheet fragment
::boost::shared_ptr< BiffWorksheetFragmentBase > xFragment;
switch( eSheetType )
{
case SHEETTYPE_WORKSHEET:
case SHEETTYPE_MACROSHEET:
case SHEETTYPE_DIALOGSHEET:
- xFragment.reset( new BiffWorksheetFragment( *this, xSheetProgress, eSheetType, nCalcSheet ) );
+ xFragment.reset( new BiffWorksheetFragment( *xSheetGlob, *this ) );
break;
case SHEETTYPE_CHARTSHEET:
- xFragment.reset( new BiffChartsheetFragment( *this, xSheetProgress, nCalcSheet ) );
+ xFragment.reset( new BiffChartsheetFragment( *xSheetGlob, *this ) );
break;
case SHEETTYPE_MODULESHEET:
case SHEETTYPE_EMPTYSHEET:
- xFragment.reset( new BiffSkipWorksheetFragment( *this, xSheetProgress, nCalcSheet ) );
+ xFragment.reset( new BiffSkipWorksheetFragment( *xSheetGlob, *this ) );
break;
}
// load the sheet fragment records
- return xFragment->isValidSheet() && xFragment->importFragment();
+ return xFragment.get() && xFragment->importFragment();
}
// ============================================================================
diff --git a/oox/source/xls/workbookhelper.cxx b/oox/source/xls/workbookhelper.cxx
index b7533d3f7a2e..bf93ef25608b 100644
--- a/oox/source/xls/workbookhelper.cxx
+++ b/oox/source/xls/workbookhelper.cxx
@@ -100,12 +100,12 @@ bool IgnoreCaseCompare::operator()( const OUString& rName1, const OUString& rNam
// ============================================================================
-class WorkbookData
+class WorkbookGlobals
{
public:
- explicit WorkbookData( ExcelFilter& rFilter );
- explicit WorkbookData( ExcelBiffFilter& rFilter, BiffType eBiff );
- ~WorkbookData();
+ explicit WorkbookGlobals( ExcelFilter& rFilter );
+ explicit WorkbookGlobals( ExcelBiffFilter& rFilter, BiffType eBiff );
+ ~WorkbookGlobals();
/** Returns true, if this helper refers to a valid document. */
inline bool isValid() const { return mxDoc.is(); }
@@ -120,14 +120,15 @@ public:
inline FilterType getFilterType() const { return meFilterType; }
/** Returns true, if the file is a multi-sheet document, or false if single-sheet. */
inline bool isWorkbookFile() const { return mbWorkbook; }
- /** Returns the index of the current sheet in the Calc document. */
- inline sal_Int16 getCurrentSheetIndex() const { return mnCurrSheet; }
- /** Sets the index of the current sheet in the Calc document. */
- inline void setCurrentSheetIndex( sal_Int16 nSheet ) { mnCurrSheet = nSheet; }
/** Returns the VBA project storage. */
inline StorageRef getVbaProjectStorage() const { return mxVbaPrjStrg; }
- /** Sets the VBA project storage. */
+ /** Returns the index of the current Calc sheet, if filter currently processes a sheet. */
+ inline sal_Int16 getCurrentSheetIndex() const { return mnCurrSheet; }
+
+ /** Sets the VBA project storage used to import VBA source code and forms. */
inline void setVbaProjectStorage( const StorageRef& rxVbaPrjStrg ) { mxVbaPrjStrg = rxVbaPrjStrg; }
+ /** Sets the index of the current Calc sheet, if filter currently processes a sheet. */
+ inline void setCurrentSheetIndex( sal_Int16 nSheet ) { mnCurrSheet = nSheet; }
// document model ---------------------------------------------------------
@@ -290,7 +291,7 @@ private:
// ----------------------------------------------------------------------------
-WorkbookData::WorkbookData( ExcelFilter& rFilter ) :
+WorkbookGlobals::WorkbookGlobals( ExcelFilter& rFilter ) :
mrBaseFilter( rFilter ),
mrExcelBase( rFilter ),
meFilterType( FILTER_OOXML ),
@@ -299,11 +300,11 @@ WorkbookData::WorkbookData( ExcelFilter& rFilter ) :
meBiff( BIFF_UNKNOWN )
{
// register at the filter, needed for virtual callbacks (even during construction)
- mrExcelBase.registerWorkbookData( *this );
+ mrExcelBase.registerWorkbookGlobals( *this );
initialize( true );
}
-WorkbookData::WorkbookData( ExcelBiffFilter& rFilter, BiffType eBiff ) :
+WorkbookGlobals::WorkbookGlobals( ExcelBiffFilter& rFilter, BiffType eBiff ) :
mrBaseFilter( rFilter ),
mrExcelBase( rFilter ),
meFilterType( FILTER_BIFF ),
@@ -312,19 +313,19 @@ WorkbookData::WorkbookData( ExcelBiffFilter& rFilter, BiffType eBiff ) :
meBiff( eBiff )
{
// register at the filter, needed for virtual callbacks (even during construction)
- mrExcelBase.registerWorkbookData( *this );
+ mrExcelBase.registerWorkbookGlobals( *this );
initialize( eBiff >= BIFF5 );
}
-WorkbookData::~WorkbookData()
+WorkbookGlobals::~WorkbookGlobals()
{
finalize();
- mrExcelBase.unregisterWorkbookData();
+ mrExcelBase.unregisterWorkbookGlobals();
}
// document model -------------------------------------------------------------
-Reference< XNameContainer > WorkbookData::getStyleFamily( bool bPageStyles ) const
+Reference< XNameContainer > WorkbookGlobals::getStyleFamily( bool bPageStyles ) const
{
Reference< XNameContainer > xStylesNC;
try
@@ -336,11 +337,11 @@ Reference< XNameContainer > WorkbookData::getStyleFamily( bool bPageStyles ) con
catch( Exception& )
{
}
- OSL_ENSURE( xStylesNC.is(), "WorkbookData::getStyleFamily - cannot access style family" );
+ OSL_ENSURE( xStylesNC.is(), "WorkbookGlobals::getStyleFamily - cannot access style family" );
return xStylesNC;
}
-Reference< XStyle > WorkbookData::getStyleObject( const OUString& rStyleName, bool bPageStyle ) const
+Reference< XStyle > WorkbookGlobals::getStyleObject( const OUString& rStyleName, bool bPageStyle ) const
{
Reference< XStyle > xStyle;
try
@@ -351,11 +352,11 @@ Reference< XStyle > WorkbookData::getStyleObject( const OUString& rStyleName, bo
catch( Exception& )
{
}
- OSL_ENSURE( xStyle.is(), "WorkbookData::getStyleObject - cannot access style object" );
+ OSL_ENSURE( xStyle.is(), "WorkbookGlobals::getStyleObject - cannot access style object" );
return xStyle;
}
-Reference< XNamedRange > WorkbookData::createNamedRangeObject( OUString& orName, sal_Int32 nNameFlags ) const
+Reference< XNamedRange > WorkbookGlobals::createNamedRangeObject( OUString& orName, sal_Int32 nNameFlags ) const
{
// create the name and insert it into the Calc document
Reference< XNamedRange > xNamedRange;
@@ -373,11 +374,11 @@ Reference< XNamedRange > WorkbookData::createNamedRangeObject( OUString& orName,
catch( Exception& )
{
}
- OSL_ENSURE( xNamedRange.is(), "WorkbookData::createNamedRangeObject - cannot create defined name" );
+ OSL_ENSURE( xNamedRange.is(), "WorkbookGlobals::createNamedRangeObject - cannot create defined name" );
return xNamedRange;
}
-Reference< XDatabaseRange > WorkbookData::createDatabaseRangeObject( OUString& orName, const CellRangeAddress& rRangeAddr ) const
+Reference< XDatabaseRange > WorkbookGlobals::createDatabaseRangeObject( OUString& orName, const CellRangeAddress& rRangeAddr ) const
{
// validate cell range
CellRangeAddress aDestRange = rRangeAddr;
@@ -399,11 +400,11 @@ Reference< XDatabaseRange > WorkbookData::createDatabaseRangeObject( OUString& o
catch( Exception& )
{
}
- OSL_ENSURE( xDatabaseRange.is(), "WorkbookData::createDatabaseRangeObject - cannot create database range" );
+ OSL_ENSURE( xDatabaseRange.is(), "WorkbookGlobals::createDatabaseRangeObject - cannot create database range" );
return xDatabaseRange;
}
-Reference< XDatabaseRange > WorkbookData::createUnnamedDatabaseRangeObject( const CellRangeAddress& rRangeAddr ) const
+Reference< XDatabaseRange > WorkbookGlobals::createUnnamedDatabaseRangeObject( const CellRangeAddress& rRangeAddr ) const
{
// validate cell range
CellRangeAddress aDestRange = rRangeAddr;
@@ -425,7 +426,7 @@ Reference< XDatabaseRange > WorkbookData::createUnnamedDatabaseRangeObject( cons
return xDatabaseRange;
}
-Reference< XStyle > WorkbookData::createStyleObject( OUString& orStyleName, bool bPageStyle ) const
+Reference< XStyle > WorkbookGlobals::createStyleObject( OUString& orStyleName, bool bPageStyle ) const
{
Reference< XStyle > xStyle;
try
@@ -437,63 +438,62 @@ Reference< XStyle > WorkbookData::createStyleObject( OUString& orStyleName, bool
catch( Exception& )
{
}
- OSL_ENSURE( xStyle.is(), "WorkbookData::createStyleObject - cannot create style" );
+ OSL_ENSURE( xStyle.is(), "WorkbookGlobals::createStyleObject - cannot create style" );
return xStyle;
}
// BIFF specific --------------------------------------------------------------
-void WorkbookData::setTextEncoding( rtl_TextEncoding eTextEnc )
+void WorkbookGlobals::setTextEncoding( rtl_TextEncoding eTextEnc )
{
if( eTextEnc != RTL_TEXTENCODING_DONTKNOW )
meTextEnc = eTextEnc;
}
-void WorkbookData::setCodePage( sal_uInt16 nCodePage )
+void WorkbookGlobals::setCodePage( sal_uInt16 nCodePage )
{
setTextEncoding( BiffHelper::calcTextEncodingFromCodePage( nCodePage ) );
mbHasCodePage = true;
}
-void WorkbookData::setAppFontEncoding( rtl_TextEncoding eAppFontEnc )
+void WorkbookGlobals::setAppFontEncoding( rtl_TextEncoding eAppFontEnc )
{
if( !mbHasCodePage )
setTextEncoding( eAppFontEnc );
}
-void WorkbookData::setIsWorkbookFile()
+void WorkbookGlobals::setIsWorkbookFile()
{
- OSL_ENSURE( meBiff == BIFF4, "WorkbookData::setIsWorkbookFile - invalid call" );
+ OSL_ENSURE( meBiff == BIFF4, "WorkbookGlobals::setIsWorkbookFile - invalid call" );
mbWorkbook = true;
}
-void WorkbookData::createBuffersPerSheet( sal_Int16 nSheet )
+void WorkbookGlobals::createBuffersPerSheet( sal_Int16 nSheet )
{
- // set mnCurrSheet to enable usage of WorkbookHelper::getCurrentSheetIndex()
- mnCurrSheet = nSheet;
switch( meBiff )
{
case BIFF2:
case BIFF3:
- OSL_ENSURE( mnCurrSheet == 0, "WorkbookData::createBuffersPerSheet - unexpected sheet index" );
- mxDefNames->setLocalCalcSheet( mnCurrSheet );
+ OSL_ENSURE( nSheet == 0, "WorkbookGlobals::createBuffersPerSheet - unexpected sheet index" );
+ mxDefNames->setLocalCalcSheet( nSheet );
break;
case BIFF4:
- OSL_ENSURE( mbWorkbook || (mnCurrSheet == 0), "WorkbookData::createBuffersPerSheet - unexpected sheet index" );
+ OSL_ENSURE( mbWorkbook || (nSheet == 0), "WorkbookGlobals::createBuffersPerSheet - unexpected sheet index" );
// #i11183# sheets in BIFF4W files have own styles and names
- if( mbWorkbook && (mnCurrSheet > 0) )
+ if( nSheet > 0 )
{
mxStyles.reset( new StylesBuffer( *this ) );
mxDefNames.reset( new DefinedNamesBuffer( *this ) );
mxExtLinks.reset( new ExternalLinkBuffer( *this ) );
}
- mxDefNames->setLocalCalcSheet( mnCurrSheet );
+ mxDefNames->setLocalCalcSheet( nSheet );
break;
case BIFF5:
// BIFF5 stores external references per sheet
- mxExtLinks.reset( new ExternalLinkBuffer( *this ) );
+ if( nSheet > 0 )
+ mxExtLinks.reset( new ExternalLinkBuffer( *this ) );
break;
case BIFF8:
@@ -502,12 +502,11 @@ void WorkbookData::createBuffersPerSheet( sal_Int16 nSheet )
case BIFF_UNKNOWN:
break;
}
- mnCurrSheet = -1;
}
// private --------------------------------------------------------------------
-void WorkbookData::initialize( bool bWorkbookFile )
+void WorkbookGlobals::initialize( bool bWorkbookFile )
{
maCellStyles = CREATE_OUSTRING( "CellStyles" );
maPageStyles = CREATE_OUSTRING( "PageStyles" );
@@ -520,7 +519,7 @@ void WorkbookData::initialize( bool bWorkbookFile )
// the spreadsheet document
mxDoc.set( mrBaseFilter.getModel(), UNO_QUERY );
- OSL_ENSURE( mxDoc.is(), "WorkbookData::initialize - no spreadsheet document" );
+ OSL_ENSURE( mxDoc.is(), "WorkbookGlobals::initialize - no spreadsheet document" );
mxWorkbookSettings.reset( new WorkbookSettings( *this ) );
mxViewSettings.reset( new ViewSettings( *this ) );
@@ -583,7 +582,7 @@ void WorkbookData::initialize( bool bWorkbookFile )
}
}
-void WorkbookData::finalize()
+void WorkbookGlobals::finalize()
{
// set some document properties needed after import
if( mrBaseFilter.isImportFilter() )
@@ -614,62 +613,73 @@ WorkbookHelper::~WorkbookHelper()
{
}
-// filter ---------------------------------------------------------------------
+/*static*/ WorkbookGlobalsRef WorkbookHelper::constructGlobals( ExcelFilter& rFilter )
+{
+ WorkbookGlobalsRef xBookGlob( new WorkbookGlobals( rFilter ) );
+ if( !xBookGlob->isValid() )
+ xBookGlob.reset();
+ return xBookGlob;
+}
-FilterBase& WorkbookHelper::getBaseFilter() const
+/*static*/ WorkbookGlobalsRef WorkbookHelper::constructGlobals( ExcelBiffFilter& rFilter, BiffType eBiff )
{
- return mrBookData.getBaseFilter();
+ WorkbookGlobalsRef xBookGlob( new WorkbookGlobals( rFilter, eBiff ) );
+ if( !xBookGlob->isValid() )
+ xBookGlob.reset();
+ return xBookGlob;
}
-Reference< XMultiServiceFactory > WorkbookHelper::getGlobalFactory() const
+// filter ---------------------------------------------------------------------
+
+FilterBase& WorkbookHelper::getBaseFilter() const
{
- return mrBookData.getBaseFilter().getServiceFactory();
+ return mrBookGlob.getBaseFilter();
}
FilterType WorkbookHelper::getFilterType() const
{
- return mrBookData.getFilterType();
+ return mrBookGlob.getFilterType();
}
SegmentProgressBar& WorkbookHelper::getProgressBar() const
{
- return mrBookData.getProgressBar();
+ return mrBookGlob.getProgressBar();
}
bool WorkbookHelper::isWorkbookFile() const
{
- return mrBookData.isWorkbookFile();
+ return mrBookGlob.isWorkbookFile();
}
sal_Int16 WorkbookHelper::getCurrentSheetIndex() const
{
- return mrBookData.getCurrentSheetIndex();
+ return mrBookGlob.getCurrentSheetIndex();
}
-void WorkbookHelper::setCurrentSheetIndex( sal_Int16 nSheet )
+void WorkbookHelper::setVbaProjectStorage( const StorageRef& rxVbaPrjStrg )
{
- mrBookData.setCurrentSheetIndex( nSheet );
+ mrBookGlob.setVbaProjectStorage( rxVbaPrjStrg );
}
-void WorkbookHelper::setVbaProjectStorage( const StorageRef& rxVbaPrjStrg )
+void WorkbookHelper::setCurrentSheetIndex( sal_Int16 nSheet )
{
- mrBookData.setVbaProjectStorage( rxVbaPrjStrg );
+ mrBookGlob.setCurrentSheetIndex( nSheet );
}
void WorkbookHelper::finalizeWorkbookImport()
{
// workbook settings, document and sheet view settings
- mrBookData.getWorkbookSettings().finalizeImport();
- mrBookData.getViewSettings().finalizeImport();
+ mrBookGlob.getWorkbookSettings().finalizeImport();
+ mrBookGlob.getViewSettings().finalizeImport();
/* Insert all pivot tables. Must be done after loading all sheets, because
data pilots expect existing source data on creation. */
- mrBookData.getPivotTables().finalizeImport();
+ mrBookGlob.getPivotTables().finalizeImport();
/* Insert scenarios after all sheet processing is done, because new hidden
sheets are created for scenarios which would confuse code that relies
on certain sheet indexes. Must be done after pivot tables too. */
- mrBookData.getScenarios().finalizeImport();
+ mrBookGlob.getScenarios().finalizeImport();
/* Set 'Default' page style to automatic page numbering (default is manual
number 1). Otherwise hidden sheets (e.g. for scenarios) which have
@@ -680,7 +690,7 @@ void WorkbookHelper::finalizeWorkbookImport()
/* Import the VBA project (after finalizing workbook settings which
contains the workbook code name). */
- StorageRef xVbaPrjStrg = mrBookData.getVbaProjectStorage();
+ StorageRef xVbaPrjStrg = mrBookGlob.getVbaProjectStorage();
if( xVbaPrjStrg.get() && xVbaPrjStrg->isStorage() )
getBaseFilter().getVbaProject().importVbaProject( *xVbaPrjStrg, getBaseFilter().getGraphicHelper() );
}
@@ -689,12 +699,7 @@ void WorkbookHelper::finalizeWorkbookImport()
Reference< XSpreadsheetDocument > WorkbookHelper::getDocument() const
{
- return mrBookData.getDocument();
-}
-
-Reference< XMultiServiceFactory > WorkbookHelper::getDocumentFactory() const
-{
- return mrBookData.getBaseFilter().getModelFactory();
+ return mrBookGlob.getDocument();
}
Reference< XSpreadsheet > WorkbookHelper::getSheetFromDoc( sal_Int16 nSheet ) const
@@ -755,134 +760,134 @@ Reference< XCellRange > WorkbookHelper::getCellRangeFromDoc( const CellRangeAddr
Reference< XNameContainer > WorkbookHelper::getStyleFamily( bool bPageStyles ) const
{
- return mrBookData.getStyleFamily( bPageStyles );
+ return mrBookGlob.getStyleFamily( bPageStyles );
}
Reference< XStyle > WorkbookHelper::getStyleObject( const OUString& rStyleName, bool bPageStyle ) const
{
- return mrBookData.getStyleObject( rStyleName, bPageStyle );
+ return mrBookGlob.getStyleObject( rStyleName, bPageStyle );
}
Reference< XNamedRange > WorkbookHelper::createNamedRangeObject( OUString& orName, sal_Int32 nNameFlags ) const
{
- return mrBookData.createNamedRangeObject( orName, nNameFlags );
+ return mrBookGlob.createNamedRangeObject( orName, nNameFlags );
}
Reference< XDatabaseRange > WorkbookHelper::createDatabaseRangeObject( OUString& orName, const CellRangeAddress& rRangeAddr ) const
{
- return mrBookData.createDatabaseRangeObject( orName, rRangeAddr );
+ return mrBookGlob.createDatabaseRangeObject( orName, rRangeAddr );
}
Reference< XDatabaseRange > WorkbookHelper::createUnnamedDatabaseRangeObject( const CellRangeAddress& rRangeAddr ) const
{
- return mrBookData.createUnnamedDatabaseRangeObject( rRangeAddr );
+ return mrBookGlob.createUnnamedDatabaseRangeObject( rRangeAddr );
}
Reference< XStyle > WorkbookHelper::createStyleObject( OUString& orStyleName, bool bPageStyle ) const
{
- return mrBookData.createStyleObject( orStyleName, bPageStyle );
+ return mrBookGlob.createStyleObject( orStyleName, bPageStyle );
}
// buffers --------------------------------------------------------------------
WorkbookSettings& WorkbookHelper::getWorkbookSettings() const
{
- return mrBookData.getWorkbookSettings();
+ return mrBookGlob.getWorkbookSettings();
}
ViewSettings& WorkbookHelper::getViewSettings() const
{
- return mrBookData.getViewSettings();
+ return mrBookGlob.getViewSettings();
}
WorksheetBuffer& WorkbookHelper::getWorksheets() const
{
- return mrBookData.getWorksheets();
+ return mrBookGlob.getWorksheets();
}
ThemeBuffer& WorkbookHelper::getTheme() const
{
- return mrBookData.getTheme();
+ return mrBookGlob.getTheme();
}
StylesBuffer& WorkbookHelper::getStyles() const
{
- return mrBookData.getStyles();
+ return mrBookGlob.getStyles();
}
SharedStringsBuffer& WorkbookHelper::getSharedStrings() const
{
- return mrBookData.getSharedStrings();
+ return mrBookGlob.getSharedStrings();
}
ExternalLinkBuffer& WorkbookHelper::getExternalLinks() const
{
- return mrBookData.getExternalLinks();
+ return mrBookGlob.getExternalLinks();
}
DefinedNamesBuffer& WorkbookHelper::getDefinedNames() const
{
- return mrBookData.getDefinedNames();
+ return mrBookGlob.getDefinedNames();
}
TableBuffer& WorkbookHelper::getTables() const
{
- return mrBookData.getTables();
+ return mrBookGlob.getTables();
}
ScenarioBuffer& WorkbookHelper::getScenarios() const
{
- return mrBookData.getScenarios();
+ return mrBookGlob.getScenarios();
}
ConnectionsBuffer& WorkbookHelper::getConnections() const
{
- return mrBookData.getConnections();
+ return mrBookGlob.getConnections();
}
PivotCacheBuffer& WorkbookHelper::getPivotCaches() const
{
- return mrBookData.getPivotCaches();
+ return mrBookGlob.getPivotCaches();
}
PivotTableBuffer& WorkbookHelper::getPivotTables() const
{
- return mrBookData.getPivotTables();
+ return mrBookGlob.getPivotTables();
}
// converters -----------------------------------------------------------------
FormulaParser& WorkbookHelper::getFormulaParser() const
{
- return mrBookData.getFormulaParser();
+ return mrBookGlob.getFormulaParser();
}
UnitConverter& WorkbookHelper::getUnitConverter() const
{
- return mrBookData.getUnitConverter();
+ return mrBookGlob.getUnitConverter();
}
AddressConverter& WorkbookHelper::getAddressConverter() const
{
- return mrBookData.getAddressConverter();
+ return mrBookGlob.getAddressConverter();
}
ExcelChartConverter& WorkbookHelper::getChartConverter() const
{
- return mrBookData.getChartConverter();
+ return mrBookGlob.getChartConverter();
}
PageSettingsConverter& WorkbookHelper::getPageSettingsConverter() const
{
- return mrBookData.getPageSettingsConverter();
+ return mrBookGlob.getPageSettingsConverter();
}
// OOXML/BIFF12 specific ------------------------------------------------------
XmlFilterBase& WorkbookHelper::getOoxFilter() const
{
- OSL_ENSURE( mrBookData.getFilterType() == FILTER_OOXML, "WorkbookHelper::getOoxFilter - invalid call" );
- return mrBookData.getOoxFilter();
+ OSL_ENSURE( mrBookGlob.getFilterType() == FILTER_OOXML, "WorkbookHelper::getOoxFilter - invalid call" );
+ return mrBookGlob.getOoxFilter();
}
bool WorkbookHelper::importOoxFragment( const ::rtl::Reference< FragmentHandler >& rxHandler )
@@ -894,82 +899,48 @@ bool WorkbookHelper::importOoxFragment( const ::rtl::Reference< FragmentHandler
BinaryFilterBase& WorkbookHelper::getBiffFilter() const
{
- OSL_ENSURE( mrBookData.getFilterType() == FILTER_BIFF, "WorkbookHelper::getBiffFilter - invalid call" );
- return mrBookData.getBiffFilter();
+ OSL_ENSURE( mrBookGlob.getFilterType() == FILTER_BIFF, "WorkbookHelper::getBiffFilter - invalid call" );
+ return mrBookGlob.getBiffFilter();
}
BiffType WorkbookHelper::getBiff() const
{
- return mrBookData.getBiff();
+ return mrBookGlob.getBiff();
}
rtl_TextEncoding WorkbookHelper::getTextEncoding() const
{
- return mrBookData.getTextEncoding();
+ return mrBookGlob.getTextEncoding();
}
void WorkbookHelper::setTextEncoding( rtl_TextEncoding eTextEnc )
{
- mrBookData.setTextEncoding( eTextEnc );
+ mrBookGlob.setTextEncoding( eTextEnc );
}
void WorkbookHelper::setCodePage( sal_uInt16 nCodePage )
{
- mrBookData.setCodePage( nCodePage );
+ mrBookGlob.setCodePage( nCodePage );
}
void WorkbookHelper::setAppFontEncoding( rtl_TextEncoding eAppFontEnc )
{
- mrBookData.setAppFontEncoding( eAppFontEnc );
+ mrBookGlob.setAppFontEncoding( eAppFontEnc );
}
void WorkbookHelper::setIsWorkbookFile()
{
- mrBookData.setIsWorkbookFile();
+ mrBookGlob.setIsWorkbookFile();
}
void WorkbookHelper::createBuffersPerSheet( sal_Int16 nSheet )
{
- mrBookData.createBuffersPerSheet( nSheet );
+ mrBookGlob.createBuffersPerSheet( nSheet );
}
BiffCodecHelper& WorkbookHelper::getCodecHelper() const
{
- return mrBookData.getCodecHelper();
-}
-
-// ============================================================================
-
-namespace prv {
-
-WorkbookDataOwner::WorkbookDataOwner( WorkbookDataRef xBookData ) :
- mxBookData( xBookData )
-{
-}
-
-WorkbookDataOwner::~WorkbookDataOwner()
-{
-}
-
-} // namespace prv
-
-// ----------------------------------------------------------------------------
-
-WorkbookHelperRoot::WorkbookHelperRoot( ExcelFilter& rFilter ) :
- prv::WorkbookDataOwner( prv::WorkbookDataRef( new WorkbookData( rFilter ) ) ),
- WorkbookHelper( *mxBookData )
-{
-}
-
-WorkbookHelperRoot::WorkbookHelperRoot( ExcelBiffFilter& rFilter, BiffType eBiff ) :
- prv::WorkbookDataOwner( prv::WorkbookDataRef( new WorkbookData( rFilter, eBiff ) ) ),
- WorkbookHelper( *mxBookData )
-{
-}
-
-bool WorkbookHelperRoot::isValid() const
-{
- return mxBookData->isValid();
+ return mrBookGlob.getCodecHelper();
}
// ============================================================================
diff --git a/oox/source/xls/workbooksettings.cxx b/oox/source/xls/workbooksettings.cxx
index 30caadaac9c3..f9eb011e01df 100644
--- a/oox/source/xls/workbooksettings.cxx
+++ b/oox/source/xls/workbooksettings.cxx
@@ -301,7 +301,7 @@ void WorkbookSettings::finalizeImport()
{
getBaseFilter().getMediaDescriptor()[ CREATE_OUSTRING( "ReadOnly" ) ] <<= true;
- Reference< XPropertySet > xDocumentSettings( getDocumentFactory()->createInstance(
+ Reference< XPropertySet > xDocumentSettings( getBaseFilter().getModelFactory()->createInstance(
CREATE_OUSTRING( "com.sun.star.document.Settings" ) ), UNO_QUERY_THROW );
PropertySet aSettingsProp( xDocumentSettings );
if( maFileSharing.mbRecommendReadOnly )
diff --git a/oox/source/xls/worksheetfragment.cxx b/oox/source/xls/worksheetfragment.cxx
index 84b6dd659cb7..3832a1b034f6 100644
--- a/oox/source/xls/worksheetfragment.cxx
+++ b/oox/source/xls/worksheetfragment.cxx
@@ -38,12 +38,14 @@
#include "oox/xls/commentsfragment.hxx"
#include "oox/xls/condformatcontext.hxx"
#include "oox/xls/drawingfragment.hxx"
+#include "oox/xls/drawingmanager.hxx"
#include "oox/xls/externallinkbuffer.hxx"
#include "oox/xls/pagesettings.hxx"
#include "oox/xls/pivottablefragment.hxx"
#include "oox/xls/querytablefragment.hxx"
#include "oox/xls/scenariobuffer.hxx"
#include "oox/xls/scenariocontext.hxx"
+#include "oox/xls/sheetdatabuffer.hxx"
#include "oox/xls/sheetdatacontext.hxx"
#include "oox/xls/tablefragment.hxx"
#include "oox/xls/viewsettings.hxx"
@@ -124,32 +126,18 @@ ContextHandlerRef DataValidationsContext::onCreateContext( sal_Int32 nElement, c
return 0;
}
-namespace {
-
-ApiTokenSequence lclImportDataValFormula( FormulaParser& rParser, const OUString& rFormula, const CellAddress& rBaseAddress )
-{
- TokensFormulaContext aContext( true, false );
- aContext.setBaseAddress( rBaseAddress );
- rParser.importFormula( aContext, rFormula );
- return aContext.getTokens();
-}
-
-} // namespace
-
void DataValidationsContext::onCharacters( const OUString& rChars )
{
if( mxValModel.get() ) switch( getCurrentElement() )
{
case XLS_TOKEN( formula1 ):
- mxValModel->maTokens1 = lclImportDataValFormula(
- getFormulaParser(), rChars, mxValModel->maRanges.getBaseAddress() );
+ mxValModel->maTokens1 = getFormulaParser().importFormula( mxValModel->maRanges.getBaseAddress(), rChars );
// process string list of a list validation (convert to list of string tokens)
if( mxValModel->mnType == XML_list )
getFormulaParser().convertStringToStringList( mxValModel->maTokens1, ',', true );
break;
case XLS_TOKEN( formula2 ):
- mxValModel->maTokens2 = lclImportDataValFormula(
- getFormulaParser(), rChars, mxValModel->maRanges.getBaseAddress() );
+ mxValModel->maTokens2 = getFormulaParser().importFormula( mxValModel->maRanges.getBaseAddress(), rChars );
break;
}
}
@@ -213,12 +201,9 @@ void DataValidationsContext::importDataValidation( SequenceInputStream& rStrm )
// condition formula(s)
FormulaParser& rParser = getFormulaParser();
- TokensFormulaContext aContext( true, false );
- aContext.setBaseAddress( aModel.maRanges.getBaseAddress() );
- rParser.importFormula( aContext, rStrm );
- aModel.maTokens1 = aContext.getTokens();
- rParser.importFormula( aContext, rStrm );
- aModel.maTokens2 = aContext.getTokens();
+ CellAddress aBaseAddr = aModel.maRanges.getBaseAddress();
+ aModel.maTokens1 = rParser.importFormula( aBaseAddr, FORMULATYPE_VALIDATION, rStrm );
+ aModel.maTokens2 = rParser.importFormula( aBaseAddr, FORMULATYPE_VALIDATION, rStrm );
// process string list of a list validation (convert to list of string tokens)
if( (aModel.mnType == XML_list) && getFlag( nFlags, BIFF_DATAVAL_STRINGLIST ) )
rParser.convertStringToStringList( aModel.maTokens1, ',', true );
@@ -229,9 +214,8 @@ void DataValidationsContext::importDataValidation( SequenceInputStream& rStrm )
// ============================================================================
-WorksheetFragment::WorksheetFragment( const WorkbookHelper& rHelper,
- const OUString& rFragmentPath, const ISegmentProgressBarRef& rxProgressBar, WorksheetType eSheetType, sal_Int16 nSheet ) :
- WorksheetFragmentBase( rHelper, rFragmentPath, rxProgressBar, eSheetType, nSheet )
+WorksheetFragment::WorksheetFragment( const WorksheetHelper& rHelper, const OUString& rFragmentPath ) :
+ WorksheetFragmentBase( rHelper, rFragmentPath )
{
// import data tables related to this worksheet
RelationsRef xTableRels = getRelations().getRelationsFromType( CREATE_OFFICEDOC_RELATION_TYPE( "table" ) );
@@ -542,14 +526,14 @@ void WorksheetFragment::importSheetFormatPr( const AttributeList& rAttribs )
void WorksheetFragment::importCol( const AttributeList& rAttribs )
{
ColumnModel aModel;
- aModel.mnFirstCol = rAttribs.getInteger( XML_min, -1 );
- aModel.mnLastCol = rAttribs.getInteger( XML_max, -1 );
- aModel.mfWidth = rAttribs.getDouble( XML_width, 0.0 );
- aModel.mnXfId = rAttribs.getInteger( XML_style, -1 );
- aModel.mnLevel = rAttribs.getInteger( XML_outlineLevel, 0 );
- aModel.mbShowPhonetic = rAttribs.getBool( XML_phonetic, false );
- aModel.mbHidden = rAttribs.getBool( XML_hidden, false );
- aModel.mbCollapsed = rAttribs.getBool( XML_collapsed, false );
+ aModel.maRange.mnFirst = rAttribs.getInteger( XML_min, -1 );
+ aModel.maRange.mnLast = rAttribs.getInteger( XML_max, -1 );
+ aModel.mfWidth = rAttribs.getDouble( XML_width, 0.0 );
+ aModel.mnXfId = rAttribs.getInteger( XML_style, -1 );
+ aModel.mnLevel = rAttribs.getInteger( XML_outlineLevel, 0 );
+ aModel.mbShowPhonetic = rAttribs.getBool( XML_phonetic, false );
+ aModel.mbHidden = rAttribs.getBool( XML_hidden, false );
+ aModel.mbCollapsed = rAttribs.getBool( XML_collapsed, false );
// set column properties in the current sheet
setColumnModel( aModel );
}
@@ -558,7 +542,7 @@ void WorksheetFragment::importMergeCell( const AttributeList& rAttribs )
{
CellRangeAddress aRange;
if( getAddressConverter().convertToCellRange( aRange, rAttribs.getString( XML_ref, OUString() ), getSheetIndex(), true, true ) )
- setMergedRange( aRange );
+ getSheetData().setMergedRange( aRange );
}
void WorksheetFragment::importHyperlink( const AttributeList& rAttribs )
@@ -660,11 +644,11 @@ void WorksheetFragment::importCol( SequenceInputStream& rStrm )
sal_Int32 nWidth;
sal_uInt16 nFlags;
- rStrm >> aModel.mnFirstCol >> aModel.mnLastCol >> nWidth >> aModel.mnXfId >> nFlags;
+ rStrm >> aModel.maRange.mnFirst >> aModel.maRange.mnLast >> nWidth >> aModel.mnXfId >> nFlags;
// column indexes are 0-based in BIFF12, but ColumnModel expects 1-based
- ++aModel.mnFirstCol;
- ++aModel.mnLastCol;
+ ++aModel.maRange.mnFirst;
+ ++aModel.maRange.mnLast;
// width is stored as 1/256th of a character in BIFF12, convert to entire character
aModel.mfWidth = static_cast< double >( nWidth ) / 256.0;
// equal flags in all BIFFs
@@ -682,7 +666,7 @@ void WorksheetFragment::importMergeCell( SequenceInputStream& rStrm )
rStrm >> aBinRange;
CellRangeAddress aRange;
if( getAddressConverter().convertToCellRange( aRange, aBinRange, getSheetIndex(), true, true ) )
- setMergedRange( aRange );
+ getSheetData().setMergedRange( aRange );
}
void WorksheetFragment::importHyperlink( SequenceInputStream& rStrm )
@@ -753,9 +737,8 @@ void WorksheetFragment::importEmbeddedOleData( StreamDataSequence& orEmbeddedDat
// ============================================================================
-BiffWorksheetFragment::BiffWorksheetFragment( const BiffWorkbookFragmentBase& rParent,
- const ISegmentProgressBarRef& rxProgressBar, WorksheetType eSheetType, sal_Int16 nSheet ) :
- BiffWorksheetFragmentBase( rParent, rxProgressBar, eSheetType, nSheet )
+BiffWorksheetFragment::BiffWorksheetFragment( const WorksheetHelper& rHelper, const BiffWorkbookFragmentBase& rParent ) :
+ BiffWorksheetFragmentBase( rHelper, rParent )
{
}
@@ -776,6 +759,7 @@ bool BiffWorksheetFragment::importFragment()
SheetViewSettings& rSheetViewSett = getSheetViewSettings();
CondFormatBuffer& rCondFormats = getCondFormats();
PageSettings& rPageSett = getPageSettings();
+ BiffSheetDrawing& rDrawing = getBiffDrawing();
// process all record in this sheet fragment
BiffInputStream& rStrm = getInputStream();
@@ -807,6 +791,7 @@ bool BiffWorksheetFragment::importFragment()
case BIFF_ID_HORPAGEBREAKS: importPageBreaks( rStrm, true ); break;
case BIFF_ID_ITERATION: rWorkbookSett.importIteration( rStrm ); break;
case BIFF_ID_LEFTMARGIN: rPageSett.importLeftMargin( rStrm ); break;
+ case BIFF_ID_NOTE: importNote( rStrm ); break;
case BIFF_ID_PANE: rSheetViewSett.importPane( rStrm ); break;
case BIFF_ID_PASSWORD: rWorksheetSett.importPassword( rStrm ); break;
case BIFF_ID_PRINTGRIDLINES: rPageSett.importPrintGridLines( rStrm ); break;
@@ -836,13 +821,13 @@ bool BiffWorksheetFragment::importFragment()
case BIFF_ID_DEFCOLWIDTH: importDefColWidth( rStrm ); break;
case BIFF3_ID_DEFROWHEIGHT: importDefRowHeight( rStrm ); break;
case BIFF_ID_HCENTER: rPageSett.importHorCenter( rStrm ); break;
+ case BIFF_ID_OBJ: rDrawing.importObj( rStrm ); break;
case BIFF_ID_OBJECTPROTECT: rWorksheetSett.importObjectProtect( rStrm ); break;
case BIFF_ID_SAVERECALC: rWorkbookSett.importSaveRecalc( rStrm ); break;
case BIFF_ID_SHEETPR: rWorksheetSett.importSheetPr( rStrm ); break;
case BIFF_ID_UNCALCED: rWorkbookSett.importUncalced( rStrm ); break;
case BIFF_ID_VCENTER: rPageSett.importVerCenter( rStrm ); break;
case BIFF3_ID_WINDOW2: rSheetViewSett.importWindow2( rStrm ); break;
-
}
break;
@@ -851,6 +836,7 @@ bool BiffWorksheetFragment::importFragment()
case BIFF_ID_COLINFO: importColInfo( rStrm ); break;
case BIFF3_ID_DEFROWHEIGHT: importDefRowHeight( rStrm ); break;
case BIFF_ID_HCENTER: rPageSett.importHorCenter( rStrm ); break;
+ case BIFF_ID_OBJ: rDrawing.importObj( rStrm ); break;
case BIFF_ID_OBJECTPROTECT: rWorksheetSett.importObjectProtect( rStrm ); break;
case BIFF_ID_PAGESETUP: rPageSett.importPageSetup( rStrm ); break;
case BIFF_ID_SAVERECALC: rWorkbookSett.importSaveRecalc( rStrm ); break;
@@ -869,6 +855,7 @@ bool BiffWorksheetFragment::importFragment()
case BIFF3_ID_DEFROWHEIGHT: importDefRowHeight( rStrm ); break;
case BIFF_ID_HCENTER: rPageSett.importHorCenter( rStrm ); break;
case BIFF_ID_MERGEDCELLS: importMergedCells( rStrm ); break; // #i62300# also in BIFF5
+ case BIFF_ID_OBJ: rDrawing.importObj( rStrm ); break;
case BIFF_ID_OBJECTPROTECT: rWorksheetSett.importObjectProtect( rStrm ); break;
case BIFF_ID_PAGESETUP: rPageSett.importPageSetup( rStrm ); break;
case BIFF_ID_PTDEFINITION: importPTDefinition( rStrm ); break;
@@ -896,6 +883,7 @@ bool BiffWorksheetFragment::importFragment()
case BIFF_ID_HYPERLINK: importHyperlink( rStrm ); break;
case BIFF_ID_LABELRANGES: importLabelRanges( rStrm ); break;
case BIFF_ID_MERGEDCELLS: importMergedCells( rStrm ); break;
+ case BIFF_ID_OBJ: rDrawing.importObj( rStrm ); break;
case BIFF_ID_OBJECTPROTECT: rWorksheetSett.importObjectProtect( rStrm ); break;
case BIFF_ID_PAGESETUP: rPageSett.importPageSetup( rStrm ); break;
case BIFF_ID_PHONETICPR: rWorksheetSett.importPhoneticPr( rStrm ); break;
@@ -958,15 +946,15 @@ void BiffWorksheetFragment::importColInfo( BiffInputStream& rStrm )
ColumnModel aModel;
// column indexes are 0-based in BIFF, but ColumnModel expects 1-based
- aModel.mnFirstCol = static_cast< sal_Int32 >( nFirstCol ) + 1;
- aModel.mnLastCol = static_cast< sal_Int32 >( nLastCol ) + 1;
+ aModel.maRange.mnFirst = static_cast< sal_Int32 >( nFirstCol ) + 1;
+ aModel.maRange.mnLast = static_cast< sal_Int32 >( nLastCol ) + 1;
// width is stored as 1/256th of a character in BIFF, convert to entire character
- aModel.mfWidth = static_cast< double >( nWidth ) / 256.0;
- aModel.mnXfId = nXfId;
- aModel.mnLevel = extractValue< sal_Int32 >( nFlags, 8, 3 );
- aModel.mbShowPhonetic = getFlag( nFlags, BIFF_COLINFO_SHOWPHONETIC );
- aModel.mbHidden = getFlag( nFlags, BIFF_COLINFO_HIDDEN );
- aModel.mbCollapsed = getFlag( nFlags, BIFF_COLINFO_COLLAPSED );
+ aModel.mfWidth = static_cast< double >( nWidth ) / 256.0;
+ aModel.mnXfId = nXfId;
+ aModel.mnLevel = extractValue< sal_Int32 >( nFlags, 8, 3 );
+ aModel.mbShowPhonetic = getFlag( nFlags, BIFF_COLINFO_SHOWPHONETIC );
+ aModel.mbHidden = getFlag( nFlags, BIFF_COLINFO_HIDDEN );
+ aModel.mbCollapsed = getFlag( nFlags, BIFF_COLINFO_COLLAPSED );
// set column properties in the current sheet
setColumnModel( aModel );
}
@@ -986,8 +974,8 @@ void BiffWorksheetFragment::importColWidth( BiffInputStream& rStrm )
ColumnModel aModel;
// column indexes are 0-based in BIFF, but ColumnModel expects 1-based
- aModel.mnFirstCol = static_cast< sal_Int32 >( nFirstCol ) + 1;
- aModel.mnLastCol = static_cast< sal_Int32 >( nLastCol ) + 1;
+ aModel.maRange.mnFirst = static_cast< sal_Int32 >( nFirstCol ) + 1;
+ aModel.maRange.mnLast = static_cast< sal_Int32 >( nLastCol ) + 1;
// width is stored as 1/256th of a character in BIFF, convert to entire character
aModel.mfWidth = static_cast< double >( nWidth ) / 256.0;
// set column properties in the current sheet
@@ -1042,10 +1030,7 @@ ApiTokenSequence lclReadDataValFormula( BiffInputStream& rStrm, FormulaParser& r
{
sal_uInt16 nFmlaSize = rStrm.readuInt16();
rStrm.skip( 2 );
- // enable NUL characters, string list is single tStr token with NUL separators
- TokensFormulaContext aContext( true, false, true );
- rParser.importFormula( aContext, rStrm, &nFmlaSize );
- return aContext.getTokens();
+ return rParser.importFormula( CellAddress(), FORMULATYPE_VALIDATION, rStrm, &nFmlaSize );
}
} // namespace
@@ -1164,7 +1149,12 @@ void BiffWorksheetFragment::importMergedCells( BiffInputStream& rStrm )
ApiCellRangeList aRanges;
getAddressConverter().convertToCellRangeList( aRanges, aBiffRanges, getSheetIndex(), true );
for( ApiCellRangeList::const_iterator aIt = aRanges.begin(), aEnd = aRanges.end(); aIt != aEnd; ++aIt )
- setMergedRange( *aIt );
+ getSheetData().setMergedRange( *aIt );
+}
+
+void BiffWorksheetFragment::importNote( BiffInputStream& rStrm )
+{
+ getComments().createComment()->importNote( rStrm );
}
void BiffWorksheetFragment::importPageBreaks( BiffInputStream& rStrm, bool bRowBreak )
diff --git a/oox/source/xls/worksheethelper.cxx b/oox/source/xls/worksheethelper.cxx
index d169f514acce..068c89cde2d9 100644
--- a/oox/source/xls/worksheethelper.cxx
+++ b/oox/source/xls/worksheethelper.cxx
@@ -43,7 +43,6 @@
#include <com/sun/star/sheet/XFormulaTokens.hpp>
#include <com/sun/star/sheet/XLabelRanges.hpp>
#include <com/sun/star/sheet/XMultiFormulaTokens.hpp>
-#include <com/sun/star/sheet/XMultipleOperation.hpp>
#include <com/sun/star/sheet/XSheetCellRangeContainer.hpp>
#include <com/sun/star/sheet/XSheetCondition2.hpp>
#include <com/sun/star/sheet/XSheetOutline.hpp>
@@ -51,24 +50,20 @@
#include <com/sun/star/table/XColumnRowRange.hpp>
#include <com/sun/star/text/WritingMode2.hpp>
#include <com/sun/star/text/XText.hpp>
-#include <com/sun/star/util/NumberFormat.hpp>
-#include <com/sun/star/util/XMergeable.hpp>
-#include <com/sun/star/util/XNumberFormatTypes.hpp>
-#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
#include <rtl/ustrbuf.hxx>
#include "oox/core/filterbase.hxx"
-#include "oox/helper/containerhelper.hxx"
#include "oox/helper/propertyset.hxx"
#include "oox/xls/addressconverter.hxx"
#include "oox/xls/autofilterbuffer.hxx"
#include "oox/xls/commentsbuffer.hxx"
#include "oox/xls/condformatbuffer.hxx"
#include "oox/xls/drawingfragment.hxx"
+#include "oox/xls/drawingmanager.hxx"
#include "oox/xls/formulaparser.hxx"
#include "oox/xls/pagesettings.hxx"
#include "oox/xls/querytablebuffer.hxx"
-#include "oox/xls/sharedformulabuffer.hxx"
#include "oox/xls/sharedstringsbuffer.hxx"
+#include "oox/xls/sheetdatabuffer.hxx"
#include "oox/xls/stylesbuffer.hxx"
#include "oox/xls/unitconverter.hxx"
#include "oox/xls/viewsettings.hxx"
@@ -114,106 +109,13 @@ void lclUpdateProgressBar( const ISegmentProgressBarRef& rxProgressBar, double f
rxProgressBar->setPosition( fPosition );
}
-// ----------------------------------------------------------------------------
-
-struct ValueRange
-{
- sal_Int32 mnFirst;
- sal_Int32 mnLast;
-
- inline explicit ValueRange( sal_Int32 nValue ) : mnFirst( nValue ), mnLast( nValue ) {}
- inline explicit ValueRange( sal_Int32 nFirst, sal_Int32 nLast ) : mnFirst( nFirst ), mnLast( nLast ) {}
-};
-
-typedef ::std::vector< ValueRange > ValueRangeVector;
-
-// ----------------------------------------------------------------------------
-
-struct ValueRangeComp
-{
- inline bool operator()( const ValueRange& rRange, sal_Int32 nValue ) const { return rRange.mnLast < nValue; }
-};
-
-
-// ----------------------------------------------------------------------------
-
-class ValueRangeSet
-{
-public:
- inline explicit ValueRangeSet() {}
-
- void insert( sal_Int32 nValue );
- void intersect( ValueRangeVector& orRanges, sal_Int32 nFirst, sal_Int32 nLast ) const;
-
-private:
- ValueRangeVector maData;
-};
-
-void ValueRangeSet::insert( sal_Int32 nValue )
-{
- // find the first range that contains nValue or that follows nValue
- ValueRangeVector::iterator aBeg = maData.begin();
- ValueRangeVector::iterator aEnd = maData.end();
- ValueRangeVector::iterator aNext = ::std::lower_bound( aBeg, aEnd, nValue, ValueRangeComp() );
-
- // nothing to do if found range contains nValue
- if( (aNext == aEnd) || (nValue < aNext->mnFirst) )
- {
- ValueRangeVector::iterator aPrev = (aNext == aBeg) ? aEnd : (aNext - 1);
- bool bJoinPrev = (aPrev != aEnd) && (aPrev->mnLast + 1 == nValue);
- bool bJoinNext = (aNext != aEnd) && (aNext->mnFirst - 1 == nValue);
- if( bJoinPrev && bJoinNext )
- {
- aPrev->mnLast = aNext->mnLast;
- maData.erase( aNext );
- }
- else if( bJoinPrev )
- ++aPrev->mnLast;
- else if( bJoinNext )
- --aNext->mnFirst;
- else
- maData.insert( aNext, ValueRange( nValue ) );
- }
-}
-
-void ValueRangeSet::intersect( ValueRangeVector& orRanges, sal_Int32 nFirst, sal_Int32 nLast ) const
-{
- orRanges.clear();
- // find the range that contains nFirst or the first range that follows nFirst
- ValueRangeVector::const_iterator aIt = ::std::lower_bound( maData.begin(), maData.end(), nFirst, ValueRangeComp() );
- for( ValueRangeVector::const_iterator aEnd = maData.end(); (aIt != aEnd) && (aIt->mnFirst <= nLast); ++aIt )
- orRanges.push_back( ValueRange( ::std::max( aIt->mnFirst, nFirst ), ::std::min( aIt->mnLast, nLast ) ) );
-}
-
} // namespace
// ============================================================================
// ============================================================================
-void CellModel::reset()
-{
- mxCell.clear();
- maValueStr = maFormulaRef = OUString();
- mnCellType = mnFormulaType = XML_TOKEN_INVALID;
- mnSharedId = mnXfId = mnNumFmtId = -1;
- mbHasValueStr = mbShowPhonetic = false;
-}
-
-// ----------------------------------------------------------------------------
-
-DataTableModel::DataTableModel() :
- mb2dTable( false ),
- mbRowTable( false ),
- mbRef1Deleted( false ),
- mbRef2Deleted( false )
-{
-}
-
-// ----------------------------------------------------------------------------
-
ColumnModel::ColumnModel() :
- mnFirstCol( -1 ),
- mnLastCol( -1 ),
+ maRange( -1 ),
mfWidth( 0.0 ),
mnXfId( -1 ),
mnLevel( 0 ),
@@ -223,27 +125,22 @@ ColumnModel::ColumnModel() :
{
}
-bool ColumnModel::tryExpand( const ColumnModel& rModel )
+bool ColumnModel::isMergeable( const ColumnModel& rModel ) const
{
- bool bExpandable =
- (mnFirstCol <= rModel.mnFirstCol) &&
- (rModel.mnFirstCol <= mnLastCol + 1) &&
- (mfWidth == rModel.mfWidth) &&
+ return
+ (maRange.mnFirst <= rModel.maRange.mnFirst) &&
+ (rModel.maRange.mnFirst <= maRange.mnLast + 1) &&
+ (mfWidth == rModel.mfWidth) &&
// ignore mnXfId, cell formatting is always set directly
- (mnLevel == rModel.mnLevel) &&
- (mbHidden == rModel.mbHidden) &&
- (mbCollapsed == rModel.mbCollapsed);
-
- if( bExpandable )
- mnLastCol = rModel.mnLastCol;
- return bExpandable;
+ (mnLevel == rModel.mnLevel) &&
+ (mbHidden == rModel.mbHidden) &&
+ (mbCollapsed == rModel.mbCollapsed);
}
// ----------------------------------------------------------------------------
RowModel::RowModel() :
- mnFirstRow( -1 ),
- mnLastRow( -1 ),
+ mnRow( -1 ),
mfHeight( 0.0 ),
mnXfId( -1 ),
mnLevel( 0 ),
@@ -257,21 +154,22 @@ RowModel::RowModel() :
{
}
-bool RowModel::tryExpand( const RowModel& rModel )
+void RowModel::insertColSpan( const ValueRange& rColSpan )
{
- bool bExpandable =
- (mnFirstRow <= rModel.mnFirstRow) &&
- (rModel.mnFirstRow <= mnLastRow + 1) &&
- (mfHeight == rModel.mfHeight) &&
- // ignore mnXfId, mbCustomFormat, mbShowPhonetic - cell formatting is always set directly
- (mnLevel == rModel.mnLevel) &&
- (mbCustomHeight == rModel.mbCustomHeight) &&
- (mbHidden == rModel.mbHidden) &&
- (mbCollapsed == rModel.mbCollapsed);
+ if( (0 <= rColSpan.mnFirst) && (rColSpan.mnFirst <= rColSpan.mnLast) )
+ maColSpans.insert( rColSpan );
+}
- if( bExpandable )
- mnLastRow = rModel.mnLastRow;
- return bExpandable;
+bool RowModel::isMergeable( const RowModel& rModel ) const
+{
+ return
+ // ignore maColSpans - is handled separately in SheetDataBuffer class
+ (mfHeight == rModel.mfHeight) &&
+ // ignore mnXfId, mbCustomFormat, mbShowPhonetic - cell formatting is always set directly
+ (mnLevel == rModel.mnLevel) &&
+ (mbCustomHeight == rModel.mbCustomHeight) &&
+ (mbHidden == rModel.mbHidden) &&
+ (mbCollapsed == rModel.mbCollapsed);
}
// ----------------------------------------------------------------------------
@@ -325,10 +223,10 @@ void ValidationModel::setBiffErrorStyle( sal_uInt8 nErrorStyle )
// ============================================================================
// ============================================================================
-class WorksheetData : public WorkbookHelper
+class WorksheetGlobals : public WorkbookHelper
{
public:
- explicit WorksheetData(
+ explicit WorksheetGlobals(
const WorkbookHelper& rHelper,
const ISegmentProgressBarRef& rxProgressBar,
WorksheetType eSheetType,
@@ -337,16 +235,12 @@ public:
/** Returns true, if this helper refers to an existing Calc sheet. */
inline bool isValidSheet() const { return mxSheet.is(); }
- /** Returns a cell formula simulating the passed boolean value. */
- const OUString& getBooleanFormula( bool bValue ) const;
-
/** Returns the type of this sheet. */
inline WorksheetType getSheetType() const { return meSheetType; }
/** Returns the index of the current sheet. */
inline sal_Int16 getSheetIndex() const { return maUsedArea.Sheet; }
/** Returns the XSpreadsheet interface of the current sheet. */
- inline const ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XSpreadsheet >&
- getSheet() const { return mxSheet; }
+ inline const Reference< XSpreadsheet >& getSheet() const { return mxSheet; }
/** Returns the XCell interface for the passed cell address. */
Reference< XCell > getCell( const CellAddress& rAddress ) const;
@@ -361,14 +255,14 @@ public:
Reference< XCellRange > getRow( sal_Int32 nRow ) const;
/** Returns the XTableColumns interface for a range of columns. */
- Reference< XTableColumns > getColumns( sal_Int32 nFirstCol, sal_Int32 nLastCol ) const;
+ Reference< XTableColumns > getColumns( const ValueRange& rColRange ) const;
/** Returns the XTableRows interface for a range of rows. */
- Reference< XTableRows > getRows( sal_Int32 nFirstRow, sal_Int32 nLastRow ) const;
+ Reference< XTableRows > getRows( const ValueRange& rRowRange ) const;
/** Returns the XDrawPage interface of the draw page of the current sheet. */
Reference< XDrawPage > getDrawPage() const;
/** Returns the size of the entire drawing page in 1/100 mm. */
- Size getDrawPageSize() const;
+ const Size& getDrawPageSize() const;
/** Returns the absolute position of the top-left corner of the cell in 1/100 mm. */
Point getCellPosition( sal_Int32 nCol, sal_Int32 nRow ) const;
@@ -376,14 +270,12 @@ public:
Size getCellSize( sal_Int32 nCol, sal_Int32 nRow ) const;
/** Returns the address of the cell that contains the passed point in 1/100 mm. */
- CellAddress getCellAddressFromPosition( const Point& rPosition, const Size& rDrawPageSize ) const;
+ CellAddress getCellAddressFromPosition( const Point& rPosition ) const;
/** Returns the cell range address that contains the passed rectangle in 1/100 mm. */
CellRangeAddress getCellRangeFromRectangle( const Rectangle& rRect ) const;
- /** Returns the worksheet settings object. */
- inline WorksheetSettings& getWorksheetSettings() { return maSheetSett; }
- /** Returns the buffer containing all shared formulas in this sheet. */
- inline SharedFormulaBuffer& getSharedFormulas() { return maSharedFmlas; }
+ /** Returns the buffer for cell contents and cell formatting. */
+ inline SheetDataBuffer& getSheetData() { return maSheetData; }
/** Returns the conditional formattings in this sheet. */
inline CondFormatBuffer& getCondFormats() { return maCondFormats; }
/** Returns the buffer for all cell comments in this sheet. */
@@ -392,19 +284,19 @@ public:
inline AutoFilterBuffer& getAutoFilters() { return maAutoFilters; }
/** Returns the buffer for all web query tables in this sheet. */
inline QueryTableBuffer& getQueryTables() { return maQueryTables; }
+ /** Returns the worksheet settings object. */
+ inline WorksheetSettings& getWorksheetSettings() { return maSheetSett; }
/** Returns the page/print settings for this sheet. */
inline PageSettings& getPageSettings() { return maPageSett; }
/** Returns the view settings for this sheet. */
inline SheetViewSettings& getSheetViewSettings() { return maSheetViewSett; }
- /** Returns the VML drawing page for this sheet (OOXML/BIFF12 only!). */
+ /** Returns the VML drawing page for this sheet (OOXML/BIFF12 only). */
inline VmlDrawing& getVmlDrawing() { return *mxVmlDrawing; }
+ /** Returns the BIFF drawing page for this sheet (BIFF2-BIFF8 only). */
+ inline BiffSheetDrawing& getBiffDrawing() const { return *mxBiffDrawing; }
/** Changes the current sheet type. */
inline void setSheetType( WorksheetType eSheetType ) { meSheetType = eSheetType; }
- /** Stores the cell format at the passed address. */
- void setCellFormat( const CellModel& rModel );
- /** Merges the cells in the passed cell range. */
- void setMergedRange( const CellRangeAddress& rRange );
/** Sets a column or row page break described in the passed struct. */
void setPageBreak( const PageBreakModel& rModel, bool bRowBreak );
/** Inserts the hyperlink URL into the spreadsheet. */
@@ -433,6 +325,8 @@ public:
@descr Column default formatting is converted directly, other settings
are cached and converted in the finalizeImport() call. */
void setColumnModel( const ColumnModel& rModel );
+ /** Converts column default cell formatting. */
+ void convertColumnFormat( sal_Int32 nFirstCol, sal_Int32 nLastCol, sal_Int32 nXfId ) const;
/** Sets default height and hidden state for all unused rows in the sheet. */
void setDefaultRowSettings( double fHeight, bool bCustomHeight, bool bHidden, bool bThickTop, bool bThickBottom );
@@ -440,11 +334,8 @@ public:
@descr Row default formatting is converted directly, other settings
are cached and converted in the finalizeImport() call. */
void setRowModel( const RowModel& rModel );
-
- /** Converts column default cell formatting. */
- void convertColumnFormat( sal_Int32 nFirstCol, sal_Int32 nLastCol, sal_Int32 nXfId ) const;
- /** Converts row default cell formatting. */
- void convertRowFormat( sal_Int32 nFirstRow, sal_Int32 nLastRow, sal_Int32 nXfId ) const;
+ /** Specifies that the passed row needs to set its height manually. */
+ void setManualRowHeight( sal_Int32 nRow );
/** Initial conversion before importing the worksheet. */
void initializeWorksheetImport();
@@ -453,57 +344,13 @@ public:
private:
typedef ::std::vector< sal_Int32 > OutlineLevelVec;
- typedef ::std::map< sal_Int32, ColumnModel > ColumnModelMap;
- typedef ::std::map< sal_Int32, RowModel > RowModelMap;
+ typedef ::std::pair< ColumnModel, sal_Int32 > ColumnModelRange;
+ typedef ::std::map< sal_Int32, ColumnModelRange > ColumnModelRangeMap;
+ typedef ::std::pair< RowModel, sal_Int32 > RowModelRange;
+ typedef ::std::map< sal_Int32, RowModelRange > RowModelRangeMap;
typedef ::std::list< HyperlinkModel > HyperlinkModelList;
typedef ::std::list< ValidationModel > ValidationModelList;
- struct XfIdRowRange
- {
- sal_Int32 mnFirstRow; /// Index of first row.
- sal_Int32 mnLastRow; /// Index of last row.
- sal_Int32 mnXfId; /// XF identifier for the row range.
-
- explicit XfIdRowRange();
- bool intersects( const CellRangeAddress& rRange ) const;
- void set( sal_Int32 nFirstRow, sal_Int32 nLastRow, sal_Int32 nXfId );
- bool tryExpand( sal_Int32 nFirstRow, sal_Int32 nLastRow, sal_Int32 nXfId );
- };
-
- struct XfIdRange
- {
- CellRangeAddress maRange; /// The formatted cell range.
- sal_Int32 mnXfId; /// XF identifier for the range.
- sal_Int32 mnNumFmtId; /// Number format id overriding the XF.
-
- void set( const CellModel& rModel );
- bool tryExpand( const CellModel& rModel );
- bool tryMerge( const XfIdRange& rXfIdRange );
- };
-
- struct MergedRange
- {
- CellRangeAddress maRange; /// The formatted cell range.
- sal_Int32 mnHorAlign; /// Horizontal alignment in the range.
-
- explicit MergedRange( const CellRangeAddress& rRange );
- explicit MergedRange( const CellAddress& rAddress, sal_Int32 nHorAlign );
- bool tryExpand( const CellAddress& rAddress, sal_Int32 nHorAlign );
- };
-
- typedef ::std::pair< sal_Int32, sal_Int32 > RowColKey;
- typedef ::std::map< RowColKey, XfIdRange > XfIdRangeMap;
- typedef ::std::list< MergedRange > MergedRangeList;
-
- /** Writes all cell formatting attributes to the passed row range. */
- void writeXfIdRowRangeProperties( const XfIdRowRange& rXfIdRowRange ) const;
- /** Writes all cell formatting attributes to the passed cell range. */
- void writeXfIdRangeProperties( const XfIdRange& rXfIdRange ) const;
- /** Tries to merge the ranges last inserted in maXfIdRanges with existing ranges. */
- void mergeXfIdRanges();
- /** Finalizes the remaining ranges in maXfIdRanges. */
- void finalizeXfIdRanges();
-
/** Inserts all imported hyperlinks into their cell ranges. */
void finalizeHyperlinkRanges() const;
/** Generates the final URL for the passed hyperlink. */
@@ -514,60 +361,52 @@ private:
/** Inserts all imported data validations into their cell ranges. */
void finalizeValidationRanges() const;
- /** Merges all cached merged ranges and updates right/bottom cell borders. */
- void finalizeMergedRanges();
- /** Merges the passed merged range and updates right/bottom cell borders. */
- void finalizeMergedRange( const CellRangeAddress& rRange );
-
/** Converts column properties for all columns in the sheet. */
void convertColumns();
/** Converts column properties. */
- void convertColumns( OutlineLevelVec& orColLevels, sal_Int32 nFirstCol, sal_Int32 nLastCol, const ColumnModel& rModel );
+ void convertColumns( OutlineLevelVec& orColLevels, const ValueRange& rColRange, const ColumnModel& rModel );
/** Converts row properties for all rows in the sheet. */
void convertRows();
/** Converts row properties. */
- void convertRows( OutlineLevelVec& orRowLevels, sal_Int32 nFirstRow, sal_Int32 nLastRow, const RowModel& rModel, double fDefHeight = -1.0 );
+ void convertRows( OutlineLevelVec& orRowLevels, const ValueRange& rRowRange, const RowModel& rModel, double fDefHeight = -1.0 );
/** Converts outline grouping for the passed column or row. */
void convertOutlines( OutlineLevelVec& orLevels, sal_Int32 nColRow, sal_Int32 nLevel, bool bCollapsed, bool bRows );
/** Groups columns or rows for the given range. */
void groupColumnsOrRows( sal_Int32 nFirstColRow, sal_Int32 nLastColRow, bool bCollapsed, bool bRows );
- /** Imports the drawings of the sheet (DML, VML), and updates the used area. */
+ /** Imports the drawings of the sheet (DML, VML, DFF) and updates the used area. */
void finalizeDrawings();
private:
- typedef ::std::auto_ptr< VmlDrawing > VmlDrawingPtr;
+ typedef ::std::auto_ptr< VmlDrawing > VmlDrawingPtr;
+ typedef ::std::auto_ptr< BiffSheetDrawing > BiffSheetDrawingPtr;
- const OUString maTrueFormula; /// Replacement formula for TRUE boolean cells.
- const OUString maFalseFormula; /// Replacement formula for FALSE boolean cells.
const OUString maSheetCellRanges; /// Service name for a SheetCellRanges object.
const OUString maUrlTextField; /// Service name for a URL text field.
const CellAddress& mrMaxApiPos; /// Reference to maximum Calc cell address from address converter.
CellRangeAddress maUsedArea; /// Used area of the sheet, and sheet index of the sheet.
ColumnModel maDefColModel; /// Default column formatting.
- ColumnModelMap maColModels; /// Columns sorted by first column index.
+ ColumnModelRangeMap maColModels; /// Ranges of columns sorted by first column index.
RowModel maDefRowModel; /// Default row formatting.
- RowModelMap maRowModels; /// Rows sorted by row index.
+ RowModelRangeMap maRowModels; /// Ranges of rows sorted by first row index.
HyperlinkModelList maHyperlinks; /// Cell ranges containing hyperlinks.
ValidationModelList maValidations; /// Cell ranges containing data validation settings.
- XfIdRowRange maXfIdRowRange; /// Cached XF identifier for a range of rows.
- XfIdRangeMap maXfIdRanges; /// Collected XF identifiers for cell ranges.
- MergedRangeList maMergedRanges; /// Merged cell ranges.
- MergedRangeList maCenterFillRanges; /// Merged cell ranges from 'center across' or 'fill' alignment.
ValueRangeSet maManualRowHeights; /// Rows that need manual height independent from own settings.
- WorksheetSettings maSheetSett; /// Global settings for this sheet.
- SharedFormulaBuffer maSharedFmlas; /// Buffer for shared formulas in this sheet.
+ SheetDataBuffer maSheetData; /// Buffer for cell contents and cell formatting.
CondFormatBuffer maCondFormats; /// Buffer for conditional formattings.
CommentsBuffer maComments; /// Buffer for all cell comments in this sheet.
AutoFilterBuffer maAutoFilters; /// Sheet auto filters (not associated to a table).
QueryTableBuffer maQueryTables; /// Buffer for all web query tables in this sheet.
+ WorksheetSettings maSheetSett; /// Global settings for this sheet.
PageSettings maPageSett; /// Page/print settings for this sheet.
SheetViewSettings maSheetViewSett; /// View settings for this sheet.
VmlDrawingPtr mxVmlDrawing; /// Collection of all VML shapes.
+ BiffSheetDrawingPtr mxBiffDrawing; /// Collection of all BIFF/DFF shapes.
OUString maDrawingPath; /// Path to DrawingML fragment.
OUString maVmlDrawingPath; /// Path to legacy VML drawing fragment.
+ Size maDrawPageSize; /// Current size of the drawing page in 1/100 mm.
Rectangle maShapeBoundingBox; /// Bounding box for all shapes from all drawings.
ISegmentProgressBarRef mxProgressBar; /// Sheet progress bar.
ISegmentProgressBarRef mxRowProgress; /// Progress bar for row/cell processing.
@@ -579,20 +418,18 @@ private:
// ----------------------------------------------------------------------------
-WorksheetData::WorksheetData( const WorkbookHelper& rHelper, const ISegmentProgressBarRef& rxProgressBar, WorksheetType eSheetType, sal_Int16 nSheet ) :
+WorksheetGlobals::WorksheetGlobals( const WorkbookHelper& rHelper, const ISegmentProgressBarRef& rxProgressBar, WorksheetType eSheetType, sal_Int16 nSheet ) :
WorkbookHelper( rHelper ),
- maTrueFormula( CREATE_OUSTRING( "=TRUE()" ) ),
- maFalseFormula( CREATE_OUSTRING( "=FALSE()" ) ),
maSheetCellRanges( CREATE_OUSTRING( "com.sun.star.sheet.SheetCellRanges" ) ),
maUrlTextField( CREATE_OUSTRING( "com.sun.star.text.TextField.URL" ) ),
mrMaxApiPos( rHelper.getAddressConverter().getMaxApiAddress() ),
maUsedArea( nSheet, SAL_MAX_INT32, SAL_MAX_INT32, -1, -1 ),
- maSheetSett( *this ),
- maSharedFmlas( *this ),
+ maSheetData( *this ),
maCondFormats( *this ),
maComments( *this ),
maAutoFilters( *this ),
maQueryTables( *this ),
+ maSheetSett( *this ),
maPageSett( *this ),
maSheetViewSett( *this ),
mxProgressBar( rxProgressBar ),
@@ -621,8 +458,17 @@ WorksheetData::WorksheetData( const WorkbookHelper& rHelper, const ISegmentProgr
maDefRowModel.mbCollapsed = false;
// buffers
- if( getFilterType() == FILTER_OOXML )
- mxVmlDrawing.reset( new VmlDrawing( *this ) );
+ switch( getFilterType() )
+ {
+ case FILTER_OOXML:
+ mxVmlDrawing.reset( new VmlDrawing( *this ) );
+ break;
+ case FILTER_BIFF:
+ mxBiffDrawing.reset( new BiffSheetDrawing( *this ) );
+ break;
+ case FILTER_UNKNOWN:
+ break;
+ }
// prepare progress bars
if( mxProgressBar.get() )
@@ -632,12 +478,7 @@ WorksheetData::WorksheetData( const WorkbookHelper& rHelper, const ISegmentProgr
}
}
-const OUString& WorksheetData::getBooleanFormula( bool bValue ) const
-{
- return bValue ? maTrueFormula : maFalseFormula;
-}
-
-Reference< XCell > WorksheetData::getCell( const CellAddress& rAddress ) const
+Reference< XCell > WorksheetGlobals::getCell( const CellAddress& rAddress ) const
{
Reference< XCell > xCell;
if( mxSheet.is() ) try
@@ -650,7 +491,7 @@ Reference< XCell > WorksheetData::getCell( const CellAddress& rAddress ) const
return xCell;
}
-Reference< XCellRange > WorksheetData::getCellRange( const CellRangeAddress& rRange ) const
+Reference< XCellRange > WorksheetGlobals::getCellRange( const CellRangeAddress& rRange ) const
{
Reference< XCellRange > xRange;
if( mxSheet.is() ) try
@@ -663,12 +504,12 @@ Reference< XCellRange > WorksheetData::getCellRange( const CellRangeAddress& rRa
return xRange;
}
-Reference< XSheetCellRanges > WorksheetData::getCellRangeList( const ApiCellRangeList& rRanges ) const
+Reference< XSheetCellRanges > WorksheetGlobals::getCellRangeList( const ApiCellRangeList& rRanges ) const
{
Reference< XSheetCellRanges > xRanges;
if( mxSheet.is() && !rRanges.empty() ) try
{
- xRanges.set( getDocumentFactory()->createInstance( maSheetCellRanges ), UNO_QUERY_THROW );
+ xRanges.set( getBaseFilter().getModelFactory()->createInstance( maSheetCellRanges ), UNO_QUERY_THROW );
Reference< XSheetCellRangeContainer > xRangeCont( xRanges, UNO_QUERY_THROW );
xRangeCont->addRangeAddresses( ContainerHelper::vectorToSequence( rRanges ), sal_False );
}
@@ -678,7 +519,7 @@ Reference< XSheetCellRanges > WorksheetData::getCellRangeList( const ApiCellRang
return xRanges;
}
-Reference< XCellRange > WorksheetData::getColumn( sal_Int32 nCol ) const
+Reference< XCellRange > WorksheetGlobals::getColumn( sal_Int32 nCol ) const
{
Reference< XCellRange > xColumn;
try
@@ -693,7 +534,7 @@ Reference< XCellRange > WorksheetData::getColumn( sal_Int32 nCol ) const
return xColumn;
}
-Reference< XCellRange > WorksheetData::getRow( sal_Int32 nRow ) const
+Reference< XCellRange > WorksheetGlobals::getRow( sal_Int32 nRow ) const
{
Reference< XCellRange > xRow;
try
@@ -708,33 +549,33 @@ Reference< XCellRange > WorksheetData::getRow( sal_Int32 nRow ) const
return xRow;
}
-Reference< XTableColumns > WorksheetData::getColumns( sal_Int32 nFirstCol, sal_Int32 nLastCol ) const
+Reference< XTableColumns > WorksheetGlobals::getColumns( const ValueRange& rColRange ) const
{
Reference< XTableColumns > xColumns;
- nLastCol = ::std::min( nLastCol, mrMaxApiPos.Column );
- if( (0 <= nFirstCol) && (nFirstCol <= nLastCol) )
+ sal_Int32 nLastCol = ::std::min( rColRange.mnLast, mrMaxApiPos.Column );
+ if( (0 <= rColRange.mnFirst) && (rColRange.mnFirst <= nLastCol) )
{
- Reference< XColumnRowRange > xRange( getCellRange( CellRangeAddress( getSheetIndex(), nFirstCol, 0, nLastCol, 0 ) ), UNO_QUERY );
+ Reference< XColumnRowRange > xRange( getCellRange( CellRangeAddress( getSheetIndex(), rColRange.mnFirst, 0, nLastCol, 0 ) ), UNO_QUERY );
if( xRange.is() )
xColumns = xRange->getColumns();
}
return xColumns;
}
-Reference< XTableRows > WorksheetData::getRows( sal_Int32 nFirstRow, sal_Int32 nLastRow ) const
+Reference< XTableRows > WorksheetGlobals::getRows( const ValueRange& rRowRange ) const
{
Reference< XTableRows > xRows;
- nLastRow = ::std::min( nLastRow, mrMaxApiPos.Row );
- if( (0 <= nFirstRow) && (nFirstRow <= nLastRow) )
+ sal_Int32 nLastRow = ::std::min( rRowRange.mnLast, mrMaxApiPos.Row );
+ if( (0 <= rRowRange.mnFirst) && (rRowRange.mnFirst <= nLastRow) )
{
- Reference< XColumnRowRange > xRange( getCellRange( CellRangeAddress( getSheetIndex(), 0, nFirstRow, 0, nLastRow ) ), UNO_QUERY );
+ Reference< XColumnRowRange > xRange( getCellRange( CellRangeAddress( getSheetIndex(), 0, rRowRange.mnFirst, 0, nLastRow ) ), UNO_QUERY );
if( xRange.is() )
xRows = xRange->getRows();
}
return xRows;
}
-Reference< XDrawPage > WorksheetData::getDrawPage() const
+Reference< XDrawPage > WorksheetGlobals::getDrawPage() const
{
Reference< XDrawPage > xDrawPage;
try
@@ -747,15 +588,13 @@ Reference< XDrawPage > WorksheetData::getDrawPage() const
return xDrawPage;
}
-Size WorksheetData::getDrawPageSize() const
+const Size& WorksheetGlobals::getDrawPageSize() const
{
- Size aSize;
- PropertySet aRangeProp( getCellRange( CellRangeAddress( getSheetIndex(), 0, 0, mrMaxApiPos.Column, mrMaxApiPos.Row ) ) );
- aRangeProp.getProperty( aSize, PROP_Size );
- return aSize;
+ OSL_ENSURE( (maDrawPageSize.Width > 0) && (maDrawPageSize.Height > 0), "WorksheetGlobals::getDrawPageSize - called too early, size invalid" );
+ return maDrawPageSize;
}
-Point WorksheetData::getCellPosition( sal_Int32 nCol, sal_Int32 nRow ) const
+Point WorksheetGlobals::getCellPosition( sal_Int32 nCol, sal_Int32 nRow ) const
{
Point aPoint;
PropertySet aCellProp( getCell( CellAddress( getSheetIndex(), nCol, nRow ) ) );
@@ -763,7 +602,7 @@ Point WorksheetData::getCellPosition( sal_Int32 nCol, sal_Int32 nRow ) const
return aPoint;
}
-Size WorksheetData::getCellSize( sal_Int32 nCol, sal_Int32 nRow ) const
+Size WorksheetGlobals::getCellSize( sal_Int32 nCol, sal_Int32 nRow ) const
{
Size aSize;
PropertySet aCellProp( getCell( CellAddress( getSheetIndex(), nCol, nRow ) ) );
@@ -840,7 +679,7 @@ bool lclUpdateInterval( sal_Int32& rnBegAddr, sal_Int32& rnMidAddr, sal_Int32& r
} // namespace
-CellAddress WorksheetData::getCellAddressFromPosition( const Point& rPosition, const Size& rDrawPageSize ) const
+CellAddress WorksheetGlobals::getCellAddressFromPosition( const Point& rPosition ) const
{
// starting cell address and its position in drawing layer (top-left edge)
sal_Int32 nBegCol = 0;
@@ -850,7 +689,7 @@ CellAddress WorksheetData::getCellAddressFromPosition( const Point& rPosition, c
// end cell address and its position in drawing layer (bottom-right edge)
sal_Int32 nEndCol = mrMaxApiPos.Column + 1;
sal_Int32 nEndRow = mrMaxApiPos.Row + 1;
- Point aEndPos( rDrawPageSize.Width, rDrawPageSize.Height );
+ Point aEndPos( maDrawPageSize.Width, maDrawPageSize.Height );
// starting point for interval search
sal_Int32 nMidCol, nMidRow;
@@ -876,12 +715,11 @@ CellAddress WorksheetData::getCellAddressFromPosition( const Point& rPosition, c
return CellAddress( getSheetIndex(), nMidCol, nMidRow );
}
-CellRangeAddress WorksheetData::getCellRangeFromRectangle( const Rectangle& rRect ) const
+CellRangeAddress WorksheetGlobals::getCellRangeFromRectangle( const Rectangle& rRect ) const
{
- Size aPageSize = getDrawPageSize();
- CellAddress aStartAddr = getCellAddressFromPosition( Point( rRect.X, rRect.Y ), aPageSize );
+ CellAddress aStartAddr = getCellAddressFromPosition( Point( rRect.X, rRect.Y ) );
Point aBotRight( rRect.X + rRect.Width, rRect.Y + rRect.Height );
- CellAddress aEndAddr = getCellAddressFromPosition( aBotRight, aPageSize );
+ CellAddress aEndAddr = getCellAddressFromPosition( aBotRight );
bool bMultiCols = aStartAddr.Column < aEndAddr.Column;
bool bMultiRows = aStartAddr.Row < aEndAddr.Row;
if( bMultiCols || bMultiRows )
@@ -897,62 +735,7 @@ CellRangeAddress WorksheetData::getCellRangeFromRectangle( const Rectangle& rRec
return CellRangeAddress( getSheetIndex(), aStartAddr.Column, aStartAddr.Row, aEndAddr.Column, aEndAddr.Row );
}
-void WorksheetData::setCellFormat( const CellModel& rModel )
-{
- if( rModel.mxCell.is() && ((rModel.mnXfId >= 0) || (rModel.mnNumFmtId >= 0)) )
- {
- // try to merge existing ranges and to write some formatting properties
- if( !maXfIdRanges.empty() )
- {
- // get row index of last inserted cell
- sal_Int32 nLastRow = maXfIdRanges.rbegin()->second.maRange.StartRow;
- // row changed - try to merge ranges of last row with existing ranges
- if( rModel.maAddress.Row != nLastRow )
- {
- mergeXfIdRanges();
- // write format properties of all ranges above last row and remove them
- XfIdRangeMap::iterator aIt = maXfIdRanges.begin(), aEnd = maXfIdRanges.end();
- while( aIt != aEnd )
- {
- // check that range cannot be merged with current row, and that range is not in cached row range
- if( (aIt->second.maRange.EndRow < nLastRow) && !maXfIdRowRange.intersects( aIt->second.maRange ) )
- {
- writeXfIdRangeProperties( aIt->second );
- maXfIdRanges.erase( aIt++ );
- }
- else
- ++aIt;
- }
- }
- }
-
- // try to expand last existing range, or create new range entry
- if( maXfIdRanges.empty() || !maXfIdRanges.rbegin()->second.tryExpand( rModel ) )
- maXfIdRanges[ RowColKey( rModel.maAddress.Row, rModel.maAddress.Column ) ].set( rModel );
-
- // update merged ranges for 'center across selection' and 'fill'
- if( const Xf* pXf = getStyles().getCellXf( rModel.mnXfId ).get() )
- {
- sal_Int32 nHorAlign = pXf->getAlignment().getModel().mnHorAlign;
- if( (nHorAlign == XML_centerContinuous) || (nHorAlign == XML_fill) )
- {
- /* start new merged range, if cell is not empty (#108781#),
- or try to expand last range with empty cell */
- if( rModel.mnCellType != XML_TOKEN_INVALID )
- maCenterFillRanges.push_back( MergedRange( rModel.maAddress, nHorAlign ) );
- else if( !maCenterFillRanges.empty() )
- maCenterFillRanges.rbegin()->tryExpand( rModel.maAddress, nHorAlign );
- }
- }
- }
-}
-
-void WorksheetData::setMergedRange( const CellRangeAddress& rRange )
-{
- maMergedRanges.push_back( MergedRange( rRange ) );
-}
-
-void WorksheetData::setPageBreak( const PageBreakModel& rModel, bool bRowBreak )
+void WorksheetGlobals::setPageBreak( const PageBreakModel& rModel, bool bRowBreak )
{
if( rModel.mbManual && (rModel.mnColRow > 0) )
{
@@ -961,27 +744,27 @@ void WorksheetData::setPageBreak( const PageBreakModel& rModel, bool bRowBreak )
}
}
-void WorksheetData::setHyperlink( const HyperlinkModel& rModel )
+void WorksheetGlobals::setHyperlink( const HyperlinkModel& rModel )
{
maHyperlinks.push_back( rModel );
}
-void WorksheetData::setValidation( const ValidationModel& rModel )
+void WorksheetGlobals::setValidation( const ValidationModel& rModel )
{
maValidations.push_back( rModel );
}
-void WorksheetData::setDrawingPath( const OUString& rDrawingPath )
+void WorksheetGlobals::setDrawingPath( const OUString& rDrawingPath )
{
maDrawingPath = rDrawingPath;
}
-void WorksheetData::setVmlDrawingPath( const OUString& rVmlDrawingPath )
+void WorksheetGlobals::setVmlDrawingPath( const OUString& rVmlDrawingPath )
{
maVmlDrawingPath = rVmlDrawingPath;
}
-void WorksheetData::extendUsedArea( const CellAddress& rAddress )
+void WorksheetGlobals::extendUsedArea( const CellAddress& rAddress )
{
maUsedArea.StartColumn = ::std::min( maUsedArea.StartColumn, rAddress.Column );
maUsedArea.StartRow = ::std::min( maUsedArea.StartRow, rAddress.Row );
@@ -989,13 +772,13 @@ void WorksheetData::extendUsedArea( const CellAddress& rAddress )
maUsedArea.EndRow = ::std::max( maUsedArea.EndRow, rAddress.Row );
}
-void WorksheetData::extendUsedArea( const CellRangeAddress& rRange )
+void WorksheetGlobals::extendUsedArea( const CellRangeAddress& rRange )
{
extendUsedArea( CellAddress( rRange.Sheet, rRange.StartColumn, rRange.StartRow ) );
extendUsedArea( CellAddress( rRange.Sheet, rRange.EndColumn, rRange.EndRow ) );
}
-void WorksheetData::extendShapeBoundingBox( const Rectangle& rShapeRect )
+void WorksheetGlobals::extendShapeBoundingBox( const Rectangle& rShapeRect )
{
if( (maShapeBoundingBox.Width == 0) && (maShapeBoundingBox.Height == 0) )
{
@@ -1013,7 +796,7 @@ void WorksheetData::extendShapeBoundingBox( const Rectangle& rShapeRect )
}
}
-void WorksheetData::setBaseColumnWidth( sal_Int32 nWidth )
+void WorksheetGlobals::setBaseColumnWidth( sal_Int32 nWidth )
{
// do not modify width, if setDefaultColumnWidth() has been used
if( !mbHasDefWidth && (nWidth > 0) )
@@ -1025,7 +808,7 @@ void WorksheetData::setBaseColumnWidth( sal_Int32 nWidth )
}
}
-void WorksheetData::setDefaultColumnWidth( double fWidth )
+void WorksheetGlobals::setDefaultColumnWidth( double fWidth )
{
// overrides a width set with setBaseColumnWidth()
if( fWidth > 0.0 )
@@ -1035,22 +818,65 @@ void WorksheetData::setDefaultColumnWidth( double fWidth )
}
}
-void WorksheetData::setColumnModel( const ColumnModel& rModel )
+void WorksheetGlobals::setColumnModel( const ColumnModel& rModel )
{
// convert 1-based OOXML column indexes to 0-based API column indexes
- sal_Int32 nFirstCol = rModel.mnFirstCol - 1;
- sal_Int32 nLastCol = rModel.mnLastCol - 1;
- if( (0 <= nFirstCol) && (nFirstCol <= mrMaxApiPos.Column) )
+ sal_Int32 nFirstCol = rModel.maRange.mnFirst - 1;
+ sal_Int32 nLastCol = rModel.maRange.mnLast - 1;
+ if( getAddressConverter().checkCol( nFirstCol, true ) && (nFirstCol <= nLastCol) )
+ {
+ // validate last column index
+ if( !getAddressConverter().checkCol( nLastCol, true ) )
+ nLastCol = mrMaxApiPos.Column;
+ // try to find entry in column model map that is able to merge with the passed model
+ bool bInsertModel = true;
+ if( !maColModels.empty() )
+ {
+ // find first column model range following nFirstCol (nFirstCol < aIt->first), or end of map
+ ColumnModelRangeMap::iterator aIt = maColModels.upper_bound( nFirstCol );
+ OSL_ENSURE( aIt == maColModels.end(), "WorksheetGlobals::setColModel - columns are unsorted" );
+ // if inserting before another column model, get last free column
+ OSL_ENSURE( (aIt == maColModels.end()) || (nLastCol < aIt->first), "WorksheetGlobals::setColModel - multiple models of the same column" );
+ if( aIt != maColModels.end() )
+ nLastCol = ::std::min( nLastCol, aIt->first - 1 );
+ if( aIt != maColModels.begin() )
+ {
+ // go to previous map element (which may be able to merge with the passed model)
+ --aIt;
+ // the usage of upper_bound() above ensures that aIt->first is less than or equal to nFirstCol now
+ sal_Int32& rnLastMapCol = aIt->second.second;
+ OSL_ENSURE( rnLastMapCol < nFirstCol, "WorksheetGlobals::setColModel - multiple models of the same column" );
+ nFirstCol = ::std::max( rnLastMapCol + 1, nFirstCol );
+ if( (rnLastMapCol + 1 == nFirstCol) && (nFirstCol <= nLastCol) && aIt->second.first.isMergeable( rModel ) )
+ {
+ // can merge with existing model, update last column index
+ rnLastMapCol = nLastCol;
+ bInsertModel = false;
+ }
+ }
+ }
+ if( nFirstCol <= nLastCol )
+ {
+ // insert the column model, if it has not been merged with another
+ if( bInsertModel )
+ maColModels[ nFirstCol ] = ColumnModelRange( rModel, nLastCol );
+ // set column formatting directly
+ convertColumnFormat( nFirstCol, nLastCol, rModel.mnXfId );
+ }
+ }
+}
+
+void WorksheetGlobals::convertColumnFormat( sal_Int32 nFirstCol, sal_Int32 nLastCol, sal_Int32 nXfId ) const
+{
+ CellRangeAddress aRange( getSheetIndex(), nFirstCol, 0, nLastCol, mrMaxApiPos.Row );
+ if( getAddressConverter().validateCellRange( aRange, true, false ) )
{
- // set column formatting directly, nLastCol is checked inside the function
- convertColumnFormat( nFirstCol, nLastCol, rModel.mnXfId );
- // expand last entry or add new entry
- if( maColModels.empty() || !maColModels.rbegin()->second.tryExpand( rModel ) )
- maColModels[ nFirstCol ] = rModel;
+ PropertySet aPropSet( getCellRange( aRange ) );
+ getStyles().writeCellXfToPropertySet( aPropSet, nXfId );
}
}
-void WorksheetData::setDefaultRowSettings( double fHeight, bool bCustomHeight, bool bHidden, bool bThickTop, bool bThickBottom )
+void WorksheetGlobals::setDefaultRowSettings( double fHeight, bool bCustomHeight, bool bHidden, bool bThickTop, bool bThickBottom )
{
maDefRowModel.mfHeight = fHeight;
maDefRowModel.mbCustomHeight = bCustomHeight;
@@ -1059,83 +885,79 @@ void WorksheetData::setDefaultRowSettings( double fHeight, bool bCustomHeight, b
maDefRowModel.mbThickBottom = bThickBottom;
}
-void WorksheetData::setRowModel( const RowModel& rModel )
+void WorksheetGlobals::setRowModel( const RowModel& rModel )
{
- // convert 1-based OOXML row indexes to 0-based API row indexes
- sal_Int32 nFirstRow = rModel.mnFirstRow - 1;
- sal_Int32 nLastRow = rModel.mnLastRow - 1;
- if( (0 <= nFirstRow) && (nFirstRow <= mrMaxApiPos.Row) )
+ // convert 1-based OOXML row index to 0-based API row index
+ sal_Int32 nRow = rModel.mnRow - 1;
+ if( getAddressConverter().checkRow( nRow, true ) )
{
- // set row formatting
- if( rModel.mbCustomFormat )
+ // try to find entry in row model map that is able to merge with the passed model
+ bool bInsertModel = true;
+ bool bUnusedRow = true;
+ if( !maRowModels.empty() )
{
- // try to expand cached row range, if formatting is equal
- if( (maXfIdRowRange.mnLastRow < 0) || !maXfIdRowRange.tryExpand( nFirstRow, nLastRow, rModel.mnXfId ) )
+ // find first row model range following nRow (nRow < aIt->first), or end of map
+ RowModelRangeMap::iterator aIt = maRowModels.upper_bound( nRow );
+ OSL_ENSURE( aIt == maRowModels.end(), "WorksheetGlobals::setRowModel - rows are unsorted" );
+ if( aIt != maRowModels.begin() )
{
- writeXfIdRowRangeProperties( maXfIdRowRange );
- maXfIdRowRange.set( nFirstRow, nLastRow, rModel.mnXfId );
+ // go to previous map element (which may be able to merge with the passed model)
+ --aIt;
+ // the usage of upper_bound() above ensures that aIt->first is less than or equal to nRow now
+ sal_Int32& rnLastMapRow = aIt->second.second;
+ bUnusedRow = rnLastMapRow < nRow;
+ OSL_ENSURE( bUnusedRow, "WorksheetGlobals::setRowModel - multiple models of the same row" );
+ if( (rnLastMapRow + 1 == nRow) && aIt->second.first.isMergeable( rModel ) )
+ {
+ // can merge with existing model, update last row index
+ ++rnLastMapRow;
+ bInsertModel = false;
+ }
}
}
- else if( maXfIdRowRange.mnLastRow >= 0 )
+ if( bUnusedRow )
{
- // finish last cached row range
- writeXfIdRowRangeProperties( maXfIdRowRange );
- maXfIdRowRange.set( -1, -1, -1 );
+ // insert the row model, if it has not been merged with another
+ if( bInsertModel )
+ maRowModels[ nRow ] = RowModelRange( rModel, nRow );
+ // set row formatting
+ maSheetData.setRowFormat( nRow, rModel.mnXfId, rModel.mbCustomFormat );
+ // set column spans
+ maSheetData.setColSpans( nRow, rModel.maColSpans );
}
-
- // expand last entry or add new entry
- if( maRowModels.empty() || !maRowModels.rbegin()->second.tryExpand( rModel ) )
- maRowModels[ nFirstRow ] = rModel;
- }
- lclUpdateProgressBar( mxRowProgress, maUsedArea, nLastRow );
-}
-
-void WorksheetData::convertColumnFormat( sal_Int32 nFirstCol, sal_Int32 nLastCol, sal_Int32 nXfId ) const
-{
- CellRangeAddress aRange( getSheetIndex(), nFirstCol, 0, nLastCol, mrMaxApiPos.Row );
- if( getAddressConverter().validateCellRange( aRange, true, false ) )
- {
- PropertySet aPropSet( getCellRange( aRange ) );
- getStyles().writeCellXfToPropertySet( aPropSet, nXfId );
}
+ lclUpdateProgressBar( mxRowProgress, maUsedArea, nRow );
}
-void WorksheetData::convertRowFormat( sal_Int32 nFirstRow, sal_Int32 nLastRow, sal_Int32 nXfId ) const
+void WorksheetGlobals::setManualRowHeight( sal_Int32 nRow )
{
- CellRangeAddress aRange( getSheetIndex(), 0, nFirstRow, mrMaxApiPos.Column, nLastRow );
- if( getAddressConverter().validateCellRange( aRange, true, false ) )
- {
- PropertySet aPropSet( getCellRange( aRange ) );
- getStyles().writeCellXfToPropertySet( aPropSet, nXfId );
- }
+ maManualRowHeights.insert( nRow );
}
-void WorksheetData::initializeWorksheetImport()
+void WorksheetGlobals::initializeWorksheetImport()
{
// set default cell style for unused cells
PropertySet aPropSet( mxSheet );
aPropSet.setProperty( PROP_CellStyle, getStyles().getDefaultStyleName() );
- /* Remember current sheet index in global data, needed by some global
+ /* Remember the current sheet index in global data, needed by global
objects, e.g. the chart converter. */
setCurrentSheetIndex( getSheetIndex() );
}
-void WorksheetData::finalizeWorksheetImport()
+void WorksheetGlobals::finalizeWorksheetImport()
{
lclUpdateProgressBar( mxRowProgress, 1.0 );
- finalizeXfIdRanges();
+ maSheetData.finalizeImport();
lclUpdateProgressBar( mxFinalProgress, 0.25 );
finalizeHyperlinkRanges();
finalizeValidationRanges();
- finalizeMergedRanges();
maAutoFilters.finalizeImport( getSheetIndex() );
- maSheetSett.finalizeImport();
maCondFormats.finalizeImport();
maQueryTables.finalizeImport();
+ maSheetSett.finalizeImport();
maPageSett.finalizeImport();
maSheetViewSett.finalizeImport();
- maSheetSett.finalizeImport();
lclUpdateProgressBar( mxFinalProgress, 0.5 );
convertColumns();
@@ -1144,159 +966,13 @@ void WorksheetData::finalizeWorksheetImport()
finalizeDrawings();
lclUpdateProgressBar( mxFinalProgress, 1.0 );
- // reset current sheet index in global data
+ // forget current sheet index in global data
setCurrentSheetIndex( -1 );
}
// private --------------------------------------------------------------------
-WorksheetData::XfIdRowRange::XfIdRowRange() :
- mnFirstRow( -1 ),
- mnLastRow( -1 ),
- mnXfId( -1 )
-{
-}
-
-bool WorksheetData::XfIdRowRange::intersects( const CellRangeAddress& rRange ) const
-{
- return (rRange.StartRow <= mnLastRow) && (mnFirstRow <= rRange.EndRow);
-}
-
-void WorksheetData::XfIdRowRange::set( sal_Int32 nFirstRow, sal_Int32 nLastRow, sal_Int32 nXfId )
-{
- mnFirstRow = nFirstRow;
- mnLastRow = nLastRow;
- mnXfId = nXfId;
-}
-
-bool WorksheetData::XfIdRowRange::tryExpand( sal_Int32 nFirstRow, sal_Int32 nLastRow, sal_Int32 nXfId )
-{
- if( mnXfId == nXfId )
- {
- if( mnLastRow + 1 == nFirstRow )
- {
- mnLastRow = nLastRow;
- return true;
- }
- if( mnFirstRow == nLastRow + 1 )
- {
- mnFirstRow = nFirstRow;
- return true;
- }
- }
- return false;
-}
-
-void WorksheetData::XfIdRange::set( const CellModel& rModel )
-{
- maRange.Sheet = rModel.maAddress.Sheet;
- maRange.StartColumn = maRange.EndColumn = rModel.maAddress.Column;
- maRange.StartRow = maRange.EndRow = rModel.maAddress.Row;
- mnXfId = rModel.mnXfId;
- mnNumFmtId = rModel.mnNumFmtId;
-}
-
-bool WorksheetData::XfIdRange::tryExpand( const CellModel& rModel )
-{
- if( (mnXfId == rModel.mnXfId) && (mnNumFmtId == rModel.mnNumFmtId) &&
- (maRange.StartRow == rModel.maAddress.Row) &&
- (maRange.EndRow == rModel.maAddress.Row) &&
- (maRange.EndColumn + 1 == rModel.maAddress.Column) )
- {
- ++maRange.EndColumn;
- return true;
- }
- return false;
-}
-
-bool WorksheetData::XfIdRange::tryMerge( const XfIdRange& rXfIdRange )
-{
- if( (mnXfId == rXfIdRange.mnXfId) &&
- (mnNumFmtId == rXfIdRange.mnNumFmtId) &&
- (maRange.EndRow + 1 == rXfIdRange.maRange.StartRow) &&
- (maRange.StartColumn == rXfIdRange.maRange.StartColumn) &&
- (maRange.EndColumn == rXfIdRange.maRange.EndColumn) )
- {
- maRange.EndRow = rXfIdRange.maRange.EndRow;
- return true;
- }
- return false;
-}
-
-
-WorksheetData::MergedRange::MergedRange( const CellRangeAddress& rRange ) :
- maRange( rRange ),
- mnHorAlign( XML_TOKEN_INVALID )
-{
-}
-
-WorksheetData::MergedRange::MergedRange( const CellAddress& rAddress, sal_Int32 nHorAlign ) :
- maRange( rAddress.Sheet, rAddress.Column, rAddress.Row, rAddress.Column, rAddress.Row ),
- mnHorAlign( nHorAlign )
-{
-}
-
-bool WorksheetData::MergedRange::tryExpand( const CellAddress& rAddress, sal_Int32 nHorAlign )
-{
- if( (mnHorAlign == nHorAlign) && (maRange.StartRow == rAddress.Row) &&
- (maRange.EndRow == rAddress.Row) && (maRange.EndColumn + 1 == rAddress.Column) )
- {
- ++maRange.EndColumn;
- return true;
- }
- return false;
-}
-
-void WorksheetData::writeXfIdRowRangeProperties( const XfIdRowRange& rXfIdRowRange ) const
-{
- if( (rXfIdRowRange.mnLastRow >= 0) && (rXfIdRowRange.mnXfId >= 0) )
- convertRowFormat( rXfIdRowRange.mnFirstRow, rXfIdRowRange.mnLastRow, rXfIdRowRange.mnXfId );
-}
-
-void WorksheetData::writeXfIdRangeProperties( const XfIdRange& rXfIdRange ) const
-{
- StylesBuffer& rStyles = getStyles();
- PropertyMap aPropMap;
- if( rXfIdRange.mnXfId >= 0 )
- rStyles.writeCellXfToPropertyMap( aPropMap, rXfIdRange.mnXfId );
- if( rXfIdRange.mnNumFmtId >= 0 )
- rStyles.writeNumFmtToPropertyMap( aPropMap, rXfIdRange.mnNumFmtId );
- PropertySet aPropSet( getCellRange( rXfIdRange.maRange ) );
- aPropSet.setProperties( aPropMap );
-}
-
-void WorksheetData::mergeXfIdRanges()
-{
- if( !maXfIdRanges.empty() )
- {
- // get row index of last range
- sal_Int32 nLastRow = maXfIdRanges.rbegin()->second.maRange.StartRow;
- // process all ranges located in the same row of the last range
- XfIdRangeMap::iterator aMergeIt = maXfIdRanges.end();
- while( (aMergeIt != maXfIdRanges.begin()) && ((--aMergeIt)->second.maRange.StartRow == nLastRow) )
- {
- const XfIdRange& rMergeXfIdRange = aMergeIt->second;
- // try to find a range that can be merged with rMergeRange
- bool bFound = false;
- for( XfIdRangeMap::iterator aIt = maXfIdRanges.begin(); !bFound && (aIt != aMergeIt); ++aIt )
- if( (bFound = aIt->second.tryMerge( rMergeXfIdRange )) == true )
- maXfIdRanges.erase( aMergeIt++ );
- }
- }
-}
-
-void WorksheetData::finalizeXfIdRanges()
-{
- // write default formatting of remaining row range
- writeXfIdRowRangeProperties( maXfIdRowRange );
- // try to merge remaining inserted ranges
- mergeXfIdRanges();
- // write all formatting
- for( XfIdRangeMap::const_iterator aIt = maXfIdRanges.begin(), aEnd = maXfIdRanges.end(); aIt != aEnd; ++aIt )
- writeXfIdRangeProperties( aIt->second );
-}
-
-void WorksheetData::finalizeHyperlinkRanges() const
+void WorksheetGlobals::finalizeHyperlinkRanges() const
{
for( HyperlinkModelList::const_iterator aIt = maHyperlinks.begin(), aEnd = maHyperlinks.end(); aIt != aEnd; ++aIt )
{
@@ -1309,7 +985,7 @@ void WorksheetData::finalizeHyperlinkRanges() const
}
}
-OUString WorksheetData::getHyperlinkUrl( const HyperlinkModel& rHyperlink ) const
+OUString WorksheetGlobals::getHyperlinkUrl( const HyperlinkModel& rHyperlink ) const
{
OUStringBuffer aUrlBuffer;
if( rHyperlink.maTarget.getLength() > 0 )
@@ -1337,20 +1013,20 @@ OUString WorksheetData::getHyperlinkUrl( const HyperlinkModel& rHyperlink ) cons
return aUrl;
}
-void WorksheetData::insertHyperlink( const CellAddress& rAddress, const OUString& rUrl ) const
+void WorksheetGlobals::insertHyperlink( const CellAddress& rAddress, const OUString& rUrl ) const
{
Reference< XCell > xCell = getCell( rAddress );
if( xCell.is() ) switch( xCell->getType() )
{
// #i54261# restrict creation of URL field to text cells
- case ::com::sun::star::table::CellContentType_TEXT:
+ case CellContentType_TEXT:
{
Reference< XText > xText( xCell, UNO_QUERY );
if( xText.is() )
{
// create a URL field object and set its properties
- Reference< XTextContent > xUrlField( getDocumentFactory()->createInstance( maUrlTextField ), UNO_QUERY );
- OSL_ENSURE( xUrlField.is(), "WorksheetData::insertHyperlink - cannot create text field" );
+ Reference< XTextContent > xUrlField( getBaseFilter().getModelFactory()->createInstance( maUrlTextField ), UNO_QUERY );
+ OSL_ENSURE( xUrlField.is(), "WorksheetGlobals::insertHyperlink - cannot create text field" );
if( xUrlField.is() )
{
// properties of the URL field
@@ -1376,15 +1052,13 @@ void WorksheetData::insertHyperlink( const CellAddress& rAddress, const OUString
// fix for #i31050# disabled, HYPERLINK is not able to return numeric value (#i91351#)
#if 0
// #i31050# replace number with HYPERLINK function
- case ::com::sun::star::table::CellContentType_VALUE:
+ case CellContentType_VALUE:
{
Reference< XFormulaTokens > xTokens( xCell, UNO_QUERY );
- OSL_ENSURE( xTokens.is(), "WorksheetHelper::insertHyperlink - missing formula interface" );
- if( xTokens.is() )
- {
- SimpleFormulaContext aContext( xTokens, false, false );
- getFormulaParser().convertNumberToHyperlink( aContext, rUrl, xCell->getValue() );
- }
+ ApiTokenSequence aTokens = getFormulaParser().convertNumberToHyperlink( rUrl, xCell->getValue() );
+ OSL_ENSURE( xTokens.is(), "WorksheetHelper::insertHyperlink - missing formula token interface" );
+ if( xTokens.is() && aTokens.hasElements() )
+ xTokens->setTokens( aTokens );
}
break;
#endif
@@ -1393,7 +1067,7 @@ void WorksheetData::insertHyperlink( const CellAddress& rAddress, const OUString
}
}
-void WorksheetData::finalizeValidationRanges() const
+void WorksheetGlobals::finalizeValidationRanges() const
{
for( ValidationModelList::const_iterator aIt = maValidations.begin(), aEnd = maValidations.end(); aIt != aEnd; ++aIt )
{
@@ -1403,37 +1077,36 @@ void WorksheetData::finalizeValidationRanges() const
if( xValidation.is() )
{
PropertySet aValProps( xValidation );
- namespace csss = ::com::sun::star::sheet;
// convert validation type to API enum
- ValidationType eType = csss::ValidationType_ANY;
+ ValidationType eType = ValidationType_ANY;
switch( aIt->mnType )
{
- case XML_custom: eType = csss::ValidationType_CUSTOM; break;
- case XML_date: eType = csss::ValidationType_DATE; break;
- case XML_decimal: eType = csss::ValidationType_DECIMAL; break;
- case XML_list: eType = csss::ValidationType_LIST; break;
- case XML_none: eType = csss::ValidationType_ANY; break;
- case XML_textLength: eType = csss::ValidationType_TEXT_LEN; break;
- case XML_time: eType = csss::ValidationType_TIME; break;
- case XML_whole: eType = csss::ValidationType_WHOLE; break;
+ case XML_custom: eType = ValidationType_CUSTOM; break;
+ case XML_date: eType = ValidationType_DATE; break;
+ case XML_decimal: eType = ValidationType_DECIMAL; break;
+ case XML_list: eType = ValidationType_LIST; break;
+ case XML_none: eType = ValidationType_ANY; break;
+ case XML_textLength: eType = ValidationType_TEXT_LEN; break;
+ case XML_time: eType = ValidationType_TIME; break;
+ case XML_whole: eType = ValidationType_WHOLE; break;
default: OSL_FAIL( "WorksheetData::finalizeValidationRanges - unknown validation type" );
}
aValProps.setProperty( PROP_Type, eType );
// convert error alert style to API enum
- ValidationAlertStyle eAlertStyle = csss::ValidationAlertStyle_STOP;
+ ValidationAlertStyle eAlertStyle = ValidationAlertStyle_STOP;
switch( aIt->mnErrorStyle )
{
- case XML_information: eAlertStyle = csss::ValidationAlertStyle_INFO; break;
- case XML_stop: eAlertStyle = csss::ValidationAlertStyle_STOP; break;
- case XML_warning: eAlertStyle = csss::ValidationAlertStyle_WARNING; break;
+ case XML_information: eAlertStyle = ValidationAlertStyle_INFO; break;
+ case XML_stop: eAlertStyle = ValidationAlertStyle_STOP; break;
+ case XML_warning: eAlertStyle = ValidationAlertStyle_WARNING; break;
default: OSL_FAIL( "WorksheetData::finalizeValidationRanges - unknown error style" );
}
aValProps.setProperty( PROP_ErrorAlertStyle, eAlertStyle );
// convert dropdown style to API visibility constants
- sal_Int16 nVisibility = aIt->mbNoDropDown ? csss::TableValidationVisibility::INVISIBLE : csss::TableValidationVisibility::UNSORTED;
+ sal_Int16 nVisibility = aIt->mbNoDropDown ? TableValidationVisibility::INVISIBLE : TableValidationVisibility::UNSORTED;
aValProps.setProperty( PROP_ShowList, nVisibility );
// messages
@@ -1468,99 +1141,36 @@ void WorksheetData::finalizeValidationRanges() const
}
}
-void WorksheetData::finalizeMergedRanges()
-{
- MergedRangeList::const_iterator aIt, aEnd;
- for( aIt = maMergedRanges.begin(), aEnd = maMergedRanges.end(); aIt != aEnd; ++aIt )
- finalizeMergedRange( aIt->maRange );
- for( aIt = maCenterFillRanges.begin(), aEnd = maCenterFillRanges.end(); aIt != aEnd; ++aIt )
- finalizeMergedRange( aIt->maRange );
-}
-
-void WorksheetData::finalizeMergedRange( const CellRangeAddress& rRange )
-{
- bool bMultiCol = rRange.StartColumn < rRange.EndColumn;
- bool bMultiRow = rRange.StartRow < rRange.EndRow;
-
- if( bMultiCol || bMultiRow ) try
- {
- // merge the cell range
- Reference< XMergeable > xMerge( getCellRange( rRange ), UNO_QUERY_THROW );
- xMerge->merge( sal_True );
-
- // if merging this range worked (no overlapping merged ranges), update cell borders
- Reference< XCell > xTopLeft( getCell( CellAddress( getSheetIndex(), rRange.StartColumn, rRange.StartRow ) ), UNO_SET_THROW );
- PropertySet aTopLeftProp( xTopLeft );
-
- // copy right border of top-right cell to right border of top-left cell
- if( bMultiCol )
- {
- PropertySet aTopRightProp( getCell( CellAddress( getSheetIndex(), rRange.EndColumn, rRange.StartRow ) ) );
- BorderLine aLine;
- if( aTopRightProp.getProperty( aLine, PROP_RightBorder ) )
- aTopLeftProp.setProperty( PROP_RightBorder, aLine );
- }
-
- // copy bottom border of bottom-left cell to bottom border of top-left cell
- if( bMultiRow )
- {
- PropertySet aBottomLeftProp( getCell( CellAddress( getSheetIndex(), rRange.StartColumn, rRange.EndRow ) ) );
- BorderLine aLine;
- if( aBottomLeftProp.getProperty( aLine, PROP_BottomBorder ) )
- aTopLeftProp.setProperty( PROP_BottomBorder, aLine );
- }
-
- // #i93609# merged range in a single row: test if manual row height is needed
- if( !bMultiRow )
- {
- bool bTextWrap = aTopLeftProp.getBoolProperty( PROP_IsTextWrapped );
- if( !bTextWrap && (xTopLeft->getType() == ::com::sun::star::table::CellContentType_TEXT) )
- {
- Reference< XText > xText( xTopLeft, UNO_QUERY );
- bTextWrap = xText.is() && (xText->getString().indexOf( '\x0A' ) >= 0);
- }
- if( bTextWrap )
- maManualRowHeights.insert( rRange.StartRow );
- }
- }
- catch( Exception& )
- {
- }
-}
-
-void WorksheetData::convertColumns()
+void WorksheetGlobals::convertColumns()
{
sal_Int32 nNextCol = 0;
sal_Int32 nMaxCol = mrMaxApiPos.Column;
// stores first grouped column index for each level
OutlineLevelVec aColLevels;
- for( ColumnModelMap::const_iterator aIt = maColModels.begin(), aEnd = maColModels.end(); aIt != aEnd; ++aIt )
+ for( ColumnModelRangeMap::iterator aIt = maColModels.begin(), aEnd = maColModels.end(); aIt != aEnd; ++aIt )
{
- // convert 1-based OOXML column indexes to 0-based API column indexes
- sal_Int32 nFirstCol = ::std::max( aIt->second.mnFirstCol - 1, nNextCol );
- sal_Int32 nLastCol = ::std::min( aIt->second.mnLastCol - 1, nMaxCol );
-
+ // column indexes are stored 0-based in maColModels
+ ValueRange aColRange( ::std::max( aIt->first, nNextCol ), ::std::min( aIt->second.second, nMaxCol ) );
// process gap between two column models, use default column model
- if( nNextCol < nFirstCol )
- convertColumns( aColLevels, nNextCol, nFirstCol - 1, maDefColModel );
+ if( nNextCol < aColRange.mnFirst )
+ convertColumns( aColLevels, ValueRange( nNextCol, aColRange.mnFirst - 1 ), maDefColModel );
// process the column model
- convertColumns( aColLevels, nFirstCol, nLastCol, aIt->second );
-
+ convertColumns( aColLevels, aColRange, aIt->second.first );
// cache next column to be processed
- nNextCol = nLastCol + 1;
+ nNextCol = aColRange.mnLast + 1;
}
// remaining default columns to end of sheet
- convertColumns( aColLevels, nNextCol, nMaxCol, maDefColModel );
+ convertColumns( aColLevels, ValueRange( nNextCol, nMaxCol ), maDefColModel );
// close remaining column outlines spanning to end of sheet
convertOutlines( aColLevels, nMaxCol + 1, 0, false, false );
}
-void WorksheetData::convertColumns( OutlineLevelVec& orColLevels,
- sal_Int32 nFirstCol, sal_Int32 nLastCol, const ColumnModel& rModel )
+void WorksheetGlobals::convertColumns( OutlineLevelVec& orColLevels,
+ const ValueRange& rColRange, const ColumnModel& rModel )
{
- PropertySet aPropSet( getColumns( nFirstCol, nLastCol ) );
+ PropertySet aPropSet( getColumns( rColRange ) );
// column width: convert 'number of characters' to column width in 1/100 mm
sal_Int32 nWidth = getUnitConverter().scaleToMm100( rModel.mfWidth, UNIT_DIGIT );
@@ -1575,54 +1185,55 @@ void WorksheetData::convertColumns( OutlineLevelVec& orColLevels,
aPropSet.setProperty( PROP_IsVisible, false );
// outline settings for this column range
- convertOutlines( orColLevels, nFirstCol, rModel.mnLevel, rModel.mbCollapsed, false );
+ convertOutlines( orColLevels, rColRange.mnFirst, rModel.mnLevel, rModel.mbCollapsed, false );
}
-void WorksheetData::convertRows()
+void WorksheetGlobals::convertRows()
{
sal_Int32 nNextRow = 0;
sal_Int32 nMaxRow = mrMaxApiPos.Row;
// stores first grouped row index for each level
OutlineLevelVec aRowLevels;
- for( RowModelMap::const_iterator aIt = maRowModels.begin(), aEnd = maRowModels.end(); aIt != aEnd; ++aIt )
+ for( RowModelRangeMap::iterator aIt = maRowModels.begin(), aEnd = maRowModels.end(); aIt != aEnd; ++aIt )
{
- // convert 1-based OOXML row indexes to 0-based API row indexes
- sal_Int32 nFirstRow = ::std::max( aIt->second.mnFirstRow - 1, nNextRow );
- sal_Int32 nLastRow = ::std::min( aIt->second.mnLastRow - 1, nMaxRow );
-
+ // row indexes are stored 0-based in maRowModels
+ ValueRange aRowRange( ::std::max( aIt->first, nNextRow ), ::std::min( aIt->second.second, nMaxRow ) );
// process gap between two row models, use default row model
- if( nNextRow < nFirstRow )
- convertRows( aRowLevels, nNextRow, nFirstRow - 1, maDefRowModel );
+ if( nNextRow < aRowRange.mnFirst )
+ convertRows( aRowLevels, ValueRange( nNextRow, aRowRange.mnFirst - 1 ), maDefRowModel );
// process the row model
- convertRows( aRowLevels, nFirstRow, nLastRow, aIt->second, maDefRowModel.mfHeight );
-
+ convertRows( aRowLevels, aRowRange, aIt->second.first, maDefRowModel.mfHeight );
// cache next row to be processed
- nNextRow = nLastRow + 1;
+ nNextRow = aRowRange.mnLast + 1;
}
// remaining default rows to end of sheet
- convertRows( aRowLevels, nNextRow, nMaxRow, maDefRowModel );
+ convertRows( aRowLevels, ValueRange( nNextRow, nMaxRow ), maDefRowModel );
// close remaining row outlines spanning to end of sheet
convertOutlines( aRowLevels, nMaxRow + 1, 0, false, true );
}
-void WorksheetData::convertRows( OutlineLevelVec& orRowLevels,
- sal_Int32 nFirstRow, sal_Int32 nLastRow, const RowModel& rModel, double fDefHeight )
+void WorksheetGlobals::convertRows( OutlineLevelVec& orRowLevels,
+ const ValueRange& rRowRange, const RowModel& rModel, double fDefHeight )
{
// row height: convert points to row height in 1/100 mm
double fHeight = (rModel.mfHeight >= 0.0) ? rModel.mfHeight : fDefHeight;
sal_Int32 nHeight = getUnitConverter().scaleToMm100( fHeight, UNIT_POINT );
if( nHeight > 0 )
{
+ /* Get all rows that have custom height inside the passed row model.
+ If the model has the custom height flag set, all its rows have
+ custom height, otherwise get all rows specified in the class member
+ maManualRowHeights that are inside the passed row model. */
ValueRangeVector aManualRows;
if( rModel.mbCustomHeight )
- aManualRows.push_back( ValueRange( nFirstRow, nLastRow ) );
+ aManualRows.push_back( rRowRange );
else
- maManualRowHeights.intersect( aManualRows, nFirstRow, nLastRow );
+ aManualRows = maManualRowHeights.getIntersection( rRowRange );
for( ValueRangeVector::const_iterator aIt = aManualRows.begin(), aEnd = aManualRows.end(); aIt != aEnd; ++aIt )
{
- PropertySet aPropSet( getRows( aIt->mnFirst, aIt->mnLast ) );
+ PropertySet aPropSet( getRows( *aIt ) );
aPropSet.setProperty( PROP_Height, nHeight );
}
}
@@ -1630,21 +1241,21 @@ void WorksheetData::convertRows( OutlineLevelVec& orRowLevels,
// hidden rows: TODO: #108683# hide rows later?
if( rModel.mbHidden )
{
- PropertySet aPropSet( getRows( nFirstRow, nLastRow ) );
+ PropertySet aPropSet( getRows( rRowRange ) );
aPropSet.setProperty( PROP_IsVisible, false );
}
// outline settings for this row range
- convertOutlines( orRowLevels, nFirstRow, rModel.mnLevel, rModel.mbCollapsed, true );
+ convertOutlines( orRowLevels, rRowRange.mnFirst, rModel.mnLevel, rModel.mbCollapsed, true );
}
-void WorksheetData::convertOutlines( OutlineLevelVec& orLevels,
+void WorksheetGlobals::convertOutlines( OutlineLevelVec& orLevels,
sal_Int32 nColRow, sal_Int32 nLevel, bool bCollapsed, bool bRows )
{
/* It is ensured from caller functions, that this function is called
without any gaps between the processed column or row ranges. */
- OSL_ENSURE( nLevel >= 0, "WorksheetData::convertOutlines - negative outline level" );
+ OSL_ENSURE( nLevel >= 0, "WorksheetGlobals::convertOutlines - negative outline level" );
nLevel = ::std::max< sal_Int32 >( nLevel, 0 );
sal_Int32 nSize = orLevels.size();
@@ -1667,7 +1278,7 @@ void WorksheetData::convertOutlines( OutlineLevelVec& orLevels,
}
}
-void WorksheetData::groupColumnsOrRows( sal_Int32 nFirstColRow, sal_Int32 nLastColRow, bool bCollapse, bool bRows )
+void WorksheetGlobals::groupColumnsOrRows( sal_Int32 nFirstColRow, sal_Int32 nLastColRow, bool bCollapse, bool bRows )
{
try
{
@@ -1675,14 +1286,14 @@ void WorksheetData::groupColumnsOrRows( sal_Int32 nFirstColRow, sal_Int32 nLastC
if( bRows )
{
CellRangeAddress aRange( getSheetIndex(), 0, nFirstColRow, 0, nLastColRow );
- xOutline->group( aRange, ::com::sun::star::table::TableOrientation_ROWS );
+ xOutline->group( aRange, TableOrientation_ROWS );
if( bCollapse )
xOutline->hideDetail( aRange );
}
else
{
CellRangeAddress aRange( getSheetIndex(), nFirstColRow, 0, nLastColRow, 0 );
- xOutline->group( aRange, ::com::sun::star::table::TableOrientation_COLUMNS );
+ xOutline->group( aRange, TableOrientation_COLUMNS );
if( bCollapse )
xOutline->hideDetail( aRange );
}
@@ -1692,8 +1303,12 @@ void WorksheetData::groupColumnsOrRows( sal_Int32 nFirstColRow, sal_Int32 nLastC
}
}
-void WorksheetData::finalizeDrawings()
+void WorksheetGlobals::finalizeDrawings()
{
+ // calculate the current drawing page size (after rows/columns are imported)
+ PropertySet aRangeProp( getCellRange( CellRangeAddress( getSheetIndex(), 0, 0, mrMaxApiPos.Column, mrMaxApiPos.Row ) ) );
+ aRangeProp.getProperty( maDrawPageSize, PROP_Size );
+
switch( getFilterType() )
{
case FILTER_OOXML:
@@ -1705,7 +1320,8 @@ void WorksheetData::finalizeDrawings()
break;
case FILTER_BIFF:
- // TODO: import DFF shapes
+ // convert BIFF3-BIFF5 drawing objects, or import and convert DFF stream
+ getBiffDrawing().finalizeImport();
break;
case FILTER_UNKNOWN:
@@ -1737,109 +1353,56 @@ void WorksheetData::finalizeDrawings()
if( maSheetViewSett.isSheetRightToLeft() )
{
PropertySet aPropSet( mxSheet );
- aPropSet.setProperty( PROP_TableLayout, ::com::sun::star::text::WritingMode2::RL_TB );
+ aPropSet.setProperty( PROP_TableLayout, WritingMode2::RL_TB );
}
}
// ============================================================================
// ============================================================================
-WorksheetHelper::WorksheetHelper( WorksheetData& rSheetData ) :
- WorkbookHelper( rSheetData ),
- mrSheetData( rSheetData )
+WorksheetHelper::WorksheetHelper( WorksheetGlobals& rSheetGlob ) :
+ WorkbookHelper( rSheetGlob ),
+ mrSheetGlob( rSheetGlob )
{
}
+/*static*/ WorksheetGlobalsRef WorksheetHelper::constructGlobals( const WorkbookHelper& rHelper,
+ const ISegmentProgressBarRef& rxProgressBar, WorksheetType eSheetType, sal_Int16 nSheet )
+{
+ WorksheetGlobalsRef xSheetGlob( new WorksheetGlobals( rHelper, rxProgressBar, eSheetType, nSheet ) );
+ if( !xSheetGlob->isValidSheet() )
+ xSheetGlob.reset();
+ return xSheetGlob;
+}
+
WorksheetType WorksheetHelper::getSheetType() const
{
- return mrSheetData.getSheetType();
+ return mrSheetGlob.getSheetType();
}
sal_Int16 WorksheetHelper::getSheetIndex() const
{
- return mrSheetData.getSheetIndex();
+ return mrSheetGlob.getSheetIndex();
}
const Reference< XSpreadsheet >& WorksheetHelper::getSheet() const
{
- return mrSheetData.getSheet();
+ return mrSheetGlob.getSheet();
}
Reference< XCell > WorksheetHelper::getCell( const CellAddress& rAddress ) const
{
- return mrSheetData.getCell( rAddress );
-}
-
-Reference< XCell > WorksheetHelper::getCell( const OUString& rAddressStr, CellAddress* opAddress ) const
-{
- CellAddress aAddress;
- if( getAddressConverter().convertToCellAddress( aAddress, rAddressStr, mrSheetData.getSheetIndex(), true ) )
- {
- if( opAddress ) *opAddress = aAddress;
- return mrSheetData.getCell( aAddress );
- }
- return Reference< XCell >();
-}
-
-Reference< XCell > WorksheetHelper::getCell( const BinAddress& rBinAddress, CellAddress* opAddress ) const
-{
- CellAddress aAddress;
- if( getAddressConverter().convertToCellAddress( aAddress, rBinAddress, mrSheetData.getSheetIndex(), true ) )
- {
- if( opAddress ) *opAddress = aAddress;
- return mrSheetData.getCell( aAddress );
- }
- return Reference< XCell >();
+ return mrSheetGlob.getCell( rAddress );
}
Reference< XCellRange > WorksheetHelper::getCellRange( const CellRangeAddress& rRange ) const
{
- return mrSheetData.getCellRange( rRange );
-}
-
-Reference< XCellRange > WorksheetHelper::getCellRange( const OUString& rRangeStr, CellRangeAddress* opRange ) const
-{
- CellRangeAddress aRange;
- if( getAddressConverter().convertToCellRange( aRange, rRangeStr, mrSheetData.getSheetIndex(), true, true ) )
- {
- if( opRange ) *opRange = aRange;
- return mrSheetData.getCellRange( aRange );
- }
- return Reference< XCellRange >();
-}
-
-Reference< XCellRange > WorksheetHelper::getCellRange( const BinRange& rBinRange, CellRangeAddress* opRange ) const
-{
- CellRangeAddress aRange;
- if( getAddressConverter().convertToCellRange( aRange, rBinRange, mrSheetData.getSheetIndex(), true, true ) )
- {
- if( opRange ) *opRange = aRange;
- return mrSheetData.getCellRange( aRange );
- }
- return Reference< XCellRange >();
+ return mrSheetGlob.getCellRange( rRange );
}
Reference< XSheetCellRanges > WorksheetHelper::getCellRangeList( const ApiCellRangeList& rRanges ) const
{
- return mrSheetData.getCellRangeList( rRanges );
-}
-
-Reference< XSheetCellRanges > WorksheetHelper::getCellRangeList(
- const OUString& rRangesStr, ApiCellRangeList* opRanges ) const
-{
- ApiCellRangeList aRanges;
- getAddressConverter().convertToCellRangeList( aRanges, rRangesStr, mrSheetData.getSheetIndex(), true );
- if( opRanges ) *opRanges = aRanges;
- return mrSheetData.getCellRangeList( aRanges );
-}
-
-Reference< XSheetCellRanges > WorksheetHelper::getCellRangeList(
- const BinRangeList& rBinRanges, ApiCellRangeList* opRanges ) const
-{
- ApiCellRangeList aRanges;
- getAddressConverter().convertToCellRangeList( aRanges, rBinRanges, mrSheetData.getSheetIndex(), true );
- if( opRanges ) *opRanges = aRanges;
- return mrSheetData.getCellRangeList( aRanges );
+ return mrSheetGlob.getCellRangeList( rRanges );
}
CellAddress WorksheetHelper::getCellAddress( const Reference< XCell >& rxCell )
@@ -1864,267 +1427,112 @@ CellRangeAddress WorksheetHelper::getRangeAddress( const Reference< XCellRange >
Reference< XCellRange > WorksheetHelper::getColumn( sal_Int32 nCol ) const
{
- return mrSheetData.getColumn( nCol );
+ return mrSheetGlob.getColumn( nCol );
}
Reference< XCellRange > WorksheetHelper::getRow( sal_Int32 nRow ) const
{
- return mrSheetData.getRow( nRow );
+ return mrSheetGlob.getRow( nRow );
}
-Reference< XTableColumns > WorksheetHelper::getColumns( sal_Int32 nFirstCol, sal_Int32 nLastCol ) const
+Reference< XTableColumns > WorksheetHelper::getColumns( const ValueRange& rColRange ) const
{
- return mrSheetData.getColumns( nFirstCol, nLastCol );
+ return mrSheetGlob.getColumns( rColRange );
}
-Reference< XTableRows > WorksheetHelper::getRows( sal_Int32 nFirstRow, sal_Int32 nLastRow ) const
+Reference< XTableRows > WorksheetHelper::getRows( const ValueRange& rRowRange ) const
{
- return mrSheetData.getRows( nFirstRow, nLastRow );
+ return mrSheetGlob.getRows( rRowRange );
}
Reference< XDrawPage > WorksheetHelper::getDrawPage() const
{
- return mrSheetData.getDrawPage();
+ return mrSheetGlob.getDrawPage();
}
Point WorksheetHelper::getCellPosition( sal_Int32 nCol, sal_Int32 nRow ) const
{
- return mrSheetData.getCellPosition( nCol, nRow );
+ return mrSheetGlob.getCellPosition( nCol, nRow );
}
Size WorksheetHelper::getCellSize( sal_Int32 nCol, sal_Int32 nRow ) const
{
- return mrSheetData.getCellSize( nCol, nRow );
+ return mrSheetGlob.getCellSize( nCol, nRow );
}
Size WorksheetHelper::getDrawPageSize() const
{
- return mrSheetData.getDrawPageSize();
+ return mrSheetGlob.getDrawPageSize();
}
-WorksheetSettings& WorksheetHelper::getWorksheetSettings() const
-{
- return mrSheetData.getWorksheetSettings();
-}
-
-SharedFormulaBuffer& WorksheetHelper::getSharedFormulas() const
+SheetDataBuffer& WorksheetHelper::getSheetData() const
{
- return mrSheetData.getSharedFormulas();
+ return mrSheetGlob.getSheetData();
}
CondFormatBuffer& WorksheetHelper::getCondFormats() const
{
- return mrSheetData.getCondFormats();
+ return mrSheetGlob.getCondFormats();
}
CommentsBuffer& WorksheetHelper::getComments() const
{
- return mrSheetData.getComments();
+ return mrSheetGlob.getComments();
}
AutoFilterBuffer& WorksheetHelper::getAutoFilters() const
{
- return mrSheetData.getAutoFilters();
+ return mrSheetGlob.getAutoFilters();
}
QueryTableBuffer& WorksheetHelper::getQueryTables() const
{
- return mrSheetData.getQueryTables();
+ return mrSheetGlob.getQueryTables();
}
-PageSettings& WorksheetHelper::getPageSettings() const
-{
- return mrSheetData.getPageSettings();
-}
-
-SheetViewSettings& WorksheetHelper::getSheetViewSettings() const
-{
- return mrSheetData.getSheetViewSettings();
-}
-
-VmlDrawing& WorksheetHelper::getVmlDrawing() const
-{
- return mrSheetData.getVmlDrawing();
-}
-
-void WorksheetHelper::setStringCell( const Reference< XCell >& rxCell, const OUString& rText ) const
-{
- OSL_ENSURE( rxCell.is(), "WorksheetHelper::setStringCell - missing cell interface" );
- Reference< XText > xText( rxCell, UNO_QUERY );
- if( xText.is() )
- xText->setString( rText );
-}
-
-void WorksheetHelper::setSharedStringCell( const Reference< XCell >& rxCell, sal_Int32 nStringId, sal_Int32 nXfId ) const
-{
- OSL_ENSURE( rxCell.is(), "WorksheetHelper::setSharedStringCell - missing cell interface" );
- getSharedStrings().convertString( Reference< XText >( rxCell, UNO_QUERY ), nStringId, nXfId );
-}
-
-void WorksheetHelper::setDateTimeCell( const Reference< XCell >& rxCell, const DateTime& rDateTime ) const
-{
- OSL_ENSURE( rxCell.is(), "WorksheetHelper::setDateTimeCell - missing cell interface" );
- // write serial date/time value into the cell
- double fSerial = getUnitConverter().calcSerialFromDateTime( rDateTime );
- rxCell->setValue( fSerial );
- // set appropriate number format
- using namespace ::com::sun::star::util::NumberFormat;
- sal_Int16 nStdFmt = (fSerial < 1.0) ? TIME : (((rDateTime.Hours > 0) || (rDateTime.Minutes > 0) || (rDateTime.Seconds > 0)) ? DATETIME : DATE);
- setStandardNumFmt( rxCell, nStdFmt );
-}
-
-void WorksheetHelper::setBooleanCell( const Reference< XCell >& rxCell, bool bValue ) const
+WorksheetSettings& WorksheetHelper::getWorksheetSettings() const
{
- OSL_ENSURE( rxCell.is(), "WorksheetHelper::setBooleanCell - missing cell interface" );
- rxCell->setFormula( mrSheetData.getBooleanFormula( bValue ) );
+ return mrSheetGlob.getWorksheetSettings();
}
-void WorksheetHelper::setErrorCell( const Reference< XCell >& rxCell, const OUString& rErrorCode ) const
+PageSettings& WorksheetHelper::getPageSettings() const
{
- setErrorCell( rxCell, getUnitConverter().calcBiffErrorCode( rErrorCode ) );
+ return mrSheetGlob.getPageSettings();
}
-void WorksheetHelper::setErrorCell( const Reference< XCell >& rxCell, sal_uInt8 nErrorCode ) const
+SheetViewSettings& WorksheetHelper::getSheetViewSettings() const
{
- Reference< XFormulaTokens > xTokens( rxCell, UNO_QUERY );
- OSL_ENSURE( xTokens.is(), "WorksheetHelper::setErrorCell - missing formula interface" );
- if( xTokens.is() )
- {
- SimpleFormulaContext aContext( xTokens, false, false );
- getFormulaParser().convertErrorToFormula( aContext, nErrorCode );
- }
+ return mrSheetGlob.getSheetViewSettings();
}
-void WorksheetHelper::setCell( CellModel& orModel ) const
+VmlDrawing& WorksheetHelper::getVmlDrawing() const
{
- OSL_ENSURE( orModel.mxCell.is(), "WorksheetHelper::setCell - missing cell interface" );
- if( orModel.mbHasValueStr ) switch( orModel.mnCellType )
- {
- case XML_b:
- setBooleanCell( orModel.mxCell, orModel.maValueStr.toDouble() != 0.0 );
- // #108770# set 'Standard' number format for all Boolean cells
- orModel.mnNumFmtId = 0;
- break;
- case XML_n:
- orModel.mxCell->setValue( orModel.maValueStr.toDouble() );
- break;
- case XML_e:
- setErrorCell( orModel.mxCell, orModel.maValueStr );
- break;
- case XML_str:
- setStringCell( orModel.mxCell, orModel.maValueStr );
- break;
- case XML_s:
- setSharedStringCell( orModel.mxCell, orModel.maValueStr.toInt32(), orModel.mnXfId );
- break;
- }
+ return mrSheetGlob.getVmlDrawing();
}
-void WorksheetHelper::setStandardNumFmt( const Reference< XCell >& rxCell, sal_Int16 nStdNumFmt ) const
+BiffSheetDrawing& WorksheetHelper::getBiffDrawing() const
{
- try
- {
- Reference< XNumberFormatsSupplier > xNumFmtsSupp( getDocument(), UNO_QUERY_THROW );
- Reference< XNumberFormatTypes > xNumFmtTypes( xNumFmtsSupp->getNumberFormats(), UNO_QUERY_THROW );
- sal_Int32 nIndex = xNumFmtTypes->getStandardFormat( nStdNumFmt, Locale() );
- PropertySet aPropSet( rxCell );
- aPropSet.setProperty( PROP_NumberFormat, nIndex );
- }
- catch( Exception& )
- {
- }
+ return mrSheetGlob.getBiffDrawing();
}
void WorksheetHelper::setSheetType( WorksheetType eSheetType )
{
- mrSheetData.setSheetType( eSheetType );
-}
-
-void WorksheetHelper::setCellFormat( const CellModel& rModel )
-{
- mrSheetData.setCellFormat( rModel );
-}
-
-void WorksheetHelper::setMergedRange( const CellRangeAddress& rRange )
-{
- mrSheetData.setMergedRange( rRange );
+ mrSheetGlob.setSheetType( eSheetType );
}
void WorksheetHelper::setPageBreak( const PageBreakModel& rModel, bool bRowBreak )
{
- mrSheetData.setPageBreak( rModel, bRowBreak );
+ mrSheetGlob.setPageBreak( rModel, bRowBreak );
}
void WorksheetHelper::setHyperlink( const HyperlinkModel& rModel )
{
- mrSheetData.setHyperlink( rModel );
+ mrSheetGlob.setHyperlink( rModel );
}
void WorksheetHelper::setValidation( const ValidationModel& rModel )
{
- mrSheetData.setValidation( rModel );
-}
-
-void WorksheetHelper::setTableOperation( const CellRangeAddress& rRange, const DataTableModel& rModel ) const
-{
- OSL_ENSURE( getAddressConverter().checkCellRange( rRange, true, false ), "WorksheetHelper::setTableOperation - invalid range" );
- bool bOk = false;
- if( !rModel.mbRef1Deleted && (rModel.maRef1.getLength() > 0) && (rRange.StartColumn > 0) && (rRange.StartRow > 0) )
- {
- CellRangeAddress aOpRange = rRange;
- CellAddress aRef1, aRef2;
- if( getAddressConverter().convertToCellAddress( aRef1, rModel.maRef1, mrSheetData.getSheetIndex(), true ) ) try
- {
- if( rModel.mb2dTable )
- {
- if( !rModel.mbRef2Deleted && getAddressConverter().convertToCellAddress( aRef2, rModel.maRef2, mrSheetData.getSheetIndex(), true ) )
- {
- // API call expects input values inside operation range
- --aOpRange.StartColumn;
- --aOpRange.StartRow;
- // formula range is top-left cell of operation range
- CellRangeAddress aFormulaRange( mrSheetData.getSheetIndex(), aOpRange.StartColumn, aOpRange.StartRow, aOpRange.StartColumn, aOpRange.StartRow );
- // set multiple operation
- Reference< XMultipleOperation > xMultOp( mrSheetData.getCellRange( aOpRange ), UNO_QUERY_THROW );
- xMultOp->setTableOperation( aFormulaRange, ::com::sun::star::sheet::TableOperationMode_BOTH, aRef2, aRef1 );
- bOk = true;
- }
- }
- else if( rModel.mbRowTable )
- {
- // formula range is column to the left of operation range
- CellRangeAddress aFormulaRange( mrSheetData.getSheetIndex(), aOpRange.StartColumn - 1, aOpRange.StartRow, aOpRange.StartColumn - 1, aOpRange.EndRow );
- // API call expects input values (top row) inside operation range
- --aOpRange.StartRow;
- // set multiple operation
- Reference< XMultipleOperation > xMultOp( mrSheetData.getCellRange( aOpRange ), UNO_QUERY_THROW );
- xMultOp->setTableOperation( aFormulaRange, ::com::sun::star::sheet::TableOperationMode_ROW, aRef1, aRef1 );
- bOk = true;
- }
- else
- {
- // formula range is row above operation range
- CellRangeAddress aFormulaRange( mrSheetData.getSheetIndex(), aOpRange.StartColumn, aOpRange.StartRow - 1, aOpRange.EndColumn, aOpRange.StartRow - 1 );
- // API call expects input values (left column) inside operation range
- --aOpRange.StartColumn;
- // set multiple operation
- Reference< XMultipleOperation > xMultOp( mrSheetData.getCellRange( aOpRange ), UNO_QUERY_THROW );
- xMultOp->setTableOperation( aFormulaRange, ::com::sun::star::sheet::TableOperationMode_COLUMN, aRef1, aRef1 );
- bOk = true;
- }
- }
- catch( Exception& )
- {
- }
- }
-
- // on error: fill cell range with error codes
- if( !bOk )
- {
- for( CellAddress aPos( mrSheetData.getSheetIndex(), rRange.StartColumn, rRange.StartRow ); aPos.Row <= rRange.EndRow; ++aPos.Row )
- for( aPos.Column = rRange.StartColumn; aPos.Column <= rRange.EndColumn; ++aPos.Column )
- setErrorCell( mrSheetData.getCell( aPos ), BIFF_ERR_REF );
- }
+ mrSheetGlob.setValidation( rModel );
}
void WorksheetHelper::setLabelRanges( const ApiCellRangeList& rColRanges, const ApiCellRangeList& rRowRanges )
@@ -2181,107 +1589,100 @@ void WorksheetHelper::setLabelRanges( const ApiCellRangeList& rColRanges, const
void WorksheetHelper::setDrawingPath( const OUString& rDrawingPath )
{
- mrSheetData.setDrawingPath( rDrawingPath );
+ mrSheetGlob.setDrawingPath( rDrawingPath );
}
void WorksheetHelper::setVmlDrawingPath( const OUString& rVmlDrawingPath )
{
- mrSheetData.setVmlDrawingPath( rVmlDrawingPath );
+ mrSheetGlob.setVmlDrawingPath( rVmlDrawingPath );
}
void WorksheetHelper::extendUsedArea( const CellAddress& rAddress )
{
- mrSheetData.extendUsedArea( rAddress );
+ mrSheetGlob.extendUsedArea( rAddress );
}
void WorksheetHelper::extendUsedArea( const CellRangeAddress& rRange )
{
- mrSheetData.extendUsedArea( rRange );
+ mrSheetGlob.extendUsedArea( rRange );
}
void WorksheetHelper::extendShapeBoundingBox( const Rectangle& rShapeRect )
{
- mrSheetData.extendShapeBoundingBox( rShapeRect );
+ mrSheetGlob.extendShapeBoundingBox( rShapeRect );
}
void WorksheetHelper::setBaseColumnWidth( sal_Int32 nWidth )
{
- mrSheetData.setBaseColumnWidth( nWidth );
+ mrSheetGlob.setBaseColumnWidth( nWidth );
}
void WorksheetHelper::setDefaultColumnWidth( double fWidth )
{
- mrSheetData.setDefaultColumnWidth( fWidth );
+ mrSheetGlob.setDefaultColumnWidth( fWidth );
}
void WorksheetHelper::setDefaultColumnFormat( sal_Int32 nFirstCol, sal_Int32 nLastCol, sal_Int32 nXfId )
{
- mrSheetData.convertColumnFormat( nFirstCol, nLastCol, nXfId );
+ mrSheetGlob.convertColumnFormat( nFirstCol, nLastCol, nXfId );
}
void WorksheetHelper::setColumnModel( const ColumnModel& rModel )
{
- mrSheetData.setColumnModel( rModel );
+ mrSheetGlob.setColumnModel( rModel );
}
void WorksheetHelper::setDefaultRowSettings( double fHeight, bool bCustomHeight, bool bHidden, bool bThickTop, bool bThickBottom )
{
- mrSheetData.setDefaultRowSettings( fHeight, bCustomHeight, bHidden, bThickTop, bThickBottom );
+ mrSheetGlob.setDefaultRowSettings( fHeight, bCustomHeight, bHidden, bThickTop, bThickBottom );
}
void WorksheetHelper::setRowModel( const RowModel& rModel )
{
- mrSheetData.setRowModel( rModel );
-}
-
-void WorksheetHelper::initializeWorksheetImport()
-{
- mrSheetData.initializeWorksheetImport();
+ mrSheetGlob.setRowModel( rModel );
}
-void WorksheetHelper::finalizeWorksheetImport()
+void WorksheetHelper::setManualRowHeight( sal_Int32 nRow )
{
- mrSheetData.finalizeWorksheetImport();
+ mrSheetGlob.setManualRowHeight( nRow );
}
-// ============================================================================
-
-namespace prv {
-
-WorksheetDataOwner::WorksheetDataOwner( WorksheetDataRef xSheetData ) :
- mxSheetData( xSheetData )
+void WorksheetHelper::putValue( const CellAddress& rAddress, double fValue ) const
{
+ Reference< XCell > xCell = getCell( rAddress );
+ OSL_ENSURE( xCell.is(), "WorksheetHelper::putValue - missing cell interface" );
+ if( xCell.is() ) xCell->setValue( fValue );
}
-WorksheetDataOwner::~WorksheetDataOwner()
+void WorksheetHelper::putString( const CellAddress& rAddress, const OUString& rText ) const
{
+ Reference< XText > xText( getCell( rAddress ), UNO_QUERY );
+ OSL_ENSURE( xText.is(), "WorksheetHelper::putString - missing text interface" );
+ if( xText.is() ) xText->setString( rText );
}
-} // namespace prv
-
-// ----------------------------------------------------------------------------
-
-WorksheetHelperRoot::WorksheetHelperRoot( const WorkbookHelper& rHelper, const ISegmentProgressBarRef& rxProgressBar, WorksheetType eSheetType, sal_Int16 nSheet ) :
- prv::WorksheetDataOwner( prv::WorksheetDataRef( new WorksheetData( rHelper, rxProgressBar, eSheetType, nSheet ) ) ),
- WorksheetHelper( *mxSheetData )
+void WorksheetHelper::putRichString( const CellAddress& rAddress, const RichString& rString, const Font* pFirstPortionFont ) const
{
+ Reference< XText > xText( getCell( rAddress ), UNO_QUERY );
+ OSL_ENSURE( xText.is(), "WorksheetHelper::putRichString - missing text interface" );
+ rString.convert( xText, pFirstPortionFont );
}
-WorksheetHelperRoot::WorksheetHelperRoot( const WorksheetHelper& rHelper ) :
- prv::WorksheetDataOwner( prv::WorksheetDataRef() ),
- WorksheetHelper( rHelper )
+void WorksheetHelper::putFormulaTokens( const CellAddress& rAddress, const ApiTokenSequence& rTokens ) const
{
+ Reference< XFormulaTokens > xTokens( getCell( rAddress ), UNO_QUERY );
+ OSL_ENSURE( xTokens.is(), "WorksheetHelper::putFormulaTokens - missing token interface" );
+ if( xTokens.is() ) xTokens->setTokens( rTokens );
}
-WorksheetHelperRoot::WorksheetHelperRoot( const WorksheetHelperRoot& rHelper ) :
- prv::WorksheetDataOwner( rHelper.mxSheetData ),
- WorksheetHelper( rHelper )
+void WorksheetHelper::initializeWorksheetImport()
{
+ mrSheetGlob.initializeWorksheetImport();
}
-bool WorksheetHelperRoot::isValidSheet() const
+void WorksheetHelper::finalizeWorksheetImport()
{
- return mxSheetData->isValidSheet();
+ mrSheetGlob.finalizeWorksheetImport();
}
// ============================================================================