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 "XMLExportDataPilot.hxx"
31 #include <xmloff/xmltoken.hxx>
32 #include <xmloff/xmlnmspe.hxx>
33 #include <xmloff/xmluconv.hxx>
34 #include <xmloff/nmspmap.hxx>
35 #include <rtl/math.hxx>
36 #include "xmlexprt.hxx"
37 #include "XMLConverter.hxx"
38 #include "document.hxx"
39 #include "dpobject.hxx"
40 #include "dociter.hxx"
41 #include "attrib.hxx"
42 #include "patattr.hxx"
43 #include "scitems.hxx"
44 #include "dpsave.hxx"
45 #include "dpshttab.hxx"
46 #include "dpsdbtab.hxx"
47 #include "dpdimsave.hxx"
48 #include "dpgroup.hxx"
49 #include "rangeutl.hxx"
50 #include <com/sun/star/sheet/DataImportMode.hpp>
51 #include <com/sun/star/sheet/DataPilotFieldReference.hpp>
52 #include <com/sun/star/sheet/DataPilotFieldReferenceType.hpp>
53 #include <com/sun/star/sheet/DataPilotFieldReferenceItemType.hpp>
54 #include <com/sun/star/sheet/DataPilotFieldSortInfo.hpp>
55 #include <com/sun/star/sheet/DataPilotFieldAutoShowInfo.hpp>
56 #include <com/sun/star/sheet/DataPilotFieldLayoutInfo.hpp>
57 #include <com/sun/star/sheet/DataPilotFieldShowItemsMode.hpp>
58 #include <com/sun/star/sheet/DataPilotFieldSortMode.hpp>
59 #include <com/sun/star/sheet/DataPilotFieldLayoutMode.hpp>
60 #include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
61 
62 using namespace com::sun::star;
63 using namespace xmloff::token;
64 using ::rtl::OUString;
65 
ScXMLExportDataPilot(ScXMLExport & rTempExport)66 ScXMLExportDataPilot::ScXMLExportDataPilot(ScXMLExport& rTempExport)
67 	: rExport(rTempExport),
68 	pDoc( NULL )
69 {
70 }
71 
~ScXMLExportDataPilot()72 ScXMLExportDataPilot::~ScXMLExportDataPilot()
73 {
74 }
75 
getDPOperatorXML(const ScQueryOp aFilterOperator,const sal_Bool bUseRegularExpressions,const sal_Bool bIsString,const double dVal,const String & sVal) const76 rtl::OUString ScXMLExportDataPilot::getDPOperatorXML(const ScQueryOp aFilterOperator, const sal_Bool bUseRegularExpressions,
77 	const sal_Bool bIsString, const double dVal, const String& sVal) const
78 {
79 	switch (aFilterOperator)
80 	{
81 		case SC_EQUAL :
82 		{
83             rtl::OUString sReturn;
84 			if (bUseRegularExpressions)
85 				sReturn = GetXMLToken(XML_MATCH);
86 			else
87 				sReturn = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("="));
88 
89             if (!bIsString && sVal == EMPTY_STRING)
90             {
91                 if (dVal == SC_EMPTYFIELDS)
92                     sReturn = GetXMLToken(XML_EMPTY);
93                 else if (dVal == SC_NONEMPTYFIELDS)
94                     sReturn = GetXMLToken(XML_NOEMPTY);
95             }
96 
97             return sReturn;
98 		}
99 		case SC_NOT_EQUAL :
100 		{
101 			if (bUseRegularExpressions)
102 				return GetXMLToken(XML_NOMATCH);
103 			else
104 				return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("!="));
105 		}
106 		case SC_BOTPERC :
107 			return GetXMLToken(XML_BOTTOM_PERCENT);
108 		case SC_BOTVAL :
109 			return GetXMLToken(XML_BOTTOM_VALUES);
110 		case SC_GREATER :
111 			return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(">"));
112 		case SC_GREATER_EQUAL :
113 			return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(">="));
114 		case SC_LESS :
115 			return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("<"));
116 		case SC_LESS_EQUAL :
117 			return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("<="));
118 		case SC_TOPPERC :
119 			return GetXMLToken(XML_TOP_PERCENT);
120 		case SC_TOPVAL :
121 			return GetXMLToken(XML_TOP_VALUES);
122 		default:
123             DBG_ERROR("This FilterOperator is not supported.");
124 	}
125 	return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("="));
126 }
127 
WriteDPCondition(const ScQueryEntry & aQueryEntry,sal_Bool bIsCaseSensitive,sal_Bool bUseRegularExpressions)128 void ScXMLExportDataPilot::WriteDPCondition(const ScQueryEntry& aQueryEntry, sal_Bool bIsCaseSensitive, sal_Bool bUseRegularExpressions)
129 {
130 	rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FIELD_NUMBER, rtl::OUString::valueOf(sal_Int32(aQueryEntry.nField)));
131 	if (bIsCaseSensitive)
132 		rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CASE_SENSITIVE, XML_TRUE);
133 	if (aQueryEntry.bQueryByString)
134 	{
135 		rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_VALUE, *aQueryEntry.pStr);
136 	}
137 	else
138     {
139 		rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATA_TYPE, XML_NUMBER);
140 		rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_VALUE, rtl::OUString(*aQueryEntry.pStr));
141     }
142 	rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_OPERATOR, getDPOperatorXML(aQueryEntry.eOp, bUseRegularExpressions,
143 		aQueryEntry.bQueryByString, aQueryEntry.nVal, *aQueryEntry.pStr));
144 	SvXMLElementExport aElemC(rExport, XML_NAMESPACE_TABLE, XML_FILTER_CONDITION, sal_True, sal_True);
145 }
146 
WriteDPFilter(const ScQueryParam & aQueryParam)147 void ScXMLExportDataPilot::WriteDPFilter(const ScQueryParam& aQueryParam)
148 {
149 	SCSIZE nQueryEntryCount = aQueryParam.GetEntryCount();
150 	if (nQueryEntryCount > 0)
151 	{
152 		sal_Bool bAnd(sal_False);
153 		sal_Bool bOr(sal_False);
154 		sal_Bool bHasEntries(sal_True);
155 		SCSIZE nEntries(0);
156 		SCSIZE j;
157 
158 		for ( j = 0; (j < nQueryEntryCount) && bHasEntries; ++j)
159 		{
160 			ScQueryEntry aEntry = aQueryParam.GetEntry(j);
161 			if (aEntry.bDoQuery)
162 			{
163 				if (nEntries > 0)
164 				{
165 					if (aEntry.eConnect == SC_AND)
166 						bAnd = sal_True;
167 					else
168 						bOr = sal_True;
169 				}
170 				++nEntries;
171 			}
172 			else
173 				bHasEntries = sal_False;
174 		}
175 		nQueryEntryCount = nEntries;
176 		if (nQueryEntryCount)
177 		{
178 			// There is never a target range in a data pilot.
179 /*			if (!aQueryParam.bInplace)
180 			{
181 				ScAddress aTargetAddress(aQueryParam.nDestCol, aQueryParam.nDestRow, aQueryParam.nDestTab);
182 				rtl::OUString sAddress;
183 				ScXMLConverter::GetStringFromAddress( sAddress, aTargetAddress, pDoc );
184 				rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_TARGET_RANGE_ADDRESS, sAddress);
185 			}*/
186 			if(!((aQueryParam.nCol1 == aQueryParam.nCol2) && (aQueryParam.nRow1 == aQueryParam.nRow2) &&
187                         (static_cast<SCCOLROW>(aQueryParam.nCol1) == static_cast<SCCOLROW>(aQueryParam.nRow1)) &&
188                         (aQueryParam.nCol1 == 0) && (aQueryParam.nTab == SCTAB_MAX)))
189 			{
190 				ScRange aConditionRange(aQueryParam.nCol1, aQueryParam.nRow1, aQueryParam.nTab,
191 					aQueryParam.nCol2, aQueryParam.nRow2, aQueryParam.nTab);
192 				rtl::OUString sConditionRange;
193 				ScRangeStringConverter::GetStringFromRange( sConditionRange, aConditionRange, pDoc, ::formula::FormulaGrammar::CONV_OOO );
194 				rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CONDITION_SOURCE_RANGE_ADDRESS, sConditionRange);
195 			}
196 			if (!aQueryParam.bDuplicate)
197 				rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DISPLAY_DUPLICATES, XML_FALSE);
198 			SvXMLElementExport aElemDPF(rExport, XML_NAMESPACE_TABLE, XML_FILTER, sal_True, sal_True);
199 			rExport.CheckAttrList();
200 			if (nQueryEntryCount  == 1)
201 			{
202 					WriteDPCondition(aQueryParam.GetEntry(0), aQueryParam.bCaseSens, aQueryParam.bRegExp);
203 			}
204 			else if (bOr && !bAnd)
205 			{
206 				SvXMLElementExport aElemOr(rExport, XML_NAMESPACE_TABLE, XML_FILTER_OR, sal_True, sal_True);
207                 for (j = 0; j < nQueryEntryCount; ++j)
208 				{
209 					WriteDPCondition(aQueryParam.GetEntry(j), aQueryParam.bCaseSens, aQueryParam.bRegExp);
210 				}
211 			}
212 			else if (bAnd && !bOr)
213 			{
214 				SvXMLElementExport aElemAnd(rExport, XML_NAMESPACE_TABLE, XML_FILTER_AND, sal_True, sal_True);
215                 for (j = 0; j < nQueryEntryCount; ++j)
216 				{
217 					WriteDPCondition(aQueryParam.GetEntry(j), aQueryParam.bCaseSens, aQueryParam.bRegExp);
218 				}
219 			}
220 			else
221 			{
222 				SvXMLElementExport aElemC(rExport, XML_NAMESPACE_TABLE, XML_FILTER_OR, sal_True, sal_True);
223 				ScQueryEntry aPrevFilterField(aQueryParam.GetEntry(0));
224 				ScQueryConnect aConnection = aQueryParam.GetEntry(1).eConnect;
225 				sal_Bool bOpenAndElement;
226 				rtl::OUString aName(rExport.GetNamespaceMap().GetQNameByKey(XML_NAMESPACE_TABLE, GetXMLToken(XML_FILTER_AND)));
227 				if (aConnection == SC_AND)
228 				{
229 					rExport.StartElement( aName, sal_True );
230 					bOpenAndElement = sal_True;
231 				}
232 				else
233 					bOpenAndElement = sal_False;
234                 for (j = 1; j < nQueryEntryCount; ++j)
235 				{
236 					if (aConnection != aQueryParam.GetEntry(j).eConnect)
237 					{
238 						aConnection = aQueryParam.GetEntry(j).eConnect;
239 						if (aQueryParam.GetEntry(j).eConnect == SC_AND)
240 						{
241 							rExport.StartElement( aName, sal_True );
242 							bOpenAndElement = sal_True;
243 							WriteDPCondition(aPrevFilterField, aQueryParam.bCaseSens, aQueryParam.bRegExp);
244 							aPrevFilterField = aQueryParam.GetEntry(j);
245 							if (j == nQueryEntryCount - 1)
246 							{
247 								WriteDPCondition(aPrevFilterField, aQueryParam.bCaseSens, aQueryParam.bRegExp);
248 								rExport.EndElement(aName, sal_True);
249 								bOpenAndElement = sal_False;
250 							}
251 						}
252 						else
253 						{
254 							WriteDPCondition(aPrevFilterField, aQueryParam.bCaseSens, aQueryParam.bRegExp);
255 							aPrevFilterField = aQueryParam.GetEntry(j);
256 							if (bOpenAndElement)
257 							{
258 								rExport.EndElement(aName, sal_True);
259 								bOpenAndElement = sal_False;
260 							}
261 							if (j == nQueryEntryCount - 1)
262 							{
263 								WriteDPCondition(aPrevFilterField, aQueryParam.bCaseSens, aQueryParam.bRegExp);
264 							}
265 						}
266 					}
267 					else
268 					{
269 						WriteDPCondition(aPrevFilterField, aQueryParam.bCaseSens, aQueryParam.bRegExp);
270 						aPrevFilterField = aQueryParam.GetEntry(j);
271 						if (j == nQueryEntryCount - 1)
272 							WriteDPCondition(aPrevFilterField, aQueryParam.bCaseSens, aQueryParam.bRegExp);
273 					}
274 				}
275 			}
276 		}
277 	}
278 }
279 
WriteFieldReference(ScDPSaveDimension * pDim)280 void ScXMLExportDataPilot::WriteFieldReference(ScDPSaveDimension* pDim)
281 {
282     const sheet::DataPilotFieldReference* pRef = pDim->GetReferenceValue();
283     if (pRef)
284     {
285         rtl::OUString sValueStr;
286         switch (pRef->ReferenceType)
287         {
288             case sheet::DataPilotFieldReferenceType::NONE :
289                 sValueStr = GetXMLToken(XML_NONE);
290                 break;
291             case sheet::DataPilotFieldReferenceType::ITEM_DIFFERENCE :
292                 sValueStr = GetXMLToken(XML_MEMBER_DIFFERENCE);
293                 break;
294             case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE :
295                 sValueStr = GetXMLToken(XML_MEMBER_PERCENTAGE);
296                 break;
297             case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE :
298                 sValueStr = GetXMLToken(XML_MEMBER_PERCENTAGE_DIFFERENCE);
299                 break;
300             case sheet::DataPilotFieldReferenceType::RUNNING_TOTAL :
301                 sValueStr = GetXMLToken(XML_RUNNING_TOTAL);
302                 break;
303             case sheet::DataPilotFieldReferenceType::ROW_PERCENTAGE :
304                 sValueStr = GetXMLToken(XML_ROW_PERCENTAGE);
305                 break;
306             case sheet::DataPilotFieldReferenceType::COLUMN_PERCENTAGE :
307                 sValueStr = GetXMLToken(XML_COLUMN_PERCENTAGE);
308                 break;
309             case sheet::DataPilotFieldReferenceType::TOTAL_PERCENTAGE :
310                 sValueStr = GetXMLToken(XML_TOTAL_PERCENTAGE);
311                 break;
312             case sheet::DataPilotFieldReferenceType::INDEX :
313                 sValueStr = GetXMLToken(XML_INDEX);
314                 break;
315         }
316         if (sValueStr.getLength())
317             rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_TYPE, sValueStr);
318 
319         if (pRef->ReferenceField.getLength())
320             rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FIELD_NAME, pRef->ReferenceField);
321 
322         if (pRef->ReferenceItemType == sheet::DataPilotFieldReferenceItemType::NAMED)
323         {
324             rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_MEMBER_TYPE, XML_NAMED);
325             rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_MEMBER_NAME, pRef->ReferenceItemName);
326         }
327         else
328         {
329             sValueStr = rtl::OUString();
330             switch(pRef->ReferenceItemType)
331             {
332                 case sheet::DataPilotFieldReferenceItemType::PREVIOUS :
333                 sValueStr = GetXMLToken(XML_PREVIOUS);
334                 break;
335                 case sheet::DataPilotFieldReferenceItemType::NEXT :
336                 sValueStr = GetXMLToken(XML_NEXT);
337                 break;
338             }
339             if (sValueStr.getLength())
340                 rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_MEMBER_TYPE, sValueStr);
341         }
342         SvXMLElementExport aElemDPFR(rExport, XML_NAMESPACE_TABLE, XML_DATA_PILOT_FIELD_REFERENCE, sal_True, sal_True);
343     }
344     rExport.CheckAttrList();
345 }
346 
WriteSortInfo(ScDPSaveDimension * pDim)347 void ScXMLExportDataPilot::WriteSortInfo(ScDPSaveDimension* pDim)
348 {
349     const sheet::DataPilotFieldSortInfo* pSortInfo = pDim->GetSortInfo();
350     if (pSortInfo)
351     {
352         if (pSortInfo->IsAscending)
353             rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ORDER, XML_ASCENDING);
354         else
355             rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ORDER, XML_DESCENDING);
356 
357         rtl::OUString sValueStr;
358         switch (pSortInfo->Mode)
359         {
360             case sheet::DataPilotFieldSortMode::NONE:
361             sValueStr = GetXMLToken(XML_NONE);
362             break;
363             case sheet::DataPilotFieldSortMode::MANUAL:
364             sValueStr = GetXMLToken(XML_MANUAL);
365             break;
366             case sheet::DataPilotFieldSortMode::NAME:
367             sValueStr = GetXMLToken(XML_NAME);
368             break;
369             case sheet::DataPilotFieldSortMode::DATA:
370             sValueStr = GetXMLToken(XML_DATA);
371             if (pSortInfo->Field.getLength())
372                 rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATA_FIELD, pSortInfo->Field);
373             break;
374         }
375         if (sValueStr.getLength())
376             rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_SORT_MODE, sValueStr);
377     	SvXMLElementExport aElemDPLSI(rExport, XML_NAMESPACE_TABLE, XML_DATA_PILOT_SORT_INFO, sal_True, sal_True);
378     }
379 }
380 
WriteAutoShowInfo(ScDPSaveDimension * pDim)381 void ScXMLExportDataPilot::WriteAutoShowInfo(ScDPSaveDimension* pDim)
382 {
383     const sheet::DataPilotFieldAutoShowInfo* pAutoInfo = pDim->GetAutoShowInfo();
384     if (pAutoInfo)
385     {
386         if (pAutoInfo->IsEnabled)
387             rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ENABLED, XML_TRUE);
388         else
389             rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ENABLED, XML_FALSE);
390 
391         rtl::OUString sValueStr;
392         switch (pAutoInfo->ShowItemsMode)
393         {
394             case sheet::DataPilotFieldShowItemsMode::FROM_TOP:
395             sValueStr = GetXMLToken(XML_FROM_TOP);
396             break;
397             case sheet::DataPilotFieldShowItemsMode::FROM_BOTTOM:
398             sValueStr = GetXMLToken(XML_FROM_BOTTOM);
399             break;
400         }
401         if (sValueStr.getLength())
402             rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DISPLAY_MEMBER_MODE, sValueStr);
403 
404     	rtl::OUStringBuffer sBuffer;
405 	    SvXMLUnitConverter::convertNumber(sBuffer, pAutoInfo->ItemCount);
406         rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_MEMBER_COUNT, sBuffer.makeStringAndClear());
407 
408         rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATA_FIELD, pAutoInfo->DataField);
409 
410     	SvXMLElementExport aElemDPLAI(rExport, XML_NAMESPACE_TABLE, XML_DATA_PILOT_DISPLAY_INFO, sal_True, sal_True);
411     }
412 }
413 
WriteLayoutInfo(ScDPSaveDimension * pDim)414 void ScXMLExportDataPilot::WriteLayoutInfo(ScDPSaveDimension* pDim)
415 {
416     const sheet::DataPilotFieldLayoutInfo* pLayoutInfo = pDim->GetLayoutInfo();
417     if (pLayoutInfo)
418     {
419         if (pLayoutInfo->AddEmptyLines)
420             rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ADD_EMPTY_LINES, XML_TRUE);
421         else
422             rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ADD_EMPTY_LINES, XML_FALSE);
423 
424         rtl::OUString sValueStr;
425         switch (pLayoutInfo->LayoutMode)
426         {
427             case sheet::DataPilotFieldLayoutMode::TABULAR_LAYOUT:
428             sValueStr = GetXMLToken(XML_TABULAR_LAYOUT);
429             break;
430             case sheet::DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_TOP:
431             sValueStr = GetXMLToken(XML_OUTLINE_SUBTOTALS_TOP);
432             break;
433             case sheet::DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_BOTTOM:
434             sValueStr = GetXMLToken(XML_OUTLINE_SUBTOTALS_BOTTOM);
435             break;
436         }
437         if (sValueStr.getLength())
438             rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_LAYOUT_MODE, sValueStr);
439     	SvXMLElementExport aElemDPLLI(rExport, XML_NAMESPACE_TABLE, XML_DATA_PILOT_LAYOUT_INFO, sal_True, sal_True);
440     }
441 }
442 
WriteSubTotals(ScDPSaveDimension * pDim)443 void ScXMLExportDataPilot::WriteSubTotals(ScDPSaveDimension* pDim)
444 {
445     using sheet::GeneralFunction;
446 
447 	sal_Int32 nSubTotalCount = pDim->GetSubTotalsCount();
448     const OUString* pLayoutName = NULL;
449     if (rExport.getDefaultVersion() == SvtSaveOptions::ODFVER_LATEST)
450         // Export display names only for 1.2 extended or later.
451         pLayoutName = pDim->GetSubtotalName();
452 
453 	if (nSubTotalCount > 0)
454 	{
455 		SvXMLElementExport aElemSTs(rExport, XML_NAMESPACE_TABLE, XML_DATA_PILOT_SUBTOTALS, sal_True, sal_True);
456 		rExport.CheckAttrList();
457 		for (sal_Int32 nSubTotal = 0; nSubTotal < nSubTotalCount; nSubTotal++)
458 		{
459 			rtl::OUString sFunction;
460             GeneralFunction nFunc = static_cast<GeneralFunction>(pDim->GetSubTotalFunc(nSubTotal));
461 			ScXMLConverter::GetStringFromFunction( sFunction, nFunc);
462 			rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FUNCTION, sFunction);
463             if (pLayoutName && nFunc == sheet::GeneralFunction_AUTO)
464                 rExport.AddAttribute(XML_NAMESPACE_TABLE_EXT, XML_DISPLAY_NAME, *pLayoutName);
465 			SvXMLElementExport aElemST(rExport, XML_NAMESPACE_TABLE, XML_DATA_PILOT_SUBTOTAL, sal_True, sal_True);
466 		}
467 	}
468 }
469 
WriteMembers(ScDPSaveDimension * pDim)470 void ScXMLExportDataPilot::WriteMembers(ScDPSaveDimension* pDim)
471 {
472     const ScDPSaveDimension::MemberList &rMembers = pDim->GetMembers();
473 	if (rMembers.begin() != rMembers.end())
474 	{
475 		SvXMLElementExport aElemDPMs(rExport, XML_NAMESPACE_TABLE, XML_DATA_PILOT_MEMBERS, sal_True, sal_True);
476 		rExport.CheckAttrList();
477 		for (ScDPSaveDimension::MemberList::const_iterator i=rMembers.begin(); i != rMembers.end() ; i++)
478 		{
479 			rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_NAME, rtl::OUString((*i)->GetName()));
480 
481             if (rExport.getDefaultVersion() == SvtSaveOptions::ODFVER_LATEST)
482             {
483                 // Export display names only for ODF 1.2 extended or later.
484                 const OUString* pLayoutName = (*i)->GetLayoutName();
485                 if (pLayoutName)
486                     rExport.AddAttribute(XML_NAMESPACE_TABLE_EXT, XML_DISPLAY_NAME, *pLayoutName);
487             }
488 
489 			rtl::OUStringBuffer sBuffer;
490 			SvXMLUnitConverter::convertBool(sBuffer, (*i)->GetIsVisible());
491 			rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DISPLAY, sBuffer.makeStringAndClear());
492 			SvXMLUnitConverter::convertBool(sBuffer, (*i)->GetShowDetails());
493 			rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_SHOW_DETAILS, sBuffer.makeStringAndClear());
494 			SvXMLElementExport aElemDPM(rExport, XML_NAMESPACE_TABLE, XML_DATA_PILOT_MEMBER, sal_True, sal_True);
495 			rExport.CheckAttrList();
496 		}
497 	}
498 }
499 
WriteLevels(ScDPSaveDimension * pDim)500 void ScXMLExportDataPilot::WriteLevels(ScDPSaveDimension* pDim)
501 {
502     // #i114202# GetShowEmpty is only valid if HasShowEmpty is true.
503     if (pDim->HasShowEmpty())
504     {
505         rtl::OUStringBuffer sBuffer;
506         SvXMLUnitConverter::convertBool(sBuffer, pDim->GetShowEmpty());
507         rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_SHOW_EMPTY, sBuffer.makeStringAndClear());
508     }
509 	SvXMLElementExport aElemDPL(rExport, XML_NAMESPACE_TABLE, XML_DATA_PILOT_LEVEL, sal_True, sal_True);
510 
511     WriteSubTotals(pDim);
512     WriteMembers(pDim);
513     WriteAutoShowInfo(pDim);
514     WriteSortInfo(pDim);
515     WriteLayoutInfo(pDim);
516 	rExport.CheckAttrList();
517 }
518 
WriteDatePart(sal_Int32 nPart)519 void ScXMLExportDataPilot::WriteDatePart(sal_Int32 nPart)
520 {
521     switch(nPart)
522     {
523     case com::sun::star::sheet::DataPilotFieldGroupBy::SECONDS :
524         {
525             rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_GROUPED_BY, XML_SECONDS);
526         }
527         break;
528     case com::sun::star::sheet::DataPilotFieldGroupBy::MINUTES :
529         {
530             rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_GROUPED_BY, XML_MINUTES);
531         }
532         break;
533     case com::sun::star::sheet::DataPilotFieldGroupBy::HOURS :
534         {
535             rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_GROUPED_BY, XML_HOURS);
536         }
537         break;
538     case com::sun::star::sheet::DataPilotFieldGroupBy::DAYS :
539         {
540             rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_GROUPED_BY, XML_DAYS);
541         }
542         break;
543     case com::sun::star::sheet::DataPilotFieldGroupBy::MONTHS :
544         {
545             rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_GROUPED_BY, XML_MONTHS);
546         }
547         break;
548     case com::sun::star::sheet::DataPilotFieldGroupBy::QUARTERS :
549         {
550             rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_GROUPED_BY, XML_QUARTERS);
551         }
552         break;
553     case com::sun::star::sheet::DataPilotFieldGroupBy::YEARS :
554         {
555             rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_GROUPED_BY, XML_YEARS);
556         }
557         break;
558     }
559 }
560 
WriteNumGroupInfo(const ScDPNumGroupInfo & rGroupInfo)561 void ScXMLExportDataPilot::WriteNumGroupInfo(const ScDPNumGroupInfo& rGroupInfo)
562 {
563     DBG_ASSERT(rGroupInfo.Enable, "group dimension should be enabled");
564     if (rGroupInfo.DateValues)
565     {
566         if (rGroupInfo.AutoStart)
567             rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATE_START, XML_AUTO);
568         else
569         {
570 			rtl::OUStringBuffer sDate;
571 			rExport.GetMM100UnitConverter().convertDateTime(sDate, rGroupInfo.Start);
572             rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATE_START, sDate.makeStringAndClear());
573         }
574         if (rGroupInfo.AutoEnd)
575             rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATE_END, XML_AUTO);
576         else
577         {
578 			rtl::OUStringBuffer sDate;
579 			rExport.GetMM100UnitConverter().convertDateTime(sDate, rGroupInfo.End);
580             rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATE_END, sDate.makeStringAndClear());
581         }
582     }
583     else
584     {
585         if (rGroupInfo.AutoStart)
586             rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_START, XML_AUTO);
587         else
588         {
589             rtl::OUString sValue( ::rtl::math::doubleToUString( rGroupInfo.Start,
590                         rtl_math_StringFormat_Automatic,
591                         rtl_math_DecimalPlaces_Max, '.', sal_True));
592             rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_START, sValue);
593         }
594         if (rGroupInfo.AutoEnd)
595             rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_END, XML_AUTO);
596         else
597         {
598 			rtl::OUStringBuffer sDate;
599             rtl::OUString sValue( ::rtl::math::doubleToUString( rGroupInfo.End,
600                         rtl_math_StringFormat_Automatic,
601                         rtl_math_DecimalPlaces_Max, '.', sal_True));
602             rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_END, sValue);
603         }
604     }
605     rtl::OUString sValue( ::rtl::math::doubleToUString( rGroupInfo.Step,
606                 rtl_math_StringFormat_Automatic,
607                 rtl_math_DecimalPlaces_Max, '.', sal_True));
608     rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_STEP, sValue);
609 }
610 
WriteGroupDimAttributes(const ScDPSaveGroupDimension * pGroupDim)611 void ScXMLExportDataPilot::WriteGroupDimAttributes(const ScDPSaveGroupDimension* pGroupDim)
612 {
613     if (pGroupDim)
614     {
615         rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_IS_GROUP_FIELD, XML_TRUE);
616         rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_SOURCE_FIELD_NAME, pGroupDim->GetSourceDimName());
617         if (pGroupDim->GetDatePart())
618         {
619             WriteDatePart(pGroupDim->GetDatePart());
620             WriteNumGroupInfo(pGroupDim->GetDateInfo());
621         }
622     }
623 }
624 
WriteNumGroupDim(const ScDPSaveNumGroupDimension * pNumGroupDim)625 void ScXMLExportDataPilot::WriteNumGroupDim(const ScDPSaveNumGroupDimension* pNumGroupDim)
626 {
627     if (pNumGroupDim)
628     {
629         rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_IS_GROUP_FIELD, XML_TRUE);
630         if (pNumGroupDim->GetDatePart())
631         {
632             WriteDatePart(pNumGroupDim->GetDatePart());
633             WriteNumGroupInfo(pNumGroupDim->GetDateInfo());
634         }
635         else
636         {
637             WriteNumGroupInfo(pNumGroupDim->GetInfo());
638         }
639     }
640 }
641 
WriteGroupDimElements(ScDPSaveDimension * pDim,const ScDPDimensionSaveData * pDimData)642 void ScXMLExportDataPilot::WriteGroupDimElements(ScDPSaveDimension* pDim, const ScDPDimensionSaveData* pDimData)
643 {
644     const ScDPSaveGroupDimension* pGroupDim = NULL;
645     const ScDPSaveNumGroupDimension* pNumGroupDim = NULL;
646     if (pDimData)
647     {
648         pGroupDim = pDimData->GetNamedGroupDim(pDim->GetName());
649         WriteGroupDimAttributes(pGroupDim);
650         pNumGroupDim = pDimData->GetNumGroupDim(pDim->GetName());
651         WriteNumGroupDim(pNumGroupDim);
652 
653         DBG_ASSERT((!pGroupDim || !pNumGroupDim), "there should be no NumGroup and Group at the same field");
654     }
655     if (pGroupDim || pNumGroupDim)
656     {
657 	    SvXMLElementExport aElemDPGs(rExport, XML_NAMESPACE_TABLE, XML_DATA_PILOT_GROUPS, sal_True, sal_True);
658         if (pGroupDim)
659         {
660             if (!pGroupDim->GetDatePart())
661             {
662                 sal_Int32 nCount = pGroupDim->GetGroupCount();
663                 for (sal_Int32 i = 0; i < nCount; ++i)
664                 {
665                     const ScDPSaveGroupItem* pGroup = pGroupDim->GetGroupByIndex( i );
666                     if (pGroup)
667                     {
668                         rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_NAME, pGroup->GetGroupName());
669     	                SvXMLElementExport aElemDPG(rExport, XML_NAMESPACE_TABLE, XML_DATA_PILOT_GROUP, sal_True, sal_True);
670                         sal_Int32 nElemCount = pGroup->GetElementCount();
671                         for(sal_Int32 j = 0; j < nElemCount; ++j)
672                         {
673                             const String* pElem = pGroup->GetElementByIndex( j );
674                             if (pElem)
675                             {
676                                 rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_NAME, *pElem);
677         	                    SvXMLElementExport aElemDPM(rExport, XML_NAMESPACE_TABLE, XML_DATA_PILOT_MEMBER, sal_True, sal_True);
678                             }
679                         }
680                     }
681                 }
682             }
683         }
684     }
685 }
686 
WriteDimension(ScDPSaveDimension * pDim,const ScDPDimensionSaveData * pDimData)687 void ScXMLExportDataPilot::WriteDimension(ScDPSaveDimension* pDim, const ScDPDimensionSaveData* pDimData)
688 {
689 	rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_SOURCE_FIELD_NAME, rtl::OUString(pDim->GetName()));
690     if (rExport.getDefaultVersion() == SvtSaveOptions::ODFVER_LATEST)
691     {
692         // Export display names only for ODF 1.2 extended or later.
693         const OUString* pLayoutName = pDim->GetLayoutName();
694         if (pLayoutName)
695             rExport.AddAttribute(XML_NAMESPACE_TABLE_EXT, XML_DISPLAY_NAME, *pLayoutName);
696     }
697 
698 	if (pDim->IsDataLayout())
699 		rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_IS_DATA_LAYOUT_FIELD, XML_TRUE);
700 	rtl::OUString sValueStr;
701 	ScXMLConverter::GetStringFromOrientation( sValueStr,
702 		(sheet::DataPilotFieldOrientation) pDim->GetOrientation() );
703 	if( sValueStr.getLength() )
704 		rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ORIENTATION, sValueStr );
705     if (pDim->GetOrientation() == sheet::DataPilotFieldOrientation_PAGE)
706         if (pDim->HasCurrentPage())
707             rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_SELECTED_PAGE, pDim->GetCurrentPage());
708 	if (pDim->GetUsedHierarchy() != 1)
709 	{
710 		rtl::OUStringBuffer sBuffer;
711 		SvXMLUnitConverter::convertNumber(sBuffer, pDim->GetUsedHierarchy());
712 		rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_USED_HIERARCHY, sBuffer.makeStringAndClear());
713 	}
714 	ScXMLConverter::GetStringFromFunction( sValueStr,
715 		(sheet::GeneralFunction) pDim->GetFunction() );
716 	rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FUNCTION, sValueStr);
717 
718     SvXMLElementExport aElemDPF(rExport, XML_NAMESPACE_TABLE, XML_DATA_PILOT_FIELD, sal_True, sal_True);
719     WriteFieldReference(pDim);
720     WriteLevels(pDim);
721     if( pDim->GetOrientation() != sheet::DataPilotFieldOrientation_DATA )
722         WriteGroupDimElements(pDim, pDimData);
723 }
724 
WriteDimensions(ScDPSaveData * pDPSave)725 void ScXMLExportDataPilot::WriteDimensions(ScDPSaveData* pDPSave)
726 {
727 	List aDimensions = pDPSave->GetDimensions();
728 	sal_Int32 nDimCount = aDimensions.Count();
729 	for (sal_Int32 nDim = 0; nDim < nDimCount; nDim++)
730 	{
731 		WriteDimension((ScDPSaveDimension*)aDimensions.GetObject(nDim), pDPSave->GetExistingDimensionData());
732 	}
733 }
734 
WriteGrandTotal(::xmloff::token::XMLTokenEnum eOrient,bool bVisible,const OUString * pGrandTotal)735 void ScXMLExportDataPilot::WriteGrandTotal(::xmloff::token::XMLTokenEnum eOrient, bool bVisible, const OUString* pGrandTotal)
736 {
737     rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DISPLAY, bVisible ? XML_TRUE : XML_FALSE);
738     rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ORIENTATION, eOrient);
739     if (pGrandTotal)
740         rExport.AddAttribute(XML_NAMESPACE_TABLE_EXT, XML_DISPLAY_NAME, *pGrandTotal);
741 
742     SvXMLElementExport aElemGrandTotal(rExport, XML_NAMESPACE_TABLE_EXT, XML_DATA_PILOT_GRAND_TOTAL, sal_True, sal_True);
743 }
744 
WriteDataPilots(const uno::Reference<sheet::XSpreadsheetDocument> &)745 void ScXMLExportDataPilot::WriteDataPilots(const uno::Reference <sheet::XSpreadsheetDocument>& /* xSpreadDoc */)
746 {
747 	pDoc = rExport.GetDocument();
748 	if (pDoc)
749 	{
750 		ScDPCollection* pDPs = pDoc->GetDPCollection();
751 		if (pDPs)
752 		{
753 			sal_Int16 nDPCount = pDPs->GetCount();
754 			if (nDPCount > 0)
755 			{
756 				SvXMLElementExport aElemDPs(rExport, XML_NAMESPACE_TABLE, XML_DATA_PILOT_TABLES, sal_True, sal_True);
757 				rExport.CheckAttrList();
758 				for (sal_Int16 i = 0; i < nDPCount; ++i)
759 				{
760 					ScDPSaveData* pDPSave = (*pDPs)[i]->GetSaveData();
761 					if (pDPSave)
762 					{
763 						ScRange aOutRange((*pDPs)[i]->GetOutRange());
764 						rtl::OUString sTargetRangeAddress;
765 						ScRangeStringConverter::GetStringFromRange( sTargetRangeAddress, aOutRange, pDoc, ::formula::FormulaGrammar::CONV_OOO );
766 						ScDocAttrIterator aAttrItr(pDoc, aOutRange.aStart.Tab(),
767 							aOutRange.aStart.Col(), aOutRange.aStart.Row(),
768 							aOutRange.aEnd.Col(), aOutRange.aEnd.Row());
769 						SCCOL nCol;
770 						SCROW nRow1, nRow2;
771 						rtl::OUString sOUButtonList;
772 						const ScPatternAttr* pAttr = aAttrItr.GetNext(nCol, nRow1, nRow2);
773 						while (pAttr)
774 						{
775 							ScMergeFlagAttr& rItem = (ScMergeFlagAttr&)pAttr->GetItem(ATTR_MERGE_FLAG);
776 							if (rItem.HasButton())
777 							{
778 								for (SCROW nButtonRow = nRow1; nButtonRow <= nRow2; ++nButtonRow)
779 								{
780 									ScAddress aButtonAddr(nCol, nButtonRow, aOutRange.aStart.Tab());
781 									ScRangeStringConverter::GetStringFromAddress(
782                                         sOUButtonList, aButtonAddr, pDoc, ::formula::FormulaGrammar::CONV_OOO, ' ', sal_True );
783 								}
784 							}
785 							pAttr = aAttrItr.GetNext(nCol, nRow1, nRow2);
786 						}
787 						rtl::OUString sName((*pDPs)[i]->GetName());
788 						rtl::OUString sApplicationData((*pDPs)[i]->GetTag());
789 						sal_Bool bRowGrand = pDPSave->GetRowGrand();
790 						sal_Bool bColumnGrand = pDPSave->GetColumnGrand();
791 						rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_NAME, sName);
792 						rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_APPLICATION_DATA, sApplicationData);
793 						rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_TARGET_RANGE_ADDRESS, sTargetRangeAddress);
794 						rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_BUTTONS, sOUButtonList);
795 						if (!(bRowGrand && bColumnGrand))
796 						{
797 							if (bRowGrand)
798 								rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_GRAND_TOTAL, XML_ROW);
799 							else if (bColumnGrand)
800 								rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_GRAND_TOTAL, XML_COLUMN);
801 							else
802 								rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_GRAND_TOTAL, XML_NONE);
803 						}
804 						if (pDPSave->GetIgnoreEmptyRows())
805 							rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_IGNORE_EMPTY_ROWS, XML_TRUE);
806 						if (pDPSave->GetRepeatIfEmpty())
807 							rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_IDENTIFY_CATEGORIES, XML_TRUE);
808                         if (!pDPSave->GetFilterButton())
809                             rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_SHOW_FILTER_BUTTON, XML_FALSE);
810                         if (!pDPSave->GetDrillDown())
811                             rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DRILL_DOWN_ON_DOUBLE_CLICK, XML_FALSE);
812 						SvXMLElementExport aElemDP(rExport, XML_NAMESPACE_TABLE, XML_DATA_PILOT_TABLE, sal_True, sal_True);
813 
814                         // grand total elements.
815 
816                         const OUString* pGrandTotalName = pDPSave->GetGrandTotalName();
817                         if (pGrandTotalName && rExport.getDefaultVersion() == SvtSaveOptions::ODFVER_LATEST)
818                         {
819                             // Use the new data-pilot-grand-total element.
820                             if (bRowGrand && bColumnGrand)
821                             {
822                                 WriteGrandTotal(XML_BOTH, true, pGrandTotalName);
823                             }
824                             else
825                             {
826                                 WriteGrandTotal(XML_ROW, bRowGrand, pGrandTotalName);
827                                 WriteGrandTotal(XML_COLUMN, bColumnGrand, pGrandTotalName);
828                             }
829                         }
830 
831 						rExport.CheckAttrList();
832 						if ((*pDPs)[i]->IsSheetData())
833 						{
834 							const ScSheetSourceDesc* pSheetSource = (*pDPs)[i]->GetSheetDesc();
835 							rtl::OUString sCellRangeAddress;
836 							ScRangeStringConverter::GetStringFromRange( sCellRangeAddress, pSheetSource->aSourceRange, pDoc, ::formula::FormulaGrammar::CONV_OOO );
837 							rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CELL_RANGE_ADDRESS, sCellRangeAddress);
838 							SvXMLElementExport aElemSCR(rExport, XML_NAMESPACE_TABLE, XML_SOURCE_CELL_RANGE, sal_True, sal_True);
839 							rExport.CheckAttrList();
840 							WriteDPFilter(pSheetSource->aQueryParam);
841 						}
842 						else if ((*pDPs)[i]->IsImportData())
843 						{
844 							const ScImportSourceDesc* pImpSource = (*pDPs)[i]->GetImportSourceDesc();
845 							switch (pImpSource->nType)
846 							{
847 								case sheet::DataImportMode_NONE : break;
848 								case sheet::DataImportMode_QUERY :
849 								{
850 									rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATABASE_NAME, rtl::OUString(pImpSource->aDBName));
851 									rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_QUERY_NAME, rtl::OUString(pImpSource->aObject));
852 									SvXMLElementExport aElemID(rExport, XML_NAMESPACE_TABLE, XML_DATABASE_SOURCE_QUERY, sal_True, sal_True);
853 									rExport.CheckAttrList();
854 								}
855 								break;
856 								case sheet::DataImportMode_TABLE :
857 								{
858 									rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATABASE_NAME, rtl::OUString(pImpSource->aDBName));
859 									rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_TABLE_NAME, rtl::OUString(pImpSource->aObject));
860 									SvXMLElementExport aElemID(rExport, XML_NAMESPACE_TABLE, XML_DATABASE_SOURCE_TABLE, sal_True, sal_True);
861 									rExport.CheckAttrList();
862 								}
863 								break;
864 								case sheet::DataImportMode_SQL :
865 								{
866 									rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATABASE_NAME, rtl::OUString(pImpSource->aDBName));
867 									rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_SQL_STATEMENT, rtl::OUString(pImpSource->aObject));
868 									if (!pImpSource->bNative)
869 										rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_PARSE_SQL_STATEMENT, XML_TRUE);
870 									SvXMLElementExport aElemID(rExport, XML_NAMESPACE_TABLE, XML_DATABASE_SOURCE_SQL, sal_True, sal_True);
871 									rExport.CheckAttrList();
872 								}
873 								break;
874 							}
875 						}
876 						else if ((*pDPs)[i]->IsServiceData())
877 						{
878 							const ScDPServiceDesc* pServSource = (*pDPs)[i]->GetDPServiceDesc();
879 							rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_NAME, rtl::OUString(pServSource->aServiceName));
880 							rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_SOURCE_NAME, rtl::OUString(pServSource->aParSource));
881 							rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_OBJECT_NAME, rtl::OUString(pServSource->aParName));
882 							rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_USER_NAME, rtl::OUString(pServSource->aParUser));
883                             // #i111754# leave out password attribute as long as DataPilotSource doesn't specify the content
884                             // rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_PASSWORD, rtl::OUString(pServSource->aParPass));
885 							SvXMLElementExport aElemSD(rExport, XML_NAMESPACE_TABLE, XML_SOURCE_SERVICE, sal_True, sal_True);
886 							rExport.CheckAttrList();
887 						}
888                         WriteDimensions(pDPSave);
889 					}
890 				}
891 			}
892 		}
893 	}
894 }
895