fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / filter / excel / xepivotxml.cxx
blobfa04e1f2558b99a3c015837ff6a52976e518db35
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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 */
10 #include <xepivotxml.hxx>
11 #include <dpcache.hxx>
12 #include <dpobject.hxx>
13 #include <dpsave.hxx>
14 #include <dputil.hxx>
15 #include <document.hxx>
17 #include <oox/export/utils.hxx>
19 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
20 #include <com/sun/star/sheet/DataPilotOutputRangeType.hpp>
21 #include <com/sun/star/sheet/GeneralFunction.hpp>
23 #include <vector>
25 using namespace oox;
26 using namespace com::sun::star;
28 namespace {
30 void savePivotCacheRecordsXml( XclExpXmlStream& rStrm, const ScDPCache& rCache )
32 SCROW nCount = rCache.GetDataSize();
33 size_t nFieldCount = rCache.GetFieldCount();
35 sax_fastparser::FSHelperPtr& pRecStrm = rStrm.GetCurrentStream();
36 pRecStrm->startElement(XML_pivotCacheRecords,
37 XML_xmlns, "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
38 FSNS(XML_xmlns, XML_r), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
39 XML_count, OString::number(static_cast<long>(nCount)).getStr(),
40 FSEND);
42 for (SCROW i = 0; i < nCount; ++i)
44 pRecStrm->startElement(XML_r, FSEND);
45 for (size_t nField = 0; nField < nFieldCount; ++nField)
47 const ScDPCache::IndexArrayType* pArray = rCache.GetFieldIndexArray(nField);
48 assert(pArray);
49 assert(static_cast<size_t>(i) < pArray->size());
50 pRecStrm->singleElement(XML_x, XML_v, OString::number((*pArray)[i]), FSEND);
52 pRecStrm->endElement(XML_r);
55 pRecStrm->endElement(XML_pivotCacheRecords);
58 const char* toOOXMLAxisType( sheet::DataPilotFieldOrientation eOrient )
60 switch (eOrient)
62 case sheet::DataPilotFieldOrientation_COLUMN:
63 return "axisCol";
64 case sheet::DataPilotFieldOrientation_ROW:
65 return "axisRow";
66 case sheet::DataPilotFieldOrientation_PAGE:
67 return "axisPage";
68 case sheet::DataPilotFieldOrientation_DATA:
69 return "axisValues";
70 case sheet::DataPilotFieldOrientation_HIDDEN:
71 default:
75 return "";
78 const char* toOOXMLSubtotalType( sheet::GeneralFunction eFunc )
80 switch (eFunc)
82 case sheet::GeneralFunction_SUM:
83 return "sum";
84 case sheet::GeneralFunction_COUNT:
85 return "count";
86 case sheet::GeneralFunction_AVERAGE:
87 return "average";
88 case sheet::GeneralFunction_MAX:
89 return "max";
90 case sheet::GeneralFunction_MIN:
91 return "min";
92 case sheet::GeneralFunction_PRODUCT:
93 return "product";
94 case sheet::GeneralFunction_COUNTNUMS:
95 return "countNums";
96 case sheet::GeneralFunction_STDEV:
97 return "stdDev";
98 case sheet::GeneralFunction_STDEVP:
99 return "stdDevp";
100 case sheet::GeneralFunction_VAR:
101 return "var";
102 case sheet::GeneralFunction_VARP:
103 return "varp";
104 case sheet::GeneralFunction_NONE:
105 case sheet::GeneralFunction_AUTO:
106 default:
109 return NULL;
114 XclExpXmlPivotCaches::XclExpXmlPivotCaches( const XclExpRoot& rRoot ) :
115 XclExpRoot(rRoot) {}
117 void XclExpXmlPivotCaches::SaveXml( XclExpXmlStream& rStrm )
119 sax_fastparser::FSHelperPtr& pWorkbookStrm = rStrm.GetCurrentStream();
120 pWorkbookStrm->startElement(XML_pivotCaches, FSEND);
122 for (size_t i = 0, n = maCaches.size(); i < n; ++i)
124 const Entry& rEntry = maCaches[i];
126 sal_Int32 nCacheId = i + 1;
127 OUString aRelId;
128 sax_fastparser::FSHelperPtr pPCStrm = rStrm.CreateOutputStream(
129 XclXmlUtils::GetStreamName("xl/pivotCache/", "pivotCacheDefinition", nCacheId),
130 XclXmlUtils::GetStreamName(NULL, "pivotCache/pivotCacheDefinition", nCacheId),
131 rStrm.GetCurrentStream()->getOutputStream(),
132 CREATE_XL_CONTENT_TYPE("pivotCacheDefinition"),
133 CREATE_OFFICEDOC_RELATION_TYPE("pivotCacheDefinition"),
134 &aRelId);
136 pWorkbookStrm->singleElement(XML_pivotCache,
137 XML_cacheId, OString::number(nCacheId).getStr(),
138 FSNS(XML_r, XML_id), XclXmlUtils::ToOString(aRelId).getStr(),
139 FSEND);
141 rStrm.PushStream(pPCStrm);
142 SavePivotCacheXml(rStrm, rEntry, nCacheId);
143 rStrm.PopStream();
146 pWorkbookStrm->endElement(XML_pivotCaches);
149 void XclExpXmlPivotCaches::SetCaches( const std::vector<Entry>& rCaches )
151 maCaches = rCaches;
154 bool XclExpXmlPivotCaches::HasCaches() const
156 return !maCaches.empty();
159 const XclExpXmlPivotCaches::Entry* XclExpXmlPivotCaches::GetCache( sal_Int32 nCacheId ) const
161 if (nCacheId <= 0)
162 // cache ID is 1-based.
163 return NULL;
165 size_t nPos = nCacheId - 1;
166 if (nPos >= maCaches.size())
167 return NULL;
169 return &maCaches[nPos];
172 void XclExpXmlPivotCaches::SavePivotCacheXml( XclExpXmlStream& rStrm, const Entry& rEntry, sal_Int32 nCounter )
174 assert(rEntry.mpCache);
175 const ScDPCache& rCache = *rEntry.mpCache;
177 sax_fastparser::FSHelperPtr& pDefStrm = rStrm.GetCurrentStream();
179 OUString aRelId;
180 sax_fastparser::FSHelperPtr pRecStrm = rStrm.CreateOutputStream(
181 XclXmlUtils::GetStreamName("xl/pivotCache/", "pivotCacheRecords", nCounter),
182 XclXmlUtils::GetStreamName(NULL, "pivotCacheRecords", nCounter),
183 pDefStrm->getOutputStream(),
184 CREATE_XL_CONTENT_TYPE("pivotCacheRecords"),
185 CREATE_OFFICEDOC_RELATION_TYPE("pivotCacheRecords"),
186 &aRelId);
188 rStrm.PushStream(pRecStrm);
189 savePivotCacheRecordsXml(rStrm, rCache);
190 rStrm.PopStream();
192 pDefStrm->startElement(XML_pivotCacheDefinition,
193 XML_xmlns, "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
194 FSNS(XML_xmlns, XML_r), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
195 FSNS(XML_r, XML_id), XclXmlUtils::ToOString(aRelId).getStr(),
196 XML_recordCount, OString::number(rEntry.mpCache->GetDataSize()).getStr(),
197 FSEND);
199 if (rEntry.meType == Worksheet)
201 pDefStrm->startElement(XML_cacheSource,
202 XML_type, "worksheet",
203 FSEND);
205 OUString aSheetName;
206 GetDoc().GetName(rEntry.maSrcRange.aStart.Tab(), aSheetName);
207 pDefStrm->singleElement(XML_worksheetSource,
208 XML_ref, XclXmlUtils::ToOString(rEntry.maSrcRange).getStr(),
209 XML_sheet, XclXmlUtils::ToOString(aSheetName).getStr(),
210 FSEND);
212 pDefStrm->endElement(XML_cacheSource);
215 size_t nCount = rCache.GetFieldCount();
216 pDefStrm->startElement(XML_cacheFields,
217 XML_count, OString::number(static_cast<long>(nCount)).getStr(),
218 FSEND);
220 for (size_t i = 0; i < nCount; ++i)
222 OUString aName = rCache.GetDimensionName(i);
224 pDefStrm->startElement(XML_cacheField,
225 XML_name, XclXmlUtils::ToOString(aName).getStr(),
226 XML_numFmtId, OString::number(0).getStr(),
227 FSEND);
229 const ScDPCache::ItemsType& rFieldItems = rCache.GetDimMemberValues(i);
231 pDefStrm->startElement(XML_sharedItems,
232 XML_count, OString::number(static_cast<long>(rFieldItems.size())).getStr(),
233 FSEND);
235 ScDPCache::ItemsType::const_iterator it = rFieldItems.begin(), itEnd = rFieldItems.end();
236 for (; it != itEnd; ++it)
238 const ScDPItemData& rItem = *it;
239 switch (rItem.GetType())
241 case ScDPItemData::String:
242 pDefStrm->singleElement(XML_s,
243 XML_v, XclXmlUtils::ToOString(rItem.GetString()).getStr(),
244 FSEND);
245 break;
246 case ScDPItemData::Value:
247 pDefStrm->singleElement(XML_n,
248 XML_v, OString::number(rItem.GetValue()).getStr(),
249 FSEND);
250 break;
251 case ScDPItemData::Empty:
252 pDefStrm->singleElement(XML_m, FSEND);
253 break;
254 case ScDPItemData::Error:
255 pDefStrm->singleElement(XML_e,
256 XML_v, XclXmlUtils::ToOString(rItem.GetString()).getStr(),
257 FSEND);
258 break;
259 case ScDPItemData::GroupValue:
260 case ScDPItemData::RangeStart:
261 // TODO : What do we do with these types?
262 pDefStrm->singleElement(XML_m, FSEND);
263 break;
264 default:
269 pDefStrm->endElement(XML_sharedItems);
270 pDefStrm->endElement(XML_cacheField);
273 pDefStrm->endElement(XML_cacheFields);
275 pDefStrm->endElement(XML_pivotCacheDefinition);
278 XclExpXmlPivotTableManager::XclExpXmlPivotTableManager( const XclExpRoot& rRoot ) :
279 XclExpRoot(rRoot), maCaches(rRoot) {}
281 void XclExpXmlPivotTableManager::Initialize()
283 const ScDocument& rDoc = GetDoc();
284 if (!rDoc.HasPivotTable())
285 // No pivot table to export.
286 return;
288 const ScDPCollection* pDPColl = rDoc.GetDPCollection();
289 if (!pDPColl)
290 return;
292 // Go through the caches first.
294 std::vector<XclExpXmlPivotCaches::Entry> aCaches;
295 const ScDPCollection::SheetCaches& rSheetCaches = pDPColl->GetSheetCaches();
296 const std::vector<ScRange>& rRanges = rSheetCaches.getAllRanges();
297 for (size_t i = 0, n = rRanges.size(); i < n; ++i)
299 const ScDPCache* pCache = rSheetCaches.getExistingCache(rRanges[i]);
300 if (!pCache)
301 continue;
303 // Get all pivot objects that reference this cache, and set up an
304 // object to cache ID mapping.
305 const ScDPCache::ObjectSetType& rRefs = pCache->GetAllReferences();
306 ScDPCache::ObjectSetType::const_iterator it = rRefs.begin(), itEnd = rRefs.end();
307 for (; it != itEnd; ++it)
308 maCacheIdMap.insert(CacheIdMapType::value_type(*it, aCaches.size()+1));
310 XclExpXmlPivotCaches::Entry aEntry;
311 aEntry.meType = XclExpXmlPivotCaches::Worksheet;
312 aEntry.mpCache = pCache;
313 aEntry.maSrcRange = rRanges[i];
314 aCaches.push_back(aEntry); // Cache ID equals position + 1.
317 // TODO : Handle name and database caches as well.
319 for (size_t i = 0, n = pDPColl->GetCount(); i < n; ++i)
321 const ScDPObject* pDPObj = (*pDPColl)[i];
322 assert(pDPObj); // We don't store NULL here.
324 // Get the cache ID for this pivot table.
325 CacheIdMapType::iterator itCache = maCacheIdMap.find(pDPObj);
326 if (itCache == maCacheIdMap.end())
327 // No cache ID found. Something is wrong here....
328 continue;
330 sal_Int32 nCacheId = itCache->second;
331 SCTAB nTab = pDPObj->GetOutRange().aStart.Tab();
333 TablesType::iterator it = maTables.find(nTab);
334 if (it == maTables.end())
336 // Insert a new instance for this sheet index.
337 std::pair<TablesType::iterator, bool> r =
338 maTables.insert(nTab, new XclExpXmlPivotTables(GetRoot(), maCaches));
339 it = r.first;
342 XclExpXmlPivotTables* p = it->second;
343 p->AppendTable(pDPObj, nCacheId, i+1);
346 maCaches.SetCaches(aCaches);
349 XclExpXmlPivotCaches& XclExpXmlPivotTableManager::GetCaches()
351 return maCaches;
354 XclExpXmlPivotTables* XclExpXmlPivotTableManager::GetTablesBySheet( SCTAB nTab )
356 TablesType::iterator it = maTables.find(nTab);
357 return it == maTables.end() ? NULL : it->second;
360 XclExpXmlPivotTables::Entry::Entry( const ScDPObject* pTable, sal_Int32 nCacheId, sal_Int32 nPivotId ) :
361 mpTable(pTable), mnCacheId(nCacheId), mnPivotId(nPivotId) {}
363 XclExpXmlPivotTables::XclExpXmlPivotTables( const XclExpRoot& rRoot, const XclExpXmlPivotCaches& rCaches ) :
364 XclExpRoot(rRoot), mrCaches(rCaches) {}
366 void XclExpXmlPivotTables::SaveXml( XclExpXmlStream& rStrm )
368 sax_fastparser::FSHelperPtr& pWSStrm = rStrm.GetCurrentStream(); // worksheet stream
370 sal_Int32 nCounter = 1; // 1-based
371 TablesType::iterator it = maTables.begin(), itEnd = maTables.end();
372 for (; it != itEnd; ++it, ++nCounter)
374 const ScDPObject& rObj = *it->mpTable;
375 sal_Int32 nCacheId = it->mnCacheId;
376 sal_Int32 nPivotId = it->mnPivotId;
378 sax_fastparser::FSHelperPtr pPivotStrm = rStrm.CreateOutputStream(
379 XclXmlUtils::GetStreamName("xl/pivotTables/", "pivotTable", nPivotId),
380 XclXmlUtils::GetStreamName(NULL, "../pivotTables/pivotTable", nPivotId),
381 pWSStrm->getOutputStream(),
382 CREATE_XL_CONTENT_TYPE("pivotTable"),
383 CREATE_OFFICEDOC_RELATION_TYPE("pivotTable"),
384 NULL);
386 rStrm.PushStream(pPivotStrm);
387 SavePivotTableXml(rStrm, rObj, nCacheId);
388 rStrm.PopStream();
392 namespace {
394 struct DataField
396 long mnPos; // field index in pivot cache.
397 const ScDPSaveDimension* mpDim;
399 DataField( long nPos, const ScDPSaveDimension* pDim ) : mnPos(nPos), mpDim(pDim) {}
404 void XclExpXmlPivotTables::SavePivotTableXml( XclExpXmlStream& rStrm, const ScDPObject& rDPObj, sal_Int32 nCacheId )
406 typedef std::unordered_map<OUString, long, OUStringHash> NameToIdMapType;
408 const XclExpXmlPivotCaches::Entry* pCacheEntry = mrCaches.GetCache(nCacheId);
409 if (!pCacheEntry)
410 // Something is horribly wrong. Check your logic.
411 return;
413 const ScDPCache& rCache = *pCacheEntry->mpCache;
415 const ScDPSaveData& rSaveData = *rDPObj.GetSaveData();
417 size_t nFieldCount = rCache.GetFieldCount();
418 std::vector<const ScDPSaveDimension*> aCachedDims;
419 NameToIdMapType aNameToIdMap;
421 aCachedDims.reserve(nFieldCount);
422 for (size_t i = 0; i < nFieldCount; ++i)
424 OUString aName = rCache.GetDimensionName(i);
425 aNameToIdMap.insert(NameToIdMapType::value_type(aName, aCachedDims.size()));
426 const ScDPSaveDimension* pDim = rSaveData.GetExistingDimensionByName(aName);
427 aCachedDims.push_back(pDim);
430 std::vector<long> aRowFields;
431 std::vector<long> aColFields;
432 std::vector<long> aPageFields;
433 std::vector<DataField> aDataFields;
435 // Use dimensions in the save data to get their correct ordering.
436 // Dimension order here is significant as they specify the order of
437 // appearance in each axis.
438 const ScDPSaveData::DimsType& rDims = rSaveData.GetDimensions();
440 for (size_t i = 0, n = rDims.size(); i < n; ++i)
442 const ScDPSaveDimension& rDim = rDims[i];
444 long nPos = -1; // position in cache
445 if (rDim.IsDataLayout())
446 nPos = -2; // Excel uses an index of -2 to indicate a data layout field.
447 else
449 OUString aSrcName = ScDPUtil::getSourceDimensionName(rDim.GetName());
450 NameToIdMapType::iterator it = aNameToIdMap.find(aSrcName);
451 if (it != aNameToIdMap.end())
452 nPos = it->second;
454 if (nPos == -1)
455 continue;
457 if (!aCachedDims[nPos])
458 continue;
461 sheet::DataPilotFieldOrientation eOrient =
462 static_cast<sheet::DataPilotFieldOrientation>(rDim.GetOrientation());
464 switch (eOrient)
466 case sheet::DataPilotFieldOrientation_COLUMN:
467 aColFields.push_back(nPos);
468 break;
469 case sheet::DataPilotFieldOrientation_ROW:
470 aRowFields.push_back(nPos);
471 break;
472 case sheet::DataPilotFieldOrientation_PAGE:
473 aPageFields.push_back(nPos);
474 break;
475 case sheet::DataPilotFieldOrientation_DATA:
476 aDataFields.push_back(DataField(nPos, &rDim));
477 break;
478 case sheet::DataPilotFieldOrientation_HIDDEN:
479 default:
484 sax_fastparser::FSHelperPtr& pPivotStrm = rStrm.GetCurrentStream();
485 pPivotStrm->startElement(XML_pivotTableDefinition,
486 XML_xmlns, "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
487 XML_name, XclXmlUtils::ToOString(rDPObj.GetName()).getStr(),
488 XML_cacheId, OString::number(nCacheId).getStr(),
489 XML_applyNumberFormats, BS(false),
490 XML_applyBorderFormats, BS(false),
491 XML_applyFontFormats, BS(false),
492 XML_applyPatternFormats, BS(false),
493 XML_applyAlignmentFormats, BS(false),
494 XML_applyWidthHeightFormats, BS(false),
495 XML_dataCaption, "Values",
496 XML_useAutoFormatting, BS(false),
497 XML_itemPrintTitles, BS(true),
498 XML_indent, BS(false),
499 XML_outline, BS(true),
500 XML_outlineData, BS(true),
501 FSEND);
503 // NB: Excel's range does not include page field area (if any).
504 ScRange aOutRange = rDPObj.GetOutputRangeByType(sheet::DataPilotOutputRangeType::TABLE);
506 sal_Int32 nFirstHeaderRow = aColFields.size();
507 sal_Int32 nFirstDataRow = 2;
508 sal_Int32 nFirstDataCol = 1;
509 ScRange aResRange = rDPObj.GetOutputRangeByType(sheet::DataPilotOutputRangeType::RESULT);
510 if (aOutRange.IsValid() && aResRange.IsValid())
512 nFirstDataRow = aResRange.aStart.Row() - aOutRange.aStart.Row();
513 nFirstDataCol = aResRange.aStart.Col() - aOutRange.aStart.Col();
516 if (!aOutRange.IsValid())
517 aOutRange = rDPObj.GetOutRange();
519 pPivotStrm->write("<")->writeId(XML_location);
520 rStrm.WriteAttributes(XML_ref,
521 XclXmlUtils::ToOString(aOutRange),
522 XML_firstHeaderRow, OString::number(nFirstHeaderRow).getStr(),
523 XML_firstDataRow, OString::number(nFirstDataRow).getStr(),
524 XML_firstDataCol, OString::number(nFirstDataCol).getStr(),
525 FSEND);
527 if (!aPageFields.empty())
529 rStrm.WriteAttributes(XML_rowPageCount, OString::number(static_cast<long>(aPageFields.size())).getStr(), FSEND);
530 rStrm.WriteAttributes(XML_colPageCount, OString::number(1).getStr(), FSEND);
533 pPivotStrm->write("/>");
535 // <pivotFields> - It must contain all fields in the pivot cache even if
536 // only some of them are used in the pivot table. The order must be as
537 // they appear in the cache.
539 pPivotStrm->startElement(XML_pivotFields,
540 XML_count, OString::number(static_cast<long>(aCachedDims.size())).getStr(),
541 FSEND);
543 for (size_t i = 0, n = aCachedDims.size(); i < n; ++i)
545 const ScDPSaveDimension* pDim = aCachedDims[i];
546 if (!pDim)
548 pPivotStrm->singleElement(XML_pivotField,
549 XML_showAll, BS(false),
550 FSEND);
551 continue;
554 sheet::DataPilotFieldOrientation eOrient =
555 static_cast<sheet::DataPilotFieldOrientation>(pDim->GetOrientation());
557 if (eOrient == sheet::DataPilotFieldOrientation_HIDDEN)
559 pPivotStrm->singleElement(XML_pivotField,
560 XML_showAll, BS(false),
561 FSEND);
562 continue;
565 if (eOrient == sheet::DataPilotFieldOrientation_DATA)
567 pPivotStrm->singleElement(XML_pivotField,
568 XML_dataField, BS(true),
569 XML_showAll, BS(false),
570 FSEND);
572 continue;
575 pPivotStrm->startElement(XML_pivotField,
576 XML_axis, toOOXMLAxisType(eOrient),
577 XML_showAll, BS(false),
578 FSEND);
580 // TODO : Dump field items.
582 pPivotStrm->endElement(XML_pivotField);
585 pPivotStrm->endElement(XML_pivotFields);
587 // <rowFields>
589 if (!aRowFields.empty())
591 pPivotStrm->startElement(XML_rowFields,
592 XML_count, OString::number(static_cast<long>(aRowFields.size())),
593 FSEND);
595 std::vector<long>::iterator it = aRowFields.begin(), itEnd = aRowFields.end();
596 for (; it != itEnd; ++it)
598 pPivotStrm->singleElement(XML_field,
599 XML_x, OString::number(*it),
600 FSEND);
603 pPivotStrm->endElement(XML_rowFields);
606 // <rowItems>
608 // <colFields>
610 if (!aColFields.empty())
612 pPivotStrm->startElement(XML_colFields,
613 XML_count, OString::number(static_cast<long>(aColFields.size())),
614 FSEND);
616 std::vector<long>::iterator it = aColFields.begin(), itEnd = aColFields.end();
617 for (; it != itEnd; ++it)
619 pPivotStrm->singleElement(XML_field,
620 XML_x, OString::number(*it),
621 FSEND);
624 pPivotStrm->endElement(XML_colFields);
627 // <colItems>
629 // <pageFields>
631 if (!aPageFields.empty())
633 pPivotStrm->startElement(XML_pageFields,
634 XML_count, OString::number(static_cast<long>(aPageFields.size())),
635 FSEND);
637 std::vector<long>::iterator it = aPageFields.begin(), itEnd = aPageFields.end();
638 for (; it != itEnd; ++it)
640 pPivotStrm->singleElement(XML_pageField,
641 XML_fld, OString::number(*it),
642 XML_hier, OString::number(-1), // TODO : handle this correctly.
643 FSEND);
646 pPivotStrm->endElement(XML_pageFields);
649 // <dataFields>
651 if (!aDataFields.empty())
653 pPivotStrm->startElement(XML_dataFields,
654 XML_count, OString::number(static_cast<long>(aDataFields.size())),
655 FSEND);
657 std::vector<DataField>::iterator it = aDataFields.begin(), itEnd = aDataFields.end();
658 for (; it != itEnd; ++it)
660 long nDimIdx = it->mnPos;
661 assert(aCachedDims[nDimIdx]); // the loop above should have screened for NULL's.
662 const ScDPSaveDimension& rDim = *it->mpDim;
663 const OUString* pName = rDim.GetLayoutName();
664 pPivotStrm->write("<")->writeId(XML_dataField);
665 if (pName)
666 rStrm.WriteAttributes(XML_name, XclXmlUtils::ToOString(*pName), FSEND);
668 rStrm.WriteAttributes(XML_fld, OString::number(nDimIdx).getStr(), FSEND);
670 sheet::GeneralFunction eFunc = static_cast<sheet::GeneralFunction>(rDim.GetFunction());
671 const char* pSubtotal = toOOXMLSubtotalType(eFunc);
672 if (pSubtotal)
673 rStrm.WriteAttributes(XML_subtotal, pSubtotal, FSEND);
675 pPivotStrm->write("/>");
678 pPivotStrm->endElement(XML_dataFields);
681 OUStringBuffer aBuf("../pivotCache/pivotCacheDefinition");
682 aBuf.append(nCacheId);
683 aBuf.append(".xml");
685 rStrm.addRelation(
686 pPivotStrm->getOutputStream(),
687 CREATE_OFFICEDOC_RELATION_TYPE("pivotCacheDefinition"),
688 aBuf.makeStringAndClear());
690 pPivotStrm->endElement(XML_pivotTableDefinition);
693 void XclExpXmlPivotTables::AppendTable( const ScDPObject* pTable, sal_Int32 nCacheId, sal_Int32 nPivotId )
695 maTables.push_back(Entry(pTable, nCacheId, nPivotId));
698 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */