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 BOOL
lcl_HasQuery( const ScQueryParam
& rParam
)
145 return rParam
.GetEntryCount() > 0 &&
146 rParam
.GetEntry(0).bDoQuery
;
149 const TypedScStrCollection
& ScSheetDPData::GetColumnEntries(long nColumn
)
151 DBG_ASSERT(nColumn
>=0 && nColumn
< pImpl
->aCacheTable
.getColSize(), "ScSheetDPData: wrong column");
153 return pImpl
->aCacheTable
.getFieldEntries(nColumn
);
156 String
ScSheetDPData::getDimensionName(long nColumn
)
159 if (getIsDataLayoutDimension(nColumn
))
161 //! different internal and display names?
163 return ScGlobal::GetRscString(STR_PIVOT_DATA
);
165 else if (nColumn
>= pImpl
->aCacheTable
.getColSize())
167 DBG_ERROR("getDimensionName: invalid dimension");
172 const String
* pStr
= pImpl
->aCacheTable
.getFieldName(nColumn
);
175 else return String();
179 BOOL
lcl_HasDateFormat( ScDocument
* pDoc
, const ScRange
& rRange
)
181 //! iterate formats in range?
183 ScAddress aPos
= rRange
.aStart
;
184 aPos
.SetRow( aPos
.Row() + 1 ); // below title
185 ULONG nFormat
= pDoc
->GetNumberFormat( aPos
);
186 SvNumberFormatter
* pFormatter
= pDoc
->GetFormatTable();
187 return ( pFormatter
->GetType(nFormat
) & NUMBERFORMAT_DATE
) != 0;
190 BOOL
ScSheetDPData::IsDateDimension(long nDim
)
193 long nColCount
= pImpl
->aCacheTable
.getColSize();
194 if (getIsDataLayoutDimension(nDim
))
198 else if (nDim
>= nColCount
)
200 DBG_ERROR("IsDateDimension: invalid dimension");
205 if (!pImpl
->pDateDim
)
207 pImpl
->pDateDim
= new BOOL
[nColCount
];
208 ScRange aTestRange
= pImpl
->aRange
;
209 for (long i
= 0; i
< nColCount
; ++i
)
211 SCCOL nCol
= (SCCOL
)( pImpl
->aRange
.aStart
.Col() + i
);
212 aTestRange
.aStart
.SetCol(nCol
);
213 aTestRange
.aEnd
.SetCol(nCol
);
214 pImpl
->pDateDim
[i
] = lcl_HasDateFormat( pImpl
->pDoc
, aTestRange
);
217 return pImpl
->pDateDim
[nDim
];
221 UINT32
ScSheetDPData::GetNumberFormat(long nDim
)
224 if (getIsDataLayoutDimension(nDim
))
228 else if (nDim
>= pImpl
->aCacheTable
.getColSize())
230 DBG_ERROR("GetNumberFormat: invalid dimension");
235 // is queried only once per dimension from ScDPOutput -> no need to cache
237 ScAddress aPos
= pImpl
->aRange
.aStart
;
238 aPos
.SetCol( sal::static_int_cast
<SCCOL
>( aPos
.Col() + nDim
) );
239 aPos
.SetRow( aPos
.Row() + 1 ); // below title
240 return pImpl
->pDoc
->GetNumberFormat( aPos
);
244 BOOL
ScSheetDPData::getIsDataLayoutDimension(long nColumn
)
247 return (nColumn
== pImpl
->aCacheTable
.getColSize());
250 void ScSheetDPData::SetEmptyFlags( BOOL bIgnoreEmptyRows
, BOOL bRepeatIfEmpty
)
252 pImpl
->bIgnoreEmptyRows
= bIgnoreEmptyRows
;
253 pImpl
->bRepeatIfEmpty
= bRepeatIfEmpty
;
256 bool ScSheetDPData::IsRepeatIfEmpty()
258 return pImpl
->bRepeatIfEmpty
;
261 void ScSheetDPData::CreateCacheTable()
263 // Scan and store the data from the source range.
264 if (!pImpl
->aCacheTable
.empty())
268 pImpl
->aCacheTable
.fillTable(pImpl
->pDoc
, pImpl
->aRange
, pImpl
->aQuery
, pImpl
->pSpecial
,
269 pImpl
->bIgnoreEmptyRows
);
272 void ScSheetDPData::FilterCacheTable(const vector
<ScDPCacheTable::Criterion
>& rCriteria
, const hash_set
<sal_Int32
>& rCatDims
)
275 pImpl
->aCacheTable
.filterByPageDimension(
276 rCriteria
, (IsRepeatIfEmpty() ? rCatDims
: hash_set
<sal_Int32
>()));
279 void ScSheetDPData::GetDrillDownData(const vector
<ScDPCacheTable::Criterion
>& rCriteria
, const hash_set
<sal_Int32
>& rCatDims
, Sequence
< Sequence
<Any
> >& rData
)
282 sal_Int32 nRowSize
= pImpl
->aCacheTable
.getRowSize();
286 pImpl
->aCacheTable
.filterTable(
287 rCriteria
, rData
, IsRepeatIfEmpty() ? rCatDims
: hash_set
<sal_Int32
>());
290 void ScSheetDPData::CalcResults(CalcInfo
& rInfo
, bool bAutoShow
)
293 CalcResultsFromCacheTable(pImpl
->aCacheTable
, rInfo
, bAutoShow
);
296 const ScDPCacheTable
& ScSheetDPData::GetCacheTable() const
298 return pImpl
->aCacheTable
;
301 // -----------------------------------------------------------------------