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