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: consdlg.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"
34 // System - Includes ---------------------------------------------------------
38 #include <sfx2/dispatch.hxx>
40 // INCLUDE -------------------------------------------------------------------
42 #include "tabvwsh.hxx"
43 #include "uiitems.hxx"
44 #include "dbcolect.hxx"
45 #include "rangenam.hxx"
46 #include "rangeutl.hxx"
47 #include "reffact.hxx"
48 #include "document.hxx"
49 #include "scresid.hxx"
51 #include "globstr.hrc"
52 #include "consdlg.hrc"
55 #include "consdlg.hxx"
57 #include <vcl/msgbox.hxx>
59 #define INFOBOX(id) InfoBox(this, ScGlobal::GetRscString(id)).Execute()
61 //============================================================================
70 void Set( const String
& rName
, const String
& rArea
, BOOL bDb
)
83 //============================================================================
84 // class ScConsolidateDialog
87 ScConsolidateDlg::ScConsolidateDlg( SfxBindings
* pB
, SfxChildWindow
* pCW
, Window
* pParent
,
88 const SfxItemSet
& rArgSet
)
90 : ScAnyRefDlg ( pB
, pCW
, pParent
, RID_SCDLG_CONSOLIDATE
),
92 aFtFunc ( this, ScResId( FT_FUNC
) ),
93 aLbFunc ( this, ScResId( LB_FUNC
) ),
95 aFtConsAreas ( this, ScResId( FT_CONSAREAS
) ),
96 aLbConsAreas ( this, ScResId( LB_CONSAREAS
) ),
98 aLbDataArea ( this, ScResId( LB_DATA_AREA
) ),
99 aFtDataArea ( this, ScResId( FT_DATA_AREA
) ),
100 aEdDataArea ( this, this, ScResId( ED_DATA_AREA
) ),
101 aRbDataArea ( this, ScResId( RB_DATA_AREA
), &aEdDataArea
, this ),
103 aLbDestArea ( this, ScResId( LB_DEST_AREA
) ),
104 aFtDestArea ( this, ScResId( FT_DEST_AREA
) ),
105 aEdDestArea ( this, this, ScResId( ED_DEST_AREA
) ),
106 aRbDestArea ( this, ScResId( RB_DEST_AREA
), &aEdDestArea
, this),
108 aFlConsBy ( this, ScResId( FL_CONSBY
) ),
109 aBtnByRow ( this, ScResId( BTN_BYROW
) ),
110 aBtnByCol ( this, ScResId( BTN_BYCOL
) ),
112 aFlSep ( this, ScResId( FL_SEP
) ),
113 aFlOptions ( this, ScResId( FL_OPTIONS
) ),
114 aBtnRefs ( this, ScResId( BTN_REFS
) ),
116 aBtnOk ( this, ScResId( BTN_OK
) ),
117 aBtnCancel ( this, ScResId( BTN_CANCEL
) ),
118 aBtnHelp ( this, ScResId( BTN_HELP
) ),
119 aBtnAdd ( this, ScResId( BTN_ADD
) ),
120 aBtnRemove ( this, ScResId( BTN_REMOVE
) ),
121 aBtnMore ( this, ScResId( BTN_MORE
) ),
123 aStrUndefined ( ScResId( SCSTR_UNDEFINED
) ),
125 theConsData ( ((const ScConsolidateItem
&)
126 rArgSet
.Get( rArgSet
.GetPool()->
127 GetWhich( SID_CONSOLIDATE
) )
129 pViewData ( ((ScTabViewShell
*)SfxViewShell::Current())->
131 pDoc ( ((ScTabViewShell
*)SfxViewShell::Current())->
132 GetViewData()->GetDocument() ),
133 pRangeUtil ( new ScRangeUtil
),
135 nAreaDataCount ( 0 ),
136 nWhichCons ( rArgSet
.GetPool()->GetWhich( SID_CONSOLIDATE
) ),
138 pRefInputEdit ( &aEdDataArea
)
145 //----------------------------------------------------------------------------
147 __EXPORT
ScConsolidateDlg::~ScConsolidateDlg()
154 //----------------------------------------------------------------------------
156 void ScConsolidateDlg::Init()
158 DBG_ASSERT( pViewData
&& pDoc
&& pRangeUtil
, "Error in Ctor" );
163 aEdDataArea
.SetGetFocusHdl( LINK( this, ScConsolidateDlg
, GetFocusHdl
) );
164 aEdDestArea
.SetGetFocusHdl( LINK( this, ScConsolidateDlg
, GetFocusHdl
) );
165 aLbDataArea
.SetGetFocusHdl( LINK( this, ScConsolidateDlg
, GetFocusHdl
) );
166 aLbDestArea
.SetGetFocusHdl( LINK( this, ScConsolidateDlg
, GetFocusHdl
) );
167 aEdDataArea
.SetModifyHdl ( LINK( this, ScConsolidateDlg
, ModifyHdl
) );
168 aEdDestArea
.SetModifyHdl ( LINK( this, ScConsolidateDlg
, ModifyHdl
) );
169 aLbConsAreas
.SetSelectHdl ( LINK( this, ScConsolidateDlg
, SelectHdl
) );
170 aLbDataArea
.SetSelectHdl ( LINK( this, ScConsolidateDlg
, SelectHdl
) );
171 aLbDestArea
.SetSelectHdl ( LINK( this, ScConsolidateDlg
, SelectHdl
) );
172 aBtnOk
.SetClickHdl ( LINK( this, ScConsolidateDlg
, OkHdl
) );
173 aBtnCancel
.SetClickHdl ( LINK( this, ScConsolidateDlg
, ClickHdl
) );
174 aBtnAdd
.SetClickHdl ( LINK( this, ScConsolidateDlg
, ClickHdl
) );
175 aBtnRemove
.SetClickHdl ( LINK( this, ScConsolidateDlg
, ClickHdl
) );
177 aBtnMore
.AddWindow( &aFlConsBy
);
178 aBtnMore
.AddWindow( &aBtnByRow
);
179 aBtnMore
.AddWindow( &aBtnByCol
);
180 aBtnMore
.AddWindow( &aFlSep
);
181 aBtnMore
.AddWindow( &aFlOptions
);
182 aBtnMore
.AddWindow( &aBtnRefs
);
185 aBtnRemove
.Disable();
187 aBtnByRow
.Check( theConsData
.bByRow
);
188 aBtnByCol
.Check( theConsData
.bByCol
);
189 aBtnRefs
.Check( theConsData
.bReferenceData
);
191 aLbFunc
.SelectEntryPos( FuncToLbPos( theConsData
.eFunction
) );
193 // Einlesen der Konsolidierungsbereiche
194 aLbConsAreas
.Clear();
195 const formula::FormulaGrammar::AddressConvention eConv
= pDoc
->GetAddressConvention();
196 for ( i
=0; i
<theConsData
.nDataAreaCount
; i
++ )
198 const ScArea
& rArea
= *(theConsData
.ppDataAreas
[i
] );
199 if ( rArea
.nTab
< pDoc
->GetTableCount() )
201 ScRange( rArea
.nColStart
, rArea
.nRowStart
, rArea
.nTab
,
202 rArea
.nColEnd
, rArea
.nRowEnd
, rArea
.nTab
).Format( aStr
,
203 SCR_ABS_3D
, pDoc
, eConv
);
204 aLbConsAreas
.InsertEntry( aStr
);
208 if ( theConsData
.nTab
< pDoc
->GetTableCount() )
210 ScAddress( theConsData
.nCol
, theConsData
.nRow
, theConsData
.nTab
211 ).Format( aStr
, SCA_ABS_3D
, pDoc
, eConv
);
212 aEdDestArea
.SetText( aStr
);
215 aEdDestArea
.SetText( EMPTY_STRING
);
217 //----------------------------------------------------------
220 * Aus den RangeNames und Datenbankbereichen werden sich
221 * in der Hilfsklasse ScAreaData die Bereichsnamen gemerkt,
222 * die in den ListBoxen erscheinen.
225 ScRangeName
* pRangeNames
= pDoc
->GetRangeName();
226 ScDBCollection
* pDbNames
= pDoc
->GetDBCollection();
227 const USHORT nRangeCount
= pRangeNames
? pRangeNames
->GetCount() : 0;
228 const USHORT nDbCount
= pDbNames
? pDbNames
->GetCount() : 0;
230 nAreaDataCount
= nRangeCount
+nDbCount
;
233 if ( nAreaDataCount
> 0 )
235 pAreaData
= new ScAreaData
[nAreaDataCount
];
241 ScAreaNameIterator
aIter( pDoc
);
242 while ( aIter
.Next( aStrName
, aRange
) )
244 aRange
.Format( aStrArea
, SCA_ABS_3D
, pDoc
, eConv
);
245 pAreaData
[nAt
++].Set( aStrName
, aStrArea
, aIter
.WasDBName() );
250 ModifyHdl( &aEdDestArea
);
251 aLbDataArea
.SelectEntryPos( 0 );
252 aEdDataArea
.SetText( EMPTY_STRING
);
253 aEdDataArea
.GrabFocus();
255 aFlSep
.SetStyle( aFlSep
.GetStyle() | WB_VERT
);
257 //@BugID 54702 Enablen/Disablen nur noch in Basisklasse
258 //SFX_APPWINDOW->Enable();
262 //----------------------------------------------------------------------------
263 void ScConsolidateDlg::FillAreaLists()
267 aLbDataArea
.InsertEntry( aStrUndefined
);
268 aLbDestArea
.InsertEntry( aStrUndefined
);
270 if ( pRangeUtil
&& pAreaData
&& (nAreaDataCount
> 0) )
275 (i
<nAreaDataCount
) && (pAreaData
[i
].aStrName
.Len()>0);
278 aLbDataArea
.InsertEntry( pAreaData
[i
].aStrName
, i
+1 );
280 // if ( !pAreaData[i].bIsDbArea )
281 aLbDestArea
.InsertEntry( pAreaData
[i
].aStrName
, i
+1 );
287 //----------------------------------------------------------------------------
288 // Uebergabe eines mit der Maus selektierten Tabellenbereiches, der dann als
289 // neue Selektion im Referenz-Fenster angezeigt wird.
292 void ScConsolidateDlg::SetReference( const ScRange
& rRef
, ScDocument
* pDocP
)
296 if ( rRef
.aStart
!= rRef
.aEnd
)
297 RefInputStart( pRefInputEdit
);
300 USHORT nFmt
= SCR_ABS_3D
; //!!! nCurTab fehlt noch
301 const formula::FormulaGrammar::AddressConvention eConv
= pDocP
->GetAddressConvention();
303 if ( rRef
.aStart
.Tab() != rRef
.aEnd
.Tab() )
306 if ( pRefInputEdit
== &aEdDataArea
)
307 rRef
.Format( aStr
, nFmt
, pDocP
, eConv
);
308 else if ( pRefInputEdit
== &aEdDestArea
)
309 rRef
.aStart
.Format( aStr
, nFmt
, pDocP
, eConv
);
311 pRefInputEdit
->SetRefString( aStr
);
314 ModifyHdl( pRefInputEdit
);
318 //----------------------------------------------------------------------------
320 BOOL __EXPORT
ScConsolidateDlg::Close()
322 return DoClose( ScConsolidateDlgWrapper::GetChildWindowId() );
326 //----------------------------------------------------------------------------
328 void ScConsolidateDlg::SetActive()
332 bDlgLostFocus
= FALSE
;
336 pRefInputEdit
->GrabFocus();
337 ModifyHdl( pRefInputEdit
);
347 //----------------------------------------------------------------------------
349 void __EXPORT
ScConsolidateDlg::Deactivate()
351 bDlgLostFocus
= TRUE
;
355 //----------------------------------------------------------------------------
357 BOOL
ScConsolidateDlg::VerifyEdit( formula::RefEdit
* pEd
)
359 if ( !pRangeUtil
|| !pDoc
|| !pViewData
||
360 ((pEd
!= &aEdDataArea
) && (pEd
!= &aEdDestArea
)) )
363 SCTAB nTab
= pViewData
->GetTabNo();
364 BOOL bEditOk
= FALSE
;
365 String theCompleteStr
;
366 const formula::FormulaGrammar::AddressConvention eConv
= pDoc
->GetAddressConvention();
368 if ( pEd
== &aEdDataArea
)
370 bEditOk
= pRangeUtil
->IsAbsArea( pEd
->GetText(), pDoc
,
371 nTab
, &theCompleteStr
, NULL
, NULL
, eConv
);
373 else if ( pEd
== &aEdDestArea
)
377 pRangeUtil
->CutPosString( pEd
->GetText(), aPosStr
);
378 bEditOk
= pRangeUtil
->IsAbsPos( aPosStr
, pDoc
,
379 nTab
, &theCompleteStr
, NULL
, eConv
);
383 pEd
->SetText( theCompleteStr
);
389 //----------------------------------------------------------------------------
393 IMPL_LINK( ScConsolidateDlg
, GetFocusHdl
, Control
*, pCtr
)
395 if ( pCtr
==(Control
*)&aEdDataArea
||
396 pCtr
==(Control
*)&aEdDestArea
)
398 pRefInputEdit
= (formula::RefEdit
*)pCtr
;
400 else if(pCtr
==(Control
*)&aLbDataArea
)
402 pRefInputEdit
= &aEdDataArea
;
404 else if(pCtr
==(Control
*)&aLbDestArea
)
406 pRefInputEdit
= &aEdDestArea
;
412 //----------------------------------------------------------------------------
414 IMPL_LINK( ScConsolidateDlg
, OkHdl
, void*, EMPTYARG
)
416 USHORT nDataAreaCount
= aLbConsAreas
.GetEntryCount();
418 if ( nDataAreaCount
> 0 )
420 ScRefAddress aDestAddress
;
421 SCTAB nTab
= pViewData
->GetTabNo();
422 String
aDestPosStr( aEdDestArea
.GetText() );
423 const formula::FormulaGrammar::AddressConvention eConv
= pDoc
->GetAddressConvention();
425 if ( pRangeUtil
->IsAbsPos( aDestPosStr
, pDoc
, nTab
, NULL
, &aDestAddress
, eConv
) )
427 ScConsolidateParam
theOutParam( theConsData
);
428 ScArea
** ppDataAreas
= new ScArea
*[nDataAreaCount
];
432 for ( i
=0; i
<nDataAreaCount
; i
++ )
435 pRangeUtil
->MakeArea( aLbConsAreas
.GetEntry( i
),
436 *pArea
, pDoc
, nTab
, eConv
);
437 ppDataAreas
[i
] = pArea
;
440 theOutParam
.nCol
= aDestAddress
.Col();
441 theOutParam
.nRow
= aDestAddress
.Row();
442 theOutParam
.nTab
= aDestAddress
.Tab();
443 theOutParam
.eFunction
= LbPosToFunc( aLbFunc
.GetSelectEntryPos() );
444 theOutParam
.bByCol
= aBtnByCol
.IsChecked();
445 theOutParam
.bByRow
= aBtnByRow
.IsChecked();
446 theOutParam
.bReferenceData
= aBtnRefs
.IsChecked();
447 theOutParam
.SetAreas( ppDataAreas
, nDataAreaCount
);
449 for ( i
=0; i
<nDataAreaCount
; i
++ )
450 delete ppDataAreas
[i
];
451 delete [] ppDataAreas
;
453 ScConsolidateItem
aOutItem( nWhichCons
, &theOutParam
);
455 SetDispatcherLock( FALSE
);
457 GetBindings().GetDispatcher()->Execute( SID_CONSOLIDATE
,
458 SFX_CALLMODE_SLOT
| SFX_CALLMODE_RECORD
,
464 INFOBOX( STR_INVALID_TABREF
);
465 aEdDestArea
.GrabFocus();
469 Close(); // keine Datenbereiche definiert -> Cancel
474 //----------------------------------------------------------------------------
476 IMPL_LINK( ScConsolidateDlg
, ClickHdl
, PushButton
*, pBtn
)
478 if ( pBtn
== &aBtnCancel
)
480 else if ( pBtn
== &aBtnAdd
)
482 if ( aEdDataArea
.GetText().Len() > 0 )
484 String
aNewEntry( aEdDataArea
.GetText() );
485 ScArea
** ppAreas
= NULL
;
486 USHORT nAreaCount
= 0;
487 const formula::FormulaGrammar::AddressConvention eConv
= pDoc
->GetAddressConvention();
489 if ( pRangeUtil
->IsAbsTabArea( aNewEntry
, pDoc
, &ppAreas
, &nAreaCount
, TRUE
, eConv
) )
491 // IsAbsTabArea() legt ein Array von ScArea-Zeigern an,
492 // welche ebenfalls dynamisch erzeugt wurden.
493 // Diese Objekte muessen hier abgeraeumt werden.
495 for ( USHORT i
=0; i
<nAreaCount
; i
++ )
501 const ScArea
& rArea
= *(ppAreas
[i
]);
502 ScRange( rArea
.nColStart
, rArea
.nRowStart
, rArea
.nTab
,
503 rArea
.nColEnd
, rArea
.nRowEnd
, rArea
.nTab
504 ).Format( aNewArea
, SCR_ABS_3D
, pDoc
, eConv
);
506 if ( aLbConsAreas
.GetEntryPos( aNewArea
)
507 == LISTBOX_ENTRY_NOTFOUND
)
509 aLbConsAreas
.InsertEntry( aNewArea
);
516 else if ( VerifyEdit( &aEdDataArea
) )
518 String
aNewArea( aEdDataArea
.GetText() );
520 if ( aLbConsAreas
.GetEntryPos( aNewArea
) == LISTBOX_ENTRY_NOTFOUND
)
521 aLbConsAreas
.InsertEntry( aNewArea
);
523 INFOBOX( STR_AREA_ALREADY_INSERTED
);
527 INFOBOX( STR_INVALID_TABREF
);
528 aEdDataArea
.GrabFocus();
532 else if ( pBtn
== &aBtnRemove
)
534 while ( aLbConsAreas
.GetSelectEntryCount() )
535 aLbConsAreas
.RemoveEntry( aLbConsAreas
.GetSelectEntryPos() );
536 aBtnRemove
.Disable();
542 //----------------------------------------------------------------------------
544 IMPL_LINK( ScConsolidateDlg
, SelectHdl
, ListBox
*, pLb
)
546 if ( pLb
== &aLbConsAreas
)
548 if ( aLbConsAreas
.GetSelectEntryCount() > 0 )
551 aBtnRemove
.Disable();
553 else if ( (pLb
== &aLbDataArea
) || (pLb
== &aLbDestArea
) )
555 Edit
* pEd
= (pLb
== &aLbDataArea
) ? &aEdDataArea
: &aEdDestArea
;
556 USHORT nSelPos
= pLb
->GetSelectEntryPos();
560 && (nAreaDataCount
> 0)
561 && (pAreaData
!= NULL
) )
563 if ( nSelPos
<= nAreaDataCount
)
565 String
aString( pAreaData
[nSelPos
-1].aStrArea
);
567 if ( pLb
== &aLbDestArea
)
568 pRangeUtil
->CutPosString( aString
, aString
);
570 pEd
->SetText( aString
);
572 if ( pEd
== &aEdDataArea
)
578 pEd
->SetText( EMPTY_STRING
);
579 if ( pEd
== &aEdDataArea
)
587 //----------------------------------------------------------------------------
589 IMPL_LINK( ScConsolidateDlg
, ModifyHdl
, formula::RefEdit
*, pEd
)
591 if ( pEd
== &aEdDataArea
)
593 String
aAreaStr( pEd
->GetText() );
594 if ( aAreaStr
.Len() > 0 )
601 else if ( pEd
== &aEdDestArea
)
603 aLbDestArea
.SelectEntryPos(0);
609 //----------------------------------------------------------------------------
610 // Verallgemeinern!!! :
611 // Resource der ListBox und diese beiden Umrechnungsmethoden gibt es
612 // auch noch in tpsubt bzw. ueberall, wo StarCalc-Funktionen
615 ScSubTotalFunc
ScConsolidateDlg::LbPosToFunc( USHORT nPos
)
619 case 2: return SUBTOTAL_FUNC_AVE
;
620 case 6: return SUBTOTAL_FUNC_CNT
;
621 case 1: return SUBTOTAL_FUNC_CNT2
;
622 case 3: return SUBTOTAL_FUNC_MAX
;
623 case 4: return SUBTOTAL_FUNC_MIN
;
624 case 5: return SUBTOTAL_FUNC_PROD
;
625 case 7: return SUBTOTAL_FUNC_STD
;
626 case 8: return SUBTOTAL_FUNC_STDP
;
627 case 9: return SUBTOTAL_FUNC_VAR
;
628 case 10: return SUBTOTAL_FUNC_VARP
;
631 return SUBTOTAL_FUNC_SUM
;
636 //----------------------------------------------------------------------------
638 USHORT
ScConsolidateDlg::FuncToLbPos( ScSubTotalFunc eFunc
)
642 case SUBTOTAL_FUNC_AVE
: return 2;
643 case SUBTOTAL_FUNC_CNT
: return 6;
644 case SUBTOTAL_FUNC_CNT2
: return 1;
645 case SUBTOTAL_FUNC_MAX
: return 3;
646 case SUBTOTAL_FUNC_MIN
: return 4;
647 case SUBTOTAL_FUNC_PROD
: return 5;
648 case SUBTOTAL_FUNC_STD
: return 7;
649 case SUBTOTAL_FUNC_STDP
: return 8;
650 case SUBTOTAL_FUNC_VAR
: return 9;
651 case SUBTOTAL_FUNC_VARP
: return 10;
652 case SUBTOTAL_FUNC_NONE
:
653 case SUBTOTAL_FUNC_SUM
: