LibreOffice Module sc (master)  1
areasdlg.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <rangelst.hxx>
21 
22 #include <sfx2/dispatch.hxx>
23 #include <svl/stritem.hxx>
24 #include <vcl/svapp.hxx>
25 #include <vcl/weld.hxx>
26 #include <unotools/charclass.hxx>
27 
28 #include <areasdlg.hxx>
29 #include <rangenam.hxx>
30 #include <reffact.hxx>
31 #include <tabvwsh.hxx>
32 #include <docsh.hxx>
33 #include <globstr.hrc>
34 #include <scresid.hxx>
35 #include <compiler.hxx>
36 #include <markdata.hxx>
37 
38 // List box positions for print range (PR)
39 enum {
43 };
44 
45 // List box positions for repeat ranges (RR)
46 enum {
50 };
51 
52 namespace
53 {
54  void ERRORBOX(weld::Window* pParent, const char* rId)
55  {
56  std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pParent,
57  VclMessageType::Warning, VclButtonsType::Ok,
58  ScResId(rId)));
59  xBox->run();
60  }
61 }
62 
63 // global functions (->at the end of the file):
64 
65 static bool lcl_CheckRepeatString( const OUString& rStr, const ScDocument& rDoc, bool bIsRow, ScRange* pRange );
66 static void lcl_GetRepeatRangeString( const ScRange* pRange, const ScDocument& rDoc, bool bIsRow, OUString& rStr );
67 
68 #if 0
69 // this method is useful when debugging address flags.
70 static void printAddressFlags(ScRefFlags nFlag)
71 {
72  if ((nFlag & ScRefFlags::COL_ABS ) == ScRefFlags::COL_ABS ) printf("ScRefFlags::COL_ABS \n");
73  if ((nFlag & ScRefFlags::ROW_ABS ) == ScRefFlags::ROW_ABS ) printf("ScRefFlags::ROW_ABS \n");
74  if ((nFlag & ScRefFlags::TAB_ABS ) == ScRefFlags::TAB_ABS ) printf("ScRefFlags::TAB_ABS \n");
75  if ((nFlag & ScRefFlags::TAB_3D ) == ScRefFlags::TAB_3D ) printf("ScRefFlags::TAB_3D \n");
76  if ((nFlag & ScRefFlags::COL2_ABS ) == ScRefFlags::COL2_ABS ) printf("ScRefFlags::COL2_ABS \n");
77  if ((nFlag & ScRefFlags::ROW2_ABS ) == ScRefFlags::ROW2_ABS ) printf("ScRefFlags::ROW2_ABS \n");
78  if ((nFlag & ScRefFlags::TAB2_ABS ) == ScRefFlags::TAB2_ABS ) printf("ScRefFlags::TAB2_ABS \n");
79  if ((nFlag & ScRefFlags::TAB2_3D ) == ScRefFlags::TAB2_3D ) printf("ScRefFlags::TAB2_3D \n");
80  if ((nFlag & ScRefFlags::ROW_VALID ) == ScRefFlags::ROW_VALID ) printf("ScRefFlags::ROW_VALID \n");
81  if ((nFlag & ScRefFlags::COL_VALID ) == ScRefFlags::COL_VALID ) printf("ScRefFlags::COL_VALID \n");
82  if ((nFlag & ScRefFlags::TAB_VALID ) == ScRefFlags::TAB_VALID ) printf("ScRefFlags::TAB_VALID \n");
83  if ((nFlag & ScRefFlags::FORCE_DOC ) == ScRefFlags::FORCE_DOC ) printf("ScRefFlags::FORCE_DOC \n");
84  if ((nFlag & ScRefFlags::ROW2_VALID ) == ScRefFlags::ROW2_VALID ) printf("ScRefFlags::ROW2_VALID \n");
85  if ((nFlag & ScRefFlags::COL2_VALID ) == ScRefFlags::COL2_VALID ) printf("ScRefFlags::COL2_VALID \n");
86  if ((nFlag & ScRefFlags::TAB2_VALID ) == ScRefFlags::TAB2_VALID ) printf("ScRefFlags::TAB2_VALID \n");
87  if ((nFlag & ScRefFlags::VALID ) == ScRefFlags::VALID ) printf("ScRefFlags::VALID \n");
88  if ((nFlag & ScRefFlags::ADDR_ABS ) == ScRefFlags::ADDR_ABS ) printf("ScRefFlags::ADDR_ABS \n");
89  if ((nFlag & ScRefFlags::RANGE_ABS ) == ScRefFlags::RANGE_ABS ) printf("ScRefFlags::RANGE_ABS \n");
90  if ((nFlag & ScRefFlags::ADDR_ABS_3D ) == ScRefFlags::ADDR_ABS_3D ) printf("ScRefFlags::ADDR_ABS_3D \n");
91  if ((nFlag & ScRefFlags::RANGE_ABS_3D ) == ScRefFlags::RANGE_ABS_3D ) printf("ScRefFlags::RANGE_ABS_3D \n");
92 }
93 #endif
94 
95 
97  : ScAnyRefDlgController(pB, pCW, pParent, "modules/scalc/ui/printareasdialog.ui", "PrintAreasDialog")
98  , bDlgLostFocus(false)
99  , pDoc(nullptr)
100  , pViewData(nullptr)
101  , nCurTab(0)
102  , m_xLbPrintArea(m_xBuilder->weld_combo_box("lbprintarea"))
103  , m_xEdPrintArea(new formula::RefEdit(m_xBuilder->weld_entry("edprintarea")))
104  , m_xRbPrintArea(new formula::RefButton(m_xBuilder->weld_button("rbprintarea")))
105  , m_xLbRepeatRow(m_xBuilder->weld_combo_box("lbrepeatrow"))
106  , m_xEdRepeatRow(new formula::RefEdit(m_xBuilder->weld_entry("edrepeatrow")))
107  , m_xRbRepeatRow(new formula::RefButton(m_xBuilder->weld_button("rbrepeatrow")))
108  , m_xLbRepeatCol(m_xBuilder->weld_combo_box("lbrepeatcol"))
109  , m_xEdRepeatCol(new formula::RefEdit(m_xBuilder->weld_entry("edrepeatcol")))
110  , m_xRbRepeatCol(new formula::RefButton(m_xBuilder->weld_button("rbrepeatcol")))
111  , m_xBtnOk(m_xBuilder->weld_button("ok"))
112  , m_xBtnCancel(m_xBuilder->weld_button("cancel"))
113  , m_xPrintFrame(m_xBuilder->weld_frame("printframe"))
114  , m_xRowFrame(m_xBuilder->weld_frame("rowframe"))
115  , m_xColFrame(m_xBuilder->weld_frame("colframe"))
116  , m_xPrintFrameFT(m_xPrintFrame->weld_label_widget())
117  , m_xRowFrameFT(m_xRowFrame->weld_label_widget())
118  , m_xColFrameFT(m_xColFrame->weld_label_widget())
119 {
120  m_xEdPrintArea->SetReferences(this, m_xPrintFrameFT.get());
122  m_xRbPrintArea->SetReferences(this, m_xEdPrintArea.get());
123 
124  m_xEdRepeatRow->SetReferences(this, m_xRowFrameFT.get());
125  m_xRbRepeatRow->SetReferences(this, m_xEdRepeatRow.get());
126 
127  m_xEdRepeatCol->SetReferences(this, m_xColFrameFT.get());
128  m_xRbRepeatCol->SetReferences(this, m_xEdRepeatCol.get());
129 
130  ScTabViewShell* pScViewSh = dynamic_cast<ScTabViewShell*>( SfxViewShell::Current() );
131  ScDocShell* pScDocSh = dynamic_cast<ScDocShell*>(SfxObjectShell::Current());
132  assert(pScDocSh && "Current DocumentShell not found :-(");
133 
134  pDoc = &pScDocSh->GetDocument();
135 
136  if ( pScViewSh )
137  {
138  pViewData = &pScViewSh->GetViewData();
140  }
141 
142  Impl_Reset();
143 
144  //@BugID 54702 Enable/Disable only in base class
145  //SFX_APPWINDOW->Enable();
146 }
147 
149 {
150 }
151 
153 {
154  DoClose( ScPrintAreasDlgWrapper::GetChildWindowId() );
155 }
156 
158 {
159  // Printing areas are per table, therefore it makes no sense,
160  // to switch the table during input
161 
162  return true;
163 }
164 
165 void ScPrintAreasDlg::SetReference( const ScRange& rRef, ScDocument& /* rDoc */ )
166 {
167  if ( !m_pRefInputEdit )
168  return;
169 
170  if ( rRef.aStart != rRef.aEnd )
172 
173  OUString aStr;
175 
176  if (m_xEdPrintArea.get() == m_pRefInputEdit)
177  {
178  aStr = rRef.Format(*pDoc, ScRefFlags::RANGE_ABS, eConv);
179  OUString aVal = m_xEdPrintArea->GetText();
180  Selection aSel = m_xEdPrintArea->GetSelection();
181  aSel.Justify();
182  aVal = aVal.replaceAt( aSel.Min(), aSel.Len(), aStr );
183  Selection aNewSel( aSel.Min(), aSel.Min()+aStr.getLength() );
184  m_xEdPrintArea->SetRefString( aVal );
185  m_xEdPrintArea->SetSelection( aNewSel );
186  }
187  else
188  {
189  bool bRow = ( m_xEdRepeatRow.get() == m_pRefInputEdit );
190  lcl_GetRepeatRangeString(&rRef, *pDoc, bRow, aStr);
191  m_pRefInputEdit->SetRefString( aStr );
192  }
193  Impl_ModifyHdl( *m_pRefInputEdit );
194 }
195 
197 {
198  if (m_pRefInputEdit == m_xEdPrintArea.get())
199  {
201  OUString aVal = m_xEdPrintArea->GetText() + OUStringChar(sep);
202  m_xEdPrintArea->SetText(aVal);
203 
204  sal_Int32 nLen = aVal.getLength();
205  m_xEdPrintArea->SetSelection( Selection( nLen, nLen ) );
206 
207  Impl_ModifyHdl( *m_xEdPrintArea );
208  }
209 }
210 
212 {
213  bDlgLostFocus = true;
214 }
215 
217 {
218  if ( bDlgLostFocus )
219  {
220  bDlgLostFocus = false;
221 
222  if ( m_pRefInputEdit )
223  {
225  Impl_ModifyHdl( *m_pRefInputEdit );
226  }
227  }
228  else
229  m_xDialog->grab_focus();
230 
231  RefInputDone();
232 }
233 
235 {
236  OUString aStrRange;
237  const ScRange* pRepeatColRange = pDoc->GetRepeatColRange( nCurTab );
238  const ScRange* pRepeatRowRange = pDoc->GetRepeatRowRange( nCurTab );
239 
240  m_xEdPrintArea->SetModifyHdl (LINK( this, ScPrintAreasDlg, Impl_ModifyHdl));
241  m_xEdRepeatRow->SetModifyHdl (LINK( this, ScPrintAreasDlg, Impl_ModifyHdl));
242  m_xEdRepeatCol->SetModifyHdl (LINK( this, ScPrintAreasDlg, Impl_ModifyHdl));
243  m_xEdPrintArea->SetGetFocusHdl(LINK( this, ScPrintAreasDlg, Impl_GetEditFocusHdl));
244  m_xEdRepeatRow->SetGetFocusHdl(LINK( this, ScPrintAreasDlg, Impl_GetEditFocusHdl));
245  m_xEdRepeatCol->SetGetFocusHdl(LINK( this, ScPrintAreasDlg, Impl_GetEditFocusHdl));
246  m_xLbPrintArea->connect_focus_in(LINK( this, ScPrintAreasDlg, Impl_GetFocusHdl));
247  m_xLbRepeatRow->connect_focus_in(LINK( this, ScPrintAreasDlg, Impl_GetFocusHdl));
248  m_xLbRepeatCol->connect_focus_in(LINK( this, ScPrintAreasDlg, Impl_GetFocusHdl));
249  m_xLbPrintArea->connect_changed(LINK( this, ScPrintAreasDlg, Impl_SelectHdl));
250  m_xLbRepeatRow->connect_changed(LINK( this, ScPrintAreasDlg, Impl_SelectHdl));
251  m_xLbRepeatCol->connect_changed(LINK( this, ScPrintAreasDlg, Impl_SelectHdl));
252  m_xBtnOk->connect_clicked(LINK( this, ScPrintAreasDlg, Impl_BtnHdl));
253  m_xBtnCancel->connect_clicked(LINK( this, ScPrintAreasDlg, Impl_BtnHdl));
254 
255  Impl_FillLists();
256 
257  // printing area
258 
259  aStrRange.clear();
262  sal_uInt16 nRangeCount = pDoc->GetPrintRangeCount( nCurTab );
263  for (sal_uInt16 i=0; i<nRangeCount; i++)
264  {
265  const ScRange* pPrintRange = pDoc->GetPrintRange( nCurTab, i );
266  if (pPrintRange)
267  {
268  if ( !aStrRange.isEmpty() )
269  aStrRange += OUStringChar(sep);
270  aStrRange += pPrintRange->Format(*pDoc, ScRefFlags::RANGE_ABS, eConv);
271  }
272  }
273  m_xEdPrintArea->SetText( aStrRange );
274 
275  // repeat row
276 
277  lcl_GetRepeatRangeString(pRepeatRowRange, *pDoc, true, aStrRange);
278  m_xEdRepeatRow->SetText( aStrRange );
279 
280  // repeat column
281 
282  lcl_GetRepeatRangeString(pRepeatColRange, *pDoc, false, aStrRange);
283  m_xEdRepeatCol->SetText( aStrRange );
284 
285  Impl_ModifyHdl( *m_xEdPrintArea );
286  Impl_ModifyHdl( *m_xEdRepeatRow );
287  Impl_ModifyHdl( *m_xEdRepeatCol );
290 
291  m_xEdPrintArea->SaveValue(); // save for FillItemSet():
292  m_xEdRepeatRow->SaveValue();
293  m_xEdRepeatCol->SaveValue();
294 }
295 
297 {
298  OUString aRangeStr = pEd->GetText();
299  bool bDataChanged = pEd->IsValueChangedFromSaved();
300 
301  if ( !aRangeStr.isEmpty() && m_xEdPrintArea.get() != pEd )
302  {
303  ScRange aRange;
305  lcl_CheckRepeatString(aRangeStr, *pDoc, m_xEdRepeatRow.get() == pEd, &aRange);
306  aRangeStr = aRange.Format(*pDoc, ScRefFlags::RANGE_ABS, eConv);
307  }
308 
309  rItem.SetValue( aRangeStr );
310 
311  return bDataChanged;
312 }
313 
315 {
316  bool bOk = false;
317  OUString aStrPrintArea = m_xEdPrintArea->GetText();
318  OUString aStrRepeatRow = m_xEdRepeatRow->GetText();
319  OUString aStrRepeatCol = m_xEdRepeatCol->GetText();
320 
321  bool bPrintAreaOk = true;
322  if ( !aStrPrintArea.isEmpty() )
323  {
324  const ScRefFlags nValidAddr = ScRefFlags::VALID | ScRefFlags::ROW_VALID | ScRefFlags::COL_VALID;
325  const ScRefFlags nValidRange = nValidAddr | ScRefFlags::ROW2_VALID | ScRefFlags::COL2_VALID;
328 
329  ScAddress aAddr;
330  ScRange aRange;
331  for ( sal_Int32 nIdx = 0; nIdx >= 0; )
332  {
333  const OUString aOne = aStrPrintArea.getToken(0, sep, nIdx);
334  ScRefFlags nResult = aRange.Parse( aOne, *pDoc, eConv );
335  if ((nResult & nValidRange) != nValidRange)
336  {
337  ScRefFlags nAddrResult = aAddr.Parse( aOne, *pDoc, eConv );
338  if ((nAddrResult & nValidAddr) != nValidAddr)
339  {
340  bPrintAreaOk = false;
341  break;
342  }
343  }
344  }
345  }
346 
347  bool bRepeatRowOk = aStrRepeatRow.isEmpty();
348  if ( !bRepeatRowOk )
349  bRepeatRowOk = lcl_CheckRepeatString(aStrRepeatRow, *pDoc, true, nullptr);
350 
351  bool bRepeatColOk = aStrRepeatCol.isEmpty();
352  if ( !bRepeatColOk )
353  bRepeatColOk = lcl_CheckRepeatString(aStrRepeatCol, *pDoc, false, nullptr);
354 
355  // error messages
356 
357  bOk = (bPrintAreaOk && bRepeatRowOk && bRepeatColOk);
358 
359  if ( !bOk )
360  {
361  formula::RefEdit* pEd = nullptr;
362 
363  if ( !bPrintAreaOk ) pEd = m_xEdPrintArea.get();
364  else if ( !bRepeatRowOk ) pEd = m_xEdRepeatRow.get();
365  else if ( !bRepeatColOk ) pEd = m_xEdRepeatCol.get();
366 
367  ERRORBOX(m_xDialog.get(), STR_INVALID_TABREF);
368 
369  OSL_ASSERT(pEd);
370 
371  if (pEd)
372  pEd->GrabFocus();
373  }
374 
375  return bOk;
376 }
377 
379 {
380 
381  // Get selection and remember String in PrintArea-ListBox
382 
383  ScRange aRange;
384  OUString aStrRange;
385  bool bSimple = true;
386 
387  if ( pViewData )
388  bSimple = (pViewData->GetSimpleArea( aRange ) == SC_MARK_SIMPLE);
389 
391 
392  if ( bSimple )
393  aStrRange = aRange.Format(*pDoc, ScRefFlags::RANGE_ABS, eConv);
394  else
395  {
396  ScRangeListRef aList( new ScRangeList );
397  pViewData->GetMarkData().FillRangeListWithMarks( aList.get(), false );
398  aList->Format(aStrRange, ScRefFlags::RANGE_ABS, *pDoc, eConv);
399  }
400 
401  m_xLbPrintArea->set_id(SC_AREASDLG_PR_SELECT, aStrRange);
402 
403  // Get ranges and remember in ListBoxen
404 
405  ScRangeName* pRangeNames = pDoc->GetRangeName();
406 
407  if (!pRangeNames || pRangeNames->empty())
408  // No range names to process.
409  return;
410 
411  for (const auto& rEntry : *pRangeNames)
412  {
413  if (!rEntry.second->HasType(ScRangeData::Type::AbsArea )
414  && !rEntry.second->HasType(ScRangeData::Type::RefArea)
415  && !rEntry.second->HasType(ScRangeData::Type::AbsPos ))
416  continue;
417 
418  OUString aName = rEntry.second->GetName();
419  OUString aSymbol;
420  rEntry.second->GetSymbol(aSymbol);
421  if (aRange.ParseAny(aSymbol, *pDoc, eConv) & ScRefFlags::VALID)
422  {
423  if (rEntry.second->HasType(ScRangeData::Type::PrintArea))
424  {
425  aSymbol = aRange.Format(*pDoc, ScRefFlags::RANGE_ABS, eConv);
426  m_xLbPrintArea->append(aSymbol, aName);
427  }
428 
429  if (rEntry.second->HasType(ScRangeData::Type::RowHeader))
430  {
431  lcl_GetRepeatRangeString(&aRange, *pDoc, true, aSymbol);
432  m_xLbRepeatRow->append(aSymbol, aName);
433  }
434 
435  if (rEntry.second->HasType(ScRangeData::Type::ColHeader))
436  {
437  lcl_GetRepeatRangeString(&aRange, *pDoc, false, aSymbol);
438  m_xLbRepeatCol->append(aSymbol, aName);
439  }
440  }
441  }
442 }
443 
444 // Handler:
445 
446 IMPL_LINK(ScPrintAreasDlg, Impl_BtnHdl, weld::Button&, rBtn, void)
447 {
448  if (m_xBtnOk.get() == &rBtn)
449  {
450  if ( Impl_CheckRefStrings() )
451  {
452  SfxStringItem aPrintArea( SID_CHANGE_PRINTAREA, "" );
453  SfxStringItem aRepeatRow( FN_PARAM_2, "" );
454  SfxStringItem aRepeatCol( FN_PARAM_3, "" );
455 
456  // Printing area changed?
457 
458  // first try the list box, if "Entire sheet" is selected
459  bool bEntireSheet = (m_xLbPrintArea->get_active() == SC_AREASDLG_PR_ENTIRE);
460  SfxBoolItem aEntireSheet( FN_PARAM_4, bEntireSheet );
461 
462  bool bDataChanged = bEntireSheet != pDoc->IsPrintEntireSheet( nCurTab );
463  if( !bEntireSheet )
464  {
465  // if new list box selection is not "Entire sheet", get the edit field contents
466  bDataChanged |= Impl_GetItem( m_xEdPrintArea.get(), aPrintArea );
467  }
468 
469  // Repeat row changed?
470 
471  bDataChanged |= Impl_GetItem( m_xEdRepeatRow.get(), aRepeatRow );
472 
473  // Repeat column changed?
474 
475  bDataChanged |= Impl_GetItem( m_xEdRepeatCol.get(), aRepeatCol );
476 
477  if ( bDataChanged )
478  {
479  SetDispatcherLock( false );
480  SwitchToDocument();
481  GetBindings().GetDispatcher()->ExecuteList(SID_CHANGE_PRINTAREA,
482  SfxCallMode::SLOT | SfxCallMode::RECORD,
483  { &aPrintArea, &aRepeatRow, &aRepeatCol, &aEntireSheet });
484  }
485 
486  response(RET_OK);
487  }
488  }
489  else if (m_xBtnCancel.get() == &rBtn)
490  response(RET_CANCEL);
491 }
492 
493 IMPL_LINK(ScPrintAreasDlg, Impl_GetEditFocusHdl, formula::RefEdit&, rCtrl, void)
494 {
495  m_pRefInputEdit = &rCtrl;
496 }
497 
498 IMPL_LINK(ScPrintAreasDlg, Impl_GetFocusHdl, weld::Widget&, rCtrl, void)
499 {
500  if (&rCtrl == m_xLbPrintArea.get())
501  m_pRefInputEdit = m_xEdPrintArea.get();
502  else if (&rCtrl == m_xLbRepeatRow.get())
503  m_pRefInputEdit = m_xEdRepeatRow.get();
504  else if (&rCtrl == m_xLbRepeatCol.get())
505  m_pRefInputEdit = m_xEdRepeatCol.get();
506 }
507 
508 IMPL_LINK( ScPrintAreasDlg, Impl_SelectHdl, weld::ComboBox&, rLb, void )
509 {
510  const sal_Int32 nSelPos = rLb.get_active();
511  formula::RefEdit* pEd = nullptr;
512 
513  // list box positions of specific entries, default to "repeat row/column" list boxes
514  sal_Int32 nAllSheetPos = SC_AREASDLG_RR_NONE;
515  sal_Int32 nFirstCustomPos = SC_AREASDLG_RR_OFFSET;
516 
517  // find edit field for list box, and list box positions
518  if (&rLb == m_xLbPrintArea.get())
519  {
520  pEd = m_xEdPrintArea.get();
521  nAllSheetPos = SC_AREASDLG_PR_ENTIRE;
522  nFirstCustomPos = SC_AREASDLG_PR_SELECT; // "Selection" and following
523  }
524  else if (&rLb == m_xLbRepeatCol.get())
525  pEd = m_xEdRepeatCol.get();
526  else if (&rLb == m_xLbRepeatRow.get())
527  pEd = m_xEdRepeatRow.get();
528  else
529  return;
530 
531  // fill edit field according to list box selection
532  if( (nSelPos == 0) || (nSelPos == nAllSheetPos) )
533  pEd->SetText( EMPTY_OUSTRING );
534  else if( nSelPos >= nFirstCustomPos )
535  pEd->SetText(rLb.get_id(nSelPos));
536 }
537 
538 IMPL_LINK( ScPrintAreasDlg, Impl_ModifyHdl, formula::RefEdit&, rEd, void )
539 {
540  weld::ComboBox* pLb = nullptr;
541 
542  // list box positions of specific entries, default to "repeat row/column" list boxes
543  sal_Int32 nUserDefPos = SC_AREASDLG_RR_USER;
544  sal_Int32 nFirstCustomPos = SC_AREASDLG_RR_OFFSET;
545 
546  if( &rEd == m_xEdPrintArea.get() )
547  {
548  pLb = m_xLbPrintArea.get();
549  nUserDefPos = SC_AREASDLG_PR_USER;
550  nFirstCustomPos = SC_AREASDLG_PR_SELECT; // "Selection" and following
551  }
552  else if( &rEd == m_xEdRepeatCol.get() )
553  pLb = m_xLbRepeatCol.get();
554  else if( &rEd == m_xEdRepeatRow.get() )
555  pLb = m_xLbRepeatRow.get();
556  else
557  return;
558 
559  // set list box selection according to edit field
560  const sal_Int32 nEntryCount = pLb->get_count();
561  OUString aStrEd( rEd.GetText() );
562  OUString aEdUpper = aStrEd.toAsciiUpperCase();
563 
564  if ( (nEntryCount > nFirstCustomPos) && !aStrEd.isEmpty() )
565  {
566  bool bFound = false;
567  sal_Int32 i;
568 
569  for ( i=nFirstCustomPos; i<nEntryCount && !bFound; i++ )
570  {
571  const OUString& rSymbol = pLb->get_id(i);
572  bFound = (rSymbol == aStrEd || rSymbol == aEdUpper);
573  }
574 
575  pLb->set_active( bFound ? i-1 : nUserDefPos );
576  }
577  else
578  pLb->set_active( !aStrEd.isEmpty() ? nUserDefPos : 0 );
579 }
580 
581 // global functions:
582 
583 // TODO: It might make sense to move these functions to address.?xx. -kohei
584 
585 static bool lcl_CheckOne_OOO( const ScDocument& rDoc, const OUString& rStr, bool bIsRow, SCCOLROW& rVal )
586 {
587  // Allowed syntax for rStr:
588  // Row: [$]1-MAXTAB
589  // Col: [$]A-IV
590 
591  OUString aStr = rStr;
592  sal_Int32 nLen = aStr.getLength();
593  SCCOLROW nNum = 0;
594  bool bStrOk = ( nLen > 0 ) && ( bIsRow ? ( nLen < 6 ) : ( nLen < 4 ) );
595 
596  if ( bStrOk )
597  {
598  if ( '$' == aStr[0] )
599  aStr = aStr.copy( 1 );
600 
601  if ( bIsRow )
602  {
603  bStrOk = CharClass::isAsciiNumeric(aStr);
604 
605  if ( bStrOk )
606  {
607  sal_Int32 n = aStr.toInt32();
608 
609  bStrOk = (n > 0) && ( n <= rDoc.GetSheetLimits().GetMaxRowCount() );
610  if ( bStrOk )
611  nNum = static_cast<SCCOLROW>(n - 1);
612  }
613  }
614  else
615  {
616  SCCOL nCol = 0;
617  bStrOk = ::AlphaToCol(rDoc, nCol, aStr);
618  nNum = nCol;
619  }
620  }
621 
622  if ( bStrOk )
623  rVal = nNum;
624 
625  return bStrOk;
626 }
627 
628 static bool lcl_CheckOne_XL_A1( const ScDocument& rDoc, const OUString& rStr, bool bIsRow, SCCOLROW& rVal )
629 {
630  // XL A1 style is identical to OOO one for print range formats.
631  return lcl_CheckOne_OOO(rDoc, rStr, bIsRow, rVal);
632 }
633 
634 static bool lcl_CheckOne_XL_R1C1( const ScDocument& rDoc, const OUString& rStr, bool bIsRow, SCCOLROW& rVal )
635 {
636  sal_Int32 nLen = rStr.getLength();
637  if (nLen <= 1)
638  // There must be at least two characters.
639  return false;
640 
641  const sal_Unicode preUpper = bIsRow ? 'R' : 'C';
642  const sal_Unicode preLower = bIsRow ? 'r' : 'c';
643  if (rStr[0] != preUpper && rStr[0] != preLower)
644  return false;
645 
646  OUString aNumStr = rStr.copy(1);
647  if (!CharClass::isAsciiNumeric(aNumStr))
648  return false;
649 
650  sal_Int32 nNum = aNumStr.toInt32();
651 
652  if (nNum <= 0)
653  return false;
654 
655  if ((bIsRow && nNum > rDoc.GetSheetLimits().GetMaxRowCount()) ||
656  (!bIsRow && nNum > rDoc.GetSheetLimits().GetMaxColCount()))
657  return false;
658 
659  rVal = static_cast<SCCOLROW>(nNum-1);
660  return true;
661 }
662 
663 static bool lcl_CheckRepeatOne( const ScDocument& rDoc, const OUString& rStr, formula::FormulaGrammar::AddressConvention eConv, bool bIsRow, SCCOLROW& rVal )
664 {
665  switch (eConv)
666  {
668  return lcl_CheckOne_OOO(rDoc, rStr, bIsRow, rVal);
670  return lcl_CheckOne_XL_A1(rDoc, rStr, bIsRow, rVal);
672  return lcl_CheckOne_XL_R1C1(rDoc, rStr, bIsRow, rVal);
673  default:
674  {
675  // added to avoid warnings
676  }
677  }
678  return false;
679 }
680 
681 static bool lcl_CheckRepeatString( const OUString& rStr, const ScDocument& rDoc, bool bIsRow, ScRange* pRange )
682 {
683  // Row: [valid row] rsep [valid row]
684  // Col: [valid col] rsep [valid col]
685 
688 
689  if (pRange)
690  {
691  // initialize the range value.
692  pRange->aStart.SetCol(0);
693  pRange->aStart.SetRow(0);
694  pRange->aEnd.SetCol(0);
695  pRange->aEnd.SetRow(0);
696  }
697 
698  OUString aBuf;
699  SCCOLROW nVal = 0;
700  sal_Int32 nLen = rStr.getLength();
701  bool bEndPos = false;
702  for( sal_Int32 i = 0; i < nLen; ++i )
703  {
704  const sal_Unicode c = rStr[i];
705  if (c == rsep)
706  {
707  if (bEndPos)
708  // We aren't supposed to have more than one range separator.
709  return false;
710 
711  // range separator
712  if (aBuf.isEmpty())
713  return false;
714 
715  bool bRes = lcl_CheckRepeatOne(rDoc, aBuf, eConv, bIsRow, nVal);
716  if (!bRes)
717  return false;
718 
719  if (pRange)
720  {
721  if (bIsRow)
722  {
723  pRange->aStart.SetRow(static_cast<SCROW>(nVal));
724  pRange->aEnd.SetRow(static_cast<SCROW>(nVal));
725  }
726  else
727  {
728  pRange->aStart.SetCol(static_cast<SCCOL>(nVal));
729  pRange->aEnd.SetCol(static_cast<SCCOL>(nVal));
730  }
731  }
732 
733  aBuf.clear();
734  bEndPos = true;
735  }
736  else
737  aBuf += OUStringChar(c);
738  }
739 
740  if (!aBuf.isEmpty())
741  {
742  bool bRes = lcl_CheckRepeatOne(rDoc, aBuf, eConv, bIsRow, nVal);
743  if (!bRes)
744  return false;
745 
746  if (pRange)
747  {
748  if (bIsRow)
749  {
750  if (!bEndPos)
751  pRange->aStart.SetRow(static_cast<SCROW>(nVal));
752  pRange->aEnd.SetRow(static_cast<SCROW>(nVal));
753  }
754  else
755  {
756  if (!bEndPos)
757  pRange->aStart.SetCol(static_cast<SCCOL>(nVal));
758  pRange->aEnd.SetCol(static_cast<SCCOL>(nVal));
759  }
760  }
761  }
762 
763  return true;
764 }
765 
766 static void lcl_GetRepeatRangeString( const ScRange* pRange, const ScDocument& rDoc, bool bIsRow, OUString& rStr )
767 {
768  rStr.clear();
769  if (!pRange)
770  return;
771 
773  const ScAddress& rStart = pRange->aStart;
774  const ScAddress& rEnd = pRange->aEnd;
775 
776  const ScRefFlags nFmt = bIsRow
777  ? (ScRefFlags::ROW_VALID | ScRefFlags::ROW_ABS)
778  : (ScRefFlags::COL_VALID | ScRefFlags::COL_ABS);
779  rStr += rStart.Format(nFmt, &rDoc, eConv);
780  if ((bIsRow && rStart.Row() != rEnd.Row()) || (!bIsRow && rStart.Col() != rEnd.Col()))
781  {
783  rStr += rEnd.Format(nFmt, &rDoc, eConv);
784  }
785 }
786 
787 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
ScMarkData & GetMarkData()
Definition: viewdata.cxx:3099
SC_DLLPUBLIC ScRefFlags ParseAny(const OUString &, const ScDocument &, const ScAddress::Details &rDetails=ScAddress::detailsOOOa1)
Definition: address.cxx:1775
virtual ~ScPrintAreasDlg() override
Definition: areasdlg.cxx:148
std::unique_ptr< weld::Label > m_xRowFrameFT
Definition: areasdlg.hxx:72
SC_DLLPUBLIC void Format(OStringBuffer &r, ScRefFlags nFlags, const ScDocument *pDocument=nullptr, const Details &rDetails=detailsOOOa1) const
Definition: address.cxx:2116
virtual bool IsTableLocked() const override
Definition: areasdlg.cxx:157
static void lcl_GetRepeatRangeString(const ScRange *pRange, const ScDocument &rDoc, bool bIsRow, OUString &rStr)
Definition: areasdlg.cxx:766
SC_DLLPUBLIC const ScRange * GetRepeatColRange(SCTAB nTab)
Definition: document.cxx:6313
ScAddress aStart
Definition: address.hxx:499
#define EMPTY_OUSTRING
Definition: global.hxx:213
SCROW Row() const
Definition: address.hxx:261
std::unique_ptr< weld::ComboBox > m_xLbRepeatCol
Definition: areasdlg.hxx:60
std::unique_ptr< weld::Label > m_xColFrameFT
Definition: areasdlg.hxx:73
static bool lcl_CheckRepeatOne(const ScDocument &rDoc, const OUString &rStr, formula::FormulaGrammar::AddressConvention eConv, bool bIsRow, SCCOLROW &rVal)
Definition: areasdlg.cxx:663
void Format(OUString &, ScRefFlags nFlags, const ScDocument &, formula::FormulaGrammar::AddressConvention eConv=formula::FormulaGrammar::CONV_OOO, sal_Unicode cDelimiter=0, bool bFullAddressNotation=false) const
Definition: rangelst.cxx:144
SCCOL GetMaxColCount() const
Definition: sheetlimits.hxx:63
SC_DLLPUBLIC ScRangeName * GetRangeName(SCTAB nTab) const
Definition: documen3.cxx:168
bool Impl_CheckRefStrings()
Definition: areasdlg.cxx:314
sal_Int64 n
aBuf
void FillRangeListWithMarks(ScRangeList *pList, bool bClear, SCTAB nForTab=-1) const
Create a range list of marks.
Definition: markdata.cxx:387
SCTAB GetTabNo() const
Definition: viewdata.hxx:394
ScAddress aEnd
Definition: address.hxx:500
std::unique_ptr< weld::ComboBox > m_xLbPrintArea
Definition: areasdlg.hxx:52
std::unique_ptr< weld::Button > m_xBtnOk
Definition: areasdlg.hxx:64
static SfxObjectShell * Current()
bool Impl_GetItem(const formula::RefEdit *pEd, SfxStringItem &rItem)
Definition: areasdlg.cxx:296
SCROW GetMaxRowCount() const
Definition: sheetlimits.hxx:61
std::unique_ptr< weld::ComboBox > m_xLbRepeatRow
Definition: areasdlg.hxx:56
RET_CANCEL
SC_DLLPUBLIC formula::FormulaGrammar::AddressConvention GetAddressConvention() const
Definition: documen3.cxx:494
virtual int get_count() const =0
std::unique_ptr< formula::RefEdit > m_xEdRepeatCol
Definition: areasdlg.hxx:61
std::unique_ptr< formula::RefEdit > m_xEdRepeatRow
Definition: areasdlg.hxx:57
sal_uInt16 sal_Unicode
void Impl_FillLists()
Definition: areasdlg.cxx:378
void SetValue(const OUString &rTheValue)
sal_Int32 SCCOLROW
a type capable of holding either SCCOL or SCROW
Definition: types.hxx:23
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
bool empty() const
Definition: rangenam.cxx:804
static SfxViewShell * Current()
SC_DLLPUBLIC const ScRange * GetPrintRange(SCTAB nTab, sal_uInt16 nPos)
Definition: document.cxx:6305
void SetRow(SCROW nRowP)
Definition: address.hxx:274
static sal_Unicode GetNativeSymbolChar(OpCode eOp)
void SetCol(SCCOL nColP)
Definition: address.hxx:278
bool IsPrintEntireSheet(SCTAB nTab) const
Returns true, if the specified sheet is always printed.
Definition: document.cxx:6292
ScViewData & GetViewData()
Definition: tabview.hxx:333
ScPrintAreasDlg(SfxBindings *pB, SfxChildWindow *pCW, weld::Window *pParent)
Definition: areasdlg.cxx:96
ocSep
std::unique_ptr< weld::Button > m_xBtnCancel
Definition: areasdlg.hxx:65
void Impl_Reset()
Definition: areasdlg.cxx:234
void SetRefString(const OUString &rStr)
T * get() const
void Justify()
SC_DLLPUBLIC sal_uInt16 GetPrintRangeCount(SCTAB nTab)
Definition: document.cxx:6297
static const OUString & GetNativeSymbol(OpCode eOp)
virtual void AddRefEntry() override
Definition: areasdlg.cxx:196
int i
std::unique_ptr< formula::RefButton > m_xRbPrintArea
Definition: areasdlg.hxx:54
sal_Int16 SCCOL
Definition: types.hxx:21
static bool lcl_CheckOne_XL_A1(const ScDocument &rDoc, const OUString &rStr, bool bIsRow, SCCOLROW &rVal)
Definition: areasdlg.cxx:628
virtual void Close() override
Definition: areasdlg.cxx:152
ScSheetLimits & GetSheetLimits() const
Definition: document.hxx:872
SC_DLLPUBLIC OUString Format(const ScDocument &rDocument, ScRefFlags nFlags=ScRefFlags::ZERO, const ScAddress::Details &rDetails=ScAddress::detailsOOOa1, bool bFullAddressNotation=false) const
Returns string with formatted cell range from aStart to aEnd, according to provided address conventio...
Definition: address.cxx:2212
OUString ScResId(const char *pId)
Definition: scdll.cxx:89
ScMarkType GetSimpleArea(SCCOL &rStartCol, SCROW &rStartRow, SCTAB &rStartTab, SCCOL &rEndCol, SCROW &rEndRow, SCTAB &rEndTab) const
Definition: viewdata.cxx:1173
void SetText(const OUString &rStr)
std::unique_ptr< formula::RefButton > m_xRbRepeatRow
Definition: areasdlg.hxx:58
virtual void RefInputDone(bool bForced=false) override
Definition: anyrefdg.cxx:756
ScViewData * pViewData
Definition: areasdlg.hxx:47
OUString GetText() const
virtual void set_active(int pos)=0
IMPL_LINK(ScPrintAreasDlg, Impl_BtnHdl, weld::Button &, rBtn, void)
Definition: areasdlg.cxx:446
SCCOL Col() const
Definition: address.hxx:266
tools::Long Len() const
formula::RefEdit * m_pRefInputEdit
Definition: areasdlg.hxx:50
bool AlphaToCol(const ScDocument &rDoc, SCCOL &rCol, const OUString &rStr)
get column number of A..IV... string
Definition: address.cxx:2541
std::unique_ptr< formula::RefEdit > m_xEdPrintArea
Definition: areasdlg.hxx:53
bool IsValueChangedFromSaved() const
static bool lcl_CheckRepeatString(const OUString &rStr, const ScDocument &rDoc, bool bIsRow, ScRange *pRange)
Definition: areasdlg.cxx:681
static bool lcl_CheckOne_OOO(const ScDocument &rDoc, const OUString &rStr, bool bIsRow, SCCOLROW &rVal)
Definition: areasdlg.cxx:585
virtual void Deactivate() override
Definition: areasdlg.cxx:211
SC_DLLPUBLIC const ScRange * GetRepeatRowRange(SCTAB nTab)
Definition: document.cxx:6321
std::unique_ptr< formula::RefButton > m_xRbRepeatCol
Definition: areasdlg.hxx:62
tools::Long Min() const
OUString aName
RET_OK
SC_DLLPUBLIC ScRefFlags Parse(const OUString &, const ScDocument &, const ScAddress::Details &rDetails=ScAddress::detailsOOOa1, ScAddress::ExternalInfo *pExtInfo=nullptr, const css::uno::Sequence< css::sheet::ExternalLinkInfo > *pExternalLinks=nullptr, const OUString *pErrRef=nullptr)
Definition: address.cxx:1742
virtual void SetActive() override
Definition: areasdlg.cxx:216
Reference< XExecutableDialog > m_xDialog
const ScDocument & GetDocument() const
Definition: docsh.hxx:216
virtual OUString get_id(int pos) const =0
static bool isAsciiNumeric(const OUString &rStr)
ScDocument * pDoc
Definition: areasdlg.hxx:46
std::unique_ptr< weld::Label > m_xPrintFrameFT
Definition: areasdlg.hxx:71
bool bDlgLostFocus
Definition: areasdlg.hxx:45
SC_DLLPUBLIC ScRefFlags Parse(const OUString &, const ScDocument &, const Details &rDetails=detailsOOOa1, ExternalInfo *pExtInfo=nullptr, const css::uno::Sequence< css::sheet::ExternalLinkInfo > *pExternalLinks=nullptr, sal_Int32 *pSheetEndPos=nullptr, const OUString *pErrRef=nullptr)
Definition: address.cxx:1548
ScRefFlags
Definition: address.hxx:144
virtual void SetReference(const ScRange &rRef, ScDocument &rDoc) override
Definition: areasdlg.cxx:165
bool DoClose(sal_uInt16 nId)
Definition: anyrefdg.cxx:695
ocRange
aStr
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage, bool bMobile=false)
static bool lcl_CheckOne_XL_R1C1(const ScDocument &rDoc, const OUString &rStr, bool bIsRow, SCCOLROW &rVal)
Definition: areasdlg.cxx:634
virtual void RefInputStart(formula::RefEdit *pEdit, formula::RefButton *pButton=nullptr) override
Definition: anyrefdg.cxx:726