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
ScAddressConversionObj(ScDocShell * pDocSh,sal_Bool bForRange)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
~ScAddressConversionObj()53 ScAddressConversionObj::~ScAddressConversionObj()
54 {
55 if (pDocShell)
56 pDocShell->GetDocument()->RemoveUnoObject(*this);
57 }
58
Notify(SfxBroadcaster &,const SfxHint & rHint)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
ParseUIString(const String & rUIString,::formula::FormulaGrammar::AddressConvention eConv)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
getPropertySetInfo()104 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScAddressConversionObj::getPropertySetInfo()
105 {
106 ScUnoGuard aGuard;
107
108 if ( bIsRange )
109 {
110 static SfxItemPropertyMapEntry aPropertyMap[] =
111 {
112 {MAP_CHAR_LEN(SC_UNONAME_ADDRESS), 0, &getCppuType((table::CellRangeAddress*)0), 0, 0 },
113 {MAP_CHAR_LEN(SC_UNONAME_PERSREPR), 0, &getCppuType((rtl::OUString*)0), 0, 0 },
114 {MAP_CHAR_LEN(SC_UNONAME_REFSHEET), 0, &getCppuType((sal_Int32*)0), 0, 0 },
115 {MAP_CHAR_LEN(SC_UNONAME_UIREPR), 0, &getCppuType((rtl::OUString*)0), 0, 0 },
116 {MAP_CHAR_LEN(SC_UNONAME_XLA1REPR), 0, &getCppuType((rtl::OUString*)0), 0, 0 },
117 {0,0,0,0,0,0}
118 };
119 static uno::Reference<beans::XPropertySetInfo> aRef(new SfxItemPropertySetInfo( aPropertyMap ));
120 return aRef;
121 }
122 else
123 {
124 static SfxItemPropertyMapEntry aPropertyMap[] =
125 {
126 {MAP_CHAR_LEN(SC_UNONAME_ADDRESS), 0, &getCppuType((table::CellAddress*)0), 0, 0 },
127 {MAP_CHAR_LEN(SC_UNONAME_PERSREPR), 0, &getCppuType((rtl::OUString*)0), 0, 0 },
128 {MAP_CHAR_LEN(SC_UNONAME_REFSHEET), 0, &getCppuType((sal_Int32*)0), 0, 0 },
129 {MAP_CHAR_LEN(SC_UNONAME_UIREPR), 0, &getCppuType((rtl::OUString*)0), 0, 0 },
130 {MAP_CHAR_LEN(SC_UNONAME_XLA1REPR), 0, &getCppuType((rtl::OUString*)0), 0, 0 },
131 {0,0,0,0,0,0}
132 };
133 static uno::Reference<beans::XPropertySetInfo> aRef(new SfxItemPropertySetInfo( aPropertyMap ));
134 return aRef;
135 }
136 }
137
setPropertyValue(const rtl::OUString & aPropertyName,const uno::Any & aValue)138 void SAL_CALL ScAddressConversionObj::setPropertyValue( const rtl::OUString& aPropertyName, const uno::Any& aValue )
139 {
140 if ( !pDocShell )
141 throw uno::RuntimeException();
142
143 sal_Bool bSuccess = sal_False;
144 String aNameStr(aPropertyName);
145 if ( aNameStr.EqualsAscii( SC_UNONAME_ADDRESS ) )
146 {
147 // read the cell/range address from API struct
148 if ( bIsRange )
149 {
150 table::CellRangeAddress aRangeAddress;
151 if ( aValue >>= aRangeAddress )
152 {
153 ScUnoConversion::FillScRange( aRange, aRangeAddress );
154 bSuccess = sal_True;
155 }
156 }
157 else
158 {
159 table::CellAddress aCellAddress;
160 if ( aValue >>= aCellAddress )
161 {
162 ScUnoConversion::FillScAddress( aRange.aStart, aCellAddress );
163 bSuccess = sal_True;
164 }
165 }
166 }
167 else if ( aNameStr.EqualsAscii( SC_UNONAME_REFSHEET ) )
168 {
169 // set the reference sheet
170 sal_Int32 nIntVal = 0;
171 if ( aValue >>= nIntVal )
172 {
173 nRefSheet = nIntVal;
174 bSuccess = sal_True;
175 }
176 }
177 else if ( aNameStr.EqualsAscii( SC_UNONAME_UIREPR ) )
178 {
179 // parse the UI representation string
180 rtl::OUString sRepresentation;
181 if (aValue >>= sRepresentation)
182 {
183 String aUIString = sRepresentation;
184 bSuccess = ParseUIString( aUIString );
185 }
186 }
187 else if ( aNameStr.EqualsAscii( SC_UNONAME_PERSREPR ) || aNameStr.EqualsAscii( SC_UNONAME_XLA1REPR ) )
188 {
189 ::formula::FormulaGrammar::AddressConvention eConv = aNameStr.EqualsAscii( SC_UNONAME_XLA1REPR ) ?
190 ::formula::FormulaGrammar::CONV_XL_A1 : ::formula::FormulaGrammar::CONV_OOO;
191
192 // parse the file format string
193 rtl::OUString sRepresentation;
194 if (aValue >>= sRepresentation)
195 {
196 String aUIString(sRepresentation);
197
198 // cell or range: strip a single "." at the start
199 if ( aUIString.GetChar(0) == (sal_Unicode) '.' )
200 aUIString.Erase( 0, 1 );
201
202 if ( bIsRange )
203 {
204 // range: also strip a "." after the last colon
205 sal_Int32 nColon = rtl::OUString(aUIString).lastIndexOf( (sal_Unicode) ':' );
206 if ( nColon >= 0 && nColon < aUIString.Len() - 1 &&
207 aUIString.GetChar((xub_StrLen)nColon+1) == (sal_Unicode) '.' )
208 aUIString.Erase( (xub_StrLen)nColon+1, 1 );
209 }
210
211 // parse the rest like a UI string
212 bSuccess = ParseUIString( aUIString, eConv );
213 }
214 }
215 else
216 throw beans::UnknownPropertyException();
217
218 if ( !bSuccess )
219 throw lang::IllegalArgumentException();
220 }
221
getPropertyValue(const rtl::OUString & aPropertyName)222 uno::Any SAL_CALL ScAddressConversionObj::getPropertyValue( const rtl::OUString& aPropertyName )
223 {
224 if ( !pDocShell )
225 throw uno::RuntimeException();
226
227 ScDocument* pDoc = pDocShell->GetDocument();
228 uno::Any aRet;
229
230 String aNameStr(aPropertyName);
231 if ( aNameStr.EqualsAscii( SC_UNONAME_ADDRESS ) )
232 {
233 if ( bIsRange )
234 {
235 table::CellRangeAddress aRangeAddress;
236 ScUnoConversion::FillApiRange( aRangeAddress, aRange );
237 aRet <<= aRangeAddress;
238 }
239 else
240 {
241 table::CellAddress aCellAddress;
242 ScUnoConversion::FillApiAddress( aCellAddress, aRange.aStart );
243 aRet <<= aCellAddress;
244 }
245 }
246 else if ( aNameStr.EqualsAscii( SC_UNONAME_REFSHEET ) )
247 {
248 aRet <<= nRefSheet;
249 }
250 else if ( aNameStr.EqualsAscii( SC_UNONAME_UIREPR ) )
251 {
252 // generate UI representation string - include sheet only if different from ref sheet
253 String aFormatStr;
254 sal_uInt16 nFlags = SCA_VALID;
255 if ( aRange.aStart.Tab() != nRefSheet )
256 nFlags |= SCA_TAB_3D;
257 if ( bIsRange )
258 aRange.Format( aFormatStr, nFlags, pDoc );
259 else
260 aRange.aStart.Format( aFormatStr, nFlags, pDoc );
261 aRet <<= rtl::OUString( aFormatStr );
262 }
263 else if ( aNameStr.EqualsAscii( SC_UNONAME_PERSREPR ) || aNameStr.EqualsAscii( SC_UNONAME_XLA1REPR ) )
264 {
265 ::formula::FormulaGrammar::AddressConvention eConv = aNameStr.EqualsAscii( SC_UNONAME_XLA1REPR ) ?
266 ::formula::FormulaGrammar::CONV_XL_A1 : ::formula::FormulaGrammar::CONV_OOO;
267
268 // generate file format string - always include sheet
269 String aFormatStr;
270 aRange.aStart.Format( aFormatStr, SCA_VALID | SCA_TAB_3D, pDoc, eConv );
271 if ( bIsRange )
272 {
273 // manually concatenate range so both parts always have the sheet name
274 aFormatStr.Append( (sal_Unicode) ':' );
275 String aSecond;
276 sal_uInt16 nFlags = SCA_VALID;
277 if( eConv != ::formula::FormulaGrammar::CONV_XL_A1 )
278 nFlags |= SCA_TAB_3D;
279 aRange.aEnd.Format( aSecond, nFlags, pDoc, eConv );
280 aFormatStr.Append( aSecond );
281 }
282 aRet <<= rtl::OUString( aFormatStr );
283 }
284 else
285 throw beans::UnknownPropertyException();
286
287 return aRet;
288 }
289
SC_IMPL_DUMMY_PROPERTY_LISTENER(ScAddressConversionObj)290 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScAddressConversionObj )
291
292 // lang::XServiceInfo
293
294 rtl::OUString SAL_CALL ScAddressConversionObj::getImplementationName()
295 {
296 return rtl::OUString::createFromAscii( "ScAddressConversionObj" );
297 }
298
supportsService(const rtl::OUString & rServiceName)299 sal_Bool SAL_CALL ScAddressConversionObj::supportsService( const rtl::OUString& rServiceName )
300 {
301 String aServiceStr( rServiceName );
302 return aServiceStr.EqualsAscii( bIsRange ? SC_SERVICENAME_RANGEADDRESS
303 : SC_SERVICENAME_CELLADDRESS );
304 }
305
getSupportedServiceNames()306 uno::Sequence<rtl::OUString> SAL_CALL ScAddressConversionObj::getSupportedServiceNames()
307 {
308 uno::Sequence<rtl::OUString> aRet(1);
309 rtl::OUString* pArray = aRet.getArray();
310 pArray[0] = rtl::OUString::createFromAscii( bIsRange ? SC_SERVICENAME_RANGEADDRESS
311 : SC_SERVICENAME_CELLADDRESS );
312 return aRet;
313 }
314