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 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
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
)
167 //--------------------------------------------------------- class ExcEmptyRec -
169 void ExcEmptyRec::Save( XclExpStream
& /*rStrm*/ )
174 UINT16
ExcEmptyRec::GetNum() const
180 sal_Size
ExcEmptyRec::GetLen() const
187 //------------------------------------------------------- class ExcRecordList -
189 ExcRecordList::~ExcRecordList()
191 for( ExcRecord
* pRec
= First(); pRec
; pRec
= Next() )
196 void ExcRecordList::Save( XclExpStream
& rStrm
)
198 for( ExcRecord
* pRec
= First(); pRec
; pRec
= Next() )
204 //--------------------------------------------------------- class ExcDummyRec -
206 void ExcDummyRec::Save( XclExpStream
& rStrm
)
208 rStrm
.Write( GetData(), GetLen() ); // raw write mode
212 UINT16
ExcDummyRec::GetNum( void ) const
219 //------------------------------------------------------- class ExcBoolRecord -
221 void ExcBoolRecord::SaveCont( XclExpStream
& rStrm
)
223 rStrm
<< (UINT16
)(bVal
? 0x0001 : 0x0000);
227 sal_Size
ExcBoolRecord::GetLen( void ) const
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 )
254 void ExcBof::SaveCont( XclExpStream
& rStrm
)
256 rStrm
<< nVers
<< nDocType
<< nRupBuild
<< nRupYear
;
260 UINT16
ExcBof::GetNum( void ) const
266 sal_Size
ExcBof::GetLen( void ) const
273 //------------------------------------------------------------- class ExcBofW -
275 ExcBofW::ExcBofW( void )
282 void ExcBofW::SaveCont( XclExpStream
& rStrm
)
284 rStrm
<< nVers
<< nDocType
<< nRupBuild
<< nRupYear
;
289 UINT16
ExcBofW::GetNum( void ) const
296 sal_Size
ExcBofW::GetLen( void ) const
303 //-------------------------------------------------------------- class ExcEof -
305 UINT16
ExcEof::GetNum( void ) const
311 sal_Size
ExcEof::GetLen( void ) const
318 //----------------------------------------------------- class ExcFngroupcount -
320 void ExcFngroupcount::SaveCont( XclExpStream
& rStrm
)
322 rStrm
<< ( UINT16
) 0x000E; // copied from Excel
326 UINT16
ExcFngroupcount::GetNum( void ) const
332 sal_Size
ExcFngroupcount::GetLen( void ) const
339 //--------------------------------------------------------- class ExcDummy_00 -
341 sal_Size
ExcDummy_00::GetLen( void ) const
347 const BYTE
* ExcDummy_00::GetData( void ) const
354 //-------------------------------------------------------- class ExcDummy_04x -
356 sal_Size
ExcDummy_040::GetLen( void ) const
362 const BYTE
* ExcDummy_040::GetData( void ) const
370 sal_Size
ExcDummy_041::GetLen( void ) const
376 const BYTE
* ExcDummy_041::GetData( void ) const
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
398 void Exc1904::SaveXml( XclExpXmlStream
& rStrm
)
400 rStrm
.WriteAttributes(
401 XML_date1904
, XclXmlUtils::ToPsz( bVal
),
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 ),
418 ExcBundlesheetBase::ExcBundlesheetBase() :
419 nStrPos( STREAM_SEEK_TO_END
),
420 nOwnPos( STREAM_SEEK_TO_END
),
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
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)
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
475 const BYTE
* ExcDummy_02a::GetData( void ) const
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
)
500 , mpManager( pManager
)
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,
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
),
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() ),
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),
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
)
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
),
597 ExcFilterCondition::~ExcFilterCondition()
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
)
615 pText
= pT
? new XclExpString( *pT
, EXC_STR_8BITLENGTH
) : NULL
;
618 void ExcFilterCondition::Save( XclExpStream
& rStrm
)
620 rStrm
<< nType
<< nOper
;
623 case EXC_AFTYPE_DOUBLE
:
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;
630 case EXC_AFTYPE_BOOLERR
:
631 rStrm
<< (UINT8
)0 << (UINT8
)((fVal
!= 0) ? 1 : 0) << (UINT32
)0 << (UINT16
)0;
634 rStrm
<< (UINT32
)0 << (UINT32
)0;
638 static const char* lcl_GetOperator( UINT8 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
)
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
)
669 rStrm
.GetCurrentStream()->singleElement( XML_customFilter
,
670 XML_operator
, lcl_GetOperator( nOper
),
671 XML_val
, lcl_GetValue( nType
, fVal
, pText
).getStr(),
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 ),
695 BOOL
XclExpAutofilter::AddCondition( ScQueryConnect eConn
, UINT8 nType
, UINT8 nOp
,
696 double fVal
, String
* pText
, BOOL bSimple
)
698 if( !aCond
[ 1 ].IsEmpty() )
701 UINT16 nInd
= aCond
[ 0 ].IsEmpty() ? 0 : 1;
704 nFlags
|= (eConn
== SC_OR
) ? EXC_AFFLAG_OR
: EXC_AFFLAG_AND
;
706 nFlags
|= (nInd
== 0) ? EXC_AFFLAG_SIMPLE1
: EXC_AFFLAG_SIMPLE2
;
708 aCond
[ nInd
].SetCondition( nType
, nOp
, fVal
, pText
);
710 AddRecSize( aCond
[ nInd
].GetTextBytes() );
715 BOOL
XclExpAutofilter::AddEntry( const ScQueryEntry
& rEntry
)
717 BOOL bConflict
= FALSE
;
722 sText
.Assign( *rEntry
.pStr
);
726 case SC_DOES_NOT_CONTAIN
:
728 sText
.InsertAscii( "*" , 0 );
729 sText
.AppendAscii( "*" );
733 case SC_DOES_NOT_BEGIN_WITH
:
734 sText
.AppendAscii( "*" );
737 case SC_DOES_NOT_END_WITH
:
738 sText
.InsertAscii( "*" , 0 );
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
);
758 sal_uInt32 nIndex
= 0;
759 BOOL bIsNum
= bLen
? GetFormatter().IsNumberFormat( sText
, nIndex
, fVal
) : TRUE
;
760 String
* pText
= bIsNum
? NULL
: &sText
;
763 UINT16 nNewFlags
= 0x0000;
767 nNewFlags
= (EXC_AFFLAG_TOP10
| EXC_AFFLAG_TOP10TOP
);
770 nNewFlags
= EXC_AFFLAG_TOP10
;
773 nNewFlags
= (EXC_AFFLAG_TOP10
| EXC_AFFLAG_TOP10TOP
| EXC_AFFLAG_TOP10PERC
);
776 nNewFlags
= (EXC_AFFLAG_TOP10
| EXC_AFFLAG_TOP10PERC
);
780 BOOL bNewTop10
= ::get_flag( nNewFlags
, EXC_AFFLAG_TOP10
);
782 bConflict
= HasTop10() && bNewTop10
;
787 if( fVal
< 0 ) fVal
= 0;
788 if( fVal
>= 501 ) fVal
= 500;
789 nFlags
|= (nNewFlags
| (UINT16
)(fVal
) << 7);
794 UINT8 nType
= bIsNum
? EXC_AFTYPE_DOUBLE
: EXC_AFTYPE_STRING
;
795 UINT8 nOper
= EXC_AFOPER_NONE
;
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;
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;
815 bConflict
= !AddCondition( rEntry
.eConnect
, nType
, nOper
, fVal
, pText
);
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() )
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,
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,
854 rWorksheet
->startElement( XML_customFilters
,
855 XML_and
, XclXmlUtils::ToPsz( (nFlags
& EXC_AFFLAG_ANDORMASK
) == EXC_AFFLAG_AND
),
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
) :
872 ScDBCollection
& rDBColl
= GetDatabaseRanges();
873 XclExpNameManager
& rNameMgr
= GetNameManager();
875 // search for first DB-range with filter
878 BOOL bAdvanced
= FALSE
;
879 ScDBData
* pData
= NULL
;
881 while( (nIndex
< rDBColl
.GetCount()) && !bFound
)
883 pData
= rDBColl
[ nIndex
];
887 pData
->GetArea( aRange
);
888 bAdvanced
= pData
->GetAdvancedQuerySource( aAdvRange
);
889 bFound
= (aRange
.aStart
.Tab() == nTab
) &&
890 (pData
->HasQueryParam() || pData
->HasAutoFilter() || bAdvanced
);
896 if( pData
&& bFound
)
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;
907 // #i2394# #100489# built-in defined names must be sorted by containing sheet name
908 rNameMgr
.InsertBuiltInName( EXC_BUILTIN_FILTERDATABASE
, aRange
);
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
;
931 BOOL bConflict
= FALSE
;
932 BOOL bContLoop
= TRUE
;
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
;
944 XclExpAutofilter
* pFilter
= GetByCol( static_cast<SCCOL
>(rEntry
.nField
) - aRange
.aStart
.Col() );
947 bHasOr
|= (rEntry
.eConnect
== SC_OR
);
949 bConflict
= (nEntry
> 1) && bHasOr
;
951 bConflict
= (nEntry
== 1) && (rEntry
.eConnect
== SC_OR
) &&
952 (nFirstField
!= rEntry
.nField
);
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();
966 maFilterList
.RemoveAllRecords();
968 if( !maFilterList
.IsEmpty() )
969 pFilterMode
= new XclExpFiltermode
;
970 pFilterInfo
= new XclExpAutofilterinfo( aRange
.aStart
, nColCnt
);
975 ExcAutoFilterRecs::~ExcAutoFilterRecs()
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
) )
1003 void ExcAutoFilterRecs::AddObjRecs()
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
);
1017 void ExcAutoFilterRecs::Save( XclExpStream
& rStrm
)
1020 pFilterMode
->Save( rStrm
);
1022 pFilterInfo
->Save( rStrm
);
1023 maFilterList
.Save( rStrm
);
1026 void ExcAutoFilterRecs::SaveXml( XclExpXmlStream
& rStrm
)
1028 if( maFilterList
.IsEmpty() )
1031 sax_fastparser::FSHelperPtr
& rWorksheet
= rStrm
.GetCurrentStream();
1032 rWorksheet
->startElement( XML_autoFilter
,
1033 XML_ref
, XclXmlUtils::ToOString( maRef
).getStr(),
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
) :
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() )
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();
1080 // ============================================================================