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