Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <svl/zforlist.hxx>
30 : :
31 : : #include "dpshttab.hxx"
32 : : #include "dptabres.hxx"
33 : : #include "document.hxx"
34 : : #include "cell.hxx"
35 : : #include "dpcachetable.hxx"
36 : : #include "dpobject.hxx"
37 : : #include "globstr.hrc"
38 : : #include "rangenam.hxx"
39 : : #include "queryentry.hxx"
40 : :
41 : : #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
42 : :
43 : : #include <vector>
44 : : #include <set>
45 : :
46 : : using namespace ::com::sun::star;
47 : : using ::com::sun::star::uno::Any;
48 : : using ::com::sun::star::uno::Sequence;
49 : : using ::rtl::OUString;
50 : : using ::std::vector;
51 : :
52 : : // -----------------------------------------------------------------------
53 : :
54 : 117 : ScSheetDPData::ScSheetDPData(ScDocument* pD, const ScSheetSourceDesc& rDesc, const ScDPCache* pCache) :
55 : : ScDPTableData(pD),
56 : 117 : aQuery ( rDesc.GetQueryParam() ),
57 : : bIgnoreEmptyRows( false ),
58 : : bRepeatIfEmpty(false),
59 : : mrDesc(rDesc),
60 [ + - ][ + - ]: 234 : aCacheTable(pCache)
61 : : {
62 [ + - ]: 117 : SCSIZE nEntryCount( aQuery.GetEntryCount());
63 [ + + ]: 1053 : for (SCSIZE j = 0; j < nEntryCount; ++j)
64 : : {
65 [ + - ]: 936 : ScQueryEntry& rEntry = aQuery.GetEntry(j);
66 [ + + ]: 936 : if (rEntry.bDoQuery)
67 : : {
68 [ + - ]: 19 : ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
69 [ - + ]: 19 : if (rItem.meType == ScQueryEntry::ByString)
70 : : {
71 : 0 : sal_uInt32 nIndex = 0;
72 : : bool bNumber = pD->GetFormatTable()->IsNumberFormat(
73 [ # # ][ # # ]: 0 : rItem.maString, nIndex, rItem.mfVal);
[ # # ][ # # ]
74 [ # # ]: 0 : rItem.meType = bNumber ? ScQueryEntry::ByValue : ScQueryEntry::ByString;
75 : : }
76 : : }
77 : : }
78 : 117 : }
79 : :
80 [ + - ][ + - ]: 117 : ScSheetDPData::~ScSheetDPData()
81 : : {
82 [ - + ]: 234 : }
83 : :
84 : 6 : void ScSheetDPData::DisposeData()
85 : : {
86 : 6 : aCacheTable.clear();
87 : 6 : }
88 : :
89 : 36938 : long ScSheetDPData::GetColumnCount()
90 : : {
91 : 36938 : CreateCacheTable();
92 : 36938 : return aCacheTable.getColSize();
93 : : }
94 : :
95 : 39000 : rtl::OUString ScSheetDPData::getDimensionName(long nColumn)
96 : : {
97 : 39000 : CreateCacheTable();
98 [ + + ]: 39000 : if (getIsDataLayoutDimension(nColumn))
99 : : {
100 : : //! different internal and display names?
101 : : //return "Data";
102 : 2961 : return ScGlobal::GetRscString(STR_PIVOT_DATA);
103 : : }
104 [ - + ]: 36039 : else if (nColumn >= aCacheTable.getColSize())
105 : : {
106 : : OSL_FAIL("getDimensionName: invalid dimension");
107 : 0 : return rtl::OUString();
108 : : }
109 : : else
110 : : {
111 : 39000 : return aCacheTable.getFieldName(static_cast<SCCOL>(nColumn));
112 : : }
113 : : }
114 : :
115 : 3163 : sal_Bool ScSheetDPData::IsDateDimension(long nDim)
116 : : {
117 : 3163 : CreateCacheTable();
118 : 3163 : long nColCount = aCacheTable.getColSize();
119 [ + + ]: 3163 : if (getIsDataLayoutDimension(nDim))
120 : : {
121 : 510 : return false;
122 : : }
123 [ - + ]: 2653 : else if (nDim >= nColCount)
124 : : {
125 : : OSL_FAIL("IsDateDimension: invalid dimension");
126 : 0 : return false;
127 : : }
128 : : else
129 : : {
130 : 3163 : return GetCacheTable().getCache()->IsDateDimension( nDim);
131 : : }
132 : : }
133 : :
134 : 214 : sal_uLong ScSheetDPData::GetNumberFormat(long nDim)
135 : : {
136 : 214 : CreateCacheTable();
137 [ - + ]: 214 : if (getIsDataLayoutDimension(nDim))
138 : : {
139 : 0 : return 0;
140 : : }
141 [ - + ]: 214 : else if (nDim >= GetCacheTable().getColSize())
142 : : {
143 : : OSL_FAIL("GetNumberFormat: invalid dimension");
144 : 0 : return 0;
145 : : }
146 : : else
147 : : {
148 : 214 : return GetCacheTable().getCache()->GetNumberFormat( nDim );
149 : : }
150 : : }
151 : 0 : sal_uInt32 ScDPTableData::GetNumberFormatByIdx( NfIndexTableOffset eIdx )
152 : : {
153 [ # # ]: 0 : if( !mpDoc )
154 : 0 : return 0;
155 : :
156 [ # # ]: 0 : if ( SvNumberFormatter* pFormatter = mpDoc->GetFormatTable() )
157 : 0 : return pFormatter->GetFormatIndex( eIdx, LANGUAGE_SYSTEM );
158 : :
159 : 0 : return 0;
160 : : }
161 : :
162 : 49526 : sal_Bool ScSheetDPData::getIsDataLayoutDimension(long nColumn)
163 : : {
164 : 49526 : CreateCacheTable();
165 : 49526 : return (nColumn ==(long)( aCacheTable.getColSize()));
166 : : }
167 : :
168 : 704 : void ScSheetDPData::SetEmptyFlags( sal_Bool bIgnoreEmptyRowsP, sal_Bool bRepeatIfEmptyP )
169 : : {
170 : 704 : bIgnoreEmptyRows = bIgnoreEmptyRowsP;
171 : 704 : bRepeatIfEmpty = bRepeatIfEmptyP;
172 : 704 : }
173 : :
174 : 1579 : bool ScSheetDPData::IsRepeatIfEmpty()
175 : : {
176 : 1579 : return bRepeatIfEmpty;
177 : : }
178 : :
179 : 129326 : void ScSheetDPData::CreateCacheTable()
180 : : {
181 : : // Scan and store the data from the source range.
182 [ + + ]: 129326 : if (!aCacheTable.empty())
183 : : // already cached.
184 : 128814 : return;
185 : :
186 [ - + ]: 512 : if (!aCacheTable.hasCache())
187 : : {
188 : : OSL_FAIL("Cache table should be created with a live data cache instance at all times.");
189 : : // This better not happen!! The cache table should be created with a
190 : : // live data cache at all times.
191 : 0 : return;
192 : : }
193 : :
194 : 129326 : aCacheTable.fillTable(aQuery, bIgnoreEmptyRows, bRepeatIfEmpty);
195 : : }
196 : :
197 : 6 : void ScSheetDPData::FilterCacheTable(const vector<ScDPCacheTable::Criterion>& rCriteria, const boost::unordered_set<sal_Int32>& rCatDims)
198 : : {
199 : 6 : CreateCacheTable();
200 : : aCacheTable.filterByPageDimension(
201 [ # # ][ + - ]: 6 : rCriteria, (IsRepeatIfEmpty() ? rCatDims : boost::unordered_set<sal_Int32>()));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ # #
# # # # ]
[ - + ]
202 : 6 : }
203 : :
204 : 158 : void ScSheetDPData::GetDrillDownData(const vector<ScDPCacheTable::Criterion>& rCriteria, const boost::unordered_set<sal_Int32>& rCatDims, Sequence< Sequence<Any> >& rData)
205 : : {
206 : 158 : CreateCacheTable();
207 : 158 : sal_Int32 nRowSize = aCacheTable.getRowSize();
208 [ - + ]: 158 : if (!nRowSize)
209 : 158 : return;
210 : :
211 : : aCacheTable.filterTable(
212 [ - + ][ # # ]: 158 : rCriteria, rData, IsRepeatIfEmpty() ? rCatDims : boost::unordered_set<sal_Int32>());
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ # # # #
# # ]
213 : : }
214 : :
215 : 122 : void ScSheetDPData::CalcResults(CalcInfo& rInfo, bool bAutoShow)
216 : : {
217 : 122 : CreateCacheTable();
218 : 122 : CalcResultsFromCacheTable(aCacheTable, rInfo, bAutoShow);
219 : 122 : }
220 : :
221 : 20878 : const ScDPCacheTable& ScSheetDPData::GetCacheTable() const
222 : : {
223 : 20878 : return aCacheTable;
224 : : }
225 : :
226 : 179 : void ScSheetDPData::ReloadCacheTable()
227 : : {
228 : 179 : aCacheTable.clear();
229 : 179 : CreateCacheTable();
230 : 179 : }
231 : :
232 : 89 : ScSheetSourceDesc::ScSheetSourceDesc(ScDocument* pDoc) :
233 [ + - ]: 89 : mpDoc(pDoc) {}
234 : :
235 : 133 : void ScSheetSourceDesc::SetSourceRange(const ScRange& rRange)
236 : : {
237 : 133 : maSourceRange = rRange;
238 : 133 : maRangeName = OUString(); // overwrite existing range name if any.
239 : 133 : }
240 : :
241 : 613 : const ScRange& ScSheetSourceDesc::GetSourceRange() const
242 : : {
243 [ + + ]: 613 : if (!maRangeName.isEmpty())
244 : : {
245 : : // Obtain the source range from the range name first.
246 : 9 : maSourceRange = ScRange();
247 : 9 : ScRangeName* pRangeName = mpDoc->GetRangeName();
248 : : do
249 : : {
250 [ + - ]: 9 : if (!pRangeName)
251 : : break;
252 : :
253 [ + - ]: 9 : OUString aUpper = ScGlobal::pCharClass->uppercase(maRangeName);
254 [ + - ]: 9 : const ScRangeData* pData = pRangeName->findByUpperName(aUpper);
255 [ - + ]: 9 : if (!pData)
256 : : break;
257 : :
258 : : // range name found. Fow now, we only use the first token and
259 : : // ignore the rest.
260 : 9 : ScRange aRange;
261 [ - + ][ + - ]: 9 : if (!pData->IsReference(aRange))
262 : : break;
263 : :
264 [ + - ]: 9 : maSourceRange = aRange;
265 : : }
266 : : while (false);
267 : : }
268 : 613 : return maSourceRange;
269 : : }
270 : :
271 : 3 : void ScSheetSourceDesc::SetRangeName(const OUString& rName)
272 : : {
273 : 3 : maRangeName = rName;
274 : 3 : }
275 : :
276 : 76 : const OUString& ScSheetSourceDesc::GetRangeName() const
277 : : {
278 : 76 : return maRangeName;
279 : : }
280 : :
281 : 171 : bool ScSheetSourceDesc::HasRangeName() const
282 : : {
283 : 171 : return !maRangeName.isEmpty();
284 : : }
285 : :
286 : 169 : void ScSheetSourceDesc::SetQueryParam(const ScQueryParam& rParam)
287 : : {
288 : 169 : maQueryParam = rParam;
289 : 169 : }
290 : :
291 : 280 : const ScQueryParam& ScSheetSourceDesc::GetQueryParam() const
292 : : {
293 : 280 : return maQueryParam;
294 : : }
295 : :
296 : 28 : bool ScSheetSourceDesc::operator== (const ScSheetSourceDesc& rOther) const
297 : : {
298 : 28 : return maSourceRange == rOther.maSourceRange &&
299 : 4 : maRangeName == rOther.maRangeName &&
300 [ - + ]: 32 : maQueryParam == rOther.maQueryParam;
[ + + + - ]
301 : : }
302 : :
303 : 117 : const ScDPCache* ScSheetSourceDesc::CreateCache(const ScDPDimensionSaveData* pDimData) const
304 : : {
305 [ - + ]: 117 : if (!mpDoc)
306 : 0 : return NULL;
307 : :
308 : 117 : sal_uLong nErrId = CheckSourceRange();
309 [ - + ]: 117 : if (nErrId)
310 : : {
311 : : OSL_FAIL( "Error Create Cache\n" );
312 : 0 : return NULL;
313 : : }
314 : :
315 : : // All cache instances are managed centrally by ScDPCollection.
316 : 117 : ScDPCollection* pDPs = mpDoc->GetDPCollection();
317 [ + + ]: 117 : if (HasRangeName())
318 : : {
319 : : // Name-based data source.
320 : 3 : ScDPCollection::NameCaches& rCaches = pDPs->GetNameCaches();
321 : 3 : return rCaches.getCache(GetRangeName(), GetSourceRange(), pDimData);
322 : : }
323 : :
324 : 114 : ScDPCollection::SheetCaches& rCaches = pDPs->GetSheetCaches();
325 : 117 : return rCaches.getCache(GetSourceRange(), pDimData);
326 : : }
327 : :
328 : 130 : sal_uLong ScSheetSourceDesc::CheckSourceRange() const
329 : : {
330 [ - + ]: 130 : if (!mpDoc)
331 : 0 : return STR_ERR_DATAPILOTSOURCE;
332 : :
333 : 130 : return 0;
334 [ + - ][ + - ]: 153 : }
335 : :
336 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|