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 <tools/debug.hxx> 36 #include <svl/zforlist.hxx> 37 38 #include "dpshttab.hxx" 39 #include "dptabres.hxx" 40 #include "document.hxx" 41 #include "collect.hxx" 42 #include "cell.hxx" 43 #include "dpcachetable.hxx" 44 #include "dpobject.hxx" 45 #include "globstr.hrc" 46 // Wang Xu Ming -- 2009-8-17 47 // DataPilot Migration - Cache&&Performance 48 #include "dpglobal.hxx" 49 // End Comments 50 #include <com/sun/star/sheet/DataPilotFieldFilter.hpp> 51 52 #include <vector> 53 #include <set> 54 55 using namespace ::com::sun::star; 56 using ::com::sun::star::uno::Any; 57 using ::com::sun::star::uno::Sequence; 58 using ::std::vector; 59 using ::std::hash_map; 60 using ::std::hash_set; 61 62 // ----------------------------------------------------------------------- 63 64 ScSheetDPData::ScSheetDPData( ScDocument* pD, const ScSheetSourceDesc& rDesc , long nCacheId) : 65 ScDPTableData(pD, rDesc.GetCacheId( pD, nCacheId) ), // DataPilot Migration - Cache&&Performance 66 aQuery ( rDesc.aQueryParam ), 67 pSpecial(NULL), 68 bIgnoreEmptyRows( sal_False ), 69 bRepeatIfEmpty(sal_False), 70 aCacheTable( pD, GetCacheId() ) // base class ID is initialized with the GetCacheId call above 71 { 72 SCSIZE nEntryCount( aQuery.GetEntryCount()); 73 pSpecial = new sal_Bool[nEntryCount]; 74 for (SCSIZE j = 0; j < nEntryCount; ++j ) 75 { 76 ScQueryEntry& rEntry = aQuery.GetEntry(j); 77 if (rEntry.bDoQuery) 78 { 79 pSpecial[j] = false; 80 if (!rEntry.bQueryByString) 81 { 82 if (*rEntry.pStr == EMPTY_STRING && 83 ((rEntry.nVal == SC_EMPTYFIELDS) || (rEntry.nVal == SC_NONEMPTYFIELDS))) 84 pSpecial[j] = true; 85 } 86 else 87 { 88 sal_uInt32 nIndex = 0; 89 rEntry.bQueryByString = 90 !(pD->GetFormatTable()-> 91 IsNumberFormat(*rEntry.pStr, nIndex, rEntry.nVal)); 92 } 93 } 94 } 95 } 96 97 ScSheetDPData::~ScSheetDPData() 98 { 99 delete[] pSpecial; 100 } 101 102 void ScSheetDPData::DisposeData() 103 { 104 aCacheTable.clear(); 105 } 106 107 long ScSheetDPData::GetColumnCount() 108 { 109 CreateCacheTable(); 110 return aCacheTable.getColSize(); 111 } 112 113 String ScSheetDPData::getDimensionName(long nColumn) 114 { 115 CreateCacheTable(); 116 if (getIsDataLayoutDimension(nColumn)) 117 { 118 //! different internal and display names? 119 //return "Data"; 120 return ScGlobal::GetRscString(STR_PIVOT_DATA); 121 } 122 else if (nColumn >= aCacheTable.getColSize()) 123 { 124 DBG_ERROR("getDimensionName: invalid dimension"); 125 return String(); 126 } 127 else 128 { 129 return aCacheTable.getFieldName((SCCOL)nColumn); 130 } 131 } 132 133 sal_Bool ScSheetDPData::IsDateDimension(long nDim) 134 { 135 CreateCacheTable(); 136 long nColCount = aCacheTable.getColSize(); 137 if (getIsDataLayoutDimension(nDim)) 138 { 139 return sal_False; 140 } 141 else if (nDim >= nColCount) 142 { 143 DBG_ERROR("IsDateDimension: invalid dimension"); 144 return sal_False; 145 } 146 else 147 { 148 return aCacheTable.GetCache()->IsDateDimension( nDim); 149 } 150 } 151 152 sal_uLong ScSheetDPData::GetNumberFormat(long nDim) 153 { 154 CreateCacheTable(); 155 if (getIsDataLayoutDimension(nDim)) 156 { 157 return 0; 158 } 159 else if (nDim >= GetCacheTable().getColSize()) 160 { 161 DBG_ERROR("GetNumberFormat: invalid dimension"); 162 return 0; 163 } 164 else 165 { 166 return GetCacheTable().GetCache()->GetNumberFormat( nDim ); 167 } 168 } 169 sal_uInt32 ScDPTableData::GetNumberFormatByIdx( NfIndexTableOffset eIdx ) 170 { 171 if( !mpDoc ) 172 return 0; 173 174 if ( SvNumberFormatter* pFormatter = mpDoc->GetFormatTable() ) 175 return pFormatter->GetFormatIndex( eIdx, LANGUAGE_SYSTEM ); 176 177 return 0; 178 } 179 180 sal_Bool ScSheetDPData::getIsDataLayoutDimension(long nColumn) 181 { 182 CreateCacheTable(); 183 return (nColumn ==(long)( aCacheTable.getColSize())); 184 } 185 186 void ScSheetDPData::SetEmptyFlags( sal_Bool bIgnoreEmptyRowsP, sal_Bool bRepeatIfEmptyP ) 187 { 188 bIgnoreEmptyRows = bIgnoreEmptyRowsP; 189 bRepeatIfEmpty = bRepeatIfEmptyP; 190 } 191 192 bool ScSheetDPData::IsRepeatIfEmpty() 193 { 194 return bRepeatIfEmpty; 195 } 196 197 void ScSheetDPData::CreateCacheTable() 198 { 199 // Scan and store the data from the source range. 200 if (!aCacheTable.empty()) 201 // already cached. 202 return; 203 204 aCacheTable.fillTable( aQuery, pSpecial, 205 bIgnoreEmptyRows, bRepeatIfEmpty ); 206 } 207 208 void ScSheetDPData::FilterCacheTable(const vector<ScDPCacheTable::Criterion>& rCriteria, const hash_set<sal_Int32>& rCatDims) 209 { 210 CreateCacheTable(); 211 aCacheTable.filterByPageDimension( 212 rCriteria, (IsRepeatIfEmpty() ? rCatDims : hash_set<sal_Int32>())); 213 } 214 215 void ScSheetDPData::GetDrillDownData(const vector<ScDPCacheTable::Criterion>& rCriteria, const hash_set<sal_Int32>& rCatDims, Sequence< Sequence<Any> >& rData) 216 { 217 CreateCacheTable(); 218 sal_Int32 nRowSize = aCacheTable.getRowSize(); 219 if (!nRowSize) 220 return; 221 222 aCacheTable.filterTable( 223 rCriteria, rData, IsRepeatIfEmpty() ? rCatDims : hash_set<sal_Int32>()); 224 } 225 226 void ScSheetDPData::CalcResults(CalcInfo& rInfo, bool bAutoShow) 227 { 228 CreateCacheTable(); 229 CalcResultsFromCacheTable(aCacheTable, rInfo, bAutoShow); 230 } 231 232 const ScDPCacheTable& ScSheetDPData::GetCacheTable() const 233 { 234 return aCacheTable; 235 } 236 237 238 // Wang Xu Ming -- 2009-8-5 239 // DataPilot Migration - Cache&&Performance 240 ScDPTableDataCache* ScSheetSourceDesc::CreateCache( ScDocument* pDoc , long nID ) const 241 { 242 if ( pDoc ) 243 { 244 ScDPTableDataCache* pCache = GetExistDPObjectCache( pDoc ); 245 if ( pCache && ( nID < 0 || nID == pCache->GetId() ) ) 246 return pCache; 247 248 sal_uLong nErrId = CheckValidate( pDoc ); 249 if ( !nErrId ) 250 { 251 pCache = new ScDPTableDataCache( pDoc ); 252 253 pCache->InitFromDoc( pDoc, aSourceRange ); 254 pCache->SetId( nID ); 255 pDoc->AddDPObjectCache( pCache ); 256 257 DBG_TRACE1("Create a cache id = %d \n", pCache->GetId() ); 258 } 259 else 260 DBG_ERROR( "\n Error Create Cache" ); 261 return pCache; 262 } 263 return NULL; 264 } 265 266 ScDPTableDataCache* ScSheetSourceDesc::GetExistDPObjectCache ( ScDocument* pDoc ) const 267 { 268 return pDoc->GetUsedDPObjectCache( aSourceRange ); 269 } 270 ScDPTableDataCache* ScSheetSourceDesc::GetCache( ScDocument* pDoc, long nID ) const 271 { 272 ScDPTableDataCache* pCache = pDoc->GetDPObjectCache( nID ); 273 if ( NULL == pCache && pDoc ) 274 pCache = GetExistDPObjectCache( pDoc ); 275 if ( NULL == pCache ) 276 pCache = CreateCache( pDoc ); 277 return pCache; 278 } 279 280 long ScSheetSourceDesc:: GetCacheId( ScDocument* pDoc, long nID ) const 281 { 282 ScDPTableDataCache* pCache = GetCache( pDoc, nID); 283 if ( NULL == pCache ) 284 return -1; 285 else 286 return pCache->GetId(); 287 } 288 289 sal_uLong ScSheetSourceDesc::CheckValidate( ScDocument* pDoc ) const 290 { 291 ScRange aSrcRange( aSourceRange); 292 if ( !pDoc ) 293 return STR_ERR_DATAPILOTSOURCE; 294 295 // #i116457# Empty column titles were allowed before 3.3, and might be useful for hidden columns with annotations. 296 // Be compatible with 3.2: Allow empty titles, create columns with empty names, hide them in the dialogs. 297 298 if( pDoc->IsBlockEmpty( aSrcRange.aStart.Tab(), aSrcRange.aStart.Col(), aSrcRange.aStart.Row()+1, aSrcRange.aEnd.Col(), aSrcRange.aEnd.Row() ) ) 299 { 300 return STR_PIVOT_ONLYONEROWERR; 301 } 302 return 0; 303 } 304 // End Comments 305 306 // ----------------------------------------------------------------------- 307 308 309 310 311 312 313 314