00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "precompiled_sc.hxx"
00030 #include "xecontent.hxx"
00031
00032 #include <list>
00033 #include <algorithm>
00034 #include <com/sun/star/container/XIndexAccess.hpp>
00035 #include <com/sun/star/frame/XModel.hpp>
00036 #include <com/sun/star/sheet/XAreaLinks.hpp>
00037 #include <com/sun/star/sheet/XAreaLink.hpp>
00038 #include <sfx2/objsh.hxx>
00039 #include <tools/urlobj.hxx>
00040 #include <svtools/itemset.hxx>
00041 #include <formula/grammar.hxx>
00042 #include "scitems.hxx"
00043 #include <svx/eeitem.hxx>
00044 #include <svx/flditem.hxx>
00045 #include "document.hxx"
00046 #include "validat.hxx"
00047 #include "unonames.hxx"
00048 #include "convuno.hxx"
00049 #include "rangenam.hxx"
00050 #include "tokenarray.hxx"
00051 #include "stlpool.hxx"
00052 #include "patattr.hxx"
00053 #include "fapihelper.hxx"
00054 #include "xehelper.hxx"
00055 #include "xestyle.hxx"
00056 #include "xename.hxx"
00057
00058 #include <oox/core/tokens.hxx>
00059
00060 using ::com::sun::star::uno::Reference;
00061 using ::com::sun::star::uno::Any;
00062 using ::com::sun::star::uno::UNO_QUERY;
00063 using ::com::sun::star::beans::XPropertySet;
00064 using ::com::sun::star::container::XIndexAccess;
00065 using ::com::sun::star::frame::XModel;
00066 using ::com::sun::star::table::CellRangeAddress;
00067 using ::com::sun::star::sheet::XAreaLinks;
00068 using ::com::sun::star::sheet::XAreaLink;
00069 using ::rtl::OString;
00070 using ::rtl::OUString;
00071 using ::rtl::OUStringBuffer;
00072
00073
00074
00075
00076 #define EXC_INCL_SST_STATISTICS 0
00077
00078
00079
00081 struct XclExpHashEntry
00082 {
00083 const XclExpString* mpString;
00084 sal_uInt32 mnSstIndex;
00085 inline explicit XclExpHashEntry( const XclExpString* pString = 0, sal_uInt32 nSstIndex = 0 ) :
00086 mpString( pString ), mnSstIndex( nSstIndex ) {}
00087 };
00088
00090 struct XclExpHashEntrySWO
00091 {
00092 inline bool operator()( const XclExpHashEntry& rLeft, const XclExpHashEntry& rRight ) const
00093 { return *rLeft.mpString < *rRight.mpString; }
00094 };
00095
00096
00097
00101 class XclExpSstImpl
00102 {
00103 public:
00104 explicit XclExpSstImpl();
00105
00107 sal_uInt32 Insert( XclExpStringRef xString );
00108
00110 void Save( XclExpStream& rStrm );
00111 void SaveXml( XclExpXmlStream& rStrm );
00112
00113 private:
00114 typedef ::std::list< XclExpStringRef > XclExpStringList;
00115 typedef ::std::vector< XclExpHashEntry > XclExpHashVec;
00116 typedef ::std::vector< XclExpHashVec > XclExpHashTab;
00117
00118 XclExpStringList maStringList;
00119 XclExpHashTab maHashTab;
00120 sal_uInt32 mnTotal;
00121 sal_uInt32 mnSize;
00122 };
00123
00124
00125
00126 const sal_uInt32 EXC_SST_HASHTABLE_SIZE = 2048;
00127
00128 XclExpSstImpl::XclExpSstImpl() :
00129 maHashTab( EXC_SST_HASHTABLE_SIZE ),
00130 mnTotal( 0 ),
00131 mnSize( 0 )
00132 {
00133 }
00134
00135 sal_uInt32 XclExpSstImpl::Insert( XclExpStringRef xString )
00136 {
00137 DBG_ASSERT( xString.get(), "XclExpSstImpl::Insert - empty pointer not allowed" );
00138 if( !xString.get() )
00139 xString.reset( new XclExpString );
00140
00141 ++mnTotal;
00142 sal_uInt32 nSstIndex = 0;
00143
00144
00145 sal_uInt16 nHash = xString->GetHash();
00146 (nHash ^= (nHash / EXC_SST_HASHTABLE_SIZE)) %= EXC_SST_HASHTABLE_SIZE;
00147
00148 XclExpHashVec& rVec = maHashTab[ nHash ];
00149 XclExpHashEntry aEntry( xString.get(), mnSize );
00150 XclExpHashVec::iterator aIt = ::std::lower_bound( rVec.begin(), rVec.end(), aEntry, XclExpHashEntrySWO() );
00151 if( (aIt == rVec.end()) || (*aIt->mpString != *xString) )
00152 {
00153 nSstIndex = mnSize;
00154 maStringList.push_back( xString );
00155 rVec.insert( aIt, aEntry );
00156 ++mnSize;
00157 }
00158 else
00159 {
00160 nSstIndex = aIt->mnSstIndex;
00161 }
00162
00163 return nSstIndex;
00164 }
00165
00166 void XclExpSstImpl::Save( XclExpStream& rStrm )
00167 {
00168 if( maStringList.empty() )
00169 return;
00170
00171 #if (OSL_DEBUG_LEVEL > 1) && EXC_INCL_SST_STATISTICS
00172 {
00173 #define APPENDINT( value ) Append( ByteString::CreateFromInt32( value ) )
00174 ScfUInt32Vec aVec;
00175 size_t nPerBucket = mnSize / EXC_SST_HASHTABLE_SIZE + 1, nEff = 0;
00176 for( XclExpHashTab::const_iterator aTIt = maHashTab.begin(), aTEnd = maHashTab.end(); aTIt != aTEnd; ++aTIt )
00177 {
00178 size_t nSize = aTIt->size();
00179 if( nSize >= aVec.size() ) aVec.resize( nSize + 1, 0 );
00180 ++aVec[ nSize ];
00181 if( nSize > nPerBucket ) nEff += nSize - nPerBucket;
00182 }
00183 ByteString aStr( "SST HASHING STATISTICS\n\n" );
00184 aStr.Append( "Total count:\t" ).APPENDINT( mnTotal ).Append( " strings\n" );
00185 aStr.Append( "Reduced to:\t" ).APPENDINT( mnSize ).Append( " strings (" );
00186 aStr.APPENDINT( 100 * mnSize / mnTotal ).Append( "%)\n" );
00187 aStr.Append( "Effectivity:\t\t" ).APPENDINT( 100 - 100 * nEff / mnSize );
00188 aStr.Append( "% (best: " ).APPENDINT( nPerBucket ).Append( " strings per bucket)\n" );
00189 aStr.Append( "\t\tCount of buckets\nBucket size\ttotal\tmax\tTotal strings\n" );
00190 for( size_t nIx = 0, nSize = aVec.size(), nInc = 1; nIx < nSize; nIx += nInc )
00191 {
00192 if( (nIx == 10) || (nIx == 100) || (nIx == 1000) ) nInc = nIx;
00193 size_t nMaxIx = ::std::min( nIx + nInc, nSize ), nCount = 0, nMaxCount = 0, nStrings = 0;
00194 for( size_t nSubIx = nIx; nSubIx < nMaxIx; ++nSubIx )
00195 {
00196 nCount += aVec[ nSubIx ];
00197 if( aVec[ nSubIx ] > nMaxCount ) nMaxCount = aVec[ nSubIx ];
00198 nStrings += nSubIx * aVec[ nSubIx ];
00199 }
00200 if( nMaxCount )
00201 {
00202 aStr.APPENDINT( nIx );
00203 if( nMaxIx - nIx > 1 ) aStr.Append( '-' ).APPENDINT( nMaxIx - 1 );
00204 aStr.Append( "\t\t" ).APPENDINT( nCount ).Append( '\t' ).APPENDINT( nMaxCount );
00205 aStr.Append( '\t' ).APPENDINT( nStrings ).Append( '\n' );
00206 }
00207 }
00208 DBG_ERRORFILE( aStr.GetBuffer() );
00209 #undef APPENDINT
00210 }
00211 #endif
00212
00213 SvMemoryStream aExtSst( 8192 );
00214
00215 sal_uInt32 nBucket = mnSize;
00216 while( nBucket > 0x0100 )
00217 nBucket /= 2;
00218
00219 sal_uInt16 nPerBucket = llimit_cast< sal_uInt16 >( nBucket, 8 );
00220 sal_uInt16 nBucketIndex = 0;
00221
00222
00223
00224 rStrm.StartRecord( EXC_ID_SST, 8 );
00225
00226 rStrm << mnTotal << mnSize;
00227 for( XclExpStringList::const_iterator aIt = maStringList.begin(), aEnd = maStringList.end(); aIt != aEnd; ++aIt )
00228 {
00229 if( !nBucketIndex )
00230 {
00231
00232 sal_uInt32 nStrmPos = static_cast< sal_uInt32 >( rStrm.GetSvStreamPos() );
00233 sal_uInt16 nRecPos = rStrm.GetRawRecPos() + 4;
00234 aExtSst << nStrmPos
00235 << nRecPos
00236 << sal_uInt16( 0 );
00237 }
00238
00239 rStrm << **aIt;
00240
00241 if( ++nBucketIndex == nPerBucket )
00242 nBucketIndex = 0;
00243 }
00244
00245 rStrm.EndRecord();
00246
00247
00248
00249 rStrm.StartRecord( EXC_ID_EXTSST, 0 );
00250
00251 rStrm << nPerBucket;
00252 rStrm.SetSliceSize( 8 );
00253 aExtSst.Seek( STREAM_SEEK_TO_BEGIN );
00254 rStrm.CopyFromStream( aExtSst );
00255
00256 rStrm.EndRecord();
00257 }
00258
00259 void XclExpSstImpl::SaveXml( XclExpXmlStream& rStrm )
00260 {
00261 if( maStringList.empty() )
00262 return;
00263
00264 sax_fastparser::FSHelperPtr pSst = rStrm.CreateOutputStream(
00265 OUString::createFromAscii( "xl/sharedStrings.xml" ),
00266 OUString::createFromAscii( "sharedStrings.xml" ),
00267 rStrm.GetCurrentStream()->getOutputStream(),
00268 "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml",
00269 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings" );
00270 rStrm.PushStream( pSst );
00271
00272 pSst->startElement( XML_sst,
00273 XML_xmlns, "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
00274 XML_count, OString::valueOf( (sal_Int32) mnTotal ).getStr(),
00275 XML_uniqueCount, OString::valueOf( (sal_Int32) mnSize ).getStr(),
00276 FSEND );
00277
00278 for( XclExpStringList::const_iterator aIt = maStringList.begin(), aEnd = maStringList.end(); aIt != aEnd; ++aIt )
00279 {
00280 pSst->startElement( XML_si, FSEND );
00281 (*aIt)->WriteXml( rStrm );
00282 pSst->endElement( XML_si );
00283 }
00284
00285 pSst->endElement( XML_sst );
00286
00287 rStrm.PopStream();
00288 }
00289
00290
00291
00292 XclExpSst::XclExpSst() :
00293 mxImpl( new XclExpSstImpl )
00294 {
00295 }
00296
00297 XclExpSst::~XclExpSst()
00298 {
00299 }
00300
00301 sal_uInt32 XclExpSst::Insert( XclExpStringRef xString )
00302 {
00303 return mxImpl->Insert( xString );
00304 }
00305
00306 void XclExpSst::Save( XclExpStream& rStrm )
00307 {
00308 mxImpl->Save( rStrm );
00309 }
00310
00311 void XclExpSst::SaveXml( XclExpXmlStream& rStrm )
00312 {
00313 mxImpl->SaveXml( rStrm );
00314 }
00315
00316
00317
00318 XclExpMergedcells::XclExpMergedcells( const XclExpRoot& rRoot ) :
00319 XclExpRoot( rRoot )
00320 {
00321 }
00322
00323 void XclExpMergedcells::AppendRange( const ScRange& rRange, sal_uInt32 nBaseXFId )
00324 {
00325 if( GetBiff() == EXC_BIFF8 )
00326 {
00327 maMergedRanges.Append( rRange );
00328 maBaseXFIds.push_back( nBaseXFId );
00329 }
00330 }
00331
00332 sal_uInt32 XclExpMergedcells::GetBaseXFId( const ScAddress& rPos ) const
00333 {
00334 DBG_ASSERT( maBaseXFIds.size() == maMergedRanges.Count(), "XclExpMergedcells::GetBaseXFId - invalid lists" );
00335 ScfUInt32Vec::const_iterator aIt = maBaseXFIds.begin();
00336 ScRangeList& rNCRanges = const_cast< ScRangeList& >( maMergedRanges );
00337 for( const ScRange* pScRange = rNCRanges.First(); pScRange; pScRange = rNCRanges.Next(), ++aIt )
00338 if( pScRange->In( rPos ) )
00339 return *aIt;
00340 return EXC_XFID_NOTFOUND;
00341 }
00342
00343 void XclExpMergedcells::Save( XclExpStream& rStrm )
00344 {
00345 if( GetBiff() == EXC_BIFF8 )
00346 {
00347 XclRangeList aXclRanges;
00348 GetAddressConverter().ConvertRangeList( aXclRanges, maMergedRanges, true );
00349 size_t nFirstRange = 0;
00350 size_t nRemainingRanges = aXclRanges.size();
00351 while( nRemainingRanges > 0 )
00352 {
00353 size_t nRangeCount = ::std::min< size_t >( nRemainingRanges, EXC_MERGEDCELLS_MAXCOUNT );
00354 rStrm.StartRecord( EXC_ID_MERGEDCELLS, 2 + 8 * nRangeCount );
00355 aXclRanges.WriteSubList( rStrm, nFirstRange, nRangeCount );
00356 rStrm.EndRecord();
00357 nFirstRange += nRangeCount;
00358 nRemainingRanges -= nRangeCount;
00359 }
00360 }
00361 }
00362
00363 void XclExpMergedcells::SaveXml( XclExpXmlStream& rStrm )
00364 {
00365 ULONG nCount = maMergedRanges.Count();
00366 if( !nCount )
00367 return;
00368 sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
00369 rWorksheet->startElement( XML_mergeCells,
00370 XML_count, OString::valueOf( (sal_Int32) nCount ).getStr(),
00371 FSEND );
00372 for( ULONG i = 0; i < nCount; ++i )
00373 {
00374 if( const ScRange* pRange = maMergedRanges.GetObject( i ) )
00375 {
00376 rWorksheet->singleElement( XML_mergeCell,
00377 XML_ref, XclXmlUtils::ToOString( *pRange ).getStr(),
00378 FSEND );
00379 }
00380 }
00381 rWorksheet->endElement( XML_mergeCells );
00382 }
00383
00384
00385
00386 XclExpHyperlink::XclExpHyperlink( const XclExpRoot& rRoot, const SvxURLField& rUrlField, const ScAddress& rScPos ) :
00387 XclExpRecord( EXC_ID_HLINK ),
00388 maScPos( rScPos ),
00389 mxVarData( new SvMemoryStream ),
00390 mnFlags( 0 )
00391 {
00392 const String& rUrl = rUrlField.GetURL();
00393 const String& rRepr = rUrlField.GetRepresentation();
00394 INetURLObject aUrlObj( rUrl );
00395 const INetProtocol eProtocol = aUrlObj.GetProtocol();
00396 bool bWithRepr = rRepr.Len() > 0;
00397 XclExpStream aXclStrm( *mxVarData, rRoot );
00398
00399
00400 if( bWithRepr )
00401 {
00402 XclExpString aDescr( rRepr, EXC_STR_FORCEUNICODE, 255 );
00403 aXclStrm << sal_uInt32( aDescr.Len() + 1 );
00404 aDescr.WriteBuffer( aXclStrm );
00405 aXclStrm << sal_uInt16( 0 );
00406
00407 mnFlags |= EXC_HLINK_DESCR;
00408 mxRepr.reset( new String( rRepr ) );
00409 }
00410
00411
00412 if( eProtocol == INET_PROT_FILE || eProtocol == INET_PROT_SMB )
00413 {
00414 sal_uInt16 nLevel;
00415 bool bRel;
00416 String aFileName( BuildFileName( nLevel, bRel, rUrl, rRoot ) );
00417
00418 if( eProtocol == INET_PROT_SMB )
00419 {
00420
00421 aFileName = aUrlObj.GetMainURL( INetURLObject::NO_DECODE );
00422 aFileName = String( aFileName.GetBuffer() + 4 );
00423 aFileName.SearchAndReplaceAll( '/', '\\' );
00424 }
00425
00426 if( !bRel )
00427 mnFlags |= EXC_HLINK_ABS;
00428 mnFlags |= EXC_HLINK_BODY;
00429
00430 ByteString aAsciiLink( aFileName, rRoot.GetTextEncoding() );
00431 XclExpString aLink( aFileName, EXC_STR_FORCEUNICODE, 255 );
00432 aXclStrm << XclTools::maGuidFileMoniker
00433 << nLevel
00434 << sal_uInt32( aAsciiLink.Len() + 1 );
00435 aXclStrm.Write( aAsciiLink.GetBuffer(), aAsciiLink.Len() );
00436 aXclStrm << sal_uInt8( 0 )
00437 << sal_uInt32( 0xDEADFFFF );
00438 aXclStrm.WriteZeroBytes( 20 );
00439 aXclStrm << sal_uInt32( aLink.GetBufferSize() + 6 )
00440 << sal_uInt32( aLink.GetBufferSize() )
00441 << sal_uInt16( 0x0003 );
00442 aLink.WriteBuffer( aXclStrm );
00443
00444 if( !mxRepr.get() )
00445 mxRepr.reset( new String( aFileName ) );
00446
00447 msTarget = XclXmlUtils::ToOUString( aLink );
00448 }
00449 else if( eProtocol != INET_PROT_NOT_VALID )
00450 {
00451 XclExpString aUrl( aUrlObj.GetURLNoMark(), EXC_STR_FORCEUNICODE, 255 );
00452 aXclStrm << XclTools::maGuidUrlMoniker
00453 << sal_uInt32( aUrl.GetBufferSize() + 2 );
00454 aUrl.WriteBuffer( aXclStrm );
00455 aXclStrm << sal_uInt16( 0 );
00456
00457 mnFlags |= EXC_HLINK_BODY | EXC_HLINK_ABS;
00458 if( !mxRepr.get() )
00459 mxRepr.reset( new String( rUrl ) );
00460
00461 msTarget = XclXmlUtils::ToOUString( aUrl );
00462 }
00463 else if( rUrl.GetChar( 0 ) == '#' )
00464 {
00465 String aTextMark( rUrl.Copy( 1 ) );
00466 aTextMark.SearchAndReplace( '.', '!' );
00467 mxTextMark.reset( new XclExpString( aTextMark, EXC_STR_FORCEUNICODE, 255 ) );
00468 }
00469
00470
00471 if( !mxTextMark.get() && aUrlObj.HasMark() )
00472 mxTextMark.reset( new XclExpString( aUrlObj.GetMark(), EXC_STR_FORCEUNICODE, 255 ) );
00473
00474 if( mxTextMark.get() )
00475 {
00476 aXclStrm << sal_uInt32( mxTextMark->Len() + 1 );
00477 mxTextMark->WriteBuffer( aXclStrm );
00478 aXclStrm << sal_uInt16( 0 );
00479
00480 mnFlags |= EXC_HLINK_MARK;
00481 }
00482
00483 SetRecSize( 32 + mxVarData->Tell() );
00484 }
00485
00486 XclExpHyperlink::~XclExpHyperlink()
00487 {
00488 }
00489
00490 String XclExpHyperlink::BuildFileName(
00491 sal_uInt16& rnLevel, bool& rbRel, const String& rUrl, const XclExpRoot& rRoot ) const
00492 {
00493 String aDosName( INetURLObject( rUrl ).getFSysPath( INetURLObject::FSYS_DOS ) );
00494 rnLevel = 0;
00495 rbRel = rRoot.IsRelUrl();
00496
00497 if( rbRel )
00498 {
00499
00500 String aTmpName( aDosName );
00501 aDosName = INetURLObject::GetRelURL( rRoot.GetBasePath(), rUrl,
00502 INetURLObject::WAS_ENCODED, INetURLObject::DECODE_WITH_CHARSET );
00503
00504 if( aDosName.SearchAscii( INET_FILE_SCHEME ) == 0 )
00505 {
00506
00507 aDosName = aTmpName;
00508 rbRel = false;
00509 }
00510 else if( aDosName.SearchAscii( "./" ) == 0 )
00511 {
00512 aDosName.Erase( 0, 2 );
00513 }
00514 else
00515 {
00516 while( aDosName.SearchAndReplaceAscii( "../", EMPTY_STRING ) == 0 )
00517 ++rnLevel;
00518 }
00519 }
00520 return aDosName;
00521 }
00522
00523 void XclExpHyperlink::WriteBody( XclExpStream& rStrm )
00524 {
00525 sal_uInt16 nXclCol = static_cast< sal_uInt16 >( maScPos.Col() );
00526 sal_uInt16 nXclRow = static_cast< sal_uInt16 >( maScPos.Row() );
00527 rStrm << nXclRow << nXclRow << nXclCol << nXclCol;
00528 WriteEmbeddedData( rStrm );
00529 }
00530
00531 void XclExpHyperlink::WriteEmbeddedData( XclExpStream& rStrm )
00532 {
00533 rStrm << XclTools::maGuidStdLink
00534 << sal_uInt32( 2 )
00535 << mnFlags;
00536
00537 mxVarData->Seek( STREAM_SEEK_TO_BEGIN );
00538 rStrm.CopyFromStream( *mxVarData );
00539 }
00540
00541 void XclExpHyperlink::SaveXml( XclExpXmlStream& rStrm )
00542 {
00543 OUString sId = rStrm.addRelation( rStrm.GetCurrentStream()->getOutputStream(),
00544 XclXmlUtils::ToOUString( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" ),
00545 msTarget,
00546 XclXmlUtils::ToOUString( "External" ) );
00547 rStrm.GetCurrentStream()->singleElement( XML_hyperlink,
00548 XML_ref, XclXmlUtils::ToOString( maScPos ).getStr(),
00549 FSNS( XML_r, XML_id ), XclXmlUtils::ToOString( sId ).getStr(),
00550 XML_location, mxTextMark.get() != NULL
00551 ? XclXmlUtils::ToOString( *mxTextMark ).getStr()
00552 : NULL,
00553
00554 XML_display, XclXmlUtils::ToOString( *mxRepr ).getStr(),
00555 FSEND );
00556 }
00557
00558
00559
00560 XclExpLabelranges::XclExpLabelranges( const XclExpRoot& rRoot ) :
00561 XclExpRoot( rRoot )
00562 {
00563 SCTAB nScTab = GetCurrScTab();
00564
00565 FillRangeList( maRowRanges, rRoot.GetDoc().GetRowNameRangesRef(), nScTab );
00566
00567 for( ScRange* pScRange = maRowRanges.First(); pScRange; pScRange = maRowRanges.Next() )
00568 if( pScRange->aStart.Col() != pScRange->aEnd.Col() )
00569 pScRange->aEnd.SetCol( pScRange->aStart.Col() );
00570
00571 FillRangeList( maColRanges, rRoot.GetDoc().GetColNameRangesRef(), nScTab );
00572 }
00573
00574 void XclExpLabelranges::FillRangeList( ScRangeList& rScRanges,
00575 ScRangePairListRef xLabelRangesRef, SCTAB nScTab )
00576 {
00577 for( const ScRangePair* pRangePair = xLabelRangesRef->First(); pRangePair; pRangePair = xLabelRangesRef->Next() )
00578 {
00579 const ScRange& rScRange = pRangePair->GetRange( 0 );
00580 if( rScRange.aStart.Tab() == nScTab )
00581 rScRanges.Append( rScRange );
00582 }
00583 }
00584
00585 void XclExpLabelranges::Save( XclExpStream& rStrm )
00586 {
00587 XclExpAddressConverter& rAddrConv = GetAddressConverter();
00588 XclRangeList aRowXclRanges, aColXclRanges;
00589 rAddrConv.ConvertRangeList( aRowXclRanges, maRowRanges, false );
00590 rAddrConv.ConvertRangeList( aColXclRanges, maColRanges, false );
00591 if( !aRowXclRanges.empty() || !aColXclRanges.empty() )
00592 {
00593 rStrm.StartRecord( EXC_ID_LABELRANGES, 4 + 8 * (aRowXclRanges.size() + aColXclRanges.size()) );
00594 rStrm << aRowXclRanges << aColXclRanges;
00595 rStrm.EndRecord();
00596 }
00597 }
00598
00599
00600
00602 class XclExpCFImpl : protected XclExpRoot
00603 {
00604 public:
00605 explicit XclExpCFImpl( const XclExpRoot& rRoot, const ScCondFormatEntry& rFormatEntry );
00606
00608 void WriteBody( XclExpStream& rStrm );
00609
00610 private:
00611 const ScCondFormatEntry& mrFormatEntry;
00612 XclFontData maFontData;
00613 XclExpCellBorder maBorder;
00614 XclExpCellArea maArea;
00615 XclTokenArrayRef mxTokArr1;
00616 XclTokenArrayRef mxTokArr2;
00617 sal_uInt32 mnFontColorId;
00618 sal_uInt8 mnType;
00619 sal_uInt8 mnOperator;
00620 bool mbFontUsed;
00621 bool mbHeightUsed;
00622 bool mbWeightUsed;
00623 bool mbColorUsed;
00624 bool mbUnderlUsed;
00625 bool mbItalicUsed;
00626 bool mbStrikeUsed;
00627 bool mbBorderUsed;
00628 bool mbPattUsed;
00629 };
00630
00631
00632
00633 XclExpCFImpl::XclExpCFImpl( const XclExpRoot& rRoot, const ScCondFormatEntry& rFormatEntry ) :
00634 XclExpRoot( rRoot ),
00635 mrFormatEntry( rFormatEntry ),
00636 mnFontColorId( 0 ),
00637 mnType( EXC_CF_TYPE_CELL ),
00638 mnOperator( EXC_CF_CMP_NONE ),
00639 mbFontUsed( false ),
00640 mbHeightUsed( false ),
00641 mbWeightUsed( false ),
00642 mbColorUsed( false ),
00643 mbUnderlUsed( false ),
00644 mbItalicUsed( false ),
00645 mbStrikeUsed( false ),
00646 mbBorderUsed( false ),
00647 mbPattUsed( false )
00648 {
00649
00650
00651
00652 if( SfxStyleSheetBase* pStyleSheet = GetDoc().GetStyleSheetPool()->Find( mrFormatEntry.GetStyle(), SFX_STYLE_FAMILY_PARA ) )
00653 {
00654 const SfxItemSet& rItemSet = pStyleSheet->GetItemSet();
00655
00656
00657 mbHeightUsed = ScfTools::CheckItem( rItemSet, ATTR_FONT_HEIGHT, true );
00658 mbWeightUsed = ScfTools::CheckItem( rItemSet, ATTR_FONT_WEIGHT, true );
00659 mbColorUsed = ScfTools::CheckItem( rItemSet, ATTR_FONT_COLOR, true );
00660 mbUnderlUsed = ScfTools::CheckItem( rItemSet, ATTR_FONT_UNDERLINE, true );
00661 mbItalicUsed = ScfTools::CheckItem( rItemSet, ATTR_FONT_POSTURE, true );
00662 mbStrikeUsed = ScfTools::CheckItem( rItemSet, ATTR_FONT_CROSSEDOUT, true );
00663 mbFontUsed = mbHeightUsed || mbWeightUsed || mbColorUsed || mbUnderlUsed || mbItalicUsed || mbStrikeUsed;
00664 if( mbFontUsed )
00665 {
00666 Font aFont;
00667 ScPatternAttr::GetFont( aFont, rItemSet, SC_AUTOCOL_RAW );
00668 maFontData.FillFromVclFont( aFont );
00669 mnFontColorId = GetPalette().InsertColor( maFontData.maColor, EXC_COLOR_CELLTEXT );
00670 }
00671
00672
00673 mbBorderUsed = ScfTools::CheckItem( rItemSet, ATTR_BORDER, true );
00674 if( mbBorderUsed )
00675 maBorder.FillFromItemSet( rItemSet, GetPalette(), GetBiff() );
00676
00677
00678 mbPattUsed = ScfTools::CheckItem( rItemSet, ATTR_BACKGROUND, true );
00679 if( mbPattUsed )
00680 maArea.FillFromItemSet( rItemSet, GetPalette(), GetBiff() );
00681 }
00682
00683
00684
00685 bool bFmla2 = false;
00686 switch( rFormatEntry.GetOperation() )
00687 {
00688 case SC_COND_NONE: mnType = EXC_CF_TYPE_NONE; break;
00689 case SC_COND_BETWEEN: mnOperator = EXC_CF_CMP_BETWEEN; bFmla2 = true; break;
00690 case SC_COND_NOTBETWEEN: mnOperator = EXC_CF_CMP_NOT_BETWEEN; bFmla2 = true; break;
00691 case SC_COND_EQUAL: mnOperator = EXC_CF_CMP_EQUAL; break;
00692 case SC_COND_NOTEQUAL: mnOperator = EXC_CF_CMP_NOT_EQUAL; break;
00693 case SC_COND_GREATER: mnOperator = EXC_CF_CMP_GREATER; break;
00694 case SC_COND_LESS: mnOperator = EXC_CF_CMP_LESS; break;
00695 case SC_COND_EQGREATER: mnOperator = EXC_CF_CMP_GREATER_EQUAL; break;
00696 case SC_COND_EQLESS: mnOperator = EXC_CF_CMP_LESS_EQUAL; break;
00697 case SC_COND_DIRECT: mnType = EXC_CF_TYPE_FMLA; break;
00698 default: mnType = EXC_CF_TYPE_NONE;
00699 DBG_ERRORFILE( "XclExpCF::WriteBody - unknown condition type" );
00700 }
00701
00702
00703
00704 XclExpFormulaCompiler& rFmlaComp = GetFormulaCompiler();
00705
00706 ::std::auto_ptr< ScTokenArray > xScTokArr( mrFormatEntry.CreateTokenArry( 0 ) );
00707 mxTokArr1 = rFmlaComp.CreateFormula( EXC_FMLATYPE_CONDFMT, *xScTokArr );
00708
00709 if( bFmla2 )
00710 {
00711 xScTokArr.reset( mrFormatEntry.CreateTokenArry( 1 ) );
00712 mxTokArr2 = rFmlaComp.CreateFormula( EXC_FMLATYPE_CONDFMT, *xScTokArr );
00713 }
00714 }
00715
00716 void XclExpCFImpl::WriteBody( XclExpStream& rStrm )
00717 {
00718
00719
00720 rStrm << mnType << mnOperator;
00721
00722
00723
00724 sal_uInt16 nFmlaSize1 = mxTokArr1.get() ? mxTokArr1->GetSize() : 0;
00725 sal_uInt16 nFmlaSize2 = mxTokArr2.get() ? mxTokArr2->GetSize() : 0;
00726 rStrm << nFmlaSize1 << nFmlaSize2;
00727
00728
00729
00730 if( mbFontUsed || mbBorderUsed || mbPattUsed )
00731 {
00732 sal_uInt32 nFlags = EXC_CF_ALLDEFAULT;
00733
00734 ::set_flag( nFlags, EXC_CF_BLOCK_FONT, mbFontUsed );
00735 ::set_flag( nFlags, EXC_CF_BLOCK_BORDER, mbBorderUsed );
00736 ::set_flag( nFlags, EXC_CF_BLOCK_AREA, mbPattUsed );
00737
00738
00739 ::set_flag( nFlags, EXC_CF_BORDER_ALL, !mbBorderUsed );
00740 ::set_flag( nFlags, EXC_CF_AREA_ALL, !mbPattUsed );
00741
00742 rStrm << nFlags << sal_uInt16( 0 );
00743
00744 if( mbFontUsed )
00745 {
00746
00747 sal_uInt32 nHeight = mbHeightUsed ? maFontData.mnHeight : 0xFFFFFFFF;
00748
00749 sal_uInt32 nStyle = 0;
00750 ::set_flag( nStyle, EXC_CF_FONT_STYLE, maFontData.mbItalic );
00751 ::set_flag( nStyle, EXC_CF_FONT_STRIKEOUT, maFontData.mbStrikeout );
00752
00753 sal_uInt32 nColor = mbColorUsed ? GetPalette().GetColorIndex( mnFontColorId ) : 0xFFFFFFFF;
00754
00755 sal_uInt32 nFontFlags1 = EXC_CF_FONT_ALLDEFAULT;
00756 ::set_flag( nFontFlags1, EXC_CF_FONT_STYLE, !(mbItalicUsed || mbWeightUsed) );
00757 ::set_flag( nFontFlags1, EXC_CF_FONT_STRIKEOUT, !mbStrikeUsed );
00758
00759 sal_uInt32 nFontFlags3 = mbUnderlUsed ? 0 : EXC_CF_FONT_UNDERL;
00760
00761 rStrm.WriteZeroBytesToRecord( 64 );
00762 rStrm << nHeight
00763 << nStyle
00764 << maFontData.mnWeight
00765 << EXC_FONTESC_NONE
00766 << maFontData.mnUnderline;
00767 rStrm.WriteZeroBytesToRecord( 3 );
00768 rStrm << nColor
00769 << sal_uInt32( 0 )
00770 << nFontFlags1
00771 << EXC_CF_FONT_ESCAPEM
00772 << nFontFlags3;
00773 rStrm.WriteZeroBytesToRecord( 16 );
00774 rStrm << sal_uInt16( 1 );
00775 }
00776
00777 if( mbBorderUsed )
00778 {
00779 sal_uInt16 nLineStyle = 0;
00780 sal_uInt32 nLineColor = 0;
00781 maBorder.SetFinalColors( GetPalette() );
00782 maBorder.FillToCF8( nLineStyle, nLineColor );
00783 rStrm << nLineStyle << nLineColor << sal_uInt16( 0 );
00784 }
00785
00786 if( mbPattUsed )
00787 {
00788 sal_uInt16 nPattern = 0, nColor = 0;
00789 maArea.SetFinalColors( GetPalette() );
00790 maArea.FillToCF8( nPattern, nColor );
00791 rStrm << nPattern << nColor;
00792 }
00793 }
00794 else
00795 {
00796
00797 rStrm << sal_uInt32( 0 ) << sal_uInt16( 0 );
00798 }
00799
00800
00801
00802 if( mxTokArr1.get() )
00803 mxTokArr1->WriteArray( rStrm );
00804 if( mxTokArr2.get() )
00805 mxTokArr2->WriteArray( rStrm );
00806 }
00807
00808
00809
00810 XclExpCF::XclExpCF( const XclExpRoot& rRoot, const ScCondFormatEntry& rFormatEntry ) :
00811 XclExpRecord( EXC_ID_CF ),
00812 XclExpRoot( rRoot ),
00813 mxImpl( new XclExpCFImpl( rRoot, rFormatEntry ) )
00814 {
00815 }
00816
00817 XclExpCF::~XclExpCF()
00818 {
00819 }
00820
00821 void XclExpCF::WriteBody( XclExpStream& rStrm )
00822 {
00823 mxImpl->WriteBody( rStrm );
00824 }
00825
00826
00827
00828 XclExpCondfmt::XclExpCondfmt( const XclExpRoot& rRoot, const ScConditionalFormat& rCondFormat ) :
00829 XclExpRecord( EXC_ID_CONDFMT ),
00830 XclExpRoot( rRoot )
00831 {
00832 ScRangeList aScRanges;
00833 GetDoc().FindConditionalFormat( rCondFormat.GetKey(), aScRanges, GetCurrScTab() );
00834 GetAddressConverter().ConvertRangeList( maXclRanges, aScRanges, true );
00835 if( !maXclRanges.empty() )
00836 {
00837 for( USHORT nIndex = 0, nCount = rCondFormat.Count(); nIndex < nCount; ++nIndex )
00838 if( const ScCondFormatEntry* pEntry = rCondFormat.GetEntry( nIndex ) )
00839 maCFList.AppendNewRecord( new XclExpCF( GetRoot(), *pEntry ) );
00840 aScRanges.Format( msSeqRef, SCA_VALID, NULL, formula::FormulaGrammar::CONV_XL_A1 );
00841 }
00842 }
00843
00844 XclExpCondfmt::~XclExpCondfmt()
00845 {
00846 }
00847
00848 bool XclExpCondfmt::IsValid() const
00849 {
00850 return !maCFList.IsEmpty() && !maXclRanges.empty();
00851 }
00852
00853 void XclExpCondfmt::Save( XclExpStream& rStrm )
00854 {
00855 if( IsValid() )
00856 {
00857 XclExpRecord::Save( rStrm );
00858 maCFList.Save( rStrm );
00859 }
00860 }
00861
00862 void XclExpCondfmt::WriteBody( XclExpStream& rStrm )
00863 {
00864 DBG_ASSERT( !maCFList.IsEmpty(), "XclExpCondfmt::WriteBody - no CF records to write" );
00865 DBG_ASSERT( !maXclRanges.empty(), "XclExpCondfmt::WriteBody - no cell ranges found" );
00866
00867 rStrm << static_cast< sal_uInt16 >( maCFList.GetSize() )
00868 << sal_uInt16( 1 )
00869 << maXclRanges.GetEnclosingRange()
00870 << maXclRanges;
00871 }
00872
00873 void XclExpCondfmt::SaveXml( XclExpXmlStream& rStrm )
00874 {
00875 if( !IsValid() )
00876 return;
00877
00878 sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
00879 rWorksheet->startElement( XML_conditionalFormatting,
00880 XML_sqref, XclXmlUtils::ToOString( msSeqRef ).getStr(),
00881
00882 FSEND );
00883 maCFList.SaveXml( rStrm );
00884
00885 rWorksheet->endElement( XML_conditionalFormatting );
00886 }
00887
00888
00889
00890 XclExpCondFormatBuffer::XclExpCondFormatBuffer( const XclExpRoot& rRoot ) :
00891 XclExpRoot( rRoot )
00892 {
00893 if( const ScConditionalFormatList* pCondFmtList = GetDoc().GetCondFormList() )
00894 {
00895 if( const ScConditionalFormatPtr* ppCondFmt = pCondFmtList->GetData() )
00896 {
00897 const ScConditionalFormatPtr* ppCondEnd = ppCondFmt + pCondFmtList->Count();
00898 for( ; ppCondFmt < ppCondEnd; ++ppCondFmt )
00899 {
00900 if( *ppCondFmt )
00901 {
00902 XclExpCondfmtList::RecordRefType xCondfmtRec( new XclExpCondfmt( GetRoot(), **ppCondFmt ) );
00903 if( xCondfmtRec->IsValid() )
00904 maCondfmtList.AppendRecord( xCondfmtRec );
00905 }
00906 }
00907 }
00908 }
00909 }
00910
00911 void XclExpCondFormatBuffer::Save( XclExpStream& rStrm )
00912 {
00913 maCondfmtList.Save( rStrm );
00914 }
00915
00916 void XclExpCondFormatBuffer::SaveXml( XclExpXmlStream& rStrm )
00917 {
00918 maCondfmtList.SaveXml( rStrm );
00919 }
00920
00921
00922
00923 namespace {
00924
00926 void lclWriteDvFormula( XclExpStream& rStrm, const XclTokenArray* pXclTokArr )
00927 {
00928 sal_uInt16 nFmlaSize = pXclTokArr ? pXclTokArr->GetSize() : 0;
00929 rStrm << nFmlaSize << sal_uInt16( 0 );
00930 if( pXclTokArr )
00931 pXclTokArr->WriteArray( rStrm );
00932 }
00933
00935 void lclWriteDvFormula( XclExpStream& rStrm, const XclExpString& rString )
00936 {
00937
00938 rStrm << static_cast< sal_uInt16 >( rString.GetSize() + 1 )
00939 << sal_uInt16( 0 )
00940 << EXC_TOKID_STR
00941 << rString;
00942 }
00943
00944 const char* lcl_GetValidationType( sal_uInt32 nFlags )
00945 {
00946 switch( nFlags & EXC_DV_MODE_MASK )
00947 {
00948 case EXC_DV_MODE_ANY: return "none";
00949 case EXC_DV_MODE_WHOLE: return "whole";
00950 case EXC_DV_MODE_DECIMAL: return "decimal";
00951 case EXC_DV_MODE_LIST: return "list";
00952 case EXC_DV_MODE_DATE: return "date";
00953 case EXC_DV_MODE_TIME: return "time";
00954 case EXC_DV_MODE_TEXTLEN: return "textLength";
00955 case EXC_DV_MODE_CUSTOM: return "custom";
00956 }
00957 return NULL;
00958 }
00959
00960 const char* lcl_GetOperatorType( sal_uInt32 nFlags )
00961 {
00962 switch( nFlags & EXC_DV_COND_MASK )
00963 {
00964 case EXC_DV_COND_BETWEEN: return "between";
00965 case EXC_DV_COND_NOTBETWEEN: return "notBetween";
00966 case EXC_DV_COND_EQUAL: return "equal";
00967 case EXC_DV_COND_NOTEQUAL: return "notEqual";
00968 case EXC_DV_COND_GREATER: return "greaterThan";
00969 case EXC_DV_COND_LESS: return "lessThan";
00970 case EXC_DV_COND_EQGREATER: return "greaterThanOrEqual";
00971 case EXC_DV_COND_EQLESS: return "lessThanOrEqual";
00972 }
00973 return NULL;
00974 }
00975
00976 }
00977
00978
00979
00980 XclExpDV::XclExpDV( const XclExpRoot& rRoot, ULONG nScHandle ) :
00981 XclExpRecord( EXC_ID_DV ),
00982 XclExpRoot( rRoot ),
00983 mnFlags( 0 ),
00984 mnScHandle( nScHandle )
00985 {
00986 if( const ScValidationData* pValData = GetDoc().GetValidationEntry( mnScHandle ) )
00987 {
00988
00989 String aTitle, aText;
00990 bool bShowPrompt = (pValData->GetInput( aTitle, aText ) == TRUE);
00991 if( aTitle.Len() )
00992 maPromptTitle.Assign( aTitle );
00993 else
00994 maPromptTitle.Assign( '\0' );
00995 if( aText.Len() )
00996 maPromptText.Assign( aText );
00997 else
00998 maPromptText.Assign( '\0' );
00999
01000
01001 ScValidErrorStyle eScErrorStyle;
01002 bool bShowError = (pValData->GetErrMsg( aTitle, aText, eScErrorStyle ) == TRUE);
01003 if( aTitle.Len() )
01004 maErrorTitle.Assign( aTitle );
01005 else
01006 maErrorTitle.Assign( '\0' );
01007 if( aText.Len() )
01008 maErrorText.Assign( aText );
01009 else
01010 maErrorText.Assign( '\0' );
01011
01012
01013 switch( pValData->GetDataMode() )
01014 {
01015 case SC_VALID_ANY: mnFlags |= EXC_DV_MODE_ANY; break;
01016 case SC_VALID_WHOLE: mnFlags |= EXC_DV_MODE_WHOLE; break;
01017 case SC_VALID_DECIMAL: mnFlags |= EXC_DV_MODE_DECIMAL; break;
01018 case SC_VALID_LIST: mnFlags |= EXC_DV_MODE_LIST; break;
01019 case SC_VALID_DATE: mnFlags |= EXC_DV_MODE_DATE; break;
01020 case SC_VALID_TIME: mnFlags |= EXC_DV_MODE_TIME; break;
01021 case SC_VALID_TEXTLEN: mnFlags |= EXC_DV_MODE_TEXTLEN; break;
01022 case SC_VALID_CUSTOM: mnFlags |= EXC_DV_MODE_CUSTOM; break;
01023 default: DBG_ERRORFILE( "XclExpDV::XclExpDV - unknown mode" );
01024 }
01025
01026 switch( pValData->GetOperation() )
01027 {
01028 case SC_COND_NONE:
01029 case SC_COND_EQUAL: mnFlags |= EXC_DV_COND_EQUAL; break;
01030 case SC_COND_LESS: mnFlags |= EXC_DV_COND_LESS; break;
01031 case SC_COND_GREATER: mnFlags |= EXC_DV_COND_GREATER; break;
01032 case SC_COND_EQLESS: mnFlags |= EXC_DV_COND_EQLESS; break;
01033 case SC_COND_EQGREATER: mnFlags |= EXC_DV_COND_EQGREATER; break;
01034 case SC_COND_NOTEQUAL: mnFlags |= EXC_DV_COND_NOTEQUAL; break;
01035 case SC_COND_BETWEEN: mnFlags |= EXC_DV_COND_BETWEEN; break;
01036 case SC_COND_NOTBETWEEN: mnFlags |= EXC_DV_COND_NOTBETWEEN; break;
01037 default: DBG_ERRORFILE( "XclExpDV::XclExpDV - unknown condition" );
01038 }
01039 switch( eScErrorStyle )
01040 {
01041 case SC_VALERR_STOP: mnFlags |= EXC_DV_ERROR_STOP; break;
01042 case SC_VALERR_WARNING: mnFlags |= EXC_DV_ERROR_WARNING; break;
01043 case SC_VALERR_INFO: mnFlags |= EXC_DV_ERROR_INFO; break;
01044 case SC_VALERR_MACRO:
01045
01046 mnFlags |= EXC_DV_ERROR_INFO;
01047 maErrorTitle.Assign( '\0' );
01048 break;
01049 default: DBG_ERRORFILE( "XclExpDV::XclExpDV - unknown error style" );
01050 }
01051 ::set_flag( mnFlags, EXC_DV_IGNOREBLANK, pValData->IsIgnoreBlank() );
01052 ::set_flag( mnFlags, EXC_DV_SUPPRESSDROPDOWN, pValData->GetListType() == ValidListType::INVISIBLE );
01053 ::set_flag( mnFlags, EXC_DV_SHOWPROMPT, bShowPrompt );
01054 ::set_flag( mnFlags, EXC_DV_SHOWERROR, bShowError );
01055
01056
01057 XclExpFormulaCompiler& rFmlaComp = GetFormulaCompiler();
01058 ::std::auto_ptr< ScTokenArray > xScTokArr;
01059
01060
01061 xScTokArr.reset( pValData->CreateTokenArry( 0 ) );
01062 if( xScTokArr.get() )
01063 {
01064 if( pValData->GetDataMode() == SC_VALID_LIST )
01065 {
01066 String aString;
01067 if( XclTokenArrayHelper::GetStringList( aString, *xScTokArr, '\n' ) )
01068 {
01069 OUStringBuffer sFormulaBuf;
01070 sFormulaBuf.append( (sal_Unicode) '"' );
01071
01072
01073
01074 mxString1.reset( new XclExpString( EXC_STR_8BITLENGTH ) );
01075 xub_StrLen nTokenCnt = aString.GetTokenCount( '\n' );
01076 xub_StrLen nStringIx = 0;
01077 for( xub_StrLen nToken = 0; nToken < nTokenCnt; ++nToken )
01078 {
01079 String aToken( aString.GetToken( 0, '\n', nStringIx ) );
01080 if( nToken > 0 )
01081 {
01082 mxString1->Append( '\0' );
01083 sFormulaBuf.append( (sal_Unicode) ',' );
01084 }
01085 mxString1->Append( aToken );
01086 sFormulaBuf.append( XclXmlUtils::ToOUString( aToken ) );
01087 }
01088 ::set_flag( mnFlags, EXC_DV_STRINGLIST );
01089
01090 sFormulaBuf.append( (sal_Unicode) '"' );
01091 msFormula1 = sFormulaBuf.makeStringAndClear();
01092 }
01093 else
01094 {
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104 mxTokArr1 = rFmlaComp.CreateFormula( EXC_FMLATYPE_LISTVAL, *xScTokArr );
01105 msFormula1 = XclXmlUtils::ToOUString( GetDoc(), pValData->GetSrcPos(), xScTokArr.get() );
01106 }
01107 }
01108 else
01109 {
01110
01111 mxTokArr1 = rFmlaComp.CreateFormula( EXC_FMLATYPE_DATAVAL, *xScTokArr );
01112 msFormula1 = XclXmlUtils::ToOUString( GetDoc(), pValData->GetSrcPos(), xScTokArr.get() );
01113 }
01114 }
01115
01116
01117 xScTokArr.reset( pValData->CreateTokenArry( 1 ) );
01118 if( xScTokArr.get() )
01119 {
01120 mxTokArr2 = rFmlaComp.CreateFormula( EXC_FMLATYPE_DATAVAL, *xScTokArr );
01121 msFormula2 = XclXmlUtils::ToOUString( GetDoc(), pValData->GetSrcPos(), xScTokArr.get() );
01122 }
01123 }
01124 else
01125 {
01126 DBG_ERRORFILE( "XclExpDV::XclExpDV - missing core data" );
01127 mnScHandle = ULONG_MAX;
01128 }
01129 }
01130
01131 XclExpDV::~XclExpDV()
01132 {
01133 }
01134
01135 void XclExpDV::InsertCellRange( const ScRange& rRange )
01136 {
01137 maScRanges.Join( rRange );
01138 }
01139
01140 bool XclExpDV::Finalize()
01141 {
01142 GetAddressConverter().ConvertRangeList( maXclRanges, maScRanges, true );
01143 return (mnScHandle != ULONG_MAX) && !maXclRanges.empty();
01144 }
01145
01146 void XclExpDV::WriteBody( XclExpStream& rStrm )
01147 {
01148
01149 rStrm << mnFlags << maPromptTitle << maErrorTitle << maPromptText << maErrorText;
01150
01151 if( mxString1.get() )
01152 lclWriteDvFormula( rStrm, *mxString1 );
01153 else
01154 lclWriteDvFormula( rStrm, mxTokArr1.get() );
01155 lclWriteDvFormula( rStrm, mxTokArr2.get() );
01156
01157 rStrm << maXclRanges;
01158 }
01159
01160 void XclExpDV::SaveXml( XclExpXmlStream& rStrm )
01161 {
01162 sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
01163 rWorksheet->startElement( XML_dataValidation,
01164 XML_allowBlank, XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_DV_IGNOREBLANK ) ),
01165 XML_error, XESTRING_TO_PSZ( maErrorText ),
01166
01167 XML_errorTitle, XESTRING_TO_PSZ( maErrorTitle ),
01168
01169 XML_operator, lcl_GetOperatorType( mnFlags ),
01170 XML_prompt, XESTRING_TO_PSZ( maPromptText ),
01171 XML_promptTitle, XESTRING_TO_PSZ( maPromptTitle ),
01172 XML_showDropDown, XclXmlUtils::ToPsz( ! ::get_flag( mnFlags, EXC_DV_SUPPRESSDROPDOWN ) ),
01173 XML_showErrorMessage, XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_DV_SHOWERROR ) ),
01174 XML_showInputMessage, XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_DV_SHOWPROMPT ) ),
01175 XML_sqref, XclXmlUtils::ToOString( maScRanges ).getStr(),
01176 XML_type, lcl_GetValidationType( mnFlags ),
01177 FSEND );
01178 if( msFormula1.getLength() )
01179 {
01180 rWorksheet->startElement( XML_formula1, FSEND );
01181 rWorksheet->writeEscaped( msFormula1 );
01182 rWorksheet->endElement( XML_formula1 );
01183 }
01184 if( msFormula2.getLength() )
01185 {
01186 rWorksheet->startElement( XML_formula2, FSEND );
01187 rWorksheet->writeEscaped( msFormula2 );
01188 rWorksheet->endElement( XML_formula2 );
01189 }
01190 rWorksheet->endElement( XML_dataValidation );
01191 }
01192
01193
01194
01195 XclExpDval::XclExpDval( const XclExpRoot& rRoot ) :
01196 XclExpRecord( EXC_ID_DVAL, 18 ),
01197 XclExpRoot( rRoot )
01198 {
01199 }
01200
01201 XclExpDval::~XclExpDval()
01202 {
01203 }
01204
01205 void XclExpDval::InsertCellRange( const ScRange& rRange, ULONG nScHandle )
01206 {
01207 if( GetBiff() == EXC_BIFF8 )
01208 {
01209 XclExpDV& rDVRec = SearchOrCreateDv( nScHandle );
01210 rDVRec.InsertCellRange( rRange );
01211 }
01212 }
01213
01214 void XclExpDval::Save( XclExpStream& rStrm )
01215 {
01216
01217 size_t nPos = maDVList.GetSize();
01218 while( nPos )
01219 {
01220 --nPos;
01221 XclExpDVRef xDVRec = maDVList.GetRecord( nPos );
01222 if( !xDVRec->Finalize() )
01223 maDVList.RemoveRecord( nPos );
01224 }
01225
01226
01227 if( !maDVList.IsEmpty() )
01228 {
01229 XclExpRecord::Save( rStrm );
01230 maDVList.Save( rStrm );
01231 }
01232 }
01233
01234 void XclExpDval::SaveXml( XclExpXmlStream& rStrm )
01235 {
01236 if( maDVList.IsEmpty() )
01237 return;
01238
01239 sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
01240 rWorksheet->startElement( XML_dataValidations,
01241 XML_count, OString::valueOf( (sal_Int32) maDVList.GetSize() ).getStr(),
01242
01243
01244
01245 FSEND );
01246 maDVList.SaveXml( rStrm );
01247 rWorksheet->endElement( XML_dataValidations );
01248 }
01249
01250 XclExpDV& XclExpDval::SearchOrCreateDv( ULONG nScHandle )
01251 {
01252
01253 if( mxLastFoundDV.get() && (mxLastFoundDV->GetScHandle() == nScHandle) )
01254 return *mxLastFoundDV;
01255
01256
01257 size_t nCurrPos = 0;
01258 if( !maDVList.IsEmpty() )
01259 {
01260 size_t nFirstPos = 0;
01261 size_t nLastPos = maDVList.GetSize() - 1;
01262 bool bLoop = true;
01263 ULONG nCurrScHandle = ::std::numeric_limits< ULONG >::max();
01264 while( (nFirstPos <= nLastPos) && bLoop )
01265 {
01266 nCurrPos = (nFirstPos + nLastPos) / 2;
01267 mxLastFoundDV = maDVList.GetRecord( nCurrPos );
01268 nCurrScHandle = mxLastFoundDV->GetScHandle();
01269 if( nCurrScHandle == nScHandle )
01270 bLoop = false;
01271 else if( nCurrScHandle < nScHandle )
01272 nFirstPos = nCurrPos + 1;
01273 else if( nCurrPos )
01274 nLastPos = nCurrPos - 1;
01275 else
01276 bLoop = false;
01277 }
01278 if( nCurrScHandle == nScHandle )
01279 return *mxLastFoundDV;
01280 else if( nCurrScHandle < nScHandle )
01281 ++nCurrPos;
01282 }
01283
01284
01285 mxLastFoundDV.reset( new XclExpDV( *this, nScHandle ) );
01286 maDVList.InsertRecord( mxLastFoundDV, nCurrPos );
01287 return *mxLastFoundDV;
01288 }
01289
01290 void XclExpDval::WriteBody( XclExpStream& rStrm )
01291 {
01292 rStrm.WriteZeroBytes( 10 );
01293 rStrm << EXC_DVAL_NOOBJ << static_cast< sal_uInt32 >( maDVList.GetSize() );
01294 }
01295
01296
01297
01298 XclExpWebQuery::XclExpWebQuery(
01299 const String& rRangeName,
01300 const String& rUrl,
01301 const String& rSource,
01302 sal_Int32 nRefrSecs ) :
01303 maDestRange( rRangeName ),
01304 maUrl( rUrl ),
01305
01306 mnRefresh( ulimit_cast< sal_Int16 >( (nRefrSecs + 59L) / 60L ) ),
01307 mbEntireDoc( false )
01308 {
01309
01310 xub_StrLen nTokenCnt = rSource.GetTokenCount( ';' );
01311 String aNewTables, aAppendTable;
01312 xub_StrLen nStringIx = 0;
01313 bool bExitLoop = false;
01314 for( xub_StrLen nToken = 0; (nToken < nTokenCnt) && !bExitLoop; ++nToken )
01315 {
01316 String aToken( rSource.GetToken( 0, ';', nStringIx ) );
01317 mbEntireDoc = ScfTools::IsHTMLDocName( aToken );
01318 bExitLoop = mbEntireDoc || ScfTools::IsHTMLTablesName( aToken );
01319 if( !bExitLoop && ScfTools::GetHTMLNameFromName( aToken, aAppendTable ) )
01320 ScGlobal::AddToken( aNewTables, aAppendTable, ',' );
01321 }
01322
01323 if( !bExitLoop )
01324 {
01325 if( aNewTables.Len() )
01326 mxQryTables.reset( new XclExpString( aNewTables ) );
01327 else
01328 mbEntireDoc = true;
01329 }
01330 }
01331
01332 XclExpWebQuery::~XclExpWebQuery()
01333 {
01334 }
01335
01336 void XclExpWebQuery::Save( XclExpStream& rStrm )
01337 {
01338 DBG_ASSERT( !mbEntireDoc || !mxQryTables.get(), "XclExpWebQuery::Save - illegal mode" );
01339 sal_uInt16 nFlags;
01340
01341
01342 rStrm.StartRecord( EXC_ID_QSI, 10 + maDestRange.GetSize() );
01343 rStrm << EXC_QSI_DEFAULTFLAGS
01344 << sal_uInt16( 0x0010 )
01345 << sal_uInt16( 0x0012 )
01346 << sal_uInt32( 0x00000000 )
01347 << maDestRange;
01348 rStrm.EndRecord();
01349
01350
01351 nFlags = 0;
01352 ::insert_value( nFlags, EXC_PQRYTYPE_WEBQUERY, 0, 3 );
01353 ::set_flag( nFlags, EXC_PQRY_WEBQUERY );
01354 ::set_flag( nFlags, EXC_PQRY_TABLES, !mbEntireDoc );
01355 rStrm.StartRecord( EXC_ID_PQRY, 12 );
01356 rStrm << nFlags
01357 << sal_uInt16( 0x0000 )
01358 << sal_uInt16( 0x0001 );
01359 rStrm.WriteZeroBytes( 6 );
01360 rStrm.EndRecord();
01361
01362
01363 rStrm.StartRecord( EXC_ID_WQSTRING, maUrl.GetSize() );
01364 rStrm << maUrl;
01365 rStrm.EndRecord();
01366
01367
01368 rStrm.StartRecord( EXC_ID_0802, 16 + maDestRange.GetSize() );
01369 rStrm << EXC_ID_0802;
01370 rStrm.WriteZeroBytes( 6 );
01371 rStrm << sal_uInt16( 0x0003 )
01372 << sal_uInt32( 0x00000000 )
01373 << sal_uInt16( 0x0010 )
01374 << maDestRange;
01375 rStrm.EndRecord();
01376
01377
01378 nFlags = mxQryTables.get() ? EXC_WQSETT_SPECTABLES : EXC_WQSETT_ALL;
01379 rStrm.StartRecord( EXC_ID_WQSETT, 28 );
01380 rStrm << EXC_ID_WQSETT
01381 << sal_uInt16( 0x0000 )
01382 << sal_uInt16( 0x0004 )
01383 << sal_uInt16( 0x0000 )
01384 << EXC_WQSETT_DEFAULTFLAGS
01385 << nFlags;
01386 rStrm.WriteZeroBytes( 10 );
01387 rStrm << mnRefresh
01388 << EXC_WQSETT_FORMATFULL
01389 << sal_uInt16( 0x0000 );
01390 rStrm.EndRecord();
01391
01392
01393 if( mxQryTables.get() )
01394 {
01395 rStrm.StartRecord( EXC_ID_WQTABLES, 4 + mxQryTables->GetSize() );
01396 rStrm << EXC_ID_WQTABLES
01397 << sal_uInt16( 0x0000 )
01398 << *mxQryTables;
01399 rStrm.EndRecord();
01400 }
01401 }
01402
01403
01404
01405 XclExpWebQueryBuffer::XclExpWebQueryBuffer( const XclExpRoot& rRoot )
01406 {
01407 SCTAB nScTab = rRoot.GetCurrScTab();
01408 SfxObjectShell* pShell = rRoot.GetDocShell();
01409 if( !pShell ) return;
01410 ScfPropertySet aModelProp( pShell->GetModel() );
01411 if( !aModelProp.Is() ) return;
01412
01413 Reference< XAreaLinks > xAreaLinks;
01414 aModelProp.GetProperty( xAreaLinks, CREATE_OUSTRING( SC_UNO_AREALINKS ) );
01415 Reference< XIndexAccess > xLinksIA( xAreaLinks, UNO_QUERY );
01416 if( !xLinksIA.is() ) return;
01417
01418 for( sal_Int32 nIndex = 0, nCount = xLinksIA->getCount(); nIndex < nCount; ++nIndex )
01419 {
01420 Reference< XAreaLink > xAreaLink( xLinksIA->getByIndex( nIndex ), UNO_QUERY );
01421 if( xAreaLink.is() )
01422 {
01423 CellRangeAddress aDestRange( xAreaLink->getDestArea() );
01424 if( static_cast< SCTAB >( aDestRange.Sheet ) == nScTab )
01425 {
01426 ScfPropertySet aLinkProp( xAreaLink );
01427 OUString aFilter;
01428 if( aLinkProp.GetProperty( aFilter, CREATE_OUSTRING( SC_UNONAME_FILTER ) ) &&
01429 (aFilter == CREATE_OUSTRING( EXC_WEBQRY_FILTER )) )
01430 {
01431
01432 OUString aUrl;
01433 sal_Int32 nRefresh = 0;
01434
01435
01436 aLinkProp.GetProperty( aUrl, CREATE_OUSTRING( SC_UNONAME_LINKURL ) );
01437 aLinkProp.GetProperty( nRefresh, CREATE_OUSTRING( SC_UNONAME_REFDELAY ) );
01438
01439 String aAbsDoc( ScGlobal::GetAbsDocName( aUrl, pShell ) );
01440 INetURLObject aUrlObj( aAbsDoc );
01441 String aWebQueryUrl( aUrlObj.getFSysPath( INetURLObject::FSYS_DOS ) );
01442 if( !aWebQueryUrl.Len() )
01443 aWebQueryUrl = aAbsDoc;
01444
01445
01446 String aRangeName;
01447 ScRange aScDestRange;
01448 ScUnoConversion::FillScRange( aScDestRange, aDestRange );
01449 if( const ScRangeData* pRangeData = rRoot.GetNamedRanges().GetRangeAtBlock( aScDestRange ) )
01450 {
01451 aRangeName = pRangeData->GetName();
01452 }
01453 else
01454 {
01455 XclExpFormulaCompiler& rFmlaComp = rRoot.GetFormulaCompiler();
01456 XclExpNameManager& rNameMgr = rRoot.GetNameManager();
01457
01458
01459 XclTokenArrayRef xTokArr = rFmlaComp.CreateFormula( EXC_FMLATYPE_WQUERY, aScDestRange );
01460 sal_uInt16 nNameIdx = rNameMgr.InsertUniqueName( aUrlObj.getBase(), xTokArr, nScTab );
01461 aRangeName = rNameMgr.GetOrigName( nNameIdx );
01462 }
01463
01464
01465 if( aRangeName.Len() )
01466 AppendNewRecord( new XclExpWebQuery(
01467 aRangeName, aWebQueryUrl, xAreaLink->getSourceArea(), nRefresh ) );
01468 }
01469 }
01470 }
01471 }
01472 }
01473
01474
01475