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 Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
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 <config_features.h>
22 #include "scitems.hxx"
23 #include <editeng/eeitem.hxx>
25 #include <sfx2/app.hxx>
26 #include <svx/algitem.hxx>
27 #include <editeng/boxitem.hxx>
28 #include <editeng/editobj.hxx>
29 #include <editeng/editview.hxx>
30 #include <editeng/langitem.hxx>
31 #include <editeng/scripttypeitem.hxx>
32 #include <editeng/justifyitem.hxx>
33 #include <sfx2/bindings.hxx>
34 #include <svl/zforlist.hxx>
35 #include <svl/zformat.hxx>
36 #include <vcl/msgbox.hxx>
37 #include <vcl/virdev.hxx>
38 #include <vcl/waitobj.hxx>
39 #include <vcl/wrkwin.hxx>
42 #include "viewfunc.hxx"
43 #include "tabvwsh.hxx"
46 #include "patattr.hxx"
47 #include "docpool.hxx"
48 #include "uiitems.hxx"
50 #include "undocell.hxx"
51 #include "undoblk.hxx"
52 #include "undotab.hxx"
53 #include "refundo.hxx"
55 #include "olinetab.hxx"
56 #include "rangeutl.hxx"
57 #include "rangenam.hxx"
58 #include "globstr.hrc"
60 #include "stlsheet.hxx"
61 #include "editutil.hxx"
62 #include "formulacell.hxx"
63 #include "scresid.hxx"
64 #include "inputhdl.hxx"
66 #include "inputopt.hxx"
67 #include "compiler.hxx"
68 #include "docfunc.hxx"
69 #include "appoptio.hxx"
70 #include "dociter.hxx"
71 #include "sizedev.hxx"
72 #include "editable.hxx"
73 #include "scui_def.hxx"
74 #include "funcdesc.hxx"
76 #include "cellsuno.hxx"
77 #include "tokenarray.hxx"
78 #include <rowheightcontext.hxx>
79 #include <docfuncutil.hxx>
83 static void lcl_PostRepaintCondFormat( const ScConditionalFormat
*pCondFmt
, ScDocShell
*pDocSh
)
87 const ScRangeList
& rRanges
= pCondFmt
->GetRange();
89 pDocSh
->PostPaint( rRanges
, PAINT_ALL
);
93 ScViewFunc::ScViewFunc( vcl::Window
* pParent
, ScDocShell
& rDocSh
, ScTabViewShell
* pViewShell
) :
94 ScTabView( pParent
, rDocSh
, pViewShell
),
99 ScViewFunc::~ScViewFunc()
103 void ScViewFunc::StartFormatArea()
106 if ( !SC_MOD()->GetInputOptions().GetExtendFormat() )
109 // start only with single cell (marked or cursor position)
111 bool bOk
= (GetViewData().GetSimpleArea( aMarkRange
) == SC_MARK_SIMPLE
);
112 if ( bOk
&& aMarkRange
.aStart
!= aMarkRange
.aEnd
)
118 aFormatSource
= aMarkRange
.aStart
;
119 aFormatArea
= ScRange( aFormatSource
);
122 bFormatValid
= false; // discard old range
125 bool ScViewFunc::TestFormatArea( SCCOL nCol
, SCROW nRow
, SCTAB nTab
, bool bAttrChanged
)
128 if ( !SC_MOD()->GetInputOptions().GetExtendFormat() )
131 // Test: treat input with numberformat (bAttrChanged) always as new Attribute
132 // (discard old Area ). If not wanted, discard if-statement
139 //! Test if cell empty ???
142 ScRange aNewRange
= aFormatArea
;
143 if ( bFormatValid
&& nTab
== aFormatSource
.Tab() )
145 if ( nRow
>= aFormatArea
.aStart
.Row() && nRow
<= aFormatArea
.aEnd
.Row() )
148 if ( nCol
>= aFormatArea
.aStart
.Col() && nCol
<= aFormatArea
.aEnd
.Col() )
150 bFound
= true; // do not change range
153 if ( nCol
+1 == aFormatArea
.aStart
.Col() )
156 aNewRange
.aStart
.SetCol( nCol
);
159 if ( nCol
== aFormatArea
.aEnd
.Col()+1 )
162 aNewRange
.aEnd
.SetCol( nCol
);
165 if ( nCol
>= aFormatArea
.aStart
.Col() && nCol
<= aFormatArea
.aEnd
.Col() )
168 if ( nRow
+1 == aFormatArea
.aStart
.Row() )
171 aNewRange
.aStart
.SetRow( nRow
);
174 if ( nRow
== aFormatArea
.aEnd
.Row()+1 )
177 aNewRange
.aEnd
.SetRow( nRow
);
183 aFormatArea
= aNewRange
; // extend
185 bFormatValid
= false; // outside of range -> break
190 void ScViewFunc::DoAutoAttributes( SCCOL nCol
, SCROW nRow
, SCTAB nTab
,
193 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
194 ScDocument
& rDoc
= pDocSh
->GetDocument();
196 const ScPatternAttr
* pSource
= rDoc
.GetPattern(
197 aFormatSource
.Col(), aFormatSource
.Row(), nTab
);
198 if ( !static_cast<const ScMergeAttr
&>(pSource
->GetItem(ATTR_MERGE
)).IsMerged() )
200 ScRange
aRange( nCol
, nRow
, nTab
, nCol
, nRow
, nTab
);
202 aMark
.SetMarkArea( aRange
);
204 ScDocFunc
&rFunc
= GetViewData().GetDocFunc();
206 // pOldPattern is only valid until call to ApplyAttributes!
207 const ScPatternAttr
* pOldPattern
= rDoc
.GetPattern( nCol
, nRow
, nTab
);
208 const ScStyleSheet
* pSrcStyle
= pSource
->GetStyleSheet();
209 if ( pSrcStyle
&& pSrcStyle
!= pOldPattern
->GetStyleSheet() )
210 rFunc
.ApplyStyle( aMark
, pSrcStyle
->GetName(), false );
212 rFunc
.ApplyAttributes( aMark
, *pSource
, false );
215 if ( bAttrChanged
) // value entered with number format?
216 aFormatSource
.Set( nCol
, nRow
, nTab
); // then set a new source
219 // additional routines
221 sal_uInt16
ScViewFunc::GetOptimalColWidth( SCCOL nCol
, SCTAB nTab
, bool bFormula
)
223 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
224 ScDocument
& rDoc
= pDocSh
->GetDocument();
225 ScMarkData
& rMark
= GetViewData().GetMarkData();
227 double nPPTX
= GetViewData().GetPPTX();
228 double nPPTY
= GetViewData().GetPPTY();
229 Fraction aZoomX
= GetViewData().GetZoomX();
230 Fraction aZoomY
= GetViewData().GetZoomY();
232 ScSizeDeviceProvider
aProv(pDocSh
);
233 if (aProv
.IsPrinter())
235 nPPTX
= aProv
.GetPPTX();
236 nPPTY
= aProv
.GetPPTY();
237 aZoomX
= aZoomY
= Fraction( 1, 1 );
240 sal_uInt16 nTwips
= rDoc
.GetOptimalColWidth( nCol
, nTab
, aProv
.GetDevice(),
241 nPPTX
, nPPTY
, aZoomX
, aZoomY
, bFormula
, &rMark
);
245 bool ScViewFunc::SelectionEditable( bool* pOnlyNotBecauseOfMatrix
/* = NULL */ )
248 ScDocument
* pDoc
= GetViewData().GetDocument();
249 ScMarkData
& rMark
= GetViewData().GetMarkData();
250 if (rMark
.IsMarked() || rMark
.IsMultiMarked())
251 bRet
= pDoc
->IsSelectionEditable( rMark
, pOnlyNotBecauseOfMatrix
);
254 SCCOL nCol
= GetViewData().GetCurX();
255 SCROW nRow
= GetViewData().GetCurY();
256 SCTAB nTab
= GetViewData().GetTabNo();
257 bRet
= pDoc
->IsBlockEditable( nTab
, nCol
, nRow
, nCol
, nRow
,
258 pOnlyNotBecauseOfMatrix
);
267 static bool lcl_FunctionKnown( sal_uInt16 nOpCode
)
269 const ScFunctionList
* pFuncList
= ScGlobal::GetStarCalcFunctionList();
272 sal_uLong nCount
= pFuncList
->GetCount();
273 for (sal_uLong i
=0; i
<nCount
; i
++)
274 if ( pFuncList
->GetFunction(i
)->nFIndex
== nOpCode
)
280 static bool lcl_AddFunction( ScAppOptions
& rAppOpt
, sal_uInt16 nOpCode
)
282 sal_uInt16 nOldCount
= rAppOpt
.GetLRUFuncListCount();
283 sal_uInt16
* pOldList
= rAppOpt
.GetLRUFuncList();
285 for (nPos
=0; nPos
<nOldCount
; nPos
++)
286 if (pOldList
[nPos
] == nOpCode
) // is the function already in the list?
289 return false; // already at the top -> no change
291 // count doesn't change, so the original array is modified
293 for (sal_uInt16 nCopy
=nPos
; nCopy
>0; nCopy
--)
294 pOldList
[nCopy
] = pOldList
[nCopy
-1];
295 pOldList
[0] = nOpCode
;
297 return true; // list has changed
300 if ( !lcl_FunctionKnown( nOpCode
) )
301 return false; // not in function list -> no change
303 sal_uInt16 nNewCount
= std::min( (sal_uInt16
)(nOldCount
+ 1), (sal_uInt16
)LRU_MAX
);
304 sal_uInt16 nNewList
[LRU_MAX
];
305 nNewList
[0] = nOpCode
;
306 for (nPos
=1; nPos
<nNewCount
; nPos
++)
307 nNewList
[nPos
] = pOldList
[nPos
-1];
308 rAppOpt
.SetLRUFuncList( nNewList
, nNewCount
);
310 return true; // list has changed
313 namespace HelperNotifyChanges
315 void NotifyIfChangesListeners(ScDocShell
&rDocShell
, ScMarkData
& rMark
, SCCOL nCol
, SCROW nRow
)
317 if (ScModelObj
*pModelObj
= getMustPropagateChangesModel(rDocShell
))
319 ScRangeList aChangeRanges
;
320 ScMarkData::iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
321 for (; itr
!= itrEnd
; ++itr
)
322 aChangeRanges
.Append( ScRange( nCol
, nRow
, *itr
) );
324 HelperNotifyChanges::Notify(*pModelObj
, aChangeRanges
, "cell-change");
332 void ScViewFunc::EnterData( SCCOL nCol
, SCROW nRow
, SCTAB nTab
,
333 const OUString
& rString
,
334 const EditTextObject
* pData
)
336 ScDocument
* pDoc
= GetViewData().GetDocument();
337 ScMarkData
rMark(GetViewData().GetMarkData());
338 bool bRecord
= pDoc
->IsUndoEnabled();
341 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
342 ScDocFunc
&rFunc
= GetViewData().GetDocFunc();
343 ScDocShellModificator
aModificator( *pDocSh
);
345 ScEditableTester
aTester( pDoc
, nCol
,nRow
, nCol
,nRow
, rMark
);
346 if (!aTester
.IsEditable())
348 ErrorMessage(aTester
.GetMessageId());
349 PaintArea(nCol
, nRow
, nCol
, nRow
); // possibly the edit-engine is still painted there
354 rFunc
.EnterListAction( STR_UNDO_ENTERDATA
);
356 bool bFormula
= false;
358 // a single '=' character is handled as string (needed for special filters)
359 if ( rString
.getLength() > 1 )
361 if ( rString
[0] == '=' )
366 else if ( rString
[0] == '+' || rString
[0] == '-' )
368 // if there is more than one leading '+' or '-' character, remove the additional ones
369 sal_Int32 nIndex
= 1;
370 sal_Int32 nLen
= rString
.getLength();
371 while ( nIndex
< nLen
&& ( rString
[ nIndex
] == '+' || rString
[ nIndex
] == '-' ) )
375 OUString aString
= rString
.replaceAt( 1, nIndex
- 1, "" );
377 // if the remaining part without the leading '+' or '-' character
378 // is non-empty and not a number, handle as formula
379 if ( aString
.getLength() > 1 )
381 sal_uInt32 nFormat
= 0;
382 pDoc
->GetNumberFormat( nCol
, nRow
, nTab
, nFormat
);
383 SvNumberFormatter
* pFormatter
= pDoc
->GetFormatTable();
385 if ( !pFormatter
->IsNumberFormat( aString
, nFormat
, fNumber
) )
393 bool bNumFmtChanged
= false;
395 { // formula, compile with autoCorrection
396 i
= rMark
.GetFirstSelected();
397 ScAddress
aPos( nCol
, nRow
, i
);
398 ScCompiler
aComp( pDoc
, aPos
);
399 aComp
.SetGrammar(pDoc
->GetGrammar());
400 //2do: enable/disable autoCorrection via calcoptions
401 aComp
.SetAutoCorrection( true );
402 if ( rString
[0] == '+' || rString
[0] == '-' )
404 aComp
.SetExtendedErrorDetection( ScCompiler::EXTENDED_ERROR_DETECTION_NAME_BREAK
);
406 OUString
aFormula( rString
);
412 bool bAddEqual
= false;
413 ScTokenArray
* pArrFirst
= pArr
= aComp
.CompileString( aFormula
);
414 bool bCorrected
= aComp
.IsCorrected();
416 { // try to parse with first parser-correction
417 pArr
= aComp
.CompileString( aComp
.GetCorrectedFormula() );
419 if ( !pArr
->GetCodeError() )
422 aComp
.CompileTokenArray();
423 bCorrected
|= aComp
.IsCorrected();
427 OUString aCorrectedFormula
;
430 aCorrectedFormula
= "=" + aComp
.GetCorrectedFormula();
433 aCorrectedFormula
= aComp
.GetCorrectedFormula();
435 if ( aCorrectedFormula
.getLength() == 1 )
436 nResult
= RET_NO
; // empty formula, just '='
439 OUString
aMessage( ScResId( SCSTR_FORMULA_AUTOCORRECTION
) );
440 aMessage
+= aCorrectedFormula
;
441 nResult
= ScopedVclPtrInstance
<QueryBox
>( GetViewData().GetDialogParent(),
442 WinBits(WB_YES_NO
| WB_DEF_YES
),
443 aMessage
)->Execute();
445 if ( nResult
== RET_YES
)
447 aFormula
= aCorrectedFormula
;
448 if ( pArr
!= pArrFirst
)
454 if ( pArr
!= pArrFirst
)
462 // to be used in multiple tabs, the formula must be compiled anew
463 // via ScFormulaCell copy-ctor because of RangeNames,
464 // the same code-array for all cells is not possible.
465 // If the array has an error, (it) must be RPN-erased in the newly generated
466 // cells and the error be set explicitly, so that
467 // via FormulaCell copy-ctor and Interpreter it will be, when possible,
468 // ironed out again, too intelligent.. e.g.: =1))
469 sal_uInt16 nError
= pArr
->GetCodeError();
472 // update list of recent functions with all functions that
473 // are not within parentheses
475 ScModule
* pScMod
= SC_MOD();
476 ScAppOptions aAppOpt
= pScMod
->GetAppOptions();
477 bool bOptChanged
= false;
479 formula::FormulaToken
** ppToken
= pArr
->GetArray();
480 sal_uInt16 nTokens
= pArr
->GetLen();
481 sal_uInt16 nLevel
= 0;
482 for (sal_uInt16 nTP
=0; nTP
<nTokens
; nTP
++)
484 formula::FormulaToken
* pTok
= ppToken
[nTP
];
485 OpCode eOp
= pTok
->GetOpCode();
488 else if ( eOp
== ocClose
&& nLevel
)
490 if ( nLevel
== 0 && pTok
->IsFunction() &&
491 lcl_AddFunction( aAppOpt
, sal::static_int_cast
<sal_uInt16
>( eOp
) ) )
497 pScMod
->SetAppOptions(aAppOpt
);
501 ScFormulaCell
aCell(pDoc
, aPos
, *pArr
, formula::FormulaGrammar::GRAM_DEFAULT
, MM_NONE
);
504 SvNumberFormatter
* pFormatter
= pDoc
->GetFormatTable();
505 ScMarkData::iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
506 for (; itr
!= itrEnd
; ++itr
)
510 sal_uLong nIndex
= (sal_uLong
) static_cast<const SfxUInt32Item
*>( pDoc
->GetAttr(
511 nCol
, nRow
, i
, ATTR_VALUE_FORMAT
))->GetValue();
512 if ( pFormatter
->GetType( nIndex
) == css::util::NumberFormat::TEXT
||
513 ( ( rString
[0] == '+' || rString
[0] == '-' ) && nError
&& rString
== aFormula
) )
517 // A clone of pData will be stored in the cell.
518 rFunc
.SetEditCell(aPos
, *pData
, true);
521 rFunc
.SetStringCell(aPos
, aFormula
, true);
525 ScFormulaCell
* pCell
= new ScFormulaCell( aCell
, *pDoc
, aPos
);
528 pCell
->GetCode()->DelRPN();
529 pCell
->SetErrCode( nError
);
530 if(pCell
->GetCode()->IsHyperLink())
531 pCell
->GetCode()->SetHyperLink(false);
533 rFunc
.SetFormulaCell(aPos
, pCell
, true);
539 ScMarkData::iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
540 for ( ; itr
!= itrEnd
; ++itr
)
542 bool bNumFmtSet
= false;
543 rFunc
.SetNormalString( bNumFmtSet
, ScAddress( nCol
, nRow
, *itr
), rString
, false );
546 /* FIXME: if set on any sheet results in changed only on
547 * sheet nTab for TestFormatArea() and DoAutoAttributes() */
548 bNumFmtChanged
= true;
553 bool bAutoFormat
= TestFormatArea(nCol
, nRow
, nTab
, bNumFmtChanged
);
556 DoAutoAttributes(nCol
, nRow
, nTab
, bNumFmtChanged
);
558 pDocSh
->UpdateOle(&GetViewData());
560 HelperNotifyChanges::NotifyIfChangesListeners(*pDocSh
, rMark
, nCol
, nRow
);
563 rFunc
.EndListAction();
565 aModificator
.SetDocumentModified();
566 lcl_PostRepaintCondFormat( pDoc
->GetCondFormat( nCol
, nRow
, nTab
), pDocSh
);
569 // enter value in single cell (on nTab only)
571 void ScViewFunc::EnterValue( SCCOL nCol
, SCROW nRow
, SCTAB nTab
, const double& rValue
)
573 ScDocument
* pDoc
= GetViewData().GetDocument();
574 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
576 if ( pDoc
&& pDocSh
)
578 bool bUndo(pDoc
->IsUndoEnabled());
579 ScDocShellModificator
aModificator( *pDocSh
);
581 ScEditableTester
aTester( pDoc
, nTab
, nCol
,nRow
, nCol
,nRow
);
582 if (aTester
.IsEditable())
584 ScAddress
aPos( nCol
, nRow
, nTab
);
585 ScCellValue aUndoCell
;
587 aUndoCell
.assign(*pDoc
, aPos
);
589 pDoc
->SetValue( nCol
, nRow
, nTab
, rValue
);
591 // because of ChangeTrack after change in document
594 pDocSh
->GetUndoManager()->AddUndoAction(
595 new ScUndoEnterValue(pDocSh
, aPos
, aUndoCell
, rValue
));
598 pDocSh
->PostPaintCell( aPos
);
599 pDocSh
->UpdateOle(&GetViewData());
600 aModificator
.SetDocumentModified();
603 ErrorMessage(aTester
.GetMessageId());
607 void ScViewFunc::EnterData( SCCOL nCol
, SCROW nRow
, SCTAB nTab
,
608 const EditTextObject
& rData
, bool bTestSimple
)
610 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
611 ScMarkData
& rMark
= GetViewData().GetMarkData();
612 ScDocument
& rDoc
= pDocSh
->GetDocument();
613 bool bRecord
= rDoc
.IsUndoEnabled();
615 ScDocShellModificator
aModificator( *pDocSh
);
617 ScEditableTester
aTester( &rDoc
, nTab
, nCol
,nRow
, nCol
,nRow
);
618 if (aTester
.IsEditable())
621 // test for attribute
623 bool bSimple
= false;
624 bool bCommon
= false;
625 std::unique_ptr
<ScPatternAttr
> pCellAttrs
;
628 const ScPatternAttr
* pOldPattern
= rDoc
.GetPattern( nCol
, nRow
, nTab
);
629 ScTabEditEngine
aEngine( *pOldPattern
, rDoc
.GetEnginePool() );
630 aEngine
.SetText(rData
);
632 if (bTestSimple
) // test, if simple string without attribute
634 ScEditAttrTester
aAttrTester( &aEngine
);
635 bSimple
= !aAttrTester
.NeedsObject();
636 bCommon
= aAttrTester
.NeedsCellAttr();
638 // formulas have to be recognized even if they're formatted
639 // (but common attributes are still collected)
641 if ( !bSimple
&& aEngine
.GetParagraphCount() == 1 )
643 OUString
aParStr(aEngine
.GetText( 0 ));
644 if ( aParStr
[0] == '=' )
648 if (bCommon
) // attribute for tab
650 pCellAttrs
.reset(new ScPatternAttr( *pOldPattern
));
651 pCellAttrs
->GetFromEditItemSet( &aAttrTester
.GetAttribs() );
652 //! remove common attributes from EditEngine?
656 // #i97726# always get text for "repeat" of undo action
657 aString
= ScEditUtil::GetSpaceDelimitedString(aEngine
);
661 EditTextObject
* pUndoData
= nullptr;
662 ScUndoEnterData::ValuesType aOldValues
;
664 if (bRecord
&& !bSimple
)
666 ScMarkData::iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
667 for (; itr
!= itrEnd
; ++itr
)
669 ScUndoEnterData::Value aOldValue
;
670 aOldValue
.mnTab
= *itr
;
671 aOldValue
.maCell
.assign(rDoc
, ScAddress(nCol
, nRow
, *itr
));
672 aOldValues
.push_back(aOldValue
);
675 pUndoData
= rData
.Clone();
681 rDoc
.ApplyPattern(nCol
,nRow
,nTab
,*pCellAttrs
); //! undo
686 AdjustRowHeight(nRow
,nRow
);
688 EnterData(nCol
,nRow
,nTab
,aString
);
692 ScMarkData::iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
693 for (; itr
!= itrEnd
; ++itr
)
695 ScAddress
aPos(nCol
, nRow
, *itr
);
696 rDoc
.SetEditText(aPos
, rData
, rDoc
.GetEditPool());
700 { // because of ChangeTrack current first
701 pDocSh
->GetUndoManager()->AddUndoAction(
702 new ScUndoEnterData(pDocSh
, ScAddress(nCol
,nRow
,nTab
), aOldValues
, aString
, pUndoData
));
707 AdjustRowHeight(nRow
,nRow
);
710 for (; itr
!= itrEnd
; ++itr
)
711 pDocSh
->PostPaintCell( nCol
, nRow
, *itr
);
715 pDocSh
->UpdateOle(&GetViewData());
717 HelperNotifyChanges::NotifyIfChangesListeners(*pDocSh
, rMark
, nCol
, nRow
);
719 aModificator
.SetDocumentModified();
721 lcl_PostRepaintCondFormat( rDoc
.GetCondFormat( nCol
, nRow
, nTab
), pDocSh
);
725 ErrorMessage(aTester
.GetMessageId());
726 PaintArea( nCol
, nRow
, nCol
, nRow
); // possibly the edit-engine is still painted there
730 void ScViewFunc::EnterDataAtCursor( const OUString
& rString
)
732 SCCOL nPosX
= GetViewData().GetCurX();
733 SCROW nPosY
= GetViewData().GetCurY();
734 SCTAB nTab
= GetViewData().GetTabNo();
736 EnterData( nPosX
, nPosY
, nTab
, rString
);
739 void ScViewFunc::EnterMatrix( const OUString
& rString
, ::formula::FormulaGrammar::Grammar eGram
)
741 ScViewData
& rData
= GetViewData();
742 const SCCOL nCol
= rData
.GetCurX();
743 const SCROW nRow
= rData
.GetCurY();
744 const ScMarkData
& rMark
= rData
.GetMarkData();
745 if ( !rMark
.IsMarked() && !rMark
.IsMultiMarked() )
747 // nothing marked -> temporarily calculate block
748 // with size of result formula to get the size
750 ScDocument
* pDoc
= rData
.GetDocument();
751 SCTAB nTab
= rData
.GetTabNo();
752 ScFormulaCell
aFormCell( pDoc
, ScAddress(nCol
,nRow
,nTab
), rString
, eGram
, MM_FORMULA
);
756 aFormCell
.GetResultDimensions( nSizeX
, nSizeY
);
757 if ( nSizeX
!= 0 && nSizeY
!= 0 &&
758 nCol
+nSizeX
-1 <= sal::static_int_cast
<SCSIZE
>(MAXCOL
) &&
759 nRow
+nSizeY
-1 <= sal::static_int_cast
<SCSIZE
>(MAXROW
) )
761 ScRange
aResult( nCol
, nRow
, nTab
,
762 sal::static_int_cast
<SCCOL
>(nCol
+nSizeX
-1),
763 sal::static_int_cast
<SCROW
>(nRow
+nSizeY
-1), nTab
);
764 MarkRange( aResult
, false );
769 if (rData
.GetSimpleArea(aRange
) == SC_MARK_SIMPLE
)
771 ScDocShell
* pDocSh
= rData
.GetDocShell();
772 bool bSuccess
= pDocSh
->GetDocFunc().EnterMatrix(
773 aRange
, &rMark
, nullptr, rString
, false, false, EMPTY_OUSTRING
, eGram
);
775 pDocSh
->UpdateOle(&GetViewData());
777 PaintArea(nCol
, nRow
, nCol
, nRow
); // possibly the edit-engine is still painted there
780 ErrorMessage(STR_NOMULTISELECT
);
783 SvtScriptType
ScViewFunc::GetSelectionScriptType()
785 SvtScriptType nScript
= SvtScriptType::NONE
;
787 ScDocument
* pDoc
= GetViewData().GetDocument();
788 const ScMarkData
& rMark
= GetViewData().GetMarkData();
789 if ( !rMark
.IsMarked() && !rMark
.IsMultiMarked() )
791 // no selection -> cursor
793 nScript
= pDoc
->GetScriptType( GetViewData().GetCurX(),
794 GetViewData().GetCurY(), GetViewData().GetTabNo());
799 rMark
.FillRangeListWithMarks( &aRanges
, false );
800 nScript
= pDoc
->GetRangeScriptType(aRanges
);
803 if (nScript
== SvtScriptType::NONE
)
804 nScript
= ScGlobal::GetDefaultScriptType();
809 const ScPatternAttr
* ScViewFunc::GetSelectionPattern()
811 // Don't use UnmarkFiltered in slot state functions, for performance reasons.
812 // The displayed state is always that of the whole selection including filtered rows.
814 const ScMarkData
& rMark
= GetViewData().GetMarkData();
815 ScDocument
* pDoc
= GetViewData().GetDocument();
816 if ( rMark
.IsMarked() || rMark
.IsMultiMarked() )
818 // MarkToMulti is no longer necessary for pDoc->GetSelectionPattern
819 const ScPatternAttr
* pAttr
= pDoc
->GetSelectionPattern( rMark
);
824 SCCOL nCol
= GetViewData().GetCurX();
825 SCROW nRow
= GetViewData().GetCurY();
826 SCTAB nTab
= GetViewData().GetTabNo();
828 ScMarkData
aTempMark( rMark
); // copy sheet selection
829 aTempMark
.SetMarkArea( ScRange( nCol
, nRow
, nTab
) );
830 const ScPatternAttr
* pAttr
= pDoc
->GetSelectionPattern( aTempMark
);
835 void ScViewFunc::GetSelectionFrame( SvxBoxItem
& rLineOuter
,
836 SvxBoxInfoItem
& rLineInner
)
838 ScDocument
* pDoc
= GetViewData().GetDocument();
839 const ScMarkData
& rMark
= GetViewData().GetMarkData();
841 if ( rMark
.IsMarked() || rMark
.IsMultiMarked() )
842 pDoc
->GetSelectionFrame( rMark
, rLineOuter
, rLineInner
);
845 const ScPatternAttr
* pAttrs
=
846 pDoc
->GetPattern( GetViewData().GetCurX(),
847 GetViewData().GetCurY(),
848 GetViewData().GetTabNo() );
850 rLineOuter
= static_cast<const SvxBoxItem
&> (pAttrs
->GetItem( ATTR_BORDER
));
851 rLineInner
= static_cast<const SvxBoxInfoItem
&>(pAttrs
->GetItem( ATTR_BORDER_INNER
));
852 rLineInner
.SetTable(false);
853 rLineInner
.SetDist(true);
854 rLineInner
.SetMinDist(false);
858 // apply attribute - undo OK
860 // complete set ( ATTR_STARTINDEX, ATTR_ENDINDEX )
862 void ScViewFunc::ApplyAttributes( const SfxItemSet
* pDialogSet
,
863 const SfxItemSet
* pOldSet
)
865 // not editable because of matrix only? attribute OK nonetheless
866 bool bOnlyNotBecauseOfMatrix
;
867 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix
) && !bOnlyNotBecauseOfMatrix
)
869 ErrorMessage(STR_PROTECTIONERR
);
873 ScPatternAttr
aOldAttrs( new SfxItemSet(*pOldSet
) );
874 ScPatternAttr
aNewAttrs( new SfxItemSet(*pDialogSet
) );
875 aNewAttrs
.DeleteUnchanged( &aOldAttrs
);
877 if ( pDialogSet
->GetItemState( ATTR_VALUE_FORMAT
) == SfxItemState::SET
)
878 { // don't reset to default SYSTEM GENERAL if not intended
879 sal_uInt32 nOldFormat
=
880 static_cast<const SfxUInt32Item
&>(pOldSet
->Get( ATTR_VALUE_FORMAT
)).GetValue();
881 sal_uInt32 nNewFormat
=
882 static_cast<const SfxUInt32Item
&>(pDialogSet
->Get( ATTR_VALUE_FORMAT
)).GetValue();
883 if ( nNewFormat
!= nOldFormat
)
885 SvNumberFormatter
* pFormatter
=
886 GetViewData().GetDocument()->GetFormatTable();
887 const SvNumberformat
* pOldEntry
= pFormatter
->GetEntry( nOldFormat
);
888 LanguageType eOldLang
=
889 pOldEntry
? pOldEntry
->GetLanguage() : LANGUAGE_DONTKNOW
;
890 const SvNumberformat
* pNewEntry
= pFormatter
->GetEntry( nNewFormat
);
891 LanguageType eNewLang
=
892 pNewEntry
? pNewEntry
->GetLanguage() : LANGUAGE_DONTKNOW
;
893 if ( eNewLang
!= eOldLang
)
895 aNewAttrs
.GetItemSet().Put(
896 SvxLanguageItem( eNewLang
, ATTR_LANGUAGE_FORMAT
) );
898 // only the language has changed -> do not touch numberformat-attribute
899 sal_uInt32 nNewMod
= nNewFormat
% SV_COUNTRY_LANGUAGE_OFFSET
;
900 if ( nNewMod
== ( nOldFormat
% SV_COUNTRY_LANGUAGE_OFFSET
) &&
901 nNewMod
<= SV_MAX_ANZ_STANDARD_FORMATE
)
902 aNewAttrs
.GetItemSet().ClearItem( ATTR_VALUE_FORMAT
);
907 const SvxBoxItem
* pOldOuter
= static_cast<const SvxBoxItem
*> (&pOldSet
->Get( ATTR_BORDER
));
908 const SvxBoxItem
* pNewOuter
= static_cast<const SvxBoxItem
*> (&pDialogSet
->Get( ATTR_BORDER
));
909 const SvxBoxInfoItem
* pOldInner
= static_cast<const SvxBoxInfoItem
*> (&pOldSet
->Get( ATTR_BORDER_INNER
));
910 const SvxBoxInfoItem
* pNewInner
= static_cast<const SvxBoxInfoItem
*> (&pDialogSet
->Get( ATTR_BORDER_INNER
));
911 SfxItemSet
& rNewSet
= aNewAttrs
.GetItemSet();
912 SfxItemPool
* pNewPool
= rNewSet
.GetPool();
914 pNewPool
->Put( *pNewOuter
); // don't delete yet
915 pNewPool
->Put( *pNewInner
);
916 rNewSet
.ClearItem( ATTR_BORDER
);
917 rNewSet
.ClearItem( ATTR_BORDER_INNER
);
920 * establish whether border attribute is to be set:
922 * 2. is one of the borders not-DontCare (since 238.f: IsxxValid())
926 bool bFrame
= (pDialogSet
->GetItemState( ATTR_BORDER
) != SfxItemState::DEFAULT
)
927 || (pDialogSet
->GetItemState( ATTR_BORDER_INNER
) != SfxItemState::DEFAULT
);
929 if ( pNewOuter
==pOldOuter
&& pNewInner
==pOldInner
)
932 // this should be intercepted by the pool: ?!??!??
934 if ( bFrame
&& pNewOuter
&& pNewInner
)
935 if ( *pNewOuter
== *pOldOuter
&& *pNewInner
== *pOldInner
)
941 && ( pNewInner
->IsValid(SvxBoxInfoItemValidFlags::LEFT
)
942 || pNewInner
->IsValid(SvxBoxInfoItemValidFlags::RIGHT
)
943 || pNewInner
->IsValid(SvxBoxInfoItemValidFlags::TOP
)
944 || pNewInner
->IsValid(SvxBoxInfoItemValidFlags::BOTTOM
)
945 || pNewInner
->IsValid(SvxBoxInfoItemValidFlags::HORI
)
946 || pNewInner
->IsValid(SvxBoxInfoItemValidFlags::VERT
) );
952 ApplySelectionPattern( aNewAttrs
); // standard only
955 // if new items are default-items, overwrite the old items:
957 bool bDefNewOuter
= ( SFX_ITEMS_STATICDEFAULT
== pNewOuter
->GetKind() );
958 bool bDefNewInner
= ( SFX_ITEMS_STATICDEFAULT
== pNewInner
->GetKind() );
960 ApplyPatternLines( aNewAttrs
,
961 bDefNewOuter
? pOldOuter
: pNewOuter
,
962 bDefNewInner
? pOldInner
: pNewInner
);
965 pNewPool
->Remove( *pNewOuter
); // release
966 pNewPool
->Remove( *pNewInner
);
971 // CellContentChanged is called in ApplySelectionPattern / ApplyPatternLines
974 void ScViewFunc::ApplyAttr( const SfxPoolItem
& rAttrItem
)
976 // not editable because of matrix only? attribute OK nonetheless
977 bool bOnlyNotBecauseOfMatrix
;
978 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix
) && !bOnlyNotBecauseOfMatrix
)
980 ErrorMessage(STR_PROTECTIONERR
);
984 ScPatternAttr
aNewAttrs( new SfxItemSet( *GetViewData().GetDocument()->GetPool(),
985 ATTR_PATTERN_START
, ATTR_PATTERN_END
) );
987 aNewAttrs
.GetItemSet().Put( rAttrItem
);
988 // if justify is set (with Buttons), always indentation 0
989 if ( rAttrItem
.Which() == ATTR_HOR_JUSTIFY
)
990 aNewAttrs
.GetItemSet().Put( SfxUInt16Item( ATTR_INDENT
, 0 ) );
991 ApplySelectionPattern( aNewAttrs
);
995 // CellContentChanged is called in ApplySelectionPattern
998 // patterns and borders
1000 void ScViewFunc::ApplyPatternLines( const ScPatternAttr
& rAttr
, const SvxBoxItem
* pNewOuter
,
1001 const SvxBoxInfoItem
* pNewInner
)
1003 ScDocument
* pDoc
= GetViewData().GetDocument();
1004 ScMarkData
aFuncMark( GetViewData().GetMarkData() ); // local copy for UnmarkFiltered
1005 ScViewUtil::UnmarkFiltered( aFuncMark
, pDoc
);
1006 bool bRecord
= true;
1007 if (!pDoc
->IsUndoEnabled())
1010 bool bRemoveAdjCellBorder
= false;
1012 bRemoveAdjCellBorder
= pNewOuter
->IsRemoveAdjacentCellBorder();
1013 ScRange aMarkRange
, aMarkRangeWithEnvelope
;
1014 aFuncMark
.MarkToSimple();
1015 bool bMulti
= aFuncMark
.IsMultiMarked();
1017 aFuncMark
.GetMultiMarkArea( aMarkRange
);
1018 else if (aFuncMark
.IsMarked())
1019 aFuncMark
.GetMarkArea( aMarkRange
);
1022 aMarkRange
= ScRange( GetViewData().GetCurX(),
1023 GetViewData().GetCurY(), GetViewData().GetTabNo() );
1026 aFuncMark
.SetMarkArea(aMarkRange
);
1029 if( bRemoveAdjCellBorder
)
1030 aFuncMark
.GetSelectionCover( aMarkRangeWithEnvelope
);
1032 aMarkRangeWithEnvelope
= aMarkRange
;
1034 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
1036 ScDocShellModificator
aModificator( *pDocSh
);
1040 ScDocument
* pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
1041 SCTAB nStartTab
= aMarkRange
.aStart
.Tab();
1042 SCTAB nTabCount
= pDoc
->GetTableCount();
1043 bool bCopyOnlyMarked
= false;
1044 if( !bRemoveAdjCellBorder
)
1045 bCopyOnlyMarked
= bMulti
;
1046 pUndoDoc
->InitUndo( pDoc
, nStartTab
, nStartTab
);
1047 ScMarkData::iterator itr
= aFuncMark
.begin(), itrEnd
= aFuncMark
.end();
1048 for (; itr
!= itrEnd
; ++itr
)
1049 if (*itr
!= nStartTab
)
1050 pUndoDoc
->AddUndoTab( *itr
, *itr
);
1052 ScRange aCopyRange
= aMarkRangeWithEnvelope
;
1053 aCopyRange
.aStart
.SetTab(0);
1054 aCopyRange
.aEnd
.SetTab(nTabCount
-1);
1055 pDoc
->CopyToDocument( aCopyRange
, InsertDeleteFlags::ATTRIB
, bCopyOnlyMarked
, pUndoDoc
, &aFuncMark
);
1057 pDocSh
->GetUndoManager()->AddUndoAction(
1058 new ScUndoSelectionAttr(
1060 aMarkRange
.aStart
.Col(), aMarkRange
.aStart
.Row(), aMarkRange
.aStart
.Tab(),
1061 aMarkRange
.aEnd
.Col(), aMarkRange
.aEnd
.Row(), aMarkRange
.aEnd
.Tab(),
1062 pUndoDoc
, bCopyOnlyMarked
, &rAttr
, pNewOuter
, pNewInner
, &aMarkRangeWithEnvelope
) );
1065 sal_uInt16 nExt
= SC_PF_TESTMERGE
;
1066 pDocSh
->UpdatePaintExt( nExt
, aMarkRangeWithEnvelope
); // content before the change
1068 pDoc
->ApplySelectionFrame( aFuncMark
, pNewOuter
, pNewInner
);
1070 pDocSh
->UpdatePaintExt( nExt
, aMarkRangeWithEnvelope
); // content after the change
1072 aFuncMark
.MarkToMulti();
1073 pDoc
->ApplySelectionPattern( rAttr
, aFuncMark
);
1075 pDocSh
->PostPaint( aMarkRange
, PAINT_GRID
, nExt
);
1076 pDocSh
->UpdateOle(&GetViewData());
1077 aModificator
.SetDocumentModified();
1078 CellContentChanged();
1085 void ScViewFunc::ApplySelectionPattern( const ScPatternAttr
& rAttr
, bool bCursorOnly
)
1087 ScViewData
& rViewData
= GetViewData();
1088 ScDocShell
* pDocSh
= rViewData
.GetDocShell();
1089 ScDocument
& rDoc
= pDocSh
->GetDocument();
1090 ScMarkData
aFuncMark( rViewData
.GetMarkData() ); // local copy for UnmarkFiltered
1091 ScViewUtil::UnmarkFiltered( aFuncMark
, &rDoc
);
1093 bool bRecord
= true;
1094 if (!rDoc
.IsUndoEnabled())
1097 // State from old ItemSet doesn't matter for paint flags, as any change will be
1098 // from SfxItemState::SET in the new ItemSet (default is ignored in ApplyPattern).
1099 // New alignment is checked (check in PostPaint isn't enough) in case a right
1100 // alignment is changed to left.
1101 const SfxItemSet
& rNewSet
= rAttr
.GetItemSet();
1102 bool bSetLines
= rNewSet
.GetItemState( ATTR_BORDER
) == SfxItemState::SET
||
1103 rNewSet
.GetItemState( ATTR_SHADOW
) == SfxItemState::SET
;
1104 bool bSetAlign
= rNewSet
.GetItemState( ATTR_HOR_JUSTIFY
) == SfxItemState::SET
;
1106 sal_uInt16 nExtFlags
= 0;
1108 nExtFlags
|= SC_PF_LINES
;
1110 nExtFlags
|= SC_PF_WHOLEROWS
;
1112 ScDocShellModificator
aModificator( *pDocSh
);
1114 bool bMulti
= aFuncMark
.IsMultiMarked();
1115 aFuncMark
.MarkToMulti();
1116 bool bOnlyTab
= (!aFuncMark
.IsMultiMarked() && !bCursorOnly
&& aFuncMark
.GetSelectCount() > 1);
1119 SCCOL nCol
= rViewData
.GetCurX();
1120 SCROW nRow
= rViewData
.GetCurY();
1121 SCTAB nTab
= rViewData
.GetTabNo();
1122 aFuncMark
.SetMarkArea(ScRange(nCol
,nRow
,nTab
));
1123 aFuncMark
.MarkToMulti();
1126 ScRangeList aChangeRanges
;
1128 if (aFuncMark
.IsMultiMarked() && !bCursorOnly
)
1131 aFuncMark
.GetMultiMarkArea( aMarkRange
);
1132 SCTAB nTabCount
= rDoc
.GetTableCount();
1133 ScMarkData::iterator itr
= aFuncMark
.begin(), itrEnd
= aFuncMark
.end();
1134 for (; itr
!= itrEnd
; ++itr
)
1136 ScRange
aChangeRange( aMarkRange
);
1137 aChangeRange
.aStart
.SetTab( *itr
);
1138 aChangeRange
.aEnd
.SetTab( *itr
);
1139 aChangeRanges
.Append( aChangeRange
);
1142 SCCOL nStartCol
= aMarkRange
.aStart
.Col();
1143 SCROW nStartRow
= aMarkRange
.aStart
.Row();
1144 SCTAB nStartTab
= aMarkRange
.aStart
.Tab();
1145 SCCOL nEndCol
= aMarkRange
.aEnd
.Col();
1146 SCROW nEndRow
= aMarkRange
.aEnd
.Row();
1147 SCTAB nEndTab
= aMarkRange
.aEnd
.Tab();
1149 ScUndoSelectionAttr
* pUndoAttr
= nullptr;
1150 ScEditDataArray
* pEditDataArray
= nullptr;
1153 ScRange aCopyRange
= aMarkRange
;
1154 aCopyRange
.aStart
.SetTab(0);
1155 aCopyRange
.aEnd
.SetTab(nTabCount
-1);
1157 ScDocument
* pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
1158 pUndoDoc
->InitUndo( &rDoc
, nStartTab
, nStartTab
);
1159 itr
= aFuncMark
.begin();
1160 for (; itr
!= itrEnd
; ++itr
)
1161 if (*itr
!= nStartTab
)
1162 pUndoDoc
->AddUndoTab( *itr
, *itr
);
1163 rDoc
.CopyToDocument( aCopyRange
, InsertDeleteFlags::ATTRIB
, bMulti
, pUndoDoc
, &aFuncMark
);
1165 aFuncMark
.MarkToMulti();
1167 pUndoAttr
= new ScUndoSelectionAttr(
1168 pDocSh
, aFuncMark
, nStartCol
, nStartRow
, nStartTab
,
1169 nEndCol
, nEndRow
, nEndTab
, pUndoDoc
, bMulti
, &rAttr
);
1170 pDocSh
->GetUndoManager()->AddUndoAction(pUndoAttr
);
1171 pEditDataArray
= pUndoAttr
->GetDataArray();
1174 rDoc
.ApplySelectionPattern( rAttr
, aFuncMark
, pEditDataArray
);
1176 pDocSh
->PostPaint( nStartCol
, nStartRow
, nStartTab
,
1177 nEndCol
, nEndRow
, nEndTab
,
1178 PAINT_GRID
, nExtFlags
| SC_PF_TESTMERGE
);
1179 pDocSh
->UpdateOle(&GetViewData());
1180 aModificator
.SetDocumentModified();
1181 CellContentChanged();
1183 else // single cell - simpler undo
1185 SCCOL nCol
= rViewData
.GetCurX();
1186 SCROW nRow
= rViewData
.GetCurY();
1187 SCTAB nTab
= rViewData
.GetTabNo();
1189 EditTextObject
* pOldEditData
= nullptr;
1190 EditTextObject
* pNewEditData
= nullptr;
1191 ScAddress
aPos(nCol
, nRow
, nTab
);
1192 ScRefCellValue
aCell(rDoc
, aPos
);
1193 if (aCell
.meType
== CELLTYPE_EDIT
)
1195 const EditTextObject
* pEditObj
= aCell
.mpEditText
;
1196 pOldEditData
= pEditObj
->Clone();
1197 rDoc
.RemoveEditTextCharAttribs(aPos
, rAttr
);
1198 pEditObj
= rDoc
.GetEditText(aPos
);
1199 pNewEditData
= pEditObj
->Clone();
1202 aChangeRanges
.Append(aPos
);
1203 std::unique_ptr
<ScPatternAttr
> pOldPat(new ScPatternAttr(*rDoc
.GetPattern( nCol
, nRow
, nTab
)));
1205 rDoc
.ApplyPattern( nCol
, nRow
, nTab
, rAttr
);
1207 const ScPatternAttr
* pNewPat
= rDoc
.GetPattern( nCol
, nRow
, nTab
);
1211 ScUndoCursorAttr
* pUndo
= new ScUndoCursorAttr(
1212 pDocSh
, nCol
, nRow
, nTab
, pOldPat
.get(), pNewPat
, &rAttr
);
1213 pUndo
->SetEditData(pOldEditData
, pNewEditData
);
1214 pDocSh
->GetUndoManager()->AddUndoAction(pUndo
);
1216 pOldPat
.reset(); // is copied in undo (Pool)
1218 pDocSh
->PostPaint( nCol
,nRow
,nTab
, nCol
,nRow
,nTab
, PAINT_GRID
, nExtFlags
| SC_PF_TESTMERGE
);
1219 pDocSh
->UpdateOle(&GetViewData());
1220 aModificator
.SetDocumentModified();
1221 CellContentChanged();
1224 ScModelObj
* pModelObj
= HelperNotifyChanges::getMustPropagateChangesModel(*pDocSh
);
1227 css::uno::Sequence
< css::beans::PropertyValue
> aProperties
;
1228 sal_Int32 nCount
= 0;
1229 const SfxItemPropertyMap
& rMap
= ScCellObj::GetCellPropertyMap();
1230 PropertyEntryVector_t aPropVector
= rMap
.getPropertyEntries();
1231 for ( sal_uInt16 nWhich
= ATTR_PATTERN_START
; nWhich
<= ATTR_PATTERN_END
; ++nWhich
)
1233 const SfxPoolItem
* pItem
= nullptr;
1234 if ( rNewSet
.GetItemState( nWhich
, true, &pItem
) == SfxItemState::SET
&& pItem
)
1236 PropertyEntryVector_t::const_iterator aIt
= aPropVector
.begin();
1237 while ( aIt
!= aPropVector
.end())
1239 if ( aIt
->nWID
== nWhich
)
1242 pItem
->QueryValue( aVal
, aIt
->nMemberId
);
1243 aProperties
.realloc( nCount
+ 1 );
1244 aProperties
[ nCount
].Name
= aIt
->sName
;
1245 aProperties
[ nCount
].Value
<<= aVal
;
1252 HelperNotifyChanges::Notify(*pModelObj
, aChangeRanges
, "attribute", aProperties
);
1258 void ScViewFunc::ApplyUserItemSet( const SfxItemSet
& rItemSet
)
1260 // ItemSet from UI, may have different pool
1262 bool bOnlyNotBecauseOfMatrix
;
1263 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix
) && !bOnlyNotBecauseOfMatrix
)
1265 ErrorMessage(STR_PROTECTIONERR
);
1269 ScPatternAttr
aNewAttrs( GetViewData().GetDocument()->GetPool() );
1270 SfxItemSet
& rNewSet
= aNewAttrs
.GetItemSet();
1271 rNewSet
.Put( rItemSet
, false );
1272 ApplySelectionPattern( aNewAttrs
);
1274 AdjustBlockHeight();
1277 const SfxStyleSheet
* ScViewFunc::GetStyleSheetFromMarked()
1279 // Don't use UnmarkFiltered in slot state functions, for performance reasons.
1280 // The displayed state is always that of the whole selection including filtered rows.
1282 const ScStyleSheet
* pSheet
= nullptr;
1283 ScViewData
& rViewData
= GetViewData();
1284 ScDocument
* pDoc
= rViewData
.GetDocument();
1285 ScMarkData
& rMark
= rViewData
.GetMarkData();
1287 if ( rMark
.IsMarked() || rMark
.IsMultiMarked() )
1288 pSheet
= pDoc
->GetSelectionStyle( rMark
); // MarkToMulti isn't necessary
1290 pSheet
= pDoc
->GetStyle( rViewData
.GetCurX(),
1291 rViewData
.GetCurY(),
1292 rViewData
.GetTabNo() );
1297 void ScViewFunc::SetStyleSheetToMarked( SfxStyleSheet
* pStyleSheet
)
1299 // not editable because of matrix only? attribute OK nonetheless
1300 bool bOnlyNotBecauseOfMatrix
;
1301 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix
) && !bOnlyNotBecauseOfMatrix
)
1303 ErrorMessage(STR_PROTECTIONERR
);
1307 if ( !pStyleSheet
) return;
1309 ScViewData
& rViewData
= GetViewData();
1310 ScDocShell
* pDocSh
= rViewData
.GetDocShell();
1311 ScDocument
& rDoc
= pDocSh
->GetDocument();
1312 ScMarkData
aFuncMark( rViewData
.GetMarkData() ); // local copy for UnmarkFiltered
1313 ScViewUtil::UnmarkFiltered( aFuncMark
, &rDoc
);
1314 SCTAB nTabCount
= rDoc
.GetTableCount();
1315 bool bRecord
= true;
1316 if (!rDoc
.IsUndoEnabled())
1319 ScDocShellModificator
aModificator( *pDocSh
);
1321 if ( aFuncMark
.IsMarked() || aFuncMark
.IsMultiMarked() )
1324 aFuncMark
.MarkToMulti();
1325 aFuncMark
.GetMultiMarkArea( aMarkRange
);
1329 SCTAB nTab
= rViewData
.GetTabNo();
1330 ScDocument
* pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
1331 pUndoDoc
->InitUndo( &rDoc
, nTab
, nTab
);
1332 ScMarkData::iterator itr
= aFuncMark
.begin(), itrEnd
= aFuncMark
.end();
1333 for (; itr
!= itrEnd
; ++itr
)
1335 pUndoDoc
->AddUndoTab( *itr
, *itr
);
1337 ScRange aCopyRange
= aMarkRange
;
1338 aCopyRange
.aStart
.SetTab(0);
1339 aCopyRange
.aEnd
.SetTab(nTabCount
-1);
1340 rDoc
.CopyToDocument( aCopyRange
, InsertDeleteFlags::ATTRIB
, true, pUndoDoc
, &aFuncMark
);
1341 aFuncMark
.MarkToMulti();
1343 OUString aName
= pStyleSheet
->GetName();
1344 pDocSh
->GetUndoManager()->AddUndoAction(
1345 new ScUndoSelectionStyle( pDocSh
, aFuncMark
, aMarkRange
, aName
, pUndoDoc
) );
1348 rDoc
.ApplySelectionStyle( static_cast<ScStyleSheet
&>(*pStyleSheet
), aFuncMark
);
1350 if (!AdjustBlockHeight())
1351 rViewData
.GetDocShell()->PostPaint( aMarkRange
, PAINT_GRID
);
1353 aFuncMark
.MarkToSimple();
1357 SCCOL nCol
= rViewData
.GetCurX();
1358 SCROW nRow
= rViewData
.GetCurY();
1359 SCTAB nTab
= rViewData
.GetTabNo();
1363 ScDocument
* pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
1364 pUndoDoc
->InitUndo( &rDoc
, nTab
, nTab
);
1365 ScMarkData::iterator itr
= aFuncMark
.begin(), itrEnd
= aFuncMark
.end();
1366 for (; itr
!= itrEnd
; ++itr
)
1368 pUndoDoc
->AddUndoTab( *itr
, *itr
);
1370 ScRange
aCopyRange( nCol
, nRow
, 0, nCol
, nRow
, nTabCount
-1 );
1371 rDoc
.CopyToDocument( aCopyRange
, InsertDeleteFlags::ATTRIB
, false, pUndoDoc
);
1373 ScRange
aMarkRange ( nCol
, nRow
, nTab
);
1374 ScMarkData aUndoMark
= aFuncMark
;
1375 aUndoMark
.SetMultiMarkArea( aMarkRange
);
1377 OUString aName
= pStyleSheet
->GetName();
1378 pDocSh
->GetUndoManager()->AddUndoAction(
1379 new ScUndoSelectionStyle( pDocSh
, aUndoMark
, aMarkRange
, aName
, pUndoDoc
) );
1382 ScMarkData::iterator itr
= aFuncMark
.begin(), itrEnd
= aFuncMark
.end();
1383 for (; itr
!= itrEnd
; ++itr
)
1384 rDoc
.ApplyStyle( nCol
, nRow
, *itr
, static_cast<ScStyleSheet
&>(*pStyleSheet
) );
1386 if (!AdjustBlockHeight())
1387 rViewData
.GetDocShell()->PostPaintCell( nCol
, nRow
, nTab
);
1391 aModificator
.SetDocumentModified();
1396 void ScViewFunc::RemoveStyleSheetInUse( const SfxStyleSheetBase
* pStyleSheet
)
1398 if ( !pStyleSheet
) return;
1400 ScViewData
& rViewData
= GetViewData();
1401 ScDocument
* pDoc
= rViewData
.GetDocument();
1402 ScDocShell
* pDocSh
= rViewData
.GetDocShell();
1404 ScDocShellModificator
aModificator( *pDocSh
);
1406 ScopedVclPtrInstance
< VirtualDevice
> pVirtDev
;
1407 pVirtDev
->SetMapMode(MAP_PIXEL
);
1408 pDoc
->StyleSheetChanged( pStyleSheet
, true, pVirtDev
,
1409 rViewData
.GetPPTX(),
1410 rViewData
.GetPPTY(),
1411 rViewData
.GetZoomX(),
1412 rViewData
.GetZoomY() );
1414 pDocSh
->PostPaint( 0,0,0, MAXCOL
,MAXROW
,MAXTAB
, PAINT_GRID
|PAINT_LEFT
);
1415 aModificator
.SetDocumentModified();
1417 ScInputHandler
* pHdl
= SC_MOD()->GetInputHdl();
1419 pHdl
->ForgetLastPattern();
1422 void ScViewFunc::UpdateStyleSheetInUse( const SfxStyleSheetBase
* pStyleSheet
)
1424 if ( !pStyleSheet
) return;
1426 ScViewData
& rViewData
= GetViewData();
1427 ScDocument
* pDoc
= rViewData
.GetDocument();
1428 ScDocShell
* pDocSh
= rViewData
.GetDocShell();
1430 ScDocShellModificator
aModificator( *pDocSh
);
1432 ScopedVclPtrInstance
< VirtualDevice
> pVirtDev
;
1433 pVirtDev
->SetMapMode(MAP_PIXEL
);
1434 pDoc
->StyleSheetChanged( pStyleSheet
, false, pVirtDev
,
1435 rViewData
.GetPPTX(),
1436 rViewData
.GetPPTY(),
1437 rViewData
.GetZoomX(),
1438 rViewData
.GetZoomY() );
1440 pDocSh
->PostPaint( 0,0,0, MAXCOL
,MAXROW
,MAXTAB
, PAINT_GRID
|PAINT_LEFT
);
1441 aModificator
.SetDocumentModified();
1443 ScInputHandler
* pHdl
= SC_MOD()->GetInputHdl();
1445 pHdl
->ForgetLastPattern();
1448 // insert cells - undo OK
1450 bool ScViewFunc::InsertCells( InsCellCmd eCmd
, bool bRecord
, bool bPartOfPaste
)
1453 if (GetViewData().GetSimpleArea(aRange
) == SC_MARK_SIMPLE
)
1455 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
1456 const ScMarkData
& rMark
= GetViewData().GetMarkData();
1457 bool bSuccess
= pDocSh
->GetDocFunc().InsertCells( aRange
, &rMark
, eCmd
, bRecord
, false, bPartOfPaste
);
1460 pDocSh
->UpdateOle(&GetViewData());
1461 CellContentChanged();
1464 if ( eCmd
== INS_INSROWS_BEFORE
|| eCmd
== INS_INSCOLS_BEFORE
|| eCmd
== INS_INSROWS_AFTER
|| eCmd
== INS_INSCOLS_AFTER
)
1466 OUString aOperation
= ( eCmd
== INS_INSROWS_BEFORE
|| eCmd
== INS_INSROWS_AFTER
) ?
1467 OUString("insert-rows"):
1468 OUString("insert-columns");
1469 HelperNotifyChanges::NotifyIfChangesListeners(*pDocSh
, aRange
, aOperation
);
1476 ErrorMessage(STR_NOMULTISELECT
);
1481 // delete cells - undo OK
1483 void ScViewFunc::DeleteCells( DelCellCmd eCmd
)
1486 if ( GetViewData().GetSimpleArea( aRange
) == SC_MARK_SIMPLE
)
1488 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
1489 const ScMarkData
& rMark
= GetViewData().GetMarkData();
1491 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
1492 // #i94841# [Collaboration] if deleting rows is rejected, the content is sometimes wrong
1493 if ( pDocSh
->IsDocShared() && ( eCmd
== DEL_DELROWS
|| eCmd
== DEL_DELCOLS
) )
1495 ScRange
aDelRange( aRange
.aStart
);
1496 SCCOLROW nCount
= 0;
1497 if ( eCmd
== DEL_DELROWS
)
1499 nCount
= sal::static_int_cast
< SCCOLROW
>( aRange
.aEnd
.Row() - aRange
.aStart
.Row() + 1 );
1503 nCount
= sal::static_int_cast
< SCCOLROW
>( aRange
.aEnd
.Col() - aRange
.aStart
.Col() + 1 );
1505 while ( nCount
> 0 )
1507 pDocSh
->GetDocFunc().DeleteCells( aDelRange
, &rMark
, eCmd
, false );
1514 pDocSh
->GetDocFunc().DeleteCells( aRange
, &rMark
, eCmd
, false );
1517 pDocSh
->UpdateOle(&GetViewData());
1518 CellContentChanged();
1521 if ( eCmd
== DEL_DELROWS
|| eCmd
== DEL_DELCOLS
)
1523 OUString aOperation
= ( eCmd
== DEL_DELROWS
) ?
1524 OUString("delete-rows"):
1525 OUString("delete-columns");
1526 HelperNotifyChanges::NotifyIfChangesListeners(*pDocSh
, aRange
, aOperation
);
1529 // put cursor directly behind deleted range
1530 SCCOL nCurX
= GetViewData().GetCurX();
1531 SCROW nCurY
= GetViewData().GetCurY();
1532 if ( eCmd
==DEL_CELLSLEFT
|| eCmd
==DEL_DELCOLS
)
1533 nCurX
= aRange
.aStart
.Col();
1535 nCurY
= aRange
.aStart
.Row();
1536 SetCursor( nCurX
, nCurY
);
1540 if (eCmd
== DEL_DELCOLS
)
1541 DeleteMulti( false );
1542 else if (eCmd
== DEL_DELROWS
)
1543 DeleteMulti( true );
1545 ErrorMessage(STR_NOMULTISELECT
);
1551 void ScViewFunc::DeleteMulti( bool bRows
)
1553 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
1554 ScDocShellModificator
aModificator( *pDocSh
);
1555 SCTAB nTab
= GetViewData().GetTabNo();
1556 ScDocument
& rDoc
= pDocSh
->GetDocument();
1557 ScMarkData
aFuncMark( GetViewData().GetMarkData() ); // local copy for UnmarkFiltered
1558 ScViewUtil::UnmarkFiltered( aFuncMark
, &rDoc
);
1560 bool bRecord
= true;
1561 if (!rDoc
.IsUndoEnabled())
1564 std::vector
<sc::ColRowSpan
> aSpans
;
1566 aSpans
= aFuncMark
.GetMarkedRowSpans();
1568 aSpans
= aFuncMark
.GetMarkedColSpans();
1572 SCCOLROW nCurPos
= bRows
? GetViewData().GetCurY() : GetViewData().GetCurX();
1573 aSpans
.push_back(sc::ColRowSpan(nCurPos
, nCurPos
));
1578 sal_uInt16 nErrorId
= 0;
1579 bool bNeedRefresh
= false;
1580 for (size_t i
= 0, n
= aSpans
.size(); i
< n
&& !nErrorId
; ++i
)
1582 SCCOLROW nStart
= aSpans
[i
].mnStart
;
1583 SCCOLROW nEnd
= aSpans
[i
].mnEnd
;
1585 SCCOL nStartCol
, nEndCol
;
1586 SCROW nStartRow
, nEndRow
;
1591 nStartRow
= static_cast<SCROW
>(nStart
);
1592 nEndRow
= static_cast<SCROW
>(nEnd
);
1596 nStartCol
= static_cast<SCCOL
>(nStart
);
1597 nEndCol
= static_cast<SCCOL
>(nEnd
);
1602 // cell protection (only needed for first range, as all following cells are moved)
1605 // test to the end of the sheet
1606 ScEditableTester
aTester( &rDoc
, nTab
, nStartCol
, nStartRow
, MAXCOL
, MAXROW
);
1607 if (!aTester
.IsEditable())
1608 nErrorId
= aTester
.GetMessageId();
1612 SCCOL nMergeStartX
= nStartCol
;
1613 SCROW nMergeStartY
= nStartRow
;
1614 SCCOL nMergeEndX
= nEndCol
;
1615 SCROW nMergeEndY
= nEndRow
;
1616 rDoc
.ExtendMerge( nMergeStartX
, nMergeStartY
, nMergeEndX
, nMergeEndY
, nTab
);
1617 rDoc
.ExtendOverlapped( nMergeStartX
, nMergeStartY
, nMergeEndX
, nMergeEndY
, nTab
);
1619 if ( nMergeStartX
!= nStartCol
|| nMergeStartY
!= nStartRow
)
1621 // Disallow deleting parts of a merged cell.
1622 // Deleting the start is allowed (merge is removed), so the end doesn't have to be checked.
1624 nErrorId
= STR_MSSG_DELETECELLS_0
;
1626 if ( nMergeEndX
!= nEndCol
|| nMergeEndY
!= nEndRow
)
1628 // detect if the start of a merged cell is deleted, so the merge flags can be refreshed
1630 bNeedRefresh
= true;
1636 ErrorMessage( nErrorId
);
1642 WaitObject
aWait( GetFrameWin() ); // important for TrackFormulas in UpdateReference
1644 ScDocument
* pUndoDoc
= nullptr;
1645 ScRefUndoData
* pUndoData
= nullptr;
1648 pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
1649 pUndoDoc
->InitUndo( &rDoc
, nTab
, nTab
, !bRows
, bRows
); // row height
1651 for (sc::ColRowSpan
& rSpan
: aSpans
)
1653 SCCOLROW nStart
= rSpan
.mnStart
;
1654 SCCOLROW nEnd
= rSpan
.mnEnd
;
1656 rDoc
.CopyToDocument( 0,nStart
,nTab
, MAXCOL
,nEnd
,nTab
, InsertDeleteFlags::ALL
,false,pUndoDoc
);
1658 rDoc
.CopyToDocument( static_cast<SCCOL
>(nStart
),0,nTab
,
1659 static_cast<SCCOL
>(nEnd
),MAXROW
,nTab
,
1660 InsertDeleteFlags::ALL
,false,pUndoDoc
);
1663 // all Formulas because of references
1664 SCTAB nTabCount
= rDoc
.GetTableCount();
1665 pUndoDoc
->AddUndoTab( 0, nTabCount
-1 );
1666 rDoc
.CopyToDocument( 0,0,0, MAXCOL
,MAXROW
,MAXTAB
, InsertDeleteFlags::FORMULA
,false,pUndoDoc
);
1668 pUndoData
= new ScRefUndoData( &rDoc
);
1670 rDoc
.BeginDrawUndo();
1673 std::vector
<sc::ColRowSpan
>::const_reverse_iterator ri
= aSpans
.rbegin(), riEnd
= aSpans
.rend();
1674 for (; ri
!= riEnd
; ++ri
)
1676 SCCOLROW nEnd
= ri
->mnEnd
;
1677 SCCOLROW nStart
= ri
->mnStart
;
1680 rDoc
.DeleteRow( 0,nTab
, MAXCOL
,nTab
, nStart
, static_cast<SCSIZE
>(nEnd
-nStart
+1) );
1682 rDoc
.DeleteCol( 0,nTab
, MAXROW
,nTab
, static_cast<SCCOL
>(nStart
), static_cast<SCSIZE
>(nEnd
-nStart
+1) );
1687 SCCOLROW nFirstStart
= aSpans
[0].mnStart
;
1688 SCCOL nStartCol
= bRows
? 0 : static_cast<SCCOL
>(nFirstStart
);
1689 SCROW nStartRow
= bRows
? static_cast<SCROW
>(nFirstStart
) : 0;
1690 SCCOL nEndCol
= MAXCOL
;
1691 SCROW nEndRow
= MAXROW
;
1693 rDoc
.RemoveFlagsTab( nStartCol
, nStartRow
, nEndCol
, nEndRow
, nTab
, ScMF::Hor
| ScMF::Ver
);
1694 rDoc
.ExtendMerge( nStartCol
, nStartRow
, nEndCol
, nEndRow
, nTab
, true );
1699 pDocSh
->GetUndoManager()->AddUndoAction(
1700 new ScUndoDeleteMulti(
1701 pDocSh
, bRows
, bNeedRefresh
, nTab
, aSpans
, pUndoDoc
, pUndoData
));
1704 if (!AdjustRowHeight(0, MAXROW
))
1709 0, aSpans
[0].mnStart
, nTab
,
1710 MAXCOL
, MAXROW
, nTab
, (PAINT_GRID
| PAINT_LEFT
));
1715 static_cast<SCCOL
>(aSpans
[0].mnStart
), 0, nTab
,
1716 MAXCOL
, MAXROW
, nTab
, (PAINT_GRID
| PAINT_TOP
));
1721 aModificator
.SetDocumentModified();
1723 CellContentChanged();
1725 // put cursor directly behind the first deleted range
1726 SCCOL nCurX
= GetViewData().GetCurX();
1727 SCROW nCurY
= GetViewData().GetCurY();
1729 nCurY
= aSpans
[0].mnStart
;
1731 nCurX
= static_cast<SCCOL
>(aSpans
[0].mnStart
);
1732 SetCursor( nCurX
, nCurY
);
1734 SfxGetpApp()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED
) );
1739 void ScViewFunc::DeleteContents( InsertDeleteFlags nFlags
)
1741 ScViewData
& rViewData
= GetViewData();
1742 rViewData
.SetPasteMode( SC_PASTE_NONE
);
1743 rViewData
.GetViewShell()->UpdateCopySourceOverlay();
1745 // not editable because of matrix only? attribute OK nonetheless
1746 bool bOnlyNotBecauseOfMatrix
;
1747 bool bEditable
= SelectionEditable( &bOnlyNotBecauseOfMatrix
);
1750 if ( !(bOnlyNotBecauseOfMatrix
&&
1751 ((nFlags
& (InsertDeleteFlags::ATTRIB
| InsertDeleteFlags::EDITATTR
)) == nFlags
)) )
1753 ErrorMessage(bOnlyNotBecauseOfMatrix
? STR_MATRIXFRAGMENTERR
: STR_PROTECTIONERR
);
1759 bool bSimple
= false;
1761 ScDocument
* pDoc
= GetViewData().GetDocument();
1762 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
1763 ScMarkData
aFuncMark( GetViewData().GetMarkData() ); // local copy for UnmarkFiltered
1764 ScViewUtil::UnmarkFiltered( aFuncMark
, pDoc
);
1767 if (!pDoc
->IsUndoEnabled())
1770 if ( !aFuncMark
.IsMarked() && !aFuncMark
.IsMultiMarked() )
1772 aMarkRange
.aStart
.SetCol(GetViewData().GetCurX());
1773 aMarkRange
.aStart
.SetRow(GetViewData().GetCurY());
1774 aMarkRange
.aStart
.SetTab(GetViewData().GetTabNo());
1775 aMarkRange
.aEnd
= aMarkRange
.aStart
;
1776 if ( pDoc
->HasAttrib( aMarkRange
, HASATTR_MERGED
) )
1778 aFuncMark
.SetMarkArea( aMarkRange
);
1784 HideAllCursors(); // for if summary is cancelled
1786 ScDocFunc
& rDocFunc
= pDocSh
->GetDocFunc();
1788 rDocFunc
.DeleteCell(aMarkRange
.aStart
, aFuncMark
, nFlags
, bRecord
);
1790 rDocFunc
.DeleteContents(aFuncMark
, nFlags
, bRecord
, false);
1792 pDocSh
->UpdateOle(&GetViewData());
1794 if (ScModelObj
*pModelObj
= HelperNotifyChanges::getMustPropagateChangesModel(*pDocSh
))
1796 ScRangeList aChangeRanges
;
1799 aChangeRanges
.Append( aMarkRange
);
1803 aFuncMark
.FillRangeListWithMarks( &aChangeRanges
, false );
1805 HelperNotifyChanges::Notify(*pModelObj
, aChangeRanges
);
1808 CellContentChanged();
1811 if ( nFlags
& InsertDeleteFlags::ATTRIB
)
1813 if ( nFlags
& InsertDeleteFlags::CONTENTS
)
1816 StartFormatArea(); // delete attribute is also attribute-change
1820 // column width/row height (via header) - undo OK
1822 void ScViewFunc::SetWidthOrHeight(
1823 bool bWidth
, const std::vector
<sc::ColRowSpan
>& rRanges
, ScSizeMode eMode
,
1824 sal_uInt16 nSizeTwips
, bool bRecord
, ScMarkData
* pMarkData
)
1826 if (rRanges
.empty())
1829 // Use view's mark if none specified, but do not modify the original data,
1830 // i.e. no MarkToMulti() on that.
1831 ScMarkData
aMarkData( pMarkData
? *pMarkData
: GetViewData().GetMarkData());
1833 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
1834 ScDocument
& rDoc
= pDocSh
->GetDocument();
1835 SCTAB nFirstTab
= aMarkData
.GetFirstSelected();
1836 SCTAB nCurTab
= GetViewData().GetTabNo();
1838 if (bRecord
&& !rDoc
.IsUndoEnabled())
1841 ScDocShellModificator
aModificator( *pDocSh
);
1843 bool bAllowed
= true;
1844 ScMarkData::iterator itr
= aMarkData
.begin(), itrEnd
= aMarkData
.end();
1845 for (; itr
!= itrEnd
&& bAllowed
; ++itr
)
1847 for (size_t i
= 0, n
= rRanges
.size(); i
< n
&& bAllowed
; ++i
)
1852 bAllowed
= rDoc
.IsBlockEditable(
1853 *itr
, rRanges
[i
].mnStart
, 0, rRanges
[i
].mnEnd
, MAXROW
,
1854 &bOnlyMatrix
) || bOnlyMatrix
;
1858 bAllowed
= rDoc
.IsBlockEditable(
1859 *itr
, 0, rRanges
[i
].mnStart
, MAXCOL
,rRanges
[i
].mnEnd
, &bOnlyMatrix
) || bOnlyMatrix
;
1864 // Allow users to resize cols/rows in readonly docs despite the r/o state.
1865 // It is frustrating to be unable to see content in mis-sized cells.
1866 if( !bAllowed
&& !pDocSh
->IsReadOnly() )
1868 ErrorMessage(STR_PROTECTIONERR
);
1872 SCCOLROW nStart
= rRanges
.front().mnStart
;
1873 SCCOLROW nEnd
= rRanges
.back().mnEnd
;
1875 bool bFormula
= false;
1876 if ( eMode
== SC_SIZE_OPTIMAL
)
1878 const ScViewOptions
& rOpts
= GetViewData().GetOptions();
1879 bFormula
= rOpts
.GetOption( VOPT_FORMULAS
);
1882 ScDocument
* pUndoDoc
= nullptr;
1883 ScOutlineTable
* pUndoTab
= nullptr;
1884 std::vector
<sc::ColRowSpan
> aUndoRanges
;
1888 rDoc
.BeginDrawUndo(); // Drawing Updates
1890 pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
1891 itr
= aMarkData
.begin();
1892 for (; itr
!= itrEnd
; ++itr
)
1896 if ( *itr
== nFirstTab
)
1897 pUndoDoc
->InitUndo( &rDoc
, *itr
, *itr
, true );
1899 pUndoDoc
->AddUndoTab( *itr
, *itr
, true );
1900 rDoc
.CopyToDocument( static_cast<SCCOL
>(nStart
), 0, *itr
,
1901 static_cast<SCCOL
>(nEnd
), MAXROW
, *itr
, InsertDeleteFlags::NONE
,
1906 if ( *itr
== nFirstTab
)
1907 pUndoDoc
->InitUndo( &rDoc
, *itr
, *itr
, false, true );
1909 pUndoDoc
->AddUndoTab( *itr
, *itr
, false, true );
1910 rDoc
.CopyToDocument( 0, nStart
, *itr
, MAXCOL
, nEnd
, *itr
, InsertDeleteFlags::NONE
, false, pUndoDoc
);
1914 aUndoRanges
= rRanges
;
1916 //! outlines from all tab?
1917 ScOutlineTable
* pTable
= rDoc
.GetOutlineTable( nCurTab
);
1919 pUndoTab
= new ScOutlineTable( *pTable
);
1922 if ( eMode
==SC_SIZE_OPTIMAL
|| eMode
==SC_SIZE_VISOPT
)
1923 aMarkData
.MarkToMulti();
1925 bool bShow
= nSizeTwips
> 0 || eMode
!= SC_SIZE_DIRECT
;
1926 bool bOutline
= false;
1928 itr
= aMarkData
.begin();
1929 for (; itr
!= itrEnd
; ++itr
)
1933 for (const sc::ColRowSpan
& rRange
: rRanges
)
1935 SCCOLROW nStartNo
= rRange
.mnStart
;
1936 SCCOLROW nEndNo
= rRange
.mnEnd
;
1938 if ( !bWidth
) // height always blockwise
1940 if ( eMode
==SC_SIZE_OPTIMAL
|| eMode
==SC_SIZE_VISOPT
)
1942 bool bAll
= ( eMode
==SC_SIZE_OPTIMAL
);
1945 // delete CR_MANUALSIZE for all in range,
1946 // then SetOptimalHeight with bShrink = FALSE
1947 for (SCROW nRow
= nStartNo
; nRow
<= nEndNo
; ++nRow
)
1949 SCROW nLastRow
= nRow
;
1950 if (rDoc
.RowHidden(nRow
, nTab
, nullptr, &nLastRow
))
1956 sal_uInt8 nOld
= rDoc
.GetRowFlags(nRow
, nTab
);
1957 if (nOld
& CR_MANUALSIZE
)
1958 rDoc
.SetRowFlags(nRow
, nTab
, nOld
& ~CR_MANUALSIZE
);
1962 double nPPTX
= GetViewData().GetPPTX();
1963 double nPPTY
= GetViewData().GetPPTY();
1964 Fraction aZoomX
= GetViewData().GetZoomX();
1965 Fraction aZoomY
= GetViewData().GetZoomY();
1967 ScSizeDeviceProvider
aProv(pDocSh
);
1968 if (aProv
.IsPrinter())
1970 nPPTX
= aProv
.GetPPTX();
1971 nPPTY
= aProv
.GetPPTY();
1972 aZoomX
= aZoomY
= Fraction( 1, 1 );
1975 sc::RowHeightContext
aCxt(nPPTX
, nPPTY
, aZoomX
, aZoomY
, aProv
.GetDevice());
1976 aCxt
.setForceAutoSize(bAll
);
1977 aCxt
.setExtraHeight(nSizeTwips
);
1978 rDoc
.SetOptimalHeight(aCxt
, nStartNo
, nEndNo
, nTab
);
1980 rDoc
.ShowRows( nStartNo
, nEndNo
, nTab
, true );
1982 // Manual-Flag already (re)set in SetOptimalHeight in case of bAll=sal_True
1983 // (set for Extra-Height, else reset).
1985 else if ( eMode
==SC_SIZE_DIRECT
)
1989 rDoc
.SetRowHeightRange( nStartNo
, nEndNo
, nTab
, nSizeTwips
);
1990 rDoc
.SetManualHeight( nStartNo
, nEndNo
, nTab
, true ); // height was set manually
1992 rDoc
.ShowRows( nStartNo
, nEndNo
, nTab
, nSizeTwips
!= 0 );
1994 else if ( eMode
==SC_SIZE_SHOW
)
1996 rDoc
.ShowRows( nStartNo
, nEndNo
, nTab
, true );
1999 else // column width
2001 for (SCCOL nCol
=static_cast<SCCOL
>(nStartNo
); nCol
<=static_cast<SCCOL
>(nEndNo
); nCol
++)
2003 if ( eMode
!= SC_SIZE_VISOPT
|| !rDoc
.ColHidden(nCol
, nTab
) )
2005 sal_uInt16 nThisSize
= nSizeTwips
;
2007 if ( eMode
==SC_SIZE_OPTIMAL
|| eMode
==SC_SIZE_VISOPT
)
2008 nThisSize
= nSizeTwips
+ GetOptimalColWidth( nCol
, nTab
, bFormula
);
2010 rDoc
.SetColWidth( nCol
, nTab
, nThisSize
);
2012 rDoc
.ShowCol( nCol
, nTab
, bShow
);
2021 if ( rDoc
.UpdateOutlineCol( static_cast<SCCOL
>(nStartNo
),
2022 static_cast<SCCOL
>(nEndNo
), nTab
, bShow
) )
2027 if ( rDoc
.UpdateOutlineRow( nStartNo
, nEndNo
, nTab
, bShow
) )
2031 rDoc
.SetDrawPageSize(nTab
);
2039 pDocSh
->GetUndoManager()->AddUndoAction(
2040 new ScUndoWidthOrHeight(
2041 pDocSh
, aMarkData
, nStart
, nCurTab
, nEnd
, nCurTab
,
2042 pUndoDoc
, aUndoRanges
, pUndoTab
, eMode
, nSizeTwips
, bWidth
));
2045 // fdo#36247 Ensure that the drawing layer's map mode scaling factors match
2046 // the new heights and widths.
2047 GetViewData().GetView()->RefreshZoom();
2049 itr
= aMarkData
.begin();
2050 for (; itr
!= itrEnd
; ++itr
)
2051 rDoc
.UpdatePageBreaks( *itr
);
2053 GetViewData().GetView()->UpdateScrollBars();
2056 itr
= aMarkData
.begin();
2057 for (; itr
!= itrEnd
; ++itr
)
2062 if (rDoc
.HasAttrib( static_cast<SCCOL
>(nStart
),0,nTab
,
2063 static_cast<SCCOL
>(nEnd
),MAXROW
,nTab
,
2064 HASATTR_MERGED
| HASATTR_OVERLAPPED
))
2066 if (nStart
> 0) // go upwards because of Lines and cursor
2068 pDocSh
->PostPaint( static_cast<SCCOL
>(nStart
), 0, nTab
,
2069 MAXCOL
, MAXROW
, nTab
, PAINT_GRID
| PAINT_TOP
);
2073 if (rDoc
.HasAttrib( 0,nStart
,nTab
, MAXCOL
,nEnd
,nTab
, HASATTR_MERGED
| HASATTR_OVERLAPPED
))
2077 pDocSh
->PostPaint( 0, nStart
, nTab
, MAXCOL
, MAXROW
, nTab
, PAINT_GRID
| PAINT_LEFT
);
2081 pDocSh
->UpdateOle(&GetViewData());
2082 if( !pDocSh
->IsReadOnly() )
2083 aModificator
.SetDocumentModified();
2088 if (ScModelObj
* pModelObj
= HelperNotifyChanges::getMustPropagateChangesModel(*pDocSh
))
2090 ScRangeList aChangeRanges
;
2091 itr
= aMarkData
.begin();
2092 for (; itr
!= itrEnd
; ++itr
)
2095 for (const sc::ColRowSpan
& rRange
: rRanges
)
2097 SCCOL nStartCol
= rRange
.mnStart
;
2098 SCCOL nEndCol
= rRange
.mnEnd
;
2099 for ( SCCOL nCol
= nStartCol
; nCol
<= nEndCol
; ++nCol
)
2101 aChangeRanges
.Append( ScRange( nCol
, 0, nTab
) );
2105 HelperNotifyChanges::Notify(*pModelObj
, aChangeRanges
, "column-resize");
2110 // column width/row height (via marked range)
2112 void ScViewFunc::SetMarkedWidthOrHeight( bool bWidth
, ScSizeMode eMode
, sal_uInt16 nSizeTwips
)
2114 ScMarkData
& rMark
= GetViewData().GetMarkData();
2116 rMark
.MarkToMulti();
2117 if (!rMark
.IsMultiMarked())
2119 SCCOL nCol
= GetViewData().GetCurX();
2120 SCROW nRow
= GetViewData().GetCurY();
2121 SCTAB nTab
= GetViewData().GetTabNo();
2124 rMark
.SetMultiMarkArea( ScRange( nCol
,nRow
,nTab
) );
2128 std::vector
<sc::ColRowSpan
> aRanges
=
2129 bWidth
? rMark
.GetMarkedColSpans() : rMark
.GetMarkedRowSpans();
2131 SetWidthOrHeight(bWidth
, aRanges
, eMode
, nSizeTwips
);
2133 rMark
.MarkToSimple();
2136 void ScViewFunc::ModifyCellSize( ScDirection eDir
, bool bOptimal
)
2138 //! step size adjustable
2139 // step size is also minimum
2140 sal_uInt16 nStepX
= STD_COL_WIDTH
/ 5;
2141 sal_uInt16 nStepY
= ScGlobal::nStdRowHeight
;
2143 ScModule
* pScMod
= SC_MOD();
2144 bool bAnyEdit
= pScMod
->IsInputMode();
2145 SCCOL nCol
= GetViewData().GetCurX();
2146 SCROW nRow
= GetViewData().GetCurY();
2147 SCTAB nTab
= GetViewData().GetTabNo();
2148 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
2149 ScDocument
& rDoc
= pDocSh
->GetDocument();
2151 bool bAllowed
, bOnlyMatrix
;
2152 if ( eDir
== DIR_LEFT
|| eDir
== DIR_RIGHT
)
2153 bAllowed
= rDoc
.IsBlockEditable( nTab
, nCol
,0, nCol
,MAXROW
, &bOnlyMatrix
);
2155 bAllowed
= rDoc
.IsBlockEditable( nTab
, 0,nRow
, MAXCOL
,nRow
, &bOnlyMatrix
);
2156 if ( !bAllowed
&& !bOnlyMatrix
)
2158 ErrorMessage(STR_PROTECTIONERR
);
2164 sal_uInt16 nWidth
= rDoc
.GetColWidth( nCol
, nTab
);
2165 sal_uInt16 nHeight
= rDoc
.GetRowHeight( nRow
, nTab
);
2166 std::vector
<sc::ColRowSpan
> aRange(1, sc::ColRowSpan(0,0));
2167 if ( eDir
== DIR_LEFT
|| eDir
== DIR_RIGHT
)
2169 if (bOptimal
) // width of this single cell
2173 // when editing the actual entered width
2174 ScInputHandler
* pHdl
= pScMod
->GetInputHdl( GetViewData().GetViewShell() );
2177 long nEdit
= pHdl
->GetTextSize().Width(); // in 0.01 mm
2179 const ScPatternAttr
* pPattern
= rDoc
.GetPattern( nCol
, nRow
, nTab
);
2180 const SvxMarginItem
& rMItem
=
2181 static_cast<const SvxMarginItem
&>(pPattern
->GetItem(ATTR_MARGIN
));
2182 sal_uInt16 nMargin
= rMItem
.GetLeftMargin() + rMItem
.GetRightMargin();
2183 if ( static_cast<const SvxHorJustifyItem
&>( pPattern
->
2184 GetItem( ATTR_HOR_JUSTIFY
)).GetValue() == SVX_HOR_JUSTIFY_LEFT
)
2185 nMargin
= sal::static_int_cast
<sal_uInt16
>(
2186 nMargin
+ static_cast<const SfxUInt16Item
&>(pPattern
->GetItem(ATTR_INDENT
)).GetValue() );
2188 nWidth
= (sal_uInt16
)(nEdit
* pDocSh
->GetOutputFactor() / HMM_PER_TWIPS
)
2189 + nMargin
+ STD_EXTRA_WIDTH
;
2194 double nPPTX
= GetViewData().GetPPTX();
2195 double nPPTY
= GetViewData().GetPPTY();
2196 Fraction aZoomX
= GetViewData().GetZoomX();
2197 Fraction aZoomY
= GetViewData().GetZoomY();
2199 ScSizeDeviceProvider
aProv(pDocSh
);
2200 if (aProv
.IsPrinter())
2202 nPPTX
= aProv
.GetPPTX();
2203 nPPTY
= aProv
.GetPPTY();
2204 aZoomX
= aZoomY
= Fraction( 1, 1 );
2207 long nPixel
= rDoc
.GetNeededSize( nCol
, nRow
, nTab
, aProv
.GetDevice(),
2208 nPPTX
, nPPTY
, aZoomX
, aZoomY
, true );
2209 sal_uInt16 nTwips
= (sal_uInt16
)( nPixel
/ nPPTX
);
2211 nWidth
= nTwips
+ STD_EXTRA_WIDTH
;
2213 nWidth
= STD_COL_WIDTH
;
2216 else // increment / decrement
2218 if ( eDir
== DIR_RIGHT
)
2219 nWidth
= sal::static_int_cast
<sal_uInt16
>( nWidth
+ nStepX
);
2220 else if ( nWidth
> nStepX
)
2221 nWidth
= sal::static_int_cast
<sal_uInt16
>( nWidth
- nStepX
);
2222 if ( nWidth
< nStepX
) nWidth
= nStepX
;
2223 if ( nWidth
> MAX_COL_WIDTH
) nWidth
= MAX_COL_WIDTH
;
2225 aRange
[0].mnStart
= nCol
;
2226 aRange
[0].mnEnd
= nCol
;
2227 SetWidthOrHeight(true, aRange
, SC_SIZE_DIRECT
, nWidth
);
2229 // adjust height of this row if width demands/allows this
2233 const ScPatternAttr
* pPattern
= rDoc
.GetPattern( nCol
, nRow
, nTab
);
2235 static_cast<const SfxBoolItem
&>(pPattern
->GetItem( ATTR_LINEBREAK
)).GetValue() ||
2236 static_cast<const SvxHorJustifyItem
&>(pPattern
->
2237 GetItem( ATTR_HOR_JUSTIFY
)).GetValue() == SVX_HOR_JUSTIFY_BLOCK
;
2239 AdjustRowHeight( nRow
, nRow
);
2247 eMode
= SC_SIZE_OPTIMAL
;
2252 eMode
= SC_SIZE_DIRECT
;
2253 if ( eDir
== DIR_BOTTOM
)
2254 nHeight
= sal::static_int_cast
<sal_uInt16
>( nHeight
+ nStepY
);
2255 else if ( nHeight
> nStepY
)
2256 nHeight
= sal::static_int_cast
<sal_uInt16
>( nHeight
- nStepY
);
2257 if ( nHeight
< nStepY
) nHeight
= nStepY
;
2258 if ( nHeight
> MAX_ROW_HEIGHT
) nHeight
= MAX_ROW_HEIGHT
;
2260 aRange
[0].mnStart
= nRow
;
2261 aRange
[0].mnEnd
= nRow
;
2262 SetWidthOrHeight(false, aRange
, eMode
, nHeight
);
2268 if ( rDoc
.HasAttrib( nCol
, nRow
, nTab
, nCol
, nRow
, nTab
, HASATTR_NEEDHEIGHT
) )
2270 ScInputHandler
* pHdl
= pScMod
->GetInputHdl( GetViewData().GetViewShell() );
2272 pHdl
->SetModified(); // so that the height is adjusted with Enter
2279 void ScViewFunc::ProtectSheet( SCTAB nTab
, const ScTableProtection
& rProtect
)
2281 if (nTab
== TABLEID_DOC
)
2284 ScMarkData
& rMark
= GetViewData().GetMarkData();
2285 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
2286 ScDocument
& rDoc
= pDocSh
->GetDocument();
2287 ScDocFunc
&rFunc
= pDocSh
->GetDocFunc();
2288 bool bUndo(rDoc
.IsUndoEnabled());
2290 // modifying several tabs is handled here
2294 OUString aUndo
= ScGlobal::GetRscString( STR_UNDO_PROTECT_TAB
);
2295 pDocSh
->GetUndoManager()->EnterListAction( aUndo
, aUndo
);
2298 ScMarkData::iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
2299 for (; itr
!= itrEnd
; ++itr
)
2300 rFunc
.ProtectSheet(*itr
, rProtect
);
2303 pDocSh
->GetUndoManager()->LeaveListAction();
2305 UpdateLayerLocks(); //! broadcast to all views
2308 void ScViewFunc::Protect( SCTAB nTab
, const OUString
& rPassword
)
2310 ScMarkData
& rMark
= GetViewData().GetMarkData();
2311 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
2312 ScDocument
& rDoc
= pDocSh
->GetDocument();
2313 ScDocFunc
&rFunc
= pDocSh
->GetDocFunc();
2314 bool bUndo(rDoc
.IsUndoEnabled());
2316 if ( nTab
== TABLEID_DOC
|| rMark
.GetSelectCount() <= 1 )
2317 rFunc
.Protect( nTab
, rPassword
, false );
2320 // modifying several tabs is handled here
2324 OUString aUndo
= ScGlobal::GetRscString( STR_UNDO_PROTECT_TAB
);
2325 pDocSh
->GetUndoManager()->EnterListAction( aUndo
, aUndo
);
2328 ScMarkData::iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
2329 for (; itr
!= itrEnd
; ++itr
)
2330 rFunc
.Protect( *itr
, rPassword
, false );
2333 pDocSh
->GetUndoManager()->LeaveListAction();
2336 UpdateLayerLocks(); //! broadcast to all views
2339 bool ScViewFunc::Unprotect( SCTAB nTab
, const OUString
& rPassword
)
2341 ScMarkData
& rMark
= GetViewData().GetMarkData();
2342 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
2343 ScDocument
& rDoc
= pDocSh
->GetDocument();
2344 ScDocFunc
&rFunc
= pDocSh
->GetDocFunc();
2345 bool bChanged
= false;
2346 bool bUndo (rDoc
.IsUndoEnabled());
2348 if ( nTab
== TABLEID_DOC
|| rMark
.GetSelectCount() <= 1 )
2349 bChanged
= rFunc
.Unprotect( nTab
, rPassword
, false );
2352 // modifying several tabs is handled here
2356 OUString aUndo
= ScGlobal::GetRscString( STR_UNDO_UNPROTECT_TAB
);
2357 pDocSh
->GetUndoManager()->EnterListAction( aUndo
, aUndo
);
2360 ScMarkData::iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
2361 for (; itr
!= itrEnd
; ++itr
)
2362 if ( rFunc
.Unprotect( *itr
, rPassword
, false ) )
2366 pDocSh
->GetUndoManager()->LeaveListAction();
2370 UpdateLayerLocks(); //! broadcast to all views
2375 void ScViewFunc::SetNoteText( const ScAddress
& rPos
, const OUString
& rNoteText
)
2377 GetViewData().GetDocShell()->GetDocFunc().SetNoteText( rPos
, rNoteText
, false );
2380 void ScViewFunc::ReplaceNote( const ScAddress
& rPos
, const OUString
& rNoteText
, const OUString
* pAuthor
, const OUString
* pDate
)
2382 GetViewData().GetDocShell()->GetDocFunc().ReplaceNote( rPos
, rNoteText
, pAuthor
, pDate
, false );
2385 void ScViewFunc::SetNumberFormat( short nFormatType
, sal_uLong nAdd
)
2387 // not editable because of matrix only? attribute OK nonetheless
2388 bool bOnlyNotBecauseOfMatrix
;
2389 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix
) && !bOnlyNotBecauseOfMatrix
)
2391 ErrorMessage(STR_PROTECTIONERR
);
2395 sal_uInt32 nNumberFormat
= 0;
2396 ScViewData
& rViewData
= GetViewData();
2397 ScDocument
* pDoc
= rViewData
.GetDocument();
2398 SvNumberFormatter
* pNumberFormatter
= pDoc
->GetFormatTable();
2399 LanguageType eLanguage
= ScGlobal::eLnge
;
2400 ScPatternAttr
aNewAttrs( pDoc
->GetPool() );
2402 // always take language from cursor position, even if there is a selection
2404 sal_uInt32 nCurrentNumberFormat
;
2405 pDoc
->GetNumberFormat( rViewData
.GetCurX(),
2406 rViewData
.GetCurY(),
2407 rViewData
.GetTabNo(),
2408 nCurrentNumberFormat
);
2409 const SvNumberformat
* pEntry
= pNumberFormatter
->GetEntry( nCurrentNumberFormat
);
2411 eLanguage
= pEntry
->GetLanguage(); // else keep ScGlobal::eLnge
2413 nNumberFormat
= pNumberFormatter
->GetStandardFormat( nFormatType
, eLanguage
) + nAdd
;
2415 SfxItemSet
& rSet
= aNewAttrs
.GetItemSet();
2416 rSet
.Put( SfxUInt32Item( ATTR_VALUE_FORMAT
, nNumberFormat
) );
2417 // ATTR_LANGUAGE_FORMAT not
2418 ApplySelectionPattern( aNewAttrs
);
2421 void ScViewFunc::SetNumFmtByStr( const OUString
& rCode
)
2423 // not editable because of matrix only? attribute OK nonetheless
2424 bool bOnlyNotBecauseOfMatrix
;
2425 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix
) && !bOnlyNotBecauseOfMatrix
)
2427 ErrorMessage(STR_PROTECTIONERR
);
2431 ScViewData
& rViewData
= GetViewData();
2432 ScDocument
* pDoc
= rViewData
.GetDocument();
2433 SvNumberFormatter
* pFormatter
= pDoc
->GetFormatTable();
2435 // language always from cursor position
2437 sal_uInt32 nCurrentNumberFormat
;
2438 pDoc
->GetNumberFormat( rViewData
.GetCurX(), rViewData
.GetCurY(),
2439 rViewData
.GetTabNo(), nCurrentNumberFormat
);
2440 const SvNumberformat
* pEntry
= pFormatter
->GetEntry( nCurrentNumberFormat
);
2441 LanguageType eLanguage
= pEntry
? pEntry
->GetLanguage() : ScGlobal::eLnge
;
2443 // determine index for String
2446 sal_uInt32 nNumberFormat
= pFormatter
->GetEntryKey( rCode
, eLanguage
);
2447 if ( nNumberFormat
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
2451 OUString aFormat
= rCode
; // will be changed
2452 sal_Int32 nErrPos
= 0;
2453 short nType
= 0; //! ???
2454 bOk
= pFormatter
->PutEntry( aFormat
, nErrPos
, nType
, nNumberFormat
, eLanguage
);
2457 if ( bOk
) // valid format?
2459 ScPatternAttr
aNewAttrs( pDoc
->GetPool() );
2460 SfxItemSet
& rSet
= aNewAttrs
.GetItemSet();
2461 rSet
.Put( SfxUInt32Item( ATTR_VALUE_FORMAT
, nNumberFormat
) );
2462 rSet
.Put( SvxLanguageItem( eLanguage
, ATTR_LANGUAGE_FORMAT
) );
2463 ApplySelectionPattern( aNewAttrs
);
2466 //! else return error / issue warning ???
2469 void ScViewFunc::ChangeNumFmtDecimals( bool bIncrement
)
2471 // not editable because of matrix only? attribute OK nonetheless
2472 bool bOnlyNotBecauseOfMatrix
;
2473 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix
) && !bOnlyNotBecauseOfMatrix
)
2475 ErrorMessage(STR_PROTECTIONERR
);
2479 ScDocument
* pDoc
= GetViewData().GetDocument();
2480 SvNumberFormatter
* pFormatter
= pDoc
->GetFormatTable();
2482 SCCOL nCol
= GetViewData().GetCurX();
2483 SCROW nRow
= GetViewData().GetCurY();
2484 SCTAB nTab
= GetViewData().GetTabNo();
2486 sal_uInt32 nOldFormat
;
2487 pDoc
->GetNumberFormat( nCol
, nRow
, nTab
, nOldFormat
);
2488 const SvNumberformat
* pOldEntry
= pFormatter
->GetEntry( nOldFormat
);
2491 OSL_FAIL("numberformat not found !!!");
2495 // what have we got here?
2497 sal_uInt32 nNewFormat
= nOldFormat
;
2498 bool bError
= false;
2500 LanguageType eLanguage
= pOldEntry
->GetLanguage();
2501 bool bThousand
, bNegRed
;
2502 sal_uInt16 nPrecision
, nLeading
;
2503 pOldEntry
->GetFormatSpecialInfo( bThousand
, bNegRed
, nPrecision
, nLeading
);
2505 short nOldType
= pOldEntry
->GetType();
2506 if ( 0 == ( nOldType
& (
2507 css::util::NumberFormat::NUMBER
| css::util::NumberFormat::CURRENCY
| css::util::NumberFormat::PERCENT
| css::util::NumberFormat::SCIENTIFIC
) ) )
2509 // date, time, fraction, logical, text can not be changed
2513 //! SvNumberformat has a Member bStandard, but doesn't disclose it
2514 bool bWasStandard
= ( nOldFormat
== pFormatter
->GetStandardIndex( eLanguage
) );
2515 OUString sExponentialStandardFormat
= "";
2518 // with "Standard" the decimal places depend on cell content
2519 // 0 if empty or text -> no decimal places
2520 double nVal
= pDoc
->GetValue( ScAddress( nCol
, nRow
, nTab
) );
2522 // the ways of the Numberformatters are unfathomable, so try:
2525 const_cast<SvNumberformat
*>(pOldEntry
)->GetOutputString( nVal
, aOut
, &pCol
);
2528 // 'E' for exponential is fixed in Numberformatter
2529 sal_Int32 nIndexE
= aOut
.indexOf((sal_Unicode
)'E');
2532 sExponentialStandardFormat
= aOut
.copy( nIndexE
).replace( '-', '+' );
2533 for ( sal_Int32 i
=1 ; i
<sExponentialStandardFormat
.getLength() ; i
++ )
2535 if ( sExponentialStandardFormat
[i
] >= '1' && sExponentialStandardFormat
[i
] <= '9' )
2536 sExponentialStandardFormat
= sExponentialStandardFormat
.replaceAt( i
, 1, "0" );
2538 aOut
= aOut
.copy( 0, nIndexE
); // remove exponential part
2540 OUString
aDecSep( pFormatter
->GetFormatDecimalSep( nOldFormat
) );
2541 sal_Int32 nPos
= aOut
.indexOf( aDecSep
);
2543 nPrecision
= aOut
.getLength() - nPos
- aDecSep
.getLength();
2548 if ( (nOldType
& css::util::NumberFormat::SCIENTIFIC
) && !bThousand
&&
2549 (pOldEntry
->GetFormatIntegerDigits()%3 == 0) && pOldEntry
->GetFormatIntegerDigits() > 0 )
2558 ++nPrecision
; // increment
2560 bError
= true; // 20 is maximum
2565 --nPrecision
; // decrement
2567 bError
= true; // 0 is minimum
2573 OUString aNewPicture
= pFormatter
->GenerateFormat(nOldFormat
, eLanguage
,
2575 nPrecision
, nLeading
)
2576 + sExponentialStandardFormat
;
2578 nNewFormat
= pFormatter
->GetEntryKey( aNewPicture
, eLanguage
);
2579 if ( nNewFormat
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
2581 sal_Int32 nErrPos
= 0;
2583 bool bOk
= pFormatter
->PutEntry( aNewPicture
, nErrPos
,
2584 nNewType
, nNewFormat
, eLanguage
);
2585 OSL_ENSURE( bOk
, "incorrect numberformat generated" );
2593 ScPatternAttr
aNewAttrs( pDoc
->GetPool() );
2594 SfxItemSet
& rSet
= aNewAttrs
.GetItemSet();
2595 rSet
.Put( SfxUInt32Item( ATTR_VALUE_FORMAT
, nNewFormat
) );
2596 // ATTR_LANGUAGE_FORMAT not
2597 ApplySelectionPattern( aNewAttrs
);
2601 void ScViewFunc::ChangeIndent( bool bIncrement
)
2603 ScViewData
& rViewData
= GetViewData();
2604 ScDocShell
* pDocSh
= rViewData
.GetDocShell();
2605 ScMarkData
& rMark
= rViewData
.GetMarkData();
2607 ScMarkData aWorkMark
= rMark
;
2608 ScViewUtil::UnmarkFiltered( aWorkMark
, &pDocSh
->GetDocument() );
2609 aWorkMark
.MarkToMulti();
2610 if (!aWorkMark
.IsMultiMarked())
2612 SCCOL nCol
= rViewData
.GetCurX();
2613 SCROW nRow
= rViewData
.GetCurY();
2614 SCTAB nTab
= rViewData
.GetTabNo();
2615 aWorkMark
.SetMultiMarkArea( ScRange(nCol
,nRow
,nTab
) );
2618 bool bSuccess
= pDocSh
->GetDocFunc().ChangeIndent( aWorkMark
, bIncrement
, false );
2621 pDocSh
->UpdateOle(&rViewData
);
2624 // stuff for sidebar panels
2625 SfxBindings
& rBindings
= GetViewData().GetBindings();
2626 rBindings
.Invalidate( SID_H_ALIGNCELL
);
2627 rBindings
.Invalidate( SID_ATTR_ALIGN_INDENT
);
2631 bool ScViewFunc::InsertName( const OUString
& rName
, const OUString
& rSymbol
,
2632 const OUString
& rType
)
2634 // Type = P,R,C,F (and combinations)
2638 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
2639 ScDocument
& rDoc
= pDocSh
->GetDocument();
2640 SCTAB nTab
= GetViewData().GetTabNo();
2641 ScRangeName
* pList
= rDoc
.GetRangeName();
2643 ScRangeData::Type nType
= ScRangeData::Type::Name
;
2644 ScRangeData
* pNewEntry
= new ScRangeData( &rDoc
, rName
, rSymbol
,
2645 ScAddress( GetViewData().GetCurX(), GetViewData().GetCurY(),
2647 OUString aUpType
= rType
.toAsciiUpperCase();
2648 if ( aUpType
.indexOf( 'P' ) != -1 )
2649 nType
|= ScRangeData::Type::PrintArea
;
2650 if ( aUpType
.indexOf( 'R' ) != -1 )
2651 nType
|= ScRangeData::Type::RowHeader
;
2652 if ( aUpType
.indexOf( 'C' ) != -1 )
2653 nType
|= ScRangeData::Type::ColHeader
;
2654 if ( aUpType
.indexOf( 'F' ) != -1 )
2655 nType
|= ScRangeData::Type::Criteria
;
2656 pNewEntry
->AddType(nType
);
2658 if ( !pNewEntry
->GetErrCode() ) // text valid?
2660 ScDocShellModificator
aModificator( *pDocSh
);
2662 rDoc
.PreprocessRangeNameUpdate();
2664 // input available yet? Then remove beforehand (=change)
2665 ScRangeData
* pData
= pList
->findByUpperName(ScGlobal::pCharClass
->uppercase(rName
));
2668 pNewEntry
->SetIndex(pData
->GetIndex());
2669 pList
->erase(*pData
);
2672 if ( pList
->insert( pNewEntry
) )
2674 pNewEntry
= nullptr; // never delete, insert took ownership
2676 rDoc
.CompileHybridFormula();
2678 aModificator
.SetDocumentModified();
2679 SfxGetpApp()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED
) );
2682 delete pNewEntry
; // if it wasn't inserted
2686 void ScViewFunc::CreateNames( sal_uInt16 nFlags
)
2690 if ( GetViewData().GetSimpleArea(aRange
) == SC_MARK_SIMPLE
)
2691 bDone
= GetViewData().GetDocShell()->GetDocFunc().CreateNames( aRange
, nFlags
, false );
2694 ErrorMessage(STR_CREATENAME_MARKERR
);
2697 sal_uInt16
ScViewFunc::GetCreateNameFlags()
2699 sal_uInt16 nFlags
= 0;
2701 SCCOL nStartCol
, nEndCol
;
2702 SCROW nStartRow
, nEndRow
;
2704 if (GetViewData().GetSimpleArea(nStartCol
,nStartRow
,nDummy
,nEndCol
,nEndRow
,nDummy
) == SC_MARK_SIMPLE
)
2706 ScDocument
* pDoc
= GetViewData().GetDocument();
2707 SCTAB nTab
= GetViewData().GetTabNo();
2713 SCCOL nFirstCol
= nStartCol
;
2714 SCCOL nLastCol
= nEndCol
;
2715 if (nStartCol
+1 < nEndCol
) { ++nFirstCol
; --nLastCol
; }
2716 for (i
=nFirstCol
; i
<=nLastCol
&& bOk
; i
++)
2717 if (!pDoc
->HasStringData( i
,nStartRow
,nTab
))
2721 else // Bottom only if not Top
2724 for (i
=nFirstCol
; i
<=nLastCol
&& bOk
; i
++)
2725 if (!pDoc
->HasStringData( i
,nEndRow
,nTab
))
2728 nFlags
|= NAME_BOTTOM
;
2732 SCROW nFirstRow
= nStartRow
;
2733 SCROW nLastRow
= nEndRow
;
2734 if (nStartRow
+1 < nEndRow
) { ++nFirstRow
; --nLastRow
; }
2735 for (j
=nFirstRow
; j
<=nLastRow
&& bOk
; j
++)
2736 if (!pDoc
->HasStringData( nStartCol
,j
,nTab
))
2739 nFlags
|= NAME_LEFT
;
2740 else // Right only if not Left
2743 for (j
=nFirstRow
; j
<=nLastRow
&& bOk
; j
++)
2744 if (!pDoc
->HasStringData( nEndCol
,j
,nTab
))
2747 nFlags
|= NAME_RIGHT
;
2751 if (nStartCol
== nEndCol
)
2752 nFlags
&= ~( NAME_LEFT
| NAME_RIGHT
);
2753 if (nStartRow
== nEndRow
)
2754 nFlags
&= ~( NAME_TOP
| NAME_BOTTOM
);
2759 void ScViewFunc::InsertNameList()
2761 ScAddress
aPos( GetViewData().GetCurX(), GetViewData().GetCurY(), GetViewData().GetTabNo() );
2762 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
2763 if ( pDocSh
->GetDocFunc().InsertNameList( aPos
, false ) )
2764 pDocSh
->UpdateOle(&GetViewData());
2767 void ScViewFunc::UpdateSelectionArea( const ScMarkData
& rSel
, ScPatternAttr
* pAttr
)
2769 ScDocShell
* pDocShell
= GetViewData().GetDocShell();
2771 if (rSel
.IsMultiMarked() )
2772 rSel
.GetMultiMarkArea( aMarkRange
);
2774 rSel
.GetMarkArea( aMarkRange
);
2776 bool bSetLines
= false;
2777 bool bSetAlign
= false;
2780 const SfxItemSet
& rNewSet
= pAttr
->GetItemSet();
2781 bSetLines
= rNewSet
.GetItemState( ATTR_BORDER
) == SfxItemState::SET
||
2782 rNewSet
.GetItemState( ATTR_SHADOW
) == SfxItemState::SET
;
2783 bSetAlign
= rNewSet
.GetItemState( ATTR_HOR_JUSTIFY
) == SfxItemState::SET
;
2786 sal_uInt16 nExtFlags
= 0;
2788 nExtFlags
|= SC_PF_LINES
;
2790 nExtFlags
|= SC_PF_WHOLEROWS
;
2792 SCCOL nStartCol
= aMarkRange
.aStart
.Col();
2793 SCROW nStartRow
= aMarkRange
.aStart
.Row();
2794 SCTAB nStartTab
= aMarkRange
.aStart
.Tab();
2795 SCCOL nEndCol
= aMarkRange
.aEnd
.Col();
2796 SCROW nEndRow
= aMarkRange
.aEnd
.Row();
2797 SCTAB nEndTab
= aMarkRange
.aEnd
.Tab();
2798 pDocShell
->PostPaint( nStartCol
, nStartRow
, nStartTab
,
2799 nEndCol
, nEndRow
, nEndTab
,
2800 PAINT_GRID
, nExtFlags
| SC_PF_TESTMERGE
);
2801 ScTabViewShell
* pTabViewShell
= GetViewData().GetViewShell();
2802 pTabViewShell
->AdjustBlockHeight(false, const_cast<ScMarkData
*>(&rSel
));
2805 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */