xref: /core/sc/source/ui/unoobj/cellsuno.cxx (revision c3d5c9a0)
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.meType;
1333     if (eType == CELLTYPE_FORMULA)
1334     {
1335         ScFormulaCell* pForm = aCell.mpFormula;
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.mpEditText;
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             aMarkData.MarkToMulti();        // needed for IsAllMarked
3661 
3662             for (size_t nR = 0, nCount = aNewRanges.size(); nR<nCount; ++nR)
3663             {
3664                 ScRange const & rRange = aNewRanges[ nR];
3665                 ScCellIterator aIter(rDoc, rRange);
3666                 for (bool bHasCell = aIter.first(); bHasCell; bHasCell = aIter.next())
3667                 {
3668                     if (aIter.getType() != CELLTYPE_FORMULA)
3669                         continue;
3670 
3671                     ScDetectiveRefIter aRefIter(rDoc, aIter.getFormulaCell());
3672                     ScRange aRefRange;
3673                     while ( aRefIter.GetNextRef( aRefRange) )
3674                     {
3675                         if ( bRecursive && !bFound && !aMarkData.IsAllMarked( aRefRange ) )
3676                             bFound = true;
3677                         aMarkData.SetMultiMarkArea(aRefRange);
3678                     }
3679                 }
3680             }
3681 
3682             aMarkData.FillRangeListWithMarks( &aNewRanges, true );
3683         }
3684         while ( bRecursive && bFound );
3685 
3686         return new ScCellRangesObj( pDocShell, aNewRanges );
3687     }
3688 
3689     return nullptr;
3690 }
3691 
3692 uno::Reference<sheet::XSheetCellRanges> SAL_CALL ScCellRangesBase::queryDependents(
3693     sal_Bool bRecursive )
3694 {
3695     SolarMutexGuard aGuard;
3696     if ( pDocShell )
3697     {
3698         ScDocument& rDoc = pDocShell->GetDocument();
3699 
3700         ScRangeList aNewRanges(aRanges);
3701         bool bFound;
3702         do
3703         {
3704             bFound = false;
3705 
3706             //  aMarkData uses aNewRanges, not aRanges, so GetMarkData can't be used
3707             ScMarkData aMarkData(rDoc.GetSheetLimits());
3708             aMarkData.MarkFromRangeList( aNewRanges, false );
3709             aMarkData.MarkToMulti();        // needed for IsAllMarked
3710 
3711             SCTAB nTab = lcl_FirstTab(aNewRanges);              //! all tables
3712 
3713             ScCellIterator aCellIter( rDoc, ScRange(0, 0, nTab, rDoc.MaxCol(), rDoc.MaxRow(), nTab) );
3714             for (bool bHasCell = aCellIter.first(); bHasCell; bHasCell = aCellIter.next())
3715             {
3716                 if (aCellIter.getType() != CELLTYPE_FORMULA)
3717                     continue;
3718 
3719                 bool bMark = false;
3720                 ScDetectiveRefIter aIter(rDoc, aCellIter.getFormulaCell());
3721                 ScRange aRefRange;
3722                 while ( aIter.GetNextRef( aRefRange) && !bMark )
3723                 {
3724                     size_t nRangesCount = aNewRanges.size();
3725                     for (size_t nR = 0; nR < nRangesCount; ++nR)
3726                     {
3727                         ScRange const & rRange = aNewRanges[ nR ];
3728                         if (rRange.Intersects(aRefRange))
3729                         {
3730                             bMark = true;                   // depending on part of Range
3731                             break;
3732                         }
3733                     }
3734                 }
3735                 if (bMark)
3736                 {
3737                     ScRange aCellRange(aCellIter.GetPos());
3738                     if ( bRecursive && !bFound && !aMarkData.IsAllMarked( aCellRange ) )
3739                         bFound = true;
3740                     aMarkData.SetMultiMarkArea(aCellRange);
3741                 }
3742             }
3743 
3744             aMarkData.FillRangeListWithMarks( &aNewRanges, true );
3745         }
3746         while ( bRecursive && bFound );
3747 
3748         return new ScCellRangesObj( pDocShell, aNewRanges );
3749     }
3750 
3751     return nullptr;
3752 }
3753 
3754 // XSearchable
3755 
3756 uno::Reference<util::XSearchDescriptor> SAL_CALL ScCellRangesBase::createSearchDescriptor()
3757 {
3758     SolarMutexGuard aGuard;
3759     return new ScCellSearchObj;
3760 }
3761 
3762 uno::Reference<container::XIndexAccess> SAL_CALL ScCellRangesBase::findAll(
3763                         const uno::Reference<util::XSearchDescriptor>& xDesc )
3764 {
3765     SolarMutexGuard aGuard;
3766     //  should we return Null if nothing is found(?)
3767     uno::Reference<container::XIndexAccess> xRet;
3768     if ( pDocShell && xDesc.is() )
3769     {
3770         ScCellSearchObj* pSearch = comphelper::getFromUnoTunnel<ScCellSearchObj>( xDesc );
3771         if (pSearch)
3772         {
3773             SvxSearchItem* pSearchItem = pSearch->GetSearchItem();
3774             if (pSearchItem)
3775             {
3776                 ScDocument& rDoc = pDocShell->GetDocument();
3777                 pSearchItem->SetCommand( SvxSearchCmd::FIND_ALL );
3778                 //  always only within this object
3779                 pSearchItem->SetSelection( !lcl_WholeSheet(rDoc, aRanges) );
3780 
3781                 ScMarkData aMark(*GetMarkData());
3782 
3783                 OUString aDummyUndo;
3784                 ScRangeList aMatchedRanges;
3785                 SCCOL nCol = 0;
3786                 SCROW nRow = 0;
3787                 SCTAB nTab = 0;
3788                 bool bFound = rDoc.SearchAndReplace(
3789                     *pSearchItem, nCol, nRow, nTab, aMark, aMatchedRanges, aDummyUndo);
3790                 if (bFound)
3791                 {
3792                     //  on findAll always CellRanges no matter how much has been found
3793                     xRet.set(new ScCellRangesObj( pDocShell, aMatchedRanges ));
3794                 }
3795             }
3796         }
3797     }
3798     return xRet;
3799 }
3800 
3801 uno::Reference<uno::XInterface> ScCellRangesBase::Find_Impl(
3802                                     const uno::Reference<util::XSearchDescriptor>& xDesc,
3803                                     const ScAddress* pLastPos )
3804 {
3805     uno::Reference<uno::XInterface> xRet;
3806     if ( pDocShell && xDesc.is() )
3807     {
3808         ScCellSearchObj* pSearch = comphelper::getFromUnoTunnel<ScCellSearchObj>( xDesc );
3809         if (pSearch)
3810         {
3811             SvxSearchItem* pSearchItem = pSearch->GetSearchItem();
3812             if (pSearchItem)
3813             {
3814                 ScDocument& rDoc = pDocShell->GetDocument();
3815                 pSearchItem->SetCommand( SvxSearchCmd::FIND );
3816                 //  only always in this object
3817                 pSearchItem->SetSelection( !lcl_WholeSheet(rDoc, aRanges) );
3818 
3819                 ScMarkData aMark(*GetMarkData());
3820 
3821                 SCCOL nCol;
3822                 SCROW nRow;
3823                 SCTAB nTab;
3824                 if (pLastPos)
3825                     pLastPos->GetVars( nCol, nRow, nTab );
3826                 else
3827                 {
3828                     nTab = lcl_FirstTab(aRanges);   //! multiple sheets?
3829                     rDoc.GetSearchAndReplaceStart( *pSearchItem, nCol, nRow );
3830                 }
3831 
3832                 OUString aDummyUndo;
3833                 ScRangeList aMatchedRanges;
3834                 bool bFound = rDoc.SearchAndReplace(
3835                     *pSearchItem, nCol, nRow, nTab, aMark, aMatchedRanges, aDummyUndo);
3836                 if (bFound)
3837                 {
3838                     ScAddress aFoundPos( nCol, nRow, nTab );
3839                     xRet.set(static_cast<cppu::OWeakObject*>(new ScCellObj( pDocShell, aFoundPos )));
3840                 }
3841             }
3842         }
3843     }
3844     return xRet;
3845 }
3846 
3847 uno::Reference<uno::XInterface> SAL_CALL ScCellRangesBase::findFirst(
3848                         const uno::Reference<util::XSearchDescriptor>& xDesc )
3849 {
3850     SolarMutexGuard aGuard;
3851     return Find_Impl( xDesc, nullptr );
3852 }
3853 
3854 uno::Reference<uno::XInterface> SAL_CALL ScCellRangesBase::findNext(
3855                         const uno::Reference<uno::XInterface>& xStartAt,
3856                         const uno::Reference<util::XSearchDescriptor >& xDesc )
3857 {
3858     SolarMutexGuard aGuard;
3859     if ( xStartAt.is() )
3860     {
3861         ScCellRangesBase* pRangesImp = comphelper::getFromUnoTunnel<ScCellRangesBase>( xStartAt );
3862         if ( pRangesImp && pRangesImp->GetDocShell() == pDocShell )
3863         {
3864             const ScRangeList& rStartRanges = pRangesImp->GetRangeList();
3865             if ( rStartRanges.size() == 1 )
3866             {
3867                 ScAddress aStartPos = rStartRanges[ 0 ].aStart;
3868                 return Find_Impl( xDesc, &aStartPos );
3869             }
3870         }
3871     }
3872     return nullptr;
3873 }
3874 
3875 // XReplaceable
3876 
3877 uno::Reference<util::XReplaceDescriptor> SAL_CALL ScCellRangesBase::createReplaceDescriptor()
3878 {
3879     SolarMutexGuard aGuard;
3880     return new ScCellSearchObj;
3881 }
3882 
3883 sal_Int32 SAL_CALL ScCellRangesBase::replaceAll( const uno::Reference<util::XSearchDescriptor>& xDesc )
3884 {
3885     SolarMutexGuard aGuard;
3886     sal_Int32 nReplaced = 0;
3887     if ( pDocShell && xDesc.is() )
3888     {
3889         ScCellSearchObj* pSearch = comphelper::getFromUnoTunnel<ScCellSearchObj>( xDesc );
3890         if (pSearch)
3891         {
3892             SvxSearchItem* pSearchItem = pSearch->GetSearchItem();
3893             if (pSearchItem)
3894             {
3895                 ScDocument& rDoc = pDocShell->GetDocument();
3896                 bool bUndo(rDoc.IsUndoEnabled());
3897                 pSearchItem->SetCommand( SvxSearchCmd::REPLACE_ALL );
3898                 //  only always in this object
3899                 pSearchItem->SetSelection( !lcl_WholeSheet(rDoc, aRanges) );
3900 
3901                 ScMarkData aMark(*GetMarkData());
3902 
3903                 SCTAB nTabCount = rDoc.GetTableCount();
3904                 bool bProtected = !pDocShell->IsEditable();
3905                 for (const auto& rTab : aMark)
3906                 {
3907                     if (rTab >= nTabCount)
3908                         break;
3909                     if ( rDoc.IsTabProtected(rTab) )
3910                         bProtected = true;
3911                 }
3912                 if (bProtected)
3913                 {
3914                     //! Exception, or what?
3915                 }
3916                 else
3917                 {
3918                     SCTAB nTab = aMark.GetFirstSelected();      // do not use if SearchAndReplace
3919                     SCCOL nCol = 0;
3920                     SCROW nRow = 0;
3921 
3922                     OUString aUndoStr;
3923                     ScDocumentUniquePtr pUndoDoc;
3924                     if (bUndo)
3925                     {
3926                         pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
3927                         pUndoDoc->InitUndo( rDoc, nTab, nTab );
3928                     }
3929                     for (const auto& rTab : aMark)
3930                     {
3931                         if (rTab >= nTabCount)
3932                             break;
3933                         if (rTab != nTab && bUndo)
3934                             pUndoDoc->AddUndoTab( rTab, rTab );
3935                     }
3936                     std::unique_ptr<ScMarkData> pUndoMark;
3937                     if (bUndo)
3938                         pUndoMark.reset(new ScMarkData(aMark));
3939 
3940                     bool bFound = false;
3941                     if (bUndo)
3942                     {
3943                         ScRangeList aMatchedRanges;
3944                         bFound = rDoc.SearchAndReplace(
3945                             *pSearchItem, nCol, nRow, nTab, aMark, aMatchedRanges, aUndoStr, pUndoDoc.get() );
3946                     }
3947                     if (bFound)
3948                     {
3949                         nReplaced = pUndoDoc->GetCellCount();
3950 
3951                         pDocShell->GetUndoManager()->AddUndoAction(
3952                             std::make_unique<ScUndoReplace>( pDocShell, *pUndoMark, nCol, nRow, nTab,
3953                                                         aUndoStr, std::move(pUndoDoc), pSearchItem ) );
3954 
3955                         pDocShell->PostPaintGridAll();
3956                         pDocShell->SetDocumentModified();
3957                     }
3958                 }
3959             }
3960         }
3961     }
3962     return nReplaced;
3963 }
3964 
3965 // XUnoTunnel
3966 
3967 UNO3_GETIMPLEMENTATION_IMPL(ScCellRangesBase);
3968 
3969 ScCellRangesObj::ScCellRangesObj(ScDocShell* pDocSh, const ScRangeList& rR)
3970     : ScCellRangesBase(pDocSh, rR)
3971 {
3972 }
3973 
3974 ScCellRangesObj::~ScCellRangesObj()
3975 {
3976 }
3977 
3978 void ScCellRangesObj::RefChanged()
3979 {
3980     ScCellRangesBase::RefChanged();
3981 }
3982 
3983 uno::Any SAL_CALL ScCellRangesObj::queryInterface( const uno::Type& rType )
3984 {
3985     SC_QUERYINTERFACE( sheet::XSheetCellRangeContainer )
3986     SC_QUERYINTERFACE( sheet::XSheetCellRanges )
3987     SC_QUERYINTERFACE( container::XIndexAccess )
3988     SC_QUERY_MULTIPLE( container::XElementAccess, container::XIndexAccess )
3989     SC_QUERYINTERFACE( container::XEnumerationAccess )
3990     SC_QUERYINTERFACE( container::XNameContainer )
3991     SC_QUERYINTERFACE( container::XNameReplace )
3992     SC_QUERYINTERFACE( container::XNameAccess )
3993 
3994     return ScCellRangesBase::queryInterface( rType );
3995 }
3996 
3997 void SAL_CALL ScCellRangesObj::acquire() noexcept
3998 {
3999     ScCellRangesBase::acquire();
4000 }
4001 
4002 void SAL_CALL ScCellRangesObj::release() noexcept
4003 {
4004     ScCellRangesBase::release();
4005 }
4006 
4007 uno::Sequence<uno::Type> SAL_CALL ScCellRangesObj::getTypes()
4008 {
4009     static const uno::Sequence<uno::Type> aTypes = comphelper::concatSequences(
4010         ScCellRangesBase::getTypes(),
4011         uno::Sequence<uno::Type>
4012         {
4013             cppu::UnoType<sheet::XSheetCellRangeContainer>::get(),
4014             cppu::UnoType<container::XNameContainer>::get(),
4015             cppu::UnoType<container::XEnumerationAccess>::get()
4016         } );
4017     return aTypes;
4018 }
4019 
4020 uno::Sequence<sal_Int8> SAL_CALL ScCellRangesObj::getImplementationId()
4021 {
4022     return css::uno::Sequence<sal_Int8>();
4023 }
4024 
4025 // XCellRanges
4026 
4027 rtl::Reference<ScCellRangeObj> ScCellRangesObj::GetObjectByIndex_Impl(sal_Int32 nIndex) const
4028 {
4029     ScDocShell* pDocSh = GetDocShell();
4030     const ScRangeList& rRanges = GetRangeList();
4031     if ( pDocSh && nIndex >= 0 && nIndex < sal::static_int_cast<sal_Int32>(rRanges.size()) )
4032     {
4033         ScRange const & rRange = rRanges[ nIndex ];
4034         if ( rRange.aStart == rRange.aEnd )
4035             return new ScCellObj( pDocSh, rRange.aStart );
4036         else
4037             return new ScCellRangeObj( pDocSh, rRange );
4038     }
4039 
4040     return nullptr;        // no DocShell or wrong index
4041 }
4042 
4043 uno::Sequence<table::CellRangeAddress> SAL_CALL ScCellRangesObj::getRangeAddresses()
4044 {
4045     SolarMutexGuard aGuard;
4046     ScDocShell* pDocSh = GetDocShell();
4047     const ScRangeList& rRanges = GetRangeList();
4048     size_t nCount = rRanges.size();
4049     if ( pDocSh && nCount )
4050     {
4051         table::CellRangeAddress aRangeAddress;
4052         uno::Sequence<table::CellRangeAddress> aSeq(nCount);
4053         table::CellRangeAddress* pAry = aSeq.getArray();
4054         for ( size_t i=0; i < nCount; i++)
4055         {
4056             ScUnoConversion::FillApiRange( aRangeAddress, rRanges[ i ] );
4057             pAry[i] = aRangeAddress;
4058         }
4059         return aSeq;
4060     }
4061 
4062     return {};   // can be empty
4063 }
4064 
4065 uno::Reference<container::XEnumerationAccess> SAL_CALL ScCellRangesObj::getCells()
4066 {
4067     SolarMutexGuard aGuard;
4068 
4069     //  getCells with empty range list is possible (no exception),
4070     //  the resulting enumeration just has no elements
4071     //  (same behaviour as a valid range with no cells)
4072     //  This is handled in ScCellsEnumeration ctor.
4073 
4074     const ScRangeList& rRanges = GetRangeList();
4075     ScDocShell* pDocSh = GetDocShell();
4076     if (pDocSh)
4077         return new ScCellsObj( pDocSh, rRanges );
4078     return nullptr;
4079 }
4080 
4081 OUString SAL_CALL ScCellRangesObj::getRangeAddressesAsString()
4082 {
4083     SolarMutexGuard aGuard;
4084     OUString aString;
4085     ScDocShell* pDocSh = GetDocShell();
4086     const ScRangeList& rRanges = GetRangeList();
4087     if (pDocSh)
4088         rRanges.Format( aString, ScRefFlags::VALID | ScRefFlags::TAB_3D, pDocSh->GetDocument() );
4089     return aString;
4090 }
4091 
4092 // XSheetCellRangeContainer
4093 
4094 void SAL_CALL ScCellRangesObj::addRangeAddress( const table::CellRangeAddress& rRange,
4095                                     sal_Bool bMergeRanges )
4096 {
4097     SolarMutexGuard aGuard;
4098     ScRange aRange(static_cast<SCCOL>(rRange.StartColumn),
4099             static_cast<SCROW>(rRange.StartRow),
4100             static_cast<SCTAB>(rRange.Sheet),
4101             static_cast<SCCOL>(rRange.EndColumn),
4102             static_cast<SCROW>(rRange.EndRow),
4103             static_cast<SCTAB>(rRange.Sheet));
4104     AddRange(aRange, bMergeRanges);
4105 }
4106 
4107 static void lcl_RemoveNamedEntry( std::vector<ScCellRangesObj::ScNamedEntry>& rNamedEntries, const ScRange& rRange )
4108 {
4109     sal_uInt16 nCount = rNamedEntries.size();
4110     for ( sal_uInt16 n=nCount; n--; )
4111         if ( rNamedEntries[n].GetRange() == rRange )
4112             rNamedEntries.erase( rNamedEntries.begin() + n );
4113 }
4114 
4115 void SAL_CALL ScCellRangesObj::removeRangeAddress( const table::CellRangeAddress& rRange )
4116 {
4117     SolarMutexGuard aGuard;
4118     const ScRangeList& rRanges = GetRangeList();
4119 
4120     ScRangeList aSheetRanges;
4121     ScRangeList aNotSheetRanges;
4122     for (size_t i = 0; i < rRanges.size(); ++i)
4123     {
4124         if (rRanges[ i].aStart.Tab() == rRange.Sheet)
4125         {
4126             aSheetRanges.push_back( rRanges[ i ] );
4127         }
4128         else
4129         {
4130             aNotSheetRanges.push_back( rRanges[ i ] );
4131         }
4132     }
4133     ScMarkData aMarkData(GetDocument()->GetSheetLimits());
4134     aMarkData.MarkFromRangeList( aSheetRanges, false );
4135     ScRange aRange(static_cast<SCCOL>(rRange.StartColumn),
4136                 static_cast<SCROW>(rRange.StartRow),
4137                 static_cast<SCTAB>(rRange.Sheet),
4138                 static_cast<SCCOL>(rRange.EndColumn),
4139                 static_cast<SCROW>(rRange.EndRow),
4140                 static_cast<SCTAB>(rRange.Sheet));
4141     if (aMarkData.GetTableSelect( aRange.aStart.Tab() ))
4142     {
4143         aMarkData.MarkToMulti();
4144         if (!aMarkData.IsAllMarked( aRange ) )
4145             throw container::NoSuchElementException();
4146 
4147         aMarkData.SetMultiMarkArea( aRange, false );
4148         lcl_RemoveNamedEntry(m_aNamedEntries, aRange);
4149 
4150     }
4151     SetNewRanges(aNotSheetRanges);
4152     ScRangeList aNew;
4153     aMarkData.FillRangeListWithMarks( &aNew, false );
4154     for ( size_t j = 0; j < aNew.size(); ++j)
4155     {
4156         AddRange(aNew[ j ], false);
4157     }
4158 }
4159 
4160 void SAL_CALL ScCellRangesObj::addRangeAddresses( const uno::Sequence<table::CellRangeAddress >& rRanges,
4161                                     sal_Bool bMergeRanges )
4162 {
4163     SolarMutexGuard aGuard;
4164     for (const table::CellRangeAddress& rRange : rRanges)
4165     {
4166         ScRange aRange(static_cast<SCCOL>(rRange.StartColumn),
4167                 static_cast<SCROW>(rRange.StartRow),
4168                 static_cast<SCTAB>(rRange.Sheet),
4169                 static_cast<SCCOL>(rRange.EndColumn),
4170                 static_cast<SCROW>(rRange.EndRow),
4171                 static_cast<SCTAB>(rRange.Sheet));
4172         AddRange(aRange, bMergeRanges);
4173     }
4174 }
4175 
4176 void SAL_CALL ScCellRangesObj::removeRangeAddresses( const uno::Sequence<table::CellRangeAddress >& rRangeSeq )
4177 {
4178     // use sometimes a better/faster implementation
4179     for (const table::CellRangeAddress& rRange : rRangeSeq)
4180     {
4181         removeRangeAddress(rRange);
4182     }
4183 }
4184 
4185 // XNameContainer
4186 
4187 static void lcl_RemoveNamedEntry( std::vector<ScCellRangesObj::ScNamedEntry>& rNamedEntries, std::u16string_view rName )
4188 {
4189     sal_uInt16 nCount = rNamedEntries.size();
4190     for ( sal_uInt16 n=nCount; n--; )
4191         if ( rNamedEntries[n].GetName() == rName )
4192             rNamedEntries.erase( rNamedEntries.begin() + n );
4193 }
4194 
4195 void SAL_CALL ScCellRangesObj::insertByName( const OUString& aName, const uno::Any& aElement )
4196 {
4197     SolarMutexGuard aGuard;
4198     ScDocShell* pDocSh = GetDocShell();
4199     bool bDone = false;
4200 
4201     //! Type of aElement can be some specific interface instead of XInterface
4202 
4203     uno::Reference<uno::XInterface> xInterface(aElement, uno::UNO_QUERY);
4204     if ( pDocSh && xInterface.is() )
4205     {
4206         ScCellRangesBase* pRangesImp = comphelper::getFromUnoTunnel<ScCellRangesBase>( xInterface );
4207         if ( pRangesImp && pRangesImp->GetDocShell() == pDocSh )
4208         {
4209             //  if explicit name is given and already existing, throw exception
4210 
4211             if ( !aName.isEmpty() )
4212             {
4213                 size_t nNamedCount = m_aNamedEntries.size();
4214                 for (size_t n = 0; n < nNamedCount; n++)
4215                 {
4216                     if (m_aNamedEntries[n].GetName() == aName)
4217                         throw container::ElementExistException();
4218                 }
4219             }
4220 
4221             ScRangeList aNew(GetRangeList());
4222             const ScRangeList& rAddRanges = pRangesImp->GetRangeList();
4223             size_t nAddCount = rAddRanges.size();
4224             for ( size_t i = 0; i < nAddCount; i++ )
4225                 aNew.Join( rAddRanges[ i ] );
4226             SetNewRanges(aNew);
4227             bDone = true;
4228 
4229             if ( !aName.isEmpty() && nAddCount == 1 )
4230             {
4231                 //  if a name is given, also insert into list of named entries
4232                 //  (only possible for a single range)
4233                 //  name is not in m_aNamedEntries (tested above)
4234                 m_aNamedEntries.emplace_back( ScNamedEntry{aName, rAddRanges[ 0 ]} );
4235             }
4236         }
4237     }
4238 
4239     if (!bDone)
4240     {
4241         //  invalid element - double names are handled above
4242         throw lang::IllegalArgumentException();
4243     }
4244 }
4245 
4246 static bool lcl_FindRangeByName( const ScRangeList& rRanges, ScDocShell* pDocSh,
4247                             std::u16string_view rName, size_t& rIndex )
4248 {
4249     if (pDocSh)
4250     {
4251         OUString aRangeStr;
4252         ScDocument& rDoc = pDocSh->GetDocument();
4253         for ( size_t i = 0, nCount = rRanges.size(); i < nCount; i++ )
4254         {
4255             aRangeStr = rRanges[ i ].Format(rDoc, ScRefFlags::VALID | ScRefFlags::TAB_3D);
4256             if ( aRangeStr == rName )
4257             {
4258                 rIndex = i;
4259                 return true;
4260             }
4261         }
4262     }
4263     return false;
4264 }
4265 
4266 static bool lcl_FindRangeOrEntry( const std::vector<ScCellRangesObj::ScNamedEntry>& rNamedEntries,
4267                             const ScRangeList& rRanges, ScDocShell* pDocSh,
4268                             const OUString& rName, ScRange& rFound )
4269 {
4270     //  exact range in list?
4271 
4272     size_t nIndex = 0;
4273     if ( lcl_FindRangeByName( rRanges, pDocSh, rName, nIndex ) )
4274     {
4275         rFound = rRanges[ nIndex ];
4276         return true;
4277     }
4278 
4279     //  range contained in selection? (sheet must be specified)
4280 
4281     ScRange aCellRange;
4282     ScRefFlags nParse = aCellRange.ParseAny( rName, pDocSh->GetDocument() );
4283     if ( (nParse & ( ScRefFlags::VALID | ScRefFlags::TAB_3D ))
4284                == ( ScRefFlags::VALID | ScRefFlags::TAB_3D ))
4285     {
4286         ScMarkData aMarkData(pDocSh->GetDocument().GetSheetLimits());
4287         aMarkData.MarkFromRangeList( rRanges, false );
4288         aMarkData.MarkToMulti();        // needed for IsAllMarked
4289         if ( aMarkData.IsAllMarked( aCellRange ) )
4290         {
4291             rFound = aCellRange;
4292             return true;
4293         }
4294     }
4295 
4296     //  named entry in this object?
4297 
4298     for (const auto & rNamedEntry : rNamedEntries)
4299         if ( rNamedEntry.GetName() == rName )
4300         {
4301             //  test if named entry is contained in rRanges
4302 
4303             const ScRange& rComp = rNamedEntry.GetRange();
4304             ScMarkData aMarkData(pDocSh->GetDocument().GetSheetLimits());
4305             aMarkData.MarkFromRangeList( rRanges, false );
4306             aMarkData.MarkToMulti();        // needed for IsAllMarked
4307             if ( aMarkData.IsAllMarked( rComp ) )
4308             {
4309                 rFound = rComp;
4310                 return true;
4311             }
4312         }
4313 
4314     return false;       // not found
4315 }
4316 
4317 void SAL_CALL ScCellRangesObj::removeByName( const OUString& aName )
4318 {
4319     SolarMutexGuard aGuard;
4320     bool bDone = false;
4321     ScDocShell* pDocSh = GetDocShell();
4322     const ScRangeList& rRanges = GetRangeList();
4323     size_t nIndex = 0;
4324     if ( lcl_FindRangeByName( rRanges, pDocSh, aName, nIndex ) )
4325     {
4326         // skip a single range
4327         ScRangeList aNew;
4328         for ( size_t i = 0, nCount = rRanges.size(); i < nCount; i++ )
4329             if (i != nIndex)
4330                 aNew.push_back( rRanges[ i ] );
4331         SetNewRanges(aNew);
4332         bDone = true;
4333     }
4334     else if (pDocSh)
4335     {
4336         //  deselect any ranges (parsed or named entry)
4337         ScRangeList aDiff;
4338         bool bValid = ( aDiff.Parse( aName, pDocSh->GetDocument() ) & ScRefFlags::VALID )
4339                                                                        == ScRefFlags::VALID;
4340         if (!bValid)
4341         {
4342             sal_uInt16 nCount = m_aNamedEntries.size();
4343             for (sal_uInt16 n=0; n<nCount && !bValid; n++)
4344                 if (m_aNamedEntries[n].GetName() == aName)
4345                 {
4346                     aDiff.RemoveAll();
4347                     aDiff.push_back(m_aNamedEntries[n].GetRange());
4348                     bValid = true;
4349                 }
4350         }
4351         if ( bValid )
4352         {
4353             ScMarkData aMarkData(GetDocument()->GetSheetLimits());
4354             aMarkData.MarkFromRangeList( rRanges, false );
4355 
4356             for ( size_t i = 0, nDiffCount = aDiff.size(); i < nDiffCount; i++ )
4357             {
4358                 ScRange const & rDiffRange = aDiff[ i ];
4359                 if (aMarkData.GetTableSelect( rDiffRange.aStart.Tab() ))
4360                     aMarkData.SetMultiMarkArea( rDiffRange, false );
4361             }
4362 
4363             ScRangeList aNew;
4364             aMarkData.FillRangeListWithMarks( &aNew, false );
4365             SetNewRanges(aNew);
4366 
4367             bDone = true;       //! error if range was not selected before?
4368         }
4369     }
4370 
4371     if (!m_aNamedEntries.empty())
4372         lcl_RemoveNamedEntry(m_aNamedEntries, aName);
4373 
4374     if (!bDone)
4375         throw container::NoSuchElementException();      // not found
4376 }
4377 
4378 // XNameReplace
4379 
4380 void SAL_CALL ScCellRangesObj::replaceByName( const OUString& aName, const uno::Any& aElement )
4381 {
4382     SolarMutexGuard aGuard;
4383     //! combine?
4384     removeByName( aName );
4385     insertByName( aName, aElement );
4386 }
4387 
4388 // XNameAccess
4389 
4390 uno::Any SAL_CALL ScCellRangesObj::getByName( const OUString& aName )
4391 {
4392     SolarMutexGuard aGuard;
4393     uno::Any aRet;
4394 
4395     ScDocShell* pDocSh = GetDocShell();
4396     const ScRangeList& rRanges = GetRangeList();
4397     ScRange aRange;
4398     if (!lcl_FindRangeOrEntry(m_aNamedEntries, rRanges,
4399                 pDocSh, aName, aRange))
4400         throw container::NoSuchElementException();
4401 
4402     uno::Reference<table::XCellRange> xRange;
4403     if ( aRange.aStart == aRange.aEnd )
4404         xRange.set(new ScCellObj( pDocSh, aRange.aStart ));
4405     else
4406         xRange.set(new ScCellRangeObj( pDocSh, aRange ));
4407     aRet <<= xRange;
4408 
4409     return aRet;
4410 }
4411 
4412 static bool lcl_FindEntryName( const std::vector<ScCellRangesObj::ScNamedEntry>& rNamedEntries,
4413                         const ScRange& rRange, OUString& rName )
4414 {
4415     sal_uInt16 nCount = rNamedEntries.size();
4416     for (sal_uInt16 i=0; i<nCount; i++)
4417         if (rNamedEntries[i].GetRange() == rRange)
4418         {
4419             rName = rNamedEntries[i].GetName();
4420             return true;
4421         }
4422     return false;
4423 }
4424 
4425 uno::Sequence<OUString> SAL_CALL ScCellRangesObj::getElementNames()
4426 {
4427     SolarMutexGuard aGuard;
4428 
4429     ScDocShell* pDocSh = GetDocShell();
4430     const ScRangeList& rRanges = GetRangeList();
4431     if (pDocSh)
4432     {
4433         OUString aRangeStr;
4434         ScDocument& rDoc = pDocSh->GetDocument();
4435         size_t nCount = rRanges.size();
4436 
4437         uno::Sequence<OUString> aSeq(nCount);
4438         OUString* pAry = aSeq.getArray();
4439         for (size_t i=0; i < nCount; i++)
4440         {
4441             //  use given name if for exactly this range, otherwise just format
4442             ScRange const & rRange = rRanges[ i ];
4443             if (m_aNamedEntries.empty() ||
4444                 !lcl_FindEntryName(m_aNamedEntries, rRange, aRangeStr))
4445             {
4446                 aRangeStr = rRange.Format(rDoc, ScRefFlags::VALID | ScRefFlags::TAB_3D);
4447             }
4448             pAry[i] = aRangeStr;
4449         }
4450         return aSeq;
4451     }
4452     return {};
4453 }
4454 
4455 sal_Bool SAL_CALL ScCellRangesObj::hasByName( const OUString& aName )
4456 {
4457     SolarMutexGuard aGuard;
4458     ScDocShell* pDocSh = GetDocShell();
4459     const ScRangeList& rRanges = GetRangeList();
4460     ScRange aRange;
4461     return lcl_FindRangeOrEntry(m_aNamedEntries, rRanges, pDocSh,
4462                 aName, aRange);
4463 }
4464 
4465 // XEnumerationAccess
4466 
4467 uno::Reference<container::XEnumeration> SAL_CALL ScCellRangesObj::createEnumeration()
4468 {
4469     SolarMutexGuard aGuard;
4470     return new ScIndexEnumeration(this, "com.sun.star.sheet.SheetCellRangesEnumeration");
4471 }
4472 
4473 // XIndexAccess
4474 
4475 sal_Int32 SAL_CALL ScCellRangesObj::getCount()
4476 {
4477     SolarMutexGuard aGuard;
4478     const ScRangeList& rRanges = GetRangeList();
4479     return rRanges.size();
4480 }
4481 
4482 uno::Any SAL_CALL ScCellRangesObj::getByIndex( sal_Int32 nIndex )
4483 {
4484     SolarMutexGuard aGuard;
4485     uno::Reference<table::XCellRange> xRange(GetObjectByIndex_Impl(nIndex));
4486     if (!xRange.is())
4487         throw lang::IndexOutOfBoundsException();
4488 
4489     return uno::makeAny(xRange);
4490 
4491 }
4492 
4493 uno::Type SAL_CALL ScCellRangesObj::getElementType()
4494 {
4495     SolarMutexGuard aGuard;
4496     return cppu::UnoType<table::XCellRange>::get();
4497 }
4498 
4499 sal_Bool SAL_CALL ScCellRangesObj::hasElements()
4500 {
4501     SolarMutexGuard aGuard;
4502     const ScRangeList& rRanges = GetRangeList();
4503     return !rRanges.empty();
4504 }
4505 
4506 // XServiceInfo
4507 OUString SAL_CALL ScCellRangesObj::getImplementationName()
4508 {
4509     return "ScCellRangesObj";
4510 }
4511 
4512 sal_Bool SAL_CALL ScCellRangesObj::supportsService( const OUString& rServiceName )
4513 {
4514     return cppu::supportsService(this, rServiceName);
4515 }
4516 
4517 uno::Sequence<OUString> SAL_CALL ScCellRangesObj::getSupportedServiceNames()
4518 {
4519     return {SCSHEETCELLRANGES_SERVICE,
4520             SCCELLPROPERTIES_SERVICE,
4521             SCCHARPROPERTIES_SERVICE,
4522             SCPARAPROPERTIES_SERVICE};
4523 }
4524 
4525 uno::Reference<table::XCellRange> ScCellRangeObj::CreateRangeFromDoc( const ScDocument& rDoc, const ScRange& rR )
4526 {
4527     SfxObjectShell* pObjSh = rDoc.GetDocumentShell();
4528     if ( auto pDocShell = dynamic_cast<ScDocShell*>( pObjSh) )
4529         return new ScCellRangeObj( pDocShell, rR );
4530     return nullptr;
4531 }
4532 
4533 ScCellRangeObj::ScCellRangeObj(ScDocShell* pDocSh, const ScRange& rR) :
4534     ScCellRangesBase( pDocSh, rR ),
4535     pRangePropSet( lcl_GetRangePropertySet() ),
4536     aRange( rR )
4537 {
4538     aRange.PutInOrder();       // beginning / end correct
4539 }
4540 
4541 ScCellRangeObj::~ScCellRangeObj()
4542 {
4543 }
4544 
4545 void ScCellRangeObj::RefChanged()
4546 {
4547     ScCellRangesBase::RefChanged();
4548 
4549     const ScRangeList& rRanges = GetRangeList();
4550     OSL_ENSURE(rRanges.size() == 1, "What ranges ?!?!");
4551     if ( !rRanges.empty() )
4552     {
4553         const ScRange & rFirst = rRanges[0];
4554         aRange = rFirst;
4555         aRange.PutInOrder();
4556     }
4557 }
4558 
4559 uno::Any SAL_CALL ScCellRangeObj::queryInterface( const uno::Type& rType )
4560 {
4561     SC_QUERYINTERFACE( sheet::XCellRangeAddressable )
4562     SC_QUERYINTERFACE( table::XCellRange )
4563     SC_QUERYINTERFACE( sheet::XSheetCellRange )
4564     SC_QUERYINTERFACE( sheet::XArrayFormulaRange )
4565     SC_QUERYINTERFACE( sheet::XArrayFormulaTokens )
4566     SC_QUERYINTERFACE( sheet::XCellRangeData )
4567     SC_QUERYINTERFACE( sheet::XCellRangeFormula )
4568     SC_QUERYINTERFACE( sheet::XMultipleOperation )
4569     SC_QUERYINTERFACE( util::XMergeable )
4570     SC_QUERYINTERFACE( sheet::XCellSeries )
4571     SC_QUERYINTERFACE( table::XAutoFormattable )
4572     SC_QUERYINTERFACE( util::XSortable )
4573     SC_QUERYINTERFACE( sheet::XSheetFilterableEx )
4574     SC_QUERYINTERFACE( sheet::XSheetFilterable )
4575     SC_QUERYINTERFACE( sheet::XSubTotalCalculatable )
4576     SC_QUERYINTERFACE( table::XColumnRowRange )
4577     SC_QUERYINTERFACE( util::XImportable )
4578     SC_QUERYINTERFACE( sheet::XCellFormatRangesSupplier )
4579     SC_QUERYINTERFACE( sheet::XUniqueCellFormatRangesSupplier )
4580 
4581     return ScCellRangesBase::queryInterface( rType );
4582 }
4583 
4584 void SAL_CALL ScCellRangeObj::acquire() noexcept
4585 {
4586     ScCellRangesBase::acquire();
4587 }
4588 
4589 void SAL_CALL ScCellRangeObj::release() noexcept
4590 {
4591     ScCellRangesBase::release();
4592 }
4593 
4594 uno::Sequence<uno::Type> SAL_CALL ScCellRangeObj::getTypes()
4595 {
4596     static const uno::Sequence<uno::Type> aTypes = comphelper::concatSequences(
4597         ScCellRangesBase::getTypes(),
4598         uno::Sequence<uno::Type>
4599         {
4600             cppu::UnoType<sheet::XCellRangeAddressable>::get(),
4601             cppu::UnoType<sheet::XSheetCellRange>::get(),
4602             cppu::UnoType<sheet::XArrayFormulaRange>::get(),
4603             cppu::UnoType<sheet::XArrayFormulaTokens>::get(),
4604             cppu::UnoType<sheet::XCellRangeData>::get(),
4605             cppu::UnoType<sheet::XCellRangeFormula>::get(),
4606             cppu::UnoType<sheet::XMultipleOperation>::get(),
4607             cppu::UnoType<util::XMergeable>::get(),
4608             cppu::UnoType<sheet::XCellSeries>::get(),
4609             cppu::UnoType<table::XAutoFormattable>::get(),
4610             cppu::UnoType<util::XSortable>::get(),
4611             cppu::UnoType<sheet::XSheetFilterableEx>::get(),
4612             cppu::UnoType<sheet::XSubTotalCalculatable>::get(),
4613             cppu::UnoType<table::XColumnRowRange>::get(),
4614             cppu::UnoType<util::XImportable>::get(),
4615             cppu::UnoType<sheet::XCellFormatRangesSupplier>::get(),
4616             cppu::UnoType<sheet::XUniqueCellFormatRangesSupplier>::get()
4617         } );
4618     return aTypes;
4619 }
4620 
4621 uno::Sequence<sal_Int8> SAL_CALL ScCellRangeObj::getImplementationId()
4622 {
4623     return css::uno::Sequence<sal_Int8>();
4624 }
4625 
4626 // XCellRange
4627 
4628 //  ColumnCount / RowCount vanished
4629 //! are used in Writer for tables ???
4630 
4631 uno::Reference<table::XCell> ScCellRangeObj::GetCellByPosition_Impl(
4632                                         sal_Int32 nColumn, sal_Int32 nRow )
4633 {
4634     ScDocShell* pDocSh = GetDocShell();
4635     if (!pDocSh)
4636         throw uno::RuntimeException();
4637 
4638     if ( nColumn >= 0 && nRow >= 0 )
4639     {
4640         sal_Int32 nPosX = aRange.aStart.Col() + nColumn;
4641         sal_Int32 nPosY = aRange.aStart.Row() + nRow;
4642 
4643         if ( nPosX <= aRange.aEnd.Col() && nPosY <= aRange.aEnd.Row() )
4644         {
4645             ScAddress aNew( static_cast<SCCOL>(nPosX), static_cast<SCROW>(nPosY), aRange.aStart.Tab() );
4646             return new ScCellObj( pDocSh, aNew );
4647         }
4648     }
4649 
4650     throw lang::IndexOutOfBoundsException();
4651 }
4652 
4653 uno::Reference<table::XCell> SAL_CALL ScCellRangeObj::getCellByPosition(
4654                                         sal_Int32 nColumn, sal_Int32 nRow )
4655 {
4656     SolarMutexGuard aGuard;
4657 
4658     return GetCellByPosition_Impl(nColumn, nRow);
4659 }
4660 
4661 uno::Reference<table::XCellRange> SAL_CALL ScCellRangeObj::getCellRangeByPosition(
4662                 sal_Int32 nLeft, sal_Int32 nTop, sal_Int32 nRight, sal_Int32 nBottom )
4663 {
4664     SolarMutexGuard aGuard;
4665 
4666     ScDocShell* pDocSh = GetDocShell();
4667     if (!pDocSh)
4668         throw uno::RuntimeException();
4669 
4670     if ( nLeft >= 0 && nTop >= 0 && nRight >= 0 && nBottom >= 0 )
4671     {
4672         sal_Int32 nStartX = aRange.aStart.Col() + nLeft;
4673         sal_Int32 nStartY = aRange.aStart.Row() + nTop;
4674         sal_Int32 nEndX = aRange.aStart.Col() + nRight;
4675         sal_Int32 nEndY = aRange.aStart.Row() + nBottom;
4676 
4677         if ( nStartX <= nEndX && nEndX <= aRange.aEnd.Col() &&
4678              nStartY <= nEndY && nEndY <= aRange.aEnd.Row() )
4679         {
4680             ScRange aNew( static_cast<SCCOL>(nStartX), static_cast<SCROW>(nStartY), aRange.aStart.Tab(),
4681                           static_cast<SCCOL>(nEndX), static_cast<SCROW>(nEndY), aRange.aEnd.Tab() );
4682             return new ScCellRangeObj( pDocSh, aNew );
4683         }
4684     }
4685 
4686     throw lang::IndexOutOfBoundsException();
4687 }
4688 
4689 uno::Reference<table::XCellRange> SAL_CALL ScCellRangeObj::getCellRangeByName(
4690                         const OUString& aName )
4691 {
4692     return getCellRangeByName( aName, ScAddress::detailsOOOa1 );
4693 }
4694 
4695 uno::Reference<table::XCellRange>  ScCellRangeObj::getCellRangeByName(
4696                         const OUString& aName, const ScAddress::Details& rDetails  )
4697 {
4698     //  name refers to the whole document (with the range's table as default),
4699     //  valid only if the range is within this range
4700 
4701     SolarMutexGuard aGuard;
4702     ScDocShell* pDocSh = GetDocShell();
4703     if ( pDocSh )
4704     {
4705         ScDocument& rDoc = pDocSh->GetDocument();
4706         SCTAB nTab = aRange.aStart.Tab();
4707 
4708         ScRange aCellRange;
4709         bool bFound = false;
4710         ScRefFlags nParse = aCellRange.ParseAny( aName, rDoc, rDetails );
4711         if ( nParse & ScRefFlags::VALID )
4712         {
4713             if ( !(nParse & ScRefFlags::TAB_3D) )   // no sheet specified -> this sheet
4714             {
4715                 aCellRange.aStart.SetTab(nTab);
4716                 aCellRange.aEnd.SetTab(nTab);
4717             }
4718             bFound = true;
4719         }
4720         else
4721         {
4722             if ( ScRangeUtil::MakeRangeFromName( aName, rDoc, nTab, aCellRange, RUTL_NAMES, rDetails) ||
4723                  ScRangeUtil::MakeRangeFromName( aName, rDoc, nTab, aCellRange, RUTL_DBASE, rDetails))
4724                 bFound = true;
4725         }
4726 
4727         if (bFound)         // valid only if within this object's range
4728         {
4729             if (!aRange.Contains(aCellRange))
4730                 bFound = false;
4731         }
4732 
4733         if (bFound)
4734         {
4735             if ( aCellRange.aStart == aCellRange.aEnd )
4736                 return new ScCellObj( pDocSh, aCellRange.aStart );
4737             else
4738                 return new ScCellRangeObj( pDocSh, aCellRange );
4739         }
4740     }
4741 
4742     throw uno::RuntimeException();
4743 }
4744 
4745 // XColumnRowRange
4746 
4747 uno::Reference<table::XTableColumns> SAL_CALL ScCellRangeObj::getColumns()
4748 {
4749     SolarMutexGuard aGuard;
4750     ScDocShell* pDocSh = GetDocShell();
4751     if (pDocSh)
4752         return new ScTableColumnsObj( pDocSh, aRange.aStart.Tab(),
4753                                         aRange.aStart.Col(), aRange.aEnd.Col() );
4754 
4755     OSL_FAIL("Document invalid");
4756     return nullptr;
4757 }
4758 
4759 uno::Reference<table::XTableRows> SAL_CALL ScCellRangeObj::getRows()
4760 {
4761     SolarMutexGuard aGuard;
4762     ScDocShell* pDocSh = GetDocShell();
4763     if (pDocSh)
4764         return new ScTableRowsObj( pDocSh, aRange.aStart.Tab(),
4765                                     aRange.aStart.Row(), aRange.aEnd.Row() );
4766 
4767     OSL_FAIL("Document invalid");
4768     return nullptr;
4769 }
4770 
4771 // XAddressableCellRange
4772 
4773 table::CellRangeAddress SAL_CALL ScCellRangeObj::getRangeAddress()
4774 {
4775     SolarMutexGuard aGuard;
4776     table::CellRangeAddress aRet;
4777     ScUnoConversion::FillApiRange( aRet, aRange );
4778     return aRet;
4779 }
4780 
4781 // XSheetCellRange
4782 
4783 uno::Reference<sheet::XSpreadsheet> SAL_CALL ScCellRangeObj::getSpreadsheet()
4784 {
4785     SolarMutexGuard aGuard;
4786     ScDocShell* pDocSh = GetDocShell();
4787     if (pDocSh)
4788         return new ScTableSheetObj( pDocSh, aRange.aStart.Tab() );
4789 
4790     OSL_FAIL("Document invalid");
4791     return nullptr;
4792 }
4793 
4794 // XArrayFormulaRange
4795 
4796 OUString SAL_CALL ScCellRangeObj::getArrayFormula()
4797 {
4798     SolarMutexGuard aGuard;
4799 
4800     //  Matrix formula if clearly part of a matrix (so when start and end of
4801     //  the block belong to the same matrix) else empty string.
4802 
4803     ScDocShell* pDocSh = GetDocShell();
4804     if (!pDocSh)
4805         return OUString();
4806 
4807     ScDocument& rDoc = pDocSh->GetDocument();
4808     ScRefCellValue aCell1(rDoc, aRange.aStart);
4809     ScRefCellValue aCell2(rDoc, aRange.aEnd);
4810     if (aCell1.meType == CELLTYPE_FORMULA && aCell2.meType == CELLTYPE_FORMULA)
4811     {
4812         const ScFormulaCell* pFCell1 = aCell1.mpFormula;
4813         const ScFormulaCell* pFCell2 = aCell2.mpFormula;
4814         ScAddress aStart1;
4815         ScAddress aStart2;
4816         if (pFCell1->GetMatrixOrigin(rDoc, aStart1) && pFCell2->GetMatrixOrigin(rDoc, aStart2))
4817         {
4818             if (aStart1 == aStart2)               // both the same matrix
4819                 return pFCell1->GetFormula();    // it doesn't matter from which cell
4820         }
4821     }
4822     return OUString();
4823 }
4824 
4825 void ScCellRangeObj::SetArrayFormula_Impl(const OUString& rFormula,
4826     const formula::FormulaGrammar::Grammar eGrammar)
4827 {
4828     ScDocShell* pDocSh = GetDocShell();
4829     if (!pDocSh)
4830         return;
4831 
4832     if ( !rFormula.isEmpty() )
4833     {
4834         if ( comphelper::getFromUnoTunnel<ScTableSheetObj>( static_cast<cppu::OWeakObject*>(this) ) )
4835         {
4836             //  don't set array formula for sheet object
4837             throw uno::RuntimeException();
4838         }
4839 
4840         pDocSh->GetDocFunc().EnterMatrix( aRange, nullptr, nullptr, rFormula, true, true, OUString()/*rFormulaNmsp*/, eGrammar );
4841     }
4842     else
4843     {
4844         //  empty string -> erase array formula
4845         ScMarkData aMark(GetDocument()->GetSheetLimits());
4846         aMark.SetMarkArea( aRange );
4847         aMark.SelectTable( aRange.aStart.Tab(), true );
4848         pDocSh->GetDocFunc().DeleteContents( aMark, InsertDeleteFlags::CONTENTS, true, true );
4849     }
4850 }
4851 
4852 void SAL_CALL ScCellRangeObj::setArrayFormula( const OUString& aFormula )
4853 {
4854     SolarMutexGuard aGuard;
4855     // GRAM_API for API compatibility.
4856     SetArrayFormula_Impl( aFormula, formula::FormulaGrammar::GRAM_API);
4857 }
4858 
4859 // XArrayFormulaTokens
4860 uno::Sequence<sheet::FormulaToken> SAL_CALL ScCellRangeObj::getArrayTokens()
4861 {
4862     SolarMutexGuard aGuard;
4863 
4864     // same cell logic as in getArrayFormula
4865 
4866     uno::Sequence<sheet::FormulaToken> aSequence;
4867     ScDocShell* pDocSh = GetDocShell();
4868     if (!pDocSh)
4869         return aSequence;
4870 
4871     ScDocument& rDoc = pDocSh->GetDocument();
4872     ScRefCellValue aCell1(rDoc, aRange.aStart);
4873     ScRefCellValue aCell2(rDoc, aRange.aEnd);
4874     if (aCell1.meType == CELLTYPE_FORMULA && aCell2.meType == CELLTYPE_FORMULA)
4875     {
4876         const ScFormulaCell* pFCell1 = aCell1.mpFormula;
4877         const ScFormulaCell* pFCell2 = aCell2.mpFormula;
4878         ScAddress aStart1;
4879         ScAddress aStart2;
4880         if (pFCell1->GetMatrixOrigin(rDoc, aStart1) && pFCell2->GetMatrixOrigin(rDoc, aStart2))
4881         {
4882             if (aStart1 == aStart2)
4883             {
4884                 const ScTokenArray* pTokenArray = pFCell1->GetCode();
4885                 if (pTokenArray)
4886                     ScTokenConversion::ConvertToTokenSequence(rDoc, aSequence, *pTokenArray);
4887             }
4888         }
4889     }
4890 
4891     return aSequence;
4892 }
4893 
4894 void SAL_CALL ScCellRangeObj::setArrayTokens( const uno::Sequence<sheet::FormulaToken>& rTokens )
4895 {
4896     SolarMutexGuard aGuard;
4897     ScDocShell* pDocSh = GetDocShell();
4898     if ( !pDocSh )
4899         return;
4900 
4901     if ( rTokens.hasElements() )
4902     {
4903         if ( comphelper::getFromUnoTunnel<ScTableSheetObj>( static_cast<cppu::OWeakObject*>(this) ) )
4904         {
4905             throw uno::RuntimeException();
4906         }
4907 
4908         ScDocument& rDoc = pDocSh->GetDocument();
4909         ScTokenArray aTokenArray(rDoc);
4910         (void)ScTokenConversion::ConvertToTokenArray( rDoc, aTokenArray, rTokens );
4911 
4912         // Actually GRAM_API is a don't-care here because of the token
4913         // array being set, it fits with other API compatibility grammars
4914         // though.
4915         pDocSh->GetDocFunc().EnterMatrix( aRange, nullptr, &aTokenArray, OUString(), true, true, OUString(), formula::FormulaGrammar::GRAM_API );
4916     }
4917     else
4918     {
4919         //  empty sequence -> erase array formula
4920         ScMarkData aMark(pDocSh->GetDocument().GetSheetLimits());
4921         aMark.SetMarkArea( aRange );
4922         aMark.SelectTable( aRange.aStart.Tab(), true );
4923         pDocSh->GetDocFunc().DeleteContents( aMark, InsertDeleteFlags::CONTENTS, true, true );
4924     }
4925 }
4926 
4927 // XCellRangeData
4928 
4929 uno::Sequence< uno::Sequence<uno::Any> > SAL_CALL ScCellRangeObj::getDataArray()
4930 {
4931     SolarMutexGuard aGuard;
4932 
4933     if ( comphelper::getFromUnoTunnel<ScTableSheetObj>( static_cast<cppu::OWeakObject*>(this) ) )
4934     {
4935         //  don't create a data array for the sheet
4936         throw uno::RuntimeException();
4937     }
4938 
4939     ScDocShell* pDocSh = GetDocShell();
4940     if (pDocSh)
4941     {
4942         uno::Any aAny;
4943         // bAllowNV = TRUE: errors as void
4944         if ( ScRangeToSequence::FillMixedArray( aAny, pDocSh->GetDocument(), aRange, true ) )
4945         {
4946             uno::Sequence< uno::Sequence<uno::Any> > aSeq;
4947             if ( aAny >>= aSeq )
4948                 return aSeq;            // success
4949         }
4950     }
4951 
4952     throw uno::RuntimeException();      // no other exceptions specified
4953 }
4954 
4955 void SAL_CALL ScCellRangeObj::setDataArray(
4956                         const uno::Sequence< uno::Sequence<uno::Any> >& aArray )
4957 {
4958     SolarMutexGuard aGuard;
4959 
4960     bool bDone = false;
4961     ScDocShell* pDocSh = GetDocShell();
4962     if (pDocSh)
4963     {
4964         //! move lcl_PutDataArray to docfunc?
4965         bDone = lcl_PutDataArray( *pDocSh, aRange, aArray );
4966     }
4967 
4968     if (!bDone)
4969         throw uno::RuntimeException();      // no other exceptions specified
4970 }
4971 
4972 // XCellRangeFormula
4973 
4974 uno::Sequence< uno::Sequence<OUString> > SAL_CALL ScCellRangeObj::getFormulaArray()
4975 {
4976     SolarMutexGuard aGuard;
4977 
4978     if ( comphelper::getFromUnoTunnel<ScTableSheetObj>( static_cast<cppu::OWeakObject*>(this) ) )
4979     {
4980         //  don't create a data array for the sheet
4981         throw uno::RuntimeException();
4982     }
4983 
4984     ScDocShell* pDocSh = GetDocShell();
4985     if (pDocSh)
4986     {
4987         SCCOL nStartCol = aRange.aStart.Col();
4988         SCROW nStartRow = aRange.aStart.Row();
4989         SCCOL nEndCol = aRange.aEnd.Col();
4990         SCROW nEndRow = aRange.aEnd.Row();
4991         SCCOL nColCount = nEndCol + 1 - nStartCol;
4992         SCROW nRowCount = nEndRow + 1 - nStartRow;
4993         SCTAB nTab = aRange.aStart.Tab();
4994 
4995         uno::Sequence< uno::Sequence<OUString> > aRowSeq( nRowCount );
4996         uno::Sequence<OUString>* pRowAry = aRowSeq.getArray();
4997         for (SCROW nRowIndex = 0; nRowIndex < nRowCount; nRowIndex++)
4998         {
4999             uno::Sequence<OUString> aColSeq( nColCount );
5000             OUString* pColAry = aColSeq.getArray();
5001             for (SCCOL nColIndex = 0; nColIndex < nColCount; nColIndex++)
5002                 pColAry[nColIndex] = lcl_GetInputString( pDocSh->GetDocument(),
5003                                     ScAddress( nStartCol+nColIndex, nStartRow+nRowIndex, nTab ), true );
5004 
5005             pRowAry[nRowIndex] = aColSeq;
5006         }
5007 
5008         return aRowSeq;
5009     }
5010 
5011     throw uno::RuntimeException();      // no other exceptions specified
5012 }
5013 
5014 void SAL_CALL ScCellRangeObj::setFormulaArray(
5015                         const uno::Sequence< uno::Sequence<OUString> >& aArray )
5016 {
5017     SolarMutexGuard aGuard;
5018 
5019     bool bDone = false;
5020     ScDocShell* pDocSh = GetDocShell();
5021     if (pDocSh)
5022     {
5023         ScExternalRefManager::ApiGuard aExtRefGuard(pDocSh->GetDocument());
5024 
5025         // GRAM_API for API compatibility.
5026         bDone = lcl_PutFormulaArray( *pDocSh, aRange, aArray, formula::FormulaGrammar::GRAM_API );
5027     }
5028 
5029     if (!bDone)
5030         throw uno::RuntimeException();      // no other exceptions specified
5031 }
5032 
5033 // XMultipleOperation
5034 
5035 void SAL_CALL ScCellRangeObj::setTableOperation( const table::CellRangeAddress& aFormulaRange,
5036                                         sheet::TableOperationMode nMode,
5037                                         const table::CellAddress& aColumnCell,
5038                                         const table::CellAddress& aRowCell )
5039 {
5040     SolarMutexGuard aGuard;
5041     ScDocShell* pDocSh = GetDocShell();
5042     if (!pDocSh)
5043         return;
5044 
5045     bool bError = false;
5046     ScTabOpParam aParam;
5047     aParam.aRefFormulaCell = ScRefAddress( static_cast<SCCOL>(aFormulaRange.StartColumn),
5048                                           static_cast<SCROW>(aFormulaRange.StartRow), aFormulaRange.Sheet );
5049     aParam.aRefFormulaEnd  = ScRefAddress( static_cast<SCCOL>(aFormulaRange.EndColumn),
5050                                           static_cast<SCROW>(aFormulaRange.EndRow), aFormulaRange.Sheet );
5051     aParam.aRefRowCell     = ScRefAddress( static_cast<SCCOL>(aRowCell.Column),
5052                                           static_cast<SCROW>(aRowCell.Row), aRowCell.Sheet );
5053     aParam.aRefColCell     = ScRefAddress( static_cast<SCCOL>(aColumnCell.Column),
5054                                           static_cast<SCROW>(aColumnCell.Row), aColumnCell.Sheet );
5055 
5056     switch (nMode)
5057     {
5058         case sheet::TableOperationMode_COLUMN:
5059             aParam.meMode = ScTabOpParam::Column;
5060             break;
5061         case sheet::TableOperationMode_ROW:
5062             aParam.meMode = ScTabOpParam::Row;
5063             break;
5064         case sheet::TableOperationMode_BOTH:
5065             aParam.meMode = ScTabOpParam::Both;
5066             break;
5067         default:
5068             bError = true;
5069     }
5070 
5071     if (!bError)
5072         pDocSh->GetDocFunc().TabOp( aRange, nullptr, aParam, true, true );
5073 }
5074 
5075 // XMergeable
5076 
5077 void SAL_CALL ScCellRangeObj::merge( sal_Bool bMerge )
5078 {
5079     SolarMutexGuard aGuard;
5080     ScDocShell* pDocSh = GetDocShell();
5081     if ( !pDocSh )
5082         return;
5083 
5084     ScCellMergeOption aMergeOption(
5085         aRange.aStart.Col(), aRange.aStart.Row(),
5086         aRange.aEnd.Col(), aRange.aEnd.Row(), false);
5087     aMergeOption.maTabs.insert(aRange.aStart.Tab());
5088     if ( bMerge )
5089         pDocSh->GetDocFunc().MergeCells( aMergeOption, false, true, true );
5090     else
5091         pDocSh->GetDocFunc().UnmergeCells( aMergeOption, true, nullptr );
5092 
5093     //! Catch error?
5094 }
5095 
5096 sal_Bool SAL_CALL ScCellRangeObj::getIsMerged()
5097 {
5098     SolarMutexGuard aGuard;
5099     ScDocShell* pDocSh = GetDocShell();
5100     return pDocSh && pDocSh->GetDocument().HasAttrib( aRange, HasAttrFlags::Merged );
5101 }
5102 
5103 // XCellSeries
5104 
5105 void SAL_CALL ScCellRangeObj::fillSeries( sheet::FillDirection nFillDirection,
5106                         sheet::FillMode nFillMode, sheet::FillDateMode nFillDateMode,
5107                         double fStep, double fEndValue )
5108 {
5109     SolarMutexGuard aGuard;
5110     ScDocShell* pDocSh = GetDocShell();
5111     if ( !pDocSh )
5112         return;
5113 
5114     bool bError = false;
5115 
5116     FillDir eDir = FILL_TO_BOTTOM;
5117     switch (nFillDirection)
5118     {
5119         case sheet::FillDirection_TO_BOTTOM:
5120             eDir = FILL_TO_BOTTOM;
5121             break;
5122         case sheet::FillDirection_TO_RIGHT:
5123             eDir = FILL_TO_RIGHT;
5124             break;
5125         case sheet::FillDirection_TO_TOP:
5126             eDir = FILL_TO_TOP;
5127             break;
5128         case sheet::FillDirection_TO_LEFT:
5129             eDir = FILL_TO_LEFT;
5130             break;
5131         default:
5132             bError = true;
5133     }
5134 
5135     FillCmd eCmd = FILL_SIMPLE;
5136     switch ( nFillMode )
5137     {
5138         case sheet::FillMode_SIMPLE:
5139             eCmd = FILL_SIMPLE;
5140             break;
5141         case sheet::FillMode_LINEAR:
5142             eCmd = FILL_LINEAR;
5143             break;
5144         case sheet::FillMode_GROWTH:
5145             eCmd = FILL_GROWTH;
5146             break;
5147         case sheet::FillMode_DATE:
5148             eCmd = FILL_DATE;
5149             break;
5150         case sheet::FillMode_AUTO:
5151             eCmd = FILL_AUTO;
5152             break;
5153         default:
5154             bError = true;
5155     }
5156 
5157     FillDateCmd eDateCmd = FILL_DAY;
5158     switch ( nFillDateMode )
5159     {
5160         case sheet::FillDateMode_FILL_DATE_DAY:
5161             eDateCmd = FILL_DAY;
5162             break;
5163         case sheet::FillDateMode_FILL_DATE_WEEKDAY:
5164             eDateCmd = FILL_WEEKDAY;
5165             break;
5166         case sheet::FillDateMode_FILL_DATE_MONTH:
5167             eDateCmd = FILL_MONTH;
5168             break;
5169         case sheet::FillDateMode_FILL_DATE_YEAR:
5170             eDateCmd = FILL_YEAR;
5171             break;
5172         default:
5173             bError = true;
5174     }
5175 
5176     if (!bError)
5177         pDocSh->GetDocFunc().FillSeries( aRange, nullptr, eDir, eCmd, eDateCmd,
5178                                             MAXDOUBLE, fStep, fEndValue, true );
5179 }
5180 
5181 void SAL_CALL ScCellRangeObj::fillAuto( sheet::FillDirection nFillDirection,
5182                                 sal_Int32 nSourceCount )
5183 {
5184     SolarMutexGuard aGuard;
5185     ScDocShell* pDocSh = GetDocShell();
5186     if ( !(pDocSh && nSourceCount) )
5187         return;
5188 
5189     ScRange aSourceRange(aRange);
5190     SCCOLROW nCount = 0;                   // "Dest-Count"
5191     FillDir eDir = FILL_TO_BOTTOM;
5192     bool bError = false;
5193     switch (nFillDirection)
5194     {
5195         case sheet::FillDirection_TO_BOTTOM:
5196             aSourceRange.aEnd.SetRow( static_cast<SCROW>( aSourceRange.aStart.Row() + nSourceCount - 1 ) );
5197             nCount = aRange.aEnd.Row() - aSourceRange.aEnd.Row();
5198             eDir = FILL_TO_BOTTOM;
5199             break;
5200         case sheet::FillDirection_TO_RIGHT:
5201             aSourceRange.aEnd.SetCol( static_cast<SCCOL>( aSourceRange.aStart.Col() + nSourceCount - 1 ) );
5202             nCount = aRange.aEnd.Col() - aSourceRange.aEnd.Col();
5203             eDir = FILL_TO_RIGHT;
5204             break;
5205         case sheet::FillDirection_TO_TOP:
5206             aSourceRange.aStart.SetRow( static_cast<SCROW>( aSourceRange.aEnd.Row() - nSourceCount + 1 ) );
5207             nCount = aSourceRange.aStart.Row() - aRange.aStart.Row();
5208             eDir = FILL_TO_TOP;
5209             break;
5210         case sheet::FillDirection_TO_LEFT:
5211             aSourceRange.aStart.SetCol( static_cast<SCCOL>( aSourceRange.aEnd.Col() - nSourceCount + 1 ) );
5212             nCount = aSourceRange.aStart.Col() - aRange.aStart.Col();
5213             eDir = FILL_TO_LEFT;
5214             break;
5215         default:
5216             bError = true;
5217     }
5218     const ScDocument& rDoc = pDocSh->GetDocument();
5219     if (nCount < 0 || nCount > rDoc.MaxRow())      // overflow
5220         bError = true;
5221 
5222     if (!bError)
5223         pDocSh->GetDocFunc().FillAuto( aSourceRange, nullptr, eDir, nCount, true );
5224 }
5225 
5226 // XAutoFormattable
5227 
5228 void SAL_CALL ScCellRangeObj::autoFormat( const OUString& aName )
5229 {
5230     SolarMutexGuard aGuard;
5231     ScDocShell* pDocSh = GetDocShell();
5232     if ( pDocSh )
5233     {
5234         ScAutoFormat* pAutoFormat = ScGlobal::GetOrCreateAutoFormat();
5235         ScAutoFormat::const_iterator it = pAutoFormat->find(aName);
5236         if (it == pAutoFormat->end())
5237             throw lang::IllegalArgumentException();
5238 
5239         ScAutoFormat::const_iterator itBeg = pAutoFormat->begin();
5240         size_t nIndex = std::distance(itBeg, it);
5241         pDocSh->GetDocFunc().AutoFormat(aRange, nullptr, nIndex, true);
5242 
5243     }
5244 }
5245 
5246 // XSortable
5247 
5248 uno::Sequence<beans::PropertyValue> SAL_CALL ScCellRangeObj::createSortDescriptor()
5249 {
5250     SolarMutexGuard aGuard;
5251     ScSortParam aParam;
5252     ScDocShell* pDocSh = GetDocShell();
5253     if ( pDocSh )
5254     {
5255         // create DB-Area only during execution; API always the exact area
5256         ScDBData* pData = pDocSh->GetDBData( aRange, SC_DB_OLD, ScGetDBSelection::ForceMark );
5257         if (pData)
5258         {
5259             pData->GetSortParam(aParam);
5260 
5261             //  SortDescriptor contains the counted fields inside the area
5262             ScRange aDBRange;
5263             pData->GetArea(aDBRange);
5264             SCCOLROW nFieldStart = aParam.bByRow ?
5265                 static_cast<SCCOLROW>(aDBRange.aStart.Col()) :
5266                 static_cast<SCCOLROW>(aDBRange.aStart.Row());
5267             for (sal_uInt16 i=0; i<aParam.GetSortKeyCount(); i++)
5268                 if ( aParam.maKeyState[i].bDoSort && aParam.maKeyState[i].nField >= nFieldStart )
5269                     aParam.maKeyState[i].nField -= nFieldStart;
5270         }
5271     }
5272 
5273     uno::Sequence<beans::PropertyValue> aSeq( ScSortDescriptor::GetPropertyCount() );
5274     ScSortDescriptor::FillProperties( aSeq, aParam );
5275     return aSeq;
5276 }
5277 
5278 void SAL_CALL ScCellRangeObj::sort( const uno::Sequence<beans::PropertyValue>& aDescriptor )
5279 {
5280     SolarMutexGuard aGuard;
5281     ScDocShell* pDocSh = GetDocShell();
5282     if (!pDocSh)
5283         return;
5284 
5285     sal_uInt16 i;
5286     ScSortParam aParam;
5287     ScDBData* pData = pDocSh->GetDBData( aRange, SC_DB_MAKE, ScGetDBSelection::ForceMark ); // if needed create area
5288     if (pData)
5289     {
5290         //  get old settings if not everything is set anew
5291         pData->GetSortParam(aParam);
5292         SCCOLROW nOldStart = aParam.bByRow ?
5293             static_cast<SCCOLROW>(aRange.aStart.Col()) :
5294             static_cast<SCCOLROW>(aRange.aStart.Row());
5295         for (i=0; i<aParam.GetSortKeyCount(); i++)
5296             if ( aParam.maKeyState[i].bDoSort && aParam.maKeyState[i].nField >= nOldStart )
5297                 aParam.maKeyState[i].nField -= nOldStart;
5298     }
5299 
5300     ScSortDescriptor::FillSortParam( aParam, aDescriptor );
5301 
5302     //  SortDescriptor contains the counted fields inside the area
5303     //  ByRow can be changed during execution of FillSortParam
5304     SCCOLROW nFieldStart = aParam.bByRow ?
5305         static_cast<SCCOLROW>(aRange.aStart.Col()) :
5306         static_cast<SCCOLROW>(aRange.aStart.Row());
5307     SCCOLROW nFieldEnd = aParam.bByRow ?
5308         static_cast<SCCOLROW>(aRange.aEnd.Col()) :
5309         static_cast<SCCOLROW>(aRange.aEnd.Row());
5310     for (i=0; i<aParam.GetSortKeyCount(); i++)
5311     {
5312         aParam.maKeyState[i].nField += nFieldStart;
5313         // tdf#103632 - sanity check poorly behaved macros.
5314         if (aParam.maKeyState[i].nField > nFieldEnd)
5315             aParam.maKeyState[i].nField = nFieldEnd;
5316     }
5317 
5318     SCTAB nTab = aRange.aStart.Tab();
5319     aParam.nCol1 = aRange.aStart.Col();
5320     aParam.nRow1 = aRange.aStart.Row();
5321     aParam.nCol2 = aRange.aEnd.Col();
5322     aParam.nRow2 = aRange.aEnd.Row();
5323 
5324     pDocSh->GetDBData( aRange, SC_DB_MAKE, ScGetDBSelection::ForceMark );       // if needed create area
5325 
5326     ScDBDocFunc aFunc(*pDocSh); // area must be created
5327     (void)aFunc.Sort( nTab, aParam, true, true, true );
5328 }
5329 
5330 // XFilterable
5331 
5332 uno::Reference<sheet::XSheetFilterDescriptor> SAL_CALL ScCellRangeObj::createFilterDescriptor(
5333                                 sal_Bool bEmpty )
5334 {
5335     SolarMutexGuard aGuard;
5336     ScDocShell* pDocSh = GetDocShell();
5337     rtl::Reference<ScFilterDescriptor> pNew = new ScFilterDescriptor(pDocSh);
5338     if ( !bEmpty && pDocSh )
5339     {
5340         // create DB-Area only during execution; API always the exact area
5341         ScDBData* pData = pDocSh->GetDBData( aRange, SC_DB_OLD, ScGetDBSelection::ForceMark );
5342         if (pData)
5343         {
5344             ScQueryParam aParam;
5345             pData->GetQueryParam(aParam);
5346             //  FilterDescriptor contains the counted fields inside the area
5347             ScRange aDBRange;
5348             pData->GetArea(aDBRange);
5349             SCCOLROW nFieldStart = aParam.bByRow ?
5350                 static_cast<SCCOLROW>(aDBRange.aStart.Col()) :
5351                 static_cast<SCCOLROW>(aDBRange.aStart.Row());
5352             SCSIZE nCount = aParam.GetEntryCount();
5353             for (SCSIZE i=0; i<nCount; i++)
5354             {
5355                 ScQueryEntry& rEntry = aParam.GetEntry(i);
5356                 if (rEntry.bDoQuery && rEntry.nField >= nFieldStart)
5357                     rEntry.nField -= nFieldStart;
5358             }
5359             pNew->SetParam(aParam);
5360         }
5361     }
5362     return pNew;
5363 }
5364 
5365 void SAL_CALL ScCellRangeObj::filter( const uno::Reference<sheet::XSheetFilterDescriptor>& xDescriptor )
5366 {
5367     SolarMutexGuard aGuard;
5368 
5369     if (!xDescriptor.is()) return;
5370 
5371     //  This could be theoretically an unknown object, so only use the
5372     //  public XSheetFilterDescriptor interface to copy the data into a
5373     //  ScFilterDescriptor object:
5374     //! if it already a ScFilterDescriptor is, direct via getImplementation?
5375 
5376     ScDocShell* pDocSh = GetDocShell();
5377     rtl::Reference<ScFilterDescriptor> xImpl(new ScFilterDescriptor(pDocSh));
5378     uno::Reference< sheet::XSheetFilterDescriptor2 > xDescriptor2( xDescriptor, uno::UNO_QUERY );
5379     if ( xDescriptor2.is() )
5380     {
5381         xImpl->setFilterFields2( xDescriptor2->getFilterFields2() );
5382     }
5383     else
5384     {
5385         xImpl->setFilterFields( xDescriptor->getFilterFields() );
5386     }
5387     //  the rest are now properties...
5388 
5389     uno::Reference<beans::XPropertySet> xPropSet( xDescriptor, uno::UNO_QUERY );
5390     if (xPropSet.is())
5391         lcl_CopyProperties(*xImpl, *xPropSet);
5392 
5393     if (!pDocSh)
5394         return;
5395 
5396     ScQueryParam aParam = xImpl->GetParam();
5397     //  FilterDescriptor contains the counted fields inside the area
5398     SCCOLROW nFieldStart = aParam.bByRow ?
5399         static_cast<SCCOLROW>(aRange.aStart.Col()) :
5400         static_cast<SCCOLROW>(aRange.aStart.Row());
5401     SCSIZE nCount = aParam.GetEntryCount();
5402     svl::SharedStringPool& rPool = pDocSh->GetDocument().GetSharedStringPool();
5403     for (SCSIZE i=0; i<nCount; i++)
5404     {
5405         ScQueryEntry& rEntry = aParam.GetEntry(i);
5406         if (rEntry.bDoQuery)
5407         {
5408             rEntry.nField += nFieldStart;
5409             //  dialog always shows the string -> must match the value
5410             ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems();
5411             rItems.resize(1);
5412             ScQueryEntry::Item& rItem = rItems.front();
5413             if (rItem.meType != ScQueryEntry::ByString)
5414             {
5415                 OUString aStr;
5416                 pDocSh->GetDocument().GetFormatTable()->GetInputLineString(rItem.mfVal, 0, aStr);
5417                 rItem.maString = rPool.intern(aStr);
5418             }
5419         }
5420     }
5421 
5422     SCTAB nTab = aRange.aStart.Tab();
5423     aParam.nCol1 = aRange.aStart.Col();
5424     aParam.nRow1 = aRange.aStart.Row();
5425     aParam.nCol2 = aRange.aEnd.Col();
5426     aParam.nRow2 = aRange.aEnd.Row();
5427 
5428     pDocSh->GetDBData( aRange, SC_DB_MAKE, ScGetDBSelection::ForceMark );   // if needed create area
5429 
5430     //! keep source range in filter descriptor
5431     //! if created by createFilterDescriptorByObject ???
5432 
5433     ScDBDocFunc aFunc(*pDocSh);
5434     aFunc.Query( nTab, aParam, nullptr, true, true );  // area must be created
5435 }
5436 
5437 //! get/setAutoFilter as properties!!!
5438 
5439 // XAdvancedFilterSource
5440 
5441 uno::Reference<sheet::XSheetFilterDescriptor> SAL_CALL ScCellRangeObj::createFilterDescriptorByObject(
5442                         const uno::Reference<sheet::XSheetFilterable>& xObject )
5443 {
5444     SolarMutexGuard aGuard;
5445 
5446     //  this here is not the area, which will be filtered, instead the area
5447     //  with the query
5448 
5449     uno::Reference<sheet::XCellRangeAddressable> xAddr( xObject, uno::UNO_QUERY );
5450 
5451     ScDocShell* pDocSh = GetDocShell();
5452     if ( !pDocSh || !xAddr.is() )
5453     {
5454         OSL_FAIL("no document or no area");
5455         return nullptr;
5456     }
5457 
5458     //! check if xObject is in the same document
5459 
5460     rtl::Reference<ScFilterDescriptor> pNew(new ScFilterDescriptor(pDocSh));  //! instead from object?
5461 
5462     ScQueryParam aParam = pNew->GetParam();
5463     aParam.bHasHeader = true;
5464 
5465     table::CellRangeAddress aDataAddress(xAddr->getRangeAddress());
5466     aParam.nCol1 = static_cast<SCCOL>(aDataAddress.StartColumn);
5467     aParam.nRow1 = static_cast<SCROW>(aDataAddress.StartRow);
5468     aParam.nCol2 = static_cast<SCCOL>(aDataAddress.EndColumn);
5469     aParam.nRow2 = static_cast<SCROW>(aDataAddress.EndRow);
5470     aParam.nTab  = aDataAddress.Sheet;
5471 
5472     ScDocument& rDoc = pDocSh->GetDocument();
5473     if (!rDoc.CreateQueryParam(aRange, aParam))
5474         return nullptr;
5475 
5476     //  FilterDescriptor contains the counted fields inside the area
5477     SCCOLROW nFieldStart = aParam.bByRow ?
5478         static_cast<SCCOLROW>(aDataAddress.StartColumn) :
5479         static_cast<SCCOLROW>(aDataAddress.StartRow);
5480     SCSIZE nCount = aParam.GetEntryCount();
5481     for (SCSIZE i=0; i<nCount; i++)
5482     {
5483         ScQueryEntry& rEntry = aParam.GetEntry(i);
5484         if (rEntry.bDoQuery && rEntry.nField >= nFieldStart)
5485             rEntry.nField -= nFieldStart;
5486     }
5487 
5488     pNew->SetParam( aParam );
5489     return pNew;
5490 }
5491 
5492 // XSubTotalSource
5493 
5494 uno::Reference<sheet::XSubTotalDescriptor> SAL_CALL ScCellRangeObj::createSubTotalDescriptor(
5495                                 sal_Bool bEmpty )
5496 {
5497     SolarMutexGuard aGuard;
5498     rtl::Reference<ScSubTotalDescriptor> pNew = new ScSubTotalDescriptor;
5499     ScDocShell* pDocSh = GetDocShell();
5500     if ( !bEmpty && pDocSh )
5501     {
5502         // create DB-Area only during execution; API always the exact area
5503         ScDBData* pData = pDocSh->GetDBData( aRange, SC_DB_OLD, ScGetDBSelection::ForceMark );
5504         if (pData)
5505         {
5506             ScSubTotalParam aParam;
5507             pData->GetSubTotalParam(aParam);
5508             //  SubTotalDescriptor contains the counted fields inside the area
5509             ScRange aDBRange;
5510             pData->GetArea(aDBRange);
5511             SCCOL nFieldStart = aDBRange.aStart.Col();
5512             for (sal_uInt16 i=0; i<MAXSUBTOTAL; i++)
5513             {
5514                 if ( aParam.bGroupActive[i] )
5515                 {
5516                     if ( aParam.nField[i] >= nFieldStart )
5517                         aParam.nField[i] = sal::static_int_cast<SCCOL>( aParam.nField[i] - nFieldStart );
5518                     for (SCCOL j=0; j<aParam.nSubTotals[i]; j++)
5519                         if ( aParam.pSubTotals[i][j] >= nFieldStart )
5520                             aParam.pSubTotals[i][j] = sal::static_int_cast<SCCOL>( aParam.pSubTotals[i][j] - nFieldStart );
5521                 }
5522             }
5523             pNew->SetParam(aParam);
5524         }
5525     }
5526     return pNew;
5527 }
5528 
5529 void SAL_CALL ScCellRangeObj::applySubTotals(
5530     const uno::Reference<sheet::XSubTotalDescriptor>& xDescriptor,
5531     sal_Bool bReplace)
5532 {
5533     SolarMutexGuard aGuard;
5534 
5535     if (!xDescriptor.is()) return;
5536 
5537     ScDocShell* pDocSh = GetDocShell();
5538     ScSubTotalDescriptorBase* pImp =
5539         comphelper::getFromUnoTunnel<ScSubTotalDescriptorBase>( xDescriptor );
5540 
5541     if (!(pDocSh && pImp))
5542         return;
5543 
5544     ScSubTotalParam aParam;
5545     pImp->GetData(aParam);      // virtual method of base class
5546 
5547     //  SubTotalDescriptor contains the counted fields inside the area
5548     SCCOL nFieldStart = aRange.aStart.Col();
5549     for (sal_uInt16 i=0; i<MAXSUBTOTAL; i++)
5550     {
5551         if ( aParam.bGroupActive[i] )
5552         {
5553             aParam.nField[i] = sal::static_int_cast<SCCOL>( aParam.nField[i] + nFieldStart );
5554             for (SCCOL j=0; j<aParam.nSubTotals[i]; j++)
5555                 aParam.pSubTotals[i][j] = sal::static_int_cast<SCCOL>( aParam.pSubTotals[i][j] + nFieldStart );
5556         }
5557     }
5558 
5559     aParam.bReplace = bReplace;
5560 
5561     SCTAB nTab = aRange.aStart.Tab();
5562     aParam.nCol1 = aRange.aStart.Col();
5563     aParam.nRow1 = aRange.aStart.Row();
5564     aParam.nCol2 = aRange.aEnd.Col();
5565     aParam.nRow2 = aRange.aEnd.Row();
5566 
5567     pDocSh->GetDBData( aRange, SC_DB_MAKE, ScGetDBSelection::ForceMark );   // if needed create area
5568 
5569     ScDBDocFunc aFunc(*pDocSh);
5570     aFunc.DoSubTotals( nTab, aParam, true, true );    // area must be created
5571 }
5572 
5573 void SAL_CALL ScCellRangeObj::removeSubTotals()
5574 {
5575     SolarMutexGuard aGuard;
5576 
5577     ScDocShell* pDocSh = GetDocShell();
5578     if (!pDocSh)
5579         return;
5580 
5581     ScSubTotalParam aParam;
5582     ScDBData* pData = pDocSh->GetDBData( aRange, SC_DB_OLD, ScGetDBSelection::ForceMark );
5583     if (pData)
5584         pData->GetSubTotalParam(aParam);    // also keep field entries during remove
5585 
5586     aParam.bRemoveOnly = true;
5587 
5588     SCTAB nTab = aRange.aStart.Tab();
5589     aParam.nCol1 = aRange.aStart.Col();
5590     aParam.nRow1 = aRange.aStart.Row();
5591     aParam.nCol2 = aRange.aEnd.Col();
5592     aParam.nRow2 = aRange.aEnd.Row();
5593 
5594     pDocSh->GetDBData( aRange, SC_DB_MAKE, ScGetDBSelection::ForceMark );   // if needed create area
5595 
5596     ScDBDocFunc aFunc(*pDocSh);
5597     aFunc.DoSubTotals( nTab, aParam, true, true );    // are must be created
5598 }
5599 
5600 uno::Sequence<beans::PropertyValue> SAL_CALL ScCellRangeObj::createImportDescriptor( sal_Bool bEmpty )
5601 {
5602     SolarMutexGuard aGuard;
5603     ScImportParam aParam;
5604     ScDocShell* pDocSh = GetDocShell();
5605     if ( !bEmpty && pDocSh )
5606     {
5607         // create DB-Area only during execution; API always the exact area
5608         ScDBData* pData = pDocSh->GetDBData( aRange, SC_DB_OLD, ScGetDBSelection::ForceMark );
5609         if (pData)
5610             pData->GetImportParam(aParam);
5611     }
5612 
5613     uno::Sequence<beans::PropertyValue> aSeq( ScImportDescriptor::GetPropertyCount() );
5614     ScImportDescriptor::FillProperties( aSeq, aParam );
5615     return aSeq;
5616 }
5617 
5618 void SAL_CALL ScCellRangeObj::doImport( const uno::Sequence<beans::PropertyValue>& aDescriptor )
5619 {
5620     SolarMutexGuard aGuard;
5621     ScDocShell* pDocSh = GetDocShell();
5622     if (!pDocSh)
5623         return;
5624 
5625     ScImportParam aParam;
5626     ScImportDescriptor::FillImportParam( aParam, aDescriptor );
5627 
5628     SCTAB nTab = aRange.aStart.Tab();
5629     aParam.nCol1 = aRange.aStart.Col();
5630     aParam.nRow1 = aRange.aStart.Row();
5631     aParam.nCol2 = aRange.aEnd.Col();
5632     aParam.nRow2 = aRange.aEnd.Row();
5633 
5634     //! TODO: could we get passed a valid result set by any means?
5635 
5636     pDocSh->GetDBData( aRange, SC_DB_MAKE, ScGetDBSelection::ForceMark );       // if needed create area
5637 
5638     ScDBDocFunc aFunc(*pDocSh);                         // are must be created
5639     aFunc.DoImport( nTab, aParam, nullptr );         //! Api-Flag as parameter
5640 }
5641 
5642 // XCellFormatRangesSupplier
5643 
5644 uno::Reference<container::XIndexAccess> SAL_CALL ScCellRangeObj::getCellFormatRanges()
5645 {
5646     SolarMutexGuard aGuard;
5647     ScDocShell* pDocSh = GetDocShell();
5648     if ( pDocSh )
5649         return new ScCellFormatsObj( pDocSh, aRange );
5650     return nullptr;
5651 }
5652 
5653 // XUniqueCellFormatRangesSupplier
5654 
5655 uno::Reference<container::XIndexAccess> SAL_CALL ScCellRangeObj::getUniqueCellFormatRanges()
5656 {
5657     SolarMutexGuard aGuard;
5658     ScDocShell* pDocSh = GetDocShell();
5659     if ( pDocSh )
5660         return new ScUniqueCellFormatsObj( pDocSh, aRange );
5661     return nullptr;
5662 }
5663 
5664 // XPropertySet extended for Range-Properties
5665 
5666 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScCellRangeObj::getPropertySetInfo()
5667 {
5668     SolarMutexGuard aGuard;
5669     static uno::Reference<beans::XPropertySetInfo> aRef(
5670         new SfxItemPropertySetInfo( pRangePropSet->getPropertyMap() ));
5671     return aRef;
5672 }
5673 
5674 void ScCellRangeObj::SetOnePropertyValue( const SfxItemPropertyMapEntry* pEntry, const uno::Any& aValue )
5675 {
5676     //  Range has only Position and Size in addition to ScCellRangesBase, both are ReadOnly
5677     //  -> nothing to do here
5678 
5679     ScCellRangesBase::SetOnePropertyValue( pEntry, aValue );
5680 }
5681 
5682 void ScCellRangeObj::GetOnePropertyValue( const SfxItemPropertyMapEntry* pEntry, uno::Any& rAny )
5683 {
5684     if ( !pEntry )
5685         return;
5686 
5687     if ( pEntry->nWID == SC_WID_UNO_POS )
5688     {
5689         ScDocShell* pDocSh = GetDocShell();
5690         if (pDocSh)
5691         {
5692             //  GetMMRect converts using HMM_PER_TWIPS, like the DrawingLayer
5693             tools::Rectangle aMMRect(pDocSh->GetDocument().GetMMRect(
5694                                     aRange.aStart.Col(), aRange.aStart.Row(),
5695                                     aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aStart.Tab() ));
5696             awt::Point aPos( aMMRect.Left(), aMMRect.Top() );
5697             rAny <<= aPos;
5698         }
5699     }
5700     else if ( pEntry->nWID == SC_WID_UNO_SIZE )
5701     {
5702         ScDocShell* pDocSh = GetDocShell();
5703         if (pDocSh)
5704         {
5705             //  GetMMRect converts using HMM_PER_TWIPS, like the DrawingLayer
5706             tools::Rectangle aMMRect = pDocSh->GetDocument().GetMMRect(
5707                                     aRange.aStart.Col(), aRange.aStart.Row(),
5708                                     aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aStart.Tab() );
5709             Size aSize(aMMRect.GetSize());
5710             awt::Size aAwtSize( aSize.Width(), aSize.Height() );
5711             rAny <<= aAwtSize;
5712         }
5713     }
5714     else
5715         ScCellRangesBase::GetOnePropertyValue( pEntry, rAny );
5716 }
5717 
5718 const SfxItemPropertyMap& ScCellRangeObj::GetItemPropertyMap()
5719 {
5720     return pRangePropSet->getPropertyMap();
5721 }
5722 
5723 // XServiceInfo
5724 
5725 OUString SAL_CALL ScCellRangeObj::getImplementationName()
5726 {
5727     return "ScCellRangeObj";
5728 }
5729 
5730 sal_Bool SAL_CALL ScCellRangeObj::supportsService( const OUString& rServiceName )
5731 {
5732     return cppu::supportsService(this, rServiceName);
5733 }
5734 
5735 uno::Sequence<OUString> SAL_CALL ScCellRangeObj::getSupportedServiceNames()
5736 {
5737     return {SCSHEETCELLRANGE_SERVICE,
5738             SCCELLRANGE_SERVICE,
5739             SCCELLPROPERTIES_SERVICE,
5740             SCCHARPROPERTIES_SERVICE,
5741             SCPARAPROPERTIES_SERVICE};
5742 }
5743 
5744 const SvxItemPropertySet* ScCellObj::GetEditPropertySet()
5745 {
5746     return lcl_GetEditPropertySet();
5747 }
5748 
5749 const SfxItemPropertyMap& ScCellObj::GetCellPropertyMap()
5750 {
5751     return lcl_GetCellPropertySet()->getPropertyMap();
5752 }
5753 
5754 ScCellObj::ScCellObj(ScDocShell* pDocSh, const ScAddress& rP) :
5755     ScCellRangeObj( pDocSh, ScRange(rP,rP) ),
5756     pCellPropSet( lcl_GetCellPropertySet() ),
5757     aCellPos( rP ),
5758     nActionLockCount( 0 )
5759 {
5760     //  pUnoText is allocated on demand (GetUnoText)
5761     //  can't be aggregated because getString/setString is handled here
5762 }
5763 
5764 SvxUnoText& ScCellObj::GetUnoText()
5765 {
5766     if (!mxUnoText.is())
5767     {
5768         mxUnoText.set(new ScCellTextObj(GetDocShell(), aCellPos));
5769         if (nActionLockCount)
5770         {
5771             ScCellEditSource* pEditSource =
5772                 static_cast<ScCellEditSource*> (mxUnoText->GetEditSource());
5773             if (pEditSource)
5774                 pEditSource->SetDoUpdateData(false);
5775         }
5776     }
5777     return *mxUnoText;
5778 }
5779 
5780 ScCellObj::~ScCellObj()
5781 {
5782 }
5783 
5784 void ScCellObj::RefChanged()
5785 {
5786     ScCellRangeObj::RefChanged();
5787 
5788     const ScRangeList& rRanges = GetRangeList();
5789     OSL_ENSURE(rRanges.size() == 1, "What ranges ?!?!");
5790     if ( !rRanges.empty() )
5791     {
5792         aCellPos = rRanges[ 0 ].aStart;
5793     }
5794 }
5795 
5796 uno::Any SAL_CALL ScCellObj::queryInterface( const uno::Type& rType )
5797 {
5798     SC_QUERYINTERFACE( table::XCell )
5799     SC_QUERYINTERFACE( table::XCell2 )
5800     SC_QUERYINTERFACE( sheet::XFormulaTokens )
5801     SC_QUERYINTERFACE( sheet::XCellAddressable )
5802     SC_QUERYINTERFACE( text::XText )
5803     SC_QUERYINTERFACE( text::XSimpleText )
5804     SC_QUERYINTERFACE( text::XTextRange )
5805     SC_QUERYINTERFACE( container::XEnumerationAccess )
5806     SC_QUERYINTERFACE( container::XElementAccess )
5807     SC_QUERYINTERFACE( sheet::XSheetAnnotationAnchor )
5808     SC_QUERYINTERFACE( text::XTextFieldsSupplier )
5809     SC_QUERYINTERFACE( document::XActionLockable )
5810 
5811     return ScCellRangeObj::queryInterface( rType );
5812 }
5813 
5814 void SAL_CALL ScCellObj::acquire() noexcept
5815 {
5816     ScCellRangeObj::acquire();
5817 }
5818 
5819 void SAL_CALL ScCellObj::release() noexcept
5820 {
5821     ScCellRangeObj::release();
5822 }
5823 
5824 uno::Sequence<uno::Type> SAL_CALL ScCellObj::getTypes()
5825 {
5826     static const uno::Sequence<uno::Type> aTypes = comphelper::concatSequences(
5827         ScCellRangeObj::getTypes(),
5828         uno::Sequence<uno::Type>
5829         {
5830             cppu::UnoType<table::XCell>::get(),
5831             cppu::UnoType<sheet::XCellAddressable>::get(),
5832             cppu::UnoType<text::XText>::get(),
5833             cppu::UnoType<container::XEnumerationAccess>::get(),
5834             cppu::UnoType<sheet::XSheetAnnotationAnchor>::get(),
5835             cppu::UnoType<text::XTextFieldsSupplier>::get(),
5836             cppu::UnoType<document::XActionLockable>::get(),
5837             cppu::UnoType<sheet::XFormulaTokens>::get(),
5838             cppu::UnoType<table::XCell2>::get()
5839         } );
5840     return aTypes;
5841 }
5842 
5843 uno::Sequence<sal_Int8> SAL_CALL ScCellObj::getImplementationId()
5844 {
5845     return css::uno::Sequence<sal_Int8>();
5846 }
5847 
5848 // helper methods
5849 
5850 OUString ScCellObj::GetInputString_Impl(bool bEnglish) const      // for getFormula / FormulaLocal
5851 {
5852     if (GetDocShell())
5853         return lcl_GetInputString( GetDocShell()->GetDocument(), aCellPos, bEnglish );
5854     return OUString();
5855 }
5856 
5857 OUString ScCellObj::GetOutputString_Impl() const
5858 {
5859     ScDocShell* pDocSh = GetDocShell();
5860     OUString aVal;
5861     if ( pDocSh )
5862     {
5863         ScDocument& rDoc = pDocSh->GetDocument();
5864         ScRefCellValue aCell(rDoc, aCellPos);
5865 
5866         aVal = ScCellFormat::GetOutputString(rDoc, aCellPos, aCell);
5867     }
5868     return aVal;
5869 }
5870 
5871 void ScCellObj::SetString_Impl(const OUString& rString, bool bInterpret, bool bEnglish)
5872 {
5873     ScDocShell* pDocSh = GetDocShell();
5874     if ( pDocSh )
5875     {
5876         // GRAM_API for API compatibility.
5877         (void)pDocSh->GetDocFunc().SetCellText(
5878             aCellPos, rString, bInterpret, bEnglish, true, formula::FormulaGrammar::GRAM_API );
5879     }
5880 }
5881 
5882 double ScCellObj::GetValue_Impl() const
5883 {
5884     ScDocShell* pDocSh = GetDocShell();
5885     if ( pDocSh )
5886         return pDocSh->GetDocument().GetValue( aCellPos );
5887 
5888     return 0.0;
5889 }
5890 
5891 void ScCellObj::SetValue_Impl(double fValue)
5892 {
5893     ScDocShell* pDocSh = GetDocShell();
5894     if ( pDocSh )
5895         pDocSh->GetDocFunc().SetValueCell(aCellPos, fValue, false);
5896 }
5897 
5898 // only for XML import
5899 
5900 void ScCellObj::InputEnglishString( const OUString& rText )
5901 {
5902     // This is like a mixture of setFormula and property FormulaLocal:
5903     // The cell's number format is checked for "text", a new cell format may be set,
5904     // but all parsing is in English.
5905 
5906     ScDocShell* pDocSh = GetDocShell();
5907     if (!pDocSh)
5908         return;
5909 
5910     ScDocument& rDoc = pDocSh->GetDocument();
5911     SvNumberFormatter* pFormatter = rDoc.GetFormatTable();
5912     sal_uInt32 nOldFormat = rDoc.GetNumberFormat( aCellPos );
5913     if (pFormatter->GetType(nOldFormat) == SvNumFormatType::TEXT)
5914     {
5915         SetString_Impl(rText, false, false);      // text cell
5916         return;
5917     }
5918 
5919     ScDocFunc &rFunc = pDocSh->GetDocFunc();
5920 
5921     ScInputStringType aRes =
5922         ScStringUtil::parseInputString(*pFormatter, rText, LANGUAGE_ENGLISH_US);
5923 
5924     if (aRes.meType != ScInputStringType::Unknown)
5925     {
5926         if ((nOldFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 && aRes.mnFormatType != SvNumFormatType::ALL)
5927         {
5928             // apply a format for the recognized type and the old format's language
5929             sal_uInt32 nNewFormat = ScGlobal::GetStandardFormat(*pFormatter, nOldFormat, aRes.mnFormatType);
5930             if (nNewFormat != nOldFormat)
5931             {
5932                 ScPatternAttr aPattern( rDoc.GetPool() );
5933                 aPattern.GetItemSet().Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNewFormat ) );
5934                 // ATTR_LANGUAGE_FORMAT remains unchanged
5935                 rFunc.ApplyAttributes( *GetMarkData(), aPattern, true );
5936             }
5937         }
5938     }
5939     switch (aRes.meType)
5940     {
5941         case ScInputStringType::Formula:
5942             rFunc.SetFormulaCell(
5943                 aCellPos,
5944                 new ScFormulaCell(rDoc, aCellPos, aRes.maText, formula::FormulaGrammar::GRAM_API),
5945                 false);
5946         break;
5947         case ScInputStringType::Number:
5948             rFunc.SetValueCell(aCellPos, aRes.mfValue, false);
5949         break;
5950         case ScInputStringType::Text:
5951             rFunc.SetStringOrEditCell(aCellPos, aRes.maText, false);
5952         break;
5953         default:
5954             SetString_Impl(rText, false, false); // probably empty string
5955     }
5956 }
5957 
5958 //  XText
5959 
5960 uno::Reference<text::XTextCursor> SAL_CALL ScCellObj::createTextCursor()
5961 {
5962     SolarMutexGuard aGuard;
5963     return new ScCellTextCursor( *this );
5964 }
5965 
5966 uno::Reference<text::XTextCursor> SAL_CALL ScCellObj::createTextCursorByRange(
5967                                     const uno::Reference<text::XTextRange>& aTextPosition )
5968 {
5969     SolarMutexGuard aGuard;
5970     rtl::Reference<SvxUnoTextCursor> pCursor = new ScCellTextCursor( *this );
5971 
5972     SvxUnoTextRangeBase* pRange = comphelper::getFromUnoTunnel<SvxUnoTextRangeBase>( aTextPosition );
5973     if(pRange)
5974         pCursor->SetSelection( pRange->GetSelection() );
5975     else
5976     {
5977         ScCellTextCursor* pOther = comphelper::getFromUnoTunnel<ScCellTextCursor>( aTextPosition );
5978         if(!pOther)
5979             throw uno::RuntimeException();
5980 
5981         pCursor->SetSelection( pOther->GetSelection() );
5982 
5983     }
5984 
5985     return pCursor;
5986 }
5987 
5988 OUString SAL_CALL ScCellObj::getString()
5989 {
5990     SolarMutexGuard aGuard;
5991     return GetOutputString_Impl();
5992 }
5993 
5994 void SAL_CALL ScCellObj::setString( const OUString& aText )
5995 {
5996     SolarMutexGuard aGuard;
5997     SetString_Impl(aText, false, false);  // always text
5998 
5999     // don't create pUnoText here if not there
6000     if (mxUnoText.is())
6001         mxUnoText->SetSelection(ESelection( 0,0, 0,aText.getLength() ));
6002 }
6003 
6004 void SAL_CALL ScCellObj::insertString( const uno::Reference<text::XTextRange>& xRange,
6005                                         const OUString& aString, sal_Bool bAbsorb )
6006 {
6007     // special handling for ScCellTextCursor is no longer needed,
6008     // SvxUnoText::insertString checks for SvxUnoTextRangeBase instead of SvxUnoTextRange
6009 
6010     SolarMutexGuard aGuard;
6011     GetUnoText().insertString(xRange, aString, bAbsorb);
6012 }
6013 
6014 void SAL_CALL ScCellObj::insertControlCharacter( const uno::Reference<text::XTextRange>& xRange,
6015                                                 sal_Int16 nControlCharacter, sal_Bool bAbsorb )
6016 {
6017     SolarMutexGuard aGuard;
6018     GetUnoText().insertControlCharacter(xRange, nControlCharacter, bAbsorb);
6019 }
6020 
6021 void SAL_CALL ScCellObj::insertTextContent( const uno::Reference<text::XTextRange >& xRange,
6022                                                 const uno::Reference<text::XTextContent >& xContent,
6023                                                 sal_Bool bAbsorb )
6024 {
6025     SolarMutexGuard aGuard;
6026     ScDocShell* pDocSh = GetDocShell();
6027     if ( pDocSh && xContent.is() )
6028     {
6029         ScEditFieldObj* pCellField = comphelper::getFromUnoTunnel<ScEditFieldObj>(xContent);
6030         SvxUnoTextRangeBase* pTextRange = comphelper::getFromUnoTunnel<ScCellTextCursor>( xRange );
6031 
6032         if ( pCellField && !pCellField->IsInserted() && pTextRange )
6033         {
6034             SvxEditSource* pEditSource = pTextRange->GetEditSource();
6035             ESelection aSelection(pTextRange->GetSelection());
6036 
6037             if (!bAbsorb)
6038             {
6039                 //  do not replace -> append
6040                 aSelection.Adjust();
6041                 aSelection.nStartPara = aSelection.nEndPara;
6042                 aSelection.nStartPos  = aSelection.nEndPos;
6043             }
6044 
6045             if (pCellField->GetFieldType() == text::textfield::Type::TABLE)
6046                 pCellField->setPropertyValue(SC_UNONAME_TABLEPOS, uno::makeAny<sal_Int32>(aCellPos.Tab()));
6047 
6048             SvxFieldItem aItem = pCellField->CreateFieldItem();
6049             SvxTextForwarder* pForwarder = pEditSource->GetTextForwarder();
6050             pForwarder->QuickInsertField( aItem, aSelection );
6051             pEditSource->UpdateData();
6052 
6053             //  new selection: a digit
6054             aSelection.Adjust();
6055             aSelection.nEndPara = aSelection.nStartPara;
6056             aSelection.nEndPos = aSelection.nStartPos + 1;
6057             uno::Reference<text::XTextRange> xParent(this);
6058             pCellField->InitDoc(
6059                 xParent, std::make_unique<ScCellEditSource>(pDocSh, aCellPos), aSelection);
6060 
6061             //  for bAbsorb=FALSE, the new selection must be behind the inserted content
6062             //  (the xml filter relies on this)
6063             if (!bAbsorb)
6064                 aSelection.nStartPos = aSelection.nEndPos;
6065 
6066             pTextRange->SetSelection( aSelection );
6067 
6068             return;
6069         }
6070     }
6071     GetUnoText().insertTextContent(xRange, xContent, bAbsorb);
6072 }
6073 
6074 void SAL_CALL ScCellObj::removeTextContent( const uno::Reference<text::XTextContent>& xContent )
6075 {
6076     SolarMutexGuard aGuard;
6077     if ( xContent.is() )
6078     {
6079         ScEditFieldObj* pCellField = comphelper::getFromUnoTunnel<ScEditFieldObj>(xContent);
6080         if ( pCellField && pCellField->IsInserted() )
6081         {
6082             //! Check if field is in this cell
6083             pCellField->DeleteField();
6084             return;
6085         }
6086     }
6087     GetUnoText().removeTextContent(xContent);
6088 }
6089 
6090 uno::Reference<text::XText> SAL_CALL ScCellObj::getText()
6091 {
6092     return this;
6093 }
6094 
6095 uno::Reference<text::XTextRange> SAL_CALL ScCellObj::getStart()
6096 {
6097     SolarMutexGuard aGuard;
6098     return GetUnoText().getStart();
6099 }
6100 
6101 uno::Reference<text::XTextRange> SAL_CALL ScCellObj::getEnd()
6102 {
6103     SolarMutexGuard aGuard;
6104     return GetUnoText().getEnd();
6105 }
6106 
6107 uno::Reference<container::XEnumeration> SAL_CALL ScCellObj::createEnumeration()
6108 {
6109     SolarMutexGuard aGuard;
6110     return GetUnoText().createEnumeration();
6111 }
6112 
6113 uno::Type SAL_CALL ScCellObj::getElementType()
6114 {
6115     SolarMutexGuard aGuard;
6116     return GetUnoText().getElementType();
6117 }
6118 
6119 sal_Bool SAL_CALL ScCellObj::hasElements()
6120 {
6121     SolarMutexGuard aGuard;
6122     return GetUnoText().hasElements();
6123 }
6124 
6125 //  XCell
6126 
6127 OUString SAL_CALL ScCellObj::getFormula()
6128 {
6129     SolarMutexGuard aGuard;
6130     return GetInputString_Impl( true /* English */ );
6131 }
6132 
6133 void SAL_CALL ScCellObj::setFormula( const OUString& aFormula )
6134 {
6135     SolarMutexGuard aGuard;
6136     SetString_Impl(aFormula, true, true); // Interpret as English
6137 }
6138 
6139 double SAL_CALL ScCellObj::getValue()
6140 {
6141     SolarMutexGuard aGuard;
6142     return GetValue_Impl();
6143 }
6144 
6145 void SAL_CALL ScCellObj::setValue( double nValue )
6146 {
6147     SolarMutexGuard aGuard;
6148     SetValue_Impl(nValue);
6149 }
6150 
6151 void SAL_CALL ScCellObj::setFormulaString( const OUString& aFormula)
6152 {
6153     SolarMutexGuard aGuard;
6154     ScDocShell *pDocSh = GetDocShell();
6155     if( pDocSh )
6156     {
6157         ScFormulaCell* pCell = new ScFormulaCell( pDocSh->GetDocument(), aCellPos );
6158         pCell->SetHybridFormula( aFormula, formula::FormulaGrammar::GRAM_NATIVE );
6159         pDocSh->GetDocFunc().SetFormulaCell(aCellPos, pCell, false);
6160     }
6161 }
6162 void SAL_CALL ScCellObj::setFormulaResult( double nValue )
6163 {
6164     SolarMutexGuard aGuard;
6165     ScDocShell* pDocSh = GetDocShell();
6166     if (pDocSh)
6167     {
6168         ScRefCellValue aCell(pDocSh->GetDocument(), aCellPos);
6169         if (aCell.meType == CELLTYPE_FORMULA)
6170         {
6171             ScFormulaCell* pCell = aCell.mpFormula;
6172             pCell->SetHybridDouble( nValue );
6173             pCell->ResetDirty();
6174             pCell->SetChanged(false);
6175         }
6176     }
6177 }
6178 
6179 table::CellContentType SAL_CALL ScCellObj::getType()
6180 {
6181     SolarMutexGuard aGuard;
6182     table::CellContentType eRet = table::CellContentType_EMPTY;
6183     ScDocShell* pDocSh = GetDocShell();
6184     if (pDocSh)
6185     {
6186         CellType eCalcType = pDocSh->GetDocument().GetCellType( aCellPos );
6187         switch (eCalcType)
6188         {
6189             case CELLTYPE_VALUE:
6190                 eRet = table::CellContentType_VALUE;
6191                 break;
6192             case CELLTYPE_STRING:
6193             case CELLTYPE_EDIT:
6194                 eRet = table::CellContentType_TEXT;
6195                 break;
6196             case CELLTYPE_FORMULA:
6197                 eRet = table::CellContentType_FORMULA;
6198                 break;
6199             default:
6200                 eRet = table::CellContentType_EMPTY;
6201         }
6202     }
6203     else
6204     {
6205         OSL_FAIL("no DocShell");     //! Exception or so?
6206     }
6207 
6208     return eRet;
6209 }
6210 
6211 sal_Int32 ScCellObj::GetResultType_Impl() const
6212 {
6213     SolarMutexGuard aGuard;
6214     sal_Int32 eRet = sheet::FormulaResult::STRING;
6215     ScDocShell* pDocSh = GetDocShell();
6216     if (pDocSh)
6217     {
6218         if (pDocSh->GetDocument().GetCellType(aCellPos) == CELLTYPE_FORMULA)
6219         {
6220             ScFormulaCell* pFCell = pDocSh->GetDocument().GetFormulaCell(aCellPos);
6221             if (!pFCell)
6222             {
6223                 // should throw instead of default string?
6224             }
6225             else if (pFCell->GetErrCode() != FormulaError::NONE )
6226             {
6227                 eRet = sheet::FormulaResult::ERROR;
6228             }
6229             else if (pFCell->IsValue())
6230             {
6231                 eRet = sheet::FormulaResult::VALUE;
6232             }
6233             else
6234             {
6235                 eRet = sheet::FormulaResult::STRING;
6236             }
6237         }
6238     }
6239     else
6240     {
6241         OSL_FAIL("no DocShell");
6242     }
6243 
6244     return eRet;
6245 }
6246 
6247 table::CellContentType ScCellObj::GetContentType_Impl()
6248 {
6249     ScDocShell* pDocSh = GetDocShell();
6250     if ( pDocSh )
6251     {
6252         ScRefCellValue aCell(pDocSh->GetDocument(), aCellPos);
6253         if (aCell.meType == CELLTYPE_FORMULA)
6254         {
6255             bool bValue = aCell.mpFormula->IsValue();
6256             return bValue ? table::CellContentType_VALUE : table::CellContentType_TEXT;
6257         }
6258     }
6259     return getType();
6260 }
6261 
6262 sal_Int32 SAL_CALL ScCellObj::getError()
6263 {
6264     SolarMutexGuard aGuard;
6265     ScDocShell* pDocSh = GetDocShell();
6266     if (!pDocSh)
6267     {
6268         OSL_FAIL("no DocShell");     //! Exception or so?
6269         return 0;
6270     }
6271 
6272     FormulaError nError = FormulaError::NONE;
6273     ScRefCellValue aCell(pDocSh->GetDocument(), aCellPos);
6274     if (aCell.meType == CELLTYPE_FORMULA)
6275         nError = aCell.mpFormula->GetErrCode();
6276 
6277     return static_cast<sal_Int32>(nError);
6278 }
6279 
6280 // XFormulaTokens
6281 
6282 uno::Sequence<sheet::FormulaToken> SAL_CALL ScCellObj::getTokens()
6283 {
6284     SolarMutexGuard aGuard;
6285     uno::Sequence<sheet::FormulaToken> aSequence;
6286     ScDocShell* pDocSh = GetDocShell();
6287     if (!pDocSh)
6288         return aSequence;
6289 
6290     ScDocument& rDoc = pDocSh->GetDocument();
6291     ScRefCellValue aCell(rDoc, aCellPos);
6292     if (aCell.meType == CELLTYPE_FORMULA)
6293     {
6294         ScTokenArray* pTokenArray = aCell.mpFormula->GetCode();
6295         if (pTokenArray)
6296             ScTokenConversion::ConvertToTokenSequence(rDoc, aSequence, *pTokenArray);
6297     }
6298     return aSequence;
6299 }
6300 
6301 void SAL_CALL ScCellObj::setTokens( const uno::Sequence<sheet::FormulaToken>& rTokens )
6302 {
6303     SolarMutexGuard aGuard;
6304     ScDocShell* pDocSh = GetDocShell();
6305     if ( pDocSh )
6306     {
6307         ScDocument& rDoc = pDocSh->GetDocument();
6308         ScTokenArray aTokenArray(rDoc);
6309         (void)ScTokenConversion::ConvertToTokenArray( rDoc, aTokenArray, rTokens );
6310 
6311         ScFormulaCell* pNewCell = new ScFormulaCell(rDoc, aCellPos, aTokenArray);
6312         (void)pDocSh->GetDocFunc().SetFormulaCell(aCellPos, pNewCell, false);
6313     }
6314 }
6315 
6316 // XCellAddressable
6317 
6318 table::CellAddress SAL_CALL ScCellObj::getCellAddress()
6319 {
6320     SolarMutexGuard aGuard;
6321     table::CellAddress aAdr;
6322     aAdr.Sheet  = aCellPos.Tab();
6323     aAdr.Column = aCellPos.Col();
6324     aAdr.Row    = aCellPos.Row();
6325     return aAdr;
6326 }
6327 
6328 // XSheetAnnotationAnchor
6329 
6330 uno::Reference<sheet::XSheetAnnotation> SAL_CALL ScCellObj::getAnnotation()
6331 {
6332     SolarMutexGuard aGuard;
6333     ScDocShell* pDocSh = GetDocShell();
6334     if ( pDocSh )
6335         return new ScAnnotationObj( pDocSh, aCellPos );
6336 
6337     OSL_FAIL("getAnnotation without DocShell");
6338     return nullptr;
6339 }
6340 
6341 // XFieldTypesSupplier
6342 
6343 uno::Reference<container::XEnumerationAccess> SAL_CALL ScCellObj::getTextFields()
6344 {
6345     SolarMutexGuard aGuard;
6346     ScDocShell* pDocSh = GetDocShell();
6347     if ( pDocSh )
6348     {
6349         uno::Reference<text::XTextRange> xContent(this);
6350         return new ScCellFieldsObj(xContent, pDocSh, aCellPos);
6351     }
6352 
6353     return nullptr;
6354 }
6355 
6356 uno::Reference<container::XNameAccess> SAL_CALL ScCellObj::getTextFieldMasters()
6357 {
6358     //  there is no such thing in Calc (?)
6359     return nullptr;
6360 }
6361 
6362 // XPropertySet extended for Cell-Properties
6363 
6364 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScCellObj::getPropertySetInfo()
6365 {
6366     SolarMutexGuard aGuard;
6367     static uno::Reference<beans::XPropertySetInfo> aRef(
6368         new SfxItemPropertySetInfo( pCellPropSet->getPropertyMap() ));
6369     return aRef;
6370 }
6371 
6372 void ScCellObj::SetOnePropertyValue( const SfxItemPropertyMapEntry* pEntry, const uno::Any& aValue )
6373 {
6374     if ( !pEntry )
6375         return;
6376 
6377     if ( pEntry->nWID == SC_WID_UNO_FORMLOC )
6378     {
6379         OUString aStrVal;
6380         aValue >>= aStrVal;
6381         SetString_Impl(aStrVal, true, false);   // interpret locally
6382     }
6383     else if ( pEntry->nWID == SC_WID_UNO_FORMRT || pEntry->nWID == SC_WID_UNO_FORMRT2
6384               || pEntry->nWID == SC_WID_UNO_CELLCONTENTTYPE )
6385     {
6386         //  Read-Only
6387         //! Exception or so...
6388     }
6389     else
6390         ScCellRangeObj::SetOnePropertyValue( pEntry, aValue );
6391 }
6392 
6393 void ScCellObj::GetOnePropertyValue( const SfxItemPropertyMapEntry* pEntry, uno::Any& rAny )
6394 {
6395     if ( !pEntry )
6396         return;
6397 
6398     if ( pEntry->nWID == SC_WID_UNO_FORMLOC )
6399     {
6400         // sal_False = local
6401         rAny <<= GetInputString_Impl(false);
6402     }
6403     else if ( pEntry->nWID == SC_WID_UNO_FORMRT2 )
6404     {
6405         sal_Int32 eType = GetResultType_Impl();
6406         rAny <<= eType;
6407     }
6408     else if ( pEntry->nWID == SC_WID_UNO_CELLCONTENTTYPE || pEntry->nWID == SC_WID_UNO_FORMRT )
6409     {
6410         table::CellContentType eType = GetContentType_Impl();
6411         rAny <<= eType;
6412     }
6413     else
6414         ScCellRangeObj::GetOnePropertyValue(pEntry, rAny);
6415 }
6416 
6417 const SfxItemPropertyMap& ScCellObj::GetItemPropertyMap()
6418 {
6419     return pCellPropSet->getPropertyMap();
6420 }
6421 
6422 // XServiceInfo
6423 
6424 OUString SAL_CALL ScCellObj::getImplementationName()
6425 {
6426     return "ScCellObj";
6427 }
6428 
6429 sal_Bool SAL_CALL ScCellObj::supportsService( const OUString& rServiceName )
6430 {
6431     return cppu::supportsService(this, rServiceName);
6432 }
6433 
6434 uno::Sequence<OUString> SAL_CALL ScCellObj::getSupportedServiceNames()
6435 {
6436     return {SCSHEETCELL_SERVICE,
6437             SCCELL_SERVICE,
6438             SCCELLPROPERTIES_SERVICE,
6439             SCCHARPROPERTIES_SERVICE,
6440             SCPARAPROPERTIES_SERVICE,
6441             SCSHEETCELLRANGE_SERVICE,
6442             SCCELLRANGE_SERVICE};
6443 }
6444 
6445 // XActionLockable
6446 
6447 sal_Bool SAL_CALL ScCellObj::isActionLocked()
6448 {
6449     SolarMutexGuard aGuard;
6450     return nActionLockCount != 0;
6451 }
6452 
6453 void SAL_CALL ScCellObj::addActionLock()
6454 {
6455     SolarMutexGuard aGuard;
6456     if (!nActionLockCount)
6457     {
6458         if (mxUnoText.is())
6459         {
6460             ScCellEditSource* pEditSource =
6461                 static_cast<ScCellEditSource*> (mxUnoText->GetEditSource());
6462             if (pEditSource)
6463                 pEditSource->SetDoUpdateData(false);
6464         }
6465     }
6466     nActionLockCount++;
6467 }
6468 
6469 void SAL_CALL ScCellObj::removeActionLock()
6470 {
6471     SolarMutexGuard aGuard;
6472     if (nActionLockCount <= 0)
6473         return;
6474 
6475     nActionLockCount--;
6476     if (nActionLockCount)
6477         return;
6478 
6479     if (mxUnoText.is())
6480     {
6481         ScCellEditSource* pEditSource =
6482             static_cast<ScCellEditSource*> (mxUnoText->GetEditSource());
6483         if (pEditSource)
6484         {
6485             pEditSource->SetDoUpdateData(true);
6486             if (pEditSource->IsDirty())
6487                 pEditSource->UpdateData();
6488         }
6489     }
6490 }
6491 
6492 void SAL_CALL ScCellObj::setActionLocks( sal_Int16 nLock )
6493 {
6494     SolarMutexGuard aGuard;
6495     if (mxUnoText.is())
6496     {
6497         ScCellEditSource* pEditSource =
6498             static_cast<ScCellEditSource*> (mxUnoText->GetEditSource());
6499         if (pEditSource)
6500         {
6501             pEditSource->SetDoUpdateData(nLock == 0);
6502             if ((nActionLockCount > 0) && (nLock == 0) && pEditSource->IsDirty())
6503                 pEditSource->UpdateData();
6504         }
6505     }
6506     nActionLockCount = nLock;
6507 }
6508 
6509 sal_Int16 SAL_CALL ScCellObj::resetActionLocks()
6510 {
6511     SolarMutexGuard aGuard;
6512     sal_uInt16 nRet(nActionLockCount);
6513     if (mxUnoText.is())
6514     {
6515         ScCellEditSource* pEditSource =
6516             static_cast<ScCellEditSource*> (mxUnoText->GetEditSource());
6517         if (pEditSource)
6518         {
6519             pEditSource->SetDoUpdateData(true);
6520             if (pEditSource->IsDirty())
6521                 pEditSource->UpdateData();
6522         }
6523     }
6524     nActionLockCount = 0;
6525     return nRet;
6526 }
6527 
6528 static ScRange MaxDocRange(ScDocShell* pDocSh, SCTAB nTab)
6529 {
6530     const SCCOL nMaxcol = pDocSh ? pDocSh->GetDocument().MaxCol() : MAXCOL;
6531     const SCROW nMaxRow = pDocSh ? pDocSh->GetDocument().MaxRow() : MAXROW;
6532     return ScRange(0, 0, nTab, nMaxcol, nMaxRow, nTab);
6533 }
6534 
6535 ScTableSheetObj::ScTableSheetObj( ScDocShell* pDocSh, SCTAB nTab ) :
6536     ScCellRangeObj( pDocSh, MaxDocRange(pDocSh, nTab) ),
6537     pSheetPropSet(lcl_GetSheetPropertySet())
6538 {
6539 }
6540 
6541 ScTableSheetObj::~ScTableSheetObj()
6542 {
6543 }
6544 
6545 void ScTableSheetObj::InitInsertSheet(ScDocShell* pDocSh, SCTAB nTab)
6546 {
6547     ScDocument& rDoc = pDocSh->GetDocument();
6548     InitInsertRange( pDocSh, ScRange(0,0,nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab) );
6549 }
6550 
6551 uno::Any SAL_CALL ScTableSheetObj::queryInterface( const uno::Type& rType )
6552 {
6553     SC_QUERYINTERFACE( sheet::XSpreadsheet )
6554     SC_QUERYINTERFACE( container::XNamed )
6555     SC_QUERYINTERFACE( sheet::XSheetPageBreak )
6556     SC_QUERYINTERFACE( sheet::XCellRangeMovement )
6557     SC_QUERYINTERFACE( table::XTableChartsSupplier )
6558     SC_QUERYINTERFACE( sheet::XDataPilotTablesSupplier )
6559     SC_QUERYINTERFACE( sheet::XScenariosSupplier )
6560     SC_QUERYINTERFACE( sheet::XSheetAnnotationsSupplier )
6561     SC_QUERYINTERFACE( drawing::XDrawPageSupplier )
6562     SC_QUERYINTERFACE( sheet::XPrintAreas )
6563     SC_QUERYINTERFACE( sheet::XSheetAuditing )
6564     SC_QUERYINTERFACE( sheet::XSheetOutline )
6565     SC_QUERYINTERFACE( util::XProtectable )
6566     SC_QUERYINTERFACE( sheet::XScenario )
6567     SC_QUERYINTERFACE( sheet::XScenarioEnhanced )
6568     SC_QUERYINTERFACE( sheet::XSheetLinkable )
6569     SC_QUERYINTERFACE( sheet::XExternalSheetName )
6570     SC_QUERYINTERFACE( document::XEventsSupplier )
6571     SC_QUERYINTERFACE( table::XTablePivotChartsSupplier )
6572 
6573     return ScCellRangeObj::queryInterface( rType );
6574 }
6575 
6576 void SAL_CALL ScTableSheetObj::acquire() noexcept
6577 {
6578     ScCellRangeObj::acquire();
6579 }
6580 
6581 void SAL_CALL ScTableSheetObj::release() noexcept
6582 {
6583     ScCellRangeObj::release();
6584 }
6585 
6586 uno::Sequence<uno::Type> SAL_CALL ScTableSheetObj::getTypes()
6587 {
6588     static const uno::Sequence<uno::Type> aTypes = comphelper::concatSequences(
6589         ScCellRangeObj::getTypes(),
6590         uno::Sequence<uno::Type>
6591         {
6592             cppu::UnoType<sheet::XSpreadsheet>::get(),
6593             cppu::UnoType<container::XNamed>::get(),
6594             cppu::UnoType<sheet::XSheetPageBreak>::get(),
6595             cppu::UnoType<sheet::XCellRangeMovement>::get(),
6596             cppu::UnoType<table::XTableChartsSupplier>::get(),
6597             cppu::UnoType<sheet::XDataPilotTablesSupplier>::get(),
6598             cppu::UnoType<sheet::XScenariosSupplier>::get(),
6599             cppu::UnoType<sheet::XSheetAnnotationsSupplier>::get(),
6600             cppu::UnoType<drawing::XDrawPageSupplier>::get(),
6601             cppu::UnoType<sheet::XPrintAreas>::get(),
6602             cppu::UnoType<sheet::XSheetAuditing>::get(),
6603             cppu::UnoType<sheet::XSheetOutline>::get(),
6604             cppu::UnoType<util::XProtectable>::get(),
6605             cppu::UnoType<sheet::XScenario>::get(),
6606             cppu::UnoType<sheet::XScenarioEnhanced>::get(),
6607             cppu::UnoType<sheet::XSheetLinkable>::get(),
6608             cppu::UnoType<sheet::XExternalSheetName>::get(),
6609             cppu::UnoType<document::XEventsSupplier>::get(),
6610             cppu::UnoType<table::XTablePivotChartsSupplier>::get()
6611         } );
6612     return aTypes;
6613 }
6614 
6615 uno::Sequence<sal_Int8> SAL_CALL ScTableSheetObj::getImplementationId()
6616 {
6617     return css::uno::Sequence<sal_Int8>();
6618 }
6619 
6620 //  Helper functions
6621 
6622 SCTAB ScTableSheetObj::GetTab_Impl() const
6623 {
6624     const ScRangeList& rRanges = GetRangeList();
6625     OSL_ENSURE(rRanges.size() == 1, "What ranges ?!?!");
6626     if ( !rRanges.empty() )
6627     {
6628         return rRanges[ 0 ].aStart.Tab();
6629     }
6630     return 0;
6631 }
6632 
6633 // former XSheet
6634 
6635 uno::Reference<table::XTableCharts> SAL_CALL ScTableSheetObj::getCharts()
6636 {
6637     SolarMutexGuard aGuard;
6638     ScDocShell* pDocSh = GetDocShell();
6639     if ( pDocSh )
6640         return new ScChartsObj( pDocSh, GetTab_Impl() );
6641 
6642     OSL_FAIL("no document");
6643     return nullptr;
6644 }
6645 
6646 uno::Reference<table::XTablePivotCharts> SAL_CALL ScTableSheetObj::getPivotCharts()
6647 {
6648     SolarMutexGuard aGuard;
6649     ScDocShell* pDocSh = GetDocShell();
6650     if (pDocSh)
6651         return new sc::TablePivotCharts(pDocSh, GetTab_Impl());
6652 
6653     OSL_FAIL("no document");
6654     return nullptr;
6655 }
6656 
6657 uno::Reference<sheet::XDataPilotTables> SAL_CALL ScTableSheetObj::getDataPilotTables()
6658 {
6659     SolarMutexGuard aGuard;
6660     ScDocShell* pDocSh = GetDocShell();
6661     if ( pDocSh )
6662         return new ScDataPilotTablesObj( pDocSh, GetTab_Impl() );
6663 
6664     OSL_FAIL("no document");
6665     return nullptr;
6666 }
6667 
6668 uno::Reference<sheet::XScenarios> SAL_CALL ScTableSheetObj::getScenarios()
6669 {
6670     SolarMutexGuard aGuard;
6671     ScDocShell* pDocSh = GetDocShell();
6672 
6673     if ( pDocSh )
6674         return new ScScenariosObj( pDocSh, GetTab_Impl() );
6675 
6676     OSL_FAIL("no document");
6677     return nullptr;
6678 }
6679 
6680 uno::Reference<sheet::XSheetAnnotations> SAL_CALL ScTableSheetObj::getAnnotations()
6681 {
6682     SolarMutexGuard aGuard;
6683     ScDocShell* pDocSh = GetDocShell();
6684 
6685     if ( pDocSh )
6686         return new ScAnnotationsObj( pDocSh, GetTab_Impl() );
6687 
6688     OSL_FAIL("no document");
6689     return nullptr;
6690 }
6691 
6692 uno::Reference<table::XCellRange> SAL_CALL ScTableSheetObj::getCellRangeByName(
6693                         const OUString& rRange )
6694 {
6695     SolarMutexGuard aGuard;
6696     return ScCellRangeObj::getCellRangeByName( rRange );
6697 }
6698 
6699 uno::Reference<sheet::XSheetCellCursor> SAL_CALL ScTableSheetObj::createCursor()
6700 {
6701     SolarMutexGuard aGuard;
6702     ScDocShell* pDocSh = GetDocShell();
6703     if ( pDocSh )
6704     {
6705         //! single cell or whole table??????
6706         const ScDocument& rDoc = pDocSh->GetDocument();
6707         SCTAB nTab = GetTab_Impl();
6708         return new ScCellCursorObj( pDocSh, ScRange( 0,0,nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab ) );
6709     }
6710     return nullptr;
6711 }
6712 
6713 uno::Reference<sheet::XSheetCellCursor> SAL_CALL ScTableSheetObj::createCursorByRange(
6714                         const uno::Reference<sheet::XSheetCellRange>& xCellRange )
6715 {
6716     SolarMutexGuard aGuard;
6717     ScDocShell* pDocSh = GetDocShell();
6718     if ( pDocSh && xCellRange.is() )
6719     {
6720         ScCellRangesBase* pRangesImp = comphelper::getFromUnoTunnel<ScCellRangesBase>( xCellRange );
6721         if (pRangesImp)
6722         {
6723             const ScRangeList& rRanges = pRangesImp->GetRangeList();
6724             OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" );
6725             return new ScCellCursorObj( pDocSh, rRanges[ 0 ] );
6726         }
6727     }
6728     return nullptr;
6729 }
6730 
6731 // XSheetCellRange
6732 
6733 uno::Reference<sheet::XSpreadsheet> SAL_CALL ScTableSheetObj::getSpreadsheet()
6734 {
6735     return this;        //!???
6736 }
6737 
6738 // XCellRange
6739 
6740 uno::Reference<table::XCell> SAL_CALL ScTableSheetObj::getCellByPosition(
6741                                         sal_Int32 nColumn, sal_Int32 nRow )
6742 {
6743     SolarMutexGuard aGuard;
6744     return ScCellRangeObj::GetCellByPosition_Impl(nColumn, nRow);
6745 }
6746 
6747 uno::Reference<table::XCellRange> SAL_CALL ScTableSheetObj::getCellRangeByPosition(
6748                 sal_Int32 nLeft, sal_Int32 nTop, sal_Int32 nRight, sal_Int32 nBottom )
6749 {
6750     SolarMutexGuard aGuard;
6751     return ScCellRangeObj::getCellRangeByPosition(nLeft,nTop,nRight,nBottom);
6752 }
6753 
6754 uno::Sequence<sheet::TablePageBreakData> SAL_CALL ScTableSheetObj::getColumnPageBreaks()
6755 {
6756     SolarMutexGuard aGuard;
6757     ScDocShell* pDocSh = GetDocShell();
6758     if ( pDocSh )
6759     {
6760         ScDocument& rDoc = pDocSh->GetDocument();
6761         SCTAB nTab = GetTab_Impl();
6762 
6763         Size aSize(rDoc.GetPageSize( nTab ));
6764         if (aSize.Width() && aSize.Height())        // effective size already set?
6765             rDoc.UpdatePageBreaks( nTab );
6766         else
6767         {
6768             //  update breaks like in ScDocShell::PageStyleModified:
6769             ScPrintFunc aPrintFunc( pDocSh, pDocSh->GetPrinter(), nTab );
6770             aPrintFunc.UpdatePages();
6771         }
6772 
6773         SCCOL nCount = 0;
6774         for (SCCOL nCol : rDoc.GetColumnsRange(nTab, 0, rDoc.MaxCol()))
6775             if (rDoc.HasColBreak(nCol, nTab) != ScBreakType::NONE)
6776                 ++nCount;
6777 
6778         sheet::TablePageBreakData aData;
6779         uno::Sequence<sheet::TablePageBreakData> aSeq(nCount);
6780         sheet::TablePageBreakData* pAry = aSeq.getArray();
6781         sal_uInt16 nPos = 0;
6782         for (SCCOL nCol : rDoc.GetColumnsRange(nTab, 0, rDoc.MaxCol()))
6783         {
6784             ScBreakType nBreak = rDoc.HasColBreak(nCol, nTab);
6785             if (nBreak != ScBreakType::NONE)
6786             {
6787                 aData.Position    = nCol;
6788                 aData.ManualBreak = bool(nBreak & ScBreakType::Manual);
6789                 pAry[nPos] = aData;
6790                 ++nPos;
6791             }
6792         }
6793         return aSeq;
6794     }
6795     return {};
6796 }
6797 
6798 uno::Sequence<sheet::TablePageBreakData> SAL_CALL ScTableSheetObj::getRowPageBreaks()
6799 {
6800     SolarMutexGuard aGuard;
6801     ScDocShell* pDocSh = GetDocShell();
6802     if ( pDocSh )
6803     {
6804         ScDocument& rDoc = pDocSh->GetDocument();
6805         SCTAB nTab = GetTab_Impl();
6806 
6807         Size aSize(rDoc.GetPageSize( nTab ));
6808         if (aSize.Width() && aSize.Height())        // effective size already set?
6809             rDoc.UpdatePageBreaks( nTab );
6810         else
6811         {
6812             //  update breaks like in ScDocShell::PageStyleModified:
6813             ScPrintFunc aPrintFunc( pDocSh, pDocSh->GetPrinter(), nTab );
6814             aPrintFunc.UpdatePages();
6815         }
6816         return rDoc.GetRowBreakData(nTab);
6817     }
6818     return {};
6819 }
6820 
6821 void SAL_CALL ScTableSheetObj::removeAllManualPageBreaks()
6822 {
6823     SolarMutexGuard aGuard;
6824     ScDocShell* pDocSh = GetDocShell();
6825     if ( !pDocSh )
6826         return;
6827 
6828     //! DocFunc function, also for ScViewFunc::RemoveManualBreaks
6829 
6830     ScDocument& rDoc = pDocSh->GetDocument();
6831     bool bUndo (rDoc.IsUndoEnabled());
6832     SCTAB nTab = GetTab_Impl();
6833 
6834     if (bUndo)
6835     {
6836         ScDocumentUniquePtr pUndoDoc(new ScDocument( SCDOCMODE_UNDO ));
6837         pUndoDoc->InitUndo( rDoc, nTab, nTab, true, true );
6838         rDoc.CopyToDocument(0,0,nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab, InsertDeleteFlags::NONE, false, *pUndoDoc);
6839         pDocSh->GetUndoManager()->AddUndoAction(
6840                                 std::make_unique<ScUndoRemoveBreaks>( pDocSh, nTab, std::move(pUndoDoc) ) );
6841     }
6842 
6843     rDoc.RemoveManualBreaks(nTab);
6844     rDoc.UpdatePageBreaks(nTab);
6845 
6846     //? UpdatePageBreakData( sal_True );
6847     pDocSh->SetDocumentModified();
6848     pDocSh->PostPaint(ScRange(0, 0, nTab, rDoc.MaxCol(), rDoc.MaxRow(), nTab), PaintPartFlags::Grid);
6849 }
6850 
6851 // XNamed
6852 
6853 OUString SAL_CALL ScTableSheetObj::getName()
6854 {
6855     SolarMutexGuard aGuard;
6856     OUString aName;
6857     ScDocShell* pDocSh = GetDocShell();
6858     if ( pDocSh )
6859         pDocSh->GetDocument().GetName( GetTab_Impl(), aName );
6860     return aName;
6861 }
6862 
6863 void SAL_CALL ScTableSheetObj::setName( const OUString& aNewName )
6864 {
6865     SolarMutexGuard aGuard;
6866     ScDocShell* pDocSh = GetDocShell();
6867     if ( pDocSh )
6868     {
6869         pDocSh->GetDocFunc().RenameTable( GetTab_Impl(), aNewName, true, true );
6870     }
6871 }
6872 
6873 // XDrawPageSupplier
6874 
6875 uno::Reference<drawing::XDrawPage> SAL_CALL ScTableSheetObj::getDrawPage()
6876 {
6877     SolarMutexGuard aGuard;
6878     ScDocShell* pDocSh = GetDocShell();
6879     if ( pDocSh )
6880     {
6881         ScDrawLayer* pDrawLayer = pDocSh->MakeDrawLayer();
6882         OSL_ENSURE(pDrawLayer,"Cannot create Draw-Layer");
6883 
6884         SCTAB nTab = GetTab_Impl();
6885         SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
6886         OSL_ENSURE(pPage,"Draw-Page not found");
6887         if (pPage)
6888             return uno::Reference<drawing::XDrawPage> (pPage->getUnoPage(), uno::UNO_QUERY);
6889 
6890         //  The DrawPage object will register itself as a Listener at SdrModel
6891         //  and should receive all action from there
6892     }
6893     return nullptr;
6894 }
6895 
6896 // XCellMovement
6897 
6898 void SAL_CALL ScTableSheetObj::insertCells( const table::CellRangeAddress& rRangeAddress,
6899                                 sheet::CellInsertMode nMode )
6900 {
6901     SolarMutexGuard aGuard;
6902     ScDocShell* pDocSh = GetDocShell();
6903     if ( !pDocSh )
6904         return;
6905 
6906     bool bDo = true;
6907     InsCellCmd eCmd = INS_NONE;
6908     switch (nMode)
6909     {
6910         case sheet::CellInsertMode_NONE:    bDo = false;                break;
6911         case sheet::CellInsertMode_DOWN:    eCmd = INS_CELLSDOWN;       break;
6912         case sheet::CellInsertMode_RIGHT:   eCmd = INS_CELLSRIGHT;      break;
6913         case sheet::CellInsertMode_ROWS:    eCmd = INS_INSROWS_BEFORE;  break;
6914         case sheet::CellInsertMode_COLUMNS: eCmd = INS_INSCOLS_BEFORE;  break;
6915         default:
6916             OSL_FAIL("insertCells: wrong mode");
6917             bDo = false;
6918     }
6919 
6920     if (bDo)
6921     {
6922         OSL_ENSURE( rRangeAddress.Sheet == GetTab_Impl(), "wrong table in CellRangeAddress" );
6923         ScRange aScRange;
6924         ScUnoConversion::FillScRange( aScRange, rRangeAddress );
6925         (void)pDocSh->GetDocFunc().InsertCells( aScRange, nullptr, eCmd, true, true );
6926     }
6927 }
6928 
6929 void SAL_CALL ScTableSheetObj::removeRange( const table::CellRangeAddress& rRangeAddress,
6930                                 sheet::CellDeleteMode nMode )
6931 {
6932     SolarMutexGuard aGuard;
6933     ScDocShell* pDocSh = GetDocShell();
6934     if ( !pDocSh )
6935         return;
6936 
6937     bool bDo = true;
6938     DelCellCmd eCmd = DelCellCmd::NONE;
6939     switch (nMode)
6940     {
6941         case sheet::CellDeleteMode_NONE:     bDo = false;           break;
6942         case sheet::CellDeleteMode_UP:       eCmd = DelCellCmd::CellsUp;    break;
6943         case sheet::CellDeleteMode_LEFT:     eCmd = DelCellCmd::CellsLeft;  break;
6944         case sheet::CellDeleteMode_ROWS:     eCmd = DelCellCmd::Rows;    break;
6945         case sheet::CellDeleteMode_COLUMNS:  eCmd = DelCellCmd::Cols;    break;
6946         default:
6947             OSL_FAIL("deleteCells: wrong mode");
6948             bDo = false;
6949     }
6950 
6951     if (bDo)
6952     {
6953         OSL_ENSURE( rRangeAddress.Sheet == GetTab_Impl(), "wrong table in CellRangeAddress" );
6954         ScRange aScRange;
6955         ScUnoConversion::FillScRange( aScRange, rRangeAddress );
6956         (void)pDocSh->GetDocFunc().DeleteCells( aScRange, nullptr, eCmd, true );
6957     }
6958 }
6959 
6960 void SAL_CALL ScTableSheetObj::moveRange( const table::CellAddress& aDestination,
6961                                         const table::CellRangeAddress& aSource )
6962 {
6963     SolarMutexGuard aGuard;
6964     ScDocShell* pDocSh = GetDocShell();
6965     if ( pDocSh )
6966     {
6967         OSL_ENSURE( aSource.Sheet == GetTab_Impl(), "wrong table in CellRangeAddress" );
6968         ScRange aSourceRange;
6969         ScUnoConversion::FillScRange( aSourceRange, aSource );
6970         ScAddress aDestPos( static_cast<SCCOL>(aDestination.Column), static_cast<SCROW>(aDestination.Row), aDestination.Sheet );
6971         (void)pDocSh->GetDocFunc().MoveBlock( aSourceRange, aDestPos, true, true, true, true );
6972     }
6973 }
6974 
6975 void SAL_CALL ScTableSheetObj::copyRange( const table::CellAddress& aDestination,
6976                                         const table::CellRangeAddress& aSource )
6977 {
6978     SolarMutexGuard aGuard;
6979     ScDocShell* pDocSh = GetDocShell();
6980     if ( pDocSh )
6981     {
6982         OSL_ENSURE( aSource.Sheet == GetTab_Impl(), "wrong table in CellRangeAddress" );
6983         ScRange aSourceRange;
6984         ScUnoConversion::FillScRange( aSourceRange, aSource );
6985         ScAddress aDestPos( static_cast<SCCOL>(aDestination.Column), static_cast<SCROW>(aDestination.Row), aDestination.Sheet );
6986         (void)pDocSh->GetDocFunc().MoveBlock( aSourceRange, aDestPos, false, true, true, true );
6987     }
6988 }
6989 
6990 // XPrintAreas
6991 
6992 void ScTableSheetObj::PrintAreaUndo_Impl( std::unique_ptr<ScPrintRangeSaver> pOldRanges )
6993 {
6994     //  page break and undo
6995     ScDocShell* pDocSh = GetDocShell();
6996 
6997     if(!pDocSh)
6998         return;
6999 
7000     ScDocument& rDoc = pDocSh->GetDocument();
7001     const bool bUndo(rDoc.IsUndoEnabled());
7002     const SCTAB nTab(GetTab_Impl());
7003 
7004     if(bUndo)
7005     {
7006         pDocSh->GetUndoManager()->AddUndoAction(
7007             std::make_unique<ScUndoPrintRange>(
7008                 pDocSh,
7009                 nTab,
7010                 std::move(pOldRanges),
7011                 rDoc.CreatePrintRangeSaver())); // create new ranges
7012     }
7013 
7014     ScPrintFunc(pDocSh, pDocSh->GetPrinter(), nTab).UpdatePages();
7015     SfxBindings* pBindings = pDocSh->GetViewBindings();
7016 
7017     if(pBindings)
7018     {
7019         pBindings->Invalidate(SID_DELETE_PRINTAREA);
7020     }
7021 
7022     pDocSh->SetDocumentModified();
7023 }
7024 
7025 uno::Sequence<table::CellRangeAddress> SAL_CALL ScTableSheetObj::getPrintAreas()
7026 {
7027     SolarMutexGuard aGuard;
7028     ScDocShell* pDocSh = GetDocShell();
7029     if ( pDocSh )
7030     {
7031         ScDocument& rDoc = pDocSh->GetDocument();
7032         SCTAB nTab = GetTab_Impl();
7033         sal_uInt16 nCount = rDoc.GetPrintRangeCount( nTab );
7034 
7035         table::CellRangeAddress aRangeAddress;
7036         uno::Sequence<table::CellRangeAddress> aSeq(nCount);
7037         table::CellRangeAddress* pAry = aSeq.getArray();
7038         for (sal_uInt16 i=0; i<nCount; i++)
7039         {
7040             const ScRange* pRange = rDoc.GetPrintRange( nTab, i );
7041             OSL_ENSURE(pRange,"where is the printing area");
7042             if (pRange)
7043             {
7044                 ScUnoConversion::FillApiRange( aRangeAddress, *pRange );
7045                 aRangeAddress.Sheet = nTab; // core does not care about sheet index
7046                 pAry[i] = aRangeAddress;
7047             }
7048         }
7049         return aSeq;
7050     }
7051     return uno::Sequence<table::CellRangeAddress>();
7052 }
7053 
7054 void SAL_CALL ScTableSheetObj::setPrintAreas(
7055                     const uno::Sequence<table::CellRangeAddress>& aPrintAreas )
7056 {
7057     SolarMutexGuard aGuard;
7058     ScDocShell* pDocSh = GetDocShell();
7059     if ( !pDocSh )
7060         return;
7061 
7062     std::unique_ptr<ScPrintRangeSaver> pOldRanges;
7063     ScDocument& rDoc = pDocSh->GetDocument();
7064     SCTAB nTab = GetTab_Impl();
7065 
7066     if ( rDoc.IsUndoEnabled() )
7067         pOldRanges = rDoc.CreatePrintRangeSaver();
7068 
7069     sal_uInt16 nCount = static_cast<sal_uInt16>(aPrintAreas.getLength());
7070     rDoc.ClearPrintRanges( nTab );
7071     if (nCount)
7072     {
7073         ScRange aPrintRange;
7074         for (const table::CellRangeAddress& rPrintArea : aPrintAreas)
7075         {
7076             ScUnoConversion::FillScRange( aPrintRange, rPrintArea );
7077             rDoc.AddPrintRange( nTab, aPrintRange );
7078         }
7079     }
7080 
7081     if ( rDoc.IsUndoEnabled() )
7082         PrintAreaUndo_Impl( std::move(pOldRanges) );   // Undo, Page Breaks, Modified etc.
7083 }
7084 
7085 sal_Bool SAL_CALL ScTableSheetObj::getPrintTitleColumns()
7086 {
7087     SolarMutexGuard aGuard;
7088     ScDocShell* pDocSh = GetDocShell();
7089     if ( pDocSh )
7090     {
7091         ScDocument& rDoc = pDocSh->GetDocument();
7092         SCTAB nTab = GetTab_Impl();
7093         return ( rDoc.GetRepeatColRange(nTab) != nullptr );
7094     }
7095     return false;
7096 }
7097 
7098 void SAL_CALL ScTableSheetObj::setPrintTitleColumns( sal_Bool bPrintTitleColumns )
7099 {
7100     SolarMutexGuard aGuard;
7101     ScDocShell* pDocSh = GetDocShell();
7102     if ( !pDocSh )
7103         return;
7104 
7105     ScDocument& rDoc = pDocSh->GetDocument();
7106     SCTAB nTab = GetTab_Impl();
7107 
7108     std::unique_ptr<ScPrintRangeSaver> pOldRanges = rDoc.CreatePrintRangeSaver();
7109 
7110     if ( bPrintTitleColumns )
7111     {
7112         if ( !rDoc.GetRepeatColRange( nTab ) )         // do not change existing area
7113         {
7114             rDoc.SetRepeatColRange( nTab, std::unique_ptr<ScRange>(new ScRange( 0, 0, nTab, 0, 0, nTab )) );     // enable
7115         }
7116     }
7117     else
7118         rDoc.SetRepeatColRange( nTab, nullptr );          // disable
7119 
7120     PrintAreaUndo_Impl( std::move(pOldRanges) );   // undo, page break, modified etc.
7121 
7122     //! save last set area during switch off and recreate during switch on ???
7123 }
7124 
7125 table::CellRangeAddress SAL_CALL ScTableSheetObj::getTitleColumns()
7126 {
7127     SolarMutexGuard aGuard;
7128     table::CellRangeAddress aRet;
7129     ScDocShell* pDocSh = GetDocShell();
7130     if ( pDocSh )
7131     {
7132         ScDocument& rDoc = pDocSh->GetDocument();
7133         SCTAB nTab = GetTab_Impl();
7134         const ScRange* pRange = rDoc.GetRepeatColRange(nTab);
7135         if (pRange)
7136         {
7137             ScUnoConversion::FillApiRange( aRet, *pRange );
7138             aRet.Sheet = nTab; // core does not care about sheet index
7139         }
7140     }
7141     return aRet;
7142 }
7143 
7144 void SAL_CALL ScTableSheetObj::setTitleColumns( const table::CellRangeAddress& aTitleColumns )
7145 {
7146     SolarMutexGuard aGuard;
7147     ScDocShell* pDocSh = GetDocShell();
7148     if ( !pDocSh )
7149         return;
7150 
7151     ScDocument& rDoc = pDocSh->GetDocument();
7152     SCTAB nTab = GetTab_Impl();
7153 
7154     std::unique_ptr<ScPrintRangeSaver> pOldRanges = rDoc.CreatePrintRangeSaver();
7155 
7156     std::unique_ptr<ScRange> pNew(new ScRange);
7157     ScUnoConversion::FillScRange( *pNew, aTitleColumns );
7158     rDoc.SetRepeatColRange( nTab, std::move(pNew) );     // also always enable
7159 
7160     PrintAreaUndo_Impl( std::move(pOldRanges) );           // undo, page breaks, modified etc.
7161 }
7162 
7163 sal_Bool SAL_CALL ScTableSheetObj::getPrintTitleRows()
7164 {
7165     SolarMutexGuard aGuard;
7166     ScDocShell* pDocSh = GetDocShell();
7167     if ( pDocSh )
7168     {
7169         ScDocument& rDoc = pDocSh->GetDocument();
7170         SCTAB nTab = GetTab_Impl();
7171         return ( rDoc.GetRepeatRowRange(nTab) != nullptr );
7172     }
7173     return false;
7174 }
7175 
7176 void SAL_CALL ScTableSheetObj::setPrintTitleRows( sal_Bool bPrintTitleRows )
7177 {
7178     SolarMutexGuard aGuard;
7179     ScDocShell* pDocSh = GetDocShell();
7180     if ( !pDocSh )
7181         return;
7182 
7183     ScDocument& rDoc = pDocSh->GetDocument();
7184     SCTAB nTab = GetTab_Impl();
7185 
7186     std::unique_ptr<ScPrintRangeSaver> pOldRanges = rDoc.CreatePrintRangeSaver();
7187 
7188     if ( bPrintTitleRows )
7189     {
7190         if ( !rDoc.GetRepeatRowRange( nTab ) )         // do not change existing area
7191         {
7192             std::unique_ptr<ScRange> pNew( new ScRange(0, 0, nTab, 0, 0, nTab) );
7193             rDoc.SetRepeatRowRange( nTab, std::move(pNew) );     // enable
7194         }
7195     }
7196     else
7197         rDoc.SetRepeatRowRange( nTab, nullptr );          // disable
7198 
7199     PrintAreaUndo_Impl( std::move(pOldRanges) );   // undo, page breaks, modified etc.
7200 
7201     //! save last set area during switch off and recreate during switch on ???
7202 }
7203 
7204 table::CellRangeAddress SAL_CALL ScTableSheetObj::getTitleRows()
7205 {
7206     SolarMutexGuard aGuard;
7207     table::CellRangeAddress aRet;
7208     ScDocShell* pDocSh = GetDocShell();
7209     if ( pDocSh )
7210     {
7211         ScDocument& rDoc = pDocSh->GetDocument();
7212         SCTAB nTab = GetTab_Impl();
7213         const ScRange* pRange = rDoc.GetRepeatRowRange(nTab);
7214         if (pRange)
7215         {
7216             ScUnoConversion::FillApiRange( aRet, *pRange );
7217             aRet.Sheet = nTab; // core does not care about sheet index
7218         }
7219     }
7220     return aRet;
7221 }
7222 
7223 void SAL_CALL ScTableSheetObj::setTitleRows( const table::CellRangeAddress& aTitleRows )
7224 {
7225     SolarMutexGuard aGuard;
7226     ScDocShell* pDocSh = GetDocShell();
7227     if ( !pDocSh )
7228         return;
7229 
7230     ScDocument& rDoc = pDocSh->GetDocument();
7231     SCTAB nTab = GetTab_Impl();
7232 
7233     std::unique_ptr<ScPrintRangeSaver> pOldRanges = rDoc.CreatePrintRangeSaver();
7234 
7235     std::unique_ptr<ScRange> pNew(new ScRange);
7236     ScUnoConversion::FillScRange( *pNew, aTitleRows );
7237     rDoc.SetRepeatRowRange( nTab, std::move(pNew) );     // also always enable
7238 
7239     PrintAreaUndo_Impl( std::move(pOldRanges) );           // Undo, page breaks, modified etc.
7240 }
7241 
7242 // XSheetLinkable
7243 
7244 sheet::SheetLinkMode SAL_CALL ScTableSheetObj::getLinkMode()
7245 {
7246     SolarMutexGuard aGuard;
7247     sheet::SheetLinkMode eRet = sheet::SheetLinkMode_NONE;
7248     ScDocShell* pDocSh = GetDocShell();
7249     if ( pDocSh )
7250     {
7251         ScLinkMode nMode = pDocSh->GetDocument().GetLinkMode( GetTab_Impl() );
7252         if ( nMode == ScLinkMode::NORMAL )
7253             eRet = sheet::SheetLinkMode_NORMAL;
7254         else if ( nMode == ScLinkMode::VALUE )
7255             eRet = sheet::SheetLinkMode_VALUE;
7256     }
7257     return eRet;
7258 }
7259 
7260 void SAL_CALL ScTableSheetObj::setLinkMode( sheet::SheetLinkMode nLinkMode )
7261 {
7262     SolarMutexGuard aGuard;
7263 
7264     //! search for filter and options in old link
7265 
7266     OUString aUrl(getLinkUrl());
7267     OUString aSheet(getLinkSheetName());
7268 
7269     link( aUrl, aSheet, "", "", nLinkMode );
7270 }
7271 
7272 OUString SAL_CALL ScTableSheetObj::getLinkUrl()
7273 {
7274     SolarMutexGuard aGuard;
7275     OUString aFile;
7276     ScDocShell* pDocSh = GetDocShell();
7277     if ( pDocSh )
7278         aFile = pDocSh->GetDocument().GetLinkDoc( GetTab_Impl() );
7279     return aFile;
7280 }
7281 
7282 void SAL_CALL ScTableSheetObj::setLinkUrl( const OUString& aLinkUrl )
7283 {
7284     SolarMutexGuard aGuard;
7285 
7286     //! search for filter and options in old link
7287 
7288     sheet::SheetLinkMode eMode = getLinkMode();
7289     OUString aSheet(getLinkSheetName());
7290 
7291     link( aLinkUrl, aSheet, "", "", eMode );
7292 }
7293 
7294 OUString SAL_CALL ScTableSheetObj::getLinkSheetName()
7295 {
7296     SolarMutexGuard aGuard;
7297     OUString aSheet;
7298     ScDocShell* pDocSh = GetDocShell();
7299     if ( pDocSh )
7300         aSheet = pDocSh->GetDocument().GetLinkTab( GetTab_Impl() );
7301     return aSheet;
7302 }
7303 
7304 void SAL_CALL ScTableSheetObj::setLinkSheetName( const OUString& aLinkSheetName )
7305 {
7306     SolarMutexGuard aGuard;
7307 
7308     //! search for filter and options in old link
7309 
7310     sheet::SheetLinkMode eMode = getLinkMode();
7311     OUString aUrl(getLinkUrl());
7312 
7313     link( aUrl, aLinkSheetName, "", "", eMode );
7314 }
7315 
7316 void SAL_CALL ScTableSheetObj::link( const OUString& aUrl, const OUString& aSheetName,
7317                         const OUString& aFilterName, const OUString& aFilterOptions,
7318                         sheet::SheetLinkMode nMode )
7319 {
7320     SolarMutexGuard aGuard;
7321     ScDocShell* pDocSh = GetDocShell();
7322     if ( !pDocSh )
7323         return;
7324 
7325     ScDocument& rDoc = pDocSh->GetDocument();
7326     SCTAB nTab = GetTab_Impl();
7327 
7328     OUString aFileString = aUrl;
7329     OUString aFilterString = aFilterName;
7330     OUString aOptString = aFilterOptions;
7331 
7332     aFileString = ScGlobal::GetAbsDocName( aFileString, pDocSh );
7333     if (aFilterString.isEmpty())
7334         ScDocumentLoader::GetFilterName( aFileString, aFilterString, aOptString, true, false );
7335 
7336     //  remove application prefix from filter name here, so the filter options
7337     //  aren't reset when the filter name is changed in ScTableLink::DataChanged
7338     ScDocumentLoader::RemoveAppPrefix( aFilterString );
7339 
7340     ScLinkMode nLinkMode = ScLinkMode::NONE;
7341     if ( nMode == sheet::SheetLinkMode_NORMAL )
7342         nLinkMode = ScLinkMode::NORMAL;
7343     else if ( nMode == sheet::SheetLinkMode_VALUE )
7344         nLinkMode = ScLinkMode::VALUE;
7345 
7346     rDoc.SetLink( nTab, nLinkMode, aFileString, aFilterString, aOptString, aSheetName, 0/*nRefresh*/ );
7347 
7348     pDocSh->UpdateLinks();                  // if needed add or delete link
7349     SfxBindings* pBindings = pDocSh->GetViewBindings();
7350     if (pBindings)
7351         pBindings->Invalidate(SID_LINKS);
7352 
7353     //! undo of link data on the table
7354 
7355     if ( !(nLinkMode != ScLinkMode::NONE && rDoc.IsExecuteLinkEnabled()) )        // update link
7356         return;
7357 
7358     //  Always update link also if already exists
7359     //! update only on the affected table???
7360 
7361     sfx2::LinkManager* pLinkManager = rDoc.GetLinkManager();
7362     sal_uInt16 nCount = pLinkManager->GetLinks().size();
7363     for ( sal_uInt16 i=0; i<nCount; i++ )
7364     {
7365         ::sfx2::SvBaseLink* pBase = pLinkManager->GetLinks()[i].get();
7366         if (auto pTabLink = dynamic_cast<ScTableLink*>( pBase))
7367         {
7368             if ( aFileString == pTabLink->GetFileName() )
7369                 pTabLink->Update();                         // include Paint&Undo
7370 
7371             //! The file name should only exists once (?)
7372         }
7373     }
7374 
7375     //! notify ScSheetLinkObj objects!!!
7376 }
7377 
7378 // XSheetAuditing
7379 
7380 sal_Bool SAL_CALL ScTableSheetObj::hideDependents( const table::CellAddress& aPosition )
7381 {
7382     SolarMutexGuard aGuard;
7383     ScDocShell* pDocSh = GetDocShell();
7384     if ( pDocSh )
7385     {
7386         SCTAB nTab = GetTab_Impl();
7387         OSL_ENSURE( aPosition.Sheet == nTab, "wrong table in CellAddress" );
7388         ScAddress aPos( static_cast<SCCOL>(aPosition.Column), static_cast<SCROW>(aPosition.Row), nTab );
7389         return pDocSh->GetDocFunc().DetectiveDelSucc( aPos );
7390     }
7391     return false;
7392 }
7393 
7394 sal_Bool SAL_CALL ScTableSheetObj::hidePrecedents( const table::CellAddress& aPosition )
7395 {
7396     SolarMutexGuard aGuard;
7397     ScDocShell* pDocSh = GetDocShell();
7398     if ( pDocSh )
7399     {
7400         SCTAB nTab = GetTab_Impl();
7401         OSL_ENSURE( aPosition.Sheet == nTab, "wrong table in CellAddress" );
7402         ScAddress aPos( static_cast<SCCOL>(aPosition.Column), static_cast<SCROW>(aPosition.Row), nTab );
7403         return pDocSh->GetDocFunc().DetectiveDelPred( aPos );
7404     }
7405     return false;
7406 }
7407 
7408 sal_Bool SAL_CALL ScTableSheetObj::showDependents( const table::CellAddress& aPosition )
7409 {
7410     SolarMutexGuard aGuard;
7411     ScDocShell* pDocSh = GetDocShell();
7412     if ( pDocSh )
7413     {
7414         SCTAB nTab = GetTab_Impl();
7415         OSL_ENSURE( aPosition.Sheet == nTab, "wrong table in CellAddress" );
7416         ScAddress aPos( static_cast<SCCOL>(aPosition.Column), static_cast<SCROW>(aPosition.Row), nTab );
7417         return pDocSh->GetDocFunc().DetectiveAddSucc( aPos );
7418     }
7419     return false;
7420 }
7421 
7422 sal_Bool SAL_CALL ScTableSheetObj::showPrecedents( const table::CellAddress& aPosition )
7423 {
7424     SolarMutexGuard aGuard;
7425     ScDocShell* pDocSh = GetDocShell();
7426     if ( pDocSh )
7427     {
7428         SCTAB nTab = GetTab_Impl();
7429         OSL_ENSURE( aPosition.Sheet == nTab, "wrong table in CellAddress" );
7430         ScAddress aPos( static_cast<SCCOL>(aPosition.Column), static_cast<SCROW>(aPosition.Row), nTab );
7431         return pDocSh->GetDocFunc().DetectiveAddPred( aPos );
7432     }
7433     return false;
7434 }
7435 
7436 sal_Bool SAL_CALL ScTableSheetObj::showErrors( const table::CellAddress& aPosition )
7437 {
7438     SolarMutexGuard aGuard;
7439     ScDocShell* pDocSh = GetDocShell();
7440     if ( pDocSh )
7441     {
7442         SCTAB nTab = GetTab_Impl();
7443         OSL_ENSURE( aPosition.Sheet == nTab, "wrong table in CellAddress" );
7444         ScAddress aPos( static_cast<SCCOL>(aPosition.Column), static_cast<SCROW>(aPosition.Row), nTab );
7445         return pDocSh->GetDocFunc().DetectiveAddError( aPos );
7446     }
7447     return false;
7448 }
7449 
7450 sal_Bool SAL_CALL ScTableSheetObj::showInvalid()
7451 {
7452     SolarMutexGuard aGuard;
7453     ScDocShell* pDocSh = GetDocShell();
7454     if ( pDocSh )
7455         return pDocSh->GetDocFunc().DetectiveMarkInvalid( GetTab_Impl() );
7456     return false;
7457 }
7458 
7459 void SAL_CALL ScTableSheetObj::clearArrows()
7460 {
7461     SolarMutexGuard aGuard;
7462     ScDocShell* pDocSh = GetDocShell();
7463     if ( pDocSh )
7464         pDocSh->GetDocFunc().DetectiveDelAll( GetTab_Impl() );
7465 }
7466 
7467 // XSheetOutline
7468 
7469 void SAL_CALL ScTableSheetObj::group( const table::CellRangeAddress& rGroupRange,
7470                                         table::TableOrientation nOrientation )
7471 {
7472     SolarMutexGuard aGuard;
7473     ScDocShell* pDocSh = GetDocShell();
7474     if ( pDocSh )
7475     {
7476         bool bColumns = ( nOrientation == table::TableOrientation_COLUMNS );
7477         ScRange aGroupRange;
7478         ScUnoConversion::FillScRange( aGroupRange, rGroupRange );
7479         ScOutlineDocFunc aFunc(*pDocSh);
7480         aFunc.MakeOutline( aGroupRange, bColumns, true, true );
7481     }
7482 }
7483 
7484 void SAL_CALL ScTableSheetObj::ungroup( const table::CellRangeAddress& rGroupRange,
7485                                         table::TableOrientation nOrientation )
7486 {
7487     SolarMutexGuard aGuard;
7488     ScDocShell* pDocSh = GetDocShell();
7489     if ( pDocSh )
7490     {
7491         bool bColumns = ( nOrientation == table::TableOrientation_COLUMNS );
7492         ScRange aGroupRange;
7493         ScUnoConversion::FillScRange( aGroupRange, rGroupRange );
7494         ScOutlineDocFunc aFunc(*pDocSh);
7495         aFunc.RemoveOutline( aGroupRange, bColumns, true, true );
7496     }
7497 }
7498 
7499 void SAL_CALL ScTableSheetObj::autoOutline( const table::CellRangeAddress& rCellRange )
7500 {
7501     SolarMutexGuard aGuard;
7502     ScDocShell* pDocSh = GetDocShell();
7503     if ( pDocSh )
7504     {
7505         ScRange aFormulaRange;
7506         ScUnoConversion::FillScRange( aFormulaRange, rCellRange );
7507         ScOutlineDocFunc aFunc(*pDocSh);
7508         aFunc.AutoOutline( aFormulaRange, true );
7509     }
7510 }
7511 
7512 void SAL_CALL ScTableSheetObj::clearOutline()
7513 {
7514     SolarMutexGuard aGuard;
7515     ScDocShell* pDocSh = GetDocShell();
7516     if ( pDocSh )
7517     {
7518         SCTAB nTab = GetTab_Impl();
7519         ScOutlineDocFunc aFunc(*pDocSh);
7520         aFunc.RemoveAllOutlines( nTab, true );
7521     }
7522 }
7523 
7524 void SAL_CALL ScTableSheetObj::hideDetail( const table::CellRangeAddress& rCellRange )
7525 {
7526     SolarMutexGuard aGuard;
7527     ScDocShell* pDocSh = GetDocShell();
7528     if ( pDocSh )
7529     {
7530         ScRange aMarkRange;
7531         ScUnoConversion::FillScRange( aMarkRange, rCellRange );
7532         ScOutlineDocFunc aFunc(*pDocSh);
7533         aFunc.HideMarkedOutlines( aMarkRange, true );
7534     }
7535 }
7536 
7537 void SAL_CALL ScTableSheetObj::showDetail( const table::CellRangeAddress& rCellRange )
7538 {
7539     SolarMutexGuard aGuard;
7540     ScDocShell* pDocSh = GetDocShell();
7541     if ( pDocSh )
7542     {
7543         ScRange aMarkRange;
7544         ScUnoConversion::FillScRange( aMarkRange, rCellRange );
7545         ScOutlineDocFunc aFunc(*pDocSh);
7546         aFunc.ShowMarkedOutlines( aMarkRange, true );
7547     }
7548 }
7549 
7550 void SAL_CALL ScTableSheetObj::showLevel( sal_Int16 nLevel, table::TableOrientation nOrientation )
7551 {
7552     SolarMutexGuard aGuard;
7553     ScDocShell* pDocSh = GetDocShell();
7554     if ( pDocSh )
7555     {
7556         bool bColumns = ( nOrientation == table::TableOrientation_COLUMNS );
7557         SCTAB nTab = GetTab_Impl();
7558         ScOutlineDocFunc aFunc(*pDocSh);
7559         aFunc.SelectLevel( nTab, bColumns, nLevel, true, true );
7560     }
7561 }
7562 
7563 // XProtectable
7564 
7565 void SAL_CALL ScTableSheetObj::protect( const OUString& aPassword )
7566 {
7567     SolarMutexGuard aGuard;
7568     ScDocShell* pDocSh = GetDocShell();
7569     // #i108245# if already protected, don't change anything
7570     if ( pDocSh && !pDocSh->GetDocument().IsTabProtected( GetTab_Impl() ) )
7571     {
7572         pDocSh->GetDocFunc().Protect( GetTab_Impl(), aPassword );
7573     }
7574 }
7575 
7576 void SAL_CALL ScTableSheetObj::unprotect( const OUString& aPassword )
7577 {
7578     SolarMutexGuard aGuard;
7579     ScDocShell* pDocSh = GetDocShell();
7580     if ( pDocSh )
7581     {
7582         bool bDone = pDocSh->GetDocFunc().Unprotect( GetTab_Impl(), aPassword, true );
7583         if (!bDone)
7584             throw lang::IllegalArgumentException();
7585     }
7586 }
7587 
7588 sal_Bool SAL_CALL ScTableSheetObj::isProtected()
7589 {
7590     SolarMutexGuard aGuard;
7591     ScDocShell* pDocSh = GetDocShell();
7592     if ( pDocSh )
7593         return pDocSh->GetDocument().IsTabProtected( GetTab_Impl() );
7594 
7595     OSL_FAIL("no DocShell");     //! Exception or so?
7596     return false;
7597 }
7598 
7599 // XScenario
7600 
7601 sal_Bool SAL_CALL ScTableSheetObj::getIsScenario()
7602 {
7603     SolarMutexGuard aGuard;
7604     ScDocShell* pDocSh = GetDocShell();
7605     if ( pDocSh )
7606         return pDocSh->GetDocument().IsScenario( GetTab_Impl() );
7607 
7608     return false;
7609 }
7610 
7611 OUString SAL_CALL ScTableSheetObj::getScenarioComment()
7612 {
7613     SolarMutexGuard aGuard;
7614     ScDocShell* pDocSh = GetDocShell();
7615     if ( pDocSh )
7616     {
7617         OUString aComment;
7618         Color  aColor;
7619         ScScenarioFlags nFlags;
7620         pDocSh->GetDocument().GetScenarioData( GetTab_Impl(), aComment, aColor, nFlags );
7621         return aComment;
7622     }
7623     return OUString();
7624 }
7625 
7626 void SAL_CALL ScTableSheetObj::setScenarioComment( const OUString& aScenarioComment )
7627 {
7628     SolarMutexGuard aGuard;
7629     ScDocShell* pDocSh = GetDocShell();
7630     if ( !pDocSh )
7631         return;
7632 
7633     ScDocument& rDoc = pDocSh->GetDocument();
7634     SCTAB nTab = GetTab_Impl();
7635 
7636     OUString aName;
7637     OUString aComment;
7638     Color  aColor;
7639     ScScenarioFlags nFlags;
7640     rDoc.GetName( nTab, aName );
7641     rDoc.GetScenarioData( nTab, aComment, aColor, nFlags );
7642 
7643     aComment = aScenarioComment;
7644 
7645     pDocSh->ModifyScenario( nTab, aName, aComment, aColor, nFlags );
7646 }
7647 
7648 void SAL_CALL ScTableSheetObj::addRanges( const uno::Sequence<table::CellRangeAddress>& rScenRanges )
7649 {
7650     SolarMutexGuard aGuard;
7651     ScDocShell* pDocSh = GetDocShell();
7652     if ( !pDocSh )
7653         return;
7654 
7655     ScDocument& rDoc = pDocSh->GetDocument();
7656     SCTAB nTab = GetTab_Impl();
7657 
7658     if (!rDoc.IsScenario(nTab))
7659         return;
7660 
7661     ScMarkData aMarkData(rDoc.GetSheetLimits());
7662     aMarkData.SelectTable( nTab, true );
7663 
7664     for (const table::CellRangeAddress& rRange : rScenRanges)
7665     {
7666         OSL_ENSURE( rRange.Sheet == nTab, "addRanges with wrong Tab" );
7667         ScRange aOneRange( static_cast<SCCOL>(rRange.StartColumn), static_cast<SCROW>(rRange.StartRow), nTab,
7668                            static_cast<SCCOL>(rRange.EndColumn),   static_cast<SCROW>(rRange.EndRow),   nTab );
7669 
7670         aMarkData.SetMultiMarkArea( aOneRange );
7671     }
7672 
7673     //  Scenario ranges are tagged with attribute
7674     ScPatternAttr aPattern( rDoc.GetPool() );
7675     aPattern.GetItemSet().Put( ScMergeFlagAttr( ScMF::Scenario ) );
7676     aPattern.GetItemSet().Put( ScProtectionAttr( true ) );
7677     pDocSh->GetDocFunc().ApplyAttributes( aMarkData, aPattern, true );
7678 }
7679 
7680 void SAL_CALL ScTableSheetObj::apply()
7681 {
7682     SolarMutexGuard aGuard;
7683     ScDocShell* pDocSh = GetDocShell();
7684     if ( !pDocSh )
7685         return;
7686 
7687     ScDocument& rDoc = pDocSh->GetDocument();
7688     SCTAB nTab = GetTab_Impl();
7689     OUString aName;
7690     rDoc.GetName( nTab, aName );       // scenario name
7691 
7692     SCTAB nDestTab = nTab;
7693     while ( nDestTab > 0 && rDoc.IsScenario(nDestTab) )
7694         --nDestTab;
7695 
7696     if ( !rDoc.IsScenario(nDestTab) )
7697         pDocSh->UseScenario( nDestTab, aName );
7698 
7699     //! otherwise error or so
7700 }
7701 
7702 // XScenarioEnhanced
7703 
7704 uno::Sequence< table::CellRangeAddress > SAL_CALL ScTableSheetObj::getRanges(  )
7705 {
7706     SolarMutexGuard aGuard;
7707     ScDocShell* pDocSh = GetDocShell();
7708     if ( pDocSh )
7709     {
7710         ScDocument& rDoc = pDocSh->GetDocument();
7711         SCTAB nTab = GetTab_Impl();
7712         const ScRangeList* pRangeList = rDoc.GetScenarioRanges(nTab);
7713         if (pRangeList)
7714         {
7715             size_t nCount = pRangeList->size();
7716             uno::Sequence< table::CellRangeAddress > aRetRanges( nCount );
7717             table::CellRangeAddress* pAry = aRetRanges.getArray();
7718             for( size_t nIndex = 0; nIndex < nCount; nIndex++ )
7719             {
7720                 const ScRange & rRange = (*pRangeList)[nIndex];
7721                 pAry->StartColumn = rRange.aStart.Col();
7722                 pAry->StartRow = rRange.aStart.Row();
7723                 pAry->EndColumn = rRange.aEnd.Col();
7724                 pAry->EndRow = rRange.aEnd.Row();
7725                 pAry->Sheet = rRange.aStart.Tab();
7726                 ++pAry;
7727             }
7728             return aRetRanges;
7729         }
7730     }
7731     return uno::Sequence< table::CellRangeAddress > ();
7732 }
7733 
7734 // XExternalSheetName
7735 
7736 void ScTableSheetObj::setExternalName( const OUString& aUrl, const OUString& aSheetName )
7737 {
7738     SolarMutexGuard aGuard;
7739     ScDocShell* pDocSh = GetDocShell();
7740     if ( pDocSh )
7741     {
7742         ScDocument& rDoc = pDocSh->GetDocument();
7743         const SCTAB nTab = GetTab_Impl();
7744         const OUString aAbsDocName( ScGlobal::GetAbsDocName( aUrl, pDocSh ) );
7745         const OUString aDocTabName( ScGlobal::GetDocTabName( aAbsDocName, aSheetName ) );
7746         if ( !rDoc.RenameTab( nTab, aDocTabName, true /*bExternalDocument*/ ) )
7747         {
7748             throw container::ElementExistException( OUString(), *this );
7749         }
7750     }
7751 }
7752 
7753 // XEventsSupplier
7754 
7755 uno::Reference<container::XNameReplace> SAL_CALL ScTableSheetObj::getEvents()
7756 {
7757     SolarMutexGuard aGuard;
7758     ScDocShell* pDocSh = GetDocShell();
7759     if ( pDocSh )
7760         return new ScSheetEventsObj( pDocSh, GetTab_Impl() );
7761 
7762     return nullptr;
7763 }
7764 
7765 // XPropertySet extended for Sheet-Properties
7766 
7767 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScTableSheetObj::getPropertySetInfo()
7768 {
7769     SolarMutexGuard aGuard;
7770     static uno::Reference<beans::XPropertySetInfo> aRef(
7771         new SfxItemPropertySetInfo( pSheetPropSet->getPropertyMap() ));
7772     return aRef;
7773 }
7774 
7775 void ScTableSheetObj::SetOnePropertyValue( const SfxItemPropertyMapEntry* pEntry, const uno::Any& aValue )
7776 {
7777     if ( !pEntry )
7778         return;
7779 
7780     if ( IsScItemWid( pEntry->nWID ) )
7781     {
7782         //  for Item WIDs, call ScCellRangesBase directly
7783         ScCellRangesBase::SetOnePropertyValue(pEntry, aValue);
7784         return;
7785     }
7786 
7787     //  own properties
7788 
7789     ScDocShell* pDocSh = GetDocShell();
7790     if (!pDocSh)
7791         return;                                                 //! Exception or so?
7792     ScDocument& rDoc = pDocSh->GetDocument();
7793     SCTAB nTab = GetTab_Impl();
7794     ScDocFunc &rFunc = pDocSh->GetDocFunc();
7795 
7796     if ( pEntry->nWID == SC_WID_UNO_PAGESTL )
7797     {
7798         OUString aStrVal;
7799         aValue >>= aStrVal;
7800         OUString aNewStr(ScStyleNameConversion::ProgrammaticToDisplayName(
7801                                             aStrVal, SfxStyleFamily::Page ));
7802 
7803         //! Undo? (also if SID_STYLE_APPLY on View)
7804 
7805         if ( rDoc.GetPageStyle( nTab ) != aNewStr )
7806         {
7807             rDoc.SetPageStyle( nTab, aNewStr );
7808             if (!rDoc.IsImportingXML())
7809             {
7810                 ScPrintFunc( pDocSh, pDocSh->GetPrinter(), nTab ).UpdatePages();
7811 
7812                 SfxBindings* pBindings = pDocSh->GetViewBindings();
7813                 if (pBindings)
7814                 {
7815                     pBindings->Invalidate( SID_STYLE_FAMILY4 );
7816                     pBindings->Invalidate( SID_STATUS_PAGESTYLE );
7817                     pBindings->Invalidate( FID_RESET_PRINTZOOM );
7818                     pBindings->Invalidate( SID_ATTR_PARA_LEFT_TO_RIGHT );
7819                     pBindings->Invalidate( SID_ATTR_PARA_RIGHT_TO_LEFT );
7820                 }
7821             }
7822             pDocSh->SetDocumentModified();
7823         }
7824     }
7825     else if ( pEntry->nWID == SC_WID_UNO_CELLVIS )
7826     {
7827         bool bVis = ScUnoHelpFunctions::GetBoolFromAny( aValue );
7828         rFunc.SetTableVisible( nTab, bVis, true );
7829     }
7830     else if ( pEntry->nWID == SC_WID_UNO_ISACTIVE )
7831     {
7832         if (rDoc.IsScenario(nTab))
7833             rDoc.SetActiveScenario( nTab, ScUnoHelpFunctions::GetBoolFromAny( aValue ) );
7834     }
7835     else if ( pEntry->nWID == SC_WID_UNO_BORDCOL )
7836     {
7837         if (rDoc.IsScenario(nTab))
7838         {
7839             Color aColor;
7840             if (aValue >>= aColor)
7841             {
7842                 OUString aName;
7843                 OUString aComment;
7844                 ScScenarioFlags nFlags;
7845                 Color aTmp;
7846                 rDoc.GetName( nTab, aName );
7847                 rDoc.GetScenarioData( nTab, aComment, aTmp, nFlags );
7848 
7849                 pDocSh->ModifyScenario( nTab, aName, aComment, aColor, nFlags );
7850             }
7851         }
7852     }
7853     else if ( pEntry->nWID == SC_WID_UNO_PROTECT )
7854     {
7855         if (rDoc.IsScenario(nTab))
7856         {
7857             OUString aName;
7858             OUString aComment;
7859             Color  aColor;
7860             ScScenarioFlags nFlags;
7861             rDoc.GetName( nTab, aName );
7862             rDoc.GetScenarioData( nTab, aComment, aColor, nFlags );
7863             bool bModify(false);
7864 
7865             if (ScUnoHelpFunctions::GetBoolFromAny( aValue ))
7866             {
7867                 if (!(nFlags & ScScenarioFlags::Protected))
7868                 {
7869                     nFlags |= ScScenarioFlags::Protected;
7870                     bModify = true;
7871                 }
7872             }
7873             else
7874             {
7875                 if (nFlags & ScScenarioFlags::Protected)
7876                 {
7877                     nFlags &= ~ScScenarioFlags::Protected;
7878                     bModify = true;
7879                 }
7880             }
7881 
7882             if (bModify)
7883                 pDocSh->ModifyScenario( nTab, aName, aComment, aColor, nFlags );
7884         }
7885     }
7886     else if ( pEntry->nWID == SC_WID_UNO_SHOWBORD )
7887     {
7888         if (rDoc.IsScenario(nTab))
7889         {
7890             OUString aName;
7891             OUString aComment;
7892             Color  aColor;
7893             ScScenarioFlags nFlags;
7894             rDoc.GetName( nTab, aName );
7895             rDoc.GetScenarioData( nTab, aComment, aColor, nFlags );
7896             bool bModify(false);
7897 
7898             if (ScUnoHelpFunctions::GetBoolFromAny( aValue ))
7899             {
7900                 if (!(nFlags & ScScenarioFlags::ShowFrame))
7901                 {
7902                     nFlags |= ScScenarioFlags::ShowFrame;
7903                     bModify = true;
7904                 }
7905             }
7906             else
7907             {
7908                 if (nFlags & ScScenarioFlags::ShowFrame)
7909                 {
7910                     nFlags &= ~ScScenarioFlags::ShowFrame;
7911                     bModify = true;
7912                 }
7913             }
7914 
7915             if (bModify)
7916                 pDocSh->ModifyScenario( nTab, aName, aComment, aColor, nFlags );
7917         }
7918     }
7919     else if ( pEntry->nWID == SC_WID_UNO_PRINTBORD )
7920     {
7921         if (rDoc.IsScenario(nTab))
7922         {
7923             OUString aName;
7924             OUString aComment;
7925             Color  aColor;
7926             ScScenarioFlags nFlags;
7927             rDoc.GetName( nTab, aName );
7928             rDoc.GetScenarioData( nTab, aComment, aColor, nFlags );
7929             bool bModify(false);
7930 
7931             if (ScUnoHelpFunctions::GetBoolFromAny( aValue ))
7932             {
7933                 if (!(nFlags & ScScenarioFlags::PrintFrame))
7934                 {
7935                     nFlags |= ScScenarioFlags::PrintFrame;
7936                     bModify = true;
7937                 }
7938             }
7939             else
7940             {
7941                 if (nFlags & ScScenarioFlags::PrintFrame)
7942                 {
7943                     nFlags &= ~ScScenarioFlags::PrintFrame;
7944                     bModify = true;
7945                 }
7946             }
7947 
7948             if (bModify)
7949                 pDocSh->ModifyScenario( nTab, aName, aComment, aColor, nFlags );
7950         }
7951     }
7952     else if ( pEntry->nWID == SC_WID_UNO_COPYBACK )
7953     {
7954         if (rDoc.IsScenario(nTab))
7955         {
7956             OUString aName;
7957             OUString aComment;
7958             Color  aColor;
7959             ScScenarioFlags nFlags;
7960             rDoc.GetName( nTab, aName );
7961             rDoc.GetScenarioData( nTab, aComment, aColor, nFlags );
7962             bool bModify(false);
7963 
7964             if (ScUnoHelpFunctions::GetBoolFromAny( aValue ))
7965             {
7966                 if (!(nFlags & ScScenarioFlags::TwoWay))
7967                 {
7968                     nFlags |= ScScenarioFlags::TwoWay;
7969                     bModify = true;
7970                 }
7971             }
7972             else
7973             {
7974                 if (nFlags & ScScenarioFlags::TwoWay)
7975                 {
7976                     nFlags &= ~ScScenarioFlags::TwoWay;
7977                     bModify = true;
7978                 }
7979             }
7980 
7981             if (bModify)
7982                 pDocSh->ModifyScenario( nTab, aName, aComment, aColor, nFlags );
7983         }
7984     }
7985     else if ( pEntry->nWID == SC_WID_UNO_COPYSTYL )
7986     {
7987         if (rDoc.IsScenario(nTab))
7988         {
7989             OUString aName;
7990             OUString aComment;
7991             Color  aColor;
7992             ScScenarioFlags nFlags;
7993             rDoc.GetName( nTab, aName );
7994             rDoc.GetScenarioData( nTab, aComment, aColor, nFlags );
7995             bool bModify(false);
7996 
7997             if (ScUnoHelpFunctions::GetBoolFromAny( aValue ))
7998             {
7999                 if (!(nFlags & ScScenarioFlags::Attrib))
8000                 {
8001                     nFlags |= ScScenarioFlags::Attrib;
8002                     bModify = true;
8003                 }
8004             }
8005             else
8006             {
8007                 if (nFlags & ScScenarioFlags::Attrib)
8008                 {
8009                     nFlags &= ~ScScenarioFlags::Attrib;
8010                     bModify = true;
8011                 }
8012             }
8013 
8014             if (bModify)
8015                 pDocSh->ModifyScenario( nTab, aName, aComment, aColor, nFlags );
8016         }
8017     }
8018     else if ( pEntry->nWID == SC_WID_UNO_COPYFORM )
8019     {
8020         if (rDoc.IsScenario(nTab))
8021         {
8022             OUString aName;
8023             OUString aComment;
8024             Color  aColor;
8025             ScScenarioFlags nFlags;
8026             rDoc.GetName( nTab, aName );
8027             rDoc.GetScenarioData( nTab, aComment, aColor, nFlags );
8028             bool bModify(false);
8029 
8030             if (ScUnoHelpFunctions::GetBoolFromAny( aValue ))
8031             {
8032                 if (nFlags & ScScenarioFlags::Value)
8033                 {
8034                     nFlags &= ~ScScenarioFlags::Value;
8035                     bModify = true;
8036                 }
8037             }
8038             else
8039             {
8040                 if (!(nFlags & ScScenarioFlags::Value))
8041                 {
8042                     nFlags |= ScScenarioFlags::Value;
8043                     bModify = true;
8044                 }
8045             }
8046 
8047             if (bModify)
8048                 pDocSh->ModifyScenario( nTab, aName, aComment, aColor, nFlags );
8049         }
8050     }
8051     else if ( pEntry->nWID == SC_WID_UNO_TABLAYOUT )
8052     {
8053         sal_Int16 nValue = 0;
8054         if (aValue >>= nValue)
8055         {
8056             if (nValue == css::text::WritingMode2::RL_TB)
8057                 rFunc.SetLayoutRTL(nTab, true);
8058             else
8059                 rFunc.SetLayoutRTL(nTab, false);
8060         }
8061     }
8062     else if ( pEntry->nWID == SC_WID_UNO_AUTOPRINT )
8063     {
8064         bool bAutoPrint = ScUnoHelpFunctions::GetBoolFromAny( aValue );
8065         if (bAutoPrint)
8066             rDoc.SetPrintEntireSheet( nTab ); // clears all print ranges
8067         else
8068         {
8069             if (rDoc.IsPrintEntireSheet( nTab ))
8070                 rDoc.ClearPrintRanges( nTab ); // if this flag is true, there are no PrintRanges, so Clear clears only the flag.
8071         }
8072     }
8073     else if ( pEntry->nWID == SC_WID_UNO_TABCOLOR )
8074     {
8075         Color aColor = COL_AUTO;
8076         if ( aValue >>= aColor )
8077         {
8078             if ( rDoc.GetTabBgColor( nTab ) != aColor )
8079                 rFunc.SetTabBgColor( nTab, aColor, true, true );
8080         }
8081     }
8082     else if ( pEntry->nWID == SC_WID_UNO_CODENAME )
8083     {
8084         OUString aCodeName;
8085         if (aValue >>= aCodeName)
8086         {
8087             pDocSh->GetDocument().SetCodeName( GetTab_Impl(), aCodeName );
8088         }
8089     }
8090     else if (pEntry->nWID == SC_WID_UNO_CONDFORMAT)
8091     {
8092         uno::Reference<sheet::XConditionalFormats> xCondFormat;
8093         if (aValue >>= xCondFormat)
8094         {
8095             // how to set the format correctly
8096         }
8097     }
8098     else
8099         ScCellRangeObj::SetOnePropertyValue(pEntry, aValue);        // base class, no Item WID
8100 }
8101 
8102 void ScTableSheetObj::GetOnePropertyValue( const SfxItemPropertyMapEntry* pEntry,
8103                                             uno::Any& rAny )
8104 {
8105     if ( !pEntry )
8106         return;
8107 
8108     ScDocShell* pDocSh = GetDocShell();
8109     if (!pDocSh)
8110         throw uno::RuntimeException();
8111     ScDocument& rDoc = pDocSh->GetDocument();
8112     SCTAB nTab = GetTab_Impl();
8113 
8114     if ( pEntry->nWID == SC_WID_UNO_NAMES )
8115     {
8116         rAny <<= uno::Reference<sheet::XNamedRanges>(new ScLocalNamedRangesObj(pDocSh, this));
8117     }
8118     else if ( pEntry->nWID == SC_WID_UNO_PAGESTL )
8119     {
8120         rAny <<= ScStyleNameConversion::DisplayToProgrammaticName(
8121                             rDoc.GetPageStyle( nTab ), SfxStyleFamily::Page );
8122     }
8123     else if ( pEntry->nWID == SC_WID_UNO_CELLVIS )
8124     {
8125         bool bVis = rDoc.IsVisible( nTab );
8126         rAny <<= bVis;
8127     }
8128     else if ( pEntry->nWID == SC_WID_UNO_LINKDISPBIT )
8129     {
8130         //  no target bitmaps for individual entries (would be all equal)
8131         // ScLinkTargetTypeObj::SetLinkTargetBitmap( aAny, SC_LINKTARGETTYPE_SHEET );
8132     }
8133     else if ( pEntry->nWID == SC_WID_UNO_LINKDISPNAME )
8134     {
8135         //  LinkDisplayName for hyperlink dialog
8136         rAny <<= getName();     // sheet name
8137     }
8138     else if ( pEntry->nWID == SC_WID_UNO_ISACTIVE )
8139     {
8140         if (rDoc.IsScenario(nTab))
8141             rAny <<= rDoc.IsActiveScenario( nTab );
8142     }
8143     else if ( pEntry->nWID == SC_WID_UNO_BORDCOL )
8144     {
8145         if (rDoc.IsScenario(nTab))
8146         {
8147             OUString aComment;
8148             Color  aColor;
8149             ScScenarioFlags nFlags;
8150             rDoc.GetScenarioData( nTab, aComment, aColor, nFlags );
8151 
8152             rAny <<= aColor;
8153         }
8154     }
8155     else if ( pEntry->nWID == SC_WID_UNO_PROTECT )
8156     {
8157         if (rDoc.IsScenario(nTab))
8158         {
8159             ScScenarioFlags nFlags;
8160             rDoc.GetScenarioFlags(nTab, nFlags);
8161 
8162             rAny <<= ((nFlags & ScScenarioFlags::Protected) != ScScenarioFlags::NONE);
8163         }
8164     }
8165     else if ( pEntry->nWID == SC_WID_UNO_SHOWBORD )
8166     {
8167         if (rDoc.IsScenario(nTab))
8168         {
8169             ScScenarioFlags nFlags;
8170             rDoc.GetScenarioFlags(nTab, nFlags);
8171 
8172             rAny <<= ((nFlags & ScScenarioFlags::ShowFrame) != ScScenarioFlags::NONE);
8173         }
8174     }
8175     else if ( pEntry->nWID == SC_WID_UNO_PRINTBORD )
8176     {
8177         if (rDoc.IsScenario(nTab))
8178         {
8179             ScScenarioFlags nFlags;
8180             rDoc.GetScenarioFlags(nTab, nFlags);
8181 
8182             rAny <<= ((nFlags & ScScenarioFlags::PrintFrame) != ScScenarioFlags::NONE);
8183         }
8184     }
8185     else if ( pEntry->nWID == SC_WID_UNO_COPYBACK )
8186     {
8187         if (rDoc.IsScenario(nTab))
8188         {
8189             ScScenarioFlags nFlags;
8190             rDoc.GetScenarioFlags(nTab, nFlags);
8191 
8192             rAny <<= ((nFlags & ScScenarioFlags::TwoWay) != ScScenarioFlags::NONE);
8193         }
8194     }
8195     else if ( pEntry->nWID == SC_WID_UNO_COPYSTYL )
8196     {
8197         if (rDoc.IsScenario(nTab))
8198         {
8199             ScScenarioFlags nFlags;
8200             rDoc.GetScenarioFlags(nTab, nFlags);
8201 
8202             rAny <<= ((nFlags & ScScenarioFlags::Attrib) != ScScenarioFlags::NONE);
8203         }
8204     }
8205     else if ( pEntry->nWID == SC_WID_UNO_COPYFORM )
8206     {
8207         if (rDoc.IsScenario(nTab))
8208         {
8209             ScScenarioFlags nFlags;
8210             rDoc.GetScenarioFlags(nTab, nFlags);
8211 
8212             rAny <<= !(nFlags & ScScenarioFlags::Value);
8213         }
8214     }
8215     else if ( pEntry->nWID == SC_WID_UNO_TABLAYOUT )
8216     {
8217         if (rDoc.IsLayoutRTL(nTab))
8218             rAny <<= sal_Int16(css::text::WritingMode2::RL_TB);
8219         else
8220             rAny <<= sal_Int16(css::text::WritingMode2::LR_TB);
8221     }
8222     else if ( pEntry->nWID == SC_WID_UNO_AUTOPRINT )
8223     {
8224         bool bAutoPrint = rDoc.IsPrintEntireSheet( nTab );
8225         rAny <<= bAutoPrint;
8226     }
8227     else if ( pEntry->nWID == SC_WID_UNO_TABCOLOR )
8228     {
8229         rAny <<= rDoc.GetTabBgColor(nTab);
8230     }
8231     else if ( pEntry->nWID == SC_WID_UNO_CODENAME )
8232     {
8233         OUString aCodeName;
8234         pDocSh->GetDocument().GetCodeName(GetTab_Impl(), aCodeName);
8235         rAny <<= aCodeName;
8236     }
8237     else if (pEntry->nWID == SC_WID_UNO_CONDFORMAT)
8238     {
8239         rAny <<= uno::Reference<sheet::XConditionalFormats>(new ScCondFormatsObj(pDocSh, nTab));
8240     }
8241     else
8242         ScCellRangeObj::GetOnePropertyValue(pEntry, rAny);
8243 }
8244 
8245 const SfxItemPropertyMap& ScTableSheetObj::GetItemPropertyMap()
8246 {
8247     return pSheetPropSet->getPropertyMap();
8248 }
8249 
8250 // XServiceInfo
8251 
8252 OUString SAL_CALL ScTableSheetObj::getImplementationName()
8253 {
8254     return "ScTableSheetObj";
8255 }
8256 
8257 sal_Bool SAL_CALL ScTableSheetObj::supportsService( const OUString& rServiceName )
8258 {
8259     return cppu::supportsService(this, rServiceName);
8260 }
8261 
8262 uno::Sequence<OUString> SAL_CALL ScTableSheetObj::getSupportedServiceNames()
8263 {
8264     return {SCSPREADSHEET_SERVICE,
8265             SCSHEETCELLRANGE_SERVICE,
8266             SCCELLRANGE_SERVICE,
8267             SCCELLPROPERTIES_SERVICE,
8268             SCCHARPROPERTIES_SERVICE,
8269             SCPARAPROPERTIES_SERVICE,
8270             SCLINKTARGET_SERVICE};
8271 }
8272 
8273 // XUnoTunnel
8274 
8275 UNO3_GETIMPLEMENTATION2_IMPL(ScTableSheetObj, ScCellRangeObj);
8276 
8277 ScTableColumnObj::ScTableColumnObj( ScDocShell* pDocSh, SCCOL nCol, SCTAB nTab ) :
8278     ScCellRangeObj( pDocSh, ScRange(nCol,0,nTab, nCol, pDocSh->GetDocument().MaxRow(),nTab) ),
8279     pColPropSet(lcl_GetColumnPropertySet())
8280 {
8281 }
8282 
8283 ScTableColumnObj::~ScTableColumnObj()
8284 {
8285 }
8286 
8287 uno::Any SAL_CALL ScTableColumnObj::queryInterface( const uno::Type& rType )
8288 {
8289     SC_QUERYINTERFACE( container::XNamed )
8290 
8291     return ScCellRangeObj::queryInterface( rType );
8292 }
8293 
8294 void SAL_CALL ScTableColumnObj::acquire() noexcept
8295 {
8296     ScCellRangeObj::acquire();
8297 }
8298 
8299 void SAL_CALL ScTableColumnObj::release() noexcept
8300 {
8301     ScCellRangeObj::release();
8302 }
8303 
8304 uno::Sequence<uno::Type> SAL_CALL ScTableColumnObj::getTypes()
8305 {
8306     return comphelper::concatSequences(
8307         ScCellRangeObj::getTypes(),
8308         uno::Sequence<uno::Type> { cppu::UnoType<container::XNamed>::get() } );
8309 }
8310 
8311 uno::Sequence<sal_Int8> SAL_CALL ScTableColumnObj::getImplementationId()
8312 {
8313     return css::uno::Sequence<sal_Int8>();
8314 }
8315 
8316 // XNamed
8317 
8318 OUString SAL_CALL ScTableColumnObj::getName()
8319 {
8320     SolarMutexGuard aGuard;
8321 
8322     const ScRange& rRange = GetRange();
8323     OSL_ENSURE(rRange.aStart.Col() == rRange.aEnd.Col(), "too many columns");
8324     SCCOL nCol = rRange.aStart.Col();
8325 
8326     return ScColToAlpha( nCol );        // from global.hxx
8327 }
8328 
8329 void SAL_CALL ScTableColumnObj::setName( const OUString& /* aNewName */ )
8330 {
8331     SolarMutexGuard aGuard;
8332     throw uno::RuntimeException();      // read-only
8333 }
8334 
8335 // XPropertySet extended for Column-Properties
8336 
8337 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScTableColumnObj::getPropertySetInfo()
8338 {
8339     SolarMutexGuard aGuard;
8340     static uno::Reference<beans::XPropertySetInfo> aRef(
8341         new SfxItemPropertySetInfo( pColPropSet->getPropertyMap() ));
8342     return aRef;
8343 }
8344 
8345 void ScTableColumnObj::SetOnePropertyValue(const SfxItemPropertyMapEntry* pEntry, const uno::Any& aValue)
8346 {
8347     if ( !pEntry )
8348         return;
8349 
8350     if ( IsScItemWid( pEntry->nWID ) )
8351     {
8352         //  for Item WIDs, call ScCellRangesBase directly
8353         ScCellRangesBase::SetOnePropertyValue(pEntry, aValue);
8354         return;
8355     }
8356 
8357     //  own properties
8358 
8359     ScDocShell* pDocSh = GetDocShell();
8360     if (!pDocSh)
8361         return;                                                 //! Exception or so?
8362     const ScRange& rRange = GetRange();
8363     OSL_ENSURE(rRange.aStart.Col() == rRange.aEnd.Col(), "Too many columns");
8364     SCCOL nCol = rRange.aStart.Col();
8365     SCTAB nTab = rRange.aStart.Tab();
8366     ScDocFunc &rFunc = pDocSh->GetDocFunc();
8367 
8368     std::vector<sc::ColRowSpan> aColArr(1, sc::ColRowSpan(nCol,nCol));
8369 
8370     if ( pEntry->nWID == SC_WID_UNO_CELLWID )
8371     {
8372         sal_Int32 nNewWidth = 0;
8373         if ( aValue >>= nNewWidth )
8374         {
8375             //  property is 1/100mm, column width is twips
8376             nNewWidth = o3tl::toTwips(nNewWidth, o3tl::Length::mm100);
8377             rFunc.SetWidthOrHeight(
8378                 true, aColArr, nTab, SC_SIZE_ORIGINAL, nNewWidth, true, true);
8379         }
8380     }
8381     else if ( pEntry->nWID == SC_WID_UNO_CELLVIS )
8382     {
8383         bool bVis = ScUnoHelpFunctions::GetBoolFromAny( aValue );
8384         ScSizeMode eMode = bVis ? SC_SIZE_SHOW : SC_SIZE_DIRECT;
8385         rFunc.SetWidthOrHeight(true, aColArr, nTab, eMode, 0, true, true);
8386         //  SC_SIZE_DIRECT with size 0 will hide
8387     }
8388     else if ( pEntry->nWID == SC_WID_UNO_OWIDTH )
8389     {
8390         bool bOpt = ScUnoHelpFunctions::GetBoolFromAny( aValue );
8391         if (bOpt)
8392             rFunc.SetWidthOrHeight(
8393                 true, aColArr, nTab, SC_SIZE_OPTIMAL, STD_EXTRA_WIDTH, true, true);
8394         // sal_False on columns currently without effect
8395     }
8396     else if ( pEntry->nWID == SC_WID_UNO_NEWPAGE || pEntry->nWID == SC_WID_UNO_MANPAGE )
8397     {
8398         bool bSet = ScUnoHelpFunctions::GetBoolFromAny( aValue );
8399         if (bSet)
8400             rFunc.InsertPageBreak( true, rRange.aStart, true, true );
8401         else
8402             rFunc.RemovePageBreak( true, rRange.aStart, true, true );
8403     }
8404     else
8405         ScCellRangeObj::SetOnePropertyValue(pEntry, aValue);        // base class, no Item WID
8406 }
8407 
8408 void ScTableColumnObj::GetOnePropertyValue( const SfxItemPropertyMapEntry* pEntry, uno::Any& rAny )
8409 {
8410     if ( !pEntry )
8411         return;
8412 
8413     ScDocShell* pDocSh = GetDocShell();
8414     if (!pDocSh)
8415         throw uno::RuntimeException();
8416 
8417     ScDocument& rDoc = pDocSh->GetDocument();
8418     const ScRange& rRange = GetRange();
8419     OSL_ENSURE(rRange.aStart.Col() == rRange.aEnd.Col(), "too many columns");
8420     SCCOL nCol = rRange.aStart.Col();
8421     SCTAB nTab = rRange.aStart.Tab();
8422 
8423     if ( pEntry->nWID == SC_WID_UNO_CELLWID )
8424     {
8425         // for hidden column, return original height
8426         sal_uInt16 nWidth = rDoc.GetOriginalWidth( nCol, nTab );
8427         //  property is 1/100mm, column width is twips
8428         nWidth = static_cast<sal_uInt16>(convertTwipToMm100(nWidth));
8429         rAny <<= static_cast<sal_Int32>(nWidth);
8430     }
8431     else if ( pEntry->nWID == SC_WID_UNO_CELLVIS )
8432     {
8433         bool bHidden = rDoc.ColHidden(nCol, nTab);
8434         rAny <<= !bHidden;
8435     }
8436     else if ( pEntry->nWID == SC_WID_UNO_OWIDTH )
8437     {
8438         //! at the moment always set ??!?!
8439         bool bOpt = !(rDoc.GetColFlags( nCol, nTab ) & CRFlags::ManualSize);
8440         rAny <<= bOpt;
8441     }
8442     else if ( pEntry->nWID == SC_WID_UNO_NEWPAGE )
8443     {
8444         ScBreakType nBreak = rDoc.HasColBreak(nCol, nTab);
8445         rAny <<= nBreak != ScBreakType::NONE;
8446     }
8447     else if ( pEntry->nWID == SC_WID_UNO_MANPAGE )
8448     {
8449         ScBreakType nBreak = rDoc.HasColBreak(nCol, nTab);
8450         rAny <<= bool(nBreak & ScBreakType::Manual);
8451     }
8452     else
8453         ScCellRangeObj::GetOnePropertyValue(pEntry, rAny);
8454 }
8455 
8456 const SfxItemPropertyMap& ScTableColumnObj::GetItemPropertyMap()
8457 {
8458     return pColPropSet->getPropertyMap();
8459 }
8460 
8461 ScTableRowObj::ScTableRowObj(ScDocShell* pDocSh, SCROW nRow, SCTAB nTab) :
8462     ScCellRangeObj( pDocSh, ScRange(0,nRow,nTab, pDocSh->GetDocument().MaxCol(),nRow,nTab) ),
8463     pRowPropSet(lcl_GetRowPropertySet())
8464 {
8465 }
8466 
8467 ScTableRowObj::~ScTableRowObj()
8468 {
8469 }
8470 
8471 // XPropertySet extended for Row-Properties
8472 
8473 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScTableRowObj::getPropertySetInfo()
8474 {
8475     SolarMutexGuard aGuard;
8476     static uno::Reference<beans::XPropertySetInfo> aRef(
8477         new SfxItemPropertySetInfo( pRowPropSet->getPropertyMap() ));
8478     return aRef;
8479 }
8480 
8481 void ScTableRowObj::SetOnePropertyValue( const SfxItemPropertyMapEntry* pEntry, const uno::Any& aValue )
8482 {
8483     if ( !pEntry )
8484         return;
8485 
8486     if ( IsScItemWid( pEntry->nWID ) )
8487     {
8488         //  for Item WIDs, call ScCellRangesBase directly
8489         ScCellRangesBase::SetOnePropertyValue(pEntry, aValue);
8490         return;
8491     }
8492 
8493     //  own properties
8494 
8495     ScDocShell* pDocSh = GetDocShell();
8496     if (!pDocSh)
8497         return;                                                 //! Exception or so?
8498     ScDocument& rDoc = pDocSh->GetDocument();
8499     const ScRange& rRange = GetRange();
8500     OSL_ENSURE(rRange.aStart.Row() == rRange.aEnd.Row(), "too many rows");
8501     SCROW nRow = rRange.aStart.Row();
8502     SCTAB nTab = rRange.aStart.Tab();
8503     ScDocFunc &rFunc = pDocSh->GetDocFunc();
8504 
8505     std::vector<sc::ColRowSpan> aRowArr(1, sc::ColRowSpan(nRow,nRow));
8506 
8507     if ( pEntry->nWID == SC_WID_UNO_CELLHGT )
8508     {
8509         sal_Int32 nNewHeight = 0;
8510         if ( aValue >>= nNewHeight )
8511         {
8512             //  property is 1/100mm, row height is twips
8513             nNewHeight = o3tl::toTwips(nNewHeight, o3tl::Length::mm100);
8514             rFunc.SetWidthOrHeight(
8515                 false, aRowArr, nTab, SC_SIZE_ORIGINAL, nNewHeight, true, true);
8516         }
8517     }
8518     else if ( pEntry->nWID == SC_WID_UNO_CELLVIS )
8519     {
8520         bool bVis = ScUnoHelpFunctions::GetBoolFromAny( aValue );
8521         ScSizeMode eMode = bVis ? SC_SIZE_SHOW : SC_SIZE_DIRECT;
8522         rFunc.SetWidthOrHeight(false, aRowArr, nTab, eMode, 0, true, true);
8523         //  SC_SIZE_DIRECT with size zero will hide
8524     }
8525     else if ( pEntry->nWID == SC_WID_UNO_CELLFILT )
8526     {
8527         bool bFil = ScUnoHelpFunctions::GetBoolFromAny( aValue );
8528         //  SC_SIZE_DIRECT with size zero will hide
8529         rDoc.SetRowFiltered(nRow, nRow, nTab, bFil);
8530     }
8531     else if ( pEntry->nWID == SC_WID_UNO_OHEIGHT )
8532     {
8533         bool bOpt = ScUnoHelpFunctions::GetBoolFromAny( aValue );
8534         if (bOpt)
8535             rFunc.SetWidthOrHeight(false, aRowArr, nTab, SC_SIZE_OPTIMAL, 0, true, true);
8536         else
8537         {
8538             //  set current height again manually
8539             sal_uInt16 nHeight = rDoc.GetOriginalHeight( nRow, nTab );
8540             rFunc.SetWidthOrHeight(false, aRowArr, nTab, SC_SIZE_ORIGINAL, nHeight, true, true);
8541         }
8542     }
8543     else if ( pEntry->nWID == SC_WID_UNO_NEWPAGE || pEntry->nWID == SC_WID_UNO_MANPAGE )
8544     {
8545         bool bSet = ScUnoHelpFunctions::GetBoolFromAny( aValue );
8546         if (bSet)
8547             rFunc.InsertPageBreak( false, rRange.aStart, true, true );
8548         else
8549             rFunc.RemovePageBreak( false, rRange.aStart, true, true );
8550     }
8551     else
8552         ScCellRangeObj::SetOnePropertyValue(pEntry, aValue);        // base class, no Item WID
8553 }
8554 
8555 void ScTableRowObj::GetOnePropertyValue( const SfxItemPropertyMapEntry* pEntry, uno::Any& rAny )
8556 {
8557     if ( !pEntry )
8558         return;
8559 
8560     ScDocShell* pDocSh = GetDocShell();
8561     if (!pDocSh)
8562         throw uno::RuntimeException();
8563     ScDocument& rDoc = pDocSh->GetDocument();
8564     const ScRange& rRange = GetRange();
8565     OSL_ENSURE(rRange.aStart.Row() == rRange.aEnd.Row(), "too many rows");
8566     SCROW nRow = rRange.aStart.Row();
8567     SCTAB nTab = rRange.aStart.Tab();
8568 
8569     if ( pEntry->nWID == SC_WID_UNO_CELLHGT )
8570     {
8571         // for hidden row, return original height
8572         sal_uInt16 nHeight = rDoc.GetOriginalHeight( nRow, nTab );
8573         //  property is 1/100mm, row height is twips
8574         nHeight = static_cast<sal_uInt16>(convertTwipToMm100(nHeight));
8575         rAny <<= static_cast<sal_Int32>(nHeight);
8576     }
8577     else if ( pEntry->nWID == SC_WID_UNO_CELLVIS )
8578     {
8579         bool bHidden = rDoc.RowHidden(nRow, nTab);
8580         rAny <<= !bHidden;
8581     }
8582     else if ( pEntry->nWID == SC_WID_UNO_CELLFILT )
8583     {
8584         bool bVis = rDoc.RowFiltered(nRow, nTab);
8585         rAny <<= bVis;
8586     }
8587     else if ( pEntry->nWID == SC_WID_UNO_OHEIGHT )
8588     {
8589         bool bOpt = !(rDoc.GetRowFlags( nRow, nTab ) & CRFlags::ManualSize);
8590         rAny <<= bOpt;
8591     }
8592     else if ( pEntry->nWID == SC_WID_UNO_NEWPAGE )
8593     {
8594         ScBreakType nBreak = rDoc.HasRowBreak(nRow, nTab);
8595         rAny <<= (nBreak != ScBreakType::NONE);
8596     }
8597     else if ( pEntry->nWID == SC_WID_UNO_MANPAGE )
8598     {
8599         bool bBreak(rDoc.HasRowBreak(nRow, nTab) & ScBreakType::Manual);
8600         rAny <<= bBreak;
8601     }
8602     else
8603         ScCellRangeObj::GetOnePropertyValue(pEntry, rAny);
8604 }
8605 
8606 const SfxItemPropertyMap& ScTableRowObj::GetItemPropertyMap()
8607 {
8608     return pRowPropSet->getPropertyMap();
8609 }
8610 
8611 ScCellsObj::ScCellsObj(ScDocShell* pDocSh, const ScRangeList& rR) :
8612     pDocShell( pDocSh ),
8613     aRanges( rR )
8614 {
8615     pDocShell->GetDocument().AddUnoObject(*this);
8616 }
8617 
8618 ScCellsObj::~ScCellsObj()
8619 {
8620     SolarMutexGuard g;
8621 
8622     if (pDocShell)
8623         pDocShell->GetDocument().RemoveUnoObject(*this);
8624 }
8625 
8626 void ScCellsObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
8627 {
8628     if ( auto pRefHint = dynamic_cast<const ScUpdateRefHint*>(&rHint) )
8629     {
8630         aRanges.UpdateReference( pRefHint->GetMode(), &pDocShell->GetDocument(), pRefHint->GetRange(),
8631                                         pRefHint->GetDx(), pRefHint->GetDy(), pRefHint->GetDz() );
8632     }
8633     else if ( rHint.GetId() == SfxHintId::Dying )
8634     {
8635         pDocShell = nullptr;
8636     }
8637 }
8638 
8639 // XEnumerationAccess
8640 
8641 uno::Reference<container::XEnumeration> SAL_CALL ScCellsObj::createEnumeration()
8642 {
8643     SolarMutexGuard aGuard;
8644     if (pDocShell)
8645         return new ScCellsEnumeration( pDocShell, aRanges );
8646     return nullptr;
8647 }
8648 
8649 uno::Type SAL_CALL ScCellsObj::getElementType()
8650 {
8651     SolarMutexGuard aGuard;
8652     return cppu::UnoType<table::XCell>::get();
8653 }
8654 
8655 sal_Bool SAL_CALL ScCellsObj::hasElements()
8656 {
8657     SolarMutexGuard aGuard;
8658     bool bHas = false;
8659     if ( pDocShell )
8660     {
8661         //! faster if test ourself?
8662 
8663         uno::Reference<container::XEnumeration> xEnum(new ScCellsEnumeration( pDocShell, aRanges ));
8664         bHas = xEnum->hasMoreElements();
8665     }
8666     return bHas;
8667 }
8668 
8669 ScCellsEnumeration::ScCellsEnumeration(ScDocShell* pDocSh, const ScRangeList& rR) :
8670     pDocShell( pDocSh ),
8671     aRanges( rR ),
8672     bAtEnd( false )
8673 {
8674     ScDocument& rDoc = pDocShell->GetDocument();
8675     rDoc.AddUnoObject(*this);
8676 
8677     if ( aRanges.empty() )
8678         bAtEnd = true;
8679     else
8680     {
8681         SCTAB nTab = aRanges[ 0 ].aStart.Tab();
8682         aPos = ScAddress(0,0,nTab);
8683         CheckPos_Impl();                    // set aPos on first matching cell
8684     }
8685 }
8686 
8687 void ScCellsEnumeration::CheckPos_Impl()
8688 {
8689     if (!pDocShell)
8690         return;
8691 
8692     bool bFound = false;
8693     ScDocument& rDoc = pDocShell->GetDocument();
8694     ScRefCellValue aCell(rDoc, aPos);
8695     if (!aCell.isEmpty())
8696     {
8697         if (!pMark)
8698         {
8699             pMark.reset( new ScMarkData(rDoc.GetSheetLimits()) );
8700             pMark->MarkFromRangeList(aRanges, false);
8701             pMark->MarkToMulti();   // needed for GetNextMarkedCell
8702         }
8703         bFound = pMark->IsCellMarked(aPos.Col(), aPos.Row());
8704     }
8705     if (!bFound)
8706         Advance_Impl();
8707 }
8708 
8709 ScCellsEnumeration::~ScCellsEnumeration()
8710 {
8711     SolarMutexGuard g;
8712 
8713     if (pDocShell)
8714         pDocShell->GetDocument().RemoveUnoObject(*this);
8715     pMark.reset();
8716 }
8717 
8718 void ScCellsEnumeration::Advance_Impl()
8719 {
8720     OSL_ENSURE(!bAtEnd,"too much Advance_Impl");
8721     if (!pMark)
8722     {
8723         pMark.reset( new ScMarkData(pDocShell->GetDocument().GetSheetLimits()) );
8724         pMark->MarkFromRangeList( aRanges, false );
8725         pMark->MarkToMulti();   // needed for GetNextMarkedCell
8726     }
8727 
8728     SCCOL nCol = aPos.Col();
8729     SCROW nRow = aPos.Row();
8730     SCTAB nTab = aPos.Tab();
8731     bool bFound = pDocShell->GetDocument().GetNextMarkedCell( nCol, nRow, nTab, *pMark );
8732     if (bFound)
8733         aPos.Set( nCol, nRow, nTab );
8734     else
8735         bAtEnd = true;      // nothing will follow
8736 }
8737 
8738 void ScCellsEnumeration::Notify( SfxBroadcaster&, const SfxHint& rHint )
8739 {
8740     const ScUpdateRefHint* pRefHint = dynamic_cast<const ScUpdateRefHint*>(&rHint);
8741     if ( pRefHint )
8742     {
8743         if (pDocShell)
8744         {
8745             aRanges.UpdateReference( pRefHint->GetMode(), &pDocShell->GetDocument(), pRefHint->GetRange(),
8746                                      pRefHint->GetDx(), pRefHint->GetDy(), pRefHint->GetDz() );
8747 
8748             pMark.reset();       // recreate from moved area
8749 
8750             if (!bAtEnd)        // adjust aPos
8751             {
8752                 ScRangeList aNew { ScRange(aPos) };
8753                 aNew.UpdateReference( pRefHint->GetMode(), &pDocShell->GetDocument(), pRefHint->GetRange(),
8754                                       pRefHint->GetDx(), pRefHint->GetDy(), pRefHint->GetDz() );
8755                 if (aNew.size()==1)
8756                 {
8757                     aPos = aNew[ 0 ].aStart;
8758                     CheckPos_Impl();
8759                 }
8760             }
8761         }
8762     }
8763     else if ( rHint.GetId() == SfxHintId::Dying )
8764     {
8765         pDocShell = nullptr;
8766     }
8767 }
8768 
8769 // XEnumeration
8770 
8771 sal_Bool SAL_CALL ScCellsEnumeration::hasMoreElements()
8772 {
8773     SolarMutexGuard aGuard;
8774     return !bAtEnd;
8775 }
8776 
8777 uno::Any SAL_CALL ScCellsEnumeration::nextElement()
8778 {
8779     SolarMutexGuard aGuard;
8780     if (pDocShell && !bAtEnd)
8781     {
8782         // interface must match ScCellsObj::getElementType
8783 
8784         ScAddress aTempPos(aPos);
8785         Advance_Impl();
8786         return uno::makeAny(uno::Reference<table::XCell>(new ScCellObj( pDocShell, aTempPos )));
8787     }
8788 
8789     throw container::NoSuchElementException();      // no more elements
8790 }
8791 
8792 ScCellFormatsObj::ScCellFormatsObj(ScDocShell* pDocSh, const ScRange& rRange) :
8793     pDocShell( pDocSh ),
8794     aTotalRange( rRange )
8795 {
8796     ScDocument& rDoc = pDocShell->GetDocument();
8797     rDoc.AddUnoObject(*this);
8798 
8799     OSL_ENSURE( aTotalRange.aStart.Tab() == aTotalRange.aEnd.Tab(), "different tables" );
8800 }
8801 
8802 ScCellFormatsObj::~ScCellFormatsObj()
8803 {
8804     SolarMutexGuard g;
8805 
8806     if (pDocShell)
8807         pDocShell->GetDocument().RemoveUnoObject(*this);
8808 }
8809 
8810 void ScCellFormatsObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
8811 {
8812     if ( dynamic_cast<const ScUpdateRefHint*>(&rHint) )
8813     {
8814         //! aTotalRange...
8815     }
8816     else if ( rHint.GetId() == SfxHintId::Dying )
8817     {
8818         pDocShell = nullptr;
8819     }
8820 }
8821 
8822 rtl::Reference<ScCellRangeObj> ScCellFormatsObj::GetObjectByIndex_Impl(tools::Long nIndex) const
8823 {
8824     //! access the AttrArrays directly !!!!
8825 
8826     rtl::Reference<ScCellRangeObj> pRet;
8827     if (pDocShell)
8828     {
8829         ScDocument& rDoc = pDocShell->GetDocument();
8830         tools::Long nPos = 0;
8831         ScAttrRectIterator aIter( rDoc, aTotalRange.aStart.Tab(),
8832                                     aTotalRange.aStart.Col(), aTotalRange.aStart.Row(),
8833                                     aTotalRange.aEnd.Col(), aTotalRange.aEnd.Row() );
8834         SCCOL nCol1, nCol2;
8835         SCROW nRow1, nRow2;
8836         while ( aIter.GetNext( nCol1, nCol2, nRow1, nRow2 ) )
8837         {
8838             if ( nPos == nIndex )
8839             {
8840                 SCTAB nTab = aTotalRange.aStart.Tab();
8841                 ScRange aNext( nCol1, nRow1, nTab, nCol2, nRow2, nTab );
8842 
8843                 if ( aNext.aStart == aNext.aEnd )
8844                     pRet = new ScCellObj( pDocShell, aNext.aStart );
8845                 else
8846                     pRet = new ScCellRangeObj( pDocShell, aNext );
8847             }
8848             ++nPos;
8849         }
8850     }
8851     return pRet;
8852 }
8853 
8854 // XIndexAccess
8855 
8856 sal_Int32 SAL_CALL ScCellFormatsObj::getCount()
8857 {
8858     SolarMutexGuard aGuard;
8859 
8860     //! access the AttrArrays directly !!!!
8861 
8862     tools::Long nCount = 0;
8863     if (pDocShell)
8864     {
8865         ScDocument& rDoc = pDocShell->GetDocument();
8866         ScAttrRectIterator aIter( rDoc, aTotalRange.aStart.Tab(),
8867                                     aTotalRange.aStart.Col(), aTotalRange.aStart.Row(),
8868                                     aTotalRange.aEnd.Col(), aTotalRange.aEnd.Row() );
8869         SCCOL nCol1, nCol2;
8870         SCROW nRow1, nRow2;
8871         while ( aIter.GetNext( nCol1, nCol2, nRow1, nRow2 ) )
8872             ++nCount;
8873     }
8874     return nCount;
8875 }
8876 
8877 uno::Any SAL_CALL ScCellFormatsObj::getByIndex( sal_Int32 nIndex )
8878 {
8879     SolarMutexGuard aGuard;
8880 
8881     uno::Reference<table::XCellRange> xRange(GetObjectByIndex_Impl(nIndex));
8882     if (!xRange.is())
8883         throw lang::IndexOutOfBoundsException();
8884 
8885     return uno::makeAny(xRange);
8886 
8887 }
8888 
8889 uno::Type SAL_CALL ScCellFormatsObj::getElementType()
8890 {
8891     SolarMutexGuard aGuard;
8892     return cppu::UnoType<table::XCellRange>::get();
8893 }
8894 
8895 sal_Bool SAL_CALL ScCellFormatsObj::hasElements()
8896 {
8897     SolarMutexGuard aGuard;
8898     return ( getCount() != 0 );     //! always greater then zero ??
8899 }
8900 
8901 // XEnumerationAccess
8902 
8903 uno::Reference<container::XEnumeration> SAL_CALL ScCellFormatsObj::createEnumeration()
8904 {
8905     SolarMutexGuard aGuard;
8906     if (pDocShell)
8907         return new ScCellFormatsEnumeration( pDocShell, aTotalRange );
8908     return nullptr;
8909 }
8910 
8911 ScCellFormatsEnumeration::ScCellFormatsEnumeration(ScDocShell* pDocSh, const ScRange& rRange) :
8912     pDocShell( pDocSh ),
8913     nTab( rRange.aStart.Tab() ),
8914     bAtEnd( false ),
8915     bDirty( false )
8916 {
8917     ScDocument& rDoc = pDocShell->GetDocument();
8918     rDoc.AddUnoObject(*this);
8919 
8920     OSL_ENSURE( rRange.aStart.Tab() == rRange.aEnd.Tab(),
8921                 "CellFormatsEnumeration: different tables" );
8922 
8923     pIter.reset( new ScAttrRectIterator( rDoc, nTab,
8924                                     rRange.aStart.Col(), rRange.aStart.Row(),
8925                                     rRange.aEnd.Col(), rRange.aEnd.Row() ) );
8926     Advance_Impl();
8927 }
8928 
8929 ScCellFormatsEnumeration::~ScCellFormatsEnumeration()
8930 {
8931     SolarMutexGuard g;
8932 
8933     if (pDocShell)
8934         pDocShell->GetDocument().RemoveUnoObject(*this);
8935 }
8936 
8937 void ScCellFormatsEnumeration::Advance_Impl()
8938 {
8939     OSL_ENSURE(!bAtEnd,"too many Advance_Impl");
8940 
8941     if ( pIter )
8942     {
8943         if ( bDirty )
8944         {
8945             pIter->DataChanged();   // new search for AttrArray-Index
8946             bDirty = false;
8947         }
8948 
8949         SCCOL nCol1, nCol2;
8950         SCROW nRow1, nRow2;
8951         if ( pIter->GetNext( nCol1, nCol2, nRow1, nRow2 ) )
8952             aNext = ScRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab );
8953         else
8954             bAtEnd = true;
8955     }
8956     else
8957         bAtEnd = true;          // document vanished or so
8958 }
8959 
8960 rtl::Reference<ScCellRangeObj> ScCellFormatsEnumeration::NextObject_Impl()
8961 {
8962     rtl::Reference<ScCellRangeObj> pRet;
8963     if (pDocShell && !bAtEnd)
8964     {
8965         if ( aNext.aStart == aNext.aEnd )
8966             pRet = new ScCellObj( pDocShell, aNext.aStart );
8967         else
8968             pRet = new ScCellRangeObj( pDocShell, aNext );
8969         Advance_Impl();
8970     }
8971     return pRet;
8972 }
8973 
8974 void ScCellFormatsEnumeration::Notify( SfxBroadcaster&, const SfxHint& rHint )
8975 {
8976     if ( dynamic_cast<const ScUpdateRefHint*>(&rHint) )
8977     {
8978         //! and now???
8979     }
8980     else
8981     {
8982         const SfxHintId nId = rHint.GetId();
8983         if ( nId == SfxHintId::Dying )
8984         {
8985             pDocShell = nullptr;
8986             pIter.reset();
8987         }
8988         else if ( nId == SfxHintId::DataChanged )
8989         {
8990             bDirty = true;          // AttrArray-Index possibly invalid
8991         }
8992     }
8993 }
8994 
8995 // XEnumeration
8996 
8997 sal_Bool SAL_CALL ScCellFormatsEnumeration::hasMoreElements()
8998 {
8999     SolarMutexGuard aGuard;
9000     return !bAtEnd;
9001 }
9002 
9003 uno::Any SAL_CALL ScCellFormatsEnumeration::nextElement()
9004 {
9005     SolarMutexGuard aGuard;
9006 
9007     if ( bAtEnd || !pDocShell )
9008         throw container::NoSuchElementException();      // no more elements
9009 
9010     // interface must match ScCellFormatsObj::getElementType
9011 
9012     return uno::makeAny(uno::Reference<table::XCellRange> (NextObject_Impl()));
9013 }
9014 
9015 ScUniqueCellFormatsObj::~ScUniqueCellFormatsObj()
9016 {
9017     SolarMutexGuard g;
9018 
9019     if (pDocShell)
9020         pDocShell->GetDocument().RemoveUnoObject(*this);
9021 }
9022 
9023 void ScUniqueCellFormatsObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
9024 {
9025     if ( dynamic_cast<const ScUpdateRefHint*>(&rHint) )
9026     {
9027         //! aTotalRange...
9028     }
9029     else
9030     {
9031         if ( rHint.GetId() == SfxHintId::Dying )
9032             pDocShell = nullptr;
9033     }
9034 }
9035 
9036 //  Fill the list of formats from the document
9037 
9038 namespace {
9039 
9040 // hash code to access the range lists by ScPatternAttr pointer
9041 struct ScPatternHashCode
9042 {
9043     size_t operator()( const ScPatternAttr* pPattern ) const
9044     {
9045         return reinterpret_cast<size_t>(pPattern);
9046     }
9047 };
9048 
9049 }
9050 
9051 // Hash map to find a range by its start row
9052 typedef std::unordered_map< SCROW, ScRange > ScRowRangeHashMap;
9053 
9054 namespace {
9055 
9056 // Hash map entry.
9057 // The Join method depends on the column-wise order of ScAttrRectIterator
9058 class ScUniqueFormatsEntry
9059 {
9060     enum EntryState { STATE_EMPTY, STATE_SINGLE, STATE_COMPLEX };
9061 
9062     EntryState          eState;
9063     ScRange             aSingleRange;
9064     ScRowRangeHashMap   aJoinedRanges;      // "active" ranges to be merged
9065     std::vector<ScRange> aCompletedRanges;   // ranges that will no longer be touched
9066     ScRangeListRef      aReturnRanges;      // result as ScRangeList for further use
9067 
9068 public:
9069                         ScUniqueFormatsEntry() : eState( STATE_EMPTY ) {}
9070 
9071     void                Join( const ScRange& rNewRange );
9072     const ScRangeList&  GetRanges();
9073     void                Clear() { aReturnRanges.clear(); }  // aJoinedRanges and aCompletedRanges are cleared in GetRanges
9074 };
9075 
9076 }
9077 
9078 void ScUniqueFormatsEntry::Join( const ScRange& rNewRange )
9079 {
9080     // Special-case handling for single range
9081 
9082     if ( eState == STATE_EMPTY )
9083     {
9084         aSingleRange = rNewRange;
9085         eState = STATE_SINGLE;
9086         return;
9087     }
9088     if ( eState == STATE_SINGLE )
9089     {
9090         if ( aSingleRange.aStart.Row() == rNewRange.aStart.Row() &&
9091              aSingleRange.aEnd.Row() == rNewRange.aEnd.Row() &&
9092              aSingleRange.aEnd.Col() + 1 == rNewRange.aStart.Col() )
9093         {
9094             aSingleRange.aEnd.SetCol( rNewRange.aEnd.Col() );
9095             return;     // still a single range
9096         }
9097 
9098         SCROW nSingleRow = aSingleRange.aStart.Row();
9099         aJoinedRanges.emplace( nSingleRow, aSingleRange );
9100         eState = STATE_COMPLEX;
9101         // continue normally
9102     }
9103 
9104     // This is called in the order of ScAttrRectIterator results.
9105     // rNewRange can only be joined with an existing entry if it's the same rows, starting in the next column.
9106     // If the old entry for the start row extends to a different end row, or ends in a different column, it
9107     // can be moved to aCompletedRanges because it can't be joined with following iterator results.
9108     // Everything happens within one sheet, so Tab can be ignored.
9109 
9110     SCROW nStartRow = rNewRange.aStart.Row();
9111     ScRowRangeHashMap::iterator aIter( aJoinedRanges.find( nStartRow ) );       // find the active entry for the start row
9112     if ( aIter != aJoinedRanges.end() )
9113     {
9114         ScRange& rOldRange = aIter->second;
9115         if ( rOldRange.aEnd.Row() == rNewRange.aEnd.Row() &&
9116              rOldRange.aEnd.Col() + 1 == rNewRange.aStart.Col() )
9117         {
9118             // extend existing range
9119             rOldRange.aEnd.SetCol( rNewRange.aEnd.Col() );
9120         }
9121         else
9122         {
9123             // move old range to aCompletedRanges, keep rNewRange for joining
9124             aCompletedRanges.push_back( rOldRange );
9125             rOldRange = rNewRange;  // replace in hash map
9126         }
9127     }
9128     else
9129     {
9130         // keep rNewRange for joining
9131         aJoinedRanges.emplace( nStartRow, rNewRange );
9132     }
9133 }
9134 
9135 const ScRangeList& ScUniqueFormatsEntry::GetRanges()
9136 {
9137     if ( eState == STATE_SINGLE )
9138     {
9139         aReturnRanges = new ScRangeList( aSingleRange );
9140         return *aReturnRanges;
9141     }
9142 
9143     // move remaining entries from aJoinedRanges to aCompletedRanges
9144 
9145     for ( const auto& rEntry : aJoinedRanges )
9146         aCompletedRanges.push_back( rEntry.second );
9147     aJoinedRanges.clear();
9148 
9149     // sort all ranges for a predictable API result
9150 
9151     std::sort( aCompletedRanges.begin(), aCompletedRanges.end() );
9152 
9153     // fill and return ScRangeList
9154 
9155     aReturnRanges = new ScRangeList;
9156     aReturnRanges->insert( aReturnRanges->end(), aCompletedRanges.begin(), aCompletedRanges.end() );
9157     aCompletedRanges.clear();
9158 
9159     return *aReturnRanges;
9160 }
9161 
9162 namespace {
9163 
9164 // function object to sort the range lists by start of first range
9165 struct ScUniqueFormatsOrder
9166 {
9167     bool operator()( const ScRangeList& rList1, const ScRangeList& rList2 ) const
9168     {
9169         // all range lists have at least one entry
9170         OSL_ENSURE( !rList1.empty() && !rList2.empty(), "ScUniqueFormatsOrder: empty list" );
9171 
9172         // compare start positions using ScAddress comparison operator
9173         return ( rList1[ 0 ].aStart < rList2[ 0 ].aStart );
9174     }
9175 };
9176 
9177 }
9178 
9179 ScUniqueCellFormatsObj::ScUniqueCellFormatsObj(ScDocShell* pDocSh, const ScRange& rTotalRange) :
9180     pDocShell( pDocSh )
9181 {
9182     pDocShell->GetDocument().AddUnoObject(*this);
9183 
9184     OSL_ENSURE( rTotalRange.aStart.Tab() == rTotalRange.aEnd.Tab(), "different tables" );
9185 
9186     ScDocument& rDoc = pDocShell->GetDocument();
9187     SCTAB nTab = rTotalRange.aStart.Tab();
9188     ScAttrRectIterator aIter( rDoc, nTab,
9189                                 rTotalRange.aStart.Col(), rTotalRange.aStart.Row(),
9190                                 rTotalRange.aEnd.Col(), rTotalRange.aEnd.Row() );
9191     SCCOL nCol1, nCol2;
9192     SCROW nRow1, nRow2;
9193 
9194     // Collect the ranges for each format in a hash map, to avoid nested loops
9195 
9196     std::unordered_map< const ScPatternAttr*, ScUniqueFormatsEntry, ScPatternHashCode > aHashMap;
9197     while (aIter.GetNext( nCol1, nCol2, nRow1, nRow2 ) )
9198     {
9199         ScRange aRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab );
9200         const ScPatternAttr* pPattern = rDoc.GetPattern(nCol1, nRow1, nTab);
9201         aHashMap[pPattern].Join( aRange );
9202     }
9203 
9204     // Fill the vector aRangeLists with the range lists from the hash map
9205 
9206     aRangeLists.reserve( aHashMap.size() );
9207     for ( auto& rMapEntry : aHashMap )
9208     {
9209         ScUniqueFormatsEntry& rEntry = rMapEntry.second;
9210         const ScRangeList& rRanges = rEntry.GetRanges();
9211         aRangeLists.push_back( rRanges );       // copy ScRangeList
9212         rEntry.Clear();                         // free memory, don't hold both copies of all ranges
9213     }
9214 
9215     // Sort the vector by first range's start position, to avoid random shuffling
9216     // due to using the ScPatterAttr pointers
9217 
9218     ::std::sort( aRangeLists.begin(), aRangeLists.end(), ScUniqueFormatsOrder() );
9219 }
9220 
9221 
9222 // XIndexAccess
9223 
9224 sal_Int32 SAL_CALL ScUniqueCellFormatsObj::getCount()
9225 {
9226     SolarMutexGuard aGuard;
9227 
9228     return aRangeLists.size();
9229 }
9230 
9231 uno::Any SAL_CALL ScUniqueCellFormatsObj::getByIndex( sal_Int32 nIndex )
9232 {
9233     SolarMutexGuard aGuard;
9234 
9235     if(o3tl::make_unsigned(nIndex) >= aRangeLists.size())
9236         throw lang::IndexOutOfBoundsException();
9237 
9238     return uno::makeAny(uno::Reference<sheet::XSheetCellRangeContainer>(new ScCellRangesObj(pDocShell, aRangeLists[nIndex])));
9239 
9240 }
9241 
9242 uno::Type SAL_CALL ScUniqueCellFormatsObj::getElementType()
9243 {
9244     SolarMutexGuard aGuard;
9245     return cppu::UnoType<sheet::XSheetCellRangeContainer>::get();
9246 }
9247 
9248 sal_Bool SAL_CALL ScUniqueCellFormatsObj::hasElements()
9249 {
9250     SolarMutexGuard aGuard;
9251     return ( !aRangeLists.empty() );
9252 }
9253 
9254 // XEnumerationAccess
9255 
9256 uno::Reference<container::XEnumeration> SAL_CALL ScUniqueCellFormatsObj::createEnumeration()
9257 {
9258     SolarMutexGuard aGuard;
9259     if (pDocShell)
9260         return new ScUniqueCellFormatsEnumeration( pDocShell, std::vector(aRangeLists) );
9261     return nullptr;
9262 }
9263 
9264 ScUniqueCellFormatsEnumeration::ScUniqueCellFormatsEnumeration(ScDocShell* pDocSh, std::vector<ScRangeList>&& rRangeLists) :
9265     aRangeLists(std::move(rRangeLists)),
9266     pDocShell( pDocSh ),
9267     nCurrentPosition(0)
9268 {
9269     pDocShell->GetDocument().AddUnoObject(*this);
9270 }
9271 
9272 ScUniqueCellFormatsEnumeration::~ScUniqueCellFormatsEnumeration()
9273 {
9274     SolarMutexGuard g;
9275 
9276     if (pDocShell)
9277         pDocShell->GetDocument().RemoveUnoObject(*this);
9278 }
9279 
9280 void ScUniqueCellFormatsEnumeration::Notify( SfxBroadcaster&, const SfxHint& rHint )
9281 {
9282     if ( dynamic_cast<const ScUpdateRefHint*>(&rHint) )
9283     {
9284         //! and now ???
9285     }
9286     else
9287     {
9288         if ( rHint.GetId() == SfxHintId::Dying )
9289             pDocShell = nullptr;
9290     }
9291 }
9292 
9293 // XEnumeration
9294 
9295 sal_Bool SAL_CALL ScUniqueCellFormatsEnumeration::hasMoreElements()
9296 {
9297     SolarMutexGuard aGuard;
9298     return o3tl::make_unsigned(nCurrentPosition) < aRangeLists.size();
9299 }
9300 
9301 uno::Any SAL_CALL ScUniqueCellFormatsEnumeration::nextElement()
9302 {
9303     SolarMutexGuard aGuard;
9304 
9305     if ( !hasMoreElements() || !pDocShell )
9306         throw container::NoSuchElementException();      // no more elements
9307 
9308     // interface type must match ScCellFormatsObj::getElementType
9309 
9310     return uno::makeAny(uno::Reference<sheet::XSheetCellRangeContainer>(new ScCellRangesObj(pDocShell, aRangeLists[nCurrentPosition++])));
9311 }
9312 
9313 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
9314