update dev300-m58
[ooovba.git] / sc / source / filter / excel / excrecds.cxx
blobd6584c76d9a279cb3e318c97a79054616a9cd386
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
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 0xe1, 0x00, 0x00, 0x00, // INTERFACEHDR
111 0xc1, 0x00, 0x02, 0x00, 0x00, 0x00, // MMS
112 0xbf, 0x00, 0x00, 0x00, // TOOLBARHDR
113 0xc0, 0x00, 0x00, 0x00, // TOOLBAREND
114 0xe2, 0x00, 0x00, 0x00, // INTERFACEEND
115 0x5c, 0x00, 0x20, 0x00, 0x04, 0x4d, 0x72, 0x20, 0x58, // WRITEACCESS
116 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
117 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
118 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
119 0x42, 0x00, 0x02, 0x00, 0xe4, 0x04, // CODEPAGE
120 0x9c, 0x00, 0x02, 0x00, 0x0e, 0x00 // FNGROUPCOUNT
122 const sal_Size ExcDummy_00::nMyLen = sizeof( ExcDummy_00::pMyData );
124 //-------------------------------------------------------- class ExcDummy_04x -
125 const BYTE ExcDummy_040::pMyData[] = {
126 0x40, 0x00, 0x02, 0x00, 0x00, 0x00, // BACKUP
127 0x8d, 0x00, 0x02, 0x00, 0x00, 0x00, // HIDEOBJ
129 const sal_Size ExcDummy_040::nMyLen = sizeof( ExcDummy_040::pMyData );
131 const BYTE ExcDummy_041::pMyData[] = {
132 0x0e, 0x00, 0x02, 0x00, 0x01, 0x00, // PRECISION
133 0xda, 0x00, 0x02, 0x00, 0x00, 0x00 // BOOKBOOL
135 const sal_Size ExcDummy_041::nMyLen = sizeof( ExcDummy_041::pMyData );
137 //-------------------------------------------------------- class ExcDummy_02a -
138 const BYTE ExcDummy_02a::pMyData[] = {
139 0x0d, 0x00, 0x02, 0x00, 0x01, 0x00, // CALCMODE
140 0x0c, 0x00, 0x02, 0x00, 0x64, 0x00, // CALCCOUNT
141 0x0f, 0x00, 0x02, 0x00, 0x01, 0x00, // REFMODE
142 0x11, 0x00, 0x02, 0x00, 0x00, 0x00, // ITERATION
143 0x10, 0x00, 0x08, 0x00, 0xfc, 0xa9, 0xf1, 0xd2, 0x4d, // DELTA
144 0x62, 0x50, 0x3f,
145 0x5f, 0x00, 0x02, 0x00, 0x01, 0x00 // SAVERECALC
147 const sal_Size ExcDummy_02a::nMyLen = sizeof( ExcDummy_02a::pMyData );
149 //----------------------------------------------------------- class ExcRecord -
151 void ExcRecord::Save( XclExpStream& rStrm )
153 SetRecHeader( GetNum(), GetLen() );
154 XclExpRecord::Save( rStrm );
157 void ExcRecord::SaveCont( XclExpStream& /*rStrm*/ )
161 void ExcRecord::WriteBody( XclExpStream& rStrm )
163 SaveCont( rStrm );
167 //--------------------------------------------------------- class ExcEmptyRec -
169 void ExcEmptyRec::Save( XclExpStream& /*rStrm*/ )
174 UINT16 ExcEmptyRec::GetNum() const
176 return 0;
180 sal_Size ExcEmptyRec::GetLen() const
182 return 0;
187 //------------------------------------------------------- class ExcRecordList -
189 ExcRecordList::~ExcRecordList()
191 for( ExcRecord* pRec = First(); pRec; pRec = Next() )
192 delete pRec;
196 void ExcRecordList::Save( XclExpStream& rStrm )
198 for( ExcRecord* pRec = First(); pRec; pRec = Next() )
199 pRec->Save( rStrm );
204 //--------------------------------------------------------- class ExcDummyRec -
206 void ExcDummyRec::Save( XclExpStream& rStrm )
208 rStrm.Write( GetData(), GetLen() ); // raw write mode
212 UINT16 ExcDummyRec::GetNum( void ) const
214 return 0x0000;
219 //------------------------------------------------------- class ExcBoolRecord -
221 void ExcBoolRecord::SaveCont( XclExpStream& rStrm )
223 rStrm << (UINT16)(bVal ? 0x0001 : 0x0000);
227 sal_Size ExcBoolRecord::GetLen( void ) const
229 return 2;
235 //--------------------------------------------------------- class ExcBof_Base -
237 ExcBof_Base::ExcBof_Base() :
238 nRupBuild( 0x096C ), // copied from Excel
239 nRupYear( 0x07C9 ) // copied from Excel
245 //-------------------------------------------------------------- class ExcBof -
247 ExcBof::ExcBof( void )
249 nDocType = 0x0010;
250 nVers = 0x0500;
254 void ExcBof::SaveCont( XclExpStream& rStrm )
256 rStrm << nVers << nDocType << nRupBuild << nRupYear;
260 UINT16 ExcBof::GetNum( void ) const
262 return 0x0809;
266 sal_Size ExcBof::GetLen( void ) const
268 return 8;
273 //------------------------------------------------------------- class ExcBofW -
275 ExcBofW::ExcBofW( void )
277 nDocType = 0x0005;
278 nVers = 0x0500;
282 void ExcBofW::SaveCont( XclExpStream& rStrm )
284 rStrm << nVers << nDocType << nRupBuild << nRupYear;
289 UINT16 ExcBofW::GetNum( void ) const
291 return 0x0809;
296 sal_Size ExcBofW::GetLen( void ) const
298 return 8;
303 //-------------------------------------------------------------- class ExcEof -
305 UINT16 ExcEof::GetNum( void ) const
307 return 0x000A;
311 sal_Size ExcEof::GetLen( void ) const
313 return 0;
318 //----------------------------------------------------- class ExcFngroupcount -
320 void ExcFngroupcount::SaveCont( XclExpStream& rStrm )
322 rStrm << ( UINT16 ) 0x000E; // copied from Excel
326 UINT16 ExcFngroupcount::GetNum( void ) const
328 return 0x009C;
332 sal_Size ExcFngroupcount::GetLen( void ) const
334 return 2;
339 //--------------------------------------------------------- class ExcDummy_00 -
341 sal_Size ExcDummy_00::GetLen( void ) const
343 return nMyLen;
347 const BYTE* ExcDummy_00::GetData( void ) const
349 return pMyData;
354 //-------------------------------------------------------- class ExcDummy_04x -
356 sal_Size ExcDummy_040::GetLen( void ) const
358 return nMyLen;
362 const BYTE* ExcDummy_040::GetData( void ) const
364 return pMyData;
370 sal_Size ExcDummy_041::GetLen( void ) const
372 return nMyLen;
376 const BYTE* ExcDummy_041::GetData( void ) const
378 return pMyData;
383 //------------------------------------------------------------- class Exc1904 -
385 Exc1904::Exc1904( ScDocument& rDoc )
387 Date* pDate = rDoc.GetFormatTable()->GetNullDate();
388 bVal = pDate ? (*pDate == Date( 1, 1, 1904 )) : FALSE;
392 UINT16 Exc1904::GetNum( void ) const
394 return 0x0022;
398 void Exc1904::SaveXml( XclExpXmlStream& rStrm )
400 rStrm.WriteAttributes(
401 XML_date1904, XclXmlUtils::ToPsz( bVal ),
402 FSEND );
407 //------------------------------------------------------ class ExcBundlesheet -
409 ExcBundlesheetBase::ExcBundlesheetBase( RootData& rRootData, SCTAB nTabNum ) :
410 nStrPos( STREAM_SEEK_TO_END ),
411 nOwnPos( STREAM_SEEK_TO_END ),
412 nGrbit( rRootData.pER->GetTabInfo().IsVisibleTab( nTabNum ) ? 0x0000 : 0x0001 ),
413 nTab( nTabNum )
418 ExcBundlesheetBase::ExcBundlesheetBase() :
419 nStrPos( STREAM_SEEK_TO_END ),
420 nOwnPos( STREAM_SEEK_TO_END ),
421 nGrbit( 0x0000 ),
422 nTab( SCTAB_GLOBAL )
427 void ExcBundlesheetBase::UpdateStreamPos( XclExpStream& rStrm )
429 rStrm.SetSvStreamPos( nOwnPos );
430 rStrm.DisableEncryption();
431 rStrm << static_cast<sal_uInt32>(nStrPos);
432 rStrm.EnableEncryption();
436 UINT16 ExcBundlesheetBase::GetNum( void ) const
438 return 0x0085;
444 ExcBundlesheet::ExcBundlesheet( RootData& rRootData, SCTAB _nTab ) :
445 ExcBundlesheetBase( rRootData, _nTab )
447 String sTabName = rRootData.pER->GetTabInfo().GetScTabName( _nTab );
448 DBG_ASSERT( sTabName.Len() < 256, "ExcBundlesheet::ExcBundlesheet - table name too long" );
449 aName = ByteString( sTabName, rRootData.pER->GetTextEncoding() );
453 void ExcBundlesheet::SaveCont( XclExpStream& rStrm )
455 nOwnPos = rStrm.GetSvStreamPos();
456 rStrm << (UINT32) 0x00000000 // dummy (stream position of the sheet)
457 << nGrbit;
458 rStrm.WriteByteString( aName ); // 8 bit length, max 255 chars
462 sal_Size ExcBundlesheet::GetLen() const
464 return 7 + Min( aName.Len(), (xub_StrLen) 255 );
468 //--------------------------------------------------------- class ExcDummy_02 -
470 sal_Size ExcDummy_02a::GetLen( void ) const
472 return nMyLen;
475 const BYTE* ExcDummy_02a::GetData( void ) const
477 return pMyData;
479 //--------------------------------------------------------- class ExcDummy_02 -
481 XclExpCountry::XclExpCountry( const XclExpRoot& rRoot ) :
482 XclExpRecord( EXC_ID_COUNTRY, 4 )
484 /* #i31530# set document country as UI country too -
485 needed for correct behaviour of number formats. */
486 mnUICountry = mnDocCountry = static_cast< sal_uInt16 >(
487 ::svx::ConvertLanguageToCountry( rRoot.GetDocLanguage() ) );
490 void XclExpCountry::WriteBody( XclExpStream& rStrm )
492 rStrm << mnUICountry << mnDocCountry;
495 // XclExpWsbool ===============================================================
497 XclExpWsbool::XclExpWsbool( bool bFitToPages, SCTAB nScTab, XclExpFilterManager* pManager )
498 : XclExpUInt16Record( EXC_ID_WSBOOL, EXC_WSBOOL_DEFAULTFLAGS )
499 , mnScTab( nScTab )
500 , mpManager( pManager )
502 if( bFitToPages )
503 SetValue( GetValue() | EXC_WSBOOL_FITTOPAGE );
506 void XclExpWsbool::SaveXml( XclExpXmlStream& rStrm )
508 sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
509 rWorksheet->startElement( XML_sheetPr,
510 // OOXTODO: XML_syncHorizontal,
511 // OOXTODO: XML_syncVertical,
512 // OOXTODO: XML_syncRef,
513 // OOXTODO: XML_transitionEvaluation,
514 // OOXTODO: XML_transitionEntry,
515 // OOXTODO: XML_published,
516 // OOXTODO: XML_codeName,
517 XML_filterMode, mpManager ? XclXmlUtils::ToPsz( mpManager->HasFilterMode( mnScTab ) ) : NULL,
518 // OOXTODO: XML_enableFormatConditionsCalculation,
519 FSEND );
520 // OOXTODO: elements XML_tabColor, XML_outlinePr
521 rWorksheet->singleElement( XML_pageSetUpPr,
522 // OOXTODO: XML_autoPageBreaks,
523 XML_fitToPage, XclXmlUtils::ToPsz( GetValue() & EXC_WSBOOL_FITTOPAGE ),
524 FSEND );
525 rWorksheet->endElement( XML_sheetPr );
529 // XclExpWindowProtection ===============================================================
531 XclExpWindowProtection::XclExpWindowProtection(bool bValue) :
532 XclExpBoolRecord(EXC_ID_WINDOWPROTECT, bValue)
536 void XclExpWindowProtection::SaveXml( XclExpXmlStream& rStrm )
538 rStrm.WriteAttributes(
539 XML_lockWindows, XclXmlUtils::ToPsz( GetBool() ),
540 FSEND );
543 // XclExpDocProtection ===============================================================
545 XclExpProtection::XclExpProtection(bool bValue) :
546 XclExpBoolRecord(EXC_ID_PROTECT, bValue)
550 // ============================================================================
552 XclExpPassHash::XclExpPassHash(const Sequence<sal_Int8>& aHash) :
553 XclExpRecord(EXC_ID_PASSWORD, 2),
554 mnHash(0x0000)
556 if (aHash.getLength() >= 2)
558 mnHash = ((aHash[0] << 8) & 0xFFFF);
559 mnHash |= (aHash[1] & 0xFF);
563 XclExpPassHash::~XclExpPassHash()
567 void XclExpPassHash::WriteBody(XclExpStream& rStrm)
569 rStrm << mnHash;
572 // ============================================================================
574 XclExpFiltermode::XclExpFiltermode() :
575 XclExpEmptyRecord( EXC_ID_FILTERMODE )
579 // ----------------------------------------------------------------------------
581 XclExpAutofilterinfo::XclExpAutofilterinfo( const ScAddress& rStartPos, SCCOL nScCol ) :
582 XclExpUInt16Record( EXC_ID_AUTOFILTERINFO, static_cast< sal_uInt16 >( nScCol ) ),
583 maStartPos( rStartPos )
587 // ----------------------------------------------------------------------------
589 ExcFilterCondition::ExcFilterCondition() :
590 nType( EXC_AFTYPE_NOTUSED ),
591 nOper( EXC_AFOPER_EQUAL ),
592 fVal( 0.0 ),
593 pText( NULL )
597 ExcFilterCondition::~ExcFilterCondition()
599 if( pText )
600 delete pText;
603 sal_Size ExcFilterCondition::GetTextBytes() const
605 return pText ? (1 + pText->GetBufferSize()) : 0;
608 void ExcFilterCondition::SetCondition( UINT8 nTp, UINT8 nOp, double fV, String* pT )
610 nType = nTp;
611 nOper = nOp;
612 fVal = fV;
614 delete pText;
615 pText = pT ? new XclExpString( *pT, EXC_STR_8BITLENGTH ) : NULL;
618 void ExcFilterCondition::Save( XclExpStream& rStrm )
620 rStrm << nType << nOper;
621 switch( nType )
623 case EXC_AFTYPE_DOUBLE:
624 rStrm << fVal;
625 break;
626 case EXC_AFTYPE_STRING:
627 DBG_ASSERT( pText, "ExcFilterCondition::Save() -- pText is NULL!" );
628 rStrm << (UINT32)0 << (UINT8) pText->Len() << (UINT16)0 << (UINT8)0;
629 break;
630 case EXC_AFTYPE_BOOLERR:
631 rStrm << (UINT8)0 << (UINT8)((fVal != 0) ? 1 : 0) << (UINT32)0 << (UINT16)0;
632 break;
633 default:
634 rStrm << (UINT32)0 << (UINT32)0;
638 static const char* lcl_GetOperator( UINT8 nOper )
640 switch( nOper )
642 case EXC_AFOPER_EQUAL: return "equal";
643 case EXC_AFOPER_GREATER: return "greaterThan";
644 case EXC_AFOPER_GREATEREQUAL: return "greaterThanOrEqual";
645 case EXC_AFOPER_LESS: return "lessThan";
646 case EXC_AFOPER_LESSEQUAL: return "lessThanOrEqual";
647 case EXC_AFOPER_NOTEQUAL: return "notEqual";
648 case EXC_AFOPER_NONE:
649 default: return "**none**";
653 static OString lcl_GetValue( UINT8 nType, double fVal, XclExpString* pStr )
655 switch( nType )
657 case EXC_AFTYPE_STRING: return XclXmlUtils::ToOString( *pStr );
658 case EXC_AFTYPE_DOUBLE: return OString::valueOf( fVal );
659 case EXC_AFTYPE_BOOLERR: return OString::valueOf( (sal_Int32) ( fVal != 0 ? 1 : 0 ) );
660 default: return OString();
664 void ExcFilterCondition::SaveXml( XclExpXmlStream& rStrm )
666 if( IsEmpty() )
667 return;
669 rStrm.GetCurrentStream()->singleElement( XML_customFilter,
670 XML_operator, lcl_GetOperator( nOper ),
671 XML_val, lcl_GetValue( nType, fVal, pText ).getStr(),
672 FSEND );
675 void ExcFilterCondition::SaveText( XclExpStream& rStrm )
677 if( nType == EXC_AFTYPE_STRING )
679 DBG_ASSERT( pText, "ExcFilterCondition::SaveText() -- pText is NULL!" );
680 pText->WriteFlagField( rStrm );
681 pText->WriteBuffer( rStrm );
685 // ----------------------------------------------------------------------------
687 XclExpAutofilter::XclExpAutofilter( const XclExpRoot& rRoot, UINT16 nC ) :
688 XclExpRecord( EXC_ID_AUTOFILTER, 24 ),
689 XclExpRoot( rRoot ),
690 nCol( nC ),
691 nFlags( 0 )
695 BOOL XclExpAutofilter::AddCondition( ScQueryConnect eConn, UINT8 nType, UINT8 nOp,
696 double fVal, String* pText, BOOL bSimple )
698 if( !aCond[ 1 ].IsEmpty() )
699 return FALSE;
701 UINT16 nInd = aCond[ 0 ].IsEmpty() ? 0 : 1;
703 if( nInd == 1 )
704 nFlags |= (eConn == SC_OR) ? EXC_AFFLAG_OR : EXC_AFFLAG_AND;
705 if( bSimple )
706 nFlags |= (nInd == 0) ? EXC_AFFLAG_SIMPLE1 : EXC_AFFLAG_SIMPLE2;
708 aCond[ nInd ].SetCondition( nType, nOp, fVal, pText );
710 AddRecSize( aCond[ nInd ].GetTextBytes() );
712 return TRUE;
715 BOOL XclExpAutofilter::AddEntry( const ScQueryEntry& rEntry )
717 BOOL bConflict = FALSE;
718 String sText;
720 if( rEntry.pStr )
722 sText.Assign( *rEntry.pStr );
723 switch( rEntry.eOp )
725 case SC_CONTAINS:
726 case SC_DOES_NOT_CONTAIN:
728 sText.InsertAscii( "*" , 0 );
729 sText.AppendAscii( "*" );
731 break;
732 case SC_BEGINS_WITH:
733 case SC_DOES_NOT_BEGIN_WITH:
734 sText.AppendAscii( "*" );
735 break;
736 case SC_ENDS_WITH:
737 case SC_DOES_NOT_END_WITH:
738 sText.InsertAscii( "*" , 0 );
739 break;
740 default:
742 //nothing
747 BOOL bLen = sText.Len() > 0;
749 // empty/nonempty fields
750 if( !bLen && (rEntry.nVal == SC_EMPTYFIELDS) )
751 bConflict = !AddCondition( rEntry.eConnect, EXC_AFTYPE_EMPTY, EXC_AFOPER_NONE, 0.0, NULL, TRUE );
752 else if( !bLen && (rEntry.nVal == SC_NONEMPTYFIELDS) )
753 bConflict = !AddCondition( rEntry.eConnect, EXC_AFTYPE_NOTEMPTY, EXC_AFOPER_NONE, 0.0, NULL, TRUE );
754 // other conditions
755 else
757 double fVal = 0.0;
758 sal_uInt32 nIndex = 0;
759 BOOL bIsNum = bLen ? GetFormatter().IsNumberFormat( sText, nIndex, fVal ) : TRUE;
760 String* pText = bIsNum ? NULL : &sText;
762 // top10 flags
763 UINT16 nNewFlags = 0x0000;
764 switch( rEntry.eOp )
766 case SC_TOPVAL:
767 nNewFlags = (EXC_AFFLAG_TOP10 | EXC_AFFLAG_TOP10TOP);
768 break;
769 case SC_BOTVAL:
770 nNewFlags = EXC_AFFLAG_TOP10;
771 break;
772 case SC_TOPPERC:
773 nNewFlags = (EXC_AFFLAG_TOP10 | EXC_AFFLAG_TOP10TOP | EXC_AFFLAG_TOP10PERC);
774 break;
775 case SC_BOTPERC:
776 nNewFlags = (EXC_AFFLAG_TOP10 | EXC_AFFLAG_TOP10PERC);
777 break;
778 default:;
780 BOOL bNewTop10 = ::get_flag( nNewFlags, EXC_AFFLAG_TOP10 );
782 bConflict = HasTop10() && bNewTop10;
783 if( !bConflict )
785 if( bNewTop10 )
787 if( fVal < 0 ) fVal = 0;
788 if( fVal >= 501 ) fVal = 500;
789 nFlags |= (nNewFlags | (UINT16)(fVal) << 7);
791 // normal condition
792 else
794 UINT8 nType = bIsNum ? EXC_AFTYPE_DOUBLE : EXC_AFTYPE_STRING;
795 UINT8 nOper = EXC_AFOPER_NONE;
797 switch( rEntry.eOp )
799 case SC_EQUAL: nOper = EXC_AFOPER_EQUAL; break;
800 case SC_LESS: nOper = EXC_AFOPER_LESS; break;
801 case SC_GREATER: nOper = EXC_AFOPER_GREATER; break;
802 case SC_LESS_EQUAL: nOper = EXC_AFOPER_LESSEQUAL; break;
803 case SC_GREATER_EQUAL: nOper = EXC_AFOPER_GREATEREQUAL; break;
804 case SC_NOT_EQUAL: nOper = EXC_AFOPER_NOTEQUAL; break;
805 case SC_CONTAINS:
806 case SC_BEGINS_WITH:
807 case SC_ENDS_WITH:
808 nOper = EXC_AFOPER_EQUAL; break;
809 case SC_DOES_NOT_CONTAIN:
810 case SC_DOES_NOT_BEGIN_WITH:
811 case SC_DOES_NOT_END_WITH:
812 nOper = EXC_AFOPER_NOTEQUAL; break;
813 default:;
815 bConflict = !AddCondition( rEntry.eConnect, nType, nOper, fVal, pText );
819 return bConflict;
822 void XclExpAutofilter::WriteBody( XclExpStream& rStrm )
824 rStrm << nCol << nFlags;
825 aCond[ 0 ].Save( rStrm );
826 aCond[ 1 ].Save( rStrm );
827 aCond[ 0 ].SaveText( rStrm );
828 aCond[ 1 ].SaveText( rStrm );
831 void XclExpAutofilter::SaveXml( XclExpXmlStream& rStrm )
833 if( !HasCondition() )
834 return;
836 sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
838 rWorksheet->startElement( XML_filterColumn,
839 XML_colId, OString::valueOf( (sal_Int32) nCol ).getStr(),
840 // OOXTODO: XML_hiddenButton, AutoFilter12 fHideArrow?
841 // OOXTODO: XML_showButton,
842 FSEND );
844 if( HasTop10() )
846 rWorksheet->singleElement( XML_top10,
847 XML_top, XclXmlUtils::ToPsz( get_flag( nFlags, EXC_AFFLAG_TOP10TOP ) ),
848 XML_percent, XclXmlUtils::ToPsz( get_flag( nFlags, EXC_AFFLAG_TOP10PERC ) ),
849 XML_val, OString::valueOf( (sal_Int32) (nFlags >> 7 ) ).getStr(),
850 // OOXTODO: XML_filterVal,
851 FSEND );
854 rWorksheet->startElement( XML_customFilters,
855 XML_and, XclXmlUtils::ToPsz( (nFlags & EXC_AFFLAG_ANDORMASK) == EXC_AFFLAG_AND ),
856 FSEND );
857 aCond[ 0 ].SaveXml( rStrm );
858 aCond[ 1 ].SaveXml( rStrm );
859 rWorksheet->endElement( XML_customFilters );
860 // OOXTODO: XLM_colorFilter, XML_dynamicFilter,
861 // XML_extLst, XML_filters, XML_iconFilter, XML_top10
862 rWorksheet->endElement( XML_filterColumn );
865 // ----------------------------------------------------------------------------
867 ExcAutoFilterRecs::ExcAutoFilterRecs( const XclExpRoot& rRoot, SCTAB nTab ) :
868 XclExpRoot( rRoot ),
869 pFilterMode( NULL ),
870 pFilterInfo( NULL )
872 ScDBCollection& rDBColl = GetDatabaseRanges();
873 XclExpNameManager& rNameMgr = GetNameManager();
875 // search for first DB-range with filter
876 UINT16 nIndex = 0;
877 BOOL bFound = FALSE;
878 BOOL bAdvanced = FALSE;
879 ScDBData* pData = NULL;
880 ScRange aAdvRange;
881 while( (nIndex < rDBColl.GetCount()) && !bFound )
883 pData = rDBColl[ nIndex ];
884 if( pData )
886 ScRange aRange;
887 pData->GetArea( aRange );
888 bAdvanced = pData->GetAdvancedQuerySource( aAdvRange );
889 bFound = (aRange.aStart.Tab() == nTab) &&
890 (pData->HasQueryParam() || pData->HasAutoFilter() || bAdvanced);
892 if( !bFound )
893 nIndex++;
896 if( pData && bFound )
898 ScQueryParam aParam;
899 pData->GetQueryParam( aParam );
901 ScRange aRange( aParam.nCol1, aParam.nRow1, aParam.nTab,
902 aParam.nCol2, aParam.nRow2, aParam.nTab );
903 SCCOL nColCnt = aParam.nCol2 - aParam.nCol1 + 1;
905 maRef = aRange;
907 // #i2394# #100489# built-in defined names must be sorted by containing sheet name
908 rNameMgr.InsertBuiltInName( EXC_BUILTIN_FILTERDATABASE, aRange );
910 // advanced filter
911 if( bAdvanced )
913 // filter criteria, excel allows only same table
914 if( aAdvRange.aStart.Tab() == nTab )
915 rNameMgr.InsertBuiltInName( EXC_BUILTIN_CRITERIA, aAdvRange );
917 // filter destination range, excel allows only same table
918 if( !aParam.bInplace )
920 ScRange aDestRange( aParam.nDestCol, aParam.nDestRow, aParam.nDestTab );
921 aDestRange.aEnd.IncCol( nColCnt - 1 );
922 if( aDestRange.aStart.Tab() == nTab )
923 rNameMgr.InsertBuiltInName( EXC_BUILTIN_EXTRACT, aDestRange );
926 pFilterMode = new XclExpFiltermode;
928 // AutoFilter
929 else
931 BOOL bConflict = FALSE;
932 BOOL bContLoop = TRUE;
933 BOOL bHasOr = FALSE;
934 SCCOLROW nFirstField = aParam.GetEntry( 0 ).nField;
936 // create AUTOFILTER records for filtered columns
937 for( SCSIZE nEntry = 0; !bConflict && bContLoop && (nEntry < aParam.GetEntryCount()); nEntry++ )
939 const ScQueryEntry& rEntry = aParam.GetEntry( nEntry );
941 bContLoop = rEntry.bDoQuery;
942 if( bContLoop )
944 XclExpAutofilter* pFilter = GetByCol( static_cast<SCCOL>(rEntry.nField) - aRange.aStart.Col() );
946 if( nEntry > 0 )
947 bHasOr |= (rEntry.eConnect == SC_OR);
949 bConflict = (nEntry > 1) && bHasOr;
950 if( !bConflict )
951 bConflict = (nEntry == 1) && (rEntry.eConnect == SC_OR) &&
952 (nFirstField != rEntry.nField);
953 if( !bConflict )
954 bConflict = pFilter->AddEntry( rEntry );
958 // additional tests for conflicts
959 for( size_t nPos = 0, nSize = maFilterList.GetSize(); !bConflict && (nPos < nSize); ++nPos )
961 XclExpAutofilterRef xFilter = maFilterList.GetRecord( nPos );
962 bConflict = xFilter->HasCondition() && xFilter->HasTop10();
965 if( bConflict )
966 maFilterList.RemoveAllRecords();
968 if( !maFilterList.IsEmpty() )
969 pFilterMode = new XclExpFiltermode;
970 pFilterInfo = new XclExpAutofilterinfo( aRange.aStart, nColCnt );
975 ExcAutoFilterRecs::~ExcAutoFilterRecs()
977 delete pFilterMode;
978 delete pFilterInfo;
981 XclExpAutofilter* ExcAutoFilterRecs::GetByCol( SCCOL nCol )
983 XclExpAutofilterRef xFilter;
984 for( size_t nPos = 0, nSize = maFilterList.GetSize(); nPos < nSize; ++nPos )
986 xFilter = maFilterList.GetRecord( nPos );
987 if( xFilter->GetCol() == static_cast<sal_uInt16>(nCol) )
988 return xFilter.get();
990 xFilter.reset( new XclExpAutofilter( GetRoot(), static_cast<sal_uInt16>(nCol) ) );
991 maFilterList.AppendRecord( xFilter );
992 return xFilter.get();
995 BOOL ExcAutoFilterRecs::IsFiltered( SCCOL nCol )
997 for( size_t nPos = 0, nSize = maFilterList.GetSize(); nPos < nSize; ++nPos )
998 if( maFilterList.GetRecord( nPos )->GetCol() == static_cast<sal_uInt16>(nCol) )
999 return TRUE;
1000 return FALSE;
1003 void ExcAutoFilterRecs::AddObjRecs()
1005 if( pFilterInfo )
1007 ScAddress aAddr( pFilterInfo->GetStartPos() );
1008 for( SCCOL nObj = 0, nCount = pFilterInfo->GetColCount(); nObj < nCount; nObj++ )
1010 XclObjDropDown* pObj = new XclObjDropDown( GetRoot(), aAddr, IsFiltered( nObj ) );
1011 GetOldRoot().pObjRecs->Add( pObj );
1012 aAddr.IncCol( 1 );
1017 void ExcAutoFilterRecs::Save( XclExpStream& rStrm )
1019 if( pFilterMode )
1020 pFilterMode->Save( rStrm );
1021 if( pFilterInfo )
1022 pFilterInfo->Save( rStrm );
1023 maFilterList.Save( rStrm );
1026 void ExcAutoFilterRecs::SaveXml( XclExpXmlStream& rStrm )
1028 if( maFilterList.IsEmpty() )
1029 return;
1031 sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
1032 rWorksheet->startElement( XML_autoFilter,
1033 XML_ref, XclXmlUtils::ToOString( maRef ).getStr(),
1034 FSEND );
1035 // OOXTODO: XML_extLst, XML_sortState
1036 maFilterList.SaveXml( rStrm );
1037 rWorksheet->endElement( XML_autoFilter );
1040 bool ExcAutoFilterRecs::HasFilterMode() const
1042 return pFilterMode != NULL;
1045 // ----------------------------------------------------------------------------
1047 XclExpFilterManager::XclExpFilterManager( const XclExpRoot& rRoot ) :
1048 XclExpRoot( rRoot )
1052 void XclExpFilterManager::InitTabFilter( SCTAB nScTab )
1054 maFilterMap[ nScTab ].reset( new ExcAutoFilterRecs( GetRoot(), nScTab ) );
1057 XclExpRecordRef XclExpFilterManager::CreateRecord( SCTAB nScTab )
1059 XclExpTabFilterRef xRec;
1060 XclExpTabFilterMap::iterator aIt = maFilterMap.find( nScTab );
1061 if( aIt != maFilterMap.end() )
1063 xRec = aIt->second;
1064 xRec->AddObjRecs();
1066 return xRec;
1069 bool XclExpFilterManager::HasFilterMode( SCTAB nScTab )
1071 XclExpTabFilterRef xRec;
1072 XclExpTabFilterMap::iterator aIt = maFilterMap.find( nScTab );
1073 if( aIt != maFilterMap.end() )
1075 return aIt->second->HasFilterMode();
1077 return false;
1080 // ============================================================================