1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sc.hxx" 30 31 32 33 // INCLUDE --------------------------------------------------------------- 34 35 #include <stdio.h> 36 #include <rtl/math.hxx> 37 #include <tools/debug.hxx> 38 #include <tools/date.hxx> 39 #include <unotools/transliterationwrapper.hxx> 40 #include <unotools/collatorwrapper.hxx> 41 42 #include <com/sun/star/sheet/DataPilotFieldFilter.hpp> 43 44 #include "dptabdat.hxx" 45 #include "global.hxx" 46 #include "dpcachetable.hxx" 47 #include "dptabres.hxx" 48 #include "document.hxx" 49 #include "dpobject.hxx" 50 51 using namespace ::com::sun::star; 52 using ::com::sun::star::uno::Sequence; 53 using ::com::sun::star::uno::Any; 54 using ::std::vector; 55 // --------------------------------------------------------------------------- 56 57 ScDPTableData::CalcInfo::CalcInfo() : 58 bRepeatIfEmpty(false) 59 { 60 } 61 62 // --------------------------------------------------------------------------- 63 64 ScDPTableData::ScDPTableData(ScDocument* pDoc, long nCacheId ) : 65 mnCacheId( nCacheId ), 66 mpDoc ( pDoc ) 67 { 68 nLastDateVal = nLastHier = nLastLevel = nLastRet = -1; // invalid 69 70 //! reset before new calculation (in case the base date is changed) 71 } 72 73 ScDPTableData::~ScDPTableData() 74 { 75 } 76 77 long ScDPTableData::GetDatePart( long nDateVal, long nHierarchy, long nLevel ) 78 { 79 if ( nDateVal == nLastDateVal && nHierarchy == nLastHier && nLevel == nLastLevel ) 80 return nLastRet; 81 82 Date aDate( 30,12,1899 ); //! get from source data (and cache here) 83 aDate += nDateVal; 84 85 long nRet = 0; 86 switch (nHierarchy) 87 { 88 case SC_DAPI_HIERARCHY_QUARTER: 89 switch (nLevel) 90 { 91 case 0: nRet = aDate.GetYear(); break; 92 case 1: nRet = (aDate.GetMonth()-1) / 3 + 1; break; 93 case 2: nRet = aDate.GetMonth(); break; 94 case 3: nRet = aDate.GetDay(); break; 95 default: 96 DBG_ERROR("GetDatePart: wrong level"); 97 } 98 break; 99 case SC_DAPI_HIERARCHY_WEEK: 100 switch (nLevel) 101 { 102 //! use settings for different definitions 103 case 0: nRet = aDate.GetYear(); break; //!... 104 case 1: nRet = aDate.GetWeekOfYear(); break; 105 case 2: nRet = (long)aDate.GetDayOfWeek(); break; 106 default: 107 DBG_ERROR("GetDatePart: wrong level"); 108 } 109 break; 110 default: 111 DBG_ERROR("GetDatePart: wrong hierarchy"); 112 } 113 114 nLastDateVal = nDateVal; 115 nLastHier = nHierarchy; 116 nLastLevel = nLevel; 117 nLastRet = nRet; 118 119 return nRet; 120 } 121 122 bool ScDPTableData::IsRepeatIfEmpty() 123 { 124 return false; 125 } 126 127 sal_uLong ScDPTableData::GetNumberFormat(long) 128 { 129 return 0; // default format 130 } 131 132 sal_Bool ScDPTableData::IsBaseForGroup(long) const 133 { 134 return sal_False; // always false 135 } 136 137 long ScDPTableData::GetGroupBase(long) const 138 { 139 return -1; // always none 140 } 141 142 sal_Bool ScDPTableData::IsNumOrDateGroup(long) const 143 { 144 return sal_False; // always false 145 } 146 147 sal_Bool ScDPTableData::IsInGroup( const ScDPItemData&, long, 148 const ScDPItemData&, long ) const 149 { 150 DBG_ERROR("IsInGroup shouldn't be called for non-group data"); 151 return sal_False; 152 } 153 154 sal_Bool ScDPTableData::HasCommonElement( const ScDPItemData&, long, 155 const ScDPItemData&, long ) const 156 { 157 DBG_ERROR("HasCommonElement shouldn't be called for non-group data"); 158 return sal_False; 159 } 160 void ScDPTableData::FillRowDataFromCacheTable(sal_Int32 nRow, const ScDPCacheTable& rCacheTable, 161 const CalcInfo& rInfo, CalcRowData& rData) 162 { 163 // column dimensions 164 GetItemData(rCacheTable, nRow, rInfo.aColLevelDims, rData.aColData); 165 166 // row dimensions 167 GetItemData(rCacheTable, nRow, rInfo.aRowLevelDims, rData.aRowData); 168 169 // page dimensions 170 GetItemData(rCacheTable, nRow, rInfo.aPageDims, rData.aPageData); 171 172 long nCacheColumnCount = rCacheTable.GetCache()->GetColumnCount(); 173 sal_Int32 n = rInfo.aDataSrcCols.size(); 174 for (sal_Int32 i = 0; i < n; ++i) 175 { 176 long nDim = rInfo.aDataSrcCols[i]; 177 rData.aValues.push_back( ScDPValueData() ); 178 // #i111435# GetItemData needs dimension indexes including groups, 179 // so the index must be checked here (groups aren't useful as data fields). 180 if ( nDim < nCacheColumnCount ) 181 { 182 ScDPValueData& rVal = rData.aValues.back(); 183 rCacheTable.getValue( rVal, static_cast<SCCOL>(nDim), static_cast<SCROW>(nRow), false); 184 } 185 } 186 } 187 188 void ScDPTableData::ProcessRowData(CalcInfo& rInfo, CalcRowData& rData, bool bAutoShow) 189 { 190 // Wang Xu Ming -- 2009-6-16 191 // DataPilot Migration 192 if (!bAutoShow) 193 { 194 LateInitParams aColParams( rInfo.aColDims, rInfo.aColLevels, sal_False ); 195 LateInitParams aRowParams ( rInfo.aRowDims, rInfo.aRowLevels, sal_True ); 196 // root always init child 197 aColParams.SetInitChild( sal_True ); 198 aColParams.SetInitAllChildren( sal_False); 199 aRowParams.SetInitChild( sal_True ); 200 aRowParams.SetInitAllChildren( sal_False); 201 202 rInfo.pColRoot->LateInitFrom( aColParams, rData.aColData,0, *rInfo.pInitState); 203 rInfo.pRowRoot->LateInitFrom( aRowParams, rData.aRowData, 0, *rInfo.pInitState); 204 } 205 // End Comments 206 207 if ( ( !rInfo.pColRoot->GetChildDimension() || rInfo.pColRoot->GetChildDimension()->IsValidEntry(rData.aColData) ) && 208 ( !rInfo.pRowRoot->GetChildDimension() || rInfo.pRowRoot->GetChildDimension()->IsValidEntry(rData.aRowData) ) ) 209 { 210 //! single process method with ColMembers, RowMembers and data !!! 211 if (rInfo.pColRoot->GetChildDimension()) 212 { 213 // Wang Xu Ming -- 2009-6-10 214 // DataPilot Migration 215 vector</*ScDPItemData*/ SCROW > aEmptyData; 216 rInfo.pColRoot->GetChildDimension()->ProcessData(rData.aColData, NULL, aEmptyData, rData.aValues); 217 // End Comments 218 } 219 220 rInfo.pRowRoot->ProcessData(rData.aRowData, rInfo.pColRoot->GetChildDimension(), 221 rData.aColData, rData.aValues); 222 } 223 } 224 225 void ScDPTableData::CalcResultsFromCacheTable(const ScDPCacheTable& rCacheTable, CalcInfo& rInfo, bool bAutoShow) 226 { 227 sal_Int32 nRowSize = rCacheTable.getRowSize(); 228 for (sal_Int32 nRow = 0; nRow < nRowSize; ++nRow) 229 { 230 if (!rCacheTable.isRowActive(nRow)) 231 continue; 232 233 CalcRowData aData; 234 FillRowDataFromCacheTable(nRow, rCacheTable, rInfo, aData); 235 ProcessRowData(rInfo, aData, bAutoShow); 236 } 237 } 238 239 // Wang Xu Ming -- 2009-6-10 240 // DataPilot Migration 241 void ScDPTableData::GetItemData(const ScDPCacheTable& rCacheTable, sal_Int32 nRow, 242 const vector<long>& rDims, vector< SCROW/*ScDPItemData*/>& rItemData) 243 // End Comments 244 { 245 sal_Int32 nDimSize = rDims.size(); 246 for (sal_Int32 i = 0; i < nDimSize; ++i) 247 { 248 long nDim = rDims[i]; 249 250 if (getIsDataLayoutDimension(nDim)) 251 { 252 rItemData.push_back( -1 ); 253 continue; 254 } 255 256 nDim = GetSourceDim( nDim ); 257 if ( nDim >= rCacheTable.GetCache()->GetColumnCount() ) 258 continue; 259 260 SCROW nId= rCacheTable.GetCache()->GetItemDataId( static_cast<SCCOL>(nDim), static_cast<SCROW>(nRow), IsRepeatIfEmpty()); 261 rItemData.push_back( nId ); 262 263 } 264 } 265 266 // ----------------------------------------------------------------------- 267 268 // Wang Xu Ming -- 2009-6-8 269 // DataPilot Migration 270 long ScDPTableData::GetMembersCount( long nDim ) 271 { 272 if ( nDim > MAXCOL ) 273 return 0; 274 return GetCacheTable().getFieldEntries( nDim ).size(); 275 } 276 277 long ScDPTableData::GetCacheId() const 278 { 279 return mnCacheId; 280 } 281 282 const ScDPItemData* ScDPTableData::GetMemberByIndex( long nDim, long nIndex ) 283 { 284 if ( nIndex >= GetMembersCount( nDim ) ) 285 return NULL; 286 287 const ::std::vector<SCROW>& nMembers = GetCacheTable().getFieldEntries( nDim ); 288 289 return GetCacheTable().GetCache()->GetItemDataById( (SCCOL) nDim, (SCROW)nMembers[nIndex] ); 290 } 291 292 const ScDPItemData* ScDPTableData::GetMemberById( long nDim, long nId) 293 { 294 295 return GetCacheTable().GetCache()->GetItemDataById( (SCCOL) nDim, (SCROW)nId); 296 } 297 298 SCROW ScDPTableData::GetIdOfItemData( long nDim, const ScDPItemData& rData ) 299 { 300 return GetCacheTable().GetCache()->GetIdByItemData((SCCOL) nDim, rData ); 301 } 302 303 const std::vector< SCROW >& ScDPTableData::GetColumnEntries( long nColumn ) 304 { 305 return GetCacheTable().getFieldEntries( nColumn ); 306 } 307 308 long ScDPTableData::GetSourceDim( long nDim ) 309 { 310 return nDim; 311 312 } 313 314 long ScDPTableData::Compare( long nDim, long nDataId1, long nDataId2) 315 { 316 if ( getIsDataLayoutDimension(nDim) ) 317 return 0; 318 319 long n1 = GetCacheTable().GetCache()->GetOrder( nDim, nDataId1); 320 long n2 = GetCacheTable().GetCache()->GetOrder( nDim, nDataId2); 321 if ( n1 > n2 ) 322 return 1; 323 else if ( n1 == n2 ) 324 return 0; 325 else 326 return -1; 327 } 328 // End Comments 329 // ----------------------------------------------------------------------- 330