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