xref: /core/sc/source/ui/unoobj/cellsuno.cxx (revision 1c027848)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <scitems.hxx>
21 #include <editeng/eeitem.hxx>
22 #include <o3tl/safeint.hxx>
23 #include <svx/svdpool.hxx>
24 
25 #include <vcl/svapp.hxx>
26 #include <svx/algitem.hxx>
27 #include <editeng/borderline.hxx>
28 #include <editeng/boxitem.hxx>
29 #include <editeng/editeng.hxx>
30 #include <editeng/flditem.hxx>
31 #include <editeng/editobj.hxx>
32 #include <editeng/unoipset.hxx>
33 #include <editeng/langitem.hxx>
34 #include <sfx2/linkmgr.hxx>
35 #include <svl/srchitem.hxx>
36 #include <svl/sharedstringpool.hxx>
37 #include <svx/unomid.hxx>
38 #include <editeng/unoprnms.hxx>
39 #include <editeng/unotext.hxx>
40 #include <svx/svdpage.hxx>
41 #include <sfx2/bindings.hxx>
42 #include <svl/zforlist.hxx>
43 #include <svl/zformat.hxx>
44 #include <cppuhelper/supportsservice.hxx>
45 #include <float.h>
46 #include <tools/diagnose_ex.h>
47 #include <tools/UnitConversion.hxx>
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>
125 #include <editeng/escapementitem.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!
160 //! Instead of Which-ID 0 use special IDs and do not compare via names!
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 
165 static const SfxItemPropertySet* lcl_GetCellsPropertySet()
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 },
170         {u"" SC_UNONAME_ASIANVERT,ATTR_VERTICAL_ASIAN,cppu::UnoType<bool>::get(),                  0, 0 },
171         {u"" SC_UNONAME_BOTTBORDER,ATTR_BORDER,       ::cppu::UnoType<table::BorderLine>::get(), 0, BOTTOM_BORDER | CONVERT_TWIPS },
172         {u"" SC_UNONAME_BOTTBORDER2,ATTR_BORDER,      ::cppu::UnoType<table::BorderLine2>::get(), 0, BOTTOM_BORDER | CONVERT_TWIPS },
173         {u"" SC_UNONAME_CELLBACK, ATTR_BACKGROUND,    cppu::UnoType<sal_Int32>::get(),            0, MID_BACK_COLOR },
174         {u"" SC_UNONAME_CELLPRO,  ATTR_PROTECTION,    cppu::UnoType<util::CellProtection>::get(), 0, 0 },
175         {u"" SC_UNONAME_CELLSTYL, SC_WID_UNO_CELLSTYL,cppu::UnoType<OUString>::get(),        0, 0 },
176         {u"" SC_UNONAME_CCOLOR,   ATTR_FONT_COLOR,    cppu::UnoType<sal_Int32>::get(),            0, 0 },
177         {u"" SC_UNONAME_COUTL,    ATTR_FONT_CONTOUR,  cppu::UnoType<bool>::get(),                  0, 0 },
178         {u"" SC_UNONAME_CCROSS,   ATTR_FONT_CROSSEDOUT,cppu::UnoType<bool>::get(),                 0, MID_CROSSED_OUT },
179         {u"" SC_UNONAME_CEMPHAS,  ATTR_FONT_EMPHASISMARK,cppu::UnoType<sal_Int16>::get(),         0, MID_EMPHASIS },
180         {u"" SC_UNONAME_CFONT,    ATTR_FONT,          cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_FAMILY },
181         {u"" SC_UNONAME_CFCHARS,  ATTR_FONT,          cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_CHAR_SET },
182         {u"" SC_UNO_CJK_CFCHARS,  ATTR_CJK_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_CHAR_SET },
183         {u"" SC_UNO_CTL_CFCHARS,  ATTR_CTL_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_CHAR_SET },
184         {u"" SC_UNONAME_CFFAMIL,  ATTR_FONT,          cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_FAMILY },
185         {u"" SC_UNO_CJK_CFFAMIL,  ATTR_CJK_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_FAMILY },
186         {u"" SC_UNO_CTL_CFFAMIL,  ATTR_CTL_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_FAMILY },
187         {u"" SC_UNONAME_CFNAME,   ATTR_FONT,          cppu::UnoType<OUString>::get(),        0, MID_FONT_FAMILY_NAME },
188         {u"" SC_UNO_CJK_CFNAME,   ATTR_CJK_FONT,      cppu::UnoType<OUString>::get(),        0, MID_FONT_FAMILY_NAME },
189         {u"" SC_UNO_CTL_CFNAME,   ATTR_CTL_FONT,      cppu::UnoType<OUString>::get(),        0, MID_FONT_FAMILY_NAME },
190         {u"" SC_UNONAME_CFPITCH,  ATTR_FONT,          cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_PITCH },
191         {u"" SC_UNO_CJK_CFPITCH,  ATTR_CJK_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_PITCH },
192         {u"" SC_UNO_CTL_CFPITCH,  ATTR_CTL_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_PITCH },
193         {u"" SC_UNONAME_CFSTYLE,  ATTR_FONT,          cppu::UnoType<OUString>::get(),        0, MID_FONT_STYLE_NAME },
194         {u"" SC_UNO_CJK_CFSTYLE,  ATTR_CJK_FONT,      cppu::UnoType<OUString>::get(),        0, MID_FONT_STYLE_NAME },
195         {u"" SC_UNO_CTL_CFSTYLE,  ATTR_CTL_FONT,      cppu::UnoType<OUString>::get(),        0, MID_FONT_STYLE_NAME },
196         {u"" SC_UNONAME_CHEIGHT,  ATTR_FONT_HEIGHT,   cppu::UnoType<float>::get(),                0, MID_FONTHEIGHT | CONVERT_TWIPS },
197         {u"" SC_UNO_CJK_CHEIGHT,  ATTR_CJK_FONT_HEIGHT,cppu::UnoType<float>::get(),               0, MID_FONTHEIGHT | CONVERT_TWIPS },
198         {u"" SC_UNO_CTL_CHEIGHT,  ATTR_CTL_FONT_HEIGHT,cppu::UnoType<float>::get(),               0, MID_FONTHEIGHT | CONVERT_TWIPS },
199         {u"" SC_UNONAME_CLOCAL,   ATTR_FONT_LANGUAGE, cppu::UnoType<lang::Locale>::get(),         0, MID_LANG_LOCALE },
200         {u"" SC_UNO_CJK_CLOCAL,   ATTR_CJK_FONT_LANGUAGE,cppu::UnoType<lang::Locale>::get(),          0, MID_LANG_LOCALE },
201         {u"" SC_UNO_CTL_CLOCAL,   ATTR_CTL_FONT_LANGUAGE,cppu::UnoType<lang::Locale>::get(),          0, MID_LANG_LOCALE },
202         {u"" SC_UNONAME_COVER,    ATTR_FONT_OVERLINE, cppu::UnoType<sal_Int16>::get(),            0, MID_TL_STYLE },
203         {u"" SC_UNONAME_COVRLCOL, ATTR_FONT_OVERLINE, cppu::UnoType<sal_Int32>::get(),            0, MID_TL_COLOR },
204         {u"" SC_UNONAME_COVRLHAS, ATTR_FONT_OVERLINE, cppu::UnoType<bool>::get(),                  0, MID_TL_HASCOLOR },
205         {u"" SC_UNONAME_CPOST,    ATTR_FONT_POSTURE,  cppu::UnoType<awt::FontSlant>::get(),       0, MID_POSTURE },
206         {u"" SC_UNO_CJK_CPOST,    ATTR_CJK_FONT_POSTURE,cppu::UnoType<awt::FontSlant>::get(),     0, MID_POSTURE },
207         {u"" SC_UNO_CTL_CPOST,    ATTR_CTL_FONT_POSTURE,cppu::UnoType<awt::FontSlant>::get(),     0, MID_POSTURE },
208         {u"" SC_UNONAME_CRELIEF,  ATTR_FONT_RELIEF,   cppu::UnoType<sal_Int16>::get(),            0, MID_RELIEF },
209         {u"" SC_UNONAME_CSHADD,   ATTR_FONT_SHADOWED, cppu::UnoType<bool>::get(),                  0, 0 },
210         {u"" SC_UNONAME_CSTRIKE,  ATTR_FONT_CROSSEDOUT,cppu::UnoType<sal_Int16>::get(),           0, MID_CROSS_OUT },
211         {u"" SC_UNONAME_CUNDER,   ATTR_FONT_UNDERLINE,cppu::UnoType<sal_Int16>::get(),            0, MID_TL_STYLE },
212         {u"" SC_UNONAME_CUNDLCOL, ATTR_FONT_UNDERLINE,cppu::UnoType<sal_Int32>::get(),            0, MID_TL_COLOR },
213         {u"" SC_UNONAME_CUNDLHAS, ATTR_FONT_UNDERLINE,cppu::UnoType<bool>::get(),                  0, MID_TL_HASCOLOR },
214         {u"" SC_UNONAME_CWEIGHT,  ATTR_FONT_WEIGHT,   cppu::UnoType<float>::get(),                0, MID_WEIGHT },
215         {u"" SC_UNO_CJK_CWEIGHT,  ATTR_CJK_FONT_WEIGHT,cppu::UnoType<float>::get(),               0, MID_WEIGHT },
216         {u"" SC_UNO_CTL_CWEIGHT,  ATTR_CTL_FONT_WEIGHT,cppu::UnoType<float>::get(),               0, MID_WEIGHT },
217         {u"" SC_UNONAME_CWORDMOD, ATTR_FONT_WORDLINE, cppu::UnoType<bool>::get(),                  0, 0 },
218         {u"" SC_UNONAME_CHCOLHDR, SC_WID_UNO_CHCOLHDR,cppu::UnoType<bool>::get(),                  0, 0 },
219         {u"" SC_UNONAME_CHROWHDR, SC_WID_UNO_CHROWHDR,cppu::UnoType<bool>::get(),                  0, 0 },
220         {u"" SC_UNONAME_CONDFMT,  SC_WID_UNO_CONDFMT, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
221         {u"" SC_UNONAME_CONDLOC,  SC_WID_UNO_CONDLOC, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
222         {u"" SC_UNONAME_CONDXML,  SC_WID_UNO_CONDXML, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
223         {u"" SC_UNONAME_DIAGONAL_BLTR, ATTR_BORDER_BLTR, ::cppu::UnoType<table::BorderLine>::get(), 0, 0 | CONVERT_TWIPS },
224         {u"" SC_UNONAME_DIAGONAL_BLTR2, ATTR_BORDER_BLTR, ::cppu::UnoType<table::BorderLine2>::get(), 0, 0 | CONVERT_TWIPS },
225         {u"" SC_UNONAME_DIAGONAL_TLBR, ATTR_BORDER_TLBR, ::cppu::UnoType<table::BorderLine>::get(), 0, 0 | CONVERT_TWIPS },
226         {u"" SC_UNONAME_DIAGONAL_TLBR2, ATTR_BORDER_TLBR, ::cppu::UnoType<table::BorderLine2>::get(), 0, 0 | CONVERT_TWIPS },
227         {u"" SC_UNONAME_CELLHJUS, ATTR_HOR_JUSTIFY,   cppu::UnoType<table::CellHoriJustify>::get(), 0, MID_HORJUST_HORJUST },
228         {u"" SC_UNONAME_CELLHJUS_METHOD, ATTR_HOR_JUSTIFY_METHOD, ::cppu::UnoType<sal_Int32>::get(),   0, 0 },
229         {u"" SC_UNONAME_CELLTRAN, ATTR_BACKGROUND,    cppu::UnoType<bool>::get(),                  0, MID_GRAPHIC_TRANSPARENT },
230         {u"" SC_UNONAME_WRAP,     ATTR_LINEBREAK,     cppu::UnoType<bool>::get(),                  0, 0 },
231         {u"" SC_UNONAME_LEFTBORDER,ATTR_BORDER,       ::cppu::UnoType<table::BorderLine>::get(), 0, LEFT_BORDER | CONVERT_TWIPS },
232         {u"" SC_UNONAME_LEFTBORDER2,ATTR_BORDER,      ::cppu::UnoType<table::BorderLine2>::get(), 0, LEFT_BORDER | CONVERT_TWIPS },
233         {u"" SC_UNONAME_NUMFMT,   ATTR_VALUE_FORMAT,  cppu::UnoType<sal_Int32>::get(),            0, 0 },
234         {u"" SC_UNONAME_NUMRULES, SC_WID_UNO_NUMRULES,cppu::UnoType<container::XIndexReplace>::get(), 0, 0 },
235         {u"" SC_UNONAME_CELLORI,  ATTR_STACKED,       cppu::UnoType<table::CellOrientation>::get(), 0, 0 },
236         {u"" SC_UNONAME_PADJUST,  ATTR_HOR_JUSTIFY,   ::cppu::UnoType<sal_Int16>::get(),    0, MID_HORJUST_ADJUST },
237         {u"" SC_UNONAME_PBMARGIN, ATTR_MARGIN,        cppu::UnoType<sal_Int32>::get(),            0, MID_MARGIN_LO_MARGIN | CONVERT_TWIPS },
238         {u"" SC_UNONAME_PINDENT,  ATTR_INDENT,        cppu::UnoType<sal_Int16>::get(),            0, 0 }, //! CONVERT_TWIPS
239         {u"" SC_UNONAME_PISCHDIST,ATTR_SCRIPTSPACE,   cppu::UnoType<bool>::get(),                  0, 0 },
240         {u"" SC_UNONAME_PISFORBID,ATTR_FORBIDDEN_RULES,cppu::UnoType<bool>::get(),                 0, 0 },
241         {u"" SC_UNONAME_PISHANG,  ATTR_HANGPUNCTUATION,cppu::UnoType<bool>::get(),                 0, 0 },
242         {u"" SC_UNONAME_PISHYPHEN,ATTR_HYPHENATE,     cppu::UnoType<bool>::get(),                  0, 0 },
243         {u"" SC_UNONAME_PLASTADJ, ATTR_HOR_JUSTIFY,   ::cppu::UnoType<sal_Int16>::get(),    0, MID_HORJUST_ADJUST },
244         {u"" SC_UNONAME_PLMARGIN, ATTR_MARGIN,        cppu::UnoType<sal_Int32>::get(),            0, MID_MARGIN_L_MARGIN  | CONVERT_TWIPS },
245         {u"" SC_UNONAME_PRMARGIN, ATTR_MARGIN,        cppu::UnoType<sal_Int32>::get(),            0, MID_MARGIN_R_MARGIN  | CONVERT_TWIPS },
246         {u"" SC_UNONAME_PTMARGIN, ATTR_MARGIN,        cppu::UnoType<sal_Int32>::get(),            0, MID_MARGIN_UP_MARGIN | CONVERT_TWIPS },
247         {u"" SC_UNONAME_RIGHTBORDER,ATTR_BORDER,      ::cppu::UnoType<table::BorderLine>::get(), 0, RIGHT_BORDER | CONVERT_TWIPS },
248         {u"" SC_UNONAME_RIGHTBORDER2,ATTR_BORDER,     ::cppu::UnoType<table::BorderLine2>::get(), 0, RIGHT_BORDER | CONVERT_TWIPS },
249         {u"" SC_UNONAME_ROTANG,   ATTR_ROTATE_VALUE,  cppu::UnoType<sal_Int32>::get(),            0, 0 },
250         {u"" SC_UNONAME_ROTREF,   ATTR_ROTATE_MODE,   cppu::UnoType<sal_Int32>::get(), 0, 0 },
251         {u"" SC_UNONAME_SHADOW,   ATTR_SHADOW,        cppu::UnoType<table::ShadowFormat>::get(),  0, 0 | CONVERT_TWIPS },
252         {u"" SC_UNONAME_SHRINK_TO_FIT, ATTR_SHRINKTOFIT, cppu::UnoType<bool>::get(),               0, 0 },
253         {u"" SC_UNONAME_TBLBORD,  SC_WID_UNO_TBLBORD, cppu::UnoType<table::TableBorder>::get(),   0, 0 | CONVERT_TWIPS },
254         {u"" SC_UNONAME_TBLBORD2,  SC_WID_UNO_TBLBORD2, cppu::UnoType<table::TableBorder2>::get(),   0, 0 | CONVERT_TWIPS },
255         {u"" SC_UNONAME_TOPBORDER,ATTR_BORDER,        ::cppu::UnoType<table::BorderLine>::get(), 0, TOP_BORDER | CONVERT_TWIPS },
256         {u"" SC_UNONAME_TOPBORDER2,ATTR_BORDER,       ::cppu::UnoType<table::BorderLine2>::get(), 0, TOP_BORDER | CONVERT_TWIPS },
257         {u"" SC_UNONAME_USERDEF,  ATTR_USERDEF,       cppu::UnoType<container::XNameContainer>::get(), 0, 0 },
258         {u"" SC_UNONAME_VALIDAT,  SC_WID_UNO_VALIDAT, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
259         {u"" SC_UNONAME_VALILOC,  SC_WID_UNO_VALILOC, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
260         {u"" SC_UNONAME_VALIXML,  SC_WID_UNO_VALIXML, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
261         {u"" SC_UNONAME_CELLVJUS, ATTR_VER_JUSTIFY,   cppu::UnoType<sal_Int32>::get(), 0, 0 },
262         {u"" SC_UNONAME_CELLVJUS_METHOD, ATTR_VER_JUSTIFY_METHOD, ::cppu::UnoType<sal_Int32>::get(),   0, 0 },
263         {u"" SC_UNONAME_WRITING,  ATTR_WRITINGDIR,    cppu::UnoType<sal_Int16>::get(),            0, 0 },
264         {u"" SC_UNONAME_HYPERLINK,  ATTR_HYPERLINK, cppu::UnoType<OUString>::get(),        0, 0 },
265         {u"" SC_UNONAME_FORMATID,  SC_WID_UNO_FORMATID, cppu::UnoType<sal_uInt64>::get(),        0, 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 
275 static const SfxItemPropertySet* lcl_GetRangePropertySet()
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 },
280         {u"" SC_UNONAME_ASIANVERT,ATTR_VERTICAL_ASIAN,cppu::UnoType<bool>::get(),                  0, 0 },
281         {u"" SC_UNONAME_BOTTBORDER,ATTR_BORDER,       ::cppu::UnoType<table::BorderLine>::get(), 0, BOTTOM_BORDER | CONVERT_TWIPS },
282         {u"" SC_UNONAME_BOTTBORDER2,ATTR_BORDER,      ::cppu::UnoType<table::BorderLine2>::get(), 0, BOTTOM_BORDER | CONVERT_TWIPS },
283         {u"" SC_UNONAME_CELLBACK, ATTR_BACKGROUND,    cppu::UnoType<sal_Int32>::get(),            0, MID_BACK_COLOR },
284         {u"" SC_UNONAME_CELLPRO,  ATTR_PROTECTION,    cppu::UnoType<util::CellProtection>::get(), 0, 0 },
285         {u"" SC_UNONAME_CELLSTYL, SC_WID_UNO_CELLSTYL,cppu::UnoType<OUString>::get(),        0, 0 },
286         {u"" SC_UNONAME_CCOLOR,   ATTR_FONT_COLOR,    cppu::UnoType<sal_Int32>::get(),            0, 0 },
287         {u"" SC_UNONAME_COUTL,    ATTR_FONT_CONTOUR,  cppu::UnoType<bool>::get(),                  0, 0 },
288         {u"" SC_UNONAME_CCROSS,   ATTR_FONT_CROSSEDOUT,cppu::UnoType<bool>::get(),                 0, MID_CROSSED_OUT },
289         {u"" SC_UNONAME_CEMPHAS,  ATTR_FONT_EMPHASISMARK,cppu::UnoType<sal_Int16>::get(),         0, MID_EMPHASIS },
290         {u"" SC_UNONAME_CFONT,    ATTR_FONT,          cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_FAMILY },
291         {u"" SC_UNONAME_CFCHARS,  ATTR_FONT,          cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_CHAR_SET },
292         {u"" SC_UNO_CJK_CFCHARS,  ATTR_CJK_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_CHAR_SET },
293         {u"" SC_UNO_CTL_CFCHARS,  ATTR_CTL_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_CHAR_SET },
294         {u"" SC_UNONAME_CFFAMIL,  ATTR_FONT,          cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_FAMILY },
295         {u"" SC_UNO_CJK_CFFAMIL,  ATTR_CJK_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_FAMILY },
296         {u"" SC_UNO_CTL_CFFAMIL,  ATTR_CTL_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_FAMILY },
297         {u"" SC_UNONAME_CFNAME,   ATTR_FONT,          cppu::UnoType<OUString>::get(),        0, MID_FONT_FAMILY_NAME },
298         {u"" SC_UNO_CJK_CFNAME,   ATTR_CJK_FONT,      cppu::UnoType<OUString>::get(),        0, MID_FONT_FAMILY_NAME },
299         {u"" SC_UNO_CTL_CFNAME,   ATTR_CTL_FONT,      cppu::UnoType<OUString>::get(),        0, MID_FONT_FAMILY_NAME },
300         {u"" SC_UNONAME_CFPITCH,  ATTR_FONT,          cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_PITCH },
301         {u"" SC_UNO_CJK_CFPITCH,  ATTR_CJK_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_PITCH },
302         {u"" SC_UNO_CTL_CFPITCH,  ATTR_CTL_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_PITCH },
303         {u"" SC_UNONAME_CFSTYLE,  ATTR_FONT,          cppu::UnoType<OUString>::get(),        0, MID_FONT_STYLE_NAME },
304         {u"" SC_UNO_CJK_CFSTYLE,  ATTR_CJK_FONT,      cppu::UnoType<OUString>::get(),        0, MID_FONT_STYLE_NAME },
305         {u"" SC_UNO_CTL_CFSTYLE,  ATTR_CTL_FONT,      cppu::UnoType<OUString>::get(),        0, MID_FONT_STYLE_NAME },
306         {u"" SC_UNONAME_CHEIGHT,  ATTR_FONT_HEIGHT,   cppu::UnoType<float>::get(),                0, MID_FONTHEIGHT | CONVERT_TWIPS },
307         {u"" SC_UNO_CJK_CHEIGHT,  ATTR_CJK_FONT_HEIGHT,cppu::UnoType<float>::get(),               0, MID_FONTHEIGHT | CONVERT_TWIPS },
308         {u"" SC_UNO_CTL_CHEIGHT,  ATTR_CTL_FONT_HEIGHT,cppu::UnoType<float>::get(),               0, MID_FONTHEIGHT | CONVERT_TWIPS },
309         {u"" SC_UNONAME_CLOCAL,   ATTR_FONT_LANGUAGE, cppu::UnoType<lang::Locale>::get(),         0, MID_LANG_LOCALE },
310         {u"" SC_UNO_CJK_CLOCAL,   ATTR_CJK_FONT_LANGUAGE,cppu::UnoType<lang::Locale>::get(),          0, MID_LANG_LOCALE },
311         {u"" SC_UNO_CTL_CLOCAL,   ATTR_CTL_FONT_LANGUAGE,cppu::UnoType<lang::Locale>::get(),          0, MID_LANG_LOCALE },
312         {u"" SC_UNONAME_COVER,    ATTR_FONT_OVERLINE, cppu::UnoType<sal_Int16>::get(),            0, MID_TL_STYLE },
313         {u"" SC_UNONAME_COVRLCOL, ATTR_FONT_OVERLINE, cppu::UnoType<sal_Int32>::get(),            0, MID_TL_COLOR },
314         {u"" SC_UNONAME_COVRLHAS, ATTR_FONT_OVERLINE, cppu::UnoType<bool>::get(),                  0, MID_TL_HASCOLOR },
315         {u"" SC_UNONAME_CPOST,    ATTR_FONT_POSTURE,  cppu::UnoType<awt::FontSlant>::get(),       0, MID_POSTURE },
316         {u"" SC_UNO_CJK_CPOST,    ATTR_CJK_FONT_POSTURE,cppu::UnoType<awt::FontSlant>::get(),     0, MID_POSTURE },
317         {u"" SC_UNO_CTL_CPOST,    ATTR_CTL_FONT_POSTURE,cppu::UnoType<awt::FontSlant>::get(),     0, MID_POSTURE },
318         {u"" SC_UNONAME_CRELIEF,  ATTR_FONT_RELIEF,   cppu::UnoType<sal_Int16>::get(),            0, MID_RELIEF },
319         {u"" SC_UNONAME_CSHADD,   ATTR_FONT_SHADOWED, cppu::UnoType<bool>::get(),                  0, 0 },
320         {u"" SC_UNONAME_CSTRIKE,  ATTR_FONT_CROSSEDOUT,cppu::UnoType<sal_Int16>::get(),           0, MID_CROSS_OUT },
321         {u"" SC_UNONAME_CUNDER,   ATTR_FONT_UNDERLINE,cppu::UnoType<sal_Int16>::get(),            0, MID_TL_STYLE },
322         {u"" SC_UNONAME_CUNDLCOL, ATTR_FONT_UNDERLINE,cppu::UnoType<sal_Int32>::get(),            0, MID_TL_COLOR },
323         {u"" SC_UNONAME_CUNDLHAS, ATTR_FONT_UNDERLINE,cppu::UnoType<bool>::get(),                  0, MID_TL_HASCOLOR },
324         {u"" SC_UNONAME_CWEIGHT,  ATTR_FONT_WEIGHT,   cppu::UnoType<float>::get(),                0, MID_WEIGHT },
325         {u"" SC_UNO_CJK_CWEIGHT,  ATTR_CJK_FONT_WEIGHT,cppu::UnoType<float>::get(),               0, MID_WEIGHT },
326         {u"" SC_UNO_CTL_CWEIGHT,  ATTR_CTL_FONT_WEIGHT,cppu::UnoType<float>::get(),               0, MID_WEIGHT },
327         {u"" SC_UNONAME_CWORDMOD, ATTR_FONT_WORDLINE, cppu::UnoType<bool>::get(),                  0, 0 },
328         {u"" SC_UNONAME_CHCOLHDR, SC_WID_UNO_CHCOLHDR,cppu::UnoType<bool>::get(),                  0, 0 },
329         {u"" SC_UNONAME_CHROWHDR, SC_WID_UNO_CHROWHDR,cppu::UnoType<bool>::get(),                  0, 0 },
330         {u"" SC_UNONAME_CONDFMT,  SC_WID_UNO_CONDFMT, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
331         {u"" SC_UNONAME_CONDLOC,  SC_WID_UNO_CONDLOC, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
332         {u"" SC_UNONAME_CONDXML,  SC_WID_UNO_CONDXML, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
333         {u"" SC_UNONAME_DIAGONAL_BLTR, ATTR_BORDER_BLTR, ::cppu::UnoType<table::BorderLine>::get(), 0, 0 | CONVERT_TWIPS },
334         {u"" SC_UNONAME_DIAGONAL_BLTR2, ATTR_BORDER_BLTR, ::cppu::UnoType<table::BorderLine2>::get(), 0, 0 | CONVERT_TWIPS },
335         {u"" SC_UNONAME_DIAGONAL_TLBR, ATTR_BORDER_TLBR, ::cppu::UnoType<table::BorderLine>::get(), 0, 0 | CONVERT_TWIPS },
336         {u"" SC_UNONAME_DIAGONAL_TLBR2, ATTR_BORDER_TLBR, ::cppu::UnoType<table::BorderLine2>::get(), 0, 0 | CONVERT_TWIPS },
337         {u"" SC_UNONAME_CELLHJUS, ATTR_HOR_JUSTIFY,   cppu::UnoType<table::CellHoriJustify>::get(),   0, MID_HORJUST_HORJUST },
338         {u"" SC_UNONAME_CELLHJUS_METHOD, ATTR_HOR_JUSTIFY_METHOD, ::cppu::UnoType<sal_Int32>::get(),   0, 0 },
339         {u"" SC_UNONAME_CELLTRAN, ATTR_BACKGROUND,    cppu::UnoType<bool>::get(),                  0, MID_GRAPHIC_TRANSPARENT },
340         {u"" SC_UNONAME_WRAP,     ATTR_LINEBREAK,     cppu::UnoType<bool>::get(),                  0, 0 },
341         {u"" SC_UNONAME_LEFTBORDER,ATTR_BORDER,       ::cppu::UnoType<table::BorderLine>::get(), 0, LEFT_BORDER | CONVERT_TWIPS },
342         {u"" SC_UNONAME_LEFTBORDER2,ATTR_BORDER,      ::cppu::UnoType<table::BorderLine2>::get(), 0, LEFT_BORDER | CONVERT_TWIPS },
343         {u"" SC_UNONAME_NUMFMT,   ATTR_VALUE_FORMAT,  cppu::UnoType<sal_Int32>::get(),            0, 0 },
344         {u"" SC_UNONAME_NUMRULES, SC_WID_UNO_NUMRULES,cppu::UnoType<container::XIndexReplace>::get(), 0, 0 },
345         {u"" SC_UNONAME_CELLORI,  ATTR_STACKED,       cppu::UnoType<table::CellOrientation>::get(), 0, 0 },
346         {u"" SC_UNONAME_PADJUST,  ATTR_HOR_JUSTIFY,   ::cppu::UnoType<sal_Int16>::get(),    0, MID_HORJUST_ADJUST },
347         {u"" SC_UNONAME_PBMARGIN, ATTR_MARGIN,        cppu::UnoType<sal_Int32>::get(),            0, MID_MARGIN_LO_MARGIN | CONVERT_TWIPS },
348         {u"" SC_UNONAME_PINDENT,  ATTR_INDENT,        cppu::UnoType<sal_Int16>::get(),            0, 0 }, //! CONVERT_TWIPS
349         {u"" SC_UNONAME_PISCHDIST,ATTR_SCRIPTSPACE,   cppu::UnoType<bool>::get(),                  0, 0 },
350         {u"" SC_UNONAME_PISFORBID,ATTR_FORBIDDEN_RULES,cppu::UnoType<bool>::get(),                 0, 0 },
351         {u"" SC_UNONAME_PISHANG,  ATTR_HANGPUNCTUATION,cppu::UnoType<bool>::get(),                 0, 0 },
352         {u"" SC_UNONAME_PISHYPHEN,ATTR_HYPHENATE,     cppu::UnoType<bool>::get(),                  0, 0 },
353         {u"" SC_UNONAME_PLASTADJ, ATTR_HOR_JUSTIFY,   ::cppu::UnoType<sal_Int16>::get(),    0, MID_HORJUST_ADJUST },
354         {u"" SC_UNONAME_PLMARGIN, ATTR_MARGIN,        cppu::UnoType<sal_Int32>::get(),            0, MID_MARGIN_L_MARGIN  | CONVERT_TWIPS },
355         {u"" SC_UNONAME_PRMARGIN, ATTR_MARGIN,        cppu::UnoType<sal_Int32>::get(),            0, MID_MARGIN_R_MARGIN  | CONVERT_TWIPS },
356         {u"" SC_UNONAME_PTMARGIN, ATTR_MARGIN,        cppu::UnoType<sal_Int32>::get(),            0, MID_MARGIN_UP_MARGIN | CONVERT_TWIPS },
357         {u"" SC_UNONAME_POS,      SC_WID_UNO_POS,     cppu::UnoType<awt::Point>::get(),           0 | beans::PropertyAttribute::READONLY, 0 },
358         {u"" SC_UNONAME_RIGHTBORDER,ATTR_BORDER,      ::cppu::UnoType<table::BorderLine>::get(), 0, RIGHT_BORDER | CONVERT_TWIPS },
359         {u"" SC_UNONAME_RIGHTBORDER2,ATTR_BORDER,     ::cppu::UnoType<table::BorderLine2>::get(), 0, RIGHT_BORDER | CONVERT_TWIPS },
360         {u"" SC_UNONAME_ROTANG,   ATTR_ROTATE_VALUE,  cppu::UnoType<sal_Int32>::get(),            0, 0 },
361         {u"" SC_UNONAME_ROTREF,   ATTR_ROTATE_MODE,   cppu::UnoType<sal_Int32>::get(), 0, 0 },
362         {u"" SC_UNONAME_SHADOW,   ATTR_SHADOW,        cppu::UnoType<table::ShadowFormat>::get(),  0, 0 | CONVERT_TWIPS },
363         {u"" SC_UNONAME_SHRINK_TO_FIT, ATTR_SHRINKTOFIT, cppu::UnoType<bool>::get(),               0, 0 },
364         {u"" SC_UNONAME_SIZE,     SC_WID_UNO_SIZE,    cppu::UnoType<awt::Size>::get(),            0 | beans::PropertyAttribute::READONLY, 0 },
365         {u"" SC_UNONAME_TBLBORD,  SC_WID_UNO_TBLBORD, cppu::UnoType<table::TableBorder>::get(),   0, 0 | CONVERT_TWIPS },
366         {u"" SC_UNONAME_TBLBORD2,  SC_WID_UNO_TBLBORD2, cppu::UnoType<table::TableBorder2>::get(),   0, 0 | CONVERT_TWIPS },
367         {u"" SC_UNONAME_TOPBORDER,ATTR_BORDER,        ::cppu::UnoType<table::BorderLine>::get(), 0, TOP_BORDER | CONVERT_TWIPS },
368         {u"" SC_UNONAME_TOPBORDER2,ATTR_BORDER,       ::cppu::UnoType<table::BorderLine2>::get(), 0, TOP_BORDER | CONVERT_TWIPS },
369         {u"" SC_UNONAME_USERDEF,  ATTR_USERDEF,       cppu::UnoType<container::XNameContainer>::get(), 0, 0 },
370         {u"" SC_UNONAME_VALIDAT,  SC_WID_UNO_VALIDAT, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
371         {u"" SC_UNONAME_VALILOC,  SC_WID_UNO_VALILOC, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
372         {u"" SC_UNONAME_VALIXML,  SC_WID_UNO_VALIXML, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
373         {u"" SC_UNONAME_CELLVJUS, ATTR_VER_JUSTIFY,   cppu::UnoType<sal_Int32>::get(), 0, 0 },
374         {u"" SC_UNONAME_CELLVJUS_METHOD, ATTR_VER_JUSTIFY_METHOD, ::cppu::UnoType<sal_Int32>::get(),   0, 0 },
375         {u"" SC_UNONAME_WRITING,  ATTR_WRITINGDIR,    cppu::UnoType<sal_Int16>::get(),            0, 0 },
376         {u"" SC_UNONAME_FORMATID,  SC_WID_UNO_FORMATID, cppu::UnoType<sal_uInt64>::get(),        0, 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 
386 static const SfxItemPropertySet* lcl_GetCellPropertySet()
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 },
391         {u"" SC_UNONAME_ASIANVERT,ATTR_VERTICAL_ASIAN,cppu::UnoType<bool>::get(),                  0, 0 },
392         {u"" SC_UNONAME_BOTTBORDER,ATTR_BORDER,       ::cppu::UnoType<table::BorderLine>::get(), 0, BOTTOM_BORDER | CONVERT_TWIPS },
393         {u"" SC_UNONAME_BOTTBORDER2,ATTR_BORDER,      ::cppu::UnoType<table::BorderLine2>::get(), 0, BOTTOM_BORDER | CONVERT_TWIPS },
394         {u"" SC_UNONAME_CELLBACK, ATTR_BACKGROUND,    cppu::UnoType<sal_Int32>::get(),            0, MID_BACK_COLOR },
395         {u"" SC_UNONAME_CELLPRO,  ATTR_PROTECTION,    cppu::UnoType<util::CellProtection>::get(), 0, 0 },
396         {u"" SC_UNONAME_CELLSTYL, SC_WID_UNO_CELLSTYL,cppu::UnoType<OUString>::get(),        0, 0 },
397         {u"" SC_UNONAME_CCOLOR,   ATTR_FONT_COLOR,    cppu::UnoType<sal_Int32>::get(),            0, 0 },
398         {u"" SC_UNONAME_COUTL,    ATTR_FONT_CONTOUR,  cppu::UnoType<bool>::get(),                  0, 0 },
399         {u"" SC_UNONAME_CCROSS,   ATTR_FONT_CROSSEDOUT,cppu::UnoType<bool>::get(),                 0, MID_CROSSED_OUT },
400         {u"" SC_UNONAME_CEMPHAS,  ATTR_FONT_EMPHASISMARK,cppu::UnoType<sal_Int16>::get(),         0, MID_EMPHASIS },
401         {u"" SC_UNONAME_CFONT,    ATTR_FONT,          cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_FAMILY },
402         {u"" SC_UNONAME_CFCHARS,  ATTR_FONT,          cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_CHAR_SET },
403         {u"" SC_UNO_CJK_CFCHARS,  ATTR_CJK_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_CHAR_SET },
404         {u"" SC_UNO_CTL_CFCHARS,  ATTR_CTL_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_CHAR_SET },
405         {u"" SC_UNONAME_CFFAMIL,  ATTR_FONT,          cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_FAMILY },
406         {u"" SC_UNO_CJK_CFFAMIL,  ATTR_CJK_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_FAMILY },
407         {u"" SC_UNO_CTL_CFFAMIL,  ATTR_CTL_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_FAMILY },
408         {u"" SC_UNONAME_CFNAME,   ATTR_FONT,          cppu::UnoType<OUString>::get(),        0, MID_FONT_FAMILY_NAME },
409         {u"" SC_UNO_CJK_CFNAME,   ATTR_CJK_FONT,      cppu::UnoType<OUString>::get(),        0, MID_FONT_FAMILY_NAME },
410         {u"" SC_UNO_CTL_CFNAME,   ATTR_CTL_FONT,      cppu::UnoType<OUString>::get(),        0, MID_FONT_FAMILY_NAME },
411         {u"" SC_UNONAME_CFPITCH,  ATTR_FONT,          cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_PITCH },
412         {u"" SC_UNO_CJK_CFPITCH,  ATTR_CJK_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_PITCH },
413         {u"" SC_UNO_CTL_CFPITCH,  ATTR_CTL_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_PITCH },
414         {u"" SC_UNONAME_CFSTYLE,  ATTR_FONT,          cppu::UnoType<OUString>::get(),        0, MID_FONT_STYLE_NAME },
415         {u"" SC_UNO_CJK_CFSTYLE,  ATTR_CJK_FONT,      cppu::UnoType<OUString>::get(),        0, MID_FONT_STYLE_NAME },
416         {u"" SC_UNO_CTL_CFSTYLE,  ATTR_CTL_FONT,      cppu::UnoType<OUString>::get(),        0, MID_FONT_STYLE_NAME },
417         {u"" SC_UNONAME_CHEIGHT,  ATTR_FONT_HEIGHT,   cppu::UnoType<float>::get(),                0, MID_FONTHEIGHT | CONVERT_TWIPS },
418         {u"" SC_UNO_CJK_CHEIGHT,  ATTR_CJK_FONT_HEIGHT,cppu::UnoType<float>::get(),               0, MID_FONTHEIGHT | CONVERT_TWIPS },
419         {u"" SC_UNO_CTL_CHEIGHT,  ATTR_CTL_FONT_HEIGHT,cppu::UnoType<float>::get(),               0, MID_FONTHEIGHT | CONVERT_TWIPS },
420         {u"" SC_UNONAME_CLOCAL,   ATTR_FONT_LANGUAGE, cppu::UnoType<lang::Locale>::get(),         0, MID_LANG_LOCALE },
421         {u"" SC_UNO_CJK_CLOCAL,   ATTR_CJK_FONT_LANGUAGE,cppu::UnoType<lang::Locale>::get(),          0, MID_LANG_LOCALE },
422         {u"" SC_UNO_CTL_CLOCAL,   ATTR_CTL_FONT_LANGUAGE,cppu::UnoType<lang::Locale>::get(),          0, MID_LANG_LOCALE },
423         {u"" SC_UNONAME_COVER,    ATTR_FONT_OVERLINE, cppu::UnoType<sal_Int16>::get(),            0, MID_TL_STYLE },
424         {u"" SC_UNONAME_COVRLCOL, ATTR_FONT_OVERLINE, cppu::UnoType<sal_Int32>::get(),            0, MID_TL_COLOR },
425         {u"" SC_UNONAME_COVRLHAS, ATTR_FONT_OVERLINE, cppu::UnoType<bool>::get(),                  0, MID_TL_HASCOLOR },
426         {u"" SC_UNONAME_CPOST,    ATTR_FONT_POSTURE,  cppu::UnoType<awt::FontSlant>::get(),       0, MID_POSTURE },
427         {u"" SC_UNO_CJK_CPOST,    ATTR_CJK_FONT_POSTURE,cppu::UnoType<awt::FontSlant>::get(),     0, MID_POSTURE },
428         {u"" SC_UNO_CTL_CPOST,    ATTR_CTL_FONT_POSTURE,cppu::UnoType<awt::FontSlant>::get(),     0, MID_POSTURE },
429         {u"" SC_UNONAME_CRELIEF,  ATTR_FONT_RELIEF,   cppu::UnoType<sal_Int16>::get(),            0, MID_RELIEF },
430         {u"" SC_UNONAME_CSHADD,   ATTR_FONT_SHADOWED, cppu::UnoType<bool>::get(),                  0, 0 },
431         {u"" SC_UNONAME_CSTRIKE,  ATTR_FONT_CROSSEDOUT,cppu::UnoType<sal_Int16>::get(),           0, MID_CROSS_OUT },
432         {u"" SC_UNONAME_CUNDER,   ATTR_FONT_UNDERLINE,cppu::UnoType<sal_Int16>::get(),            0, MID_TL_STYLE },
433         {u"" SC_UNONAME_CUNDLCOL, ATTR_FONT_UNDERLINE,cppu::UnoType<sal_Int32>::get(),            0, MID_TL_COLOR },
434         {u"" SC_UNONAME_CUNDLHAS, ATTR_FONT_UNDERLINE,cppu::UnoType<bool>::get(),                  0, MID_TL_HASCOLOR },
435         {u"" SC_UNONAME_CWEIGHT,  ATTR_FONT_WEIGHT,   cppu::UnoType<float>::get(),                0, MID_WEIGHT },
436         {u"" SC_UNO_CJK_CWEIGHT,  ATTR_CJK_FONT_WEIGHT,cppu::UnoType<float>::get(),               0, MID_WEIGHT },
437         {u"" SC_UNO_CTL_CWEIGHT,  ATTR_CTL_FONT_WEIGHT,cppu::UnoType<float>::get(),               0, MID_WEIGHT },
438         {u"" SC_UNONAME_CWORDMOD, ATTR_FONT_WORDLINE, cppu::UnoType<bool>::get(),                  0, 0 },
439         {u"" SC_UNONAME_CHCOLHDR, SC_WID_UNO_CHCOLHDR,cppu::UnoType<bool>::get(),                  0, 0 },
440         {u"" SC_UNONAME_CHROWHDR, SC_WID_UNO_CHROWHDR,cppu::UnoType<bool>::get(),                  0, 0 },
441         {u"" SC_UNONAME_CONDFMT,  SC_WID_UNO_CONDFMT, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
442         {u"" SC_UNONAME_CONDLOC,  SC_WID_UNO_CONDLOC, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
443         {u"" SC_UNONAME_CONDXML,  SC_WID_UNO_CONDXML, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
444         {u"" SC_UNONAME_DIAGONAL_BLTR, ATTR_BORDER_BLTR, ::cppu::UnoType<table::BorderLine>::get(), 0, 0 | CONVERT_TWIPS },
445         {u"" SC_UNONAME_DIAGONAL_BLTR2, ATTR_BORDER_BLTR, ::cppu::UnoType<table::BorderLine2>::get(), 0, 0 | CONVERT_TWIPS },
446         {u"" SC_UNONAME_DIAGONAL_TLBR, ATTR_BORDER_TLBR, ::cppu::UnoType<table::BorderLine>::get(), 0, 0 | CONVERT_TWIPS },
447         {u"" SC_UNONAME_DIAGONAL_TLBR2, ATTR_BORDER_TLBR, ::cppu::UnoType<table::BorderLine2>::get(), 0, 0 | CONVERT_TWIPS },
448         {u"" SC_UNONAME_FORMLOC,  SC_WID_UNO_FORMLOC, cppu::UnoType<OUString>::get(),        0, 0 },
449         {u"" SC_UNONAME_FORMRT,   SC_WID_UNO_FORMRT,  cppu::UnoType<table::CellContentType>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
450         {u"" SC_UNONAME_CELLCONTENTTYPE,   SC_WID_UNO_CELLCONTENTTYPE,  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 },
452         {u"" SC_UNONAME_CELLHJUS, ATTR_HOR_JUSTIFY,   cppu::UnoType<table::CellHoriJustify>::get(), 0, MID_HORJUST_HORJUST },
453         {u"" SC_UNONAME_CELLHJUS_METHOD, ATTR_HOR_JUSTIFY_METHOD, ::cppu::UnoType<sal_Int32>::get(),   0, 0 },
454         {u"" SC_UNONAME_CELLTRAN, ATTR_BACKGROUND,    cppu::UnoType<bool>::get(),                  0, MID_GRAPHIC_TRANSPARENT },
455         {u"" SC_UNONAME_WRAP,     ATTR_LINEBREAK,     cppu::UnoType<bool>::get(),                  0, 0 },
456         {u"" SC_UNONAME_LEFTBORDER,ATTR_BORDER,       ::cppu::UnoType<table::BorderLine>::get(), 0, LEFT_BORDER | CONVERT_TWIPS },
457         {u"" SC_UNONAME_LEFTBORDER2,ATTR_BORDER,      ::cppu::UnoType<table::BorderLine2>::get(), 0, LEFT_BORDER | CONVERT_TWIPS },
458         {u"" SC_UNONAME_NUMFMT,   ATTR_VALUE_FORMAT,  cppu::UnoType<sal_Int32>::get(),            0, 0 },
459         {u"" SC_UNONAME_NUMRULES, SC_WID_UNO_NUMRULES,cppu::UnoType<container::XIndexReplace>::get(), 0, 0 },
460         {u"" SC_UNONAME_CELLORI,  ATTR_STACKED,       cppu::UnoType<table::CellOrientation>::get(), 0, 0 },
461         {u"" SC_UNONAME_PADJUST,  ATTR_HOR_JUSTIFY,   ::cppu::UnoType<sal_Int16>::get(),    0, MID_HORJUST_ADJUST },
462         {u"" SC_UNONAME_PBMARGIN, ATTR_MARGIN,        cppu::UnoType<sal_Int32>::get(),            0, MID_MARGIN_LO_MARGIN | CONVERT_TWIPS },
463         {u"" SC_UNONAME_PINDENT,  ATTR_INDENT,        cppu::UnoType<sal_Int16>::get(),            0, 0 }, //! CONVERT_TWIPS
464         {u"" SC_UNONAME_PISCHDIST,ATTR_SCRIPTSPACE,   cppu::UnoType<bool>::get(),                  0, 0 },
465         {u"" SC_UNONAME_PISFORBID,ATTR_FORBIDDEN_RULES,cppu::UnoType<bool>::get(),                 0, 0 },
466         {u"" SC_UNONAME_PISHANG,  ATTR_HANGPUNCTUATION,cppu::UnoType<bool>::get(),                 0, 0 },
467         {u"" SC_UNONAME_PISHYPHEN,ATTR_HYPHENATE,     cppu::UnoType<bool>::get(),                  0, 0 },
468         {u"" SC_UNONAME_PLASTADJ, ATTR_HOR_JUSTIFY,   ::cppu::UnoType<sal_Int16>::get(),    0, MID_HORJUST_ADJUST },
469         {u"" SC_UNONAME_PLMARGIN, ATTR_MARGIN,        cppu::UnoType<sal_Int32>::get(),            0, MID_MARGIN_L_MARGIN  | CONVERT_TWIPS },
470         {u"" SC_UNONAME_PRMARGIN, ATTR_MARGIN,        cppu::UnoType<sal_Int32>::get(),            0, MID_MARGIN_R_MARGIN  | CONVERT_TWIPS },
471         {u"" SC_UNONAME_PTMARGIN, ATTR_MARGIN,        cppu::UnoType<sal_Int32>::get(),            0, MID_MARGIN_UP_MARGIN | CONVERT_TWIPS },
472         {u"" SC_UNONAME_POS,      SC_WID_UNO_POS,     cppu::UnoType<awt::Point>::get(),           0 | beans::PropertyAttribute::READONLY, 0 },
473         {u"" SC_UNONAME_RIGHTBORDER,ATTR_BORDER,      ::cppu::UnoType<table::BorderLine>::get(), 0, RIGHT_BORDER | CONVERT_TWIPS },
474         {u"" SC_UNONAME_RIGHTBORDER2,ATTR_BORDER,     ::cppu::UnoType<table::BorderLine2>::get(), 0, RIGHT_BORDER | CONVERT_TWIPS },
475         {u"" SC_UNONAME_ROTANG,   ATTR_ROTATE_VALUE,  cppu::UnoType<sal_Int32>::get(),            0, 0 },
476         {u"" SC_UNONAME_ROTREF,   ATTR_ROTATE_MODE,   cppu::UnoType<sal_Int32>::get(), 0, 0 },
477         {u"" SC_UNONAME_SHADOW,   ATTR_SHADOW,        cppu::UnoType<table::ShadowFormat>::get(),  0, 0 | CONVERT_TWIPS },
478         {u"" SC_UNONAME_SHRINK_TO_FIT, ATTR_SHRINKTOFIT, cppu::UnoType<bool>::get(),               0, 0 },
479         {u"" SC_UNONAME_SIZE,     SC_WID_UNO_SIZE,    cppu::UnoType<awt::Size>::get(),            0 | beans::PropertyAttribute::READONLY, 0 },
480         {u"" SC_UNONAME_TBLBORD,  SC_WID_UNO_TBLBORD, cppu::UnoType<table::TableBorder>::get(),   0, 0 | CONVERT_TWIPS },
481         {u"" SC_UNONAME_TBLBORD2,  SC_WID_UNO_TBLBORD2, cppu::UnoType<table::TableBorder2>::get(),   0, 0 | CONVERT_TWIPS },
482         {u"" SC_UNONAME_TOPBORDER,ATTR_BORDER,        ::cppu::UnoType<table::BorderLine>::get(), 0, TOP_BORDER | CONVERT_TWIPS },
483         {u"" SC_UNONAME_TOPBORDER2,ATTR_BORDER,       ::cppu::UnoType<table::BorderLine2>::get(), 0, TOP_BORDER | CONVERT_TWIPS },
484         {u"" SC_UNONAME_USERDEF,  ATTR_USERDEF,       cppu::UnoType<container::XNameContainer>::get(), 0, 0 },
485         {u"" SC_UNONAME_VALIDAT,  SC_WID_UNO_VALIDAT, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
486         {u"" SC_UNONAME_VALILOC,  SC_WID_UNO_VALILOC, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
487         {u"" SC_UNONAME_VALIXML,  SC_WID_UNO_VALIXML, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
488         {u"" SC_UNONAME_CELLVJUS, ATTR_VER_JUSTIFY,   cppu::UnoType<sal_Int32>::get(), 0, 0 },
489         {u"" SC_UNONAME_CELLVJUS_METHOD, ATTR_VER_JUSTIFY_METHOD, ::cppu::UnoType<sal_Int32>::get(),   0, 0 },
490         {u"" SC_UNONAME_WRITING,  ATTR_WRITINGDIR,    cppu::UnoType<sal_Int16>::get(),            0, 0 },
491         {u"" UNO_NAME_EDIT_CHAR_ESCAPEMENT,   EE_CHAR_ESCAPEMENT, cppu::UnoType<sal_Int32>::get(),            0, 0 },
492         {u"" SC_UNONAME_HYPERLINK,  ATTR_HYPERLINK, cppu::UnoType<OUString>::get(),        0, 0 },
493         {u"" SC_UNONAME_FORMATID,  SC_WID_UNO_FORMATID, cppu::UnoType<sal_uInt64>::get(),        0, 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 
503 static const SfxItemPropertySet* lcl_GetColumnPropertySet()
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 },
508         {u"" SC_UNONAME_ASIANVERT,ATTR_VERTICAL_ASIAN,cppu::UnoType<bool>::get(),                  0, 0 },
509         {u"" SC_UNONAME_BOTTBORDER,ATTR_BORDER,       ::cppu::UnoType<table::BorderLine>::get(), 0, BOTTOM_BORDER | CONVERT_TWIPS },
510         {u"" SC_UNONAME_BOTTBORDER2,ATTR_BORDER,      ::cppu::UnoType<table::BorderLine2>::get(), 0, BOTTOM_BORDER | CONVERT_TWIPS },
511         {u"" SC_UNONAME_CELLBACK, ATTR_BACKGROUND,    cppu::UnoType<sal_Int32>::get(),            0, MID_BACK_COLOR },
512         {u"" SC_UNONAME_CELLPRO,  ATTR_PROTECTION,    cppu::UnoType<util::CellProtection>::get(), 0, 0 },
513         {u"" SC_UNONAME_CELLSTYL, SC_WID_UNO_CELLSTYL,cppu::UnoType<OUString>::get(),        0, 0 },
514         {u"" SC_UNONAME_CCOLOR,   ATTR_FONT_COLOR,    cppu::UnoType<sal_Int32>::get(),            0, 0 },
515         {u"" SC_UNONAME_COUTL,    ATTR_FONT_CONTOUR,  cppu::UnoType<bool>::get(),                  0, 0 },
516         {u"" SC_UNONAME_CCROSS,   ATTR_FONT_CROSSEDOUT,cppu::UnoType<bool>::get(),                 0, MID_CROSSED_OUT },
517         {u"" SC_UNONAME_CEMPHAS,  ATTR_FONT_EMPHASISMARK,cppu::UnoType<sal_Int16>::get(),         0, MID_EMPHASIS },
518         {u"" SC_UNONAME_CFONT,    ATTR_FONT,          cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_FAMILY },
519         {u"" SC_UNONAME_CFCHARS,  ATTR_FONT,          cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_CHAR_SET },
520         {u"" SC_UNO_CJK_CFCHARS,  ATTR_CJK_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_CHAR_SET },
521         {u"" SC_UNO_CTL_CFCHARS,  ATTR_CTL_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_CHAR_SET },
522         {u"" SC_UNONAME_CFFAMIL,  ATTR_FONT,          cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_FAMILY },
523         {u"" SC_UNO_CJK_CFFAMIL,  ATTR_CJK_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_FAMILY },
524         {u"" SC_UNO_CTL_CFFAMIL,  ATTR_CTL_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_FAMILY },
525         {u"" SC_UNONAME_CFNAME,   ATTR_FONT,          cppu::UnoType<OUString>::get(),        0, MID_FONT_FAMILY_NAME },
526         {u"" SC_UNO_CJK_CFNAME,   ATTR_CJK_FONT,      cppu::UnoType<OUString>::get(),        0, MID_FONT_FAMILY_NAME },
527         {u"" SC_UNO_CTL_CFNAME,   ATTR_CTL_FONT,      cppu::UnoType<OUString>::get(),        0, MID_FONT_FAMILY_NAME },
528         {u"" SC_UNONAME_CFPITCH,  ATTR_FONT,          cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_PITCH },
529         {u"" SC_UNO_CJK_CFPITCH,  ATTR_CJK_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_PITCH },
530         {u"" SC_UNO_CTL_CFPITCH,  ATTR_CTL_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_PITCH },
531         {u"" SC_UNONAME_CFSTYLE,  ATTR_FONT,          cppu::UnoType<OUString>::get(),        0, MID_FONT_STYLE_NAME },
532         {u"" SC_UNO_CJK_CFSTYLE,  ATTR_CJK_FONT,      cppu::UnoType<OUString>::get(),        0, MID_FONT_STYLE_NAME },
533         {u"" SC_UNO_CTL_CFSTYLE,  ATTR_CTL_FONT,      cppu::UnoType<OUString>::get(),        0, MID_FONT_STYLE_NAME },
534         {u"" SC_UNONAME_CHEIGHT,  ATTR_FONT_HEIGHT,   cppu::UnoType<float>::get(),                0, MID_FONTHEIGHT | CONVERT_TWIPS },
535         {u"" SC_UNO_CJK_CHEIGHT,  ATTR_CJK_FONT_HEIGHT,cppu::UnoType<float>::get(),               0, MID_FONTHEIGHT | CONVERT_TWIPS },
536         {u"" SC_UNO_CTL_CHEIGHT,  ATTR_CTL_FONT_HEIGHT,cppu::UnoType<float>::get(),               0, MID_FONTHEIGHT | CONVERT_TWIPS },
537         {u"" SC_UNONAME_CLOCAL,   ATTR_FONT_LANGUAGE, cppu::UnoType<lang::Locale>::get(),         0, MID_LANG_LOCALE },
538         {u"" SC_UNO_CJK_CLOCAL,   ATTR_CJK_FONT_LANGUAGE,cppu::UnoType<lang::Locale>::get(),          0, MID_LANG_LOCALE },
539         {u"" SC_UNO_CTL_CLOCAL,   ATTR_CTL_FONT_LANGUAGE,cppu::UnoType<lang::Locale>::get(),          0, MID_LANG_LOCALE },
540         {u"" SC_UNONAME_COVER,    ATTR_FONT_OVERLINE, cppu::UnoType<sal_Int16>::get(),            0, MID_TL_STYLE },
541         {u"" SC_UNONAME_COVRLCOL, ATTR_FONT_OVERLINE, cppu::UnoType<sal_Int32>::get(),            0, MID_TL_COLOR },
542         {u"" SC_UNONAME_COVRLHAS, ATTR_FONT_OVERLINE, cppu::UnoType<bool>::get(),                  0, MID_TL_HASCOLOR },
543         {u"" SC_UNONAME_CPOST,    ATTR_FONT_POSTURE,  cppu::UnoType<awt::FontSlant>::get(),       0, MID_POSTURE },
544         {u"" SC_UNO_CJK_CPOST,    ATTR_CJK_FONT_POSTURE,cppu::UnoType<awt::FontSlant>::get(),     0, MID_POSTURE },
545         {u"" SC_UNO_CTL_CPOST,    ATTR_CTL_FONT_POSTURE,cppu::UnoType<awt::FontSlant>::get(),     0, MID_POSTURE },
546         {u"" SC_UNONAME_CRELIEF,  ATTR_FONT_RELIEF,   cppu::UnoType<sal_Int16>::get(),            0, MID_RELIEF },
547         {u"" SC_UNONAME_CSHADD,   ATTR_FONT_SHADOWED, cppu::UnoType<bool>::get(),                  0, 0 },
548         {u"" SC_UNONAME_CSTRIKE,  ATTR_FONT_CROSSEDOUT,cppu::UnoType<sal_Int16>::get(),           0, MID_CROSS_OUT },
549         {u"" SC_UNONAME_CUNDER,   ATTR_FONT_UNDERLINE,cppu::UnoType<sal_Int16>::get(),            0, MID_TL_STYLE },
550         {u"" SC_UNONAME_CUNDLCOL, ATTR_FONT_UNDERLINE,cppu::UnoType<sal_Int32>::get(),            0, MID_TL_COLOR },
551         {u"" SC_UNONAME_CUNDLHAS, ATTR_FONT_UNDERLINE,cppu::UnoType<bool>::get(),                  0, MID_TL_HASCOLOR },
552         {u"" SC_UNONAME_CWEIGHT,  ATTR_FONT_WEIGHT,   cppu::UnoType<float>::get(),                0, MID_WEIGHT },
553         {u"" SC_UNO_CJK_CWEIGHT,  ATTR_CJK_FONT_WEIGHT,cppu::UnoType<float>::get(),               0, MID_WEIGHT },
554         {u"" SC_UNO_CTL_CWEIGHT,  ATTR_CTL_FONT_WEIGHT,cppu::UnoType<float>::get(),               0, MID_WEIGHT },
555         {u"" SC_UNONAME_CWORDMOD, ATTR_FONT_WORDLINE, cppu::UnoType<bool>::get(),                  0, 0 },
556         {u"" SC_UNONAME_CHCOLHDR, SC_WID_UNO_CHCOLHDR,cppu::UnoType<bool>::get(),                  0, 0 },
557         {u"" SC_UNONAME_CHROWHDR, SC_WID_UNO_CHROWHDR,cppu::UnoType<bool>::get(),                  0, 0 },
558         {u"" SC_UNONAME_CONDFMT,  SC_WID_UNO_CONDFMT, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
559         {u"" SC_UNONAME_CONDLOC,  SC_WID_UNO_CONDLOC, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
560         {u"" SC_UNONAME_CONDXML,  SC_WID_UNO_CONDXML, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
561         {u"" SC_UNONAME_DIAGONAL_BLTR, ATTR_BORDER_BLTR, ::cppu::UnoType<table::BorderLine>::get(), 0, 0 | CONVERT_TWIPS },
562         {u"" SC_UNONAME_DIAGONAL_BLTR2, ATTR_BORDER_BLTR, ::cppu::UnoType<table::BorderLine2>::get(), 0, 0 | CONVERT_TWIPS },
563         {u"" SC_UNONAME_DIAGONAL_TLBR, ATTR_BORDER_TLBR, ::cppu::UnoType<table::BorderLine>::get(), 0, 0 | CONVERT_TWIPS },
564         {u"" SC_UNONAME_DIAGONAL_TLBR2, ATTR_BORDER_TLBR, ::cppu::UnoType<table::BorderLine2>::get(), 0, 0 | CONVERT_TWIPS },
565         {u"" SC_UNONAME_CELLHJUS, ATTR_HOR_JUSTIFY,   cppu::UnoType<table::CellHoriJustify>::get(), 0, MID_HORJUST_HORJUST },
566         {u"" SC_UNONAME_CELLHJUS_METHOD, ATTR_HOR_JUSTIFY_METHOD, ::cppu::UnoType<sal_Int32>::get(),   0, 0 },
567         {u"" SC_UNONAME_CELLTRAN, ATTR_BACKGROUND,    cppu::UnoType<bool>::get(),                  0, MID_GRAPHIC_TRANSPARENT },
568         {u"" SC_UNONAME_MANPAGE,  SC_WID_UNO_MANPAGE, cppu::UnoType<bool>::get(),                  0, 0 },
569         {u"" SC_UNONAME_NEWPAGE,  SC_WID_UNO_NEWPAGE, cppu::UnoType<bool>::get(),                  0, 0 },
570         {u"" SC_UNONAME_WRAP,     ATTR_LINEBREAK,     cppu::UnoType<bool>::get(),                  0, 0 },
571         {u"" SC_UNONAME_CELLVIS,  SC_WID_UNO_CELLVIS, cppu::UnoType<bool>::get(),                  0, 0 },
572         {u"" SC_UNONAME_LEFTBORDER,ATTR_BORDER,       ::cppu::UnoType<table::BorderLine>::get(), 0, LEFT_BORDER | CONVERT_TWIPS },
573         {u"" SC_UNONAME_LEFTBORDER2,ATTR_BORDER,      ::cppu::UnoType<table::BorderLine2>::get(), 0, LEFT_BORDER | CONVERT_TWIPS },
574         {u"" SC_UNONAME_NUMFMT,   ATTR_VALUE_FORMAT,  cppu::UnoType<sal_Int32>::get(),            0, 0 },
575         {u"" SC_UNONAME_NUMRULES, SC_WID_UNO_NUMRULES,cppu::UnoType<container::XIndexReplace>::get(), 0, 0 },
576         {u"" SC_UNONAME_OWIDTH,   SC_WID_UNO_OWIDTH,  cppu::UnoType<bool>::get(),                  0, 0 },
577         {u"" SC_UNONAME_CELLORI,  ATTR_STACKED,       cppu::UnoType<table::CellOrientation>::get(), 0, 0 },
578         {u"" SC_UNONAME_PADJUST,  ATTR_HOR_JUSTIFY,   ::cppu::UnoType<sal_Int16>::get(),    0, MID_HORJUST_ADJUST },
579         {u"" SC_UNONAME_PBMARGIN, ATTR_MARGIN,        cppu::UnoType<sal_Int32>::get(),            0, MID_MARGIN_LO_MARGIN | CONVERT_TWIPS },
580         {u"" SC_UNONAME_PINDENT,  ATTR_INDENT,        cppu::UnoType<sal_Int16>::get(),            0, 0 }, //! CONVERT_TWIPS
581         {u"" SC_UNONAME_PISCHDIST,ATTR_SCRIPTSPACE,   cppu::UnoType<bool>::get(),                  0, 0 },
582         {u"" SC_UNONAME_PISFORBID,ATTR_FORBIDDEN_RULES,cppu::UnoType<bool>::get(),                 0, 0 },
583         {u"" SC_UNONAME_PISHANG,  ATTR_HANGPUNCTUATION,cppu::UnoType<bool>::get(),                 0, 0 },
584         {u"" SC_UNONAME_PISHYPHEN,ATTR_HYPHENATE,     cppu::UnoType<bool>::get(),                  0, 0 },
585         {u"" SC_UNONAME_PLASTADJ, ATTR_HOR_JUSTIFY,   ::cppu::UnoType<sal_Int16>::get(),    0, MID_HORJUST_ADJUST },
586         {u"" SC_UNONAME_PLMARGIN, ATTR_MARGIN,        cppu::UnoType<sal_Int32>::get(),            0, MID_MARGIN_L_MARGIN  | CONVERT_TWIPS },
587         {u"" SC_UNONAME_PRMARGIN, ATTR_MARGIN,        cppu::UnoType<sal_Int32>::get(),            0, MID_MARGIN_R_MARGIN  | CONVERT_TWIPS },
588         {u"" SC_UNONAME_PTMARGIN, ATTR_MARGIN,        cppu::UnoType<sal_Int32>::get(),            0, MID_MARGIN_UP_MARGIN | CONVERT_TWIPS },
589         {u"" SC_UNONAME_POS,      SC_WID_UNO_POS,     cppu::UnoType<awt::Point>::get(),           0 | beans::PropertyAttribute::READONLY, 0 },
590         {u"" SC_UNONAME_RIGHTBORDER,ATTR_BORDER,      ::cppu::UnoType<table::BorderLine>::get(), 0, RIGHT_BORDER | CONVERT_TWIPS },
591         {u"" SC_UNONAME_RIGHTBORDER2,ATTR_BORDER,      ::cppu::UnoType<table::BorderLine2>::get(), 0, RIGHT_BORDER | CONVERT_TWIPS },
592         {u"" SC_UNONAME_ROTANG,   ATTR_ROTATE_VALUE,  cppu::UnoType<sal_Int32>::get(),            0, 0 },
593         {u"" SC_UNONAME_ROTREF,   ATTR_ROTATE_MODE,   cppu::UnoType<sal_Int32>::get(), 0, 0 },
594         {u"" SC_UNONAME_SHADOW,   ATTR_SHADOW,        cppu::UnoType<table::ShadowFormat>::get(),  0, 0 | CONVERT_TWIPS },
595         {u"" SC_UNONAME_SHRINK_TO_FIT, ATTR_SHRINKTOFIT, cppu::UnoType<bool>::get(),               0, 0 },
596         {u"" SC_UNONAME_SIZE,     SC_WID_UNO_SIZE,    cppu::UnoType<awt::Size>::get(),            0 | beans::PropertyAttribute::READONLY, 0 },
597         {u"" SC_UNONAME_TBLBORD,  SC_WID_UNO_TBLBORD, cppu::UnoType<table::TableBorder>::get(),   0, 0 | CONVERT_TWIPS },
598         {u"" SC_UNONAME_TBLBORD2,  SC_WID_UNO_TBLBORD2, cppu::UnoType<table::TableBorder2>::get(),   0, 0 | CONVERT_TWIPS },
599         {u"" SC_UNONAME_TOPBORDER,ATTR_BORDER,        ::cppu::UnoType<table::BorderLine>::get(), 0, TOP_BORDER | CONVERT_TWIPS },
600         {u"" SC_UNONAME_TOPBORDER2,ATTR_BORDER,       ::cppu::UnoType<table::BorderLine2>::get(), 0, TOP_BORDER | CONVERT_TWIPS },
601         {u"" SC_UNONAME_USERDEF,  ATTR_USERDEF,       cppu::UnoType<container::XNameContainer>::get(), 0, 0 },
602         {u"" SC_UNONAME_VALIDAT,  SC_WID_UNO_VALIDAT, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
603         {u"" SC_UNONAME_VALILOC,  SC_WID_UNO_VALILOC, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
604         {u"" SC_UNONAME_VALIXML,  SC_WID_UNO_VALIXML, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
605         {u"" SC_UNONAME_CELLVJUS, ATTR_VER_JUSTIFY,   cppu::UnoType<sal_Int32>::get(), 0, 0 },
606         {u"" SC_UNONAME_CELLVJUS_METHOD, ATTR_VER_JUSTIFY_METHOD, ::cppu::UnoType<sal_Int32>::get(),   0, 0 },
607         {u"" SC_UNONAME_CELLWID,  SC_WID_UNO_CELLWID, cppu::UnoType<sal_Int32>::get(),            0, 0 },
608         {u"" SC_UNONAME_WRITING,  ATTR_WRITINGDIR,    cppu::UnoType<sal_Int16>::get(),            0, 0 },
609         { u"", 0, css::uno::Type(), 0, 0 }
610     };
611     static SfxItemPropertySet aColumnPropertySet( aColumnPropertyMap_Impl );
612     return &aColumnPropertySet;
613 }
614 
615 static const SfxItemPropertySet* lcl_GetRowPropertySet()
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 },
620         {u"" SC_UNONAME_ASIANVERT,ATTR_VERTICAL_ASIAN,cppu::UnoType<bool>::get(),                  0, 0 },
621         {u"" SC_UNONAME_BOTTBORDER,ATTR_BORDER,       ::cppu::UnoType<table::BorderLine>::get(), 0, BOTTOM_BORDER | CONVERT_TWIPS },
622         {u"" SC_UNONAME_BOTTBORDER2,ATTR_BORDER,      ::cppu::UnoType<table::BorderLine2>::get(), 0, BOTTOM_BORDER | CONVERT_TWIPS },
623         {u"" SC_UNONAME_CELLBACK, ATTR_BACKGROUND,    cppu::UnoType<sal_Int32>::get(),            0, MID_BACK_COLOR },
624         {u"" SC_UNONAME_CELLPRO,  ATTR_PROTECTION,    cppu::UnoType<util::CellProtection>::get(), 0, 0 },
625         {u"" SC_UNONAME_CELLSTYL, SC_WID_UNO_CELLSTYL,cppu::UnoType<OUString>::get(),        0, 0 },
626         {u"" SC_UNONAME_CCOLOR,   ATTR_FONT_COLOR,    cppu::UnoType<sal_Int32>::get(),            0, 0 },
627         {u"" SC_UNONAME_COUTL,    ATTR_FONT_CONTOUR,  cppu::UnoType<bool>::get(),                  0, 0 },
628         {u"" SC_UNONAME_CCROSS,   ATTR_FONT_CROSSEDOUT,cppu::UnoType<bool>::get(),                 0, MID_CROSSED_OUT },
629         {u"" SC_UNONAME_CEMPHAS,  ATTR_FONT_EMPHASISMARK,cppu::UnoType<sal_Int16>::get(),         0, MID_EMPHASIS },
630         {u"" SC_UNONAME_CFONT,    ATTR_FONT,          cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_FAMILY },
631         {u"" SC_UNONAME_CFCHARS,  ATTR_FONT,          cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_CHAR_SET },
632         {u"" SC_UNO_CJK_CFCHARS,  ATTR_CJK_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_CHAR_SET },
633         {u"" SC_UNO_CTL_CFCHARS,  ATTR_CTL_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_CHAR_SET },
634         {u"" SC_UNONAME_CFFAMIL,  ATTR_FONT,          cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_FAMILY },
635         {u"" SC_UNO_CJK_CFFAMIL,  ATTR_CJK_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_FAMILY },
636         {u"" SC_UNO_CTL_CFFAMIL,  ATTR_CTL_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_FAMILY },
637         {u"" SC_UNONAME_CFNAME,   ATTR_FONT,          cppu::UnoType<OUString>::get(),        0, MID_FONT_FAMILY_NAME },
638         {u"" SC_UNO_CJK_CFNAME,   ATTR_CJK_FONT,      cppu::UnoType<OUString>::get(),        0, MID_FONT_FAMILY_NAME },
639         {u"" SC_UNO_CTL_CFNAME,   ATTR_CTL_FONT,      cppu::UnoType<OUString>::get(),        0, MID_FONT_FAMILY_NAME },
640         {u"" SC_UNONAME_CFPITCH,  ATTR_FONT,          cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_PITCH },
641         {u"" SC_UNO_CJK_CFPITCH,  ATTR_CJK_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_PITCH },
642         {u"" SC_UNO_CTL_CFPITCH,  ATTR_CTL_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_PITCH },
643         {u"" SC_UNONAME_CFSTYLE,  ATTR_FONT,          cppu::UnoType<OUString>::get(),        0, MID_FONT_STYLE_NAME },
644         {u"" SC_UNO_CJK_CFSTYLE,  ATTR_CJK_FONT,      cppu::UnoType<OUString>::get(),        0, MID_FONT_STYLE_NAME },
645         {u"" SC_UNO_CTL_CFSTYLE,  ATTR_CTL_FONT,      cppu::UnoType<OUString>::get(),        0, MID_FONT_STYLE_NAME },
646         {u"" SC_UNONAME_CHEIGHT,  ATTR_FONT_HEIGHT,   cppu::UnoType<float>::get(),                0, MID_FONTHEIGHT | CONVERT_TWIPS },
647         {u"" SC_UNO_CJK_CHEIGHT,  ATTR_CJK_FONT_HEIGHT,cppu::UnoType<float>::get(),               0, MID_FONTHEIGHT | CONVERT_TWIPS },
648         {u"" SC_UNO_CTL_CHEIGHT,  ATTR_CTL_FONT_HEIGHT,cppu::UnoType<float>::get(),               0, MID_FONTHEIGHT | CONVERT_TWIPS },
649         {u"" SC_UNONAME_CLOCAL,   ATTR_FONT_LANGUAGE, cppu::UnoType<lang::Locale>::get(),         0, MID_LANG_LOCALE },
650         {u"" SC_UNO_CJK_CLOCAL,   ATTR_CJK_FONT_LANGUAGE,cppu::UnoType<lang::Locale>::get(),          0, MID_LANG_LOCALE },
651         {u"" SC_UNO_CTL_CLOCAL,   ATTR_CTL_FONT_LANGUAGE,cppu::UnoType<lang::Locale>::get(),          0, MID_LANG_LOCALE },
652         {u"" SC_UNONAME_COVER,    ATTR_FONT_OVERLINE, cppu::UnoType<sal_Int16>::get(),            0, MID_TL_STYLE },
653         {u"" SC_UNONAME_COVRLCOL, ATTR_FONT_OVERLINE, cppu::UnoType<sal_Int32>::get(),            0, MID_TL_COLOR },
654         {u"" SC_UNONAME_COVRLHAS, ATTR_FONT_OVERLINE, cppu::UnoType<bool>::get(),                  0, MID_TL_HASCOLOR },
655         {u"" SC_UNONAME_CPOST,    ATTR_FONT_POSTURE,  cppu::UnoType<awt::FontSlant>::get(),       0, MID_POSTURE },
656         {u"" SC_UNO_CJK_CPOST,    ATTR_CJK_FONT_POSTURE,cppu::UnoType<awt::FontSlant>::get(),     0, MID_POSTURE },
657         {u"" SC_UNO_CTL_CPOST,    ATTR_CTL_FONT_POSTURE,cppu::UnoType<awt::FontSlant>::get(),     0, MID_POSTURE },
658         {u"" SC_UNONAME_CRELIEF,  ATTR_FONT_RELIEF,   cppu::UnoType<sal_Int16>::get(),            0, MID_RELIEF },
659         {u"" SC_UNONAME_CSHADD,   ATTR_FONT_SHADOWED, cppu::UnoType<bool>::get(),                  0, 0 },
660         {u"" SC_UNONAME_CSTRIKE,  ATTR_FONT_CROSSEDOUT,cppu::UnoType<sal_Int16>::get(),           0, MID_CROSS_OUT },
661         {u"" SC_UNONAME_CUNDER,   ATTR_FONT_UNDERLINE,cppu::UnoType<sal_Int16>::get(),            0, MID_TL_STYLE },
662         {u"" SC_UNONAME_CUNDLCOL, ATTR_FONT_UNDERLINE,cppu::UnoType<sal_Int32>::get(),            0, MID_TL_COLOR },
663         {u"" SC_UNONAME_CUNDLHAS, ATTR_FONT_UNDERLINE,cppu::UnoType<bool>::get(),                  0, MID_TL_HASCOLOR },
664         {u"" SC_UNONAME_CWEIGHT,  ATTR_FONT_WEIGHT,   cppu::UnoType<float>::get(),                0, MID_WEIGHT },
665         {u"" SC_UNO_CJK_CWEIGHT,  ATTR_CJK_FONT_WEIGHT,cppu::UnoType<float>::get(),               0, MID_WEIGHT },
666         {u"" SC_UNO_CTL_CWEIGHT,  ATTR_CTL_FONT_WEIGHT,cppu::UnoType<float>::get(),               0, MID_WEIGHT },
667         {u"" SC_UNONAME_CWORDMOD, ATTR_FONT_WORDLINE, cppu::UnoType<bool>::get(),                  0, 0 },
668         {u"" SC_UNONAME_CHCOLHDR, SC_WID_UNO_CHCOLHDR,cppu::UnoType<bool>::get(),                  0, 0 },
669         {u"" SC_UNONAME_CHROWHDR, SC_WID_UNO_CHROWHDR,cppu::UnoType<bool>::get(),                  0, 0 },
670         {u"" SC_UNONAME_CONDFMT,  SC_WID_UNO_CONDFMT, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
671         {u"" SC_UNONAME_CONDLOC,  SC_WID_UNO_CONDLOC, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
672         {u"" SC_UNONAME_CONDXML,  SC_WID_UNO_CONDXML, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
673         {u"" SC_UNONAME_DIAGONAL_BLTR, ATTR_BORDER_BLTR, ::cppu::UnoType<table::BorderLine>::get(), 0, 0 | CONVERT_TWIPS },
674         {u"" SC_UNONAME_DIAGONAL_BLTR2, ATTR_BORDER_BLTR, ::cppu::UnoType<table::BorderLine2>::get(), 0, 0 | CONVERT_TWIPS },
675         {u"" SC_UNONAME_DIAGONAL_TLBR, ATTR_BORDER_TLBR, ::cppu::UnoType<table::BorderLine>::get(), 0, 0 | CONVERT_TWIPS },
676         {u"" SC_UNONAME_DIAGONAL_TLBR2, ATTR_BORDER_TLBR, ::cppu::UnoType<table::BorderLine2>::get(), 0, 0 | CONVERT_TWIPS },
677         {u"" SC_UNONAME_CELLHGT,  SC_WID_UNO_CELLHGT, cppu::UnoType<sal_Int32>::get(),            0, 0 },
678         {u"" SC_UNONAME_CELLHJUS, ATTR_HOR_JUSTIFY,   cppu::UnoType<table::CellHoriJustify>::get(), 0, MID_HORJUST_HORJUST },
679         {u"" SC_UNONAME_CELLHJUS_METHOD, ATTR_HOR_JUSTIFY_METHOD, ::cppu::UnoType<sal_Int32>::get(),   0, 0 },
680         {u"" SC_UNONAME_CELLTRAN, ATTR_BACKGROUND,    cppu::UnoType<bool>::get(),                  0, MID_GRAPHIC_TRANSPARENT },
681         {u"" SC_UNONAME_CELLFILT, SC_WID_UNO_CELLFILT,cppu::UnoType<bool>::get(),                  0, 0 },
682         {u"" SC_UNONAME_MANPAGE,  SC_WID_UNO_MANPAGE, cppu::UnoType<bool>::get(),                  0, 0 },
683         {u"" SC_UNONAME_NEWPAGE,  SC_WID_UNO_NEWPAGE, cppu::UnoType<bool>::get(),                  0, 0 },
684         {u"" SC_UNONAME_WRAP,     ATTR_LINEBREAK,     cppu::UnoType<bool>::get(),                  0, 0 },
685         {u"" SC_UNONAME_CELLVIS,  SC_WID_UNO_CELLVIS, cppu::UnoType<bool>::get(),                  0, 0 },
686         {u"" SC_UNONAME_LEFTBORDER,ATTR_BORDER,       ::cppu::UnoType<table::BorderLine>::get(), 0, LEFT_BORDER | CONVERT_TWIPS },
687         {u"" SC_UNONAME_LEFTBORDER2,ATTR_BORDER,      ::cppu::UnoType<table::BorderLine2>::get(), 0, LEFT_BORDER | CONVERT_TWIPS },
688         {u"" SC_UNONAME_NUMFMT,   ATTR_VALUE_FORMAT,  cppu::UnoType<sal_Int32>::get(),            0, 0 },
689         {u"" SC_UNONAME_NUMRULES, SC_WID_UNO_NUMRULES,cppu::UnoType<container::XIndexReplace>::get(), 0, 0 },
690         {u"" SC_UNONAME_OHEIGHT,  SC_WID_UNO_OHEIGHT, cppu::UnoType<bool>::get(),                  0, 0 },
691         {u"" SC_UNONAME_CELLORI,  ATTR_STACKED,       cppu::UnoType<table::CellOrientation>::get(), 0, 0 },
692         {u"" SC_UNONAME_PADJUST,  ATTR_HOR_JUSTIFY,   ::cppu::UnoType<sal_Int16>::get(),    0, MID_HORJUST_ADJUST },
693         {u"" SC_UNONAME_PBMARGIN, ATTR_MARGIN,        cppu::UnoType<sal_Int32>::get(),            0, MID_MARGIN_LO_MARGIN | CONVERT_TWIPS },
694         {u"" SC_UNONAME_PINDENT,  ATTR_INDENT,        cppu::UnoType<sal_Int16>::get(),            0, 0 }, //! CONVERT_TWIPS
695         {u"" SC_UNONAME_PISCHDIST,ATTR_SCRIPTSPACE,   cppu::UnoType<bool>::get(),                  0, 0 },
696         {u"" SC_UNONAME_PISFORBID,ATTR_FORBIDDEN_RULES,cppu::UnoType<bool>::get(),                 0, 0 },
697         {u"" SC_UNONAME_PISHANG,  ATTR_HANGPUNCTUATION,cppu::UnoType<bool>::get(),                 0, 0 },
698         {u"" SC_UNONAME_PISHYPHEN,ATTR_HYPHENATE,     cppu::UnoType<bool>::get(),                  0, 0 },
699         {u"" SC_UNONAME_PLASTADJ, ATTR_HOR_JUSTIFY,   ::cppu::UnoType<sal_Int16>::get(),    0, MID_HORJUST_ADJUST },
700         {u"" SC_UNONAME_PLMARGIN, ATTR_MARGIN,        cppu::UnoType<sal_Int32>::get(),            0, MID_MARGIN_L_MARGIN  | CONVERT_TWIPS },
701         {u"" SC_UNONAME_PRMARGIN, ATTR_MARGIN,        cppu::UnoType<sal_Int32>::get(),            0, MID_MARGIN_R_MARGIN  | CONVERT_TWIPS },
702         {u"" SC_UNONAME_PTMARGIN, ATTR_MARGIN,        cppu::UnoType<sal_Int32>::get(),            0, MID_MARGIN_UP_MARGIN | CONVERT_TWIPS },
703         {u"" SC_UNONAME_POS,      SC_WID_UNO_POS,     cppu::UnoType<awt::Point>::get(),           0 | beans::PropertyAttribute::READONLY, 0 },
704         {u"" SC_UNONAME_RIGHTBORDER,ATTR_BORDER,      ::cppu::UnoType<table::BorderLine>::get(), 0, RIGHT_BORDER | CONVERT_TWIPS },
705         {u"" SC_UNONAME_RIGHTBORDER2,ATTR_BORDER,     ::cppu::UnoType<table::BorderLine2>::get(), 0, RIGHT_BORDER | CONVERT_TWIPS },
706         {u"" SC_UNONAME_ROTANG,   ATTR_ROTATE_VALUE,  cppu::UnoType<sal_Int32>::get(),            0, 0 },
707         {u"" SC_UNONAME_ROTREF,   ATTR_ROTATE_MODE,   cppu::UnoType<sal_Int32>::get(), 0, 0 },
708         {u"" SC_UNONAME_SHADOW,   ATTR_SHADOW,        cppu::UnoType<table::ShadowFormat>::get(),  0, 0 | CONVERT_TWIPS },
709         {u"" SC_UNONAME_SHRINK_TO_FIT, ATTR_SHRINKTOFIT, cppu::UnoType<bool>::get(),               0, 0 },
710         {u"" SC_UNONAME_SIZE,     SC_WID_UNO_SIZE,    cppu::UnoType<awt::Size>::get(),            0 | beans::PropertyAttribute::READONLY, 0 },
711         {u"" SC_UNONAME_TBLBORD,  SC_WID_UNO_TBLBORD, cppu::UnoType<table::TableBorder>::get(),   0, 0 | CONVERT_TWIPS },
712         {u"" SC_UNONAME_TBLBORD2,  SC_WID_UNO_TBLBORD2, cppu::UnoType<table::TableBorder2>::get(),   0, 0 | CONVERT_TWIPS },
713         {u"" SC_UNONAME_TOPBORDER,ATTR_BORDER,        ::cppu::UnoType<table::BorderLine>::get(), 0, TOP_BORDER | CONVERT_TWIPS },
714         {u"" SC_UNONAME_TOPBORDER2,ATTR_BORDER,       ::cppu::UnoType<table::BorderLine2>::get(), 0, TOP_BORDER | CONVERT_TWIPS },
715         {u"" SC_UNONAME_USERDEF,  ATTR_USERDEF,       cppu::UnoType<container::XNameContainer>::get(), 0, 0 },
716         {u"" SC_UNONAME_VALIDAT,  SC_WID_UNO_VALIDAT, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
717         {u"" SC_UNONAME_VALILOC,  SC_WID_UNO_VALILOC, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
718         {u"" SC_UNONAME_VALIXML,  SC_WID_UNO_VALIXML, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
719         {u"" SC_UNONAME_CELLVJUS, ATTR_VER_JUSTIFY,   cppu::UnoType<sal_Int32>::get(), 0, 0 },
720         {u"" SC_UNONAME_CELLVJUS_METHOD, ATTR_VER_JUSTIFY_METHOD, ::cppu::UnoType<sal_Int32>::get(),   0, 0 },
721         {u"" SC_UNONAME_WRITING,  ATTR_WRITINGDIR,    cppu::UnoType<sal_Int16>::get(),            0, 0 },
722         { u"", 0, css::uno::Type(), 0, 0 }
723     };
724     static SfxItemPropertySet aRowPropertySet( aRowPropertyMap_Impl );
725     return &aRowPropertySet;
726 }
727 
728 static const SfxItemPropertySet* lcl_GetSheetPropertySet()
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 },
733         {u"" SC_UNONAME_ASIANVERT,ATTR_VERTICAL_ASIAN,cppu::UnoType<bool>::get(),                  0, 0 },
734         {u"" SC_UNONAME_AUTOPRINT,SC_WID_UNO_AUTOPRINT,cppu::UnoType<bool>::get(),                 0, 0 },
735         {u"" SC_UNONAME_BORDCOL,  SC_WID_UNO_BORDCOL, cppu::UnoType<sal_Int32>::get(),            0, 0 },
736         {u"" SC_UNONAME_BOTTBORDER,ATTR_BORDER,       ::cppu::UnoType<table::BorderLine>::get(), 0, BOTTOM_BORDER | CONVERT_TWIPS },
737         {u"" SC_UNONAME_BOTTBORDER2,ATTR_BORDER,      ::cppu::UnoType<table::BorderLine2>::get(), 0, BOTTOM_BORDER | CONVERT_TWIPS },
738         {u"" SC_UNONAME_CELLBACK, ATTR_BACKGROUND,    cppu::UnoType<sal_Int32>::get(),            0, MID_BACK_COLOR },
739         {u"" SC_UNONAME_CELLPRO,  ATTR_PROTECTION,    cppu::UnoType<util::CellProtection>::get(), 0, 0 },
740         {u"" SC_UNONAME_CELLSTYL, SC_WID_UNO_CELLSTYL,cppu::UnoType<OUString>::get(),        0, 0 },
741         {u"" SC_UNONAME_CCOLOR,   ATTR_FONT_COLOR,    cppu::UnoType<sal_Int32>::get(),            0, 0 },
742         {u"" SC_UNONAME_COUTL,    ATTR_FONT_CONTOUR,  cppu::UnoType<bool>::get(),                  0, 0 },
743         {u"" SC_UNONAME_CCROSS,   ATTR_FONT_CROSSEDOUT,cppu::UnoType<bool>::get(),                 0, MID_CROSSED_OUT },
744         {u"" SC_UNONAME_CEMPHAS,  ATTR_FONT_EMPHASISMARK,cppu::UnoType<sal_Int16>::get(),         0, MID_EMPHASIS },
745         {u"" SC_UNONAME_CFONT,    ATTR_FONT,          cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_FAMILY },
746         {u"" SC_UNONAME_CFCHARS,  ATTR_FONT,          cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_CHAR_SET },
747         {u"" SC_UNO_CJK_CFCHARS,  ATTR_CJK_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_CHAR_SET },
748         {u"" SC_UNO_CTL_CFCHARS,  ATTR_CTL_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_CHAR_SET },
749         {u"" SC_UNONAME_CFFAMIL,  ATTR_FONT,          cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_FAMILY },
750         {u"" SC_UNO_CJK_CFFAMIL,  ATTR_CJK_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_FAMILY },
751         {u"" SC_UNO_CTL_CFFAMIL,  ATTR_CTL_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_FAMILY },
752         {u"" SC_UNONAME_CFNAME,   ATTR_FONT,          cppu::UnoType<OUString>::get(),        0, MID_FONT_FAMILY_NAME },
753         {u"" SC_UNO_CJK_CFNAME,   ATTR_CJK_FONT,      cppu::UnoType<OUString>::get(),        0, MID_FONT_FAMILY_NAME },
754         {u"" SC_UNO_CTL_CFNAME,   ATTR_CTL_FONT,      cppu::UnoType<OUString>::get(),        0, MID_FONT_FAMILY_NAME },
755         {u"" SC_UNONAME_CFPITCH,  ATTR_FONT,          cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_PITCH },
756         {u"" SC_UNO_CJK_CFPITCH,  ATTR_CJK_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_PITCH },
757         {u"" SC_UNO_CTL_CFPITCH,  ATTR_CTL_FONT,      cppu::UnoType<sal_Int16>::get(),            0, MID_FONT_PITCH },
758         {u"" SC_UNONAME_CFSTYLE,  ATTR_FONT,          cppu::UnoType<OUString>::get(),        0, MID_FONT_STYLE_NAME },
759         {u"" SC_UNO_CJK_CFSTYLE,  ATTR_CJK_FONT,      cppu::UnoType<OUString>::get(),        0, MID_FONT_STYLE_NAME },
760         {u"" SC_UNO_CTL_CFSTYLE,  ATTR_CTL_FONT,      cppu::UnoType<OUString>::get(),        0, MID_FONT_STYLE_NAME },
761         {u"" SC_UNONAME_CHEIGHT,  ATTR_FONT_HEIGHT,   cppu::UnoType<float>::get(),                0, MID_FONTHEIGHT | CONVERT_TWIPS },
762         {u"" SC_UNO_CJK_CHEIGHT,  ATTR_CJK_FONT_HEIGHT,cppu::UnoType<float>::get(),               0, MID_FONTHEIGHT | CONVERT_TWIPS },
763         {u"" SC_UNO_CTL_CHEIGHT,  ATTR_CTL_FONT_HEIGHT,cppu::UnoType<float>::get(),               0, MID_FONTHEIGHT | CONVERT_TWIPS },
764         {u"" SC_UNONAME_CLOCAL,   ATTR_FONT_LANGUAGE, cppu::UnoType<lang::Locale>::get(),         0, MID_LANG_LOCALE },
765         {u"" SC_UNO_CJK_CLOCAL,   ATTR_CJK_FONT_LANGUAGE,cppu::UnoType<lang::Locale>::get(),          0, MID_LANG_LOCALE },
766         {u"" SC_UNO_CTL_CLOCAL,   ATTR_CTL_FONT_LANGUAGE,cppu::UnoType<lang::Locale>::get(),          0, MID_LANG_LOCALE },
767         {u"" SC_UNONAME_COVER,    ATTR_FONT_OVERLINE, cppu::UnoType<sal_Int16>::get(),            0, MID_TL_STYLE },
768         {u"" SC_UNONAME_COVRLCOL, ATTR_FONT_OVERLINE, cppu::UnoType<sal_Int32>::get(),            0, MID_TL_COLOR },
769         {u"" SC_UNONAME_COVRLHAS, ATTR_FONT_OVERLINE, cppu::UnoType<bool>::get(),                  0, MID_TL_HASCOLOR },
770         {u"" SC_UNONAME_CPOST,    ATTR_FONT_POSTURE,  cppu::UnoType<awt::FontSlant>::get(),       0, MID_POSTURE },
771         {u"" SC_UNO_CJK_CPOST,    ATTR_CJK_FONT_POSTURE,cppu::UnoType<awt::FontSlant>::get(),     0, MID_POSTURE },
772         {u"" SC_UNO_CTL_CPOST,    ATTR_CTL_FONT_POSTURE,cppu::UnoType<awt::FontSlant>::get(),     0, MID_POSTURE },
773         {u"" SC_UNONAME_CRELIEF,  ATTR_FONT_RELIEF,   cppu::UnoType<sal_Int16>::get(),            0, MID_RELIEF },
774         {u"" SC_UNONAME_CSHADD,   ATTR_FONT_SHADOWED, cppu::UnoType<bool>::get(),                  0, 0 },
775         {u"" SC_UNONAME_CSTRIKE,  ATTR_FONT_CROSSEDOUT,cppu::UnoType<sal_Int16>::get(),           0, MID_CROSS_OUT },
776         {u"" SC_UNONAME_CUNDER,   ATTR_FONT_UNDERLINE,cppu::UnoType<sal_Int16>::get(),            0, MID_TL_STYLE },
777         {u"" SC_UNONAME_CUNDLCOL, ATTR_FONT_UNDERLINE,cppu::UnoType<sal_Int32>::get(),            0, MID_TL_COLOR },
778         {u"" SC_UNONAME_CUNDLHAS, ATTR_FONT_UNDERLINE,cppu::UnoType<bool>::get(),                  0, MID_TL_HASCOLOR },
779         {u"" SC_UNONAME_CWEIGHT,  ATTR_FONT_WEIGHT,   cppu::UnoType<float>::get(),                0, MID_WEIGHT },
780         {u"" SC_UNO_CJK_CWEIGHT,  ATTR_CJK_FONT_WEIGHT,cppu::UnoType<float>::get(),               0, MID_WEIGHT },
781         {u"" SC_UNO_CTL_CWEIGHT,  ATTR_CTL_FONT_WEIGHT,cppu::UnoType<float>::get(),               0, MID_WEIGHT },
782         {u"" SC_UNONAME_CWORDMOD, ATTR_FONT_WORDLINE, cppu::UnoType<bool>::get(),                  0, 0 },
783         {u"" SC_UNONAME_CHCOLHDR, SC_WID_UNO_CHCOLHDR,cppu::UnoType<bool>::get(),                  0, 0 },
784         {u"" SC_UNONAME_CHROWHDR, SC_WID_UNO_CHROWHDR,cppu::UnoType<bool>::get(),                  0, 0 },
785         {u"" SC_UNONAME_CONDFMT,  SC_WID_UNO_CONDFMT, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
786         {u"" SC_UNONAME_CONDLOC,  SC_WID_UNO_CONDLOC, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
787         {u"" SC_UNONAME_CONDXML,  SC_WID_UNO_CONDXML, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
788         {u"" SC_UNONAME_COPYBACK, SC_WID_UNO_COPYBACK,cppu::UnoType<bool>::get(),                  0, 0 },
789         {u"" SC_UNONAME_COPYFORM, SC_WID_UNO_COPYFORM,cppu::UnoType<bool>::get(),                  0, 0 },
790         {u"" SC_UNONAME_COPYSTYL, SC_WID_UNO_COPYSTYL,cppu::UnoType<bool>::get(),                  0, 0 },
791         {u"" SC_UNONAME_DIAGONAL_BLTR, ATTR_BORDER_BLTR, ::cppu::UnoType<table::BorderLine>::get(), 0, 0 | CONVERT_TWIPS },
792         {u"" SC_UNONAME_DIAGONAL_BLTR2, ATTR_BORDER_BLTR, ::cppu::UnoType<table::BorderLine2>::get(), 0, 0 | CONVERT_TWIPS },
793         {u"" SC_UNONAME_DIAGONAL_TLBR, ATTR_BORDER_TLBR, ::cppu::UnoType<table::BorderLine>::get(), 0, 0 | CONVERT_TWIPS },
794         {u"" SC_UNONAME_DIAGONAL_TLBR2, ATTR_BORDER_TLBR, ::cppu::UnoType<table::BorderLine2>::get(), 0, 0 | CONVERT_TWIPS },
795         {u"" SC_UNONAME_CELLHJUS, ATTR_HOR_JUSTIFY,   cppu::UnoType<table::CellHoriJustify>::get(), 0, MID_HORJUST_HORJUST },
796         {u"" SC_UNONAME_CELLHJUS_METHOD, ATTR_HOR_JUSTIFY_METHOD, ::cppu::UnoType<sal_Int32>::get(),   0, 0 },
797         {u"" SC_UNONAME_ISACTIVE, SC_WID_UNO_ISACTIVE,cppu::UnoType<bool>::get(),                  0, 0 },
798         {u"" SC_UNONAME_CELLTRAN, ATTR_BACKGROUND,    cppu::UnoType<bool>::get(),                  0, MID_GRAPHIC_TRANSPARENT },
799         {u"" SC_UNONAME_WRAP,     ATTR_LINEBREAK,     cppu::UnoType<bool>::get(),                  0, 0 },
800         {u"" SC_UNONAME_CELLVIS,  SC_WID_UNO_CELLVIS, cppu::UnoType<bool>::get(),                  0, 0 },
801         {u"" SC_UNONAME_LEFTBORDER,ATTR_BORDER,       ::cppu::UnoType<table::BorderLine>::get(), 0, LEFT_BORDER | CONVERT_TWIPS },
802         {u"" SC_UNONAME_LEFTBORDER2,ATTR_BORDER,      ::cppu::UnoType<table::BorderLine2>::get(), 0, LEFT_BORDER | CONVERT_TWIPS },
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 },
805         {u"" SC_UNONAME_NUMFMT,   ATTR_VALUE_FORMAT,  cppu::UnoType<sal_Int32>::get(),            0, 0 },
806         {u"" SC_UNONAME_NUMRULES, SC_WID_UNO_NUMRULES,cppu::UnoType<container::XIndexReplace>::get(), 0, 0 },
807         {u"" SC_UNONAME_CELLORI,  ATTR_STACKED,       cppu::UnoType<table::CellOrientation>::get(), 0, 0 },
808         {u"" SC_UNONAME_PAGESTL,  SC_WID_UNO_PAGESTL, cppu::UnoType<OUString>::get(),        0, 0 },
809         {u"" SC_UNONAME_PADJUST,  ATTR_HOR_JUSTIFY,   ::cppu::UnoType<sal_Int16>::get(),    0, MID_HORJUST_ADJUST },
810         {u"" SC_UNONAME_PBMARGIN, ATTR_MARGIN,        cppu::UnoType<sal_Int32>::get(),            0, MID_MARGIN_LO_MARGIN | CONVERT_TWIPS },
811         {u"" SC_UNONAME_PINDENT,  ATTR_INDENT,        cppu::UnoType<sal_Int16>::get(),            0, 0 }, //! CONVERT_TWIPS
812         {u"" SC_UNONAME_PISCHDIST,ATTR_SCRIPTSPACE,   cppu::UnoType<bool>::get(),                  0, 0 },
813         {u"" SC_UNONAME_PISFORBID,ATTR_FORBIDDEN_RULES,cppu::UnoType<bool>::get(),                 0, 0 },
814         {u"" SC_UNONAME_PISHANG,  ATTR_HANGPUNCTUATION,cppu::UnoType<bool>::get(),                 0, 0 },
815         {u"" SC_UNONAME_PISHYPHEN,ATTR_HYPHENATE,     cppu::UnoType<bool>::get(),                  0, 0 },
816         {u"" SC_UNONAME_PLASTADJ, ATTR_HOR_JUSTIFY,   ::cppu::UnoType<sal_Int16>::get(),    0, MID_HORJUST_ADJUST },
817         {u"" SC_UNONAME_PLMARGIN, ATTR_MARGIN,        cppu::UnoType<sal_Int32>::get(),            0, MID_MARGIN_L_MARGIN  | CONVERT_TWIPS },
818         {u"" SC_UNONAME_PRMARGIN, ATTR_MARGIN,        cppu::UnoType<sal_Int32>::get(),            0, MID_MARGIN_R_MARGIN  | CONVERT_TWIPS },
819         {u"" SC_UNONAME_PTMARGIN, ATTR_MARGIN,        cppu::UnoType<sal_Int32>::get(),            0, MID_MARGIN_UP_MARGIN | CONVERT_TWIPS },
820         {u"" SC_UNONAME_POS,      SC_WID_UNO_POS,     cppu::UnoType<awt::Point>::get(),           0 | beans::PropertyAttribute::READONLY, 0 },
821         {u"" SC_UNONAME_PRINTBORD,SC_WID_UNO_PRINTBORD,cppu::UnoType<bool>::get(),                 0, 0 },
822         {u"" SC_UNONAME_PROTECT,  SC_WID_UNO_PROTECT, cppu::UnoType<bool>::get(),                  0, 0 },
823         {u"" SC_UNONAME_RIGHTBORDER,ATTR_BORDER,      ::cppu::UnoType<table::BorderLine>::get(), 0, RIGHT_BORDER | CONVERT_TWIPS },
824         {u"" SC_UNONAME_RIGHTBORDER2,ATTR_BORDER,     ::cppu::UnoType<table::BorderLine2>::get(), 0, RIGHT_BORDER | CONVERT_TWIPS },
825         {u"" SC_UNONAME_ROTANG,   ATTR_ROTATE_VALUE,  cppu::UnoType<sal_Int32>::get(),            0, 0 },
826         {u"" SC_UNONAME_ROTREF,   ATTR_ROTATE_MODE,   cppu::UnoType<sal_Int32>::get(), 0, 0 },
827         {u"" SC_UNONAME_SHADOW,   ATTR_SHADOW,        cppu::UnoType<table::ShadowFormat>::get(),  0, 0 | CONVERT_TWIPS },
828         {u"" SC_UNONAME_SHOWBORD, SC_WID_UNO_SHOWBORD,cppu::UnoType<bool>::get(),                  0, 0 },
829         {u"" SC_UNONAME_SHRINK_TO_FIT, ATTR_SHRINKTOFIT, cppu::UnoType<bool>::get(),               0, 0 },
830         {u"" SC_UNONAME_SIZE,     SC_WID_UNO_SIZE,    cppu::UnoType<awt::Size>::get(),            0 | beans::PropertyAttribute::READONLY, 0 },
831         {u"" SC_UNONAME_TBLBORD,  SC_WID_UNO_TBLBORD, cppu::UnoType<table::TableBorder>::get(),   0, 0 | CONVERT_TWIPS },
832         {u"" SC_UNONAME_TBLBORD2,  SC_WID_UNO_TBLBORD2, cppu::UnoType<table::TableBorder2>::get(),   0, 0 | CONVERT_TWIPS },
833         {u"" SC_UNONAME_TABLAYOUT,SC_WID_UNO_TABLAYOUT,cppu::UnoType<sal_Int16>::get(),           0, 0 },
834         {u"" SC_UNONAME_CONDFORMAT, SC_WID_UNO_CONDFORMAT, cppu::UnoType<sheet::XConditionalFormats>::get(), 0, 0},
835         {u"" SC_UNONAME_TOPBORDER,ATTR_BORDER,        ::cppu::UnoType<table::BorderLine>::get(), 0, TOP_BORDER | CONVERT_TWIPS },
836         {u"" SC_UNONAME_TOPBORDER2,ATTR_BORDER,       ::cppu::UnoType<table::BorderLine2>::get(), 0, TOP_BORDER | CONVERT_TWIPS },
837         {u"" SC_UNONAME_USERDEF,  ATTR_USERDEF,       cppu::UnoType<container::XNameContainer>::get(), 0, 0 },
838         {u"" SC_UNONAME_VALIDAT,  SC_WID_UNO_VALIDAT, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
839         {u"" SC_UNONAME_VALILOC,  SC_WID_UNO_VALILOC, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
840         {u"" SC_UNONAME_VALIXML,  SC_WID_UNO_VALIXML, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
841         {u"" SC_UNONAME_CELLVJUS, ATTR_VER_JUSTIFY,   cppu::UnoType<sal_Int32>::get(), 0, 0 },
842         {u"" SC_UNONAME_CELLVJUS_METHOD, ATTR_VER_JUSTIFY_METHOD, ::cppu::UnoType<sal_Int32>::get(),   0, 0 },
843         {u"" SC_UNONAME_WRITING,  ATTR_WRITINGDIR,    cppu::UnoType<sal_Int16>::get(),            0, 0 },
844         {u"" SC_UNONAME_TABCOLOR, SC_WID_UNO_TABCOLOR, cppu::UnoType<sal_Int32>::get(), 0, 0 },
845         {u"" SC_UNO_CODENAME,        SC_WID_UNO_CODENAME, cppu::UnoType<OUString>::get(),    0, 0},
846         {u"" SC_UNO_NAMEDRANGES, SC_WID_UNO_NAMES, cppu::UnoType<sheet::XNamedRanges>::get(), 0, 0 },
847         { u"", 0, css::uno::Type(), 0, 0 }
848     };
849     static SfxItemPropertySet aSheetPropertySet( aSheetPropertyMap_Impl );
850     return &aSheetPropertySet;
851 }
852 
853 static const SfxItemPropertyMapEntry* lcl_GetEditPropertyMap()
854 {
855     static const SfxItemPropertyMapEntry aEditPropertyMap_Impl[] =
856     {
857         SVX_UNOEDIT_CHAR_PROPERTIES,
858         SVX_UNOEDIT_FONT_PROPERTIES,
859         SVX_UNOEDIT_PARA_PROPERTIES,
860         SVX_UNOEDIT_NUMBERING_PROPERTIE,    // for completeness of service ParagraphProperties
861         {u"" SC_UNONAME_TEXTUSER, EE_CHAR_XMLATTRIBS, cppu::UnoType<container::XNameContainer>::get(), 0, 0},
862         {u"" SC_UNONAME_USERDEF,  EE_PARA_XMLATTRIBS, cppu::UnoType<container::XNameContainer>::get(), 0, 0},
863         { u"", 0, css::uno::Type(), 0, 0 }
864     };
865     return aEditPropertyMap_Impl;
866 }
867 static const SvxItemPropertySet* lcl_GetEditPropertySet()
868 {
869     static SvxItemPropertySet aEditPropertySet( lcl_GetEditPropertyMap(), SdrObject::GetGlobalDrawObjectItemPool() );
870     return &aEditPropertySet;
871 }
872 
873 #define SCCHARPROPERTIES_SERVICE    "com.sun.star.style.CharacterProperties"
874 #define SCPARAPROPERTIES_SERVICE    "com.sun.star.style.ParagraphProperties"
875 #define SCCELLPROPERTIES_SERVICE    "com.sun.star.table.CellProperties"
876 #define SCCELLRANGE_SERVICE         "com.sun.star.table.CellRange"
877 #define SCCELL_SERVICE              "com.sun.star.table.Cell"
878 #define SCSHEETCELLRANGES_SERVICE   "com.sun.star.sheet.SheetCellRanges"
879 #define SCSHEETCELLRANGE_SERVICE    "com.sun.star.sheet.SheetCellRange"
880 #define SCSPREADSHEET_SERVICE       "com.sun.star.sheet.Spreadsheet"
881 #define SCSHEETCELL_SERVICE         "com.sun.star.sheet.SheetCell"
882 
883 SC_SIMPLE_SERVICE_INFO( ScCellFormatsEnumeration, "ScCellFormatsEnumeration", "com.sun.star.sheet.CellFormatRangesEnumeration" )
884 SC_SIMPLE_SERVICE_INFO( ScCellFormatsObj, "ScCellFormatsObj", "com.sun.star.sheet.CellFormatRanges" )
885 SC_SIMPLE_SERVICE_INFO( ScUniqueCellFormatsEnumeration, "ScUniqueCellFormatsEnumeration", "com.sun.star.sheet.UniqueCellFormatRangesEnumeration" )
886 SC_SIMPLE_SERVICE_INFO( ScUniqueCellFormatsObj, "ScUniqueCellFormatsObj", "com.sun.star.sheet.UniqueCellFormatRanges" )
887 SC_SIMPLE_SERVICE_INFO( ScCellRangesBase, "ScCellRangesBase", "stardiv.unknown" )
888 SC_SIMPLE_SERVICE_INFO( ScCellsEnumeration, "ScCellsEnumeration", "com.sun.star.sheet.CellsEnumeration" )
889 SC_SIMPLE_SERVICE_INFO( ScCellsObj, "ScCellsObj", "com.sun.star.sheet.Cells" )
890 SC_SIMPLE_SERVICE_INFO( ScTableColumnObj, "ScTableColumnObj", "com.sun.star.table.TableColumn" )
891 SC_SIMPLE_SERVICE_INFO( ScTableRowObj, "ScTableRowObj", "com.sun.star.table.TableRow" )
892 
893 //! move ScLinkListener into another file !!!
894 
895 ScLinkListener::~ScLinkListener()
896 {
897 }
898 
899 void ScLinkListener::Notify( const SfxHint& rHint )
900 {
901     aLink.Call( rHint );
902 }
903 
904 static void lcl_CopyProperties( beans::XPropertySet& rDest, beans::XPropertySet& rSource )
905 {
906     uno::Reference<beans::XPropertySetInfo> xInfo(rSource.getPropertySetInfo());
907     if (xInfo.is())
908     {
909         const uno::Sequence<beans::Property> aSeq(xInfo->getProperties());
910         for (const beans::Property& rProp : aSeq)
911         {
912             OUString aName(rProp.Name);
913             rDest.setPropertyValue( aName, rSource.getPropertyValue( aName ) );
914         }
915     }
916 }
917 
918 static SCTAB lcl_FirstTab( const ScRangeList& rRanges )
919 {
920     if (rRanges.empty())
921         throw std::out_of_range("empty range");
922     const ScRange & rFirst = rRanges[0];
923     return rFirst.aStart.Tab();
924 }
925 
926 static bool lcl_WholeSheet( const ScDocument& rDoc, const ScRangeList& rRanges )
927 {
928     if ( rRanges.size() == 1 )
929     {
930         const ScRange & rRange = rRanges[0];
931         if ( rRange.aStart.Col() == 0 && rRange.aEnd.Col() == rDoc.MaxCol() &&
932              rRange.aStart.Row() == 0 && rRange.aEnd.Row() == rDoc.MaxRow() )
933             return true;
934     }
935     return false;
936 }
937 
938 namespace {
939 template<typename BorderLineType>
940 const ::editeng::SvxBorderLine* lcl_getBorderLine(
941         ::editeng::SvxBorderLine& rLine, const BorderLineType& rStruct )
942 {
943     // Convert from 1/100mm to Twips.
944     if (!SvxBoxItem::LineToSvxLine( rStruct, rLine, true))
945         return nullptr;
946 
947     if ( rLine.GetOutWidth() || rLine.GetInWidth() || rLine.GetDistance() )
948         return &rLine;
949     else
950         return nullptr;
951 }
952 }
953 
954 const ::editeng::SvxBorderLine* ScHelperFunctions::GetBorderLine(
955         ::editeng::SvxBorderLine& rLine, const table::BorderLine& rStruct )
956 {
957     return lcl_getBorderLine( rLine, rStruct);
958 }
959 
960 const ::editeng::SvxBorderLine* ScHelperFunctions::GetBorderLine(
961         ::editeng::SvxBorderLine& rLine, const table::BorderLine2& rStruct )
962 {
963     return lcl_getBorderLine( rLine, rStruct);
964 }
965 
966 namespace {
967 template<typename TableBorderType>
968 void lcl_fillBoxItems( SvxBoxItem& rOuter, SvxBoxInfoItem& rInner, const TableBorderType& rBorder )
969 {
970     ::editeng::SvxBorderLine aLine;
971     rOuter.SetAllDistances(static_cast<sal_uInt16>(convertMm100ToTwip(rBorder.Distance)));
972     rOuter.SetLine( ScHelperFunctions::GetBorderLine( aLine, rBorder.TopLine ),         SvxBoxItemLine::TOP );
973     rOuter.SetLine( ScHelperFunctions::GetBorderLine( aLine, rBorder.BottomLine ),      SvxBoxItemLine::BOTTOM );
974     rOuter.SetLine( ScHelperFunctions::GetBorderLine( aLine, rBorder.LeftLine ),        SvxBoxItemLine::LEFT );
975     rOuter.SetLine( ScHelperFunctions::GetBorderLine( aLine, rBorder.RightLine ),       SvxBoxItemLine::RIGHT );
976     rInner.SetLine( ScHelperFunctions::GetBorderLine( aLine, rBorder.HorizontalLine ),  SvxBoxInfoItemLine::HORI );
977     rInner.SetLine( ScHelperFunctions::GetBorderLine( aLine, rBorder.VerticalLine ),    SvxBoxInfoItemLine::VERT );
978     rInner.SetValid( SvxBoxInfoItemValidFlags::TOP,      rBorder.IsTopLineValid );
979     rInner.SetValid( SvxBoxInfoItemValidFlags::BOTTOM,   rBorder.IsBottomLineValid );
980     rInner.SetValid( SvxBoxInfoItemValidFlags::LEFT,     rBorder.IsLeftLineValid );
981     rInner.SetValid( SvxBoxInfoItemValidFlags::RIGHT,    rBorder.IsRightLineValid );
982     rInner.SetValid( SvxBoxInfoItemValidFlags::HORI,     rBorder.IsHorizontalLineValid );
983     rInner.SetValid( SvxBoxInfoItemValidFlags::VERT,     rBorder.IsVerticalLineValid );
984     rInner.SetValid( SvxBoxInfoItemValidFlags::DISTANCE, rBorder.IsDistanceValid );
985     rInner.SetTable( true );
986 }
987 }
988 
989 void ScHelperFunctions::FillBoxItems( SvxBoxItem& rOuter, SvxBoxInfoItem& rInner, const table::TableBorder& rBorder )
990 {
991     lcl_fillBoxItems( rOuter, rInner, rBorder);
992 }
993 
994 void ScHelperFunctions::FillBoxItems( SvxBoxItem& rOuter, SvxBoxInfoItem& rInner, const table::TableBorder2& rBorder )
995 {
996     lcl_fillBoxItems( rOuter, rInner, rBorder);
997 }
998 
999 void ScHelperFunctions::FillBorderLine( table::BorderLine& rStruct, const ::editeng::SvxBorderLine* pLine )
1000 {
1001     // Convert from Twips to 1/100mm.
1002     table::BorderLine2 aStruct( SvxBoxItem::SvxLineToLine( pLine, true));
1003     rStruct = aStruct;
1004 }
1005 
1006 void ScHelperFunctions::FillBorderLine( table::BorderLine2& rStruct, const ::editeng::SvxBorderLine* pLine )
1007 {
1008     rStruct = SvxBoxItem::SvxLineToLine( pLine, true);
1009 }
1010 
1011 namespace {
1012 template<typename TableBorderItem>
1013 void lcl_fillTableBorder( TableBorderItem& rBorder, const SvxBoxItem& rOuter, const SvxBoxInfoItem& rInner,
1014         bool bInvalidateHorVerDist )
1015 {
1016     ScHelperFunctions::FillBorderLine( rBorder.TopLine,         rOuter.GetTop() );
1017     ScHelperFunctions::FillBorderLine( rBorder.BottomLine,      rOuter.GetBottom() );
1018     ScHelperFunctions::FillBorderLine( rBorder.LeftLine,        rOuter.GetLeft() );
1019     ScHelperFunctions::FillBorderLine( rBorder.RightLine,       rOuter.GetRight() );
1020     ScHelperFunctions::FillBorderLine( rBorder.HorizontalLine,  rInner.GetHori() );
1021     ScHelperFunctions::FillBorderLine( rBorder.VerticalLine,    rInner.GetVert() );
1022 
1023     rBorder.Distance                = rOuter.GetSmallestDistance();
1024     rBorder.IsTopLineValid          = rInner.IsValid(SvxBoxInfoItemValidFlags::TOP);
1025     rBorder.IsBottomLineValid       = rInner.IsValid(SvxBoxInfoItemValidFlags::BOTTOM);
1026     rBorder.IsLeftLineValid         = rInner.IsValid(SvxBoxInfoItemValidFlags::LEFT);
1027     rBorder.IsRightLineValid        = rInner.IsValid(SvxBoxInfoItemValidFlags::RIGHT);
1028     rBorder.IsHorizontalLineValid   = !bInvalidateHorVerDist && rInner.IsValid(SvxBoxInfoItemValidFlags::HORI);
1029     rBorder.IsVerticalLineValid     = !bInvalidateHorVerDist && rInner.IsValid(SvxBoxInfoItemValidFlags::VERT);
1030     rBorder.IsDistanceValid         = !bInvalidateHorVerDist && rInner.IsValid(SvxBoxInfoItemValidFlags::DISTANCE);
1031 }
1032 }
1033 
1034 void ScHelperFunctions::AssignTableBorderToAny( uno::Any& rAny,
1035         const SvxBoxItem& rOuter, const SvxBoxInfoItem& rInner, bool bInvalidateHorVerDist )
1036 {
1037     table::TableBorder aBorder;
1038     lcl_fillTableBorder( aBorder, rOuter, rInner, bInvalidateHorVerDist);
1039     rAny <<= aBorder;
1040 }
1041 
1042 void ScHelperFunctions::AssignTableBorder2ToAny( uno::Any& rAny,
1043         const SvxBoxItem& rOuter, const SvxBoxInfoItem& rInner, bool bInvalidateHorVerDist )
1044 {
1045     table::TableBorder2 aBorder;
1046     lcl_fillTableBorder( aBorder, rOuter, rInner, bInvalidateHorVerDist);
1047     rAny <<= aBorder;
1048 }
1049 
1050 //! move lcl_ApplyBorder to docfunc !
1051 
1052 void ScHelperFunctions::ApplyBorder( ScDocShell* pDocShell, const ScRangeList& rRanges,
1053                         const SvxBoxItem& rOuter, const SvxBoxInfoItem& rInner )
1054 {
1055     ScDocument& rDoc = pDocShell->GetDocument();
1056     bool bUndo(rDoc.IsUndoEnabled());
1057     ScDocumentUniquePtr pUndoDoc;
1058     if (bUndo)
1059         pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
1060     size_t nCount = rRanges.size();
1061     for (size_t i = 0; i < nCount; ++i)
1062     {
1063         ScRange const & rRange = rRanges[ i ];
1064         SCTAB nTab = rRange.aStart.Tab();
1065 
1066         if (bUndo)
1067         {
1068             if ( i==0 )
1069                 pUndoDoc->InitUndo( rDoc, nTab, nTab );
1070             else
1071                 pUndoDoc->AddUndoTab( nTab, nTab );
1072             rDoc.CopyToDocument(rRange, InsertDeleteFlags::ATTRIB, false, *pUndoDoc);
1073         }
1074 
1075         ScMarkData aMark(rDoc.GetSheetLimits());
1076         aMark.SetMarkArea( rRange );
1077         aMark.SelectTable( nTab, true );
1078 
1079         rDoc.ApplySelectionFrame(aMark, rOuter, &rInner);
1080         // don't need RowHeight if there is only a border
1081     }
1082 
1083     if (bUndo)
1084     {
1085         pDocShell->GetUndoManager()->AddUndoAction(
1086                 std::make_unique<ScUndoBorder>( pDocShell, rRanges, std::move(pUndoDoc), rOuter, rInner ) );
1087     }
1088 
1089     for (size_t i = 0; i < nCount; ++i )
1090         pDocShell->PostPaint( rRanges[ i ], PaintPartFlags::Grid, SC_PF_LINES | SC_PF_TESTMERGE );
1091 
1092     pDocShell->SetDocumentModified();
1093 }
1094 
1095 //! move lcl_PutDataArray to docfunc?
1096 //! merge loop with ScFunctionAccess::callFunction
1097 
1098 static bool lcl_PutDataArray( ScDocShell& rDocShell, const ScRange& rRange,
1099                         const uno::Sequence< uno::Sequence<uno::Any> >& aData )
1100 {
1101     ScDocument& rDoc = rDocShell.GetDocument();
1102     SCTAB nTab = rRange.aStart.Tab();
1103     SCCOL nStartCol = rRange.aStart.Col();
1104     SCROW nStartRow = rRange.aStart.Row();
1105     SCCOL nEndCol = rRange.aEnd.Col();
1106     SCROW nEndRow = rRange.aEnd.Row();
1107     bool bUndo(rDoc.IsUndoEnabled());
1108 
1109     if ( !rDoc.IsBlockEditable( nTab, nStartCol,nStartRow, nEndCol,nEndRow ) )
1110     {
1111         //! error message
1112         return false;
1113     }
1114 
1115     sal_Int32 nCols = 0;
1116     sal_Int32 nRows = aData.getLength();
1117     if ( nRows )
1118         nCols = aData[0].getLength();
1119 
1120     if ( nCols != nEndCol-nStartCol+1 || nRows != nEndRow-nStartRow+1 )
1121     {
1122         //! error message?
1123         return false;
1124     }
1125 
1126     ScDocumentUniquePtr pUndoDoc;
1127     if ( bUndo )
1128     {
1129         pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
1130         pUndoDoc->InitUndo( rDoc, nTab, nTab );
1131         rDoc.CopyToDocument(rRange, InsertDeleteFlags::CONTENTS|InsertDeleteFlags::NOCAPTIONS, false, *pUndoDoc);
1132     }
1133 
1134     rDoc.DeleteAreaTab( nStartCol, nStartRow, nEndCol, nEndRow, nTab, InsertDeleteFlags::CONTENTS );
1135 
1136     bool bError = false;
1137     SCROW nDocRow = nStartRow;
1138     for (const uno::Sequence<uno::Any>& rColSeq : aData)
1139     {
1140         if ( rColSeq.getLength() == nCols )
1141         {
1142             SCCOL nDocCol = nStartCol;
1143             for (const uno::Any& rElement : rColSeq)
1144             {
1145                 ScAddress aPos(nDocCol, nDocRow, nTab);
1146 
1147                 switch( rElement.getValueTypeClass() )
1148                 {
1149                     case uno::TypeClass_VOID:
1150                     {
1151                         // void = "no value"
1152                         rDoc.SetError( nDocCol, nDocRow, nTab, FormulaError::NotAvailable );
1153                     }
1154                     break;
1155 
1156                     //  #87871# accept integer types because Basic passes a floating point
1157                     //  variable as byte, short or long if it's an integer number.
1158                     case uno::TypeClass_BYTE:
1159                     case uno::TypeClass_SHORT:
1160                     case uno::TypeClass_UNSIGNED_SHORT:
1161                     case uno::TypeClass_LONG:
1162                     case uno::TypeClass_UNSIGNED_LONG:
1163                     case uno::TypeClass_FLOAT:
1164                     case uno::TypeClass_DOUBLE:
1165                     {
1166                         double fVal(0.0);
1167                         rElement >>= fVal;
1168                         rDoc.SetValue(aPos, fVal);
1169                     }
1170                     break;
1171 
1172                     case uno::TypeClass_STRING:
1173                     {
1174                         OUString aUStr;
1175                         rElement >>= aUStr;
1176                         if ( !aUStr.isEmpty() )
1177                         {
1178                             ScSetStringParam aParam;
1179                             aParam.setTextInput();
1180                             rDoc.SetString(aPos, aUStr, &aParam);
1181                         }
1182                     }
1183                     break;
1184 
1185                     // accept Sequence<FormulaToken> for formula cells
1186                     case uno::TypeClass_SEQUENCE:
1187                     {
1188                         uno::Sequence< sheet::FormulaToken > aTokens;
1189                         if ( rElement >>= aTokens )
1190                         {
1191                             ScTokenArray aTokenArray(rDoc);
1192                             ScTokenConversion::ConvertToTokenArray( rDoc, aTokenArray, aTokens );
1193                             rDoc.SetFormula(aPos, aTokenArray);
1194                         }
1195                         else
1196                             bError = true;
1197                     }
1198                     break;
1199 
1200                     default:
1201                         bError = true;      // invalid type
1202                 }
1203                 ++nDocCol;
1204             }
1205         }
1206         else
1207             bError = true;                          // wrong size
1208 
1209         ++nDocRow;
1210     }
1211 
1212     bool bHeight = rDocShell.AdjustRowHeight( nStartRow, nEndRow, nTab );
1213 
1214     if ( pUndoDoc )
1215     {
1216         ScMarkData aDestMark(rDoc.GetSheetLimits());
1217         aDestMark.SelectOneTable( nTab );
1218         rDocShell.GetUndoManager()->AddUndoAction(
1219             std::make_unique<ScUndoPaste>(
1220                 &rDocShell, ScRange(nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab),
1221                 aDestMark, std::move(pUndoDoc), nullptr, InsertDeleteFlags::CONTENTS, nullptr, false));
1222     }
1223 
1224     if (!bHeight)
1225         rDocShell.PostPaint( rRange, PaintPartFlags::Grid );      // AdjustRowHeight may have painted already
1226 
1227     rDocShell.SetDocumentModified();
1228 
1229     return !bError;
1230 }
1231 
1232 static bool lcl_PutFormulaArray( ScDocShell& rDocShell, const ScRange& rRange,
1233         const uno::Sequence< uno::Sequence<OUString> >& aData,
1234         const formula::FormulaGrammar::Grammar eGrammar )
1235 {
1236     ScDocument& rDoc = rDocShell.GetDocument();
1237     SCTAB nTab = rRange.aStart.Tab();
1238     SCCOL nStartCol = rRange.aStart.Col();
1239     SCROW nStartRow = rRange.aStart.Row();
1240     SCCOL nEndCol = rRange.aEnd.Col();
1241     SCROW nEndRow = rRange.aEnd.Row();
1242     bool bUndo(rDoc.IsUndoEnabled());
1243 
1244     if ( !rDoc.IsBlockEditable( nTab, nStartCol,nStartRow, nEndCol,nEndRow ) )
1245     {
1246         //! error message
1247         return false;
1248     }
1249 
1250     sal_Int32 nCols = 0;
1251     sal_Int32 nRows = aData.getLength();
1252     if ( nRows )
1253         nCols = aData[0].getLength();
1254 
1255     if ( nCols != nEndCol-nStartCol+1 || nRows != nEndRow-nStartRow+1 )
1256     {
1257         //! error message?
1258         return false;
1259     }
1260 
1261     ScDocumentUniquePtr pUndoDoc;
1262     if ( bUndo )
1263     {
1264         pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
1265         pUndoDoc->InitUndo( rDoc, nTab, nTab );
1266         rDoc.CopyToDocument(rRange, InsertDeleteFlags::CONTENTS, false, *pUndoDoc);
1267     }
1268 
1269     rDoc.DeleteAreaTab( nStartCol, nStartRow, nEndCol, nEndRow, nTab, InsertDeleteFlags::CONTENTS );
1270 
1271     bool bError = false;
1272     SCROW nDocRow = nStartRow;
1273     for (const uno::Sequence<OUString>& rColSeq : aData)
1274     {
1275         if ( rColSeq.getLength() == nCols )
1276         {
1277             SCCOL nDocCol = nStartCol;
1278             for (const OUString& aText : rColSeq)
1279             {
1280                 ScAddress aPos( nDocCol, nDocRow, nTab );
1281 
1282                 ScInputStringType aRes =
1283                     ScStringUtil::parseInputString(
1284                         *rDoc.GetFormatTable(), aText, LANGUAGE_ENGLISH_US);
1285                 switch (aRes.meType)
1286                 {
1287                     case ScInputStringType::Formula:
1288                         rDoc.SetFormula(aPos, aRes.maText, eGrammar);
1289                     break;
1290                     case ScInputStringType::Number:
1291                         rDoc.SetValue(aPos, aRes.mfValue);
1292                     break;
1293                     case ScInputStringType::Text:
1294                         rDoc.SetTextCell(aPos, aRes.maText);
1295                     break;
1296                     default:
1297                         ;
1298                 }
1299 
1300                 ++nDocCol;
1301             }
1302         }
1303         else
1304             bError = true;                          // wrong size
1305 
1306         ++nDocRow;
1307     }
1308 
1309     bool bHeight = rDocShell.AdjustRowHeight( nStartRow, nEndRow, nTab );
1310 
1311     if ( pUndoDoc )
1312     {
1313         ScMarkData aDestMark(rDoc.GetSheetLimits());
1314         aDestMark.SelectOneTable( nTab );
1315         rDocShell.GetUndoManager()->AddUndoAction(
1316             std::make_unique<ScUndoPaste>( &rDocShell,
1317                 ScRange(nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab), aDestMark,
1318                 std::move(pUndoDoc), nullptr, InsertDeleteFlags::CONTENTS, nullptr, false));
1319     }
1320 
1321     if (!bHeight)
1322         rDocShell.PostPaint( rRange, PaintPartFlags::Grid );      // AdjustRowHeight may have painted already
1323 
1324     rDocShell.SetDocumentModified();
1325 
1326     return !bError;
1327 }
1328 
1329 //  used in ScCellRangeObj::getFormulaArray and ScCellObj::GetInputString_Impl
1330 static OUString lcl_GetInputString( ScDocument& rDoc, const ScAddress& rPos, bool bEnglish )
1331 {
1332     ScRefCellValue aCell(rDoc, rPos);
1333     if (aCell.isEmpty())
1334         return EMPTY_OUSTRING;
1335 
1336     OUString aVal;
1337 
1338     CellType eType = aCell.meType;
1339     if (eType == CELLTYPE_FORMULA)
1340     {
1341         ScFormulaCell* pForm = aCell.mpFormula;
1342         pForm->GetFormula( aVal, formula::FormulaGrammar::mapAPItoGrammar( bEnglish, false));
1343         return aVal;
1344     }
1345 
1346     SvNumberFormatter* pFormatter = bEnglish ? ScGlobal::GetEnglishFormatter() :
1347                                                 rDoc.GetFormatTable();
1348     // Since the English formatter was constructed with
1349     // LANGUAGE_ENGLISH_US the "General" format has index key 0,
1350     // we don't have to query.
1351     sal_uInt32 nNumFmt = bEnglish ? 0 : rDoc.GetNumberFormat(rPos);
1352 
1353     if (eType == CELLTYPE_EDIT)
1354     {
1355         //  GetString on EditCell turns breaks into spaces,
1356         //  but we need the breaks here
1357         const EditTextObject* pData = aCell.mpEditText;
1358         if (pData)
1359         {
1360             EditEngine& rEngine = rDoc.GetEditEngine();
1361             rEngine.SetText(*pData);
1362             aVal = rEngine.GetText();
1363         }
1364     }
1365     else
1366         ScCellFormat::GetInputString(aCell, nNumFmt, aVal, *pFormatter, rDoc);
1367 
1368     //  if applicable, prepend ' like in ScTabViewShell::UpdateInputHandler
1369     if ( eType == CELLTYPE_STRING || eType == CELLTYPE_EDIT )
1370     {
1371         double fDummy;
1372         OUString aTempString = aVal;
1373         bool bIsNumberFormat(pFormatter->IsNumberFormat(aTempString, nNumFmt, fDummy));
1374         if ( bIsNumberFormat )
1375             aTempString = "'" + aTempString;
1376         else if ( aTempString.startsWith("'") )
1377         {
1378             //  if the string starts with a "'", add another one because setFormula
1379             //  strips one (like text input, except for "text" number formats)
1380             if ( bEnglish || ( pFormatter->GetType(nNumFmt) != SvNumFormatType::TEXT ) )
1381                 aTempString = "'" + aTempString;
1382         }
1383         aVal = aTempString;
1384     }
1385     return aVal;
1386 }
1387 
1388 ScCellRangesBase::ScCellRangesBase(ScDocShell* pDocSh, const ScRange& rR) :
1389     pPropSet(lcl_GetCellsPropertySet()),
1390     pDocShell( pDocSh ),
1391     nObjectId( 0 ),
1392     bChartColAsHdr( false ),
1393     bChartRowAsHdr( false ),
1394     bCursorOnly( false ),
1395     bGotDataChangedHint( false ),
1396     aValueListeners( 0 )
1397 {
1398     // this is a hack to get m_wThis initialized; ideally there would be
1399     // factory functions doing this but there are so many subclasses of this...
1400     osl_atomic_increment(&m_refCount);
1401     {
1402         m_wThis = uno::Reference<uno::XInterface>(
1403                     static_cast<cppu::OWeakObject*>(this));
1404     }
1405     osl_atomic_decrement(&m_refCount);
1406 
1407     ScRange aCellRange(rR);
1408     aCellRange.PutInOrder();
1409     aRanges.push_back( aCellRange );
1410 
1411     if (pDocShell)  // Null if created with createInstance
1412     {
1413         ScDocument& rDoc = pDocShell->GetDocument();
1414         rDoc.AddUnoObject(*this);
1415         nObjectId = rDoc.GetNewUnoId();
1416     }
1417 }
1418 
1419 ScCellRangesBase::ScCellRangesBase(ScDocShell* pDocSh, const ScRangeList& rR) :
1420     pPropSet(lcl_GetCellsPropertySet()),
1421     pDocShell( pDocSh ),
1422     aRanges( rR ),
1423     nObjectId( 0 ),
1424     bChartColAsHdr( false ),
1425     bChartRowAsHdr( false ),
1426     bCursorOnly( false ),
1427     bGotDataChangedHint( false ),
1428     aValueListeners( 0 )
1429 {
1430     // this is a hack to get m_wThis initialized; ideally there would be
1431     // factory functions doing this but there are so many subclasses of this...
1432     osl_atomic_increment(&m_refCount);
1433     {
1434         m_wThis = uno::Reference<uno::XInterface>(
1435                     static_cast<cppu::OWeakObject*>(this));
1436     }
1437     osl_atomic_decrement(&m_refCount);
1438 
1439     if (pDocShell)  // Null if created with createInstance
1440     {
1441         ScDocument& rDoc = pDocShell->GetDocument();
1442         rDoc.AddUnoObject(*this);
1443         nObjectId = rDoc.GetNewUnoId();
1444     }
1445 }
1446 
1447 ScCellRangesBase::~ScCellRangesBase()
1448 {
1449     SolarMutexGuard g;
1450 
1451     //  call RemoveUnoObject first, so no notification can happen
1452     //  during ForgetCurrentAttrs
1453 
1454     if (pDocShell)
1455         pDocShell->GetDocument().RemoveUnoObject(*this);
1456 
1457     ForgetCurrentAttrs();
1458     ForgetMarkData();
1459 
1460     pValueListener.reset();
1461 
1462     //! unregister XChartDataChangeEventListener ??
1463     //! (ChartCollection will then hold this object as well!)
1464 }
1465 
1466 void ScCellRangesBase::ForgetCurrentAttrs()
1467 {
1468     pCurrentFlat.reset();
1469     pCurrentDeep.reset();
1470     pCurrentDataSet.reset();
1471     pNoDfltCurrentDataSet.reset();
1472     pCurrentDataSet = nullptr;
1473     pNoDfltCurrentDataSet = nullptr;
1474 
1475     // #i62483# pMarkData can remain unchanged, is deleted only if the range changes (RefChanged)
1476 }
1477 
1478 void ScCellRangesBase::ForgetMarkData()
1479 {
1480     pMarkData.reset();
1481 }
1482 
1483 const ScPatternAttr* ScCellRangesBase::GetCurrentAttrsFlat()
1484 {
1485     //  get and cache direct cell attributes for this object's range
1486 
1487     if ( !pCurrentFlat && pDocShell )
1488     {
1489         ScDocument& rDoc = pDocShell->GetDocument();
1490         pCurrentFlat = rDoc.CreateSelectionPattern( *GetMarkData(), false );
1491     }
1492     return pCurrentFlat.get();
1493 }
1494 
1495 const ScPatternAttr* ScCellRangesBase::GetCurrentAttrsDeep()
1496 {
1497     //  get and cache cell attributes (incl. styles) for this object's range
1498 
1499     if ( !pCurrentDeep && pDocShell )
1500     {
1501         ScDocument& rDoc = pDocShell->GetDocument();
1502         pCurrentDeep = rDoc.CreateSelectionPattern( *GetMarkData() );
1503     }
1504     return pCurrentDeep.get();
1505 }
1506 
1507 SfxItemSet* ScCellRangesBase::GetCurrentDataSet(bool bNoDflt)
1508 {
1509     if(!pCurrentDataSet)
1510     {
1511         const ScPatternAttr* pPattern = GetCurrentAttrsDeep();
1512         if ( pPattern )
1513         {
1514             //  replace Dontcare with Default,  so that we always have a reflection
1515             pCurrentDataSet.reset( new SfxItemSet( pPattern->GetItemSet() ) );
1516             pNoDfltCurrentDataSet.reset( new SfxItemSet( pPattern->GetItemSet() ) );
1517             pCurrentDataSet->ClearInvalidItems();
1518         }
1519     }
1520     return bNoDflt ? pNoDfltCurrentDataSet.get() : pCurrentDataSet.get();
1521 }
1522 
1523 const ScMarkData* ScCellRangesBase::GetMarkData()
1524 {
1525     if (!pMarkData)
1526     {
1527         pMarkData.reset( new ScMarkData(GetDocument()->GetSheetLimits(), aRanges) );
1528     }
1529     return pMarkData.get();
1530 }
1531 
1532 void ScCellRangesBase::Notify( SfxBroadcaster&, const SfxHint& rHint )
1533 {
1534     uno::Reference<uno::XInterface> const xThis(m_wThis);
1535     if (!xThis.is())
1536     {   // fdo#72695: if UNO object is already dead, don't revive it with event
1537         if (SfxHintId::Dying == rHint.GetId())
1538         {   // if the document dies, must reset to avoid crash in dtor!
1539             ForgetCurrentAttrs();
1540             pDocShell = nullptr;
1541         }
1542         return;
1543     }
1544     if ( auto pRefHint = dynamic_cast<const ScUpdateRefHint*>(&rHint) )
1545     {
1546         ScDocument& rDoc = pDocShell->GetDocument();
1547         std::unique_ptr<ScRangeList> pUndoRanges;
1548         if ( rDoc.HasUnoRefUndo() )
1549             pUndoRanges.reset(new ScRangeList( aRanges ));
1550 
1551         if ( aRanges.UpdateReference( pRefHint->GetMode(), &rDoc, pRefHint->GetRange(),
1552                                     pRefHint->GetDx(), pRefHint->GetDy(), pRefHint->GetDz() ) )
1553         {
1554             if (  pRefHint->GetMode() == URM_INSDEL
1555                && aRanges.size() == 1
1556                && comphelper::getUnoTunnelImplementation<ScTableSheetObj>(xThis)
1557                )
1558             {
1559                 // #101755#; the range size of a sheet does not change
1560                 ScRange & rR = aRanges.front();
1561                 rR.aStart.SetCol(0);
1562                 rR.aStart.SetRow(0);
1563                 rR.aEnd.SetCol(rDoc.MaxCol());
1564                 rR.aEnd.SetRow(rDoc.MaxRow());
1565             }
1566             RefChanged();
1567 
1568             // any change of the range address is broadcast to value (modify) listeners
1569             if ( !aValueListeners.empty() )
1570                 bGotDataChangedHint = true;
1571 
1572             if ( pUndoRanges )
1573                 rDoc.AddUnoRefChange( nObjectId, *pUndoRanges );
1574         }
1575     }
1576     else if ( auto pUndoHint = dynamic_cast<const ScUnoRefUndoHint*>(&rHint) )
1577     {
1578         if ( pUndoHint->GetObjectId() == nObjectId )
1579         {
1580             // restore ranges from hint
1581 
1582             aRanges = pUndoHint->GetRanges();
1583 
1584             RefChanged();
1585             if ( !aValueListeners.empty() )
1586                 bGotDataChangedHint = true;     // need to broadcast the undo, too
1587         }
1588     }
1589     else
1590     {
1591         const SfxHintId nId = rHint.GetId();
1592         if ( nId == SfxHintId::Dying )
1593         {
1594             ForgetCurrentAttrs();
1595             pDocShell = nullptr;           // invalid
1596 
1597             if ( !aValueListeners.empty() )
1598             {
1599                 //  dispose listeners
1600 
1601                 lang::EventObject aEvent;
1602                 aEvent.Source.set(static_cast<cppu::OWeakObject*>(this));
1603                 for (uno::Reference<util::XModifyListener> & xValueListener : aValueListeners)
1604                     xValueListener->disposing( aEvent );
1605 
1606                 aValueListeners.clear();
1607 
1608                 //  The listeners can't have the last ref to this, as it's still held
1609                 //  by the DocShell.
1610             }
1611         }
1612         else if ( nId == SfxHintId::DataChanged )
1613         {
1614             // document content changed -> forget cached attributes
1615             ForgetCurrentAttrs();
1616 
1617             if ( bGotDataChangedHint && pDocShell )
1618             {
1619                 //  This object was notified of content changes, so one call
1620                 //  for each listener is generated now.
1621                 //  The calls can't be executed directly because the document's
1622                 //  UNO broadcaster list must not be modified.
1623                 //  Instead, add to the document's list of listener calls,
1624                 //  which will be executed directly after the broadcast of
1625                 //  SfxHintId::DataChanged.
1626 
1627                 lang::EventObject aEvent;
1628                 aEvent.Source.set(static_cast<cppu::OWeakObject*>(this));
1629 
1630                 // the EventObject holds a Ref to this object until after the listener calls
1631 
1632                 ScDocument& rDoc = pDocShell->GetDocument();
1633                 for (const uno::Reference<util::XModifyListener> & xValueListener : aValueListeners)
1634                     rDoc.AddUnoListenerCall( xValueListener, aEvent );
1635 
1636                 bGotDataChangedHint = false;
1637             }
1638         }
1639         else if ( nId == SfxHintId::ScCalcAll )
1640         {
1641             // broadcast from DoHardRecalc - set bGotDataChangedHint
1642             // (SfxHintId::DataChanged follows separately)
1643 
1644             if ( !aValueListeners.empty() )
1645                 bGotDataChangedHint = true;
1646         }
1647     }
1648 }
1649 
1650 void ScCellRangesBase::RefChanged()
1651 {
1652     //! adjust XChartDataChangeEventListener
1653 
1654     if ( pValueListener && !aValueListeners.empty() )
1655     {
1656         pValueListener->EndListeningAll();
1657 
1658         ScDocument& rDoc = pDocShell->GetDocument();
1659         for ( size_t i = 0, nCount = aRanges.size(); i < nCount; ++i )
1660             rDoc.StartListeningArea( aRanges[ i ], false, pValueListener.get() );
1661     }
1662 
1663     ForgetCurrentAttrs();
1664     ForgetMarkData();
1665 }
1666 
1667 ScDocument* ScCellRangesBase::GetDocument() const
1668 {
1669     if (pDocShell)
1670         return &pDocShell->GetDocument();
1671     else
1672         return nullptr;
1673 }
1674 
1675 void ScCellRangesBase::InitInsertRange(ScDocShell* pDocSh, const ScRange& rR)
1676 {
1677     if ( pDocShell || !pDocSh )
1678         return;
1679 
1680     pDocShell = pDocSh;
1681 
1682     ScRange aCellRange(rR);
1683     aCellRange.PutInOrder();
1684     aRanges.RemoveAll();
1685     aRanges.push_back( aCellRange );
1686 
1687     pDocShell->GetDocument().AddUnoObject(*this);
1688 
1689     RefChanged();   // adjust range in range object
1690 }
1691 
1692 void ScCellRangesBase::AddRange(const ScRange& rRange, const bool bMergeRanges)
1693 {
1694     if (bMergeRanges)
1695         aRanges.Join(rRange);
1696     else
1697         aRanges.push_back(rRange);
1698     RefChanged();
1699 }
1700 
1701 void ScCellRangesBase::SetNewRange(const ScRange& rNew)
1702 {
1703     ScRange aCellRange(rNew);
1704     aCellRange.PutInOrder();
1705 
1706     aRanges.RemoveAll();
1707     aRanges.push_back( aCellRange );
1708     RefChanged();
1709 }
1710 
1711 void ScCellRangesBase::SetNewRanges(const ScRangeList& rNew)
1712 {
1713     aRanges = rNew;
1714     RefChanged();
1715 }
1716 
1717 void ScCellRangesBase::SetCursorOnly( bool bSet )
1718 {
1719     //  set for a selection object that is created from the cursor position
1720     //  without anything selected (may contain several sheets)
1721 
1722     bCursorOnly = bSet;
1723 }
1724 
1725 void ScCellRangesBase::PaintGridRanges_Impl( )
1726 {
1727     for (size_t i = 0, nCount = aRanges.size(); i < nCount; ++i)
1728         pDocShell->PostPaint( aRanges[ i ], PaintPartFlags::Grid );
1729 }
1730 
1731 // XSheetOperation
1732 
1733 double SAL_CALL ScCellRangesBase::computeFunction( sheet::GeneralFunction nFunction )
1734 {
1735     SolarMutexGuard aGuard;
1736     ScMarkData aMark(*GetMarkData());
1737     aMark.MarkToSimple();
1738     if (!aMark.IsMarked())
1739         aMark.SetMarkNegative(true);    // so we can enter dummy position
1740 
1741     ScAddress aDummy;                   // if not marked, ignored if it is negative
1742     double fVal;
1743     ScSubTotalFunc eFunc = ScDPUtil::toSubTotalFunc(static_cast<ScGeneralFunction>(nFunction));
1744     ScDocument& rDoc = pDocShell->GetDocument();
1745     if ( !rDoc.GetSelectionFunction( eFunc, aDummy, aMark, fVal ) )
1746     {
1747         throw uno::RuntimeException();      //! own exception?
1748     }
1749 
1750     return fVal;
1751 }
1752 
1753 void SAL_CALL ScCellRangesBase::clearContents( sal_Int32 nContentFlags )
1754 {
1755     SolarMutexGuard aGuard;
1756     if ( !aRanges.empty() )
1757     {
1758         // only for clearContents: EDITATTR is only used if no contents are deleted
1759         InsertDeleteFlags nDelFlags = static_cast<InsertDeleteFlags>(nContentFlags) & InsertDeleteFlags::ALL;
1760         if ( ( nDelFlags & InsertDeleteFlags::EDITATTR ) && ( nDelFlags & InsertDeleteFlags::CONTENTS ) == InsertDeleteFlags::NONE )
1761             nDelFlags |= InsertDeleteFlags::EDITATTR;
1762 
1763         pDocShell->GetDocFunc().DeleteContents( *GetMarkData(), nDelFlags, true, true );
1764     }
1765     // otherwise nothing to do
1766 }
1767 
1768 // XPropertyState
1769 
1770 const SfxItemPropertyMap& ScCellRangesBase::GetItemPropertyMap()
1771 {
1772     return pPropSet->getPropertyMap();
1773 }
1774 
1775 static void lcl_GetPropertyWhich( const SfxItemPropertySimpleEntry* pEntry,
1776                                                 sal_uInt16& rItemWhich )
1777 {
1778     //  Which-ID of the affected items also when the item can't handle
1779     //  the property by itself
1780     if ( !pEntry )
1781         return;
1782 
1783     if ( IsScItemWid( pEntry->nWID ) )
1784         rItemWhich = pEntry->nWID;
1785     else
1786         switch ( pEntry->nWID )
1787         {
1788             case SC_WID_UNO_TBLBORD:
1789             case SC_WID_UNO_TBLBORD2:
1790                 rItemWhich = ATTR_BORDER;
1791                 break;
1792             case SC_WID_UNO_CONDFMT:
1793             case SC_WID_UNO_CONDLOC:
1794             case SC_WID_UNO_CONDXML:
1795                 rItemWhich = ATTR_CONDITIONAL;
1796                 break;
1797             case SC_WID_UNO_VALIDAT:
1798             case SC_WID_UNO_VALILOC:
1799             case SC_WID_UNO_VALIXML:
1800                 rItemWhich = ATTR_VALIDDATA;
1801                 break;
1802         }
1803 
1804 }
1805 
1806 beans::PropertyState ScCellRangesBase::GetOnePropertyState( sal_uInt16 nItemWhich, const SfxItemPropertySimpleEntry* pEntry )
1807 {
1808     beans::PropertyState eRet = beans::PropertyState_DIRECT_VALUE;
1809     if ( nItemWhich )                   // item wid (from map or special case)
1810     {
1811         //  For items that contain several properties (like background),
1812         //  "ambiguous" is returned too often here
1813 
1814         //  for PropertyState, don't look at styles
1815         const ScPatternAttr* pPattern = GetCurrentAttrsFlat();
1816         if ( pPattern )
1817         {
1818             SfxItemState eState = pPattern->GetItemSet().GetItemState( nItemWhich, false );
1819 
1820             if ( nItemWhich == ATTR_VALUE_FORMAT && eState == SfxItemState::DEFAULT )
1821                 eState = pPattern->GetItemSet().GetItemState( ATTR_LANGUAGE_FORMAT, false );
1822 
1823             if ( eState == SfxItemState::SET )
1824                 eRet = beans::PropertyState_DIRECT_VALUE;
1825             else if ( eState == SfxItemState::DEFAULT )
1826                 eRet = beans::PropertyState_DEFAULT_VALUE;
1827             else if ( eState == SfxItemState::DONTCARE )
1828                 eRet = beans::PropertyState_AMBIGUOUS_VALUE;
1829             else
1830             {
1831                 OSL_FAIL("unknown ItemState");
1832             }
1833         }
1834     }
1835     else if ( pEntry )
1836     {
1837         if ( pEntry->nWID == SC_WID_UNO_CHCOLHDR || pEntry->nWID == SC_WID_UNO_CHROWHDR || pEntry->nWID == SC_WID_UNO_ABSNAME )
1838             eRet = beans::PropertyState_DIRECT_VALUE;
1839         else if ( pEntry->nWID == SC_WID_UNO_CELLSTYL )
1840         {
1841             //  a style is always set, there's no default state
1842             const ScStyleSheet* pStyle = pDocShell->GetDocument().GetSelectionStyle(*GetMarkData());
1843             if (pStyle)
1844                 eRet = beans::PropertyState_DIRECT_VALUE;
1845             else
1846                 eRet = beans::PropertyState_AMBIGUOUS_VALUE;
1847         }
1848         else if ( pEntry->nWID == SC_WID_UNO_NUMRULES )
1849             eRet = beans::PropertyState_DEFAULT_VALUE;      // numbering rules are always default
1850     }
1851     return eRet;
1852 }
1853 
1854 beans::PropertyState SAL_CALL ScCellRangesBase::getPropertyState( const OUString& aPropertyName )
1855 {
1856     SolarMutexGuard aGuard;
1857     if ( aRanges.empty() )
1858         throw uno::RuntimeException();
1859 
1860     const SfxItemPropertyMap& rMap = GetItemPropertyMap();     // from derived class
1861     sal_uInt16 nItemWhich = 0;
1862     const SfxItemPropertySimpleEntry* pEntry  = rMap.getByName( aPropertyName );
1863     lcl_GetPropertyWhich( pEntry, nItemWhich );
1864     return GetOnePropertyState( nItemWhich, pEntry );
1865 }
1866 
1867 uno::Sequence<beans::PropertyState> SAL_CALL ScCellRangesBase::getPropertyStates(
1868                                 const uno::Sequence<OUString>& aPropertyNames )
1869 {
1870     SolarMutexGuard aGuard;
1871 
1872     const SfxItemPropertyMap& rPropertyMap = GetItemPropertyMap();     // from derived class
1873 
1874     uno::Sequence<beans::PropertyState> aRet(aPropertyNames.getLength());
1875     std::transform(aPropertyNames.begin(), aPropertyNames.end(), aRet.begin(),
1876         [this, &rPropertyMap](const auto& rName) -> beans::PropertyState {
1877             sal_uInt16 nItemWhich = 0;
1878             const SfxItemPropertySimpleEntry* pEntry  = rPropertyMap.getByName( rName );
1879             lcl_GetPropertyWhich( pEntry, nItemWhich );
1880             return GetOnePropertyState(nItemWhich, pEntry);
1881         });
1882     return aRet;
1883 }
1884 
1885 void SAL_CALL ScCellRangesBase::setPropertyToDefault( const OUString& aPropertyName )
1886 {
1887     SolarMutexGuard aGuard;
1888     if ( !pDocShell )
1889         return;
1890 
1891     const SfxItemPropertyMap& rPropertyMap = GetItemPropertyMap();     // from derived class
1892     sal_uInt16 nItemWhich = 0;
1893     const SfxItemPropertySimpleEntry* pEntry  = rPropertyMap.getByName( aPropertyName );
1894     lcl_GetPropertyWhich( pEntry, nItemWhich );
1895     if ( nItemWhich )               // item wid (from map or special case)
1896     {
1897         if ( !aRanges.empty() )     // empty = nothing to do
1898         {
1899             //! for items that have multiple properties (e.g. background)
1900             //! too much will be reset
1901             //! for ATTR_ROTATE_VALUE, reset ATTR_ORIENTATION as well?
1902 
1903             sal_uInt16 aWIDs[3];
1904             aWIDs[0] = nItemWhich;
1905             if ( nItemWhich == ATTR_VALUE_FORMAT )
1906             {
1907                 aWIDs[1] = ATTR_LANGUAGE_FORMAT; // language for number formats
1908                 aWIDs[2] = 0;
1909             }
1910             else
1911                 aWIDs[1] = 0;
1912             pDocShell->GetDocFunc().ClearItems( *GetMarkData(), aWIDs, true );
1913         }
1914     }
1915     else if ( pEntry )
1916     {
1917         if ( pEntry->nWID == SC_WID_UNO_CHCOLHDR )
1918             bChartColAsHdr = false;
1919         else if ( pEntry->nWID == SC_WID_UNO_CHROWHDR )
1920             bChartRowAsHdr = false;
1921         else if ( pEntry->nWID == SC_WID_UNO_CELLSTYL )
1922         {
1923             OUString aStyleName( ScResId( STR_STYLENAME_STANDARD ) );
1924             pDocShell->GetDocFunc().ApplyStyle( *GetMarkData(), aStyleName, true );
1925         }
1926     }
1927 }
1928 
1929 uno::Any SAL_CALL ScCellRangesBase::getPropertyDefault( const OUString& aPropertyName )
1930 {
1931     //! bundle with getPropertyValue
1932 
1933     SolarMutexGuard aGuard;
1934     uno::Any aAny;
1935 
1936     if ( pDocShell )
1937     {
1938         ScDocument& rDoc = pDocShell->GetDocument();
1939         const SfxItemPropertyMap& rPropertyMap = GetItemPropertyMap();     // from derived class
1940         const SfxItemPropertySimpleEntry* pEntry = rPropertyMap.getByName( aPropertyName );
1941         if ( pEntry )
1942         {
1943             if ( IsScItemWid( pEntry->nWID ) )
1944             {
1945                 const ScPatternAttr* pPattern = rDoc.GetDefPattern();
1946                 if ( pPattern )
1947                 {
1948                     const SfxItemSet& rSet = pPattern->GetItemSet();
1949 
1950                     switch ( pEntry->nWID )     // for item-specific handling
1951                     {
1952                         case ATTR_VALUE_FORMAT:
1953                             //  default has no language set
1954                             aAny <<= static_cast<sal_Int32>( static_cast<const SfxUInt32Item&>(rSet.Get(pEntry->nWID)).GetValue() );
1955                             break;
1956                         case ATTR_INDENT:
1957                             aAny <<= static_cast<sal_Int16>( convertTwipToMm100(static_cast<const ScIndentItem&>(
1958                                             rSet.Get(pEntry->nWID)).GetValue()) );
1959                             break;
1960                         default:
1961                             pPropSet->getPropertyValue(aPropertyName, rSet, aAny);
1962                     }
1963                 }
1964             }
1965             else
1966                 switch ( pEntry->nWID )
1967                 {
1968                     case SC_WID_UNO_CHCOLHDR:
1969                     case SC_WID_UNO_CHROWHDR:
1970                         aAny <<= false;
1971                         break;
1972                     case SC_WID_UNO_CELLSTYL:
1973                         aAny <<= ScStyleNameConversion::DisplayToProgrammaticName(
1974                                     ScResId(STR_STYLENAME_STANDARD), SfxStyleFamily::Para );
1975                         break;
1976                     case SC_WID_UNO_TBLBORD:
1977                     case SC_WID_UNO_TBLBORD2:
1978                         {
1979                             const ScPatternAttr* pPattern = rDoc.GetDefPattern();
1980                             if ( pPattern )
1981                             {
1982                                 if (pEntry->nWID == SC_WID_UNO_TBLBORD2)
1983                                     ScHelperFunctions::AssignTableBorder2ToAny( aAny,
1984                                             pPattern->GetItem(ATTR_BORDER),
1985                                             pPattern->GetItem(ATTR_BORDER_INNER) );
1986                                 else
1987                                     ScHelperFunctions::AssignTableBorderToAny( aAny,
1988                                             pPattern->GetItem(ATTR_BORDER),
1989                                             pPattern->GetItem(ATTR_BORDER_INNER) );
1990                             }
1991                         }
1992                         break;
1993                     case SC_WID_UNO_CONDFMT:
1994                     case SC_WID_UNO_CONDLOC:
1995                     case SC_WID_UNO_CONDXML:
1996                         {
1997                             bool bEnglish = ( pEntry->nWID != SC_WID_UNO_CONDLOC );
1998                             bool bXML = ( pEntry->nWID == SC_WID_UNO_CONDXML );
1999                             formula::FormulaGrammar::Grammar eGrammar = (bXML ?
2000                                     rDoc.GetStorageGrammar() :
2001                                    formula::FormulaGrammar::mapAPItoGrammar( bEnglish, bXML));
2002 
2003                             aAny <<= uno::Reference<sheet::XSheetConditionalEntries>(
2004                                     new ScTableConditionalFormat( &rDoc, 0, aRanges[0].aStart.Tab(), eGrammar ));
2005                         }
2006                         break;
2007                     case SC_WID_UNO_VALIDAT:
2008                     case SC_WID_UNO_VALILOC:
2009                     case SC_WID_UNO_VALIXML:
2010                         {
2011                             bool bEnglish = ( pEntry->nWID != SC_WID_UNO_VALILOC );
2012                             bool bXML = ( pEntry->nWID == SC_WID_UNO_VALIXML );
2013                             formula::FormulaGrammar::Grammar eGrammar = (bXML ?
2014                                     rDoc.GetStorageGrammar() :
2015                                    formula::FormulaGrammar::mapAPItoGrammar( bEnglish, bXML));
2016 
2017                             aAny <<= uno::Reference<beans::XPropertySet>(
2018                                     new ScTableValidationObj( rDoc, 0, eGrammar ));
2019                         }
2020                         break;
2021                     case SC_WID_UNO_NUMRULES:
2022                         {
2023                             aAny <<= ScStyleObj::CreateEmptyNumberingRules();
2024                         }
2025                         break;
2026                 }
2027         }
2028     }
2029 
2030     return aAny;
2031 }
2032 
2033 // XPropertySet
2034 
2035 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScCellRangesBase::getPropertySetInfo()
2036 {
2037     SolarMutexGuard aGuard;
2038     static uno::Reference<beans::XPropertySetInfo> aRef(
2039         new SfxItemPropertySetInfo( pPropSet->getPropertyMap() ));
2040     return aRef;
2041 }
2042 
2043 static void lcl_SetCellProperty( const SfxItemPropertySimpleEntry& rEntry, const uno::Any& rValue,
2044                             ScPatternAttr& rPattern, const ScDocument &rDoc,
2045                             sal_uInt16& rFirstItemId, sal_uInt16& rSecondItemId )
2046 {
2047     rFirstItemId = rEntry.nWID;
2048     rSecondItemId = 0;
2049 
2050     SfxItemSet& rSet = rPattern.GetItemSet();
2051     switch ( rEntry.nWID )
2052     {
2053         case ATTR_VALUE_FORMAT:
2054             {
2055                 // language for number formats
2056                 SvNumberFormatter* pFormatter = rDoc.GetFormatTable();
2057                 sal_uLong nOldFormat = rSet.Get( ATTR_VALUE_FORMAT ).GetValue();
2058                 LanguageType eOldLang = rSet.Get( ATTR_LANGUAGE_FORMAT ).GetLanguage();
2059                 nOldFormat = pFormatter->GetFormatForLanguageIfBuiltIn( nOldFormat, eOldLang );
2060 
2061                 sal_Int32 nIntVal = 0;
2062                 if ( !(rValue >>= nIntVal) )
2063                     throw lang::IllegalArgumentException();
2064 
2065                 sal_uLong nNewFormat = static_cast<sal_uLong>(nIntVal);
2066                 rSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNewFormat ) );
2067 
2068                 const SvNumberformat* pNewEntry = pFormatter->GetEntry( nNewFormat );
2069                 LanguageType eNewLang =
2070                     pNewEntry ? pNewEntry->GetLanguage() : LANGUAGE_DONTKNOW;
2071                 if ( eNewLang != eOldLang && eNewLang != LANGUAGE_DONTKNOW )
2072                 {
2073                     rSet.Put( SvxLanguageItem( eNewLang, ATTR_LANGUAGE_FORMAT ) );
2074 
2075                     // if only language is changed,
2076                     // don't touch number format attribute
2077                     sal_uLong nNewMod = nNewFormat % SV_COUNTRY_LANGUAGE_OFFSET;
2078                     if ( nNewMod == ( nOldFormat % SV_COUNTRY_LANGUAGE_OFFSET ) &&
2079                          nNewMod <= SV_MAX_COUNT_STANDARD_FORMATS )
2080                     {
2081                         rFirstItemId = 0;       // don't use ATTR_VALUE_FORMAT value
2082                     }
2083 
2084                     rSecondItemId = ATTR_LANGUAGE_FORMAT;
2085                 }
2086 
2087             }
2088             break;
2089         case ATTR_INDENT:
2090             {
2091                 sal_Int16 nIntVal = 0;
2092                 if ( !(rValue >>= nIntVal) )
2093                     throw lang::IllegalArgumentException();
2094 
2095                 rSet.Put(ScIndentItem(static_cast<sal_uInt16>(convertMm100ToTwip(nIntVal))));
2096 
2097             }
2098             break;
2099         case ATTR_ROTATE_VALUE:
2100             {
2101                 sal_Int32 nRotVal = 0;
2102                 if ( !(rValue >>= nRotVal) )
2103                     throw lang::IllegalArgumentException();
2104 
2105                 //  stored value is always between 0 and 360 deg.
2106                 nRotVal %= 36000;
2107                 if ( nRotVal < 0 )
2108                     nRotVal += 36000;
2109 
2110                 rSet.Put( ScRotateValueItem( Degree100(nRotVal) ) );
2111 
2112             }
2113             break;
2114         case ATTR_STACKED:
2115             {
2116                 table::CellOrientation eOrient;
2117                 if( rValue >>= eOrient )
2118                 {
2119                     switch( eOrient )
2120                     {
2121                         case table::CellOrientation_STANDARD:
2122                             rSet.Put( ScVerticalStackCell( false ) );
2123                         break;
2124                         case table::CellOrientation_TOPBOTTOM:
2125                             rSet.Put( ScVerticalStackCell( false ) );
2126                             rSet.Put( ScRotateValueItem( 27000_deg100 ) );
2127                             rSecondItemId = ATTR_ROTATE_VALUE;
2128                         break;
2129                         case table::CellOrientation_BOTTOMTOP:
2130                             rSet.Put( ScVerticalStackCell( false ) );
2131                             rSet.Put( ScRotateValueItem( 9000_deg100 ) );
2132                             rSecondItemId = ATTR_ROTATE_VALUE;
2133                         break;
2134                         case table::CellOrientation_STACKED:
2135                             rSet.Put( ScVerticalStackCell( true ) );
2136                         break;
2137                         default:
2138                         {
2139                             // added to avoid warnings
2140                         }
2141                     }
2142                 }
2143             }
2144             break;
2145         default:
2146             {
2147                 lcl_GetCellsPropertySet()->setPropertyValue(rEntry, rValue, rSet);
2148             }
2149     }
2150 }
2151 
2152 void SAL_CALL ScCellRangesBase::setPropertyValue(
2153                         const OUString& aPropertyName, const uno::Any& aValue )
2154 {
2155     SolarMutexGuard aGuard;
2156 
2157     if ( !pDocShell || aRanges.empty() )
2158         throw uno::RuntimeException();
2159 
2160     const SfxItemPropertyMap& rPropertyMap = GetItemPropertyMap();     // from derived class
2161     const SfxItemPropertySimpleEntry* pEntry = rPropertyMap.getByName( aPropertyName );
2162     if ( !pEntry )
2163         throw beans::UnknownPropertyException(aPropertyName);
2164 
2165     SetOnePropertyValue( pEntry, aValue );
2166 }
2167 
2168 void ScCellRangesBase::SetOnePropertyValue( const SfxItemPropertySimpleEntry* pEntry, const uno::Any& aValue )
2169 {
2170     if ( !pEntry )
2171         return;
2172 
2173     if ( IsScItemWid( pEntry->nWID ) )
2174     {
2175         if ( !aRanges.empty() )     // empty = nothing to do
2176         {
2177             ScDocument& rDoc = pDocShell->GetDocument();
2178 
2179             //  For parts of compound items with multiple properties (e.g. background)
2180             //  the old item has to be first fetched from the document.
2181             //! But we can't recognize this case here
2182             //! -> an extra flag in PropertyMap entry, or something like that???
2183             //! fetch the item directly from its position in the range?
2184             //  ClearInvalidItems, so that in any case we have an item with the correct type
2185 
2186             ScPatternAttr aPattern( *GetCurrentAttrsDeep() );
2187             SfxItemSet& rSet = aPattern.GetItemSet();
2188             rSet.ClearInvalidItems();
2189 
2190             sal_uInt16 nFirstItem, nSecondItem;
2191             lcl_SetCellProperty( *pEntry, aValue, aPattern, rDoc, nFirstItem, nSecondItem );
2192 
2193             for (sal_uInt16 nWhich = ATTR_PATTERN_START; nWhich <= ATTR_PATTERN_END; nWhich++)
2194                 if ( nWhich != nFirstItem && nWhich != nSecondItem )
2195                     rSet.ClearItem(nWhich);
2196 
2197             pDocShell->GetDocFunc().ApplyAttributes( *GetMarkData(), aPattern, true );
2198         }
2199     }
2200     else        // implemented here
2201         switch ( pEntry->nWID )
2202         {
2203             case EE_CHAR_ESCAPEMENT:    // Specifically for xlsx import
2204             {
2205                 sal_Int32 nValue = 0;
2206                 aValue >>= nValue;
2207                 if (nValue)
2208                 {
2209                     for (size_t i = 0, n = aRanges.size(); i < n; ++i)
2210                     {
2211                         ScRange const & rRange = aRanges[i];
2212 
2213                         /* TODO: Iterate through the range */
2214                         ScAddress aAddr = rRange.aStart;
2215                         ScDocument& rDoc = pDocShell->GetDocument();
2216                         ScRefCellValue aCell(rDoc, aAddr);
2217 
2218                         OUString aStr = aCell.getString(&rDoc);
2219                         EditEngine aEngine( rDoc.GetEnginePool() );
2220                         aEngine.SetEditTextObjectPool(rDoc.GetEditPool());
2221 
2222                         /* EE_CHAR_ESCAPEMENT seems to be set on the cell _only_ when
2223                          * there are no other attribs for the cell.
2224                          * So, it is safe to overwrite the complete attribute set.
2225                          * If there is a need - getting CellType and processing
2226                          * the attributes could be considered.
2227                          */
2228                         SfxItemSet aAttr = aEngine.GetEmptyItemSet();
2229                         aEngine.SetText(aStr);
2230                         if( nValue < 0 )    // Subscript
2231                             aAttr.Put( SvxEscapementItem( SvxEscapement::Subscript, EE_CHAR_ESCAPEMENT ) );
2232                         else                // Superscript
2233                             aAttr.Put( SvxEscapementItem( SvxEscapement::Superscript, EE_CHAR_ESCAPEMENT ) );
2234                         aEngine.QuickSetAttribs(aAttr, ESelection(0, 0, 0, aStr.getLength()));
2235 
2236                         // The cell will own the text object instance.
2237                         rDoc.SetEditText(aRanges[0].aStart, aEngine.CreateTextObject());
2238                     }
2239                 }
2240             }
2241             break;
2242             case SC_WID_UNO_CHCOLHDR:
2243                 // chart header flags are set for this object, not stored with document
2244                 bChartColAsHdr = ScUnoHelpFunctions::GetBoolFromAny( aValue );
2245                 break;
2246             case SC_WID_UNO_CHROWHDR:
2247                 bChartRowAsHdr = ScUnoHelpFunctions::GetBoolFromAny( aValue );
2248                 break;
2249             case SC_WID_UNO_CELLSTYL:
2250                 {
2251                     OUString aStrVal;
2252                     aValue >>= aStrVal;
2253                     OUString aString(ScStyleNameConversion::ProgrammaticToDisplayName(
2254                                                         aStrVal, SfxStyleFamily::Para ));
2255                     pDocShell->GetDocFunc().ApplyStyle( *GetMarkData(), aString, true );
2256                 }
2257                 break;
2258             case SC_WID_UNO_TBLBORD:
2259                 {
2260                     table::TableBorder aBorder;
2261                     if ( !aRanges.empty() && ( aValue >>= aBorder ) )   // empty = nothing to do
2262                     {
2263                         SvxBoxItem aOuter(ATTR_BORDER);
2264                         SvxBoxInfoItem aInner(ATTR_BORDER_INNER);
2265                         ScHelperFunctions::FillBoxItems( aOuter, aInner, aBorder );
2266 
2267                         ScHelperFunctions::ApplyBorder( pDocShell, aRanges, aOuter, aInner );   //! docfunc
2268                     }
2269                 }
2270                 break;
2271             case SC_WID_UNO_TBLBORD2:
2272                 {
2273                     table::TableBorder2 aBorder2;
2274                     if ( !aRanges.empty() && ( aValue >>= aBorder2 ) )   // empty = nothing to do
2275                     {
2276                         SvxBoxItem aOuter(ATTR_BORDER);
2277                         SvxBoxInfoItem aInner(ATTR_BORDER_INNER);
2278                         ScHelperFunctions::FillBoxItems( aOuter, aInner, aBorder2 );
2279 
2280                         ScHelperFunctions::ApplyBorder( pDocShell, aRanges, aOuter, aInner );   //! docfunc
2281                     }
2282                 }
2283                 break;
2284             case SC_WID_UNO_CONDFMT:
2285             case SC_WID_UNO_CONDLOC:
2286             case SC_WID_UNO_CONDXML:
2287                 {
2288                     uno::Reference<sheet::XSheetConditionalEntries> xInterface(aValue, uno::UNO_QUERY);
2289                     if ( !aRanges.empty() && xInterface.is() )  // empty = nothing to do
2290                     {
2291                         ScTableConditionalFormat* pFormat =
2292                                 comphelper::getUnoTunnelImplementation<ScTableConditionalFormat>( xInterface );
2293                         if (pFormat)
2294                         {
2295                             ScDocument& rDoc = pDocShell->GetDocument();
2296                             bool bEnglish = ( pEntry->nWID != SC_WID_UNO_CONDLOC );
2297                             bool bXML = ( pEntry->nWID == SC_WID_UNO_CONDXML );
2298                             formula::FormulaGrammar::Grammar eGrammar = (bXML ?
2299                                    formula::FormulaGrammar::GRAM_UNSPECIFIED :
2300                                    formula::FormulaGrammar::mapAPItoGrammar( bEnglish, bXML));
2301 
2302                             SCTAB nTab = aRanges.front().aStart.Tab();
2303                             // To remove conditional formats for all cells in aRanges we need to:
2304                             // Remove conditional format data from cells' attributes
2305                             rDoc.RemoveCondFormatData( aRanges, nTab,  0 );
2306                             // And also remove ranges from conditional formats list
2307                             for (size_t i = 0; i < aRanges.size(); ++i)
2308                             {
2309                                 rDoc.GetCondFormList( aRanges[i].aStart.Tab() )->DeleteArea(
2310                                     aRanges[i].aStart.Col(), aRanges[i].aStart.Row(),
2311                                     aRanges[i].aEnd.Col(), aRanges[i].aEnd.Row() );
2312                             }
2313 
2314                             // Then we can apply new conditional format if there is one
2315                             if (pFormat->getCount())
2316                             {
2317                                 auto pNew = std::make_unique<ScConditionalFormat>( 0, &rDoc );    // Index will be set on inserting
2318                                 pFormat->FillFormat( *pNew, rDoc, eGrammar );
2319                                 pNew->SetRange( aRanges );
2320                                 pDocShell->GetDocFunc().ReplaceConditionalFormat( 0, std::move(pNew), nTab, aRanges );
2321                             }
2322 
2323                             // and repaint
2324                             for (size_t i = 0; i < aRanges.size(); ++i)
2325                                 pDocShell->PostPaint(aRanges[i], PaintPartFlags::Grid);
2326                             pDocShell->SetDocumentModified();
2327                         }
2328                     }
2329                 }
2330                 break;
2331             case SC_WID_UNO_VALIDAT:
2332             case SC_WID_UNO_VALILOC:
2333             case SC_WID_UNO_VALIXML:
2334                 {
2335                     uno::Reference<beans::XPropertySet> xInterface(aValue, uno::UNO_QUERY);
2336                     if ( !aRanges.empty() && xInterface.is() )  // empty = nothing to do
2337                     {
2338                         ScTableValidationObj* pValidObj =
2339                                 comphelper::getUnoTunnelImplementation<ScTableValidationObj>( xInterface );
2340                         if (pValidObj)
2341                         {
2342                             ScDocument& rDoc = pDocShell->GetDocument();
2343                             bool bEnglish = ( pEntry->nWID != SC_WID_UNO_VALILOC );
2344                             bool bXML = ( pEntry->nWID == SC_WID_UNO_VALIXML );
2345                             formula::FormulaGrammar::Grammar eGrammar = (bXML ?
2346                                    formula::FormulaGrammar::GRAM_UNSPECIFIED :
2347                                    formula::FormulaGrammar::mapAPItoGrammar( bEnglish, bXML));
2348 
2349                             std::unique_ptr<ScValidationData> pNewData(
2350                                     pValidObj->CreateValidationData( rDoc, eGrammar ));
2351                             sal_uLong nIndex = rDoc.AddValidationEntry( *pNewData );
2352                             pNewData.reset();
2353 
2354                             ScPatternAttr aPattern( rDoc.GetPool() );
2355                             aPattern.GetItemSet().Put( SfxUInt32Item( ATTR_VALIDDATA, nIndex ) );
2356                             pDocShell->GetDocFunc().ApplyAttributes( *GetMarkData(), aPattern, true );
2357                         }
2358                     }
2359                 }
2360                 break;
2361             // SC_WID_UNO_NUMRULES is ignored...
2362         }
2363 }
2364 
2365 uno::Any SAL_CALL ScCellRangesBase::getPropertyValue( const OUString& aPropertyName )
2366 {
2367     SolarMutexGuard aGuard;
2368 
2369     if ( !pDocShell || aRanges.empty() )
2370         throw uno::RuntimeException();
2371 
2372     const SfxItemPropertyMap& rPropertyMap = GetItemPropertyMap();     // from derived class
2373     const SfxItemPropertySimpleEntry* pEntry = rPropertyMap.getByName( aPropertyName );
2374     if ( !pEntry )
2375         throw beans::UnknownPropertyException(aPropertyName);
2376 
2377     uno::Any aAny;
2378     GetOnePropertyValue( pEntry, aAny );
2379     return aAny;
2380 }
2381 
2382 void ScCellRangesBase::GetOnePropertyValue( const SfxItemPropertySimpleEntry* pEntry, uno::Any& rAny )
2383 {
2384     if ( !pEntry )
2385         return;
2386 
2387     if ( IsScItemWid( pEntry->nWID ) )
2388     {
2389         SfxItemSet* pDataSet = GetCurrentDataSet();
2390         if ( pDataSet )
2391         {
2392             switch ( pEntry->nWID )     // for special handling of items
2393             {
2394                 case ATTR_VALUE_FORMAT:
2395                     {
2396                         ScDocument& rDoc = pDocShell->GetDocument();
2397 
2398                         sal_uLong nOldFormat =
2399                                 pDataSet->Get( ATTR_VALUE_FORMAT ).GetValue();
2400                         LanguageType eOldLang =
2401                                 pDataSet->Get( ATTR_LANGUAGE_FORMAT ).GetLanguage();
2402                         nOldFormat = rDoc.GetFormatTable()->
2403                                 GetFormatForLanguageIfBuiltIn( nOldFormat, eOldLang );
2404                         rAny <<= static_cast<sal_Int32>(nOldFormat);
2405                     }
2406                     break;
2407                 case ATTR_INDENT:
2408                     rAny <<= static_cast<sal_Int16>( convertTwipToMm100(static_cast<const ScIndentItem&>(
2409                                     pDataSet->Get(pEntry->nWID)).GetValue()) );
2410                     break;
2411                 case ATTR_STACKED:
2412                     {
2413                         Degree100 nRot = pDataSet->Get(ATTR_ROTATE_VALUE).GetValue();
2414                         bool bStacked = static_cast<const ScVerticalStackCell&>(pDataSet->Get(pEntry->nWID)).GetValue();
2415                         SvxOrientationItem( nRot, bStacked, 0 ).QueryValue( rAny );
2416                     }
2417                     break;
2418                 default:
2419                     pPropSet->getPropertyValue(*pEntry, *pDataSet, rAny);
2420             }
2421         }
2422     }
2423     else        // implemented here
2424         switch ( pEntry->nWID )
2425         {
2426             case SC_WID_UNO_CHCOLHDR:
2427                 rAny <<= bChartColAsHdr;
2428                 break;
2429             case SC_WID_UNO_CHROWHDR:
2430                 rAny <<= bChartRowAsHdr;
2431                 break;
2432             case SC_WID_UNO_CELLSTYL:
2433                 {
2434                     OUString aStyleName;
2435                     const ScStyleSheet* pStyle = pDocShell->GetDocument().GetSelectionStyle(*GetMarkData());
2436                     if (pStyle)
2437                         aStyleName = pStyle->GetName();
2438                     rAny <<= ScStyleNameConversion::DisplayToProgrammaticName(
2439                                                             aStyleName, SfxStyleFamily::Para );
2440                 }
2441                 break;
2442             case SC_WID_UNO_TBLBORD:
2443             case SC_WID_UNO_TBLBORD2:
2444                 {
2445                     //! loop through all ranges
2446                     if ( !aRanges.empty() )
2447                     {
2448                         const ScRange & rFirst = aRanges[ 0 ];
2449                         SvxBoxItem aOuter(ATTR_BORDER);
2450                         SvxBoxInfoItem aInner(ATTR_BORDER_INNER);
2451 
2452                         ScDocument& rDoc = pDocShell->GetDocument();
2453                         ScMarkData aMark(rDoc.GetSheetLimits());
2454                         aMark.SetMarkArea( rFirst );
2455                         aMark.SelectTable( rFirst.aStart.Tab(), true );
2456                         rDoc.GetSelectionFrame( aMark, aOuter, aInner );
2457 
2458                         if (pEntry->nWID == SC_WID_UNO_TBLBORD2)
2459                             ScHelperFunctions::AssignTableBorder2ToAny( rAny, aOuter, aInner);
2460                         else
2461                             ScHelperFunctions::AssignTableBorderToAny( rAny, aOuter, aInner);
2462                     }
2463                 }
2464                 break;
2465             case SC_WID_UNO_CONDFMT:
2466             case SC_WID_UNO_CONDLOC:
2467             case SC_WID_UNO_CONDXML:
2468                 {
2469                     const ScPatternAttr* pPattern = GetCurrentAttrsDeep();
2470                     if ( pPattern )
2471                     {
2472                         ScDocument& rDoc = pDocShell->GetDocument();
2473                         bool bEnglish = ( pEntry->nWID != SC_WID_UNO_CONDLOC );
2474                         bool bXML = ( pEntry->nWID == SC_WID_UNO_CONDXML );
2475                         formula::FormulaGrammar::Grammar eGrammar = (bXML ?
2476                                 rDoc.GetStorageGrammar() :
2477                                formula::FormulaGrammar::mapAPItoGrammar( bEnglish, bXML));
2478                         const ScCondFormatIndexes& rIndex =
2479                                 pPattern->GetItem(ATTR_CONDITIONAL).GetCondFormatData();
2480                         sal_uLong nIndex = 0;
2481                         if(!rIndex.empty())
2482                             nIndex = rIndex[0];
2483                         rAny <<= uno::Reference<sheet::XSheetConditionalEntries>(
2484                                 new ScTableConditionalFormat( &rDoc, nIndex, aRanges.front().aStart.Tab(), eGrammar ));
2485                     }
2486                 }
2487                 break;
2488             case SC_WID_UNO_VALIDAT:
2489             case SC_WID_UNO_VALILOC:
2490             case SC_WID_UNO_VALIXML:
2491                 {
2492                     const ScPatternAttr* pPattern = GetCurrentAttrsDeep();
2493                     if ( pPattern )
2494                     {
2495                         ScDocument& rDoc = pDocShell->GetDocument();
2496                         bool bEnglish = ( pEntry->nWID != SC_WID_UNO_VALILOC );
2497                         bool bXML = ( pEntry->nWID == SC_WID_UNO_VALIXML );
2498                         formula::FormulaGrammar::Grammar eGrammar = (bXML ?
2499                                 rDoc.GetStorageGrammar() :
2500                                formula::FormulaGrammar::mapAPItoGrammar( bEnglish, bXML));
2501                         sal_uLong nIndex =
2502                                 pPattern->GetItem(ATTR_VALIDDATA).GetValue();
2503                         rAny <<= uno::Reference<beans::XPropertySet>(
2504                                 new ScTableValidationObj( rDoc, nIndex, eGrammar ));
2505                     }
2506                 }
2507                 break;
2508             case SC_WID_UNO_NUMRULES:
2509                 {
2510                     // always return empty numbering rules object
2511                     rAny <<= ScStyleObj::CreateEmptyNumberingRules();
2512                 }
2513                 break;
2514             case SC_WID_UNO_ABSNAME:
2515                 {
2516                     OUString sRet;
2517                     aRanges.Format(sRet, ScRefFlags::RANGE_ABS_3D, pDocShell->GetDocument());
2518                     rAny <<= sRet;
2519                 }
2520             break;
2521             case SC_WID_UNO_FORMATID:
2522                 {
2523                     const ScPatternAttr* pPattern = GetCurrentAttrsFlat();
2524                     rAny <<= pPattern->GetKey();
2525                 }
2526             break;
2527         }
2528 }
2529 
2530 void SAL_CALL ScCellRangesBase::addPropertyChangeListener( const OUString& /* aPropertyName */,
2531                             const uno::Reference<beans::XPropertyChangeListener>& /* aListener */)
2532 {
2533     SolarMutexGuard aGuard;
2534     if ( aRanges.empty() )
2535         throw uno::RuntimeException();
2536 
2537     OSL_FAIL("not implemented");
2538 }
2539 
2540 void SAL_CALL ScCellRangesBase::removePropertyChangeListener( const OUString& /* aPropertyName */,
2541                             const uno::Reference<beans::XPropertyChangeListener>& /* aListener */)
2542 {
2543     SolarMutexGuard aGuard;
2544     if ( aRanges.empty() )
2545         throw uno::RuntimeException();
2546 
2547     OSL_FAIL("not implemented");
2548 }
2549 
2550 void SAL_CALL ScCellRangesBase::addVetoableChangeListener( const OUString&,
2551                             const uno::Reference<beans::XVetoableChangeListener>&)
2552 {
2553     OSL_FAIL("not implemented");
2554 }
2555 
2556 void SAL_CALL ScCellRangesBase::removeVetoableChangeListener( const OUString&,
2557                             const uno::Reference<beans::XVetoableChangeListener>&)
2558 {
2559     OSL_FAIL("not implemented");
2560 }
2561 
2562 // XMultiPropertySet
2563 
2564 void SAL_CALL ScCellRangesBase::setPropertyValues( const uno::Sequence< OUString >& aPropertyNames,
2565                                     const uno::Sequence< uno::Any >& aValues )
2566 {
2567     SolarMutexGuard aGuard;
2568 
2569     sal_Int32 nCount(aPropertyNames.getLength());
2570     sal_Int32 nValues(aValues.getLength());
2571     if (nCount != nValues)
2572         throw lang::IllegalArgumentException();
2573 
2574     if ( !(pDocShell && nCount) )
2575         return;
2576 
2577     const SfxItemPropertyMap& rPropertyMap = GetItemPropertyMap();      // from derived class
2578     const OUString* pNames = aPropertyNames.getConstArray();
2579     const uno::Any* pValues = aValues.getConstArray();
2580 
2581     std::unique_ptr<const SfxItemPropertySimpleEntry*[]> pEntryArray(new const SfxItemPropertySimpleEntry*[nCount]);
2582 
2583     sal_Int32 i;
2584     for(i = 0; i < nCount; i++)
2585     {
2586         // first loop: find all properties in map, but handle only CellStyle
2587         // (CellStyle must be set before any other cell properties)
2588 
2589         const SfxItemPropertySimpleEntry* pEntry = rPropertyMap.getByName( pNames[i] );
2590         pEntryArray[i] = pEntry;
2591         if (pEntry)
2592         {
2593             if ( pEntry->nWID == SC_WID_UNO_CELLSTYL )
2594             {
2595                 try
2596                 {
2597                     SetOnePropertyValue( pEntry, pValues[i] );
2598                 }
2599                 catch ( lang::IllegalArgumentException& )
2600                 {
2601                     TOOLS_WARN_EXCEPTION( "sc", "exception when setting cell style");     // not supposed to happen
2602                 }
2603             }
2604         }
2605     }
2606 
2607     ScDocument& rDoc = pDocShell->GetDocument();
2608     std::unique_ptr<ScPatternAttr> pOldPattern;
2609     std::unique_ptr<ScPatternAttr> pNewPattern;
2610 
2611     for(i = 0; i < nCount; i++)
2612     {
2613         // second loop: handle other properties
2614 
2615         const SfxItemPropertySimpleEntry* pEntry = pEntryArray[i];
2616         if ( pEntry )
2617         {
2618             if ( IsScItemWid( pEntry->nWID ) )  // can be handled by SfxItemPropertySet
2619             {
2620                 if ( !pOldPattern )
2621                 {
2622                     pOldPattern.reset(new ScPatternAttr( *GetCurrentAttrsDeep() ));
2623                     pOldPattern->GetItemSet().ClearInvalidItems();
2624                     pNewPattern.reset(new ScPatternAttr( rDoc.GetPool() ));
2625                 }
2626 
2627                 //  collect items in pNewPattern, apply with one call after the loop
2628 
2629                 sal_uInt16 nFirstItem, nSecondItem;
2630                 lcl_SetCellProperty( *pEntry, pValues[i], *pOldPattern, rDoc, nFirstItem, nSecondItem );
2631 
2632                 //  put only affected items into new set
2633                 if ( nFirstItem )
2634                     pNewPattern->GetItemSet().Put( pOldPattern->GetItemSet().Get( nFirstItem ) );
2635                 if ( nSecondItem )
2636                     pNewPattern->GetItemSet().Put( pOldPattern->GetItemSet().Get( nSecondItem ) );
2637             }
2638             else if ( pEntry->nWID != SC_WID_UNO_CELLSTYL )   // CellStyle is handled above
2639             {
2640                 //  call virtual method to set a single property
2641                 SetOnePropertyValue( pEntry, pValues[i] );
2642             }
2643         }
2644     }
2645 
2646     if ( pNewPattern && !aRanges.empty() )
2647         pDocShell->GetDocFunc().ApplyAttributes( *GetMarkData(), *pNewPattern, true );
2648 }
2649 
2650 uno::Sequence<uno::Any> SAL_CALL ScCellRangesBase::getPropertyValues(
2651                                 const uno::Sequence< OUString >& aPropertyNames )
2652 {
2653     SolarMutexGuard aGuard;
2654 
2655     const SfxItemPropertyMap& rPropertyMap = GetItemPropertyMap();     // from derived class
2656 
2657     uno::Sequence<uno::Any> aRet(aPropertyNames.getLength());
2658     uno::Any* pProperties = aRet.getArray();
2659     for(sal_Int32 i = 0; i < aPropertyNames.getLength(); i++)
2660     {
2661         const SfxItemPropertySimpleEntry* pEntry = rPropertyMap.getByName( aPropertyNames[i] );
2662         GetOnePropertyValue( pEntry, pProperties[i] );
2663     }
2664     return aRet;
2665 }
2666 
2667 void SAL_CALL ScCellRangesBase::addPropertiesChangeListener( const uno::Sequence< OUString >& /* aPropertyNames */,
2668                                     const uno::Reference< beans::XPropertiesChangeListener >& /* xListener */ )
2669 {
2670     OSL_FAIL("not implemented");
2671 }
2672 
2673 void SAL_CALL ScCellRangesBase::removePropertiesChangeListener( const uno::Reference< beans::XPropertiesChangeListener >& /* xListener */ )
2674 {
2675     OSL_FAIL("not implemented");
2676 }
2677 
2678 void SAL_CALL ScCellRangesBase::firePropertiesChangeEvent( const uno::Sequence< OUString >& /* aPropertyNames */,
2679                                     const uno::Reference< beans::XPropertiesChangeListener >& /* xListener */ )
2680 {
2681     OSL_FAIL("not implemented");
2682 }
2683 
2684 IMPL_LINK( ScCellRangesBase, ValueListenerHdl, const SfxHint&, rHint, void )
2685 {
2686     if ( pDocShell && (rHint.GetId() == SfxHintId::ScDataChanged))
2687     {
2688         //  This may be called several times for a single change, if several formulas
2689         //  in the range are notified. So only a flag is set that is checked when
2690         //  SfxHintId::DataChanged is received.
2691 
2692         bGotDataChangedHint = true;
2693     }
2694 }
2695 
2696 // XTolerantMultiPropertySet
2697 uno::Sequence< beans::SetPropertyTolerantFailed > SAL_CALL ScCellRangesBase::setPropertyValuesTolerant( const uno::Sequence< OUString >& aPropertyNames,
2698                                     const uno::Sequence< uno::Any >& aValues )
2699 {
2700     SolarMutexGuard aGuard;
2701 
2702     sal_Int32 nCount(aPropertyNames.getLength());
2703     sal_Int32 nValues(aValues.getLength());
2704     if (nCount != nValues)
2705         throw lang::IllegalArgumentException();
2706 
2707     if ( pDocShell && nCount )
2708     {
2709         uno::Sequence < beans::SetPropertyTolerantFailed > aReturns(nCount);
2710         beans::SetPropertyTolerantFailed* pReturns = aReturns.getArray();
2711 
2712         const SfxItemPropertyMap& rPropertyMap = GetItemPropertyMap();     // from derived class
2713         const OUString* pNames = aPropertyNames.getConstArray();
2714         const uno::Any* pValues = aValues.getConstArray();
2715 
2716         std::unique_ptr<const SfxItemPropertySimpleEntry*[]> pMapArray(new const SfxItemPropertySimpleEntry*[nCount]);
2717 
2718         sal_Int32 i;
2719         for(i = 0; i < nCount; i++)
2720         {
2721             // first loop: find all properties in map, but handle only CellStyle
2722             // (CellStyle must be set before any other cell properties)
2723 
2724             const SfxItemPropertySimpleEntry* pEntry = rPropertyMap.getByName( pNames[i] );
2725             pMapArray[i] = pEntry;
2726             if (pEntry)
2727             {
2728                 if ( pEntry->nWID == SC_WID_UNO_CELLSTYL )
2729                 {
2730                     try
2731                     {
2732                         SetOnePropertyValue( pEntry, pValues[i] );
2733                     }
2734                     catch ( lang::IllegalArgumentException& )
2735                     {
2736                         TOOLS_WARN_EXCEPTION( "sc", "exception when setting cell style");     // not supposed to happen
2737                     }
2738                 }
2739             }
2740         }
2741 
2742         ScDocument& rDoc = pDocShell->GetDocument();
2743         std::unique_ptr<ScPatternAttr> pOldPattern;
2744         std::unique_ptr<ScPatternAttr> pNewPattern;
2745 
2746         sal_Int32 nFailed(0);
2747         for(i = 0; i < nCount; i++)
2748         {
2749             // second loop: handle other properties
2750 
2751             const SfxItemPropertySimpleEntry* pEntry = pMapArray[i];
2752             if ( pEntry && ((pEntry->nFlags & beans::PropertyAttribute::READONLY) == 0))
2753             {
2754                 if ( IsScItemWid( pEntry->nWID ) )  // can be handled by SfxItemPropertySet
2755                 {
2756                     if ( !pOldPattern )
2757                     {
2758                         pOldPattern.reset(new ScPatternAttr( *GetCurrentAttrsDeep() ));
2759                         pOldPattern->GetItemSet().ClearInvalidItems();
2760                         pNewPattern.reset(new ScPatternAttr( rDoc.GetPool() ));
2761                     }
2762 
2763                     //  collect items in pNewPattern, apply with one call after the loop
2764                     try
2765                     {
2766                         sal_uInt16 nFirstItem, nSecondItem;
2767                         lcl_SetCellProperty( *pEntry, pValues[i], *pOldPattern, rDoc, nFirstItem, nSecondItem );
2768 
2769                         //  put only affected items into new set
2770                         if ( nFirstItem )
2771                             pNewPattern->GetItemSet().Put( pOldPattern->GetItemSet().Get( nFirstItem ) );
2772                         if ( nSecondItem )
2773                             pNewPattern->GetItemSet().Put( pOldPattern->GetItemSet().Get( nSecondItem ) );
2774                     }
2775                     catch ( lang::IllegalArgumentException& )
2776                     {
2777                         pReturns[nFailed].Name = pNames[i];
2778                         pReturns[nFailed++].Result = beans::TolerantPropertySetResultType::ILLEGAL_ARGUMENT;
2779                     }
2780                 }
2781                 else if ( pEntry->nWID != SC_WID_UNO_CELLSTYL )   // CellStyle is handled above
2782                 {
2783                     //  call virtual method to set a single property
2784                     try
2785                     {
2786                         SetOnePropertyValue( pEntry, pValues[i] );
2787                     }
2788                     catch ( lang::IllegalArgumentException& )
2789                     {
2790                         pReturns[nFailed].Name = pNames[i];
2791                         pReturns[nFailed++].Result = beans::TolerantPropertySetResultType::ILLEGAL_ARGUMENT;
2792                     }
2793                 }
2794             }
2795             else
2796             {
2797                 pReturns[nFailed].Name = pNames[i];
2798                 if (pEntry)
2799                     pReturns[nFailed++].Result = beans::TolerantPropertySetResultType::PROPERTY_VETO;
2800                 else
2801                     pReturns[nFailed++].Result = beans::TolerantPropertySetResultType::UNKNOWN_PROPERTY;
2802             }
2803         }
2804 
2805         if ( pNewPattern && !aRanges.empty() )
2806             pDocShell->GetDocFunc().ApplyAttributes( *GetMarkData(), *pNewPattern, true );
2807 
2808         aReturns.realloc(nFailed);
2809 
2810         return aReturns;
2811     }
2812     return uno::Sequence < beans::SetPropertyTolerantFailed >();
2813 }
2814 
2815 uno::Sequence< beans::GetPropertyTolerantResult > SAL_CALL ScCellRangesBase::getPropertyValuesTolerant( const uno::Sequence< OUString >& aPropertyNames )
2816 {
2817     SolarMutexGuard aGuard;
2818 
2819     sal_Int32 nCount(aPropertyNames.getLength());
2820     uno::Sequence < beans::GetPropertyTolerantResult > aReturns(nCount);
2821     beans::GetPropertyTolerantResult* pReturns = aReturns.getArray();
2822 
2823     const SfxItemPropertyMap& rPropertyMap = GetItemPropertyMap();     // from derived class
2824 
2825     for(sal_Int32 i = 0; i < nCount; i++)
2826     {
2827         const SfxItemPropertySimpleEntry* pEntry = rPropertyMap.getByName( aPropertyNames[i] );
2828         if (!pEntry)
2829         {
2830             pReturns[i].Result = beans::TolerantPropertySetResultType::UNKNOWN_PROPERTY;
2831         }
2832         else
2833         {
2834             sal_uInt16 nItemWhich = 0;
2835             lcl_GetPropertyWhich( pEntry, nItemWhich );
2836             pReturns[i].State = GetOnePropertyState( nItemWhich, pEntry );
2837             GetOnePropertyValue( pEntry, pReturns[i].Value );
2838             pReturns[i].Result = beans::TolerantPropertySetResultType::SUCCESS;
2839         }
2840     }
2841     return aReturns;
2842 }
2843 
2844 uno::Sequence< beans::GetDirectPropertyTolerantResult > SAL_CALL ScCellRangesBase::getDirectPropertyValuesTolerant( const uno::Sequence< OUString >& aPropertyNames )
2845 {
2846     SolarMutexGuard aGuard;
2847 
2848     sal_Int32 nCount(aPropertyNames.getLength());
2849     uno::Sequence < beans::GetDirectPropertyTolerantResult > aReturns(nCount);
2850     beans::GetDirectPropertyTolerantResult* pReturns = aReturns.getArray();
2851 
2852     const SfxItemPropertyMap& rPropertyMap = GetItemPropertyMap();     // from derived class
2853 
2854     sal_Int32 j = 0;
2855     for(sal_Int32 i = 0; i < nCount; i++)
2856     {
2857         const SfxItemPropertySimpleEntry* pEntry = rPropertyMap.getByName( aPropertyNames[i] );
2858         if (!pEntry)
2859         {
2860             pReturns[i].Result = beans::TolerantPropertySetResultType::UNKNOWN_PROPERTY;
2861         }
2862         else
2863         {
2864             sal_uInt16 nItemWhich = 0;
2865             lcl_GetPropertyWhich( pEntry, nItemWhich );
2866             pReturns[j].State = GetOnePropertyState( nItemWhich, pEntry );
2867             if (pReturns[j].State == beans::PropertyState_DIRECT_VALUE)
2868             {
2869                 GetOnePropertyValue( pEntry, pReturns[j].Value );
2870                 pReturns[j].Result = beans::TolerantPropertySetResultType::SUCCESS;
2871                 pReturns[j].Name = aPropertyNames[i];
2872                 ++j;
2873             }
2874         }
2875     }
2876     if (j < nCount)
2877         aReturns.realloc(j);
2878     return aReturns;
2879 }
2880 
2881 // XIndent
2882 
2883 void SAL_CALL ScCellRangesBase::decrementIndent()
2884 {
2885     SolarMutexGuard aGuard;
2886     if ( pDocShell && !aRanges.empty() )
2887     {
2888         //#97041#; put only MultiMarked ScMarkData in ChangeIndent
2889         ScMarkData aMarkData(*GetMarkData());
2890         aMarkData.MarkToMulti();
2891         pDocShell->GetDocFunc().ChangeIndent( aMarkData, false, true );
2892     }
2893 }
2894 
2895 void SAL_CALL ScCellRangesBase::incrementIndent()
2896 {
2897     SolarMutexGuard aGuard;
2898     if ( pDocShell && !aRanges.empty() )
2899     {
2900         //#97041#; put only MultiMarked ScMarkData in ChangeIndent
2901         ScMarkData aMarkData(*GetMarkData());
2902         aMarkData.MarkToMulti();
2903         pDocShell->GetDocFunc().ChangeIndent( aMarkData, true, true );
2904     }
2905 }
2906 
2907 // XChartData
2908 
2909 std::unique_ptr<ScMemChart> ScCellRangesBase::CreateMemChart_Impl() const
2910 {
2911     if ( pDocShell && !aRanges.empty() )
2912     {
2913         ScRangeListRef xChartRanges;
2914         if ( aRanges.size() == 1 )
2915         {
2916             //  set useful table limit (only occupied data area)
2917             //  (only here - Listeners are registered for the whole area)
2918             //! check immediately if a ScTableSheetObj?
2919 
2920             const ScDocument & rDoc = pDocShell->GetDocument();
2921             const ScRange & rRange = aRanges[0];
2922             if ( rRange.aStart.Col() == 0 && rRange.aEnd.Col() == rDoc.MaxCol() &&
2923                  rRange.aStart.Row() == 0 && rRange.aEnd.Row() == rDoc.MaxRow() )
2924             {
2925                 SCTAB nTab = rRange.aStart.Tab();
2926 
2927                 SCCOL nStartX;
2928                 SCROW nStartY; // Get start
2929                 if (!pDocShell->GetDocument().GetDataStart( nTab, nStartX, nStartY ))
2930                 {
2931                     nStartX = 0;
2932                     nStartY = 0;
2933                 }
2934 
2935                 SCCOL nEndX;
2936                 SCROW nEndY; // Get end
2937                 if (!pDocShell->GetDocument().GetTableArea( nTab, nEndX, nEndY ))
2938                 {
2939                     nEndX = 0;
2940                     nEndY = 0;
2941                 }
2942 
2943                 xChartRanges = new ScRangeList( ScRange( nStartX, nStartY, nTab, nEndX, nEndY, nTab ) );
2944             }
2945         }
2946         if (!xChartRanges.is())         //  otherwise take Ranges directly
2947             xChartRanges = new ScRangeList(aRanges);
2948         ScChartArray aArr( pDocShell->GetDocument(), xChartRanges );
2949 
2950         // RowAsHdr = ColHeaders and vice versa
2951         aArr.SetHeaders( bChartRowAsHdr, bChartColAsHdr );
2952 
2953         return aArr.CreateMemChart();
2954     }
2955     return nullptr;
2956 }
2957 
2958 uno::Sequence< uno::Sequence<double> > SAL_CALL ScCellRangesBase::getData()
2959 {
2960     SolarMutexGuard aGuard;
2961     std::unique_ptr<ScMemChart> pMemChart(CreateMemChart_Impl());
2962     if ( pMemChart )
2963     {
2964         sal_Int32 nColCount = pMemChart->GetColCount();
2965         sal_Int32 nRowCount = static_cast<sal_Int32>(pMemChart->GetRowCount());
2966 
2967         uno::Sequence< uno::Sequence<double> > aRowSeq( nRowCount );
2968         uno::Sequence<double>* pRowAry = aRowSeq.getArray();
2969         for (sal_Int32 nRow = 0; nRow < nRowCount; nRow++)
2970         {
2971             uno::Sequence<double> aColSeq( nColCount );
2972             double* pColAry = aColSeq.getArray();
2973             for (sal_Int32 nCol = 0; nCol < nColCount; nCol++)
2974                 pColAry[nCol] = pMemChart->GetData( nCol, nRow );
2975 
2976             pRowAry[nRow] = aColSeq;
2977         }
2978 
2979         return aRowSeq;
2980     }
2981 
2982     return uno::Sequence< uno::Sequence<double> >(0);
2983 }
2984 
2985 ScRangeListRef ScCellRangesBase::GetLimitedChartRanges_Impl( sal_Int32 nDataColumns, sal_Int32 nDataRows ) const
2986 {
2987     if ( aRanges.size() == 1 )
2988     {
2989         const ScDocument & rDoc = pDocShell->GetDocument();
2990         const ScRange & rRange = aRanges[0];
2991         if ( rRange.aStart.Col() == 0 && rRange.aEnd.Col() == rDoc.MaxCol() &&
2992              rRange.aStart.Row() == 0 && rRange.aEnd.Row() == rDoc.MaxRow() )
2993         {
2994             //  if aRanges is a complete sheet, limit to given size
2995 
2996             SCTAB nTab = rRange.aStart.Tab();
2997 
2998             sal_Int32 nEndColumn = nDataColumns - 1 + ( bChartColAsHdr ? 1 : 0 );
2999             if ( nEndColumn < 0 )
3000                 nEndColumn = 0;
3001             if ( nEndColumn > rDoc.MaxCol() )
3002                 nEndColumn = rDoc.MaxCol();
3003 
3004             sal_Int32 nEndRow = nDataRows - 1 + ( bChartRowAsHdr ? 1 : 0 );
3005             if ( nEndRow < 0 )
3006                 nEndRow = 0;
3007             if ( nEndRow > rDoc.MaxRow() )
3008                 nEndRow = rDoc.MaxRow();
3009 
3010             ScRangeListRef xChartRanges = new ScRangeList( ScRange( 0, 0, nTab, static_cast<SCCOL>(nEndColumn), static_cast<SCROW>(nEndRow), nTab ) );
3011             return xChartRanges;
3012         }
3013     }
3014 
3015     return new ScRangeList(aRanges);        // as-is
3016 }
3017 
3018 void SAL_CALL ScCellRangesBase::setData( const uno::Sequence< uno::Sequence<double> >& aData )
3019 {
3020     SolarMutexGuard aGuard;
3021     bool bDone = false;
3022     sal_Int32 nRowCount = aData.getLength();
3023     sal_Int32 nColCount = nRowCount ? aData[0].getLength() : 0;
3024     ScRangeListRef xChartRanges = GetLimitedChartRanges_Impl( nColCount, nRowCount );
3025     if ( pDocShell && xChartRanges.is() )
3026     {
3027         ScDocument& rDoc = pDocShell->GetDocument();
3028         ScChartArray aArr( rDoc, xChartRanges );
3029         aArr.SetHeaders( bChartRowAsHdr, bChartColAsHdr );      // RowAsHdr = ColHeaders
3030         const ScChartPositionMap* pPosMap = aArr.GetPositionMap();
3031         if (pPosMap)
3032         {
3033             if ( pPosMap->GetColCount() == static_cast<SCCOL>(nColCount) &&
3034                  pPosMap->GetRowCount() == static_cast<SCROW>(nRowCount) )
3035             {
3036                 for (sal_Int32 nRow=0; nRow<nRowCount; nRow++)
3037                 {
3038                     const uno::Sequence<double>& rRowSeq = aData[nRow];
3039                     const double* pArray = rRowSeq.getConstArray();
3040                     nColCount = rRowSeq.getLength();
3041                     for (sal_Int32 nCol=0; nCol<nColCount; nCol++)
3042                     {
3043                         const ScAddress* pPos = pPosMap->GetPosition(
3044                                 sal::static_int_cast<SCCOL>(nCol),
3045                                 sal::static_int_cast<SCROW>(nRow) );
3046                         if (pPos)
3047                         {
3048                             double fVal = pArray[nCol];
3049                             if ( fVal == DBL_MIN )
3050                                 rDoc.SetEmptyCell(*pPos);
3051                             else
3052                                 rDoc.SetValue(*pPos, pArray[nCol]);
3053                         }
3054                     }
3055                 }
3056 
3057                 //! undo
3058                 PaintGridRanges_Impl();
3059                 pDocShell->SetDocumentModified();
3060                 ForceChartListener_Impl();          // call listeners for this object synchronously
3061                 bDone = true;
3062             }
3063         }
3064     }
3065 
3066     if (!bDone)
3067         throw uno::RuntimeException();
3068 }
3069 
3070 uno::Sequence<OUString> SAL_CALL ScCellRangesBase::getRowDescriptions()
3071 {
3072     SolarMutexGuard aGuard;
3073     std::unique_ptr<ScMemChart> pMemChart(CreateMemChart_Impl());
3074     if ( pMemChart )
3075     {
3076         sal_Int32 nRowCount = static_cast<sal_Int32>(pMemChart->GetRowCount());
3077         uno::Sequence<OUString> aSeq( nRowCount );
3078         OUString* pAry = aSeq.getArray();
3079         for (sal_Int32 nRow = 0; nRow < nRowCount; nRow++)
3080             pAry[nRow] = pMemChart->GetRowText(nRow);
3081 
3082         return aSeq;
3083     }
3084     return uno::Sequence<OUString>(0);
3085 }
3086 
3087 void SAL_CALL ScCellRangesBase::setRowDescriptions(
3088                         const uno::Sequence<OUString>& aRowDescriptions )
3089 {
3090     SolarMutexGuard aGuard;
3091     bool bDone = false;
3092     if ( bChartColAsHdr )
3093     {
3094         sal_Int32 nRowCount = aRowDescriptions.getLength();
3095         ScRangeListRef xChartRanges = GetLimitedChartRanges_Impl( 1, nRowCount );
3096         if ( pDocShell && xChartRanges.is() )
3097         {
3098             ScDocument& rDoc = pDocShell->GetDocument();
3099             ScChartArray aArr( rDoc, xChartRanges );
3100             aArr.SetHeaders( bChartRowAsHdr, bChartColAsHdr );      // RowAsHdr = ColHeaders
3101             const ScChartPositionMap* pPosMap = aArr.GetPositionMap();
3102             if (pPosMap)
3103             {
3104                 if ( pPosMap->GetRowCount() == static_cast<SCROW>(nRowCount) )
3105                 {
3106                     const OUString* pArray = aRowDescriptions.getConstArray();
3107                     for (sal_Int32 nRow=0; nRow<nRowCount; nRow++)
3108                     {
3109                         const ScAddress* pPos = pPosMap->GetRowHeaderPosition(
3110                                 static_cast<SCSIZE>(nRow) );
3111                         if (pPos)
3112                         {
3113                             const OUString& aStr = pArray[nRow];
3114                             if (aStr.isEmpty())
3115                                 rDoc.SetEmptyCell(*pPos);
3116                             else
3117                             {
3118                                 ScSetStringParam aParam;
3119                                 aParam.setTextInput();
3120                                 rDoc.SetString(*pPos, aStr, &aParam);
3121                             }
3122                         }
3123                     }
3124 
3125                     //! undo
3126                     PaintGridRanges_Impl();
3127                     pDocShell->SetDocumentModified();
3128                     ForceChartListener_Impl();          // call listeners for this object synchronously
3129                     bDone = true;
3130                 }
3131             }
3132         }
3133     }
3134 
3135     if (!bDone)
3136         throw uno::RuntimeException();
3137 }
3138 
3139 uno::Sequence<OUString> SAL_CALL ScCellRangesBase::getColumnDescriptions()
3140 {
3141     SolarMutexGuard aGuard;
3142     std::unique_ptr<ScMemChart> pMemChart(CreateMemChart_Impl());
3143     if ( pMemChart )
3144     {
3145         sal_Int32 nColCount = pMemChart->GetColCount();
3146         uno::Sequence<OUString> aSeq( nColCount );
3147         OUString* pAry = aSeq.getArray();
3148         for (sal_Int32 nCol = 0; nCol < nColCount; nCol++)
3149             pAry[nCol] = pMemChart->GetColText(nCol);
3150 
3151         return aSeq;
3152     }
3153     return uno::Sequence<OUString>(0);
3154 }
3155 
3156 void SAL_CALL ScCellRangesBase::setColumnDescriptions(
3157     const uno::Sequence<OUString>& aColumnDescriptions )
3158 {
3159     SolarMutexGuard aGuard;
3160     bool bDone = false;
3161     if ( bChartRowAsHdr )
3162     {
3163         sal_Int32 nColCount = aColumnDescriptions.getLength();
3164         ScRangeListRef xChartRanges = GetLimitedChartRanges_Impl( nColCount, 1 );
3165         if ( pDocShell && xChartRanges.is() )
3166         {
3167             ScDocument& rDoc = pDocShell->GetDocument();
3168             ScChartArray aArr( rDoc, xChartRanges );
3169             aArr.SetHeaders( bChartRowAsHdr, bChartColAsHdr );      // RowAsHdr = ColHeaders
3170             const ScChartPositionMap* pPosMap = aArr.GetPositionMap();
3171             if (pPosMap)
3172             {
3173                 if ( pPosMap->GetColCount() == static_cast<SCCOL>(nColCount) )
3174                 {
3175                     const OUString* pArray = aColumnDescriptions.getConstArray();
3176                     for (sal_Int32 nCol=0; nCol<nColCount; nCol++)
3177                     {
3178                         const ScAddress* pPos = pPosMap->GetColHeaderPosition(
3179                             sal::static_int_cast<SCCOL>(nCol) );
3180                         if (pPos)
3181                         {
3182                             const OUString& aStr = pArray[nCol];
3183                             if (aStr.isEmpty())
3184                                 rDoc.SetEmptyCell(*pPos);
3185                             else
3186                             {
3187                                 ScSetStringParam aParam;
3188                                 aParam.setTextInput();
3189                                 rDoc.SetString(*pPos, aStr, &aParam);
3190                             }
3191                         }
3192                     }
3193 
3194                     //! undo
3195                     PaintGridRanges_Impl();
3196                     pDocShell->SetDocumentModified();
3197                     ForceChartListener_Impl();          // call listeners for this object synchronously
3198                     bDone = true;
3199                 }
3200             }
3201         }
3202     }
3203 
3204     if (!bDone)
3205         throw uno::RuntimeException();
3206 }
3207 
3208 void ScCellRangesBase::ForceChartListener_Impl()
3209 {
3210     //  call Update immediately so the caller to setData etc. can
3211     //  recognize the listener call
3212 
3213     if (!pDocShell)
3214         return;
3215 
3216     ScChartListenerCollection* pColl = pDocShell->GetDocument().GetChartListenerCollection();
3217     if (!pColl)
3218         return;
3219 
3220     ScChartListenerCollection::ListenersType& rListeners = pColl->getListeners();
3221     for (auto const& it : rListeners)
3222     {
3223         ScChartListener *const p = it.second.get();
3224         assert(p);
3225         if (p->GetUnoSource() == static_cast<chart::XChartData*>(this) && p->IsDirty())
3226             p->Update();
3227     }
3228 }
3229 
3230 void SAL_CALL ScCellRangesBase::addChartDataChangeEventListener( const uno::Reference<
3231                                     chart::XChartDataChangeEventListener >& aListener )
3232 {
3233     SolarMutexGuard aGuard;
3234     if ( !pDocShell || aRanges.empty() )
3235         return;
3236 
3237     //! test for duplicates ?
3238 
3239     ScDocument& rDoc = pDocShell->GetDocument();
3240     ScRangeListRef aRangesRef( new ScRangeList(aRanges) );
3241     ScChartListenerCollection* pColl = rDoc.GetChartListenerCollection();
3242     OUString aName = pColl->getUniqueName(u"__Uno");
3243     if (aName.isEmpty())
3244         // failed to create unique name.
3245         return;
3246 
3247     ScChartListener* pListener = new ScChartListener( aName, rDoc, aRangesRef );
3248     pListener->SetUno( aListener, this );
3249     pColl->insert( pListener );
3250     pListener->StartListeningTo();
3251 }
3252 
3253 void SAL_CALL ScCellRangesBase::removeChartDataChangeEventListener( const uno::Reference<
3254                                     chart::XChartDataChangeEventListener >& aListener )
3255 {
3256     SolarMutexGuard aGuard;
3257     if ( pDocShell && !aRanges.empty() )
3258     {
3259         ScDocument& rDoc = pDocShell->GetDocument();
3260         ScChartListenerCollection* pColl = rDoc.GetChartListenerCollection();
3261         pColl->FreeUno( aListener, this );
3262     }
3263 }
3264 
3265 double SAL_CALL ScCellRangesBase::getNotANumber()
3266 {
3267     //  use DBL_MIN in ScChartArray, because Chart wants it so
3268     return DBL_MIN;
3269 }
3270 
3271 sal_Bool SAL_CALL ScCellRangesBase::isNotANumber( double nNumber )
3272 {
3273     //  use DBL_MIN in ScChartArray, because Chart wants it so
3274     return (nNumber == DBL_MIN);
3275 }
3276 
3277 // XModifyBroadcaster
3278 
3279 void SAL_CALL ScCellRangesBase::addModifyListener(const uno::Reference<util::XModifyListener>& aListener)
3280 {
3281     SolarMutexGuard aGuard;
3282     if ( aRanges.empty() )
3283         throw uno::RuntimeException();
3284 
3285     aValueListeners.emplace_back( aListener );
3286 
3287     if ( aValueListeners.size() == 1 )
3288     {
3289         if (!pValueListener)
3290             pValueListener.reset( new ScLinkListener( LINK( this, ScCellRangesBase, ValueListenerHdl ) ) );
3291 
3292         ScDocument& rDoc = pDocShell->GetDocument();
3293         for ( size_t i = 0, nCount = aRanges.size(); i < nCount; i++)
3294             rDoc.StartListeningArea( aRanges[ i ], false, pValueListener.get() );
3295 
3296         acquire();  // don't lose this object (one ref for all listeners)
3297     }
3298 }
3299 
3300 void SAL_CALL ScCellRangesBase::removeModifyListener( const uno::Reference<util::XModifyListener>& aListener )
3301 {
3302 
3303     SolarMutexGuard aGuard;
3304     if ( aRanges.empty() )
3305         throw uno::RuntimeException();
3306 
3307     rtl::Reference<ScCellRangesBase> xSelfHold(this); // in case the listeners have the last ref
3308 
3309     sal_uInt16 nCount = aValueListeners.size();
3310     for ( sal_uInt16 n=nCount; n--; )
3311     {
3312         uno::Reference<util::XModifyListener>& rObj = aValueListeners[n];
3313         if ( rObj == aListener )
3314         {
3315             aValueListeners.erase( aValueListeners.begin() + n );
3316 
3317             if ( aValueListeners.empty() )
3318             {
3319                 if (pValueListener)
3320                     pValueListener->EndListeningAll();
3321 
3322                 release();      // release the ref for the listeners
3323             }
3324 
3325             break;
3326         }
3327     }
3328 }
3329 
3330 // XCellRangesQuery
3331 
3332 uno::Reference<sheet::XSheetCellRanges> SAL_CALL ScCellRangesBase::queryVisibleCells()
3333 {
3334     SolarMutexGuard aGuard;
3335     if (pDocShell)
3336     {
3337         //! Separate for all tables, if markings separated per table
3338         SCTAB nTab = lcl_FirstTab(aRanges);
3339 
3340         ScMarkData aMarkData(*GetMarkData());
3341 
3342         ScDocument& rDoc = pDocShell->GetDocument();
3343         SCCOL nCol = 0, nLastCol;
3344         while (nCol <= rDoc.MaxCol())
3345         {
3346             if (rDoc.ColHidden(nCol, nTab, nullptr, &nLastCol))
3347                 // hidden columns.  Deselect them.
3348                 aMarkData.SetMultiMarkArea(ScRange(nCol, 0, nTab, nLastCol, rDoc.MaxRow(), nTab), false);
3349 
3350             nCol = nLastCol + 1;
3351         }
3352 
3353         SCROW nRow = 0, nLastRow;
3354         while (nRow <= rDoc.MaxRow())
3355         {
3356             if (rDoc.RowHidden(nRow, nTab, nullptr, &nLastRow))
3357                 // These rows are hidden.  Deselect them.
3358                 aMarkData.SetMultiMarkArea(ScRange(0, nRow, nTab, rDoc.MaxCol(), nLastRow, nTab), false);
3359 
3360             nRow = nLastRow + 1;
3361         }
3362 
3363         ScRangeList aNewRanges;
3364         aMarkData.FillRangeListWithMarks( &aNewRanges, false );
3365         return new ScCellRangesObj( pDocShell, aNewRanges );
3366     }
3367 
3368     return nullptr;
3369 }
3370 
3371 uno::Reference<sheet::XSheetCellRanges> SAL_CALL ScCellRangesBase::queryEmptyCells()
3372 {
3373     SolarMutexGuard aGuard;
3374     if (pDocShell)
3375     {
3376         ScDocument& rDoc = pDocShell->GetDocument();
3377 
3378         ScMarkData aMarkData(*GetMarkData());
3379 
3380         //  mark occupied cells
3381         for (size_t i = 0, nCount = aRanges.size(); i < nCount; ++i)
3382         {
3383             ScRange const & rRange = aRanges[ i ];
3384 
3385             ScCellIterator aIter(rDoc, rRange);
3386             for (bool bHasCell = aIter.first(); bHasCell; bHasCell = aIter.next())
3387             {
3388                 //  notes count as non-empty
3389                 if (!aIter.isEmpty())
3390                     aMarkData.SetMultiMarkArea(aIter.GetPos(), false);
3391             }
3392         }
3393 
3394         ScRangeList aNewRanges;
3395         //  IsMultiMarked is not enough (will not be reset during deselecting)
3396         //if (aMarkData.HasAnyMultiMarks()) // #i20044# should be set for all empty range
3397         aMarkData.FillRangeListWithMarks( &aNewRanges, false );
3398 
3399         return new ScCellRangesObj( pDocShell, aNewRanges );    // aNewRanges can be empty
3400     }
3401 
3402     return nullptr;
3403 }
3404 
3405 uno::Reference<sheet::XSheetCellRanges> SAL_CALL ScCellRangesBase::queryContentCells(
3406     sal_Int16 nContentFlags )
3407 {
3408     SolarMutexGuard aGuard;
3409     if (pDocShell)
3410     {
3411         ScDocument& rDoc = pDocShell->GetDocument();
3412 
3413         ScMarkData aMarkData(rDoc.GetSheetLimits());
3414 
3415         //  select matching cells
3416         for ( size_t i = 0, nCount = aRanges.size(); i < nCount; ++i )
3417         {
3418             ScRange const & rRange = aRanges[ i ];
3419 
3420             ScCellIterator aIter(rDoc, rRange);
3421             for (bool bHasCell = aIter.first(); bHasCell; bHasCell = aIter.next())
3422             {
3423                 bool bAdd = false;
3424                 switch (aIter.getType())
3425                 {
3426                     case CELLTYPE_STRING:
3427                         if ( nContentFlags & sheet::CellFlags::STRING )
3428                             bAdd = true;
3429                         break;
3430                     case CELLTYPE_EDIT:
3431                         if ( (nContentFlags & sheet::CellFlags::STRING) || (nContentFlags & sheet::CellFlags::FORMATTED) )
3432                             bAdd = true;
3433                         break;
3434                     case CELLTYPE_FORMULA:
3435                         if ( nContentFlags & sheet::CellFlags::FORMULA )
3436                             bAdd = true;
3437                         break;
3438                     case CELLTYPE_VALUE:
3439                         if ( (nContentFlags & (sheet::CellFlags::VALUE|sheet::CellFlags::DATETIME))
3440                                 == (sheet::CellFlags::VALUE|sheet::CellFlags::DATETIME) )
3441                             bAdd = true;
3442                         else
3443                         {
3444                             //  date/time identification
3445 
3446                             sal_uLong nIndex = static_cast<sal_uLong>(rDoc.GetAttr(
3447                                         aIter.GetPos(), ATTR_VALUE_FORMAT)->GetValue());
3448                             SvNumFormatType nTyp = rDoc.GetFormatTable()->GetType(nIndex);
3449                             if ((nTyp == SvNumFormatType::DATE) || (nTyp == SvNumFormatType::TIME) ||
3450                                     (nTyp == SvNumFormatType::DATETIME))
3451                             {
3452                                 if ( nContentFlags & sheet::CellFlags::DATETIME )
3453                                     bAdd = true;
3454                             }
3455                             else
3456                             {
3457                                 if ( nContentFlags & sheet::CellFlags::VALUE )
3458                                     bAdd = true;
3459                             }
3460                         }
3461                         break;
3462                     default:
3463                         {
3464                             // added to avoid warnings
3465                         }
3466                 }
3467 
3468                 if (bAdd)
3469                     aMarkData.SetMultiMarkArea(aIter.GetPos());
3470             }
3471         }
3472 
3473         if (nContentFlags & sheet::CellFlags::ANNOTATION)
3474         {
3475             std::vector<sc::NoteEntry> aNotes;
3476             rDoc.GetNotesInRange(aRanges, aNotes);
3477 
3478             for (const auto& i : aNotes)
3479             {
3480                 aMarkData.SetMultiMarkArea(i.maPos);
3481             }
3482         }
3483 
3484         ScRangeList aNewRanges;
3485         if (aMarkData.IsMultiMarked())
3486             aMarkData.FillRangeListWithMarks( &aNewRanges, false );
3487 
3488         return new ScCellRangesObj( pDocShell, aNewRanges );    // aNewRanges can be empty
3489     }
3490 
3491     return nullptr;
3492 }
3493 
3494 uno::Reference<sheet::XSheetCellRanges> SAL_CALL ScCellRangesBase::queryFormulaCells(
3495     sal_Int32 nResultFlags )
3496 {
3497     SolarMutexGuard aGuard;
3498     if (pDocShell)
3499     {
3500         ScDocument& rDoc = pDocShell->GetDocument();
3501 
3502         ScMarkData aMarkData(rDoc.GetSheetLimits());
3503 
3504         //  select matching cells
3505         for ( size_t i = 0, nCount = aRanges.size(); i < nCount; ++i )
3506         {
3507             ScRange const & rRange = aRanges[ i ];
3508 
3509             ScCellIterator aIter(rDoc, rRange);
3510             for (bool bHasCell = aIter.first(); bHasCell; bHasCell = aIter.next())
3511             {
3512                 if (aIter.getType() == CELLTYPE_FORMULA)
3513                 {
3514                     ScFormulaCell* pFCell = aIter.getFormulaCell();
3515                     bool bAdd = false;
3516                     if (pFCell->GetErrCode() != FormulaError::NONE)
3517                     {
3518                         if ( nResultFlags & sheet::FormulaResult::ERROR )
3519                             bAdd = true;
3520                     }
3521                     else if (pFCell->IsValue())
3522                     {
3523                         if ( nResultFlags & sheet::FormulaResult::VALUE )
3524                             bAdd = true;
3525                     }
3526                     else    // String
3527                     {
3528                         if ( nResultFlags & sheet::FormulaResult::STRING )
3529                             bAdd = true;
3530                     }
3531 
3532                     if (bAdd)
3533                         aMarkData.SetMultiMarkArea(aIter.GetPos());
3534                 }
3535             }
3536         }
3537 
3538         ScRangeList aNewRanges;
3539         if (aMarkData.IsMultiMarked())
3540             aMarkData.FillRangeListWithMarks( &aNewRanges, false );
3541 
3542         return new ScCellRangesObj( pDocShell, aNewRanges );    // aNewRanges can be empty
3543     }
3544 
3545     return nullptr;
3546 }
3547 
3548 uno::Reference<sheet::XSheetCellRanges> ScCellRangesBase::QueryDifferences_Impl(
3549                         const table::CellAddress& aCompare, bool bColumnDiff)
3550 {
3551     if (pDocShell)
3552     {
3553         size_t nRangeCount = aRanges.size();
3554         size_t i;
3555         ScDocument& rDoc = pDocShell->GetDocument();
3556         ScMarkData aMarkData(rDoc.GetSheetLimits());
3557 
3558         SCCOLROW nCmpPos = bColumnDiff ? static_cast<SCCOLROW>(aCompare.Row) : static_cast<SCCOLROW>(aCompare.Column);
3559 
3560         //  first select everything, where at all something is in the comparison column
3561         //  (in the second step the selection is cancelled for equal cells)
3562 
3563         SCTAB nTab = lcl_FirstTab(aRanges); //! for all tables, if markings per table
3564         ScRange aCmpRange, aCellRange;
3565         if (bColumnDiff)
3566             aCmpRange = ScRange( 0,nCmpPos,nTab, rDoc.MaxCol(),nCmpPos,nTab );
3567         else
3568             aCmpRange = ScRange( static_cast<SCCOL>(nCmpPos),0,nTab, static_cast<SCCOL>(nCmpPos),rDoc.MaxRow(),nTab );
3569         ScCellIterator aCmpIter(rDoc, aCmpRange);
3570         for (bool bHasCell = aCmpIter.first(); bHasCell; bHasCell = aCmpIter.next())
3571         {
3572             SCCOLROW nCellPos = bColumnDiff ? static_cast<SCCOLROW>(aCmpIter.GetPos().Col()) : static_cast<SCCOLROW>(aCmpIter.GetPos().Row());
3573             if (bColumnDiff)
3574                 aCellRange = ScRange( static_cast<SCCOL>(nCellPos),0,nTab,
3575                         static_cast<SCCOL>(nCellPos),rDoc.MaxRow(),nTab );
3576             else
3577                 aCellRange = ScRange( 0,nCellPos,nTab, rDoc.MaxCol(),nCellPos,nTab );
3578 
3579             for (i=0; i<nRangeCount; i++)
3580             {
3581                 ScRange aRange( aRanges[ i ] );
3582                 if ( aRange.Intersects( aCellRange ) )
3583                 {
3584                     if (bColumnDiff)
3585                     {
3586                         aRange.aStart.SetCol(static_cast<SCCOL>(nCellPos));
3587                         aRange.aEnd.SetCol(static_cast<SCCOL>(nCellPos));
3588                     }
3589                     else
3590                     {
3591                         aRange.aStart.SetRow(nCellPos);
3592                         aRange.aEnd.SetRow(nCellPos);
3593                     }
3594                     aMarkData.SetMultiMarkArea( aRange );
3595                 }
3596             }
3597         }
3598 
3599         //  compare all not empty cells with the comparison column and accordingly
3600         //  select or cancel
3601 
3602         ScAddress aCmpAddr;
3603         for (i=0; i<nRangeCount; i++)
3604         {
3605             ScRange const & rRange = aRanges[ i ];
3606 
3607             ScCellIterator aIter( rDoc, rRange );
3608             for (bool bHasCell = aIter.first(); bHasCell; bHasCell = aIter.next())
3609             {
3610                 if (bColumnDiff)
3611                     aCmpAddr = ScAddress( aIter.GetPos().Col(), nCmpPos, aIter.GetPos().Tab() );
3612                 else
3613                     aCmpAddr = ScAddress( static_cast<SCCOL>(nCmpPos), aIter.GetPos().Row(), aIter.GetPos().Tab() );
3614 
3615                 ScRange aOneRange(aIter.GetPos());
3616                 if (!aIter.equalsWithoutFormat(aCmpAddr))
3617                     aMarkData.SetMultiMarkArea( aOneRange );
3618                 else
3619                     aMarkData.SetMultiMarkArea( aOneRange, false );     // deselect
3620             }
3621         }
3622 
3623         ScRangeList aNewRanges;
3624         if (aMarkData.IsMultiMarked())
3625             aMarkData.FillRangeListWithMarks( &aNewRanges, false );
3626 
3627         return new ScCellRangesObj( pDocShell, aNewRanges );    // aNewRanges can be empty
3628     }
3629     return nullptr;
3630 }
3631 
3632 uno::Reference<sheet::XSheetCellRanges > SAL_CALL ScCellRangesBase::queryColumnDifferences(
3633     const table::CellAddress& aCompare )
3634 {
3635     SolarMutexGuard aGuard;
3636     return QueryDifferences_Impl( aCompare, true );
3637 }
3638 
3639 uno::Reference<sheet::XSheetCellRanges> SAL_CALL ScCellRangesBase::queryRowDifferences(
3640     const table::CellAddress& aCompare )
3641 {
3642     SolarMutexGuard aGuard;
3643     return QueryDifferences_Impl( aCompare, false );
3644 }
3645 
3646 uno::Reference<sheet::XSheetCellRanges> SAL_CALL ScCellRangesBase::queryIntersection(
3647                             const table::CellRangeAddress& aRange )
3648 {
3649     SolarMutexGuard aGuard;
3650     ScRange aMask( static_cast<SCCOL>(aRange.StartColumn), static_cast<SCROW>(aRange.StartRow), aRange.Sheet,
3651                    static_cast<SCCOL>(aRange.EndColumn),   static_cast<SCROW>(aRange.EndRow),   aRange.Sheet );
3652 
3653     ScRangeList aNew;
3654     for ( size_t i = 0, nCount = aRanges.size(); i < nCount; ++i )
3655     {
3656         ScRange aTemp( aRanges[ i ] );
3657         if ( aTemp.Intersects( aMask ) )
3658             aNew.Join( ScRange( std::max( aTemp.aStart.Col(), aMask.aStart.Col() ),
3659                                 std::max( aTemp.aStart.Row(), aMask.aStart.Row() ),
3660                                 std::max( aTemp.aStart.Tab(), aMask.aStart.Tab() ),
3661                                 std::min( aTemp.aEnd.Col(), aMask.aEnd.Col() ),
3662                                 std::min( aTemp.aEnd.Row(), aMask.aEnd.Row() ),
3663                                 std::min( aTemp.aEnd.Tab(), aMask.aEnd.Tab() ) ) );
3664     }
3665 
3666     return new ScCellRangesObj( pDocShell, aNew );  // can be empty
3667 }
3668 
3669 // XFormulaQuery
3670 
3671 uno::Reference<sheet::XSheetCellRanges> SAL_CALL ScCellRangesBase::queryPrecedents(
3672     sal_Bool bRecursive )
3673 {
3674     SolarMutexGuard aGuard;
3675     if ( pDocShell )
3676     {
3677         ScDocument& rDoc = pDocShell->GetDocument();
3678 
3679         ScRangeList aNewRanges(aRanges);
3680         bool bFound;
3681         do
3682         {
3683             bFound = false;
3684 
3685             //  aMarkData uses aNewRanges, not aRanges, so GetMarkData can't be used
3686             ScMarkData aMarkData(rDoc.GetSheetLimits());
3687             aMarkData.MarkFromRangeList( aNewRanges, false );
3688             aMarkData.MarkToMulti();        // needed for IsAllMarked
3689 
3690             for (size_t nR = 0, nCount = aNewRanges.size(); nR<nCount; ++nR)
3691             {
3692                 ScRange const & rRange = aNewRanges[ nR];
3693                 ScCellIterator aIter(rDoc, rRange);
3694                 for (bool bHasCell = aIter.first(); bHasCell; bHasCell = aIter.next())
3695                 {
3696                     if (aIter.getType() != CELLTYPE_FORMULA)
3697                         continue;
3698 
3699                     ScDetectiveRefIter aRefIter(rDoc, aIter.getFormulaCell());
3700                     ScRange aRefRange;
3701                     while ( aRefIter.GetNextRef( aRefRange) )
3702                     {
3703                         if ( bRecursive && !bFound && !aMarkData.IsAllMarked( aRefRange ) )
3704                             bFound = true;
3705                         aMarkData.SetMultiMarkArea(aRefRange);
3706                     }
3707                 }
3708             }
3709 
3710             aMarkData.FillRangeListWithMarks( &aNewRanges, true );
3711         }
3712         while ( bRecursive && bFound );
3713 
3714         return new ScCellRangesObj( pDocShell, aNewRanges );
3715     }
3716 
3717     return nullptr;
3718 }
3719 
3720 uno::Reference<sheet::XSheetCellRanges> SAL_CALL ScCellRangesBase::queryDependents(
3721     sal_Bool bRecursive )
3722 {
3723     SolarMutexGuard aGuard;
3724     if ( pDocShell )
3725     {
3726         ScDocument& rDoc = pDocShell->GetDocument();
3727 
3728         ScRangeList aNewRanges(aRanges);
3729         bool bFound;
3730         do
3731         {
3732             bFound = false;
3733 
3734             //  aMarkData uses aNewRanges, not aRanges, so GetMarkData can't be used
3735             ScMarkData aMarkData(rDoc.GetSheetLimits());
3736             aMarkData.MarkFromRangeList( aNewRanges, false );
3737             aMarkData.MarkToMulti();        // needed for IsAllMarked
3738 
3739             SCTAB nTab = lcl_FirstTab(aNewRanges);              //! all tables
3740 
3741             ScCellIterator aCellIter( rDoc, ScRange(0, 0, nTab, rDoc.MaxCol(), rDoc.MaxRow(), nTab) );
3742             for (bool bHasCell = aCellIter.first(); bHasCell; bHasCell = aCellIter.next())
3743             {
3744                 if (aCellIter.getType() != CELLTYPE_FORMULA)
3745                     continue;
3746 
3747                 bool bMark = false;
3748                 ScDetectiveRefIter aIter(rDoc, aCellIter.getFormulaCell());
3749                 ScRange aRefRange;
3750                 while ( aIter.GetNextRef( aRefRange) && !bMark )
3751                 {
3752                     size_t nRangesCount = aNewRanges.size();
3753                     for (size_t nR = 0; nR < nRangesCount; ++nR)
3754                     {
3755                         ScRange const & rRange = aNewRanges[ nR ];
3756                         if (rRange.Intersects(aRefRange))
3757                         {
3758                             bMark = true;                   // depending on part of Range
3759                             break;
3760                         }
3761                     }
3762                 }
3763                 if (bMark)
3764                 {
3765                     ScRange aCellRange(aCellIter.GetPos());
3766                     if ( bRecursive && !bFound && !aMarkData.IsAllMarked( aCellRange ) )
3767                         bFound = true;
3768                     aMarkData.SetMultiMarkArea(aCellRange);
3769                 }
3770             }
3771 
3772             aMarkData.FillRangeListWithMarks( &aNewRanges, true );
3773         }
3774         while ( bRecursive && bFound );
3775 
3776         return new ScCellRangesObj( pDocShell, aNewRanges );
3777     }
3778 
3779     return nullptr;
3780 }
3781 
3782 // XSearchable
3783 
3784 uno::Reference<util::XSearchDescriptor> SAL_CALL ScCellRangesBase::createSearchDescriptor()
3785 {
3786     SolarMutexGuard aGuard;
3787     return new ScCellSearchObj;
3788 }
3789 
3790 uno::Reference<container::XIndexAccess> SAL_CALL ScCellRangesBase::findAll(
3791                         const uno::Reference<util::XSearchDescriptor>& xDesc )
3792 {
3793     SolarMutexGuard aGuard;
3794     //  should we return Null if nothing is found(?)
3795     uno::Reference<container::XIndexAccess> xRet;
3796     if ( pDocShell && xDesc.is() )
3797     {
3798         ScCellSearchObj* pSearch = comphelper::getUnoTunnelImplementation<ScCellSearchObj>( xDesc );
3799         if (pSearch)
3800         {
3801             SvxSearchItem* pSearchItem = pSearch->GetSearchItem();
3802             if (pSearchItem)
3803             {
3804                 ScDocument& rDoc = pDocShell->GetDocument();
3805                 pSearchItem->SetCommand( SvxSearchCmd::FIND_ALL );
3806                 //  always only within this object
3807                 pSearchItem->SetSelection( !lcl_WholeSheet(rDoc, aRanges) );
3808 
3809                 ScMarkData aMark(*GetMarkData());
3810 
3811                 OUString aDummyUndo;
3812                 ScRangeList aMatchedRanges;
3813                 SCCOL nCol = 0;
3814                 SCROW nRow = 0;
3815                 SCTAB nTab = 0;
3816                 bool bFound = rDoc.SearchAndReplace(
3817                     *pSearchItem, nCol, nRow, nTab, aMark, aMatchedRanges, aDummyUndo);
3818                 if (bFound)
3819                 {
3820                     //  on findAll always CellRanges no matter how much has been found
3821                     xRet.set(new ScCellRangesObj( pDocShell, aMatchedRanges ));
3822                 }
3823             }
3824         }
3825     }
3826     return xRet;
3827 }
3828 
3829 uno::Reference<uno::XInterface> ScCellRangesBase::Find_Impl(
3830                                     const uno::Reference<util::XSearchDescriptor>& xDesc,
3831                                     const ScAddress* pLastPos )
3832 {
3833     uno::Reference<uno::XInterface> xRet;
3834     if ( pDocShell && xDesc.is() )
3835     {
3836         ScCellSearchObj* pSearch = comphelper::getUnoTunnelImplementation<ScCellSearchObj>( xDesc );
3837         if (pSearch)
3838         {
3839             SvxSearchItem* pSearchItem = pSearch->GetSearchItem();
3840             if (pSearchItem)
3841             {
3842                 ScDocument& rDoc = pDocShell->GetDocument();
3843                 pSearchItem->SetCommand( SvxSearchCmd::FIND );
3844                 //  only always in this object
3845                 pSearchItem->SetSelection( !lcl_WholeSheet(rDoc, aRanges) );
3846 
3847                 ScMarkData aMark(*GetMarkData());
3848 
3849                 SCCOL nCol;
3850                 SCROW nRow;
3851                 SCTAB nTab;
3852                 if (pLastPos)
3853                     pLastPos->GetVars( nCol, nRow, nTab );
3854                 else
3855                 {
3856                     nTab = lcl_FirstTab(aRanges);   //! multiple sheets?
3857                     rDoc.GetSearchAndReplaceStart( *pSearchItem, nCol, nRow );
3858                 }
3859 
3860                 OUString aDummyUndo;
3861                 ScRangeList aMatchedRanges;
3862                 bool bFound = rDoc.SearchAndReplace(
3863                     *pSearchItem, nCol, nRow, nTab, aMark, aMatchedRanges, aDummyUndo);
3864                 if (bFound)
3865                 {
3866                     ScAddress aFoundPos( nCol, nRow, nTab );
3867                     xRet.set(static_cast<cppu::OWeakObject*>(new ScCellObj( pDocShell, aFoundPos )));
3868                 }
3869             }
3870         }
3871     }
3872     return xRet;
3873 }
3874 
3875 uno::Reference<uno::XInterface> SAL_CALL ScCellRangesBase::findFirst(
3876                         const uno::Reference<util::XSearchDescriptor>& xDesc )
3877 {
3878     SolarMutexGuard aGuard;
3879     return Find_Impl( xDesc, nullptr );
3880 }
3881 
3882 uno::Reference<uno::XInterface> SAL_CALL ScCellRangesBase::findNext(
3883                         const uno::Reference<uno::XInterface>& xStartAt,
3884                         const uno::Reference<util::XSearchDescriptor >& xDesc )
3885 {
3886     SolarMutexGuard aGuard;
3887     if ( xStartAt.is() )
3888     {
3889         ScCellRangesBase* pRangesImp = comphelper::getUnoTunnelImplementation<ScCellRangesBase>( xStartAt );
3890         if ( pRangesImp && pRangesImp->GetDocShell() == pDocShell )
3891         {
3892             const ScRangeList& rStartRanges = pRangesImp->GetRangeList();
3893             if ( rStartRanges.size() == 1 )
3894             {
3895                 ScAddress aStartPos = rStartRanges[ 0 ].aStart;
3896                 return Find_Impl( xDesc, &aStartPos );
3897             }
3898         }
3899     }
3900     return nullptr;
3901 }
3902 
3903 // XReplaceable
3904 
3905 uno::Reference<util::XReplaceDescriptor> SAL_CALL ScCellRangesBase::createReplaceDescriptor()
3906 {
3907     SolarMutexGuard aGuard;
3908     return new ScCellSearchObj;
3909 }
3910 
3911 sal_Int32 SAL_CALL ScCellRangesBase::replaceAll( const uno::Reference<util::XSearchDescriptor>& xDesc )
3912 {
3913     SolarMutexGuard aGuard;
3914     sal_Int32 nReplaced = 0;
3915     if ( pDocShell && xDesc.is() )
3916     {
3917         ScCellSearchObj* pSearch = comphelper::getUnoTunnelImplementation<ScCellSearchObj>( xDesc );
3918         if (pSearch)
3919         {
3920             SvxSearchItem* pSearchItem = pSearch->GetSearchItem();
3921             if (pSearchItem)
3922             {
3923                 ScDocument& rDoc = pDocShell->GetDocument();
3924                 bool bUndo(rDoc.IsUndoEnabled());
3925                 pSearchItem->SetCommand( SvxSearchCmd::REPLACE_ALL );
3926                 //  only always in this object
3927                 pSearchItem->SetSelection( !lcl_WholeSheet(rDoc, aRanges) );
3928 
3929                 ScMarkData aMark(*GetMarkData());
3930 
3931                 SCTAB nTabCount = rDoc.GetTableCount();
3932                 bool bProtected = !pDocShell->IsEditable();
3933                 for (const auto& rTab : aMark)
3934                 {
3935                     if (rTab >= nTabCount)
3936                         break;
3937                     if ( rDoc.IsTabProtected(rTab) )
3938                         bProtected = true;
3939                 }
3940                 if (bProtected)
3941                 {
3942                     //! Exception, or what?
3943                 }
3944                 else
3945                 {
3946                     SCTAB nTab = aMark.GetFirstSelected();      // do not use if SearchAndReplace
3947                     SCCOL nCol = 0;
3948                     SCROW nRow = 0;
3949 
3950                     OUString aUndoStr;
3951                     ScDocumentUniquePtr pUndoDoc;
3952                     if (bUndo)
3953                     {
3954                         pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
3955                         pUndoDoc->InitUndo( rDoc, nTab, nTab );
3956                     }
3957                     for (const auto& rTab : aMark)
3958                     {
3959                         if (rTab >= nTabCount)
3960                             break;
3961                         if (rTab != nTab && bUndo)
3962                             pUndoDoc->AddUndoTab( rTab, rTab );
3963                     }
3964                     std::unique_ptr<ScMarkData> pUndoMark;
3965                     if (bUndo)
3966                         pUndoMark.reset(new ScMarkData(aMark));
3967 
3968                     bool bFound = false;
3969                     if (bUndo)
3970                     {
3971                         ScRangeList aMatchedRanges;
3972                         bFound = rDoc.SearchAndReplace(
3973                             *pSearchItem, nCol, nRow, nTab, aMark, aMatchedRanges, aUndoStr, pUndoDoc.get() );
3974                     }
3975                     if (bFound)
3976                     {
3977                         nReplaced = pUndoDoc->GetCellCount();
3978 
3979                         pDocShell->GetUndoManager()->AddUndoAction(
3980                             std::make_unique<ScUndoReplace>( pDocShell, *pUndoMark, nCol, nRow, nTab,
3981                                                         aUndoStr, std::move(pUndoDoc), pSearchItem ) );
3982 
3983                         pDocShell->PostPaintGridAll();
3984                         pDocShell->SetDocumentModified();
3985                     }
3986                 }
3987             }
3988         }
3989     }
3990     return nReplaced;
3991 }
3992 
3993 // XUnoTunnel
3994 
3995 UNO3_GETIMPLEMENTATION_IMPL(ScCellRangesBase);
3996 
3997 typedef std::vector<ScNamedEntry> ScNamedEntryArr_Impl;
3998 
3999 struct ScCellRangesObj::Impl
4000 {
4001     ScNamedEntryArr_Impl m_aNamedEntries;
4002 };
4003 
4004 ScCellRangesObj::ScCellRangesObj(ScDocShell* pDocSh, const ScRangeList& rR)
4005     : ScCellRangesBase(pDocSh, rR)
4006     , m_pImpl(new Impl)
4007 {
4008 }
4009 
4010 ScCellRangesObj::~ScCellRangesObj()
4011 {
4012 }
4013 
4014 void ScCellRangesObj::RefChanged()
4015 {
4016     ScCellRangesBase::RefChanged();
4017 }
4018 
4019 uno::Any SAL_CALL ScCellRangesObj::queryInterface( const uno::Type& rType )
4020 {
4021     SC_QUERYINTERFACE( sheet::XSheetCellRangeContainer )
4022     SC_QUERYINTERFACE( sheet::XSheetCellRanges )
4023     SC_QUERYINTERFACE( container::XIndexAccess )
4024     SC_QUERY_MULTIPLE( container::XElementAccess, container::XIndexAccess )
4025     SC_QUERYINTERFACE( container::XEnumerationAccess )
4026     SC_QUERYINTERFACE( container::XNameContainer )
4027     SC_QUERYINTERFACE( container::XNameReplace )
4028     SC_QUERYINTERFACE( container::XNameAccess )
4029 
4030     return ScCellRangesBase::queryInterface( rType );
4031 }
4032 
4033 void SAL_CALL ScCellRangesObj::acquire() throw()
4034 {
4035     ScCellRangesBase::acquire();
4036 }
4037 
4038 void SAL_CALL ScCellRangesObj::release() throw()
4039 {
4040     ScCellRangesBase::release();
4041 }
4042 
4043 uno::Sequence<uno::Type> SAL_CALL ScCellRangesObj::getTypes()
4044 {
4045     static const uno::Sequence<uno::Type> aTypes = comphelper::concatSequences(
4046         ScCellRangesBase::getTypes(),
4047         uno::Sequence<uno::Type>
4048         {
4049             cppu::UnoType<sheet::XSheetCellRangeContainer>::get(),
4050             cppu::UnoType<container::XNameContainer>::get(),
4051             cppu::UnoType<container::XEnumerationAccess>::get()
4052         } );
4053     return aTypes;
4054 }
4055 
4056 uno::Sequence<sal_Int8> SAL_CALL ScCellRangesObj::getImplementationId()
4057 {
4058     return css::uno::Sequence<sal_Int8>();
4059 }
4060 
4061 // XCellRanges
4062 
4063 ScCellRangeObj* ScCellRangesObj::GetObjectByIndex_Impl(sal_Int32 nIndex) const
4064 {
4065     ScDocShell* pDocSh = GetDocShell();
4066     const ScRangeList& rRanges = GetRangeList();
4067     if ( pDocSh && nIndex >= 0 && nIndex < sal::static_int_cast<sal_Int32>(rRanges.size()) )
4068     {
4069         ScRange const & rRange = rRanges[ nIndex ];
4070         if ( rRange.aStart == rRange.aEnd )
4071             return new ScCellObj( pDocSh, rRange.aStart );
4072         else
4073             return new ScCellRangeObj( pDocSh, rRange );
4074     }
4075 
4076     return nullptr;        // no DocShell or wrong index
4077 }
4078 
4079 uno::Sequence<table::CellRangeAddress> SAL_CALL ScCellRangesObj::getRangeAddresses()
4080 {
4081     SolarMutexGuard aGuard;
4082     ScDocShell* pDocSh = GetDocShell();
4083     const ScRangeList& rRanges = GetRangeList();
4084     size_t nCount = rRanges.size();
4085     if ( pDocSh && nCount )
4086     {
4087         table::CellRangeAddress aRangeAddress;
4088         uno::Sequence<table::CellRangeAddress> aSeq(nCount);
4089         table::CellRangeAddress* pAry = aSeq.getArray();
4090         for ( size_t i=0; i < nCount; i++)
4091         {
4092             ScUnoConversion::FillApiRange( aRangeAddress, rRanges[ i ] );
4093             pAry[i] = aRangeAddress;
4094         }
4095         return aSeq;
4096     }
4097 
4098     return uno::Sequence<table::CellRangeAddress>(0);   // can be empty
4099 }
4100 
4101 uno::Reference<container::XEnumerationAccess> SAL_CALL ScCellRangesObj::getCells()
4102 {
4103     SolarMutexGuard aGuard;
4104 
4105     //  getCells with empty range list is possible (no exception),
4106     //  the resulting enumeration just has no elements
4107     //  (same behaviour as a valid range with no cells)
4108     //  This is handled in ScCellsEnumeration ctor.
4109 
4110     const ScRangeList& rRanges = GetRangeList();
4111     ScDocShell* pDocSh = GetDocShell();
4112     if (pDocSh)
4113         return new ScCellsObj( pDocSh, rRanges );
4114     return nullptr;
4115 }
4116 
4117 OUString SAL_CALL ScCellRangesObj::getRangeAddressesAsString()
4118 {
4119     SolarMutexGuard aGuard;
4120     OUString aString;
4121     ScDocShell* pDocSh = GetDocShell();
4122     const ScRangeList& rRanges = GetRangeList();
4123     if (pDocSh)
4124         rRanges.Format( aString, ScRefFlags::VALID | ScRefFlags::TAB_3D, pDocSh->GetDocument() );
4125     return aString;
4126 }
4127 
4128 // XSheetCellRangeContainer
4129 
4130 void SAL_CALL ScCellRangesObj::addRangeAddress( const table::CellRangeAddress& rRange,
4131                                     sal_Bool bMergeRanges )
4132 {
4133     SolarMutexGuard aGuard;
4134     ScRange aRange(static_cast<SCCOL>(rRange.StartColumn),
4135             static_cast<SCROW>(rRange.StartRow),
4136             static_cast<SCTAB>(rRange.Sheet),
4137             static_cast<SCCOL>(rRange.EndColumn),
4138             static_cast<SCROW>(rRange.EndRow),
4139             static_cast<SCTAB>(rRange.Sheet));
4140     AddRange(aRange, bMergeRanges);
4141 }
4142 
4143 static void lcl_RemoveNamedEntry( ScNamedEntryArr_Impl& rNamedEntries, const ScRange& rRange )
4144 {
4145     sal_uInt16 nCount = rNamedEntries.size();
4146     for ( sal_uInt16 n=nCount; n--; )
4147         if ( rNamedEntries[n].GetRange() == rRange )
4148             rNamedEntries.erase( rNamedEntries.begin() + n );
4149 }
4150 
4151 void SAL_CALL ScCellRangesObj::removeRangeAddress( const table::CellRangeAddress& rRange )
4152 {
4153     SolarMutexGuard aGuard;
4154     const ScRangeList& rRanges = GetRangeList();
4155 
4156     ScRangeList aSheetRanges;
4157     ScRangeList aNotSheetRanges;
4158     for (size_t i = 0; i < rRanges.size(); ++i)
4159     {
4160         if (rRanges[ i].aStart.Tab() == rRange.Sheet)
4161         {
4162             aSheetRanges.push_back( rRanges[ i ] );
4163         }
4164         else
4165         {
4166             aNotSheetRanges.push_back( rRanges[ i ] );
4167         }
4168     }
4169     ScMarkData aMarkData(GetDocument()->GetSheetLimits());
4170     aMarkData.MarkFromRangeList( aSheetRanges, false );
4171     ScRange aRange(static_cast<SCCOL>(rRange.StartColumn),
4172                 static_cast<SCROW>(rRange.StartRow),
4173                 static_cast<SCTAB>(rRange.Sheet),
4174                 static_cast<SCCOL>(rRange.EndColumn),
4175                 static_cast<SCROW>(rRange.EndRow),
4176                 static_cast<SCTAB>(rRange.Sheet));
4177     if (aMarkData.GetTableSelect( aRange.aStart.Tab() ))
4178     {
4179         aMarkData.MarkToMulti();
4180         if (!aMarkData.IsAllMarked( aRange ) )
4181             throw container::NoSuchElementException();
4182 
4183         aMarkData.SetMultiMarkArea( aRange, false );
4184         lcl_RemoveNamedEntry(m_pImpl->m_aNamedEntries, aRange);
4185 
4186     }
4187     SetNewRanges(aNotSheetRanges);
4188     ScRangeList aNew;
4189     aMarkData.FillRangeListWithMarks( &aNew, false );
4190     for ( size_t j = 0; j < aNew.size(); ++j)
4191     {
4192         AddRange(aNew[ j ], false);
4193     }
4194 }
4195 
4196 void SAL_CALL ScCellRangesObj::addRangeAddresses( const uno::Sequence<table::CellRangeAddress >& rRanges,
4197                                     sal_Bool bMergeRanges )
4198 {
4199     SolarMutexGuard aGuard;
4200     for (const table::CellRangeAddress& rRange : rRanges)
4201     {
4202         ScRange aRange(static_cast<SCCOL>(rRange.StartColumn),
4203                 static_cast<SCROW>(rRange.StartRow),
4204                 static_cast<SCTAB>(rRange.Sheet),
4205                 static_cast<SCCOL>(rRange.EndColumn),
4206                 static_cast<SCROW>(rRange.EndRow),
4207                 static_cast<SCTAB>(rRange.Sheet));
4208         AddRange(aRange, bMergeRanges);
4209     }
4210 }
4211 
4212 void SAL_CALL ScCellRangesObj::removeRangeAddresses( const uno::Sequence<table::CellRangeAddress >& rRangeSeq )
4213 {
4214     // use sometimes a better/faster implementation
4215     for (const table::CellRangeAddress& rRange : rRangeSeq)
4216     {
4217         removeRangeAddress(rRange);
4218     }
4219 }
4220 
4221 // XNameContainer
4222 
4223 static void lcl_RemoveNamedEntry( ScNamedEntryArr_Impl& rNamedEntries, std::u16string_view rName )
4224 {
4225     sal_uInt16 nCount = rNamedEntries.size();
4226     for ( sal_uInt16 n=nCount; n--; )
4227         if ( rNamedEntries[n].GetName() == rName )
4228             rNamedEntries.erase( rNamedEntries.begin() + n );
4229 }
4230 
4231 void SAL_CALL ScCellRangesObj::insertByName( const OUString& aName, const uno::Any& aElement )
4232 {
4233     SolarMutexGuard aGuard;
4234     ScDocShell* pDocSh = GetDocShell();
4235     bool bDone = false;
4236 
4237     //! Type of aElement can be some specific interface instead of XInterface
4238 
4239     uno::Reference<uno::XInterface> xInterface(aElement, uno::UNO_QUERY);
4240     if ( pDocSh && xInterface.is() )
4241     {
4242         ScCellRangesBase* pRangesImp = comphelper::getUnoTunnelImplementation<ScCellRangesBase>( xInterface );
4243         if ( pRangesImp && pRangesImp->GetDocShell() == pDocSh )
4244         {
4245             //  if explicit name is given and already existing, throw exception
4246 
4247             if ( !aName.isEmpty() )
4248             {
4249                 size_t nNamedCount = m_pImpl->m_aNamedEntries.size();
4250                 for (size_t n = 0; n < nNamedCount; n++)
4251                 {
4252                     if (m_pImpl->m_aNamedEntries[n].GetName() == aName)
4253                         throw container::ElementExistException();
4254                 }
4255             }
4256 
4257             ScRangeList aNew(GetRangeList());
4258             const ScRangeList& rAddRanges = pRangesImp->GetRangeList();
4259             size_t nAddCount = rAddRanges.size();
4260             for ( size_t i = 0; i < nAddCount; i++ )
4261                 aNew.Join( rAddRanges[ i ] );
4262             SetNewRanges(aNew);
4263             bDone = true;
4264 
4265             if ( !aName.isEmpty() && nAddCount == 1 )
4266             {
4267                 //  if a name is given, also insert into list of named entries
4268                 //  (only possible for a single range)
4269                 //  name is not in m_pImpl->m_aNamedEntries (tested above)
4270                 m_pImpl->m_aNamedEntries.emplace_back( aName, rAddRanges[ 0 ] );
4271             }
4272         }
4273     }
4274 
4275     if (!bDone)
4276     {
4277         //  invalid element - double names are handled above
4278         throw lang::IllegalArgumentException();
4279     }
4280 }
4281 
4282 static bool lcl_FindRangeByName( const ScRangeList& rRanges, ScDocShell* pDocSh,
4283                             std::u16string_view rName, size_t& rIndex )
4284 {
4285     if (pDocSh)
4286     {
4287         OUString aRangeStr;
4288         ScDocument& rDoc = pDocSh->GetDocument();
4289         for ( size_t i = 0, nCount = rRanges.size(); i < nCount; i++ )
4290         {
4291             aRangeStr = rRanges[ i ].Format(rDoc, ScRefFlags::VALID | ScRefFlags::TAB_3D);
4292             if ( aRangeStr == rName )
4293             {
4294                 rIndex = i;
4295                 return true;
4296             }
4297         }
4298     }
4299     return false;
4300 }
4301 
4302 static bool lcl_FindRangeOrEntry( const ScNamedEntryArr_Impl& rNamedEntries,
4303                             const ScRangeList& rRanges, ScDocShell* pDocSh,
4304                             const OUString& rName, ScRange& rFound )
4305 {
4306     //  exact range in list?
4307 
4308     size_t nIndex = 0;
4309     if ( lcl_FindRangeByName( rRanges, pDocSh, rName, nIndex ) )
4310     {
4311         rFound = rRanges[ nIndex ];
4312         return true;
4313     }
4314 
4315     //  range contained in selection? (sheet must be specified)
4316 
4317     ScRange aCellRange;
4318     ScRefFlags nParse = aCellRange.ParseAny( rName, pDocSh->GetDocument() );
4319     if ( (nParse & ( ScRefFlags::VALID | ScRefFlags::TAB_3D ))
4320                == ( ScRefFlags::VALID | ScRefFlags::TAB_3D ))
4321     {
4322         ScMarkData aMarkData(pDocSh->GetDocument().GetSheetLimits());
4323         aMarkData.MarkFromRangeList( rRanges, false );
4324         aMarkData.MarkToMulti();        // needed for IsAllMarked
4325         if ( aMarkData.IsAllMarked( aCellRange ) )
4326         {
4327             rFound = aCellRange;
4328             return true;
4329         }
4330     }
4331 
4332     //  named entry in this object?
4333 
4334     for (const auto & rNamedEntry : rNamedEntries)
4335         if ( rNamedEntry.GetName() == rName )
4336         {
4337             //  test if named entry is contained in rRanges
4338 
4339             const ScRange& rComp = rNamedEntry.GetRange();
4340             ScMarkData aMarkData(pDocSh->GetDocument().GetSheetLimits());
4341             aMarkData.MarkFromRangeList( rRanges, false );
4342             aMarkData.MarkToMulti();        // needed for IsAllMarked
4343             if ( aMarkData.IsAllMarked( rComp ) )
4344             {
4345                 rFound = rComp;
4346                 return true;
4347             }
4348         }
4349 
4350     return false;       // not found
4351 }
4352 
4353 void SAL_CALL ScCellRangesObj::removeByName( const OUString& aName )
4354 {
4355     SolarMutexGuard aGuard;
4356     bool bDone = false;
4357     ScDocShell* pDocSh = GetDocShell();
4358     const ScRangeList& rRanges = GetRangeList();
4359     size_t nIndex = 0;
4360     if ( lcl_FindRangeByName( rRanges, pDocSh, aName, nIndex ) )
4361     {
4362         // skip a single range
4363         ScRangeList aNew;
4364         for ( size_t i = 0, nCount = rRanges.size(); i < nCount; i++ )
4365             if (i != nIndex)
4366                 aNew.push_back( rRanges[ i ] );
4367         SetNewRanges(aNew);
4368         bDone = true;
4369     }
4370     else if (pDocSh)
4371     {
4372         //  deselect any ranges (parsed or named entry)
4373         ScRangeList aDiff;
4374         bool bValid = ( aDiff.Parse( aName, pDocSh->GetDocument() ) & ScRefFlags::VALID )
4375                                                                        == ScRefFlags::VALID;
4376         if (!bValid)
4377         {
4378             sal_uInt16 nCount = m_pImpl->m_aNamedEntries.size();
4379             for (sal_uInt16 n=0; n<nCount && !bValid; n++)
4380                 if (m_pImpl->m_aNamedEntries[n].GetName() == aName)
4381                 {
4382                     aDiff.RemoveAll();
4383                     aDiff.push_back(m_pImpl->m_aNamedEntries[n].GetRange());
4384                     bValid = true;
4385                 }
4386         }
4387         if ( bValid )
4388         {
4389             ScMarkData aMarkData(GetDocument()->GetSheetLimits());
4390             aMarkData.MarkFromRangeList( rRanges, false );
4391 
4392             for ( size_t i = 0, nDiffCount = aDiff.size(); i < nDiffCount; i++ )
4393             {
4394                 ScRange const & rDiffRange = aDiff[ i ];
4395                 if (aMarkData.GetTableSelect( rDiffRange.aStart.Tab() ))
4396                     aMarkData.SetMultiMarkArea( rDiffRange, false );
4397             }
4398 
4399             ScRangeList aNew;
4400             aMarkData.FillRangeListWithMarks( &aNew, false );
4401             SetNewRanges(aNew);
4402 
4403             bDone = true;       //! error if range was not selected before?
4404         }
4405     }
4406 
4407     if (!m_pImpl->m_aNamedEntries.empty())
4408         lcl_RemoveNamedEntry(m_pImpl->m_aNamedEntries, aName);
4409 
4410     if (!bDone)
4411         throw container::NoSuchElementException();      // not found
4412 }
4413 
4414 // XNameReplace
4415 
4416 void SAL_CALL ScCellRangesObj::replaceByName( const OUString& aName, const uno::Any& aElement )
4417 {
4418     SolarMutexGuard aGuard;
4419     //! combine?
4420     removeByName( aName );
4421     insertByName( aName, aElement );
4422 }
4423 
4424 // XNameAccess
4425 
4426 uno::Any SAL_CALL ScCellRangesObj::getByName( const OUString& aName )
4427 {
4428     SolarMutexGuard aGuard;
4429     uno::Any aRet;
4430 
4431     ScDocShell* pDocSh = GetDocShell();
4432     const ScRangeList& rRanges = GetRangeList();
4433     ScRange aRange;
4434     if (!lcl_FindRangeOrEntry(m_pImpl->m_aNamedEntries, rRanges,
4435                 pDocSh, aName, aRange))
4436         throw container::NoSuchElementException();
4437 
4438     uno::Reference<table::XCellRange> xRange;
4439     if ( aRange.aStart == aRange.aEnd )
4440         xRange.set(new ScCellObj( pDocSh, aRange.aStart ));
4441     else
4442         xRange.set(new ScCellRangeObj( pDocSh, aRange ));
4443     aRet <<= xRange;
4444 
4445     return aRet;
4446 }
4447 
4448 static bool lcl_FindEntryName( const ScNamedEntryArr_Impl& rNamedEntries,
4449                         const ScRange& rRange, OUString& rName )
4450 {
4451     sal_uInt16 nCount = rNamedEntries.size();
4452     for (sal_uInt16 i=0; i<nCount; i++)
4453         if (rNamedEntries[i].GetRange() == rRange)
4454         {
4455             rName = rNamedEntries[i].GetName();
4456             return true;
4457         }
4458     return false;
4459 }
4460 
4461 uno::Sequence<OUString> SAL_CALL ScCellRangesObj::getElementNames()
4462 {
4463     SolarMutexGuard aGuard;
4464 
4465     ScDocShell* pDocSh = GetDocShell();
4466     const ScRangeList& rRanges = GetRangeList();
4467     if (pDocSh)
4468     {
4469         OUString aRangeStr;
4470         ScDocument& rDoc = pDocSh->GetDocument();
4471         size_t nCount = rRanges.size();
4472 
4473         uno::Sequence<OUString> aSeq(nCount);
4474         OUString* pAry = aSeq.getArray();
4475         for (size_t i=0; i < nCount; i++)
4476         {
4477             //  use given name if for exactly this range, otherwise just format
4478             ScRange const & rRange = rRanges[ i ];
4479             if (m_pImpl->m_aNamedEntries.empty() ||
4480                 !lcl_FindEntryName(m_pImpl->m_aNamedEntries, rRange, aRangeStr))
4481             {
4482                 aRangeStr = rRange.Format(rDoc, ScRefFlags::VALID | ScRefFlags::TAB_3D);
4483             }
4484             pAry[i] = aRangeStr;
4485         }
4486         return aSeq;
4487     }
4488     return uno::Sequence<OUString>(0);
4489 }
4490 
4491 sal_Bool SAL_CALL ScCellRangesObj::hasByName( const OUString& aName )
4492 {
4493     SolarMutexGuard aGuard;
4494     ScDocShell* pDocSh = GetDocShell();
4495     const ScRangeList& rRanges = GetRangeList();
4496     ScRange aRange;
4497     return lcl_FindRangeOrEntry(m_pImpl->m_aNamedEntries, rRanges, pDocSh,
4498                 aName, aRange);
4499 }
4500 
4501 // XEnumerationAccess
4502 
4503 uno::Reference<container::XEnumeration> SAL_CALL ScCellRangesObj::createEnumeration()
4504 {
4505     SolarMutexGuard aGuard;
4506     return new ScIndexEnumeration(this, "com.sun.star.sheet.SheetCellRangesEnumeration");
4507 }
4508 
4509 // XIndexAccess
4510 
4511 sal_Int32 SAL_CALL ScCellRangesObj::getCount()
4512 {
4513     SolarMutexGuard aGuard;
4514     const ScRangeList& rRanges = GetRangeList();
4515     return rRanges.size();
4516 }
4517 
4518 uno::Any SAL_CALL ScCellRangesObj::getByIndex( sal_Int32 nIndex )
4519 {
4520     SolarMutexGuard aGuard;
4521     uno::Reference<table::XCellRange> xRange(GetObjectByIndex_Impl(nIndex));
4522     if (!xRange.is())
4523         throw lang::IndexOutOfBoundsException();
4524 
4525     return uno::makeAny(xRange);
4526 
4527 }
4528 
4529 uno::Type SAL_CALL ScCellRangesObj::getElementType()
4530 {
4531     SolarMutexGuard aGuard;
4532     return cppu::UnoType<table::XCellRange>::get();
4533 }
4534 
4535 sal_Bool SAL_CALL ScCellRangesObj::hasElements()
4536 {
4537     SolarMutexGuard aGuard;
4538     const ScRangeList& rRanges = GetRangeList();
4539     return !rRanges.empty();
4540 }
4541 
4542 // XServiceInfo
4543 OUString SAL_CALL ScCellRangesObj::getImplementationName()
4544 {
4545     return "ScCellRangesObj";
4546 }
4547 
4548 sal_Bool SAL_CALL ScCellRangesObj::supportsService( const OUString& rServiceName )
4549 {
4550     return cppu::supportsService(this, rServiceName);
4551 }
4552 
4553 uno::Sequence<OUString> SAL_CALL ScCellRangesObj::getSupportedServiceNames()
4554 {
4555     return {SCSHEETCELLRANGES_SERVICE,
4556             SCCELLPROPERTIES_SERVICE,
4557             SCCHARPROPERTIES_SERVICE,
4558             SCPARAPROPERTIES_SERVICE};
4559 }
4560 
4561 uno::Reference<table::XCellRange> ScCellRangeObj::CreateRangeFromDoc( const ScDocument& rDoc, const ScRange& rR )
4562 {
4563     SfxObjectShell* pObjSh = rDoc.GetDocumentShell();
4564     if ( auto pDocShell = dynamic_cast<ScDocShell*>( pObjSh) )
4565         return new ScCellRangeObj( pDocShell, rR );
4566     return nullptr;
4567 }
4568 
4569 ScCellRangeObj::ScCellRangeObj(ScDocShell* pDocSh, const ScRange& rR) :
4570     ScCellRangesBase( pDocSh, rR ),
4571     pRangePropSet( lcl_GetRangePropertySet() ),
4572     aRange( rR )
4573 {
4574     aRange.PutInOrder();       // beginning / end correct
4575 }
4576 
4577 ScCellRangeObj::~ScCellRangeObj()
4578 {
4579 }
4580 
4581 void ScCellRangeObj::RefChanged()
4582 {
4583     ScCellRangesBase::RefChanged();
4584 
4585     const ScRangeList& rRanges = GetRangeList();
4586     OSL_ENSURE(rRanges.size() == 1, "What ranges ?!?!");
4587     if ( !rRanges.empty() )
4588     {
4589         const ScRange & rFirst = rRanges[0];
4590         aRange = rFirst;
4591         aRange.PutInOrder();
4592     }
4593 }
4594 
4595 uno::Any SAL_CALL ScCellRangeObj::queryInterface( const uno::Type& rType )
4596 {
4597     SC_QUERYINTERFACE( sheet::XCellRangeAddressable )
4598     SC_QUERYINTERFACE( table::XCellRange )
4599     SC_QUERYINTERFACE( sheet::XSheetCellRange )
4600     SC_QUERYINTERFACE( sheet::XArrayFormulaRange )
4601     SC_QUERYINTERFACE( sheet::XArrayFormulaTokens )
4602     SC_QUERYINTERFACE( sheet::XCellRangeData )
4603     SC_QUERYINTERFACE( sheet::XCellRangeFormula )
4604     SC_QUERYINTERFACE( sheet::XMultipleOperation )
4605     SC_QUERYINTERFACE( util::XMergeable )
4606     SC_QUERYINTERFACE( sheet::XCellSeries )
4607     SC_QUERYINTERFACE( table::XAutoFormattable )
4608     SC_QUERYINTERFACE( util::XSortable )
4609     SC_QUERYINTERFACE( sheet::XSheetFilterableEx )
4610     SC_QUERYINTERFACE( sheet::XSheetFilterable )
4611     SC_QUERYINTERFACE( sheet::XSubTotalCalculatable )
4612     SC_QUERYINTERFACE( table::XColumnRowRange )
4613     SC_QUERYINTERFACE( util::XImportable )
4614     SC_QUERYINTERFACE( sheet::XCellFormatRangesSupplier )
4615     SC_QUERYINTERFACE( sheet::XUniqueCellFormatRangesSupplier )
4616 
4617     return ScCellRangesBase::queryInterface( rType );
4618 }
4619 
4620 void SAL_CALL ScCellRangeObj::acquire() throw()
4621 {
4622     ScCellRangesBase::acquire();
4623 }
4624 
4625 void SAL_CALL ScCellRangeObj::release() throw()
4626 {
4627     ScCellRangesBase::release();
4628 }
4629 
4630 uno::Sequence<uno::Type> SAL_CALL ScCellRangeObj::getTypes()
4631 {
4632     static const uno::Sequence<uno::Type> aTypes = comphelper::concatSequences(
4633         ScCellRangesBase::getTypes(),
4634         uno::Sequence<uno::Type>
4635         {
4636             cppu::UnoType<sheet::XCellRangeAddressable>::get(),
4637             cppu::UnoType<sheet::XSheetCellRange>::get(),
4638             cppu::UnoType<sheet::XArrayFormulaRange>::get(),
4639             cppu::UnoType<sheet::XArrayFormulaTokens>::get(),
4640             cppu::UnoType<sheet::XCellRangeData>::get(),
4641             cppu::UnoType<sheet::XCellRangeFormula>::get(),
4642             cppu::UnoType<sheet::XMultipleOperation>::get(),
4643             cppu::UnoType<util::XMergeable>::get(),
4644             cppu::UnoType<sheet::XCellSeries>::get(),
4645             cppu::UnoType<table::XAutoFormattable>::get(),
4646             cppu::UnoType<util::XSortable>::get(),
4647             cppu::UnoType<sheet::XSheetFilterableEx>::get(),
4648             cppu::UnoType<sheet::XSubTotalCalculatable>::get(),
4649             cppu::UnoType<table::XColumnRowRange>::get(),
4650             cppu::UnoType<util::XImportable>::get(),
4651             cppu::UnoType<sheet::XCellFormatRangesSupplier>::get(),
4652             cppu::UnoType<sheet::XUniqueCellFormatRangesSupplier>::get()
4653         } );
4654     return aTypes;
4655 }
4656 
4657 uno::Sequence<sal_Int8> SAL_CALL ScCellRangeObj::getImplementationId()
4658 {
4659     return css::uno::Sequence<sal_Int8>();
4660 }
4661 
4662 // XCellRange
4663 
4664 //  ColumnCount / RowCount vanished
4665 //! are used in Writer for tables ???
4666 
4667 uno::Reference<table::XCell> ScCellRangeObj::GetCellByPosition_Impl(
4668                                         sal_Int32 nColumn, sal_Int32 nRow )
4669 {
4670     ScDocShell* pDocSh = GetDocShell();
4671     if (!pDocSh)
4672         throw uno::RuntimeException();
4673 
4674     if ( nColumn >= 0 && nRow >= 0 )
4675     {
4676         sal_Int32 nPosX = aRange.aStart.Col() + nColumn;
4677         sal_Int32 nPosY = aRange.aStart.Row() + nRow;
4678 
4679         if ( nPosX <= aRange.aEnd.Col() && nPosY <= aRange.aEnd.Row() )
4680         {
4681             ScAddress aNew( static_cast<SCCOL>(nPosX), static_cast<SCROW>(nPosY), aRange.aStart.Tab() );
4682             return new ScCellObj( pDocSh, aNew );
4683         }
4684     }
4685 
4686     throw lang::IndexOutOfBoundsException();
4687 }
4688 
4689 uno::Reference<table::XCell> SAL_CALL ScCellRangeObj::getCellByPosition(
4690                                         sal_Int32 nColumn, sal_Int32 nRow )
4691 {
4692     SolarMutexGuard aGuard;
4693 
4694     return GetCellByPosition_Impl(nColumn, nRow);
4695 }
4696 
4697 uno::Reference<table::XCellRange> SAL_CALL ScCellRangeObj::getCellRangeByPosition(
4698                 sal_Int32 nLeft, sal_Int32 nTop, sal_Int32 nRight, sal_Int32 nBottom )
4699 {
4700     SolarMutexGuard aGuard;
4701 
4702     ScDocShell* pDocSh = GetDocShell();
4703     if (!pDocSh)
4704         throw uno::RuntimeException();
4705 
4706     if ( nLeft >= 0 && nTop >= 0 && nRight >= 0 && nBottom >= 0 )
4707     {
4708         sal_Int32 nStartX = aRange.aStart.Col() + nLeft;
4709         sal_Int32 nStartY = aRange.aStart.Row() + nTop;
4710         sal_Int32 nEndX = aRange.aStart.Col() + nRight;
4711         sal_Int32 nEndY = aRange.aStart.Row() + nBottom;
4712 
4713         if ( nStartX <= nEndX && nEndX <= aRange.aEnd.Col() &&
4714              nStartY <= nEndY && nEndY <= aRange.aEnd.Row() )
4715         {
4716             ScRange aNew( static_cast<SCCOL>(nStartX), static_cast<SCROW>(nStartY), aRange.aStart.Tab(),
4717                           static_cast<SCCOL>(nEndX), static_cast<SCROW>(nEndY), aRange.aEnd.Tab() );
4718             return new ScCellRangeObj( pDocSh, aNew );
4719         }
4720     }
4721 
4722     throw lang::IndexOutOfBoundsException();
4723 }
4724 
4725 uno::Reference<table::XCellRange> SAL_CALL ScCellRangeObj::getCellRangeByName(
4726                         const OUString& aName )
4727 {
4728     return getCellRangeByName( aName, ScAddress::detailsOOOa1 );
4729 }
4730 
4731 uno::Reference<table::XCellRange>  ScCellRangeObj::getCellRangeByName(
4732                         const OUString& aName, const ScAddress::Details& rDetails  )
4733 {
4734     //  name refers to the whole document (with the range's table as default),
4735     //  valid only if the range is within this range
4736 
4737     SolarMutexGuard aGuard;
4738     ScDocShell* pDocSh = GetDocShell();
4739     if ( pDocSh )
4740     {
4741         ScDocument& rDoc = pDocSh->GetDocument();
4742         SCTAB nTab = aRange.aStart.Tab();
4743 
4744         ScRange aCellRange;
4745         bool bFound = false;
4746         ScRefFlags nParse = aCellRange.ParseAny( aName, rDoc, rDetails );
4747         if ( nParse & ScRefFlags::VALID )
4748         {
4749             if ( !(nParse & ScRefFlags::TAB_3D) )   // no sheet specified -> this sheet
4750             {
4751                 aCellRange.aStart.SetTab(nTab);
4752                 aCellRange.aEnd.SetTab(nTab);
4753             }
4754             bFound = true;
4755         }
4756         else
4757         {
4758             if ( ScRangeUtil::MakeRangeFromName( aName, rDoc, nTab, aCellRange ) ||
4759                  ScRangeUtil::MakeRangeFromName( aName, rDoc, nTab, aCellRange, RUTL_DBASE ) )
4760                 bFound = true;
4761         }
4762 
4763         if (bFound)         // valid only if within this object's range
4764         {
4765             if (!aRange.In(aCellRange))
4766                 bFound = false;
4767         }
4768 
4769         if (bFound)
4770         {
4771             if ( aCellRange.aStart == aCellRange.aEnd )
4772                 return new ScCellObj( pDocSh, aCellRange.aStart );
4773             else
4774                 return new ScCellRangeObj( pDocSh, aCellRange );
4775         }
4776     }
4777 
4778     throw uno::RuntimeException();
4779 }
4780 
4781 // XColumnRowRange
4782 
4783 uno::Reference<table::XTableColumns> SAL_CALL ScCellRangeObj::getColumns()
4784 {
4785     SolarMutexGuard aGuard;
4786     ScDocShell* pDocSh = GetDocShell();
4787     if (pDocSh)
4788         return new ScTableColumnsObj( pDocSh, aRange.aStart.Tab(),
4789                                         aRange.aStart.Col(), aRange.aEnd.Col() );
4790 
4791     OSL_FAIL("Document invalid");
4792     return nullptr;
4793 }
4794 
4795 uno::Reference<table::XTableRows> SAL_CALL ScCellRangeObj::getRows()
4796 {
4797     SolarMutexGuard aGuard;
4798     ScDocShell* pDocSh = GetDocShell();
4799     if (pDocSh)
4800         return new ScTableRowsObj( pDocSh, aRange.aStart.Tab(),
4801                                     aRange.aStart.Row(), aRange.aEnd.Row() );
4802 
4803     OSL_FAIL("Document invalid");
4804     return nullptr;
4805 }
4806 
4807 // XAddressableCellRange
4808 
4809 table::CellRangeAddress SAL_CALL ScCellRangeObj::getRangeAddress()
4810 {
4811     SolarMutexGuard aGuard;
4812     table::CellRangeAddress aRet;
4813     ScUnoConversion::FillApiRange( aRet, aRange );
4814     return aRet;
4815 }
4816 
4817 // XSheetCellRange
4818 
4819 uno::Reference<sheet::XSpreadsheet> SAL_CALL ScCellRangeObj::getSpreadsheet()
4820 {
4821     SolarMutexGuard aGuard;
4822     ScDocShell* pDocSh = GetDocShell();
4823     if (pDocSh)
4824         return new ScTableSheetObj( pDocSh, aRange.aStart.Tab() );
4825 
4826     OSL_FAIL("Document invalid");
4827     return nullptr;
4828 }
4829 
4830 // XArrayFormulaRange
4831 
4832 OUString SAL_CALL ScCellRangeObj::getArrayFormula()
4833 {
4834     SolarMutexGuard aGuard;
4835 
4836     //  Matrix formula if clearly part of a matrix (so when start and end of
4837     //  the block belong to the same matrix) else empty string.
4838 
4839     ScDocShell* pDocSh = GetDocShell();
4840     if (!pDocSh)
4841         return EMPTY_OUSTRING;
4842 
4843     OUString aFormula;
4844 
4845     ScDocument& rDoc = pDocSh->GetDocument();
4846     ScRefCellValue aCell1(rDoc, aRange.aStart);
4847     ScRefCellValue aCell2(rDoc, aRange.aEnd);
4848     if (aCell1.meType == CELLTYPE_FORMULA && aCell2.meType == CELLTYPE_FORMULA)
4849     {
4850         const ScFormulaCell* pFCell1 = aCell1.mpFormula;
4851         const ScFormulaCell* pFCell2 = aCell2.mpFormula;
4852         ScAddress aStart1;
4853         ScAddress aStart2;
4854         if (pFCell1->GetMatrixOrigin(rDoc, aStart1) && pFCell2->GetMatrixOrigin(rDoc, aStart2))
4855         {
4856             if (aStart1 == aStart2)               // both the same matrix
4857                 pFCell1->GetFormula(aFormula);    // it doesn't matter from which cell
4858         }
4859     }
4860     return aFormula;
4861 }
4862 
4863 void ScCellRangeObj::SetArrayFormula_Impl(const OUString& rFormula,
4864     const formula::FormulaGrammar::Grammar eGrammar)
4865 {
4866     ScDocShell* pDocSh = GetDocShell();
4867     if (!pDocSh)
4868         return;
4869 
4870     if ( !rFormula.isEmpty() )
4871     {
4872         if ( comphelper::getUnoTunnelImplementation<ScTableSheetObj>( static_cast<cppu::OWeakObject*>(this) ) )
4873         {
4874             //  don't set array formula for sheet object
4875             throw uno::RuntimeException();
4876         }
4877 
4878         pDocSh->GetDocFunc().EnterMatrix( aRange, nullptr, nullptr, rFormula, true, true, OUString()/*rFormulaNmsp*/, eGrammar );
4879     }
4880     else
4881     {
4882         //  empty string -> erase array formula
4883         ScMarkData aMark(GetDocument()->GetSheetLimits());
4884         aMark.SetMarkArea( aRange );
4885         aMark.SelectTable( aRange.aStart.Tab(), true );
4886         pDocSh->GetDocFunc().DeleteContents( aMark, InsertDeleteFlags::CONTENTS, true, true );
4887     }
4888 }
4889 
4890 void SAL_CALL ScCellRangeObj::setArrayFormula( const OUString& aFormula )
4891 {
4892     SolarMutexGuard aGuard;
4893     // GRAM_API for API compatibility.
4894     SetArrayFormula_Impl( aFormula, formula::FormulaGrammar::GRAM_API);
4895 }
4896 
4897 // XArrayFormulaTokens
4898 uno::Sequence<sheet::FormulaToken> SAL_CALL ScCellRangeObj::getArrayTokens()
4899 {
4900     SolarMutexGuard aGuard;
4901 
4902     // same cell logic as in getArrayFormula
4903 
4904     uno::Sequence<sheet::FormulaToken> aSequence;
4905     ScDocShell* pDocSh = GetDocShell();
4906     if (!pDocSh)
4907         return aSequence;
4908 
4909     ScDocument& rDoc = pDocSh->GetDocument();
4910     ScRefCellValue aCell1(rDoc, aRange.aStart);
4911     ScRefCellValue aCell2(rDoc, aRange.aEnd);
4912     if (aCell1.meType == CELLTYPE_FORMULA && aCell2.meType == CELLTYPE_FORMULA)
4913     {
4914         const ScFormulaCell* pFCell1 = aCell1.mpFormula;
4915         const ScFormulaCell* pFCell2 = aCell2.mpFormula;
4916         ScAddress aStart1;
4917         ScAddress aStart2;
4918         if (pFCell1->GetMatrixOrigin(rDoc, aStart1) && pFCell2->GetMatrixOrigin(rDoc, aStart2))
4919         {
4920             if (aStart1 == aStart2)
4921             {
4922                 const ScTokenArray* pTokenArray = pFCell1->GetCode();
4923                 if (pTokenArray)
4924                     ScTokenConversion::ConvertToTokenSequence(rDoc, aSequence, *pTokenArray);
4925             }
4926         }
4927     }
4928 
4929     return aSequence;
4930 }
4931 
4932 void SAL_CALL ScCellRangeObj::setArrayTokens( const uno::Sequence<sheet::FormulaToken>& rTokens )
4933 {
4934     SolarMutexGuard aGuard;
4935     ScDocShell* pDocSh = GetDocShell();
4936     if ( !pDocSh )
4937         return;
4938 
4939     if ( rTokens.hasElements() )
4940     {
4941         if ( comphelper::getUnoTunnelImplementation<ScTableSheetObj>( static_cast<cppu::OWeakObject*>(this) ) )
4942         {
4943             throw uno::RuntimeException();
4944         }
4945 
4946         ScDocument& rDoc = pDocSh->GetDocument();
4947         ScTokenArray aTokenArray(rDoc);
4948         (void)ScTokenConversion::ConvertToTokenArray( rDoc, aTokenArray, rTokens );
4949 
4950         // Actually GRAM_API is a don't-care here because of the token
4951         // array being set, it fits with other API compatibility grammars
4952         // though.
4953         pDocSh->GetDocFunc().EnterMatrix( aRange, nullptr, &aTokenArray, EMPTY_OUSTRING, true, true, EMPTY_OUSTRING, formula::FormulaGrammar::GRAM_API );
4954     }
4955     else
4956     {
4957         //  empty sequence -> erase array formula
4958         ScMarkData aMark(pDocSh->GetDocument().GetSheetLimits());
4959         aMark.SetMarkArea( aRange );
4960         aMark.SelectTable( aRange.aStart.Tab(), true );
4961         pDocSh->GetDocFunc().DeleteContents( aMark, InsertDeleteFlags::CONTENTS, true, true );
4962     }
4963 }
4964 
4965 // XCellRangeData
4966 
4967 uno::Sequence< uno::Sequence<uno::Any> > SAL_CALL ScCellRangeObj::getDataArray()
4968 {
4969     SolarMutexGuard aGuard;
4970 
4971     if ( comphelper::getUnoTunnelImplementation<ScTableSheetObj>( static_cast<cppu::OWeakObject*>(this) ) )
4972     {
4973         //  don't create a data array for the sheet
4974         throw uno::RuntimeException();
4975     }
4976 
4977     ScDocShell* pDocSh = GetDocShell();
4978     if (pDocSh)
4979     {
4980         uno::Any aAny;
4981         // bAllowNV = TRUE: errors as void
4982         if ( ScRangeToSequence::FillMixedArray( aAny, pDocSh->GetDocument(), aRange, true ) )
4983         {
4984             uno::Sequence< uno::Sequence<uno::Any> > aSeq;
4985             if ( aAny >>= aSeq )
4986                 return aSeq;            // success
4987         }
4988     }
4989 
4990     throw uno::RuntimeException();      // no other exceptions specified
4991 }
4992 
4993 void SAL_CALL ScCellRangeObj::setDataArray(
4994                         const uno::Sequence< uno::Sequence<uno::Any> >& aArray )
4995 {
4996     SolarMutexGuard aGuard;
4997 
4998     bool bDone = false;
4999     ScDocShell* pDocSh = GetDocShell();
5000     if (pDocSh)
5001     {
5002         //! move lcl_PutDataArray to docfunc?
5003         bDone = lcl_PutDataArray( *pDocSh, aRange, aArray );
5004     }
5005 
5006     if (!bDone)
5007         throw uno::RuntimeException();      // no other exceptions specified
5008 }
5009 
5010 // XCellRangeFormula
5011 
5012 uno::Sequence< uno::Sequence<OUString> > SAL_CALL ScCellRangeObj::getFormulaArray()
5013 {
5014     SolarMutexGuard aGuard;
5015 
5016     if ( comphelper::getUnoTunnelImplementation<ScTableSheetObj>( static_cast<cppu::OWeakObject*>(this) ) )
5017     {
5018         //  don't create a data array for the sheet
5019         throw uno::RuntimeException();
5020     }
5021 
5022     ScDocShell* pDocSh = GetDocShell();
5023     if (pDocSh)
5024     {
5025         SCCOL nStartCol = aRange.aStart.Col();
5026         SCROW nStartRow = aRange.aStart.Row();
5027         SCCOL nEndCol = aRange.aEnd.Col();
5028         SCROW nEndRow = aRange.aEnd.Row();
5029         SCCOL nColCount = nEndCol + 1 - nStartCol;
5030         SCROW nRowCount = nEndRow + 1 - nStartRow;
5031         SCTAB nTab = aRange.aStart.Tab();
5032 
5033         uno::Sequence< uno::Sequence<OUString> > aRowSeq( nRowCount );
5034         uno::Sequence<OUString>* pRowAry = aRowSeq.getArray();
5035         for (SCROW nRowIndex = 0; nRowIndex < nRowCount; nRowIndex++)
5036         {
5037             uno::Sequence<OUString> aColSeq( nColCount );
5038             OUString* pColAry = aColSeq.getArray();
5039             for (SCCOL nColIndex = 0; nColIndex < nColCount; nColIndex++)
5040                 pColAry[nColIndex] = lcl_GetInputString( pDocSh->GetDocument(),
5041                                     ScAddress( nStartCol+nColIndex, nStartRow+nRowIndex, nTab ), true );
5042 
5043             pRowAry[nRowIndex] = aColSeq;
5044         }
5045 
5046         return aRowSeq;
5047     }
5048 
5049     throw uno::RuntimeException();      // no other exceptions specified
5050 }
5051 
5052 void SAL_CALL ScCellRangeObj::setFormulaArray(
5053                         const uno::Sequence< uno::Sequence<OUString> >& aArray )
5054 {
5055     SolarMutexGuard aGuard;
5056 
5057     bool bDone = false;
5058     ScDocShell* pDocSh = GetDocShell();
5059     if (pDocSh)
5060     {
5061         ScExternalRefManager::ApiGuard aExtRefGuard(pDocSh->GetDocument());
5062 
5063         // GRAM_API for API compatibility.
5064         bDone = lcl_PutFormulaArray( *pDocSh, aRange, aArray, formula::FormulaGrammar::GRAM_API );
5065     }
5066 
5067     if (!bDone)
5068         throw uno::RuntimeException();      // no other exceptions specified
5069 }
5070 
5071 // XMultipleOperation
5072 
5073 void SAL_CALL ScCellRangeObj::setTableOperation( const table::CellRangeAddress& aFormulaRange,
5074                                         sheet::TableOperationMode nMode,
5075                                         const table::CellAddress& aColumnCell,
5076                                         const table::CellAddress& aRowCell )
5077 {
5078     SolarMutexGuard aGuard;
5079     ScDocShell* pDocSh = GetDocShell();
5080     if (!pDocSh)
5081         return;
5082 
5083     bool bError = false;
5084     ScTabOpParam aParam;
5085     aParam.aRefFormulaCell = ScRefAddress( static_cast<SCCOL>(aFormulaRange.StartColumn),
5086                                           static_cast<SCROW>(aFormulaRange.StartRow), aFormulaRange.Sheet );
5087     aParam.aRefFormulaEnd  = ScRefAddress( static_cast<SCCOL>(aFormulaRange.EndColumn),
5088                                           static_cast<SCROW>(aFormulaRange.EndRow), aFormulaRange.Sheet );
5089     aParam.aRefRowCell     = ScRefAddress( static_cast<SCCOL>(aRowCell.Column),
5090                                           static_cast<SCROW>(aRowCell.Row), aRowCell.Sheet );
5091     aParam.aRefColCell     = ScRefAddress( static_cast<SCCOL>(aColumnCell.Column),
5092                                           static_cast<SCROW>(aColumnCell.Row), aColumnCell.Sheet );
5093 
5094     switch (nMode)
5095     {
5096         case sheet::TableOperationMode_COLUMN:
5097             aParam.meMode = ScTabOpParam::Column;
5098             break;
5099         case sheet::TableOperationMode_ROW:
5100             aParam.meMode = ScTabOpParam::Row;
5101             break;
5102         case sheet::TableOperationMode_BOTH:
5103             aParam.meMode = ScTabOpParam::Both;
5104             break;
5105         default:
5106             bError = true;
5107     }
5108 
5109     if (!bError)
5110         pDocSh->GetDocFunc().TabOp( aRange, nullptr, aParam, true, true );
5111 }
5112 
5113 // XMergeable
5114 
5115 void SAL_CALL ScCellRangeObj::merge( sal_Bool bMerge )
5116 {
5117     SolarMutexGuard aGuard;
5118     ScDocShell* pDocSh = GetDocShell();
5119     if ( !pDocSh )
5120         return;
5121 
5122     ScCellMergeOption aMergeOption(
5123         aRange.aStart.Col(), aRange.aStart.Row(),
5124         aRange.aEnd.Col(), aRange.aEnd.Row(), false);
5125     aMergeOption.maTabs.insert(aRange.aStart.Tab());
5126     if ( bMerge )
5127         pDocSh->GetDocFunc().MergeCells( aMergeOption, false, true, true );
5128     else
5129         pDocSh->GetDocFunc().UnmergeCells( aMergeOption, true, nullptr );
5130 
5131     //! Catch error?
5132 }
5133 
5134 sal_Bool SAL_CALL ScCellRangeObj::getIsMerged()
5135 {
5136     SolarMutexGuard aGuard;
5137     ScDocShell* pDocSh = GetDocShell();
5138     return pDocSh && pDocSh->GetDocument().HasAttrib( aRange, HasAttrFlags::Merged );
5139 }
5140 
5141 // XCellSeries
5142 
5143 void SAL_CALL ScCellRangeObj::fillSeries( sheet::FillDirection nFillDirection,
5144                         sheet::FillMode nFillMode, sheet::FillDateMode nFillDateMode,
5145                         double fStep, double fEndValue )
5146 {
5147     SolarMutexGuard aGuard;
5148     ScDocShell* pDocSh = GetDocShell();
5149     if ( !pDocSh )
5150         return;
5151 
5152     bool bError = false;
5153 
5154     FillDir eDir = FILL_TO_BOTTOM;
5155     switch (nFillDirection)
5156     {
5157         case sheet::FillDirection_TO_BOTTOM:
5158             eDir = FILL_TO_BOTTOM;
5159             break;
5160         case sheet::FillDirection_TO_RIGHT:
5161             eDir = FILL_TO_RIGHT;
5162             break;
5163         case sheet::FillDirection_TO_TOP:
5164             eDir = FILL_TO_TOP;
5165             break;
5166         case sheet::FillDirection_TO_LEFT:
5167             eDir = FILL_TO_LEFT;
5168             break;
5169         default:
5170             bError = true;
5171     }
5172 
5173     FillCmd eCmd = FILL_SIMPLE;
5174     switch ( nFillMode )
5175     {
5176         case sheet::FillMode_SIMPLE:
5177             eCmd = FILL_SIMPLE;
5178             break;
5179         case sheet::FillMode_LINEAR:
5180             eCmd = FILL_LINEAR;
5181             break;
5182         case sheet::FillMode_GROWTH:
5183             eCmd = FILL_GROWTH;
5184             break;
5185         case sheet::FillMode_DATE:
5186             eCmd = FILL_DATE;
5187             break;
5188         case sheet::FillMode_AUTO:
5189             eCmd = FILL_AUTO;
5190             break;
5191         default:
5192             bError = true;
5193     }
5194 
5195     FillDateCmd eDateCmd = FILL_DAY;
5196     switch ( nFillDateMode )
5197     {
5198         case sheet::FillDateMode_FILL_DATE_DAY:
5199             eDateCmd = FILL_DAY;
5200             break;
5201         case sheet::FillDateMode_FILL_DATE_WEEKDAY:
5202             eDateCmd = FILL_WEEKDAY;
5203             break;
5204         case sheet::FillDateMode_FILL_DATE_MONTH:
5205             eDateCmd = FILL_MONTH;
5206             break;
5207         case sheet::FillDateMode_FILL_DATE_YEAR:
5208             eDateCmd = FILL_YEAR;
5209             break;
5210         default:
5211             bError = true;
5212     }
5213 
5214     if (!bError)
5215         pDocSh->GetDocFunc().FillSeries( aRange, nullptr, eDir, eCmd, eDateCmd,
5216                                             MAXDOUBLE, fStep, fEndValue, true );
5217 }
5218 
5219 void SAL_CALL ScCellRangeObj::fillAuto( sheet::FillDirection nFillDirection,
5220                                 sal_Int32 nSourceCount )
5221 {
5222     SolarMutexGuard aGuard;
5223     ScDocShell* pDocSh = GetDocShell();
5224     if ( !(pDocSh && nSourceCount) )
5225         return;
5226 
5227     ScRange aSourceRange(aRange);
5228     SCCOLROW nCount = 0;                   // "Dest-Count"
5229     FillDir eDir = FILL_TO_BOTTOM;
5230     bool bError = false;
5231     switch (nFillDirection)
5232     {
5233         case sheet::FillDirection_TO_BOTTOM:
5234             aSourceRange.aEnd.SetRow( static_cast<SCROW>( aSourceRange.aStart.Row() + nSourceCount - 1 ) );
5235             nCount = aRange.aEnd.Row() - aSourceRange.aEnd.Row();
5236             eDir = FILL_TO_BOTTOM;
5237             break;
5238         case sheet::FillDirection_TO_RIGHT:
5239             aSourceRange.aEnd.SetCol( static_cast<SCCOL>( aSourceRange.aStart.Col() + nSourceCount - 1 ) );
5240             nCount = aRange.aEnd.Col() - aSourceRange.aEnd.Col();
5241             eDir = FILL_TO_RIGHT;
5242             break;
5243         case sheet::FillDirection_TO_TOP:
5244             aSourceRange.aStart.SetRow( static_cast<SCROW>( aSourceRange.aEnd.Row() - nSourceCount + 1 ) );
5245             nCount = aSourceRange.aStart.Row() - aRange.aStart.Row();
5246             eDir = FILL_TO_TOP;
5247             break;
5248         case sheet::FillDirection_TO_LEFT:
5249             aSourceRange.aStart.SetCol( static_cast<SCCOL>( aSourceRange.aEnd.Col() - nSourceCount + 1 ) );
5250             nCount = aSourceRange.aStart.Col() - aRange.aStart.Col();
5251             eDir = FILL_TO_LEFT;
5252             break;
5253         default:
5254             bError = true;
5255     }
5256     const ScDocument& rDoc = pDocSh->GetDocument();
5257     if (nCount < 0 || nCount > rDoc.MaxRow())      // overflow
5258         bError = true;
5259 
5260     if (!bError)
5261         pDocSh->GetDocFunc().FillAuto( aSourceRange, nullptr, eDir, nCount, true );
5262 }
5263 
5264 // XAutoFormattable
5265 
5266 void SAL_CALL ScCellRangeObj::autoFormat( const OUString& aName )
5267 {
5268     SolarMutexGuard aGuard;
5269     ScDocShell* pDocSh = GetDocShell();
5270     if ( pDocSh )
5271     {
5272         ScAutoFormat* pAutoFormat = ScGlobal::GetOrCreateAutoFormat();
5273         ScAutoFormat::const_iterator it = pAutoFormat->find(aName);
5274         if (it == pAutoFormat->end())
5275             throw lang::IllegalArgumentException();
5276 
5277         ScAutoFormat::const_iterator itBeg = pAutoFormat->begin();
5278         size_t nIndex = std::distance(itBeg, it);
5279         pDocSh->GetDocFunc().AutoFormat(aRange, nullptr, nIndex, true);
5280 
5281     }
5282 }
5283 
5284 // XSortable
5285 
5286 uno::Sequence<beans::PropertyValue> SAL_CALL ScCellRangeObj::createSortDescriptor()
5287 {
5288     SolarMutexGuard aGuard;
5289     ScSortParam aParam;
5290     ScDocShell* pDocSh = GetDocShell();
5291     if ( pDocSh )
5292     {
5293         // create DB-Area only during execution; API always the exact area
5294         ScDBData* pData = pDocSh->GetDBData( aRange, SC_DB_OLD, ScGetDBSelection::ForceMark );
5295         if (pData)
5296         {
5297             pData->GetSortParam(aParam);
5298 
5299             //  SortDescriptor contains the counted fields inside the area
5300             ScRange aDBRange;
5301             pData->GetArea(aDBRange);
5302             SCCOLROW nFieldStart = aParam.bByRow ?
5303                 static_cast<SCCOLROW>(aDBRange.aStart.Col()) :
5304                 static_cast<SCCOLROW>(aDBRange.aStart.Row());
5305             for (sal_uInt16 i=0; i<aParam.GetSortKeyCount(); i++)
5306                 if ( aParam.maKeyState[i].bDoSort && aParam.maKeyState[i].nField >= nFieldStart )
5307                     aParam.maKeyState[i].nField -= nFieldStart;
5308         }
5309     }
5310 
5311     uno::Sequence<beans::PropertyValue> aSeq( ScSortDescriptor::GetPropertyCount() );
5312     ScSortDescriptor::FillProperties( aSeq, aParam );
5313     return aSeq;
5314 }
5315 
5316 void SAL_CALL ScCellRangeObj::sort( const uno::Sequence<beans::PropertyValue>& aDescriptor )
5317 {
5318     SolarMutexGuard aGuard;
5319     ScDocShell* pDocSh = GetDocShell();
5320     if (!pDocSh)
5321         return;
5322 
5323     sal_uInt16 i;
5324     ScSortParam aParam;
5325     ScDBData* pData = pDocSh->GetDBData( aRange, SC_DB_MAKE, ScGetDBSelection::ForceMark ); // if needed create area
5326     if (pData)
5327     {
5328         //  get old settings if not everything is set anew
5329         pData->GetSortParam(aParam);
5330         SCCOLROW nOldStart = aParam.bByRow ?
5331             static_cast<SCCOLROW>(aRange.aStart.Col()) :
5332             static_cast<SCCOLROW>(aRange.aStart.Row());
5333         for (i=0; i<aParam.GetSortKeyCount(); i++)
5334             if ( aParam.maKeyState[i].bDoSort && aParam.maKeyState[i].nField >= nOldStart )
5335                 aParam.maKeyState[i].nField -= nOldStart;
5336     }
5337 
5338     ScSortDescriptor::FillSortParam( aParam, aDescriptor );
5339 
5340     //  SortDescriptor contains the counted fields inside the area
5341     //  ByRow can be changed during execution of FillSortParam
5342     SCCOLROW nFieldStart = aParam.bByRow ?
5343         static_cast<SCCOLROW>(aRange.aStart.Col()) :
5344         static_cast<SCCOLROW>(aRange.aStart.Row());
5345     SCCOLROW nFieldEnd = aParam.bByRow ?
5346         static_cast<SCCOLROW>(aRange.aEnd.Col()) :
5347         static_cast<SCCOLROW>(aRange.aEnd.Row());
5348     for (i=0; i<aParam.GetSortKeyCount(); i++)
5349     {
5350         aParam.maKeyState[i].nField += nFieldStart;
5351         // tdf#103632 - sanity check poorly behaved macros.
5352         if (aParam.maKeyState[i].nField > nFieldEnd)
5353             aParam.maKeyState[i].nField = nFieldEnd;
5354     }
5355 
5356     SCTAB nTab = aRange.aStart.Tab();
5357     aParam.nCol1 = aRange.aStart.Col();
5358     aParam.nRow1 = aRange.aStart.Row();
5359     aParam.nCol2 = aRange.aEnd.Col();
5360     aParam.nRow2 = aRange.aEnd.Row();
5361 
5362     pDocSh->GetDBData( aRange, SC_DB_MAKE, ScGetDBSelection::ForceMark );       // if needed create area
5363 
5364     ScDBDocFunc aFunc(*pDocSh); // area must be created
5365     (void)aFunc.Sort( nTab, aParam, true, true, true );
5366 }
5367 
5368 // XFilterable
5369 
5370 uno::Reference<sheet::XSheetFilterDescriptor> SAL_CALL ScCellRangeObj::createFilterDescriptor(
5371                                 sal_Bool bEmpty )
5372 {
5373     SolarMutexGuard aGuard;
5374     ScDocShell* pDocSh = GetDocShell();
5375     ScFilterDescriptor* pNew = new ScFilterDescriptor(pDocSh);
5376     if ( !bEmpty && pDocSh )
5377     {
5378         // create DB-Area only during execution; API always the exact area
5379         ScDBData* pData = pDocSh->GetDBData( aRange, SC_DB_OLD, ScGetDBSelection::ForceMark );
5380         if (pData)
5381         {
5382             ScQueryParam aParam;
5383             pData->GetQueryParam(aParam);
5384             //  FilterDescriptor contains the counted fields inside the area
5385             ScRange aDBRange;
5386             pData->GetArea(aDBRange);
5387             SCCOLROW nFieldStart = aParam.bByRow ?
5388                 static_cast<SCCOLROW>(aDBRange.aStart.Col()) :
5389                 static_cast<SCCOLROW>(aDBRange.aStart.Row());
5390             SCSIZE nCount = aParam.GetEntryCount();
5391             for (SCSIZE i=0; i<nCount; i++)
5392             {
5393                 ScQueryEntry& rEntry = aParam.GetEntry(i);
5394                 if (rEntry.bDoQuery && rEntry.nField >= nFieldStart)
5395                     rEntry.nField -= nFieldStart;
5396             }
5397             pNew->SetParam(aParam);
5398         }
5399     }
5400     return pNew;
5401 }
5402 
5403 void SAL_CALL ScCellRangeObj::filter( const uno::Reference<sheet::XSheetFilterDescriptor>& xDescriptor )
5404 {
5405     SolarMutexGuard aGuard;
5406 
5407     if (!xDescriptor.is()) return;
5408 
5409     //  This could be theoretically an unknown object, so only use the
5410     //  public XSheetFilterDescriptor interface to copy the data into a
5411     //  ScFilterDescriptor object:
5412     //! if it already a ScFilterDescriptor is, direct via getImplementation?
5413 
5414     ScDocShell* pDocSh = GetDocShell();
5415     rtl::Reference<ScFilterDescriptor> xImpl(new ScFilterDescriptor(pDocSh));
5416     uno::Reference< sheet::XSheetFilterDescriptor2 > xDescriptor2( xDescriptor, uno::UNO_QUERY );
5417     if ( xDescriptor2.is() )
5418     {
5419         xImpl->setFilterFields2( xDescriptor2->getFilterFields2() );
5420     }
5421     else
5422     {
5423         xImpl->setFilterFields( xDescriptor->getFilterFields() );
5424     }
5425     //  the rest are now properties...
5426 
5427     uno::Reference<beans::XPropertySet> xPropSet( xDescriptor, uno::UNO_QUERY );
5428     if (xPropSet.is())
5429         lcl_CopyProperties(*xImpl, *xPropSet);
5430 
5431     if (!pDocSh)
5432         return;
5433 
5434     ScQueryParam aParam = xImpl->GetParam();
5435     //  FilterDescriptor contains the counted fields inside the area
5436     SCCOLROW nFieldStart = aParam.bByRow ?
5437         static_cast<SCCOLROW>(aRange.aStart.Col()) :
5438         static_cast<SCCOLROW>(aRange.aStart.Row());
5439     SCSIZE nCount = aParam.GetEntryCount();
5440     svl::SharedStringPool& rPool = pDocSh->GetDocument().GetSharedStringPool();
5441     for (SCSIZE i=0; i<nCount; i++)
5442     {
5443         ScQueryEntry& rEntry = aParam.GetEntry(i);
5444         if (rEntry.bDoQuery)
5445         {
5446             rEntry.nField += nFieldStart;
5447             //  dialog always shows the string -> must match the value
5448             ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems();
5449             rItems.resize(1);
5450             ScQueryEntry::Item& rItem = rItems.front();
5451             if (rItem.meType != ScQueryEntry::ByString)
5452             {
5453                 OUString aStr;
5454                 pDocSh->GetDocument().GetFormatTable()->GetInputLineString(rItem.mfVal, 0, aStr);
5455                 rItem.maString = rPool.intern(aStr);
5456             }
5457         }
5458     }
5459 
5460     SCTAB nTab = aRange.aStart.Tab();
5461     aParam.nCol1 = aRange.aStart.Col();
5462     aParam.nRow1 = aRange.aStart.Row();
5463     aParam.nCol2 = aRange.aEnd.Col();
5464     aParam.nRow2 = aRange.aEnd.Row();
5465 
5466     pDocSh->GetDBData( aRange, SC_DB_MAKE, ScGetDBSelection::ForceMark );   // if needed create area
5467 
5468     //! keep source range in filter descriptor
5469     //! if created by createFilterDescriptorByObject ???
5470 
5471     ScDBDocFunc aFunc(*pDocSh);
5472     aFunc.Query( nTab, aParam, nullptr, true, true );  // area must be created
5473 }
5474 
5475 //! get/setAutoFilter as properties!!!
5476 
5477 // XAdvancedFilterSource
5478 
5479 uno::Reference<sheet::XSheetFilterDescriptor> SAL_CALL ScCellRangeObj::createFilterDescriptorByObject(
5480                         const uno::Reference<sheet::XSheetFilterable>& xObject )
5481 {
5482     SolarMutexGuard aGuard;
5483 
5484     //  this here is not the area, which will be filtered, instead the area
5485     //  with the query
5486 
5487     uno::Reference<sheet::XCellRangeAddressable> xAddr( xObject, uno::UNO_QUERY );
5488 
5489     ScDocShell* pDocSh = GetDocShell();
5490     if ( !pDocSh || !xAddr.is() )
5491     {
5492         OSL_FAIL("no document or no area");
5493         return nullptr;
5494     }
5495 
5496     //! check if xObject is in the same document
5497 
5498     rtl::Reference<ScFilterDescriptor> pNew(new ScFilterDescriptor(pDocSh));  //! instead from object?
5499 
5500     ScQueryParam aParam = pNew->GetParam();
5501     aParam.bHasHeader = true;
5502 
5503     table::CellRangeAddress aDataAddress(xAddr->getRangeAddress());
5504     aParam.nCol1 = static_cast<SCCOL>(aDataAddress.StartColumn);
5505     aParam.nRow1 = static_cast<SCROW>(aDataAddress.StartRow);
5506     aParam.nCol2 = static_cast<SCCOL>(aDataAddress.EndColumn);
5507     aParam.nRow2 = static_cast<SCROW>(aDataAddress.EndRow);
5508     aParam.nTab  = aDataAddress.Sheet;
5509 
5510     ScDocument& rDoc = pDocSh->GetDocument();
5511     if (!rDoc.CreateQueryParam(aRange, aParam))
5512         return nullptr;
5513 
5514     //  FilterDescriptor contains the counted fields inside the area
5515     SCCOLROW nFieldStart = aParam.bByRow ?
5516         static_cast<SCCOLROW>(aDataAddress.StartColumn) :
5517         static_cast<SCCOLROW>(aDataAddress.StartRow);
5518     SCSIZE nCount = aParam.GetEntryCount();
5519     for (SCSIZE i=0; i<nCount; i++)
5520     {
5521         ScQueryEntry& rEntry = aParam.GetEntry(i);
5522         if (rEntry.bDoQuery && rEntry.nField >= nFieldStart)
5523             rEntry.nField -= nFieldStart;
5524     }
5525 
5526     pNew->SetParam( aParam );
5527     return pNew;
5528 }
5529 
5530 // XSubTotalSource
5531 
5532 uno::Reference<sheet::XSubTotalDescriptor> SAL_CALL ScCellRangeObj::createSubTotalDescriptor(
5533                                 sal_Bool bEmpty )
5534 {
5535     SolarMutexGuard aGuard;
5536     ScSubTotalDescriptor* pNew = new ScSubTotalDescriptor;
5537     ScDocShell* pDocSh = GetDocShell();
5538     if ( !bEmpty && pDocSh )
5539     {
5540         // create DB-Area only during execution; API always the exact area
5541         ScDBData* pData = pDocSh->GetDBData( aRange, SC_DB_OLD, ScGetDBSelection::ForceMark );
5542         if (pData)
5543         {
5544             ScSubTotalParam aParam;
5545             pData->GetSubTotalParam(aParam);
5546             //  SubTotalDescriptor contains the counted fields inside the area
5547             ScRange aDBRange;
5548             pData->GetArea(aDBRange);
5549             SCCOL nFieldStart = aDBRange.aStart.Col();
5550             for (sal_uInt16 i=0; i<MAXSUBTOTAL; i++)
5551             {
5552                 if ( aParam.bGroupActive[i] )
5553                 {
5554                     if ( aParam.nField[i] >= nFieldStart )
5555                         aParam.nField[i] = sal::static_int_cast<SCCOL>( aParam.nField[i] - nFieldStart );
5556                     for (SCCOL j=0; j<aParam.nSubTotals[i]; j++)
5557                         if ( aParam.pSubTotals[i][j] >= nFieldStart )
5558                             aParam.pSubTotals[i][j] = sal::static_int_cast<SCCOL>( aParam.pSubTotals[i][j] - nFieldStart );
5559                 }
5560             }
5561             pNew->SetParam(aParam);
5562         }
5563     }
5564     return pNew;
5565 }
5566 
5567 void SAL_CALL ScCellRangeObj::applySubTotals(
5568     const uno::Reference<sheet::XSubTotalDescriptor>& xDescriptor,
5569     sal_Bool bReplace)
5570 {
5571     SolarMutexGuard aGuard;
5572 
5573     if (!xDescriptor.is()) return;
5574 
5575     ScDocShell* pDocSh = GetDocShell();
5576     ScSubTotalDescriptorBase* pImp =
5577         comphelper::getUnoTunnelImplementation<ScSubTotalDescriptorBase>( xDescriptor );
5578 
5579     if (!(pDocSh && pImp))
5580         return;
5581 
5582     ScSubTotalParam aParam;
5583     pImp->GetData(aParam);      // virtual method of base class
5584 
5585     //  SubTotalDescriptor contains the counted fields inside the area
5586     SCCOL nFieldStart = aRange.aStart.Col();
5587     for (sal_uInt16 i=0; i<MAXSUBTOTAL; i++)
5588     {
5589         if ( aParam.bGroupActive[i] )
5590         {
5591             aParam.nField[i] = sal::static_int_cast<SCCOL>( aParam.nField[i] + nFieldStart );
5592             for (SCCOL j=0; j<aParam.nSubTotals[i]; j++)
5593                 aParam.pSubTotals[i][j] = sal::static_int_cast<SCCOL>( aParam.pSubTotals[i][j] + nFieldStart );
5594         }
5595     }
5596 
5597     aParam.bReplace = bReplace;
5598 
5599     SCTAB nTab = aRange.aStart.Tab();
5600     aParam.nCol1 = aRange.aStart.Col();
5601     aParam.nRow1 = aRange.aStart.Row();
5602     aParam.nCol2 = aRange.aEnd.Col();
5603     aParam.nRow2 = aRange.aEnd.Row();
5604 
5605     pDocSh->GetDBData( aRange, SC_DB_MAKE, ScGetDBSelection::ForceMark );   // if needed create area
5606 
5607     ScDBDocFunc aFunc(*pDocSh);
5608     aFunc.DoSubTotals( nTab, aParam, true, true );    // area must be created
5609 }
5610 
5611 void SAL_CALL ScCellRangeObj::removeSubTotals()
5612 {
5613     SolarMutexGuard aGuard;
5614 
5615     ScDocShell* pDocSh = GetDocShell();
5616     if (!pDocSh)
5617         return;
5618 
5619     ScSubTotalParam aParam;
5620     ScDBData* pData = pDocSh->GetDBData( aRange, SC_DB_OLD, ScGetDBSelection::ForceMark );
5621     if (pData)
5622         pData->GetSubTotalParam(aParam);    // also keep field entries during remove
5623 
5624     aParam.bRemoveOnly = true;
5625 
5626     SCTAB nTab = aRange.aStart.Tab();
5627     aParam.nCol1 = aRange.aStart.Col();
5628     aParam.nRow1 = aRange.aStart.Row();
5629     aParam.nCol2 = aRange.aEnd.Col();
5630     aParam.nRow2 = aRange.aEnd.Row();
5631 
5632     pDocSh->GetDBData( aRange, SC_DB_MAKE, ScGetDBSelection::ForceMark );   // if needed create area
5633 
5634     ScDBDocFunc aFunc(*pDocSh);
5635     aFunc.DoSubTotals( nTab, aParam, true, true );    // are must be created
5636 }
5637 
5638 uno::Sequence<beans::PropertyValue> SAL_CALL ScCellRangeObj::createImportDescriptor( sal_Bool bEmpty )
5639 {
5640     SolarMutexGuard aGuard;
5641     ScImportParam aParam;
5642     ScDocShell* pDocSh = GetDocShell();
5643     if ( !bEmpty && pDocSh )
5644     {
5645         // create DB-Area only during execution; API always the exact area
5646         ScDBData* pData = pDocSh->GetDBData( aRange, SC_DB_OLD, ScGetDBSelection::ForceMark );
5647         if (pData)
5648             pData->GetImportParam(aParam);
5649     }
5650 
5651     uno::Sequence<beans::PropertyValue> aSeq( ScImportDescriptor::GetPropertyCount() );
5652     ScImportDescriptor::FillProperties( aSeq, aParam );
5653     return aSeq;
5654 }
5655 
5656 void SAL_CALL ScCellRangeObj::doImport( const uno::Sequence<beans::PropertyValue>& aDescriptor )
5657 {
5658     SolarMutexGuard aGuard;
5659     ScDocShell* pDocSh = GetDocShell();
5660     if (!pDocSh)
5661         return;
5662 
5663     ScImportParam aParam;
5664     ScImportDescriptor::FillImportParam( aParam, aDescriptor );
5665 
5666     SCTAB nTab = aRange.aStart.Tab();
5667     aParam.nCol1 = aRange.aStart.Col();
5668     aParam.nRow1 = aRange.aStart.Row();
5669     aParam.nCol2 = aRange.aEnd.Col();
5670     aParam.nRow2 = aRange.aEnd.Row();
5671 
5672     //! TODO: could we get passed a valid result set by any means?
5673 
5674     pDocSh->GetDBData( aRange, SC_DB_MAKE, ScGetDBSelection::ForceMark );       // if needed create area
5675 
5676     ScDBDocFunc aFunc(*pDocSh);                         // are must be created
5677     aFunc.DoImport( nTab, aParam, nullptr );         //! Api-Flag as parameter
5678 }
5679 
5680 // XCellFormatRangesSupplier
5681 
5682 uno::Reference<container::XIndexAccess> SAL_CALL ScCellRangeObj::getCellFormatRanges()
5683 {
5684     SolarMutexGuard aGuard;
5685     ScDocShell* pDocSh = GetDocShell();
5686     if ( pDocSh )
5687         return new ScCellFormatsObj( pDocSh, aRange );
5688     return nullptr;
5689 }
5690 
5691 // XUniqueCellFormatRangesSupplier
5692 
5693 uno::Reference<container::XIndexAccess> SAL_CALL ScCellRangeObj::getUniqueCellFormatRanges()
5694 {
5695     SolarMutexGuard aGuard;
5696     ScDocShell* pDocSh = GetDocShell();
5697     if ( pDocSh )
5698         return new ScUniqueCellFormatsObj( pDocSh, aRange );
5699     return nullptr;
5700 }
5701 
5702 // XPropertySet extended for Range-Properties
5703 
5704 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScCellRangeObj::getPropertySetInfo()
5705 {
5706     SolarMutexGuard aGuard;
5707     static uno::Reference<beans::XPropertySetInfo> aRef(
5708         new SfxItemPropertySetInfo( pRangePropSet->getPropertyMap() ));
5709     return aRef;
5710 }
5711 
5712 void ScCellRangeObj::SetOnePropertyValue( const SfxItemPropertySimpleEntry* pEntry, const uno::Any& aValue )
5713 {
5714     //  Range has only Position and Size in addition to ScCellRangesBase, both are ReadOnly
5715     //  -> nothing to do here
5716 
5717     ScCellRangesBase::SetOnePropertyValue( pEntry, aValue );
5718 }
5719 
5720 void ScCellRangeObj::GetOnePropertyValue( const SfxItemPropertySimpleEntry* pEntry, uno::Any& rAny )
5721 {
5722     if ( !pEntry )
5723         return;
5724 
5725     if ( pEntry->nWID == SC_WID_UNO_POS )
5726     {
5727         ScDocShell* pDocSh = GetDocShell();
5728         if (pDocSh)
5729         {
5730             //  GetMMRect converts using HMM_PER_TWIPS, like the DrawingLayer
5731             tools::Rectangle aMMRect(pDocSh->GetDocument().GetMMRect(
5732                                     aRange.aStart.Col(), aRange.aStart.Row(),
5733                                     aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aStart.Tab() ));
5734             awt::Point aPos( aMMRect.Left(), aMMRect.Top() );
5735             rAny <<= aPos;
5736         }
5737     }
5738     else if ( pEntry->nWID == SC_WID_UNO_SIZE )
5739     {
5740         ScDocShell* pDocSh = GetDocShell();
5741         if (pDocSh)
5742         {
5743             //  GetMMRect converts using HMM_PER_TWIPS, like the DrawingLayer
5744             tools::Rectangle aMMRect = pDocSh->GetDocument().GetMMRect(
5745                                     aRange.aStart.Col(), aRange.aStart.Row(),
5746                                     aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aStart.Tab() );
5747             Size aSize(aMMRect.GetSize());
5748             awt::Size aAwtSize( aSize.Width(), aSize.Height() );
5749             rAny <<= aAwtSize;
5750         }
5751     }
5752     else
5753         ScCellRangesBase::GetOnePropertyValue( pEntry, rAny );
5754 }
5755 
5756 const SfxItemPropertyMap& ScCellRangeObj::GetItemPropertyMap()
5757 {
5758     return pRangePropSet->getPropertyMap();
5759 }
5760 
5761 // XServiceInfo
5762 
5763 OUString SAL_CALL ScCellRangeObj::getImplementationName()
5764 {
5765     return "ScCellRangeObj";
5766 }
5767 
5768 sal_Bool SAL_CALL ScCellRangeObj::supportsService( const OUString& rServiceName )
5769 {
5770     return cppu::supportsService(this, rServiceName);
5771 }
5772 
5773 uno::Sequence<OUString> SAL_CALL ScCellRangeObj::getSupportedServiceNames()
5774 {
5775     return {SCSHEETCELLRANGE_SERVICE,
5776             SCCELLRANGE_SERVICE,
5777             SCCELLPROPERTIES_SERVICE,
5778             SCCHARPROPERTIES_SERVICE,
5779             SCPARAPROPERTIES_SERVICE};
5780 }
5781 
5782 const SvxItemPropertySet* ScCellObj::GetEditPropertySet()
5783 {
5784     return lcl_GetEditPropertySet();
5785 }
5786 
5787 const SfxItemPropertyMap& ScCellObj::GetCellPropertyMap()
5788 {
5789     return lcl_GetCellPropertySet()->getPropertyMap();
5790 }
5791 
5792 ScCellObj::ScCellObj(ScDocShell* pDocSh, const ScAddress& rP) :
5793     ScCellRangeObj( pDocSh, ScRange(rP,rP) ),
5794     pCellPropSet( lcl_GetCellPropertySet() ),
5795     aCellPos( rP ),
5796     nActionLockCount( 0 )
5797 {
5798     //  pUnoText is allocated on demand (GetUnoText)
5799     //  can't be aggregated because getString/setString is handled here
5800 }
5801 
5802 SvxUnoText& ScCellObj::GetUnoText()
5803 {
5804     if (!mxUnoText.is())
5805     {
5806         mxUnoText.set(new ScCellTextObj(GetDocShell(), aCellPos));
5807         if (nActionLockCount)
5808         {
5809             ScCellEditSource* pEditSource =
5810                 static_cast<ScCellEditSource*> (mxUnoText->GetEditSource());
5811             if (pEditSource)
5812                 pEditSource->SetDoUpdateData(false);
5813         }
5814     }
5815     return *mxUnoText;
5816 }
5817 
5818 ScCellObj::~ScCellObj()
5819 {
5820 }
5821 
5822 void ScCellObj::RefChanged()
5823 {
5824     ScCellRangeObj::RefChanged();
5825 
5826     const ScRangeList& rRanges = GetRangeList();
5827     OSL_ENSURE(rRanges.size() == 1, "What ranges ?!?!");
5828     if ( !rRanges.empty() )
5829     {
5830         aCellPos = rRanges[ 0 ].aStart;
5831     }
5832 }
5833 
5834 uno::Any SAL_CALL ScCellObj::queryInterface( const uno::Type& rType )
5835 {
5836     SC_QUERYINTERFACE( table::XCell )
5837     SC_QUERYINTERFACE( table::XCell2 )
5838     SC_QUERYINTERFACE( sheet::XFormulaTokens )
5839     SC_QUERYINTERFACE( sheet::XCellAddressable )
5840     SC_QUERYINTERFACE( text::XText )
5841     SC_QUERYINTERFACE( text::XSimpleText )
5842     SC_QUERYINTERFACE( text::XTextRange )
5843     SC_QUERYINTERFACE( container::XEnumerationAccess )
5844     SC_QUERYINTERFACE( container::XElementAccess )
5845     SC_QUERYINTERFACE( sheet::XSheetAnnotationAnchor )
5846     SC_QUERYINTERFACE( text::XTextFieldsSupplier )
5847     SC_QUERYINTERFACE( document::XActionLockable )
5848 
5849     return ScCellRangeObj::queryInterface( rType );
5850 }
5851 
5852 void SAL_CALL ScCellObj::acquire() throw()
5853 {
5854     ScCellRangeObj::acquire();
5855 }
5856 
5857 void SAL_CALL ScCellObj::release() throw()
5858 {
5859     ScCellRangeObj::release();
5860 }
5861 
5862 uno::Sequence<uno::Type> SAL_CALL ScCellObj::getTypes()
5863 {
5864     static const uno::Sequence<uno::Type> aTypes = comphelper::concatSequences(
5865         ScCellRangeObj::getTypes(),
5866         uno::Sequence<uno::Type>
5867         {
5868             cppu::UnoType<table::XCell>::get(),
5869             cppu::UnoType<sheet::XCellAddressable>::get(),
5870             cppu::UnoType<text::XText>::get(),
5871             cppu::UnoType<container::XEnumerationAccess>::get(),
5872             cppu::UnoType<sheet::XSheetAnnotationAnchor>::get(),
5873             cppu::UnoType<text::XTextFieldsSupplier>::get(),
5874             cppu::UnoType<document::XActionLockable>::get(),
5875             cppu::UnoType<sheet::XFormulaTokens>::get(),
5876             cppu::UnoType<table::XCell2>::get()
5877         } );
5878     return aTypes;
5879 }
5880 
5881 uno::Sequence<sal_Int8> SAL_CALL ScCellObj::getImplementationId()
5882 {
5883     return css::uno::Sequence<sal_Int8>();
5884 }
5885 
5886 // helper methods
5887 
5888 OUString ScCellObj::GetInputString_Impl(bool bEnglish) const      // for getFormula / FormulaLocal
5889 {
5890     if (GetDocShell())
5891         return lcl_GetInputString( GetDocShell()->GetDocument(), aCellPos, bEnglish );
5892     return OUString();
5893 }
5894 
5895 OUString ScCellObj::GetOutputString_Impl() const
5896 {
5897     ScDocShell* pDocSh = GetDocShell();
5898     OUString aVal;
5899     if ( pDocSh )
5900     {
5901         ScDocument& rDoc = pDocSh->GetDocument();
5902         ScRefCellValue aCell(rDoc, aCellPos);
5903 
5904         aVal = ScCellFormat::GetOutputString(rDoc, aCellPos, aCell);
5905     }
5906     return aVal;
5907 }
5908 
5909 void ScCellObj::SetString_Impl(const OUString& rString, bool bInterpret, bool bEnglish)
5910 {
5911     ScDocShell* pDocSh = GetDocShell();
5912     if ( pDocSh )
5913     {
5914         // GRAM_API for API compatibility.
5915         (void)pDocSh->GetDocFunc().SetCellText(
5916             aCellPos, rString, bInterpret, bEnglish, true, formula::FormulaGrammar::GRAM_API );
5917     }
5918 }
5919 
5920 double ScCellObj::GetValue_Impl() const
5921 {
5922     ScDocShell* pDocSh = GetDocShell();
5923     if ( pDocSh )
5924         return pDocSh->GetDocument().GetValue( aCellPos );
5925 
5926     return 0.0;
5927 }
5928 
5929 void ScCellObj::SetValue_Impl(double fValue)
5930 {
5931     ScDocShell* pDocSh = GetDocShell();
5932     if ( pDocSh )
5933         pDocSh->GetDocFunc().SetValueCell(aCellPos, fValue, false);
5934 }
5935 
5936 // only for XML import
5937 
5938 void ScCellObj::InputEnglishString( const OUString& rText )
5939 {
5940     // This is like a mixture of setFormula and property FormulaLocal:
5941     // The cell's number format is checked for "text", a new cell format may be set,
5942     // but all parsing is in English.
5943 
5944     ScDocShell* pDocSh = GetDocShell();
5945     if (!pDocSh)
5946         return;
5947 
5948     ScDocument& rDoc = pDocSh->GetDocument();
5949     SvNumberFormatter* pFormatter = rDoc.GetFormatTable();
5950     sal_uInt32 nOldFormat = rDoc.GetNumberFormat( aCellPos );
5951     if (pFormatter->GetType(nOldFormat) == SvNumFormatType::TEXT)
5952     {
5953         SetString_Impl(rText, false, false);      // text cell
5954         return;
5955     }
5956 
5957     ScDocFunc &rFunc = pDocSh->GetDocFunc();
5958 
5959     ScInputStringType aRes =
5960         ScStringUtil::parseInputString(*pFormatter, rText, LANGUAGE_ENGLISH_US);
5961 
5962     if (aRes.meType != ScInputStringType::Unknown)
5963     {
5964         if ((nOldFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 && aRes.mnFormatType != SvNumFormatType::ALL)
5965         {
5966             // apply a format for the recognized type and the old format's language
5967             sal_uInt32 nNewFormat = ScGlobal::GetStandardFormat(*pFormatter, nOldFormat, aRes.mnFormatType);
5968             if (nNewFormat != nOldFormat)
5969             {
5970                 ScPatternAttr aPattern( rDoc.GetPool() );
5971                 aPattern.GetItemSet().Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNewFormat ) );
5972                 // ATTR_LANGUAGE_FORMAT remains unchanged
5973                 rFunc.ApplyAttributes( *GetMarkData(), aPattern, true );
5974             }
5975         }
5976     }
5977     switch (aRes.meType)
5978     {
5979         case ScInputStringType::Formula:
5980             rFunc.SetFormulaCell(
5981                 aCellPos,
5982                 new ScFormulaCell(rDoc, aCellPos, aRes.maText, formula::FormulaGrammar::GRAM_API),
5983                 false);
5984         break;
5985         case ScInputStringType::Number:
5986             rFunc.SetValueCell(aCellPos, aRes.mfValue, false);
5987         break;
5988         case ScInputStringType::Text:
5989             rFunc.SetStringOrEditCell(aCellPos, aRes.maText, false);
5990         break;
5991         default:
5992             SetString_Impl(rText, false, false); // probably empty string
5993     }
5994 }
5995 
5996 //  XText
5997 
5998 uno::Reference<text::XTextCursor> SAL_CALL ScCellObj::createTextCursor()
5999 {
6000     SolarMutexGuard aGuard;
6001     return new ScCellTextCursor( *this );
6002 }
6003 
6004 uno::Reference<text::XTextCursor> SAL_CALL ScCellObj::createTextCursorByRange(
6005                                     const uno::Reference<text::XTextRange>& aTextPosition )
6006 {
6007     SolarMutexGuard aGuard;
6008     SvxUnoTextCursor* pCursor = new ScCellTextCursor( *this );
6009     uno::Reference<text::XTextCursor> xCursor(pCursor);
6010 
6011     SvxUnoTextRangeBase* pRange = comphelper::getUnoTunnelImplementation<SvxUnoTextRangeBase>( aTextPosition );
6012     if(pRange)
6013         pCursor->SetSelection( pRange->GetSelection() );
6014     else
6015     {
6016         ScCellTextCursor* pOther = comphelper::getUnoTunnelImplementation<ScCellTextCursor>( aTextPosition );
6017         if(!pOther)
6018             throw uno::RuntimeException();
6019 
6020         pCursor->SetSelection( pOther->GetSelection() );
6021 
6022     }
6023 
6024     return xCursor;
6025 }
6026 
6027 OUString SAL_CALL ScCellObj::getString()
6028 {
6029     SolarMutexGuard aGuard;
6030     return GetOutputString_Impl();
6031 }
6032 
6033 void SAL_CALL ScCellObj::setString( const OUString& aText )
6034 {
6035     SolarMutexGuard aGuard;
6036     SetString_Impl(aText, false, false);  // always text
6037 
6038     // don't create pUnoText here if not there
6039     if (mxUnoText.is())
6040         mxUnoText->SetSelection(ESelection( 0,0, 0,aText.getLength() ));
6041 }
6042 
6043 void SAL_CALL ScCellObj::insertString( const uno::Reference<text::XTextRange>& xRange,
6044                                         const OUString& aString, sal_Bool bAbsorb )
6045 {
6046     // special handling for ScCellTextCursor is no longer needed,
6047     // SvxUnoText::insertString checks for SvxUnoTextRangeBase instead of SvxUnoTextRange
6048 
6049     SolarMutexGuard aGuard;
6050     GetUnoText().insertString(xRange, aString, bAbsorb);
6051 }
6052 
6053 void SAL_CALL ScCellObj::insertControlCharacter( const uno::Reference<text::XTextRange>& xRange,
6054                                                 sal_Int16 nControlCharacter, sal_Bool bAbsorb )
6055 {
6056     SolarMutexGuard aGuard;
6057     GetUnoText().insertControlCharacter(xRange, nControlCharacter, bAbsorb);
6058 }
6059 
6060 void SAL_CALL ScCellObj::insertTextContent( const uno::Reference<text::XTextRange >& xRange,
6061                                                 const uno::Reference<text::XTextContent >& xContent,
6062                                                 sal_Bool bAbsorb )
6063 {
6064     SolarMutexGuard aGuard;
6065     ScDocShell* pDocSh = GetDocShell();
6066     if ( pDocSh && xContent.is() )
6067     {
6068         ScEditFieldObj* pCellField = comphelper::getUnoTunnelImplementation<ScEditFieldObj>(xContent);
6069         SvxUnoTextRangeBase* pTextRange = comphelper::getUnoTunnelImplementation<ScCellTextCursor>( xRange );
6070 
6071         if ( pCellField && !pCellField->IsInserted() && pTextRange )
6072         {
6073             SvxEditSource* pEditSource = pTextRange->GetEditSource();
6074             ESelection aSelection(pTextRange->GetSelection());
6075 
6076             if (!bAbsorb)
6077             {
6078                 //  do not replace -> append
6079                 aSelection.Adjust();
6080                 aSelection.nStartPara = aSelection.nEndPara;
6081                 aSelection.nStartPos  = aSelection.nEndPos;
6082             }
6083 
6084             if (pCellField->GetFieldType() == text::textfield::Type::TABLE)
6085                 pCellField->setPropertyValue(SC_UNONAME_TABLEPOS, uno::makeAny<sal_Int32>(aCellPos.Tab()));
6086 
6087             SvxFieldItem aItem = pCellField->CreateFieldItem();
6088             SvxTextForwarder* pForwarder = pEditSource->GetTextForwarder();
6089             pForwarder->QuickInsertField( aItem, aSelection );
6090             pEditSource->UpdateData();
6091 
6092             //  new selection: a digit
6093             aSelection.Adjust();
6094             aSelection.nEndPara = aSelection.nStartPara;
6095             aSelection.nEndPos = aSelection.nStartPos + 1;
6096             uno::Reference<text::XTextRange> xParent(this);
6097             pCellField->InitDoc(
6098                 xParent, std::make_unique<ScCellEditSource>(pDocSh, aCellPos), aSelection);
6099 
6100             //  for bAbsorb=FALSE, the new selection must be behind the inserted content
6101             //  (the xml filter relies on this)
6102             if (!bAbsorb)
6103                 aSelection.nStartPos = aSelection.nEndPos;
6104 
6105             pTextRange->SetSelection( aSelection );
6106 
6107             return;
6108         }
6109     }
6110     GetUnoText().insertTextContent(xRange, xContent, bAbsorb);
6111 }
6112 
6113 void SAL_CALL ScCellObj::removeTextContent( const uno::Reference<text::XTextContent>& xContent )
6114 {
6115     SolarMutexGuard aGuard;
6116     if ( xContent.is() )
6117     {
6118         ScEditFieldObj* pCellField = comphelper::getUnoTunnelImplementation<ScEditFieldObj>(xContent);
6119         if ( pCellField && pCellField->IsInserted() )
6120         {
6121             //! Check if field is in this cell
6122             pCellField->DeleteField();
6123             return;
6124         }
6125     }
6126     GetUnoText().removeTextContent(xContent);
6127 }
6128 
6129 uno::Reference<text::XText> SAL_CALL ScCellObj::getText()
6130 {
6131     return this;
6132 }
6133 
6134 uno::Reference<text::XTextRange> SAL_CALL ScCellObj::getStart()
6135 {
6136     SolarMutexGuard aGuard;
6137     return GetUnoText().getStart();
6138 }
6139 
6140 uno::Reference<text::XTextRange> SAL_CALL ScCellObj::getEnd()
6141 {
6142     SolarMutexGuard aGuard;
6143     return GetUnoText().getEnd();
6144 }
6145 
6146 uno::Reference<container::XEnumeration> SAL_CALL ScCellObj::createEnumeration()
6147 {
6148     SolarMutexGuard aGuard;
6149     return GetUnoText().createEnumeration();
6150 }
6151 
6152 uno::Type SAL_CALL ScCellObj::getElementType()
6153 {
6154     SolarMutexGuard aGuard;
6155     return GetUnoText().getElementType();
6156 }
6157 
6158 sal_Bool SAL_CALL ScCellObj::hasElements()
6159 {
6160     SolarMutexGuard aGuard;
6161     return GetUnoText().hasElements();
6162 }
6163 
6164 //  XCell
6165 
6166 OUString SAL_CALL ScCellObj::getFormula()
6167 {
6168     SolarMutexGuard aGuard;
6169     return GetInputString_Impl( true /* English */ );
6170 }
6171 
6172 void SAL_CALL ScCellObj::setFormula( const OUString& aFormula )
6173 {
6174     SolarMutexGuard aGuard;
6175     SetString_Impl(aFormula, true, true); // Interpret as English
6176 }
6177 
6178 double SAL_CALL ScCellObj::getValue()
6179 {
6180     SolarMutexGuard aGuard;
6181     return GetValue_Impl();
6182 }
6183 
6184 void SAL_CALL ScCellObj::setValue( double nValue )
6185 {
6186     SolarMutexGuard aGuard;
6187     SetValue_Impl(nValue);
6188 }
6189 
6190 void SAL_CALL ScCellObj::setFormulaString( const OUString& aFormula)
6191 {
6192     SolarMutexGuard aGuard;
6193     ScDocShell *pDocSh = GetDocShell();
6194     if( pDocSh )
6195     {
6196         ScFormulaCell* pCell = new ScFormulaCell( pDocSh->GetDocument(), aCellPos );
6197         pCell->SetHybridFormula( aFormula, formula::FormulaGrammar::GRAM_NATIVE );
6198         pDocSh->GetDocFunc().SetFormulaCell(aCellPos, pCell, false);
6199     }
6200 }
6201 void SAL_CALL ScCellObj::setFormulaResult( double nValue )
6202 {
6203     SolarMutexGuard aGuard;
6204     ScDocShell* pDocSh = GetDocShell();
6205     if (pDocSh)
6206     {
6207         ScRefCellValue aCell(pDocSh->GetDocument(), aCellPos);
6208         if (aCell.meType == CELLTYPE_FORMULA)
6209         {
6210             ScFormulaCell* pCell = aCell.mpFormula;
6211             pCell->SetHybridDouble( nValue );
6212             pCell->ResetDirty();
6213             pCell->SetChanged(false);
6214         }
6215     }
6216 }
6217 
6218 table::CellContentType SAL_CALL ScCellObj::getType()
6219 {
6220     SolarMutexGuard aGuard;
6221     table::CellContentType eRet = table::CellContentType_EMPTY;
6222     ScDocShell* pDocSh = GetDocShell();
6223     if (pDocSh)
6224     {
6225         CellType eCalcType = pDocSh->GetDocument().GetCellType( aCellPos );
6226         switch (eCalcType)
6227         {
6228             case CELLTYPE_VALUE:
6229                 eRet = table::CellContentType_VALUE;
6230                 break;
6231             case CELLTYPE_STRING:
6232             case CELLTYPE_EDIT:
6233                 eRet = table::CellContentType_TEXT;
6234                 break;
6235             case CELLTYPE_FORMULA:
6236                 eRet = table::CellContentType_FORMULA;
6237                 break;
6238             default:
6239                 eRet = table::CellContentType_EMPTY;
6240         }
6241     }
6242     else
6243     {
6244         OSL_FAIL("no DocShell");     //! Exception or so?
6245     }
6246 
6247     return eRet;
6248 }
6249 
6250 sal_Int32 ScCellObj::GetResultType_Impl() const
6251 {
6252     SolarMutexGuard aGuard;
6253     sal_Int32 eRet = sheet::FormulaResult::STRING;
6254     ScDocShell* pDocSh = GetDocShell();
6255     if (pDocSh)
6256     {
6257         if (pDocSh->GetDocument().GetCellType(aCellPos) == CELLTYPE_FORMULA)
6258         {
6259             ScFormulaCell* pFCell = pDocSh->GetDocument().GetFormulaCell(aCellPos);
6260             if (!pFCell)
6261             {
6262                 // should throw instead of default string?
6263             }
6264             else if (pFCell->GetErrCode() != FormulaError::NONE )
6265             {
6266                 eRet = sheet::FormulaResult::ERROR;
6267             }
6268             else if (pFCell->IsValue())
6269             {
6270                 eRet = sheet::FormulaResult::VALUE;
6271             }
6272             else
6273             {
6274                 eRet = sheet::FormulaResult::STRING;
6275             }
6276         }
6277     }
6278     else
6279     {
6280         OSL_FAIL("no DocShell");
6281     }
6282 
6283     return eRet;
6284 }
6285 
6286 table::CellContentType ScCellObj::GetContentType_Impl()
6287 {
6288     ScDocShell* pDocSh = GetDocShell();
6289     if ( pDocSh )
6290     {
6291         ScRefCellValue aCell(pDocSh->GetDocument(), aCellPos);
6292         if (aCell.meType == CELLTYPE_FORMULA)
6293         {
6294             bool bValue = aCell.mpFormula->IsValue();
6295             return bValue ? table::CellContentType_VALUE : table::CellContentType_TEXT;
6296         }
6297     }
6298     return getType();
6299 }
6300 
6301 sal_Int32 SAL_CALL ScCellObj::getError()
6302 {
6303     SolarMutexGuard aGuard;
6304     ScDocShell* pDocSh = GetDocShell();
6305     if (!pDocSh)
6306     {
6307         OSL_FAIL("no DocShell");     //! Exception or so?
6308         return 0;
6309     }
6310 
6311     FormulaError nError = FormulaError::NONE;
6312     ScRefCellValue aCell(pDocSh->GetDocument(), aCellPos);
6313     if (aCell.meType == CELLTYPE_FORMULA)
6314         nError = aCell.mpFormula->GetErrCode();
6315 
6316     return static_cast<sal_Int32>(nError);
6317 }
6318 
6319 // XFormulaTokens
6320 
6321 uno::Sequence<sheet::FormulaToken> SAL_CALL ScCellObj::getTokens()
6322 {
6323     SolarMutexGuard aGuard;
6324     uno::Sequence<sheet::FormulaToken> aSequence;
6325     ScDocShell* pDocSh = GetDocShell();
6326     if (!pDocSh)
6327         return aSequence;
6328 
6329     ScDocument& rDoc = pDocSh->GetDocument();
6330     ScRefCellValue aCell(rDoc, aCellPos);
6331     if (aCell.meType == CELLTYPE_FORMULA)
6332     {
6333         ScTokenArray* pTokenArray = aCell.mpFormula->GetCode();
6334         if (pTokenArray)
6335             ScTokenConversion::ConvertToTokenSequence(rDoc, aSequence, *pTokenArray);
6336     }
6337     return aSequence;
6338 }
6339 
6340 void SAL_CALL ScCellObj::setTokens( const uno::Sequence<sheet::FormulaToken>& rTokens )
6341 {
6342     SolarMutexGuard aGuard;
6343     ScDocShell* pDocSh = GetDocShell();
6344     if ( pDocSh )
6345     {
6346         ScDocument& rDoc = pDocSh->GetDocument();
6347         ScTokenArray aTokenArray(rDoc);
6348         (void)ScTokenConversion::ConvertToTokenArray( rDoc, aTokenArray, rTokens );
6349 
6350         ScFormulaCell* pNewCell = new ScFormulaCell(rDoc, aCellPos, aTokenArray);
6351         (void)pDocSh->GetDocFunc().SetFormulaCell(aCellPos, pNewCell, false);
6352     }
6353 }
6354 
6355 // XCellAddressable
6356 
6357 table::CellAddress SAL_CALL ScCellObj::getCellAddress()
6358 {
6359     SolarMutexGuard aGuard;
6360     table::CellAddress aAdr;
6361     aAdr.Sheet  = aCellPos.Tab();
6362     aAdr.Column = aCellPos.Col();
6363     aAdr.Row    = aCellPos.Row();
6364     return aAdr;
6365 }
6366 
6367 // XSheetAnnotationAnchor
6368 
6369 uno::Reference<sheet::XSheetAnnotation> SAL_CALL ScCellObj::getAnnotation()
6370 {
6371     SolarMutexGuard aGuard;
6372     ScDocShell* pDocSh = GetDocShell();
6373     if ( pDocSh )
6374         return new ScAnnotationObj( pDocSh, aCellPos );
6375 
6376     OSL_FAIL("getAnnotation without DocShell");
6377     return nullptr;
6378 }
6379 
6380 // XFieldTypesSupplier
6381 
6382 uno::Reference<container::XEnumerationAccess> SAL_CALL ScCellObj::getTextFields()
6383 {
6384     SolarMutexGuard aGuard;
6385     ScDocShell* pDocSh = GetDocShell();
6386     if ( pDocSh )
6387     {
6388         uno::Reference<text::XTextRange> xContent(this);
6389         return new ScCellFieldsObj(xContent, pDocSh, aCellPos);
6390     }
6391 
6392     return nullptr;
6393 }
6394 
6395 uno::Reference<container::XNameAccess> SAL_CALL ScCellObj::getTextFieldMasters()
6396 {
6397     //  there is no such thing in Calc (?)
6398     return nullptr;
6399 }
6400 
6401 // XPropertySet extended for Cell-Properties
6402 
6403 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScCellObj::getPropertySetInfo()
6404 {
6405     SolarMutexGuard aGuard;
6406     static uno::Reference<beans::XPropertySetInfo> aRef(
6407         new SfxItemPropertySetInfo( pCellPropSet->getPropertyMap() ));
6408     return aRef;
6409 }
6410 
6411 void ScCellObj::SetOnePropertyValue( const SfxItemPropertySimpleEntry* pEntry, const uno::Any& aValue )
6412 {
6413     if ( !pEntry )
6414         return;
6415 
6416     if ( pEntry->nWID == SC_WID_UNO_FORMLOC )
6417     {
6418         OUString aStrVal;
6419         aValue >>= aStrVal;
6420         SetString_Impl(aStrVal, true, false);   // interpret locally
6421     }
6422     else if ( pEntry->nWID == SC_WID_UNO_FORMRT || pEntry->nWID == SC_WID_UNO_FORMRT2
6423               || pEntry->nWID == SC_WID_UNO_CELLCONTENTTYPE )
6424     {
6425         //  Read-Only
6426         //! Exception or so...
6427     }
6428     else
6429         ScCellRangeObj::SetOnePropertyValue( pEntry, aValue );
6430 }
6431 
6432 void ScCellObj::GetOnePropertyValue( const SfxItemPropertySimpleEntry* pEntry, uno::Any& rAny )
6433 {
6434     if ( !pEntry )
6435         return;
6436 
6437     if ( pEntry->nWID == SC_WID_UNO_FORMLOC )
6438     {
6439         // sal_False = local
6440         rAny <<= GetInputString_Impl(false);
6441     }
6442     else if ( pEntry->nWID == SC_WID_UNO_FORMRT2 )
6443     {
6444         sal_Int32 eType = GetResultType_Impl();
6445         rAny <<= eType;
6446     }
6447     else if ( pEntry->nWID == SC_WID_UNO_CELLCONTENTTYPE || pEntry->nWID == SC_WID_UNO_FORMRT )
6448     {
6449         table::CellContentType eType = GetContentType_Impl();
6450         rAny <<= eType;
6451     }
6452     else
6453         ScCellRangeObj::GetOnePropertyValue(pEntry, rAny);
6454 }
6455 
6456 const SfxItemPropertyMap& ScCellObj::GetItemPropertyMap()
6457 {
6458     return pCellPropSet->getPropertyMap();
6459 }
6460 
6461 // XServiceInfo
6462 
6463 OUString SAL_CALL ScCellObj::getImplementationName()
6464 {
6465     return "ScCellObj";
6466 }
6467 
6468 sal_Bool SAL_CALL ScCellObj::supportsService( const OUString& rServiceName )
6469 {
6470     return cppu::supportsService(this, rServiceName);
6471 }
6472 
6473 uno::Sequence<OUString> SAL_CALL ScCellObj::getSupportedServiceNames()
6474 {
6475     return {SCSHEETCELL_SERVICE,
6476             SCCELL_SERVICE,
6477             SCCELLPROPERTIES_SERVICE,
6478             SCCHARPROPERTIES_SERVICE,
6479             SCPARAPROPERTIES_SERVICE,
6480             SCSHEETCELLRANGE_SERVICE,
6481             SCCELLRANGE_SERVICE};
6482 }
6483 
6484 // XActionLockable
6485 
6486 sal_Bool SAL_CALL ScCellObj::isActionLocked()
6487 {
6488     SolarMutexGuard aGuard;
6489     return nActionLockCount != 0;
6490 }
6491 
6492 void SAL_CALL ScCellObj::addActionLock()
6493 {
6494     SolarMutexGuard aGuard;
6495     if (!nActionLockCount)
6496     {
6497         if (mxUnoText.is())
6498         {
6499             ScCellEditSource* pEditSource =
6500                 static_cast<ScCellEditSource*> (mxUnoText->GetEditSource());
6501             if (pEditSource)
6502                 pEditSource->SetDoUpdateData(false);
6503         }
6504     }
6505     nActionLockCount++;
6506 }
6507 
6508 void SAL_CALL ScCellObj::removeActionLock()
6509 {
6510     SolarMutexGuard aGuard;
6511     if (nActionLockCount <= 0)
6512         return;
6513 
6514     nActionLockCount--;
6515     if (nActionLockCount)
6516         return;
6517 
6518     if (mxUnoText.is())
6519     {
6520         ScCellEditSource* pEditSource =
6521             static_cast<ScCellEditSource*> (mxUnoText->GetEditSource());
6522         if (pEditSource)
6523         {
6524             pEditSource->SetDoUpdateData(true);
6525             if (pEditSource->IsDirty())
6526                 pEditSource->UpdateData();
6527         }
6528     }
6529 }
6530 
6531 void SAL_CALL ScCellObj::setActionLocks( sal_Int16 nLock )
6532 {
6533     SolarMutexGuard aGuard;
6534     if (mxUnoText.is())
6535     {
6536         ScCellEditSource* pEditSource =
6537             static_cast<ScCellEditSource*> (mxUnoText->GetEditSource());
6538         if (pEditSource)
6539         {
6540             pEditSource->SetDoUpdateData(nLock == 0);
6541             if ((nActionLockCount > 0) && (nLock == 0) && pEditSource->IsDirty())
6542                 pEditSource->UpdateData();
6543         }
6544     }
6545     nActionLockCount = nLock;
6546 }
6547 
6548 sal_Int16 SAL_CALL ScCellObj::resetActionLocks()
6549 {
6550     SolarMutexGuard aGuard;
6551     sal_uInt16 nRet(nActionLockCount);
6552     if (mxUnoText.is())
6553     {
6554         ScCellEditSource* pEditSource =
6555             static_cast<ScCellEditSource*> (mxUnoText->GetEditSource());
6556         if (pEditSource)
6557         {
6558             pEditSource->SetDoUpdateData(true);
6559             if (pEditSource->IsDirty())
6560                 pEditSource->UpdateData();
6561         }
6562     }
6563     nActionLockCount = 0;
6564     return nRet;
6565 }
6566 
6567 static ScRange MaxDocRange(ScDocShell* pDocSh, SCTAB nTab)
6568 {
6569     const SCCOL nMaxcol = pDocSh ? pDocSh->GetDocument().MaxCol() : MAXCOL;
6570     const SCROW nMaxRow = pDocSh ? pDocSh->GetDocument().MaxRow() : MAXROW;
6571     return ScRange(0, 0, nTab, nMaxcol, nMaxRow, nTab);
6572 }
6573 
6574 ScTableSheetObj::ScTableSheetObj( ScDocShell* pDocSh, SCTAB nTab ) :
6575     ScCellRangeObj( pDocSh, MaxDocRange(pDocSh, nTab) ),
6576     pSheetPropSet(lcl_GetSheetPropertySet())
6577 {
6578 }
6579 
6580 ScTableSheetObj::~ScTableSheetObj()
6581 {
6582 }
6583 
6584 void ScTableSheetObj::InitInsertSheet(ScDocShell* pDocSh, SCTAB nTab)
6585 {
6586     ScDocument& rDoc = pDocSh->GetDocument();
6587     InitInsertRange( pDocSh, ScRange(0,0,nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab) );
6588 }
6589 
6590 uno::Any SAL_CALL ScTableSheetObj::queryInterface( const uno::Type& rType )
6591 {
6592     SC_QUERYINTERFACE( sheet::XSpreadsheet )
6593     SC_QUERYINTERFACE( container::XNamed )
6594     SC_QUERYINTERFACE( sheet::XSheetPageBreak )
6595     SC_QUERYINTERFACE( sheet::XCellRangeMovement )
6596     SC_QUERYINTERFACE( table::XTableChartsSupplier )
6597     SC_QUERYINTERFACE( sheet::XDataPilotTablesSupplier )
6598     SC_QUERYINTERFACE( sheet::XScenariosSupplier )
6599     SC_QUERYINTERFACE( sheet::XSheetAnnotationsSupplier )
6600     SC_QUERYINTERFACE( drawing::XDrawPageSupplier )
6601     SC_QUERYINTERFACE( sheet::XPrintAreas )
6602     SC_QUERYINTERFACE( sheet::XSheetAuditing )
6603     SC_QUERYINTERFACE( sheet::XSheetOutline )
6604     SC_QUERYINTERFACE( util::XProtectable )
6605     SC_QUERYINTERFACE( sheet::XScenario )
6606     SC_QUERYINTERFACE( sheet::XScenarioEnhanced )
6607     SC_QUERYINTERFACE( sheet::XSheetLinkable )
6608     SC_QUERYINTERFACE( sheet::XExternalSheetName )
6609     SC_QUERYINTERFACE( document::XEventsSupplier )
6610     SC_QUERYINTERFACE( table::XTablePivotChartsSupplier )
6611 
6612     return ScCellRangeObj::queryInterface( rType );
6613 }
6614 
6615 void SAL_CALL ScTableSheetObj::acquire() throw()
6616 {
6617     ScCellRangeObj::acquire();
6618 }
6619 
6620 void SAL_CALL ScTableSheetObj::release() throw()
6621 {
6622     ScCellRangeObj::release();
6623 }
6624 
6625 uno::Sequence<uno::Type> SAL_CALL ScTableSheetObj::getTypes()
6626 {
6627     static const uno::Sequence<uno::Type> aTypes = comphelper::concatSequences(
6628         ScCellRangeObj::getTypes(),
6629         uno::Sequence<uno::Type>
6630         {
6631             cppu::UnoType<sheet::XSpreadsheet>::get(),
6632             cppu::UnoType<container::XNamed>::get(),
6633             cppu::UnoType<sheet::XSheetPageBreak>::get(),
6634             cppu::UnoType<sheet::XCellRangeMovement>::get(),
6635             cppu::UnoType<table::XTableChartsSupplier>::get(),
6636             cppu::UnoType<sheet::XDataPilotTablesSupplier>::get(),
6637             cppu::UnoType<sheet::XScenariosSupplier>::get(),
6638             cppu::UnoType<sheet::XSheetAnnotationsSupplier>::get(),
6639             cppu::UnoType<drawing::XDrawPageSupplier>::get(),
6640             cppu::UnoType<sheet::XPrintAreas>::get(),
6641             cppu::UnoType<sheet::XSheetAuditing>::get(),
6642             cppu::UnoType<sheet::XSheetOutline>::get(),
6643             cppu::UnoType<util::XProtectable>::get(),
6644             cppu::UnoType<sheet::XScenario>::get(),
6645             cppu::UnoType<sheet::XScenarioEnhanced>::get(),
6646             cppu::UnoType<sheet::XSheetLinkable>::get(),
6647             cppu::UnoType<sheet::XExternalSheetName>::get(),
6648             cppu::UnoType<document::XEventsSupplier>::get(),
6649             cppu::UnoType<table::XTablePivotChartsSupplier>::get()
6650         } );
6651     return aTypes;
6652 }
6653 
6654 uno::Sequence<sal_Int8> SAL_CALL ScTableSheetObj::getImplementationId()
6655 {
6656     return css::uno::Sequence<sal_Int8>();
6657 }
6658 
6659 //  Helper functions
6660 
6661 SCTAB ScTableSheetObj::GetTab_Impl() const
6662 {
6663     const ScRangeList& rRanges = GetRangeList();
6664     OSL_ENSURE(rRanges.size() == 1, "What ranges ?!?!");
6665     if ( !rRanges.empty() )
6666     {
6667         return rRanges[ 0 ].aStart.Tab();
6668     }
6669     return 0;
6670 }
6671 
6672 // former XSheet
6673 
6674 uno::Reference<table::XTableCharts> SAL_CALL ScTableSheetObj::getCharts()
6675 {
6676     SolarMutexGuard aGuard;
6677     ScDocShell* pDocSh = GetDocShell();
6678     if ( pDocSh )
6679         return new ScChartsObj( pDocSh, GetTab_Impl() );
6680 
6681     OSL_FAIL("no document");
6682     return nullptr;
6683 }
6684 
6685 uno::Reference<table::XTablePivotCharts> SAL_CALL ScTableSheetObj::getPivotCharts()
6686 {
6687     SolarMutexGuard aGuard;
6688     ScDocShell* pDocSh = GetDocShell();
6689     if (pDocSh)
6690         return new sc::TablePivotCharts(pDocSh, GetTab_Impl());
6691 
6692     OSL_FAIL("no document");
6693     return nullptr;
6694 }
6695 
6696 uno::Reference<sheet::XDataPilotTables> SAL_CALL ScTableSheetObj::getDataPilotTables()
6697 {
6698     SolarMutexGuard aGuard;
6699     ScDocShell* pDocSh = GetDocShell();
6700     if ( pDocSh )
6701         return new ScDataPilotTablesObj( pDocSh, GetTab_Impl() );
6702 
6703     OSL_FAIL("no document");
6704     return nullptr;
6705 }
6706 
6707 uno::Reference<sheet::XScenarios> SAL_CALL ScTableSheetObj::getScenarios()
6708 {
6709     SolarMutexGuard aGuard;
6710     ScDocShell* pDocSh = GetDocShell();
6711 
6712     if ( pDocSh )
6713         return new ScScenariosObj( pDocSh, GetTab_Impl() );
6714 
6715     OSL_FAIL("no document");
6716     return nullptr;
6717 }
6718 
6719 uno::Reference<sheet::XSheetAnnotations> SAL_CALL ScTableSheetObj::getAnnotations()
6720 {
6721     SolarMutexGuard aGuard;
6722     ScDocShell* pDocSh = GetDocShell();
6723 
6724     if ( pDocSh )
6725         return new ScAnnotationsObj( pDocSh, GetTab_Impl() );
6726 
6727     OSL_FAIL("no document");
6728     return nullptr;
6729 }
6730 
6731 uno::Reference<table::XCellRange> SAL_CALL ScTableSheetObj::getCellRangeByName(
6732                         const OUString& rRange )
6733 {
6734     SolarMutexGuard aGuard;
6735     return ScCellRangeObj::getCellRangeByName( rRange );
6736 }
6737 
6738 uno::Reference<sheet::XSheetCellCursor> SAL_CALL ScTableSheetObj::createCursor()
6739 {
6740     SolarMutexGuard aGuard;
6741     ScDocShell* pDocSh = GetDocShell();
6742     if ( pDocSh )
6743     {
6744         //! single cell or whole table??????
6745         const ScDocument& rDoc = pDocSh->GetDocument();
6746         SCTAB nTab = GetTab_Impl();
6747         return new ScCellCursorObj( pDocSh, ScRange( 0,0,nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab ) );
6748     }
6749     return nullptr;
6750 }
6751 
6752 uno::Reference<sheet::XSheetCellCursor> SAL_CALL ScTableSheetObj::createCursorByRange(
6753                         const uno::Reference<sheet::XSheetCellRange>& xCellRange )
6754 {
6755     SolarMutexGuard aGuard;
6756     ScDocShell* pDocSh = GetDocShell();
6757     if ( pDocSh && xCellRange.is() )
6758     {
6759         ScCellRangesBase* pRangesImp = comphelper::getUnoTunnelImplementation<ScCellRangesBase>( xCellRange );
6760         if (pRangesImp)
6761         {
6762             const ScRangeList& rRanges = pRangesImp->GetRangeList();
6763             OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" );
6764             return new ScCellCursorObj( pDocSh, rRanges[ 0 ] );
6765         }
6766     }
6767     return nullptr;
6768 }
6769 
6770 // XSheetCellRange
6771 
6772 uno::Reference<sheet::XSpreadsheet> SAL_CALL ScTableSheetObj::getSpreadsheet()
6773 {
6774     return this;        //!???
6775 }
6776 
6777 // XCellRange
6778 
6779 uno::Reference<table::XCell> SAL_CALL ScTableSheetObj::getCellByPosition(
6780                                         sal_Int32 nColumn, sal_Int32 nRow )
6781 {
6782     SolarMutexGuard aGuard;
6783     return ScCellRangeObj::GetCellByPosition_Impl(nColumn, nRow);
6784 }
6785 
6786 uno::Reference<table::XCellRange> SAL_CALL ScTableSheetObj::getCellRangeByPosition(
6787                 sal_Int32 nLeft, sal_Int32 nTop, sal_Int32 nRight, sal_Int32 nBottom )
6788 {
6789     SolarMutexGuard aGuard;
6790     return ScCellRangeObj::getCellRangeByPosition(nLeft,nTop,nRight,nBottom);
6791 }
6792 
6793 uno::Sequence<sheet::TablePageBreakData> SAL_CALL ScTableSheetObj::getColumnPageBreaks()
6794 {
6795     SolarMutexGuard aGuard;
6796     ScDocShell* pDocSh = GetDocShell();
6797     if ( pDocSh )
6798     {
6799         ScDocument& rDoc = pDocSh->GetDocument();
6800         SCTAB nTab = GetTab_Impl();
6801 
6802         Size aSize(rDoc.GetPageSize( nTab ));
6803         if (aSize.Width() && aSize.Height())        // effective size already set?
6804             rDoc.UpdatePageBreaks( nTab );
6805         else
6806         {
6807             //  update breaks like in ScDocShell::PageStyleModified:
6808             ScPrintFunc aPrintFunc( pDocSh, pDocSh->GetPrinter(), nTab );
6809             aPrintFunc.UpdatePages();
6810         }
6811 
6812         SCCOL nCount = 0;
6813         for (SCCOL nCol : rDoc.GetColumnsRange(nTab, 0, rDoc.MaxCol()))
6814             if (rDoc.HasColBreak(nCol, nTab) != ScBreakType::NONE)
6815                 ++nCount;
6816 
6817         sheet::TablePageBreakData aData;
6818         uno::Sequence<sheet::TablePageBreakData> aSeq(nCount);
6819         sheet::TablePageBreakData* pAry = aSeq.getArray();
6820         sal_uInt16 nPos = 0;
6821         for (SCCOL nCol : rDoc.GetColumnsRange(nTab, 0, rDoc.MaxCol()))
6822         {
6823             ScBreakType nBreak = rDoc.HasColBreak(nCol, nTab);
6824             if (nBreak != ScBreakType::NONE)
6825             {
6826                 aData.Position    = nCol;
6827                 aData.ManualBreak = bool(nBreak & ScBreakType::Manual);
6828                 pAry[nPos] = aData;
6829                 ++nPos;
6830             }
6831         }
6832         return aSeq;
6833     }
6834     return uno::Sequence<sheet::TablePageBreakData>(0);
6835 }
6836 
6837 uno::Sequence<sheet::TablePageBreakData> SAL_CALL ScTableSheetObj::getRowPageBreaks()
6838 {
6839     SolarMutexGuard aGuard;
6840     ScDocShell* pDocSh = GetDocShell();
6841     if ( pDocSh )
6842     {
6843         ScDocument& rDoc = pDocSh->GetDocument();
6844         SCTAB nTab = GetTab_Impl();
6845 
6846         Size aSize(rDoc.GetPageSize( nTab ));
6847         if (aSize.Width() && aSize.Height())        // effective size already set?
6848             rDoc.UpdatePageBreaks( nTab );
6849         else
6850         {
6851             //  update breaks like in ScDocShell::PageStyleModified:
6852             ScPrintFunc aPrintFunc( pDocSh, pDocSh->GetPrinter(), nTab );
6853             aPrintFunc.UpdatePages();
6854         }
6855         return rDoc.GetRowBreakData(nTab);
6856     }
6857     return uno::Sequence<sheet::TablePageBreakData>(0);
6858 }
6859 
6860 void SAL_CALL ScTableSheetObj::removeAllManualPageBreaks()
6861 {
6862     SolarMutexGuard aGuard;
6863     ScDocShell* pDocSh = GetDocShell();
6864     if ( !pDocSh )
6865         return;
6866 
6867     //! DocFunc function, also for ScViewFunc::RemoveManualBreaks
6868 
6869     ScDocument& rDoc = pDocSh->GetDocument();
6870     bool bUndo (rDoc.IsUndoEnabled());
6871     SCTAB nTab = GetTab_Impl();
6872 
6873     if (bUndo)
6874     {
6875         ScDocumentUniquePtr pUndoDoc(new ScDocument( SCDOCMODE_UNDO ));
6876         pUndoDoc->InitUndo( rDoc, nTab, nTab, true, true );
6877         rDoc.CopyToDocument(0,0,nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab, InsertDeleteFlags::NONE, false, *pUndoDoc);
6878         pDocSh->GetUndoManager()->AddUndoAction(
6879                                 std::make_unique<ScUndoRemoveBreaks>( pDocSh, nTab, std::move(pUndoDoc) ) );
6880     }
6881 
6882     rDoc.RemoveManualBreaks(nTab);
6883     rDoc.UpdatePageBreaks(nTab);
6884 
6885     //? UpdatePageBreakData( sal_True );
6886     pDocSh->SetDocumentModified();
6887     pDocSh->PostPaint(ScRange(0, 0, nTab, rDoc.MaxCol(), rDoc.MaxRow(), nTab), PaintPartFlags::Grid);
6888 }
6889 
6890 // XNamed
6891 
6892 OUString SAL_CALL ScTableSheetObj::getName()
6893 {
6894     SolarMutexGuard aGuard;
6895     OUString aName;
6896     ScDocShell* pDocSh = GetDocShell();
6897     if ( pDocSh )
6898         pDocSh->GetDocument().GetName( GetTab_Impl(), aName );
6899     return aName;
6900 }
6901 
6902 void SAL_CALL ScTableSheetObj::setName( const OUString& aNewName )
6903 {
6904     SolarMutexGuard aGuard;
6905     ScDocShell* pDocSh = GetDocShell();
6906     if ( pDocSh )
6907     {
6908         pDocSh->GetDocFunc().RenameTable( GetTab_Impl(), aNewName, true, true );
6909     }
6910 }
6911 
6912 // XDrawPageSupplier
6913 
6914 uno::Reference<drawing::XDrawPage> SAL_CALL ScTableSheetObj::getDrawPage()
6915 {
6916     SolarMutexGuard aGuard;
6917     ScDocShell* pDocSh = GetDocShell();
6918     if ( pDocSh )
6919     {
6920         ScDrawLayer* pDrawLayer = pDocSh->MakeDrawLayer();
6921         OSL_ENSURE(pDrawLayer,"Cannot create Draw-Layer");
6922 
6923         SCTAB nTab = GetTab_Impl();
6924         SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
6925         OSL_ENSURE(pPage,"Draw-Page not found");
6926         if (pPage)
6927             return uno::Reference<drawing::XDrawPage> (pPage->getUnoPage(), uno::UNO_QUERY);
6928 
6929         //  The DrawPage object will register itself as a Listener at SdrModel
6930         //  and should receive all action from there
6931     }
6932     return nullptr;
6933 }
6934 
6935 // XCellMovement
6936 
6937 void SAL_CALL ScTableSheetObj::insertCells( const table::CellRangeAddress& rRangeAddress,
6938                                 sheet::CellInsertMode nMode )
6939 {
6940     SolarMutexGuard aGuard;
6941     ScDocShell* pDocSh = GetDocShell();
6942     if ( !pDocSh )
6943         return;
6944 
6945     bool bDo = true;
6946     InsCellCmd eCmd = INS_NONE;
6947     switch (nMode)
6948     {
6949         case sheet::CellInsertMode_NONE:    bDo = false;                break;
6950         case sheet::CellInsertMode_DOWN:    eCmd = INS_CELLSDOWN;       break;
6951         case sheet::CellInsertMode_RIGHT:   eCmd = INS_CELLSRIGHT;      break;
6952         case sheet::CellInsertMode_ROWS:    eCmd = INS_INSROWS_BEFORE;  break;
6953         case sheet::CellInsertMode_COLUMNS: eCmd = INS_INSCOLS_BEFORE;  break;
6954         default:
6955             OSL_FAIL("insertCells: wrong mode");
6956             bDo = false;
6957     }
6958 
6959     if (bDo)
6960     {
6961         OSL_ENSURE( rRangeAddress.Sheet == GetTab_Impl(), "wrong table in CellRangeAddress" );
6962         ScRange aScRange;
6963         ScUnoConversion::FillScRange( aScRange, rRangeAddress );
6964         (void)pDocSh->GetDocFunc().InsertCells( aScRange, nullptr, eCmd, true, true );
6965     }
6966 }
6967 
6968 void SAL_CALL ScTableSheetObj::removeRange( const table::CellRangeAddress& rRangeAddress,
6969                                 sheet::CellDeleteMode nMode )
6970 {
6971     SolarMutexGuard aGuard;
6972     ScDocShell* pDocSh = GetDocShell();
6973     if ( !pDocSh )
6974         return;
6975 
6976     bool bDo = true;
6977     DelCellCmd eCmd = DelCellCmd::NONE;
6978     switch (nMode)
6979     {
6980         case sheet::CellDeleteMode_NONE:     bDo = false;           break;
6981         case sheet::CellDeleteMode_UP:       eCmd = DelCellCmd::CellsUp;    break;
6982         case sheet::CellDeleteMode_LEFT:     eCmd = DelCellCmd::CellsLeft;  break;
6983         case sheet::CellDeleteMode_ROWS:     eCmd = DelCellCmd::Rows;    break;
6984         case sheet::CellDeleteMode_COLUMNS:  eCmd = DelCellCmd::Cols;    break;
6985         default:
6986             OSL_FAIL("deleteCells: wrong mode");
6987             bDo = false;
6988     }
6989 
6990     if (bDo)
6991     {
6992         OSL_ENSURE( rRangeAddress.Sheet == GetTab_Impl(), "wrong table in CellRangeAddress" );
6993         ScRange aScRange;
6994         ScUnoConversion::FillScRange( aScRange, rRangeAddress );
6995         (void)pDocSh->GetDocFunc().DeleteCells( aScRange, nullptr, eCmd, true );
6996     }
6997 }
6998 
6999 void SAL_CALL ScTableSheetObj::moveRange( const table::CellAddress& aDestination,
7000                                         const table::CellRangeAddress& aSource )
7001 {
7002     SolarMutexGuard aGuard;
7003     ScDocShell* pDocSh = GetDocShell();
7004     if ( pDocSh )
7005     {
7006         OSL_ENSURE( aSource.Sheet == GetTab_Impl(), "wrong table in CellRangeAddress" );
7007         ScRange aSourceRange;
7008         ScUnoConversion::FillScRange( aSourceRange, aSource );
7009         ScAddress aDestPos( static_cast<SCCOL>(aDestination.Column), static_cast<SCROW>(aDestination.Row), aDestination.Sheet );
7010         (void)pDocSh->GetDocFunc().MoveBlock( aSourceRange, aDestPos, true, true, true, true );
7011     }
7012 }
7013 
7014 void SAL_CALL ScTableSheetObj::copyRange( const table::CellAddress& aDestination,
7015                                         const table::CellRangeAddress& aSource )
7016 {
7017     SolarMutexGuard aGuard;
7018     ScDocShell* pDocSh = GetDocShell();
7019     if ( pDocSh )
7020     {
7021         OSL_ENSURE( aSource.Sheet == GetTab_Impl(), "wrong table in CellRangeAddress" );
7022         ScRange aSourceRange;
7023         ScUnoConversion::FillScRange( aSourceRange, aSource );
7024         ScAddress aDestPos( static_cast<SCCOL>(aDestination.Column), static_cast<SCROW>(aDestination.Row), aDestination.Sheet );
7025         (void)pDocSh->GetDocFunc().MoveBlock( aSourceRange, aDestPos, false, true, true, true );
7026     }
7027 }
7028 
7029 // XPrintAreas
7030 
7031 void ScTableSheetObj::PrintAreaUndo_Impl( std::unique_ptr<ScPrintRangeSaver> pOldRanges )
7032 {
7033     //  page break and undo
7034     ScDocShell* pDocSh = GetDocShell();
7035 
7036     if(!pDocSh)
7037         return;
7038 
7039     ScDocument& rDoc = pDocSh->GetDocument();
7040     const bool bUndo(rDoc.IsUndoEnabled());
7041     const SCTAB nTab(GetTab_Impl());
7042 
7043     if(bUndo)
7044     {
7045         pDocSh->GetUndoManager()->AddUndoAction(
7046             std::make_unique<ScUndoPrintRange>(
7047                 pDocSh,
7048                 nTab,
7049                 std::move(pOldRanges),
7050                 rDoc.CreatePrintRangeSaver())); // create new ranges
7051     }
7052 
7053     ScPrintFunc(pDocSh, pDocSh->GetPrinter(), nTab).UpdatePages();
7054     SfxBindings* pBindings = pDocSh->GetViewBindings();
7055 
7056     if(pBindings)
7057     {
7058         pBindings->Invalidate(SID_DELETE_PRINTAREA);
7059     }
7060 
7061     pDocSh->SetDocumentModified();
7062 }
7063 
7064 uno::Sequence<table::CellRangeAddress> SAL_CALL ScTableSheetObj::getPrintAreas()
7065 {
7066     SolarMutexGuard aGuard;
7067     ScDocShell* pDocSh = GetDocShell();
7068     if ( pDocSh )
7069     {
7070         ScDocument& rDoc = pDocSh->GetDocument();
7071         SCTAB nTab = GetTab_Impl();
7072         sal_uInt16 nCount = rDoc.GetPrintRangeCount( nTab );
7073 
7074         table::CellRangeAddress aRangeAddress;
7075         uno::Sequence<table::CellRangeAddress> aSeq(nCount);
7076         table::CellRangeAddress* pAry = aSeq.getArray();
7077         for (sal_uInt16 i=0; i<nCount; i++)
7078         {
7079             const ScRange* pRange = rDoc.GetPrintRange( nTab, i );
7080             OSL_ENSURE(pRange,"where is the printing area");
7081             if (pRange)
7082             {
7083                 ScUnoConversion::FillApiRange( aRangeAddress, *pRange );
7084                 aRangeAddress.Sheet = nTab; // core does not care about sheet index
7085                 pAry[i] = aRangeAddress;
7086             }
7087         }
7088         return aSeq;
7089     }
7090     return uno::Sequence<table::CellRangeAddress>();
7091 }
7092 
7093 void SAL_CALL ScTableSheetObj::setPrintAreas(
7094                     const uno::Sequence<table::CellRangeAddress>& aPrintAreas )
7095 {
7096     SolarMutexGuard aGuard;
7097     ScDocShell* pDocSh = GetDocShell();
7098     if ( !pDocSh )
7099         return;
7100 
7101     std::unique_ptr<ScPrintRangeSaver> pOldRanges;
7102     ScDocument& rDoc = pDocSh->GetDocument();
7103     SCTAB nTab = GetTab_Impl();
7104 
7105     if ( rDoc.IsUndoEnabled() )
7106         pOldRanges = rDoc.CreatePrintRangeSaver();
7107 
7108     sal_uInt16 nCount = static_cast<sal_uInt16>(aPrintAreas.getLength());
7109     rDoc.ClearPrintRanges( nTab );
7110     if (nCount)
7111     {
7112         ScRange aPrintRange;
7113         for (const table::CellRangeAddress& rPrintArea : aPrintAreas)
7114         {
7115             ScUnoConversion::FillScRange( aPrintRange, rPrintArea );
7116             rDoc.AddPrintRange( nTab, aPrintRange );
7117         }
7118     }
7119 
7120     if ( rDoc.IsUndoEnabled() )
7121         PrintAreaUndo_Impl( std::move(pOldRanges) );   // Undo, Page Breaks, Modified etc.
7122 }
7123 
7124 sal_Bool SAL_CALL ScTableSheetObj::getPrintTitleColumns()
7125 {
7126     SolarMutexGuard aGuard;
7127     ScDocShell* pDocSh = GetDocShell();
7128     if ( pDocSh )
7129     {
7130         ScDocument& rDoc = pDocSh->GetDocument();
7131         SCTAB nTab = GetTab_Impl();
7132         return ( rDoc.GetRepeatColRange(nTab) != nullptr );
7133     }
7134     return false;
7135 }
7136 
7137 void SAL_CALL ScTableSheetObj::setPrintTitleColumns( sal_Bool bPrintTitleColumns )
7138 {
7139     SolarMutexGuard aGuard;
7140     ScDocShell* pDocSh = GetDocShell();
7141     if ( !pDocSh )
7142         return;
7143 
7144     ScDocument& rDoc = pDocSh->GetDocument();
7145     SCTAB nTab = GetTab_Impl();
7146 
7147     std::unique_ptr<ScPrintRangeSaver> pOldRanges = rDoc.CreatePrintRangeSaver();
7148 
7149     if ( bPrintTitleColumns )
7150     {
7151         if ( !rDoc.GetRepeatColRange( nTab ) )         // do not change existing area
7152         {
7153             rDoc.SetRepeatColRange( nTab, std::unique_ptr<ScRange>(new ScRange( 0, 0, nTab, 0, 0, nTab )) );     // enable
7154         }
7155     }
7156     else
7157         rDoc.SetRepeatColRange( nTab, nullptr );          // disable
7158 
7159     PrintAreaUndo_Impl( std::move(pOldRanges) );   // undo, page break, modified etc.
7160 
7161     //! save last set area during switch off and recreate during switch on ???
7162 }
7163 
7164 table::CellRangeAddress SAL_CALL ScTableSheetObj::getTitleColumns()
7165 {
7166     SolarMutexGuard aGuard;
7167     table::CellRangeAddress aRet;
7168     ScDocShell* pDocSh = GetDocShell();
7169     if ( pDocSh )
7170     {
7171         ScDocument& rDoc = pDocSh->GetDocument();
7172         SCTAB nTab = GetTab_Impl();
7173         const ScRange* pRange = rDoc.GetRepeatColRange(nTab);
7174         if (pRange)
7175         {
7176             ScUnoConversion::FillApiRange( aRet, *pRange );
7177             aRet.Sheet = nTab; // core does not care about sheet index
7178         }
7179     }
7180     return aRet;
7181 }
7182 
7183 void SAL_CALL ScTableSheetObj::setTitleColumns( const table::CellRangeAddress& aTitleColumns )
7184 {
7185     SolarMutexGuard aGuard;
7186     ScDocShell* pDocSh = GetDocShell();
7187     if ( !pDocSh )
7188         return;
7189 
7190     ScDocument& rDoc = pDocSh->GetDocument();
7191     SCTAB nTab = GetTab_Impl();
7192 
7193     std::unique_ptr<ScPrintRangeSaver> pOldRanges = rDoc.CreatePrintRangeSaver();
7194 
7195     std::unique_ptr<ScRange> pNew(new ScRange);
7196     ScUnoConversion::FillScRange( *pNew, aTitleColumns );
7197     rDoc.SetRepeatColRange( nTab, std::move(pNew) );     // also always enable
7198 
7199     PrintAreaUndo_Impl( std::move(pOldRanges) );           // undo, page breaks, modified etc.
7200 }
7201 
7202 sal_Bool SAL_CALL ScTableSheetObj::getPrintTitleRows()
7203 {
7204     SolarMutexGuard aGuard;
7205     ScDocShell* pDocSh = GetDocShell();
7206     if ( pDocSh )
7207     {
7208         ScDocument& rDoc = pDocSh->GetDocument();
7209         SCTAB nTab = GetTab_Impl();
7210         return ( rDoc.GetRepeatRowRange(nTab) != nullptr );
7211     }
7212     return false;
7213 }
7214 
7215 void SAL_CALL ScTableSheetObj::setPrintTitleRows( sal_Bool bPrintTitleRows )
7216 {
7217     SolarMutexGuard aGuard;
7218     ScDocShell* pDocSh = GetDocShell();
7219     if ( !pDocSh )
7220         return;
7221 
7222     ScDocument& rDoc = pDocSh->GetDocument();
7223     SCTAB nTab = GetTab_Impl();
7224 
7225     std::unique_ptr<ScPrintRangeSaver> pOldRanges = rDoc.CreatePrintRangeSaver();
7226 
7227     if ( bPrintTitleRows )
7228     {
7229         if ( !rDoc.GetRepeatRowRange( nTab ) )         // do not change existing area
7230         {
7231             std::unique_ptr<ScRange> pNew( new ScRange(0, 0, nTab, 0, 0, nTab) );
7232             rDoc.SetRepeatRowRange( nTab, std::move(pNew) );     // enable
7233         }
7234     }
7235     else
7236         rDoc.SetRepeatRowRange( nTab, nullptr );          // disable
7237 
7238     PrintAreaUndo_Impl( std::move(pOldRanges) );   // undo, page breaks, modified etc.
7239 
7240     //! save last set area during switch off and recreate during switch on ???
7241 }
7242 
7243 table::CellRangeAddress SAL_CALL ScTableSheetObj::getTitleRows()
7244 {
7245     SolarMutexGuard aGuard;
7246     table::CellRangeAddress aRet;
7247     ScDocShell* pDocSh = GetDocShell();
7248     if ( pDocSh )
7249     {
7250         ScDocument& rDoc = pDocSh->GetDocument();
7251         SCTAB nTab = GetTab_Impl();
7252         const ScRange* pRange = rDoc.GetRepeatRowRange(nTab);
7253         if (pRange)
7254         {
7255             ScUnoConversion::FillApiRange( aRet, *pRange );
7256             aRet.Sheet = nTab; // core does not care about sheet index
7257         }
7258     }
7259     return aRet;
7260 }
7261 
7262 void SAL_CALL ScTableSheetObj::setTitleRows( const table::CellRangeAddress& aTitleRows )
7263 {
7264     SolarMutexGuard aGuard;
7265     ScDocShell* pDocSh = GetDocShell();
7266     if ( !pDocSh )
7267         return;
7268 
7269     ScDocument& rDoc = pDocSh->GetDocument();
7270     SCTAB nTab = GetTab_Impl();
7271 
7272     std::unique_ptr<ScPrintRangeSaver> pOldRanges = rDoc.CreatePrintRangeSaver();
7273 
7274     std::unique_ptr<ScRange> pNew(new ScRange);
7275     ScUnoConversion::FillScRange( *pNew, aTitleRows );
7276     rDoc.SetRepeatRowRange( nTab, std::move(pNew) );     // also always enable
7277 
7278     PrintAreaUndo_Impl( std::move(pOldRanges) );           // Undo, page breaks, modified etc.
7279 }
7280 
7281 // XSheetLinkable
7282 
7283 sheet::SheetLinkMode SAL_CALL ScTableSheetObj::getLinkMode()
7284 {
7285     SolarMutexGuard aGuard;
7286     sheet::SheetLinkMode eRet = sheet::SheetLinkMode_NONE;
7287     ScDocShell* pDocSh = GetDocShell();
7288     if ( pDocSh )
7289     {
7290         ScLinkMode nMode = pDocSh->GetDocument().GetLinkMode( GetTab_Impl() );
7291         if ( nMode == ScLinkMode::NORMAL )
7292             eRet = sheet::SheetLinkMode_NORMAL;
7293         else if ( nMode == ScLinkMode::VALUE )
7294             eRet = sheet::SheetLinkMode_VALUE;
7295     }
7296     return eRet;
7297 }
7298 
7299 void SAL_CALL ScTableSheetObj::setLinkMode( sheet::SheetLinkMode nLinkMode )
7300 {
7301     SolarMutexGuard aGuard;
7302 
7303     //! search for filter and options in old link
7304 
7305     OUString aUrl(getLinkUrl());
7306     OUString aSheet(getLinkSheetName());
7307 
7308     link( aUrl, aSheet, "", "", nLinkMode );
7309 }
7310 
7311 OUString SAL_CALL ScTableSheetObj::getLinkUrl()
7312 {
7313     SolarMutexGuard aGuard;
7314     OUString aFile;
7315     ScDocShell* pDocSh = GetDocShell();
7316     if ( pDocSh )
7317         aFile = pDocSh->GetDocument().GetLinkDoc( GetTab_Impl() );
7318     return aFile;
7319 }
7320 
7321 void SAL_CALL ScTableSheetObj::setLinkUrl( const OUString& aLinkUrl )
7322 {
7323     SolarMutexGuard aGuard;
7324 
7325     //! search for filter and options in old link
7326 
7327     sheet::SheetLinkMode eMode = getLinkMode();
7328     OUString aSheet(getLinkSheetName());
7329 
7330     link( aLinkUrl, aSheet, "", "", eMode );
7331 }
7332 
7333 OUString SAL_CALL ScTableSheetObj::getLinkSheetName()
7334 {
7335     SolarMutexGuard aGuard;
7336     OUString aSheet;
7337     ScDocShell* pDocSh = GetDocShell();
7338     if ( pDocSh )
7339         aSheet = pDocSh->GetDocument().GetLinkTab( GetTab_Impl() );
7340     return aSheet;
7341 }
7342 
7343 void SAL_CALL ScTableSheetObj::setLinkSheetName( const OUString& aLinkSheetName )
7344 {
7345     SolarMutexGuard aGuard;
7346 
7347     //! search for filter and options in old link
7348 
7349     sheet::SheetLinkMode eMode = getLinkMode();
7350     OUString aUrl(getLinkUrl());
7351 
7352     link( aUrl, aLinkSheetName, "", "", eMode );
7353 }
7354 
7355 void SAL_CALL ScTableSheetObj::link( const OUString& aUrl, const OUString& aSheetName,
7356                         const OUString& aFilterName, const OUString& aFilterOptions,
7357                         sheet::SheetLinkMode nMode )
7358 {
7359     SolarMutexGuard aGuard;
7360     ScDocShell* pDocSh = GetDocShell();
7361     if ( !pDocSh )
7362         return;
7363 
7364     ScDocument& rDoc = pDocSh->GetDocument();
7365     SCTAB nTab = GetTab_Impl();
7366 
7367     OUString aFileString = aUrl;
7368     OUString aFilterString = aFilterName;
7369     OUString aOptString = aFilterOptions;
7370 
7371     aFileString = ScGlobal::GetAbsDocName( aFileString, pDocSh );
7372     if (aFilterString.isEmpty())
7373         ScDocumentLoader::GetFilterName( aFileString, aFilterString, aOptString, true, false );
7374 
7375     //  remove application prefix from filter name here, so the filter options
7376     //  aren't reset when the filter name is changed in ScTableLink::DataChanged
7377     ScDocumentLoader::RemoveAppPrefix( aFilterString );
7378 
7379     ScLinkMode nLinkMode = ScLinkMode::NONE;
7380     if ( nMode == sheet::SheetLinkMode_NORMAL )
7381         nLinkMode = ScLinkMode::NORMAL;
7382     else if ( nMode == sheet::SheetLinkMode_VALUE )
7383         nLinkMode = ScLinkMode::VALUE;
7384 
7385     rDoc.SetLink( nTab, nLinkMode, aFileString, aFilterString, aOptString, aSheetName, 0/*nRefresh*/ );
7386 
7387     pDocSh->UpdateLinks();                  // if needed add or delete link
7388     SfxBindings* pBindings = pDocSh->GetViewBindings();
7389     if (pBindings)
7390         pBindings->Invalidate(SID_LINKS);
7391 
7392     //! undo of link data on the table
7393 
7394     if ( !(nLinkMode != ScLinkMode::NONE && rDoc.IsExecuteLinkEnabled()) )        // update link
7395         return;
7396 
7397     //  Always update link also if already exists
7398     //! update only on the affected table???
7399 
7400     sfx2::LinkManager* pLinkManager = rDoc.GetLinkManager();
7401     sal_uInt16 nCount = pLinkManager->GetLinks().size();
7402     for ( sal_uInt16 i=0; i<nCount; i++ )
7403     {
7404         ::sfx2::SvBaseLink* pBase = pLinkManager->GetLinks()[i].get();
7405         if (auto pTabLink = dynamic_cast<ScTableLink*>( pBase))
7406         {
7407             if ( aFileString == pTabLink->GetFileName() )
7408                 pTabLink->Update();                         // include Paint&Undo
7409 
7410             //! The file name should only exists once (?)
7411         }
7412     }
7413 
7414     //! notify ScSheetLinkObj objects!!!
7415 }
7416 
7417 // XSheetAuditing
7418 
7419 sal_Bool SAL_CALL ScTableSheetObj::hideDependents( const table::CellAddress& aPosition )
7420 {
7421     SolarMutexGuard aGuard;
7422     ScDocShell* pDocSh = GetDocShell();
7423     if ( pDocSh )
7424     {
7425         SCTAB nTab = GetTab_Impl();
7426         OSL_ENSURE( aPosition.Sheet == nTab, "wrong table in CellAddress" );
7427         ScAddress aPos( static_cast<SCCOL>(aPosition.Column), static_cast<SCROW>(aPosition.Row), nTab );
7428         return pDocSh->GetDocFunc().DetectiveDelSucc( aPos );
7429     }
7430     return false;
7431 }
7432 
7433 sal_Bool SAL_CALL ScTableSheetObj::hidePrecedents( const table::CellAddress& aPosition )
7434 {
7435     SolarMutexGuard aGuard;
7436     ScDocShell* pDocSh = GetDocShell();
7437     if ( pDocSh )
7438     {
7439         SCTAB nTab = GetTab_Impl();
7440         OSL_ENSURE( aPosition.Sheet == nTab, "wrong table in CellAddress" );
7441         ScAddress aPos( static_cast<SCCOL>(aPosition.Column), static_cast<SCROW>(aPosition.Row), nTab );
7442         return pDocSh->GetDocFunc().DetectiveDelPred( aPos );
7443     }
7444     return false;
7445 }
7446 
7447 sal_Bool SAL_CALL ScTableSheetObj::showDependents( const table::CellAddress& aPosition )
7448 {
7449     SolarMutexGuard aGuard;
7450     ScDocShell* pDocSh = GetDocShell();
7451     if ( pDocSh )
7452     {
7453         SCTAB nTab = GetTab_Impl();
7454         OSL_ENSURE( aPosition.Sheet == nTab, "wrong table in CellAddress" );
7455         ScAddress aPos( static_cast<SCCOL>(aPosition.Column), static_cast<SCROW>(aPosition.Row), nTab );
7456         return pDocSh->GetDocFunc().DetectiveAddSucc( aPos );
7457     }
7458     return false;
7459 }
7460 
7461 sal_Bool SAL_CALL ScTableSheetObj::showPrecedents( const table::CellAddress& aPosition )
7462 {
7463     SolarMutexGuard aGuard;
7464     ScDocShell* pDocSh = GetDocShell();
7465     if ( pDocSh )
7466     {
7467         SCTAB nTab = GetTab_Impl();
7468         OSL_ENSURE( aPosition.Sheet == nTab, "wrong table in CellAddress" );
7469         ScAddress aPos( static_cast<SCCOL>(aPosition.Column), static_cast<SCROW>(aPosition.Row), nTab );
7470         return pDocSh->GetDocFunc().DetectiveAddPred( aPos );
7471     }
7472     return false;
7473 }
7474 
7475 sal_Bool SAL_CALL ScTableSheetObj::showErrors( const table::CellAddress& aPosition )
7476 {
7477     SolarMutexGuard aGuard;
7478     ScDocShell* pDocSh = GetDocShell();
7479     if ( pDocSh )
7480     {
7481         SCTAB nTab = GetTab_Impl();
7482         OSL_ENSURE( aPosition.Sheet == nTab, "wrong table in CellAddress" );
7483         ScAddress aPos( static_cast<SCCOL>(aPosition.Column), static_cast<SCROW>(aPosition.Row), nTab );
7484         return pDocSh->GetDocFunc().DetectiveAddError( aPos );
7485     }
7486     return false;
7487 }
7488 
7489 sal_Bool SAL_CALL ScTableSheetObj::showInvalid()
7490 {
7491     SolarMutexGuard aGuard;
7492     ScDocShell* pDocSh = GetDocShell();
7493     if ( pDocSh )
7494         return pDocSh->GetDocFunc().DetectiveMarkInvalid( GetTab_Impl() );
7495     return false;
7496 }
7497 
7498 void SAL_CALL ScTableSheetObj::clearArrows()
7499 {
7500     SolarMutexGuard aGuard;
7501     ScDocShell* pDocSh = GetDocShell();
7502     if ( pDocSh )
7503         pDocSh->GetDocFunc().DetectiveDelAll( GetTab_Impl() );
7504 }
7505 
7506 // XSheetOutline
7507 
7508 void SAL_CALL ScTableSheetObj::group( const table::CellRangeAddress& rGroupRange,
7509                                         table::TableOrientation nOrientation )
7510 {
7511     SolarMutexGuard aGuard;
7512     ScDocShell* pDocSh = GetDocShell();
7513     if ( pDocSh )
7514     {
7515         bool bColumns = ( nOrientation == table::TableOrientation_COLUMNS );
7516         ScRange aGroupRange;
7517         ScUnoConversion::FillScRange( aGroupRange, rGroupRange );
7518         ScOutlineDocFunc aFunc(*pDocSh);
7519         aFunc.MakeOutline( aGroupRange, bColumns, true, true );
7520     }
7521 }
7522 
7523 void SAL_CALL ScTableSheetObj::ungroup( const table::CellRangeAddress& rGroupRange,
7524                                         table::TableOrientation nOrientation )
7525 {
7526     SolarMutexGuard aGuard;
7527     ScDocShell* pDocSh = GetDocShell();
7528     if ( pDocSh )
7529     {
7530         bool bColumns = ( nOrientation == table::TableOrientation_COLUMNS );
7531         ScRange aGroupRange;
7532         ScUnoConversion::FillScRange( aGroupRange, rGroupRange );
7533         ScOutlineDocFunc aFunc(*pDocSh);
7534         aFunc.RemoveOutline( aGroupRange, bColumns, true, true );
7535     }
7536 }
7537 
7538 void SAL_CALL ScTableSheetObj::autoOutline( const table::CellRangeAddress& rCellRange )
7539 {
7540     SolarMutexGuard aGuard;
7541     ScDocShell* pDocSh = GetDocShell();
7542     if ( pDocSh )
7543     {
7544         ScRange aFormulaRange;
7545         ScUnoConversion::FillScRange( aFormulaRange, rCellRange );
7546         ScOutlineDocFunc aFunc(*pDocSh);
7547         aFunc.AutoOutline( aFormulaRange, true );
7548     }
7549 }
7550 
7551 void SAL_CALL ScTableSheetObj::clearOutline()
7552 {
7553     SolarMutexGuard aGuard;
7554     ScDocShell* pDocSh = GetDocShell();
7555     if ( pDocSh )
7556     {
7557         SCTAB nTab = GetTab_Impl();
7558         ScOutlineDocFunc aFunc(*pDocSh);
7559         aFunc.RemoveAllOutlines( nTab, true );
7560     }
7561 }
7562 
7563 void SAL_CALL ScTableSheetObj::hideDetail( const table::CellRangeAddress& rCellRange )
7564 {
7565     SolarMutexGuard aGuard;
7566     ScDocShell* pDocSh = GetDocShell();
7567     if ( pDocSh )
7568     {
7569         ScRange aMarkRange;
7570         ScUnoConversion::FillScRange( aMarkRange, rCellRange );
7571         ScOutlineDocFunc aFunc(*pDocSh);
7572         aFunc.HideMarkedOutlines( aMarkRange, true );
7573     }
7574 }
7575 
7576 void SAL_CALL ScTableSheetObj::showDetail( const table::CellRangeAddress& rCellRange )
7577 {
7578     SolarMutexGuard aGuard;
7579     ScDocShell* pDocSh = GetDocShell();
7580     if ( pDocSh )
7581     {
7582         ScRange aMarkRange;
7583         ScUnoConversion::FillScRange( aMarkRange, rCellRange );
7584         ScOutlineDocFunc aFunc(*pDocSh);
7585         aFunc.ShowMarkedOutlines( aMarkRange, true );
7586     }
7587 }
7588 
7589 void SAL_CALL ScTableSheetObj::showLevel( sal_Int16 nLevel, table::TableOrientation nOrientation )
7590 {
7591     SolarMutexGuard aGuard;
7592     ScDocShell* pDocSh = GetDocShell();
7593     if ( pDocSh )
7594     {
7595         bool bColumns = ( nOrientation == table::TableOrientation_COLUMNS );
7596         SCTAB nTab = GetTab_Impl();
7597         ScOutlineDocFunc aFunc(*pDocSh);
7598         aFunc.SelectLevel( nTab, bColumns, nLevel, true, true );
7599     }
7600 }
7601 
7602 // XProtectable
7603 
7604 void SAL_CALL ScTableSheetObj::protect( const OUString& aPassword )
7605 {
7606     SolarMutexGuard aGuard;
7607     ScDocShell* pDocSh = GetDocShell();
7608     // #i108245# if already protected, don't change anything
7609     if ( pDocSh && !pDocSh->GetDocument().IsTabProtected( GetTab_Impl() ) )
7610     {
7611         pDocSh->GetDocFunc().Protect( GetTab_Impl(), aPassword );
7612     }
7613 }
7614 
7615 void SAL_CALL ScTableSheetObj::unprotect( const OUString& aPassword )
7616 {
7617     SolarMutexGuard aGuard;
7618     ScDocShell* pDocSh = GetDocShell();
7619     if ( pDocSh )
7620     {
7621         bool bDone = pDocSh->GetDocFunc().Unprotect( GetTab_Impl(), aPassword, true );
7622         if (!bDone)
7623             throw lang::IllegalArgumentException();
7624     }
7625 }
7626 
7627 sal_Bool SAL_CALL ScTableSheetObj::isProtected()
7628 {
7629     SolarMutexGuard aGuard;
7630     ScDocShell* pDocSh = GetDocShell();
7631     if ( pDocSh )
7632         return pDocSh->GetDocument().IsTabProtected( GetTab_Impl() );
7633 
7634     OSL_FAIL("no DocShell");     //! Exception or so?
7635     return false;
7636 }
7637 
7638 // XScenario
7639 
7640 sal_Bool SAL_CALL ScTableSheetObj::getIsScenario()
7641 {
7642     SolarMutexGuard aGuard;
7643     ScDocShell* pDocSh = GetDocShell();
7644     if ( pDocSh )
7645         return pDocSh->GetDocument().IsScenario( GetTab_Impl() );
7646 
7647     return false;
7648 }
7649 
7650 OUString SAL_CALL ScTableSheetObj::getScenarioComment()
7651 {
7652     SolarMutexGuard aGuard;
7653     ScDocShell* pDocSh = GetDocShell();
7654     if ( pDocSh )
7655     {
7656         OUString aComment;
7657         Color  aColor;
7658         ScScenarioFlags nFlags;
7659         pDocSh->GetDocument().GetScenarioData( GetTab_Impl(), aComment, aColor, nFlags );
7660         return aComment;
7661     }
7662     return OUString();
7663 }
7664 
7665 void SAL_CALL ScTableSheetObj::setScenarioComment( const OUString& aScenarioComment )
7666 {
7667     SolarMutexGuard aGuard;
7668     ScDocShell* pDocSh = GetDocShell();
7669     if ( !pDocSh )
7670         return;
7671 
7672     ScDocument& rDoc = pDocSh->GetDocument();
7673     SCTAB nTab = GetTab_Impl();
7674 
7675     OUString aName;
7676     OUString aComment;
7677     Color  aColor;
7678     ScScenarioFlags nFlags;
7679     rDoc.GetName( nTab, aName );
7680     rDoc.GetScenarioData( nTab, aComment, aColor, nFlags );
7681 
7682     aComment = aScenarioComment;
7683 
7684     pDocSh->ModifyScenario( nTab, aName, aComment, aColor, nFlags );
7685 }
7686 
7687 void SAL_CALL ScTableSheetObj::addRanges( const uno::Sequence<table::CellRangeAddress>& rScenRanges )
7688 {
7689     SolarMutexGuard aGuard;
7690     ScDocShell* pDocSh = GetDocShell();
7691     if ( !pDocSh )
7692         return;
7693 
7694     ScDocument& rDoc = pDocSh->GetDocument();
7695     SCTAB nTab = GetTab_Impl();
7696 
7697     if (!rDoc.IsScenario(nTab))
7698         return;
7699 
7700     ScMarkData aMarkData(rDoc.GetSheetLimits());
7701     aMarkData.SelectTable( nTab, true );
7702 
7703     for (const table::CellRangeAddress& rRange : rScenRanges)
7704     {
7705         OSL_ENSURE( rRange.Sheet == nTab, "addRanges with wrong Tab" );
7706         ScRange aOneRange( static_cast<SCCOL>(rRange.StartColumn), static_cast<SCROW>(rRange.StartRow), nTab,
7707                            static_cast<SCCOL>(rRange.EndColumn),   static_cast<SCROW>(rRange.EndRow),   nTab );
7708 
7709         aMarkData.SetMultiMarkArea( aOneRange );
7710     }
7711 
7712     //  Scenario ranges are tagged with attribute
7713     ScPatternAttr aPattern( rDoc.GetPool() );
7714     aPattern.GetItemSet().Put( ScMergeFlagAttr( ScMF::Scenario ) );
7715     aPattern.GetItemSet().Put( ScProtectionAttr( true ) );
7716     pDocSh->GetDocFunc().ApplyAttributes( aMarkData, aPattern, true );
7717 }
7718 
7719 void SAL_CALL ScTableSheetObj::apply()
7720 {
7721     SolarMutexGuard aGuard;
7722     ScDocShell* pDocSh = GetDocShell();
7723     if ( !pDocSh )
7724         return;
7725 
7726     ScDocument& rDoc = pDocSh->GetDocument();
7727     SCTAB nTab = GetTab_Impl();
7728     OUString aName;
7729     rDoc.GetName( nTab, aName );       // scenario name
7730 
7731     SCTAB nDestTab = nTab;
7732     while ( nDestTab > 0 && rDoc.IsScenario(nDestTab) )
7733         --nDestTab;
7734 
7735     if ( !rDoc.IsScenario(nDestTab) )
7736         pDocSh->UseScenario( nDestTab, aName );
7737 
7738     //! otherwise error or so
7739 }
7740 
7741 // XScenarioEnhanced
7742 
7743 uno::Sequence< table::CellRangeAddress > SAL_CALL ScTableSheetObj::getRanges(  )
7744 {
7745     SolarMutexGuard aGuard;
7746     ScDocShell* pDocSh = GetDocShell();
7747     if ( pDocSh )
7748     {
7749         ScDocument& rDoc = pDocSh->GetDocument();
7750         SCTAB nTab = GetTab_Impl();
7751         const ScRangeList* pRangeList = rDoc.GetScenarioRanges(nTab);
7752         if (pRangeList)
7753         {
7754             size_t nCount = pRangeList->size();
7755             uno::Sequence< table::CellRangeAddress > aRetRanges( nCount );
7756             table::CellRangeAddress* pAry = aRetRanges.getArray();
7757             for( size_t nIndex = 0; nIndex < nCount; nIndex++ )
7758             {
7759                 const ScRange & rRange = (*pRangeList)[nIndex];
7760                 pAry->StartColumn = rRange.aStart.Col();
7761                 pAry->StartRow = rRange.aStart.Row();
7762                 pAry->EndColumn = rRange.aEnd.Col();
7763                 pAry->EndRow = rRange.aEnd.Row();
7764                 pAry->Sheet = rRange.aStart.Tab();
7765                 ++pAry;
7766             }
7767             return aRetRanges;
7768         }
7769     }
7770     return uno::Sequence< table::CellRangeAddress > ();
7771 }
7772 
7773 // XExternalSheetName
7774 
7775 void ScTableSheetObj::setExternalName( const OUString& aUrl, const OUString& aSheetName )
7776 {
7777     SolarMutexGuard aGuard;
7778     ScDocShell* pDocSh = GetDocShell();
7779     if ( pDocSh )
7780     {
7781         ScDocument& rDoc = pDocSh->GetDocument();
7782         const SCTAB nTab = GetTab_Impl();
7783         const OUString aAbsDocName( ScGlobal::GetAbsDocName( aUrl, pDocSh ) );
7784         const OUString aDocTabName( ScGlobal::GetDocTabName( aAbsDocName, aSheetName ) );
7785         if ( !rDoc.RenameTab( nTab, aDocTabName, true /*bExternalDocument*/ ) )
7786         {
7787             throw container::ElementExistException( OUString(), *this );
7788         }
7789     }
7790 }
7791 
7792 // XEventsSupplier
7793 
7794 uno::Reference<container::XNameReplace> SAL_CALL ScTableSheetObj::getEvents()
7795 {
7796     SolarMutexGuard aGuard;
7797     ScDocShell* pDocSh = GetDocShell();
7798     if ( pDocSh )
7799         return new ScSheetEventsObj( pDocSh, GetTab_Impl() );
7800 
7801     return nullptr;
7802 }
7803 
7804 // XPropertySet extended for Sheet-Properties
7805 
7806 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScTableSheetObj::getPropertySetInfo()
7807 {
7808     SolarMutexGuard aGuard;
7809     static uno::Reference<beans::XPropertySetInfo> aRef(
7810         new SfxItemPropertySetInfo( pSheetPropSet->getPropertyMap() ));
7811     return aRef;
7812 }
7813 
7814 void ScTableSheetObj::SetOnePropertyValue( const SfxItemPropertySimpleEntry* pEntry, const uno::Any& aValue )
7815 {
7816     if ( !pEntry )
7817         return;
7818 
7819     if ( IsScItemWid( pEntry->nWID ) )
7820     {
7821         //  for Item WIDs, call ScCellRangesBase directly
7822         ScCellRangesBase::SetOnePropertyValue(pEntry, aValue);
7823         return;
7824     }
7825 
7826     //  own properties
7827 
7828     ScDocShell* pDocSh = GetDocShell();
7829     if (!pDocSh)
7830         return;                                                 //! Exception or so?
7831     ScDocument& rDoc = pDocSh->GetDocument();
7832     SCTAB nTab = GetTab_Impl();
7833     ScDocFunc &rFunc = pDocSh->GetDocFunc();
7834 
7835     if ( pEntry->nWID == SC_WID_UNO_PAGESTL )
7836     {
7837         OUString aStrVal;
7838         aValue >>= aStrVal;
7839         OUString aNewStr(ScStyleNameConversion::ProgrammaticToDisplayName(
7840                                             aStrVal, SfxStyleFamily::Page ));
7841 
7842         //! Undo? (also if SID_STYLE_APPLY on View)
7843 
7844         if ( rDoc.GetPageStyle( nTab ) != aNewStr )
7845         {
7846             rDoc.SetPageStyle( nTab, aNewStr );
7847             if (!rDoc.IsImportingXML())
7848             {
7849                 ScPrintFunc( pDocSh, pDocSh->GetPrinter(), nTab ).UpdatePages();
7850 
7851                 SfxBindings* pBindings = pDocSh->GetViewBindings();
7852                 if (pBindings)
7853                 {
7854                     pBindings->Invalidate( SID_STYLE_FAMILY4 );
7855                     pBindings->Invalidate( SID_STATUS_PAGESTYLE );
7856                     pBindings->Invalidate( FID_RESET_PRINTZOOM );
7857                     pBindings->Invalidate( SID_ATTR_PARA_LEFT_TO_RIGHT );
7858                     pBindings->Invalidate( SID_ATTR_PARA_RIGHT_TO_LEFT );
7859                 }
7860             }
7861             pDocSh->SetDocumentModified();
7862         }
7863     }
7864     else if ( pEntry->nWID == SC_WID_UNO_CELLVIS )
7865     {
7866         bool bVis = ScUnoHelpFunctions::GetBoolFromAny( aValue );
7867         rFunc.SetTableVisible( nTab, bVis, true );
7868     }
7869     else if ( pEntry->nWID == SC_WID_UNO_ISACTIVE )
7870     {
7871         if (rDoc.IsScenario(nTab))
7872             rDoc.SetActiveScenario( nTab, ScUnoHelpFunctions::GetBoolFromAny( aValue ) );
7873     }
7874     else if ( pEntry->nWID == SC_WID_UNO_BORDCOL )
7875     {
7876         if (rDoc.IsScenario(nTab))
7877         {
7878             Color aColor;
7879             if (aValue >>= aColor)
7880             {
7881                 OUString aName;
7882                 OUString aComment;
7883                 ScScenarioFlags nFlags;
7884                 Color aTmp;
7885                 rDoc.GetName( nTab, aName );
7886                 rDoc.GetScenarioData( nTab, aComment, aTmp, nFlags );
7887 
7888                 pDocSh->ModifyScenario( nTab, aName, aComment, aColor, nFlags );
7889             }
7890         }
7891     }
7892     else if ( pEntry->nWID == SC_WID_UNO_PROTECT )
7893     {
7894         if (rDoc.IsScenario(nTab))
7895         {
7896             OUString aName;
7897             OUString aComment;
7898             Color  aColor;
7899             ScScenarioFlags nFlags;
7900             rDoc.GetName( nTab, aName );
7901             rDoc.GetScenarioData( nTab, aComment, aColor, nFlags );
7902             bool bModify(false);
7903 
7904             if (ScUnoHelpFunctions::GetBoolFromAny( aValue ))
7905             {
7906                 if (!(nFlags & ScScenarioFlags::Protected))
7907                 {
7908                     nFlags |= ScScenarioFlags::Protected;
7909                     bModify = true;
7910                 }
7911             }
7912             else
7913             {
7914                 if (nFlags & ScScenarioFlags::Protected)
7915                 {
7916                     nFlags &= ~ScScenarioFlags::Protected;
7917                     bModify = true;
7918                 }
7919             }
7920 
7921             if (bModify)
7922                 pDocSh->ModifyScenario( nTab, aName, aComment, aColor, nFlags );
7923         }
7924     }
7925     else if ( pEntry->nWID == SC_WID_UNO_SHOWBORD )
7926     {
7927         if (rDoc.IsScenario(nTab))
7928         {
7929             OUString aName;
7930             OUString aComment;
7931             Color  aColor;
7932             ScScenarioFlags nFlags;
7933             rDoc.GetName( nTab, aName );
7934             rDoc.GetScenarioData( nTab, aComment, aColor, nFlags );
7935             bool bModify(false);
7936 
7937             if (ScUnoHelpFunctions::GetBoolFromAny( aValue ))
7938             {
7939                 if (!(nFlags & ScScenarioFlags::ShowFrame))
7940                 {
7941                     nFlags |= ScScenarioFlags::ShowFrame;
7942                     bModify = true;
7943                 }
7944             }
7945             else
7946             {
7947                 if (nFlags & ScScenarioFlags::ShowFrame)
7948                 {
7949                     nFlags &= ~ScScenarioFlags::ShowFrame;
7950                     bModify = true;
7951                 }
7952             }
7953 
7954             if (bModify)
7955                 pDocSh->ModifyScenario( nTab, aName, aComment, aColor, nFlags );
7956         }
7957     }
7958     else if ( pEntry->nWID == SC_WID_UNO_PRINTBORD )
7959     {
7960         if (rDoc.IsScenario(nTab))
7961         {
7962             OUString aName;
7963             OUString aComment;
7964             Color  aColor;
7965             ScScenarioFlags nFlags;
7966             rDoc.GetName( nTab, aName );
7967             rDoc.GetScenarioData( nTab, aComment, aColor, nFlags );
7968             bool bModify(false);
7969 
7970             if (ScUnoHelpFunctions::GetBoolFromAny( aValue ))
7971             {
7972                 if (!(nFlags & ScScenarioFlags::PrintFrame))
7973                 {
7974                     nFlags |= ScScenarioFlags::PrintFrame;
7975                     bModify = true;
7976                 }
7977             }
7978             else
7979             {
7980                 if (nFlags & ScScenarioFlags::PrintFrame)
7981                 {
7982                     nFlags &= ~ScScenarioFlags::PrintFrame;
7983                     bModify = true;
7984                 }
7985             }
7986 
7987             if (bModify)
7988                 pDocSh->ModifyScenario( nTab, aName, aComment, aColor, nFlags );
7989         }
7990     }
7991     else if ( pEntry->nWID == SC_WID_UNO_COPYBACK )
7992     {
7993         if (rDoc.IsScenario(nTab))
7994         {
7995             OUString aName;
7996             OUString aComment;
7997             Color  aColor;
7998             ScScenarioFlags nFlags;
7999             rDoc.GetName( nTab, aName );
8000             rDoc.GetScenarioData( nTab, aComment, aColor, nFlags );
8001             bool bModify(false);
8002 
8003             if (ScUnoHelpFunctions::GetBoolFromAny( aValue ))
8004             {
8005                 if (!(nFlags & ScScenarioFlags::TwoWay))
8006                 {
8007                     nFlags |= ScScenarioFlags::TwoWay;
8008                     bModify = true;
8009                 }
8010             }
8011             else
8012             {
8013                 if (nFlags & ScScenarioFlags::TwoWay)
8014                 {
8015                     nFlags &= ~ScScenarioFlags::TwoWay;
8016                     bModify = true;
8017                 }
8018             }
8019 
8020             if (bModify)
8021                 pDocSh->ModifyScenario( nTab, aName, aComment, aColor, nFlags );
8022         }
8023     }
8024     else if ( pEntry->nWID == SC_WID_UNO_COPYSTYL )
8025     {
8026         if (rDoc.IsScenario(nTab))
8027         {
8028             OUString aName;
8029             OUString aComment;
8030             Color  aColor;
8031             ScScenarioFlags nFlags;
8032             rDoc.GetName( nTab, aName );
8033             rDoc.GetScenarioData( nTab, aComment, aColor, nFlags );
8034             bool bModify(false);
8035 
8036             if (ScUnoHelpFunctions::GetBoolFromAny( aValue ))
8037             {
8038                 if (!(nFlags & ScScenarioFlags::Attrib))
8039                 {
8040                     nFlags |= ScScenarioFlags::Attrib;
8041                     bModify = true;
8042                 }
8043             }
8044             else
8045             {
8046                 if (nFlags & ScScenarioFlags::Attrib)
8047                 {
8048                     nFlags &= ~ScScenarioFlags::Attrib;
8049                     bModify = true;
8050                 }
8051             }
8052 
8053             if (bModify)
8054                 pDocSh->ModifyScenario( nTab, aName, aComment, aColor, nFlags );
8055         }
8056     }
8057     else if ( pEntry->nWID == SC_WID_UNO_COPYFORM )
8058     {
8059         if (rDoc.IsScenario(nTab))
8060         {
8061             OUString aName;
8062             OUString aComment;
8063             Color  aColor;
8064             ScScenarioFlags nFlags;
8065             rDoc.GetName( nTab, aName );
8066             rDoc.GetScenarioData( nTab, aComment, aColor, nFlags );
8067             bool bModify(false);
8068 
8069             if (ScUnoHelpFunctions::GetBoolFromAny( aValue ))
8070             {
8071                 if (nFlags & ScScenarioFlags::Value)
8072                 {
8073                     nFlags &= ~ScScenarioFlags::Value;
8074                     bModify = true;
8075                 }
8076             }
8077             else
8078             {
8079                 if (!(nFlags & ScScenarioFlags::Value))
8080                 {
8081                     nFlags |= ScScenarioFlags::Value;
8082                     bModify = true;
8083                 }
8084             }
8085 
8086             if (bModify)
8087                 pDocSh->ModifyScenario( nTab, aName, aComment, aColor, nFlags );
8088         }
8089     }
8090     else if ( pEntry->nWID == SC_WID_UNO_TABLAYOUT )
8091     {
8092         sal_Int16 nValue = 0;
8093         if (aValue >>= nValue)
8094         {
8095             if (nValue == css::text::WritingMode2::RL_TB)
8096                 rFunc.SetLayoutRTL(nTab, true);
8097             else
8098                 rFunc.SetLayoutRTL(nTab, false);
8099         }
8100     }
8101     else if ( pEntry->nWID == SC_WID_UNO_AUTOPRINT )
8102     {
8103         bool bAutoPrint = ScUnoHelpFunctions::GetBoolFromAny( aValue );
8104         if (bAutoPrint)
8105             rDoc.SetPrintEntireSheet( nTab ); // clears all print ranges
8106         else
8107         {
8108             if (rDoc.IsPrintEntireSheet( nTab ))
8109                 rDoc.ClearPrintRanges( nTab ); // if this flag is true, there are no PrintRanges, so Clear clears only the flag.
8110         }
8111     }
8112     else if ( pEntry->nWID == SC_WID_UNO_TABCOLOR )
8113     {
8114         Color aColor = COL_AUTO;
8115         if ( aValue >>= aColor )
8116         {
8117             if ( rDoc.GetTabBgColor( nTab ) != aColor )
8118                 rFunc.SetTabBgColor( nTab, aColor, true, true );
8119         }
8120     }
8121     else if ( pEntry->nWID == SC_WID_UNO_CODENAME )
8122     {
8123         OUString aCodeName;
8124         if (aValue >>= aCodeName)
8125         {
8126             pDocSh->GetDocument().SetCodeName( GetTab_Impl(), aCodeName );
8127         }
8128     }
8129     else if (pEntry->nWID == SC_WID_UNO_CONDFORMAT)
8130     {
8131         uno::Reference<sheet::XConditionalFormats> xCondFormat;
8132         if (aValue >>= xCondFormat)
8133         {
8134             // how to set the format correctly
8135         }
8136     }
8137     else
8138         ScCellRangeObj::SetOnePropertyValue(pEntry, aValue);        // base class, no Item WID
8139 }
8140 
8141 void ScTableSheetObj::GetOnePropertyValue( const SfxItemPropertySimpleEntry* pEntry,
8142                                             uno::Any& rAny )
8143 {
8144     if ( !pEntry )
8145         return;
8146 
8147     ScDocShell* pDocSh = GetDocShell();
8148     if (!pDocSh)
8149         throw uno::RuntimeException();
8150     ScDocument& rDoc = pDocSh->GetDocument();
8151     SCTAB nTab = GetTab_Impl();
8152 
8153     if ( pEntry->nWID == SC_WID_UNO_NAMES )
8154     {
8155         rAny <<= uno::Reference<sheet::XNamedRanges>(new ScLocalNamedRangesObj(pDocSh, this));
8156     }
8157     else if ( pEntry->nWID == SC_WID_UNO_PAGESTL )
8158     {
8159         rAny <<= ScStyleNameConversion::DisplayToProgrammaticName(
8160                             rDoc.GetPageStyle( nTab ), SfxStyleFamily::Page );
8161     }
8162     else if ( pEntry->nWID == SC_WID_UNO_CELLVIS )
8163     {
8164         bool bVis = rDoc.IsVisible( nTab );
8165         rAny <<= bVis;
8166     }
8167     else if ( pEntry->nWID == SC_WID_UNO_LINKDISPBIT )
8168     {
8169         //  no target bitmaps for individual entries (would be all equal)
8170         // ScLinkTargetTypeObj::SetLinkTargetBitmap( aAny, SC_LINKTARGETTYPE_SHEET );
8171     }
8172     else if ( pEntry->nWID == SC_WID_UNO_LINKDISPNAME )
8173     {
8174         //  LinkDisplayName for hyperlink dialog
8175         rAny <<= getName();     // sheet name
8176     }
8177     else if ( pEntry->nWID == SC_WID_UNO_ISACTIVE )
8178     {
8179         if (rDoc.IsScenario(nTab))
8180             rAny <<= rDoc.IsActiveScenario( nTab );
8181     }
8182     else if ( pEntry->nWID == SC_WID_UNO_BORDCOL )
8183     {
8184         if (rDoc.IsScenario(nTab))
8185         {
8186             OUString aComment;
8187             Color  aColor;
8188             ScScenarioFlags nFlags;
8189             rDoc.GetScenarioData( nTab, aComment, aColor, nFlags );
8190 
8191             rAny <<= aColor;
8192         }
8193     }
8194     else if ( pEntry->nWID == SC_WID_UNO_PROTECT )
8195     {
8196         if (rDoc.IsScenario(nTab))
8197         {
8198             ScScenarioFlags nFlags;
8199             rDoc.GetScenarioFlags(nTab, nFlags);
8200 
8201             rAny <<= ((nFlags & ScScenarioFlags::Protected) != ScScenarioFlags::NONE);
8202         }
8203     }
8204     else if ( pEntry->nWID == SC_WID_UNO_SHOWBORD )
8205     {
8206         if (rDoc.IsScenario(nTab))
8207         {
8208             ScScenarioFlags nFlags;
8209             rDoc.GetScenarioFlags(nTab, nFlags);
8210 
8211             rAny <<= ((nFlags & ScScenarioFlags::ShowFrame) != ScScenarioFlags::NONE);
8212         }
8213     }
8214     else if ( pEntry->nWID == SC_WID_UNO_PRINTBORD )
8215     {
8216         if (rDoc.IsScenario(nTab))
8217         {
8218             ScScenarioFlags nFlags;
8219             rDoc.GetScenarioFlags(nTab, nFlags);
8220 
8221             rAny <<= ((nFlags & ScScenarioFlags::PrintFrame) != ScScenarioFlags::NONE);
8222         }
8223     }
8224     else if ( pEntry->nWID == SC_WID_UNO_COPYBACK )
8225     {
8226         if (rDoc.IsScenario(nTab))
8227         {
8228             ScScenarioFlags nFlags;
8229             rDoc.GetScenarioFlags(nTab, nFlags);
8230 
8231             rAny <<= ((nFlags & ScScenarioFlags::TwoWay) != ScScenarioFlags::NONE);
8232         }
8233     }
8234     else if ( pEntry->nWID == SC_WID_UNO_COPYSTYL )
8235     {
8236         if (rDoc.IsScenario(nTab))
8237         {
8238             ScScenarioFlags nFlags;
8239             rDoc.GetScenarioFlags(nTab, nFlags);
8240 
8241             rAny <<= ((nFlags & ScScenarioFlags::Attrib) != ScScenarioFlags::NONE);
8242         }
8243     }
8244     else if ( pEntry->nWID == SC_WID_UNO_COPYFORM )
8245     {
8246         if (rDoc.IsScenario(nTab))
8247         {
8248             ScScenarioFlags nFlags;
8249             rDoc.GetScenarioFlags(nTab, nFlags);
8250 
8251             rAny <<= !(nFlags & ScScenarioFlags::Value);
8252         }
8253     }
8254     else if ( pEntry->nWID == SC_WID_UNO_TABLAYOUT )
8255     {
8256         if (rDoc.IsLayoutRTL(nTab))
8257             rAny <<= sal_Int16(css::text::WritingMode2::RL_TB);
8258         else
8259             rAny <<= sal_Int16(css::text::WritingMode2::LR_TB);
8260     }
8261     else if ( pEntry->nWID == SC_WID_UNO_AUTOPRINT )
8262     {
8263         bool bAutoPrint = rDoc.IsPrintEntireSheet( nTab );
8264         rAny <<= bAutoPrint;
8265     }
8266     else if ( pEntry->nWID == SC_WID_UNO_TABCOLOR )
8267     {
8268         rAny <<= rDoc.GetTabBgColor(nTab);
8269     }
8270     else if ( pEntry->nWID == SC_WID_UNO_CODENAME )
8271     {
8272         OUString aCodeName;
8273         pDocSh->GetDocument().GetCodeName(GetTab_Impl(), aCodeName);
8274         rAny <<= aCodeName;
8275     }
8276     else if (pEntry->nWID == SC_WID_UNO_CONDFORMAT)
8277     {
8278         rAny <<= uno::Reference<sheet::XConditionalFormats>(new ScCondFormatsObj(pDocSh, nTab));
8279     }
8280     else
8281         ScCellRangeObj::GetOnePropertyValue(pEntry, rAny);
8282 }
8283 
8284 const SfxItemPropertyMap& ScTableSheetObj::GetItemPropertyMap()
8285 {
8286     return pSheetPropSet->getPropertyMap();
8287 }
8288 
8289 // XServiceInfo
8290 
8291 OUString SAL_CALL ScTableSheetObj::getImplementationName()
8292 {
8293     return "ScTableSheetObj";
8294 }
8295 
8296 sal_Bool SAL_CALL ScTableSheetObj::supportsService( const OUString& rServiceName )
8297 {
8298     return cppu::supportsService(this, rServiceName);
8299 }
8300 
8301 uno::Sequence<OUString> SAL_CALL ScTableSheetObj::getSupportedServiceNames()
8302 {
8303     return {SCSPREADSHEET_SERVICE,
8304             SCSHEETCELLRANGE_SERVICE,
8305             SCCELLRANGE_SERVICE,
8306             SCCELLPROPERTIES_SERVICE,
8307             SCCHARPROPERTIES_SERVICE,
8308             SCPARAPROPERTIES_SERVICE,
8309             SCLINKTARGET_SERVICE};
8310 }
8311 
8312 // XUnoTunnel
8313 
8314 UNO3_GETIMPLEMENTATION2_IMPL(ScTableSheetObj, ScCellRangeObj);
8315 
8316 ScTableColumnObj::ScTableColumnObj( ScDocShell* pDocSh, SCCOL nCol, SCTAB nTab ) :
8317     ScCellRangeObj( pDocSh, ScRange(nCol,0,nTab, nCol, pDocSh->GetDocument().MaxRow(),nTab) ),
8318     pColPropSet(lcl_GetColumnPropertySet())
8319 {
8320 }
8321 
8322 ScTableColumnObj::~ScTableColumnObj()
8323 {
8324 }
8325 
8326 uno::Any SAL_CALL ScTableColumnObj::queryInterface( const uno::Type& rType )
8327 {
8328     SC_QUERYINTERFACE( container::XNamed )
8329 
8330     return ScCellRangeObj::queryInterface( rType );
8331 }
8332 
8333 void SAL_CALL ScTableColumnObj::acquire() throw()
8334 {
8335     ScCellRangeObj::acquire();
8336 }
8337 
8338 void SAL_CALL ScTableColumnObj::release() throw()
8339 {
8340     ScCellRangeObj::release();
8341 }
8342 
8343 uno::Sequence<uno::Type> SAL_CALL ScTableColumnObj::getTypes()
8344 {
8345     return comphelper::concatSequences(
8346         ScCellRangeObj::getTypes(),
8347         uno::Sequence<uno::Type> { cppu::UnoType<container::XNamed>::get() } );
8348 }
8349 
8350 uno::Sequence<sal_Int8> SAL_CALL ScTableColumnObj::getImplementationId()
8351 {
8352     return css::uno::Sequence<sal_Int8>();
8353 }
8354 
8355 // XNamed
8356 
8357 OUString SAL_CALL ScTableColumnObj::getName()
8358 {
8359     SolarMutexGuard aGuard;
8360 
8361     const ScRange& rRange = GetRange();
8362     OSL_ENSURE(rRange.aStart.Col() == rRange.aEnd.Col(), "too many columns");
8363     SCCOL nCol = rRange.aStart.Col();
8364 
8365     return ScColToAlpha( nCol );        // from global.hxx
8366 }
8367 
8368 void SAL_CALL ScTableColumnObj::setName( const OUString& /* aNewName */ )
8369 {
8370     SolarMutexGuard aGuard;
8371     throw uno::RuntimeException();      // read-only
8372 }
8373 
8374 // XPropertySet extended for Column-Properties
8375 
8376 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScTableColumnObj::getPropertySetInfo()
8377 {
8378     SolarMutexGuard aGuard;
8379     static uno::Reference<beans::XPropertySetInfo> aRef(
8380         new SfxItemPropertySetInfo( pColPropSet->getPropertyMap() ));
8381     return aRef;
8382 }
8383 
8384 void ScTableColumnObj::SetOnePropertyValue(const SfxItemPropertySimpleEntry* pEntry, const uno::Any& aValue)
8385 {
8386     if ( !pEntry )
8387         return;
8388 
8389     if ( IsScItemWid( pEntry->nWID ) )
8390     {
8391         //  for Item WIDs, call ScCellRangesBase directly
8392         ScCellRangesBase::SetOnePropertyValue(pEntry, aValue);
8393         return;
8394     }
8395 
8396     //  own properties
8397 
8398     ScDocShell* pDocSh = GetDocShell();
8399     if (!pDocSh)
8400         return;                                                 //! Exception or so?
8401     const ScRange& rRange = GetRange();
8402     OSL_ENSURE(rRange.aStart.Col() == rRange.aEnd.Col(), "Too many columns");
8403     SCCOL nCol = rRange.aStart.Col();
8404     SCTAB nTab = rRange.aStart.Tab();
8405     ScDocFunc &rFunc = pDocSh->GetDocFunc();
8406 
8407     std::vector<sc::ColRowSpan> aColArr(1, sc::ColRowSpan(nCol,nCol));
8408 
8409     if ( pEntry->nWID == SC_WID_UNO_CELLWID )
8410     {
8411         sal_Int32 nNewWidth = 0;
8412         if ( aValue >>= nNewWidth )
8413         {
8414             //  property is 1/100mm, column width is twips
8415             nNewWidth = convertMm100ToTwip(nNewWidth);
8416             rFunc.SetWidthOrHeight(
8417                 true, aColArr, nTab, SC_SIZE_ORIGINAL, static_cast<sal_uInt16>(nNewWidth), true, true);
8418         }
8419     }
8420     else if ( pEntry->nWID == SC_WID_UNO_CELLVIS )
8421     {
8422         bool bVis = ScUnoHelpFunctions::GetBoolFromAny( aValue );
8423         ScSizeMode eMode = bVis ? SC_SIZE_SHOW : SC_SIZE_DIRECT;
8424         rFunc.SetWidthOrHeight(true, aColArr, nTab, eMode, 0, true, true);
8425         //  SC_SIZE_DIRECT with size 0 will hide
8426     }
8427     else if ( pEntry->nWID == SC_WID_UNO_OWIDTH )
8428     {
8429         bool bOpt = ScUnoHelpFunctions::GetBoolFromAny( aValue );
8430         if (bOpt)
8431             rFunc.SetWidthOrHeight(
8432                 true, aColArr, nTab, SC_SIZE_OPTIMAL, STD_EXTRA_WIDTH, true, true);
8433         // sal_False on columns currently without effect
8434     }
8435     else if ( pEntry->nWID == SC_WID_UNO_NEWPAGE || pEntry->nWID == SC_WID_UNO_MANPAGE )
8436     {
8437         bool bSet = ScUnoHelpFunctions::GetBoolFromAny( aValue );
8438         if (bSet)
8439             rFunc.InsertPageBreak( true, rRange.aStart, true, true );
8440         else
8441             rFunc.RemovePageBreak( true, rRange.aStart, true, true );
8442     }
8443     else
8444         ScCellRangeObj::SetOnePropertyValue(pEntry, aValue);        // base class, no Item WID
8445 }
8446 
8447 void ScTableColumnObj::GetOnePropertyValue( const SfxItemPropertySimpleEntry* pEntry, uno::Any& rAny )
8448 {
8449     if ( !pEntry )
8450         return;
8451 
8452     ScDocShell* pDocSh = GetDocShell();
8453     if (!pDocSh)
8454         throw uno::RuntimeException();
8455 
8456     ScDocument& rDoc = pDocSh->GetDocument();
8457     const ScRange& rRange = GetRange();
8458     OSL_ENSURE(rRange.aStart.Col() == rRange.aEnd.Col(), "too many columns");
8459     SCCOL nCol = rRange.aStart.Col();
8460     SCTAB nTab = rRange.aStart.Tab();
8461 
8462     if ( pEntry->nWID == SC_WID_UNO_CELLWID )
8463     {
8464         // for hidden column, return original height
8465         sal_uInt16 nWidth = rDoc.GetOriginalWidth( nCol, nTab );
8466         //  property is 1/100mm, column width is twips
8467         nWidth = static_cast<sal_uInt16>(convertTwipToMm100(nWidth));
8468         rAny <<= static_cast<sal_Int32>(nWidth);
8469     }
8470     else if ( pEntry->nWID == SC_WID_UNO_CELLVIS )
8471     {
8472         bool bHidden = rDoc.ColHidden(nCol, nTab);
8473         rAny <<= !bHidden;
8474     }
8475     else if ( pEntry->nWID == SC_WID_UNO_OWIDTH )
8476     {
8477         //! at the moment always set ??!?!
8478         bool bOpt = !(rDoc.GetColFlags( nCol, nTab ) & CRFlags::ManualSize);
8479         rAny <<= bOpt;
8480     }
8481     else if ( pEntry->nWID == SC_WID_UNO_NEWPAGE )
8482     {
8483         ScBreakType nBreak = rDoc.HasColBreak(nCol, nTab);
8484         rAny <<= nBreak != ScBreakType::NONE;
8485     }
8486     else if ( pEntry->nWID == SC_WID_UNO_MANPAGE )
8487     {
8488         ScBreakType nBreak = rDoc.HasColBreak(nCol, nTab);
8489         rAny <<= bool(nBreak & ScBreakType::Manual);
8490     }
8491     else
8492         ScCellRangeObj::GetOnePropertyValue(pEntry, rAny);
8493 }
8494 
8495 const SfxItemPropertyMap& ScTableColumnObj::GetItemPropertyMap()
8496 {
8497     return pColPropSet->getPropertyMap();
8498 }
8499 
8500 ScTableRowObj::ScTableRowObj(ScDocShell* pDocSh, SCROW nRow, SCTAB nTab) :
8501     ScCellRangeObj( pDocSh, ScRange(0,nRow,nTab, pDocSh->GetDocument().MaxCol(),nRow,nTab) ),
8502     pRowPropSet(lcl_GetRowPropertySet())
8503 {
8504 }
8505 
8506 ScTableRowObj::~ScTableRowObj()
8507 {
8508 }
8509 
8510 // XPropertySet extended for Row-Properties
8511 
8512 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScTableRowObj::getPropertySetInfo()
8513 {
8514     SolarMutexGuard aGuard;
8515     static uno::Reference<beans::XPropertySetInfo> aRef(
8516         new SfxItemPropertySetInfo( pRowPropSet->getPropertyMap() ));
8517     return aRef;
8518 }
8519 
8520 void ScTableRowObj::SetOnePropertyValue( const SfxItemPropertySimpleEntry* pEntry, const uno::Any& aValue )
8521 {
8522     if ( !pEntry )
8523         return;
8524 
8525     if ( IsScItemWid( pEntry->nWID ) )
8526     {
8527         //  for Item WIDs, call ScCellRangesBase directly
8528         ScCellRangesBase::SetOnePropertyValue(pEntry, aValue);
8529         return;
8530     }
8531 
8532     //  own properties
8533 
8534     ScDocShell* pDocSh = GetDocShell();
8535     if (!pDocSh)
8536         return;                                                 //! Exception or so?
8537     ScDocument& rDoc = pDocSh->GetDocument();
8538     const ScRange& rRange = GetRange();
8539     OSL_ENSURE(rRange.aStart.Row() == rRange.aEnd.Row(), "too many rows");
8540     SCROW nRow = rRange.aStart.Row();
8541     SCTAB nTab = rRange.aStart.Tab();
8542     ScDocFunc &rFunc = pDocSh->GetDocFunc();
8543 
8544     std::vector<sc::ColRowSpan> aRowArr(1, sc::ColRowSpan(nRow,nRow));
8545 
8546     if ( pEntry->nWID == SC_WID_UNO_CELLHGT )
8547     {
8548         sal_Int32 nNewHeight = 0;
8549         if ( aValue >>= nNewHeight )
8550         {
8551             //  property is 1/100mm, row height is twips
8552             nNewHeight = convertMm100ToTwip(nNewHeight);
8553             rFunc.SetWidthOrHeight(
8554                 false, aRowArr, nTab, SC_SIZE_ORIGINAL, static_cast<sal_uInt16>(nNewHeight), true, true);
8555         }
8556     }
8557     else if ( pEntry->nWID == SC_WID_UNO_CELLVIS )
8558     {
8559         bool bVis = ScUnoHelpFunctions::GetBoolFromAny( aValue );
8560         ScSizeMode eMode = bVis ? SC_SIZE_SHOW : SC_SIZE_DIRECT;
8561         rFunc.SetWidthOrHeight(false, aRowArr, nTab, eMode, 0, true, true);
8562         //  SC_SIZE_DIRECT with size zero will hide
8563     }
8564     else if ( pEntry->nWID == SC_WID_UNO_CELLFILT )
8565     {
8566         bool bFil = ScUnoHelpFunctions::GetBoolFromAny( aValue );
8567         //  SC_SIZE_DIRECT with size zero will hide
8568         rDoc.SetRowFiltered(nRow, nRow, nTab, bFil);
8569     }
8570     else if ( pEntry->nWID == SC_WID_UNO_OHEIGHT )
8571     {
8572         bool bOpt = ScUnoHelpFunctions::GetBoolFromAny( aValue );
8573         if (bOpt)
8574             rFunc.SetWidthOrHeight(false, aRowArr, nTab, SC_SIZE_OPTIMAL, 0, true, true);
8575         else
8576         {
8577             //  set current height again manually
8578             sal_uInt16 nHeight = rDoc.GetOriginalHeight( nRow, nTab );
8579             rFunc.SetWidthOrHeight(false, aRowArr, nTab, SC_SIZE_ORIGINAL, nHeight, true, true);
8580         }
8581     }
8582     else if ( pEntry->nWID == SC_WID_UNO_NEWPAGE || pEntry->nWID == SC_WID_UNO_MANPAGE )
8583     {
8584         bool bSet = ScUnoHelpFunctions::GetBoolFromAny( aValue );
8585         if (bSet)
8586             rFunc.InsertPageBreak( false, rRange.aStart, true, true );
8587         else
8588             rFunc.RemovePageBreak( false, rRange.aStart, true, true );
8589     }
8590     else
8591         ScCellRangeObj::SetOnePropertyValue(pEntry, aValue);        // base class, no Item WID
8592 }
8593 
8594 void ScTableRowObj::GetOnePropertyValue( const SfxItemPropertySimpleEntry* pEntry, uno::Any& rAny )
8595 {
8596     if ( !pEntry )
8597         return;
8598 
8599     ScDocShell* pDocSh = GetDocShell();
8600     if (!pDocSh)
8601         throw uno::RuntimeException();
8602     ScDocument& rDoc = pDocSh->GetDocument();
8603     const ScRange& rRange = GetRange();
8604     OSL_ENSURE(rRange.aStart.Row() == rRange.aEnd.Row(), "too many rows");
8605     SCROW nRow = rRange.aStart.Row();
8606     SCTAB nTab = rRange.aStart.Tab();
8607 
8608     if ( pEntry->nWID == SC_WID_UNO_CELLHGT )
8609     {
8610         // for hidden row, return original height
8611         sal_uInt16 nHeight = rDoc.GetOriginalHeight( nRow, nTab );
8612         //  property is 1/100mm, row height is twips
8613         nHeight = static_cast<sal_uInt16>(convertTwipToMm100(nHeight));
8614         rAny <<= static_cast<sal_Int32>(nHeight);
8615     }
8616     else if ( pEntry->nWID == SC_WID_UNO_CELLVIS )
8617     {
8618         bool bHidden = rDoc.RowHidden(nRow, nTab);
8619         rAny <<= !bHidden;
8620     }
8621     else if ( pEntry->nWID == SC_WID_UNO_CELLFILT )
8622     {
8623         bool bVis = rDoc.RowFiltered(nRow, nTab);
8624         rAny <<= bVis;
8625     }
8626     else if ( pEntry->nWID == SC_WID_UNO_OHEIGHT )
8627     {
8628         bool bOpt = !(rDoc.GetRowFlags( nRow, nTab ) & CRFlags::ManualSize);
8629         rAny <<= bOpt;
8630     }
8631     else if ( pEntry->nWID == SC_WID_UNO_NEWPAGE )
8632     {
8633         ScBreakType nBreak = rDoc.HasRowBreak(nRow, nTab);
8634         rAny <<= (nBreak != ScBreakType::NONE);
8635     }
8636     else if ( pEntry->nWID == SC_WID_UNO_MANPAGE )
8637     {
8638         bool bBreak(rDoc.HasRowBreak(nRow, nTab) & ScBreakType::Manual);
8639         rAny <<= bBreak;
8640     }
8641     else
8642         ScCellRangeObj::GetOnePropertyValue(pEntry, rAny);
8643 }
8644 
8645 const SfxItemPropertyMap& ScTableRowObj::GetItemPropertyMap()
8646 {
8647     return pRowPropSet->getPropertyMap();
8648 }
8649 
8650 ScCellsObj::ScCellsObj(ScDocShell* pDocSh, const ScRangeList& rR) :
8651     pDocShell( pDocSh ),
8652     aRanges( rR )
8653 {
8654     pDocShell->GetDocument().AddUnoObject(*this);
8655 }
8656 
8657 ScCellsObj::~ScCellsObj()
8658 {
8659     SolarMutexGuard g;
8660 
8661     if (pDocShell)
8662         pDocShell->GetDocument().RemoveUnoObject(*this);
8663 }
8664 
8665 void ScCellsObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
8666 {
8667     if ( auto pRefHint = dynamic_cast<const ScUpdateRefHint*>(&rHint) )
8668     {
8669         aRanges.UpdateReference( pRefHint->GetMode(), &pDocShell->GetDocument(), pRefHint->GetRange(),
8670                                         pRefHint->GetDx(), pRefHint->GetDy(), pRefHint->GetDz() );
8671     }
8672     else if ( rHint.GetId() == SfxHintId::Dying )
8673     {
8674         pDocShell = nullptr;
8675     }
8676 }
8677 
8678 // XEnumerationAccess
8679 
8680 uno::Reference<container::XEnumeration> SAL_CALL ScCellsObj::createEnumeration()
8681 {
8682     SolarMutexGuard aGuard;
8683     if (pDocShell)
8684         return new ScCellsEnumeration( pDocShell, aRanges );
8685     return nullptr;
8686 }
8687 
8688 uno::Type SAL_CALL ScCellsObj::getElementType()
8689 {
8690     SolarMutexGuard aGuard;
8691     return cppu::UnoType<table::XCell>::get();
8692 }
8693 
8694 sal_Bool SAL_CALL ScCellsObj::hasElements()
8695 {
8696     SolarMutexGuard aGuard;
8697     bool bHas = false;
8698     if ( pDocShell )
8699     {
8700         //! faster if test ourself?
8701 
8702         uno::Reference<container::XEnumeration> xEnum(new ScCellsEnumeration( pDocShell, aRanges ));
8703         bHas = xEnum->hasMoreElements();
8704     }
8705     return bHas;
8706 }
8707 
8708 ScCellsEnumeration::ScCellsEnumeration(ScDocShell* pDocSh, const ScRangeList& rR) :
8709     pDocShell( pDocSh ),
8710     aRanges( rR ),
8711     bAtEnd( false )
8712 {
8713     ScDocument& rDoc = pDocShell->GetDocument();
8714     rDoc.AddUnoObject(*this);
8715 
8716     if ( aRanges.empty() )
8717         bAtEnd = true;
8718     else
8719     {
8720         SCTAB nTab = aRanges[ 0 ].aStart.Tab();
8721         aPos = ScAddress(0,0,nTab);
8722         CheckPos_Impl();                    // set aPos on first matching cell
8723     }
8724 }
8725 
8726 void ScCellsEnumeration::CheckPos_Impl()
8727 {
8728     if (!pDocShell)
8729         return;
8730 
8731     bool bFound = false;
8732     ScDocument& rDoc = pDocShell->GetDocument();
8733     ScRefCellValue aCell(rDoc, aPos);
8734     if (!aCell.isEmpty())
8735     {
8736         if (!pMark)
8737         {
8738             pMark.reset( new ScMarkData(rDoc.GetSheetLimits()) );
8739             pMark->MarkFromRangeList(aRanges, false);
8740             pMark->MarkToMulti();   // needed for GetNextMarkedCell
8741         }
8742         bFound = pMark->IsCellMarked(aPos.Col(), aPos.Row());
8743     }
8744     if (!bFound)
8745         Advance_Impl();
8746 }
8747 
8748 ScCellsEnumeration::~ScCellsEnumeration()
8749 {
8750     SolarMutexGuard g;
8751 
8752     if (pDocShell)
8753         pDocShell->GetDocument().RemoveUnoObject(*this);
8754     pMark.reset();
8755 }
8756 
8757 void ScCellsEnumeration::Advance_Impl()
8758 {
8759     OSL_ENSURE(!bAtEnd,"too much Advance_Impl");
8760     if (!pMark)
8761     {
8762         pMark.reset( new ScMarkData(pDocShell->GetDocument().GetSheetLimits()) );
8763         pMark->MarkFromRangeList( aRanges, false );
8764         pMark->MarkToMulti();   // needed for GetNextMarkedCell
8765     }
8766 
8767     SCCOL nCol = aPos.Col();
8768     SCROW nRow = aPos.Row();
8769     SCTAB nTab = aPos.Tab();
8770     bool bFound = pDocShell->GetDocument().GetNextMarkedCell( nCol, nRow, nTab, *pMark );
8771     if (bFound)
8772         aPos.Set( nCol, nRow, nTab );
8773     else
8774         bAtEnd = true;      // nothing will follow
8775 }
8776 
8777 void ScCellsEnumeration::Notify( SfxBroadcaster&, const SfxHint& rHint )
8778 {
8779     const ScUpdateRefHint* pRefHint = dynamic_cast<const ScUpdateRefHint*>(&rHint);
8780     if ( pRefHint )
8781     {
8782         if (pDocShell)
8783         {
8784             aRanges.UpdateReference( pRefHint->GetMode(), &pDocShell->GetDocument(), pRefHint->GetRange(),
8785                                      pRefHint->GetDx(), pRefHint->GetDy(), pRefHint->GetDz() );
8786 
8787             pMark.reset();       // recreate from moved area
8788 
8789             if (!bAtEnd)        // adjust aPos
8790             {
8791                 ScRangeList aNew { ScRange(aPos) };
8792                 aNew.UpdateReference( pRefHint->GetMode(), &pDocShell->GetDocument(), pRefHint->GetRange(),
8793                                       pRefHint->GetDx(), pRefHint->GetDy(), pRefHint->GetDz() );
8794                 if (aNew.size()==1)
8795                 {
8796                     aPos = aNew[ 0 ].aStart;
8797                     CheckPos_Impl();
8798                 }
8799             }
8800         }
8801     }
8802     else if ( rHint.GetId() == SfxHintId::Dying )
8803     {
8804         pDocShell = nullptr;
8805     }
8806 }
8807 
8808 // XEnumeration
8809 
8810 sal_Bool SAL_CALL ScCellsEnumeration::hasMoreElements()
8811 {
8812     SolarMutexGuard aGuard;
8813     return !bAtEnd;
8814 }
8815 
8816 uno::Any SAL_CALL ScCellsEnumeration::nextElement()
8817 {
8818     SolarMutexGuard aGuard;
8819     if (pDocShell && !bAtEnd)
8820     {
8821         // interface must match ScCellsObj::getElementType
8822 
8823         ScAddress aTempPos(aPos);
8824         Advance_Impl();
8825         return uno::makeAny(uno::Reference<table::XCell>(new ScCellObj( pDocShell, aTempPos )));
8826     }
8827 
8828     throw container::NoSuchElementException();      // no more elements
8829 }
8830 
8831 ScCellFormatsObj::ScCellFormatsObj(ScDocShell* pDocSh, const ScRange& rRange) :
8832     pDocShell( pDocSh ),
8833     aTotalRange( rRange )
8834 {
8835     ScDocument& rDoc = pDocShell->GetDocument();
8836     rDoc.AddUnoObject(*this);
8837 
8838     OSL_ENSURE( aTotalRange.aStart.Tab() == aTotalRange.aEnd.Tab(), "different tables" );
8839 }
8840 
8841 ScCellFormatsObj::~ScCellFormatsObj()
8842 {
8843     SolarMutexGuard g;
8844 
8845     if (pDocShell)
8846         pDocShell->GetDocument().RemoveUnoObject(*this);
8847 }
8848 
8849 void ScCellFormatsObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
8850 {
8851     if ( dynamic_cast<const ScUpdateRefHint*>(&rHint) )
8852     {
8853         //! aTotalRange...
8854     }
8855     else if ( rHint.GetId() == SfxHintId::Dying )
8856     {
8857         pDocShell = nullptr;
8858     }
8859 }
8860 
8861 ScCellRangeObj* ScCellFormatsObj::GetObjectByIndex_Impl(tools::Long nIndex) const
8862 {
8863     //! access the AttrArrays directly !!!!
8864 
8865     ScCellRangeObj* pRet = nullptr;
8866     if (pDocShell)
8867     {
8868         ScDocument& rDoc = pDocShell->GetDocument();
8869         tools::Long nPos = 0;
8870         ScAttrRectIterator aIter( rDoc, aTotalRange.aStart.Tab(),
8871                                     aTotalRange.aStart.Col(), aTotalRange.aStart.Row(),
8872                                     aTotalRange.aEnd.Col(), aTotalRange.aEnd.Row() );
8873         SCCOL nCol1, nCol2;
8874         SCROW nRow1, nRow2;
8875         while ( aIter.GetNext( nCol1, nCol2, nRow1, nRow2 ) )
8876         {
8877             if ( nPos == nIndex )
8878             {
8879                 SCTAB nTab = aTotalRange.aStart.Tab();
8880                 ScRange aNext( nCol1, nRow1, nTab, nCol2, nRow2, nTab );
8881 
8882                 if ( aNext.aStart == aNext.aEnd )
8883                     pRet = new ScCellObj( pDocShell, aNext.aStart );
8884                 else
8885                     pRet = new ScCellRangeObj( pDocShell, aNext );
8886             }
8887             ++nPos;
8888         }
8889     }
8890     return pRet;
8891 }
8892 
8893 // XIndexAccess
8894 
8895 sal_Int32 SAL_CALL ScCellFormatsObj::getCount()
8896 {
8897     SolarMutexGuard aGuard;
8898 
8899     //! access the AttrArrays directly !!!!
8900 
8901     tools::Long nCount = 0;
8902     if (pDocShell)
8903     {
8904         ScDocument& rDoc = pDocShell->GetDocument();
8905         ScAttrRectIterator aIter( rDoc, aTotalRange.aStart.Tab(),
8906                                     aTotalRange.aStart.Col(), aTotalRange.aStart.Row(),
8907                                     aTotalRange.aEnd.Col(), aTotalRange.aEnd.Row() );
8908         SCCOL nCol1, nCol2;
8909         SCROW nRow1, nRow2;
8910         while ( aIter.GetNext( nCol1, nCol2, nRow1, nRow2 ) )
8911             ++nCount;
8912     }
8913     return nCount;
8914 }
8915 
8916 uno::Any SAL_CALL ScCellFormatsObj::getByIndex( sal_Int32 nIndex )
8917 {
8918     SolarMutexGuard aGuard;
8919 
8920     uno::Reference<table::XCellRange> xRange(GetObjectByIndex_Impl(nIndex));
8921     if (!xRange.is())
8922         throw lang::IndexOutOfBoundsException();
8923 
8924     return uno::makeAny(xRange);
8925 
8926 }
8927 
8928 uno::Type SAL_CALL ScCellFormatsObj::getElementType()
8929 {
8930     SolarMutexGuard aGuard;
8931     return cppu::UnoType<table::XCellRange>::get();
8932 }
8933 
8934 sal_Bool SAL_CALL ScCellFormatsObj::hasElements()
8935 {
8936     SolarMutexGuard aGuard;
8937     return ( getCount() != 0 );     //! always greater then zero ??
8938 }
8939 
8940 // XEnumerationAccess
8941 
8942 uno::Reference<container::XEnumeration> SAL_CALL ScCellFormatsObj::createEnumeration()
8943 {
8944     SolarMutexGuard aGuard;
8945     if (pDocShell)
8946         return new ScCellFormatsEnumeration( pDocShell, aTotalRange );
8947     return nullptr;
8948 }
8949 
8950 ScCellFormatsEnumeration::ScCellFormatsEnumeration(ScDocShell* pDocSh, const ScRange& rRange) :
8951     pDocShell( pDocSh ),
8952     nTab( rRange.aStart.Tab() ),
8953     bAtEnd( false ),
8954     bDirty( false )
8955 {
8956     ScDocument& rDoc = pDocShell->GetDocument();
8957     rDoc.AddUnoObject(*this);
8958 
8959     OSL_ENSURE( rRange.aStart.Tab() == rRange.aEnd.Tab(),
8960                 "CellFormatsEnumeration: different tables" );
8961 
8962     pIter.reset( new ScAttrRectIterator( rDoc, nTab,
8963                                     rRange.aStart.Col(), rRange.aStart.Row(),
8964                                     rRange.aEnd.Col(), rRange.aEnd.Row() ) );
8965     Advance_Impl();
8966 }
8967 
8968 ScCellFormatsEnumeration::~ScCellFormatsEnumeration()
8969 {
8970     SolarMutexGuard g;
8971 
8972     if (pDocShell)
8973         pDocShell->GetDocument().RemoveUnoObject(*this);
8974 }
8975 
8976 void ScCellFormatsEnumeration::Advance_Impl()
8977 {
8978     OSL_ENSURE(!bAtEnd,"too many Advance_Impl");
8979 
8980     if ( pIter )
8981     {
8982         if ( bDirty )
8983         {
8984             pIter->DataChanged();   // new search for AttrArray-Index
8985             bDirty = false;
8986         }
8987 
8988         SCCOL nCol1, nCol2;
8989         SCROW nRow1, nRow2;
8990         if ( pIter->GetNext( nCol1, nCol2, nRow1, nRow2 ) )
8991             aNext = ScRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab );
8992         else
8993             bAtEnd = true;
8994     }
8995     else
8996         bAtEnd = true;          // document vanished or so
8997 }
8998 
8999 ScCellRangeObj* ScCellFormatsEnumeration::NextObject_Impl()
9000 {
9001     ScCellRangeObj* pRet = nullptr;
9002     if (pDocShell && !bAtEnd)
9003     {
9004         if ( aNext.aStart == aNext.aEnd )
9005             pRet = new ScCellObj( pDocShell, aNext.aStart );
9006         else
9007             pRet = new ScCellRangeObj( pDocShell, aNext );
9008         Advance_Impl();
9009     }
9010     return pRet;
9011 }
9012 
9013 void ScCellFormatsEnumeration::Notify( SfxBroadcaster&, const SfxHint& rHint )
9014 {
9015     if ( dynamic_cast<const ScUpdateRefHint*>(&rHint) )
9016     {
9017         //! and now???
9018     }
9019     else
9020     {
9021         const SfxHintId nId = rHint.GetId();
9022         if ( nId == SfxHintId::Dying )
9023         {
9024             pDocShell = nullptr;
9025             pIter.reset();
9026         }
9027         else if ( nId == SfxHintId::DataChanged )
9028         {
9029             bDirty = true;          // AttrArray-Index possibly invalid
9030         }
9031     }
9032 }
9033 
9034 // XEnumeration
9035 
9036 sal_Bool SAL_CALL ScCellFormatsEnumeration::hasMoreElements()
9037 {
9038     SolarMutexGuard aGuard;
9039     return !bAtEnd;
9040 }
9041 
9042 uno::Any SAL_CALL ScCellFormatsEnumeration::nextElement()
9043 {
9044     SolarMutexGuard aGuard;
9045 
9046     if ( bAtEnd || !pDocShell )
9047         throw container::NoSuchElementException();      // no more elements
9048 
9049     // interface must match ScCellFormatsObj::getElementType
9050 
9051     return uno::makeAny(uno::Reference<table::XCellRange> (NextObject_Impl()));
9052 }
9053 
9054 ScUniqueCellFormatsObj::~ScUniqueCellFormatsObj()
9055 {
9056     SolarMutexGuard g;
9057 
9058     if (pDocShell)
9059         pDocShell->GetDocument().RemoveUnoObject(*this);
9060 }
9061 
9062 void ScUniqueCellFormatsObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
9063 {
9064     if ( dynamic_cast<const ScUpdateRefHint*>(&rHint) )
9065     {
9066         //! aTotalRange...
9067     }
9068     else
9069     {
9070         if ( rHint.GetId() == SfxHintId::Dying )
9071             pDocShell = nullptr;
9072     }
9073 }
9074 
9075 //  Fill the list of formats from the document
9076 
9077 namespace {
9078 
9079 // hash code to access the range lists by ScPatternAttr pointer
9080 struct ScPatternHashCode
9081 {
9082     size_t operator()( const ScPatternAttr* pPattern ) const
9083     {
9084         return reinterpret_cast<size_t>(pPattern);
9085     }
9086 };
9087 
9088 }
9089 
9090 // Hash map to find a range by its start row
9091 typedef std::unordered_map< SCROW, ScRange > ScRowRangeHashMap;
9092 
9093 namespace {
9094 
9095 // Hash map entry.
9096 // The Join method depends on the column-wise order of ScAttrRectIterator
9097 class ScUniqueFormatsEntry
9098 {
9099     enum EntryState { STATE_EMPTY, STATE_SINGLE, STATE_COMPLEX };
9100 
9101     EntryState          eState;
9102     ScRange             aSingleRange;
9103     ScRowRangeHashMap   aJoinedRanges;      // "active" ranges to be merged
9104     std::vector<ScRange> aCompletedRanges;   // ranges that will no longer be touched
9105     ScRangeListRef      aReturnRanges;      // result as ScRangeList for further use
9106 
9107 public:
9108                         ScUniqueFormatsEntry() : eState( STATE_EMPTY ) {}
9109 
9110     void                Join( const ScRange& rNewRange );
9111     const ScRangeList&  GetRanges();
9112     void                Clear() { aReturnRanges.clear(); }  // aJoinedRanges and aCompletedRanges are cleared in GetRanges
9113 };
9114 
9115 }
9116 
9117 void ScUniqueFormatsEntry::Join( const ScRange& rNewRange )
9118 {
9119     // Special-case handling for single range
9120 
9121     if ( eState == STATE_EMPTY )
9122     {
9123         aSingleRange = rNewRange;
9124         eState = STATE_SINGLE;
9125         return;
9126     }
9127     if ( eState == STATE_SINGLE )
9128     {
9129         if ( aSingleRange.aStart.Row() == rNewRange.aStart.Row() &&
9130              aSingleRange.aEnd.Row() == rNewRange.aEnd.Row() &&
9131              aSingleRange.aEnd.Col() + 1 == rNewRange.aStart.Col() )
9132         {
9133             aSingleRange.aEnd.SetCol( rNewRange.aEnd.Col() );
9134             return;     // still a single range
9135         }
9136 
9137         SCROW nSingleRow = aSingleRange.aStart.Row();
9138         aJoinedRanges.emplace( nSingleRow, aSingleRange );
9139         eState = STATE_COMPLEX;
9140         // continue normally
9141     }
9142 
9143     // This is called in the order of ScAttrRectIterator results.
9144     // rNewRange can only be joined with an existing entry if it's the same rows, starting in the next column.
9145     // If the old entry for the start row extends to a different end row, or ends in a different column, it
9146     // can be moved to aCompletedRanges because it can't be joined with following iterator results.
9147     // Everything happens within one sheet, so Tab can be ignored.
9148 
9149     SCROW nStartRow = rNewRange.aStart.Row();
9150     ScRowRangeHashMap::iterator aIter( aJoinedRanges.find( nStartRow ) );       // find the active entry for the start row
9151     if ( aIter != aJoinedRanges.end() )
9152     {
9153         ScRange& rOldRange = aIter->second;
9154         if ( rOldRange.aEnd.Row() == rNewRange.aEnd.Row() &&
9155              rOldRange.aEnd.Col() + 1 == rNewRange.aStart.Col() )
9156         {
9157             // extend existing range
9158             rOldRange.aEnd.SetCol( rNewRange.aEnd.Col() );
9159         }
9160         else
9161         {
9162             // move old range to aCompletedRanges, keep rNewRange for joining
9163             aCompletedRanges.push_back( rOldRange );
9164             rOldRange = rNewRange;  // replace in hash map
9165         }
9166     }
9167     else
9168     {
9169         // keep rNewRange for joining
9170         aJoinedRanges.emplace( nStartRow, rNewRange );
9171     }
9172 }
9173 
9174 const ScRangeList& ScUniqueFormatsEntry::GetRanges()
9175 {
9176     if ( eState == STATE_SINGLE )
9177     {
9178         aReturnRanges = new ScRangeList( aSingleRange );
9179         return *aReturnRanges;
9180     }
9181 
9182     // move remaining entries from aJoinedRanges to aCompletedRanges
9183 
9184     for ( const auto& rEntry : aJoinedRanges )
9185         aCompletedRanges.push_back( rEntry.second );
9186     aJoinedRanges.clear();
9187 
9188     // sort all ranges for a predictable API result
9189 
9190     std::sort( aCompletedRanges.begin(), aCompletedRanges.end() );
9191 
9192     // fill and return ScRangeList
9193 
9194     aReturnRanges = new ScRangeList;
9195     for ( const auto& rCompletedRange : aCompletedRanges )
9196         aReturnRanges->push_back( rCompletedRange );
9197     aCompletedRanges.clear();
9198 
9199     return *aReturnRanges;
9200 }
9201 
9202 typedef std::unordered_map< const ScPatternAttr*, ScUniqueFormatsEntry, ScPatternHashCode > ScUniqueFormatsHashMap;
9203 
9204 namespace {
9205 
9206 // function object to sort the range lists by start of first range
9207 struct ScUniqueFormatsOrder
9208 {
9209     bool operator()( const ScRangeList& rList1, const ScRangeList& rList2 ) const
9210     {
9211         // all range lists have at least one entry
9212         OSL_ENSURE( !rList1.empty() && !rList2.empty(), "ScUniqueFormatsOrder: empty list" );
9213 
9214         // compare start positions using ScAddress comparison operator
9215         return ( rList1[ 0 ].aStart < rList2[ 0 ].aStart );
9216     }
9217 };
9218 
9219 }
9220 
9221 ScUniqueCellFormatsObj::ScUniqueCellFormatsObj(ScDocShell* pDocSh, const ScRange& rTotalRange) :
9222     pDocShell( pDocSh ),
9223     aRangeLists()
9224 {
9225     pDocShell->GetDocument().AddUnoObject(*this);
9226 
9227     OSL_ENSURE( rTotalRange.aStart.Tab() == rTotalRange.aEnd.Tab(), "different tables" );
9228 
9229     ScDocument& rDoc = pDocShell->GetDocument();
9230     SCTAB nTab = rTotalRange.aStart.Tab();
9231     ScAttrRectIterator aIter( rDoc, nTab,
9232                                 rTotalRange.aStart.Col(), rTotalRange.aStart.Row(),
9233                                 rTotalRange.aEnd.Col(), rTotalRange.aEnd.Row() );
9234     SCCOL nCol1, nCol2;
9235     SCROW nRow1, nRow2;
9236 
9237     // Collect the ranges for each format in a hash map, to avoid nested loops
9238 
9239     ScUniqueFormatsHashMap aHashMap;
9240     while (aIter.GetNext( nCol1, nCol2, nRow1, nRow2 ) )
9241     {
9242         ScRange aRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab );
9243         const ScPatternAttr* pPattern = rDoc.GetPattern(nCol1, nRow1, nTab);
9244         aHashMap[pPattern].Join( aRange );
9245     }
9246 
9247     // Fill the vector aRangeLists with the range lists from the hash map
9248 
9249     aRangeLists.reserve( aHashMap.size() );
9250     for ( auto& rMapEntry : aHashMap )
9251     {
9252         ScUniqueFormatsEntry& rEntry = rMapEntry.second;
9253         const ScRangeList& rRanges = rEntry.GetRanges();
9254         aRangeLists.push_back( rRanges );       // copy ScRangeList
9255         rEntry.Clear();                         // free memory, don't hold both copies of all ranges
9256     }
9257 
9258     // Sort the vector by first range's start position, to avoid random shuffling
9259     // due to using the ScPatterAttr pointers
9260 
9261     ::std::sort( aRangeLists.begin(), aRangeLists.end(), ScUniqueFormatsOrder() );
9262 }
9263 
9264 
9265 // XIndexAccess
9266 
9267 sal_Int32 SAL_CALL ScUniqueCellFormatsObj::getCount()
9268 {
9269     SolarMutexGuard aGuard;
9270 
9271     return aRangeLists.size();
9272 }
9273 
9274 uno::Any SAL_CALL ScUniqueCellFormatsObj::getByIndex( sal_Int32 nIndex )
9275 {
9276     SolarMutexGuard aGuard;
9277 
9278     if(o3tl::make_unsigned(nIndex) >= aRangeLists.size())
9279         throw lang::IndexOutOfBoundsException();
9280 
9281     return uno::makeAny(uno::Reference<sheet::XSheetCellRangeContainer>(new ScCellRangesObj(pDocShell, aRangeLists[nIndex])));
9282 
9283 }
9284 
9285 uno::Type SAL_CALL ScUniqueCellFormatsObj::getElementType()
9286 {
9287     SolarMutexGuard aGuard;
9288     return cppu::UnoType<sheet::XSheetCellRangeContainer>::get();
9289 }
9290 
9291 sal_Bool SAL_CALL ScUniqueCellFormatsObj::hasElements()
9292 {
9293     SolarMutexGuard aGuard;
9294     return ( !aRangeLists.empty() );
9295 }
9296 
9297 // XEnumerationAccess
9298 
9299 uno::Reference<container::XEnumeration> SAL_CALL ScUniqueCellFormatsObj::createEnumeration()
9300 {
9301     SolarMutexGuard aGuard;
9302     if (pDocShell)
9303         return new ScUniqueCellFormatsEnumeration( pDocShell, aRangeLists );
9304     return nullptr;
9305 }
9306 
9307 ScUniqueCellFormatsEnumeration::ScUniqueCellFormatsEnumeration(ScDocShell* pDocSh, const std::vector<ScRangeList>& rRangeLists) :
9308     aRangeLists(rRangeLists),
9309     pDocShell( pDocSh ),
9310     nCurrentPosition(0)
9311 {
9312     pDocShell->GetDocument().AddUnoObject(*this);
9313 }
9314 
9315 ScUniqueCellFormatsEnumeration::~ScUniqueCellFormatsEnumeration()
9316 {
9317     SolarMutexGuard g;
9318 
9319     if (pDocShell)
9320         pDocShell->GetDocument().RemoveUnoObject(*this);
9321 }
9322 
9323 void ScUniqueCellFormatsEnumeration::Notify( SfxBroadcaster&, const SfxHint& rHint )
9324 {
9325     if ( dynamic_cast<const ScUpdateRefHint*>(&rHint) )
9326     {
9327         //! and now ???
9328     }
9329     else
9330     {
9331         if ( rHint.GetId() == SfxHintId::Dying )
9332             pDocShell = nullptr;
9333     }
9334 }
9335 
9336 // XEnumeration
9337 
9338 sal_Bool SAL_CALL ScUniqueCellFormatsEnumeration::hasMoreElements()
9339 {
9340     SolarMutexGuard aGuard;
9341     return o3tl::make_unsigned(nCurrentPosition) < aRangeLists.size();
9342 }
9343 
9344 uno::Any SAL_CALL ScUniqueCellFormatsEnumeration::nextElement()
9345 {
9346     SolarMutexGuard aGuard;
9347 
9348     if ( !hasMoreElements() || !pDocShell )
9349         throw container::NoSuchElementException();      // no more elements
9350 
9351     // interface type must match ScCellFormatsObj::getElementType
9352 
9353     return uno::makeAny(uno::Reference<sheet::XSheetCellRangeContainer>(new ScCellRangesObj(pDocShell, aRangeLists[nCurrentPosition++])));
9354 }
9355 
9356 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
9357