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