1*9b5730f6SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*9b5730f6SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*9b5730f6SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*9b5730f6SAndrew Rist * distributed with this work for additional information 6*9b5730f6SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*9b5730f6SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*9b5730f6SAndrew Rist * "License"); you may not use this file except in compliance 9*9b5730f6SAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 11*9b5730f6SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 13*9b5730f6SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*9b5730f6SAndrew Rist * software distributed under the License is distributed on an 15*9b5730f6SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*9b5730f6SAndrew Rist * KIND, either express or implied. See the License for the 17*9b5730f6SAndrew Rist * specific language governing permissions and limitations 18*9b5730f6SAndrew Rist * under the License. 19cdf0e10cSrcweir * 20*9b5730f6SAndrew Rist *************************************************************/ 21*9b5730f6SAndrew Rist 22*9b5730f6SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_connectivity.hxx" 26cdf0e10cSrcweir #include "calc/CTable.hxx" 27cdf0e10cSrcweir #include <com/sun/star/sdbc/ColumnValue.hpp> 28cdf0e10cSrcweir #include <com/sun/star/sdbc/DataType.hpp> 29cdf0e10cSrcweir //#ifndef _COM_SUN_STAR_UCB_XCONTENTACCESS_HPP_ 30cdf0e10cSrcweir //#include <com/sun/star/ucb/XContentAccess.hpp> 31cdf0e10cSrcweir //#endif 32cdf0e10cSrcweir #include <com/sun/star/sdbc/XRow.hpp> 33cdf0e10cSrcweir #include <com/sun/star/sheet/XSpreadsheetDocument.hpp> 34cdf0e10cSrcweir #include <com/sun/star/sheet/XSpreadsheet.hpp> 35cdf0e10cSrcweir #include <com/sun/star/sheet/XCellRangeAddressable.hpp> 36cdf0e10cSrcweir #include <com/sun/star/sheet/XCellRangesQuery.hpp> 37cdf0e10cSrcweir #include <com/sun/star/sheet/XDatabaseRanges.hpp> 38cdf0e10cSrcweir #include <com/sun/star/sheet/XDatabaseRange.hpp> 39cdf0e10cSrcweir #include <com/sun/star/sheet/XCellRangeReferrer.hpp> 40cdf0e10cSrcweir #include <com/sun/star/sheet/XUsedAreaCursor.hpp> 41cdf0e10cSrcweir #include <com/sun/star/sheet/CellFlags.hpp> 42cdf0e10cSrcweir #include <com/sun/star/sheet/FormulaResult.hpp> 43cdf0e10cSrcweir #include <com/sun/star/util/NumberFormat.hpp> 44cdf0e10cSrcweir #include <com/sun/star/util/XNumberFormatsSupplier.hpp> 45cdf0e10cSrcweir #include <com/sun/star/text/XText.hpp> 46cdf0e10cSrcweir #include <svl/converter.hxx> 47cdf0e10cSrcweir #include "calc/CConnection.hxx" 48cdf0e10cSrcweir #include "calc/CColumns.hxx" 49cdf0e10cSrcweir #include "connectivity/sdbcx/VColumn.hxx" 50cdf0e10cSrcweir #include <rtl/ustrbuf.hxx> 51cdf0e10cSrcweir #include <osl/thread.h> 52cdf0e10cSrcweir #include <tools/config.hxx> 53cdf0e10cSrcweir #include <comphelper/sequence.hxx> 54cdf0e10cSrcweir #include <svl/zforlist.hxx> 55cdf0e10cSrcweir #include <rtl/math.hxx> 56cdf0e10cSrcweir #include <comphelper/extract.hxx> 57cdf0e10cSrcweir #include <connectivity/dbexception.hxx> 58cdf0e10cSrcweir #include <connectivity/dbconversion.hxx> 59cdf0e10cSrcweir #include <comphelper/types.hxx> 60cdf0e10cSrcweir #include <rtl/logfile.hxx> 61cdf0e10cSrcweir 62cdf0e10cSrcweir using namespace connectivity; 63cdf0e10cSrcweir using namespace connectivity::calc; 64cdf0e10cSrcweir using namespace connectivity::file; 65cdf0e10cSrcweir using namespace ::cppu; 66cdf0e10cSrcweir using namespace ::dbtools; 67cdf0e10cSrcweir using namespace ::com::sun::star::uno; 68cdf0e10cSrcweir using namespace ::com::sun::star::beans; 69cdf0e10cSrcweir using namespace ::com::sun::star::sdbcx; 70cdf0e10cSrcweir using namespace ::com::sun::star::sdbc; 71cdf0e10cSrcweir using namespace ::com::sun::star::container; 72cdf0e10cSrcweir using namespace ::com::sun::star::lang; 73cdf0e10cSrcweir using namespace ::com::sun::star::sheet; 74cdf0e10cSrcweir using namespace ::com::sun::star::table; 75cdf0e10cSrcweir using namespace ::com::sun::star::text; 76cdf0e10cSrcweir using namespace ::com::sun::star::util; 77cdf0e10cSrcweir 78cdf0e10cSrcweir // ------------------------------------------------------------------------- 79cdf0e10cSrcweir 80cdf0e10cSrcweir void lcl_UpdateArea( const Reference<XCellRange>& xUsedRange, sal_Int32& rEndCol, sal_Int32& rEndRow ) 81cdf0e10cSrcweir { 82cdf0e10cSrcweir //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::lcl_UpdateArea" ); 83cdf0e10cSrcweir // update rEndCol, rEndRow if any non-empty cell in xUsedRange is right/below 84cdf0e10cSrcweir 85cdf0e10cSrcweir const Reference<XCellRangesQuery> xUsedQuery( xUsedRange, UNO_QUERY ); 86cdf0e10cSrcweir if ( xUsedQuery.is() ) 87cdf0e10cSrcweir { 88cdf0e10cSrcweir const sal_Int16 nContentFlags = 89cdf0e10cSrcweir CellFlags::STRING | CellFlags::VALUE | CellFlags::DATETIME | CellFlags::FORMULA | CellFlags::ANNOTATION; 90cdf0e10cSrcweir 91cdf0e10cSrcweir const Reference<XSheetCellRanges> xUsedRanges = xUsedQuery->queryContentCells( nContentFlags ); 92cdf0e10cSrcweir const Sequence<CellRangeAddress> aAddresses = xUsedRanges->getRangeAddresses(); 93cdf0e10cSrcweir 94cdf0e10cSrcweir const sal_Int32 nCount = aAddresses.getLength(); 95cdf0e10cSrcweir const CellRangeAddress* pData = aAddresses.getConstArray(); 96cdf0e10cSrcweir for ( sal_Int32 i=0; i<nCount; i++ ) 97cdf0e10cSrcweir { 98cdf0e10cSrcweir rEndCol = pData[i].EndColumn > rEndCol ? pData[i].EndColumn : rEndCol; 99cdf0e10cSrcweir rEndRow = pData[i].EndRow > rEndRow ? pData[i].EndRow : rEndRow; 100cdf0e10cSrcweir } 101cdf0e10cSrcweir } 102cdf0e10cSrcweir } 103cdf0e10cSrcweir 104cdf0e10cSrcweir void lcl_GetDataArea( const Reference<XSpreadsheet>& xSheet, sal_Int32& rColumnCount, sal_Int32& rRowCount ) 105cdf0e10cSrcweir { 106cdf0e10cSrcweir //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::lcl_GetDataArea" ); 107cdf0e10cSrcweir Reference<XSheetCellCursor> xCursor = xSheet->createCursor(); 108cdf0e10cSrcweir Reference<XCellRangeAddressable> xRange( xCursor, UNO_QUERY ); 109cdf0e10cSrcweir if ( !xRange.is() ) 110cdf0e10cSrcweir { 111cdf0e10cSrcweir rColumnCount = rRowCount = 0; 112cdf0e10cSrcweir return; 113cdf0e10cSrcweir } 114cdf0e10cSrcweir 115cdf0e10cSrcweir // first find the contiguous cell area starting at A1 116cdf0e10cSrcweir 117cdf0e10cSrcweir xCursor->collapseToSize( 1, 1 ); // single (first) cell 118cdf0e10cSrcweir xCursor->collapseToCurrentRegion(); // contiguous data area 119cdf0e10cSrcweir 120cdf0e10cSrcweir CellRangeAddress aRegionAddr = xRange->getRangeAddress(); 121cdf0e10cSrcweir sal_Int32 nEndCol = aRegionAddr.EndColumn; 122cdf0e10cSrcweir sal_Int32 nEndRow = aRegionAddr.EndRow; 123cdf0e10cSrcweir 124cdf0e10cSrcweir Reference<XUsedAreaCursor> xUsed( xCursor, UNO_QUERY ); 125cdf0e10cSrcweir if ( xUsed.is() ) 126cdf0e10cSrcweir { 127cdf0e10cSrcweir // The used area from XUsedAreaCursor includes visible attributes. 128cdf0e10cSrcweir // If the used area is larger than the contiguous cell area, find non-empty 129cdf0e10cSrcweir // cells in that area. 130cdf0e10cSrcweir 131cdf0e10cSrcweir xUsed->gotoEndOfUsedArea( sal_False ); 132cdf0e10cSrcweir CellRangeAddress aUsedAddr = xRange->getRangeAddress(); 133cdf0e10cSrcweir 134cdf0e10cSrcweir if ( aUsedAddr.EndColumn > aRegionAddr.EndColumn ) 135cdf0e10cSrcweir { 136cdf0e10cSrcweir Reference<XCellRange> xUsedRange = xSheet->getCellRangeByPosition( 137cdf0e10cSrcweir aRegionAddr.EndColumn + 1, 0, aUsedAddr.EndColumn, aUsedAddr.EndRow ); 138cdf0e10cSrcweir lcl_UpdateArea( xUsedRange, nEndCol, nEndRow ); 139cdf0e10cSrcweir } 140cdf0e10cSrcweir 141cdf0e10cSrcweir if ( aUsedAddr.EndRow > aRegionAddr.EndRow ) 142cdf0e10cSrcweir { 143cdf0e10cSrcweir // only up to the last column of aRegionAddr, the other columns are handled above 144cdf0e10cSrcweir Reference<XCellRange> xUsedRange = xSheet->getCellRangeByPosition( 145cdf0e10cSrcweir 0, aRegionAddr.EndRow + 1, aRegionAddr.EndColumn, aUsedAddr.EndRow ); 146cdf0e10cSrcweir lcl_UpdateArea( xUsedRange, nEndCol, nEndRow ); 147cdf0e10cSrcweir } 148cdf0e10cSrcweir } 149cdf0e10cSrcweir 150cdf0e10cSrcweir rColumnCount = nEndCol + 1; // number of columns 151cdf0e10cSrcweir rRowCount = nEndRow; // first row (headers) is not counted 152cdf0e10cSrcweir } 153cdf0e10cSrcweir 154cdf0e10cSrcweir CellContentType lcl_GetContentOrResultType( const Reference<XCell>& xCell ) 155cdf0e10cSrcweir { 156cdf0e10cSrcweir //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::lcl_GetContentOrResultType" ); 157cdf0e10cSrcweir CellContentType eCellType = xCell->getType(); 158cdf0e10cSrcweir if ( eCellType == CellContentType_FORMULA ) 159cdf0e10cSrcweir { 160cdf0e10cSrcweir static const ::rtl::OUString s_sFormulaResultType(RTL_CONSTASCII_USTRINGPARAM("FormulaResultType")); 161cdf0e10cSrcweir Reference<XPropertySet> xProp( xCell, UNO_QUERY ); 162cdf0e10cSrcweir try 163cdf0e10cSrcweir { 164cdf0e10cSrcweir xProp->getPropertyValue( s_sFormulaResultType ) >>= eCellType; // type of formula result 165cdf0e10cSrcweir } 166cdf0e10cSrcweir catch (UnknownPropertyException&) 167cdf0e10cSrcweir { 168cdf0e10cSrcweir eCellType = CellContentType_VALUE; // if FormulaResultType property not available 169cdf0e10cSrcweir } 170cdf0e10cSrcweir } 171cdf0e10cSrcweir return eCellType; 172cdf0e10cSrcweir } 173cdf0e10cSrcweir 174cdf0e10cSrcweir Reference<XCell> lcl_GetUsedCell( const Reference<XSpreadsheet>& xSheet, sal_Int32 nDocColumn, sal_Int32 nDocRow ) 175cdf0e10cSrcweir { 176cdf0e10cSrcweir //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::lcl_GetUsedCell" ); 177cdf0e10cSrcweir Reference<XCell> xCell = xSheet->getCellByPosition( nDocColumn, nDocRow ); 178cdf0e10cSrcweir if ( xCell.is() && xCell->getType() == CellContentType_EMPTY ) 179cdf0e10cSrcweir { 180cdf0e10cSrcweir // get first non-empty cell 181cdf0e10cSrcweir 182cdf0e10cSrcweir Reference<XCellRangeAddressable> xAddr( xSheet, UNO_QUERY ); 183cdf0e10cSrcweir if (xAddr.is()) 184cdf0e10cSrcweir { 185cdf0e10cSrcweir CellRangeAddress aTotalRange = xAddr->getRangeAddress(); 186cdf0e10cSrcweir sal_Int32 nLastRow = aTotalRange.EndRow; 187cdf0e10cSrcweir Reference<XCellRangesQuery> xQuery( xSheet->getCellRangeByPosition( nDocColumn, nDocRow, nDocColumn, nLastRow ), UNO_QUERY ); 188cdf0e10cSrcweir if (xQuery.is()) 189cdf0e10cSrcweir { 190cdf0e10cSrcweir // queryIntersection to get a ranges object 191cdf0e10cSrcweir Reference<XSheetCellRanges> xRanges = xQuery->queryIntersection( aTotalRange ); 192cdf0e10cSrcweir if (xRanges.is()) 193cdf0e10cSrcweir { 194cdf0e10cSrcweir Reference<XEnumerationAccess> xCells = xRanges->getCells(); 195cdf0e10cSrcweir if (xCells.is()) 196cdf0e10cSrcweir { 197cdf0e10cSrcweir Reference<XEnumeration> xEnum = xCells->createEnumeration(); 198cdf0e10cSrcweir if ( xEnum.is() && xEnum->hasMoreElements() ) 199cdf0e10cSrcweir { 200cdf0e10cSrcweir // get first non-empty cell from enumeration 201cdf0e10cSrcweir xCell.set(xEnum->nextElement(),UNO_QUERY); 202cdf0e10cSrcweir } 203cdf0e10cSrcweir // otherwise, keep empty cell 204cdf0e10cSrcweir } 205cdf0e10cSrcweir } 206cdf0e10cSrcweir } 207cdf0e10cSrcweir } 208cdf0e10cSrcweir } 209cdf0e10cSrcweir return xCell; 210cdf0e10cSrcweir } 211cdf0e10cSrcweir 212cdf0e10cSrcweir bool lcl_HasTextInColumn( const Reference<XSpreadsheet>& xSheet, sal_Int32 nDocColumn, sal_Int32 nDocRow ) 213cdf0e10cSrcweir { 214cdf0e10cSrcweir //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::lcl_HasTextInColumn" ); 215cdf0e10cSrcweir // look for any text cell or text result in the column 216cdf0e10cSrcweir 217cdf0e10cSrcweir Reference<XCellRangeAddressable> xAddr( xSheet, UNO_QUERY ); 218cdf0e10cSrcweir if (xAddr.is()) 219cdf0e10cSrcweir { 220cdf0e10cSrcweir CellRangeAddress aTotalRange = xAddr->getRangeAddress(); 221cdf0e10cSrcweir sal_Int32 nLastRow = aTotalRange.EndRow; 222cdf0e10cSrcweir Reference<XCellRangesQuery> xQuery( xSheet->getCellRangeByPosition( nDocColumn, nDocRow, nDocColumn, nLastRow ), UNO_QUERY ); 223cdf0e10cSrcweir if (xQuery.is()) 224cdf0e10cSrcweir { 225cdf0e10cSrcweir // are there text cells in the column? 226cdf0e10cSrcweir Reference<XSheetCellRanges> xTextContent = xQuery->queryContentCells( CellFlags::STRING ); 227cdf0e10cSrcweir if ( xTextContent.is() && xTextContent->hasElements() ) 228cdf0e10cSrcweir return true; 229cdf0e10cSrcweir 230cdf0e10cSrcweir // are there formulas with text results in the column? 231cdf0e10cSrcweir Reference<XSheetCellRanges> xTextFormula = xQuery->queryFormulaCells( FormulaResult::STRING ); 232cdf0e10cSrcweir if ( xTextFormula.is() && xTextFormula->hasElements() ) 233cdf0e10cSrcweir return true; 234cdf0e10cSrcweir } 235cdf0e10cSrcweir } 236cdf0e10cSrcweir 237cdf0e10cSrcweir return false; 238cdf0e10cSrcweir } 239cdf0e10cSrcweir 240cdf0e10cSrcweir void lcl_GetColumnInfo( const Reference<XSpreadsheet>& xSheet, const Reference<XNumberFormats>& xFormats, 241cdf0e10cSrcweir sal_Int32 nDocColumn, sal_Int32 nStartRow, sal_Bool bHasHeaders, 242cdf0e10cSrcweir ::rtl::OUString& rName, sal_Int32& rDataType, sal_Bool& rCurrency ) 243cdf0e10cSrcweir { 244cdf0e10cSrcweir //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::lcl_GetColumnInfo" ); 245cdf0e10cSrcweir //! avoid duplicate field names 246cdf0e10cSrcweir 247cdf0e10cSrcweir // get column name from first row, if range contains headers 248cdf0e10cSrcweir 249cdf0e10cSrcweir if ( bHasHeaders ) 250cdf0e10cSrcweir { 251cdf0e10cSrcweir Reference<XText> xHeaderText( xSheet->getCellByPosition( nDocColumn, nStartRow ), UNO_QUERY ); 252cdf0e10cSrcweir if ( xHeaderText.is() ) 253cdf0e10cSrcweir rName = xHeaderText->getString(); 254cdf0e10cSrcweir } 255cdf0e10cSrcweir 256cdf0e10cSrcweir // get column type from first data row 257cdf0e10cSrcweir 258cdf0e10cSrcweir sal_Int32 nDataRow = nStartRow; 259cdf0e10cSrcweir if ( bHasHeaders ) 260cdf0e10cSrcweir ++nDataRow; 261cdf0e10cSrcweir Reference<XCell> xDataCell = lcl_GetUsedCell( xSheet, nDocColumn, nDataRow ); 262cdf0e10cSrcweir 263cdf0e10cSrcweir Reference<XPropertySet> xProp( xDataCell, UNO_QUERY ); 264cdf0e10cSrcweir if ( xProp.is() ) 265cdf0e10cSrcweir { 266cdf0e10cSrcweir rCurrency = sal_False; // set to true for currency below 267cdf0e10cSrcweir 268cdf0e10cSrcweir const CellContentType eCellType = lcl_GetContentOrResultType( xDataCell ); 269cdf0e10cSrcweir // #i35178# use "text" type if there is any text cell in the column 270cdf0e10cSrcweir if ( eCellType == CellContentType_TEXT || lcl_HasTextInColumn( xSheet, nDocColumn, nDataRow ) ) 271cdf0e10cSrcweir rDataType = DataType::VARCHAR; 272cdf0e10cSrcweir else if ( eCellType == CellContentType_VALUE ) 273cdf0e10cSrcweir { 274cdf0e10cSrcweir // get number format to distinguish between different types 275cdf0e10cSrcweir 276cdf0e10cSrcweir sal_Int16 nNumType = NumberFormat::NUMBER; 277cdf0e10cSrcweir try 278cdf0e10cSrcweir { 279cdf0e10cSrcweir static ::rtl::OUString s_NumberFormat(RTL_CONSTASCII_USTRINGPARAM("NumberFormat")); 280cdf0e10cSrcweir sal_Int32 nKey = 0; 281cdf0e10cSrcweir 282cdf0e10cSrcweir if ( xProp->getPropertyValue( s_NumberFormat ) >>= nKey ) 283cdf0e10cSrcweir { 284cdf0e10cSrcweir const Reference<XPropertySet> xFormat = xFormats->getByKey( nKey ); 285cdf0e10cSrcweir if ( xFormat.is() ) 286cdf0e10cSrcweir { 287cdf0e10cSrcweir xFormat->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE) ) >>= nNumType; 288cdf0e10cSrcweir } 289cdf0e10cSrcweir } 290cdf0e10cSrcweir } 291cdf0e10cSrcweir catch ( Exception& ) 292cdf0e10cSrcweir { 293cdf0e10cSrcweir } 294cdf0e10cSrcweir 295cdf0e10cSrcweir if ( nNumType & NumberFormat::TEXT ) 296cdf0e10cSrcweir rDataType = DataType::VARCHAR; 297cdf0e10cSrcweir else if ( nNumType & NumberFormat::NUMBER ) 298cdf0e10cSrcweir rDataType = DataType::DECIMAL; 299cdf0e10cSrcweir else if ( nNumType & NumberFormat::CURRENCY ) 300cdf0e10cSrcweir { 301cdf0e10cSrcweir rCurrency = sal_True; 302cdf0e10cSrcweir rDataType = DataType::DECIMAL; 303cdf0e10cSrcweir } 304cdf0e10cSrcweir else if ( ( nNumType & NumberFormat::DATETIME ) == NumberFormat::DATETIME ) 305cdf0e10cSrcweir { 306cdf0e10cSrcweir // NumberFormat::DATETIME is DATE | TIME 307cdf0e10cSrcweir rDataType = DataType::TIMESTAMP; 308cdf0e10cSrcweir } 309cdf0e10cSrcweir else if ( nNumType & NumberFormat::DATE ) 310cdf0e10cSrcweir rDataType = DataType::DATE; 311cdf0e10cSrcweir else if ( nNumType & NumberFormat::TIME ) 312cdf0e10cSrcweir rDataType = DataType::TIME; 313cdf0e10cSrcweir else if ( nNumType & NumberFormat::LOGICAL ) 314cdf0e10cSrcweir rDataType = DataType::BIT; 315cdf0e10cSrcweir else 316cdf0e10cSrcweir rDataType = DataType::DECIMAL; 317cdf0e10cSrcweir } 318cdf0e10cSrcweir else 319cdf0e10cSrcweir { 320cdf0e10cSrcweir // whole column empty 321cdf0e10cSrcweir rDataType = DataType::VARCHAR; 322cdf0e10cSrcweir } 323cdf0e10cSrcweir } 324cdf0e10cSrcweir } 325cdf0e10cSrcweir 326cdf0e10cSrcweir // ------------------------------------------------------------------------- 327cdf0e10cSrcweir 328cdf0e10cSrcweir void lcl_SetValue( ORowSetValue& rValue, const Reference<XSpreadsheet>& xSheet, 329cdf0e10cSrcweir sal_Int32 nStartCol, sal_Int32 nStartRow, sal_Bool bHasHeaders, 330cdf0e10cSrcweir const ::Date& rNullDate, 331cdf0e10cSrcweir sal_Int32 nDBRow, sal_Int32 nDBColumn, sal_Int32 nType ) 332cdf0e10cSrcweir { 333cdf0e10cSrcweir //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::lcl_SetValue" ); 334cdf0e10cSrcweir sal_Int32 nDocColumn = nStartCol + nDBColumn - 1; // database counts from 1 335cdf0e10cSrcweir sal_Int32 nDocRow = nStartRow + nDBRow - 1; 336cdf0e10cSrcweir if (bHasHeaders) 337cdf0e10cSrcweir ++nDocRow; 338cdf0e10cSrcweir 339cdf0e10cSrcweir const Reference<XCell> xCell = xSheet->getCellByPosition( nDocColumn, nDocRow ); 340cdf0e10cSrcweir if ( xCell.is() ) 341cdf0e10cSrcweir { 342cdf0e10cSrcweir CellContentType eCellType = lcl_GetContentOrResultType( xCell ); 343cdf0e10cSrcweir switch (nType) 344cdf0e10cSrcweir { 345cdf0e10cSrcweir case DataType::VARCHAR: 346cdf0e10cSrcweir if ( eCellType == CellContentType_EMPTY ) 347cdf0e10cSrcweir rValue.setNull(); 348cdf0e10cSrcweir else 349cdf0e10cSrcweir { 350cdf0e10cSrcweir // #i25840# still let Calc convert numbers to text 351cdf0e10cSrcweir const Reference<XText> xText( xCell, UNO_QUERY ); 352cdf0e10cSrcweir if ( xText.is() ) 353cdf0e10cSrcweir rValue = xText->getString(); 354cdf0e10cSrcweir } 355cdf0e10cSrcweir break; 356cdf0e10cSrcweir case DataType::DECIMAL: 357cdf0e10cSrcweir if ( eCellType == CellContentType_VALUE ) 358cdf0e10cSrcweir rValue = xCell->getValue(); // double 359cdf0e10cSrcweir else 360cdf0e10cSrcweir rValue.setNull(); 361cdf0e10cSrcweir break; 362cdf0e10cSrcweir case DataType::BIT: 363cdf0e10cSrcweir if ( eCellType == CellContentType_VALUE ) 364cdf0e10cSrcweir rValue = (sal_Bool)( xCell->getValue() != 0.0 ); 365cdf0e10cSrcweir else 366cdf0e10cSrcweir rValue.setNull(); 367cdf0e10cSrcweir break; 368cdf0e10cSrcweir case DataType::DATE: 369cdf0e10cSrcweir if ( eCellType == CellContentType_VALUE ) 370cdf0e10cSrcweir { 371cdf0e10cSrcweir ::Date aDate( rNullDate ); 372cdf0e10cSrcweir aDate += (long)::rtl::math::approxFloor( xCell->getValue() ); 373cdf0e10cSrcweir ::com::sun::star::util::Date aDateStruct( aDate.GetDay(), aDate.GetMonth(), aDate.GetYear() ); 374cdf0e10cSrcweir rValue = aDateStruct; 375cdf0e10cSrcweir } 376cdf0e10cSrcweir else 377cdf0e10cSrcweir rValue.setNull(); 378cdf0e10cSrcweir break; 379cdf0e10cSrcweir case DataType::TIME: 380cdf0e10cSrcweir if ( eCellType == CellContentType_VALUE ) 381cdf0e10cSrcweir { 382cdf0e10cSrcweir double fCellVal = xCell->getValue(); 383cdf0e10cSrcweir double fTime = fCellVal - rtl::math::approxFloor( fCellVal ); 384cdf0e10cSrcweir long nIntTime = (long)rtl::math::round( fTime * 8640000.0 ); 385cdf0e10cSrcweir if ( nIntTime == 8640000 ) 386cdf0e10cSrcweir nIntTime = 0; // 23:59:59.995 and above is 00:00:00.00 387cdf0e10cSrcweir ::com::sun::star::util::Time aTime; 388cdf0e10cSrcweir aTime.HundredthSeconds = (sal_uInt16)( nIntTime % 100 ); 389cdf0e10cSrcweir nIntTime /= 100; 390cdf0e10cSrcweir aTime.Seconds = (sal_uInt16)( nIntTime % 60 ); 391cdf0e10cSrcweir nIntTime /= 60; 392cdf0e10cSrcweir aTime.Minutes = (sal_uInt16)( nIntTime % 60 ); 393cdf0e10cSrcweir nIntTime /= 60; 394cdf0e10cSrcweir OSL_ENSURE( nIntTime < 24, "error in time calculation" ); 395cdf0e10cSrcweir aTime.Hours = (sal_uInt16) nIntTime; 396cdf0e10cSrcweir rValue = aTime; 397cdf0e10cSrcweir } 398cdf0e10cSrcweir else 399cdf0e10cSrcweir rValue.setNull(); 400cdf0e10cSrcweir break; 401cdf0e10cSrcweir case DataType::TIMESTAMP: 402cdf0e10cSrcweir if ( eCellType == CellContentType_VALUE ) 403cdf0e10cSrcweir { 404cdf0e10cSrcweir double fCellVal = xCell->getValue(); 405cdf0e10cSrcweir double fDays = ::rtl::math::approxFloor( fCellVal ); 406cdf0e10cSrcweir double fTime = fCellVal - fDays; 407cdf0e10cSrcweir long nIntDays = (long)fDays; 408cdf0e10cSrcweir long nIntTime = (long)::rtl::math::round( fTime * 8640000.0 ); 409cdf0e10cSrcweir if ( nIntTime == 8640000 ) 410cdf0e10cSrcweir { 411cdf0e10cSrcweir nIntTime = 0; // 23:59:59.995 and above is 00:00:00.00 412cdf0e10cSrcweir ++nIntDays; // (next day) 413cdf0e10cSrcweir } 414cdf0e10cSrcweir 415cdf0e10cSrcweir ::com::sun::star::util::DateTime aDateTime; 416cdf0e10cSrcweir 417cdf0e10cSrcweir aDateTime.HundredthSeconds = (sal_uInt16)( nIntTime % 100 ); 418cdf0e10cSrcweir nIntTime /= 100; 419cdf0e10cSrcweir aDateTime.Seconds = (sal_uInt16)( nIntTime % 60 ); 420cdf0e10cSrcweir nIntTime /= 60; 421cdf0e10cSrcweir aDateTime.Minutes = (sal_uInt16)( nIntTime % 60 ); 422cdf0e10cSrcweir nIntTime /= 60; 423cdf0e10cSrcweir OSL_ENSURE( nIntTime < 24, "error in time calculation" ); 424cdf0e10cSrcweir aDateTime.Hours = (sal_uInt16) nIntTime; 425cdf0e10cSrcweir 426cdf0e10cSrcweir ::Date aDate( rNullDate ); 427cdf0e10cSrcweir aDate += nIntDays; 428cdf0e10cSrcweir aDateTime.Day = aDate.GetDay(); 429cdf0e10cSrcweir aDateTime.Month = aDate.GetMonth(); 430cdf0e10cSrcweir aDateTime.Year = aDate.GetYear(); 431cdf0e10cSrcweir 432cdf0e10cSrcweir rValue = aDateTime; 433cdf0e10cSrcweir } 434cdf0e10cSrcweir else 435cdf0e10cSrcweir rValue.setNull(); 436cdf0e10cSrcweir break; 437cdf0e10cSrcweir } // switch (nType) 438cdf0e10cSrcweir } 439cdf0e10cSrcweir 440cdf0e10cSrcweir // rValue.setTypeKind(nType); 441cdf0e10cSrcweir } 442cdf0e10cSrcweir 443cdf0e10cSrcweir // ------------------------------------------------------------------------- 444cdf0e10cSrcweir 445cdf0e10cSrcweir ::rtl::OUString lcl_GetColumnStr( sal_Int32 nColumn ) 446cdf0e10cSrcweir { 447cdf0e10cSrcweir //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::lcl_GetColumnStr" ); 448cdf0e10cSrcweir if ( nColumn < 26 ) 449cdf0e10cSrcweir return ::rtl::OUString::valueOf( (sal_Unicode) ( 'A' + nColumn ) ); 450cdf0e10cSrcweir else 451cdf0e10cSrcweir { 452cdf0e10cSrcweir ::rtl::OUStringBuffer aBuffer(2); 453cdf0e10cSrcweir aBuffer.setLength( 2 ); 454cdf0e10cSrcweir aBuffer.setCharAt( 0, (sal_Unicode) ( 'A' + ( nColumn / 26 ) - 1 ) ); 455cdf0e10cSrcweir aBuffer.setCharAt( 1, (sal_Unicode) ( 'A' + ( nColumn % 26 ) ) ); 456cdf0e10cSrcweir return aBuffer.makeStringAndClear(); 457cdf0e10cSrcweir } 458cdf0e10cSrcweir } 459cdf0e10cSrcweir 460cdf0e10cSrcweir void OCalcTable::fillColumns() 461cdf0e10cSrcweir { 462cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::fillColumns" ); 463cdf0e10cSrcweir if ( !m_xSheet.is() ) 464cdf0e10cSrcweir throw SQLException(); 465cdf0e10cSrcweir 466cdf0e10cSrcweir String aStrFieldName; 467cdf0e10cSrcweir aStrFieldName.AssignAscii("Column"); 468cdf0e10cSrcweir ::rtl::OUString aTypeName; 469cdf0e10cSrcweir ::comphelper::UStringMixEqual aCase(m_pConnection->getMetaData()->supportsMixedCaseQuotedIdentifiers()); 470cdf0e10cSrcweir const sal_Bool bStoresMixedCaseQuotedIdentifiers = getConnection()->getMetaData()->supportsMixedCaseQuotedIdentifiers(); 471cdf0e10cSrcweir 472cdf0e10cSrcweir for (sal_Int32 i = 0; i < m_nDataCols; i++) 473cdf0e10cSrcweir { 474cdf0e10cSrcweir ::rtl::OUString aColumnName; 475cdf0e10cSrcweir sal_Int32 eType = DataType::OTHER; 476cdf0e10cSrcweir sal_Bool bCurrency = sal_False; 477cdf0e10cSrcweir 478cdf0e10cSrcweir lcl_GetColumnInfo( m_xSheet, m_xFormats, m_nStartCol + i, m_nStartRow, m_bHasHeaders, 479cdf0e10cSrcweir aColumnName, eType, bCurrency ); 480cdf0e10cSrcweir 481cdf0e10cSrcweir if ( !aColumnName.getLength() ) 482cdf0e10cSrcweir aColumnName = lcl_GetColumnStr( i ); 483cdf0e10cSrcweir 484cdf0e10cSrcweir sal_Int32 nPrecision = 0; //! ... 485cdf0e10cSrcweir sal_Int32 nDecimals = 0; //! ... 486cdf0e10cSrcweir 487cdf0e10cSrcweir switch ( eType ) 488cdf0e10cSrcweir { 489cdf0e10cSrcweir case DataType::VARCHAR: 490cdf0e10cSrcweir { 491cdf0e10cSrcweir static const ::rtl::OUString s_sType(RTL_CONSTASCII_USTRINGPARAM("VARCHAR")); 492cdf0e10cSrcweir aTypeName = s_sType; 493cdf0e10cSrcweir } 494cdf0e10cSrcweir break; 495cdf0e10cSrcweir case DataType::DECIMAL: 496cdf0e10cSrcweir aTypeName = ::rtl::OUString::createFromAscii("DECIMAL"); 497cdf0e10cSrcweir break; 498cdf0e10cSrcweir case DataType::BIT: 499cdf0e10cSrcweir aTypeName = ::rtl::OUString::createFromAscii("BOOL"); 500cdf0e10cSrcweir break; 501cdf0e10cSrcweir case DataType::DATE: 502cdf0e10cSrcweir aTypeName = ::rtl::OUString::createFromAscii("DATE"); 503cdf0e10cSrcweir break; 504cdf0e10cSrcweir case DataType::TIME: 505cdf0e10cSrcweir aTypeName = ::rtl::OUString::createFromAscii("TIME"); 506cdf0e10cSrcweir break; 507cdf0e10cSrcweir case DataType::TIMESTAMP: 508cdf0e10cSrcweir aTypeName = ::rtl::OUString::createFromAscii("TIMESTAMP"); 509cdf0e10cSrcweir break; 510cdf0e10cSrcweir default: 511cdf0e10cSrcweir OSL_ASSERT("missing type name"); 512cdf0e10cSrcweir aTypeName = ::rtl::OUString(); 513cdf0e10cSrcweir } 514cdf0e10cSrcweir 515cdf0e10cSrcweir // check if the column name already exists 516cdf0e10cSrcweir ::rtl::OUString aAlias = aColumnName; 517cdf0e10cSrcweir OSQLColumns::Vector::const_iterator aFind = connectivity::find(m_aColumns->get().begin(),m_aColumns->get().end(),aAlias,aCase); 518cdf0e10cSrcweir sal_Int32 nExprCnt = 0; 519cdf0e10cSrcweir while(aFind != m_aColumns->get().end()) 520cdf0e10cSrcweir { 521cdf0e10cSrcweir (aAlias = aColumnName) += ::rtl::OUString::valueOf((sal_Int32)++nExprCnt); 522cdf0e10cSrcweir aFind = connectivity::find(m_aColumns->get().begin(),m_aColumns->get().end(),aAlias,aCase); 523cdf0e10cSrcweir } 524cdf0e10cSrcweir 525cdf0e10cSrcweir sdbcx::OColumn* pColumn = new sdbcx::OColumn( aAlias, aTypeName, ::rtl::OUString(),::rtl::OUString(), 526cdf0e10cSrcweir ColumnValue::NULLABLE, nPrecision, nDecimals, 527cdf0e10cSrcweir eType, sal_False, sal_False, bCurrency, 528cdf0e10cSrcweir bStoresMixedCaseQuotedIdentifiers); 529cdf0e10cSrcweir Reference< XPropertySet> xCol = pColumn; 530cdf0e10cSrcweir m_aColumns->get().push_back(xCol); 531cdf0e10cSrcweir m_aTypes.push_back(eType); 532cdf0e10cSrcweir m_aPrecisions.push_back(nPrecision); 533cdf0e10cSrcweir m_aScales.push_back(nDecimals); 534cdf0e10cSrcweir } 535cdf0e10cSrcweir } 536cdf0e10cSrcweir 537cdf0e10cSrcweir // ------------------------------------------------------------------------- 538cdf0e10cSrcweir OCalcTable::OCalcTable(sdbcx::OCollection* _pTables,OCalcConnection* _pConnection, 539cdf0e10cSrcweir const ::rtl::OUString& _Name, 540cdf0e10cSrcweir const ::rtl::OUString& _Type, 541cdf0e10cSrcweir const ::rtl::OUString& _Description , 542cdf0e10cSrcweir const ::rtl::OUString& _SchemaName, 543cdf0e10cSrcweir const ::rtl::OUString& _CatalogName 544cdf0e10cSrcweir ) : OCalcTable_BASE(_pTables,_pConnection,_Name, 545cdf0e10cSrcweir _Type, 546cdf0e10cSrcweir _Description, 547cdf0e10cSrcweir _SchemaName, 548cdf0e10cSrcweir _CatalogName) 549cdf0e10cSrcweir ,m_pConnection(_pConnection) 550cdf0e10cSrcweir ,m_nStartCol(0) 551cdf0e10cSrcweir ,m_nStartRow(0) 552cdf0e10cSrcweir ,m_nDataCols(0) 553cdf0e10cSrcweir ,m_nDataRows(0) 554cdf0e10cSrcweir ,m_bHasHeaders(sal_False) 555cdf0e10cSrcweir { 556cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::OCalcTable" ); 557cdf0e10cSrcweir } 558cdf0e10cSrcweir // ----------------------------------------------------------------------------- 559cdf0e10cSrcweir void OCalcTable::construct() 560cdf0e10cSrcweir { 561cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::construct" ); 562cdf0e10cSrcweir // get sheet object 563cdf0e10cSrcweir Reference< XSpreadsheetDocument> xDoc = m_pConnection->acquireDoc(); 564cdf0e10cSrcweir if (xDoc.is()) 565cdf0e10cSrcweir { 566cdf0e10cSrcweir Reference<XSpreadsheets> xSheets = xDoc->getSheets(); 567cdf0e10cSrcweir if ( xSheets.is() && xSheets->hasByName( m_Name ) ) 568cdf0e10cSrcweir { 569cdf0e10cSrcweir m_xSheet.set(xSheets->getByName( m_Name ),UNO_QUERY); 570cdf0e10cSrcweir if ( m_xSheet.is() ) 571cdf0e10cSrcweir { 572cdf0e10cSrcweir lcl_GetDataArea( m_xSheet, m_nDataCols, m_nDataRows ); 573cdf0e10cSrcweir m_bHasHeaders = sal_True; 574cdf0e10cSrcweir // whole sheet is always assumed to include a header row 575cdf0e10cSrcweir } 576cdf0e10cSrcweir } 577cdf0e10cSrcweir else // no sheet -> try database range 578cdf0e10cSrcweir { 579cdf0e10cSrcweir Reference<XPropertySet> xDocProp( xDoc, UNO_QUERY ); 580cdf0e10cSrcweir if ( xDocProp.is() ) 581cdf0e10cSrcweir { 582cdf0e10cSrcweir Reference<XDatabaseRanges> xRanges(xDocProp->getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DatabaseRanges")) ),UNO_QUERY); 583cdf0e10cSrcweir 584cdf0e10cSrcweir if ( xRanges.is() && xRanges->hasByName( m_Name ) ) 585cdf0e10cSrcweir { 586cdf0e10cSrcweir Reference<XDatabaseRange> xDBRange(xRanges->getByName( m_Name ),UNO_QUERY); 587cdf0e10cSrcweir Reference<XCellRangeReferrer> xRefer( xDBRange, UNO_QUERY ); 588cdf0e10cSrcweir if ( xRefer.is() ) 589cdf0e10cSrcweir { 590cdf0e10cSrcweir // Header flag is always stored with database range 591cdf0e10cSrcweir // Get flag from FilterDescriptor 592cdf0e10cSrcweir 593cdf0e10cSrcweir sal_Bool bRangeHeader = sal_True; 594cdf0e10cSrcweir Reference<XPropertySet> xFiltProp( xDBRange->getFilterDescriptor(), UNO_QUERY ); 595cdf0e10cSrcweir if ( xFiltProp.is() ) 596cdf0e10cSrcweir xFiltProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ContainsHeader"))) >>= bRangeHeader; 597cdf0e10cSrcweir 598cdf0e10cSrcweir Reference<XSheetCellRange> xSheetRange( xRefer->getReferredCells(), UNO_QUERY ); 599cdf0e10cSrcweir Reference<XCellRangeAddressable> xAddr( xSheetRange, UNO_QUERY ); 600cdf0e10cSrcweir if ( xSheetRange.is() && xAddr.is() ) 601cdf0e10cSrcweir { 602cdf0e10cSrcweir m_xSheet = xSheetRange->getSpreadsheet(); 603cdf0e10cSrcweir CellRangeAddress aRangeAddr = xAddr->getRangeAddress(); 604cdf0e10cSrcweir m_nStartCol = aRangeAddr.StartColumn; 605cdf0e10cSrcweir m_nStartRow = aRangeAddr.StartRow; 606cdf0e10cSrcweir m_nDataCols = aRangeAddr.EndColumn - m_nStartCol + 1; 607cdf0e10cSrcweir // m_nDataRows is excluding header row 608cdf0e10cSrcweir m_nDataRows = aRangeAddr.EndRow - m_nStartRow; 609cdf0e10cSrcweir if ( !bRangeHeader ) 610cdf0e10cSrcweir { 611cdf0e10cSrcweir // m_nDataRows counts the whole range 612cdf0e10cSrcweir m_nDataRows += 1; 613cdf0e10cSrcweir } 614cdf0e10cSrcweir 615cdf0e10cSrcweir m_bHasHeaders = bRangeHeader; 616cdf0e10cSrcweir } 617cdf0e10cSrcweir } 618cdf0e10cSrcweir } 619cdf0e10cSrcweir } 620cdf0e10cSrcweir } 621cdf0e10cSrcweir 622cdf0e10cSrcweir Reference<XNumberFormatsSupplier> xSupp( xDoc, UNO_QUERY ); 623cdf0e10cSrcweir if (xSupp.is()) 624cdf0e10cSrcweir m_xFormats = xSupp->getNumberFormats(); 625cdf0e10cSrcweir 626cdf0e10cSrcweir Reference<XPropertySet> xProp( xDoc, UNO_QUERY ); 627cdf0e10cSrcweir if (xProp.is()) 628cdf0e10cSrcweir { 629cdf0e10cSrcweir ::com::sun::star::util::Date aDateStruct; 630cdf0e10cSrcweir if ( xProp->getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("NullDate")) ) >>= aDateStruct ) 631cdf0e10cSrcweir m_aNullDate = ::Date( aDateStruct.Day, aDateStruct.Month, aDateStruct.Year ); 632cdf0e10cSrcweir } 633cdf0e10cSrcweir } 634cdf0e10cSrcweir 635cdf0e10cSrcweir //! default if no null date available? 636cdf0e10cSrcweir 637cdf0e10cSrcweir fillColumns(); 638cdf0e10cSrcweir 639cdf0e10cSrcweir refreshColumns(); 640cdf0e10cSrcweir } 641cdf0e10cSrcweir // ------------------------------------------------------------------------- 642cdf0e10cSrcweir void OCalcTable::refreshColumns() 643cdf0e10cSrcweir { 644cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::refreshColumns" ); 645cdf0e10cSrcweir ::osl::MutexGuard aGuard( m_aMutex ); 646cdf0e10cSrcweir 647cdf0e10cSrcweir TStringVector aVector; 648cdf0e10cSrcweir 649cdf0e10cSrcweir OSQLColumns::Vector::const_iterator aEnd = m_aColumns->get().end(); 650cdf0e10cSrcweir for(OSQLColumns::Vector::const_iterator aIter = m_aColumns->get().begin();aIter != aEnd;++aIter) 651cdf0e10cSrcweir aVector.push_back(Reference< XNamed>(*aIter,UNO_QUERY)->getName()); 652cdf0e10cSrcweir 653cdf0e10cSrcweir if(m_pColumns) 654cdf0e10cSrcweir m_pColumns->reFill(aVector); 655cdf0e10cSrcweir else 656cdf0e10cSrcweir m_pColumns = new OCalcColumns(this,m_aMutex,aVector); 657cdf0e10cSrcweir } 658cdf0e10cSrcweir // ------------------------------------------------------------------------- 659cdf0e10cSrcweir void OCalcTable::refreshIndexes() 660cdf0e10cSrcweir { 661cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::refreshIndexes" ); 662cdf0e10cSrcweir // Calc table has no index 663cdf0e10cSrcweir } 664cdf0e10cSrcweir 665cdf0e10cSrcweir // ------------------------------------------------------------------------- 666cdf0e10cSrcweir void SAL_CALL OCalcTable::disposing(void) 667cdf0e10cSrcweir { 668cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::disposing" ); 669cdf0e10cSrcweir OFileTable::disposing(); 670cdf0e10cSrcweir ::osl::MutexGuard aGuard(m_aMutex); 671cdf0e10cSrcweir m_aColumns = NULL; 672cdf0e10cSrcweir if ( m_pConnection ) 673cdf0e10cSrcweir m_pConnection->releaseDoc(); 674cdf0e10cSrcweir m_pConnection = NULL; 675cdf0e10cSrcweir 676cdf0e10cSrcweir } 677cdf0e10cSrcweir // ------------------------------------------------------------------------- 678cdf0e10cSrcweir Sequence< Type > SAL_CALL OCalcTable::getTypes( ) throw(RuntimeException) 679cdf0e10cSrcweir { 680cdf0e10cSrcweir //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::getTypes" ); 681cdf0e10cSrcweir Sequence< Type > aTypes = OTable_TYPEDEF::getTypes(); 682cdf0e10cSrcweir ::std::vector<Type> aOwnTypes; 683cdf0e10cSrcweir aOwnTypes.reserve(aTypes.getLength()); 684cdf0e10cSrcweir 685cdf0e10cSrcweir const Type* pBegin = aTypes.getConstArray(); 686cdf0e10cSrcweir const Type* pEnd = pBegin + aTypes.getLength(); 687cdf0e10cSrcweir for(;pBegin != pEnd;++pBegin) 688cdf0e10cSrcweir { 689cdf0e10cSrcweir if(!( *pBegin == ::getCppuType((const Reference<XKeysSupplier>*)0) || 690cdf0e10cSrcweir *pBegin == ::getCppuType((const Reference<XIndexesSupplier>*)0) || 691cdf0e10cSrcweir *pBegin == ::getCppuType((const Reference<XRename>*)0) || 692cdf0e10cSrcweir *pBegin == ::getCppuType((const Reference<XAlterTable>*)0) || 693cdf0e10cSrcweir *pBegin == ::getCppuType((const Reference<XDataDescriptorFactory>*)0))) 694cdf0e10cSrcweir aOwnTypes.push_back(*pBegin); 695cdf0e10cSrcweir } 696cdf0e10cSrcweir aOwnTypes.push_back(::getCppuType( (const Reference< ::com::sun::star::lang::XUnoTunnel > *)0 )); 697cdf0e10cSrcweir 698cdf0e10cSrcweir const Type* pAttrs = aOwnTypes.empty() ? 0 : &aOwnTypes[0]; 699cdf0e10cSrcweir return Sequence< Type >(pAttrs, aOwnTypes.size()); 700cdf0e10cSrcweir } 701cdf0e10cSrcweir 702cdf0e10cSrcweir // ------------------------------------------------------------------------- 703cdf0e10cSrcweir Any SAL_CALL OCalcTable::queryInterface( const Type & rType ) throw(RuntimeException) 704cdf0e10cSrcweir { 705cdf0e10cSrcweir if( rType == ::getCppuType((const Reference<XKeysSupplier>*)0) || 706cdf0e10cSrcweir rType == ::getCppuType((const Reference<XIndexesSupplier>*)0) || 707cdf0e10cSrcweir rType == ::getCppuType((const Reference<XRename>*)0) || 708cdf0e10cSrcweir rType == ::getCppuType((const Reference<XAlterTable>*)0) || 709cdf0e10cSrcweir rType == ::getCppuType((const Reference<XDataDescriptorFactory>*)0)) 710cdf0e10cSrcweir return Any(); 711cdf0e10cSrcweir 712cdf0e10cSrcweir const Any aRet = ::cppu::queryInterface(rType,static_cast< ::com::sun::star::lang::XUnoTunnel*> (this)); 713cdf0e10cSrcweir return aRet.hasValue() ? aRet : OTable_TYPEDEF::queryInterface(rType); 714cdf0e10cSrcweir } 715cdf0e10cSrcweir 716cdf0e10cSrcweir //-------------------------------------------------------------------------- 717cdf0e10cSrcweir Sequence< sal_Int8 > OCalcTable::getUnoTunnelImplementationId() 718cdf0e10cSrcweir { 719cdf0e10cSrcweir //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::getUnoTunnelImplementationId" ); 720cdf0e10cSrcweir static ::cppu::OImplementationId * pId = 0; 721cdf0e10cSrcweir if (! pId) 722cdf0e10cSrcweir { 723cdf0e10cSrcweir ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); 724cdf0e10cSrcweir if (! pId) 725cdf0e10cSrcweir { 726cdf0e10cSrcweir static ::cppu::OImplementationId aId; 727cdf0e10cSrcweir pId = &aId; 728cdf0e10cSrcweir } 729cdf0e10cSrcweir } 730cdf0e10cSrcweir return pId->getImplementationId(); 731cdf0e10cSrcweir } 732cdf0e10cSrcweir 733cdf0e10cSrcweir // com::sun::star::lang::XUnoTunnel 734cdf0e10cSrcweir //------------------------------------------------------------------ 735cdf0e10cSrcweir sal_Int64 OCalcTable::getSomething( const Sequence< sal_Int8 > & rId ) throw (RuntimeException) 736cdf0e10cSrcweir { 737cdf0e10cSrcweir //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::getSomething" ); 738cdf0e10cSrcweir return (rId.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(), rId.getConstArray(), 16 ) ) 739cdf0e10cSrcweir ? reinterpret_cast< sal_Int64 >( this ) 740cdf0e10cSrcweir : OCalcTable_BASE::getSomething(rId); 741cdf0e10cSrcweir } 742cdf0e10cSrcweir //------------------------------------------------------------------ 743cdf0e10cSrcweir sal_Int32 OCalcTable::getCurrentLastPos() const 744cdf0e10cSrcweir { 745cdf0e10cSrcweir //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::getCurrentLastPos" ); 746cdf0e10cSrcweir return m_nDataRows; 747cdf0e10cSrcweir } 748cdf0e10cSrcweir //------------------------------------------------------------------ 749cdf0e10cSrcweir sal_Bool OCalcTable::seekRow(IResultSetHelper::Movement eCursorPosition, sal_Int32 nOffset, sal_Int32& nCurPos) 750cdf0e10cSrcweir { 751cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::seekRow" ); 752cdf0e10cSrcweir // ---------------------------------------------------------- 753cdf0e10cSrcweir // Positionierung vorbereiten: 754cdf0e10cSrcweir 755cdf0e10cSrcweir sal_uInt32 nNumberOfRecords = m_nDataRows; 756cdf0e10cSrcweir sal_uInt32 nTempPos = m_nFilePos; 757cdf0e10cSrcweir m_nFilePos = nCurPos; 758cdf0e10cSrcweir 759cdf0e10cSrcweir switch(eCursorPosition) 760cdf0e10cSrcweir { 761cdf0e10cSrcweir case IResultSetHelper::NEXT: 762cdf0e10cSrcweir m_nFilePos++; 763cdf0e10cSrcweir break; 764cdf0e10cSrcweir case IResultSetHelper::PRIOR: 765cdf0e10cSrcweir if (m_nFilePos > 0) 766cdf0e10cSrcweir m_nFilePos--; 767cdf0e10cSrcweir break; 768cdf0e10cSrcweir case IResultSetHelper::FIRST: 769cdf0e10cSrcweir m_nFilePos = 1; 770cdf0e10cSrcweir break; 771cdf0e10cSrcweir case IResultSetHelper::LAST: 772cdf0e10cSrcweir m_nFilePos = nNumberOfRecords; 773cdf0e10cSrcweir break; 774cdf0e10cSrcweir case IResultSetHelper::RELATIVE: 775cdf0e10cSrcweir m_nFilePos = (((sal_Int32)m_nFilePos) + nOffset < 0) ? 0L 776cdf0e10cSrcweir : (sal_uInt32)(((sal_Int32)m_nFilePos) + nOffset); 777cdf0e10cSrcweir break; 778cdf0e10cSrcweir case IResultSetHelper::ABSOLUTE: 779cdf0e10cSrcweir case IResultSetHelper::BOOKMARK: 780cdf0e10cSrcweir m_nFilePos = (sal_uInt32)nOffset; 781cdf0e10cSrcweir break; 782cdf0e10cSrcweir } 783cdf0e10cSrcweir 784cdf0e10cSrcweir if (m_nFilePos > (sal_Int32)nNumberOfRecords) 785cdf0e10cSrcweir m_nFilePos = (sal_Int32)nNumberOfRecords + 1; 786cdf0e10cSrcweir 787cdf0e10cSrcweir if (m_nFilePos == 0 || m_nFilePos == (sal_Int32)nNumberOfRecords + 1) 788cdf0e10cSrcweir goto Error; 789cdf0e10cSrcweir else 790cdf0e10cSrcweir { 791cdf0e10cSrcweir //! read buffer / setup row object etc? 792cdf0e10cSrcweir } 793cdf0e10cSrcweir goto End; 794cdf0e10cSrcweir 795cdf0e10cSrcweir Error: 796cdf0e10cSrcweir switch(eCursorPosition) 797cdf0e10cSrcweir { 798cdf0e10cSrcweir case IResultSetHelper::PRIOR: 799cdf0e10cSrcweir case IResultSetHelper::FIRST: 800cdf0e10cSrcweir m_nFilePos = 0; 801cdf0e10cSrcweir break; 802cdf0e10cSrcweir case IResultSetHelper::LAST: 803cdf0e10cSrcweir case IResultSetHelper::NEXT: 804cdf0e10cSrcweir case IResultSetHelper::ABSOLUTE: 805cdf0e10cSrcweir case IResultSetHelper::RELATIVE: 806cdf0e10cSrcweir if (nOffset > 0) 807cdf0e10cSrcweir m_nFilePos = nNumberOfRecords + 1; 808cdf0e10cSrcweir else if (nOffset < 0) 809cdf0e10cSrcweir m_nFilePos = 0; 810cdf0e10cSrcweir break; 811cdf0e10cSrcweir case IResultSetHelper::BOOKMARK: 812cdf0e10cSrcweir m_nFilePos = nTempPos; // vorherige Position 813cdf0e10cSrcweir } 814cdf0e10cSrcweir // aStatus.Set(SDB_STAT_NO_DATA_FOUND); 815cdf0e10cSrcweir return sal_False; 816cdf0e10cSrcweir 817cdf0e10cSrcweir End: 818cdf0e10cSrcweir nCurPos = m_nFilePos; 819cdf0e10cSrcweir return sal_True; 820cdf0e10cSrcweir } 821cdf0e10cSrcweir //------------------------------------------------------------------ 822cdf0e10cSrcweir sal_Bool OCalcTable::fetchRow( OValueRefRow& _rRow, const OSQLColumns & _rCols, 823cdf0e10cSrcweir sal_Bool _bUseTableDefs, sal_Bool bRetrieveData ) 824cdf0e10cSrcweir { 825cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::fetchRow" ); 826cdf0e10cSrcweir // read the bookmark 827cdf0e10cSrcweir 828cdf0e10cSrcweir sal_Bool bIsCurRecordDeleted = sal_False; 829cdf0e10cSrcweir _rRow->setDeleted(bIsCurRecordDeleted); 830cdf0e10cSrcweir *(_rRow->get())[0] = m_nFilePos; 831cdf0e10cSrcweir 832cdf0e10cSrcweir if (!bRetrieveData) 833cdf0e10cSrcweir return sal_True; 834cdf0e10cSrcweir 835cdf0e10cSrcweir // fields 836cdf0e10cSrcweir 837cdf0e10cSrcweir OSQLColumns::Vector::const_iterator aIter = _rCols.get().begin(); 838cdf0e10cSrcweir OSQLColumns::Vector::const_iterator aEnd = _rCols.get().end(); 839cdf0e10cSrcweir const OValueRefVector::Vector::size_type nCount = _rRow->get().size(); 840cdf0e10cSrcweir for (OValueRefVector::Vector::size_type i = 1; aIter != aEnd && i < nCount; 841cdf0e10cSrcweir ++aIter, i++) 842cdf0e10cSrcweir { 843cdf0e10cSrcweir if ( (_rRow->get())[i]->isBound() ) 844cdf0e10cSrcweir { 845cdf0e10cSrcweir sal_Int32 nType = 0; 846cdf0e10cSrcweir if ( _bUseTableDefs ) 847cdf0e10cSrcweir nType = m_aTypes[i-1]; 848cdf0e10cSrcweir else 849cdf0e10cSrcweir (*aIter)->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)) >>= nType; 850cdf0e10cSrcweir 851cdf0e10cSrcweir 852cdf0e10cSrcweir lcl_SetValue( (_rRow->get())[i]->get(), m_xSheet, m_nStartCol, m_nStartRow, m_bHasHeaders, 853cdf0e10cSrcweir m_aNullDate, m_nFilePos, i, nType ); 854cdf0e10cSrcweir } 855cdf0e10cSrcweir } 856cdf0e10cSrcweir return sal_True; 857cdf0e10cSrcweir } 858cdf0e10cSrcweir // ------------------------------------------------------------------------- 859cdf0e10cSrcweir void OCalcTable::FileClose() 860cdf0e10cSrcweir { 861cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::FileClose" ); 862cdf0e10cSrcweir ::osl::MutexGuard aGuard(m_aMutex); 863cdf0e10cSrcweir 864cdf0e10cSrcweir OCalcTable_BASE::FileClose(); 865cdf0e10cSrcweir } 866cdf0e10cSrcweir // ------------------------------------------------------------------------- 867cdf0e10cSrcweir 868