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: dpshttab.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 // INCLUDE --------------------------------------------------------------
38 #include <tools/debug.hxx>
39 #include <svtools/zforlist.hxx>
41 #include "dpshttab.hxx"
42 #include "dptabres.hxx"
43 #include "document.hxx"
44 #include "collect.hxx"
46 #include "dpcachetable.hxx"
47 #include "dpobject.hxx"
48 #include "globstr.hrc"
50 #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
55 using namespace ::com::sun::star
;
56 using ::com::sun::star::uno::Any
;
57 using ::com::sun::star::uno::Sequence
;
59 using ::std::hash_map
;
60 using ::std::hash_set
;
62 // -----------------------------------------------------------------------
64 class ScSheetDPData_Impl
70 BOOL
* pSpecial
; // to flag special handling of query parameters in ValidQuery.
71 BOOL bIgnoreEmptyRows
;
74 SCROW nNextRow
; // for iterator, within range
76 ScDPCacheTable aCacheTable
;
78 ScSheetDPData_Impl(ScDPCollection
* p
) :
85 // -----------------------------------------------------------------------
87 ScSheetDPData::ScSheetDPData( ScDocument
* pD
, const ScSheetSourceDesc
& rDesc
) :
90 pImpl
= new ScSheetDPData_Impl(pD
->GetDPCollection());
92 pImpl
->aRange
= rDesc
.aSourceRange
;
93 pImpl
->aQuery
= rDesc
.aQueryParam
;
94 pImpl
->bIgnoreEmptyRows
= FALSE
;
95 pImpl
->bRepeatIfEmpty
= FALSE
;
96 pImpl
->pDateDim
= NULL
;
98 pImpl
->nNextRow
= pImpl
->aRange
.aStart
.Row() + 1;
100 SCSIZE
nEntryCount(pImpl
->aQuery
.GetEntryCount());
101 pImpl
->pSpecial
= new BOOL
[nEntryCount
];
102 for (SCSIZE j
= 0; j
< nEntryCount
; ++j
)
104 ScQueryEntry
& rEntry
= pImpl
->aQuery
.GetEntry(j
);
107 pImpl
->pSpecial
[j
] = false;
108 if (!rEntry
.bQueryByString
)
110 if (*rEntry
.pStr
== EMPTY_STRING
&&
111 ((rEntry
.nVal
== SC_EMPTYFIELDS
) || (rEntry
.nVal
== SC_NONEMPTYFIELDS
)))
112 pImpl
->pSpecial
[j
] = true;
116 sal_uInt32 nIndex
= 0;
117 rEntry
.bQueryByString
=
118 !(pD
->GetFormatTable()->
119 IsNumberFormat(*rEntry
.pStr
, nIndex
, rEntry
.nVal
));
125 ScSheetDPData::~ScSheetDPData()
127 delete[] pImpl
->pDateDim
;
128 delete[] pImpl
->pSpecial
;
132 void ScSheetDPData::DisposeData()
134 pImpl
->aCacheTable
.clear();
137 long ScSheetDPData::GetColumnCount()
140 return pImpl
->aCacheTable
.getColSize();
143 const TypedScStrCollection
& ScSheetDPData::GetColumnEntries(long nColumn
)
145 DBG_ASSERT(nColumn
>=0 && nColumn
< pImpl
->aCacheTable
.getColSize(), "ScSheetDPData: wrong column");
147 return pImpl
->aCacheTable
.getFieldEntries(nColumn
);
150 String
ScSheetDPData::getDimensionName(long nColumn
)
153 if (getIsDataLayoutDimension(nColumn
))
155 //! different internal and display names?
157 return ScGlobal::GetRscString(STR_PIVOT_DATA
);
159 else if (nColumn
>= pImpl
->aCacheTable
.getColSize())
161 DBG_ERROR("getDimensionName: invalid dimension");
166 const String
* pStr
= pImpl
->aCacheTable
.getFieldName(nColumn
);
169 else return String();
173 BOOL
lcl_HasDateFormat( ScDocument
* pDoc
, const ScRange
& rRange
)
175 //! iterate formats in range?
177 ScAddress aPos
= rRange
.aStart
;
178 aPos
.SetRow( aPos
.Row() + 1 ); // below title
179 ULONG nFormat
= pDoc
->GetNumberFormat( aPos
);
180 SvNumberFormatter
* pFormatter
= pDoc
->GetFormatTable();
181 return ( pFormatter
->GetType(nFormat
) & NUMBERFORMAT_DATE
) != 0;
184 BOOL
ScSheetDPData::IsDateDimension(long nDim
)
187 long nColCount
= pImpl
->aCacheTable
.getColSize();
188 if (getIsDataLayoutDimension(nDim
))
192 else if (nDim
>= nColCount
)
194 DBG_ERROR("IsDateDimension: invalid dimension");
199 if (!pImpl
->pDateDim
)
201 pImpl
->pDateDim
= new BOOL
[nColCount
];
202 ScRange aTestRange
= pImpl
->aRange
;
203 for (long i
= 0; i
< nColCount
; ++i
)
205 SCCOL nCol
= (SCCOL
)( pImpl
->aRange
.aStart
.Col() + i
);
206 aTestRange
.aStart
.SetCol(nCol
);
207 aTestRange
.aEnd
.SetCol(nCol
);
208 pImpl
->pDateDim
[i
] = lcl_HasDateFormat( pImpl
->pDoc
, aTestRange
);
211 return pImpl
->pDateDim
[nDim
];
215 UINT32
ScSheetDPData::GetNumberFormat(long nDim
)
218 if (getIsDataLayoutDimension(nDim
))
222 else if (nDim
>= pImpl
->aCacheTable
.getColSize())
224 DBG_ERROR("GetNumberFormat: invalid dimension");
229 // is queried only once per dimension from ScDPOutput -> no need to cache
231 ScAddress aPos
= pImpl
->aRange
.aStart
;
232 aPos
.SetCol( sal::static_int_cast
<SCCOL
>( aPos
.Col() + nDim
) );
233 aPos
.SetRow( aPos
.Row() + 1 ); // below title
234 return pImpl
->pDoc
->GetNumberFormat( aPos
);
238 BOOL
ScSheetDPData::getIsDataLayoutDimension(long nColumn
)
241 return (nColumn
== pImpl
->aCacheTable
.getColSize());
244 void ScSheetDPData::SetEmptyFlags( BOOL bIgnoreEmptyRows
, BOOL bRepeatIfEmpty
)
246 pImpl
->bIgnoreEmptyRows
= bIgnoreEmptyRows
;
247 pImpl
->bRepeatIfEmpty
= bRepeatIfEmpty
;
250 bool ScSheetDPData::IsRepeatIfEmpty()
252 return pImpl
->bRepeatIfEmpty
;
255 void ScSheetDPData::CreateCacheTable()
257 // Scan and store the data from the source range.
258 if (!pImpl
->aCacheTable
.empty())
262 pImpl
->aCacheTable
.fillTable(pImpl
->pDoc
, pImpl
->aRange
, pImpl
->aQuery
, pImpl
->pSpecial
,
263 pImpl
->bIgnoreEmptyRows
);
266 void ScSheetDPData::FilterCacheTable(const vector
<ScDPCacheTable::Criterion
>& rCriteria
, const hash_set
<sal_Int32
>& rCatDims
)
269 pImpl
->aCacheTable
.filterByPageDimension(
270 rCriteria
, (IsRepeatIfEmpty() ? rCatDims
: hash_set
<sal_Int32
>()));
273 void ScSheetDPData::GetDrillDownData(const vector
<ScDPCacheTable::Criterion
>& rCriteria
, const hash_set
<sal_Int32
>& rCatDims
, Sequence
< Sequence
<Any
> >& rData
)
276 sal_Int32 nRowSize
= pImpl
->aCacheTable
.getRowSize();
280 pImpl
->aCacheTable
.filterTable(
281 rCriteria
, rData
, IsRepeatIfEmpty() ? rCatDims
: hash_set
<sal_Int32
>());
284 void ScSheetDPData::CalcResults(CalcInfo
& rInfo
, bool bAutoShow
)
287 CalcResultsFromCacheTable(pImpl
->aCacheTable
, rInfo
, bAutoShow
);
290 const ScDPCacheTable
& ScSheetDPData::GetCacheTable() const
292 return pImpl
->aCacheTable
;
295 // -----------------------------------------------------------------------