summaryrefslogtreecommitdiffstats
path: root/sc/source/ui/unoobj/cellsuno.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/ui/unoobj/cellsuno.cxx')
-rw-r--r--sc/source/ui/unoobj/cellsuno.cxx9302
1 files changed, 9302 insertions, 0 deletions
diff --git a/sc/source/ui/unoobj/cellsuno.cxx b/sc/source/ui/unoobj/cellsuno.cxx
new file mode 100644
index 000000000..b2117cefc
--- /dev/null
+++ b/sc/source/ui/unoobj/cellsuno.cxx
@@ -0,0 +1,9302 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <scitems.hxx>
+#include <editeng/eeitem.hxx>
+#include <o3tl/safeint.hxx>
+#include <svx/svdpool.hxx>
+
+#include <vcl/svapp.hxx>
+#include <svx/algitem.hxx>
+#include <editeng/borderline.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/editeng.hxx>
+#include <editeng/flditem.hxx>
+#include <editeng/editobj.hxx>
+#include <editeng/unoipset.hxx>
+#include <editeng/langitem.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <svl/numformat.hxx>
+#include <svl/srchitem.hxx>
+#include <svl/sharedstringpool.hxx>
+#include <svx/unomid.hxx>
+#include <editeng/unoprnms.hxx>
+#include <editeng/unotext.hxx>
+#include <svx/svdpage.hxx>
+#include <sfx2/bindings.hxx>
+#include <svl/zforlist.hxx>
+#include <svl/zformat.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <float.h>
+#include <tools/diagnose_ex.h>
+#include <tools/UnitConversion.hxx>
+
+#include <com/sun/star/awt/XBitmap.hpp>
+#include <com/sun/star/util/CellProtection.hpp>
+#include <com/sun/star/table/CellHoriJustify.hpp>
+#include <com/sun/star/table/CellOrientation.hpp>
+#include <com/sun/star/table/ShadowFormat.hpp>
+#include <com/sun/star/table/TableBorder.hpp>
+#include <com/sun/star/table/TableBorder2.hpp>
+#include <com/sun/star/sheet/CellFlags.hpp>
+#include <com/sun/star/sheet/FormulaResult.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/lang/Locale.hpp>
+#include <com/sun/star/beans/TolerantPropertySetResultType.hpp>
+#include <com/sun/star/beans/SetPropertyTolerantFailed.hpp>
+#include <com/sun/star/text/WritingMode2.hpp>
+#include <com/sun/star/text/textfield/Type.hpp>
+#include <com/sun/star/sheet/XConditionalFormats.hpp>
+
+#include <autoform.hxx>
+#include <cellvalue.hxx>
+#include <cellmergeoption.hxx>
+#include <cellsuno.hxx>
+#include <cursuno.hxx>
+#include <textuno.hxx>
+#include <editsrc.hxx>
+#include <notesuno.hxx>
+#include <fielduno.hxx>
+#include <docuno.hxx>
+#include <datauno.hxx>
+#include <dapiuno.hxx>
+#include <chartuno.hxx>
+#include <fmtuno.hxx>
+#include <miscuno.hxx>
+#include <convuno.hxx>
+#include <srchuno.hxx>
+#include <nameuno.hxx>
+#include <targuno.hxx>
+#include <tokenuno.hxx>
+#include <eventuno.hxx>
+#include <docsh.hxx>
+#include <markdata.hxx>
+#include <patattr.hxx>
+#include <docpool.hxx>
+#include <docfunc.hxx>
+#include <dbdocfun.hxx>
+#include <olinefun.hxx>
+#include <hints.hxx>
+#include <formulacell.hxx>
+#include <undotab.hxx>
+#include <undoblk.hxx>
+#include <stlsheet.hxx>
+#include <dbdata.hxx>
+#include <attrib.hxx>
+#include <chartarr.hxx>
+#include <chartlis.hxx>
+#include <drwlayer.hxx>
+#include <printfun.hxx>
+#include <prnsave.hxx>
+#include <tablink.hxx>
+#include <dociter.hxx>
+#include <rangeutl.hxx>
+#include <conditio.hxx>
+#include <validat.hxx>
+#include <sc.hrc>
+#include <cellform.hxx>
+#include <globstr.hrc>
+#include <scresid.hxx>
+#include <unonames.hxx>
+#include <styleuno.hxx>
+#include <rangeseq.hxx>
+#include <unowids.hxx>
+#include <paramisc.hxx>
+#include <queryentry.hxx>
+#include <formula/errorcodes.hxx>
+#include <unoreflist.hxx>
+#include <formula/grammar.hxx>
+#include <editeng/escapementitem.hxx>
+#include <stringutil.hxx>
+#include <formulaiter.hxx>
+#include <tokenarray.hxx>
+#include <stylehelper.hxx>
+#include <dputil.hxx>
+#include <sortparam.hxx>
+#include <condformatuno.hxx>
+#include <TablePivotCharts.hxx>
+#include <table.hxx>
+#include <refundo.hxx>
+#include <columnspanset.hxx>
+
+#include <memory>
+
+using namespace com::sun::star;
+
+// The names in the maps must be sorted according to strcmp!
+//! Instead of Which-ID 0 use special IDs and do not compare via names!
+
+// Left/Right/Top/BottomBorder are mapped directly to the core items,
+// not collected/applied to the borders of a range -> ATTR_BORDER can be used directly
+
+static const SfxItemPropertySet* lcl_GetCellsPropertySet()
+{
+ static const SfxItemPropertyMapEntry aCellsPropertyMap_Impl[] =
+ {
+ { SC_UNONAME_ABSNAME, SC_WID_UNO_ABSNAME, cppu::UnoType<OUString>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
+ { SC_UNONAME_ASIANVERT,ATTR_VERTICAL_ASIAN,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_BOTTBORDER,ATTR_BORDER, ::cppu::UnoType<table::BorderLine>::get(), 0, BOTTOM_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_BOTTBORDER2,ATTR_BORDER, ::cppu::UnoType<table::BorderLine2>::get(), 0, BOTTOM_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_CELLBACK, ATTR_BACKGROUND, cppu::UnoType<sal_Int32>::get(), 0, MID_BACK_COLOR },
+ { SC_UNONAME_CELLPRO, ATTR_PROTECTION, cppu::UnoType<util::CellProtection>::get(), 0, 0 },
+ { SC_UNONAME_CELLSTYL, SC_WID_UNO_CELLSTYL,cppu::UnoType<OUString>::get(), 0, 0 },
+ { SC_UNONAME_CCOLOR, ATTR_FONT_COLOR, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_COUTL, ATTR_FONT_CONTOUR, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CCROSS, ATTR_FONT_CROSSEDOUT,cppu::UnoType<bool>::get(), 0, MID_CROSSED_OUT },
+ { SC_UNONAME_CEMPHAS, ATTR_FONT_EMPHASISMARK,cppu::UnoType<sal_Int16>::get(), 0, MID_EMPHASIS },
+ { SC_UNONAME_CFONT, ATTR_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_FAMILY },
+ { SC_UNONAME_CFCHARS, ATTR_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_CHAR_SET },
+ { SC_UNO_CJK_CFCHARS, ATTR_CJK_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_CHAR_SET },
+ { SC_UNO_CTL_CFCHARS, ATTR_CTL_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_CHAR_SET },
+ { SC_UNONAME_CFFAMIL, ATTR_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_FAMILY },
+ { SC_UNO_CJK_CFFAMIL, ATTR_CJK_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_FAMILY },
+ { SC_UNO_CTL_CFFAMIL, ATTR_CTL_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_FAMILY },
+ { SC_UNONAME_CFNAME, ATTR_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_FAMILY_NAME },
+ { SC_UNO_CJK_CFNAME, ATTR_CJK_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_FAMILY_NAME },
+ { SC_UNO_CTL_CFNAME, ATTR_CTL_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_FAMILY_NAME },
+ { SC_UNONAME_CFPITCH, ATTR_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_PITCH },
+ { SC_UNO_CJK_CFPITCH, ATTR_CJK_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_PITCH },
+ { SC_UNO_CTL_CFPITCH, ATTR_CTL_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_PITCH },
+ { SC_UNONAME_CFSTYLE, ATTR_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_STYLE_NAME },
+ { SC_UNO_CJK_CFSTYLE, ATTR_CJK_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_STYLE_NAME },
+ { SC_UNO_CTL_CFSTYLE, ATTR_CTL_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_STYLE_NAME },
+ { SC_UNONAME_CHEIGHT, ATTR_FONT_HEIGHT, cppu::UnoType<float>::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS },
+ { SC_UNO_CJK_CHEIGHT, ATTR_CJK_FONT_HEIGHT,cppu::UnoType<float>::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS },
+ { SC_UNO_CTL_CHEIGHT, ATTR_CTL_FONT_HEIGHT,cppu::UnoType<float>::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS },
+ { SC_UNONAME_CLOCAL, ATTR_FONT_LANGUAGE, cppu::UnoType<lang::Locale>::get(), 0, MID_LANG_LOCALE },
+ { SC_UNO_CJK_CLOCAL, ATTR_CJK_FONT_LANGUAGE,cppu::UnoType<lang::Locale>::get(), 0, MID_LANG_LOCALE },
+ { SC_UNO_CTL_CLOCAL, ATTR_CTL_FONT_LANGUAGE,cppu::UnoType<lang::Locale>::get(), 0, MID_LANG_LOCALE },
+ { SC_UNONAME_COVER, ATTR_FONT_OVERLINE, cppu::UnoType<sal_Int16>::get(), 0, MID_TL_STYLE },
+ { SC_UNONAME_COVRLCOL, ATTR_FONT_OVERLINE, cppu::UnoType<sal_Int32>::get(), 0, MID_TL_COLOR },
+ { SC_UNONAME_COVRLHAS, ATTR_FONT_OVERLINE, cppu::UnoType<bool>::get(), 0, MID_TL_HASCOLOR },
+ { SC_UNONAME_CPOST, ATTR_FONT_POSTURE, cppu::UnoType<awt::FontSlant>::get(), 0, MID_POSTURE },
+ { SC_UNO_CJK_CPOST, ATTR_CJK_FONT_POSTURE,cppu::UnoType<awt::FontSlant>::get(), 0, MID_POSTURE },
+ { SC_UNO_CTL_CPOST, ATTR_CTL_FONT_POSTURE,cppu::UnoType<awt::FontSlant>::get(), 0, MID_POSTURE },
+ { SC_UNONAME_CRELIEF, ATTR_FONT_RELIEF, cppu::UnoType<sal_Int16>::get(), 0, MID_RELIEF },
+ { SC_UNONAME_CSHADD, ATTR_FONT_SHADOWED, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CSTRIKE, ATTR_FONT_CROSSEDOUT,cppu::UnoType<sal_Int16>::get(), 0, MID_CROSS_OUT },
+ { SC_UNONAME_CUNDER, ATTR_FONT_UNDERLINE,cppu::UnoType<sal_Int16>::get(), 0, MID_TL_STYLE },
+ { SC_UNONAME_CUNDLCOL, ATTR_FONT_UNDERLINE,cppu::UnoType<sal_Int32>::get(), 0, MID_TL_COLOR },
+ { SC_UNONAME_CUNDLHAS, ATTR_FONT_UNDERLINE,cppu::UnoType<bool>::get(), 0, MID_TL_HASCOLOR },
+ { SC_UNONAME_CWEIGHT, ATTR_FONT_WEIGHT, cppu::UnoType<float>::get(), 0, MID_WEIGHT },
+ { SC_UNO_CJK_CWEIGHT, ATTR_CJK_FONT_WEIGHT,cppu::UnoType<float>::get(), 0, MID_WEIGHT },
+ { SC_UNO_CTL_CWEIGHT, ATTR_CTL_FONT_WEIGHT,cppu::UnoType<float>::get(), 0, MID_WEIGHT },
+ { SC_UNONAME_CWORDMOD, ATTR_FONT_WORDLINE, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CHCOLHDR, SC_WID_UNO_CHCOLHDR,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CHROWHDR, SC_WID_UNO_CHROWHDR,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CONDFMT, SC_WID_UNO_CONDFMT, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
+ { SC_UNONAME_CONDLOC, SC_WID_UNO_CONDLOC, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
+ { SC_UNONAME_CONDXML, SC_WID_UNO_CONDXML, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
+ { SC_UNONAME_DIAGONAL_BLTR, ATTR_BORDER_BLTR, ::cppu::UnoType<table::BorderLine>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_DIAGONAL_BLTR2, ATTR_BORDER_BLTR, ::cppu::UnoType<table::BorderLine2>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_DIAGONAL_TLBR, ATTR_BORDER_TLBR, ::cppu::UnoType<table::BorderLine>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_DIAGONAL_TLBR2, ATTR_BORDER_TLBR, ::cppu::UnoType<table::BorderLine2>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_CELLHJUS, ATTR_HOR_JUSTIFY, cppu::UnoType<table::CellHoriJustify>::get(), 0, MID_HORJUST_HORJUST },
+ { SC_UNONAME_CELLHJUS_METHOD, ATTR_HOR_JUSTIFY_METHOD, ::cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_CELLTRAN, ATTR_BACKGROUND, cppu::UnoType<bool>::get(), 0, MID_GRAPHIC_TRANSPARENT },
+ { SC_UNONAME_WRAP, ATTR_LINEBREAK, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_LEFTBORDER,ATTR_BORDER, ::cppu::UnoType<table::BorderLine>::get(), 0, LEFT_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_LEFTBORDER2,ATTR_BORDER, ::cppu::UnoType<table::BorderLine2>::get(), 0, LEFT_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_NUMFMT, ATTR_VALUE_FORMAT, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_NUMRULES, SC_WID_UNO_NUMRULES,cppu::UnoType<container::XIndexReplace>::get(), 0, 0 },
+ { SC_UNONAME_CELLORI, ATTR_STACKED, cppu::UnoType<table::CellOrientation>::get(), 0, 0 },
+ { SC_UNONAME_PADJUST, ATTR_HOR_JUSTIFY, ::cppu::UnoType<sal_Int16>::get(), 0, MID_HORJUST_ADJUST },
+ { SC_UNONAME_PBMARGIN, ATTR_MARGIN, cppu::UnoType<sal_Int32>::get(), 0, MID_MARGIN_LO_MARGIN | CONVERT_TWIPS },
+ { SC_UNONAME_PINDENT, ATTR_INDENT, cppu::UnoType<sal_Int16>::get(), 0, 0 }, //! CONVERT_TWIPS
+ { SC_UNONAME_PISCHDIST,ATTR_SCRIPTSPACE, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_PISFORBID,ATTR_FORBIDDEN_RULES,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_PISHANG, ATTR_HANGPUNCTUATION,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_PISHYPHEN,ATTR_HYPHENATE, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_PLASTADJ, ATTR_HOR_JUSTIFY, ::cppu::UnoType<sal_Int16>::get(), 0, MID_HORJUST_ADJUST },
+ { SC_UNONAME_PLMARGIN, ATTR_MARGIN, cppu::UnoType<sal_Int32>::get(), 0, MID_MARGIN_L_MARGIN | CONVERT_TWIPS },
+ { SC_UNONAME_PRMARGIN, ATTR_MARGIN, cppu::UnoType<sal_Int32>::get(), 0, MID_MARGIN_R_MARGIN | CONVERT_TWIPS },
+ { SC_UNONAME_PTMARGIN, ATTR_MARGIN, cppu::UnoType<sal_Int32>::get(), 0, MID_MARGIN_UP_MARGIN | CONVERT_TWIPS },
+ { SC_UNONAME_RIGHTBORDER,ATTR_BORDER, ::cppu::UnoType<table::BorderLine>::get(), 0, RIGHT_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_RIGHTBORDER2,ATTR_BORDER, ::cppu::UnoType<table::BorderLine2>::get(), 0, RIGHT_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_ROTANG, ATTR_ROTATE_VALUE, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_ROTREF, ATTR_ROTATE_MODE, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_SHADOW, ATTR_SHADOW, cppu::UnoType<table::ShadowFormat>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_SHRINK_TO_FIT, ATTR_SHRINKTOFIT, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_TBLBORD, SC_WID_UNO_TBLBORD, cppu::UnoType<table::TableBorder>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_TBLBORD2, SC_WID_UNO_TBLBORD2, cppu::UnoType<table::TableBorder2>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_TOPBORDER,ATTR_BORDER, ::cppu::UnoType<table::BorderLine>::get(), 0, TOP_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_TOPBORDER2,ATTR_BORDER, ::cppu::UnoType<table::BorderLine2>::get(), 0, TOP_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_USERDEF, ATTR_USERDEF, cppu::UnoType<container::XNameContainer>::get(), 0, 0 },
+ { SC_UNONAME_VALIDAT, SC_WID_UNO_VALIDAT, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
+ { SC_UNONAME_VALILOC, SC_WID_UNO_VALILOC, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
+ { SC_UNONAME_VALIXML, SC_WID_UNO_VALIXML, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
+ { SC_UNONAME_CELLVJUS, ATTR_VER_JUSTIFY, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_CELLVJUS_METHOD, ATTR_VER_JUSTIFY_METHOD, ::cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_WRITING, ATTR_WRITINGDIR, cppu::UnoType<sal_Int16>::get(), 0, 0 },
+ { SC_UNONAME_HYPERLINK, ATTR_HYPERLINK, cppu::UnoType<OUString>::get(), 0, 0 },
+ { SC_UNONAME_FORMATID, SC_WID_UNO_FORMATID, cppu::UnoType<sal_uInt64>::get(), 0, 0 },
+ { u"", 0, css::uno::Type(), 0, 0 }
+ };
+ static SfxItemPropertySet aCellsPropertySet( aCellsPropertyMap_Impl );
+ return &aCellsPropertySet;
+}
+
+// CellRange contains all entries from Cells, plus its own entries
+// with Which-ID 0 (those are needed only for getPropertySetInfo).
+
+static const SfxItemPropertySet* lcl_GetRangePropertySet()
+{
+ static const SfxItemPropertyMapEntry aRangePropertyMap_Impl[] =
+ {
+ { SC_UNONAME_ABSNAME, SC_WID_UNO_ABSNAME, cppu::UnoType<OUString>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
+ { SC_UNONAME_ASIANVERT,ATTR_VERTICAL_ASIAN,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_BOTTBORDER,ATTR_BORDER, ::cppu::UnoType<table::BorderLine>::get(), 0, BOTTOM_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_BOTTBORDER2,ATTR_BORDER, ::cppu::UnoType<table::BorderLine2>::get(), 0, BOTTOM_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_CELLBACK, ATTR_BACKGROUND, cppu::UnoType<sal_Int32>::get(), 0, MID_BACK_COLOR },
+ { SC_UNONAME_CELLPRO, ATTR_PROTECTION, cppu::UnoType<util::CellProtection>::get(), 0, 0 },
+ { SC_UNONAME_CELLSTYL, SC_WID_UNO_CELLSTYL,cppu::UnoType<OUString>::get(), 0, 0 },
+ { SC_UNONAME_CCOLOR, ATTR_FONT_COLOR, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_COUTL, ATTR_FONT_CONTOUR, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CCROSS, ATTR_FONT_CROSSEDOUT,cppu::UnoType<bool>::get(), 0, MID_CROSSED_OUT },
+ { SC_UNONAME_CEMPHAS, ATTR_FONT_EMPHASISMARK,cppu::UnoType<sal_Int16>::get(), 0, MID_EMPHASIS },
+ { SC_UNONAME_CFONT, ATTR_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_FAMILY },
+ { SC_UNONAME_CFCHARS, ATTR_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_CHAR_SET },
+ { SC_UNO_CJK_CFCHARS, ATTR_CJK_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_CHAR_SET },
+ { SC_UNO_CTL_CFCHARS, ATTR_CTL_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_CHAR_SET },
+ { SC_UNONAME_CFFAMIL, ATTR_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_FAMILY },
+ { SC_UNO_CJK_CFFAMIL, ATTR_CJK_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_FAMILY },
+ { SC_UNO_CTL_CFFAMIL, ATTR_CTL_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_FAMILY },
+ { SC_UNONAME_CFNAME, ATTR_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_FAMILY_NAME },
+ { SC_UNO_CJK_CFNAME, ATTR_CJK_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_FAMILY_NAME },
+ { SC_UNO_CTL_CFNAME, ATTR_CTL_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_FAMILY_NAME },
+ { SC_UNONAME_CFPITCH, ATTR_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_PITCH },
+ { SC_UNO_CJK_CFPITCH, ATTR_CJK_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_PITCH },
+ { SC_UNO_CTL_CFPITCH, ATTR_CTL_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_PITCH },
+ { SC_UNONAME_CFSTYLE, ATTR_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_STYLE_NAME },
+ { SC_UNO_CJK_CFSTYLE, ATTR_CJK_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_STYLE_NAME },
+ { SC_UNO_CTL_CFSTYLE, ATTR_CTL_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_STYLE_NAME },
+ { SC_UNONAME_CHEIGHT, ATTR_FONT_HEIGHT, cppu::UnoType<float>::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS },
+ { SC_UNO_CJK_CHEIGHT, ATTR_CJK_FONT_HEIGHT,cppu::UnoType<float>::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS },
+ { SC_UNO_CTL_CHEIGHT, ATTR_CTL_FONT_HEIGHT,cppu::UnoType<float>::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS },
+ { SC_UNONAME_CLOCAL, ATTR_FONT_LANGUAGE, cppu::UnoType<lang::Locale>::get(), 0, MID_LANG_LOCALE },
+ { SC_UNO_CJK_CLOCAL, ATTR_CJK_FONT_LANGUAGE,cppu::UnoType<lang::Locale>::get(), 0, MID_LANG_LOCALE },
+ { SC_UNO_CTL_CLOCAL, ATTR_CTL_FONT_LANGUAGE,cppu::UnoType<lang::Locale>::get(), 0, MID_LANG_LOCALE },
+ { SC_UNONAME_COVER, ATTR_FONT_OVERLINE, cppu::UnoType<sal_Int16>::get(), 0, MID_TL_STYLE },
+ { SC_UNONAME_COVRLCOL, ATTR_FONT_OVERLINE, cppu::UnoType<sal_Int32>::get(), 0, MID_TL_COLOR },
+ { SC_UNONAME_COVRLHAS, ATTR_FONT_OVERLINE, cppu::UnoType<bool>::get(), 0, MID_TL_HASCOLOR },
+ { SC_UNONAME_CPOST, ATTR_FONT_POSTURE, cppu::UnoType<awt::FontSlant>::get(), 0, MID_POSTURE },
+ { SC_UNO_CJK_CPOST, ATTR_CJK_FONT_POSTURE,cppu::UnoType<awt::FontSlant>::get(), 0, MID_POSTURE },
+ { SC_UNO_CTL_CPOST, ATTR_CTL_FONT_POSTURE,cppu::UnoType<awt::FontSlant>::get(), 0, MID_POSTURE },
+ { SC_UNONAME_CRELIEF, ATTR_FONT_RELIEF, cppu::UnoType<sal_Int16>::get(), 0, MID_RELIEF },
+ { SC_UNONAME_CSHADD, ATTR_FONT_SHADOWED, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CSTRIKE, ATTR_FONT_CROSSEDOUT,cppu::UnoType<sal_Int16>::get(), 0, MID_CROSS_OUT },
+ { SC_UNONAME_CUNDER, ATTR_FONT_UNDERLINE,cppu::UnoType<sal_Int16>::get(), 0, MID_TL_STYLE },
+ { SC_UNONAME_CUNDLCOL, ATTR_FONT_UNDERLINE,cppu::UnoType<sal_Int32>::get(), 0, MID_TL_COLOR },
+ { SC_UNONAME_CUNDLHAS, ATTR_FONT_UNDERLINE,cppu::UnoType<bool>::get(), 0, MID_TL_HASCOLOR },
+ { SC_UNONAME_CWEIGHT, ATTR_FONT_WEIGHT, cppu::UnoType<float>::get(), 0, MID_WEIGHT },
+ { SC_UNO_CJK_CWEIGHT, ATTR_CJK_FONT_WEIGHT,cppu::UnoType<float>::get(), 0, MID_WEIGHT },
+ { SC_UNO_CTL_CWEIGHT, ATTR_CTL_FONT_WEIGHT,cppu::UnoType<float>::get(), 0, MID_WEIGHT },
+ { SC_UNONAME_CWORDMOD, ATTR_FONT_WORDLINE, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CHCOLHDR, SC_WID_UNO_CHCOLHDR,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CHROWHDR, SC_WID_UNO_CHROWHDR,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CONDFMT, SC_WID_UNO_CONDFMT, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
+ { SC_UNONAME_CONDLOC, SC_WID_UNO_CONDLOC, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
+ { SC_UNONAME_CONDXML, SC_WID_UNO_CONDXML, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
+ { SC_UNONAME_DIAGONAL_BLTR, ATTR_BORDER_BLTR, ::cppu::UnoType<table::BorderLine>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_DIAGONAL_BLTR2, ATTR_BORDER_BLTR, ::cppu::UnoType<table::BorderLine2>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_DIAGONAL_TLBR, ATTR_BORDER_TLBR, ::cppu::UnoType<table::BorderLine>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_DIAGONAL_TLBR2, ATTR_BORDER_TLBR, ::cppu::UnoType<table::BorderLine2>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_CELLHJUS, ATTR_HOR_JUSTIFY, cppu::UnoType<table::CellHoriJustify>::get(), 0, MID_HORJUST_HORJUST },
+ { SC_UNONAME_CELLHJUS_METHOD, ATTR_HOR_JUSTIFY_METHOD, ::cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_CELLTRAN, ATTR_BACKGROUND, cppu::UnoType<bool>::get(), 0, MID_GRAPHIC_TRANSPARENT },
+ { SC_UNONAME_WRAP, ATTR_LINEBREAK, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_LEFTBORDER,ATTR_BORDER, ::cppu::UnoType<table::BorderLine>::get(), 0, LEFT_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_LEFTBORDER2,ATTR_BORDER, ::cppu::UnoType<table::BorderLine2>::get(), 0, LEFT_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_NUMFMT, ATTR_VALUE_FORMAT, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_NUMRULES, SC_WID_UNO_NUMRULES,cppu::UnoType<container::XIndexReplace>::get(), 0, 0 },
+ { SC_UNONAME_CELLORI, ATTR_STACKED, cppu::UnoType<table::CellOrientation>::get(), 0, 0 },
+ { SC_UNONAME_PADJUST, ATTR_HOR_JUSTIFY, ::cppu::UnoType<sal_Int16>::get(), 0, MID_HORJUST_ADJUST },
+ { SC_UNONAME_PBMARGIN, ATTR_MARGIN, cppu::UnoType<sal_Int32>::get(), 0, MID_MARGIN_LO_MARGIN | CONVERT_TWIPS },
+ { SC_UNONAME_PINDENT, ATTR_INDENT, cppu::UnoType<sal_Int16>::get(), 0, 0 }, //! CONVERT_TWIPS
+ { SC_UNONAME_PISCHDIST,ATTR_SCRIPTSPACE, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_PISFORBID,ATTR_FORBIDDEN_RULES,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_PISHANG, ATTR_HANGPUNCTUATION,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_PISHYPHEN,ATTR_HYPHENATE, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_PLASTADJ, ATTR_HOR_JUSTIFY, ::cppu::UnoType<sal_Int16>::get(), 0, MID_HORJUST_ADJUST },
+ { SC_UNONAME_PLMARGIN, ATTR_MARGIN, cppu::UnoType<sal_Int32>::get(), 0, MID_MARGIN_L_MARGIN | CONVERT_TWIPS },
+ { SC_UNONAME_PRMARGIN, ATTR_MARGIN, cppu::UnoType<sal_Int32>::get(), 0, MID_MARGIN_R_MARGIN | CONVERT_TWIPS },
+ { SC_UNONAME_PTMARGIN, ATTR_MARGIN, cppu::UnoType<sal_Int32>::get(), 0, MID_MARGIN_UP_MARGIN | CONVERT_TWIPS },
+ { SC_UNONAME_POS, SC_WID_UNO_POS, cppu::UnoType<awt::Point>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
+ { SC_UNONAME_RIGHTBORDER,ATTR_BORDER, ::cppu::UnoType<table::BorderLine>::get(), 0, RIGHT_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_RIGHTBORDER2,ATTR_BORDER, ::cppu::UnoType<table::BorderLine2>::get(), 0, RIGHT_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_ROTANG, ATTR_ROTATE_VALUE, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_ROTREF, ATTR_ROTATE_MODE, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_SHADOW, ATTR_SHADOW, cppu::UnoType<table::ShadowFormat>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_SHRINK_TO_FIT, ATTR_SHRINKTOFIT, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_SIZE, SC_WID_UNO_SIZE, cppu::UnoType<awt::Size>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
+ { SC_UNONAME_TBLBORD, SC_WID_UNO_TBLBORD, cppu::UnoType<table::TableBorder>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_TBLBORD2, SC_WID_UNO_TBLBORD2, cppu::UnoType<table::TableBorder2>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_TOPBORDER,ATTR_BORDER, ::cppu::UnoType<table::BorderLine>::get(), 0, TOP_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_TOPBORDER2,ATTR_BORDER, ::cppu::UnoType<table::BorderLine2>::get(), 0, TOP_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_USERDEF, ATTR_USERDEF, cppu::UnoType<container::XNameContainer>::get(), 0, 0 },
+ { SC_UNONAME_VALIDAT, SC_WID_UNO_VALIDAT, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
+ { SC_UNONAME_VALILOC, SC_WID_UNO_VALILOC, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
+ { SC_UNONAME_VALIXML, SC_WID_UNO_VALIXML, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
+ { SC_UNONAME_CELLVJUS, ATTR_VER_JUSTIFY, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_CELLVJUS_METHOD, ATTR_VER_JUSTIFY_METHOD, ::cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_WRITING, ATTR_WRITINGDIR, cppu::UnoType<sal_Int16>::get(), 0, 0 },
+ { SC_UNONAME_FORMATID, SC_WID_UNO_FORMATID, cppu::UnoType<sal_uInt64>::get(), 0, 0 },
+ { u"", 0, css::uno::Type(), 0, 0 }
+ };
+ static SfxItemPropertySet aRangePropertySet( aRangePropertyMap_Impl );
+ return &aRangePropertySet;
+}
+
+// Cell contains entries from CellRange, plus its own entries
+// with Which-ID 0 (those are needed only for getPropertySetInfo).
+
+static const SfxItemPropertySet* lcl_GetCellPropertySet()
+{
+ static const SfxItemPropertyMapEntry aCellPropertyMap_Impl[] =
+ {
+ { SC_UNONAME_ABSNAME, SC_WID_UNO_ABSNAME, cppu::UnoType<OUString>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
+ { SC_UNONAME_ASIANVERT,ATTR_VERTICAL_ASIAN,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_BOTTBORDER,ATTR_BORDER, ::cppu::UnoType<table::BorderLine>::get(), 0, BOTTOM_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_BOTTBORDER2,ATTR_BORDER, ::cppu::UnoType<table::BorderLine2>::get(), 0, BOTTOM_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_CELLBACK, ATTR_BACKGROUND, cppu::UnoType<sal_Int32>::get(), 0, MID_BACK_COLOR },
+ { SC_UNONAME_CELLPRO, ATTR_PROTECTION, cppu::UnoType<util::CellProtection>::get(), 0, 0 },
+ { SC_UNONAME_CELLSTYL, SC_WID_UNO_CELLSTYL,cppu::UnoType<OUString>::get(), 0, 0 },
+ { SC_UNONAME_CCOLOR, ATTR_FONT_COLOR, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_COUTL, ATTR_FONT_CONTOUR, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CCROSS, ATTR_FONT_CROSSEDOUT,cppu::UnoType<bool>::get(), 0, MID_CROSSED_OUT },
+ { SC_UNONAME_CEMPHAS, ATTR_FONT_EMPHASISMARK,cppu::UnoType<sal_Int16>::get(), 0, MID_EMPHASIS },
+ { SC_UNONAME_CFONT, ATTR_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_FAMILY },
+ { SC_UNONAME_CFCHARS, ATTR_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_CHAR_SET },
+ { SC_UNO_CJK_CFCHARS, ATTR_CJK_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_CHAR_SET },
+ { SC_UNO_CTL_CFCHARS, ATTR_CTL_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_CHAR_SET },
+ { SC_UNONAME_CFFAMIL, ATTR_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_FAMILY },
+ { SC_UNO_CJK_CFFAMIL, ATTR_CJK_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_FAMILY },
+ { SC_UNO_CTL_CFFAMIL, ATTR_CTL_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_FAMILY },
+ { SC_UNONAME_CFNAME, ATTR_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_FAMILY_NAME },
+ { SC_UNO_CJK_CFNAME, ATTR_CJK_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_FAMILY_NAME },
+ { SC_UNO_CTL_CFNAME, ATTR_CTL_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_FAMILY_NAME },
+ { SC_UNONAME_CFPITCH, ATTR_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_PITCH },
+ { SC_UNO_CJK_CFPITCH, ATTR_CJK_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_PITCH },
+ { SC_UNO_CTL_CFPITCH, ATTR_CTL_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_PITCH },
+ { SC_UNONAME_CFSTYLE, ATTR_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_STYLE_NAME },
+ { SC_UNO_CJK_CFSTYLE, ATTR_CJK_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_STYLE_NAME },
+ { SC_UNO_CTL_CFSTYLE, ATTR_CTL_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_STYLE_NAME },
+ { SC_UNONAME_CHEIGHT, ATTR_FONT_HEIGHT, cppu::UnoType<float>::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS },
+ { SC_UNO_CJK_CHEIGHT, ATTR_CJK_FONT_HEIGHT,cppu::UnoType<float>::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS },
+ { SC_UNO_CTL_CHEIGHT, ATTR_CTL_FONT_HEIGHT,cppu::UnoType<float>::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS },
+ { SC_UNONAME_CLOCAL, ATTR_FONT_LANGUAGE, cppu::UnoType<lang::Locale>::get(), 0, MID_LANG_LOCALE },
+ { SC_UNO_CJK_CLOCAL, ATTR_CJK_FONT_LANGUAGE,cppu::UnoType<lang::Locale>::get(), 0, MID_LANG_LOCALE },
+ { SC_UNO_CTL_CLOCAL, ATTR_CTL_FONT_LANGUAGE,cppu::UnoType<lang::Locale>::get(), 0, MID_LANG_LOCALE },
+ { SC_UNONAME_COVER, ATTR_FONT_OVERLINE, cppu::UnoType<sal_Int16>::get(), 0, MID_TL_STYLE },
+ { SC_UNONAME_COVRLCOL, ATTR_FONT_OVERLINE, cppu::UnoType<sal_Int32>::get(), 0, MID_TL_COLOR },
+ { SC_UNONAME_COVRLHAS, ATTR_FONT_OVERLINE, cppu::UnoType<bool>::get(), 0, MID_TL_HASCOLOR },
+ { SC_UNONAME_CPOST, ATTR_FONT_POSTURE, cppu::UnoType<awt::FontSlant>::get(), 0, MID_POSTURE },
+ { SC_UNO_CJK_CPOST, ATTR_CJK_FONT_POSTURE,cppu::UnoType<awt::FontSlant>::get(), 0, MID_POSTURE },
+ { SC_UNO_CTL_CPOST, ATTR_CTL_FONT_POSTURE,cppu::UnoType<awt::FontSlant>::get(), 0, MID_POSTURE },
+ { SC_UNONAME_CRELIEF, ATTR_FONT_RELIEF, cppu::UnoType<sal_Int16>::get(), 0, MID_RELIEF },
+ { SC_UNONAME_CSHADD, ATTR_FONT_SHADOWED, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CSTRIKE, ATTR_FONT_CROSSEDOUT,cppu::UnoType<sal_Int16>::get(), 0, MID_CROSS_OUT },
+ { SC_UNONAME_CUNDER, ATTR_FONT_UNDERLINE,cppu::UnoType<sal_Int16>::get(), 0, MID_TL_STYLE },
+ { SC_UNONAME_CUNDLCOL, ATTR_FONT_UNDERLINE,cppu::UnoType<sal_Int32>::get(), 0, MID_TL_COLOR },
+ { SC_UNONAME_CUNDLHAS, ATTR_FONT_UNDERLINE,cppu::UnoType<bool>::get(), 0, MID_TL_HASCOLOR },
+ { SC_UNONAME_CWEIGHT, ATTR_FONT_WEIGHT, cppu::UnoType<float>::get(), 0, MID_WEIGHT },
+ { SC_UNO_CJK_CWEIGHT, ATTR_CJK_FONT_WEIGHT,cppu::UnoType<float>::get(), 0, MID_WEIGHT },
+ { SC_UNO_CTL_CWEIGHT, ATTR_CTL_FONT_WEIGHT,cppu::UnoType<float>::get(), 0, MID_WEIGHT },
+ { SC_UNONAME_CWORDMOD, ATTR_FONT_WORDLINE, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CHCOLHDR, SC_WID_UNO_CHCOLHDR,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CHROWHDR, SC_WID_UNO_CHROWHDR,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CONDFMT, SC_WID_UNO_CONDFMT, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
+ { SC_UNONAME_CONDLOC, SC_WID_UNO_CONDLOC, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
+ { SC_UNONAME_CONDXML, SC_WID_UNO_CONDXML, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
+ { SC_UNONAME_DIAGONAL_BLTR, ATTR_BORDER_BLTR, ::cppu::UnoType<table::BorderLine>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_DIAGONAL_BLTR2, ATTR_BORDER_BLTR, ::cppu::UnoType<table::BorderLine2>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_DIAGONAL_TLBR, ATTR_BORDER_TLBR, ::cppu::UnoType<table::BorderLine>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_DIAGONAL_TLBR2, ATTR_BORDER_TLBR, ::cppu::UnoType<table::BorderLine2>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_FORMLOC, SC_WID_UNO_FORMLOC, cppu::UnoType<OUString>::get(), 0, 0 },
+ { SC_UNONAME_FORMRT, SC_WID_UNO_FORMRT, cppu::UnoType<table::CellContentType>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
+ { SC_UNONAME_CELLCONTENTTYPE, SC_WID_UNO_CELLCONTENTTYPE, cppu::UnoType<table::CellContentType>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
+ { SC_UNONAME_FORMRT2, SC_WID_UNO_FORMRT2, cppu::UnoType<sal_Int32>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
+ { SC_UNONAME_CELLHJUS, ATTR_HOR_JUSTIFY, cppu::UnoType<table::CellHoriJustify>::get(), 0, MID_HORJUST_HORJUST },
+ { SC_UNONAME_CELLHJUS_METHOD, ATTR_HOR_JUSTIFY_METHOD, ::cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_CELLTRAN, ATTR_BACKGROUND, cppu::UnoType<bool>::get(), 0, MID_GRAPHIC_TRANSPARENT },
+ { SC_UNONAME_WRAP, ATTR_LINEBREAK, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_LEFTBORDER,ATTR_BORDER, ::cppu::UnoType<table::BorderLine>::get(), 0, LEFT_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_LEFTBORDER2,ATTR_BORDER, ::cppu::UnoType<table::BorderLine2>::get(), 0, LEFT_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_NUMFMT, ATTR_VALUE_FORMAT, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_NUMRULES, SC_WID_UNO_NUMRULES,cppu::UnoType<container::XIndexReplace>::get(), 0, 0 },
+ { SC_UNONAME_CELLORI, ATTR_STACKED, cppu::UnoType<table::CellOrientation>::get(), 0, 0 },
+ { SC_UNONAME_PADJUST, ATTR_HOR_JUSTIFY, ::cppu::UnoType<sal_Int16>::get(), 0, MID_HORJUST_ADJUST },
+ { SC_UNONAME_PBMARGIN, ATTR_MARGIN, cppu::UnoType<sal_Int32>::get(), 0, MID_MARGIN_LO_MARGIN | CONVERT_TWIPS },
+ { SC_UNONAME_PINDENT, ATTR_INDENT, cppu::UnoType<sal_Int16>::get(), 0, 0 }, //! CONVERT_TWIPS
+ { SC_UNONAME_PISCHDIST,ATTR_SCRIPTSPACE, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_PISFORBID,ATTR_FORBIDDEN_RULES,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_PISHANG, ATTR_HANGPUNCTUATION,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_PISHYPHEN,ATTR_HYPHENATE, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_PLASTADJ, ATTR_HOR_JUSTIFY, ::cppu::UnoType<sal_Int16>::get(), 0, MID_HORJUST_ADJUST },
+ { SC_UNONAME_PLMARGIN, ATTR_MARGIN, cppu::UnoType<sal_Int32>::get(), 0, MID_MARGIN_L_MARGIN | CONVERT_TWIPS },
+ { SC_UNONAME_PRMARGIN, ATTR_MARGIN, cppu::UnoType<sal_Int32>::get(), 0, MID_MARGIN_R_MARGIN | CONVERT_TWIPS },
+ { SC_UNONAME_PTMARGIN, ATTR_MARGIN, cppu::UnoType<sal_Int32>::get(), 0, MID_MARGIN_UP_MARGIN | CONVERT_TWIPS },
+ { SC_UNONAME_POS, SC_WID_UNO_POS, cppu::UnoType<awt::Point>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
+ { SC_UNONAME_RIGHTBORDER,ATTR_BORDER, ::cppu::UnoType<table::BorderLine>::get(), 0, RIGHT_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_RIGHTBORDER2,ATTR_BORDER, ::cppu::UnoType<table::BorderLine2>::get(), 0, RIGHT_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_ROTANG, ATTR_ROTATE_VALUE, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_ROTREF, ATTR_ROTATE_MODE, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_SHADOW, ATTR_SHADOW, cppu::UnoType<table::ShadowFormat>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_SHRINK_TO_FIT, ATTR_SHRINKTOFIT, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_SIZE, SC_WID_UNO_SIZE, cppu::UnoType<awt::Size>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
+ { SC_UNONAME_TBLBORD, SC_WID_UNO_TBLBORD, cppu::UnoType<table::TableBorder>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_TBLBORD2, SC_WID_UNO_TBLBORD2, cppu::UnoType<table::TableBorder2>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_TOPBORDER,ATTR_BORDER, ::cppu::UnoType<table::BorderLine>::get(), 0, TOP_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_TOPBORDER2,ATTR_BORDER, ::cppu::UnoType<table::BorderLine2>::get(), 0, TOP_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_USERDEF, ATTR_USERDEF, cppu::UnoType<container::XNameContainer>::get(), 0, 0 },
+ { SC_UNONAME_VALIDAT, SC_WID_UNO_VALIDAT, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
+ { SC_UNONAME_VALILOC, SC_WID_UNO_VALILOC, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
+ { SC_UNONAME_VALIXML, SC_WID_UNO_VALIXML, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
+ { SC_UNONAME_CELLVJUS, ATTR_VER_JUSTIFY, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_CELLVJUS_METHOD, ATTR_VER_JUSTIFY_METHOD, ::cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_WRITING, ATTR_WRITINGDIR, cppu::UnoType<sal_Int16>::get(), 0, 0 },
+ { UNO_NAME_EDIT_CHAR_ESCAPEMENT, EE_CHAR_ESCAPEMENT, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_HYPERLINK, ATTR_HYPERLINK, cppu::UnoType<OUString>::get(), 0, 0 },
+ { SC_UNONAME_FORMATID, SC_WID_UNO_FORMATID, cppu::UnoType<sal_uInt64>::get(), 0, 0 },
+ { u"", 0, css::uno::Type(), 0, 0 }
+ };
+ static SfxItemPropertySet aCellPropertySet( aCellPropertyMap_Impl );
+ return &aCellPropertySet;
+}
+
+// Column and Row contain all entries from CellRange, plus its own entries
+// with Which-ID 0 (those are needed only for getPropertySetInfo).
+
+static const SfxItemPropertySet* lcl_GetColumnPropertySet()
+{
+ static const SfxItemPropertyMapEntry aColumnPropertyMap_Impl[] =
+ {
+ { SC_UNONAME_ABSNAME, SC_WID_UNO_ABSNAME, cppu::UnoType<OUString>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
+ { SC_UNONAME_ASIANVERT,ATTR_VERTICAL_ASIAN,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_BOTTBORDER,ATTR_BORDER, ::cppu::UnoType<table::BorderLine>::get(), 0, BOTTOM_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_BOTTBORDER2,ATTR_BORDER, ::cppu::UnoType<table::BorderLine2>::get(), 0, BOTTOM_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_CELLBACK, ATTR_BACKGROUND, cppu::UnoType<sal_Int32>::get(), 0, MID_BACK_COLOR },
+ { SC_UNONAME_CELLPRO, ATTR_PROTECTION, cppu::UnoType<util::CellProtection>::get(), 0, 0 },
+ { SC_UNONAME_CELLSTYL, SC_WID_UNO_CELLSTYL,cppu::UnoType<OUString>::get(), 0, 0 },
+ { SC_UNONAME_CCOLOR, ATTR_FONT_COLOR, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_COUTL, ATTR_FONT_CONTOUR, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CCROSS, ATTR_FONT_CROSSEDOUT,cppu::UnoType<bool>::get(), 0, MID_CROSSED_OUT },
+ { SC_UNONAME_CEMPHAS, ATTR_FONT_EMPHASISMARK,cppu::UnoType<sal_Int16>::get(), 0, MID_EMPHASIS },
+ { SC_UNONAME_CFONT, ATTR_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_FAMILY },
+ { SC_UNONAME_CFCHARS, ATTR_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_CHAR_SET },
+ { SC_UNO_CJK_CFCHARS, ATTR_CJK_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_CHAR_SET },
+ { SC_UNO_CTL_CFCHARS, ATTR_CTL_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_CHAR_SET },
+ { SC_UNONAME_CFFAMIL, ATTR_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_FAMILY },
+ { SC_UNO_CJK_CFFAMIL, ATTR_CJK_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_FAMILY },
+ { SC_UNO_CTL_CFFAMIL, ATTR_CTL_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_FAMILY },
+ { SC_UNONAME_CFNAME, ATTR_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_FAMILY_NAME },
+ { SC_UNO_CJK_CFNAME, ATTR_CJK_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_FAMILY_NAME },
+ { SC_UNO_CTL_CFNAME, ATTR_CTL_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_FAMILY_NAME },
+ { SC_UNONAME_CFPITCH, ATTR_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_PITCH },
+ { SC_UNO_CJK_CFPITCH, ATTR_CJK_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_PITCH },
+ { SC_UNO_CTL_CFPITCH, ATTR_CTL_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_PITCH },
+ { SC_UNONAME_CFSTYLE, ATTR_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_STYLE_NAME },
+ { SC_UNO_CJK_CFSTYLE, ATTR_CJK_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_STYLE_NAME },
+ { SC_UNO_CTL_CFSTYLE, ATTR_CTL_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_STYLE_NAME },
+ { SC_UNONAME_CHEIGHT, ATTR_FONT_HEIGHT, cppu::UnoType<float>::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS },
+ { SC_UNO_CJK_CHEIGHT, ATTR_CJK_FONT_HEIGHT,cppu::UnoType<float>::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS },
+ { SC_UNO_CTL_CHEIGHT, ATTR_CTL_FONT_HEIGHT,cppu::UnoType<float>::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS },
+ { SC_UNONAME_CLOCAL, ATTR_FONT_LANGUAGE, cppu::UnoType<lang::Locale>::get(), 0, MID_LANG_LOCALE },
+ { SC_UNO_CJK_CLOCAL, ATTR_CJK_FONT_LANGUAGE,cppu::UnoType<lang::Locale>::get(), 0, MID_LANG_LOCALE },
+ { SC_UNO_CTL_CLOCAL, ATTR_CTL_FONT_LANGUAGE,cppu::UnoType<lang::Locale>::get(), 0, MID_LANG_LOCALE },
+ { SC_UNONAME_COVER, ATTR_FONT_OVERLINE, cppu::UnoType<sal_Int16>::get(), 0, MID_TL_STYLE },
+ { SC_UNONAME_COVRLCOL, ATTR_FONT_OVERLINE, cppu::UnoType<sal_Int32>::get(), 0, MID_TL_COLOR },
+ { SC_UNONAME_COVRLHAS, ATTR_FONT_OVERLINE, cppu::UnoType<bool>::get(), 0, MID_TL_HASCOLOR },
+ { SC_UNONAME_CPOST, ATTR_FONT_POSTURE, cppu::UnoType<awt::FontSlant>::get(), 0, MID_POSTURE },
+ { SC_UNO_CJK_CPOST, ATTR_CJK_FONT_POSTURE,cppu::UnoType<awt::FontSlant>::get(), 0, MID_POSTURE },
+ { SC_UNO_CTL_CPOST, ATTR_CTL_FONT_POSTURE,cppu::UnoType<awt::FontSlant>::get(), 0, MID_POSTURE },
+ { SC_UNONAME_CRELIEF, ATTR_FONT_RELIEF, cppu::UnoType<sal_Int16>::get(), 0, MID_RELIEF },
+ { SC_UNONAME_CSHADD, ATTR_FONT_SHADOWED, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CSTRIKE, ATTR_FONT_CROSSEDOUT,cppu::UnoType<sal_Int16>::get(), 0, MID_CROSS_OUT },
+ { SC_UNONAME_CUNDER, ATTR_FONT_UNDERLINE,cppu::UnoType<sal_Int16>::get(), 0, MID_TL_STYLE },
+ { SC_UNONAME_CUNDLCOL, ATTR_FONT_UNDERLINE,cppu::UnoType<sal_Int32>::get(), 0, MID_TL_COLOR },
+ { SC_UNONAME_CUNDLHAS, ATTR_FONT_UNDERLINE,cppu::UnoType<bool>::get(), 0, MID_TL_HASCOLOR },
+ { SC_UNONAME_CWEIGHT, ATTR_FONT_WEIGHT, cppu::UnoType<float>::get(), 0, MID_WEIGHT },
+ { SC_UNO_CJK_CWEIGHT, ATTR_CJK_FONT_WEIGHT,cppu::UnoType<float>::get(), 0, MID_WEIGHT },
+ { SC_UNO_CTL_CWEIGHT, ATTR_CTL_FONT_WEIGHT,cppu::UnoType<float>::get(), 0, MID_WEIGHT },
+ { SC_UNONAME_CWORDMOD, ATTR_FONT_WORDLINE, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CHCOLHDR, SC_WID_UNO_CHCOLHDR,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CHROWHDR, SC_WID_UNO_CHROWHDR,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CONDFMT, SC_WID_UNO_CONDFMT, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
+ { SC_UNONAME_CONDLOC, SC_WID_UNO_CONDLOC, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
+ { SC_UNONAME_CONDXML, SC_WID_UNO_CONDXML, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
+ { SC_UNONAME_DIAGONAL_BLTR, ATTR_BORDER_BLTR, ::cppu::UnoType<table::BorderLine>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_DIAGONAL_BLTR2, ATTR_BORDER_BLTR, ::cppu::UnoType<table::BorderLine2>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_DIAGONAL_TLBR, ATTR_BORDER_TLBR, ::cppu::UnoType<table::BorderLine>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_DIAGONAL_TLBR2, ATTR_BORDER_TLBR, ::cppu::UnoType<table::BorderLine2>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_CELLHJUS, ATTR_HOR_JUSTIFY, cppu::UnoType<table::CellHoriJustify>::get(), 0, MID_HORJUST_HORJUST },
+ { SC_UNONAME_CELLHJUS_METHOD, ATTR_HOR_JUSTIFY_METHOD, ::cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_CELLTRAN, ATTR_BACKGROUND, cppu::UnoType<bool>::get(), 0, MID_GRAPHIC_TRANSPARENT },
+ { SC_UNONAME_MANPAGE, SC_WID_UNO_MANPAGE, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_NEWPAGE, SC_WID_UNO_NEWPAGE, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_WRAP, ATTR_LINEBREAK, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CELLVIS, SC_WID_UNO_CELLVIS, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_LEFTBORDER,ATTR_BORDER, ::cppu::UnoType<table::BorderLine>::get(), 0, LEFT_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_LEFTBORDER2,ATTR_BORDER, ::cppu::UnoType<table::BorderLine2>::get(), 0, LEFT_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_NUMFMT, ATTR_VALUE_FORMAT, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_NUMRULES, SC_WID_UNO_NUMRULES,cppu::UnoType<container::XIndexReplace>::get(), 0, 0 },
+ { SC_UNONAME_OWIDTH, SC_WID_UNO_OWIDTH, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CELLORI, ATTR_STACKED, cppu::UnoType<table::CellOrientation>::get(), 0, 0 },
+ { SC_UNONAME_PADJUST, ATTR_HOR_JUSTIFY, ::cppu::UnoType<sal_Int16>::get(), 0, MID_HORJUST_ADJUST },
+ { SC_UNONAME_PBMARGIN, ATTR_MARGIN, cppu::UnoType<sal_Int32>::get(), 0, MID_MARGIN_LO_MARGIN | CONVERT_TWIPS },
+ { SC_UNONAME_PINDENT, ATTR_INDENT, cppu::UnoType<sal_Int16>::get(), 0, 0 }, //! CONVERT_TWIPS
+ { SC_UNONAME_PISCHDIST,ATTR_SCRIPTSPACE, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_PISFORBID,ATTR_FORBIDDEN_RULES,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_PISHANG, ATTR_HANGPUNCTUATION,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_PISHYPHEN,ATTR_HYPHENATE, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_PLASTADJ, ATTR_HOR_JUSTIFY, ::cppu::UnoType<sal_Int16>::get(), 0, MID_HORJUST_ADJUST },
+ { SC_UNONAME_PLMARGIN, ATTR_MARGIN, cppu::UnoType<sal_Int32>::get(), 0, MID_MARGIN_L_MARGIN | CONVERT_TWIPS },
+ { SC_UNONAME_PRMARGIN, ATTR_MARGIN, cppu::UnoType<sal_Int32>::get(), 0, MID_MARGIN_R_MARGIN | CONVERT_TWIPS },
+ { SC_UNONAME_PTMARGIN, ATTR_MARGIN, cppu::UnoType<sal_Int32>::get(), 0, MID_MARGIN_UP_MARGIN | CONVERT_TWIPS },
+ { SC_UNONAME_POS, SC_WID_UNO_POS, cppu::UnoType<awt::Point>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
+ { SC_UNONAME_RIGHTBORDER,ATTR_BORDER, ::cppu::UnoType<table::BorderLine>::get(), 0, RIGHT_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_RIGHTBORDER2,ATTR_BORDER, ::cppu::UnoType<table::BorderLine2>::get(), 0, RIGHT_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_ROTANG, ATTR_ROTATE_VALUE, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_ROTREF, ATTR_ROTATE_MODE, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_SHADOW, ATTR_SHADOW, cppu::UnoType<table::ShadowFormat>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_SHRINK_TO_FIT, ATTR_SHRINKTOFIT, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_SIZE, SC_WID_UNO_SIZE, cppu::UnoType<awt::Size>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
+ { SC_UNONAME_TBLBORD, SC_WID_UNO_TBLBORD, cppu::UnoType<table::TableBorder>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_TBLBORD2, SC_WID_UNO_TBLBORD2, cppu::UnoType<table::TableBorder2>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_TOPBORDER,ATTR_BORDER, ::cppu::UnoType<table::BorderLine>::get(), 0, TOP_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_TOPBORDER2,ATTR_BORDER, ::cppu::UnoType<table::BorderLine2>::get(), 0, TOP_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_USERDEF, ATTR_USERDEF, cppu::UnoType<container::XNameContainer>::get(), 0, 0 },
+ { SC_UNONAME_VALIDAT, SC_WID_UNO_VALIDAT, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
+ { SC_UNONAME_VALILOC, SC_WID_UNO_VALILOC, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
+ { SC_UNONAME_VALIXML, SC_WID_UNO_VALIXML, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
+ { SC_UNONAME_CELLVJUS, ATTR_VER_JUSTIFY, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_CELLVJUS_METHOD, ATTR_VER_JUSTIFY_METHOD, ::cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_CELLWID, SC_WID_UNO_CELLWID, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_WRITING, ATTR_WRITINGDIR, cppu::UnoType<sal_Int16>::get(), 0, 0 },
+ { u"", 0, css::uno::Type(), 0, 0 }
+ };
+ static SfxItemPropertySet aColumnPropertySet( aColumnPropertyMap_Impl );
+ return &aColumnPropertySet;
+}
+
+static const SfxItemPropertySet* lcl_GetRowPropertySet()
+{
+ static const SfxItemPropertyMapEntry aRowPropertyMap_Impl[] =
+ {
+ { SC_UNONAME_ABSNAME, SC_WID_UNO_ABSNAME, cppu::UnoType<OUString>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
+ { SC_UNONAME_ASIANVERT,ATTR_VERTICAL_ASIAN,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_BOTTBORDER,ATTR_BORDER, ::cppu::UnoType<table::BorderLine>::get(), 0, BOTTOM_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_BOTTBORDER2,ATTR_BORDER, ::cppu::UnoType<table::BorderLine2>::get(), 0, BOTTOM_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_CELLBACK, ATTR_BACKGROUND, cppu::UnoType<sal_Int32>::get(), 0, MID_BACK_COLOR },
+ { SC_UNONAME_CELLPRO, ATTR_PROTECTION, cppu::UnoType<util::CellProtection>::get(), 0, 0 },
+ { SC_UNONAME_CELLSTYL, SC_WID_UNO_CELLSTYL,cppu::UnoType<OUString>::get(), 0, 0 },
+ { SC_UNONAME_CCOLOR, ATTR_FONT_COLOR, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_COUTL, ATTR_FONT_CONTOUR, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CCROSS, ATTR_FONT_CROSSEDOUT,cppu::UnoType<bool>::get(), 0, MID_CROSSED_OUT },
+ { SC_UNONAME_CEMPHAS, ATTR_FONT_EMPHASISMARK,cppu::UnoType<sal_Int16>::get(), 0, MID_EMPHASIS },
+ { SC_UNONAME_CFONT, ATTR_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_FAMILY },
+ { SC_UNONAME_CFCHARS, ATTR_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_CHAR_SET },
+ { SC_UNO_CJK_CFCHARS, ATTR_CJK_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_CHAR_SET },
+ { SC_UNO_CTL_CFCHARS, ATTR_CTL_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_CHAR_SET },
+ { SC_UNONAME_CFFAMIL, ATTR_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_FAMILY },
+ { SC_UNO_CJK_CFFAMIL, ATTR_CJK_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_FAMILY },
+ { SC_UNO_CTL_CFFAMIL, ATTR_CTL_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_FAMILY },
+ { SC_UNONAME_CFNAME, ATTR_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_FAMILY_NAME },
+ { SC_UNO_CJK_CFNAME, ATTR_CJK_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_FAMILY_NAME },
+ { SC_UNO_CTL_CFNAME, ATTR_CTL_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_FAMILY_NAME },
+ { SC_UNONAME_CFPITCH, ATTR_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_PITCH },
+ { SC_UNO_CJK_CFPITCH, ATTR_CJK_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_PITCH },
+ { SC_UNO_CTL_CFPITCH, ATTR_CTL_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_PITCH },
+ { SC_UNONAME_CFSTYLE, ATTR_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_STYLE_NAME },
+ { SC_UNO_CJK_CFSTYLE, ATTR_CJK_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_STYLE_NAME },
+ { SC_UNO_CTL_CFSTYLE, ATTR_CTL_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_STYLE_NAME },
+ { SC_UNONAME_CHEIGHT, ATTR_FONT_HEIGHT, cppu::UnoType<float>::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS },
+ { SC_UNO_CJK_CHEIGHT, ATTR_CJK_FONT_HEIGHT,cppu::UnoType<float>::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS },
+ { SC_UNO_CTL_CHEIGHT, ATTR_CTL_FONT_HEIGHT,cppu::UnoType<float>::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS },
+ { SC_UNONAME_CLOCAL, ATTR_FONT_LANGUAGE, cppu::UnoType<lang::Locale>::get(), 0, MID_LANG_LOCALE },
+ { SC_UNO_CJK_CLOCAL, ATTR_CJK_FONT_LANGUAGE,cppu::UnoType<lang::Locale>::get(), 0, MID_LANG_LOCALE },
+ { SC_UNO_CTL_CLOCAL, ATTR_CTL_FONT_LANGUAGE,cppu::UnoType<lang::Locale>::get(), 0, MID_LANG_LOCALE },
+ { SC_UNONAME_COVER, ATTR_FONT_OVERLINE, cppu::UnoType<sal_Int16>::get(), 0, MID_TL_STYLE },
+ { SC_UNONAME_COVRLCOL, ATTR_FONT_OVERLINE, cppu::UnoType<sal_Int32>::get(), 0, MID_TL_COLOR },
+ { SC_UNONAME_COVRLHAS, ATTR_FONT_OVERLINE, cppu::UnoType<bool>::get(), 0, MID_TL_HASCOLOR },
+ { SC_UNONAME_CPOST, ATTR_FONT_POSTURE, cppu::UnoType<awt::FontSlant>::get(), 0, MID_POSTURE },
+ { SC_UNO_CJK_CPOST, ATTR_CJK_FONT_POSTURE,cppu::UnoType<awt::FontSlant>::get(), 0, MID_POSTURE },
+ { SC_UNO_CTL_CPOST, ATTR_CTL_FONT_POSTURE,cppu::UnoType<awt::FontSlant>::get(), 0, MID_POSTURE },
+ { SC_UNONAME_CRELIEF, ATTR_FONT_RELIEF, cppu::UnoType<sal_Int16>::get(), 0, MID_RELIEF },
+ { SC_UNONAME_CSHADD, ATTR_FONT_SHADOWED, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CSTRIKE, ATTR_FONT_CROSSEDOUT,cppu::UnoType<sal_Int16>::get(), 0, MID_CROSS_OUT },
+ { SC_UNONAME_CUNDER, ATTR_FONT_UNDERLINE,cppu::UnoType<sal_Int16>::get(), 0, MID_TL_STYLE },
+ { SC_UNONAME_CUNDLCOL, ATTR_FONT_UNDERLINE,cppu::UnoType<sal_Int32>::get(), 0, MID_TL_COLOR },
+ { SC_UNONAME_CUNDLHAS, ATTR_FONT_UNDERLINE,cppu::UnoType<bool>::get(), 0, MID_TL_HASCOLOR },
+ { SC_UNONAME_CWEIGHT, ATTR_FONT_WEIGHT, cppu::UnoType<float>::get(), 0, MID_WEIGHT },
+ { SC_UNO_CJK_CWEIGHT, ATTR_CJK_FONT_WEIGHT,cppu::UnoType<float>::get(), 0, MID_WEIGHT },
+ { SC_UNO_CTL_CWEIGHT, ATTR_CTL_FONT_WEIGHT,cppu::UnoType<float>::get(), 0, MID_WEIGHT },
+ { SC_UNONAME_CWORDMOD, ATTR_FONT_WORDLINE, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CHCOLHDR, SC_WID_UNO_CHCOLHDR,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CHROWHDR, SC_WID_UNO_CHROWHDR,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CONDFMT, SC_WID_UNO_CONDFMT, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
+ { SC_UNONAME_CONDLOC, SC_WID_UNO_CONDLOC, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
+ { SC_UNONAME_CONDXML, SC_WID_UNO_CONDXML, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
+ { SC_UNONAME_DIAGONAL_BLTR, ATTR_BORDER_BLTR, ::cppu::UnoType<table::BorderLine>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_DIAGONAL_BLTR2, ATTR_BORDER_BLTR, ::cppu::UnoType<table::BorderLine2>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_DIAGONAL_TLBR, ATTR_BORDER_TLBR, ::cppu::UnoType<table::BorderLine>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_DIAGONAL_TLBR2, ATTR_BORDER_TLBR, ::cppu::UnoType<table::BorderLine2>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_CELLHGT, SC_WID_UNO_CELLHGT, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_CELLHJUS, ATTR_HOR_JUSTIFY, cppu::UnoType<table::CellHoriJustify>::get(), 0, MID_HORJUST_HORJUST },
+ { SC_UNONAME_CELLHJUS_METHOD, ATTR_HOR_JUSTIFY_METHOD, ::cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_CELLTRAN, ATTR_BACKGROUND, cppu::UnoType<bool>::get(), 0, MID_GRAPHIC_TRANSPARENT },
+ { SC_UNONAME_CELLFILT, SC_WID_UNO_CELLFILT,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_MANPAGE, SC_WID_UNO_MANPAGE, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_NEWPAGE, SC_WID_UNO_NEWPAGE, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_WRAP, ATTR_LINEBREAK, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CELLVIS, SC_WID_UNO_CELLVIS, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_LEFTBORDER,ATTR_BORDER, ::cppu::UnoType<table::BorderLine>::get(), 0, LEFT_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_LEFTBORDER2,ATTR_BORDER, ::cppu::UnoType<table::BorderLine2>::get(), 0, LEFT_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_NUMFMT, ATTR_VALUE_FORMAT, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_NUMRULES, SC_WID_UNO_NUMRULES,cppu::UnoType<container::XIndexReplace>::get(), 0, 0 },
+ { SC_UNONAME_OHEIGHT, SC_WID_UNO_OHEIGHT, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CELLORI, ATTR_STACKED, cppu::UnoType<table::CellOrientation>::get(), 0, 0 },
+ { SC_UNONAME_PADJUST, ATTR_HOR_JUSTIFY, ::cppu::UnoType<sal_Int16>::get(), 0, MID_HORJUST_ADJUST },
+ { SC_UNONAME_PBMARGIN, ATTR_MARGIN, cppu::UnoType<sal_Int32>::get(), 0, MID_MARGIN_LO_MARGIN | CONVERT_TWIPS },
+ { SC_UNONAME_PINDENT, ATTR_INDENT, cppu::UnoType<sal_Int16>::get(), 0, 0 }, //! CONVERT_TWIPS
+ { SC_UNONAME_PISCHDIST,ATTR_SCRIPTSPACE, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_PISFORBID,ATTR_FORBIDDEN_RULES,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_PISHANG, ATTR_HANGPUNCTUATION,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_PISHYPHEN,ATTR_HYPHENATE, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_PLASTADJ, ATTR_HOR_JUSTIFY, ::cppu::UnoType<sal_Int16>::get(), 0, MID_HORJUST_ADJUST },
+ { SC_UNONAME_PLMARGIN, ATTR_MARGIN, cppu::UnoType<sal_Int32>::get(), 0, MID_MARGIN_L_MARGIN | CONVERT_TWIPS },
+ { SC_UNONAME_PRMARGIN, ATTR_MARGIN, cppu::UnoType<sal_Int32>::get(), 0, MID_MARGIN_R_MARGIN | CONVERT_TWIPS },
+ { SC_UNONAME_PTMARGIN, ATTR_MARGIN, cppu::UnoType<sal_Int32>::get(), 0, MID_MARGIN_UP_MARGIN | CONVERT_TWIPS },
+ { SC_UNONAME_POS, SC_WID_UNO_POS, cppu::UnoType<awt::Point>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
+ { SC_UNONAME_RIGHTBORDER,ATTR_BORDER, ::cppu::UnoType<table::BorderLine>::get(), 0, RIGHT_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_RIGHTBORDER2,ATTR_BORDER, ::cppu::UnoType<table::BorderLine2>::get(), 0, RIGHT_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_ROTANG, ATTR_ROTATE_VALUE, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_ROTREF, ATTR_ROTATE_MODE, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_SHADOW, ATTR_SHADOW, cppu::UnoType<table::ShadowFormat>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_SHRINK_TO_FIT, ATTR_SHRINKTOFIT, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_SIZE, SC_WID_UNO_SIZE, cppu::UnoType<awt::Size>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
+ { SC_UNONAME_TBLBORD, SC_WID_UNO_TBLBORD, cppu::UnoType<table::TableBorder>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_TBLBORD2, SC_WID_UNO_TBLBORD2, cppu::UnoType<table::TableBorder2>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_TOPBORDER,ATTR_BORDER, ::cppu::UnoType<table::BorderLine>::get(), 0, TOP_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_TOPBORDER2,ATTR_BORDER, ::cppu::UnoType<table::BorderLine2>::get(), 0, TOP_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_USERDEF, ATTR_USERDEF, cppu::UnoType<container::XNameContainer>::get(), 0, 0 },
+ { SC_UNONAME_VALIDAT, SC_WID_UNO_VALIDAT, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
+ { SC_UNONAME_VALILOC, SC_WID_UNO_VALILOC, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
+ { SC_UNONAME_VALIXML, SC_WID_UNO_VALIXML, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
+ { SC_UNONAME_CELLVJUS, ATTR_VER_JUSTIFY, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_CELLVJUS_METHOD, ATTR_VER_JUSTIFY_METHOD, ::cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_WRITING, ATTR_WRITINGDIR, cppu::UnoType<sal_Int16>::get(), 0, 0 },
+ { u"", 0, css::uno::Type(), 0, 0 }
+ };
+ static SfxItemPropertySet aRowPropertySet( aRowPropertyMap_Impl );
+ return &aRowPropertySet;
+}
+
+static const SfxItemPropertySet* lcl_GetSheetPropertySet()
+{
+ static const SfxItemPropertyMapEntry aSheetPropertyMap_Impl[] =
+ {
+ { SC_UNONAME_ABSNAME, SC_WID_UNO_ABSNAME, cppu::UnoType<OUString>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
+ { SC_UNONAME_ASIANVERT,ATTR_VERTICAL_ASIAN,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_AUTOPRINT,SC_WID_UNO_AUTOPRINT,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_BORDCOL, SC_WID_UNO_BORDCOL, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_BOTTBORDER,ATTR_BORDER, ::cppu::UnoType<table::BorderLine>::get(), 0, BOTTOM_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_BOTTBORDER2,ATTR_BORDER, ::cppu::UnoType<table::BorderLine2>::get(), 0, BOTTOM_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_CELLBACK, ATTR_BACKGROUND, cppu::UnoType<sal_Int32>::get(), 0, MID_BACK_COLOR },
+ { SC_UNONAME_CELLPRO, ATTR_PROTECTION, cppu::UnoType<util::CellProtection>::get(), 0, 0 },
+ { SC_UNONAME_CELLSTYL, SC_WID_UNO_CELLSTYL,cppu::UnoType<OUString>::get(), 0, 0 },
+ { SC_UNONAME_CCOLOR, ATTR_FONT_COLOR, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_COUTL, ATTR_FONT_CONTOUR, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CCROSS, ATTR_FONT_CROSSEDOUT,cppu::UnoType<bool>::get(), 0, MID_CROSSED_OUT },
+ { SC_UNONAME_CEMPHAS, ATTR_FONT_EMPHASISMARK,cppu::UnoType<sal_Int16>::get(), 0, MID_EMPHASIS },
+ { SC_UNONAME_CFONT, ATTR_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_FAMILY },
+ { SC_UNONAME_CFCHARS, ATTR_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_CHAR_SET },
+ { SC_UNO_CJK_CFCHARS, ATTR_CJK_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_CHAR_SET },
+ { SC_UNO_CTL_CFCHARS, ATTR_CTL_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_CHAR_SET },
+ { SC_UNONAME_CFFAMIL, ATTR_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_FAMILY },
+ { SC_UNO_CJK_CFFAMIL, ATTR_CJK_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_FAMILY },
+ { SC_UNO_CTL_CFFAMIL, ATTR_CTL_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_FAMILY },
+ { SC_UNONAME_CFNAME, ATTR_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_FAMILY_NAME },
+ { SC_UNO_CJK_CFNAME, ATTR_CJK_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_FAMILY_NAME },
+ { SC_UNO_CTL_CFNAME, ATTR_CTL_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_FAMILY_NAME },
+ { SC_UNONAME_CFPITCH, ATTR_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_PITCH },
+ { SC_UNO_CJK_CFPITCH, ATTR_CJK_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_PITCH },
+ { SC_UNO_CTL_CFPITCH, ATTR_CTL_FONT, cppu::UnoType<sal_Int16>::get(), 0, MID_FONT_PITCH },
+ { SC_UNONAME_CFSTYLE, ATTR_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_STYLE_NAME },
+ { SC_UNO_CJK_CFSTYLE, ATTR_CJK_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_STYLE_NAME },
+ { SC_UNO_CTL_CFSTYLE, ATTR_CTL_FONT, cppu::UnoType<OUString>::get(), 0, MID_FONT_STYLE_NAME },
+ { SC_UNONAME_CHEIGHT, ATTR_FONT_HEIGHT, cppu::UnoType<float>::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS },
+ { SC_UNO_CJK_CHEIGHT, ATTR_CJK_FONT_HEIGHT,cppu::UnoType<float>::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS },
+ { SC_UNO_CTL_CHEIGHT, ATTR_CTL_FONT_HEIGHT,cppu::UnoType<float>::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS },
+ { SC_UNONAME_CLOCAL, ATTR_FONT_LANGUAGE, cppu::UnoType<lang::Locale>::get(), 0, MID_LANG_LOCALE },
+ { SC_UNO_CJK_CLOCAL, ATTR_CJK_FONT_LANGUAGE,cppu::UnoType<lang::Locale>::get(), 0, MID_LANG_LOCALE },
+ { SC_UNO_CTL_CLOCAL, ATTR_CTL_FONT_LANGUAGE,cppu::UnoType<lang::Locale>::get(), 0, MID_LANG_LOCALE },
+ { SC_UNONAME_COVER, ATTR_FONT_OVERLINE, cppu::UnoType<sal_Int16>::get(), 0, MID_TL_STYLE },
+ { SC_UNONAME_COVRLCOL, ATTR_FONT_OVERLINE, cppu::UnoType<sal_Int32>::get(), 0, MID_TL_COLOR },
+ { SC_UNONAME_COVRLHAS, ATTR_FONT_OVERLINE, cppu::UnoType<bool>::get(), 0, MID_TL_HASCOLOR },
+ { SC_UNONAME_CPOST, ATTR_FONT_POSTURE, cppu::UnoType<awt::FontSlant>::get(), 0, MID_POSTURE },
+ { SC_UNO_CJK_CPOST, ATTR_CJK_FONT_POSTURE,cppu::UnoType<awt::FontSlant>::get(), 0, MID_POSTURE },
+ { SC_UNO_CTL_CPOST, ATTR_CTL_FONT_POSTURE,cppu::UnoType<awt::FontSlant>::get(), 0, MID_POSTURE },
+ { SC_UNONAME_CRELIEF, ATTR_FONT_RELIEF, cppu::UnoType<sal_Int16>::get(), 0, MID_RELIEF },
+ { SC_UNONAME_CSHADD, ATTR_FONT_SHADOWED, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CSTRIKE, ATTR_FONT_CROSSEDOUT,cppu::UnoType<sal_Int16>::get(), 0, MID_CROSS_OUT },
+ { SC_UNONAME_CUNDER, ATTR_FONT_UNDERLINE,cppu::UnoType<sal_Int16>::get(), 0, MID_TL_STYLE },
+ { SC_UNONAME_CUNDLCOL, ATTR_FONT_UNDERLINE,cppu::UnoType<sal_Int32>::get(), 0, MID_TL_COLOR },
+ { SC_UNONAME_CUNDLHAS, ATTR_FONT_UNDERLINE,cppu::UnoType<bool>::get(), 0, MID_TL_HASCOLOR },
+ { SC_UNONAME_CWEIGHT, ATTR_FONT_WEIGHT, cppu::UnoType<float>::get(), 0, MID_WEIGHT },
+ { SC_UNO_CJK_CWEIGHT, ATTR_CJK_FONT_WEIGHT,cppu::UnoType<float>::get(), 0, MID_WEIGHT },
+ { SC_UNO_CTL_CWEIGHT, ATTR_CTL_FONT_WEIGHT,cppu::UnoType<float>::get(), 0, MID_WEIGHT },
+ { SC_UNONAME_CWORDMOD, ATTR_FONT_WORDLINE, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CHCOLHDR, SC_WID_UNO_CHCOLHDR,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CHROWHDR, SC_WID_UNO_CHROWHDR,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CONDFMT, SC_WID_UNO_CONDFMT, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
+ { SC_UNONAME_CONDLOC, SC_WID_UNO_CONDLOC, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
+ { SC_UNONAME_CONDXML, SC_WID_UNO_CONDXML, cppu::UnoType<sheet::XSheetConditionalEntries>::get(), 0, 0 },
+ { SC_UNONAME_COPYBACK, SC_WID_UNO_COPYBACK,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_COPYFORM, SC_WID_UNO_COPYFORM,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_COPYSTYL, SC_WID_UNO_COPYSTYL,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_DIAGONAL_BLTR, ATTR_BORDER_BLTR, ::cppu::UnoType<table::BorderLine>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_DIAGONAL_BLTR2, ATTR_BORDER_BLTR, ::cppu::UnoType<table::BorderLine2>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_DIAGONAL_TLBR, ATTR_BORDER_TLBR, ::cppu::UnoType<table::BorderLine>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_DIAGONAL_TLBR2, ATTR_BORDER_TLBR, ::cppu::UnoType<table::BorderLine2>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_CELLHJUS, ATTR_HOR_JUSTIFY, cppu::UnoType<table::CellHoriJustify>::get(), 0, MID_HORJUST_HORJUST },
+ { SC_UNONAME_CELLHJUS_METHOD, ATTR_HOR_JUSTIFY_METHOD, ::cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_ISACTIVE, SC_WID_UNO_ISACTIVE,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CELLTRAN, ATTR_BACKGROUND, cppu::UnoType<bool>::get(), 0, MID_GRAPHIC_TRANSPARENT },
+ { SC_UNONAME_WRAP, ATTR_LINEBREAK, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_CELLVIS, SC_WID_UNO_CELLVIS, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_LEFTBORDER,ATTR_BORDER, ::cppu::UnoType<table::BorderLine>::get(), 0, LEFT_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_LEFTBORDER2,ATTR_BORDER, ::cppu::UnoType<table::BorderLine2>::get(), 0, LEFT_BORDER | CONVERT_TWIPS },
+ { SC_UNO_LINKDISPBIT, SC_WID_UNO_LINKDISPBIT,cppu::UnoType<awt::XBitmap>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
+ { SC_UNO_LINKDISPNAME, SC_WID_UNO_LINKDISPNAME,cppu::UnoType<OUString>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
+ { SC_UNONAME_NUMFMT, ATTR_VALUE_FORMAT, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_NUMRULES, SC_WID_UNO_NUMRULES,cppu::UnoType<container::XIndexReplace>::get(), 0, 0 },
+ { SC_UNONAME_CELLORI, ATTR_STACKED, cppu::UnoType<table::CellOrientation>::get(), 0, 0 },
+ { SC_UNONAME_PAGESTL, SC_WID_UNO_PAGESTL, cppu::UnoType<OUString>::get(), 0, 0 },
+ { SC_UNONAME_PADJUST, ATTR_HOR_JUSTIFY, ::cppu::UnoType<sal_Int16>::get(), 0, MID_HORJUST_ADJUST },
+ { SC_UNONAME_PBMARGIN, ATTR_MARGIN, cppu::UnoType<sal_Int32>::get(), 0, MID_MARGIN_LO_MARGIN | CONVERT_TWIPS },
+ { SC_UNONAME_PINDENT, ATTR_INDENT, cppu::UnoType<sal_Int16>::get(), 0, 0 }, //! CONVERT_TWIPS
+ { SC_UNONAME_PISCHDIST,ATTR_SCRIPTSPACE, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_PISFORBID,ATTR_FORBIDDEN_RULES,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_PISHANG, ATTR_HANGPUNCTUATION,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_PISHYPHEN,ATTR_HYPHENATE, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_PLASTADJ, ATTR_HOR_JUSTIFY, ::cppu::UnoType<sal_Int16>::get(), 0, MID_HORJUST_ADJUST },
+ { SC_UNONAME_PLMARGIN, ATTR_MARGIN, cppu::UnoType<sal_Int32>::get(), 0, MID_MARGIN_L_MARGIN | CONVERT_TWIPS },
+ { SC_UNONAME_PRMARGIN, ATTR_MARGIN, cppu::UnoType<sal_Int32>::get(), 0, MID_MARGIN_R_MARGIN | CONVERT_TWIPS },
+ { SC_UNONAME_PTMARGIN, ATTR_MARGIN, cppu::UnoType<sal_Int32>::get(), 0, MID_MARGIN_UP_MARGIN | CONVERT_TWIPS },
+ { SC_UNONAME_POS, SC_WID_UNO_POS, cppu::UnoType<awt::Point>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
+ { SC_UNONAME_PRINTBORD,SC_WID_UNO_PRINTBORD,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_PROTECT, SC_WID_UNO_PROTECT, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_RIGHTBORDER,ATTR_BORDER, ::cppu::UnoType<table::BorderLine>::get(), 0, RIGHT_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_RIGHTBORDER2,ATTR_BORDER, ::cppu::UnoType<table::BorderLine2>::get(), 0, RIGHT_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_ROTANG, ATTR_ROTATE_VALUE, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_ROTREF, ATTR_ROTATE_MODE, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_SHADOW, ATTR_SHADOW, cppu::UnoType<table::ShadowFormat>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_SHOWBORD, SC_WID_UNO_SHOWBORD,cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_SHRINK_TO_FIT, ATTR_SHRINKTOFIT, cppu::UnoType<bool>::get(), 0, 0 },
+ { SC_UNONAME_SIZE, SC_WID_UNO_SIZE, cppu::UnoType<awt::Size>::get(), 0 | beans::PropertyAttribute::READONLY, 0 },
+ { SC_UNONAME_TBLBORD, SC_WID_UNO_TBLBORD, cppu::UnoType<table::TableBorder>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_TBLBORD2, SC_WID_UNO_TBLBORD2, cppu::UnoType<table::TableBorder2>::get(), 0, 0 | CONVERT_TWIPS },
+ { SC_UNONAME_TABLAYOUT,SC_WID_UNO_TABLAYOUT,cppu::UnoType<sal_Int16>::get(), 0, 0 },
+ { SC_UNONAME_CONDFORMAT, SC_WID_UNO_CONDFORMAT, cppu::UnoType<sheet::XConditionalFormats>::get(), 0, 0},
+ { SC_UNONAME_TOPBORDER,ATTR_BORDER, ::cppu::UnoType<table::BorderLine>::get(), 0, TOP_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_TOPBORDER2,ATTR_BORDER, ::cppu::UnoType<table::BorderLine2>::get(), 0, TOP_BORDER | CONVERT_TWIPS },
+ { SC_UNONAME_USERDEF, ATTR_USERDEF, cppu::UnoType<container::XNameContainer>::get(), 0, 0 },
+ { SC_UNONAME_VALIDAT, SC_WID_UNO_VALIDAT, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
+ { SC_UNONAME_VALILOC, SC_WID_UNO_VALILOC, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
+ { SC_UNONAME_VALIXML, SC_WID_UNO_VALIXML, cppu::UnoType<beans::XPropertySet>::get(), 0, 0 },
+ { SC_UNONAME_CELLVJUS, ATTR_VER_JUSTIFY, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_CELLVJUS_METHOD, ATTR_VER_JUSTIFY_METHOD, ::cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNONAME_WRITING, ATTR_WRITINGDIR, cppu::UnoType<sal_Int16>::get(), 0, 0 },
+ { SC_UNONAME_TABCOLOR, SC_WID_UNO_TABCOLOR, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { SC_UNO_CODENAME, SC_WID_UNO_CODENAME, cppu::UnoType<OUString>::get(), 0, 0},
+ { SC_UNO_NAMEDRANGES, SC_WID_UNO_NAMES, cppu::UnoType<sheet::XNamedRanges>::get(), 0, 0 },
+ { u"", 0, css::uno::Type(), 0, 0 }
+ };
+ static SfxItemPropertySet aSheetPropertySet( aSheetPropertyMap_Impl );
+ return &aSheetPropertySet;
+}
+
+static const SfxItemPropertyMapEntry* lcl_GetEditPropertyMap()
+{
+ static const SfxItemPropertyMapEntry aEditPropertyMap_Impl[] =
+ {
+ SVX_UNOEDIT_CHAR_PROPERTIES,
+ SVX_UNOEDIT_FONT_PROPERTIES,
+ SVX_UNOEDIT_PARA_PROPERTIES,
+ SVX_UNOEDIT_NUMBERING_PROPERTY, // for completeness of service ParagraphProperties
+ { SC_UNONAME_TEXTUSER, EE_CHAR_XMLATTRIBS, cppu::UnoType<container::XNameContainer>::get(), 0, 0},
+ { SC_UNONAME_USERDEF, EE_PARA_XMLATTRIBS, cppu::UnoType<container::XNameContainer>::get(), 0, 0},
+ { u"", 0, css::uno::Type(), 0, 0 }
+ };
+ return aEditPropertyMap_Impl;
+}
+static const SvxItemPropertySet* lcl_GetEditPropertySet()
+{
+ static SvxItemPropertySet aEditPropertySet( lcl_GetEditPropertyMap(), SdrObject::GetGlobalDrawObjectItemPool() );
+ return &aEditPropertySet;
+}
+
+constexpr OUStringLiteral SCCHARPROPERTIES_SERVICE = u"com.sun.star.style.CharacterProperties";
+constexpr OUStringLiteral SCPARAPROPERTIES_SERVICE = u"com.sun.star.style.ParagraphProperties";
+constexpr OUStringLiteral SCCELLPROPERTIES_SERVICE = u"com.sun.star.table.CellProperties";
+constexpr OUStringLiteral SCCELLRANGE_SERVICE = u"com.sun.star.table.CellRange";
+constexpr OUStringLiteral SCCELL_SERVICE = u"com.sun.star.table.Cell";
+constexpr OUStringLiteral SCSHEETCELLRANGES_SERVICE = u"com.sun.star.sheet.SheetCellRanges";
+constexpr OUStringLiteral SCSHEETCELLRANGE_SERVICE = u"com.sun.star.sheet.SheetCellRange";
+constexpr OUStringLiteral SCSPREADSHEET_SERVICE = u"com.sun.star.sheet.Spreadsheet";
+constexpr OUStringLiteral SCSHEETCELL_SERVICE = u"com.sun.star.sheet.SheetCell";
+
+SC_SIMPLE_SERVICE_INFO( ScCellFormatsEnumeration, "ScCellFormatsEnumeration", "com.sun.star.sheet.CellFormatRangesEnumeration" )
+SC_SIMPLE_SERVICE_INFO( ScCellFormatsObj, "ScCellFormatsObj", "com.sun.star.sheet.CellFormatRanges" )
+SC_SIMPLE_SERVICE_INFO( ScUniqueCellFormatsEnumeration, "ScUniqueCellFormatsEnumeration", "com.sun.star.sheet.UniqueCellFormatRangesEnumeration" )
+SC_SIMPLE_SERVICE_INFO( ScUniqueCellFormatsObj, "ScUniqueCellFormatsObj", "com.sun.star.sheet.UniqueCellFormatRanges" )
+SC_SIMPLE_SERVICE_INFO( ScCellRangesBase, "ScCellRangesBase", "stardiv.unknown" )
+SC_SIMPLE_SERVICE_INFO( ScCellsEnumeration, "ScCellsEnumeration", "com.sun.star.sheet.CellsEnumeration" )
+SC_SIMPLE_SERVICE_INFO( ScCellsObj, "ScCellsObj", "com.sun.star.sheet.Cells" )
+SC_SIMPLE_SERVICE_INFO( ScTableColumnObj, "ScTableColumnObj", "com.sun.star.table.TableColumn" )
+SC_SIMPLE_SERVICE_INFO( ScTableRowObj, "ScTableRowObj", "com.sun.star.table.TableRow" )
+
+//! move ScLinkListener into another file !!!
+
+ScLinkListener::~ScLinkListener()
+{
+}
+
+void ScLinkListener::Notify( const SfxHint& rHint )
+{
+ aLink.Call( rHint );
+}
+
+static void lcl_CopyProperties( beans::XPropertySet& rDest, beans::XPropertySet& rSource )
+{
+ uno::Reference<beans::XPropertySetInfo> xInfo(rSource.getPropertySetInfo());
+ if (xInfo.is())
+ {
+ const uno::Sequence<beans::Property> aSeq(xInfo->getProperties());
+ for (const beans::Property& rProp : aSeq)
+ {
+ OUString aName(rProp.Name);
+ rDest.setPropertyValue( aName, rSource.getPropertyValue( aName ) );
+ }
+ }
+}
+
+static SCTAB lcl_FirstTab( const ScRangeList& rRanges )
+{
+ if (rRanges.empty())
+ throw std::out_of_range("empty range");
+ const ScRange & rFirst = rRanges[0];
+ return rFirst.aStart.Tab();
+}
+
+static bool lcl_WholeSheet( const ScDocument& rDoc, const ScRangeList& rRanges )
+{
+ if ( rRanges.size() == 1 )
+ {
+ const ScRange & rRange = rRanges[0];
+ if ( rRange.aStart.Col() == 0 && rRange.aEnd.Col() == rDoc.MaxCol() &&
+ rRange.aStart.Row() == 0 && rRange.aEnd.Row() == rDoc.MaxRow() )
+ return true;
+ }
+ return false;
+}
+
+namespace {
+template<typename BorderLineType>
+const ::editeng::SvxBorderLine* lcl_getBorderLine(
+ ::editeng::SvxBorderLine& rLine, const BorderLineType& rStruct )
+{
+ // Convert from 1/100mm to Twips.
+ if (!SvxBoxItem::LineToSvxLine( rStruct, rLine, true))
+ return nullptr;
+
+ if ( rLine.GetOutWidth() || rLine.GetInWidth() || rLine.GetDistance() )
+ return &rLine;
+ else
+ return nullptr;
+}
+}
+
+const ::editeng::SvxBorderLine* ScHelperFunctions::GetBorderLine(
+ ::editeng::SvxBorderLine& rLine, const table::BorderLine& rStruct )
+{
+ return lcl_getBorderLine( rLine, rStruct);
+}
+
+const ::editeng::SvxBorderLine* ScHelperFunctions::GetBorderLine(
+ ::editeng::SvxBorderLine& rLine, const table::BorderLine2& rStruct )
+{
+ return lcl_getBorderLine( rLine, rStruct);
+}
+
+namespace {
+template<typename TableBorderType>
+void lcl_fillBoxItems( SvxBoxItem& rOuter, SvxBoxInfoItem& rInner, const TableBorderType& rBorder )
+{
+ ::editeng::SvxBorderLine aLine;
+ rOuter.SetAllDistances(o3tl::toTwips(rBorder.Distance, o3tl::Length::mm100));
+ rOuter.SetLine( ScHelperFunctions::GetBorderLine( aLine, rBorder.TopLine ), SvxBoxItemLine::TOP );
+ rOuter.SetLine( ScHelperFunctions::GetBorderLine( aLine, rBorder.BottomLine ), SvxBoxItemLine::BOTTOM );
+ rOuter.SetLine( ScHelperFunctions::GetBorderLine( aLine, rBorder.LeftLine ), SvxBoxItemLine::LEFT );
+ rOuter.SetLine( ScHelperFunctions::GetBorderLine( aLine, rBorder.RightLine ), SvxBoxItemLine::RIGHT );
+ rInner.SetLine( ScHelperFunctions::GetBorderLine( aLine, rBorder.HorizontalLine ), SvxBoxInfoItemLine::HORI );
+ rInner.SetLine( ScHelperFunctions::GetBorderLine( aLine, rBorder.VerticalLine ), SvxBoxInfoItemLine::VERT );
+ rInner.SetValid( SvxBoxInfoItemValidFlags::TOP, rBorder.IsTopLineValid );
+ rInner.SetValid( SvxBoxInfoItemValidFlags::BOTTOM, rBorder.IsBottomLineValid );
+ rInner.SetValid( SvxBoxInfoItemValidFlags::LEFT, rBorder.IsLeftLineValid );
+ rInner.SetValid( SvxBoxInfoItemValidFlags::RIGHT, rBorder.IsRightLineValid );
+ rInner.SetValid( SvxBoxInfoItemValidFlags::HORI, rBorder.IsHorizontalLineValid );
+ rInner.SetValid( SvxBoxInfoItemValidFlags::VERT, rBorder.IsVerticalLineValid );
+ rInner.SetValid( SvxBoxInfoItemValidFlags::DISTANCE, rBorder.IsDistanceValid );
+ rInner.SetTable( true );
+}
+}
+
+void ScHelperFunctions::FillBoxItems( SvxBoxItem& rOuter, SvxBoxInfoItem& rInner, const table::TableBorder& rBorder )
+{
+ lcl_fillBoxItems( rOuter, rInner, rBorder);
+}
+
+void ScHelperFunctions::FillBoxItems( SvxBoxItem& rOuter, SvxBoxInfoItem& rInner, const table::TableBorder2& rBorder )
+{
+ lcl_fillBoxItems( rOuter, rInner, rBorder);
+}
+
+void ScHelperFunctions::FillBorderLine( table::BorderLine& rStruct, const ::editeng::SvxBorderLine* pLine )
+{
+ // Convert from Twips to 1/100mm.
+ rStruct = SvxBoxItem::SvxLineToLine( pLine, true);
+}
+
+void ScHelperFunctions::FillBorderLine( table::BorderLine2& rStruct, const ::editeng::SvxBorderLine* pLine )
+{
+ rStruct = SvxBoxItem::SvxLineToLine( pLine, true);
+}
+
+namespace {
+template<typename TableBorderItem>
+void lcl_fillTableBorder( TableBorderItem& rBorder, const SvxBoxItem& rOuter, const SvxBoxInfoItem& rInner,
+ bool bInvalidateHorVerDist )
+{
+ ScHelperFunctions::FillBorderLine( rBorder.TopLine, rOuter.GetTop() );
+ ScHelperFunctions::FillBorderLine( rBorder.BottomLine, rOuter.GetBottom() );
+ ScHelperFunctions::FillBorderLine( rBorder.LeftLine, rOuter.GetLeft() );
+ ScHelperFunctions::FillBorderLine( rBorder.RightLine, rOuter.GetRight() );
+ ScHelperFunctions::FillBorderLine( rBorder.HorizontalLine, rInner.GetHori() );
+ ScHelperFunctions::FillBorderLine( rBorder.VerticalLine, rInner.GetVert() );
+
+ rBorder.Distance = rOuter.GetSmallestDistance();
+ rBorder.IsTopLineValid = rInner.IsValid(SvxBoxInfoItemValidFlags::TOP);
+ rBorder.IsBottomLineValid = rInner.IsValid(SvxBoxInfoItemValidFlags::BOTTOM);
+ rBorder.IsLeftLineValid = rInner.IsValid(SvxBoxInfoItemValidFlags::LEFT);
+ rBorder.IsRightLineValid = rInner.IsValid(SvxBoxInfoItemValidFlags::RIGHT);
+ rBorder.IsHorizontalLineValid = !bInvalidateHorVerDist && rInner.IsValid(SvxBoxInfoItemValidFlags::HORI);
+ rBorder.IsVerticalLineValid = !bInvalidateHorVerDist && rInner.IsValid(SvxBoxInfoItemValidFlags::VERT);
+ rBorder.IsDistanceValid = !bInvalidateHorVerDist && rInner.IsValid(SvxBoxInfoItemValidFlags::DISTANCE);
+}
+}
+
+void ScHelperFunctions::AssignTableBorderToAny( uno::Any& rAny,
+ const SvxBoxItem& rOuter, const SvxBoxInfoItem& rInner, bool bInvalidateHorVerDist )
+{
+ table::TableBorder aBorder;
+ lcl_fillTableBorder( aBorder, rOuter, rInner, bInvalidateHorVerDist);
+ rAny <<= aBorder;
+}
+
+void ScHelperFunctions::AssignTableBorder2ToAny( uno::Any& rAny,
+ const SvxBoxItem& rOuter, const SvxBoxInfoItem& rInner, bool bInvalidateHorVerDist )
+{
+ table::TableBorder2 aBorder;
+ lcl_fillTableBorder( aBorder, rOuter, rInner, bInvalidateHorVerDist);
+ rAny <<= aBorder;
+}
+
+//! move lcl_ApplyBorder to docfunc !
+
+void ScHelperFunctions::ApplyBorder( ScDocShell* pDocShell, const ScRangeList& rRanges,
+ const SvxBoxItem& rOuter, const SvxBoxInfoItem& rInner )
+{
+ ScDocument& rDoc = pDocShell->GetDocument();
+ bool bUndo(rDoc.IsUndoEnabled());
+ ScDocumentUniquePtr pUndoDoc;
+ if (bUndo)
+ pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
+ size_t nCount = rRanges.size();
+ for (size_t i = 0; i < nCount; ++i)
+ {
+ ScRange const & rRange = rRanges[ i ];
+ SCTAB nTab = rRange.aStart.Tab();
+
+ if (bUndo)
+ {
+ if ( i==0 )
+ pUndoDoc->InitUndo( rDoc, nTab, nTab );
+ else
+ pUndoDoc->AddUndoTab( nTab, nTab );
+ rDoc.CopyToDocument(rRange, InsertDeleteFlags::ATTRIB, false, *pUndoDoc);
+ }
+
+ ScMarkData aMark(rDoc.GetSheetLimits());
+ aMark.SetMarkArea( rRange );
+ aMark.SelectTable( nTab, true );
+
+ rDoc.ApplySelectionFrame(aMark, rOuter, &rInner);
+ // don't need RowHeight if there is only a border
+ }
+
+ if (bUndo)
+ {
+ pDocShell->GetUndoManager()->AddUndoAction(
+ std::make_unique<ScUndoBorder>( pDocShell, rRanges, std::move(pUndoDoc), rOuter, rInner ) );
+ }
+
+ for (size_t i = 0; i < nCount; ++i )
+ pDocShell->PostPaint( rRanges[ i ], PaintPartFlags::Grid, SC_PF_LINES | SC_PF_TESTMERGE );
+
+ pDocShell->SetDocumentModified();
+}
+
+//! move lcl_PutDataArray to docfunc?
+//! merge loop with ScFunctionAccess::callFunction
+
+static bool lcl_PutDataArray( ScDocShell& rDocShell, const ScRange& rRange,
+ const uno::Sequence< uno::Sequence<uno::Any> >& aData )
+{
+ ScDocument& rDoc = rDocShell.GetDocument();
+ ScFieldEditEngine& rEngine = rDoc.GetEditEngine();
+ SCTAB nTab = rRange.aStart.Tab();
+ SCCOL nStartCol = rRange.aStart.Col();
+ SCROW nStartRow = rRange.aStart.Row();
+ SCCOL nEndCol = rRange.aEnd.Col();
+ SCROW nEndRow = rRange.aEnd.Row();
+ bool bUndo(rDoc.IsUndoEnabled());
+
+ if ( !rDoc.IsBlockEditable( nTab, nStartCol,nStartRow, nEndCol,nEndRow ) )
+ {
+ //! error message
+ return false;
+ }
+
+ sal_Int32 nCols = 0;
+ sal_Int32 nRows = aData.getLength();
+ if ( nRows )
+ nCols = aData[0].getLength();
+
+ if ( nCols != nEndCol-nStartCol+1 || nRows != nEndRow-nStartRow+1 )
+ {
+ //! error message?
+ return false;
+ }
+
+ ScDocumentUniquePtr pUndoDoc;
+ if ( bUndo )
+ {
+ pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
+ pUndoDoc->InitUndo( rDoc, nTab, nTab );
+ rDoc.CopyToDocument(rRange, InsertDeleteFlags::CONTENTS|InsertDeleteFlags::NOCAPTIONS, false, *pUndoDoc);
+ }
+
+ rDoc.DeleteAreaTab( nStartCol, nStartRow, nEndCol, nEndRow, nTab, InsertDeleteFlags::CONTENTS );
+
+ bool bError = false;
+ SCROW nDocRow = nStartRow;
+ for (const uno::Sequence<uno::Any>& rColSeq : aData)
+ {
+ if ( rColSeq.getLength() == nCols )
+ {
+ SCCOL nDocCol = nStartCol;
+ for (const uno::Any& rElement : rColSeq)
+ {
+ ScAddress aPos(nDocCol, nDocRow, nTab);
+
+ switch( rElement.getValueTypeClass() )
+ {
+ case uno::TypeClass_VOID:
+ {
+ // void = "no value"
+ rDoc.SetError( nDocCol, nDocRow, nTab, FormulaError::NotAvailable );
+ }
+ break;
+
+ // #87871# accept integer types because Basic passes a floating point
+ // variable as byte, short or long if it's an integer number.
+ case uno::TypeClass_BYTE:
+ case uno::TypeClass_SHORT:
+ case uno::TypeClass_UNSIGNED_SHORT:
+ case uno::TypeClass_LONG:
+ case uno::TypeClass_UNSIGNED_LONG:
+ case uno::TypeClass_FLOAT:
+ case uno::TypeClass_DOUBLE:
+ {
+ double fVal(0.0);
+ rElement >>= fVal;
+ rDoc.SetValue(aPos, fVal);
+ }
+ break;
+
+ case uno::TypeClass_STRING:
+ {
+ OUString aUStr;
+ rElement >>= aUStr;
+ if ( !aUStr.isEmpty() )
+ {
+ // tdf#146454 - check for a multiline string since setting an edit
+ // or string cell is in magnitudes slower than setting a plain string
+ if (ScStringUtil::isMultiline(aUStr))
+ {
+ rEngine.SetTextCurrentDefaults(aUStr);
+ rDoc.SetEditText(aPos, rEngine.CreateTextObject());
+ }
+ else
+ {
+ ScSetStringParam aParam;
+ aParam.setTextInput();
+ rDoc.SetString(aPos, aUStr, &aParam);
+ }
+ }
+ }
+ break;
+
+ // accept Sequence<FormulaToken> for formula cells
+ case uno::TypeClass_SEQUENCE:
+ {
+ uno::Sequence< sheet::FormulaToken > aTokens;
+ if ( rElement >>= aTokens )
+ {
+ ScTokenArray aTokenArray(rDoc);
+ ScTokenConversion::ConvertToTokenArray( rDoc, aTokenArray, aTokens );
+ rDoc.SetFormula(aPos, aTokenArray);
+ }
+ else
+ bError = true;
+ }
+ break;
+
+ default:
+ bError = true; // invalid type
+ }
+ ++nDocCol;
+ }
+ }
+ else
+ bError = true; // wrong size
+
+ ++nDocRow;
+ }
+
+ bool bHeight = rDocShell.AdjustRowHeight( nStartRow, nEndRow, nTab );
+
+ if ( pUndoDoc )
+ {
+ ScMarkData aDestMark(rDoc.GetSheetLimits());
+ aDestMark.SelectOneTable( nTab );
+ rDocShell.GetUndoManager()->AddUndoAction(
+ std::make_unique<ScUndoPaste>(
+ &rDocShell, ScRange(nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab),
+ aDestMark, std::move(pUndoDoc), nullptr, InsertDeleteFlags::CONTENTS, nullptr, false));
+ }
+
+ if (!bHeight)
+ rDocShell.PostPaint( rRange, PaintPartFlags::Grid ); // AdjustRowHeight may have painted already
+
+ rDocShell.SetDocumentModified();
+
+ return !bError;
+}
+
+static bool lcl_PutFormulaArray( ScDocShell& rDocShell, const ScRange& rRange,
+ const uno::Sequence< uno::Sequence<OUString> >& aData,
+ const formula::FormulaGrammar::Grammar eGrammar )
+{
+ ScDocument& rDoc = rDocShell.GetDocument();
+ SCTAB nTab = rRange.aStart.Tab();
+ SCCOL nStartCol = rRange.aStart.Col();
+ SCROW nStartRow = rRange.aStart.Row();
+ SCCOL nEndCol = rRange.aEnd.Col();
+ SCROW nEndRow = rRange.aEnd.Row();
+ bool bUndo(rDoc.IsUndoEnabled());
+
+ if ( !rDoc.IsBlockEditable( nTab, nStartCol,nStartRow, nEndCol,nEndRow ) )
+ {
+ //! error message
+ return false;
+ }
+
+ sal_Int32 nCols = 0;
+ sal_Int32 nRows = aData.getLength();
+ if ( nRows )
+ nCols = aData[0].getLength();
+
+ if ( nCols != nEndCol-nStartCol+1 || nRows != nEndRow-nStartRow+1 )
+ {
+ //! error message?
+ return false;
+ }
+
+ ScDocumentUniquePtr pUndoDoc;
+ if ( bUndo )
+ {
+ pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
+ pUndoDoc->InitUndo( rDoc, nTab, nTab );
+ rDoc.CopyToDocument(rRange, InsertDeleteFlags::CONTENTS, false, *pUndoDoc);
+ }
+
+ rDoc.DeleteAreaTab( nStartCol, nStartRow, nEndCol, nEndRow, nTab, InsertDeleteFlags::CONTENTS );
+
+ bool bError = false;
+ SCROW nDocRow = nStartRow;
+ for (const uno::Sequence<OUString>& rColSeq : aData)
+ {
+ if ( rColSeq.getLength() == nCols )
+ {
+ SCCOL nDocCol = nStartCol;
+ for (const OUString& aText : rColSeq)
+ {
+ ScAddress aPos( nDocCol, nDocRow, nTab );
+
+ ScInputStringType aRes =
+ ScStringUtil::parseInputString(
+ *rDoc.GetFormatTable(), aText, LANGUAGE_ENGLISH_US);
+ switch (aRes.meType)
+ {
+ case ScInputStringType::Formula:
+ rDoc.SetFormula(aPos, aRes.maText, eGrammar);
+ break;
+ case ScInputStringType::Number:
+ rDoc.SetValue(aPos, aRes.mfValue);
+ break;
+ case ScInputStringType::Text:
+ rDoc.SetTextCell(aPos, aRes.maText);
+ break;
+ default:
+ ;
+ }
+
+ ++nDocCol;
+ }
+ }
+ else
+ bError = true; // wrong size
+
+ ++nDocRow;
+ }
+
+ bool bHeight = rDocShell.AdjustRowHeight( nStartRow, nEndRow, nTab );
+
+ if ( pUndoDoc )
+ {
+ ScMarkData aDestMark(rDoc.GetSheetLimits());
+ aDestMark.SelectOneTable( nTab );
+ rDocShell.GetUndoManager()->AddUndoAction(
+ std::make_unique<ScUndoPaste>( &rDocShell,
+ ScRange(nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab), aDestMark,
+ std::move(pUndoDoc), nullptr, InsertDeleteFlags::CONTENTS, nullptr, false));
+ }
+
+ if (!bHeight)
+ rDocShell.PostPaint( rRange, PaintPartFlags::Grid ); // AdjustRowHeight may have painted already
+
+ rDocShell.SetDocumentModified();
+
+ return !bError;
+}
+
+// used in ScCellRangeObj::getFormulaArray and ScCellObj::GetInputString_Impl
+static OUString lcl_GetInputString( ScDocument& rDoc, const ScAddress& rPos, bool bEnglish )
+{
+ ScRefCellValue aCell(rDoc, rPos);
+ if (aCell.isEmpty())
+ return OUString();
+
+ OUString aVal;
+
+ CellType eType = aCell.meType;
+ if (eType == CELLTYPE_FORMULA)
+ {
+ ScFormulaCell* pForm = aCell.mpFormula;
+ return pForm->GetFormula( formula::FormulaGrammar::mapAPItoGrammar( bEnglish, false));
+ }
+
+ SvNumberFormatter* pFormatter = bEnglish ? ScGlobal::GetEnglishFormatter() :
+ rDoc.GetFormatTable();
+ // Since the English formatter was constructed with
+ // LANGUAGE_ENGLISH_US the "General" format has index key 0,
+ // we don't have to query.
+ sal_uInt32 nNumFmt = bEnglish ? 0 : rDoc.GetNumberFormat(rPos);
+
+ if (eType == CELLTYPE_EDIT)
+ {
+ // GetString on EditCell turns breaks into spaces,
+ // but we need the breaks here
+ const EditTextObject* pData = aCell.mpEditText;
+ if (pData)
+ {
+ EditEngine& rEngine = rDoc.GetEditEngine();
+ rEngine.SetText(*pData);
+ aVal = rEngine.GetText();
+ }
+ }
+ else
+ aVal = ScCellFormat::GetInputString(aCell, nNumFmt, *pFormatter, rDoc);
+
+ // if applicable, prepend ' like in ScTabViewShell::UpdateInputHandler
+ if ( eType == CELLTYPE_STRING || eType == CELLTYPE_EDIT )
+ {
+ double fDummy;
+ OUString aTempString = aVal;
+ bool bIsNumberFormat(pFormatter->IsNumberFormat(aTempString, nNumFmt, fDummy));
+ if ( bIsNumberFormat )
+ aTempString = "'" + aTempString;
+ else if ( aTempString.startsWith("'") )
+ {
+ // if the string starts with a "'", add another one because setFormula
+ // strips one (like text input, except for "text" number formats)
+ if ( bEnglish || ( pFormatter->GetType(nNumFmt) != SvNumFormatType::TEXT ) )
+ aTempString = "'" + aTempString;
+ }
+ aVal = aTempString;
+ }
+ return aVal;
+}
+
+ScCellRangesBase::ScCellRangesBase(ScDocShell* pDocSh, const ScRange& rR) :
+ pPropSet(lcl_GetCellsPropertySet()),
+ pDocShell( pDocSh ),
+ nObjectId( 0 ),
+ bChartColAsHdr( false ),
+ bChartRowAsHdr( false ),
+ bCursorOnly( false ),
+ bGotDataChangedHint( false ),
+ aValueListeners( 0 )
+{
+ ScRange aCellRange(rR);
+ aCellRange.PutInOrder();
+ aRanges.push_back( aCellRange );
+
+ if (pDocShell) // Null if created with createInstance
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+ rDoc.AddUnoObject(*this);
+ nObjectId = rDoc.GetNewUnoId();
+ }
+}
+
+ScCellRangesBase::ScCellRangesBase(ScDocShell* pDocSh, const ScRangeList& rR) :
+ pPropSet(lcl_GetCellsPropertySet()),
+ pDocShell( pDocSh ),
+ aRanges( rR ),
+ nObjectId( 0 ),
+ bChartColAsHdr( false ),
+ bChartRowAsHdr( false ),
+ bCursorOnly( false ),
+ bGotDataChangedHint( false ),
+ aValueListeners( 0 )
+{
+ if (pDocShell) // Null if created with createInstance
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+ rDoc.AddUnoObject(*this);
+ nObjectId = rDoc.GetNewUnoId();
+ }
+}
+
+ScCellRangesBase::~ScCellRangesBase()
+{
+ SolarMutexGuard g;
+
+ // call RemoveUnoObject first, so no notification can happen
+ // during ForgetCurrentAttrs
+
+ if (pDocShell)
+ pDocShell->GetDocument().RemoveUnoObject(*this);
+
+ ForgetCurrentAttrs();
+ ForgetMarkData();
+
+ pValueListener.reset();
+
+ //! unregister XChartDataChangeEventListener ??
+ //! (ChartCollection will then hold this object as well!)
+}
+
+void ScCellRangesBase::ForgetCurrentAttrs()
+{
+ pCurrentFlat.reset();
+ pCurrentDeep.reset();
+ moCurrentDataSet.reset();
+ moNoDfltCurrentDataSet.reset();
+
+ // #i62483# pMarkData can remain unchanged, is deleted only if the range changes (RefChanged)
+}
+
+void ScCellRangesBase::ForgetMarkData()
+{
+ pMarkData.reset();
+}
+
+const ScPatternAttr* ScCellRangesBase::GetCurrentAttrsFlat()
+{
+ // get and cache direct cell attributes for this object's range
+
+ if ( !pCurrentFlat && pDocShell )
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+ pCurrentFlat = rDoc.CreateSelectionPattern( *GetMarkData(), false );
+ }
+ return pCurrentFlat.get();
+}
+
+const ScPatternAttr* ScCellRangesBase::GetCurrentAttrsDeep()
+{
+ // get and cache cell attributes (incl. styles) for this object's range
+
+ if ( !pCurrentDeep && pDocShell )
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+ pCurrentDeep = rDoc.CreateSelectionPattern( *GetMarkData() );
+ }
+ return pCurrentDeep.get();
+}
+
+SfxItemSet* ScCellRangesBase::GetCurrentDataSet(bool bNoDflt)
+{
+ if(!moCurrentDataSet)
+ {
+ const ScPatternAttr* pPattern = GetCurrentAttrsDeep();
+ if ( pPattern )
+ {
+ // replace Dontcare with Default, so that we always have a reflection
+ moCurrentDataSet.emplace( pPattern->GetItemSet() );
+ moNoDfltCurrentDataSet.emplace( pPattern->GetItemSet() );
+ moCurrentDataSet->ClearInvalidItems();
+ }
+ }
+ if (bNoDflt)
+ {
+ if (moNoDfltCurrentDataSet)
+ return &*moNoDfltCurrentDataSet;
+ }
+ else
+ {
+ if (moCurrentDataSet)
+ return &*moCurrentDataSet;
+ }
+ return nullptr;
+}
+
+const ScMarkData* ScCellRangesBase::GetMarkData()
+{
+ if (!pMarkData)
+ {
+ pMarkData.reset( new ScMarkData(GetDocument()->GetSheetLimits(), aRanges) );
+ }
+ return pMarkData.get();
+}
+
+void ScCellRangesBase::Notify( SfxBroadcaster&, const SfxHint& rHint )
+{
+ const SfxHintId nId = rHint.GetId();
+ if ( nId == SfxHintId::Dying )
+ {
+ // if the document dies, must reset to avoid crash in dtor!
+ ForgetCurrentAttrs();
+ pDocShell = nullptr; // invalid
+
+ // fdo#72695: if UNO object is already dead, don't revive it with event
+ if ( m_refCount > 0 && !aValueListeners.empty() )
+ {
+ // dispose listeners
+
+ lang::EventObject aEvent;
+ aEvent.Source.set(static_cast<cppu::OWeakObject*>(this));
+ for (uno::Reference<util::XModifyListener> & xValueListener : aValueListeners)
+ xValueListener->disposing( aEvent );
+
+ aValueListeners.clear();
+
+ // The listeners can't have the last ref to this, as it's still held
+ // by the DocShell.
+ }
+ }
+ else if ( nId == SfxHintId::DataChanged )
+ {
+ // document content changed -> forget cached attributes
+ ForgetCurrentAttrs();
+
+ if ( bGotDataChangedHint && pDocShell )
+ {
+ // This object was notified of content changes, so one call
+ // for each listener is generated now.
+ // The calls can't be executed directly because the document's
+ // UNO broadcaster list must not be modified.
+ // Instead, add to the document's list of listener calls,
+ // which will be executed directly after the broadcast of
+ // SfxHintId::DataChanged.
+
+ lang::EventObject aEvent;
+ aEvent.Source.set(static_cast<cppu::OWeakObject*>(this));
+
+ // the EventObject holds a Ref to this object until after the listener calls
+
+ ScDocument& rDoc = pDocShell->GetDocument();
+ for (const uno::Reference<util::XModifyListener> & xValueListener : aValueListeners)
+ rDoc.AddUnoListenerCall( xValueListener, aEvent );
+
+ bGotDataChangedHint = false;
+ }
+ }
+ else if ( nId == SfxHintId::ScCalcAll )
+ {
+ // broadcast from DoHardRecalc - set bGotDataChangedHint
+ // (SfxHintId::DataChanged follows separately)
+
+ if ( !aValueListeners.empty() )
+ bGotDataChangedHint = true;
+ }
+ else if ( auto pRefHint = dynamic_cast<const ScUpdateRefHint*>(&rHint) )
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+ std::unique_ptr<ScRangeList> pUndoRanges;
+ if ( rDoc.HasUnoRefUndo() )
+ pUndoRanges.reset(new ScRangeList( aRanges ));
+
+ if ( aRanges.UpdateReference( pRefHint->GetMode(), &rDoc, pRefHint->GetRange(),
+ pRefHint->GetDx(), pRefHint->GetDy(), pRefHint->GetDz() ) )
+ {
+ if ( pRefHint->GetMode() == URM_INSDEL
+ && aRanges.size() == 1
+ && dynamic_cast<ScTableSheetObj*>(this)
+ )
+ {
+ // #101755#; the range size of a sheet does not change
+ ScRange & rR = aRanges.front();
+ rR.aStart.SetCol(0);
+ rR.aStart.SetRow(0);
+ rR.aEnd.SetCol(rDoc.MaxCol());
+ rR.aEnd.SetRow(rDoc.MaxRow());
+ }
+ RefChanged();
+
+ // any change of the range address is broadcast to value (modify) listeners
+ if ( !aValueListeners.empty() )
+ bGotDataChangedHint = true;
+
+ if ( pUndoRanges )
+ rDoc.AddUnoRefChange( nObjectId, *pUndoRanges );
+ }
+ }
+ else if ( auto pUndoHint = dynamic_cast<const ScUnoRefUndoHint*>(&rHint) )
+ {
+ if ( pUndoHint->GetObjectId() == nObjectId )
+ {
+ // restore ranges from hint
+
+ aRanges = pUndoHint->GetRanges();
+
+ RefChanged();
+ if ( !aValueListeners.empty() )
+ bGotDataChangedHint = true; // need to broadcast the undo, too
+ }
+ }
+}
+
+void ScCellRangesBase::RefChanged()
+{
+ //! adjust XChartDataChangeEventListener
+
+ if ( pValueListener && !aValueListeners.empty() )
+ {
+ pValueListener->EndListeningAll();
+
+ ScDocument& rDoc = pDocShell->GetDocument();
+ for ( size_t i = 0, nCount = aRanges.size(); i < nCount; ++i )
+ rDoc.StartListeningArea( aRanges[ i ], false, pValueListener.get() );
+ }
+
+ ForgetCurrentAttrs();
+ ForgetMarkData();
+}
+
+ScDocument* ScCellRangesBase::GetDocument() const
+{
+ if (pDocShell)
+ return &pDocShell->GetDocument();
+ else
+ return nullptr;
+}
+
+void ScCellRangesBase::InitInsertRange(ScDocShell* pDocSh, const ScRange& rR)
+{
+ if ( pDocShell || !pDocSh )
+ return;
+
+ pDocShell = pDocSh;
+
+ ScRange aCellRange(rR);
+ aCellRange.PutInOrder();
+ aRanges.RemoveAll();
+ aRanges.push_back( aCellRange );
+
+ pDocShell->GetDocument().AddUnoObject(*this);
+
+ RefChanged(); // adjust range in range object
+}
+
+void ScCellRangesBase::AddRange(const ScRange& rRange, const bool bMergeRanges)
+{
+ if (bMergeRanges)
+ aRanges.Join(rRange);
+ else
+ aRanges.push_back(rRange);
+ RefChanged();
+}
+
+void ScCellRangesBase::SetNewRange(const ScRange& rNew)
+{
+ ScRange aCellRange(rNew);
+ aCellRange.PutInOrder();
+
+ aRanges.RemoveAll();
+ aRanges.push_back( aCellRange );
+ RefChanged();
+}
+
+void ScCellRangesBase::SetNewRanges(const ScRangeList& rNew)
+{
+ aRanges = rNew;
+ RefChanged();
+}
+
+void ScCellRangesBase::SetCursorOnly( bool bSet )
+{
+ // set for a selection object that is created from the cursor position
+ // without anything selected (may contain several sheets)
+
+ bCursorOnly = bSet;
+}
+
+void ScCellRangesBase::PaintGridRanges_Impl( )
+{
+ for (size_t i = 0, nCount = aRanges.size(); i < nCount; ++i)
+ pDocShell->PostPaint( aRanges[ i ], PaintPartFlags::Grid );
+}
+
+// XSheetOperation
+
+double SAL_CALL ScCellRangesBase::computeFunction( sheet::GeneralFunction nFunction )
+{
+ SolarMutexGuard aGuard;
+ ScMarkData aMark(*GetMarkData());
+ aMark.MarkToSimple();
+ if (!aMark.IsMarked())
+ aMark.SetMarkNegative(true); // so we can enter dummy position
+
+ ScAddress aDummy; // if not marked, ignored if it is negative
+ double fVal;
+ ScSubTotalFunc eFunc = ScDPUtil::toSubTotalFunc(static_cast<ScGeneralFunction>(nFunction));
+ ScDocument& rDoc = pDocShell->GetDocument();
+ if ( !rDoc.GetSelectionFunction( eFunc, aDummy, aMark, fVal ) )
+ {
+ throw uno::RuntimeException(); //! own exception?
+ }
+
+ return fVal;
+}
+
+void SAL_CALL ScCellRangesBase::clearContents( sal_Int32 nContentFlags )
+{
+ SolarMutexGuard aGuard;
+ if ( !aRanges.empty() )
+ {
+ // only for clearContents: EDITATTR is only used if no contents are deleted
+ InsertDeleteFlags nDelFlags = static_cast<InsertDeleteFlags>(nContentFlags) & InsertDeleteFlags::ALL;
+ if ( ( nDelFlags & InsertDeleteFlags::EDITATTR ) && ( nDelFlags & InsertDeleteFlags::CONTENTS ) == InsertDeleteFlags::NONE )
+ nDelFlags |= InsertDeleteFlags::EDITATTR;
+
+ pDocShell->GetDocFunc().DeleteContents( *GetMarkData(), nDelFlags, true, true );
+ }
+ // otherwise nothing to do
+}
+
+// XPropertyState
+
+const SfxItemPropertyMap& ScCellRangesBase::GetItemPropertyMap()
+{
+ return pPropSet->getPropertyMap();
+}
+
+static void lcl_GetPropertyWhich( const SfxItemPropertyMapEntry* pEntry,
+ sal_uInt16& rItemWhich )
+{
+ // Which-ID of the affected items also when the item can't handle
+ // the property by itself
+ if ( !pEntry )
+ return;
+
+ if ( IsScItemWid( pEntry->nWID ) )
+ rItemWhich = pEntry->nWID;
+ else
+ switch ( pEntry->nWID )
+ {
+ case SC_WID_UNO_TBLBORD:
+ case SC_WID_UNO_TBLBORD2:
+ rItemWhich = ATTR_BORDER;
+ break;
+ case SC_WID_UNO_CONDFMT:
+ case SC_WID_UNO_CONDLOC:
+ case SC_WID_UNO_CONDXML:
+ rItemWhich = ATTR_CONDITIONAL;
+ break;
+ case SC_WID_UNO_VALIDAT:
+ case SC_WID_UNO_VALILOC:
+ case SC_WID_UNO_VALIXML:
+ rItemWhich = ATTR_VALIDDATA;
+ break;
+ }
+
+}
+
+beans::PropertyState ScCellRangesBase::GetOnePropertyState( sal_uInt16 nItemWhich, const SfxItemPropertyMapEntry* pEntry )
+{
+ beans::PropertyState eRet = beans::PropertyState_DIRECT_VALUE;
+ if ( nItemWhich ) // item wid (from map or special case)
+ {
+ // For items that contain several properties (like background),
+ // "ambiguous" is returned too often here
+
+ // for PropertyState, don't look at styles
+ const ScPatternAttr* pPattern = GetCurrentAttrsFlat();
+ if ( pPattern )
+ {
+ SfxItemState eState = pPattern->GetItemSet().GetItemState( nItemWhich, false );
+
+ if ( nItemWhich == ATTR_VALUE_FORMAT && eState == SfxItemState::DEFAULT )
+ eState = pPattern->GetItemSet().GetItemState( ATTR_LANGUAGE_FORMAT, false );
+
+ if ( eState == SfxItemState::SET )
+ eRet = beans::PropertyState_DIRECT_VALUE;
+ else if ( eState == SfxItemState::DEFAULT )
+ eRet = beans::PropertyState_DEFAULT_VALUE;
+ else if ( eState == SfxItemState::DONTCARE )
+ eRet = beans::PropertyState_AMBIGUOUS_VALUE;
+ else
+ {
+ OSL_FAIL("unknown ItemState");
+ }
+ }
+ }
+ else if ( pEntry )
+ {
+ if ( pEntry->nWID == SC_WID_UNO_CHCOLHDR || pEntry->nWID == SC_WID_UNO_CHROWHDR || pEntry->nWID == SC_WID_UNO_ABSNAME )
+ eRet = beans::PropertyState_DIRECT_VALUE;
+ else if ( pEntry->nWID == SC_WID_UNO_CELLSTYL )
+ {
+ // a style is always set, there's no default state
+ const ScStyleSheet* pStyle = pDocShell->GetDocument().GetSelectionStyle(*GetMarkData());
+ if (pStyle)
+ eRet = beans::PropertyState_DIRECT_VALUE;
+ else
+ eRet = beans::PropertyState_AMBIGUOUS_VALUE;
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_NUMRULES )
+ eRet = beans::PropertyState_DEFAULT_VALUE; // numbering rules are always default
+ }
+ return eRet;
+}
+
+beans::PropertyState SAL_CALL ScCellRangesBase::getPropertyState( const OUString& aPropertyName )
+{
+ SolarMutexGuard aGuard;
+ if ( aRanges.empty() )
+ throw uno::RuntimeException();
+
+ const SfxItemPropertyMap& rMap = GetItemPropertyMap(); // from derived class
+ sal_uInt16 nItemWhich = 0;
+ const SfxItemPropertyMapEntry* pEntry = rMap.getByName( aPropertyName );
+ lcl_GetPropertyWhich( pEntry, nItemWhich );
+ return GetOnePropertyState( nItemWhich, pEntry );
+}
+
+uno::Sequence<beans::PropertyState> SAL_CALL ScCellRangesBase::getPropertyStates(
+ const uno::Sequence<OUString>& aPropertyNames )
+{
+ SolarMutexGuard aGuard;
+
+ const SfxItemPropertyMap& rPropertyMap = GetItemPropertyMap(); // from derived class
+
+ uno::Sequence<beans::PropertyState> aRet(aPropertyNames.getLength());
+ std::transform(aPropertyNames.begin(), aPropertyNames.end(), aRet.getArray(),
+ [this, &rPropertyMap](const auto& rName) -> beans::PropertyState {
+ sal_uInt16 nItemWhich = 0;
+ const SfxItemPropertyMapEntry* pEntry = rPropertyMap.getByName( rName );
+ lcl_GetPropertyWhich( pEntry, nItemWhich );
+ return GetOnePropertyState(nItemWhich, pEntry);
+ });
+ return aRet;
+}
+
+void SAL_CALL ScCellRangesBase::setPropertyToDefault( const OUString& aPropertyName )
+{
+ SolarMutexGuard aGuard;
+ if ( !pDocShell )
+ return;
+
+ const SfxItemPropertyMap& rPropertyMap = GetItemPropertyMap(); // from derived class
+ sal_uInt16 nItemWhich = 0;
+ const SfxItemPropertyMapEntry* pEntry = rPropertyMap.getByName( aPropertyName );
+ lcl_GetPropertyWhich( pEntry, nItemWhich );
+ if ( nItemWhich ) // item wid (from map or special case)
+ {
+ if ( !aRanges.empty() ) // empty = nothing to do
+ {
+ //! for items that have multiple properties (e.g. background)
+ //! too much will be reset
+ //! for ATTR_ROTATE_VALUE, reset ATTR_ORIENTATION as well?
+
+ sal_uInt16 aWIDs[3];
+ aWIDs[0] = nItemWhich;
+ if ( nItemWhich == ATTR_VALUE_FORMAT )
+ {
+ aWIDs[1] = ATTR_LANGUAGE_FORMAT; // language for number formats
+ aWIDs[2] = 0;
+ }
+ else
+ aWIDs[1] = 0;
+ pDocShell->GetDocFunc().ClearItems( *GetMarkData(), aWIDs, true );
+ }
+ }
+ else if ( pEntry )
+ {
+ if ( pEntry->nWID == SC_WID_UNO_CHCOLHDR )
+ bChartColAsHdr = false;
+ else if ( pEntry->nWID == SC_WID_UNO_CHROWHDR )
+ bChartRowAsHdr = false;
+ else if ( pEntry->nWID == SC_WID_UNO_CELLSTYL )
+ {
+ OUString aStyleName( ScResId( STR_STYLENAME_STANDARD ) );
+ pDocShell->GetDocFunc().ApplyStyle( *GetMarkData(), aStyleName, true );
+ }
+ }
+}
+
+uno::Any SAL_CALL ScCellRangesBase::getPropertyDefault( const OUString& aPropertyName )
+{
+ //! bundle with getPropertyValue
+
+ SolarMutexGuard aGuard;
+ uno::Any aAny;
+
+ if ( pDocShell )
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+ const SfxItemPropertyMap& rPropertyMap = GetItemPropertyMap(); // from derived class
+ const SfxItemPropertyMapEntry* pEntry = rPropertyMap.getByName( aPropertyName );
+ if ( pEntry )
+ {
+ if ( IsScItemWid( pEntry->nWID ) )
+ {
+ const ScPatternAttr* pPattern = rDoc.GetDefPattern();
+ if ( pPattern )
+ {
+ const SfxItemSet& rSet = pPattern->GetItemSet();
+
+ switch ( pEntry->nWID ) // for item-specific handling
+ {
+ case ATTR_VALUE_FORMAT:
+ // default has no language set
+ aAny <<= static_cast<sal_Int32>( static_cast<const SfxUInt32Item&>(rSet.Get(pEntry->nWID)).GetValue() );
+ break;
+ case ATTR_INDENT:
+ aAny <<= static_cast<sal_Int16>( convertTwipToMm100(static_cast<const ScIndentItem&>(
+ rSet.Get(pEntry->nWID)).GetValue()) );
+ break;
+ default:
+ pPropSet->getPropertyValue(aPropertyName, rSet, aAny);
+ }
+ }
+ }
+ else
+ switch ( pEntry->nWID )
+ {
+ case SC_WID_UNO_CHCOLHDR:
+ case SC_WID_UNO_CHROWHDR:
+ aAny <<= false;
+ break;
+ case SC_WID_UNO_CELLSTYL:
+ aAny <<= ScStyleNameConversion::DisplayToProgrammaticName(
+ ScResId(STR_STYLENAME_STANDARD), SfxStyleFamily::Para );
+ break;
+ case SC_WID_UNO_TBLBORD:
+ case SC_WID_UNO_TBLBORD2:
+ {
+ const ScPatternAttr* pPattern = rDoc.GetDefPattern();
+ if ( pPattern )
+ {
+ if (pEntry->nWID == SC_WID_UNO_TBLBORD2)
+ ScHelperFunctions::AssignTableBorder2ToAny( aAny,
+ pPattern->GetItem(ATTR_BORDER),
+ pPattern->GetItem(ATTR_BORDER_INNER) );
+ else
+ ScHelperFunctions::AssignTableBorderToAny( aAny,
+ pPattern->GetItem(ATTR_BORDER),
+ pPattern->GetItem(ATTR_BORDER_INNER) );
+ }
+ }
+ break;
+ case SC_WID_UNO_CONDFMT:
+ case SC_WID_UNO_CONDLOC:
+ case SC_WID_UNO_CONDXML:
+ {
+ bool bEnglish = ( pEntry->nWID != SC_WID_UNO_CONDLOC );
+ bool bXML = ( pEntry->nWID == SC_WID_UNO_CONDXML );
+ formula::FormulaGrammar::Grammar eGrammar = (bXML ?
+ rDoc.GetStorageGrammar() :
+ formula::FormulaGrammar::mapAPItoGrammar( bEnglish, bXML));
+
+ aAny <<= uno::Reference<sheet::XSheetConditionalEntries>(
+ new ScTableConditionalFormat( &rDoc, 0, aRanges[0].aStart.Tab(), eGrammar ));
+ }
+ break;
+ case SC_WID_UNO_VALIDAT:
+ case SC_WID_UNO_VALILOC:
+ case SC_WID_UNO_VALIXML:
+ {
+ bool bEnglish = ( pEntry->nWID != SC_WID_UNO_VALILOC );
+ bool bXML = ( pEntry->nWID == SC_WID_UNO_VALIXML );
+ formula::FormulaGrammar::Grammar eGrammar = (bXML ?
+ rDoc.GetStorageGrammar() :
+ formula::FormulaGrammar::mapAPItoGrammar( bEnglish, bXML));
+
+ aAny <<= uno::Reference<beans::XPropertySet>(
+ new ScTableValidationObj( rDoc, 0, eGrammar ));
+ }
+ break;
+ case SC_WID_UNO_NUMRULES:
+ {
+ aAny <<= ScStyleObj::CreateEmptyNumberingRules();
+ }
+ break;
+ }
+ }
+ }
+
+ return aAny;
+}
+
+// XPropertySet
+
+uno::Reference<beans::XPropertySetInfo> SAL_CALL ScCellRangesBase::getPropertySetInfo()
+{
+ SolarMutexGuard aGuard;
+ static uno::Reference<beans::XPropertySetInfo> aRef(
+ new SfxItemPropertySetInfo( pPropSet->getPropertyMap() ));
+ return aRef;
+}
+
+static void lcl_SetCellProperty( const SfxItemPropertyMapEntry& rEntry, const uno::Any& rValue,
+ ScPatternAttr& rPattern, const ScDocument &rDoc,
+ sal_uInt16& rFirstItemId, sal_uInt16& rSecondItemId )
+{
+ rFirstItemId = rEntry.nWID;
+ rSecondItemId = 0;
+
+ SfxItemSet& rSet = rPattern.GetItemSet();
+ switch ( rEntry.nWID )
+ {
+ case ATTR_VALUE_FORMAT:
+ {
+ // language for number formats
+ SvNumberFormatter* pFormatter = rDoc.GetFormatTable();
+ sal_uLong nOldFormat = rSet.Get( ATTR_VALUE_FORMAT ).GetValue();
+ LanguageType eOldLang = rSet.Get( ATTR_LANGUAGE_FORMAT ).GetLanguage();
+ nOldFormat = pFormatter->GetFormatForLanguageIfBuiltIn( nOldFormat, eOldLang );
+
+ sal_Int32 nIntVal = 0;
+ if ( !(rValue >>= nIntVal) )
+ throw lang::IllegalArgumentException();
+
+ sal_uLong nNewFormat = static_cast<sal_uLong>(nIntVal);
+ rSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNewFormat ) );
+
+ const SvNumberformat* pNewEntry = pFormatter->GetEntry( nNewFormat );
+ LanguageType eNewLang =
+ pNewEntry ? pNewEntry->GetLanguage() : LANGUAGE_DONTKNOW;
+ if ( eNewLang != eOldLang && eNewLang != LANGUAGE_DONTKNOW )
+ {
+ rSet.Put( SvxLanguageItem( eNewLang, ATTR_LANGUAGE_FORMAT ) );
+
+ // if only language is changed,
+ // don't touch number format attribute
+ sal_uLong nNewMod = nNewFormat % SV_COUNTRY_LANGUAGE_OFFSET;
+ if ( nNewMod == ( nOldFormat % SV_COUNTRY_LANGUAGE_OFFSET ) &&
+ nNewMod <= SV_MAX_COUNT_STANDARD_FORMATS )
+ {
+ rFirstItemId = 0; // don't use ATTR_VALUE_FORMAT value
+ }
+
+ rSecondItemId = ATTR_LANGUAGE_FORMAT;
+ }
+
+ }
+ break;
+ case ATTR_INDENT:
+ {
+ sal_Int16 nIntVal = 0;
+ if ( !(rValue >>= nIntVal) )
+ throw lang::IllegalArgumentException();
+
+ rSet.Put(ScIndentItem(o3tl::toTwips(nIntVal, o3tl::Length::mm100)));
+
+ }
+ break;
+ case ATTR_ROTATE_VALUE:
+ {
+ sal_Int32 nRotVal = 0;
+ if ( !(rValue >>= nRotVal) )
+ throw lang::IllegalArgumentException();
+
+ // stored value is always between 0 and 360 deg.
+ nRotVal %= 36000;
+ if ( nRotVal < 0 )
+ nRotVal += 36000;
+
+ rSet.Put( ScRotateValueItem( Degree100(nRotVal) ) );
+
+ }
+ break;
+ case ATTR_STACKED:
+ {
+ table::CellOrientation eOrient;
+ if( rValue >>= eOrient )
+ {
+ switch( eOrient )
+ {
+ case table::CellOrientation_STANDARD:
+ rSet.Put( ScVerticalStackCell( false ) );
+ break;
+ case table::CellOrientation_TOPBOTTOM:
+ rSet.Put( ScVerticalStackCell( false ) );
+ rSet.Put( ScRotateValueItem( 27000_deg100 ) );
+ rSecondItemId = ATTR_ROTATE_VALUE;
+ break;
+ case table::CellOrientation_BOTTOMTOP:
+ rSet.Put( ScVerticalStackCell( false ) );
+ rSet.Put( ScRotateValueItem( 9000_deg100 ) );
+ rSecondItemId = ATTR_ROTATE_VALUE;
+ break;
+ case table::CellOrientation_STACKED:
+ rSet.Put( ScVerticalStackCell( true ) );
+ break;
+ default:
+ {
+ // added to avoid warnings
+ }
+ }
+ }
+ }
+ break;
+ default:
+ {
+ lcl_GetCellsPropertySet()->setPropertyValue(rEntry, rValue, rSet);
+ }
+ }
+}
+
+void SAL_CALL ScCellRangesBase::setPropertyValue(
+ const OUString& aPropertyName, const uno::Any& aValue )
+{
+ SolarMutexGuard aGuard;
+
+ if ( !pDocShell || aRanges.empty() )
+ throw uno::RuntimeException();
+
+ const SfxItemPropertyMap& rPropertyMap = GetItemPropertyMap(); // from derived class
+ const SfxItemPropertyMapEntry* pEntry = rPropertyMap.getByName( aPropertyName );
+ if ( !pEntry )
+ throw beans::UnknownPropertyException(aPropertyName);
+
+ SetOnePropertyValue( pEntry, aValue );
+}
+
+void ScCellRangesBase::SetOnePropertyValue( const SfxItemPropertyMapEntry* pEntry, const uno::Any& aValue )
+{
+ if ( !pEntry )
+ return;
+
+ if ( IsScItemWid( pEntry->nWID ) )
+ {
+ if ( !aRanges.empty() ) // empty = nothing to do
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+
+ // For parts of compound items with multiple properties (e.g. background)
+ // the old item has to be first fetched from the document.
+ //! But we can't recognize this case here
+ //! -> an extra flag in PropertyMap entry, or something like that???
+ //! fetch the item directly from its position in the range?
+ // ClearInvalidItems, so that in any case we have an item with the correct type
+
+ ScPatternAttr aPattern( *GetCurrentAttrsDeep() );
+ SfxItemSet& rSet = aPattern.GetItemSet();
+ rSet.ClearInvalidItems();
+
+ sal_uInt16 nFirstItem, nSecondItem;
+ lcl_SetCellProperty( *pEntry, aValue, aPattern, rDoc, nFirstItem, nSecondItem );
+
+ for (sal_uInt16 nWhich = ATTR_PATTERN_START; nWhich <= ATTR_PATTERN_END; nWhich++)
+ if ( nWhich != nFirstItem && nWhich != nSecondItem )
+ rSet.ClearItem(nWhich);
+
+ pDocShell->GetDocFunc().ApplyAttributes( *GetMarkData(), aPattern, true );
+ }
+ }
+ else // implemented here
+ switch ( pEntry->nWID )
+ {
+ case EE_CHAR_ESCAPEMENT: // Specifically for xlsx import
+ {
+ sal_Int32 nValue = 0;
+ aValue >>= nValue;
+ if (nValue)
+ {
+ for (size_t i = 0, n = aRanges.size(); i < n; ++i)
+ {
+ ScRange const & rRange = aRanges[i];
+
+ /* TODO: Iterate through the range */
+ ScAddress aAddr = rRange.aStart;
+ ScDocument& rDoc = pDocShell->GetDocument();
+ ScRefCellValue aCell(rDoc, aAddr);
+
+ OUString aStr = aCell.getString(&rDoc);
+ EditEngine aEngine( rDoc.GetEnginePool() );
+ aEngine.SetEditTextObjectPool(rDoc.GetEditPool());
+
+ /* EE_CHAR_ESCAPEMENT seems to be set on the cell _only_ when
+ * there are no other attribs for the cell.
+ * So, it is safe to overwrite the complete attribute set.
+ * If there is a need - getting CellType and processing
+ * the attributes could be considered.
+ */
+ SfxItemSet aAttr = aEngine.GetEmptyItemSet();
+ aEngine.SetText(aStr);
+ if( nValue < 0 ) // Subscript
+ aAttr.Put( SvxEscapementItem( SvxEscapement::Subscript, EE_CHAR_ESCAPEMENT ) );
+ else // Superscript
+ aAttr.Put( SvxEscapementItem( SvxEscapement::Superscript, EE_CHAR_ESCAPEMENT ) );
+ aEngine.QuickSetAttribs(aAttr, ESelection(0, 0, 0, aStr.getLength()));
+
+ // The cell will own the text object instance.
+ rDoc.SetEditText(aRanges[0].aStart, aEngine.CreateTextObject());
+ }
+ }
+ }
+ break;
+ case SC_WID_UNO_CHCOLHDR:
+ // chart header flags are set for this object, not stored with document
+ bChartColAsHdr = ScUnoHelpFunctions::GetBoolFromAny( aValue );
+ break;
+ case SC_WID_UNO_CHROWHDR:
+ bChartRowAsHdr = ScUnoHelpFunctions::GetBoolFromAny( aValue );
+ break;
+ case SC_WID_UNO_CELLSTYL:
+ {
+ OUString aStrVal;
+ aValue >>= aStrVal;
+ OUString aString(ScStyleNameConversion::ProgrammaticToDisplayName(
+ aStrVal, SfxStyleFamily::Para ));
+ pDocShell->GetDocFunc().ApplyStyle( *GetMarkData(), aString, true );
+ }
+ break;
+ case SC_WID_UNO_TBLBORD:
+ {
+ table::TableBorder aBorder;
+ if ( !aRanges.empty() && ( aValue >>= aBorder ) ) // empty = nothing to do
+ {
+ SvxBoxItem aOuter(ATTR_BORDER);
+ SvxBoxInfoItem aInner(ATTR_BORDER_INNER);
+ ScHelperFunctions::FillBoxItems( aOuter, aInner, aBorder );
+
+ ScHelperFunctions::ApplyBorder( pDocShell, aRanges, aOuter, aInner ); //! docfunc
+ }
+ }
+ break;
+ case SC_WID_UNO_TBLBORD2:
+ {
+ table::TableBorder2 aBorder2;
+ if ( !aRanges.empty() && ( aValue >>= aBorder2 ) ) // empty = nothing to do
+ {
+ SvxBoxItem aOuter(ATTR_BORDER);
+ SvxBoxInfoItem aInner(ATTR_BORDER_INNER);
+ ScHelperFunctions::FillBoxItems( aOuter, aInner, aBorder2 );
+
+ ScHelperFunctions::ApplyBorder( pDocShell, aRanges, aOuter, aInner ); //! docfunc
+ }
+ }
+ break;
+ case SC_WID_UNO_CONDFMT:
+ case SC_WID_UNO_CONDLOC:
+ case SC_WID_UNO_CONDXML:
+ {
+ uno::Reference<sheet::XSheetConditionalEntries> xInterface(aValue, uno::UNO_QUERY);
+ if ( !aRanges.empty() && xInterface.is() ) // empty = nothing to do
+ {
+ ScTableConditionalFormat* pFormat =
+ comphelper::getFromUnoTunnel<ScTableConditionalFormat>( xInterface );
+ if (pFormat)
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+ bool bEnglish = ( pEntry->nWID != SC_WID_UNO_CONDLOC );
+ bool bXML = ( pEntry->nWID == SC_WID_UNO_CONDXML );
+ formula::FormulaGrammar::Grammar eGrammar = (bXML ?
+ formula::FormulaGrammar::GRAM_UNSPECIFIED :
+ formula::FormulaGrammar::mapAPItoGrammar( bEnglish, bXML));
+
+ SCTAB nTab = aRanges.front().aStart.Tab();
+ // To remove conditional formats for all cells in aRanges we need to:
+ // Remove conditional format data from cells' attributes
+ rDoc.RemoveCondFormatData( aRanges, nTab, 0 );
+ // And also remove ranges from conditional formats list
+ for (size_t i = 0; i < aRanges.size(); ++i)
+ {
+ rDoc.GetCondFormList( aRanges[i].aStart.Tab() )->DeleteArea(
+ aRanges[i].aStart.Col(), aRanges[i].aStart.Row(),
+ aRanges[i].aEnd.Col(), aRanges[i].aEnd.Row() );
+ }
+
+ // Then we can apply new conditional format if there is one
+ if (pFormat->getCount())
+ {
+ auto pNew = std::make_unique<ScConditionalFormat>( 0, &rDoc ); // Index will be set on inserting
+ pFormat->FillFormat( *pNew, rDoc, eGrammar );
+ pNew->SetRange( aRanges );
+ pDocShell->GetDocFunc().ReplaceConditionalFormat( 0, std::move(pNew), nTab, aRanges );
+ }
+
+ // and repaint
+ for (size_t i = 0; i < aRanges.size(); ++i)
+ pDocShell->PostPaint(aRanges[i], PaintPartFlags::Grid);
+ pDocShell->SetDocumentModified();
+ }
+ }
+ }
+ break;
+ case SC_WID_UNO_VALIDAT:
+ case SC_WID_UNO_VALILOC:
+ case SC_WID_UNO_VALIXML:
+ {
+ uno::Reference<beans::XPropertySet> xInterface(aValue, uno::UNO_QUERY);
+ if ( !aRanges.empty() && xInterface.is() ) // empty = nothing to do
+ {
+ ScTableValidationObj* pValidObj =
+ comphelper::getFromUnoTunnel<ScTableValidationObj>( xInterface );
+ if (pValidObj)
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+ bool bEnglish = ( pEntry->nWID != SC_WID_UNO_VALILOC );
+ bool bXML = ( pEntry->nWID == SC_WID_UNO_VALIXML );
+ formula::FormulaGrammar::Grammar eGrammar = (bXML ?
+ formula::FormulaGrammar::GRAM_UNSPECIFIED :
+ formula::FormulaGrammar::mapAPItoGrammar( bEnglish, bXML));
+
+ std::unique_ptr<ScValidationData> pNewData(
+ pValidObj->CreateValidationData( rDoc, eGrammar ));
+ sal_uLong nIndex = rDoc.AddValidationEntry( *pNewData );
+ pNewData.reset();
+
+ ScPatternAttr aPattern( rDoc.GetPool() );
+ aPattern.GetItemSet().Put( SfxUInt32Item( ATTR_VALIDDATA, nIndex ) );
+ pDocShell->GetDocFunc().ApplyAttributes( *GetMarkData(), aPattern, true );
+ }
+ }
+ }
+ break;
+ // SC_WID_UNO_NUMRULES is ignored...
+ }
+}
+
+uno::Any SAL_CALL ScCellRangesBase::getPropertyValue( const OUString& aPropertyName )
+{
+ SolarMutexGuard aGuard;
+
+ if ( !pDocShell || aRanges.empty() )
+ throw uno::RuntimeException();
+
+ const SfxItemPropertyMap& rPropertyMap = GetItemPropertyMap(); // from derived class
+ const SfxItemPropertyMapEntry* pEntry = rPropertyMap.getByName( aPropertyName );
+ if ( !pEntry )
+ throw beans::UnknownPropertyException(aPropertyName);
+
+ uno::Any aAny;
+ GetOnePropertyValue( pEntry, aAny );
+ return aAny;
+}
+
+void ScCellRangesBase::GetOnePropertyValue( const SfxItemPropertyMapEntry* pEntry, uno::Any& rAny )
+{
+ if ( !pEntry )
+ return;
+
+ if ( IsScItemWid( pEntry->nWID ) )
+ {
+ SfxItemSet* pDataSet = GetCurrentDataSet();
+ if ( pDataSet )
+ {
+ switch ( pEntry->nWID ) // for special handling of items
+ {
+ case ATTR_VALUE_FORMAT:
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+
+ sal_uLong nOldFormat =
+ pDataSet->Get( ATTR_VALUE_FORMAT ).GetValue();
+ LanguageType eOldLang =
+ pDataSet->Get( ATTR_LANGUAGE_FORMAT ).GetLanguage();
+ nOldFormat = rDoc.GetFormatTable()->
+ GetFormatForLanguageIfBuiltIn( nOldFormat, eOldLang );
+ rAny <<= static_cast<sal_Int32>(nOldFormat);
+ }
+ break;
+ case ATTR_INDENT:
+ rAny <<= static_cast<sal_Int16>( convertTwipToMm100(static_cast<const ScIndentItem&>(
+ pDataSet->Get(pEntry->nWID)).GetValue()) );
+ break;
+ case ATTR_STACKED:
+ {
+ Degree100 nRot = pDataSet->Get(ATTR_ROTATE_VALUE).GetValue();
+ bool bStacked = static_cast<const ScVerticalStackCell&>(pDataSet->Get(pEntry->nWID)).GetValue();
+ SvxOrientationItem( nRot, bStacked, TypedWhichId<SvxOrientationItem>(0) ).QueryValue( rAny );
+ }
+ break;
+ default:
+ pPropSet->getPropertyValue(*pEntry, *pDataSet, rAny);
+ }
+ }
+ }
+ else // implemented here
+ switch ( pEntry->nWID )
+ {
+ case SC_WID_UNO_CHCOLHDR:
+ rAny <<= bChartColAsHdr;
+ break;
+ case SC_WID_UNO_CHROWHDR:
+ rAny <<= bChartRowAsHdr;
+ break;
+ case SC_WID_UNO_CELLSTYL:
+ {
+ OUString aStyleName;
+ const ScStyleSheet* pStyle = pDocShell->GetDocument().GetSelectionStyle(*GetMarkData());
+ if (pStyle)
+ aStyleName = pStyle->GetName();
+ rAny <<= ScStyleNameConversion::DisplayToProgrammaticName(
+ aStyleName, SfxStyleFamily::Para );
+ }
+ break;
+ case SC_WID_UNO_TBLBORD:
+ case SC_WID_UNO_TBLBORD2:
+ {
+ //! loop through all ranges
+ if ( !aRanges.empty() )
+ {
+ const ScRange & rFirst = aRanges[ 0 ];
+ SvxBoxItem aOuter(ATTR_BORDER);
+ SvxBoxInfoItem aInner(ATTR_BORDER_INNER);
+
+ ScDocument& rDoc = pDocShell->GetDocument();
+ ScMarkData aMark(rDoc.GetSheetLimits());
+ aMark.SetMarkArea( rFirst );
+ aMark.SelectTable( rFirst.aStart.Tab(), true );
+ rDoc.GetSelectionFrame( aMark, aOuter, aInner );
+
+ if (pEntry->nWID == SC_WID_UNO_TBLBORD2)
+ ScHelperFunctions::AssignTableBorder2ToAny( rAny, aOuter, aInner);
+ else
+ ScHelperFunctions::AssignTableBorderToAny( rAny, aOuter, aInner);
+ }
+ }
+ break;
+ case SC_WID_UNO_CONDFMT:
+ case SC_WID_UNO_CONDLOC:
+ case SC_WID_UNO_CONDXML:
+ {
+ const ScPatternAttr* pPattern = GetCurrentAttrsDeep();
+ if ( pPattern )
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+ bool bEnglish = ( pEntry->nWID != SC_WID_UNO_CONDLOC );
+ bool bXML = ( pEntry->nWID == SC_WID_UNO_CONDXML );
+ formula::FormulaGrammar::Grammar eGrammar = (bXML ?
+ rDoc.GetStorageGrammar() :
+ formula::FormulaGrammar::mapAPItoGrammar( bEnglish, bXML));
+ const ScCondFormatIndexes& rIndex =
+ pPattern->GetItem(ATTR_CONDITIONAL).GetCondFormatData();
+ sal_uLong nIndex = 0;
+ if(!rIndex.empty())
+ nIndex = rIndex[0];
+ rAny <<= uno::Reference<sheet::XSheetConditionalEntries>(
+ new ScTableConditionalFormat( &rDoc, nIndex, aRanges.front().aStart.Tab(), eGrammar ));
+ }
+ }
+ break;
+ case SC_WID_UNO_VALIDAT:
+ case SC_WID_UNO_VALILOC:
+ case SC_WID_UNO_VALIXML:
+ {
+ const ScPatternAttr* pPattern = GetCurrentAttrsDeep();
+ if ( pPattern )
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+ bool bEnglish = ( pEntry->nWID != SC_WID_UNO_VALILOC );
+ bool bXML = ( pEntry->nWID == SC_WID_UNO_VALIXML );
+ formula::FormulaGrammar::Grammar eGrammar = (bXML ?
+ rDoc.GetStorageGrammar() :
+ formula::FormulaGrammar::mapAPItoGrammar( bEnglish, bXML));
+ sal_uLong nIndex =
+ pPattern->GetItem(ATTR_VALIDDATA).GetValue();
+ rAny <<= uno::Reference<beans::XPropertySet>(
+ new ScTableValidationObj( rDoc, nIndex, eGrammar ));
+ }
+ }
+ break;
+ case SC_WID_UNO_NUMRULES:
+ {
+ // always return empty numbering rules object
+ rAny <<= ScStyleObj::CreateEmptyNumberingRules();
+ }
+ break;
+ case SC_WID_UNO_ABSNAME:
+ {
+ OUString sRet;
+ aRanges.Format(sRet, ScRefFlags::RANGE_ABS_3D, pDocShell->GetDocument());
+ rAny <<= sRet;
+ }
+ break;
+ case SC_WID_UNO_FORMATID:
+ {
+ const ScPatternAttr* pPattern = GetCurrentAttrsFlat();
+ rAny <<= pPattern->GetKey();
+ }
+ break;
+ }
+}
+
+void SAL_CALL ScCellRangesBase::addPropertyChangeListener( const OUString& /* aPropertyName */,
+ const uno::Reference<beans::XPropertyChangeListener>& /* aListener */)
+{
+ SolarMutexGuard aGuard;
+ if ( aRanges.empty() )
+ throw uno::RuntimeException();
+
+ OSL_FAIL("not implemented");
+}
+
+void SAL_CALL ScCellRangesBase::removePropertyChangeListener( const OUString& /* aPropertyName */,
+ const uno::Reference<beans::XPropertyChangeListener>& /* aListener */)
+{
+ SolarMutexGuard aGuard;
+ if ( aRanges.empty() )
+ throw uno::RuntimeException();
+
+ OSL_FAIL("not implemented");
+}
+
+void SAL_CALL ScCellRangesBase::addVetoableChangeListener( const OUString&,
+ const uno::Reference<beans::XVetoableChangeListener>&)
+{
+ OSL_FAIL("not implemented");
+}
+
+void SAL_CALL ScCellRangesBase::removeVetoableChangeListener( const OUString&,
+ const uno::Reference<beans::XVetoableChangeListener>&)
+{
+ OSL_FAIL("not implemented");
+}
+
+// XMultiPropertySet
+
+void SAL_CALL ScCellRangesBase::setPropertyValues( const uno::Sequence< OUString >& aPropertyNames,
+ const uno::Sequence< uno::Any >& aValues )
+{
+ SolarMutexGuard aGuard;
+
+ sal_Int32 nCount(aPropertyNames.getLength());
+ sal_Int32 nValues(aValues.getLength());
+ if (nCount != nValues)
+ throw lang::IllegalArgumentException();
+
+ if ( !(pDocShell && nCount) )
+ return;
+
+ const SfxItemPropertyMap& rPropertyMap = GetItemPropertyMap(); // from derived class
+ const OUString* pNames = aPropertyNames.getConstArray();
+ const uno::Any* pValues = aValues.getConstArray();
+
+ std::unique_ptr<const SfxItemPropertyMapEntry*[]> pEntryArray(new const SfxItemPropertyMapEntry*[nCount]);
+
+ sal_Int32 i;
+ for(i = 0; i < nCount; i++)
+ {
+ // first loop: find all properties in map, but handle only CellStyle
+ // (CellStyle must be set before any other cell properties)
+
+ const SfxItemPropertyMapEntry* pEntry = rPropertyMap.getByName( pNames[i] );
+ pEntryArray[i] = pEntry;
+ if (pEntry)
+ {
+ if ( pEntry->nWID == SC_WID_UNO_CELLSTYL )
+ {
+ try
+ {
+ SetOnePropertyValue( pEntry, pValues[i] );
+ }
+ catch ( lang::IllegalArgumentException& )
+ {
+ TOOLS_WARN_EXCEPTION( "sc", "exception when setting cell style"); // not supposed to happen
+ }
+ }
+ }
+ }
+
+ ScDocument& rDoc = pDocShell->GetDocument();
+ std::unique_ptr<ScPatternAttr> pOldPattern;
+ std::unique_ptr<ScPatternAttr> pNewPattern;
+
+ for(i = 0; i < nCount; i++)
+ {
+ // second loop: handle other properties
+
+ const SfxItemPropertyMapEntry* pEntry = pEntryArray[i];
+ if ( pEntry )
+ {
+ if ( IsScItemWid( pEntry->nWID ) ) // can be handled by SfxItemPropertySet
+ {
+ if ( !pOldPattern )
+ {
+ pOldPattern.reset(new ScPatternAttr( *GetCurrentAttrsDeep() ));
+ pOldPattern->GetItemSet().ClearInvalidItems();
+ pNewPattern.reset(new ScPatternAttr( rDoc.GetPool() ));
+ }
+
+ // collect items in pNewPattern, apply with one call after the loop
+
+ sal_uInt16 nFirstItem, nSecondItem;
+ lcl_SetCellProperty( *pEntry, pValues[i], *pOldPattern, rDoc, nFirstItem, nSecondItem );
+
+ // put only affected items into new set
+ if ( nFirstItem )
+ pNewPattern->GetItemSet().Put( pOldPattern->GetItemSet().Get( nFirstItem ) );
+ if ( nSecondItem )
+ pNewPattern->GetItemSet().Put( pOldPattern->GetItemSet().Get( nSecondItem ) );
+ }
+ else if ( pEntry->nWID != SC_WID_UNO_CELLSTYL ) // CellStyle is handled above
+ {
+ // call virtual method to set a single property
+ SetOnePropertyValue( pEntry, pValues[i] );
+ }
+ }
+ }
+
+ if ( pNewPattern && !aRanges.empty() )
+ pDocShell->GetDocFunc().ApplyAttributes( *GetMarkData(), *pNewPattern, true );
+}
+
+uno::Sequence<uno::Any> SAL_CALL ScCellRangesBase::getPropertyValues(
+ const uno::Sequence< OUString >& aPropertyNames )
+{
+ SolarMutexGuard aGuard;
+
+ const SfxItemPropertyMap& rPropertyMap = GetItemPropertyMap(); // from derived class
+
+ uno::Sequence<uno::Any> aRet(aPropertyNames.getLength());
+ uno::Any* pProperties = aRet.getArray();
+ for(sal_Int32 i = 0; i < aPropertyNames.getLength(); i++)
+ {
+ const SfxItemPropertyMapEntry* pEntry = rPropertyMap.getByName( aPropertyNames[i] );
+ GetOnePropertyValue( pEntry, pProperties[i] );
+ }
+ return aRet;
+}
+
+void SAL_CALL ScCellRangesBase::addPropertiesChangeListener( const uno::Sequence< OUString >& /* aPropertyNames */,
+ const uno::Reference< beans::XPropertiesChangeListener >& /* xListener */ )
+{
+ OSL_FAIL("not implemented");
+}
+
+void SAL_CALL ScCellRangesBase::removePropertiesChangeListener( const uno::Reference< beans::XPropertiesChangeListener >& /* xListener */ )
+{
+ OSL_FAIL("not implemented");
+}
+
+void SAL_CALL ScCellRangesBase::firePropertiesChangeEvent( const uno::Sequence< OUString >& /* aPropertyNames */,
+ const uno::Reference< beans::XPropertiesChangeListener >& /* xListener */ )
+{
+ OSL_FAIL("not implemented");
+}
+
+IMPL_LINK( ScCellRangesBase, ValueListenerHdl, const SfxHint&, rHint, void )
+{
+ if ( pDocShell && (rHint.GetId() == SfxHintId::ScDataChanged))
+ {
+ // This may be called several times for a single change, if several formulas
+ // in the range are notified. So only a flag is set that is checked when
+ // SfxHintId::DataChanged is received.
+
+ bGotDataChangedHint = true;
+ }
+}
+
+// XTolerantMultiPropertySet
+uno::Sequence< beans::SetPropertyTolerantFailed > SAL_CALL ScCellRangesBase::setPropertyValuesTolerant( const uno::Sequence< OUString >& aPropertyNames,
+ const uno::Sequence< uno::Any >& aValues )
+{
+ SolarMutexGuard aGuard;
+
+ sal_Int32 nCount(aPropertyNames.getLength());
+ sal_Int32 nValues(aValues.getLength());
+ if (nCount != nValues)
+ throw lang::IllegalArgumentException();
+
+ if ( pDocShell && nCount )
+ {
+ uno::Sequence < beans::SetPropertyTolerantFailed > aReturns(nCount);
+ beans::SetPropertyTolerantFailed* pReturns = aReturns.getArray();
+
+ const SfxItemPropertyMap& rPropertyMap = GetItemPropertyMap(); // from derived class
+ const OUString* pNames = aPropertyNames.getConstArray();
+ const uno::Any* pValues = aValues.getConstArray();
+
+ std::unique_ptr<const SfxItemPropertyMapEntry*[]> pMapArray(new const SfxItemPropertyMapEntry*[nCount]);
+
+ sal_Int32 i;
+ for(i = 0; i < nCount; i++)
+ {
+ // first loop: find all properties in map, but handle only CellStyle
+ // (CellStyle must be set before any other cell properties)
+
+ const SfxItemPropertyMapEntry* pEntry = rPropertyMap.getByName( pNames[i] );
+ pMapArray[i] = pEntry;
+ if (pEntry)
+ {
+ if ( pEntry->nWID == SC_WID_UNO_CELLSTYL )
+ {
+ try
+ {
+ SetOnePropertyValue( pEntry, pValues[i] );
+ }
+ catch ( lang::IllegalArgumentException& )
+ {
+ TOOLS_WARN_EXCEPTION( "sc", "exception when setting cell style"); // not supposed to happen
+ }
+ }
+ }
+ }
+
+ ScDocument& rDoc = pDocShell->GetDocument();
+ std::unique_ptr<ScPatternAttr> pOldPattern;
+ std::unique_ptr<ScPatternAttr> pNewPattern;
+
+ sal_Int32 nFailed(0);
+ for(i = 0; i < nCount; i++)
+ {
+ // second loop: handle other properties
+
+ const SfxItemPropertyMapEntry* pEntry = pMapArray[i];
+ if ( pEntry && ((pEntry->nFlags & beans::PropertyAttribute::READONLY) == 0))
+ {
+ if ( IsScItemWid( pEntry->nWID ) ) // can be handled by SfxItemPropertySet
+ {
+ if ( !pOldPattern )
+ {
+ pOldPattern.reset(new ScPatternAttr( *GetCurrentAttrsDeep() ));
+ pOldPattern->GetItemSet().ClearInvalidItems();
+ pNewPattern.reset(new ScPatternAttr( rDoc.GetPool() ));
+ }
+
+ // collect items in pNewPattern, apply with one call after the loop
+ try
+ {
+ sal_uInt16 nFirstItem, nSecondItem;
+ lcl_SetCellProperty( *pEntry, pValues[i], *pOldPattern, rDoc, nFirstItem, nSecondItem );
+
+ // put only affected items into new set
+ if ( nFirstItem )
+ pNewPattern->GetItemSet().Put( pOldPattern->GetItemSet().Get( nFirstItem ) );
+ if ( nSecondItem )
+ pNewPattern->GetItemSet().Put( pOldPattern->GetItemSet().Get( nSecondItem ) );
+ }
+ catch ( lang::IllegalArgumentException& )
+ {
+ pReturns[nFailed].Name = pNames[i];
+ pReturns[nFailed++].Result = beans::TolerantPropertySetResultType::ILLEGAL_ARGUMENT;
+ }
+ }
+ else if ( pEntry->nWID != SC_WID_UNO_CELLSTYL ) // CellStyle is handled above
+ {
+ // call virtual method to set a single property
+ try
+ {
+ SetOnePropertyValue( pEntry, pValues[i] );
+ }
+ catch ( lang::IllegalArgumentException& )
+ {
+ pReturns[nFailed].Name = pNames[i];
+ pReturns[nFailed++].Result = beans::TolerantPropertySetResultType::ILLEGAL_ARGUMENT;
+ }
+ }
+ }
+ else
+ {
+ pReturns[nFailed].Name = pNames[i];
+ if (pEntry)
+ pReturns[nFailed++].Result = beans::TolerantPropertySetResultType::PROPERTY_VETO;
+ else
+ pReturns[nFailed++].Result = beans::TolerantPropertySetResultType::UNKNOWN_PROPERTY;
+ }
+ }
+
+ if ( pNewPattern && !aRanges.empty() )
+ pDocShell->GetDocFunc().ApplyAttributes( *GetMarkData(), *pNewPattern, true );
+
+ aReturns.realloc(nFailed);
+
+ return aReturns;
+ }
+ return uno::Sequence < beans::SetPropertyTolerantFailed >();
+}
+
+uno::Sequence< beans::GetPropertyTolerantResult > SAL_CALL ScCellRangesBase::getPropertyValuesTolerant( const uno::Sequence< OUString >& aPropertyNames )
+{
+ SolarMutexGuard aGuard;
+
+ sal_Int32 nCount(aPropertyNames.getLength());
+ uno::Sequence < beans::GetPropertyTolerantResult > aReturns(nCount);
+ beans::GetPropertyTolerantResult* pReturns = aReturns.getArray();
+
+ const SfxItemPropertyMap& rPropertyMap = GetItemPropertyMap(); // from derived class
+
+ for(sal_Int32 i = 0; i < nCount; i++)
+ {
+ const SfxItemPropertyMapEntry* pEntry = rPropertyMap.getByName( aPropertyNames[i] );
+ if (!pEntry)
+ {
+ pReturns[i].Result = beans::TolerantPropertySetResultType::UNKNOWN_PROPERTY;
+ }
+ else
+ {
+ sal_uInt16 nItemWhich = 0;
+ lcl_GetPropertyWhich( pEntry, nItemWhich );
+ pReturns[i].State = GetOnePropertyState( nItemWhich, pEntry );
+ GetOnePropertyValue( pEntry, pReturns[i].Value );
+ pReturns[i].Result = beans::TolerantPropertySetResultType::SUCCESS;
+ }
+ }
+ return aReturns;
+}
+
+uno::Sequence< beans::GetDirectPropertyTolerantResult > SAL_CALL ScCellRangesBase::getDirectPropertyValuesTolerant( const uno::Sequence< OUString >& aPropertyNames )
+{
+ SolarMutexGuard aGuard;
+
+ sal_Int32 nCount(aPropertyNames.getLength());
+ uno::Sequence < beans::GetDirectPropertyTolerantResult > aReturns(nCount);
+ beans::GetDirectPropertyTolerantResult* pReturns = aReturns.getArray();
+
+ const SfxItemPropertyMap& rPropertyMap = GetItemPropertyMap(); // from derived class
+
+ sal_Int32 j = 0;
+ for(sal_Int32 i = 0; i < nCount; i++)
+ {
+ const SfxItemPropertyMapEntry* pEntry = rPropertyMap.getByName( aPropertyNames[i] );
+ if (!pEntry)
+ {
+ pReturns[i].Result = beans::TolerantPropertySetResultType::UNKNOWN_PROPERTY;
+ }
+ else
+ {
+ sal_uInt16 nItemWhich = 0;
+ lcl_GetPropertyWhich( pEntry, nItemWhich );
+ pReturns[j].State = GetOnePropertyState( nItemWhich, pEntry );
+ if (pReturns[j].State == beans::PropertyState_DIRECT_VALUE)
+ {
+ GetOnePropertyValue( pEntry, pReturns[j].Value );
+ pReturns[j].Result = beans::TolerantPropertySetResultType::SUCCESS;
+ pReturns[j].Name = aPropertyNames[i];
+ ++j;
+ }
+ }
+ }
+ if (j < nCount)
+ aReturns.realloc(j);
+ return aReturns;
+}
+
+// XIndent
+
+void SAL_CALL ScCellRangesBase::decrementIndent()
+{
+ SolarMutexGuard aGuard;
+ if ( pDocShell && !aRanges.empty() )
+ {
+ //#97041#; put only MultiMarked ScMarkData in ChangeIndent
+ ScMarkData aMarkData(*GetMarkData());
+ aMarkData.MarkToMulti();
+ pDocShell->GetDocFunc().ChangeIndent( aMarkData, false, true );
+ }
+}
+
+void SAL_CALL ScCellRangesBase::incrementIndent()
+{
+ SolarMutexGuard aGuard;
+ if ( pDocShell && !aRanges.empty() )
+ {
+ //#97041#; put only MultiMarked ScMarkData in ChangeIndent
+ ScMarkData aMarkData(*GetMarkData());
+ aMarkData.MarkToMulti();
+ pDocShell->GetDocFunc().ChangeIndent( aMarkData, true, true );
+ }
+}
+
+// XChartData
+
+std::unique_ptr<ScMemChart> ScCellRangesBase::CreateMemChart_Impl() const
+{
+ if ( pDocShell && !aRanges.empty() )
+ {
+ ScRangeListRef xChartRanges;
+ if ( aRanges.size() == 1 )
+ {
+ // set useful table limit (only occupied data area)
+ // (only here - Listeners are registered for the whole area)
+ //! check immediately if a ScTableSheetObj?
+
+ const ScDocument & rDoc = pDocShell->GetDocument();
+ const ScRange & rRange = aRanges[0];
+ if ( rRange.aStart.Col() == 0 && rRange.aEnd.Col() == rDoc.MaxCol() &&
+ rRange.aStart.Row() == 0 && rRange.aEnd.Row() == rDoc.MaxRow() )
+ {
+ SCTAB nTab = rRange.aStart.Tab();
+
+ SCCOL nStartX;
+ SCROW nStartY; // Get start
+ if (!pDocShell->GetDocument().GetDataStart( nTab, nStartX, nStartY ))
+ {
+ nStartX = 0;
+ nStartY = 0;
+ }
+
+ SCCOL nEndX;
+ SCROW nEndY; // Get end
+ if (!pDocShell->GetDocument().GetTableArea( nTab, nEndX, nEndY ))
+ {
+ nEndX = 0;
+ nEndY = 0;
+ }
+
+ xChartRanges = new ScRangeList( ScRange( nStartX, nStartY, nTab, nEndX, nEndY, nTab ) );
+ }
+ }
+ if (!xChartRanges.is()) // otherwise take Ranges directly
+ xChartRanges = new ScRangeList(aRanges);
+ ScChartArray aArr( pDocShell->GetDocument(), xChartRanges );
+
+ // RowAsHdr = ColHeaders and vice versa
+ aArr.SetHeaders( bChartRowAsHdr, bChartColAsHdr );
+
+ return aArr.CreateMemChart();
+ }
+ return nullptr;
+}
+
+uno::Sequence< uno::Sequence<double> > SAL_CALL ScCellRangesBase::getData()
+{
+ SolarMutexGuard aGuard;
+ std::unique_ptr<ScMemChart> pMemChart(CreateMemChart_Impl());
+ if ( pMemChart )
+ {
+ sal_Int32 nColCount = pMemChart->GetColCount();
+ sal_Int32 nRowCount = static_cast<sal_Int32>(pMemChart->GetRowCount());
+
+ uno::Sequence< uno::Sequence<double> > aRowSeq( nRowCount );
+ uno::Sequence<double>* pRowAry = aRowSeq.getArray();
+ for (sal_Int32 nRow = 0; nRow < nRowCount; nRow++)
+ {
+ uno::Sequence<double> aColSeq( nColCount );
+ double* pColAry = aColSeq.getArray();
+ for (sal_Int32 nCol = 0; nCol < nColCount; nCol++)
+ pColAry[nCol] = pMemChart->GetData( nCol, nRow );
+
+ pRowAry[nRow] = aColSeq;
+ }
+
+ return aRowSeq;
+ }
+
+ return {};
+}
+
+ScRangeListRef ScCellRangesBase::GetLimitedChartRanges_Impl( sal_Int32 nDataColumns, sal_Int32 nDataRows ) const
+{
+ if ( aRanges.size() == 1 )
+ {
+ const ScDocument & rDoc = pDocShell->GetDocument();
+ const ScRange & rRange = aRanges[0];
+ if ( rRange.aStart.Col() == 0 && rRange.aEnd.Col() == rDoc.MaxCol() &&
+ rRange.aStart.Row() == 0 && rRange.aEnd.Row() == rDoc.MaxRow() )
+ {
+ // if aRanges is a complete sheet, limit to given size
+
+ SCTAB nTab = rRange.aStart.Tab();
+
+ sal_Int32 nEndColumn = nDataColumns - 1 + ( bChartColAsHdr ? 1 : 0 );
+ if ( nEndColumn < 0 )
+ nEndColumn = 0;
+ if ( nEndColumn > rDoc.MaxCol() )
+ nEndColumn = rDoc.MaxCol();
+
+ sal_Int32 nEndRow = nDataRows - 1 + ( bChartRowAsHdr ? 1 : 0 );
+ if ( nEndRow < 0 )
+ nEndRow = 0;
+ if ( nEndRow > rDoc.MaxRow() )
+ nEndRow = rDoc.MaxRow();
+
+ ScRangeListRef xChartRanges = new ScRangeList( ScRange( 0, 0, nTab, static_cast<SCCOL>(nEndColumn), static_cast<SCROW>(nEndRow), nTab ) );
+ return xChartRanges;
+ }
+ }
+
+ return new ScRangeList(aRanges); // as-is
+}
+
+void SAL_CALL ScCellRangesBase::setData( const uno::Sequence< uno::Sequence<double> >& aData )
+{
+ SolarMutexGuard aGuard;
+ bool bDone = false;
+ sal_Int32 nRowCount = aData.getLength();
+ sal_Int32 nColCount = nRowCount ? aData[0].getLength() : 0;
+ ScRangeListRef xChartRanges = GetLimitedChartRanges_Impl( nColCount, nRowCount );
+ if ( pDocShell && xChartRanges.is() )
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+ ScChartArray aArr( rDoc, xChartRanges );
+ aArr.SetHeaders( bChartRowAsHdr, bChartColAsHdr ); // RowAsHdr = ColHeaders
+ const ScChartPositionMap* pPosMap = aArr.GetPositionMap();
+ if (pPosMap)
+ {
+ if ( pPosMap->GetColCount() == static_cast<SCCOL>(nColCount) &&
+ pPosMap->GetRowCount() == static_cast<SCROW>(nRowCount) )
+ {
+ for (sal_Int32 nRow=0; nRow<nRowCount; nRow++)
+ {
+ const uno::Sequence<double>& rRowSeq = aData[nRow];
+ const double* pArray = rRowSeq.getConstArray();
+ nColCount = rRowSeq.getLength();
+ for (sal_Int32 nCol=0; nCol<nColCount; nCol++)
+ {
+ const ScAddress* pPos = pPosMap->GetPosition(
+ sal::static_int_cast<SCCOL>(nCol),
+ sal::static_int_cast<SCROW>(nRow) );
+ if (pPos)
+ {
+ double fVal = pArray[nCol];
+ if ( fVal == DBL_MIN )
+ rDoc.SetEmptyCell(*pPos);
+ else
+ rDoc.SetValue(*pPos, pArray[nCol]);
+ }
+ }
+ }
+
+ //! undo
+ PaintGridRanges_Impl();
+ pDocShell->SetDocumentModified();
+ ForceChartListener_Impl(); // call listeners for this object synchronously
+ bDone = true;
+ }
+ }
+ }
+
+ if (!bDone)
+ throw uno::RuntimeException();
+}
+
+uno::Sequence<OUString> SAL_CALL ScCellRangesBase::getRowDescriptions()
+{
+ SolarMutexGuard aGuard;
+ std::unique_ptr<ScMemChart> pMemChart(CreateMemChart_Impl());
+ if ( pMemChart )
+ {
+ sal_Int32 nRowCount = static_cast<sal_Int32>(pMemChart->GetRowCount());
+ uno::Sequence<OUString> aSeq( nRowCount );
+ OUString* pAry = aSeq.getArray();
+ for (sal_Int32 nRow = 0; nRow < nRowCount; nRow++)
+ pAry[nRow] = pMemChart->GetRowText(nRow);
+
+ return aSeq;
+ }
+ return {};
+}
+
+void SAL_CALL ScCellRangesBase::setRowDescriptions(
+ const uno::Sequence<OUString>& aRowDescriptions )
+{
+ SolarMutexGuard aGuard;
+ bool bDone = false;
+ if ( bChartColAsHdr )
+ {
+ sal_Int32 nRowCount = aRowDescriptions.getLength();
+ ScRangeListRef xChartRanges = GetLimitedChartRanges_Impl( 1, nRowCount );
+ if ( pDocShell && xChartRanges.is() )
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+ ScChartArray aArr( rDoc, xChartRanges );
+ aArr.SetHeaders( bChartRowAsHdr, bChartColAsHdr ); // RowAsHdr = ColHeaders
+ const ScChartPositionMap* pPosMap = aArr.GetPositionMap();
+ if (pPosMap)
+ {
+ if ( pPosMap->GetRowCount() == static_cast<SCROW>(nRowCount) )
+ {
+ const OUString* pArray = aRowDescriptions.getConstArray();
+ for (sal_Int32 nRow=0; nRow<nRowCount; nRow++)
+ {
+ const ScAddress* pPos = pPosMap->GetRowHeaderPosition(
+ static_cast<SCSIZE>(nRow) );
+ if (pPos)
+ {
+ const OUString& aStr = pArray[nRow];
+ if (aStr.isEmpty())
+ rDoc.SetEmptyCell(*pPos);
+ else
+ {
+ ScSetStringParam aParam;
+ aParam.setTextInput();
+ rDoc.SetString(*pPos, aStr, &aParam);
+ }
+ }
+ }
+
+ //! undo
+ PaintGridRanges_Impl();
+ pDocShell->SetDocumentModified();
+ ForceChartListener_Impl(); // call listeners for this object synchronously
+ bDone = true;
+ }
+ }
+ }
+ }
+
+ if (!bDone)
+ throw uno::RuntimeException();
+}
+
+uno::Sequence<OUString> SAL_CALL ScCellRangesBase::getColumnDescriptions()
+{
+ SolarMutexGuard aGuard;
+ std::unique_ptr<ScMemChart> pMemChart(CreateMemChart_Impl());
+ if ( pMemChart )
+ {
+ sal_Int32 nColCount = pMemChart->GetColCount();
+ uno::Sequence<OUString> aSeq( nColCount );
+ OUString* pAry = aSeq.getArray();
+ for (sal_Int32 nCol = 0; nCol < nColCount; nCol++)
+ pAry[nCol] = pMemChart->GetColText(nCol);
+
+ return aSeq;
+ }
+ return {};
+}
+
+void SAL_CALL ScCellRangesBase::setColumnDescriptions(
+ const uno::Sequence<OUString>& aColumnDescriptions )
+{
+ SolarMutexGuard aGuard;
+ bool bDone = false;
+ if ( bChartRowAsHdr )
+ {
+ sal_Int32 nColCount = aColumnDescriptions.getLength();
+ ScRangeListRef xChartRanges = GetLimitedChartRanges_Impl( nColCount, 1 );
+ if ( pDocShell && xChartRanges.is() )
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+ ScChartArray aArr( rDoc, xChartRanges );
+ aArr.SetHeaders( bChartRowAsHdr, bChartColAsHdr ); // RowAsHdr = ColHeaders
+ const ScChartPositionMap* pPosMap = aArr.GetPositionMap();
+ if (pPosMap)
+ {
+ if ( pPosMap->GetColCount() == static_cast<SCCOL>(nColCount) )
+ {
+ const OUString* pArray = aColumnDescriptions.getConstArray();
+ for (sal_Int32 nCol=0; nCol<nColCount; nCol++)
+ {
+ const ScAddress* pPos = pPosMap->GetColHeaderPosition(
+ sal::static_int_cast<SCCOL>(nCol) );
+ if (pPos)
+ {
+ const OUString& aStr = pArray[nCol];
+ if (aStr.isEmpty())
+ rDoc.SetEmptyCell(*pPos);
+ else
+ {
+ ScSetStringParam aParam;
+ aParam.setTextInput();
+ rDoc.SetString(*pPos, aStr, &aParam);
+ }
+ }
+ }
+
+ //! undo
+ PaintGridRanges_Impl();
+ pDocShell->SetDocumentModified();
+ ForceChartListener_Impl(); // call listeners for this object synchronously
+ bDone = true;
+ }
+ }
+ }
+ }
+
+ if (!bDone)
+ throw uno::RuntimeException();
+}
+
+void ScCellRangesBase::ForceChartListener_Impl()
+{
+ // call Update immediately so the caller to setData etc. can
+ // recognize the listener call
+
+ if (!pDocShell)
+ return;
+
+ ScChartListenerCollection* pColl = pDocShell->GetDocument().GetChartListenerCollection();
+ if (!pColl)
+ return;
+
+ ScChartListenerCollection::ListenersType& rListeners = pColl->getListeners();
+ for (auto const& it : rListeners)
+ {
+ ScChartListener *const p = it.second.get();
+ assert(p);
+ if (p->GetUnoSource() == static_cast<chart::XChartData*>(this) && p->IsDirty())
+ p->Update();
+ }
+}
+
+void SAL_CALL ScCellRangesBase::addChartDataChangeEventListener( const uno::Reference<
+ chart::XChartDataChangeEventListener >& aListener )
+{
+ SolarMutexGuard aGuard;
+ if ( !pDocShell || aRanges.empty() )
+ return;
+
+ //! test for duplicates ?
+
+ ScDocument& rDoc = pDocShell->GetDocument();
+ ScRangeListRef aRangesRef( new ScRangeList(aRanges) );
+ ScChartListenerCollection* pColl = rDoc.GetChartListenerCollection();
+ OUString aName = pColl->getUniqueName(u"__Uno");
+ if (aName.isEmpty())
+ // failed to create unique name.
+ return;
+
+ ScChartListener* pListener = new ScChartListener( aName, rDoc, aRangesRef );
+ pListener->SetUno( aListener, this );
+ pColl->insert( pListener );
+ pListener->StartListeningTo();
+}
+
+void SAL_CALL ScCellRangesBase::removeChartDataChangeEventListener( const uno::Reference<
+ chart::XChartDataChangeEventListener >& aListener )
+{
+ SolarMutexGuard aGuard;
+ if ( pDocShell && !aRanges.empty() )
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+ ScChartListenerCollection* pColl = rDoc.GetChartListenerCollection();
+ pColl->FreeUno( aListener, this );
+ }
+}
+
+double SAL_CALL ScCellRangesBase::getNotANumber()
+{
+ // use DBL_MIN in ScChartArray, because Chart wants it so
+ return DBL_MIN;
+}
+
+sal_Bool SAL_CALL ScCellRangesBase::isNotANumber( double nNumber )
+{
+ // use DBL_MIN in ScChartArray, because Chart wants it so
+ return (nNumber == DBL_MIN);
+}
+
+// XModifyBroadcaster
+
+void SAL_CALL ScCellRangesBase::addModifyListener(const uno::Reference<util::XModifyListener>& aListener)
+{
+ SolarMutexGuard aGuard;
+ if ( aRanges.empty() )
+ throw uno::RuntimeException();
+
+ aValueListeners.emplace_back( aListener );
+
+ if ( aValueListeners.size() == 1 )
+ {
+ if (!pValueListener)
+ pValueListener.reset( new ScLinkListener( LINK( this, ScCellRangesBase, ValueListenerHdl ) ) );
+
+ ScDocument& rDoc = pDocShell->GetDocument();
+ for ( size_t i = 0, nCount = aRanges.size(); i < nCount; i++)
+ rDoc.StartListeningArea( aRanges[ i ], false, pValueListener.get() );
+
+ acquire(); // don't lose this object (one ref for all listeners)
+ }
+}
+
+void SAL_CALL ScCellRangesBase::removeModifyListener( const uno::Reference<util::XModifyListener>& aListener )
+{
+
+ SolarMutexGuard aGuard;
+ if ( aRanges.empty() )
+ throw uno::RuntimeException();
+
+ rtl::Reference<ScCellRangesBase> xSelfHold(this); // in case the listeners have the last ref
+
+ sal_uInt16 nCount = aValueListeners.size();
+ for ( sal_uInt16 n=nCount; n--; )
+ {
+ uno::Reference<util::XModifyListener>& rObj = aValueListeners[n];
+ if ( rObj == aListener )
+ {
+ aValueListeners.erase( aValueListeners.begin() + n );
+
+ if ( aValueListeners.empty() )
+ {
+ if (pValueListener)
+ pValueListener->EndListeningAll();
+
+ release(); // release the ref for the listeners
+ }
+
+ break;
+ }
+ }
+}
+
+// XCellRangesQuery
+
+uno::Reference<sheet::XSheetCellRanges> SAL_CALL ScCellRangesBase::queryVisibleCells()
+{
+ SolarMutexGuard aGuard;
+ if (pDocShell)
+ {
+ //! Separate for all tables, if markings separated per table
+ SCTAB nTab = lcl_FirstTab(aRanges);
+
+ ScMarkData aMarkData(*GetMarkData());
+
+ ScDocument& rDoc = pDocShell->GetDocument();
+ SCCOL nCol = 0, nLastCol;
+ while (nCol <= rDoc.MaxCol())
+ {
+ if (rDoc.ColHidden(nCol, nTab, nullptr, &nLastCol))
+ // hidden columns. Deselect them.
+ aMarkData.SetMultiMarkArea(ScRange(nCol, 0, nTab, nLastCol, rDoc.MaxRow(), nTab), false);
+
+ nCol = nLastCol + 1;
+ }
+
+ SCROW nRow = 0, nLastRow;
+ while (nRow <= rDoc.MaxRow())
+ {
+ if (rDoc.RowHidden(nRow, nTab, nullptr, &nLastRow))
+ // These rows are hidden. Deselect them.
+ aMarkData.SetMultiMarkArea(ScRange(0, nRow, nTab, rDoc.MaxCol(), nLastRow, nTab), false);
+
+ nRow = nLastRow + 1;
+ }
+
+ ScRangeList aNewRanges;
+ aMarkData.FillRangeListWithMarks( &aNewRanges, false );
+ return new ScCellRangesObj( pDocShell, aNewRanges );
+ }
+
+ return nullptr;
+}
+
+uno::Reference<sheet::XSheetCellRanges> SAL_CALL ScCellRangesBase::queryEmptyCells()
+{
+ SolarMutexGuard aGuard;
+ if (pDocShell)
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+
+ ScMarkData aMarkData(*GetMarkData());
+
+ // mark occupied cells
+ for (size_t i = 0, nCount = aRanges.size(); i < nCount; ++i)
+ {
+ ScRange const & rRange = aRanges[ i ];
+
+ ScCellIterator aIter(rDoc, rRange);
+ for (bool bHasCell = aIter.first(); bHasCell; bHasCell = aIter.next())
+ {
+ // notes count as non-empty
+ if (!aIter.isEmpty())
+ aMarkData.SetMultiMarkArea(aIter.GetPos(), false);
+ }
+ }
+
+ ScRangeList aNewRanges;
+ // IsMultiMarked is not enough (will not be reset during deselecting)
+ //if (aMarkData.HasAnyMultiMarks()) // #i20044# should be set for all empty range
+ aMarkData.FillRangeListWithMarks( &aNewRanges, false );
+
+ return new ScCellRangesObj( pDocShell, aNewRanges ); // aNewRanges can be empty
+ }
+
+ return nullptr;
+}
+
+uno::Reference<sheet::XSheetCellRanges> SAL_CALL ScCellRangesBase::queryContentCells(
+ sal_Int16 nContentFlags )
+{
+ SolarMutexGuard aGuard;
+ if (pDocShell)
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+
+ ScMarkData aMarkData(rDoc.GetSheetLimits());
+
+ // select matching cells
+ for ( size_t i = 0, nCount = aRanges.size(); i < nCount; ++i )
+ {
+ ScRange const & rRange = aRanges[ i ];
+
+ ScCellIterator aIter(rDoc, rRange);
+ for (bool bHasCell = aIter.first(); bHasCell; bHasCell = aIter.next())
+ {
+ bool bAdd = false;
+ switch (aIter.getType())
+ {
+ case CELLTYPE_STRING:
+ if ( nContentFlags & sheet::CellFlags::STRING )
+ bAdd = true;
+ break;
+ case CELLTYPE_EDIT:
+ if ( (nContentFlags & sheet::CellFlags::STRING) || (nContentFlags & sheet::CellFlags::FORMATTED) )
+ bAdd = true;
+ break;
+ case CELLTYPE_FORMULA:
+ if ( nContentFlags & sheet::CellFlags::FORMULA )
+ bAdd = true;
+ break;
+ case CELLTYPE_VALUE:
+ if ( (nContentFlags & (sheet::CellFlags::VALUE|sheet::CellFlags::DATETIME))
+ == (sheet::CellFlags::VALUE|sheet::CellFlags::DATETIME) )
+ bAdd = true;
+ else
+ {
+ // date/time identification
+
+ sal_uLong nIndex = static_cast<sal_uLong>(rDoc.GetAttr(
+ aIter.GetPos(), ATTR_VALUE_FORMAT)->GetValue());
+ SvNumFormatType nTyp = rDoc.GetFormatTable()->GetType(nIndex);
+ if ((nTyp == SvNumFormatType::DATE) || (nTyp == SvNumFormatType::TIME) ||
+ (nTyp == SvNumFormatType::DATETIME))
+ {
+ if ( nContentFlags & sheet::CellFlags::DATETIME )
+ bAdd = true;
+ }
+ else
+ {
+ if ( nContentFlags & sheet::CellFlags::VALUE )
+ bAdd = true;
+ }
+ }
+ break;
+ default:
+ {
+ // added to avoid warnings
+ }
+ }
+
+ if (bAdd)
+ aMarkData.SetMultiMarkArea(aIter.GetPos());
+ }
+ }
+
+ if (nContentFlags & sheet::CellFlags::ANNOTATION)
+ {
+ std::vector<sc::NoteEntry> aNotes;
+ rDoc.GetNotesInRange(aRanges, aNotes);
+
+ for (const auto& i : aNotes)
+ {
+ aMarkData.SetMultiMarkArea(i.maPos);
+ }
+ }
+
+ ScRangeList aNewRanges;
+ if (aMarkData.IsMultiMarked())
+ aMarkData.FillRangeListWithMarks( &aNewRanges, false );
+
+ return new ScCellRangesObj( pDocShell, aNewRanges ); // aNewRanges can be empty
+ }
+
+ return nullptr;
+}
+
+uno::Reference<sheet::XSheetCellRanges> SAL_CALL ScCellRangesBase::queryFormulaCells(
+ sal_Int32 nResultFlags )
+{
+ SolarMutexGuard aGuard;
+ if (pDocShell)
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+
+ ScMarkData aMarkData(rDoc.GetSheetLimits());
+
+ // select matching cells
+ for ( size_t i = 0, nCount = aRanges.size(); i < nCount; ++i )
+ {
+ ScRange const & rRange = aRanges[ i ];
+
+ ScCellIterator aIter(rDoc, rRange);
+ for (bool bHasCell = aIter.first(); bHasCell; bHasCell = aIter.next())
+ {
+ if (aIter.getType() == CELLTYPE_FORMULA)
+ {
+ ScFormulaCell* pFCell = aIter.getFormulaCell();
+ bool bAdd = false;
+ if (pFCell->GetErrCode() != FormulaError::NONE)
+ {
+ if ( nResultFlags & sheet::FormulaResult::ERROR )
+ bAdd = true;
+ }
+ else if (pFCell->IsValue())
+ {
+ if ( nResultFlags & sheet::FormulaResult::VALUE )
+ bAdd = true;
+ }
+ else // String
+ {
+ if ( nResultFlags & sheet::FormulaResult::STRING )
+ bAdd = true;
+ }
+
+ if (bAdd)
+ aMarkData.SetMultiMarkArea(aIter.GetPos());
+ }
+ }
+ }
+
+ ScRangeList aNewRanges;
+ if (aMarkData.IsMultiMarked())
+ aMarkData.FillRangeListWithMarks( &aNewRanges, false );
+
+ return new ScCellRangesObj( pDocShell, aNewRanges ); // aNewRanges can be empty
+ }
+
+ return nullptr;
+}
+
+uno::Reference<sheet::XSheetCellRanges> ScCellRangesBase::QueryDifferences_Impl(
+ const table::CellAddress& aCompare, bool bColumnDiff)
+{
+ if (pDocShell)
+ {
+ size_t nRangeCount = aRanges.size();
+ size_t i;
+ ScDocument& rDoc = pDocShell->GetDocument();
+ ScMarkData aMarkData(rDoc.GetSheetLimits());
+
+ SCCOLROW nCmpPos = bColumnDiff ? static_cast<SCCOLROW>(aCompare.Row) : static_cast<SCCOLROW>(aCompare.Column);
+
+ // first select everything, where at all something is in the comparison column
+ // (in the second step the selection is cancelled for equal cells)
+
+ SCTAB nTab = lcl_FirstTab(aRanges); //! for all tables, if markings per table
+ ScRange aCmpRange, aCellRange;
+ if (bColumnDiff)
+ aCmpRange = ScRange( 0,nCmpPos,nTab, rDoc.MaxCol(),nCmpPos,nTab );
+ else
+ aCmpRange = ScRange( static_cast<SCCOL>(nCmpPos),0,nTab, static_cast<SCCOL>(nCmpPos),rDoc.MaxRow(),nTab );
+ ScCellIterator aCmpIter(rDoc, aCmpRange);
+ for (bool bHasCell = aCmpIter.first(); bHasCell; bHasCell = aCmpIter.next())
+ {
+ SCCOLROW nCellPos = bColumnDiff ? static_cast<SCCOLROW>(aCmpIter.GetPos().Col()) : static_cast<SCCOLROW>(aCmpIter.GetPos().Row());
+ if (bColumnDiff)
+ aCellRange = ScRange( static_cast<SCCOL>(nCellPos),0,nTab,
+ static_cast<SCCOL>(nCellPos),rDoc.MaxRow(),nTab );
+ else
+ aCellRange = ScRange( 0,nCellPos,nTab, rDoc.MaxCol(),nCellPos,nTab );
+
+ for (i=0; i<nRangeCount; i++)
+ {
+ ScRange aRange( aRanges[ i ] );
+ if ( aRange.Intersects( aCellRange ) )
+ {
+ if (bColumnDiff)
+ {
+ aRange.aStart.SetCol(static_cast<SCCOL>(nCellPos));
+ aRange.aEnd.SetCol(static_cast<SCCOL>(nCellPos));
+ }
+ else
+ {
+ aRange.aStart.SetRow(nCellPos);
+ aRange.aEnd.SetRow(nCellPos);
+ }
+ aMarkData.SetMultiMarkArea( aRange );
+ }
+ }
+ }
+
+ // compare all not empty cells with the comparison column and accordingly
+ // select or cancel
+
+ ScAddress aCmpAddr;
+ for (i=0; i<nRangeCount; i++)
+ {
+ ScRange const & rRange = aRanges[ i ];
+
+ ScCellIterator aIter( rDoc, rRange );
+ for (bool bHasCell = aIter.first(); bHasCell; bHasCell = aIter.next())
+ {
+ if (bColumnDiff)
+ aCmpAddr = ScAddress( aIter.GetPos().Col(), nCmpPos, aIter.GetPos().Tab() );
+ else
+ aCmpAddr = ScAddress( static_cast<SCCOL>(nCmpPos), aIter.GetPos().Row(), aIter.GetPos().Tab() );
+
+ ScRange aOneRange(aIter.GetPos());
+ if (!aIter.equalsWithoutFormat(aCmpAddr))
+ aMarkData.SetMultiMarkArea( aOneRange );
+ else
+ aMarkData.SetMultiMarkArea( aOneRange, false ); // deselect
+ }
+ }
+
+ ScRangeList aNewRanges;
+ if (aMarkData.IsMultiMarked())
+ aMarkData.FillRangeListWithMarks( &aNewRanges, false );
+
+ return new ScCellRangesObj( pDocShell, aNewRanges ); // aNewRanges can be empty
+ }
+ return nullptr;
+}
+
+uno::Reference<sheet::XSheetCellRanges > SAL_CALL ScCellRangesBase::queryColumnDifferences(
+ const table::CellAddress& aCompare )
+{
+ SolarMutexGuard aGuard;
+ return QueryDifferences_Impl( aCompare, true );
+}
+
+uno::Reference<sheet::XSheetCellRanges> SAL_CALL ScCellRangesBase::queryRowDifferences(
+ const table::CellAddress& aCompare )
+{
+ SolarMutexGuard aGuard;
+ return QueryDifferences_Impl( aCompare, false );
+}
+
+uno::Reference<sheet::XSheetCellRanges> SAL_CALL ScCellRangesBase::queryIntersection(
+ const table::CellRangeAddress& aRange )
+{
+ SolarMutexGuard aGuard;
+ ScRange aMask( static_cast<SCCOL>(aRange.StartColumn), static_cast<SCROW>(aRange.StartRow), aRange.Sheet,
+ static_cast<SCCOL>(aRange.EndColumn), static_cast<SCROW>(aRange.EndRow), aRange.Sheet );
+
+ ScRangeList aNew;
+ for ( size_t i = 0, nCount = aRanges.size(); i < nCount; ++i )
+ {
+ ScRange aTemp( aRanges[ i ] );
+ if ( aTemp.Intersects( aMask ) )
+ aNew.Join( ScRange( std::max( aTemp.aStart.Col(), aMask.aStart.Col() ),
+ std::max( aTemp.aStart.Row(), aMask.aStart.Row() ),
+ std::max( aTemp.aStart.Tab(), aMask.aStart.Tab() ),
+ std::min( aTemp.aEnd.Col(), aMask.aEnd.Col() ),
+ std::min( aTemp.aEnd.Row(), aMask.aEnd.Row() ),
+ std::min( aTemp.aEnd.Tab(), aMask.aEnd.Tab() ) ) );
+ }
+
+ return new ScCellRangesObj( pDocShell, aNew ); // can be empty
+}
+
+// XFormulaQuery
+
+uno::Reference<sheet::XSheetCellRanges> SAL_CALL ScCellRangesBase::queryPrecedents(
+ sal_Bool bRecursive )
+{
+ SolarMutexGuard aGuard;
+ if ( pDocShell )
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+
+ ScRangeList aNewRanges(aRanges);
+ bool bFound;
+ do
+ {
+ bFound = false;
+
+ // aMarkData uses aNewRanges, not aRanges, so GetMarkData can't be used
+ ScMarkData aMarkData(rDoc.GetSheetLimits());
+ aMarkData.MarkFromRangeList( aNewRanges, false );
+
+ for (size_t nR = 0, nCount = aNewRanges.size(); nR<nCount; ++nR)
+ {
+ ScRange const & rRange = aNewRanges[ nR];
+ ScCellIterator aIter(rDoc, rRange);
+ for (bool bHasCell = aIter.first(); bHasCell; bHasCell = aIter.next())
+ {
+ if (aIter.getType() != CELLTYPE_FORMULA)
+ continue;
+
+ ScDetectiveRefIter aRefIter(rDoc, aIter.getFormulaCell());
+ ScRange aRefRange;
+ while ( aRefIter.GetNextRef( aRefRange) )
+ {
+ if ( bRecursive && !bFound && !aMarkData.IsAllMarked( aRefRange ) )
+ bFound = true;
+ aMarkData.SetMultiMarkArea(aRefRange);
+ }
+ }
+ }
+
+ aMarkData.FillRangeListWithMarks( &aNewRanges, true );
+ }
+ while ( bRecursive && bFound );
+
+ return new ScCellRangesObj( pDocShell, aNewRanges );
+ }
+
+ return nullptr;
+}
+
+uno::Reference<sheet::XSheetCellRanges> SAL_CALL ScCellRangesBase::queryDependents(
+ sal_Bool bRecursive )
+{
+ SolarMutexGuard aGuard;
+ if ( pDocShell )
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+
+ ScRangeList aNewRanges(aRanges);
+ bool bFound;
+ do
+ {
+ bFound = false;
+
+ // aMarkData uses aNewRanges, not aRanges, so GetMarkData can't be used
+ ScMarkData aMarkData(rDoc.GetSheetLimits());
+ aMarkData.MarkFromRangeList( aNewRanges, false );
+
+ SCTAB nTab = lcl_FirstTab(aNewRanges); //! all tables
+
+ ScCellIterator aCellIter( rDoc, ScRange(0, 0, nTab, rDoc.MaxCol(), rDoc.MaxRow(), nTab) );
+ for (bool bHasCell = aCellIter.first(); bHasCell; bHasCell = aCellIter.next())
+ {
+ if (aCellIter.getType() != CELLTYPE_FORMULA)
+ continue;
+
+ bool bMark = false;
+ ScDetectiveRefIter aIter(rDoc, aCellIter.getFormulaCell());
+ ScRange aRefRange;
+ while ( aIter.GetNextRef( aRefRange) && !bMark )
+ {
+ size_t nRangesCount = aNewRanges.size();
+ for (size_t nR = 0; nR < nRangesCount; ++nR)
+ {
+ ScRange const & rRange = aNewRanges[ nR ];
+ if (rRange.Intersects(aRefRange))
+ {
+ bMark = true; // depending on part of Range
+ break;
+ }
+ }
+ }
+ if (bMark)
+ {
+ ScRange aCellRange(aCellIter.GetPos());
+ if ( bRecursive && !bFound && !aMarkData.IsAllMarked( aCellRange ) )
+ bFound = true;
+ aMarkData.SetMultiMarkArea(aCellRange);
+ }
+ }
+
+ aMarkData.FillRangeListWithMarks( &aNewRanges, true );
+ }
+ while ( bRecursive && bFound );
+
+ return new ScCellRangesObj( pDocShell, aNewRanges );
+ }
+
+ return nullptr;
+}
+
+// XSearchable
+
+uno::Reference<util::XSearchDescriptor> SAL_CALL ScCellRangesBase::createSearchDescriptor()
+{
+ return new ScCellSearchObj;
+}
+
+uno::Reference<container::XIndexAccess> SAL_CALL ScCellRangesBase::findAll(
+ const uno::Reference<util::XSearchDescriptor>& xDesc )
+{
+ SolarMutexGuard aGuard;
+ // should we return Null if nothing is found(?)
+ uno::Reference<container::XIndexAccess> xRet;
+ if ( pDocShell && xDesc.is() )
+ {
+ ScCellSearchObj* pSearch = comphelper::getFromUnoTunnel<ScCellSearchObj>( xDesc );
+ if (pSearch)
+ {
+ SvxSearchItem* pSearchItem = pSearch->GetSearchItem();
+ if (pSearchItem)
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+ pSearchItem->SetCommand( SvxSearchCmd::FIND_ALL );
+ // always only within this object
+ pSearchItem->SetSelection( !lcl_WholeSheet(rDoc, aRanges) );
+
+ ScMarkData aMark(*GetMarkData());
+
+ OUString aDummyUndo;
+ ScRangeList aMatchedRanges;
+ SCCOL nCol = 0;
+ SCROW nRow = 0;
+ SCTAB nTab = 0;
+ bool bFound = rDoc.SearchAndReplace(
+ *pSearchItem, nCol, nRow, nTab, aMark, aMatchedRanges, aDummyUndo);
+ if (bFound)
+ {
+ // on findAll always CellRanges no matter how much has been found
+ xRet.set(new ScCellRangesObj( pDocShell, aMatchedRanges ));
+ }
+ }
+ }
+ }
+ return xRet;
+}
+
+uno::Reference<uno::XInterface> ScCellRangesBase::Find_Impl(
+ const uno::Reference<util::XSearchDescriptor>& xDesc,
+ const ScAddress* pLastPos )
+{
+ uno::Reference<uno::XInterface> xRet;
+ if ( pDocShell && xDesc.is() )
+ {
+ ScCellSearchObj* pSearch = comphelper::getFromUnoTunnel<ScCellSearchObj>( xDesc );
+ if (pSearch)
+ {
+ SvxSearchItem* pSearchItem = pSearch->GetSearchItem();
+ if (pSearchItem)
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+ pSearchItem->SetCommand( SvxSearchCmd::FIND );
+ // only always in this object
+ pSearchItem->SetSelection( !lcl_WholeSheet(rDoc, aRanges) );
+
+ ScMarkData aMark(*GetMarkData());
+
+ SCCOL nCol;
+ SCROW nRow;
+ SCTAB nTab;
+ if (pLastPos)
+ pLastPos->GetVars( nCol, nRow, nTab );
+ else
+ {
+ nTab = lcl_FirstTab(aRanges); //! multiple sheets?
+ rDoc.GetSearchAndReplaceStart( *pSearchItem, nCol, nRow );
+ }
+
+ OUString aDummyUndo;
+ ScRangeList aMatchedRanges;
+ bool bFound = rDoc.SearchAndReplace(
+ *pSearchItem, nCol, nRow, nTab, aMark, aMatchedRanges, aDummyUndo);
+ if (bFound)
+ {
+ ScAddress aFoundPos( nCol, nRow, nTab );
+ xRet.set(static_cast<cppu::OWeakObject*>(new ScCellObj( pDocShell, aFoundPos )));
+ }
+ }
+ }
+ }
+ return xRet;
+}
+
+uno::Reference<uno::XInterface> SAL_CALL ScCellRangesBase::findFirst(
+ const uno::Reference<util::XSearchDescriptor>& xDesc )
+{
+ SolarMutexGuard aGuard;
+ return Find_Impl( xDesc, nullptr );
+}
+
+uno::Reference<uno::XInterface> SAL_CALL ScCellRangesBase::findNext(
+ const uno::Reference<uno::XInterface>& xStartAt,
+ const uno::Reference<util::XSearchDescriptor >& xDesc )
+{
+ SolarMutexGuard aGuard;
+ if ( xStartAt.is() )
+ {
+ ScCellRangesBase* pRangesImp = comphelper::getFromUnoTunnel<ScCellRangesBase>( xStartAt );
+ if ( pRangesImp && pRangesImp->GetDocShell() == pDocShell )
+ {
+ const ScRangeList& rStartRanges = pRangesImp->GetRangeList();
+ if ( rStartRanges.size() == 1 )
+ {
+ ScAddress aStartPos = rStartRanges[ 0 ].aStart;
+ return Find_Impl( xDesc, &aStartPos );
+ }
+ }
+ }
+ return nullptr;
+}
+
+// XReplaceable
+
+uno::Reference<util::XReplaceDescriptor> SAL_CALL ScCellRangesBase::createReplaceDescriptor()
+{
+ return new ScCellSearchObj;
+}
+
+sal_Int32 SAL_CALL ScCellRangesBase::replaceAll( const uno::Reference<util::XSearchDescriptor>& xDesc )
+{
+ SolarMutexGuard aGuard;
+ sal_uInt64 nReplaced = 0;
+ if ( pDocShell && xDesc.is() )
+ {
+ ScCellSearchObj* pSearch = comphelper::getFromUnoTunnel<ScCellSearchObj>( xDesc );
+ if (pSearch)
+ {
+ SvxSearchItem* pSearchItem = pSearch->GetSearchItem();
+ if (pSearchItem)
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+ bool bUndo(rDoc.IsUndoEnabled());
+ pSearchItem->SetCommand( SvxSearchCmd::REPLACE_ALL );
+ // only always in this object
+ pSearchItem->SetSelection( !lcl_WholeSheet(rDoc, aRanges) );
+
+ ScMarkData aMark(*GetMarkData());
+
+ SCTAB nTabCount = rDoc.GetTableCount();
+ bool bProtected = !pDocShell->IsEditable();
+ for (const auto& rTab : aMark)
+ {
+ if (rTab >= nTabCount)
+ break;
+ if ( rDoc.IsTabProtected(rTab) )
+ bProtected = true;
+ }
+ if (bProtected)
+ {
+ //! Exception, or what?
+ }
+ else
+ {
+ SCTAB nTab = aMark.GetFirstSelected(); // do not use if SearchAndReplace
+ SCCOL nCol = 0;
+ SCROW nRow = 0;
+
+ OUString aUndoStr;
+ ScDocumentUniquePtr pUndoDoc;
+ if (bUndo)
+ {
+ pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
+ pUndoDoc->InitUndo( rDoc, nTab, nTab );
+ }
+ for (const auto& rTab : aMark)
+ {
+ if (rTab >= nTabCount)
+ break;
+ if (rTab != nTab && bUndo)
+ pUndoDoc->AddUndoTab( rTab, rTab );
+ }
+ std::unique_ptr<ScMarkData> pUndoMark;
+ if (bUndo)
+ pUndoMark.reset(new ScMarkData(aMark));
+
+ bool bFound = false;
+ if (bUndo)
+ {
+ ScRangeList aMatchedRanges;
+ bFound = rDoc.SearchAndReplace(
+ *pSearchItem, nCol, nRow, nTab, aMark, aMatchedRanges, aUndoStr, pUndoDoc.get() );
+ }
+ if (bFound)
+ {
+ nReplaced = pUndoDoc->GetCellCount();
+
+ pDocShell->GetUndoManager()->AddUndoAction(
+ std::make_unique<ScUndoReplace>( pDocShell, *pUndoMark, nCol, nRow, nTab,
+ aUndoStr, std::move(pUndoDoc), pSearchItem ) );
+
+ pDocShell->PostPaintGridAll();
+ pDocShell->SetDocumentModified();
+ }
+ }
+ }
+ }
+ }
+ return nReplaced;
+}
+
+// XUnoTunnel
+
+UNO3_GETIMPLEMENTATION_IMPL(ScCellRangesBase);
+
+ScCellRangesObj::ScCellRangesObj(ScDocShell* pDocSh, const ScRangeList& rR)
+ : ScCellRangesBase(pDocSh, rR)
+{
+}
+
+ScCellRangesObj::~ScCellRangesObj()
+{
+}
+
+void ScCellRangesObj::RefChanged()
+{
+ ScCellRangesBase::RefChanged();
+}
+
+uno::Any SAL_CALL ScCellRangesObj::queryInterface( const uno::Type& rType )
+{
+ SC_QUERYINTERFACE( sheet::XSheetCellRangeContainer )
+ SC_QUERYINTERFACE( sheet::XSheetCellRanges )
+ SC_QUERYINTERFACE( container::XIndexAccess )
+ SC_QUERY_MULTIPLE( container::XElementAccess, container::XIndexAccess )
+ SC_QUERYINTERFACE( container::XEnumerationAccess )
+ SC_QUERYINTERFACE( container::XNameContainer )
+ SC_QUERYINTERFACE( container::XNameReplace )
+ SC_QUERYINTERFACE( container::XNameAccess )
+
+ return ScCellRangesBase::queryInterface( rType );
+}
+
+void SAL_CALL ScCellRangesObj::acquire() noexcept
+{
+ ScCellRangesBase::acquire();
+}
+
+void SAL_CALL ScCellRangesObj::release() noexcept
+{
+ ScCellRangesBase::release();
+}
+
+uno::Sequence<uno::Type> SAL_CALL ScCellRangesObj::getTypes()
+{
+ static const uno::Sequence<uno::Type> aTypes = comphelper::concatSequences(
+ ScCellRangesBase::getTypes(),
+ uno::Sequence<uno::Type>
+ {
+ cppu::UnoType<sheet::XSheetCellRangeContainer>::get(),
+ cppu::UnoType<container::XNameContainer>::get(),
+ cppu::UnoType<container::XEnumerationAccess>::get()
+ } );
+ return aTypes;
+}
+
+uno::Sequence<sal_Int8> SAL_CALL ScCellRangesObj::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// XCellRanges
+
+rtl::Reference<ScCellRangeObj> ScCellRangesObj::GetObjectByIndex_Impl(sal_Int32 nIndex) const
+{
+ ScDocShell* pDocSh = GetDocShell();
+ const ScRangeList& rRanges = GetRangeList();
+ if ( pDocSh && nIndex >= 0 && nIndex < sal::static_int_cast<sal_Int32>(rRanges.size()) )
+ {
+ ScRange const & rRange = rRanges[ nIndex ];
+ if ( rRange.aStart == rRange.aEnd )
+ return new ScCellObj( pDocSh, rRange.aStart );
+ else
+ return new ScCellRangeObj( pDocSh, rRange );
+ }
+
+ return nullptr; // no DocShell or wrong index
+}
+
+uno::Sequence<table::CellRangeAddress> SAL_CALL ScCellRangesObj::getRangeAddresses()
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ const ScRangeList& rRanges = GetRangeList();
+ size_t nCount = rRanges.size();
+ if ( pDocSh && nCount )
+ {
+ table::CellRangeAddress aRangeAddress;
+ uno::Sequence<table::CellRangeAddress> aSeq(nCount);
+ table::CellRangeAddress* pAry = aSeq.getArray();
+ for ( size_t i=0; i < nCount; i++)
+ {
+ ScUnoConversion::FillApiRange( aRangeAddress, rRanges[ i ] );
+ pAry[i] = aRangeAddress;
+ }
+ return aSeq;
+ }
+
+ return {}; // can be empty
+}
+
+uno::Reference<container::XEnumerationAccess> SAL_CALL ScCellRangesObj::getCells()
+{
+ SolarMutexGuard aGuard;
+
+ // getCells with empty range list is possible (no exception),
+ // the resulting enumeration just has no elements
+ // (same behaviour as a valid range with no cells)
+ // This is handled in ScCellsEnumeration ctor.
+
+ const ScRangeList& rRanges = GetRangeList();
+ ScDocShell* pDocSh = GetDocShell();
+ if (pDocSh)
+ return new ScCellsObj( pDocSh, rRanges );
+ return nullptr;
+}
+
+OUString SAL_CALL ScCellRangesObj::getRangeAddressesAsString()
+{
+ SolarMutexGuard aGuard;
+ OUString aString;
+ ScDocShell* pDocSh = GetDocShell();
+ const ScRangeList& rRanges = GetRangeList();
+ if (pDocSh)
+ rRanges.Format( aString, ScRefFlags::VALID | ScRefFlags::TAB_3D, pDocSh->GetDocument() );
+ return aString;
+}
+
+// XSheetCellRangeContainer
+
+void SAL_CALL ScCellRangesObj::addRangeAddress( const table::CellRangeAddress& rRange,
+ sal_Bool bMergeRanges )
+{
+ SolarMutexGuard aGuard;
+ ScRange aRange(static_cast<SCCOL>(rRange.StartColumn),
+ static_cast<SCROW>(rRange.StartRow),
+ static_cast<SCTAB>(rRange.Sheet),
+ static_cast<SCCOL>(rRange.EndColumn),
+ static_cast<SCROW>(rRange.EndRow),
+ static_cast<SCTAB>(rRange.Sheet));
+ AddRange(aRange, bMergeRanges);
+}
+
+static void lcl_RemoveNamedEntry( std::vector<ScCellRangesObj::ScNamedEntry>& rNamedEntries, const ScRange& rRange )
+{
+ sal_uInt16 nCount = rNamedEntries.size();
+ for ( sal_uInt16 n=nCount; n--; )
+ if ( rNamedEntries[n].GetRange() == rRange )
+ rNamedEntries.erase( rNamedEntries.begin() + n );
+}
+
+void SAL_CALL ScCellRangesObj::removeRangeAddress( const table::CellRangeAddress& rRange )
+{
+ SolarMutexGuard aGuard;
+ const ScRangeList& rRanges = GetRangeList();
+
+ ScRangeList aSheetRanges;
+ ScRangeList aNotSheetRanges;
+ for (size_t i = 0; i < rRanges.size(); ++i)
+ {
+ if (rRanges[ i].aStart.Tab() == rRange.Sheet)
+ {
+ aSheetRanges.push_back( rRanges[ i ] );
+ }
+ else
+ {
+ aNotSheetRanges.push_back( rRanges[ i ] );
+ }
+ }
+ ScMarkData aMarkData(GetDocument()->GetSheetLimits());
+ aMarkData.MarkFromRangeList( aSheetRanges, false );
+ ScRange aRange(static_cast<SCCOL>(rRange.StartColumn),
+ static_cast<SCROW>(rRange.StartRow),
+ static_cast<SCTAB>(rRange.Sheet),
+ static_cast<SCCOL>(rRange.EndColumn),
+ static_cast<SCROW>(rRange.EndRow),
+ static_cast<SCTAB>(rRange.Sheet));
+ if (aMarkData.GetTableSelect( aRange.aStart.Tab() ))
+ {
+ aMarkData.MarkToMulti();
+ if (!aMarkData.IsAllMarked( aRange ) )
+ throw container::NoSuchElementException();
+
+ aMarkData.SetMultiMarkArea( aRange, false );
+ lcl_RemoveNamedEntry(m_aNamedEntries, aRange);
+
+ }
+ SetNewRanges(aNotSheetRanges);
+ ScRangeList aNew;
+ aMarkData.FillRangeListWithMarks( &aNew, false );
+ for ( size_t j = 0; j < aNew.size(); ++j)
+ {
+ AddRange(aNew[ j ], false);
+ }
+}
+
+void SAL_CALL ScCellRangesObj::addRangeAddresses( const uno::Sequence<table::CellRangeAddress >& rRanges,
+ sal_Bool bMergeRanges )
+{
+ SolarMutexGuard aGuard;
+ for (const table::CellRangeAddress& rRange : rRanges)
+ {
+ ScRange aRange(static_cast<SCCOL>(rRange.StartColumn),
+ static_cast<SCROW>(rRange.StartRow),
+ static_cast<SCTAB>(rRange.Sheet),
+ static_cast<SCCOL>(rRange.EndColumn),
+ static_cast<SCROW>(rRange.EndRow),
+ static_cast<SCTAB>(rRange.Sheet));
+ AddRange(aRange, bMergeRanges);
+ }
+}
+
+void SAL_CALL ScCellRangesObj::removeRangeAddresses( const uno::Sequence<table::CellRangeAddress >& rRangeSeq )
+{
+ // use sometimes a better/faster implementation
+ for (const table::CellRangeAddress& rRange : rRangeSeq)
+ {
+ removeRangeAddress(rRange);
+ }
+}
+
+// XNameContainer
+
+static void lcl_RemoveNamedEntry( std::vector<ScCellRangesObj::ScNamedEntry>& rNamedEntries, std::u16string_view rName )
+{
+ sal_uInt16 nCount = rNamedEntries.size();
+ for ( sal_uInt16 n=nCount; n--; )
+ if ( rNamedEntries[n].GetName() == rName )
+ rNamedEntries.erase( rNamedEntries.begin() + n );
+}
+
+void SAL_CALL ScCellRangesObj::insertByName( const OUString& aName, const uno::Any& aElement )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ bool bDone = false;
+
+ //! Type of aElement can be some specific interface instead of XInterface
+
+ uno::Reference<uno::XInterface> xInterface(aElement, uno::UNO_QUERY);
+ if ( pDocSh && xInterface.is() )
+ {
+ ScCellRangesBase* pRangesImp = comphelper::getFromUnoTunnel<ScCellRangesBase>( xInterface );
+ if ( pRangesImp && pRangesImp->GetDocShell() == pDocSh )
+ {
+ // if explicit name is given and already existing, throw exception
+
+ if ( !aName.isEmpty() )
+ {
+ size_t nNamedCount = m_aNamedEntries.size();
+ for (size_t n = 0; n < nNamedCount; n++)
+ {
+ if (m_aNamedEntries[n].GetName() == aName)
+ throw container::ElementExistException();
+ }
+ }
+
+ ScRangeList aNew(GetRangeList());
+ const ScRangeList& rAddRanges = pRangesImp->GetRangeList();
+ size_t nAddCount = rAddRanges.size();
+ for ( size_t i = 0; i < nAddCount; i++ )
+ aNew.Join( rAddRanges[ i ] );
+ SetNewRanges(aNew);
+ bDone = true;
+
+ if ( !aName.isEmpty() && nAddCount == 1 )
+ {
+ // if a name is given, also insert into list of named entries
+ // (only possible for a single range)
+ // name is not in m_aNamedEntries (tested above)
+ m_aNamedEntries.emplace_back( ScNamedEntry{aName, rAddRanges[ 0 ]} );
+ }
+ }
+ }
+
+ if (!bDone)
+ {
+ // invalid element - double names are handled above
+ throw lang::IllegalArgumentException();
+ }
+}
+
+static bool lcl_FindRangeByName( const ScRangeList& rRanges, ScDocShell* pDocSh,
+ std::u16string_view rName, size_t& rIndex )
+{
+ if (pDocSh)
+ {
+ OUString aRangeStr;
+ ScDocument& rDoc = pDocSh->GetDocument();
+ for ( size_t i = 0, nCount = rRanges.size(); i < nCount; i++ )
+ {
+ aRangeStr = rRanges[ i ].Format(rDoc, ScRefFlags::VALID | ScRefFlags::TAB_3D);
+ if ( aRangeStr == rName )
+ {
+ rIndex = i;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+static bool lcl_FindRangeOrEntry( const std::vector<ScCellRangesObj::ScNamedEntry>& rNamedEntries,
+ const ScRangeList& rRanges, ScDocShell* pDocSh,
+ const OUString& rName, ScRange& rFound )
+{
+ // exact range in list?
+
+ size_t nIndex = 0;
+ if ( lcl_FindRangeByName( rRanges, pDocSh, rName, nIndex ) )
+ {
+ rFound = rRanges[ nIndex ];
+ return true;
+ }
+
+ // range contained in selection? (sheet must be specified)
+
+ ScRange aCellRange;
+ ScRefFlags nParse = aCellRange.ParseAny( rName, pDocSh->GetDocument() );
+ if ( (nParse & ( ScRefFlags::VALID | ScRefFlags::TAB_3D ))
+ == ( ScRefFlags::VALID | ScRefFlags::TAB_3D ))
+ {
+ ScMarkData aMarkData(pDocSh->GetDocument().GetSheetLimits());
+ aMarkData.MarkFromRangeList( rRanges, false );
+ if ( aMarkData.IsAllMarked( aCellRange ) )
+ {
+ rFound = aCellRange;
+ return true;
+ }
+ }
+
+ // named entry in this object?
+
+ for (const auto & rNamedEntry : rNamedEntries)
+ if ( rNamedEntry.GetName() == rName )
+ {
+ // test if named entry is contained in rRanges
+
+ const ScRange& rComp = rNamedEntry.GetRange();
+ ScMarkData aMarkData(pDocSh->GetDocument().GetSheetLimits());
+ aMarkData.MarkFromRangeList( rRanges, false );
+ if ( aMarkData.IsAllMarked( rComp ) )
+ {
+ rFound = rComp;
+ return true;
+ }
+ }
+
+ return false; // not found
+}
+
+void SAL_CALL ScCellRangesObj::removeByName( const OUString& aName )
+{
+ SolarMutexGuard aGuard;
+ bool bDone = false;
+ ScDocShell* pDocSh = GetDocShell();
+ const ScRangeList& rRanges = GetRangeList();
+ size_t nIndex = 0;
+ if ( lcl_FindRangeByName( rRanges, pDocSh, aName, nIndex ) )
+ {
+ // skip a single range
+ ScRangeList aNew;
+ for ( size_t i = 0, nCount = rRanges.size(); i < nCount; i++ )
+ if (i != nIndex)
+ aNew.push_back( rRanges[ i ] );
+ SetNewRanges(aNew);
+ bDone = true;
+ }
+ else if (pDocSh)
+ {
+ // deselect any ranges (parsed or named entry)
+ ScRangeList aDiff;
+ bool bValid = ( aDiff.Parse( aName, pDocSh->GetDocument() ) & ScRefFlags::VALID )
+ == ScRefFlags::VALID;
+ if (!bValid)
+ {
+ sal_uInt16 nCount = m_aNamedEntries.size();
+ for (sal_uInt16 n=0; n<nCount && !bValid; n++)
+ if (m_aNamedEntries[n].GetName() == aName)
+ {
+ aDiff.RemoveAll();
+ aDiff.push_back(m_aNamedEntries[n].GetRange());
+ bValid = true;
+ }
+ }
+ if ( bValid )
+ {
+ ScMarkData aMarkData(GetDocument()->GetSheetLimits());
+ aMarkData.MarkFromRangeList( rRanges, false );
+
+ for ( size_t i = 0, nDiffCount = aDiff.size(); i < nDiffCount; i++ )
+ {
+ ScRange const & rDiffRange = aDiff[ i ];
+ if (aMarkData.GetTableSelect( rDiffRange.aStart.Tab() ))
+ aMarkData.SetMultiMarkArea( rDiffRange, false );
+ }
+
+ ScRangeList aNew;
+ aMarkData.FillRangeListWithMarks( &aNew, false );
+ SetNewRanges(aNew);
+
+ bDone = true; //! error if range was not selected before?
+ }
+ }
+
+ if (!m_aNamedEntries.empty())
+ lcl_RemoveNamedEntry(m_aNamedEntries, aName);
+
+ if (!bDone)
+ throw container::NoSuchElementException(); // not found
+}
+
+// XNameReplace
+
+void SAL_CALL ScCellRangesObj::replaceByName( const OUString& aName, const uno::Any& aElement )
+{
+ SolarMutexGuard aGuard;
+ //! combine?
+ removeByName( aName );
+ insertByName( aName, aElement );
+}
+
+// XNameAccess
+
+uno::Any SAL_CALL ScCellRangesObj::getByName( const OUString& aName )
+{
+ SolarMutexGuard aGuard;
+ uno::Any aRet;
+
+ ScDocShell* pDocSh = GetDocShell();
+ const ScRangeList& rRanges = GetRangeList();
+ ScRange aRange;
+ if (!lcl_FindRangeOrEntry(m_aNamedEntries, rRanges,
+ pDocSh, aName, aRange))
+ throw container::NoSuchElementException();
+
+ uno::Reference<table::XCellRange> xRange;
+ if ( aRange.aStart == aRange.aEnd )
+ xRange.set(new ScCellObj( pDocSh, aRange.aStart ));
+ else
+ xRange.set(new ScCellRangeObj( pDocSh, aRange ));
+ aRet <<= xRange;
+
+ return aRet;
+}
+
+static bool lcl_FindEntryName( const std::vector<ScCellRangesObj::ScNamedEntry>& rNamedEntries,
+ const ScRange& rRange, OUString& rName )
+{
+ sal_uInt16 nCount = rNamedEntries.size();
+ for (sal_uInt16 i=0; i<nCount; i++)
+ if (rNamedEntries[i].GetRange() == rRange)
+ {
+ rName = rNamedEntries[i].GetName();
+ return true;
+ }
+ return false;
+}
+
+uno::Sequence<OUString> SAL_CALL ScCellRangesObj::getElementNames()
+{
+ SolarMutexGuard aGuard;
+
+ ScDocShell* pDocSh = GetDocShell();
+ const ScRangeList& rRanges = GetRangeList();
+ if (pDocSh)
+ {
+ OUString aRangeStr;
+ ScDocument& rDoc = pDocSh->GetDocument();
+ size_t nCount = rRanges.size();
+
+ uno::Sequence<OUString> aSeq(nCount);
+ OUString* pAry = aSeq.getArray();
+ for (size_t i=0; i < nCount; i++)
+ {
+ // use given name if for exactly this range, otherwise just format
+ ScRange const & rRange = rRanges[ i ];
+ if (m_aNamedEntries.empty() ||
+ !lcl_FindEntryName(m_aNamedEntries, rRange, aRangeStr))
+ {
+ aRangeStr = rRange.Format(rDoc, ScRefFlags::VALID | ScRefFlags::TAB_3D);
+ }
+ pAry[i] = aRangeStr;
+ }
+ return aSeq;
+ }
+ return {};
+}
+
+sal_Bool SAL_CALL ScCellRangesObj::hasByName( const OUString& aName )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ const ScRangeList& rRanges = GetRangeList();
+ ScRange aRange;
+ return lcl_FindRangeOrEntry(m_aNamedEntries, rRanges, pDocSh,
+ aName, aRange);
+}
+
+// XEnumerationAccess
+
+uno::Reference<container::XEnumeration> SAL_CALL ScCellRangesObj::createEnumeration()
+{
+ SolarMutexGuard aGuard;
+ return new ScIndexEnumeration(this, "com.sun.star.sheet.SheetCellRangesEnumeration");
+}
+
+// XIndexAccess
+
+sal_Int32 SAL_CALL ScCellRangesObj::getCount()
+{
+ SolarMutexGuard aGuard;
+ const ScRangeList& rRanges = GetRangeList();
+ return rRanges.size();
+}
+
+uno::Any SAL_CALL ScCellRangesObj::getByIndex( sal_Int32 nIndex )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference<table::XCellRange> xRange(GetObjectByIndex_Impl(nIndex));
+ if (!xRange.is())
+ throw lang::IndexOutOfBoundsException();
+
+ return uno::Any(xRange);
+
+}
+
+uno::Type SAL_CALL ScCellRangesObj::getElementType()
+{
+ return cppu::UnoType<table::XCellRange>::get();
+}
+
+sal_Bool SAL_CALL ScCellRangesObj::hasElements()
+{
+ SolarMutexGuard aGuard;
+ const ScRangeList& rRanges = GetRangeList();
+ return !rRanges.empty();
+}
+
+// XServiceInfo
+OUString SAL_CALL ScCellRangesObj::getImplementationName()
+{
+ return "ScCellRangesObj";
+}
+
+sal_Bool SAL_CALL ScCellRangesObj::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence<OUString> SAL_CALL ScCellRangesObj::getSupportedServiceNames()
+{
+ return {SCSHEETCELLRANGES_SERVICE,
+ SCCELLPROPERTIES_SERVICE,
+ SCCHARPROPERTIES_SERVICE,
+ SCPARAPROPERTIES_SERVICE};
+}
+
+uno::Reference<table::XCellRange> ScCellRangeObj::CreateRangeFromDoc( const ScDocument& rDoc, const ScRange& rR )
+{
+ SfxObjectShell* pObjSh = rDoc.GetDocumentShell();
+ if ( auto pDocShell = dynamic_cast<ScDocShell*>( pObjSh) )
+ return new ScCellRangeObj( pDocShell, rR );
+ return nullptr;
+}
+
+ScCellRangeObj::ScCellRangeObj(ScDocShell* pDocSh, const ScRange& rR) :
+ ScCellRangesBase( pDocSh, rR ),
+ pRangePropSet( lcl_GetRangePropertySet() ),
+ aRange( rR )
+{
+ aRange.PutInOrder(); // beginning / end correct
+}
+
+ScCellRangeObj::~ScCellRangeObj()
+{
+}
+
+void ScCellRangeObj::RefChanged()
+{
+ ScCellRangesBase::RefChanged();
+
+ const ScRangeList& rRanges = GetRangeList();
+ OSL_ENSURE(rRanges.size() == 1, "What ranges ?!?!");
+ if ( !rRanges.empty() )
+ {
+ const ScRange & rFirst = rRanges[0];
+ aRange = rFirst;
+ aRange.PutInOrder();
+ }
+}
+
+uno::Any SAL_CALL ScCellRangeObj::queryInterface( const uno::Type& rType )
+{
+ SC_QUERYINTERFACE( sheet::XCellRangeAddressable )
+ SC_QUERYINTERFACE( table::XCellRange )
+ SC_QUERYINTERFACE( sheet::XSheetCellRange )
+ SC_QUERYINTERFACE( sheet::XArrayFormulaRange )
+ SC_QUERYINTERFACE( sheet::XArrayFormulaTokens )
+ SC_QUERYINTERFACE( sheet::XCellRangeData )
+ SC_QUERYINTERFACE( sheet::XCellRangeFormula )
+ SC_QUERYINTERFACE( sheet::XMultipleOperation )
+ SC_QUERYINTERFACE( util::XMergeable )
+ SC_QUERYINTERFACE( sheet::XCellSeries )
+ SC_QUERYINTERFACE( table::XAutoFormattable )
+ SC_QUERYINTERFACE( util::XSortable )
+ SC_QUERYINTERFACE( sheet::XSheetFilterableEx )
+ SC_QUERYINTERFACE( sheet::XSheetFilterable )
+ SC_QUERYINTERFACE( sheet::XSubTotalCalculatable )
+ SC_QUERYINTERFACE( table::XColumnRowRange )
+ SC_QUERYINTERFACE( util::XImportable )
+ SC_QUERYINTERFACE( sheet::XCellFormatRangesSupplier )
+ SC_QUERYINTERFACE( sheet::XUniqueCellFormatRangesSupplier )
+
+ return ScCellRangesBase::queryInterface( rType );
+}
+
+void SAL_CALL ScCellRangeObj::acquire() noexcept
+{
+ ScCellRangesBase::acquire();
+}
+
+void SAL_CALL ScCellRangeObj::release() noexcept
+{
+ ScCellRangesBase::release();
+}
+
+uno::Sequence<uno::Type> SAL_CALL ScCellRangeObj::getTypes()
+{
+ static const uno::Sequence<uno::Type> aTypes = comphelper::concatSequences(
+ ScCellRangesBase::getTypes(),
+ uno::Sequence<uno::Type>
+ {
+ cppu::UnoType<sheet::XCellRangeAddressable>::get(),
+ cppu::UnoType<sheet::XSheetCellRange>::get(),
+ cppu::UnoType<sheet::XArrayFormulaRange>::get(),
+ cppu::UnoType<sheet::XArrayFormulaTokens>::get(),
+ cppu::UnoType<sheet::XCellRangeData>::get(),
+ cppu::UnoType<sheet::XCellRangeFormula>::get(),
+ cppu::UnoType<sheet::XMultipleOperation>::get(),
+ cppu::UnoType<util::XMergeable>::get(),
+ cppu::UnoType<sheet::XCellSeries>::get(),
+ cppu::UnoType<table::XAutoFormattable>::get(),
+ cppu::UnoType<util::XSortable>::get(),
+ cppu::UnoType<sheet::XSheetFilterableEx>::get(),
+ cppu::UnoType<sheet::XSubTotalCalculatable>::get(),
+ cppu::UnoType<table::XColumnRowRange>::get(),
+ cppu::UnoType<util::XImportable>::get(),
+ cppu::UnoType<sheet::XCellFormatRangesSupplier>::get(),
+ cppu::UnoType<sheet::XUniqueCellFormatRangesSupplier>::get()
+ } );
+ return aTypes;
+}
+
+uno::Sequence<sal_Int8> SAL_CALL ScCellRangeObj::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// XCellRange
+
+// ColumnCount / RowCount vanished
+//! are used in Writer for tables ???
+
+uno::Reference<table::XCell> ScCellRangeObj::GetCellByPosition_Impl(
+ sal_Int32 nColumn, sal_Int32 nRow )
+{
+ ScDocShell* pDocSh = GetDocShell();
+ if (!pDocSh)
+ throw uno::RuntimeException();
+
+ if ( nColumn >= 0 && nRow >= 0 )
+ {
+ sal_Int32 nPosX = aRange.aStart.Col() + nColumn;
+ sal_Int32 nPosY = aRange.aStart.Row() + nRow;
+
+ if ( nPosX <= aRange.aEnd.Col() && nPosY <= aRange.aEnd.Row() )
+ {
+ ScAddress aNew( static_cast<SCCOL>(nPosX), static_cast<SCROW>(nPosY), aRange.aStart.Tab() );
+ return new ScCellObj( pDocSh, aNew );
+ }
+ }
+
+ throw lang::IndexOutOfBoundsException();
+}
+
+uno::Reference<table::XCell> SAL_CALL ScCellRangeObj::getCellByPosition(
+ sal_Int32 nColumn, sal_Int32 nRow )
+{
+ SolarMutexGuard aGuard;
+
+ return GetCellByPosition_Impl(nColumn, nRow);
+}
+
+uno::Reference<table::XCellRange> SAL_CALL ScCellRangeObj::getCellRangeByPosition(
+ sal_Int32 nLeft, sal_Int32 nTop, sal_Int32 nRight, sal_Int32 nBottom )
+{
+ SolarMutexGuard aGuard;
+
+ ScDocShell* pDocSh = GetDocShell();
+ if (!pDocSh)
+ throw uno::RuntimeException();
+
+ if ( nLeft >= 0 && nTop >= 0 && nRight >= 0 && nBottom >= 0 )
+ {
+ sal_Int32 nStartX = aRange.aStart.Col() + nLeft;
+ sal_Int32 nStartY = aRange.aStart.Row() + nTop;
+ sal_Int32 nEndX = aRange.aStart.Col() + nRight;
+ sal_Int32 nEndY = aRange.aStart.Row() + nBottom;
+
+ if ( nStartX <= nEndX && nEndX <= aRange.aEnd.Col() &&
+ nStartY <= nEndY && nEndY <= aRange.aEnd.Row() )
+ {
+ ScRange aNew( static_cast<SCCOL>(nStartX), static_cast<SCROW>(nStartY), aRange.aStart.Tab(),
+ static_cast<SCCOL>(nEndX), static_cast<SCROW>(nEndY), aRange.aEnd.Tab() );
+ return new ScCellRangeObj( pDocSh, aNew );
+ }
+ }
+
+ throw lang::IndexOutOfBoundsException();
+}
+
+uno::Reference<table::XCellRange> SAL_CALL ScCellRangeObj::getCellRangeByName(
+ const OUString& aName )
+{
+ return getCellRangeByName( aName, ScAddress::detailsOOOa1 );
+}
+
+uno::Reference<table::XCellRange> ScCellRangeObj::getCellRangeByName(
+ const OUString& aName, const ScAddress::Details& rDetails )
+{
+ // name refers to the whole document (with the range's table as default),
+ // valid only if the range is within this range
+
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ ScDocument& rDoc = pDocSh->GetDocument();
+ SCTAB nTab = aRange.aStart.Tab();
+
+ ScRange aCellRange;
+ bool bFound = false;
+ ScRefFlags nParse = aCellRange.ParseAny( aName, rDoc, rDetails );
+ if ( nParse & ScRefFlags::VALID )
+ {
+ if ( !(nParse & ScRefFlags::TAB_3D) ) // no sheet specified -> this sheet
+ {
+ aCellRange.aStart.SetTab(nTab);
+ aCellRange.aEnd.SetTab(nTab);
+ }
+ bFound = true;
+ }
+ else
+ {
+ if ( ScRangeUtil::MakeRangeFromName( aName, rDoc, nTab, aCellRange, RUTL_NAMES, rDetails) ||
+ ScRangeUtil::MakeRangeFromName( aName, rDoc, nTab, aCellRange, RUTL_DBASE, rDetails))
+ bFound = true;
+ }
+
+ if (bFound) // valid only if within this object's range
+ {
+ if (!aRange.Contains(aCellRange))
+ bFound = false;
+ }
+
+ if (bFound)
+ {
+ if ( aCellRange.aStart == aCellRange.aEnd )
+ return new ScCellObj( pDocSh, aCellRange.aStart );
+ else
+ return new ScCellRangeObj( pDocSh, aCellRange );
+ }
+ }
+
+ throw uno::RuntimeException();
+}
+
+// XColumnRowRange
+
+uno::Reference<table::XTableColumns> SAL_CALL ScCellRangeObj::getColumns()
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if (pDocSh)
+ return new ScTableColumnsObj( pDocSh, aRange.aStart.Tab(),
+ aRange.aStart.Col(), aRange.aEnd.Col() );
+
+ OSL_FAIL("Document invalid");
+ return nullptr;
+}
+
+uno::Reference<table::XTableRows> SAL_CALL ScCellRangeObj::getRows()
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if (pDocSh)
+ return new ScTableRowsObj( pDocSh, aRange.aStart.Tab(),
+ aRange.aStart.Row(), aRange.aEnd.Row() );
+
+ OSL_FAIL("Document invalid");
+ return nullptr;
+}
+
+// XAddressableCellRange
+
+table::CellRangeAddress SAL_CALL ScCellRangeObj::getRangeAddress()
+{
+ SolarMutexGuard aGuard;
+ table::CellRangeAddress aRet;
+ ScUnoConversion::FillApiRange( aRet, aRange );
+ return aRet;
+}
+
+// XSheetCellRange
+
+uno::Reference<sheet::XSpreadsheet> SAL_CALL ScCellRangeObj::getSpreadsheet()
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if (pDocSh)
+ return new ScTableSheetObj( pDocSh, aRange.aStart.Tab() );
+
+ OSL_FAIL("Document invalid");
+ return nullptr;
+}
+
+// XArrayFormulaRange
+
+OUString SAL_CALL ScCellRangeObj::getArrayFormula()
+{
+ SolarMutexGuard aGuard;
+
+ // Matrix formula if clearly part of a matrix (so when start and end of
+ // the block belong to the same matrix) else empty string.
+
+ ScDocShell* pDocSh = GetDocShell();
+ if (!pDocSh)
+ return OUString();
+
+ ScDocument& rDoc = pDocSh->GetDocument();
+ ScRefCellValue aCell1(rDoc, aRange.aStart);
+ ScRefCellValue aCell2(rDoc, aRange.aEnd);
+ if (aCell1.meType == CELLTYPE_FORMULA && aCell2.meType == CELLTYPE_FORMULA)
+ {
+ const ScFormulaCell* pFCell1 = aCell1.mpFormula;
+ const ScFormulaCell* pFCell2 = aCell2.mpFormula;
+ ScAddress aStart1;
+ ScAddress aStart2;
+ if (pFCell1->GetMatrixOrigin(rDoc, aStart1) && pFCell2->GetMatrixOrigin(rDoc, aStart2))
+ {
+ if (aStart1 == aStart2) // both the same matrix
+ return pFCell1->GetFormula(); // it doesn't matter from which cell
+ }
+ }
+ return OUString();
+}
+
+void ScCellRangeObj::SetArrayFormula_Impl(const OUString& rFormula,
+ const formula::FormulaGrammar::Grammar eGrammar)
+{
+ ScDocShell* pDocSh = GetDocShell();
+ if (!pDocSh)
+ return;
+
+ if ( !rFormula.isEmpty() )
+ {
+ if ( comphelper::getFromUnoTunnel<ScTableSheetObj>( static_cast<cppu::OWeakObject*>(this) ) )
+ {
+ // don't set array formula for sheet object
+ throw uno::RuntimeException();
+ }
+
+ pDocSh->GetDocFunc().EnterMatrix( aRange, nullptr, nullptr, rFormula, true, true, OUString()/*rFormulaNmsp*/, eGrammar );
+ }
+ else
+ {
+ // empty string -> erase array formula
+ ScMarkData aMark(GetDocument()->GetSheetLimits());
+ aMark.SetMarkArea( aRange );
+ aMark.SelectTable( aRange.aStart.Tab(), true );
+ pDocSh->GetDocFunc().DeleteContents( aMark, InsertDeleteFlags::CONTENTS, true, true );
+ }
+}
+
+void SAL_CALL ScCellRangeObj::setArrayFormula( const OUString& aFormula )
+{
+ SolarMutexGuard aGuard;
+ // GRAM_API for API compatibility.
+ SetArrayFormula_Impl( aFormula, formula::FormulaGrammar::GRAM_API);
+}
+
+// XArrayFormulaTokens
+uno::Sequence<sheet::FormulaToken> SAL_CALL ScCellRangeObj::getArrayTokens()
+{
+ SolarMutexGuard aGuard;
+
+ // same cell logic as in getArrayFormula
+
+ uno::Sequence<sheet::FormulaToken> aSequence;
+ ScDocShell* pDocSh = GetDocShell();
+ if (!pDocSh)
+ return aSequence;
+
+ ScDocument& rDoc = pDocSh->GetDocument();
+ ScRefCellValue aCell1(rDoc, aRange.aStart);
+ ScRefCellValue aCell2(rDoc, aRange.aEnd);
+ if (aCell1.meType == CELLTYPE_FORMULA && aCell2.meType == CELLTYPE_FORMULA)
+ {
+ const ScFormulaCell* pFCell1 = aCell1.mpFormula;
+ const ScFormulaCell* pFCell2 = aCell2.mpFormula;
+ ScAddress aStart1;
+ ScAddress aStart2;
+ if (pFCell1->GetMatrixOrigin(rDoc, aStart1) && pFCell2->GetMatrixOrigin(rDoc, aStart2))
+ {
+ if (aStart1 == aStart2)
+ {
+ const ScTokenArray* pTokenArray = pFCell1->GetCode();
+ if (pTokenArray)
+ ScTokenConversion::ConvertToTokenSequence(rDoc, aSequence, *pTokenArray);
+ }
+ }
+ }
+
+ return aSequence;
+}
+
+void SAL_CALL ScCellRangeObj::setArrayTokens( const uno::Sequence<sheet::FormulaToken>& rTokens )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( !pDocSh )
+ return;
+
+ if ( rTokens.hasElements() )
+ {
+ if ( comphelper::getFromUnoTunnel<ScTableSheetObj>( static_cast<cppu::OWeakObject*>(this) ) )
+ {
+ throw uno::RuntimeException();
+ }
+
+ ScDocument& rDoc = pDocSh->GetDocument();
+ ScTokenArray aTokenArray(rDoc);
+ (void)ScTokenConversion::ConvertToTokenArray( rDoc, aTokenArray, rTokens );
+
+ // Actually GRAM_API is a don't-care here because of the token
+ // array being set, it fits with other API compatibility grammars
+ // though.
+ pDocSh->GetDocFunc().EnterMatrix( aRange, nullptr, &aTokenArray, OUString(), true, true, OUString(), formula::FormulaGrammar::GRAM_API );
+ }
+ else
+ {
+ // empty sequence -> erase array formula
+ ScMarkData aMark(pDocSh->GetDocument().GetSheetLimits());
+ aMark.SetMarkArea( aRange );
+ aMark.SelectTable( aRange.aStart.Tab(), true );
+ pDocSh->GetDocFunc().DeleteContents( aMark, InsertDeleteFlags::CONTENTS, true, true );
+ }
+}
+
+// XCellRangeData
+
+uno::Sequence< uno::Sequence<uno::Any> > SAL_CALL ScCellRangeObj::getDataArray()
+{
+ SolarMutexGuard aGuard;
+
+ if ( comphelper::getFromUnoTunnel<ScTableSheetObj>( static_cast<cppu::OWeakObject*>(this) ) )
+ {
+ // don't create a data array for the sheet
+ throw uno::RuntimeException();
+ }
+
+ ScDocShell* pDocSh = GetDocShell();
+ if (pDocSh)
+ {
+ uno::Any aAny;
+ // bAllowNV = TRUE: errors as void
+ if ( ScRangeToSequence::FillMixedArray( aAny, pDocSh->GetDocument(), aRange, true ) )
+ {
+ uno::Sequence< uno::Sequence<uno::Any> > aSeq;
+ if ( aAny >>= aSeq )
+ return aSeq; // success
+ }
+ }
+
+ throw uno::RuntimeException(); // no other exceptions specified
+}
+
+void SAL_CALL ScCellRangeObj::setDataArray(
+ const uno::Sequence< uno::Sequence<uno::Any> >& aArray )
+{
+ SolarMutexGuard aGuard;
+
+ bool bDone = false;
+ ScDocShell* pDocSh = GetDocShell();
+ if (pDocSh)
+ {
+ //! move lcl_PutDataArray to docfunc?
+ bDone = lcl_PutDataArray( *pDocSh, aRange, aArray );
+ }
+
+ if (!bDone)
+ throw uno::RuntimeException(); // no other exceptions specified
+}
+
+// XCellRangeFormula
+
+uno::Sequence< uno::Sequence<OUString> > SAL_CALL ScCellRangeObj::getFormulaArray()
+{
+ SolarMutexGuard aGuard;
+
+ if ( comphelper::getFromUnoTunnel<ScTableSheetObj>( static_cast<cppu::OWeakObject*>(this) ) )
+ {
+ // don't create a data array for the sheet
+ throw uno::RuntimeException();
+ }
+
+ ScDocShell* pDocSh = GetDocShell();
+ if (pDocSh)
+ {
+ SCCOL nStartCol = aRange.aStart.Col();
+ SCROW nStartRow = aRange.aStart.Row();
+ SCCOL nEndCol = aRange.aEnd.Col();
+ SCROW nEndRow = aRange.aEnd.Row();
+ SCCOL nColCount = nEndCol + 1 - nStartCol;
+ SCROW nRowCount = nEndRow + 1 - nStartRow;
+ SCTAB nTab = aRange.aStart.Tab();
+
+ uno::Sequence< uno::Sequence<OUString> > aRowSeq( nRowCount );
+ uno::Sequence<OUString>* pRowAry = aRowSeq.getArray();
+ for (SCROW nRowIndex = 0; nRowIndex < nRowCount; nRowIndex++)
+ {
+ uno::Sequence<OUString> aColSeq( nColCount );
+ OUString* pColAry = aColSeq.getArray();
+ for (SCCOL nColIndex = 0; nColIndex < nColCount; nColIndex++)
+ pColAry[nColIndex] = lcl_GetInputString( pDocSh->GetDocument(),
+ ScAddress( nStartCol+nColIndex, nStartRow+nRowIndex, nTab ), true );
+
+ pRowAry[nRowIndex] = aColSeq;
+ }
+
+ return aRowSeq;
+ }
+
+ throw uno::RuntimeException(); // no other exceptions specified
+}
+
+void SAL_CALL ScCellRangeObj::setFormulaArray(
+ const uno::Sequence< uno::Sequence<OUString> >& aArray )
+{
+ SolarMutexGuard aGuard;
+
+ bool bDone = false;
+ ScDocShell* pDocSh = GetDocShell();
+ if (pDocSh)
+ {
+ ScExternalRefManager::ApiGuard aExtRefGuard(pDocSh->GetDocument());
+
+ // GRAM_API for API compatibility.
+ bDone = lcl_PutFormulaArray( *pDocSh, aRange, aArray, formula::FormulaGrammar::GRAM_API );
+ }
+
+ if (!bDone)
+ throw uno::RuntimeException(); // no other exceptions specified
+}
+
+// XMultipleOperation
+
+void SAL_CALL ScCellRangeObj::setTableOperation( const table::CellRangeAddress& aFormulaRange,
+ sheet::TableOperationMode nMode,
+ const table::CellAddress& aColumnCell,
+ const table::CellAddress& aRowCell )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if (!pDocSh)
+ return;
+
+ bool bError = false;
+ ScTabOpParam aParam;
+ aParam.aRefFormulaCell = ScRefAddress( static_cast<SCCOL>(aFormulaRange.StartColumn),
+ static_cast<SCROW>(aFormulaRange.StartRow), aFormulaRange.Sheet );
+ aParam.aRefFormulaEnd = ScRefAddress( static_cast<SCCOL>(aFormulaRange.EndColumn),
+ static_cast<SCROW>(aFormulaRange.EndRow), aFormulaRange.Sheet );
+ aParam.aRefRowCell = ScRefAddress( static_cast<SCCOL>(aRowCell.Column),
+ static_cast<SCROW>(aRowCell.Row), aRowCell.Sheet );
+ aParam.aRefColCell = ScRefAddress( static_cast<SCCOL>(aColumnCell.Column),
+ static_cast<SCROW>(aColumnCell.Row), aColumnCell.Sheet );
+
+ switch (nMode)
+ {
+ case sheet::TableOperationMode_COLUMN:
+ aParam.meMode = ScTabOpParam::Column;
+ break;
+ case sheet::TableOperationMode_ROW:
+ aParam.meMode = ScTabOpParam::Row;
+ break;
+ case sheet::TableOperationMode_BOTH:
+ aParam.meMode = ScTabOpParam::Both;
+ break;
+ default:
+ bError = true;
+ }
+
+ if (!bError)
+ pDocSh->GetDocFunc().TabOp( aRange, nullptr, aParam, true, true );
+}
+
+// XMergeable
+
+void SAL_CALL ScCellRangeObj::merge( sal_Bool bMerge )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( !pDocSh )
+ return;
+
+ ScCellMergeOption aMergeOption(
+ aRange.aStart.Col(), aRange.aStart.Row(),
+ aRange.aEnd.Col(), aRange.aEnd.Row(), false);
+ aMergeOption.maTabs.insert(aRange.aStart.Tab());
+ if ( bMerge )
+ pDocSh->GetDocFunc().MergeCells( aMergeOption, false, true, true );
+ else
+ pDocSh->GetDocFunc().UnmergeCells( aMergeOption, true, nullptr );
+
+ //! Catch error?
+}
+
+sal_Bool SAL_CALL ScCellRangeObj::getIsMerged()
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ return pDocSh && pDocSh->GetDocument().HasAttrib( aRange, HasAttrFlags::Merged );
+}
+
+// XCellSeries
+
+void SAL_CALL ScCellRangeObj::fillSeries( sheet::FillDirection nFillDirection,
+ sheet::FillMode nFillMode, sheet::FillDateMode nFillDateMode,
+ double fStep, double fEndValue )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( !pDocSh )
+ return;
+
+ bool bError = false;
+
+ FillDir eDir = FILL_TO_BOTTOM;
+ switch (nFillDirection)
+ {
+ case sheet::FillDirection_TO_BOTTOM:
+ eDir = FILL_TO_BOTTOM;
+ break;
+ case sheet::FillDirection_TO_RIGHT:
+ eDir = FILL_TO_RIGHT;
+ break;
+ case sheet::FillDirection_TO_TOP:
+ eDir = FILL_TO_TOP;
+ break;
+ case sheet::FillDirection_TO_LEFT:
+ eDir = FILL_TO_LEFT;
+ break;
+ default:
+ bError = true;
+ }
+
+ FillCmd eCmd = FILL_SIMPLE;
+ switch ( nFillMode )
+ {
+ case sheet::FillMode_SIMPLE:
+ eCmd = FILL_SIMPLE;
+ break;
+ case sheet::FillMode_LINEAR:
+ eCmd = FILL_LINEAR;
+ break;
+ case sheet::FillMode_GROWTH:
+ eCmd = FILL_GROWTH;
+ break;
+ case sheet::FillMode_DATE:
+ eCmd = FILL_DATE;
+ break;
+ case sheet::FillMode_AUTO:
+ eCmd = FILL_AUTO;
+ break;
+ default:
+ bError = true;
+ }
+
+ FillDateCmd eDateCmd = FILL_DAY;
+ switch ( nFillDateMode )
+ {
+ case sheet::FillDateMode_FILL_DATE_DAY:
+ eDateCmd = FILL_DAY;
+ break;
+ case sheet::FillDateMode_FILL_DATE_WEEKDAY:
+ eDateCmd = FILL_WEEKDAY;
+ break;
+ case sheet::FillDateMode_FILL_DATE_MONTH:
+ eDateCmd = FILL_MONTH;
+ break;
+ case sheet::FillDateMode_FILL_DATE_YEAR:
+ eDateCmd = FILL_YEAR;
+ break;
+ default:
+ bError = true;
+ }
+
+ if (!bError)
+ pDocSh->GetDocFunc().FillSeries( aRange, nullptr, eDir, eCmd, eDateCmd,
+ MAXDOUBLE, fStep, fEndValue, true );
+}
+
+void SAL_CALL ScCellRangeObj::fillAuto( sheet::FillDirection nFillDirection,
+ sal_Int32 nSourceCount )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( !(pDocSh && nSourceCount) )
+ return;
+
+ ScRange aSourceRange(aRange);
+ SCCOLROW nCount = 0; // "Dest-Count"
+ FillDir eDir = FILL_TO_BOTTOM;
+ bool bError = false;
+ switch (nFillDirection)
+ {
+ case sheet::FillDirection_TO_BOTTOM:
+ aSourceRange.aEnd.SetRow( static_cast<SCROW>( aSourceRange.aStart.Row() + nSourceCount - 1 ) );
+ nCount = aRange.aEnd.Row() - aSourceRange.aEnd.Row();
+ eDir = FILL_TO_BOTTOM;
+ break;
+ case sheet::FillDirection_TO_RIGHT:
+ aSourceRange.aEnd.SetCol( static_cast<SCCOL>( aSourceRange.aStart.Col() + nSourceCount - 1 ) );
+ nCount = aRange.aEnd.Col() - aSourceRange.aEnd.Col();
+ eDir = FILL_TO_RIGHT;
+ break;
+ case sheet::FillDirection_TO_TOP:
+ aSourceRange.aStart.SetRow( static_cast<SCROW>( aSourceRange.aEnd.Row() - nSourceCount + 1 ) );
+ nCount = aSourceRange.aStart.Row() - aRange.aStart.Row();
+ eDir = FILL_TO_TOP;
+ break;
+ case sheet::FillDirection_TO_LEFT:
+ aSourceRange.aStart.SetCol( static_cast<SCCOL>( aSourceRange.aEnd.Col() - nSourceCount + 1 ) );
+ nCount = aSourceRange.aStart.Col() - aRange.aStart.Col();
+ eDir = FILL_TO_LEFT;
+ break;
+ default:
+ bError = true;
+ }
+ const ScDocument& rDoc = pDocSh->GetDocument();
+ if (nCount < 0 || nCount > rDoc.MaxRow()) // overflow
+ bError = true;
+
+ if (!bError)
+ pDocSh->GetDocFunc().FillAuto( aSourceRange, nullptr, eDir, nCount, true );
+}
+
+// XAutoFormattable
+
+void SAL_CALL ScCellRangeObj::autoFormat( const OUString& aName )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ ScAutoFormat* pAutoFormat = ScGlobal::GetOrCreateAutoFormat();
+ ScAutoFormat::const_iterator it = pAutoFormat->find(aName);
+ if (it == pAutoFormat->end())
+ throw lang::IllegalArgumentException();
+
+ ScAutoFormat::const_iterator itBeg = pAutoFormat->begin();
+ size_t nIndex = std::distance(itBeg, it);
+ pDocSh->GetDocFunc().AutoFormat(aRange, nullptr, nIndex, true);
+
+ }
+}
+
+// XSortable
+
+uno::Sequence<beans::PropertyValue> SAL_CALL ScCellRangeObj::createSortDescriptor()
+{
+ SolarMutexGuard aGuard;
+ ScSortParam aParam;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ // create DB-Area only during execution; API always the exact area
+ ScDBData* pData = pDocSh->GetDBData( aRange, SC_DB_OLD, ScGetDBSelection::ForceMark );
+ if (pData)
+ {
+ pData->GetSortParam(aParam);
+
+ // SortDescriptor contains the counted fields inside the area
+ ScRange aDBRange;
+ pData->GetArea(aDBRange);
+ SCCOLROW nFieldStart = aParam.bByRow ?
+ static_cast<SCCOLROW>(aDBRange.aStart.Col()) :
+ static_cast<SCCOLROW>(aDBRange.aStart.Row());
+ for (sal_uInt16 i=0; i<aParam.GetSortKeyCount(); i++)
+ if ( aParam.maKeyState[i].bDoSort && aParam.maKeyState[i].nField >= nFieldStart )
+ aParam.maKeyState[i].nField -= nFieldStart;
+ }
+ }
+
+ uno::Sequence<beans::PropertyValue> aSeq( ScSortDescriptor::GetPropertyCount() );
+ ScSortDescriptor::FillProperties( aSeq, aParam );
+ return aSeq;
+}
+
+void SAL_CALL ScCellRangeObj::sort( const uno::Sequence<beans::PropertyValue>& aDescriptor )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if (!pDocSh)
+ return;
+
+ sal_uInt16 i;
+ ScSortParam aParam;
+ ScDBData* pData = pDocSh->GetDBData( aRange, SC_DB_MAKE, ScGetDBSelection::ForceMark ); // if needed create area
+ if (pData)
+ {
+ // get old settings if not everything is set anew
+ pData->GetSortParam(aParam);
+ SCCOLROW nOldStart = aParam.bByRow ?
+ static_cast<SCCOLROW>(aRange.aStart.Col()) :
+ static_cast<SCCOLROW>(aRange.aStart.Row());
+ for (i=0; i<aParam.GetSortKeyCount(); i++)
+ if ( aParam.maKeyState[i].bDoSort && aParam.maKeyState[i].nField >= nOldStart )
+ aParam.maKeyState[i].nField -= nOldStart;
+ }
+
+ ScSortDescriptor::FillSortParam( aParam, aDescriptor );
+
+ // SortDescriptor contains the counted fields inside the area
+ // ByRow can be changed during execution of FillSortParam
+ SCCOLROW nFieldStart = aParam.bByRow ?
+ static_cast<SCCOLROW>(aRange.aStart.Col()) :
+ static_cast<SCCOLROW>(aRange.aStart.Row());
+ SCCOLROW nFieldEnd = aParam.bByRow ?
+ static_cast<SCCOLROW>(aRange.aEnd.Col()) :
+ static_cast<SCCOLROW>(aRange.aEnd.Row());
+ for (i=0; i<aParam.GetSortKeyCount(); i++)
+ {
+ aParam.maKeyState[i].nField += nFieldStart;
+ // tdf#103632 - sanity check poorly behaved macros.
+ if (aParam.maKeyState[i].nField > nFieldEnd)
+ aParam.maKeyState[i].nField = nFieldEnd;
+ }
+
+ SCTAB nTab = aRange.aStart.Tab();
+ aParam.nCol1 = aRange.aStart.Col();
+ aParam.nRow1 = aRange.aStart.Row();
+ aParam.nCol2 = aRange.aEnd.Col();
+ aParam.nRow2 = aRange.aEnd.Row();
+
+ pDocSh->GetDBData( aRange, SC_DB_MAKE, ScGetDBSelection::ForceMark ); // if needed create area
+
+ ScDBDocFunc aFunc(*pDocSh); // area must be created
+ (void)aFunc.Sort( nTab, aParam, true, true, true );
+}
+
+// XFilterable
+
+uno::Reference<sheet::XSheetFilterDescriptor> SAL_CALL ScCellRangeObj::createFilterDescriptor(
+ sal_Bool bEmpty )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ rtl::Reference<ScFilterDescriptor> pNew = new ScFilterDescriptor(pDocSh);
+ if ( !bEmpty && pDocSh )
+ {
+ // create DB-Area only during execution; API always the exact area
+ ScDBData* pData = pDocSh->GetDBData( aRange, SC_DB_OLD, ScGetDBSelection::ForceMark );
+ if (pData)
+ {
+ ScQueryParam aParam;
+ pData->GetQueryParam(aParam);
+ // FilterDescriptor contains the counted fields inside the area
+ ScRange aDBRange;
+ pData->GetArea(aDBRange);
+ SCCOLROW nFieldStart = aParam.bByRow ?
+ static_cast<SCCOLROW>(aDBRange.aStart.Col()) :
+ static_cast<SCCOLROW>(aDBRange.aStart.Row());
+ SCSIZE nCount = aParam.GetEntryCount();
+ for (SCSIZE i=0; i<nCount; i++)
+ {
+ ScQueryEntry& rEntry = aParam.GetEntry(i);
+ if (rEntry.bDoQuery && rEntry.nField >= nFieldStart)
+ rEntry.nField -= nFieldStart;
+ }
+ pNew->SetParam(aParam);
+ }
+ }
+ return pNew;
+}
+
+void SAL_CALL ScCellRangeObj::filter( const uno::Reference<sheet::XSheetFilterDescriptor>& xDescriptor )
+{
+ SolarMutexGuard aGuard;
+
+ if (!xDescriptor.is()) return;
+
+ // This could be theoretically an unknown object, so only use the
+ // public XSheetFilterDescriptor interface to copy the data into a
+ // ScFilterDescriptor object:
+ //! if it already a ScFilterDescriptor is, direct via getImplementation?
+
+ ScDocShell* pDocSh = GetDocShell();
+ rtl::Reference<ScFilterDescriptor> xImpl(new ScFilterDescriptor(pDocSh));
+ uno::Reference< sheet::XSheetFilterDescriptor2 > xDescriptor2( xDescriptor, uno::UNO_QUERY );
+ if ( xDescriptor2.is() )
+ {
+ xImpl->setFilterFields2( xDescriptor2->getFilterFields2() );
+ }
+ else
+ {
+ xImpl->setFilterFields( xDescriptor->getFilterFields() );
+ }
+ // the rest are now properties...
+
+ uno::Reference<beans::XPropertySet> xPropSet( xDescriptor, uno::UNO_QUERY );
+ if (xPropSet.is())
+ lcl_CopyProperties(*xImpl, *xPropSet);
+
+ if (!pDocSh)
+ return;
+
+ ScQueryParam aParam = xImpl->GetParam();
+ // FilterDescriptor contains the counted fields inside the area
+ SCCOLROW nFieldStart = aParam.bByRow ?
+ static_cast<SCCOLROW>(aRange.aStart.Col()) :
+ static_cast<SCCOLROW>(aRange.aStart.Row());
+ SCSIZE nCount = aParam.GetEntryCount();
+ svl::SharedStringPool& rPool = pDocSh->GetDocument().GetSharedStringPool();
+ for (SCSIZE i=0; i<nCount; i++)
+ {
+ ScQueryEntry& rEntry = aParam.GetEntry(i);
+ if (rEntry.bDoQuery)
+ {
+ rEntry.nField += nFieldStart;
+ // dialog always shows the string -> must match the value
+ ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems();
+ rItems.resize(1);
+ ScQueryEntry::Item& rItem = rItems.front();
+ if (rItem.meType != ScQueryEntry::ByString)
+ {
+ OUString aStr;
+ pDocSh->GetDocument().GetFormatTable()->GetInputLineString(rItem.mfVal, 0, aStr);
+ rItem.maString = rPool.intern(aStr);
+ }
+ }
+ }
+
+ SCTAB nTab = aRange.aStart.Tab();
+ aParam.nCol1 = aRange.aStart.Col();
+ aParam.nRow1 = aRange.aStart.Row();
+ aParam.nCol2 = aRange.aEnd.Col();
+ aParam.nRow2 = aRange.aEnd.Row();
+
+ pDocSh->GetDBData( aRange, SC_DB_MAKE, ScGetDBSelection::ForceMark ); // if needed create area
+
+ //! keep source range in filter descriptor
+ //! if created by createFilterDescriptorByObject ???
+
+ ScDBDocFunc aFunc(*pDocSh);
+ aFunc.Query( nTab, aParam, nullptr, true, true ); // area must be created
+}
+
+//! get/setAutoFilter as properties!!!
+
+// XAdvancedFilterSource
+
+uno::Reference<sheet::XSheetFilterDescriptor> SAL_CALL ScCellRangeObj::createFilterDescriptorByObject(
+ const uno::Reference<sheet::XSheetFilterable>& xObject )
+{
+ SolarMutexGuard aGuard;
+
+ // this here is not the area, which will be filtered, instead the area
+ // with the query
+
+ uno::Reference<sheet::XCellRangeAddressable> xAddr( xObject, uno::UNO_QUERY );
+
+ ScDocShell* pDocSh = GetDocShell();
+ if ( !pDocSh || !xAddr.is() )
+ {
+ OSL_FAIL("no document or no area");
+ return nullptr;
+ }
+
+ //! check if xObject is in the same document
+
+ rtl::Reference<ScFilterDescriptor> pNew(new ScFilterDescriptor(pDocSh)); //! instead from object?
+
+ ScQueryParam aParam = pNew->GetParam();
+ aParam.bHasHeader = true;
+
+ table::CellRangeAddress aDataAddress(xAddr->getRangeAddress());
+ aParam.nCol1 = static_cast<SCCOL>(aDataAddress.StartColumn);
+ aParam.nRow1 = static_cast<SCROW>(aDataAddress.StartRow);
+ aParam.nCol2 = static_cast<SCCOL>(aDataAddress.EndColumn);
+ aParam.nRow2 = static_cast<SCROW>(aDataAddress.EndRow);
+ aParam.nTab = aDataAddress.Sheet;
+
+ ScDocument& rDoc = pDocSh->GetDocument();
+ if (!rDoc.CreateQueryParam(aRange, aParam))
+ return nullptr;
+
+ // FilterDescriptor contains the counted fields inside the area
+ SCCOLROW nFieldStart = aParam.bByRow ?
+ static_cast<SCCOLROW>(aDataAddress.StartColumn) :
+ static_cast<SCCOLROW>(aDataAddress.StartRow);
+ SCSIZE nCount = aParam.GetEntryCount();
+ for (SCSIZE i=0; i<nCount; i++)
+ {
+ ScQueryEntry& rEntry = aParam.GetEntry(i);
+ if (rEntry.bDoQuery && rEntry.nField >= nFieldStart)
+ rEntry.nField -= nFieldStart;
+ }
+
+ pNew->SetParam( aParam );
+ return pNew;
+}
+
+// XSubTotalSource
+
+uno::Reference<sheet::XSubTotalDescriptor> SAL_CALL ScCellRangeObj::createSubTotalDescriptor(
+ sal_Bool bEmpty )
+{
+ SolarMutexGuard aGuard;
+ rtl::Reference<ScSubTotalDescriptor> pNew = new ScSubTotalDescriptor;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( !bEmpty && pDocSh )
+ {
+ // create DB-Area only during execution; API always the exact area
+ ScDBData* pData = pDocSh->GetDBData( aRange, SC_DB_OLD, ScGetDBSelection::ForceMark );
+ if (pData)
+ {
+ ScSubTotalParam aParam;
+ pData->GetSubTotalParam(aParam);
+ // SubTotalDescriptor contains the counted fields inside the area
+ ScRange aDBRange;
+ pData->GetArea(aDBRange);
+ SCCOL nFieldStart = aDBRange.aStart.Col();
+ for (sal_uInt16 i=0; i<MAXSUBTOTAL; i++)
+ {
+ if ( aParam.bGroupActive[i] )
+ {
+ if ( aParam.nField[i] >= nFieldStart )
+ aParam.nField[i] = sal::static_int_cast<SCCOL>( aParam.nField[i] - nFieldStart );
+ for (SCCOL j=0; j<aParam.nSubTotals[i]; j++)
+ if ( aParam.pSubTotals[i][j] >= nFieldStart )
+ aParam.pSubTotals[i][j] = sal::static_int_cast<SCCOL>( aParam.pSubTotals[i][j] - nFieldStart );
+ }
+ }
+ pNew->SetParam(aParam);
+ }
+ }
+ return pNew;
+}
+
+void SAL_CALL ScCellRangeObj::applySubTotals(
+ const uno::Reference<sheet::XSubTotalDescriptor>& xDescriptor,
+ sal_Bool bReplace)
+{
+ SolarMutexGuard aGuard;
+
+ if (!xDescriptor.is()) return;
+
+ ScDocShell* pDocSh = GetDocShell();
+ ScSubTotalDescriptorBase* pImp =
+ comphelper::getFromUnoTunnel<ScSubTotalDescriptorBase>( xDescriptor );
+
+ if (!(pDocSh && pImp))
+ return;
+
+ ScSubTotalParam aParam;
+ pImp->GetData(aParam); // virtual method of base class
+
+ // SubTotalDescriptor contains the counted fields inside the area
+ SCCOL nFieldStart = aRange.aStart.Col();
+ for (sal_uInt16 i=0; i<MAXSUBTOTAL; i++)
+ {
+ if ( aParam.bGroupActive[i] )
+ {
+ aParam.nField[i] = sal::static_int_cast<SCCOL>( aParam.nField[i] + nFieldStart );
+ for (SCCOL j=0; j<aParam.nSubTotals[i]; j++)
+ aParam.pSubTotals[i][j] = sal::static_int_cast<SCCOL>( aParam.pSubTotals[i][j] + nFieldStart );
+ }
+ }
+
+ aParam.bReplace = bReplace;
+
+ SCTAB nTab = aRange.aStart.Tab();
+ aParam.nCol1 = aRange.aStart.Col();
+ aParam.nRow1 = aRange.aStart.Row();
+ aParam.nCol2 = aRange.aEnd.Col();
+ aParam.nRow2 = aRange.aEnd.Row();
+
+ pDocSh->GetDBData( aRange, SC_DB_MAKE, ScGetDBSelection::ForceMark ); // if needed create area
+
+ ScDBDocFunc aFunc(*pDocSh);
+ aFunc.DoSubTotals( nTab, aParam, true, true ); // area must be created
+}
+
+void SAL_CALL ScCellRangeObj::removeSubTotals()
+{
+ SolarMutexGuard aGuard;
+
+ ScDocShell* pDocSh = GetDocShell();
+ if (!pDocSh)
+ return;
+
+ ScSubTotalParam aParam;
+ ScDBData* pData = pDocSh->GetDBData( aRange, SC_DB_OLD, ScGetDBSelection::ForceMark );
+ if (pData)
+ pData->GetSubTotalParam(aParam); // also keep field entries during remove
+
+ aParam.bRemoveOnly = true;
+
+ SCTAB nTab = aRange.aStart.Tab();
+ aParam.nCol1 = aRange.aStart.Col();
+ aParam.nRow1 = aRange.aStart.Row();
+ aParam.nCol2 = aRange.aEnd.Col();
+ aParam.nRow2 = aRange.aEnd.Row();
+
+ pDocSh->GetDBData( aRange, SC_DB_MAKE, ScGetDBSelection::ForceMark ); // if needed create area
+
+ ScDBDocFunc aFunc(*pDocSh);
+ aFunc.DoSubTotals( nTab, aParam, true, true ); // are must be created
+}
+
+uno::Sequence<beans::PropertyValue> SAL_CALL ScCellRangeObj::createImportDescriptor( sal_Bool bEmpty )
+{
+ SolarMutexGuard aGuard;
+ ScImportParam aParam;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( !bEmpty && pDocSh )
+ {
+ // create DB-Area only during execution; API always the exact area
+ ScDBData* pData = pDocSh->GetDBData( aRange, SC_DB_OLD, ScGetDBSelection::ForceMark );
+ if (pData)
+ pData->GetImportParam(aParam);
+ }
+
+ uno::Sequence<beans::PropertyValue> aSeq( ScImportDescriptor::GetPropertyCount() );
+ ScImportDescriptor::FillProperties( aSeq, aParam );
+ return aSeq;
+}
+
+void SAL_CALL ScCellRangeObj::doImport( const uno::Sequence<beans::PropertyValue>& aDescriptor )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if (!pDocSh)
+ return;
+
+ ScImportParam aParam;
+ ScImportDescriptor::FillImportParam( aParam, aDescriptor );
+
+ SCTAB nTab = aRange.aStart.Tab();
+ aParam.nCol1 = aRange.aStart.Col();
+ aParam.nRow1 = aRange.aStart.Row();
+ aParam.nCol2 = aRange.aEnd.Col();
+ aParam.nRow2 = aRange.aEnd.Row();
+
+ //! TODO: could we get passed a valid result set by any means?
+
+ pDocSh->GetDBData( aRange, SC_DB_MAKE, ScGetDBSelection::ForceMark ); // if needed create area
+
+ ScDBDocFunc aFunc(*pDocSh); // are must be created
+ aFunc.DoImport( nTab, aParam, nullptr ); //! Api-Flag as parameter
+}
+
+// XCellFormatRangesSupplier
+
+uno::Reference<container::XIndexAccess> SAL_CALL ScCellRangeObj::getCellFormatRanges()
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ return new ScCellFormatsObj( pDocSh, aRange );
+ return nullptr;
+}
+
+// XUniqueCellFormatRangesSupplier
+
+uno::Reference<container::XIndexAccess> SAL_CALL ScCellRangeObj::getUniqueCellFormatRanges()
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ return new ScUniqueCellFormatsObj( pDocSh, aRange );
+ return nullptr;
+}
+
+// XPropertySet extended for Range-Properties
+
+uno::Reference<beans::XPropertySetInfo> SAL_CALL ScCellRangeObj::getPropertySetInfo()
+{
+ SolarMutexGuard aGuard;
+ static uno::Reference<beans::XPropertySetInfo> aRef(
+ new SfxItemPropertySetInfo( pRangePropSet->getPropertyMap() ));
+ return aRef;
+}
+
+void ScCellRangeObj::SetOnePropertyValue( const SfxItemPropertyMapEntry* pEntry, const uno::Any& aValue )
+{
+ // Range has only Position and Size in addition to ScCellRangesBase, both are ReadOnly
+ // -> nothing to do here
+
+ ScCellRangesBase::SetOnePropertyValue( pEntry, aValue );
+}
+
+void ScCellRangeObj::GetOnePropertyValue( const SfxItemPropertyMapEntry* pEntry, uno::Any& rAny )
+{
+ if ( !pEntry )
+ return;
+
+ if ( pEntry->nWID == SC_WID_UNO_POS )
+ {
+ ScDocShell* pDocSh = GetDocShell();
+ if (pDocSh)
+ {
+ // GetMMRect converts using HMM_PER_TWIPS, like the DrawingLayer
+ tools::Rectangle aMMRect(pDocSh->GetDocument().GetMMRect(
+ aRange.aStart.Col(), aRange.aStart.Row(),
+ aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aStart.Tab() ));
+ awt::Point aPos( aMMRect.Left(), aMMRect.Top() );
+ rAny <<= aPos;
+ }
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_SIZE )
+ {
+ ScDocShell* pDocSh = GetDocShell();
+ if (pDocSh)
+ {
+ // GetMMRect converts using HMM_PER_TWIPS, like the DrawingLayer
+ tools::Rectangle aMMRect = pDocSh->GetDocument().GetMMRect(
+ aRange.aStart.Col(), aRange.aStart.Row(),
+ aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aStart.Tab() );
+ Size aSize(aMMRect.GetSize());
+ awt::Size aAwtSize( aSize.Width(), aSize.Height() );
+ rAny <<= aAwtSize;
+ }
+ }
+ else
+ ScCellRangesBase::GetOnePropertyValue( pEntry, rAny );
+}
+
+const SfxItemPropertyMap& ScCellRangeObj::GetItemPropertyMap()
+{
+ return pRangePropSet->getPropertyMap();
+}
+
+// XServiceInfo
+
+OUString SAL_CALL ScCellRangeObj::getImplementationName()
+{
+ return "ScCellRangeObj";
+}
+
+sal_Bool SAL_CALL ScCellRangeObj::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence<OUString> SAL_CALL ScCellRangeObj::getSupportedServiceNames()
+{
+ return {SCSHEETCELLRANGE_SERVICE,
+ SCCELLRANGE_SERVICE,
+ SCCELLPROPERTIES_SERVICE,
+ SCCHARPROPERTIES_SERVICE,
+ SCPARAPROPERTIES_SERVICE};
+}
+
+const SvxItemPropertySet* ScCellObj::GetEditPropertySet()
+{
+ return lcl_GetEditPropertySet();
+}
+
+const SfxItemPropertyMap& ScCellObj::GetCellPropertyMap()
+{
+ return lcl_GetCellPropertySet()->getPropertyMap();
+}
+
+ScCellObj::ScCellObj(ScDocShell* pDocSh, const ScAddress& rP) :
+ ScCellRangeObj( pDocSh, ScRange(rP,rP) ),
+ pCellPropSet( lcl_GetCellPropertySet() ),
+ aCellPos( rP ),
+ nActionLockCount( 0 )
+{
+ // pUnoText is allocated on demand (GetUnoText)
+ // can't be aggregated because getString/setString is handled here
+}
+
+SvxUnoText& ScCellObj::GetUnoText()
+{
+ if (!mxUnoText.is())
+ {
+ mxUnoText.set(new ScCellTextObj(GetDocShell(), aCellPos));
+ if (nActionLockCount)
+ {
+ ScCellEditSource* pEditSource =
+ static_cast<ScCellEditSource*> (mxUnoText->GetEditSource());
+ if (pEditSource)
+ pEditSource->SetDoUpdateData(false);
+ }
+ }
+ return *mxUnoText;
+}
+
+ScCellObj::~ScCellObj()
+{
+}
+
+void ScCellObj::RefChanged()
+{
+ ScCellRangeObj::RefChanged();
+
+ const ScRangeList& rRanges = GetRangeList();
+ OSL_ENSURE(rRanges.size() == 1, "What ranges ?!?!");
+ if ( !rRanges.empty() )
+ {
+ aCellPos = rRanges[ 0 ].aStart;
+ }
+}
+
+uno::Any SAL_CALL ScCellObj::queryInterface( const uno::Type& rType )
+{
+ SC_QUERYINTERFACE( table::XCell )
+ SC_QUERYINTERFACE( table::XCell2 )
+ SC_QUERYINTERFACE( sheet::XFormulaTokens )
+ SC_QUERYINTERFACE( sheet::XCellAddressable )
+ SC_QUERYINTERFACE( text::XText )
+ SC_QUERYINTERFACE( text::XSimpleText )
+ SC_QUERYINTERFACE( text::XTextRange )
+ SC_QUERYINTERFACE( container::XEnumerationAccess )
+ SC_QUERYINTERFACE( container::XElementAccess )
+ SC_QUERYINTERFACE( sheet::XSheetAnnotationAnchor )
+ SC_QUERYINTERFACE( text::XTextFieldsSupplier )
+ SC_QUERYINTERFACE( document::XActionLockable )
+
+ return ScCellRangeObj::queryInterface( rType );
+}
+
+void SAL_CALL ScCellObj::acquire() noexcept
+{
+ ScCellRangeObj::acquire();
+}
+
+void SAL_CALL ScCellObj::release() noexcept
+{
+ ScCellRangeObj::release();
+}
+
+uno::Sequence<uno::Type> SAL_CALL ScCellObj::getTypes()
+{
+ static const uno::Sequence<uno::Type> aTypes = comphelper::concatSequences(
+ ScCellRangeObj::getTypes(),
+ uno::Sequence<uno::Type>
+ {
+ cppu::UnoType<table::XCell>::get(),
+ cppu::UnoType<sheet::XCellAddressable>::get(),
+ cppu::UnoType<text::XText>::get(),
+ cppu::UnoType<container::XEnumerationAccess>::get(),
+ cppu::UnoType<sheet::XSheetAnnotationAnchor>::get(),
+ cppu::UnoType<text::XTextFieldsSupplier>::get(),
+ cppu::UnoType<document::XActionLockable>::get(),
+ cppu::UnoType<sheet::XFormulaTokens>::get(),
+ cppu::UnoType<table::XCell2>::get()
+ } );
+ return aTypes;
+}
+
+uno::Sequence<sal_Int8> SAL_CALL ScCellObj::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// helper methods
+
+OUString ScCellObj::GetInputString_Impl(bool bEnglish) const // for getFormula / FormulaLocal
+{
+ if (GetDocShell())
+ return lcl_GetInputString( GetDocShell()->GetDocument(), aCellPos, bEnglish );
+ return OUString();
+}
+
+OUString ScCellObj::GetOutputString_Impl() const
+{
+ ScDocShell* pDocSh = GetDocShell();
+ OUString aVal;
+ if ( pDocSh )
+ {
+ ScDocument& rDoc = pDocSh->GetDocument();
+ ScRefCellValue aCell(rDoc, aCellPos);
+
+ aVal = ScCellFormat::GetOutputString(rDoc, aCellPos, aCell);
+ }
+ return aVal;
+}
+
+void ScCellObj::SetString_Impl(const OUString& rString, bool bInterpret, bool bEnglish)
+{
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ // GRAM_API for API compatibility.
+ (void)pDocSh->GetDocFunc().SetCellText(
+ aCellPos, rString, bInterpret, bEnglish, true, formula::FormulaGrammar::GRAM_API );
+ }
+}
+
+double ScCellObj::GetValue_Impl() const
+{
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ return pDocSh->GetDocument().GetValue( aCellPos );
+
+ return 0.0;
+}
+
+void ScCellObj::SetValue_Impl(double fValue)
+{
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ pDocSh->GetDocFunc().SetValueCell(aCellPos, fValue, false);
+}
+
+// only for XML import
+
+void ScCellObj::InputEnglishString( const OUString& rText )
+{
+ // This is like a mixture of setFormula and property FormulaLocal:
+ // The cell's number format is checked for "text", a new cell format may be set,
+ // but all parsing is in English.
+
+ ScDocShell* pDocSh = GetDocShell();
+ if (!pDocSh)
+ return;
+
+ ScDocument& rDoc = pDocSh->GetDocument();
+ SvNumberFormatter* pFormatter = rDoc.GetFormatTable();
+ sal_uInt32 nOldFormat = rDoc.GetNumberFormat( aCellPos );
+ if (pFormatter->GetType(nOldFormat) == SvNumFormatType::TEXT)
+ {
+ SetString_Impl(rText, false, false); // text cell
+ return;
+ }
+
+ ScDocFunc &rFunc = pDocSh->GetDocFunc();
+
+ ScInputStringType aRes =
+ ScStringUtil::parseInputString(*pFormatter, rText, LANGUAGE_ENGLISH_US);
+
+ if (aRes.meType != ScInputStringType::Unknown)
+ {
+ if ((nOldFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 && aRes.mnFormatType != SvNumFormatType::ALL)
+ {
+ // apply a format for the recognized type and the old format's language
+ sal_uInt32 nNewFormat = ScGlobal::GetStandardFormat(*pFormatter, nOldFormat, aRes.mnFormatType);
+ if (nNewFormat != nOldFormat)
+ {
+ ScPatternAttr aPattern( rDoc.GetPool() );
+ aPattern.GetItemSet().Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNewFormat ) );
+ // ATTR_LANGUAGE_FORMAT remains unchanged
+ rFunc.ApplyAttributes( *GetMarkData(), aPattern, true );
+ }
+ }
+ }
+ switch (aRes.meType)
+ {
+ case ScInputStringType::Formula:
+ rFunc.SetFormulaCell(
+ aCellPos,
+ new ScFormulaCell(rDoc, aCellPos, aRes.maText, formula::FormulaGrammar::GRAM_API),
+ false);
+ break;
+ case ScInputStringType::Number:
+ rFunc.SetValueCell(aCellPos, aRes.mfValue, false);
+ break;
+ case ScInputStringType::Text:
+ rFunc.SetStringOrEditCell(aCellPos, aRes.maText, false);
+ break;
+ default:
+ SetString_Impl(rText, false, false); // probably empty string
+ }
+}
+
+// XText
+
+uno::Reference<text::XTextCursor> SAL_CALL ScCellObj::createTextCursor()
+{
+ SolarMutexGuard aGuard;
+ return new ScCellTextCursor( *this );
+}
+
+uno::Reference<text::XTextCursor> SAL_CALL ScCellObj::createTextCursorByRange(
+ const uno::Reference<text::XTextRange>& aTextPosition )
+{
+ SolarMutexGuard aGuard;
+ rtl::Reference<SvxUnoTextCursor> pCursor = new ScCellTextCursor( *this );
+
+ SvxUnoTextRangeBase* pRange = comphelper::getFromUnoTunnel<SvxUnoTextRangeBase>( aTextPosition );
+ if(pRange)
+ pCursor->SetSelection( pRange->GetSelection() );
+ else
+ {
+ ScCellTextCursor* pOther = comphelper::getFromUnoTunnel<ScCellTextCursor>( aTextPosition );
+ if(!pOther)
+ throw uno::RuntimeException();
+
+ pCursor->SetSelection( pOther->GetSelection() );
+
+ }
+
+ return pCursor;
+}
+
+OUString SAL_CALL ScCellObj::getString()
+{
+ SolarMutexGuard aGuard;
+ return GetOutputString_Impl();
+}
+
+void SAL_CALL ScCellObj::setString( const OUString& aText )
+{
+ SolarMutexGuard aGuard;
+ SetString_Impl(aText, false, false); // always text
+
+ // don't create pUnoText here if not there
+ if (mxUnoText.is())
+ mxUnoText->SetSelection(ESelection( 0,0, 0,aText.getLength() ));
+}
+
+void SAL_CALL ScCellObj::insertString( const uno::Reference<text::XTextRange>& xRange,
+ const OUString& aString, sal_Bool bAbsorb )
+{
+ // special handling for ScCellTextCursor is no longer needed,
+ // SvxUnoText::insertString checks for SvxUnoTextRangeBase instead of SvxUnoTextRange
+
+ SolarMutexGuard aGuard;
+ GetUnoText().insertString(xRange, aString, bAbsorb);
+}
+
+void SAL_CALL ScCellObj::insertControlCharacter( const uno::Reference<text::XTextRange>& xRange,
+ sal_Int16 nControlCharacter, sal_Bool bAbsorb )
+{
+ SolarMutexGuard aGuard;
+ GetUnoText().insertControlCharacter(xRange, nControlCharacter, bAbsorb);
+}
+
+void SAL_CALL ScCellObj::insertTextContent( const uno::Reference<text::XTextRange >& xRange,
+ const uno::Reference<text::XTextContent >& xContent,
+ sal_Bool bAbsorb )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh && xContent.is() )
+ {
+ ScEditFieldObj* pCellField = comphelper::getFromUnoTunnel<ScEditFieldObj>(xContent);
+ SvxUnoTextRangeBase* pTextRange = comphelper::getFromUnoTunnel<ScCellTextCursor>( xRange );
+
+ if ( pCellField && !pCellField->IsInserted() && pTextRange )
+ {
+ SvxEditSource* pEditSource = pTextRange->GetEditSource();
+ ESelection aSelection(pTextRange->GetSelection());
+
+ if (!bAbsorb)
+ {
+ // do not replace -> append
+ aSelection.Adjust();
+ aSelection.nStartPara = aSelection.nEndPara;
+ aSelection.nStartPos = aSelection.nEndPos;
+ }
+
+ if (pCellField->GetFieldType() == text::textfield::Type::TABLE)
+ pCellField->setPropertyValue(SC_UNONAME_TABLEPOS, uno::Any(sal_Int32(aCellPos.Tab())));
+
+ SvxFieldItem aItem = pCellField->CreateFieldItem();
+ SvxTextForwarder* pForwarder = pEditSource->GetTextForwarder();
+ pForwarder->QuickInsertField( aItem, aSelection );
+ pEditSource->UpdateData();
+
+ // new selection: a digit
+ aSelection.Adjust();
+ aSelection.nEndPara = aSelection.nStartPara;
+ aSelection.nEndPos = aSelection.nStartPos + 1;
+ uno::Reference<text::XTextRange> xParent(this);
+ pCellField->InitDoc(
+ xParent, std::make_unique<ScCellEditSource>(pDocSh, aCellPos), aSelection);
+
+ // for bAbsorb=FALSE, the new selection must be behind the inserted content
+ // (the xml filter relies on this)
+ if (!bAbsorb)
+ aSelection.nStartPos = aSelection.nEndPos;
+
+ pTextRange->SetSelection( aSelection );
+
+ return;
+ }
+ }
+ GetUnoText().insertTextContent(xRange, xContent, bAbsorb);
+}
+
+void SAL_CALL ScCellObj::removeTextContent( const uno::Reference<text::XTextContent>& xContent )
+{
+ SolarMutexGuard aGuard;
+ if ( xContent.is() )
+ {
+ ScEditFieldObj* pCellField = comphelper::getFromUnoTunnel<ScEditFieldObj>(xContent);
+ if ( pCellField && pCellField->IsInserted() )
+ {
+ //! Check if field is in this cell
+ pCellField->DeleteField();
+ return;
+ }
+ }
+ GetUnoText().removeTextContent(xContent);
+}
+
+uno::Reference<text::XText> SAL_CALL ScCellObj::getText()
+{
+ return this;
+}
+
+uno::Reference<text::XTextRange> SAL_CALL ScCellObj::getStart()
+{
+ SolarMutexGuard aGuard;
+ return GetUnoText().getStart();
+}
+
+uno::Reference<text::XTextRange> SAL_CALL ScCellObj::getEnd()
+{
+ SolarMutexGuard aGuard;
+ return GetUnoText().getEnd();
+}
+
+uno::Reference<container::XEnumeration> SAL_CALL ScCellObj::createEnumeration()
+{
+ SolarMutexGuard aGuard;
+ return GetUnoText().createEnumeration();
+}
+
+uno::Type SAL_CALL ScCellObj::getElementType()
+{
+ SolarMutexGuard aGuard;
+ return GetUnoText().getElementType();
+}
+
+sal_Bool SAL_CALL ScCellObj::hasElements()
+{
+ SolarMutexGuard aGuard;
+ return GetUnoText().hasElements();
+}
+
+// XCell
+
+OUString SAL_CALL ScCellObj::getFormula()
+{
+ SolarMutexGuard aGuard;
+ return GetInputString_Impl( true /* English */ );
+}
+
+void SAL_CALL ScCellObj::setFormula( const OUString& aFormula )
+{
+ SolarMutexGuard aGuard;
+ SetString_Impl(aFormula, true, true); // Interpret as English
+}
+
+double SAL_CALL ScCellObj::getValue()
+{
+ SolarMutexGuard aGuard;
+ return GetValue_Impl();
+}
+
+void SAL_CALL ScCellObj::setValue( double nValue )
+{
+ SolarMutexGuard aGuard;
+ SetValue_Impl(nValue);
+}
+
+void SAL_CALL ScCellObj::setFormulaString( const OUString& aFormula)
+{
+ SolarMutexGuard aGuard;
+ ScDocShell *pDocSh = GetDocShell();
+ if( pDocSh )
+ {
+ ScFormulaCell* pCell = new ScFormulaCell( pDocSh->GetDocument(), aCellPos );
+ pCell->SetHybridFormula( aFormula, formula::FormulaGrammar::GRAM_NATIVE );
+ pDocSh->GetDocFunc().SetFormulaCell(aCellPos, pCell, false);
+ }
+}
+void SAL_CALL ScCellObj::setFormulaResult( double nValue )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if (pDocSh)
+ {
+ ScRefCellValue aCell(pDocSh->GetDocument(), aCellPos);
+ if (aCell.meType == CELLTYPE_FORMULA)
+ {
+ ScFormulaCell* pCell = aCell.mpFormula;
+ pCell->SetHybridDouble( nValue );
+ pCell->ResetDirty();
+ pCell->SetChanged(false);
+ }
+ }
+}
+
+table::CellContentType SAL_CALL ScCellObj::getType()
+{
+ SolarMutexGuard aGuard;
+ table::CellContentType eRet = table::CellContentType_EMPTY;
+ ScDocShell* pDocSh = GetDocShell();
+ if (pDocSh)
+ {
+ CellType eCalcType = pDocSh->GetDocument().GetCellType( aCellPos );
+ switch (eCalcType)
+ {
+ case CELLTYPE_VALUE:
+ eRet = table::CellContentType_VALUE;
+ break;
+ case CELLTYPE_STRING:
+ case CELLTYPE_EDIT:
+ eRet = table::CellContentType_TEXT;
+ break;
+ case CELLTYPE_FORMULA:
+ eRet = table::CellContentType_FORMULA;
+ break;
+ default:
+ eRet = table::CellContentType_EMPTY;
+ }
+ }
+ else
+ {
+ OSL_FAIL("no DocShell"); //! Exception or so?
+ }
+
+ return eRet;
+}
+
+sal_Int32 ScCellObj::GetResultType_Impl() const
+{
+ SolarMutexGuard aGuard;
+ sal_Int32 eRet = sheet::FormulaResult::STRING;
+ ScDocShell* pDocSh = GetDocShell();
+ if (pDocSh)
+ {
+ if (pDocSh->GetDocument().GetCellType(aCellPos) == CELLTYPE_FORMULA)
+ {
+ ScFormulaCell* pFCell = pDocSh->GetDocument().GetFormulaCell(aCellPos);
+ if (!pFCell)
+ {
+ // should throw instead of default string?
+ }
+ else if (pFCell->GetErrCode() != FormulaError::NONE )
+ {
+ eRet = sheet::FormulaResult::ERROR;
+ }
+ else if (pFCell->IsValue())
+ {
+ eRet = sheet::FormulaResult::VALUE;
+ }
+ else
+ {
+ eRet = sheet::FormulaResult::STRING;
+ }
+ }
+ }
+ else
+ {
+ OSL_FAIL("no DocShell");
+ }
+
+ return eRet;
+}
+
+table::CellContentType ScCellObj::GetContentType_Impl()
+{
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ ScRefCellValue aCell(pDocSh->GetDocument(), aCellPos);
+ if (aCell.meType == CELLTYPE_FORMULA)
+ {
+ bool bValue = aCell.mpFormula->IsValue();
+ return bValue ? table::CellContentType_VALUE : table::CellContentType_TEXT;
+ }
+ }
+ return getType();
+}
+
+sal_Int32 SAL_CALL ScCellObj::getError()
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if (!pDocSh)
+ {
+ OSL_FAIL("no DocShell"); //! Exception or so?
+ return 0;
+ }
+
+ FormulaError nError = FormulaError::NONE;
+ ScRefCellValue aCell(pDocSh->GetDocument(), aCellPos);
+ if (aCell.meType == CELLTYPE_FORMULA)
+ nError = aCell.mpFormula->GetErrCode();
+
+ return static_cast<sal_Int32>(nError);
+}
+
+// XFormulaTokens
+
+uno::Sequence<sheet::FormulaToken> SAL_CALL ScCellObj::getTokens()
+{
+ SolarMutexGuard aGuard;
+ uno::Sequence<sheet::FormulaToken> aSequence;
+ ScDocShell* pDocSh = GetDocShell();
+ if (!pDocSh)
+ return aSequence;
+
+ ScDocument& rDoc = pDocSh->GetDocument();
+ ScRefCellValue aCell(rDoc, aCellPos);
+ if (aCell.meType == CELLTYPE_FORMULA)
+ {
+ ScTokenArray* pTokenArray = aCell.mpFormula->GetCode();
+ if (pTokenArray)
+ ScTokenConversion::ConvertToTokenSequence(rDoc, aSequence, *pTokenArray);
+ }
+ return aSequence;
+}
+
+void SAL_CALL ScCellObj::setTokens( const uno::Sequence<sheet::FormulaToken>& rTokens )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ ScDocument& rDoc = pDocSh->GetDocument();
+ ScTokenArray aTokenArray(rDoc);
+ (void)ScTokenConversion::ConvertToTokenArray( rDoc, aTokenArray, rTokens );
+
+ ScFormulaCell* pNewCell = new ScFormulaCell(rDoc, aCellPos, aTokenArray);
+ (void)pDocSh->GetDocFunc().SetFormulaCell(aCellPos, pNewCell, false);
+ }
+}
+
+// XCellAddressable
+
+table::CellAddress SAL_CALL ScCellObj::getCellAddress()
+{
+ SolarMutexGuard aGuard;
+ table::CellAddress aAdr;
+ aAdr.Sheet = aCellPos.Tab();
+ aAdr.Column = aCellPos.Col();
+ aAdr.Row = aCellPos.Row();
+ return aAdr;
+}
+
+// XSheetAnnotationAnchor
+
+uno::Reference<sheet::XSheetAnnotation> SAL_CALL ScCellObj::getAnnotation()
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ return new ScAnnotationObj( pDocSh, aCellPos );
+
+ OSL_FAIL("getAnnotation without DocShell");
+ return nullptr;
+}
+
+// XFieldTypesSupplier
+
+uno::Reference<container::XEnumerationAccess> SAL_CALL ScCellObj::getTextFields()
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ uno::Reference<text::XTextRange> xContent(this);
+ return new ScCellFieldsObj(xContent, pDocSh, aCellPos);
+ }
+
+ return nullptr;
+}
+
+uno::Reference<container::XNameAccess> SAL_CALL ScCellObj::getTextFieldMasters()
+{
+ // there is no such thing in Calc (?)
+ return nullptr;
+}
+
+// XPropertySet extended for Cell-Properties
+
+uno::Reference<beans::XPropertySetInfo> SAL_CALL ScCellObj::getPropertySetInfo()
+{
+ SolarMutexGuard aGuard;
+ static uno::Reference<beans::XPropertySetInfo> aRef(
+ new SfxItemPropertySetInfo( pCellPropSet->getPropertyMap() ));
+ return aRef;
+}
+
+void ScCellObj::SetOnePropertyValue( const SfxItemPropertyMapEntry* pEntry, const uno::Any& aValue )
+{
+ if ( !pEntry )
+ return;
+
+ if ( pEntry->nWID == SC_WID_UNO_FORMLOC )
+ {
+ OUString aStrVal;
+ aValue >>= aStrVal;
+ SetString_Impl(aStrVal, true, false); // interpret locally
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_FORMRT || pEntry->nWID == SC_WID_UNO_FORMRT2
+ || pEntry->nWID == SC_WID_UNO_CELLCONTENTTYPE )
+ {
+ // Read-Only
+ //! Exception or so...
+ }
+ else
+ ScCellRangeObj::SetOnePropertyValue( pEntry, aValue );
+}
+
+void ScCellObj::GetOnePropertyValue( const SfxItemPropertyMapEntry* pEntry, uno::Any& rAny )
+{
+ if ( !pEntry )
+ return;
+
+ if ( pEntry->nWID == SC_WID_UNO_FORMLOC )
+ {
+ // sal_False = local
+ rAny <<= GetInputString_Impl(false);
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_FORMRT2 )
+ {
+ sal_Int32 eType = GetResultType_Impl();
+ rAny <<= eType;
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_CELLCONTENTTYPE || pEntry->nWID == SC_WID_UNO_FORMRT )
+ {
+ table::CellContentType eType = GetContentType_Impl();
+ rAny <<= eType;
+ }
+ else
+ ScCellRangeObj::GetOnePropertyValue(pEntry, rAny);
+}
+
+const SfxItemPropertyMap& ScCellObj::GetItemPropertyMap()
+{
+ return pCellPropSet->getPropertyMap();
+}
+
+// XServiceInfo
+
+OUString SAL_CALL ScCellObj::getImplementationName()
+{
+ return "ScCellObj";
+}
+
+sal_Bool SAL_CALL ScCellObj::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence<OUString> SAL_CALL ScCellObj::getSupportedServiceNames()
+{
+ return {SCSHEETCELL_SERVICE,
+ SCCELL_SERVICE,
+ SCCELLPROPERTIES_SERVICE,
+ SCCHARPROPERTIES_SERVICE,
+ SCPARAPROPERTIES_SERVICE,
+ SCSHEETCELLRANGE_SERVICE,
+ SCCELLRANGE_SERVICE};
+}
+
+// XActionLockable
+
+sal_Bool SAL_CALL ScCellObj::isActionLocked()
+{
+ SolarMutexGuard aGuard;
+ return nActionLockCount != 0;
+}
+
+void SAL_CALL ScCellObj::addActionLock()
+{
+ SolarMutexGuard aGuard;
+ if (!nActionLockCount)
+ {
+ if (mxUnoText.is())
+ {
+ ScCellEditSource* pEditSource =
+ static_cast<ScCellEditSource*> (mxUnoText->GetEditSource());
+ if (pEditSource)
+ pEditSource->SetDoUpdateData(false);
+ }
+ }
+ nActionLockCount++;
+}
+
+void SAL_CALL ScCellObj::removeActionLock()
+{
+ SolarMutexGuard aGuard;
+ if (nActionLockCount <= 0)
+ return;
+
+ nActionLockCount--;
+ if (nActionLockCount)
+ return;
+
+ if (mxUnoText.is())
+ {
+ ScCellEditSource* pEditSource =
+ static_cast<ScCellEditSource*> (mxUnoText->GetEditSource());
+ if (pEditSource)
+ {
+ pEditSource->SetDoUpdateData(true);
+ if (pEditSource->IsDirty())
+ pEditSource->UpdateData();
+ }
+ }
+}
+
+void SAL_CALL ScCellObj::setActionLocks( sal_Int16 nLock )
+{
+ SolarMutexGuard aGuard;
+ if (mxUnoText.is())
+ {
+ ScCellEditSource* pEditSource =
+ static_cast<ScCellEditSource*> (mxUnoText->GetEditSource());
+ if (pEditSource)
+ {
+ pEditSource->SetDoUpdateData(nLock == 0);
+ if ((nActionLockCount > 0) && (nLock == 0) && pEditSource->IsDirty())
+ pEditSource->UpdateData();
+ }
+ }
+ nActionLockCount = nLock;
+}
+
+sal_Int16 SAL_CALL ScCellObj::resetActionLocks()
+{
+ SolarMutexGuard aGuard;
+ sal_uInt16 nRet(nActionLockCount);
+ if (mxUnoText.is())
+ {
+ ScCellEditSource* pEditSource =
+ static_cast<ScCellEditSource*> (mxUnoText->GetEditSource());
+ if (pEditSource)
+ {
+ pEditSource->SetDoUpdateData(true);
+ if (pEditSource->IsDirty())
+ pEditSource->UpdateData();
+ }
+ }
+ nActionLockCount = 0;
+ return nRet;
+}
+
+static ScRange MaxDocRange(ScDocShell* pDocSh, SCTAB nTab)
+{
+ const SCCOL nMaxcol = pDocSh ? pDocSh->GetDocument().MaxCol() : MAXCOL;
+ const SCROW nMaxRow = pDocSh ? pDocSh->GetDocument().MaxRow() : MAXROW;
+ return ScRange(0, 0, nTab, nMaxcol, nMaxRow, nTab);
+}
+
+ScTableSheetObj::ScTableSheetObj( ScDocShell* pDocSh, SCTAB nTab ) :
+ ScCellRangeObj( pDocSh, MaxDocRange(pDocSh, nTab) ),
+ pSheetPropSet(lcl_GetSheetPropertySet())
+{
+}
+
+ScTableSheetObj::~ScTableSheetObj()
+{
+}
+
+void ScTableSheetObj::InitInsertSheet(ScDocShell* pDocSh, SCTAB nTab)
+{
+ ScDocument& rDoc = pDocSh->GetDocument();
+ InitInsertRange( pDocSh, ScRange(0,0,nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab) );
+}
+
+uno::Any SAL_CALL ScTableSheetObj::queryInterface( const uno::Type& rType )
+{
+ SC_QUERYINTERFACE( sheet::XSpreadsheet )
+ SC_QUERYINTERFACE( container::XNamed )
+ SC_QUERYINTERFACE( sheet::XSheetPageBreak )
+ SC_QUERYINTERFACE( sheet::XCellRangeMovement )
+ SC_QUERYINTERFACE( table::XTableChartsSupplier )
+ SC_QUERYINTERFACE( sheet::XDataPilotTablesSupplier )
+ SC_QUERYINTERFACE( sheet::XScenariosSupplier )
+ SC_QUERYINTERFACE( sheet::XSheetAnnotationsSupplier )
+ SC_QUERYINTERFACE( drawing::XDrawPageSupplier )
+ SC_QUERYINTERFACE( sheet::XPrintAreas )
+ SC_QUERYINTERFACE( sheet::XSheetAuditing )
+ SC_QUERYINTERFACE( sheet::XSheetOutline )
+ SC_QUERYINTERFACE( util::XProtectable )
+ SC_QUERYINTERFACE( sheet::XScenario )
+ SC_QUERYINTERFACE( sheet::XScenarioEnhanced )
+ SC_QUERYINTERFACE( sheet::XSheetLinkable )
+ SC_QUERYINTERFACE( sheet::XExternalSheetName )
+ SC_QUERYINTERFACE( document::XEventsSupplier )
+ SC_QUERYINTERFACE( table::XTablePivotChartsSupplier )
+
+ return ScCellRangeObj::queryInterface( rType );
+}
+
+void SAL_CALL ScTableSheetObj::acquire() noexcept
+{
+ ScCellRangeObj::acquire();
+}
+
+void SAL_CALL ScTableSheetObj::release() noexcept
+{
+ ScCellRangeObj::release();
+}
+
+uno::Sequence<uno::Type> SAL_CALL ScTableSheetObj::getTypes()
+{
+ static const uno::Sequence<uno::Type> aTypes = comphelper::concatSequences(
+ ScCellRangeObj::getTypes(),
+ uno::Sequence<uno::Type>
+ {
+ cppu::UnoType<sheet::XSpreadsheet>::get(),
+ cppu::UnoType<container::XNamed>::get(),
+ cppu::UnoType<sheet::XSheetPageBreak>::get(),
+ cppu::UnoType<sheet::XCellRangeMovement>::get(),
+ cppu::UnoType<table::XTableChartsSupplier>::get(),
+ cppu::UnoType<sheet::XDataPilotTablesSupplier>::get(),
+ cppu::UnoType<sheet::XScenariosSupplier>::get(),
+ cppu::UnoType<sheet::XSheetAnnotationsSupplier>::get(),
+ cppu::UnoType<drawing::XDrawPageSupplier>::get(),
+ cppu::UnoType<sheet::XPrintAreas>::get(),
+ cppu::UnoType<sheet::XSheetAuditing>::get(),
+ cppu::UnoType<sheet::XSheetOutline>::get(),
+ cppu::UnoType<util::XProtectable>::get(),
+ cppu::UnoType<sheet::XScenario>::get(),
+ cppu::UnoType<sheet::XScenarioEnhanced>::get(),
+ cppu::UnoType<sheet::XSheetLinkable>::get(),
+ cppu::UnoType<sheet::XExternalSheetName>::get(),
+ cppu::UnoType<document::XEventsSupplier>::get(),
+ cppu::UnoType<table::XTablePivotChartsSupplier>::get()
+ } );
+ return aTypes;
+}
+
+uno::Sequence<sal_Int8> SAL_CALL ScTableSheetObj::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// Helper functions
+
+SCTAB ScTableSheetObj::GetTab_Impl() const
+{
+ const ScRangeList& rRanges = GetRangeList();
+ OSL_ENSURE(rRanges.size() == 1, "What ranges ?!?!");
+ if ( !rRanges.empty() )
+ {
+ return rRanges[ 0 ].aStart.Tab();
+ }
+ return 0;
+}
+
+// former XSheet
+
+uno::Reference<table::XTableCharts> SAL_CALL ScTableSheetObj::getCharts()
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ return new ScChartsObj( pDocSh, GetTab_Impl() );
+
+ OSL_FAIL("no document");
+ return nullptr;
+}
+
+uno::Reference<table::XTablePivotCharts> SAL_CALL ScTableSheetObj::getPivotCharts()
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if (pDocSh)
+ return new sc::TablePivotCharts(pDocSh, GetTab_Impl());
+
+ OSL_FAIL("no document");
+ return nullptr;
+}
+
+uno::Reference<sheet::XDataPilotTables> SAL_CALL ScTableSheetObj::getDataPilotTables()
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ return new ScDataPilotTablesObj(*pDocSh, GetTab_Impl());
+
+ OSL_FAIL("no document");
+ return nullptr;
+}
+
+uno::Reference<sheet::XScenarios> SAL_CALL ScTableSheetObj::getScenarios()
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+
+ if ( pDocSh )
+ return new ScScenariosObj( pDocSh, GetTab_Impl() );
+
+ OSL_FAIL("no document");
+ return nullptr;
+}
+
+uno::Reference<sheet::XSheetAnnotations> SAL_CALL ScTableSheetObj::getAnnotations()
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+
+ if ( pDocSh )
+ return new ScAnnotationsObj( pDocSh, GetTab_Impl() );
+
+ OSL_FAIL("no document");
+ return nullptr;
+}
+
+uno::Reference<table::XCellRange> SAL_CALL ScTableSheetObj::getCellRangeByName(
+ const OUString& rRange )
+{
+ SolarMutexGuard aGuard;
+ return ScCellRangeObj::getCellRangeByName( rRange );
+}
+
+uno::Reference<sheet::XSheetCellCursor> SAL_CALL ScTableSheetObj::createCursor()
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ //! single cell or whole table??????
+ const ScDocument& rDoc = pDocSh->GetDocument();
+ SCTAB nTab = GetTab_Impl();
+ return new ScCellCursorObj( pDocSh, ScRange( 0,0,nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab ) );
+ }
+ return nullptr;
+}
+
+uno::Reference<sheet::XSheetCellCursor> SAL_CALL ScTableSheetObj::createCursorByRange(
+ const uno::Reference<sheet::XSheetCellRange>& xCellRange )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh && xCellRange.is() )
+ {
+ ScCellRangesBase* pRangesImp = comphelper::getFromUnoTunnel<ScCellRangesBase>( xCellRange );
+ if (pRangesImp)
+ {
+ const ScRangeList& rRanges = pRangesImp->GetRangeList();
+ SAL_WARN_IF( rRanges.size() != 1, "sc", "ScTableSheetObj::createCursorByRange: Range? Ranges?");
+ if (rRanges.empty())
+ return nullptr;
+ return new ScCellCursorObj( pDocSh, rRanges[ 0 ] );
+ }
+ }
+ return nullptr;
+}
+
+// XSheetCellRange
+
+uno::Reference<sheet::XSpreadsheet> SAL_CALL ScTableSheetObj::getSpreadsheet()
+{
+ return this; //!???
+}
+
+// XCellRange
+
+uno::Reference<table::XCell> SAL_CALL ScTableSheetObj::getCellByPosition(
+ sal_Int32 nColumn, sal_Int32 nRow )
+{
+ SolarMutexGuard aGuard;
+ return ScCellRangeObj::GetCellByPosition_Impl(nColumn, nRow);
+}
+
+uno::Reference<table::XCellRange> SAL_CALL ScTableSheetObj::getCellRangeByPosition(
+ sal_Int32 nLeft, sal_Int32 nTop, sal_Int32 nRight, sal_Int32 nBottom )
+{
+ SolarMutexGuard aGuard;
+ return ScCellRangeObj::getCellRangeByPosition(nLeft,nTop,nRight,nBottom);
+}
+
+uno::Sequence<sheet::TablePageBreakData> SAL_CALL ScTableSheetObj::getColumnPageBreaks()
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ ScDocument& rDoc = pDocSh->GetDocument();
+ SCTAB nTab = GetTab_Impl();
+
+ Size aSize(rDoc.GetPageSize( nTab ));
+ if (aSize.Width() && aSize.Height()) // effective size already set?
+ rDoc.UpdatePageBreaks( nTab );
+ else
+ {
+ // update breaks like in ScDocShell::PageStyleModified:
+ ScPrintFunc aPrintFunc( pDocSh, pDocSh->GetPrinter(), nTab );
+ aPrintFunc.UpdatePages();
+ }
+
+ SCCOL nCount = 0;
+ for (SCCOL nCol : rDoc.GetColumnsRange(nTab, 0, rDoc.MaxCol()))
+ if (rDoc.HasColBreak(nCol, nTab) != ScBreakType::NONE)
+ ++nCount;
+
+ sheet::TablePageBreakData aData;
+ uno::Sequence<sheet::TablePageBreakData> aSeq(nCount);
+ sheet::TablePageBreakData* pAry = aSeq.getArray();
+ sal_uInt16 nPos = 0;
+ for (SCCOL nCol : rDoc.GetColumnsRange(nTab, 0, rDoc.MaxCol()))
+ {
+ ScBreakType nBreak = rDoc.HasColBreak(nCol, nTab);
+ if (nBreak != ScBreakType::NONE)
+ {
+ aData.Position = nCol;
+ aData.ManualBreak = bool(nBreak & ScBreakType::Manual);
+ pAry[nPos] = aData;
+ ++nPos;
+ }
+ }
+ return aSeq;
+ }
+ return {};
+}
+
+uno::Sequence<sheet::TablePageBreakData> SAL_CALL ScTableSheetObj::getRowPageBreaks()
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ ScDocument& rDoc = pDocSh->GetDocument();
+ SCTAB nTab = GetTab_Impl();
+
+ Size aSize(rDoc.GetPageSize( nTab ));
+ if (aSize.Width() && aSize.Height()) // effective size already set?
+ rDoc.UpdatePageBreaks( nTab );
+ else
+ {
+ // update breaks like in ScDocShell::PageStyleModified:
+ ScPrintFunc aPrintFunc( pDocSh, pDocSh->GetPrinter(), nTab );
+ aPrintFunc.UpdatePages();
+ }
+ return rDoc.GetRowBreakData(nTab);
+ }
+ return {};
+}
+
+void SAL_CALL ScTableSheetObj::removeAllManualPageBreaks()
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( !pDocSh )
+ return;
+
+ //! DocFunc function, also for ScViewFunc::RemoveManualBreaks
+
+ ScDocument& rDoc = pDocSh->GetDocument();
+ bool bUndo (rDoc.IsUndoEnabled());
+ SCTAB nTab = GetTab_Impl();
+
+ if (bUndo)
+ {
+ ScDocumentUniquePtr pUndoDoc(new ScDocument( SCDOCMODE_UNDO ));
+ pUndoDoc->InitUndo( rDoc, nTab, nTab, true, true );
+ rDoc.CopyToDocument(0,0,nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab, InsertDeleteFlags::NONE, false, *pUndoDoc);
+ pDocSh->GetUndoManager()->AddUndoAction(
+ std::make_unique<ScUndoRemoveBreaks>( pDocSh, nTab, std::move(pUndoDoc) ) );
+ }
+
+ rDoc.RemoveManualBreaks(nTab);
+ rDoc.UpdatePageBreaks(nTab);
+
+ //? UpdatePageBreakData( sal_True );
+ pDocSh->SetDocumentModified();
+ pDocSh->PostPaint(ScRange(0, 0, nTab, rDoc.MaxCol(), rDoc.MaxRow(), nTab), PaintPartFlags::Grid);
+}
+
+// XNamed
+
+OUString SAL_CALL ScTableSheetObj::getName()
+{
+ SolarMutexGuard aGuard;
+ OUString aName;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ pDocSh->GetDocument().GetName( GetTab_Impl(), aName );
+ return aName;
+}
+
+void SAL_CALL ScTableSheetObj::setName( const OUString& aNewName )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ pDocSh->GetDocFunc().RenameTable( GetTab_Impl(), aNewName, true, true );
+ }
+}
+
+// XDrawPageSupplier
+
+uno::Reference<drawing::XDrawPage> SAL_CALL ScTableSheetObj::getDrawPage()
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ ScDrawLayer* pDrawLayer = pDocSh->MakeDrawLayer();
+ OSL_ENSURE(pDrawLayer,"Cannot create Draw-Layer");
+
+ SCTAB nTab = GetTab_Impl();
+ SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
+ OSL_ENSURE(pPage,"Draw-Page not found");
+ if (pPage)
+ return uno::Reference<drawing::XDrawPage> (pPage->getUnoPage(), uno::UNO_QUERY);
+
+ // The DrawPage object will register itself as a Listener at SdrModel
+ // and should receive all action from there
+ }
+ return nullptr;
+}
+
+// XCellMovement
+
+void SAL_CALL ScTableSheetObj::insertCells( const table::CellRangeAddress& rRangeAddress,
+ sheet::CellInsertMode nMode )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( !pDocSh )
+ return;
+
+ bool bDo = true;
+ InsCellCmd eCmd = INS_NONE;
+ switch (nMode)
+ {
+ case sheet::CellInsertMode_NONE: bDo = false; break;
+ case sheet::CellInsertMode_DOWN: eCmd = INS_CELLSDOWN; break;
+ case sheet::CellInsertMode_RIGHT: eCmd = INS_CELLSRIGHT; break;
+ case sheet::CellInsertMode_ROWS: eCmd = INS_INSROWS_BEFORE; break;
+ case sheet::CellInsertMode_COLUMNS: eCmd = INS_INSCOLS_BEFORE; break;
+ default:
+ OSL_FAIL("insertCells: wrong mode");
+ bDo = false;
+ }
+
+ if (bDo)
+ {
+ OSL_ENSURE( rRangeAddress.Sheet == GetTab_Impl(), "wrong table in CellRangeAddress" );
+ ScRange aScRange;
+ ScUnoConversion::FillScRange( aScRange, rRangeAddress );
+ (void)pDocSh->GetDocFunc().InsertCells( aScRange, nullptr, eCmd, true, true );
+ }
+}
+
+void SAL_CALL ScTableSheetObj::removeRange( const table::CellRangeAddress& rRangeAddress,
+ sheet::CellDeleteMode nMode )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( !pDocSh )
+ return;
+
+ bool bDo = true;
+ DelCellCmd eCmd = DelCellCmd::NONE;
+ switch (nMode)
+ {
+ case sheet::CellDeleteMode_NONE: bDo = false; break;
+ case sheet::CellDeleteMode_UP: eCmd = DelCellCmd::CellsUp; break;
+ case sheet::CellDeleteMode_LEFT: eCmd = DelCellCmd::CellsLeft; break;
+ case sheet::CellDeleteMode_ROWS: eCmd = DelCellCmd::Rows; break;
+ case sheet::CellDeleteMode_COLUMNS: eCmd = DelCellCmd::Cols; break;
+ default:
+ OSL_FAIL("deleteCells: wrong mode");
+ bDo = false;
+ }
+
+ if (bDo)
+ {
+ OSL_ENSURE( rRangeAddress.Sheet == GetTab_Impl(), "wrong table in CellRangeAddress" );
+ ScRange aScRange;
+ ScUnoConversion::FillScRange( aScRange, rRangeAddress );
+ (void)pDocSh->GetDocFunc().DeleteCells( aScRange, nullptr, eCmd, true );
+ }
+}
+
+void SAL_CALL ScTableSheetObj::moveRange( const table::CellAddress& aDestination,
+ const table::CellRangeAddress& aSource )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ OSL_ENSURE( aSource.Sheet == GetTab_Impl(), "wrong table in CellRangeAddress" );
+ ScRange aSourceRange;
+ ScUnoConversion::FillScRange( aSourceRange, aSource );
+ ScAddress aDestPos( static_cast<SCCOL>(aDestination.Column), static_cast<SCROW>(aDestination.Row), aDestination.Sheet );
+ (void)pDocSh->GetDocFunc().MoveBlock( aSourceRange, aDestPos, true, true, true, true );
+ }
+}
+
+void SAL_CALL ScTableSheetObj::copyRange( const table::CellAddress& aDestination,
+ const table::CellRangeAddress& aSource )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ OSL_ENSURE( aSource.Sheet == GetTab_Impl(), "wrong table in CellRangeAddress" );
+ ScRange aSourceRange;
+ ScUnoConversion::FillScRange( aSourceRange, aSource );
+ ScAddress aDestPos( static_cast<SCCOL>(aDestination.Column), static_cast<SCROW>(aDestination.Row), aDestination.Sheet );
+ (void)pDocSh->GetDocFunc().MoveBlock( aSourceRange, aDestPos, false, true, true, true );
+ }
+}
+
+// XPrintAreas
+
+void ScTableSheetObj::PrintAreaUndo_Impl( std::unique_ptr<ScPrintRangeSaver> pOldRanges )
+{
+ // page break and undo
+ ScDocShell* pDocSh = GetDocShell();
+
+ if(!pDocSh)
+ return;
+
+ ScDocument& rDoc = pDocSh->GetDocument();
+ const bool bUndo(rDoc.IsUndoEnabled());
+ const SCTAB nTab(GetTab_Impl());
+
+ if(bUndo)
+ {
+ pDocSh->GetUndoManager()->AddUndoAction(
+ std::make_unique<ScUndoPrintRange>(
+ pDocSh,
+ nTab,
+ std::move(pOldRanges),
+ rDoc.CreatePrintRangeSaver())); // create new ranges
+ }
+
+ ScPrintFunc(pDocSh, pDocSh->GetPrinter(), nTab).UpdatePages();
+ SfxBindings* pBindings = pDocSh->GetViewBindings();
+
+ if(pBindings)
+ {
+ pBindings->Invalidate(SID_DELETE_PRINTAREA);
+ }
+
+ pDocSh->SetDocumentModified();
+}
+
+uno::Sequence<table::CellRangeAddress> SAL_CALL ScTableSheetObj::getPrintAreas()
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ ScDocument& rDoc = pDocSh->GetDocument();
+ SCTAB nTab = GetTab_Impl();
+ sal_uInt16 nCount = rDoc.GetPrintRangeCount( nTab );
+
+ table::CellRangeAddress aRangeAddress;
+ uno::Sequence<table::CellRangeAddress> aSeq(nCount);
+ table::CellRangeAddress* pAry = aSeq.getArray();
+ for (sal_uInt16 i=0; i<nCount; i++)
+ {
+ const ScRange* pRange = rDoc.GetPrintRange( nTab, i );
+ OSL_ENSURE(pRange,"where is the printing area");
+ if (pRange)
+ {
+ ScUnoConversion::FillApiRange( aRangeAddress, *pRange );
+ aRangeAddress.Sheet = nTab; // core does not care about sheet index
+ pAry[i] = aRangeAddress;
+ }
+ }
+ return aSeq;
+ }
+ return uno::Sequence<table::CellRangeAddress>();
+}
+
+void SAL_CALL ScTableSheetObj::setPrintAreas(
+ const uno::Sequence<table::CellRangeAddress>& aPrintAreas )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( !pDocSh )
+ return;
+
+ std::unique_ptr<ScPrintRangeSaver> pOldRanges;
+ ScDocument& rDoc = pDocSh->GetDocument();
+ SCTAB nTab = GetTab_Impl();
+
+ if ( rDoc.IsUndoEnabled() )
+ pOldRanges = rDoc.CreatePrintRangeSaver();
+
+ sal_uInt16 nCount = static_cast<sal_uInt16>(aPrintAreas.getLength());
+ rDoc.ClearPrintRanges( nTab );
+ if (nCount)
+ {
+ ScRange aPrintRange;
+ for (const table::CellRangeAddress& rPrintArea : aPrintAreas)
+ {
+ ScUnoConversion::FillScRange( aPrintRange, rPrintArea );
+ rDoc.AddPrintRange( nTab, aPrintRange );
+ }
+ }
+
+ if ( rDoc.IsUndoEnabled() )
+ PrintAreaUndo_Impl( std::move(pOldRanges) ); // Undo, Page Breaks, Modified etc.
+}
+
+sal_Bool SAL_CALL ScTableSheetObj::getPrintTitleColumns()
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ ScDocument& rDoc = pDocSh->GetDocument();
+ SCTAB nTab = GetTab_Impl();
+ return rDoc.GetRepeatColRange(nTab).has_value();
+ }
+ return false;
+}
+
+void SAL_CALL ScTableSheetObj::setPrintTitleColumns( sal_Bool bPrintTitleColumns )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( !pDocSh )
+ return;
+
+ ScDocument& rDoc = pDocSh->GetDocument();
+ SCTAB nTab = GetTab_Impl();
+
+ std::unique_ptr<ScPrintRangeSaver> pOldRanges = rDoc.CreatePrintRangeSaver();
+
+ if ( bPrintTitleColumns )
+ {
+ if ( !rDoc.GetRepeatColRange( nTab ) ) // do not change existing area
+ {
+ rDoc.SetRepeatColRange( nTab, ScRange( 0, 0, nTab, 0, 0, nTab ) ); // enable
+ }
+ }
+ else
+ rDoc.SetRepeatColRange( nTab, std::nullopt ); // disable
+
+ PrintAreaUndo_Impl( std::move(pOldRanges) ); // undo, page break, modified etc.
+
+ //! save last set area during switch off and recreate during switch on ???
+}
+
+table::CellRangeAddress SAL_CALL ScTableSheetObj::getTitleColumns()
+{
+ SolarMutexGuard aGuard;
+ table::CellRangeAddress aRet;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ ScDocument& rDoc = pDocSh->GetDocument();
+ SCTAB nTab = GetTab_Impl();
+ std::optional<ScRange> oRange = rDoc.GetRepeatColRange(nTab);
+ if (oRange)
+ {
+ ScUnoConversion::FillApiRange( aRet, *oRange );
+ aRet.Sheet = nTab; // core does not care about sheet index
+ }
+ }
+ return aRet;
+}
+
+void SAL_CALL ScTableSheetObj::setTitleColumns( const table::CellRangeAddress& aTitleColumns )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( !pDocSh )
+ return;
+
+ ScDocument& rDoc = pDocSh->GetDocument();
+ SCTAB nTab = GetTab_Impl();
+
+ std::unique_ptr<ScPrintRangeSaver> pOldRanges = rDoc.CreatePrintRangeSaver();
+
+ ScRange aNew;
+ ScUnoConversion::FillScRange( aNew, aTitleColumns );
+ rDoc.SetRepeatColRange( nTab, std::move(aNew) ); // also always enable
+
+ PrintAreaUndo_Impl( std::move(pOldRanges) ); // undo, page breaks, modified etc.
+}
+
+sal_Bool SAL_CALL ScTableSheetObj::getPrintTitleRows()
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ ScDocument& rDoc = pDocSh->GetDocument();
+ SCTAB nTab = GetTab_Impl();
+ return rDoc.GetRepeatRowRange(nTab).has_value();
+ }
+ return false;
+}
+
+void SAL_CALL ScTableSheetObj::setPrintTitleRows( sal_Bool bPrintTitleRows )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( !pDocSh )
+ return;
+
+ ScDocument& rDoc = pDocSh->GetDocument();
+ SCTAB nTab = GetTab_Impl();
+
+ std::unique_ptr<ScPrintRangeSaver> pOldRanges = rDoc.CreatePrintRangeSaver();
+
+ if ( bPrintTitleRows )
+ {
+ if ( !rDoc.GetRepeatRowRange( nTab ) ) // do not change existing area
+ {
+ rDoc.SetRepeatRowRange( nTab, ScRange(0, 0, nTab, 0, 0, nTab) ); // enable
+ }
+ }
+ else
+ rDoc.SetRepeatRowRange( nTab, std::nullopt ); // disable
+
+ PrintAreaUndo_Impl( std::move(pOldRanges) ); // undo, page breaks, modified etc.
+
+ //! save last set area during switch off and recreate during switch on ???
+}
+
+table::CellRangeAddress SAL_CALL ScTableSheetObj::getTitleRows()
+{
+ SolarMutexGuard aGuard;
+ table::CellRangeAddress aRet;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ ScDocument& rDoc = pDocSh->GetDocument();
+ SCTAB nTab = GetTab_Impl();
+ std::optional<ScRange> oRange = rDoc.GetRepeatRowRange(nTab);
+ if (oRange)
+ {
+ ScUnoConversion::FillApiRange( aRet, *oRange );
+ aRet.Sheet = nTab; // core does not care about sheet index
+ }
+ }
+ return aRet;
+}
+
+void SAL_CALL ScTableSheetObj::setTitleRows( const table::CellRangeAddress& aTitleRows )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( !pDocSh )
+ return;
+
+ ScDocument& rDoc = pDocSh->GetDocument();
+ SCTAB nTab = GetTab_Impl();
+
+ std::unique_ptr<ScPrintRangeSaver> pOldRanges = rDoc.CreatePrintRangeSaver();
+
+ ScRange aNew;
+ ScUnoConversion::FillScRange( aNew, aTitleRows );
+ rDoc.SetRepeatRowRange( nTab, std::move(aNew) ); // also always enable
+
+ PrintAreaUndo_Impl( std::move(pOldRanges) ); // Undo, page breaks, modified etc.
+}
+
+// XSheetLinkable
+
+sheet::SheetLinkMode SAL_CALL ScTableSheetObj::getLinkMode()
+{
+ SolarMutexGuard aGuard;
+ sheet::SheetLinkMode eRet = sheet::SheetLinkMode_NONE;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ ScLinkMode nMode = pDocSh->GetDocument().GetLinkMode( GetTab_Impl() );
+ if ( nMode == ScLinkMode::NORMAL )
+ eRet = sheet::SheetLinkMode_NORMAL;
+ else if ( nMode == ScLinkMode::VALUE )
+ eRet = sheet::SheetLinkMode_VALUE;
+ }
+ return eRet;
+}
+
+void SAL_CALL ScTableSheetObj::setLinkMode( sheet::SheetLinkMode nLinkMode )
+{
+ SolarMutexGuard aGuard;
+
+ //! search for filter and options in old link
+
+ OUString aUrl(getLinkUrl());
+ OUString aSheet(getLinkSheetName());
+
+ link( aUrl, aSheet, "", "", nLinkMode );
+}
+
+OUString SAL_CALL ScTableSheetObj::getLinkUrl()
+{
+ SolarMutexGuard aGuard;
+ OUString aFile;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ aFile = pDocSh->GetDocument().GetLinkDoc( GetTab_Impl() );
+ return aFile;
+}
+
+void SAL_CALL ScTableSheetObj::setLinkUrl( const OUString& aLinkUrl )
+{
+ SolarMutexGuard aGuard;
+
+ //! search for filter and options in old link
+
+ sheet::SheetLinkMode eMode = getLinkMode();
+ OUString aSheet(getLinkSheetName());
+
+ link( aLinkUrl, aSheet, "", "", eMode );
+}
+
+OUString SAL_CALL ScTableSheetObj::getLinkSheetName()
+{
+ SolarMutexGuard aGuard;
+ OUString aSheet;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ aSheet = pDocSh->GetDocument().GetLinkTab( GetTab_Impl() );
+ return aSheet;
+}
+
+void SAL_CALL ScTableSheetObj::setLinkSheetName( const OUString& aLinkSheetName )
+{
+ SolarMutexGuard aGuard;
+
+ //! search for filter and options in old link
+
+ sheet::SheetLinkMode eMode = getLinkMode();
+ OUString aUrl(getLinkUrl());
+
+ link( aUrl, aLinkSheetName, "", "", eMode );
+}
+
+void SAL_CALL ScTableSheetObj::link( const OUString& aUrl, const OUString& aSheetName,
+ const OUString& aFilterName, const OUString& aFilterOptions,
+ sheet::SheetLinkMode nMode )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( !pDocSh )
+ return;
+
+ ScDocument& rDoc = pDocSh->GetDocument();
+ SCTAB nTab = GetTab_Impl();
+
+ OUString aFileString = aUrl;
+ OUString aFilterString = aFilterName;
+ OUString aOptString = aFilterOptions;
+
+ aFileString = ScGlobal::GetAbsDocName( aFileString, pDocSh );
+ if (aFilterString.isEmpty())
+ ScDocumentLoader::GetFilterName( aFileString, aFilterString, aOptString, true, false );
+
+ // remove application prefix from filter name here, so the filter options
+ // aren't reset when the filter name is changed in ScTableLink::DataChanged
+ ScDocumentLoader::RemoveAppPrefix( aFilterString );
+
+ ScLinkMode nLinkMode = ScLinkMode::NONE;
+ if ( nMode == sheet::SheetLinkMode_NORMAL )
+ nLinkMode = ScLinkMode::NORMAL;
+ else if ( nMode == sheet::SheetLinkMode_VALUE )
+ nLinkMode = ScLinkMode::VALUE;
+
+ rDoc.SetLink( nTab, nLinkMode, aFileString, aFilterString, aOptString, aSheetName, 0/*nRefresh*/ );
+
+ pDocSh->UpdateLinks(); // if needed add or delete link
+ SfxBindings* pBindings = pDocSh->GetViewBindings();
+ if (pBindings)
+ pBindings->Invalidate(SID_LINKS);
+
+ //! undo of link data on the table
+
+ if ( !(nLinkMode != ScLinkMode::NONE && rDoc.IsExecuteLinkEnabled()) ) // update link
+ return;
+
+ // Always update link also if already exists
+ //! update only on the affected table???
+
+ sfx2::LinkManager* pLinkManager = rDoc.GetLinkManager();
+ sal_uInt16 nCount = pLinkManager->GetLinks().size();
+ for ( sal_uInt16 i=0; i<nCount; i++ )
+ {
+ ::sfx2::SvBaseLink* pBase = pLinkManager->GetLinks()[i].get();
+ if (auto pTabLink = dynamic_cast<ScTableLink*>( pBase))
+ {
+ if ( aFileString == pTabLink->GetFileName() )
+ pTabLink->Update(); // include Paint&Undo
+
+ //! The file name should only exists once (?)
+ }
+ }
+
+ //! notify ScSheetLinkObj objects!!!
+}
+
+// XSheetAuditing
+
+sal_Bool SAL_CALL ScTableSheetObj::hideDependents( const table::CellAddress& aPosition )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ SCTAB nTab = GetTab_Impl();
+ OSL_ENSURE( aPosition.Sheet == nTab, "wrong table in CellAddress" );
+ ScAddress aPos( static_cast<SCCOL>(aPosition.Column), static_cast<SCROW>(aPosition.Row), nTab );
+ return pDocSh->GetDocFunc().DetectiveDelSucc( aPos );
+ }
+ return false;
+}
+
+sal_Bool SAL_CALL ScTableSheetObj::hidePrecedents( const table::CellAddress& aPosition )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ SCTAB nTab = GetTab_Impl();
+ OSL_ENSURE( aPosition.Sheet == nTab, "wrong table in CellAddress" );
+ ScAddress aPos( static_cast<SCCOL>(aPosition.Column), static_cast<SCROW>(aPosition.Row), nTab );
+ return pDocSh->GetDocFunc().DetectiveDelPred( aPos );
+ }
+ return false;
+}
+
+sal_Bool SAL_CALL ScTableSheetObj::showDependents( const table::CellAddress& aPosition )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ SCTAB nTab = GetTab_Impl();
+ OSL_ENSURE( aPosition.Sheet == nTab, "wrong table in CellAddress" );
+ ScAddress aPos( static_cast<SCCOL>(aPosition.Column), static_cast<SCROW>(aPosition.Row), nTab );
+ return pDocSh->GetDocFunc().DetectiveAddSucc( aPos );
+ }
+ return false;
+}
+
+sal_Bool SAL_CALL ScTableSheetObj::showPrecedents( const table::CellAddress& aPosition )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ SCTAB nTab = GetTab_Impl();
+ OSL_ENSURE( aPosition.Sheet == nTab, "wrong table in CellAddress" );
+ ScAddress aPos( static_cast<SCCOL>(aPosition.Column), static_cast<SCROW>(aPosition.Row), nTab );
+ return pDocSh->GetDocFunc().DetectiveAddPred( aPos );
+ }
+ return false;
+}
+
+sal_Bool SAL_CALL ScTableSheetObj::showErrors( const table::CellAddress& aPosition )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ SCTAB nTab = GetTab_Impl();
+ OSL_ENSURE( aPosition.Sheet == nTab, "wrong table in CellAddress" );
+ ScAddress aPos( static_cast<SCCOL>(aPosition.Column), static_cast<SCROW>(aPosition.Row), nTab );
+ return pDocSh->GetDocFunc().DetectiveAddError( aPos );
+ }
+ return false;
+}
+
+sal_Bool SAL_CALL ScTableSheetObj::showInvalid()
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ return pDocSh->GetDocFunc().DetectiveMarkInvalid( GetTab_Impl() );
+ return false;
+}
+
+void SAL_CALL ScTableSheetObj::clearArrows()
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ pDocSh->GetDocFunc().DetectiveDelAll( GetTab_Impl() );
+}
+
+// XSheetOutline
+
+void SAL_CALL ScTableSheetObj::group( const table::CellRangeAddress& rGroupRange,
+ table::TableOrientation nOrientation )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ bool bColumns = ( nOrientation == table::TableOrientation_COLUMNS );
+ ScRange aGroupRange;
+ ScUnoConversion::FillScRange( aGroupRange, rGroupRange );
+ ScOutlineDocFunc aFunc(*pDocSh);
+ aFunc.MakeOutline( aGroupRange, bColumns, true, true );
+ }
+}
+
+void SAL_CALL ScTableSheetObj::ungroup( const table::CellRangeAddress& rGroupRange,
+ table::TableOrientation nOrientation )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ bool bColumns = ( nOrientation == table::TableOrientation_COLUMNS );
+ ScRange aGroupRange;
+ ScUnoConversion::FillScRange( aGroupRange, rGroupRange );
+ ScOutlineDocFunc aFunc(*pDocSh);
+ aFunc.RemoveOutline( aGroupRange, bColumns, true, true );
+ }
+}
+
+void SAL_CALL ScTableSheetObj::autoOutline( const table::CellRangeAddress& rCellRange )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ ScRange aFormulaRange;
+ ScUnoConversion::FillScRange( aFormulaRange, rCellRange );
+ ScOutlineDocFunc aFunc(*pDocSh);
+ aFunc.AutoOutline( aFormulaRange, true );
+ }
+}
+
+void SAL_CALL ScTableSheetObj::clearOutline()
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ SCTAB nTab = GetTab_Impl();
+ ScOutlineDocFunc aFunc(*pDocSh);
+ aFunc.RemoveAllOutlines( nTab, true );
+ }
+}
+
+void SAL_CALL ScTableSheetObj::hideDetail( const table::CellRangeAddress& rCellRange )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ ScRange aMarkRange;
+ ScUnoConversion::FillScRange( aMarkRange, rCellRange );
+ ScOutlineDocFunc aFunc(*pDocSh);
+ aFunc.HideMarkedOutlines( aMarkRange, true );
+ }
+}
+
+void SAL_CALL ScTableSheetObj::showDetail( const table::CellRangeAddress& rCellRange )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ ScRange aMarkRange;
+ ScUnoConversion::FillScRange( aMarkRange, rCellRange );
+ ScOutlineDocFunc aFunc(*pDocSh);
+ aFunc.ShowMarkedOutlines( aMarkRange, true );
+ }
+}
+
+void SAL_CALL ScTableSheetObj::showLevel( sal_Int16 nLevel, table::TableOrientation nOrientation )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ bool bColumns = ( nOrientation == table::TableOrientation_COLUMNS );
+ SCTAB nTab = GetTab_Impl();
+ ScOutlineDocFunc aFunc(*pDocSh);
+ aFunc.SelectLevel( nTab, bColumns, nLevel, true, true );
+ }
+}
+
+// XProtectable
+
+void SAL_CALL ScTableSheetObj::protect( const OUString& aPassword )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ // #i108245# if already protected, don't change anything
+ if ( pDocSh && !pDocSh->GetDocument().IsTabProtected( GetTab_Impl() ) )
+ {
+ pDocSh->GetDocFunc().Protect( GetTab_Impl(), aPassword );
+ }
+}
+
+void SAL_CALL ScTableSheetObj::unprotect( const OUString& aPassword )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ bool bDone = pDocSh->GetDocFunc().Unprotect( GetTab_Impl(), aPassword, true );
+ if (!bDone)
+ throw lang::IllegalArgumentException();
+ }
+}
+
+sal_Bool SAL_CALL ScTableSheetObj::isProtected()
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ return pDocSh->GetDocument().IsTabProtected( GetTab_Impl() );
+
+ OSL_FAIL("no DocShell"); //! Exception or so?
+ return false;
+}
+
+// XScenario
+
+sal_Bool SAL_CALL ScTableSheetObj::getIsScenario()
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ return pDocSh->GetDocument().IsScenario( GetTab_Impl() );
+
+ return false;
+}
+
+OUString SAL_CALL ScTableSheetObj::getScenarioComment()
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ OUString aComment;
+ Color aColor;
+ ScScenarioFlags nFlags;
+ pDocSh->GetDocument().GetScenarioData( GetTab_Impl(), aComment, aColor, nFlags );
+ return aComment;
+ }
+ return OUString();
+}
+
+void SAL_CALL ScTableSheetObj::setScenarioComment( const OUString& aScenarioComment )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( !pDocSh )
+ return;
+
+ ScDocument& rDoc = pDocSh->GetDocument();
+ SCTAB nTab = GetTab_Impl();
+
+ OUString aName;
+ OUString aComment;
+ Color aColor;
+ ScScenarioFlags nFlags;
+ rDoc.GetName( nTab, aName );
+ rDoc.GetScenarioData( nTab, aComment, aColor, nFlags );
+
+ aComment = aScenarioComment;
+
+ pDocSh->ModifyScenario( nTab, aName, aComment, aColor, nFlags );
+}
+
+void SAL_CALL ScTableSheetObj::addRanges( const uno::Sequence<table::CellRangeAddress>& rScenRanges )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( !pDocSh )
+ return;
+
+ ScDocument& rDoc = pDocSh->GetDocument();
+ SCTAB nTab = GetTab_Impl();
+
+ if (!rDoc.IsScenario(nTab))
+ return;
+
+ ScMarkData aMarkData(rDoc.GetSheetLimits());
+ aMarkData.SelectTable( nTab, true );
+
+ for (const table::CellRangeAddress& rRange : rScenRanges)
+ {
+ OSL_ENSURE( rRange.Sheet == nTab, "addRanges with wrong Tab" );
+ ScRange aOneRange( static_cast<SCCOL>(rRange.StartColumn), static_cast<SCROW>(rRange.StartRow), nTab,
+ static_cast<SCCOL>(rRange.EndColumn), static_cast<SCROW>(rRange.EndRow), nTab );
+
+ aMarkData.SetMultiMarkArea( aOneRange );
+ }
+
+ // Scenario ranges are tagged with attribute
+ ScPatternAttr aPattern( rDoc.GetPool() );
+ aPattern.GetItemSet().Put( ScMergeFlagAttr( ScMF::Scenario ) );
+ aPattern.GetItemSet().Put( ScProtectionAttr( true ) );
+ pDocSh->GetDocFunc().ApplyAttributes( aMarkData, aPattern, true );
+}
+
+void SAL_CALL ScTableSheetObj::apply()
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( !pDocSh )
+ return;
+
+ ScDocument& rDoc = pDocSh->GetDocument();
+ SCTAB nTab = GetTab_Impl();
+ OUString aName;
+ rDoc.GetName( nTab, aName ); // scenario name
+
+ SCTAB nDestTab = nTab;
+ while ( nDestTab > 0 && rDoc.IsScenario(nDestTab) )
+ --nDestTab;
+
+ if ( !rDoc.IsScenario(nDestTab) )
+ pDocSh->UseScenario( nDestTab, aName );
+
+ //! otherwise error or so
+}
+
+// XScenarioEnhanced
+
+uno::Sequence< table::CellRangeAddress > SAL_CALL ScTableSheetObj::getRanges( )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ ScDocument& rDoc = pDocSh->GetDocument();
+ SCTAB nTab = GetTab_Impl();
+ const ScRangeList* pRangeList = rDoc.GetScenarioRanges(nTab);
+ if (pRangeList)
+ {
+ size_t nCount = pRangeList->size();
+ uno::Sequence< table::CellRangeAddress > aRetRanges( nCount );
+ table::CellRangeAddress* pAry = aRetRanges.getArray();
+ for( size_t nIndex = 0; nIndex < nCount; nIndex++ )
+ {
+ const ScRange & rRange = (*pRangeList)[nIndex];
+ pAry->StartColumn = rRange.aStart.Col();
+ pAry->StartRow = rRange.aStart.Row();
+ pAry->EndColumn = rRange.aEnd.Col();
+ pAry->EndRow = rRange.aEnd.Row();
+ pAry->Sheet = rRange.aStart.Tab();
+ ++pAry;
+ }
+ return aRetRanges;
+ }
+ }
+ return uno::Sequence< table::CellRangeAddress > ();
+}
+
+// XExternalSheetName
+
+void ScTableSheetObj::setExternalName( const OUString& aUrl, const OUString& aSheetName )
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ {
+ ScDocument& rDoc = pDocSh->GetDocument();
+ const SCTAB nTab = GetTab_Impl();
+ const OUString aAbsDocName( ScGlobal::GetAbsDocName( aUrl, pDocSh ) );
+ const OUString aDocTabName( ScGlobal::GetDocTabName( aAbsDocName, aSheetName ) );
+ if ( !rDoc.RenameTab( nTab, aDocTabName, true /*bExternalDocument*/ ) )
+ {
+ throw container::ElementExistException( OUString(), *this );
+ }
+ }
+}
+
+// XEventsSupplier
+
+uno::Reference<container::XNameReplace> SAL_CALL ScTableSheetObj::getEvents()
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if ( pDocSh )
+ return new ScSheetEventsObj( pDocSh, GetTab_Impl() );
+
+ return nullptr;
+}
+
+// XPropertySet extended for Sheet-Properties
+
+uno::Reference<beans::XPropertySetInfo> SAL_CALL ScTableSheetObj::getPropertySetInfo()
+{
+ SolarMutexGuard aGuard;
+ static uno::Reference<beans::XPropertySetInfo> aRef(
+ new SfxItemPropertySetInfo( pSheetPropSet->getPropertyMap() ));
+ return aRef;
+}
+
+void ScTableSheetObj::SetOnePropertyValue( const SfxItemPropertyMapEntry* pEntry, const uno::Any& aValue )
+{
+ if ( !pEntry )
+ return;
+
+ if ( IsScItemWid( pEntry->nWID ) )
+ {
+ // for Item WIDs, call ScCellRangesBase directly
+ ScCellRangesBase::SetOnePropertyValue(pEntry, aValue);
+ return;
+ }
+
+ // own properties
+
+ ScDocShell* pDocSh = GetDocShell();
+ if (!pDocSh)
+ return; //! Exception or so?
+ ScDocument& rDoc = pDocSh->GetDocument();
+ SCTAB nTab = GetTab_Impl();
+ ScDocFunc &rFunc = pDocSh->GetDocFunc();
+
+ if ( pEntry->nWID == SC_WID_UNO_PAGESTL )
+ {
+ OUString aStrVal;
+ aValue >>= aStrVal;
+ OUString aNewStr(ScStyleNameConversion::ProgrammaticToDisplayName(
+ aStrVal, SfxStyleFamily::Page ));
+
+ //! Undo? (also if SID_STYLE_APPLY on View)
+
+ if ( rDoc.GetPageStyle( nTab ) != aNewStr )
+ {
+ rDoc.SetPageStyle( nTab, aNewStr );
+ if (!rDoc.IsImportingXML())
+ {
+ ScPrintFunc( pDocSh, pDocSh->GetPrinter(), nTab ).UpdatePages();
+
+ SfxBindings* pBindings = pDocSh->GetViewBindings();
+ if (pBindings)
+ {
+ pBindings->Invalidate( SID_STYLE_FAMILY4 );
+ pBindings->Invalidate( SID_STATUS_PAGESTYLE );
+ pBindings->Invalidate( FID_RESET_PRINTZOOM );
+ pBindings->Invalidate( SID_ATTR_PARA_LEFT_TO_RIGHT );
+ pBindings->Invalidate( SID_ATTR_PARA_RIGHT_TO_LEFT );
+ }
+ }
+ pDocSh->SetDocumentModified();
+ }
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_CELLVIS )
+ {
+ bool bVis = ScUnoHelpFunctions::GetBoolFromAny( aValue );
+ rFunc.SetTableVisible( nTab, bVis, true );
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_ISACTIVE )
+ {
+ if (rDoc.IsScenario(nTab))
+ rDoc.SetActiveScenario( nTab, ScUnoHelpFunctions::GetBoolFromAny( aValue ) );
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_BORDCOL )
+ {
+ if (rDoc.IsScenario(nTab))
+ {
+ Color aColor;
+ if (aValue >>= aColor)
+ {
+ OUString aName;
+ OUString aComment;
+ ScScenarioFlags nFlags;
+ Color aTmp;
+ rDoc.GetName( nTab, aName );
+ rDoc.GetScenarioData( nTab, aComment, aTmp, nFlags );
+
+ pDocSh->ModifyScenario( nTab, aName, aComment, aColor, nFlags );
+ }
+ }
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_PROTECT )
+ {
+ if (rDoc.IsScenario(nTab))
+ {
+ OUString aName;
+ OUString aComment;
+ Color aColor;
+ ScScenarioFlags nFlags;
+ rDoc.GetName( nTab, aName );
+ rDoc.GetScenarioData( nTab, aComment, aColor, nFlags );
+ bool bModify(false);
+
+ if (ScUnoHelpFunctions::GetBoolFromAny( aValue ))
+ {
+ if (!(nFlags & ScScenarioFlags::Protected))
+ {
+ nFlags |= ScScenarioFlags::Protected;
+ bModify = true;
+ }
+ }
+ else
+ {
+ if (nFlags & ScScenarioFlags::Protected)
+ {
+ nFlags &= ~ScScenarioFlags::Protected;
+ bModify = true;
+ }
+ }
+
+ if (bModify)
+ pDocSh->ModifyScenario( nTab, aName, aComment, aColor, nFlags );
+ }
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_SHOWBORD )
+ {
+ if (rDoc.IsScenario(nTab))
+ {
+ OUString aName;
+ OUString aComment;
+ Color aColor;
+ ScScenarioFlags nFlags;
+ rDoc.GetName( nTab, aName );
+ rDoc.GetScenarioData( nTab, aComment, aColor, nFlags );
+ bool bModify(false);
+
+ if (ScUnoHelpFunctions::GetBoolFromAny( aValue ))
+ {
+ if (!(nFlags & ScScenarioFlags::ShowFrame))
+ {
+ nFlags |= ScScenarioFlags::ShowFrame;
+ bModify = true;
+ }
+ }
+ else
+ {
+ if (nFlags & ScScenarioFlags::ShowFrame)
+ {
+ nFlags &= ~ScScenarioFlags::ShowFrame;
+ bModify = true;
+ }
+ }
+
+ if (bModify)
+ pDocSh->ModifyScenario( nTab, aName, aComment, aColor, nFlags );
+ }
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_PRINTBORD )
+ {
+ if (rDoc.IsScenario(nTab))
+ {
+ OUString aName;
+ OUString aComment;
+ Color aColor;
+ ScScenarioFlags nFlags;
+ rDoc.GetName( nTab, aName );
+ rDoc.GetScenarioData( nTab, aComment, aColor, nFlags );
+ bool bModify(false);
+
+ if (ScUnoHelpFunctions::GetBoolFromAny( aValue ))
+ {
+ if (!(nFlags & ScScenarioFlags::PrintFrame))
+ {
+ nFlags |= ScScenarioFlags::PrintFrame;
+ bModify = true;
+ }
+ }
+ else
+ {
+ if (nFlags & ScScenarioFlags::PrintFrame)
+ {
+ nFlags &= ~ScScenarioFlags::PrintFrame;
+ bModify = true;
+ }
+ }
+
+ if (bModify)
+ pDocSh->ModifyScenario( nTab, aName, aComment, aColor, nFlags );
+ }
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_COPYBACK )
+ {
+ if (rDoc.IsScenario(nTab))
+ {
+ OUString aName;
+ OUString aComment;
+ Color aColor;
+ ScScenarioFlags nFlags;
+ rDoc.GetName( nTab, aName );
+ rDoc.GetScenarioData( nTab, aComment, aColor, nFlags );
+ bool bModify(false);
+
+ if (ScUnoHelpFunctions::GetBoolFromAny( aValue ))
+ {
+ if (!(nFlags & ScScenarioFlags::TwoWay))
+ {
+ nFlags |= ScScenarioFlags::TwoWay;
+ bModify = true;
+ }
+ }
+ else
+ {
+ if (nFlags & ScScenarioFlags::TwoWay)
+ {
+ nFlags &= ~ScScenarioFlags::TwoWay;
+ bModify = true;
+ }
+ }
+
+ if (bModify)
+ pDocSh->ModifyScenario( nTab, aName, aComment, aColor, nFlags );
+ }
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_COPYSTYL )
+ {
+ if (rDoc.IsScenario(nTab))
+ {
+ OUString aName;
+ OUString aComment;
+ Color aColor;
+ ScScenarioFlags nFlags;
+ rDoc.GetName( nTab, aName );
+ rDoc.GetScenarioData( nTab, aComment, aColor, nFlags );
+ bool bModify(false);
+
+ if (ScUnoHelpFunctions::GetBoolFromAny( aValue ))
+ {
+ if (!(nFlags & ScScenarioFlags::Attrib))
+ {
+ nFlags |= ScScenarioFlags::Attrib;
+ bModify = true;
+ }
+ }
+ else
+ {
+ if (nFlags & ScScenarioFlags::Attrib)
+ {
+ nFlags &= ~ScScenarioFlags::Attrib;
+ bModify = true;
+ }
+ }
+
+ if (bModify)
+ pDocSh->ModifyScenario( nTab, aName, aComment, aColor, nFlags );
+ }
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_COPYFORM )
+ {
+ if (rDoc.IsScenario(nTab))
+ {
+ OUString aName;
+ OUString aComment;
+ Color aColor;
+ ScScenarioFlags nFlags;
+ rDoc.GetName( nTab, aName );
+ rDoc.GetScenarioData( nTab, aComment, aColor, nFlags );
+ bool bModify(false);
+
+ if (ScUnoHelpFunctions::GetBoolFromAny( aValue ))
+ {
+ if (nFlags & ScScenarioFlags::Value)
+ {
+ nFlags &= ~ScScenarioFlags::Value;
+ bModify = true;
+ }
+ }
+ else
+ {
+ if (!(nFlags & ScScenarioFlags::Value))
+ {
+ nFlags |= ScScenarioFlags::Value;
+ bModify = true;
+ }
+ }
+
+ if (bModify)
+ pDocSh->ModifyScenario( nTab, aName, aComment, aColor, nFlags );
+ }
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_TABLAYOUT )
+ {
+ sal_Int16 nValue = 0;
+ if (aValue >>= nValue)
+ {
+ if (nValue == css::text::WritingMode2::RL_TB)
+ rFunc.SetLayoutRTL(nTab, true);
+ else
+ rFunc.SetLayoutRTL(nTab, false);
+ }
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_AUTOPRINT )
+ {
+ bool bAutoPrint = ScUnoHelpFunctions::GetBoolFromAny( aValue );
+ if (bAutoPrint)
+ rDoc.SetPrintEntireSheet( nTab ); // clears all print ranges
+ else
+ {
+ if (rDoc.IsPrintEntireSheet( nTab ))
+ rDoc.ClearPrintRanges( nTab ); // if this flag is true, there are no PrintRanges, so Clear clears only the flag.
+ }
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_TABCOLOR )
+ {
+ Color aColor = COL_AUTO;
+ if ( aValue >>= aColor )
+ {
+ if ( rDoc.GetTabBgColor( nTab ) != aColor )
+ rFunc.SetTabBgColor( nTab, aColor, true, true );
+ }
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_CODENAME )
+ {
+ OUString aCodeName;
+ if (aValue >>= aCodeName)
+ {
+ pDocSh->GetDocument().SetCodeName( GetTab_Impl(), aCodeName );
+ }
+ }
+ else if (pEntry->nWID == SC_WID_UNO_CONDFORMAT)
+ {
+ uno::Reference<sheet::XConditionalFormats> xCondFormat;
+ if (aValue >>= xCondFormat)
+ {
+ // how to set the format correctly
+ }
+ }
+ else
+ ScCellRangeObj::SetOnePropertyValue(pEntry, aValue); // base class, no Item WID
+}
+
+void ScTableSheetObj::GetOnePropertyValue( const SfxItemPropertyMapEntry* pEntry,
+ uno::Any& rAny )
+{
+ if ( !pEntry )
+ return;
+
+ ScDocShell* pDocSh = GetDocShell();
+ if (!pDocSh)
+ throw uno::RuntimeException();
+ ScDocument& rDoc = pDocSh->GetDocument();
+ SCTAB nTab = GetTab_Impl();
+
+ if ( pEntry->nWID == SC_WID_UNO_NAMES )
+ {
+ rAny <<= uno::Reference<sheet::XNamedRanges>(new ScLocalNamedRangesObj(pDocSh, this));
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_PAGESTL )
+ {
+ rAny <<= ScStyleNameConversion::DisplayToProgrammaticName(
+ rDoc.GetPageStyle( nTab ), SfxStyleFamily::Page );
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_CELLVIS )
+ {
+ bool bVis = rDoc.IsVisible( nTab );
+ rAny <<= bVis;
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_LINKDISPBIT )
+ {
+ // no target bitmaps for individual entries (would be all equal)
+ // ScLinkTargetTypeObj::SetLinkTargetBitmap( aAny, SC_LINKTARGETTYPE_SHEET );
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_LINKDISPNAME )
+ {
+ // LinkDisplayName for hyperlink dialog
+ rAny <<= getName(); // sheet name
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_ISACTIVE )
+ {
+ if (rDoc.IsScenario(nTab))
+ rAny <<= rDoc.IsActiveScenario( nTab );
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_BORDCOL )
+ {
+ if (rDoc.IsScenario(nTab))
+ {
+ OUString aComment;
+ Color aColor;
+ ScScenarioFlags nFlags;
+ rDoc.GetScenarioData( nTab, aComment, aColor, nFlags );
+
+ rAny <<= aColor;
+ }
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_PROTECT )
+ {
+ if (rDoc.IsScenario(nTab))
+ {
+ ScScenarioFlags nFlags;
+ rDoc.GetScenarioFlags(nTab, nFlags);
+
+ rAny <<= ((nFlags & ScScenarioFlags::Protected) != ScScenarioFlags::NONE);
+ }
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_SHOWBORD )
+ {
+ if (rDoc.IsScenario(nTab))
+ {
+ ScScenarioFlags nFlags;
+ rDoc.GetScenarioFlags(nTab, nFlags);
+
+ rAny <<= ((nFlags & ScScenarioFlags::ShowFrame) != ScScenarioFlags::NONE);
+ }
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_PRINTBORD )
+ {
+ if (rDoc.IsScenario(nTab))
+ {
+ ScScenarioFlags nFlags;
+ rDoc.GetScenarioFlags(nTab, nFlags);
+
+ rAny <<= ((nFlags & ScScenarioFlags::PrintFrame) != ScScenarioFlags::NONE);
+ }
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_COPYBACK )
+ {
+ if (rDoc.IsScenario(nTab))
+ {
+ ScScenarioFlags nFlags;
+ rDoc.GetScenarioFlags(nTab, nFlags);
+
+ rAny <<= ((nFlags & ScScenarioFlags::TwoWay) != ScScenarioFlags::NONE);
+ }
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_COPYSTYL )
+ {
+ if (rDoc.IsScenario(nTab))
+ {
+ ScScenarioFlags nFlags;
+ rDoc.GetScenarioFlags(nTab, nFlags);
+
+ rAny <<= ((nFlags & ScScenarioFlags::Attrib) != ScScenarioFlags::NONE);
+ }
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_COPYFORM )
+ {
+ if (rDoc.IsScenario(nTab))
+ {
+ ScScenarioFlags nFlags;
+ rDoc.GetScenarioFlags(nTab, nFlags);
+
+ rAny <<= !(nFlags & ScScenarioFlags::Value);
+ }
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_TABLAYOUT )
+ {
+ if (rDoc.IsLayoutRTL(nTab))
+ rAny <<= sal_Int16(css::text::WritingMode2::RL_TB);
+ else
+ rAny <<= sal_Int16(css::text::WritingMode2::LR_TB);
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_AUTOPRINT )
+ {
+ bool bAutoPrint = rDoc.IsPrintEntireSheet( nTab );
+ rAny <<= bAutoPrint;
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_TABCOLOR )
+ {
+ rAny <<= rDoc.GetTabBgColor(nTab);
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_CODENAME )
+ {
+ OUString aCodeName;
+ pDocSh->GetDocument().GetCodeName(GetTab_Impl(), aCodeName);
+ rAny <<= aCodeName;
+ }
+ else if (pEntry->nWID == SC_WID_UNO_CONDFORMAT)
+ {
+ rAny <<= uno::Reference<sheet::XConditionalFormats>(new ScCondFormatsObj(pDocSh, nTab));
+ }
+ else
+ ScCellRangeObj::GetOnePropertyValue(pEntry, rAny);
+}
+
+const SfxItemPropertyMap& ScTableSheetObj::GetItemPropertyMap()
+{
+ return pSheetPropSet->getPropertyMap();
+}
+
+// XServiceInfo
+
+OUString SAL_CALL ScTableSheetObj::getImplementationName()
+{
+ return "ScTableSheetObj";
+}
+
+sal_Bool SAL_CALL ScTableSheetObj::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence<OUString> SAL_CALL ScTableSheetObj::getSupportedServiceNames()
+{
+ return {SCSPREADSHEET_SERVICE,
+ SCSHEETCELLRANGE_SERVICE,
+ SCCELLRANGE_SERVICE,
+ SCCELLPROPERTIES_SERVICE,
+ SCCHARPROPERTIES_SERVICE,
+ SCPARAPROPERTIES_SERVICE,
+ SCLINKTARGET_SERVICE};
+}
+
+// XUnoTunnel
+
+UNO3_GETIMPLEMENTATION2_IMPL(ScTableSheetObj, ScCellRangeObj);
+
+ScTableColumnObj::ScTableColumnObj( ScDocShell* pDocSh, SCCOL nCol, SCTAB nTab ) :
+ ScCellRangeObj( pDocSh, ScRange(nCol,0,nTab, nCol, pDocSh->GetDocument().MaxRow(),nTab) ),
+ pColPropSet(lcl_GetColumnPropertySet())
+{
+}
+
+ScTableColumnObj::~ScTableColumnObj()
+{
+}
+
+uno::Any SAL_CALL ScTableColumnObj::queryInterface( const uno::Type& rType )
+{
+ SC_QUERYINTERFACE( container::XNamed )
+
+ return ScCellRangeObj::queryInterface( rType );
+}
+
+void SAL_CALL ScTableColumnObj::acquire() noexcept
+{
+ ScCellRangeObj::acquire();
+}
+
+void SAL_CALL ScTableColumnObj::release() noexcept
+{
+ ScCellRangeObj::release();
+}
+
+uno::Sequence<uno::Type> SAL_CALL ScTableColumnObj::getTypes()
+{
+ return comphelper::concatSequences(
+ ScCellRangeObj::getTypes(),
+ uno::Sequence<uno::Type> { cppu::UnoType<container::XNamed>::get() } );
+}
+
+uno::Sequence<sal_Int8> SAL_CALL ScTableColumnObj::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// XNamed
+
+OUString SAL_CALL ScTableColumnObj::getName()
+{
+ SolarMutexGuard aGuard;
+
+ const ScRange& rRange = GetRange();
+ OSL_ENSURE(rRange.aStart.Col() == rRange.aEnd.Col(), "too many columns");
+ SCCOL nCol = rRange.aStart.Col();
+
+ return ScColToAlpha( nCol ); // from global.hxx
+}
+
+void SAL_CALL ScTableColumnObj::setName( const OUString& /* aNewName */ )
+{
+ throw uno::RuntimeException(); // read-only
+}
+
+// XPropertySet extended for Column-Properties
+
+uno::Reference<beans::XPropertySetInfo> SAL_CALL ScTableColumnObj::getPropertySetInfo()
+{
+ SolarMutexGuard aGuard;
+ static uno::Reference<beans::XPropertySetInfo> aRef(
+ new SfxItemPropertySetInfo( pColPropSet->getPropertyMap() ));
+ return aRef;
+}
+
+void ScTableColumnObj::SetOnePropertyValue(const SfxItemPropertyMapEntry* pEntry, const uno::Any& aValue)
+{
+ if ( !pEntry )
+ return;
+
+ if ( IsScItemWid( pEntry->nWID ) )
+ {
+ // for Item WIDs, call ScCellRangesBase directly
+ ScCellRangesBase::SetOnePropertyValue(pEntry, aValue);
+ return;
+ }
+
+ // own properties
+
+ ScDocShell* pDocSh = GetDocShell();
+ if (!pDocSh)
+ return; //! Exception or so?
+ const ScRange& rRange = GetRange();
+ OSL_ENSURE(rRange.aStart.Col() == rRange.aEnd.Col(), "Too many columns");
+ SCCOL nCol = rRange.aStart.Col();
+ SCTAB nTab = rRange.aStart.Tab();
+ ScDocFunc &rFunc = pDocSh->GetDocFunc();
+
+ std::vector<sc::ColRowSpan> aColArr(1, sc::ColRowSpan(nCol,nCol));
+
+ if ( pEntry->nWID == SC_WID_UNO_CELLWID )
+ {
+ sal_Int32 nNewWidth = 0;
+ if ( aValue >>= nNewWidth )
+ {
+ // property is 1/100mm, column width is twips
+ nNewWidth = o3tl::toTwips(nNewWidth, o3tl::Length::mm100);
+ rFunc.SetWidthOrHeight(
+ true, aColArr, nTab, SC_SIZE_ORIGINAL, nNewWidth, true, true);
+ }
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_CELLVIS )
+ {
+ bool bVis = ScUnoHelpFunctions::GetBoolFromAny( aValue );
+ ScSizeMode eMode = bVis ? SC_SIZE_SHOW : SC_SIZE_DIRECT;
+ rFunc.SetWidthOrHeight(true, aColArr, nTab, eMode, 0, true, true);
+ // SC_SIZE_DIRECT with size 0 will hide
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_OWIDTH )
+ {
+ bool bOpt = ScUnoHelpFunctions::GetBoolFromAny( aValue );
+ if (bOpt)
+ rFunc.SetWidthOrHeight(
+ true, aColArr, nTab, SC_SIZE_OPTIMAL, STD_EXTRA_WIDTH, true, true);
+ // sal_False on columns currently without effect
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_NEWPAGE || pEntry->nWID == SC_WID_UNO_MANPAGE )
+ {
+ bool bSet = ScUnoHelpFunctions::GetBoolFromAny( aValue );
+ if (bSet)
+ rFunc.InsertPageBreak( true, rRange.aStart, true, true );
+ else
+ rFunc.RemovePageBreak( true, rRange.aStart, true, true );
+ }
+ else
+ ScCellRangeObj::SetOnePropertyValue(pEntry, aValue); // base class, no Item WID
+}
+
+void ScTableColumnObj::GetOnePropertyValue( const SfxItemPropertyMapEntry* pEntry, uno::Any& rAny )
+{
+ if ( !pEntry )
+ return;
+
+ ScDocShell* pDocSh = GetDocShell();
+ if (!pDocSh)
+ throw uno::RuntimeException();
+
+ ScDocument& rDoc = pDocSh->GetDocument();
+ const ScRange& rRange = GetRange();
+ OSL_ENSURE(rRange.aStart.Col() == rRange.aEnd.Col(), "too many columns");
+ SCCOL nCol = rRange.aStart.Col();
+ SCTAB nTab = rRange.aStart.Tab();
+
+ if ( pEntry->nWID == SC_WID_UNO_CELLWID )
+ {
+ // for hidden column, return original height
+ sal_uInt16 nWidth = rDoc.GetOriginalWidth( nCol, nTab );
+ // property is 1/100mm, column width is twips
+ nWidth = static_cast<sal_uInt16>(convertTwipToMm100(nWidth));
+ rAny <<= static_cast<sal_Int32>(nWidth);
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_CELLVIS )
+ {
+ bool bHidden = rDoc.ColHidden(nCol, nTab);
+ rAny <<= !bHidden;
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_OWIDTH )
+ {
+ //! at the moment always set ??!?!
+ bool bOpt = !(rDoc.GetColFlags( nCol, nTab ) & CRFlags::ManualSize);
+ rAny <<= bOpt;
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_NEWPAGE )
+ {
+ ScBreakType nBreak = rDoc.HasColBreak(nCol, nTab);
+ rAny <<= nBreak != ScBreakType::NONE;
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_MANPAGE )
+ {
+ ScBreakType nBreak = rDoc.HasColBreak(nCol, nTab);
+ rAny <<= bool(nBreak & ScBreakType::Manual);
+ }
+ else
+ ScCellRangeObj::GetOnePropertyValue(pEntry, rAny);
+}
+
+const SfxItemPropertyMap& ScTableColumnObj::GetItemPropertyMap()
+{
+ return pColPropSet->getPropertyMap();
+}
+
+ScTableRowObj::ScTableRowObj(ScDocShell* pDocSh, SCROW nRow, SCTAB nTab) :
+ ScCellRangeObj( pDocSh, ScRange(0,nRow,nTab, pDocSh->GetDocument().MaxCol(),nRow,nTab) ),
+ pRowPropSet(lcl_GetRowPropertySet())
+{
+}
+
+ScTableRowObj::~ScTableRowObj()
+{
+}
+
+// XPropertySet extended for Row-Properties
+
+uno::Reference<beans::XPropertySetInfo> SAL_CALL ScTableRowObj::getPropertySetInfo()
+{
+ SolarMutexGuard aGuard;
+ static uno::Reference<beans::XPropertySetInfo> aRef(
+ new SfxItemPropertySetInfo( pRowPropSet->getPropertyMap() ));
+ return aRef;
+}
+
+void ScTableRowObj::SetOnePropertyValue( const SfxItemPropertyMapEntry* pEntry, const uno::Any& aValue )
+{
+ if ( !pEntry )
+ return;
+
+ if ( IsScItemWid( pEntry->nWID ) )
+ {
+ // for Item WIDs, call ScCellRangesBase directly
+ ScCellRangesBase::SetOnePropertyValue(pEntry, aValue);
+ return;
+ }
+
+ // own properties
+
+ ScDocShell* pDocSh = GetDocShell();
+ if (!pDocSh)
+ return; //! Exception or so?
+ ScDocument& rDoc = pDocSh->GetDocument();
+ const ScRange& rRange = GetRange();
+ OSL_ENSURE(rRange.aStart.Row() == rRange.aEnd.Row(), "too many rows");
+ SCROW nRow = rRange.aStart.Row();
+ SCTAB nTab = rRange.aStart.Tab();
+ ScDocFunc &rFunc = pDocSh->GetDocFunc();
+
+ std::vector<sc::ColRowSpan> aRowArr(1, sc::ColRowSpan(nRow,nRow));
+
+ if ( pEntry->nWID == SC_WID_UNO_CELLHGT )
+ {
+ sal_Int32 nNewHeight = 0;
+ if ( aValue >>= nNewHeight )
+ {
+ // property is 1/100mm, row height is twips
+ nNewHeight = o3tl::toTwips(nNewHeight, o3tl::Length::mm100);
+ rFunc.SetWidthOrHeight(
+ false, aRowArr, nTab, SC_SIZE_ORIGINAL, nNewHeight, true, true);
+ }
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_CELLVIS )
+ {
+ bool bVis = ScUnoHelpFunctions::GetBoolFromAny( aValue );
+ ScSizeMode eMode = bVis ? SC_SIZE_SHOW : SC_SIZE_DIRECT;
+ rFunc.SetWidthOrHeight(false, aRowArr, nTab, eMode, 0, true, true);
+ // SC_SIZE_DIRECT with size zero will hide
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_CELLFILT )
+ {
+ bool bFil = ScUnoHelpFunctions::GetBoolFromAny( aValue );
+ // SC_SIZE_DIRECT with size zero will hide
+ rDoc.SetRowFiltered(nRow, nRow, nTab, bFil);
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_OHEIGHT )
+ {
+ bool bOpt = ScUnoHelpFunctions::GetBoolFromAny( aValue );
+ if (bOpt)
+ rFunc.SetWidthOrHeight(false, aRowArr, nTab, SC_SIZE_OPTIMAL, 0, true, true);
+ else
+ {
+ // set current height again manually
+ sal_uInt16 nHeight = rDoc.GetOriginalHeight( nRow, nTab );
+ rFunc.SetWidthOrHeight(false, aRowArr, nTab, SC_SIZE_ORIGINAL, nHeight, true, true);
+ }
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_NEWPAGE || pEntry->nWID == SC_WID_UNO_MANPAGE )
+ {
+ bool bSet = ScUnoHelpFunctions::GetBoolFromAny( aValue );
+ if (bSet)
+ rFunc.InsertPageBreak( false, rRange.aStart, true, true );
+ else
+ rFunc.RemovePageBreak( false, rRange.aStart, true, true );
+ }
+ else
+ ScCellRangeObj::SetOnePropertyValue(pEntry, aValue); // base class, no Item WID
+}
+
+void ScTableRowObj::GetOnePropertyValue( const SfxItemPropertyMapEntry* pEntry, uno::Any& rAny )
+{
+ if ( !pEntry )
+ return;
+
+ ScDocShell* pDocSh = GetDocShell();
+ if (!pDocSh)
+ throw uno::RuntimeException();
+ ScDocument& rDoc = pDocSh->GetDocument();
+ const ScRange& rRange = GetRange();
+ OSL_ENSURE(rRange.aStart.Row() == rRange.aEnd.Row(), "too many rows");
+ SCROW nRow = rRange.aStart.Row();
+ SCTAB nTab = rRange.aStart.Tab();
+
+ if ( pEntry->nWID == SC_WID_UNO_CELLHGT )
+ {
+ // for hidden row, return original height
+ sal_uInt16 nHeight = rDoc.GetOriginalHeight( nRow, nTab );
+ // property is 1/100mm, row height is twips
+ nHeight = static_cast<sal_uInt16>(convertTwipToMm100(nHeight));
+ rAny <<= static_cast<sal_Int32>(nHeight);
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_CELLVIS )
+ {
+ bool bHidden = rDoc.RowHidden(nRow, nTab);
+ rAny <<= !bHidden;
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_CELLFILT )
+ {
+ bool bVis = rDoc.RowFiltered(nRow, nTab);
+ rAny <<= bVis;
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_OHEIGHT )
+ {
+ bool bOpt = !(rDoc.GetRowFlags( nRow, nTab ) & CRFlags::ManualSize);
+ rAny <<= bOpt;
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_NEWPAGE )
+ {
+ ScBreakType nBreak = rDoc.HasRowBreak(nRow, nTab);
+ rAny <<= (nBreak != ScBreakType::NONE);
+ }
+ else if ( pEntry->nWID == SC_WID_UNO_MANPAGE )
+ {
+ bool bBreak(rDoc.HasRowBreak(nRow, nTab) & ScBreakType::Manual);
+ rAny <<= bBreak;
+ }
+ else
+ ScCellRangeObj::GetOnePropertyValue(pEntry, rAny);
+}
+
+const SfxItemPropertyMap& ScTableRowObj::GetItemPropertyMap()
+{
+ return pRowPropSet->getPropertyMap();
+}
+
+ScCellsObj::ScCellsObj(ScDocShell* pDocSh, const ScRangeList& rR) :
+ pDocShell( pDocSh ),
+ aRanges( rR )
+{
+ pDocShell->GetDocument().AddUnoObject(*this);
+}
+
+ScCellsObj::~ScCellsObj()
+{
+ SolarMutexGuard g;
+
+ if (pDocShell)
+ pDocShell->GetDocument().RemoveUnoObject(*this);
+}
+
+void ScCellsObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
+{
+ if ( auto pRefHint = dynamic_cast<const ScUpdateRefHint*>(&rHint) )
+ {
+ aRanges.UpdateReference( pRefHint->GetMode(), &pDocShell->GetDocument(), pRefHint->GetRange(),
+ pRefHint->GetDx(), pRefHint->GetDy(), pRefHint->GetDz() );
+ }
+ else if ( rHint.GetId() == SfxHintId::Dying )
+ {
+ pDocShell = nullptr;
+ }
+}
+
+// XEnumerationAccess
+
+uno::Reference<container::XEnumeration> SAL_CALL ScCellsObj::createEnumeration()
+{
+ SolarMutexGuard aGuard;
+ if (pDocShell)
+ return new ScCellsEnumeration( pDocShell, aRanges );
+ return nullptr;
+}
+
+uno::Type SAL_CALL ScCellsObj::getElementType()
+{
+ return cppu::UnoType<table::XCell>::get();
+}
+
+sal_Bool SAL_CALL ScCellsObj::hasElements()
+{
+ SolarMutexGuard aGuard;
+ bool bHas = false;
+ if ( pDocShell )
+ {
+ //! faster if test ourself?
+
+ uno::Reference<container::XEnumeration> xEnum(new ScCellsEnumeration( pDocShell, aRanges ));
+ bHas = xEnum->hasMoreElements();
+ }
+ return bHas;
+}
+
+ScCellsEnumeration::ScCellsEnumeration(ScDocShell* pDocSh, const ScRangeList& rR) :
+ pDocShell( pDocSh ),
+ aRanges( rR ),
+ bAtEnd( false )
+{
+ ScDocument& rDoc = pDocShell->GetDocument();
+ rDoc.AddUnoObject(*this);
+
+ if ( aRanges.empty() )
+ bAtEnd = true;
+ else
+ {
+ SCTAB nTab = aRanges[ 0 ].aStart.Tab();
+ aPos = ScAddress(0,0,nTab);
+ CheckPos_Impl(); // set aPos on first matching cell
+ }
+}
+
+void ScCellsEnumeration::CheckPos_Impl()
+{
+ if (!pDocShell)
+ return;
+
+ bool bFound = false;
+ ScDocument& rDoc = pDocShell->GetDocument();
+ ScRefCellValue aCell(rDoc, aPos);
+ if (!aCell.isEmpty())
+ {
+ if (!pMark)
+ {
+ pMark.reset( new ScMarkData(rDoc.GetSheetLimits()) );
+ pMark->MarkFromRangeList(aRanges, false);
+ pMark->MarkToMulti(); // needed for GetNextMarkedCell
+ }
+ bFound = pMark->IsCellMarked(aPos.Col(), aPos.Row());
+ }
+ if (!bFound)
+ Advance_Impl();
+}
+
+ScCellsEnumeration::~ScCellsEnumeration()
+{
+ SolarMutexGuard g;
+
+ if (pDocShell)
+ pDocShell->GetDocument().RemoveUnoObject(*this);
+ pMark.reset();
+}
+
+void ScCellsEnumeration::Advance_Impl()
+{
+ OSL_ENSURE(!bAtEnd,"too much Advance_Impl");
+ if (!pMark)
+ {
+ pMark.reset( new ScMarkData(pDocShell->GetDocument().GetSheetLimits()) );
+ pMark->MarkFromRangeList( aRanges, false );
+ pMark->MarkToMulti(); // needed for GetNextMarkedCell
+ }
+
+ SCCOL nCol = aPos.Col();
+ SCROW nRow = aPos.Row();
+ SCTAB nTab = aPos.Tab();
+ bool bFound = pDocShell->GetDocument().GetNextMarkedCell( nCol, nRow, nTab, *pMark );
+ if (bFound)
+ aPos.Set( nCol, nRow, nTab );
+ else
+ bAtEnd = true; // nothing will follow
+}
+
+void ScCellsEnumeration::Notify( SfxBroadcaster&, const SfxHint& rHint )
+{
+ const ScUpdateRefHint* pRefHint = dynamic_cast<const ScUpdateRefHint*>(&rHint);
+ if ( pRefHint )
+ {
+ if (pDocShell)
+ {
+ aRanges.UpdateReference( pRefHint->GetMode(), &pDocShell->GetDocument(), pRefHint->GetRange(),
+ pRefHint->GetDx(), pRefHint->GetDy(), pRefHint->GetDz() );
+
+ pMark.reset(); // recreate from moved area
+
+ if (!bAtEnd) // adjust aPos
+ {
+ ScRangeList aNew { ScRange(aPos) };
+ aNew.UpdateReference( pRefHint->GetMode(), &pDocShell->GetDocument(), pRefHint->GetRange(),
+ pRefHint->GetDx(), pRefHint->GetDy(), pRefHint->GetDz() );
+ if (aNew.size()==1)
+ {
+ aPos = aNew[ 0 ].aStart;
+ CheckPos_Impl();
+ }
+ }
+ }
+ }
+ else if ( rHint.GetId() == SfxHintId::Dying )
+ {
+ pDocShell = nullptr;
+ }
+}
+
+// XEnumeration
+
+sal_Bool SAL_CALL ScCellsEnumeration::hasMoreElements()
+{
+ SolarMutexGuard aGuard;
+ return !bAtEnd;
+}
+
+uno::Any SAL_CALL ScCellsEnumeration::nextElement()
+{
+ SolarMutexGuard aGuard;
+ if (pDocShell && !bAtEnd)
+ {
+ // interface must match ScCellsObj::getElementType
+
+ ScAddress aTempPos(aPos);
+ Advance_Impl();
+ return uno::Any(uno::Reference<table::XCell>(new ScCellObj( pDocShell, aTempPos )));
+ }
+
+ throw container::NoSuchElementException(); // no more elements
+}
+
+ScCellFormatsObj::ScCellFormatsObj(ScDocShell* pDocSh, const ScRange& rRange) :
+ pDocShell( pDocSh ),
+ aTotalRange( rRange )
+{
+ ScDocument& rDoc = pDocShell->GetDocument();
+ rDoc.AddUnoObject(*this);
+
+ OSL_ENSURE( aTotalRange.aStart.Tab() == aTotalRange.aEnd.Tab(), "different tables" );
+}
+
+ScCellFormatsObj::~ScCellFormatsObj()
+{
+ SolarMutexGuard g;
+
+ if (pDocShell)
+ pDocShell->GetDocument().RemoveUnoObject(*this);
+}
+
+void ScCellFormatsObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
+{
+ if ( dynamic_cast<const ScUpdateRefHint*>(&rHint) )
+ {
+ //! aTotalRange...
+ }
+ else if ( rHint.GetId() == SfxHintId::Dying )
+ {
+ pDocShell = nullptr;
+ }
+}
+
+rtl::Reference<ScCellRangeObj> ScCellFormatsObj::GetObjectByIndex_Impl(tools::Long nIndex) const
+{
+ //! access the AttrArrays directly !!!!
+
+ if (pDocShell)
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+ tools::Long nPos = 0;
+ ScAttrRectIterator aIter( rDoc, aTotalRange.aStart.Tab(),
+ aTotalRange.aStart.Col(), aTotalRange.aStart.Row(),
+ aTotalRange.aEnd.Col(), aTotalRange.aEnd.Row() );
+ SCCOL nCol1, nCol2;
+ SCROW nRow1, nRow2;
+ while ( aIter.GetNext( nCol1, nCol2, nRow1, nRow2 ) )
+ {
+ if ( nPos == nIndex )
+ {
+ SCTAB nTab = aTotalRange.aStart.Tab();
+ ScRange aNext( nCol1, nRow1, nTab, nCol2, nRow2, nTab );
+
+ if ( aNext.aStart == aNext.aEnd )
+ return new ScCellObj( pDocShell, aNext.aStart );
+ else
+ return new ScCellRangeObj( pDocShell, aNext );
+ }
+ ++nPos;
+ }
+ }
+ return {};
+}
+
+// XIndexAccess
+
+sal_Int32 SAL_CALL ScCellFormatsObj::getCount()
+{
+ SolarMutexGuard aGuard;
+
+ //! access the AttrArrays directly !!!!
+
+ tools::Long nCount = 0;
+ if (pDocShell)
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+ ScAttrRectIterator aIter( rDoc, aTotalRange.aStart.Tab(),
+ aTotalRange.aStart.Col(), aTotalRange.aStart.Row(),
+ aTotalRange.aEnd.Col(), aTotalRange.aEnd.Row() );
+ SCCOL nCol1, nCol2;
+ SCROW nRow1, nRow2;
+ while ( aIter.GetNext( nCol1, nCol2, nRow1, nRow2 ) )
+ ++nCount;
+ }
+ return nCount;
+}
+
+uno::Any SAL_CALL ScCellFormatsObj::getByIndex( sal_Int32 nIndex )
+{
+ SolarMutexGuard aGuard;
+
+ uno::Reference<table::XCellRange> xRange(GetObjectByIndex_Impl(nIndex));
+ if (!xRange.is())
+ throw lang::IndexOutOfBoundsException();
+
+ return uno::Any(xRange);
+
+}
+
+uno::Type SAL_CALL ScCellFormatsObj::getElementType()
+{
+ return cppu::UnoType<table::XCellRange>::get();
+}
+
+sal_Bool SAL_CALL ScCellFormatsObj::hasElements()
+{
+ SolarMutexGuard aGuard;
+ return ( getCount() != 0 ); //! always greater then zero ??
+}
+
+// XEnumerationAccess
+
+uno::Reference<container::XEnumeration> SAL_CALL ScCellFormatsObj::createEnumeration()
+{
+ SolarMutexGuard aGuard;
+ if (pDocShell)
+ return new ScCellFormatsEnumeration( pDocShell, aTotalRange );
+ return nullptr;
+}
+
+ScCellFormatsEnumeration::ScCellFormatsEnumeration(ScDocShell* pDocSh, const ScRange& rRange) :
+ pDocShell( pDocSh ),
+ nTab( rRange.aStart.Tab() ),
+ bAtEnd( false ),
+ bDirty( false )
+{
+ ScDocument& rDoc = pDocShell->GetDocument();
+ rDoc.AddUnoObject(*this);
+
+ OSL_ENSURE( rRange.aStart.Tab() == rRange.aEnd.Tab(),
+ "CellFormatsEnumeration: different tables" );
+
+ pIter.reset( new ScAttrRectIterator( rDoc, nTab,
+ rRange.aStart.Col(), rRange.aStart.Row(),
+ rRange.aEnd.Col(), rRange.aEnd.Row() ) );
+ Advance_Impl();
+}
+
+ScCellFormatsEnumeration::~ScCellFormatsEnumeration()
+{
+ SolarMutexGuard g;
+
+ if (pDocShell)
+ pDocShell->GetDocument().RemoveUnoObject(*this);
+}
+
+void ScCellFormatsEnumeration::Advance_Impl()
+{
+ OSL_ENSURE(!bAtEnd,"too many Advance_Impl");
+
+ if ( pIter )
+ {
+ if ( bDirty )
+ {
+ pIter->DataChanged(); // new search for AttrArray-Index
+ bDirty = false;
+ }
+
+ SCCOL nCol1, nCol2;
+ SCROW nRow1, nRow2;
+ if ( pIter->GetNext( nCol1, nCol2, nRow1, nRow2 ) )
+ aNext = ScRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab );
+ else
+ bAtEnd = true;
+ }
+ else
+ bAtEnd = true; // document vanished or so
+}
+
+rtl::Reference<ScCellRangeObj> ScCellFormatsEnumeration::NextObject_Impl()
+{
+ rtl::Reference<ScCellRangeObj> pRet;
+ if (pDocShell && !bAtEnd)
+ {
+ if ( aNext.aStart == aNext.aEnd )
+ pRet = new ScCellObj( pDocShell, aNext.aStart );
+ else
+ pRet = new ScCellRangeObj( pDocShell, aNext );
+ Advance_Impl();
+ }
+ return pRet;
+}
+
+void ScCellFormatsEnumeration::Notify( SfxBroadcaster&, const SfxHint& rHint )
+{
+ if ( dynamic_cast<const ScUpdateRefHint*>(&rHint) )
+ {
+ //! and now???
+ }
+ else
+ {
+ const SfxHintId nId = rHint.GetId();
+ if ( nId == SfxHintId::Dying )
+ {
+ pDocShell = nullptr;
+ pIter.reset();
+ }
+ else if ( nId == SfxHintId::DataChanged )
+ {
+ bDirty = true; // AttrArray-Index possibly invalid
+ }
+ }
+}
+
+// XEnumeration
+
+sal_Bool SAL_CALL ScCellFormatsEnumeration::hasMoreElements()
+{
+ SolarMutexGuard aGuard;
+ return !bAtEnd;
+}
+
+uno::Any SAL_CALL ScCellFormatsEnumeration::nextElement()
+{
+ SolarMutexGuard aGuard;
+
+ if ( bAtEnd || !pDocShell )
+ throw container::NoSuchElementException(); // no more elements
+
+ // interface must match ScCellFormatsObj::getElementType
+
+ return uno::Any(uno::Reference<table::XCellRange> (NextObject_Impl()));
+}
+
+ScUniqueCellFormatsObj::~ScUniqueCellFormatsObj()
+{
+ SolarMutexGuard g;
+
+ if (pDocShell)
+ pDocShell->GetDocument().RemoveUnoObject(*this);
+}
+
+void ScUniqueCellFormatsObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
+{
+ if ( dynamic_cast<const ScUpdateRefHint*>(&rHint) )
+ {
+ //! aTotalRange...
+ }
+ else
+ {
+ if ( rHint.GetId() == SfxHintId::Dying )
+ pDocShell = nullptr;
+ }
+}
+
+// Fill the list of formats from the document
+
+namespace {
+
+// hash code to access the range lists by ScPatternAttr pointer
+struct ScPatternHashCode
+{
+ size_t operator()( const ScPatternAttr* pPattern ) const
+ {
+ return reinterpret_cast<size_t>(pPattern);
+ }
+};
+
+}
+
+// Hash map to find a range by its start row
+typedef std::unordered_map< SCROW, ScRange > ScRowRangeHashMap;
+
+namespace {
+
+// Hash map entry.
+// The Join method depends on the column-wise order of ScAttrRectIterator
+class ScUniqueFormatsEntry
+{
+ enum EntryState { STATE_EMPTY, STATE_SINGLE, STATE_COMPLEX };
+
+ EntryState eState;
+ ScRange aSingleRange;
+ ScRowRangeHashMap aJoinedRanges; // "active" ranges to be merged
+ std::vector<ScRange> aCompletedRanges; // ranges that will no longer be touched
+ ScRangeListRef aReturnRanges; // result as ScRangeList for further use
+
+public:
+ ScUniqueFormatsEntry() : eState( STATE_EMPTY ) {}
+
+ void Join( const ScRange& rNewRange );
+ const ScRangeList& GetRanges();
+ void Clear() { aReturnRanges.clear(); } // aJoinedRanges and aCompletedRanges are cleared in GetRanges
+};
+
+}
+
+void ScUniqueFormatsEntry::Join( const ScRange& rNewRange )
+{
+ // Special-case handling for single range
+
+ if ( eState == STATE_EMPTY )
+ {
+ aSingleRange = rNewRange;
+ eState = STATE_SINGLE;
+ return;
+ }
+ if ( eState == STATE_SINGLE )
+ {
+ if ( aSingleRange.aStart.Row() == rNewRange.aStart.Row() &&
+ aSingleRange.aEnd.Row() == rNewRange.aEnd.Row() &&
+ aSingleRange.aEnd.Col() + 1 == rNewRange.aStart.Col() )
+ {
+ aSingleRange.aEnd.SetCol( rNewRange.aEnd.Col() );
+ return; // still a single range
+ }
+
+ SCROW nSingleRow = aSingleRange.aStart.Row();
+ aJoinedRanges.emplace( nSingleRow, aSingleRange );
+ eState = STATE_COMPLEX;
+ // continue normally
+ }
+
+ // This is called in the order of ScAttrRectIterator results.
+ // rNewRange can only be joined with an existing entry if it's the same rows, starting in the next column.
+ // If the old entry for the start row extends to a different end row, or ends in a different column, it
+ // can be moved to aCompletedRanges because it can't be joined with following iterator results.
+ // Everything happens within one sheet, so Tab can be ignored.
+
+ SCROW nStartRow = rNewRange.aStart.Row();
+ ScRowRangeHashMap::iterator aIter( aJoinedRanges.find( nStartRow ) ); // find the active entry for the start row
+ if ( aIter != aJoinedRanges.end() )
+ {
+ ScRange& rOldRange = aIter->second;
+ if ( rOldRange.aEnd.Row() == rNewRange.aEnd.Row() &&
+ rOldRange.aEnd.Col() + 1 == rNewRange.aStart.Col() )
+ {
+ // extend existing range
+ rOldRange.aEnd.SetCol( rNewRange.aEnd.Col() );
+ }
+ else
+ {
+ // move old range to aCompletedRanges, keep rNewRange for joining
+ aCompletedRanges.push_back( rOldRange );
+ rOldRange = rNewRange; // replace in hash map
+ }
+ }
+ else
+ {
+ // keep rNewRange for joining
+ aJoinedRanges.emplace( nStartRow, rNewRange );
+ }
+}
+
+const ScRangeList& ScUniqueFormatsEntry::GetRanges()
+{
+ if ( eState == STATE_SINGLE )
+ {
+ aReturnRanges = new ScRangeList( aSingleRange );
+ return *aReturnRanges;
+ }
+
+ // move remaining entries from aJoinedRanges to aCompletedRanges
+
+ for ( const auto& rEntry : aJoinedRanges )
+ aCompletedRanges.push_back( rEntry.second );
+ aJoinedRanges.clear();
+
+ // sort all ranges for a predictable API result
+
+ std::sort( aCompletedRanges.begin(), aCompletedRanges.end() );
+
+ // fill and return ScRangeList
+
+ aReturnRanges = new ScRangeList;
+ aReturnRanges->insert( aReturnRanges->end(), aCompletedRanges.begin(), aCompletedRanges.end() );
+ aCompletedRanges.clear();
+
+ return *aReturnRanges;
+}
+
+namespace {
+
+// function object to sort the range lists by start of first range
+struct ScUniqueFormatsOrder
+{
+ bool operator()( const ScRangeList& rList1, const ScRangeList& rList2 ) const
+ {
+ // all range lists have at least one entry
+ OSL_ENSURE( !rList1.empty() && !rList2.empty(), "ScUniqueFormatsOrder: empty list" );
+
+ // compare start positions using ScAddress comparison operator
+ return ( rList1[ 0 ].aStart < rList2[ 0 ].aStart );
+ }
+};
+
+}
+
+ScUniqueCellFormatsObj::ScUniqueCellFormatsObj(ScDocShell* pDocSh, const ScRange& rTotalRange) :
+ pDocShell( pDocSh )
+{
+ pDocShell->GetDocument().AddUnoObject(*this);
+
+ OSL_ENSURE( rTotalRange.aStart.Tab() == rTotalRange.aEnd.Tab(), "different tables" );
+
+ ScDocument& rDoc = pDocShell->GetDocument();
+ SCTAB nTab = rTotalRange.aStart.Tab();
+ ScAttrRectIterator aIter( rDoc, nTab,
+ rTotalRange.aStart.Col(), rTotalRange.aStart.Row(),
+ rTotalRange.aEnd.Col(), rTotalRange.aEnd.Row() );
+ SCCOL nCol1, nCol2;
+ SCROW nRow1, nRow2;
+
+ // Collect the ranges for each format in a hash map, to avoid nested loops
+
+ std::unordered_map< const ScPatternAttr*, ScUniqueFormatsEntry, ScPatternHashCode > aHashMap;
+ while (aIter.GetNext( nCol1, nCol2, nRow1, nRow2 ) )
+ {
+ ScRange aRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab );
+ const ScPatternAttr* pPattern = rDoc.GetPattern(nCol1, nRow1, nTab);
+ aHashMap[pPattern].Join( aRange );
+ }
+
+ // Fill the vector aRangeLists with the range lists from the hash map
+
+ aRangeLists.reserve( aHashMap.size() );
+ for ( auto& rMapEntry : aHashMap )
+ {
+ ScUniqueFormatsEntry& rEntry = rMapEntry.second;
+ const ScRangeList& rRanges = rEntry.GetRanges();
+ aRangeLists.push_back( rRanges ); // copy ScRangeList
+ rEntry.Clear(); // free memory, don't hold both copies of all ranges
+ }
+
+ // Sort the vector by first range's start position, to avoid random shuffling
+ // due to using the ScPatterAttr pointers
+
+ ::std::sort( aRangeLists.begin(), aRangeLists.end(), ScUniqueFormatsOrder() );
+}
+
+
+// XIndexAccess
+
+sal_Int32 SAL_CALL ScUniqueCellFormatsObj::getCount()
+{
+ SolarMutexGuard aGuard;
+
+ return aRangeLists.size();
+}
+
+uno::Any SAL_CALL ScUniqueCellFormatsObj::getByIndex( sal_Int32 nIndex )
+{
+ SolarMutexGuard aGuard;
+
+ if(o3tl::make_unsigned(nIndex) >= aRangeLists.size())
+ throw lang::IndexOutOfBoundsException();
+
+ return uno::Any(uno::Reference<sheet::XSheetCellRangeContainer>(new ScCellRangesObj(pDocShell, aRangeLists[nIndex])));
+
+}
+
+uno::Type SAL_CALL ScUniqueCellFormatsObj::getElementType()
+{
+ return cppu::UnoType<sheet::XSheetCellRangeContainer>::get();
+}
+
+sal_Bool SAL_CALL ScUniqueCellFormatsObj::hasElements()
+{
+ SolarMutexGuard aGuard;
+ return ( !aRangeLists.empty() );
+}
+
+// XEnumerationAccess
+
+uno::Reference<container::XEnumeration> SAL_CALL ScUniqueCellFormatsObj::createEnumeration()
+{
+ SolarMutexGuard aGuard;
+ if (pDocShell)
+ return new ScUniqueCellFormatsEnumeration( pDocShell, std::vector(aRangeLists) );
+ return nullptr;
+}
+
+ScUniqueCellFormatsEnumeration::ScUniqueCellFormatsEnumeration(ScDocShell* pDocSh, std::vector<ScRangeList>&& rRangeLists) :
+ aRangeLists(std::move(rRangeLists)),
+ pDocShell( pDocSh ),
+ nCurrentPosition(0)
+{
+ pDocShell->GetDocument().AddUnoObject(*this);
+}
+
+ScUniqueCellFormatsEnumeration::~ScUniqueCellFormatsEnumeration()
+{
+ SolarMutexGuard g;
+
+ if (pDocShell)
+ pDocShell->GetDocument().RemoveUnoObject(*this);
+}
+
+void ScUniqueCellFormatsEnumeration::Notify( SfxBroadcaster&, const SfxHint& rHint )
+{
+ if ( dynamic_cast<const ScUpdateRefHint*>(&rHint) )
+ {
+ //! and now ???
+ }
+ else
+ {
+ if ( rHint.GetId() == SfxHintId::Dying )
+ pDocShell = nullptr;
+ }
+}
+
+// XEnumeration
+
+sal_Bool SAL_CALL ScUniqueCellFormatsEnumeration::hasMoreElements()
+{
+ SolarMutexGuard aGuard;
+ return o3tl::make_unsigned(nCurrentPosition) < aRangeLists.size();
+}
+
+uno::Any SAL_CALL ScUniqueCellFormatsEnumeration::nextElement()
+{
+ SolarMutexGuard aGuard;
+
+ if ( !hasMoreElements() || !pDocShell )
+ throw container::NoSuchElementException(); // no more elements
+
+ // interface type must match ScCellFormatsObj::getElementType
+
+ return uno::Any(uno::Reference<sheet::XSheetCellRangeContainer>(new ScCellRangesObj(pDocShell, aRangeLists[nCurrentPosition++])));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */