diff options
Diffstat (limited to 'bf_sc/source/ui/docshell/sc_dbdocimp.cxx')
-rw-r--r-- | bf_sc/source/ui/docshell/sc_dbdocimp.cxx | 495 |
1 files changed, 495 insertions, 0 deletions
diff --git a/bf_sc/source/ui/docshell/sc_dbdocimp.cxx b/bf_sc/source/ui/docshell/sc_dbdocimp.cxx new file mode 100644 index 000000000..bb716d9bf --- /dev/null +++ b/bf_sc/source/ui/docshell/sc_dbdocimp.cxx @@ -0,0 +1,495 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifdef _MSC_VER +#pragma hdrstop +#endif + + +#include <comphelper/processfactory.hxx> +#include <comphelper/types.hxx> +#include <vcl/msgbox.hxx> +#include <tools/debug.hxx> +#include <bf_svx/dataaccessdescriptor.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/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 <legacysmgr/legacy_binfilters_smgr.hxx> +namespace binfilter { +using namespace ::com::sun::star; + +class SbaSelectionList: public List , public SvRefBase +{ +public: + SbaSelectionList(): + List(CONTAINER_MAXBLOCKSIZE,100,100){} +}; + +SV_DECL_IMPL_REF(SbaSelectionList) + +#define SC_SERVICE_ROWSET "com.sun.star.sdb.RowSet" +#define SC_SERVICE_INTHANDLER "com.sun.star.sdb.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" + + +/*M*/ BOOL ScDBDocFunc::DoImport( USHORT nTab, const ScImportParam& rParam, +/*M*/ const uno::Reference< sdbc::XResultSet >& xResultSet, +/*M*/ const SbaSelectionList* pSelection, BOOL bRecord, BOOL bAddrInsert ) +/*M*/ { +/*M*/ ScDocument* pDoc = rDocShell.GetDocument(); +/*M*/ +/*M*/ if (bRecord && !pDoc->IsUndoEnabled()) +/*M*/ bRecord = FALSE; +/*M*/ +/*M*/ ScDBData* pDBData = 0; +/*M*/ if ( !bAddrInsert ) +/*M*/ { +/*M*/ OSL_FAIL( "DoImport: no DBData" ); +/*M*/ return FALSE; +/*M*/ } +/*M*/ +/*M*/ Window* pWaitWin = rDocShell.GetDialogParent(); +/*M*/ if (pWaitWin) +/*M*/ pWaitWin->EnterWait(); +/*M*/ ScDocShellModificator aModificator( rDocShell ); +/*M*/ +/*M*/ BOOL bSuccess = FALSE; +/*M*/ String aErrorMessage; +/*M*/ +/*M*/ USHORT nCol = rParam.nCol1; +/*M*/ USHORT nRow = rParam.nRow1; +/*M*/ USHORT nEndCol = nCol; // end of resulting database area +/*M*/ USHORT nEndRow = nRow; +/*M*/ long i; +/*M*/ +/*M*/ BOOL bDoSelection = FALSE; +/*M*/ ULONG nListPos = 0; +/*M*/ ULONG nRowsRead = 0; +/*M*/ ULONG nListCount = 0; +/*M*/ +/*M*/ // -1 is special +/*M*/ if ( pSelection && pSelection->Count() && (long)pSelection->GetObject(0) != -1L ) +/*M*/ { +/*M*/ bDoSelection = TRUE; +/*M*/ nListCount = pSelection->Count(); +/*M*/ } +/*M*/ +/*M*/ // ImportDoc - also used for Redo +/*M*/ ScDocument* pImportDoc = new ScDocument( SCDOCMODE_UNDO ); +/*M*/ pImportDoc->InitUndo( pDoc, nTab, nTab ); +/*M*/ ScColumn::bDoubleAlloc = TRUE; +/*M*/ +/*M*/ // +/*M*/ // get data from database into import document +/*M*/ // +/*M*/ +/*M*/ try +/*M*/ { +/*M*/ // progress bar +/*M*/ // only text (title is still needed, for the cancel button) +/*M*/ ScProgress aProgress( &rDocShell, ScGlobal::GetRscString(STR_UNDO_IMPORTDATA), 0 ); +/*M*/ USHORT nInserted = 0; +/*M*/ +/*M*/ uno::Reference<sdbc::XRowSet> xRowSet = uno::Reference<sdbc::XRowSet>( +/*M*/ xResultSet, uno::UNO_QUERY ); +/*M*/ sal_Bool bDispose = sal_False; +/*M*/ if ( !xRowSet.is() ) +/*M*/ { +/*M*/ bDispose = sal_True; +/*M*/ xRowSet = uno::Reference<sdbc::XRowSet>( +/*M*/ ::legacy_binfilters::getLegacyProcessServiceFactory()->createInstance( +/*M*/ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( SC_SERVICE_ROWSET )) ), +/*M*/ uno::UNO_QUERY); +/*M*/ uno::Reference<beans::XPropertySet> xRowProp( xRowSet, uno::UNO_QUERY ); +/*M*/ DBG_ASSERT( xRowProp.is(), "can't get RowSet" ); +/*M*/ if ( xRowProp.is() ) +/*M*/ { +/*M*/ // +/*M*/ // set source parameters +/*M*/ // +/*M*/ +/*M*/ sal_Int32 nType = rParam.bSql ? sdb::CommandType::COMMAND : +/*M*/ ( (rParam.nType == ScDbQuery) ? sdb::CommandType::QUERY : +/*M*/ sdb::CommandType::TABLE ); +/*M*/ uno::Any aAny; +/*M*/ +/*M*/ aAny <<= ::rtl::OUString( rParam.aDBName ); +/*M*/ xRowProp->setPropertyValue( +/*M*/ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_DBPROP_DATASOURCENAME)), aAny ); +/*M*/ +/*M*/ aAny <<= ::rtl::OUString( rParam.aStatement ); +/*M*/ xRowProp->setPropertyValue( +/*M*/ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_DBPROP_COMMAND)), aAny ); +/*M*/ +/*M*/ aAny <<= nType; +/*M*/ xRowProp->setPropertyValue( +/*M*/ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_DBPROP_COMMANDTYPE)), aAny ); +/*M*/ +/*M*/ uno::Reference<sdb::XCompletedExecution> xExecute( xRowSet, uno::UNO_QUERY ); +/*M*/ if ( xExecute.is() ) +/*M*/ { +/*M*/ uno::Reference<task::XInteractionHandler> xHandler( +/*M*/ ::legacy_binfilters::getLegacyProcessServiceFactory()->createInstance( +/*M*/ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( SC_SERVICE_INTHANDLER )) ), +/*M*/ uno::UNO_QUERY); +/*M*/ xExecute->executeWithCompletion( xHandler ); +/*M*/ } +/*M*/ else +/*M*/ xRowSet->execute(); +/*M*/ } +/*M*/ } +/*M*/ if ( xRowSet.is() ) +/*M*/ { +/*M*/ // +/*M*/ // get column descriptions +/*M*/ // +/*M*/ +/*M*/ long nColCount = 0; +/*M*/ uno::Reference<sdbc::XResultSetMetaData> xMeta; +/*M*/ uno::Reference<sdbc::XResultSetMetaDataSupplier> xMetaSupp( xRowSet, uno::UNO_QUERY ); +/*M*/ if ( xMetaSupp.is() ) +/*M*/ xMeta = xMetaSupp->getMetaData(); +/*M*/ if ( xMeta.is() ) +/*M*/ nColCount = xMeta->getColumnCount(); // this is the number of real columns +/*M*/ +/*M*/ if ( rParam.nCol1 + nColCount - 1 > MAXCOL ) +/*M*/ { +/*M*/ nColCount = 0; +/*M*/ //! error message +/*M*/ } +/*M*/ +/*M*/ uno::Reference<sdbc::XRow> xRow( xRowSet, uno::UNO_QUERY ); +/*M*/ if ( nColCount > 0 && xRow.is() ) +/*M*/ { +/*M*/ nEndCol = (USHORT)( rParam.nCol1 + nColCount - 1 ); +/*M*/ +/*M*/ uno::Sequence<sal_Int32> aColTypes( nColCount ); // column types +/*M*/ uno::Sequence<sal_Bool> aColCurr( nColCount ); // currency flag is not in types +/*M*/ sal_Int32* pTypeArr = aColTypes.getArray(); +/*M*/ sal_Bool* pCurrArr = aColCurr.getArray(); +/*M*/ for (i=0; i<nColCount; i++) +/*M*/ { +/*M*/ pTypeArr[i] = xMeta->getColumnType( i+1 ); +/*M*/ pCurrArr[i] = xMeta->isCurrency( i+1 ); +/*M*/ } +/*M*/ +/*M*/ if ( !bAddrInsert ) // read column names +/*M*/ { +/*M*/ nCol = rParam.nCol1; +/*M*/ for (i=0; i<nColCount; i++) +/*M*/ { +/*M*/ pImportDoc->SetString( nCol, nRow, nTab, +/*M*/ xMeta->getColumnLabel( i+1 ) ); +/*M*/ ++nCol; +/*M*/ } +/*M*/ ++nRow; +/*M*/ } +/*M*/ +/*M*/ BOOL bEnd = FALSE; +/*M*/ xRowSet->beforeFirst(); +/*M*/ while ( !bEnd && xRowSet->next() ) +/*M*/ { +/*M*/ // skip rows that are not selected +/*M*/ +/*M*/ if (bDoSelection) +/*M*/ { +/*M*/ if (nListPos < nListCount) +/*M*/ { +/*M*/ ULONG nNextRow = (ULONG) pSelection->GetObject(nListPos); +/*M*/ while (nRowsRead+1 < nNextRow && !bEnd) +/*M*/ { +/*M*/ if ( !xRowSet->next() ) +/*M*/ bEnd = TRUE; +/*M*/ ++nRowsRead; +/*M*/ } +/*M*/ ++nListPos; +/*M*/ } +/*M*/ else +/*M*/ { +/*M*/ bEnd = TRUE; +/*M*/ } +/*M*/ } +/*M*/ +/*M*/ if ( !bEnd ) +/*M*/ { +/*M*/ if ( nRow <= MAXROW ) +/*M*/ { +/*M*/ nCol = rParam.nCol1; +/*M*/ for (i=0; i<nColCount; i++) +/*M*/ { +/*M*/ ScDatabaseDocUtil::PutData( pImportDoc, nCol, nRow, nTab, +/*M*/ xRow, i+1, pTypeArr[i], pCurrArr[i] ); +/*M*/ ++nCol; +/*M*/ } +/*M*/ nEndRow = nRow; +/*M*/ ++nRow; +/*M*/ +/*M*/ // progress bar +/*M*/ +/*M*/ ++nInserted; +/*M*/ } +/*M*/ else // past the end of the spreadsheet +/*M*/ { +/*M*/ bEnd = TRUE; // don't continue +/*M*/ } +/*M*/ } +/*M*/ +/*M*/ ++nRowsRead; +/*M*/ } +/*M*/ +/*M*/ bSuccess = TRUE; +/*M*/ } +/*M*/ +/*M*/ if ( bDispose ) +/*M*/ ::comphelper::disposeComponent( xRowSet ); +/*M*/ } +/*M*/ } +/*M*/ catch ( sdbc::SQLException& rError ) +/*M*/ { +/*M*/ aErrorMessage = rError.Message; +/*M*/ } +/*M*/ catch ( uno::Exception& ) +/*M*/ { +/*M*/ OSL_FAIL("Unexpected exception in database"); +/*M*/ } +/*M*/ +/*M*/ ScColumn::bDoubleAlloc = FALSE; +/*M*/ pImportDoc->DoColResize( nTab, rParam.nCol1,nEndCol, 0 ); +/*M*/ +/*M*/ // +/*M*/ // test for cell protection +/*M*/ // +/*M*/ +/*M*/ BOOL bKeepFormat = !bAddrInsert && pDBData->IsKeepFmt(); +/*M*/ BOOL bMoveCells = !bAddrInsert && pDBData->IsDoSize(); +/*M*/ USHORT nFormulaCols = 0; // columns to be filled with formulas +/*M*/ if (bMoveCells && nEndCol == rParam.nCol2) +/*M*/ { +/*M*/ // if column count changes, formulas would become invalid anyway +/*M*/ // -> only set nFormulaCols for unchanged column count +/*M*/ +/*M*/ USHORT nTestCol = rParam.nCol2 + 1; // right of the data +/*M*/ USHORT nTestRow = rParam.nRow1 + 1; // below the title row +/*M*/ while ( nTestCol <= MAXCOL && +/*M*/ pDoc->GetCellType(ScAddress( nTestCol, nTestRow, nTab )) == CELLTYPE_FORMULA ) +/*M*/ ++nTestCol, ++nFormulaCols; +/*M*/ } +/*M*/ +/*M*/ if (bSuccess) +/*M*/ { +/*M*/ // old and new range editable? +/*N*/ ScEditableTester aTester; +/*N*/ aTester.TestBlock( pDoc, nTab, rParam.nCol1,rParam.nRow1,rParam.nCol2,rParam.nRow2 ); +/*N*/ aTester.TestBlock( pDoc, nTab, rParam.nCol1,rParam.nRow1,nEndCol,nEndRow ); +/*N*/ if ( !aTester.IsEditable() ) +/*N*/ { +/*N*/ bSuccess = FALSE; +/*N*/ } +/*N*/ else if ( pDoc->GetChangeTrack() != NULL ) +/*M*/ { +/*M*/ bSuccess = FALSE; +/*M*/ } +/*M*/ } +/*M*/ +/*M*/ if ( bSuccess && bMoveCells ) +/*M*/ { +/*M*/ bSuccess = FALSE; +/*M*/ } +/*M*/ +/*M*/ // +/*M*/ // copy data from import doc into real document +/*M*/ // +/*M*/ +/*M*/ if ( bSuccess ) +/*M*/ { +/*M*/ if (bKeepFormat) +/*M*/ { +/*M*/ // keep formatting of title and first data row from the document +/*M*/ // CopyToDocument also copies styles, Apply... needs separate calls +/*M*/ +/*M*/ USHORT nMinEndCol = Min( rParam.nCol2, nEndCol ); // not too much +/*M*/ nMinEndCol += nFormulaCols; // only if column count unchanged +/*M*/ pImportDoc->DeleteAreaTab( 0,0, MAXCOL,MAXROW, nTab, IDF_ATTRIB ); +/*M*/ pDoc->CopyToDocument( rParam.nCol1, rParam.nRow1, nTab, +/*M*/ nMinEndCol, rParam.nRow1, nTab, +/*M*/ IDF_ATTRIB, FALSE, pImportDoc ); +/*M*/ +/*M*/ USHORT nDataStartRow = rParam.nRow1+1; +/*M*/ for (USHORT nCopyCol=rParam.nCol1; nCopyCol<=nMinEndCol; nCopyCol++) +/*M*/ { +/*M*/ const ScPatternAttr* pSrcPattern = pDoc->GetPattern( +/*M*/ nCopyCol, nDataStartRow, nTab ); +/*M*/ pImportDoc->ApplyPatternAreaTab( nCopyCol, nDataStartRow, nCopyCol, nEndRow, +/*M*/ nTab, *pSrcPattern ); +/*M*/ const ScStyleSheet* pStyle = pSrcPattern->GetStyleSheet(); +/*M*/ if (pStyle) +/*M*/ pImportDoc->ApplyStyleAreaTab( nCopyCol, nDataStartRow, nCopyCol, nEndRow, +/*M*/ nTab, *pStyle ); +/*M*/ } +/*M*/ } +/*M*/ +/*M*/ // don't set cell protection attribute if table is protected +/*M*/ if (pDoc->IsTabProtected(nTab)) +/*M*/ { +/*M*/ ScPatternAttr aPattern(pImportDoc->GetPool()); +/*M*/ aPattern.GetItemSet().Put( ScProtectionAttr( FALSE,FALSE,FALSE,FALSE ) ); +/*M*/ pImportDoc->ApplyPatternAreaTab( 0,0,MAXCOL,MAXROW, nTab, aPattern ); +/*M*/ } +/*M*/ +/*M*/ // +/*M*/ // copy old data for undo +/*M*/ // +/*M*/ +/*M*/ USHORT nUndoEndCol = Max( nEndCol, rParam.nCol2 ); // rParam = old end +/*M*/ USHORT nUndoEndRow = Max( nEndRow, rParam.nRow2 ); +/*M*/ +/*M*/ ScDocument* pUndoDoc = NULL; +/*M*/ if ( bRecord ) +/*M*/ { +/*M*/ pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); +/*M*/ pUndoDoc->InitUndo( pDoc, nTab, nTab ); +/*M*/ } +/*M*/ +/*M*/ ScMarkData aNewMark; +/*M*/ aNewMark.SelectOneTable( nTab ); +/*M*/ +/*M*/ if (bRecord) +/*M*/ { +/*M*/ // nFormulaCols is set only if column count is unchanged +/*M*/ pDoc->CopyToDocument( rParam.nCol1, rParam.nRow1, nTab, +/*M*/ nEndCol+nFormulaCols, nEndRow, nTab, +/*M*/ IDF_ALL, FALSE, pUndoDoc ); +/*M*/ if ( rParam.nCol2 > nEndCol ) +/*M*/ pDoc->CopyToDocument( nEndCol+1, rParam.nRow1, nTab, +/*M*/ nUndoEndCol, nUndoEndRow, nTab, +/*M*/ IDF_ALL, FALSE, pUndoDoc ); +/*M*/ if ( rParam.nRow2 > nEndRow ) +/*M*/ pDoc->CopyToDocument( rParam.nCol1, nEndRow+1, nTab, +/*M*/ nUndoEndCol+nFormulaCols, nUndoEndRow, nTab, +/*M*/ IDF_ALL, FALSE, pUndoDoc ); +/*M*/ } +/*M*/ +/*M*/ // +/*M*/ // move new data +/*M*/ // +/*M*/ +/*M*/ if (bMoveCells) +/*M*/ { +/*M*/ // clear only the range without the formulas, +/*M*/ // so the formula title and first row are preserved +/*M*/ +/*M*/ ScRange aDelRange( rParam.nCol1, rParam.nRow1, nTab, +/*M*/ rParam.nCol2, rParam.nRow2, nTab ); +/*M*/ pDoc->DeleteAreaTab( aDelRange, IDF_ALL ); // ohne die Formeln +/*M*/ } +/*M*/ else if ( nEndCol < rParam.nCol2 ) // DeleteArea calls PutInOrder +/*M*/ pDoc->DeleteArea( nEndCol+1, rParam.nRow1, rParam.nCol2, rParam.nRow2, +/*M*/ aNewMark, IDF_CONTENTS ); +/*M*/ +/*M*/ // CopyToDocument doesn't remove contents +/*M*/ pDoc->DeleteAreaTab( rParam.nCol1, rParam.nRow1, nEndCol, nEndRow, nTab, IDF_CONTENTS ); +/*M*/ +/*M*/ // #41216# remove each column from ImportDoc after copying to reduce memory usage +/*M*/ BOOL bOldAutoCalc = pDoc->GetAutoCalc(); +/*M*/ pDoc->SetAutoCalc( FALSE ); // outside of the loop +/*M*/ for (USHORT nCopyCol = rParam.nCol1; nCopyCol <= nEndCol; nCopyCol++) +/*M*/ { +/*M*/ pImportDoc->CopyToDocument( nCopyCol, rParam.nRow1, nTab, nCopyCol, nEndRow, nTab, +/*M*/ IDF_ALL, FALSE, pDoc ); +/*M*/ pImportDoc->DeleteAreaTab( nCopyCol, rParam.nRow1, nCopyCol, nEndRow, nTab, IDF_CONTENTS ); +/*M*/ pImportDoc->DoColResize( nTab, nCopyCol, nCopyCol, 0 ); +/*M*/ } +/*M*/ pDoc->SetAutoCalc( bOldAutoCalc ); +/*M*/ +/*M*/ if (nFormulaCols) // copy formulas +/*M*/ { +/*M*/ if (bKeepFormat) // formats for formulas +/*M*/ pImportDoc->CopyToDocument( nEndCol+1, rParam.nRow1, nTab, +/*M*/ nEndCol+nFormulaCols, nEndRow, nTab, +/*M*/ IDF_ATTRIB, FALSE, pDoc ); +/*M*/ // fill formulas +/*M*/ ScMarkData aMark; +/*M*/ aMark.SelectOneTable(nTab); +/*M*/ } +/*M*/ +/*M*/ // if new range is smaller, clear old contents +/*M*/ +/*M*/ if (!bMoveCells) // move has happened above +/*M*/ { +/*M*/ if ( rParam.nCol2 > nEndCol ) +/*M*/ pDoc->DeleteArea( nEndCol+1, rParam.nRow1, rParam.nCol2, rParam.nRow2, +/*M*/ aNewMark, IDF_CONTENTS ); +/*M*/ if ( rParam.nRow2 > nEndRow ) +/*M*/ pDoc->DeleteArea( rParam.nCol1, nEndRow+1, rParam.nCol2, rParam.nRow2, +/*M*/ aNewMark, IDF_CONTENTS ); +/*M*/ } +/*M*/ +/*M*/ pDoc->SetDirty(); +/*M*/ rDocShell.PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID ); +/*M*/ aModificator.SetDocumentModified(); +/*M*/ +/*M*/ if (pWaitWin) +/*M*/ pWaitWin->LeaveWait(); +/*M*/ } +/*M*/ delete pImportDoc; +/*M*/ +/*M*/ return bSuccess; +/*M*/ } + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |