LCOV - code coverage report
Current view: top level - sc/source/filter/excel - xepivotxml.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 274 303 90.4 %
Date: 2015-06-13 12:38:46 Functions: 21 21 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  */
       9             : 
      10             : #include <xepivotxml.hxx>
      11             : #include <dpcache.hxx>
      12             : #include <dpobject.hxx>
      13             : #include <dpsave.hxx>
      14             : #include <dputil.hxx>
      15             : #include <document.hxx>
      16             : 
      17             : #include <oox/export/utils.hxx>
      18             : 
      19             : #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
      20             : #include <com/sun/star/sheet/DataPilotOutputRangeType.hpp>
      21             : #include <com/sun/star/sheet/GeneralFunction.hpp>
      22             : 
      23             : #include <vector>
      24             : 
      25             : using namespace oox;
      26             : using namespace com::sun::star;
      27             : 
      28             : namespace {
      29             : 
      30           2 : void savePivotCacheRecordsXml( XclExpXmlStream& rStrm, const ScDPCache& rCache )
      31             : {
      32           2 :     SCROW nCount = rCache.GetDataSize();
      33           2 :     size_t nFieldCount = rCache.GetFieldCount();
      34             : 
      35           2 :     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           2 :         FSEND);
      41             : 
      42          11 :     for (SCROW i = 0; i < nCount; ++i)
      43             :     {
      44           9 :         pRecStrm->startElement(XML_r, FSEND);
      45          43 :         for (size_t nField = 0; nField < nFieldCount; ++nField)
      46             :         {
      47          34 :             const ScDPCache::IndexArrayType* pArray = rCache.GetFieldIndexArray(nField);
      48             :             assert(pArray);
      49             :             assert(static_cast<size_t>(i) < pArray->size());
      50          34 :             pRecStrm->singleElement(XML_x, XML_v, OString::number((*pArray)[i]), FSEND);
      51             :         }
      52           9 :         pRecStrm->endElement(XML_r);
      53             :     }
      54             : 
      55           2 :     pRecStrm->endElement(XML_pivotCacheRecords);
      56           2 : }
      57             : 
      58           5 : const char* toOOXMLAxisType( sheet::DataPilotFieldOrientation eOrient )
      59             : {
      60           5 :     switch (eOrient)
      61             :     {
      62             :         case sheet::DataPilotFieldOrientation_COLUMN:
      63           1 :             return "axisCol";
      64             :         case sheet::DataPilotFieldOrientation_ROW:
      65           2 :             return "axisRow";
      66             :         case sheet::DataPilotFieldOrientation_PAGE:
      67           2 :             return "axisPage";
      68             :         case sheet::DataPilotFieldOrientation_DATA:
      69           0 :             return "axisValues";
      70             :         case sheet::DataPilotFieldOrientation_HIDDEN:
      71             :         default:
      72             :             ;
      73             :     }
      74             : 
      75           0 :     return "";
      76             : }
      77             : 
      78           3 : const char* toOOXMLSubtotalType( sheet::GeneralFunction eFunc )
      79             : {
      80           3 :     switch (eFunc)
      81             :     {
      82             :         case sheet::GeneralFunction_SUM:
      83           2 :             return "sum";
      84             :         case sheet::GeneralFunction_COUNT:
      85           1 :             return "count";
      86             :         case sheet::GeneralFunction_AVERAGE:
      87           0 :             return "average";
      88             :         case sheet::GeneralFunction_MAX:
      89           0 :             return "max";
      90             :         case sheet::GeneralFunction_MIN:
      91           0 :             return "min";
      92             :         case sheet::GeneralFunction_PRODUCT:
      93           0 :             return "product";
      94             :         case sheet::GeneralFunction_COUNTNUMS:
      95           0 :             return "countNums";
      96             :         case sheet::GeneralFunction_STDEV:
      97           0 :             return "stdDev";
      98             :         case sheet::GeneralFunction_STDEVP:
      99           0 :             return "stdDevp";
     100             :         case sheet::GeneralFunction_VAR:
     101           0 :             return "var";
     102             :         case sheet::GeneralFunction_VARP:
     103           0 :             return "varp";
     104             :         case sheet::GeneralFunction_NONE:
     105             :         case sheet::GeneralFunction_AUTO:
     106             :         default:
     107             :             ;
     108             :     }
     109           0 :     return NULL;
     110             : }
     111             : 
     112             : }
     113             : 
     114          55 : XclExpXmlPivotCaches::XclExpXmlPivotCaches( const XclExpRoot& rRoot ) :
     115          55 :     XclExpRoot(rRoot) {}
     116             : 
     117           2 : void XclExpXmlPivotCaches::SaveXml( XclExpXmlStream& rStrm )
     118             : {
     119           2 :     sax_fastparser::FSHelperPtr& pWorkbookStrm = rStrm.GetCurrentStream();
     120           2 :     pWorkbookStrm->startElement(XML_pivotCaches, FSEND);
     121             : 
     122           4 :     for (size_t i = 0, n = maCaches.size(); i < n; ++i)
     123             :     {
     124           2 :         const Entry& rEntry = maCaches[i];
     125             : 
     126           2 :         sal_Int32 nCacheId = i + 1;
     127           2 :         OUString aRelId;
     128             :         sax_fastparser::FSHelperPtr pPCStrm = rStrm.CreateOutputStream(
     129             :             XclXmlUtils::GetStreamName("xl/pivotCache/", "pivotCacheDefinition", nCacheId),
     130             :             XclXmlUtils::GetStreamName(NULL, "pivotCache/pivotCacheDefinition", nCacheId),
     131           2 :             rStrm.GetCurrentStream()->getOutputStream(),
     132             :             CREATE_XL_CONTENT_TYPE("pivotCacheDefinition"),
     133             :             CREATE_OFFICEDOC_RELATION_TYPE("pivotCacheDefinition"),
     134           4 :             &aRelId);
     135             : 
     136             :         pWorkbookStrm->singleElement(XML_pivotCache,
     137             :             XML_cacheId, OString::number(nCacheId).getStr(),
     138             :             FSNS(XML_r, XML_id), XclXmlUtils::ToOString(aRelId).getStr(),
     139           2 :             FSEND);
     140             : 
     141           2 :         rStrm.PushStream(pPCStrm);
     142           2 :         SavePivotCacheXml(rStrm, rEntry, nCacheId);
     143           2 :         rStrm.PopStream();
     144           2 :     }
     145             : 
     146           2 :     pWorkbookStrm->endElement(XML_pivotCaches);
     147           2 : }
     148             : 
     149           2 : void XclExpXmlPivotCaches::SetCaches( const std::vector<Entry>& rCaches )
     150             : {
     151           2 :     maCaches = rCaches;
     152           2 : }
     153             : 
     154          55 : bool XclExpXmlPivotCaches::HasCaches() const
     155             : {
     156          55 :     return !maCaches.empty();
     157             : }
     158             : 
     159           2 : const XclExpXmlPivotCaches::Entry* XclExpXmlPivotCaches::GetCache( sal_Int32 nCacheId ) const
     160             : {
     161           2 :     if (nCacheId <= 0)
     162             :         // cache ID is 1-based.
     163           0 :         return NULL;
     164             : 
     165           2 :     size_t nPos = nCacheId - 1;
     166           2 :     if (nPos >= maCaches.size())
     167           0 :         return NULL;
     168             : 
     169           2 :     return &maCaches[nPos];
     170             : }
     171             : 
     172           2 : void XclExpXmlPivotCaches::SavePivotCacheXml( XclExpXmlStream& rStrm, const Entry& rEntry, sal_Int32 nCounter )
     173             : {
     174             :     assert(rEntry.mpCache);
     175           2 :     const ScDPCache& rCache = *rEntry.mpCache;
     176             : 
     177           2 :     sax_fastparser::FSHelperPtr& pDefStrm = rStrm.GetCurrentStream();
     178             : 
     179           2 :     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           4 :         &aRelId);
     187             : 
     188           2 :     rStrm.PushStream(pRecStrm);
     189           2 :     savePivotCacheRecordsXml(rStrm, rCache);
     190           2 :     rStrm.PopStream();
     191             : 
     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           2 :         FSEND);
     198             : 
     199           2 :     if (rEntry.meType == Worksheet)
     200             :     {
     201             :         pDefStrm->startElement(XML_cacheSource,
     202             :             XML_type, "worksheet",
     203           2 :             FSEND);
     204             : 
     205           2 :         OUString aSheetName;
     206           2 :         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           2 :             FSEND);
     211             : 
     212           2 :         pDefStrm->endElement(XML_cacheSource);
     213             :     }
     214             : 
     215           2 :     size_t nCount = rCache.GetFieldCount();
     216             :     pDefStrm->startElement(XML_cacheFields,
     217             :         XML_count, OString::number(static_cast<long>(nCount)).getStr(),
     218           2 :         FSEND);
     219             : 
     220          14 :     for (size_t i = 0; i < nCount; ++i)
     221             :     {
     222          12 :         OUString aName = rCache.GetDimensionName(i);
     223             : 
     224             :         pDefStrm->startElement(XML_cacheField,
     225             :             XML_name, XclXmlUtils::ToOString(aName).getStr(),
     226             :             XML_numFmtId, OString::number(0).getStr(),
     227          12 :             FSEND);
     228             : 
     229          12 :         const ScDPCache::ItemsType& rFieldItems = rCache.GetDimMemberValues(i);
     230             : 
     231             :         pDefStrm->startElement(XML_sharedItems,
     232          12 :             XML_count, OString::number(static_cast<long>(rFieldItems.size())).getStr(),
     233          12 :             FSEND);
     234             : 
     235          12 :         ScDPCache::ItemsType::const_iterator it = rFieldItems.begin(), itEnd = rFieldItems.end();
     236          46 :         for (; it != itEnd; ++it)
     237             :         {
     238          34 :             const ScDPItemData& rItem = *it;
     239          34 :             switch (rItem.GetType())
     240             :             {
     241             :                 case ScDPItemData::String:
     242             :                     pDefStrm->singleElement(XML_s,
     243             :                         XML_v, XclXmlUtils::ToOString(rItem.GetString()).getStr(),
     244          21 :                         FSEND);
     245          21 :                 break;
     246             :                 case ScDPItemData::Value:
     247             :                     pDefStrm->singleElement(XML_n,
     248             :                         XML_v, OString::number(rItem.GetValue()).getStr(),
     249          13 :                         FSEND);
     250          13 :                 break;
     251             :                 case ScDPItemData::Empty:
     252           0 :                     pDefStrm->singleElement(XML_m, FSEND);
     253           0 :                 break;
     254             :                 case ScDPItemData::Error:
     255             :                     pDefStrm->singleElement(XML_e,
     256             :                         XML_v, XclXmlUtils::ToOString(rItem.GetString()).getStr(),
     257           0 :                         FSEND);
     258           0 :                 break;
     259             :                 case ScDPItemData::GroupValue:
     260             :                 case ScDPItemData::RangeStart:
     261             :                     // TODO : What do we do with these types?
     262           0 :                     pDefStrm->singleElement(XML_m, FSEND);
     263           0 :                 break;
     264             :                 default:
     265             :                     ;
     266             :             }
     267             :         }
     268             : 
     269          12 :         pDefStrm->endElement(XML_sharedItems);
     270          12 :         pDefStrm->endElement(XML_cacheField);
     271          12 :     }
     272             : 
     273           2 :     pDefStrm->endElement(XML_cacheFields);
     274             : 
     275           4 :     pDefStrm->endElement(XML_pivotCacheDefinition);
     276           2 : }
     277             : 
     278          55 : XclExpXmlPivotTableManager::XclExpXmlPivotTableManager( const XclExpRoot& rRoot ) :
     279          55 :     XclExpRoot(rRoot), maCaches(rRoot) {}
     280             : 
     281          55 : void XclExpXmlPivotTableManager::Initialize()
     282             : {
     283          55 :     const ScDocument& rDoc = GetDoc();
     284          55 :     if (!rDoc.HasPivotTable())
     285             :         // No pivot table to export.
     286         106 :         return;
     287             : 
     288           2 :     const ScDPCollection* pDPColl = rDoc.GetDPCollection();
     289           2 :     if (!pDPColl)
     290           0 :         return;
     291             : 
     292             :     // Go through the caches first.
     293             : 
     294           2 :     std::vector<XclExpXmlPivotCaches::Entry> aCaches;
     295           2 :     const ScDPCollection::SheetCaches& rSheetCaches = pDPColl->GetSheetCaches();
     296           2 :     const std::vector<ScRange>& rRanges = rSheetCaches.getAllRanges();
     297           4 :     for (size_t i = 0, n = rRanges.size(); i < n; ++i)
     298             :     {
     299           2 :         const ScDPCache* pCache = rSheetCaches.getExistingCache(rRanges[i]);
     300           2 :         if (!pCache)
     301           0 :             continue;
     302             : 
     303             :         // Get all pivot objects that reference this cache, and set up an
     304             :         // object to cache ID mapping.
     305           2 :         const ScDPCache::ObjectSetType& rRefs = pCache->GetAllReferences();
     306           2 :         ScDPCache::ObjectSetType::const_iterator it = rRefs.begin(), itEnd = rRefs.end();
     307           4 :         for (; it != itEnd; ++it)
     308           2 :             maCacheIdMap.insert(CacheIdMapType::value_type(*it, aCaches.size()+1));
     309             : 
     310           2 :         XclExpXmlPivotCaches::Entry aEntry;
     311           2 :         aEntry.meType = XclExpXmlPivotCaches::Worksheet;
     312           2 :         aEntry.mpCache = pCache;
     313           2 :         aEntry.maSrcRange = rRanges[i];
     314           2 :         aCaches.push_back(aEntry); // Cache ID equals position + 1.
     315             :     }
     316             : 
     317             :     // TODO : Handle name and database caches as well.
     318             : 
     319           4 :     for (size_t i = 0, n = pDPColl->GetCount(); i < n; ++i)
     320             :     {
     321           2 :         const ScDPObject* pDPObj = (*pDPColl)[i];
     322             :         assert(pDPObj); // We don't store NULL here.
     323             : 
     324             :         // Get the cache ID for this pivot table.
     325           2 :         CacheIdMapType::iterator itCache = maCacheIdMap.find(pDPObj);
     326           2 :         if (itCache == maCacheIdMap.end())
     327             :             // No cache ID found.  Something is wrong here....
     328           0 :             continue;
     329             : 
     330           2 :         sal_Int32 nCacheId = itCache->second;
     331           2 :         SCTAB nTab = pDPObj->GetOutRange().aStart.Tab();
     332             : 
     333           2 :         TablesType::iterator it = maTables.find(nTab);
     334           2 :         if (it == maTables.end())
     335             :         {
     336             :             // Insert a new instance for this sheet index.
     337             :             std::pair<TablesType::iterator, bool> r =
     338           2 :                 maTables.insert(nTab, new XclExpXmlPivotTables(GetRoot(), maCaches));
     339           2 :             it = r.first;
     340             :         }
     341             : 
     342           2 :         XclExpXmlPivotTables* p = it->second;
     343           2 :         p->AppendTable(pDPObj, nCacheId, i+1);
     344             :     }
     345             : 
     346           2 :     maCaches.SetCaches(aCaches);
     347             : }
     348             : 
     349          55 : XclExpXmlPivotCaches& XclExpXmlPivotTableManager::GetCaches()
     350             : {
     351          55 :     return maCaches;
     352             : }
     353             : 
     354         100 : XclExpXmlPivotTables* XclExpXmlPivotTableManager::GetTablesBySheet( SCTAB nTab )
     355             : {
     356         100 :     TablesType::iterator it = maTables.find(nTab);
     357         100 :     return it == maTables.end() ? NULL : it->second;
     358             : }
     359             : 
     360           2 : XclExpXmlPivotTables::Entry::Entry( const ScDPObject* pTable, sal_Int32 nCacheId, sal_Int32 nPivotId ) :
     361           2 :     mpTable(pTable), mnCacheId(nCacheId), mnPivotId(nPivotId) {}
     362             : 
     363           2 : XclExpXmlPivotTables::XclExpXmlPivotTables( const XclExpRoot& rRoot, const XclExpXmlPivotCaches& rCaches ) :
     364           2 :     XclExpRoot(rRoot), mrCaches(rCaches) {}
     365             : 
     366           2 : void XclExpXmlPivotTables::SaveXml( XclExpXmlStream& rStrm )
     367             : {
     368           2 :     sax_fastparser::FSHelperPtr& pWSStrm = rStrm.GetCurrentStream(); // worksheet stream
     369             : 
     370           2 :     sal_Int32 nCounter = 1; // 1-based
     371           2 :     TablesType::iterator it = maTables.begin(), itEnd = maTables.end();
     372           4 :     for (; it != itEnd; ++it, ++nCounter)
     373             :     {
     374           2 :         const ScDPObject& rObj = *it->mpTable;
     375           2 :         sal_Int32 nCacheId = it->mnCacheId;
     376           2 :         sal_Int32 nPivotId = it->mnPivotId;
     377             : 
     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           2 :             NULL);
     385             : 
     386           2 :         rStrm.PushStream(pPivotStrm);
     387           2 :         SavePivotTableXml(rStrm, rObj, nCacheId);
     388           2 :         rStrm.PopStream();
     389           2 :     }
     390           2 : }
     391             : 
     392             : namespace {
     393             : 
     394             : struct DataField
     395             : {
     396             :     long mnPos; // field index in pivot cache.
     397             :     const ScDPSaveDimension* mpDim;
     398             : 
     399           3 :     DataField( long nPos, const ScDPSaveDimension* pDim ) : mnPos(nPos), mpDim(pDim) {}
     400             : };
     401             : 
     402             : }
     403             : 
     404           2 : void XclExpXmlPivotTables::SavePivotTableXml( XclExpXmlStream& rStrm, const ScDPObject& rDPObj, sal_Int32 nCacheId )
     405             : {
     406             :     typedef std::unordered_map<OUString, long, OUStringHash> NameToIdMapType;
     407             : 
     408           2 :     const XclExpXmlPivotCaches::Entry* pCacheEntry = mrCaches.GetCache(nCacheId);
     409           2 :     if (!pCacheEntry)
     410             :         // Something is horribly wrong.  Check your logic.
     411           2 :         return;
     412             : 
     413           2 :     const ScDPCache& rCache = *pCacheEntry->mpCache;
     414             : 
     415           2 :     const ScDPSaveData& rSaveData = *rDPObj.GetSaveData();
     416             : 
     417           2 :     size_t nFieldCount = rCache.GetFieldCount();
     418           2 :     std::vector<const ScDPSaveDimension*> aCachedDims;
     419           4 :     NameToIdMapType aNameToIdMap;
     420             : 
     421           2 :     aCachedDims.reserve(nFieldCount);
     422          14 :     for (size_t i = 0; i < nFieldCount; ++i)
     423             :     {
     424          12 :         OUString aName = rCache.GetDimensionName(i);
     425          12 :         aNameToIdMap.insert(NameToIdMapType::value_type(aName, aCachedDims.size()));
     426          12 :         const ScDPSaveDimension* pDim = rSaveData.GetExistingDimensionByName(aName);
     427          12 :         aCachedDims.push_back(pDim);
     428          12 :     }
     429             : 
     430           4 :     std::vector<long> aRowFields;
     431           4 :     std::vector<long> aColFields;
     432           4 :     std::vector<long> aPageFields;
     433           4 :     std::vector<DataField> aDataFields;
     434             : 
     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           2 :     const ScDPSaveData::DimsType& rDims = rSaveData.GetDimensions();
     439             : 
     440          16 :     for (size_t i = 0, n = rDims.size(); i < n; ++i)
     441             :     {
     442          14 :         const ScDPSaveDimension& rDim = rDims[i];
     443             : 
     444          14 :         long nPos = -1; // position in cache
     445          14 :         if (rDim.IsDataLayout())
     446           1 :             nPos = -2; // Excel uses an index of -2 to indicate a data layout field.
     447             :         else
     448             :         {
     449          13 :             OUString aSrcName = ScDPUtil::getSourceDimensionName(rDim.GetName());
     450          13 :             NameToIdMapType::iterator it = aNameToIdMap.find(aSrcName);
     451          13 :             if (it != aNameToIdMap.end())
     452          13 :                 nPos = it->second;
     453             : 
     454          13 :             if (nPos == -1)
     455           0 :                 continue;
     456             : 
     457          13 :             if (!aCachedDims[nPos])
     458           0 :                 continue;
     459             :         }
     460             : 
     461             :         sheet::DataPilotFieldOrientation eOrient =
     462          14 :             static_cast<sheet::DataPilotFieldOrientation>(rDim.GetOrientation());
     463             : 
     464          14 :         switch (eOrient)
     465             :         {
     466             :             case sheet::DataPilotFieldOrientation_COLUMN:
     467           2 :                 aColFields.push_back(nPos);
     468           2 :             break;
     469             :             case sheet::DataPilotFieldOrientation_ROW:
     470           2 :                 aRowFields.push_back(nPos);
     471           2 :             break;
     472             :             case sheet::DataPilotFieldOrientation_PAGE:
     473           2 :                 aPageFields.push_back(nPos);
     474           2 :             break;
     475             :             case sheet::DataPilotFieldOrientation_DATA:
     476           3 :                 aDataFields.push_back(DataField(nPos, &rDim));
     477           3 :             break;
     478             :             case sheet::DataPilotFieldOrientation_HIDDEN:
     479             :             default:
     480             :                 ;
     481             :         }
     482             :     }
     483             : 
     484           2 :     sax_fastparser::FSHelperPtr& pPivotStrm = rStrm.GetCurrentStream();
     485             :     pPivotStrm->startElement(XML_pivotTableDefinition,
     486             :         XML_xmlns, "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
     487           2 :         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           4 :         FSEND);
     502             : 
     503             :     // NB: Excel's range does not include page field area (if any).
     504           2 :     ScRange aOutRange = rDPObj.GetOutputRangeByType(sheet::DataPilotOutputRangeType::TABLE);
     505             : 
     506           2 :     sal_Int32 nFirstHeaderRow = aColFields.size();
     507           2 :     sal_Int32 nFirstDataRow = 2;
     508           2 :     sal_Int32 nFirstDataCol = 1;
     509           2 :     ScRange aResRange = rDPObj.GetOutputRangeByType(sheet::DataPilotOutputRangeType::RESULT);
     510           2 :     if (aOutRange.IsValid() && aResRange.IsValid())
     511             :     {
     512           2 :         nFirstDataRow = aResRange.aStart.Row() - aOutRange.aStart.Row();
     513           2 :         nFirstDataCol = aResRange.aStart.Col() - aOutRange.aStart.Col();
     514             :     }
     515             : 
     516           2 :     if (!aOutRange.IsValid())
     517           0 :         aOutRange = rDPObj.GetOutRange();
     518             : 
     519           2 :     pPivotStrm->write("<")->writeId(XML_location);
     520             :     rStrm.WriteAttributes(XML_ref,
     521             :         XclXmlUtils::ToOString(aOutRange),
     522           4 :         XML_firstHeaderRow, OString::number(nFirstHeaderRow).getStr(),
     523           4 :         XML_firstDataRow, OString::number(nFirstDataRow).getStr(),
     524           4 :         XML_firstDataCol, OString::number(nFirstDataCol).getStr(),
     525          12 :         FSEND);
     526             : 
     527           2 :     if (!aPageFields.empty())
     528             :     {
     529           1 :         rStrm.WriteAttributes(XML_rowPageCount, OString::number(static_cast<long>(aPageFields.size())).getStr(), FSEND);
     530           1 :         rStrm.WriteAttributes(XML_colPageCount, OString::number(1).getStr(), FSEND);
     531             :     }
     532             : 
     533           2 :     pPivotStrm->write("/>");
     534             : 
     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.
     538             : 
     539             :     pPivotStrm->startElement(XML_pivotFields,
     540           2 :         XML_count, OString::number(static_cast<long>(aCachedDims.size())).getStr(),
     541           2 :         FSEND);
     542             : 
     543          14 :     for (size_t i = 0, n = aCachedDims.size(); i < n; ++i)
     544             :     {
     545          12 :         const ScDPSaveDimension* pDim = aCachedDims[i];
     546          12 :         if (!pDim)
     547             :         {
     548             :             pPivotStrm->singleElement(XML_pivotField,
     549             :                 XML_showAll, BS(false),
     550           0 :                 FSEND);
     551           0 :             continue;
     552             :         }
     553             : 
     554             :         sheet::DataPilotFieldOrientation eOrient =
     555          12 :             static_cast<sheet::DataPilotFieldOrientation>(pDim->GetOrientation());
     556             : 
     557          12 :         if (eOrient == sheet::DataPilotFieldOrientation_HIDDEN)
     558             :         {
     559             :             pPivotStrm->singleElement(XML_pivotField,
     560             :                 XML_showAll, BS(false),
     561           5 :                 FSEND);
     562           5 :             continue;
     563             :         }
     564             : 
     565           7 :         if (eOrient == sheet::DataPilotFieldOrientation_DATA)
     566             :         {
     567             :             pPivotStrm->singleElement(XML_pivotField,
     568             :                 XML_dataField, BS(true),
     569             :                 XML_showAll, BS(false),
     570           2 :                 FSEND);
     571             : 
     572           2 :             continue;
     573             :         }
     574             : 
     575             :         pPivotStrm->startElement(XML_pivotField,
     576             :             XML_axis, toOOXMLAxisType(eOrient),
     577             :             XML_showAll, BS(false),
     578           5 :             FSEND);
     579             : 
     580             :         // TODO : Dump field items.
     581             : 
     582           5 :         pPivotStrm->endElement(XML_pivotField);
     583             :     }
     584             : 
     585           2 :     pPivotStrm->endElement(XML_pivotFields);
     586             : 
     587             :     // <rowFields>
     588             : 
     589           2 :     if (!aRowFields.empty())
     590             :     {
     591             :         pPivotStrm->startElement(XML_rowFields,
     592           2 :             XML_count, OString::number(static_cast<long>(aRowFields.size())),
     593           2 :             FSEND);
     594             : 
     595           2 :         std::vector<long>::iterator it = aRowFields.begin(), itEnd = aRowFields.end();
     596           4 :         for (; it != itEnd; ++it)
     597             :         {
     598             :             pPivotStrm->singleElement(XML_field,
     599           2 :                 XML_x, OString::number(*it),
     600           2 :                 FSEND);
     601             :         }
     602             : 
     603           2 :         pPivotStrm->endElement(XML_rowFields);
     604             :     }
     605             : 
     606             :     // <rowItems>
     607             : 
     608             :     // <colFields>
     609             : 
     610           2 :     if (!aColFields.empty())
     611             :     {
     612             :         pPivotStrm->startElement(XML_colFields,
     613           2 :             XML_count, OString::number(static_cast<long>(aColFields.size())),
     614           2 :             FSEND);
     615             : 
     616           2 :         std::vector<long>::iterator it = aColFields.begin(), itEnd = aColFields.end();
     617           4 :         for (; it != itEnd; ++it)
     618             :         {
     619             :             pPivotStrm->singleElement(XML_field,
     620           2 :                 XML_x, OString::number(*it),
     621           2 :                 FSEND);
     622             :         }
     623             : 
     624           2 :         pPivotStrm->endElement(XML_colFields);
     625             :     }
     626             : 
     627             :     // <colItems>
     628             : 
     629             :     // <pageFields>
     630             : 
     631           2 :     if (!aPageFields.empty())
     632             :     {
     633             :         pPivotStrm->startElement(XML_pageFields,
     634           1 :             XML_count, OString::number(static_cast<long>(aPageFields.size())),
     635           1 :             FSEND);
     636             : 
     637           1 :         std::vector<long>::iterator it = aPageFields.begin(), itEnd = aPageFields.end();
     638           3 :         for (; it != itEnd; ++it)
     639             :         {
     640             :             pPivotStrm->singleElement(XML_pageField,
     641           2 :                 XML_fld, OString::number(*it),
     642             :                 XML_hier, OString::number(-1), // TODO : handle this correctly.
     643           4 :                 FSEND);
     644             :         }
     645             : 
     646           1 :         pPivotStrm->endElement(XML_pageFields);
     647             :     }
     648             : 
     649             :     // <dataFields>
     650             : 
     651           2 :     if (!aDataFields.empty())
     652             :     {
     653             :         pPivotStrm->startElement(XML_dataFields,
     654           2 :             XML_count, OString::number(static_cast<long>(aDataFields.size())),
     655           2 :             FSEND);
     656             : 
     657           2 :         std::vector<DataField>::iterator it = aDataFields.begin(), itEnd = aDataFields.end();
     658           5 :         for (; it != itEnd; ++it)
     659             :         {
     660           3 :             long nDimIdx = it->mnPos;
     661             :             assert(aCachedDims[nDimIdx]); // the loop above should have screened for NULL's.
     662           3 :             const ScDPSaveDimension& rDim = *it->mpDim;
     663           3 :             const OUString* pName = rDim.GetLayoutName();
     664           3 :             pPivotStrm->write("<")->writeId(XML_dataField);
     665           3 :             if (pName)
     666           0 :                 rStrm.WriteAttributes(XML_name, XclXmlUtils::ToOString(*pName), FSEND);
     667             : 
     668           3 :             rStrm.WriteAttributes(XML_fld, OString::number(nDimIdx).getStr(), FSEND);
     669             : 
     670           3 :             sheet::GeneralFunction eFunc = static_cast<sheet::GeneralFunction>(rDim.GetFunction());
     671           3 :             const char* pSubtotal = toOOXMLSubtotalType(eFunc);
     672           3 :             if (pSubtotal)
     673           3 :                 rStrm.WriteAttributes(XML_subtotal, pSubtotal, FSEND);
     674             : 
     675           3 :             pPivotStrm->write("/>");
     676             :         }
     677             : 
     678           2 :         pPivotStrm->endElement(XML_dataFields);
     679             :     }
     680             : 
     681           2 :     OUStringBuffer aBuf("../pivotCache/pivotCacheDefinition");
     682           2 :     aBuf.append(nCacheId);
     683           2 :     aBuf.append(".xml");
     684             : 
     685             :     rStrm.addRelation(
     686             :         pPivotStrm->getOutputStream(),
     687             :         CREATE_OFFICEDOC_RELATION_TYPE("pivotCacheDefinition"),
     688           2 :         aBuf.makeStringAndClear());
     689             : 
     690           4 :     pPivotStrm->endElement(XML_pivotTableDefinition);
     691             : }
     692             : 
     693           2 : void XclExpXmlPivotTables::AppendTable( const ScDPObject* pTable, sal_Int32 nCacheId, sal_Int32 nPivotId )
     694             : {
     695           2 :     maTables.push_back(Entry(pTable, nCacheId, nPivotId));
     696          32 : }
     697             : 
     698             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11