LibreOffice Module sc (master)  1
cellsuno.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <scitems.hxx>
21 #include <editeng/eeitem.hxx>
22 #include <o3tl/safeint.hxx>
23 #include <svx/svdpool.hxx>
24 
25 #include <vcl/svapp.hxx>
26 #include <svx/algitem.hxx>
27 #include <editeng/borderline.hxx>
28 #include <editeng/boxitem.hxx>
29 #include <editeng/editeng.hxx>
30 #include <editeng/flditem.hxx>
31 #include <editeng/editobj.hxx>
32 #include <editeng/unoipset.hxx>
33 #include <editeng/langitem.hxx>
34 #include <sfx2/linkmgr.hxx>
35 #include <svl/srchitem.hxx>
36 #include <svl/sharedstringpool.hxx>
37 #include <svx/unomid.hxx>
38 #include <editeng/unoprnms.hxx>
39 #include <editeng/unotext.hxx>
40 #include <svx/svdpage.hxx>
41 #include <sfx2/bindings.hxx>
42 #include <svl/zforlist.hxx>
43 #include <svl/zformat.hxx>
45 #include <float.h>
46 #include <tools/diagnose_ex.h>
47 
48 #include <com/sun/star/awt/XBitmap.hpp>
49 #include <com/sun/star/util/CellProtection.hpp>
50 #include <com/sun/star/table/CellHoriJustify.hpp>
51 #include <com/sun/star/table/CellOrientation.hpp>
52 #include <com/sun/star/table/ShadowFormat.hpp>
53 #include <com/sun/star/table/TableBorder.hpp>
54 #include <com/sun/star/table/TableBorder2.hpp>
55 #include <com/sun/star/sheet/CellFlags.hpp>
56 #include <com/sun/star/sheet/FormulaResult.hpp>
57 #include <com/sun/star/beans/PropertyAttribute.hpp>
58 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
59 #include <com/sun/star/lang/Locale.hpp>
60 #include <com/sun/star/beans/TolerantPropertySetResultType.hpp>
61 #include <com/sun/star/beans/SetPropertyTolerantFailed.hpp>
62 #include <com/sun/star/text/WritingMode2.hpp>
63 #include <com/sun/star/text/textfield/Type.hpp>
64 #include <com/sun/star/sheet/XConditionalFormats.hpp>
65 
66 #include <autoform.hxx>
67 #include <cellvalue.hxx>
68 #include <cellmergeoption.hxx>
69 #include <cellsuno.hxx>
70 #include <cursuno.hxx>
71 #include <textuno.hxx>
72 #include <editsrc.hxx>
73 #include <notesuno.hxx>
74 #include <fielduno.hxx>
75 #include <docuno.hxx>
76 #include <datauno.hxx>
77 #include <dapiuno.hxx>
78 #include <chartuno.hxx>
79 #include <fmtuno.hxx>
80 #include <miscuno.hxx>
81 #include <convuno.hxx>
82 #include <srchuno.hxx>
83 #include <nameuno.hxx>
84 #include <targuno.hxx>
85 #include <tokenuno.hxx>
86 #include <eventuno.hxx>
87 #include <docsh.hxx>
88 #include <markdata.hxx>
89 #include <patattr.hxx>
90 #include <docpool.hxx>
91 #include <docfunc.hxx>
92 #include <dbdocfun.hxx>
93 #include <olinefun.hxx>
94 #include <hints.hxx>
95 #include <formulacell.hxx>
96 #include <undotab.hxx>
97 #include <undoblk.hxx>
98 #include <stlsheet.hxx>
99 #include <dbdata.hxx>
100 #include <attrib.hxx>
101 #include <chartarr.hxx>
102 #include <chartlis.hxx>
103 #include <drwlayer.hxx>
104 #include <printfun.hxx>
105 #include <prnsave.hxx>
106 #include <tablink.hxx>
107 #include <dociter.hxx>
108 #include <rangeutl.hxx>
109 #include <conditio.hxx>
110 #include <validat.hxx>
111 #include <sc.hrc>
112 #include <cellform.hxx>
113 #include <globstr.hrc>
114 #include <scresid.hxx>
115 #include <unonames.hxx>
116 #include <styleuno.hxx>
117 #include <rangeseq.hxx>
118 #include <unowids.hxx>
119 #include <paramisc.hxx>
120 #include <queryentry.hxx>
121 #include <formula/errorcodes.hxx>
122 #include <unoreflist.hxx>
123 #include <formula/grammar.hxx>
125 #include <stringutil.hxx>
126 #include <formulaiter.hxx>
127 #include <tokenarray.hxx>
128 #include <stylehelper.hxx>
129 #include <dputil.hxx>
130 #include <sortparam.hxx>
131 #include <condformatuno.hxx>
132 #include <TablePivotCharts.hxx>
133 #include <table.hxx>
134 #include <refundo.hxx>
135 #include <columnspanset.hxx>
136 
137 #include <memory>
138 
139 using namespace com::sun::star;
140 
141 namespace {
142 
143 class ScNamedEntry
144 {
145  OUString aName;
146  ScRange aRange;
147 
148 public:
149  ScNamedEntry(const OUString& rN, const ScRange& rR) :
150  aName(rN), aRange(rR) {}
151 
152  const OUString& GetName() const { return aName; }
153  const ScRange& GetRange() const { return aRange; }
154 };
155 
156 }
157 
158 // The names in the maps must be sorted according to strcmp!
160 
161 // Left/Right/Top/BottomBorder are mapped directly to the core items,
162 // not collected/applied to the borders of a range -> ATTR_BORDER can be used directly
163 
165 {
166  static const SfxItemPropertyMapEntry aCellsPropertyMap_Impl[] =
167  {
168  {u"" SC_UNONAME_ABSNAME, SC_WID_UNO_ABSNAME, cppu::UnoType<OUString>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
265  { u"", 0, css::uno::Type(), 0, 0 }
266  };
267  static SfxItemPropertySet aCellsPropertySet( aCellsPropertyMap_Impl );
268  return &aCellsPropertySet;
269 }
270 
271 // CellRange contains all entries from Cells, plus its own entries
272 // with Which-ID 0 (those are needed only for getPropertySetInfo).
273 
275 {
276  static const SfxItemPropertyMapEntry aRangePropertyMap_Impl[] =
277  {
278  {u"" SC_UNONAME_ABSNAME, SC_WID_UNO_ABSNAME, cppu::UnoType<OUString>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
356  {u"" SC_UNONAME_POS, SC_WID_UNO_POS, cppu::UnoType<awt::Point>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
363  {u"" SC_UNONAME_SIZE, SC_WID_UNO_SIZE, cppu::UnoType<awt::Size>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
376  { u"", 0, css::uno::Type(), 0, 0 }
377  };
378  static SfxItemPropertySet aRangePropertySet( aRangePropertyMap_Impl );
379  return &aRangePropertySet;
380 }
381 
382 // Cell contains entries from CellRange, plus its own entries
383 // with Which-ID 0 (those are needed only for getPropertySetInfo).
384 
386 {
387  static const SfxItemPropertyMapEntry aCellPropertyMap_Impl[] =
388  {
389  {u"" SC_UNONAME_ABSNAME, SC_WID_UNO_ABSNAME, cppu::UnoType<OUString>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
448  {u"" SC_UNONAME_FORMRT, SC_WID_UNO_FORMRT, cppu::UnoType<table::CellContentType>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
450  {u"" SC_UNONAME_FORMRT2, SC_WID_UNO_FORMRT2, cppu::UnoType<sal_Int32>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
471  {u"" SC_UNONAME_POS, SC_WID_UNO_POS, cppu::UnoType<awt::Point>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
478  {u"" SC_UNONAME_SIZE, SC_WID_UNO_SIZE, cppu::UnoType<awt::Size>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
493  { u"", 0, css::uno::Type(), 0, 0 }
494  };
495  static SfxItemPropertySet aCellPropertySet( aCellPropertyMap_Impl );
496  return &aCellPropertySet;
497 }
498 
499 // Column and Row contain all entries from CellRange, plus its own entries
500 // with Which-ID 0 (those are needed only for getPropertySetInfo).
501 
503 {
504  static const SfxItemPropertyMapEntry aColumnPropertyMap_Impl[] =
505  {
506  {u"" SC_UNONAME_ABSNAME, SC_WID_UNO_ABSNAME, cppu::UnoType<OUString>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
588  {u"" SC_UNONAME_POS, SC_WID_UNO_POS, cppu::UnoType<awt::Point>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
595  {u"" SC_UNONAME_SIZE, SC_WID_UNO_SIZE, cppu::UnoType<awt::Size>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
608  { u"", 0, css::uno::Type(), 0, 0 }
609  };
610  static SfxItemPropertySet aColumnPropertySet( aColumnPropertyMap_Impl );
611  return &aColumnPropertySet;
612 }
613 
615 {
616  static const SfxItemPropertyMapEntry aRowPropertyMap_Impl[] =
617  {
618  {u"" SC_UNONAME_ABSNAME, SC_WID_UNO_ABSNAME, cppu::UnoType<OUString>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
702  {u"" SC_UNONAME_POS, SC_WID_UNO_POS, cppu::UnoType<awt::Point>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
709  {u"" SC_UNONAME_SIZE, SC_WID_UNO_SIZE, cppu::UnoType<awt::Size>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
721  { u"", 0, css::uno::Type(), 0, 0 }
722  };
723  static SfxItemPropertySet aRowPropertySet( aRowPropertyMap_Impl );
724  return &aRowPropertySet;
725 }
726 
728 {
729  static const SfxItemPropertyMapEntry aSheetPropertyMap_Impl[] =
730  {
731  {u"" SC_UNONAME_ABSNAME, SC_WID_UNO_ABSNAME, cppu::UnoType<OUString>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
802  {u"" SC_UNO_LINKDISPBIT, SC_WID_UNO_LINKDISPBIT,cppu::UnoType<awt::XBitmap>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
803  {u"" SC_UNO_LINKDISPNAME, SC_WID_UNO_LINKDISPNAME,cppu::UnoType<OUString>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
819  {u"" SC_UNONAME_POS, SC_WID_UNO_POS, cppu::UnoType<awt::Point>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
829  {u"" SC_UNONAME_SIZE, SC_WID_UNO_SIZE, cppu::UnoType<awt::Size>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
846  { u"", 0, css::uno::Type(), 0, 0 }
847  };
848  static SfxItemPropertySet aSheetPropertySet( aSheetPropertyMap_Impl );
849  return &aSheetPropertySet;
850 }
851 
853 {
854  static const SfxItemPropertyMapEntry aEditPropertyMap_Impl[] =
855  {
859  SVX_UNOEDIT_NUMBERING_PROPERTIE, // for completeness of service ParagraphProperties
862  { u"", 0, css::uno::Type(), 0, 0 }
863  };
864  return aEditPropertyMap_Impl;
865 }
867 {
869  return &aEditPropertySet;
870 }
871 
872 using sc::HMMToTwips;
873 using sc::TwipsToHMM;
874 
875 #define SCCHARPROPERTIES_SERVICE "com.sun.star.style.CharacterProperties"
876 #define SCPARAPROPERTIES_SERVICE "com.sun.star.style.ParagraphProperties"
877 #define SCCELLPROPERTIES_SERVICE "com.sun.star.table.CellProperties"
878 #define SCCELLRANGE_SERVICE "com.sun.star.table.CellRange"
879 #define SCCELL_SERVICE "com.sun.star.table.Cell"
880 #define SCSHEETCELLRANGES_SERVICE "com.sun.star.sheet.SheetCellRanges"
881 #define SCSHEETCELLRANGE_SERVICE "com.sun.star.sheet.SheetCellRange"
882 #define SCSPREADSHEET_SERVICE "com.sun.star.sheet.Spreadsheet"
883 #define SCSHEETCELL_SERVICE "com.sun.star.sheet.SheetCell"
884 
885 SC_SIMPLE_SERVICE_INFO( ScCellFormatsEnumeration, "ScCellFormatsEnumeration", "com.sun.star.sheet.CellFormatRangesEnumeration" )
886 SC_SIMPLE_SERVICE_INFO( ScCellFormatsObj, "ScCellFormatsObj", "com.sun.star.sheet.CellFormatRanges" )
887 SC_SIMPLE_SERVICE_INFO( ScUniqueCellFormatsEnumeration, "ScUniqueCellFormatsEnumeration", "com.sun.star.sheet.UniqueCellFormatRangesEnumeration" )
888 SC_SIMPLE_SERVICE_INFO( ScUniqueCellFormatsObj, "ScUniqueCellFormatsObj", "com.sun.star.sheet.UniqueCellFormatRanges" )
889 SC_SIMPLE_SERVICE_INFO( ScCellRangesBase, "ScCellRangesBase", "stardiv.unknown" )
890 SC_SIMPLE_SERVICE_INFO( ScCellsEnumeration, "ScCellsEnumeration", "com.sun.star.sheet.CellsEnumeration" )
891 SC_SIMPLE_SERVICE_INFO( ScCellsObj, "ScCellsObj", "com.sun.star.sheet.Cells" )
892 SC_SIMPLE_SERVICE_INFO( ScTableColumnObj, "ScTableColumnObj", "com.sun.star.table.TableColumn" )
893 SC_SIMPLE_SERVICE_INFO( ScTableRowObj, "ScTableRowObj", "com.sun.star.table.TableRow" )
894 
896 
898 {
899 }
900 
901 void ScLinkListener::Notify( const SfxHint& rHint )
902 {
903  aLink.Call( rHint );
904 }
905 
907 {
908  uno::Reference<beans::XPropertySetInfo> xInfo(rSource.getPropertySetInfo());
909  if (xInfo.is())
910  {
911  const uno::Sequence<beans::Property> aSeq(xInfo->getProperties());
912  for (const beans::Property& rProp : aSeq)
913  {
914  OUString aName(rProp.Name);
915  rDest.setPropertyValue( aName, rSource.getPropertyValue( aName ) );
916  }
917  }
918 }
919 
920 static SCTAB lcl_FirstTab( const ScRangeList& rRanges )
921 {
922  if (rRanges.empty())
923  throw std::out_of_range("empty range");
924  const ScRange & rFirst = rRanges[0];
925  return rFirst.aStart.Tab();
926 }
927 
928 static bool lcl_WholeSheet( const ScDocument& rDoc, const ScRangeList& rRanges )
929 {
930  if ( rRanges.size() == 1 )
931  {
932  const ScRange & rRange = rRanges[0];
933  if ( rRange.aStart.Col() == 0 && rRange.aEnd.Col() == rDoc.MaxCol() &&
934  rRange.aStart.Row() == 0 && rRange.aEnd.Row() == rDoc.MaxRow() )
935  return true;
936  }
937  return false;
938 }
939 
940 namespace {
941 template<typename BorderLineType>
942 const ::editeng::SvxBorderLine* lcl_getBorderLine(
943  ::editeng::SvxBorderLine& rLine, const BorderLineType& rStruct )
944 {
945  // Convert from 1/100mm to Twips.
946  if (!SvxBoxItem::LineToSvxLine( rStruct, rLine, true))
947  return nullptr;
948 
949  if ( rLine.GetOutWidth() || rLine.GetInWidth() || rLine.GetDistance() )
950  return &rLine;
951  else
952  return nullptr;
953 }
954 }
955 
956 const ::editeng::SvxBorderLine* ScHelperFunctions::GetBorderLine(
957  ::editeng::SvxBorderLine& rLine, const table::BorderLine& rStruct )
958 {
959  return lcl_getBorderLine( rLine, rStruct);
960 }
961 
962 const ::editeng::SvxBorderLine* ScHelperFunctions::GetBorderLine(
963  ::editeng::SvxBorderLine& rLine, const table::BorderLine2& rStruct )
964 {
965  return lcl_getBorderLine( rLine, rStruct);
966 }
967 
968 namespace {
969 template<typename TableBorderType>
970 void lcl_fillBoxItems( SvxBoxItem& rOuter, SvxBoxInfoItem& rInner, const TableBorderType& rBorder )
971 {
973  rOuter.SetAllDistances(static_cast<sal_uInt16>(HMMToTwips(rBorder.Distance)));
974  rOuter.SetLine( ScHelperFunctions::GetBorderLine( aLine, rBorder.TopLine ), SvxBoxItemLine::TOP );
975  rOuter.SetLine( ScHelperFunctions::GetBorderLine( aLine, rBorder.BottomLine ), SvxBoxItemLine::BOTTOM );
976  rOuter.SetLine( ScHelperFunctions::GetBorderLine( aLine, rBorder.LeftLine ), SvxBoxItemLine::LEFT );
977  rOuter.SetLine( ScHelperFunctions::GetBorderLine( aLine, rBorder.RightLine ), SvxBoxItemLine::RIGHT );
978  rInner.SetLine( ScHelperFunctions::GetBorderLine( aLine, rBorder.HorizontalLine ), SvxBoxInfoItemLine::HORI );
979  rInner.SetLine( ScHelperFunctions::GetBorderLine( aLine, rBorder.VerticalLine ), SvxBoxInfoItemLine::VERT );
980  rInner.SetValid( SvxBoxInfoItemValidFlags::TOP, rBorder.IsTopLineValid );
981  rInner.SetValid( SvxBoxInfoItemValidFlags::BOTTOM, rBorder.IsBottomLineValid );
982  rInner.SetValid( SvxBoxInfoItemValidFlags::LEFT, rBorder.IsLeftLineValid );
983  rInner.SetValid( SvxBoxInfoItemValidFlags::RIGHT, rBorder.IsRightLineValid );
984  rInner.SetValid( SvxBoxInfoItemValidFlags::HORI, rBorder.IsHorizontalLineValid );
985  rInner.SetValid( SvxBoxInfoItemValidFlags::VERT, rBorder.IsVerticalLineValid );
986  rInner.SetValid( SvxBoxInfoItemValidFlags::DISTANCE, rBorder.IsDistanceValid );
987  rInner.SetTable( true );
988 }
989 }
990 
991 void ScHelperFunctions::FillBoxItems( SvxBoxItem& rOuter, SvxBoxInfoItem& rInner, const table::TableBorder& rBorder )
992 {
993  lcl_fillBoxItems( rOuter, rInner, rBorder);
994 }
995 
996 void ScHelperFunctions::FillBoxItems( SvxBoxItem& rOuter, SvxBoxInfoItem& rInner, const table::TableBorder2& rBorder )
997 {
998  lcl_fillBoxItems( rOuter, rInner, rBorder);
999 }
1000 
1001 void ScHelperFunctions::FillBorderLine( table::BorderLine& rStruct, const ::editeng::SvxBorderLine* pLine )
1002 {
1003  // Convert from Twips to 1/100mm.
1004  table::BorderLine2 aStruct( SvxBoxItem::SvxLineToLine( pLine, true));
1005  rStruct = aStruct;
1006 }
1007 
1008 void ScHelperFunctions::FillBorderLine( table::BorderLine2& rStruct, const ::editeng::SvxBorderLine* pLine )
1009 {
1010  rStruct = SvxBoxItem::SvxLineToLine( pLine, true);
1011 }
1012 
1013 namespace {
1014 template<typename TableBorderItem>
1015 void lcl_fillTableBorder( TableBorderItem& rBorder, const SvxBoxItem& rOuter, const SvxBoxInfoItem& rInner,
1016  bool bInvalidateHorVerDist )
1017 {
1018  ScHelperFunctions::FillBorderLine( rBorder.TopLine, rOuter.GetTop() );
1019  ScHelperFunctions::FillBorderLine( rBorder.BottomLine, rOuter.GetBottom() );
1020  ScHelperFunctions::FillBorderLine( rBorder.LeftLine, rOuter.GetLeft() );
1021  ScHelperFunctions::FillBorderLine( rBorder.RightLine, rOuter.GetRight() );
1022  ScHelperFunctions::FillBorderLine( rBorder.HorizontalLine, rInner.GetHori() );
1023  ScHelperFunctions::FillBorderLine( rBorder.VerticalLine, rInner.GetVert() );
1024 
1025  rBorder.Distance = rOuter.GetSmallestDistance();
1026  rBorder.IsTopLineValid = rInner.IsValid(SvxBoxInfoItemValidFlags::TOP);
1027  rBorder.IsBottomLineValid = rInner.IsValid(SvxBoxInfoItemValidFlags::BOTTOM);
1028  rBorder.IsLeftLineValid = rInner.IsValid(SvxBoxInfoItemValidFlags::LEFT);
1029  rBorder.IsRightLineValid = rInner.IsValid(SvxBoxInfoItemValidFlags::RIGHT);
1030  rBorder.IsHorizontalLineValid = !bInvalidateHorVerDist && rInner.IsValid(SvxBoxInfoItemValidFlags::HORI);
1031  rBorder.IsVerticalLineValid = !bInvalidateHorVerDist && rInner.IsValid(SvxBoxInfoItemValidFlags::VERT);
1032  rBorder.IsDistanceValid = !bInvalidateHorVerDist && rInner.IsValid(SvxBoxInfoItemValidFlags::DISTANCE);
1033 }
1034 }
1035 
1037  const SvxBoxItem& rOuter, const SvxBoxInfoItem& rInner, bool bInvalidateHorVerDist )
1038 {
1039  table::TableBorder aBorder;
1040  lcl_fillTableBorder( aBorder, rOuter, rInner, bInvalidateHorVerDist);
1041  rAny <<= aBorder;
1042 }
1043 
1045  const SvxBoxItem& rOuter, const SvxBoxInfoItem& rInner, bool bInvalidateHorVerDist )
1046 {
1047  table::TableBorder2 aBorder;
1048  lcl_fillTableBorder( aBorder, rOuter, rInner, bInvalidateHorVerDist);
1049  rAny <<= aBorder;
1050 }
1051 
1053 
1054 void ScHelperFunctions::ApplyBorder( ScDocShell* pDocShell, const ScRangeList& rRanges,
1055  const SvxBoxItem& rOuter, const SvxBoxInfoItem& rInner )
1056 {
1057  ScDocument& rDoc = pDocShell->GetDocument();
1058  bool bUndo(rDoc.IsUndoEnabled());
1059  ScDocumentUniquePtr pUndoDoc;
1060  if (bUndo)
1061  pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
1062  size_t nCount = rRanges.size();
1063  for (size_t i = 0; i < nCount; ++i)
1064  {
1065  ScRange const & rRange = rRanges[ i ];
1066  SCTAB nTab = rRange.aStart.Tab();
1067 
1068  if (bUndo)
1069  {
1070  if ( i==0 )
1071  pUndoDoc->InitUndo( rDoc, nTab, nTab );
1072  else
1073  pUndoDoc->AddUndoTab( nTab, nTab );
1074  rDoc.CopyToDocument(rRange, InsertDeleteFlags::ATTRIB, false, *pUndoDoc);
1075  }
1076 
1077  ScMarkData aMark(rDoc.GetSheetLimits());
1078  aMark.SetMarkArea( rRange );
1079  aMark.SelectTable( nTab, true );
1080 
1081  rDoc.ApplySelectionFrame(aMark, rOuter, &rInner);
1082  // don't need RowHeight if there is only a border
1083  }
1084 
1085  if (bUndo)
1086  {
1087  pDocShell->GetUndoManager()->AddUndoAction(
1088  std::make_unique<ScUndoBorder>( pDocShell, rRanges, std::move(pUndoDoc), rOuter, rInner ) );
1089  }
1090 
1091  for (size_t i = 0; i < nCount; ++i )
1092  pDocShell->PostPaint( rRanges[ i ], PaintPartFlags::Grid, SC_PF_LINES | SC_PF_TESTMERGE );
1093 
1094  pDocShell->SetDocumentModified();
1095 }
1096 
1099 
1100 static bool lcl_PutDataArray( ScDocShell& rDocShell, const ScRange& rRange,
1101  const uno::Sequence< uno::Sequence<uno::Any> >& aData )
1102 {
1103  ScDocument& rDoc = rDocShell.GetDocument();
1104  SCTAB nTab = rRange.aStart.Tab();
1105  SCCOL nStartCol = rRange.aStart.Col();
1106  SCROW nStartRow = rRange.aStart.Row();
1107  SCCOL nEndCol = rRange.aEnd.Col();
1108  SCROW nEndRow = rRange.aEnd.Row();
1109  bool bUndo(rDoc.IsUndoEnabled());
1110 
1111  if ( !rDoc.IsBlockEditable( nTab, nStartCol,nStartRow, nEndCol,nEndRow ) )
1112  {
1114  return false;
1115  }
1116 
1117  sal_Int32 nCols = 0;
1118  sal_Int32 nRows = aData.getLength();
1119  if ( nRows )
1120  nCols = aData[0].getLength();
1121 
1122  if ( nCols != nEndCol-nStartCol+1 || nRows != nEndRow-nStartRow+1 )
1123  {
1125  return false;
1126  }
1127 
1128  ScDocumentUniquePtr pUndoDoc;
1129  if ( bUndo )
1130  {
1131  pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
1132  pUndoDoc->InitUndo( rDoc, nTab, nTab );
1134  }
1135 
1136  rDoc.DeleteAreaTab( nStartCol, nStartRow, nEndCol, nEndRow, nTab, InsertDeleteFlags::CONTENTS );
1137 
1138  bool bError = false;
1139  SCROW nDocRow = nStartRow;
1140  for (const uno::Sequence<uno::Any>& rColSeq : aData)
1141  {
1142  if ( rColSeq.getLength() == nCols )
1143  {
1144  SCCOL nDocCol = nStartCol;
1145  for (const uno::Any& rElement : rColSeq)
1146  {
1147  ScAddress aPos(nDocCol, nDocRow, nTab);
1148 
1149  switch( rElement.getValueTypeClass() )
1150  {
1151  case uno::TypeClass_VOID:
1152  {
1153  // void = "no value"
1154  rDoc.SetError( nDocCol, nDocRow, nTab, FormulaError::NotAvailable );
1155  }
1156  break;
1157 
1158  // #87871# accept integer types because Basic passes a floating point
1159  // variable as byte, short or long if it's an integer number.
1160  case uno::TypeClass_BYTE:
1161  case uno::TypeClass_SHORT:
1162  case uno::TypeClass_UNSIGNED_SHORT:
1163  case uno::TypeClass_LONG:
1164  case uno::TypeClass_UNSIGNED_LONG:
1165  case uno::TypeClass_FLOAT:
1166  case uno::TypeClass_DOUBLE:
1167  {
1168  double fVal(0.0);
1169  rElement >>= fVal;
1170  rDoc.SetValue(aPos, fVal);
1171  }
1172  break;
1173 
1174  case uno::TypeClass_STRING:
1175  {
1176  OUString aUStr;
1177  rElement >>= aUStr;
1178  if ( !aUStr.isEmpty() )
1179  {
1180  ScSetStringParam aParam;
1181  aParam.setTextInput();
1182  rDoc.SetString(aPos, aUStr, &aParam);
1183  }
1184  }
1185  break;
1186 
1187  // accept Sequence<FormulaToken> for formula cells
1188  case uno::TypeClass_SEQUENCE:
1189  {
1190  uno::Sequence< sheet::FormulaToken > aTokens;
1191  if ( rElement >>= aTokens )
1192  {
1193  ScTokenArray aTokenArray(rDoc);
1194  ScTokenConversion::ConvertToTokenArray( rDoc, aTokenArray, aTokens );
1195  rDoc.SetFormula(aPos, aTokenArray);
1196  }
1197  else
1198  bError = true;
1199  }
1200  break;
1201 
1202  default:
1203  bError = true; // invalid type
1204  }
1205  ++nDocCol;
1206  }
1207  }
1208  else
1209  bError = true; // wrong size
1210 
1211  ++nDocRow;
1212  }
1213 
1214  bool bHeight = rDocShell.AdjustRowHeight( nStartRow, nEndRow, nTab );
1215 
1216  if ( pUndoDoc )
1217  {
1218  ScMarkData aDestMark(rDoc.GetSheetLimits());
1219  aDestMark.SelectOneTable( nTab );
1220  rDocShell.GetUndoManager()->AddUndoAction(
1221  std::make_unique<ScUndoPaste>(
1222  &rDocShell, ScRange(nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab),
1223  aDestMark, std::move(pUndoDoc), nullptr, InsertDeleteFlags::CONTENTS, nullptr, false));
1224  }
1225 
1226  if (!bHeight)
1227  rDocShell.PostPaint( rRange, PaintPartFlags::Grid ); // AdjustRowHeight may have painted already
1228 
1229  rDocShell.SetDocumentModified();
1230 
1231  return !bError;
1232 }
1233 
1234 static bool lcl_PutFormulaArray( ScDocShell& rDocShell, const ScRange& rRange,
1235  const uno::Sequence< uno::Sequence<OUString> >& aData,
1236  const formula::FormulaGrammar::Grammar eGrammar )
1237 {
1238  ScDocument& rDoc = rDocShell.GetDocument();
1239  SCTAB nTab = rRange.aStart.Tab();
1240  SCCOL nStartCol = rRange.aStart.Col();
1241  SCROW nStartRow = rRange.aStart.Row();
1242  SCCOL nEndCol = rRange.aEnd.Col();
1243  SCROW nEndRow = rRange.aEnd.Row();
1244  bool bUndo(rDoc.IsUndoEnabled());
1245 
1246  if ( !rDoc.IsBlockEditable( nTab, nStartCol,nStartRow, nEndCol,nEndRow ) )
1247  {
1249  return false;
1250  }
1251 
1252  sal_Int32 nCols = 0;
1253  sal_Int32 nRows = aData.getLength();
1254  if ( nRows )
1255  nCols = aData[0].getLength();
1256 
1257  if ( nCols != nEndCol-nStartCol+1 || nRows != nEndRow-nStartRow+1 )
1258  {
1260  return false;
1261  }
1262 
1263  ScDocumentUniquePtr pUndoDoc;
1264  if ( bUndo )
1265  {
1266  pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
1267  pUndoDoc->InitUndo( rDoc, nTab, nTab );
1268  rDoc.CopyToDocument(rRange, InsertDeleteFlags::CONTENTS, false, *pUndoDoc);
1269  }
1270 
1271  rDoc.DeleteAreaTab( nStartCol, nStartRow, nEndCol, nEndRow, nTab, InsertDeleteFlags::CONTENTS );
1272 
1273  bool bError = false;
1274  SCROW nDocRow = nStartRow;
1275  for (const uno::Sequence<OUString>& rColSeq : aData)
1276  {
1277  if ( rColSeq.getLength() == nCols )
1278  {
1279  SCCOL nDocCol = nStartCol;
1280  for (const OUString& aText : rColSeq)
1281  {
1282  ScAddress aPos( nDocCol, nDocRow, nTab );
1283 
1284  ScInputStringType aRes =
1286  *rDoc.GetFormatTable(), aText, LANGUAGE_ENGLISH_US);
1287  switch (aRes.meType)
1288  {
1290  rDoc.SetFormula(aPos, aRes.maText, eGrammar);
1291  break;
1293  rDoc.SetValue(aPos, aRes.mfValue);
1294  break;
1296  rDoc.SetTextCell(aPos, aRes.maText);
1297  break;
1298  default:
1299  ;
1300  }
1301 
1302  ++nDocCol;
1303  }
1304  }
1305  else
1306  bError = true; // wrong size
1307 
1308  ++nDocRow;
1309  }
1310 
1311  bool bHeight = rDocShell.AdjustRowHeight( nStartRow, nEndRow, nTab );
1312 
1313  if ( pUndoDoc )
1314  {
1315  ScMarkData aDestMark(rDoc.GetSheetLimits());
1316  aDestMark.SelectOneTable( nTab );
1317  rDocShell.GetUndoManager()->AddUndoAction(
1318  std::make_unique<ScUndoPaste>( &rDocShell,
1319  ScRange(nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab), aDestMark,
1320  std::move(pUndoDoc), nullptr, InsertDeleteFlags::CONTENTS, nullptr, false));
1321  }
1322 
1323  if (!bHeight)
1324  rDocShell.PostPaint( rRange, PaintPartFlags::Grid ); // AdjustRowHeight may have painted already
1325 
1326  rDocShell.SetDocumentModified();
1327 
1328  return !bError;
1329 }
1330 
1331 // used in ScCellRangeObj::getFormulaArray and ScCellObj::GetInputString_Impl
1332 static OUString lcl_GetInputString( ScDocument& rDoc, const ScAddress& rPos, bool bEnglish )
1333 {
1334  ScRefCellValue aCell(rDoc, rPos);
1335  if (aCell.isEmpty())
1336  return EMPTY_OUSTRING;
1337 
1338  OUString aVal;
1339 
1340  CellType eType = aCell.meType;
1341  if (eType == CELLTYPE_FORMULA)
1342  {
1343  ScFormulaCell* pForm = aCell.mpFormula;
1344  pForm->GetFormula( aVal, formula::FormulaGrammar::mapAPItoGrammar( bEnglish, false));
1345  return aVal;
1346  }
1347 
1348  SvNumberFormatter* pFormatter = bEnglish ? ScGlobal::GetEnglishFormatter() :
1349  rDoc.GetFormatTable();
1350  // Since the English formatter was constructed with
1351  // LANGUAGE_ENGLISH_US the "General" format has index key 0,
1352  // we don't have to query.
1353  sal_uInt32 nNumFmt = bEnglish ? 0 : rDoc.GetNumberFormat(rPos);
1354 
1355  if (eType == CELLTYPE_EDIT)
1356  {
1357  // GetString on EditCell turns breaks into spaces,
1358  // but we need the breaks here
1359  const EditTextObject* pData = aCell.mpEditText;
1360  if (pData)
1361  {
1362  EditEngine& rEngine = rDoc.GetEditEngine();
1363  rEngine.SetText(*pData);
1364  aVal = rEngine.GetText();
1365  }
1366  }
1367  else
1368  ScCellFormat::GetInputString(aCell, nNumFmt, aVal, *pFormatter, rDoc);
1369 
1370  // if applicable, prepend ' like in ScTabViewShell::UpdateInputHandler
1371  if ( eType == CELLTYPE_STRING || eType == CELLTYPE_EDIT )
1372  {
1373  double fDummy;
1374  OUString aTempString = aVal;
1375  bool bIsNumberFormat(pFormatter->IsNumberFormat(aTempString, nNumFmt, fDummy));
1376  if ( bIsNumberFormat )
1377  aTempString = "'" + aTempString;
1378  else if ( aTempString.startsWith("'") )
1379  {
1380  // if the string starts with a "'", add another one because setFormula
1381  // strips one (like text input, except for "text" number formats)
1382  if ( bEnglish || ( pFormatter->GetType(nNumFmt) != SvNumFormatType::TEXT ) )
1383  aTempString = "'" + aTempString;
1384  }
1385  aVal = aTempString;
1386  }
1387  return aVal;
1388 }
1389 
1391  pPropSet(lcl_GetCellsPropertySet()),
1392  pDocShell( pDocSh ),
1393  nObjectId( 0 ),
1394  bChartColAsHdr( false ),
1395  bChartRowAsHdr( false ),
1396  bCursorOnly( false ),
1397  bGotDataChangedHint( false ),
1398  aValueListeners( 0 )
1399 {
1400  // this is a hack to get m_wThis initialized; ideally there would be
1401  // factory functions doing this but there are so many subclasses of this...
1402  osl_atomic_increment(&m_refCount);
1403  {
1404  m_wThis = uno::Reference<uno::XInterface>(
1405  static_cast<cppu::OWeakObject*>(this));
1406  }
1407  osl_atomic_decrement(&m_refCount);
1408 
1409  ScRange aCellRange(rR);
1410  aCellRange.PutInOrder();
1411  aRanges.push_back( aCellRange );
1412 
1413  if (pDocShell) // Null if created with createInstance
1414  {
1415  ScDocument& rDoc = pDocShell->GetDocument();
1416  rDoc.AddUnoObject(*this);
1417  nObjectId = rDoc.GetNewUnoId();
1418  }
1419 }
1420 
1422  pPropSet(lcl_GetCellsPropertySet()),
1423  pDocShell( pDocSh ),
1424  aRanges( rR ),
1425  nObjectId( 0 ),
1426  bChartColAsHdr( false ),
1427  bChartRowAsHdr( false ),
1428  bCursorOnly( false ),
1429  bGotDataChangedHint( false ),
1430  aValueListeners( 0 )
1431 {
1432  // this is a hack to get m_wThis initialized; ideally there would be
1433  // factory functions doing this but there are so many subclasses of this...
1434  osl_atomic_increment(&m_refCount);
1435  {
1436  m_wThis = uno::Reference<uno::XInterface>(
1437  static_cast<cppu::OWeakObject*>(this));
1438  }
1439  osl_atomic_decrement(&m_refCount);
1440 
1441  if (pDocShell) // Null if created with createInstance
1442  {
1443  ScDocument& rDoc = pDocShell->GetDocument();
1444  rDoc.AddUnoObject(*this);
1445  nObjectId = rDoc.GetNewUnoId();
1446  }
1447 }
1448 
1450 {
1451  SolarMutexGuard g;
1452 
1453  // call RemoveUnoObject first, so no notification can happen
1454  // during ForgetCurrentAttrs
1455 
1456  if (pDocShell)
1458 
1460  ForgetMarkData();
1461 
1462  pValueListener.reset();
1463 
1466 }
1467 
1469 {
1470  pCurrentFlat.reset();
1471  pCurrentDeep.reset();
1472  pCurrentDataSet.reset();
1473  pNoDfltCurrentDataSet.reset();
1474  pCurrentDataSet = nullptr;
1475  pNoDfltCurrentDataSet = nullptr;
1476 
1477  // #i62483# pMarkData can remain unchanged, is deleted only if the range changes (RefChanged)
1478 }
1479 
1481 {
1482  pMarkData.reset();
1483 }
1484 
1486 {
1487  // get and cache direct cell attributes for this object's range
1488 
1489  if ( !pCurrentFlat && pDocShell )
1490  {
1491  ScDocument& rDoc = pDocShell->GetDocument();
1492  pCurrentFlat = rDoc.CreateSelectionPattern( *GetMarkData(), false );
1493  }
1494  return pCurrentFlat.get();
1495 }
1496 
1498 {
1499  // get and cache cell attributes (incl. styles) for this object's range
1500 
1501  if ( !pCurrentDeep && pDocShell )
1502  {
1503  ScDocument& rDoc = pDocShell->GetDocument();
1505  }
1506  return pCurrentDeep.get();
1507 }
1508 
1510 {
1511  if(!pCurrentDataSet)
1512  {
1513  const ScPatternAttr* pPattern = GetCurrentAttrsDeep();
1514  if ( pPattern )
1515  {
1516  // replace Dontcare with Default, so that we always have a reflection
1517  pCurrentDataSet.reset( new SfxItemSet( pPattern->GetItemSet() ) );
1518  pNoDfltCurrentDataSet.reset( new SfxItemSet( pPattern->GetItemSet() ) );
1519  pCurrentDataSet->ClearInvalidItems();
1520  }
1521  }
1522  return bNoDflt ? pNoDfltCurrentDataSet.get() : pCurrentDataSet.get();
1523 }
1524 
1526 {
1527  if (!pMarkData)
1528  {
1529  pMarkData.reset( new ScMarkData(GetDocument()->GetSheetLimits(), aRanges) );
1530  }
1531  return pMarkData.get();
1532 }
1533 
1535 {
1536  uno::Reference<uno::XInterface> const xThis(m_wThis);
1537  if (!xThis.is())
1538  { // fdo#72695: if UNO object is already dead, don't revive it with event
1539  if (SfxHintId::Dying == rHint.GetId())
1540  { // if the document dies, must reset to avoid crash in dtor!
1542  pDocShell = nullptr;
1543  }
1544  return;
1545  }
1546  if ( auto pRefHint = dynamic_cast<const ScUpdateRefHint*>(&rHint) )
1547  {
1548  ScDocument& rDoc = pDocShell->GetDocument();
1549  std::unique_ptr<ScRangeList> pUndoRanges;
1550  if ( rDoc.HasUnoRefUndo() )
1551  pUndoRanges.reset(new ScRangeList( aRanges ));
1552 
1553  if ( aRanges.UpdateReference( pRefHint->GetMode(), &rDoc, pRefHint->GetRange(),
1554  pRefHint->GetDx(), pRefHint->GetDy(), pRefHint->GetDz() ) )
1555  {
1556  if ( pRefHint->GetMode() == URM_INSDEL
1557  && aRanges.size() == 1
1558  && comphelper::getUnoTunnelImplementation<ScTableSheetObj>(xThis)
1559  )
1560  {
1561  // #101755#; the range size of a sheet does not change
1562  ScRange & rR = aRanges.front();
1563  rR.aStart.SetCol(0);
1564  rR.aStart.SetRow(0);
1565  rR.aEnd.SetCol(rDoc.MaxCol());
1566  rR.aEnd.SetRow(rDoc.MaxRow());
1567  }
1568  RefChanged();
1569 
1570  // any change of the range address is broadcast to value (modify) listeners
1571  if ( !aValueListeners.empty() )
1572  bGotDataChangedHint = true;
1573 
1574  if ( pUndoRanges )
1575  rDoc.AddUnoRefChange( nObjectId, *pUndoRanges );
1576  }
1577  }
1578  else if ( auto pUndoHint = dynamic_cast<const ScUnoRefUndoHint*>(&rHint) )
1579  {
1580  if ( pUndoHint->GetObjectId() == nObjectId )
1581  {
1582  // restore ranges from hint
1583 
1584  aRanges = pUndoHint->GetRanges();
1585 
1586  RefChanged();
1587  if ( !aValueListeners.empty() )
1588  bGotDataChangedHint = true; // need to broadcast the undo, too
1589  }
1590  }
1591  else
1592  {
1593  const SfxHintId nId = rHint.GetId();
1594  if ( nId == SfxHintId::Dying )
1595  {
1597  pDocShell = nullptr; // invalid
1598 
1599  if ( !aValueListeners.empty() )
1600  {
1601  // dispose listeners
1602 
1603  lang::EventObject aEvent;
1604  aEvent.Source.set(static_cast<cppu::OWeakObject*>(this));
1605  for (uno::Reference<util::XModifyListener> & xValueListener : aValueListeners)
1606  xValueListener->disposing( aEvent );
1607 
1608  aValueListeners.clear();
1609 
1610  // The listeners can't have the last ref to this, as it's still held
1611  // by the DocShell.
1612  }
1613  }
1614  else if ( nId == SfxHintId::DataChanged )
1615  {
1616  // document content changed -> forget cached attributes
1618 
1619  if ( bGotDataChangedHint && pDocShell )
1620  {
1621  // This object was notified of content changes, so one call
1622  // for each listener is generated now.
1623  // The calls can't be executed directly because the document's
1624  // UNO broadcaster list must not be modified.
1625  // Instead, add to the document's list of listener calls,
1626  // which will be executed directly after the broadcast of
1627  // SfxHintId::DataChanged.
1628 
1629  lang::EventObject aEvent;
1630  aEvent.Source.set(static_cast<cppu::OWeakObject*>(this));
1631 
1632  // the EventObject holds a Ref to this object until after the listener calls
1633 
1634  ScDocument& rDoc = pDocShell->GetDocument();
1635  for (const uno::Reference<util::XModifyListener> & xValueListener : aValueListeners)
1636  rDoc.AddUnoListenerCall( xValueListener, aEvent );
1637 
1638  bGotDataChangedHint = false;
1639  }
1640  }
1641  else if ( nId == SfxHintId::ScCalcAll )
1642  {
1643  // broadcast from DoHardRecalc - set bGotDataChangedHint
1644  // (SfxHintId::DataChanged follows separately)
1645 
1646  if ( !aValueListeners.empty() )
1647  bGotDataChangedHint = true;
1648  }
1649  }
1650 }
1651 
1653 {
1655 
1656  if ( pValueListener && !aValueListeners.empty() )
1657  {
1658  pValueListener->EndListeningAll();
1659 
1660  ScDocument& rDoc = pDocShell->GetDocument();
1661  for ( size_t i = 0, nCount = aRanges.size(); i < nCount; ++i )
1662  rDoc.StartListeningArea( aRanges[ i ], false, pValueListener.get() );
1663  }
1664 
1666  ForgetMarkData();
1667 }
1668 
1670 {
1671  if (pDocShell)
1672  return &pDocShell->GetDocument();
1673  else
1674  return nullptr;
1675 }
1676 
1678 {
1679  if ( pDocShell || !pDocSh )
1680  return;
1681 
1682  pDocShell = pDocSh;
1683 
1684  ScRange aCellRange(rR);
1685  aCellRange.PutInOrder();
1686  aRanges.RemoveAll();
1687  aRanges.push_back( aCellRange );
1688 
1690 
1691  RefChanged(); // adjust range in range object
1692 }
1693 
1694 void ScCellRangesBase::AddRange(const ScRange& rRange, const bool bMergeRanges)
1695 {
1696  if (bMergeRanges)
1697  aRanges.Join(rRange);
1698  else
1699  aRanges.push_back(rRange);
1700  RefChanged();
1701 }
1702 
1704 {
1705  ScRange aCellRange(rNew);
1706  aCellRange.PutInOrder();
1707 
1708  aRanges.RemoveAll();
1709  aRanges.push_back( aCellRange );
1710  RefChanged();
1711 }
1712 
1714 {
1715  aRanges = rNew;
1716  RefChanged();
1717 }
1718 
1720 {
1721  // set for a selection object that is created from the cursor position
1722  // without anything selected (may contain several sheets)
1723 
1724  bCursorOnly = bSet;
1725 }
1726 
1728 {
1729  for (size_t i = 0, nCount = aRanges.size(); i < nCount; ++i)
1731 }
1732 
1733 // XSheetOperation
1734 
1735 double SAL_CALL ScCellRangesBase::computeFunction( sheet::GeneralFunction nFunction )
1736 {
1737  SolarMutexGuard aGuard;
1738  ScMarkData aMark(*GetMarkData());
1739  aMark.MarkToSimple();
1740  if (!aMark.IsMarked())
1741  aMark.SetMarkNegative(true); // so we can enter dummy position
1742 
1743  ScAddress aDummy; // if not marked, ignored if it is negative
1744  double fVal;
1745  ScSubTotalFunc eFunc = ScDPUtil::toSubTotalFunc(static_cast<ScGeneralFunction>(nFunction));
1746  ScDocument& rDoc = pDocShell->GetDocument();
1747  if ( !rDoc.GetSelectionFunction( eFunc, aDummy, aMark, fVal ) )
1748  {
1749  throw uno::RuntimeException();
1750  }
1751 
1752  return fVal;
1753 }
1754 
1755 void SAL_CALL ScCellRangesBase::clearContents( sal_Int32 nContentFlags )
1756 {
1757  SolarMutexGuard aGuard;
1758  if ( !aRanges.empty() )
1759  {
1760  // only for clearContents: EDITATTR is only used if no contents are deleted
1761  InsertDeleteFlags nDelFlags = static_cast<InsertDeleteFlags>(nContentFlags) & InsertDeleteFlags::ALL;
1762  if ( ( nDelFlags & InsertDeleteFlags::EDITATTR ) && ( nDelFlags & InsertDeleteFlags::CONTENTS ) == InsertDeleteFlags::NONE )
1763  nDelFlags |= InsertDeleteFlags::EDITATTR;
1764 
1765  pDocShell->GetDocFunc().DeleteContents( *GetMarkData(), nDelFlags, true, true );
1766  }
1767  // otherwise nothing to do
1768 }
1769 
1770 // XPropertyState
1771 
1773 {
1774  return pPropSet->getPropertyMap();
1775 }
1776 
1778  sal_uInt16& rItemWhich )
1779 {
1780  // Which-ID of the affected items also when the item can't handle
1781  // the property by itself
1782  if ( !pEntry )
1783  return;
1784 
1785  if ( IsScItemWid( pEntry->nWID ) )
1786  rItemWhich = pEntry->nWID;
1787  else
1788  switch ( pEntry->nWID )
1789  {
1790  case SC_WID_UNO_TBLBORD:
1791  case SC_WID_UNO_TBLBORD2:
1792  rItemWhich = ATTR_BORDER;
1793  break;
1794  case SC_WID_UNO_CONDFMT:
1795  case SC_WID_UNO_CONDLOC:
1796  case SC_WID_UNO_CONDXML:
1797  rItemWhich = ATTR_CONDITIONAL;
1798  break;
1799  case SC_WID_UNO_VALIDAT:
1800  case SC_WID_UNO_VALILOC:
1801  case SC_WID_UNO_VALIXML:
1802  rItemWhich = ATTR_VALIDDATA;
1803  break;
1804  }
1805 
1806 }
1807 
1808 beans::PropertyState ScCellRangesBase::GetOnePropertyState( sal_uInt16 nItemWhich, const SfxItemPropertySimpleEntry* pEntry )
1809 {
1810  beans::PropertyState eRet = beans::PropertyState_DIRECT_VALUE;
1811  if ( nItemWhich ) // item wid (from map or special case)
1812  {
1813  // For items that contain several properties (like background),
1814  // "ambiguous" is returned too often here
1815 
1816  // for PropertyState, don't look at styles
1817  const ScPatternAttr* pPattern = GetCurrentAttrsFlat();
1818  if ( pPattern )
1819  {
1820  SfxItemState eState = pPattern->GetItemSet().GetItemState( nItemWhich, false );
1821 
1822  if ( nItemWhich == ATTR_VALUE_FORMAT && eState == SfxItemState::DEFAULT )
1823  eState = pPattern->GetItemSet().GetItemState( ATTR_LANGUAGE_FORMAT, false );
1824 
1825  if ( eState == SfxItemState::SET )
1826  eRet = beans::PropertyState_DIRECT_VALUE;
1827  else if ( eState == SfxItemState::DEFAULT )
1828  eRet = beans::PropertyState_DEFAULT_VALUE;
1829  else if ( eState == SfxItemState::DONTCARE )
1830  eRet = beans::PropertyState_AMBIGUOUS_VALUE;
1831  else
1832  {
1833  OSL_FAIL("unknown ItemState");
1834  }
1835  }
1836  }
1837  else if ( pEntry )
1838  {
1839  if ( pEntry->nWID == SC_WID_UNO_CHCOLHDR || pEntry->nWID == SC_WID_UNO_CHROWHDR || pEntry->nWID == SC_WID_UNO_ABSNAME )
1840  eRet = beans::PropertyState_DIRECT_VALUE;
1841  else if ( pEntry->nWID == SC_WID_UNO_CELLSTYL )
1842  {
1843  // a style is always set, there's no default state
1845  if (pStyle)
1846  eRet = beans::PropertyState_DIRECT_VALUE;
1847  else
1848  eRet = beans::PropertyState_AMBIGUOUS_VALUE;
1849  }
1850  else if ( pEntry->nWID == SC_WID_UNO_NUMRULES )
1851  eRet = beans::PropertyState_DEFAULT_VALUE; // numbering rules are always default
1852  }
1853  return eRet;
1854 }
1855 
1856 beans::PropertyState SAL_CALL ScCellRangesBase::getPropertyState( const OUString& aPropertyName )
1857 {
1858  SolarMutexGuard aGuard;
1859  if ( aRanges.empty() )
1860  throw uno::RuntimeException();
1861 
1862  const SfxItemPropertyMap& rMap = GetItemPropertyMap(); // from derived class
1863  sal_uInt16 nItemWhich = 0;
1864  const SfxItemPropertySimpleEntry* pEntry = rMap.getByName( aPropertyName );
1865  lcl_GetPropertyWhich( pEntry, nItemWhich );
1866  return GetOnePropertyState( nItemWhich, pEntry );
1867 }
1868 
1869 uno::Sequence<beans::PropertyState> SAL_CALL ScCellRangesBase::getPropertyStates(
1870  const uno::Sequence<OUString>& aPropertyNames )
1871 {
1872  SolarMutexGuard aGuard;
1873 
1874  const SfxItemPropertyMap& rPropertyMap = GetItemPropertyMap(); // from derived class
1875 
1876  uno::Sequence<beans::PropertyState> aRet(aPropertyNames.getLength());
1877  std::transform(aPropertyNames.begin(), aPropertyNames.end(), aRet.begin(),
1878  [this, &rPropertyMap](const auto& rName) -> beans::PropertyState {
1879  sal_uInt16 nItemWhich = 0;
1880  const SfxItemPropertySimpleEntry* pEntry = rPropertyMap.getByName( rName );
1881  lcl_GetPropertyWhich( pEntry, nItemWhich );
1882  return GetOnePropertyState(nItemWhich, pEntry);
1883  });
1884  return aRet;
1885 }
1886 
1887 void SAL_CALL ScCellRangesBase::setPropertyToDefault( const OUString& aPropertyName )
1888 {
1889  SolarMutexGuard aGuard;
1890  if ( !pDocShell )
1891  return;
1892 
1893  const SfxItemPropertyMap& rPropertyMap = GetItemPropertyMap(); // from derived class
1894  sal_uInt16 nItemWhich = 0;
1895  const SfxItemPropertySimpleEntry* pEntry = rPropertyMap.getByName( aPropertyName );
1896  lcl_GetPropertyWhich( pEntry, nItemWhich );
1897  if ( nItemWhich ) // item wid (from map or special case)
1898  {
1899  if ( !aRanges.empty() ) // empty = nothing to do
1900  {
1904 
1905  sal_uInt16 aWIDs[3];
1906  aWIDs[0] = nItemWhich;
1907  if ( nItemWhich == ATTR_VALUE_FORMAT )
1908  {
1909  aWIDs[1] = ATTR_LANGUAGE_FORMAT; // language for number formats
1910  aWIDs[2] = 0;
1911  }
1912  else
1913  aWIDs[1] = 0;
1914  pDocShell->GetDocFunc().ClearItems( *GetMarkData(), aWIDs, true );
1915  }
1916  }
1917  else if ( pEntry )
1918  {
1919  if ( pEntry->nWID == SC_WID_UNO_CHCOLHDR )
1920  bChartColAsHdr = false;
1921  else if ( pEntry->nWID == SC_WID_UNO_CHROWHDR )
1922  bChartRowAsHdr = false;
1923  else if ( pEntry->nWID == SC_WID_UNO_CELLSTYL )
1924  {
1925  OUString aStyleName( ScResId( STR_STYLENAME_STANDARD ) );
1926  pDocShell->GetDocFunc().ApplyStyle( *GetMarkData(), aStyleName, true );
1927  }
1928  }
1929 }
1930 
1931 uno::Any SAL_CALL ScCellRangesBase::getPropertyDefault( const OUString& aPropertyName )
1932 {
1934 
1935  SolarMutexGuard aGuard;
1936  uno::Any aAny;
1937 
1938  if ( pDocShell )
1939  {
1940  ScDocument& rDoc = pDocShell->GetDocument();
1941  const SfxItemPropertyMap& rPropertyMap = GetItemPropertyMap(); // from derived class
1942  const SfxItemPropertySimpleEntry* pEntry = rPropertyMap.getByName( aPropertyName );
1943  if ( pEntry )
1944  {
1945  if ( IsScItemWid( pEntry->nWID ) )
1946  {
1947  const ScPatternAttr* pPattern = rDoc.GetDefPattern();
1948  if ( pPattern )
1949  {
1950  const SfxItemSet& rSet = pPattern->GetItemSet();
1951 
1952  switch ( pEntry->nWID ) // for item-specific handling
1953  {
1954  case ATTR_VALUE_FORMAT:
1955  // default has no language set
1956  aAny <<= static_cast<sal_Int32>( static_cast<const SfxUInt32Item&>(rSet.Get(pEntry->nWID)).GetValue() );
1957  break;
1958  case ATTR_INDENT:
1959  aAny <<= static_cast<sal_Int16>( TwipsToHMM(static_cast<const ScIndentItem&>(
1960  rSet.Get(pEntry->nWID)).GetValue()) );
1961  break;
1962  default:
1963  pPropSet->getPropertyValue(aPropertyName, rSet, aAny);
1964  }
1965  }
1966  }
1967  else
1968  switch ( pEntry->nWID )
1969  {
1970  case SC_WID_UNO_CHCOLHDR:
1971  case SC_WID_UNO_CHROWHDR:
1972  aAny <<= false;
1973  break;
1974  case SC_WID_UNO_CELLSTYL:
1976  ScResId(STR_STYLENAME_STANDARD), SfxStyleFamily::Para );
1977  break;
1978  case SC_WID_UNO_TBLBORD:
1979  case SC_WID_UNO_TBLBORD2:
1980  {
1981  const ScPatternAttr* pPattern = rDoc.GetDefPattern();
1982  if ( pPattern )
1983  {
1984  if (pEntry->nWID == SC_WID_UNO_TBLBORD2)
1986  pPattern->GetItem(ATTR_BORDER),
1987  pPattern->GetItem(ATTR_BORDER_INNER) );
1988  else
1990  pPattern->GetItem(ATTR_BORDER),
1991  pPattern->GetItem(ATTR_BORDER_INNER) );
1992  }
1993  }
1994  break;
1995  case SC_WID_UNO_CONDFMT:
1996  case SC_WID_UNO_CONDLOC:
1997  case SC_WID_UNO_CONDXML:
1998  {
1999  bool bEnglish = ( pEntry->nWID != SC_WID_UNO_CONDLOC );
2000  bool bXML = ( pEntry->nWID == SC_WID_UNO_CONDXML );
2001  formula::FormulaGrammar::Grammar eGrammar = (bXML ?
2002  rDoc.GetStorageGrammar() :
2003  formula::FormulaGrammar::mapAPItoGrammar( bEnglish, bXML));
2004 
2005  aAny <<= uno::Reference<sheet::XSheetConditionalEntries>(
2006  new ScTableConditionalFormat( &rDoc, 0, aRanges[0].aStart.Tab(), eGrammar ));
2007  }
2008  break;
2009  case SC_WID_UNO_VALIDAT:
2010  case SC_WID_UNO_VALILOC:
2011  case SC_WID_UNO_VALIXML:
2012  {
2013  bool bEnglish = ( pEntry->nWID != SC_WID_UNO_VALILOC );
2014  bool bXML = ( pEntry->nWID == SC_WID_UNO_VALIXML );
2015  formula::FormulaGrammar::Grammar eGrammar = (bXML ?
2016  rDoc.GetStorageGrammar() :
2017  formula::FormulaGrammar::mapAPItoGrammar( bEnglish, bXML));
2018 
2019  aAny <<= uno::Reference<beans::XPropertySet>(
2020  new ScTableValidationObj( rDoc, 0, eGrammar ));
2021  }
2022  break;
2023  case SC_WID_UNO_NUMRULES:
2024  {
2026  }
2027  break;
2028  }
2029  }
2030  }
2031 
2032  return aAny;
2033 }
2034 
2035 // XPropertySet
2036 
2037 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScCellRangesBase::getPropertySetInfo()
2038 {
2039  SolarMutexGuard aGuard;
2040  static uno::Reference<beans::XPropertySetInfo> aRef(
2042  return aRef;
2043 }
2044 
2045 static void lcl_SetCellProperty( const SfxItemPropertySimpleEntry& rEntry, const uno::Any& rValue,
2046  ScPatternAttr& rPattern, const ScDocument &rDoc,
2047  sal_uInt16& rFirstItemId, sal_uInt16& rSecondItemId )
2048 {
2049  rFirstItemId = rEntry.nWID;
2050  rSecondItemId = 0;
2051 
2052  SfxItemSet& rSet = rPattern.GetItemSet();
2053  switch ( rEntry.nWID )
2054  {
2055  case ATTR_VALUE_FORMAT:
2056  {
2057  // language for number formats
2058  SvNumberFormatter* pFormatter = rDoc.GetFormatTable();
2059  sal_uLong nOldFormat = rSet.Get( ATTR_VALUE_FORMAT ).GetValue();
2060  LanguageType eOldLang = rSet.Get( ATTR_LANGUAGE_FORMAT ).GetLanguage();
2061  nOldFormat = pFormatter->GetFormatForLanguageIfBuiltIn( nOldFormat, eOldLang );
2062 
2063  sal_Int32 nIntVal = 0;
2064  if ( !(rValue >>= nIntVal) )
2065  throw lang::IllegalArgumentException();
2066 
2067  sal_uLong nNewFormat = static_cast<sal_uLong>(nIntVal);
2068  rSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNewFormat ) );
2069 
2070  const SvNumberformat* pNewEntry = pFormatter->GetEntry( nNewFormat );
2071  LanguageType eNewLang =
2072  pNewEntry ? pNewEntry->GetLanguage() : LANGUAGE_DONTKNOW;
2073  if ( eNewLang != eOldLang && eNewLang != LANGUAGE_DONTKNOW )
2074  {
2075  rSet.Put( SvxLanguageItem( eNewLang, ATTR_LANGUAGE_FORMAT ) );
2076 
2077  // if only language is changed,
2078  // don't touch number format attribute
2079  sal_uLong nNewMod = nNewFormat % SV_COUNTRY_LANGUAGE_OFFSET;
2080  if ( nNewMod == ( nOldFormat % SV_COUNTRY_LANGUAGE_OFFSET ) &&
2081  nNewMod <= SV_MAX_COUNT_STANDARD_FORMATS )
2082  {
2083  rFirstItemId = 0; // don't use ATTR_VALUE_FORMAT value
2084  }
2085 
2086  rSecondItemId = ATTR_LANGUAGE_FORMAT;
2087  }
2088 
2089  }
2090  break;
2091  case ATTR_INDENT:
2092  {
2093  sal_Int16 nIntVal = 0;
2094  if ( !(rValue >>= nIntVal) )
2095  throw lang::IllegalArgumentException();
2096 
2097  rSet.Put( ScIndentItem( static_cast<sal_uInt16>(HMMToTwips(nIntVal)) ) );
2098 
2099  }
2100  break;
2101  case ATTR_ROTATE_VALUE:
2102  {
2103  sal_Int32 nRotVal = 0;
2104  if ( !(rValue >>= nRotVal) )
2105  throw lang::IllegalArgumentException();
2106 
2107  // stored value is always between 0 and 360 deg.
2108  nRotVal %= 36000;
2109  if ( nRotVal < 0 )
2110  nRotVal += 36000;
2111 
2112  rSet.Put( ScRotateValueItem( Degree100(nRotVal) ) );
2113 
2114  }
2115  break;
2116  case ATTR_STACKED:
2117  {
2118  table::CellOrientation eOrient;
2119  if( rValue >>= eOrient )
2120  {
2121  switch( eOrient )
2122  {
2123  case table::CellOrientation_STANDARD:
2124  rSet.Put( ScVerticalStackCell( false ) );
2125  break;
2126  case table::CellOrientation_TOPBOTTOM:
2127  rSet.Put( ScVerticalStackCell( false ) );
2128  rSet.Put( ScRotateValueItem( 27000_deg100 ) );
2129  rSecondItemId = ATTR_ROTATE_VALUE;
2130  break;
2131  case table::CellOrientation_BOTTOMTOP:
2132  rSet.Put( ScVerticalStackCell( false ) );
2133  rSet.Put( ScRotateValueItem( 9000_deg100 ) );
2134  rSecondItemId = ATTR_ROTATE_VALUE;
2135  break;
2136  case table::CellOrientation_STACKED:
2137  rSet.Put( ScVerticalStackCell( true ) );
2138  break;
2139  default:
2140  {
2141  // added to avoid warnings
2142  }
2143  }
2144  }
2145  }
2146  break;
2147  default:
2148  {
2149  lcl_GetCellsPropertySet()->setPropertyValue(rEntry, rValue, rSet);
2150  }
2151  }
2152 }
2153 
2155  const OUString& aPropertyName, const uno::Any& aValue )
2156 {
2157  SolarMutexGuard aGuard;
2158 
2159  if ( !pDocShell || aRanges.empty() )
2160  throw uno::RuntimeException();
2161 
2162  const SfxItemPropertyMap& rPropertyMap = GetItemPropertyMap(); // from derived class
2163  const SfxItemPropertySimpleEntry* pEntry = rPropertyMap.getByName( aPropertyName );
2164  if ( !pEntry )
2165  throw beans::UnknownPropertyException(aPropertyName);
2166 
2167  SetOnePropertyValue( pEntry, aValue );
2168 }
2169 
2171 {
2172  if ( !pEntry )
2173  return;
2174 
2175  if ( IsScItemWid( pEntry->nWID ) )
2176  {
2177  if ( !aRanges.empty() ) // empty = nothing to do
2178  {
2179  ScDocument& rDoc = pDocShell->GetDocument();
2180 
2181  // For parts of compound items with multiple properties (e.g. background)
2182  // the old item has to be first fetched from the document.
2186  // ClearInvalidItems, so that in any case we have an item with the correct type
2187 
2188  ScPatternAttr aPattern( *GetCurrentAttrsDeep() );
2189  SfxItemSet& rSet = aPattern.GetItemSet();
2190  rSet.ClearInvalidItems();
2191 
2192  sal_uInt16 nFirstItem, nSecondItem;
2193  lcl_SetCellProperty( *pEntry, aValue, aPattern, rDoc, nFirstItem, nSecondItem );
2194 
2195  for (sal_uInt16 nWhich = ATTR_PATTERN_START; nWhich <= ATTR_PATTERN_END; nWhich++)
2196  if ( nWhich != nFirstItem && nWhich != nSecondItem )
2197  rSet.ClearItem(nWhich);
2198 
2199  pDocShell->GetDocFunc().ApplyAttributes( *GetMarkData(), aPattern, true );
2200  }
2201  }
2202  else // implemented here
2203  switch ( pEntry->nWID )
2204  {
2205  case EE_CHAR_ESCAPEMENT: // Specifically for xlsx import
2206  {
2207  sal_Int32 nValue = 0;
2208  aValue >>= nValue;
2209  if (nValue)
2210  {
2211  for (size_t i = 0, n = aRanges.size(); i < n; ++i)
2212  {
2213  ScRange const & rRange = aRanges[i];
2214 
2215  /* TODO: Iterate through the range */
2216  ScAddress aAddr = rRange.aStart;
2217  ScDocument& rDoc = pDocShell->GetDocument();
2218  ScRefCellValue aCell(rDoc, aAddr);
2219 
2220  OUString aStr = aCell.getString(&rDoc);
2221  EditEngine aEngine( rDoc.GetEnginePool() );
2222  aEngine.SetEditTextObjectPool(rDoc.GetEditPool());
2223 
2224  /* EE_CHAR_ESCAPEMENT seems to be set on the cell _only_ when
2225  * there are no other attribs for the cell.
2226  * So, it is safe to overwrite the complete attribute set.
2227  * If there is a need - getting CellType and processing
2228  * the attributes could be considered.
2229  */
2230  SfxItemSet aAttr = aEngine.GetEmptyItemSet();
2231  aEngine.SetText(aStr);
2232  if( nValue < 0 ) // Subscript
2233  aAttr.Put( SvxEscapementItem( SvxEscapement::Subscript, EE_CHAR_ESCAPEMENT ) );
2234  else // Superscript
2235  aAttr.Put( SvxEscapementItem( SvxEscapement::Superscript, EE_CHAR_ESCAPEMENT ) );
2236  aEngine.QuickSetAttribs(aAttr, ESelection(0, 0, 0, aStr.getLength()));
2237 
2238  // The cell will own the text object instance.
2239  rDoc.SetEditText(aRanges[0].aStart, aEngine.CreateTextObject());
2240  }
2241  }
2242  }
2243  break;
2244  case SC_WID_UNO_CHCOLHDR:
2245  // chart header flags are set for this object, not stored with document
2247  break;
2248  case SC_WID_UNO_CHROWHDR:
2250  break;
2251  case SC_WID_UNO_CELLSTYL:
2252  {
2253  OUString aStrVal;
2254  aValue >>= aStrVal;
2256  aStrVal, SfxStyleFamily::Para ));
2257  pDocShell->GetDocFunc().ApplyStyle( *GetMarkData(), aString, true );
2258  }
2259  break;
2260  case SC_WID_UNO_TBLBORD:
2261  {
2262  table::TableBorder aBorder;
2263  if ( !aRanges.empty() && ( aValue >>= aBorder ) ) // empty = nothing to do
2264  {
2265  SvxBoxItem aOuter(ATTR_BORDER);
2267  ScHelperFunctions::FillBoxItems( aOuter, aInner, aBorder );
2268 
2269  ScHelperFunctions::ApplyBorder( pDocShell, aRanges, aOuter, aInner );
2270  }
2271  }
2272  break;
2273  case SC_WID_UNO_TBLBORD2:
2274  {
2275  table::TableBorder2 aBorder2;
2276  if ( !aRanges.empty() && ( aValue >>= aBorder2 ) ) // empty = nothing to do
2277  {
2278  SvxBoxItem aOuter(ATTR_BORDER);
2280  ScHelperFunctions::FillBoxItems( aOuter, aInner, aBorder2 );
2281 
2282  ScHelperFunctions::ApplyBorder( pDocShell, aRanges, aOuter, aInner );
2283  }
2284  }
2285  break;
2286  case SC_WID_UNO_CONDFMT:
2287  case SC_WID_UNO_CONDLOC:
2288  case SC_WID_UNO_CONDXML:
2289  {
2290  uno::Reference<sheet::XSheetConditionalEntries> xInterface(aValue, uno::UNO_QUERY);
2291  if ( !aRanges.empty() && xInterface.is() ) // empty = nothing to do
2292  {
2293  ScTableConditionalFormat* pFormat =
2294  comphelper::getUnoTunnelImplementation<ScTableConditionalFormat>( xInterface );
2295  if (pFormat)
2296  {
2297  ScDocument& rDoc = pDocShell->GetDocument();
2298  bool bEnglish = ( pEntry->nWID != SC_WID_UNO_CONDLOC );
2299  bool bXML = ( pEntry->nWID == SC_WID_UNO_CONDXML );
2300  formula::FormulaGrammar::Grammar eGrammar = (bXML ?
2302  formula::FormulaGrammar::mapAPItoGrammar( bEnglish, bXML));
2303 
2304  SCTAB nTab = aRanges.front().aStart.Tab();
2305  // To remove conditional formats for all cells in aRanges we need to:
2306  // Remove conditional format data from cells' attributes
2307  rDoc.RemoveCondFormatData( aRanges, nTab, 0 );
2308  // And also remove ranges from conditional formats list
2309  for (size_t i = 0; i < aRanges.size(); ++i)
2310  {
2311  rDoc.GetCondFormList( aRanges[i].aStart.Tab() )->DeleteArea(
2312  aRanges[i].aStart.Col(), aRanges[i].aStart.Row(),
2313  aRanges[i].aEnd.Col(), aRanges[i].aEnd.Row() );
2314  }
2315 
2316  // Then we can apply new conditional format if there is one
2317  if (pFormat->getCount())
2318  {
2319  auto pNew = std::make_unique<ScConditionalFormat>( 0, &rDoc ); // Index will be set on inserting
2320  pFormat->FillFormat( *pNew, rDoc, eGrammar );
2321  pNew->SetRange( aRanges );
2322  pDocShell->GetDocFunc().ReplaceConditionalFormat( 0, std::move(pNew), nTab, aRanges );
2323  }
2324 
2325  // and repaint
2326  for (size_t i = 0; i < aRanges.size(); ++i)
2329  }
2330  }
2331  }
2332  break;
2333  case SC_WID_UNO_VALIDAT:
2334  case SC_WID_UNO_VALILOC:
2335  case SC_WID_UNO_VALIXML:
2336  {
2337  uno::Reference<beans::XPropertySet> xInterface(aValue, uno::UNO_QUERY);
2338  if ( !aRanges.empty() && xInterface.is() ) // empty = nothing to do
2339  {
2340  ScTableValidationObj* pValidObj =
2341  comphelper::getUnoTunnelImplementation<ScTableValidationObj>( xInterface );
2342  if (pValidObj)
2343  {
2344  ScDocument& rDoc = pDocShell->GetDocument();
2345  bool bEnglish = ( pEntry->nWID != SC_WID_UNO_VALILOC );
2346  bool bXML = ( pEntry->nWID == SC_WID_UNO_VALIXML );
2347  formula::FormulaGrammar::Grammar eGrammar = (bXML ?
2349  formula::FormulaGrammar::mapAPItoGrammar( bEnglish, bXML));
2350 
2351  std::unique_ptr<ScValidationData> pNewData(
2352  pValidObj->CreateValidationData( rDoc, eGrammar ));
2353  sal_uLong nIndex = rDoc.AddValidationEntry( *pNewData );
2354  pNewData.reset();
2355 
2356  ScPatternAttr aPattern( rDoc.GetPool() );
2357  aPattern.GetItemSet().Put( SfxUInt32Item( ATTR_VALIDDATA, nIndex ) );
2358  pDocShell->GetDocFunc().ApplyAttributes( *GetMarkData(), aPattern, true );
2359  }
2360  }
2361  }
2362  break;
2363  // SC_WID_UNO_NUMRULES is ignored...
2364  }
2365 }
2366 
2367 uno::Any SAL_CALL ScCellRangesBase::getPropertyValue( const OUString& aPropertyName )
2368 {
2369  SolarMutexGuard aGuard;
2370 
2371  if ( !pDocShell || aRanges.empty() )
2372  throw uno::RuntimeException();
2373 
2374  const SfxItemPropertyMap& rPropertyMap = GetItemPropertyMap(); // from derived class
2375  const SfxItemPropertySimpleEntry* pEntry = rPropertyMap.getByName( aPropertyName );
2376  if ( !pEntry )
2377  throw beans::UnknownPropertyException(aPropertyName);
2378 
2379  uno::Any aAny;
2380  GetOnePropertyValue( pEntry, aAny );
2381  return aAny;
2382 }
2383 
2385 {
2386  if ( !pEntry )
2387  return;
2388 
2389  if ( IsScItemWid( pEntry->nWID ) )
2390  {
2391  SfxItemSet* pDataSet = GetCurrentDataSet();
2392  if ( pDataSet )
2393  {
2394  switch ( pEntry->nWID ) // for special handling of items
2395  {
2396  case ATTR_VALUE_FORMAT:
2397  {
2398  ScDocument& rDoc = pDocShell->GetDocument();
2399 
2400  sal_uLong nOldFormat =
2401  pDataSet->Get( ATTR_VALUE_FORMAT ).GetValue();
2402  LanguageType eOldLang =
2403  pDataSet->Get( ATTR_LANGUAGE_FORMAT ).GetLanguage();
2404  nOldFormat = rDoc.GetFormatTable()->
2405  GetFormatForLanguageIfBuiltIn( nOldFormat, eOldLang );
2406  rAny <<= static_cast<sal_Int32>(nOldFormat);
2407  }
2408  break;
2409  case ATTR_INDENT:
2410  rAny <<= static_cast<sal_Int16>( TwipsToHMM(static_cast<const ScIndentItem&>(
2411  pDataSet->Get(pEntry->nWID)).GetValue()) );
2412  break;
2413  case ATTR_STACKED:
2414  {
2415  Degree100 nRot = pDataSet->Get(ATTR_ROTATE_VALUE).GetValue();
2416  bool bStacked = static_cast<const ScVerticalStackCell&>(pDataSet->Get(pEntry->nWID)).GetValue();
2417  SvxOrientationItem( nRot, bStacked, 0 ).QueryValue( rAny );
2418  }
2419  break;
2420  default:
2421  pPropSet->getPropertyValue(*pEntry, *pDataSet, rAny);
2422  }
2423  }
2424  }
2425  else // implemented here
2426  switch ( pEntry->nWID )
2427  {
2428  case SC_WID_UNO_CHCOLHDR:
2429  rAny <<= bChartColAsHdr;
2430  break;
2431  case SC_WID_UNO_CHROWHDR:
2432  rAny <<= bChartRowAsHdr;
2433  break;
2434  case SC_WID_UNO_CELLSTYL:
2435  {
2436  OUString aStyleName;
2438  if (pStyle)
2439  aStyleName = pStyle->GetName();
2441  aStyleName, SfxStyleFamily::Para );
2442  }
2443  break;
2444  case SC_WID_UNO_TBLBORD:
2445  case SC_WID_UNO_TBLBORD2:
2446  {
2448  if ( !aRanges.empty() )
2449  {
2450  const ScRange & rFirst = aRanges[ 0 ];
2451  SvxBoxItem aOuter(ATTR_BORDER);
2453 
2454  ScDocument& rDoc = pDocShell->GetDocument();
2455  ScMarkData aMark(rDoc.GetSheetLimits());
2456  aMark.SetMarkArea( rFirst );
2457  aMark.SelectTable( rFirst.aStart.Tab(), true );
2458  rDoc.GetSelectionFrame( aMark, aOuter, aInner );
2459 
2460  if (pEntry->nWID == SC_WID_UNO_TBLBORD2)
2461  ScHelperFunctions::AssignTableBorder2ToAny( rAny, aOuter, aInner);
2462  else
2463  ScHelperFunctions::AssignTableBorderToAny( rAny, aOuter, aInner);
2464  }
2465  }
2466  break;
2467  case SC_WID_UNO_CONDFMT:
2468  case SC_WID_UNO_CONDLOC:
2469  case SC_WID_UNO_CONDXML:
2470  {
2471  const ScPatternAttr* pPattern = GetCurrentAttrsDeep();
2472  if ( pPattern )
2473  {
2474  ScDocument& rDoc = pDocShell->GetDocument();
2475  bool bEnglish = ( pEntry->nWID != SC_WID_UNO_CONDLOC );
2476  bool bXML = ( pEntry->nWID == SC_WID_UNO_CONDXML );
2477  formula::FormulaGrammar::Grammar eGrammar = (bXML ?
2478  rDoc.GetStorageGrammar() :
2479  formula::FormulaGrammar::mapAPItoGrammar( bEnglish, bXML));
2480  const ScCondFormatIndexes& rIndex =
2481  pPattern->GetItem(ATTR_CONDITIONAL).GetCondFormatData();
2482  sal_uLong nIndex = 0;
2483  if(!rIndex.empty())
2484  nIndex = rIndex[0];
2485  rAny <<= uno::Reference<sheet::XSheetConditionalEntries>(
2486  new ScTableConditionalFormat( &rDoc, nIndex, aRanges.front().aStart.Tab(), eGrammar ));
2487  }
2488  }
2489  break;
2490  case SC_WID_UNO_VALIDAT:
2491  case SC_WID_UNO_VALILOC:
2492  case SC_WID_UNO_VALIXML:
2493  {
2494  const ScPatternAttr* pPattern = GetCurrentAttrsDeep();
2495  if ( pPattern )
2496  {
2497  ScDocument& rDoc = pDocShell->GetDocument();
2498  bool bEnglish = ( pEntry->nWID != SC_WID_UNO_VALILOC );
2499  bool bXML = ( pEntry->nWID == SC_WID_UNO_VALIXML );
2500  formula::FormulaGrammar::Grammar eGrammar = (bXML ?
2501  rDoc.GetStorageGrammar() :
2502  formula::FormulaGrammar::mapAPItoGrammar( bEnglish, bXML));
2503  sal_uLong nIndex =
2504  pPattern->GetItem(ATTR_VALIDDATA).GetValue();
2505  rAny <<= uno::Reference<beans::XPropertySet>(
2506  new ScTableValidationObj( rDoc, nIndex, eGrammar ));
2507  }
2508  }
2509  break;
2510  case SC_WID_UNO_NUMRULES:
2511  {
2512  // always return empty numbering rules object
2514  }
2515  break;
2516  case SC_WID_UNO_ABSNAME:
2517  {
2518  OUString sRet;
2520  rAny <<= sRet;
2521  }
2522  break;
2523  case SC_WID_UNO_FORMATID:
2524  {
2525  const ScPatternAttr* pPattern = GetCurrentAttrsFlat();
2526  rAny <<= pPattern->GetKey();
2527  }
2528  break;
2529  }
2530 }
2531 
2532 void SAL_CALL ScCellRangesBase::addPropertyChangeListener( const OUString& /* aPropertyName */,
2533  const uno::Reference<beans::XPropertyChangeListener>& /* aListener */)
2534 {
2535  SolarMutexGuard aGuard;
2536  if ( aRanges.empty() )
2537  throw uno::RuntimeException();
2538 
2539  OSL_FAIL("not implemented");
2540 }
2541 
2542 void SAL_CALL ScCellRangesBase::removePropertyChangeListener( const OUString& /* aPropertyName */,
2543  const uno::Reference<beans::XPropertyChangeListener>& /* aListener */)
2544 {
2545  SolarMutexGuard aGuard;
2546  if ( aRanges.empty() )
2547  throw uno::RuntimeException();
2548 
2549  OSL_FAIL("not implemented");
2550 }
2551 
2552 void SAL_CALL ScCellRangesBase::addVetoableChangeListener( const OUString&,
2553  const uno::Reference<beans::XVetoableChangeListener>&)
2554 {
2555  OSL_FAIL("not implemented");
2556 }
2557 
2558 void SAL_CALL ScCellRangesBase::removeVetoableChangeListener( const OUString&,
2559  const uno::Reference<beans::XVetoableChangeListener>&)
2560 {
2561  OSL_FAIL("not implemented");
2562 }
2563 
2564 // XMultiPropertySet
2565 
2566 void SAL_CALL ScCellRangesBase::setPropertyValues( const uno::Sequence< OUString >& aPropertyNames,
2567  const uno::Sequence< uno::Any >& aValues )
2568 {
2569  SolarMutexGuard aGuard;
2570 
2571  sal_Int32 nCount(aPropertyNames.getLength());
2572  sal_Int32 nValues(aValues.getLength());
2573  if (nCount != nValues)
2574  throw lang::IllegalArgumentException();
2575 
2576  if ( !(pDocShell && nCount) )
2577  return;
2578 
2579  const SfxItemPropertyMap& rPropertyMap = GetItemPropertyMap(); // from derived class
2580  const OUString* pNames = aPropertyNames.getConstArray();
2581  const uno::Any* pValues = aValues.getConstArray();
2582 
2583  std::unique_ptr<const SfxItemPropertySimpleEntry*[]> pEntryArray(new const SfxItemPropertySimpleEntry*[nCount]);
2584 
2585  sal_Int32 i;
2586  for(i = 0; i < nCount; i++)
2587  {
2588  // first loop: find all properties in map, but handle only CellStyle
2589  // (CellStyle must be set before any other cell properties)
2590 
2591  const SfxItemPropertySimpleEntry* pEntry = rPropertyMap.getByName( pNames[i] );
2592  pEntryArray[i] = pEntry;
2593  if (pEntry)
2594  {
2595  if ( pEntry->nWID == SC_WID_UNO_CELLSTYL )
2596  {
2597  try
2598  {
2599  SetOnePropertyValue( pEntry, pValues[i] );
2600  }
2601  catch ( lang::IllegalArgumentException& )
2602  {
2603  TOOLS_WARN_EXCEPTION( "sc", "exception when setting cell style"); // not supposed to happen
2604  }
2605  }
2606  }
2607  }
2608 
2609  ScDocument& rDoc = pDocShell->GetDocument();
2610  std::unique_ptr<ScPatternAttr> pOldPattern;
2611  std::unique_ptr<ScPatternAttr> pNewPattern;
2612 
2613  for(i = 0; i < nCount; i++)
2614  {
2615  // second loop: handle other properties
2616 
2617  const SfxItemPropertySimpleEntry* pEntry = pEntryArray[i];
2618  if ( pEntry )
2619  {
2620  if ( IsScItemWid( pEntry->nWID ) ) // can be handled by SfxItemPropertySet
2621  {
2622  if ( !pOldPattern )
2623  {
2624  pOldPattern.reset(new ScPatternAttr( *GetCurrentAttrsDeep() ));
2625  pOldPattern->GetItemSet().ClearInvalidItems();
2626  pNewPattern.reset(new ScPatternAttr( rDoc.GetPool() ));
2627  }
2628 
2629  // collect items in pNewPattern, apply with one call after the loop
2630 
2631  sal_uInt16 nFirstItem, nSecondItem;
2632  lcl_SetCellProperty( *pEntry, pValues[i], *pOldPattern, rDoc, nFirstItem, nSecondItem );
2633 
2634  // put only affected items into new set
2635  if ( nFirstItem )
2636  pNewPattern->GetItemSet().Put( pOldPattern->GetItemSet().Get( nFirstItem ) );
2637  if ( nSecondItem )
2638  pNewPattern->GetItemSet().Put( pOldPattern->GetItemSet().Get( nSecondItem ) );
2639  }
2640  else if ( pEntry->nWID != SC_WID_UNO_CELLSTYL ) // CellStyle is handled above
2641  {
2642  // call virtual method to set a single property
2643  SetOnePropertyValue( pEntry, pValues[i] );
2644  }
2645  }
2646  }
2647 
2648  if ( pNewPattern && !aRanges.empty() )
2649  pDocShell->GetDocFunc().ApplyAttributes( *GetMarkData(), *pNewPattern, true );
2650 }
2651 
2652 uno::Sequence<uno::Any> SAL_CALL ScCellRangesBase::getPropertyValues(
2653  const uno::Sequence< OUString >& aPropertyNames )
2654 {
2655  SolarMutexGuard aGuard;
2656 
2657  const SfxItemPropertyMap& rPropertyMap = GetItemPropertyMap(); // from derived class
2658 
2659  uno::Sequence<uno::Any> aRet(aPropertyNames.getLength());
2660  uno::Any* pProperties = aRet.getArray();
2661  for(sal_Int32 i = 0; i < aPropertyNames.getLength(); i++)
2662  {
2663  const SfxItemPropertySimpleEntry* pEntry = rPropertyMap.getByName( aPropertyNames[i] );
2664  GetOnePropertyValue( pEntry, pProperties[i] );
2665  }
2666  return aRet;
2667 }
2668 
2669 void SAL_CALL ScCellRangesBase::addPropertiesChangeListener( const uno::Sequence< OUString >& /* aPropertyNames */,
2670  const uno::Reference< beans::XPropertiesChangeListener >& /* xListener */ )
2671 {
2672  OSL_FAIL("not implemented");
2673 }
2674 
2675 void SAL_CALL ScCellRangesBase::removePropertiesChangeListener( const uno::Reference< beans::XPropertiesChangeListener >& /* xListener */ )
2676 {
2677  OSL_FAIL("not implemented");
2678 }
2679 
2680 void SAL_CALL ScCellRangesBase::firePropertiesChangeEvent( const uno::Sequence< OUString >& /* aPropertyNames */,
2681  const uno::Reference< beans::XPropertiesChangeListener >& /* xListener */ )
2682 {
2683  OSL_FAIL("not implemented");
2684 }
2685 
2686 IMPL_LINK( ScCellRangesBase, ValueListenerHdl, const SfxHint&, rHint, void )
2687 {
2688  if ( pDocShell && (rHint.GetId() == SfxHintId::ScDataChanged))
2689  {
2690  // This may be called several times for a single change, if several formulas
2691  // in the range are notified. So only a flag is set that is checked when
2692  // SfxHintId::DataChanged is received.
2693 
2694  bGotDataChangedHint = true;
2695  }
2696 }
2697 
2698 // XTolerantMultiPropertySet