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: pivot.cxx,v $
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"
36 // -----------------------------------------------------------------------
37 #if OLD_PIVOT_IMPLEMENTATION
39 #pragma optimize("",off)
42 // INCLUDE ---------------------------------------------------------------
44 #include <svtools/zforlist.hxx>
45 #include <tools/solar.h>
47 #include "globstr.hrc"
49 #include "subtotal.hxx"
50 #include "scitems.hxx"
52 #include "patattr.hxx"
53 #include "docpool.hxx"
54 #include "document.hxx"
55 #include "userlist.hxx"
58 #include "rechead.hxx"
59 #include "compiler.hxx" // fuer errNoValue
60 #include "progress.hxx"
65 // STATIC DATA -----------------------------------------------------------
67 //! bei Gelegenheit...
69 static short nStaticStrRefCount
= 0;
70 static String
* pLabel
[PIVOT_MAXFUNC
+1]; // incl. "auto"
71 static String
* pLabelTotal
;
72 static String
* pLabelData
;
74 static SCSIZE nDataMult
= 1;
78 static const USHORT nFuncMaskArr
[PIVOT_MAXFUNC
+1] =
90 PIVOT_FUNC_AUTO
}; // automatisch
92 // -----------------------------------------------------------------------
99 // 6 einzelne "Gesamt" oben rechts
100 // 7 "Gesamt" oben rechts
101 // 8 einzelne "Gesamt" unten links
102 // 9 "Gesamt" unten links
103 // 10 innere Kategorie links
104 // 11 Teilergebnis Label einzeln links
105 // 12 Teilergebnis Label gesamt links
106 // 13 letzte Kategorie links
107 // 14 innere Kategorie oben
108 // 15 Teilergebnis Label einzeln oben
109 // 16 Teilergebnis Label gesamt oben
110 // 17 letzte Kategorie oben
112 // 19 Werte in Teilergebnisspalte
113 // 20 Werte in Gesamt-Spalte
114 // 21 Werte in einzelnen Gesamt-Spalten
115 // 22 Werte in Ergebnis-Zeile Teilergebnis oder Gesamt
116 // 23 Kreuzung von Spalte/Zeile (Teilergebnis-Spalte)
117 // 24 Kreuzung von Spalte/Zeile (Gesamt-Spalte)
118 // 25 wie 24 bei einzelnen "Gesamt"
120 SCSIZE
lcl_MaskToIndex( USHORT nFuncMask
)
123 for (i
=0; i
<=PIVOT_MAXFUNC
; i
++)
124 if (nFuncMask
== nFuncMaskArr
[i
])
127 DBG_ERROR("Falsche Maske in MaskToIndex");
131 BOOL
lcl_IsEmptyLine( ScDocument
* pDoc
, const ScAddress
& rPos
, SCCOL nCol2
)
133 //! ans Document verschieben !!!
135 ScAddress
aAdr( rPos
);
136 for (SCCOL nCol
=aAdr
.Col(); nCol
<=nCol2
; nCol
++)
139 if ( pDoc
->GetCell( aAdr
) )
145 ScPivot::ScPivot(ScDocument
* pDocument
) :
149 bIgnoreEmpty (FALSE
),
151 bMakeTotalCol (TRUE
),
152 bMakeTotalRow (TRUE
),
173 for (SCSIZE i
=0; i
<PIVOT_MAXFIELD
; i
++)
175 pColList
[i
] = new PivotScStrCollection();
176 pRowList
[i
] = new PivotScStrCollection();
178 pDataList
= pColList
[0];
185 // Initialisierung der statischen Strings, wenn noetig
186 nStaticStrRefCount
+= 1;
187 if ( nStaticStrRefCount
< 2 )
189 pLabelTotal
= new String( ScGlobal::GetRscString(STR_PIVOT_TOTAL
) );
190 pLabelData
= new String( ScGlobal::GetRscString(STR_PIVOT_DATA
) );
192 for (SCSIZE i
=0; i
<=PIVOT_MAXFUNC
; i
++ ) // incl. "auto"
193 pLabel
[i
] = new String
; // kein Leerzeichen
195 *pLabel
[ 0] = ScGlobal::GetRscString(STR_FUN_TEXT_SUM
);
196 *pLabel
[ 1] = ScGlobal::GetRscString(STR_FUN_TEXT_COUNT
);
197 *pLabel
[ 2] = ScGlobal::GetRscString(STR_FUN_TEXT_AVG
);
198 *pLabel
[ 3] = ScGlobal::GetRscString(STR_FUN_TEXT_MAX
);
199 *pLabel
[ 4] = ScGlobal::GetRscString(STR_FUN_TEXT_MIN
);
200 *pLabel
[ 5] = ScGlobal::GetRscString(STR_FUN_TEXT_PRODUCT
);
201 *pLabel
[ 6] = ScGlobal::GetRscString(STR_FUN_TEXT_COUNT
); // Count2
202 *pLabel
[ 7] = ScGlobal::GetRscString(STR_FUN_TEXT_STDDEV
);
203 *pLabel
[ 8] = ScGlobal::GetRscString(STR_FUN_TEXT_STDDEV
); // Stddev2
204 *pLabel
[ 9] = ScGlobal::GetRscString(STR_FUN_TEXT_VAR
);
205 *pLabel
[10] = ScGlobal::GetRscString(STR_FUN_TEXT_VAR
); // Var2
206 *pLabel
[11] = ScGlobal::GetRscString(STR_TABLE_ERGEBNIS
);
210 ScPivot::ScPivot(const ScPivot
& rPivot
):
213 aQuery (rPivot
.aQuery
),
214 bHasHeader (rPivot
.bHasHeader
),
215 bIgnoreEmpty (rPivot
.bIgnoreEmpty
),
216 bDetectCat (rPivot
.bDetectCat
),
217 bMakeTotalCol (rPivot
.bMakeTotalCol
),
218 bMakeTotalRow (rPivot
.bMakeTotalRow
),
219 aName (rPivot
.aName
),
223 nSrcCol1 (rPivot
.nSrcCol1
),
224 nSrcRow1 (rPivot
.nSrcRow1
),
225 nSrcCol2 (rPivot
.nSrcCol2
),
226 nSrcRow2 (rPivot
.nSrcRow2
),
227 nSrcTab (rPivot
.nSrcTab
),
228 nDestCol1 (rPivot
.nDestCol1
),
229 nDestRow1 (rPivot
.nDestRow1
),
230 nDestCol2 (rPivot
.nDestCol2
),
231 nDestRow2 (rPivot
.nDestRow2
),
232 nDestTab (rPivot
.nDestTab
),
241 if (rPivot
.nColNameCount
>0 && rPivot
.pColNames
)
243 nColNameCount
= rPivot
.nColNameCount
;
244 pColNames
= new String
[nColNameCount
];
245 for (SCSIZE nCol
=0; nCol
<nColNameCount
; nCol
++)
246 pColNames
[nCol
] = rPivot
.pColNames
[nCol
];
249 for (SCSIZE i
=0; i
<PIVOT_MAXFIELD
; i
++)
251 pColList
[i
] = new PivotScStrCollection();
252 pRowList
[i
] = new PivotScStrCollection();
254 pDataList
= pColList
[0];
259 SetColFields( rPivot
.aColArr
, rPivot
.nColCount
);
260 SetRowFields( rPivot
.aRowArr
, rPivot
.nRowCount
);
261 SetDataFields( rPivot
.aDataArr
, rPivot
.nDataCount
);
263 nStaticStrRefCount
+= 1;
268 for (SCSIZE i
=0; i
<PIVOT_MAXFIELD
; i
++)
275 for (SCSIZE j
=0; j
<nDataRowCount
; j
++)
276 delete[] ppDataArr
[j
];
284 // statische Strings ggF. wieder abraeumen
285 nStaticStrRefCount
-= 1;
286 if ( nStaticStrRefCount
== 0 )
291 for ( SCSIZE k
=0; k
<=PIVOT_MAXFUNC
; k
++ ) // incl. "auto"
296 ScPivot
* ScPivot::CreateNew() const
298 ScPivot
* pNewPivot
= new ScPivot( pDoc
);
300 pNewPivot
->SetQuery(aQuery
);
301 pNewPivot
->SetHeader(bHasHeader
);
302 pNewPivot
->SetIgnoreEmpty(bIgnoreEmpty
);
303 pNewPivot
->SetDetectCat(bDetectCat
);
304 pNewPivot
->SetMakeTotalCol(bMakeTotalCol
);
305 pNewPivot
->SetMakeTotalRow(bMakeTotalRow
);
307 pNewPivot
->SetSrcArea( nSrcCol1
, nSrcRow1
, nSrcCol2
, nSrcRow2
, nSrcTab
);
308 pNewPivot
->SetDestPos( nDestCol1
, nDestRow1
, nDestTab
);
313 void lcl_LoadFieldArr30( SvStream
& /* rStream */, PivotField
* /* pField */, USHORT
/* nCount */ )
315 #if SC_ROWLIMIT_STREAM_ACCESS
316 #error address types changed!
319 for (i
=0; i
<nCount
; i
++)
321 rStream
>> pField
[i
].nCol
322 >> pField
[i
].nFuncMask
323 >> pField
[i
].nFuncCount
;
328 void lcl_LoadFieldArr( SvStream
& /* rStream */, PivotField
* /* pField */, USHORT
/* nCount */ )
330 #if SC_ROWLIMIT_STREAM_ACCESS
331 #error address types changed!
334 for (i
=0; i
<nCount
; i
++)
339 rStream
.SeekRel( cData
& 0x0F );
340 rStream
>> pField
[i
].nCol
341 >> pField
[i
].nFuncMask
342 >> pField
[i
].nFuncCount
;
347 void lcl_SaveFieldArr( SvStream
& /* rStream */, const PivotField
* /* pField */, USHORT
/* nCount */ )
349 #if SC_ROWLIMIT_STREAM_ACCESS
350 #error address types changed!
353 for (i
=0; i
<nCount
; i
++)
355 rStream
<< (BYTE
) 0x00
357 << pField
[i
].nFuncMask
358 << pField
[i
].nFuncCount
;
363 // nach Load muessen Daten neu berechnet werden !
365 BOOL
ScPivot::Load( SvStream
& /* rStream */, ScMultipleReadHeader
& rHdr
)
368 #if SC_ROWLIMIT_STREAM_ACCESS
369 #error address types changed!
371 rStream
>> bHasHeader
385 // Arrays immer ueber Set...Fields initalisieren!
388 PivotFieldArr aFieldArr
;
390 if( pDoc
->GetSrcVersion() >= SC_DATABYTES2
)
393 lcl_LoadFieldArr( rStream
, aFieldArr
, nCount
);
394 SetColFields(aFieldArr
, nCount
);
397 lcl_LoadFieldArr( rStream
, aFieldArr
, nCount
);
398 SetRowFields(aFieldArr
, nCount
);
401 lcl_LoadFieldArr( rStream
, aFieldArr
, nCount
);
402 SetDataFields(aFieldArr
, nCount
);
407 lcl_LoadFieldArr30( rStream
, aFieldArr
, nCount
);
408 SetColFields(aFieldArr
, nCount
);
411 lcl_LoadFieldArr30( rStream
, aFieldArr
, nCount
);
412 SetRowFields(aFieldArr
, nCount
);
415 lcl_LoadFieldArr30( rStream
, aFieldArr
, nCount
);
416 SetDataFields(aFieldArr
, nCount
);
419 aQuery
.Load( rStream
);
421 rStream
>> bIgnoreEmpty
;
422 rStream
>> bDetectCat
;
424 if (rHdr
.BytesLeft())
426 rStream
>> bMakeTotalCol
; // ab 355i
427 rStream
>> bMakeTotalRow
;
430 if (rHdr
.BytesLeft()) // ab 500a
432 rStream
.ReadByteString( aName
, rStream
.GetStreamCharSet() );
433 rStream
.ReadByteString( aTag
, rStream
.GetStreamCharSet() );
435 DBG_ASSERT(!pColNames
, "Spaltennamen schon gesetzt?");
436 rStream
>> nColNameCount
;
439 pColNames
= new String
[nColNameCount
];
440 for (SCCOL nCol
=0; nCol
<nColNameCount
; nCol
++)
441 rStream
.ReadByteString( pColNames
[nCol
], rStream
.GetStreamCharSet() );
444 // sonst wird hinterher aus ScPivotCollection::Load ein Name vergeben
451 BOOL
ScPivot::Store( SvStream
& /* rStream */, ScMultipleWriteHeader
& rHdr
) const
454 #if SC_ROWLIMIT_STREAM_ACCESS
455 #error address types changed!
457 rStream
<< bHasHeader
472 lcl_SaveFieldArr( rStream
, aColArr
, nColCount
);
473 rStream
<< nRowCount
;
474 lcl_SaveFieldArr( rStream
, aRowArr
, nRowCount
);
475 rStream
<< nDataCount
;
476 lcl_SaveFieldArr( rStream
, aDataArr
, nDataCount
);
478 aQuery
.Store( rStream
);
480 rStream
<< bIgnoreEmpty
;
481 rStream
<< bDetectCat
;
483 rStream
<< bMakeTotalCol
; // ab 355i
484 rStream
<< bMakeTotalRow
;
486 if( rStream
.GetVersion() > SOFFICE_FILEFORMAT_40
) // Name/Tag/Spalten ab 5.0
488 rStream
.WriteByteString( aName
, rStream
.GetStreamCharSet() );
489 rStream
.WriteByteString( aTag
, rStream
.GetStreamCharSet() );
491 if (!pColNames
) ((ScPivot
*)this)->nColNameCount
= 0; // soll nicht sein
492 rStream
<< nColNameCount
;
493 for (SCCOL nCol
=0; nCol
<nColNameCount
; nCol
++)
494 rStream
.WriteByteString( pColNames
[nCol
], rStream
.GetStreamCharSet() );
502 void ScPivot::SetQuery(const ScQueryParam
& rQuery
)
509 void ScPivot::GetQuery(ScQueryParam
& rQuery
) const
514 void ScPivot::SetHeader(BOOL bHeader
)
516 bHasHeader
= bHeader
;
520 BOOL
ScPivot::GetHeader() const
525 void ScPivot::SetIgnoreEmpty(BOOL bIgnore
)
527 bIgnoreEmpty
= bIgnore
;
531 BOOL
ScPivot::GetIgnoreEmpty() const
536 void ScPivot::SetDetectCat(BOOL bDetect
)
538 bDetectCat
= bDetect
;
542 BOOL
ScPivot::GetDetectCat() const
547 void ScPivot::SetMakeTotalCol(BOOL bSet
)
549 bMakeTotalCol
= bSet
;
553 BOOL
ScPivot::GetMakeTotalCol() const
555 return bMakeTotalCol
;
558 void ScPivot::SetMakeTotalRow(BOOL bSet
)
560 bMakeTotalRow
= bSet
;
564 BOOL
ScPivot::GetMakeTotalRow() const
566 return bMakeTotalRow
;
569 void ScPivot::SetName(const String
& rNew
)
574 const String
& ScPivot::GetName() const
579 void ScPivot::SetTag(const String
& rNew
)
584 const String
& ScPivot::GetTag() const
589 void ScPivot::SetSrcArea(SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
, SCTAB nTab
)
591 nSrcCol1
= Min(nCol1
, (SCCOL
)MAXCOL
);
592 nSrcRow1
= Min(nRow1
, (SCROW
)MAXROW
);
593 nSrcCol2
= Min(nCol2
, (SCCOL
)MAXCOL
);
594 nSrcRow2
= Min(nRow2
, (SCROW
)MAXROW
);
599 void ScPivot::GetSrcArea(SCCOL
& rCol1
, SCROW
& rRow1
, SCCOL
& rCol2
, SCROW
& rRow2
, SCTAB
& rTab
) const
608 ScRange
ScPivot::GetSrcArea() const
610 return ScRange( nSrcCol1
,nSrcRow1
,nSrcTab
, nSrcCol2
,nSrcRow2
,nSrcTab
);
613 void ScPivot::SetDestPos(SCCOL nCol
, SCROW nRow
, SCTAB nTab
)
621 void ScPivot::GetDestArea(SCCOL
& rCol1
, SCROW
& rRow1
, SCCOL
& rCol2
, SCROW
& rRow2
, SCTAB
& rTab
) const
638 ScRange
ScPivot::GetDestArea() const
640 ScAddress
aStart( nDestCol1
, nDestRow1
, nDestTab
);
641 ScAddress aEnd
= aStart
;
643 aEnd
= ScAddress( nDestCol2
, nDestRow2
, nDestTab
);
644 return ScRange( aStart
, aEnd
);
647 void ScPivot::MoveSrcArea( SCCOL nNewCol
, SCROW nNewRow
, SCTAB nNewTab
)
649 if ( nNewCol
!= nSrcCol1
|| nNewRow
!= nSrcRow1
|| nNewTab
!= nSrcTab
)
651 SCsCOL nDiffX
= nNewCol
- (SCsCOL
) nSrcCol1
;
652 SCsROW nDiffY
= nNewRow
- (SCsROW
) nSrcRow1
;
655 nSrcCol1
= sal::static_int_cast
<SCCOL
>( nSrcCol1
+ nDiffX
);
656 nSrcCol2
= sal::static_int_cast
<SCCOL
>( nSrcCol2
+ nDiffX
);
657 nSrcRow1
= sal::static_int_cast
<SCROW
>( nSrcRow1
+ nDiffY
);
658 nSrcRow2
= sal::static_int_cast
<SCROW
>( nSrcRow2
+ nDiffY
);
660 aQuery
.nCol1
= sal::static_int_cast
<SCCOL
>( aQuery
.nCol1
+ nDiffX
);
661 aQuery
.nCol2
= sal::static_int_cast
<SCCOL
>( aQuery
.nCol2
+ nDiffX
);
662 aQuery
.nRow1
= sal::static_int_cast
<SCROW
>( aQuery
.nRow1
+ nDiffY
);
663 aQuery
.nRow2
= sal::static_int_cast
<SCROW
>( aQuery
.nRow2
+ nDiffY
);
665 SCSIZE nEC
= aQuery
.GetEntryCount();
666 for (SCSIZE i
=0; i
<nEC
; i
++)
667 if (aQuery
.GetEntry(i
).bDoQuery
)
668 aQuery
.GetEntry(i
).nField
+= nDiffX
;
674 for (nC
=0; nC
<nColCount
; nC
++)
675 if (aColArr
[nC
].nCol
!= PIVOT_DATA_FIELD
)
676 aColArr
[nC
].nCol
= sal::static_int_cast
<SCsCOL
>( aColArr
[nC
].nCol
+ nDiffX
);
677 for (nR
=0; nR
<nRowCount
; nR
++)
678 if (aRowArr
[nR
].nCol
!= PIVOT_DATA_FIELD
)
679 aRowArr
[nR
].nCol
= sal::static_int_cast
<SCsCOL
>( aRowArr
[nR
].nCol
+ nDiffX
);
680 for (nC
=0; nC
<nDataCount
; nC
++)
681 if (aDataArr
[nC
].nCol
!= PIVOT_DATA_FIELD
)
682 aDataArr
[nC
].nCol
= sal::static_int_cast
<SCsCOL
>( aDataArr
[nC
].nCol
+ nDiffX
);
687 void ScPivot::ExtendSrcArea( SCCOL nNewEndCol
, SCROW nNewEndRow
)
689 DBG_ASSERT( nNewEndCol
>= nSrcCol2
&& nNewEndRow
>= nSrcRow2
, "ExtendSrcArea: zu klein" );
691 nSrcCol2
= nNewEndCol
;
692 nSrcRow2
= nNewEndRow
;
694 // alles andere bleibt erhalten
697 void ScPivot::MoveDestArea( SCCOL nNewCol
, SCROW nNewRow
, SCTAB nNewTab
)
699 if ( nNewCol
!= nDestCol1
|| nNewRow
!= nDestRow1
|| nNewTab
!= nDestTab
)
701 SCsCOL nDiffX
= nNewCol
- (SCsCOL
) nDestCol1
;
702 SCsROW nDiffY
= nNewRow
- (SCsROW
) nDestRow1
;
705 nDestCol1
= sal::static_int_cast
<SCCOL
>( nDestCol1
+ nDiffX
);
706 nDestRow1
= sal::static_int_cast
<SCROW
>( nDestRow1
+ nDiffY
);
710 nDestCol2
= sal::static_int_cast
<SCCOL
>( nDestCol2
+ nDiffX
);
711 nDestRow2
= sal::static_int_cast
<SCROW
>( nDestRow2
+ nDiffY
);
713 nDataStartCol
= sal::static_int_cast
<SCCOL
>( nDataStartCol
+ nDiffX
);
714 nDataStartRow
= sal::static_int_cast
<SCROW
>( nDataStartRow
+ nDiffY
);
719 void ScPivot::SetColFields(const PivotField
* pFieldArr
, SCSIZE nCount
)
721 nColCount
= Max(static_cast<SCSIZE
>(0), Min(nCount
, PIVOT_MAXFIELD
));
722 for (SCSIZE i
= 0; i
< nColCount
; i
++)
724 aColArr
[i
] = pFieldArr
[i
];
725 aColArr
[i
].nFuncCount
= 0;
726 if (aColArr
[i
].nCol
== PIVOT_DATA_FIELD
)
728 aColArr
[i
].nFuncMask
= PIVOT_FUNC_NONE
;
729 pDataList
= pColList
[i
];
734 for (SCsCOL j
=0; j
<=PIVOT_MAXFUNC
; j
++) // incl. "auto"
735 if (aColArr
[i
].nFuncMask
& nFuncMaskArr
[j
])
736 aColArr
[i
].nFuncCount
++;
742 void ScPivot::GetColFields(PivotField
* pFieldArr
, SCSIZE
& rCount
) const
744 for (SCSIZE i
=0; i
<nColCount
; i
++)
745 pFieldArr
[i
] = aColArr
[i
];
749 void ScPivot::SetRowFields(const PivotField
* pFieldArr
, SCSIZE nCount
)
751 nRowCount
= Max(static_cast<SCSIZE
>(0), Min(nCount
, PIVOT_MAXFIELD
));
752 for (SCSIZE i
= 0; i
< nRowCount
; i
++)
754 aRowArr
[i
] = pFieldArr
[i
];
755 aRowArr
[i
].nFuncCount
= 0;
756 if (aRowArr
[i
].nCol
== PIVOT_DATA_FIELD
)
758 aRowArr
[i
].nFuncMask
= PIVOT_FUNC_NONE
;
759 pDataList
= pRowList
[i
];
764 for (SCSIZE j
=0; j
<=PIVOT_MAXFUNC
; j
++) // incl. "auto"
765 if (aRowArr
[i
].nFuncMask
& nFuncMaskArr
[j
])
766 aRowArr
[i
].nFuncCount
++;
772 void ScPivot::GetRowFields(PivotField
* pFieldArr
, SCSIZE
& rCount
) const
774 for (SCSIZE i
=0; i
<nRowCount
; i
++)
775 pFieldArr
[i
] = aRowArr
[i
];
779 void ScPivot::SetDataFields(const PivotField
* pFieldArr
, SCSIZE nCount
)
785 // nDataCount vorausberechnen (wie unten)
789 for (i
= 0; i
< nCount
; i
++)
790 for (nFuncNo
=0; nFuncNo
<PIVOT_MAXFUNC
; nFuncNo
++)
791 if (pFieldArr
[i
].nFuncMask
& nFuncMaskArr
[nFuncNo
])
792 if (nDataCount
+1 < PIVOT_MAXFIELD
)
796 // Eintraege anpassen
799 if ((nRowCount
== 1) && (aRowArr
[0].nCol
== PIVOT_DATA_FIELD
) && (nDataCount
== 1))
801 aColArr
[nColCount
] = aRowArr
[0];
802 pDataList
= pColList
[nColCount
];
807 if ((nColCount
== 1) && (aColArr
[0].nCol
== PIVOT_DATA_FIELD
) && (nDataCount
== 1))
809 aRowArr
[nRowCount
] = aColArr
[0];
810 pDataList
= pRowList
[nRowCount
];
816 if ((nDataCount
== 1)
817 && (aColArr
[nColCount
-1].nCol
!= PIVOT_DATA_FIELD
)
818 && (aColArr
[nRowCount
-1].nCol
!= PIVOT_DATA_FIELD
))
823 SCSIZE nIndex
= PIVOT_MAXFIELD
;
824 for (i
=0; i
<nColCount
; i
++)
826 if (aColArr
[i
].nCol
== PIVOT_DATA_FIELD
)
832 DBG_ASSERT(nIndex
< PIVOT_MAXFIELD
, "no data field (GPF in old versions!)");
833 if ( nIndex
< PIVOT_MAXFIELD
)
835 memcpy(&aColArr
[nIndex
], &aColArr
[nIndex
+1], (PIVOT_MAXFIELD
- nIndex
- 1) * sizeof(PivotField
));
836 aColArr
[nColCount
-1] = aField
;
837 pDataList
= pColList
[nColCount
-1];
843 SCSIZE nIndex
= PIVOT_MAXFIELD
;
844 for (i
=0; i
<nRowCount
; i
++)
846 if (aRowArr
[i
].nCol
== PIVOT_DATA_FIELD
)
852 DBG_ASSERT(nIndex
< PIVOT_MAXFIELD
, "no data field (GPF in old versions!)");
853 if ( nIndex
< PIVOT_MAXFIELD
)
855 memcpy(&aRowArr
[nIndex
], &aRowArr
[nIndex
+1], (PIVOT_MAXFIELD
- nIndex
- 1) * sizeof(PivotField
));
856 aRowArr
[nRowCount
-1] = aField
;
857 pDataList
= pRowList
[nRowCount
-1];
863 // Datenfelder in Eintraege mit nur einer Funktion aufteilen
866 pDataList
->FreeAll();
868 for (i
= 0; i
< nCount
; i
++)
870 for (nFuncNo
=0; nFuncNo
<PIVOT_MAXFUNC
; nFuncNo
++)
871 if (pFieldArr
[i
].nFuncMask
& nFuncMaskArr
[nFuncNo
])
872 if (nDataCount
+1 < PIVOT_MAXFIELD
)
874 aDataArr
[nDataCount
] = pFieldArr
[i
];
875 aDataArr
[nDataCount
].nFuncCount
= 0;
876 aDataArr
[nDataCount
].nFuncMask
= nFuncMaskArr
[nFuncNo
];
879 pDoc
->GetString(aDataArr
[nDataCount
].nCol
, nSrcRow1
, nSrcTab
, aStr
);
881 aStr
= ScColToAlpha( aDataArr
[nDataCount
].nCol
);
882 TypedStrData
* pStrData
= new TypedStrData(aStr
);
883 if (!(pDataList
->AtInsert(pDataList
->GetCount(), pStrData
)))
886 DBG_ERROR("Fehler bei pDataList->AtInsert");
900 void ScPivot::GetDataFields(PivotField
* pFieldArr
, SCSIZE
& rCount
) const
902 /* for (SCSIZE i=0; i<nDataCount; i++)
903 pFieldArr[i] = aDataArr[i];
908 for (SCSIZE i
=0; i
<nDataCount
; i
++)
911 for (SCSIZE j
=0; j
<rCount
&& !bFound
; j
++)
912 if (pFieldArr
[j
].nCol
== aDataArr
[i
].nCol
)
914 // add to previous column only if new bits aren't already set there
915 if ( ( pFieldArr
[j
].nFuncMask
& aDataArr
[i
].nFuncMask
) == 0 )
917 pFieldArr
[j
].nFuncMask
|= aDataArr
[i
].nFuncMask
;
918 pFieldArr
[j
].nFuncCount
++;
924 pFieldArr
[rCount
] = aDataArr
[i
];
930 BOOL
ScPivot::CreateData(BOOL bKeepDest
)
936 SCCOL nOldCol2
= nDestCol2
;
937 SCROW nOldRow2
= nDestRow2
;
939 pColRef
= new PivotColRef
[MAXCOL
];
940 aQuery
.nCol1
= nSrcCol1
;
941 aQuery
.nRow1
= nSrcRow1
;
942 aQuery
.nCol2
= nSrcCol2
;
943 aQuery
.nRow2
= nSrcRow2
;
944 aQuery
.bHasHeader
= bHasHeader
;
945 BOOL bRet
= CreateFields();
948 SCSIZE i
=0; // nDataMult berechnen - nach CreateFields, vor CreateFieldData !!!
954 while (i
<nColCount
&& aColArr
[i
].nCol
!= PIVOT_DATA_FIELD
) i
++;
957 nDataMult
*= pColList
[i
++]->GetCount();
961 while (i
<nRowCount
&& aRowArr
[i
].nCol
!= PIVOT_DATA_FIELD
) i
++;
964 nDataMult
*= pRowList
[i
++]->GetCount();
967 DBG_ASSERT(nDataMult
,"nDataMult==0");
970 if ((ValidCol(nDestCol2
)) && (ValidRow(nDestRow2
)))
981 bValidArea
= TRUE
; //! ???
982 nDestCol2
= nOldCol2
;
983 nDestRow2
= nOldRow2
;
989 void ScPivot::DrawData()
991 ScProgress
aProgress( pDoc
->GetDocumentShell(), ScGlobal::GetRscString(STR_PIVOT_PROGRESS
), nDestRow2
-nDestRow1
);
998 pDoc
->pTab
[nDestTab
]->DeleteArea(nDestCol1
, nDestRow1
, nDestCol2
, nDestRow2
, IDF_ALL
);
1000 if ( nDataStartRow
> nDestRow1
+nFirstLine
)
1001 SetStyle(nDestCol1
, nDestRow1
+nFirstLine
, nDestCol2
, nDataStartRow
-1, PIVOT_STYLE_TOP
);
1002 SetStyle(nDataStartCol
, nDataStartRow
, nDestCol2
, nDestRow2
, PIVOT_STYLE_INNER
);
1004 pDoc
->SetString(nDestCol1
, nDestRow1
, nDestTab
, ScGlobal::GetRscString(STR_CELL_FILTER
));
1006 SetButton(nDestCol1
, nDestRow1
, nDestCol1
, nDestRow1
);
1008 if (bHasHeader
) // Spalten / Zeilennamen ausgeben
1013 nRow
= nDataStartRow
- 1;
1014 for (i
=0; i
<nColCount
; i
++)
1016 if (aColArr
[i
].nCol
!= PIVOT_DATA_FIELD
)
1018 pDoc
->GetString(aColArr
[i
].nCol
, nSrcRow1
, nSrcTab
, aStr
);
1020 aStr
= ScColToAlpha( aColArr
[i
].nCol
);
1021 pDoc
->SetString(nCol
, nRow
, nDestTab
, aStr
);
1025 else if (nDataCount
> 1)
1027 pDoc
->SetString(nCol
, nRow
, nDestTab
, *pLabelData
);
1032 SetButton(nDestCol1
, nRow
, nCol
-1, nRow
);
1033 SetStyle(nDestCol1
, nRow
, nCol
-1, nRow
, PIVOT_STYLE_FIELDNAME
);
1037 nCol
= nDataStartCol
;
1038 nRow
= nDestRow1
+ nFirstLine
;
1039 for (i
=0; i
<nRowCount
; i
++)
1041 if (aRowArr
[i
].nCol
!= PIVOT_DATA_FIELD
)
1043 pDoc
->GetString(aRowArr
[i
].nCol
, nSrcRow1
, nSrcTab
, aStr
);
1045 aStr
= ScColToAlpha( aRowArr
[i
].nCol
);
1046 pDoc
->SetString(nCol
, nRow
, nDestTab
, aStr
);
1050 else if (nDataCount
> 1)
1052 pDoc
->SetString(nCol
, nRow
, nDestTab
, *pLabelData
);
1057 SetButton(nDataStartCol
, nRow
, nCol
-1, nRow
);
1058 SetStyle(nDataStartCol
, nRow
, nCol
-1, nRow
, PIVOT_STYLE_FIELDNAME
);
1062 BOOL bNoRows
= (nRowCount
== 0) || ( nRowCount
== 1 && aRowArr
[0].nCol
== PIVOT_DATA_FIELD
);
1063 BOOL bNoCols
= (nColCount
== 0) || ( nColCount
== 1 && aColArr
[0].nCol
== PIVOT_DATA_FIELD
);
1064 if (!bMakeTotalCol
) bNoRows
= TRUE
;
1065 if (!bMakeTotalRow
) bNoCols
= TRUE
;
1067 SCCOL nTotalCol
= nDestCol2
;
1068 SCROW nTotalRow
= nDestRow2
;
1070 nTotalRow
= sal::static_int_cast
<SCROW
>( nTotalRow
- ( nDataCount
- 1 ) );
1072 nTotalCol
= sal::static_int_cast
<SCCOL
>( nTotalCol
- ( nDataCount
- 1 ) );
1074 // Spaltenkoepfe ausgeben und ColRef initialisieren
1075 // (String-Collections sind initialisiert)
1078 nCol
= nDataStartCol
;
1080 RowToTable(0, nCol
);
1082 // Zeilenkoepfe und Daten ausgeben
1083 // (ruft SetDataLine/SetFuncLine auf)
1085 nRow
= nDataStartRow
;
1086 ColToTable(0, nRow
, aProgress
);
1088 // Gesamtergebnis-Zeilen
1093 for (SCSIZE nTotCnt
= 0; nTotCnt
<nDataCount
; nTotCnt
++)
1094 SetFuncLine(nDataStartCol
, nRow
+nTotCnt
, nDestTab
,
1095 aDataArr
[nTotCnt
].nFuncMask
, nTotCnt
, 0, nDataRowCount
);
1097 SetFuncLine(nDataStartCol
, nRow
, nDestTab
, PIVOT_FUNC_AUTO
, SCSIZE_MAX
, 0, nDataRowCount
);
1101 // Rahmen Spaltenergebnis
1107 for (i
=0; i
<nDataCount
; i
++)
1109 String aLab
= *pLabelTotal
;
1111 aLab
+= *pLabel
[lcl_MaskToIndex( aDataArr
[i
].nFuncMask
)];
1113 aLab
+= pDataList
->GetString(sal::static_int_cast
<USHORT
>(i
));
1114 pDoc
->SetString(sal::static_int_cast
<SCCOL
>(nTotalCol
+i
),
1115 sal::static_int_cast
<SCROW
>(nDestRow1
+ nFirstLine
), nDestTab
, aLab
);
1121 pDoc
->SetString(nTotalCol
, nDestRow1
+ nFirstLine
, nDestTab
, *pLabelTotal
);
1125 if ( nDataStartRow
> 0 )
1126 SetStyle(nTotalCol
, nDestRow1
+nFirstLine
, nDestCol2
, nDataStartRow
-1, PIVOT_STYLE_TITLE
);
1127 SetStyle(nTotalCol
, nDataStartRow
, nDestCol2
, nDestRow2
, PIVOT_STYLE_RESULT
);
1128 SetFrame(nTotalCol
, nDestRow1
+ nFirstLine
, nDestCol2
, nDestRow2
);
1131 // Rahmen Zeilenergebnis
1137 for (i
=0; i
<nDataCount
; i
++)
1139 String aLab
= *pLabelTotal
;
1141 aLab
+= *pLabel
[lcl_MaskToIndex( aDataArr
[i
].nFuncMask
)];
1143 aLab
+= pDataList
->GetString(sal::static_int_cast
<USHORT
>(i
));
1144 pDoc
->SetString(nDestCol1
, nTotalRow
+i
, nDestTab
, aLab
);
1150 pDoc
->SetString(nDestCol1
, nTotalRow
, nDestTab
, *pLabelTotal
);
1154 if ( nDataStartCol
> 0 )
1155 SetStyle(nDestCol1
, nTotalRow
, nDataStartCol
-1, nDestRow2
, PIVOT_STYLE_TITLE
);
1156 SetStyle(nDataStartCol
, nTotalRow
, nDestCol2
, nDestRow2
, PIVOT_STYLE_RESULT
);
1157 SetFrame(nDestCol1
, nTotalRow
, nDestCol2
, nDestRow2
);
1161 SetFrame(nDestCol1
, nDestRow1
+ nFirstLine
, nDestCol2
, nDestRow2
, 40);
1164 void ScPivot::ReleaseData()
1166 for (SCSIZE i
= 0; i
< PIVOT_MAXFIELD
; i
++)
1168 pColList
[i
]->FreeAll();
1169 pRowList
[i
]->FreeAll();
1173 for (SCSIZE i
=0; i
<nDataRowCount
; i
++)
1174 delete[] ppDataArr
[i
];
1184 BOOL
ScPivot::IsPivotAtCursor(SCCOL nCol
, SCROW nRow
, SCTAB nTab
) const
1187 return ( nTab
== nDestTab
1188 && nCol
>= nDestCol1
&& nCol
<= nDestCol2
1189 && nRow
>= nDestRow1
&& nRow
<= nDestRow2
);
1194 BOOL
ScPivot::IsFilterAtCursor(SCCOL nCol
, SCROW nRow
, SCTAB nTab
) const
1197 return (nCol
== nDestCol1
&& nRow
== nDestRow1
&& nTab
== nDestTab
);
1202 BOOL
ScPivot::GetColFieldAtCursor(SCCOL nCol
, SCROW nRow
, SCTAB nTab
, SCCOL
& rField
) const
1208 bRet
= ( nCol
>= nDestCol1
&& nCol
< nDataStartCol
1209 && nRow
== nDataStartRow
- 1
1210 && nTab
== nDestTab
);
1213 rField
= aColArr
[nCol
- nDestCol1
].nCol
;
1214 if (rField
== PIVOT_DATA_FIELD
)
1215 bRet
= (nDataCount
> 1);
1221 BOOL
ScPivot::GetRowFieldAtCursor(SCCOL nCol
, SCROW nRow
, SCTAB nTab
, SCCOL
& rField
) const
1227 bRet
= ( nCol
>= nDataStartCol
&& nCol
< sal::static_int_cast
<SCCOL
>(nDataStartCol
+ nRowCount
)
1228 && nRow
== nDestRow1
+ nFirstLine
1229 && nTab
== nDestTab
);
1232 rField
= aRowArr
[nCol
- nDataStartCol
].nCol
;
1233 if (rField
== PIVOT_DATA_FIELD
)
1234 bRet
= (nDataCount
> 1);
1241 //--------------------------------------------------------------------------------------------------
1243 //--------------------------------------------------------------------------------------------------
1245 BOOL
ScPivot::CreateFields()
1251 TypedStrData
* pStrData
;
1257 // Sortieren nach Benutzerdefinierte Listen ??
1258 for (i
= 0; i
< nColCount
; i
++)
1260 if (aColArr
[i
].nCol
!= PIVOT_DATA_FIELD
)
1262 pDoc
->GetString(aColArr
[i
].nCol
, nSrcRow1
+ nHeader
, nSrcTab
, aStr
);
1263 pColList
[i
]->SetUserData(ScGlobal::GetUserList()->GetData(aStr
));
1266 pColList
[i
]->SetUserData(NULL
);
1268 for (i
= 0; i
< nRowCount
; i
++)
1270 if (aRowArr
[i
].nCol
!= PIVOT_DATA_FIELD
)
1272 pDoc
->GetString(aRowArr
[i
].nCol
, nSrcRow1
+ nHeader
, nSrcTab
, aStr
);
1273 pRowList
[i
]->SetUserData(ScGlobal::GetUserList()->GetData(aStr
));
1276 pRowList
[i
]->SetUserData(NULL
);
1279 ScAddress
aSrcAdr( nSrcCol1
, 0, nSrcTab
);
1280 for (nRow
= nSrcRow1
+ nHeader
; nRow
<= nSrcRow2
; nRow
++)
1282 BOOL bValidLine
= TRUE
;
1285 aSrcAdr
.SetRow( nRow
);
1286 bValidLine
= !lcl_IsEmptyLine( pDoc
, aSrcAdr
, nSrcCol2
);
1289 bValidLine
= pDoc
->pTab
[nSrcTab
]->ValidQuery(nRow
, aQuery
);
1292 // Sortierte Liste der Felder erzeugen
1293 //! statt GetCategoryString leere weglassen !
1295 for (i
= 0; i
< nColCount
; i
++)
1297 if (aColArr
[i
].nCol
!= PIVOT_DATA_FIELD
)
1299 SCROW nCatRow
= bDetectCat
? GetCategoryRow( aColArr
[i
].nCol
, nRow
) : nRow
;
1300 pStrData
= new TypedStrData( pDoc
, aColArr
[i
].nCol
, nCatRow
, nSrcTab
, TRUE
);
1301 if (!(pColList
[i
]->Insert(pStrData
)))
1305 for (i
= 0; i
< nRowCount
; i
++)
1307 if (aRowArr
[i
].nCol
!= PIVOT_DATA_FIELD
)
1309 SCROW nCatRow
= bDetectCat
? GetCategoryRow( aRowArr
[i
].nCol
, nRow
) : nRow
;
1310 pStrData
= new TypedStrData( pDoc
, aRowArr
[i
].nCol
, nCatRow
, nSrcTab
, TRUE
);
1311 if (!(pRowList
[i
]->Insert(pStrData
)))
1320 void ScPivot::CreateFieldData()
1322 SCSIZE
* pRowListIndex
= nRowCount
? new SCSIZE
[nRowCount
] : NULL
;
1323 SCSIZE
* pColListIndex
= nColCount
? new SCSIZE
[nColCount
] : NULL
;
1327 ppDataArr
= new SubTotal
*[nDataRowCount
];
1328 for (i
=0; i
<nDataRowCount
; i
++)
1329 ppDataArr
[i
] = new SubTotal
[nDataColCount
];
1332 for (j
=0; j
<nDataRowCount
; j
++)
1333 for (i
=0; i
<nDataColCount
; i
++)
1334 ppDataArr
[j
][i
].nIndex
= j
/nDataMult
%nDataCount
;
1336 for (j
=0; j
<nDataRowCount
; j
++)
1337 for (i
=0; i
<nDataColCount
; i
++)
1338 ppDataArr
[j
][i
].nIndex
= i
/nDataMult
%nDataCount
;
1345 ScAddress
aSrcAdr( nSrcCol1
, 0, nSrcTab
);
1346 for (SCROW nRow
= nSrcRow1
+ nHeader
; nRow
<= nSrcRow2
; nRow
++)
1348 BOOL bValidLine
= TRUE
;
1351 aSrcAdr
.SetRow( nRow
);
1352 bValidLine
= !lcl_IsEmptyLine( pDoc
, aSrcAdr
, nSrcCol2
);
1355 bValidLine
= pDoc
->pTab
[nSrcTab
]->ValidQuery(nRow
, aQuery
);
1358 // Indizes der Kategorien nur einmal ausserhalb nDataCount
1359 for (j
=0; j
<nRowCount
; j
++)
1360 if (aRowArr
[j
].nCol
!= PIVOT_DATA_FIELD
)
1362 SCROW nCatRow
= bDetectCat
? GetCategoryRow( aRowArr
[j
].nCol
, nRow
) : nRow
;
1363 TypedStrData
aStrData( pDoc
, aRowArr
[j
].nCol
, nCatRow
, nSrcTab
, TRUE
);
1364 pRowListIndex
[j
] = pRowList
[j
]->GetIndex(&aStrData
);
1366 for (j
=0; j
<nColCount
; j
++)
1367 if (aColArr
[j
].nCol
!= PIVOT_DATA_FIELD
)
1369 SCROW nCatRow
= bDetectCat
? GetCategoryRow( aColArr
[j
].nCol
, nRow
) : nRow
;
1370 TypedStrData
aStrData( pDoc
, aColArr
[j
].nCol
, nCatRow
, nSrcTab
, TRUE
);
1371 pColListIndex
[j
] = pColList
[j
]->GetIndex(&aStrData
);
1378 ScAddress
aAdr( 0, nRow
, nSrcTab
);
1380 for (i
=0; i
<nDataCount
; i
++)
1382 // ColIndex Berechnen
1384 for (j
=0; j
<nRowCount
; j
++)
1386 if (aRowArr
[j
].nCol
== PIVOT_DATA_FIELD
)
1389 nIndex
= pRowListIndex
[j
];
1392 for (k
=j
+1; k
<nRowCount
; k
++)
1393 nIndex
*= pRowList
[k
]->GetCount();
1397 // RowIndex Berechnen
1399 for (j
=0; j
<nColCount
; j
++)
1401 if (aColArr
[j
].nCol
== PIVOT_DATA_FIELD
)
1404 nIndex
= pColListIndex
[j
];
1407 for (k
=j
+1; k
<nColCount
; k
++)
1408 nIndex
*= pColList
[k
]->GetCount();
1413 if ((nCIndex
< nDataColCount
) && (nRIndex
< nDataRowCount
))
1415 DBG_ASSERT(ppDataArr
[nRIndex
][nCIndex
].nIndex
== i
, "falsch init.");
1417 ppDataArr
[nRIndex
][nCIndex
].nIndex
= i
;
1418 aAdr
.SetCol( aDataArr
[i
].nCol
);
1419 CellType eCellType
= pDoc
->GetCellType( aAdr
);
1420 if ((eCellType
!= CELLTYPE_NONE
) && (eCellType
!= CELLTYPE_NOTE
))
1422 BOOL bValue
= (eCellType
== CELLTYPE_VALUE
);
1423 if (eCellType
== CELLTYPE_FORMULA
)
1425 ScBaseCell
* pCell
= pDoc
->GetCell( aAdr
);
1426 bValue
= ((ScFormulaCell
*)pCell
)->IsValue();
1431 double nVal
= pDoc
->GetValue( aAdr
);
1432 ppDataArr
[nRIndex
][nCIndex
].Update(nVal
);
1435 ppDataArr
[nRIndex
][nCIndex
].UpdateNoVal(); // nur nCount
1442 delete pColListIndex
;
1443 delete pRowListIndex
;
1446 void ScPivot::CalcArea()
1448 BOOL bNoRows
= (nRowCount
== 0) || ( nRowCount
== 1 && aRowArr
[0].nCol
== PIVOT_DATA_FIELD
);
1449 BOOL bNoCols
= (nColCount
== 0) || ( nColCount
== 1 && aColArr
[0].nCol
== PIVOT_DATA_FIELD
);
1450 if (!bMakeTotalCol
) bNoRows
= TRUE
;
1451 if (!bMakeTotalRow
) bNoCols
= TRUE
;
1453 // StartSpalte/StartZeile des Datenbereichs berechnen
1457 nDataStartCol
= sal::static_int_cast
<SCCOL
>(nDestCol1
+ nColCount
);
1459 nDataStartCol
= sal::static_int_cast
<SCCOL
>(nDestCol1
+ Max(static_cast<SCSIZE
>(0), nColCount
- 1));
1462 nDataStartCol
= sal::static_int_cast
<SCCOL
>(nDestCol1
+ nColCount
);
1466 nDataStartRow
= nDestRow1
+ nRowCount
+ nFirstLine
+ 1;
1468 nDataStartRow
= nDestRow1
+ Max(static_cast<SCSIZE
>(0), nRowCount
- 1) + nFirstLine
+ 1;
1471 nDataStartRow
= nDestRow1
+ nRowCount
+ nFirstLine
+ 1;
1474 // Groesse der PivotTabelle berechnen
1477 if (nRowCount
== 0 || (nRowCount
==1 && aRowArr
[0].nCol
==PIVOT_DATA_FIELD
&& nDataCount
==1))
1480 if (nDataCount
== 1)
1481 nDestCol2
= sal::static_int_cast
<SCCOL
>(nDestCol1
+ nColCount
- 1);
1483 nDestCol2
= sal::static_int_cast
<SCCOL
>(nDestCol1
+ nColCount
);
1489 if ((aRowArr
[nRowCount
-1].nCol
== PIVOT_DATA_FIELD
) && (nDataCount
== 1))
1493 SCSIZE nColLines
= pRowList
[nRowCount
-nDx
]->GetCount(); // SCSIZE to recognize overflow
1494 nDataColCount
= pRowList
[nRowCount
-nDx
]->GetCount();
1495 for (SCSIZE i
=nRowCount
-nDx
; i
-- > 0; )
1497 nColLines
*= pRowList
[i
]->GetCount();
1498 nDataColCount
*= pRowList
[i
]->GetCount();
1500 nColLines
+= (pRowList
[i
]->GetCount() * aRowArr
[i
].nFuncCount
* nDataCount
);
1502 nColLines
+= (pRowList
[i
]->GetCount() * aRowArr
[i
].nFuncCount
);
1505 // Ergebnisspalten des letzten Elements
1506 if (aRowArr[nRowCount-1].nCol != PIVOT_DATA_FIELD)
1507 nColLines += (pRowList[nRowCount-1]->GetCount() * aRowArr[nRowCount-1].nFuncCount);
1509 if (nColLines
> static_cast<SCSIZE
>(MAXCOL
))
1510 nDestCol2
= MAXCOL
+2; // ungueltig, 1 wird unten abgezogen
1511 else if (bDataAtCol
)
1514 nDestCol2
= sal::static_int_cast
<SCCOL
>(nDestCol1
+ nColCount
+ nColLines
);
1516 nDestCol2
= sal::static_int_cast
<SCCOL
>(nDestCol1
+ (nColCount
- 1) + nColLines
);
1521 nDestCol2
= sal::static_int_cast
<SCCOL
>(nDestCol1
+ nColCount
+ nColLines
);
1524 if (nColCount
== 0 || (nColCount
==1 && aColArr
[0].nCol
==PIVOT_DATA_FIELD
&& nDataCount
==1))
1527 if (nDataCount
== 1)
1528 nDestRow2
= nDestRow1
+ (nRowCount
- 1) + nFirstLine
+ 1;
1530 nDestRow2
= nDestRow1
+ nRowCount
+ nFirstLine
+ 1;
1536 if ((aColArr
[nColCount
-1].nCol
== PIVOT_DATA_FIELD
) && (nDataCount
== 1))
1540 SCSIZE nRowLines
= pColList
[nColCount
-nDx
]->GetCount(); // SCSIZE to recognize overflow
1541 nDataRowCount
= pColList
[nColCount
-nDx
]->GetCount();
1542 for (SCSIZE i
=nColCount
-nDx
; i
-- > 0; )
1544 nRowLines
*= pColList
[i
]->GetCount();
1545 nDataRowCount
*= pColList
[i
]->GetCount();
1547 nRowLines
+= (pColList
[i
]->GetCount() * aColArr
[i
].nFuncCount
* nDataCount
);
1549 nRowLines
+= (pColList
[i
]->GetCount() * aColArr
[i
].nFuncCount
);
1552 // Ergebniszeilen des letzten Elements
1553 if (aColArr[nColCount-1].nCol != PIVOT_DATA_FIELD)
1554 nRowLines += (pColList[nColCount-1]->GetCount() * aColArr[nColCount-1].nFuncCount);
1556 if (nRowLines
> static_cast<SCSIZE
>(MAXROW
))
1557 nDestRow2
= MAXROW
+2; // ungueltig, 1 wird unten abgezogen
1558 else if (!bDataAtCol
)
1561 nDestRow2
= nDestRow1
+ nRowCount
+ nRowLines
+ nFirstLine
+ 1;
1563 nDestRow2
= nDestRow1
+ (nRowCount
- 1) + nRowLines
+ nFirstLine
+ 1;
1568 nDestRow2
= nDestRow1
+ nRowCount
+ nRowLines
+ nFirstLine
+ 1;
1574 nDestRow2
+= nDataCount
;
1580 nDestCol2
= sal::static_int_cast
<SCCOL
>(nDestCol2
+ nDataCount
);
1585 void ScPivot::SetDataLine(SCCOL nCol
, SCROW nRow
, SCTAB
/* nTab */, SCSIZE nRIndex
)
1589 SubTotal aGrandTotal
[PIVOT_MAXFIELD
]; // pro Daten-Feld
1591 for (SCSIZE i
=0; i
< nColIndex
; i
++)
1593 SCSIZE nCIndex
= pColRef
[i
].nDataIndex
;
1594 if (nCIndex
!= sal::static_int_cast
<SCSIZE
>(PIVOT_FUNC_REF
))
1596 // if ( ppDataArr[nRIndex][nCIndex].GetCount() )
1598 SCSIZE nDIndex
= ppDataArr
[nRIndex
][nCIndex
].nIndex
;
1599 SetValue( sal::static_int_cast
<SCCOL
>(nCol
+i
), nRow
, ppDataArr
[nRIndex
][nCIndex
], aDataArr
[nDIndex
].nFuncMask
);
1603 aGrandTotal
[0].Update(ppDataArr
[nRIndex
][nCIndex
]);
1605 aGrandTotal
[nDIndex
].Update(ppDataArr
[nRIndex
][nCIndex
]);
1612 while ((pColRef
[k
].nDataIndex
== sal::static_int_cast
<SCSIZE
>(PIVOT_FUNC_REF
)) && (k
> 0))
1614 for (SCSIZE j
=k
+1; (j
-- > 0) && (pColRef
[j
].nRecCount
> pColRef
[i
].nRecCount
); )
1616 nCIndex2
= pColRef
[j
].nDataIndex
;
1617 if (nCIndex2
!= sal::static_int_cast
<SCSIZE
>(PIVOT_FUNC_REF
))
1619 if ((pColRef
[i
].nIndex
== ppDataArr
[nRIndex
][nCIndex2
].nIndex
) ||
1620 (pColRef
[i
].nIndex
== SCSIZE_MAX
))
1622 aTotal
.Update( ppDataArr
[nRIndex
][nCIndex2
] );
1627 USHORT nFunc
= pColRef
[i
].nFuncMask
;
1628 if (nFunc
== PIVOT_FUNC_AUTO
)
1629 nFunc
= aDataArr
[nRIndex
/nDataMult
%nDataCount
].nFuncMask
;
1630 SetValue( sal::static_int_cast
<SCCOL
>(nCol
+i
), nRow
, aTotal
, nFunc
);
1635 BOOL bNoRows
= (nRowCount
== 0) || ( nRowCount
== 1 && aRowArr
[0].nCol
== PIVOT_DATA_FIELD
);
1636 if (!bMakeTotalCol
) bNoRows
= TRUE
;
1642 SetValue( nDestCol2
, nRow
, aGrandTotal
[0], aDataArr
[nRIndex
/nDataMult
%nDataCount
].nFuncMask
);
1647 SCCOL nTotalCol
= sal::static_int_cast
<SCCOL
>(nDestCol2
- nDataCount
+ 1);
1648 for (SCSIZE nTotCnt
= 0; nTotCnt
<nDataCount
; nTotCnt
++)
1650 SetValue( sal::static_int_cast
<SCCOL
>(nTotalCol
+nTotCnt
), nRow
, aGrandTotal
[nTotCnt
], aDataArr
[nTotCnt
].nFuncMask
);
1657 void ScPivot::SetFuncLine(SCCOL nCol
, SCROW nRow
, SCTAB
/* nTab */, USHORT nFunc
, SCSIZE nIndex
, SCSIZE nStartRIndex
, SCSIZE nEndRIndex
)
1659 SCSIZE nSubtCount
= 0;
1660 SubTotal aGrandTotal
[PIVOT_MAXFIELD
];
1661 USHORT nThisFunc
= nFunc
;
1663 for (SCSIZE i
=0; i
<nColIndex
; i
++)
1665 SCSIZE nCIndex
= pColRef
[i
].nDataIndex
;
1666 if (nCIndex
!= sal::static_int_cast
<SCSIZE
>(PIVOT_FUNC_REF
))
1669 for (SCSIZE j
= nStartRIndex
; j
< nEndRIndex
; j
++)
1671 SCSIZE nDIndex
= ppDataArr
[j
][nCIndex
].nIndex
;
1672 if ((nIndex
== nDIndex
) || (nIndex
== SCSIZE_MAX
))
1674 aTotal
.Update( ppDataArr
[j
][nCIndex
] );
1679 aGrandTotal
[0].Update( aTotal
);
1681 aGrandTotal
[nCIndex
/nDataMult
%nDataCount
].Update( aTotal
); //! immer ?
1683 if (nFunc
== PIVOT_FUNC_AUTO
)
1687 if (nIndex
<nDataCount
)
1688 nThisFunc
= aDataArr
[nIndex
].nFuncMask
;
1691 DBG_ERROR("wat fuer'n Index ???");
1695 nThisFunc
= aDataArr
[nCIndex
/nDataMult
%nDataCount
].nFuncMask
;
1697 SetValue( sal::static_int_cast
<SCCOL
>(nCol
+i
), nRow
, aTotal
, nThisFunc
);
1701 { // Kreuzungspunkte kompatibel ?
1703 if ( nFunc
== pColRef
[i
].nFuncMask
)
1705 SCSIZE nEffIndex
= nIndex
;
1706 if (nEffIndex
== SCSIZE_MAX
)
1708 nEffIndex
= nSubtCount
% nDataCount
;
1714 while ((pColRef
[k
].nDataIndex
== sal::static_int_cast
<SCSIZE
>(PIVOT_FUNC_REF
)) && (k
> 0))
1716 for (SCSIZE j
=k
+1; (j
-- > 0) && (pColRef
[j
].nRecCount
> pColRef
[i
].nRecCount
); )
1718 nCIndex
= pColRef
[j
].nDataIndex
;
1719 if (nCIndex
!= sal::static_int_cast
<SCSIZE
>(PIVOT_FUNC_REF
))
1721 for (SCSIZE nRIndex
= nStartRIndex
; nRIndex
< nEndRIndex
; nRIndex
++)
1723 SCSIZE nDIndex
= ppDataArr
[nRIndex
][nCIndex
].nIndex
;
1724 if (nEffIndex
== nDIndex
)
1726 aTotal
.Update( ppDataArr
[nRIndex
][nCIndex
] );
1732 if (nFunc
== PIVOT_FUNC_AUTO
)
1734 if (nEffIndex
<nDataCount
)
1735 nThisFunc
= aDataArr
[nEffIndex
].nFuncMask
;
1738 DBG_ERROR("wat fuer'n Index ???");
1741 SetValue( sal::static_int_cast
<SCCOL
>(nCol
+i
), nRow
, aTotal
, nThisFunc
);
1747 BOOL bNoRows
= (nRowCount
== 0) || ( nRowCount
== 1 && aRowArr
[0].nCol
== PIVOT_DATA_FIELD
);
1748 if (!bMakeTotalCol
) bNoRows
= TRUE
;
1754 if (nFunc
== PIVOT_FUNC_AUTO
)
1756 if (nIndex
<nDataCount
)
1757 nThisFunc
= aDataArr
[nIndex
].nFuncMask
;
1760 DBG_ERROR("wat fuer'n Index ???");
1763 SetValue( nDestCol2
, nRow
, aGrandTotal
[0], nThisFunc
);
1768 SCCOL nTotalCol
= sal::static_int_cast
<SCCOL
>(nDestCol2
- nDataCount
+ 1);
1769 for (SCSIZE nTotCnt
= 0; nTotCnt
<nDataCount
; nTotCnt
++)
1771 if (nFunc
== PIVOT_FUNC_AUTO
)
1772 nThisFunc
= aDataArr
[nTotCnt
%nDataCount
].nFuncMask
;
1773 SetValue( sal::static_int_cast
<SCCOL
>(nTotalCol
+nTotCnt
), nRow
, aGrandTotal
[nTotCnt
], nThisFunc
);
1780 void ScPivot::ColToTable(SCSIZE nField
, SCROW
& nRow
, ScProgress
& rProgress
)
1782 SCCOL nCol
= sal::static_int_cast
<SCCOL
>(nDestCol1
+ nField
);
1785 // SetDataLine(nCol + 1, nRow, nDestTab, nRowIndex);
1786 SetDataLine(nCol
, nRow
, nDestTab
, nRowIndex
);
1792 if ((aColArr
[nColCount
-1].nCol
== PIVOT_DATA_FIELD
) && (nDataCount
== 1))
1796 if (nField
< nColCount
- nDx
)
1798 for (USHORT i
= 0; i
< pColList
[nField
]->GetCount(); i
++)
1800 SCSIZE nSaveIndex
= nRowIndex
;
1801 String aStr
= pColList
[nField
]->GetString(i
);
1802 if (!aStr
.Len()) aStr
= ScGlobal::GetRscString(STR_EMPTYDATA
);
1803 pDoc
->SetString(nCol
, nRow
, nDestTab
, aStr
);
1805 SCROW nSaveRow
= nRow
;
1806 ColToTable(nField
+ 1, nRow
, rProgress
);
1807 SetStyle(nCol
, nSaveRow
, nCol
, nRow
- 1, PIVOT_STYLE_CATEGORY
);
1808 SetFrame(nCol
, nSaveRow
, nCol
, nRow
- 1);
1809 if (aColArr
[nField
].nFuncCount
> 0) // Zwischenergebnisse eingestellt?
1812 for (SCSIZE j
=0; j
<=PIVOT_MAXFUNC
; j
++) // incl. "auto"
1814 if (aColArr
[nField
].nFuncMask
& nFuncMaskArr
[j
])
1819 for (SCSIZE k
=0; k
< nDataCount
; k
++)
1821 String aDataStr
= pDataList
->GetString(sal::static_int_cast
<USHORT
>(k
)); // always String
1824 if ( j
==PIVOT_MAXFUNC
)
1825 nFuncType
= lcl_MaskToIndex( aDataArr
[k
].nFuncMask
);
1829 aLab
+= *pLabel
[nFuncType
];
1832 pDoc
->SetString(nCol
, nRow
, nDestTab
, aLab
);
1834 SetFuncLine(nDataStartCol
, nRow
, nDestTab
, nFuncMaskArr
[j
], k
, nSaveIndex
, nRowIndex
);
1843 pDoc
->SetString(nCol
, nRow
, nDestTab
, aLab
);
1845 SetFuncLine(nDataStartCol
, nRow
, nDestTab
, nFuncMaskArr
[j
], SCSIZE_MAX
, nSaveIndex
, nRowIndex
);
1850 if ( nDataStartCol
> 0 )
1851 SetStyle(nCol
, nSaveRow
, nDataStartCol
-1, nRow
-1, PIVOT_STYLE_TITLE
);
1852 SetStyle(nDataStartCol
, nSaveRow
, nDestCol2
, nRow
-1, PIVOT_STYLE_RESULT
);
1853 SetFrameHor(nCol
, nSaveRow
, nDestCol2
, nRow
-1);
1855 nSaveIndex
= nRowIndex
;
1858 else if (nField
< nColCount
)
1860 SCSIZE nCatCount
= pColList
[nField
]->GetCount();
1861 SetStyle(nCol
, nRow
, nCol
, nRow
+nCatCount
-1, PIVOT_STYLE_CATEGORY
);
1862 SetFrame(nCol
, nRow
, nDestCol2
, nRow
+nCatCount
-1);
1863 for (SCSIZE i
= 0; i
< nCatCount
; i
++)
1865 String aTmpStr
= pColList
[nField
]->GetString(sal::static_int_cast
<USHORT
>(i
));
1866 if (!aTmpStr
.Len()) aTmpStr
= ScGlobal::GetRscString(STR_EMPTYDATA
);
1869 if (pColList
[nField
] == pDataList
)
1871 SCSIZE nFuncType
= lcl_MaskToIndex( aDataArr
[i
].nFuncMask
);
1872 aPutStr
= *pLabel
[nFuncType
];
1879 pDoc
->SetString(nCol
, nRow
, nDestTab
, aPutStr
);
1881 SetDataLine(nCol
+ 1, nRow
, nDestTab
, nRowIndex
);
1885 rProgress
.SetState( nRow
- nDestRow1
);
1890 void ScPivot::RowToTable(SCSIZE nField
, SCCOL
& nCol
)
1893 SCROW nRow
= nDestRow1
+ nFirstLine
+ nField
+ 1;
1896 pColRef
[nColIndex
].nDataIndex
= nDataIndex
;
1903 if ((aRowArr
[nRowCount
-1].nCol
== PIVOT_DATA_FIELD
) && (nDataCount
== 1))
1908 if (nField
< nRowCount
- nDx
)
1910 for (USHORT i
= 0; i
< pRowList
[nField
]->GetCount(); i
++)
1912 String aStr
= pRowList
[nField
]->GetString(i
);
1913 if (!aStr
.Len()) aStr
= ScGlobal::GetRscString(STR_EMPTYDATA
);
1914 pDoc
->SetString(nCol
, nRow
, nDestTab
, aStr
);
1916 SCCOL nSaveCol
= nCol
;
1917 RowToTable(nField
+ 1, nCol
);
1918 SetStyle(nSaveCol
, nRow
, nCol
- 1, nRow
, PIVOT_STYLE_CATEGORY
);
1919 SetFrame(nSaveCol
, nRow
, nCol
- 1, nRow
);
1920 if (aRowArr
[nField
].nFuncCount
> 0)
1923 for (SCSIZE j
=0; j
<=PIVOT_MAXFUNC
; j
++) // incl. "auto"
1925 if (aRowArr
[nField
].nFuncMask
& nFuncMaskArr
[j
])
1930 for (SCSIZE k
=0; k
< nDataCount
; k
++)
1934 if ( j
==PIVOT_MAXFUNC
)
1935 nFuncType
= lcl_MaskToIndex( aDataArr
[k
].nFuncMask
);
1939 aLab
+= *pLabel
[nFuncType
];
1941 aLab
+= pDataList
->GetString(sal::static_int_cast
<USHORT
>(k
));
1942 pDoc
->SetString(nCol
, nRow
, nDestTab
, aLab
);
1944 pColRef
[nColIndex
].nDataIndex
= PIVOT_FUNC_REF
;
1945 pColRef
[nColIndex
].nRecCount
= nRecCount
;
1946 pColRef
[nColIndex
].nIndex
= k
;
1947 pColRef
[nColIndex
].nFuncMask
= nFuncMaskArr
[j
];
1957 pDoc
->SetString(nCol
, nRow
, nDestTab
, aLab
);
1959 pColRef
[nColIndex
].nDataIndex
= PIVOT_FUNC_REF
;
1960 pColRef
[nColIndex
].nRecCount
= nRecCount
;
1961 pColRef
[nColIndex
].nIndex
= SCSIZE_MAX
;
1962 pColRef
[nColIndex
].nFuncMask
= nFuncMaskArr
[j
];
1968 if ( nDataStartRow
> 0 )
1969 SetStyle(nSaveCol
, nRow
,
1970 nCol
-1, nDataStartRow
-1, PIVOT_STYLE_TITLE
);
1971 SetStyle(nSaveCol
, nDataStartRow
, nCol
-1, nDestRow2
, PIVOT_STYLE_RESULT
);
1972 SetFrameVer(nSaveCol
, nRow
, nCol
-1, nDestRow2
);
1976 else if (nField
< nRowCount
)
1978 SCSIZE nCatCount
= pRowList
[nField
]->GetCount();
1979 SetStyle(nCol
, nRow
, sal::static_int_cast
<SCCOL
>(nCol
+nCatCount
-1), nRow
, PIVOT_STYLE_CATEGORY
);
1980 SetFrame(nCol
, nRow
, sal::static_int_cast
<SCCOL
>(nCol
+nCatCount
-1), nDestRow2
);
1981 for (SCSIZE i
= 0; i
< nCatCount
; i
++)
1983 String aTmpStr
= pRowList
[nField
]->GetString(sal::static_int_cast
<USHORT
>(i
));
1984 if (!aTmpStr
.Len()) aTmpStr
= ScGlobal::GetRscString(STR_EMPTYDATA
);
1987 if (pRowList
[nField
] == pDataList
)
1989 SCSIZE nFuncType
= lcl_MaskToIndex( aDataArr
[i
].nFuncMask
);
1990 aPutStr
= *pLabel
[nFuncType
];
1997 pDoc
->SetString(nCol
, nRow
, nDestTab
, aPutStr
);
1999 pColRef
[nColIndex
].nDataIndex
= nDataIndex
;
2000 pColRef
[nColIndex
].nRecCount
= nRecCount
;
2001 pColRef
[nColIndex
].nIndex
= SCSIZE_MAX
;
2002 pColRef
[nColIndex
].nFuncMask
= PIVOT_FUNC_NONE
;
2011 SCROW
ScPivot::GetCategoryRow( SCCOL nCol
, SCROW nRow
)
2013 SCROW nMinRow
= nSrcRow1
;
2014 if (bHasHeader
) ++nMinRow
;
2015 BOOL bFound
= FALSE
;
2018 if ( !pDoc
->HasData( nCol
, nRow
, nSrcTab
) && nRow
>nMinRow
)