1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_scfilt.hxx"
26
27
28
29 //------------------------------------------------------------------------
30
31 #include "excrecds.hxx"
32
33 #include <map>
34 #include <filter/msfilter/countryid.hxx>
35
36 #include "scitems.hxx"
37 #include <editeng/eeitem.hxx>
38
39 #include <sfx2/objsh.hxx>
40
41 #include <editeng/editdata.hxx>
42 #include <editeng/editeng.hxx>
43 #include <editeng/editobj.hxx>
44 #include <editeng/editstat.hxx>
45
46 #include <editeng/flditem.hxx>
47 #include <editeng/flstitem.hxx>
48
49 #include <svx/algitem.hxx>
50 #include <editeng/boxitem.hxx>
51 #include <editeng/brshitem.hxx>
52 #include <svx/pageitem.hxx>
53 #include <editeng/paperinf.hxx>
54 #include <editeng/sizeitem.hxx>
55 #include <editeng/ulspitem.hxx>
56 #include <editeng/fhgtitem.hxx>
57 #include <editeng/escpitem.hxx>
58 #include <svl/intitem.hxx>
59 #include <svl/zforlist.hxx>
60 #include <svl/zformat.hxx>
61 #include <svtools/ctrltool.hxx>
62
63 #define _SVSTDARR_USHORTS
64 #include <svl/svstdarr.hxx>
65
66 #include <string.h>
67
68 #include "global.hxx"
69 #include "globstr.hrc"
70 #include "docpool.hxx"
71 #include "patattr.hxx"
72 #include "cell.hxx"
73 #include "document.hxx"
74 #include "scextopt.hxx"
75 #include "patattr.hxx"
76 #include "attrib.hxx"
77 #include "progress.hxx"
78 #include "dociter.hxx"
79 #include "rangenam.hxx"
80 #include "dbcolect.hxx"
81 #include "stlsheet.hxx"
82 #include "stlpool.hxx"
83 #include "editutil.hxx"
84 #include "formula/errorcodes.hxx"
85
86 #include "excdoc.hxx"
87 #include "xeescher.hxx"
88 #include "xeformula.hxx"
89 #include "xelink.hxx"
90 #include "xename.hxx"
91 #include "xecontent.hxx"
92
93 #include "xcl97rec.hxx"
94
95 using namespace ::oox;
96
97 using ::com::sun::star::uno::Sequence;
98 using ::rtl::OString;
99
100 //--------------------------------------------------------- class ExcDummy_00 -
101 const sal_uInt8 ExcDummy_00::pMyData[] = {
102 0x5c, 0x00, 0x20, 0x00, 0x04, 'C', 'a', 'l', 'c', // WRITEACCESS
103 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
104 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
105 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
106 };
107 const sal_Size ExcDummy_00::nMyLen = sizeof( ExcDummy_00::pMyData );
108
109 //-------------------------------------------------------- class ExcDummy_04x -
110 const sal_uInt8 ExcDummy_040::pMyData[] = {
111 0x40, 0x00, 0x02, 0x00, 0x00, 0x00, // BACKUP
112 0x8d, 0x00, 0x02, 0x00, 0x00, 0x00, // HIDEOBJ
113 };
114 const sal_Size ExcDummy_040::nMyLen = sizeof( ExcDummy_040::pMyData );
115
116 const sal_uInt8 ExcDummy_041::pMyData[] = {
117 0x0e, 0x00, 0x02, 0x00, 0x01, 0x00, // PRECISION
118 0xda, 0x00, 0x02, 0x00, 0x00, 0x00 // BOOKBOOL
119 };
120 const sal_Size ExcDummy_041::nMyLen = sizeof( ExcDummy_041::pMyData );
121
122 //-------------------------------------------------------- class ExcDummy_02a -
123 const sal_uInt8 ExcDummy_02a::pMyData[] = {
124 0x0d, 0x00, 0x02, 0x00, 0x01, 0x00, // CALCMODE
125 0x0c, 0x00, 0x02, 0x00, 0x64, 0x00, // CALCCOUNT
126 0x0f, 0x00, 0x02, 0x00, 0x01, 0x00, // REFMODE
127 0x11, 0x00, 0x02, 0x00, 0x00, 0x00, // ITERATION
128 0x10, 0x00, 0x08, 0x00, 0xfc, 0xa9, 0xf1, 0xd2, 0x4d, // DELTA
129 0x62, 0x50, 0x3f,
130 0x5f, 0x00, 0x02, 0x00, 0x01, 0x00 // SAVERECALC
131 };
132 const sal_Size ExcDummy_02a::nMyLen = sizeof( ExcDummy_02a::pMyData );
133
134 //----------------------------------------------------------- class ExcRecord -
135
Save(XclExpStream & rStrm)136 void ExcRecord::Save( XclExpStream& rStrm )
137 {
138 SetRecHeader( GetNum(), GetLen() );
139 XclExpRecord::Save( rStrm );
140 }
141
SaveCont(XclExpStream &)142 void ExcRecord::SaveCont( XclExpStream& /*rStrm*/ )
143 {
144 }
145
WriteBody(XclExpStream & rStrm)146 void ExcRecord::WriteBody( XclExpStream& rStrm )
147 {
148 SaveCont( rStrm );
149 }
150
151
152 //--------------------------------------------------------- class ExcEmptyRec -
153
Save(XclExpStream &)154 void ExcEmptyRec::Save( XclExpStream& /*rStrm*/ )
155 {
156 }
157
158
GetNum() const159 sal_uInt16 ExcEmptyRec::GetNum() const
160 {
161 return 0;
162 }
163
164
GetLen() const165 sal_Size ExcEmptyRec::GetLen() const
166 {
167 return 0;
168 }
169
170
171
172 //------------------------------------------------------- class ExcRecordList -
173
~ExcRecordList()174 ExcRecordList::~ExcRecordList()
175 {
176 for( ExcRecord* pRec = First(); pRec; pRec = Next() )
177 delete pRec;
178 }
179
180
Save(XclExpStream & rStrm)181 void ExcRecordList::Save( XclExpStream& rStrm )
182 {
183 for( ExcRecord* pRec = First(); pRec; pRec = Next() )
184 pRec->Save( rStrm );
185 }
186
187
188
189 //--------------------------------------------------------- class ExcDummyRec -
190
Save(XclExpStream & rStrm)191 void ExcDummyRec::Save( XclExpStream& rStrm )
192 {
193 rStrm.Write( GetData(), GetLen() ); // raw write mode
194 }
195
196
GetNum(void) const197 sal_uInt16 ExcDummyRec::GetNum( void ) const
198 {
199 return 0x0000;
200 }
201
202
203
204 //------------------------------------------------------- class ExcBoolRecord -
205
SaveCont(XclExpStream & rStrm)206 void ExcBoolRecord::SaveCont( XclExpStream& rStrm )
207 {
208 rStrm << (sal_uInt16)(bVal ? 0x0001 : 0x0000);
209 }
210
211
GetLen(void) const212 sal_Size ExcBoolRecord::GetLen( void ) const
213 {
214 return 2;
215 }
216
217
218
219
220 //--------------------------------------------------------- class ExcBof_Base -
221
ExcBof_Base()222 ExcBof_Base::ExcBof_Base() :
223 nRupBuild( 0x096C ), // copied from Excel
224 nRupYear( 0x07C9 ) // copied from Excel
225 {
226 }
227
228
229
230 //-------------------------------------------------------------- class ExcBof -
231
ExcBof(void)232 ExcBof::ExcBof( void )
233 {
234 nDocType = 0x0010;
235 nVers = 0x0500;
236 }
237
238
SaveCont(XclExpStream & rStrm)239 void ExcBof::SaveCont( XclExpStream& rStrm )
240 {
241 rStrm << nVers << nDocType << nRupBuild << nRupYear;
242 }
243
244
GetNum(void) const245 sal_uInt16 ExcBof::GetNum( void ) const
246 {
247 return 0x0809;
248 }
249
250
GetLen(void) const251 sal_Size ExcBof::GetLen( void ) const
252 {
253 return 8;
254 }
255
256
257
258 //------------------------------------------------------------- class ExcBofW -
259
ExcBofW(void)260 ExcBofW::ExcBofW( void )
261 {
262 nDocType = 0x0005;
263 nVers = 0x0500;
264 }
265
266
SaveCont(XclExpStream & rStrm)267 void ExcBofW::SaveCont( XclExpStream& rStrm )
268 {
269 rStrm << nVers << nDocType << nRupBuild << nRupYear;
270 }
271
272
273
GetNum(void) const274 sal_uInt16 ExcBofW::GetNum( void ) const
275 {
276 return 0x0809;
277 }
278
279
280
GetLen(void) const281 sal_Size ExcBofW::GetLen( void ) const
282 {
283 return 8;
284 }
285
286
287
288 //-------------------------------------------------------------- class ExcEof -
289
GetNum(void) const290 sal_uInt16 ExcEof::GetNum( void ) const
291 {
292 return 0x000A;
293 }
294
295
GetLen(void) const296 sal_Size ExcEof::GetLen( void ) const
297 {
298 return 0;
299 }
300
301
302
303 //--------------------------------------------------------- class ExcDummy_00 -
304
GetLen(void) const305 sal_Size ExcDummy_00::GetLen( void ) const
306 {
307 return nMyLen;
308 }
309
310
GetData(void) const311 const sal_uInt8* ExcDummy_00::GetData( void ) const
312 {
313 return pMyData;
314 }
315
316
317
318 //-------------------------------------------------------- class ExcDummy_04x -
319
GetLen(void) const320 sal_Size ExcDummy_040::GetLen( void ) const
321 {
322 return nMyLen;
323 }
324
325
GetData(void) const326 const sal_uInt8* ExcDummy_040::GetData( void ) const
327 {
328 return pMyData;
329 }
330
331
332
333
GetLen(void) const334 sal_Size ExcDummy_041::GetLen( void ) const
335 {
336 return nMyLen;
337 }
338
339
GetData(void) const340 const sal_uInt8* ExcDummy_041::GetData( void ) const
341 {
342 return pMyData;
343 }
344
345
346
347 //------------------------------------------------------------- class Exc1904 -
348
Exc1904(ScDocument & rDoc)349 Exc1904::Exc1904( ScDocument& rDoc )
350 {
351 Date* pDate = rDoc.GetFormatTable()->GetNullDate();
352 bVal = pDate ? (*pDate == Date( 1, 1, 1904 )) : sal_False;
353 }
354
355
GetNum(void) const356 sal_uInt16 Exc1904::GetNum( void ) const
357 {
358 return 0x0022;
359 }
360
361
SaveXml(XclExpXmlStream & rStrm)362 void Exc1904::SaveXml( XclExpXmlStream& rStrm )
363 {
364 rStrm.WriteAttributes(
365 XML_date1904, XclXmlUtils::ToPsz( bVal ),
366 FSEND );
367 }
368
369
370
371 //------------------------------------------------------ class ExcBundlesheet -
372
ExcBundlesheetBase(RootData & rRootData,SCTAB nTabNum)373 ExcBundlesheetBase::ExcBundlesheetBase( RootData& rRootData, SCTAB nTabNum ) :
374 nStrPos( STREAM_SEEK_TO_END ),
375 nOwnPos( STREAM_SEEK_TO_END ),
376 nGrbit( rRootData.pER->GetTabInfo().IsVisibleTab( nTabNum ) ? 0x0000 : 0x0001 ),
377 nTab( nTabNum )
378 {
379 }
380
381
ExcBundlesheetBase()382 ExcBundlesheetBase::ExcBundlesheetBase() :
383 nStrPos( STREAM_SEEK_TO_END ),
384 nOwnPos( STREAM_SEEK_TO_END ),
385 nGrbit( 0x0000 ),
386 nTab( SCTAB_GLOBAL )
387 {
388 }
389
390
UpdateStreamPos(XclExpStream & rStrm)391 void ExcBundlesheetBase::UpdateStreamPos( XclExpStream& rStrm )
392 {
393 rStrm.SetSvStreamPos( nOwnPos );
394 rStrm.DisableEncryption();
395 rStrm << static_cast<sal_uInt32>(nStrPos);
396 rStrm.EnableEncryption();
397 }
398
399
GetNum(void) const400 sal_uInt16 ExcBundlesheetBase::GetNum( void ) const
401 {
402 return 0x0085;
403 }
404
405
406
407
ExcBundlesheet(RootData & rRootData,SCTAB _nTab)408 ExcBundlesheet::ExcBundlesheet( RootData& rRootData, SCTAB _nTab ) :
409 ExcBundlesheetBase( rRootData, _nTab )
410 {
411 String sTabName = rRootData.pER->GetTabInfo().GetScTabName( _nTab );
412 DBG_ASSERT( sTabName.Len() < 256, "ExcBundlesheet::ExcBundlesheet - table name too long" );
413 aName = ByteString( sTabName, rRootData.pER->GetTextEncoding() );
414 }
415
416
SaveCont(XclExpStream & rStrm)417 void ExcBundlesheet::SaveCont( XclExpStream& rStrm )
418 {
419 nOwnPos = rStrm.GetSvStreamPos();
420 rStrm << (sal_uInt32) 0x00000000 // dummy (stream position of the sheet)
421 << nGrbit;
422 rStrm.WriteByteString( aName ); // 8 bit length, max 255 chars
423 }
424
425
GetLen() const426 sal_Size ExcBundlesheet::GetLen() const
427 {
428 return 7 + Min( aName.Len(), (xub_StrLen) 255 );
429 }
430
431
432 //--------------------------------------------------------- class ExcDummy_02 -
433
GetLen(void) const434 sal_Size ExcDummy_02a::GetLen( void ) const
435 {
436 return nMyLen;
437 }
438
GetData(void) const439 const sal_uInt8* ExcDummy_02a::GetData( void ) const
440 {
441 return pMyData;
442 }
443 //--------------------------------------------------------- class ExcDummy_02 -
444
XclExpCountry(const XclExpRoot & rRoot)445 XclExpCountry::XclExpCountry( const XclExpRoot& rRoot ) :
446 XclExpRecord( EXC_ID_COUNTRY, 4 )
447 {
448 /* #i31530# set document country as UI country too -
449 needed for correct behaviour of number formats. */
450 mnUICountry = mnDocCountry = static_cast< sal_uInt16 >(
451 ::msfilter::ConvertLanguageToCountry( rRoot.GetDocLanguage() ) );
452 }
453
WriteBody(XclExpStream & rStrm)454 void XclExpCountry::WriteBody( XclExpStream& rStrm )
455 {
456 rStrm << mnUICountry << mnDocCountry;
457 }
458
459 // XclExpWsbool ===============================================================
460
XclExpWsbool(bool bFitToPages,SCTAB nScTab,XclExpFilterManager * pManager)461 XclExpWsbool::XclExpWsbool( bool bFitToPages, SCTAB nScTab, XclExpFilterManager* pManager )
462 : XclExpUInt16Record( EXC_ID_WSBOOL, EXC_WSBOOL_DEFAULTFLAGS )
463 , mnScTab( nScTab )
464 , mpManager( pManager )
465 {
466 if( bFitToPages )
467 SetValue( GetValue() | EXC_WSBOOL_FITTOPAGE );
468 }
469
SaveXml(XclExpXmlStream & rStrm)470 void XclExpWsbool::SaveXml( XclExpXmlStream& rStrm )
471 {
472 sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
473 rWorksheet->startElement( XML_sheetPr,
474 // OOXTODO: XML_syncHorizontal,
475 // OOXTODO: XML_syncVertical,
476 // OOXTODO: XML_syncRef,
477 // OOXTODO: XML_transitionEvaluation,
478 // OOXTODO: XML_transitionEntry,
479 // OOXTODO: XML_published,
480 // OOXTODO: XML_codeName,
481 XML_filterMode, mpManager ? XclXmlUtils::ToPsz( mpManager->HasFilterMode( mnScTab ) ) : NULL,
482 // OOXTODO: XML_enableFormatConditionsCalculation,
483 FSEND );
484 // OOXTODO: elements XML_tabColor, XML_outlinePr
485 rWorksheet->singleElement( XML_pageSetUpPr,
486 // OOXTODO: XML_autoPageBreaks,
487 XML_fitToPage, XclXmlUtils::ToPsz( GetValue() & EXC_WSBOOL_FITTOPAGE ),
488 FSEND );
489 rWorksheet->endElement( XML_sheetPr );
490 }
491
492
493 // XclExpWindowProtection ===============================================================
494
XclExpWindowProtection(bool bValue)495 XclExpWindowProtection::XclExpWindowProtection(bool bValue) :
496 XclExpBoolRecord(EXC_ID_WINDOWPROTECT, bValue)
497 {
498 }
499
SaveXml(XclExpXmlStream & rStrm)500 void XclExpWindowProtection::SaveXml( XclExpXmlStream& rStrm )
501 {
502 rStrm.WriteAttributes(
503 XML_lockWindows, XclXmlUtils::ToPsz( GetBool() ),
504 FSEND );
505 }
506
507 // XclExpDocProtection ===============================================================
508
XclExpProtection(bool bValue)509 XclExpProtection::XclExpProtection(bool bValue) :
510 XclExpBoolRecord(EXC_ID_PROTECT, bValue)
511 {
512 }
513
514 // ============================================================================
515
XclExpPassHash(const Sequence<sal_Int8> & aHash)516 XclExpPassHash::XclExpPassHash(const Sequence<sal_Int8>& aHash) :
517 XclExpRecord(EXC_ID_PASSWORD, 2),
518 mnHash(0x0000)
519 {
520 if (aHash.getLength() >= 2)
521 {
522 mnHash = ((aHash[0] << 8) & 0xFFFF);
523 mnHash |= (aHash[1] & 0xFF);
524 }
525 }
526
~XclExpPassHash()527 XclExpPassHash::~XclExpPassHash()
528 {
529 }
530
WriteBody(XclExpStream & rStrm)531 void XclExpPassHash::WriteBody(XclExpStream& rStrm)
532 {
533 rStrm << mnHash;
534 }
535
536 // ============================================================================
537
XclExpFiltermode()538 XclExpFiltermode::XclExpFiltermode() :
539 XclExpEmptyRecord( EXC_ID_FILTERMODE )
540 {
541 }
542
543 // ----------------------------------------------------------------------------
544
XclExpAutofilterinfo(const ScAddress & rStartPos,SCCOL nScCol)545 XclExpAutofilterinfo::XclExpAutofilterinfo( const ScAddress& rStartPos, SCCOL nScCol ) :
546 XclExpUInt16Record( EXC_ID_AUTOFILTERINFO, static_cast< sal_uInt16 >( nScCol ) ),
547 maStartPos( rStartPos )
548 {
549 }
550
551 // ----------------------------------------------------------------------------
552
ExcFilterCondition()553 ExcFilterCondition::ExcFilterCondition() :
554 nType( EXC_AFTYPE_NOTUSED ),
555 nOper( EXC_AFOPER_EQUAL ),
556 fVal( 0.0 ),
557 pText( NULL )
558 {
559 }
560
~ExcFilterCondition()561 ExcFilterCondition::~ExcFilterCondition()
562 {
563 if( pText )
564 delete pText;
565 }
566
GetTextBytes() const567 sal_Size ExcFilterCondition::GetTextBytes() const
568 {
569 return pText ? (1 + pText->GetBufferSize()) : 0;
570 }
571
SetCondition(sal_uInt8 nTp,sal_uInt8 nOp,double fV,String * pT)572 void ExcFilterCondition::SetCondition( sal_uInt8 nTp, sal_uInt8 nOp, double fV, String* pT )
573 {
574 nType = nTp;
575 nOper = nOp;
576 fVal = fV;
577
578 delete pText;
579 pText = pT ? new XclExpString( *pT, EXC_STR_8BITLENGTH ) : NULL;
580 }
581
Save(XclExpStream & rStrm)582 void ExcFilterCondition::Save( XclExpStream& rStrm )
583 {
584 rStrm << nType << nOper;
585 switch( nType )
586 {
587 case EXC_AFTYPE_DOUBLE:
588 rStrm << fVal;
589 break;
590 case EXC_AFTYPE_STRING:
591 DBG_ASSERT( pText, "ExcFilterCondition::Save() -- pText is NULL!" );
592 rStrm << (sal_uInt32)0 << (sal_uInt8) pText->Len() << (sal_uInt16)0 << (sal_uInt8)0;
593 break;
594 case EXC_AFTYPE_BOOLERR:
595 rStrm << (sal_uInt8)0 << (sal_uInt8)((fVal != 0) ? 1 : 0) << (sal_uInt32)0 << (sal_uInt16)0;
596 break;
597 default:
598 rStrm << (sal_uInt32)0 << (sal_uInt32)0;
599 }
600 }
601
lcl_GetOperator(sal_uInt8 nOper)602 static const char* lcl_GetOperator( sal_uInt8 nOper )
603 {
604 switch( nOper )
605 {
606 case EXC_AFOPER_EQUAL: return "equal";
607 case EXC_AFOPER_GREATER: return "greaterThan";
608 case EXC_AFOPER_GREATEREQUAL: return "greaterThanOrEqual";
609 case EXC_AFOPER_LESS: return "lessThan";
610 case EXC_AFOPER_LESSEQUAL: return "lessThanOrEqual";
611 case EXC_AFOPER_NOTEQUAL: return "notEqual";
612 case EXC_AFOPER_NONE:
613 default: return "**none**";
614 }
615 }
616
lcl_GetValue(sal_uInt8 nType,double fVal,XclExpString * pStr)617 static OString lcl_GetValue( sal_uInt8 nType, double fVal, XclExpString* pStr )
618 {
619 switch( nType )
620 {
621 case EXC_AFTYPE_STRING: return XclXmlUtils::ToOString( *pStr );
622 case EXC_AFTYPE_DOUBLE: return OString::valueOf( fVal );
623 case EXC_AFTYPE_BOOLERR: return OString::valueOf( (sal_Int32) ( fVal != 0 ? 1 : 0 ) );
624 default: return OString();
625 }
626 }
627
SaveXml(XclExpXmlStream & rStrm)628 void ExcFilterCondition::SaveXml( XclExpXmlStream& rStrm )
629 {
630 if( IsEmpty() )
631 return;
632
633 rStrm.GetCurrentStream()->singleElement( XML_customFilter,
634 XML_operator, lcl_GetOperator( nOper ),
635 XML_val, lcl_GetValue( nType, fVal, pText ).getStr(),
636 FSEND );
637 }
638
SaveText(XclExpStream & rStrm)639 void ExcFilterCondition::SaveText( XclExpStream& rStrm )
640 {
641 if( nType == EXC_AFTYPE_STRING )
642 {
643 DBG_ASSERT( pText, "ExcFilterCondition::SaveText() -- pText is NULL!" );
644 pText->WriteFlagField( rStrm );
645 pText->WriteBuffer( rStrm );
646 }
647 }
648
649 // ----------------------------------------------------------------------------
650
XclExpAutofilter(const XclExpRoot & rRoot,sal_uInt16 nC)651 XclExpAutofilter::XclExpAutofilter( const XclExpRoot& rRoot, sal_uInt16 nC ) :
652 XclExpRecord( EXC_ID_AUTOFILTER, 24 ),
653 XclExpRoot( rRoot ),
654 nCol( nC ),
655 nFlags( 0 )
656 {
657 }
658
AddCondition(ScQueryConnect eConn,sal_uInt8 nType,sal_uInt8 nOp,double fVal,String * pText,sal_Bool bSimple)659 sal_Bool XclExpAutofilter::AddCondition( ScQueryConnect eConn, sal_uInt8 nType, sal_uInt8 nOp,
660 double fVal, String* pText, sal_Bool bSimple )
661 {
662 if( !aCond[ 1 ].IsEmpty() )
663 return sal_False;
664
665 sal_uInt16 nInd = aCond[ 0 ].IsEmpty() ? 0 : 1;
666
667 if( nInd == 1 )
668 nFlags |= (eConn == SC_OR) ? EXC_AFFLAG_OR : EXC_AFFLAG_AND;
669 if( bSimple )
670 nFlags |= (nInd == 0) ? EXC_AFFLAG_SIMPLE1 : EXC_AFFLAG_SIMPLE2;
671
672 aCond[ nInd ].SetCondition( nType, nOp, fVal, pText );
673
674 AddRecSize( aCond[ nInd ].GetTextBytes() );
675
676 return sal_True;
677 }
678
AddEntry(const ScQueryEntry & rEntry)679 sal_Bool XclExpAutofilter::AddEntry( const ScQueryEntry& rEntry )
680 {
681 sal_Bool bConflict = sal_False;
682 String sText;
683
684 if( rEntry.pStr )
685 {
686 sText.Assign( *rEntry.pStr );
687 switch( rEntry.eOp )
688 {
689 case SC_CONTAINS:
690 case SC_DOES_NOT_CONTAIN:
691 {
692 sText.InsertAscii( "*" , 0 );
693 sText.AppendAscii( "*" );
694 }
695 break;
696 case SC_BEGINS_WITH:
697 case SC_DOES_NOT_BEGIN_WITH:
698 sText.AppendAscii( "*" );
699 break;
700 case SC_ENDS_WITH:
701 case SC_DOES_NOT_END_WITH:
702 sText.InsertAscii( "*" , 0 );
703 break;
704 default:
705 {
706 //nothing
707 }
708 }
709 }
710
711 sal_Bool bLen = sText.Len() > 0;
712
713 // empty/nonempty fields
714 if( !bLen && (rEntry.nVal == SC_EMPTYFIELDS) )
715 bConflict = !AddCondition( rEntry.eConnect, EXC_AFTYPE_EMPTY, EXC_AFOPER_NONE, 0.0, NULL, sal_True );
716 else if( !bLen && (rEntry.nVal == SC_NONEMPTYFIELDS) )
717 bConflict = !AddCondition( rEntry.eConnect, EXC_AFTYPE_NOTEMPTY, EXC_AFOPER_NONE, 0.0, NULL, sal_True );
718 // other conditions
719 else
720 {
721 double fVal = 0.0;
722 sal_uInt32 nIndex = 0;
723 sal_Bool bIsNum = bLen ? GetFormatter().IsNumberFormat( sText, nIndex, fVal ) : sal_True;
724 String* pText = bIsNum ? NULL : &sText;
725
726 // top10 flags
727 sal_uInt16 nNewFlags = 0x0000;
728 switch( rEntry.eOp )
729 {
730 case SC_TOPVAL:
731 nNewFlags = (EXC_AFFLAG_TOP10 | EXC_AFFLAG_TOP10TOP);
732 break;
733 case SC_BOTVAL:
734 nNewFlags = EXC_AFFLAG_TOP10;
735 break;
736 case SC_TOPPERC:
737 nNewFlags = (EXC_AFFLAG_TOP10 | EXC_AFFLAG_TOP10TOP | EXC_AFFLAG_TOP10PERC);
738 break;
739 case SC_BOTPERC:
740 nNewFlags = (EXC_AFFLAG_TOP10 | EXC_AFFLAG_TOP10PERC);
741 break;
742 default:;
743 }
744 sal_Bool bNewTop10 = ::get_flag( nNewFlags, EXC_AFFLAG_TOP10 );
745
746 bConflict = HasTop10() && bNewTop10;
747 if( !bConflict )
748 {
749 if( bNewTop10 )
750 {
751 if( fVal < 0 ) fVal = 0;
752 if( fVal >= 501 ) fVal = 500;
753 nFlags |= (nNewFlags | (sal_uInt16)(fVal) << 7);
754 }
755 // normal condition
756 else
757 {
758 sal_uInt8 nType = bIsNum ? EXC_AFTYPE_DOUBLE : EXC_AFTYPE_STRING;
759 sal_uInt8 nOper = EXC_AFOPER_NONE;
760
761 switch( rEntry.eOp )
762 {
763 case SC_EQUAL: nOper = EXC_AFOPER_EQUAL; break;
764 case SC_LESS: nOper = EXC_AFOPER_LESS; break;
765 case SC_GREATER: nOper = EXC_AFOPER_GREATER; break;
766 case SC_LESS_EQUAL: nOper = EXC_AFOPER_LESSEQUAL; break;
767 case SC_GREATER_EQUAL: nOper = EXC_AFOPER_GREATEREQUAL; break;
768 case SC_NOT_EQUAL: nOper = EXC_AFOPER_NOTEQUAL; break;
769 case SC_CONTAINS:
770 case SC_BEGINS_WITH:
771 case SC_ENDS_WITH:
772 nOper = EXC_AFOPER_EQUAL; break;
773 case SC_DOES_NOT_CONTAIN:
774 case SC_DOES_NOT_BEGIN_WITH:
775 case SC_DOES_NOT_END_WITH:
776 nOper = EXC_AFOPER_NOTEQUAL; break;
777 default:;
778 }
779 bConflict = !AddCondition( rEntry.eConnect, nType, nOper, fVal, pText );
780 }
781 }
782 }
783 return bConflict;
784 }
785
WriteBody(XclExpStream & rStrm)786 void XclExpAutofilter::WriteBody( XclExpStream& rStrm )
787 {
788 rStrm << nCol << nFlags;
789 aCond[ 0 ].Save( rStrm );
790 aCond[ 1 ].Save( rStrm );
791 aCond[ 0 ].SaveText( rStrm );
792 aCond[ 1 ].SaveText( rStrm );
793 }
794
SaveXml(XclExpXmlStream & rStrm)795 void XclExpAutofilter::SaveXml( XclExpXmlStream& rStrm )
796 {
797 if( !HasCondition() )
798 return;
799
800 sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
801
802 rWorksheet->startElement( XML_filterColumn,
803 XML_colId, OString::valueOf( (sal_Int32) nCol ).getStr(),
804 // OOXTODO: XML_hiddenButton, AutoFilter12 fHideArrow?
805 // OOXTODO: XML_showButton,
806 FSEND );
807
808 if( HasTop10() )
809 {
810 rWorksheet->singleElement( XML_top10,
811 XML_top, XclXmlUtils::ToPsz( get_flag( nFlags, EXC_AFFLAG_TOP10TOP ) ),
812 XML_percent, XclXmlUtils::ToPsz( get_flag( nFlags, EXC_AFFLAG_TOP10PERC ) ),
813 XML_val, OString::valueOf( (sal_Int32) (nFlags >> 7 ) ).getStr(),
814 // OOXTODO: XML_filterVal,
815 FSEND );
816 }
817
818 rWorksheet->startElement( XML_customFilters,
819 XML_and, XclXmlUtils::ToPsz( (nFlags & EXC_AFFLAG_ANDORMASK) == EXC_AFFLAG_AND ),
820 FSEND );
821 aCond[ 0 ].SaveXml( rStrm );
822 aCond[ 1 ].SaveXml( rStrm );
823 rWorksheet->endElement( XML_customFilters );
824 // OOXTODO: XLM_colorFilter, XML_dynamicFilter,
825 // XML_extLst, XML_filters, XML_iconFilter, XML_top10
826 rWorksheet->endElement( XML_filterColumn );
827 }
828
829 // ----------------------------------------------------------------------------
830
ExcAutoFilterRecs(const XclExpRoot & rRoot,SCTAB nTab)831 ExcAutoFilterRecs::ExcAutoFilterRecs( const XclExpRoot& rRoot, SCTAB nTab ) :
832 XclExpRoot( rRoot ),
833 pFilterMode( NULL ),
834 pFilterInfo( NULL )
835 {
836 ScDBCollection& rDBColl = GetDatabaseRanges();
837 XclExpNameManager& rNameMgr = GetNameManager();
838
839 // search for first DB-range with filter
840 sal_uInt16 nIndex = 0;
841 sal_Bool bFound = sal_False;
842 sal_Bool bAdvanced = sal_False;
843 ScDBData* pData = NULL;
844 ScRange aAdvRange;
845 while( (nIndex < rDBColl.GetCount()) && !bFound )
846 {
847 pData = rDBColl[ nIndex ];
848 if( pData )
849 {
850 ScRange aRange;
851 pData->GetArea( aRange );
852 bAdvanced = pData->GetAdvancedQuerySource( aAdvRange );
853 bFound = (aRange.aStart.Tab() == nTab) &&
854 (pData->HasQueryParam() || pData->HasAutoFilter() || bAdvanced);
855 }
856 if( !bFound )
857 nIndex++;
858 }
859
860 if( pData && bFound )
861 {
862 ScQueryParam aParam;
863 pData->GetQueryParam( aParam );
864
865 ScRange aRange( aParam.nCol1, aParam.nRow1, aParam.nTab,
866 aParam.nCol2, aParam.nRow2, aParam.nTab );
867 SCCOL nColCnt = aParam.nCol2 - aParam.nCol1 + 1;
868
869 maRef = aRange;
870
871 // #i2394# #100489# built-in defined names must be sorted by containing sheet name
872 rNameMgr.InsertBuiltInName( EXC_BUILTIN_FILTERDATABASE, aRange );
873
874 // advanced filter
875 if( bAdvanced )
876 {
877 // filter criteria, excel allows only same table
878 if( aAdvRange.aStart.Tab() == nTab )
879 rNameMgr.InsertBuiltInName( EXC_BUILTIN_CRITERIA, aAdvRange );
880
881 // filter destination range, excel allows only same table
882 if( !aParam.bInplace )
883 {
884 ScRange aDestRange( aParam.nDestCol, aParam.nDestRow, aParam.nDestTab );
885 aDestRange.aEnd.IncCol( nColCnt - 1 );
886 if( aDestRange.aStart.Tab() == nTab )
887 rNameMgr.InsertBuiltInName( EXC_BUILTIN_EXTRACT, aDestRange );
888 }
889
890 pFilterMode = new XclExpFiltermode;
891 }
892 // AutoFilter
893 else
894 {
895 sal_Bool bConflict = sal_False;
896 sal_Bool bContLoop = sal_True;
897 sal_Bool bHasOr = sal_False;
898 SCCOLROW nFirstField = aParam.GetEntry( 0 ).nField;
899
900 // create AUTOFILTER records for filtered columns
901 for( SCSIZE nEntry = 0; !bConflict && bContLoop && (nEntry < aParam.GetEntryCount()); nEntry++ )
902 {
903 const ScQueryEntry& rEntry = aParam.GetEntry( nEntry );
904
905 bContLoop = rEntry.bDoQuery;
906 if( bContLoop )
907 {
908 XclExpAutofilter* pFilter = GetByCol( static_cast<SCCOL>(rEntry.nField) - aRange.aStart.Col() );
909
910 if( nEntry > 0 )
911 bHasOr |= (rEntry.eConnect == SC_OR);
912
913 bConflict = (nEntry > 1) && bHasOr;
914 if( !bConflict )
915 bConflict = (nEntry == 1) && (rEntry.eConnect == SC_OR) &&
916 (nFirstField != rEntry.nField);
917 if( !bConflict )
918 bConflict = pFilter->AddEntry( rEntry );
919 }
920 }
921
922 // additional tests for conflicts
923 for( size_t nPos = 0, nSize = maFilterList.GetSize(); !bConflict && (nPos < nSize); ++nPos )
924 {
925 XclExpAutofilterRef xFilter = maFilterList.GetRecord( nPos );
926 bConflict = xFilter->HasCondition() && xFilter->HasTop10();
927 }
928
929 if( bConflict )
930 maFilterList.RemoveAllRecords();
931
932 if( !maFilterList.IsEmpty() )
933 pFilterMode = new XclExpFiltermode;
934 pFilterInfo = new XclExpAutofilterinfo( aRange.aStart, nColCnt );
935 }
936 }
937 }
938
~ExcAutoFilterRecs()939 ExcAutoFilterRecs::~ExcAutoFilterRecs()
940 {
941 delete pFilterMode;
942 delete pFilterInfo;
943 }
944
GetByCol(SCCOL nCol)945 XclExpAutofilter* ExcAutoFilterRecs::GetByCol( SCCOL nCol )
946 {
947 XclExpAutofilterRef xFilter;
948 for( size_t nPos = 0, nSize = maFilterList.GetSize(); nPos < nSize; ++nPos )
949 {
950 xFilter = maFilterList.GetRecord( nPos );
951 if( xFilter->GetCol() == static_cast<sal_uInt16>(nCol) )
952 return xFilter.get();
953 }
954 xFilter.reset( new XclExpAutofilter( GetRoot(), static_cast<sal_uInt16>(nCol) ) );
955 maFilterList.AppendRecord( xFilter );
956 return xFilter.get();
957 }
958
IsFiltered(SCCOL nCol)959 sal_Bool ExcAutoFilterRecs::IsFiltered( SCCOL nCol )
960 {
961 for( size_t nPos = 0, nSize = maFilterList.GetSize(); nPos < nSize; ++nPos )
962 if( maFilterList.GetRecord( nPos )->GetCol() == static_cast<sal_uInt16>(nCol) )
963 return sal_True;
964 return sal_False;
965 }
966
AddObjRecs()967 void ExcAutoFilterRecs::AddObjRecs()
968 {
969 if( pFilterInfo )
970 {
971 ScAddress aAddr( pFilterInfo->GetStartPos() );
972 for( SCCOL nObj = 0, nCount = pFilterInfo->GetColCount(); nObj < nCount; nObj++ )
973 {
974 XclObj* pObjRec = new XclObjDropDown( GetObjectManager(), aAddr, IsFiltered( nObj ) );
975 GetObjectManager().AddObj( pObjRec );
976 aAddr.IncCol( 1 );
977 }
978 }
979 }
980
Save(XclExpStream & rStrm)981 void ExcAutoFilterRecs::Save( XclExpStream& rStrm )
982 {
983 if( pFilterMode )
984 pFilterMode->Save( rStrm );
985 if( pFilterInfo )
986 pFilterInfo->Save( rStrm );
987 maFilterList.Save( rStrm );
988 }
989
SaveXml(XclExpXmlStream & rStrm)990 void ExcAutoFilterRecs::SaveXml( XclExpXmlStream& rStrm )
991 {
992 if( maFilterList.IsEmpty() )
993 return;
994
995 sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
996 rWorksheet->startElement( XML_autoFilter,
997 XML_ref, XclXmlUtils::ToOString( maRef ).getStr(),
998 FSEND );
999 // OOXTODO: XML_extLst, XML_sortState
1000 maFilterList.SaveXml( rStrm );
1001 rWorksheet->endElement( XML_autoFilter );
1002 }
1003
HasFilterMode() const1004 bool ExcAutoFilterRecs::HasFilterMode() const
1005 {
1006 return pFilterMode != NULL;
1007 }
1008
1009 // ----------------------------------------------------------------------------
1010
XclExpFilterManager(const XclExpRoot & rRoot)1011 XclExpFilterManager::XclExpFilterManager( const XclExpRoot& rRoot ) :
1012 XclExpRoot( rRoot )
1013 {
1014 }
1015
InitTabFilter(SCTAB nScTab)1016 void XclExpFilterManager::InitTabFilter( SCTAB nScTab )
1017 {
1018 maFilterMap[ nScTab ].reset( new ExcAutoFilterRecs( GetRoot(), nScTab ) );
1019 }
1020
CreateRecord(SCTAB nScTab)1021 XclExpRecordRef XclExpFilterManager::CreateRecord( SCTAB nScTab )
1022 {
1023 XclExpTabFilterRef xRec;
1024 XclExpTabFilterMap::iterator aIt = maFilterMap.find( nScTab );
1025 if( aIt != maFilterMap.end() )
1026 {
1027 xRec = aIt->second;
1028 xRec->AddObjRecs();
1029 }
1030 return xRec;
1031 }
1032
HasFilterMode(SCTAB nScTab)1033 bool XclExpFilterManager::HasFilterMode( SCTAB nScTab )
1034 {
1035 XclExpTabFilterRef xRec;
1036 XclExpTabFilterMap::iterator aIt = maFilterMap.find( nScTab );
1037 if( aIt != maFilterMap.end() )
1038 {
1039 return aIt->second->HasFilterMode();
1040 }
1041 return false;
1042 }
1043
1044 // ============================================================================
1045
1046