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