1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 #include <ooo/vba/excel/XRange.hpp> 25 #include <com/sun/star/sheet/XCellRangeAddressable.hpp> 26 #include <com/sun/star/sheet/XSheetConditionalEntry.hpp> 27 #include <vector> 28 #include "vbaformatconditions.hxx" 29 #include "vbaformatcondition.hxx" 30 #include "vbaworkbook.hxx" 31 #include "vbastyles.hxx" 32 #include "vbaglobals.hxx" 33 using namespace ::ooo::vba; 34 using namespace ::com::sun::star; 35 36 typedef std::vector< beans::PropertyValue > VecPropValues; 37 38 static rtl::OUString OPERATOR( RTL_CONSTASCII_USTRINGPARAM("Operator") ); 39 static rtl::OUString FORMULA1( RTL_CONSTASCII_USTRINGPARAM("Formula1") ); 40 static rtl::OUString FORMULA2( RTL_CONSTASCII_USTRINGPARAM("Formula2") ); 41 static rtl::OUString STYLENAME( RTL_CONSTASCII_USTRINGPARAM("StyleName") ); 42 static rtl::OUString sStyleNamePrefix( RTL_CONSTASCII_USTRINGPARAM("Excel_CondFormat") ); 43 44 ScVbaFormatConditions::ScVbaFormatConditions( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext > & xContext, const uno::Reference< sheet::XSheetConditionalEntries >& _xSheetConditionalEntries, const uno::Reference< frame::XModel >& /*xModel*/ ) : ScVbaFormatConditions_BASE( xParent, xContext, uno::Reference< container::XIndexAccess >( _xSheetConditionalEntries, uno::UNO_QUERY_THROW ) ), mxSheetConditionalEntries( _xSheetConditionalEntries ) 45 { 46 mxRangeParent.set( xParent, uno::UNO_QUERY_THROW ); 47 uno::Reference< excel::XApplication> xApp( Application(), uno::UNO_QUERY_THROW ); 48 mxStyles.set( xApp->getThisWorkbook()->Styles( uno::Any() ), uno::UNO_QUERY_THROW ); 49 uno::Reference< sheet::XCellRangeAddressable > xCellRange( mxRangeParent->getCellRange(), uno::UNO_QUERY_THROW ); 50 mxParentRangePropertySet.set( xCellRange, uno::UNO_QUERY_THROW ); 51 52 table::CellRangeAddress rangeAddress = xCellRange->getRangeAddress(); 53 maCellAddress = table::CellAddress( rangeAddress.Sheet, rangeAddress.StartColumn, rangeAddress.StartRow ); 54 } 55 56 void SAL_CALL 57 ScVbaFormatConditions::Delete( ) throw (script::BasicErrorException, uno::RuntimeException) 58 { 59 try 60 { 61 ScVbaStyles* pStyles = static_cast< ScVbaStyles* >( mxStyles.get() ); 62 if ( !pStyles ) 63 DebugHelper::exception(SbERR_METHOD_FAILED, rtl::OUString() ); 64 sal_Int32 nCount = mxSheetConditionalEntries->getCount(); 65 for (sal_Int32 i = nCount - 1; i >= 0; i--) 66 { 67 uno::Reference< sheet::XSheetConditionalEntry > xSheetConditionalEntry( mxSheetConditionalEntries->getByIndex(i), uno::UNO_QUERY_THROW ); 68 pStyles->Delete(xSheetConditionalEntry->getStyleName()); 69 mxSheetConditionalEntries->removeByIndex(i); 70 } 71 notifyRange(); 72 } 73 catch (uno::Exception& ) 74 { 75 DebugHelper::exception(SbERR_METHOD_FAILED, rtl::OUString()); 76 } 77 } 78 79 uno::Type SAL_CALL 80 ScVbaFormatConditions::getElementType() throw (css::uno::RuntimeException) 81 { 82 return excel::XFormatCondition::static_type(0); 83 } 84 85 86 uno::Any xSheetConditionToFormatCondition( const uno::Reference< XHelperInterface >& xRangeParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< excel::XStyles >& xStyles, const uno::Reference< excel::XFormatConditions >& xFormatConditions, const uno::Reference< beans::XPropertySet >& xRangeProps, const uno::Any& aObject ) 87 { 88 uno::Reference< sheet::XSheetConditionalEntry > xSheetConditionalEntry; 89 aObject >>= xSheetConditionalEntry; 90 91 uno::Reference< excel::XStyle > xStyle( xStyles->Item( uno::makeAny( xSheetConditionalEntry->getStyleName() ), uno::Any() ), uno::UNO_QUERY_THROW ); 92 uno::Reference< excel::XFormatCondition > xCondition = new ScVbaFormatCondition( xRangeParent, xContext, xSheetConditionalEntry, xStyle, xFormatConditions, xRangeProps ); 93 return uno::makeAny( xCondition ); 94 } 95 96 uno::Any 97 ScVbaFormatConditions::createCollectionObject(const uno::Any& aObject ) 98 { 99 return xSheetConditionToFormatCondition( uno::Reference< XHelperInterface >( mxRangeParent, uno::UNO_QUERY_THROW ), mxContext, mxStyles, this, mxParentRangePropertySet, aObject ); 100 } 101 102 class EnumWrapper : public EnumerationHelper_BASE 103 { 104 uno::Reference<container::XIndexAccess > m_xIndexAccess; 105 uno::Reference<excel::XRange > m_xParentRange; 106 uno::Reference<uno::XComponentContext > m_xContext; 107 uno::Reference<excel::XStyles > m_xStyles; 108 uno::Reference<excel::XFormatConditions > m_xParentCollection; 109 uno::Reference<beans::XPropertySet > m_xProps; 110 111 sal_Int32 nIndex; 112 public: 113 EnumWrapper( const uno::Reference< container::XIndexAccess >& xIndexAccess, const uno::Reference<excel::XRange >& xRange, const uno::Reference<uno::XComponentContext >& xContext, const uno::Reference<excel::XStyles >& xStyles, const uno::Reference< excel::XFormatConditions >& xCollection, const uno::Reference<beans::XPropertySet >& xProps ) : m_xIndexAccess( xIndexAccess ), m_xParentRange( xRange ), m_xContext( xContext ), m_xStyles( xStyles ), m_xParentCollection( xCollection ), m_xProps( xProps ), nIndex( 0 ) {} 114 virtual ::sal_Bool SAL_CALL hasMoreElements( ) throw (uno::RuntimeException) 115 { 116 return ( nIndex < m_xIndexAccess->getCount() ); 117 } 118 119 virtual uno::Any SAL_CALL nextElement( ) throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException) 120 { 121 if ( nIndex < m_xIndexAccess->getCount() ) 122 return xSheetConditionToFormatCondition( uno::Reference< XHelperInterface >( m_xParentRange, uno::UNO_QUERY_THROW ), m_xContext, m_xStyles, m_xParentCollection, m_xProps, m_xIndexAccess->getByIndex( nIndex++ ) ); 123 throw container::NoSuchElementException(); 124 } 125 }; 126 127 uno::Reference< excel::XFormatCondition > SAL_CALL 128 ScVbaFormatConditions::Add( ::sal_Int32 _nType, const uno::Any& _aOperator, const uno::Any& _aFormula1, const uno::Any& _aFormula2 ) throw (script::BasicErrorException, uno::RuntimeException) 129 { 130 return Add( _nType, _aOperator, _aFormula1, _aFormula2, uno::Reference< excel::XStyle >() ); 131 } 132 133 uno::Reference< excel::XFormatCondition > 134 ScVbaFormatConditions::Add( ::sal_Int32 _nType, const uno::Any& _aOperator, const uno::Any& _aFormula1, const uno::Any& _aFormula2, const css::uno::Reference< excel::XStyle >& _xStyle ) throw (script::BasicErrorException, uno::RuntimeException) 135 { 136 // #TODO 137 // #FIXME 138 // This method will NOT handle r1c1 formulas [*]and only assumes that 139 // the formulas are _xlA1 based ( need to hook into calc work ths should 140 // address this ) 141 // [*] reason: getA1Formula method below is just a hook and just 142 // returns whats it gets ( e.g. doesn't convert anything ) 143 uno::Reference< excel::XStyle > xStyle( _xStyle ); 144 uno::Reference< excel::XFormatCondition > xFormatCondition; 145 try 146 { 147 rtl::OUString sStyleName; 148 if ( !xStyle.is() ) 149 { 150 sStyleName = getStyleName(); 151 xStyle = mxStyles->Add(sStyleName, uno::Any() ); 152 } 153 else 154 { 155 sStyleName = xStyle->getName(); 156 } 157 158 VecPropValues aPropertyValueVector; 159 sheet::ConditionOperator aType = ScVbaFormatCondition::retrieveAPIType(_nType, uno::Reference< sheet::XSheetCondition >() ); 160 uno::Any aValue; 161 162 if ( aType == sheet::ConditionOperator_FORMULA) 163 aValue = uno::makeAny( sheet::ConditionOperator_FORMULA ); 164 else 165 aValue = uno::makeAny( ScVbaFormatCondition::retrieveAPIOperator(_aOperator) ); 166 167 beans::PropertyValue aProperty( OPERATOR, 0, aValue, beans::PropertyState_DIRECT_VALUE ); 168 aPropertyValueVector.push_back( aProperty ); 169 170 if ( _aFormula1.hasValue() ) 171 { 172 beans::PropertyValue aProp( FORMULA1, 0, uno::makeAny( getA1Formula( _aFormula1 ) ), beans::PropertyState_DIRECT_VALUE ); 173 aPropertyValueVector.push_back( aProp ); 174 } 175 if ( _aFormula2.hasValue() ) 176 { 177 beans::PropertyValue aProp( FORMULA2, 0, uno::makeAny( getA1Formula( _aFormula2 ) ), beans::PropertyState_DIRECT_VALUE ); 178 aPropertyValueVector.push_back( aProp ); 179 } 180 aProperty.Name = STYLENAME; 181 aProperty.Value = uno::makeAny( sStyleName ); 182 183 // convert vector to sequence 184 uno::Sequence< beans::PropertyValue > aPropertyValueList(aPropertyValueVector.size()); 185 VecPropValues::iterator it = aPropertyValueVector.begin(); 186 VecPropValues::iterator it_end = aPropertyValueVector.end(); 187 for ( sal_Int32 index=0; it != it_end; ++it ) 188 aPropertyValueList[ index++ ] = *it; 189 190 mxSheetConditionalEntries->addNew(aPropertyValueList); 191 for (sal_Int32 i = mxSheetConditionalEntries->getCount()-1; i >= 0; i--) 192 { 193 uno::Reference< sheet::XSheetConditionalEntry > xSheetConditionalEntry( mxSheetConditionalEntries->getByIndex(i), uno::UNO_QUERY_THROW ); 194 if (xSheetConditionalEntry->getStyleName().equals(sStyleName)) 195 { 196 xFormatCondition = new ScVbaFormatCondition(uno::Reference< XHelperInterface >( mxRangeParent, uno::UNO_QUERY_THROW ), mxContext, xSheetConditionalEntry, xStyle, this, mxParentRangePropertySet); 197 notifyRange(); 198 return xFormatCondition; 199 } 200 } 201 } 202 catch (uno::Exception& ) 203 { 204 } 205 DebugHelper::exception(SbERR_METHOD_FAILED, rtl::OUString() ); 206 return xFormatCondition; 207 } 208 209 210 uno::Reference< container::XEnumeration > SAL_CALL 211 ScVbaFormatConditions::createEnumeration() throw (uno::RuntimeException) 212 { 213 return new EnumWrapper( m_xIndexAccess, mxRangeParent, mxContext, mxStyles, this, mxParentRangePropertySet ); 214 } 215 216 217 void 218 ScVbaFormatConditions::notifyRange() throw ( script::BasicErrorException ) 219 { 220 try 221 { 222 mxParentRangePropertySet->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ConditionalFormat")), uno::makeAny( mxSheetConditionalEntries )); 223 } 224 catch (uno::Exception& ) 225 { 226 DebugHelper::exception(SbERR_METHOD_FAILED, rtl::OUString()); 227 } 228 } 229 230 rtl::OUString 231 ScVbaFormatConditions::getA1Formula(const css::uno::Any& _aFormula) throw ( script::BasicErrorException ) 232 { 233 // #TODO, #FIXME hook-in proper formula conversion detection & logic 234 rtl::OUString sFormula; 235 if ( !( _aFormula >>= sFormula ) ) 236 DebugHelper::exception(SbERR_BAD_PARAMETER, rtl::OUString() ); 237 return sFormula; 238 } 239 240 rtl::OUString 241 ScVbaFormatConditions::getStyleName() 242 { 243 ScVbaStyles* pStyles = static_cast< ScVbaStyles* >( mxStyles.get() ); 244 if ( !pStyles ) 245 DebugHelper::exception(SbERR_METHOD_FAILED, rtl::OUString() ); 246 uno::Sequence< rtl::OUString > sCellStyleNames = pStyles->getStyleNames(); 247 return ContainerUtilities::getUniqueName(sCellStyleNames, sStyleNamePrefix, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("_") )); 248 } 249 250 void 251 ScVbaFormatConditions::removeFormatCondition( const rtl::OUString& _sStyleName, sal_Bool _bRemoveStyle) throw ( script::BasicErrorException ) 252 { 253 try 254 { 255 sal_Int32 nElems = mxSheetConditionalEntries->getCount(); 256 for (sal_Int32 i = 0; i < nElems; i++) 257 { 258 uno::Reference< sheet::XSheetConditionalEntry > xSheetConditionalEntry( mxSheetConditionalEntries->getByIndex(i), uno::UNO_QUERY_THROW ); 259 if (_sStyleName.equals(xSheetConditionalEntry->getStyleName())) 260 { 261 mxSheetConditionalEntries->removeByIndex(i); 262 if (_bRemoveStyle) 263 { 264 ScVbaStyles* pStyles = static_cast< ScVbaStyles* >( mxStyles.get() ); 265 if ( !pStyles ) 266 DebugHelper::exception(SbERR_METHOD_FAILED, rtl::OUString()); 267 pStyles->Delete( _sStyleName ); 268 } 269 return; 270 } 271 } 272 } 273 catch (uno::Exception& ) 274 { 275 DebugHelper::exception(SbERR_METHOD_FAILED, rtl::OUString()); 276 } 277 } 278 279 rtl::OUString& 280 ScVbaFormatConditions::getServiceImplName() 281 { 282 static rtl::OUString sImplName( RTL_CONSTASCII_USTRINGPARAM("ScVbaFormatConditions") ); 283 return sImplName; 284 } 285 286 uno::Sequence< rtl::OUString > 287 ScVbaFormatConditions::getServiceNames() 288 { 289 static uno::Sequence< rtl::OUString > aServiceNames; 290 if ( aServiceNames.getLength() == 0 ) 291 { 292 aServiceNames.realloc( 1 ); 293 aServiceNames[ 0 ] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ooo.vba.excel.FormatConditions" ) ); 294 } 295 return aServiceNames; 296 } 297 298