xref: /AOO41X/main/sc/source/ui/docshell/docsh8.cxx (revision b3f79822e811ac3493b185030a72c3c5a51f32d8)
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 substract 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