Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <svl/zforlist.hxx>
21 :
22 : #include "dpshttab.hxx"
23 : #include "dptabres.hxx"
24 : #include "document.hxx"
25 : #include "formulacell.hxx"
26 : #include "dpfilteredcache.hxx"
27 : #include "dpobject.hxx"
28 : #include "globstr.hrc"
29 : #include "rangenam.hxx"
30 : #include "queryentry.hxx"
31 :
32 : #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
33 :
34 : #include <vector>
35 : #include <set>
36 :
37 : using namespace ::com::sun::star;
38 : using ::com::sun::star::uno::Any;
39 : using ::com::sun::star::uno::Sequence;
40 : using ::std::vector;
41 :
42 : // -----------------------------------------------------------------------
43 :
44 74 : ScSheetDPData::ScSheetDPData(ScDocument* pD, const ScSheetSourceDesc& rDesc, const ScDPCache& rCache) :
45 : ScDPTableData(pD),
46 74 : aQuery ( rDesc.GetQueryParam() ),
47 : bIgnoreEmptyRows( false ),
48 : bRepeatIfEmpty(false),
49 148 : aCacheTable(rCache)
50 : {
51 74 : SCSIZE nEntryCount( aQuery.GetEntryCount());
52 666 : for (SCSIZE j = 0; j < nEntryCount; ++j)
53 : {
54 592 : ScQueryEntry& rEntry = aQuery.GetEntry(j);
55 592 : if (rEntry.bDoQuery)
56 : {
57 11 : ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
58 11 : if (rItem.meType == ScQueryEntry::ByString)
59 : {
60 0 : sal_uInt32 nIndex = 0;
61 : bool bNumber = pD->GetFormatTable()->IsNumberFormat(
62 0 : rItem.maString, nIndex, rItem.mfVal);
63 0 : rItem.meType = bNumber ? ScQueryEntry::ByValue : ScQueryEntry::ByString;
64 : }
65 : }
66 : }
67 74 : }
68 :
69 148 : ScSheetDPData::~ScSheetDPData()
70 : {
71 148 : }
72 :
73 8 : void ScSheetDPData::DisposeData()
74 : {
75 8 : aCacheTable.clear();
76 8 : }
77 :
78 21261 : long ScSheetDPData::GetColumnCount()
79 : {
80 21261 : CreateCacheTable();
81 21261 : return aCacheTable.getColSize();
82 : }
83 :
84 27010 : OUString ScSheetDPData::getDimensionName(long nColumn)
85 : {
86 27010 : CreateCacheTable();
87 27010 : if (getIsDataLayoutDimension(nColumn))
88 : {
89 : //! different internal and display names?
90 : //return "Data";
91 1964 : return ScGlobal::GetRscString(STR_PIVOT_DATA);
92 : }
93 25046 : else if (nColumn >= aCacheTable.getColSize())
94 : {
95 : OSL_FAIL("getDimensionName: invalid dimension");
96 0 : return OUString();
97 : }
98 : else
99 : {
100 25046 : return aCacheTable.getFieldName(static_cast<SCCOL>(nColumn));
101 : }
102 : }
103 :
104 1717 : sal_Bool ScSheetDPData::IsDateDimension(long nDim)
105 : {
106 1717 : CreateCacheTable();
107 1717 : long nColCount = aCacheTable.getColSize();
108 1717 : if (getIsDataLayoutDimension(nDim))
109 : {
110 249 : return false;
111 : }
112 1468 : else if (nDim >= nColCount)
113 : {
114 : OSL_FAIL("IsDateDimension: invalid dimension");
115 0 : return false;
116 : }
117 : else
118 : {
119 1468 : return GetCacheTable().getCache()->IsDateDimension( nDim);
120 : }
121 : }
122 :
123 550 : sal_uLong ScSheetDPData::GetNumberFormat(long nDim)
124 : {
125 550 : CreateCacheTable();
126 550 : if (getIsDataLayoutDimension(nDim))
127 : {
128 78 : return 0;
129 : }
130 472 : else if (nDim >= GetCacheTable().getColSize())
131 : {
132 : OSL_FAIL("GetNumberFormat: invalid dimension");
133 0 : return 0;
134 : }
135 : else
136 : {
137 472 : return GetCacheTable().getCache()->GetNumberFormat( nDim );
138 : }
139 : }
140 6 : sal_uInt32 ScDPTableData::GetNumberFormatByIdx( NfIndexTableOffset eIdx )
141 : {
142 6 : if( !mpDoc )
143 0 : return 0;
144 :
145 6 : if ( SvNumberFormatter* pFormatter = mpDoc->GetFormatTable() )
146 6 : return pFormatter->GetFormatIndex( eIdx, LANGUAGE_SYSTEM );
147 :
148 0 : return 0;
149 : }
150 :
151 34103 : sal_Bool ScSheetDPData::getIsDataLayoutDimension(long nColumn)
152 : {
153 34103 : CreateCacheTable();
154 34103 : return (nColumn ==(long)( aCacheTable.getColSize()));
155 : }
156 :
157 471 : void ScSheetDPData::SetEmptyFlags( sal_Bool bIgnoreEmptyRowsP, sal_Bool bRepeatIfEmptyP )
158 : {
159 471 : bIgnoreEmptyRows = bIgnoreEmptyRowsP;
160 471 : bRepeatIfEmpty = bRepeatIfEmptyP;
161 471 : }
162 :
163 885 : bool ScSheetDPData::IsRepeatIfEmpty()
164 : {
165 885 : return bRepeatIfEmpty;
166 : }
167 :
168 85004 : void ScSheetDPData::CreateCacheTable()
169 : {
170 : // Scan and store the data from the source range.
171 85004 : if (!aCacheTable.empty())
172 : // already cached.
173 169710 : return;
174 :
175 298 : aCacheTable.fillTable(aQuery, bIgnoreEmptyRows, bRepeatIfEmpty);
176 : }
177 :
178 2 : void ScSheetDPData::FilterCacheTable(const vector<ScDPFilteredCache::Criterion>& rCriteria, const boost::unordered_set<sal_Int32>& rCatDims)
179 : {
180 2 : CreateCacheTable();
181 : aCacheTable.filterByPageDimension(
182 2 : rCriteria, (IsRepeatIfEmpty() ? rCatDims : boost::unordered_set<sal_Int32>()));
183 2 : }
184 :
185 133 : void ScSheetDPData::GetDrillDownData(const vector<ScDPFilteredCache::Criterion>& rCriteria, const boost::unordered_set<sal_Int32>& rCatDims, Sequence< Sequence<Any> >& rData)
186 : {
187 133 : CreateCacheTable();
188 133 : sal_Int32 nRowSize = aCacheTable.getRowSize();
189 133 : if (!nRowSize)
190 133 : return;
191 :
192 : aCacheTable.filterTable(
193 133 : rCriteria, rData, IsRepeatIfEmpty() ? rCatDims : boost::unordered_set<sal_Int32>());
194 : }
195 :
196 70 : void ScSheetDPData::CalcResults(CalcInfo& rInfo, bool bAutoShow)
197 : {
198 70 : CreateCacheTable();
199 70 : CalcResultsFromCacheTable(aCacheTable, rInfo, bAutoShow);
200 70 : }
201 :
202 18014 : const ScDPFilteredCache& ScSheetDPData::GetCacheTable() const
203 : {
204 18014 : return aCacheTable;
205 : }
206 :
207 149 : void ScSheetDPData::ReloadCacheTable()
208 : {
209 149 : aCacheTable.clear();
210 149 : CreateCacheTable();
211 149 : }
212 :
213 57 : ScSheetSourceDesc::ScSheetSourceDesc(ScDocument* pDoc) :
214 57 : mpDoc(pDoc) {}
215 :
216 103 : void ScSheetSourceDesc::SetSourceRange(const ScRange& rRange)
217 : {
218 103 : maSourceRange = rRange;
219 103 : maRangeName = OUString(); // overwrite existing range name if any.
220 103 : }
221 :
222 500 : const ScRange& ScSheetSourceDesc::GetSourceRange() const
223 : {
224 500 : if (!maRangeName.isEmpty())
225 : {
226 : // Obtain the source range from the range name first.
227 4 : maSourceRange = ScRange();
228 4 : ScRangeName* pRangeName = mpDoc->GetRangeName();
229 : do
230 : {
231 4 : if (!pRangeName)
232 0 : break;
233 :
234 4 : OUString aUpper = ScGlobal::pCharClass->uppercase(maRangeName);
235 4 : const ScRangeData* pData = pRangeName->findByUpperName(aUpper);
236 4 : if (!pData)
237 0 : break;
238 :
239 : // range name found. Fow now, we only use the first token and
240 : // ignore the rest.
241 4 : ScRange aRange;
242 4 : if (!pData->IsReference(aRange))
243 0 : break;
244 :
245 4 : maSourceRange = aRange;
246 : }
247 : while (false);
248 : }
249 500 : return maSourceRange;
250 : }
251 :
252 1 : void ScSheetSourceDesc::SetRangeName(const OUString& rName)
253 : {
254 1 : maRangeName = rName;
255 1 : }
256 :
257 68 : const OUString& ScSheetSourceDesc::GetRangeName() const
258 : {
259 68 : return maRangeName;
260 : }
261 :
262 98 : bool ScSheetSourceDesc::HasRangeName() const
263 : {
264 98 : return !maRangeName.isEmpty();
265 : }
266 :
267 129 : void ScSheetSourceDesc::SetQueryParam(const ScQueryParam& rParam)
268 : {
269 129 : maQueryParam = rParam;
270 129 : }
271 :
272 199 : const ScQueryParam& ScSheetSourceDesc::GetQueryParam() const
273 : {
274 199 : return maQueryParam;
275 : }
276 :
277 21 : bool ScSheetSourceDesc::operator== (const ScSheetSourceDesc& rOther) const
278 : {
279 23 : return maSourceRange == rOther.maSourceRange &&
280 23 : maRangeName == rOther.maRangeName &&
281 23 : maQueryParam == rOther.maQueryParam;
282 : }
283 :
284 74 : const ScDPCache* ScSheetSourceDesc::CreateCache(const ScDPDimensionSaveData* pDimData) const
285 : {
286 74 : if (!mpDoc)
287 0 : return NULL;
288 :
289 74 : sal_uLong nErrId = CheckSourceRange();
290 74 : if (nErrId)
291 : {
292 : OSL_FAIL( "Error Create Cache\n" );
293 0 : return NULL;
294 : }
295 :
296 : // All cache instances are managed centrally by ScDPCollection.
297 74 : ScDPCollection* pDPs = mpDoc->GetDPCollection();
298 74 : if (HasRangeName())
299 : {
300 : // Name-based data source.
301 1 : ScDPCollection::NameCaches& rCaches = pDPs->GetNameCaches();
302 1 : return rCaches.getCache(GetRangeName(), GetSourceRange(), pDimData);
303 : }
304 :
305 73 : ScDPCollection::SheetCaches& rCaches = pDPs->GetSheetCaches();
306 73 : return rCaches.getCache(GetSourceRange(), pDimData);
307 : }
308 :
309 79 : sal_uLong ScSheetSourceDesc::CheckSourceRange() const
310 : {
311 79 : if (!mpDoc)
312 0 : return STR_ERR_DATAPILOTSOURCE;
313 :
314 : // Make sure the range is valid and sane.
315 79 : const ScRange& rSrcRange = GetSourceRange();
316 79 : if (!rSrcRange.IsValid())
317 0 : return STR_ERR_DATAPILOTSOURCE;
318 :
319 79 : if (rSrcRange.aStart.Col() > rSrcRange.aEnd.Col() || rSrcRange.aStart.Row() > rSrcRange.aEnd.Row())
320 0 : return STR_ERR_DATAPILOTSOURCE;
321 :
322 79 : return 0;
323 93 : }
324 :
325 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|