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