1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26 
27 
28 
29 // INCLUDE ---------------------------------------------------------------
30 #include "XMLExportDatabaseRanges.hxx"
31 #include <xmloff/xmltoken.hxx>
32 #include <xmloff/xmlnmspe.hxx>
33 #include <xmloff/xmluconv.hxx>
34 #include <xmloff/nmspmap.hxx>
35 #include "xmlexprt.hxx"
36 #include "XMLExportIterator.hxx"
37 #include "XMLConverter.hxx"
38 #include "unonames.hxx"
39 #include "dbcolect.hxx"
40 #include "document.hxx"
41 #include "globstr.hrc"
42 #include "XMLExportSharedData.hxx"
43 #include "rangeutl.hxx"
44 #include <com/sun/star/sheet/DataImportMode.hpp>
45 #include <com/sun/star/table/TableSortField.hpp>
46 #include <com/sun/star/table/TableSortFieldType.hpp>
47 #include <com/sun/star/sheet/XSubTotalField.hpp>
48 #include <com/sun/star/sheet/XDatabaseRanges.hpp>
49 #include <com/sun/star/sheet/XDatabaseRange.hpp>
50 #include <com/sun/star/table/TableOrientation.hpp>
51 #include <tools/debug.hxx>
52 #include <comphelper/extract.hxx>
53 
54 //! not found in unonames.hxx
55 #define SC_USERLIST "UserList"
56 #define SC_SORTASCENDING "SortAscending"
57 #define SC_ENABLEUSERSORTLIST "EnableUserSortList"
58 #define SC_USERSORTLISTINDEX "UserSortListIndex"
59 
60 using namespace com::sun::star;
61 using namespace xmloff::token;
62 
ScXMLExportDatabaseRanges(ScXMLExport & rTempExport)63 ScXMLExportDatabaseRanges::ScXMLExportDatabaseRanges(ScXMLExport& rTempExport)
64 	: rExport(rTempExport),
65 	pDoc( NULL )
66 {
67 }
68 
~ScXMLExportDatabaseRanges()69 ScXMLExportDatabaseRanges::~ScXMLExportDatabaseRanges()
70 {
71 }
72 
GetEmptyDatabaseRanges()73 ScMyEmptyDatabaseRangesContainer ScXMLExportDatabaseRanges::GetEmptyDatabaseRanges()
74 {
75 	ScMyEmptyDatabaseRangesContainer aSkipRanges;
76 	if (rExport.GetModel().is())
77 	{
78 		sal_Int32 nSkipRangesCount = 0;
79 		uno::Reference <beans::XPropertySet> xPropertySet (rExport.GetModel(), uno::UNO_QUERY);
80 		if (xPropertySet.is())
81 		{
82             uno::Reference <sheet::XDatabaseRanges> xDatabaseRanges(xPropertySet->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_DATABASERNG))), uno::UNO_QUERY);
83 			rExport.CheckAttrList();
84 			if (xDatabaseRanges.is())
85 			{
86 				uno::Sequence <rtl::OUString> aRanges(xDatabaseRanges->getElementNames());
87 				sal_Int32 nDatabaseRangesCount = aRanges.getLength();
88 				for (sal_Int32 i = 0; i < nDatabaseRangesCount; ++i)
89 				{
90 					rtl::OUString sDatabaseRangeName(aRanges[i]);
91                     uno::Reference <sheet::XDatabaseRange> xDatabaseRange(xDatabaseRanges->getByName(sDatabaseRangeName), uno::UNO_QUERY);
92 					if (xDatabaseRange.is())
93 					{
94 						uno::Reference <beans::XPropertySet> xDatabaseRangePropertySet (xDatabaseRange, uno::UNO_QUERY);
95 						if (xDatabaseRangePropertySet.is() &&
96                             ::cppu::any2bool(xDatabaseRangePropertySet->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_STRIPDAT)))))
97 						{
98 							uno::Sequence <beans::PropertyValue> aImportProperties(xDatabaseRange->getImportDescriptor());
99 							sal_Int32 nLength = aImportProperties.getLength();
100 							sheet::DataImportMode nSourceType = sheet::DataImportMode_NONE;
101 							for (sal_Int32 j = 0; j < nLength; ++j)
102 								if (aImportProperties[j].Name == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_SRCTYPE)))
103 									aImportProperties[j].Value >>= nSourceType;
104 							if (nSourceType != sheet::DataImportMode_NONE)
105                             {
106                                 table::CellRangeAddress aArea = xDatabaseRange->getDataArea();
107 								aSkipRanges.AddNewEmptyDatabaseRange(aArea);
108 
109                                 // #105276#; set last row/column so default styles are collected
110                                 rExport.GetSharedData()->SetLastColumn(aArea.Sheet, aArea.EndColumn);
111                                 rExport.GetSharedData()->SetLastRow(aArea.Sheet, aArea.EndRow);
112                             }
113 						}
114 					}
115 				}
116 				if (nSkipRangesCount > 1)
117 					aSkipRanges.Sort();
118 			}
119 		}
120 	}
121 	return aSkipRanges;
122 }
123 
WriteImportDescriptor(const uno::Sequence<beans::PropertyValue> aImportDescriptor)124 void ScXMLExportDatabaseRanges::WriteImportDescriptor(const uno::Sequence <beans::PropertyValue> aImportDescriptor)
125 {
126 	sal_Int32 nProperties = aImportDescriptor.getLength();
127 	rtl::OUString sDatabaseName;
128     rtl::OUString sConRes;
129 	rtl::OUString sSourceObject;
130     sheet::DataImportMode nSourceType = sheet::DataImportMode_NONE;
131     sal_Bool bNative = sal_False;
132 	for (sal_Int16 i = 0; i < nProperties; ++i)
133 	{
134 		if (aImportDescriptor[i].Name == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_DBNAME)))
135 			aImportDescriptor[i].Value >>= sDatabaseName;
136 		else if (aImportDescriptor[i].Name == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_CONRES)))
137 			aImportDescriptor[i].Value >>= sConRes;
138 		else if (aImportDescriptor[i].Name == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_SRCOBJ)))
139 			aImportDescriptor[i].Value >>= sSourceObject;
140 		else if (aImportDescriptor[i].Name == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_SRCTYPE)))
141 			aImportDescriptor[i].Value >>= nSourceType;
142         else if (aImportDescriptor[i].Name == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_ISNATIVE)))
143 			bNative = ::cppu::any2bool(aImportDescriptor[i].Value);
144 	}
145 	switch (nSourceType)
146 	{
147 		case sheet::DataImportMode_NONE : break;
148 		case sheet::DataImportMode_QUERY :
149 		{
150             if (sDatabaseName.getLength())
151                 rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATABASE_NAME, sDatabaseName);
152 			rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_QUERY_NAME, sSourceObject);
153 			SvXMLElementExport aElemID(rExport, XML_NAMESPACE_TABLE, XML_DATABASE_SOURCE_QUERY, sal_True, sal_True);
154             if (sConRes.getLength())
155             {
156                 rExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, sConRes );
157     			SvXMLElementExport aElemCR(rExport, XML_NAMESPACE_FORM, XML_CONNECTION_RESOURCE, sal_True, sal_True);
158             }
159 			rExport.CheckAttrList();
160 		}
161 		break;
162 		case sheet::DataImportMode_TABLE :
163 		{
164             if (sDatabaseName.getLength())
165                 rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATABASE_NAME, sDatabaseName);
166 			rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_TABLE_NAME, sSourceObject);
167 			SvXMLElementExport aElemID(rExport, XML_NAMESPACE_TABLE, XML_DATABASE_SOURCE_TABLE, sal_True, sal_True);
168             if (sConRes.getLength())
169             {
170                 rExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, sConRes );
171     			SvXMLElementExport aElemCR(rExport, XML_NAMESPACE_FORM, XML_CONNECTION_RESOURCE, sal_True, sal_True);
172             }
173 			rExport.CheckAttrList();
174 		}
175 		break;
176 		case sheet::DataImportMode_SQL :
177 		{
178             if (sDatabaseName.getLength())
179                 rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATABASE_NAME, sDatabaseName);
180 			rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_SQL_STATEMENT, sSourceObject);
181 			if (!bNative)
182 				rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_PARSE_SQL_STATEMENT, XML_TRUE);
183 			SvXMLElementExport aElemID(rExport, XML_NAMESPACE_TABLE, XML_DATABASE_SOURCE_SQL, sal_True, sal_True);
184             if (sConRes.getLength())
185             {
186                 rExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, sConRes );
187     			SvXMLElementExport aElemCR(rExport, XML_NAMESPACE_FORM, XML_CONNECTION_RESOURCE, sal_True, sal_True);
188             }
189 			rExport.CheckAttrList();
190 		}
191 		break;
192         default:
193         {
194             // added to avoid warnings
195         }
196 	}
197 }
198 
getOperatorXML(const long aFilterOperator,const sal_Bool bUseRegularExpressions) const199 rtl::OUString ScXMLExportDatabaseRanges::getOperatorXML(const long aFilterOperator, const sal_Bool bUseRegularExpressions) const
200 {
201     switch (aFilterOperator)
202     {
203         case sheet::FilterOperator2::EQUAL :
204         {
205             if (bUseRegularExpressions)
206                 return GetXMLToken(XML_MATCH);
207             else
208                 return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("="));
209         }
210         case sheet::FilterOperator2::NOT_EQUAL :
211         {
212             if (bUseRegularExpressions)
213                 return GetXMLToken(XML_NOMATCH);
214             else
215                 return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("!="));
216         }
217         case sheet::FilterOperator2::BOTTOM_PERCENT :
218             return GetXMLToken(XML_BOTTOM_PERCENT);
219         case sheet::FilterOperator2::BOTTOM_VALUES :
220             return GetXMLToken(XML_BOTTOM_VALUES);
221         case sheet::FilterOperator2::EMPTY :
222             return GetXMLToken(XML_EMPTY);
223         case sheet::FilterOperator2::GREATER :
224             return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(">"));
225         case sheet::FilterOperator2::GREATER_EQUAL :
226             return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(">="));
227         case sheet::FilterOperator2::LESS :
228             return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("<"));
229         case sheet::FilterOperator2::LESS_EQUAL :
230             return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("<="));
231         case sheet::FilterOperator2::NOT_EMPTY :
232             return GetXMLToken(XML_NOEMPTY);
233         case sheet::FilterOperator2::TOP_PERCENT :
234             return GetXMLToken(XML_TOP_PERCENT);
235         case sheet::FilterOperator2::TOP_VALUES :
236             return GetXMLToken(XML_TOP_VALUES);
237         case sheet::FilterOperator2::CONTAINS :
238             return GetXMLToken(XML_CONTAINS);
239         case sheet::FilterOperator2::DOES_NOT_CONTAIN :
240             return GetXMLToken(XML_DOES_NOT_CONTAIN);
241         case sheet::FilterOperator2::BEGINS_WITH :
242             return GetXMLToken(XML_BEGINS_WITH);
243         case sheet::FilterOperator2::DOES_NOT_BEGIN_WITH :
244             return GetXMLToken(XML_DOES_NOT_BEGIN_WITH);
245         case sheet::FilterOperator2::ENDS_WITH :
246             return GetXMLToken(XML_ENDS_WITH);
247         case sheet::FilterOperator2::DOES_NOT_END_WITH :
248             return GetXMLToken(XML_DOES_NOT_END_WITH);
249         default:
250         {
251             // added to avoid warnings
252         }
253 	}
254 	return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("="));
255 }
256 
WriteCondition(const sheet::TableFilterField2 & aFilterField,sal_Bool bIsCaseSensitive,sal_Bool bUseRegularExpressions)257 void ScXMLExportDatabaseRanges::WriteCondition(const sheet::TableFilterField2& aFilterField, sal_Bool bIsCaseSensitive, sal_Bool bUseRegularExpressions)
258 {
259 	rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FIELD_NUMBER, rtl::OUString::valueOf(aFilterField.Field));
260 	if (bIsCaseSensitive)
261 		rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CASE_SENSITIVE, XML_TRUE);
262 	if (aFilterField.IsNumeric)
263 	{
264 		rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATA_TYPE, XML_NUMBER);
265 		rtl::OUStringBuffer sBuffer;
266 		rExport.GetMM100UnitConverter().convertDouble(sBuffer, aFilterField.NumericValue);
267 		rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_VALUE, sBuffer.makeStringAndClear());
268 	}
269 	else
270 		rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_VALUE, aFilterField.StringValue);
271 	rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_OPERATOR, getOperatorXML(aFilterField.Operator, bUseRegularExpressions));
272 	SvXMLElementExport aElemC(rExport, XML_NAMESPACE_TABLE, XML_FILTER_CONDITION, sal_True, sal_True);
273 }
274 
WriteFilterDescriptor(const uno::Reference<sheet::XSheetFilterDescriptor2> & xSheetFilterDescriptor,const rtl::OUString sDatabaseRangeName)275 void ScXMLExportDatabaseRanges::WriteFilterDescriptor(const uno::Reference <sheet::XSheetFilterDescriptor2>& xSheetFilterDescriptor, const rtl::OUString sDatabaseRangeName)
276 {
277     uno::Sequence< sheet::TableFilterField2 > aTableFilterFields( xSheetFilterDescriptor->getFilterFields2() );
278 	sal_Int32 nTableFilterFields = aTableFilterFields.getLength();
279 	if (nTableFilterFields > 0)
280 	{
281 		uno::Reference <beans::XPropertySet> xPropertySet (xSheetFilterDescriptor, uno::UNO_QUERY);
282 		if (xPropertySet.is())
283 		{
284 			if (::cppu::any2bool(xPropertySet->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_COPYOUT)))))
285             {
286 				table::CellAddress aOutputPosition;
287 				if (xPropertySet->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_OUTPOS))) >>= aOutputPosition)
288 				{
289 					rtl::OUString sOUCellAddress;
290 					ScRangeStringConverter::GetStringFromAddress( sOUCellAddress, aOutputPosition, pDoc, ::formula::FormulaGrammar::CONV_OOO );
291 					rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_TARGET_RANGE_ADDRESS, sOUCellAddress);
292 				}
293 			}
294 			ScDBCollection* pDBCollection = pDoc->GetDBCollection();
295 			sal_uInt16 nIndex;
296 			pDBCollection->SearchName(sDatabaseRangeName, nIndex);
297 			ScDBData* pDBData = (*pDBCollection)[nIndex];
298 			ScRange aAdvSource;
299 			if (pDBData->GetAdvancedQuerySource(aAdvSource))
300 			{
301 				rtl::OUString sOUCellAddress;
302 				ScRangeStringConverter::GetStringFromRange( sOUCellAddress, aAdvSource, pDoc, ::formula::FormulaGrammar::CONV_OOO );
303 				rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CONDITION_SOURCE_RANGE_ADDRESS, sOUCellAddress);
304 			}
305 
306 			if (::cppu::any2bool(xPropertySet->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_SKIPDUP)))))
307 				rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DISPLAY_DUPLICATES, XML_FALSE);
308 			SvXMLElementExport aElemF(rExport, XML_NAMESPACE_TABLE, XML_FILTER, sal_True, sal_True);
309 			rExport.CheckAttrList();
310 			sal_Bool bIsCaseSensitive = ::cppu::any2bool(xPropertySet->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_ISCASE))));
311 			sal_Bool bUseRegularExpressions = ::cppu::any2bool(xPropertySet->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_USEREGEX))));
312 			sal_Bool bAnd = sal_False;
313 			sal_Bool bOr = sal_False;
314 			for (sal_Int32 i = 1; i < nTableFilterFields; ++i)
315 			{
316 				if (aTableFilterFields[i].Connection == sheet::FilterConnection_AND)
317 					bAnd = sal_True;
318 				else
319 					bOr = sal_True;
320 			}
321 			if (bOr && !bAnd)
322 			{
323 				SvXMLElementExport aElemOr(rExport, XML_NAMESPACE_TABLE, XML_FILTER_OR, sal_True, sal_True);
324                 for (sal_Int32 i = 0; i < nTableFilterFields; ++i)
325 				{
326 					WriteCondition(aTableFilterFields[i], bIsCaseSensitive, bUseRegularExpressions);
327 				}
328 			}
329 			else if (bAnd && !bOr)
330 			{
331 				SvXMLElementExport aElemAnd(rExport, XML_NAMESPACE_TABLE, XML_FILTER_AND, sal_True, sal_True);
332                 for (sal_Int32 i = 0; i < nTableFilterFields; ++i)
333 				{
334 					WriteCondition(aTableFilterFields[i], bIsCaseSensitive, bUseRegularExpressions);
335 				}
336 			}
337 			else if (nTableFilterFields  == 1)
338 			{
339 				WriteCondition(aTableFilterFields[0], bIsCaseSensitive, bUseRegularExpressions);
340 			}
341 			else
342 			{
343 				SvXMLElementExport aElemC(rExport, XML_NAMESPACE_TABLE, XML_FILTER_OR, sal_True, sal_True);
344                 sheet::TableFilterField2 aPrevFilterField = aTableFilterFields[0];
345 				sheet::FilterConnection aConnection = aTableFilterFields[1].Connection;
346 				sal_Bool bOpenAndElement;
347 				rtl::OUString aName = rExport.GetNamespaceMap().GetQNameByKey(XML_NAMESPACE_TABLE, GetXMLToken(XML_FILTER_AND));
348 				if (aConnection == sheet::FilterConnection_AND)
349 				{
350 					rExport.StartElement( aName, sal_True);
351 					bOpenAndElement = sal_True;
352 				}
353 				else
354 					bOpenAndElement = sal_False;
355                 for (sal_Int32 i = 1; i < nTableFilterFields; ++i)
356 				{
357 					if (aConnection != aTableFilterFields[i].Connection)
358 					{
359 						aConnection = aTableFilterFields[i].Connection;
360 						if (aTableFilterFields[i].Connection == sheet::FilterConnection_AND)
361 						{
362 							rExport.StartElement( aName, sal_True );
363 							bOpenAndElement = sal_True;
364 							WriteCondition(aPrevFilterField, bIsCaseSensitive, bUseRegularExpressions);
365 							aPrevFilterField = aTableFilterFields[i];
366 							if (i == nTableFilterFields - 1)
367 							{
368 								WriteCondition(aPrevFilterField, bIsCaseSensitive, bUseRegularExpressions);
369 								rExport.EndElement(aName, sal_True);
370 								bOpenAndElement = sal_False;
371 							}
372 						}
373 						else
374 						{
375 							WriteCondition(aPrevFilterField, bIsCaseSensitive, bUseRegularExpressions);
376 							aPrevFilterField = aTableFilterFields[i];
377 							if (bOpenAndElement)
378 							{
379 								rExport.EndElement(aName, sal_True);
380 								bOpenAndElement = sal_False;
381 							}
382 							if (i == nTableFilterFields - 1)
383 							{
384 								WriteCondition(aPrevFilterField, bIsCaseSensitive, bUseRegularExpressions);
385 							}
386 						}
387 					}
388 					else
389 					{
390 						WriteCondition(aPrevFilterField, bIsCaseSensitive, bUseRegularExpressions);
391 						aPrevFilterField = aTableFilterFields[i];
392 						if (i == nTableFilterFields - 1)
393 							WriteCondition(aPrevFilterField, bIsCaseSensitive, bUseRegularExpressions);
394 					}
395 				}
396                 if(bOpenAndElement)
397                     rExport.EndElement(aName, sal_True);
398 			}
399 		}
400 	}
401 }
402 
WriteSortDescriptor(const uno::Sequence<beans::PropertyValue> aSortProperties)403 void ScXMLExportDatabaseRanges::WriteSortDescriptor(const uno::Sequence <beans::PropertyValue> aSortProperties)
404 {
405 	uno::Sequence <table::TableSortField> aSortFields;
406 	sal_Bool bBindFormatsToContent (sal_True);
407 	sal_Bool bCopyOutputData (sal_False);
408 //    sal_Bool bIsCaseSensitive (sal_False);
409 	sal_Bool bIsUserListEnabled (sal_False);
410 	table::CellAddress aOutputPosition;
411     sal_Int32 nUserListIndex = 0;
412 	sal_Int32 nProperties = aSortProperties.getLength();
413     sal_Int32 i;
414     for (i = 0; i < nProperties; ++i)
415 	{
416 		if (aSortProperties[i].Name.compareToAscii(SC_UNONAME_BINDFMT) == 0)
417 			 bBindFormatsToContent = ::cppu::any2bool(aSortProperties[i].Value);
418 		else if (aSortProperties[i].Name.compareToAscii(SC_UNONAME_COPYOUT) == 0)
419 			bCopyOutputData = ::cppu::any2bool(aSortProperties[i].Value);
420 //      no longer supported
421 /*		else if (aSortProperties[i].Name.compareToAscii(SC_UNONAME_ISCASE) == 0)
422 			bIsCaseSensitive = ::cppu::any2bool(aSortProperties[i].Value);*/
423 		else if (aSortProperties[i].Name.compareToAscii(SC_UNONAME_ISULIST) == 0)
424 			bIsUserListEnabled = ::cppu::any2bool(aSortProperties[i].Value);
425 		else if (aSortProperties[i].Name.compareToAscii(SC_UNONAME_OUTPOS) == 0)
426 			aSortProperties[i].Value >>= aOutputPosition;
427 		else if (aSortProperties[i].Name.compareToAscii(SC_UNONAME_UINDEX) == 0)
428 			aSortProperties[i].Value >>= nUserListIndex;
429 		else if (aSortProperties[i].Name.compareToAscii(SC_UNONAME_SORTFLD) == 0)
430 			aSortProperties[i].Value >>= aSortFields;
431 //      no longer supported
432 /*		else if (aSortProperties[i].Name.compareToAscii(SC_UNONAME_COLLLOC) == 0)
433 			aSortProperties[i].Value >>= aCollatorLocale;
434 		else if (aSortProperties[i].Name.compareToAscii(SC_UNONAME_COLLALG) == 0)
435 			aSortProperties[i].Value >>= sCollatorAlgorithm;*/
436 	}
437 	sal_Int32 nSortFields = aSortFields.getLength();
438 	if (nSortFields > 0)
439 	{
440 		if (!bBindFormatsToContent)
441 			rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_BIND_STYLES_TO_CONTENT, XML_FALSE);
442 		if (bCopyOutputData)
443 		{
444 			rtl::OUString sOUCellAddress;
445 			ScRangeStringConverter::GetStringFromAddress( sOUCellAddress, aOutputPosition, pDoc, ::formula::FormulaGrammar::CONV_OOO );
446 			rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_TARGET_RANGE_ADDRESS, sOUCellAddress);
447 		}
448 //      no longer supported
449 //		if (bIsCaseSensitive)
450 //			rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CASE_SENSITIVE, XML_TRUE);
451 
452         if (aSortFields[0].IsCaseSensitive)
453             rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CASE_SENSITIVE, XML_TRUE);
454 #ifdef DBG_UTIL
455         sal_Bool bCaseSensitive(aSortFields[0].IsCaseSensitive);
456         for (i = 1; i < nSortFields; ++i)
457 		{
458             DBG_ASSERT(bCaseSensitive == aSortFields[i].IsCaseSensitive, "seems that it is now possible to have every field case sensitive");
459         }
460 #endif
461 //      no longer supported
462 /*		if (aCollatorLocale.Language.getLength())
463 			rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_LANGUAGE, aCollatorLocale.Language);
464 		if (aCollatorLocale.Country.getLength())
465 			rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_COUNTRY, aCollatorLocale.Country);
466 		if (sCollatorAlgorithm.getLength())
467 			rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ALGORITHM, sCollatorAlgorithm);*/
468 		if (aSortFields[0].CollatorLocale.Language.getLength())
469 			rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_LANGUAGE, aSortFields[0].CollatorLocale.Language);
470 		if (aSortFields[0].CollatorLocale.Country.getLength())
471 			rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_COUNTRY, aSortFields[0].CollatorLocale.Country);
472 		if (aSortFields[0].CollatorAlgorithm.getLength())
473 			rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ALGORITHM, aSortFields[0].CollatorAlgorithm);
474 #ifdef DBG_UTIL
475         rtl::OUString sLanguage(aSortFields[0].CollatorLocale.Language);
476         rtl::OUString sCountry(aSortFields[0].CollatorLocale.Country);
477         rtl::OUString sAlgorithm(aSortFields[0].CollatorAlgorithm);
478 		for (i = 1; i < nSortFields; ++i)
479 		{
480             DBG_ASSERT(sLanguage == aSortFields[i].CollatorLocale.Language, "seems that it is now possible to have every field localized");
481             DBG_ASSERT(sCountry == aSortFields[i].CollatorLocale.Country, "seems that it is now possible to have every field localized");
482             DBG_ASSERT(sAlgorithm == aSortFields[i].CollatorAlgorithm, "seems that it is now possible to have every field localized");
483         }
484 #endif
485 		SvXMLElementExport aElemS(rExport, XML_NAMESPACE_TABLE, XML_SORT, sal_True, sal_True);
486 		rExport.CheckAttrList();
487 		for (i = 0; i < nSortFields; ++i)
488 		{
489 			rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FIELD_NUMBER, rtl::OUString::valueOf(aSortFields[i].Field));
490 			if (!aSortFields[i].IsAscending)
491 				rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ORDER, XML_DESCENDING);
492 			if (!bIsUserListEnabled)
493 			{
494 				switch (aSortFields[i].FieldType)
495 				{
496 					case table::TableSortFieldType_ALPHANUMERIC :
497 						rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATA_TYPE, XML_TEXT);
498 					break;
499 					case table::TableSortFieldType_AUTOMATIC :
500 						rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATA_TYPE, XML_AUTOMATIC);
501 					break;
502 					case table::TableSortFieldType_NUMERIC :
503 						rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATA_TYPE, XML_NUMBER);
504 					break;
505                     default:
506                     {
507                         // added to avoid warnings
508                     }
509 				}
510 			}
511 			else
512 				rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATA_TYPE, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_USERLIST)) + rtl::OUString::valueOf(nUserListIndex));
513 			SvXMLElementExport aElemSb(rExport, XML_NAMESPACE_TABLE, XML_SORT_BY, sal_True, sal_True);
514 			rExport.CheckAttrList();
515 		}
516 	}
517 }
518 
WriteSubTotalDescriptor(const com::sun::star::uno::Reference<com::sun::star::sheet::XSubTotalDescriptor> xSubTotalDescriptor,const rtl::OUString sDatabaseRangeName)519 void ScXMLExportDatabaseRanges::WriteSubTotalDescriptor(const com::sun::star::uno::Reference <com::sun::star::sheet::XSubTotalDescriptor> xSubTotalDescriptor, const rtl::OUString sDatabaseRangeName)
520 {
521 	uno::Reference <container::XIndexAccess> xIndexAccess (xSubTotalDescriptor, uno::UNO_QUERY);
522 	if (xIndexAccess.is())
523 	{
524 		sal_Int32 nSubTotalFields = xIndexAccess->getCount();
525 		if (nSubTotalFields > 0)
526 		{
527 			uno::Reference <beans::XPropertySet> xPropertySet (xSubTotalDescriptor, uno::UNO_QUERY);
528 //			sal_Bool bEnableUserSortList = sal_False;
529 //			sal_Bool bSortAscending = sal_True;
530 //			sal_Int32 nUserSortListIndex = 0;
531 			if (xPropertySet.is())
532 			{
533 				if (!::cppu::any2bool(xPropertySet->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_BINDFMT)))))
534 					rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_BIND_STYLES_TO_CONTENT, XML_FALSE);
535 				if (::cppu::any2bool(xPropertySet->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_INSBRK)))))
536 					rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_PAGE_BREAKS_ON_GROUP_CHANGE, XML_TRUE);
537 				if (::cppu::any2bool(xPropertySet->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_ISCASE)))))
538 					rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CASE_SENSITIVE, XML_TRUE);
539 //				bSortAscending = ::cppu::any2bool(xPropertySet->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_SORTASCENDING))));
540 //				if (::cppu::any2bool(xPropertySet->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_ENABLEUSERSORTLIST)))))
541 //					xPropertySet->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_USERSORTLISTINDEX))) >>= nUserSortListIndex;
542 			}
543 			SvXMLElementExport aElemSTRs(rExport, XML_NAMESPACE_TABLE, XML_SUBTOTAL_RULES, sal_True, sal_True);
544 			rExport.CheckAttrList();
545 			{
546 				ScDBCollection* pDBCollection = pDoc->GetDBCollection();
547 				sal_uInt16 nIndex;
548 				pDBCollection->SearchName(sDatabaseRangeName, nIndex);
549 				ScDBData* pDBData = (*pDBCollection)[nIndex];
550 				ScSubTotalParam aSubTotalParam;
551 				pDBData->GetSubTotalParam(aSubTotalParam);
552 				if (aSubTotalParam.bDoSort)
553 				{
554 					if (!aSubTotalParam.bAscending)
555 						rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ORDER, XML_DESCENDING);
556 					if (aSubTotalParam.bUserDef)
557 					{
558 						rtl::OUString sUserList(RTL_CONSTASCII_USTRINGPARAM(SC_USERLIST));
559 						sUserList += rtl::OUString::valueOf(aSubTotalParam.nUserIndex);
560 						rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATA_TYPE, sUserList);
561 					}
562 					SvXMLElementExport aElemSGs(rExport, XML_NAMESPACE_TABLE, XML_SORT_GROUPS, sal_True, sal_True);
563 					rExport.CheckAttrList();
564 				}
565 			}
566 			for (sal_Int32 i = 0; i < nSubTotalFields; ++i)
567 			{
568                 uno::Reference <sheet::XSubTotalField> xSubTotalField(xIndexAccess->getByIndex(i), uno::UNO_QUERY);
569 				if (xSubTotalField.is())
570 				{
571 					sal_Int32 nGroupColumn = xSubTotalField->getGroupColumn();
572 					rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_GROUP_BY_FIELD_NUMBER, rtl::OUString::valueOf(nGroupColumn));
573 					SvXMLElementExport aElemSTR(rExport, XML_NAMESPACE_TABLE, XML_SUBTOTAL_RULE, sal_True, sal_True);
574 					rExport.CheckAttrList();
575 					uno::Sequence <sheet::SubTotalColumn> aSubTotalColumns = xSubTotalField->getSubTotalColumns();
576 					sal_Int32 nSubTotalColumns = aSubTotalColumns.getLength();
577 					for (sal_Int32 j = 0; j < nSubTotalColumns; ++j)
578 					{
579 						rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FIELD_NUMBER, rtl::OUString::valueOf(aSubTotalColumns[j].Column));
580 						rtl::OUString sFunction;
581 						ScXMLConverter::GetStringFromFunction( sFunction, aSubTotalColumns[j].Function );
582 						rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FUNCTION, sFunction);
583 						SvXMLElementExport aElemSTF(rExport, XML_NAMESPACE_TABLE, XML_SUBTOTAL_FIELD, sal_True, sal_True);
584 						rExport.CheckAttrList();
585 					}
586 				}
587 			}
588 		}
589 	}
590 }
591 
WriteDatabaseRanges(const com::sun::star::uno::Reference<com::sun::star::sheet::XSpreadsheetDocument> & xSpreadDoc)592 void ScXMLExportDatabaseRanges::WriteDatabaseRanges(const com::sun::star::uno::Reference <com::sun::star::sheet::XSpreadsheetDocument>& xSpreadDoc)
593 {
594 	pDoc = rExport.GetDocument();
595 	if (pDoc)
596 	{
597 		uno::Reference <beans::XPropertySet> xPropertySet (xSpreadDoc, uno::UNO_QUERY);
598 		if (xPropertySet.is())
599 		{
600             uno::Reference <sheet::XDatabaseRanges> xDatabaseRanges(xPropertySet->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_DATABASERNG))), uno::UNO_QUERY);
601 			rExport.CheckAttrList();
602 			if (xDatabaseRanges.is())
603 			{
604 				uno::Sequence <rtl::OUString> aRanges(xDatabaseRanges->getElementNames());
605 				sal_Int32 nDatabaseRangesCount = aRanges.getLength();
606 				if (nDatabaseRangesCount > 0)
607 				{
608 					SvXMLElementExport aElemDRs(rExport, XML_NAMESPACE_TABLE, XML_DATABASE_RANGES, sal_True, sal_True);
609 					for (sal_Int32 i = 0; i < nDatabaseRangesCount; ++i)
610 					{
611 						rtl::OUString sDatabaseRangeName(aRanges[i]);
612                         uno::Reference <sheet::XDatabaseRange> xDatabaseRange(xDatabaseRanges->getByName(sDatabaseRangeName), uno::UNO_QUERY);
613 						if (xDatabaseRange.is())
614 						{
615 							rtl::OUString sOUUnbenannt (ScGlobal::GetRscString(STR_DB_NONAME));
616 							if (sOUUnbenannt != sDatabaseRangeName)
617 								rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_NAME, sDatabaseRangeName);
618 							table::CellRangeAddress aRangeAddress(xDatabaseRange->getDataArea());
619 							rtl::OUString sOUAddress;
620 							ScRangeStringConverter::GetStringFromRange( sOUAddress, aRangeAddress, pDoc, ::formula::FormulaGrammar::CONV_OOO );
621 							rExport.AddAttribute (XML_NAMESPACE_TABLE, XML_TARGET_RANGE_ADDRESS, sOUAddress);
622 							ScDBCollection* pDBCollection = pDoc->GetDBCollection();
623 							sal_uInt16 nIndex;
624 							pDBCollection->SearchName(sDatabaseRangeName, nIndex);
625 							ScDBData* pDBData = (*pDBCollection)[nIndex];
626 							if (pDBData->HasImportSelection())
627 								rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_IS_SELECTION, XML_TRUE);
628 							if (pDBData->HasAutoFilter())
629 								rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DISPLAY_FILTER_BUTTONS, XML_TRUE);
630 							uno::Reference <beans::XPropertySet> xPropertySetDatabaseRange (xDatabaseRange, uno::UNO_QUERY);
631 							if (xPropertySetDatabaseRange.is())
632 							{
633 								if (::cppu::any2bool(xPropertySetDatabaseRange->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_KEEPFORM)))))
634 									rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ON_UPDATE_KEEP_STYLES, XML_TRUE);
635 								if (::cppu::any2bool(xPropertySetDatabaseRange->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_MOVCELLS)))))
636 									rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ON_UPDATE_KEEP_SIZE, XML_FALSE);
637 								if (::cppu::any2bool(xPropertySetDatabaseRange->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_STRIPDAT)))))
638 									rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_HAS_PERSISTENT_DATA, XML_FALSE);
639 							}
640 
641                             uno::Reference< sheet::XSheetFilterDescriptor2 > xSheetFilterDescriptor(
642                                     xDatabaseRange->getFilterDescriptor(), uno::UNO_QUERY );
643 							uno::Sequence <beans::PropertyValue> aSortProperties(xDatabaseRange->getSortDescriptor());
644 							if (xSheetFilterDescriptor.is())
645 							{
646 								uno::Reference <beans::XPropertySet> xFilterProperties (xSheetFilterDescriptor, uno::UNO_QUERY);
647 								if (xFilterProperties.is())
648 								{
649 									if (!::cppu::any2bool(xFilterProperties->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_CONTHDR)))))
650 										rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CONTAINS_HEADER, XML_FALSE);
651 
652 									// #98317#; there is no orientation on the filter
653 /*									table::TableOrientation eFilterOrient(table::TableOrientation_ROWS);
654 									if (::cppu::any2bool(xFilterProperties->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_ORIENT)))))
655 										eFilterOrient = table::TableOrientation_ROWS;*/
656 
657 									sal_Bool bSortColumns(sal_True);
658 									sal_Bool bFound(sal_False);
659                                     sal_Int32 nProperty(0);
660 									while (!bFound && (nProperty < aSortProperties.getLength()))
661 									{
662 										if (aSortProperties[nProperty].Name.compareToAscii(SC_UNONAME_ISSORTCOLUMNS) == 0)
663 										{
664                                             bSortColumns = ::cppu::any2bool(aSortProperties[nProperty].Value);
665 											bFound = sal_True;
666 										}
667 										else
668 											++nProperty;
669 									}
670 
671 									if (bSortColumns)
672 										rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ORIENTATION, XML_COLUMN);
673 								}
674 							}
675 							sal_Int32 nRefresh( pDBData->GetRefreshDelay() );
676 							if( nRefresh )
677 							{
678 								rtl::OUStringBuffer sBuffer;
679 								SvXMLUnitConverter::convertTime( sBuffer, (double)nRefresh / 86400 );
680 								rExport.AddAttribute( XML_NAMESPACE_TABLE, XML_REFRESH_DELAY, sBuffer.makeStringAndClear() );
681 							}
682 							SvXMLElementExport aElemDR(rExport, XML_NAMESPACE_TABLE, XML_DATABASE_RANGE, sal_True, sal_True);
683 							rExport.CheckAttrList();
684 							WriteImportDescriptor(xDatabaseRange->getImportDescriptor());
685 							if (xSheetFilterDescriptor.is())
686 								WriteFilterDescriptor(xSheetFilterDescriptor, sDatabaseRangeName);
687 							WriteSortDescriptor(aSortProperties);
688 							WriteSubTotalDescriptor(xDatabaseRange->getSubTotalDescriptor(), sDatabaseRangeName);
689 						}
690 					}
691 				}
692 			}
693 		}
694 	}
695 }
696