Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "xipivot.hxx"
21 :
22 : #include <com/sun/star/sheet/DataPilotFieldSortInfo.hpp>
23 : #include <com/sun/star/sheet/DataPilotFieldAutoShowInfo.hpp>
24 : #include <com/sun/star/sheet/DataPilotFieldLayoutInfo.hpp>
25 : #include <com/sun/star/sheet/DataPilotFieldReference.hpp>
26 :
27 : #include <tools/datetime.hxx>
28 : #include <svl/zformat.hxx>
29 : #include <svl/intitem.hxx>
30 :
31 : #include "document.hxx"
32 : #include "formulacell.hxx"
33 : #include "dpsave.hxx"
34 : #include "dpdimsave.hxx"
35 : #include "dpobject.hxx"
36 : #include "dpshttab.hxx"
37 : #include "dpoutputgeometry.hxx"
38 : #include "scitems.hxx"
39 : #include "attrib.hxx"
40 :
41 : #include "xltracer.hxx"
42 : #include "xistream.hxx"
43 : #include "xihelper.hxx"
44 : #include "xilink.hxx"
45 : #include "xiescher.hxx"
46 :
47 : //! TODO ExcelToSc usage
48 : #include "excform.hxx"
49 : #include "xltable.hxx"
50 : #include "documentimport.hxx"
51 :
52 : #include <vector>
53 :
54 : using namespace com::sun::star;
55 :
56 : using ::com::sun::star::sheet::DataPilotFieldOrientation;
57 : using ::com::sun::star::sheet::DataPilotFieldOrientation_DATA;
58 : using ::com::sun::star::sheet::DataPilotFieldSortInfo;
59 : using ::com::sun::star::sheet::DataPilotFieldAutoShowInfo;
60 : using ::com::sun::star::sheet::DataPilotFieldLayoutInfo;
61 : using ::com::sun::star::sheet::DataPilotFieldReference;
62 : using ::std::vector;
63 :
64 : // Pivot cache
65 :
66 30 : XclImpPCItem::XclImpPCItem( XclImpStream& rStrm )
67 : {
68 30 : switch( rStrm.GetRecId() )
69 : {
70 8 : case EXC_ID_SXDOUBLE: ReadSxdouble( rStrm ); break;
71 0 : case EXC_ID_SXBOOLEAN: ReadSxboolean( rStrm ); break;
72 0 : case EXC_ID_SXERROR: ReadSxerror( rStrm ); break;
73 0 : case EXC_ID_SXINTEGER: ReadSxinteger( rStrm ); break;
74 22 : case EXC_ID_SXSTRING: ReadSxstring( rStrm ); break;
75 0 : case EXC_ID_SXDATETIME: ReadSxdatetime( rStrm ); break;
76 0 : case EXC_ID_SXEMPTY: ReadSxempty( rStrm ); break;
77 : default: OSL_FAIL( "XclImpPCItem::XclImpPCItem - unknown record id" );
78 : }
79 30 : }
80 :
81 : namespace {
82 :
83 0 : void lclSetValue( XclImpRoot& rRoot, const ScAddress& rScPos, double fValue, short nFormatType )
84 : {
85 0 : ScDocumentImport& rDoc = rRoot.GetDocImport();
86 0 : rDoc.setNumericCell(rScPos, fValue);
87 0 : sal_uInt32 nScNumFmt = rRoot.GetFormatter().GetStandardFormat( nFormatType, rRoot.GetDocLanguage() );
88 0 : rDoc.getDoc().ApplyAttr(
89 0 : rScPos.Col(), rScPos.Row(), rScPos.Tab(), SfxUInt32Item(ATTR_VALUE_FORMAT, nScNumFmt));
90 0 : }
91 :
92 : } // namespace
93 :
94 0 : void XclImpPCItem::WriteToSource( XclImpRoot& rRoot, const ScAddress& rScPos ) const
95 : {
96 0 : ScDocumentImport& rDoc = rRoot.GetDocImport();
97 0 : if( const OUString* pText = GetText() )
98 0 : rDoc.setStringCell(rScPos, *pText);
99 0 : else if( const double* pfValue = GetDouble() )
100 0 : rDoc.setNumericCell(rScPos, *pfValue);
101 0 : else if( const sal_Int16* pnValue = GetInteger() )
102 0 : rDoc.setNumericCell(rScPos, *pnValue);
103 0 : else if( const bool* pbValue = GetBool() )
104 0 : lclSetValue( rRoot, rScPos, *pbValue ? 1.0 : 0.0, NUMBERFORMAT_LOGICAL );
105 0 : else if( const DateTime* pDateTime = GetDateTime() )
106 : {
107 : // set number format date, time, or date/time, depending on the value
108 0 : double fValue = rRoot.GetDoubleFromDateTime( *pDateTime );
109 0 : double fInt = 0.0;
110 0 : double fFrac = modf( fValue, &fInt );
111 0 : short nFormatType = ((fFrac == 0.0) && (fInt != 0.0)) ? NUMBERFORMAT_DATE :
112 0 : ((fInt == 0.0) ? NUMBERFORMAT_TIME : NUMBERFORMAT_DATETIME);
113 0 : lclSetValue( rRoot, rScPos, fValue, nFormatType );
114 : }
115 0 : else if( const sal_uInt16* pnError = GetError() )
116 : {
117 : double fValue;
118 0 : sal_uInt8 nErrCode = static_cast< sal_uInt8 >( *pnError );
119 0 : const ScTokenArray* pScTokArr = rRoot.GetOldFmlaConverter().GetBoolErr(
120 0 : XclTools::ErrorToEnum( fValue, true, nErrCode ) );
121 0 : ScFormulaCell* pCell = pScTokArr ? new ScFormulaCell(&rDoc.getDoc(), rScPos, *pScTokArr) : new ScFormulaCell(&rDoc.getDoc(), rScPos);
122 0 : pCell->SetHybridDouble( fValue );
123 0 : rDoc.setFormulaCell(rScPos, pCell);
124 : }
125 0 : }
126 :
127 8 : void XclImpPCItem::ReadSxdouble( XclImpStream& rStrm )
128 : {
129 : OSL_ENSURE( rStrm.GetRecSize() == 8, "XclImpPCItem::ReadSxdouble - wrong record size" );
130 8 : SetDouble( rStrm.ReadDouble() );
131 8 : }
132 :
133 0 : void XclImpPCItem::ReadSxboolean( XclImpStream& rStrm )
134 : {
135 : OSL_ENSURE( rStrm.GetRecSize() == 2, "XclImpPCItem::ReadSxboolean - wrong record size" );
136 0 : SetBool( rStrm.ReaduInt16() != 0 );
137 0 : }
138 :
139 0 : void XclImpPCItem::ReadSxerror( XclImpStream& rStrm )
140 : {
141 : OSL_ENSURE( rStrm.GetRecSize() == 2, "XclImpPCItem::ReadSxerror - wrong record size" );
142 0 : SetError( rStrm.ReaduInt16() );
143 0 : }
144 :
145 0 : void XclImpPCItem::ReadSxinteger( XclImpStream& rStrm )
146 : {
147 : OSL_ENSURE( rStrm.GetRecSize() == 2, "XclImpPCItem::ReadSxinteger - wrong record size" );
148 0 : SetInteger( rStrm.ReadInt16() );
149 0 : }
150 :
151 22 : void XclImpPCItem::ReadSxstring( XclImpStream& rStrm )
152 : {
153 : OSL_ENSURE( rStrm.GetRecSize() >= 3, "XclImpPCItem::ReadSxstring - wrong record size" );
154 22 : SetText( rStrm.ReadUniString() );
155 22 : }
156 :
157 0 : void XclImpPCItem::ReadSxdatetime( XclImpStream& rStrm )
158 : {
159 : OSL_ENSURE( rStrm.GetRecSize() == 8, "XclImpPCItem::ReadSxdatetime - wrong record size" );
160 : sal_uInt16 nYear, nMonth;
161 : sal_uInt8 nDay, nHour, nMin, nSec;
162 0 : rStrm >> nYear >> nMonth >> nDay >> nHour >> nMin >> nSec;
163 0 : SetDateTime( DateTime( Date( nDay, nMonth, nYear ), tools::Time( nHour, nMin, nSec ) ) );
164 0 : }
165 :
166 0 : void XclImpPCItem::ReadSxempty( XclImpStream& rStrm )
167 : {
168 : (void)rStrm; // avoid compiler warning
169 : OSL_ENSURE( rStrm.GetRecSize() == 0, "XclImpPCItem::ReadSxempty - wrong record size" );
170 0 : SetEmpty();
171 0 : }
172 :
173 10 : XclImpPCField::XclImpPCField( const XclImpRoot& rRoot, XclImpPivotCache& rPCache, sal_uInt16 nFieldIdx ) :
174 : XclPCField( EXC_PCFIELD_UNKNOWN, nFieldIdx ),
175 : XclImpRoot( rRoot ),
176 : mrPCache( rPCache ),
177 : mnSourceScCol( -1 ),
178 10 : mbNumGroupInfoRead( false )
179 : {
180 10 : }
181 :
182 20 : XclImpPCField::~XclImpPCField()
183 : {
184 20 : }
185 :
186 : // general field/item access --------------------------------------------------
187 :
188 12 : const OUString& XclImpPCField::GetFieldName( const ScfStringVec& rVisNames ) const
189 : {
190 12 : if( IsGroupChildField() && (mnFieldIdx < rVisNames.size()) )
191 : {
192 0 : const OUString& rVisName = rVisNames[ mnFieldIdx ];
193 0 : if (!rVisName.isEmpty())
194 0 : return rVisName;
195 : }
196 12 : return maFieldInfo.maName;
197 : }
198 :
199 0 : const XclImpPCField* XclImpPCField::GetGroupBaseField() const
200 : {
201 : OSL_ENSURE( IsGroupChildField(), "XclImpPCField::GetGroupBaseField - this field type does not have a base field" );
202 0 : return IsGroupChildField() ? mrPCache.GetField( maFieldInfo.mnGroupBase ) : 0;
203 : }
204 :
205 20 : const XclImpPCItem* XclImpPCField::GetItem( sal_uInt16 nItemIdx ) const
206 : {
207 20 : return (nItemIdx < maItems.size()) ? maItems[ nItemIdx ].get() : 0;
208 : }
209 :
210 0 : const XclImpPCItem* XclImpPCField::GetLimitItem( sal_uInt16 nItemIdx ) const
211 : {
212 : OSL_ENSURE( nItemIdx < 3, "XclImpPCField::GetLimitItem - invalid item index" );
213 : OSL_ENSURE( nItemIdx < maNumGroupItems.size(), "XclImpPCField::GetLimitItem - no item found" );
214 0 : return (nItemIdx < maNumGroupItems.size()) ? maNumGroupItems[ nItemIdx ].get() : 0;
215 : }
216 :
217 0 : void XclImpPCField::WriteFieldNameToSource( SCCOL nScCol, SCTAB nScTab )
218 : {
219 : OSL_ENSURE( HasOrigItems(), "XclImpPCField::WriteFieldNameToSource - only for standard fields" );
220 0 : GetDocImport().setStringCell(ScAddress(nScCol, 0, nScTab), maFieldInfo.maName);
221 0 : mnSourceScCol = nScCol;
222 0 : }
223 :
224 0 : void XclImpPCField::WriteOrigItemToSource( SCROW nScRow, SCTAB nScTab, sal_uInt16 nItemIdx )
225 : {
226 0 : if( nItemIdx < maOrigItems.size() )
227 0 : maOrigItems[ nItemIdx ]->WriteToSource( GetRoot(), ScAddress( mnSourceScCol, nScRow, nScTab ) );
228 0 : }
229 :
230 0 : void XclImpPCField::WriteLastOrigItemToSource( SCROW nScRow, SCTAB nScTab )
231 : {
232 0 : if( !maOrigItems.empty() )
233 0 : maOrigItems.back()->WriteToSource( GetRoot(), ScAddress( mnSourceScCol, nScRow, nScTab ) );
234 0 : }
235 :
236 : // records --------------------------------------------------------------------
237 :
238 10 : void XclImpPCField::ReadSxfield( XclImpStream& rStrm )
239 : {
240 10 : rStrm >> maFieldInfo;
241 :
242 : /* Detect the type of this field. This is done very restrictive to detect
243 : any unexpected state. */
244 10 : meFieldType = EXC_PCFIELD_UNKNOWN;
245 :
246 10 : bool bItems = ::get_flag( maFieldInfo.mnFlags, EXC_SXFIELD_HASITEMS );
247 10 : bool bPostp = ::get_flag( maFieldInfo.mnFlags, EXC_SXFIELD_POSTPONE );
248 10 : bool bCalced = ::get_flag( maFieldInfo.mnFlags, EXC_SXFIELD_CALCED );
249 10 : bool bChild = ::get_flag( maFieldInfo.mnFlags, EXC_SXFIELD_HASCHILD );
250 10 : bool bNum = ::get_flag( maFieldInfo.mnFlags, EXC_SXFIELD_NUMGROUP );
251 :
252 10 : sal_uInt16 nVisC = maFieldInfo.mnVisItems;
253 10 : sal_uInt16 nGroupC = maFieldInfo.mnGroupItems;
254 10 : sal_uInt16 nBaseC = maFieldInfo.mnBaseItems;
255 10 : sal_uInt16 nOrigC = maFieldInfo.mnOrigItems;
256 : OSL_ENSURE( nVisC > 0, "XclImpPCField::ReadSxfield - field without visible items" );
257 :
258 10 : sal_uInt16 nType = maFieldInfo.mnFlags & EXC_SXFIELD_DATA_MASK;
259 : bool bType =
260 2 : (nType == EXC_SXFIELD_DATA_STR) ||
261 2 : (nType == EXC_SXFIELD_DATA_INT) ||
262 0 : (nType == EXC_SXFIELD_DATA_DBL) ||
263 0 : (nType == EXC_SXFIELD_DATA_STR_INT) ||
264 0 : (nType == EXC_SXFIELD_DATA_STR_DBL) ||
265 0 : (nType == EXC_SXFIELD_DATA_DATE) ||
266 0 : (nType == EXC_SXFIELD_DATA_DATE_EMP) ||
267 10 : (nType == EXC_SXFIELD_DATA_DATE_NUM) ||
268 10 : (nType == EXC_SXFIELD_DATA_DATE_STR);
269 : bool bTypeNone =
270 10 : (nType == EXC_SXFIELD_DATA_NONE);
271 : // for now, ignore data type of calculated fields
272 : OSL_ENSURE( bCalced || bType || bTypeNone, "XclImpPCField::ReadSxfield - unknown item data type" );
273 :
274 10 : if( nVisC > 0 || bPostp )
275 : {
276 10 : if( bItems && !bPostp )
277 : {
278 20 : if( !bCalced )
279 : {
280 : // 1) standard fields and standard grouping fields
281 10 : if( !bNum )
282 : {
283 : // 1a) standard field without grouping
284 10 : if( bType && (nGroupC == 0) && (nBaseC == 0) && (nOrigC == nVisC) )
285 10 : meFieldType = EXC_PCFIELD_STANDARD;
286 :
287 : // 1b) standard grouping field
288 0 : else if( bTypeNone && (nGroupC == nVisC) && (nBaseC > 0) && (nOrigC == 0) )
289 0 : meFieldType = EXC_PCFIELD_STDGROUP;
290 : }
291 : // 2) numerical grouping fields
292 0 : else if( (nGroupC == nVisC) && (nBaseC == 0) )
293 : {
294 : // 2a) single num/date grouping field without child grouping field
295 0 : if( !bChild && bType && (nOrigC > 0) )
296 : {
297 0 : switch( nType )
298 : {
299 : case EXC_SXFIELD_DATA_INT:
300 0 : case EXC_SXFIELD_DATA_DBL: meFieldType = EXC_PCFIELD_NUMGROUP; break;
301 0 : case EXC_SXFIELD_DATA_DATE: meFieldType = EXC_PCFIELD_DATEGROUP; break;
302 : default: OSL_FAIL( "XclImpPCField::ReadSxfield - numeric group with wrong data type" );
303 : }
304 : }
305 :
306 : // 2b) first date grouping field with child grouping field
307 0 : else if( bChild && (nType == EXC_SXFIELD_DATA_DATE) && (nOrigC > 0) )
308 0 : meFieldType = EXC_PCFIELD_DATEGROUP;
309 :
310 : // 2c) additional date grouping field
311 0 : else if( bTypeNone && (nOrigC == 0) )
312 0 : meFieldType = EXC_PCFIELD_DATECHILD;
313 : }
314 : OSL_ENSURE( meFieldType != EXC_PCFIELD_UNKNOWN, "XclImpPCField::ReadSxfield - invalid standard or grouped field" );
315 : }
316 :
317 : // 3) calculated field
318 : else
319 : {
320 0 : if( !bChild && !bNum && (nGroupC == 0) && (nBaseC == 0) && (nOrigC == 0) )
321 0 : meFieldType = EXC_PCFIELD_CALCED;
322 : OSL_ENSURE( meFieldType == EXC_PCFIELD_CALCED, "XclImpPCField::ReadSxfield - invalid calculated field" );
323 : }
324 : }
325 :
326 0 : else if( !bItems && bPostp )
327 : {
328 : // 4) standard field with postponed items
329 0 : if( !bCalced && !bChild && !bNum && bType && (nGroupC == 0) && (nBaseC == 0) && (nOrigC == 0) )
330 0 : meFieldType = EXC_PCFIELD_STANDARD;
331 : OSL_ENSURE( meFieldType == EXC_PCFIELD_STANDARD, "XclImpPCField::ReadSxfield - invalid postponed field" );
332 : }
333 : }
334 10 : }
335 :
336 30 : void XclImpPCField::ReadItem( XclImpStream& rStrm )
337 : {
338 : OSL_ENSURE( HasInlineItems() || HasPostponedItems(), "XclImpPCField::ReadItem - field does not expect items" );
339 :
340 : // read the item
341 30 : XclImpPCItemRef xItem( new XclImpPCItem( rStrm ) );
342 :
343 : // try to insert into an item list
344 30 : if( mbNumGroupInfoRead )
345 : {
346 : // there are 3 items after SXNUMGROUP that contain grouping limits and step count
347 0 : if( maNumGroupItems.size() < 3 )
348 0 : maNumGroupItems.push_back( xItem );
349 : else
350 0 : maOrigItems.push_back( xItem );
351 : }
352 30 : else if( HasInlineItems() || HasPostponedItems() )
353 : {
354 30 : maItems.push_back( xItem );
355 : // visible item is original item in standard fields
356 30 : if( IsStandardField() )
357 30 : maOrigItems.push_back( xItem );
358 30 : }
359 30 : }
360 :
361 0 : void XclImpPCField::ReadSxnumgroup( XclImpStream& rStrm )
362 : {
363 : OSL_ENSURE( IsNumGroupField() || IsDateGroupField(), "XclImpPCField::ReadSxnumgroup - SXNUMGROUP outside numeric grouping field" );
364 : OSL_ENSURE( !mbNumGroupInfoRead, "XclImpPCField::ReadSxnumgroup - multiple SXNUMGROUP records" );
365 : OSL_ENSURE( maItems.size() == maFieldInfo.mnGroupItems, "XclImpPCField::ReadSxnumgroup - SXNUMGROUP out of record order" );
366 0 : rStrm >> maNumGroupInfo;
367 0 : mbNumGroupInfoRead = IsNumGroupField() || IsDateGroupField();
368 0 : }
369 :
370 0 : void XclImpPCField::ReadSxgroupinfo( XclImpStream& rStrm )
371 : {
372 : OSL_ENSURE( IsStdGroupField(), "XclImpPCField::ReadSxgroupinfo - SXGROUPINFO outside grouping field" );
373 : OSL_ENSURE( maGroupOrder.empty(), "XclImpPCField::ReadSxgroupinfo - multiple SXGROUPINFO records" );
374 : OSL_ENSURE( maItems.size() == maFieldInfo.mnGroupItems, "XclImpPCField::ReadSxgroupinfo - SXGROUPINFO out of record order" );
375 : OSL_ENSURE( (rStrm.GetRecLeft() / 2) == maFieldInfo.mnBaseItems, "XclImpPCField::ReadSxgroupinfo - wrong SXGROUPINFO size" );
376 0 : maGroupOrder.clear();
377 0 : size_t nSize = rStrm.GetRecLeft() / 2;
378 0 : maGroupOrder.resize( nSize, 0 );
379 0 : for( size_t nIdx = 0; nIdx < nSize; ++nIdx )
380 0 : rStrm >> maGroupOrder[ nIdx ];
381 0 : }
382 :
383 : // grouping -------------------------------------------------------------------
384 :
385 4 : void XclImpPCField::ConvertGroupField( ScDPSaveData& rSaveData, const ScfStringVec& rVisNames ) const
386 : {
387 4 : if (!GetFieldName(rVisNames).isEmpty())
388 : {
389 4 : if( IsStdGroupField() )
390 0 : ConvertStdGroupField( rSaveData, rVisNames );
391 4 : else if( IsNumGroupField() )
392 0 : ConvertNumGroupField( rSaveData, rVisNames );
393 4 : else if( IsDateGroupField() )
394 0 : ConvertDateGroupField( rSaveData, rVisNames );
395 : }
396 4 : }
397 :
398 : // private --------------------------------------------------------------------
399 :
400 0 : void XclImpPCField::ConvertStdGroupField( ScDPSaveData& rSaveData, const ScfStringVec& rVisNames ) const
401 : {
402 0 : if( const XclImpPCField* pBaseField = GetGroupBaseField() )
403 : {
404 0 : const OUString& rBaseFieldName = pBaseField->GetFieldName( rVisNames );
405 0 : if( !rBaseFieldName.isEmpty() )
406 : {
407 : // *** create a ScDPSaveGroupItem for each own item, they collect base item names ***
408 0 : ScDPSaveGroupItemVec aGroupItems;
409 0 : aGroupItems.reserve( maItems.size() );
410 : // initialize with own item names
411 0 : for( XclImpPCItemVec::const_iterator aIt = maItems.begin(), aEnd = maItems.end(); aIt != aEnd; ++aIt )
412 0 : aGroupItems.push_back( ScDPSaveGroupItem( (*aIt)->ConvertToText() ) );
413 :
414 : // *** iterate over all base items, set their names at corresponding own items ***
415 0 : for( sal_uInt16 nItemIdx = 0, nItemCount = static_cast< sal_uInt16 >( maGroupOrder.size() ); nItemIdx < nItemCount; ++nItemIdx )
416 0 : if( maGroupOrder[ nItemIdx ] < aGroupItems.size() )
417 0 : if( const XclImpPCItem* pBaseItem = pBaseField->GetItem( nItemIdx ) )
418 0 : if( const XclImpPCItem* pGroupItem = GetItem( maGroupOrder[ nItemIdx ] ) )
419 0 : if( *pBaseItem != *pGroupItem )
420 0 : aGroupItems[ maGroupOrder[ nItemIdx ] ].AddElement( pBaseItem->ConvertToText() );
421 :
422 : // *** create the ScDPSaveGroupDimension object, fill with grouping info ***
423 0 : ScDPSaveGroupDimension aGroupDim( rBaseFieldName, GetFieldName( rVisNames ) );
424 0 : for( ScDPSaveGroupItemVec::const_iterator aIt = aGroupItems.begin(), aEnd = aGroupItems.end(); aIt != aEnd; ++aIt )
425 0 : if( !aIt->IsEmpty() )
426 0 : aGroupDim.AddGroupItem( *aIt );
427 0 : rSaveData.GetDimensionData()->AddGroupDimension( aGroupDim );
428 : }
429 : }
430 0 : }
431 :
432 0 : void XclImpPCField::ConvertNumGroupField( ScDPSaveData& rSaveData, const ScfStringVec& rVisNames ) const
433 : {
434 0 : ScDPNumGroupInfo aNumInfo( GetScNumGroupInfo() );
435 0 : ScDPSaveNumGroupDimension aNumGroupDim( GetFieldName( rVisNames ), aNumInfo );
436 0 : rSaveData.GetDimensionData()->AddNumGroupDimension( aNumGroupDim );
437 0 : }
438 :
439 0 : void XclImpPCField::ConvertDateGroupField( ScDPSaveData& rSaveData, const ScfStringVec& rVisNames ) const
440 : {
441 0 : ScDPNumGroupInfo aDateInfo( GetScDateGroupInfo() );
442 0 : sal_Int32 nScDateType = maNumGroupInfo.GetScDateType();
443 :
444 0 : switch( meFieldType )
445 : {
446 : case EXC_PCFIELD_DATEGROUP:
447 : {
448 0 : if( aDateInfo.mbDateValues )
449 : {
450 : // special case for days only with step value - create numeric grouping
451 0 : ScDPSaveNumGroupDimension aNumGroupDim( GetFieldName( rVisNames ), aDateInfo );
452 0 : rSaveData.GetDimensionData()->AddNumGroupDimension( aNumGroupDim );
453 : }
454 : else
455 : {
456 0 : ScDPSaveNumGroupDimension aNumGroupDim( GetFieldName( rVisNames ), ScDPNumGroupInfo() );
457 0 : aNumGroupDim.SetDateInfo( aDateInfo, nScDateType );
458 0 : rSaveData.GetDimensionData()->AddNumGroupDimension( aNumGroupDim );
459 : }
460 : }
461 0 : break;
462 :
463 : case EXC_PCFIELD_DATECHILD:
464 : {
465 0 : if( const XclImpPCField* pBaseField = GetGroupBaseField() )
466 : {
467 0 : const OUString& rBaseFieldName = pBaseField->GetFieldName( rVisNames );
468 0 : if( !rBaseFieldName.isEmpty() )
469 : {
470 0 : ScDPSaveGroupDimension aGroupDim( rBaseFieldName, GetFieldName( rVisNames ) );
471 0 : aGroupDim.SetDateInfo( aDateInfo, nScDateType );
472 0 : rSaveData.GetDimensionData()->AddGroupDimension( aGroupDim );
473 : }
474 : }
475 : }
476 0 : break;
477 :
478 : default:
479 : OSL_FAIL( "XclImpPCField::ConvertDateGroupField - unknown date field type" );
480 : }
481 0 : }
482 :
483 0 : ScDPNumGroupInfo XclImpPCField::GetScNumGroupInfo() const
484 : {
485 0 : ScDPNumGroupInfo aNumInfo;
486 0 : aNumInfo.mbEnable = true;
487 0 : aNumInfo.mbDateValues = false;
488 0 : aNumInfo.mbAutoStart = true;
489 0 : aNumInfo.mbAutoEnd = true;
490 :
491 0 : if( const double* pfMinValue = GetNumGroupLimit( EXC_SXFIELD_INDEX_MIN ) )
492 : {
493 0 : aNumInfo.mfStart = *pfMinValue;
494 0 : aNumInfo.mbAutoStart = ::get_flag( maNumGroupInfo.mnFlags, EXC_SXNUMGROUP_AUTOMIN );
495 : }
496 0 : if( const double* pfMaxValue = GetNumGroupLimit( EXC_SXFIELD_INDEX_MAX ) )
497 : {
498 0 : aNumInfo.mfEnd = *pfMaxValue;
499 0 : aNumInfo.mbAutoEnd = ::get_flag( maNumGroupInfo.mnFlags, EXC_SXNUMGROUP_AUTOMAX );
500 : }
501 0 : if( const double* pfStepValue = GetNumGroupLimit( EXC_SXFIELD_INDEX_STEP ) )
502 0 : aNumInfo.mfStep = *pfStepValue;
503 :
504 0 : return aNumInfo;
505 : }
506 :
507 0 : ScDPNumGroupInfo XclImpPCField::GetScDateGroupInfo() const
508 : {
509 0 : ScDPNumGroupInfo aDateInfo;
510 0 : aDateInfo.mbEnable = true;
511 0 : aDateInfo.mbDateValues = false;
512 0 : aDateInfo.mbAutoStart = true;
513 0 : aDateInfo.mbAutoEnd = true;
514 :
515 0 : if( const DateTime* pMinDate = GetDateGroupLimit( EXC_SXFIELD_INDEX_MIN ) )
516 : {
517 0 : aDateInfo.mfStart = GetDoubleFromDateTime( *pMinDate );
518 0 : aDateInfo.mbAutoStart = ::get_flag( maNumGroupInfo.mnFlags, EXC_SXNUMGROUP_AUTOMIN );
519 : }
520 0 : if( const DateTime* pMaxDate = GetDateGroupLimit( EXC_SXFIELD_INDEX_MAX ) )
521 : {
522 0 : aDateInfo.mfEnd = GetDoubleFromDateTime( *pMaxDate );
523 0 : aDateInfo.mbAutoEnd = ::get_flag( maNumGroupInfo.mnFlags, EXC_SXNUMGROUP_AUTOMAX );
524 : }
525 : // GetDateGroupStep() returns a value for date type "day" in single date groups only
526 0 : if( const sal_Int16* pnStepValue = GetDateGroupStep() )
527 : {
528 0 : aDateInfo.mfStep = *pnStepValue;
529 0 : aDateInfo.mbDateValues = true;
530 : }
531 :
532 0 : return aDateInfo;
533 : }
534 :
535 0 : const double* XclImpPCField::GetNumGroupLimit( sal_uInt16 nLimitIdx ) const
536 : {
537 : OSL_ENSURE( IsNumGroupField(), "XclImpPCField::GetNumGroupLimit - only for numeric grouping fields" );
538 0 : if( const XclImpPCItem* pItem = GetLimitItem( nLimitIdx ) )
539 : {
540 : OSL_ENSURE( pItem->GetDouble(), "XclImpPCField::GetNumGroupLimit - SXDOUBLE item expected" );
541 0 : return pItem->GetDouble();
542 : }
543 0 : return 0;
544 : }
545 :
546 0 : const DateTime* XclImpPCField::GetDateGroupLimit( sal_uInt16 nLimitIdx ) const
547 : {
548 : OSL_ENSURE( IsDateGroupField(), "XclImpPCField::GetDateGroupLimit - only for date grouping fields" );
549 0 : if( const XclImpPCItem* pItem = GetLimitItem( nLimitIdx ) )
550 : {
551 : OSL_ENSURE( pItem->GetDateTime(), "XclImpPCField::GetDateGroupLimit - SXDATETIME item expected" );
552 0 : return pItem->GetDateTime();
553 : }
554 0 : return 0;
555 : }
556 :
557 0 : const sal_Int16* XclImpPCField::GetDateGroupStep() const
558 : {
559 : // only for single date grouping fields, not for grouping chains
560 0 : if( !IsGroupBaseField() && !IsGroupChildField() )
561 : {
562 : // only days may have a step value, return 0 for all other date types
563 0 : if( maNumGroupInfo.GetXclDataType() == EXC_SXNUMGROUP_TYPE_DAY )
564 : {
565 0 : if( const XclImpPCItem* pItem = GetLimitItem( EXC_SXFIELD_INDEX_STEP ) )
566 : {
567 : OSL_ENSURE( pItem->GetInteger(), "XclImpPCField::GetDateGroupStep - SXINTEGER item expected" );
568 0 : if( const sal_Int16* pnStep = pItem->GetInteger() )
569 : {
570 : OSL_ENSURE( *pnStep > 0, "XclImpPCField::GetDateGroupStep - invalid step count" );
571 : // return nothing for step count 1 - this is also a standard date group in Excel
572 0 : return (*pnStep > 1) ? pnStep : 0;
573 : }
574 : }
575 : }
576 : }
577 0 : return 0;
578 : }
579 :
580 4 : XclImpPivotCache::XclImpPivotCache( const XclImpRoot& rRoot ) :
581 : XclImpRoot( rRoot ),
582 : maSrcRange( ScAddress::INITIALIZE_INVALID ),
583 : mnStrmId( 0 ),
584 : mnSrcType( EXC_SXVS_UNKNOWN ),
585 4 : mbSelfRef( false )
586 : {
587 4 : }
588 :
589 8 : XclImpPivotCache::~XclImpPivotCache()
590 : {
591 8 : }
592 :
593 : // data access ----------------------------------------------------------------
594 :
595 10 : sal_uInt16 XclImpPivotCache::GetFieldCount() const
596 : {
597 10 : return static_cast< sal_uInt16 >( maFields.size() );
598 : }
599 :
600 30 : const XclImpPCField* XclImpPivotCache::GetField( sal_uInt16 nFieldIdx ) const
601 : {
602 30 : return (nFieldIdx < maFields.size()) ? maFields[ nFieldIdx ].get() : 0;
603 : }
604 :
605 : // records --------------------------------------------------------------------
606 :
607 4 : void XclImpPivotCache::ReadSxidstm( XclImpStream& rStrm )
608 : {
609 4 : rStrm >> mnStrmId;
610 4 : }
611 :
612 4 : void XclImpPivotCache::ReadSxvs( XclImpStream& rStrm )
613 : {
614 4 : rStrm >> mnSrcType;
615 4 : GetTracer().TracePivotDataSource( mnSrcType != EXC_SXVS_SHEET );
616 4 : }
617 :
618 4 : void XclImpPivotCache::ReadDconref( XclImpStream& rStrm )
619 : {
620 : /* Read DCONREF only once (by checking maTabName), there may be other
621 : DCONREF records in another context. Read reference only if a leading
622 : SXVS record is present (by checking mnSrcType). */
623 4 : if( !maTabName.isEmpty() || (mnSrcType != EXC_SXVS_SHEET) )
624 4 : return;
625 :
626 4 : XclRange aXclRange( ScAddress::UNINITIALIZED );
627 4 : aXclRange.Read( rStrm, false );
628 4 : OUString aEncUrl = rStrm.ReadUniString();
629 :
630 4 : XclImpUrlHelper::DecodeUrl( maUrl, maTabName, mbSelfRef, GetRoot(), aEncUrl );
631 :
632 : /* Do not convert maTabName to Calc sheet name -> original name is used to
633 : find the sheet in the document. Sheet index of source range will be
634 : found later in XclImpPivotCache::ReadPivotCacheStream(), because sheet
635 : may not exist yet. */
636 4 : if( mbSelfRef )
637 4 : GetAddressConverter().ConvertRange( maSrcRange, aXclRange, 0, 0, true );
638 : }
639 :
640 0 : void XclImpPivotCache::ReadDConName( XclImpStream& rStrm )
641 : {
642 0 : maSrcRangeName = rStrm.ReadUniString();
643 :
644 : // This 2-byte value equals the length of string that follows, or if 0 it
645 : // indicates that the name has a workbook scope. For now, we only support
646 : // internal defined name with a workbook scope.
647 : sal_uInt16 nFlag;
648 0 : rStrm >> nFlag;
649 0 : mbSelfRef = (nFlag == 0);
650 :
651 0 : if (!mbSelfRef)
652 : // External name is not supported yet.
653 0 : maSrcRangeName = OUString();
654 0 : }
655 :
656 4 : void XclImpPivotCache::ReadPivotCacheStream( XclImpStream& rStrm )
657 : {
658 4 : if( (mnSrcType != EXC_SXVS_SHEET) && (mnSrcType != EXC_SXVS_EXTERN) )
659 0 : return;
660 :
661 4 : ScDocument& rDoc = GetDoc();
662 4 : SCCOL nFieldScCol = 0; // column index of source data for next field
663 4 : SCROW nItemScRow = 0; // row index of source data for current items
664 4 : SCTAB nScTab = 0; // sheet index of source data
665 4 : bool bGenerateSource = false; // true = write source data from cache to dummy table
666 :
667 4 : if( mbSelfRef )
668 : {
669 4 : if (maSrcRangeName.isEmpty())
670 : {
671 : // try to find internal sheet containing the source data
672 4 : nScTab = GetTabInfo().GetScTabFromXclName( maTabName );
673 4 : if( rDoc.HasTable( nScTab ) )
674 : {
675 : // set sheet index to source range
676 4 : maSrcRange.aStart.SetTab( nScTab );
677 4 : maSrcRange.aEnd.SetTab( nScTab );
678 : }
679 : else
680 : {
681 : // create dummy sheet for deleted internal sheet
682 0 : bGenerateSource = true;
683 : }
684 : }
685 : }
686 : else
687 : {
688 : // create dummy sheet for external sheet
689 0 : bGenerateSource = true;
690 : }
691 :
692 : // create dummy sheet for source data from external or deleted sheet
693 4 : if( bGenerateSource )
694 : {
695 0 : if( rDoc.GetTableCount() >= MAXTABCOUNT )
696 : // cannot create more sheets -> exit
697 0 : return;
698 :
699 0 : nScTab = rDoc.GetTableCount();
700 0 : rDoc.MakeTable( nScTab );
701 0 : OUStringBuffer aDummyName("DPCache");
702 0 : if( maTabName.getLength() > 0 )
703 0 : aDummyName.append( '_' ).append( maTabName );
704 0 : OUString aName = aDummyName.makeStringAndClear();
705 0 : rDoc.CreateValidTabName( aName );
706 0 : rDoc.RenameTab( nScTab, aName );
707 : // set sheet index to source range
708 0 : maSrcRange.aStart.SetTab( nScTab );
709 0 : maSrcRange.aEnd.SetTab( nScTab );
710 : }
711 :
712 : // open pivot cache storage stream
713 4 : SotStorageRef xSvStrg = OpenStorage( EXC_STORAGE_PTCACHE );
714 8 : SotStorageStreamRef xSvStrm = OpenStream( xSvStrg, ScfTools::GetHexStr( mnStrmId ) );
715 4 : if( !xSvStrm.Is() )
716 0 : return;
717 :
718 : // create Excel record stream object
719 8 : XclImpStream aPCStrm( *xSvStrm, GetRoot() );
720 4 : aPCStrm.CopyDecrypterFrom( rStrm ); // pivot cache streams are encrypted
721 :
722 8 : XclImpPCFieldRef xCurrField; // current field for new items
723 8 : XclImpPCFieldVec aOrigFields; // all standard fields with inline original items
724 8 : XclImpPCFieldVec aPostpFields; // all standard fields with postponed original items
725 4 : size_t nPostpIdx = 0; // index to current field with postponed items
726 4 : bool bLoop = true; // true = continue loop
727 :
728 82 : while( bLoop && aPCStrm.StartNextRecord() )
729 : {
730 74 : switch( aPCStrm.GetRecId() )
731 : {
732 : case EXC_ID_EOF:
733 4 : bLoop = false;
734 4 : break;
735 :
736 : case EXC_ID_SXDB:
737 4 : aPCStrm >> maPCInfo;
738 4 : break;
739 :
740 : case EXC_ID_SXFIELD:
741 : {
742 10 : xCurrField.reset();
743 10 : sal_uInt16 nNewFieldIdx = GetFieldCount();
744 10 : if( nNewFieldIdx < EXC_PC_MAXFIELDCOUNT )
745 : {
746 10 : xCurrField.reset( new XclImpPCField( GetRoot(), *this, nNewFieldIdx ) );
747 10 : maFields.push_back( xCurrField );
748 10 : xCurrField->ReadSxfield( aPCStrm );
749 10 : if( xCurrField->HasOrigItems() )
750 : {
751 10 : if( xCurrField->HasPostponedItems() )
752 0 : aPostpFields.push_back( xCurrField );
753 : else
754 10 : aOrigFields.push_back( xCurrField );
755 : // insert field name into generated source data, field remembers its column index
756 10 : if( bGenerateSource && (nFieldScCol <= MAXCOL) )
757 0 : xCurrField->WriteFieldNameToSource( nFieldScCol++, nScTab );
758 : }
759 : // do not read items into invalid/postponed fields
760 10 : if( !xCurrField->HasInlineItems() )
761 0 : xCurrField.reset();
762 : }
763 : }
764 10 : break;
765 :
766 : case EXC_ID_SXINDEXLIST:
767 : // read index list and insert all items into generated source data
768 12 : if( bGenerateSource && (nItemScRow <= MAXROW) && (++nItemScRow <= MAXROW) )
769 : {
770 0 : for( XclImpPCFieldVec::const_iterator aIt = aOrigFields.begin(), aEnd = aOrigFields.end(); aIt != aEnd; ++aIt )
771 : {
772 0 : sal_uInt16 nItemIdx = (*aIt)->Has16BitIndexes() ? aPCStrm.ReaduInt16() : aPCStrm.ReaduInt8();
773 0 : (*aIt)->WriteOrigItemToSource( nItemScRow, nScTab, nItemIdx );
774 : }
775 : }
776 12 : xCurrField.reset();
777 12 : break;
778 :
779 : case EXC_ID_SXDOUBLE:
780 : case EXC_ID_SXBOOLEAN:
781 : case EXC_ID_SXERROR:
782 : case EXC_ID_SXINTEGER:
783 : case EXC_ID_SXSTRING:
784 : case EXC_ID_SXDATETIME:
785 : case EXC_ID_SXEMPTY:
786 30 : if( xCurrField ) // inline items
787 : {
788 30 : xCurrField->ReadItem( aPCStrm );
789 : }
790 0 : else if( !aPostpFields.empty() ) // postponed items
791 : {
792 : // read postponed item
793 0 : aPostpFields[ nPostpIdx ]->ReadItem( aPCStrm );
794 : // write item to source
795 0 : if( bGenerateSource && (nItemScRow <= MAXROW) )
796 : {
797 : // start new row, if there are only postponed fields
798 0 : if( aOrigFields.empty() && (nPostpIdx == 0) )
799 0 : ++nItemScRow;
800 0 : if( nItemScRow <= MAXROW )
801 0 : aPostpFields[ nPostpIdx ]->WriteLastOrigItemToSource( nItemScRow, nScTab );
802 : }
803 : // get index of next postponed field
804 0 : ++nPostpIdx;
805 0 : if( nPostpIdx >= aPostpFields.size() )
806 0 : nPostpIdx = 0;
807 : }
808 30 : break;
809 :
810 : case EXC_ID_SXNUMGROUP:
811 0 : if( xCurrField )
812 0 : xCurrField->ReadSxnumgroup( aPCStrm );
813 0 : break;
814 :
815 : case EXC_ID_SXGROUPINFO:
816 0 : if( xCurrField )
817 0 : xCurrField->ReadSxgroupinfo( aPCStrm );
818 0 : break;
819 :
820 : // known but ignored records
821 : case EXC_ID_SXRULE:
822 : case EXC_ID_SXFILT:
823 : case EXC_ID_00F5:
824 : case EXC_ID_SXNAME:
825 : case EXC_ID_SXPAIR:
826 : case EXC_ID_SXFMLA:
827 : case EXC_ID_SXFORMULA:
828 : case EXC_ID_SXDBEX:
829 : case EXC_ID_SXFDBTYPE:
830 14 : break;
831 :
832 : default:
833 : OSL_TRACE( "XclImpPivotCache::ReadPivotCacheStream - unknown record 0x%04hX", aPCStrm.GetRecId() );
834 : }
835 : }
836 :
837 : OSL_ENSURE( maPCInfo.mnTotalFields == maFields.size(),
838 : "XclImpPivotCache::ReadPivotCacheStream - field count mismatch" );
839 :
840 4 : if (HasCacheRecords())
841 : {
842 4 : SCROW nNewEnd = maSrcRange.aStart.Row() + maPCInfo.mnSrcRecs;
843 4 : maSrcRange.aEnd.SetRow(nNewEnd);
844 : }
845 :
846 : // set source range for external source data
847 4 : if( bGenerateSource && (nFieldScCol > 0) )
848 : {
849 0 : maSrcRange.aStart.SetCol( 0 );
850 0 : maSrcRange.aStart.SetRow( 0 );
851 : // nFieldScCol points to first unused column
852 0 : maSrcRange.aEnd.SetCol( nFieldScCol - 1 );
853 : // nItemScRow points to last used row
854 0 : maSrcRange.aEnd.SetRow( nItemScRow );
855 4 : }
856 : }
857 :
858 4 : bool XclImpPivotCache::HasCacheRecords() const
859 : {
860 4 : return static_cast<bool>(maPCInfo.mnFlags & EXC_SXDB_SAVEDATA);
861 : }
862 :
863 2 : bool XclImpPivotCache::IsRefreshOnLoad() const
864 : {
865 2 : return static_cast<bool>(maPCInfo.mnFlags & EXC_SXDB_REFRESH_LOAD);
866 : }
867 :
868 2 : bool XclImpPivotCache::IsValid() const
869 : {
870 2 : if (!maSrcRangeName.isEmpty())
871 0 : return true;
872 :
873 2 : return maSrcRange.IsValid();
874 : }
875 :
876 : // Pivot table
877 :
878 30 : XclImpPTItem::XclImpPTItem( const XclImpPCField* pCacheField ) :
879 30 : mpCacheField( pCacheField )
880 : {
881 30 : }
882 :
883 20 : const OUString* XclImpPTItem::GetItemName() const
884 : {
885 20 : if( mpCacheField )
886 20 : if( const XclImpPCItem* pCacheItem = mpCacheField->GetItem( maItemInfo.mnCacheIdx ) )
887 : //! TODO: use XclImpPCItem::ConvertToText(), if all conversions are available
888 16 : return pCacheItem->IsEmpty() ? NULL : pCacheItem->GetText();
889 4 : return 0;
890 : }
891 :
892 30 : void XclImpPTItem::ReadSxvi( XclImpStream& rStrm )
893 : {
894 30 : rStrm >> maItemInfo;
895 30 : }
896 :
897 18 : void XclImpPTItem::ConvertItem( ScDPSaveDimension& rSaveDim ) const
898 : {
899 18 : if (const OUString* pItemName = GetItemName())
900 : {
901 14 : ScDPSaveMember& rMember = *rSaveDim.GetMemberByName( *pItemName );
902 14 : rMember.SetIsVisible( !::get_flag( maItemInfo.mnFlags, EXC_SXVI_HIDDEN ) );
903 14 : rMember.SetShowDetails( !::get_flag( maItemInfo.mnFlags, EXC_SXVI_HIDEDETAIL ) );
904 14 : if (maItemInfo.HasVisName())
905 0 : rMember.SetLayoutName(*maItemInfo.GetVisName());
906 : }
907 18 : }
908 :
909 14 : XclImpPTField::XclImpPTField( const XclImpPivotTable& rPTable, sal_uInt16 nCacheIdx ) :
910 14 : mrPTable( rPTable )
911 : {
912 14 : maFieldInfo.mnCacheIdx = nCacheIdx;
913 14 : }
914 :
915 : // general field/item access --------------------------------------------------
916 :
917 42 : const XclImpPCField* XclImpPTField::GetCacheField() const
918 : {
919 42 : XclImpPivotCacheRef xPCache = mrPTable.GetPivotCache();
920 42 : return xPCache ? xPCache->GetField( maFieldInfo.mnCacheIdx ) : 0;
921 : }
922 :
923 8 : OUString XclImpPTField::GetFieldName() const
924 : {
925 8 : const XclImpPCField* pField = GetCacheField();
926 8 : return pField ? pField->GetFieldName( mrPTable.GetVisFieldNames() ) : OUString();
927 : }
928 :
929 10 : OUString XclImpPTField::GetVisFieldName() const
930 : {
931 10 : const OUString* pVisName = maFieldInfo.GetVisName();
932 10 : return pVisName ? *pVisName : OUString();
933 : }
934 :
935 2 : const XclImpPTItem* XclImpPTField::GetItem( sal_uInt16 nItemIdx ) const
936 : {
937 2 : return (nItemIdx < maItems.size()) ? maItems[ nItemIdx ].get() : 0;
938 : }
939 :
940 2 : const OUString* XclImpPTField::GetItemName( sal_uInt16 nItemIdx ) const
941 : {
942 2 : const XclImpPTItem* pItem = GetItem( nItemIdx );
943 2 : return pItem ? pItem->GetItemName() : 0;
944 : }
945 :
946 : // records --------------------------------------------------------------------
947 :
948 10 : void XclImpPTField::ReadSxvd( XclImpStream& rStrm )
949 : {
950 10 : rStrm >> maFieldInfo;
951 10 : }
952 :
953 10 : void XclImpPTField::ReadSxvdex( XclImpStream& rStrm )
954 : {
955 10 : rStrm >> maFieldExtInfo;
956 10 : }
957 :
958 30 : void XclImpPTField::ReadSxvi( XclImpStream& rStrm )
959 : {
960 30 : XclImpPTItemRef xItem( new XclImpPTItem( GetCacheField() ) );
961 30 : maItems.push_back( xItem );
962 30 : xItem->ReadSxvi( rStrm );
963 30 : }
964 :
965 : // row/column fields ----------------------------------------------------------
966 :
967 4 : void XclImpPTField::ConvertRowColField( ScDPSaveData& rSaveData ) const
968 : {
969 : OSL_ENSURE( maFieldInfo.mnAxes & EXC_SXVD_AXIS_ROWCOL, "XclImpPTField::ConvertRowColField - no row/column field" );
970 : // special data orientation field?
971 4 : if( maFieldInfo.mnCacheIdx == EXC_SXIVD_DATA )
972 0 : rSaveData.GetDataLayoutDimension()->SetOrientation( static_cast< sal_uInt16 >( maFieldInfo.GetApiOrient( EXC_SXVD_AXIS_ROWCOL ) ) );
973 : else
974 4 : ConvertRCPField( rSaveData );
975 4 : }
976 :
977 : // page fields ----------------------------------------------------------------
978 :
979 0 : void XclImpPTField::SetPageFieldInfo( const XclPTPageFieldInfo& rPageInfo )
980 : {
981 0 : maPageInfo = rPageInfo;
982 0 : }
983 :
984 0 : void XclImpPTField::ConvertPageField( ScDPSaveData& rSaveData ) const
985 : {
986 : OSL_ENSURE( maFieldInfo.mnAxes & EXC_SXVD_AXIS_PAGE, "XclImpPTField::ConvertPageField - no page field" );
987 0 : if( ScDPSaveDimension* pSaveDim = ConvertRCPField( rSaveData ) )
988 : {
989 0 : const OUString* pName = GetItemName( maPageInfo.mnSelItem );
990 0 : if (pName)
991 0 : pSaveDim->SetCurrentPage(pName);
992 : }
993 0 : }
994 :
995 : // hidden fields --------------------------------------------------------------
996 :
997 0 : void XclImpPTField::ConvertHiddenField( ScDPSaveData& rSaveData ) const
998 : {
999 : OSL_ENSURE( (maFieldInfo.mnAxes & EXC_SXVD_AXIS_ROWCOLPAGE) == 0, "XclImpPTField::ConvertHiddenField - field not hidden" );
1000 0 : ConvertRCPField( rSaveData );
1001 0 : }
1002 :
1003 : // data fields ----------------------------------------------------------------
1004 :
1005 2 : bool XclImpPTField::HasDataFieldInfo() const
1006 : {
1007 2 : return !maDataInfoList.empty();
1008 : }
1009 :
1010 2 : void XclImpPTField::AddDataFieldInfo( const XclPTDataFieldInfo& rDataInfo )
1011 : {
1012 : OSL_ENSURE( maFieldInfo.mnAxes & EXC_SXVD_AXIS_DATA, "XclImpPTField::AddDataFieldInfo - no data field" );
1013 2 : maDataInfoList.push_back( rDataInfo );
1014 2 : }
1015 :
1016 2 : void XclImpPTField::ConvertDataField( ScDPSaveData& rSaveData ) const
1017 : {
1018 : OSL_ENSURE( maFieldInfo.mnAxes & EXC_SXVD_AXIS_DATA, "XclImpPTField::ConvertDataField - no data field" );
1019 : OSL_ENSURE( !maDataInfoList.empty(), "XclImpPTField::ConvertDataField - no data field info" );
1020 2 : if (maDataInfoList.empty())
1021 0 : return;
1022 :
1023 2 : OUString aFieldName = GetFieldName();
1024 2 : if (aFieldName.isEmpty())
1025 0 : return;
1026 :
1027 2 : XclPTDataFieldInfoList::const_iterator aIt = maDataInfoList.begin(), aEnd = maDataInfoList.end();
1028 :
1029 2 : ScDPSaveDimension& rSaveDim = *rSaveData.GetNewDimensionByName(aFieldName);
1030 2 : ConvertDataField( rSaveDim, *aIt );
1031 :
1032 : // multiple data fields -> clone dimension
1033 2 : for( ++aIt; aIt != aEnd; ++aIt )
1034 : {
1035 0 : ScDPSaveDimension& rDupDim = rSaveData.DuplicateDimension( rSaveDim );
1036 0 : ConvertDataFieldInfo( rDupDim, *aIt );
1037 2 : }
1038 : }
1039 :
1040 : // private --------------------------------------------------------------------
1041 :
1042 : /**
1043 : * Convert Excel-encoded subtotal name to a Calc-encoded one.
1044 : */
1045 0 : static OUString lcl_convertExcelSubtotalName(const OUString& rName)
1046 : {
1047 0 : OUStringBuffer aBuf;
1048 0 : const sal_Unicode* p = rName.getStr();
1049 0 : sal_Int32 n = rName.getLength();
1050 0 : for (sal_Int32 i = 0; i < n; ++i)
1051 : {
1052 0 : const sal_Unicode c = p[i];
1053 0 : if (c == '\\')
1054 : {
1055 0 : aBuf.append(c);
1056 0 : aBuf.append(c);
1057 : }
1058 : else
1059 0 : aBuf.append(c);
1060 : }
1061 0 : return aBuf.makeStringAndClear();
1062 : }
1063 :
1064 4 : ScDPSaveDimension* XclImpPTField::ConvertRCPField( ScDPSaveData& rSaveData ) const
1065 : {
1066 4 : const OUString& rFieldName = GetFieldName();
1067 4 : if( rFieldName.isEmpty() )
1068 0 : return 0;
1069 :
1070 4 : const XclImpPCField* pCacheField = GetCacheField();
1071 4 : if( !pCacheField || !pCacheField->IsSupportedField() )
1072 0 : return 0;
1073 :
1074 4 : ScDPSaveDimension* pTest = rSaveData.GetNewDimensionByName(rFieldName);
1075 4 : if (!pTest)
1076 0 : return NULL;
1077 :
1078 4 : ScDPSaveDimension& rSaveDim = *pTest;
1079 :
1080 : // orientation
1081 4 : rSaveDim.SetOrientation( static_cast< sal_uInt16 >( maFieldInfo.GetApiOrient( EXC_SXVD_AXIS_ROWCOLPAGE ) ) );
1082 :
1083 : // general field info
1084 4 : ConvertFieldInfo( rSaveDim );
1085 :
1086 : // visible name
1087 4 : if (const OUString* pVisName = maFieldInfo.GetVisName())
1088 0 : if (!pVisName->isEmpty())
1089 0 : rSaveDim.SetLayoutName( *pVisName );
1090 :
1091 : // subtotal function(s)
1092 8 : XclPTSubtotalVec aSubtotalVec;
1093 4 : maFieldInfo.GetSubtotals( aSubtotalVec );
1094 4 : if( !aSubtotalVec.empty() )
1095 4 : rSaveDim.SetSubTotals( static_cast< long >( aSubtotalVec.size() ), &aSubtotalVec[ 0 ] );
1096 :
1097 : // sorting
1098 8 : DataPilotFieldSortInfo aSortInfo;
1099 4 : aSortInfo.Field = mrPTable.GetDataFieldName( maFieldExtInfo.mnSortField );
1100 4 : aSortInfo.IsAscending = ::get_flag( maFieldExtInfo.mnFlags, EXC_SXVDEX_SORT_ASC );
1101 4 : aSortInfo.Mode = maFieldExtInfo.GetApiSortMode();
1102 4 : rSaveDim.SetSortInfo( &aSortInfo );
1103 :
1104 : // auto show
1105 8 : DataPilotFieldAutoShowInfo aShowInfo;
1106 4 : aShowInfo.IsEnabled = ::get_flag( maFieldExtInfo.mnFlags, EXC_SXVDEX_AUTOSHOW );
1107 4 : aShowInfo.ShowItemsMode = maFieldExtInfo.GetApiAutoShowMode();
1108 4 : aShowInfo.ItemCount = maFieldExtInfo.GetApiAutoShowCount();
1109 4 : aShowInfo.DataField = mrPTable.GetDataFieldName( maFieldExtInfo.mnShowField );
1110 4 : rSaveDim.SetAutoShowInfo( &aShowInfo );
1111 :
1112 : // layout
1113 4 : DataPilotFieldLayoutInfo aLayoutInfo;
1114 4 : aLayoutInfo.LayoutMode = maFieldExtInfo.GetApiLayoutMode();
1115 4 : aLayoutInfo.AddEmptyLines = ::get_flag( maFieldExtInfo.mnFlags, EXC_SXVDEX_LAYOUT_BLANK );
1116 4 : rSaveDim.SetLayoutInfo( &aLayoutInfo );
1117 :
1118 : // grouping info
1119 4 : pCacheField->ConvertGroupField( rSaveData, mrPTable.GetVisFieldNames() );
1120 :
1121 : // custom subtotal name
1122 4 : if (maFieldExtInfo.mpFieldTotalName.get())
1123 : {
1124 0 : OUString aSubName = lcl_convertExcelSubtotalName(*maFieldExtInfo.mpFieldTotalName);
1125 0 : rSaveDim.SetSubtotalName(aSubName);
1126 : }
1127 :
1128 8 : return &rSaveDim;
1129 : }
1130 :
1131 6 : void XclImpPTField::ConvertFieldInfo( ScDPSaveDimension& rSaveDim ) const
1132 : {
1133 6 : rSaveDim.SetShowEmpty( ::get_flag( maFieldExtInfo.mnFlags, EXC_SXVDEX_SHOWALL ) );
1134 6 : ConvertItems( rSaveDim );
1135 6 : }
1136 :
1137 2 : void XclImpPTField::ConvertDataField( ScDPSaveDimension& rSaveDim, const XclPTDataFieldInfo& rDataInfo ) const
1138 : {
1139 : // orientation
1140 2 : rSaveDim.SetOrientation( DataPilotFieldOrientation_DATA );
1141 : // general field info
1142 2 : ConvertFieldInfo( rSaveDim );
1143 : // extended data field info
1144 2 : ConvertDataFieldInfo( rSaveDim, rDataInfo );
1145 2 : }
1146 :
1147 2 : void XclImpPTField::ConvertDataFieldInfo( ScDPSaveDimension& rSaveDim, const XclPTDataFieldInfo& rDataInfo ) const
1148 : {
1149 : // visible name
1150 2 : const OUString* pVisName = rDataInfo.GetVisName();
1151 2 : if (pVisName && !pVisName->isEmpty())
1152 2 : rSaveDim.SetLayoutName(*pVisName);
1153 :
1154 : // aggregation function
1155 2 : rSaveDim.SetFunction( static_cast< sal_uInt16 >( rDataInfo.GetApiAggFunc() ) );
1156 :
1157 : // result field reference
1158 2 : sal_Int32 nRefType = rDataInfo.GetApiRefType();
1159 2 : DataPilotFieldReference aFieldRef;
1160 2 : aFieldRef.ReferenceType = nRefType;
1161 2 : const XclImpPTField* pRefField = mrPTable.GetField(rDataInfo.mnRefField);
1162 2 : if (pRefField)
1163 : {
1164 2 : aFieldRef.ReferenceField = pRefField->GetFieldName();
1165 2 : aFieldRef.ReferenceItemType = rDataInfo.GetApiRefItemType();
1166 2 : if (aFieldRef.ReferenceItemType == sheet::DataPilotFieldReferenceItemType::NAMED)
1167 : {
1168 2 : const OUString* pRefItemName = pRefField->GetItemName(rDataInfo.mnRefItem);
1169 2 : if (pRefItemName)
1170 2 : aFieldRef.ReferenceItemName = *pRefItemName;
1171 : }
1172 : }
1173 :
1174 2 : rSaveDim.SetReferenceValue(&aFieldRef);
1175 2 : }
1176 :
1177 6 : void XclImpPTField::ConvertItems( ScDPSaveDimension& rSaveDim ) const
1178 : {
1179 24 : for( XclImpPTItemVec::const_iterator aIt = maItems.begin(), aEnd = maItems.end(); aIt != aEnd; ++aIt )
1180 18 : (*aIt)->ConvertItem( rSaveDim );
1181 6 : }
1182 :
1183 4 : XclImpPivotTable::XclImpPivotTable( const XclImpRoot& rRoot ) :
1184 : XclImpRoot( rRoot ),
1185 : maDataOrientField( *this, EXC_SXIVD_DATA ),
1186 4 : mpDPObj(NULL)
1187 : {
1188 4 : }
1189 :
1190 8 : XclImpPivotTable::~XclImpPivotTable()
1191 : {
1192 8 : }
1193 :
1194 : // cache/field access, misc. --------------------------------------------------
1195 :
1196 12 : sal_uInt16 XclImpPivotTable::GetFieldCount() const
1197 : {
1198 12 : return static_cast< sal_uInt16 >( maFields.size() );
1199 : }
1200 :
1201 14 : const XclImpPTField* XclImpPivotTable::GetField( sal_uInt16 nFieldIdx ) const
1202 : {
1203 : return (nFieldIdx == EXC_SXIVD_DATA) ? &maDataOrientField :
1204 14 : ((nFieldIdx < maFields.size()) ? maFields[ nFieldIdx ].get() : 0);
1205 : }
1206 :
1207 2 : XclImpPTField* XclImpPivotTable::GetFieldAcc( sal_uInt16 nFieldIdx )
1208 : {
1209 : // do not return maDataOrientField
1210 2 : return (nFieldIdx < maFields.size()) ? maFields[ nFieldIdx ].get() : 0;
1211 : }
1212 :
1213 8 : const XclImpPTField* XclImpPivotTable::GetDataField( sal_uInt16 nDataFieldIdx ) const
1214 : {
1215 8 : if( nDataFieldIdx < maOrigDataFields.size() )
1216 0 : return GetField( maOrigDataFields[ nDataFieldIdx ] );
1217 8 : return 0;
1218 : }
1219 :
1220 8 : OUString XclImpPivotTable::GetDataFieldName( sal_uInt16 nDataFieldIdx ) const
1221 : {
1222 8 : if( const XclImpPTField* pField = GetDataField( nDataFieldIdx ) )
1223 0 : return pField->GetFieldName();
1224 8 : return OUString();
1225 : }
1226 :
1227 : // records --------------------------------------------------------------------
1228 :
1229 4 : void XclImpPivotTable::ReadSxview( XclImpStream& rStrm )
1230 : {
1231 4 : rStrm >> maPTInfo;
1232 :
1233 4 : GetAddressConverter().ConvertRange(
1234 8 : maOutScRange, maPTInfo.maOutXclRange, GetCurrScTab(), GetCurrScTab(), true );
1235 :
1236 4 : mxPCache = GetPivotTableManager().GetPivotCache( maPTInfo.mnCacheIdx );
1237 4 : mxCurrField.reset();
1238 4 : }
1239 :
1240 10 : void XclImpPivotTable::ReadSxvd( XclImpStream& rStrm )
1241 : {
1242 10 : sal_uInt16 nFieldCount = GetFieldCount();
1243 10 : if( nFieldCount < EXC_PT_MAXFIELDCOUNT )
1244 : {
1245 : // cache index for the field is equal to the SXVD record index
1246 10 : mxCurrField.reset( new XclImpPTField( *this, nFieldCount ) );
1247 10 : maFields.push_back( mxCurrField );
1248 10 : mxCurrField->ReadSxvd( rStrm );
1249 : // add visible name of new field to list of visible names
1250 10 : maVisFieldNames.push_back( mxCurrField->GetVisFieldName() );
1251 : OSL_ENSURE( maFields.size() == maVisFieldNames.size(),
1252 : "XclImpPivotTable::ReadSxvd - wrong size of visible name array" );
1253 : }
1254 : else
1255 0 : mxCurrField.reset();
1256 10 : }
1257 :
1258 30 : void XclImpPivotTable::ReadSxvi( XclImpStream& rStrm )
1259 : {
1260 30 : if( mxCurrField )
1261 30 : mxCurrField->ReadSxvi( rStrm );
1262 30 : }
1263 :
1264 10 : void XclImpPivotTable::ReadSxvdex( XclImpStream& rStrm )
1265 : {
1266 10 : if( mxCurrField )
1267 10 : mxCurrField->ReadSxvdex( rStrm );
1268 10 : }
1269 :
1270 4 : void XclImpPivotTable::ReadSxivd( XclImpStream& rStrm )
1271 : {
1272 4 : mxCurrField.reset();
1273 :
1274 : // find the index vector to fill (row SXIVD doesn't exist without row fields)
1275 4 : ScfUInt16Vec* pFieldVec = 0;
1276 4 : if( maRowFields.empty() && (maPTInfo.mnRowFields > 0) )
1277 4 : pFieldVec = &maRowFields;
1278 0 : else if( maColFields.empty() && (maPTInfo.mnColFields > 0) )
1279 0 : pFieldVec = &maColFields;
1280 :
1281 : // fill the vector from record data
1282 4 : if( pFieldVec )
1283 : {
1284 4 : sal_uInt16 nSize = ulimit_cast< sal_uInt16 >( rStrm.GetRecSize() / 2, EXC_PT_MAXROWCOLCOUNT );
1285 4 : pFieldVec->reserve( nSize );
1286 12 : for( sal_uInt16 nIdx = 0; nIdx < nSize; ++nIdx )
1287 : {
1288 : sal_uInt16 nFieldIdx;
1289 8 : rStrm >> nFieldIdx;
1290 8 : pFieldVec->push_back( nFieldIdx );
1291 :
1292 : // set orientation at special data orientation field
1293 8 : if( nFieldIdx == EXC_SXIVD_DATA )
1294 : {
1295 0 : sal_uInt16 nAxis = (pFieldVec == &maRowFields) ? EXC_SXVD_AXIS_ROW : EXC_SXVD_AXIS_COL;
1296 0 : maDataOrientField.SetAxes( nAxis );
1297 : }
1298 : }
1299 : }
1300 4 : }
1301 :
1302 0 : void XclImpPivotTable::ReadSxpi( XclImpStream& rStrm )
1303 : {
1304 0 : mxCurrField.reset();
1305 :
1306 0 : sal_uInt16 nSize = ulimit_cast< sal_uInt16 >( rStrm.GetRecSize() / 6 );
1307 0 : for( sal_uInt16 nEntry = 0; nEntry < nSize; ++nEntry )
1308 : {
1309 0 : XclPTPageFieldInfo aPageInfo;
1310 0 : rStrm >> aPageInfo;
1311 0 : if( XclImpPTField* pField = GetFieldAcc( aPageInfo.mnField ) )
1312 : {
1313 0 : maPageFields.push_back( aPageInfo.mnField );
1314 0 : pField->SetPageFieldInfo( aPageInfo );
1315 : }
1316 0 : GetCurrSheetDrawing().SetSkipObj( aPageInfo.mnObjId );
1317 : }
1318 0 : }
1319 :
1320 2 : void XclImpPivotTable::ReadSxdi( XclImpStream& rStrm )
1321 : {
1322 2 : mxCurrField.reset();
1323 :
1324 2 : XclPTDataFieldInfo aDataInfo;
1325 2 : rStrm >> aDataInfo;
1326 2 : if( XclImpPTField* pField = GetFieldAcc( aDataInfo.mnField ) )
1327 : {
1328 2 : maOrigDataFields.push_back( aDataInfo.mnField );
1329 : // DataPilot does not support double data fields -> add first appearance to index list only
1330 2 : if( !pField->HasDataFieldInfo() )
1331 2 : maFiltDataFields.push_back( aDataInfo.mnField );
1332 2 : pField->AddDataFieldInfo( aDataInfo );
1333 2 : }
1334 2 : }
1335 :
1336 4 : void XclImpPivotTable::ReadSxex( XclImpStream& rStrm )
1337 : {
1338 4 : rStrm >> maPTExtInfo;
1339 4 : }
1340 :
1341 4 : void XclImpPivotTable::ReadSxViewEx9( XclImpStream& rStrm )
1342 : {
1343 4 : rStrm >> maPTViewEx9Info;
1344 4 : }
1345 :
1346 4 : void XclImpPivotTable::Convert()
1347 : {
1348 4 : if( !mxPCache || !mxPCache->IsValid() )
1349 6 : return;
1350 :
1351 2 : ScDPSaveData aSaveData;
1352 :
1353 : // *** global settings ***
1354 :
1355 2 : aSaveData.SetRowGrand( ::get_flag( maPTInfo.mnFlags, EXC_SXVIEW_ROWGRAND ) );
1356 2 : aSaveData.SetColumnGrand( ::get_flag( maPTInfo.mnFlags, EXC_SXVIEW_COLGRAND ) );
1357 2 : aSaveData.SetFilterButton( false );
1358 2 : aSaveData.SetDrillDown( ::get_flag( maPTExtInfo.mnFlags, EXC_SXEX_DRILLDOWN ) );
1359 :
1360 : // *** fields ***
1361 :
1362 2 : ScfUInt16Vec::const_iterator aIt, aEnd;
1363 :
1364 : // row fields
1365 6 : for( aIt = maRowFields.begin(), aEnd = maRowFields.end(); aIt != aEnd; ++aIt )
1366 4 : if( const XclImpPTField* pField = GetField( *aIt ) )
1367 4 : pField->ConvertRowColField( aSaveData );
1368 :
1369 : // column fields
1370 2 : for( aIt = maColFields.begin(), aEnd = maColFields.end(); aIt != aEnd; ++aIt )
1371 0 : if( const XclImpPTField* pField = GetField( *aIt ) )
1372 0 : pField->ConvertRowColField( aSaveData );
1373 :
1374 : // page fields
1375 2 : for( aIt = maPageFields.begin(), aEnd = maPageFields.end(); aIt != aEnd; ++aIt )
1376 0 : if( const XclImpPTField* pField = GetField( *aIt ) )
1377 0 : pField->ConvertPageField( aSaveData );
1378 :
1379 : // We need to import hidden fields because hidden fields may contain
1380 : // special settings for subtotals (aggregation function, filters, custom
1381 : // name etc.) and members (hidden, custom name etc.).
1382 :
1383 : // hidden fields
1384 8 : for( sal_uInt16 nField = 0, nCount = GetFieldCount(); nField < nCount; ++nField )
1385 6 : if( const XclImpPTField* pField = GetField( nField ) )
1386 6 : if (!pField->GetAxes())
1387 0 : pField->ConvertHiddenField( aSaveData );
1388 :
1389 : // data fields
1390 4 : for( aIt = maFiltDataFields.begin(), aEnd = maFiltDataFields.end(); aIt != aEnd; ++aIt )
1391 2 : if( const XclImpPTField* pField = GetField( *aIt ) )
1392 2 : pField->ConvertDataField( aSaveData );
1393 :
1394 : // *** insert into Calc document ***
1395 :
1396 : // create source descriptor
1397 4 : ScSheetSourceDesc aDesc(GetDocPtr());
1398 2 : const OUString& rSrcName = mxPCache->GetSourceRangeName();
1399 2 : if (!rSrcName.isEmpty())
1400 : // Range name is the data source.
1401 0 : aDesc.SetRangeName(rSrcName);
1402 : else
1403 : // Normal cell range.
1404 2 : aDesc.SetSourceRange(mxPCache->GetSourceRange());
1405 :
1406 : // adjust output range to include the page fields
1407 2 : ScRange aOutRange( maOutScRange );
1408 2 : if( !maPageFields.empty() )
1409 : {
1410 0 : SCsROW nDecRows = ::std::min< SCsROW >( aOutRange.aStart.Row(), maPageFields.size() + 1 );
1411 0 : aOutRange.aStart.IncRow( -nDecRows );
1412 : }
1413 :
1414 : // create the DataPilot
1415 2 : ScDPObject* pDPObj = new ScDPObject( GetDocPtr() );
1416 2 : pDPObj->SetName( maPTInfo.maTableName );
1417 2 : if (!maPTInfo.maDataName.isEmpty())
1418 2 : aSaveData.GetDataLayoutDimension()->SetLayoutName(maPTInfo.maDataName);
1419 :
1420 2 : if (!maPTViewEx9Info.maGrandTotalName.isEmpty())
1421 0 : aSaveData.SetGrandTotalName(maPTViewEx9Info.maGrandTotalName);
1422 :
1423 2 : pDPObj->SetSaveData( aSaveData );
1424 2 : pDPObj->SetSheetDesc( aDesc );
1425 2 : pDPObj->SetOutRange( aOutRange );
1426 2 : pDPObj->SetHeaderLayout( maPTViewEx9Info.mnGridLayout == 0 );
1427 :
1428 2 : GetDoc().GetDPCollection()->InsertNewTable(pDPObj);
1429 2 : mpDPObj = pDPObj;
1430 :
1431 4 : ApplyMergeFlags(aOutRange, aSaveData);
1432 : }
1433 :
1434 4 : void XclImpPivotTable::MaybeRefresh()
1435 : {
1436 4 : if (mpDPObj && mxPCache->IsRefreshOnLoad())
1437 : {
1438 : // 'refresh table on load' flag is set. Refresh the table now. Some
1439 : // Excel files contain partial table output when this flag is set.
1440 0 : ScRange aOutRange = mpDPObj->GetOutRange();
1441 0 : mpDPObj->Output(aOutRange.aStart);
1442 : }
1443 4 : }
1444 :
1445 2 : void XclImpPivotTable::ApplyMergeFlags(const ScRange& rOutRange, const ScDPSaveData& rSaveData)
1446 : {
1447 : // Apply merge flags for varoius datapilot controls.
1448 :
1449 2 : ScDPOutputGeometry aGeometry(rOutRange, false);
1450 2 : aGeometry.setColumnFieldCount(maPTInfo.mnColFields);
1451 2 : aGeometry.setPageFieldCount(maPTInfo.mnPageFields);
1452 2 : aGeometry.setDataFieldCount(maPTInfo.mnDataFields);
1453 2 : aGeometry.setRowFieldCount(maPTInfo.mnRowFields);
1454 :
1455 2 : ScDocument& rDoc = GetDoc();
1456 :
1457 4 : vector<const ScDPSaveDimension*> aFieldDims;
1458 4 : vector<ScAddress> aFieldBtns;
1459 :
1460 2 : aGeometry.getPageFieldPositions(aFieldBtns);
1461 2 : vector<ScAddress>::const_iterator itr = aFieldBtns.begin(), itrEnd = aFieldBtns.end();
1462 2 : for (; itr != itrEnd; ++itr)
1463 : {
1464 0 : rDoc.ApplyFlagsTab(itr->Col(), itr->Row(), itr->Col(), itr->Row(), itr->Tab(), SC_MF_BUTTON);
1465 :
1466 0 : sal_uInt16 nMFlag = SC_MF_BUTTON_POPUP;
1467 0 : OUString aName = rDoc.GetString(itr->Col(), itr->Row(), itr->Tab());
1468 0 : if (rSaveData.HasInvisibleMember(aName))
1469 0 : nMFlag |= SC_MF_HIDDEN_MEMBER;
1470 :
1471 0 : rDoc.ApplyFlagsTab(itr->Col()+1, itr->Row(), itr->Col()+1, itr->Row(), itr->Tab(), nMFlag);
1472 0 : }
1473 :
1474 2 : aGeometry.getColumnFieldPositions(aFieldBtns);
1475 2 : rSaveData.GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_COLUMN, aFieldDims);
1476 2 : if (aFieldBtns.size() == aFieldDims.size())
1477 : {
1478 2 : itr = aFieldBtns.begin();
1479 2 : itrEnd = aFieldBtns.end();
1480 2 : vector<const ScDPSaveDimension*>::const_iterator itDim = aFieldDims.begin();
1481 2 : for (; itr != itrEnd; ++itr, ++itDim)
1482 : {
1483 0 : sal_Int16 nMFlag = SC_MF_BUTTON;
1484 0 : const ScDPSaveDimension* pDim = *itDim;
1485 0 : if (pDim->HasInvisibleMember())
1486 0 : nMFlag |= SC_MF_HIDDEN_MEMBER;
1487 0 : if (!pDim->IsDataLayout())
1488 0 : nMFlag |= SC_MF_BUTTON_POPUP;
1489 0 : rDoc.ApplyFlagsTab(itr->Col(), itr->Row(), itr->Col(), itr->Row(), itr->Tab(), nMFlag);
1490 : }
1491 : }
1492 :
1493 2 : aGeometry.getRowFieldPositions(aFieldBtns);
1494 2 : rSaveData.GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_ROW, aFieldDims);
1495 2 : if (aFieldBtns.size() == aFieldDims.size())
1496 : {
1497 2 : itr = aFieldBtns.begin();
1498 2 : itrEnd = aFieldBtns.end();
1499 2 : vector<const ScDPSaveDimension*>::const_iterator itDim = aFieldDims.begin();
1500 6 : for (; itr != itrEnd; ++itr, ++itDim)
1501 : {
1502 4 : sal_Int16 nMFlag = SC_MF_BUTTON;
1503 4 : const ScDPSaveDimension* pDim = *itDim;
1504 4 : if (pDim->HasInvisibleMember())
1505 0 : nMFlag |= SC_MF_HIDDEN_MEMBER;
1506 4 : if (!pDim->IsDataLayout())
1507 4 : nMFlag |= SC_MF_BUTTON_POPUP;
1508 4 : rDoc.ApplyFlagsTab(itr->Col(), itr->Row(), itr->Col(), itr->Row(), itr->Tab(), nMFlag);
1509 : }
1510 2 : }
1511 2 : }
1512 :
1513 142 : XclImpPivotTableManager::XclImpPivotTableManager( const XclImpRoot& rRoot ) :
1514 142 : XclImpRoot( rRoot )
1515 : {
1516 142 : }
1517 :
1518 284 : XclImpPivotTableManager::~XclImpPivotTableManager()
1519 : {
1520 284 : }
1521 :
1522 : // pivot cache records --------------------------------------------------------
1523 :
1524 4 : XclImpPivotCacheRef XclImpPivotTableManager::GetPivotCache( sal_uInt16 nCacheIdx )
1525 : {
1526 4 : XclImpPivotCacheRef xPCache;
1527 4 : if( nCacheIdx < maPCaches.size() )
1528 2 : xPCache = maPCaches[ nCacheIdx ];
1529 4 : return xPCache;
1530 : }
1531 :
1532 4 : void XclImpPivotTableManager::ReadSxidstm( XclImpStream& rStrm )
1533 : {
1534 4 : XclImpPivotCacheRef xPCache( new XclImpPivotCache( GetRoot() ) );
1535 4 : maPCaches.push_back( xPCache );
1536 4 : xPCache->ReadSxidstm( rStrm );
1537 4 : }
1538 :
1539 4 : void XclImpPivotTableManager::ReadSxvs( XclImpStream& rStrm )
1540 : {
1541 4 : if( !maPCaches.empty() )
1542 4 : maPCaches.back()->ReadSxvs( rStrm );
1543 4 : }
1544 :
1545 4 : void XclImpPivotTableManager::ReadDconref( XclImpStream& rStrm )
1546 : {
1547 4 : if( !maPCaches.empty() )
1548 4 : maPCaches.back()->ReadDconref( rStrm );
1549 4 : }
1550 :
1551 0 : void XclImpPivotTableManager::ReadDConName( XclImpStream& rStrm )
1552 : {
1553 0 : if( !maPCaches.empty() )
1554 0 : maPCaches.back()->ReadDConName( rStrm );
1555 0 : }
1556 :
1557 : // pivot table records --------------------------------------------------------
1558 :
1559 4 : void XclImpPivotTableManager::ReadSxview( XclImpStream& rStrm )
1560 : {
1561 4 : XclImpPivotTableRef xPTable( new XclImpPivotTable( GetRoot() ) );
1562 4 : maPTables.push_back( xPTable );
1563 4 : xPTable->ReadSxview( rStrm );
1564 4 : }
1565 :
1566 10 : void XclImpPivotTableManager::ReadSxvd( XclImpStream& rStrm )
1567 : {
1568 10 : if( !maPTables.empty() )
1569 10 : maPTables.back()->ReadSxvd( rStrm );
1570 10 : }
1571 :
1572 10 : void XclImpPivotTableManager::ReadSxvdex( XclImpStream& rStrm )
1573 : {
1574 10 : if( !maPTables.empty() )
1575 10 : maPTables.back()->ReadSxvdex( rStrm );
1576 10 : }
1577 :
1578 4 : void XclImpPivotTableManager::ReadSxivd( XclImpStream& rStrm )
1579 : {
1580 4 : if( !maPTables.empty() )
1581 4 : maPTables.back()->ReadSxivd( rStrm );
1582 4 : }
1583 :
1584 0 : void XclImpPivotTableManager::ReadSxpi( XclImpStream& rStrm )
1585 : {
1586 0 : if( !maPTables.empty() )
1587 0 : maPTables.back()->ReadSxpi( rStrm );
1588 0 : }
1589 :
1590 2 : void XclImpPivotTableManager::ReadSxdi( XclImpStream& rStrm )
1591 : {
1592 2 : if( !maPTables.empty() )
1593 2 : maPTables.back()->ReadSxdi( rStrm );
1594 2 : }
1595 :
1596 30 : void XclImpPivotTableManager::ReadSxvi( XclImpStream& rStrm )
1597 : {
1598 30 : if( !maPTables.empty() )
1599 30 : maPTables.back()->ReadSxvi( rStrm );
1600 30 : }
1601 :
1602 4 : void XclImpPivotTableManager::ReadSxex( XclImpStream& rStrm )
1603 : {
1604 4 : if( !maPTables.empty() )
1605 4 : maPTables.back()->ReadSxex( rStrm );
1606 4 : }
1607 :
1608 4 : void XclImpPivotTableManager::ReadSxViewEx9( XclImpStream& rStrm )
1609 : {
1610 4 : if( !maPTables.empty() )
1611 4 : maPTables.back()->ReadSxViewEx9( rStrm );
1612 4 : }
1613 :
1614 140 : void XclImpPivotTableManager::ReadPivotCaches( XclImpStream& rStrm )
1615 : {
1616 144 : for( XclImpPivotCacheVec::iterator aIt = maPCaches.begin(), aEnd = maPCaches.end(); aIt != aEnd; ++aIt )
1617 4 : (*aIt)->ReadPivotCacheStream( rStrm );
1618 140 : }
1619 :
1620 142 : void XclImpPivotTableManager::ConvertPivotTables()
1621 : {
1622 146 : for( XclImpPivotTableVec::iterator aIt = maPTables.begin(), aEnd = maPTables.end(); aIt != aEnd; ++aIt )
1623 4 : (*aIt)->Convert();
1624 142 : }
1625 :
1626 142 : void XclImpPivotTableManager::MaybeRefreshPivotTables()
1627 : {
1628 146 : for( XclImpPivotTableVec::iterator aIt = maPTables.begin(), aEnd = maPTables.end(); aIt != aEnd; ++aIt )
1629 4 : (*aIt)->MaybeRefresh();
1630 190 : }
1631 :
1632 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|