/**************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"



// INCLUDE ---------------------------------------------------------

#include <comphelper/processfactory.hxx>
#include <comphelper/types.hxx>
#include <vcl/msgbox.hxx>
#include <tools/debug.hxx>
#include <svx/dataaccessdescriptor.hxx>
#include <sfx2/viewfrm.hxx>

#include <com/sun/star/sdb/CommandType.hpp>
#include <com/sun/star/sdb/XCompletedExecution.hpp>
#include <com/sun/star/sdbc/XRow.hpp>
#include <com/sun/star/sdbc/XRowSet.hpp>
#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
#include <com/sun/star/sdbcx/XRowLocate.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/frame/XDispatchProvider.hpp>
#include <com/sun/star/frame/FrameSearchFlag.hpp>
#include <com/sun/star/view/XSelectionSupplier.hpp>


#include "dbdocfun.hxx"
#include "docsh.hxx"
#include "globstr.hrc"
#include "scerrors.hxx"
#include "dbcolect.hxx"
#include "markdata.hxx"
#include "undodat.hxx"
#include "progress.hxx"
#include "patattr.hxx"
#include "docpool.hxx"
#include "attrib.hxx"
#include "dbdocutl.hxx"
#include "editable.hxx"
#include "hints.hxx"
#include "miscuno.hxx"

using namespace com::sun::star;

#define SC_SERVICE_ROWSET			"com.sun.star.sdb.RowSet"
#define SC_SERVICE_INTHANDLER		"com.sun.star.task.InteractionHandler"

//!	move to a header file?
#define SC_DBPROP_DATASOURCENAME	"DataSourceName"
#define SC_DBPROP_COMMAND			"Command"
#define SC_DBPROP_COMMANDTYPE		"CommandType"
#define SC_DBPROP_SELECTION			"Selection"
#define SC_DBPROP_CURSOR			"Cursor"

// static
void ScDBDocFunc::ShowInBeamer( const ScImportParam& rParam, SfxViewFrame* pFrame )
{
	//	called after opening the database beamer

	if ( !pFrame || !rParam.bImport )
		return;

	uno::Reference<frame::XFrame> xFrame = pFrame->GetFrame().GetFrameInterface();
	uno::Reference<frame::XDispatchProvider> xDP(xFrame, uno::UNO_QUERY);

	uno::Reference<frame::XFrame> xBeamerFrame = xFrame->findFrame(
										rtl::OUString::createFromAscii("_beamer"),
										frame::FrameSearchFlag::CHILDREN);
	if (xBeamerFrame.is())
	{
		uno::Reference<frame::XController> xController = xBeamerFrame->getController();
		uno::Reference<view::XSelectionSupplier> xControllerSelection(xController, uno::UNO_QUERY);
		if (xControllerSelection.is())
		{
			sal_Int32 nType = rParam.bSql ? sdb::CommandType::COMMAND :
						( (rParam.nType == ScDbQuery) ? sdb::CommandType::QUERY :
														sdb::CommandType::TABLE );

            ::svx::ODataAccessDescriptor aSelection;
            aSelection.setDataSource(rtl::OUString( rParam.aDBName ));
            aSelection[svx::daCommand]      <<= rtl::OUString( rParam.aStatement );
            aSelection[svx::daCommandType]  <<= nType;

			xControllerSelection->select(uno::makeAny(aSelection.createPropertyValueSequence()));
		}
		else
		{
			DBG_ERROR("no selection supplier in the beamer!");
		}
	}
}

// -----------------------------------------------------------------

sal_Bool ScDBDocFunc::DoImportUno( const ScAddress& rPos,
								const uno::Sequence<beans::PropertyValue>& aArgs )
{
    svx::ODataAccessDescriptor aDesc( aArgs );      // includes selection and result set

    //  create database range
	ScDBData* pDBData = rDocShell.GetDBData( ScRange(rPos), SC_DB_IMPORT, SC_DBSEL_KEEP );
	DBG_ASSERT(pDBData, "can't create DB data");
	String sTarget = pDBData->GetName();

    UpdateImport( sTarget, aDesc );

	return sal_True;
}

// -----------------------------------------------------------------

sal_Bool ScDBDocFunc::DoImport( SCTAB nTab, const ScImportParam& rParam,
        const svx::ODataAccessDescriptor* pDescriptor, sal_Bool bRecord, sal_Bool bAddrInsert )
{
	ScDocument* pDoc = rDocShell.GetDocument();

	if (bRecord && !pDoc->IsUndoEnabled())
		bRecord = sal_False;

	ScDBData* pDBData = 0;
	if ( !bAddrInsert )
	{
		pDBData = pDoc->GetDBAtArea( nTab, rParam.nCol1, rParam.nRow1,
											rParam.nCol2, rParam.nRow2 );
		if (!pDBData)
		{
			DBG_ERROR( "DoImport: no DBData" );
			return sal_False;
		}
	}

	Window* pWaitWin = rDocShell.GetActiveDialogParent();
	if (pWaitWin)
		pWaitWin->EnterWait();
	ScDocShellModificator aModificator( rDocShell );

	sal_Bool bSuccess = sal_False;
	sal_Bool bApi = sal_False;						//! pass as argument
	sal_Bool bTruncated = sal_False;				// for warning
	sal_uInt16 nErrStringId = 0;
	String aErrorMessage;

	SCCOL nCol = rParam.nCol1;
	SCROW nRow = rParam.nRow1;
	SCCOL nEndCol = nCol;					// end of resulting database area
	SCROW nEndRow = nRow;
	long i;

	sal_Bool bDoSelection = sal_False;
	sal_Bool bRealSelection = sal_False;			// sal_True if not everything is selected
    sal_Bool bBookmarkSelection = sal_False;
    sal_Int32 nListPos = 0;
    sal_Int32 nRowsRead = 0;
    sal_Int32 nListCount = 0;

    uno::Sequence<uno::Any> aSelection;
    if ( pDescriptor && pDescriptor->has(svx::daSelection) )
    {
        (*pDescriptor)[svx::daSelection] >>= aSelection;
        nListCount = aSelection.getLength();
        if ( nListCount > 0 )
        {
            bDoSelection = sal_True;
            if ( pDescriptor->has(svx::daBookmarkSelection) )
                bBookmarkSelection = ScUnoHelpFunctions::GetBoolFromAny( (*pDescriptor)[svx::daBookmarkSelection] );
            if ( bBookmarkSelection )
            {
                // From bookmarks, there's no way to detect if all records are selected.
                // Rely on base to pass no selection in that case.
                bRealSelection = sal_True;
            }
        }
    }

    uno::Reference<sdbc::XResultSet> xResultSet;
    if ( pDescriptor && pDescriptor->has(svx::daCursor) )
        xResultSet.set((*pDescriptor)[svx::daCursor], uno::UNO_QUERY);

	// ImportDoc - also used for Redo
	ScDocument* pImportDoc = new ScDocument( SCDOCMODE_UNDO );
	pImportDoc->InitUndo( pDoc, nTab, nTab );
	ScColumn::bDoubleAlloc = sal_True;

	//
	//	get data from database into import document
	//

	try
	{
		//	progress bar
		//	only text (title is still needed, for the cancel button)
		ScProgress aProgress( &rDocShell, ScGlobal::GetRscString(STR_UNDO_IMPORTDATA), 0 );
		sal_uInt16 nInserted = 0;

        uno::Reference<sdbc::XRowSet> xRowSet = uno::Reference<sdbc::XRowSet>(
                xResultSet, uno::UNO_QUERY );
        sal_Bool bDispose = sal_False;
        if ( !xRowSet.is() )
        {
            bDispose = sal_True;
            xRowSet = uno::Reference<sdbc::XRowSet>(
                    comphelper::getProcessServiceFactory()->createInstance(
                        rtl::OUString::createFromAscii( SC_SERVICE_ROWSET ) ),
                    uno::UNO_QUERY);
            uno::Reference<beans::XPropertySet> xRowProp( xRowSet, uno::UNO_QUERY );
            DBG_ASSERT( xRowProp.is(), "can't get RowSet" );
            if ( xRowProp.is() )
            {
                //
                //	set source parameters
                //

                sal_Int32 nType = rParam.bSql ? sdb::CommandType::COMMAND :
                            ( (rParam.nType == ScDbQuery) ? sdb::CommandType::QUERY :
                                                            sdb::CommandType::TABLE );
                uno::Any aAny;

                aAny <<= rtl::OUString( rParam.aDBName );
                xRowProp->setPropertyValue(
                            rtl::OUString::createFromAscii(SC_DBPROP_DATASOURCENAME), aAny );

                aAny <<= rtl::OUString( rParam.aStatement );
                xRowProp->setPropertyValue(
                            rtl::OUString::createFromAscii(SC_DBPROP_COMMAND), aAny );

                aAny <<= nType;
                xRowProp->setPropertyValue(
                            rtl::OUString::createFromAscii(SC_DBPROP_COMMANDTYPE), aAny );

                uno::Reference<sdb::XCompletedExecution> xExecute( xRowSet, uno::UNO_QUERY );
                if ( xExecute.is() )
                {
                    uno::Reference<task::XInteractionHandler> xHandler(
                            comphelper::getProcessServiceFactory()->createInstance(
                                rtl::OUString::createFromAscii( SC_SERVICE_INTHANDLER ) ),
                            uno::UNO_QUERY);
                    xExecute->executeWithCompletion( xHandler );
                }
                else
                    xRowSet->execute();
            }
        }
        if ( xRowSet.is() )
        {
			//
			//	get column descriptions
			//

			long nColCount = 0;
			uno::Reference<sdbc::XResultSetMetaData> xMeta;
			uno::Reference<sdbc::XResultSetMetaDataSupplier> xMetaSupp( xRowSet, uno::UNO_QUERY );
			if ( xMetaSupp.is() )
				xMeta = xMetaSupp->getMetaData();
			if ( xMeta.is() )
				nColCount = xMeta->getColumnCount();	// this is the number of real columns

			if ( rParam.nCol1 + nColCount - 1 > MAXCOL )
			{
				nColCount = 0;
				//!	error message
			}

            uno::Reference<sdbcx::XRowLocate> xLocate;
            if ( bBookmarkSelection )
            {
                xLocate.set( xRowSet, uno::UNO_QUERY );
                if ( !xLocate.is() )
                {
                    DBG_ERRORFILE("can't get XRowLocate");
                    bDoSelection = bRealSelection = bBookmarkSelection = sal_False;
                }
            }

			uno::Reference<sdbc::XRow> xRow( xRowSet, uno::UNO_QUERY );
			if ( nColCount > 0 && xRow.is() )
			{
				nEndCol = (SCCOL)( rParam.nCol1 + nColCount - 1 );

				uno::Sequence<sal_Int32> aColTypes( nColCount );	// column types
				uno::Sequence<sal_Bool> aColCurr( nColCount );		// currency flag is not in types
				sal_Int32* pTypeArr = aColTypes.getArray();
				sal_Bool* pCurrArr = aColCurr.getArray();
				for (i=0; i<nColCount; i++)
				{
					pTypeArr[i] = xMeta->getColumnType( i+1 );
					pCurrArr[i] = xMeta->isCurrency( i+1 );
				}

				if ( !bAddrInsert )					// read column names
				{
					nCol = rParam.nCol1;
					for (i=0; i<nColCount; i++)
					{
						pImportDoc->SetString( nCol, nRow, nTab,
												xMeta->getColumnLabel( i+1 ) );
						++nCol;
					}
					++nRow;
				}

				sal_Bool bEnd = sal_False;
				if ( !bDoSelection )
					xRowSet->beforeFirst();
				while ( !bEnd )
				{
					//	skip rows that are not selected
					if ( !bDoSelection )
					{
                        if ( (bEnd = !xRowSet->next()) == sal_False )
							++nRowsRead;
					}
					else
					{
						if (nListPos < nListCount)
						{
                            if ( bBookmarkSelection )
                            {
                                bEnd = !xLocate->moveToBookmark(aSelection[nListPos]);
                            }
                            else    // use record numbers
                            {
                                sal_Int32 nNextRow = 0;
                                aSelection[nListPos] >>= nNextRow;
                                if ( nRowsRead+1 < nNextRow )
                                    bRealSelection = sal_True;
                                bEnd = !xRowSet->absolute(nRowsRead = nNextRow);
                            }
                            ++nListPos;
						}
						else
						{
                            if ( !bBookmarkSelection && xRowSet->next() )
                                bRealSelection = sal_True;                      // more data available but not used
                            bEnd = sal_True;
						}
					}

					if ( !bEnd )
					{
						if ( ValidRow(nRow) )
						{
							nCol = rParam.nCol1;
							for (i=0; i<nColCount; i++)
							{
								ScDatabaseDocUtil::PutData( pImportDoc, nCol, nRow, nTab,
												xRow, i+1, pTypeArr[i], pCurrArr[i] );
								++nCol;
							}
							nEndRow = nRow;
							++nRow;

							//	progress bar

							++nInserted;
							if (!(nInserted & 15))
							{
								String aPict = ScGlobal::GetRscString( STR_PROGRESS_IMPORT );
								String aText = aPict.GetToken(0,'#');
								aText += String::CreateFromInt32( nInserted );
								aText += aPict.GetToken(1,'#');

								if (!aProgress.SetStateText( 0, aText ))	// stopped by user?
								{
									bEnd = sal_True;
									bSuccess = sal_False;
									nErrStringId = STR_DATABASE_ABORTED;
								}
							}
						}
						else		// past the end of the spreadsheet
						{
							bEnd = sal_True;			// don't continue
							bTruncated = sal_True;		// warning flag
						}
					}
				}

				bSuccess = sal_True;
			}

            if ( bDispose )
                ::comphelper::disposeComponent( xRowSet );
		}
	}
	catch ( sdbc::SQLException& rError )
	{
		aErrorMessage = rError.Message;
	}
	catch ( uno::Exception& )
	{
		DBG_ERROR("Unexpected exception in database");
	}

	ScColumn::bDoubleAlloc = sal_False;
	pImportDoc->DoColResize( nTab, rParam.nCol1,nEndCol, 0 );

	//
	//	test for cell protection
	//

	sal_Bool bKeepFormat = !bAddrInsert && pDBData->IsKeepFmt();
	sal_Bool bMoveCells = !bAddrInsert && pDBData->IsDoSize();
	SCCOL nFormulaCols = 0;	// columns to be filled with formulas
	if (bMoveCells && nEndCol == rParam.nCol2)
	{
		//	if column count changes, formulas would become invalid anyway
		//	-> only set nFormulaCols for unchanged column count

		SCCOL nTestCol = rParam.nCol2 + 1;		// right of the data
		SCROW nTestRow = rParam.nRow1 + 1;		// below the title row
		while ( nTestCol <= MAXCOL &&
				pDoc->GetCellType(ScAddress( nTestCol, nTestRow, nTab )) == CELLTYPE_FORMULA )
			++nTestCol, ++nFormulaCols;
	}

	if (bSuccess)
	{
		//	old and new range editable?
		ScEditableTester aTester;
		aTester.TestBlock( pDoc, nTab, rParam.nCol1,rParam.nRow1,rParam.nCol2,rParam.nRow2 );
		aTester.TestBlock( pDoc, nTab, rParam.nCol1,rParam.nRow1,nEndCol,nEndRow );
		if ( !aTester.IsEditable() )
		{
			nErrStringId = aTester.GetMessageId();
			bSuccess = sal_False;
		}
		else if ( pDoc->GetChangeTrack() != NULL )
		{
			nErrStringId = STR_PROTECTIONERR;
			bSuccess = sal_False;
		}
	}

	if ( bSuccess && bMoveCells )
	{
		ScRange aOld( rParam.nCol1, rParam.nRow1, nTab,
						rParam.nCol2+nFormulaCols, rParam.nRow2, nTab );
		ScRange aNew( rParam.nCol1, rParam.nRow1, nTab,
						nEndCol+nFormulaCols, nEndRow, nTab );
		if (!pDoc->CanFitBlock( aOld, aNew ))
		{
			nErrStringId = STR_MSSG_DOSUBTOTALS_2;		// can't insert cells
			bSuccess = sal_False;
		}
	}

	//
	//	copy data from import doc into real document
	//

	if ( bSuccess )
	{
		if (bKeepFormat)
		{
			//	keep formatting of title and first data row from the document
			//	CopyToDocument also copies styles, Apply... needs separate calls

			SCCOL nMinEndCol = Min( rParam.nCol2, nEndCol );	// not too much
            nMinEndCol = sal::static_int_cast<SCCOL>( nMinEndCol + nFormulaCols );  // only if column count unchanged
			pImportDoc->DeleteAreaTab( 0,0, MAXCOL,MAXROW, nTab, IDF_ATTRIB );
			pDoc->CopyToDocument( rParam.nCol1, rParam.nRow1, nTab,
									nMinEndCol, rParam.nRow1, nTab,
									IDF_ATTRIB, sal_False, pImportDoc );

			SCROW nDataStartRow = rParam.nRow1+1;
			for (SCCOL nCopyCol=rParam.nCol1; nCopyCol<=nMinEndCol; nCopyCol++)
			{
				const ScPatternAttr* pSrcPattern = pDoc->GetPattern(
													nCopyCol, nDataStartRow, nTab );
				pImportDoc->ApplyPatternAreaTab( nCopyCol, nDataStartRow, nCopyCol, nEndRow,
													nTab, *pSrcPattern );
				const ScStyleSheet* pStyle = pSrcPattern->GetStyleSheet();
				if (pStyle)
					pImportDoc->ApplyStyleAreaTab( nCopyCol, nDataStartRow, nCopyCol, nEndRow,
													nTab, *pStyle );
			}
		}

		//	don't set cell protection attribute if table is protected
		if (pDoc->IsTabProtected(nTab))
		{
			ScPatternAttr aPattern(pImportDoc->GetPool());
			aPattern.GetItemSet().Put( ScProtectionAttr( sal_False,sal_False,sal_False,sal_False ) );
			pImportDoc->ApplyPatternAreaTab( 0,0,MAXCOL,MAXROW, nTab, aPattern );
		}

		//
		//	copy old data for undo
		//

		SCCOL nUndoEndCol = Max( nEndCol, rParam.nCol2 );		// rParam = old end
		SCROW nUndoEndRow = Max( nEndRow, rParam.nRow2 );

		ScDocument* pUndoDoc = NULL;
		ScDBData* pUndoDBData = NULL;
		if ( bRecord )
		{
			pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
			pUndoDoc->InitUndo( pDoc, nTab, nTab );

			if ( !bAddrInsert )
				pUndoDBData = new ScDBData( *pDBData );
		}

		ScMarkData aNewMark;
		aNewMark.SelectOneTable( nTab );

		if (bRecord)
		{
            // do not touch notes (ScUndoImportData does not support drawing undo)
            sal_uInt16 nCopyFlags = IDF_ALL & ~IDF_NOTE;

			//	nFormulaCols is set only if column count is unchanged
			pDoc->CopyToDocument( rParam.nCol1, rParam.nRow1, nTab,
									nEndCol+nFormulaCols, nEndRow, nTab,
                                    nCopyFlags, sal_False, pUndoDoc );
			if ( rParam.nCol2 > nEndCol )
				pDoc->CopyToDocument( nEndCol+1, rParam.nRow1, nTab,
										nUndoEndCol, nUndoEndRow, nTab,
                                        nCopyFlags, sal_False, pUndoDoc );
			if ( rParam.nRow2 > nEndRow )
				pDoc->CopyToDocument( rParam.nCol1, nEndRow+1, nTab,
										nUndoEndCol+nFormulaCols, nUndoEndRow, nTab,
                                        nCopyFlags, sal_False, pUndoDoc );
		}

		//
		//	move new data
		//

		if (bMoveCells)
		{
			//	clear only the range without the formulas,
			//	so the formula title and first row are preserved

			ScRange aDelRange( rParam.nCol1, rParam.nRow1, nTab,
								rParam.nCol2, rParam.nRow2, nTab );
            pDoc->DeleteAreaTab( aDelRange, IDF_ALL & ~IDF_NOTE );  // ohne die Formeln

			ScRange aOld( rParam.nCol1, rParam.nRow1, nTab,
							rParam.nCol2+nFormulaCols, rParam.nRow2, nTab );
			ScRange aNew( rParam.nCol1, rParam.nRow1, nTab,
							nEndCol+nFormulaCols, nEndRow, nTab );
			pDoc->FitBlock( aOld, aNew, sal_False );		// Formeln nicht loeschen
		}
		else if ( nEndCol < rParam.nCol2 )		// DeleteArea calls PutInOrder
			pDoc->DeleteArea( nEndCol+1, rParam.nRow1, rParam.nCol2, rParam.nRow2,
                                aNewMark, IDF_CONTENTS & ~IDF_NOTE );

		//	CopyToDocument doesn't remove contents
        pDoc->DeleteAreaTab( rParam.nCol1, rParam.nRow1, nEndCol, nEndRow, nTab, IDF_CONTENTS & ~IDF_NOTE );

		//	#41216# remove each column from ImportDoc after copying to reduce memory usage
		sal_Bool bOldAutoCalc = pDoc->GetAutoCalc();
		pDoc->SetAutoCalc( sal_False );				// outside of the loop
		for (SCCOL nCopyCol = rParam.nCol1; nCopyCol <= nEndCol; nCopyCol++)
		{
			pImportDoc->CopyToDocument( nCopyCol, rParam.nRow1, nTab, nCopyCol, nEndRow, nTab,
										IDF_ALL, sal_False, pDoc );
			pImportDoc->DeleteAreaTab( nCopyCol, rParam.nRow1, nCopyCol, nEndRow, nTab, IDF_CONTENTS );
			pImportDoc->DoColResize( nTab, nCopyCol, nCopyCol, 0 );
		}
		pDoc->SetAutoCalc( bOldAutoCalc );

		if (nFormulaCols > 0)				// copy formulas
		{
			if (bKeepFormat)			// formats for formulas
				pImportDoc->CopyToDocument( nEndCol+1, rParam.nRow1, nTab,
											nEndCol+nFormulaCols, nEndRow, nTab,
											IDF_ATTRIB, sal_False, pDoc );
			// fill formulas
			ScMarkData aMark;
			aMark.SelectOneTable(nTab);
			pDoc->Fill( nEndCol+1, rParam.nRow1+1, nEndCol+nFormulaCols, rParam.nRow1+1,
							aMark, nEndRow-rParam.nRow1-1, FILL_TO_BOTTOM, FILL_SIMPLE );
		}

		//	if new range is smaller, clear old contents

		if (!bMoveCells)		// move has happened above
		{
			if ( rParam.nCol2 > nEndCol )
				pDoc->DeleteArea( nEndCol+1, rParam.nRow1, rParam.nCol2, rParam.nRow2,
									aNewMark, IDF_CONTENTS );
			if ( rParam.nRow2 > nEndRow )
				pDoc->DeleteArea( rParam.nCol1, nEndRow+1, rParam.nCol2, rParam.nRow2,
									aNewMark, IDF_CONTENTS );
		}

		if( !bAddrInsert )		// update database range
		{
			pDBData->SetImportParam( rParam );
			pDBData->SetHeader( sal_True );
			pDBData->SetByRow( sal_True );
			pDBData->SetArea( nTab, rParam.nCol1,rParam.nRow1, nEndCol,nEndRow );
			pDBData->SetImportSelection( bRealSelection );
			pDoc->CompileDBFormula();
		}

		if (bRecord)
		{
			ScDocument* pRedoDoc = pImportDoc;
			pImportDoc = NULL;

			if (nFormulaCols > 0)					// include filled formulas for redo
				pDoc->CopyToDocument( rParam.nCol1, rParam.nRow1, nTab,
										nEndCol+nFormulaCols, nEndRow, nTab,
                                        IDF_ALL & ~IDF_NOTE, sal_False, pRedoDoc );

			ScDBData* pRedoDBData = pDBData ? new ScDBData( *pDBData ) : NULL;

			rDocShell.GetUndoManager()->AddUndoAction(
				new ScUndoImportData( &rDocShell, nTab,
										rParam, nUndoEndCol, nUndoEndRow,
										nFormulaCols,
										pUndoDoc, pRedoDoc, pUndoDBData, pRedoDBData ) );
		}

		pDoc->SetDirty();
		rDocShell.PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID );
		aModificator.SetDocumentModified();

	    ScDBRangeRefreshedHint aHint( rParam );
	    pDoc->BroadcastUno( aHint );

		if (pWaitWin)
			pWaitWin->LeaveWait();

		if ( bTruncated && !bApi )			// show warning
			ErrorHandler::HandleError(SCWARN_IMPORT_RANGE_OVERFLOW);
	}
	else if ( !bApi )
	{
		if (pWaitWin)
			pWaitWin->LeaveWait();

		if (!aErrorMessage.Len())
		{
			if (!nErrStringId)
				nErrStringId = STR_MSSG_IMPORTDATA_0;
			aErrorMessage = ScGlobal::GetRscString( nErrStringId );
		}
		InfoBox aInfoBox( rDocShell.GetActiveDialogParent(), aErrorMessage );
		aInfoBox.Execute();
	}

	delete pImportDoc;

	return bSuccess;
}
