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 <sfx2/objsh.hxx>
24 #include <unotools/charclass.hxx>
26 #include <com/sun/star/container/XContentEnumerationAccess.hpp>
27 #include <com/sun/star/lang/XServiceName.hpp>
28 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
29 #include <com/sun/star/lang/XSingleComponentFactory.hpp>
30 #include <com/sun/star/reflection/XIdlClass.hpp>
31 #include <com/sun/star/beans/XIntrospectionAccess.hpp>
32 #include <com/sun/star/beans/Introspection.hpp>
33 #include <com/sun/star/beans/MethodConcept.hpp>
34 #include <com/sun/star/beans/XPropertySet.hpp>
35 #include <com/sun/star/table/XCellRange.hpp>
36 #include <com/sun/star/lang/Locale.hpp>
37 #include <com/sun/star/sheet/XCompatibilityNames.hpp>
38 #include <com/sun/star/sheet/NoConvergenceException.hpp>
40 #include "addincol.hxx"
41 #include "addinhelpid.hxx"
42 #include "compiler.hxx"
43 #include "scmatrix.hxx"
44 #include "addinlis.hxx"
45 #include "formula/errorcodes.hxx"
46 #include "scfuncs.hrc"
47 #include "optutil.hxx"
48 #include "addincfg.hxx"
50 #include "rangeseq.hxx"
51 #include "funcdesc.hxx"
52 #include "svl/sharedstring.hxx"
53 #include "formulaopt.hxx"
55 using namespace com::sun::star
;
57 #define SC_CALLERPOS_NONE (-1)
59 ScUnoAddInFuncData::ScUnoAddInFuncData( const OUString
& rNam
, const OUString
& rLoc
,
60 const OUString
& rDesc
,
61 sal_uInt16 nCat
, const OString
& sHelp
,
62 const uno::Reference
<reflection::XIdlMethod
>& rFunc
,
64 long nAC
, const ScAddInArgDesc
* pAD
,
66 aOriginalName( rNam
),
70 aDescription( rDesc
),
77 bCompInitialized( false )
81 pArgDescs
= new ScAddInArgDesc
[nArgCount
];
82 for (long i
=0; i
<nArgCount
; i
++)
83 pArgDescs
[i
] = pAD
[i
];
88 aUpperName
= ScGlobal::pCharClass
->uppercase(aUpperName
);
89 aUpperLocal
= ScGlobal::pCharClass
->uppercase(aUpperLocal
);
92 ScUnoAddInFuncData::~ScUnoAddInFuncData()
97 const ::std::vector
<ScUnoAddInFuncData::LocalizedName
>& ScUnoAddInFuncData::GetCompNames() const
99 if ( !bCompInitialized
)
101 // read sequence of compatibility names on demand
103 uno::Reference
<sheet::XAddIn
> xAddIn
;
104 if ( aObject
>>= xAddIn
)
106 uno::Reference
<sheet::XCompatibilityNames
> xComp( xAddIn
, uno::UNO_QUERY
);
107 if ( xComp
.is() && xFunction
.is() )
109 OUString aMethodName
= xFunction
->getName();
110 uno::Sequence
< sheet::LocalizedName
> aCompNames( xComp
->getCompatibilityNames( aMethodName
));
112 sal_Int32 nSeqLen
= aCompNames
.getLength();
115 const sheet::LocalizedName
* pArray
= aCompNames
.getArray();
116 for (sal_Int32 i
=0; i
<nSeqLen
; i
++)
118 maCompNames
.push_back( LocalizedName(
119 LanguageTag::convertToBcp47( pArray
[i
].Locale
, false),
126 bCompInitialized
= true; // also if not successful
131 void ScUnoAddInFuncData::SetCompNames( const ::std::vector
< ScUnoAddInFuncData::LocalizedName
>& rNew
)
133 OSL_ENSURE( !bCompInitialized
, "SetCompNames after initializing" );
137 bCompInitialized
= true;
140 bool ScUnoAddInFuncData::GetExcelName( LanguageType eDestLang
, OUString
& rRetExcelName
) const
142 const ::std::vector
<LocalizedName
>& rCompNames
= GetCompNames();
143 if ( !rCompNames
.empty() )
145 LanguageTag
aLanguageTag( eDestLang
);
146 const OUString
aSearch( aLanguageTag
.getBcp47());
148 // First, check exact match without fallback overhead.
149 ::std::vector
<LocalizedName
>::const_iterator
itNames( rCompNames
.begin());
150 for ( ; itNames
!= rCompNames
.end(); ++itNames
)
152 if ((*itNames
).maLocale
== aSearch
)
154 rRetExcelName
= (*itNames
).maName
;
159 // Second, try match of fallback search with fallback locales,
160 // appending also 'en-US' and 'en' to search if not queried.
161 ::std::vector
< OUString
> aFallbackSearch( aLanguageTag
.getFallbackStrings( true));
162 if (aSearch
!= "en-US")
164 aFallbackSearch
.push_back( "en-US");
167 aFallbackSearch
.push_back( "en");
170 ::std::vector
< OUString
>::const_iterator
itSearch( aFallbackSearch
.begin());
171 for ( ; itSearch
!= aFallbackSearch
.end(); ++itSearch
)
173 itNames
= rCompNames
.begin();
174 for ( ; itNames
!= rCompNames
.end(); ++itNames
)
176 // We checked already the full tag, start with second.
177 ::std::vector
< OUString
> aFallbackLocales( LanguageTag( (*itNames
).maLocale
).getFallbackStrings( false));
178 for (::std::vector
< OUString
>::const_iterator
itLocales( aFallbackLocales
.begin());
179 itLocales
!= aFallbackLocales
.end(); ++itLocales
)
181 if (*itLocales
== *itSearch
)
183 rRetExcelName
= (*itNames
).maName
;
190 // Third, last resort, use first (default) entry.
191 rRetExcelName
= rCompNames
[0].maName
;
197 void ScUnoAddInFuncData::SetFunction( const uno::Reference
< reflection::XIdlMethod
>& rNewFunc
, const uno::Any
& rNewObj
)
199 xFunction
= rNewFunc
;
203 void ScUnoAddInFuncData::SetArguments( long nNewCount
, const ScAddInArgDesc
* pNewDescs
)
207 nArgCount
= nNewCount
;
210 pArgDescs
= new ScAddInArgDesc
[nArgCount
];
211 for (long i
=0; i
<nArgCount
; i
++)
212 pArgDescs
[i
] = pNewDescs
[i
];
218 void ScUnoAddInFuncData::SetCallerPos( long nNewPos
)
220 nCallerPos
= nNewPos
;
223 ScUnoAddInCollection::ScUnoAddInCollection() :
226 pExactHashMap( NULL
),
227 pNameHashMap( NULL
),
228 pLocalHashMap( NULL
),
229 bInitialized( false )
233 ScUnoAddInCollection::~ScUnoAddInCollection()
238 void ScUnoAddInCollection::Clear()
240 DELETEZ( pExactHashMap
);
241 DELETEZ( pNameHashMap
);
242 DELETEZ( pLocalHashMap
);
245 for ( long i
=0; i
<nFuncCount
; i
++ )
246 delete ppFuncData
[i
];
252 bInitialized
= false;
255 void ScUnoAddInCollection::Initialize()
257 OSL_ENSURE( !bInitialized
, "Initialize twice?" );
259 uno::Reference
<lang::XMultiServiceFactory
> xManager
= comphelper::getProcessServiceFactory();
260 uno::Reference
<container::XContentEnumerationAccess
> xEnAc( xManager
, uno::UNO_QUERY
);
263 uno::Reference
<container::XEnumeration
> xEnum
=
264 xEnAc
->createContentEnumeration( "com.sun.star.sheet.AddIn" );
267 // loop through all AddIns
268 while ( xEnum
->hasMoreElements() )
270 uno::Any aAddInAny
= xEnum
->nextElement();
274 uno::Reference
<uno::XInterface
> xIntFac
;
275 aAddInAny
>>= xIntFac
;
278 // #i59984# try XSingleComponentFactory in addition to (old) XSingleServiceFactory,
279 // passing the context to the component
281 uno::Reference
<uno::XInterface
> xInterface
;
282 uno::Reference
<uno::XComponentContext
> xCtx(
283 comphelper::getComponentContext(xManager
));
284 uno::Reference
<lang::XSingleComponentFactory
> xCFac( xIntFac
, uno::UNO_QUERY
);
287 xInterface
= xCFac
->createInstanceWithContext(xCtx
);
289 ReadFromAddIn( xInterface
);
292 if (!xInterface
.is())
294 uno::Reference
<lang::XSingleServiceFactory
> xFac( xIntFac
, uno::UNO_QUERY
);
297 xInterface
= xFac
->createInstance();
299 ReadFromAddIn( xInterface
);
303 } catch ( const uno::Exception
& ) {
304 SAL_WARN ( "sc", "Failed to initialize create instance of sheet.AddIn" );
310 // ReadConfiguration is called after looking at the AddIn implementations.
311 // Duplicated are skipped (by using the service information, they don't have to be updated again
312 // when argument information is needed).
315 bInitialized
= true; // with or without functions
318 static sal_uInt16
lcl_GetCategory( const OUString
& rName
)
320 static const sal_Char
* aFuncNames
[SC_FUNCGROUP_COUNT
] =
322 // array index = ID - 1 (ID starts at 1)
324 "Database", // ID_FUNCTION_GRP_DATABASE
325 "Date&Time", // ID_FUNCTION_GRP_DATETIME
326 "Financial", // ID_FUNCTION_GRP_FINANZ
327 "Information", // ID_FUNCTION_GRP_INFO
328 "Logical", // ID_FUNCTION_GRP_LOGIC
329 "Mathematical", // ID_FUNCTION_GRP_MATH
330 "Matrix", // ID_FUNCTION_GRP_MATRIX
331 "Statistical", // ID_FUNCTION_GRP_STATISTIC
332 "Spreadsheet", // ID_FUNCTION_GRP_TABLE
333 "Text", // ID_FUNCTION_GRP_TEXT
334 "Add-In" // ID_FUNCTION_GRP_ADDINS
336 for (sal_uInt16 i
=0; i
<SC_FUNCGROUP_COUNT
; i
++)
337 if ( rName
.equalsAscii( aFuncNames
[i
] ) )
338 return i
+1; // IDs start at 1
340 return ID_FUNCTION_GRP_ADDINS
; // if not found, use Add-In group
343 #define CFGPATH_ADDINS "Office.CalcAddIns/AddInInfo"
344 #define CFGSTR_ADDINFUNCTIONS "AddInFunctions"
346 #define CFG_FUNCPROP_DISPLAYNAME 0
347 #define CFG_FUNCPROP_DESCRIPTION 1
348 #define CFG_FUNCPROP_CATEGORY 2
349 #define CFG_FUNCPROP_COUNT 3
350 #define CFGSTR_DISPLAYNAME "DisplayName"
351 #define CFGSTR_DESCRIPTION "Description"
352 #define CFGSTR_CATEGORY "Category"
353 // CategoryDisplayName is ignored for now
355 #define CFGSTR_COMPATIBILITYNAME "CompatibilityName"
356 #define CFGSTR_PARAMETERS "Parameters"
358 void ScUnoAddInCollection::ReadConfiguration()
360 // called only from Initialize
362 ScAddInCfg
& rAddInConfig
= SC_MOD()->GetAddInCfg();
364 // additional, temporary config item for the compatibility names
365 ScLinkConfigItem
aAllLocalesConfig( OUString(CFGPATH_ADDINS
), CONFIG_MODE_ALL_LOCALES
);
366 // CommitLink is not used (only reading values)
368 const OUString
sSlash('/');
370 // get the list of add-ins (services)
371 OUString aEmptyString
;
372 uno::Sequence
<OUString
> aServiceNames
= rAddInConfig
.GetNodeNames( aEmptyString
);
374 sal_Int32 nServiceCount
= aServiceNames
.getLength();
375 for ( sal_Int32 nService
= 0; nService
< nServiceCount
; nService
++ )
377 OUString aServiceName
= aServiceNames
[nService
];
378 ScUnoAddInHelpIdGenerator
aHelpIdGenerator( aServiceName
);
380 OUString aFunctionsPath
= aServiceName
;
381 aFunctionsPath
+= sSlash
;
382 aFunctionsPath
+= OUString(CFGSTR_ADDINFUNCTIONS
);
384 uno::Sequence
<OUString
> aFunctionNames
= rAddInConfig
.GetNodeNames( aFunctionsPath
);
385 sal_Int32 nNewCount
= aFunctionNames
.getLength();
389 long nOld
= nFuncCount
;
390 nFuncCount
= nNewCount
+nOld
;
393 ScUnoAddInFuncData
** ppNew
= new ScUnoAddInFuncData
*[nFuncCount
];
394 for (long i
=0; i
<nOld
; i
++)
395 ppNew
[i
] = ppFuncData
[i
];
400 ppFuncData
= new ScUnoAddInFuncData
*[nFuncCount
];
402 //! TODO: adjust bucket count?
403 if ( !pExactHashMap
)
404 pExactHashMap
= new ScAddInHashMap
;
406 pNameHashMap
= new ScAddInHashMap
;
407 if ( !pLocalHashMap
)
408 pLocalHashMap
= new ScAddInHashMap
;
410 //! get the function information in a single call for all functions?
412 const OUString
* pFuncNameArray
= aFunctionNames
.getConstArray();
413 for ( sal_Int32 nFuncPos
= 0; nFuncPos
< nNewCount
; nFuncPos
++ )
415 ppFuncData
[nFuncPos
+nOld
] = NULL
;
417 // stored function name: (service name).(function)
418 OUStringBuffer
aFuncNameBuffer( aServiceName
.getLength()+1+pFuncNameArray
[nFuncPos
].getLength());
419 aFuncNameBuffer
.append(aServiceName
);
420 aFuncNameBuffer
.append('.');
421 aFuncNameBuffer
.append(pFuncNameArray
[nFuncPos
]);
422 OUString aFuncName
= aFuncNameBuffer
.makeStringAndClear();
424 // skip the function if already known (read from old AddIn service)
426 if ( pExactHashMap
->find( aFuncName
) == pExactHashMap
->end() )
429 OUString aDescription
;
430 sal_uInt16 nCategory
= ID_FUNCTION_GRP_ADDINS
;
432 // get direct information on the function
434 OUString aFuncPropPath
= aFunctionsPath
;
435 aFuncPropPath
+= sSlash
;
436 aFuncPropPath
+= pFuncNameArray
[nFuncPos
];
437 aFuncPropPath
+= sSlash
;
439 uno::Sequence
<OUString
> aFuncPropNames(CFG_FUNCPROP_COUNT
);
440 OUString
* pNameArray
= aFuncPropNames
.getArray();
441 pNameArray
[CFG_FUNCPROP_DISPLAYNAME
] = aFuncPropPath
;
442 pNameArray
[CFG_FUNCPROP_DISPLAYNAME
] += OUString(CFGSTR_DISPLAYNAME
);
443 pNameArray
[CFG_FUNCPROP_DESCRIPTION
] = aFuncPropPath
;
444 pNameArray
[CFG_FUNCPROP_DESCRIPTION
] += OUString(CFGSTR_DESCRIPTION
);
445 pNameArray
[CFG_FUNCPROP_CATEGORY
] = aFuncPropPath
;
446 pNameArray
[CFG_FUNCPROP_CATEGORY
] += OUString(CFGSTR_CATEGORY
);
448 uno::Sequence
<uno::Any
> aFuncProperties
= rAddInConfig
.GetProperties( aFuncPropNames
);
449 if ( aFuncProperties
.getLength() == CFG_FUNCPROP_COUNT
)
451 aFuncProperties
[CFG_FUNCPROP_DISPLAYNAME
] >>= aLocalName
;
452 aFuncProperties
[CFG_FUNCPROP_DESCRIPTION
] >>= aDescription
;
454 OUString aCategoryName
;
455 aFuncProperties
[CFG_FUNCPROP_CATEGORY
] >>= aCategoryName
;
456 nCategory
= lcl_GetCategory( aCategoryName
);
459 // get compatibility names
461 ::std::vector
<ScUnoAddInFuncData::LocalizedName
> aCompNames
;
463 OUString aCompPath
= aFuncPropPath
;
464 aCompPath
+= OUString(CFGSTR_COMPATIBILITYNAME
);
465 uno::Sequence
<OUString
> aCompPropNames( &aCompPath
, 1 );
467 uno::Sequence
<uno::Any
> aCompProperties
= aAllLocalesConfig
.GetProperties( aCompPropNames
);
468 if ( aCompProperties
.getLength() == 1 )
470 uno::Sequence
<beans::PropertyValue
> aLocalEntries
;
471 if ( aCompProperties
[0] >>= aLocalEntries
)
473 sal_Int32 nLocaleCount
= aLocalEntries
.getLength();
474 const beans::PropertyValue
* pConfigArray
= aLocalEntries
.getConstArray();
476 for ( sal_Int32 nLocale
= 0; nLocale
< nLocaleCount
; nLocale
++ )
478 // PropertyValue name is the locale ("convert" from
479 // string to string to canonicalize)
480 OUString
aLocale( LanguageTag( pConfigArray
[nLocale
].Name
, true).getBcp47( false));
481 // PropertyValue value is the localized value (string in this case)
483 pConfigArray
[nLocale
].Value
>>= aName
;
484 aCompNames
.push_back( ScUnoAddInFuncData::LocalizedName( aLocale
, aName
));
491 ScAddInArgDesc
* pVisibleArgs
= NULL
;
492 long nVisibleCount
= 0;
493 long nCallerPos
= SC_CALLERPOS_NONE
;
495 OUString aArgumentsPath
= aFuncPropPath
;
496 aArgumentsPath
+= OUString(CFGSTR_PARAMETERS
);
498 uno::Sequence
<OUString
> aArgumentNames
= rAddInConfig
.GetNodeNames( aArgumentsPath
);
499 sal_Int32 nArgumentCount
= aArgumentNames
.getLength();
500 if ( nArgumentCount
)
502 // get DisplayName and Description for each argument
503 uno::Sequence
<OUString
> aArgPropNames( nArgumentCount
* 2 );
504 OUString
* pPropNameArray
= aArgPropNames
.getArray();
507 sal_Int32 nIndex
= 0;
508 const OUString
* pArgNameArray
= aArgumentNames
.getConstArray();
509 for ( nArgument
= 0; nArgument
< nArgumentCount
; nArgument
++ )
511 OUString aOneArgPath
= aArgumentsPath
;
512 aOneArgPath
+= sSlash
;
513 aOneArgPath
+= pArgNameArray
[nArgument
];
514 aOneArgPath
+= sSlash
;
516 pPropNameArray
[nIndex
] = aOneArgPath
;
517 pPropNameArray
[nIndex
++] += OUString(CFGSTR_DISPLAYNAME
);
518 pPropNameArray
[nIndex
] = aOneArgPath
;
519 pPropNameArray
[nIndex
++] += OUString(CFGSTR_DESCRIPTION
);
522 uno::Sequence
<uno::Any
> aArgProperties
= rAddInConfig
.GetProperties( aArgPropNames
);
523 if ( aArgProperties
.getLength() == aArgPropNames
.getLength() )
525 const uno::Any
* pPropArray
= aArgProperties
.getConstArray();
526 OUString sDisplayName
;
527 OUString sDescription
;
529 ScAddInArgDesc aDesc
;
530 aDesc
.eType
= SC_ADDINARG_NONE
; // arg type is not in configuration
531 aDesc
.bOptional
= false;
533 nVisibleCount
= nArgumentCount
;
534 pVisibleArgs
= new ScAddInArgDesc
[nVisibleCount
];
537 for ( nArgument
= 0; nArgument
< nArgumentCount
; nArgument
++ )
539 pPropArray
[nIndex
++] >>= sDisplayName
;
540 pPropArray
[nIndex
++] >>= sDescription
;
542 aDesc
.aInternalName
= pArgNameArray
[nArgument
];
543 aDesc
.aName
= sDisplayName
;
544 aDesc
.aDescription
= sDescription
;
546 pVisibleArgs
[nArgument
] = aDesc
;
551 OString sHelpId
= aHelpIdGenerator
.GetHelpId( pFuncNameArray
[nFuncPos
] );
553 uno::Reference
<reflection::XIdlMethod
> xFunc
; // remains empty
554 uno::Any aObject
; // also empty
556 // create and insert into the array
558 ScUnoAddInFuncData
* pData
= new ScUnoAddInFuncData(
559 aFuncName
, aLocalName
, aDescription
,
562 nVisibleCount
, pVisibleArgs
, nCallerPos
);
564 pData
->SetCompNames( aCompNames
);
566 ppFuncData
[nFuncPos
+nOld
] = pData
;
568 pExactHashMap
->insert(
569 ScAddInHashMap::value_type(
570 pData
->GetOriginalName(),
572 pNameHashMap
->insert(
573 ScAddInHashMap::value_type(
574 pData
->GetUpperName(),
576 pLocalHashMap
->insert(
577 ScAddInHashMap::value_type(
578 pData
->GetUpperLocal(),
581 delete[] pVisibleArgs
;
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
);
595 uno::Reference
<lang::XMultiServiceFactory
> xServiceFactory
= comphelper::getProcessServiceFactory();
596 uno::Reference
<uno::XInterface
> xInterface( xServiceFactory
->createInstance( aServiceName
) );
599 UpdateFromAddIn( xInterface
, aServiceName
);
603 bool ScUnoAddInCollection::GetExcelName( const OUString
& rCalcName
,
604 LanguageType eDestLang
, OUString
& rRetExcelName
)
606 const ScUnoAddInFuncData
* pFuncData
= GetFuncData( rCalcName
);
608 return pFuncData
->GetExcelName( eDestLang
, rRetExcelName
);
612 bool ScUnoAddInCollection::GetCalcName( const OUString
& rExcelName
, OUString
& rRetCalcName
)
617 OUString aUpperCmp
= ScGlobal::pCharClass
->uppercase(rExcelName
);
619 for (long i
=0; i
<nFuncCount
; i
++)
621 ScUnoAddInFuncData
* pFuncData
= ppFuncData
[i
];
624 const ::std::vector
<ScUnoAddInFuncData::LocalizedName
>& rNames
= pFuncData
->GetCompNames();
625 if ( !rNames
.empty() )
627 ::std::vector
<ScUnoAddInFuncData::LocalizedName
>::const_iterator
it( rNames
.begin());
628 for ( ; it
!= rNames
.end(); ++it
)
630 if ( ScGlobal::pCharClass
->uppercase( (*it
).maName
) == aUpperCmp
)
632 //! store upper case for comparing?
634 // use the first function that has this name for any language
635 rRetCalcName
= pFuncData
->GetOriginalName();
645 inline bool IsTypeName( const OUString
& rName
, const uno::Type
& rType
)
647 return rName
== rType
.getTypeName();
650 static bool lcl_ValidReturnType( const uno::Reference
<reflection::XIdlClass
>& xClass
)
652 // this must match with ScUnoAddInCall::SetResult
654 if ( !xClass
.is() ) return false;
656 switch (xClass
->getTypeClass())
658 case uno::TypeClass_ANY
: // variable type
659 case uno::TypeClass_ENUM
: //! ???
660 case uno::TypeClass_BOOLEAN
:
661 case uno::TypeClass_CHAR
:
662 case uno::TypeClass_BYTE
:
663 case uno::TypeClass_SHORT
:
664 case uno::TypeClass_UNSIGNED_SHORT
:
665 case uno::TypeClass_LONG
:
666 case uno::TypeClass_UNSIGNED_LONG
:
667 case uno::TypeClass_FLOAT
:
668 case uno::TypeClass_DOUBLE
:
669 case uno::TypeClass_STRING
:
670 return true; // values or string
672 case uno::TypeClass_INTERFACE
:
674 // return type XInterface may contain a XVolatileResult
675 //! XIdlClass needs getType() method!
677 OUString sName
= xClass
->getName();
679 IsTypeName( sName
, getCppuType((uno::Reference
<sheet::XVolatileResult
>*)0) ) ||
680 IsTypeName( sName
, getCppuType((uno::Reference
<uno::XInterface
>*)0) ) );
685 // nested sequences for arrays
686 //! XIdlClass needs getType() method!
688 OUString sName
= xClass
->getName();
690 IsTypeName( sName
, getCppuType((uno::Sequence
< uno::Sequence
<sal_Int32
> >*)0) ) ||
691 IsTypeName( sName
, getCppuType((uno::Sequence
< uno::Sequence
<double> >*)0) ) ||
692 IsTypeName( sName
, getCppuType((uno::Sequence
< uno::Sequence
<OUString
> >*)0) ) ||
693 IsTypeName( sName
, getCppuType((uno::Sequence
< uno::Sequence
<uno::Any
> >*)0) ) );
698 static ScAddInArgumentType
lcl_GetArgType( const uno::Reference
<reflection::XIdlClass
>& xClass
)
701 return SC_ADDINARG_NONE
;
703 uno::TypeClass eType
= xClass
->getTypeClass();
705 if ( eType
== uno::TypeClass_LONG
) //! other integer types?
706 return SC_ADDINARG_INTEGER
;
708 if ( eType
== uno::TypeClass_DOUBLE
)
709 return SC_ADDINARG_DOUBLE
;
711 if ( eType
== uno::TypeClass_STRING
)
712 return SC_ADDINARG_STRING
;
714 //! XIdlClass needs getType() method!
715 OUString sName
= xClass
->getName();
717 if (IsTypeName( sName
, getCppuType((uno::Sequence
< uno::Sequence
<sal_Int32
> >*)0) ))
718 return SC_ADDINARG_INTEGER_ARRAY
;
720 if (IsTypeName( sName
, getCppuType((uno::Sequence
< uno::Sequence
<double> >*)0) ))
721 return SC_ADDINARG_DOUBLE_ARRAY
;
723 if (IsTypeName( sName
, getCppuType((uno::Sequence
< uno::Sequence
<OUString
> >*)0) ))
724 return SC_ADDINARG_STRING_ARRAY
;
726 if (IsTypeName( sName
, getCppuType((uno::Sequence
< uno::Sequence
<uno::Any
> >*)0) ))
727 return SC_ADDINARG_MIXED_ARRAY
;
729 if (IsTypeName( sName
, getCppuType((uno::Any
*)0) ))
730 return SC_ADDINARG_VALUE_OR_ARRAY
;
732 if (IsTypeName( sName
, getCppuType((uno::Reference
<table::XCellRange
>*)0) ))
733 return SC_ADDINARG_CELLRANGE
;
735 if (IsTypeName( sName
, getCppuType((uno::Reference
<beans::XPropertySet
>*)0) ))
736 return SC_ADDINARG_CALLER
;
738 if (IsTypeName( sName
, getCppuType((uno::Sequence
<uno::Any
>*)0) ))
739 return SC_ADDINARG_VARARGS
;
741 return SC_ADDINARG_NONE
;
744 void ScUnoAddInCollection::ReadFromAddIn( const uno::Reference
<uno::XInterface
>& xInterface
)
746 uno::Reference
<sheet::XAddIn
> xAddIn( xInterface
, uno::UNO_QUERY
);
747 uno::Reference
<lang::XServiceName
> xName( xInterface
, uno::UNO_QUERY
);
748 if ( xAddIn
.is() && xName
.is() )
750 // fdo50118 when GetUseEnglishFunctionName() returns true, set the
751 // locale to en-US to get English function names
752 if ( SC_MOD()->GetFormulaOptions().GetUseEnglishFuncName() )
753 xAddIn
->setLocale( lang::Locale( "en", "US", ""));
755 xAddIn
->setLocale( Application::GetSettings().GetUILanguageTag().getLocale());
757 OUString
aServiceName( xName
->getServiceName() );
758 ScUnoAddInHelpIdGenerator
aHelpIdGenerator( aServiceName
);
760 //! pass XIntrospection to ReadFromAddIn
762 uno::Reference
<uno::XComponentContext
> xContext
= comphelper::getProcessComponentContext();
764 uno::Reference
<beans::XIntrospection
> xIntro
= beans::Introspection::create( xContext
);
767 uno::Reference
<beans::XIntrospectionAccess
> xAcc
= xIntro
->inspect(aObject
);
770 uno::Sequence
< uno::Reference
<reflection::XIdlMethod
> > aMethods
=
771 xAcc
->getMethods( beans::MethodConcept::ALL
);
772 long nNewCount
= aMethods
.getLength();
775 long nOld
= nFuncCount
;
776 nFuncCount
= nNewCount
+nOld
;
779 ScUnoAddInFuncData
** ppNew
= new ScUnoAddInFuncData
*[nFuncCount
];
780 for (long i
=0; i
<nOld
; i
++)
781 ppNew
[i
] = ppFuncData
[i
];
786 ppFuncData
= new ScUnoAddInFuncData
*[nFuncCount
];
788 //! TODO: adjust bucket count?
789 if ( !pExactHashMap
)
790 pExactHashMap
= new ScAddInHashMap
;
792 pNameHashMap
= new ScAddInHashMap
;
793 if ( !pLocalHashMap
)
794 pLocalHashMap
= new ScAddInHashMap
;
796 const uno::Reference
<reflection::XIdlMethod
>* pArray
= aMethods
.getConstArray();
797 for (long nFuncPos
=0; nFuncPos
<nNewCount
; nFuncPos
++)
799 ppFuncData
[nFuncPos
+nOld
] = NULL
;
801 uno::Reference
<reflection::XIdlMethod
> xFunc
= pArray
[nFuncPos
];
804 // leave out internal functions
805 uno::Reference
<reflection::XIdlClass
> xClass
=
806 xFunc
->getDeclaringClass();
810 //! XIdlClass needs getType() method!
811 OUString sName
= xClass
->getName();
814 getCppuType((uno::Reference
<uno::XInterface
>*)0) ) ||
816 getCppuType((uno::Reference
<lang::XServiceName
>*)0) ) ||
818 getCppuType((uno::Reference
<lang::XServiceInfo
>*)0) ) ||
820 getCppuType((uno::Reference
<sheet::XAddIn
>*)0) ) );
824 uno::Reference
<reflection::XIdlClass
> xReturn
=
825 xFunc
->getReturnType();
826 if ( !lcl_ValidReturnType( xReturn
) )
831 OUString aFuncU
= xFunc
->getName();
833 // stored function name: (service name).(function)
834 OUStringBuffer
aFuncNameBuffer( aServiceName
.getLength()+1+aFuncU
.getLength());
835 aFuncNameBuffer
.append(aServiceName
);
836 aFuncNameBuffer
.append('.');
837 aFuncNameBuffer
.append(aFuncU
);
838 OUString aFuncName
= aFuncNameBuffer
.makeStringAndClear();
841 long nVisibleCount
= 0;
842 long nCallerPos
= SC_CALLERPOS_NONE
;
844 uno::Sequence
<reflection::ParamInfo
> aParams
=
845 xFunc
->getParameterInfos();
846 long nParamCount
= aParams
.getLength();
847 const reflection::ParamInfo
* pParArr
= aParams
.getConstArray();
849 for (nParamPos
=0; nParamPos
<nParamCount
; nParamPos
++)
851 if ( pParArr
[nParamPos
].aMode
!= reflection::ParamMode_IN
)
853 uno::Reference
<reflection::XIdlClass
> xParClass
=
854 pParArr
[nParamPos
].aType
;
855 ScAddInArgumentType eArgType
= lcl_GetArgType( xParClass
);
856 if ( eArgType
== SC_ADDINARG_NONE
)
858 else if ( eArgType
== SC_ADDINARG_CALLER
)
859 nCallerPos
= nParamPos
;
865 sal_uInt16 nCategory
= lcl_GetCategory(
866 xAddIn
->getProgrammaticCategoryName( aFuncU
) );
868 OString sHelpId
= aHelpIdGenerator
.GetHelpId( aFuncU
);
873 aLocalName
= xAddIn
->
874 getDisplayFunctionName( aFuncU
);
876 catch(uno::Exception
&)
881 OUString aDescription
;
884 aDescription
= xAddIn
->
885 getFunctionDescription( aFuncU
);
887 catch(uno::Exception
&)
889 aDescription
= "###";
892 ScAddInArgDesc
* pVisibleArgs
= NULL
;
893 if ( nVisibleCount
> 0 )
895 ScAddInArgDesc aDesc
;
896 pVisibleArgs
= new ScAddInArgDesc
[nVisibleCount
];
898 for (nParamPos
=0; nParamPos
<nParamCount
; nParamPos
++)
900 uno::Reference
<reflection::XIdlClass
> xParClass
=
901 pParArr
[nParamPos
].aType
;
902 ScAddInArgumentType eArgType
= lcl_GetArgType( xParClass
);
903 if ( eArgType
!= SC_ADDINARG_CALLER
)
909 getDisplayArgumentName( aFuncU
, nParamPos
);
911 catch(uno::Exception
&)
919 getArgumentDescription( aFuncU
, nParamPos
);
921 catch(uno::Exception
&)
927 ( eArgType
== SC_ADDINARG_VALUE_OR_ARRAY
||
928 eArgType
== SC_ADDINARG_VARARGS
);
930 aDesc
.eType
= eArgType
;
931 aDesc
.aName
= aArgName
;
932 aDesc
.aDescription
= aArgDesc
;
933 aDesc
.bOptional
= bOptional
;
934 //! initialize aInternalName only from config?
935 aDesc
.aInternalName
= pParArr
[nParamPos
].aName
;
937 pVisibleArgs
[nDestPos
++] = aDesc
;
940 OSL_ENSURE( nDestPos
==nVisibleCount
, "wrong count" );
943 ppFuncData
[nFuncPos
+nOld
] = new ScUnoAddInFuncData(
944 aFuncName
, aLocalName
, aDescription
,
947 nVisibleCount
, pVisibleArgs
, nCallerPos
);
949 const ScUnoAddInFuncData
* pData
=
950 ppFuncData
[nFuncPos
+nOld
];
951 pExactHashMap
->insert(
952 ScAddInHashMap::value_type(
953 pData
->GetOriginalName(),
955 pNameHashMap
->insert(
956 ScAddInHashMap::value_type(
957 pData
->GetUpperName(),
959 pLocalHashMap
->insert(
960 ScAddInHashMap::value_type(
961 pData
->GetUpperLocal(),
964 delete[] pVisibleArgs
;
974 static void lcl_UpdateFunctionList( ScFunctionList
& rFunctionList
, const ScUnoAddInFuncData
& rFuncData
)
976 OUString aCompare
= rFuncData
.GetUpperLocal(); // as used in FillFunctionDescFromData
978 sal_uLong nCount
= rFunctionList
.GetCount();
979 for (sal_uLong nPos
=0; nPos
<nCount
; nPos
++)
981 const ScFuncDesc
* pDesc
= rFunctionList
.GetFunction( nPos
);
982 if ( pDesc
&& pDesc
->pFuncName
&& *pDesc
->pFuncName
== aCompare
)
984 ScUnoAddInCollection::FillFunctionDescFromData( rFuncData
, *const_cast<ScFuncDesc
*>(pDesc
) );
990 static const ScAddInArgDesc
* lcl_FindArgDesc( const ScUnoAddInFuncData
& rFuncData
, const OUString
& rArgIntName
)
992 long nArgCount
= rFuncData
.GetArgumentCount();
993 const ScAddInArgDesc
* pArguments
= rFuncData
.GetArguments();
994 for (long nPos
=0; nPos
<nArgCount
; nPos
++)
996 if ( pArguments
[nPos
].aInternalName
== rArgIntName
)
997 return &pArguments
[nPos
];
1002 void ScUnoAddInCollection::UpdateFromAddIn( const uno::Reference
<uno::XInterface
>& xInterface
,
1003 const OUString
& rServiceName
)
1005 uno::Reference
<lang::XLocalizable
> xLoc( xInterface
, uno::UNO_QUERY
);
1006 if ( xLoc
.is() ) // optional in new add-ins
1008 // fdo50118 when GetUseEnglishFunctionName() returns true, set the
1009 // locale to en-US to get English function names
1010 if ( SC_MOD()->GetFormulaOptions().GetUseEnglishFuncName() )
1011 xLoc
->setLocale( lang::Locale( "en", "US", ""));
1013 xLoc
->setLocale( Application::GetSettings().GetUILanguageTag().getLocale());
1016 // if function list was already initialized, it must be updated
1018 ScFunctionList
* pFunctionList
= NULL
;
1019 if ( ScGlobal::HasStarCalcFunctionList() )
1020 pFunctionList
= ScGlobal::GetStarCalcFunctionList();
1022 // only get the function information from Introspection
1024 uno::Reference
<uno::XComponentContext
> xContext
= comphelper::getProcessComponentContext();
1026 uno::Reference
<beans::XIntrospection
> xIntro
= beans::Introspection::create(xContext
);
1028 aObject
<<= xInterface
;
1029 uno::Reference
<beans::XIntrospectionAccess
> xAcc
= xIntro
->inspect(aObject
);
1032 uno::Sequence
< uno::Reference
<reflection::XIdlMethod
> > aMethods
=
1033 xAcc
->getMethods( beans::MethodConcept::ALL
);
1034 long nMethodCount
= aMethods
.getLength();
1035 const uno::Reference
<reflection::XIdlMethod
>* pArray
= aMethods
.getConstArray();
1036 for (long nFuncPos
=0; nFuncPos
<nMethodCount
; nFuncPos
++)
1038 uno::Reference
<reflection::XIdlMethod
> xFunc
= pArray
[nFuncPos
];
1041 OUString aFuncU
= xFunc
->getName();
1043 // stored function name: (service name).(function)
1044 OUStringBuffer
aFuncNameBuffer( rServiceName
.getLength()+1+aFuncU
.getLength());
1045 aFuncNameBuffer
.append(rServiceName
);
1046 aFuncNameBuffer
.append('.');
1047 aFuncNameBuffer
.append(aFuncU
);
1048 OUString aFuncName
= aFuncNameBuffer
.makeStringAndClear();
1050 // internal names are skipped because no FuncData exists
1051 ScUnoAddInFuncData
* pOldData
= const_cast<ScUnoAddInFuncData
*>( GetFuncData( aFuncName
) );
1054 // Create new (complete) argument info.
1055 // As in ReadFromAddIn, the reflection information is authoritative.
1056 // Local names and descriptions from pOldData are looked up using the
1057 // internal argument name.
1060 long nVisibleCount
= 0;
1061 long nCallerPos
= SC_CALLERPOS_NONE
;
1063 uno::Sequence
<reflection::ParamInfo
> aParams
=
1064 xFunc
->getParameterInfos();
1065 long nParamCount
= aParams
.getLength();
1066 const reflection::ParamInfo
* pParArr
= aParams
.getConstArray();
1068 for (nParamPos
=0; nParamPos
<nParamCount
; nParamPos
++)
1070 if ( pParArr
[nParamPos
].aMode
!= reflection::ParamMode_IN
)
1072 uno::Reference
<reflection::XIdlClass
> xParClass
=
1073 pParArr
[nParamPos
].aType
;
1074 ScAddInArgumentType eArgType
= lcl_GetArgType( xParClass
);
1075 if ( eArgType
== SC_ADDINARG_NONE
)
1077 else if ( eArgType
== SC_ADDINARG_CALLER
)
1078 nCallerPos
= nParamPos
;
1084 ScAddInArgDesc
* pVisibleArgs
= NULL
;
1085 if ( nVisibleCount
> 0 )
1087 ScAddInArgDesc aDesc
;
1088 pVisibleArgs
= new ScAddInArgDesc
[nVisibleCount
];
1090 for (nParamPos
=0; nParamPos
<nParamCount
; nParamPos
++)
1092 uno::Reference
<reflection::XIdlClass
> xParClass
=
1093 pParArr
[nParamPos
].aType
;
1094 ScAddInArgumentType eArgType
= lcl_GetArgType( xParClass
);
1095 if ( eArgType
!= SC_ADDINARG_CALLER
)
1097 const ScAddInArgDesc
* pOldArgDesc
=
1098 lcl_FindArgDesc( *pOldData
, pParArr
[nParamPos
].aName
);
1101 aDesc
.aName
= pOldArgDesc
->aName
;
1102 aDesc
.aDescription
= pOldArgDesc
->aDescription
;
1105 aDesc
.aName
= aDesc
.aDescription
= "###";
1108 ( eArgType
== SC_ADDINARG_VALUE_OR_ARRAY
||
1109 eArgType
== SC_ADDINARG_VARARGS
);
1111 aDesc
.eType
= eArgType
;
1112 aDesc
.bOptional
= bOptional
;
1113 //! initialize aInternalName only from config?
1114 aDesc
.aInternalName
= pParArr
[nParamPos
].aName
;
1116 pVisibleArgs
[nDestPos
++] = aDesc
;
1119 OSL_ENSURE( nDestPos
==nVisibleCount
, "wrong count" );
1122 pOldData
->SetFunction( xFunc
, aObject
);
1123 pOldData
->SetArguments( nVisibleCount
, pVisibleArgs
);
1124 pOldData
->SetCallerPos( nCallerPos
);
1126 if ( pFunctionList
)
1127 lcl_UpdateFunctionList( *pFunctionList
, *pOldData
);
1129 delete[] pVisibleArgs
;
1137 OUString
ScUnoAddInCollection::FindFunction( const OUString
& rUpperName
, bool bLocalFirst
)
1142 if (nFuncCount
== 0)
1143 return EMPTY_OUSTRING
;
1147 // first scan all local names (used for entering formulas)
1149 ScAddInHashMap::const_iterator
iLook( pLocalHashMap
->find( rUpperName
) );
1150 if ( iLook
!= pLocalHashMap
->end() )
1151 return iLook
->second
->GetOriginalName();
1155 // first scan international names (used when calling a function)
1156 //! before that, check for exact match???
1158 ScAddInHashMap::const_iterator
iLook( pNameHashMap
->find( rUpperName
) );
1159 if ( iLook
!= pNameHashMap
->end() )
1160 return iLook
->second
->GetOriginalName();
1162 // after that, scan all local names (to allow replacing old AddIns with Uno)
1164 iLook
= pLocalHashMap
->find( rUpperName
);
1165 if ( iLook
!= pLocalHashMap
->end() )
1166 return iLook
->second
->GetOriginalName();
1169 return EMPTY_OUSTRING
;
1172 const ScUnoAddInFuncData
* ScUnoAddInCollection::GetFuncData( const OUString
& rName
, bool bComplete
)
1177 // rName must be the exact internal name
1179 ScAddInHashMap::const_iterator
iLook( pExactHashMap
->find( rName
) );
1180 if ( iLook
!= pExactHashMap
->end() )
1182 const ScUnoAddInFuncData
* pFuncData
= iLook
->second
;
1184 if ( bComplete
&& !pFuncData
->GetFunction().is() ) //! extra flag?
1185 LoadComponent( *pFuncData
);
1193 const ScUnoAddInFuncData
* ScUnoAddInCollection::GetFuncData( long nIndex
)
1198 if (nIndex
< nFuncCount
)
1199 return ppFuncData
[nIndex
];
1203 void ScUnoAddInCollection::LocalizeString( OUString
& rName
)
1208 // modify rName - input: exact name
1210 ScAddInHashMap::const_iterator
iLook( pExactHashMap
->find( rName
) );
1211 if ( iLook
!= pExactHashMap
->end() )
1212 rName
= iLook
->second
->GetUpperLocal(); //! upper?
1215 long ScUnoAddInCollection::GetFuncCount()
1223 bool ScUnoAddInCollection::FillFunctionDesc( long nFunc
, ScFuncDesc
& rDesc
)
1228 if (nFunc
>= nFuncCount
|| !ppFuncData
[nFunc
])
1231 const ScUnoAddInFuncData
& rFuncData
= *ppFuncData
[nFunc
];
1233 return FillFunctionDescFromData( rFuncData
, rDesc
);
1236 bool ScUnoAddInCollection::FillFunctionDescFromData( const ScUnoAddInFuncData
& rFuncData
, ScFuncDesc
& rDesc
)
1240 bool bIncomplete
= !rFuncData
.GetFunction().is(); //! extra flag?
1242 long nArgCount
= rFuncData
.GetArgumentCount();
1243 if ( nArgCount
> USHRT_MAX
)
1247 nArgCount
= 0; // if incomplete, fill without argument info (no wrong order)
1249 // nFIndex is set from outside
1251 rDesc
.pFuncName
= new OUString( rFuncData
.GetUpperLocal() ); //! upper?
1252 rDesc
.nCategory
= rFuncData
.GetCategory();
1253 rDesc
.sHelpId
= rFuncData
.GetHelpId();
1255 OUString aDesc
= rFuncData
.GetDescription();
1256 if (aDesc
.isEmpty())
1257 aDesc
= rFuncData
.GetLocalName(); // use name if no description is available
1258 rDesc
.pFuncDesc
= new OUString( aDesc
);
1260 // AddInArgumentType_CALLER is already left out in FuncData
1262 rDesc
.nArgCount
= (sal_uInt16
)nArgCount
;
1265 bool bMultiple
= false;
1266 const ScAddInArgDesc
* pArgs
= rFuncData
.GetArguments();
1268 rDesc
.ppDefArgNames
= new OUString
*[nArgCount
];
1269 rDesc
.ppDefArgDescs
= new OUString
*[nArgCount
];
1270 rDesc
.pDefArgFlags
= new ScFuncDesc::ParameterFlags
[nArgCount
];
1271 for ( long nArg
=0; nArg
<nArgCount
; nArg
++ )
1273 rDesc
.ppDefArgNames
[nArg
] = new OUString( pArgs
[nArg
].aName
);
1274 rDesc
.ppDefArgDescs
[nArg
] = new OUString( pArgs
[nArg
].aDescription
);
1275 rDesc
.pDefArgFlags
[nArg
].bOptional
= pArgs
[nArg
].bOptional
;
1276 rDesc
.pDefArgFlags
[nArg
].bSuppress
= false;
1278 // no empty names...
1279 if ( rDesc
.ppDefArgNames
[nArg
]->isEmpty() )
1281 OUString
aDefName("arg");
1282 aDefName
+= OUString::number( nArg
+1 );
1283 *rDesc
.ppDefArgNames
[nArg
] = aDefName
;
1286 // last argument repeated?
1287 if ( nArg
+1 == nArgCount
&& ( pArgs
[nArg
].eType
== SC_ADDINARG_VARARGS
) )
1292 rDesc
.nArgCount
+= VAR_ARGS
- 1; // VAR_ARGS means just one repeated arg
1295 rDesc
.bIncomplete
= bIncomplete
;
1300 ScUnoAddInCall::ScUnoAddInCall( ScUnoAddInCollection
& rColl
, const OUString
& rName
,
1301 long nParamCount
) :
1302 bValidCount( false ),
1303 nErrCode( errNoCode
), // before function was called
1308 pFuncData
= rColl
.GetFuncData( rName
, true ); // need fully initialized data
1309 OSL_ENSURE( pFuncData
, "Function Data missing" );
1312 long nDescCount
= pFuncData
->GetArgumentCount();
1313 const ScAddInArgDesc
* pArgs
= pFuncData
->GetArguments();
1315 // is aVarArg sequence needed?
1316 if ( nParamCount
>= nDescCount
&& nDescCount
> 0 &&
1317 pArgs
[nDescCount
-1].eType
== SC_ADDINARG_VARARGS
)
1319 long nVarCount
= nParamCount
- ( nDescCount
- 1 ); // size of last argument
1320 aVarArg
.realloc( nVarCount
);
1323 else if ( nParamCount
<= nDescCount
)
1325 // all args behind nParamCount must be optional
1327 for (long i
=nParamCount
; i
<nDescCount
; i
++)
1328 if ( !pArgs
[i
].bOptional
)
1329 bValidCount
= false;
1331 // else invalid (too many arguments)
1334 aArgs
.realloc( nDescCount
); // sequence must always match function signature
1338 ScUnoAddInCall::~ScUnoAddInCall()
1340 // pFuncData is deleted with ScUnoAddInCollection
1343 bool ScUnoAddInCall::ValidParamCount()
1348 ScAddInArgumentType
ScUnoAddInCall::GetArgType( long nPos
)
1352 long nCount
= pFuncData
->GetArgumentCount();
1353 const ScAddInArgDesc
* pArgs
= pFuncData
->GetArguments();
1355 // if last arg is sequence, use "any" type
1356 if ( nCount
> 0 && nPos
>= nCount
-1 && pArgs
[nCount
-1].eType
== SC_ADDINARG_VARARGS
)
1357 return SC_ADDINARG_VALUE_OR_ARRAY
;
1359 if ( nPos
< nCount
)
1360 return pArgs
[nPos
].eType
;
1362 return SC_ADDINARG_VALUE_OR_ARRAY
; //! error code !!!!
1365 bool ScUnoAddInCall::NeedsCaller() const
1367 return pFuncData
&& pFuncData
->GetCallerPos() != SC_CALLERPOS_NONE
;
1370 void ScUnoAddInCall::SetCaller( const uno::Reference
<uno::XInterface
>& rInterface
)
1372 xCaller
= rInterface
;
1375 void ScUnoAddInCall::SetCallerFromObjectShell( SfxObjectShell
* pObjSh
)
1379 uno::Reference
<uno::XInterface
> xInt( pObjSh
->GetBaseModel(), uno::UNO_QUERY
);
1384 void ScUnoAddInCall::SetParam( long nPos
, const uno::Any
& rValue
)
1388 long nCount
= pFuncData
->GetArgumentCount();
1389 const ScAddInArgDesc
* pArgs
= pFuncData
->GetArguments();
1390 if ( nCount
> 0 && nPos
>= nCount
-1 && pArgs
[nCount
-1].eType
== SC_ADDINARG_VARARGS
)
1392 long nVarPos
= nPos
-(nCount
-1);
1393 if ( nVarPos
< aVarArg
.getLength() )
1394 aVarArg
.getArray()[nVarPos
] = rValue
;
1397 OSL_FAIL("wrong argument number");
1400 else if ( nPos
< aArgs
.getLength() )
1401 aArgs
.getArray()[nPos
] = rValue
;
1404 OSL_FAIL("wrong argument number");
1409 void ScUnoAddInCall::ExecuteCall()
1414 long nCount
= pFuncData
->GetArgumentCount();
1415 const ScAddInArgDesc
* pArgs
= pFuncData
->GetArguments();
1416 if ( nCount
> 0 && pArgs
[nCount
-1].eType
== SC_ADDINARG_VARARGS
)
1418 // insert aVarArg as last argument
1419 //! after inserting caller (to prevent copying twice)?
1421 OSL_ENSURE( aArgs
.getLength() == nCount
, "wrong argument count" );
1422 aArgs
.getArray()[nCount
-1] <<= aVarArg
;
1425 if ( pFuncData
->GetCallerPos() != SC_CALLERPOS_NONE
)
1427 uno::Any aCallerAny
;
1428 aCallerAny
<<= xCaller
;
1430 long nUserLen
= aArgs
.getLength();
1431 long nCallPos
= pFuncData
->GetCallerPos();
1432 if (nCallPos
>nUserLen
) // should not happen
1434 OSL_FAIL("wrong CallPos");
1435 nCallPos
= nUserLen
;
1438 long nDestLen
= nUserLen
+ 1;
1439 uno::Sequence
<uno::Any
> aRealArgs( nDestLen
);
1440 uno::Any
* pDest
= aRealArgs
.getArray();
1442 const uno::Any
* pSource
= aArgs
.getConstArray();
1445 for ( long nDestPos
= 0; nDestPos
< nDestLen
; nDestPos
++ )
1447 if ( nDestPos
== nCallPos
)
1448 pDest
[nDestPos
] = aCallerAny
;
1450 pDest
[nDestPos
] = pSource
[nSrcPos
++];
1453 ExecuteCallWithArgs( aRealArgs
);
1456 ExecuteCallWithArgs( aArgs
);
1459 void ScUnoAddInCall::ExecuteCallWithArgs(uno::Sequence
<uno::Any
>& rCallArgs
)
1461 // rCallArgs may not match argument descriptions (because of caller)
1463 uno::Reference
<reflection::XIdlMethod
> xFunction
;
1467 xFunction
= pFuncData
->GetFunction();
1468 aObject
= pFuncData
->GetObject();
1471 if ( xFunction
.is() )
1478 aAny
= xFunction
->invoke( aObject
, rCallArgs
);
1480 catch(lang::IllegalArgumentException
&)
1482 nErrCode
= errIllegalArgument
;
1485 catch(const reflection::InvocationTargetException
& rWrapped
)
1487 if ( rWrapped
.TargetException
.getValueType().equals(
1488 getCppuType( (lang::IllegalArgumentException
*)0 ) ) )
1489 nErrCode
= errIllegalArgument
;
1490 else if ( rWrapped
.TargetException
.getValueType().equals(
1491 getCppuType( (sheet::NoConvergenceException
*)0 ) ) )
1492 nErrCode
= errNoConvergence
;
1494 nErrCode
= errNoValue
;
1497 catch(uno::Exception
&)
1499 nErrCode
= errNoValue
;
1503 SetResult( aAny
); // convert result to Calc types
1507 void ScUnoAddInCall::SetResult( const uno::Any
& rNewRes
)
1512 // Reflection* pRefl = rNewRes.getReflection();
1514 uno::TypeClass eClass
= rNewRes
.getValueTypeClass();
1515 uno::Type aType
= rNewRes
.getValueType();
1518 case uno::TypeClass_VOID
:
1519 nErrCode
= NOTAVAILABLE
; // #NA
1522 case uno::TypeClass_ENUM
:
1523 case uno::TypeClass_BOOLEAN
:
1524 case uno::TypeClass_CHAR
:
1525 case uno::TypeClass_BYTE
:
1526 case uno::TypeClass_SHORT
:
1527 case uno::TypeClass_UNSIGNED_SHORT
:
1528 case uno::TypeClass_LONG
:
1529 case uno::TypeClass_UNSIGNED_LONG
:
1530 case uno::TypeClass_FLOAT
:
1531 case uno::TypeClass_DOUBLE
:
1533 uno::TypeClass eMyClass
;
1534 ScApiTypeConversion::ConvertAnyToDouble( fValue
, eMyClass
, rNewRes
);
1539 case uno::TypeClass_STRING
:
1541 rNewRes
>>= aString
;
1546 case uno::TypeClass_INTERFACE
:
1548 //! directly extract XVolatileResult from any?
1549 uno::Reference
<uno::XInterface
> xInterface
;
1550 rNewRes
>>= xInterface
;
1551 if ( xInterface
.is() )
1552 xVarRes
= uno::Reference
<sheet::XVolatileResult
>( xInterface
, uno::UNO_QUERY
);
1555 nErrCode
= errNoValue
; // unknown interface
1560 if ( aType
.equals( getCppuType( (uno::Sequence
< uno::Sequence
<sal_Int32
> > *)0 ) ) )
1562 const uno::Sequence
< uno::Sequence
<sal_Int32
> >* pRowSeq
= NULL
;
1564 //! use pointer from any!
1565 uno::Sequence
< uno::Sequence
<sal_Int32
> > aSequence
;
1566 if ( rNewRes
>>= aSequence
)
1567 pRowSeq
= &aSequence
;
1571 long nRowCount
= pRowSeq
->getLength();
1572 const uno::Sequence
<sal_Int32
>* pRowArr
= pRowSeq
->getConstArray();
1573 long nMaxColCount
= 0;
1575 for (nRow
=0; nRow
<nRowCount
; nRow
++)
1577 long nTmp
= pRowArr
[nRow
].getLength();
1578 if ( nTmp
> nMaxColCount
)
1579 nMaxColCount
= nTmp
;
1581 if ( nMaxColCount
&& nRowCount
)
1583 xMatrix
= new ScMatrix(
1584 static_cast<SCSIZE
>(nMaxColCount
),
1585 static_cast<SCSIZE
>(nRowCount
), 0.0);
1586 for (nRow
=0; nRow
<nRowCount
; nRow
++)
1588 long nColCount
= pRowArr
[nRow
].getLength();
1589 const sal_Int32
* pColArr
= pRowArr
[nRow
].getConstArray();
1590 for (nCol
=0; nCol
<nColCount
; nCol
++)
1591 xMatrix
->PutDouble( pColArr
[nCol
],
1592 static_cast<SCSIZE
>(nCol
),
1593 static_cast<SCSIZE
>(nRow
) );
1594 for (nCol
=nColCount
; nCol
<nMaxColCount
; nCol
++)
1595 xMatrix
->PutDouble( 0.0,
1596 static_cast<SCSIZE
>(nCol
),
1597 static_cast<SCSIZE
>(nRow
) );
1602 else if ( aType
.equals( getCppuType( (uno::Sequence
< uno::Sequence
<double> > *)0 ) ) )
1604 const uno::Sequence
< uno::Sequence
<double> >* pRowSeq
= NULL
;
1606 //! use pointer from any!
1607 uno::Sequence
< uno::Sequence
<double> > aSequence
;
1608 if ( rNewRes
>>= aSequence
)
1609 pRowSeq
= &aSequence
;
1613 long nRowCount
= pRowSeq
->getLength();
1614 const uno::Sequence
<double>* pRowArr
= pRowSeq
->getConstArray();
1615 long nMaxColCount
= 0;
1617 for (nRow
=0; nRow
<nRowCount
; nRow
++)
1619 long nTmp
= pRowArr
[nRow
].getLength();
1620 if ( nTmp
> nMaxColCount
)
1621 nMaxColCount
= nTmp
;
1623 if ( nMaxColCount
&& nRowCount
)
1625 xMatrix
= new ScMatrix(
1626 static_cast<SCSIZE
>(nMaxColCount
),
1627 static_cast<SCSIZE
>(nRowCount
), 0.0);
1628 for (nRow
=0; nRow
<nRowCount
; nRow
++)
1630 long nColCount
= pRowArr
[nRow
].getLength();
1631 const double* pColArr
= pRowArr
[nRow
].getConstArray();
1632 for (nCol
=0; nCol
<nColCount
; nCol
++)
1633 xMatrix
->PutDouble( pColArr
[nCol
],
1634 static_cast<SCSIZE
>(nCol
),
1635 static_cast<SCSIZE
>(nRow
) );
1636 for (nCol
=nColCount
; nCol
<nMaxColCount
; nCol
++)
1637 xMatrix
->PutDouble( 0.0,
1638 static_cast<SCSIZE
>(nCol
),
1639 static_cast<SCSIZE
>(nRow
) );
1644 else if ( aType
.equals( getCppuType( (uno::Sequence
< uno::Sequence
<OUString
> > *)0 ) ) )
1646 const uno::Sequence
< uno::Sequence
<OUString
> >* pRowSeq
= NULL
;
1648 //! use pointer from any!
1649 uno::Sequence
< uno::Sequence
<OUString
> > aSequence
;
1650 if ( rNewRes
>>= aSequence
)
1651 pRowSeq
= &aSequence
;
1655 long nRowCount
= pRowSeq
->getLength();
1656 const uno::Sequence
<OUString
>* pRowArr
= pRowSeq
->getConstArray();
1657 long nMaxColCount
= 0;
1659 for (nRow
=0; nRow
<nRowCount
; nRow
++)
1661 long nTmp
= pRowArr
[nRow
].getLength();
1662 if ( nTmp
> nMaxColCount
)
1663 nMaxColCount
= nTmp
;
1665 if ( nMaxColCount
&& nRowCount
)
1667 xMatrix
= new ScMatrix(
1668 static_cast<SCSIZE
>(nMaxColCount
),
1669 static_cast<SCSIZE
>(nRowCount
), 0.0);
1670 for (nRow
=0; nRow
<nRowCount
; nRow
++)
1672 long nColCount
= pRowArr
[nRow
].getLength();
1673 const OUString
* pColArr
= pRowArr
[nRow
].getConstArray();
1674 for (nCol
=0; nCol
<nColCount
; nCol
++)
1677 svl::SharedString(pColArr
[nCol
]),
1678 static_cast<SCSIZE
>(nCol
), static_cast<SCSIZE
>(nRow
));
1680 for (nCol
=nColCount
; nCol
<nMaxColCount
; nCol
++)
1683 svl::SharedString(EMPTY_OUSTRING
),
1684 static_cast<SCSIZE
>(nCol
), static_cast<SCSIZE
>(nRow
));
1690 else if ( aType
.equals( getCppuType( (uno::Sequence
< uno::Sequence
<uno::Any
> > *)0 ) ) )
1692 xMatrix
= ScSequenceToMatrix::CreateMixedMatrix( rNewRes
);
1695 if (!xMatrix
) // no array found
1696 nErrCode
= errNoValue
; //! code for error in return type???
1700 ScMatrixRef
ScUnoAddInCall::GetMatrix() const
1705 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */