1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: pivot2.cxx,v $
10 * $Revision: 1.14.32.3 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
37 #pragma optimize("",off)
40 // INCLUDE ---------------------------------------------------------------
42 #include "scitems.hxx"
43 #include <svx/boxitem.hxx>
44 #include <svx/wghtitem.hxx>
45 #include <svx/algitem.hxx>
46 #include <unotools/transliterationwrapper.hxx>
48 #include "globstr.hrc"
49 #include "subtotal.hxx"
50 #include "rangeutl.hxx"
52 #include "patattr.hxx"
53 #include "docpool.hxx"
54 #include "document.hxx"
55 #include "userlist.hxx"
57 #include "rechead.hxx"
58 #include "formula/errorcodes.hxx" // fuer errNoValue
59 #include "refupdat.hxx"
60 #include "stlpool.hxx"
61 #include "stlsheet.hxx"
63 using ::com::sun::star::sheet::DataPilotFieldReference
;
65 // STATIC DATA -----------------------------------------------------------
67 #if OLD_PIVOT_IMPLEMENTATION
68 //--------------------------------------------------------------------------------------------------
69 // Hilfsmethoden von ScPivot
70 //--------------------------------------------------------------------------------------------------
72 void ScPivot::SetFrame(SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
, USHORT nWidth
)
74 if (pDoc
->pTab
[nDestTab
])
77 aLine
.SetOutWidth(nWidth
);
78 SvxBoxItem
aBox( ATTR_BORDER
);
79 aBox
.SetLine(&aLine
, BOX_LINE_LEFT
);
80 aBox
.SetLine(&aLine
, BOX_LINE_TOP
);
81 aBox
.SetLine(&aLine
, BOX_LINE_RIGHT
);
82 aBox
.SetLine(&aLine
, BOX_LINE_BOTTOM
);
83 SvxBoxInfoItem
aBoxInfo( ATTR_BORDER_INNER
);
84 aBoxInfo
.SetValid(VALID_HORI
,FALSE
);
85 aBoxInfo
.SetValid(VALID_VERT
,FALSE
);
86 aBoxInfo
.SetValid(VALID_DISTANCE
,FALSE
);
87 pDoc
->pTab
[nDestTab
]->ApplyBlockFrame(&aBox
, &aBoxInfo
, nCol1
, nRow1
, nCol2
, nRow2
);
91 void ScPivot::SetFrameHor(SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
)
93 if (pDoc
->pTab
[nDestTab
])
96 aLine
.SetOutWidth(20);
97 SvxBoxItem
aBox( ATTR_BORDER
);
98 aBox
.SetLine(&aLine
, BOX_LINE_LEFT
);
99 aBox
.SetLine(&aLine
, BOX_LINE_TOP
);
100 aBox
.SetLine(&aLine
, BOX_LINE_RIGHT
);
101 aBox
.SetLine(&aLine
, BOX_LINE_BOTTOM
);
102 SvxBoxInfoItem
aBoxInfo(ATTR_BORDER_INNER
);
103 aBoxInfo
.SetValid(VALID_VERT
,FALSE
);
104 aBoxInfo
.SetValid(VALID_DISTANCE
,FALSE
);
105 aBoxInfo
.SetLine(&aLine
, BOXINFO_LINE_HORI
);
106 pDoc
->pTab
[nDestTab
]->ApplyBlockFrame(&aBox
, &aBoxInfo
, nCol1
, nRow1
, nCol2
, nRow2
);
110 void ScPivot::SetFrameVer(SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
)
112 if (pDoc
->pTab
[nDestTab
])
115 aLine
.SetOutWidth(20);
116 SvxBoxItem
aBox( ATTR_BORDER
);
117 aBox
.SetLine(&aLine
, BOX_LINE_LEFT
);
118 aBox
.SetLine(&aLine
, BOX_LINE_TOP
);
119 aBox
.SetLine(&aLine
, BOX_LINE_RIGHT
);
120 aBox
.SetLine(&aLine
, BOX_LINE_BOTTOM
);
121 SvxBoxInfoItem
aBoxInfo( ATTR_BORDER_INNER
);
122 aBoxInfo
.SetValid(VALID_HORI
,FALSE
);
123 aBoxInfo
.SetValid(VALID_DISTANCE
,FALSE
);
124 aBoxInfo
.SetLine(&aLine
, BOXINFO_LINE_VERT
);
125 pDoc
->pTab
[nDestTab
]->ApplyBlockFrame(&aBox
, &aBoxInfo
, nCol1
, nRow1
, nCol2
, nRow2
);
129 void ScPivot::SetFontBold(SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
)
131 if (pDoc
->pTab
[nDestTab
])
133 ScPatternAttr
aPattern( pDoc
->GetPool() );
134 aPattern
.GetItemSet().Put( SvxWeightItem( WEIGHT_BOLD
, ATTR_FONT_WEIGHT
) );
135 pDoc
->pTab
[nDestTab
]->ApplyPatternArea(nCol1
, nRow1
, nCol2
, nRow2
, aPattern
);
139 void ScPivot::SetJustifyLeft(SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
)
141 if (pDoc
->pTab
[nDestTab
])
143 ScPatternAttr
aPattern( pDoc
->GetPool() );
144 aPattern
.GetItemSet().Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_LEFT
, ATTR_HOR_JUSTIFY
) );
145 pDoc
->pTab
[nDestTab
]->ApplyPatternArea(nCol1
, nRow1
, nCol2
, nRow2
, aPattern
);
149 void ScPivot::SetJustifyRight(SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
)
151 if (pDoc
->pTab
[nDestTab
])
153 ScPatternAttr
aPattern( pDoc
->GetPool() );
154 aPattern
.GetItemSet().Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_RIGHT
, ATTR_HOR_JUSTIFY
) );
155 pDoc
->pTab
[nDestTab
]->ApplyPatternArea(nCol1
, nRow1
, nCol2
, nRow2
, aPattern
);
159 void ScPivot::SetButton(SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
)
161 pDoc
->ApplyFlagsTab(nCol1
, nRow1
, nCol2
, nRow2
, nDestTab
, SC_MF_BUTTON
);
164 void ScPivot::SetStyle(SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
, USHORT nId
)
166 if ( nCol1
> nCol2
|| nRow1
> nRow2
)
167 return; // Falls Bereiche leer sind
169 USHORT nStringId
= 0;
172 case PIVOT_STYLE_INNER
: nStringId
= STR_PIVOT_STYLE_INNER
; break;
173 case PIVOT_STYLE_RESULT
: nStringId
= STR_PIVOT_STYLE_RESULT
; break;
174 case PIVOT_STYLE_CATEGORY
: nStringId
= STR_PIVOT_STYLE_CATEGORY
; break;
175 case PIVOT_STYLE_TITLE
: nStringId
= STR_PIVOT_STYLE_TITLE
; break;
176 case PIVOT_STYLE_FIELDNAME
: nStringId
= STR_PIVOT_STYLE_FIELDNAME
; break;
177 case PIVOT_STYLE_TOP
: nStringId
= STR_PIVOT_STYLE_TOP
; break;
179 DBG_ERROR("falsche ID bei ScPivot::SetStyle");
182 String aStyleName
= ScGlobal::GetRscString(nStringId
);
184 ScStyleSheetPool
* pStlPool
= pDoc
->GetStyleSheetPool();
185 ScStyleSheet
* pStyle
= (ScStyleSheet
*) pStlPool
->Find( aStyleName
, SFX_STYLE_FAMILY_PARA
);
190 pStyle
= (ScStyleSheet
*) &pStlPool
->Make( aStyleName
, SFX_STYLE_FAMILY_PARA
,
191 SFXSTYLEBIT_USERDEF
);
192 pStyle
->SetParent( ScGlobal::GetRscString(STR_STYLENAME_STANDARD
) );
193 SfxItemSet
& rSet
= pStyle
->GetItemSet();
194 if ( nId
==PIVOT_STYLE_RESULT
|| nId
==PIVOT_STYLE_TITLE
)
195 rSet
.Put( SvxWeightItem( WEIGHT_BOLD
, ATTR_FONT_WEIGHT
) );
196 if ( nId
==PIVOT_STYLE_CATEGORY
|| nId
==PIVOT_STYLE_TITLE
)
197 rSet
.Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_LEFT
, ATTR_HOR_JUSTIFY
) );
200 pDoc
->pTab
[nDestTab
]->ApplyStyleArea( nCol1
, nRow1
, nCol2
, nRow2
, *pStyle
);
203 void ScPivot::SetValue(SCCOL nCol
, SCROW nRow
, const SubTotal
& rTotal
, USHORT nFunc
)
205 if ( rTotal
.Valid( nFunc
) == 1)
206 pDoc
->SetValue(nCol
, nRow
, nDestTab
, rTotal
.Result( nFunc
));
207 else if ( rTotal
.Valid( nFunc
) == 0)
208 pDoc
->SetError(nCol
, nRow
, nDestTab
, errNoValue
);
211 //--------------------------------------------------------------------------------------------------
213 void ScPivot::GetParam( ScPivotParam
& rParam
, ScQueryParam
& rQuery
, ScArea
& rSrcArea
) const
218 GetDestArea( rParam
.nCol
,rParam
.nRow
, nDummyCol
,nDummyRow
, rParam
.nTab
);
220 // Row und Col in der Bedeutung vertauscht:
221 GetRowFields( rParam
.aColArr
, nCount
);
222 rParam
.nColCount
= nCount
;
223 GetColFields( rParam
.aRowArr
, nCount
);
224 rParam
.nRowCount
= nCount
;
225 GetDataFields( rParam
.aDataArr
, nCount
);
226 rParam
.nDataCount
= nCount
;
228 rParam
.bIgnoreEmptyRows
= GetIgnoreEmpty();
229 rParam
.bDetectCategories
= GetDetectCat();
230 rParam
.bMakeTotalCol
= GetMakeTotalCol();
231 rParam
.bMakeTotalRow
= GetMakeTotalRow();
234 GetSrcArea( rSrcArea
.nColStart
, rSrcArea
.nRowStart
,
235 rSrcArea
.nColEnd
, rSrcArea
.nRowEnd
, rSrcArea
.nTab
);
238 void ScPivot::SetParam( const ScPivotParam
& rParam
, const ScQueryParam
& rQuery
,
239 const ScArea
& rSrcArea
)
243 SetSrcArea( rSrcArea
.nColStart
, rSrcArea
.nRowStart
,
244 rSrcArea
.nColEnd
, rSrcArea
.nRowEnd
, rSrcArea
.nTab
);
245 SetDestPos( rParam
.nCol
, rParam
.nRow
, rParam
.nTab
);
246 SetIgnoreEmpty( rParam
.bIgnoreEmptyRows
);
247 SetDetectCat( rParam
.bDetectCategories
);
248 SetMakeTotalCol( rParam
.bMakeTotalCol
);
249 SetMakeTotalRow( rParam
.bMakeTotalRow
);
251 // Row und Col in der Bedeutung vertauscht:
252 SetRowFields( rParam
.aColArr
, rParam
.nColCount
);
253 SetColFields( rParam
.aRowArr
, rParam
.nRowCount
);
254 SetDataFields( rParam
.aDataArr
, rParam
.nDataCount
);
257 ScDataObject
* ScPivot::Clone() const
259 return new ScPivot(*this);
262 //--------------------------------------------------------------------------------------------------
263 // PivotScStrCollection
264 //--------------------------------------------------------------------------------------------------
266 ScDataObject
* PivotScStrCollection::Clone() const
268 return new PivotScStrCollection(*this);
271 short PivotScStrCollection::Compare(ScDataObject
* pKey1
, ScDataObject
* pKey2
) const
273 DBG_ASSERT(pKey1
&&pKey2
,"0-Zeiger bei PivotScStrCollection::Compare");
277 TypedStrData
& rData1
= (TypedStrData
&)*pKey1
;
278 TypedStrData
& rData2
= (TypedStrData
&)*pKey2
;
280 if ( rData1
.nStrType
> rData2
.nStrType
)
282 else if ( rData1
.nStrType
< rData2
.nStrType
)
284 else if ( !rData1
.nStrType
/* && !rData2.nStrType */ )
286 // Zahlen vergleichen:
288 if ( rData1
.nValue
== rData2
.nValue
)
290 else if ( rData1
.nValue
< rData2
.nValue
)
295 else /* if ( rData1.nStrType && rData2.nStrType ) */
297 // Strings vergleichen:
300 nResult
= sal::static_int_cast
<short>(pUserData
->ICompare(rData1
.aStrValue
, rData2
.aStrValue
));
303 nResult
= (short) ScGlobal::pTransliteration
->compareString(
304 rData1
.aStrValue
, rData2
.aStrValue
);
311 USHORT
PivotScStrCollection::GetIndex(TypedStrData
* pData
) const
314 if (!Search(pData
, nIndex
))
319 //--------------------------------------------------------------------------------------------------
321 //--------------------------------------------------------------------------------------------------
323 String
ScPivotCollection::CreateNewName( USHORT nMin
) const
325 String
aBase( RTL_CONSTASCII_USTRINGPARAM("DataPilot") );
328 for (USHORT nAdd
=0; nAdd
<=nCount
; nAdd
++) // nCount+1 Versuche
330 String aNewName
= aBase
;
331 aNewName
+= String::CreateFromInt32( nMin
+ nAdd
);
333 for (USHORT i
=0; i
<nCount
&& !bFound
; i
++)
334 if (((ScPivot
*)pItems
[i
])->GetName() == aNewName
)
337 return aNewName
; // freien Namen gefunden
339 return String(); // sollte nicht vorkommen
342 ScPivot
* ScPivotCollection::GetPivotAtCursor(SCCOL nCol
, SCROW nRow
, SCTAB nTab
) const
346 for (USHORT i
= 0; i
< nCount
; i
++)
347 if (((ScPivot
*)pItems
[i
])->IsPivotAtCursor(nCol
, nRow
, nTab
))
349 return (ScPivot
*)pItems
[i
];
355 BOOL
ScPivotCollection::Load(SvStream
& rStream
)
357 BOOL bSuccess
= TRUE
;
361 ScMultipleReadHeader
aHdr( rStream
);
363 rStream
>> nNewCount
;
364 for (i
=0; i
<nNewCount
&& bSuccess
; i
++)
366 ScPivot
* pPivot
= new ScPivot( pDoc
);
369 bSuccess
= pPivot
->Load(rStream
, aHdr
);
376 // fuer alte Dateien: eindeutige Namen vergeben
379 for (i
=0; i
<nCount
; i
++)
380 if (!((const ScPivot
*)At(i
))->GetName().Len())
381 ((ScPivot
*)At(i
))->SetName( CreateNewName() );
386 BOOL
ScPivotCollection::Store(SvStream
& rStream
) const
388 BOOL bSuccess
= TRUE
;
390 ScMultipleWriteHeader
aHdr( rStream
);
394 for (USHORT i
=0; i
<nCount
&& bSuccess
; i
++)
395 bSuccess
= ((const ScPivot
*)At(i
))->Store( rStream
, aHdr
);
400 void ScPivotCollection::UpdateReference(UpdateRefMode eUpdateRefMode
,
401 SCCOL nCol1
, SCROW nRow1
, SCTAB nTab1
,
402 SCCOL nCol2
, SCROW nRow2
, SCTAB nTab2
,
403 SCsCOL nDx
, SCsROW nDy
, SCsTAB nDz
)
405 for (USHORT i
=0; i
<nCount
; i
++)
414 ScPivot
* pPivot
= (ScPivot
*)pItems
[i
];
418 pPivot
->GetSrcArea( theCol1
, theRow1
, theCol2
, theRow2
, theTab1
);
421 eRes
= ScRefUpdate::Update( pDoc
, eUpdateRefMode
,
422 nCol1
,nRow1
,nTab1
, nCol2
,nRow2
,nTab2
, nDx
,nDy
,nDz
,
423 theCol1
,theRow1
,theTab1
, theCol2
,theRow2
,theTab2
);
425 if (eRes
!= UR_NOTHING
)
426 pPivot
->MoveSrcArea( theCol1
, theRow1
, theTab1
);
430 pPivot
->GetDestArea( theCol1
, theRow1
, theCol2
, theRow2
, theTab1
);
433 eRes
= ScRefUpdate::Update( pDoc
, eUpdateRefMode
,
434 nCol1
,nRow1
,nTab1
, nCol2
,nRow2
,nTab2
, nDx
,nDy
,nDz
,
435 theCol1
,theRow1
,theTab1
, theCol2
,theRow2
,theTab2
);
437 if (eRes
!= UR_NOTHING
)
438 pPivot
->MoveDestArea( theCol1
, theRow1
, theTab1
);
442 void ScPivotCollection::UpdateGrow( const ScRange
& rArea
, SCCOL nGrowX
, SCROW nGrowY
)
446 for (USHORT i
=0; i
<nCount
; i
++)
448 ScPivot
* pPivot
= (ScPivot
*)pItems
[i
];
449 ScRange aSrc
= pPivot
->GetSrcArea();
450 ScRefUpdateRes eRes
= ScRefUpdate::DoGrow( rArea
, nGrowX
, nGrowY
, aSrc
);
451 if (eRes
!= UR_NOTHING
)
452 pPivot
->ExtendSrcArea( aSrc
.aEnd
.Col(), aSrc
.aEnd
.Row() );
456 BOOL
ScPivotCollection::operator==(const ScPivotCollection
& rCmp
) const
458 if (nCount
!= rCmp
.nCount
)
462 return TRUE
; // beide leer - nicht erst die Param's anlegen!
464 ScPivotParam aMyParam
, aCmpParam
;
465 ScQueryParam aMyQuery
, aCmpQuery
;
466 ScArea aMyArea
, aCmpArea
;
468 for (USHORT i
=0; i
<nCount
; i
++)
470 ScPivot
* pMyPivot
= (ScPivot
*)pItems
[i
];
471 pMyPivot
->GetParam( aMyParam
, aMyQuery
, aMyArea
);
472 ScPivot
* pCmpPivot
= (ScPivot
*)rCmp
.pItems
[i
];
473 pCmpPivot
->GetParam( aCmpParam
, aCmpQuery
, aCmpArea
);
474 if (!( aMyArea
==aCmpArea
&& aMyParam
==aCmpParam
&& aMyQuery
==aCmpQuery
))
481 ScDataObject
* ScPivotCollection::Clone() const
483 return new ScPivotCollection(*this);
488 // ============================================================================
490 ScDPLabelData::ScDPLabelData( const String
& rName
, short nCol
, bool bIsValue
) :
493 mnFuncMask( PIVOT_FUNC_NONE
),
496 mbIsValue( bIsValue
)
500 // ============================================================================
502 ScDPFuncData::ScDPFuncData( short nCol
, USHORT nFuncMask
) :
504 mnFuncMask( nFuncMask
)
508 ScDPFuncData::ScDPFuncData( short nCol
, USHORT nFuncMask
, const DataPilotFieldReference
& rFieldRef
) :
510 mnFuncMask( nFuncMask
),
511 maFieldRef( rFieldRef
)
515 // ============================================================================