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