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 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_sc.hxx" 26 27 28 29 #include <com/sun/star/table/CellAddress.hpp> 30 #include <com/sun/star/table/CellRangeAddress.hpp> 31 32 #include <svl/itemprop.hxx> 33 34 #include "docsh.hxx" 35 #include "unonames.hxx" 36 #include "unoguard.hxx" 37 #include "miscuno.hxx" 38 #include "convuno.hxx" 39 #include "addruno.hxx" 40 41 using namespace com::sun::star; 42 43 //------------------------------------------------------------------------ 44 45 ScAddressConversionObj::ScAddressConversionObj(ScDocShell* pDocSh, sal_Bool bForRange) : 46 pDocShell( pDocSh ), 47 nRefSheet( 0 ), 48 bIsRange( bForRange ) 49 { 50 pDocShell->GetDocument()->AddUnoObject(*this); 51 } 52 53 ScAddressConversionObj::~ScAddressConversionObj() 54 { 55 if (pDocShell) 56 pDocShell->GetDocument()->RemoveUnoObject(*this); 57 } 58 59 void ScAddressConversionObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) 60 { 61 if ( rHint.ISA( SfxSimpleHint ) && 62 ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) 63 { 64 pDocShell = NULL; // invalid 65 } 66 } 67 68 sal_Bool ScAddressConversionObj::ParseUIString( const String& rUIString, ::formula::FormulaGrammar::AddressConvention eConv ) 69 { 70 if (!pDocShell) 71 return sal_False; 72 73 ScDocument* pDoc = pDocShell->GetDocument(); 74 sal_Bool bSuccess = sal_False; 75 if ( bIsRange ) 76 { 77 sal_uInt16 nResult = aRange.ParseAny( rUIString, pDoc, eConv ); 78 if ( nResult & SCA_VALID ) 79 { 80 if ( ( nResult & SCA_TAB_3D ) == 0 ) 81 aRange.aStart.SetTab( static_cast<SCTAB>(nRefSheet) ); 82 if ( ( nResult & SCA_TAB2_3D ) == 0 ) 83 aRange.aEnd.SetTab( aRange.aStart.Tab() ); 84 // different sheets are not supported in CellRangeAddress 85 if ( aRange.aStart.Tab() == aRange.aEnd.Tab() ) 86 bSuccess = sal_True; 87 } 88 } 89 else 90 { 91 sal_uInt16 nResult = aRange.aStart.Parse( rUIString, pDoc, eConv ); 92 if ( nResult & SCA_VALID ) 93 { 94 if ( ( nResult & SCA_TAB_3D ) == 0 ) 95 aRange.aStart.SetTab( static_cast<SCTAB>(nRefSheet) ); 96 bSuccess = sal_True; 97 } 98 } 99 return bSuccess; 100 } 101 102 // XPropertySet 103 104 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScAddressConversionObj::getPropertySetInfo() 105 throw(uno::RuntimeException) 106 { 107 ScUnoGuard aGuard; 108 109 if ( bIsRange ) 110 { 111 static SfxItemPropertyMapEntry aPropertyMap[] = 112 { 113 {MAP_CHAR_LEN(SC_UNONAME_ADDRESS), 0, &getCppuType((table::CellRangeAddress*)0), 0, 0 }, 114 {MAP_CHAR_LEN(SC_UNONAME_PERSREPR), 0, &getCppuType((rtl::OUString*)0), 0, 0 }, 115 {MAP_CHAR_LEN(SC_UNONAME_REFSHEET), 0, &getCppuType((sal_Int32*)0), 0, 0 }, 116 {MAP_CHAR_LEN(SC_UNONAME_UIREPR), 0, &getCppuType((rtl::OUString*)0), 0, 0 }, 117 {MAP_CHAR_LEN(SC_UNONAME_XLA1REPR), 0, &getCppuType((rtl::OUString*)0), 0, 0 }, 118 {0,0,0,0,0,0} 119 }; 120 static uno::Reference<beans::XPropertySetInfo> aRef(new SfxItemPropertySetInfo( aPropertyMap )); 121 return aRef; 122 } 123 else 124 { 125 static SfxItemPropertyMapEntry aPropertyMap[] = 126 { 127 {MAP_CHAR_LEN(SC_UNONAME_ADDRESS), 0, &getCppuType((table::CellAddress*)0), 0, 0 }, 128 {MAP_CHAR_LEN(SC_UNONAME_PERSREPR), 0, &getCppuType((rtl::OUString*)0), 0, 0 }, 129 {MAP_CHAR_LEN(SC_UNONAME_REFSHEET), 0, &getCppuType((sal_Int32*)0), 0, 0 }, 130 {MAP_CHAR_LEN(SC_UNONAME_UIREPR), 0, &getCppuType((rtl::OUString*)0), 0, 0 }, 131 {MAP_CHAR_LEN(SC_UNONAME_XLA1REPR), 0, &getCppuType((rtl::OUString*)0), 0, 0 }, 132 {0,0,0,0,0,0} 133 }; 134 static uno::Reference<beans::XPropertySetInfo> aRef(new SfxItemPropertySetInfo( aPropertyMap )); 135 return aRef; 136 } 137 } 138 139 void SAL_CALL ScAddressConversionObj::setPropertyValue( const rtl::OUString& aPropertyName, const uno::Any& aValue ) 140 throw(beans::UnknownPropertyException, beans::PropertyVetoException, 141 lang::IllegalArgumentException, lang::WrappedTargetException, 142 uno::RuntimeException) 143 { 144 if ( !pDocShell ) 145 throw uno::RuntimeException(); 146 147 sal_Bool bSuccess = sal_False; 148 String aNameStr(aPropertyName); 149 if ( aNameStr.EqualsAscii( SC_UNONAME_ADDRESS ) ) 150 { 151 // read the cell/range address from API struct 152 if ( bIsRange ) 153 { 154 table::CellRangeAddress aRangeAddress; 155 if ( aValue >>= aRangeAddress ) 156 { 157 ScUnoConversion::FillScRange( aRange, aRangeAddress ); 158 bSuccess = sal_True; 159 } 160 } 161 else 162 { 163 table::CellAddress aCellAddress; 164 if ( aValue >>= aCellAddress ) 165 { 166 ScUnoConversion::FillScAddress( aRange.aStart, aCellAddress ); 167 bSuccess = sal_True; 168 } 169 } 170 } 171 else if ( aNameStr.EqualsAscii( SC_UNONAME_REFSHEET ) ) 172 { 173 // set the reference sheet 174 sal_Int32 nIntVal = 0; 175 if ( aValue >>= nIntVal ) 176 { 177 nRefSheet = nIntVal; 178 bSuccess = sal_True; 179 } 180 } 181 else if ( aNameStr.EqualsAscii( SC_UNONAME_UIREPR ) ) 182 { 183 // parse the UI representation string 184 rtl::OUString sRepresentation; 185 if (aValue >>= sRepresentation) 186 { 187 String aUIString = sRepresentation; 188 bSuccess = ParseUIString( aUIString ); 189 } 190 } 191 else if ( aNameStr.EqualsAscii( SC_UNONAME_PERSREPR ) || aNameStr.EqualsAscii( SC_UNONAME_XLA1REPR ) ) 192 { 193 ::formula::FormulaGrammar::AddressConvention eConv = aNameStr.EqualsAscii( SC_UNONAME_XLA1REPR ) ? 194 ::formula::FormulaGrammar::CONV_XL_A1 : ::formula::FormulaGrammar::CONV_OOO; 195 196 // parse the file format string 197 rtl::OUString sRepresentation; 198 if (aValue >>= sRepresentation) 199 { 200 String aUIString(sRepresentation); 201 202 // cell or range: strip a single "." at the start 203 if ( aUIString.GetChar(0) == (sal_Unicode) '.' ) 204 aUIString.Erase( 0, 1 ); 205 206 if ( bIsRange ) 207 { 208 // range: also strip a "." after the last colon 209 sal_Int32 nColon = rtl::OUString(aUIString).lastIndexOf( (sal_Unicode) ':' ); 210 if ( nColon >= 0 && nColon < aUIString.Len() - 1 && 211 aUIString.GetChar((xub_StrLen)nColon+1) == (sal_Unicode) '.' ) 212 aUIString.Erase( (xub_StrLen)nColon+1, 1 ); 213 } 214 215 // parse the rest like a UI string 216 bSuccess = ParseUIString( aUIString, eConv ); 217 } 218 } 219 else 220 throw beans::UnknownPropertyException(); 221 222 if ( !bSuccess ) 223 throw lang::IllegalArgumentException(); 224 } 225 226 uno::Any SAL_CALL ScAddressConversionObj::getPropertyValue( const rtl::OUString& aPropertyName ) 227 throw(beans::UnknownPropertyException, lang::WrappedTargetException, 228 uno::RuntimeException) 229 { 230 if ( !pDocShell ) 231 throw uno::RuntimeException(); 232 233 ScDocument* pDoc = pDocShell->GetDocument(); 234 uno::Any aRet; 235 236 String aNameStr(aPropertyName); 237 if ( aNameStr.EqualsAscii( SC_UNONAME_ADDRESS ) ) 238 { 239 if ( bIsRange ) 240 { 241 table::CellRangeAddress aRangeAddress; 242 ScUnoConversion::FillApiRange( aRangeAddress, aRange ); 243 aRet <<= aRangeAddress; 244 } 245 else 246 { 247 table::CellAddress aCellAddress; 248 ScUnoConversion::FillApiAddress( aCellAddress, aRange.aStart ); 249 aRet <<= aCellAddress; 250 } 251 } 252 else if ( aNameStr.EqualsAscii( SC_UNONAME_REFSHEET ) ) 253 { 254 aRet <<= nRefSheet; 255 } 256 else if ( aNameStr.EqualsAscii( SC_UNONAME_UIREPR ) ) 257 { 258 // generate UI representation string - include sheet only if different from ref sheet 259 String aFormatStr; 260 sal_uInt16 nFlags = SCA_VALID; 261 if ( aRange.aStart.Tab() != nRefSheet ) 262 nFlags |= SCA_TAB_3D; 263 if ( bIsRange ) 264 aRange.Format( aFormatStr, nFlags, pDoc ); 265 else 266 aRange.aStart.Format( aFormatStr, nFlags, pDoc ); 267 aRet <<= rtl::OUString( aFormatStr ); 268 } 269 else if ( aNameStr.EqualsAscii( SC_UNONAME_PERSREPR ) || aNameStr.EqualsAscii( SC_UNONAME_XLA1REPR ) ) 270 { 271 ::formula::FormulaGrammar::AddressConvention eConv = aNameStr.EqualsAscii( SC_UNONAME_XLA1REPR ) ? 272 ::formula::FormulaGrammar::CONV_XL_A1 : ::formula::FormulaGrammar::CONV_OOO; 273 274 // generate file format string - always include sheet 275 String aFormatStr; 276 aRange.aStart.Format( aFormatStr, SCA_VALID | SCA_TAB_3D, pDoc, eConv ); 277 if ( bIsRange ) 278 { 279 // manually concatenate range so both parts always have the sheet name 280 aFormatStr.Append( (sal_Unicode) ':' ); 281 String aSecond; 282 sal_uInt16 nFlags = SCA_VALID; 283 if( eConv != ::formula::FormulaGrammar::CONV_XL_A1 ) 284 nFlags |= SCA_TAB_3D; 285 aRange.aEnd.Format( aSecond, nFlags, pDoc, eConv ); 286 aFormatStr.Append( aSecond ); 287 } 288 aRet <<= rtl::OUString( aFormatStr ); 289 } 290 else 291 throw beans::UnknownPropertyException(); 292 293 return aRet; 294 } 295 296 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScAddressConversionObj ) 297 298 // lang::XServiceInfo 299 300 rtl::OUString SAL_CALL ScAddressConversionObj::getImplementationName() throw(uno::RuntimeException) 301 { 302 return rtl::OUString::createFromAscii( "ScAddressConversionObj" ); 303 } 304 305 sal_Bool SAL_CALL ScAddressConversionObj::supportsService( const rtl::OUString& rServiceName ) 306 throw(uno::RuntimeException) 307 { 308 String aServiceStr( rServiceName ); 309 return aServiceStr.EqualsAscii( bIsRange ? SC_SERVICENAME_RANGEADDRESS 310 : SC_SERVICENAME_CELLADDRESS ); 311 } 312 313 uno::Sequence<rtl::OUString> SAL_CALL ScAddressConversionObj::getSupportedServiceNames() 314 throw(uno::RuntimeException) 315 { 316 uno::Sequence<rtl::OUString> aRet(1); 317 rtl::OUString* pArray = aRet.getArray(); 318 pArray[0] = rtl::OUString::createFromAscii( bIsRange ? SC_SERVICENAME_RANGEADDRESS 319 : SC_SERVICENAME_CELLADDRESS ); 320 return aRet; 321 } 322 323