Coverage Report

Created: 2026-05-16 09:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sc/source/ui/docshell/dbdocimp.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
#include <vcl/errinf.hxx>
21
#include <comphelper/processfactory.hxx>
22
#include <comphelper/types.hxx>
23
#include <vcl/svapp.hxx>
24
#include <vcl/vclenum.hxx>
25
#include <vcl/weld/MessageDialog.hxx>
26
#include <vcl/weld/weld.hxx>
27
#include <svx/dataaccessdescriptor.hxx>
28
#include <sfx2/viewfrm.hxx>
29
#include <sal/log.hxx>
30
#include <osl/diagnose.h>
31
#include <comphelper/diagnose_ex.hxx>
32
33
#include <com/sun/star/sdb/CommandType.hpp>
34
#include <com/sun/star/sdb/XCompletedExecution.hpp>
35
#include <com/sun/star/sdbc/SQLException.hpp>
36
#include <com/sun/star/sdbc/XRow.hpp>
37
#include <com/sun/star/sdbc/XRowSet.hpp>
38
#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
39
#include <com/sun/star/sdbcx/XRowLocate.hpp>
40
#include <com/sun/star/task/InteractionHandler.hpp>
41
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
42
#include <com/sun/star/beans/XPropertySet.hpp>
43
#include <com/sun/star/frame/FrameSearchFlag.hpp>
44
#include <com/sun/star/view/XSelectionSupplier.hpp>
45
46
#include <dbdocfun.hxx>
47
#include <docsh.hxx>
48
#include <globstr.hrc>
49
#include <scresid.hxx>
50
#include <scerrors.hxx>
51
#include <dbdata.hxx>
52
#include <markdata.hxx>
53
#include <undodat.hxx>
54
#include <progress.hxx>
55
#include <patattr.hxx>
56
#include <docpool.hxx>
57
#include <attrib.hxx>
58
#include <dbdocutl.hxx>
59
#include <editable.hxx>
60
#include <hints.hxx>
61
#include <miscuno.hxx>
62
#include <chgtrack.hxx>
63
#include <refupdatecontext.hxx>
64
65
using namespace com::sun::star;
66
67
constexpr OUStringLiteral SC_SERVICE_ROWSET = u"com.sun.star.sdb.RowSet";
68
69
//! move to a header file?
70
constexpr OUStringLiteral SC_DBPROP_DATASOURCENAME = u"DataSourceName";
71
constexpr OUStringLiteral SC_DBPROP_COMMAND = u"Command";
72
constexpr OUStringLiteral SC_DBPROP_COMMANDTYPE = u"CommandType";
73
74
void ScDBDocFunc::ShowInBeamer( const ScImportParam& rParam, const SfxViewFrame* pFrame )
75
0
{
76
    //  called after opening the database beamer
77
78
0
    if ( !pFrame || !rParam.bImport )
79
0
        return;
80
81
0
    uno::Reference<frame::XFrame> xFrame = pFrame->GetFrame().GetFrameInterface();
82
83
0
    uno::Reference<frame::XFrame> xBeamerFrame = xFrame->findFrame(
84
0
                                        u"_beamer"_ustr,
85
0
                                        frame::FrameSearchFlag::CHILDREN);
86
0
    if (!xBeamerFrame.is())
87
0
        return;
88
89
0
    uno::Reference<frame::XController> xController = xBeamerFrame->getController();
90
0
    uno::Reference<view::XSelectionSupplier> xControllerSelection(xController, uno::UNO_QUERY);
91
0
    if (xControllerSelection.is())
92
0
    {
93
0
        sal_Int32 nType = rParam.bSql ? sdb::CommandType::COMMAND :
94
0
                    ( (rParam.nType == ScDbQuery) ? sdb::CommandType::QUERY :
95
0
                                                    sdb::CommandType::TABLE );
96
97
0
        svx::ODataAccessDescriptor aSelection;
98
0
        aSelection.setDataSource(rParam.aDBName);
99
0
        aSelection[svx::DataAccessDescriptorProperty::Command]      <<= rParam.aStatement;
100
0
        aSelection[svx::DataAccessDescriptorProperty::CommandType]  <<= nType;
101
102
0
        xControllerSelection->select(uno::Any(aSelection.createPropertyValueSequence()));
103
0
    }
104
0
    else
105
0
    {
106
0
        OSL_FAIL("no selection supplier in the beamer!");
107
0
    }
108
0
}
109
110
void ScDBDocFunc::DoImportUno( const ScAddress& rPos,
111
                                const uno::Sequence<beans::PropertyValue>& aArgs )
112
0
{
113
0
    svx::ODataAccessDescriptor aDesc( aArgs );      // includes selection and result set
114
115
    //  create database range
116
0
    ScDBData* pDBData = rDocShell.GetDBData( ScRange(rPos), SC_DB_IMPORT, ScGetDBSelection::Keep );
117
0
    assert(pDBData && "can't create DB data");
118
0
    OUString sTarget = pDBData->GetName();
119
120
0
    UpdateImport( sTarget, aDesc );
121
0
}
122
123
bool ScDBDocFunc::DoImport( SCTAB nTab, const ScImportParam& rParam,
124
        const svx::ODataAccessDescriptor* pDescriptor )
125
0
{
126
0
    ScDocument& rDoc = rDocShell.GetDocument();
127
0
    ScChangeTrack *pChangeTrack = nullptr;
128
0
    ScRange aChangedRange;
129
130
0
    bool bRecord = true;
131
0
    if (!rDoc.IsUndoEnabled())
132
0
        bRecord = false;
133
134
0
    ScDBData* pDBData = rDoc.GetDBAtArea( nTab, rParam.nCol1, rParam.nRow1,
135
0
                                          rParam.nCol2, rParam.nRow2 );
136
0
    if (!pDBData)
137
0
    {
138
0
        OSL_FAIL( "DoImport: no DBData" );
139
0
        return false;
140
0
    }
141
142
0
    std::unique_ptr<weld::WaitObject> xWaitWin(new weld::WaitObject(ScDocShell::GetActiveDialogParent()));
143
0
    ScDocShellModificator aModificator( rDocShell );
144
145
0
    bool bSuccess = false;
146
0
    bool bTruncated = false;                // for warning
147
0
    TranslateId pErrStringId;
148
0
    OUString aErrorMessage;
149
150
0
    SCCOL nCol = rParam.nCol1;
151
0
    SCROW nRow = rParam.nRow1;
152
0
    SCCOL nEndCol = nCol;                   // end of resulting database area
153
0
    SCROW nEndRow = nRow;
154
155
0
    bool bDoSelection = false;
156
0
    bool bRealSelection = false;            // sal_True if not everything is selected
157
0
    bool bBookmarkSelection = false;
158
0
    sal_Int32 nListPos = 0;
159
0
    sal_Int32 nRowsRead = 0;
160
0
    sal_Int32 nListCount = 0;
161
162
0
    uno::Sequence<uno::Any> aSelection;
163
0
    if ( pDescriptor && pDescriptor->has(svx::DataAccessDescriptorProperty::Selection) )
164
0
    {
165
0
        (*pDescriptor)[svx::DataAccessDescriptorProperty::Selection] >>= aSelection;
166
0
        nListCount = aSelection.getLength();
167
0
        if ( nListCount > 0 )
168
0
        {
169
0
            bDoSelection = true;
170
0
            if ( pDescriptor->has(svx::DataAccessDescriptorProperty::BookmarkSelection) )
171
0
                bBookmarkSelection = ScUnoHelpFunctions::GetBoolFromAny( (*pDescriptor)[svx::DataAccessDescriptorProperty::BookmarkSelection] );
172
0
            if ( bBookmarkSelection )
173
0
            {
174
                // From bookmarks, there's no way to detect if all records are selected.
175
                // Rely on base to pass no selection in that case.
176
0
                bRealSelection = true;
177
0
            }
178
0
        }
179
0
    }
180
181
0
    uno::Reference<sdbc::XResultSet> xResultSet;
182
0
    if ( pDescriptor && pDescriptor->has(svx::DataAccessDescriptorProperty::Cursor) )
183
0
        xResultSet.set((*pDescriptor)[svx::DataAccessDescriptorProperty::Cursor], uno::UNO_QUERY);
184
185
    // ImportDoc - also used for Redo
186
0
    ScDocumentUniquePtr pImportDoc(new ScDocument( SCDOCMODE_UNDO ));
187
0
    pImportDoc->InitUndo( rDoc, nTab, nTab );
188
189
    //  get data from database into import document
190
191
0
    try
192
0
    {
193
        //  progress bar
194
        //  only text (title is still needed, for the cancel button)
195
0
        ScProgress aProgress( &rDocShell, ScResId(STR_UNDO_IMPORTDATA), 0, true );
196
197
0
        uno::Reference<sdbc::XRowSet> xRowSet( xResultSet, uno::UNO_QUERY );
198
0
        bool bDispose = false;
199
0
        if ( !xRowSet.is() )
200
0
        {
201
0
            bDispose = true;
202
0
            xRowSet.set(comphelper::getProcessServiceFactory()->createInstance(
203
0
                            SC_SERVICE_ROWSET ),
204
0
                        uno::UNO_QUERY);
205
0
            uno::Reference<beans::XPropertySet> xRowProp( xRowSet, uno::UNO_QUERY );
206
0
            OSL_ENSURE( xRowProp.is(), "can't get RowSet" );
207
0
            if ( xRowProp.is() )
208
0
            {
209
210
                //  set source parameters
211
212
0
                sal_Int32 nType = rParam.bSql ? sdb::CommandType::COMMAND :
213
0
                            ( (rParam.nType == ScDbQuery) ? sdb::CommandType::QUERY :
214
0
                                                            sdb::CommandType::TABLE );
215
216
0
                xRowProp->setPropertyValue( SC_DBPROP_DATASOURCENAME, uno::Any(rParam.aDBName) );
217
218
0
                xRowProp->setPropertyValue( SC_DBPROP_COMMAND, uno::Any(rParam.aStatement) );
219
220
0
                xRowProp->setPropertyValue( SC_DBPROP_COMMANDTYPE, uno::Any(nType) );
221
222
0
                uno::Reference<sdb::XCompletedExecution> xExecute( xRowSet, uno::UNO_QUERY );
223
0
                if ( xExecute.is() )
224
0
                {
225
0
                    uno::Reference<task::XInteractionHandler> xHandler(
226
0
                        task::InteractionHandler::createWithParent(comphelper::getProcessComponentContext(), nullptr),
227
0
                        uno::UNO_QUERY_THROW);
228
0
                    xExecute->executeWithCompletion( xHandler );
229
0
                }
230
0
                else
231
0
                    xRowSet->execute();
232
0
            }
233
0
        }
234
0
        if ( xRowSet.is() )
235
0
        {
236
237
            //  get column descriptions
238
239
0
            sal_Int32 nColCount = 0;
240
0
            uno::Reference<sdbc::XResultSetMetaData> xMeta;
241
0
            uno::Reference<sdbc::XResultSetMetaDataSupplier> xMetaSupp( xRowSet, uno::UNO_QUERY );
242
0
            if ( xMetaSupp.is() )
243
0
                xMeta = xMetaSupp->getMetaData();
244
0
            if ( xMeta.is() )
245
0
                nColCount = xMeta->getColumnCount();    // this is the number of real columns
246
247
0
            if ( rParam.nCol1 + nColCount - 1 > rDoc.MaxCol() )
248
0
            {
249
0
                nColCount = 0;
250
                //! error message
251
0
            }
252
253
0
            uno::Reference<sdbcx::XRowLocate> xLocate;
254
0
            if ( bBookmarkSelection )
255
0
            {
256
0
                xLocate.set( xRowSet, uno::UNO_QUERY );
257
0
                if ( !xLocate.is() )
258
0
                {
259
0
                    SAL_WARN( "sc.ui","can't get XRowLocate");
260
0
                    bDoSelection = bRealSelection = bBookmarkSelection = false;
261
0
                }
262
0
            }
263
264
0
            uno::Reference<sdbc::XRow> xRow( xRowSet, uno::UNO_QUERY );
265
0
            if ( nColCount > 0 && xRow.is() )
266
0
            {
267
0
                nEndCol = static_cast<SCCOL>( rParam.nCol1 + nColCount - 1 );
268
269
0
                uno::Sequence<sal_Int32> aColTypes( nColCount );    // column types
270
0
                uno::Sequence<sal_Bool> aColCurr( nColCount );      // currency flag is not in types
271
0
                sal_Int32* pTypeArr = aColTypes.getArray();
272
0
                sal_Bool* pCurrArr = aColCurr.getArray();
273
0
                for (tools::Long i=0; i<nColCount; i++)
274
0
                {
275
0
                    pTypeArr[i] = xMeta->getColumnType( i+1 );
276
0
                    pCurrArr[i] = xMeta->isCurrency( i+1 );
277
0
                }
278
279
                // read column names
280
0
                nCol = rParam.nCol1;
281
0
                for (tools::Long i=0; i<nColCount; i++)
282
0
                {
283
0
                    pImportDoc->SetString( nCol, nRow, nTab,
284
0
                                            xMeta->getColumnLabel( i+1 ) );
285
0
                    ++nCol;
286
0
                }
287
0
                ++nRow;
288
289
0
                bool bEnd = false;
290
0
                if ( !bDoSelection )
291
0
                    xRowSet->beforeFirst();
292
0
                sal_uInt16 nInserted = 0;
293
0
                while ( !bEnd )
294
0
                {
295
                    //  skip rows that are not selected
296
0
                    if ( !bDoSelection )
297
0
                    {
298
0
                        bEnd = !xRowSet->next();
299
0
                        if ( !bEnd )
300
0
                            ++nRowsRead;
301
0
                    }
302
0
                    else
303
0
                    {
304
0
                        if (nListPos < nListCount)
305
0
                        {
306
0
                            if ( bBookmarkSelection )
307
0
                            {
308
0
                                bEnd = !xLocate->moveToBookmark(aSelection[nListPos]);
309
0
                            }
310
0
                            else    // use record numbers
311
0
                            {
312
0
                                sal_Int32 nNextRow = 0;
313
0
                                aSelection[nListPos] >>= nNextRow;
314
0
                                if ( nRowsRead+1 < nNextRow )
315
0
                                    bRealSelection = true;
316
0
                                nRowsRead = nNextRow;
317
0
                                bEnd = !xRowSet->absolute(nRowsRead);
318
0
                            }
319
0
                            ++nListPos;
320
0
                        }
321
0
                        else
322
0
                        {
323
0
                            if ( !bBookmarkSelection && xRowSet->next() )
324
0
                                bRealSelection = true;                      // more data available but not used
325
0
                            bEnd = true;
326
0
                        }
327
0
                    }
328
329
0
                    if ( !bEnd )
330
0
                    {
331
0
                        if ( rDoc.ValidRow(nRow) )
332
0
                        {
333
0
                            nCol = rParam.nCol1;
334
0
                            for (tools::Long i=0; i<nColCount; i++)
335
0
                            {
336
0
                                ScDatabaseDocUtil::PutData( *pImportDoc, nCol, nRow, nTab,
337
0
                                                xRow, i+1, pTypeArr[i], pCurrArr[i] );
338
0
                                ++nCol;
339
0
                            }
340
0
                            nEndRow = nRow;
341
0
                            ++nRow;
342
343
                            //  progress bar
344
345
0
                            ++nInserted;
346
0
                            if (!(nInserted & 15))
347
0
                            {
348
0
                                aProgress.SetState( 0 );
349
0
                            }
350
0
                        }
351
0
                        else        // past the end of the spreadsheet
352
0
                        {
353
0
                            bEnd = true;            // don't continue
354
0
                            bTruncated = true;      // warning flag
355
0
                        }
356
0
                    }
357
0
                }
358
359
0
                bSuccess = true;
360
0
            }
361
362
0
            if ( bDispose )
363
0
                ::comphelper::disposeComponent( xRowSet );
364
0
        }
365
0
    }
366
0
    catch ( const sdbc::SQLException& rError )
367
0
    {
368
0
        aErrorMessage = rError.Message;
369
0
    }
370
0
    catch ( uno::Exception& )
371
0
    {
372
0
        TOOLS_WARN_EXCEPTION( "sc", "Unexpected exception in database");
373
0
    }
374
375
    //  test for cell protection
376
377
0
    bool bKeepFormat = pDBData->IsKeepFmt();
378
0
    bool bMoveCells = pDBData->IsDoSize();
379
0
    SCCOL nFormulaCols = 0; // columns to be filled with formulas
380
0
    if (bMoveCells && nEndCol == rParam.nCol2)
381
0
    {
382
        //  if column count changes, formulas would become invalid anyway
383
        //  -> only set nFormulaCols for unchanged column count
384
385
0
        SCCOL nTestCol = rParam.nCol2 + 1;      // right of the data
386
0
        SCROW nTestRow = rParam.nRow1 + 1;      // below the title row
387
0
        while ( nTestCol <= rDoc.MaxCol() &&
388
0
                rDoc.GetCellType(ScAddress( nTestCol, nTestRow, nTab )) == CELLTYPE_FORMULA )
389
0
        {
390
0
            ++nTestCol;
391
0
            ++nFormulaCols;
392
0
        }
393
0
    }
394
395
0
    if (bSuccess)
396
0
    {
397
        //  old and new range editable?
398
0
        ScEditableTester aTester;
399
0
        aTester.TestBlock( rDoc, nTab, rParam.nCol1,rParam.nRow1,rParam.nCol2,rParam.nRow2 );
400
0
        aTester.TestBlock( rDoc, nTab, rParam.nCol1,rParam.nRow1,nEndCol,nEndRow );
401
0
        if ( !aTester.IsEditable() )
402
0
        {
403
0
            pErrStringId = aTester.GetMessageId();
404
0
            bSuccess = false;
405
0
        }
406
0
        else if ( (pChangeTrack = rDoc.GetChangeTrack()) != nullptr )
407
0
            aChangedRange = ScRange(rParam.nCol1, rParam.nRow1, nTab,
408
0
                        nEndCol+nFormulaCols, nEndRow, nTab );
409
0
    }
410
411
0
    if ( bSuccess && bMoveCells )
412
0
    {
413
0
        ScRange aOld( rParam.nCol1, rParam.nRow1, nTab,
414
0
                        rParam.nCol2+nFormulaCols, rParam.nRow2, nTab );
415
0
        ScRange aNew( rParam.nCol1, rParam.nRow1, nTab,
416
0
                        nEndCol+nFormulaCols, nEndRow, nTab );
417
0
        if (!rDoc.CanFitBlock( aOld, aNew ))
418
0
        {
419
0
            pErrStringId = STR_MSSG_DOSUBTOTALS_2;      // can't insert cells
420
0
            bSuccess = false;
421
0
        }
422
0
    }
423
424
    //  copy data from import doc into real document
425
426
0
    if ( bSuccess )
427
0
    {
428
0
        if (bKeepFormat)
429
0
        {
430
            //  keep formatting of title and first data row from the document
431
            //  CopyToDocument also copies styles, Apply... needs separate calls
432
433
0
            SCCOL nMinEndCol = std::min( rParam.nCol2, nEndCol );    // not too much
434
0
            nMinEndCol = sal::static_int_cast<SCCOL>( nMinEndCol + nFormulaCols );  // only if column count unchanged
435
0
            pImportDoc->DeleteAreaTab( 0,0, rDoc.MaxCol(),rDoc.MaxRow(), nTab, InsertDeleteFlags::ATTRIB );
436
0
            rDoc.CopyToDocument(rParam.nCol1, rParam.nRow1, nTab,
437
0
                                nMinEndCol, rParam.nRow1, nTab,
438
0
                                InsertDeleteFlags::ATTRIB, false, *pImportDoc);
439
440
0
            SCROW nDataStartRow = rParam.nRow1+1;
441
0
            for (SCCOL nCopyCol=rParam.nCol1; nCopyCol<=nMinEndCol; nCopyCol++)
442
0
            {
443
0
                const ScPatternAttr* pSrcPattern = rDoc.GetPattern(
444
0
                                                    nCopyCol, nDataStartRow, nTab );
445
0
                pImportDoc->ApplyPatternAreaTab( nCopyCol, nDataStartRow, nCopyCol, nEndRow,
446
0
                                                    nTab, *pSrcPattern );
447
0
                const ScStyleSheet* pStyle = pSrcPattern->GetStyleSheet();
448
0
                if (pStyle)
449
0
                    pImportDoc->ApplyStyleAreaTab( nCopyCol, nDataStartRow, nCopyCol, nEndRow,
450
0
                                                    nTab, *pStyle );
451
0
            }
452
0
        }
453
454
        //  don't set cell protection attribute if table is protected
455
0
        if (rDoc.IsTabProtected(nTab))
456
0
        {
457
0
            ScPatternAttr aPattern(pImportDoc->getCellAttributeHelper());
458
0
            aPattern.ItemSetPut(ScProtectionAttr(false,false,false,false));
459
0
            pImportDoc->ApplyPatternAreaTab( 0,0,rDoc.MaxCol(),rDoc.MaxRow(), nTab, aPattern );
460
0
        }
461
462
        //  copy old data for undo
463
464
0
        SCCOL nUndoEndCol = std::max( nEndCol, rParam.nCol2 );       // rParam = old end
465
0
        SCROW nUndoEndRow = std::max( nEndRow, rParam.nRow2 );
466
467
0
        ScDocumentUniquePtr pUndoDoc;
468
0
        std::unique_ptr<ScDBData> pUndoDBData;
469
0
        if ( bRecord )
470
0
        {
471
0
            pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
472
0
            pUndoDoc->InitUndo( rDoc, nTab, nTab );
473
474
0
            pUndoDBData.reset(new ScDBData( *pDBData ));
475
0
        }
476
477
0
        ScMarkData aNewMark(rDoc.GetSheetLimits());
478
0
        aNewMark.SelectOneTable( nTab );
479
480
0
        if (bRecord)
481
0
        {
482
            // do not touch notes (ScUndoImportData does not support drawing undo)
483
0
            InsertDeleteFlags nCopyFlags = InsertDeleteFlags::ALL & ~InsertDeleteFlags::NOTE;
484
485
            //  nFormulaCols is set only if column count is unchanged
486
0
            rDoc.CopyToDocument(rParam.nCol1, rParam.nRow1, nTab,
487
0
                                nEndCol+nFormulaCols, nEndRow, nTab,
488
0
                                nCopyFlags, false, *pUndoDoc);
489
0
            if ( rParam.nCol2 > nEndCol )
490
0
                rDoc.CopyToDocument(nEndCol+1, rParam.nRow1, nTab,
491
0
                                    nUndoEndCol, nUndoEndRow, nTab,
492
0
                                    nCopyFlags, false, *pUndoDoc);
493
0
            if ( rParam.nRow2 > nEndRow )
494
0
                rDoc.CopyToDocument(rParam.nCol1, nEndRow+1, nTab,
495
0
                                    nUndoEndCol+nFormulaCols, nUndoEndRow, nTab,
496
0
                                    nCopyFlags, false, *pUndoDoc);
497
0
        }
498
499
        //  move new data
500
501
0
        if (bMoveCells)
502
0
        {
503
            //  clear only the range without the formulas,
504
            //  so the formula title and first row are preserved
505
506
0
            ScRange aDelRange( rParam.nCol1, rParam.nRow1, nTab,
507
0
                                rParam.nCol2, rParam.nRow2, nTab );
508
0
            rDoc.DeleteAreaTab( aDelRange, InsertDeleteFlags::ALL & ~InsertDeleteFlags::NOTE );  // without the formulas
509
510
0
            ScRange aOld( rParam.nCol1, rParam.nRow1, nTab,
511
0
                            rParam.nCol2+nFormulaCols, rParam.nRow2, nTab );
512
0
            ScRange aNew( rParam.nCol1, rParam.nRow1, nTab,
513
0
                            nEndCol+nFormulaCols, nEndRow, nTab );
514
0
            rDoc.FitBlock( aOld, aNew, false );        // Do not delete formulas
515
0
        }
516
0
        else if ( nEndCol < rParam.nCol2 )      // DeleteArea calls PutInOrder
517
0
            rDoc.DeleteArea( nEndCol+1, rParam.nRow1, rParam.nCol2, rParam.nRow2,
518
0
                                aNewMark, InsertDeleteFlags::CONTENTS & ~InsertDeleteFlags::NOTE );
519
520
        //  CopyToDocument doesn't remove contents
521
0
        rDoc.DeleteAreaTab( rParam.nCol1, rParam.nRow1, nEndCol, nEndRow, nTab, InsertDeleteFlags::CONTENTS & ~InsertDeleteFlags::NOTE );
522
523
        //  remove each column from ImportDoc after copying to reduce memory usage
524
0
        bool bOldAutoCalc = rDoc.GetAutoCalc();
525
0
        rDoc.SetAutoCalc( false );             // outside of the loop
526
0
        for (SCCOL nCopyCol = rParam.nCol1; nCopyCol <= nEndCol; nCopyCol++)
527
0
        {
528
0
            pImportDoc->CopyToDocument(nCopyCol, rParam.nRow1, nTab, nCopyCol, nEndRow, nTab,
529
0
                                       InsertDeleteFlags::ALL, false, rDoc);
530
0
            pImportDoc->DeleteAreaTab( nCopyCol, rParam.nRow1, nCopyCol, nEndRow, nTab, InsertDeleteFlags::CONTENTS );
531
0
        }
532
0
        rDoc.SetAutoCalc( bOldAutoCalc );
533
534
0
        if (nFormulaCols > 0)               // copy formulas
535
0
        {
536
0
            if (bKeepFormat)            // formats for formulas
537
0
                pImportDoc->CopyToDocument(nEndCol+1, rParam.nRow1, nTab,
538
0
                                           nEndCol+nFormulaCols, nEndRow, nTab,
539
0
                                           InsertDeleteFlags::ATTRIB, false, rDoc);
540
            // fill formulas
541
0
            ScMarkData aMark(rDoc.GetSheetLimits());
542
0
            aMark.SelectOneTable(nTab);
543
544
0
            sal_uLong nProgCount = nFormulaCols;
545
0
            nProgCount *= nEndRow-rParam.nRow1-1;
546
0
            ScProgress aProgress( rDoc.GetDocumentShell(),
547
0
                    ScResId(STR_FILL_SERIES_PROGRESS), nProgCount, true );
548
549
0
            rDoc.Fill( nEndCol+1, rParam.nRow1+1, nEndCol+nFormulaCols, rParam.nRow1+1,
550
0
                            &aProgress, aMark, nEndRow-rParam.nRow1-1, FILL_TO_BOTTOM, FILL_SIMPLE );
551
0
        }
552
553
        //  if new range is smaller, clear old contents
554
555
0
        if (!bMoveCells)        // move has happened above
556
0
        {
557
0
            if ( rParam.nCol2 > nEndCol )
558
0
                rDoc.DeleteArea( nEndCol+1, rParam.nRow1, rParam.nCol2, rParam.nRow2,
559
0
                                    aNewMark, InsertDeleteFlags::CONTENTS );
560
0
            if ( rParam.nRow2 > nEndRow )
561
0
                rDoc.DeleteArea( rParam.nCol1, nEndRow+1, rParam.nCol2, rParam.nRow2,
562
0
                                    aNewMark, InsertDeleteFlags::CONTENTS );
563
0
        }
564
565
566
        // tdf#117436 - adjust row height to accommodate potential multiline cells
567
0
        rDoc.GetDocumentShell()->AdjustRowHeight(rParam.nRow1, nEndRow, nTab);
568
569
        // update database range
570
0
        pDBData->SetImportParam( rParam );
571
0
        pDBData->SetHeader( true );
572
0
        pDBData->SetByRow( true );
573
0
        pDBData->SetArea( nTab, rParam.nCol1,rParam.nRow1, nEndCol,nEndRow );
574
0
        pDBData->SetImportSelection( bRealSelection );
575
0
        rDoc.CompileDBFormula();
576
577
0
        if (bRecord)
578
0
        {
579
0
            ScDocumentUniquePtr pRedoDoc = std::move(pImportDoc);
580
581
0
            if (nFormulaCols > 0)                   // include filled formulas for redo
582
0
                rDoc.CopyToDocument(rParam.nCol1, rParam.nRow1, nTab,
583
0
                                    nEndCol+nFormulaCols, nEndRow, nTab,
584
0
                                    InsertDeleteFlags::ALL & ~InsertDeleteFlags::NOTE, false, *pRedoDoc);
585
586
0
            std::unique_ptr<ScDBData> pRedoDBData(new ScDBData(*pDBData));
587
588
0
            rDocShell.GetUndoManager()->AddUndoAction(
589
0
                std::make_unique<ScUndoImportData>( rDocShell, nTab,
590
0
                                        rParam, nUndoEndCol, nUndoEndRow,
591
0
                                        nFormulaCols,
592
0
                                        std::move(pUndoDoc), std::move(pRedoDoc),
593
0
                                        std::move(pUndoDBData), std::move(pRedoDBData) ) );
594
0
        }
595
596
0
        sc::SetFormulaDirtyContext aCxt;
597
0
        rDoc.SetAllFormulasDirty(aCxt);
598
0
        rDocShell.PostPaint(ScRange(0, 0, nTab, rDoc.MaxCol(), rDoc.MaxRow(), nTab), PaintPartFlags::Grid);
599
0
        aModificator.SetDocumentModified();
600
601
0
        ScDBRangeRefreshedHint aHint( rParam );
602
0
        rDoc.BroadcastUno( aHint );
603
604
0
        xWaitWin.reset();
605
606
0
        if ( bTruncated )          // show warning
607
0
            ErrorHandler::HandleError(SCWARN_IMPORT_RANGE_OVERFLOW);
608
0
    }
609
0
    else
610
0
    {
611
0
        xWaitWin.reset();
612
613
0
        if (aErrorMessage.isEmpty())
614
0
        {
615
0
            if (!pErrStringId)
616
0
                pErrStringId = STR_MSSG_IMPORTDATA_0;
617
0
            aErrorMessage = ScResId(pErrStringId);
618
0
        }
619
620
0
        std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(),
621
0
                                                      VclMessageType::Info, VclButtonsType::Ok,
622
0
                                                      aErrorMessage));
623
0
        xInfoBox->run();
624
0
    }
625
626
0
    pImportDoc.reset();
627
628
0
    if (bSuccess && pChangeTrack)
629
0
        pChangeTrack->AppendInsert ( aChangedRange );
630
631
0
    return bSuccess;
632
0
}
633
634
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */