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 { 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 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 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 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 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 396 inline sal_Bool IsAsciiDigit( sal_Unicode c ) 397 { 398 return 0x30 <= c && c <= 0x39; 399 } 400 401 inline sal_Bool IsAsciiAlpha( sal_Unicode c ) 402 { 403 return (0x41 <= c && c <= 0x5a) || (0x61 <= c && c <= 0x7a); 404 } 405 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 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 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 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