LibreOffice Module sc (master)  1
addincol.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
22 #include <vcl/svapp.hxx>
23 #include <vcl/settings.hxx>
24 #include <sfx2/objsh.hxx>
25 #include <unotools/charclass.hxx>
26 #include <sal/log.hxx>
27 #include <osl/diagnose.h>
28 
29 #include <com/sun/star/container/XContentEnumerationAccess.hpp>
30 #include <com/sun/star/frame/XModel.hpp>
31 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
32 #include <com/sun/star/lang/XServiceInfo.hpp>
33 #include <com/sun/star/lang/XServiceName.hpp>
34 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
35 #include <com/sun/star/lang/XSingleComponentFactory.hpp>
36 #include <com/sun/star/reflection/XIdlClass.hpp>
37 #include <com/sun/star/beans/XIntrospectionAccess.hpp>
38 #include <com/sun/star/beans/theIntrospection.hpp>
39 #include <com/sun/star/beans/MethodConcept.hpp>
40 #include <com/sun/star/beans/XPropertySet.hpp>
41 #include <com/sun/star/beans/PropertyValue.hpp>
42 #include <com/sun/star/table/XCellRange.hpp>
43 #include <com/sun/star/lang/Locale.hpp>
44 #include <com/sun/star/sheet/XCompatibilityNames.hpp>
45 #include <com/sun/star/sheet/NoConvergenceException.hpp>
46 #include <com/sun/star/sheet/XAddIn.hpp>
47 #include <com/sun/star/sheet/XVolatileResult.hpp>
48 
49 #include <addincol.hxx>
50 #include <addinhelpid.hxx>
51 #include <scmatrix.hxx>
52 #include <formula/errorcodes.hxx>
53 #include <formula/funcvarargs.h>
54 #include <optutil.hxx>
55 #include <addincfg.hxx>
56 #include <scmod.hxx>
57 #include <rangeseq.hxx>
58 #include <funcdesc.hxx>
59 #include <svl/sharedstring.hxx>
60 #include <formulaopt.hxx>
61 #include <memory>
62 
63 using namespace com::sun::star;
64 
65 #define SC_CALLERPOS_NONE (-1)
66 
67 ScUnoAddInFuncData::ScUnoAddInFuncData( const OUString& rNam, const OUString& rLoc,
68  const OUString& rDesc,
69  sal_uInt16 nCat, const OString& sHelp,
70  const uno::Reference<reflection::XIdlMethod>& rFunc,
71  const uno::Any& rO,
72  tools::Long nAC, const ScAddInArgDesc* pAD,
73  tools::Long nCP ) :
74  aOriginalName( rNam ),
75  aLocalName( rLoc ),
76  aUpperName( rNam ),
77  aUpperLocal( rLoc ),
78  aDescription( rDesc ),
79  xFunction( rFunc ),
80  aObject( rO ),
81  nArgCount( nAC ),
82  nCallerPos( nCP ),
83  nCategory( nCat ),
84  sHelpId( sHelp ),
85  bCompInitialized( false )
86 {
87  if ( nArgCount )
88  {
89  pArgDescs.reset( new ScAddInArgDesc[nArgCount] );
90  for (tools::Long i=0; i<nArgCount; i++)
91  pArgDescs[i] = pAD[i];
92  }
93 
96 }
97 
99 {
100 }
101 
102 const ::std::vector<ScUnoAddInFuncData::LocalizedName>& ScUnoAddInFuncData::GetCompNames() const
103 {
104  if ( !bCompInitialized )
105  {
106  // read sequence of compatibility names on demand
107 
108  uno::Reference<sheet::XAddIn> xAddIn;
109  if ( aObject >>= xAddIn )
110  {
111  uno::Reference<sheet::XCompatibilityNames> xComp( xAddIn, uno::UNO_QUERY );
112  if ( xComp.is() && xFunction.is() )
113  {
114  OUString aMethodName = xFunction->getName();
115  const uno::Sequence< sheet::LocalizedName> aCompNames( xComp->getCompatibilityNames( aMethodName ));
116  maCompNames.clear();
117  for (const sheet::LocalizedName& rCompName : aCompNames)
118  {
119  maCompNames.emplace_back(
120  LanguageTag::convertToBcp47( rCompName.Locale, false),
121  rCompName.Name);
122  }
123  }
124  }
125 
126  bCompInitialized = true; // also if not successful
127  }
128  return maCompNames;
129 }
130 
131 void ScUnoAddInFuncData::SetCompNames( const ::std::vector< ScUnoAddInFuncData::LocalizedName >& rNew )
132 {
133  OSL_ENSURE( !bCompInitialized, "SetCompNames after initializing" );
134 
135  maCompNames = rNew;
136 
137  bCompInitialized = true;
138 }
139 
140 bool ScUnoAddInFuncData::GetExcelName( LanguageType eDestLang, OUString& rRetExcelName ) const
141 {
142  const ::std::vector<LocalizedName>& rCompNames = GetCompNames();
143  if ( !rCompNames.empty() )
144  {
145  LanguageTag aLanguageTag( eDestLang);
146  const OUString& aSearch( aLanguageTag.getBcp47());
147 
148  // First, check exact match without fallback overhead.
149  ::std::vector<LocalizedName>::const_iterator itNames = std::find_if(rCompNames.begin(), rCompNames.end(),
150  [&aSearch](const LocalizedName& rName) { return rName.maLocale == aSearch; });
151  if (itNames != rCompNames.end())
152  {
153  rRetExcelName = (*itNames).maName;
154  return true;
155  }
156 
157  // Second, try match of fallback search with fallback locales,
158  // appending also 'en-US' and 'en' to search if not queried.
159  ::std::vector< OUString > aFallbackSearch( aLanguageTag.getFallbackStrings( true));
160  if (aSearch != "en-US")
161  {
162  aFallbackSearch.emplace_back("en-US");
163  if (aSearch != "en")
164  {
165  aFallbackSearch.emplace_back("en");
166  }
167  }
168  for (const auto& rSearch : aFallbackSearch)
169  {
170  for (const auto& rCompName : rCompNames)
171  {
172  // We checked already the full tag, start with second.
173  ::std::vector< OUString > aFallbackLocales( LanguageTag( rCompName.maLocale).getFallbackStrings( false));
174  if (std::find(aFallbackLocales.begin(), aFallbackLocales.end(), rSearch) != aFallbackLocales.end())
175  {
176  rRetExcelName = rCompName.maName;
177  return true;
178  }
179  }
180  }
181 
182  // Third, last resort, use first (default) entry.
183  rRetExcelName = rCompNames[0].maName;
184  return true;
185  }
186  return false;
187 }
188 
189 void ScUnoAddInFuncData::SetFunction( const uno::Reference< reflection::XIdlMethod>& rNewFunc, const uno::Any& rNewObj )
190 {
191  xFunction = rNewFunc;
192  aObject = rNewObj;
193 }
194 
196 {
197  nArgCount = nNewCount;
198  if ( nArgCount )
199  {
200  pArgDescs.reset( new ScAddInArgDesc[nArgCount] );
201  for (tools::Long i=0; i<nArgCount; i++)
202  pArgDescs[i] = pNewDescs[i];
203  }
204  else
205  pArgDescs.reset();
206 }
207 
209 {
210  nCallerPos = nNewPos;
211 }
212 
214  nFuncCount( 0 ),
215  bInitialized( false )
216 {
217 }
218 
220 {
221 }
222 
224 {
225  pExactHashMap.reset();
226  pNameHashMap.reset();
227  pLocalHashMap.reset();
228  ppFuncData.reset();
229  nFuncCount = 0;
230 
231  bInitialized = false;
232 }
233 
235 {
236  OSL_ENSURE( !bInitialized, "Initialize twice?" );
237 
238  uno::Reference<lang::XMultiServiceFactory> xManager = comphelper::getProcessServiceFactory();
239  uno::Reference<container::XContentEnumerationAccess> xEnAc( xManager, uno::UNO_QUERY );
240  if ( xEnAc.is() )
241  {
242  uno::Reference<container::XEnumeration> xEnum =
243  xEnAc->createContentEnumeration( "com.sun.star.sheet.AddIn" );
244  if ( xEnum.is() )
245  {
246  // loop through all AddIns
247  while ( xEnum->hasMoreElements() )
248  {
249  uno::Any aAddInAny = xEnum->nextElement();
250 
251  try
252  {
253  uno::Reference<uno::XInterface> xIntFac;
254  aAddInAny >>= xIntFac;
255  if ( xIntFac.is() )
256  {
257  // #i59984# try XSingleComponentFactory in addition to (old) XSingleServiceFactory,
258  // passing the context to the component
259 
260  uno::Reference<uno::XInterface> xInterface;
261  uno::Reference<uno::XComponentContext> xCtx(
263  uno::Reference<lang::XSingleComponentFactory> xCFac( xIntFac, uno::UNO_QUERY );
264  if (xCFac.is())
265  {
266  xInterface = xCFac->createInstanceWithContext(xCtx);
267  if (xInterface.is())
268  ReadFromAddIn( xInterface );
269  }
270 
271  if (!xInterface.is())
272  {
273  uno::Reference<lang::XSingleServiceFactory> xFac( xIntFac, uno::UNO_QUERY );
274  if ( xFac.is() )
275  {
276  xInterface = xFac->createInstance();
277  if (xInterface.is())
278  ReadFromAddIn( xInterface );
279  }
280  }
281  }
282  } catch ( const uno::Exception& ) {
283  SAL_WARN ( "sc", "Failed to initialize create instance of sheet.AddIn" );
284  }
285  }
286  }
287  }
288 
289  // ReadConfiguration is called after looking at the AddIn implementations.
290  // Duplicated are skipped (by using the service information, they don't have to be updated again
291  // when argument information is needed).
293 
294  bInitialized = true; // with or without functions
295 }
296 
297 static sal_uInt16 lcl_GetCategory( const OUString& rName )
298 {
299  static const char* aFuncNames[SC_FUNCGROUP_COUNT] =
300  {
301  // array index = ID - 1 (ID starts at 1)
302  // all upper case
303  "Database", // ID_FUNCTION_GRP_DATABASE
304  "Date&Time", // ID_FUNCTION_GRP_DATETIME
305  "Financial", // ID_FUNCTION_GRP_FINANCIAL
306  "Information", // ID_FUNCTION_GRP_INFO
307  "Logical", // ID_FUNCTION_GRP_LOGIC
308  "Mathematical", // ID_FUNCTION_GRP_MATH
309  "Matrix", // ID_FUNCTION_GRP_MATRIX
310  "Statistical", // ID_FUNCTION_GRP_STATISTIC
311  "Spreadsheet", // ID_FUNCTION_GRP_TABLE
312  "Text", // ID_FUNCTION_GRP_TEXT
313  "Add-In" // ID_FUNCTION_GRP_ADDINS
314  };
315  for (sal_uInt16 i=0; i<SC_FUNCGROUP_COUNT; i++)
316  if ( rName.equalsAscii( aFuncNames[i] ) )
317  return i+1; // IDs start at 1
318 
319  return ID_FUNCTION_GRP_ADDINS; // if not found, use Add-In group
320 }
321 
322 #define CFGPATH_ADDINS "Office.CalcAddIns/AddInInfo"
323 #define CFGSTR_ADDINFUNCTIONS "AddInFunctions"
324 
325 #define CFG_FUNCPROP_DISPLAYNAME 0
326 #define CFG_FUNCPROP_DESCRIPTION 1
327 #define CFG_FUNCPROP_CATEGORY 2
328 #define CFG_FUNCPROP_COUNT 3
329 #define CFGSTR_DISPLAYNAME "DisplayName"
330 #define CFGSTR_DESCRIPTION "Description"
331 #define CFGSTR_CATEGORY "Category"
332 // CategoryDisplayName is ignored for now
333 
334 #define CFGSTR_COMPATIBILITYNAME "CompatibilityName"
335 #define CFGSTR_PARAMETERS "Parameters"
336 
338 {
339  // called only from Initialize
340 
341  ScAddInCfg& rAddInConfig = SC_MOD()->GetAddInCfg();
342 
343  // additional, temporary config item for the compatibility names
344  ScLinkConfigItem aAllLocalesConfig( CFGPATH_ADDINS, ConfigItemMode::AllLocales );
345  // CommitLink is not used (only reading values)
346 
347  const OUString sSlash('/');
348 
349  // get the list of add-ins (services)
350  const uno::Sequence<OUString> aServiceNames = rAddInConfig.GetNodeNames( "" );
351 
352  for ( const OUString& aServiceName : aServiceNames )
353  {
354  ScUnoAddInHelpIdGenerator aHelpIdGenerator( aServiceName );
355 
356  OUString aFunctionsPath(aServiceName + sSlash + CFGSTR_ADDINFUNCTIONS);
357 
358  uno::Sequence<OUString> aFunctionNames = rAddInConfig.GetNodeNames( aFunctionsPath );
359  sal_Int32 nNewCount = aFunctionNames.getLength();
360 
361  // allocate pointers
362 
363  tools::Long nOld = nFuncCount;
364  nFuncCount = nNewCount+nOld;
365  if ( nOld )
366  {
367  std::unique_ptr<std::unique_ptr<ScUnoAddInFuncData>[]> ppNew(new std::unique_ptr<ScUnoAddInFuncData>[nFuncCount]);
368  for (tools::Long i=0; i<nOld; i++)
369  ppNew[i] = std::move(ppFuncData[i]);
370  ppFuncData = std::move(ppNew);
371  }
372  else
373  ppFuncData.reset( new std::unique_ptr<ScUnoAddInFuncData>[nFuncCount] );
374 
375  //TODO: adjust bucket count?
376  if ( !pExactHashMap )
377  pExactHashMap.reset( new ScAddInHashMap );
378  if ( !pNameHashMap )
379  pNameHashMap.reset( new ScAddInHashMap );
380  if ( !pLocalHashMap )
381  pLocalHashMap.reset( new ScAddInHashMap );
382 
383  //TODO: get the function information in a single call for all functions?
384 
385  const OUString* pFuncNameArray = aFunctionNames.getConstArray();
386  for ( sal_Int32 nFuncPos = 0; nFuncPos < nNewCount; nFuncPos++ )
387  {
388  ppFuncData[nFuncPos+nOld] = nullptr;
389 
390  // stored function name: (service name).(function)
391  OUString aFuncName = aServiceName + "." + pFuncNameArray[nFuncPos];
392 
393  // skip the function if already known (read from old AddIn service)
394 
395  if ( pExactHashMap->find( aFuncName ) == pExactHashMap->end() )
396  {
397  OUString aLocalName;
398  OUString aDescription;
399  sal_uInt16 nCategory = ID_FUNCTION_GRP_ADDINS;
400 
401  // get direct information on the function
402 
403  OUString aFuncPropPath = aFunctionsPath + sSlash + pFuncNameArray[nFuncPos] + sSlash;
404 
405  uno::Sequence<OUString> aFuncPropNames{
406  (aFuncPropPath + CFGSTR_DISPLAYNAME), // CFG_FUNCPROP_DISPLAYNAME
407  (aFuncPropPath + CFGSTR_DESCRIPTION), // CFG_FUNCPROP_DESCRIPTION
408  (aFuncPropPath + CFGSTR_CATEGORY)}; // CFG_FUNCPROP_CATEGORY
409 
410  uno::Sequence<uno::Any> aFuncProperties = rAddInConfig.GetProperties( aFuncPropNames );
411  if ( aFuncProperties.getLength() == CFG_FUNCPROP_COUNT )
412  {
413  aFuncProperties[CFG_FUNCPROP_DISPLAYNAME] >>= aLocalName;
414  aFuncProperties[CFG_FUNCPROP_DESCRIPTION] >>= aDescription;
415 
416  OUString aCategoryName;
417  aFuncProperties[CFG_FUNCPROP_CATEGORY] >>= aCategoryName;
418  nCategory = lcl_GetCategory( aCategoryName );
419  }
420 
421  // get compatibility names
422 
423  ::std::vector<ScUnoAddInFuncData::LocalizedName> aCompNames;
424 
425  OUString aCompPath(aFuncPropPath + CFGSTR_COMPATIBILITYNAME);
426  uno::Sequence<OUString> aCompPropNames( &aCompPath, 1 );
427 
428  uno::Sequence<uno::Any> aCompProperties = aAllLocalesConfig.GetProperties( aCompPropNames );
429  if ( aCompProperties.getLength() == 1 )
430  {
431  uno::Sequence<beans::PropertyValue> aLocalEntries;
432  if ( aCompProperties[0] >>= aLocalEntries )
433  {
434  for ( const beans::PropertyValue& rConfig : std::as_const(aLocalEntries) )
435  {
436  // PropertyValue name is the locale ("convert" from
437  // string to canonicalize)
438  OUString aLocale( LanguageTag( rConfig.Name, true).getBcp47( false));
439  // PropertyValue value is the localized value (string in this case)
440  OUString aName;
441  rConfig.Value >>= aName;
442  aCompNames.emplace_back( aLocale, aName);
443  }
444  }
445  }
446 
447  // get argument info
448 
449  std::unique_ptr<ScAddInArgDesc[]> pVisibleArgs;
450  tools::Long nVisibleCount = 0;
451 
452  OUString aArgumentsPath(aFuncPropPath + CFGSTR_PARAMETERS);
453 
454  const uno::Sequence<OUString> aArgumentNames = rAddInConfig.GetNodeNames( aArgumentsPath );
455  sal_Int32 nArgumentCount = aArgumentNames.getLength();
456  if ( nArgumentCount )
457  {
458  // get DisplayName and Description for each argument
459  uno::Sequence<OUString> aArgPropNames( nArgumentCount * 2 );
460  OUString* pPropNameArray = aArgPropNames.getArray();
461 
462  sal_Int32 nIndex = 0;
463  for ( const OUString& rArgName : aArgumentNames )
464  {
465  OUString aOneArgPath = aArgumentsPath + sSlash + rArgName + sSlash;
466 
467  pPropNameArray[nIndex++] = aOneArgPath
469  pPropNameArray[nIndex++] = aOneArgPath
471  }
472 
473  uno::Sequence<uno::Any> aArgProperties = rAddInConfig.GetProperties( aArgPropNames );
474  if ( aArgProperties.getLength() == aArgPropNames.getLength() )
475  {
476  const OUString* pArgNameArray = aArgumentNames.getConstArray();
477  const uno::Any* pPropArray = aArgProperties.getConstArray();
478  OUString sDisplayName;
479  OUString sDescription;
480 
481  ScAddInArgDesc aDesc;
482  aDesc.eType = SC_ADDINARG_NONE; // arg type is not in configuration
483  aDesc.bOptional = false;
484 
485  nVisibleCount = nArgumentCount;
486  pVisibleArgs.reset(new ScAddInArgDesc[nVisibleCount]);
487 
488  nIndex = 0;
489  for ( sal_Int32 nArgument = 0; nArgument < nArgumentCount; nArgument++ )
490  {
491  pPropArray[nIndex++] >>= sDisplayName;
492  pPropArray[nIndex++] >>= sDescription;
493 
494  aDesc.aInternalName = pArgNameArray[nArgument];
495  aDesc.aName = sDisplayName;
496  aDesc.aDescription = sDescription;
497 
498  pVisibleArgs[nArgument] = aDesc;
499  }
500  }
501  }
502 
503  OString sHelpId = aHelpIdGenerator.GetHelpId( pFuncNameArray[nFuncPos] );
504 
505  uno::Reference<reflection::XIdlMethod> xFunc; // remains empty
506  uno::Any aObject; // also empty
507 
508  // create and insert into the array
509 
511  aFuncName, aLocalName, aDescription,
512  nCategory, sHelpId,
513  xFunc, aObject,
514  nVisibleCount, pVisibleArgs.get(), SC_CALLERPOS_NONE );
515 
516  pData->SetCompNames( aCompNames );
517 
518  ppFuncData[nFuncPos+nOld].reset(pData);
519 
520  pExactHashMap->emplace(
521  pData->GetOriginalName(),
522  pData );
523  pNameHashMap->emplace(
524  pData->GetUpperName(),
525  pData );
526  pLocalHashMap->emplace(
527  pData->GetUpperLocal(),
528  pData );
529  }
530  }
531  }
532 }
533 
535 {
536  const OUString& aFullName = rFuncData.GetOriginalName();
537  sal_Int32 nPos = aFullName.lastIndexOf( '.' );
538  if ( nPos <= 0 )
539  return;
540 
541  OUString aServiceName = aFullName.copy( 0, nPos );
542 
543  try
544  {
545  uno::Reference<lang::XMultiServiceFactory> xServiceFactory = comphelper::getProcessServiceFactory();
546  uno::Reference<uno::XInterface> xInterface( xServiceFactory->createInstance( aServiceName ) );
547 
548  if (xInterface.is())
549  UpdateFromAddIn( xInterface, aServiceName );
550  }
551  catch (const uno::Exception &)
552  {
553  SAL_WARN ("sc", "Failed to create addin component '"
554  << aServiceName << "'");
555  }
556 }
557 
558 bool ScUnoAddInCollection::GetExcelName( const OUString& rCalcName,
559  LanguageType eDestLang, OUString& rRetExcelName )
560 {
561  const ScUnoAddInFuncData* pFuncData = GetFuncData( rCalcName );
562  if ( pFuncData )
563  return pFuncData->GetExcelName( eDestLang, rRetExcelName);
564  return false;
565 }
566 
567 bool ScUnoAddInCollection::GetCalcName( const OUString& rExcelName, OUString& rRetCalcName )
568 {
569  if (!bInitialized)
570  Initialize();
571 
572  OUString aUpperCmp = ScGlobal::getCharClassPtr()->uppercase(rExcelName);
573 
574  for (tools::Long i=0; i<nFuncCount; i++)
575  {
576  ScUnoAddInFuncData* pFuncData = ppFuncData[i].get();
577  if ( pFuncData )
578  {
579  const ::std::vector<ScUnoAddInFuncData::LocalizedName>& rNames = pFuncData->GetCompNames();
580  auto bFound = std::any_of(rNames.begin(), rNames.end(),
581  [&aUpperCmp](const ScUnoAddInFuncData::LocalizedName& rName) {
582  return ScGlobal::getCharClassPtr()->uppercase( rName.maName ) == aUpperCmp; });
583  if (bFound)
584  {
585  //TODO: store upper case for comparing?
586 
587  // use the first function that has this name for any language
588  rRetCalcName = pFuncData->GetOriginalName();
589  return true;
590  }
591  }
592  }
593  return false;
594 }
595 
596 static bool IsTypeName( std::u16string_view rName, const uno::Type& rType )
597 {
598  return rName == rType.getTypeName();
599 }
600 
601 static bool lcl_ValidReturnType( const uno::Reference<reflection::XIdlClass>& xClass )
602 {
603  // this must match with ScUnoAddInCall::SetResult
604 
605  if ( !xClass.is() ) return false;
606 
607  switch (xClass->getTypeClass())
608  {
609  case uno::TypeClass_ANY: // variable type
610  case uno::TypeClass_ENUM: //TODO: ???
611  case uno::TypeClass_BOOLEAN:
612  case uno::TypeClass_CHAR:
613  case uno::TypeClass_BYTE:
614  case uno::TypeClass_SHORT:
615  case uno::TypeClass_UNSIGNED_SHORT:
616  case uno::TypeClass_LONG:
617  case uno::TypeClass_UNSIGNED_LONG:
618  case uno::TypeClass_FLOAT:
619  case uno::TypeClass_DOUBLE:
620  case uno::TypeClass_STRING:
621  return true; // values or string
622 
623  case uno::TypeClass_INTERFACE:
624  {
625  // return type XInterface may contain a XVolatileResult
626  //TODO: XIdlClass needs getType() method!
627 
628  OUString sName = xClass->getName();
629  return (
632  }
633 
634  default:
635  {
636  // nested sequences for arrays
637  //TODO: XIdlClass needs getType() method!
638 
639  OUString sName = xClass->getName();
640  return (
641  IsTypeName( sName, cppu::UnoType<uno::Sequence< uno::Sequence<sal_Int32> >>::get() ) ||
642  IsTypeName( sName, cppu::UnoType<uno::Sequence< uno::Sequence<double> >>::get() ) ||
643  IsTypeName( sName, cppu::UnoType<uno::Sequence< uno::Sequence<OUString> >>::get() ) ||
644  IsTypeName( sName, cppu::UnoType<uno::Sequence< uno::Sequence<uno::Any> >>::get() ) );
645  }
646  }
647 }
648 
649 static ScAddInArgumentType lcl_GetArgType( const uno::Reference<reflection::XIdlClass>& xClass )
650 {
651  if (!xClass.is())
652  return SC_ADDINARG_NONE;
653 
654  uno::TypeClass eType = xClass->getTypeClass();
655 
656  if ( eType == uno::TypeClass_LONG ) //TODO: other integer types?
657  return SC_ADDINARG_INTEGER;
658 
659  if ( eType == uno::TypeClass_DOUBLE )
660  return SC_ADDINARG_DOUBLE;
661 
662  if ( eType == uno::TypeClass_STRING )
663  return SC_ADDINARG_STRING;
664 
665  //TODO: XIdlClass needs getType() method!
666  OUString sName = xClass->getName();
667 
668  if (IsTypeName( sName, cppu::UnoType<uno::Sequence< uno::Sequence<sal_Int32> >>::get() ))
670 
671  if (IsTypeName( sName, cppu::UnoType<uno::Sequence< uno::Sequence<double> >>::get() ))
673 
674  if (IsTypeName( sName, cppu::UnoType<uno::Sequence< uno::Sequence<OUString> >>::get() ))
676 
677  if (IsTypeName( sName, cppu::UnoType<uno::Sequence< uno::Sequence<uno::Any> >>::get() ))
679 
682 
684  return SC_ADDINARG_CELLRANGE;
685 
687  return SC_ADDINARG_CALLER;
688 
689  if (IsTypeName( sName, cppu::UnoType<uno::Sequence<uno::Any>>::get() ))
690  return SC_ADDINARG_VARARGS;
691 
692  return SC_ADDINARG_NONE;
693 }
694 
695 void ScUnoAddInCollection::ReadFromAddIn( const uno::Reference<uno::XInterface>& xInterface )
696 {
697  uno::Reference<sheet::XAddIn> xAddIn( xInterface, uno::UNO_QUERY );
698  uno::Reference<lang::XServiceName> xName( xInterface, uno::UNO_QUERY );
699  if ( !(xAddIn.is() && xName.is()) )
700  return;
701 
702  // fdo50118 when GetUseEnglishFunctionName() returns true, set the
703  // locale to en-US to get English function names
704  if ( SC_MOD()->GetFormulaOptions().GetUseEnglishFuncName() )
705  xAddIn->setLocale( lang::Locale( "en", "US", ""));
706  else
707  xAddIn->setLocale( Application::GetSettings().GetUILanguageTag().getLocale());
708 
709  OUString aServiceName( xName->getServiceName() );
710  ScUnoAddInHelpIdGenerator aHelpIdGenerator( aServiceName );
711 
712  //TODO: pass XIntrospection to ReadFromAddIn
713 
714  uno::Reference<uno::XComponentContext> xContext = comphelper::getProcessComponentContext();
715 
716  uno::Reference<beans::XIntrospection> xIntro = beans::theIntrospection::get( xContext );
717  uno::Any aObject;
718  aObject <<= xAddIn;
719  uno::Reference<beans::XIntrospectionAccess> xAcc = xIntro->inspect(aObject);
720  if (!xAcc.is())
721  return;
722 
723  uno::Sequence< uno::Reference<reflection::XIdlMethod> > aMethods =
724  xAcc->getMethods( beans::MethodConcept::ALL );
725  tools::Long nNewCount = aMethods.getLength();
726  if ( !nNewCount )
727  return;
728 
729  tools::Long nOld = nFuncCount;
730  nFuncCount = nNewCount+nOld;
731  if ( nOld )
732  {
733  std::unique_ptr<std::unique_ptr<ScUnoAddInFuncData>[]> ppNew(new std::unique_ptr<ScUnoAddInFuncData>[nFuncCount]);
734  for (tools::Long i=0; i<nOld; i++)
735  ppNew[i] = std::move(ppFuncData[i]);
736  ppFuncData = std::move(ppNew);
737  }
738  else
739  ppFuncData.reset(new std::unique_ptr<ScUnoAddInFuncData>[nFuncCount]);
740 
741  //TODO: adjust bucket count?
742  if ( !pExactHashMap )
743  pExactHashMap.reset( new ScAddInHashMap );
744  if ( !pNameHashMap )
745  pNameHashMap.reset( new ScAddInHashMap );
746  if ( !pLocalHashMap )
747  pLocalHashMap.reset( new ScAddInHashMap );
748 
749  const uno::Reference<reflection::XIdlMethod>* pArray = aMethods.getConstArray();
750  for (tools::Long nFuncPos=0; nFuncPos<nNewCount; nFuncPos++)
751  {
752  ppFuncData[nFuncPos+nOld] = nullptr;
753 
754  uno::Reference<reflection::XIdlMethod> xFunc = pArray[nFuncPos];
755  if (xFunc.is())
756  {
757  // leave out internal functions
758  uno::Reference<reflection::XIdlClass> xClass =
759  xFunc->getDeclaringClass();
760  bool bSkip = true;
761  if ( xClass.is() )
762  {
763  //TODO: XIdlClass needs getType() method!
764  OUString sName = xClass->getName();
765  bSkip = (
766  IsTypeName( sName,
768  IsTypeName( sName,
770  IsTypeName( sName,
772  IsTypeName( sName,
774  }
775  if (!bSkip)
776  {
777  uno::Reference<reflection::XIdlClass> xReturn =
778  xFunc->getReturnType();
779  if ( !lcl_ValidReturnType( xReturn ) )
780  bSkip = true;
781  }
782  if (!bSkip)
783  {
784  OUString aFuncU = xFunc->getName();
785 
786  // stored function name: (service name).(function)
787  OUString aFuncName = aServiceName + "." + aFuncU;
788 
789  bool bValid = true;
790  tools::Long nVisibleCount = 0;
791  tools::Long nCallerPos = SC_CALLERPOS_NONE;
792 
793  uno::Sequence<reflection::ParamInfo> aParams =
794  xFunc->getParameterInfos();
795  tools::Long nParamCount = aParams.getLength();
796  const reflection::ParamInfo* pParArr = aParams.getConstArray();
797  tools::Long nParamPos;
798  for (nParamPos=0; nParamPos<nParamCount; nParamPos++)
799  {
800  if ( pParArr[nParamPos].aMode != reflection::ParamMode_IN )
801  bValid = false;
802  uno::Reference<reflection::XIdlClass> xParClass =
803  pParArr[nParamPos].aType;
804  ScAddInArgumentType eArgType = lcl_GetArgType( xParClass );
805  if ( eArgType == SC_ADDINARG_NONE )
806  bValid = false;
807  else if ( eArgType == SC_ADDINARG_CALLER )
808  nCallerPos = nParamPos;
809  else
810  ++nVisibleCount;
811  }
812  if (bValid)
813  {
814  sal_uInt16 nCategory = lcl_GetCategory(
815  xAddIn->getProgrammaticCategoryName( aFuncU ) );
816 
817  OString sHelpId = aHelpIdGenerator.GetHelpId( aFuncU );
818 
819  OUString aLocalName;
820  try
821  {
822  aLocalName = xAddIn->
823  getDisplayFunctionName( aFuncU );
824  }
825  catch(uno::Exception&)
826  {
827  aLocalName = "###";
828  }
829 
830  OUString aDescription;
831  try
832  {
833  aDescription = xAddIn->
834  getFunctionDescription( aFuncU );
835  }
836  catch(uno::Exception&)
837  {
838  aDescription = "###";
839  }
840 
841  std::unique_ptr<ScAddInArgDesc[]> pVisibleArgs;
842  if ( nVisibleCount > 0 )
843  {
844  ScAddInArgDesc aDesc;
845  pVisibleArgs.reset(new ScAddInArgDesc[nVisibleCount]);
846  tools::Long nDestPos = 0;
847  for (nParamPos=0; nParamPos<nParamCount; nParamPos++)
848  {
849  uno::Reference<reflection::XIdlClass> xParClass =
850  pParArr[nParamPos].aType;
851  ScAddInArgumentType eArgType = lcl_GetArgType( xParClass );
852  if ( eArgType != SC_ADDINARG_CALLER )
853  {
854  OUString aArgName;
855  try
856  {
857  aArgName = xAddIn->
858  getDisplayArgumentName( aFuncU, nParamPos );
859  }
860  catch(uno::Exception&)
861  {
862  aArgName = "###";
863  }
864  OUString aArgDesc;
865  try
866  {
867  aArgDesc = xAddIn->
868  getArgumentDescription( aFuncU, nParamPos );
869  }
870  catch(uno::Exception&)
871  {
872  aArgDesc = "###";
873  }
874 
875  bool bOptional =
876  ( eArgType == SC_ADDINARG_VALUE_OR_ARRAY ||
877  eArgType == SC_ADDINARG_VARARGS );
878 
879  aDesc.eType = eArgType;
880  aDesc.aName = aArgName;
881  aDesc.aDescription = aArgDesc;
882  aDesc.bOptional = bOptional;
883  //TODO: initialize aInternalName only from config?
884  aDesc.aInternalName = pParArr[nParamPos].aName;
885 
886  pVisibleArgs[nDestPos++] = aDesc;
887  }
888  }
889  OSL_ENSURE( nDestPos==nVisibleCount, "wrong count" );
890  }
891 
892  ppFuncData[nFuncPos+nOld].reset( new ScUnoAddInFuncData(
893  aFuncName, aLocalName, aDescription,
894  nCategory, sHelpId,
895  xFunc, aObject,
896  nVisibleCount, pVisibleArgs.get(), nCallerPos ) );
897 
898  const ScUnoAddInFuncData* pData =
899  ppFuncData[nFuncPos+nOld].get();
900  pExactHashMap->emplace(
901  pData->GetOriginalName(),
902  pData );
903  pNameHashMap->emplace(
904  pData->GetUpperName(),
905  pData );
906  pLocalHashMap->emplace(
907  pData->GetUpperLocal(),
908  pData );
909  }
910  }
911  }
912  }
913 }
914 
915 static void lcl_UpdateFunctionList( const ScFunctionList& rFunctionList, const ScUnoAddInFuncData& rFuncData )
916 {
917  const OUString& aCompare = rFuncData.GetUpperLocal(); // as used in FillFunctionDescFromData
918 
919  sal_uLong nCount = rFunctionList.GetCount();
920  for (sal_uLong nPos=0; nPos<nCount; nPos++)
921  {
922  const ScFuncDesc* pDesc = rFunctionList.GetFunction( nPos );
923  if ( pDesc && pDesc->mxFuncName && *pDesc->mxFuncName == aCompare )
924  {
925  ScUnoAddInCollection::FillFunctionDescFromData( rFuncData, *const_cast<ScFuncDesc*>(pDesc) );
926  break;
927  }
928  }
929 }
930 
931 static const ScAddInArgDesc* lcl_FindArgDesc( const ScUnoAddInFuncData& rFuncData, std::u16string_view rArgIntName )
932 {
933  tools::Long nArgCount = rFuncData.GetArgumentCount();
934  const ScAddInArgDesc* pArguments = rFuncData.GetArguments();
935  for (tools::Long nPos=0; nPos<nArgCount; nPos++)
936  {
937  if ( pArguments[nPos].aInternalName == rArgIntName )
938  return &pArguments[nPos];
939  }
940  return nullptr;
941 }
942 
943 void ScUnoAddInCollection::UpdateFromAddIn( const uno::Reference<uno::XInterface>& xInterface,
944  std::u16string_view rServiceName )
945 {
946  uno::Reference<lang::XLocalizable> xLoc( xInterface, uno::UNO_QUERY );
947  if ( xLoc.is() ) // optional in new add-ins
948  {
949  // fdo50118 when GetUseEnglishFunctionName() returns true, set the
950  // locale to en-US to get English function names
951  if ( SC_MOD()->GetFormulaOptions().GetUseEnglishFuncName() )
952  xLoc->setLocale( lang::Locale( "en", "US", ""));
953  else
954  xLoc->setLocale( Application::GetSettings().GetUILanguageTag().getLocale());
955  }
956 
957  // if function list was already initialized, it must be updated
958 
959  ScFunctionList* pFunctionList = nullptr;
961  pFunctionList = ScGlobal::GetStarCalcFunctionList();
962 
963  // only get the function information from Introspection
964 
965  uno::Reference<uno::XComponentContext> xContext = comphelper::getProcessComponentContext();
966 
967  uno::Reference<beans::XIntrospection> xIntro = beans::theIntrospection::get(xContext);
968  uno::Any aObject;
969  aObject <<= xInterface;
970  uno::Reference<beans::XIntrospectionAccess> xAcc = xIntro->inspect(aObject);
971  if (!xAcc.is())
972  return;
973 
974  const uno::Sequence< uno::Reference<reflection::XIdlMethod> > aMethods =
975  xAcc->getMethods( beans::MethodConcept::ALL );
976  for (const uno::Reference<reflection::XIdlMethod>& xFunc : aMethods)
977  {
978  if (xFunc.is())
979  {
980  OUString aFuncU = xFunc->getName();
981 
982  // stored function name: (service name).(function)
983  OUString aFuncName = OUString::Concat(rServiceName) + "." + aFuncU;
984 
985  // internal names are skipped because no FuncData exists
986  ScUnoAddInFuncData* pOldData = const_cast<ScUnoAddInFuncData*>( GetFuncData( aFuncName ) );
987  if ( pOldData )
988  {
989  // Create new (complete) argument info.
990  // As in ReadFromAddIn, the reflection information is authoritative.
991  // Local names and descriptions from pOldData are looked up using the
992  // internal argument name.
993 
994  bool bValid = true;
995  tools::Long nVisibleCount = 0;
996  tools::Long nCallerPos = SC_CALLERPOS_NONE;
997 
998  const uno::Sequence<reflection::ParamInfo> aParams =
999  xFunc->getParameterInfos();
1000  tools::Long nParamCount = aParams.getLength();
1001  const reflection::ParamInfo* pParArr = aParams.getConstArray();
1002  for (tools::Long nParamPos=0; nParamPos<nParamCount; nParamPos++)
1003  {
1004  if ( pParArr[nParamPos].aMode != reflection::ParamMode_IN )
1005  bValid = false;
1006  uno::Reference<reflection::XIdlClass> xParClass =
1007  pParArr[nParamPos].aType;
1008  ScAddInArgumentType eArgType = lcl_GetArgType( xParClass );
1009  if ( eArgType == SC_ADDINARG_NONE )
1010  bValid = false;
1011  else if ( eArgType == SC_ADDINARG_CALLER )
1012  nCallerPos = nParamPos;
1013  else
1014  ++nVisibleCount;
1015  }
1016  if (bValid)
1017  {
1018  std::unique_ptr<ScAddInArgDesc[]> pVisibleArgs;
1019  if ( nVisibleCount > 0 )
1020  {
1021  ScAddInArgDesc aDesc;
1022  pVisibleArgs.reset(new ScAddInArgDesc[nVisibleCount]);
1023  tools::Long nDestPos = 0;
1024  for (const auto& rParam : aParams)
1025  {
1026  uno::Reference<reflection::XIdlClass> xParClass =
1027  rParam.aType;
1028  ScAddInArgumentType eArgType = lcl_GetArgType( xParClass );
1029  if ( eArgType != SC_ADDINARG_CALLER )
1030  {
1031  const ScAddInArgDesc* pOldArgDesc =
1032  lcl_FindArgDesc( *pOldData, rParam.aName );
1033  if ( pOldArgDesc )
1034  {
1035  aDesc.aName = pOldArgDesc->aName;
1036  aDesc.aDescription = pOldArgDesc->aDescription;
1037  }
1038  else
1039  aDesc.aName = aDesc.aDescription = "###";
1040 
1041  bool bOptional =
1042  ( eArgType == SC_ADDINARG_VALUE_OR_ARRAY ||
1043  eArgType == SC_ADDINARG_VARARGS );
1044 
1045  aDesc.eType = eArgType;
1046  aDesc.bOptional = bOptional;
1047  //TODO: initialize aInternalName only from config?
1048  aDesc.aInternalName = rParam.aName;
1049 
1050  pVisibleArgs[nDestPos++] = aDesc;
1051  }
1052  }
1053  OSL_ENSURE( nDestPos==nVisibleCount, "wrong count" );
1054  }
1055 
1056  pOldData->SetFunction( xFunc, aObject );
1057  pOldData->SetArguments( nVisibleCount, pVisibleArgs.get() );
1058  pOldData->SetCallerPos( nCallerPos );
1059 
1060  if ( pFunctionList )
1061  lcl_UpdateFunctionList( *pFunctionList, *pOldData );
1062  }
1063  }
1064  }
1065  }
1066 }
1067 
1068 const OUString & ScUnoAddInCollection::FindFunction( const OUString& rUpperName, bool bLocalFirst )
1069 {
1070  if (!bInitialized)
1071  Initialize();
1072 
1073  if (nFuncCount == 0)
1074  return EMPTY_OUSTRING;
1075 
1076  if ( bLocalFirst )
1077  {
1078  // first scan all local names (used for entering formulas)
1079 
1080  ScAddInHashMap::const_iterator iLook( pLocalHashMap->find( rUpperName ) );
1081  if ( iLook != pLocalHashMap->end() )
1082  return iLook->second->GetOriginalName();
1083  }
1084  else
1085  {
1086  // first scan international names (used when calling a function)
1087  //TODO: before that, check for exact match???
1088 
1089  ScAddInHashMap::const_iterator iLook( pNameHashMap->find( rUpperName ) );
1090  if ( iLook != pNameHashMap->end() )
1091  return iLook->second->GetOriginalName();
1092 
1093  // after that, scan all local names (to allow replacing old AddIns with Uno)
1094 
1095  iLook = pLocalHashMap->find( rUpperName );
1096  if ( iLook != pLocalHashMap->end() )
1097  return iLook->second->GetOriginalName();
1098  }
1099 
1100  return EMPTY_OUSTRING;
1101 }
1102 
1103 const ScUnoAddInFuncData* ScUnoAddInCollection::GetFuncData( const OUString& rName, bool bComplete )
1104 {
1105  if (!bInitialized)
1106  Initialize();
1107 
1108  // rName must be the exact internal name
1109 
1110  ScAddInHashMap::const_iterator iLook( pExactHashMap->find( rName ) );
1111  if ( iLook != pExactHashMap->end() )
1112  {
1113  const ScUnoAddInFuncData* pFuncData = iLook->second;
1114 
1115  if ( bComplete && !pFuncData->GetFunction().is() ) //TODO: extra flag?
1116  LoadComponent( *pFuncData );
1117 
1118  return pFuncData;
1119  }
1120 
1121  return nullptr;
1122 }
1123 
1125 {
1126  if (!bInitialized)
1127  Initialize();
1128 
1129  if (nIndex < nFuncCount)
1130  return ppFuncData[nIndex].get();
1131  return nullptr;
1132 }
1133 
1135 {
1136  if (!bInitialized)
1137  Initialize();
1138 
1139  // modify rName - input: exact name
1140 
1141  ScAddInHashMap::const_iterator iLook( pExactHashMap->find( rName ) );
1142  if ( iLook != pExactHashMap->end() )
1143  rName = iLook->second->GetUpperLocal(); //TODO: upper?
1144 }
1145 
1147 {
1148  if (!bInitialized)
1149  Initialize();
1150 
1151  return nFuncCount;
1152 }
1153 
1155 {
1156  if (!bInitialized)
1157  Initialize();
1158 
1159  if (nFunc >= nFuncCount || !ppFuncData[nFunc])
1160  return false;
1161 
1162  const ScUnoAddInFuncData& rFuncData = *ppFuncData[nFunc];
1163 
1164  return FillFunctionDescFromData( rFuncData, rDesc );
1165 }
1166 
1168 {
1169  rDesc.Clear();
1170 
1171  bool bIncomplete = !rFuncData.GetFunction().is(); //TODO: extra flag?
1172 
1173  tools::Long nArgCount = rFuncData.GetArgumentCount();
1174  if ( nArgCount > SAL_MAX_UINT16 )
1175  return false;
1176 
1177  if ( bIncomplete )
1178  nArgCount = 0; // if incomplete, fill without argument info (no wrong order)
1179 
1180  // nFIndex is set from outside
1181 
1182  rDesc.mxFuncName = rFuncData.GetUpperLocal(); //TODO: upper?
1183  rDesc.nCategory = rFuncData.GetCategory();
1184  rDesc.sHelpId = rFuncData.GetHelpId();
1185 
1186  OUString aDesc = rFuncData.GetDescription();
1187  if (aDesc.isEmpty())
1188  aDesc = rFuncData.GetLocalName(); // use name if no description is available
1189  rDesc.mxFuncDesc = aDesc ;
1190 
1191  // AddInArgumentType_CALLER is already left out in FuncData
1192 
1193  rDesc.nArgCount = static_cast<sal_uInt16>(nArgCount);
1194  if ( nArgCount )
1195  {
1196  bool bMultiple = false;
1197  const ScAddInArgDesc* pArgs = rFuncData.GetArguments();
1198 
1199  rDesc.maDefArgNames.clear();
1200  rDesc.maDefArgNames.resize(nArgCount);
1201  rDesc.maDefArgDescs.clear();
1202  rDesc.maDefArgDescs.resize(nArgCount);
1203  rDesc.pDefArgFlags = new ScFuncDesc::ParameterFlags[nArgCount];
1204  for ( tools::Long nArg=0; nArg<nArgCount; nArg++ )
1205  {
1206  rDesc.maDefArgNames[nArg] = pArgs[nArg].aName;
1207  rDesc.maDefArgDescs[nArg] = pArgs[nArg].aDescription;
1208  rDesc.pDefArgFlags[nArg].bOptional = pArgs[nArg].bOptional;
1209 
1210  // no empty names...
1211  if ( rDesc.maDefArgNames[nArg].isEmpty() )
1212  {
1213  OUString aDefName = "arg" + OUString::number( nArg+1 );
1214  rDesc.maDefArgNames[nArg] = aDefName;
1215  }
1216 
1217  // last argument repeated?
1218  if ( nArg+1 == nArgCount && ( pArgs[nArg].eType == SC_ADDINARG_VARARGS ) )
1219  bMultiple = true;
1220  }
1221 
1222  if ( bMultiple )
1223  rDesc.nArgCount += VAR_ARGS - 1; // VAR_ARGS means just one repeated arg
1224  }
1225 
1226  rDesc.bIncomplete = bIncomplete;
1227 
1228  return true;
1229 }
1230 
1233  bValidCount( false ),
1234  nErrCode( FormulaError::NoCode ), // before function was called
1235  bHasString( true ),
1236  fValue( 0.0 ),
1237  xMatrix( nullptr )
1238 {
1239  pFuncData = rColl.GetFuncData( rName, true ); // need fully initialized data
1240  OSL_ENSURE( pFuncData, "Function Data missing" );
1241  if ( !pFuncData )
1242  return;
1243 
1244  tools::Long nDescCount = pFuncData->GetArgumentCount();
1245  const ScAddInArgDesc* pArgs = pFuncData->GetArguments();
1246 
1247  // is aVarArg sequence needed?
1248  if ( nParamCount >= nDescCount && nDescCount > 0 &&
1249  pArgs[nDescCount-1].eType == SC_ADDINARG_VARARGS )
1250  {
1251  tools::Long nVarCount = nParamCount - ( nDescCount - 1 ); // size of last argument
1252  aVarArg.realloc( nVarCount );
1253  bValidCount = true;
1254  }
1255  else if ( nParamCount <= nDescCount )
1256  {
1257  // all args behind nParamCount must be optional
1258  bValidCount = true;
1259  for (tools::Long i=nParamCount; i<nDescCount; i++)
1260  if ( !pArgs[i].bOptional )
1261  bValidCount = false;
1262  }
1263  // else invalid (too many arguments)
1264 
1265  if ( bValidCount )
1266  aArgs.realloc( nDescCount ); // sequence must always match function signature
1267 }
1268 
1270 {
1271  // pFuncData is deleted with ScUnoAddInCollection
1272 }
1273 
1275 {
1276  if ( pFuncData )
1277  {
1279  const ScAddInArgDesc* pArgs = pFuncData->GetArguments();
1280 
1281  // if last arg is sequence, use "any" type
1282  if ( nCount > 0 && nPos >= nCount-1 && pArgs[nCount-1].eType == SC_ADDINARG_VARARGS )
1284 
1285  if ( nPos < nCount )
1286  return pArgs[nPos].eType;
1287  }
1288  return SC_ADDINARG_VALUE_OR_ARRAY; //TODO: error code !!!!
1289 }
1290 
1292 {
1294 }
1295 
1296 void ScUnoAddInCall::SetCaller( const uno::Reference<uno::XInterface>& rInterface )
1297 {
1298  xCaller = rInterface;
1299 }
1300 
1302 {
1303  if (pObjSh)
1304  {
1305  uno::Reference<uno::XInterface> xInt( pObjSh->GetBaseModel(), uno::UNO_QUERY );
1306  SetCaller( xInt );
1307  }
1308 }
1309 
1310 void ScUnoAddInCall::SetParam( tools::Long nPos, const uno::Any& rValue )
1311 {
1312  if ( !pFuncData )
1313  return;
1314 
1316  const ScAddInArgDesc* pArgs = pFuncData->GetArguments();
1317  if ( nCount > 0 && nPos >= nCount-1 && pArgs[nCount-1].eType == SC_ADDINARG_VARARGS )
1318  {
1319  tools::Long nVarPos = nPos-(nCount-1);
1320  if ( nVarPos < aVarArg.getLength() )
1321  aVarArg.getArray()[nVarPos] = rValue;
1322  else
1323  {
1324  OSL_FAIL("wrong argument number");
1325  }
1326  }
1327  else if ( nPos < aArgs.getLength() )
1328  aArgs.getArray()[nPos] = rValue;
1329  else
1330  {
1331  OSL_FAIL("wrong argument number");
1332  }
1333 }
1334 
1336 {
1337  if ( !pFuncData )
1338  return;
1339 
1341  const ScAddInArgDesc* pArgs = pFuncData->GetArguments();
1342  if ( nCount > 0 && pArgs[nCount-1].eType == SC_ADDINARG_VARARGS )
1343  {
1344  // insert aVarArg as last argument
1345  //TODO: after inserting caller (to prevent copying twice)?
1346 
1347  OSL_ENSURE( aArgs.getLength() == nCount, "wrong argument count" );
1348  aArgs.getArray()[nCount-1] <<= aVarArg;
1349  }
1350 
1352  {
1353  uno::Any aCallerAny;
1354  aCallerAny <<= xCaller;
1355 
1356  tools::Long nUserLen = aArgs.getLength();
1357  tools::Long nCallPos = pFuncData->GetCallerPos();
1358  if (nCallPos>nUserLen) // should not happen
1359  {
1360  OSL_FAIL("wrong CallPos");
1361  nCallPos = nUserLen;
1362  }
1363 
1364  tools::Long nDestLen = nUserLen + 1;
1365  uno::Sequence<uno::Any> aRealArgs( nDestLen );
1366  uno::Any* pDest = aRealArgs.getArray();
1367 
1368  pDest = std::copy_n(aArgs.begin(), nCallPos, pDest);
1369  *pDest = aCallerAny;
1370  std::copy(std::next(aArgs.begin(), nCallPos), aArgs.end(), std::next(pDest));
1371 
1372  ExecuteCallWithArgs( aRealArgs );
1373  }
1374  else
1376 }
1377 
1378 void ScUnoAddInCall::ExecuteCallWithArgs(uno::Sequence<uno::Any>& rCallArgs)
1379 {
1380  // rCallArgs may not match argument descriptions (because of caller)
1381 
1382  uno::Reference<reflection::XIdlMethod> xFunction;
1383  uno::Any aObject;
1384  if ( pFuncData )
1385  {
1386  xFunction = pFuncData->GetFunction();
1387  aObject = pFuncData->GetObject();
1388  }
1389 
1390  if ( !xFunction.is() )
1391  return;
1392 
1393  uno::Any aAny;
1394  nErrCode = FormulaError::NONE;
1395 
1396  try
1397  {
1398  aAny = xFunction->invoke( aObject, rCallArgs );
1399  }
1400  catch(lang::IllegalArgumentException&)
1401  {
1402  nErrCode = FormulaError::IllegalArgument;
1403  }
1404  catch(const reflection::InvocationTargetException& rWrapped)
1405  {
1406  if ( rWrapped.TargetException.getValueType().equals(
1408  nErrCode = FormulaError::IllegalArgument;
1409  else if ( rWrapped.TargetException.getValueType().equals(
1411  nErrCode = FormulaError::NoConvergence;
1412  else
1413  nErrCode = FormulaError::NoValue;
1414  }
1415  catch(uno::Exception&)
1416  {
1417  nErrCode = FormulaError::NoValue;
1418  }
1419 
1420  if (nErrCode == FormulaError::NONE)
1421  SetResult( aAny ); // convert result to Calc types
1422 }
1423 
1424 template <typename T>
1425 static sal_Int32 lcl_GetMaxColCount(const uno::Sequence< uno::Sequence<T> >* pRowSeq)
1426 {
1427  if (!pRowSeq->hasElements())
1428  return 0;
1429 
1430  auto pRow = std::max_element(pRowSeq->begin(), pRowSeq->end(),
1431  [](const uno::Sequence<T>& a, const uno::Sequence<T>& b) {
1432  return a.getLength() < b.getLength(); });
1433  return pRow->getLength();
1434 }
1435 
1436 void ScUnoAddInCall::SetResult( const uno::Any& rNewRes )
1437 {
1438  nErrCode = FormulaError::NONE;
1439  xVarRes = nullptr;
1440 
1441  // Reflection* pRefl = rNewRes.getReflection();
1442 
1443  uno::TypeClass eClass = rNewRes.getValueTypeClass();
1444  const uno::Type& aType = rNewRes.getValueType();
1445  switch (eClass)
1446  {
1447  case uno::TypeClass_VOID:
1448  nErrCode = FormulaError::NotAvailable; // #NA
1449  break;
1450 
1451  case uno::TypeClass_ENUM:
1452  case uno::TypeClass_BOOLEAN:
1453  case uno::TypeClass_CHAR:
1454  case uno::TypeClass_BYTE:
1455  case uno::TypeClass_SHORT:
1456  case uno::TypeClass_UNSIGNED_SHORT:
1457  case uno::TypeClass_LONG:
1458  case uno::TypeClass_UNSIGNED_LONG:
1459  case uno::TypeClass_FLOAT:
1460  case uno::TypeClass_DOUBLE:
1461  {
1462  uno::TypeClass eMyClass;
1463  ScApiTypeConversion::ConvertAnyToDouble( fValue, eMyClass, rNewRes);
1464  bHasString = false;
1465  }
1466  break;
1467 
1468  case uno::TypeClass_STRING:
1469  {
1470  rNewRes >>= aString;
1471  bHasString = true;
1472  }
1473  break;
1474 
1475  case uno::TypeClass_INTERFACE:
1476  {
1477  //TODO: directly extract XVolatileResult from any?
1478  uno::Reference<uno::XInterface> xInterface;
1479  rNewRes >>= xInterface;
1480  if ( xInterface.is() )
1481  xVarRes.set( xInterface, uno::UNO_QUERY );
1482 
1483  if (!xVarRes.is())
1484  nErrCode = FormulaError::NoValue; // unknown interface
1485  }
1486  break;
1487 
1488  default:
1489  if ( aType.equals( cppu::UnoType<uno::Sequence< uno::Sequence<sal_Int32> >>::get() ) )
1490  {
1491  const uno::Sequence< uno::Sequence<sal_Int32> >* pRowSeq = nullptr;
1492 
1493  //TODO: use pointer from any!
1494  uno::Sequence< uno::Sequence<sal_Int32> > aSequence;
1495  if ( rNewRes >>= aSequence )
1496  pRowSeq = &aSequence;
1497 
1498  if ( pRowSeq )
1499  {
1500  sal_Int32 nRowCount = pRowSeq->getLength();
1501  sal_Int32 nMaxColCount = lcl_GetMaxColCount(pRowSeq);
1502  if ( nMaxColCount && nRowCount )
1503  {
1504  const uno::Sequence<sal_Int32>* pRowArr = pRowSeq->getConstArray();
1505  xMatrix = new ScMatrix(
1506  static_cast<SCSIZE>(nMaxColCount),
1507  static_cast<SCSIZE>(nRowCount), 0.0);
1508  for (sal_Int32 nRow=0; nRow<nRowCount; nRow++)
1509  {
1510  sal_Int32 nColCount = pRowArr[nRow].getLength();
1511  const sal_Int32* pColArr = pRowArr[nRow].getConstArray();
1512  for (sal_Int32 nCol=0; nCol<nColCount; nCol++)
1513  xMatrix->PutDouble( pColArr[nCol],
1514  static_cast<SCSIZE>(nCol),
1515  static_cast<SCSIZE>(nRow) );
1516  for (sal_Int32 nCol=nColCount; nCol<nMaxColCount; nCol++)
1517  xMatrix->PutDouble( 0.0,
1518  static_cast<SCSIZE>(nCol),
1519  static_cast<SCSIZE>(nRow) );
1520  }
1521  }
1522  }
1523  }
1524  else if ( aType.equals( cppu::UnoType<uno::Sequence< uno::Sequence<double> >>::get() ) )
1525  {
1526  const uno::Sequence< uno::Sequence<double> >* pRowSeq = nullptr;
1527 
1528  //TODO: use pointer from any!
1529  uno::Sequence< uno::Sequence<double> > aSequence;
1530  if ( rNewRes >>= aSequence )
1531  pRowSeq = &aSequence;
1532 
1533  if ( pRowSeq )
1534  {
1535  sal_Int32 nRowCount = pRowSeq->getLength();
1536  sal_Int32 nMaxColCount = lcl_GetMaxColCount(pRowSeq);
1537  if ( nMaxColCount && nRowCount )
1538  {
1539  const uno::Sequence<double>* pRowArr = pRowSeq->getConstArray();
1540  xMatrix = new ScMatrix(
1541  static_cast<SCSIZE>(nMaxColCount),
1542  static_cast<SCSIZE>(nRowCount), 0.0);
1543  for (sal_Int32 nRow=0; nRow<nRowCount; nRow++)
1544  {
1545  sal_Int32 nColCount = pRowArr[nRow].getLength();
1546  const double* pColArr = pRowArr[nRow].getConstArray();
1547  for (sal_Int32 nCol=0; nCol<nColCount; nCol++)
1548  xMatrix->PutDouble( pColArr[nCol],
1549  static_cast<SCSIZE>(nCol),
1550  static_cast<SCSIZE>(nRow) );
1551  for (sal_Int32 nCol=nColCount; nCol<nMaxColCount; nCol++)
1552  xMatrix->PutDouble( 0.0,
1553  static_cast<SCSIZE>(nCol),
1554  static_cast<SCSIZE>(nRow) );
1555  }
1556  }
1557  }
1558  }
1559  else if ( aType.equals( cppu::UnoType<uno::Sequence< uno::Sequence<OUString> >>::get() ) )
1560  {
1561  const uno::Sequence< uno::Sequence<OUString> >* pRowSeq = nullptr;
1562 
1563  //TODO: use pointer from any!
1564  uno::Sequence< uno::Sequence<OUString> > aSequence;
1565  if ( rNewRes >>= aSequence )
1566  pRowSeq = &aSequence;
1567 
1568  if ( pRowSeq )
1569  {
1570  sal_Int32 nRowCount = pRowSeq->getLength();
1571  sal_Int32 nMaxColCount = lcl_GetMaxColCount(pRowSeq);
1572  if ( nMaxColCount && nRowCount )
1573  {
1574  const uno::Sequence<OUString>* pRowArr = pRowSeq->getConstArray();
1575  xMatrix = new ScMatrix(
1576  static_cast<SCSIZE>(nMaxColCount),
1577  static_cast<SCSIZE>(nRowCount), 0.0);
1578  for (sal_Int32 nRow=0; nRow<nRowCount; nRow++)
1579  {
1580  sal_Int32 nColCount = pRowArr[nRow].getLength();
1581  const OUString* pColArr = pRowArr[nRow].getConstArray();
1582  for (sal_Int32 nCol=0; nCol<nColCount; nCol++)
1583  {
1584  xMatrix->PutString(
1585  svl::SharedString(pColArr[nCol]),
1586  static_cast<SCSIZE>(nCol), static_cast<SCSIZE>(nRow));
1587  }
1588  for (sal_Int32 nCol=nColCount; nCol<nMaxColCount; nCol++)
1589  {
1590  xMatrix->PutString(
1592  static_cast<SCSIZE>(nCol), static_cast<SCSIZE>(nRow));
1593  }
1594  }
1595  }
1596  }
1597  }
1598  else if ( aType.equals( cppu::UnoType<uno::Sequence< uno::Sequence<uno::Any> >>::get() ) )
1599  {
1601  }
1602 
1603  if (!xMatrix) // no array found
1604  nErrCode = FormulaError::NoValue; //TODO: code for error in return type???
1605  }
1606 }
1607 
1608 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Matrix data type that can store values of mixed types.
Definition: scmatrix.hxx:112
constexpr Method aMethods[]
#define ID_FUNCTION_GRP_ADDINS
Definition: scfuncs.hxx:31
List of spreadsheet functions.
Definition: funcdesc.hxx:241
OUString aName
Definition: addincol.hxx:67
sal_Int32 nIndex
bool NeedsCaller() const
Definition: addincol.cxx:1291
const ::std::vector< LocalizedName > & GetCompNames() const
Definition: addincol.cxx:102
#define EMPTY_OUSTRING
Definition: global.hxx:213
bool bOptional
Parameter is optional.
Definition: funcdesc.hxx:211
static bool IsTypeName(std::u16string_view rName, const uno::Type &rType)
Definition: addincol.cxx:596
std::unique_ptr< ContentProperties > pData
ScMatrixRef xMatrix
Definition: addincol.hxx:197
const ScUnoAddInFuncData * GetFuncData(const OUString &rName, bool bComplete=false)
Only if bComplete is set, the function reference and argument types are initialized (component may ha...
Definition: addincol.cxx:1103
sal_uInt16 char char * pDesc
Definition: callform.cxx:57
static OUString convertToBcp47(LanguageType nLangID)
sal_uIntPtr sal_uLong
long Long
Stores whether a parameter is optional or suppressed.
Definition: funcdesc.hxx:209
static const AllSettings & GetSettings()
const OUString & GetLocalName() const
Definition: addincol.hxx:112
const OUString & getBcp47(bool bResolveSystem=true) const
static bool ConvertAnyToDouble(double &o_fVal, css::uno::TypeClass &o_eClass, const css::uno::Any &rAny)
Convert a uno::Any to double if possible, including integer types.
Definition: rangeseq.cxx:327
OUString aDescription
Definition: addincol.hxx:68
void LoadComponent(const ScUnoAddInFuncData &rFuncData)
Definition: addincol.cxx:534
void SetCallerPos(tools::Long nNewPos)
Definition: addincol.cxx:208
Sequence< OUString > aServiceNames
tools::Long nFuncCount
Definition: addincol.hxx:138
std::unordered_map< OUString, const ScUnoAddInFuncData * > ScAddInHashMap
Definition: addincol.hxx:44
void SetParam(tools::Long nPos, const css::uno::Any &rValue)
Definition: addincol.cxx:1310
const OUString & GetUpperName() const
Definition: addincol.hxx:113
OUString aUpperName
for entering formulas
Definition: addincol.hxx:87
const OUString & GetDescription() const
Definition: addincol.hxx:121
const css::uno::Any & GetObject() const
Definition: addincol.hxx:117
#define CFG_FUNCPROP_COUNT
Definition: addincol.cxx:328
OString GetHelpId(const OUString &rFuncName) const
#define SC_FUNCGROUP_COUNT
Definition: funcdesc.hxx:301
css::uno::Reference< css::sheet::XVolatileResult > xVarRes
Definition: addincol.hxx:198
void SetFunction(const css::uno::Reference< css::reflection::XIdlMethod > &rNewFunc, const css::uno::Any &rNewObj)
Definition: addincol.cxx:189
std::unique_ptr< ScAddInHashMap > pExactHashMap
exact internal name
Definition: addincol.hxx:140
bool GetExcelName(const OUString &rCalcName, LanguageType eDestLang, OUString &rRetExcelName)
leave rRetExcelName unchanged, if no matching name is found
Definition: addincol.cxx:558
char sal_uInt16 & nParamCount
Definition: callform.cxx:53
void SetCaller(const css::uno::Reference< css::uno::XInterface > &rInterface)
Definition: addincol.cxx:1296
#define SAL_MAX_UINT16
ScAddInArgumentType eType
Definition: addincol.hxx:69
#define CFG_FUNCPROP_DISPLAYNAME
Definition: addincol.cxx:325
int nCount
Generates help IDs for standard Calc AddIns.
Definition: addinhelpid.hxx:28
ParameterFlags * pDefArgFlags
Flags for each parameter.
Definition: funcdesc.hxx:220
void ExecuteCall()
Definition: addincol.cxx:1335
#define CFGSTR_DISPLAYNAME
Definition: addincol.cxx:329
ScAddInArgumentType GetArgType(tools::Long nPos)
Definition: addincol.cxx:1274
css::uno::Reference< css::frame::XModel > GetBaseModel() const
void SetArguments(tools::Long nNewCount, const ScAddInArgDesc *pNewDescs)
Definition: addincol.cxx:195
const char * sName
const OUString & GetUpperLocal() const
Definition: addincol.hxx:114
css::uno::Reference< css::uno::XInterface > xCaller
Definition: addincol.hxx:190
css::uno::Sequence< css::uno::Any > GetProperties(const css::uno::Sequence< OUString > &rNames)
Definition: addincfg.hxx:35
DocumentType eType
#define CFGSTR_ADDINFUNCTIONS
Definition: addincol.cxx:323
XPropertySet.
Definition: addincol.hxx:60
static sal_Int32 lcl_GetMaxColCount(const uno::Sequence< uno::Sequence< T > > *pRowSeq)
Definition: addincol.cxx:1425
sal_uInt16 nCategory
Function category.
Definition: funcdesc.hxx:222
OUString aUpperLocal
for entering formulas
Definition: addincol.hxx:88
int i
uno_Any a
static bool lcl_ValidReturnType(const uno::Reference< reflection::XIdlClass > &xClass)
Definition: addincol.cxx:601
std::unique_ptr< ScAddInHashMap > pLocalHashMap
localized name upper
Definition: addincol.hxx:142
#define VAR_ARGS
std::vector< OUString > maDefArgDescs
Description(s) of parameter(s)
Definition: funcdesc.hxx:219
#define CFGSTR_CATEGORY
Definition: addincol.cxx:331
#define SC_MOD()
Definition: scmod.hxx:249
mutable::std::vector< LocalizedName > maCompNames
Definition: addincol.hxx:98
const OUString & FindFunction(const OUString &rUpperName, bool bLocalFirst)
User entered name. rUpperName MUST already be upper case!
Definition: addincol.cxx:1068
static bool FillFunctionDescFromData(const ScUnoAddInFuncData &rFuncData, ScFuncDesc &rDesc)
Definition: addincol.cxx:1167
void LocalizeString(OUString &rName)
modify rName - input: exact name
Definition: addincol.cxx:1134
OUString uppercase(const OUString &rStr, sal_Int32 nPos, sal_Int32 nCount) const
std::unique_ptr< ScAddInHashMap > pNameHashMap
internal name upper
Definition: addincol.hxx:141
std::optional< OUString > mxFuncDesc
Description of function.
Definition: funcdesc.hxx:217
sal_uInt16 GetCategory() const
Definition: addincol.hxx:122
void ReadFromAddIn(const css::uno::Reference< css::uno::XInterface > &xInterface)
Definition: addincol.cxx:695
::std::vector< OUString > getFallbackStrings(bool bIncludeFullBcp47) const
Reference< XComponentContext > getComponentContext(Reference< XMultiServiceFactory > const &factory)
const OUString & GetOriginalName() const
Definition: addincol.hxx:111
const ScFuncDesc * GetFunction(sal_uInt32 nIndex) const
Definition: funcdesc.cxx:1015
OUString aInternalName
used to match configuration and reflection information
Definition: addincol.hxx:66
#define CFG_FUNCPROP_DESCRIPTION
Definition: addincol.cxx:326
const ScAddInArgDesc * GetArguments() const
Definition: addincol.hxx:119
FormulaError
static ScFunctionList * GetStarCalcFunctionList()
Definition: global.cxx:609
std::unique_ptr< ScAddInArgDesc[]> pArgDescs
Definition: addincol.hxx:94
#define CFGSTR_COMPATIBILITYNAME
Definition: addincol.cxx:334
static ScAddInArgumentType lcl_GetArgType(const uno::Reference< reflection::XIdlClass > &xClass)
Definition: addincol.cxx:649
const LanguageTag & getLocale()
static bool HasStarCalcFunctionList()
Definition: global.cxx:604
const css::uno::Reference< css::reflection::XIdlMethod > & GetFunction() const
Definition: addincol.hxx:115
css::uno::Sequence< css::uno::Any > aVarArg
Definition: addincol.hxx:189
FormulaError nErrCode
Definition: addincol.hxx:193
tools::Long nCallerPos
Definition: addincol.hxx:95
Reference< XMultiServiceFactory > getProcessServiceFactory()
std::optional< OUString > mxFuncName
Function name.
Definition: funcdesc.hxx:216
#define CFGSTR_DESCRIPTION
Definition: addincol.cxx:330
void Clear()
Clears the object.
Definition: funcdesc.cxx:118
css::uno::Sequence< css::uno::Any > aArgs
Definition: addincol.hxx:188
static const ScAddInArgDesc * lcl_FindArgDesc(const ScUnoAddInFuncData &rFuncData, std::u16string_view rArgIntName)
Definition: addincol.cxx:931
void SetCallerFromObjectShell(const SfxObjectShell *pSh)
Definition: addincol.cxx:1301
#define CFGSTR_PARAMETERS
Definition: addincol.cxx:335
static ScMatrixRef CreateMixedMatrix(const css::uno::Any &rAny)
Convert a sequence of mixed elements to ScMatrix.
Definition: rangeseq.cxx:357
OUString aName
tools::Long GetArgumentCount() const
Definition: addincol.hxx:118
ScUnoAddInFuncData(const OUString &rNam, const OUString &rLoc, const OUString &rDesc, sal_uInt16 nCat, const OString &, const css::uno::Reference< css::reflection::XIdlMethod > &rFunc, const css::uno::Any &rO, tools::Long nAC, const ScAddInArgDesc *pAD, tools::Long nCP)
Definition: addincol.cxx:67
const ScUnoAddInFuncData * pFuncData
Definition: addincol.hxx:187
std::unique_ptr< std::unique_ptr< ScUnoAddInFuncData >[]> ppFuncData
Definition: addincol.hxx:139
css::uno::Reference< css::reflection::XIdlMethod > xFunction
Definition: addincol.hxx:90
static SC_DLLPUBLIC const CharClass * getCharClassPtr()
Definition: global.cxx:1009
tools::Long GetCallerPos() const
Definition: addincol.hxx:120
Reference< XComponentContext > getProcessComponentContext()
XCellRange.
Definition: addincol.hxx:59
OUString aString
Definition: addincol.hxx:196
#define CFGPATH_ADDINS
Definition: addincol.cxx:322
sal_uInt32 GetCount() const
Definition: funcdesc.hxx:247
#define CFG_FUNCPROP_CATEGORY
Definition: addincol.cxx:327
void SetCompNames(const ::std::vector< LocalizedName > &rNew)
Definition: addincol.cxx:131
void SetResult(const css::uno::Any &rNewRes)
Definition: addincol.cxx:1436
OString sHelpId
HelpId of function.
Definition: funcdesc.hxx:226
css::uno::Sequence< OUString > GetNodeNames(const OUString &rNode)
#define SAL_WARN(area, stream)
static sal_uInt16 lcl_GetCategory(const OUString &rName)
Definition: addincol.cxx:297
const OString & GetHelpId() const
Definition: addincol.hxx:123
std::vector< OUString > maDefArgNames
Parameter name(s)
Definition: funcdesc.hxx:218
static void lcl_UpdateFunctionList(const ScFunctionList &rFunctionList, const ScUnoAddInFuncData &rFuncData)
Definition: addincol.cxx:915
ScAddInArgumentType
Definition: addincol.hxx:48
bool GetExcelName(LanguageType eDestLang, OUString &rRetExcelName) const
Definition: addincol.cxx:140
tools::Long nArgCount
Definition: addincol.hxx:92
bool FillFunctionDesc(tools::Long nFunc, ScFuncDesc &rDesc)
Definition: addincol.cxx:1154
#define SC_CALLERPOS_NONE
Definition: addincol.cxx:65
void ExecuteCallWithArgs(css::uno::Sequence< css::uno::Any > &rCallArgs)
Definition: addincol.cxx:1378
bool GetCalcName(const OUString &rExcelName, OUString &rRetCalcName)
leave rRetCalcName unchanged, if no matching name is found
Definition: addincol.cxx:567
bool bIncomplete
Incomplete argument info (set for add-in info from configuration)
Definition: funcdesc.hxx:227
css::uno::Sequence< css::uno::Any > GetProperties(const css::uno::Sequence< OUString > &rNames)
Definition: optutil.hxx:51
css::uno::Any aObject
Definition: addincol.hxx:91
ScUnoAddInCall(ScUnoAddInCollection &rColl, const OUString &rName, tools::Long nParamCount)
Definition: addincol.cxx:1231
Stores and generates human readable descriptions for spreadsheet-functions, e.g. functions used in fo...
Definition: funcdesc.hxx:40
sal_uInt16 nArgCount
All parameter count, suppressed and unsuppressed.
Definition: funcdesc.hxx:223
void UpdateFromAddIn(const css::uno::Reference< css::uno::XInterface > &xInterface, std::u16string_view rServiceName)
Definition: addincol.cxx:943
tools::Long GetFuncCount()
Definition: addincol.cxx:1146
sal_uInt16 nPos
OUString sDisplayName