1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sfx2/dispatch.hxx>
22 #include "tabvwsh.hxx"
23 #include "uiitems.hxx"
25 #include "rangenam.hxx"
26 #include "rangeutl.hxx"
27 #include "reffact.hxx"
28 #include "document.hxx"
29 #include "scresid.hxx"
31 #include "globstr.hrc"
34 #include "consdlg.hxx"
35 #include <vcl/msgbox.hxx>
37 #define INFOBOX(id) ScopedVclPtr<InfoBox>::Create(this, ScGlobal::GetRscString(id))->Execute()
49 void Set( const OUString
& rName
, const OUString
& rArea
, bool bDb
)
61 ScConsolidateDlg::ScConsolidateDlg( SfxBindings
* pB
, SfxChildWindow
* pCW
, vcl::Window
* pParent
,
62 const SfxItemSet
& rArgSet
)
64 : ScAnyRefDlg ( pB
, pCW
, pParent
, "ConsolidateDialog" , "modules/scalc/ui/consolidatedialog.ui" ),
65 aStrUndefined ( ScResId( SCSTR_UNDEFINED
) ),
66 theConsData ( static_cast<const ScConsolidateItem
&>(
67 rArgSet
.Get( rArgSet
.GetPool()->
68 GetWhich( SID_CONSOLIDATE
) )
70 rViewData ( static_cast<ScTabViewShell
*>(SfxViewShell::Current())->
72 pDoc ( static_cast<ScTabViewShell
*>(SfxViewShell::Current())->
73 GetViewData().GetDocument() ),
74 pRangeUtil ( new ScRangeUtil
),
77 nWhichCons ( rArgSet
.GetPool()->GetWhich( SID_CONSOLIDATE
) ),
78 bDlgLostFocus ( false )
81 get(pLbConsAreas
,"consareas");
83 get(pLbDataArea
,"lbdataarea");
84 get(pEdDataArea
,"eddataarea");
85 get(pRbDataArea
,"rbdataarea");
87 pRefInputEdit
= pEdDataArea
;
89 get(pLbDestArea
,"lbdestarea");
90 get(pEdDestArea
,"eddestarea");
91 get(pRbDestArea
,"rbdestarea");
93 get(pExpander
,"more");
94 get(pBtnByRow
,"byrow");
95 get(pBtnByCol
,"bycol");
99 get(pBtnCancel
,"cancel");
101 get(pBtnRemove
,"delete");
106 ScConsolidateDlg::~ScConsolidateDlg()
111 void ScConsolidateDlg::dispose()
116 pLbConsAreas
.clear();
131 pRefInputEdit
.clear();
132 ScAnyRefDlg::dispose();
135 void ScConsolidateDlg::Init()
137 OSL_ENSURE( pDoc
&& pRangeUtil
, "Error in Ctor" );
142 pRbDataArea
->SetReferences(this, pEdDataArea
);
143 pEdDataArea
->SetReferences(this, get
<FixedText
>("ftdataarea"));
144 pRbDestArea
->SetReferences(this, pEdDestArea
);
145 pEdDestArea
->SetReferences(this, get
<FixedText
>("ftdestarea"));
147 pEdDataArea
->SetGetFocusHdl( LINK( this, ScConsolidateDlg
, GetFocusHdl
) );
148 pEdDestArea
->SetGetFocusHdl( LINK( this, ScConsolidateDlg
, GetFocusHdl
) );
149 pLbDataArea
->SetGetFocusHdl( LINK( this, ScConsolidateDlg
, GetFocusHdl
) );
150 pLbDestArea
->SetGetFocusHdl( LINK( this, ScConsolidateDlg
, GetFocusHdl
) );
151 pEdDataArea
->SetModifyHdl ( LINK( this, ScConsolidateDlg
, ModifyHdl
) );
152 pEdDestArea
->SetModifyHdl ( LINK( this, ScConsolidateDlg
, ModifyHdl
) );
153 pLbConsAreas
->SetSelectHdl ( LINK( this, ScConsolidateDlg
, SelectHdl
) );
154 pLbDataArea
->SetSelectHdl ( LINK( this, ScConsolidateDlg
, SelectHdl
) );
155 pLbDestArea
->SetSelectHdl ( LINK( this, ScConsolidateDlg
, SelectHdl
) );
156 pBtnOk
->SetClickHdl ( LINK( this, ScConsolidateDlg
, OkHdl
) );
157 pBtnCancel
->SetClickHdl ( LINK( this, ScConsolidateDlg
, ClickHdl
) );
158 pBtnAdd
->SetClickHdl ( LINK( this, ScConsolidateDlg
, ClickHdl
) );
159 pBtnRemove
->SetClickHdl ( LINK( this, ScConsolidateDlg
, ClickHdl
) );
162 pBtnRemove
->Disable();
164 pBtnByRow
->Check( theConsData
.bByRow
);
165 pBtnByCol
->Check( theConsData
.bByCol
);
166 pBtnRefs
->Check( theConsData
.bReferenceData
);
168 pLbFunc
->SelectEntryPos( FuncToLbPos( theConsData
.eFunction
) );
170 // Hack: pLbConsAreas used to be MultiLB. We don't have VCL builder equivalent
171 // of it yet. So enable selecting multiple items here
172 pLbConsAreas
->EnableMultiSelection( true );
174 pLbConsAreas
->set_width_request(pLbConsAreas
->approximate_char_width() * 16);
175 pLbConsAreas
->SetDropDownLineCount(5);
177 // read consolidation areas
178 pLbConsAreas
->Clear();
179 const formula::FormulaGrammar::AddressConvention eConv
= pDoc
->GetAddressConvention();
180 for ( i
=0; i
<theConsData
.nDataAreaCount
; i
++ )
182 const ScArea
& rArea
= *(theConsData
.ppDataAreas
[i
] );
183 if ( rArea
.nTab
< pDoc
->GetTableCount() )
185 aStr
= ScRange( rArea
.nColStart
, rArea
.nRowStart
, rArea
.nTab
,
186 rArea
.nColEnd
, rArea
.nRowEnd
, rArea
.nTab
).Format(
187 SCR_ABS_3D
, pDoc
, eConv
);
188 pLbConsAreas
->InsertEntry( aStr
);
192 if ( theConsData
.nTab
< pDoc
->GetTableCount() )
194 aStr
= ScAddress( theConsData
.nCol
, theConsData
.nRow
, theConsData
.nTab
195 ).Format( SCA_ABS_3D
, pDoc
, eConv
);
196 pEdDestArea
->SetText( aStr
);
199 pEdDestArea
->SetText(OUString());
201 // Use the ScAreaData helper class to save those range names from the
202 // RangeNames and database ranges that appear in the ListBoxes.
204 ScRangeName
* pRangeNames
= pDoc
->GetRangeName();
205 ScDBCollection
* pDbNames
= pDoc
->GetDBCollection();
206 size_t nRangeCount
= pRangeNames
? pRangeNames
->size() : 0;
207 size_t nDbCount
= pDbNames
? pDbNames
->getNamedDBs().size() : 0;
209 nAreaDataCount
= nRangeCount
+nDbCount
;
212 if ( nAreaDataCount
> 0 )
214 pAreaData
= new ScAreaData
[nAreaDataCount
];
219 ScAreaNameIterator
aIter( pDoc
);
220 while ( aIter
.Next( aStrName
, aRange
) )
222 OUString
aStrArea(aRange
.Format(SCA_ABS_3D
, pDoc
, eConv
));
223 pAreaData
[nAt
++].Set( aStrName
, aStrArea
, aIter
.WasDBName() );
228 ModifyHdl( pEdDestArea
);
229 pLbDataArea
->SelectEntryPos( 0 );
230 pEdDataArea
->SetText(OUString());
231 pEdDataArea
->GrabFocus();
233 //aFlSep.SetStyle( aFlSep.GetStyle() | WB_VERT );
235 //@BugID 54702 enable/disable only in base class
236 //SFX_APPWINDOW->Enable();
239 void ScConsolidateDlg::FillAreaLists()
241 pLbDataArea
->Clear();
242 pLbDestArea
->Clear();
243 pLbDataArea
->InsertEntry( aStrUndefined
);
244 pLbDestArea
->InsertEntry( aStrUndefined
);
246 if ( pRangeUtil
&& pAreaData
&& (nAreaDataCount
> 0) )
249 (i
<nAreaDataCount
) && (!pAreaData
[i
].aStrName
.isEmpty());
252 pLbDataArea
->InsertEntry( pAreaData
[i
].aStrName
, i
+1 );
254 // if ( !pAreaData[i].bIsDbArea )
255 pLbDestArea
->InsertEntry( pAreaData
[i
].aStrName
, i
+1 );
260 // Handover of a range within a table that has been selected by the mouse.
261 // This range is then shown in the reference window as new selection.
263 void ScConsolidateDlg::SetReference( const ScRange
& rRef
, ScDocument
* pDocP
)
267 if ( rRef
.aStart
!= rRef
.aEnd
)
268 RefInputStart( pRefInputEdit
);
271 sal_uInt16 nFmt
= SCR_ABS_3D
; //!!! nCurTab is still missing
272 const formula::FormulaGrammar::AddressConvention eConv
= pDocP
->GetAddressConvention();
274 if ( rRef
.aStart
.Tab() != rRef
.aEnd
.Tab() )
277 if ( pRefInputEdit
== pEdDataArea
)
278 aStr
= rRef
.Format(nFmt
, pDocP
, eConv
);
279 else if ( pRefInputEdit
== pEdDestArea
)
280 aStr
= rRef
.aStart
.Format(nFmt
, pDocP
, eConv
);
282 pRefInputEdit
->SetRefString( aStr
);
283 ModifyHdl( pRefInputEdit
);
287 bool ScConsolidateDlg::Close()
289 return DoClose( ScConsolidateDlgWrapper::GetChildWindowId() );
292 void ScConsolidateDlg::SetActive()
296 bDlgLostFocus
= false;
300 pRefInputEdit
->GrabFocus();
301 ModifyHdl( pRefInputEdit
);
310 void ScConsolidateDlg::Deactivate()
312 bDlgLostFocus
= true;
315 bool ScConsolidateDlg::VerifyEdit( formula::RefEdit
* pEd
)
317 if ( !pRangeUtil
|| !pDoc
||
318 ((pEd
!= pEdDataArea
) && (pEd
!= pEdDestArea
)) )
321 SCTAB nTab
= rViewData
.GetTabNo();
322 bool bEditOk
= false;
323 OUString theCompleteStr
;
324 const formula::FormulaGrammar::AddressConvention eConv
= pDoc
->GetAddressConvention();
326 if ( pEd
== pEdDataArea
)
328 bEditOk
= ScRangeUtil::IsAbsArea( pEd
->GetText(), pDoc
,
329 nTab
, &theCompleteStr
, NULL
, NULL
, eConv
);
331 else if ( pEd
== pEdDestArea
)
335 ScRangeUtil::CutPosString( pEd
->GetText(), aPosStr
);
336 bEditOk
= ScRangeUtil::IsAbsPos( aPosStr
, pDoc
,
337 nTab
, &theCompleteStr
, NULL
, eConv
);
341 pEd
->SetText( theCompleteStr
);
348 IMPL_LINK( ScConsolidateDlg
, GetFocusHdl
, Control
*, pCtr
)
350 if ( pCtr
==(Control
*)pEdDataArea
||
351 pCtr
==(Control
*)pEdDestArea
)
353 pRefInputEdit
= static_cast<formula::RefEdit
*>(pCtr
);
355 else if(pCtr
==(Control
*)pLbDataArea
)
357 pRefInputEdit
= pEdDataArea
;
359 else if(pCtr
==(Control
*)pLbDestArea
)
361 pRefInputEdit
= pEdDestArea
;
366 IMPL_LINK_NOARG(ScConsolidateDlg
, OkHdl
)
368 sal_uInt16 nDataAreaCount
= pLbConsAreas
->GetEntryCount();
370 if ( nDataAreaCount
> 0 )
372 ScRefAddress aDestAddress
;
373 SCTAB nTab
= rViewData
.GetTabNo();
374 OUString
aDestPosStr( pEdDestArea
->GetText() );
375 const formula::FormulaGrammar::AddressConvention eConv
= pDoc
->GetAddressConvention();
377 if ( ScRangeUtil::IsAbsPos( aDestPosStr
, pDoc
, nTab
, NULL
, &aDestAddress
, eConv
) )
379 ScConsolidateParam
theOutParam( theConsData
);
380 ScArea
** ppDataAreas
= new ScArea
*[nDataAreaCount
];
384 for ( i
=0; i
<nDataAreaCount
; i
++ )
387 ScRangeUtil::MakeArea( pLbConsAreas
->GetEntry( i
),
388 *pArea
, pDoc
, nTab
, eConv
);
389 ppDataAreas
[i
] = pArea
;
392 theOutParam
.nCol
= aDestAddress
.Col();
393 theOutParam
.nRow
= aDestAddress
.Row();
394 theOutParam
.nTab
= aDestAddress
.Tab();
395 theOutParam
.eFunction
= LbPosToFunc( pLbFunc
->GetSelectEntryPos() );
396 theOutParam
.bByCol
= pBtnByCol
->IsChecked();
397 theOutParam
.bByRow
= pBtnByRow
->IsChecked();
398 theOutParam
.bReferenceData
= pBtnRefs
->IsChecked();
399 theOutParam
.SetAreas( ppDataAreas
, nDataAreaCount
);
401 for ( i
=0; i
<nDataAreaCount
; i
++ )
402 delete ppDataAreas
[i
];
403 delete [] ppDataAreas
;
405 ScConsolidateItem
aOutItem( nWhichCons
, &theOutParam
);
407 SetDispatcherLock( false );
409 GetBindings().GetDispatcher()->Execute( SID_CONSOLIDATE
,
410 SfxCallMode::SLOT
| SfxCallMode::RECORD
,
416 INFOBOX( STR_INVALID_TABREF
);
417 pEdDestArea
->GrabFocus();
421 Close(); // no area defined -> Cancel
425 IMPL_LINK( ScConsolidateDlg
, ClickHdl
, PushButton
*, pBtn
)
427 if ( pBtn
== pBtnCancel
)
429 else if ( pBtn
== pBtnAdd
)
431 if ( !pEdDataArea
->GetText().isEmpty() )
433 OUString
aNewEntry( pEdDataArea
->GetText() );
434 ScArea
** ppAreas
= NULL
;
435 sal_uInt16 nAreaCount
= 0;
436 const formula::FormulaGrammar::AddressConvention eConv
= pDoc
->GetAddressConvention();
438 if ( ScRangeUtil::IsAbsTabArea( aNewEntry
, pDoc
, &ppAreas
, &nAreaCount
, true, eConv
) )
440 // IsAbsTabArea() creates an array of ScArea pointers,
441 // which have been created dynamically as well.
442 // These objects need to be deleted here.
444 for ( sal_uInt16 i
=0; i
<nAreaCount
; i
++ )
450 const ScArea
& rArea
= *(ppAreas
[i
]);
451 aNewArea
= ScRange( rArea
.nColStart
, rArea
.nRowStart
, rArea
.nTab
,
452 rArea
.nColEnd
, rArea
.nRowEnd
, rArea
.nTab
453 ).Format(SCR_ABS_3D
, pDoc
, eConv
);
455 if ( pLbConsAreas
->GetEntryPos( aNewArea
)
456 == LISTBOX_ENTRY_NOTFOUND
)
458 pLbConsAreas
->InsertEntry( aNewArea
);
465 else if ( VerifyEdit( pEdDataArea
) )
467 OUString
aNewArea( pEdDataArea
->GetText() );
469 if ( pLbConsAreas
->GetEntryPos( aNewArea
) == LISTBOX_ENTRY_NOTFOUND
)
470 pLbConsAreas
->InsertEntry( aNewArea
);
472 INFOBOX( STR_AREA_ALREADY_INSERTED
);
476 INFOBOX( STR_INVALID_TABREF
);
477 pEdDataArea
->GrabFocus();
481 else if ( pBtn
== pBtnRemove
)
483 while ( pLbConsAreas
->GetSelectEntryCount() )
484 pLbConsAreas
->RemoveEntry( pLbConsAreas
->GetSelectEntryPos() );
485 pBtnRemove
->Disable();
490 IMPL_LINK( ScConsolidateDlg
, SelectHdl
, ListBox
*, pLb
)
492 if ( pLb
== pLbConsAreas
)
494 if ( pLbConsAreas
->GetSelectEntryCount() > 0 )
495 pBtnRemove
->Enable();
497 pBtnRemove
->Disable();
499 else if ( (pLb
== pLbDataArea
) || (pLb
== pLbDestArea
) )
501 Edit
* pEd
= (pLb
== pLbDataArea
) ? pEdDataArea
: pEdDestArea
;
502 sal_uInt16 nSelPos
= pLb
->GetSelectEntryPos();
506 && (nAreaDataCount
> 0)
507 && (pAreaData
!= NULL
) )
509 if ( static_cast<size_t>(nSelPos
) <= nAreaDataCount
)
511 OUString
aString( pAreaData
[nSelPos
-1].aStrArea
);
513 if ( pLb
== pLbDestArea
)
514 ScRangeUtil::CutPosString( aString
, aString
);
516 pEd
->SetText( aString
);
518 if ( pEd
== pEdDataArea
)
524 pEd
->SetText( EMPTY_OUSTRING
);
525 if ( pEd
== pEdDataArea
)
532 IMPL_LINK( ScConsolidateDlg
, ModifyHdl
, formula::RefEdit
*, pEd
)
534 if ( pEd
== pEdDataArea
)
536 OUString
aAreaStr( pEd
->GetText() );
537 if ( !aAreaStr
.isEmpty() )
544 else if ( pEd
== pEdDestArea
)
546 pLbDestArea
->SelectEntryPos(0);
552 // Resource of the ListBox and these two conversion methods are also in
553 // tpsubt and everywhere, where StarCalc functions are selectable.
555 ScSubTotalFunc
ScConsolidateDlg::LbPosToFunc( sal_uInt16 nPos
)
559 case 2: return SUBTOTAL_FUNC_AVE
;
560 case 6: return SUBTOTAL_FUNC_CNT
;
561 case 1: return SUBTOTAL_FUNC_CNT2
;
562 case 3: return SUBTOTAL_FUNC_MAX
;
563 case 4: return SUBTOTAL_FUNC_MIN
;
564 case 5: return SUBTOTAL_FUNC_PROD
;
565 case 7: return SUBTOTAL_FUNC_STD
;
566 case 8: return SUBTOTAL_FUNC_STDP
;
567 case 9: return SUBTOTAL_FUNC_VAR
;
568 case 10: return SUBTOTAL_FUNC_VARP
;
571 return SUBTOTAL_FUNC_SUM
;
575 sal_uInt16
ScConsolidateDlg::FuncToLbPos( ScSubTotalFunc eFunc
)
579 case SUBTOTAL_FUNC_AVE
: return 2;
580 case SUBTOTAL_FUNC_CNT
: return 6;
581 case SUBTOTAL_FUNC_CNT2
: return 1;
582 case SUBTOTAL_FUNC_MAX
: return 3;
583 case SUBTOTAL_FUNC_MIN
: return 4;
584 case SUBTOTAL_FUNC_PROD
: return 5;
585 case SUBTOTAL_FUNC_STD
: return 7;
586 case SUBTOTAL_FUNC_STDP
: return 8;
587 case SUBTOTAL_FUNC_VAR
: return 9;
588 case SUBTOTAL_FUNC_VARP
: return 10;
589 case SUBTOTAL_FUNC_NONE
:
590 case SUBTOTAL_FUNC_SUM
:
596 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */