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