Coverage Report

Created: 2026-08-14 10:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sc/source/ui/docshell/docfunc.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 <svx/TableAutoFmt.hxx>
21
#include <scitems.hxx>
22
23
#include <comphelper/lok.hxx>
24
#include <o3tl/safeint.hxx>
25
#include <o3tl/string_view.hxx>
26
#include <sfx2/app.hxx>
27
#include <editeng/editobj.hxx>
28
#include <editeng/justifyitem.hxx>
29
#include <sfx2/linkmgr.hxx>
30
#include <sfx2/bindings.hxx>
31
#include <utility>
32
#include <vcl/weld/MessageDialog.hxx>
33
#include <vcl/weld/WaitObject.hxx>
34
#include <vcl/stdtext.hxx>
35
#include <vcl/svapp.hxx>
36
#include <svx/svdocapt.hxx>
37
#include <sal/log.hxx>
38
#include <unotools/charclass.hxx>
39
#include <osl/diagnose.h>
40
41
#include <com/sun/star/container/XNameContainer.hpp>
42
#include <com/sun/star/script/ModuleType.hpp>
43
#include <com/sun/star/script/XLibraryContainer.hpp>
44
#include <com/sun/star/script/vba/XVBAModuleInfo.hpp>
45
46
#include <docfunc.hxx>
47
48
#include <sc.hrc>
49
#include <strings.hrc>
50
51
#include <arealink.hxx>
52
#include <attrib.hxx>
53
#include <dociter.hxx>
54
#include <autoform.hxx>
55
#include <formulacell.hxx>
56
#include <cellmergeoption.hxx>
57
#include <detdata.hxx>
58
#include <detfunc.hxx>
59
#include <docpool.hxx>
60
#include <docsh.hxx>
61
#include <drwlayer.hxx>
62
#include <editutil.hxx>
63
#include <globstr.hrc>
64
#include <olinetab.hxx>
65
#include <patattr.hxx>
66
#include <rangenam.hxx>
67
#include <refundo.hxx>
68
#include <scresid.hxx>
69
#include <stlpool.hxx>
70
#include <stlsheet.hxx>
71
#include <tablink.hxx>
72
#include <tabvwsh.hxx>
73
#include <uiitems.hxx>
74
#include <undoblk.hxx>
75
#include <undocell.hxx>
76
#include <undodraw.hxx>
77
#include <undotab.hxx>
78
#include <sizedev.hxx>
79
#include <scmod.hxx>
80
#include <inputhdl.hxx>
81
#include <editable.hxx>
82
#include <compiler.hxx>
83
#include <scui_def.hxx>
84
#include <tabprotection.hxx>
85
#include <clipparam.hxx>
86
#include <externalrefmgr.hxx>
87
#include <undorangename.hxx>
88
#include <progress.hxx>
89
#include <dpobject.hxx>
90
#include <stringutil.hxx>
91
#include <cellvalue.hxx>
92
#include <tokenarray.hxx>
93
#include <rowheightcontext.hxx>
94
#include <cellvalues.hxx>
95
#include <undoconvert.hxx>
96
#include <docfuncutil.hxx>
97
#include <sheetevents.hxx>
98
#include <conditio.hxx>
99
#include <columnspanset.hxx>
100
#include <validat.hxx>
101
#include <SparklineGroup.hxx>
102
#include <SparklineAttributes.hxx>
103
#include <SheetViewOperationsTester.hxx>
104
#include <config_features.h>
105
106
#include <memory>
107
#include <operation/OperationType.hxx>
108
#include <operation/DeleteContentOperation.hxx>
109
#include <operation/DeleteSparklineGroupOperation.hxx>
110
#include <operation/DeleteSparklineOperation.hxx>
111
#include <operation/DeleteCellOperation.hxx>
112
#include <operation/DeleteCellsOperation.hxx>
113
#include <operation/InsertThreadedCommentOperation.hxx>
114
#include <operation/SetNormalStringOperation.hxx>
115
#include <operation/SetValueOperation.hxx>
116
#include <operation/SetStringOperation.hxx>
117
#include <operation/SetFormulaOperation.hxx>
118
#include <operation/SetEditTextOperation.hxx>
119
#include <operation/ApplyAttributesOperation.hxx>
120
#include <operation/AutoFormatOperation.hxx>
121
#include <operation/ChangeIndentOperation.hxx>
122
#include <operation/ChangeSparklineGroupAttributesOperation.hxx>
123
#include <operation/ChangeSparklineOperation.hxx>
124
#include <operation/ClearItemsOperation.hxx>
125
#include <operation/ConvertFormulaToValueOperation.hxx>
126
#include <operation/EnterMatrixOperation.hxx>
127
#include <operation/FillAutoOperation.hxx>
128
#include <operation/FillSeriesOperation.hxx>
129
#include <operation/FillSimpleOperation.hxx>
130
#include <operation/GroupSparklinesOperation.hxx>
131
#include <operation/InsertCellsOperation.hxx>
132
#include <operation/InsertNameListOperation.hxx>
133
#include <operation/InsertSheetViewOperation.hxx>
134
#include <operation/InsertSparklinesOperation.hxx>
135
#include <operation/MergeCellsOperation.hxx>
136
#include <operation/MoveBlockOperation.hxx>
137
#include <operation/MultipleOpsOperation.hxx>
138
#include <operation/ReplaceNoteTextOperation.hxx>
139
#include <operation/SetNoteTextOperation.hxx>
140
#include <operation/TransliterateTextOperation.hxx>
141
#include <operation/UngroupSparklinesOperation.hxx>
142
#include <basic/basmgr.hxx>
143
#include <set>
144
#include <vector>
145
#include <sfx2/viewfrm.hxx>
146
147
using namespace com::sun::star;
148
149
void ScDocFunc::NotifyDrawUndo( std::unique_ptr<SdrUndoAction> pUndoAction)
150
0
{
151
    // #i101118# if drawing layer collects the undo actions, add it there
152
0
    ScDrawLayer* pDrawLayer = rDocShell.GetDocument().GetDrawLayer();
153
0
    if( pDrawLayer && pDrawLayer->IsRecording() )
154
0
        pDrawLayer->AddCalcUndo( std::move(pUndoAction) );
155
0
    else
156
0
        rDocShell.GetUndoManager()->AddUndoAction( std::make_unique<ScUndoDraw>( std::move(pUndoAction), rDocShell ) );
157
0
    rDocShell.SetDrawModified();
158
159
    // Sync sheet views for standalone drawing modifications.
160
    // Draw operations always target the default view's page, so
161
    // just sync the default view to the sheet views.
162
0
    if (!pDrawLayer || !pDrawLayer->IsRecording())
163
0
    {
164
0
        ScViewData* pViewData = ScDocShell::GetViewData();
165
0
        if (pViewData)
166
0
        {
167
0
            ScDocument& rDoc = rDocShell.GetDocument();
168
0
            SCTAB nCurrentTab = pViewData->GetTabNumber();
169
0
            SCTAB nDefaultTab = rDoc.GetDefaultViewTableNumber(nCurrentTab);
170
0
            rDoc.SyncSheetViews(nDefaultTab);
171
0
        }
172
0
    }
173
174
    // the affected sheet isn't known, so all stream positions are invalidated
175
0
    ScDocument& rDoc = rDocShell.GetDocument();
176
0
    SCTAB nTabCount = rDoc.GetTableCount();
177
0
    for (SCTAB nTab=0; nTab<nTabCount; nTab++)
178
0
        rDoc.SetStreamValid(nTab, false);
179
0
}
180
181
//  paint row above the range (because of lines after AdjustRowHeight)
182
183
void ScDocFunc::PaintAbove(ScDocShell& rDocShell, const ScRange& rRange)
184
0
{
185
0
    SCROW nRow = rRange.aStart.Row();
186
0
    if ( nRow > 0 )
187
0
    {
188
0
        SCTAB nTab = rRange.aStart.Tab();   //! all of them?
189
0
        --nRow;
190
0
        ScDocument& rDoc = rDocShell.GetDocument();
191
0
        rDocShell.PostPaint( ScRange(0,nRow,nTab,rDoc.MaxCol(),nRow,nTab), PaintPartFlags::Grid );
192
0
    }
193
0
}
194
195
bool ScDocFunc::AdjustRowHeight( const ScRange& rRange, bool bPaint, bool bApi )
196
1.83k
{
197
1.83k
    ScDocument& rDoc = rDocShell.GetDocument();
198
1.83k
    SfxViewShell* pSomeViewForThisDoc = rDocShell.GetBestViewShell(false);
199
1.83k
    if ( rDoc.IsImportingXML() )
200
797
    {
201
        //  for XML import, all row heights are updated together after importing
202
797
        return false;
203
797
    }
204
1.03k
    if ( rDoc.IsAdjustHeightLocked() )
205
1.03k
    {
206
1.03k
        return false;
207
1.03k
    }
208
209
0
    SCTAB nTab      = rRange.aStart.Tab();
210
0
    SCROW nStartRow = rRange.aStart.Row();
211
0
    SCROW nEndRow   = rRange.aEnd.Row();
212
213
0
    ScSizeDeviceProvider aProv( rDocShell );
214
0
    double fOne(1.0);
215
216
0
    sc::RowHeightContext aCxt(rDoc.MaxRow(), aProv.GetPPTX(), aProv.GetPPTY(), fOne, fOne, aProv.GetDevice());
217
0
    bool bChanged = rDoc.SetOptimalHeight(aCxt, nStartRow, nEndRow, nTab, bApi);
218
    // tdf#76183: recalculate objects' positions
219
0
    if (bChanged)
220
0
    {
221
0
        if (comphelper::LibreOfficeKit::isActive())
222
0
        {
223
0
            SfxViewShell* pViewShell = SfxViewShell::GetFirst();
224
0
            while (pViewShell)
225
0
            {
226
0
                ScTabViewShell* pTabViewShell = dynamic_cast<ScTabViewShell*>(pViewShell);
227
0
                if (pTabViewShell && pSomeViewForThisDoc && pTabViewShell->GetDocId() == pSomeViewForThisDoc->GetDocId())
228
0
                {
229
0
                    if (ScPositionHelper* pPosHelper = pTabViewShell->GetViewData().GetLOKHeightHelper(nTab))
230
0
                        pPosHelper->invalidateByIndex(nStartRow);
231
0
                }
232
0
                pViewShell = SfxViewShell::GetNext(*pViewShell);
233
0
            }
234
0
        }
235
0
        rDoc.SetDrawPageSize(nTab);
236
0
    }
237
238
0
    if ( bPaint && bChanged )
239
0
        rDocShell.PostPaint(ScRange(0, nStartRow, nTab, rDoc.MaxCol(), rDoc.MaxRow(), nTab),
240
0
                            PaintPartFlags::Grid | PaintPartFlags::Left);
241
242
0
    if (comphelper::LibreOfficeKit::isActive())
243
0
    {
244
0
        ScTabViewShell::notifyAllViewsHeaderInvalidation(pSomeViewForThisDoc, ROW_HEADER, nTab);
245
0
        ScTabViewShell::notifyAllViewsSheetGeomInvalidation(
246
0
            pSomeViewForThisDoc, false /* bColumns */, true /* bRows */, true /* bSizes*/,
247
0
            false /* bHidden */, false /* bFiltered */, false /* bGroups */, nTab);
248
0
    }
249
250
0
    return bChanged;
251
1.03k
}
252
253
bool ScDocFunc::DetectiveAddPred(const ScAddress& rPos)
254
0
{
255
0
    ScDocShellModificator aModificator( rDocShell );
256
257
0
    rDocShell.MakeDrawLayer();
258
0
    ScDocument& rDoc = rDocShell.GetDocument();
259
0
    bool bUndo (rDoc.IsUndoEnabled());
260
0
    ScDrawLayer* pModel = rDoc.GetDrawLayer();
261
0
    SCCOL nCol = rPos.Col();
262
0
    SCROW nRow = rPos.Row();
263
0
    SCTAB nTab = rPos.Tab();
264
265
0
    if (bUndo)
266
0
        pModel->BeginCalcUndo(false);
267
0
    bool bDone = ScDetectiveFunc(rDoc, nTab).ShowPred( nCol, nRow );
268
0
    std::unique_ptr<SdrUndoGroup> pUndo;
269
0
    if (bUndo)
270
0
        pUndo = pModel->GetCalcUndo();
271
0
    if (bDone)
272
0
    {
273
0
        ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_ADDPRED );
274
0
        rDoc.AddDetectiveOperation( aOperation );
275
0
        if (bUndo)
276
0
        {
277
0
            rDocShell.GetUndoManager()->AddUndoAction(
278
0
                        std::make_unique<ScUndoDetective>( rDocShell, std::move(pUndo), &aOperation ) );
279
0
        }
280
0
        aModificator.SetDocumentModified();
281
0
        SfxBindings* pBindings = rDocShell.GetViewBindings();
282
0
        if (pBindings)
283
0
            pBindings->Invalidate( SID_DETECTIVE_REFRESH );
284
0
    }
285
286
0
    return bDone;
287
0
}
288
289
bool ScDocFunc::DetectiveDelPred(const ScAddress& rPos)
290
0
{
291
0
    ScDocument& rDoc = rDocShell.GetDocument();
292
293
0
    bool bUndo(rDoc.IsUndoEnabled());
294
0
    ScDrawLayer* pModel = rDoc.GetDrawLayer();
295
0
    if (!pModel)
296
0
        return false;
297
298
0
    ScDocShellModificator aModificator( rDocShell );
299
300
0
    SCCOL nCol = rPos.Col();
301
0
    SCROW nRow = rPos.Row();
302
0
    SCTAB nTab = rPos.Tab();
303
304
0
    if (bUndo)
305
0
        pModel->BeginCalcUndo(false);
306
0
    bool bDone = ScDetectiveFunc(rDoc, nTab).DeletePred( nCol, nRow );
307
0
    std::unique_ptr<SdrUndoGroup> pUndo;
308
0
    if (bUndo)
309
0
        pUndo = pModel->GetCalcUndo();
310
0
    if (bDone)
311
0
    {
312
0
        ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_DELPRED );
313
0
        rDoc.AddDetectiveOperation( aOperation );
314
0
        if (bUndo)
315
0
        {
316
0
            rDocShell.GetUndoManager()->AddUndoAction(
317
0
                        std::make_unique<ScUndoDetective>( rDocShell, std::move(pUndo), &aOperation ) );
318
0
        }
319
0
        aModificator.SetDocumentModified();
320
0
        SfxBindings* pBindings = rDocShell.GetViewBindings();
321
0
        if (pBindings)
322
0
            pBindings->Invalidate( SID_DETECTIVE_REFRESH );
323
0
    }
324
325
0
    return bDone;
326
0
}
327
328
bool ScDocFunc::DetectiveAddSucc(const ScAddress& rPos)
329
0
{
330
0
    ScDocShellModificator aModificator( rDocShell );
331
332
0
    rDocShell.MakeDrawLayer();
333
0
    ScDocument& rDoc = rDocShell.GetDocument();
334
335
0
    bool bUndo(rDoc.IsUndoEnabled());
336
0
    ScDrawLayer* pModel = rDoc.GetDrawLayer();
337
0
    SCCOL nCol = rPos.Col();
338
0
    SCROW nRow = rPos.Row();
339
0
    SCTAB nTab = rPos.Tab();
340
341
0
    if (bUndo)
342
0
        pModel->BeginCalcUndo(false);
343
0
    bool bDone = ScDetectiveFunc(rDoc, nTab).ShowSucc( nCol, nRow );
344
0
    std::unique_ptr<SdrUndoGroup> pUndo;
345
0
    if (bUndo)
346
0
        pUndo = pModel->GetCalcUndo();
347
0
    if (bDone)
348
0
    {
349
0
        ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_ADDSUCC );
350
0
        rDoc.AddDetectiveOperation( aOperation );
351
0
        if (bUndo)
352
0
        {
353
0
            rDocShell.GetUndoManager()->AddUndoAction(
354
0
                        std::make_unique<ScUndoDetective>( rDocShell, std::move(pUndo), &aOperation ) );
355
0
        }
356
0
        aModificator.SetDocumentModified();
357
0
        SfxBindings* pBindings = rDocShell.GetViewBindings();
358
0
        if (pBindings)
359
0
            pBindings->Invalidate( SID_DETECTIVE_REFRESH );
360
0
    }
361
362
0
    return bDone;
363
0
}
364
365
bool ScDocFunc::DetectiveDelSucc(const ScAddress& rPos)
366
0
{
367
0
    ScDocument& rDoc = rDocShell.GetDocument();
368
369
0
    bool bUndo (rDoc.IsUndoEnabled());
370
0
    ScDrawLayer* pModel = rDoc.GetDrawLayer();
371
0
    if (!pModel)
372
0
        return false;
373
374
0
    ScDocShellModificator aModificator( rDocShell );
375
376
0
    SCCOL nCol = rPos.Col();
377
0
    SCROW nRow = rPos.Row();
378
0
    SCTAB nTab = rPos.Tab();
379
380
0
    if (bUndo)
381
0
        pModel->BeginCalcUndo(false);
382
0
    bool bDone = ScDetectiveFunc(rDoc, nTab).DeleteSucc( nCol, nRow );
383
0
    std::unique_ptr<SdrUndoGroup> pUndo;
384
0
    if (bUndo)
385
0
        pUndo = pModel->GetCalcUndo();
386
0
    if (bDone)
387
0
    {
388
0
        ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_DELSUCC );
389
0
        rDoc.AddDetectiveOperation( aOperation );
390
0
        if (bUndo)
391
0
        {
392
0
            rDocShell.GetUndoManager()->AddUndoAction(
393
0
                        std::make_unique<ScUndoDetective>( rDocShell, std::move(pUndo), &aOperation ) );
394
0
        }
395
0
        aModificator.SetDocumentModified();
396
0
        SfxBindings* pBindings = rDocShell.GetViewBindings();
397
0
        if (pBindings)
398
0
            pBindings->Invalidate( SID_DETECTIVE_REFRESH );
399
0
    }
400
401
0
    return bDone;
402
0
}
403
404
bool ScDocFunc::DetectiveAddError(const ScAddress& rPos)
405
0
{
406
0
    ScDocShellModificator aModificator( rDocShell );
407
408
0
    rDocShell.MakeDrawLayer();
409
0
    ScDocument& rDoc = rDocShell.GetDocument();
410
411
0
    bool bUndo (rDoc.IsUndoEnabled());
412
0
    ScDrawLayer* pModel = rDoc.GetDrawLayer();
413
0
    SCCOL nCol = rPos.Col();
414
0
    SCROW nRow = rPos.Row();
415
0
    SCTAB nTab = rPos.Tab();
416
417
0
    if (bUndo)
418
0
        pModel->BeginCalcUndo(false);
419
0
    bool bDone = ScDetectiveFunc(rDoc, nTab).ShowError( nCol, nRow );
420
0
    std::unique_ptr<SdrUndoGroup> pUndo;
421
0
    if (bUndo)
422
0
        pUndo = pModel->GetCalcUndo();
423
0
    if (bDone)
424
0
    {
425
0
        ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_ADDERROR );
426
0
        rDoc.AddDetectiveOperation( aOperation );
427
0
        if (bUndo)
428
0
        {
429
0
            rDocShell.GetUndoManager()->AddUndoAction(
430
0
                        std::make_unique<ScUndoDetective>( rDocShell, std::move(pUndo), &aOperation ) );
431
0
        }
432
0
        aModificator.SetDocumentModified();
433
0
        SfxBindings* pBindings = rDocShell.GetViewBindings();
434
0
        if (pBindings)
435
0
            pBindings->Invalidate( SID_DETECTIVE_REFRESH );
436
0
    }
437
438
0
    return bDone;
439
0
}
440
441
bool ScDocFunc::DetectiveMarkInvalid(SCTAB nTab)
442
0
{
443
0
    ScDocShellModificator aModificator( rDocShell );
444
445
0
    rDocShell.MakeDrawLayer();
446
0
    ScDocument& rDoc = rDocShell.GetDocument();
447
448
0
    bool bUndo (rDoc.IsUndoEnabled());
449
0
    ScDrawLayer* pModel = rDoc.GetDrawLayer();
450
451
0
    std::unique_ptr<weld::WaitObject> xWaitWin(new weld::WaitObject(ScDocShell::GetActiveDialogParent()));
452
0
    if (bUndo)
453
0
        pModel->BeginCalcUndo(false);
454
0
    bool bOverflow;
455
0
    bool bDone = ScDetectiveFunc(rDoc, nTab).MarkInvalid( bOverflow );
456
0
    std::unique_ptr<SdrUndoGroup> pUndo;
457
0
    if (bUndo)
458
0
        pUndo = pModel->GetCalcUndo();
459
0
    xWaitWin.reset();
460
0
    if (bDone)
461
0
    {
462
0
        if (pUndo && bUndo)
463
0
        {
464
0
            pUndo->SetComment( ScResId( STR_UNDO_DETINVALID ) );
465
0
            rDocShell.GetUndoManager()->AddUndoAction( std::move(pUndo) );
466
0
        }
467
0
        aModificator.SetDocumentModified();
468
0
        if ( bOverflow )
469
0
        {
470
0
            std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(nullptr,
471
0
                                                          VclMessageType::Info, VclButtonsType::Ok,
472
0
                                                          ScResId(STR_DETINVALID_OVERFLOW)));
473
0
            xInfoBox->run();
474
0
        }
475
0
    }
476
477
0
    return bDone;
478
0
}
479
480
bool ScDocFunc::DetectiveDelAll(SCTAB nTab)
481
0
{
482
0
    ScDocument& rDoc = rDocShell.GetDocument();
483
484
0
    bool bUndo (rDoc.IsUndoEnabled());
485
0
    ScDrawLayer* pModel = rDoc.GetDrawLayer();
486
0
    if (!pModel)
487
0
        return false;
488
489
0
    ScDocShellModificator aModificator( rDocShell );
490
491
0
    if (bUndo)
492
0
        pModel->BeginCalcUndo(false);
493
0
    bool bDone = ScDetectiveFunc(rDoc, nTab).DeleteAll( ScDetectiveDelete::Detective );
494
0
    std::unique_ptr<SdrUndoGroup> pUndo;
495
0
    if (bUndo)
496
0
        pUndo = pModel->GetCalcUndo();
497
0
    if (bDone)
498
0
    {
499
0
        ScDetOpList* pOldList = rDoc.GetDetOpList();
500
0
        std::unique_ptr<ScDetOpList> pUndoList;
501
0
        if (bUndo && pOldList)
502
0
            pUndoList.reset(new ScDetOpList(*pOldList));
503
504
0
        rDoc.ClearDetectiveOperations();
505
506
0
        if (bUndo)
507
0
        {
508
0
            rDocShell.GetUndoManager()->AddUndoAction(
509
0
                        std::make_unique<ScUndoDetective>( rDocShell, std::move(pUndo), nullptr, std::move(pUndoList) ) );
510
0
        }
511
0
        aModificator.SetDocumentModified();
512
0
        SfxBindings* pBindings = rDocShell.GetViewBindings();
513
0
        if (pBindings)
514
0
            pBindings->Invalidate( SID_DETECTIVE_REFRESH );
515
0
    }
516
517
0
    return bDone;
518
0
}
519
520
bool ScDocFunc::DetectiveRefresh( bool bAutomatic )
521
7.05k
{
522
7.05k
    bool bDone = false;
523
7.05k
    ScDocument& rDoc = rDocShell.GetDocument();
524
525
7.05k
    ScDetOpList* pList = rDoc.GetDetOpList();
526
7.05k
    if ( pList && pList->Count() )
527
0
    {
528
0
        rDocShell.MakeDrawLayer();
529
0
        ScDrawLayer* pModel = rDoc.GetDrawLayer();
530
0
        const bool bUndo (rDoc.IsUndoEnabled());
531
0
        if (bUndo)
532
0
            pModel->BeginCalcUndo(false);
533
534
        //  Delete in all sheets
535
536
0
        SCTAB nTabCount = rDoc.GetTableCount();
537
0
        for (SCTAB nTab=0; nTab<nTabCount; nTab++)
538
0
            ScDetectiveFunc( rDoc,nTab ).DeleteAll( ScDetectiveDelete::Arrows );    // don't remove circles
539
540
        //  repeat
541
542
0
        size_t nCount = pList->Count();
543
0
        for (size_t i=0; i < nCount; ++i)
544
0
        {
545
0
            const ScDetOpData& rData = pList->GetObject(i);
546
0
            const ScAddress& aPos = rData.GetPos();
547
0
            ScDetectiveFunc aFunc( rDoc, aPos.Tab() );
548
0
            SCCOL nCol = aPos.Col();
549
0
            SCROW nRow = aPos.Row();
550
0
            switch (rData.GetOperation())
551
0
            {
552
0
                case SCDETOP_ADDSUCC:
553
0
                    aFunc.ShowSucc( nCol, nRow );
554
0
                    break;
555
0
                case SCDETOP_DELSUCC:
556
0
                    aFunc.DeleteSucc( nCol, nRow );
557
0
                    break;
558
0
                case SCDETOP_ADDPRED:
559
0
                     aFunc.ShowPred( nCol, nRow );
560
0
                     break;
561
0
                case SCDETOP_DELPRED:
562
0
                    aFunc.DeletePred( nCol, nRow );
563
0
                    break;
564
0
                case SCDETOP_ADDERROR:
565
0
                    aFunc.ShowError( nCol, nRow );
566
0
                    break;
567
0
                default:
568
0
                    OSL_FAIL("wrong operation in DetectiveRefresh");
569
0
            }
570
0
        }
571
572
0
        if (bUndo)
573
0
        {
574
0
            std::unique_ptr<SdrUndoGroup> pUndo = pModel->GetCalcUndo();
575
0
            if (pUndo)
576
0
            {
577
0
                pUndo->SetComment( ScResId( STR_UNDO_DETREFRESH ) );
578
                // associate with the last action
579
0
                rDocShell.GetUndoManager()->AddUndoAction(
580
0
                                                std::make_unique<ScUndoDraw>( std::move(pUndo), rDocShell ),
581
0
                                                    bAutomatic );
582
0
            }
583
0
        }
584
0
        rDocShell.SetDrawModified();
585
0
        bDone = true;
586
0
    }
587
7.05k
    return bDone;
588
7.05k
}
589
590
static void lcl_collectAllPredOrSuccRanges(
591
    const ScRangeList& rSrcRanges, std::vector<ScTokenRef>& rRefTokens, ScDocShell& rDocShell,
592
    bool bPred)
593
0
{
594
0
    ScDocument& rDoc = rDocShell.GetDocument();
595
0
    std::vector<ScTokenRef> aRefTokens;
596
0
    if (rSrcRanges.empty())
597
0
        return;
598
0
    ScRange const & rFrontRange = rSrcRanges.front();
599
0
    ScDetectiveFunc aDetFunc(rDoc, rFrontRange.aStart.Tab());
600
0
    for (ScRange const & r : rSrcRanges)
601
0
    {
602
0
        if (bPred)
603
0
        {
604
0
            aDetFunc.GetAllPreds(
605
0
                r.aStart.Col(), r.aStart.Row(), r.aEnd.Col(), r.aEnd.Row(), aRefTokens);
606
0
        }
607
0
        else
608
0
        {
609
0
            aDetFunc.GetAllSuccs(
610
0
                r.aStart.Col(), r.aStart.Row(), r.aEnd.Col(), r.aEnd.Row(), aRefTokens);
611
0
        }
612
0
    }
613
0
    rRefTokens.swap(aRefTokens);
614
0
}
615
616
void ScDocFunc::DetectiveCollectAllPreds(const ScRangeList& rSrcRanges, std::vector<ScTokenRef>& rRefTokens)
617
0
{
618
0
    lcl_collectAllPredOrSuccRanges(rSrcRanges, rRefTokens, rDocShell, true);
619
0
}
620
621
void ScDocFunc::DetectiveCollectAllSuccs(const ScRangeList& rSrcRanges, std::vector<ScTokenRef>& rRefTokens)
622
0
{
623
0
    lcl_collectAllPredOrSuccRanges(rSrcRanges, rRefTokens, rDocShell, false);
624
0
}
625
626
bool ScDocFunc::DeleteContents(const ScMarkData& rMark, InsertDeleteFlags nFlags, bool bRecord, bool bApi)
627
285
{
628
285
    sc::DeleteContentOperation aOperation(*this, rDocShell, rMark, nFlags, bRecord, bApi);
629
285
    return aOperation.run();
630
285
}
631
632
tools::Long ScDocShell::GetTwipWidthHint(const ScAddress& rPos)
633
0
{
634
0
    ScViewData* pViewData = GetViewData();
635
0
    if (!pViewData)
636
0
        return -1;
637
638
0
    ScSizeDeviceProvider aProv(*this);
639
0
    double fZoomX, fZoomY;
640
0
    double nPPTX, nPPTY;
641
0
    pViewData->setupSizeDeviceProviderForColWidth(aProv, fZoomX, fZoomY, nPPTX, nPPTY);
642
643
0
    ScDocument& rDoc = GetDocument();
644
0
    tools::Long nWidth = rDoc.GetNeededSize(rPos.Col(), rPos.Row(), rPos.Tab(), aProv.GetDevice(),
645
0
                                            nPPTX, nPPTY, fZoomX, fZoomY, true /*bWidth*/);
646
647
0
    return (nWidth + 2) / nPPTX; // same as ScColumn::GetOptimalColWidth
648
0
}
649
650
bool ScDocFunc::DeleteCell(
651
    const ScAddress& rPos, const ScMarkData& rMark, InsertDeleteFlags nFlags, bool bRecord, bool bApi )
652
0
{
653
0
    sc::DeleteCellOperation aOperation(*this, rDocShell, rPos, rMark, nFlags, bRecord, bApi);
654
0
    return aOperation.run();
655
0
}
656
657
bool ScDocFunc::TransliterateText( const ScMarkData& rMark, TransliterationFlags nType,
658
                                    bool bApi )
659
0
{
660
0
    sc::TransliterateTextOperation aOperation(*this, rDocShell, rMark, nType, bApi);
661
0
    return aOperation.run();
662
0
}
663
664
bool ScDocFunc::SetNormalString(bool& o_rbNumFmtSet, const ScAddress& rPos, const OUString& rText, bool bApi )
665
0
{
666
0
    sc::SetNormalStringOperation aOperation(*this, rDocShell, rPos, rText, bApi);
667
0
    bool bResult = aOperation.run();
668
0
    if (bResult)
669
0
        o_rbNumFmtSet = aOperation.isNumberFormatSet();
670
0
    return bResult;
671
0
}
672
673
bool ScDocFunc::SetValueCell( const ScAddress& rPos, double fVal, bool bInteraction )
674
0
{
675
0
    sc::SetValueOperation aOperation(*this, rDocShell, rPos, fVal, !bInteraction);
676
0
    return aOperation.run();
677
0
}
678
679
void ScDocFunc::SetValueCells( const ScAddress& rPos, const std::vector<double>& aVals, bool bInteraction )
680
0
{
681
0
    ScDocument& rDoc = rDocShell.GetDocument();
682
683
    // Check for invalid range.
684
0
    SCROW nLastRow = rPos.Row() + aVals.size() - 1;
685
0
    if (nLastRow > rDoc.MaxRow())
686
        // out of bound.
687
0
        return;
688
689
0
    ScRange aRange(rPos);
690
0
    aRange.aEnd.SetRow(nLastRow);
691
692
0
    ScDocShellModificator aModificator(rDocShell);
693
694
0
    if (rDoc.IsUndoEnabled())
695
0
    {
696
0
        std::unique_ptr<sc::UndoSetCells> pUndoObj(new sc::UndoSetCells(rDocShell, rPos));
697
0
        rDoc.TransferCellValuesTo(rPos, aVals.size(), pUndoObj->GetOldValues());
698
0
        pUndoObj->SetNewValues(aVals);
699
0
        SfxUndoManager* pUndoMgr = rDocShell.GetUndoManager();
700
0
        pUndoMgr->AddUndoAction(std::move(pUndoObj));
701
0
    }
702
703
0
    rDoc.SetValues(rPos, aVals);
704
705
0
    rDocShell.PostPaint(aRange, PaintPartFlags::Grid);
706
0
    aModificator.SetDocumentModified();
707
708
    // #103934#; notify editline and cell in edit mode
709
0
    if (!bInteraction)
710
0
        NotifyInputHandler(rPos);
711
0
}
712
713
bool ScDocFunc::SetStringCell( const ScAddress& rPos, const OUString& rStr, bool bInteraction )
714
60
{
715
60
    sc::SetStringOperation aOperation(*this, rDocShell, rPos, rStr, !bInteraction);
716
60
    return aOperation.run();
717
60
}
718
719
bool ScDocFunc::SetEditCell( const ScAddress& rPos, const EditTextObject& rStr, bool bInteraction )
720
0
{
721
0
    sc::SetEditTextOperation aOperation(*this, rDocShell, rPos, rStr, !bInteraction);
722
0
    return aOperation.run();
723
0
}
724
725
bool ScDocFunc::SetStringOrEditCell( const ScAddress& rPos, const OUString& rStr, bool bInteraction )
726
60
{
727
60
    ScDocument& rDoc = rDocShell.GetDocument();
728
729
60
    if (ScStringUtil::isMultiline(rStr))
730
0
    {
731
0
        ScFieldEditEngine& rEngine = rDoc.GetEditEngine();
732
0
        rEngine.SetTextCurrentDefaults(rStr);
733
0
        std::unique_ptr<EditTextObject> pEditText(rEngine.CreateTextObject());
734
0
        return SetEditCell(rPos, *pEditText, bInteraction);
735
0
    }
736
60
    else
737
60
        return SetStringCell(rPos, rStr, bInteraction);
738
60
}
739
740
bool ScDocFunc::SetFormulaCell( const ScAddress& rPos, ScFormulaCell* pCell, bool bInteraction )
741
0
{
742
0
    sc::SetFormulaOperation aOperation(*this, rDocShell, rPos, pCell, !bInteraction);
743
0
    return aOperation.run();
744
0
}
745
746
bool ScDocFunc::SetFormulaCells( const ScAddress& rPos, std::vector<ScFormulaCell*>& rCells, bool bInteraction )
747
0
{
748
0
    ScDocument& rDoc = rDocShell.GetDocument();
749
750
0
    const size_t nLength = rCells.size();
751
0
    if (rPos.Row() + nLength - 1 > o3tl::make_unsigned(rDoc.MaxRow()))
752
        // out of bound
753
0
        return false;
754
755
0
    ScRange aRange(rPos);
756
0
    aRange.aEnd.IncRow(nLength - 1);
757
758
0
    ScDocShellModificator aModificator( rDocShell );
759
0
    bool bUndo = rDoc.IsUndoEnabled();
760
761
0
    std::unique_ptr<sc::UndoSetCells> pUndoObj;
762
0
    if (bUndo)
763
0
    {
764
0
        pUndoObj.reset(new sc::UndoSetCells(rDocShell, rPos));
765
0
        rDoc.TransferCellValuesTo(rPos, nLength, pUndoObj->GetOldValues());
766
0
    }
767
768
0
    rDoc.SetFormulaCells(rPos, rCells);
769
770
    // For performance reasons API calls may disable calculation while
771
    // operating and recalculate once when done. If through user interaction
772
    // and AutoCalc is disabled, calculate the formula (without its
773
    // dependencies) once so the result matches the current document's content.
774
0
    if (bInteraction && !rDoc.GetAutoCalc())
775
0
    {
776
0
        for (auto* pCell : rCells)
777
0
        {
778
            // calculate just the cell once and set Dirty again
779
0
            pCell->Interpret();
780
0
            pCell->SetDirtyVar();
781
0
            rDoc.PutInFormulaTree( pCell);
782
0
        }
783
0
    }
784
785
0
    if (bUndo)
786
0
    {
787
0
        pUndoObj->SetNewValues(rCells);
788
0
        SfxUndoManager* pUndoMgr = rDocShell.GetUndoManager();
789
0
        pUndoMgr->AddUndoAction(std::move(pUndoObj));
790
0
    }
791
792
0
    rDocShell.PostPaint(aRange, PaintPartFlags::Grid);
793
0
    aModificator.SetDocumentModified();
794
795
    // #103934#; notify editline and cell in edit mode
796
0
    if (!bInteraction)
797
0
        NotifyInputHandler( rPos );
798
799
0
    return true;
800
0
}
801
802
void ScDocFunc::NotifyInputHandler( const ScAddress& rPos )
803
60
{
804
60
    ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
805
60
    if ( !(pViewSh && pViewSh->GetViewData().GetDocShell() == &rDocShell) )
806
60
        return;
807
808
0
    ScInputHandler* pInputHdl = ScModule::get()->GetInputHdl();
809
0
    if ( pInputHdl && pInputHdl->GetCursorPos() == rPos )
810
0
    {
811
0
        bool bIsEditMode(pInputHdl->IsEditMode());
812
813
        // set modified if in editmode, because so the string is not set in the InputWindow like in the cell
814
        // (the cell shows the same like the InputWindow)
815
0
        if (bIsEditMode)
816
0
            pInputHdl->SetModified();
817
0
        pViewSh->UpdateInputHandler(false, !bIsEditMode);
818
0
    }
819
0
}
820
821
namespace {
822
823
    struct ScMyRememberItem
824
    {
825
        sal_Int32   nIndex;
826
        SfxItemSet  aItemSet;
827
828
        ScMyRememberItem(SfxItemSet _aItemSet, sal_Int32 nTempIndex) :
829
0
            nIndex(nTempIndex), aItemSet(std::move(_aItemSet)) {}
830
    };
831
832
}
833
834
void ScDocFunc::PutData( const ScAddress& rPos, ScEditEngineDefaulter& rEngine, bool bApi )
835
0
{
836
    //  PutData calls PutCell or SetNormalString
837
838
0
    bool bRet = false;
839
0
    ScDocument& rDoc = rDocShell.GetDocument();
840
0
    ScEditAttrTester aTester( &rEngine );
841
0
    bool bEditCell = aTester.NeedsObject();
842
0
    if ( bEditCell )
843
0
    {
844
        // #i61702# With bLoseContent set, the content of rEngine isn't restored
845
        // (used in loading XML, where after the removeActionLock call the API object's
846
        // EditEngine isn't accessed again.
847
0
        bool bLoseContent = rDoc.IsImportingXML();
848
849
0
        const bool bUpdateMode = rEngine.SetUpdateLayout(false);
850
851
0
        std::vector<std::unique_ptr<ScMyRememberItem>> aRememberItems;
852
853
        //  All paragraph attributes must be removed before calling CreateTextObject,
854
        //  not only alignment, so the object doesn't contain the cell attributes as
855
        //  paragraph attributes. Before removing the attributes store them in a vector to
856
        //  set them back to the EditEngine.
857
0
        sal_Int32 nCount = rEngine.GetParagraphCount();
858
0
        for (sal_Int32 i=0; i<nCount; i++)
859
0
        {
860
0
            const SfxItemSet& rOld = rEngine.GetParaAttribs( i );
861
0
            if ( rOld.Count() )
862
0
            {
863
0
                if ( !bLoseContent )
864
0
                {
865
0
                    aRememberItems.push_back(std::make_unique<ScMyRememberItem>(rEngine.GetParaAttribs(i), i));
866
0
                }
867
0
                rEngine.SetParaAttribs( i, SfxItemSet( *rOld.GetPool(), rOld.GetRanges() ) );
868
0
            }
869
0
        }
870
871
        // A copy of pNewData will be stored in the cell.
872
0
        std::unique_ptr<EditTextObject> pNewData(rEngine.CreateTextObject());
873
0
        bRet = SetEditCell(rPos, *pNewData, !bApi);
874
875
        // Set the paragraph attributes back to the EditEngine.
876
0
        for (const auto& rxItem : aRememberItems)
877
0
        {
878
0
            rEngine.SetParaAttribs(rxItem->nIndex, rxItem->aItemSet);
879
0
        }
880
881
        // #i61702# if the content isn't accessed, there's no need to set the UpdateMode again
882
0
        if ( bUpdateMode && !bLoseContent )
883
0
            rEngine.SetUpdateLayout(true);
884
0
    }
885
0
    else
886
0
    {
887
0
        OUString aText = rEngine.GetText();
888
0
        if (aText.isEmpty())
889
0
        {
890
0
            bool bNumFmtSet = false;
891
0
            bRet = SetNormalString( bNumFmtSet, rPos, aText, bApi );
892
0
        }
893
0
        else
894
0
            bRet = SetStringCell(rPos, aText, !bApi);
895
0
    }
896
897
0
    if ( !(bRet && aTester.NeedsCellAttr()) )
898
0
        return;
899
900
0
    const SfxItemSet& rEditAttr = aTester.GetAttribs();
901
0
    ScPatternAttr aPattern(rDoc.getCellAttributeHelper());
902
0
    aPattern.GetFromEditItemSet( &rEditAttr );
903
0
    aPattern.DeleteUnchanged( rDoc.GetPattern( rPos.Col(), rPos.Row(), rPos.Tab() ) );
904
0
    aPattern.ItemSetClearItem(ATTR_HOR_JUSTIFY);    // wasn't removed above if no edit object
905
0
    if ( aPattern.GetItemSet().Count() > 0 )
906
0
    {
907
0
        ScMarkData aMark(rDoc.GetSheetLimits());
908
0
        aMark.SelectTable( rPos.Tab(), true );
909
0
        aMark.SetMarkArea( ScRange( rPos ) );
910
0
        ApplyAttributes( aMark, aPattern, bApi );
911
0
    }
912
0
}
913
914
bool ScDocFunc::SetCellText(
915
    const ScAddress& rPos, const OUString& rText, bool bInterpret, bool bEnglish, bool bApi,
916
    const formula::FormulaGrammar::Grammar eGrammar )
917
60
{
918
60
    bool bSet = false;
919
60
    if ( bInterpret )
920
60
    {
921
60
        if ( bEnglish )
922
60
        {
923
60
            ScDocument& rDoc = rDocShell.GetDocument();
924
925
60
            ::std::optional<ScExternalRefManager::ApiGuard> pExtRefGuard;
926
60
            if (bApi)
927
60
                pExtRefGuard.emplace(rDoc);
928
929
60
            ScInputStringType aRes =
930
60
                ScStringUtil::parseInputString(rDoc.GetNonThreadedContext(), rText, LANGUAGE_ENGLISH_US);
931
932
60
            switch (aRes.meType)
933
60
            {
934
0
                case ScInputStringType::Formula:
935
0
                    bSet = SetFormulaCell(rPos, new ScFormulaCell(rDoc, rPos, aRes.maText, eGrammar), !bApi);
936
0
                break;
937
0
                case ScInputStringType::Number:
938
0
                    bSet = SetValueCell(rPos, aRes.mfValue, !bApi);
939
0
                break;
940
60
                case ScInputStringType::Text:
941
60
                    bSet = SetStringOrEditCell(rPos, aRes.maText, !bApi);
942
60
                break;
943
0
                default:
944
0
                    ;
945
60
            }
946
60
        }
947
        // otherwise keep Null -> SetString with local formulas/number formats
948
60
    }
949
0
    else if (!rText.isEmpty())
950
0
    {
951
0
        bSet = SetStringOrEditCell(rPos, rText, !bApi);
952
0
    }
953
954
60
    if (!bSet)
955
0
    {
956
0
        bool bNumFmtSet = false;
957
0
        bSet = SetNormalString( bNumFmtSet, rPos, rText, bApi );
958
0
    }
959
60
    return bSet;
960
60
}
961
962
bool ScDocFunc::ShowNote( const ScAddress& rPos, bool bShow )
963
13.5k
{
964
13.5k
    ScDocument& rDoc = rDocShell.GetDocument();
965
13.5k
    ScPostIt* pNote = rDoc.GetNote( rPos );
966
13.5k
    if( !pNote || (bShow == pNote->IsCaptionShown()) ||
967
0
        (comphelper::LibreOfficeKit::isActive() && !comphelper::LibreOfficeKit::isTiledAnnotations()) )
968
13.5k
        return false;
969
970
    // move the caption to internal or hidden layer and create undo action
971
0
    pNote->ShowCaption( rPos, bShow );
972
0
    if( rDoc.IsUndoEnabled() )
973
0
        rDocShell.GetUndoManager()->AddUndoAction( std::make_unique<ScUndoShowHideNote>( rDocShell, rPos, bShow ) );
974
975
0
    rDoc.SetStreamValid(rPos.Tab(), false);
976
977
0
    ScTabView::OnLOKNoteStateChanged(pNote);
978
979
0
    if (ScViewData* pViewData = ScDocShell::GetViewData())
980
0
    {
981
0
        if (ScDrawView* pDrawView = pViewData->GetScDrawView())
982
0
            pDrawView->SyncForGrid( pNote->GetCaption());
983
0
    }
984
985
0
    rDocShell.SetDocumentModified();
986
987
0
    return true;
988
13.5k
}
989
990
void ScDocFunc::SetNoteText( const ScAddress& rPos, const OUString& rText, bool bApi )
991
0
{
992
0
    sc::SetNoteTextOperation aOperation(rDocShell, rPos, rText, bApi);
993
0
    aOperation.run();
994
0
}
995
996
void ScDocFunc::ReplaceNote( const ScAddress& rPos, const OUString& rNoteText, const OUString* pAuthor, const OUString* pDate, bool bApi )
997
0
{
998
0
    sc::ReplaceNoteTextOperation aOperation(rDocShell, rPos, rNoteText, pAuthor, pDate, bApi);
999
0
    aOperation.run();
1000
0
}
1001
1002
void ScDocFunc::InsertThreadedComment( const ScAddress& rPos, const OUString& rText, const OUString* pAuthor, bool bApi )
1003
0
{
1004
0
    sc::InsertThreadedCommentOperation aOperation(rDocShell, rPos, rText, pAuthor, bApi);
1005
0
    aOperation.run();
1006
0
}
1007
1008
void ScDocFunc::ImportNote( const ScAddress& rPos,
1009
                            std::unique_ptr<GenerateNoteCaption> xGenerator,
1010
                            const tools::Rectangle& rCaptionRect, bool bShown )
1011
16.6k
{
1012
16.6k
    ScDocShellModificator aModificator( rDocShell );
1013
16.6k
    ScDocument& rDoc = rDocShell.GetDocument();
1014
1015
16.6k
    std::unique_ptr<ScPostIt> pOldNote = rDoc.ReleaseNote( rPos );
1016
16.6k
    SAL_WARN_IF(pOldNote, "sc.ui", "imported data has >1 notes on same cell? at pos " << rPos);
1017
1018
    // create new note
1019
16.6k
    ScNoteUtil::CreateNoteFromGenerator(rDoc, rPos, std::move(xGenerator),
1020
16.6k
                                        rCaptionRect, bShown);
1021
1022
16.6k
    rDoc.SetStreamValid(rPos.Tab(), false);
1023
1024
16.6k
    aModificator.SetDocumentModified();
1025
16.6k
}
1026
1027
bool ScDocFunc::ApplyAttributes(const ScMarkData& rMark, const ScPatternAttr& rPattern, bool bApi )
1028
883
{
1029
883
    sc::ApplyAttributesOperation aOperation(*this, rDocShell, rMark, rPattern, bApi);
1030
883
    return aOperation.run();
1031
883
}
1032
1033
bool ScDocFunc::ApplyStyle( const ScMarkData& rMark, const OUString& rStyleName,
1034
                                bool bApi )
1035
4.21k
{
1036
4.21k
    ScDocument& rDoc = rDocShell.GetDocument();
1037
4.21k
    bool bRecord = true;
1038
4.21k
    if ( !rDoc.IsUndoEnabled() )
1039
4.21k
        bRecord = false;
1040
1041
4.21k
    bool bImportingXML = rDoc.IsImportingXML();
1042
    // Cell formats can still be set if the range isn't editable only because of matrix formulas.
1043
    // #i62483# When loading XML, the check can be skipped altogether.
1044
4.21k
    bool bOnlyNotBecauseOfMatrix;
1045
4.21k
    if ( !bImportingXML && !rDoc.IsSelectionEditable( rMark, &bOnlyNotBecauseOfMatrix )
1046
0
            && !bOnlyNotBecauseOfMatrix )
1047
0
    {
1048
0
        if (!bApi)
1049
0
            rDocShell.ErrorMessage(STR_PROTECTIONERR);
1050
0
        return false;
1051
0
    }
1052
1053
4.21k
    ScStyleSheet* pStyleSheet = static_cast<ScStyleSheet*>( rDoc.GetStyleSheetPool()->Find(
1054
4.21k
                                                rStyleName, SfxStyleFamily::Para ));
1055
4.21k
    if (!pStyleSheet)
1056
3.53k
        return false;
1057
1058
677
    ScDocShellModificator aModificator( rDocShell );
1059
1060
677
    ScRange aMultiRange;
1061
677
    bool bMulti = rMark.IsMultiMarked();
1062
677
    if ( bMulti )
1063
115
        aMultiRange = rMark.GetMultiMarkArea();
1064
562
    else
1065
562
        aMultiRange = rMark.GetMarkArea();
1066
1067
677
    if ( bRecord )
1068
0
    {
1069
0
        ScDocumentUniquePtr pUndoDoc(new ScDocument( SCDOCMODE_UNDO ));
1070
0
        SCTAB nStartTab = aMultiRange.aStart.Tab();
1071
0
        SCTAB nTabCount = rDoc.GetTableCount();
1072
0
        pUndoDoc->InitUndo( rDoc, nStartTab, nStartTab );
1073
0
        for (const auto& rTab : rMark)
1074
0
        {
1075
0
            if (rTab >= nTabCount)
1076
0
                break;
1077
1078
0
            if (rTab != nStartTab)
1079
0
                pUndoDoc->AddUndoTab( rTab, rTab );
1080
0
        }
1081
1082
0
        ScRange aCopyRange = aMultiRange;
1083
0
        aCopyRange.aStart.SetTab(0);
1084
0
        aCopyRange.aEnd.SetTab(nTabCount-1);
1085
0
        rDoc.CopyToDocument( aCopyRange, InsertDeleteFlags::ATTRIB, bMulti, *pUndoDoc, &rMark );
1086
1087
0
        rDocShell.GetUndoManager()->AddUndoAction(
1088
0
            std::make_unique<ScUndoSelectionStyle>(
1089
0
                    rDocShell, rMark, aMultiRange, rStyleName, std::move(pUndoDoc) ) );
1090
1091
0
    }
1092
1093
677
    rDoc.ApplySelectionStyle( *pStyleSheet, rMark );
1094
1095
677
    if (!AdjustRowHeight( aMultiRange, true, bApi ))
1096
677
        rDocShell.PostPaint( aMultiRange, PaintPartFlags::Grid );
1097
1098
677
    aModificator.SetDocumentModified();
1099
1100
677
    return true;
1101
4.21k
}
1102
1103
bool ScDocFunc::InsertCells( const ScRange& rRange, const ScMarkData* pTabMark, InsCellCmd eCmd,
1104
                             bool bRecord, bool bApi, bool bPartOfPaste, size_t nInsertCount )
1105
0
{
1106
0
    sc::InsertCellsOperation aOperation(rDocShell, rRange, pTabMark, eCmd, bRecord, bApi, bPartOfPaste, nInsertCount);
1107
0
    return aOperation.run();
1108
0
}
1109
1110
bool ScDocFunc::DeleteCells( const ScRange& rRange, const ScMarkData* pTabMark, DelCellCmd eCmd,
1111
                             bool bApi )
1112
0
{
1113
0
    sc::DeleteCellsOperation aOperation(rDocShell, rRange, pTabMark, eCmd, bApi);
1114
0
    return aOperation.run();
1115
0
}
1116
1117
bool ScDocFunc::MoveBlock( const ScRange& rSource, const ScAddress& rDestPos,
1118
                                bool bCut, bool bRecord, bool bPaint, bool bApi )
1119
0
{
1120
0
    sc::MoveBlockOperation aOperation(rDocShell, rSource, rDestPos, bCut, bRecord, bPaint, bApi);
1121
0
    return aOperation.run();
1122
0
}
1123
1124
static uno::Reference< uno::XInterface > GetDocModuleObject( const SfxObjectShell& rDocSh, const OUString& sCodeName )
1125
0
{
1126
0
    uno::Reference< lang::XMultiServiceFactory> xSF(rDocSh.GetModel(), uno::UNO_QUERY);
1127
0
    uno::Reference< container::XNameAccess > xVBACodeNamedObjectAccess;
1128
0
    uno::Reference< uno::XInterface > xDocModuleApiObject;
1129
0
    if ( xSF.is() )
1130
0
    {
1131
0
        xVBACodeNamedObjectAccess.set( xSF->createInstance(u"ooo.vba.VBAObjectModuleObjectProvider"_ustr), uno::UNO_QUERY );
1132
0
        xDocModuleApiObject.set( xVBACodeNamedObjectAccess->getByName( sCodeName ), uno::UNO_QUERY );
1133
0
    }
1134
0
    return xDocModuleApiObject;
1135
1136
0
}
1137
1138
static script::ModuleInfo lcl_InitModuleInfo( const SfxObjectShell& rDocSh, const OUString& sModule )
1139
0
{
1140
0
    script::ModuleInfo sModuleInfo;
1141
0
    sModuleInfo.ModuleType = script::ModuleType::DOCUMENT;
1142
0
    sModuleInfo.ModuleObject = GetDocModuleObject( rDocSh, sModule );
1143
0
    return sModuleInfo;
1144
0
}
1145
1146
void VBA_InsertModule( ScDocument& rDoc, SCTAB nTab, const OUString& sSource )
1147
0
{
1148
0
    ScDocShell& rDocSh = *rDoc.GetDocumentShell();
1149
0
    uno::Reference< script::XLibraryContainer > xLibContainer = rDocSh.GetBasicContainer();
1150
0
    OSL_ENSURE( xLibContainer.is(), "No BasicContainer!" );
1151
1152
0
    uno::Reference< container::XNameContainer > xLib;
1153
0
    if( xLibContainer.is() )
1154
0
    {
1155
0
        OUString aLibName( u"Standard"_ustr );
1156
#if HAVE_FEATURE_SCRIPTING
1157
        if ( rDocSh.GetBasicManager() && !rDocSh.GetBasicManager()->GetName().isEmpty() )
1158
        {
1159
            aLibName = rDocSh.GetBasicManager()->GetName();
1160
        }
1161
#endif
1162
0
        uno::Any aLibAny = xLibContainer->getByName( aLibName );
1163
0
        aLibAny >>= xLib;
1164
0
    }
1165
0
    if( !xLib.is() )
1166
0
        return;
1167
1168
    // if the Module with codename exists then find a new name
1169
0
    sal_Int32 nNum = 1;
1170
0
    OUString genModuleName = u"Sheet1"_ustr;
1171
0
    while( xLib->hasByName( genModuleName ) )
1172
0
        genModuleName = "Sheet" + OUString::number( ++nNum );
1173
1174
0
    uno::Any aSourceAny;
1175
0
    OUString sTmpSource = sSource;
1176
0
    if ( sTmpSource.isEmpty() )
1177
0
        sTmpSource = "Rem Attribute VBA_ModuleType=VBADocumentModule\nOption VBASupport 1\n";
1178
0
    aSourceAny <<= sTmpSource;
1179
0
    uno::Reference< script::vba::XVBAModuleInfo > xVBAModuleInfo( xLib, uno::UNO_QUERY );
1180
0
    if ( xVBAModuleInfo.is() )
1181
0
    {
1182
0
        rDoc.SetCodeName( nTab, genModuleName );
1183
0
        script::ModuleInfo sModuleInfo = lcl_InitModuleInfo(  rDocSh, genModuleName );
1184
0
        xVBAModuleInfo->insertModuleInfo( genModuleName, sModuleInfo );
1185
0
        xLib->insertByName( genModuleName, aSourceAny );
1186
0
    }
1187
0
}
1188
1189
void VBA_DeleteModule( ScDocShell& rDocSh, const OUString& sModuleName )
1190
0
{
1191
0
    uno::Reference< script::XLibraryContainer > xLibContainer = rDocSh.GetBasicContainer();
1192
0
    OSL_ENSURE( xLibContainer.is(), "No BasicContainer!" );
1193
1194
0
    uno::Reference< container::XNameContainer > xLib;
1195
0
    if( xLibContainer.is() )
1196
0
    {
1197
0
        OUString aLibName( u"Standard"_ustr );
1198
#if HAVE_FEATURE_SCRIPTING
1199
        if ( rDocSh.GetBasicManager() && !rDocSh.GetBasicManager()->GetName().isEmpty() )
1200
        {
1201
            aLibName = rDocSh.GetBasicManager()->GetName();
1202
        }
1203
#endif
1204
0
        uno::Any aLibAny = xLibContainer->getByName( aLibName );
1205
0
        aLibAny >>= xLib;
1206
0
    }
1207
0
    if( xLib.is() )
1208
0
    {
1209
0
        uno::Reference< script::vba::XVBAModuleInfo > xVBAModuleInfo( xLib, uno::UNO_QUERY );
1210
0
        if( xLib->hasByName( sModuleName ) )
1211
0
            xLib->removeByName( sModuleName );
1212
0
        if ( xVBAModuleInfo.is() && xVBAModuleInfo->hasModuleInfo(sModuleName) )
1213
0
            xVBAModuleInfo->removeModuleInfo( sModuleName );
1214
1215
0
    }
1216
0
}
1217
1218
bool ScDocFunc::InsertTable( SCTAB nTab, const OUString& rName, bool bRecord, bool bApi )
1219
0
{
1220
0
    bool bSuccess = false;
1221
0
    weld::WaitObject aWait( ScDocShell::GetActiveDialogParent() );
1222
1223
0
    ScDocShellModificator aModificator( rDocShell );
1224
1225
0
    ScDocument& rDoc = rDocShell.GetDocument();
1226
1227
    // Strange loop, also basic is loaded too early ( InsertTable )
1228
    // is called via the xml import for sheets in described in ODF
1229
0
    bool bInsertDocModule = false;
1230
1231
0
    if(  !rDocShell.GetDocument().IsImportingXML() )
1232
0
    {
1233
0
        bInsertDocModule = rDoc.IsInVBAMode();
1234
0
    }
1235
0
    if ( bInsertDocModule || ( bRecord && !rDoc.IsUndoEnabled() ) )
1236
0
        bRecord = false;
1237
1238
0
    if (bRecord)
1239
0
        rDoc.BeginDrawUndo();                          //  InsertTab generates SdrUndoNewPage
1240
1241
0
    SCTAB nTabCount = rDoc.GetTableCount();
1242
0
    bool bAppend = ( nTab >= nTabCount );
1243
0
    if ( bAppend )
1244
0
        nTab = nTabCount;       // important for Undo
1245
1246
0
    if (rDoc.InsertTab( nTab, rName ))
1247
0
    {
1248
0
        if (bRecord)
1249
0
            rDocShell.GetUndoManager()->AddUndoAction(
1250
0
                        std::make_unique<ScUndoInsertTab>( rDocShell, nTab, bAppend, rName));
1251
        //  Update views:
1252
        // Only insert vba modules if vba mode ( and not currently importing XML )
1253
0
        if( bInsertDocModule )
1254
0
        {
1255
0
            VBA_InsertModule( rDoc, nTab, OUString() );
1256
0
        }
1257
0
        rDocShell.Broadcast( ScTablesHint( SC_TAB_INSERTED, nTab ) );
1258
1259
0
        rDocShell.PostPaintExtras();
1260
0
        aModificator.SetDocumentModified();
1261
0
        SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScTablesChanged ) );
1262
0
        bSuccess = true;
1263
0
    }
1264
0
    else if (!bApi)
1265
0
        rDocShell.ErrorMessage(STR_TABINSERT_ERROR);
1266
1267
0
    return bSuccess;
1268
0
}
1269
1270
std::pair<sc::SheetViewID, SCTAB> ScDocFunc::InsertSheetView( SCTAB nTab, bool bRecord )
1271
0
{
1272
0
    sc::InsertSheetViewOperation aOperation(rDocShell, nTab, bRecord);
1273
0
    if (!aOperation.run())
1274
0
        return { sc::InvalidSheetViewID, -1 };
1275
0
    return { aOperation.getSheetViewID(), aOperation.getSheetViewTab() };
1276
0
}
1277
1278
bool ScDocFunc::DeleteTable( SCTAB nTab, bool bRecord )
1279
0
{
1280
0
    weld::WaitObject aWait( ScDocShell::GetActiveDialogParent() );
1281
1282
0
    ScDocShellModificator aModificator( rDocShell );
1283
1284
0
    bool bSuccess = false;
1285
0
    ScDocument& rDoc = rDocShell.GetDocument();
1286
0
    bool bVbaEnabled = rDoc.IsInVBAMode();
1287
0
    if (bRecord && !rDoc.IsUndoEnabled())
1288
0
        bRecord = false;
1289
0
    if ( bVbaEnabled )
1290
0
        bRecord = false;
1291
0
    bool bWasLinked = rDoc.IsLinked(nTab);
1292
0
    ScDocumentUniquePtr pUndoDoc;
1293
0
    std::unique_ptr<ScRefUndoData> pUndoData;
1294
0
    if (bRecord)
1295
0
    {
1296
0
        pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
1297
0
        SCTAB nCount = rDoc.GetTableCount();
1298
1299
0
        pUndoDoc->InitUndo( rDoc, nTab, nTab, true, true );     // only nTab with Flags
1300
0
        pUndoDoc->AddUndoTab( 0, nCount-1 );                    // all sheets for references
1301
1302
0
        rDoc.CopyToDocument(0,0,nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab, InsertDeleteFlags::ALL,false, *pUndoDoc );
1303
0
        OUString aOldName;
1304
0
        rDoc.GetName( nTab, aOldName );
1305
0
        pUndoDoc->RenameTab( nTab, aOldName );
1306
0
        if (bWasLinked)
1307
0
            pUndoDoc->SetLink( nTab, rDoc.GetLinkMode(nTab), rDoc.GetLinkDoc(nTab),
1308
0
                                rDoc.GetLinkFlt(nTab), rDoc.GetLinkOpt(nTab),
1309
0
                                rDoc.GetLinkTab(nTab),
1310
0
                                rDoc.GetLinkRefreshDelay(nTab) );
1311
1312
0
        if ( rDoc.IsScenario(nTab) )
1313
0
        {
1314
0
            pUndoDoc->SetScenario( nTab, true );
1315
0
            OUString aComment;
1316
0
            Color  aColor;
1317
0
            ScScenarioFlags nScenFlags;
1318
0
            rDoc.GetScenarioData( nTab, aComment, aColor, nScenFlags );
1319
0
            pUndoDoc->SetScenarioData( nTab, aComment, aColor, nScenFlags );
1320
0
            bool bActive = rDoc.IsActiveScenario( nTab );
1321
0
            pUndoDoc->SetActiveScenario( nTab, bActive );
1322
0
        }
1323
0
        pUndoDoc->SetVisible( nTab, rDoc.IsVisible( nTab ) );
1324
0
        pUndoDoc->SetTabBgColor( nTab, rDoc.GetTabBgColor(nTab) );
1325
0
        auto pSheetEvents = rDoc.GetSheetEvents( nTab );
1326
0
        pUndoDoc->SetSheetEvents( nTab, std::unique_ptr<ScSheetEvents>(pSheetEvents ? new ScSheetEvents(*pSheetEvents) : nullptr) );
1327
1328
        //  Drawing-Layer has to take care of its own undo!!!
1329
0
        rDoc.BeginDrawUndo();                          //  DeleteTab generates SdrUndoDelPage
1330
1331
0
        pUndoData.reset(new ScRefUndoData( rDoc ));
1332
0
    }
1333
1334
0
    if (rDoc.DeleteTab(nTab))
1335
0
    {
1336
0
        if (bRecord)
1337
0
        {
1338
0
            std::vector<SCTAB> theTabs;
1339
0
            theTabs.push_back(nTab);
1340
0
            rDocShell.GetUndoManager()->AddUndoAction(
1341
0
                        std::make_unique<ScUndoDeleteTab>( rDocShell, theTabs, std::move(pUndoDoc), std::move(pUndoData) ));
1342
0
        }
1343
        //  Update views:
1344
0
        if( bVbaEnabled )
1345
0
        {
1346
0
            OUString sCodeName;
1347
0
            if( rDoc.GetCodeName( nTab, sCodeName ) )
1348
0
            {
1349
0
                VBA_DeleteModule( rDocShell, sCodeName );
1350
0
            }
1351
0
        }
1352
0
        rDocShell.Broadcast( ScTablesHint( SC_TAB_DELETED, nTab ) );
1353
1354
0
        if (bWasLinked)
1355
0
        {
1356
0
            rDocShell.UpdateLinks();                // update Link-Manager
1357
0
            SfxBindings* pBindings = rDocShell.GetViewBindings();
1358
0
            if (pBindings)
1359
0
                pBindings->Invalidate(SID_LINKS);
1360
0
        }
1361
1362
0
        rDocShell.PostPaintExtras();
1363
0
        aModificator.SetDocumentModified();
1364
1365
0
        SfxApplication* pSfxApp = SfxGetpApp();                                // Navigator
1366
0
        pSfxApp->Broadcast( SfxHint( SfxHintId::ScTablesChanged ) );
1367
0
        pSfxApp->Broadcast( SfxHint( SfxHintId::ScAreasChanged ) );
1368
0
        pSfxApp->Broadcast( SfxHint( SfxHintId::ScDbAreasChanged ) );
1369
0
        pSfxApp->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged ) );
1370
1371
0
        bSuccess = true;
1372
0
    }
1373
0
    return bSuccess;
1374
0
}
1375
1376
void ScDocFunc::SetTableVisible( SCTAB nTab, bool bVisible, bool bApi )
1377
2.54k
{
1378
2.54k
    ScDocument& rDoc = rDocShell.GetDocument();
1379
2.54k
    bool bUndo(rDoc.IsUndoEnabled());
1380
2.54k
    if ( rDoc.IsVisible( nTab ) == bVisible )
1381
2.54k
        return;                                // nothing to do - ok
1382
1383
0
    if ( !rDoc.IsDocEditable() )
1384
0
    {
1385
0
        if (!bApi)
1386
0
            rDocShell.ErrorMessage(STR_PROTECTIONERR);
1387
0
        return;
1388
0
    }
1389
1390
0
    ScDocShellModificator aModificator( rDocShell );
1391
1392
0
    if ( !bVisible && !rDoc.IsImportingXML() )     // #i57869# allow hiding in any order for loading
1393
0
    {
1394
        // do not disable all sheets
1395
1396
0
        sal_uInt16 nVisCount = 0;
1397
0
        SCTAB nCount = rDoc.GetTableCount();
1398
0
        for (SCTAB i=0; i<nCount && nVisCount<2; i++)
1399
0
            if (rDoc.IsVisible(i))
1400
0
                ++nVisCount;
1401
1402
0
        if (nVisCount <= 1)
1403
0
        {
1404
0
            if (!bApi)
1405
0
                rDocShell.ErrorMessage(STR_PROTECTIONERR);  //! separate error message?
1406
0
            return;
1407
0
        }
1408
0
    }
1409
1410
0
    rDoc.SetVisible( nTab, bVisible );
1411
0
    if (bUndo)
1412
0
    {
1413
0
        std::vector<SCTAB> undoTabs { nTab };
1414
0
        rDocShell.GetUndoManager()->AddUndoAction( std::make_unique<ScUndoShowHideTab>( rDocShell, std::move(undoTabs), bVisible ) );
1415
0
    }
1416
1417
    //  update views
1418
0
    if (!bVisible)
1419
0
        rDocShell.Broadcast( ScTablesHint( SC_TAB_HIDDEN, nTab ) );
1420
1421
0
    SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScTablesChanged ) );
1422
0
    rDocShell.PostPaint(0,0,0,rDoc.MaxCol(),rDoc.MaxRow(),MAXTAB, PaintPartFlags::Extras);
1423
0
    aModificator.SetDocumentModified();
1424
0
}
1425
1426
bool ScDocFunc::SetLayoutRTL( SCTAB nTab, bool bRTL )
1427
253
{
1428
253
    ScDocument& rDoc = rDocShell.GetDocument();
1429
253
    bool bUndo(rDoc.IsUndoEnabled());
1430
253
    if ( rDoc.IsLayoutRTL( nTab ) == bRTL )
1431
235
        return true;                                // nothing to do - ok
1432
1433
    //! protection (sheet or document?)
1434
1435
18
    ScDocShellModificator aModificator( rDocShell );
1436
1437
18
    rDoc.SetLayoutRTL( nTab, bRTL, ScObjectHandling::MirrorRTLMode);
1438
1439
18
    if (bUndo)
1440
0
    {
1441
0
        rDocShell.GetUndoManager()->AddUndoAction( std::make_unique<ScUndoLayoutRTL>( rDocShell, nTab, bRTL ) );
1442
0
    }
1443
1444
18
    rDocShell.PostPaint( 0,0,nTab,rDoc.MaxCol(),rDoc.MaxRow(),nTab, PaintPartFlags::All );
1445
18
    aModificator.SetDocumentModified();
1446
1447
18
    SfxBindings* pBindings = rDocShell.GetViewBindings();
1448
18
    if (pBindings)
1449
0
    {
1450
0
        pBindings->Invalidate( FID_TAB_RTL );
1451
0
        pBindings->Invalidate( SID_ATTR_SIZE );
1452
0
    }
1453
1454
18
    return true;
1455
253
}
1456
1457
bool ScDocFunc::RenameTable( SCTAB nTab, const OUString& rName, bool bRecord, bool bApi )
1458
0
{
1459
0
    ScDocument& rDoc = rDocShell.GetDocument();
1460
0
    if (bRecord && !rDoc.IsUndoEnabled())
1461
0
        bRecord = false;
1462
0
    if ( !rDoc.IsDocEditable() )
1463
0
    {
1464
0
        if (!bApi)
1465
0
            rDocShell.ErrorMessage(STR_PROTECTIONERR);
1466
0
        return false;
1467
0
    }
1468
1469
0
    ScDocShellModificator aModificator( rDocShell );
1470
1471
0
    bool bSuccess = false;
1472
0
    OUString sOldName;
1473
0
    rDoc.GetName(nTab, sOldName);
1474
0
    if (rDoc.RenameTab( nTab, rName ))
1475
0
    {
1476
0
        if (bRecord)
1477
0
        {
1478
0
            rDocShell.GetUndoManager()->AddUndoAction(
1479
0
                            std::make_unique<ScUndoRenameTab>( rDocShell, nTab, sOldName, rName));
1480
0
        }
1481
0
        rDocShell.PostPaintExtras();
1482
0
        aModificator.SetDocumentModified();
1483
0
        SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScTablesChanged ) );
1484
0
        SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreasChanged ) );
1485
1486
0
        bSuccess = true;
1487
0
    }
1488
0
    return bSuccess;
1489
0
}
1490
1491
bool ScDocFunc::SetTabBgColor( SCTAB nTab, const Color& rColor, bool bRecord, bool bApi )
1492
313
{
1493
1494
313
    ScDocument& rDoc = rDocShell.GetDocument();
1495
313
    if (bRecord && !rDoc.IsUndoEnabled())
1496
313
        bRecord = false;
1497
313
    if ( !rDoc.IsDocEditable() || rDoc.IsTabProtected(nTab) )
1498
3
    {
1499
3
        if (!bApi)
1500
0
            rDocShell.ErrorMessage(STR_PROTECTIONERR); //TODO Check to see what this string is...
1501
3
        return false;
1502
3
    }
1503
1504
310
    Color aOldTabBgColor = rDoc.GetTabBgColor(nTab);
1505
1506
310
    bool bSuccess = false;
1507
310
    rDoc.SetTabBgColor(nTab, rColor);
1508
310
    if ( rDoc.GetTabBgColor(nTab) == rColor)
1509
310
        bSuccess = true;
1510
310
    if (bSuccess)
1511
310
    {
1512
310
        if (bRecord)
1513
0
        {
1514
0
            rDocShell.GetUndoManager()->AddUndoAction(
1515
0
                std::make_unique<ScUndoTabColor>( rDocShell, nTab, aOldTabBgColor, rColor));
1516
0
        }
1517
310
        rDocShell.PostPaintExtras();
1518
310
        ScDocShellModificator aModificator( rDocShell );
1519
310
        aModificator.SetDocumentModified();
1520
310
        SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScTablesChanged ) );
1521
1522
310
        bSuccess = true;
1523
310
    }
1524
310
    return bSuccess;
1525
313
}
1526
1527
bool ScDocFunc::SetTabBgColor(
1528
    ScUndoTabColorInfo::List& rUndoTabColorList, bool bApi )
1529
0
{
1530
0
    ScDocument& rDoc = rDocShell.GetDocument();
1531
0
    bool bRecord = true;
1532
0
    if (!rDoc.IsUndoEnabled())
1533
0
        bRecord = false;
1534
1535
0
    if ( !rDoc.IsDocEditable() )
1536
0
    {
1537
0
        if (!bApi)
1538
0
            rDocShell.ErrorMessage(STR_PROTECTIONERR); //TODO Get a better String Error...
1539
0
        return false;
1540
0
    }
1541
1542
0
    sal_uInt16 nTab;
1543
0
    Color aNewTabBgColor;
1544
0
    bool bSuccess = true;
1545
0
    size_t nTabProtectCount = 0;
1546
0
    size_t nTabListCount = rUndoTabColorList.size();
1547
0
    for ( size_t i = 0; i < nTabListCount; ++i )
1548
0
    {
1549
0
        ScUndoTabColorInfo& rInfo = rUndoTabColorList[i];
1550
0
        nTab = rInfo.mnTabId;
1551
0
        if ( !rDoc.IsTabProtected(nTab) )
1552
0
        {
1553
0
            aNewTabBgColor = rInfo.maNewTabBgColor;
1554
0
            rInfo.maOldTabBgColor = rDoc.GetTabBgColor(nTab);
1555
0
            rDoc.SetTabBgColor(nTab, aNewTabBgColor);
1556
0
            if ( rDoc.GetTabBgColor(nTab) != aNewTabBgColor)
1557
0
            {
1558
0
                bSuccess = false;
1559
0
                break;
1560
0
            }
1561
0
        }
1562
0
        else
1563
0
        {
1564
0
            nTabProtectCount++;
1565
0
        }
1566
0
    }
1567
1568
0
    if ( nTabProtectCount == nTabListCount )
1569
0
    {
1570
0
        if (!bApi)
1571
0
            rDocShell.ErrorMessage(STR_PROTECTIONERR); //TODO Get a better String Error...
1572
0
        return false;
1573
0
    }
1574
1575
0
    if (bSuccess)
1576
0
    {
1577
0
        if (bRecord)
1578
0
        {
1579
0
            rDocShell.GetUndoManager()->AddUndoAction(
1580
0
                std::make_unique<ScUndoTabColor>( rDocShell, std::vector(rUndoTabColorList)));
1581
0
        }
1582
0
        rDocShell.PostPaintExtras();
1583
0
        ScDocShellModificator aModificator( rDocShell );
1584
0
        aModificator.SetDocumentModified();
1585
0
    }
1586
0
    return bSuccess;
1587
0
}
1588
1589
//! SetWidthOrHeight - duplicated in ViewFunc !!!!!!
1590
//! Problems:
1591
//! - Optimal height of text cells is different for a printer and a screen
1592
//! - Optimal width needs a selection in order to take only selected cells into account
1593
1594
static sal_uInt16 lcl_GetOptimalColWidth( ScDocShell& rDocShell, SCCOL nCol, SCTAB nTab )
1595
0
{
1596
0
    ScSizeDeviceProvider aProv(rDocShell);
1597
0
    OutputDevice* pDev = aProv.GetDevice();         // has pixel MapMode
1598
0
    double nPPTX = aProv.GetPPTX();
1599
0
    double nPPTY = aProv.GetPPTY();
1600
1601
0
    ScDocument& rDoc = rDocShell.GetDocument();
1602
0
    double fOne(1.0);
1603
0
    sal_uInt16 nTwips = rDoc.GetOptimalColWidth( nCol, nTab, pDev, nPPTX, nPPTY, fOne, fOne,
1604
0
                                                false/*bFormula*/ );
1605
1606
0
    return nTwips;
1607
0
}
1608
1609
bool ScDocFunc::SetWidthOrHeight(
1610
    bool bWidth, const std::vector<sc::ColRowSpan>& rRanges, SCTAB nTab,
1611
    ScSizeMode eMode, sal_uInt16 nSizeTwips, bool bRecord, bool bApi )
1612
12.3k
{
1613
12.3k
    ScDocShellModificator aModificator( rDocShell );
1614
1615
12.3k
    if (rRanges.empty())
1616
0
        return true;
1617
1618
12.3k
    ScDocument& rDoc = rDocShell.GetDocument();
1619
12.3k
    if ( bRecord && !rDoc.IsUndoEnabled() )
1620
12.3k
        bRecord = false;
1621
1622
    // import into read-only document is possible
1623
12.3k
    if ( !rDoc.IsChangeReadOnlyEnabled() && !rDocShell.IsEditable() )
1624
0
    {
1625
0
        if (!bApi)
1626
0
            rDocShell.ErrorMessage(STR_PROTECTIONERR);      //! separate error message?
1627
0
        return false;
1628
0
    }
1629
1630
12.3k
    SCCOLROW nStart = rRanges[0].mnStart;
1631
12.3k
    SCCOLROW nEnd = rRanges[0].mnEnd;
1632
1633
12.3k
    if ( eMode == SC_SIZE_OPTIMAL )
1634
0
    {
1635
        //! Option "Show formulas" - but where to get them from?
1636
0
    }
1637
1638
12.3k
    ScDocumentUniquePtr pUndoDoc;
1639
12.3k
    std::unique_ptr<ScOutlineTable> pUndoTab;
1640
12.3k
    std::vector<sc::ColRowSpan> aUndoRanges;
1641
1642
12.3k
    if ( bRecord )
1643
0
    {
1644
0
        rDoc.BeginDrawUndo();                          // Drawing Updates
1645
1646
0
        pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
1647
0
        if (bWidth)
1648
0
        {
1649
0
            pUndoDoc->InitUndo( rDoc, nTab, nTab, true );
1650
0
            rDoc.CopyToDocument( static_cast<SCCOL>(nStart), 0, nTab, static_cast<SCCOL>(nEnd), rDoc.MaxRow(), nTab, InsertDeleteFlags::NONE, false, *pUndoDoc );
1651
0
        }
1652
0
        else
1653
0
        {
1654
0
            pUndoDoc->InitUndo( rDoc, nTab, nTab, false, true );
1655
0
            rDoc.CopyToDocument( 0, static_cast<SCROW>(nStart), nTab, rDoc.MaxCol(), static_cast<SCROW>(nEnd), nTab, InsertDeleteFlags::NONE, false, *pUndoDoc );
1656
0
        }
1657
1658
0
        aUndoRanges = rRanges;
1659
1660
0
        ScOutlineTable* pTable = rDoc.GetOutlineTable( nTab );
1661
0
        if (pTable)
1662
0
            pUndoTab.reset(new ScOutlineTable( *pTable ));
1663
0
    }
1664
1665
12.3k
    bool bShow = nSizeTwips > 0 || eMode != SC_SIZE_DIRECT;
1666
12.3k
    bool bOutline = false;
1667
1668
12.3k
    for (const sc::ColRowSpan& rRange : rRanges)
1669
12.3k
    {
1670
12.3k
        SCCOLROW nStartNo = rRange.mnStart;
1671
12.3k
        SCCOLROW nEndNo   = rRange.mnEnd;
1672
1673
12.3k
        if ( !bWidth )                      // deal with heights always in blocks
1674
0
        {
1675
0
            if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
1676
0
            {
1677
0
                bool bAll = ( eMode==SC_SIZE_OPTIMAL );
1678
0
                if (!bAll)
1679
0
                {
1680
                    //  delete for all that have CRFlags::ManualSize enabled
1681
                    //  then SetOptimalHeight with bShrink = FALSE
1682
0
                    for (SCROW nRow=nStartNo; nRow<=nEndNo; nRow++)
1683
0
                    {
1684
0
                        CRFlags nOld = rDoc.GetRowFlags(nRow,nTab);
1685
0
                        SCROW nLastRow = -1;
1686
0
                        bool bHidden = rDoc.RowHidden(nRow, nTab, nullptr, &nLastRow);
1687
0
                        if ( !bHidden && ( nOld & CRFlags::ManualSize ) )
1688
0
                            rDoc.SetRowFlags( nRow, nTab, nOld & ~CRFlags::ManualSize );
1689
0
                    }
1690
0
                }
1691
1692
0
                ScSizeDeviceProvider aProv( rDocShell );
1693
0
                double fOne(1.0);
1694
0
                sc::RowHeightContext aCxt(rDoc.MaxRow(), aProv.GetPPTX(), aProv.GetPPTY(), fOne, fOne, aProv.GetDevice());
1695
0
                aCxt.setForceAutoSize(bAll);
1696
0
                rDoc.SetOptimalHeight(aCxt, nStartNo, nEndNo, nTab, bApi);
1697
1698
0
                if (bAll)
1699
0
                    rDoc.ShowRows( nStartNo, nEndNo, nTab, true );
1700
1701
                //  Manual flag will be set already in SetOptimalHeight if bAll=true
1702
                //  (it is on when Extra-Height, otherwise off).
1703
0
            }
1704
0
            else if ( eMode==SC_SIZE_DIRECT || eMode==SC_SIZE_ORIGINAL )
1705
0
            {
1706
0
                if (nSizeTwips)
1707
0
                {
1708
0
                    rDoc.SetRowHeightRange( nStartNo, nEndNo, nTab, nSizeTwips );
1709
0
                    rDoc.SetManualHeight( nStartNo, nEndNo, nTab, true );          // height was set manually
1710
0
                }
1711
0
                if ( eMode != SC_SIZE_ORIGINAL )
1712
0
                    rDoc.ShowRows( nStartNo, nEndNo, nTab, nSizeTwips != 0 );
1713
0
            }
1714
0
            else if ( eMode==SC_SIZE_SHOW )
1715
0
            {
1716
0
                rDoc.ShowRows( nStartNo, nEndNo, nTab, true );
1717
0
            }
1718
0
        }
1719
12.3k
        else                                // Column widths
1720
12.3k
        {
1721
58.5k
            for (SCCOL nCol=static_cast<SCCOL>(nStartNo); nCol<=static_cast<SCCOL>(nEndNo); nCol++)
1722
46.2k
            {
1723
46.2k
                if ( eMode != SC_SIZE_VISOPT || !rDoc.ColHidden(nCol, nTab) )
1724
46.2k
                {
1725
46.2k
                    sal_uInt16 nThisSize = nSizeTwips;
1726
1727
46.2k
                    if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
1728
0
                        nThisSize = nSizeTwips +
1729
0
                                    lcl_GetOptimalColWidth( rDocShell, nCol, nTab );
1730
46.2k
                    if ( nThisSize )
1731
20.2k
                        rDoc.SetColWidth( nCol, nTab, nThisSize );
1732
1733
46.2k
                    if ( eMode != SC_SIZE_ORIGINAL )
1734
25.9k
                        rDoc.ShowCol( nCol, nTab, bShow );
1735
46.2k
                }
1736
46.2k
            }
1737
12.3k
        }
1738
1739
                            //  adjust outlines
1740
1741
12.3k
        if ( eMode != SC_SIZE_ORIGINAL )
1742
7.39k
        {
1743
7.39k
            if (bWidth)
1744
7.39k
                bOutline = bOutline || rDoc.UpdateOutlineCol(
1745
7.39k
                        static_cast<SCCOL>(nStartNo),
1746
7.39k
                        static_cast<SCCOL>(nEndNo), nTab, bShow );
1747
0
            else
1748
0
                bOutline = bOutline || rDoc.UpdateOutlineRow(
1749
0
                        static_cast<SCROW>(nStartNo),
1750
0
                        static_cast<SCROW>(nEndNo), nTab, bShow );
1751
7.39k
        }
1752
12.3k
    }
1753
12.3k
    rDoc.SetDrawPageSize(nTab);
1754
1755
12.3k
    if (!bOutline)
1756
12.3k
        pUndoTab.reset();
1757
1758
12.3k
    if (bRecord)
1759
0
    {
1760
0
        ScMarkData aMark(rDoc.GetSheetLimits());
1761
0
        aMark.SelectOneTable( nTab );
1762
0
        rDocShell.GetUndoManager()->AddUndoAction(
1763
0
            std::make_unique<ScUndoWidthOrHeight>(
1764
0
                rDocShell, aMark, nStart, nTab, nEnd, nTab, std::move(pUndoDoc),
1765
0
                std::move(aUndoRanges), std::move(pUndoTab), eMode, nSizeTwips, bWidth));
1766
0
    }
1767
1768
12.3k
    rDoc.UpdatePageBreaks( nTab );
1769
1770
12.3k
    ScTabViewShell* pViewSh = rDocShell.GetBestViewShell();
1771
12.3k
    if (pViewSh)
1772
0
        pViewSh->OnLOKSetWidthOrHeight(nStart, bWidth);
1773
1774
12.3k
    rDocShell.PostPaint(0,0,nTab,rDoc.MaxCol(),rDoc.MaxRow(),nTab,PaintPartFlags::All);
1775
12.3k
    aModificator.SetDocumentModified();
1776
1777
12.3k
    return false;
1778
12.3k
}
1779
1780
bool ScDocFunc::InsertPageBreak( bool bColumn, const ScAddress& rPos,
1781
                                bool bRecord, bool bSetModified )
1782
109
{
1783
109
    ScDocShellModificator aModificator( rDocShell );
1784
1785
109
    ScDocument& rDoc = rDocShell.GetDocument();
1786
109
    if (bRecord && !rDoc.IsUndoEnabled())
1787
109
        bRecord = false;
1788
109
    SCTAB nTab = rPos.Tab();
1789
109
    SfxBindings* pBindings = rDocShell.GetViewBindings();
1790
1791
109
    SCCOLROW nPos = bColumn ? static_cast<SCCOLROW>(rPos.Col()) :
1792
109
        static_cast<SCCOLROW>(rPos.Row());
1793
109
    if (nPos == 0)
1794
0
        return false;                   // first column / row
1795
1796
109
    ScBreakType nBreak = bColumn ?
1797
49
        rDoc.HasColBreak(static_cast<SCCOL>(nPos), nTab) :
1798
109
        rDoc.HasRowBreak(static_cast<SCROW>(nPos), nTab);
1799
109
    if (nBreak & ScBreakType::Manual)
1800
0
        return true;
1801
1802
109
    if (bRecord)
1803
0
        rDocShell.GetUndoManager()->AddUndoAction(
1804
0
            std::make_unique<ScUndoPageBreak>( rDocShell, rPos.Col(), rPos.Row(), nTab, bColumn, true ) );
1805
1806
109
    if (bColumn)
1807
49
        rDoc.SetColBreak(static_cast<SCCOL>(nPos), nTab, false, true);
1808
60
    else
1809
60
        rDoc.SetRowBreak(static_cast<SCROW>(nPos), nTab, false, true);
1810
1811
109
    rDoc.InvalidatePageBreaks(nTab);
1812
109
    rDoc.UpdatePageBreaks( nTab );
1813
1814
109
    rDoc.SetStreamValid(nTab, false);
1815
1816
109
    if (bColumn)
1817
49
    {
1818
49
        rDocShell.PostPaint( static_cast<SCCOL>(nPos)-1, 0, nTab, rDoc.MaxCol(), rDoc.MaxRow(), nTab, PaintPartFlags::Grid );
1819
49
        if (pBindings)
1820
0
        {
1821
0
            pBindings->Invalidate( FID_INS_COLBRK );
1822
0
            pBindings->Invalidate( FID_DEL_COLBRK );
1823
0
        }
1824
49
    }
1825
60
    else
1826
60
    {
1827
60
        rDocShell.PostPaint( 0, static_cast<SCROW>(nPos)-1, nTab, rDoc.MaxCol(), rDoc.MaxRow(), nTab, PaintPartFlags::Grid );
1828
60
        if (pBindings)
1829
0
        {
1830
0
            pBindings->Invalidate( FID_INS_ROWBRK );
1831
0
            pBindings->Invalidate( FID_DEL_ROWBRK );
1832
0
        }
1833
60
    }
1834
109
    if (pBindings)
1835
0
        pBindings->Invalidate( FID_DEL_MANUALBREAKS );
1836
1837
109
    if (bSetModified)
1838
109
        aModificator.SetDocumentModified();
1839
1840
109
    return true;
1841
109
}
1842
1843
bool ScDocFunc::RemovePageBreak( bool bColumn, const ScAddress& rPos,
1844
                                bool bRecord, bool bSetModified )
1845
13.5k
{
1846
13.5k
    ScDocShellModificator aModificator( rDocShell );
1847
1848
13.5k
    ScDocument& rDoc = rDocShell.GetDocument();
1849
13.5k
    if (bRecord && !rDoc.IsUndoEnabled())
1850
13.5k
        bRecord = false;
1851
13.5k
    SCTAB nTab = rPos.Tab();
1852
13.5k
    SfxBindings* pBindings = rDocShell.GetViewBindings();
1853
1854
13.5k
    SCCOLROW nPos = bColumn ? static_cast<SCCOLROW>(rPos.Col()) :
1855
13.5k
        static_cast<SCCOLROW>(rPos.Row());
1856
1857
13.5k
    ScBreakType nBreak;
1858
13.5k
    if (bColumn)
1859
13.5k
        nBreak = rDoc.HasColBreak(static_cast<SCCOL>(nPos), nTab);
1860
0
    else
1861
0
        nBreak = rDoc.HasRowBreak(static_cast<SCROW>(nPos), nTab);
1862
13.5k
    if (!(nBreak & ScBreakType::Manual))
1863
        // There is no manual break.
1864
13.5k
        return false;
1865
1866
0
    if (bRecord)
1867
0
        rDocShell.GetUndoManager()->AddUndoAction(
1868
0
            std::make_unique<ScUndoPageBreak>( rDocShell, rPos.Col(), rPos.Row(), nTab, bColumn, false ) );
1869
1870
0
    if (bColumn)
1871
0
        rDoc.RemoveColBreak(static_cast<SCCOL>(nPos), nTab, false, true);
1872
0
    else
1873
0
        rDoc.RemoveRowBreak(static_cast<SCROW>(nPos), nTab, false, true);
1874
1875
0
    rDoc.UpdatePageBreaks( nTab );
1876
1877
0
    rDoc.SetStreamValid(nTab, false);
1878
1879
0
    if (bColumn)
1880
0
    {
1881
0
        rDocShell.PostPaint( static_cast<SCCOL>(nPos)-1, 0, nTab, rDoc.MaxCol(), rDoc.MaxRow(), nTab, PaintPartFlags::Grid );
1882
0
        if (pBindings)
1883
0
        {
1884
0
            pBindings->Invalidate( FID_INS_COLBRK );
1885
0
            pBindings->Invalidate( FID_DEL_COLBRK );
1886
0
        }
1887
0
    }
1888
0
    else
1889
0
    {
1890
0
        rDocShell.PostPaint( 0, nPos-1, nTab, rDoc.MaxCol(), rDoc.MaxRow(), nTab, PaintPartFlags::Grid );
1891
0
        if (pBindings)
1892
0
        {
1893
0
            pBindings->Invalidate( FID_INS_ROWBRK );
1894
0
            pBindings->Invalidate( FID_DEL_ROWBRK );
1895
0
        }
1896
0
    }
1897
0
    if (pBindings)
1898
0
        pBindings->Invalidate( FID_DEL_MANUALBREAKS );
1899
1900
0
    if (bSetModified)
1901
0
        aModificator.SetDocumentModified();
1902
1903
0
    return true;
1904
13.5k
}
1905
1906
void ScDocFunc::ProtectSheet( SCTAB nTab, const ScTableProtection& rProtect )
1907
0
{
1908
0
    ScDocument& rDoc = rDocShell.GetDocument();
1909
1910
0
    std::unique_ptr<ScTableProtection> p;
1911
0
    if (!rProtect.isProtected() && rDoc.IsUndoEnabled())
1912
0
    {
1913
        // In case of unprotecting, use a copy of passed ScTableProtection object for undo
1914
0
        p = std::make_unique<ScTableProtection>(rProtect);
1915
0
    }
1916
0
    rDoc.SetTabProtection(nTab, &rProtect);
1917
0
    if (rDoc.IsUndoEnabled())
1918
0
    {
1919
0
        if (!p)
1920
0
        {
1921
            // For protection case, use a copy of resulting ScTableProtection for undo
1922
0
            const ScTableProtection* pProtect = rDoc.GetTabProtection(nTab);
1923
0
            p = std::make_unique<ScTableProtection>(*pProtect);
1924
0
        }
1925
0
        rDocShell.GetUndoManager()->AddUndoAction(
1926
0
            std::make_unique<ScUndoTabProtect>(rDocShell, nTab, std::move(p)));
1927
        // ownership of unique_ptr now transferred to ScUndoTabProtect.
1928
0
    }
1929
0
    for (SfxViewFrame* fr = SfxViewFrame::GetFirst(&rDocShell); fr;
1930
0
         fr = SfxViewFrame::GetNext(*fr, &rDocShell))
1931
0
        if (ScTabViewShell* pTabViewShell = dynamic_cast<ScTabViewShell*>(fr->GetViewShell()))
1932
0
            pTabViewShell->SetTabProtectionSymbol(nTab, rProtect.isProtected());
1933
0
    rDocShell.PostPaintGridAll();
1934
0
    ScDocShellModificator aModificator(rDocShell);
1935
0
    aModificator.SetDocumentModified();
1936
0
}
1937
1938
void ScDocFunc::ProtectDocument(const ScDocProtection& rProtect)
1939
0
{
1940
0
    ScDocument& rDoc = rDocShell.GetDocument();
1941
1942
0
    std::unique_ptr<ScDocProtection> p;
1943
0
    if (!rProtect.isProtected() && rDoc.IsUndoEnabled())
1944
0
    {
1945
        // In case of unprotecting, use a copy of passed ScTableProtection object for undo
1946
0
        p = std::make_unique<ScDocProtection>(rProtect);
1947
0
    }
1948
0
    rDoc.SetDocProtection(&rProtect);
1949
0
    if (rDoc.IsUndoEnabled())
1950
0
    {
1951
0
        if (!p)
1952
0
        {
1953
            // For protection case, use a copy of resulting ScTableProtection for undo
1954
0
            ScDocProtection* pProtect = rDoc.GetDocProtection();
1955
0
            p = std::make_unique<ScDocProtection>(*pProtect);
1956
0
        }
1957
0
        rDocShell.GetUndoManager()->AddUndoAction(
1958
0
            std::make_unique<ScUndoDocProtect>(rDocShell, std::move(p)));
1959
        // ownership of unique_ptr now transferred to ScUndoTabProtect.
1960
0
    }
1961
1962
0
    rDocShell.PostPaintGridAll();
1963
0
    ScDocShellModificator aModificator(rDocShell);
1964
0
    aModificator.SetDocumentModified();
1965
0
}
1966
1967
bool ScDocFunc::Protect( SCTAB nTab, const OUString& rPassword )
1968
0
{
1969
0
    if (nTab == TABLEID_DOC)
1970
0
    {
1971
        // document protection
1972
0
        ScDocProtection aProtection;
1973
0
        aProtection.setProtected(true);
1974
0
        aProtection.setPassword(rPassword);
1975
0
        ProtectDocument(aProtection);
1976
1977
0
    }
1978
0
    else
1979
0
    {
1980
        // sheet protection
1981
1982
0
        const ScTableProtection* pOldProtection = rDocShell.GetDocument().GetTabProtection(nTab);
1983
0
        ::std::unique_ptr<ScTableProtection> pNewProtection(pOldProtection ? new ScTableProtection(*pOldProtection) : new ScTableProtection());
1984
0
        pNewProtection->setProtected(true);
1985
0
        pNewProtection->setPassword(rPassword);
1986
0
        ProtectSheet(nTab, *pNewProtection);
1987
0
    }
1988
0
    return true;
1989
0
}
1990
1991
bool ScDocFunc::Unprotect( SCTAB nTab, std::u16string_view rPassword, bool bApi )
1992
0
{
1993
0
    ScDocument& rDoc = rDocShell.GetDocument();
1994
1995
0
    if (nTab == TABLEID_DOC)
1996
0
    {
1997
        // document protection
1998
1999
0
        ScDocProtection* pDocProtect = rDoc.GetDocProtection();
2000
0
        if (!pDocProtect || !pDocProtect->isProtected())
2001
            // already unprotected (should not happen)!
2002
0
            return true;
2003
2004
0
        if (!pDocProtect->verifyPassword(rPassword))
2005
0
        {
2006
0
            if (!bApi)
2007
0
            {
2008
0
                std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(),
2009
0
                                                              VclMessageType::Info, VclButtonsType::Ok,
2010
0
                                                              ScResId(SCSTR_WRONGPASSWORD)));
2011
0
                xInfoBox->run();
2012
0
            }
2013
0
            return false;
2014
0
        }
2015
2016
0
        ScDocProtection aNewProtection(*pDocProtect);
2017
0
        aNewProtection.setProtected(false);
2018
0
        ProtectDocument(aNewProtection);
2019
2020
0
    }
2021
0
    else
2022
0
    {
2023
        // sheet protection
2024
2025
0
        const ScTableProtection* pTabProtect = rDoc.GetTabProtection(nTab);
2026
0
        if (!pTabProtect || !pTabProtect->isProtected())
2027
            // already unprotected (should not happen)!
2028
0
            return true;
2029
0
        if (!pTabProtect->verifyPassword(rPassword))
2030
0
        {
2031
0
            if (!bApi)
2032
0
            {
2033
0
                std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(),
2034
0
                                                              VclMessageType::Info, VclButtonsType::Ok,
2035
0
                                                              ScResId(SCSTR_WRONGPASSWORD)));
2036
0
                xInfoBox->run();
2037
0
            }
2038
0
            return false;
2039
0
        }
2040
2041
0
        ScTableProtection aNewProtection(*pTabProtect);
2042
0
        aNewProtection.setProtected(false);
2043
0
        ProtectSheet(nTab, aNewProtection);
2044
0
    }
2045
2046
0
    return true;
2047
0
}
2048
2049
void ScDocFunc::ClearItems( const ScMarkData& rMark, const sal_uInt16* pWhich, bool bApi )
2050
0
{
2051
0
    sc::ClearItemsOperation aOperation(rDocShell, rMark, pWhich, bApi);
2052
0
    aOperation.run();
2053
0
}
2054
2055
bool ScDocFunc::ChangeIndent( const ScMarkData& rMark, bool bIncrement, bool bApi )
2056
0
{
2057
0
    sc::ChangeIndentOperation aOperation(rDocShell, rMark, bIncrement, bApi);
2058
0
    return aOperation.run();
2059
0
}
2060
2061
bool ScDocFunc::AutoFormat( const ScRange& rRange, const ScMarkData* pTabMark,
2062
                            sal_uInt16 nFormatNo, bool bApi )
2063
0
{
2064
0
    sc::AutoFormatOperation aOperation(*this, rDocShell, rRange, pTabMark, nFormatNo, bApi);
2065
0
    return aOperation.run();
2066
0
}
2067
2068
bool ScDocFunc::EnterMatrix( const ScRange& rRange, const ScMarkData* pTabMark,
2069
        const ScTokenArray* pTokenArray, const OUString& rString, bool bApi, bool bEnglish,
2070
        const OUString& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar,
2071
        bool bDynamicArrayMaster)
2072
0
{
2073
0
    sc::EnterMatrixOperation aOperation(rDocShell, rRange, pTabMark, pTokenArray,
2074
0
                                        rString, bApi, bEnglish, rFormulaNmsp, eGrammar,
2075
0
                                        bDynamicArrayMaster);
2076
0
    return aOperation.run();
2077
0
}
2078
2079
bool ScDocFunc::TabOp( const ScRange& rRange, const ScMarkData* pTabMark,
2080
                            const ScTabOpParam& rParam, bool bRecord, bool bApi )
2081
0
{
2082
0
    sc::MultipleOpsOperation aOperation(rDocShell, rRange, pTabMark, rParam, bRecord, bApi);
2083
0
    return aOperation.run();
2084
0
}
2085
2086
bool ScDocFunc::FillSimple( const ScRange& rRange, const ScMarkData* pTabMark,
2087
                            FillDir eDir, bool bApi )
2088
0
{
2089
0
    sc::FillSimpleOperation aOperation(*this, rDocShell, rRange, pTabMark, eDir, bApi);
2090
0
    return aOperation.run();
2091
0
}
2092
2093
bool ScDocFunc::FillSeries( const ScRange& rRange, const ScMarkData* pTabMark,
2094
                            FillDir eDir, FillCmd eCmd, FillDateCmd eDateCmd,
2095
                            double fStart, double fStep, double fMax,
2096
                            bool bApi )
2097
0
{
2098
0
    sc::FillSeriesOperation aOperation(*this, rDocShell, rRange, pTabMark, eDir, eCmd, eDateCmd,
2099
0
                                       fStart, fStep, fMax, bApi);
2100
0
    return aOperation.run();
2101
0
}
2102
2103
bool ScDocFunc::FillAuto( ScRange& rRange, const ScMarkData* pTabMark,
2104
                            FillDir eDir, sal_uLong nCount, bool bApi )
2105
0
{
2106
0
    return FillAuto( rRange, pTabMark, eDir, FILL_AUTO, FILL_DAY, nCount, 1.0/*fStep*/, MAXDOUBLE/*fMax*/, true/*bRecord*/, bApi );
2107
0
}
2108
2109
bool ScDocFunc::FillAuto( ScRange& rRange, const ScMarkData* pTabMark, FillDir eDir, FillCmd eCmd, FillDateCmd  eDateCmd, sal_uLong nCount, double fStep, double fMax,  bool bRecord, bool bApi )
2110
0
{
2111
0
    sc::FillAutoOperation aOperation(*this, rDocShell, rRange, pTabMark, eDir, eCmd, eDateCmd,
2112
0
                                     nCount, fStep, fMax, bRecord, bApi);
2113
0
    return aOperation.run();
2114
0
}
2115
2116
bool ScDocFunc::MergeCells( const ScCellMergeOption& rOption, bool bContents, bool bRecord, bool bApi, bool bEmptyMergedCells /*=false*/ )
2117
0
{
2118
0
    sc::MergeCellsOperation aOperation(rDocShell, rOption, bContents, bRecord, bApi, bEmptyMergedCells);
2119
0
    return aOperation.run();
2120
0
}
2121
2122
bool ScDocFunc::UnmergeCells( const ScRange& rRange, bool bRecord, ScUndoRemoveMerge* pUndoRemoveMerge )
2123
0
{
2124
0
    ScCellMergeOption aOption(rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row());
2125
0
    SCTAB nTab1 = rRange.aStart.Tab(), nTab2 = rRange.aEnd.Tab();
2126
0
    for (SCTAB i = nTab1; i <= nTab2; ++i)
2127
0
        aOption.maTabs.insert(i);
2128
2129
0
    return UnmergeCells(aOption, bRecord, pUndoRemoveMerge);
2130
0
}
2131
2132
bool ScDocFunc::UnmergeCells( const ScCellMergeOption& rOption, bool bRecord, ScUndoRemoveMerge* pUndoRemoveMerge )
2133
0
{
2134
0
    if (rOption.maTabs.empty())
2135
        // Nothing to unmerge.
2136
0
        return true;
2137
2138
0
    ScDocShellModificator aModificator( rDocShell );
2139
0
    ScDocument& rDoc = rDocShell.GetDocument();
2140
2141
0
    if (bRecord && !rDoc.IsUndoEnabled())
2142
0
        bRecord = false;
2143
2144
0
    ScDocument* pUndoDoc = (pUndoRemoveMerge ? pUndoRemoveMerge->GetUndoDoc() : nullptr);
2145
0
    assert( pUndoDoc || !pUndoRemoveMerge );
2146
0
    for (const SCTAB nTab : rOption.maTabs)
2147
0
    {
2148
0
        ScRange aRange = rOption.getSingleRange(nTab);
2149
0
        if ( !rDoc.HasAttrib(aRange, HasAttrFlags::Merged) )
2150
0
            continue;
2151
2152
0
        ScRange aExtended = aRange;
2153
0
        rDoc.ExtendMerge(aExtended);
2154
0
        ScRange aRefresh = aExtended;
2155
0
        rDoc.ExtendOverlapped(aRefresh);
2156
2157
0
        if (bRecord)
2158
0
        {
2159
0
            if (!pUndoDoc)
2160
0
            {
2161
0
                pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2162
0
                pUndoDoc->InitUndo(rDoc, *rOption.maTabs.begin(), *rOption.maTabs.rbegin());
2163
0
            }
2164
0
            rDoc.CopyToDocument(aExtended, InsertDeleteFlags::ATTRIB, false, *pUndoDoc);
2165
0
        }
2166
2167
0
        const SfxPoolItem& rDefAttr = rDoc.GetPool()->GetUserOrPoolDefaultItem( ATTR_MERGE );
2168
0
        ScPatternAttr aPattern(rDoc.getCellAttributeHelper());
2169
0
        aPattern.ItemSetPut(rDefAttr);
2170
0
        rDoc.ApplyPatternAreaTab( aRange.aStart.Col(), aRange.aStart.Row(),
2171
0
                                   aRange.aEnd.Col(), aRange.aEnd.Row(), nTab,
2172
0
                                   aPattern );
2173
2174
0
        rDoc.RemoveFlagsTab( aExtended.aStart.Col(), aExtended.aStart.Row(),
2175
0
                              aExtended.aEnd.Col(), aExtended.aEnd.Row(), nTab,
2176
0
                              ScMF::Hor | ScMF::Ver );
2177
2178
0
        rDoc.ExtendMerge( aRefresh, true );
2179
2180
0
        if ( !AdjustRowHeight( aExtended, true, true ) )
2181
0
            rDocShell.PostPaint( aExtended, PaintPartFlags::Grid );
2182
2183
0
        bool bDone = ScDetectiveFunc(rDoc, nTab).DeleteAll( ScDetectiveDelete::Circles );
2184
0
        if(bDone)
2185
0
           DetectiveMarkInvalid(nTab);
2186
0
    }
2187
2188
0
    if (bRecord)
2189
0
    {
2190
0
        if (pUndoRemoveMerge)
2191
0
        {
2192
            // If pUndoRemoveMerge was passed, the caller is responsible for
2193
            // adding it to Undo. Just add the current option.
2194
0
            pUndoRemoveMerge->AddCellMergeOption( rOption);
2195
0
        }
2196
0
        else
2197
0
        {
2198
0
            rDocShell.GetUndoManager()->AddUndoAction(
2199
0
                    std::make_unique<ScUndoRemoveMerge>( rDocShell, rOption, ScDocumentUniquePtr(pUndoDoc) ) );
2200
0
        }
2201
0
    }
2202
0
    aModificator.SetDocumentModified();
2203
2204
0
    return true;
2205
0
}
2206
2207
void ScDocFunc::ModifyRangeNames( const ScRangeName& rNewRanges, SCTAB nTab )
2208
0
{
2209
0
    SetNewRangeNames( std::unique_ptr<ScRangeName>(new ScRangeName(rNewRanges)), true, nTab );
2210
0
}
2211
2212
void ScDocFunc::SetNewRangeNames( std::unique_ptr<ScRangeName> pNewRanges, bool bModifyDoc, SCTAB nTab )     // takes ownership of pNewRanges
2213
0
{
2214
0
    ScDocShellModificator aModificator( rDocShell );
2215
2216
0
    OSL_ENSURE( pNewRanges, "pNewRanges is 0" );
2217
0
    ScDocument& rDoc = rDocShell.GetDocument();
2218
0
    bool bUndo(rDoc.IsUndoEnabled());
2219
2220
0
    if (bUndo)
2221
0
    {
2222
0
        ScRangeName* pOld;
2223
0
        if (nTab >=0)
2224
0
        {
2225
0
            pOld = rDoc.GetRangeName(nTab);
2226
0
        }
2227
0
        else
2228
0
        {
2229
0
            pOld = rDoc.GetRangeName();
2230
0
        }
2231
0
        std::unique_ptr<ScRangeName> pUndoRanges(new ScRangeName(*pOld));
2232
0
        std::unique_ptr<ScRangeName> pRedoRanges(new ScRangeName(*pNewRanges));
2233
0
        rDocShell.GetUndoManager()->AddUndoAction(
2234
0
            std::make_unique<ScUndoRangeNames>( rDocShell, std::move(pUndoRanges), std::move(pRedoRanges), nTab ) );
2235
0
    }
2236
2237
    // #i55926# While loading XML, formula cells only have a single string token,
2238
    // so CompileNameFormula would never find any name (index) tokens, and would
2239
    // unnecessarily loop through all cells.
2240
0
    bool bCompile = ( !rDoc.IsImportingXML() && rDoc.GetNamedRangesLockCount() == 0 );
2241
2242
0
    if ( bCompile )
2243
0
        rDoc.PreprocessRangeNameUpdate();
2244
0
    if (nTab >= 0)
2245
0
        rDoc.SetRangeName( nTab, std::move(pNewRanges) ); // takes ownership
2246
0
    else
2247
0
        rDoc.SetRangeName( std::move(pNewRanges) );       // takes ownership
2248
0
    if ( bCompile )
2249
0
        rDoc.CompileHybridFormula();
2250
2251
0
    if (bModifyDoc)
2252
0
    {
2253
0
        aModificator.SetDocumentModified();
2254
0
        SfxGetpApp()->Broadcast( SfxHint(SfxHintId::ScAreasChanged) );
2255
0
    }
2256
0
}
2257
2258
void ScDocFunc::ModifyAllRangeNames(const std::map<OUString, ScRangeName>& rRangeMap)
2259
0
{
2260
0
    ScDocShellModificator aModificator(rDocShell);
2261
0
    ScDocument& rDoc = rDocShell.GetDocument();
2262
2263
0
    if (rDoc.IsUndoEnabled())
2264
0
    {
2265
0
        std::map<OUString, ScRangeName*> aOldRangeMap;
2266
0
        rDoc.GetRangeNameMap(aOldRangeMap);
2267
0
        rDocShell.GetUndoManager()->AddUndoAction(
2268
0
                std::make_unique<ScUndoAllRangeNames>(rDocShell, aOldRangeMap, rRangeMap));
2269
0
    }
2270
2271
0
    rDoc.PreprocessAllRangeNamesUpdate(rRangeMap);
2272
0
    rDoc.SetAllRangeNames(rRangeMap);
2273
0
    rDoc.CompileHybridFormula();
2274
2275
0
    aModificator.SetDocumentModified();
2276
0
    SfxGetpApp()->Broadcast(SfxHint(SfxHintId::ScAreasChanged));
2277
0
}
2278
2279
void ScDocFunc::CreateOneName( ScRangeName& rList,
2280
                                SCCOL nPosX, SCROW nPosY, SCTAB nTab,
2281
                                SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
2282
                                bool& rCancel, bool bApi )
2283
0
{
2284
0
    if (rCancel)
2285
0
        return;
2286
2287
0
    ScDocument& rDoc = rDocShell.GetDocument();
2288
0
    if (rDoc.HasValueData( nPosX, nPosY, nTab ))
2289
0
        return;
2290
2291
0
    OUString aName = rDoc.GetString(nPosX, nPosY, nTab);
2292
0
    ScRangeData::MakeValidName(rDoc, aName);
2293
0
    if (aName.isEmpty())
2294
0
        return;
2295
2296
0
    OUString aContent( ScRange( nX1, nY1, nTab, nX2, nY2, nTab ).Format(
2297
0
                rDoc, ScRefFlags::RANGE_ABS_3D, ScAddress::Details( rDoc.GetAddressConvention(), nPosY, nPosX)));
2298
2299
0
    bool bInsert = false;
2300
0
    ScRangeData* pOld = rList.findByUpperName(ScGlobal::getCharClass().uppercase(aName));
2301
0
    if (pOld)
2302
0
    {
2303
0
        OUString aOldStr = pOld->GetSymbol();
2304
0
        if (aOldStr != aContent)
2305
0
        {
2306
0
            if (bApi)
2307
0
                bInsert = true;     // don't check via API
2308
0
            else
2309
0
            {
2310
0
                OUString aTemplate = ScResId( STR_CREATENAME_REPLACE );
2311
0
                OUString aMessage = o3tl::getToken(aTemplate, 0, '#' ) + aName + o3tl::getToken(aTemplate, 1, '#' );
2312
2313
0
                std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(),
2314
0
                                                               VclMessageType::Question, VclButtonsType::YesNo,
2315
0
                                                               aMessage));
2316
0
                xQueryBox->add_button(GetStandardText(StandardButtonType::Cancel), RET_CANCEL);
2317
0
                xQueryBox->set_default_response(RET_YES);
2318
2319
0
                short nResult = xQueryBox->run();
2320
0
                if ( nResult == RET_YES )
2321
0
                {
2322
0
                    rList.erase(*pOld);
2323
0
                    bInsert = true;
2324
0
                }
2325
0
                else if ( nResult == RET_CANCEL )
2326
0
                    rCancel = true;
2327
0
            }
2328
0
        }
2329
0
    }
2330
0
    else
2331
0
        bInsert = true;
2332
2333
0
    if (bInsert)
2334
0
    {
2335
0
        ScRangeData* pData = new ScRangeData( rDoc, aName, aContent,
2336
0
                ScAddress( nPosX, nPosY, nTab));
2337
0
        if (!rList.insert(pData))
2338
0
        {
2339
0
            OSL_FAIL("nanu?");
2340
0
        }
2341
0
    }
2342
0
}
2343
2344
bool ScDocFunc::CreateNames( const ScRange& rRange, CreateNameFlags nFlags, bool bApi, SCTAB aTab )
2345
0
{
2346
0
    if (nFlags == CreateNameFlags::NONE)
2347
0
        return false;       // was nothing
2348
2349
0
    ScDocShellModificator aModificator( rDocShell );
2350
2351
0
    bool bDone = false;
2352
0
    SCCOL nStartCol = rRange.aStart.Col();
2353
0
    SCROW nStartRow = rRange.aStart.Row();
2354
0
    SCCOL nEndCol = rRange.aEnd.Col();
2355
0
    SCROW nEndRow = rRange.aEnd.Row();
2356
0
    SCTAB nTab = rRange.aStart.Tab();
2357
0
    OSL_ENSURE(rRange.aEnd.Tab() == nTab, "CreateNames: multiple tables not possible");
2358
2359
0
    bool bValid = true;
2360
0
    if ( nFlags & ( CreateNameFlags::Top | CreateNameFlags::Bottom ) )
2361
0
        if ( nStartRow == nEndRow )
2362
0
            bValid = false;
2363
0
    if ( nFlags & ( CreateNameFlags::Left | CreateNameFlags::Right ) )
2364
0
        if ( nStartCol == nEndCol )
2365
0
            bValid = false;
2366
2367
0
    if (bValid)
2368
0
    {
2369
0
        ScDocument& rDoc = rDocShell.GetDocument();
2370
0
        ScRangeName* pNames;
2371
0
        if (aTab >=0)
2372
0
            pNames = rDoc.GetRangeName(nTab);
2373
0
        else
2374
0
            pNames = rDoc.GetRangeName();
2375
2376
0
        if (!pNames)
2377
0
            return false;   // shouldn't happen
2378
0
        ScRangeName aNewRanges( *pNames );
2379
2380
0
        bool bTop   ( nFlags & CreateNameFlags::Top );
2381
0
        bool bLeft  ( nFlags & CreateNameFlags::Left );
2382
0
        bool bBottom( nFlags & CreateNameFlags::Bottom );
2383
0
        bool bRight ( nFlags & CreateNameFlags::Right );
2384
2385
0
        SCCOL nContX1 = nStartCol;
2386
0
        SCROW nContY1 = nStartRow;
2387
0
        SCCOL nContX2 = nEndCol;
2388
0
        SCROW nContY2 = nEndRow;
2389
2390
0
        if ( bTop )
2391
0
            ++nContY1;
2392
0
        if ( bLeft )
2393
0
            ++nContX1;
2394
0
        if ( bBottom )
2395
0
            --nContY2;
2396
0
        if ( bRight )
2397
0
            --nContX2;
2398
2399
0
        bool bCancel = false;
2400
0
        SCCOL i;
2401
0
        SCROW j;
2402
2403
0
        if ( bTop )
2404
0
            for (i=nContX1; i<=nContX2; i++)
2405
0
                CreateOneName( aNewRanges, i,nStartRow,nTab, i,nContY1,i,nContY2, bCancel, bApi );
2406
0
        if ( bLeft )
2407
0
            for (j=nContY1; j<=nContY2; j++)
2408
0
                CreateOneName( aNewRanges, nStartCol,j,nTab, nContX1,j,nContX2,j, bCancel, bApi );
2409
0
        if ( bBottom )
2410
0
            for (i=nContX1; i<=nContX2; i++)
2411
0
                CreateOneName( aNewRanges, i,nEndRow,nTab, i,nContY1,i,nContY2, bCancel, bApi );
2412
0
        if ( bRight )
2413
0
            for (j=nContY1; j<=nContY2; j++)
2414
0
                CreateOneName( aNewRanges, nEndCol,j,nTab, nContX1,j,nContX2,j, bCancel, bApi );
2415
2416
0
        if ( bTop && bLeft )
2417
0
            CreateOneName( aNewRanges, nStartCol,nStartRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
2418
0
        if ( bTop && bRight )
2419
0
            CreateOneName( aNewRanges, nEndCol,nStartRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
2420
0
        if ( bBottom && bLeft )
2421
0
            CreateOneName( aNewRanges, nStartCol,nEndRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
2422
0
        if ( bBottom && bRight )
2423
0
            CreateOneName( aNewRanges, nEndCol,nEndRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
2424
2425
0
        ModifyRangeNames( aNewRanges, aTab );
2426
0
        bDone = true;
2427
2428
0
    }
2429
2430
0
    return bDone;
2431
0
}
2432
2433
bool ScDocFunc::InsertNameList( const ScAddress& rStartPos, bool bApi )
2434
0
{
2435
0
    sc::InsertNameListOperation aOperation(rDocShell, rStartPos, bApi);
2436
0
    return aOperation.run();
2437
0
}
2438
2439
void ScDocFunc::ResizeMatrix( const ScRange& rOldRange, const ScAddress& rNewEnd )
2440
0
{
2441
0
    ScDocument& rDoc = rDocShell.GetDocument();
2442
0
    SCCOL nStartCol = rOldRange.aStart.Col();
2443
0
    SCROW nStartRow = rOldRange.aStart.Row();
2444
0
    SCTAB nTab = rOldRange.aStart.Tab();
2445
2446
0
    OUString aFormula = rDoc.GetFormula( nStartCol, nStartRow, nTab );
2447
0
    if ( !(aFormula.startsWith("{") && aFormula.endsWith("}")) )
2448
0
        return;
2449
2450
0
    OUString aUndo = ScResId( STR_UNDO_RESIZEMATRIX );
2451
0
    bool bUndo(rDoc.IsUndoEnabled());
2452
0
    if (bUndo)
2453
0
    {
2454
0
        ViewShellId nViewShellId(1);
2455
0
        if (ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell())
2456
0
            nViewShellId = pViewSh->GetViewShellId();
2457
0
        rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo, 0, nViewShellId );
2458
0
    }
2459
2460
0
    aFormula = aFormula.copy(1, aFormula.getLength()-2);
2461
2462
0
    ScMarkData aMark(rDoc.GetSheetLimits());
2463
0
    aMark.SetMarkArea( rOldRange );
2464
0
    aMark.SelectTable( nTab, true );
2465
0
    ScRange aNewRange( rOldRange.aStart, rNewEnd );
2466
2467
0
    if ( DeleteContents( aMark, InsertDeleteFlags::CONTENTS, true, false/*bApi*/ ) )
2468
0
    {
2469
        // Formula string was obtained in document grammar.
2470
0
        if (!EnterMatrix( aNewRange, &aMark, nullptr, aFormula, false/*bApi*/, false, OUString(), rDoc.GetGrammar() ))
2471
0
        {
2472
            // try to restore the previous state
2473
0
            EnterMatrix( rOldRange, &aMark, nullptr, aFormula, false/*bApi*/, false, OUString(), rDoc.GetGrammar() );
2474
0
        }
2475
0
    }
2476
2477
0
    if (bUndo)
2478
0
        rDocShell.GetUndoManager()->LeaveListAction();
2479
0
}
2480
2481
void ScDocFunc::InsertAreaLink( const OUString& rFile, const OUString& rFilter,
2482
                                const OUString& rOptions, const OUString& rSource,
2483
                                const ScRange& rDestRange, sal_Int32 nRefreshDelaySeconds,
2484
                                bool bFitBlock, bool bApi )
2485
0
{
2486
0
    ScDocument& rDoc = rDocShell.GetDocument();
2487
0
    bool bUndo (rDoc.IsUndoEnabled());
2488
2489
0
    sfx2::LinkManager* pLinkManager = rDoc.GetLinkManager();
2490
2491
    //  #i52120# if other area links exist at the same start position,
2492
    //  remove them first (file format specifies only one link definition
2493
    //  for a cell)
2494
2495
0
    sal_uInt16 nLinkCount = pLinkManager->GetLinks().size();
2496
0
    sal_uInt16 nRemoved = 0;
2497
0
    sal_uInt16 nLinkPos = 0;
2498
0
    while (nLinkPos<nLinkCount)
2499
0
    {
2500
0
        ::sfx2::SvBaseLink* pBase = pLinkManager->GetLinks()[nLinkPos].get();
2501
0
        ScAreaLink* pLink = dynamic_cast<ScAreaLink*>(pBase);
2502
0
        if (pLink && pLink->GetDestArea().aStart == rDestRange.aStart)
2503
0
        {
2504
0
            if ( bUndo )
2505
0
            {
2506
0
                if ( !nRemoved )
2507
0
                {
2508
                    // group all remove and the insert action
2509
0
                    OUString aUndo = ScResId( STR_UNDO_INSERTAREALINK );
2510
0
                    ViewShellId nViewShellId(-1);
2511
0
                    if (ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell())
2512
0
                        nViewShellId = pViewSh->GetViewShellId();
2513
0
                    rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo, 0, nViewShellId );
2514
0
                }
2515
2516
0
                ScAreaLink* pOldArea = static_cast<ScAreaLink*>(pBase);
2517
0
                rDocShell.GetUndoManager()->AddUndoAction(
2518
0
                    std::make_unique<ScUndoRemoveAreaLink>( rDocShell,
2519
0
                        pOldArea->GetFile(), pOldArea->GetFilter(), pOldArea->GetOptions(),
2520
0
                        pOldArea->GetSource(), pOldArea->GetDestArea(), pOldArea->GetRefreshDelaySeconds() ) );
2521
0
            }
2522
0
            pLinkManager->Remove( pBase );
2523
0
            nLinkCount = pLinkManager->GetLinks().size();
2524
0
            ++nRemoved;
2525
0
        }
2526
0
        else
2527
0
            ++nLinkPos;
2528
0
    }
2529
2530
0
    OUString aFilterName = rFilter;
2531
0
    OUString aNewOptions = rOptions;
2532
0
    if (aFilterName.isEmpty())
2533
0
        ScDocumentLoader::GetFilterName( rFile, aFilterName, aNewOptions, true, !bApi );
2534
2535
    //  remove application prefix from filter name here, so the filter options
2536
    //  aren't reset when the filter name is changed in ScAreaLink::DataChanged
2537
0
    ScDocumentLoader::RemoveAppPrefix( aFilterName );
2538
2539
0
    ScAreaLink* pLink = new ScAreaLink( rDocShell, rFile, aFilterName,
2540
0
                                        aNewOptions, rSource, rDestRange, nRefreshDelaySeconds );
2541
0
    OUString aTmp = aFilterName;
2542
0
    pLinkManager->InsertFileLink( *pLink, sfx2::SvBaseLinkObjectType::ClientFile, rFile, &aTmp, &rSource );
2543
2544
    //  Undo for an empty link
2545
2546
0
    if (bUndo)
2547
0
    {
2548
0
        rDocShell.GetUndoManager()->AddUndoAction( std::make_unique<ScUndoInsertAreaLink>( rDocShell,
2549
0
                                                    rFile, aFilterName, aNewOptions,
2550
0
                                                    rSource, rDestRange, nRefreshDelaySeconds ) );
2551
0
        if ( nRemoved )
2552
0
            rDocShell.GetUndoManager()->LeaveListAction();  // undo for link update is still separate
2553
0
    }
2554
2555
    //  Update has its own undo
2556
0
    if (rDoc.IsExecuteLinkEnabled())
2557
0
    {
2558
0
        pLink->SetDoInsert(bFitBlock);  // if applicable, don't insert anything on first update
2559
0
        pLink->Update();                // no SetInCreate -> carry out update
2560
0
    }
2561
0
    pLink->SetDoInsert(true);       // Default = true
2562
2563
0
    SfxBindings* pBindings = rDocShell.GetViewBindings();
2564
0
    if (pBindings)
2565
0
        pBindings->Invalidate( SID_LINKS );
2566
2567
0
    SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged ) );     // Navigator
2568
0
}
2569
2570
void ScDocFunc::ReplaceConditionalFormat( sal_uLong nOldFormat, std::unique_ptr<ScConditionalFormat> pFormat, SCTAB nTab, const ScRangeList& rRanges )
2571
0
{
2572
0
    ScDocShellModificator aModificator(rDocShell);
2573
0
    ScDocument& rDoc = rDocShell.GetDocument();
2574
0
    if(rDoc.IsTabProtected(nTab))
2575
0
        return;
2576
2577
0
    ScRange aCombinedRange = rRanges.Combine();
2578
0
    std::unique_ptr<ScUndoConditionalFormat> pUndo;
2579
0
    if (rDoc.IsUndoEnabled())
2580
0
        pUndo.reset(new ScUndoConditionalFormat(rDocShell, nTab));
2581
2582
0
    std::unique_ptr<ScRange> pRepaintRange;
2583
0
    if(nOldFormat)
2584
0
    {
2585
0
        ScConditionalFormat* pOldFormat = rDoc.GetCondFormList(nTab)->GetFormat(nOldFormat);
2586
0
        if(pOldFormat)
2587
0
        {
2588
0
            pRepaintRange.reset(new ScRange( pOldFormat->GetRange().Combine() ));
2589
0
            rDoc.RemoveCondFormatData(pOldFormat->GetRange(), nTab, pOldFormat->GetKey());
2590
0
        }
2591
2592
0
        rDoc.DeleteConditionalFormat(nOldFormat, nTab);
2593
0
        rDoc.SetStreamValid(nTab, false);
2594
0
    }
2595
0
    if(pFormat)
2596
0
    {
2597
0
        if(pRepaintRange)
2598
0
            pRepaintRange->ExtendTo(aCombinedRange);
2599
0
        else
2600
0
            pRepaintRange.reset(new ScRange(aCombinedRange));
2601
2602
0
        sal_uInt32 nIndex = rDoc.AddCondFormat(std::move(pFormat), nTab);
2603
2604
0
        rDoc.AddCondFormatData(rRanges, nTab, nIndex);
2605
0
        rDoc.SetStreamValid(nTab, false);
2606
0
    }
2607
2608
0
    if (pUndo)
2609
0
    {
2610
0
        pUndo->setRedoData();
2611
0
        rDocShell.GetUndoManager()->AddUndoAction(std::move(pUndo));
2612
0
    }
2613
2614
0
    if(pRepaintRange)
2615
0
        rDocShell.PostPaint(*pRepaintRange, PaintPartFlags::Grid, SC_PF_TESTMERGE);
2616
2617
0
    aModificator.SetDocumentModified();
2618
0
    SfxGetpApp()->Broadcast(SfxHint(SfxHintId::ScAreasChanged));
2619
0
}
2620
2621
void ScDocFunc::SetConditionalFormatList( ScConditionalFormatList* pList, SCTAB nTab )
2622
0
{
2623
0
    ScDocShellModificator aModificator(rDocShell);
2624
0
    ScDocument& rDoc = rDocShell.GetDocument();
2625
0
    if(rDoc.IsTabProtected(nTab))
2626
0
        return;
2627
2628
0
    bool bUndo = rDoc.IsUndoEnabled();
2629
0
    ScDocumentUniquePtr pUndoDoc;
2630
0
    if (bUndo)
2631
0
    {
2632
0
        pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO));
2633
0
        pUndoDoc->InitUndo( rDoc, nTab, nTab );
2634
2635
0
        ScConditionalFormatList* pOld = rDoc.GetCondFormList(nTab);
2636
2637
0
        if (pOld)
2638
0
            pUndoDoc->SetCondFormList(pOld->Clone(*pUndoDoc), nTab);
2639
0
        else
2640
0
            pUndoDoc->SetCondFormList(nullptr, nTab);
2641
2642
0
    }
2643
2644
    // first remove all old entries
2645
0
    ScConditionalFormatList* pOldList = rDoc.GetCondFormList(nTab);
2646
0
    pOldList->RemoveFromDocument(rDoc);
2647
2648
    // then set new entries
2649
0
    pList->AddToDocument(rDoc);
2650
2651
0
    rDoc.SetCondFormList(pList, nTab);
2652
0
    rDocShell.PostPaintGridAll();
2653
2654
0
    if(bUndo)
2655
0
    {
2656
0
        ScDocumentUniquePtr pRedoDoc(new ScDocument(SCDOCMODE_UNDO));
2657
0
        pRedoDoc->InitUndo( rDoc, nTab, nTab );
2658
0
        pRedoDoc->SetCondFormList(pList->Clone(*pRedoDoc), nTab);
2659
2660
0
        rDocShell.GetUndoManager()->AddUndoAction(
2661
0
                std::make_unique<ScUndoConditionalFormatList>(rDocShell, std::move(pUndoDoc), std::move(pRedoDoc), nTab));
2662
0
    }
2663
2664
0
    rDoc.SetStreamValid(nTab, false);
2665
0
    aModificator.SetDocumentModified();
2666
0
    SfxGetpApp()->Broadcast(SfxHint(SfxHintId::ScAreasChanged));
2667
0
}
2668
2669
void ScDocFunc::ConvertFormulaToValue( const ScRange& rRange, bool bInteraction )
2670
0
{
2671
0
    sc::ConvertFormulaToValueOperation aOperation(rDocShell, rRange, bInteraction);
2672
0
    aOperation.run();
2673
0
}
2674
2675
void ScDocFunc::EnterListAction(TranslateId pNameResId)
2676
0
{
2677
0
    OUString aUndo(ScResId(pNameResId));
2678
0
    ViewShellId nViewShellId(-1);
2679
0
    if (ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell())
2680
0
        nViewShellId = pViewSh->GetViewShellId();
2681
0
    rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo, 0, nViewShellId );
2682
0
}
2683
2684
void ScDocFunc::EndListAction()
2685
0
{
2686
0
    rDocShell.GetUndoManager()->LeaveListAction();
2687
0
}
2688
2689
bool ScDocFunc::InsertSparklines(ScRange const& rDataRange, ScRange const& rSparklineRange,
2690
                                 const std::shared_ptr<sc::SparklineGroup>& pSparklineGroup)
2691
0
{
2692
0
    sc::InsertSparklinesOperation aOperation(rDocShell, rDataRange, rSparklineRange, pSparklineGroup);
2693
0
    return aOperation.run();
2694
0
}
2695
2696
bool ScDocFunc::DeleteSparkline(ScAddress const& rAddress)
2697
0
{
2698
0
    sc::DeleteSparklineOperation aOperation(rDocShell, rAddress);
2699
0
    return aOperation.run();
2700
0
}
2701
2702
bool ScDocFunc::DeleteSparklineGroup(std::shared_ptr<sc::SparklineGroup> const& pSparklineGroup, SCTAB nTab)
2703
0
{
2704
0
    sc::DeleteSparklineGroupOperation aOperation(rDocShell, pSparklineGroup, nTab);
2705
0
    return aOperation.run();
2706
0
}
2707
2708
bool ScDocFunc::ChangeSparklineGroupAttributes(std::shared_ptr<sc::SparklineGroup> const& pExistingSparklineGroup,
2709
                                               sc::SparklineAttributes const& rNewAttributes)
2710
0
{
2711
0
    sc::ChangeSparklineGroupAttributesOperation aOperation(rDocShell, pExistingSparklineGroup, rNewAttributes);
2712
0
    return aOperation.run();
2713
0
}
2714
2715
bool ScDocFunc::GroupSparklines(ScRange const& rRange, std::shared_ptr<sc::SparklineGroup> const& rpGroup)
2716
0
{
2717
0
    sc::GroupSparklinesOperation aOperation(rDocShell, rRange, rpGroup);
2718
0
    return aOperation.run();
2719
0
}
2720
2721
bool ScDocFunc::UngroupSparklines(ScRange const& rRange)
2722
0
{
2723
0
    sc::UngroupSparklinesOperation aOperation(rDocShell, rRange);
2724
0
    return aOperation.run();
2725
0
}
2726
2727
bool ScDocFunc::ChangeSparkline(std::shared_ptr<sc::Sparkline> const& rpSparkline, SCTAB nTab, ScRangeList const& rDataRange)
2728
0
{
2729
0
    sc::ChangeSparklineOperation aOperation(rDocShell, rpSparkline, nTab, rDataRange);
2730
0
    return aOperation.run();
2731
0
}
2732
2733
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */