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