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 $
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"
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>
76 #include "globstr.hrc"
77 #include "docpool.hxx"
78 #include "patattr.hxx"
80 #include "document.hxx"
81 #include "scextopt.hxx"
82 #include "patattr.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"
94 #include "xeformula.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
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
)
160 //--------------------------------------------------------- class ExcEmptyRec -
162 void ExcEmptyRec::Save( XclExpStream
& /*rStrm*/ )
167 UINT16
ExcEmptyRec::GetNum() const
173 sal_Size
ExcEmptyRec::GetLen() const
180 //------------------------------------------------------- class ExcRecordList -
182 ExcRecordList::~ExcRecordList()
184 for( ExcRecord
* pRec
= First(); pRec
; pRec
= Next() )
189 void ExcRecordList::Save( XclExpStream
& rStrm
)
191 for( ExcRecord
* pRec
= First(); pRec
; pRec
= Next() )
197 //--------------------------------------------------------- class ExcDummyRec -
199 void ExcDummyRec::Save( XclExpStream
& rStrm
)
201 rStrm
.Write( GetData(), GetLen() ); // raw write mode
205 UINT16
ExcDummyRec::GetNum( void ) const
212 //------------------------------------------------------- class ExcBoolRecord -
214 void ExcBoolRecord::SaveCont( XclExpStream
& rStrm
)
216 rStrm
<< (UINT16
)(bVal
? 0x0001 : 0x0000);
220 sal_Size
ExcBoolRecord::GetLen( void ) const
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 )
247 void ExcBof::SaveCont( XclExpStream
& rStrm
)
249 rStrm
<< nVers
<< nDocType
<< nRupBuild
<< nRupYear
;
253 UINT16
ExcBof::GetNum( void ) const
259 sal_Size
ExcBof::GetLen( void ) const
266 //------------------------------------------------------------- class ExcBofW -
268 ExcBofW::ExcBofW( void )
275 void ExcBofW::SaveCont( XclExpStream
& rStrm
)
277 rStrm
<< nVers
<< nDocType
<< nRupBuild
<< nRupYear
;
282 UINT16
ExcBofW::GetNum( void ) const
289 sal_Size
ExcBofW::GetLen( void ) const
296 //-------------------------------------------------------------- class ExcEof -
298 UINT16
ExcEof::GetNum( void ) const
304 sal_Size
ExcEof::GetLen( void ) const
311 //--------------------------------------------------------- class ExcDummy_00 -
313 sal_Size
ExcDummy_00::GetLen( void ) const
319 const BYTE
* ExcDummy_00::GetData( void ) const
326 //-------------------------------------------------------- class ExcDummy_04x -
328 sal_Size
ExcDummy_040::GetLen( void ) const
334 const BYTE
* ExcDummy_040::GetData( void ) const
342 sal_Size
ExcDummy_041::GetLen( void ) const
348 const BYTE
* ExcDummy_041::GetData( void ) const
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
370 void Exc1904::SaveXml( XclExpXmlStream
& rStrm
)
372 rStrm
.WriteAttributes(
373 XML_date1904
, XclXmlUtils::ToPsz( bVal
),
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 ),
390 ExcBundlesheetBase::ExcBundlesheetBase() :
391 nStrPos( STREAM_SEEK_TO_END
),
392 nOwnPos( STREAM_SEEK_TO_END
),
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
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)
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
447 const BYTE
* ExcDummy_02a::GetData( void ) const
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
)
472 , mpManager( pManager
)
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,
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
),
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() ),
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),
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
)
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
),
569 ExcFilterCondition::~ExcFilterCondition()
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
)
587 pText
= pT
? new XclExpString( *pT
, EXC_STR_8BITLENGTH
) : NULL
;
590 void ExcFilterCondition::Save( XclExpStream
& rStrm
)
592 rStrm
<< nType
<< nOper
;
595 case EXC_AFTYPE_DOUBLE
:
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;
602 case EXC_AFTYPE_BOOLERR
:
603 rStrm
<< (UINT8
)0 << (UINT8
)((fVal
!= 0) ? 1 : 0) << (UINT32
)0 << (UINT16
)0;
606 rStrm
<< (UINT32
)0 << (UINT32
)0;
610 static const char* lcl_GetOperator( UINT8 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
)
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
)
641 rStrm
.GetCurrentStream()->singleElement( XML_customFilter
,
642 XML_operator
, lcl_GetOperator( nOper
),
643 XML_val
, lcl_GetValue( nType
, fVal
, pText
).getStr(),
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 ),
667 BOOL
XclExpAutofilter::AddCondition( ScQueryConnect eConn
, UINT8 nType
, UINT8 nOp
,
668 double fVal
, String
* pText
, BOOL bSimple
)
670 if( !aCond
[ 1 ].IsEmpty() )
673 UINT16 nInd
= aCond
[ 0 ].IsEmpty() ? 0 : 1;
676 nFlags
|= (eConn
== SC_OR
) ? EXC_AFFLAG_OR
: EXC_AFFLAG_AND
;
678 nFlags
|= (nInd
== 0) ? EXC_AFFLAG_SIMPLE1
: EXC_AFFLAG_SIMPLE2
;
680 aCond
[ nInd
].SetCondition( nType
, nOp
, fVal
, pText
);
682 AddRecSize( aCond
[ nInd
].GetTextBytes() );
687 BOOL
XclExpAutofilter::AddEntry( const ScQueryEntry
& rEntry
)
689 BOOL bConflict
= FALSE
;
694 sText
.Assign( *rEntry
.pStr
);
698 case SC_DOES_NOT_CONTAIN
:
700 sText
.InsertAscii( "*" , 0 );
701 sText
.AppendAscii( "*" );
705 case SC_DOES_NOT_BEGIN_WITH
:
706 sText
.AppendAscii( "*" );
709 case SC_DOES_NOT_END_WITH
:
710 sText
.InsertAscii( "*" , 0 );
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
);
730 sal_uInt32 nIndex
= 0;
731 BOOL bIsNum
= bLen
? GetFormatter().IsNumberFormat( sText
, nIndex
, fVal
) : TRUE
;
732 String
* pText
= bIsNum
? NULL
: &sText
;
735 UINT16 nNewFlags
= 0x0000;
739 nNewFlags
= (EXC_AFFLAG_TOP10
| EXC_AFFLAG_TOP10TOP
);
742 nNewFlags
= EXC_AFFLAG_TOP10
;
745 nNewFlags
= (EXC_AFFLAG_TOP10
| EXC_AFFLAG_TOP10TOP
| EXC_AFFLAG_TOP10PERC
);
748 nNewFlags
= (EXC_AFFLAG_TOP10
| EXC_AFFLAG_TOP10PERC
);
752 BOOL bNewTop10
= ::get_flag( nNewFlags
, EXC_AFFLAG_TOP10
);
754 bConflict
= HasTop10() && bNewTop10
;
759 if( fVal
< 0 ) fVal
= 0;
760 if( fVal
>= 501 ) fVal
= 500;
761 nFlags
|= (nNewFlags
| (UINT16
)(fVal
) << 7);
766 UINT8 nType
= bIsNum
? EXC_AFTYPE_DOUBLE
: EXC_AFTYPE_STRING
;
767 UINT8 nOper
= EXC_AFOPER_NONE
;
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;
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;
787 bConflict
= !AddCondition( rEntry
.eConnect
, nType
, nOper
, fVal
, pText
);
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() )
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,
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,
826 rWorksheet
->startElement( XML_customFilters
,
827 XML_and
, XclXmlUtils::ToPsz( (nFlags
& EXC_AFFLAG_ANDORMASK
) == EXC_AFFLAG_AND
),
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
) :
844 ScDBCollection
& rDBColl
= GetDatabaseRanges();
845 XclExpNameManager
& rNameMgr
= GetNameManager();
847 // search for first DB-range with filter
850 BOOL bAdvanced
= FALSE
;
851 ScDBData
* pData
= NULL
;
853 while( (nIndex
< rDBColl
.GetCount()) && !bFound
)
855 pData
= rDBColl
[ nIndex
];
859 pData
->GetArea( aRange
);
860 bAdvanced
= pData
->GetAdvancedQuerySource( aAdvRange
);
861 bFound
= (aRange
.aStart
.Tab() == nTab
) &&
862 (pData
->HasQueryParam() || pData
->HasAutoFilter() || bAdvanced
);
868 if( pData
&& bFound
)
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;
879 // #i2394# #100489# built-in defined names must be sorted by containing sheet name
880 rNameMgr
.InsertBuiltInName( EXC_BUILTIN_FILTERDATABASE
, aRange
);
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
;
903 BOOL bConflict
= FALSE
;
904 BOOL bContLoop
= TRUE
;
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
;
916 XclExpAutofilter
* pFilter
= GetByCol( static_cast<SCCOL
>(rEntry
.nField
) - aRange
.aStart
.Col() );
919 bHasOr
|= (rEntry
.eConnect
== SC_OR
);
921 bConflict
= (nEntry
> 1) && bHasOr
;
923 bConflict
= (nEntry
== 1) && (rEntry
.eConnect
== SC_OR
) &&
924 (nFirstField
!= rEntry
.nField
);
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();
938 maFilterList
.RemoveAllRecords();
940 if( !maFilterList
.IsEmpty() )
941 pFilterMode
= new XclExpFiltermode
;
942 pFilterInfo
= new XclExpAutofilterinfo( aRange
.aStart
, nColCnt
);
947 ExcAutoFilterRecs::~ExcAutoFilterRecs()
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
) )
975 void ExcAutoFilterRecs::AddObjRecs()
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
);
989 void ExcAutoFilterRecs::Save( XclExpStream
& rStrm
)
992 pFilterMode
->Save( rStrm
);
994 pFilterInfo
->Save( rStrm
);
995 maFilterList
.Save( rStrm
);
998 void ExcAutoFilterRecs::SaveXml( XclExpXmlStream
& rStrm
)
1000 if( maFilterList
.IsEmpty() )
1003 sax_fastparser::FSHelperPtr
& rWorksheet
= rStrm
.GetCurrentStream();
1004 rWorksheet
->startElement( XML_autoFilter
,
1005 XML_ref
, XclXmlUtils::ToOString( maRef
).getStr(),
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
) :
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() )
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();
1052 // ============================================================================