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