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>
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>
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>
48#include <osl/diagnose.h>
49
50#include <map>
51
53constexpr OUStringLiteral SC_USERLIST = u"UserList";
54
55using namespace com::sun::star;
56using namespace xmloff::token;
57
58void 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
76
77 if (!aParam.bInplace)
78 {
79 OUString aStr;
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
172namespace {
173
174class WriteDatabaseRange
175{
176 ScXMLExport& mrExport;
177 ScDocument* mpDoc;
178 sal_Int32 mnCounter;
179 ScDBCollection::RangeType meRangeType;
180public:
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
220private:
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);
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,
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 {
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)
463 }
464 else
465 {
466 OUStringBuffer buffer;
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 {
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: */
void writeSort(ScXMLExport &mrExport, const ScSortParam &aParam, const ScRange &aRange, const ScDocument *mpDoc)
constexpr OUStringLiteral SC_USERLIST
not found in unonames.hxx
SCROW Row() const
Definition: address.hxx:274
SCCOL Col() const
Definition: address.hxx:279
Stores global anonymous database ranges.
Definition: dbdata.hxx:285
bool empty() const
Definition: dbdata.cxx:1349
Stores global named database ranges.
Definition: dbdata.hxx:243
NamedDBs & getNamedDBs()
Definition: dbdata.hxx:324
AnonDBs & getAnonDBs()
Definition: dbdata.hxx:327
bool IsDoSize() const
Definition: dbdata.hxx:142
void GetImportParam(ScImportParam &rImportParam) const
Definition: dbdata.cxx:478
bool HasAutoFilter() const
Definition: dbdata.hxx:212
const OUString & GetName() const
Definition: dbdata.hxx:127
void GetArea(SCTAB &rTab, SCCOL &rCol1, SCROW &rRow1, SCCOL &rCol2, SCROW &rRow2) const
Definition: dbdata.cxx:298
SC_DLLPUBLIC bool GetAdvancedQuerySource(ScRange &rSource) const
Definition: dbdata.cxx:455
SC_DLLPUBLIC void GetSortParam(ScSortParam &rSortParam) const
Definition: dbdata.cxx:399
bool IsStripData() const
Definition: dbdata.hxx:146
SC_DLLPUBLIC void GetQueryParam(ScQueryParam &rQueryParam) const
Definition: dbdata.cxx:422
bool HasImportSelection() const
Definition: dbdata.hxx:209
bool IsKeepFmt() const
Definition: dbdata.hxx:144
void GetSubTotalParam(ScSubTotalParam &rSubTotalParam) const
Definition: dbdata.cxx:461
SC_DLLPUBLIC ScDBCollection * GetDBCollection() const
Definition: document.hxx:827
SC_DLLPUBLIC ScDBData * GetAnonymousDBData(SCTAB nTab)
Definition: document.cxx:290
SC_DLLPUBLIC SCTAB GetTableCount() const
Definition: document.cxx:297
void AddNewEmptyDatabaseRange(const css::table::CellRangeAddress &aCellRangeAddress)
void SetLastColumn(const sal_Int32 nTable, const sal_Int32 nCol)
void SetLastRow(const sal_Int32 nTable, const sal_Int32 nRow)
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)
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.
ScAddress aStart
Definition: address.hxx:497
sal_Int32 GetRefreshDelaySeconds() const
static OUString GetStringFromFunction(const sal_Int16 eFunction)
ScMyEmptyDatabaseRangesContainer GetEmptyDatabaseRanges()
ScXMLExportDatabaseRanges(ScXMLExport &rExport)
ScDocument * GetDocument()
Definition: xmlexprt.hxx:240
ScMySharedData * GetSharedData()
Definition: xmlexprt.hxx:257
const SvXMLNamespaceMap & GetNamespaceMap() const
void StartElement(sal_uInt16 nPrefix, enum ::xmloff::token::XMLTokenEnum eName, bool bIgnWSOutside)
void AddAttribute(sal_uInt16 nPrefix, const OUString &rName, const OUString &rValue)
const css::uno::Reference< css::frame::XModel > & GetModel() const
SvtSaveOptions::ODFSaneDefaultVersion getSaneDefaultVersion() const
void CheckAttrList()
void AddLanguageTagAttributes(sal_uInt16 nPrefix, sal_uInt16 nPrefixRfc, const css::lang::Locale &rLocale, bool bWriteEmpty)
void EndElement(sal_uInt16 nPrefix, enum ::xmloff::token::XMLTokenEnum eName, bool bIgnWSInside)
OUString GetQNameByKey(sal_uInt16 nKey, const OUString &rLocalName, bool bCache=true) const
static bool convertColor(sal_Int32 &rColor, std::u16string_view rValue)
static void convertDuration(OUStringBuffer &rBuffer, const double fTime)
const OUString & getString() const
bool has(DataAccessDescriptorProperty _eWhich) const
void setDataSource(const OUString &_sDataSourceNameOrLocation)
int nCount
float u
const SCSIZE MAXSUBTOTAL
Definition: global.hxx:82
ScQueryConnect
Definition: global.hxx:854
@ SC_AND
Definition: global.hxx:855
ScSubTotalFunc
Definition: global.hxx:860
@ ScDbQuery
Definition: global.hxx:421
@ SC_DOES_NOT_CONTAIN
Definition: global.hxx:846
@ SC_LESS_EQUAL
Definition: global.hxx:838
@ SC_LESS
Definition: global.hxx:836
@ SC_GREATER_EQUAL
Definition: global.hxx:839
@ SC_CONTAINS
Definition: global.hxx:845
@ SC_TOPPERC
Definition: global.hxx:843
@ SC_ENDS_WITH
Definition: global.hxx:849
@ SC_DOES_NOT_END_WITH
Definition: global.hxx:850
@ SC_BEGINS_WITH
Definition: global.hxx:847
@ SC_TOPVAL
Definition: global.hxx:841
@ SC_GREATER
Definition: global.hxx:837
@ SC_EQUAL
Definition: global.hxx:835
@ SC_BOTPERC
Definition: global.hxx:844
@ SC_NOT_EQUAL
Definition: global.hxx:840
@ SC_DOES_NOT_BEGIN_WITH
Definition: global.hxx:848
@ SC_BOTVAL
Definition: global.hxx:842
constexpr OUStringLiteral STR_DB_GLOBAL_NONAME
Definition: globalnames.hxx:15
constexpr OUStringLiteral STR_DB_LOCAL_NONAME
Definition: globalnames.hxx:14
OUString aName
void * p
aStr
aBuf
int i
XML_ORDER
XML_FIELD_NUMBER
XML_BIND_STYLES_TO_CONTENT
XML_CASE_SENSITIVE
XML_TRUE
XML_SORT
XML_FALSE
XML_SORT_BY
XML_TARGET_RANGE_ADDRESS
XML_AUTOMATIC
XML_DATA_TYPE
XML_TRANSPARENT
XML_DESCENDING
XML_ALGORITHM
XML_DATABASE_RANGES
const OUString & GetXMLToken(enum XMLTokenEnum eToken)
bool mbCellFormats
If TRUE, consider the presence of cell formats.
Definition: sortparam.hxx:59
OUString aStatement
Definition: global.hxx:447
sal_uInt8 nType
Definition: global.hxx:450
OUString aDBName
Definition: global.hxx:446
bool bNative
Definition: global.hxx:448
bool bImport
Definition: global.hxx:445
svl::SharedString maString
Definition: queryentry.hxx:49
Each instance of this struct represents a single filtering criteria.
Definition: queryentry.hxx:34
SCCOLROW nField
Definition: queryentry.hxx:61
bool IsQueryByNonEmpty() const
Definition: queryentry.cxx:109
ScQueryConnect eConnect
Definition: queryentry.hxx:63
std::vector< Item > QueryItemsType
Definition: queryentry.hxx:58
bool IsQueryByEmpty() const
Definition: queryentry.cxx:87
ScQueryOp eOp
Definition: queryentry.hxx:62
QueryItemsType & GetQueryItems()
Definition: queryentry.hxx:75
SC_DLLPUBLIC const ScQueryEntry & GetEntry(SCSIZE n) const
Definition: queryparam.cxx:116
utl::SearchParam::SearchType eSearchType
Definition: queryparam.hxx:43
SC_DLLPUBLIC SCSIZE GetEntryCount() const
Definition: queryparam.cxx:111
SCTAB nDestTab
Definition: sortparam.hxx:126
SCROW nDestRow
Definition: sortparam.hxx:128
SCCOL nDestCol
Definition: sortparam.hxx:127
::std::vector< ScSortKeyState > maKeyState
Definition: sortparam.hxx:130
OUString aCollatorAlgorithm
Definition: sortparam.hxx:132
ScDataAreaExtras aDataAreaExtras
Definition: sortparam.hxx:118
css::lang::Locale aCollatorLocale
Definition: sortparam.hxx:131
sal_uInt16 nUserIndex
Definition: sortparam.hxx:119
sal_uInt16 GetSortKeyCount() const
Definition: sortparam.hxx:148
bool bCaseSens
Definition: sortparam.hxx:122
bool bUserDef
sort user defined
bool bPagebreak
page break at change of group
bool bAscending
sort ascending
bool bGroupActive[MAXSUBTOTAL]
active groups
sal_uInt16 nUserIndex
index into list
SCCOL nField[MAXSUBTOTAL]
associated field
SCCOL nSubTotals[MAXSUBTOTAL]
number of SubTotals
bool bDoSort
presort
std::unique_ptr< ScSubTotalFunc[]> pFunctions[MAXSUBTOTAL]
array of associated functions
std::unique_ptr< SCCOL[]> pSubTotals[MAXSUBTOTAL]
array of columns to be calculated
bool bIncludePattern
sort formats
sal_Int32 SCCOLROW
a type capable of holding either SCCOL or SCROW
Definition: types.hxx:23
sal_Int16 SCTAB
Definition: types.hxx:22
sal_Int16 SCCOL
Definition: types.hxx:21
constexpr OUStringLiteral SC_UNO_DATABASERNG
Definition: unonames.hxx:43
constexpr OUStringLiteral SC_UNONAME_STRIPDAT
Definition: unonames.hxx:301
constexpr OUStringLiteral SC_UNONAME_SRCTYPE
Definition: unonames.hxx:300
constexpr sal_uInt16 XML_NAMESPACE_TABLE