/* -*- 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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::get(), 0 | beans::PropertyAttribute::READONLY, 0 }, { SC_UNONAME_ASIANVERT,ATTR_VERTICAL_ASIAN,cppu::UnoType::get(), 0, 0 }, CELL_BORDER_PROPERTIES CELL_BACKGROUND_COLOR_PROPERTIES { SC_UNONAME_CELLPRO, ATTR_PROTECTION, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLSTYL, SC_WID_UNO_CELLSTYL,cppu::UnoType::get(), 0, 0 }, CHAR_COLOR_PROPERTIES { SC_UNONAME_COUTL, ATTR_FONT_CONTOUR, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CCROSS, ATTR_FONT_CROSSEDOUT,cppu::UnoType::get(), 0, MID_CROSSED_OUT }, { SC_UNONAME_CEMPHAS, ATTR_FONT_EMPHASISMARK,cppu::UnoType::get(), 0, MID_EMPHASIS }, { SC_UNONAME_CFONT, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY }, { SC_UNONAME_CFCHARS, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_CHAR_SET }, { SC_UNO_CJK_CFCHARS, ATTR_CJK_FONT, cppu::UnoType::get(), 0, MID_FONT_CHAR_SET }, { SC_UNO_CTL_CFCHARS, ATTR_CTL_FONT, cppu::UnoType::get(), 0, MID_FONT_CHAR_SET }, { SC_UNONAME_CFFAMIL, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY }, { SC_UNO_CJK_CFFAMIL, ATTR_CJK_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY }, { SC_UNO_CTL_CFFAMIL, ATTR_CTL_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY }, { SC_UNONAME_CFNAME, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY_NAME }, { SC_UNO_CJK_CFNAME, ATTR_CJK_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY_NAME }, { SC_UNO_CTL_CFNAME, ATTR_CTL_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY_NAME }, { SC_UNONAME_CFPITCH, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_PITCH }, { SC_UNO_CJK_CFPITCH, ATTR_CJK_FONT, cppu::UnoType::get(), 0, MID_FONT_PITCH }, { SC_UNO_CTL_CFPITCH, ATTR_CTL_FONT, cppu::UnoType::get(), 0, MID_FONT_PITCH }, { SC_UNONAME_CFSTYLE, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_STYLE_NAME }, { SC_UNO_CJK_CFSTYLE, ATTR_CJK_FONT, cppu::UnoType::get(), 0, MID_FONT_STYLE_NAME }, { SC_UNO_CTL_CFSTYLE, ATTR_CTL_FONT, cppu::UnoType::get(), 0, MID_FONT_STYLE_NAME }, { SC_UNONAME_CHEIGHT, ATTR_FONT_HEIGHT, cppu::UnoType::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, { SC_UNO_CJK_CHEIGHT, ATTR_CJK_FONT_HEIGHT,cppu::UnoType::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, { SC_UNO_CTL_CHEIGHT, ATTR_CTL_FONT_HEIGHT,cppu::UnoType::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, { SC_UNONAME_CLOCAL, ATTR_FONT_LANGUAGE, cppu::UnoType::get(), 0, MID_LANG_LOCALE }, { SC_UNO_CJK_CLOCAL, ATTR_CJK_FONT_LANGUAGE,cppu::UnoType::get(), 0, MID_LANG_LOCALE }, { SC_UNO_CTL_CLOCAL, ATTR_CTL_FONT_LANGUAGE,cppu::UnoType::get(), 0, MID_LANG_LOCALE }, { SC_UNONAME_COVER, ATTR_FONT_OVERLINE, cppu::UnoType::get(), 0, MID_TL_STYLE }, { SC_UNONAME_COVRLCOL, ATTR_FONT_OVERLINE, cppu::UnoType::get(), 0, MID_TL_COLOR }, { SC_UNONAME_COVRLHAS, ATTR_FONT_OVERLINE, cppu::UnoType::get(), 0, MID_TL_HASCOLOR }, { SC_UNONAME_CPOST, ATTR_FONT_POSTURE, cppu::UnoType::get(), 0, MID_POSTURE }, { SC_UNO_CJK_CPOST, ATTR_CJK_FONT_POSTURE,cppu::UnoType::get(), 0, MID_POSTURE }, { SC_UNO_CTL_CPOST, ATTR_CTL_FONT_POSTURE,cppu::UnoType::get(), 0, MID_POSTURE }, { SC_UNONAME_CRELIEF, ATTR_FONT_RELIEF, cppu::UnoType::get(), 0, MID_RELIEF }, { SC_UNONAME_CSHADD, ATTR_FONT_SHADOWED, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CSTRIKE, ATTR_FONT_CROSSEDOUT,cppu::UnoType::get(), 0, MID_CROSS_OUT }, { SC_UNONAME_CUNDER, ATTR_FONT_UNDERLINE,cppu::UnoType::get(), 0, MID_TL_STYLE }, { SC_UNONAME_CUNDLCOL, ATTR_FONT_UNDERLINE,cppu::UnoType::get(), 0, MID_TL_COLOR }, { SC_UNONAME_CUNDLHAS, ATTR_FONT_UNDERLINE,cppu::UnoType::get(), 0, MID_TL_HASCOLOR }, { SC_UNONAME_CWEIGHT, ATTR_FONT_WEIGHT, cppu::UnoType::get(), 0, MID_WEIGHT }, { SC_UNO_CJK_CWEIGHT, ATTR_CJK_FONT_WEIGHT,cppu::UnoType::get(), 0, MID_WEIGHT }, { SC_UNO_CTL_CWEIGHT, ATTR_CTL_FONT_WEIGHT,cppu::UnoType::get(), 0, MID_WEIGHT }, { SC_UNONAME_CWORDMOD, ATTR_FONT_WORDLINE, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CHCOLHDR, SC_WID_UNO_CHCOLHDR,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CHROWHDR, SC_WID_UNO_CHROWHDR,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CONDFMT, SC_WID_UNO_CONDFMT, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CONDLOC, SC_WID_UNO_CONDLOC, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CONDXML, SC_WID_UNO_CONDXML, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_DIAGONAL_BLTR, ATTR_BORDER_BLTR, ::cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_DIAGONAL_BLTR2, ATTR_BORDER_BLTR, ::cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_DIAGONAL_TLBR, ATTR_BORDER_TLBR, ::cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_DIAGONAL_TLBR2, ATTR_BORDER_TLBR, ::cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_CELLHJUS, ATTR_HOR_JUSTIFY, cppu::UnoType::get(), 0, MID_HORJUST_HORJUST }, { SC_UNONAME_CELLHJUS_METHOD, ATTR_HOR_JUSTIFY_METHOD, ::cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLTRAN, ATTR_BACKGROUND, cppu::UnoType::get(), 0, MID_GRAPHIC_TRANSPARENT }, { SC_UNONAME_WRAP, ATTR_LINEBREAK, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_NUMFMT, ATTR_VALUE_FORMAT, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_NUMRULES, SC_WID_UNO_NUMRULES,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLORI, ATTR_STACKED, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_PADJUST, ATTR_HOR_JUSTIFY, ::cppu::UnoType::get(), 0, MID_HORJUST_ADJUST }, { SC_UNONAME_PBMARGIN, ATTR_MARGIN, cppu::UnoType::get(), 0, MID_MARGIN_LO_MARGIN | CONVERT_TWIPS }, { SC_UNONAME_PINDENT, ATTR_INDENT, cppu::UnoType::get(), 0, 0 }, //! CONVERT_TWIPS { SC_UNONAME_PISCHDIST,ATTR_SCRIPTSPACE, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_PISFORBID,ATTR_FORBIDDEN_RULES,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_PISHANG, ATTR_HANGPUNCTUATION,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_PISHYPHEN,ATTR_HYPHENATE, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_PLASTADJ, ATTR_HOR_JUSTIFY, ::cppu::UnoType::get(), 0, MID_HORJUST_ADJUST }, { SC_UNONAME_PLMARGIN, ATTR_MARGIN, cppu::UnoType::get(), 0, MID_MARGIN_L_MARGIN | CONVERT_TWIPS }, { SC_UNONAME_PRMARGIN, ATTR_MARGIN, cppu::UnoType::get(), 0, MID_MARGIN_R_MARGIN | CONVERT_TWIPS }, { SC_UNONAME_PTMARGIN, ATTR_MARGIN, cppu::UnoType::get(), 0, MID_MARGIN_UP_MARGIN | CONVERT_TWIPS }, { SC_UNONAME_ROTANG, ATTR_ROTATE_VALUE, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_ROTREF, ATTR_ROTATE_MODE, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_SHADOW, ATTR_SHADOW, cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_SHRINK_TO_FIT, ATTR_SHRINKTOFIT, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_TBLBORD, SC_WID_UNO_TBLBORD, cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_TBLBORD2, SC_WID_UNO_TBLBORD2, cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_USERDEF, ATTR_USERDEF, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_VALIDAT, SC_WID_UNO_VALIDAT, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_VALILOC, SC_WID_UNO_VALILOC, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_VALIXML, SC_WID_UNO_VALIXML, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLVJUS, ATTR_VER_JUSTIFY, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLVJUS_METHOD, ATTR_VER_JUSTIFY_METHOD, ::cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_WRITING, ATTR_WRITINGDIR, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_HYPERLINK, ATTR_HYPERLINK, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_FORMATID, SC_WID_UNO_FORMATID, cppu::UnoType::get(), 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::get(), 0 | beans::PropertyAttribute::READONLY, 0 }, { SC_UNONAME_ASIANVERT,ATTR_VERTICAL_ASIAN,cppu::UnoType::get(), 0, 0 }, CELL_BORDER_PROPERTIES CELL_BACKGROUND_COLOR_PROPERTIES { SC_UNONAME_CELLPRO, ATTR_PROTECTION, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLSTYL, SC_WID_UNO_CELLSTYL,cppu::UnoType::get(), 0, 0 }, CHAR_COLOR_PROPERTIES { SC_UNONAME_COUTL, ATTR_FONT_CONTOUR, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CCROSS, ATTR_FONT_CROSSEDOUT,cppu::UnoType::get(), 0, MID_CROSSED_OUT }, { SC_UNONAME_CEMPHAS, ATTR_FONT_EMPHASISMARK,cppu::UnoType::get(), 0, MID_EMPHASIS }, { SC_UNONAME_CFONT, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY }, { SC_UNONAME_CFCHARS, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_CHAR_SET }, { SC_UNO_CJK_CFCHARS, ATTR_CJK_FONT, cppu::UnoType::get(), 0, MID_FONT_CHAR_SET }, { SC_UNO_CTL_CFCHARS, ATTR_CTL_FONT, cppu::UnoType::get(), 0, MID_FONT_CHAR_SET }, { SC_UNONAME_CFFAMIL, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY }, { SC_UNO_CJK_CFFAMIL, ATTR_CJK_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY }, { SC_UNO_CTL_CFFAMIL, ATTR_CTL_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY }, { SC_UNONAME_CFNAME, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY_NAME }, { SC_UNO_CJK_CFNAME, ATTR_CJK_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY_NAME }, { SC_UNO_CTL_CFNAME, ATTR_CTL_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY_NAME }, { SC_UNONAME_CFPITCH, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_PITCH }, { SC_UNO_CJK_CFPITCH, ATTR_CJK_FONT, cppu::UnoType::get(), 0, MID_FONT_PITCH }, { SC_UNO_CTL_CFPITCH, ATTR_CTL_FONT, cppu::UnoType::get(), 0, MID_FONT_PITCH }, { SC_UNONAME_CFSTYLE, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_STYLE_NAME }, { SC_UNO_CJK_CFSTYLE, ATTR_CJK_FONT, cppu::UnoType::get(), 0, MID_FONT_STYLE_NAME }, { SC_UNO_CTL_CFSTYLE, ATTR_CTL_FONT, cppu::UnoType::get(), 0, MID_FONT_STYLE_NAME }, { SC_UNONAME_CHEIGHT, ATTR_FONT_HEIGHT, cppu::UnoType::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, { SC_UNO_CJK_CHEIGHT, ATTR_CJK_FONT_HEIGHT,cppu::UnoType::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, { SC_UNO_CTL_CHEIGHT, ATTR_CTL_FONT_HEIGHT,cppu::UnoType::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, { SC_UNONAME_CLOCAL, ATTR_FONT_LANGUAGE, cppu::UnoType::get(), 0, MID_LANG_LOCALE }, { SC_UNO_CJK_CLOCAL, ATTR_CJK_FONT_LANGUAGE,cppu::UnoType::get(), 0, MID_LANG_LOCALE }, { SC_UNO_CTL_CLOCAL, ATTR_CTL_FONT_LANGUAGE,cppu::UnoType::get(), 0, MID_LANG_LOCALE }, { SC_UNONAME_COVER, ATTR_FONT_OVERLINE, cppu::UnoType::get(), 0, MID_TL_STYLE }, { SC_UNONAME_COVRLCOL, ATTR_FONT_OVERLINE, cppu::UnoType::get(), 0, MID_TL_COLOR }, { SC_UNONAME_COVRLHAS, ATTR_FONT_OVERLINE, cppu::UnoType::get(), 0, MID_TL_HASCOLOR }, { SC_UNONAME_CPOST, ATTR_FONT_POSTURE, cppu::UnoType::get(), 0, MID_POSTURE }, { SC_UNO_CJK_CPOST, ATTR_CJK_FONT_POSTURE,cppu::UnoType::get(), 0, MID_POSTURE }, { SC_UNO_CTL_CPOST, ATTR_CTL_FONT_POSTURE,cppu::UnoType::get(), 0, MID_POSTURE }, { SC_UNONAME_CRELIEF, ATTR_FONT_RELIEF, cppu::UnoType::get(), 0, MID_RELIEF }, { SC_UNONAME_CSHADD, ATTR_FONT_SHADOWED, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CSTRIKE, ATTR_FONT_CROSSEDOUT,cppu::UnoType::get(), 0, MID_CROSS_OUT }, { SC_UNONAME_CUNDER, ATTR_FONT_UNDERLINE,cppu::UnoType::get(), 0, MID_TL_STYLE }, { SC_UNONAME_CUNDLCOL, ATTR_FONT_UNDERLINE,cppu::UnoType::get(), 0, MID_TL_COLOR }, { SC_UNONAME_CUNDLHAS, ATTR_FONT_UNDERLINE,cppu::UnoType::get(), 0, MID_TL_HASCOLOR }, { SC_UNONAME_CWEIGHT, ATTR_FONT_WEIGHT, cppu::UnoType::get(), 0, MID_WEIGHT }, { SC_UNO_CJK_CWEIGHT, ATTR_CJK_FONT_WEIGHT,cppu::UnoType::get(), 0, MID_WEIGHT }, { SC_UNO_CTL_CWEIGHT, ATTR_CTL_FONT_WEIGHT,cppu::UnoType::get(), 0, MID_WEIGHT }, { SC_UNONAME_CWORDMOD, ATTR_FONT_WORDLINE, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CHCOLHDR, SC_WID_UNO_CHCOLHDR,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CHROWHDR, SC_WID_UNO_CHROWHDR,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CONDFMT, SC_WID_UNO_CONDFMT, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CONDLOC, SC_WID_UNO_CONDLOC, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CONDXML, SC_WID_UNO_CONDXML, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_DIAGONAL_BLTR, ATTR_BORDER_BLTR, ::cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_DIAGONAL_BLTR2, ATTR_BORDER_BLTR, ::cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_DIAGONAL_TLBR, ATTR_BORDER_TLBR, ::cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_DIAGONAL_TLBR2, ATTR_BORDER_TLBR, ::cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_CELLHJUS, ATTR_HOR_JUSTIFY, cppu::UnoType::get(), 0, MID_HORJUST_HORJUST }, { SC_UNONAME_CELLHJUS_METHOD, ATTR_HOR_JUSTIFY_METHOD, ::cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLTRAN, ATTR_BACKGROUND, cppu::UnoType::get(), 0, MID_GRAPHIC_TRANSPARENT }, { SC_UNONAME_WRAP, ATTR_LINEBREAK, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_NUMFMT, ATTR_VALUE_FORMAT, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_NUMRULES, SC_WID_UNO_NUMRULES,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLORI, ATTR_STACKED, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_PADJUST, ATTR_HOR_JUSTIFY, ::cppu::UnoType::get(), 0, MID_HORJUST_ADJUST }, { SC_UNONAME_PBMARGIN, ATTR_MARGIN, cppu::UnoType::get(), 0, MID_MARGIN_LO_MARGIN | CONVERT_TWIPS }, { SC_UNONAME_PINDENT, ATTR_INDENT, cppu::UnoType::get(), 0, 0 }, //! CONVERT_TWIPS { SC_UNONAME_PISCHDIST,ATTR_SCRIPTSPACE, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_PISFORBID,ATTR_FORBIDDEN_RULES,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_PISHANG, ATTR_HANGPUNCTUATION,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_PISHYPHEN,ATTR_HYPHENATE, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_PLASTADJ, ATTR_HOR_JUSTIFY, ::cppu::UnoType::get(), 0, MID_HORJUST_ADJUST }, { SC_UNONAME_PLMARGIN, ATTR_MARGIN, cppu::UnoType::get(), 0, MID_MARGIN_L_MARGIN | CONVERT_TWIPS }, { SC_UNONAME_PRMARGIN, ATTR_MARGIN, cppu::UnoType::get(), 0, MID_MARGIN_R_MARGIN | CONVERT_TWIPS }, { SC_UNONAME_PTMARGIN, ATTR_MARGIN, cppu::UnoType::get(), 0, MID_MARGIN_UP_MARGIN | CONVERT_TWIPS }, { SC_UNONAME_POS, SC_WID_UNO_POS, cppu::UnoType::get(), 0 | beans::PropertyAttribute::READONLY, 0 }, { SC_UNONAME_ROTANG, ATTR_ROTATE_VALUE, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_ROTREF, ATTR_ROTATE_MODE, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_SHADOW, ATTR_SHADOW, cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_SHRINK_TO_FIT, ATTR_SHRINKTOFIT, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_SIZE, SC_WID_UNO_SIZE, cppu::UnoType::get(), 0 | beans::PropertyAttribute::READONLY, 0 }, { SC_UNONAME_TBLBORD, SC_WID_UNO_TBLBORD, cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_TBLBORD2, SC_WID_UNO_TBLBORD2, cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_USERDEF, ATTR_USERDEF, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_VALIDAT, SC_WID_UNO_VALIDAT, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_VALILOC, SC_WID_UNO_VALILOC, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_VALIXML, SC_WID_UNO_VALIXML, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLVJUS, ATTR_VER_JUSTIFY, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLVJUS_METHOD, ATTR_VER_JUSTIFY_METHOD, ::cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_WRITING, ATTR_WRITINGDIR, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_FORMATID, SC_WID_UNO_FORMATID, cppu::UnoType::get(), 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::get(), 0 | beans::PropertyAttribute::READONLY, 0 }, { SC_UNONAME_ASIANVERT,ATTR_VERTICAL_ASIAN,cppu::UnoType::get(), 0, 0 }, CELL_BORDER_PROPERTIES CELL_BACKGROUND_COLOR_PROPERTIES { SC_UNONAME_CELLPRO, ATTR_PROTECTION, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLSTYL, SC_WID_UNO_CELLSTYL,cppu::UnoType::get(), 0, 0 }, CHAR_COLOR_PROPERTIES { SC_UNONAME_COUTL, ATTR_FONT_CONTOUR, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CCROSS, ATTR_FONT_CROSSEDOUT,cppu::UnoType::get(), 0, MID_CROSSED_OUT }, { SC_UNONAME_CEMPHAS, ATTR_FONT_EMPHASISMARK,cppu::UnoType::get(), 0, MID_EMPHASIS }, { SC_UNONAME_CFONT, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY }, { SC_UNONAME_CFCHARS, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_CHAR_SET }, { SC_UNO_CJK_CFCHARS, ATTR_CJK_FONT, cppu::UnoType::get(), 0, MID_FONT_CHAR_SET }, { SC_UNO_CTL_CFCHARS, ATTR_CTL_FONT, cppu::UnoType::get(), 0, MID_FONT_CHAR_SET }, { SC_UNONAME_CFFAMIL, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY }, { SC_UNO_CJK_CFFAMIL, ATTR_CJK_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY }, { SC_UNO_CTL_CFFAMIL, ATTR_CTL_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY }, { SC_UNONAME_CFNAME, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY_NAME }, { SC_UNO_CJK_CFNAME, ATTR_CJK_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY_NAME }, { SC_UNO_CTL_CFNAME, ATTR_CTL_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY_NAME }, { SC_UNONAME_CFPITCH, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_PITCH }, { SC_UNO_CJK_CFPITCH, ATTR_CJK_FONT, cppu::UnoType::get(), 0, MID_FONT_PITCH }, { SC_UNO_CTL_CFPITCH, ATTR_CTL_FONT, cppu::UnoType::get(), 0, MID_FONT_PITCH }, { SC_UNONAME_CFSTYLE, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_STYLE_NAME }, { SC_UNO_CJK_CFSTYLE, ATTR_CJK_FONT, cppu::UnoType::get(), 0, MID_FONT_STYLE_NAME }, { SC_UNO_CTL_CFSTYLE, ATTR_CTL_FONT, cppu::UnoType::get(), 0, MID_FONT_STYLE_NAME }, { SC_UNONAME_CHEIGHT, ATTR_FONT_HEIGHT, cppu::UnoType::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, { SC_UNO_CJK_CHEIGHT, ATTR_CJK_FONT_HEIGHT,cppu::UnoType::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, { SC_UNO_CTL_CHEIGHT, ATTR_CTL_FONT_HEIGHT,cppu::UnoType::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, { SC_UNONAME_CLOCAL, ATTR_FONT_LANGUAGE, cppu::UnoType::get(), 0, MID_LANG_LOCALE }, { SC_UNO_CJK_CLOCAL, ATTR_CJK_FONT_LANGUAGE,cppu::UnoType::get(), 0, MID_LANG_LOCALE }, { SC_UNO_CTL_CLOCAL, ATTR_CTL_FONT_LANGUAGE,cppu::UnoType::get(), 0, MID_LANG_LOCALE }, { SC_UNONAME_COVER, ATTR_FONT_OVERLINE, cppu::UnoType::get(), 0, MID_TL_STYLE }, { SC_UNONAME_COVRLCOL, ATTR_FONT_OVERLINE, cppu::UnoType::get(), 0, MID_TL_COLOR }, { SC_UNONAME_COVRLHAS, ATTR_FONT_OVERLINE, cppu::UnoType::get(), 0, MID_TL_HASCOLOR }, { SC_UNONAME_CPOST, ATTR_FONT_POSTURE, cppu::UnoType::get(), 0, MID_POSTURE }, { SC_UNO_CJK_CPOST, ATTR_CJK_FONT_POSTURE,cppu::UnoType::get(), 0, MID_POSTURE }, { SC_UNO_CTL_CPOST, ATTR_CTL_FONT_POSTURE,cppu::UnoType::get(), 0, MID_POSTURE }, { SC_UNONAME_CRELIEF, ATTR_FONT_RELIEF, cppu::UnoType::get(), 0, MID_RELIEF }, { SC_UNONAME_CSHADD, ATTR_FONT_SHADOWED, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CSTRIKE, ATTR_FONT_CROSSEDOUT,cppu::UnoType::get(), 0, MID_CROSS_OUT }, { SC_UNONAME_CUNDER, ATTR_FONT_UNDERLINE,cppu::UnoType::get(), 0, MID_TL_STYLE }, { SC_UNONAME_CUNDLCOL, ATTR_FONT_UNDERLINE,cppu::UnoType::get(), 0, MID_TL_COLOR }, { SC_UNONAME_CUNDLHAS, ATTR_FONT_UNDERLINE,cppu::UnoType::get(), 0, MID_TL_HASCOLOR }, { SC_UNONAME_CWEIGHT, ATTR_FONT_WEIGHT, cppu::UnoType::get(), 0, MID_WEIGHT }, { SC_UNO_CJK_CWEIGHT, ATTR_CJK_FONT_WEIGHT,cppu::UnoType::get(), 0, MID_WEIGHT }, { SC_UNO_CTL_CWEIGHT, ATTR_CTL_FONT_WEIGHT,cppu::UnoType::get(), 0, MID_WEIGHT }, { SC_UNONAME_CWORDMOD, ATTR_FONT_WORDLINE, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CHCOLHDR, SC_WID_UNO_CHCOLHDR,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CHROWHDR, SC_WID_UNO_CHROWHDR,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CONDFMT, SC_WID_UNO_CONDFMT, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CONDLOC, SC_WID_UNO_CONDLOC, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CONDXML, SC_WID_UNO_CONDXML, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_DIAGONAL_BLTR, ATTR_BORDER_BLTR, ::cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_DIAGONAL_BLTR2, ATTR_BORDER_BLTR, ::cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_DIAGONAL_TLBR, ATTR_BORDER_TLBR, ::cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_DIAGONAL_TLBR2, ATTR_BORDER_TLBR, ::cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_FORMLOC, SC_WID_UNO_FORMLOC, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_FORMRT, SC_WID_UNO_FORMRT, cppu::UnoType::get(), 0 | beans::PropertyAttribute::READONLY, 0 }, { SC_UNONAME_CELLCONTENTTYPE, SC_WID_UNO_CELLCONTENTTYPE, cppu::UnoType::get(), 0 | beans::PropertyAttribute::READONLY, 0 }, { SC_UNONAME_FORMRT2, SC_WID_UNO_FORMRT2, cppu::UnoType::get(), 0 | beans::PropertyAttribute::READONLY, 0 }, { SC_UNONAME_CELLHJUS, ATTR_HOR_JUSTIFY, cppu::UnoType::get(), 0, MID_HORJUST_HORJUST }, { SC_UNONAME_CELLHJUS_METHOD, ATTR_HOR_JUSTIFY_METHOD, ::cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLTRAN, ATTR_BACKGROUND, cppu::UnoType::get(), 0, MID_GRAPHIC_TRANSPARENT }, { SC_UNONAME_WRAP, ATTR_LINEBREAK, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_NUMFMT, ATTR_VALUE_FORMAT, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_NUMRULES, SC_WID_UNO_NUMRULES,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLORI, ATTR_STACKED, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_PADJUST, ATTR_HOR_JUSTIFY, ::cppu::UnoType::get(), 0, MID_HORJUST_ADJUST }, { SC_UNONAME_PBMARGIN, ATTR_MARGIN, cppu::UnoType::get(), 0, MID_MARGIN_LO_MARGIN | CONVERT_TWIPS }, { SC_UNONAME_PINDENT, ATTR_INDENT, cppu::UnoType::get(), 0, 0 }, //! CONVERT_TWIPS { SC_UNONAME_PISCHDIST,ATTR_SCRIPTSPACE, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_PISFORBID,ATTR_FORBIDDEN_RULES,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_PISHANG, ATTR_HANGPUNCTUATION,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_PISHYPHEN,ATTR_HYPHENATE, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_PLASTADJ, ATTR_HOR_JUSTIFY, ::cppu::UnoType::get(), 0, MID_HORJUST_ADJUST }, { SC_UNONAME_PLMARGIN, ATTR_MARGIN, cppu::UnoType::get(), 0, MID_MARGIN_L_MARGIN | CONVERT_TWIPS }, { SC_UNONAME_PRMARGIN, ATTR_MARGIN, cppu::UnoType::get(), 0, MID_MARGIN_R_MARGIN | CONVERT_TWIPS }, { SC_UNONAME_PTMARGIN, ATTR_MARGIN, cppu::UnoType::get(), 0, MID_MARGIN_UP_MARGIN | CONVERT_TWIPS }, { SC_UNONAME_POS, SC_WID_UNO_POS, cppu::UnoType::get(), 0 | beans::PropertyAttribute::READONLY, 0 }, { SC_UNONAME_ROTANG, ATTR_ROTATE_VALUE, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_ROTREF, ATTR_ROTATE_MODE, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_SHADOW, ATTR_SHADOW, cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_SHRINK_TO_FIT, ATTR_SHRINKTOFIT, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_SIZE, SC_WID_UNO_SIZE, cppu::UnoType::get(), 0 | beans::PropertyAttribute::READONLY, 0 }, { SC_UNONAME_TBLBORD, SC_WID_UNO_TBLBORD, cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_TBLBORD2, SC_WID_UNO_TBLBORD2, cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_USERDEF, ATTR_USERDEF, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_VALIDAT, SC_WID_UNO_VALIDAT, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_VALILOC, SC_WID_UNO_VALILOC, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_VALIXML, SC_WID_UNO_VALIXML, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLVJUS, ATTR_VER_JUSTIFY, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLVJUS_METHOD, ATTR_VER_JUSTIFY_METHOD, ::cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_WRITING, ATTR_WRITINGDIR, cppu::UnoType::get(), 0, 0 }, { UNO_NAME_EDIT_CHAR_ESCAPEMENT, EE_CHAR_ESCAPEMENT, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_HYPERLINK, ATTR_HYPERLINK, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_FORMATID, SC_WID_UNO_FORMATID, cppu::UnoType::get(), 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::get(), 0 | beans::PropertyAttribute::READONLY, 0 }, { SC_UNONAME_ASIANVERT,ATTR_VERTICAL_ASIAN,cppu::UnoType::get(), 0, 0 }, CELL_BORDER_PROPERTIES CELL_BACKGROUND_COLOR_PROPERTIES { SC_UNONAME_CELLPRO, ATTR_PROTECTION, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLSTYL, SC_WID_UNO_CELLSTYL,cppu::UnoType::get(), 0, 0 }, CHAR_COLOR_PROPERTIES { SC_UNONAME_COUTL, ATTR_FONT_CONTOUR, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CCROSS, ATTR_FONT_CROSSEDOUT,cppu::UnoType::get(), 0, MID_CROSSED_OUT }, { SC_UNONAME_CEMPHAS, ATTR_FONT_EMPHASISMARK,cppu::UnoType::get(), 0, MID_EMPHASIS }, { SC_UNONAME_CFONT, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY }, { SC_UNONAME_CFCHARS, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_CHAR_SET }, { SC_UNO_CJK_CFCHARS, ATTR_CJK_FONT, cppu::UnoType::get(), 0, MID_FONT_CHAR_SET }, { SC_UNO_CTL_CFCHARS, ATTR_CTL_FONT, cppu::UnoType::get(), 0, MID_FONT_CHAR_SET }, { SC_UNONAME_CFFAMIL, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY }, { SC_UNO_CJK_CFFAMIL, ATTR_CJK_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY }, { SC_UNO_CTL_CFFAMIL, ATTR_CTL_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY }, { SC_UNONAME_CFNAME, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY_NAME }, { SC_UNO_CJK_CFNAME, ATTR_CJK_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY_NAME }, { SC_UNO_CTL_CFNAME, ATTR_CTL_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY_NAME }, { SC_UNONAME_CFPITCH, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_PITCH }, { SC_UNO_CJK_CFPITCH, ATTR_CJK_FONT, cppu::UnoType::get(), 0, MID_FONT_PITCH }, { SC_UNO_CTL_CFPITCH, ATTR_CTL_FONT, cppu::UnoType::get(), 0, MID_FONT_PITCH }, { SC_UNONAME_CFSTYLE, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_STYLE_NAME }, { SC_UNO_CJK_CFSTYLE, ATTR_CJK_FONT, cppu::UnoType::get(), 0, MID_FONT_STYLE_NAME }, { SC_UNO_CTL_CFSTYLE, ATTR_CTL_FONT, cppu::UnoType::get(), 0, MID_FONT_STYLE_NAME }, { SC_UNONAME_CHEIGHT, ATTR_FONT_HEIGHT, cppu::UnoType::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, { SC_UNO_CJK_CHEIGHT, ATTR_CJK_FONT_HEIGHT,cppu::UnoType::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, { SC_UNO_CTL_CHEIGHT, ATTR_CTL_FONT_HEIGHT,cppu::UnoType::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, { SC_UNONAME_CLOCAL, ATTR_FONT_LANGUAGE, cppu::UnoType::get(), 0, MID_LANG_LOCALE }, { SC_UNO_CJK_CLOCAL, ATTR_CJK_FONT_LANGUAGE,cppu::UnoType::get(), 0, MID_LANG_LOCALE }, { SC_UNO_CTL_CLOCAL, ATTR_CTL_FONT_LANGUAGE,cppu::UnoType::get(), 0, MID_LANG_LOCALE }, { SC_UNONAME_COVER, ATTR_FONT_OVERLINE, cppu::UnoType::get(), 0, MID_TL_STYLE }, { SC_UNONAME_COVRLCOL, ATTR_FONT_OVERLINE, cppu::UnoType::get(), 0, MID_TL_COLOR }, { SC_UNONAME_COVRLHAS, ATTR_FONT_OVERLINE, cppu::UnoType::get(), 0, MID_TL_HASCOLOR }, { SC_UNONAME_CPOST, ATTR_FONT_POSTURE, cppu::UnoType::get(), 0, MID_POSTURE }, { SC_UNO_CJK_CPOST, ATTR_CJK_FONT_POSTURE,cppu::UnoType::get(), 0, MID_POSTURE }, { SC_UNO_CTL_CPOST, ATTR_CTL_FONT_POSTURE,cppu::UnoType::get(), 0, MID_POSTURE }, { SC_UNONAME_CRELIEF, ATTR_FONT_RELIEF, cppu::UnoType::get(), 0, MID_RELIEF }, { SC_UNONAME_CSHADD, ATTR_FONT_SHADOWED, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CSTRIKE, ATTR_FONT_CROSSEDOUT,cppu::UnoType::get(), 0, MID_CROSS_OUT }, { SC_UNONAME_CUNDER, ATTR_FONT_UNDERLINE,cppu::UnoType::get(), 0, MID_TL_STYLE }, { SC_UNONAME_CUNDLCOL, ATTR_FONT_UNDERLINE,cppu::UnoType::get(), 0, MID_TL_COLOR }, { SC_UNONAME_CUNDLHAS, ATTR_FONT_UNDERLINE,cppu::UnoType::get(), 0, MID_TL_HASCOLOR }, { SC_UNONAME_CWEIGHT, ATTR_FONT_WEIGHT, cppu::UnoType::get(), 0, MID_WEIGHT }, { SC_UNO_CJK_CWEIGHT, ATTR_CJK_FONT_WEIGHT,cppu::UnoType::get(), 0, MID_WEIGHT }, { SC_UNO_CTL_CWEIGHT, ATTR_CTL_FONT_WEIGHT,cppu::UnoType::get(), 0, MID_WEIGHT }, { SC_UNONAME_CWORDMOD, ATTR_FONT_WORDLINE, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CHCOLHDR, SC_WID_UNO_CHCOLHDR,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CHROWHDR, SC_WID_UNO_CHROWHDR,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CONDFMT, SC_WID_UNO_CONDFMT, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CONDLOC, SC_WID_UNO_CONDLOC, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CONDXML, SC_WID_UNO_CONDXML, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_DIAGONAL_BLTR, ATTR_BORDER_BLTR, ::cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_DIAGONAL_BLTR2, ATTR_BORDER_BLTR, ::cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_DIAGONAL_TLBR, ATTR_BORDER_TLBR, ::cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_DIAGONAL_TLBR2, ATTR_BORDER_TLBR, ::cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_CELLHJUS, ATTR_HOR_JUSTIFY, cppu::UnoType::get(), 0, MID_HORJUST_HORJUST }, { SC_UNONAME_CELLHJUS_METHOD, ATTR_HOR_JUSTIFY_METHOD, ::cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLTRAN, ATTR_BACKGROUND, cppu::UnoType::get(), 0, MID_GRAPHIC_TRANSPARENT }, { SC_UNONAME_MANPAGE, SC_WID_UNO_MANPAGE, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_NEWPAGE, SC_WID_UNO_NEWPAGE, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_WRAP, ATTR_LINEBREAK, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLVIS, SC_WID_UNO_CELLVIS, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_NUMFMT, ATTR_VALUE_FORMAT, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_NUMRULES, SC_WID_UNO_NUMRULES,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_OWIDTH, SC_WID_UNO_OWIDTH, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLORI, ATTR_STACKED, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_PADJUST, ATTR_HOR_JUSTIFY, ::cppu::UnoType::get(), 0, MID_HORJUST_ADJUST }, { SC_UNONAME_PBMARGIN, ATTR_MARGIN, cppu::UnoType::get(), 0, MID_MARGIN_LO_MARGIN | CONVERT_TWIPS }, { SC_UNONAME_PINDENT, ATTR_INDENT, cppu::UnoType::get(), 0, 0 }, //! CONVERT_TWIPS { SC_UNONAME_PISCHDIST,ATTR_SCRIPTSPACE, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_PISFORBID,ATTR_FORBIDDEN_RULES,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_PISHANG, ATTR_HANGPUNCTUATION,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_PISHYPHEN,ATTR_HYPHENATE, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_PLASTADJ, ATTR_HOR_JUSTIFY, ::cppu::UnoType::get(), 0, MID_HORJUST_ADJUST }, { SC_UNONAME_PLMARGIN, ATTR_MARGIN, cppu::UnoType::get(), 0, MID_MARGIN_L_MARGIN | CONVERT_TWIPS }, { SC_UNONAME_PRMARGIN, ATTR_MARGIN, cppu::UnoType::get(), 0, MID_MARGIN_R_MARGIN | CONVERT_TWIPS }, { SC_UNONAME_PTMARGIN, ATTR_MARGIN, cppu::UnoType::get(), 0, MID_MARGIN_UP_MARGIN | CONVERT_TWIPS }, { SC_UNONAME_POS, SC_WID_UNO_POS, cppu::UnoType::get(), 0 | beans::PropertyAttribute::READONLY, 0 }, { SC_UNONAME_ROTANG, ATTR_ROTATE_VALUE, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_ROTREF, ATTR_ROTATE_MODE, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_SHADOW, ATTR_SHADOW, cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_SHRINK_TO_FIT, ATTR_SHRINKTOFIT, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_SIZE, SC_WID_UNO_SIZE, cppu::UnoType::get(), 0 | beans::PropertyAttribute::READONLY, 0 }, { SC_UNONAME_TBLBORD, SC_WID_UNO_TBLBORD, cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_TBLBORD2, SC_WID_UNO_TBLBORD2, cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_USERDEF, ATTR_USERDEF, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_VALIDAT, SC_WID_UNO_VALIDAT, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_VALILOC, SC_WID_UNO_VALILOC, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_VALIXML, SC_WID_UNO_VALIXML, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLVJUS, ATTR_VER_JUSTIFY, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLVJUS_METHOD, ATTR_VER_JUSTIFY_METHOD, ::cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLWID, SC_WID_UNO_CELLWID, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_WRITING, ATTR_WRITINGDIR, cppu::UnoType::get(), 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::get(), 0 | beans::PropertyAttribute::READONLY, 0 }, { SC_UNONAME_ASIANVERT,ATTR_VERTICAL_ASIAN,cppu::UnoType::get(), 0, 0 }, CELL_BORDER_PROPERTIES CELL_BACKGROUND_COLOR_PROPERTIES { SC_UNONAME_CELLPRO, ATTR_PROTECTION, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLSTYL, SC_WID_UNO_CELLSTYL,cppu::UnoType::get(), 0, 0 }, CHAR_COLOR_PROPERTIES { SC_UNONAME_COUTL, ATTR_FONT_CONTOUR, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CCROSS, ATTR_FONT_CROSSEDOUT,cppu::UnoType::get(), 0, MID_CROSSED_OUT }, { SC_UNONAME_CEMPHAS, ATTR_FONT_EMPHASISMARK,cppu::UnoType::get(), 0, MID_EMPHASIS }, { SC_UNONAME_CFONT, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY }, { SC_UNONAME_CFCHARS, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_CHAR_SET }, { SC_UNO_CJK_CFCHARS, ATTR_CJK_FONT, cppu::UnoType::get(), 0, MID_FONT_CHAR_SET }, { SC_UNO_CTL_CFCHARS, ATTR_CTL_FONT, cppu::UnoType::get(), 0, MID_FONT_CHAR_SET }, { SC_UNONAME_CFFAMIL, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY }, { SC_UNO_CJK_CFFAMIL, ATTR_CJK_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY }, { SC_UNO_CTL_CFFAMIL, ATTR_CTL_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY }, { SC_UNONAME_CFNAME, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY_NAME }, { SC_UNO_CJK_CFNAME, ATTR_CJK_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY_NAME }, { SC_UNO_CTL_CFNAME, ATTR_CTL_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY_NAME }, { SC_UNONAME_CFPITCH, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_PITCH }, { SC_UNO_CJK_CFPITCH, ATTR_CJK_FONT, cppu::UnoType::get(), 0, MID_FONT_PITCH }, { SC_UNO_CTL_CFPITCH, ATTR_CTL_FONT, cppu::UnoType::get(), 0, MID_FONT_PITCH }, { SC_UNONAME_CFSTYLE, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_STYLE_NAME }, { SC_UNO_CJK_CFSTYLE, ATTR_CJK_FONT, cppu::UnoType::get(), 0, MID_FONT_STYLE_NAME }, { SC_UNO_CTL_CFSTYLE, ATTR_CTL_FONT, cppu::UnoType::get(), 0, MID_FONT_STYLE_NAME }, { SC_UNONAME_CHEIGHT, ATTR_FONT_HEIGHT, cppu::UnoType::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, { SC_UNO_CJK_CHEIGHT, ATTR_CJK_FONT_HEIGHT,cppu::UnoType::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, { SC_UNO_CTL_CHEIGHT, ATTR_CTL_FONT_HEIGHT,cppu::UnoType::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, { SC_UNONAME_CLOCAL, ATTR_FONT_LANGUAGE, cppu::UnoType::get(), 0, MID_LANG_LOCALE }, { SC_UNO_CJK_CLOCAL, ATTR_CJK_FONT_LANGUAGE,cppu::UnoType::get(), 0, MID_LANG_LOCALE }, { SC_UNO_CTL_CLOCAL, ATTR_CTL_FONT_LANGUAGE,cppu::UnoType::get(), 0, MID_LANG_LOCALE }, { SC_UNONAME_COVER, ATTR_FONT_OVERLINE, cppu::UnoType::get(), 0, MID_TL_STYLE }, { SC_UNONAME_COVRLCOL, ATTR_FONT_OVERLINE, cppu::UnoType::get(), 0, MID_TL_COLOR }, { SC_UNONAME_COVRLHAS, ATTR_FONT_OVERLINE, cppu::UnoType::get(), 0, MID_TL_HASCOLOR }, { SC_UNONAME_CPOST, ATTR_FONT_POSTURE, cppu::UnoType::get(), 0, MID_POSTURE }, { SC_UNO_CJK_CPOST, ATTR_CJK_FONT_POSTURE,cppu::UnoType::get(), 0, MID_POSTURE }, { SC_UNO_CTL_CPOST, ATTR_CTL_FONT_POSTURE,cppu::UnoType::get(), 0, MID_POSTURE }, { SC_UNONAME_CRELIEF, ATTR_FONT_RELIEF, cppu::UnoType::get(), 0, MID_RELIEF }, { SC_UNONAME_CSHADD, ATTR_FONT_SHADOWED, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CSTRIKE, ATTR_FONT_CROSSEDOUT,cppu::UnoType::get(), 0, MID_CROSS_OUT }, { SC_UNONAME_CUNDER, ATTR_FONT_UNDERLINE,cppu::UnoType::get(), 0, MID_TL_STYLE }, { SC_UNONAME_CUNDLCOL, ATTR_FONT_UNDERLINE,cppu::UnoType::get(), 0, MID_TL_COLOR }, { SC_UNONAME_CUNDLHAS, ATTR_FONT_UNDERLINE,cppu::UnoType::get(), 0, MID_TL_HASCOLOR }, { SC_UNONAME_CWEIGHT, ATTR_FONT_WEIGHT, cppu::UnoType::get(), 0, MID_WEIGHT }, { SC_UNO_CJK_CWEIGHT, ATTR_CJK_FONT_WEIGHT,cppu::UnoType::get(), 0, MID_WEIGHT }, { SC_UNO_CTL_CWEIGHT, ATTR_CTL_FONT_WEIGHT,cppu::UnoType::get(), 0, MID_WEIGHT }, { SC_UNONAME_CWORDMOD, ATTR_FONT_WORDLINE, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CHCOLHDR, SC_WID_UNO_CHCOLHDR,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CHROWHDR, SC_WID_UNO_CHROWHDR,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CONDFMT, SC_WID_UNO_CONDFMT, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CONDLOC, SC_WID_UNO_CONDLOC, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CONDXML, SC_WID_UNO_CONDXML, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_DIAGONAL_BLTR, ATTR_BORDER_BLTR, ::cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_DIAGONAL_BLTR2, ATTR_BORDER_BLTR, ::cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_DIAGONAL_TLBR, ATTR_BORDER_TLBR, ::cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_DIAGONAL_TLBR2, ATTR_BORDER_TLBR, ::cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_CELLHGT, SC_WID_UNO_CELLHGT, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLHJUS, ATTR_HOR_JUSTIFY, cppu::UnoType::get(), 0, MID_HORJUST_HORJUST }, { SC_UNONAME_CELLHJUS_METHOD, ATTR_HOR_JUSTIFY_METHOD, ::cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLTRAN, ATTR_BACKGROUND, cppu::UnoType::get(), 0, MID_GRAPHIC_TRANSPARENT }, { SC_UNONAME_CELLFILT, SC_WID_UNO_CELLFILT,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_MANPAGE, SC_WID_UNO_MANPAGE, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_NEWPAGE, SC_WID_UNO_NEWPAGE, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_WRAP, ATTR_LINEBREAK, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLVIS, SC_WID_UNO_CELLVIS, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_NUMFMT, ATTR_VALUE_FORMAT, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_NUMRULES, SC_WID_UNO_NUMRULES,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_OHEIGHT, SC_WID_UNO_OHEIGHT, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLORI, ATTR_STACKED, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_PADJUST, ATTR_HOR_JUSTIFY, ::cppu::UnoType::get(), 0, MID_HORJUST_ADJUST }, { SC_UNONAME_PBMARGIN, ATTR_MARGIN, cppu::UnoType::get(), 0, MID_MARGIN_LO_MARGIN | CONVERT_TWIPS }, { SC_UNONAME_PINDENT, ATTR_INDENT, cppu::UnoType::get(), 0, 0 }, //! CONVERT_TWIPS { SC_UNONAME_PISCHDIST,ATTR_SCRIPTSPACE, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_PISFORBID,ATTR_FORBIDDEN_RULES,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_PISHANG, ATTR_HANGPUNCTUATION,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_PISHYPHEN,ATTR_HYPHENATE, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_PLASTADJ, ATTR_HOR_JUSTIFY, ::cppu::UnoType::get(), 0, MID_HORJUST_ADJUST }, { SC_UNONAME_PLMARGIN, ATTR_MARGIN, cppu::UnoType::get(), 0, MID_MARGIN_L_MARGIN | CONVERT_TWIPS }, { SC_UNONAME_PRMARGIN, ATTR_MARGIN, cppu::UnoType::get(), 0, MID_MARGIN_R_MARGIN | CONVERT_TWIPS }, { SC_UNONAME_PTMARGIN, ATTR_MARGIN, cppu::UnoType::get(), 0, MID_MARGIN_UP_MARGIN | CONVERT_TWIPS }, { SC_UNONAME_POS, SC_WID_UNO_POS, cppu::UnoType::get(), 0 | beans::PropertyAttribute::READONLY, 0 }, { SC_UNONAME_ROTANG, ATTR_ROTATE_VALUE, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_ROTREF, ATTR_ROTATE_MODE, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_SHADOW, ATTR_SHADOW, cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_SHRINK_TO_FIT, ATTR_SHRINKTOFIT, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_SIZE, SC_WID_UNO_SIZE, cppu::UnoType::get(), 0 | beans::PropertyAttribute::READONLY, 0 }, { SC_UNONAME_TBLBORD, SC_WID_UNO_TBLBORD, cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_TBLBORD2, SC_WID_UNO_TBLBORD2, cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_USERDEF, ATTR_USERDEF, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_VALIDAT, SC_WID_UNO_VALIDAT, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_VALILOC, SC_WID_UNO_VALILOC, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_VALIXML, SC_WID_UNO_VALIXML, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLVJUS, ATTR_VER_JUSTIFY, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLVJUS_METHOD, ATTR_VER_JUSTIFY_METHOD, ::cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_WRITING, ATTR_WRITINGDIR, cppu::UnoType::get(), 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::get(), 0 | beans::PropertyAttribute::READONLY, 0 }, { SC_UNONAME_ASIANVERT,ATTR_VERTICAL_ASIAN,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_AUTOPRINT,SC_WID_UNO_AUTOPRINT,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_BORDCOL, SC_WID_UNO_BORDCOL, cppu::UnoType::get(), 0, 0 }, CELL_BORDER_PROPERTIES CELL_BACKGROUND_COLOR_PROPERTIES { SC_UNONAME_CELLPRO, ATTR_PROTECTION, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLSTYL, SC_WID_UNO_CELLSTYL,cppu::UnoType::get(), 0, 0 }, CHAR_COLOR_PROPERTIES { SC_UNONAME_COUTL, ATTR_FONT_CONTOUR, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CCROSS, ATTR_FONT_CROSSEDOUT,cppu::UnoType::get(), 0, MID_CROSSED_OUT }, { SC_UNONAME_CEMPHAS, ATTR_FONT_EMPHASISMARK,cppu::UnoType::get(), 0, MID_EMPHASIS }, { SC_UNONAME_CFONT, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY }, { SC_UNONAME_CFCHARS, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_CHAR_SET }, { SC_UNO_CJK_CFCHARS, ATTR_CJK_FONT, cppu::UnoType::get(), 0, MID_FONT_CHAR_SET }, { SC_UNO_CTL_CFCHARS, ATTR_CTL_FONT, cppu::UnoType::get(), 0, MID_FONT_CHAR_SET }, { SC_UNONAME_CFFAMIL, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY }, { SC_UNO_CJK_CFFAMIL, ATTR_CJK_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY }, { SC_UNO_CTL_CFFAMIL, ATTR_CTL_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY }, { SC_UNONAME_CFNAME, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY_NAME }, { SC_UNO_CJK_CFNAME, ATTR_CJK_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY_NAME }, { SC_UNO_CTL_CFNAME, ATTR_CTL_FONT, cppu::UnoType::get(), 0, MID_FONT_FAMILY_NAME }, { SC_UNONAME_CFPITCH, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_PITCH }, { SC_UNO_CJK_CFPITCH, ATTR_CJK_FONT, cppu::UnoType::get(), 0, MID_FONT_PITCH }, { SC_UNO_CTL_CFPITCH, ATTR_CTL_FONT, cppu::UnoType::get(), 0, MID_FONT_PITCH }, { SC_UNONAME_CFSTYLE, ATTR_FONT, cppu::UnoType::get(), 0, MID_FONT_STYLE_NAME }, { SC_UNO_CJK_CFSTYLE, ATTR_CJK_FONT, cppu::UnoType::get(), 0, MID_FONT_STYLE_NAME }, { SC_UNO_CTL_CFSTYLE, ATTR_CTL_FONT, cppu::UnoType::get(), 0, MID_FONT_STYLE_NAME }, { SC_UNONAME_CHEIGHT, ATTR_FONT_HEIGHT, cppu::UnoType::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, { SC_UNO_CJK_CHEIGHT, ATTR_CJK_FONT_HEIGHT,cppu::UnoType::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, { SC_UNO_CTL_CHEIGHT, ATTR_CTL_FONT_HEIGHT,cppu::UnoType::get(), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, { SC_UNONAME_CLOCAL, ATTR_FONT_LANGUAGE, cppu::UnoType::get(), 0, MID_LANG_LOCALE }, { SC_UNO_CJK_CLOCAL, ATTR_CJK_FONT_LANGUAGE,cppu::UnoType::get(), 0, MID_LANG_LOCALE }, { SC_UNO_CTL_CLOCAL, ATTR_CTL_FONT_LANGUAGE,cppu::UnoType::get(), 0, MID_LANG_LOCALE }, { SC_UNONAME_COVER, ATTR_FONT_OVERLINE, cppu::UnoType::get(), 0, MID_TL_STYLE }, { SC_UNONAME_COVRLCOL, ATTR_FONT_OVERLINE, cppu::UnoType::get(), 0, MID_TL_COLOR }, { SC_UNONAME_COVRLHAS, ATTR_FONT_OVERLINE, cppu::UnoType::get(), 0, MID_TL_HASCOLOR }, { SC_UNONAME_CPOST, ATTR_FONT_POSTURE, cppu::UnoType::get(), 0, MID_POSTURE }, { SC_UNO_CJK_CPOST, ATTR_CJK_FONT_POSTURE,cppu::UnoType::get(), 0, MID_POSTURE }, { SC_UNO_CTL_CPOST, ATTR_CTL_FONT_POSTURE,cppu::UnoType::get(), 0, MID_POSTURE }, { SC_UNONAME_CRELIEF, ATTR_FONT_RELIEF, cppu::UnoType::get(), 0, MID_RELIEF }, { SC_UNONAME_CSHADD, ATTR_FONT_SHADOWED, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CSTRIKE, ATTR_FONT_CROSSEDOUT,cppu::UnoType::get(), 0, MID_CROSS_OUT }, { SC_UNONAME_CUNDER, ATTR_FONT_UNDERLINE,cppu::UnoType::get(), 0, MID_TL_STYLE }, { SC_UNONAME_CUNDLCOL, ATTR_FONT_UNDERLINE,cppu::UnoType::get(), 0, MID_TL_COLOR }, { SC_UNONAME_CUNDLHAS, ATTR_FONT_UNDERLINE,cppu::UnoType::get(), 0, MID_TL_HASCOLOR }, { SC_UNONAME_CWEIGHT, ATTR_FONT_WEIGHT, cppu::UnoType::get(), 0, MID_WEIGHT }, { SC_UNO_CJK_CWEIGHT, ATTR_CJK_FONT_WEIGHT,cppu::UnoType::get(), 0, MID_WEIGHT }, { SC_UNO_CTL_CWEIGHT, ATTR_CTL_FONT_WEIGHT,cppu::UnoType::get(), 0, MID_WEIGHT }, { SC_UNONAME_CWORDMOD, ATTR_FONT_WORDLINE, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CHCOLHDR, SC_WID_UNO_CHCOLHDR,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CHROWHDR, SC_WID_UNO_CHROWHDR,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CONDFMT, SC_WID_UNO_CONDFMT, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CONDLOC, SC_WID_UNO_CONDLOC, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CONDXML, SC_WID_UNO_CONDXML, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_COPYBACK, SC_WID_UNO_COPYBACK,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_COPYFORM, SC_WID_UNO_COPYFORM,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_COPYSTYL, SC_WID_UNO_COPYSTYL,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_DIAGONAL_BLTR, ATTR_BORDER_BLTR, ::cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_DIAGONAL_BLTR2, ATTR_BORDER_BLTR, ::cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_DIAGONAL_TLBR, ATTR_BORDER_TLBR, ::cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_DIAGONAL_TLBR2, ATTR_BORDER_TLBR, ::cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_CELLHJUS, ATTR_HOR_JUSTIFY, cppu::UnoType::get(), 0, MID_HORJUST_HORJUST }, { SC_UNONAME_CELLHJUS_METHOD, ATTR_HOR_JUSTIFY_METHOD, ::cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_ISACTIVE, SC_WID_UNO_ISACTIVE,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLTRAN, ATTR_BACKGROUND, cppu::UnoType::get(), 0, MID_GRAPHIC_TRANSPARENT }, { SC_UNONAME_WRAP, ATTR_LINEBREAK, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLVIS, SC_WID_UNO_CELLVIS, cppu::UnoType::get(), 0, 0 }, { SC_UNO_LINKDISPBIT, SC_WID_UNO_LINKDISPBIT,cppu::UnoType::get(), 0 | beans::PropertyAttribute::READONLY, 0 }, { SC_UNO_LINKDISPNAME, SC_WID_UNO_LINKDISPNAME,cppu::UnoType::get(), 0 | beans::PropertyAttribute::READONLY, 0 }, { SC_UNONAME_NUMFMT, ATTR_VALUE_FORMAT, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_NUMRULES, SC_WID_UNO_NUMRULES,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLORI, ATTR_STACKED, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_PAGESTL, SC_WID_UNO_PAGESTL, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_PADJUST, ATTR_HOR_JUSTIFY, ::cppu::UnoType::get(), 0, MID_HORJUST_ADJUST }, { SC_UNONAME_PBMARGIN, ATTR_MARGIN, cppu::UnoType::get(), 0, MID_MARGIN_LO_MARGIN | CONVERT_TWIPS }, { SC_UNONAME_PINDENT, ATTR_INDENT, cppu::UnoType::get(), 0, 0 }, //! CONVERT_TWIPS { SC_UNONAME_PISCHDIST,ATTR_SCRIPTSPACE, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_PISFORBID,ATTR_FORBIDDEN_RULES,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_PISHANG, ATTR_HANGPUNCTUATION,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_PISHYPHEN,ATTR_HYPHENATE, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_PLASTADJ, ATTR_HOR_JUSTIFY, ::cppu::UnoType::get(), 0, MID_HORJUST_ADJUST }, { SC_UNONAME_PLMARGIN, ATTR_MARGIN, cppu::UnoType::get(), 0, MID_MARGIN_L_MARGIN | CONVERT_TWIPS }, { SC_UNONAME_PRMARGIN, ATTR_MARGIN, cppu::UnoType::get(), 0, MID_MARGIN_R_MARGIN | CONVERT_TWIPS }, { SC_UNONAME_PTMARGIN, ATTR_MARGIN, cppu::UnoType::get(), 0, MID_MARGIN_UP_MARGIN | CONVERT_TWIPS }, { SC_UNONAME_POS, SC_WID_UNO_POS, cppu::UnoType::get(), 0 | beans::PropertyAttribute::READONLY, 0 }, { SC_UNONAME_PRINTBORD,SC_WID_UNO_PRINTBORD,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_PROTECT, SC_WID_UNO_PROTECT, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_ROTANG, ATTR_ROTATE_VALUE, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_ROTREF, ATTR_ROTATE_MODE, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_SHADOW, ATTR_SHADOW, cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_SHOWBORD, SC_WID_UNO_SHOWBORD,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_SHRINK_TO_FIT, ATTR_SHRINKTOFIT, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_SIZE, SC_WID_UNO_SIZE, cppu::UnoType::get(), 0 | beans::PropertyAttribute::READONLY, 0 }, { SC_UNONAME_TBLBORD, SC_WID_UNO_TBLBORD, cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_TBLBORD2, SC_WID_UNO_TBLBORD2, cppu::UnoType::get(), 0, 0 | CONVERT_TWIPS }, { SC_UNONAME_TABLAYOUT,SC_WID_UNO_TABLAYOUT,cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CONDFORMAT, SC_WID_UNO_CONDFORMAT, cppu::UnoType::get(), 0, 0}, { SC_UNONAME_USERDEF, ATTR_USERDEF, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_VALIDAT, SC_WID_UNO_VALIDAT, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_VALILOC, SC_WID_UNO_VALILOC, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_VALIXML, SC_WID_UNO_VALIXML, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLVJUS, ATTR_VER_JUSTIFY, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_CELLVJUS_METHOD, ATTR_VER_JUSTIFY_METHOD, ::cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_WRITING, ATTR_WRITINGDIR, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_TABCOLOR, SC_WID_UNO_TABCOLOR, cppu::UnoType::get(), 0, 0 }, { SC_UNO_CODENAME, SC_WID_UNO_CODENAME, cppu::UnoType::get(), 0, 0}, { SC_UNO_NAMEDRANGES, SC_WID_UNO_NAMES, cppu::UnoType::get(), 0, 0 }, }; static SfxItemPropertySet aSheetPropertySet( aSheetPropertyMap_Impl ); return &aSheetPropertySet; } static std::span 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::get(), 0, 0}, { SC_UNONAME_USERDEF, EE_PARA_XMLATTRIBS, cppu::UnoType::get(), 0, 0}, }; return aEditPropertyMap_Impl; } static const SvxItemPropertySet* lcl_GetEditPropertySet() { static SvxItemPropertySet aEditPropertySet( lcl_GetEditPropertyMap(), SdrObject::GetGlobalDrawObjectItemPool() ); return &aEditPropertySet; } constexpr OUString SCCHARPROPERTIES_SERVICE = u"com.sun.star.style.CharacterProperties"_ustr; constexpr OUString SCPARAPROPERTIES_SERVICE = u"com.sun.star.style.ParagraphProperties"_ustr; constexpr OUString SCCELLPROPERTIES_SERVICE = u"com.sun.star.table.CellProperties"_ustr; constexpr OUString SCCELLRANGE_SERVICE = u"com.sun.star.table.CellRange"_ustr; constexpr OUString SCCELL_SERVICE = u"com.sun.star.table.Cell"_ustr; constexpr OUString SCSHEETCELLRANGES_SERVICE = u"com.sun.star.sheet.SheetCellRanges"_ustr; constexpr OUString SCSHEETCELLRANGE_SERVICE = u"com.sun.star.sheet.SheetCellRange"_ustr; constexpr OUString SCSPREADSHEET_SERVICE = u"com.sun.star.sheet.Spreadsheet"_ustr; constexpr OUString SCSHEETCELL_SERVICE = u"com.sun.star.sheet.SheetCell"_ustr; 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 xInfo(rSource.getPropertySetInfo()); if (xInfo.is()) { const uno::Sequence 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 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 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 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( 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 >& 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& 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 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( &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 >& 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& rColSeq : aData) { if ( rColSeq.getLength() == nCols ) { SCCOL nDocCol = nStartCol; for (const OUString& aText : rColSeq) { ScAddress aPos( nDocCol, nDocRow, nTab ); ScInputStringType aRes = ScStringUtil::parseInputString( rDoc.GetNonThreadedContext(), 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( &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.getType(); if (eType == CELLTYPE_FORMULA) { ScFormulaCell* pForm = aCell.getFormula(); return pForm->GetFormula( formula::FormulaGrammar::mapAPItoGrammar( bEnglish, false)); } // use an InterpreterContext, possibly with a different formatter, to uniformly use // ScCellFormat::GetInputString everywhere ScInterpreterContextGetterGuard aContextGetterGuard(rDoc, bEnglish ? ScGlobal::GetEnglishFormatter() : rDoc.GetFormatTable()); ScInterpreterContext* pInterpreterContext = aContextGetterGuard.GetInterpreterContext(); // 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.getEditText(); if (pData) { EditEngine& rEngine = rDoc.GetEditEngine(); rEngine.SetText(*pData); aVal = rEngine.GetText(); } } else aVal = ScCellFormat::GetInputString(aCell, nNumFmt, pInterpreterContext, rDoc); // if applicable, prepend ' like in ScTabViewShell::UpdateInputHandler if ( eType == CELLTYPE_STRING || eType == CELLTYPE_EDIT ) { double fDummy; OUString aTempString = aVal; bool bIsNumberFormat(pInterpreterContext->NFIsNumberFormat(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 || ( pInterpreterContext->NFGetType(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, ScRangeList aR) : pPropSet(lcl_GetCellsPropertySet()), pDocShell( pDocSh ), aRanges(std::move( aR )), 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 = getXWeak(); for (uno::Reference & 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 = getXWeak(); // the EventObject holds a Ref to this object until after the listener calls ScDocument& rDoc = pDocShell->GetDocument(); for (const uno::Reference & 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(&rHint) ) { ScDocument& rDoc = pDocShell->GetDocument(); std::unique_ptr 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(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(&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(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(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::INVALID ) 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 SAL_CALL ScCellRangesBase::getPropertyStates( const uno::Sequence& aPropertyNames ) { SolarMutexGuard aGuard; const SfxItemPropertyMap& rPropertyMap = GetItemPropertyMap(); // from derived class uno::Sequence 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.getCellAttributeHelper().getDefaultCellAttribute()); 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( static_cast(rSet.Get(pEntry->nWID)).GetValue() ); break; case ATTR_INDENT: aAny <<= static_cast( convertTwipToMm100(static_cast( 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.getCellAttributeHelper().getDefaultCellAttribute()); 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( 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( new ScTableValidationObj( rDoc, 0, eGrammar )); } break; case SC_WID_UNO_NUMRULES: { aAny <<= ScStyleObj::CreateEmptyNumberingRules(); } break; } } } return aAny; } // XPropertySet uno::Reference SAL_CALL ScCellRangesBase::getPropertySetInfo() { SolarMutexGuard aGuard; static uno::Reference 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(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: { SfxItemPropertySet::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 xInterface(aValue, uno::UNO_QUERY); if ( !aRanges.empty() && xInterface.is() ) // empty = nothing to do { ScTableConditionalFormat* pFormat = dynamic_cast( xInterface.get() ); 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( 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 xInterface(aValue, uno::UNO_QUERY); if ( !aRanges.empty() && xInterface.is() ) // empty = nothing to do { ScTableValidationObj* pValidObj = dynamic_cast( xInterface.get() ); 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 pNewData( pValidObj->CreateValidationData( rDoc, eGrammar )); sal_uInt32 nIndex = rDoc.AddValidationEntry( *pNewData ); pNewData.reset(); ScPatternAttr aPattern(rDoc.getCellAttributeHelper()); 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(nOldFormat); } break; case ATTR_INDENT: rAny <<= static_cast( convertTwipToMm100(static_cast( pDataSet->Get(pEntry->nWID)).GetValue()) ); break; case ATTR_STACKED: { Degree100 nRot = pDataSet->Get(ATTR_ROTATE_VALUE).GetValue(); bool bStacked = static_cast(pDataSet->Get(pEntry->nWID)).GetValue(); SvxOrientationItem( nRot, bStacked, TypedWhichId(0) ).QueryValue( rAny ); } break; default: SfxItemPropertySet::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( 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( 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->GetPAKey(); } break; } } void SAL_CALL ScCellRangesBase::addPropertyChangeListener( const OUString& /* aPropertyName */, const uno::Reference& /* aListener */) { SolarMutexGuard aGuard; if ( aRanges.empty() ) throw uno::RuntimeException(); OSL_FAIL("not implemented"); } void SAL_CALL ScCellRangesBase::removePropertyChangeListener( const OUString& /* aPropertyName */, const uno::Reference& /* aListener */) { SolarMutexGuard aGuard; if ( aRanges.empty() ) throw uno::RuntimeException(); OSL_FAIL("not implemented"); } void SAL_CALL ScCellRangesBase::addVetoableChangeListener( const OUString&, const uno::Reference&) { OSL_FAIL("not implemented"); } void SAL_CALL ScCellRangesBase::removeVetoableChangeListener( const OUString&, const uno::Reference&) { 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 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 pOldPattern; std::unique_ptr 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.getCellAttributeHelper())); } // 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 SAL_CALL ScCellRangesBase::getPropertyValues( const uno::Sequence< OUString >& aPropertyNames ) { SolarMutexGuard aGuard; const SfxItemPropertyMap& rPropertyMap = GetItemPropertyMap(); // from derived class uno::Sequence 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 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 pOldPattern; std::unique_ptr 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.getCellAttributeHelper())); } // 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 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 > SAL_CALL ScCellRangesBase::getData() { SolarMutexGuard aGuard; std::unique_ptr pMemChart(CreateMemChart_Impl()); if ( pMemChart ) { sal_Int32 nColCount = pMemChart->GetColCount(); sal_Int32 nRowCount = static_cast(pMemChart->GetRowCount()); uno::Sequence< uno::Sequence > aRowSeq( nRowCount ); uno::Sequence* pRowAry = aRowSeq.getArray(); for (sal_Int32 nRow = 0; nRow < nRowCount; nRow++) { uno::Sequence 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(nEndColumn), static_cast(nEndRow), nTab ) ); return xChartRanges; } } return new ScRangeList(aRanges); // as-is } void SAL_CALL ScCellRangesBase::setData( const uno::Sequence< uno::Sequence >& 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(nColCount) && pPosMap->GetRowCount() == static_cast(nRowCount) ) { for (sal_Int32 nRow=0; nRow& rRowSeq = aData[nRow]; const double* pArray = rRowSeq.getConstArray(); nColCount = rRowSeq.getLength(); for (sal_Int32 nCol=0; nColGetPosition( sal::static_int_cast(nCol), sal::static_int_cast(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 SAL_CALL ScCellRangesBase::getRowDescriptions() { SolarMutexGuard aGuard; std::unique_ptr pMemChart(CreateMemChart_Impl()); if ( pMemChart ) { sal_Int32 nRowCount = static_cast(pMemChart->GetRowCount()); uno::Sequence 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& 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(nRowCount) ) { const OUString* pArray = aRowDescriptions.getConstArray(); for (sal_Int32 nRow=0; nRowGetRowHeaderPosition( static_cast(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 SAL_CALL ScCellRangesBase::getColumnDescriptions() { SolarMutexGuard aGuard; std::unique_ptr pMemChart(CreateMemChart_Impl()); if ( pMemChart ) { sal_Int32 nColCount = pMemChart->GetColCount(); uno::Sequence 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& 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(nColCount) ) { const OUString* pArray = aColumnDescriptions.getConstArray(); for (sal_Int32 nCol=0; nColGetColHeaderPosition( sal::static_int_cast(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(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& 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& aListener ) { SolarMutexGuard aGuard; if ( aRanges.empty() ) throw uno::RuntimeException(); rtl::Reference xSelfHold(this); // in case the listeners have the last ref sal_uInt16 nCount = aValueListeners.size(); for ( sal_uInt16 n=nCount; n--; ) { uno::Reference& 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 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 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 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(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 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 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 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(aCompare.Row) : static_cast(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(nCmpPos),0,nTab, static_cast(nCmpPos),rDoc.MaxRow(),nTab ); ScCellIterator aCmpIter(rDoc, aCmpRange); for (bool bHasCell = aCmpIter.first(); bHasCell; bHasCell = aCmpIter.next()) { SCCOLROW nCellPos = bColumnDiff ? static_cast(aCmpIter.GetPos().Col()) : static_cast(aCmpIter.GetPos().Row()); if (bColumnDiff) aCellRange = ScRange( static_cast(nCellPos),0,nTab, static_cast(nCellPos),rDoc.MaxRow(),nTab ); else aCellRange = ScRange( 0,nCellPos,nTab, rDoc.MaxCol(),nCellPos,nTab ); for (i=0; i(nCellPos)); aRange.aEnd.SetCol(static_cast(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(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 SAL_CALL ScCellRangesBase::queryColumnDifferences( const table::CellAddress& aCompare ) { SolarMutexGuard aGuard; return QueryDifferences_Impl( aCompare, true ); } uno::Reference SAL_CALL ScCellRangesBase::queryRowDifferences( const table::CellAddress& aCompare ) { SolarMutexGuard aGuard; return QueryDifferences_Impl( aCompare, false ); } uno::Reference SAL_CALL ScCellRangesBase::queryIntersection( const table::CellRangeAddress& aRange ) { SolarMutexGuard aGuard; ScRange aMask( static_cast(aRange.StartColumn), static_cast(aRange.StartRow), aRange.Sheet, static_cast(aRange.EndColumn), static_cast(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 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 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 SAL_CALL ScCellRangesBase::createSearchDescriptor() { return new ScCellSearchObj; } uno::Reference SAL_CALL ScCellRangesBase::findAll( const uno::Reference& xDesc ) { SolarMutexGuard aGuard; // should we return Null if nothing is found(?) uno::Reference xRet; if ( pDocShell && xDesc.is() ) { ScCellSearchObj* pSearch = dynamic_cast( xDesc.get() ); 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 bMatchedRangesWereClamped = false; bool bFound = rDoc.SearchAndReplace( *pSearchItem, nCol, nRow, nTab, aMark, aMatchedRanges, aDummyUndo, nullptr, bMatchedRangesWereClamped); if (bFound) { // on findAll always CellRanges no matter how much has been found xRet.set(new ScCellRangesObj( pDocShell, aMatchedRanges )); } } } } return xRet; } uno::Reference ScCellRangesBase::Find_Impl( const uno::Reference& xDesc, const ScAddress* pLastPos ) { uno::Reference xRet; if ( pDocShell && xDesc.is() ) { ScCellSearchObj* pSearch = dynamic_cast( xDesc.get() ); 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 bMatchedRangesWereClamped; bool bFound = rDoc.SearchAndReplace( *pSearchItem, nCol, nRow, nTab, aMark, aMatchedRanges, aDummyUndo, nullptr, bMatchedRangesWereClamped); if (bFound) { ScAddress aFoundPos( nCol, nRow, nTab ); xRet.set(cppu::getXWeak(new ScCellObj( pDocShell, aFoundPos ))); } } } } return xRet; } uno::Reference SAL_CALL ScCellRangesBase::findFirst( const uno::Reference& xDesc ) { SolarMutexGuard aGuard; return Find_Impl( xDesc, nullptr ); } uno::Reference SAL_CALL ScCellRangesBase::findNext( const uno::Reference& xStartAt, const uno::Reference& xDesc ) { SolarMutexGuard aGuard; if ( xStartAt.is() ) { ScCellRangesBase* pRangesImp = dynamic_cast( xStartAt.get() ); 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 SAL_CALL ScCellRangesBase::createReplaceDescriptor() { return new ScCellSearchObj; } sal_Int32 SAL_CALL ScCellRangesBase::replaceAll( const uno::Reference& xDesc ) { SolarMutexGuard aGuard; sal_uInt64 nReplaced = 0; if ( pDocShell && xDesc.is() ) { ScCellSearchObj* pSearch = dynamic_cast( xDesc.get() ); 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 pUndoMark; if (bUndo) pUndoMark.reset(new ScMarkData(aMark)); bool bFound = false; if (bUndo) { ScRangeList aMatchedRanges; bool bMatchedRangesWereClamped; bFound = rDoc.SearchAndReplace( *pSearchItem, nCol, nRow, nTab, aMark, aMatchedRanges, aUndoStr, pUndoDoc.get(), bMatchedRangesWereClamped ); } if (bFound) { nReplaced = pUndoDoc->GetCellCount(); pDocShell->GetUndoManager()->AddUndoAction( std::make_unique( pDocShell, *pUndoMark, nCol, nRow, nTab, aUndoStr, std::move(pUndoDoc), pSearchItem ) ); pDocShell->PostPaintGridAll(); pDocShell->SetDocumentModified(); } } } } } return nReplaced; } 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 ) { uno::Any aReturn = ::cppu::queryInterface(rType, static_cast(this), static_cast(this), static_cast(this), static_cast(static_cast(this)), static_cast(this), static_cast(this), static_cast(this), static_cast(this)); if ( aReturn.hasValue() ) return aReturn; return ScCellRangesBase::queryInterface( rType ); } void SAL_CALL ScCellRangesObj::acquire() noexcept { ScCellRangesBase::acquire(); } void SAL_CALL ScCellRangesObj::release() noexcept { ScCellRangesBase::release(); } uno::Sequence SAL_CALL ScCellRangesObj::getTypes() { static const uno::Sequence aTypes = comphelper::concatSequences( ScCellRangesBase::getTypes(), uno::Sequence { cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get() } ); return aTypes; } uno::Sequence SAL_CALL ScCellRangesObj::getImplementationId() { return css::uno::Sequence(); } // XCellRanges rtl::Reference ScCellRangesObj::GetObjectByIndex_Impl(sal_Int32 nIndex) const { ScDocShell* pDocSh = GetDocShell(); const ScRangeList& rRanges = GetRangeList(); if ( pDocSh && nIndex >= 0 && nIndex < sal::static_int_cast(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 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 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 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(rRange.StartColumn), static_cast(rRange.StartRow), static_cast(rRange.Sheet), static_cast(rRange.EndColumn), static_cast(rRange.EndRow), static_cast(rRange.Sheet)); AddRange(aRange, bMergeRanges); } static void lcl_RemoveNamedEntry( std::vector& 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(rRange.StartColumn), static_cast(rRange.StartRow), static_cast(rRange.Sheet), static_cast(rRange.EndColumn), static_cast(rRange.EndRow), static_cast(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& rRanges, sal_Bool bMergeRanges ) { SolarMutexGuard aGuard; for (const table::CellRangeAddress& rRange : rRanges) { ScRange aRange(static_cast(rRange.StartColumn), static_cast(rRange.StartRow), static_cast(rRange.Sheet), static_cast(rRange.EndColumn), static_cast(rRange.EndRow), static_cast(rRange.Sheet)); AddRange(aRange, bMergeRanges); } } void SAL_CALL ScCellRangesObj::removeRangeAddresses( const uno::Sequence& rRangeSeq ) { // use sometimes a better/faster implementation for (const table::CellRangeAddress& rRange : rRangeSeq) { removeRangeAddress(rRange); } } // XNameContainer static void lcl_RemoveNamedEntry( std::vector& 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 xInterface(aElement, uno::UNO_QUERY); if ( pDocSh && xInterface.is() ) { ScCellRangesBase* pRangesImp = dynamic_cast( xInterface.get() ); 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& 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; nGetSheetLimits()); 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 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& rNamedEntries, const ScRange& rRange, OUString& rName ) { sal_uInt16 nCount = rNamedEntries.size(); for (sal_uInt16 i=0; i 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 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 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 xRange(GetObjectByIndex_Impl(nIndex)); if (!xRange.is()) throw lang::IndexOutOfBoundsException(); return uno::Any(xRange); } uno::Type SAL_CALL ScCellRangesObj::getElementType() { return cppu::UnoType::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 SAL_CALL ScCellRangesObj::getSupportedServiceNames() { return {SCSHEETCELLRANGES_SERVICE, SCCELLPROPERTIES_SERVICE, SCCHARPROPERTIES_SERVICE, SCPARAPROPERTIES_SERVICE}; } uno::Reference ScCellRangeObj::CreateRangeFromDoc( const ScDocument& rDoc, const ScRange& rR ) { if ( ScDocShell* pDocShell = rDoc.GetDocumentShell() ) 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 ) { uno::Any aReturn = ::cppu::queryInterface(rType, static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this)); if ( aReturn.hasValue() ) return aReturn; return ScCellRangesBase::queryInterface( rType ); } void SAL_CALL ScCellRangeObj::acquire() noexcept { ScCellRangesBase::acquire(); } void SAL_CALL ScCellRangeObj::release() noexcept { ScCellRangesBase::release(); } uno::Sequence SAL_CALL ScCellRangeObj::getTypes() { static const uno::Sequence aTypes = comphelper::concatSequences( ScCellRangesBase::getTypes(), uno::Sequence { cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get() } ); return aTypes; } uno::Sequence SAL_CALL ScCellRangeObj::getImplementationId() { return css::uno::Sequence(); } // XCellRange // ColumnCount / RowCount vanished //! are used in Writer for tables ??? uno::Reference 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(nPosX), static_cast(nPosY), aRange.aStart.Tab() ); return new ScCellObj( pDocSh, aNew ); } } throw lang::IndexOutOfBoundsException(); } uno::Reference SAL_CALL ScCellRangeObj::getCellByPosition( sal_Int32 nColumn, sal_Int32 nRow ) { SolarMutexGuard aGuard; return GetCellByPosition_Impl(nColumn, nRow); } uno::Reference 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(nStartX), static_cast(nStartY), aRange.aStart.Tab(), static_cast(nEndX), static_cast(nEndY), aRange.aEnd.Tab() ); return new ScCellRangeObj( pDocSh, aNew ); } } throw lang::IndexOutOfBoundsException(); } uno::Reference SAL_CALL ScCellRangeObj::getCellRangeByName( const OUString& aName ) { return getCellRangeByName( aName, ScAddress::detailsOOOa1 ); } uno::Reference 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 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 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 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.getType() == CELLTYPE_FORMULA && aCell2.getType() == CELLTYPE_FORMULA) { const ScFormulaCell* pFCell1 = aCell1.getFormula(); const ScFormulaCell* pFCell2 = aCell2.getFormula(); 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 ( dynamic_cast( 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 SAL_CALL ScCellRangeObj::getArrayTokens() { SolarMutexGuard aGuard; // same cell logic as in getArrayFormula uno::Sequence aSequence; ScDocShell* pDocSh = GetDocShell(); if (!pDocSh) return aSequence; ScDocument& rDoc = pDocSh->GetDocument(); ScRefCellValue aCell1(rDoc, aRange.aStart); ScRefCellValue aCell2(rDoc, aRange.aEnd); if (aCell1.getType() == CELLTYPE_FORMULA && aCell2.getType() == CELLTYPE_FORMULA) { const ScFormulaCell* pFCell1 = aCell1.getFormula(); const ScFormulaCell* pFCell2 = aCell2.getFormula(); 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& rTokens ) { SolarMutexGuard aGuard; ScDocShell* pDocSh = GetDocShell(); if ( !pDocSh ) return; if ( rTokens.hasElements() ) { if ( dynamic_cast( 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 > SAL_CALL ScCellRangeObj::getDataArray() { SolarMutexGuard aGuard; if ( dynamic_cast( 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 > aSeq; if ( aAny >>= aSeq ) return aSeq; // success } } throw uno::RuntimeException(); // no other exceptions specified } void SAL_CALL ScCellRangeObj::setDataArray( const uno::Sequence< uno::Sequence >& 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 > SAL_CALL ScCellRangeObj::getFormulaArray() { SolarMutexGuard aGuard; if ( dynamic_cast( 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 > aRowSeq( nRowCount ); uno::Sequence* pRowAry = aRowSeq.getArray(); for (SCROW nRowIndex = 0; nRowIndex < nRowCount; nRowIndex++) { uno::Sequence 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 >& 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(aFormulaRange.StartColumn), static_cast(aFormulaRange.StartRow), aFormulaRange.Sheet ); aParam.aRefFormulaEnd = ScRefAddress( static_cast(aFormulaRange.EndColumn), static_cast(aFormulaRange.EndRow), aFormulaRange.Sheet ); aParam.aRefRowCell = ScRefAddress( static_cast(aRowCell.Column), static_cast(aRowCell.Row), aRowCell.Sheet ); aParam.aRefColCell = ScRefAddress( static_cast(aColumnCell.Column), static_cast(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( 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( 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( 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( 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 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(aDBRange.aStart.Col()) : static_cast(aDBRange.aStart.Row()); for (sal_uInt16 i=0; i= nFieldStart ) aParam.maKeyState[i].nField -= nFieldStart; } } uno::Sequence aSeq( ScSortDescriptor::GetPropertyCount() ); ScSortDescriptor::FillProperties( aSeq, aParam ); return aSeq; } void SAL_CALL ScCellRangeObj::sort( const uno::Sequence& 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(aRange.aStart.Col()) : static_cast(aRange.aStart.Row()); for (i=0; i= 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(aRange.aStart.Col()) : static_cast(aRange.aStart.Row()); SCCOLROW nFieldEnd = aParam.bByRow ? static_cast(aRange.aEnd.Col()) : static_cast(aRange.aEnd.Row()); for (i=0; i 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 SAL_CALL ScCellRangeObj::createFilterDescriptor( sal_Bool bEmpty ) { SolarMutexGuard aGuard; ScDocShell* pDocSh = GetDocShell(); rtl::Reference 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(aDBRange.aStart.Col()) : static_cast(aDBRange.aStart.Row()); SCSIZE nCount = aParam.GetEntryCount(); for (SCSIZE i=0; i= nFieldStart) rEntry.nField -= nFieldStart; } pNew->SetParam(aParam); } } return pNew; } void SAL_CALL ScCellRangeObj::filter( const uno::Reference& 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 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 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(aRange.aStart.Col()) : static_cast(aRange.aStart.Row()); SCSIZE nCount = aParam.GetEntryCount(); svl::SharedStringPool& rPool = pDocSh->GetDocument().GetSharedStringPool(); for (SCSIZE i=0; i 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 SAL_CALL ScCellRangeObj::createFilterDescriptorByObject( const uno::Reference& xObject ) { SolarMutexGuard aGuard; // this here is not the area, which will be filtered, instead the area // with the query uno::Reference 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 pNew(new ScFilterDescriptor(pDocSh)); //! instead from object? ScQueryParam aParam = pNew->GetParam(); aParam.bHasHeader = true; table::CellRangeAddress aDataAddress(xAddr->getRangeAddress()); aParam.nCol1 = static_cast(aDataAddress.StartColumn); aParam.nRow1 = static_cast(aDataAddress.StartRow); aParam.nCol2 = static_cast(aDataAddress.EndColumn); aParam.nRow2 = static_cast(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(aDataAddress.StartColumn) : static_cast(aDataAddress.StartRow); SCSIZE nCount = aParam.GetEntryCount(); for (SCSIZE i=0; i= nFieldStart) rEntry.nField -= nFieldStart; } pNew->SetParam( aParam ); return pNew; } // XSubTotalSource uno::Reference SAL_CALL ScCellRangeObj::createSubTotalDescriptor( sal_Bool bEmpty ) { SolarMutexGuard aGuard; rtl::Reference 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= nFieldStart ) aParam.nField[i] = sal::static_int_cast( aParam.nField[i] - nFieldStart ); for (SCCOL j=0; j= nFieldStart ) aParam.pSubTotals[i][j] = sal::static_int_cast( aParam.pSubTotals[i][j] - nFieldStart ); } } pNew->SetParam(aParam); } } return pNew; } void SAL_CALL ScCellRangeObj::applySubTotals( const uno::Reference& xDescriptor, sal_Bool bReplace) { SolarMutexGuard aGuard; if (!xDescriptor.is()) return; ScDocShell* pDocSh = GetDocShell(); ScSubTotalDescriptorBase* pImp = dynamic_cast( xDescriptor.get() ); 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( aParam.nField[i] + nFieldStart ); for (SCCOL j=0; j( 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 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 aSeq( ScImportDescriptor::GetPropertyCount() ); ScImportDescriptor::FillProperties( aSeq, aParam ); return aSeq; } void SAL_CALL ScCellRangeObj::doImport( const uno::Sequence& 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 SAL_CALL ScCellRangeObj::getCellFormatRanges() { SolarMutexGuard aGuard; ScDocShell* pDocSh = GetDocShell(); if ( pDocSh ) return new ScCellFormatsObj( pDocSh, aRange ); return nullptr; } // XUniqueCellFormatRangesSupplier uno::Reference 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 SAL_CALL ScCellRangeObj::getPropertySetInfo() { SolarMutexGuard aGuard; static uno::Reference 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 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 (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 ) { uno::Any aReturn = ::cppu::queryInterface(rType, static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this)); if ( aReturn.hasValue() ) return aReturn; return ScCellRangeObj::queryInterface( rType ); } void SAL_CALL ScCellObj::acquire() noexcept { ScCellRangeObj::acquire(); } void SAL_CALL ScCellObj::release() noexcept { ScCellRangeObj::release(); } uno::Sequence SAL_CALL ScCellObj::getTypes() { static const uno::Sequence aTypes = comphelper::concatSequences( ScCellRangeObj::getTypes(), uno::Sequence { cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get() } ); return aTypes; } uno::Sequence SAL_CALL ScCellObj::getImplementationId() { return css::uno::Sequence(); } // 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(); ScInterpreterContext& rContext = rDoc.GetNonThreadedContext(); sal_uInt32 nOldFormat = rDoc.GetNumberFormat( aCellPos ); if (rContext.NFGetType(nOldFormat) == SvNumFormatType::TEXT) { SetString_Impl(rText, false, false); // text cell return; } ScDocFunc &rFunc = pDocSh->GetDocFunc(); ScInputStringType aRes = ScStringUtil::parseInputString(rContext, 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(rContext, nOldFormat, aRes.mnFormatType); if (nNewFormat != nOldFormat) { ScPatternAttr aPattern(rDoc.getCellAttributeHelper()); 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 SAL_CALL ScCellObj::createTextCursor() { SolarMutexGuard aGuard; return new ScCellTextCursor( *this ); } uno::Reference SAL_CALL ScCellObj::createTextCursorByRange( const uno::Reference& aTextPosition ) { SolarMutexGuard aGuard; rtl::Reference pCursor = new ScCellTextCursor( *this ); SvxUnoTextRangeBase* pRange = comphelper::getFromUnoTunnel( aTextPosition ); if(pRange) pCursor->SetSelection( pRange->GetSelection() ); else { ScCellTextCursor* pOther = comphelper::getFromUnoTunnel( 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& 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& xRange, sal_Int16 nControlCharacter, sal_Bool bAbsorb ) { SolarMutexGuard aGuard; GetUnoText().insertControlCharacter(xRange, nControlCharacter, bAbsorb); } void SAL_CALL ScCellObj::insertTextContent( const uno::Reference& xRange, const uno::Reference& xContent, sal_Bool bAbsorb ) { SolarMutexGuard aGuard; ScDocShell* pDocSh = GetDocShell(); if ( pDocSh && xContent.is() ) { ScEditFieldObj* pCellField = dynamic_cast(xContent.get()); SvxUnoTextRangeBase* pTextRange = comphelper::getFromUnoTunnel( 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 xParent(this); pCellField->InitDoc( xParent, std::make_unique(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& xContent ) { SolarMutexGuard aGuard; if ( xContent.is() ) { ScEditFieldObj* pCellField = dynamic_cast(xContent.get()); if ( pCellField && pCellField->IsInserted() ) { //! Check if field is in this cell pCellField->DeleteField(); return; } } GetUnoText().removeTextContent(xContent); } uno::Reference SAL_CALL ScCellObj::getText() { return this; } uno::Reference SAL_CALL ScCellObj::getStart() { SolarMutexGuard aGuard; return GetUnoText().getStart(); } uno::Reference SAL_CALL ScCellObj::getEnd() { SolarMutexGuard aGuard; return GetUnoText().getEnd(); } uno::Reference 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.getType() == CELLTYPE_FORMULA) { ScFormulaCell* pCell = aCell.getFormula(); 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.getType() == CELLTYPE_FORMULA) { bool bValue = aCell.getFormula()->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.getType() == CELLTYPE_FORMULA) nError = aCell.getFormula()->GetErrCode(); return static_cast(nError); } // XFormulaTokens uno::Sequence SAL_CALL ScCellObj::getTokens() { SolarMutexGuard aGuard; uno::Sequence aSequence; ScDocShell* pDocSh = GetDocShell(); if (!pDocSh) return aSequence; ScDocument& rDoc = pDocSh->GetDocument(); ScRefCellValue aCell(rDoc, aCellPos); if (aCell.getType() == CELLTYPE_FORMULA) { ScTokenArray* pTokenArray = aCell.getFormula()->GetCode(); if (pTokenArray) ScTokenConversion::ConvertToTokenSequence(rDoc, aSequence, *pTokenArray); } return aSequence; } void SAL_CALL ScCellObj::setTokens( const uno::Sequence& 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 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 SAL_CALL ScCellObj::getTextFields() { SolarMutexGuard aGuard; ScDocShell* pDocSh = GetDocShell(); if ( pDocSh ) { uno::Reference xContent(this); return new ScCellFieldsObj(xContent, pDocSh, aCellPos); } return nullptr; } uno::Reference SAL_CALL ScCellObj::getTextFieldMasters() { // there is no such thing in Calc (?) return nullptr; } // XPropertySet extended for Cell-Properties uno::Reference SAL_CALL ScCellObj::getPropertySetInfo() { SolarMutexGuard aGuard; static uno::Reference 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 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 (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 (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 (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 (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 ) { uno::Any aReturn = ::cppu::queryInterface(rType, static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this), static_cast(this)); if ( aReturn.hasValue() ) return aReturn; return ScCellRangeObj::queryInterface( rType ); } void SAL_CALL ScTableSheetObj::acquire() noexcept { ScCellRangeObj::acquire(); } void SAL_CALL ScTableSheetObj::release() noexcept { ScCellRangeObj::release(); } uno::Sequence SAL_CALL ScTableSheetObj::getTypes() { static const uno::Sequence aTypes = comphelper::concatSequences( ScCellRangeObj::getTypes(), uno::Sequence { cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get() } ); return aTypes; } uno::Sequence SAL_CALL ScTableSheetObj::getImplementationId() { return css::uno::Sequence(); } // 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 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 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 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 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 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 SAL_CALL ScTableSheetObj::getCellRangeByName( const OUString& rRange ) { SolarMutexGuard aGuard; return ScCellRangeObj::getCellRangeByName( rRange ); } uno::Reference 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 SAL_CALL ScTableSheetObj::createCursorByRange( const uno::Reference& xCellRange ) { SolarMutexGuard aGuard; ScDocShell* pDocSh = GetDocShell(); if ( pDocSh && xCellRange.is() ) { ScCellRangesBase* pRangesImp = dynamic_cast( xCellRange.get() ); 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 SAL_CALL ScTableSheetObj::getSpreadsheet() { return this; //!??? } // XCellRange uno::Reference SAL_CALL ScTableSheetObj::getCellByPosition( sal_Int32 nColumn, sal_Int32 nRow ) { SolarMutexGuard aGuard; return ScCellRangeObj::GetCellByPosition_Impl(nColumn, nRow); } uno::Reference 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 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 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 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( 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 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(nTab)); OSL_ENSURE(pPage,"Draw-Page not found"); if (pPage) return uno::Reference (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(aDestination.Column), static_cast(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(aDestination.Column), static_cast(aDestination.Row), aDestination.Sheet ); (void)pDocSh->GetDocFunc().MoveBlock( aSourceRange, aDestPos, false, true, true, true ); } } // XPrintAreas void ScTableSheetObj::PrintAreaUndo_Impl( std::unique_ptr 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( 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 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 aSeq(nCount); table::CellRangeAddress* pAry = aSeq.getArray(); for (sal_uInt16 i=0; i(); } void SAL_CALL ScTableSheetObj::setPrintAreas( const uno::Sequence& aPrintAreas ) { SolarMutexGuard aGuard; ScDocShell* pDocSh = GetDocShell(); if ( !pDocSh ) return; std::unique_ptr pOldRanges; ScDocument& rDoc = pDocSh->GetDocument(); SCTAB nTab = GetTab_Impl(); if ( rDoc.IsUndoEnabled() ) pOldRanges = rDoc.CreatePrintRangeSaver(); sal_uInt16 nCount = static_cast(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 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 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 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 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 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 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; iGetLinks()[i].get(); if (auto pTabLink = dynamic_cast( 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(aPosition.Column), static_cast(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(aPosition.Column), static_cast(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(aPosition.Column), static_cast(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(aPosition.Column), static_cast(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(aPosition.Column), static_cast(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& 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(rRange.StartColumn), static_cast(rRange.StartRow), nTab, static_cast(rRange.EndColumn), static_cast(rRange.EndRow), nTab ); aMarkData.SetMultiMarkArea( aOneRange ); } // Scenario ranges are tagged with attribute ScPatternAttr aPattern(rDoc.getCellAttributeHelper()); 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 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 SAL_CALL ScTableSheetObj::getPropertySetInfo() { SolarMutexGuard aGuard; static uno::Reference 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 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(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(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 SAL_CALL ScTableSheetObj::getSupportedServiceNames() { return {SCSPREADSHEET_SERVICE, SCSHEETCELLRANGE_SERVICE, SCCELLRANGE_SERVICE, SCCELLPROPERTIES_SERVICE, SCCHARPROPERTIES_SERVICE, SCPARAPROPERTIES_SERVICE, SCLINKTARGET_SERVICE}; } 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 ) { uno::Any aReturn = ::cppu::queryInterface(rType, static_cast(this)); if ( aReturn.hasValue() ) return aReturn; return ScCellRangeObj::queryInterface( rType ); } void SAL_CALL ScTableColumnObj::acquire() noexcept { ScCellRangeObj::acquire(); } void SAL_CALL ScTableColumnObj::release() noexcept { ScCellRangeObj::release(); } uno::Sequence SAL_CALL ScTableColumnObj::getTypes() { return comphelper::concatSequences( ScCellRangeObj::getTypes(), uno::Sequence { cppu::UnoType::get() } ); } uno::Sequence SAL_CALL ScTableColumnObj::getImplementationId() { return css::uno::Sequence(); } // 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 SAL_CALL ScTableColumnObj::getPropertySetInfo() { SolarMutexGuard aGuard; static uno::Reference 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 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(convertTwipToMm100(nWidth)); rAny <<= static_cast(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 SAL_CALL ScTableRowObj::getPropertySetInfo() { SolarMutexGuard aGuard; static uno::Reference 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 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(convertTwipToMm100(nHeight)); rAny <<= static_cast(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, ScRangeList aR) : pDocShell( pDocSh ), aRanges(std::move( aR )) { 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(&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 SAL_CALL ScCellsObj::createEnumeration() { SolarMutexGuard aGuard; if (pDocShell) return new ScCellsEnumeration( pDocShell, aRanges ); return nullptr; } uno::Type SAL_CALL ScCellsObj::getElementType() { return cppu::UnoType::get(); } sal_Bool SAL_CALL ScCellsObj::hasElements() { SolarMutexGuard aGuard; bool bHas = false; if ( pDocShell ) { //! faster if test ourself? uno::Reference xEnum(new ScCellsEnumeration( pDocShell, aRanges )); bHas = xEnum->hasMoreElements(); } return bHas; } ScCellsEnumeration::ScCellsEnumeration(ScDocShell* pDocSh, ScRangeList aR) : pDocShell( pDocSh ), aRanges(std::move( aR )), 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(&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(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(&rHint) ) { //! aTotalRange... } else if ( rHint.GetId() == SfxHintId::Dying ) { pDocShell = nullptr; } } rtl::Reference 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 xRange(GetObjectByIndex_Impl(nIndex)); if (!xRange.is()) throw lang::IndexOutOfBoundsException(); return uno::Any(xRange); } uno::Type SAL_CALL ScCellFormatsObj::getElementType() { return cppu::UnoType::get(); } sal_Bool SAL_CALL ScCellFormatsObj::hasElements() { SolarMutexGuard aGuard; return ( getCount() != 0 ); //! always greater then zero ?? } // XEnumerationAccess uno::Reference 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 ScCellFormatsEnumeration::NextObject_Impl() { rtl::Reference 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(&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 (NextObject_Impl())); } ScUniqueCellFormatsObj::~ScUniqueCellFormatsObj() { SolarMutexGuard g; if (pDocShell) pDocShell->GetDocument().RemoveUnoObject(*this); } void ScUniqueCellFormatsObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) { if ( dynamic_cast(&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(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 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(new ScCellRangesObj(pDocShell, aRangeLists[nIndex]))); } uno::Type SAL_CALL ScUniqueCellFormatsObj::getElementType() { return cppu::UnoType::get(); } sal_Bool SAL_CALL ScUniqueCellFormatsObj::hasElements() { SolarMutexGuard aGuard; return ( !aRangeLists.empty() ); } // XEnumerationAccess uno::Reference SAL_CALL ScUniqueCellFormatsObj::createEnumeration() { SolarMutexGuard aGuard; if (pDocShell) return new ScUniqueCellFormatsEnumeration( pDocShell, std::vector(aRangeLists) ); return nullptr; } ScUniqueCellFormatsEnumeration::ScUniqueCellFormatsEnumeration(ScDocShell* pDocSh, std::vector&& 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(&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(new ScCellRangesObj(pDocShell, aRangeLists[nCurrentPosition++]))); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */