1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <comphelper/processfactory.hxx>
21 #include <i18nlangtag/languagetag.hxx>
22 #include <vcl/svapp.hxx>
23 #include <vcl/settings.hxx>
24 #include <sfx2/objsh.hxx>
25 #include <unotools/charclass.hxx>
27 #include <com/sun/star/container/XContentEnumerationAccess.hpp>
28 #include <com/sun/star/lang/XServiceName.hpp>
29 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
30 #include <com/sun/star/lang/XSingleComponentFactory.hpp>
31 #include <com/sun/star/reflection/XIdlClass.hpp>
32 #include <com/sun/star/beans/XIntrospectionAccess.hpp>
33 #include <com/sun/star/beans/theIntrospection.hpp>
34 #include <com/sun/star/beans/MethodConcept.hpp>
35 #include <com/sun/star/beans/XPropertySet.hpp>
36 #include <com/sun/star/table/XCellRange.hpp>
37 #include <com/sun/star/lang/Locale.hpp>
38 #include <com/sun/star/sheet/XCompatibilityNames.hpp>
39 #include <com/sun/star/sheet/NoConvergenceException.hpp>
41 #include "addincol.hxx"
42 #include "addinhelpid.hxx"
43 #include "compiler.hxx"
44 #include "scmatrix.hxx"
45 #include "addinlis.hxx"
46 #include <formula/errorcodes.hxx>
47 #include "scfuncs.hrc"
48 #include "optutil.hxx"
49 #include "addincfg.hxx"
51 #include "rangeseq.hxx"
52 #include "funcdesc.hxx"
53 #include <svl/sharedstring.hxx>
54 #include "formulaopt.hxx"
55 #include <boost/scoped_array.hpp>
57 using namespace com::sun::star
;
59 #define SC_CALLERPOS_NONE (-1)
61 ScUnoAddInFuncData::ScUnoAddInFuncData( const OUString
& rNam
, const OUString
& rLoc
,
62 const OUString
& rDesc
,
63 sal_uInt16 nCat
, const OString
& sHelp
,
64 const uno::Reference
<reflection::XIdlMethod
>& rFunc
,
66 long nAC
, const ScAddInArgDesc
* pAD
,
68 aOriginalName( rNam
),
72 aDescription( rDesc
),
79 bCompInitialized( false )
83 pArgDescs
= new ScAddInArgDesc
[nArgCount
];
84 for (long i
=0; i
<nArgCount
; i
++)
85 pArgDescs
[i
] = pAD
[i
];
90 aUpperName
= ScGlobal::pCharClass
->uppercase(aUpperName
);
91 aUpperLocal
= ScGlobal::pCharClass
->uppercase(aUpperLocal
);
94 ScUnoAddInFuncData::~ScUnoAddInFuncData()
99 const ::std::vector
<ScUnoAddInFuncData::LocalizedName
>& ScUnoAddInFuncData::GetCompNames() const
101 if ( !bCompInitialized
)
103 // read sequence of compatibility names on demand
105 uno::Reference
<sheet::XAddIn
> xAddIn
;
106 if ( aObject
>>= xAddIn
)
108 uno::Reference
<sheet::XCompatibilityNames
> xComp( xAddIn
, uno::UNO_QUERY
);
109 if ( xComp
.is() && xFunction
.is() )
111 OUString aMethodName
= xFunction
->getName();
112 uno::Sequence
< sheet::LocalizedName
> aCompNames( xComp
->getCompatibilityNames( aMethodName
));
114 sal_Int32 nSeqLen
= aCompNames
.getLength();
117 const sheet::LocalizedName
* pArray
= aCompNames
.getArray();
118 for (sal_Int32 i
=0; i
<nSeqLen
; i
++)
120 maCompNames
.push_back( LocalizedName(
121 LanguageTag::convertToBcp47( pArray
[i
].Locale
, false),
128 bCompInitialized
= true; // also if not successful
133 void ScUnoAddInFuncData::SetCompNames( const ::std::vector
< ScUnoAddInFuncData::LocalizedName
>& rNew
)
135 OSL_ENSURE( !bCompInitialized
, "SetCompNames after initializing" );
139 bCompInitialized
= true;
142 bool ScUnoAddInFuncData::GetExcelName( LanguageType eDestLang
, OUString
& rRetExcelName
) const
144 const ::std::vector
<LocalizedName
>& rCompNames
= GetCompNames();
145 if ( !rCompNames
.empty() )
147 LanguageTag
aLanguageTag( eDestLang
);
148 const OUString
aSearch( aLanguageTag
.getBcp47());
150 // First, check exact match without fallback overhead.
151 ::std::vector
<LocalizedName
>::const_iterator
itNames( rCompNames
.begin());
152 for ( ; itNames
!= rCompNames
.end(); ++itNames
)
154 if ((*itNames
).maLocale
== aSearch
)
156 rRetExcelName
= (*itNames
).maName
;
161 // Second, try match of fallback search with fallback locales,
162 // appending also 'en-US' and 'en' to search if not queried.
163 ::std::vector
< OUString
> aFallbackSearch( aLanguageTag
.getFallbackStrings( true));
164 if (aSearch
!= "en-US")
166 aFallbackSearch
.push_back( "en-US");
169 aFallbackSearch
.push_back( "en");
172 ::std::vector
< OUString
>::const_iterator
itSearch( aFallbackSearch
.begin());
173 for ( ; itSearch
!= aFallbackSearch
.end(); ++itSearch
)
175 itNames
= rCompNames
.begin();
176 for ( ; itNames
!= rCompNames
.end(); ++itNames
)
178 // We checked already the full tag, start with second.
179 ::std::vector
< OUString
> aFallbackLocales( LanguageTag( (*itNames
).maLocale
).getFallbackStrings( false));
180 for (::std::vector
< OUString
>::const_iterator
itLocales( aFallbackLocales
.begin());
181 itLocales
!= aFallbackLocales
.end(); ++itLocales
)
183 if (*itLocales
== *itSearch
)
185 rRetExcelName
= (*itNames
).maName
;
192 // Third, last resort, use first (default) entry.
193 rRetExcelName
= rCompNames
[0].maName
;
199 void ScUnoAddInFuncData::SetFunction( const uno::Reference
< reflection::XIdlMethod
>& rNewFunc
, const uno::Any
& rNewObj
)
201 xFunction
= rNewFunc
;
205 void ScUnoAddInFuncData::SetArguments( long nNewCount
, const ScAddInArgDesc
* pNewDescs
)
209 nArgCount
= nNewCount
;
212 pArgDescs
= new ScAddInArgDesc
[nArgCount
];
213 for (long i
=0; i
<nArgCount
; i
++)
214 pArgDescs
[i
] = pNewDescs
[i
];
220 void ScUnoAddInFuncData::SetCallerPos( long nNewPos
)
222 nCallerPos
= nNewPos
;
225 ScUnoAddInCollection::ScUnoAddInCollection() :
228 pExactHashMap( NULL
),
229 pNameHashMap( NULL
),
230 pLocalHashMap( NULL
),
231 bInitialized( false )
235 ScUnoAddInCollection::~ScUnoAddInCollection()
240 void ScUnoAddInCollection::Clear()
242 DELETEZ( pExactHashMap
);
243 DELETEZ( pNameHashMap
);
244 DELETEZ( pLocalHashMap
);
247 for ( long i
=0; i
<nFuncCount
; i
++ )
248 delete ppFuncData
[i
];
254 bInitialized
= false;
257 void ScUnoAddInCollection::Initialize()
259 OSL_ENSURE( !bInitialized
, "Initialize twice?" );
261 uno::Reference
<lang::XMultiServiceFactory
> xManager
= comphelper::getProcessServiceFactory();
262 uno::Reference
<container::XContentEnumerationAccess
> xEnAc( xManager
, uno::UNO_QUERY
);
265 uno::Reference
<container::XEnumeration
> xEnum
=
266 xEnAc
->createContentEnumeration( "com.sun.star.sheet.AddIn" );
269 // loop through all AddIns
270 while ( xEnum
->hasMoreElements() )
272 uno::Any aAddInAny
= xEnum
->nextElement();
276 uno::Reference
<uno::XInterface
> xIntFac
;
277 aAddInAny
>>= xIntFac
;
280 // #i59984# try XSingleComponentFactory in addition to (old) XSingleServiceFactory,
281 // passing the context to the component
283 uno::Reference
<uno::XInterface
> xInterface
;
284 uno::Reference
<uno::XComponentContext
> xCtx(
285 comphelper::getComponentContext(xManager
));
286 uno::Reference
<lang::XSingleComponentFactory
> xCFac( xIntFac
, uno::UNO_QUERY
);
289 xInterface
= xCFac
->createInstanceWithContext(xCtx
);
291 ReadFromAddIn( xInterface
);
294 if (!xInterface
.is())
296 uno::Reference
<lang::XSingleServiceFactory
> xFac( xIntFac
, uno::UNO_QUERY
);
299 xInterface
= xFac
->createInstance();
301 ReadFromAddIn( xInterface
);
305 } catch ( const uno::Exception
& ) {
306 SAL_WARN ( "sc", "Failed to initialize create instance of sheet.AddIn" );
312 // ReadConfiguration is called after looking at the AddIn implementations.
313 // Duplicated are skipped (by using the service information, they don't have to be updated again
314 // when argument information is needed).
317 bInitialized
= true; // with or without functions
320 static sal_uInt16
lcl_GetCategory( const OUString
& rName
)
322 static const sal_Char
* aFuncNames
[SC_FUNCGROUP_COUNT
] =
324 // array index = ID - 1 (ID starts at 1)
326 "Database", // ID_FUNCTION_GRP_DATABASE
327 "Date&Time", // ID_FUNCTION_GRP_DATETIME
328 "Financial", // ID_FUNCTION_GRP_FINANZ
329 "Information", // ID_FUNCTION_GRP_INFO
330 "Logical", // ID_FUNCTION_GRP_LOGIC
331 "Mathematical", // ID_FUNCTION_GRP_MATH
332 "Matrix", // ID_FUNCTION_GRP_MATRIX
333 "Statistical", // ID_FUNCTION_GRP_STATISTIC
334 "Spreadsheet", // ID_FUNCTION_GRP_TABLE
335 "Text", // ID_FUNCTION_GRP_TEXT
336 "Add-In" // ID_FUNCTION_GRP_ADDINS
338 for (sal_uInt16 i
=0; i
<SC_FUNCGROUP_COUNT
; i
++)
339 if ( rName
.equalsAscii( aFuncNames
[i
] ) )
340 return i
+1; // IDs start at 1
342 return ID_FUNCTION_GRP_ADDINS
; // if not found, use Add-In group
345 #define CFGPATH_ADDINS "Office.CalcAddIns/AddInInfo"
346 #define CFGSTR_ADDINFUNCTIONS "AddInFunctions"
348 #define CFG_FUNCPROP_DISPLAYNAME 0
349 #define CFG_FUNCPROP_DESCRIPTION 1
350 #define CFG_FUNCPROP_CATEGORY 2
351 #define CFG_FUNCPROP_COUNT 3
352 #define CFGSTR_DISPLAYNAME "DisplayName"
353 #define CFGSTR_DESCRIPTION "Description"
354 #define CFGSTR_CATEGORY "Category"
355 // CategoryDisplayName is ignored for now
357 #define CFGSTR_COMPATIBILITYNAME "CompatibilityName"
358 #define CFGSTR_PARAMETERS "Parameters"
360 void ScUnoAddInCollection::ReadConfiguration()
362 // called only from Initialize
364 ScAddInCfg
& rAddInConfig
= SC_MOD()->GetAddInCfg();
366 // additional, temporary config item for the compatibility names
367 ScLinkConfigItem
aAllLocalesConfig( OUString(CFGPATH_ADDINS
), ConfigItemMode::AllLocales
);
368 // CommitLink is not used (only reading values)
370 const OUString
sSlash('/');
372 // get the list of add-ins (services)
373 OUString aEmptyString
;
374 uno::Sequence
<OUString
> aServiceNames
= rAddInConfig
.GetNodeNames( aEmptyString
);
376 sal_Int32 nServiceCount
= aServiceNames
.getLength();
377 for ( sal_Int32 nService
= 0; nService
< nServiceCount
; nService
++ )
379 OUString aServiceName
= aServiceNames
[nService
];
380 ScUnoAddInHelpIdGenerator
aHelpIdGenerator( aServiceName
);
382 OUString aFunctionsPath
= aServiceName
;
383 aFunctionsPath
+= sSlash
;
384 aFunctionsPath
+= OUString(CFGSTR_ADDINFUNCTIONS
);
386 uno::Sequence
<OUString
> aFunctionNames
= rAddInConfig
.GetNodeNames( aFunctionsPath
);
387 sal_Int32 nNewCount
= aFunctionNames
.getLength();
391 long nOld
= nFuncCount
;
392 nFuncCount
= nNewCount
+nOld
;
395 ScUnoAddInFuncData
** ppNew
= new ScUnoAddInFuncData
*[nFuncCount
];
396 for (long i
=0; i
<nOld
; i
++)
397 ppNew
[i
] = ppFuncData
[i
];
402 ppFuncData
= new ScUnoAddInFuncData
*[nFuncCount
];
404 //TODO: adjust bucket count?
405 if ( !pExactHashMap
)
406 pExactHashMap
= new ScAddInHashMap
;
408 pNameHashMap
= new ScAddInHashMap
;
409 if ( !pLocalHashMap
)
410 pLocalHashMap
= new ScAddInHashMap
;
412 //TODO: get the function information in a single call for all functions?
414 const OUString
* pFuncNameArray
= aFunctionNames
.getConstArray();
415 for ( sal_Int32 nFuncPos
= 0; nFuncPos
< nNewCount
; nFuncPos
++ )
417 ppFuncData
[nFuncPos
+nOld
] = NULL
;
419 // stored function name: (service name).(function)
420 OUStringBuffer
aFuncNameBuffer( aServiceName
.getLength()+1+pFuncNameArray
[nFuncPos
].getLength());
421 aFuncNameBuffer
.append(aServiceName
);
422 aFuncNameBuffer
.append('.');
423 aFuncNameBuffer
.append(pFuncNameArray
[nFuncPos
]);
424 OUString aFuncName
= aFuncNameBuffer
.makeStringAndClear();
426 // skip the function if already known (read from old AddIn service)
428 if ( pExactHashMap
->find( aFuncName
) == pExactHashMap
->end() )
431 OUString aDescription
;
432 sal_uInt16 nCategory
= ID_FUNCTION_GRP_ADDINS
;
434 // get direct information on the function
436 OUString aFuncPropPath
= aFunctionsPath
;
437 aFuncPropPath
+= sSlash
;
438 aFuncPropPath
+= pFuncNameArray
[nFuncPos
];
439 aFuncPropPath
+= sSlash
;
441 uno::Sequence
<OUString
> aFuncPropNames(CFG_FUNCPROP_COUNT
);
442 OUString
* pNameArray
= aFuncPropNames
.getArray();
443 pNameArray
[CFG_FUNCPROP_DISPLAYNAME
] = aFuncPropPath
;
444 pNameArray
[CFG_FUNCPROP_DISPLAYNAME
] += OUString(CFGSTR_DISPLAYNAME
);
445 pNameArray
[CFG_FUNCPROP_DESCRIPTION
] = aFuncPropPath
;
446 pNameArray
[CFG_FUNCPROP_DESCRIPTION
] += OUString(CFGSTR_DESCRIPTION
);
447 pNameArray
[CFG_FUNCPROP_CATEGORY
] = aFuncPropPath
;
448 pNameArray
[CFG_FUNCPROP_CATEGORY
] += OUString(CFGSTR_CATEGORY
);
450 uno::Sequence
<uno::Any
> aFuncProperties
= rAddInConfig
.GetProperties( aFuncPropNames
);
451 if ( aFuncProperties
.getLength() == CFG_FUNCPROP_COUNT
)
453 aFuncProperties
[CFG_FUNCPROP_DISPLAYNAME
] >>= aLocalName
;
454 aFuncProperties
[CFG_FUNCPROP_DESCRIPTION
] >>= aDescription
;
456 OUString aCategoryName
;
457 aFuncProperties
[CFG_FUNCPROP_CATEGORY
] >>= aCategoryName
;
458 nCategory
= lcl_GetCategory( aCategoryName
);
461 // get compatibility names
463 ::std::vector
<ScUnoAddInFuncData::LocalizedName
> aCompNames
;
465 OUString aCompPath
= aFuncPropPath
;
466 aCompPath
+= OUString(CFGSTR_COMPATIBILITYNAME
);
467 uno::Sequence
<OUString
> aCompPropNames( &aCompPath
, 1 );
469 uno::Sequence
<uno::Any
> aCompProperties
= aAllLocalesConfig
.GetProperties( aCompPropNames
);
470 if ( aCompProperties
.getLength() == 1 )
472 uno::Sequence
<beans::PropertyValue
> aLocalEntries
;
473 if ( aCompProperties
[0] >>= aLocalEntries
)
475 sal_Int32 nLocaleCount
= aLocalEntries
.getLength();
476 const beans::PropertyValue
* pConfigArray
= aLocalEntries
.getConstArray();
478 for ( sal_Int32 nLocale
= 0; nLocale
< nLocaleCount
; nLocale
++ )
480 // PropertyValue name is the locale ("convert" from
481 // string to string to canonicalize)
482 OUString
aLocale( LanguageTag( pConfigArray
[nLocale
].Name
, true).getBcp47( false));
483 // PropertyValue value is the localized value (string in this case)
485 pConfigArray
[nLocale
].Value
>>= aName
;
486 aCompNames
.push_back( ScUnoAddInFuncData::LocalizedName( aLocale
, aName
));
493 boost::scoped_array
<ScAddInArgDesc
> pVisibleArgs
;
494 long nVisibleCount
= 0;
495 long nCallerPos
= SC_CALLERPOS_NONE
;
497 OUString aArgumentsPath
= aFuncPropPath
;
498 aArgumentsPath
+= OUString(CFGSTR_PARAMETERS
);
500 uno::Sequence
<OUString
> aArgumentNames
= rAddInConfig
.GetNodeNames( aArgumentsPath
);
501 sal_Int32 nArgumentCount
= aArgumentNames
.getLength();
502 if ( nArgumentCount
)
504 // get DisplayName and Description for each argument
505 uno::Sequence
<OUString
> aArgPropNames( nArgumentCount
* 2 );
506 OUString
* pPropNameArray
= aArgPropNames
.getArray();
509 sal_Int32 nIndex
= 0;
510 const OUString
* pArgNameArray
= aArgumentNames
.getConstArray();
511 for ( nArgument
= 0; nArgument
< nArgumentCount
; nArgument
++ )
513 OUString aOneArgPath
= aArgumentsPath
;
514 aOneArgPath
+= sSlash
;
515 aOneArgPath
+= pArgNameArray
[nArgument
];
516 aOneArgPath
+= sSlash
;
518 pPropNameArray
[nIndex
] = aOneArgPath
;
519 pPropNameArray
[nIndex
++] += OUString(CFGSTR_DISPLAYNAME
);
520 pPropNameArray
[nIndex
] = aOneArgPath
;
521 pPropNameArray
[nIndex
++] += OUString(CFGSTR_DESCRIPTION
);
524 uno::Sequence
<uno::Any
> aArgProperties
= rAddInConfig
.GetProperties( aArgPropNames
);
525 if ( aArgProperties
.getLength() == aArgPropNames
.getLength() )
527 const uno::Any
* pPropArray
= aArgProperties
.getConstArray();
528 OUString sDisplayName
;
529 OUString sDescription
;
531 ScAddInArgDesc aDesc
;
532 aDesc
.eType
= SC_ADDINARG_NONE
; // arg type is not in configuration
533 aDesc
.bOptional
= false;
535 nVisibleCount
= nArgumentCount
;
536 pVisibleArgs
.reset(new ScAddInArgDesc
[nVisibleCount
]);
539 for ( nArgument
= 0; nArgument
< nArgumentCount
; nArgument
++ )
541 pPropArray
[nIndex
++] >>= sDisplayName
;
542 pPropArray
[nIndex
++] >>= sDescription
;
544 aDesc
.aInternalName
= pArgNameArray
[nArgument
];
545 aDesc
.aName
= sDisplayName
;
546 aDesc
.aDescription
= sDescription
;
548 pVisibleArgs
[nArgument
] = aDesc
;
553 OString sHelpId
= aHelpIdGenerator
.GetHelpId( pFuncNameArray
[nFuncPos
] );
555 uno::Reference
<reflection::XIdlMethod
> xFunc
; // remains empty
556 uno::Any aObject
; // also empty
558 // create and insert into the array
560 ScUnoAddInFuncData
* pData
= new ScUnoAddInFuncData(
561 aFuncName
, aLocalName
, aDescription
,
564 nVisibleCount
, pVisibleArgs
.get(), nCallerPos
);
566 pData
->SetCompNames( aCompNames
);
568 ppFuncData
[nFuncPos
+nOld
] = pData
;
570 pExactHashMap
->insert(
571 ScAddInHashMap::value_type(
572 pData
->GetOriginalName(),
574 pNameHashMap
->insert(
575 ScAddInHashMap::value_type(
576 pData
->GetUpperName(),
578 pLocalHashMap
->insert(
579 ScAddInHashMap::value_type(
580 pData
->GetUpperLocal(),
587 void ScUnoAddInCollection::LoadComponent( const ScUnoAddInFuncData
& rFuncData
)
589 OUString aFullName
= rFuncData
.GetOriginalName();
590 sal_Int32 nPos
= aFullName
.lastIndexOf( (sal_Unicode
) '.' );
593 OUString aServiceName
= aFullName
.copy( 0, nPos
);
597 uno::Reference
<lang::XMultiServiceFactory
> xServiceFactory
= comphelper::getProcessServiceFactory();
598 uno::Reference
<uno::XInterface
> xInterface( xServiceFactory
->createInstance( aServiceName
) );
601 UpdateFromAddIn( xInterface
, aServiceName
);
603 catch (const uno::Exception
&)
605 SAL_WARN ("sc", "Failed to create addin component '"
606 << aServiceName
<< "'");
611 bool ScUnoAddInCollection::GetExcelName( const OUString
& rCalcName
,
612 LanguageType eDestLang
, OUString
& rRetExcelName
)
614 const ScUnoAddInFuncData
* pFuncData
= GetFuncData( rCalcName
);
616 return pFuncData
->GetExcelName( eDestLang
, rRetExcelName
);
620 bool ScUnoAddInCollection::GetCalcName( const OUString
& rExcelName
, OUString
& rRetCalcName
)
625 OUString aUpperCmp
= ScGlobal::pCharClass
->uppercase(rExcelName
);
627 for (long i
=0; i
<nFuncCount
; i
++)
629 ScUnoAddInFuncData
* pFuncData
= ppFuncData
[i
];
632 const ::std::vector
<ScUnoAddInFuncData::LocalizedName
>& rNames
= pFuncData
->GetCompNames();
633 if ( !rNames
.empty() )
635 ::std::vector
<ScUnoAddInFuncData::LocalizedName
>::const_iterator
it( rNames
.begin());
636 for ( ; it
!= rNames
.end(); ++it
)
638 if ( ScGlobal::pCharClass
->uppercase( (*it
).maName
) == aUpperCmp
)
640 //TODO: store upper case for comparing?
642 // use the first function that has this name for any language
643 rRetCalcName
= pFuncData
->GetOriginalName();
653 inline bool IsTypeName( const OUString
& rName
, const uno::Type
& rType
)
655 return rName
== rType
.getTypeName();
658 static bool lcl_ValidReturnType( const uno::Reference
<reflection::XIdlClass
>& xClass
)
660 // this must match with ScUnoAddInCall::SetResult
662 if ( !xClass
.is() ) return false;
664 switch (xClass
->getTypeClass())
666 case uno::TypeClass_ANY
: // variable type
667 case uno::TypeClass_ENUM
: //TODO: ???
668 case uno::TypeClass_BOOLEAN
:
669 case uno::TypeClass_CHAR
:
670 case uno::TypeClass_BYTE
:
671 case uno::TypeClass_SHORT
:
672 case uno::TypeClass_UNSIGNED_SHORT
:
673 case uno::TypeClass_LONG
:
674 case uno::TypeClass_UNSIGNED_LONG
:
675 case uno::TypeClass_FLOAT
:
676 case uno::TypeClass_DOUBLE
:
677 case uno::TypeClass_STRING
:
678 return true; // values or string
680 case uno::TypeClass_INTERFACE
:
682 // return type XInterface may contain a XVolatileResult
683 //TODO: XIdlClass needs getType() method!
685 OUString sName
= xClass
->getName();
687 IsTypeName( sName
, cppu::UnoType
<sheet::XVolatileResult
>::get()) ||
688 IsTypeName( sName
, cppu::UnoType
<uno::XInterface
>::get()) );
693 // nested sequences for arrays
694 //TODO: XIdlClass needs getType() method!
696 OUString sName
= xClass
->getName();
698 IsTypeName( sName
, cppu::UnoType
<uno::Sequence
< uno::Sequence
<sal_Int32
> >>::get() ) ||
699 IsTypeName( sName
, cppu::UnoType
<uno::Sequence
< uno::Sequence
<double> >>::get() ) ||
700 IsTypeName( sName
, cppu::UnoType
<uno::Sequence
< uno::Sequence
<OUString
> >>::get() ) ||
701 IsTypeName( sName
, cppu::UnoType
<uno::Sequence
< uno::Sequence
<uno::Any
> >>::get() ) );
706 static ScAddInArgumentType
lcl_GetArgType( const uno::Reference
<reflection::XIdlClass
>& xClass
)
709 return SC_ADDINARG_NONE
;
711 uno::TypeClass eType
= xClass
->getTypeClass();
713 if ( eType
== uno::TypeClass_LONG
) //TODO: other integer types?
714 return SC_ADDINARG_INTEGER
;
716 if ( eType
== uno::TypeClass_DOUBLE
)
717 return SC_ADDINARG_DOUBLE
;
719 if ( eType
== uno::TypeClass_STRING
)
720 return SC_ADDINARG_STRING
;
722 //TODO: XIdlClass needs getType() method!
723 OUString sName
= xClass
->getName();
725 if (IsTypeName( sName
, cppu::UnoType
<uno::Sequence
< uno::Sequence
<sal_Int32
> >>::get() ))
726 return SC_ADDINARG_INTEGER_ARRAY
;
728 if (IsTypeName( sName
, cppu::UnoType
<uno::Sequence
< uno::Sequence
<double> >>::get() ))
729 return SC_ADDINARG_DOUBLE_ARRAY
;
731 if (IsTypeName( sName
, cppu::UnoType
<uno::Sequence
< uno::Sequence
<OUString
> >>::get() ))
732 return SC_ADDINARG_STRING_ARRAY
;
734 if (IsTypeName( sName
, cppu::UnoType
<uno::Sequence
< uno::Sequence
<uno::Any
> >>::get() ))
735 return SC_ADDINARG_MIXED_ARRAY
;
737 if (IsTypeName( sName
, cppu::UnoType
<uno::Any
>::get()))
738 return SC_ADDINARG_VALUE_OR_ARRAY
;
740 if (IsTypeName( sName
, cppu::UnoType
<table::XCellRange
>::get()))
741 return SC_ADDINARG_CELLRANGE
;
743 if (IsTypeName( sName
, cppu::UnoType
<beans::XPropertySet
>::get()))
744 return SC_ADDINARG_CALLER
;
746 if (IsTypeName( sName
, cppu::UnoType
<uno::Sequence
<uno::Any
>>::get() ))
747 return SC_ADDINARG_VARARGS
;
749 return SC_ADDINARG_NONE
;
752 void ScUnoAddInCollection::ReadFromAddIn( const uno::Reference
<uno::XInterface
>& xInterface
)
754 uno::Reference
<sheet::XAddIn
> xAddIn( xInterface
, uno::UNO_QUERY
);
755 uno::Reference
<lang::XServiceName
> xName( xInterface
, uno::UNO_QUERY
);
756 if ( xAddIn
.is() && xName
.is() )
758 // fdo50118 when GetUseEnglishFunctionName() returns true, set the
759 // locale to en-US to get English function names
760 if ( SC_MOD()->GetFormulaOptions().GetUseEnglishFuncName() )
761 xAddIn
->setLocale( lang::Locale( "en", "US", ""));
763 xAddIn
->setLocale( Application::GetSettings().GetUILanguageTag().getLocale());
765 OUString
aServiceName( xName
->getServiceName() );
766 ScUnoAddInHelpIdGenerator
aHelpIdGenerator( aServiceName
);
768 //TODO: pass XIntrospection to ReadFromAddIn
770 uno::Reference
<uno::XComponentContext
> xContext
= comphelper::getProcessComponentContext();
772 uno::Reference
<beans::XIntrospection
> xIntro
= beans::theIntrospection::get( xContext
);
775 uno::Reference
<beans::XIntrospectionAccess
> xAcc
= xIntro
->inspect(aObject
);
778 uno::Sequence
< uno::Reference
<reflection::XIdlMethod
> > aMethods
=
779 xAcc
->getMethods( beans::MethodConcept::ALL
);
780 long nNewCount
= aMethods
.getLength();
783 long nOld
= nFuncCount
;
784 nFuncCount
= nNewCount
+nOld
;
787 ScUnoAddInFuncData
** ppNew
= new ScUnoAddInFuncData
*[nFuncCount
];
788 for (long i
=0; i
<nOld
; i
++)
789 ppNew
[i
] = ppFuncData
[i
];
794 ppFuncData
= new ScUnoAddInFuncData
*[nFuncCount
];
796 //TODO: adjust bucket count?
797 if ( !pExactHashMap
)
798 pExactHashMap
= new ScAddInHashMap
;
800 pNameHashMap
= new ScAddInHashMap
;
801 if ( !pLocalHashMap
)
802 pLocalHashMap
= new ScAddInHashMap
;
804 const uno::Reference
<reflection::XIdlMethod
>* pArray
= aMethods
.getConstArray();
805 for (long nFuncPos
=0; nFuncPos
<nNewCount
; nFuncPos
++)
807 ppFuncData
[nFuncPos
+nOld
] = NULL
;
809 uno::Reference
<reflection::XIdlMethod
> xFunc
= pArray
[nFuncPos
];
812 // leave out internal functions
813 uno::Reference
<reflection::XIdlClass
> xClass
=
814 xFunc
->getDeclaringClass();
818 //TODO: XIdlClass needs getType() method!
819 OUString sName
= xClass
->getName();
822 cppu::UnoType
<uno::XInterface
>::get()) ||
824 cppu::UnoType
<lang::XServiceName
>::get()) ||
826 cppu::UnoType
<lang::XServiceInfo
>::get()) ||
828 cppu::UnoType
<sheet::XAddIn
>::get()) );
832 uno::Reference
<reflection::XIdlClass
> xReturn
=
833 xFunc
->getReturnType();
834 if ( !lcl_ValidReturnType( xReturn
) )
839 OUString aFuncU
= xFunc
->getName();
841 // stored function name: (service name).(function)
842 OUStringBuffer
aFuncNameBuffer( aServiceName
.getLength()+1+aFuncU
.getLength());
843 aFuncNameBuffer
.append(aServiceName
);
844 aFuncNameBuffer
.append('.');
845 aFuncNameBuffer
.append(aFuncU
);
846 OUString aFuncName
= aFuncNameBuffer
.makeStringAndClear();
849 long nVisibleCount
= 0;
850 long nCallerPos
= SC_CALLERPOS_NONE
;
852 uno::Sequence
<reflection::ParamInfo
> aParams
=
853 xFunc
->getParameterInfos();
854 long nParamCount
= aParams
.getLength();
855 const reflection::ParamInfo
* pParArr
= aParams
.getConstArray();
857 for (nParamPos
=0; nParamPos
<nParamCount
; nParamPos
++)
859 if ( pParArr
[nParamPos
].aMode
!= reflection::ParamMode_IN
)
861 uno::Reference
<reflection::XIdlClass
> xParClass
=
862 pParArr
[nParamPos
].aType
;
863 ScAddInArgumentType eArgType
= lcl_GetArgType( xParClass
);
864 if ( eArgType
== SC_ADDINARG_NONE
)
866 else if ( eArgType
== SC_ADDINARG_CALLER
)
867 nCallerPos
= nParamPos
;
873 sal_uInt16 nCategory
= lcl_GetCategory(
874 xAddIn
->getProgrammaticCategoryName( aFuncU
) );
876 OString sHelpId
= aHelpIdGenerator
.GetHelpId( aFuncU
);
881 aLocalName
= xAddIn
->
882 getDisplayFunctionName( aFuncU
);
884 catch(uno::Exception
&)
889 OUString aDescription
;
892 aDescription
= xAddIn
->
893 getFunctionDescription( aFuncU
);
895 catch(uno::Exception
&)
897 aDescription
= "###";
900 boost::scoped_array
<ScAddInArgDesc
> pVisibleArgs
;
901 if ( nVisibleCount
> 0 )
903 ScAddInArgDesc aDesc
;
904 pVisibleArgs
.reset(new ScAddInArgDesc
[nVisibleCount
]);
906 for (nParamPos
=0; nParamPos
<nParamCount
; nParamPos
++)
908 uno::Reference
<reflection::XIdlClass
> xParClass
=
909 pParArr
[nParamPos
].aType
;
910 ScAddInArgumentType eArgType
= lcl_GetArgType( xParClass
);
911 if ( eArgType
!= SC_ADDINARG_CALLER
)
917 getDisplayArgumentName( aFuncU
, nParamPos
);
919 catch(uno::Exception
&)
927 getArgumentDescription( aFuncU
, nParamPos
);
929 catch(uno::Exception
&)
935 ( eArgType
== SC_ADDINARG_VALUE_OR_ARRAY
||
936 eArgType
== SC_ADDINARG_VARARGS
);
938 aDesc
.eType
= eArgType
;
939 aDesc
.aName
= aArgName
;
940 aDesc
.aDescription
= aArgDesc
;
941 aDesc
.bOptional
= bOptional
;
942 //TODO: initialize aInternalName only from config?
943 aDesc
.aInternalName
= pParArr
[nParamPos
].aName
;
945 pVisibleArgs
[nDestPos
++] = aDesc
;
948 OSL_ENSURE( nDestPos
==nVisibleCount
, "wrong count" );
951 ppFuncData
[nFuncPos
+nOld
] = new ScUnoAddInFuncData(
952 aFuncName
, aLocalName
, aDescription
,
955 nVisibleCount
, pVisibleArgs
.get(), nCallerPos
);
957 const ScUnoAddInFuncData
* pData
=
958 ppFuncData
[nFuncPos
+nOld
];
959 pExactHashMap
->insert(
960 ScAddInHashMap::value_type(
961 pData
->GetOriginalName(),
963 pNameHashMap
->insert(
964 ScAddInHashMap::value_type(
965 pData
->GetUpperName(),
967 pLocalHashMap
->insert(
968 ScAddInHashMap::value_type(
969 pData
->GetUpperLocal(),
980 static void lcl_UpdateFunctionList( ScFunctionList
& rFunctionList
, const ScUnoAddInFuncData
& rFuncData
)
982 OUString aCompare
= rFuncData
.GetUpperLocal(); // as used in FillFunctionDescFromData
984 sal_uLong nCount
= rFunctionList
.GetCount();
985 for (sal_uLong nPos
=0; nPos
<nCount
; nPos
++)
987 const ScFuncDesc
* pDesc
= rFunctionList
.GetFunction( nPos
);
988 if ( pDesc
&& pDesc
->pFuncName
&& *pDesc
->pFuncName
== aCompare
)
990 ScUnoAddInCollection::FillFunctionDescFromData( rFuncData
, *const_cast<ScFuncDesc
*>(pDesc
) );
996 static const ScAddInArgDesc
* lcl_FindArgDesc( const ScUnoAddInFuncData
& rFuncData
, const OUString
& rArgIntName
)
998 long nArgCount
= rFuncData
.GetArgumentCount();
999 const ScAddInArgDesc
* pArguments
= rFuncData
.GetArguments();
1000 for (long nPos
=0; nPos
<nArgCount
; nPos
++)
1002 if ( pArguments
[nPos
].aInternalName
== rArgIntName
)
1003 return &pArguments
[nPos
];
1008 void ScUnoAddInCollection::UpdateFromAddIn( const uno::Reference
<uno::XInterface
>& xInterface
,
1009 const OUString
& rServiceName
)
1011 uno::Reference
<lang::XLocalizable
> xLoc( xInterface
, uno::UNO_QUERY
);
1012 if ( xLoc
.is() ) // optional in new add-ins
1014 // fdo50118 when GetUseEnglishFunctionName() returns true, set the
1015 // locale to en-US to get English function names
1016 if ( SC_MOD()->GetFormulaOptions().GetUseEnglishFuncName() )
1017 xLoc
->setLocale( lang::Locale( "en", "US", ""));
1019 xLoc
->setLocale( Application::GetSettings().GetUILanguageTag().getLocale());
1022 // if function list was already initialized, it must be updated
1024 ScFunctionList
* pFunctionList
= NULL
;
1025 if ( ScGlobal::HasStarCalcFunctionList() )
1026 pFunctionList
= ScGlobal::GetStarCalcFunctionList();
1028 // only get the function information from Introspection
1030 uno::Reference
<uno::XComponentContext
> xContext
= comphelper::getProcessComponentContext();
1032 uno::Reference
<beans::XIntrospection
> xIntro
= beans::theIntrospection::get(xContext
);
1034 aObject
<<= xInterface
;
1035 uno::Reference
<beans::XIntrospectionAccess
> xAcc
= xIntro
->inspect(aObject
);
1038 uno::Sequence
< uno::Reference
<reflection::XIdlMethod
> > aMethods
=
1039 xAcc
->getMethods( beans::MethodConcept::ALL
);
1040 long nMethodCount
= aMethods
.getLength();
1041 const uno::Reference
<reflection::XIdlMethod
>* pArray
= aMethods
.getConstArray();
1042 for (long nFuncPos
=0; nFuncPos
<nMethodCount
; nFuncPos
++)
1044 uno::Reference
<reflection::XIdlMethod
> xFunc
= pArray
[nFuncPos
];
1047 OUString aFuncU
= xFunc
->getName();
1049 // stored function name: (service name).(function)
1050 OUStringBuffer
aFuncNameBuffer( rServiceName
.getLength()+1+aFuncU
.getLength());
1051 aFuncNameBuffer
.append(rServiceName
);
1052 aFuncNameBuffer
.append('.');
1053 aFuncNameBuffer
.append(aFuncU
);
1054 OUString aFuncName
= aFuncNameBuffer
.makeStringAndClear();
1056 // internal names are skipped because no FuncData exists
1057 ScUnoAddInFuncData
* pOldData
= const_cast<ScUnoAddInFuncData
*>( GetFuncData( aFuncName
) );
1060 // Create new (complete) argument info.
1061 // As in ReadFromAddIn, the reflection information is authoritative.
1062 // Local names and descriptions from pOldData are looked up using the
1063 // internal argument name.
1066 long nVisibleCount
= 0;
1067 long nCallerPos
= SC_CALLERPOS_NONE
;
1069 uno::Sequence
<reflection::ParamInfo
> aParams
=
1070 xFunc
->getParameterInfos();
1071 long nParamCount
= aParams
.getLength();
1072 const reflection::ParamInfo
* pParArr
= aParams
.getConstArray();
1074 for (nParamPos
=0; nParamPos
<nParamCount
; nParamPos
++)
1076 if ( pParArr
[nParamPos
].aMode
!= reflection::ParamMode_IN
)
1078 uno::Reference
<reflection::XIdlClass
> xParClass
=
1079 pParArr
[nParamPos
].aType
;
1080 ScAddInArgumentType eArgType
= lcl_GetArgType( xParClass
);
1081 if ( eArgType
== SC_ADDINARG_NONE
)
1083 else if ( eArgType
== SC_ADDINARG_CALLER
)
1084 nCallerPos
= nParamPos
;
1090 boost::scoped_array
<ScAddInArgDesc
> pVisibleArgs
;
1091 if ( nVisibleCount
> 0 )
1093 ScAddInArgDesc aDesc
;
1094 pVisibleArgs
.reset(new ScAddInArgDesc
[nVisibleCount
]);
1096 for (nParamPos
=0; nParamPos
<nParamCount
; nParamPos
++)
1098 uno::Reference
<reflection::XIdlClass
> xParClass
=
1099 pParArr
[nParamPos
].aType
;
1100 ScAddInArgumentType eArgType
= lcl_GetArgType( xParClass
);
1101 if ( eArgType
!= SC_ADDINARG_CALLER
)
1103 const ScAddInArgDesc
* pOldArgDesc
=
1104 lcl_FindArgDesc( *pOldData
, pParArr
[nParamPos
].aName
);
1107 aDesc
.aName
= pOldArgDesc
->aName
;
1108 aDesc
.aDescription
= pOldArgDesc
->aDescription
;
1111 aDesc
.aName
= aDesc
.aDescription
= "###";
1114 ( eArgType
== SC_ADDINARG_VALUE_OR_ARRAY
||
1115 eArgType
== SC_ADDINARG_VARARGS
);
1117 aDesc
.eType
= eArgType
;
1118 aDesc
.bOptional
= bOptional
;
1119 //TODO: initialize aInternalName only from config?
1120 aDesc
.aInternalName
= pParArr
[nParamPos
].aName
;
1122 pVisibleArgs
[nDestPos
++] = aDesc
;
1125 OSL_ENSURE( nDestPos
==nVisibleCount
, "wrong count" );
1128 pOldData
->SetFunction( xFunc
, aObject
);
1129 pOldData
->SetArguments( nVisibleCount
, pVisibleArgs
.get() );
1130 pOldData
->SetCallerPos( nCallerPos
);
1132 if ( pFunctionList
)
1133 lcl_UpdateFunctionList( *pFunctionList
, *pOldData
);
1141 OUString
ScUnoAddInCollection::FindFunction( const OUString
& rUpperName
, bool bLocalFirst
)
1146 if (nFuncCount
== 0)
1147 return EMPTY_OUSTRING
;
1151 // first scan all local names (used for entering formulas)
1153 ScAddInHashMap::const_iterator
iLook( pLocalHashMap
->find( rUpperName
) );
1154 if ( iLook
!= pLocalHashMap
->end() )
1155 return iLook
->second
->GetOriginalName();
1159 // first scan international names (used when calling a function)
1160 //TODO: before that, check for exact match???
1162 ScAddInHashMap::const_iterator
iLook( pNameHashMap
->find( rUpperName
) );
1163 if ( iLook
!= pNameHashMap
->end() )
1164 return iLook
->second
->GetOriginalName();
1166 // after that, scan all local names (to allow replacing old AddIns with Uno)
1168 iLook
= pLocalHashMap
->find( rUpperName
);
1169 if ( iLook
!= pLocalHashMap
->end() )
1170 return iLook
->second
->GetOriginalName();
1173 return EMPTY_OUSTRING
;
1176 const ScUnoAddInFuncData
* ScUnoAddInCollection::GetFuncData( const OUString
& rName
, bool bComplete
)
1181 // rName must be the exact internal name
1183 ScAddInHashMap::const_iterator
iLook( pExactHashMap
->find( rName
) );
1184 if ( iLook
!= pExactHashMap
->end() )
1186 const ScUnoAddInFuncData
* pFuncData
= iLook
->second
;
1188 if ( bComplete
&& !pFuncData
->GetFunction().is() ) //TODO: extra flag?
1189 LoadComponent( *pFuncData
);
1197 const ScUnoAddInFuncData
* ScUnoAddInCollection::GetFuncData( long nIndex
)
1202 if (nIndex
< nFuncCount
)
1203 return ppFuncData
[nIndex
];
1207 void ScUnoAddInCollection::LocalizeString( OUString
& rName
)
1212 // modify rName - input: exact name
1214 ScAddInHashMap::const_iterator
iLook( pExactHashMap
->find( rName
) );
1215 if ( iLook
!= pExactHashMap
->end() )
1216 rName
= iLook
->second
->GetUpperLocal(); //TODO: upper?
1219 long ScUnoAddInCollection::GetFuncCount()
1227 bool ScUnoAddInCollection::FillFunctionDesc( long nFunc
, ScFuncDesc
& rDesc
)
1232 if (nFunc
>= nFuncCount
|| !ppFuncData
[nFunc
])
1235 const ScUnoAddInFuncData
& rFuncData
= *ppFuncData
[nFunc
];
1237 return FillFunctionDescFromData( rFuncData
, rDesc
);
1240 bool ScUnoAddInCollection::FillFunctionDescFromData( const ScUnoAddInFuncData
& rFuncData
, ScFuncDesc
& rDesc
)
1244 bool bIncomplete
= !rFuncData
.GetFunction().is(); //TODO: extra flag?
1246 long nArgCount
= rFuncData
.GetArgumentCount();
1247 if ( nArgCount
> USHRT_MAX
)
1251 nArgCount
= 0; // if incomplete, fill without argument info (no wrong order)
1253 // nFIndex is set from outside
1255 rDesc
.pFuncName
= new OUString( rFuncData
.GetUpperLocal() ); //TODO: upper?
1256 rDesc
.nCategory
= rFuncData
.GetCategory();
1257 rDesc
.sHelpId
= rFuncData
.GetHelpId();
1259 OUString aDesc
= rFuncData
.GetDescription();
1260 if (aDesc
.isEmpty())
1261 aDesc
= rFuncData
.GetLocalName(); // use name if no description is available
1262 rDesc
.pFuncDesc
= new OUString( aDesc
);
1264 // AddInArgumentType_CALLER is already left out in FuncData
1266 rDesc
.nArgCount
= (sal_uInt16
)nArgCount
;
1269 bool bMultiple
= false;
1270 const ScAddInArgDesc
* pArgs
= rFuncData
.GetArguments();
1272 rDesc
.maDefArgNames
.clear();
1273 rDesc
.maDefArgNames
.resize(nArgCount
);
1274 rDesc
.maDefArgDescs
.clear();
1275 rDesc
.maDefArgDescs
.resize(nArgCount
);
1276 rDesc
.pDefArgFlags
= new ScFuncDesc::ParameterFlags
[nArgCount
];
1277 for ( long nArg
=0; nArg
<nArgCount
; nArg
++ )
1279 rDesc
.maDefArgNames
[nArg
] = pArgs
[nArg
].aName
;
1280 rDesc
.maDefArgDescs
[nArg
] = pArgs
[nArg
].aDescription
;
1281 rDesc
.pDefArgFlags
[nArg
].bOptional
= pArgs
[nArg
].bOptional
;
1282 rDesc
.pDefArgFlags
[nArg
].bSuppress
= false;
1284 // no empty names...
1285 if ( rDesc
.maDefArgNames
[nArg
].isEmpty() )
1287 OUString
aDefName("arg");
1288 aDefName
+= OUString::number( nArg
+1 );
1289 rDesc
.maDefArgNames
[nArg
] = aDefName
;
1292 // last argument repeated?
1293 if ( nArg
+1 == nArgCount
&& ( pArgs
[nArg
].eType
== SC_ADDINARG_VARARGS
) )
1298 rDesc
.nArgCount
+= VAR_ARGS
- 1; // VAR_ARGS means just one repeated arg
1301 rDesc
.bIncomplete
= bIncomplete
;
1306 ScUnoAddInCall::ScUnoAddInCall( ScUnoAddInCollection
& rColl
, const OUString
& rName
,
1307 long nParamCount
) :
1308 bValidCount( false ),
1309 nErrCode( errNoCode
), // before function was called
1314 pFuncData
= rColl
.GetFuncData( rName
, true ); // need fully initialized data
1315 OSL_ENSURE( pFuncData
, "Function Data missing" );
1318 long nDescCount
= pFuncData
->GetArgumentCount();
1319 const ScAddInArgDesc
* pArgs
= pFuncData
->GetArguments();
1321 // is aVarArg sequence needed?
1322 if ( nParamCount
>= nDescCount
&& nDescCount
> 0 &&
1323 pArgs
[nDescCount
-1].eType
== SC_ADDINARG_VARARGS
)
1325 long nVarCount
= nParamCount
- ( nDescCount
- 1 ); // size of last argument
1326 aVarArg
.realloc( nVarCount
);
1329 else if ( nParamCount
<= nDescCount
)
1331 // all args behind nParamCount must be optional
1333 for (long i
=nParamCount
; i
<nDescCount
; i
++)
1334 if ( !pArgs
[i
].bOptional
)
1335 bValidCount
= false;
1337 // else invalid (too many arguments)
1340 aArgs
.realloc( nDescCount
); // sequence must always match function signature
1344 ScUnoAddInCall::~ScUnoAddInCall()
1346 // pFuncData is deleted with ScUnoAddInCollection
1349 ScAddInArgumentType
ScUnoAddInCall::GetArgType( long nPos
)
1353 long nCount
= pFuncData
->GetArgumentCount();
1354 const ScAddInArgDesc
* pArgs
= pFuncData
->GetArguments();
1356 // if last arg is sequence, use "any" type
1357 if ( nCount
> 0 && nPos
>= nCount
-1 && pArgs
[nCount
-1].eType
== SC_ADDINARG_VARARGS
)
1358 return SC_ADDINARG_VALUE_OR_ARRAY
;
1360 if ( nPos
< nCount
)
1361 return pArgs
[nPos
].eType
;
1363 return SC_ADDINARG_VALUE_OR_ARRAY
; //TODO: error code !!!!
1366 bool ScUnoAddInCall::NeedsCaller() const
1368 return pFuncData
&& pFuncData
->GetCallerPos() != SC_CALLERPOS_NONE
;
1371 void ScUnoAddInCall::SetCaller( const uno::Reference
<uno::XInterface
>& rInterface
)
1373 xCaller
= rInterface
;
1376 void ScUnoAddInCall::SetCallerFromObjectShell( SfxObjectShell
* pObjSh
)
1380 uno::Reference
<uno::XInterface
> xInt( pObjSh
->GetBaseModel(), uno::UNO_QUERY
);
1385 void ScUnoAddInCall::SetParam( long nPos
, const uno::Any
& rValue
)
1389 long nCount
= pFuncData
->GetArgumentCount();
1390 const ScAddInArgDesc
* pArgs
= pFuncData
->GetArguments();
1391 if ( nCount
> 0 && nPos
>= nCount
-1 && pArgs
[nCount
-1].eType
== SC_ADDINARG_VARARGS
)
1393 long nVarPos
= nPos
-(nCount
-1);
1394 if ( nVarPos
< aVarArg
.getLength() )
1395 aVarArg
.getArray()[nVarPos
] = rValue
;
1398 OSL_FAIL("wrong argument number");
1401 else if ( nPos
< aArgs
.getLength() )
1402 aArgs
.getArray()[nPos
] = rValue
;
1405 OSL_FAIL("wrong argument number");
1410 void ScUnoAddInCall::ExecuteCall()
1415 long nCount
= pFuncData
->GetArgumentCount();
1416 const ScAddInArgDesc
* pArgs
= pFuncData
->GetArguments();
1417 if ( nCount
> 0 && pArgs
[nCount
-1].eType
== SC_ADDINARG_VARARGS
)
1419 // insert aVarArg as last argument
1420 //TODO: after inserting caller (to prevent copying twice)?
1422 OSL_ENSURE( aArgs
.getLength() == nCount
, "wrong argument count" );
1423 aArgs
.getArray()[nCount
-1] <<= aVarArg
;
1426 if ( pFuncData
->GetCallerPos() != SC_CALLERPOS_NONE
)
1428 uno::Any aCallerAny
;
1429 aCallerAny
<<= xCaller
;
1431 long nUserLen
= aArgs
.getLength();
1432 long nCallPos
= pFuncData
->GetCallerPos();
1433 if (nCallPos
>nUserLen
) // should not happen
1435 OSL_FAIL("wrong CallPos");
1436 nCallPos
= nUserLen
;
1439 long nDestLen
= nUserLen
+ 1;
1440 uno::Sequence
<uno::Any
> aRealArgs( nDestLen
);
1441 uno::Any
* pDest
= aRealArgs
.getArray();
1443 const uno::Any
* pSource
= aArgs
.getConstArray();
1446 for ( long nDestPos
= 0; nDestPos
< nDestLen
; nDestPos
++ )
1448 if ( nDestPos
== nCallPos
)
1449 pDest
[nDestPos
] = aCallerAny
;
1451 pDest
[nDestPos
] = pSource
[nSrcPos
++];
1454 ExecuteCallWithArgs( aRealArgs
);
1457 ExecuteCallWithArgs( aArgs
);
1460 void ScUnoAddInCall::ExecuteCallWithArgs(uno::Sequence
<uno::Any
>& rCallArgs
)
1462 // rCallArgs may not match argument descriptions (because of caller)
1464 uno::Reference
<reflection::XIdlMethod
> xFunction
;
1468 xFunction
= pFuncData
->GetFunction();
1469 aObject
= pFuncData
->GetObject();
1472 if ( xFunction
.is() )
1479 aAny
= xFunction
->invoke( aObject
, rCallArgs
);
1481 catch(lang::IllegalArgumentException
&)
1483 nErrCode
= errIllegalArgument
;
1486 catch(const reflection::InvocationTargetException
& rWrapped
)
1488 if ( rWrapped
.TargetException
.getValueType().equals(
1489 cppu::UnoType
<lang::IllegalArgumentException
>::get()) )
1490 nErrCode
= errIllegalArgument
;
1491 else if ( rWrapped
.TargetException
.getValueType().equals(
1492 cppu::UnoType
<sheet::NoConvergenceException
>::get()) )
1493 nErrCode
= errNoConvergence
;
1495 nErrCode
= errNoValue
;
1498 catch(uno::Exception
&)
1500 nErrCode
= errNoValue
;
1504 SetResult( aAny
); // convert result to Calc types
1508 void ScUnoAddInCall::SetResult( const uno::Any
& rNewRes
)
1513 // Reflection* pRefl = rNewRes.getReflection();
1515 uno::TypeClass eClass
= rNewRes
.getValueTypeClass();
1516 uno::Type aType
= rNewRes
.getValueType();
1519 case uno::TypeClass_VOID
:
1520 nErrCode
= NOTAVAILABLE
; // #NA
1523 case uno::TypeClass_ENUM
:
1524 case uno::TypeClass_BOOLEAN
:
1525 case uno::TypeClass_CHAR
:
1526 case uno::TypeClass_BYTE
:
1527 case uno::TypeClass_SHORT
:
1528 case uno::TypeClass_UNSIGNED_SHORT
:
1529 case uno::TypeClass_LONG
:
1530 case uno::TypeClass_UNSIGNED_LONG
:
1531 case uno::TypeClass_FLOAT
:
1532 case uno::TypeClass_DOUBLE
:
1534 uno::TypeClass eMyClass
;
1535 ScApiTypeConversion::ConvertAnyToDouble( fValue
, eMyClass
, rNewRes
);
1540 case uno::TypeClass_STRING
:
1542 rNewRes
>>= aString
;
1547 case uno::TypeClass_INTERFACE
:
1549 //TODO: directly extract XVolatileResult from any?
1550 uno::Reference
<uno::XInterface
> xInterface
;
1551 rNewRes
>>= xInterface
;
1552 if ( xInterface
.is() )
1553 xVarRes
= uno::Reference
<sheet::XVolatileResult
>( xInterface
, uno::UNO_QUERY
);
1556 nErrCode
= errNoValue
; // unknown interface
1561 if ( aType
.equals( cppu::UnoType
<uno::Sequence
< uno::Sequence
<sal_Int32
> >>::get() ) )
1563 const uno::Sequence
< uno::Sequence
<sal_Int32
> >* pRowSeq
= NULL
;
1565 //TODO: use pointer from any!
1566 uno::Sequence
< uno::Sequence
<sal_Int32
> > aSequence
;
1567 if ( rNewRes
>>= aSequence
)
1568 pRowSeq
= &aSequence
;
1572 long nRowCount
= pRowSeq
->getLength();
1573 const uno::Sequence
<sal_Int32
>* pRowArr
= pRowSeq
->getConstArray();
1574 long nMaxColCount
= 0;
1576 for (nRow
=0; nRow
<nRowCount
; nRow
++)
1578 long nTmp
= pRowArr
[nRow
].getLength();
1579 if ( nTmp
> nMaxColCount
)
1580 nMaxColCount
= nTmp
;
1582 if ( nMaxColCount
&& nRowCount
)
1584 xMatrix
= new ScMatrix(
1585 static_cast<SCSIZE
>(nMaxColCount
),
1586 static_cast<SCSIZE
>(nRowCount
), 0.0);
1587 for (nRow
=0; nRow
<nRowCount
; nRow
++)
1589 long nColCount
= pRowArr
[nRow
].getLength();
1590 const sal_Int32
* pColArr
= pRowArr
[nRow
].getConstArray();
1591 for (nCol
=0; nCol
<nColCount
; nCol
++)
1592 xMatrix
->PutDouble( pColArr
[nCol
],
1593 static_cast<SCSIZE
>(nCol
),
1594 static_cast<SCSIZE
>(nRow
) );
1595 for (nCol
=nColCount
; nCol
<nMaxColCount
; nCol
++)
1596 xMatrix
->PutDouble( 0.0,
1597 static_cast<SCSIZE
>(nCol
),
1598 static_cast<SCSIZE
>(nRow
) );
1603 else if ( aType
.equals( cppu::UnoType
<uno::Sequence
< uno::Sequence
<double> >>::get() ) )
1605 const uno::Sequence
< uno::Sequence
<double> >* pRowSeq
= NULL
;
1607 //TODO: use pointer from any!
1608 uno::Sequence
< uno::Sequence
<double> > aSequence
;
1609 if ( rNewRes
>>= aSequence
)
1610 pRowSeq
= &aSequence
;
1614 long nRowCount
= pRowSeq
->getLength();
1615 const uno::Sequence
<double>* pRowArr
= pRowSeq
->getConstArray();
1616 long nMaxColCount
= 0;
1618 for (nRow
=0; nRow
<nRowCount
; nRow
++)
1620 long nTmp
= pRowArr
[nRow
].getLength();
1621 if ( nTmp
> nMaxColCount
)
1622 nMaxColCount
= nTmp
;
1624 if ( nMaxColCount
&& nRowCount
)
1626 xMatrix
= new ScMatrix(
1627 static_cast<SCSIZE
>(nMaxColCount
),
1628 static_cast<SCSIZE
>(nRowCount
), 0.0);
1629 for (nRow
=0; nRow
<nRowCount
; nRow
++)
1631 long nColCount
= pRowArr
[nRow
].getLength();
1632 const double* pColArr
= pRowArr
[nRow
].getConstArray();
1633 for (nCol
=0; nCol
<nColCount
; nCol
++)
1634 xMatrix
->PutDouble( pColArr
[nCol
],
1635 static_cast<SCSIZE
>(nCol
),
1636 static_cast<SCSIZE
>(nRow
) );
1637 for (nCol
=nColCount
; nCol
<nMaxColCount
; nCol
++)
1638 xMatrix
->PutDouble( 0.0,
1639 static_cast<SCSIZE
>(nCol
),
1640 static_cast<SCSIZE
>(nRow
) );
1645 else if ( aType
.equals( cppu::UnoType
<uno::Sequence
< uno::Sequence
<OUString
> >>::get() ) )
1647 const uno::Sequence
< uno::Sequence
<OUString
> >* pRowSeq
= NULL
;
1649 //TODO: use pointer from any!
1650 uno::Sequence
< uno::Sequence
<OUString
> > aSequence
;
1651 if ( rNewRes
>>= aSequence
)
1652 pRowSeq
= &aSequence
;
1656 long nRowCount
= pRowSeq
->getLength();
1657 const uno::Sequence
<OUString
>* pRowArr
= pRowSeq
->getConstArray();
1658 long nMaxColCount
= 0;
1660 for (nRow
=0; nRow
<nRowCount
; nRow
++)
1662 long nTmp
= pRowArr
[nRow
].getLength();
1663 if ( nTmp
> nMaxColCount
)
1664 nMaxColCount
= nTmp
;
1666 if ( nMaxColCount
&& nRowCount
)
1668 xMatrix
= new ScMatrix(
1669 static_cast<SCSIZE
>(nMaxColCount
),
1670 static_cast<SCSIZE
>(nRowCount
), 0.0);
1671 for (nRow
=0; nRow
<nRowCount
; nRow
++)
1673 long nColCount
= pRowArr
[nRow
].getLength();
1674 const OUString
* pColArr
= pRowArr
[nRow
].getConstArray();
1675 for (nCol
=0; nCol
<nColCount
; nCol
++)
1678 svl::SharedString(pColArr
[nCol
]),
1679 static_cast<SCSIZE
>(nCol
), static_cast<SCSIZE
>(nRow
));
1681 for (nCol
=nColCount
; nCol
<nMaxColCount
; nCol
++)
1684 svl::SharedString(EMPTY_OUSTRING
),
1685 static_cast<SCSIZE
>(nCol
), static_cast<SCSIZE
>(nRow
));
1691 else if ( aType
.equals( cppu::UnoType
<uno::Sequence
< uno::Sequence
<uno::Any
> >>::get() ) )
1693 xMatrix
= ScSequenceToMatrix::CreateMixedMatrix( rNewRes
);
1696 if (!xMatrix
) // no array found
1697 nErrCode
= errNoValue
; //TODO: code for error in return type???
1701 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */