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