xref: /aoo42x/main/sc/source/ui/docshell/docsh8.cxx (revision 86e1cf34)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26 
27 
28 
29 // INCLUDE ---------------------------------------------------------------
30 
31 #include <stdio.h>
32 #include <tools/urlobj.hxx>
33 #include <svl/converter.hxx>
34 #include <svl/zforlist.hxx>
35 #include <comphelper/types.hxx>
36 #include <ucbhelper/content.hxx>
37 #include <unotools/sharedunocomponent.hxx>
38 #include <comphelper/processfactory.hxx>
39 #include <svx/txenctab.hxx>
40 #include <svx/dbcharsethelper.hxx>
41 
42 #include <com/sun/star/sdb/CommandType.hpp>
43 #include <com/sun/star/sdbc/DataType.hpp>
44 #include <com/sun/star/sdbc/XConnection.hpp>
45 #include <com/sun/star/sdbc/XDriver.hpp>
46 #include <com/sun/star/sdbc/XDriverAccess.hpp>
47 #include <com/sun/star/sdbc/XDriverManager.hpp>
48 #include <com/sun/star/sdbc/XResultSetUpdate.hpp>
49 #include <com/sun/star/sdbc/XRow.hpp>
50 #include <com/sun/star/sdbc/XRowSet.hpp>
51 #include <com/sun/star/sdbc/XRowUpdate.hpp>
52 #include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
53 #include <com/sun/star/sdbcx/XAppend.hpp>
54 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
55 #include <com/sun/star/sdbcx/XDataDefinitionSupplier.hpp>
56 #include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
57 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
58 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
59 #include <com/sun/star/beans/XPropertySet.hpp>
60 #include <com/sun/star/container/XEnumerationAccess.hpp>
61 #include <com/sun/star/lang/XComponent.hpp>
62 #include <com/sun/star/ucb/NameClash.hpp>
63 #include <com/sun/star/ucb/TransferInfo.hpp>
64 #include <com/sun/star/ucb/XCommandInfo.hpp>
65 
66 #include "scerrors.hxx"
67 #include "docsh.hxx"
68 #include "filter.hxx"
69 #include "progress.hxx"
70 #include "collect.hxx"
71 #include "cell.hxx"
72 #include "editutil.hxx"
73 #include "cellform.hxx"
74 #include "dbdocutl.hxx"
75 #include "dociter.hxx"
76 #include "globstr.hrc"
77 
78 using namespace com::sun::star;
79 
80 // -----------------------------------------------------------------------
81 
82 #define SC_SERVICE_ROWSET			"com.sun.star.sdb.RowSet"
83 #define SC_SERVICE_DRVMAN			"com.sun.star.sdbc.DriverManager"
84 
85 //!	move to a header file?
86 //#define SC_DBPROP_DATASOURCENAME	"DataSourceName"
87 #define SC_DBPROP_ACTIVECONNECTION	"ActiveConnection"
88 #define SC_DBPROP_COMMAND			"Command"
89 #define SC_DBPROP_COMMANDTYPE		"CommandType"
90 
91 #define SC_DBPROP_NAME				"Name"
92 #define SC_DBPROP_TYPE				"Type"
93 #define SC_DBPROP_PRECISION			"Precision"
94 #define SC_DBPROP_SCALE				"Scale"
95 
96 #define SC_DBPROP_EXTENSION			"Extension"
97 #define SC_DBPROP_CHARSET			"CharSet"
98 
99 #define SC_ROWCOUNT_ERROR		(-1)
100 
101 namespace
102 {
lcl_getDBaseConnection(uno::Reference<sdbc::XDriverManager> & _rDrvMgr,uno::Reference<sdbc::XConnection> & _rConnection,String & _rTabName,const String & rFullFileName,rtl_TextEncoding eCharSet)103     sal_uLong lcl_getDBaseConnection(uno::Reference<sdbc::XDriverManager>& _rDrvMgr,uno::Reference<sdbc::XConnection>& _rConnection,String& _rTabName,const String& rFullFileName,rtl_TextEncoding eCharSet)
104     {
105         INetURLObject aURL;
106 	    aURL.SetSmartProtocol( INET_PROT_FILE );
107 	    aURL.SetSmartURL( rFullFileName );
108         _rTabName = aURL.getBase( INetURLObject::LAST_SEGMENT, true,
109                 INetURLObject::DECODE_UNAMBIGUOUS );
110 	    String aExtension = aURL.getExtension();
111 	    aURL.removeSegment();
112 	    aURL.removeFinalSlash();
113 	    String aPath = aURL.GetMainURL(INetURLObject::NO_DECODE);
114         uno::Reference<lang::XMultiServiceFactory> xFactory = comphelper::getProcessServiceFactory();
115 		if (!xFactory.is()) return SCERR_EXPORT_CONNECT;
116 
117 		_rDrvMgr.set( xFactory->createInstance(
118 							rtl::OUString::createFromAscii( SC_SERVICE_DRVMAN ) ),
119 							uno::UNO_QUERY);
120 		DBG_ASSERT( _rDrvMgr.is(), "can't get DriverManager" );
121 		if (!_rDrvMgr.is()) return SCERR_EXPORT_CONNECT;
122 
123 		// get connection
124 
125 		String aConnUrl = String::CreateFromAscii("sdbc:dbase:");
126 		aConnUrl += aPath;
127 
128 		svxform::ODataAccessCharsetHelper aHelper;
129         ::std::vector< rtl_TextEncoding > aEncodings;
130         aHelper.getSupportedTextEncodings( aEncodings );
131         ::std::vector< rtl_TextEncoding >::iterator aIter = ::std::find(aEncodings.begin(),aEncodings.end(),(rtl_TextEncoding) eCharSet);
132         if ( aIter == aEncodings.end() )
133         {
134             DBG_ERRORFILE( "DBaseImport: dbtools::OCharsetMap doesn't know text encoding" );
135             return SCERR_IMPORT_CONNECT;
136         } // if ( aIter == aMap.end() )
137         rtl::OUString aCharSetStr;
138         if ( RTL_TEXTENCODING_DONTKNOW != *aIter )
139 		{	// it's not the virtual "system charset"
140 			const char* pIanaName = rtl_getMimeCharsetFromTextEncoding( *aIter );
141 			OSL_ENSURE( pIanaName, "invalid mime name!" );
142 			if ( pIanaName )
143 				aCharSetStr = ::rtl::OUString::createFromAscii( pIanaName );
144 		}
145 
146 		uno::Sequence<beans::PropertyValue> aProps(2);
147 		aProps[0].Name = rtl::OUString::createFromAscii(SC_DBPROP_EXTENSION);
148 		aProps[0].Value <<= rtl::OUString( aExtension );
149 		aProps[1].Name = rtl::OUString::createFromAscii(SC_DBPROP_CHARSET);
150 		aProps[1].Value <<= aCharSetStr;
151 
152 		_rConnection = _rDrvMgr->getConnectionWithInfo( aConnUrl, aProps );
153         return 0L;
154     }
155 }
156 // -----------------------------------------------------------------------
157 // MoveFile/KillFile/IsDocument: similar to SfxContentHelper
158 
159 // static
MoveFile(const INetURLObject & rSourceObj,const INetURLObject & rDestObj)160 sal_Bool ScDocShell::MoveFile( const INetURLObject& rSourceObj, const INetURLObject& rDestObj )
161 {
162 	sal_Bool bMoveData = sal_True;
163 	sal_Bool bRet = sal_True, bKillSource = sal_False;
164 	if ( rSourceObj.GetProtocol() != rDestObj.GetProtocol() )
165 	{
166 		bMoveData = sal_False;
167 		bKillSource = sal_True;
168 	}
169 	String aName = rDestObj.getName();
170 	INetURLObject aDestPathObj = rDestObj;
171 	aDestPathObj.removeSegment();
172 	aDestPathObj.setFinalSlash();
173 
174 	try
175 	{
176 		::ucbhelper::Content aDestPath( aDestPathObj.GetMainURL(INetURLObject::NO_DECODE),
177 							uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > () );
178 		uno::Reference< ::com::sun::star::ucb::XCommandInfo > xInfo = aDestPath.getCommands();
179 		rtl::OUString aTransferName = rtl::OUString::createFromAscii( "transfer" );
180 		if ( xInfo->hasCommandByName( aTransferName ) )
181 		{
182 			aDestPath.executeCommand( aTransferName, uno::makeAny(
183                 ::com::sun::star::ucb::TransferInfo( bMoveData, rSourceObj.GetMainURL(INetURLObject::NO_DECODE), aName,
184                										::com::sun::star::ucb::NameClash::ERROR ) ) );
185 		}
186 		else
187 		{
188 			DBG_ERRORFILE( "transfer command not available" );
189 		}
190 	}
191 	catch( uno::Exception& )
192 	{
193 		// ucb may throw different exceptions on failure now
194 		bRet = sal_False;
195 	}
196 
197 	if ( bKillSource )
198 		KillFile( rSourceObj );
199 
200 	return bRet;
201 }
202 
203 
204 // static
KillFile(const INetURLObject & rURL)205 sal_Bool ScDocShell::KillFile( const INetURLObject& rURL )
206 {
207 	sal_Bool bRet = sal_True;
208 	try
209 	{
210 		::ucbhelper::Content aCnt( rURL.GetMainURL(INetURLObject::NO_DECODE),
211 						uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > () );
212 		aCnt.executeCommand( rtl::OUString::createFromAscii( "delete" ),
213 								comphelper::makeBoolAny( sal_True ) );
214 	}
215 	catch( uno::Exception& )
216 	{
217 		// ucb may throw different exceptions on failure now
218 		bRet = sal_False;
219 	}
220 
221 	return bRet;
222 }
223 
224 // static
IsDocument(const INetURLObject & rURL)225 sal_Bool ScDocShell::IsDocument( const INetURLObject& rURL )
226 {
227 	sal_Bool bRet = sal_False;
228 	try
229 	{
230 		::ucbhelper::Content aCnt( rURL.GetMainURL(INetURLObject::NO_DECODE),
231 						uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > () );
232 		bRet = aCnt.isDocument();
233 	}
234     catch( uno::Exception& )
235 	{
236 		// ucb may throw different exceptions on failure now - warning only
237 		DBG_WARNING( "Any other exception" );
238 	}
239 
240 	return bRet;
241 }
242 
243 // -----------------------------------------------------------------------
244 
DBaseImport(const String & rFullFileName,CharSet eCharSet,sal_Bool bSimpleColWidth[MAXCOLCOUNT])245 sal_uLong ScDocShell::DBaseImport( const String& rFullFileName, CharSet eCharSet,
246 								sal_Bool bSimpleColWidth[MAXCOLCOUNT] )
247 {
248 	sal_uLong nErr = eERR_OK;
249 	long i;
250     long nColCount = 0;
251 
252 	try
253 	{
254 		String aTabName;
255         uno::Reference<sdbc::XDriverManager> xDrvMan;
256         uno::Reference<sdbc::XConnection> xConnection;
257 		sal_uLong nRet = lcl_getDBaseConnection(xDrvMan,xConnection,aTabName,rFullFileName,eCharSet);
258         if ( !xConnection.is() || !xDrvMan.is() )
259             return nRet;
260         ::utl::DisposableComponent aConnectionHelper(xConnection);
261 
262         ScProgress aProgress( this, ScGlobal::GetRscString( STR_LOAD_DOC ), 0 );
263         uno::Reference<lang::XMultiServiceFactory> xFactory = comphelper::getProcessServiceFactory();
264 		uno::Reference<sdbc::XRowSet> xRowSet( xFactory->createInstance(
265 							rtl::OUString::createFromAscii( SC_SERVICE_ROWSET ) ),
266 							uno::UNO_QUERY);
267         ::utl::DisposableComponent aRowSetHelper(xRowSet);
268 		uno::Reference<beans::XPropertySet> xRowProp( xRowSet, uno::UNO_QUERY );
269 		DBG_ASSERT( xRowProp.is(), "can't get RowSet" );
270 		if (!xRowProp.is()) return SCERR_IMPORT_CONNECT;
271 
272 		sal_Int32 nType = sdb::CommandType::TABLE;
273 		uno::Any aAny;
274 
275 		aAny <<= xConnection;
276 		xRowProp->setPropertyValue(
277 					rtl::OUString::createFromAscii(SC_DBPROP_ACTIVECONNECTION), aAny );
278 
279 		aAny <<= nType;
280 		xRowProp->setPropertyValue(
281 					rtl::OUString::createFromAscii(SC_DBPROP_COMMANDTYPE), aAny );
282 
283 		aAny <<= rtl::OUString( aTabName );
284 		xRowProp->setPropertyValue(
285 					rtl::OUString::createFromAscii(SC_DBPROP_COMMAND), aAny );
286 
287 		xRowSet->execute();
288 
289 		uno::Reference<sdbc::XResultSetMetaData> xMeta;
290 		uno::Reference<sdbc::XResultSetMetaDataSupplier> xMetaSupp( xRowSet, uno::UNO_QUERY );
291 		if ( xMetaSupp.is() )
292 			xMeta = xMetaSupp->getMetaData();
293 		if ( xMeta.is() )
294 			nColCount = xMeta->getColumnCount();	// this is the number of real columns
295 
296 		if ( nColCount > MAXCOL+1 )
297 		{
298 			nColCount = MAXCOL+1;
299 			nErr = SCWARN_IMPORT_RANGE_OVERFLOW;	// warning
300 		}
301 
302 		uno::Reference<sdbc::XRow> xRow( xRowSet, uno::UNO_QUERY );
303 		DBG_ASSERT( xRow.is(), "can't get Row" );
304 		if (!xRow.is()) return SCERR_IMPORT_CONNECT;
305 
306 		// currency flag is not needed for dBase
307 		uno::Sequence<sal_Int32> aColTypes( nColCount );	// column types
308 		sal_Int32* pTypeArr = aColTypes.getArray();
309 		for (i=0; i<nColCount; i++)
310 			pTypeArr[i] = xMeta->getColumnType( i+1 );
311 
312 		//	read column names
313 		//!	add type descriptions
314 
315         aProgress.SetState( 0 );
316         ScColumn::bDoubleAlloc = sal_True;      // row count isn't readily available in advance
317 
318 		for (i=0; i<nColCount; i++)
319 		{
320 			String aHeader = xMeta->getColumnLabel( i+1 );
321 
322 			switch ( pTypeArr[i] )
323 			{
324 				case sdbc::DataType::BIT:
325 					aHeader.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ",L" ));
326 					break;
327 				case sdbc::DataType::DATE:
328 					aHeader.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ",D" ));
329 					break;
330 				case sdbc::DataType::LONGVARCHAR:
331 					aHeader.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ",M" ));
332 					break;
333 				case sdbc::DataType::VARCHAR:
334 					aHeader.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ",C," ));
335 					aHeader += String::CreateFromInt32( xMeta->getColumnDisplaySize( i+1 ) );
336 					break;
337 				case sdbc::DataType::DECIMAL:
338 					{
339 						long nPrec = xMeta->getPrecision( i+1 );
340 						long nScale = xMeta->getScale( i+1 );
341 						aHeader.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ",N," ));
342 						aHeader += String::CreateFromInt32(
343 									SvDbaseConverter::ConvertPrecisionToDbase(
344 										nPrec, nScale ) );
345 						aHeader += ',';
346 						aHeader += String::CreateFromInt32( nScale );
347 					}
348 					break;
349 			}
350 
351 			aDocument.SetString( static_cast<SCCOL>(i), 0, 0, aHeader );
352 		}
353 
354 		SCROW nRow = 1;		// 0 is column titles
355 		sal_Bool bEnd = sal_False;
356 		while ( !bEnd && xRowSet->next() )
357 		{
358 			if ( nRow <= MAXROW )
359 			{
360 				SCCOL nCol = 0;
361 				for (i=0; i<nColCount; i++)
362 				{
363 					ScDatabaseDocUtil::PutData( &aDocument, nCol, nRow, 0,
364 												xRow, i+1, pTypeArr[i], sal_False,
365 												&bSimpleColWidth[nCol] );
366 					++nCol;
367 				}
368 				++nRow;
369 			}
370 			else		// past the end of the spreadsheet
371 			{
372 				bEnd = sal_True;							// don't continue
373 				nErr = SCWARN_IMPORT_RANGE_OVERFLOW;	// warning message
374 			}
375 		}
376 	}
377 	catch ( sdbc::SQLException& )
378 	{
379 		nErr = SCERR_IMPORT_CONNECT;
380 	}
381 	catch ( uno::Exception& )
382 	{
383 		DBG_ERROR("Unexpected exception in database");
384 		nErr = ERRCODE_IO_GENERAL;
385 	}
386 
387     ScColumn::bDoubleAlloc = sal_False;
388     if ( nColCount > 0 )
389         aDocument.DoColResize( 0, 0, static_cast<SCCOL>(nColCount) - 1, 0 );
390 
391 	return nErr;
392 }
393 
394 // -----------------------------------------------------------------------
395 
IsAsciiDigit(sal_Unicode c)396 inline sal_Bool IsAsciiDigit( sal_Unicode c )
397 {
398 	return 0x30 <= c && c <= 0x39;
399 }
400 
IsAsciiAlpha(sal_Unicode c)401 inline sal_Bool IsAsciiAlpha( sal_Unicode c )
402 {
403 	return (0x41 <= c && c <= 0x5a) || (0x61 <= c && c <= 0x7a);
404 }
405 
lcl_GetColumnTypes(ScDocShell & rDocShell,const ScRange & rDataRange,sal_Bool bHasFieldNames,rtl::OUString * pColNames,sal_Int32 * pColTypes,sal_Int32 * pColLengths,sal_Int32 * pColScales,sal_Bool & bHasMemo,CharSet eCharSet)406 void lcl_GetColumnTypes( ScDocShell& rDocShell,
407 							const ScRange& rDataRange, sal_Bool bHasFieldNames,
408 							rtl::OUString* pColNames, sal_Int32* pColTypes,
409 							sal_Int32* pColLengths, sal_Int32* pColScales,
410 							sal_Bool& bHasMemo, CharSet eCharSet )
411 {
412 	//	updating of column titles didn't work in 5.2 and isn't always wanted
413 	//	(saving normally shouldn't modify the document)
414 	//!	read flag from configuration
415 	sal_Bool bUpdateTitles = sal_False;
416 
417 	ScDocument* pDoc = rDocShell.GetDocument();
418 	SvNumberFormatter* pNumFmt = pDoc->GetFormatTable();
419 
420 	SCTAB nTab = rDataRange.aStart.Tab();
421 	SCCOL nFirstCol = rDataRange.aStart.Col();
422 	SCROW nFirstRow = rDataRange.aStart.Row();
423 	SCCOL nLastCol = rDataRange.aEnd.Col();
424 	SCROW nLastRow = rDataRange.aEnd.Row();
425 
426 	ScStrCollection aFieldNamesCollection;
427 
428 	long nField = 0;
429 	SCROW nFirstDataRow = ( bHasFieldNames ? nFirstRow + 1 : nFirstRow );
430 	for ( SCCOL nCol = nFirstCol; nCol <= nLastCol; nCol++ )
431 	{
432 		sal_Bool bTypeDefined = sal_False;
433 		sal_Bool bPrecDefined = sal_False;
434 		sal_Int32 nFieldLen = 0;
435 		sal_Int32 nPrecision = 0;
436 		sal_Int32 nDbType = sdbc::DataType::SQLNULL;
437 		String aFieldName, aString;
438 
439 		// Feldname[,Type[,Width[,Prec]]]
440 		// Typ etc.: L; D; C[,W]; N[,W[,P]]
441 		if ( bHasFieldNames )
442 		{
443 			pDoc->GetString( nCol, nFirstRow, nTab, aString );
444 			aString.ToUpperAscii();
445 			xub_StrLen nToken = aString.GetTokenCount( ',' );
446 			if ( nToken > 1 )
447 			{
448 				aFieldName = aString.GetToken( 0, ',' );
449 				aString.EraseAllChars( ' ' );
450 				switch ( aString.GetToken( 1, ',' ).GetChar(0) )
451 				{
452 					case 'L' :
453 						nDbType = sdbc::DataType::BIT;
454 						nFieldLen = 1;
455 						bTypeDefined = sal_True;
456 						bPrecDefined = sal_True;
457 						break;
458 					case 'D' :
459 						nDbType = sdbc::DataType::DATE;
460 						nFieldLen = 8;
461 						bTypeDefined = sal_True;
462 						bPrecDefined = sal_True;
463 						break;
464 					case 'M' :
465 						nDbType = sdbc::DataType::LONGVARCHAR;
466 						nFieldLen = 10;
467 						bTypeDefined = sal_True;
468 						bPrecDefined = sal_True;
469 						bHasMemo = sal_True;
470 						break;
471 					case 'C' :
472 						nDbType = sdbc::DataType::VARCHAR;
473 						bTypeDefined = sal_True;
474 						bPrecDefined = sal_True;
475 						break;
476 					case 'N' :
477 						nDbType = sdbc::DataType::DECIMAL;
478 						bTypeDefined = sal_True;
479 						break;
480 				}
481 				if ( bTypeDefined && !nFieldLen && nToken > 2 )
482 				{
483 					nFieldLen = aString.GetToken( 2, ',' ).ToInt32();
484 					if ( !bPrecDefined && nToken > 3 )
485 					{
486 						String aTmp( aString.GetToken( 3, ',' ) );
487 						if ( CharClass::isAsciiNumeric(aTmp) )
488 						{
489 							nPrecision = aTmp.ToInt32();
490 							bPrecDefined = sal_True;
491 						}
492 					}
493 				}
494 			}
495 			else
496 				aFieldName = aString;
497 
498 			// Feldnamen pruefen und ggbf. gueltigen Feldnamen erzeugen.
499 			// Erstes Zeichen muss Buchstabe sein,
500 			// weitere nur alphanumerisch und Unterstrich erlaubt,
501 			// "_DBASELOCK" ist reserviert (obsolet weil erstes Zeichen kein Buchstabe),
502 			// keine doppelten Namen.
503 			if ( !IsAsciiAlpha( aFieldName.GetChar(0) ) )
504 				aFieldName.Insert( 'N', 0 );
505 			String aTmpStr;
506 			sal_Unicode c;
507             for ( const sal_Unicode* p = aFieldName.GetBuffer(); ( c = *p ) != 0; p++ )
508 			{
509 				if ( IsAsciiAlpha( c ) || IsAsciiDigit( c ) || c == '_' )
510 					aTmpStr += c;
511 				else
512 					aTmpStr += '_';
513 			}
514 			aFieldName = aTmpStr;
515 			if ( aFieldName.Len() > 10 )
516 				aFieldName.Erase( 10 );
517 			StrData* pStrData = new StrData( aFieldName );
518 			if ( !aFieldNamesCollection.Insert( pStrData ) )
519 			{	// doppelter Feldname, numerisch erweitern
520 				sal_uInt16 nSub = 1;
521 				String aFixPart( aFieldName );
522 				do
523 				{
524 					++nSub;
525 					String aVarPart = String::CreateFromInt32( nSub );
526 					if ( aFixPart.Len() + aVarPart.Len() > 10 )
527 						aFixPart.Erase( 10 - aVarPart.Len() );
528 					aFieldName = aFixPart;
529 					aFieldName += aVarPart;
530 					pStrData->SetString( aFieldName );
531 				} while ( !aFieldNamesCollection.Insert( pStrData ) );
532 			}
533 		}
534 		else
535 		{
536 			aFieldName = 'N';
537 			aFieldName += String::CreateFromInt32(nCol+1);
538 		}
539 
540 		if ( !bTypeDefined )
541 		{	// Feldtyp
542 			ScBaseCell* pCell;
543 			pDoc->GetCell( nCol, nFirstDataRow, nTab, pCell );
544 			if ( !pCell || pCell->HasStringData() )
545 				nDbType = sdbc::DataType::VARCHAR;
546 			else
547 			{
548 				sal_uInt32 nFormat;
549 				pDoc->GetNumberFormat( nCol, nFirstDataRow, nTab, nFormat );
550 				if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA
551 				  && ((nFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0) )
552 				{
553 					nFormat = ScGlobal::GetStandardFormat(
554 						((ScFormulaCell*)pCell)->GetValue(), *pNumFmt, nFormat,
555 						((ScFormulaCell*)pCell)->GetFormatType() );
556 				}
557 				switch ( pNumFmt->GetType( nFormat ) )
558 				{
559 					case NUMBERFORMAT_LOGICAL :
560 						nDbType = sdbc::DataType::BIT;
561 						nFieldLen = 1;
562 						break;
563 					case NUMBERFORMAT_DATE :
564 						nDbType = sdbc::DataType::DATE;
565 						nFieldLen = 8;
566 						break;
567 					case NUMBERFORMAT_TIME :
568 					case NUMBERFORMAT_DATETIME :
569 						nDbType = sdbc::DataType::VARCHAR;
570 						break;
571 					default:
572 						nDbType = sdbc::DataType::DECIMAL;
573 				}
574 			}
575 		}
576 		sal_Bool bSdbLenAdjusted = sal_False;
577 		sal_Bool bSdbLenBad = sal_False;
578 		// Feldlaenge
579 		if ( nDbType == sdbc::DataType::VARCHAR && !nFieldLen )
580 		{	// maximale Feldbreite bestimmen
581 			nFieldLen = pDoc->GetMaxStringLen( nTab, nCol, nFirstDataRow,
582 				nLastRow, eCharSet );
583 			if ( nFieldLen == 0 )
584 				nFieldLen = 1;
585 		}
586         else if ( nDbType == sdbc::DataType::DECIMAL )
587         {	// maximale Feldbreite und Nachkommastellen bestimmen
588             xub_StrLen nLen;
589             sal_uInt16 nPrec;
590             nLen = pDoc->GetMaxNumberStringLen( nPrec, nTab, nCol,
591                 nFirstDataRow, nLastRow );
592             // dBaseIII Limit Nachkommastellen: 15
593 			if ( nPrecision > 15 )
594 				nPrecision = 15;
595 			if ( nPrec > 15 )
596 				nPrec = 15;
597 			if ( bPrecDefined && nPrecision != nPrec )
598 			{	// Laenge auf vorgegebene Nachkommastellen anpassen
599 				if ( nPrecision )
600                     nLen = sal::static_int_cast<xub_StrLen>( nLen + ( nPrecision - nPrec ) );
601 				else
602 					nLen -= nPrec+1;			// auch den . mit raus
603 			}
604 			if ( nLen > nFieldLen && !bTypeDefined )
605 				nFieldLen = nLen;
606 			if ( !bPrecDefined )
607 				nPrecision = nPrec;
608 			if ( nFieldLen == 0 )
609 				nFieldLen = 1;
610 			else if ( nFieldLen > 19 )
611 				nFieldLen = 19;		// dBaseIII Limit Feldlaenge numerisch: 19
612 			if ( nPrecision && nFieldLen < nPrecision + 2 )
613 				nFieldLen = nPrecision + 2;		// 0. muss mit reinpassen
614 			// 538 MUST: Sdb internal representation adds 2 to the field length!
615 			// To give the user what he wants we must subtract it here.
616  			//! CAVEAT! There is no way to define a numeric field with a length
617  			//! of 1 and no decimals!
618 			if ( nFieldLen == 1 && nPrecision == 0 )
619 				bSdbLenBad = sal_True;
620 			nFieldLen = SvDbaseConverter::ConvertPrecisionToOdbc( nFieldLen, nPrecision );
621 			bSdbLenAdjusted = sal_True;
622 		}
623 		if ( nFieldLen > 254 )
624 		{
625 			if ( nDbType == sdbc::DataType::VARCHAR )
626 			{	// zu lang fuer normales Textfeld => Memofeld
627 				nDbType = sdbc::DataType::LONGVARCHAR;
628 				nFieldLen = 10;
629 				bHasMemo = sal_True;
630 			}
631 			else
632 				nFieldLen = 254;					// dumm gelaufen..
633 		}
634 
635 		pColNames[nField] = aFieldName;
636 		pColTypes[nField] = nDbType;
637 		pColLengths[nField] = nFieldLen;
638 		pColScales[nField] = nPrecision;
639 
640 		// undo change to field length, reflect reality
641 		if ( bSdbLenAdjusted )
642 		{
643 			nFieldLen = SvDbaseConverter::ConvertPrecisionToDbase( nFieldLen, nPrecision );
644 			if ( bSdbLenBad && nFieldLen == 1 )
645 				nFieldLen = 2;		// THIS is reality
646 		}
647 		if ( bUpdateTitles )
648 		{	// Angabe anpassen und ausgeben
649 			String aOutString = aFieldName;
650 			switch ( nDbType )
651 			{
652 				case sdbc::DataType::BIT :
653 					aOutString.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ",L" ));
654 					break;
655 				case sdbc::DataType::DATE :
656 					aOutString.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ",D" ));
657 					break;
658 				case sdbc::DataType::LONGVARCHAR :
659 					aOutString.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ",M" ));
660 					break;
661 				case sdbc::DataType::VARCHAR :
662 					aOutString.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ",C," ));
663 					aOutString += String::CreateFromInt32( nFieldLen );
664 					break;
665 				case sdbc::DataType::DECIMAL :
666 					aOutString.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ",N," ));
667 					aOutString += String::CreateFromInt32( nFieldLen );
668 					aOutString += ',';
669 					aOutString += String::CreateFromInt32( nPrecision );
670 					break;
671 			}
672 			if ( !aOutString.EqualsIgnoreCaseAscii( aString ) )
673 			{
674 				pDoc->SetString( nCol, nFirstRow, nTab, aOutString );
675 				rDocShell.PostPaint( nCol, nFirstRow, nTab, nCol, nFirstRow, nTab, PAINT_GRID );
676 			}
677 		}
678 		++nField;
679 	}
680 }
681 
682 
lcl_getLongVarCharEditString(String & rString,const ScBaseCell * pCell,ScFieldEditEngine & rEditEngine)683 inline void lcl_getLongVarCharEditString( String& rString,
684         const ScBaseCell* pCell, ScFieldEditEngine& rEditEngine )
685 {
686     rEditEngine.SetText( *((const ScEditCell*)pCell)->GetData() );
687     rString = rEditEngine.GetText( LINEEND_CRLF );
688 }
689 
lcl_getLongVarCharString(String & rString,ScBaseCell * pCell,ScDocument & rDocument,SCCOL nCol,SCROW nRow,SCTAB nTab,SvNumberFormatter & rNumFmt)690 inline void lcl_getLongVarCharString( String& rString, ScBaseCell* pCell,
691         ScDocument& rDocument, SCCOL nCol, SCROW nRow, SCTAB nTab,
692         SvNumberFormatter& rNumFmt )
693 {
694     sal_uInt32 nFormat;
695     Color* pColor;
696     rDocument.GetNumberFormat( nCol, nRow, nTab, nFormat );
697     ScCellFormat::GetString( pCell, nFormat, rString, &pColor, rNumFmt );
698 }
699 
700 
DBaseExport(const String & rFullFileName,CharSet eCharSet,sal_Bool & bHasMemo)701 sal_uLong ScDocShell::DBaseExport( const String& rFullFileName, CharSet eCharSet, sal_Bool& bHasMemo )
702 {
703 	// remove the file so the dBase driver doesn't find an invalid file
704 	INetURLObject aDeleteObj( rFullFileName, INET_PROT_FILE );
705 	KillFile( aDeleteObj );
706 
707 	sal_uLong nErr = eERR_OK;
708 	uno::Any aAny;
709 
710 	SCCOL nFirstCol, nLastCol;
711 	SCROW  nFirstRow, nLastRow;
712 	SCTAB nTab = GetSaveTab();
713 	aDocument.GetDataStart( nTab, nFirstCol, nFirstRow );
714 	aDocument.GetCellArea( nTab, nLastCol, nLastRow );
715     if ( nFirstCol > nLastCol )
716         nFirstCol = nLastCol;
717     if ( nFirstRow > nLastRow )
718         nFirstRow = nLastRow;
719 	ScProgress aProgress( this, ScGlobal::GetRscString( STR_SAVE_DOC ),
720 													nLastRow - nFirstRow );
721 	SvNumberFormatter* pNumFmt = aDocument.GetFormatTable();
722 
723 	sal_Bool bHasFieldNames = sal_True;
724 	for ( SCCOL nDocCol = nFirstCol; nDocCol <= nLastCol && bHasFieldNames; nDocCol++ )
725 	{	// nur Strings in erster Zeile => sind Feldnamen
726 		if ( !aDocument.HasStringData( nDocCol, nFirstRow, nTab ) )
727 			bHasFieldNames = sal_False;
728 	}
729 
730 	long nColCount = nLastCol - nFirstCol + 1;
731 	uno::Sequence<rtl::OUString> aColNames( nColCount );
732 	uno::Sequence<sal_Int32> aColTypes( nColCount );
733 	uno::Sequence<sal_Int32> aColLengths( nColCount );
734 	uno::Sequence<sal_Int32> aColScales( nColCount );
735 
736 	ScRange aDataRange( nFirstCol, nFirstRow, nTab, nLastCol, nLastRow, nTab );
737 	lcl_GetColumnTypes( *this, aDataRange, bHasFieldNames,
738 						aColNames.getArray(), aColTypes.getArray(),
739 						aColLengths.getArray(), aColScales.getArray(),
740 						bHasMemo, eCharSet );
741     // also needed for exception catch
742     SCROW nDocRow = 0;
743     ScFieldEditEngine aEditEngine( aDocument.GetEditPool() );
744     String aString;
745     String aTabName;
746 
747 	try
748 	{
749         uno::Reference<sdbc::XDriverManager> xDrvMan;
750         uno::Reference<sdbc::XConnection> xConnection;
751 		sal_uLong nRet = lcl_getDBaseConnection(xDrvMan,xConnection,aTabName,rFullFileName,eCharSet);
752         if ( !xConnection.is() || !xDrvMan.is() )
753             return nRet;
754         ::utl::DisposableComponent aConnectionHelper(xConnection);
755 
756 		// get dBase driver
757         uno::Reference< sdbc::XDriverAccess> xAccess(xDrvMan,uno::UNO_QUERY);
758         uno::Reference< sdbcx::XDataDefinitionSupplier > xDDSup( xAccess->getDriverByURL( xConnection->getMetaData()->getURL() ), uno::UNO_QUERY );
759 		if ( !xDDSup.is() )
760             return SCERR_EXPORT_CONNECT;
761 
762 		// create table
763 		uno::Reference<sdbcx::XTablesSupplier> xTablesSupp =xDDSup->getDataDefinitionByConnection( xConnection );
764 		DBG_ASSERT( xTablesSupp.is(), "can't get Data Definition" );
765 		if (!xTablesSupp.is()) return SCERR_EXPORT_CONNECT;
766 
767 		uno::Reference<container::XNameAccess> xTables = xTablesSupp->getTables();
768 		DBG_ASSERT( xTables.is(), "can't get Tables" );
769 		if (!xTables.is()) return SCERR_EXPORT_CONNECT;
770 
771 		uno::Reference<sdbcx::XDataDescriptorFactory> xTablesFact( xTables, uno::UNO_QUERY );
772 		DBG_ASSERT( xTablesFact.is(), "can't get tables factory" );
773 		if (!xTablesFact.is()) return SCERR_EXPORT_CONNECT;
774 
775 		uno::Reference<sdbcx::XAppend> xTablesAppend( xTables, uno::UNO_QUERY );
776 		DBG_ASSERT( xTablesAppend.is(), "can't get tables XAppend" );
777 		if (!xTablesAppend.is()) return SCERR_EXPORT_CONNECT;
778 
779 		uno::Reference<beans::XPropertySet> xTableDesc = xTablesFact->createDataDescriptor();
780 		DBG_ASSERT( xTableDesc.is(), "can't get table descriptor" );
781 		if (!xTableDesc.is()) return SCERR_EXPORT_CONNECT;
782 
783 		aAny <<= rtl::OUString( aTabName );
784 		xTableDesc->setPropertyValue( rtl::OUString::createFromAscii(SC_DBPROP_NAME), aAny );
785 
786 		// create columns
787 
788 		uno::Reference<sdbcx::XColumnsSupplier> xColumnsSupp( xTableDesc, uno::UNO_QUERY );
789 		DBG_ASSERT( xColumnsSupp.is(), "can't get columns supplier" );
790 		if (!xColumnsSupp.is()) return SCERR_EXPORT_CONNECT;
791 
792 		uno::Reference<container::XNameAccess> xColumns = xColumnsSupp->getColumns();
793 		DBG_ASSERT( xColumns.is(), "can't get columns" );
794 		if (!xColumns.is()) return SCERR_EXPORT_CONNECT;
795 
796 		uno::Reference<sdbcx::XDataDescriptorFactory> xColumnsFact( xColumns, uno::UNO_QUERY );
797 		DBG_ASSERT( xColumnsFact.is(), "can't get columns factory" );
798 		if (!xColumnsFact.is()) return SCERR_EXPORT_CONNECT;
799 
800 		uno::Reference<sdbcx::XAppend> xColumnsAppend( xColumns, uno::UNO_QUERY );
801 		DBG_ASSERT( xColumnsAppend.is(), "can't get columns XAppend" );
802 		if (!xColumnsAppend.is()) return SCERR_EXPORT_CONNECT;
803 
804 		const rtl::OUString* pColNames = aColNames.getConstArray();
805 		const sal_Int32* pColTypes     = aColTypes.getConstArray();
806 		const sal_Int32* pColLengths   = aColLengths.getConstArray();
807 		const sal_Int32* pColScales    = aColScales.getConstArray();
808 		long nCol;
809 
810 		for (nCol=0; nCol<nColCount; nCol++)
811 		{
812 			uno::Reference<beans::XPropertySet> xColumnDesc = xColumnsFact->createDataDescriptor();
813 			DBG_ASSERT( xColumnDesc.is(), "can't get column descriptor" );
814 			if (!xColumnDesc.is()) return SCERR_EXPORT_CONNECT;
815 
816 			aAny <<= pColNames[nCol];
817 			xColumnDesc->setPropertyValue( rtl::OUString::createFromAscii(SC_DBPROP_NAME), aAny );
818 
819 			aAny <<= pColTypes[nCol];
820 			xColumnDesc->setPropertyValue( rtl::OUString::createFromAscii(SC_DBPROP_TYPE), aAny );
821 
822 			aAny <<= pColLengths[nCol];
823 			xColumnDesc->setPropertyValue( rtl::OUString::createFromAscii(SC_DBPROP_PRECISION), aAny );
824 
825 			aAny <<= pColScales[nCol];
826 			xColumnDesc->setPropertyValue( rtl::OUString::createFromAscii(SC_DBPROP_SCALE), aAny );
827 
828 			xColumnsAppend->appendByDescriptor( xColumnDesc );
829 		}
830 
831 		xTablesAppend->appendByDescriptor( xTableDesc );
832 
833 		// re-open connection
834 //		xConnection = xDrvMan->getConnectionWithInfo( aConnUrl, aProps );
835 //		DBG_ASSERT( xConnection.is(), "can't get Connection" );
836 //		if (!xConnection.is()) return SCERR_EXPORT_CONNECT;
837 
838 		// get row set for writing
839         uno::Reference<lang::XMultiServiceFactory> xFactory = comphelper::getProcessServiceFactory();
840 		uno::Reference<sdbc::XRowSet> xRowSet( xFactory->createInstance(
841 							rtl::OUString::createFromAscii( SC_SERVICE_ROWSET ) ),
842 							uno::UNO_QUERY);
843         ::utl::DisposableComponent aRowSetHelper(xRowSet);
844 		uno::Reference<beans::XPropertySet> xRowProp( xRowSet, uno::UNO_QUERY );
845 		DBG_ASSERT( xRowProp.is(), "can't get RowSet" );
846 		if (!xRowProp.is()) return SCERR_EXPORT_CONNECT;
847 
848 		aAny <<= xConnection;
849 		xRowProp->setPropertyValue(
850 					rtl::OUString::createFromAscii(SC_DBPROP_ACTIVECONNECTION), aAny );
851 
852 		aAny <<= (sal_Int32) sdb::CommandType::TABLE;
853 		xRowProp->setPropertyValue(
854 					rtl::OUString::createFromAscii(SC_DBPROP_COMMANDTYPE), aAny );
855 
856 		aAny <<= rtl::OUString( aTabName );
857 		xRowProp->setPropertyValue(
858 					rtl::OUString::createFromAscii(SC_DBPROP_COMMAND), aAny );
859 
860 		xRowSet->execute();
861 
862 		// write data rows
863 
864 		uno::Reference<sdbc::XResultSetUpdate> xResultUpdate( xRowSet, uno::UNO_QUERY );
865 		DBG_ASSERT( xResultUpdate.is(), "can't get XResultSetUpdate" );
866 		if (!xResultUpdate.is()) return SCERR_EXPORT_CONNECT;
867 
868 		uno::Reference<sdbc::XRowUpdate> xRowUpdate( xRowSet, uno::UNO_QUERY );
869 		DBG_ASSERT( xRowUpdate.is(), "can't get XRowUpdate" );
870 		if (!xRowUpdate.is()) return SCERR_EXPORT_CONNECT;
871 
872 		SCROW nFirstDataRow = ( bHasFieldNames ? nFirstRow + 1 : nFirstRow );
873 		double fVal;
874 
875 		for ( nDocRow = nFirstDataRow; nDocRow <= nLastRow; nDocRow++ )
876 		{
877 			xResultUpdate->moveToInsertRow();
878 
879 			for (nCol=0; nCol<nColCount; nCol++)
880 			{
881                 SCCOL nDocCol = sal::static_int_cast<SCCOL>( nFirstCol + nCol );
882 
883 				switch (pColTypes[nCol])
884 				{
885 					case sdbc::DataType::LONGVARCHAR:
886 						{
887 							ScBaseCell* pCell;
888 							aDocument.GetCell( nDocCol, nDocRow, nTab, pCell );
889 							if ( pCell && pCell->GetCellType() != CELLTYPE_NOTE )
890 							{
891 								if ( pCell->GetCellType() == CELLTYPE_EDIT )
892 								{	// #60761# Paragraphs erhalten
893                                     lcl_getLongVarCharEditString( aString,
894                                             pCell, aEditEngine);
895 								}
896 								else
897 								{
898                                     lcl_getLongVarCharString( aString, pCell,
899                                             aDocument, nDocCol, nDocRow, nTab,
900                                             *pNumFmt);
901 								}
902 								xRowUpdate->updateString( nCol+1, aString );
903 							}
904 							else
905 								xRowUpdate->updateNull( nCol+1 );
906 						}
907 						break;
908 
909 					case sdbc::DataType::VARCHAR:
910 						aDocument.GetString( nDocCol, nDocRow, nTab, aString );
911 						xRowUpdate->updateString( nCol+1, aString );
912 						if ( nErr == eERR_OK && pColLengths[nCol] < aString.Len() )
913 							nErr = SCWARN_EXPORT_DATALOST;
914 						break;
915 
916 					case sdbc::DataType::DATE:
917 						{
918 							aDocument.GetValue( nDocCol, nDocRow, nTab, fVal );
919 							// #39274# zwischen 0 Wert und 0 kein Wert unterscheiden
920 							sal_Bool bIsNull = (fVal == 0.0);
921 							if ( bIsNull )
922 								bIsNull = !aDocument.HasValueData( nDocCol, nDocRow, nTab );
923 							if ( bIsNull )
924 							{
925 								xRowUpdate->updateNull( nCol+1 );
926 								if ( nErr == eERR_OK &&
927 										aDocument.HasStringData( nDocCol, nDocRow, nTab ) )
928 									nErr = SCWARN_EXPORT_DATALOST;
929 							}
930 							else
931 							{
932 								Date aDate = *(pNumFmt->GetNullDate());		// tools date
933 								aDate += (long)fVal;						//! approxfloor?
934 								util::Date aUnoDate( aDate.GetDay(), aDate.GetMonth(), aDate.GetYear() );
935 								xRowUpdate->updateDate( nCol+1, aUnoDate );
936 							}
937 						}
938 						break;
939 
940 					case sdbc::DataType::DECIMAL:
941 					case sdbc::DataType::BIT:
942 						aDocument.GetValue( nDocCol, nDocRow, nTab, fVal );
943 						if ( fVal == 0.0 && nErr == eERR_OK &&
944 											aDocument.HasStringData( nDocCol, nDocRow, nTab ) )
945 							nErr = SCWARN_EXPORT_DATALOST;
946 						if ( pColTypes[nCol] == sdbc::DataType::BIT )
947 							xRowUpdate->updateBoolean( nCol+1, ( fVal != 0.0 ) );
948 						else
949 							xRowUpdate->updateDouble( nCol+1, fVal );
950 						break;
951 
952 					default:
953 						DBG_ERROR( "ScDocShell::DBaseExport: unknown FieldType" );
954 						if ( nErr == eERR_OK )
955 							nErr = SCWARN_EXPORT_DATALOST;
956 						aDocument.GetValue( nDocCol, nDocRow, nTab, fVal );
957 						xRowUpdate->updateDouble( nCol+1, fVal );
958 				}
959 			}
960 
961 			xResultUpdate->insertRow();
962 
963 			//!	error handling and recovery of old
964 			//!	ScDocShell::SbaSdbExport is still missing!
965 
966 			if ( !aProgress.SetStateOnPercent( nDocRow - nFirstRow ) )
967 			{	// UserBreak
968 				nErr = SCERR_EXPORT_DATA;
969 				break;
970 			}
971 		}
972 
973 		comphelper::disposeComponent( xRowSet );
974 		comphelper::disposeComponent( xConnection );
975 	}
976 	catch ( sdbc::SQLException& aException )
977 	{
978         sal_Int32 nError = aException.ErrorCode;
979 #if OSL_DEBUG_LEVEL > 1
980         fprintf( stderr, "ScDocShell::DBaseExport: SQLException ErrorCode: %d, SQLState: %s, Message: %s\n",
981                 (int)nError, OUStringToOString( aException.SQLState,
982                     RTL_TEXTENCODING_UTF8).getStr(), OUStringToOString(
983                         aException.Message, RTL_TEXTENCODING_UTF8).getStr());
984 #endif
985         if (nError == 22018 || nError == 22001)
986         {
987             // SQL error 22018: Character not in target encoding.
988             // SQL error 22001: String length exceeds field width (after encoding).
989             bool bEncErr = (nError == 22018);
990             bool bIsOctetTextEncoding = rtl_isOctetTextEncoding( eCharSet);
991             DBG_ASSERT( !bEncErr || bIsOctetTextEncoding, "ScDocShell::DBaseExport: encoding error and not an octect textencoding");
992             SCCOL nDocCol = nFirstCol;
993             const sal_Int32* pColTypes = aColTypes.getConstArray();
994             const sal_Int32* pColLengths = aColLengths.getConstArray();
995             ScHorizontalCellIterator aIter( &aDocument, nTab, nFirstCol,
996                     nDocRow, nLastCol, nDocRow);
997             ScBaseCell* pCell = NULL;
998             bool bTest = true;
999             while (bTest && ((pCell = aIter.GetNext( nDocCol, nDocRow)) != NULL))
1000             {
1001                 SCCOL nCol = nDocCol - nFirstCol;
1002                 switch (pColTypes[nCol])
1003                 {
1004                     case sdbc::DataType::LONGVARCHAR:
1005                         {
1006                             if ( pCell->GetCellType() != CELLTYPE_NOTE )
1007                             {
1008                                 if ( pCell->GetCellType() == CELLTYPE_EDIT )
1009                                     lcl_getLongVarCharEditString( aString,
1010                                             pCell, aEditEngine);
1011                                 else
1012                                     lcl_getLongVarCharString( aString,
1013                                             pCell, aDocument, nDocCol,
1014                                             nDocRow, nTab, *pNumFmt);
1015                             }
1016                         }
1017                         break;
1018 
1019                     case sdbc::DataType::VARCHAR:
1020                         aDocument.GetString( nDocCol, nDocRow, nTab, aString);
1021                         break;
1022 
1023                     // NOTE: length of DECIMAL fields doesn't need to be
1024                     // checked here, the database driver adjusts the field
1025                     // width accordingly.
1026 
1027                     default:
1028                         bTest = false;
1029                 }
1030                 if (bTest)
1031                 {
1032                     sal_Int32 nLen;
1033                     if (bIsOctetTextEncoding)
1034                     {
1035                         rtl::OUString aOUString( aString);
1036                         rtl::OString aOString;
1037                         if (!aOUString.convertToString( &aOString, eCharSet,
1038                                     RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
1039                                     RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR))
1040                         {
1041                             bTest = false;
1042                             bEncErr = true;
1043                         }
1044                         nLen = aOString.getLength();
1045 #if OSL_DEBUG_LEVEL > 1
1046                         if (!bTest)
1047                             fprintf( stderr, "ScDocShell::DBaseExport encoding error, string with default replacements: ``%s''\n",
1048                                     OUStringToOString( aOUString, eCharSet).getStr());
1049 #endif
1050                     }
1051                     else
1052                         nLen = aString.Len() * sizeof(sal_Unicode);
1053                     if (!bEncErr &&
1054                             pColTypes[nCol] != sdbc::DataType::LONGVARCHAR &&
1055                             pColLengths[nCol] < nLen)
1056                     {
1057                         bTest = false;
1058 #if OSL_DEBUG_LEVEL > 1
1059                         fprintf( stderr, "ScDocShell::DBaseExport: field width: %d, encoded length: %d\n",
1060                                 (int)pColLengths[nCol], (int)nLen);
1061 #endif
1062                     }
1063                 }
1064                 else
1065                     bTest = true;
1066             }
1067             String sPosition( ScAddress( nDocCol, nDocRow, nTab).GetColRowString());
1068             String sEncoding( SvxTextEncodingTable().GetTextString( eCharSet));
1069             nErr = *new TwoStringErrorInfo( (bEncErr ? SCERR_EXPORT_ENCODING :
1070                         SCERR_EXPORT_FIELDWIDTH), sPosition, sEncoding,
1071                     ERRCODE_BUTTON_OK | ERRCODE_MSG_ERROR);
1072         }
1073         else if ( aException.Message.getLength() )
1074             nErr = *new StringErrorInfo( (SCERR_EXPORT_SQLEXCEPTION), aException.Message, ERRCODE_BUTTON_OK | ERRCODE_MSG_ERROR);
1075         else
1076             nErr = SCERR_EXPORT_DATA;
1077 	}
1078 	catch ( uno::Exception& )
1079 	{
1080 		DBG_ERROR("Unexpected exception in database");
1081 		nErr = ERRCODE_IO_GENERAL;
1082 	}
1083 
1084 	return nErr;
1085 }
1086 
1087 
1088