tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sc / source / ui / unoobj / datauno.cxx
blob99cb53d482221de2e9090830046a37005b25a98e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <datauno.hxx>
22 #include <svl/hint.hxx>
23 #include <svl/numformat.hxx>
24 #include <svl/sharedstringpool.hxx>
25 #include <utility>
26 #include <vcl/svapp.hxx>
27 #include <unotools/charclass.hxx>
28 #include <osl/diagnose.h>
30 #include <com/sun/star/awt/XBitmap.hpp>
31 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
32 #include <com/sun/star/util/SortField.hpp>
33 #include <com/sun/star/table/TableSortField.hpp>
34 #include <com/sun/star/beans/PropertyAttribute.hpp>
35 #include <com/sun/star/table/TableOrientation.hpp>
36 #include <com/sun/star/table/CellRangeAddress.hpp>
37 #include <com/sun/star/sheet/DataImportMode.hpp>
38 #include <com/sun/star/sheet/FilterFieldType.hpp>
39 #include <com/sun/star/sheet/FilterOperator2.hpp>
40 #include <com/sun/star/sheet/TableFilterField2.hpp>
42 #include <dapiuno.hxx>
43 #include <cellsuno.hxx>
44 #include <miscuno.hxx>
45 #include <targuno.hxx>
46 #include <rangeutl.hxx>
47 #include <dbdata.hxx>
48 #include <docsh.hxx>
49 #include <dbdocfun.hxx>
50 #include <unonames.hxx>
51 #include <globalnames.hxx>
52 #include <convuno.hxx>
53 #include <hints.hxx>
54 #include <attrib.hxx>
55 #include <dpshttab.hxx>
56 #include <queryentry.hxx>
57 #include <dputil.hxx>
58 #include <sortparam.hxx>
59 #include <dpobject.hxx>
60 #include <filterentries.hxx>
62 #include <comphelper/extract.hxx>
63 #include <cppuhelper/supportsservice.hxx>
64 #include <svx/dataaccessdescriptor.hxx>
66 #include <memory>
68 using namespace com::sun::star;
69 using namespace css::sheet;
71 // everything without Which-ID, map only for PropertySetInfo
73 static std::span<const SfxItemPropertyMapEntry> lcl_GetSubTotalPropertyMap()
75 // some old property names are for 5.2 compatibility
77 static const SfxItemPropertyMapEntry aSubTotalPropertyMap_Impl[] =
79 { SC_UNONAME_BINDFMT, 0, cppu::UnoType<bool>::get(), 0, 0},
80 { SC_UNONAME_CASE, 0, cppu::UnoType<bool>::get(), 0, 0},
81 { SC_UNONAME_ENABSORT, 0, cppu::UnoType<bool>::get(), 0, 0},
82 { SC_UNONAME_ENUSLIST, 0, cppu::UnoType<bool>::get(), 0, 0},
83 { SC_UNONAME_FORMATS, 0, cppu::UnoType<bool>::get(), 0, 0},
84 { SC_UNONAME_INSBRK, 0, cppu::UnoType<bool>::get(), 0, 0},
85 { SC_UNONAME_ISCASE, 0, cppu::UnoType<bool>::get(), 0, 0},
86 { SC_UNONAME_MAXFLD, 0, cppu::UnoType<sal_Int32>::get(), beans::PropertyAttribute::READONLY, 0},
87 { SC_UNONAME_SORTASC, 0, cppu::UnoType<bool>::get(), 0, 0},
88 { SC_UNONAME_ULIST, 0, cppu::UnoType<bool>::get(), 0, 0},
89 { SC_UNONAME_UINDEX, 0, cppu::UnoType<sal_Int32>::get(), 0, 0},
90 { SC_UNONAME_USINDEX, 0, cppu::UnoType<sal_Int32>::get(), 0, 0},
92 return aSubTotalPropertyMap_Impl;
95 static std::span<const SfxItemPropertyMapEntry> lcl_GetFilterPropertyMap()
97 static const SfxItemPropertyMapEntry aFilterPropertyMap_Impl[] =
99 { SC_UNONAME_CONTHDR, 0, cppu::UnoType<bool>::get(), 0, 0},
100 { SC_UNONAME_COPYOUT, 0, cppu::UnoType<bool>::get(), 0, 0},
101 { SC_UNONAME_ISCASE, 0, cppu::UnoType<bool>::get(), 0, 0},
102 { SC_UNONAME_MAXFLD, 0, cppu::UnoType<sal_Int32>::get(), beans::PropertyAttribute::READONLY, 0},
103 { SC_UNONAME_ORIENT, 0, cppu::UnoType<table::TableOrientation>::get(), 0, 0},
104 { SC_UNONAME_OUTPOS, 0, cppu::UnoType<table::CellAddress>::get(), 0, 0},
105 { SC_UNONAME_SAVEOUT, 0, cppu::UnoType<bool>::get(), 0, 0},
106 { SC_UNONAME_SKIPDUP, 0, cppu::UnoType<bool>::get(), 0, 0},
107 { SC_UNONAME_USEREGEX, 0, cppu::UnoType<bool>::get(), 0, 0},
109 return aFilterPropertyMap_Impl;
112 static std::span<const SfxItemPropertyMapEntry> lcl_GetDBRangePropertyMap()
114 static const SfxItemPropertyMapEntry aDBRangePropertyMap_Impl[] =
116 { SC_UNONAME_AUTOFLT, 0, cppu::UnoType<bool>::get(), 0, 0},
117 { SC_UNONAME_FLTCRT, 0, cppu::UnoType<table::CellRangeAddress>::get(), 0, 0},
118 { SC_UNONAME_FROMSELECT,0, cppu::UnoType<bool>::get(), 0, 0},
119 { SC_UNONAME_ISUSER, 0, cppu::UnoType<bool>::get(), beans::PropertyAttribute::READONLY, 0 },
120 { SC_UNONAME_KEEPFORM, 0, cppu::UnoType<bool>::get(), 0, 0},
121 { SC_UNO_LINKDISPBIT, 0, cppu::UnoType<awt::XBitmap>::get(), beans::PropertyAttribute::READONLY, 0 },
122 { SC_UNO_LINKDISPNAME, 0, cppu::UnoType<OUString>::get(), beans::PropertyAttribute::READONLY, 0 },
123 { SC_UNONAME_MOVCELLS, 0, cppu::UnoType<bool>::get(), 0, 0},
124 { SC_UNONAME_REFPERIOD, 0, cppu::UnoType<sal_Int32>::get(), 0, 0},
125 { SC_UNONAME_STRIPDAT, 0, cppu::UnoType<bool>::get(), 0, 0},
126 { SC_UNONAME_TOKENINDEX,0, cppu::UnoType<sal_Int32>::get(), beans::PropertyAttribute::READONLY, 0 },
127 { SC_UNONAME_USEFLTCRT,0, cppu::UnoType<bool>::get(), 0, 0},
128 { SC_UNONAME_TOTALSROW,0, cppu::UnoType<bool>::get(), 0, 0},
129 { SC_UNONAME_CONTHDR ,0, cppu::UnoType<bool>::get(), 0, 0},
131 return aDBRangePropertyMap_Impl;
134 SC_SIMPLE_SERVICE_INFO( ScConsolidationDescriptor, u"ScConsolidationDescriptor"_ustr, u"com.sun.star.sheet.ConsolidationDescriptor"_ustr )
135 SC_SIMPLE_SERVICE_INFO( ScDatabaseRangesObj, u"ScDatabaseRangesObj"_ustr, u"com.sun.star.sheet.DatabaseRanges"_ustr )
136 SC_SIMPLE_SERVICE_INFO( ScFilterDescriptorBase, u"ScFilterDescriptorBase"_ustr, u"com.sun.star.sheet.SheetFilterDescriptor"_ustr )
137 SC_SIMPLE_SERVICE_INFO( ScSubTotalDescriptorBase, u"ScSubTotalDescriptorBase"_ustr, u"com.sun.star.sheet.SubTotalDescriptor"_ustr )
138 SC_SIMPLE_SERVICE_INFO( ScSubTotalFieldObj, u"ScSubTotalFieldObj"_ustr, u"com.sun.star.sheet.SubTotalField"_ustr )
140 sheet::GeneralFunction ScDataUnoConversion::SubTotalToGeneral( ScSubTotalFunc eSubTotal )
142 sheet::GeneralFunction eGeneral;
143 switch (eSubTotal)
145 case SUBTOTAL_FUNC_NONE: eGeneral = sheet::GeneralFunction_NONE; break;
146 case SUBTOTAL_FUNC_AVE: eGeneral = sheet::GeneralFunction_AVERAGE; break;
147 case SUBTOTAL_FUNC_CNT: eGeneral = sheet::GeneralFunction_COUNTNUMS; break;
148 case SUBTOTAL_FUNC_CNT2: eGeneral = sheet::GeneralFunction_COUNT; break;
149 case SUBTOTAL_FUNC_MAX: eGeneral = sheet::GeneralFunction_MAX; break;
150 case SUBTOTAL_FUNC_MIN: eGeneral = sheet::GeneralFunction_MIN; break;
151 case SUBTOTAL_FUNC_PROD: eGeneral = sheet::GeneralFunction_PRODUCT; break;
152 case SUBTOTAL_FUNC_STD: eGeneral = sheet::GeneralFunction_STDEV; break;
153 case SUBTOTAL_FUNC_STDP: eGeneral = sheet::GeneralFunction_STDEVP; break;
154 case SUBTOTAL_FUNC_SUM: eGeneral = sheet::GeneralFunction_SUM; break;
155 case SUBTOTAL_FUNC_VAR: eGeneral = sheet::GeneralFunction_VAR; break;
156 case SUBTOTAL_FUNC_VARP: eGeneral = sheet::GeneralFunction_VARP; break;
157 default:
158 OSL_FAIL("SubTotalToGeneral: wrong enum");
159 eGeneral = sheet::GeneralFunction_NONE;
160 break;
162 return eGeneral;
165 void ScImportDescriptor::FillProperties( uno::Sequence<beans::PropertyValue>& rSeq, const ScImportParam& rParam )
167 OSL_ENSURE( rSeq.getLength() == GetPropertyCount(), "wrong Count" );
169 beans::PropertyValue* pArray = rSeq.getArray();
171 sheet::DataImportMode eMode = sheet::DataImportMode_NONE;
172 if ( rParam.bImport )
174 if ( rParam.bSql )
175 eMode = sheet::DataImportMode_SQL;
176 else if ( rParam.nType == ScDbQuery )
177 eMode = sheet::DataImportMode_QUERY;
178 else
179 eMode = sheet::DataImportMode_TABLE; // type always ScDbQuery or ScDbTable
182 svx::ODataAccessDescriptor aDescriptor;
183 aDescriptor.setDataSource(rParam.aDBName);
184 if (aDescriptor.has( svx::DataAccessDescriptorProperty::DataSource ))
186 pArray[0].Name = SC_UNONAME_DBNAME;
187 pArray[0].Value <<= rParam.aDBName;
189 else if (aDescriptor.has( svx::DataAccessDescriptorProperty::ConnectionResource ))
191 pArray[0].Name = SC_UNONAME_CONRES;
192 pArray[0].Value <<= rParam.aDBName;
195 pArray[1].Name = SC_UNONAME_SRCTYPE;
196 pArray[1].Value <<= eMode;
198 pArray[2].Name = SC_UNONAME_SRCOBJ;
199 pArray[2].Value <<= rParam.aStatement;
201 pArray[3].Name = SC_UNONAME_ISNATIVE;
202 pArray[3].Value <<= rParam.bNative;
205 void ScImportDescriptor::FillImportParam( ScImportParam& rParam, const uno::Sequence<beans::PropertyValue>& rSeq )
207 OUString aStrVal;
208 for (const beans::PropertyValue& rProp : rSeq)
210 OUString aPropName(rProp.Name);
212 if (aPropName == SC_UNONAME_ISNATIVE)
213 rParam.bNative = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value );
214 else if (aPropName == SC_UNONAME_DBNAME)
216 if ( rProp.Value >>= aStrVal )
217 rParam.aDBName = aStrVal;
219 else if (aPropName == SC_UNONAME_CONRES)
221 if ( rProp.Value >>= aStrVal )
222 rParam.aDBName = aStrVal;
224 else if (aPropName == SC_UNONAME_SRCOBJ)
226 if ( rProp.Value >>= aStrVal )
227 rParam.aStatement = aStrVal;
229 else if (aPropName == SC_UNONAME_SRCTYPE)
231 //! test for correct enum type?
232 sheet::DataImportMode eMode = static_cast<sheet::DataImportMode>(ScUnoHelpFunctions::GetEnumFromAny( rProp.Value ));
233 switch (eMode)
235 case sheet::DataImportMode_NONE:
236 rParam.bImport = false;
237 break;
238 case sheet::DataImportMode_SQL:
239 rParam.bImport = true;
240 rParam.bSql = true;
241 break;
242 case sheet::DataImportMode_TABLE:
243 rParam.bImport = true;
244 rParam.bSql = false;
245 rParam.nType = ScDbTable;
246 break;
247 case sheet::DataImportMode_QUERY:
248 rParam.bImport = true;
249 rParam.bSql = false;
250 rParam.nType = ScDbQuery;
251 break;
252 default:
253 OSL_FAIL("wrong mode");
254 rParam.bImport = false;
260 void ScSortDescriptor::FillProperties( uno::Sequence<beans::PropertyValue>& rSeq, const ScSortParam& rParam )
262 OSL_ENSURE( rSeq.getLength() == GetPropertyCount(), "wrong count" );
264 beans::PropertyValue* pArray = rSeq.getArray();
266 // gather Uno values together
268 table::CellAddress aOutPos;
269 aOutPos.Sheet = rParam.nDestTab;
270 aOutPos.Column = rParam.nDestCol;
271 aOutPos.Row = rParam.nDestRow;
273 sal_uInt16 nSortCount = 0;
274 while ( nSortCount < rParam.GetSortKeyCount() && rParam.maKeyState[nSortCount].bDoSort )
275 ++nSortCount;
277 uno::Sequence<table::TableSortField> aFields(nSortCount);
278 if (nSortCount)
280 table::TableSortField* pFieldArray = aFields.getArray();
281 for (sal_uInt16 i=0; i<nSortCount; i++)
283 pFieldArray[i].Field = rParam.maKeyState[i].nField;
284 pFieldArray[i].IsAscending = rParam.maKeyState[i].bAscending;
285 pFieldArray[i].FieldType = table::TableSortFieldType_AUTOMATIC; // always automatic
286 pFieldArray[i].IsCaseSensitive = rParam.bCaseSens;
287 pFieldArray[i].CollatorLocale = rParam.aCollatorLocale;
288 pFieldArray[i].CollatorAlgorithm = rParam.aCollatorAlgorithm;
292 // fill the sequence
294 pArray[0].Name = SC_UNONAME_ISSORTCOLUMNS;
295 pArray[0].Value <<= !rParam.bByRow;
297 pArray[1].Name = SC_UNONAME_CONTHDR;
298 pArray[1].Value <<= rParam.bHasHeader;
300 pArray[2].Name = SC_UNONAME_MAXFLD;
301 pArray[2].Value <<= static_cast<sal_Int32>( rParam.GetSortKeyCount() );
303 pArray[3].Name = SC_UNONAME_SORTFLD;
304 pArray[3].Value <<= aFields;
306 pArray[4].Name = SC_UNONAME_BINDFMT;
307 pArray[4].Value <<= rParam.aDataAreaExtras.mbCellFormats;
309 pArray[5].Name = SC_UNONAME_COPYOUT;
310 pArray[5].Value <<= !rParam.bInplace;
312 pArray[6].Name = SC_UNONAME_OUTPOS;
313 pArray[6].Value <<= aOutPos;
315 pArray[7].Name = SC_UNONAME_ISULIST;
316 pArray[7].Value <<= rParam.bUserDef;
318 pArray[8].Name = SC_UNONAME_UINDEX;
319 pArray[8].Value <<= static_cast<sal_Int32>( rParam.nUserIndex );
322 void ScSortDescriptor::FillSortParam( ScSortParam& rParam, const uno::Sequence<beans::PropertyValue>& rSeq )
324 sal_Int32 nSortSize = static_cast<sal_Int32>(rParam.GetSortKeyCount());
326 for (const beans::PropertyValue& rProp : rSeq)
328 OUString aPropName(rProp.Name);
330 if (aPropName == SC_UNONAME_ORIENT)
332 //! test for correct enum type?
333 table::TableOrientation eOrient = static_cast<table::TableOrientation>(ScUnoHelpFunctions::GetEnumFromAny( rProp.Value ));
334 rParam.bByRow = ( eOrient != table::TableOrientation_COLUMNS );
336 else if (aPropName == SC_UNONAME_ISSORTCOLUMNS)
338 rParam.bByRow = !::cppu::any2bool(rProp.Value);
340 else if (aPropName == SC_UNONAME_CONTHDR)
341 rParam.bHasHeader = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value );
342 else if (aPropName == SC_UNONAME_MAXFLD)
344 sal_Int32 nVal;
345 if ( (rProp.Value >>= nVal) && nVal > nSortSize )
347 //! specify exceptions
348 //! throw lang::IllegalArgumentException();
351 else if (aPropName == SC_UNONAME_SORTFLD)
353 uno::Sequence<util::SortField> aSeq;
354 uno::Sequence<table::TableSortField> aNewSeq;
355 if ( rProp.Value >>= aSeq )
357 sal_Int32 nCount = aSeq.getLength();
358 sal_Int32 i;
359 if ( nCount > static_cast<sal_Int32>( rParam.GetSortKeyCount() ) )
361 // tdf#105301 - increase the size of the sorting keys
362 nSortSize = nCount;
363 rParam.maKeyState.resize(nCount);
365 const util::SortField* pFieldArray = aSeq.getConstArray();
366 for (i=0; i<nCount; i++)
368 rParam.maKeyState[i].nField = static_cast<SCCOLROW>( pFieldArray[i].Field );
369 rParam.maKeyState[i].bAscending = pFieldArray[i].SortAscending;
371 // FieldType is ignored
372 rParam.maKeyState[i].bDoSort = true;
374 for (i=nCount; i<nSortSize; i++)
375 rParam.maKeyState[i].bDoSort = false;
377 else if ( rProp.Value >>= aNewSeq )
379 sal_Int32 nCount = aNewSeq.getLength();
380 sal_Int32 i;
381 if ( nCount > nSortSize )
383 nCount = nSortSize;
384 rParam.maKeyState.resize(nCount);
386 const table::TableSortField* pFieldArray = aNewSeq.getConstArray();
387 for (i=0; i<nCount; i++)
389 rParam.maKeyState[i].nField = static_cast<SCCOLROW>( pFieldArray[i].Field );
390 rParam.maKeyState[i].bAscending = pFieldArray[i].IsAscending;
392 // only one is possible, sometime we should make it possible to have different for every entry
393 rParam.bCaseSens = pFieldArray[i].IsCaseSensitive;
394 rParam.aCollatorLocale = pFieldArray[i].CollatorLocale;
395 rParam.aCollatorAlgorithm = pFieldArray[i].CollatorAlgorithm;
397 // FieldType is ignored
398 rParam.maKeyState[i].bDoSort = true;
400 for (i=nCount; i<nSortSize; i++)
401 rParam.maKeyState[i].bDoSort = false;
404 else if (aPropName == SC_UNONAME_ISCASE)
406 rParam.bCaseSens = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value );
408 else if (aPropName == SC_UNONAME_BINDFMT)
409 rParam.aDataAreaExtras.mbCellFormats = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value );
410 else if (aPropName == SC_UNONAME_COPYOUT)
411 rParam.bInplace = !ScUnoHelpFunctions::GetBoolFromAny( rProp.Value );
412 else if (aPropName == SC_UNONAME_OUTPOS)
414 table::CellAddress aAddress;
415 if ( rProp.Value >>= aAddress )
417 rParam.nDestTab = aAddress.Sheet;
418 rParam.nDestCol = static_cast<SCCOL>(aAddress.Column);
419 rParam.nDestRow = static_cast<SCROW>(aAddress.Row);
422 else if (aPropName == SC_UNONAME_ISULIST)
423 rParam.bUserDef = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value );
424 else if (aPropName == SC_UNONAME_UINDEX)
426 sal_Int32 nVal = 0;
427 if ( rProp.Value >>= nVal )
428 rParam.nUserIndex = static_cast<sal_uInt16>(nVal);
430 else if (aPropName == SC_UNONAME_COLLLOC)
432 rProp.Value >>= rParam.aCollatorLocale;
434 else if (aPropName == SC_UNONAME_COLLALG)
436 OUString sStr;
437 if ( rProp.Value >>= sStr )
438 rParam.aCollatorAlgorithm = sStr;
443 ScSubTotalFieldObj::ScSubTotalFieldObj( ScSubTotalDescriptorBase* pDesc, sal_uInt16 nP ) :
444 xParent( pDesc ),
445 nPos( nP )
447 OSL_ENSURE(pDesc, "ScSubTotalFieldObj: Parent is 0");
450 ScSubTotalFieldObj::~ScSubTotalFieldObj()
454 // XSubTotalField
456 sal_Int32 SAL_CALL ScSubTotalFieldObj::getGroupColumn()
458 SolarMutexGuard aGuard;
459 ScSubTotalParam aParam;
460 xParent->GetData(aParam);
462 return aParam.aGroups[nPos].nField;
465 void SAL_CALL ScSubTotalFieldObj::setGroupColumn( sal_Int32 nGroupColumn )
467 SolarMutexGuard aGuard;
468 ScSubTotalParam aParam;
469 xParent->GetData(aParam);
471 aParam.aGroups[nPos].nField = static_cast<SCCOL>(nGroupColumn);
473 xParent->PutData(aParam);
476 uno::Sequence<sheet::SubTotalColumn> SAL_CALL ScSubTotalFieldObj::getSubTotalColumns()
478 SolarMutexGuard aGuard;
479 ScSubTotalParam aParam;
480 xParent->GetData(aParam);
482 SCCOL nCount = aParam.aGroups[nPos].nSubTotals;
483 uno::Sequence<sheet::SubTotalColumn> aSeq(nCount);
484 sheet::SubTotalColumn* pAry = aSeq.getArray();
485 for (SCCOL i=0; i<nCount; i++)
487 pAry[i].Column = aParam.aGroups[nPos].col(i);
488 pAry[i].Function = ScDataUnoConversion::SubTotalToGeneral(aParam.aGroups[nPos].func(i));
490 return aSeq;
493 void SAL_CALL ScSubTotalFieldObj::setSubTotalColumns(
494 const uno::Sequence<sheet::SubTotalColumn>& aSubTotalColumns )
496 SolarMutexGuard aGuard;
497 ScSubTotalParam aParam;
498 xParent->GetData(aParam);
500 if (aSubTotalColumns.getLength() <= SCCOL_MAX)
501 aParam.aGroups[nPos].SetSubtotals(aSubTotalColumns);
502 //! otherwise exception or so? (too many columns)
504 xParent->PutData(aParam);
507 ScSubTotalDescriptorBase::ScSubTotalDescriptorBase() :
508 aPropSet( lcl_GetSubTotalPropertyMap() )
512 ScSubTotalDescriptorBase::~ScSubTotalDescriptorBase()
516 // XSubTotalDescriptor
518 rtl::Reference<ScSubTotalFieldObj> ScSubTotalDescriptorBase::GetObjectByIndex_Impl(sal_uInt16 nIndex)
520 if ( nIndex < getCount() )
521 return new ScSubTotalFieldObj( this, nIndex );
522 return nullptr;
525 void SAL_CALL ScSubTotalDescriptorBase::clear()
527 SolarMutexGuard aGuard;
528 ScSubTotalParam aParam;
529 GetData(aParam);
531 for (auto& group : aParam.aGroups)
532 group.bActive = false;
534 //! notify the field objects???
536 PutData(aParam);
539 void SAL_CALL ScSubTotalDescriptorBase::addNew(
540 const uno::Sequence<sheet::SubTotalColumn>& aSubTotalColumns,
541 sal_Int32 nGroupColumn )
543 SolarMutexGuard aGuard;
544 ScSubTotalParam aParam;
545 GetData(aParam);
547 sal_uInt16 nPos = 0;
548 while (nPos < MAXSUBTOTAL && aParam.aGroups[nPos].bActive)
549 ++nPos;
551 if (nPos >= MAXSUBTOTAL || aSubTotalColumns.getLength() > SCCOL_MAX)
552 // too many fields / columns
553 throw uno::RuntimeException(); // no other exceptions specified
554 auto& group = aParam.aGroups[nPos];
556 group.bActive = true;
557 group.nField = static_cast<SCCOL>(nGroupColumn);
558 group.SetSubtotals(aSubTotalColumns);
560 PutData(aParam);
563 // flags/settings as properties
565 // XEnumerationAccess
567 uno::Reference<container::XEnumeration> SAL_CALL ScSubTotalDescriptorBase::createEnumeration()
569 SolarMutexGuard aGuard;
570 return new ScIndexEnumeration(this, u"com.sun.star.sheet.SubTotalFieldsEnumeration"_ustr);
573 // XIndexAccess
575 sal_Int32 SAL_CALL ScSubTotalDescriptorBase::getCount()
577 SolarMutexGuard aGuard;
578 ScSubTotalParam aParam;
579 GetData(aParam);
581 sal_uInt16 nCount = 0;
582 while ( nCount < MAXSUBTOTAL && aParam.aGroups[nCount].bActive )
583 ++nCount;
584 return nCount;
587 uno::Any SAL_CALL ScSubTotalDescriptorBase::getByIndex( sal_Int32 nIndex )
589 SolarMutexGuard aGuard;
590 uno::Reference<sheet::XSubTotalField> xField(GetObjectByIndex_Impl(static_cast<sal_uInt16>(nIndex)));
591 if (!xField.is())
592 throw lang::IndexOutOfBoundsException();
594 return uno::Any(xField);
597 uno::Type SAL_CALL ScSubTotalDescriptorBase::getElementType()
599 return cppu::UnoType<sheet::XSubTotalField>::get();
602 sal_Bool SAL_CALL ScSubTotalDescriptorBase::hasElements()
604 SolarMutexGuard aGuard;
605 return ( getCount() != 0 );
608 // XPropertySet
610 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScSubTotalDescriptorBase::getPropertySetInfo()
612 SolarMutexGuard aGuard;
613 static uno::Reference<beans::XPropertySetInfo> aRef(
614 new SfxItemPropertySetInfo( aPropSet.getPropertyMap() ));
615 return aRef;
618 void SAL_CALL ScSubTotalDescriptorBase::setPropertyValue(
619 const OUString& aPropertyName, const uno::Any& aValue )
621 SolarMutexGuard aGuard;
622 ScSubTotalParam aParam;
623 GetData(aParam);
625 // some old property names are for 5.2 compatibility
627 if (aPropertyName == SC_UNONAME_CASE || aPropertyName == SC_UNONAME_ISCASE )
628 aParam.bCaseSens = ScUnoHelpFunctions::GetBoolFromAny( aValue );
629 else if (aPropertyName == SC_UNONAME_FORMATS || aPropertyName == SC_UNONAME_BINDFMT )
630 aParam.bIncludePattern = ScUnoHelpFunctions::GetBoolFromAny( aValue );
631 else if (aPropertyName == SC_UNONAME_ENABSORT )
632 aParam.bDoSort = ScUnoHelpFunctions::GetBoolFromAny( aValue );
633 else if (aPropertyName == SC_UNONAME_SORTASC )
634 aParam.bAscending = ScUnoHelpFunctions::GetBoolFromAny( aValue );
635 else if (aPropertyName == SC_UNONAME_INSBRK )
636 aParam.bPagebreak = ScUnoHelpFunctions::GetBoolFromAny( aValue );
637 else if (aPropertyName == SC_UNONAME_ULIST || aPropertyName == SC_UNONAME_ENUSLIST )
638 aParam.bUserDef = ScUnoHelpFunctions::GetBoolFromAny( aValue );
639 else if (aPropertyName == SC_UNONAME_UINDEX || aPropertyName == SC_UNONAME_USINDEX )
641 sal_Int32 nVal = 0;
642 if ( aValue >>= nVal )
643 aParam.nUserIndex = static_cast<sal_uInt16>(nVal);
645 else if (aPropertyName == SC_UNONAME_MAXFLD )
647 sal_Int32 nVal = 0;
648 if ( (aValue >>= nVal) && nVal > sal::static_int_cast<sal_Int32>(MAXSUBTOTAL) )
650 throw lang::IllegalArgumentException();
654 PutData(aParam);
657 uno::Any SAL_CALL ScSubTotalDescriptorBase::getPropertyValue( const OUString& aPropertyName )
659 SolarMutexGuard aGuard;
660 ScSubTotalParam aParam;
661 GetData(aParam);
663 uno::Any aRet;
665 // some old property names are for 5.2 compatibility
667 if (aPropertyName == SC_UNONAME_CASE || aPropertyName == SC_UNONAME_ISCASE )
668 aRet <<= aParam.bCaseSens;
669 else if (aPropertyName == SC_UNONAME_FORMATS || aPropertyName == SC_UNONAME_BINDFMT )
670 aRet <<= aParam.bIncludePattern;
671 else if (aPropertyName == SC_UNONAME_ENABSORT )
672 aRet <<= aParam.bDoSort;
673 else if (aPropertyName == SC_UNONAME_SORTASC )
674 aRet <<= aParam.bAscending;
675 else if (aPropertyName == SC_UNONAME_INSBRK )
676 aRet <<= aParam.bPagebreak;
677 else if (aPropertyName == SC_UNONAME_ULIST || aPropertyName == SC_UNONAME_ENUSLIST )
678 aRet <<= aParam.bUserDef;
679 else if (aPropertyName == SC_UNONAME_UINDEX || aPropertyName == SC_UNONAME_USINDEX )
680 aRet <<= static_cast<sal_Int32>(aParam.nUserIndex);
681 else if (aPropertyName == SC_UNONAME_MAXFLD )
682 aRet <<= sal_Int32(MAXSUBTOTAL);
684 return aRet;
687 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScSubTotalDescriptorBase )
689 ScSubTotalDescriptor::ScSubTotalDescriptor()
693 ScSubTotalDescriptor::~ScSubTotalDescriptor()
697 void ScSubTotalDescriptor::GetData( ScSubTotalParam& rParam ) const
699 rParam = aStoredParam; // query for interface
702 void ScSubTotalDescriptor::PutData( const ScSubTotalParam& rParam )
704 aStoredParam = rParam; // set by the interface
707 void ScSubTotalDescriptor::SetParam( const ScSubTotalParam& rNew )
709 aStoredParam = rNew; // set from outside
712 ScRangeSubTotalDescriptor::ScRangeSubTotalDescriptor(ScDatabaseRangeObj* pPar) :
713 mxParent(pPar)
717 ScRangeSubTotalDescriptor::~ScRangeSubTotalDescriptor()
721 void ScRangeSubTotalDescriptor::GetData( ScSubTotalParam& rParam ) const
723 if (mxParent.is())
724 mxParent->GetSubTotalParam( rParam );
727 void ScRangeSubTotalDescriptor::PutData( const ScSubTotalParam& rParam )
729 if (mxParent.is())
730 mxParent->SetSubTotalParam( rParam );
733 ScConsolidationDescriptor::ScConsolidationDescriptor()
737 ScConsolidationDescriptor::~ScConsolidationDescriptor()
741 void ScConsolidationDescriptor::SetParam( const ScConsolidateParam& rNew )
743 aParam = rNew;
746 // XConsolidationDescriptor
748 sheet::GeneralFunction SAL_CALL ScConsolidationDescriptor::getFunction()
750 SolarMutexGuard aGuard;
751 return ScDataUnoConversion::SubTotalToGeneral(aParam.eFunction);
754 void SAL_CALL ScConsolidationDescriptor::setFunction( sheet::GeneralFunction nFunction )
756 SolarMutexGuard aGuard;
757 aParam.eFunction = ScDPUtil::toSubTotalFunc(static_cast<ScGeneralFunction>(nFunction));
760 uno::Sequence<table::CellRangeAddress> SAL_CALL ScConsolidationDescriptor::getSources()
762 SolarMutexGuard aGuard;
763 sal_uInt16 nCount = aParam.nDataAreaCount;
764 if (!aParam.pDataAreas)
765 nCount = 0;
766 table::CellRangeAddress aRange;
767 uno::Sequence<table::CellRangeAddress> aSeq(nCount);
768 table::CellRangeAddress* pAry = aSeq.getArray();
769 for (sal_uInt16 i=0; i<nCount; i++)
771 ScArea const & rArea = aParam.pDataAreas[i];
772 aRange.Sheet = rArea.nTab;
773 aRange.StartColumn = rArea.nColStart;
774 aRange.StartRow = rArea.nRowStart;
775 aRange.EndColumn = rArea.nColEnd;
776 aRange.EndRow = rArea.nRowEnd;
777 pAry[i] = aRange;
779 return aSeq;
782 void SAL_CALL ScConsolidationDescriptor::setSources(
783 const uno::Sequence<table::CellRangeAddress>& aSources )
785 SolarMutexGuard aGuard;
786 sal_uInt16 nCount = static_cast<sal_uInt16>(aSources.getLength());
787 if (nCount)
789 const table::CellRangeAddress* pAry = aSources.getConstArray();
790 std::unique_ptr<ScArea[]> pNew(new ScArea[nCount]);
791 sal_uInt16 i;
792 for (i=0; i<nCount; i++)
793 pNew[i] = ScArea( pAry[i].Sheet,
794 static_cast<SCCOL>(pAry[i].StartColumn), pAry[i].StartRow,
795 static_cast<SCCOL>(pAry[i].EndColumn), pAry[i].EndRow );
797 aParam.SetAreas( std::move(pNew), nCount ); // copy everything
799 else
800 aParam.ClearDataAreas();
803 table::CellAddress SAL_CALL ScConsolidationDescriptor::getStartOutputPosition()
805 SolarMutexGuard aGuard;
806 table::CellAddress aPos;
807 aPos.Column = aParam.nCol;
808 aPos.Row = aParam.nRow;
809 aPos.Sheet = aParam.nTab;
810 return aPos;
813 void SAL_CALL ScConsolidationDescriptor::setStartOutputPosition(
814 const table::CellAddress& aStartOutputPosition )
816 SolarMutexGuard aGuard;
817 aParam.nCol = static_cast<SCCOL>(aStartOutputPosition.Column);
818 aParam.nRow = static_cast<SCROW>(aStartOutputPosition.Row);
819 aParam.nTab = aStartOutputPosition.Sheet;
822 sal_Bool SAL_CALL ScConsolidationDescriptor::getUseColumnHeaders()
824 SolarMutexGuard aGuard;
825 return aParam.bByCol;
828 void SAL_CALL ScConsolidationDescriptor::setUseColumnHeaders( sal_Bool bUseColumnHeaders )
830 SolarMutexGuard aGuard;
831 aParam.bByCol = bUseColumnHeaders;
834 sal_Bool SAL_CALL ScConsolidationDescriptor::getUseRowHeaders()
836 SolarMutexGuard aGuard;
837 return aParam.bByRow;
840 void SAL_CALL ScConsolidationDescriptor::setUseRowHeaders( sal_Bool bUseRowHeaders )
842 SolarMutexGuard aGuard;
843 aParam.bByRow = bUseRowHeaders;
846 sal_Bool SAL_CALL ScConsolidationDescriptor::getInsertLinks()
848 SolarMutexGuard aGuard;
849 return aParam.bReferenceData;
852 void SAL_CALL ScConsolidationDescriptor::setInsertLinks( sal_Bool bInsertLinks )
854 SolarMutexGuard aGuard;
855 aParam.bReferenceData = bInsertLinks;
858 ScFilterDescriptorBase::ScFilterDescriptorBase(ScDocShell* pDocShell) :
859 aPropSet( lcl_GetFilterPropertyMap() ),
860 pDocSh(pDocShell)
862 if (pDocSh)
863 pDocSh->GetDocument().AddUnoObject(*this);
866 ScFilterDescriptorBase::~ScFilterDescriptorBase()
868 SolarMutexGuard g;
870 if (pDocSh)
871 pDocSh->GetDocument().RemoveUnoObject(*this);
874 void ScFilterDescriptorBase::Notify( SfxBroadcaster&, const SfxHint& rHint )
876 if ( rHint.GetId() == SfxHintId::Dying )
878 pDocSh = nullptr; // invalid
882 // XSheetFilterDescriptor and XSheetFilterDescriptor2
884 uno::Sequence<sheet::TableFilterField> SAL_CALL ScFilterDescriptorBase::getFilterFields()
886 SolarMutexGuard aGuard;
887 ScQueryParam aParam;
888 GetData(aParam);
890 SCSIZE nEntries = aParam.GetEntryCount(); // allocated entries in Param
891 SCSIZE nCount = 0; // active
892 while ( nCount < nEntries &&
893 aParam.GetEntry(nCount).bDoQuery )
894 ++nCount;
896 sheet::TableFilterField aField;
897 uno::Sequence<sheet::TableFilterField> aSeq(static_cast<sal_Int32>(nCount));
898 sheet::TableFilterField* pAry = aSeq.getArray();
899 for (SCSIZE i=0; i<nCount; i++)
901 const ScQueryEntry& rEntry = aParam.GetEntry(i);
902 if (rEntry.GetQueryItems().empty())
903 continue;
905 const ScQueryEntry::Item& rItem = rEntry.GetQueryItems().front();
907 aField.Connection = (rEntry.eConnect == SC_AND) ? sheet::FilterConnection_AND :
908 sheet::FilterConnection_OR;
909 aField.Field = rEntry.nField;
910 aField.IsNumeric = rItem.meType != ScQueryEntry::ByString;
911 aField.StringValue = rItem.maString.getString();
912 aField.NumericValue = rItem.mfVal;
914 switch (rEntry.eOp) // ScQueryOp
916 case SC_EQUAL:
918 aField.Operator = sheet::FilterOperator_EQUAL;
919 if (rEntry.IsQueryByEmpty())
921 aField.Operator = sheet::FilterOperator_EMPTY;
922 aField.NumericValue = 0;
924 else if (rEntry.IsQueryByNonEmpty())
926 aField.Operator = sheet::FilterOperator_NOT_EMPTY;
927 aField.NumericValue = 0;
930 break;
931 case SC_LESS: aField.Operator = sheet::FilterOperator_LESS; break;
932 case SC_GREATER: aField.Operator = sheet::FilterOperator_GREATER; break;
933 case SC_LESS_EQUAL: aField.Operator = sheet::FilterOperator_LESS_EQUAL; break;
934 case SC_GREATER_EQUAL: aField.Operator = sheet::FilterOperator_GREATER_EQUAL; break;
935 case SC_NOT_EQUAL: aField.Operator = sheet::FilterOperator_NOT_EQUAL; break;
936 case SC_TOPVAL: aField.Operator = sheet::FilterOperator_TOP_VALUES; break;
937 case SC_BOTVAL: aField.Operator = sheet::FilterOperator_BOTTOM_VALUES; break;
938 case SC_TOPPERC: aField.Operator = sheet::FilterOperator_TOP_PERCENT; break;
939 case SC_BOTPERC: aField.Operator = sheet::FilterOperator_BOTTOM_PERCENT; break;
940 default:
941 OSL_FAIL("wrong filter enum");
942 aField.Operator = sheet::FilterOperator_EMPTY;
944 pAry[i] = aField;
946 return aSeq;
949 namespace {
951 template<typename T>
952 void convertQueryEntryToUno(const ScQueryEntry& rEntry, T& rField)
954 rField.Connection = (rEntry.eConnect == SC_AND) ? sheet::FilterConnection_AND : sheet::FilterConnection_OR;
955 rField.Field = rEntry.nField;
957 switch (rEntry.eOp) // ScQueryOp
959 case SC_EQUAL: rField.Operator = sheet::FilterOperator2::EQUAL; break;
960 case SC_LESS: rField.Operator = sheet::FilterOperator2::LESS; break;
961 case SC_GREATER: rField.Operator = sheet::FilterOperator2::GREATER; break;
962 case SC_LESS_EQUAL: rField.Operator = sheet::FilterOperator2::LESS_EQUAL; break;
963 case SC_GREATER_EQUAL: rField.Operator = sheet::FilterOperator2::GREATER_EQUAL; break;
964 case SC_NOT_EQUAL: rField.Operator = sheet::FilterOperator2::NOT_EQUAL; break;
965 case SC_TOPVAL: rField.Operator = sheet::FilterOperator2::TOP_VALUES; break;
966 case SC_BOTVAL: rField.Operator = sheet::FilterOperator2::BOTTOM_VALUES; break;
967 case SC_TOPPERC: rField.Operator = sheet::FilterOperator2::TOP_PERCENT; break;
968 case SC_BOTPERC: rField.Operator = sheet::FilterOperator2::BOTTOM_PERCENT; break;
969 case SC_CONTAINS: rField.Operator = sheet::FilterOperator2::CONTAINS; break;
970 case SC_DOES_NOT_CONTAIN: rField.Operator = sheet::FilterOperator2::DOES_NOT_CONTAIN; break;
971 case SC_BEGINS_WITH: rField.Operator = sheet::FilterOperator2::BEGINS_WITH; break;
972 case SC_DOES_NOT_BEGIN_WITH: rField.Operator = sheet::FilterOperator2::DOES_NOT_BEGIN_WITH; break;
973 case SC_ENDS_WITH: rField.Operator = sheet::FilterOperator2::ENDS_WITH; break;
974 case SC_DOES_NOT_END_WITH: rField.Operator = sheet::FilterOperator2::DOES_NOT_END_WITH; break;
975 default:
976 OSL_FAIL("Unknown filter operator value.");
977 rField.Operator = sheet::FilterOperator2::EMPTY;
981 template<typename T>
982 void convertUnoToQueryEntry(const T& rField, ScQueryEntry& rEntry)
984 rEntry.bDoQuery = true;
985 rEntry.eConnect = (rField.Connection == sheet::FilterConnection_AND) ? SC_AND : SC_OR;
986 rEntry.nField = rField.Field;
988 switch (rField.Operator) // FilterOperator
990 case sheet::FilterOperator2::EQUAL: rEntry.eOp = SC_EQUAL; break;
991 case sheet::FilterOperator2::LESS: rEntry.eOp = SC_LESS; break;
992 case sheet::FilterOperator2::GREATER: rEntry.eOp = SC_GREATER; break;
993 case sheet::FilterOperator2::LESS_EQUAL: rEntry.eOp = SC_LESS_EQUAL; break;
994 case sheet::FilterOperator2::GREATER_EQUAL: rEntry.eOp = SC_GREATER_EQUAL; break;
995 case sheet::FilterOperator2::NOT_EQUAL: rEntry.eOp = SC_NOT_EQUAL; break;
996 case sheet::FilterOperator2::TOP_VALUES: rEntry.eOp = SC_TOPVAL; break;
997 case sheet::FilterOperator2::BOTTOM_VALUES: rEntry.eOp = SC_BOTVAL; break;
998 case sheet::FilterOperator2::TOP_PERCENT: rEntry.eOp = SC_TOPPERC; break;
999 case sheet::FilterOperator2::BOTTOM_PERCENT: rEntry.eOp = SC_BOTPERC; break;
1000 case sheet::FilterOperator2::CONTAINS: rEntry.eOp = SC_CONTAINS; break;
1001 case sheet::FilterOperator2::DOES_NOT_CONTAIN: rEntry.eOp = SC_DOES_NOT_CONTAIN; break;
1002 case sheet::FilterOperator2::BEGINS_WITH: rEntry.eOp = SC_BEGINS_WITH; break;
1003 case sheet::FilterOperator2::DOES_NOT_BEGIN_WITH: rEntry.eOp = SC_DOES_NOT_BEGIN_WITH;break;
1004 case sheet::FilterOperator2::ENDS_WITH: rEntry.eOp = SC_ENDS_WITH; break;
1005 case sheet::FilterOperator2::DOES_NOT_END_WITH: rEntry.eOp = SC_DOES_NOT_END_WITH; break;
1006 case sheet::FilterOperator2::EMPTY:
1007 rEntry.SetQueryByEmpty();
1008 break;
1009 case sheet::FilterOperator2::NOT_EMPTY:
1010 rEntry.SetQueryByNonEmpty();
1011 break;
1012 default:
1013 OSL_FAIL("Unknown filter operator type.");
1014 rEntry.eOp = SC_EQUAL;
1018 void fillQueryParam(
1019 ScQueryParam& rParam, ScDocument* pDoc,
1020 const uno::Sequence<sheet::TableFilterField2>& aFilterFields)
1022 size_t nCount = static_cast<size_t>(aFilterFields.getLength());
1023 rParam.Resize(nCount);
1025 const sheet::TableFilterField2* pAry = aFilterFields.getConstArray();
1026 svl::SharedStringPool& rPool = pDoc->GetSharedStringPool();
1027 for (size_t i = 0; i < nCount; ++i)
1029 ScQueryEntry& rEntry = rParam.GetEntry(i);
1030 convertUnoToQueryEntry(pAry[i], rEntry);
1032 if (pAry[i].Operator != sheet::FilterOperator2::EMPTY && pAry[i].Operator != sheet::FilterOperator2::NOT_EMPTY)
1034 ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems();
1035 rItems.resize(1);
1036 ScQueryEntry::Item& rItem = rItems.front();
1037 rItem.meType = pAry[i].IsNumeric ? ScQueryEntry::ByValue : ScQueryEntry::ByString;
1038 rItem.mfVal = pAry[i].NumericValue;
1039 rItem.maString = rPool.intern(pAry[i].StringValue);
1041 if (rItem.meType == ScQueryEntry::ByValue)
1043 OUString aStr = pDoc->GetFormatTable()->GetInputLineString(rItem.mfVal, 0);
1044 rItem.maString = rPool.intern(aStr);
1049 size_t nParamCount = rParam.GetEntryCount(); // if below eight Param isn't resized
1050 for (size_t i = nCount; i < nParamCount; ++i)
1051 rParam.GetEntry(i).bDoQuery = false; // reset surplus fields
1054 void fillQueryParam(
1055 ScQueryParam& rParam, ScDocument* pDoc,
1056 const uno::Sequence<sheet::TableFilterField3>& aFilterFields)
1058 size_t nCount = static_cast<size_t>(aFilterFields.getLength());
1059 rParam.Resize(nCount);
1061 svl::SharedStringPool& rPool = pDoc->GetSharedStringPool();
1062 const sheet::TableFilterField3* pAry = aFilterFields.getConstArray();
1063 for (size_t i = 0; i < nCount; ++i)
1065 ScQueryEntry& rEntry = rParam.GetEntry(i);
1066 convertUnoToQueryEntry(pAry[i], rEntry);
1068 if (pAry[i].Operator != sheet::FilterOperator2::EMPTY && pAry[i].Operator != sheet::FilterOperator2::NOT_EMPTY)
1070 ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems();
1071 rItems.clear();
1072 const uno::Sequence<sheet::FilterFieldValue>& rVals = pAry[i].Values;
1073 for (const auto& rVal : rVals)
1075 ScQueryEntry::Item aItem;
1076 switch (rVal.FilterType)
1078 case FilterFieldType::NUMERIC:
1079 aItem.meType = ScQueryEntry::ByValue;
1080 break;
1081 case FilterFieldType::STRING:
1082 aItem.meType = ScQueryEntry::ByString;
1083 break;
1084 case FilterFieldType::DATE:
1085 aItem.meType = ScQueryEntry::ByDate;
1086 break;
1087 case FilterFieldType::TEXT_COLOR:
1088 aItem.meType = ScQueryEntry::ByTextColor;
1089 break;
1090 case FilterFieldType::BACKGROUND_COLOR:
1091 aItem.meType = ScQueryEntry::ByBackgroundColor;
1092 break;
1094 aItem.mfVal = rVal.NumericValue;
1095 aItem.maString = rPool.intern(rVal.StringValue);
1097 if (aItem.meType == ScQueryEntry::ByValue)
1099 OUString aStr = pDoc->GetFormatTable()->GetInputLineString(aItem.mfVal, 0);
1100 aItem.maString = rPool.intern(aStr);
1102 else if (aItem.meType == ScQueryEntry::ByTextColor
1103 || aItem.meType == ScQueryEntry::ByBackgroundColor)
1105 aItem.maColor = Color(ColorTransparency, rVal.ColorValue);
1108 // filter all dates starting with the given date filter YYYY or YYYY-MM and filter all datetimes
1109 // starting with the given datetime filter YYYY-MM-DD, YYYY-MM-DD HH, or YYYY-MM-DD HH:MM
1110 if( aItem.meType == ScQueryEntry::ByDate && aItem.maString.getLength() < 19 )
1112 ScFilterEntries aFilterEntries;
1113 pDoc->GetFilterEntries(rEntry.nField, rParam.nRow1, rParam.nTab, aFilterEntries);
1114 for( const auto& rFilter : aFilterEntries )
1116 if( rFilter.GetString().startsWith(rVal.StringValue) )
1118 aItem.maString = rPool.intern(rFilter.GetString());
1119 rItems.push_back(aItem);
1123 else
1125 rItems.push_back(aItem);
1131 size_t nParamCount = rParam.GetEntryCount(); // if below eight Param isn't resized
1132 for (size_t i = nCount; i < nParamCount; ++i)
1133 rParam.GetEntry(i).bDoQuery = false; // reset surplus fields
1138 uno::Sequence<sheet::TableFilterField2> SAL_CALL ScFilterDescriptorBase::getFilterFields2()
1140 SolarMutexGuard aGuard;
1141 ScQueryParam aParam;
1142 GetData(aParam);
1144 SCSIZE nEntries = aParam.GetEntryCount(); // allocated entries in Param
1145 SCSIZE nCount = 0; // active
1146 while ( nCount < nEntries &&
1147 aParam.GetEntry(nCount).bDoQuery )
1148 ++nCount;
1150 sheet::TableFilterField2 aField;
1151 uno::Sequence<sheet::TableFilterField2> aSeq(static_cast<sal_Int32>(nCount));
1152 sheet::TableFilterField2* pAry = aSeq.getArray();
1153 for (SCSIZE i=0; i<nCount; i++)
1155 const ScQueryEntry& rEntry = aParam.GetEntry(i);
1156 convertQueryEntryToUno(rEntry, aField);
1158 bool bByEmpty = false;
1159 if (aField.Operator == sheet::FilterOperator2::EQUAL)
1161 if (rEntry.IsQueryByEmpty())
1163 aField.Operator = sheet::FilterOperator2::EMPTY;
1164 aField.NumericValue = 0;
1165 bByEmpty = true;
1167 else if (rEntry.IsQueryByNonEmpty())
1169 aField.Operator = sheet::FilterOperator2::NOT_EMPTY;
1170 aField.NumericValue = 0;
1171 bByEmpty = true;
1175 if (!bByEmpty && !rEntry.GetQueryItems().empty())
1177 const ScQueryEntry::Item& rItem = rEntry.GetQueryItems().front();
1178 aField.IsNumeric = rItem.meType != ScQueryEntry::ByString;
1179 aField.StringValue = rItem.maString.getString();
1180 aField.NumericValue = rItem.mfVal;
1183 pAry[i] = aField;
1185 return aSeq;
1188 uno::Sequence<sheet::TableFilterField3> SAL_CALL ScFilterDescriptorBase::getFilterFields3()
1190 SolarMutexGuard aGuard;
1191 ScQueryParam aParam;
1192 GetData(aParam);
1194 SCSIZE nEntries = aParam.GetEntryCount(); // allocated entries in Param
1195 SCSIZE nCount = 0; // active
1196 while ( nCount < nEntries &&
1197 aParam.GetEntry(nCount).bDoQuery )
1198 ++nCount;
1200 sheet::TableFilterField3 aField;
1201 uno::Sequence<sheet::TableFilterField3> aSeq(static_cast<sal_Int32>(nCount));
1202 sheet::TableFilterField3* pAry = aSeq.getArray();
1203 for (SCSIZE i = 0; i < nCount; ++i)
1205 const ScQueryEntry& rEntry = aParam.GetEntry(i);
1206 convertQueryEntryToUno(rEntry, aField);
1208 bool bByEmpty = false;
1209 if (aField.Operator == sheet::FilterOperator2::EQUAL)
1211 if (rEntry.IsQueryByEmpty())
1213 aField.Operator = sheet::FilterOperator2::EMPTY;
1214 aField.Values.realloc(1);
1215 aField.Values.getArray()[0].NumericValue = 0;
1216 bByEmpty = true;
1218 else if (rEntry.IsQueryByNonEmpty())
1220 aField.Operator = sheet::FilterOperator2::NOT_EMPTY;
1221 aField.Values.realloc(1);
1222 aField.Values.getArray()[0].NumericValue = 0;
1223 bByEmpty = true;
1227 if (!bByEmpty)
1229 const ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems();
1230 size_t nItemCount = rItems.size();
1231 aField.Values.realloc(nItemCount);
1232 auto pValues = aField.Values.getArray();
1233 size_t j = 0;
1234 for (const auto& rItem : rItems)
1236 pValues[j].IsNumeric = rItem.meType != ScQueryEntry::ByString;
1237 pValues[j].StringValue = rItem.maString.getString();
1238 pValues[j].NumericValue = rItem.mfVal;
1239 ++j;
1243 pAry[i] = aField;
1245 return aSeq;
1248 void SAL_CALL ScFilterDescriptorBase::setFilterFields(
1249 const uno::Sequence<sheet::TableFilterField>& aFilterFields )
1251 SolarMutexGuard aGuard;
1252 ScQueryParam aParam;
1253 GetData(aParam);
1255 SCSIZE nCount = static_cast<SCSIZE>(aFilterFields.getLength());
1256 aParam.Resize( nCount );
1258 ScDocument& rDoc = pDocSh->GetDocument();
1259 svl::SharedStringPool& rPool = rDoc.GetSharedStringPool();
1260 const sheet::TableFilterField* pAry = aFilterFields.getConstArray();
1261 SCSIZE i;
1262 for (i=0; i<nCount; i++)
1264 ScQueryEntry& rEntry = aParam.GetEntry(i);
1265 ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems();
1266 rItems.resize(1);
1267 ScQueryEntry::Item& rItem = rItems.front();
1268 rEntry.bDoQuery = true;
1269 rEntry.eConnect = (pAry[i].Connection == sheet::FilterConnection_AND) ? SC_AND : SC_OR;
1270 rEntry.nField = pAry[i].Field;
1271 rItem.meType = pAry[i].IsNumeric ? ScQueryEntry::ByValue : ScQueryEntry::ByString;
1272 rItem.mfVal = pAry[i].NumericValue;
1273 rItem.maString = rPool.intern(pAry[i].StringValue);
1275 if (rItem.meType != ScQueryEntry::ByString)
1277 OUString aStr = rDoc.GetFormatTable()->GetInputLineString(rItem.mfVal, 0);
1278 rItem.maString = rPool.intern(aStr);
1281 switch (pAry[i].Operator) // FilterOperator
1283 case sheet::FilterOperator_EQUAL: rEntry.eOp = SC_EQUAL; break;
1284 case sheet::FilterOperator_LESS: rEntry.eOp = SC_LESS; break;
1285 case sheet::FilterOperator_GREATER: rEntry.eOp = SC_GREATER; break;
1286 case sheet::FilterOperator_LESS_EQUAL: rEntry.eOp = SC_LESS_EQUAL; break;
1287 case sheet::FilterOperator_GREATER_EQUAL: rEntry.eOp = SC_GREATER_EQUAL; break;
1288 case sheet::FilterOperator_NOT_EQUAL: rEntry.eOp = SC_NOT_EQUAL; break;
1289 case sheet::FilterOperator_TOP_VALUES: rEntry.eOp = SC_TOPVAL; break;
1290 case sheet::FilterOperator_BOTTOM_VALUES: rEntry.eOp = SC_BOTVAL; break;
1291 case sheet::FilterOperator_TOP_PERCENT: rEntry.eOp = SC_TOPPERC; break;
1292 case sheet::FilterOperator_BOTTOM_PERCENT: rEntry.eOp = SC_BOTPERC; break;
1293 case sheet::FilterOperator_EMPTY:
1294 rEntry.SetQueryByEmpty();
1295 break;
1296 case sheet::FilterOperator_NOT_EMPTY:
1297 rEntry.SetQueryByNonEmpty();
1298 break;
1299 default:
1300 OSL_FAIL("Wrong query enum");
1301 rEntry.eOp = SC_EQUAL;
1305 SCSIZE nParamCount = aParam.GetEntryCount(); // if below eight Param isn't resized
1306 for (i=nCount; i<nParamCount; i++)
1307 aParam.GetEntry(i).bDoQuery = false; // reset surplus fields
1309 PutData(aParam);
1312 void SAL_CALL ScFilterDescriptorBase::setFilterFields2(
1313 const uno::Sequence<sheet::TableFilterField2>& aFilterFields )
1315 SolarMutexGuard aGuard;
1316 ScQueryParam aParam;
1317 GetData(aParam);
1318 fillQueryParam(aParam, &pDocSh->GetDocument(), aFilterFields);
1319 PutData(aParam);
1322 void SAL_CALL ScFilterDescriptorBase::setFilterFields3(
1323 const uno::Sequence<sheet::TableFilterField3>& aFilterFields )
1325 SolarMutexGuard aGuard;
1326 ScQueryParam aParam;
1327 GetData(aParam);
1328 fillQueryParam(aParam, &pDocSh->GetDocument(), aFilterFields);
1329 PutData(aParam);
1332 // Rest are Properties
1334 // XPropertySet
1336 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScFilterDescriptorBase::getPropertySetInfo()
1338 SolarMutexGuard aGuard;
1339 static uno::Reference<beans::XPropertySetInfo> aRef(
1340 new SfxItemPropertySetInfo( aPropSet.getPropertyMap() ));
1341 return aRef;
1344 void SAL_CALL ScFilterDescriptorBase::setPropertyValue(
1345 const OUString& aPropertyName, const uno::Any& aValue )
1347 SolarMutexGuard aGuard;
1348 ScQueryParam aParam;
1349 GetData(aParam);
1351 if (aPropertyName == SC_UNONAME_CONTHDR)
1352 aParam.bHasHeader = ScUnoHelpFunctions::GetBoolFromAny( aValue );
1353 else if (aPropertyName == SC_UNONAME_COPYOUT)
1354 aParam.bInplace = !(ScUnoHelpFunctions::GetBoolFromAny( aValue ));
1355 else if (aPropertyName == SC_UNONAME_ISCASE)
1356 aParam.bCaseSens = ScUnoHelpFunctions::GetBoolFromAny( aValue );
1357 else if (aPropertyName == SC_UNONAME_MAXFLD)
1359 // silently ignored
1361 else if (aPropertyName == SC_UNONAME_ORIENT)
1363 //! test for correct enum type?
1364 table::TableOrientation eOrient = static_cast<table::TableOrientation>(ScUnoHelpFunctions::GetEnumFromAny( aValue ));
1365 aParam.bByRow = ( eOrient != table::TableOrientation_COLUMNS );
1367 else if (aPropertyName == SC_UNONAME_OUTPOS)
1369 table::CellAddress aAddress;
1370 if ( aValue >>= aAddress )
1372 aParam.nDestTab = aAddress.Sheet;
1373 aParam.nDestCol = static_cast<SCCOL>(aAddress.Column);
1374 aParam.nDestRow = static_cast<SCROW>(aAddress.Row);
1377 else if (aPropertyName == SC_UNONAME_SAVEOUT)
1378 aParam.bDestPers = ScUnoHelpFunctions::GetBoolFromAny( aValue );
1379 else if (aPropertyName == SC_UNONAME_SKIPDUP)
1380 aParam.bDuplicate = !(ScUnoHelpFunctions::GetBoolFromAny( aValue ));
1381 else if (aPropertyName == SC_UNONAME_USEREGEX)
1382 aParam.eSearchType = ScUnoHelpFunctions::GetBoolFromAny( aValue ) ? utl::SearchParam::SearchType::Regexp :
1383 utl::SearchParam::SearchType::Normal;
1385 PutData(aParam);
1388 uno::Any SAL_CALL ScFilterDescriptorBase::getPropertyValue( const OUString& aPropertyName )
1390 SolarMutexGuard aGuard;
1391 ScQueryParam aParam;
1392 GetData(aParam);
1394 uno::Any aRet;
1396 if (aPropertyName == SC_UNONAME_CONTHDR )
1397 aRet <<= aParam.bHasHeader;
1398 else if (aPropertyName == SC_UNONAME_COPYOUT )
1399 aRet <<= !(aParam.bInplace);
1400 else if (aPropertyName == SC_UNONAME_ISCASE )
1401 aRet <<= aParam.bCaseSens;
1402 else if (aPropertyName == SC_UNONAME_MAXFLD )
1403 aRet <<= static_cast<sal_Int32>(aParam.GetEntryCount());
1404 else if (aPropertyName == SC_UNONAME_ORIENT )
1406 table::TableOrientation eOrient = aParam.bByRow ? table::TableOrientation_ROWS :
1407 table::TableOrientation_COLUMNS;
1408 aRet <<= eOrient;
1410 else if (aPropertyName == SC_UNONAME_OUTPOS )
1412 table::CellAddress aOutPos;
1413 aOutPos.Sheet = aParam.nDestTab;
1414 aOutPos.Column = aParam.nDestCol;
1415 aOutPos.Row = aParam.nDestRow;
1416 aRet <<= aOutPos;
1418 else if (aPropertyName == SC_UNONAME_SAVEOUT )
1419 aRet <<= aParam.bDestPers;
1420 else if (aPropertyName == SC_UNONAME_SKIPDUP )
1421 aRet <<= !(aParam.bDuplicate);
1422 else if (aPropertyName == SC_UNONAME_USEREGEX )
1423 aRet <<= (aParam.eSearchType == utl::SearchParam::SearchType::Regexp);
1425 return aRet;
1428 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScFilterDescriptorBase )
1430 ScFilterDescriptor::ScFilterDescriptor(ScDocShell* pDocShell)
1432 ScFilterDescriptorBase(pDocShell)
1436 ScFilterDescriptor::~ScFilterDescriptor()
1440 void ScFilterDescriptor::GetData( ScQueryParam& rParam ) const
1442 rParam = aStoredParam; // query for interface
1445 void ScFilterDescriptor::PutData( const ScQueryParam& rParam )
1447 aStoredParam = rParam; // set by the interface
1450 void ScFilterDescriptor::SetParam( const ScQueryParam& rNew )
1452 aStoredParam = rNew; // set from outside
1455 ScRangeFilterDescriptor::ScRangeFilterDescriptor(ScDocShell* pDocShell, ScDatabaseRangeObj* pPar) :
1456 ScFilterDescriptorBase(pDocShell),
1457 mxParent(pPar)
1461 ScRangeFilterDescriptor::~ScRangeFilterDescriptor()
1465 void ScRangeFilterDescriptor::GetData( ScQueryParam& rParam ) const
1467 if (mxParent.is())
1468 mxParent->GetQueryParam( rParam );
1471 void ScRangeFilterDescriptor::PutData( const ScQueryParam& rParam )
1473 if (mxParent.is())
1474 mxParent->SetQueryParam( rParam );
1477 ScDataPilotFilterDescriptor::ScDataPilotFilterDescriptor(ScDocShell* pDocShell, ScDataPilotDescriptorBase* pPar) :
1478 ScFilterDescriptorBase(pDocShell),
1479 mxParent(pPar)
1483 ScDataPilotFilterDescriptor::~ScDataPilotFilterDescriptor()
1487 void ScDataPilotFilterDescriptor::GetData( ScQueryParam& rParam ) const
1489 if (mxParent.is())
1491 ScDPObject* pDPObj = mxParent->GetDPObject();
1492 if (pDPObj && pDPObj->IsSheetData())
1493 rParam = pDPObj->GetSheetDesc()->GetQueryParam();
1497 void ScDataPilotFilterDescriptor::PutData( const ScQueryParam& rParam )
1499 if (!mxParent.is())
1500 return;
1502 ScDPObject* pDPObj = mxParent->GetDPObject();
1503 if (pDPObj)
1505 ScSheetSourceDesc aSheetDesc(&mxParent->GetDocShell()->GetDocument());
1506 if (pDPObj->IsSheetData())
1507 aSheetDesc = *pDPObj->GetSheetDesc();
1508 aSheetDesc.SetQueryParam(rParam);
1509 pDPObj->SetSheetDesc(aSheetDesc);
1510 mxParent->SetDPObject(pDPObj);
1514 ScDatabaseRangeObj::ScDatabaseRangeObj(ScDocShell* pDocSh, OUString aNm) :
1515 pDocShell( pDocSh ),
1516 aName(std::move( aNm )),
1517 aPropSet( lcl_GetDBRangePropertyMap() ),
1518 bIsUnnamed(false),
1519 aTab( 0 )
1521 pDocShell->GetDocument().AddUnoObject(*this);
1524 ScDatabaseRangeObj::ScDatabaseRangeObj(ScDocShell* pDocSh, const SCTAB nTab) :
1525 pDocShell( pDocSh ),
1526 aName(STR_DB_LOCAL_NONAME),
1527 aPropSet( lcl_GetDBRangePropertyMap() ),
1528 bIsUnnamed(true),
1529 aTab( nTab )
1531 pDocShell->GetDocument().AddUnoObject(*this);
1534 ScDatabaseRangeObj::~ScDatabaseRangeObj()
1536 SolarMutexGuard g;
1538 if (pDocShell)
1539 pDocShell->GetDocument().RemoveUnoObject(*this);
1542 void ScDatabaseRangeObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
1545 if ( rHint.GetId() == SfxHintId::Dying )
1546 pDocShell = nullptr;
1547 else if ( rHint.GetId() == SfxHintId::ScDBRangeRefreshed )
1549 auto pRefreshHint = static_cast<const ScDBRangeRefreshedHint*>(&rHint);
1550 ScDBData* pDBData = GetDBData_Impl();
1551 ScImportParam aParam;
1552 pDBData->GetImportParam(aParam);
1553 if (aParam == pRefreshHint->GetImportParam())
1554 Refreshed_Impl();
1558 // Help functions
1560 ScDBData* ScDatabaseRangeObj::GetDBData_Impl() const
1562 ScDBData* pRet = nullptr;
1563 if (pDocShell)
1565 if (bIsUnnamed)
1567 pRet = pDocShell->GetDocument().GetAnonymousDBData(aTab);
1569 else
1571 ScDBCollection* pNames = pDocShell->GetDocument().GetDBCollection();
1572 if (pNames)
1574 ScDBData* p = pNames->getNamedDBs().findByUpperName(ScGlobal::getCharClass().uppercase(aName));
1575 if (p)
1576 pRet = p;
1580 return pRet;
1583 // XNamed
1585 OUString SAL_CALL ScDatabaseRangeObj::getName()
1587 SolarMutexGuard aGuard;
1588 return aName;
1591 void SAL_CALL ScDatabaseRangeObj::setName( const OUString& aNewName )
1593 SolarMutexGuard aGuard;
1594 if (pDocShell)
1596 ScDBDocFunc aFunc(*pDocShell);
1597 bool bOk = aFunc.RenameDBRange( aName, aNewName );
1598 if (bOk)
1599 aName = aNewName;
1603 // XDatabaseRange
1605 table::CellRangeAddress SAL_CALL ScDatabaseRangeObj::getDataArea()
1607 SolarMutexGuard aGuard;
1608 table::CellRangeAddress aAddress;
1609 ScDBData* pData = GetDBData_Impl();
1610 if (pData)
1612 ScRange aRange;
1613 pData->GetArea(aRange);
1614 aAddress.Sheet = aRange.aStart.Tab();
1615 aAddress.StartColumn = aRange.aStart.Col();
1616 aAddress.StartRow = aRange.aStart.Row();
1617 aAddress.EndColumn = aRange.aEnd.Col();
1618 aAddress.EndRow = aRange.aEnd.Row();
1620 return aAddress;
1623 void SAL_CALL ScDatabaseRangeObj::setDataArea( const table::CellRangeAddress& aDataArea )
1625 SolarMutexGuard aGuard;
1626 ScDBData* pData = GetDBData_Impl();
1627 if ( pDocShell && pData )
1629 ScDBData aNewData( *pData );
1630 //! MoveTo ???
1631 aNewData.SetArea( aDataArea.Sheet, static_cast<SCCOL>(aDataArea.StartColumn), static_cast<SCROW>(aDataArea.StartRow),
1632 static_cast<SCCOL>(aDataArea.EndColumn), static_cast<SCROW>(aDataArea.EndRow) );
1633 ScDBDocFunc aFunc(*pDocShell);
1634 aFunc.ModifyDBData(aNewData);
1638 uno::Sequence<beans::PropertyValue> SAL_CALL ScDatabaseRangeObj::getSortDescriptor()
1640 SolarMutexGuard aGuard;
1641 ScSortParam aParam;
1642 const ScDBData* pData = GetDBData_Impl();
1643 if (pData)
1645 pData->GetSortParam(aParam);
1647 // SortDescriptor contains the counted fields inside the area
1648 ScRange aDBRange;
1649 pData->GetArea(aDBRange);
1650 SCCOLROW nFieldStart = aParam.bByRow ? static_cast<SCCOLROW>(aDBRange.aStart.Col()) : static_cast<SCCOLROW>(aDBRange.aStart.Row());
1651 for (sal_uInt16 i=0; i<aParam.GetSortKeyCount(); i++)
1652 if ( aParam.maKeyState[i].bDoSort && aParam.maKeyState[i].nField >= nFieldStart )
1653 aParam.maKeyState[i].nField -= nFieldStart;
1656 uno::Sequence<beans::PropertyValue> aSeq( ScSortDescriptor::GetPropertyCount() );
1657 ScSortDescriptor::FillProperties( aSeq, aParam );
1658 return aSeq;
1661 void ScDatabaseRangeObj::GetQueryParam(ScQueryParam& rQueryParam) const
1663 const ScDBData* pData = GetDBData_Impl();
1664 if (!pData)
1665 return;
1667 pData->GetQueryParam(rQueryParam);
1669 // FilterDescriptor contains the counted fields inside the area
1670 ScRange aDBRange;
1671 pData->GetArea(aDBRange);
1672 SCCOLROW nFieldStart = rQueryParam.bByRow ? static_cast<SCCOLROW>(aDBRange.aStart.Col()) : static_cast<SCCOLROW>(aDBRange.aStart.Row());
1673 SCSIZE nCount = rQueryParam.GetEntryCount();
1674 for (SCSIZE i=0; i<nCount; i++)
1676 ScQueryEntry& rEntry = rQueryParam.GetEntry(i);
1677 if (rEntry.bDoQuery && rEntry.nField >= nFieldStart)
1678 rEntry.nField -= nFieldStart;
1682 void ScDatabaseRangeObj::SetQueryParam(const ScQueryParam& rQueryParam)
1684 const ScDBData* pData = GetDBData_Impl();
1685 if (!pData)
1686 return;
1688 // FilterDescriptor contains the counted fields inside the area
1689 ScQueryParam aParam(rQueryParam);
1690 ScRange aDBRange;
1691 pData->GetArea(aDBRange);
1692 SCCOLROW nFieldStart = aParam.bByRow ? static_cast<SCCOLROW>(aDBRange.aStart.Col()) : static_cast<SCCOLROW>(aDBRange.aStart.Row());
1694 SCSIZE nCount = aParam.GetEntryCount();
1695 for (SCSIZE i=0; i<nCount; i++)
1697 ScQueryEntry& rEntry = aParam.GetEntry(i);
1698 if (rEntry.bDoQuery)
1699 rEntry.nField += nFieldStart;
1702 ScDBData aNewData( *pData );
1703 aNewData.SetQueryParam(aParam);
1704 aNewData.SetHeader(aParam.bHasHeader); // not in ScDBData::SetQueryParam
1705 aNewData.SetTotals(aParam.bHasTotals); // not in ScDBData::SetQueryParam
1706 ScDBDocFunc aFunc(*pDocShell);
1707 aFunc.ModifyDBData(aNewData);
1710 uno::Reference<sheet::XSheetFilterDescriptor> SAL_CALL ScDatabaseRangeObj::getFilterDescriptor()
1712 SolarMutexGuard aGuard;
1713 return new ScRangeFilterDescriptor(pDocShell, this);
1716 void ScDatabaseRangeObj::GetSubTotalParam(ScSubTotalParam& rSubTotalParam) const
1718 const ScDBData* pData = GetDBData_Impl();
1719 if (!pData)
1720 return;
1722 pData->GetSubTotalParam(rSubTotalParam);
1724 // FilterDescriptor contains the counted fields inside the area
1725 ScRange aDBRange;
1726 pData->GetArea(aDBRange);
1727 SCCOL nFieldStart = aDBRange.aStart.Col();
1728 for (auto& group : rSubTotalParam.aGroups)
1730 if (group.bActive)
1732 if (group.nField >= nFieldStart)
1733 group.nField -= nFieldStart;
1734 for (SCCOL j = 0; j < group.nSubTotals; j++)
1735 if (group.col(j) >= nFieldStart)
1736 group.col(j) -= nFieldStart;
1741 void ScDatabaseRangeObj::SetSubTotalParam(const ScSubTotalParam& rSubTotalParam)
1743 const ScDBData* pData = GetDBData_Impl();
1744 if (!pData)
1745 return;
1747 // FilterDescriptor contains the counted fields inside the area
1748 ScSubTotalParam aParam(rSubTotalParam);
1749 ScRange aDBRange;
1750 pData->GetArea(aDBRange);
1751 SCCOL nFieldStart = aDBRange.aStart.Col();
1752 for (auto& group : aParam.aGroups)
1754 if (group.bActive)
1756 group.nField += nFieldStart;
1757 for (SCCOL j = 0; j < group.nSubTotals; j++)
1758 group.col(j) += nFieldStart;
1762 ScDBData aNewData( *pData );
1763 aNewData.SetSubTotalParam(aParam);
1764 ScDBDocFunc aFunc(*pDocShell);
1765 aFunc.ModifyDBData(aNewData);
1768 uno::Reference<sheet::XSubTotalDescriptor> SAL_CALL ScDatabaseRangeObj::getSubTotalDescriptor()
1770 SolarMutexGuard aGuard;
1771 return new ScRangeSubTotalDescriptor(this);
1774 uno::Sequence<beans::PropertyValue> SAL_CALL ScDatabaseRangeObj::getImportDescriptor()
1776 SolarMutexGuard aGuard;
1777 ScImportParam aParam;
1778 const ScDBData* pData = GetDBData_Impl();
1779 if (pData)
1780 pData->GetImportParam(aParam);
1782 uno::Sequence<beans::PropertyValue> aSeq( ScImportDescriptor::GetPropertyCount() );
1783 ScImportDescriptor::FillProperties( aSeq, aParam );
1784 return aSeq;
1787 // XRefreshable
1789 void SAL_CALL ScDatabaseRangeObj::refresh()
1791 SolarMutexGuard aGuard;
1792 ScDBData* pData = GetDBData_Impl();
1793 if ( !(pDocShell && pData) )
1794 return;
1796 ScDBDocFunc aFunc(*pDocShell);
1798 // repeat import?
1799 bool bContinue = true;
1800 ScImportParam aImportParam;
1801 pData->GetImportParam( aImportParam );
1802 if (aImportParam.bImport && !pData->HasImportSelection())
1804 SCTAB nTab;
1805 SCCOL nDummyCol;
1806 SCROW nDummyRow;
1807 pData->GetArea( nTab, nDummyCol,nDummyRow,nDummyCol,nDummyRow );
1808 bContinue = aFunc.DoImport( nTab, aImportParam, nullptr ); //! Api-Flag as parameter
1811 // if no error then internal operations (sort, query, subtotal)
1812 if (bContinue)
1813 aFunc.RepeatDB( pData->GetName(), true, bIsUnnamed, aTab );
1816 void SAL_CALL ScDatabaseRangeObj::addRefreshListener(
1817 const uno::Reference<util::XRefreshListener >& xListener )
1819 SolarMutexGuard aGuard;
1820 aRefreshListeners.emplace_back( xListener );
1822 // hold one additional ref to keep this object alive as long as there are listeners
1823 if ( aRefreshListeners.size() == 1 )
1824 acquire();
1827 void SAL_CALL ScDatabaseRangeObj::removeRefreshListener(
1828 const uno::Reference<util::XRefreshListener >& xListener )
1830 SolarMutexGuard aGuard;
1831 sal_uInt16 nCount = aRefreshListeners.size();
1832 for ( sal_uInt16 n=nCount; n--; )
1834 uno::Reference<util::XRefreshListener>& rObj = aRefreshListeners[n];
1835 if ( rObj == xListener )
1837 aRefreshListeners.erase( aRefreshListeners.begin() + n );
1838 if ( aRefreshListeners.empty() )
1839 release(); // release ref for listeners
1840 break;
1845 void ScDatabaseRangeObj::Refreshed_Impl()
1847 lang::EventObject aEvent;
1848 aEvent.Source = getXWeak();
1849 for (uno::Reference<util::XRefreshListener> & xRefreshListener : aRefreshListeners)
1850 xRefreshListener->refreshed( aEvent );
1853 // XCellRangeSource
1855 uno::Reference<table::XCellRange> SAL_CALL ScDatabaseRangeObj::getReferredCells()
1857 SolarMutexGuard aGuard;
1858 ScDBData* pData = GetDBData_Impl();
1859 if ( pData )
1861 //! static function to create ScCellObj/ScCellRange on ScCellRangeObj ???
1862 ScRange aRange;
1864 pData->GetArea(aRange);
1865 if ( aRange.aStart == aRange.aEnd )
1866 return new ScCellObj( pDocShell, aRange.aStart );
1867 else
1868 return new ScCellRangeObj( pDocShell, aRange );
1870 return nullptr;
1873 // XPropertySet
1875 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDatabaseRangeObj::getPropertySetInfo()
1877 SolarMutexGuard aGuard;
1878 static uno::Reference<beans::XPropertySetInfo> aRef(
1879 new SfxItemPropertySetInfo( aPropSet.getPropertyMap() ));
1880 return aRef;
1883 void SAL_CALL ScDatabaseRangeObj::setPropertyValue(
1884 const OUString& aPropertyName, const uno::Any& aValue )
1886 SolarMutexGuard aGuard;
1887 ScDBData* pData = GetDBData_Impl();
1888 if ( !(pDocShell && pData) )
1889 return;
1891 ScDBData aNewData( *pData );
1892 bool bDo = true;
1894 if ( aPropertyName == SC_UNONAME_KEEPFORM )
1895 aNewData.SetKeepFmt( ScUnoHelpFunctions::GetBoolFromAny( aValue ) );
1896 else if ( aPropertyName == SC_UNONAME_MOVCELLS )
1897 aNewData.SetDoSize( ScUnoHelpFunctions::GetBoolFromAny( aValue ) );
1898 else if ( aPropertyName == SC_UNONAME_STRIPDAT )
1899 aNewData.SetStripData( ScUnoHelpFunctions::GetBoolFromAny( aValue ) );
1900 else if (aPropertyName == SC_UNONAME_AUTOFLT )
1902 bool bAutoFilter(ScUnoHelpFunctions::GetBoolFromAny( aValue ));
1903 aNewData.SetAutoFilter(bAutoFilter);
1904 ScRange aRange;
1905 aNewData.GetArea(aRange);
1906 ScDocument& rDoc = pDocShell->GetDocument();
1907 if (bAutoFilter)
1908 rDoc.ApplyFlagsTab( aRange.aStart.Col(), aRange.aStart.Row(),
1909 aRange.aEnd.Col(), aRange.aStart.Row(),
1910 aRange.aStart.Tab(), ScMF::Auto );
1911 else if (!bAutoFilter)
1912 rDoc.RemoveFlagsTab(aRange.aStart.Col(), aRange.aStart.Row(),
1913 aRange.aEnd.Col(), aRange.aStart.Row(),
1914 aRange.aStart.Tab(), ScMF::Auto );
1915 ScRange aPaintRange(aRange.aStart, aRange.aEnd);
1916 aPaintRange.aEnd.SetRow(aPaintRange.aStart.Row());
1917 pDocShell->PostPaint(aPaintRange, PaintPartFlags::Grid);
1919 else if (aPropertyName == SC_UNONAME_USEFLTCRT )
1921 if (ScUnoHelpFunctions::GetBoolFromAny( aValue ))
1923 // only here to set bIsAdvanced in ScDBData
1924 ScRange aRange;
1925 (void)aNewData.GetAdvancedQuerySource(aRange);
1926 aNewData.SetAdvancedQuerySource(&aRange);
1928 else
1929 aNewData.SetAdvancedQuerySource(nullptr);
1931 else if (aPropertyName == SC_UNONAME_FLTCRT )
1933 table::CellRangeAddress aRange;
1934 if (aValue >>= aRange)
1936 ScRange aCoreRange;
1937 ScUnoConversion::FillScRange(aCoreRange, aRange);
1939 aNewData.SetAdvancedQuerySource(&aCoreRange);
1942 else if (aPropertyName == SC_UNONAME_FROMSELECT )
1944 aNewData.SetImportSelection(::cppu::any2bool(aValue));
1946 else if (aPropertyName == SC_UNONAME_REFPERIOD )
1948 sal_Int32 nRefresh = 0;
1949 if (aValue >>= nRefresh)
1951 ScDocument& rDoc = pDocShell->GetDocument();
1952 aNewData.SetRefreshDelay(nRefresh);
1953 if (rDoc.GetDBCollection())
1955 aNewData.SetRefreshHandler( rDoc.GetDBCollection()->GetRefreshHandler() );
1956 aNewData.SetRefreshControl( &rDoc.GetRefreshTimerControlAddress() );
1960 else if (aPropertyName == SC_UNONAME_CONRES )
1963 else if ( aPropertyName == SC_UNONAME_TOTALSROW )
1964 aNewData.SetTotals( ScUnoHelpFunctions::GetBoolFromAny( aValue ) );
1965 else if ( aPropertyName == SC_UNONAME_CONTHDR )
1966 aNewData.SetHeader( ScUnoHelpFunctions::GetBoolFromAny( aValue ) );
1967 else
1968 bDo = false;
1970 if (bDo)
1972 ScDBDocFunc aFunc(*pDocShell);
1973 aFunc.ModifyDBData(aNewData);
1977 uno::Any SAL_CALL ScDatabaseRangeObj::getPropertyValue( const OUString& aPropertyName )
1979 SolarMutexGuard aGuard;
1980 uno::Any aRet;
1981 ScDBData* pData = GetDBData_Impl();
1982 if ( pData )
1984 if ( aPropertyName == SC_UNONAME_KEEPFORM )
1985 aRet <<= pData->IsKeepFmt();
1986 else if ( aPropertyName == SC_UNONAME_MOVCELLS )
1987 aRet <<= pData->IsDoSize();
1988 else if ( aPropertyName == SC_UNONAME_STRIPDAT )
1989 aRet <<= pData->IsStripData();
1990 else if ( aPropertyName == SC_UNONAME_ISUSER )
1992 // all database ranges except "unnamed" are user defined
1993 aRet <<= (pData->GetName() != STR_DB_LOCAL_NONAME);
1995 else if ( aPropertyName == SC_UNO_LINKDISPBIT )
1997 // no target bitmaps for individual entries (would be all equal)
1998 // ScLinkTargetTypeObj::SetLinkTargetBitmap( aRet, SC_LINKTARGETTYPE_DBAREA );
2000 else if ( aPropertyName == SC_UNO_LINKDISPNAME )
2001 aRet <<= aName;
2002 else if (aPropertyName == SC_UNONAME_AUTOFLT )
2004 bool bAutoFilter(GetDBData_Impl()->HasAutoFilter());
2006 aRet <<= bAutoFilter;
2008 else if (aPropertyName == SC_UNONAME_USEFLTCRT )
2010 ScRange aRange;
2011 bool bIsAdvancedSource(GetDBData_Impl()->GetAdvancedQuerySource(aRange));
2013 aRet <<= bIsAdvancedSource;
2015 else if (aPropertyName == SC_UNONAME_FLTCRT )
2017 table::CellRangeAddress aRange;
2018 ScRange aCoreRange;
2019 if (GetDBData_Impl()->GetAdvancedQuerySource(aCoreRange))
2020 ScUnoConversion::FillApiRange(aRange, aCoreRange);
2022 aRet <<= aRange;
2024 else if (aPropertyName == SC_UNONAME_FROMSELECT )
2026 aRet <<= GetDBData_Impl()->HasImportSelection();
2028 else if (aPropertyName == SC_UNONAME_REFPERIOD )
2030 sal_Int32 nRefresh(GetDBData_Impl()->GetRefreshDelaySeconds());
2031 aRet <<= nRefresh;
2033 else if (aPropertyName == SC_UNONAME_CONRES )
2036 else if (aPropertyName == SC_UNONAME_TOKENINDEX )
2038 // get index for use in formula tokens (read-only)
2039 aRet <<= static_cast<sal_Int32>(GetDBData_Impl()->GetIndex());
2041 else if (aPropertyName == SC_UNONAME_TOTALSROW )
2043 bool bTotals(GetDBData_Impl()->HasTotals());
2045 aRet <<= bTotals;
2047 else if (aPropertyName == SC_UNONAME_CONTHDR )
2049 bool bHeader(GetDBData_Impl()->HasHeader());
2051 aRet <<= bHeader;
2054 return aRet;
2057 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDatabaseRangeObj )
2059 // XServiceInfo
2060 OUString SAL_CALL ScDatabaseRangeObj::getImplementationName()
2062 return u"ScDatabaseRangeObj"_ustr;
2065 sal_Bool SAL_CALL ScDatabaseRangeObj::supportsService( const OUString& rServiceName )
2067 return cppu::supportsService(this, rServiceName);
2070 uno::Sequence<OUString> SAL_CALL ScDatabaseRangeObj::getSupportedServiceNames()
2072 return {u"com.sun.star.sheet.DatabaseRange"_ustr,
2073 SCLINKTARGET_SERVICE};
2076 ScDatabaseRangesObj::ScDatabaseRangesObj(ScDocShell* pDocSh) :
2077 pDocShell( pDocSh )
2079 pDocShell->GetDocument().AddUnoObject(*this);
2082 ScDatabaseRangesObj::~ScDatabaseRangesObj()
2084 SolarMutexGuard g;
2086 if (pDocShell)
2087 pDocShell->GetDocument().RemoveUnoObject(*this);
2090 void ScDatabaseRangesObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
2092 // reference update does not matter here
2094 if ( rHint.GetId() == SfxHintId::Dying )
2096 pDocShell = nullptr;
2100 // XDatabaseRanges
2102 rtl::Reference<ScDatabaseRangeObj> ScDatabaseRangesObj::GetObjectByIndex_Impl(size_t nIndex)
2104 if (!pDocShell)
2105 return nullptr;
2107 ScDBCollection* pNames = pDocShell->GetDocument().GetDBCollection();
2108 if (!pNames)
2109 return nullptr;
2111 const ScDBCollection::NamedDBs& rDBs = pNames->getNamedDBs();
2112 if (rDBs.empty() || nIndex >= rDBs.size())
2113 return nullptr;
2115 ScDBCollection::NamedDBs::const_iterator itr = rDBs.begin();
2116 ::std::advance(itr, nIndex); // boundary check is done above.
2117 return new ScDatabaseRangeObj(pDocShell, (*itr)->GetName());
2120 rtl::Reference<ScDatabaseRangeObj> ScDatabaseRangesObj::GetObjectByName_Impl(const OUString& aName)
2122 if ( pDocShell && hasByName(aName) )
2124 return new ScDatabaseRangeObj( pDocShell, aName );
2126 return nullptr;
2129 void SAL_CALL ScDatabaseRangesObj::addNewByName( const OUString& aName,
2130 const table::CellRangeAddress& aRange )
2132 SolarMutexGuard aGuard;
2133 bool bDone = false;
2134 if (pDocShell)
2136 ScDBDocFunc aFunc(*pDocShell);
2138 ScRange aNameRange( static_cast<SCCOL>(aRange.StartColumn), static_cast<SCROW>(aRange.StartRow), aRange.Sheet,
2139 static_cast<SCCOL>(aRange.EndColumn), static_cast<SCROW>(aRange.EndRow), aRange.Sheet );
2140 bDone = aFunc.AddDBRange( aName, aNameRange );
2142 if (!bDone)
2143 throw uno::RuntimeException(); // no other exceptions specified
2146 void SAL_CALL ScDatabaseRangesObj::removeByName( const OUString& aName )
2148 SolarMutexGuard aGuard;
2149 bool bDone = false;
2150 if (pDocShell)
2152 ScDBDocFunc aFunc(*pDocShell);
2153 bDone = aFunc.DeleteDBRange( aName );
2155 if (!bDone)
2156 throw uno::RuntimeException(); // no other exceptions specified
2159 // XEnumerationAccess
2161 uno::Reference<container::XEnumeration> SAL_CALL ScDatabaseRangesObj::createEnumeration()
2163 SolarMutexGuard aGuard;
2164 return new ScIndexEnumeration(this, u"com.sun.star.sheet.DatabaseRangesEnumeration"_ustr);
2167 // XIndexAccess
2169 sal_Int32 SAL_CALL ScDatabaseRangesObj::getCount()
2171 SolarMutexGuard aGuard;
2173 //! need to omit "unnamed"?
2175 if (pDocShell)
2177 ScDBCollection* pNames = pDocShell->GetDocument().GetDBCollection();
2178 if (pNames)
2179 return static_cast<sal_Int32>(pNames->getNamedDBs().size());
2181 return 0;
2184 uno::Any SAL_CALL ScDatabaseRangesObj::getByIndex( sal_Int32 nIndex )
2186 SolarMutexGuard aGuard;
2187 if (nIndex < 0)
2188 throw lang::IndexOutOfBoundsException();
2190 uno::Reference<sheet::XDatabaseRange> xRange(GetObjectByIndex_Impl(static_cast<size_t>(nIndex)));
2191 if (!xRange.is())
2192 throw lang::IndexOutOfBoundsException();
2194 return uno::Any(xRange);
2197 uno::Type SAL_CALL ScDatabaseRangesObj::getElementType()
2199 return cppu::UnoType<sheet::XDatabaseRange>::get();
2202 sal_Bool SAL_CALL ScDatabaseRangesObj::hasElements()
2204 SolarMutexGuard aGuard;
2205 return ( getCount() != 0 );
2208 // XNameAccess
2210 uno::Any SAL_CALL ScDatabaseRangesObj::getByName( const OUString& aName )
2212 SolarMutexGuard aGuard;
2213 uno::Reference<sheet::XDatabaseRange> xRange(GetObjectByName_Impl(aName));
2214 if (!xRange.is())
2215 throw container::NoSuchElementException();
2217 return uno::Any(xRange);
2220 uno::Sequence<OUString> SAL_CALL ScDatabaseRangesObj::getElementNames()
2222 SolarMutexGuard aGuard;
2224 //! need to omit "unnamed"?
2226 if (pDocShell)
2228 ScDBCollection* pNames = pDocShell->GetDocument().GetDBCollection();
2229 if (pNames)
2231 const ScDBCollection::NamedDBs& rDBs = pNames->getNamedDBs();
2232 uno::Sequence<OUString> aSeq(rDBs.size());
2233 auto aSeqRange = asNonConstRange(aSeq);
2234 size_t i = 0;
2235 for (const auto& rDB : rDBs)
2237 aSeqRange[i] = rDB->GetName();
2238 ++i;
2241 return aSeq;
2244 return {};
2247 sal_Bool SAL_CALL ScDatabaseRangesObj::hasByName( const OUString& aName )
2249 SolarMutexGuard aGuard;
2251 //! need to omit "unnamed"?
2253 if (pDocShell)
2255 ScDBCollection* pNames = pDocShell->GetDocument().GetDBCollection();
2256 if (pNames)
2257 return pNames->getNamedDBs().findByUpperName(ScGlobal::getCharClass().uppercase(aName)) != nullptr;
2259 return false;
2262 ScUnnamedDatabaseRangesObj::ScUnnamedDatabaseRangesObj(ScDocShell* pDocSh) :
2263 pDocShell( pDocSh )
2265 pDocShell->GetDocument().AddUnoObject(*this);
2268 ScUnnamedDatabaseRangesObj::~ScUnnamedDatabaseRangesObj()
2270 SolarMutexGuard g;
2272 if (pDocShell)
2273 pDocShell->GetDocument().RemoveUnoObject(*this);
2276 void ScUnnamedDatabaseRangesObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
2278 // reference update does not matter here
2280 if ( rHint.GetId() == SfxHintId::Dying )
2282 pDocShell = nullptr;
2286 // XUnnamedDatabaseRanges
2288 void ScUnnamedDatabaseRangesObj::setByTable( const table::CellRangeAddress& aRange )
2290 SolarMutexGuard aGuard;
2291 bool bDone = false;
2292 if (pDocShell)
2294 if ( pDocShell->GetDocument().GetTableCount() <= aRange.Sheet )
2295 throw lang::IndexOutOfBoundsException();
2297 ScDBDocFunc aFunc(*pDocShell);
2298 ScRange aUnnamedRange( static_cast<SCCOL>(aRange.StartColumn), static_cast<SCROW>(aRange.StartRow), aRange.Sheet,
2299 static_cast<SCCOL>(aRange.EndColumn), static_cast<SCROW>(aRange.EndRow), aRange.Sheet );
2300 bDone = aFunc.AddDBRange( STR_DB_LOCAL_NONAME, aUnnamedRange );
2302 if (!bDone)
2303 throw uno::RuntimeException(); // no other exceptions specified
2306 uno::Any ScUnnamedDatabaseRangesObj::getByTable( sal_Int32 nTab )
2308 SolarMutexGuard aGuard;
2309 if (!pDocShell)
2310 throw uno::RuntimeException();
2312 if ( pDocShell->GetDocument().GetTableCount() <= nTab )
2313 throw lang::IndexOutOfBoundsException();
2314 uno::Reference<sheet::XDatabaseRange> xRange(
2315 new ScDatabaseRangeObj(pDocShell, static_cast<SCTAB>(nTab)));
2316 if (!xRange.is())
2317 throw container::NoSuchElementException();
2319 return uno::Any(xRange);
2322 sal_Bool ScUnnamedDatabaseRangesObj::hasByTable( sal_Int32 nTab )
2324 SolarMutexGuard aGuard;
2325 if (pDocShell)
2327 if (pDocShell->GetDocument().GetTableCount() <= nTab)
2328 throw lang::IndexOutOfBoundsException();
2329 if (pDocShell->GetDocument().GetAnonymousDBData(static_cast<SCTAB>(nTab)))
2330 return true;
2331 return false;
2333 else
2334 return false;
2337 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */