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/xmlnmspe.hxx>
24 #include <xmloff/nmspmap.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  OUStringBuffer aBuf;
212  aBuf.append(STR_DB_GLOBAL_NONAME);
213  aBuf.append(++mnCounter); // 1-based, for entirely arbitrary reasons. The numbers are ignored on import.
214 
215  write(aBuf.makeStringAndClear(), rData);
216  }
217  else if (meRangeType == ScDBCollection::GlobalNamed)
218  write(rData.GetName(), rData);
219  }
220 
221  void operator() (std::unique_ptr<ScDBData> const& p)
222  {
223  return operator()(*p);
224  }
225 
226 private:
227  void write(const OUString& rName, const ScDBData& rData)
228  {
229  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_NAME, rName);
230 
231  // range
232  ScRange aRange;
233  rData.GetArea(aRange);
234  OUString aRangeStr;
236  aRangeStr, aRange, mpDoc, ::formula::FormulaGrammar::CONV_OOO);
237  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_TARGET_RANGE_ADDRESS, aRangeStr);
238 
239  // various boolean flags.
240  if (rData.HasImportSelection())
241  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_IS_SELECTION, XML_TRUE);
242  if (rData.HasAutoFilter())
243  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DISPLAY_FILTER_BUTTONS, XML_TRUE);
244  if (rData.IsKeepFmt())
245  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ON_UPDATE_KEEP_STYLES, XML_TRUE);
246  if (rData.IsDoSize())
247  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ON_UPDATE_KEEP_SIZE, XML_FALSE);
248  if (rData.IsStripData())
249  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_HAS_PERSISTENT_DATA, XML_FALSE);
250 
251  ScQueryParam aQueryParam;
252  rData.GetQueryParam(aQueryParam);
253  if (!aQueryParam.bHasHeader)
254  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CONTAINS_HEADER, XML_FALSE);
255 
256  ScSortParam aSortParam;
257  rData.GetSortParam(aSortParam);
258  if (!aSortParam.bByRow)
259  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ORIENTATION, XML_COLUMN);
260 
261  sal_Int32 nRefresh = rData.GetRefreshDelay();
262  if (nRefresh)
263  {
264  OUStringBuffer aBuf;
266  static_cast<double>(nRefresh) / 86400.0);
267  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_REFRESH_DELAY, aBuf.makeStringAndClear());
268  }
269 
270  SvXMLElementExport aElemDR(mrExport, XML_NAMESPACE_TABLE, XML_DATABASE_RANGE, true, true);
271 
272  ScSortParam aParam;
273  rData.GetSortParam(aParam);
274 
275  writeImport(rData);
276  writeFilter(rData);
277  writeSort(mrExport, aParam, aRange, mpDoc);
278  writeSubtotals(rData);
279  }
280 
281  void writeImport(const ScDBData& rData)
282  {
283  ScImportParam aParam;
284  rData.GetImportParam(aParam);
285 
286  OUString sDatabaseName;
287  OUString sConRes;
288 
289  svx::ODataAccessDescriptor aDescriptor;
290  aDescriptor.setDataSource(aParam.aDBName);
292  {
293  sDatabaseName = aParam.aDBName;
294  }
296  {
297  sConRes = aParam.aDBName;
298  }
299 
300  sheet::DataImportMode nSourceType = sheet::DataImportMode_NONE;
301  if (aParam.bImport)
302  {
303  if (aParam.bSql)
304  nSourceType = sheet::DataImportMode_SQL;
305  else if (aParam.nType == ScDbQuery)
306  nSourceType = sheet::DataImportMode_QUERY;
307  else
308  nSourceType = sheet::DataImportMode_TABLE;
309  }
310 
311  switch (nSourceType)
312  {
313  case sheet::DataImportMode_NONE : break;
314  case sheet::DataImportMode_QUERY :
315  {
316  if (!sDatabaseName.isEmpty())
317  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATABASE_NAME, sDatabaseName);
318  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_QUERY_NAME, aParam.aStatement);
319  SvXMLElementExport aElemID(mrExport, XML_NAMESPACE_TABLE, XML_DATABASE_SOURCE_QUERY, true, true);
320  if (!sConRes.isEmpty())
321  {
322  mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, sConRes );
323  SvXMLElementExport aElemCR(mrExport, XML_NAMESPACE_FORM, XML_CONNECTION_RESOURCE, true, true);
324  }
325  }
326  break;
327  case sheet::DataImportMode_TABLE :
328  {
329  if (!sDatabaseName.isEmpty())
330  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATABASE_NAME, sDatabaseName);
331  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATABASE_TABLE_NAME, aParam.aStatement);
332  SvXMLElementExport aElemID(mrExport, XML_NAMESPACE_TABLE, XML_DATABASE_SOURCE_TABLE, true, true);
333  if (!sConRes.isEmpty())
334  {
335  mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, sConRes );
336  SvXMLElementExport aElemCR(mrExport, XML_NAMESPACE_FORM, XML_CONNECTION_RESOURCE, true, true);
337  }
338  }
339  break;
340  case sheet::DataImportMode_SQL :
341  {
342  if (!sDatabaseName.isEmpty())
343  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATABASE_NAME, sDatabaseName);
344  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_SQL_STATEMENT, aParam.aStatement);
345  if (!aParam.bNative)
346  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_PARSE_SQL_STATEMENT, XML_TRUE);
347  SvXMLElementExport aElemID(mrExport, XML_NAMESPACE_TABLE, XML_DATABASE_SOURCE_SQL, true, true);
348  if (!sConRes.isEmpty())
349  {
350  mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, sConRes );
351  SvXMLElementExport aElemCR(mrExport, XML_NAMESPACE_FORM, XML_CONNECTION_RESOURCE, true, true);
352  }
353  }
354  break;
355  default:
356  {
357  // added to avoid warnings
358  }
359  }
360  }
361 
362  static OUString getOperatorXML(const ScQueryEntry& rEntry, utl::SearchParam::SearchType eSearchType)
363  {
364  switch (rEntry.eOp)
365  {
366  case SC_BEGINS_WITH:
367  return GetXMLToken(XML_BEGINS_WITH);
368  case SC_BOTPERC:
369  return GetXMLToken(XML_BOTTOM_PERCENT);
370  case SC_BOTVAL:
371  return GetXMLToken(XML_BOTTOM_VALUES);
372  case SC_CONTAINS:
373  return GetXMLToken(XML_CONTAINS);
375  return GetXMLToken(XML_DOES_NOT_BEGIN_WITH);
376  case SC_DOES_NOT_CONTAIN:
377  return GetXMLToken(XML_DOES_NOT_CONTAIN);
379  return GetXMLToken(XML_DOES_NOT_END_WITH);
380  case SC_ENDS_WITH:
381  return GetXMLToken(XML_ENDS_WITH);
382  case SC_EQUAL:
383  {
384  if (rEntry.IsQueryByEmpty())
385  return GetXMLToken(XML_EMPTY);
386  else if (rEntry.IsQueryByNonEmpty())
387  return GetXMLToken(XML_NOEMPTY);
388 
389  if (eSearchType == utl::SearchParam::SearchType::Regexp)
390  return GetXMLToken(XML_MATCH);
391  else
392  return "=";
393  }
394  case SC_GREATER:
395  return ">";
396  case SC_GREATER_EQUAL:
397  return ">=";
398  case SC_LESS:
399  return "<";
400  case SC_LESS_EQUAL:
401  return "<=";
402  case SC_NOT_EQUAL:
403  if (eSearchType == utl::SearchParam::SearchType::Regexp)
404  return GetXMLToken(XML_NOMATCH);
405  else
406  return "!=";
407  case SC_TOPPERC:
408  return GetXMLToken(XML_TOP_PERCENT);
409  case SC_TOPVAL:
410  return GetXMLToken(XML_TOP_VALUES);
411  default:
412  ;
413  }
414  return "=";
415  }
416 
417  class WriteSetItem
418  {
419  ScXMLExport& mrExport;
420  public:
421  explicit WriteSetItem(ScXMLExport& r) : mrExport(r) {}
422  void operator() (const ScQueryEntry::Item& rItem) const
423  {
424  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_VALUE, rItem.maString.getString());
425  SvXMLElementExport aElem(mrExport, XML_NAMESPACE_TABLE, XML_FILTER_SET_ITEM, true, true);
426  }
427  };
428 
429  void writeCondition(const ScQueryEntry& rEntry, SCCOLROW nFieldStart, bool bCaseSens,
430  utl::SearchParam::SearchType eSearchType)
431  {
432  const ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems();
433  if (rItems.empty())
434  {
435  OSL_FAIL("Query entry has no items at all! It must have at least one!");
436  return;
437  }
438 
439  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FIELD_NUMBER, OUString::number(rEntry.nField - nFieldStart));
440  if (bCaseSens)
441  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CASE_SENSITIVE, XML_TRUE);
442 
443  if (rItems.size() == 1)
444  {
445  // Single item condition.
446  const ScQueryEntry::Item& rItem = rItems.front();
447  if (rItem.meType == ScQueryEntry::ByString)
448  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_VALUE, rItem.maString.getString());
449  else
450  {
451  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATA_TYPE, XML_NUMBER);
452  OUStringBuffer aBuf;
454  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_VALUE, aBuf.makeStringAndClear());
455  }
456 
457  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_OPERATOR, getOperatorXML(rEntry, eSearchType));
458  SvXMLElementExport aElemC(mrExport, XML_NAMESPACE_TABLE, XML_FILTER_CONDITION, true, true);
459  }
460  else
461  {
462  // Multi-item condition.
463  assert( rItems.size() > 1 && "rItems should have more than 1 element");
464 
465  // Store the 1st value for backward compatibility.
466  const ScQueryEntry::Item& rItem = rItems.front();
467  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_VALUE, rItem.maString.getString());
468  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_OPERATOR, OUString("="));
469  SvXMLElementExport aElemC(mrExport, XML_NAMESPACE_TABLE, XML_FILTER_CONDITION, true, true);
470 
471  std::for_each(rItems.begin(), rItems.end(), WriteSetItem(mrExport));
472  }
473  }
474 
475  void writeFilter(const ScDBData& rData)
476  {
477  ScQueryParam aParam;
478  rData.GetQueryParam(aParam);
479  size_t nCount = 0;
480  for (size_t n = aParam.GetEntryCount(); nCount < n; ++nCount)
481  {
482  if (!aParam.GetEntry(nCount).bDoQuery)
483  break;
484  }
485 
486  if (!nCount)
487  // No filter criteria to save. Bail out.
488  return;
489 
490  if (!aParam.bInplace)
491  {
492  OUString aAddrStr;
494  aAddrStr, ScAddress(aParam.nDestCol, aParam.nDestRow, aParam.nDestTab), mpDoc, ::formula::FormulaGrammar::CONV_OOO);
495  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_TARGET_RANGE_ADDRESS, aAddrStr);
496  }
497 
498  ScRange aAdvSource;
499  if (rData.GetAdvancedQuerySource(aAdvSource))
500  {
501  OUString aAddrStr;
503  aAddrStr, aAdvSource, mpDoc, ::formula::FormulaGrammar::CONV_OOO);
504  if (!aAddrStr.isEmpty())
505  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CONDITION_SOURCE_RANGE_ADDRESS, aAddrStr);
506  }
507 
508  if (!aParam.bDuplicate)
509  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DISPLAY_DUPLICATES, XML_FALSE);
510 
511  SvXMLElementExport aElemF(mrExport, XML_NAMESPACE_TABLE, XML_FILTER, true, true);
512 
513  bool bAnd = false;
514  bool bOr = false;
515 
516  for (size_t i = 0; i < nCount; ++i)
517  {
518  const ScQueryEntry& rEntry = aParam.GetEntry(i);
519  if (rEntry.eConnect == SC_AND)
520  bAnd = true;
521  else
522  bOr = true;
523  }
524 
525  // Note that export field index values are relative to the first field.
526  ScRange aRange;
527  rData.GetArea(aRange);
528  SCCOLROW nFieldStart = aParam.bByRow ? aRange.aStart.Col() : aRange.aStart.Row();
529 
530  if (bOr && !bAnd)
531  {
532  SvXMLElementExport aElemOr(mrExport, XML_NAMESPACE_TABLE, XML_FILTER_OR, true, true);
533  for (size_t i = 0; i < nCount; ++i)
534  writeCondition(aParam.GetEntry(i), nFieldStart, aParam.bCaseSens, aParam.eSearchType);
535  }
536  else if (bAnd && !bOr)
537  {
538  SvXMLElementExport aElemAnd(mrExport, XML_NAMESPACE_TABLE, XML_FILTER_AND, true, true);
539  for (size_t i = 0; i < nCount; ++i)
540  writeCondition(aParam.GetEntry(i), nFieldStart, aParam.bCaseSens, aParam.eSearchType);
541  }
542  else if (nCount == 1)
543  {
544  writeCondition(aParam.GetEntry(0), nFieldStart, aParam.bCaseSens, aParam.eSearchType);
545  }
546  else
547  {
548  SvXMLElementExport aElemC(mrExport, XML_NAMESPACE_TABLE, XML_FILTER_OR, true, true);
549  ScQueryEntry aPrevEntry = aParam.GetEntry(0);
550  ScQueryConnect eConnect = aParam.GetEntry(1).eConnect;
551  bool bOpenAndElement = false;
552  OUString aName = mrExport.GetNamespaceMap().GetQNameByKey(XML_NAMESPACE_TABLE, GetXMLToken(XML_FILTER_AND));
553 
554  if (eConnect == SC_AND)
555  {
556  mrExport.StartElement(aName, true);
557  bOpenAndElement = true;
558  }
559  else
560  bOpenAndElement = false;
561 
562  for (size_t i = 1; i < nCount; ++i)
563  {
564  const ScQueryEntry& rEntry = aParam.GetEntry(i);
565  if (eConnect != rEntry.eConnect)
566  {
567  eConnect = rEntry.eConnect;
568  if (rEntry.eConnect == SC_AND)
569  {
570  mrExport.StartElement(aName, true );
571  bOpenAndElement = true;
572  writeCondition(aPrevEntry, nFieldStart, aParam.bCaseSens, aParam.eSearchType);
573  aPrevEntry = rEntry;
574  if (i == nCount - 1)
575  {
576  writeCondition(aPrevEntry, nFieldStart, aParam.bCaseSens, aParam.eSearchType);
577  mrExport.EndElement(aName, true);
578  bOpenAndElement = false;
579  }
580  }
581  else
582  {
583  writeCondition(aPrevEntry, nFieldStart, aParam.bCaseSens, aParam.eSearchType);
584  aPrevEntry = rEntry;
585  if (bOpenAndElement)
586  {
587  mrExport.EndElement(aName, true);
588  bOpenAndElement = false;
589  }
590  if (i == nCount - 1)
591  writeCondition(aPrevEntry, nFieldStart, aParam.bCaseSens, aParam.eSearchType);
592  }
593  }
594  else
595  {
596  writeCondition(aPrevEntry, nFieldStart, aParam.bCaseSens, aParam.eSearchType);
597  aPrevEntry = rEntry;
598  if (i == nCount - 1)
599  writeCondition(aPrevEntry, nFieldStart, aParam.bCaseSens, aParam.eSearchType);
600  }
601  }
602  if(bOpenAndElement)
603  mrExport.EndElement(aName, true);
604  }
605  }
606 
607  void writeSubtotals(const ScDBData& rData)
608  {
609  ScSubTotalParam aParam;
610  rData.GetSubTotalParam(aParam);
611 
612  size_t nCount = 0;
613  for (; nCount < MAXSUBTOTAL; ++nCount)
614  {
615  if (!aParam.bGroupActive[nCount])
616  break;
617  }
618 
619  if (!nCount)
620  return;
621 
622  if (!aParam.bIncludePattern)
623  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_BIND_STYLES_TO_CONTENT, XML_FALSE);
624 
625  if (aParam.bPagebreak)
626  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_PAGE_BREAKS_ON_GROUP_CHANGE, XML_TRUE);
627 
628  if (aParam.bCaseSens)
629  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CASE_SENSITIVE, XML_TRUE);
630 
631  SvXMLElementExport aElemSTRs(mrExport, XML_NAMESPACE_TABLE, XML_SUBTOTAL_RULES, true, true);
632 
633  if (aParam.bDoSort)
634  {
635  if (!aParam.bAscending)
636  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ORDER, XML_DESCENDING);
637 
638  if (aParam.bUserDef)
639  {
640  OUString aBuf = SC_USERLIST + OUString::number(static_cast<sal_Int32>(aParam.nUserIndex));
641  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATA_TYPE, aBuf);
642  }
643  SvXMLElementExport aElemSGs(mrExport, XML_NAMESPACE_TABLE, XML_SORT_GROUPS, true, true);
644  }
645 
646  for (size_t i = 0; i < MAXSUBTOTAL; ++i)
647  {
648  if (!aParam.bGroupActive[i])
649  // We're done!
650  break;
651 
652  sal_Int32 nFieldCol = static_cast<sal_Int32>(aParam.nField[i]);
653  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_GROUP_BY_FIELD_NUMBER, OUString::number(nFieldCol));
654  SvXMLElementExport aElemSTR(mrExport, XML_NAMESPACE_TABLE, XML_SUBTOTAL_RULE, true, true);
655 
656  for (SCCOL j = 0, n = aParam.nSubTotals[i]; j < n; ++j)
657  {
658  sal_Int32 nCol = static_cast<sal_Int32>(aParam.pSubTotals[i][j]);
659  ScSubTotalFunc eFunc = aParam.pFunctions[i][j];
660 
661  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FIELD_NUMBER, OUString::number(nCol));
662  OUString aFuncStr;
663  ScXMLConverter::GetStringFromFunction(aFuncStr, eFunc);
664  mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FUNCTION, aFuncStr);
665 
666  SvXMLElementExport aElemSTF(mrExport, XML_NAMESPACE_TABLE, XML_SUBTOTAL_FIELD, true, true);
667  }
668  }
669  }
670 };
671 
672 }
673 
675 {
677  if (!pDoc)
678  return;
679 
680  // Get sheet-local anonymous ranges.
681  SCTAB nTabCount = pDoc->GetTableCount();
682  std::map<SCTAB, const ScDBData*> aSheetDBs;
683  for (SCTAB i = 0; i < nTabCount; ++i)
684  {
685  const ScDBData* p = pDoc->GetAnonymousDBData(i);
686  if (p)
687  aSheetDBs.emplace(i, p);
688  }
689 
690  bool bHasRanges = !aSheetDBs.empty();
691 
692  // See if we have global ranges.
693  ScDBCollection* pDBCollection = pDoc->GetDBCollection();
694  if (pDBCollection)
695  {
696  if (!pDBCollection->getNamedDBs().empty() || !pDBCollection->getAnonDBs().empty())
697  bHasRanges = true;
698  }
699 
700  if (!bHasRanges)
701  // No ranges to export. Bail out.
702  return;
703 
705 
706  WriteDatabaseRange func(rExport, pDoc);
707 
708  if (pDBCollection)
709  {
710  // Write global named ranges.
711  func.setRangeType(ScDBCollection::GlobalNamed);
712  const ScDBCollection::NamedDBs& rNamedDBs = pDBCollection->getNamedDBs();
713  ::std::for_each(rNamedDBs.begin(), rNamedDBs.end(), func);
714 
715  // Add global anonymous DB ranges.
716  func.setRangeType(ScDBCollection::GlobalAnonymous);
717  const ScDBCollection::AnonDBs& rAnonDBs = pDBCollection->getAnonDBs();
718  ::std::for_each(rAnonDBs.begin(), rAnonDBs.end(), func);
719  }
720 
721  // Write sheet-local ranges.
722  func.setRangeType(ScDBCollection::SheetAnonymous);
723  ::std::for_each(aSheetDBs.begin(), aSheetDBs.end(), func);
724 }
725 
726 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
::std::vector< ScSortKeyState > maKeyState
Definition: sortparam.hxx:61
bool bGroupActive[MAXSUBTOTAL]
active groups
sal_uInt16 nUserIndex
Definition: sortparam.hxx:47
#define SC_UNONAME_SRCTYPE
Definition: unonames.hxx:291
bool HasAutoFilter() const
Definition: dbdata.hxx:204
SC_DLLPUBLIC ScDBCollection * GetDBCollection() const
Definition: document.hxx:819
OUString getString() const
SCCOL nField[MAXSUBTOTAL]
associated field
bool bUserDef
sort user defined
ScAddress aStart
Definition: address.hxx:500
SC_DLLPUBLIC ScDBData * GetAnonymousDBData(SCTAB nTab)
Definition: document.cxx:306
SCROW Row() const
Definition: address.hxx:262
void setDataSource(const OUString &_sDataSourceNameOrLocation)
OUString aDBName
Definition: global.hxx:455
css::lang::Locale aCollatorLocale
Definition: sortparam.hxx:62
SCCOL nDestCol
Definition: sortparam.hxx:58
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:1262
void GetSortParam(ScSortParam &rSortParam) const
Definition: dbdata.cxx:387
XML_FIELD_NUMBER
XML_ORDER
void CheckAttrList()
#define STR_DB_LOCAL_NONAME
Definition: globalnames.hxx:13
sal_Int64 n
QueryItemsType & GetQueryItems()
Definition: queryentry.hxx:65
ScMySharedData * GetSharedData()
Definition: xmlexprt.hxx:257
aBuf
#define SC_USERLIST
not found in unonames.hxx
SCCOLROW nField
Definition: queryentry.hxx:51
bool bDoSort
presort
XML_BIND_STYLES_TO_CONTENT
XML_ALGORITHM
bool IsQueryByEmpty() const
Definition: queryentry.cxx:84
bool bPagebreak
page break at change of group
bool IsDoSize() const
Definition: dbdata.hxx:136
bool bUserDef
Definition: sortparam.hxx:54
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
static void convertDouble(OUStringBuffer &rBuffer, double fNumber, bool bWriteUnits, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit)
const css::uno::Reference< css::frame::XModel > & GetModel() const
sal_uInt16 nUserIndex
index into list
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
sal_Int32 SCCOLROW
a type capable of holding either SCCOL or SCROW
Definition: types.hxx:24
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
SCCOL * pSubTotals[MAXSUBTOTAL]
array of columns to be calculated
Stores global anonymous database ranges.
Definition: dbdata.hxx:276
ScXMLExportDatabaseRanges(ScXMLExport &rExport)
OUString aStatement
Definition: global.hxx:456
XML_SORT_BY
ScSubTotalFunc * pFunctions[MAXSUBTOTAL]
array of associated functions
XML_DATABASE_RANGES
SCCOL nSubTotals[MAXSUBTOTAL]
number of SubTotals
int i
bool IsQueryByNonEmpty() const
Definition: queryentry.cxx:106
sal_Int16 SCCOL
Definition: types.hxx:22
bool bNative
Definition: global.hxx:457
const OUString & GetName() const
Definition: dbdata.hxx:122
void GetImportParam(ScImportParam &rImportParam) const
Definition: dbdata.cxx:466
bool IsKeepFmt() const
Definition: dbdata.hxx:138
static void convertDuration(OUStringBuffer &rBuffer, const double fTime)
bool bCaseSens
Definition: sortparam.hxx:50
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:301
bool IsStripData() const
Definition: dbdata.hxx:140
svl::SharedString maString
Definition: queryentry.hxx:41
const SvXMLNamespaceMap & GetNamespaceMap() const
SCCOL Col() const
Definition: address.hxx:267
void GetSubTotalParam(ScSubTotalParam &rSubTotalParam) const
Definition: dbdata.cxx:449
XML_DATA_TYPE
void AddNewEmptyDatabaseRange(const css::table::CellRangeAddress &aCellRangeAddress)
Stores global named database ranges.
Definition: dbdata.hxx:235
ScDocument * GetDocument()
Definition: xmlexprt.hxx:240
bool bInplace
Definition: sortparam.hxx:56
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)
constexpr sal_uInt16 XML_NAMESPACE_TABLE
#define STR_DB_GLOBAL_NONAME
Definition: globalnames.hxx:14
sal_uInt16 GetSortKeyCount() const
Definition: sortparam.hxx:79
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:1186
XML_TARGET_RANGE_ADDRESS
SC_DLLPUBLIC void GetQueryParam(ScQueryParam &rQueryParam) const
Definition: dbdata.cxx:410
bool HasImportSelection() const
Definition: dbdata.hxx:201
ScQueryConnect eConnect
Definition: queryentry.hxx:53
OUString aCollatorAlgorithm
Definition: sortparam.hxx:63
bool bImport
Definition: global.hxx:454
#define SC_UNO_DATABASERNG
Definition: unonames.hxx:42
NamedDBs & getNamedDBs()
Definition: dbdata.hxx:315
XML_TRUE
std::vector< Item > QueryItemsType
Definition: queryentry.hxx:48
static void GetStringFromFunction(OUString &rString, const sal_Int16 eFunction)
SC_DLLPUBLIC bool GetAdvancedQuerySource(ScRange &rSource) const
Definition: dbdata.cxx:443
SCROW nDestRow
Definition: sortparam.hxx:59
ScSubTotalFunc
Definition: global.hxx:848
bool bIncludePattern
Definition: sortparam.hxx:55
ScQueryOp eOp
Definition: queryentry.hxx:52
css::uno::Any const SvXMLExport & rExport
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:44
sal_Int16 SCTAB
Definition: types.hxx:23
const SCSIZE MAXSUBTOTAL
Definition: global.hxx:78
ScQueryConnect
Definition: global.hxx:842
SCTAB nDestTab
Definition: sortparam.hxx:57
#define SC_UNONAME_STRIPDAT
Definition: unonames.hxx:292