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