merge the formfield patch from ooo-build
[ooovba.git] / sc / source / filter / excel / excrecds.cxx
blob1923bea0270ab419cde46ec0ad5ba8c084df4995
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: excrecds.cxx,v $
10 * $Revision: 1.88 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
36 //------------------------------------------------------------------------
38 #include "excrecds.hxx"
40 #include <map>
41 #include <svx/countryid.hxx>
43 #include "scitems.hxx"
44 #include <svx/eeitem.hxx>
46 #include <sfx2/objsh.hxx>
48 #include <svx/editdata.hxx>
49 #include <svx/editeng.hxx>
50 #include <svx/editobj.hxx>
51 #include <svx/editstat.hxx>
53 #include <svx/flditem.hxx>
54 #include <svx/flstitem.hxx>
56 #include <svx/algitem.hxx>
57 #include <svx/boxitem.hxx>
58 #include <svx/brshitem.hxx>
59 #include <svx/pageitem.hxx>
60 #include <svx/paperinf.hxx>
61 #include <svx/sizeitem.hxx>
62 #include <svx/ulspitem.hxx>
63 #include <svx/fhgtitem.hxx>
64 #include <svx/escpitem.hxx>
65 #include <svtools/intitem.hxx>
66 #include <svtools/zforlist.hxx>
67 #include <svtools/zformat.hxx>
68 #include <svtools/ctrltool.hxx>
70 #define _SVSTDARR_USHORTS
71 #include <svtools/svstdarr.hxx>
73 #include <string.h>
75 #include "global.hxx"
76 #include "globstr.hrc"
77 #include "docpool.hxx"
78 #include "patattr.hxx"
79 #include "cell.hxx"
80 #include "document.hxx"
81 #include "scextopt.hxx"
82 #include "patattr.hxx"
83 #include "attrib.hxx"
84 #include "progress.hxx"
85 #include "dociter.hxx"
86 #include "rangenam.hxx"
87 #include "dbcolect.hxx"
88 #include "stlsheet.hxx"
89 #include "stlpool.hxx"
90 #include "editutil.hxx"
91 #include "formula/errorcodes.hxx"
93 #include "excdoc.hxx"
94 #include "xeformula.hxx"
95 #include "xelink.hxx"
96 #include "xename.hxx"
97 #include "xecontent.hxx"
99 #include "xcl97rec.hxx"
101 #include <oox/core/tokens.hxx>
103 using ::com::sun::star::uno::Sequence;
106 using ::rtl::OString;
108 //--------------------------------------------------------- class ExcDummy_00 -
109 const BYTE ExcDummy_00::pMyData[] = {
110 0x5c, 0x00, 0x20, 0x00, 0x04, 'C', 'a', 'l', 'c', // WRITEACCESS
111 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
112 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
113 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
115 const sal_Size ExcDummy_00::nMyLen = sizeof( ExcDummy_00::pMyData );
117 //-------------------------------------------------------- class ExcDummy_04x -
118 const BYTE ExcDummy_040::pMyData[] = {
119 0x40, 0x00, 0x02, 0x00, 0x00, 0x00, // BACKUP
120 0x8d, 0x00, 0x02, 0x00, 0x00, 0x00, // HIDEOBJ
122 const sal_Size ExcDummy_040::nMyLen = sizeof( ExcDummy_040::pMyData );
124 const BYTE ExcDummy_041::pMyData[] = {
125 0x0e, 0x00, 0x02, 0x00, 0x01, 0x00, // PRECISION
126 0xda, 0x00, 0x02, 0x00, 0x00, 0x00 // BOOKBOOL
128 const sal_Size ExcDummy_041::nMyLen = sizeof( ExcDummy_041::pMyData );
130 //-------------------------------------------------------- class ExcDummy_02a -
131 const BYTE ExcDummy_02a::pMyData[] = {
132 0x0d, 0x00, 0x02, 0x00, 0x01, 0x00, // CALCMODE
133 0x0c, 0x00, 0x02, 0x00, 0x64, 0x00, // CALCCOUNT
134 0x0f, 0x00, 0x02, 0x00, 0x01, 0x00, // REFMODE
135 0x11, 0x00, 0x02, 0x00, 0x00, 0x00, // ITERATION
136 0x10, 0x00, 0x08, 0x00, 0xfc, 0xa9, 0xf1, 0xd2, 0x4d, // DELTA
137 0x62, 0x50, 0x3f,
138 0x5f, 0x00, 0x02, 0x00, 0x01, 0x00 // SAVERECALC
140 const sal_Size ExcDummy_02a::nMyLen = sizeof( ExcDummy_02a::pMyData );
142 //----------------------------------------------------------- class ExcRecord -
144 void ExcRecord::Save( XclExpStream& rStrm )
146 SetRecHeader( GetNum(), GetLen() );
147 XclExpRecord::Save( rStrm );
150 void ExcRecord::SaveCont( XclExpStream& /*rStrm*/ )
154 void ExcRecord::WriteBody( XclExpStream& rStrm )
156 SaveCont( rStrm );
160 //--------------------------------------------------------- class ExcEmptyRec -
162 void ExcEmptyRec::Save( XclExpStream& /*rStrm*/ )
167 UINT16 ExcEmptyRec::GetNum() const
169 return 0;
173 sal_Size ExcEmptyRec::GetLen() const
175 return 0;
180 //------------------------------------------------------- class ExcRecordList -
182 ExcRecordList::~ExcRecordList()
184 for( ExcRecord* pRec = First(); pRec; pRec = Next() )
185 delete pRec;
189 void ExcRecordList::Save( XclExpStream& rStrm )
191 for( ExcRecord* pRec = First(); pRec; pRec = Next() )
192 pRec->Save( rStrm );
197 //--------------------------------------------------------- class ExcDummyRec -
199 void ExcDummyRec::Save( XclExpStream& rStrm )
201 rStrm.Write( GetData(), GetLen() ); // raw write mode
205 UINT16 ExcDummyRec::GetNum( void ) const
207 return 0x0000;
212 //------------------------------------------------------- class ExcBoolRecord -
214 void ExcBoolRecord::SaveCont( XclExpStream& rStrm )
216 rStrm << (UINT16)(bVal ? 0x0001 : 0x0000);
220 sal_Size ExcBoolRecord::GetLen( void ) const
222 return 2;
228 //--------------------------------------------------------- class ExcBof_Base -
230 ExcBof_Base::ExcBof_Base() :
231 nRupBuild( 0x096C ), // copied from Excel
232 nRupYear( 0x07C9 ) // copied from Excel
238 //-------------------------------------------------------------- class ExcBof -
240 ExcBof::ExcBof( void )
242 nDocType = 0x0010;
243 nVers = 0x0500;
247 void ExcBof::SaveCont( XclExpStream& rStrm )
249 rStrm << nVers << nDocType << nRupBuild << nRupYear;
253 UINT16 ExcBof::GetNum( void ) const
255 return 0x0809;
259 sal_Size ExcBof::GetLen( void ) const
261 return 8;
266 //------------------------------------------------------------- class ExcBofW -
268 ExcBofW::ExcBofW( void )
270 nDocType = 0x0005;
271 nVers = 0x0500;
275 void ExcBofW::SaveCont( XclExpStream& rStrm )
277 rStrm << nVers << nDocType << nRupBuild << nRupYear;
282 UINT16 ExcBofW::GetNum( void ) const
284 return 0x0809;
289 sal_Size ExcBofW::GetLen( void ) const
291 return 8;
296 //-------------------------------------------------------------- class ExcEof -
298 UINT16 ExcEof::GetNum( void ) const
300 return 0x000A;
304 sal_Size ExcEof::GetLen( void ) const
306 return 0;
311 //--------------------------------------------------------- class ExcDummy_00 -
313 sal_Size ExcDummy_00::GetLen( void ) const
315 return nMyLen;
319 const BYTE* ExcDummy_00::GetData( void ) const
321 return pMyData;
326 //-------------------------------------------------------- class ExcDummy_04x -
328 sal_Size ExcDummy_040::GetLen( void ) const
330 return nMyLen;
334 const BYTE* ExcDummy_040::GetData( void ) const
336 return pMyData;
342 sal_Size ExcDummy_041::GetLen( void ) const
344 return nMyLen;
348 const BYTE* ExcDummy_041::GetData( void ) const
350 return pMyData;
355 //------------------------------------------------------------- class Exc1904 -
357 Exc1904::Exc1904( ScDocument& rDoc )
359 Date* pDate = rDoc.GetFormatTable()->GetNullDate();
360 bVal = pDate ? (*pDate == Date( 1, 1, 1904 )) : FALSE;
364 UINT16 Exc1904::GetNum( void ) const
366 return 0x0022;
370 void Exc1904::SaveXml( XclExpXmlStream& rStrm )
372 rStrm.WriteAttributes(
373 XML_date1904, XclXmlUtils::ToPsz( bVal ),
374 FSEND );
379 //------------------------------------------------------ class ExcBundlesheet -
381 ExcBundlesheetBase::ExcBundlesheetBase( RootData& rRootData, SCTAB nTabNum ) :
382 nStrPos( STREAM_SEEK_TO_END ),
383 nOwnPos( STREAM_SEEK_TO_END ),
384 nGrbit( rRootData.pER->GetTabInfo().IsVisibleTab( nTabNum ) ? 0x0000 : 0x0001 ),
385 nTab( nTabNum )
390 ExcBundlesheetBase::ExcBundlesheetBase() :
391 nStrPos( STREAM_SEEK_TO_END ),
392 nOwnPos( STREAM_SEEK_TO_END ),
393 nGrbit( 0x0000 ),
394 nTab( SCTAB_GLOBAL )
399 void ExcBundlesheetBase::UpdateStreamPos( XclExpStream& rStrm )
401 rStrm.SetSvStreamPos( nOwnPos );
402 rStrm.DisableEncryption();
403 rStrm << static_cast<sal_uInt32>(nStrPos);
404 rStrm.EnableEncryption();
408 UINT16 ExcBundlesheetBase::GetNum( void ) const
410 return 0x0085;
416 ExcBundlesheet::ExcBundlesheet( RootData& rRootData, SCTAB _nTab ) :
417 ExcBundlesheetBase( rRootData, _nTab )
419 String sTabName = rRootData.pER->GetTabInfo().GetScTabName( _nTab );
420 DBG_ASSERT( sTabName.Len() < 256, "ExcBundlesheet::ExcBundlesheet - table name too long" );
421 aName = ByteString( sTabName, rRootData.pER->GetTextEncoding() );
425 void ExcBundlesheet::SaveCont( XclExpStream& rStrm )
427 nOwnPos = rStrm.GetSvStreamPos();
428 rStrm << (UINT32) 0x00000000 // dummy (stream position of the sheet)
429 << nGrbit;
430 rStrm.WriteByteString( aName ); // 8 bit length, max 255 chars
434 sal_Size ExcBundlesheet::GetLen() const
436 return 7 + Min( aName.Len(), (xub_StrLen) 255 );
440 //--------------------------------------------------------- class ExcDummy_02 -
442 sal_Size ExcDummy_02a::GetLen( void ) const
444 return nMyLen;
447 const BYTE* ExcDummy_02a::GetData( void ) const
449 return pMyData;
451 //--------------------------------------------------------- class ExcDummy_02 -
453 XclExpCountry::XclExpCountry( const XclExpRoot& rRoot ) :
454 XclExpRecord( EXC_ID_COUNTRY, 4 )
456 /* #i31530# set document country as UI country too -
457 needed for correct behaviour of number formats. */
458 mnUICountry = mnDocCountry = static_cast< sal_uInt16 >(
459 ::svx::ConvertLanguageToCountry( rRoot.GetDocLanguage() ) );
462 void XclExpCountry::WriteBody( XclExpStream& rStrm )
464 rStrm << mnUICountry << mnDocCountry;
467 // XclExpWsbool ===============================================================
469 XclExpWsbool::XclExpWsbool( bool bFitToPages, SCTAB nScTab, XclExpFilterManager* pManager )
470 : XclExpUInt16Record( EXC_ID_WSBOOL, EXC_WSBOOL_DEFAULTFLAGS )
471 , mnScTab( nScTab )
472 , mpManager( pManager )
474 if( bFitToPages )
475 SetValue( GetValue() | EXC_WSBOOL_FITTOPAGE );
478 void XclExpWsbool::SaveXml( XclExpXmlStream& rStrm )
480 sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
481 rWorksheet->startElement( XML_sheetPr,
482 // OOXTODO: XML_syncHorizontal,
483 // OOXTODO: XML_syncVertical,
484 // OOXTODO: XML_syncRef,
485 // OOXTODO: XML_transitionEvaluation,
486 // OOXTODO: XML_transitionEntry,
487 // OOXTODO: XML_published,
488 // OOXTODO: XML_codeName,
489 XML_filterMode, mpManager ? XclXmlUtils::ToPsz( mpManager->HasFilterMode( mnScTab ) ) : NULL,
490 // OOXTODO: XML_enableFormatConditionsCalculation,
491 FSEND );
492 // OOXTODO: elements XML_tabColor, XML_outlinePr
493 rWorksheet->singleElement( XML_pageSetUpPr,
494 // OOXTODO: XML_autoPageBreaks,
495 XML_fitToPage, XclXmlUtils::ToPsz( GetValue() & EXC_WSBOOL_FITTOPAGE ),
496 FSEND );
497 rWorksheet->endElement( XML_sheetPr );
501 // XclExpWindowProtection ===============================================================
503 XclExpWindowProtection::XclExpWindowProtection(bool bValue) :
504 XclExpBoolRecord(EXC_ID_WINDOWPROTECT, bValue)
508 void XclExpWindowProtection::SaveXml( XclExpXmlStream& rStrm )
510 rStrm.WriteAttributes(
511 XML_lockWindows, XclXmlUtils::ToPsz( GetBool() ),
512 FSEND );
515 // XclExpDocProtection ===============================================================
517 XclExpProtection::XclExpProtection(bool bValue) :
518 XclExpBoolRecord(EXC_ID_PROTECT, bValue)
522 // ============================================================================
524 XclExpPassHash::XclExpPassHash(const Sequence<sal_Int8>& aHash) :
525 XclExpRecord(EXC_ID_PASSWORD, 2),
526 mnHash(0x0000)
528 if (aHash.getLength() >= 2)
530 mnHash = ((aHash[0] << 8) & 0xFFFF);
531 mnHash |= (aHash[1] & 0xFF);
535 XclExpPassHash::~XclExpPassHash()
539 void XclExpPassHash::WriteBody(XclExpStream& rStrm)
541 rStrm << mnHash;
544 // ============================================================================
546 XclExpFiltermode::XclExpFiltermode() :
547 XclExpEmptyRecord( EXC_ID_FILTERMODE )
551 // ----------------------------------------------------------------------------
553 XclExpAutofilterinfo::XclExpAutofilterinfo( const ScAddress& rStartPos, SCCOL nScCol ) :
554 XclExpUInt16Record( EXC_ID_AUTOFILTERINFO, static_cast< sal_uInt16 >( nScCol ) ),
555 maStartPos( rStartPos )
559 // ----------------------------------------------------------------------------
561 ExcFilterCondition::ExcFilterCondition() :
562 nType( EXC_AFTYPE_NOTUSED ),
563 nOper( EXC_AFOPER_EQUAL ),
564 fVal( 0.0 ),
565 pText( NULL )
569 ExcFilterCondition::~ExcFilterCondition()
571 if( pText )
572 delete pText;
575 sal_Size ExcFilterCondition::GetTextBytes() const
577 return pText ? (1 + pText->GetBufferSize()) : 0;
580 void ExcFilterCondition::SetCondition( UINT8 nTp, UINT8 nOp, double fV, String* pT )
582 nType = nTp;
583 nOper = nOp;
584 fVal = fV;
586 delete pText;
587 pText = pT ? new XclExpString( *pT, EXC_STR_8BITLENGTH ) : NULL;
590 void ExcFilterCondition::Save( XclExpStream& rStrm )
592 rStrm << nType << nOper;
593 switch( nType )
595 case EXC_AFTYPE_DOUBLE:
596 rStrm << fVal;
597 break;
598 case EXC_AFTYPE_STRING:
599 DBG_ASSERT( pText, "ExcFilterCondition::Save() -- pText is NULL!" );
600 rStrm << (UINT32)0 << (UINT8) pText->Len() << (UINT16)0 << (UINT8)0;
601 break;
602 case EXC_AFTYPE_BOOLERR:
603 rStrm << (UINT8)0 << (UINT8)((fVal != 0) ? 1 : 0) << (UINT32)0 << (UINT16)0;
604 break;
605 default:
606 rStrm << (UINT32)0 << (UINT32)0;
610 static const char* lcl_GetOperator( UINT8 nOper )
612 switch( nOper )
614 case EXC_AFOPER_EQUAL: return "equal";
615 case EXC_AFOPER_GREATER: return "greaterThan";
616 case EXC_AFOPER_GREATEREQUAL: return "greaterThanOrEqual";
617 case EXC_AFOPER_LESS: return "lessThan";
618 case EXC_AFOPER_LESSEQUAL: return "lessThanOrEqual";
619 case EXC_AFOPER_NOTEQUAL: return "notEqual";
620 case EXC_AFOPER_NONE:
621 default: return "**none**";
625 static OString lcl_GetValue( UINT8 nType, double fVal, XclExpString* pStr )
627 switch( nType )
629 case EXC_AFTYPE_STRING: return XclXmlUtils::ToOString( *pStr );
630 case EXC_AFTYPE_DOUBLE: return OString::valueOf( fVal );
631 case EXC_AFTYPE_BOOLERR: return OString::valueOf( (sal_Int32) ( fVal != 0 ? 1 : 0 ) );
632 default: return OString();
636 void ExcFilterCondition::SaveXml( XclExpXmlStream& rStrm )
638 if( IsEmpty() )
639 return;
641 rStrm.GetCurrentStream()->singleElement( XML_customFilter,
642 XML_operator, lcl_GetOperator( nOper ),
643 XML_val, lcl_GetValue( nType, fVal, pText ).getStr(),
644 FSEND );
647 void ExcFilterCondition::SaveText( XclExpStream& rStrm )
649 if( nType == EXC_AFTYPE_STRING )
651 DBG_ASSERT( pText, "ExcFilterCondition::SaveText() -- pText is NULL!" );
652 pText->WriteFlagField( rStrm );
653 pText->WriteBuffer( rStrm );
657 // ----------------------------------------------------------------------------
659 XclExpAutofilter::XclExpAutofilter( const XclExpRoot& rRoot, UINT16 nC ) :
660 XclExpRecord( EXC_ID_AUTOFILTER, 24 ),
661 XclExpRoot( rRoot ),
662 nCol( nC ),
663 nFlags( 0 )
667 BOOL XclExpAutofilter::AddCondition( ScQueryConnect eConn, UINT8 nType, UINT8 nOp,
668 double fVal, String* pText, BOOL bSimple )
670 if( !aCond[ 1 ].IsEmpty() )
671 return FALSE;
673 UINT16 nInd = aCond[ 0 ].IsEmpty() ? 0 : 1;
675 if( nInd == 1 )
676 nFlags |= (eConn == SC_OR) ? EXC_AFFLAG_OR : EXC_AFFLAG_AND;
677 if( bSimple )
678 nFlags |= (nInd == 0) ? EXC_AFFLAG_SIMPLE1 : EXC_AFFLAG_SIMPLE2;
680 aCond[ nInd ].SetCondition( nType, nOp, fVal, pText );
682 AddRecSize( aCond[ nInd ].GetTextBytes() );
684 return TRUE;
687 BOOL XclExpAutofilter::AddEntry( const ScQueryEntry& rEntry )
689 BOOL bConflict = FALSE;
690 String sText;
692 if( rEntry.pStr )
694 sText.Assign( *rEntry.pStr );
695 switch( rEntry.eOp )
697 case SC_CONTAINS:
698 case SC_DOES_NOT_CONTAIN:
700 sText.InsertAscii( "*" , 0 );
701 sText.AppendAscii( "*" );
703 break;
704 case SC_BEGINS_WITH:
705 case SC_DOES_NOT_BEGIN_WITH:
706 sText.AppendAscii( "*" );
707 break;
708 case SC_ENDS_WITH:
709 case SC_DOES_NOT_END_WITH:
710 sText.InsertAscii( "*" , 0 );
711 break;
712 default:
714 //nothing
719 BOOL bLen = sText.Len() > 0;
721 // empty/nonempty fields
722 if( !bLen && (rEntry.nVal == SC_EMPTYFIELDS) )
723 bConflict = !AddCondition( rEntry.eConnect, EXC_AFTYPE_EMPTY, EXC_AFOPER_NONE, 0.0, NULL, TRUE );
724 else if( !bLen && (rEntry.nVal == SC_NONEMPTYFIELDS) )
725 bConflict = !AddCondition( rEntry.eConnect, EXC_AFTYPE_NOTEMPTY, EXC_AFOPER_NONE, 0.0, NULL, TRUE );
726 // other conditions
727 else
729 double fVal = 0.0;
730 sal_uInt32 nIndex = 0;
731 BOOL bIsNum = bLen ? GetFormatter().IsNumberFormat( sText, nIndex, fVal ) : TRUE;
732 String* pText = bIsNum ? NULL : &sText;
734 // top10 flags
735 UINT16 nNewFlags = 0x0000;
736 switch( rEntry.eOp )
738 case SC_TOPVAL:
739 nNewFlags = (EXC_AFFLAG_TOP10 | EXC_AFFLAG_TOP10TOP);
740 break;
741 case SC_BOTVAL:
742 nNewFlags = EXC_AFFLAG_TOP10;
743 break;
744 case SC_TOPPERC:
745 nNewFlags = (EXC_AFFLAG_TOP10 | EXC_AFFLAG_TOP10TOP | EXC_AFFLAG_TOP10PERC);
746 break;
747 case SC_BOTPERC:
748 nNewFlags = (EXC_AFFLAG_TOP10 | EXC_AFFLAG_TOP10PERC);
749 break;
750 default:;
752 BOOL bNewTop10 = ::get_flag( nNewFlags, EXC_AFFLAG_TOP10 );
754 bConflict = HasTop10() && bNewTop10;
755 if( !bConflict )
757 if( bNewTop10 )
759 if( fVal < 0 ) fVal = 0;
760 if( fVal >= 501 ) fVal = 500;
761 nFlags |= (nNewFlags | (UINT16)(fVal) << 7);
763 // normal condition
764 else
766 UINT8 nType = bIsNum ? EXC_AFTYPE_DOUBLE : EXC_AFTYPE_STRING;
767 UINT8 nOper = EXC_AFOPER_NONE;
769 switch( rEntry.eOp )
771 case SC_EQUAL: nOper = EXC_AFOPER_EQUAL; break;
772 case SC_LESS: nOper = EXC_AFOPER_LESS; break;
773 case SC_GREATER: nOper = EXC_AFOPER_GREATER; break;
774 case SC_LESS_EQUAL: nOper = EXC_AFOPER_LESSEQUAL; break;
775 case SC_GREATER_EQUAL: nOper = EXC_AFOPER_GREATEREQUAL; break;
776 case SC_NOT_EQUAL: nOper = EXC_AFOPER_NOTEQUAL; break;
777 case SC_CONTAINS:
778 case SC_BEGINS_WITH:
779 case SC_ENDS_WITH:
780 nOper = EXC_AFOPER_EQUAL; break;
781 case SC_DOES_NOT_CONTAIN:
782 case SC_DOES_NOT_BEGIN_WITH:
783 case SC_DOES_NOT_END_WITH:
784 nOper = EXC_AFOPER_NOTEQUAL; break;
785 default:;
787 bConflict = !AddCondition( rEntry.eConnect, nType, nOper, fVal, pText );
791 return bConflict;
794 void XclExpAutofilter::WriteBody( XclExpStream& rStrm )
796 rStrm << nCol << nFlags;
797 aCond[ 0 ].Save( rStrm );
798 aCond[ 1 ].Save( rStrm );
799 aCond[ 0 ].SaveText( rStrm );
800 aCond[ 1 ].SaveText( rStrm );
803 void XclExpAutofilter::SaveXml( XclExpXmlStream& rStrm )
805 if( !HasCondition() )
806 return;
808 sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
810 rWorksheet->startElement( XML_filterColumn,
811 XML_colId, OString::valueOf( (sal_Int32) nCol ).getStr(),
812 // OOXTODO: XML_hiddenButton, AutoFilter12 fHideArrow?
813 // OOXTODO: XML_showButton,
814 FSEND );
816 if( HasTop10() )
818 rWorksheet->singleElement( XML_top10,
819 XML_top, XclXmlUtils::ToPsz( get_flag( nFlags, EXC_AFFLAG_TOP10TOP ) ),
820 XML_percent, XclXmlUtils::ToPsz( get_flag( nFlags, EXC_AFFLAG_TOP10PERC ) ),
821 XML_val, OString::valueOf( (sal_Int32) (nFlags >> 7 ) ).getStr(),
822 // OOXTODO: XML_filterVal,
823 FSEND );
826 rWorksheet->startElement( XML_customFilters,
827 XML_and, XclXmlUtils::ToPsz( (nFlags & EXC_AFFLAG_ANDORMASK) == EXC_AFFLAG_AND ),
828 FSEND );
829 aCond[ 0 ].SaveXml( rStrm );
830 aCond[ 1 ].SaveXml( rStrm );
831 rWorksheet->endElement( XML_customFilters );
832 // OOXTODO: XLM_colorFilter, XML_dynamicFilter,
833 // XML_extLst, XML_filters, XML_iconFilter, XML_top10
834 rWorksheet->endElement( XML_filterColumn );
837 // ----------------------------------------------------------------------------
839 ExcAutoFilterRecs::ExcAutoFilterRecs( const XclExpRoot& rRoot, SCTAB nTab ) :
840 XclExpRoot( rRoot ),
841 pFilterMode( NULL ),
842 pFilterInfo( NULL )
844 ScDBCollection& rDBColl = GetDatabaseRanges();
845 XclExpNameManager& rNameMgr = GetNameManager();
847 // search for first DB-range with filter
848 UINT16 nIndex = 0;
849 BOOL bFound = FALSE;
850 BOOL bAdvanced = FALSE;
851 ScDBData* pData = NULL;
852 ScRange aAdvRange;
853 while( (nIndex < rDBColl.GetCount()) && !bFound )
855 pData = rDBColl[ nIndex ];
856 if( pData )
858 ScRange aRange;
859 pData->GetArea( aRange );
860 bAdvanced = pData->GetAdvancedQuerySource( aAdvRange );
861 bFound = (aRange.aStart.Tab() == nTab) &&
862 (pData->HasQueryParam() || pData->HasAutoFilter() || bAdvanced);
864 if( !bFound )
865 nIndex++;
868 if( pData && bFound )
870 ScQueryParam aParam;
871 pData->GetQueryParam( aParam );
873 ScRange aRange( aParam.nCol1, aParam.nRow1, aParam.nTab,
874 aParam.nCol2, aParam.nRow2, aParam.nTab );
875 SCCOL nColCnt = aParam.nCol2 - aParam.nCol1 + 1;
877 maRef = aRange;
879 // #i2394# #100489# built-in defined names must be sorted by containing sheet name
880 rNameMgr.InsertBuiltInName( EXC_BUILTIN_FILTERDATABASE, aRange );
882 // advanced filter
883 if( bAdvanced )
885 // filter criteria, excel allows only same table
886 if( aAdvRange.aStart.Tab() == nTab )
887 rNameMgr.InsertBuiltInName( EXC_BUILTIN_CRITERIA, aAdvRange );
889 // filter destination range, excel allows only same table
890 if( !aParam.bInplace )
892 ScRange aDestRange( aParam.nDestCol, aParam.nDestRow, aParam.nDestTab );
893 aDestRange.aEnd.IncCol( nColCnt - 1 );
894 if( aDestRange.aStart.Tab() == nTab )
895 rNameMgr.InsertBuiltInName( EXC_BUILTIN_EXTRACT, aDestRange );
898 pFilterMode = new XclExpFiltermode;
900 // AutoFilter
901 else
903 BOOL bConflict = FALSE;
904 BOOL bContLoop = TRUE;
905 BOOL bHasOr = FALSE;
906 SCCOLROW nFirstField = aParam.GetEntry( 0 ).nField;
908 // create AUTOFILTER records for filtered columns
909 for( SCSIZE nEntry = 0; !bConflict && bContLoop && (nEntry < aParam.GetEntryCount()); nEntry++ )
911 const ScQueryEntry& rEntry = aParam.GetEntry( nEntry );
913 bContLoop = rEntry.bDoQuery;
914 if( bContLoop )
916 XclExpAutofilter* pFilter = GetByCol( static_cast<SCCOL>(rEntry.nField) - aRange.aStart.Col() );
918 if( nEntry > 0 )
919 bHasOr |= (rEntry.eConnect == SC_OR);
921 bConflict = (nEntry > 1) && bHasOr;
922 if( !bConflict )
923 bConflict = (nEntry == 1) && (rEntry.eConnect == SC_OR) &&
924 (nFirstField != rEntry.nField);
925 if( !bConflict )
926 bConflict = pFilter->AddEntry( rEntry );
930 // additional tests for conflicts
931 for( size_t nPos = 0, nSize = maFilterList.GetSize(); !bConflict && (nPos < nSize); ++nPos )
933 XclExpAutofilterRef xFilter = maFilterList.GetRecord( nPos );
934 bConflict = xFilter->HasCondition() && xFilter->HasTop10();
937 if( bConflict )
938 maFilterList.RemoveAllRecords();
940 if( !maFilterList.IsEmpty() )
941 pFilterMode = new XclExpFiltermode;
942 pFilterInfo = new XclExpAutofilterinfo( aRange.aStart, nColCnt );
947 ExcAutoFilterRecs::~ExcAutoFilterRecs()
949 delete pFilterMode;
950 delete pFilterInfo;
953 XclExpAutofilter* ExcAutoFilterRecs::GetByCol( SCCOL nCol )
955 XclExpAutofilterRef xFilter;
956 for( size_t nPos = 0, nSize = maFilterList.GetSize(); nPos < nSize; ++nPos )
958 xFilter = maFilterList.GetRecord( nPos );
959 if( xFilter->GetCol() == static_cast<sal_uInt16>(nCol) )
960 return xFilter.get();
962 xFilter.reset( new XclExpAutofilter( GetRoot(), static_cast<sal_uInt16>(nCol) ) );
963 maFilterList.AppendRecord( xFilter );
964 return xFilter.get();
967 BOOL ExcAutoFilterRecs::IsFiltered( SCCOL nCol )
969 for( size_t nPos = 0, nSize = maFilterList.GetSize(); nPos < nSize; ++nPos )
970 if( maFilterList.GetRecord( nPos )->GetCol() == static_cast<sal_uInt16>(nCol) )
971 return TRUE;
972 return FALSE;
975 void ExcAutoFilterRecs::AddObjRecs()
977 if( pFilterInfo )
979 ScAddress aAddr( pFilterInfo->GetStartPos() );
980 for( SCCOL nObj = 0, nCount = pFilterInfo->GetColCount(); nObj < nCount; nObj++ )
982 XclObjDropDown* pObj = new XclObjDropDown( GetRoot(), aAddr, IsFiltered( nObj ) );
983 GetOldRoot().pObjRecs->Add( pObj );
984 aAddr.IncCol( 1 );
989 void ExcAutoFilterRecs::Save( XclExpStream& rStrm )
991 if( pFilterMode )
992 pFilterMode->Save( rStrm );
993 if( pFilterInfo )
994 pFilterInfo->Save( rStrm );
995 maFilterList.Save( rStrm );
998 void ExcAutoFilterRecs::SaveXml( XclExpXmlStream& rStrm )
1000 if( maFilterList.IsEmpty() )
1001 return;
1003 sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
1004 rWorksheet->startElement( XML_autoFilter,
1005 XML_ref, XclXmlUtils::ToOString( maRef ).getStr(),
1006 FSEND );
1007 // OOXTODO: XML_extLst, XML_sortState
1008 maFilterList.SaveXml( rStrm );
1009 rWorksheet->endElement( XML_autoFilter );
1012 bool ExcAutoFilterRecs::HasFilterMode() const
1014 return pFilterMode != NULL;
1017 // ----------------------------------------------------------------------------
1019 XclExpFilterManager::XclExpFilterManager( const XclExpRoot& rRoot ) :
1020 XclExpRoot( rRoot )
1024 void XclExpFilterManager::InitTabFilter( SCTAB nScTab )
1026 maFilterMap[ nScTab ].reset( new ExcAutoFilterRecs( GetRoot(), nScTab ) );
1029 XclExpRecordRef XclExpFilterManager::CreateRecord( SCTAB nScTab )
1031 XclExpTabFilterRef xRec;
1032 XclExpTabFilterMap::iterator aIt = maFilterMap.find( nScTab );
1033 if( aIt != maFilterMap.end() )
1035 xRec = aIt->second;
1036 xRec->AddObjRecs();
1038 return xRec;
1041 bool XclExpFilterManager::HasFilterMode( SCTAB nScTab )
1043 XclExpTabFilterRef xRec;
1044 XclExpTabFilterMap::iterator aIt = maFilterMap.find( nScTab );
1045 if( aIt != maFilterMap.end() )
1047 return aIt->second->HasFilterMode();
1049 return false;
1052 // ============================================================================