1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source eCode 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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <scitems.hxx>
22 #include <sfx2/app.hxx>
23 #include <sfx2/request.hxx>
24 #include <editeng/borderline.hxx>
25 #include <editeng/boxitem.hxx>
26 #include <editeng/fontitem.hxx>
27 #include <editeng/lineitem.hxx>
28 #include <editeng/scripttypeitem.hxx>
29 #include <svl/srchitem.hxx>
30 #include <sfx2/linkmgr.hxx>
31 #include <sfx2/dispatch.hxx>
32 #include <sfx2/docfilt.hxx>
33 #include <sfx2/docfile.hxx>
34 #include <sfx2/objitem.hxx>
35 #include <sfx2/viewfrm.hxx>
36 #include <svl/numformat.hxx>
37 #include <svl/stritem.hxx>
38 #include <svl/zforlist.hxx>
39 #include <svx/srchdlg.hxx>
40 #include <svx/svdview.hxx>
41 #include <vcl/svapp.hxx>
42 #include <vcl/weld.hxx>
43 #include <osl/diagnose.h>
45 #include <viewfunc.hxx>
46 #include <vcl/uitest/logger.hxx>
47 #include <vcl/uitest/eventdescription.hxx>
50 #include <globstr.hrc>
51 #include <scresid.hxx>
54 #include <autoform.hxx>
55 #include <formulacell.hxx>
56 #include <cellmergeoption.hxx>
57 #include <compiler.hxx>
58 #include <docfunc.hxx>
59 #include <docpool.hxx>
62 #include <patattr.hxx>
63 #include <printfun.hxx>
64 #include <refundo.hxx>
66 #include <tablink.hxx>
67 #include <tabvwsh.hxx>
68 #include <uiitems.hxx>
69 #include <undoblk.hxx>
70 #include <undotab.hxx>
71 #include <sizedev.hxx>
72 #include <editable.hxx>
74 #include <charthelper.hxx>
75 #include <tabbgcolor.hxx>
76 #include <clipparam.hxx>
77 #include <prnsave.hxx>
78 #include <searchresults.hxx>
79 #include <tokenarray.hxx>
80 #include <rowheightcontext.hxx>
81 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
82 #include <comphelper/lok.hxx>
83 #include <mergecellsdialog.hxx>
84 #include <sheetevents.hxx>
85 #include <columnspanset.hxx>
89 #include <boost/property_tree/json_parser.hpp>
90 #include <tools/json_writer.hxx>
92 #include <officecfg/Office/Calc.hxx>
93 #include <sfx2/lokhelper.hxx>
95 using namespace com::sun::star
;
96 using ::editeng::SvxBorderLine
;
100 void collectUIInformation(std::map
<OUString
, OUString
>&& aParameters
, const OUString
& rAction
)
102 EventDescription aDescription
;
103 aDescription
.aID
= "grid_window";
104 aDescription
.aAction
= rAction
;
105 aDescription
.aParameters
= std::move(aParameters
);
106 aDescription
.aParent
= "MainWindow";
107 aDescription
.aKeyWord
= "ScGridWinUIObject";
109 UITestLogger::getInstance().logEvent(aDescription
);
114 using ::std::unique_ptr
;
116 bool ScViewFunc::AdjustBlockHeight( bool bPaint
, ScMarkData
* pMarkData
)
118 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
120 pMarkData
= &GetViewData().GetMarkData();
122 ScDocument
& rDoc
= pDocSh
->GetDocument();
123 std::vector
<sc::ColRowSpan
> aMarkedRows
= pMarkData
->GetMarkedRowSpans();
125 if (aMarkedRows
.empty())
127 SCROW nCurRow
= GetViewData().GetCurY();
128 aMarkedRows
.emplace_back(nCurRow
, nCurRow
);
131 if (comphelper::LibreOfficeKit::isActive())
133 SCCOLROW nStart
= aMarkedRows
[0].mnStart
;
134 OnLOKSetWidthOrHeight(nStart
, /*width: */ false);
137 double nPPTX
= GetViewData().GetPPTX();
138 double nPPTY
= GetViewData().GetPPTY();
139 Fraction aZoomX
= GetViewData().GetZoomX();
140 Fraction aZoomY
= GetViewData().GetZoomY();
142 ScSizeDeviceProvider
aProv(pDocSh
);
143 if (aProv
.IsPrinter())
145 nPPTX
= aProv
.GetPPTX();
146 nPPTY
= aProv
.GetPPTY();
147 aZoomX
= aZoomY
= Fraction( 1, 1 );
150 sc::RowHeightContext
aCxt(rDoc
.MaxRow(), nPPTX
, nPPTY
, aZoomX
, aZoomY
, aProv
.GetDevice());
151 bool bAnyChanged
= false;
152 for (const SCTAB
& nTab
: *pMarkData
)
154 bool bChanged
= false;
156 for (const auto& rRow
: aMarkedRows
)
158 SCROW nStartNo
= rRow
.mnStart
;
159 SCROW nEndNo
= rRow
.mnEnd
;
160 ScAddress
aTopLeft(0, nStartNo
, nTab
);
161 rDoc
.UpdateScriptTypes(aTopLeft
, rDoc
.GetSheetLimits().GetMaxColCount(), nEndNo
-nStartNo
+1);
162 if (rDoc
.SetOptimalHeight(aCxt
, nStartNo
, nEndNo
, nTab
, true))
166 bAnyChanged
= bChanged
= true;
169 // tdf#76183: recalculate objects' positions
171 rDoc
.SetDrawPageSize(nTab
);
172 if ( bPaint
&& bChanged
)
173 pDocSh
->PostPaint( 0, nPaintY
, nTab
, rDoc
.MaxCol(), rDoc
.MaxRow(), nTab
,
174 PaintPartFlags::Grid
| PaintPartFlags::Left
);
177 if ( bPaint
&& bAnyChanged
)
178 pDocSh
->UpdateOle(GetViewData());
180 if (comphelper::LibreOfficeKit::isActive())
182 SCTAB nTab
= GetViewData().GetTabNo();
183 ScTabViewShell::notifyAllViewsSheetGeomInvalidation(
184 GetViewData().GetViewShell(),
185 false /* bColumns */, true /* bRows */,
186 true /* bSizes*/, false /* bHidden */, false /* bFiltered */,
187 false /* bGroups */, nTab
);
188 ScTabViewShell::notifyAllViewsHeaderInvalidation(GetViewData().GetViewShell(), ROW_HEADER
, nTab
);
194 bool ScViewFunc::AdjustRowHeight( SCROW nStartRow
, SCROW nEndRow
, bool bApi
)
196 if (comphelper::LibreOfficeKit::isActive())
198 OnLOKSetWidthOrHeight(nStartRow
, /*width: */ false);
201 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
202 ScDocument
& rDoc
= pDocSh
->GetDocument();
203 SCTAB nTab
= GetViewData().GetTabNo();
204 double nPPTX
= GetViewData().GetPPTX();
205 double nPPTY
= GetViewData().GetPPTY();
206 Fraction aZoomX
= GetViewData().GetZoomX();
207 Fraction aZoomY
= GetViewData().GetZoomY();
208 sal_uInt16 nOldPixel
= 0;
209 if (nStartRow
== nEndRow
)
210 nOldPixel
= static_cast<sal_uInt16
>(rDoc
.GetRowHeight(nStartRow
,nTab
) * nPPTY
);
212 ScSizeDeviceProvider
aProv(pDocSh
);
213 if (aProv
.IsPrinter())
215 nPPTX
= aProv
.GetPPTX();
216 nPPTY
= aProv
.GetPPTY();
217 aZoomX
= aZoomY
= Fraction( 1, 1 );
219 sc::RowHeightContext
aCxt(rDoc
.MaxRow(), nPPTX
, nPPTY
, aZoomX
, aZoomY
, aProv
.GetDevice());
220 bool bChanged
= rDoc
.SetOptimalHeight(aCxt
, nStartRow
, nEndRow
, nTab
, bApi
);
222 // tdf#76183: recalculate objects' positions
224 rDoc
.SetDrawPageSize(nTab
);
226 if (bChanged
&& ( nStartRow
== nEndRow
))
228 sal_uInt16 nNewPixel
= static_cast<sal_uInt16
>(rDoc
.GetRowHeight(nStartRow
,nTab
) * nPPTY
);
229 if ( nNewPixel
== nOldPixel
)
234 pDocSh
->PostPaint( 0, nStartRow
, nTab
, rDoc
.MaxCol(), rDoc
.MaxRow(), nTab
,
235 PaintPartFlags::Grid
| PaintPartFlags::Left
);
237 if (comphelper::LibreOfficeKit::isActive())
239 ScTabViewShell::notifyAllViewsSheetGeomInvalidation(
240 GetViewData().GetViewShell(),
241 false /* bColumns */, true /* bRows */,
242 true /* bSizes*/, false /* bHidden */, false /* bFiltered */,
243 false /* bGroups */, nTab
);
244 ScTabViewShell::notifyAllViewsHeaderInvalidation(GetViewData().GetViewShell(), ROW_HEADER
, GetViewData().GetTabNo());
272 static ScAutoSum
lcl_IsAutoSumData( ScDocument
& rDoc
, SCCOL nCol
, SCROW nRow
,
273 SCTAB nTab
, ScDirection eDir
, SCCOLROW
& nExtend
)
275 ScRefCellValue
aCell(rDoc
, ScAddress(nCol
, nRow
, nTab
));
276 if (aCell
.hasNumeric())
278 if (aCell
.getType() == CELLTYPE_FORMULA
)
280 ScAutoSum val
= ScAutoSumNone
;
281 ScTokenArray
* pCode
= aCell
.getFormula()->GetCode();
284 switch( pCode
->GetOuterFuncOpCode() )
286 case ocSum
: val
= ScAutoSumSum
;
288 case ocAverage
: val
= ScAutoSumAverage
;
290 case ocMax
: val
= ScAutoSumMax
;
292 case ocMin
: val
= ScAutoSumMin
;
294 case ocCount
: val
= ScAutoSumCount
;
296 case ocCount2
: val
= ScAutoSumCountA
;
298 case ocProduct
: val
= ScAutoSumProduct
;
300 case ocStDev
: val
= ScAutoSumStDev
;
302 case ocStDevP
: val
= ScAutoSumStDevP
;
304 case ocVar
: val
= ScAutoSumVar
;
306 case ocVarP
: val
= ScAutoSumVarP
;
311 if ( pCode
->GetAdjacentExtendOfOuterFuncRefs( nExtend
,
312 ScAddress( nCol
, nRow
, nTab
), eDir
) )
316 return ScAutoSumData
;
318 return ScAutoSumNone
;
321 #define SC_AUTOSUM_MAXCOUNT 20
323 static ScAutoSum
lcl_SeekAutoSumData( ScDocument
& rDoc
, SCCOL
& nCol
, SCROW
& nRow
,
324 SCTAB nTab
, ScDirection eDir
, SCCOLROW
& nExtend
)
326 sal_uInt16 nCount
= 0;
327 while (nCount
< SC_AUTOSUM_MAXCOUNT
)
329 if ( eDir
== DIR_TOP
)
334 return ScAutoSumNone
;
341 return ScAutoSumNone
;
344 if ( (eSum
= lcl_IsAutoSumData(
345 rDoc
, nCol
, nRow
, nTab
, eDir
, nExtend
)) != ScAutoSumNone
)
349 return ScAutoSumNone
;
352 #undef SC_AUTOSUM_MAXCOUNT
354 static bool lcl_FindNextSumEntryInColumn( ScDocument
& rDoc
, SCCOL nCol
, SCROW
& nRow
,
355 SCTAB nTab
, SCCOLROW
& nExtend
, SCROW nMinRow
)
357 const SCROW nTmp
= nRow
;
358 ScAutoSum eSkip
= ScAutoSumNone
;
361 eSkip
= lcl_IsAutoSumData( rDoc
, nCol
, nRow
, nTab
, DIR_TOP
, nExtend
);
362 if (eSkip
!= ScAutoSumData
|| nRow
<= nMinRow
)
366 return eSkip
>= ScAutoSumSum
&& nRow
< nTmp
;
369 static bool lcl_FindNextSumEntryInRow( ScDocument
& rDoc
, SCCOL
& nCol
, SCROW nRow
,
370 SCTAB nTab
, SCCOLROW
& nExtend
, SCCOL nMinCol
)
372 const SCCOL nTmp
= nCol
;
373 ScAutoSum eSkip
= ScAutoSumNone
;
376 eSkip
= lcl_IsAutoSumData( rDoc
, nCol
, nRow
, nTab
, DIR_LEFT
, nExtend
);
377 if (eSkip
!= ScAutoSumData
|| nCol
<= nMinCol
)
381 return eSkip
>= ScAutoSumSum
&& nCol
< nTmp
;
384 static ScAutoSum
lcl_GetAutoSumForColumnRange( ScDocument
& rDoc
, ScRangeList
& rRangeList
, const ScRange
& rRange
)
386 const ScAddress aStart
= rRange
.aStart
;
387 const ScAddress aEnd
= rRange
.aEnd
;
388 if ( aStart
.Col() != aEnd
.Col() )
390 return ScAutoSumNone
;
393 const SCTAB nTab
= aEnd
.Tab();
394 const SCCOL nCol
= aEnd
.Col();
395 SCROW nEndRow
= aEnd
.Row();
396 SCROW nStartRow
= nEndRow
;
397 SCCOLROW nExtend
= 0;
398 ScAutoSum eSum
= lcl_IsAutoSumData( rDoc
, nCol
, nEndRow
, nTab
, DIR_TOP
, nExtend
/*out*/ );
400 if ( eSum
>= ScAutoSumSum
)
402 bool bContinue
= false;
405 rRangeList
.push_back( ScRange( nCol
, nStartRow
, nTab
, nCol
, nEndRow
, nTab
) );
406 nEndRow
= static_cast< SCROW
>( nExtend
);
407 bContinue
= lcl_FindNextSumEntryInColumn( rDoc
, nCol
, nEndRow
/*inout*/, nTab
, nExtend
/*out*/, aStart
.Row() );
412 } while ( bContinue
);
416 while ( nStartRow
> aStart
.Row() )
418 eSum
= lcl_IsAutoSumData( rDoc
, nCol
, nStartRow
-1, nTab
, DIR_TOP
, nExtend
/*out*/ );
419 if (eSum
>= ScAutoSumSum
)
423 rRangeList
.push_back( ScRange( nCol
, nStartRow
, nTab
, nCol
, nEndRow
, nTab
) );
424 if (eSum
== ScAutoSumNone
)
425 eSum
= ScAutoSumData
;
431 static ScAutoSum
lcl_GetAutoSumForRowRange( ScDocument
& rDoc
, ScRangeList
& rRangeList
, const ScRange
& rRange
)
433 const ScAddress aStart
= rRange
.aStart
;
434 const ScAddress aEnd
= rRange
.aEnd
;
435 if ( aStart
.Row() != aEnd
.Row() )
437 return ScAutoSumNone
;
440 const SCTAB nTab
= aEnd
.Tab();
441 const SCROW nRow
= aEnd
.Row();
442 SCCOL nEndCol
= aEnd
.Col();
443 SCCOL nStartCol
= nEndCol
;
444 SCCOLROW nExtend
= 0;
445 ScAutoSum eSum
= lcl_IsAutoSumData( rDoc
, nEndCol
, nRow
, nTab
, DIR_LEFT
, nExtend
/*out*/ );
447 if ( eSum
>= ScAutoSumSum
)
449 bool bContinue
= false;
452 rRangeList
.push_back( ScRange( nStartCol
, nRow
, nTab
, nEndCol
, nRow
, nTab
) );
453 nEndCol
= static_cast< SCCOL
>( nExtend
);
454 bContinue
= lcl_FindNextSumEntryInRow( rDoc
, nEndCol
/*inout*/, nRow
, nTab
, nExtend
/*out*/, aStart
.Col() );
459 } while ( bContinue
);
463 while ( nStartCol
> aStart
.Col() )
465 eSum
= lcl_IsAutoSumData( rDoc
, nStartCol
-1, nRow
, nTab
, DIR_LEFT
, nExtend
/*out*/ );
466 if (eSum
>= ScAutoSumSum
)
470 rRangeList
.push_back( ScRange( nStartCol
, nRow
, nTab
, nEndCol
, nRow
, nTab
) );
471 if (eSum
== ScAutoSumNone
)
472 eSum
= ScAutoSumData
;
478 static sal_Int8
GetSubTotal( const OpCode eCode
)
483 case ocSum
: val
= 9;
485 case ocAverage
: val
= 1;
487 case ocMax
: val
= 4;
489 case ocMin
: val
= 5;
491 case ocCount
: val
= 2;
493 case ocCount2
: val
= 3;
495 case ocProduct
: val
= 6;
497 case ocStDev
: val
= 7;
499 case ocStDevP
: val
= 8;
501 case ocVar
: val
= 10;
503 case ocVarP
: val
= 11;
511 bool ScViewFunc::GetAutoSumArea( ScRangeList
& rRangeList
)
513 ScDocument
& rDoc
= GetViewData().GetDocument();
514 SCTAB nTab
= GetViewData().GetTabNo();
516 SCCOL nCol
= GetViewData().GetCurX();
517 SCROW nRow
= GetViewData().GetCurY();
519 SCCOL nStartCol
= nCol
;
520 SCROW nStartRow
= nRow
;
521 SCCOL nEndCol
= nCol
;
522 SCROW nEndRow
= nRow
;
523 SCCOL nSeekCol
= nCol
;
524 SCROW nSeekRow
= nRow
;
525 SCCOLROW nExtend
; // will become valid via reference for ScAutoSumSum
532 && ((eSum
= lcl_IsAutoSumData( rDoc
, nCol
, nRow
-1, nTab
,
533 DIR_TOP
, nExtend
/*out*/ )) == ScAutoSumData
)
534 && ((eSum
= lcl_IsAutoSumData( rDoc
, nCol
, nRow
-1, nTab
,
535 DIR_LEFT
, nExtend
/*out*/ )) == ScAutoSumData
)
541 else if ( nCol
!= 0 && (eSum
= lcl_IsAutoSumData( rDoc
, nCol
-1, nRow
, nTab
,
542 DIR_LEFT
, nExtend
/*out*/ )) == ScAutoSumData
)
547 else if ( (eSum
= lcl_SeekAutoSumData( rDoc
, nCol
, nSeekRow
, nTab
, DIR_TOP
, nExtend
/*out*/ )) != ScAutoSumNone
)
549 else if (( eSum
= lcl_SeekAutoSumData( rDoc
, nSeekCol
, nRow
, nTab
, DIR_LEFT
, nExtend
/*out*/ )) != ScAutoSumNone
)
556 nStartRow
= nSeekRow
; // nSeekRow might be adjusted via reference
557 if ( eSum
>= ScAutoSumSum
&& eSum
< ScAutoSumEnd
)
558 nEndRow
= nStartRow
; // only sum sums
560 nEndRow
= nRow
- 1; // maybe extend data area at bottom
564 nStartCol
= nSeekCol
; // nSeekCol might be adjusted via reference
565 if ( eSum
>= ScAutoSumSum
)
566 nEndCol
= nStartCol
; // only sum sums
568 nEndCol
= nCol
- 1; // maybe extend data area to the right
570 bool bContinue
= false;
573 if ( eSum
== ScAutoSumData
)
577 while ( nStartRow
!= 0 && lcl_IsAutoSumData( rDoc
, nCol
,
578 nStartRow
-1, nTab
, DIR_TOP
, nExtend
/*out*/ ) == eSum
)
583 while ( nStartCol
!= 0 && lcl_IsAutoSumData( rDoc
, nStartCol
-1,
584 nRow
, nTab
, DIR_LEFT
, nExtend
/*out*/ ) == eSum
)
588 rRangeList
.push_back(
589 ScRange( nStartCol
, nStartRow
, nTab
, nEndCol
, nEndRow
, nTab
) );
590 if ( eSum
>= ScAutoSumSum
)
594 nEndRow
= static_cast< SCROW
>( nExtend
);
595 bContinue
= lcl_FindNextSumEntryInColumn( rDoc
, nCol
, nEndRow
/*inout*/, nTab
, nExtend
/*out*/, 0 );
603 nEndCol
= static_cast< SCCOL
>( nExtend
);
604 bContinue
= lcl_FindNextSumEntryInRow( rDoc
, nEndCol
/*inout*/, nRow
, nTab
, nExtend
/*out*/, 0 );
611 } while ( bContinue
);
617 void ScViewFunc::EnterAutoSum(const ScRangeList
& rRangeList
, bool bSubTotal
, const ScAddress
& rAddr
, const OpCode eCode
)
619 OUString aFormula
= GetAutoSumFormula( rRangeList
, bSubTotal
, rAddr
, eCode
);
620 EnterBlock( aFormula
, nullptr );
623 bool ScViewFunc::AutoSum( const ScRange
& rRange
, bool bSubTotal
, bool bSetCursor
, bool bContinue
, const OpCode eCode
)
625 ScDocument
& rDoc
= GetViewData().GetDocument();
626 const SCTAB nTab
= rRange
.aStart
.Tab();
627 SCCOL nStartCol
= rRange
.aStart
.Col();
628 SCROW nStartRow
= rRange
.aStart
.Row();
629 const SCCOL nEndCol
= rRange
.aEnd
.Col();
630 const SCROW nEndRow
= rRange
.aEnd
.Row();
631 SCCOLROW nExtend
= 0; // out parameter for lcl_IsAutoSumData
633 // ignore rows at the top of the given range which don't contain autosum data
634 bool bRowData
= false;
635 for ( SCROW nRow
= nStartRow
; nRow
<= nEndRow
; ++nRow
)
637 for ( SCCOL nCol
= nStartCol
; nCol
<= nEndCol
; ++nCol
)
639 if ( lcl_IsAutoSumData( rDoc
, nCol
, nRow
, nTab
, DIR_TOP
, nExtend
) != ScAutoSumNone
)
656 // ignore columns at the left of the given range which don't contain autosum data
657 bool bColData
= false;
658 for ( SCCOL nCol
= nStartCol
; nCol
<= nEndCol
; ++nCol
)
660 for ( SCROW nRow
= nStartRow
; nRow
<= nEndRow
; ++nRow
)
662 if ( lcl_IsAutoSumData( rDoc
, nCol
, nRow
, nTab
, DIR_LEFT
, nExtend
) != ScAutoSumNone
)
679 const bool bEndRowEmpty
= rDoc
.IsBlockEmpty( nStartCol
, nEndRow
, nEndCol
, nEndRow
, nTab
);
680 const bool bEndColEmpty
= rDoc
.IsBlockEmpty( nEndCol
, nStartRow
, nEndCol
, nEndRow
, nTab
);
681 bool bRow
= ( nStartRow
!= nEndRow
) && ( bEndRowEmpty
|| !bEndColEmpty
);
682 bool bCol
= ( nStartCol
!= nEndCol
) && ( bEndColEmpty
|| nStartRow
== nEndRow
);
684 // find an empty row for entering the result
685 SCROW nInsRow
= nEndRow
;
686 if ( bRow
&& !bEndRowEmpty
)
688 if ( nInsRow
< rDoc
.MaxRow() )
691 while ( !rDoc
.IsBlockEmpty( nStartCol
, nInsRow
, nEndCol
, nInsRow
, nTab
) )
693 if ( nInsRow
< rDoc
.MaxRow() )
710 // find an empty column for entering the result
711 SCCOL nInsCol
= nEndCol
;
712 if ( bCol
&& !bEndColEmpty
)
714 if ( nInsCol
< rDoc
.MaxCol() )
717 while ( !rDoc
.IsBlockEmpty( nInsCol
, nStartRow
, nInsCol
, nEndRow
, nTab
) )
719 if ( nInsCol
< rDoc
.MaxCol() )
736 if ( !bRow
&& !bCol
)
741 SCCOL nMarkEndCol
= nEndCol
;
742 SCROW nMarkEndRow
= nEndRow
;
743 ScAutoSum eSum
= ScAutoSumNone
;
746 SCROW nColSumsStartRow
= 0;
747 SCCOL nRowSumsStartCol
= 0;
751 // calculate the row sums for all columns of the given range
753 SCROW nSumEndRow
= nEndRow
;
757 // the last row of the given range is empty;
758 // don't take into account for calculating the autosum
763 // increase mark range
767 for ( SCCOL nCol
= nStartCol
; nCol
<= nEndCol
; ++nCol
)
769 if ( !rDoc
.IsBlockEmpty( nCol
, nStartRow
, nCol
, nSumEndRow
, nTab
) )
771 ScRangeList aRangeList
;
772 // Include the originally selected start row.
773 const ScRange
aRange( nCol
, rRange
.aStart
.Row(), nTab
, nCol
, nSumEndRow
, nTab
);
774 if ( (eSum
= lcl_GetAutoSumForColumnRange( rDoc
, aRangeList
, aRange
)) != ScAutoSumNone
)
777 nRowSumsStartCol
= aRangeList
[0].aStart
.Col();
778 const OUString aFormula
= GetAutoSumFormula(
779 aRangeList
, bSubTotal
, ScAddress(nCol
, nInsRow
, nTab
), eCode
);
780 EnterData( nCol
, nInsRow
, nTab
, aFormula
);
788 // calculate the column sums for all rows of the given range
790 SCCOL nSumEndCol
= nEndCol
;
794 // the last column of the given range is empty;
795 // don't take into account for calculating the autosum
800 // increase mark range
804 for ( SCROW nRow
= nStartRow
; nRow
<= nEndRow
; ++nRow
)
806 if ( !rDoc
.IsBlockEmpty( nStartCol
, nRow
, nSumEndCol
, nRow
, nTab
) )
808 ScRangeList aRangeList
;
809 // Include the originally selected start column.
810 const ScRange
aRange( rRange
.aStart
.Col(), nRow
, nTab
, nSumEndCol
, nRow
, nTab
);
811 if ( (eSum
= lcl_GetAutoSumForRowRange( rDoc
, aRangeList
, aRange
)) != ScAutoSumNone
)
814 nColSumsStartRow
= aRangeList
[0].aStart
.Row();
815 const OUString aFormula
= GetAutoSumFormula( aRangeList
, bSubTotal
, ScAddress(nInsCol
, nRow
, nTab
), eCode
);
816 EnterData( nInsCol
, nRow
, nTab
, aFormula
);
822 // Set new mark range and cursor position.
823 // For sum of sums (and data until sum) mark the actual resulting range if
824 // there is only one, or the data range if more than one. Otherwise use the
825 // original selection. All extended by end column/row where the sum is put.
826 const ScRange
aMarkRange(
827 (eSum
>= ScAutoSumSum
?
828 (nRowSums
== 1 ? nRowSumsStartCol
: nStartCol
) :
829 rRange
.aStart
.Col()),
830 (eSum
>= ScAutoSumSum
?
831 (nColSums
== 1 ? nColSumsStartRow
: nStartRow
) :
832 rRange
.aStart
.Row()),
833 nTab
, nMarkEndCol
, nMarkEndRow
, nTab
);
834 MarkRange( aMarkRange
, false, bContinue
);
837 SetCursor( nMarkEndCol
, nMarkEndRow
);
843 OUString
ScViewFunc::GetAutoSumFormula( const ScRangeList
& rRangeList
, bool bSubTotal
, const ScAddress
& rAddr
, const OpCode eCode
)
845 ScViewData
& rViewData
= GetViewData();
846 ScDocument
& rDoc
= rViewData
.GetDocument();
847 ScTokenArray
aArray(rDoc
);
849 aArray
.AddOpCode(bSubTotal
? ocSubTotal
: eCode
);
850 aArray
.AddOpCode(ocOpen
);
854 aArray
.AddDouble( GetSubTotal( eCode
) );
855 aArray
.AddOpCode(ocSep
);
858 if(!rRangeList
.empty())
860 size_t ListSize
= rRangeList
.size();
861 for ( size_t i
= 0; i
< ListSize
; ++i
)
863 const ScRange
& r
= rRangeList
[i
];
865 aArray
.AddOpCode(ocSep
);
866 ScComplexRefData aRef
;
867 aRef
.InitRangeRel(rDoc
, r
, rAddr
);
868 aArray
.AddDoubleReference(aRef
);
872 aArray
.AddOpCode(ocClose
);
874 ScCompiler
aComp(rDoc
, rAddr
, aArray
, rDoc
.GetGrammar());
876 aComp
.CreateStringFromTokenArray(aBuf
);
878 return aBuf
.makeStringAndClear();
881 void ScViewFunc::EnterBlock( const OUString
& rString
, const EditTextObject
* pData
)
883 // test for multi selection
885 SCCOL nCol
= GetViewData().GetCurX();
886 SCROW nRow
= GetViewData().GetCurY();
887 SCTAB nTab
= GetViewData().GetTabNo();
888 ScMarkData
& rMark
= GetViewData().GetMarkData();
889 if ( rMark
.IsMultiMarked() )
891 rMark
.MarkToSimple();
892 if ( rMark
.IsMultiMarked() )
893 { // "Insert into multi selection not possible"
894 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0
);
896 // insert into single cell
898 EnterData(nCol
, nRow
, nTab
, *pData
);
900 EnterData( nCol
, nRow
, nTab
, rString
);
905 if (GetViewData().SelectionForbidsCellFill())
907 PaintArea(nCol
, nRow
, nCol
, nRow
); // possibly the edit-engine is still painted there
911 ScDocument
& rDoc
= GetViewData().GetDocument();
912 OUString aNewStr
= rString
;
915 const ScPatternAttr
* pOldPattern
= rDoc
.GetPattern( nCol
, nRow
, nTab
);
916 ScTabEditEngine
aEngine( *pOldPattern
, rDoc
.GetEnginePool(), &rDoc
);
917 aEngine
.SetTextCurrentDefaults(*pData
);
919 ScEditAttrTester
aTester( &aEngine
);
920 if (!aTester
.NeedsObject())
922 aNewStr
= aEngine
.GetText();
927 // Insert via PasteFromClip
928 weld::WaitObject
aWait(GetViewData().GetDialogParent());
930 ScAddress
aPos( nCol
, nRow
, nTab
);
932 ScDocumentUniquePtr
pInsDoc(new ScDocument( SCDOCMODE_CLIP
));
933 pInsDoc
->ResetClip( &rDoc
, nTab
);
935 if (aNewStr
[0] == '=') // Formula ?
937 // SetString not possible, because in Clipboard-Documents nothing will be compiled!
938 pInsDoc
->SetFormulaCell(aPos
, new ScFormulaCell(rDoc
, aPos
, aNewStr
));
942 // A copy of pData will be stored.
943 pInsDoc
->SetEditText(aPos
, *pData
, rDoc
.GetEditPool());
946 pInsDoc
->SetString( nCol
, nRow
, nTab
, aNewStr
);
948 pInsDoc
->SetClipArea( ScRange(aPos
) );
949 // insert Block, with Undo etc.
950 if ( !PasteFromClip( InsertDeleteFlags::CONTENTS
, pInsDoc
.get(), ScPasteFunc::NONE
, false, false,
951 false, INS_NONE
, InsertDeleteFlags::ATTRIB
) )
954 const SfxUInt32Item
* pItem
= pInsDoc
->GetAttr(
955 nCol
, nRow
, nTab
, ATTR_VALUE_FORMAT
);
957 { // set number format if incompatible
958 // MarkData was already MarkToSimple'ed in PasteFromClip
959 const ScRange
& aRange
= rMark
.GetMarkArea();
960 ScPatternAttr
aPattern(rDoc
.getCellAttributeHelper());
961 aPattern
.GetItemSet().Put( *pItem
);
962 SvNumFormatType nNewType
= rDoc
.GetFormatTable()->GetType( pItem
->GetValue() );
963 rDoc
.ApplyPatternIfNumberformatIncompatible( aRange
, rMark
,
964 aPattern
, nNewType
);
970 void ScViewFunc::InsertPageBreak( bool bColumn
, bool bRecord
, const ScAddress
* pPos
,
973 SCTAB nTab
= GetViewData().GetTabNo();
978 aCursor
= ScAddress( GetViewData().GetCurX(), GetViewData().GetCurY(), nTab
);
980 bool bSuccess
= GetViewData().GetDocShell()->GetDocFunc().
981 InsertPageBreak( bColumn
, aCursor
, bRecord
, bSetModified
);
983 if ( bSuccess
&& bSetModified
)
984 UpdatePageBreakData( true ); // for PageBreak-Mode
987 void ScViewFunc::DeletePageBreak( bool bColumn
, bool bRecord
, const ScAddress
* pPos
,
990 SCTAB nTab
= GetViewData().GetTabNo();
995 aCursor
= ScAddress( GetViewData().GetCurX(), GetViewData().GetCurY(), nTab
);
997 bool bSuccess
= GetViewData().GetDocShell()->GetDocFunc().
998 RemovePageBreak( bColumn
, aCursor
, bRecord
, bSetModified
);
1000 if ( bSuccess
&& bSetModified
)
1001 UpdatePageBreakData( true ); // for PageBreak-Mode
1004 void ScViewFunc::RemoveManualBreaks()
1006 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
1007 ScDocument
& rDoc
= pDocSh
->GetDocument();
1008 SCTAB nTab
= GetViewData().GetTabNo();
1009 bool bUndo(rDoc
.IsUndoEnabled());
1013 ScDocumentUniquePtr
pUndoDoc(new ScDocument( SCDOCMODE_UNDO
));
1014 pUndoDoc
->InitUndo( rDoc
, nTab
, nTab
, true, true );
1015 rDoc
.CopyToDocument( 0,0,nTab
, rDoc
.MaxCol(), rDoc
.MaxRow(), nTab
, InsertDeleteFlags::NONE
, false, *pUndoDoc
);
1016 pDocSh
->GetUndoManager()->AddUndoAction(
1017 std::make_unique
<ScUndoRemoveBreaks
>( pDocSh
, nTab
, std::move(pUndoDoc
) ) );
1020 rDoc
.RemoveManualBreaks(nTab
);
1021 rDoc
.UpdatePageBreaks(nTab
);
1023 UpdatePageBreakData( true );
1024 pDocSh
->SetDocumentModified();
1025 pDocSh
->PostPaint( 0,0,nTab
, rDoc
.MaxCol(), rDoc
.MaxRow(), nTab
, PaintPartFlags::Grid
);
1028 void ScViewFunc::SetPrintZoom(sal_uInt16 nScale
)
1030 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
1031 SCTAB nTab
= GetViewData().GetTabNo();
1032 pDocSh
->SetPrintZoom( nTab
, nScale
, 0/*nPages*/ );
1035 void ScViewFunc::AdjustPrintZoom()
1038 if ( GetViewData().GetSimpleArea( aRange
) != SC_MARK_SIMPLE
)
1039 aRange
= GetViewData().GetMarkData().GetMultiMarkArea();
1040 GetViewData().GetDocShell()->AdjustPrintZoom( aRange
);
1043 void ScViewFunc::SetPrintRanges( bool bEntireSheet
, const OUString
* pPrint
,
1044 const OUString
* pRepCol
, const OUString
* pRepRow
,
1047 // on all selected tables
1049 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
1050 ScDocument
& rDoc
= pDocSh
->GetDocument();
1051 ScMarkData
& rMark
= GetViewData().GetMarkData();
1052 bool bUndo (rDoc
.IsUndoEnabled());
1054 std::unique_ptr
<ScPrintRangeSaver
> pOldRanges
= rDoc
.CreatePrintRangeSaver();
1056 ScAddress::Details
aDetails(rDoc
.GetAddressConvention(), 0, 0);
1058 for (const SCTAB
& nTab
: rMark
)
1060 ScRange
aRange( 0,0,nTab
);
1066 rDoc
.ClearPrintRanges( nTab
);
1067 rDoc
.ClearPrintNamedRanges(nTab
);
1072 rDoc
.SetPrintEntireSheet( nTab
);
1076 if ( !pPrint
->isEmpty() )
1078 const sal_Unicode sep
= ScCompiler::GetNativeSymbolChar(ocSep
);
1082 const OUString aToken
= pPrint
->getToken(0, sep
, nPos
);
1083 if ( aRange
.ParseAny( aToken
, rDoc
, aDetails
) & ScRefFlags::VALID
)
1084 rDoc
.AddPrintRange( nTab
, aRange
);
1089 else // NULL = use selection (print range is always set), use empty string to delete all ranges
1091 if ( GetViewData().GetSimpleArea( aRange
) == SC_MARK_SIMPLE
)
1093 rDoc
.AddPrintRange( nTab
, aRange
);
1095 else if ( rMark
.IsMultiMarked() )
1097 rMark
.MarkToMulti();
1098 ScRangeListRef
pList( new ScRangeList
);
1099 rMark
.FillRangeListWithMarks( pList
.get(), false );
1100 for (size_t i
= 0, n
= pList
->size(); i
< n
; ++i
)
1102 const ScRange
& rR
= (*pList
)[i
];
1103 rDoc
.AddPrintRange(nTab
, rR
);
1112 if ( pRepCol
->isEmpty() )
1113 rDoc
.SetRepeatColRange( nTab
, std::nullopt
);
1115 if ( aRange
.ParseAny( *pRepCol
, rDoc
, aDetails
) & ScRefFlags::VALID
)
1116 rDoc
.SetRepeatColRange( nTab
, std::move(aRange
) );
1123 if ( pRepRow
->isEmpty() )
1124 rDoc
.SetRepeatRowRange( nTab
, std::nullopt
);
1126 if ( aRange
.ParseAny( *pRepRow
, rDoc
, aDetails
) & ScRefFlags::VALID
)
1127 rDoc
.SetRepeatRowRange( nTab
, std::move(aRange
) );
1131 // undo (for all tables)
1134 SCTAB nCurTab
= GetViewData().GetTabNo();
1135 std::unique_ptr
<ScPrintRangeSaver
> pNewRanges
= rDoc
.CreatePrintRangeSaver();
1136 if (comphelper::LibreOfficeKit::isActive())
1138 tools::JsonWriter aJsonWriter
;
1139 pNewRanges
->GetPrintRangesInfo(aJsonWriter
);
1141 SfxViewShell
* pViewShell
= GetViewData().GetViewShell();
1142 const OString message
= aJsonWriter
.finishAndGetAsOString();
1143 pViewShell
->libreOfficeKitViewCallback(LOK_CALLBACK_PRINT_RANGES
, message
);
1146 pDocSh
->GetUndoManager()->AddUndoAction(
1147 std::make_unique
<ScUndoPrintRange
>( pDocSh
, nCurTab
, std::move(pOldRanges
), std::move(pNewRanges
) ) );
1152 // update page breaks
1154 for (const auto& rTab
: rMark
)
1155 ScPrintFunc( pDocSh
, pDocSh
->GetPrinter(), rTab
).UpdatePages();
1157 SfxBindings
& rBindings
= GetViewData().GetBindings();
1158 rBindings
.Invalidate( SID_DELETE_PRINTAREA
);
1160 pDocSh
->SetDocumentModified();
1165 bool ScViewFunc::TestMergeCells() // pre-test (for menu)
1167 // simple test: true if there's a selection but no multi selection and not filtered
1169 const ScMarkData
& rMark
= GetViewData().GetMarkData();
1170 if ( rMark
.IsMarked() || rMark
.IsMultiMarked() )
1173 bool bMergeable
= ( GetViewData().GetSimpleArea( aRange
) == SC_MARK_SIMPLE
);
1174 bMergeable
= bMergeable
&& ( aRange
.aStart
.Col() != aRange
.aEnd
.Col() ||
1175 aRange
.aStart
.Row() != aRange
.aEnd
.Row() );
1182 void ScViewFunc::MergeCells( bool bApi
, bool bDoContents
, bool bCenter
,
1183 const sal_uInt16 nSlot
)
1185 // Editable- and Being-Nested- test must be at the beginning (in DocFunc too),
1186 // so that the Contents-QueryBox won't appear
1187 ScEditableTester
aTester( this );
1188 if (!aTester
.IsEditable())
1190 ErrorMessage(aTester
.GetMessageId());
1194 ScMarkData
& rMark
= GetViewData().GetMarkData();
1195 rMark
.MarkToSimple();
1196 if (!rMark
.IsMarked())
1198 ErrorMessage(STR_NOMULTISELECT
);
1202 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
1203 ScDocument
& rDoc
= pDocSh
->GetDocument();
1205 const ScRange
& aMarkRange
= rMark
.GetMarkArea();
1206 SCCOL nStartCol
= aMarkRange
.aStart
.Col();
1207 SCROW nStartRow
= aMarkRange
.aStart
.Row();
1208 SCTAB nStartTab
= aMarkRange
.aStart
.Tab();
1209 SCCOL nEndCol
= aMarkRange
.aEnd
.Col();
1210 SCROW nEndRow
= aMarkRange
.aEnd
.Row();
1211 SCTAB nEndTab
= aMarkRange
.aEnd
.Tab();
1212 if ( nStartCol
== nEndCol
&& nStartRow
== nEndRow
)
1218 if ( rDoc
.HasAttrib( nStartCol
, nStartRow
, nStartTab
, nEndCol
, nEndRow
, nEndTab
,
1219 HasAttrFlags::Merged
| HasAttrFlags::Overlapped
) )
1220 { // "Don't nest merging !"
1221 ErrorMessage(STR_MSSG_MERGECELLS_0
);
1225 // Check for the contents of all selected tables.
1226 bool bAskDialog
= false;
1227 ScCellMergeOption
aMergeOption(nStartCol
, nStartRow
, nEndCol
, nEndRow
, bCenter
);
1228 for (const SCTAB
& i
: rMark
)
1230 aMergeOption
.maTabs
.insert(i
);
1232 sc::MultiDataCellState aState
= rDoc
.HasMultipleDataCells(aMergeOption
.getSingleRange(i
));
1233 switch (aState
.meState
)
1235 case sc::MultiDataCellState::HasMultipleCells
:
1237 // this range contains multiple data cells.
1241 case sc::MultiDataCellState::HasOneCell
:
1243 // this range contains only one data cell.
1244 if (nStartCol
!= aState
.mnCol1
|| nStartRow
!= aState
.mnRow1
)
1245 bDoContents
= true; // move the value to the top-left.
1253 bool bEmptyMergedCells
= officecfg::Office::Calc::Compatibility::MergeCells::EmptyMergedCells::get();
1255 auto doMerge
= [this, pDocSh
, aMergeOption
=std::move(aMergeOption
),
1256 bApi
, nStartCol
, nStartRow
, aMarkRange
]
1257 (bool bNowDoContents
, bool bNowEmptyMergedCells
)
1259 if (pDocSh
->GetDocFunc().MergeCells(aMergeOption
, bNowDoContents
, true/*bRecord*/,
1260 bApi
, bNowEmptyMergedCells
))
1262 SetCursor( nStartCol
, nStartRow
);
1263 // DoneBlockMode( sal_False);
1266 pDocSh
->UpdateOle(GetViewData());
1269 OUString aStartAddress
= aMarkRange
.aStart
.GetColRowString();
1270 OUString aEndAddress
= aMarkRange
.aEnd
.GetColRowString();
1272 collectUIInformation({{"RANGE", aStartAddress
+ ":" + aEndAddress
}}, u
"MERGE_CELLS"_ustr
);
1278 bool bShowDialog
= officecfg::Office::Calc::Compatibility::MergeCells::ShowDialog::get();
1279 if (!bApi
&& bShowDialog
)
1281 auto pBox
= std::make_shared
<ScMergeCellsDialog
>(GetViewData().GetDialogParent());
1283 SfxViewShell
* pViewShell
= GetViewData().GetViewShell();
1285 weld::DialogController::runAsync(pBox
, [pBox
, bDoContents
, bEmptyMergedCells
, pViewShell
,
1286 nSlot
, bApi
, doMerge
=std::move(doMerge
)](sal_Int32 nRetVal
) {
1287 if (nRetVal
== RET_OK
)
1289 bool bRealDoContents
= bDoContents
;
1290 bool bRealEmptyMergedCells
= bEmptyMergedCells
;
1291 switch (pBox
->GetMergeCellsOption())
1293 case MoveContentHiddenCells
:
1294 bRealDoContents
= true;
1296 case KeepContentHiddenCells
:
1297 bRealEmptyMergedCells
= false;
1299 case EmptyContentHiddenCells
:
1300 bRealEmptyMergedCells
= true;
1303 assert(!"Unknown option for merge cells.");
1307 doMerge(bRealDoContents
, bRealEmptyMergedCells
);
1311 SfxRequest
aReq(pViewShell
->GetViewFrame(), nSlot
);
1312 if (!bApi
&& bRealDoContents
)
1313 aReq
.AppendItem(SfxBoolItem(nSlot
, bDoContents
));
1314 SfxBindings
& rBindings
= pViewShell
->GetViewFrame().GetBindings();
1315 rBindings
.Invalidate(nSlot
);
1323 doMerge(bDoContents
, bEmptyMergedCells
);
1326 bool ScViewFunc::TestRemoveMerge()
1328 bool bMerged
= false;
1330 if (GetViewData().GetSimpleArea( aRange
) == SC_MARK_SIMPLE
)
1332 ScDocument
& rDoc
= GetViewData().GetDocument();
1333 if ( rDoc
.HasAttrib( aRange
, HasAttrFlags::Merged
) )
1339 static bool lcl_extendMergeRange(ScCellMergeOption
& rOption
, const ScRange
& rRange
)
1341 bool bExtended
= false;
1342 if (rOption
.mnStartCol
> rRange
.aStart
.Col())
1344 rOption
.mnStartCol
= rRange
.aStart
.Col();
1347 if (rOption
.mnStartRow
> rRange
.aStart
.Row())
1349 rOption
.mnStartRow
= rRange
.aStart
.Row();
1352 if (rOption
.mnEndCol
< rRange
.aEnd
.Col())
1354 rOption
.mnEndCol
= rRange
.aEnd
.Col();
1357 if (rOption
.mnEndRow
< rRange
.aEnd
.Row())
1359 rOption
.mnEndRow
= rRange
.aEnd
.Row();
1365 bool ScViewFunc::RemoveMerge()
1368 ScEditableTester
aTester( this );
1369 if (!aTester
.IsEditable())
1371 ErrorMessage(aTester
.GetMessageId());
1374 else if (GetViewData().GetSimpleArea( aRange
) == SC_MARK_SIMPLE
)
1376 ScDocument
& rDoc
= GetViewData().GetDocument();
1377 ScRange
aExtended( aRange
);
1378 rDoc
.ExtendMerge( aExtended
);
1379 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
1380 const ScMarkData
& rMark
= GetViewData().GetMarkData();
1381 ScCellMergeOption
aOption(aRange
.aStart
.Col(), aRange
.aStart
.Row(), aRange
.aEnd
.Col(), aRange
.aEnd
.Row());
1382 bool bExtended
= false;
1386 for (const SCTAB
& i
: rMark
)
1388 aOption
.maTabs
.insert(i
);
1389 aExtended
.aStart
.SetTab(i
);
1390 aExtended
.aEnd
.SetTab(i
);
1391 rDoc
.ExtendMerge(aExtended
);
1392 rDoc
.ExtendOverlapped(aExtended
);
1394 // Expand the current range to be inclusive of all merged
1395 // areas on all sheets.
1396 bExtended
= lcl_extendMergeRange(aOption
, aExtended
);
1401 bool bOk
= pDocSh
->GetDocFunc().UnmergeCells(aOption
, true/*bRecord*/, nullptr);
1402 aExtended
= aOption
.getFirstSingleRange();
1403 MarkRange( aExtended
);
1406 pDocSh
->UpdateOle(GetViewData());
1409 OUString aCellLocation
= aRange
.aStart
.GetColRowString();
1410 collectUIInformation({{"CELL", aCellLocation
}}, u
"UNMERGE_CELL"_ustr
);
1412 return true; //! bOk ??
1415 void ScViewFunc::FillSimple( FillDir eDir
)
1418 if (GetViewData().GetSimpleArea(aRange
) == SC_MARK_SIMPLE
)
1420 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
1421 const ScMarkData
& rMark
= GetViewData().GetMarkData();
1422 bool bSuccess
= pDocSh
->GetDocFunc().FillSimple( aRange
, &rMark
, eDir
, false );
1425 pDocSh
->UpdateOle(GetViewData());
1428 auto& rDoc
= pDocSh
->GetDocument();
1429 const ScTabViewShell
* pTabViewShell
= GetViewData().GetViewShell();
1430 const bool bDoAutoSpell
= pTabViewShell
&& pTabViewShell
->IsAutoSpell();
1433 // Copy AutoSpellData from above(left/right/below) if no selection.
1436 case FILL_TO_BOTTOM
:
1437 if (aRange
.aStart
.Row() > 0 && aRange
.aStart
.Row() == aRange
.aEnd
.Row())
1438 aRange
.aStart
.IncRow(-1);
1441 if (aRange
.aEnd
.Row() < rDoc
.MaxRow() && aRange
.aStart
.Row() == aRange
.aEnd
.Row())
1442 aRange
.aEnd
.IncRow(1);
1445 if (aRange
.aStart
.Col() > 0 && aRange
.aStart
.Col() == aRange
.aEnd
.Col())
1446 aRange
.aStart
.IncCol(-1);
1449 if (aRange
.aEnd
.Col() < rDoc
.MaxCol() && aRange
.aStart
.Col() == aRange
.aEnd
.Col())
1450 aRange
.aEnd
.IncCol(1);
1453 CopyAutoSpellData(eDir
, aRange
.aStart
.Col(), aRange
.aStart
.Row(), aRange
.aEnd
.Col(), aRange
.aEnd
.Row(),
1454 ::std::numeric_limits
<sal_uLong
>::max());
1457 // Invalidate cell slots and update input line with new content.
1458 CellContentChanged();
1462 ErrorMessage(STR_NOMULTISELECT
);
1465 void ScViewFunc::FillSeries( FillDir eDir
, FillCmd eCmd
, FillDateCmd eDateCmd
,
1466 double fStart
, double fStep
, double fMax
)
1469 if (GetViewData().GetSimpleArea(aRange
) == SC_MARK_SIMPLE
)
1471 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
1472 const ScMarkData
& rMark
= GetViewData().GetMarkData();
1473 bool bSuccess
= pDocSh
->GetDocFunc().
1474 FillSeries( aRange
, &rMark
, eDir
, eCmd
, eDateCmd
,
1475 fStart
, fStep
, fMax
, false );
1478 pDocSh
->UpdateOle(GetViewData());
1481 HelperNotifyChanges::NotifyIfChangesListeners(*pDocSh
, aRange
);
1485 ErrorMessage(STR_NOMULTISELECT
);
1488 void ScViewFunc::FillAuto( FillDir eDir
, SCCOL nStartCol
, SCROW nStartRow
,
1489 SCCOL nEndCol
, SCROW nEndRow
, sal_uLong nCount
)
1491 SCTAB nTab
= GetViewData().GetTabNo();
1492 ScRange
aRange( nStartCol
,nStartRow
,nTab
, nEndCol
,nEndRow
,nTab
);
1493 ScRange
aSourceRange( aRange
);
1494 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
1495 const ScMarkData
& rMark
= GetViewData().GetMarkData();
1496 bool bSuccess
= pDocSh
->GetDocFunc().
1497 FillAuto( aRange
, &rMark
, eDir
, nCount
, false );
1501 MarkRange( aRange
, false ); // aRange was modified in FillAuto
1502 pDocSh
->UpdateOle(GetViewData());
1505 const ScTabViewShell
* pTabViewShell
= GetViewData().GetViewShell();
1506 const bool bDoAutoSpell
= pTabViewShell
&& pTabViewShell
->IsAutoSpell();
1508 CopyAutoSpellData(eDir
, nStartCol
, nStartRow
, nEndCol
, nEndRow
, nCount
);
1510 ScModelObj
* pModelObj
= pDocSh
->GetModel();
1512 ScRangeList aChangeRanges
;
1513 ScRange
aChangeRange( aRange
);
1516 case FILL_TO_BOTTOM
:
1517 aChangeRange
.aStart
.SetRow( aSourceRange
.aEnd
.Row() + 1 );
1520 aChangeRange
.aEnd
.SetRow( aSourceRange
.aStart
.Row() - 1 );
1523 aChangeRange
.aStart
.SetCol( aSourceRange
.aEnd
.Col() + 1 );
1526 aChangeRange
.aEnd
.SetCol( aSourceRange
.aStart
.Col() - 1 );
1531 aChangeRanges
.push_back( aChangeRange
);
1533 if (HelperNotifyChanges::getMustPropagateChangesModel(pModelObj
))
1534 HelperNotifyChanges::Notify(*pModelObj
, aChangeRanges
);
1536 HelperNotifyChanges::Notify(*pModelObj
, aChangeRanges
, u
"data-area-invalidate"_ustr
);
1539 void ScViewFunc::CopyAutoSpellData( FillDir eDir
, SCCOL nStartCol
, SCROW nStartRow
,
1540 SCCOL nEndCol
, SCROW nEndRow
, sal_uLong nCount
)
1542 const ScDocument
* pDoc
= &GetViewData().GetDocument();
1543 SCTAB nTab
= GetViewData().GetTabNo();
1546 ScGridWindow
* pWin
= GetActiveWin();
1547 if ( pWin
->InsideVisibleRange(nStartCol
, nStartRow
) && pWin
->InsideVisibleRange(nEndCol
, nEndRow
) )
1549 if ( nCount
== ::std::numeric_limits
<sal_uLong
>::max() )
1553 case FILL_TO_BOTTOM
:
1554 for ( SCCOL nColItr
= nStartCol
; nColItr
<= nEndCol
; ++nColItr
)
1556 eCellType
= pDoc
->GetCellType(nColItr
, nStartRow
, nTab
); // We need this optimization only for EditTextObject source cells
1557 if (eCellType
!= CELLTYPE_EDIT
)
1560 const std::vector
<editeng::MisspellRanges
>* pRanges
= pWin
->GetAutoSpellData(nColItr
, nStartRow
);
1563 for ( SCROW nRowItr
= nStartRow
+ 1; nRowItr
<= nEndRow
; ++nRowItr
)
1564 pWin
->SetAutoSpellData(nColItr
, nRowItr
, pRanges
);
1568 for ( SCCOL nColItr
= nStartCol
; nColItr
<= nEndCol
; ++nColItr
)
1570 eCellType
= pDoc
->GetCellType(nColItr
, nEndRow
, nTab
); // We need this optimization only for EditTextObject source cells
1571 if (eCellType
!= CELLTYPE_EDIT
)
1574 const std::vector
<editeng::MisspellRanges
>* pRanges
= pWin
->GetAutoSpellData(nColItr
, nEndRow
);
1577 for ( SCROW nRowItr
= nEndRow
- 1; nRowItr
>= nStartRow
; --nRowItr
)
1578 pWin
->SetAutoSpellData(nColItr
, nRowItr
, pRanges
);
1582 for ( SCROW nRowItr
= nStartRow
; nRowItr
<= nEndRow
; ++nRowItr
)
1584 eCellType
= pDoc
->GetCellType(nStartCol
, nRowItr
, nTab
); // We need this optimization only for EditTextObject source cells
1585 if (eCellType
!= CELLTYPE_EDIT
)
1588 const std::vector
<editeng::MisspellRanges
>* pRanges
= pWin
->GetAutoSpellData(nStartCol
, nRowItr
);
1591 for ( SCCOL nColItr
= nStartCol
+ 1; nColItr
<= nEndCol
; ++nColItr
)
1592 pWin
->SetAutoSpellData(nColItr
, nRowItr
, pRanges
);
1596 for ( SCROW nRowItr
= nStartRow
; nRowItr
<= nEndRow
; ++nRowItr
)
1598 eCellType
= pDoc
->GetCellType(nEndCol
, nRowItr
, nTab
); // We need this optimization only for EditTextObject source cells
1599 if (eCellType
!= CELLTYPE_EDIT
)
1602 const std::vector
<editeng::MisspellRanges
>* pRanges
= pWin
->GetAutoSpellData(nEndCol
, nRowItr
);
1605 for ( SCCOL nColItr
= nEndCol
- 1; nColItr
>= nStartCol
; --nColItr
)
1606 pWin
->SetAutoSpellData(nColItr
, nRowItr
, pRanges
);
1613 typedef const std::vector
<editeng::MisspellRanges
>* MisspellRangesType
;
1614 SCROW nRowRepeatSize
= nEndRow
- nStartRow
+ 1;
1615 SCCOL nColRepeatSize
= nEndCol
- nStartCol
+ 1;
1618 std::vector
<std::vector
<MisspellRangesType
>> aSourceSpellRanges(nRowRepeatSize
, std::vector
<MisspellRangesType
>(nColRepeatSize
, nullptr));
1620 for ( SCROW nRowIdx
= 0; nRowIdx
< nRowRepeatSize
; ++nRowIdx
)
1622 for ( SCCOL nColIdx
= 0; nColIdx
< nColRepeatSize
; ++nColIdx
)
1624 eCellType
= pDoc
->GetCellType(nStartCol
+ nColIdx
, nStartRow
+ nRowIdx
, nTab
); // We need this optimization only for EditTextObject source cells
1625 if (eCellType
!= CELLTYPE_EDIT
)
1628 aSourceSpellRanges
[nRowIdx
][nColIdx
] = pWin
->GetAutoSpellData( nStartCol
+ nColIdx
, nStartRow
+ nRowIdx
);
1634 case FILL_TO_BOTTOM
:
1635 nTillRow
= nEndRow
+ nCount
;
1636 for ( SCCOL nColItr
= nStartCol
; nColItr
<= nEndCol
; ++nColItr
)
1638 for ( SCROW nRowItr
= nEndRow
+ 1; nRowItr
<= nTillRow
; ++nRowItr
)
1640 size_t nSourceRowIdx
= ( nRowItr
- nEndRow
- 1 ) % nRowRepeatSize
;
1641 MisspellRangesType pRanges
= aSourceSpellRanges
[nSourceRowIdx
][nColItr
- nStartCol
];
1644 pWin
->SetAutoSpellData(nColItr
, nRowItr
, pRanges
);
1650 nTillRow
= nStartRow
- nCount
;
1651 for ( SCCOL nColItr
= nStartCol
; nColItr
<= nEndCol
; ++nColItr
)
1653 for ( SCROW nRowItr
= nStartRow
- 1; nRowItr
>= nTillRow
; --nRowItr
)
1655 size_t nSourceRowIdx
= nRowRepeatSize
- 1 - ( ( nStartRow
- 1 - nRowItr
) % nRowRepeatSize
);
1656 MisspellRangesType pRanges
= aSourceSpellRanges
[nSourceRowIdx
][nColItr
- nStartCol
];
1659 pWin
->SetAutoSpellData(nColItr
, nRowItr
, pRanges
);
1665 nTillCol
= nEndCol
+ nCount
;
1666 for ( SCCOL nColItr
= nEndCol
+ 1; nColItr
<= nTillCol
; ++nColItr
)
1668 size_t nSourceColIdx
= ( nColItr
- nEndCol
- 1 ) % nColRepeatSize
;
1669 for ( SCROW nRowItr
= nStartRow
; nRowItr
<= nEndRow
; ++nRowItr
)
1671 MisspellRangesType pRanges
= aSourceSpellRanges
[nRowItr
- nStartRow
][nSourceColIdx
];
1674 pWin
->SetAutoSpellData(nColItr
, nRowItr
, pRanges
);
1680 nTillCol
= nStartCol
- nCount
;
1681 for ( SCCOL nColItr
= nStartCol
- 1; nColItr
>= nTillCol
; --nColItr
)
1683 size_t nSourceColIdx
= nColRepeatSize
- 1 - ( ( nStartCol
- 1 - nColItr
) % nColRepeatSize
);
1684 for ( SCROW nRowItr
= nStartRow
; nRowItr
<= nEndRow
; ++nRowItr
)
1686 MisspellRangesType pRanges
= aSourceSpellRanges
[nRowItr
- nStartRow
][nSourceColIdx
];
1689 pWin
->SetAutoSpellData(nColItr
, nRowItr
, pRanges
);
1696 pWin
->ResetAutoSpellForContentChange();
1700 void ScViewFunc::FillTab( InsertDeleteFlags nFlags
, ScPasteFunc nFunction
, bool bSkipEmpty
, bool bAsLink
)
1702 //! allow source sheet to be protected
1703 ScEditableTester
aTester( this );
1704 if (!aTester
.IsEditable())
1706 ErrorMessage(aTester
.GetMessageId());
1710 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
1711 ScDocument
& rDoc
= pDocSh
->GetDocument();
1712 ScMarkData
& rMark
= GetViewData().GetMarkData();
1713 SCTAB nTab
= GetViewData().GetTabNo();
1714 bool bUndo(rDoc
.IsUndoEnabled());
1717 rMark
.MarkToSimple();
1718 bool bMulti
= rMark
.IsMultiMarked();
1720 aMarkRange
= rMark
.GetMultiMarkArea();
1721 else if (rMark
.IsMarked())
1722 aMarkRange
= rMark
.GetMarkArea();
1724 aMarkRange
= ScRange( GetViewData().GetCurX(), GetViewData().GetCurY(), nTab
);
1726 ScDocumentUniquePtr pUndoDoc
;
1730 pUndoDoc
.reset(new ScDocument( SCDOCMODE_UNDO
));
1731 pUndoDoc
->InitUndo( rDoc
, nTab
, nTab
);
1733 for (const SCTAB
& i
: rMark
)
1736 pUndoDoc
->AddUndoTab( i
, i
);
1737 aMarkRange
.aStart
.SetTab( i
);
1738 aMarkRange
.aEnd
.SetTab( i
);
1739 rDoc
.CopyToDocument( aMarkRange
, InsertDeleteFlags::ALL
, bMulti
, *pUndoDoc
);
1744 rDoc
.FillTabMarked( nTab
, rMark
, nFlags
, nFunction
, bSkipEmpty
, bAsLink
);
1747 aMarkRange
.aStart
.SetTab( nTab
);
1748 aMarkRange
.aEnd
.SetTab( nTab
);
1749 rDoc
.FillTab( aMarkRange
, rMark
, nFlags
, nFunction
, bSkipEmpty
, bAsLink
);
1753 { //! for ChangeTrack not until the end
1754 pDocSh
->GetUndoManager()->AddUndoAction(
1755 std::make_unique
<ScUndoFillTable
>( pDocSh
, rMark
,
1756 aMarkRange
.aStart
.Col(), aMarkRange
.aStart
.Row(), nTab
,
1757 aMarkRange
.aEnd
.Col(), aMarkRange
.aEnd
.Row(), nTab
,
1758 std::move(pUndoDoc
), bMulti
, nTab
, nFlags
, nFunction
, bSkipEmpty
, bAsLink
) );
1761 pDocSh
->PostPaintGridAll();
1762 pDocSh
->PostDataChanged();
1765 /** Downward fill of selected cell(s) by double-clicking cross-hair cursor
1767 Either, extends a current selection if non-empty cells exist immediately
1768 below the selection, overwriting cells below the selection up to the
1769 minimum row of already filled cells.
1771 Or, extends a current selection down to the last non-empty cell of an
1772 adjacent column when the lower-right corner of the selection is
1773 double-clicked. It uses a left-adjoining non-empty column as a guide if
1774 such is available, otherwise a right-adjoining non-empty column is used.
1776 @return No return value
1780 void ScViewFunc::FillCrossDblClick()
1783 GetViewData().GetSimpleArea( aRange
);
1784 aRange
.PutInOrder();
1786 SCTAB nTab
= GetViewData().GetCurPos().Tab();
1787 SCCOL nStartX
= aRange
.aStart
.Col();
1788 SCROW nStartY
= aRange
.aStart
.Row();
1789 SCCOL nEndX
= aRange
.aEnd
.Col();
1790 SCROW nEndY
= aRange
.aEnd
.Row();
1792 ScDocument
& rDoc
= GetViewData().GetDocument();
1794 if (nEndY
>= rDoc
.MaxRow())
1798 // Make sure the selection is not empty
1799 if ( rDoc
.IsBlockEmpty( nStartX
, nStartY
, nEndX
, nEndY
, nTab
) )
1802 // If there is data in all columns immediately below the selection then
1803 // switch to overwriting fill.
1804 SCROW nOverWriteEndRow
= rDoc
.MaxRow();
1805 for (SCCOL nCol
= nStartX
; nCol
<= nEndX
; ++nCol
)
1807 if (rDoc
.HasData( nCol
, nEndY
+ 1, nTab
))
1809 // Determine the shortest data column to end the fill.
1810 SCROW nY
= nEndY
+ 1;
1811 // FindAreaPos() returns the start row of the next data block if
1812 // the current row is the last row of a data block and an empty
1813 // cell follows. Somewhat unexpected behaviour...
1814 // So check beforehand if there is one non-empty cell following.
1815 if (rDoc
.HasData( nCol
, nY
+ 1, nTab
))
1817 rDoc
.FindAreaPos( nCol
, nY
, nTab
, SC_MOVE_DOWN
);
1818 if (nOverWriteEndRow
> nY
)
1819 nOverWriteEndRow
= nY
;
1823 nOverWriteEndRow
= nY
;
1828 nOverWriteEndRow
= 0;
1833 if (nOverWriteEndRow
> nEndY
)
1835 FillAuto( FILL_TO_BOTTOM
, nStartX
, nStartY
, nEndX
, nEndY
, nOverWriteEndRow
- nEndY
);
1839 // Non-overwriting fill follows.
1841 const bool bDataLeft
= (nStartX
> 0);
1842 if (!bDataLeft
&& nEndX
>= rDoc
.MaxCol())
1843 // Absolutely no data left or right of selection.
1846 // Check that there is
1847 // 1) data immediately left (preferred) or right of start (row) of selection
1848 // 2) data there below
1849 // 3) no data immediately below selection
1851 SCCOL nMovX
= (bDataLeft
? nStartX
- 1 : nEndX
+ 1);
1852 SCROW nMovY
= nStartY
;
1853 bool bDataFound
= (rDoc
.HasData( nMovX
, nStartY
, nTab
) && rDoc
.HasData( nMovX
, nStartY
+ 1, nTab
));
1854 if (!bDataFound
&& bDataLeft
&& nEndX
< rDoc
.MaxCol())
1856 nMovX
= nEndX
+ 1; // check right
1857 bDataFound
= (rDoc
.HasData( nMovX
, nStartY
, nTab
) && rDoc
.HasData( nMovX
, nStartY
+ 1, nTab
));
1860 if (!(bDataFound
&& rDoc
.IsEmptyData( nStartX
, nEndY
+ 1, nEndX
, nEndY
+ 1, nTab
)))
1863 // Get end of data left or right.
1864 rDoc
.FindAreaPos( nMovX
, nMovY
, nTab
, SC_MOVE_DOWN
);
1865 // Find minimum end row of below empty area and data right.
1866 for (SCCOL nX
= nStartX
; nX
<= nEndX
; ++nX
)
1868 SCROW nY
= nEndY
+ 1;
1869 // Get next row with data in this column.
1870 rDoc
.FindAreaPos( nX
, nY
, nTab
, SC_MOVE_DOWN
);
1871 if (nMovY
== rDoc
.MaxRow() && nY
== rDoc
.MaxRow())
1873 // FindAreaPos() returns MAXROW also if there is no data at all
1874 // from the start, so check if that contains data if the nearby
1875 // (left or right) data ends there and increment if no data
1876 // here, pretending the next data would be thereafter so nMovY
1877 // will not be decremented.
1878 if (!rDoc
.HasData( nX
, nY
, nTab
))
1887 FillAuto( FILL_TO_BOTTOM
, nStartX
, nStartY
, nEndX
, nEndY
, nMovY
- nEndY
);
1891 void ScViewFunc::ConvertFormulaToValue()
1894 GetViewData().GetSimpleArea(aRange
);
1895 aRange
.PutInOrder();
1897 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
1898 pDocSh
->GetDocFunc().ConvertFormulaToValue(aRange
, true);
1899 // tdf#131326 - invalidate cell slots and update input line with new content
1900 CellContentChanged();
1901 pDocSh
->PostPaint(aRange
, PaintPartFlags::Grid
);
1904 void ScViewFunc::TransliterateText( TransliterationFlags nType
)
1906 ScMarkData aFuncMark
= GetViewData().GetMarkData();
1907 if ( !aFuncMark
.IsMarked() && !aFuncMark
.IsMultiMarked() )
1909 // no selection -> use cursor position
1911 ScAddress
aCursor( GetViewData().GetCurX(), GetViewData().GetCurY(), GetViewData().GetTabNo() );
1912 aFuncMark
.SetMarkArea( ScRange( aCursor
) );
1915 bool bSuccess
= GetViewData().GetDocShell()->GetDocFunc().
1916 TransliterateText( aFuncMark
, nType
, false );
1919 GetViewData().GetViewShell()->UpdateInputHandler();
1925 ScAutoFormatData
* ScViewFunc::CreateAutoFormatData()
1927 ScAutoFormatData
* pData
= nullptr;
1934 if (GetViewData().GetSimpleArea(nStartCol
,nStartRow
,nStartTab
,nEndCol
,nEndRow
,nEndTab
) == SC_MARK_SIMPLE
)
1936 if ( nEndCol
-nStartCol
>= 3 && nEndRow
-nStartRow
>= 3 )
1938 ScDocument
& rDoc
= GetViewData().GetDocument();
1939 pData
= new ScAutoFormatData
;
1940 rDoc
.GetAutoFormatData( nStartTab
, nStartCol
,nStartRow
,nEndCol
,nEndRow
, *pData
);
1946 void ScViewFunc::AutoFormat( sal_uInt16 nFormatNo
)
1949 if (GetViewData().GetSimpleArea(aRange
) == SC_MARK_SIMPLE
)
1951 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
1952 ScMarkData
& rMark
= GetViewData().GetMarkData();
1954 bool bSuccess
= pDocSh
->GetDocFunc().AutoFormat( aRange
, &rMark
, nFormatNo
, false );
1956 pDocSh
->UpdateOle(GetViewData());
1959 ErrorMessage(STR_NOMULTISELECT
);
1964 bool ScViewFunc::SearchAndReplace( const SvxSearchItem
* pSearchItem
,
1965 bool bAddUndo
, bool bIsApi
)
1967 SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::Empty
);
1968 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
1969 ScDocument
& rDoc
= pDocSh
->GetDocument();
1970 ScMarkData
& rMark
= GetViewData().GetMarkData();
1971 if (bAddUndo
&& !rDoc
.IsUndoEnabled())
1974 if ( !rMark
.IsMarked() && !rMark
.IsMultiMarked() && (pSearchItem
->HasStartPoint()) )
1976 // No selection -> but we have a start point (top left corner of the
1977 // current view), start searching from there, not from the current
1982 int nPixelX
= pSearchItem
->GetStartPointX() * GetViewData().GetPPTX();
1983 int nPixelY
= pSearchItem
->GetStartPointY() * GetViewData().GetPPTY();
1985 GetViewData().GetPosFromPixel(nPixelX
, nPixelY
, GetViewData().GetActivePart(), nPosX
, nPosY
);
1987 AlignToCursor( nPosX
, nPosY
, SC_FOLLOW_JUMP
);
1988 SetCursor( nPosX
, nPosY
, true );
1991 SCCOL nCol
, nOldCol
;
1992 SCROW nRow
, nOldRow
;
1993 SCTAB nTab
, nOldTab
;
1994 nCol
= nOldCol
= GetViewData().GetCurX();
1995 nRow
= nOldRow
= GetViewData().GetCurY();
1996 nTab
= nOldTab
= GetViewData().GetTabNo();
1998 SvxSearchCmd nCommand
= pSearchItem
->GetCommand();
1999 bool bAllTables
= pSearchItem
->IsAllTables();
2000 std::set
<SCTAB
> aOldSelectedTables
;
2001 SCTAB nLastTab
= rDoc
.GetTableCount() - 1;
2002 SCTAB nStartTab
, nEndTab
;
2007 std::set
<SCTAB
> aTmp(rMark
.begin(), rMark
.end());
2008 aOldSelectedTables
.swap(aTmp
);
2011 { //! at least one is always selected
2012 nStartTab
= rMark
.GetFirstSelected();
2013 nEndTab
= rMark
.GetLastSelected();
2016 if ( nCommand
== SvxSearchCmd::FIND
2017 || nCommand
== SvxSearchCmd::FIND_ALL
)
2020 //! account for bAttrib during Undo !!!
2022 ScDocumentUniquePtr pUndoDoc
;
2023 std::unique_ptr
<ScMarkData
> pUndoMark
;
2027 pUndoMark
.reset(new ScMarkData(rMark
)); // Mark is being modified
2028 if ( nCommand
== SvxSearchCmd::REPLACE_ALL
)
2030 pUndoDoc
.reset(new ScDocument(SCDOCMODE_UNDO
));
2031 pUndoDoc
->InitUndo( rDoc
, nStartTab
, nEndTab
);
2036 { //! select all, after pUndoMark has been created
2037 for ( SCTAB j
= nStartTab
; j
<= nEndTab
; j
++ )
2039 rMark
.SelectTable( j
, true );
2043 DoneBlockMode(true); // don't delete mark
2044 InitOwnBlockMode( ScRange( nCol
, nRow
, nStartTab
, nCol
, nRow
, nEndTab
));
2046 // If search starts at the beginning don't ask again whether it shall start at the beginning
2048 if ( nCol
== 0 && nRow
== 0 && nTab
== nStartTab
&& !pSearchItem
->GetBackward() )
2051 bool bFound
= false;
2054 GetFrameWin()->EnterWait();
2055 ScRangeList aMatchedRanges
;
2056 bool bMatchedRangesWereClamped
= false;
2057 if (rDoc
.SearchAndReplace(*pSearchItem
, nCol
, nRow
, nTab
, rMark
, aMatchedRanges
, aUndoStr
, pUndoDoc
.get(), bMatchedRangesWereClamped
))
2062 GetViewData().GetDocShell()->GetUndoManager()->AddUndoAction(
2063 std::make_unique
<ScUndoReplace
>( GetViewData().GetDocShell(), *pUndoMark
,
2065 aUndoStr
, std::move(pUndoDoc
), pSearchItem
) );
2068 if (nCommand
== SvxSearchCmd::FIND_ALL
|| nCommand
== SvxSearchCmd::REPLACE_ALL
)
2070 SfxViewFrame
* pViewFrm
= SfxViewFrame::Current();
2071 bool bShow
= GetViewData().GetViewShell()->GetViewData().GetOptions().GetOption( VOPT_SUMMARY
);
2073 if (bShow
&& pViewFrm
&& !comphelper::LibreOfficeKit::isActive())
2075 pViewFrm
->ShowChildWindow(sc::SearchResultsDlgWrapper::GetChildWindowId());
2076 SfxChildWindow
* pWnd
= pViewFrm
->GetChildWindow(sc::SearchResultsDlgWrapper::GetChildWindowId());
2079 sc::SearchResultsDlg
* pDlg
= static_cast<sc::SearchResultsDlg
*>(pWnd
->GetController().get());
2082 const bool bCellNotes
= (pSearchItem
->GetCellType() == SvxSearchCellType::NOTE
);
2083 // ScCellIterator iterates over cells with content,
2084 // for empty cells iterate over match positions.
2085 const bool bEmptyCells
= (!bCellNotes
2086 && ((nCommand
== SvxSearchCmd::FIND_ALL
2087 && ScDocument::IsEmptyCellSearch(*pSearchItem
))
2088 || (nCommand
== SvxSearchCmd::REPLACE_ALL
2089 && pSearchItem
->GetReplaceString().isEmpty())));
2090 pDlg
->FillResults(rDoc
, aMatchedRanges
, bCellNotes
, bEmptyCells
, bMatchedRangesWereClamped
);
2096 for (size_t i
= 0, n
= aMatchedRanges
.size(); i
< n
; ++i
)
2098 const ScRange
& r
= aMatchedRanges
[i
];
2099 if (r
.aStart
.Tab() == nTab
)
2100 rMark
.SetMultiMarkArea(r
);
2104 break; // break 'while (TRUE)'
2106 else if ( bFirst
&& (nCommand
== SvxSearchCmd::FIND
||
2107 nCommand
== SvxSearchCmd::REPLACE
) )
2110 GetFrameWin()->LeaveWait();
2113 if ( nStartTab
== nEndTab
)
2114 SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::EndSheet
);
2116 SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::End
);
2118 rDoc
.GetSearchAndReplaceStart( *pSearchItem
, nCol
, nRow
);
2119 if (pSearchItem
->GetBackward())
2126 break; // break 'while (TRUE)'
2129 else // nothing found
2131 if ( nCommand
== SvxSearchCmd::FIND_ALL
|| nCommand
== SvxSearchCmd::REPLACE_ALL
)
2133 pDocSh
->PostPaintGridAll(); // Mark
2136 GetFrameWin()->LeaveWait();
2139 GetViewData().GetViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_SEARCH_NOT_FOUND
, pSearchItem
->GetSearchString().toUtf8());
2140 SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::NotFound
);
2143 break; // break 'while (TRUE)'
2147 if (!aOldSelectedTables
.empty())
2149 // restore originally selected table
2150 for (SCTAB i
= 0; i
<= nEndTab
; ++i
)
2151 rMark
.SelectTable(i
, false);
2153 for (const auto& rTab
: aOldSelectedTables
)
2154 rMark
.SelectTable(rTab
, true);
2157 { // if a table is selected as a "match" it remains selected.
2158 rMark
.SelectTable( nTab
, true );
2159 // It's a swap if only one table was selected before
2160 //! otherwise now one table more might be selected
2161 if ( aOldSelectedTables
.size() == 1 && nTab
!= nOldTab
)
2162 rMark
.SelectTable( nOldTab
, false );
2166 // Avoid LOK selection notifications before we have all the results.
2167 GetViewData().GetViewShell()->setTiledSearching(true);
2169 GetViewData().GetViewShell()->setTiledSearching(false);
2173 if ( nTab
!= GetViewData().GetTabNo() )
2176 // if nothing is marked, DoneBlockMode, then marking can start
2177 // directly from this place via Shift-Cursor
2178 if (!rMark
.IsMarked() && !rMark
.IsMultiMarked())
2179 DoneBlockMode(true);
2181 AlignToCursor( nCol
, nRow
, SC_FOLLOW_JUMP
);
2182 SetCursor( nCol
, nRow
, true );
2184 if (comphelper::LibreOfficeKit::isActive())
2186 Point aCurPos
= GetViewData().GetScrPos(nCol
, nRow
, GetViewData().GetActivePart());
2188 // just update the cell selection
2189 ScGridWindow
* pGridWindow
= GetViewData().GetActiveWin();
2190 // Don't move cell selection handles for find-all: selection of all but the first result would be lost.
2191 if (pGridWindow
&& nCommand
== SvxSearchCmd::FIND
)
2193 // move the cell selection handles
2194 pGridWindow
->SetCellSelectionPixel(LOK_SETTEXTSELECTION_RESET
, aCurPos
.X(), aCurPos
.Y());
2195 pGridWindow
->SetCellSelectionPixel(LOK_SETTEXTSELECTION_START
, aCurPos
.X(), aCurPos
.Y());
2196 pGridWindow
->SetCellSelectionPixel(LOK_SETTEXTSELECTION_END
, aCurPos
.X(), aCurPos
.Y());
2201 std::vector
<tools::Rectangle
> aLogicRects
;
2202 pGridWindow
->GetCellSelection(aLogicRects
);
2204 boost::property_tree::ptree aTree
;
2205 aTree
.put("searchString", pSearchItem
->GetSearchString().toUtf8().getStr());
2206 aTree
.put("highlightAll", nCommand
== SvxSearchCmd::FIND_ALL
);
2208 boost::property_tree::ptree aSelections
;
2209 for (const tools::Rectangle
& rLogicRect
: aLogicRects
)
2211 boost::property_tree::ptree aSelection
;
2212 aSelection
.put("part", OString::number(nTab
).getStr());
2213 aSelection
.put("rectangles", rLogicRect
.toString().getStr());
2214 aSelections
.push_back(std::make_pair("", aSelection
));
2216 aTree
.add_child("searchResultSelection", aSelections
);
2218 std::stringstream aStream
;
2219 boost::property_tree::write_json(aStream
, aTree
);
2220 OString
aPayload( aStream
.str() );
2221 SfxViewShell
* pViewShell
= GetViewData().GetViewShell();
2222 pViewShell
->libreOfficeKitViewCallback(LOK_CALLBACK_SEARCH_RESULT_SELECTION
, aPayload
);
2224 // Trigger LOK_CALLBACK_TEXT_SELECTION now.
2229 if ( nCommand
== SvxSearchCmd::REPLACE
2230 || nCommand
== SvxSearchCmd::REPLACE_ALL
)
2232 if ( nCommand
== SvxSearchCmd::REPLACE
)
2234 pDocSh
->PostPaint( nCol
,nRow
,nTab
, nCol
,nRow
,nTab
, PaintPartFlags::Grid
);
2236 // jump to next cell if we replaced everything in the cell
2237 // where the cursor was positioned (but avoid switching tabs)
2238 if ( nCol
== nOldCol
&& nRow
== nOldRow
&& nTab
== nOldTab
)
2240 SvxSearchItem aSearchItem
= ScGlobal::GetSearchItem();
2241 aSearchItem
.SetCommand(SvxSearchCmd::FIND
);
2242 aSearchItem
.SetWhich(SID_SEARCH_ITEM
);
2244 ScRangeList aMatchedRanges
;
2245 bool bMatchedRangesWereClamped
;
2246 ScTable::UpdateSearchItemAddressForReplace( aSearchItem
, nCol
, nRow
);
2247 if ( rDoc
.SearchAndReplace( aSearchItem
, nCol
, nRow
, nTab
, rMark
, aMatchedRanges
, aUndoStr
, nullptr, bMatchedRangesWereClamped
) &&
2248 ( nTab
== nOldTab
) &&
2249 ( nCol
!= nOldCol
|| nRow
!= nOldRow
) )
2251 AlignToCursor(nCol
, nRow
, SC_FOLLOW_JUMP
);
2252 SetCursor( nCol
, nRow
, true );
2257 pDocSh
->PostPaintGridAll();
2258 pDocSh
->SetDocumentModified();
2260 else if ( nCommand
== SvxSearchCmd::FIND_ALL
)
2261 pDocSh
->PostPaintGridAll(); // mark
2262 GetFrameWin()->LeaveWait();
2269 void ScViewFunc::Solve( const ScSolveParam
& rParam
)
2271 ScDocument
& rDoc
= GetViewData().GetDocument();
2273 SCCOL nDestCol
= rParam
.aRefVariableCell
.Col();
2274 SCROW nDestRow
= rParam
.aRefVariableCell
.Row();
2275 SCTAB nDestTab
= rParam
.aRefVariableCell
.Tab();
2277 ScEditableTester
aTester( rDoc
, nDestTab
, nDestCol
,nDestRow
, nDestCol
,nDestRow
);
2278 if (!aTester
.IsEditable())
2280 ErrorMessage(aTester
.GetMessageId());
2284 OUString aTargetValStr
;
2285 if ( rParam
.pStrTargetVal
)
2286 aTargetValStr
= *rParam
.pStrTargetVal
;
2290 double nSolveResult
;
2291 GetFrameWin()->EnterWait();
2295 rParam
.aRefFormulaCell
.Col(),
2296 rParam
.aRefFormulaCell
.Row(),
2297 rParam
.aRefFormulaCell
.Tab(),
2298 nDestCol
, nDestRow
, nDestTab
,
2302 GetFrameWin()->LeaveWait();
2304 SvNumberFormatter
* pFormatter
= rDoc
.GetFormatTable();
2305 sal_uLong nFormat
= 0;
2306 const ScPatternAttr
* pPattern
= rDoc
.GetPattern( nDestCol
, nDestRow
, nDestTab
);
2308 nFormat
= pPattern
->GetNumberFormat( pFormatter
);
2310 pFormatter
->GetOutputString( nSolveResult
, nFormat
, aResStr
, &p
);
2314 aMsgStr
+= ScResId( STR_MSSG_SOLVE_0
) +
2316 ScResId( STR_MSSG_SOLVE_1
);
2320 aMsgStr
= ScResId( STR_MSSG_SOLVE_2
) +
2321 ScResId( STR_MSSG_SOLVE_3
) +
2323 ScResId( STR_MSSG_SOLVE_4
);
2326 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(GetViewData().GetDialogParent(),
2327 VclMessageType::Question
, VclButtonsType::YesNo
, aMsgStr
));
2328 xBox
->set_title(ScResId(STR_MSSG_DOSUBTOTALS_0
));
2329 xBox
->set_default_response(RET_NO
);
2330 int nResponse
= xBox
->run();
2331 if (nResponse
== RET_YES
)
2332 EnterValue( nDestCol
, nDestRow
, nDestTab
, nSolveResult
);
2334 GetViewData().GetViewShell()->UpdateInputHandler( true );
2339 void ScViewFunc::TabOp( const ScTabOpParam
& rParam
, bool bRecord
)
2342 if (GetViewData().GetSimpleArea(aRange
) == SC_MARK_SIMPLE
)
2344 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
2345 ScMarkData
& rMark
= GetViewData().GetMarkData();
2346 pDocSh
->GetDocFunc().TabOp( aRange
, &rMark
, rParam
, bRecord
, false );
2349 ErrorMessage(STR_NOMULTISELECT
);
2352 void ScViewFunc::MakeScenario( const OUString
& rName
, const OUString
& rComment
,
2353 const Color
& rColor
, ScScenarioFlags nFlags
)
2355 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
2356 ScMarkData
& rMark
= GetViewData().GetMarkData();
2357 SCTAB nTab
= GetViewData().GetTabNo();
2359 SCTAB nNewTab
= pDocSh
->MakeScenario( nTab
, rName
, rComment
, rColor
, nFlags
, rMark
);
2360 if (nFlags
& ScScenarioFlags::CopyAll
)
2361 SetTabNo( nNewTab
, true ); // ScScenarioFlags::CopyAll -> visible
2364 SfxBindings
& rBindings
= GetViewData().GetBindings();
2365 rBindings
.Invalidate( SID_STATUS_DOCPOS
); // Statusbar
2366 rBindings
.Invalidate( SID_ROWCOL_SELCOUNT
); // Statusbar
2367 rBindings
.Invalidate( SID_TABLES_COUNT
);
2368 rBindings
.Invalidate( SID_SELECT_SCENARIO
);
2369 rBindings
.Invalidate( FID_TABLE_SHOW
);
2373 void ScViewFunc::ExtendScenario()
2375 ScEditableTester
aTester( this );
2376 if (!aTester
.IsEditable())
2378 ErrorMessage(aTester
.GetMessageId());
2382 // Undo: apply attributes
2384 ScDocument
& rDoc
= GetViewData().GetDocument();
2385 ScPatternAttr
aPattern(rDoc
.getCellAttributeHelper());
2386 aPattern
.GetItemSet().Put( ScMergeFlagAttr( ScMF::Scenario
) );
2387 aPattern
.GetItemSet().Put( ScProtectionAttr( true ) );
2388 ApplySelectionPattern(aPattern
);
2391 void ScViewFunc::UseScenario( const OUString
& rName
)
2393 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
2394 SCTAB nTab
= GetViewData().GetTabNo();
2397 InitOwnBlockMode( ScRange( GetViewData().GetCurX(), GetViewData().GetCurY(), nTab
));
2398 pDocSh
->UseScenario( nTab
, rName
);
2403 bool ScViewFunc::InsertTable( const OUString
& rName
, SCTAB nTab
, bool bRecord
)
2405 // Order Table/Name is inverted for DocFunc
2406 bool bSuccess
= GetViewData().GetDocShell()->GetDocFunc().
2407 InsertTable( nTab
, rName
, bRecord
, false );
2409 SetTabNo( nTab
, true );
2416 void ScViewFunc::InsertTables(std::vector
<OUString
>& aNames
, SCTAB nTab
,
2417 SCTAB nCount
, bool bRecord
)
2419 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
2420 ScDocument
& rDoc
= pDocSh
->GetDocument();
2421 if (bRecord
&& !rDoc
.IsUndoEnabled())
2424 weld::WaitObject
aWait(GetViewData().GetDialogParent());
2428 rDoc
.BeginDrawUndo(); // InsertTab creates a SdrUndoNewPage
2435 rDoc
.CreateValidTabNames(aNames
, nCount
);
2437 if (rDoc
.InsertTabs(nTab
, aNames
))
2439 pDocSh
->Broadcast( ScTablesHint( SC_TABS_INSERTED
, nTab
, nCount
) );
2447 pDocSh
->GetUndoManager()->AddUndoAction(
2448 std::make_unique
<ScUndoInsertTables
>( pDocSh
, nTab
, std::move(aNames
)));
2452 SetTabNo( nTab
, true );
2453 pDocSh
->PostPaintExtras();
2454 pDocSh
->SetDocumentModified();
2455 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScTablesChanged
) );
2458 bool ScViewFunc::AppendTable( const OUString
& rName
, bool bRecord
)
2460 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
2461 ScDocument
& rDoc
= pDocSh
->GetDocument();
2462 if (bRecord
&& !rDoc
.IsUndoEnabled())
2465 weld::WaitObject
aWait(GetViewData().GetDialogParent());
2468 rDoc
.BeginDrawUndo(); // InsertTab creates a SdrUndoNewPage
2470 if (rDoc
.InsertTab( SC_TAB_APPEND
, rName
))
2472 SCTAB nTab
= rDoc
.GetTableCount()-1;
2474 pDocSh
->GetUndoManager()->AddUndoAction(
2475 std::make_unique
<ScUndoInsertTab
>( pDocSh
, nTab
, true, rName
));
2476 GetViewData().InsertTab( nTab
);
2477 SetTabNo( nTab
, true );
2478 pDocSh
->PostPaintExtras();
2479 pDocSh
->SetDocumentModified();
2480 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScTablesChanged
) );
2489 void ScViewFunc::DeleteTable( SCTAB nTab
, bool bRecord
)
2491 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
2492 ScDocument
& rDoc
= pDocSh
->GetDocument();
2494 bool bSuccess
= pDocSh
->GetDocFunc().DeleteTable( nTab
, bRecord
);
2497 SCTAB nNewTab
= nTab
;
2498 if ( nNewTab
>= rDoc
.GetTableCount() )
2500 SetTabNo( nNewTab
, true );
2504 //only use this method for undo for now, all sheets must be connected
2505 //this method doesn't support undo for now, merge it when it with the other method later
2506 void ScViewFunc::DeleteTables( const SCTAB nTab
, SCTAB nSheets
)
2508 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
2509 ScDocument
& rDoc
= pDocSh
->GetDocument();
2510 bool bVbaEnabled
= rDoc
.IsInVBAMode();
2511 SCTAB nNewTab
= nTab
;
2512 weld::WaitObject
aWait(GetViewData().GetDialogParent());
2514 while ( nNewTab
> 0 && !rDoc
.IsVisible( nNewTab
) )
2517 if (!rDoc
.DeleteTabs(nTab
, nSheets
))
2522 for (SCTAB aTab
= 0; aTab
< nSheets
; ++aTab
)
2525 bool bHasCodeName
= rDoc
.GetCodeName( nTab
+ aTab
, sCodeName
);
2527 VBA_DeleteModule( *pDocSh
, sCodeName
);
2531 pDocSh
->Broadcast( ScTablesHint( SC_TABS_DELETED
, nTab
, nSheets
) );
2532 if ( nNewTab
>= rDoc
.GetTableCount() )
2533 nNewTab
= rDoc
.GetTableCount() - 1;
2534 SetTabNo( nNewTab
, true );
2536 pDocSh
->PostPaintExtras();
2537 pDocSh
->SetDocumentModified();
2539 SfxApplication
* pSfxApp
= SfxGetpApp(); // Navigator
2540 pSfxApp
->Broadcast( SfxHint( SfxHintId::ScTablesChanged
) );
2541 pSfxApp
->Broadcast( SfxHint( SfxHintId::ScDbAreasChanged
) );
2542 pSfxApp
->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged
) );
2545 bool ScViewFunc::DeleteTables(const vector
<SCTAB
> &TheTabs
, bool bRecord
)
2547 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
2548 ScDocument
& rDoc
= pDocSh
->GetDocument();
2549 bool bVbaEnabled
= rDoc
.IsInVBAMode();
2550 SCTAB nNewTab
= TheTabs
.front();
2551 weld::WaitObject
aWait(GetViewData().GetDialogParent());
2552 if (bRecord
&& !rDoc
.IsUndoEnabled())
2557 while ( nNewTab
> 0 && !rDoc
.IsVisible( nNewTab
) )
2560 bool bWasLinked
= false;
2561 ScDocumentUniquePtr pUndoDoc
;
2562 std::unique_ptr
<ScRefUndoData
> pUndoData
;
2565 pUndoDoc
.reset(new ScDocument( SCDOCMODE_UNDO
));
2566 SCTAB nCount
= rDoc
.GetTableCount();
2569 bool isFirstTab
= true;
2570 for(SCTAB nTab
: TheTabs
)
2574 pUndoDoc
->InitUndo( rDoc
, nTab
,nTab
, true,true ); // incl. column/fow flags
2578 pUndoDoc
->AddUndoTab( nTab
,nTab
, true,true ); // incl. column/fow flags
2580 rDoc
.CopyToDocument(0,0,nTab
, rDoc
.MaxCol(), rDoc
.MaxRow(), nTab
, InsertDeleteFlags::ALL
,false, *pUndoDoc
);
2581 rDoc
.GetName( nTab
, aOldName
);
2582 pUndoDoc
->RenameTab( nTab
, aOldName
);
2583 if (rDoc
.IsLinked(nTab
))
2586 pUndoDoc
->SetLink( nTab
, rDoc
.GetLinkMode(nTab
), rDoc
.GetLinkDoc(nTab
),
2587 rDoc
.GetLinkFlt(nTab
), rDoc
.GetLinkOpt(nTab
),
2588 rDoc
.GetLinkTab(nTab
),
2589 rDoc
.GetLinkRefreshDelay(nTab
) );
2591 if ( rDoc
.IsScenario(nTab
) )
2593 pUndoDoc
->SetScenario( nTab
, true );
2596 ScScenarioFlags nScenFlags
;
2597 rDoc
.GetScenarioData( nTab
, aComment
, aColor
, nScenFlags
);
2598 pUndoDoc
->SetScenarioData( nTab
, aComment
, aColor
, nScenFlags
);
2599 bool bActive
= rDoc
.IsActiveScenario( nTab
);
2600 pUndoDoc
->SetActiveScenario( nTab
, bActive
);
2602 pUndoDoc
->SetVisible( nTab
, rDoc
.IsVisible( nTab
) );
2603 pUndoDoc
->SetTabBgColor( nTab
, rDoc
.GetTabBgColor(nTab
) );
2604 auto pSheetEvents
= rDoc
.GetSheetEvents( nTab
);
2605 pUndoDoc
->SetSheetEvents( nTab
, std::unique_ptr
<ScSheetEvents
>(pSheetEvents
? new ScSheetEvents(*pSheetEvents
) : nullptr) );
2606 pUndoDoc
->SetLayoutRTL( nTab
, rDoc
.IsLayoutRTL( nTab
) );
2608 if ( rDoc
.IsTabProtected( nTab
) )
2609 pUndoDoc
->SetTabProtection(nTab
, rDoc
.GetTabProtection(nTab
));
2611 // Drawing-Layer is responsible for its Undo !!!
2612 // pUndoDoc->TransferDrawPage(rDoc, nTab,nTab);
2615 pUndoDoc
->AddUndoTab( 0, nCount
-1 ); // all Tabs for references
2617 rDoc
.BeginDrawUndo(); // DeleteTab creates a SdrUndoDelPage
2619 pUndoData
.reset(new ScRefUndoData( &rDoc
));
2622 bool bDelDone
= false;
2624 for(int i
=TheTabs
.size()-1; i
>=0; --i
)
2627 bool bHasCodeName
= rDoc
.GetCodeName( TheTabs
[i
], sCodeName
);
2628 if (rDoc
.DeleteTab(TheTabs
[i
]))
2631 if( bVbaEnabled
&& bHasCodeName
)
2633 VBA_DeleteModule( *pDocSh
, sCodeName
);
2635 pDocSh
->Broadcast( ScTablesHint( SC_TAB_DELETED
, TheTabs
[i
] ) );
2640 pDocSh
->GetUndoManager()->AddUndoAction(
2641 std::make_unique
<ScUndoDeleteTab
>( GetViewData().GetDocShell(), TheTabs
,
2642 std::move(pUndoDoc
), std::move(pUndoData
) ));
2647 if ( nNewTab
>= rDoc
.GetTableCount() )
2648 nNewTab
= rDoc
.GetTableCount() - 1;
2650 SetTabNo( nNewTab
, true );
2654 pDocSh
->UpdateLinks(); // update Link-Manager
2655 GetViewData().GetBindings().Invalidate(SID_LINKS
);
2658 pDocSh
->PostPaintExtras();
2659 pDocSh
->SetDocumentModified();
2661 SfxApplication
* pSfxApp
= SfxGetpApp(); // Navigator
2662 pSfxApp
->Broadcast( SfxHint( SfxHintId::ScTablesChanged
) );
2663 pSfxApp
->Broadcast( SfxHint( SfxHintId::ScAreasChanged
) );
2664 pSfxApp
->Broadcast( SfxHint( SfxHintId::ScDbAreasChanged
) );
2665 pSfxApp
->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged
) );
2670 bool ScViewFunc::RenameTable( const OUString
& rName
, SCTAB nTab
)
2672 // order Table/Name is inverted for DocFunc
2673 bool bSuccess
= GetViewData().GetDocShell()->GetDocFunc().
2674 RenameTable( nTab
, rName
, true, false );
2677 // the table name might be part of a formula
2678 GetViewData().GetViewShell()->UpdateInputHandler();
2683 bool ScViewFunc::SetTabBgColor( const Color
& rColor
, SCTAB nTab
)
2685 bool bSuccess
= GetViewData().GetDocShell()->GetDocFunc().SetTabBgColor( nTab
, rColor
, true, false );
2688 GetViewData().GetViewShell()->UpdateInputHandler();
2693 bool ScViewFunc::SetTabBgColor( ScUndoTabColorInfo::List
& rUndoSetTabBgColorInfoList
)
2695 bool bSuccess
= GetViewData().GetDocShell()->GetDocFunc().SetTabBgColor( rUndoSetTabBgColorInfoList
, false );
2698 GetViewData().GetViewShell()->UpdateInputHandler();
2703 void ScViewFunc::InsertAreaLink( const OUString
& rFile
,
2704 const OUString
& rFilter
, const OUString
& rOptions
,
2705 const OUString
& rSource
)
2707 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
2708 SCCOL nPosX
= GetViewData().GetCurX();
2709 SCROW nPosY
= GetViewData().GetCurY();
2710 SCTAB nTab
= GetViewData().GetTabNo();
2711 ScAddress
aPos( nPosX
, nPosY
, nTab
);
2713 pDocSh
->GetDocFunc().InsertAreaLink( rFile
, rFilter
, rOptions
, rSource
, ScRange(aPos
), 0/*nRefresh*/, false, false );
2716 void ScViewFunc::InsertTableLink( const OUString
& rFile
,
2717 const OUString
& rFilter
, const OUString
& rOptions
,
2718 std::u16string_view rTabName
)
2720 OUString aFilterName
= rFilter
;
2721 OUString aOpt
= rOptions
;
2722 ScDocumentLoader
aLoader( rFile
, aFilterName
, aOpt
);
2723 if (aLoader
.IsError())
2726 ScDocShell
* pSrcSh
= aLoader
.GetDocShell();
2727 ScDocument
& rSrcDoc
= pSrcSh
->GetDocument();
2728 SCTAB nTab
= MAXTAB
+1;
2729 if (rTabName
.empty()) // no name given -> first table
2734 SCTAB nCount
= rSrcDoc
.GetTableCount();
2735 for (SCTAB i
=0; i
<nCount
; i
++)
2737 rSrcDoc
.GetName( i
, aTemp
);
2738 if ( aTemp
== rTabName
)
2743 if ( nTab
<= MAXTAB
)
2744 ImportTables( pSrcSh
, 1, &nTab
, true,
2745 GetViewData().GetTabNo() );
2748 // Copy/link tables from another document
2750 void ScViewFunc::ImportTables( ScDocShell
* pSrcShell
,
2751 SCTAB nCount
, const SCTAB
* pSrcTabs
, bool bLink
,SCTAB nTab
)
2753 ScDocument
& rSrcDoc
= pSrcShell
->GetDocument();
2755 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
2756 ScDocument
& rDoc
= pDocSh
->GetDocument();
2757 bool bUndo(rDoc
.IsUndoEnabled());
2759 bool bError
= false;
2761 if (rSrcDoc
.GetDrawLayer())
2762 pDocSh
->MakeDrawLayer();
2765 rDoc
.BeginDrawUndo(); // drawing layer must do its own undo actions
2767 SCTAB nInsCount
= 0;
2769 for( i
=0; i
<nCount
; i
++ )
2770 { // insert sheets first and update all references
2772 rSrcDoc
.GetName( pSrcTabs
[i
], aName
);
2773 rDoc
.CreateValidTabName( aName
);
2774 if ( !rDoc
.InsertTab( nTab
+i
, aName
) )
2776 bError
= true; // total error
2781 for (i
=0; i
<nCount
&& !bError
; i
++)
2783 SCTAB nSrcTab
= pSrcTabs
[i
];
2784 SCTAB nDestTab1
=nTab
+i
;
2785 bool bValid
= pDocSh
->TransferTab( *pSrcShell
, nSrcTab
, nDestTab1
,
2786 false, false ); // no insert
2797 sfx2::LinkManager
* pLinkManager
= rDoc
.GetLinkManager();
2799 SfxMedium
* pMed
= pSrcShell
->GetMedium();
2800 OUString aFileName
= pMed
->GetName();
2801 OUString aFilterName
;
2802 if (pMed
->GetFilter())
2803 aFilterName
= pMed
->GetFilter()->GetFilterName();
2804 OUString aOptions
= ScDocumentLoader::GetOptions(*pMed
);
2806 bool bWasThere
= rDoc
.HasLink( aFileName
, aFilterName
, aOptions
);
2808 sal_uLong nRefresh
= 0;
2810 for (i
=0; i
<nInsCount
; i
++)
2812 rSrcDoc
.GetName( pSrcTabs
[i
], aTabStr
);
2813 rDoc
.SetLink( nTab
+i
, ScLinkMode::NORMAL
,
2814 aFileName
, aFilterName
, aOptions
, aTabStr
, nRefresh
);
2817 if (!bWasThere
) // Insert link only once per source document
2819 ScTableLink
* pLink
= new ScTableLink( pDocSh
, aFileName
, aFilterName
, aOptions
, nRefresh
);
2820 pLink
->SetInCreate( true );
2821 pLinkManager
->InsertFileLink( *pLink
, sfx2::SvBaseLinkObjectType::ClientFile
, aFileName
, &aFilterName
);
2823 pLink
->SetInCreate( false );
2825 SfxBindings
& rBindings
= GetViewData().GetBindings();
2826 rBindings
.Invalidate( SID_LINKS
);
2832 pDocSh
->GetUndoManager()->AddUndoAction(
2833 std::make_unique
<ScUndoImportTab
>( pDocSh
, nTab
, nCount
) );
2836 for (i
=0; i
<nInsCount
; i
++)
2837 GetViewData().InsertTab(nTab
);
2838 SetTabNo(nTab
,true);
2839 pDocSh
->PostPaint( 0,0,0, rDoc
.MaxCol(), rDoc
.MaxRow(), MAXTAB
,
2840 PaintPartFlags::Grid
| PaintPartFlags::Top
| PaintPartFlags::Left
| PaintPartFlags::Extras
);
2842 SfxApplication
* pSfxApp
= SfxGetpApp();
2843 pSfxApp
->Broadcast( SfxHint( SfxHintId::ScTablesChanged
) );
2844 pSfxApp
->Broadcast( SfxHint( SfxHintId::ScAreasChanged
) );
2846 pDocSh
->PostPaintExtras();
2847 pDocSh
->PostPaintGridAll();
2848 pDocSh
->SetDocumentModified();
2851 // Move/Copy table to another document
2853 void ScViewFunc::MoveTable(sal_uInt16 nDestDocNo
, SCTAB nDestTab
, bool bCopy
,
2854 const OUString
* pNewTabName
, bool bContextMenu
,
2855 SCTAB nContextMenuSourceTab
)
2857 ScDocument
& rDoc
= GetViewData().GetDocument();
2858 ScDocShell
* pDocShell
= GetViewData().GetDocShell();
2859 ScDocShell
* pDestShell
= nullptr;
2860 ScTabViewShell
* pDestViewSh
= nullptr;
2861 bool bUndo (rDoc
.IsUndoEnabled());
2862 bool bRename
= pNewTabName
&& !pNewTabName
->isEmpty();
2864 bool bNewDoc
= (nDestDocNo
== SC_DOC_NEW
);
2867 nDestTab
= 0; // firstly insert
2869 // execute without SfxCallMode::RECORD, because already contained in move command
2871 SfxStringItem
aItem( SID_FILE_NAME
, "private:factory/" + STRING_SCAPP
);
2872 SfxStringItem
aTarget( SID_TARGETNAME
, u
"_blank"_ustr
);
2874 const SfxPoolItemHolder
aResult(GetViewData().GetDispatcher().ExecuteList(
2875 SID_OPENDOC
, SfxCallMode::API
|SfxCallMode::SYNCHRON
,
2876 { &aItem
, &aTarget
}));
2880 if ( auto pObjectItem
= dynamic_cast<const SfxObjectItem
*>(aResult
.getItem()) )
2881 pDestShell
= dynamic_cast<ScDocShell
*>( pObjectItem
->GetShell() );
2882 else if ( auto pViewFrameItem
= dynamic_cast<const SfxViewFrameItem
*>(aResult
.getItem()))
2884 SfxViewFrame
* pFrm
= pViewFrameItem
->GetFrame();
2886 pDestShell
= dynamic_cast<ScDocShell
*>( pFrm
->GetObjectShell() );
2889 pDestViewSh
= pDestShell
->GetBestViewShell();
2893 pDestShell
= ScDocShell::GetShellByNum( nDestDocNo
);
2897 OSL_FAIL("Destination document not found !!!");
2901 ScMarkData
& rMark
= GetViewData().GetMarkData();
2902 if (bRename
&& rMark
.GetSelectCount() != 1)
2904 // Custom sheet name is provided, but more than one sheet is selected.
2905 // We don't support this scenario at the moment.
2909 ScDocument
& rDestDoc
= pDestShell
->GetDocument();
2911 if (&rDestDoc
!= &rDoc
)
2915 while (rDestDoc
.GetTableCount() > 1)
2916 rDestDoc
.DeleteTab(0);
2917 rDestDoc
.RenameTab( 0, u
"______42_____"_ustr
);
2920 SCTAB nTabCount
= rDoc
.GetTableCount();
2921 SCTAB nTabSelCount
= rMark
.GetSelectCount();
2923 vector
<SCTAB
> TheTabs
;
2925 for(SCTAB i
=0; i
<nTabCount
; ++i
)
2927 if(rMark
.GetTableSelect(i
))
2930 rDoc
.GetName( i
, aTabName
);
2931 TheTabs
.push_back(i
);
2932 for(SCTAB j
=i
+1;j
<nTabCount
;j
++)
2934 if((!rDoc
.IsVisible(j
)) && rDoc
.IsScenario(j
))
2936 rDoc
.GetName( j
, aTabName
);
2937 TheTabs
.push_back(j
);
2945 GetFrameWin()->EnterWait();
2947 if (rDoc
.GetDrawLayer())
2948 pDestShell
->MakeDrawLayer();
2950 if (!bNewDoc
&& bUndo
)
2951 rDestDoc
.BeginDrawUndo(); // drawing layer must do its own undo actions
2954 if(nDestTab
==SC_TAB_APPEND
)
2955 nDestTab
=rDestDoc
.GetTableCount();
2956 SCTAB nDestTab1
=nDestTab
;
2958 for( size_t j
=0; j
<TheTabs
.size(); ++j
, ++nDestTab1
)
2959 { // insert sheets first and update all references
2962 aName
= *pNewTabName
;
2964 rDoc
.GetName( TheTabs
[j
], aName
);
2966 rDestDoc
.CreateValidTabName( aName
);
2967 if ( !rDestDoc
.InsertTab( nDestTab1
, aName
) )
2969 bValid
= false; // total error
2972 ScRange
aRange( 0, 0, TheTabs
[j
], rDoc
.MaxCol(), rDoc
.MaxRow(), TheTabs
[j
] );
2973 aParam
.maRanges
.push_back(aRange
);
2975 rDoc
.SetClipParam(aParam
);
2978 nDestTab1
= nDestTab
;
2979 for(SCTAB nTab
: TheTabs
)
2981 bValid
= pDestShell
->TransferTab( *pDocShell
, nTab
, nDestTab1
, false, false );
2985 if (!bNewDoc
&& bUndo
)
2988 rDestDoc
.GetName(nDestTab
, sName
);
2989 pDestShell
->GetUndoManager()->AddUndoAction(
2990 std::make_unique
<ScUndoImportTab
>( pDestShell
, nDestTab
,
2991 static_cast<SCTAB
>(TheTabs
.size())));
2996 pDestShell
->GetUndoManager()->Clear();
2999 GetFrameWin()->LeaveWait();
3003 ErrorMessage(STR_TABINSERT_ERROR
);
3009 if(nTabCount
!=nTabSelCount
)
3010 DeleteTables(TheTabs
); // incl. Paint & Undo
3012 ErrorMessage(STR_TABREMOVE_ERROR
);
3017 // ChartListenerCollection must be updated before DeleteTab
3018 if ( rDestDoc
.IsChartListenerCollectionNeedsUpdate() )
3019 rDestDoc
.UpdateChartListenerCollection();
3021 SCTAB nNumTabsInserted
= static_cast<SCTAB
>(TheTabs
.size());
3022 pDestShell
->Broadcast( ScTablesHint( SC_TABS_INSERTED
, 0, nNumTabsInserted
) );
3024 rDestDoc
.DeleteTab( nNumTabsInserted
); // old first table
3025 pDestShell
->Broadcast( ScTablesHint( SC_TAB_DELETED
, nNumTabsInserted
) );
3029 // Make sure to clear the cached page view after sheet
3030 // deletion, which still points to the sdr page belonging to
3031 // the deleted sheet.
3032 SdrView
* pSdrView
= pDestViewSh
->GetScDrawView();
3034 pSdrView
->ClearPageView();
3036 pDestViewSh
->TabChanged(); // pages on the drawing layer
3038 pDestShell
->PostPaint( 0,0,0, rDoc
.MaxCol(), rDoc
.MaxRow(), MAXTAB
,
3039 PaintPartFlags::Grid
| PaintPartFlags::Top
| PaintPartFlags::Left
|
3040 PaintPartFlags::Extras
| PaintPartFlags::Size
);
3041 // PaintPartFlags::Size for outline
3045 pDestShell
->Broadcast( ScTablesHint( SC_TAB_INSERTED
, nDestTab
) );
3046 pDestShell
->PostPaintExtras();
3047 pDestShell
->PostPaintGridAll();
3052 pDestShell
->SetDocumentModified();
3053 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScTablesChanged
) );
3057 // Move or copy within the same document.
3058 SCTAB nTabCount
= rDoc
.GetTableCount();
3060 unique_ptr
< vector
<SCTAB
> > pSrcTabs(new vector
<SCTAB
>);
3061 unique_ptr
< vector
<SCTAB
> > pDestTabs(new vector
<SCTAB
>);
3062 unique_ptr
< vector
<OUString
> > pTabNames(new vector
<OUString
>);
3063 unique_ptr
< vector
<OUString
> > pDestNames
;
3064 pSrcTabs
->reserve(nTabCount
);
3065 pDestTabs
->reserve(nTabCount
);
3066 pTabNames
->reserve(nTabCount
);
3072 rDoc
.GetName(nContextMenuSourceTab
, aTabName
);
3073 pTabNames
->push_back(aTabName
);
3077 for(SCTAB i
=0;i
<nTabCount
;i
++)
3079 if(rMark
.GetTableSelect(i
))
3082 rDoc
.GetName( i
, aTabName
);
3083 pTabNames
->push_back(aTabName
);
3085 for(SCTAB j
=i
+1;j
<nTabCount
;j
++)
3087 if((!rDoc
.IsVisible(j
)) && rDoc
.IsScenario(j
))
3089 rDoc
.GetName( j
, aTabName
);
3090 pTabNames
->push_back(aTabName
);
3100 rDoc
.BeginDrawUndo(); // drawing layer must do its own undo actions
3102 rDoc
.GetName( nDestTab
, aDestName
);
3103 SCTAB nDestTab1
=nDestTab
;
3105 for (size_t j
= 0, n
= pTabNames
->size(); j
< n
; ++j
)
3107 nTabCount
= rDoc
.GetTableCount();
3108 const OUString
& rStr
= (*pTabNames
)[j
];
3109 if(!rDoc
.GetTable(rStr
,nMovTab
))
3113 if(!rDoc
.GetTable(aDestName
,nDestTab1
))
3115 nDestTab1
=nTabCount
;
3117 pDocShell
->MoveTable( nMovTab
, nDestTab1
, bCopy
, false ); // Undo is here
3119 // tdf#43175 - Adjust chart references on every copied sheet
3122 // New position of source table after moving
3123 SCTAB nSrcTab
= (nDestTab1
<= nMovTab
) ? nMovTab
+ 1 : nMovTab
;
3124 //#i29848# adjust references to data on the copied sheet
3125 ScChartHelper::AdjustRangesOfChartsOnDestinationPage(rDoc
, rDestDoc
, nSrcTab
,
3129 if(bCopy
&& rDoc
.IsScenario(nMovTab
))
3133 ScScenarioFlags nFlags
;
3135 rDoc
.GetScenarioData(nMovTab
, aComment
,aColor
, nFlags
);
3136 rDoc
.SetScenario(nDestTab1
,true);
3137 rDoc
.SetScenarioData(nDestTab1
,aComment
,aColor
,nFlags
);
3138 bool bActive
= rDoc
.IsActiveScenario(nMovTab
);
3139 rDoc
.SetActiveScenario( nDestTab1
, bActive
);
3140 bool bVisible
=rDoc
.IsVisible(nMovTab
);
3141 rDoc
.SetVisible(nDestTab1
,bVisible
);
3144 pSrcTabs
->push_back(nMovTab
);
3148 if(!rDoc
.GetTable(rStr
,nDestTab1
))
3150 nDestTab1
=nTabCount
;
3154 pDestTabs
->push_back(nDestTab1
);
3157 // Rename must be done after all sheets have been moved.
3160 pDestNames
.reset(new vector
<OUString
>);
3161 size_t n
= pDestTabs
->size();
3162 pDestNames
->reserve(n
);
3163 for (size_t j
= 0; j
< n
; ++j
)
3165 SCTAB nRenameTab
= (*pDestTabs
)[j
];
3166 OUString aTabName
= *pNewTabName
;
3167 rDoc
.CreateValidTabName( aTabName
);
3168 pDestNames
->push_back(aTabName
);
3169 rDoc
.RenameTab(nRenameTab
, aTabName
);
3173 // No need to keep this around when we are not renaming.
3176 SCTAB nTab
= GetViewData().GetTabNo();
3178 if (comphelper::LibreOfficeKit::isActive() && !pSrcTabs
->empty())
3180 ScModelObj
* pModel
= pDocShell
->GetModel();
3181 SfxLokHelper::notifyDocumentSizeChangedAllViews(pModel
);
3188 pDocShell
->GetUndoManager()->AddUndoAction(
3189 std::make_unique
<ScUndoCopyTab
>(
3190 pDocShell
, std::move(pSrcTabs
), std::move(pDestTabs
), std::move(pDestNames
)));
3194 pDocShell
->GetUndoManager()->AddUndoAction(
3195 std::make_unique
<ScUndoMoveTab
>(
3196 pDocShell
, std::move(pSrcTabs
), std::move(pDestTabs
), std::move(pTabNames
), std::move(pDestNames
)));
3202 for (SCTAB i
= 0; i
< nTabCount
; i
++)
3204 if (rMark
.GetTableSelect(i
))
3210 SCTAB nNewTab
= nDestTab
;
3211 if (nNewTab
== SC_TAB_APPEND
)
3212 nNewTab
= rDoc
.GetTableCount() - 1;
3213 else if (!bCopy
&& nTab
< nDestTab
)
3216 SetTabNo(nNewTab
, true);
3221 void ScViewFunc::ShowTable( const std::vector
<OUString
>& rNames
)
3223 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
3224 ScDocument
& rDoc
= pDocSh
->GetDocument();
3225 bool bUndo(rDoc
.IsUndoEnabled());
3227 std::vector
<SCTAB
> undoTabs
;
3232 for (const OUString
& aName
: rNames
)
3234 if (rDoc
.GetTable(aName
, nPos
))
3236 rDoc
.SetVisible( nPos
, true );
3237 SetTabNo( nPos
, true );
3238 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScTablesChanged
) );
3242 undoTabs
.push_back(nPos
);
3249 pDocSh
->GetUndoManager()->AddUndoAction( std::make_unique
<ScUndoShowHideTab
>( pDocSh
, std::move(undoTabs
), true ) );
3251 pDocSh
->PostPaint(0,0,0,rDoc
.MaxCol(),rDoc
.MaxRow(),MAXTAB
, PaintPartFlags::Extras
);
3252 pDocSh
->SetDocumentModified();
3256 void ScViewFunc::HideTable( const ScMarkData
& rMark
, SCTAB nTabToSelect
)
3258 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
3259 ScDocument
& rDoc
= pDocSh
->GetDocument();
3260 bool bUndo(rDoc
.IsUndoEnabled());
3262 SCTAB nTabCount
= rDoc
.GetTableCount();
3264 SCTAB nTabSelCount
= rMark
.GetSelectCount();
3266 // check to make sure we won't hide all sheets. we need at least one visible at all times.
3267 for ( SCTAB i
=0; i
< nTabCount
&& nVisible
<= nTabSelCount
; i
++ )
3268 if (rDoc
.IsVisible(i
))
3271 if (nVisible
<= nTabSelCount
)
3274 std::vector
<SCTAB
> undoTabs
;
3276 // need to take a copy of selectedtabs since it is modified in the loop
3277 const ScMarkData::MarkedTabsType selectedTabs
= rMark
.GetSelectedTabs();
3278 for (const SCTAB
& nTab
: selectedTabs
)
3280 if (rDoc
.IsVisible( nTab
))
3282 rDoc
.SetVisible( nTab
, false );
3284 pDocSh
->Broadcast( ScTablesHint( SC_TAB_HIDDEN
, nTab
) );
3285 SetTabNo( nTab
, true );
3288 undoTabs
.push_back(nTab
);
3292 if (nTabToSelect
!= -1)
3293 SetTabNo(nTabToSelect
);
3297 pDocSh
->GetUndoManager()->AddUndoAction( std::make_unique
<ScUndoShowHideTab
>( pDocSh
, std::move(undoTabs
), false ) );
3301 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScTablesChanged
) );
3302 pDocSh
->PostPaint(0,0,0,rDoc
.MaxCol(),rDoc
.MaxRow(),MAXTAB
, PaintPartFlags::Extras
);
3303 pDocSh
->SetDocumentModified();
3306 void ScViewFunc::InsertSpecialChar( const OUString
& rStr
, const vcl::Font
& rFont
)
3308 ScEditableTester
aTester( this );
3309 if (!aTester
.IsEditable())
3311 ErrorMessage(aTester
.GetMessageId());
3315 const sal_Unicode
* pChar
= rStr
.getStr();
3316 ScTabViewShell
* pViewShell
= GetViewData().GetViewShell();
3317 SvxFontItem
aFontItem( rFont
.GetFamilyType(),
3318 rFont
.GetFamilyName(),
3319 rFont
.GetStyleName(),
3324 // if string contains WEAK characters, set all fonts
3325 SvtScriptType nScript
;
3326 ScDocument
& rDoc
= GetViewData().GetDocument();
3327 if ( rDoc
.HasStringWeakCharacters( rStr
) )
3328 nScript
= SvtScriptType::LATIN
| SvtScriptType::ASIAN
| SvtScriptType::COMPLEX
;
3330 nScript
= rDoc
.GetStringScriptType( rStr
);
3332 SvxScriptSetItem
aSetItem( SID_ATTR_CHAR_FONT
, pViewShell
->GetPool() );
3333 aSetItem
.PutItemForScriptType( nScript
, aFontItem
);
3334 ApplyUserItemSet( aSetItem
.GetItemSet() );
3337 pViewShell
->TabKeyInput( KeyEvent( *(pChar
++), vcl::KeyCode() ) );
3340 void ScViewFunc::UpdateLineAttrs( SvxBorderLine
& rLine
,
3341 const SvxBorderLine
* pDestLine
,
3342 const SvxBorderLine
* pSrcLine
,
3345 if ( !(pSrcLine
&& pDestLine
) )
3350 rLine
.SetColor ( pSrcLine
->GetColor() );
3351 rLine
.SetBorderLineStyle(pDestLine
->GetBorderLineStyle());
3352 rLine
.SetWidth ( pDestLine
->GetWidth() );
3356 rLine
.SetColor ( pDestLine
->GetColor() );
3357 rLine
.SetBorderLineStyle(pSrcLine
->GetBorderLineStyle());
3358 rLine
.SetWidth ( pSrcLine
->GetWidth() );
3362 #define SET_LINE_ATTRIBUTES(LINE,BOXLINE) \
3363 pBoxLine = aBoxItem.Get##LINE(); \
3368 UpdateLineAttrs( aLine, pBoxLine, pLine, bColorOnly ); \
3369 aBoxItem.SetLine( &aLine, BOXLINE ); \
3372 aBoxItem.SetLine( nullptr, BOXLINE ); \
3375 void ScViewFunc::SetSelectionFrameLines( const SvxBorderLine
* pLine
,
3378 // Not editable only due to a matrix? Attribute is ok anyhow.
3379 bool bOnlyNotBecauseOfMatrix
;
3380 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix
) && !bOnlyNotBecauseOfMatrix
)
3382 ErrorMessage(STR_PROTECTIONERR
);
3386 ScDocument
& rDoc
= GetViewData().GetDocument();
3387 ScMarkData
aFuncMark( GetViewData().GetMarkData() ); // local copy for UnmarkFiltered
3388 ScViewUtil::UnmarkFiltered( aFuncMark
, rDoc
);
3389 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
3390 const ScPatternAttr
* pSelAttrs
= GetSelectionPattern();
3391 const SfxItemSet
& rSelItemSet
= pSelAttrs
->GetItemSet();
3393 const SfxPoolItem
* pBorderAttr
= nullptr;
3394 SfxItemState eItemState
= rSelItemSet
.GetItemState( ATTR_BORDER
, true, &pBorderAttr
);
3396 const SfxPoolItem
* pTLBRItem
= nullptr;
3397 SfxItemState eTLBRState
= rSelItemSet
.GetItemState( ATTR_BORDER_TLBR
, true, &pTLBRItem
);
3399 const SfxPoolItem
* pBLTRItem
= nullptr;
3400 SfxItemState eBLTRState
= rSelItemSet
.GetItemState( ATTR_BORDER_BLTR
, true, &pBLTRItem
);
3402 // any of the lines visible?
3403 if( !((eItemState
!= SfxItemState::DEFAULT
) || (eTLBRState
!= SfxItemState::DEFAULT
) || (eBLTRState
!= SfxItemState::DEFAULT
)) )
3406 // none of the lines don't care?
3407 if( (eItemState
!= SfxItemState::INVALID
) && (eTLBRState
!= SfxItemState::INVALID
) && (eBLTRState
!= SfxItemState::INVALID
) )
3409 SfxItemSetFixed
<ATTR_PATTERN_START
, ATTR_PATTERN_END
> aOldSet( *rDoc
.GetPool() );
3410 SfxItemSetFixed
<ATTR_PATTERN_START
, ATTR_PATTERN_END
> aNewSet( *rDoc
.GetPool() );
3412 SvxBorderLine aLine
;
3416 const SvxBorderLine
* pBoxLine
= nullptr;
3417 SvxBoxItem
aBoxItem( *static_cast<const SvxBoxItem
*>(pBorderAttr
) );
3418 SvxBoxInfoItem
aBoxInfoItem( ATTR_BORDER_INNER
);
3420 // here pBoxLine is used
3421 SET_LINE_ATTRIBUTES(Top
,SvxBoxItemLine::TOP
)
3422 SET_LINE_ATTRIBUTES(Bottom
,SvxBoxItemLine::BOTTOM
)
3423 SET_LINE_ATTRIBUTES(Left
,SvxBoxItemLine::LEFT
)
3424 SET_LINE_ATTRIBUTES(Right
,SvxBoxItemLine::RIGHT
)
3426 aBoxInfoItem
.SetLine( aBoxItem
.GetTop(), SvxBoxInfoItemLine::HORI
);
3427 aBoxInfoItem
.SetLine( aBoxItem
.GetLeft(), SvxBoxInfoItemLine::VERT
);
3428 aBoxInfoItem
.ResetFlags(); // set Lines to Valid
3430 aOldSet
.Put( *pBorderAttr
);
3431 aNewSet
.Put( aBoxItem
);
3432 aNewSet
.Put( aBoxInfoItem
);
3435 if( pTLBRItem
&& static_cast<const SvxLineItem
*>(pTLBRItem
)->GetLine() )
3437 SvxLineItem
aTLBRItem( *static_cast<const SvxLineItem
*>(pTLBRItem
) );
3438 UpdateLineAttrs( aLine
, aTLBRItem
.GetLine(), pLine
, bColorOnly
);
3439 aTLBRItem
.SetLine( &aLine
);
3440 aOldSet
.Put( *pTLBRItem
);
3441 aNewSet
.Put( aTLBRItem
);
3444 if( pBLTRItem
&& static_cast<const SvxLineItem
*>(pBLTRItem
)->GetLine() )
3446 SvxLineItem
aBLTRItem( *static_cast<const SvxLineItem
*>(pBLTRItem
) );
3447 UpdateLineAttrs( aLine
, aBLTRItem
.GetLine(), pLine
, bColorOnly
);
3448 aBLTRItem
.SetLine( &aLine
);
3449 aOldSet
.Put( *pBLTRItem
);
3450 aNewSet
.Put( aBLTRItem
);
3453 ApplyAttributes( aNewSet
, aOldSet
);
3455 else // if ( eItemState == SfxItemState::INVALID )
3457 aFuncMark
.MarkToMulti();
3458 rDoc
.ApplySelectionLineStyle( aFuncMark
, pLine
, bColorOnly
);
3461 const ScRange
& aMarkRange
= aFuncMark
.GetMultiMarkArea();
3462 SCCOL nStartCol
= aMarkRange
.aStart
.Col();
3463 SCROW nStartRow
= aMarkRange
.aStart
.Row();
3464 SCTAB nStartTab
= aMarkRange
.aStart
.Tab();
3465 SCCOL nEndCol
= aMarkRange
.aEnd
.Col();
3466 SCROW nEndRow
= aMarkRange
.aEnd
.Row();
3467 SCTAB nEndTab
= aMarkRange
.aEnd
.Tab();
3468 pDocSh
->PostPaint( nStartCol
, nStartRow
, nStartTab
,
3469 nEndCol
, nEndRow
, nEndTab
,
3470 PaintPartFlags::Grid
, SC_PF_LINES
| SC_PF_TESTMERGE
);
3472 pDocSh
->UpdateOle(GetViewData());
3473 pDocSh
->SetDocumentModified();
3476 #undef SET_LINE_ATTRIBUTES
3478 void ScViewFunc::SetValidation( const ScValidationData
& rNew
)
3480 ScDocument
& rDoc
= GetViewData().GetDocument();
3481 sal_uInt32 nIndex
= rDoc
.AddValidationEntry(rNew
); // for it there is no Undo
3482 SfxUInt32Item
aItem( ATTR_VALIDDATA
, nIndex
);
3484 ApplyAttr( aItem
); // with Paint and Undo...
3487 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */