xref: /aoo41x/main/sc/source/ui/docshell/dbdocimp.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sc.hxx"
30 
31 
32 
33 // INCLUDE ---------------------------------------------------------
34 
35 #include <comphelper/processfactory.hxx>
36 #include <comphelper/types.hxx>
37 #include <vcl/msgbox.hxx>
38 #include <tools/debug.hxx>
39 #include <svx/dataaccessdescriptor.hxx>
40 #include <sfx2/viewfrm.hxx>
41 
42 #include <com/sun/star/sdb/CommandType.hpp>
43 #include <com/sun/star/sdb/XCompletedExecution.hpp>
44 #include <com/sun/star/sdbc/XRow.hpp>
45 #include <com/sun/star/sdbc/XRowSet.hpp>
46 #include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
47 #include <com/sun/star/sdbcx/XRowLocate.hpp>
48 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
49 #include <com/sun/star/beans/XPropertySet.hpp>
50 #include <com/sun/star/frame/XDispatchProvider.hpp>
51 #include <com/sun/star/frame/FrameSearchFlag.hpp>
52 #include <com/sun/star/view/XSelectionSupplier.hpp>
53 
54 
55 #include "dbdocfun.hxx"
56 #include "docsh.hxx"
57 #include "globstr.hrc"
58 #include "scerrors.hxx"
59 #include "dbcolect.hxx"
60 #include "markdata.hxx"
61 #include "undodat.hxx"
62 #include "progress.hxx"
63 #include "patattr.hxx"
64 #include "docpool.hxx"
65 #include "attrib.hxx"
66 #include "dbdocutl.hxx"
67 #include "editable.hxx"
68 #include "hints.hxx"
69 #include "miscuno.hxx"
70 
71 using namespace com::sun::star;
72 
73 #define SC_SERVICE_ROWSET			"com.sun.star.sdb.RowSet"
74 #define SC_SERVICE_INTHANDLER		"com.sun.star.task.InteractionHandler"
75 
76 //!	move to a header file?
77 #define SC_DBPROP_DATASOURCENAME	"DataSourceName"
78 #define SC_DBPROP_COMMAND			"Command"
79 #define SC_DBPROP_COMMANDTYPE		"CommandType"
80 #define SC_DBPROP_SELECTION			"Selection"
81 #define SC_DBPROP_CURSOR			"Cursor"
82 
83 // static
84 void ScDBDocFunc::ShowInBeamer( const ScImportParam& rParam, SfxViewFrame* pFrame )
85 {
86 	//	called after opening the database beamer
87 
88 	if ( !pFrame || !rParam.bImport )
89 		return;
90 
91 	uno::Reference<frame::XFrame> xFrame = pFrame->GetFrame().GetFrameInterface();
92 	uno::Reference<frame::XDispatchProvider> xDP(xFrame, uno::UNO_QUERY);
93 
94 	uno::Reference<frame::XFrame> xBeamerFrame = xFrame->findFrame(
95 										rtl::OUString::createFromAscii("_beamer"),
96 										frame::FrameSearchFlag::CHILDREN);
97 	if (xBeamerFrame.is())
98 	{
99 		uno::Reference<frame::XController> xController = xBeamerFrame->getController();
100 		uno::Reference<view::XSelectionSupplier> xControllerSelection(xController, uno::UNO_QUERY);
101 		if (xControllerSelection.is())
102 		{
103 			sal_Int32 nType = rParam.bSql ? sdb::CommandType::COMMAND :
104 						( (rParam.nType == ScDbQuery) ? sdb::CommandType::QUERY :
105 														sdb::CommandType::TABLE );
106 
107             ::svx::ODataAccessDescriptor aSelection;
108             aSelection.setDataSource(rtl::OUString( rParam.aDBName ));
109             aSelection[svx::daCommand]      <<= rtl::OUString( rParam.aStatement );
110             aSelection[svx::daCommandType]  <<= nType;
111 
112 			xControllerSelection->select(uno::makeAny(aSelection.createPropertyValueSequence()));
113 		}
114 		else
115 		{
116 			DBG_ERROR("no selection supplier in the beamer!");
117 		}
118 	}
119 }
120 
121 // -----------------------------------------------------------------
122 
123 sal_Bool ScDBDocFunc::DoImportUno( const ScAddress& rPos,
124 								const uno::Sequence<beans::PropertyValue>& aArgs )
125 {
126     svx::ODataAccessDescriptor aDesc( aArgs );      // includes selection and result set
127 
128     //  create database range
129 	ScDBData* pDBData = rDocShell.GetDBData( ScRange(rPos), SC_DB_IMPORT, SC_DBSEL_KEEP );
130 	DBG_ASSERT(pDBData, "can't create DB data");
131 	String sTarget = pDBData->GetName();
132 
133     UpdateImport( sTarget, aDesc );
134 
135 	return sal_True;
136 }
137 
138 // -----------------------------------------------------------------
139 
140 sal_Bool ScDBDocFunc::DoImport( SCTAB nTab, const ScImportParam& rParam,
141         const svx::ODataAccessDescriptor* pDescriptor, sal_Bool bRecord, sal_Bool bAddrInsert )
142 {
143 	ScDocument* pDoc = rDocShell.GetDocument();
144 
145 	if (bRecord && !pDoc->IsUndoEnabled())
146 		bRecord = sal_False;
147 
148 	ScDBData* pDBData = 0;
149 	if ( !bAddrInsert )
150 	{
151 		pDBData = pDoc->GetDBAtArea( nTab, rParam.nCol1, rParam.nRow1,
152 											rParam.nCol2, rParam.nRow2 );
153 		if (!pDBData)
154 		{
155 			DBG_ERROR( "DoImport: no DBData" );
156 			return sal_False;
157 		}
158 	}
159 
160 	Window* pWaitWin = rDocShell.GetActiveDialogParent();
161 	if (pWaitWin)
162 		pWaitWin->EnterWait();
163 	ScDocShellModificator aModificator( rDocShell );
164 
165 	sal_Bool bSuccess = sal_False;
166 	sal_Bool bApi = sal_False;						//! pass as argument
167 	sal_Bool bTruncated = sal_False;				// for warning
168 	sal_uInt16 nErrStringId = 0;
169 	String aErrorMessage;
170 
171 	SCCOL nCol = rParam.nCol1;
172 	SCROW nRow = rParam.nRow1;
173 	SCCOL nEndCol = nCol;					// end of resulting database area
174 	SCROW nEndRow = nRow;
175 	long i;
176 
177 	sal_Bool bDoSelection = sal_False;
178 	sal_Bool bRealSelection = sal_False;			// sal_True if not everything is selected
179     sal_Bool bBookmarkSelection = sal_False;
180     sal_Int32 nListPos = 0;
181     sal_Int32 nRowsRead = 0;
182     sal_Int32 nListCount = 0;
183 
184     uno::Sequence<uno::Any> aSelection;
185     if ( pDescriptor && pDescriptor->has(svx::daSelection) )
186     {
187         (*pDescriptor)[svx::daSelection] >>= aSelection;
188         nListCount = aSelection.getLength();
189         if ( nListCount > 0 )
190         {
191             bDoSelection = sal_True;
192             if ( pDescriptor->has(svx::daBookmarkSelection) )
193                 bBookmarkSelection = ScUnoHelpFunctions::GetBoolFromAny( (*pDescriptor)[svx::daBookmarkSelection] );
194             if ( bBookmarkSelection )
195             {
196                 // From bookmarks, there's no way to detect if all records are selected.
197                 // Rely on base to pass no selection in that case.
198                 bRealSelection = sal_True;
199             }
200         }
201     }
202 
203     uno::Reference<sdbc::XResultSet> xResultSet;
204     if ( pDescriptor && pDescriptor->has(svx::daCursor) )
205         xResultSet.set((*pDescriptor)[svx::daCursor], uno::UNO_QUERY);
206 
207 	// ImportDoc - also used for Redo
208 	ScDocument* pImportDoc = new ScDocument( SCDOCMODE_UNDO );
209 	pImportDoc->InitUndo( pDoc, nTab, nTab );
210 	ScColumn::bDoubleAlloc = sal_True;
211 
212 	//
213 	//	get data from database into import document
214 	//
215 
216 	try
217 	{
218 		//	progress bar
219 		//	only text (title is still needed, for the cancel button)
220 		ScProgress aProgress( &rDocShell, ScGlobal::GetRscString(STR_UNDO_IMPORTDATA), 0 );
221 		sal_uInt16 nInserted = 0;
222 
223         uno::Reference<sdbc::XRowSet> xRowSet = uno::Reference<sdbc::XRowSet>(
224                 xResultSet, uno::UNO_QUERY );
225         sal_Bool bDispose = sal_False;
226         if ( !xRowSet.is() )
227         {
228             bDispose = sal_True;
229             xRowSet = uno::Reference<sdbc::XRowSet>(
230                     comphelper::getProcessServiceFactory()->createInstance(
231                         rtl::OUString::createFromAscii( SC_SERVICE_ROWSET ) ),
232                     uno::UNO_QUERY);
233             uno::Reference<beans::XPropertySet> xRowProp( xRowSet, uno::UNO_QUERY );
234             DBG_ASSERT( xRowProp.is(), "can't get RowSet" );
235             if ( xRowProp.is() )
236             {
237                 //
238                 //	set source parameters
239                 //
240 
241                 sal_Int32 nType = rParam.bSql ? sdb::CommandType::COMMAND :
242                             ( (rParam.nType == ScDbQuery) ? sdb::CommandType::QUERY :
243                                                             sdb::CommandType::TABLE );
244                 uno::Any aAny;
245 
246                 aAny <<= rtl::OUString( rParam.aDBName );
247                 xRowProp->setPropertyValue(
248                             rtl::OUString::createFromAscii(SC_DBPROP_DATASOURCENAME), aAny );
249 
250                 aAny <<= rtl::OUString( rParam.aStatement );
251                 xRowProp->setPropertyValue(
252                             rtl::OUString::createFromAscii(SC_DBPROP_COMMAND), aAny );
253 
254                 aAny <<= nType;
255                 xRowProp->setPropertyValue(
256                             rtl::OUString::createFromAscii(SC_DBPROP_COMMANDTYPE), aAny );
257 
258                 uno::Reference<sdb::XCompletedExecution> xExecute( xRowSet, uno::UNO_QUERY );
259                 if ( xExecute.is() )
260                 {
261                     uno::Reference<task::XInteractionHandler> xHandler(
262                             comphelper::getProcessServiceFactory()->createInstance(
263                                 rtl::OUString::createFromAscii( SC_SERVICE_INTHANDLER ) ),
264                             uno::UNO_QUERY);
265                     xExecute->executeWithCompletion( xHandler );
266                 }
267                 else
268                     xRowSet->execute();
269             }
270         }
271         if ( xRowSet.is() )
272         {
273 			//
274 			//	get column descriptions
275 			//
276 
277 			long nColCount = 0;
278 			uno::Reference<sdbc::XResultSetMetaData> xMeta;
279 			uno::Reference<sdbc::XResultSetMetaDataSupplier> xMetaSupp( xRowSet, uno::UNO_QUERY );
280 			if ( xMetaSupp.is() )
281 				xMeta = xMetaSupp->getMetaData();
282 			if ( xMeta.is() )
283 				nColCount = xMeta->getColumnCount();	// this is the number of real columns
284 
285 			if ( rParam.nCol1 + nColCount - 1 > MAXCOL )
286 			{
287 				nColCount = 0;
288 				//!	error message
289 			}
290 
291             uno::Reference<sdbcx::XRowLocate> xLocate;
292             if ( bBookmarkSelection )
293             {
294                 xLocate.set( xRowSet, uno::UNO_QUERY );
295                 if ( !xLocate.is() )
296                 {
297                     DBG_ERRORFILE("can't get XRowLocate");
298                     bDoSelection = bRealSelection = bBookmarkSelection = sal_False;
299                 }
300             }
301 
302 			uno::Reference<sdbc::XRow> xRow( xRowSet, uno::UNO_QUERY );
303 			if ( nColCount > 0 && xRow.is() )
304 			{
305 				nEndCol = (SCCOL)( rParam.nCol1 + nColCount - 1 );
306 
307 				uno::Sequence<sal_Int32> aColTypes( nColCount );	// column types
308 				uno::Sequence<sal_Bool> aColCurr( nColCount );		// currency flag is not in types
309 				sal_Int32* pTypeArr = aColTypes.getArray();
310 				sal_Bool* pCurrArr = aColCurr.getArray();
311 				for (i=0; i<nColCount; i++)
312 				{
313 					pTypeArr[i] = xMeta->getColumnType( i+1 );
314 					pCurrArr[i] = xMeta->isCurrency( i+1 );
315 				}
316 
317 				if ( !bAddrInsert )					// read column names
318 				{
319 					nCol = rParam.nCol1;
320 					for (i=0; i<nColCount; i++)
321 					{
322 						pImportDoc->SetString( nCol, nRow, nTab,
323 												xMeta->getColumnLabel( i+1 ) );
324 						++nCol;
325 					}
326 					++nRow;
327 				}
328 
329 				sal_Bool bEnd = sal_False;
330 				if ( !bDoSelection )
331 					xRowSet->beforeFirst();
332 				while ( !bEnd )
333 				{
334 					//	skip rows that are not selected
335 					if ( !bDoSelection )
336 					{
337                         if ( (bEnd = !xRowSet->next()) == sal_False )
338 							++nRowsRead;
339 					}
340 					else
341 					{
342 						if (nListPos < nListCount)
343 						{
344                             if ( bBookmarkSelection )
345                             {
346                                 bEnd = !xLocate->moveToBookmark(aSelection[nListPos]);
347                             }
348                             else    // use record numbers
349                             {
350                                 sal_Int32 nNextRow = 0;
351                                 aSelection[nListPos] >>= nNextRow;
352                                 if ( nRowsRead+1 < nNextRow )
353                                     bRealSelection = sal_True;
354                                 bEnd = !xRowSet->absolute(nRowsRead = nNextRow);
355                             }
356                             ++nListPos;
357 						}
358 						else
359 						{
360                             if ( !bBookmarkSelection && xRowSet->next() )
361                                 bRealSelection = sal_True;                      // more data available but not used
362                             bEnd = sal_True;
363 						}
364 					}
365 
366 					if ( !bEnd )
367 					{
368 						if ( ValidRow(nRow) )
369 						{
370 							nCol = rParam.nCol1;
371 							for (i=0; i<nColCount; i++)
372 							{
373 								ScDatabaseDocUtil::PutData( pImportDoc, nCol, nRow, nTab,
374 												xRow, i+1, pTypeArr[i], pCurrArr[i] );
375 								++nCol;
376 							}
377 							nEndRow = nRow;
378 							++nRow;
379 
380 							//	progress bar
381 
382 							++nInserted;
383 							if (!(nInserted & 15))
384 							{
385 								String aPict = ScGlobal::GetRscString( STR_PROGRESS_IMPORT );
386 								String aText = aPict.GetToken(0,'#');
387 								aText += String::CreateFromInt32( nInserted );
388 								aText += aPict.GetToken(1,'#');
389 
390 								if (!aProgress.SetStateText( 0, aText ))	// stopped by user?
391 								{
392 									bEnd = sal_True;
393 									bSuccess = sal_False;
394 									nErrStringId = STR_DATABASE_ABORTED;
395 								}
396 							}
397 						}
398 						else		// past the end of the spreadsheet
399 						{
400 							bEnd = sal_True;			// don't continue
401 							bTruncated = sal_True;		// warning flag
402 						}
403 					}
404 				}
405 
406 				bSuccess = sal_True;
407 			}
408 
409             if ( bDispose )
410                 ::comphelper::disposeComponent( xRowSet );
411 		}
412 	}
413 	catch ( sdbc::SQLException& rError )
414 	{
415 		aErrorMessage = rError.Message;
416 	}
417 	catch ( uno::Exception& )
418 	{
419 		DBG_ERROR("Unexpected exception in database");
420 	}
421 
422 	ScColumn::bDoubleAlloc = sal_False;
423 	pImportDoc->DoColResize( nTab, rParam.nCol1,nEndCol, 0 );
424 
425 	//
426 	//	test for cell protection
427 	//
428 
429 	sal_Bool bKeepFormat = !bAddrInsert && pDBData->IsKeepFmt();
430 	sal_Bool bMoveCells = !bAddrInsert && pDBData->IsDoSize();
431 	SCCOL nFormulaCols = 0;	// columns to be filled with formulas
432 	if (bMoveCells && nEndCol == rParam.nCol2)
433 	{
434 		//	if column count changes, formulas would become invalid anyway
435 		//	-> only set nFormulaCols for unchanged column count
436 
437 		SCCOL nTestCol = rParam.nCol2 + 1;		// right of the data
438 		SCROW nTestRow = rParam.nRow1 + 1;		// below the title row
439 		while ( nTestCol <= MAXCOL &&
440 				pDoc->GetCellType(ScAddress( nTestCol, nTestRow, nTab )) == CELLTYPE_FORMULA )
441 			++nTestCol, ++nFormulaCols;
442 	}
443 
444 	if (bSuccess)
445 	{
446 		//	old and new range editable?
447 		ScEditableTester aTester;
448 		aTester.TestBlock( pDoc, nTab, rParam.nCol1,rParam.nRow1,rParam.nCol2,rParam.nRow2 );
449 		aTester.TestBlock( pDoc, nTab, rParam.nCol1,rParam.nRow1,nEndCol,nEndRow );
450 		if ( !aTester.IsEditable() )
451 		{
452 			nErrStringId = aTester.GetMessageId();
453 			bSuccess = sal_False;
454 		}
455 		else if ( pDoc->GetChangeTrack() != NULL )
456 		{
457 			nErrStringId = STR_PROTECTIONERR;
458 			bSuccess = sal_False;
459 		}
460 	}
461 
462 	if ( bSuccess && bMoveCells )
463 	{
464 		ScRange aOld( rParam.nCol1, rParam.nRow1, nTab,
465 						rParam.nCol2+nFormulaCols, rParam.nRow2, nTab );
466 		ScRange aNew( rParam.nCol1, rParam.nRow1, nTab,
467 						nEndCol+nFormulaCols, nEndRow, nTab );
468 		if (!pDoc->CanFitBlock( aOld, aNew ))
469 		{
470 			nErrStringId = STR_MSSG_DOSUBTOTALS_2;		// can't insert cells
471 			bSuccess = sal_False;
472 		}
473 	}
474 
475 	//
476 	//	copy data from import doc into real document
477 	//
478 
479 	if ( bSuccess )
480 	{
481 		if (bKeepFormat)
482 		{
483 			//	keep formatting of title and first data row from the document
484 			//	CopyToDocument also copies styles, Apply... needs separate calls
485 
486 			SCCOL nMinEndCol = Min( rParam.nCol2, nEndCol );	// not too much
487             nMinEndCol = sal::static_int_cast<SCCOL>( nMinEndCol + nFormulaCols );  // only if column count unchanged
488 			pImportDoc->DeleteAreaTab( 0,0, MAXCOL,MAXROW, nTab, IDF_ATTRIB );
489 			pDoc->CopyToDocument( rParam.nCol1, rParam.nRow1, nTab,
490 									nMinEndCol, rParam.nRow1, nTab,
491 									IDF_ATTRIB, sal_False, pImportDoc );
492 
493 			SCROW nDataStartRow = rParam.nRow1+1;
494 			for (SCCOL nCopyCol=rParam.nCol1; nCopyCol<=nMinEndCol; nCopyCol++)
495 			{
496 				const ScPatternAttr* pSrcPattern = pDoc->GetPattern(
497 													nCopyCol, nDataStartRow, nTab );
498 				pImportDoc->ApplyPatternAreaTab( nCopyCol, nDataStartRow, nCopyCol, nEndRow,
499 													nTab, *pSrcPattern );
500 				const ScStyleSheet* pStyle = pSrcPattern->GetStyleSheet();
501 				if (pStyle)
502 					pImportDoc->ApplyStyleAreaTab( nCopyCol, nDataStartRow, nCopyCol, nEndRow,
503 													nTab, *pStyle );
504 			}
505 		}
506 
507 		//	don't set cell protection attribute if table is protected
508 		if (pDoc->IsTabProtected(nTab))
509 		{
510 			ScPatternAttr aPattern(pImportDoc->GetPool());
511 			aPattern.GetItemSet().Put( ScProtectionAttr( sal_False,sal_False,sal_False,sal_False ) );
512 			pImportDoc->ApplyPatternAreaTab( 0,0,MAXCOL,MAXROW, nTab, aPattern );
513 		}
514 
515 		//
516 		//	copy old data for undo
517 		//
518 
519 		SCCOL nUndoEndCol = Max( nEndCol, rParam.nCol2 );		// rParam = old end
520 		SCROW nUndoEndRow = Max( nEndRow, rParam.nRow2 );
521 
522 		ScDocument* pUndoDoc = NULL;
523 		ScDBData* pUndoDBData = NULL;
524 		if ( bRecord )
525 		{
526 			pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
527 			pUndoDoc->InitUndo( pDoc, nTab, nTab );
528 
529 			if ( !bAddrInsert )
530 				pUndoDBData = new ScDBData( *pDBData );
531 		}
532 
533 		ScMarkData aNewMark;
534 		aNewMark.SelectOneTable( nTab );
535 
536 		if (bRecord)
537 		{
538             // do not touch notes (ScUndoImportData does not support drawing undo)
539             sal_uInt16 nCopyFlags = IDF_ALL & ~IDF_NOTE;
540 
541 			//	nFormulaCols is set only if column count is unchanged
542 			pDoc->CopyToDocument( rParam.nCol1, rParam.nRow1, nTab,
543 									nEndCol+nFormulaCols, nEndRow, nTab,
544                                     nCopyFlags, sal_False, pUndoDoc );
545 			if ( rParam.nCol2 > nEndCol )
546 				pDoc->CopyToDocument( nEndCol+1, rParam.nRow1, nTab,
547 										nUndoEndCol, nUndoEndRow, nTab,
548                                         nCopyFlags, sal_False, pUndoDoc );
549 			if ( rParam.nRow2 > nEndRow )
550 				pDoc->CopyToDocument( rParam.nCol1, nEndRow+1, nTab,
551 										nUndoEndCol+nFormulaCols, nUndoEndRow, nTab,
552                                         nCopyFlags, sal_False, pUndoDoc );
553 		}
554 
555 		//
556 		//	move new data
557 		//
558 
559 		if (bMoveCells)
560 		{
561 			//	clear only the range without the formulas,
562 			//	so the formula title and first row are preserved
563 
564 			ScRange aDelRange( rParam.nCol1, rParam.nRow1, nTab,
565 								rParam.nCol2, rParam.nRow2, nTab );
566             pDoc->DeleteAreaTab( aDelRange, IDF_ALL & ~IDF_NOTE );  // ohne die Formeln
567 
568 			ScRange aOld( rParam.nCol1, rParam.nRow1, nTab,
569 							rParam.nCol2+nFormulaCols, rParam.nRow2, nTab );
570 			ScRange aNew( rParam.nCol1, rParam.nRow1, nTab,
571 							nEndCol+nFormulaCols, nEndRow, nTab );
572 			pDoc->FitBlock( aOld, aNew, sal_False );		// Formeln nicht loeschen
573 		}
574 		else if ( nEndCol < rParam.nCol2 )		// DeleteArea calls PutInOrder
575 			pDoc->DeleteArea( nEndCol+1, rParam.nRow1, rParam.nCol2, rParam.nRow2,
576                                 aNewMark, IDF_CONTENTS & ~IDF_NOTE );
577 
578 		//	CopyToDocument doesn't remove contents
579         pDoc->DeleteAreaTab( rParam.nCol1, rParam.nRow1, nEndCol, nEndRow, nTab, IDF_CONTENTS & ~IDF_NOTE );
580 
581 		//	#41216# remove each column from ImportDoc after copying to reduce memory usage
582 		sal_Bool bOldAutoCalc = pDoc->GetAutoCalc();
583 		pDoc->SetAutoCalc( sal_False );				// outside of the loop
584 		for (SCCOL nCopyCol = rParam.nCol1; nCopyCol <= nEndCol; nCopyCol++)
585 		{
586 			pImportDoc->CopyToDocument( nCopyCol, rParam.nRow1, nTab, nCopyCol, nEndRow, nTab,
587 										IDF_ALL, sal_False, pDoc );
588 			pImportDoc->DeleteAreaTab( nCopyCol, rParam.nRow1, nCopyCol, nEndRow, nTab, IDF_CONTENTS );
589 			pImportDoc->DoColResize( nTab, nCopyCol, nCopyCol, 0 );
590 		}
591 		pDoc->SetAutoCalc( bOldAutoCalc );
592 
593 		if (nFormulaCols > 0)				// copy formulas
594 		{
595 			if (bKeepFormat)			// formats for formulas
596 				pImportDoc->CopyToDocument( nEndCol+1, rParam.nRow1, nTab,
597 											nEndCol+nFormulaCols, nEndRow, nTab,
598 											IDF_ATTRIB, sal_False, pDoc );
599 			// fill formulas
600 			ScMarkData aMark;
601 			aMark.SelectOneTable(nTab);
602 			pDoc->Fill( nEndCol+1, rParam.nRow1+1, nEndCol+nFormulaCols, rParam.nRow1+1,
603 							aMark, nEndRow-rParam.nRow1-1, FILL_TO_BOTTOM, FILL_SIMPLE );
604 		}
605 
606 		//	if new range is smaller, clear old contents
607 
608 		if (!bMoveCells)		// move has happened above
609 		{
610 			if ( rParam.nCol2 > nEndCol )
611 				pDoc->DeleteArea( nEndCol+1, rParam.nRow1, rParam.nCol2, rParam.nRow2,
612 									aNewMark, IDF_CONTENTS );
613 			if ( rParam.nRow2 > nEndRow )
614 				pDoc->DeleteArea( rParam.nCol1, nEndRow+1, rParam.nCol2, rParam.nRow2,
615 									aNewMark, IDF_CONTENTS );
616 		}
617 
618 		if( !bAddrInsert )		// update database range
619 		{
620 			pDBData->SetImportParam( rParam );
621 			pDBData->SetHeader( sal_True );
622 			pDBData->SetByRow( sal_True );
623 			pDBData->SetArea( nTab, rParam.nCol1,rParam.nRow1, nEndCol,nEndRow );
624 			pDBData->SetImportSelection( bRealSelection );
625 			pDoc->CompileDBFormula();
626 		}
627 
628 		if (bRecord)
629 		{
630 			ScDocument* pRedoDoc = pImportDoc;
631 			pImportDoc = NULL;
632 
633 			if (nFormulaCols > 0)					// include filled formulas for redo
634 				pDoc->CopyToDocument( rParam.nCol1, rParam.nRow1, nTab,
635 										nEndCol+nFormulaCols, nEndRow, nTab,
636                                         IDF_ALL & ~IDF_NOTE, sal_False, pRedoDoc );
637 
638 			ScDBData* pRedoDBData = pDBData ? new ScDBData( *pDBData ) : NULL;
639 
640 			rDocShell.GetUndoManager()->AddUndoAction(
641 				new ScUndoImportData( &rDocShell, nTab,
642 										rParam, nUndoEndCol, nUndoEndRow,
643 										nFormulaCols,
644 										pUndoDoc, pRedoDoc, pUndoDBData, pRedoDBData ) );
645 		}
646 
647 		pDoc->SetDirty();
648 		rDocShell.PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID );
649 		aModificator.SetDocumentModified();
650 
651 	    ScDBRangeRefreshedHint aHint( rParam );
652 	    pDoc->BroadcastUno( aHint );
653 
654 		if (pWaitWin)
655 			pWaitWin->LeaveWait();
656 
657 		if ( bTruncated && !bApi )			// show warning
658 			ErrorHandler::HandleError(SCWARN_IMPORT_RANGE_OVERFLOW);
659 	}
660 	else if ( !bApi )
661 	{
662 		if (pWaitWin)
663 			pWaitWin->LeaveWait();
664 
665 		if (!aErrorMessage.Len())
666 		{
667 			if (!nErrStringId)
668 				nErrStringId = STR_MSSG_IMPORTDATA_0;
669 			aErrorMessage = ScGlobal::GetRscString( nErrStringId );
670 		}
671 		InfoBox aInfoBox( rDocShell.GetActiveDialogParent(), aErrorMessage );
672 		aInfoBox.Execute();
673 	}
674 
675 	delete pImportDoc;
676 
677 	return bSuccess;
678 }
679 
680 
681 
682 
683