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