xref: /trunk/main/sc/source/ui/unoobj/addruno.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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