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