LibreOffice Module sc (master)  1
XMLExportDatabaseRanges.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 <memory>
22 #include <xmloff/xmltoken.hxx>
23 #include <xmloff/xmlnamespace.hxx>
24 #include <xmloff/namespacemap.hxx>
25 #include <sax/tools/converter.hxx>
26 #include "xmlexprt.hxx"
27 #include "XMLExportIterator.hxx"
28 #include "XMLConverter.hxx"
29 #include <unonames.hxx>
30 #include <dbdata.hxx>
31 #include <document.hxx>
32 #include <globalnames.hxx>
33 #include "XMLExportSharedData.hxx"
34 #include <rangeutl.hxx>
35 #include <subtotalparam.hxx>
36 #include <queryparam.hxx>
37 #include <queryentry.hxx>
38 #include <sortparam.hxx>
39 
41 
42 #include <com/sun/star/beans/XPropertySet.hpp>
43 #include <com/sun/star/frame/XModel.hpp>
44 #include <com/sun/star/sheet/DataImportMode.hpp>
45 #include <com/sun/star/sheet/XDatabaseRanges.hpp>
46 #include <com/sun/star/sheet/XDatabaseRange.hpp>
47 #include <comphelper/extract.hxx>
48 #include <osl/diagnose.h>
49 
50 #include <map>
51 
53 constexpr OUStringLiteral SC_USERLIST = u"UserList";
54 
55 using namespace com::sun::star;
56 using namespace xmloff::token;
57 
58 void writeSort(ScXMLExport& mrExport, const ScSortParam& aParam, const ScRange& aRange, const ScDocument* mpDoc)
59 {
60  // Count sort items first.
61  size_t nSortCount = 0;
62  for (; nSortCount < aParam.GetSortKeyCount(); ++nSortCount)
63  {
64  if (!aParam.maKeyState[nSortCount].bDoSort)
65  break;
66  }
67 
68  if (!nSortCount)
69  // Nothing to export.
70  return;
71 
72  ScAddress aOutPos(aParam.nDestCol, aParam.nDestRow, aParam.nDestTab);
73 
74  if (!aParam.aDataAreaExtras.mbCellFormats)
76 
77  if (!aParam.bInplace)
78  {
79  OUString aStr;
81  aStr, aOutPos, mpDoc, ::formula::FormulaGrammar::CONV_OOO);
83  }
84 
85  if (aParam.bCaseSens)
87 
89  if (!aParam.aCollatorAlgorithm.isEmpty())
91 
92  SvXMLElementExport aElemS(mrExport, XML_NAMESPACE_TABLE, XML_SORT, true, true);
93 
94  SCCOLROW nFieldStart = aParam.bByRow ? aRange.aStart.Col() : aRange.aStart.Row();
95 
96  for (size_t i = 0; i < nSortCount; ++i)
97  {
98  // Convert field value from absolute to relative.
99  SCCOLROW nField = aParam.maKeyState[i].nField - nFieldStart;
100  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FIELD_NUMBER, OUString::number(nField));
101 
102  if (!aParam.maKeyState[i].bAscending)
104 
105  if (aParam.bUserDef)
106  {
107  OUString aBuf = SC_USERLIST + OUString::number(static_cast<sal_Int32>(aParam.nUserIndex));
109  }
110  else
111  {
112  // Right now we only support automatic field type. In the
113  // future we may support numeric or alphanumeric field type.
115  }
116 
117  SvXMLElementExport aElemSb(mrExport, XML_NAMESPACE_TABLE, XML_SORT_BY, true, true);
118  }
119 }
120 
122  : rExport(rTempExport),
123  pDoc( nullptr )
124 {
125 }
126 
128 {
130  if (rExport.GetModel().is())
131  {
132  uno::Reference <beans::XPropertySet> xPropertySet (rExport.GetModel(), uno::UNO_QUERY);
133  if (xPropertySet.is())
134  {
135  uno::Reference <sheet::XDatabaseRanges> xDatabaseRanges(xPropertySet->getPropertyValue(SC_UNO_DATABASERNG), uno::UNO_QUERY);
137  if (xDatabaseRanges.is())
138  {
139  const uno::Sequence <OUString> aRanges(xDatabaseRanges->getElementNames());
140  for (const OUString& sDatabaseRangeName : aRanges)
141  {
142  uno::Reference <sheet::XDatabaseRange> xDatabaseRange(xDatabaseRanges->getByName(sDatabaseRangeName), uno::UNO_QUERY);
143  if (xDatabaseRange.is())
144  {
145  uno::Reference <beans::XPropertySet> xDatabaseRangePropertySet (xDatabaseRange, uno::UNO_QUERY);
146  if (xDatabaseRangePropertySet.is() &&
147  ::cppu::any2bool(xDatabaseRangePropertySet->getPropertyValue(SC_UNONAME_STRIPDAT)))
148  {
149  const uno::Sequence <beans::PropertyValue> aImportProperties(xDatabaseRange->getImportDescriptor());
150  sheet::DataImportMode nSourceType = sheet::DataImportMode_NONE;
151  for (const auto& rProp : aImportProperties)
152  if ( rProp.Name == SC_UNONAME_SRCTYPE )
153  rProp.Value >>= nSourceType;
154  if (nSourceType != sheet::DataImportMode_NONE)
155  {
156  table::CellRangeAddress aArea = xDatabaseRange->getDataArea();
157  aSkipRanges.AddNewEmptyDatabaseRange(aArea);
158 
159  // #105276#; set last row/column so default styles are collected
160  rExport.GetSharedData()->SetLastColumn(aArea.Sheet, aArea.EndColumn);
161  rExport.GetSharedData()->SetLastRow(aArea.Sheet, aArea.EndRow);
162  }
163  }
164  }
165  }
166  }
167  }
168  }
169  return aSkipRanges;
170 }
171 
172 namespace {
173 
174 class WriteDatabaseRange
175 {
176  ScXMLExport& mrExport;
177  ScDocument* mpDoc;
178  sal_Int32 mnCounter;
179  ScDBCollection::RangeType meRangeType;
180 public:
181 
182  WriteDatabaseRange(ScXMLExport& rExport, ScDocument* pDoc) :
183  mrExport(rExport), mpDoc(pDoc), mnCounter(0), meRangeType(ScDBCollection::GlobalNamed) {}
184 
185  void setRangeType(ScDBCollection::RangeType eNew)
186  {
187  meRangeType = eNew;
188  }
189 
190  void operator() (const ::std::pair<SCTAB, const ScDBData*>& r)
191  {
192  if (meRangeType != ScDBCollection::SheetAnonymous)
193  return;
194 
195  // name
196  OUString aBuf = STR_DB_LOCAL_NONAME +
197  OUString::number(static_cast<sal_Int32>(r.first)); // appended number equals sheet index on import.
198 
199  write(aBuf, *r.second);
200  }
201 
202  void operator() (const ScDBData& rData)
203  {
204  if (meRangeType == ScDBCollection::GlobalAnonymous)
205  {
206  // name
207  OUString aBuf = STR_DB_GLOBAL_NONAME + OUString::number(++mnCounter); // 1-based, for entirely arbitrary reasons. The numbers are ignored on import.
208 
209  write(aBuf, rData);
210  }
211  else if (meRangeType == ScDBCollection::GlobalNamed)
212  write(rData.GetName(), rData);
213  }
214 
215  void operator() (std::unique_ptr<ScDBData> const& p)
216  {
217  return operator()(*p);
218  }
219 
220 private:
221  void write(const OUString& rName, const ScDBData& rData)
222  {
223  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_NAME, rName);
224 
225  // range
226  ScRange aRange;
227  rData.GetArea(aRange);
228  OUString aRangeStr;
230  aRangeStr, aRange, mpDoc, ::formula::FormulaGrammar::CONV_OOO);
231  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_TARGET_RANGE_ADDRESS, aRangeStr);
232 
233  // various boolean flags.
234  if (rData.HasImportSelection())
235  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_IS_SELECTION, XML_TRUE);
236  if (rData.HasAutoFilter())
237  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DISPLAY_FILTER_BUTTONS, XML_TRUE);
238  if (rData.IsKeepFmt())
239  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ON_UPDATE_KEEP_STYLES, XML_TRUE);
240  if (rData.IsDoSize())
241  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ON_UPDATE_KEEP_SIZE, XML_FALSE);
242  if (rData.IsStripData())
243  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_HAS_PERSISTENT_DATA, XML_FALSE);
244 
245  ScQueryParam aQueryParam;
246  rData.GetQueryParam(aQueryParam);
247  if (!aQueryParam.bHasHeader)
248  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CONTAINS_HEADER, XML_FALSE);
249 
250  ScSortParam aSortParam;
251  rData.GetSortParam(aSortParam);
252  if (!aSortParam.bByRow)
253  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ORIENTATION, XML_COLUMN);
254 
255  sal_Int32 nRefreshDelaySeconds = rData.GetRefreshDelaySeconds();
256  if (nRefreshDelaySeconds)
257  {
258  OUStringBuffer aBuf;
260  static_cast<double>(nRefreshDelaySeconds) / 86400.0);
261  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_REFRESH_DELAY, aBuf.makeStringAndClear());
262  }
263 
264  SvXMLElementExport aElemDR(mrExport, XML_NAMESPACE_TABLE, XML_DATABASE_RANGE, true, true);
265 
266  ScSortParam aParam;
267  rData.GetSortParam(aParam);
268 
269  writeImport(rData);
270  writeFilter(rData);
271  writeSort(mrExport, aParam, aRange, mpDoc);
272  writeSubtotals(rData);
273  }
274 
275  void writeImport(const ScDBData& rData)
276  {
277  ScImportParam aParam;
278  rData.GetImportParam(aParam);
279 
280  OUString sDatabaseName;
281  OUString sConRes;
282 
283  svx::ODataAccessDescriptor aDescriptor;
284  aDescriptor.setDataSource(aParam.aDBName);
286  {
287  sDatabaseName = aParam.aDBName;
288  }
290  {
291  sConRes = aParam.aDBName;
292  }
293 
294  sheet::DataImportMode nSourceType = sheet::DataImportMode_NONE;
295  if (aParam.bImport)
296  {
297  if (aParam.bSql)
298  nSourceType = sheet::DataImportMode_SQL;
299  else if (aParam.nType == ScDbQuery)
300  nSourceType = sheet::DataImportMode_QUERY;
301  else
302  nSourceType = sheet::DataImportMode_TABLE;
303  }
304 
305  switch (nSourceType)
306  {
307  case sheet::DataImportMode_NONE : break;
308  case sheet::DataImportMode_QUERY :
309  {
310  if (!sDatabaseName.isEmpty())
311  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATABASE_NAME, sDatabaseName);
312  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_QUERY_NAME, aParam.aStatement);
313  SvXMLElementExport aElemID(mrExport, XML_NAMESPACE_TABLE, XML_DATABASE_SOURCE_QUERY, true, true);
314  if (!sConRes.isEmpty())
315  {
316  mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, sConRes );
317  SvXMLElementExport aElemCR(mrExport, XML_NAMESPACE_FORM, XML_CONNECTION_RESOURCE, true, true);
318  }
319  }
320  break;
321  case sheet::DataImportMode_TABLE :
322  {
323  if (!sDatabaseName.isEmpty())
324  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATABASE_NAME, sDatabaseName);
325  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATABASE_TABLE_NAME, aParam.aStatement);
326  SvXMLElementExport aElemID(mrExport, XML_NAMESPACE_TABLE, XML_DATABASE_SOURCE_TABLE, true, true);
327  if (!sConRes.isEmpty())
328  {
329  mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, sConRes );
330  SvXMLElementExport aElemCR(mrExport, XML_NAMESPACE_FORM, XML_CONNECTION_RESOURCE, true, true);
331  }
332  }
333  break;
334  case sheet::DataImportMode_SQL :
335  {
336  if (!sDatabaseName.isEmpty())
337  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATABASE_NAME, sDatabaseName);
338  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_SQL_STATEMENT, aParam.aStatement);
339  if (!aParam.bNative)
340  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_PARSE_SQL_STATEMENT, XML_TRUE);
341  SvXMLElementExport aElemID(mrExport, XML_NAMESPACE_TABLE, XML_DATABASE_SOURCE_SQL, true, true);
342  if (!sConRes.isEmpty())
343  {
344  mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, sConRes );
345  SvXMLElementExport aElemCR(mrExport, XML_NAMESPACE_FORM, XML_CONNECTION_RESOURCE, true, true);
346  }
347  }
348  break;
349  default:
350  {
351  // added to avoid warnings
352  }
353  }
354  }
355 
356  static OUString getOperatorXML(const ScQueryEntry& rEntry, utl::SearchParam::SearchType eSearchType)
357  {
358  switch (rEntry.eOp)
359  {
360  case SC_BEGINS_WITH:
361  return GetXMLToken(XML_BEGINS_WITH);
362  case SC_BOTPERC:
363  return GetXMLToken(XML_BOTTOM_PERCENT);
364  case SC_BOTVAL:
365  return GetXMLToken(XML_BOTTOM_VALUES);
366  case SC_CONTAINS:
367  return GetXMLToken(XML_CONTAINS);
369  return GetXMLToken(XML_DOES_NOT_BEGIN_WITH);
370  case SC_DOES_NOT_CONTAIN:
371  return GetXMLToken(XML_DOES_NOT_CONTAIN);
373  return GetXMLToken(XML_DOES_NOT_END_WITH);
374  case SC_ENDS_WITH:
375  return GetXMLToken(XML_ENDS_WITH);
376  case SC_EQUAL:
377  {
378  if (rEntry.IsQueryByEmpty())
379  return GetXMLToken(XML_EMPTY);
380  else if (rEntry.IsQueryByNonEmpty())
381  return GetXMLToken(XML_NOEMPTY);
382 
383  if (eSearchType == utl::SearchParam::SearchType::Regexp)
384  return GetXMLToken(XML_MATCH);
385  else
386  return "=";
387  }
388  case SC_GREATER:
389  return ">";
390  case SC_GREATER_EQUAL:
391  return ">=";
392  case SC_LESS:
393  return "<";
394  case SC_LESS_EQUAL:
395  return "<=";
396  case SC_NOT_EQUAL:
397  if (eSearchType == utl::SearchParam::SearchType::Regexp)
398  return GetXMLToken(XML_NOMATCH);
399  else
400  return "!=";
401  case SC_TOPPERC:
402  return GetXMLToken(XML_TOP_PERCENT);
403  case SC_TOPVAL:
404  return GetXMLToken(XML_TOP_VALUES);
405  default:
406  ;
407  }
408  return "=";
409  }
410 
411  class WriteSetItem
412  {
413  ScXMLExport& mrExport;
414  public:
415  explicit WriteSetItem(ScXMLExport& r) : mrExport(r) {}
416  void operator() (const ScQueryEntry::Item& rItem) const
417  {
418  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_VALUE, rItem.maString.getString());
419  SvXMLElementExport aElem(mrExport, XML_NAMESPACE_TABLE, XML_FILTER_SET_ITEM, true, true);
420  }
421  };
422 
423  void writeCondition(const ScQueryEntry& rEntry, SCCOLROW nFieldStart, bool bCaseSens,
424  utl::SearchParam::SearchType eSearchType)
425  {
426  const ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems();
427  if (rItems.empty())
428  {
429  OSL_FAIL("Query entry has no items at all! It must have at least one!");
430  return;
431  }
432 
433  if (rItems.size() == 1)
434  {
435  // Single item condition.
436  const ScQueryEntry::Item& rItem = rItems.front();
437  if (rItem.meType == ScQueryEntry::ByString)
438  {
439  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_VALUE, rItem.maString.getString());
440  }
441  else if (rItem.meType == ScQueryEntry::ByDate)
442  {
443  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_VALUE, rItem.maString.getString());
444  }
445  else if (rItem.meType == ScQueryEntry::ByTextColor
447  {
449  {
450  if (rItem.meType == ScQueryEntry::ByTextColor)
451  mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_DATA_TYPE, XML_TEXT_COLOR);
452  else
453  mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_DATA_TYPE,
454  XML_BACKGROUND_COLOR);
455  }
456 
457  OUString colorValue;
458  if (rItem.maColor == COL_AUTO) // tdf#142965
459  {
460  colorValue = rItem.meType == ScQueryEntry::ByTextColor
461  ? GetXMLToken(XML_WINDOW_FONT_COLOR)
462  : GetXMLToken(XML_TRANSPARENT);
463  }
464  else
465  {
466  OUStringBuffer buffer;
467  sax::Converter::convertColor(buffer, rItem.maColor);
468  colorValue = buffer.makeStringAndClear();
469  }
470  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_VALUE, colorValue);
471  }
472  else
473  {
474  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATA_TYPE, XML_NUMBER);
475  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_VALUE, rItem.maString.getString());
476  }
477 
478  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_OPERATOR, getOperatorXML(rEntry, eSearchType));
479  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FIELD_NUMBER, OUString::number(rEntry.nField - nFieldStart));
480  if (bCaseSens)
481  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CASE_SENSITIVE, XML_TRUE);
482  SvXMLElementExport aElemC(mrExport, XML_NAMESPACE_TABLE, XML_FILTER_CONDITION, true, true);
483  }
484  else
485  {
486  // Multi-item condition.
487  assert( rItems.size() > 1 && "rItems should have more than 1 element");
488 
489  // Store the 1st value for backward compatibility.
490  const ScQueryEntry::Item& rItem = rItems.front();
491  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_VALUE, rItem.maString.getString());
492  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_OPERATOR, OUString("="));
493  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FIELD_NUMBER, OUString::number(rEntry.nField - nFieldStart));
494  if (bCaseSens)
495  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CASE_SENSITIVE, XML_TRUE);
496  SvXMLElementExport aElemC(mrExport, XML_NAMESPACE_TABLE, XML_FILTER_CONDITION, true, true);
497 
498  std::for_each(rItems.begin(), rItems.end(), WriteSetItem(mrExport));
499  }
500  }
501 
502  void writeFilter(const ScDBData& rData)
503  {
504  ScQueryParam aParam;
505  rData.GetQueryParam(aParam);
506  size_t nCount = 0;
507  for (size_t n = aParam.GetEntryCount(); nCount < n; ++nCount)
508  {
509  if (!aParam.GetEntry(nCount).bDoQuery)
510  break;
511  }
512 
513  if (!nCount)
514  // No filter criteria to save. Bail out.
515  return;
516 
517  if (!aParam.bInplace)
518  {
519  OUString aAddrStr;
521  aAddrStr, ScAddress(aParam.nDestCol, aParam.nDestRow, aParam.nDestTab), mpDoc, ::formula::FormulaGrammar::CONV_OOO);
522  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_TARGET_RANGE_ADDRESS, aAddrStr);
523  }
524 
525  ScRange aAdvSource;
526  if (rData.GetAdvancedQuerySource(aAdvSource))
527  {
528  OUString aAddrStr;
530  aAddrStr, aAdvSource, mpDoc, ::formula::FormulaGrammar::CONV_OOO);
531  if (!aAddrStr.isEmpty())
532  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CONDITION_SOURCE_RANGE_ADDRESS, aAddrStr);
533  }
534 
535  if (!aParam.bDuplicate)
536  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DISPLAY_DUPLICATES, XML_FALSE);
537 
538  SvXMLElementExport aElemF(mrExport, XML_NAMESPACE_TABLE, XML_FILTER, true, true);
539 
540  bool bAnd = false;
541  bool bOr = false;
542 
543  for (size_t i = 0; i < nCount; ++i)
544  {
545  const ScQueryEntry& rEntry = aParam.GetEntry(i);
546  if (rEntry.eConnect == SC_AND)
547  bAnd = true;
548  else
549  bOr = true;
550  }
551 
552  // Note that export field index values are relative to the first field.
553  ScRange aRange;
554  rData.GetArea(aRange);
555  SCCOLROW nFieldStart = aParam.bByRow ? aRange.aStart.Col() : aRange.aStart.Row();
556 
557  if (bOr && !bAnd)
558  {
559  SvXMLElementExport aElemOr(mrExport, XML_NAMESPACE_TABLE, XML_FILTER_OR, true, true);
560  for (size_t i = 0; i < nCount; ++i)
561  writeCondition(aParam.GetEntry(i), nFieldStart, aParam.bCaseSens, aParam.eSearchType);
562  }
563  else if (bAnd && !bOr)
564  {
565  SvXMLElementExport aElemAnd(mrExport, XML_NAMESPACE_TABLE, XML_FILTER_AND, true, true);
566  for (size_t i = 0; i < nCount; ++i)
567  writeCondition(aParam.GetEntry(i), nFieldStart, aParam.bCaseSens, aParam.eSearchType);
568  }
569  else if (nCount == 1)
570  {
571  writeCondition(aParam.GetEntry(0), nFieldStart, aParam.bCaseSens, aParam.eSearchType);
572  }
573  else
574  {
575  SvXMLElementExport aElemC(mrExport, XML_NAMESPACE_TABLE, XML_FILTER_OR, true, true);
576  ScQueryEntry aPrevEntry = aParam.GetEntry(0);
577  ScQueryConnect eConnect = aParam.GetEntry(1).eConnect;
578  bool bOpenAndElement = false;
579  OUString aName = mrExport.GetNamespaceMap().GetQNameByKey(XML_NAMESPACE_TABLE, GetXMLToken(XML_FILTER_AND));
580 
581  if (eConnect == SC_AND)
582  {
583  mrExport.StartElement(aName, true);
584  bOpenAndElement = true;
585  }
586  else
587  bOpenAndElement = false;
588 
589  for (size_t i = 1; i < nCount; ++i)
590  {
591  const ScQueryEntry& rEntry = aParam.GetEntry(i);
592  if (eConnect != rEntry.eConnect)
593  {
594  eConnect = rEntry.eConnect;
595  if (rEntry.eConnect == SC_AND)
596  {
597  mrExport.StartElement(aName, true );
598  bOpenAndElement = true;
599  writeCondition(aPrevEntry, nFieldStart, aParam.bCaseSens, aParam.eSearchType);
600  aPrevEntry = rEntry;
601  if (i == nCount - 1)
602  {
603  writeCondition(aPrevEntry, nFieldStart, aParam.bCaseSens, aParam.eSearchType);
604  mrExport.EndElement(aName, true);
605  bOpenAndElement = false;
606  }
607  }
608  else
609  {
610  writeCondition(aPrevEntry, nFieldStart, aParam.bCaseSens, aParam.eSearchType);
611  aPrevEntry = rEntry;
612  if (bOpenAndElement)
613  {
614  mrExport.EndElement(aName, true);
615  bOpenAndElement = false;
616  }
617  if (i == nCount - 1)
618  writeCondition(aPrevEntry, nFieldStart, aParam.bCaseSens, aParam.eSearchType);
619  }
620  }
621  else
622  {
623  writeCondition(aPrevEntry, nFieldStart, aParam.bCaseSens, aParam.eSearchType);
624  aPrevEntry = rEntry;
625  if (i == nCount - 1)
626  writeCondition(aPrevEntry, nFieldStart, aParam.bCaseSens, aParam.eSearchType);
627  }
628  }
629  if(bOpenAndElement)
630  mrExport.EndElement(aName, true);
631  }
632  }
633 
634  void writeSubtotals(const ScDBData& rData)
635  {
636  ScSubTotalParam aParam;
637  rData.GetSubTotalParam(aParam);
638 
639  size_t nCount = 0;
640  for (; nCount < MAXSUBTOTAL; ++nCount)
641  {
642  if (!aParam.bGroupActive[nCount])
643  break;
644  }
645 
646  if (!nCount)
647  return;
648 
649  if (!aParam.bIncludePattern)
650  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_BIND_STYLES_TO_CONTENT, XML_FALSE);
651 
652  if (aParam.bPagebreak)
653  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_PAGE_BREAKS_ON_GROUP_CHANGE, XML_TRUE);
654 
655  if (aParam.bCaseSens)
656  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CASE_SENSITIVE, XML_TRUE);
657 
658  SvXMLElementExport aElemSTRs(mrExport, XML_NAMESPACE_TABLE, XML_SUBTOTAL_RULES, true, true);
659 
660  if (aParam.bDoSort)
661  {
662  if (!aParam.bAscending)
663  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ORDER, XML_DESCENDING);
664 
665  if (aParam.bUserDef)
666  {
667  OUString aBuf = SC_USERLIST + OUString::number(static_cast<sal_Int32>(aParam.nUserIndex));
668  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATA_TYPE, aBuf);
669  }
670  SvXMLElementExport aElemSGs(mrExport, XML_NAMESPACE_TABLE, XML_SORT_GROUPS, true, true);
671  }
672 
673  for (size_t i = 0; i < MAXSUBTOTAL; ++i)
674  {
675  if (!aParam.bGroupActive[i])
676  // We're done!
677  break;
678 
679  sal_Int32 nFieldCol = static_cast<sal_Int32>(aParam.nField[i]);
680  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_GROUP_BY_FIELD_NUMBER, OUString::number(nFieldCol));
681  SvXMLElementExport aElemSTR(mrExport, XML_NAMESPACE_TABLE, XML_SUBTOTAL_RULE, true, true);
682 
683  for (SCCOL j = 0, n = aParam.nSubTotals[i]; j < n; ++j)
684  {
685  sal_Int32 nCol = static_cast<sal_Int32>(aParam.pSubTotals[i][j]);
686  ScSubTotalFunc eFunc = aParam.pFunctions[i][j];
687 
688  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FIELD_NUMBER, OUString::number(nCol));
689  OUString aFuncStr = ScXMLConverter::GetStringFromFunction(eFunc);
690  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FUNCTION, aFuncStr);
691 
692  SvXMLElementExport aElemSTF(mrExport, XML_NAMESPACE_TABLE, XML_SUBTOTAL_FIELD, true, true);
693  }
694  }
695  }
696 };
697 
698 }
699 
701 {
703  if (!pDoc)
704  return;
705 
706  // Get sheet-local anonymous ranges.
707  SCTAB nTabCount = pDoc->GetTableCount();
708  std::map<SCTAB, const ScDBData*> aSheetDBs;
709  for (SCTAB i = 0; i < nTabCount; ++i)
710  {
711  const ScDBData* p = pDoc->GetAnonymousDBData(i);
712  if (p)
713  aSheetDBs.emplace(i, p);
714  }
715 
716  bool bHasRanges = !aSheetDBs.empty();
717 
718  // See if we have global ranges.
719  ScDBCollection* pDBCollection = pDoc->GetDBCollection();
720  if (pDBCollection)
721  {
722  if (!pDBCollection->getNamedDBs().empty() || !pDBCollection->getAnonDBs().empty())
723  bHasRanges = true;
724  }
725 
726  if (!bHasRanges)
727  // No ranges to export. Bail out.
728  return;
729 
731 
732  WriteDatabaseRange func(rExport, pDoc);
733 
734  if (pDBCollection)
735  {
736  // Write global named ranges.
737  func.setRangeType(ScDBCollection::GlobalNamed);
738  const ScDBCollection::NamedDBs& rNamedDBs = pDBCollection->getNamedDBs();
739  ::std::for_each(rNamedDBs.begin(), rNamedDBs.end(), func);
740 
741  // Add global anonymous DB ranges.
742  func.setRangeType(ScDBCollection::GlobalAnonymous);
743  const ScDBCollection::AnonDBs& rAnonDBs = pDBCollection->getAnonDBs();
744  ::std::for_each(rAnonDBs.begin(), rAnonDBs.end(), func);
745  }
746 
747  // Write sheet-local ranges.
748  func.setRangeType(ScDBCollection::SheetAnonymous);
749  ::std::for_each(aSheetDBs.begin(), aSheetDBs.end(), func);
750 }
751 
752 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
::std::vector< ScSortKeyState > maKeyState
Definition: sortparam.hxx:121
bool bGroupActive[MAXSUBTOTAL]
active groups
sal_uInt16 nUserIndex
Definition: sortparam.hxx:110
#define SC_UNONAME_SRCTYPE
Definition: unonames.hxx:292
static OUString GetStringFromFunction(const sal_Int16 eFunction)
bool HasAutoFilter() const
Definition: dbdata.hxx:204
SC_DLLPUBLIC ScDBCollection * GetDBCollection() const
Definition: document.hxx:825
OUString getString() const
SCCOL nField[MAXSUBTOTAL]
associated field
bool bUserDef
sort user defined
ScAddress aStart
Definition: address.hxx:497
XML_FIELD_NUMBER
SC_DLLPUBLIC ScDBData * GetAnonymousDBData(SCTAB nTab)
Definition: document.cxx:308
SCROW Row() const
Definition: address.hxx:274
void setDataSource(const OUString &_sDataSourceNameOrLocation)
OUString aDBName
Definition: global.hxx:444
css::lang::Locale aCollatorLocale
Definition: sortparam.hxx:122
SCCOL nDestCol
Definition: sortparam.hxx:118
static void GetStringFromRange(OUString &rString, const ScRange &rRange, const ScDocument *pDocument, formula::FormulaGrammar::AddressConvention eConv, sal_Unicode cSeparator= ' ', bool bAppendStr=false, ScRefFlags nFormatFlags=ScRefFlags::VALID|ScRefFlags::TAB_3D)
bool empty() const
Definition: dbdata.cxx:1324
SC_DLLPUBLIC void GetSortParam(ScSortParam &rSortParam) const
Definition: dbdata.cxx:401
void CheckAttrList()
XML_DESCENDING
XML_SORT_BY
sal_Int64 n
QueryItemsType & GetQueryItems()
Definition: queryentry.hxx:75
ScMySharedData * GetSharedData()
Definition: xmlexprt.hxx:257
aBuf
SCCOLROW nField
Definition: queryentry.hxx:61
bool bDoSort
presort
bool IsQueryByEmpty() const
Definition: queryentry.cxx:87
bool bPagebreak
page break at change of group
XML_DATA_TYPE
XML_AUTOMATIC
bool IsDoSize() const
Definition: dbdata.hxx:136
static void GetStringFromAddress(OUString &rString, const ScAddress &rAddress, const ScDocument *pDocument, formula::FormulaGrammar::AddressConvention eConv, sal_Unicode cSeparator= ' ', bool bAppendStr=false, ScRefFlags nFormatFlags=ScRefFlags::VALID|ScRefFlags::TAB_3D)
Range to String core.
const css::uno::Reference< css::frame::XModel > & GetModel() const
sal_uInt16 nUserIndex
index into list
sal_Int32 SCCOLROW
a type capable of holding either SCCOL or SCROW
Definition: types.hxx:23
SC_DLLPUBLIC SCTAB GetTableCount() const
Definition: document.cxx:315
AnonDBs & getAnonDBs()
Definition: dbdata.hxx:319
void AddLanguageTagAttributes(sal_uInt16 nPrefix, sal_uInt16 nPrefixRfc, const css::lang::Locale &rLocale, bool bWriteEmpty)
XML_ORDER
int nCount
void AddAttribute(sal_uInt16 nPrefix, const OUString &rName, const OUString &rValue)
SC_DLLPUBLIC SCSIZE GetEntryCount() const
Definition: queryparam.cxx:110
void StartElement(sal_uInt16 nPrefix, enum::xmloff::token::XMLTokenEnum eName, bool bIgnWSOutside)
SC_DLLPUBLIC const ScQueryEntry & GetEntry(SCSIZE n) const
Definition: queryparam.cxx:115
XML_SORT
void writeSort(ScXMLExport &mrExport, const ScSortParam &aParam, const ScRange &aRange, const ScDocument *mpDoc)
Stores global anonymous database ranges.
Definition: dbdata.hxx:276
ScXMLExportDatabaseRanges(ScXMLExport &rExport)
SvtSaveOptions::ODFSaneDefaultVersion getSaneDefaultVersion() const
OUString aStatement
Definition: global.hxx:445
constexpr OUStringLiteral SC_USERLIST
not found in unonames.hxx
XML_ALGORITHM
SCCOL nSubTotals[MAXSUBTOTAL]
number of SubTotals
int i
bool IsQueryByNonEmpty() const
Definition: queryentry.cxx:109
sal_Int16 SCCOL
Definition: types.hxx:21
bool bNative
Definition: global.hxx:446
constexpr OUStringLiteral STR_DB_GLOBAL_NONAME
Definition: globalnames.hxx:15
float u
const OUString & GetName() const
Definition: dbdata.hxx:121
void GetImportParam(ScImportParam &rImportParam) const
Definition: dbdata.cxx:480
static bool convertColor(sal_Int32 &rColor, std::u16string_view rValue)
bool IsKeepFmt() const
Definition: dbdata.hxx:138
std::unique_ptr< ScSubTotalFunc[]> pFunctions[MAXSUBTOTAL]
array of associated functions
static void convertDuration(OUStringBuffer &rBuffer, const double fTime)
bool bCaseSens
Definition: sortparam.hxx:113
sal_Int32 GetRefreshDelaySeconds() const
XML_TARGET_RANGE_ADDRESS
OUString GetQNameByKey(sal_uInt16 nKey, const OUString &rLocalName, bool bCache=true) const
constexpr OUStringLiteral STR_DB_LOCAL_NONAME
Definition: globalnames.hxx:14
void GetArea(SCTAB &rTab, SCCOL &rCol1, SCROW &rRow1, SCCOL &rCol2, SCROW &rRow2) const
Definition: dbdata.cxx:300
bool IsStripData() const
Definition: dbdata.hxx:140
svl::SharedString maString
Definition: queryentry.hxx:49
const SvXMLNamespaceMap & GetNamespaceMap() const
ScDataAreaExtras aDataAreaExtras
Definition: sortparam.hxx:109
SCCOL Col() const
Definition: address.hxx:279
void GetSubTotalParam(ScSubTotalParam &rSubTotalParam) const
Definition: dbdata.cxx:463
XML_TRUE
void AddNewEmptyDatabaseRange(const css::table::CellRangeAddress &aCellRangeAddress)
Stores global named database ranges.
Definition: dbdata.hxx:234
XML_DATABASE_RANGES
ScDocument * GetDocument()
Definition: xmlexprt.hxx:240
bool mbCellFormats
If TRUE, consider the presence of cell formats.
Definition: sortparam.hxx:50
XML_FALSE
constexpr sal_uInt16 XML_NAMESPACE_TABLE
void EndElement(sal_uInt16 nPrefix, enum::xmloff::token::XMLTokenEnum eName, bool bIgnWSInside)
bool has(DataAccessDescriptorProperty _eWhich) const
sal_uInt8 nType
Definition: global.hxx:448
const OUString & GetXMLToken(enum XMLTokenEnum eToken)
void SetLastRow(const sal_Int32 nTable, const sal_Int32 nRow)
sal_uInt16 GetSortKeyCount() const
Definition: sortparam.hxx:139
void SetLastColumn(const sal_Int32 nTable, const sal_Int32 nCol)
OUString aName
XML_CASE_SENSITIVE
bool bIncludePattern
sort formats
ScMyEmptyDatabaseRangesContainer GetEmptyDatabaseRanges()
void * p
bool empty() const
Definition: dbdata.cxx:1243
SC_DLLPUBLIC void GetQueryParam(ScQueryParam &rQueryParam) const
Definition: dbdata.cxx:424
bool HasImportSelection() const
Definition: dbdata.hxx:201
ScQueryConnect eConnect
Definition: queryentry.hxx:63
OUString aCollatorAlgorithm
Definition: sortparam.hxx:123
bool bImport
Definition: global.hxx:443
#define SC_UNO_DATABASERNG
Definition: unonames.hxx:43
NamedDBs & getNamedDBs()
Definition: dbdata.hxx:316
std::vector< Item > QueryItemsType
Definition: queryentry.hxx:58
XML_BIND_STYLES_TO_CONTENT
SC_DLLPUBLIC bool GetAdvancedQuerySource(ScRange &rSource) const
Definition: dbdata.cxx:457
SCROW nDestRow
Definition: sortparam.hxx:119
XML_TRANSPARENT
ScSubTotalFunc
Definition: global.hxx:843
std::unique_ptr< SCCOL[]> pSubTotals[MAXSUBTOTAL]
array of columns to be calculated
ScQueryOp eOp
Definition: queryentry.hxx:62
aStr
bool bAscending
sort ascending
Each instance of this struct represents a single filtering criteria.
Definition: queryentry.hxx:33
utl::SearchParam::SearchType eSearchType
Definition: queryparam.hxx:43
sal_Int16 SCTAB
Definition: types.hxx:22
const SCSIZE MAXSUBTOTAL
Definition: global.hxx:81
ScQueryConnect
Definition: global.hxx:837
SCTAB nDestTab
Definition: sortparam.hxx:117
#define SC_UNONAME_STRIPDAT
Definition: unonames.hxx:293