/************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_connectivity.hxx" #include "calc/CTable.hxx" #include #include //#ifndef _COM_SUN_STAR_UCB_XCONTENTACCESS_HPP_ //#include //#endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "calc/CConnection.hxx" #include "calc/CColumns.hxx" #include "connectivity/sdbcx/VColumn.hxx" #include #include #include #include #include #include #include #include #include #include #include using namespace connectivity; using namespace connectivity::calc; using namespace connectivity::file; using namespace ::cppu; using namespace ::dbtools; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::beans; using namespace ::com::sun::star::sdbcx; using namespace ::com::sun::star::sdbc; using namespace ::com::sun::star::container; using namespace ::com::sun::star::lang; using namespace ::com::sun::star::sheet; using namespace ::com::sun::star::table; using namespace ::com::sun::star::text; using namespace ::com::sun::star::util; // ------------------------------------------------------------------------- void lcl_UpdateArea( const Reference& xUsedRange, sal_Int32& rEndCol, sal_Int32& rEndRow ) { //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::lcl_UpdateArea" ); // update rEndCol, rEndRow if any non-empty cell in xUsedRange is right/below const Reference xUsedQuery( xUsedRange, UNO_QUERY ); if ( xUsedQuery.is() ) { const sal_Int16 nContentFlags = CellFlags::STRING | CellFlags::VALUE | CellFlags::DATETIME | CellFlags::FORMULA | CellFlags::ANNOTATION; const Reference xUsedRanges = xUsedQuery->queryContentCells( nContentFlags ); const Sequence aAddresses = xUsedRanges->getRangeAddresses(); const sal_Int32 nCount = aAddresses.getLength(); const CellRangeAddress* pData = aAddresses.getConstArray(); for ( sal_Int32 i=0; i rEndCol ? pData[i].EndColumn : rEndCol; rEndRow = pData[i].EndRow > rEndRow ? pData[i].EndRow : rEndRow; } } } void lcl_GetDataArea( const Reference& xSheet, sal_Int32& rColumnCount, sal_Int32& rRowCount ) { //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::lcl_GetDataArea" ); Reference xCursor = xSheet->createCursor(); Reference xRange( xCursor, UNO_QUERY ); if ( !xRange.is() ) { rColumnCount = rRowCount = 0; return; } // first find the contiguous cell area starting at A1 xCursor->collapseToSize( 1, 1 ); // single (first) cell xCursor->collapseToCurrentRegion(); // contiguous data area CellRangeAddress aRegionAddr = xRange->getRangeAddress(); sal_Int32 nEndCol = aRegionAddr.EndColumn; sal_Int32 nEndRow = aRegionAddr.EndRow; Reference xUsed( xCursor, UNO_QUERY ); if ( xUsed.is() ) { // The used area from XUsedAreaCursor includes visible attributes. // If the used area is larger than the contiguous cell area, find non-empty // cells in that area. xUsed->gotoEndOfUsedArea( sal_False ); CellRangeAddress aUsedAddr = xRange->getRangeAddress(); if ( aUsedAddr.EndColumn > aRegionAddr.EndColumn ) { Reference xUsedRange = xSheet->getCellRangeByPosition( aRegionAddr.EndColumn + 1, 0, aUsedAddr.EndColumn, aUsedAddr.EndRow ); lcl_UpdateArea( xUsedRange, nEndCol, nEndRow ); } if ( aUsedAddr.EndRow > aRegionAddr.EndRow ) { // only up to the last column of aRegionAddr, the other columns are handled above Reference xUsedRange = xSheet->getCellRangeByPosition( 0, aRegionAddr.EndRow + 1, aRegionAddr.EndColumn, aUsedAddr.EndRow ); lcl_UpdateArea( xUsedRange, nEndCol, nEndRow ); } } rColumnCount = nEndCol + 1; // number of columns rRowCount = nEndRow; // first row (headers) is not counted } CellContentType lcl_GetContentOrResultType( const Reference& xCell ) { //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::lcl_GetContentOrResultType" ); CellContentType eCellType = xCell->getType(); if ( eCellType == CellContentType_FORMULA ) { static const ::rtl::OUString s_sFormulaResultType(RTL_CONSTASCII_USTRINGPARAM("FormulaResultType")); Reference xProp( xCell, UNO_QUERY ); try { xProp->getPropertyValue( s_sFormulaResultType ) >>= eCellType; // type of formula result } catch (UnknownPropertyException&) { eCellType = CellContentType_VALUE; // if FormulaResultType property not available } } return eCellType; } Reference lcl_GetUsedCell( const Reference& xSheet, sal_Int32 nDocColumn, sal_Int32 nDocRow ) { //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::lcl_GetUsedCell" ); Reference xCell = xSheet->getCellByPosition( nDocColumn, nDocRow ); if ( xCell.is() && xCell->getType() == CellContentType_EMPTY ) { // get first non-empty cell Reference xAddr( xSheet, UNO_QUERY ); if (xAddr.is()) { CellRangeAddress aTotalRange = xAddr->getRangeAddress(); sal_Int32 nLastRow = aTotalRange.EndRow; Reference xQuery( xSheet->getCellRangeByPosition( nDocColumn, nDocRow, nDocColumn, nLastRow ), UNO_QUERY ); if (xQuery.is()) { // queryIntersection to get a ranges object Reference xRanges = xQuery->queryIntersection( aTotalRange ); if (xRanges.is()) { Reference xCells = xRanges->getCells(); if (xCells.is()) { Reference xEnum = xCells->createEnumeration(); if ( xEnum.is() && xEnum->hasMoreElements() ) { // get first non-empty cell from enumeration xCell.set(xEnum->nextElement(),UNO_QUERY); } // otherwise, keep empty cell } } } } } return xCell; } bool lcl_HasTextInColumn( const Reference& xSheet, sal_Int32 nDocColumn, sal_Int32 nDocRow ) { //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::lcl_HasTextInColumn" ); // look for any text cell or text result in the column Reference xAddr( xSheet, UNO_QUERY ); if (xAddr.is()) { CellRangeAddress aTotalRange = xAddr->getRangeAddress(); sal_Int32 nLastRow = aTotalRange.EndRow; Reference xQuery( xSheet->getCellRangeByPosition( nDocColumn, nDocRow, nDocColumn, nLastRow ), UNO_QUERY ); if (xQuery.is()) { // are there text cells in the column? Reference xTextContent = xQuery->queryContentCells( CellFlags::STRING ); if ( xTextContent.is() && xTextContent->hasElements() ) return true; // are there formulas with text results in the column? Reference xTextFormula = xQuery->queryFormulaCells( FormulaResult::STRING ); if ( xTextFormula.is() && xTextFormula->hasElements() ) return true; } } return false; } void lcl_GetColumnInfo( const Reference& xSheet, const Reference& xFormats, sal_Int32 nDocColumn, sal_Int32 nStartRow, sal_Bool bHasHeaders, ::rtl::OUString& rName, sal_Int32& rDataType, sal_Bool& rCurrency ) { //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::lcl_GetColumnInfo" ); //! avoid duplicate field names // get column name from first row, if range contains headers if ( bHasHeaders ) { Reference xHeaderText( xSheet->getCellByPosition( nDocColumn, nStartRow ), UNO_QUERY ); if ( xHeaderText.is() ) rName = xHeaderText->getString(); } // get column type from first data row sal_Int32 nDataRow = nStartRow; if ( bHasHeaders ) ++nDataRow; Reference xDataCell = lcl_GetUsedCell( xSheet, nDocColumn, nDataRow ); Reference xProp( xDataCell, UNO_QUERY ); if ( xProp.is() ) { rCurrency = sal_False; // set to true for currency below const CellContentType eCellType = lcl_GetContentOrResultType( xDataCell ); // #i35178# use "text" type if there is any text cell in the column if ( eCellType == CellContentType_TEXT || lcl_HasTextInColumn( xSheet, nDocColumn, nDataRow ) ) rDataType = DataType::VARCHAR; else if ( eCellType == CellContentType_VALUE ) { // get number format to distinguish between different types sal_Int16 nNumType = NumberFormat::NUMBER; try { static ::rtl::OUString s_NumberFormat(RTL_CONSTASCII_USTRINGPARAM("NumberFormat")); sal_Int32 nKey = 0; if ( xProp->getPropertyValue( s_NumberFormat ) >>= nKey ) { const Reference xFormat = xFormats->getByKey( nKey ); if ( xFormat.is() ) { xFormat->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE) ) >>= nNumType; } } } catch ( Exception& ) { } if ( nNumType & NumberFormat::TEXT ) rDataType = DataType::VARCHAR; else if ( nNumType & NumberFormat::NUMBER ) rDataType = DataType::DECIMAL; else if ( nNumType & NumberFormat::CURRENCY ) { rCurrency = sal_True; rDataType = DataType::DECIMAL; } else if ( ( nNumType & NumberFormat::DATETIME ) == NumberFormat::DATETIME ) { // NumberFormat::DATETIME is DATE | TIME rDataType = DataType::TIMESTAMP; } else if ( nNumType & NumberFormat::DATE ) rDataType = DataType::DATE; else if ( nNumType & NumberFormat::TIME ) rDataType = DataType::TIME; else if ( nNumType & NumberFormat::LOGICAL ) rDataType = DataType::BIT; else rDataType = DataType::DECIMAL; } else { // whole column empty rDataType = DataType::VARCHAR; } } } // ------------------------------------------------------------------------- void lcl_SetValue( ORowSetValue& rValue, const Reference& xSheet, sal_Int32 nStartCol, sal_Int32 nStartRow, sal_Bool bHasHeaders, const ::Date& rNullDate, sal_Int32 nDBRow, sal_Int32 nDBColumn, sal_Int32 nType ) { //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::lcl_SetValue" ); sal_Int32 nDocColumn = nStartCol + nDBColumn - 1; // database counts from 1 sal_Int32 nDocRow = nStartRow + nDBRow - 1; if (bHasHeaders) ++nDocRow; const Reference xCell = xSheet->getCellByPosition( nDocColumn, nDocRow ); if ( xCell.is() ) { CellContentType eCellType = lcl_GetContentOrResultType( xCell ); switch (nType) { case DataType::VARCHAR: if ( eCellType == CellContentType_EMPTY ) rValue.setNull(); else { // #i25840# still let Calc convert numbers to text const Reference xText( xCell, UNO_QUERY ); if ( xText.is() ) rValue = xText->getString(); } break; case DataType::DECIMAL: if ( eCellType == CellContentType_VALUE ) rValue = xCell->getValue(); // double else rValue.setNull(); break; case DataType::BIT: if ( eCellType == CellContentType_VALUE ) rValue = (sal_Bool)( xCell->getValue() != 0.0 ); else rValue.setNull(); break; case DataType::DATE: if ( eCellType == CellContentType_VALUE ) { ::Date aDate( rNullDate ); aDate += (long)::rtl::math::approxFloor( xCell->getValue() ); ::com::sun::star::util::Date aDateStruct( aDate.GetDay(), aDate.GetMonth(), aDate.GetYear() ); rValue = aDateStruct; } else rValue.setNull(); break; case DataType::TIME: if ( eCellType == CellContentType_VALUE ) { double fCellVal = xCell->getValue(); double fTime = fCellVal - rtl::math::approxFloor( fCellVal ); long nIntTime = (long)rtl::math::round( fTime * 8640000.0 ); if ( nIntTime == 8640000 ) nIntTime = 0; // 23:59:59.995 and above is 00:00:00.00 ::com::sun::star::util::Time aTime; aTime.HundredthSeconds = (sal_uInt16)( nIntTime % 100 ); nIntTime /= 100; aTime.Seconds = (sal_uInt16)( nIntTime % 60 ); nIntTime /= 60; aTime.Minutes = (sal_uInt16)( nIntTime % 60 ); nIntTime /= 60; OSL_ENSURE( nIntTime < 24, "error in time calculation" ); aTime.Hours = (sal_uInt16) nIntTime; rValue = aTime; } else rValue.setNull(); break; case DataType::TIMESTAMP: if ( eCellType == CellContentType_VALUE ) { double fCellVal = xCell->getValue(); double fDays = ::rtl::math::approxFloor( fCellVal ); double fTime = fCellVal - fDays; long nIntDays = (long)fDays; long nIntTime = (long)::rtl::math::round( fTime * 8640000.0 ); if ( nIntTime == 8640000 ) { nIntTime = 0; // 23:59:59.995 and above is 00:00:00.00 ++nIntDays; // (next day) } ::com::sun::star::util::DateTime aDateTime; aDateTime.HundredthSeconds = (sal_uInt16)( nIntTime % 100 ); nIntTime /= 100; aDateTime.Seconds = (sal_uInt16)( nIntTime % 60 ); nIntTime /= 60; aDateTime.Minutes = (sal_uInt16)( nIntTime % 60 ); nIntTime /= 60; OSL_ENSURE( nIntTime < 24, "error in time calculation" ); aDateTime.Hours = (sal_uInt16) nIntTime; ::Date aDate( rNullDate ); aDate += nIntDays; aDateTime.Day = aDate.GetDay(); aDateTime.Month = aDate.GetMonth(); aDateTime.Year = aDate.GetYear(); rValue = aDateTime; } else rValue.setNull(); break; } // switch (nType) } // rValue.setTypeKind(nType); } // ------------------------------------------------------------------------- ::rtl::OUString lcl_GetColumnStr( sal_Int32 nColumn ) { //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::lcl_GetColumnStr" ); if ( nColumn < 26 ) return ::rtl::OUString::valueOf( (sal_Unicode) ( 'A' + nColumn ) ); else { ::rtl::OUStringBuffer aBuffer(2); aBuffer.setLength( 2 ); aBuffer.setCharAt( 0, (sal_Unicode) ( 'A' + ( nColumn / 26 ) - 1 ) ); aBuffer.setCharAt( 1, (sal_Unicode) ( 'A' + ( nColumn % 26 ) ) ); return aBuffer.makeStringAndClear(); } } void OCalcTable::fillColumns() { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::fillColumns" ); if ( !m_xSheet.is() ) throw SQLException(); String aStrFieldName; aStrFieldName.AssignAscii("Column"); ::rtl::OUString aTypeName; ::comphelper::UStringMixEqual aCase(m_pConnection->getMetaData()->supportsMixedCaseQuotedIdentifiers()); const sal_Bool bStoresMixedCaseQuotedIdentifiers = getConnection()->getMetaData()->supportsMixedCaseQuotedIdentifiers(); for (sal_Int32 i = 0; i < m_nDataCols; i++) { ::rtl::OUString aColumnName; sal_Int32 eType = DataType::OTHER; sal_Bool bCurrency = sal_False; lcl_GetColumnInfo( m_xSheet, m_xFormats, m_nStartCol + i, m_nStartRow, m_bHasHeaders, aColumnName, eType, bCurrency ); if ( !aColumnName.getLength() ) aColumnName = lcl_GetColumnStr( i ); sal_Int32 nPrecision = 0; //! ... sal_Int32 nDecimals = 0; //! ... switch ( eType ) { case DataType::VARCHAR: { static const ::rtl::OUString s_sType(RTL_CONSTASCII_USTRINGPARAM("VARCHAR")); aTypeName = s_sType; } break; case DataType::DECIMAL: aTypeName = ::rtl::OUString::createFromAscii("DECIMAL"); break; case DataType::BIT: aTypeName = ::rtl::OUString::createFromAscii("BOOL"); break; case DataType::DATE: aTypeName = ::rtl::OUString::createFromAscii("DATE"); break; case DataType::TIME: aTypeName = ::rtl::OUString::createFromAscii("TIME"); break; case DataType::TIMESTAMP: aTypeName = ::rtl::OUString::createFromAscii("TIMESTAMP"); break; default: OSL_ASSERT("missing type name"); aTypeName = ::rtl::OUString(); } // check if the column name already exists ::rtl::OUString aAlias = aColumnName; OSQLColumns::Vector::const_iterator aFind = connectivity::find(m_aColumns->get().begin(),m_aColumns->get().end(),aAlias,aCase); sal_Int32 nExprCnt = 0; while(aFind != m_aColumns->get().end()) { (aAlias = aColumnName) += ::rtl::OUString::valueOf((sal_Int32)++nExprCnt); aFind = connectivity::find(m_aColumns->get().begin(),m_aColumns->get().end(),aAlias,aCase); } sdbcx::OColumn* pColumn = new sdbcx::OColumn( aAlias, aTypeName, ::rtl::OUString(),::rtl::OUString(), ColumnValue::NULLABLE, nPrecision, nDecimals, eType, sal_False, sal_False, bCurrency, bStoresMixedCaseQuotedIdentifiers); Reference< XPropertySet> xCol = pColumn; m_aColumns->get().push_back(xCol); m_aTypes.push_back(eType); m_aPrecisions.push_back(nPrecision); m_aScales.push_back(nDecimals); } } // ------------------------------------------------------------------------- OCalcTable::OCalcTable(sdbcx::OCollection* _pTables,OCalcConnection* _pConnection, const ::rtl::OUString& _Name, const ::rtl::OUString& _Type, const ::rtl::OUString& _Description , const ::rtl::OUString& _SchemaName, const ::rtl::OUString& _CatalogName ) : OCalcTable_BASE(_pTables,_pConnection,_Name, _Type, _Description, _SchemaName, _CatalogName) ,m_pConnection(_pConnection) ,m_nStartCol(0) ,m_nStartRow(0) ,m_nDataCols(0) ,m_nDataRows(0) ,m_bHasHeaders(sal_False) { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::OCalcTable" ); } // ----------------------------------------------------------------------------- void OCalcTable::construct() { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::construct" ); // get sheet object Reference< XSpreadsheetDocument> xDoc = m_pConnection->acquireDoc(); if (xDoc.is()) { Reference xSheets = xDoc->getSheets(); if ( xSheets.is() && xSheets->hasByName( m_Name ) ) { m_xSheet.set(xSheets->getByName( m_Name ),UNO_QUERY); if ( m_xSheet.is() ) { lcl_GetDataArea( m_xSheet, m_nDataCols, m_nDataRows ); m_bHasHeaders = sal_True; // whole sheet is always assumed to include a header row } } else // no sheet -> try database range { Reference xDocProp( xDoc, UNO_QUERY ); if ( xDocProp.is() ) { Reference xRanges(xDocProp->getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DatabaseRanges")) ),UNO_QUERY); if ( xRanges.is() && xRanges->hasByName( m_Name ) ) { Reference xDBRange(xRanges->getByName( m_Name ),UNO_QUERY); Reference xRefer( xDBRange, UNO_QUERY ); if ( xRefer.is() ) { // Header flag is always stored with database range // Get flag from FilterDescriptor sal_Bool bRangeHeader = sal_True; Reference xFiltProp( xDBRange->getFilterDescriptor(), UNO_QUERY ); if ( xFiltProp.is() ) xFiltProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ContainsHeader"))) >>= bRangeHeader; Reference xSheetRange( xRefer->getReferredCells(), UNO_QUERY ); Reference xAddr( xSheetRange, UNO_QUERY ); if ( xSheetRange.is() && xAddr.is() ) { m_xSheet = xSheetRange->getSpreadsheet(); CellRangeAddress aRangeAddr = xAddr->getRangeAddress(); m_nStartCol = aRangeAddr.StartColumn; m_nStartRow = aRangeAddr.StartRow; m_nDataCols = aRangeAddr.EndColumn - m_nStartCol + 1; // m_nDataRows is excluding header row m_nDataRows = aRangeAddr.EndRow - m_nStartRow; if ( !bRangeHeader ) { // m_nDataRows counts the whole range m_nDataRows += 1; } m_bHasHeaders = bRangeHeader; } } } } } Reference xSupp( xDoc, UNO_QUERY ); if (xSupp.is()) m_xFormats = xSupp->getNumberFormats(); Reference xProp( xDoc, UNO_QUERY ); if (xProp.is()) { ::com::sun::star::util::Date aDateStruct; if ( xProp->getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("NullDate")) ) >>= aDateStruct ) m_aNullDate = ::Date( aDateStruct.Day, aDateStruct.Month, aDateStruct.Year ); } } //! default if no null date available? fillColumns(); refreshColumns(); } // ------------------------------------------------------------------------- void OCalcTable::refreshColumns() { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::refreshColumns" ); ::osl::MutexGuard aGuard( m_aMutex ); TStringVector aVector; OSQLColumns::Vector::const_iterator aEnd = m_aColumns->get().end(); for(OSQLColumns::Vector::const_iterator aIter = m_aColumns->get().begin();aIter != aEnd;++aIter) aVector.push_back(Reference< XNamed>(*aIter,UNO_QUERY)->getName()); if(m_pColumns) m_pColumns->reFill(aVector); else m_pColumns = new OCalcColumns(this,m_aMutex,aVector); } // ------------------------------------------------------------------------- void OCalcTable::refreshIndexes() { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::refreshIndexes" ); // Calc table has no index } // ------------------------------------------------------------------------- void SAL_CALL OCalcTable::disposing(void) { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::disposing" ); OFileTable::disposing(); ::osl::MutexGuard aGuard(m_aMutex); m_aColumns = NULL; if ( m_pConnection ) m_pConnection->releaseDoc(); m_pConnection = NULL; } // ------------------------------------------------------------------------- Sequence< Type > SAL_CALL OCalcTable::getTypes( ) throw(RuntimeException) { //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::getTypes" ); Sequence< Type > aTypes = OTable_TYPEDEF::getTypes(); ::std::vector aOwnTypes; aOwnTypes.reserve(aTypes.getLength()); const Type* pBegin = aTypes.getConstArray(); const Type* pEnd = pBegin + aTypes.getLength(); for(;pBegin != pEnd;++pBegin) { if(!( *pBegin == ::getCppuType((const Reference*)0) || *pBegin == ::getCppuType((const Reference*)0) || *pBegin == ::getCppuType((const Reference*)0) || *pBegin == ::getCppuType((const Reference*)0) || *pBegin == ::getCppuType((const Reference*)0))) aOwnTypes.push_back(*pBegin); } aOwnTypes.push_back(::getCppuType( (const Reference< ::com::sun::star::lang::XUnoTunnel > *)0 )); const Type* pAttrs = aOwnTypes.empty() ? 0 : &aOwnTypes[0]; return Sequence< Type >(pAttrs, aOwnTypes.size()); } // ------------------------------------------------------------------------- Any SAL_CALL OCalcTable::queryInterface( const Type & rType ) throw(RuntimeException) { if( rType == ::getCppuType((const Reference*)0) || rType == ::getCppuType((const Reference*)0) || rType == ::getCppuType((const Reference*)0) || rType == ::getCppuType((const Reference*)0) || rType == ::getCppuType((const Reference*)0)) return Any(); const Any aRet = ::cppu::queryInterface(rType,static_cast< ::com::sun::star::lang::XUnoTunnel*> (this)); return aRet.hasValue() ? aRet : OTable_TYPEDEF::queryInterface(rType); } //-------------------------------------------------------------------------- Sequence< sal_Int8 > OCalcTable::getUnoTunnelImplementationId() { //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::getUnoTunnelImplementationId" ); static ::cppu::OImplementationId * pId = 0; if (! pId) { ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); if (! pId) { static ::cppu::OImplementationId aId; pId = &aId; } } return pId->getImplementationId(); } // com::sun::star::lang::XUnoTunnel //------------------------------------------------------------------ sal_Int64 OCalcTable::getSomething( const Sequence< sal_Int8 > & rId ) throw (RuntimeException) { //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::getSomething" ); return (rId.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(), rId.getConstArray(), 16 ) ) ? reinterpret_cast< sal_Int64 >( this ) : OCalcTable_BASE::getSomething(rId); } //------------------------------------------------------------------ sal_Int32 OCalcTable::getCurrentLastPos() const { //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::getCurrentLastPos" ); return m_nDataRows; } //------------------------------------------------------------------ sal_Bool OCalcTable::seekRow(IResultSetHelper::Movement eCursorPosition, sal_Int32 nOffset, sal_Int32& nCurPos) { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::seekRow" ); // ---------------------------------------------------------- // Positionierung vorbereiten: sal_uInt32 nNumberOfRecords = m_nDataRows; sal_uInt32 nTempPos = m_nFilePos; m_nFilePos = nCurPos; switch(eCursorPosition) { case IResultSetHelper::NEXT: m_nFilePos++; break; case IResultSetHelper::PRIOR: if (m_nFilePos > 0) m_nFilePos--; break; case IResultSetHelper::FIRST: m_nFilePos = 1; break; case IResultSetHelper::LAST: m_nFilePos = nNumberOfRecords; break; case IResultSetHelper::RELATIVE: m_nFilePos = (((sal_Int32)m_nFilePos) + nOffset < 0) ? 0L : (sal_uInt32)(((sal_Int32)m_nFilePos) + nOffset); break; case IResultSetHelper::ABSOLUTE: case IResultSetHelper::BOOKMARK: m_nFilePos = (sal_uInt32)nOffset; break; } if (m_nFilePos > (sal_Int32)nNumberOfRecords) m_nFilePos = (sal_Int32)nNumberOfRecords + 1; if (m_nFilePos == 0 || m_nFilePos == (sal_Int32)nNumberOfRecords + 1) goto Error; else { //! read buffer / setup row object etc? } goto End; Error: switch(eCursorPosition) { case IResultSetHelper::PRIOR: case IResultSetHelper::FIRST: m_nFilePos = 0; break; case IResultSetHelper::LAST: case IResultSetHelper::NEXT: case IResultSetHelper::ABSOLUTE: case IResultSetHelper::RELATIVE: if (nOffset > 0) m_nFilePos = nNumberOfRecords + 1; else if (nOffset < 0) m_nFilePos = 0; break; case IResultSetHelper::BOOKMARK: m_nFilePos = nTempPos; // vorherige Position } // aStatus.Set(SDB_STAT_NO_DATA_FOUND); return sal_False; End: nCurPos = m_nFilePos; return sal_True; } //------------------------------------------------------------------ sal_Bool OCalcTable::fetchRow( OValueRefRow& _rRow, const OSQLColumns & _rCols, sal_Bool _bUseTableDefs, sal_Bool bRetrieveData ) { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::fetchRow" ); // read the bookmark sal_Bool bIsCurRecordDeleted = sal_False; _rRow->setDeleted(bIsCurRecordDeleted); *(_rRow->get())[0] = m_nFilePos; if (!bRetrieveData) return sal_True; // fields OSQLColumns::Vector::const_iterator aIter = _rCols.get().begin(); OSQLColumns::Vector::const_iterator aEnd = _rCols.get().end(); const OValueRefVector::Vector::size_type nCount = _rRow->get().size(); for (OValueRefVector::Vector::size_type i = 1; aIter != aEnd && i < nCount; ++aIter, i++) { if ( (_rRow->get())[i]->isBound() ) { sal_Int32 nType = 0; if ( _bUseTableDefs ) nType = m_aTypes[i-1]; else (*aIter)->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)) >>= nType; lcl_SetValue( (_rRow->get())[i]->get(), m_xSheet, m_nStartCol, m_nStartRow, m_bHasHeaders, m_aNullDate, m_nFilePos, i, nType ); } } return sal_True; } // ------------------------------------------------------------------------- void OCalcTable::FileClose() { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcTable::FileClose" ); ::osl::MutexGuard aGuard(m_aMutex); OCalcTable_BASE::FileClose(); } // -------------------------------------------------------------------------