1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: docsh8.cxx,v $
10 * $Revision: 1.27.32.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
36 // INCLUDE ---------------------------------------------------------------
39 #include <tools/urlobj.hxx>
40 #include <svtools/converter.hxx>
41 #include <svtools/zforlist.hxx>
42 #include <comphelper/types.hxx>
43 #include <ucbhelper/content.hxx>
44 #include <unotools/sharedunocomponent.hxx>
45 #include <comphelper/processfactory.hxx>
46 #include <svx/txenctab.hxx>
47 #include <svx/dbcharsethelper.hxx>
49 #include <com/sun/star/sdb/CommandType.hpp>
50 #include <com/sun/star/sdbc/DataType.hpp>
51 #include <com/sun/star/sdbc/XConnection.hpp>
52 #include <com/sun/star/sdbc/XDriver.hpp>
53 #include <com/sun/star/sdbc/XDriverAccess.hpp>
54 #include <com/sun/star/sdbc/XDriverManager.hpp>
55 #include <com/sun/star/sdbc/XResultSetUpdate.hpp>
56 #include <com/sun/star/sdbc/XRow.hpp>
57 #include <com/sun/star/sdbc/XRowSet.hpp>
58 #include <com/sun/star/sdbc/XRowUpdate.hpp>
59 #include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
60 #include <com/sun/star/sdbcx/XAppend.hpp>
61 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
62 #include <com/sun/star/sdbcx/XDataDefinitionSupplier.hpp>
63 #include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
64 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
65 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
66 #include <com/sun/star/beans/XPropertySet.hpp>
67 #include <com/sun/star/container/XEnumerationAccess.hpp>
68 #include <com/sun/star/lang/XComponent.hpp>
69 #include <com/sun/star/ucb/NameClash.hpp>
70 #include <com/sun/star/ucb/TransferInfo.hpp>
71 #include <com/sun/star/ucb/XCommandInfo.hpp>
73 #include "scerrors.hxx"
76 #include "progress.hxx"
77 #include "collect.hxx"
79 #include "editutil.hxx"
80 #include "cellform.hxx"
81 #include "dbdocutl.hxx"
82 #include "dociter.hxx"
83 #include "globstr.hrc"
84 #include "svtools/zformat.hxx"
85 #include "svtools/intitem.hxx"
86 #include "patattr.hxx"
87 #include "scitems.hxx"
88 #include "docpool.hxx"
92 using namespace com::sun::star
;
95 // -----------------------------------------------------------------------
97 #define SC_SERVICE_ROWSET "com.sun.star.sdb.RowSet"
98 #define SC_SERVICE_DRVMAN "com.sun.star.sdbc.DriverManager"
100 //! move to a header file?
101 //#define SC_DBPROP_DATASOURCENAME "DataSourceName"
102 #define SC_DBPROP_ACTIVECONNECTION "ActiveConnection"
103 #define SC_DBPROP_COMMAND "Command"
104 #define SC_DBPROP_COMMANDTYPE "CommandType"
106 #define SC_DBPROP_NAME "Name"
107 #define SC_DBPROP_TYPE "Type"
108 #define SC_DBPROP_PRECISION "Precision"
109 #define SC_DBPROP_SCALE "Scale"
111 #define SC_DBPROP_EXTENSION "Extension"
112 #define SC_DBPROP_CHARSET "CharSet"
114 #define SC_ROWCOUNT_ERROR (-1)
118 ULONG
lcl_getDBaseConnection(uno::Reference
<sdbc::XDriverManager
>& _rDrvMgr
,uno::Reference
<sdbc::XConnection
>& _rConnection
,String
& _rTabName
,const String
& rFullFileName
,rtl_TextEncoding eCharSet
)
121 aURL
.SetSmartProtocol( INET_PROT_FILE
);
122 aURL
.SetSmartURL( rFullFileName
);
123 _rTabName
= aURL
.getBase( INetURLObject::LAST_SEGMENT
, true,
124 INetURLObject::DECODE_UNAMBIGUOUS
);
125 String aExtension
= aURL
.getExtension();
126 aURL
.removeSegment();
127 aURL
.removeFinalSlash();
128 String aPath
= aURL
.GetMainURL(INetURLObject::NO_DECODE
);
129 uno::Reference
<lang::XMultiServiceFactory
> xFactory
= comphelper::getProcessServiceFactory();
130 if (!xFactory
.is()) return SCERR_EXPORT_CONNECT
;
132 _rDrvMgr
.set( xFactory
->createInstance(
133 rtl::OUString::createFromAscii( SC_SERVICE_DRVMAN
) ),
135 DBG_ASSERT( _rDrvMgr
.is(), "can't get DriverManager" );
136 if (!_rDrvMgr
.is()) return SCERR_EXPORT_CONNECT
;
140 String aConnUrl
= String::CreateFromAscii("sdbc:dbase:");
143 svxform::ODataAccessCharsetHelper aHelper
;
144 ::std::vector
< rtl_TextEncoding
> aEncodings
;
145 aHelper
.getSupportedTextEncodings( aEncodings
);
146 ::std::vector
< rtl_TextEncoding
>::iterator aIter
= ::std::find(aEncodings
.begin(),aEncodings
.end(),(rtl_TextEncoding
) eCharSet
);
147 if ( aIter
== aEncodings
.end() )
149 DBG_ERRORFILE( "DBaseImport: dbtools::OCharsetMap doesn't know text encoding" );
150 return SCERR_IMPORT_CONNECT
;
151 } // if ( aIter == aMap.end() )
152 rtl::OUString aCharSetStr
;
153 if ( RTL_TEXTENCODING_DONTKNOW
!= *aIter
)
154 { // it's not the virtual "system charset"
155 const char* pIanaName
= rtl_getMimeCharsetFromTextEncoding( *aIter
);
156 OSL_ENSURE( pIanaName
, "invalid mime name!" );
158 aCharSetStr
= ::rtl::OUString::createFromAscii( pIanaName
);
161 uno::Sequence
<beans::PropertyValue
> aProps(2);
162 aProps
[0].Name
= rtl::OUString::createFromAscii(SC_DBPROP_EXTENSION
);
163 aProps
[0].Value
<<= rtl::OUString( aExtension
);
164 aProps
[1].Name
= rtl::OUString::createFromAscii(SC_DBPROP_CHARSET
);
165 aProps
[1].Value
<<= aCharSetStr
;
167 _rConnection
= _rDrvMgr
->getConnectionWithInfo( aConnUrl
, aProps
);
171 // -----------------------------------------------------------------------
172 // MoveFile/KillFile/IsDocument: similar to SfxContentHelper
175 BOOL
ScDocShell::MoveFile( const INetURLObject
& rSourceObj
, const INetURLObject
& rDestObj
)
177 sal_Bool bMoveData
= sal_True
;
178 sal_Bool bRet
= sal_True
, bKillSource
= sal_False
;
179 if ( rSourceObj
.GetProtocol() != rDestObj
.GetProtocol() )
181 bMoveData
= sal_False
;
182 bKillSource
= sal_True
;
184 String aName
= rDestObj
.getName();
185 INetURLObject aDestPathObj
= rDestObj
;
186 aDestPathObj
.removeSegment();
187 aDestPathObj
.setFinalSlash();
191 ::ucbhelper::Content
aDestPath( aDestPathObj
.GetMainURL(INetURLObject::NO_DECODE
),
192 uno::Reference
< ::com::sun::star::ucb::XCommandEnvironment
> () );
193 uno::Reference
< ::com::sun::star::ucb::XCommandInfo
> xInfo
= aDestPath
.getCommands();
194 rtl::OUString aTransferName
= rtl::OUString::createFromAscii( "transfer" );
195 if ( xInfo
->hasCommandByName( aTransferName
) )
197 aDestPath
.executeCommand( aTransferName
, uno::makeAny(
198 ::com::sun::star::ucb::TransferInfo( bMoveData
, rSourceObj
.GetMainURL(INetURLObject::NO_DECODE
), aName
,
199 ::com::sun::star::ucb::NameClash::ERROR
) ) );
203 DBG_ERRORFILE( "transfer command not available" );
206 catch( uno::Exception
& )
208 // ucb may throw different exceptions on failure now
213 KillFile( rSourceObj
);
220 BOOL
ScDocShell::KillFile( const INetURLObject
& rURL
)
222 sal_Bool bRet
= sal_True
;
225 ::ucbhelper::Content
aCnt( rURL
.GetMainURL(INetURLObject::NO_DECODE
),
226 uno::Reference
< ::com::sun::star::ucb::XCommandEnvironment
> () );
227 aCnt
.executeCommand( rtl::OUString::createFromAscii( "delete" ),
228 comphelper::makeBoolAny( sal_True
) );
230 catch( uno::Exception
& )
232 // ucb may throw different exceptions on failure now
240 BOOL
ScDocShell::IsDocument( const INetURLObject
& rURL
)
242 sal_Bool bRet
= sal_False
;
245 ::ucbhelper::Content
aCnt( rURL
.GetMainURL(INetURLObject::NO_DECODE
),
246 uno::Reference
< ::com::sun::star::ucb::XCommandEnvironment
> () );
247 bRet
= aCnt
.isDocument();
249 catch( uno::Exception
& )
251 // ucb may throw different exceptions on failure now - warning only
252 DBG_WARNING( "Any other exception" );
258 // -----------------------------------------------------------------------
260 static void lcl_setScalesToColumns(ScDocument
& rDoc
, const vector
<long>& rScales
)
262 SvNumberFormatter
* pFormatter
= rDoc
.GetFormatTable();
266 SCCOL nColCount
= static_cast<SCCOL
>(rScales
.size());
267 for (SCCOL i
= 0; i
< nColCount
; ++i
)
272 sal_uInt32 nOldFormat
;
273 rDoc
.GetNumberFormat(static_cast<SCCOL
>(i
), 0, 0, nOldFormat
);
274 const SvNumberformat
* pOldEntry
= pFormatter
->GetEntry(nOldFormat
);
278 LanguageType eLang
= pOldEntry
->GetLanguage();
279 BOOL bThousand
, bNegRed
;
280 USHORT nPrecision
, nLeading
;
281 pOldEntry
->GetFormatSpecialInfo(bThousand
, bNegRed
, nPrecision
, nLeading
);
283 nPrecision
= static_cast<USHORT
>(rScales
[i
]);
285 pFormatter
->GenerateFormat(aNewPicture
, nOldFormat
, eLang
,
286 bThousand
, bNegRed
, nPrecision
, nLeading
);
288 sal_uInt32 nNewFormat
= pFormatter
->GetEntryKey(aNewPicture
, eLang
);
289 if (nNewFormat
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
291 xub_StrLen nErrPos
= 0;
293 bool bOk
= pFormatter
->PutEntry(
294 aNewPicture
, nErrPos
, nNewType
, nNewFormat
, eLang
);
300 ScPatternAttr
aNewAttrs( rDoc
.GetPool() );
301 SfxItemSet
& rSet
= aNewAttrs
.GetItemSet();
302 rSet
.Put( SfxUInt32Item(ATTR_VALUE_FORMAT
, nNewFormat
) );
303 rDoc
.ApplyPatternAreaTab(static_cast<SCCOL
>(i
), 0, static_cast<SCCOL
>(i
), MAXROW
, 0, aNewAttrs
);
307 ULONG
ScDocShell::DBaseImport( const String
& rFullFileName
, CharSet eCharSet
,
308 BOOL bSimpleColWidth
[MAXCOLCOUNT
] )
310 ULONG nErr
= eERR_OK
;
316 uno::Reference
<sdbc::XDriverManager
> xDrvMan
;
317 uno::Reference
<sdbc::XConnection
> xConnection
;
318 ULONG nRet
= lcl_getDBaseConnection(xDrvMan
,xConnection
,aTabName
,rFullFileName
,eCharSet
);
319 if ( !xConnection
.is() || !xDrvMan
.is() )
321 ::utl::DisposableComponent
aConnectionHelper(xConnection
);
326 DBG_ERROR("can't get row count");
330 ScProgress
aProgress( this, ScGlobal::GetRscString( STR_LOAD_DOC
), nRowCount
);
331 uno::Reference
<lang::XMultiServiceFactory
> xFactory
= comphelper::getProcessServiceFactory();
332 uno::Reference
<sdbc::XRowSet
> xRowSet( xFactory
->createInstance(
333 rtl::OUString::createFromAscii( SC_SERVICE_ROWSET
) ),
335 ::utl::DisposableComponent
aRowSetHelper(xRowSet
);
336 uno::Reference
<beans::XPropertySet
> xRowProp( xRowSet
, uno::UNO_QUERY
);
337 DBG_ASSERT( xRowProp
.is(), "can't get RowSet" );
338 if (!xRowProp
.is()) return SCERR_IMPORT_CONNECT
;
340 sal_Int32 nType
= sdb::CommandType::TABLE
;
343 aAny
<<= xConnection
;
344 xRowProp
->setPropertyValue(
345 rtl::OUString::createFromAscii(SC_DBPROP_ACTIVECONNECTION
), aAny
);
348 xRowProp
->setPropertyValue(
349 rtl::OUString::createFromAscii(SC_DBPROP_COMMANDTYPE
), aAny
);
351 aAny
<<= rtl::OUString( aTabName
);
352 xRowProp
->setPropertyValue(
353 rtl::OUString::createFromAscii(SC_DBPROP_COMMAND
), aAny
);
358 uno::Reference
<sdbc::XResultSetMetaData
> xMeta
;
359 uno::Reference
<sdbc::XResultSetMetaDataSupplier
> xMetaSupp( xRowSet
, uno::UNO_QUERY
);
360 if ( xMetaSupp
.is() )
361 xMeta
= xMetaSupp
->getMetaData();
363 nColCount
= xMeta
->getColumnCount(); // this is the number of real columns
365 if ( nColCount
> MAXCOL
+1 )
367 nColCount
= MAXCOL
+1;
368 nErr
= SCWARN_IMPORT_RANGE_OVERFLOW
; // warning
372 aDocument
.DoColResize( 0, 0, static_cast<SCCOL
>(nColCount
) - 1,
373 static_cast<SCSIZE
>(nRowCount
) + 1 );
375 uno::Reference
<sdbc::XRow
> xRow( xRowSet
, uno::UNO_QUERY
);
376 DBG_ASSERT( xRow
.is(), "can't get Row" );
377 if (!xRow
.is()) return SCERR_IMPORT_CONNECT
;
379 // currency flag is not needed for dBase
380 uno::Sequence
<sal_Int32
> aColTypes( nColCount
); // column types
381 sal_Int32
* pTypeArr
= aColTypes
.getArray();
382 for (i
=0; i
<nColCount
; i
++)
383 pTypeArr
[i
] = xMeta
->getColumnType( i
+1 );
386 //! add type descriptions
388 vector
<long> aScales(nColCount
, -1);
389 for (i
=0; i
<nColCount
; i
++)
391 String aHeader
= xMeta
->getColumnLabel( i
+1 );
393 switch ( pTypeArr
[i
] )
395 case sdbc::DataType::BIT
:
396 aHeader
.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ",L" ));
398 case sdbc::DataType::DATE
:
399 aHeader
.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ",D" ));
401 case sdbc::DataType::LONGVARCHAR
:
402 aHeader
.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ",M" ));
404 case sdbc::DataType::VARCHAR
:
405 aHeader
.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ",C," ));
406 aHeader
+= String::CreateFromInt32( xMeta
->getColumnDisplaySize( i
+1 ) );
408 case sdbc::DataType::DECIMAL
:
410 long nPrec
= xMeta
->getPrecision( i
+1 );
411 long nScale
= xMeta
->getScale( i
+1 );
412 aHeader
.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ",N," ));
413 aHeader
+= String::CreateFromInt32(
414 SvDbaseConverter::ConvertPrecisionToDbase(
417 aHeader
+= String::CreateFromInt32( nScale
);
423 aDocument
.SetString( static_cast<SCCOL
>(i
), 0, 0, aHeader
);
426 lcl_setScalesToColumns(aDocument
, aScales
);
428 SCROW nRow
= 1; // 0 is column titles
430 while ( !bEnd
&& xRowSet
->next() )
432 if ( nRow
<= MAXROW
)
435 for (i
=0; i
<nColCount
; i
++)
437 ScDatabaseDocUtil::PutData( &aDocument
, nCol
, nRow
, 0,
438 xRow
, i
+1, pTypeArr
[i
], FALSE
,
439 &bSimpleColWidth
[nCol
] );
444 else // past the end of the spreadsheet
446 bEnd
= TRUE
; // don't continue
447 nErr
= SCWARN_IMPORT_RANGE_OVERFLOW
; // warning message
451 aProgress
.SetStateOnPercent( nRow
);
454 catch ( sdbc::SQLException
& )
456 nErr
= SCERR_IMPORT_CONNECT
;
458 catch ( uno::Exception
& )
460 DBG_ERROR("Unexpected exception in database");
461 nErr
= ERRCODE_IO_GENERAL
;
467 // -----------------------------------------------------------------------
469 inline sal_Bool
IsAsciiDigit( sal_Unicode c
)
471 return 0x30 <= c
&& c
<= 0x39;
474 inline sal_Bool
IsAsciiAlpha( sal_Unicode c
)
476 return (0x41 <= c
&& c
<= 0x5a) || (0x61 <= c
&& c
<= 0x7a);
479 void lcl_GetColumnTypes( ScDocShell
& rDocShell
,
480 const ScRange
& rDataRange
, BOOL bHasFieldNames
,
481 rtl::OUString
* pColNames
, sal_Int32
* pColTypes
,
482 sal_Int32
* pColLengths
, sal_Int32
* pColScales
,
483 BOOL
& bHasMemo
, CharSet eCharSet
)
485 // updating of column titles didn't work in 5.2 and isn't always wanted
486 // (saving normally shouldn't modify the document)
487 //! read flag from configuration
488 BOOL bUpdateTitles
= FALSE
;
490 ScDocument
* pDoc
= rDocShell
.GetDocument();
491 SvNumberFormatter
* pNumFmt
= pDoc
->GetFormatTable();
493 SCTAB nTab
= rDataRange
.aStart
.Tab();
494 SCCOL nFirstCol
= rDataRange
.aStart
.Col();
495 SCROW nFirstRow
= rDataRange
.aStart
.Row();
496 SCCOL nLastCol
= rDataRange
.aEnd
.Col();
497 SCROW nLastRow
= rDataRange
.aEnd
.Row();
499 ScStrCollection aFieldNamesCollection
;
502 SCROW nFirstDataRow
= ( bHasFieldNames
? nFirstRow
+ 1 : nFirstRow
);
503 for ( SCCOL nCol
= nFirstCol
; nCol
<= nLastCol
; nCol
++ )
505 BOOL bTypeDefined
= FALSE
;
506 BOOL bPrecDefined
= FALSE
;
507 sal_Int32 nFieldLen
= 0;
508 sal_Int32 nPrecision
= 0;
509 sal_Int32 nDbType
= sdbc::DataType::SQLNULL
;
510 String aFieldName
, aString
;
512 // Feldname[,Type[,Width[,Prec]]]
513 // Typ etc.: L; D; C[,W]; N[,W[,P]]
514 if ( bHasFieldNames
)
516 pDoc
->GetString( nCol
, nFirstRow
, nTab
, aString
);
517 aString
.ToUpperAscii();
518 xub_StrLen nToken
= aString
.GetTokenCount( ',' );
521 aFieldName
= aString
.GetToken( 0, ',' );
522 aString
.EraseAllChars( ' ' );
523 switch ( aString
.GetToken( 1, ',' ).GetChar(0) )
526 nDbType
= sdbc::DataType::BIT
;
532 nDbType
= sdbc::DataType::DATE
;
538 nDbType
= sdbc::DataType::LONGVARCHAR
;
545 nDbType
= sdbc::DataType::VARCHAR
;
550 nDbType
= sdbc::DataType::DECIMAL
;
553 if ( bTypeDefined
&& !nFieldLen
&& nToken
> 2 )
555 nFieldLen
= aString
.GetToken( 2, ',' ).ToInt32();
556 if ( !bPrecDefined
&& nToken
> 3 )
558 String
aTmp( aString
.GetToken( 3, ',' ) );
559 if ( CharClass::isAsciiNumeric(aTmp
) )
561 nPrecision
= aTmp
.ToInt32();
568 aFieldName
= aString
;
570 // Feldnamen pruefen und ggbf. gueltigen Feldnamen erzeugen.
571 // Erstes Zeichen muss Buchstabe sein,
572 // weitere nur alphanumerisch und Unterstrich erlaubt,
573 // "_DBASELOCK" ist reserviert (obsolet weil erstes Zeichen kein Buchstabe),
574 // keine doppelten Namen.
575 if ( !IsAsciiAlpha( aFieldName
.GetChar(0) ) )
576 aFieldName
.Insert( 'N', 0 );
579 for ( const sal_Unicode
* p
= aFieldName
.GetBuffer(); ( c
= *p
) != 0; p
++ )
581 if ( IsAsciiAlpha( c
) || IsAsciiDigit( c
) || c
== '_' )
586 aFieldName
= aTmpStr
;
587 if ( aFieldName
.Len() > 10 )
588 aFieldName
.Erase( 10 );
589 StrData
* pStrData
= new StrData( aFieldName
);
590 if ( !aFieldNamesCollection
.Insert( pStrData
) )
591 { // doppelter Feldname, numerisch erweitern
593 String
aFixPart( aFieldName
);
597 String aVarPart
= String::CreateFromInt32( nSub
);
598 if ( aFixPart
.Len() + aVarPart
.Len() > 10 )
599 aFixPart
.Erase( 10 - aVarPart
.Len() );
600 aFieldName
= aFixPart
;
601 aFieldName
+= aVarPart
;
602 pStrData
->SetString( aFieldName
);
603 } while ( !aFieldNamesCollection
.Insert( pStrData
) );
609 aFieldName
+= String::CreateFromInt32(nCol
+1);
615 pDoc
->GetCell( nCol
, nFirstDataRow
, nTab
, pCell
);
616 if ( !pCell
|| pCell
->HasStringData() )
617 nDbType
= sdbc::DataType::VARCHAR
;
621 pDoc
->GetNumberFormat( nCol
, nFirstDataRow
, nTab
, nFormat
);
622 if ( pCell
&& pCell
->GetCellType() == CELLTYPE_FORMULA
623 && ((nFormat
% SV_COUNTRY_LANGUAGE_OFFSET
) == 0) )
625 nFormat
= ScGlobal::GetStandardFormat(
626 ((ScFormulaCell
*)pCell
)->GetValue(), *pNumFmt
, nFormat
,
627 ((ScFormulaCell
*)pCell
)->GetFormatType() );
629 switch ( pNumFmt
->GetType( nFormat
) )
631 case NUMBERFORMAT_LOGICAL
:
632 nDbType
= sdbc::DataType::BIT
;
635 case NUMBERFORMAT_DATE
:
636 nDbType
= sdbc::DataType::DATE
;
639 case NUMBERFORMAT_TIME
:
640 case NUMBERFORMAT_DATETIME
:
641 nDbType
= sdbc::DataType::VARCHAR
;
644 nDbType
= sdbc::DataType::DECIMAL
;
648 BOOL bSdbLenAdjusted
= FALSE
;
649 BOOL bSdbLenBad
= FALSE
;
651 if ( nDbType
== sdbc::DataType::VARCHAR
&& !nFieldLen
)
652 { // maximale Feldbreite bestimmen
653 nFieldLen
= pDoc
->GetMaxStringLen( nTab
, nCol
, nFirstDataRow
,
654 nLastRow
, eCharSet
);
655 if ( nFieldLen
== 0 )
658 else if ( nDbType
== sdbc::DataType::DECIMAL
)
659 { // maximale Feldbreite und Nachkommastellen bestimmen
662 nLen
= pDoc
->GetMaxNumberStringLen( nPrec
, nTab
, nCol
,
663 nFirstDataRow
, nLastRow
);
664 // dBaseIII Limit Nachkommastellen: 15
665 if ( nPrecision
> 15 )
669 if ( bPrecDefined
&& nPrecision
!= nPrec
)
670 { // Laenge auf vorgegebene Nachkommastellen anpassen
672 nLen
= sal::static_int_cast
<xub_StrLen
>( nLen
+ ( nPrecision
- nPrec
) );
674 nLen
-= nPrec
+1; // auch den . mit raus
676 if ( nLen
> nFieldLen
&& !bTypeDefined
)
680 if ( nFieldLen
== 0 )
682 else if ( nFieldLen
> 19 )
683 nFieldLen
= 19; // dBaseIII Limit Feldlaenge numerisch: 19
684 if ( nPrecision
&& nFieldLen
< nPrecision
+ 2 )
685 nFieldLen
= nPrecision
+ 2; // 0. muss mit reinpassen
686 // 538 MUST: Sdb internal representation adds 2 to the field length!
687 // To give the user what he wants we must substract it here.
688 //! CAVEAT! There is no way to define a numeric field with a length
689 //! of 1 and no decimals!
690 if ( nFieldLen
== 1 && nPrecision
== 0 )
692 nFieldLen
= SvDbaseConverter::ConvertPrecisionToOdbc( nFieldLen
, nPrecision
);
693 bSdbLenAdjusted
= TRUE
;
695 if ( nFieldLen
> 254 )
697 if ( nDbType
== sdbc::DataType::VARCHAR
)
698 { // zu lang fuer normales Textfeld => Memofeld
699 nDbType
= sdbc::DataType::LONGVARCHAR
;
704 nFieldLen
= 254; // dumm gelaufen..
707 pColNames
[nField
] = aFieldName
;
708 pColTypes
[nField
] = nDbType
;
709 pColLengths
[nField
] = nFieldLen
;
710 pColScales
[nField
] = nPrecision
;
712 // undo change to field length, reflect reality
713 if ( bSdbLenAdjusted
)
715 nFieldLen
= SvDbaseConverter::ConvertPrecisionToDbase( nFieldLen
, nPrecision
);
716 if ( bSdbLenBad
&& nFieldLen
== 1 )
717 nFieldLen
= 2; // THIS is reality
720 { // Angabe anpassen und ausgeben
721 String aOutString
= aFieldName
;
724 case sdbc::DataType::BIT
:
725 aOutString
.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ",L" ));
727 case sdbc::DataType::DATE
:
728 aOutString
.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ",D" ));
730 case sdbc::DataType::LONGVARCHAR
:
731 aOutString
.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ",M" ));
733 case sdbc::DataType::VARCHAR
:
734 aOutString
.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ",C," ));
735 aOutString
+= String::CreateFromInt32( nFieldLen
);
737 case sdbc::DataType::DECIMAL
:
738 aOutString
.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ",N," ));
739 aOutString
+= String::CreateFromInt32( nFieldLen
);
741 aOutString
+= String::CreateFromInt32( nPrecision
);
744 if ( !aOutString
.EqualsIgnoreCaseAscii( aString
) )
746 pDoc
->SetString( nCol
, nFirstRow
, nTab
, aOutString
);
747 rDocShell
.PostPaint( nCol
, nFirstRow
, nTab
, nCol
, nFirstRow
, nTab
, PAINT_GRID
);
755 inline void lcl_getLongVarCharEditString( String
& rString
,
756 const ScBaseCell
* pCell
, ScFieldEditEngine
& rEditEngine
)
758 rEditEngine
.SetText( *((const ScEditCell
*)pCell
)->GetData() );
759 rString
= rEditEngine
.GetText( LINEEND_CRLF
);
762 inline void lcl_getLongVarCharString( String
& rString
, ScBaseCell
* pCell
,
763 ScDocument
& rDocument
, SCCOL nCol
, SCROW nRow
, SCTAB nTab
,
764 SvNumberFormatter
& rNumFmt
)
768 rDocument
.GetNumberFormat( nCol
, nRow
, nTab
, nFormat
);
769 ScCellFormat::GetString( pCell
, nFormat
, rString
, &pColor
, rNumFmt
);
773 ULONG
ScDocShell::DBaseExport( const String
& rFullFileName
, CharSet eCharSet
, BOOL
& bHasMemo
)
775 // remove the file so the dBase driver doesn't find an invalid file
776 INetURLObject
aDeleteObj( rFullFileName
, INET_PROT_FILE
);
777 KillFile( aDeleteObj
);
779 ULONG nErr
= eERR_OK
;
782 SCCOL nFirstCol
, nLastCol
;
783 SCROW nFirstRow
, nLastRow
;
784 SCTAB nTab
= GetSaveTab();
785 aDocument
.GetDataStart( nTab
, nFirstCol
, nFirstRow
);
786 aDocument
.GetCellArea( nTab
, nLastCol
, nLastRow
);
787 if ( nFirstCol
> nLastCol
)
788 nFirstCol
= nLastCol
;
789 if ( nFirstRow
> nLastRow
)
790 nFirstRow
= nLastRow
;
791 ScProgress
aProgress( this, ScGlobal::GetRscString( STR_SAVE_DOC
),
792 nLastRow
- nFirstRow
);
793 SvNumberFormatter
* pNumFmt
= aDocument
.GetFormatTable();
795 BOOL bHasFieldNames
= TRUE
;
796 for ( SCCOL nDocCol
= nFirstCol
; nDocCol
<= nLastCol
&& bHasFieldNames
; nDocCol
++ )
797 { // nur Strings in erster Zeile => sind Feldnamen
798 if ( !aDocument
.HasStringData( nDocCol
, nFirstRow
, nTab
) )
799 bHasFieldNames
= FALSE
;
802 long nColCount
= nLastCol
- nFirstCol
+ 1;
803 uno::Sequence
<rtl::OUString
> aColNames( nColCount
);
804 uno::Sequence
<sal_Int32
> aColTypes( nColCount
);
805 uno::Sequence
<sal_Int32
> aColLengths( nColCount
);
806 uno::Sequence
<sal_Int32
> aColScales( nColCount
);
808 ScRange
aDataRange( nFirstCol
, nFirstRow
, nTab
, nLastCol
, nLastRow
, nTab
);
809 lcl_GetColumnTypes( *this, aDataRange
, bHasFieldNames
,
810 aColNames
.getArray(), aColTypes
.getArray(),
811 aColLengths
.getArray(), aColScales
.getArray(),
812 bHasMemo
, eCharSet
);
813 // also needed for exception catch
815 ScFieldEditEngine
aEditEngine( aDocument
.GetEditPool() );
821 uno::Reference
<sdbc::XDriverManager
> xDrvMan
;
822 uno::Reference
<sdbc::XConnection
> xConnection
;
823 ULONG nRet
= lcl_getDBaseConnection(xDrvMan
,xConnection
,aTabName
,rFullFileName
,eCharSet
);
824 if ( !xConnection
.is() || !xDrvMan
.is() )
826 ::utl::DisposableComponent
aConnectionHelper(xConnection
);
829 uno::Reference
< sdbc::XDriverAccess
> xAccess(xDrvMan
,uno::UNO_QUERY
);
830 uno::Reference
< sdbcx::XDataDefinitionSupplier
> xDDSup( xAccess
->getDriverByURL( xConnection
->getMetaData()->getURL() ), uno::UNO_QUERY
);
832 return SCERR_EXPORT_CONNECT
;
835 uno::Reference
<sdbcx::XTablesSupplier
> xTablesSupp
=xDDSup
->getDataDefinitionByConnection( xConnection
);
836 DBG_ASSERT( xTablesSupp
.is(), "can't get Data Definition" );
837 if (!xTablesSupp
.is()) return SCERR_EXPORT_CONNECT
;
839 uno::Reference
<container::XNameAccess
> xTables
= xTablesSupp
->getTables();
840 DBG_ASSERT( xTables
.is(), "can't get Tables" );
841 if (!xTables
.is()) return SCERR_EXPORT_CONNECT
;
843 uno::Reference
<sdbcx::XDataDescriptorFactory
> xTablesFact( xTables
, uno::UNO_QUERY
);
844 DBG_ASSERT( xTablesFact
.is(), "can't get tables factory" );
845 if (!xTablesFact
.is()) return SCERR_EXPORT_CONNECT
;
847 uno::Reference
<sdbcx::XAppend
> xTablesAppend( xTables
, uno::UNO_QUERY
);
848 DBG_ASSERT( xTablesAppend
.is(), "can't get tables XAppend" );
849 if (!xTablesAppend
.is()) return SCERR_EXPORT_CONNECT
;
851 uno::Reference
<beans::XPropertySet
> xTableDesc
= xTablesFact
->createDataDescriptor();
852 DBG_ASSERT( xTableDesc
.is(), "can't get table descriptor" );
853 if (!xTableDesc
.is()) return SCERR_EXPORT_CONNECT
;
855 aAny
<<= rtl::OUString( aTabName
);
856 xTableDesc
->setPropertyValue( rtl::OUString::createFromAscii(SC_DBPROP_NAME
), aAny
);
860 uno::Reference
<sdbcx::XColumnsSupplier
> xColumnsSupp( xTableDesc
, uno::UNO_QUERY
);
861 DBG_ASSERT( xColumnsSupp
.is(), "can't get columns supplier" );
862 if (!xColumnsSupp
.is()) return SCERR_EXPORT_CONNECT
;
864 uno::Reference
<container::XNameAccess
> xColumns
= xColumnsSupp
->getColumns();
865 DBG_ASSERT( xColumns
.is(), "can't get columns" );
866 if (!xColumns
.is()) return SCERR_EXPORT_CONNECT
;
868 uno::Reference
<sdbcx::XDataDescriptorFactory
> xColumnsFact( xColumns
, uno::UNO_QUERY
);
869 DBG_ASSERT( xColumnsFact
.is(), "can't get columns factory" );
870 if (!xColumnsFact
.is()) return SCERR_EXPORT_CONNECT
;
872 uno::Reference
<sdbcx::XAppend
> xColumnsAppend( xColumns
, uno::UNO_QUERY
);
873 DBG_ASSERT( xColumnsAppend
.is(), "can't get columns XAppend" );
874 if (!xColumnsAppend
.is()) return SCERR_EXPORT_CONNECT
;
876 const rtl::OUString
* pColNames
= aColNames
.getConstArray();
877 const sal_Int32
* pColTypes
= aColTypes
.getConstArray();
878 const sal_Int32
* pColLengths
= aColLengths
.getConstArray();
879 const sal_Int32
* pColScales
= aColScales
.getConstArray();
882 for (nCol
=0; nCol
<nColCount
; nCol
++)
884 uno::Reference
<beans::XPropertySet
> xColumnDesc
= xColumnsFact
->createDataDescriptor();
885 DBG_ASSERT( xColumnDesc
.is(), "can't get column descriptor" );
886 if (!xColumnDesc
.is()) return SCERR_EXPORT_CONNECT
;
888 aAny
<<= pColNames
[nCol
];
889 xColumnDesc
->setPropertyValue( rtl::OUString::createFromAscii(SC_DBPROP_NAME
), aAny
);
891 aAny
<<= pColTypes
[nCol
];
892 xColumnDesc
->setPropertyValue( rtl::OUString::createFromAscii(SC_DBPROP_TYPE
), aAny
);
894 aAny
<<= pColLengths
[nCol
];
895 xColumnDesc
->setPropertyValue( rtl::OUString::createFromAscii(SC_DBPROP_PRECISION
), aAny
);
897 aAny
<<= pColScales
[nCol
];
898 xColumnDesc
->setPropertyValue( rtl::OUString::createFromAscii(SC_DBPROP_SCALE
), aAny
);
900 xColumnsAppend
->appendByDescriptor( xColumnDesc
);
903 xTablesAppend
->appendByDescriptor( xTableDesc
);
905 // re-open connection
906 // xConnection = xDrvMan->getConnectionWithInfo( aConnUrl, aProps );
907 // DBG_ASSERT( xConnection.is(), "can't get Connection" );
908 // if (!xConnection.is()) return SCERR_EXPORT_CONNECT;
910 // get row set for writing
911 uno::Reference
<lang::XMultiServiceFactory
> xFactory
= comphelper::getProcessServiceFactory();
912 uno::Reference
<sdbc::XRowSet
> xRowSet( xFactory
->createInstance(
913 rtl::OUString::createFromAscii( SC_SERVICE_ROWSET
) ),
915 ::utl::DisposableComponent
aRowSetHelper(xRowSet
);
916 uno::Reference
<beans::XPropertySet
> xRowProp( xRowSet
, uno::UNO_QUERY
);
917 DBG_ASSERT( xRowProp
.is(), "can't get RowSet" );
918 if (!xRowProp
.is()) return SCERR_EXPORT_CONNECT
;
920 aAny
<<= xConnection
;
921 xRowProp
->setPropertyValue(
922 rtl::OUString::createFromAscii(SC_DBPROP_ACTIVECONNECTION
), aAny
);
924 aAny
<<= (sal_Int32
) sdb::CommandType::TABLE
;
925 xRowProp
->setPropertyValue(
926 rtl::OUString::createFromAscii(SC_DBPROP_COMMANDTYPE
), aAny
);
928 aAny
<<= rtl::OUString( aTabName
);
929 xRowProp
->setPropertyValue(
930 rtl::OUString::createFromAscii(SC_DBPROP_COMMAND
), aAny
);
936 uno::Reference
<sdbc::XResultSetUpdate
> xResultUpdate( xRowSet
, uno::UNO_QUERY
);
937 DBG_ASSERT( xResultUpdate
.is(), "can't get XResultSetUpdate" );
938 if (!xResultUpdate
.is()) return SCERR_EXPORT_CONNECT
;
940 uno::Reference
<sdbc::XRowUpdate
> xRowUpdate( xRowSet
, uno::UNO_QUERY
);
941 DBG_ASSERT( xRowUpdate
.is(), "can't get XRowUpdate" );
942 if (!xRowUpdate
.is()) return SCERR_EXPORT_CONNECT
;
944 SCROW nFirstDataRow
= ( bHasFieldNames
? nFirstRow
+ 1 : nFirstRow
);
947 for ( nDocRow
= nFirstDataRow
; nDocRow
<= nLastRow
; nDocRow
++ )
949 xResultUpdate
->moveToInsertRow();
951 for (nCol
=0; nCol
<nColCount
; nCol
++)
953 SCCOL nDocCol
= sal::static_int_cast
<SCCOL
>( nFirstCol
+ nCol
);
955 switch (pColTypes
[nCol
])
957 case sdbc::DataType::LONGVARCHAR
:
960 aDocument
.GetCell( nDocCol
, nDocRow
, nTab
, pCell
);
961 if ( pCell
&& pCell
->GetCellType() != CELLTYPE_NOTE
)
963 if ( pCell
->GetCellType() == CELLTYPE_EDIT
)
964 { // #60761# Paragraphs erhalten
965 lcl_getLongVarCharEditString( aString
,
970 lcl_getLongVarCharString( aString
, pCell
,
971 aDocument
, nDocCol
, nDocRow
, nTab
,
974 xRowUpdate
->updateString( nCol
+1, aString
);
977 xRowUpdate
->updateNull( nCol
+1 );
981 case sdbc::DataType::VARCHAR
:
982 aDocument
.GetString( nDocCol
, nDocRow
, nTab
, aString
);
983 xRowUpdate
->updateString( nCol
+1, aString
);
984 if ( nErr
== eERR_OK
&& pColLengths
[nCol
] < aString
.Len() )
985 nErr
= SCWARN_EXPORT_DATALOST
;
988 case sdbc::DataType::DATE
:
990 aDocument
.GetValue( nDocCol
, nDocRow
, nTab
, fVal
);
991 // #39274# zwischen 0 Wert und 0 kein Wert unterscheiden
992 BOOL bIsNull
= (fVal
== 0.0);
994 bIsNull
= !aDocument
.HasValueData( nDocCol
, nDocRow
, nTab
);
997 xRowUpdate
->updateNull( nCol
+1 );
998 if ( nErr
== eERR_OK
&&
999 aDocument
.HasStringData( nDocCol
, nDocRow
, nTab
) )
1000 nErr
= SCWARN_EXPORT_DATALOST
;
1004 Date aDate
= *(pNumFmt
->GetNullDate()); // tools date
1005 aDate
+= (long)fVal
; //! approxfloor?
1006 util::Date
aUnoDate( aDate
.GetDay(), aDate
.GetMonth(), aDate
.GetYear() );
1007 xRowUpdate
->updateDate( nCol
+1, aUnoDate
);
1012 case sdbc::DataType::DECIMAL
:
1013 case sdbc::DataType::BIT
:
1014 aDocument
.GetValue( nDocCol
, nDocRow
, nTab
, fVal
);
1015 if ( fVal
== 0.0 && nErr
== eERR_OK
&&
1016 aDocument
.HasStringData( nDocCol
, nDocRow
, nTab
) )
1017 nErr
= SCWARN_EXPORT_DATALOST
;
1018 if ( pColTypes
[nCol
] == sdbc::DataType::BIT
)
1019 xRowUpdate
->updateBoolean( nCol
+1, ( fVal
!= 0.0 ) );
1021 xRowUpdate
->updateDouble( nCol
+1, fVal
);
1025 DBG_ERROR( "ScDocShell::DBaseExport: unknown FieldType" );
1026 if ( nErr
== eERR_OK
)
1027 nErr
= SCWARN_EXPORT_DATALOST
;
1028 aDocument
.GetValue( nDocCol
, nDocRow
, nTab
, fVal
);
1029 xRowUpdate
->updateDouble( nCol
+1, fVal
);
1033 xResultUpdate
->insertRow();
1035 //! error handling and recovery of old
1036 //! ScDocShell::SbaSdbExport is still missing!
1038 if ( !aProgress
.SetStateOnPercent( nDocRow
- nFirstRow
) )
1040 nErr
= SCERR_EXPORT_DATA
;
1045 comphelper::disposeComponent( xRowSet
);
1046 comphelper::disposeComponent( xConnection
);
1048 catch ( sdbc::SQLException
& aException
)
1050 sal_Int32 nError
= aException
.ErrorCode
;
1051 #if OSL_DEBUG_LEVEL > 1
1052 fprintf( stderr
, "ScDocShell::DBaseExport: SQLException ErrorCode: %d, SQLState: %s, Message: %s\n",
1053 (int)nError
, OUStringToOString( aException
.SQLState
,
1054 RTL_TEXTENCODING_UTF8
).getStr(), OUStringToOString(
1055 aException
.Message
, RTL_TEXTENCODING_UTF8
).getStr());
1057 if (nError
== 22018 || nError
== 22001)
1059 // SQL error 22018: Character not in target encoding.
1060 // SQL error 22001: String length exceeds field width (after encoding).
1061 bool bEncErr
= (nError
== 22018);
1062 bool bIsOctetTextEncoding
= rtl_isOctetTextEncoding( eCharSet
);
1063 DBG_ASSERT( !bEncErr
|| bIsOctetTextEncoding
, "ScDocShell::DBaseExport: encoding error and not an octect textencoding");
1064 SCCOL nDocCol
= nFirstCol
;
1065 const sal_Int32
* pColTypes
= aColTypes
.getConstArray();
1066 const sal_Int32
* pColLengths
= aColLengths
.getConstArray();
1067 ScHorizontalCellIterator
aIter( &aDocument
, nTab
, nFirstCol
,
1068 nDocRow
, nLastCol
, nDocRow
);
1069 ScBaseCell
* pCell
= NULL
;
1071 while (bTest
&& ((pCell
= aIter
.GetNext( nDocCol
, nDocRow
)) != NULL
))
1073 SCCOL nCol
= nDocCol
- nFirstCol
;
1074 switch (pColTypes
[nCol
])
1076 case sdbc::DataType::LONGVARCHAR
:
1078 if ( pCell
->GetCellType() != CELLTYPE_NOTE
)
1080 if ( pCell
->GetCellType() == CELLTYPE_EDIT
)
1081 lcl_getLongVarCharEditString( aString
,
1082 pCell
, aEditEngine
);
1084 lcl_getLongVarCharString( aString
,
1085 pCell
, aDocument
, nDocCol
,
1086 nDocRow
, nTab
, *pNumFmt
);
1091 case sdbc::DataType::VARCHAR
:
1092 aDocument
.GetString( nDocCol
, nDocRow
, nTab
, aString
);
1095 // NOTE: length of DECIMAL fields doesn't need to be
1096 // checked here, the database driver adjusts the field
1097 // width accordingly.
1105 if (bIsOctetTextEncoding
)
1107 rtl::OUString
aOUString( aString
);
1108 rtl::OString aOString
;
1109 if (!aOUString
.convertToString( &aOString
, eCharSet
,
1110 RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
|
1111 RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR
))
1116 nLen
= aOString
.getLength();
1117 #if OSL_DEBUG_LEVEL > 1
1119 fprintf( stderr
, "ScDocShell::DBaseExport encoding error, string with default replacements: ``%s''\n",
1120 OUStringToOString( aOUString
, eCharSet
).getStr());
1124 nLen
= aString
.Len() * sizeof(sal_Unicode
);
1126 pColTypes
[nCol
] != sdbc::DataType::LONGVARCHAR
&&
1127 pColLengths
[nCol
] < nLen
)
1130 #if OSL_DEBUG_LEVEL > 1
1131 fprintf( stderr
, "ScDocShell::DBaseExport: field width: %d, encoded length: %d\n",
1132 (int)pColLengths
[nCol
], (int)nLen
);
1139 String
sPosition( ScAddress( nDocCol
, nDocRow
, nTab
).GetColRowString());
1140 String
sEncoding( SvxTextEncodingTable().GetTextString( eCharSet
));
1141 nErr
= *new TwoStringErrorInfo( (bEncErr
? SCERR_EXPORT_ENCODING
:
1142 SCERR_EXPORT_FIELDWIDTH
), sPosition
, sEncoding
,
1143 ERRCODE_BUTTON_OK
| ERRCODE_MSG_ERROR
);
1145 else if ( aException
.Message
.getLength() )
1146 nErr
= *new StringErrorInfo( (SCERR_EXPORT_SQLEXCEPTION
), aException
.Message
, ERRCODE_BUTTON_OK
| ERRCODE_MSG_ERROR
);
1148 nErr
= SCERR_EXPORT_DATA
;
1150 catch ( uno::Exception
& )
1152 DBG_ERROR("Unexpected exception in database");
1153 nErr
= ERRCODE_IO_GENERAL
;