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