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, OUString 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 display names and
364 // compatibility names.
365 ScLinkConfigItem aAllLocalesConfig( CFGPATH_ADDINS, ConfigItemMode::AllLocales );
366 // CommitLink is not used (only reading values)
367
368 const OUString sSlash('/');
369
370 // get the list of add-ins (services)
371 const uno::Sequence<OUString> aServiceNames = rAddInConfig.GetNodeNames( "" );
372
373 for ( const OUString& aServiceName : aServiceNames )
374 {
375 ScUnoAddInHelpIdGenerator aHelpIdGenerator( aServiceName );
376
377 OUString aFunctionsPath(aServiceName + sSlash + CFGSTR_ADDINFUNCTIONS);
378
379 uno::Sequence<OUString> aFunctionNames = rAddInConfig.GetNodeNames( aFunctionsPath );
380 sal_Int32 nNewCount = aFunctionNames.getLength();
381
382 // allocate pointers
383
384 tools::Long nOld = nFuncCount;
385 nFuncCount = nNewCount+nOld;
386 if ( nOld )
387 {
388 std::unique_ptr<std::unique_ptr<ScUnoAddInFuncData>[]> ppNew(new std::unique_ptr<ScUnoAddInFuncData>[nFuncCount]);
389 for (tools::Long i=0; i<nOld; i++)
390 ppNew[i] = std::move(ppFuncData[i]);
391 ppFuncData = std::move(ppNew);
392 }
393 else
394 ppFuncData.reset( new std::unique_ptr<ScUnoAddInFuncData>[nFuncCount] );
395
396 //TODO: adjust bucket count?
397 if ( !pExactHashMap )
398 pExactHashMap.reset( new ScAddInHashMap );
399 if ( !pNameHashMap )
400 pNameHashMap.reset( new ScAddInHashMap );
401 if ( !pLocalHashMap )
402 pLocalHashMap.reset( new ScAddInHashMap );
403 if ( !pEnglishHashMap )
404 pEnglishHashMap.reset( new ScAddInHashMap );
405
406 //TODO: get the function information in a single call for all functions?
407
408 const OUString* pFuncNameArray = aFunctionNames.getConstArray();
409 for ( sal_Int32 nFuncPos = 0; nFuncPos < nNewCount; nFuncPos++ )
410 {
411 ppFuncData[nFuncPos+nOld] = nullptr;
412
413 // stored function name: (service name).(function)
414 OUString aFuncName = aServiceName + "." + pFuncNameArray[nFuncPos];
415
416 // skip the function if already known (read from old AddIn service)
417
418 if ( pExactHashMap->find( aFuncName ) == pExactHashMap->end() )
419 {
420 OUString aEnglishName;
421 OUString aLocalName;
422 OUString aDescription;
423 sal_uInt16 nCategory = ID_FUNCTION_GRP_ADDINS;
424
425 // get direct information on the function
426
427 OUString aFuncPropPath = aFunctionsPath + sSlash + pFuncNameArray[nFuncPos] + sSlash;
428
429 uno::Sequence<OUString> aFuncPropNames{
430 (aFuncPropPath + CFGSTR_DISPLAYNAME), // CFG_FUNCPROP_DISPLAYNAME
431 (aFuncPropPath + CFGSTR_DESCRIPTION), // CFG_FUNCPROP_DESCRIPTION
432 (aFuncPropPath + CFGSTR_CATEGORY)}; // CFG_FUNCPROP_CATEGORY
433
434 uno::Sequence<uno::Any> aFuncProperties = rAddInConfig.GetProperties( aFuncPropNames );
435 if ( aFuncProperties.getLength() == CFG_FUNCPROP_COUNT )
436 {
437 aFuncProperties[CFG_FUNCPROP_DISPLAYNAME] >>= aLocalName;
438 aFuncProperties[CFG_FUNCPROP_DESCRIPTION] >>= aDescription;
439
440 OUString aCategoryName;
441 aFuncProperties[CFG_FUNCPROP_CATEGORY] >>= aCategoryName;
442 nCategory = lcl_GetCategory( aCategoryName );
443 }
444
445 // get English display name
446
447 OUString aDisplayNamePath(aFuncPropPath + CFGSTR_DISPLAYNAME);
448 uno::Sequence<OUString> aDisplayNamePropNames( &aDisplayNamePath, 1 );
449
450 uno::Sequence<uno::Any> aDisplayNameProperties = aAllLocalesConfig.GetProperties( aDisplayNamePropNames );
451 if ( aDisplayNameProperties.getLength() == 1 )
452 {
453 uno::Sequence<beans::PropertyValue> aLocalEntries;
454 if ( aDisplayNameProperties[0] >>= aLocalEntries )
455 {
456 for ( const beans::PropertyValue& rConfig : std::as_const(aLocalEntries) )
457 {
458 // PropertyValue name is the locale ("convert" from
459 // string to canonicalize).
460 OUString aLocale( LanguageTag( rConfig.Name, true).getBcp47( false));
461 // PropertyValue value is the localized value (string in this case).
462 OUString aName;
463 rConfig.Value >>= aName;
464 // Accept 'en' and 'en-...' but prefer 'en-US'.
465 if (aLocale == "en-US" && !aName.isEmpty())
466 aEnglishName = aName;
467 else if (aEnglishName.isEmpty() && (aLocale == "en" || aLocale.startsWith("en-")))
468 aEnglishName = aName;
469 }
470 }
471 }
472 bool bNeedEnglish = aEnglishName.isEmpty();
473
474 // get compatibility names
475
476 ::std::vector<ScUnoAddInFuncData::LocalizedName> aCompNames;
477
478 OUString aCompPath(aFuncPropPath + CFGSTR_COMPATIBILITYNAME);
479 uno::Sequence<OUString> aCompPropNames( &aCompPath, 1 );
480
481 uno::Sequence<uno::Any> aCompProperties = aAllLocalesConfig.GetProperties( aCompPropNames );
482 if ( aCompProperties.getLength() == 1 )
483 {
484 uno::Sequence<beans::PropertyValue> aLocalEntries;
485 if ( aCompProperties[0] >>= aLocalEntries )
486 {
487 for ( const beans::PropertyValue& rConfig : std::as_const(aLocalEntries) )
488 {
489 // PropertyValue name is the locale ("convert" from
490 // string to canonicalize).
491 OUString aLocale( LanguageTag( rConfig.Name, true).getBcp47( false));
492 // PropertyValue value is the localized value (string in this case).
493 OUString aName;
494 rConfig.Value >>= aName;
495 if (!aName.isEmpty())
496 {
497 aCompNames.emplace_back( aLocale, aName);
498 if (bNeedEnglish)
499 {
500 // Accept 'en' and 'en-...' but prefer 'en-US'.
501 if (aLocale == "en-US")
502 aEnglishName = aName;
503 else if (aEnglishName.isEmpty() && (aLocale == "en" || aLocale.startsWith("en-")))
504 aEnglishName = aName;
505 }
506 }
507 }
508 }
509 }
510
511 // get argument info
512
513 std::unique_ptr<ScAddInArgDesc[]> pVisibleArgs;
514 tools::Long nVisibleCount = 0;
515
516 OUString aArgumentsPath(aFuncPropPath + CFGSTR_PARAMETERS);
517
518 const uno::Sequence<OUString> aArgumentNames = rAddInConfig.GetNodeNames( aArgumentsPath );
519 sal_Int32 nArgumentCount = aArgumentNames.getLength();
520 if ( nArgumentCount )
521 {
522 // get DisplayName and Description for each argument
523 uno::Sequence<OUString> aArgPropNames( nArgumentCount * 2 );
524 OUString* pPropNameArray = aArgPropNames.getArray();
525
526 sal_Int32 nIndex = 0;
527 for ( const OUString& rArgName : aArgumentNames )
528 {
529 OUString aOneArgPath = aArgumentsPath + sSlash + rArgName + sSlash;
530
531 pPropNameArray[nIndex++] = aOneArgPath
533 pPropNameArray[nIndex++] = aOneArgPath
535 }
536
537 uno::Sequence<uno::Any> aArgProperties = rAddInConfig.GetProperties( aArgPropNames );
538 if ( aArgProperties.getLength() == aArgPropNames.getLength() )
539 {
540 const OUString* pArgNameArray = aArgumentNames.getConstArray();
541 const uno::Any* pPropArray = aArgProperties.getConstArray();
542 OUString sDisplayName;
543 OUString sDescription;
544
545 ScAddInArgDesc aDesc;
546 aDesc.eType = SC_ADDINARG_NONE; // arg type is not in configuration
547 aDesc.bOptional = false;
548
549 nVisibleCount = nArgumentCount;
550 pVisibleArgs.reset(new ScAddInArgDesc[nVisibleCount]);
551
552 nIndex = 0;
553 for ( sal_Int32 nArgument = 0; nArgument < nArgumentCount; nArgument++ )
554 {
555 pPropArray[nIndex++] >>= sDisplayName;
556 pPropArray[nIndex++] >>= sDescription;
557
558 aDesc.aInternalName = pArgNameArray[nArgument];
559 aDesc.aName = sDisplayName;
560 aDesc.aDescription = sDescription;
561
562 pVisibleArgs[nArgument] = aDesc;
563 }
564 }
565 }
566
567 OUString sHelpId = aHelpIdGenerator.GetHelpId( pFuncNameArray[nFuncPos] );
568
569 uno::Reference<reflection::XIdlMethod> xFunc; // remains empty
570 uno::Any aObject; // also empty
571
572 // create and insert into the array
573
575 aFuncName, aLocalName, aDescription,
576 nCategory, sHelpId,
577 xFunc, aObject,
578 nVisibleCount, pVisibleArgs.get(), SC_CALLERPOS_NONE );
579
580 pData->SetCompNames( std::move(aCompNames) );
581
582 ppFuncData[nFuncPos+nOld].reset(pData);
583
584 pExactHashMap->emplace(
585 pData->GetOriginalName(),
586 pData );
587 pNameHashMap->emplace(
588 pData->GetUpperName(),
589 pData );
590 pLocalHashMap->emplace(
591 pData->GetUpperLocal(),
592 pData );
593
594 if (aEnglishName.isEmpty())
595 SAL_WARN("sc.core", "no English name for " << aLocalName << " " << aFuncName);
596 else
597 {
598 pEnglishHashMap->emplace(
599 ScCompiler::GetCharClassEnglish()->uppercase(aEnglishName),
600 pData );
601 }
602 pData->SetEnglishName(aEnglishName); // takes care of handling empty
603 }
604 }
605 }
606}
607
609{
610 const OUString& aFullName = rFuncData.GetOriginalName();
611 sal_Int32 nPos = aFullName.lastIndexOf( '.' );
612 if ( nPos <= 0 )
613 return;
614
615 OUString aServiceName = aFullName.copy( 0, nPos );
616
617 try
618 {
619 uno::Reference<lang::XMultiServiceFactory> xServiceFactory = comphelper::getProcessServiceFactory();
620 uno::Reference<uno::XInterface> xInterface( xServiceFactory->createInstance( aServiceName ) );
621
622 if (xInterface.is())
623 UpdateFromAddIn( xInterface, aServiceName );
624 }
625 catch (const uno::Exception &)
626 {
627 SAL_WARN ("sc", "Failed to create addin component '"
628 << aServiceName << "'");
629 }
630}
631
632bool ScUnoAddInCollection::GetExcelName( const OUString& rCalcName,
633 LanguageType eDestLang, OUString& rRetExcelName )
634{
635 const ScUnoAddInFuncData* pFuncData = GetFuncData( rCalcName );
636 if ( pFuncData )
637 return pFuncData->GetExcelName( LanguageTag( eDestLang), rRetExcelName);
638 return false;
639}
640
641bool ScUnoAddInCollection::GetCalcName( const OUString& rExcelName, OUString& rRetCalcName )
642{
643 if (!bInitialized)
644 Initialize();
645
646 OUString aUpperCmp = ScGlobal::getCharClass().uppercase(rExcelName);
647
648 for (tools::Long i=0; i<nFuncCount; i++)
649 {
650 ScUnoAddInFuncData* pFuncData = ppFuncData[i].get();
651 if ( pFuncData )
652 {
653 const ::std::vector<ScUnoAddInFuncData::LocalizedName>& rNames = pFuncData->GetCompNames();
654 auto bFound = std::any_of(rNames.begin(), rNames.end(),
655 [&aUpperCmp](const ScUnoAddInFuncData::LocalizedName& rName) {
656 return ScGlobal::getCharClass().uppercase( rName.maName ) == aUpperCmp; });
657 if (bFound)
658 {
659 //TODO: store upper case for comparing?
660
661 // use the first function that has this name for any language
662 rRetCalcName = pFuncData->GetOriginalName();
663 return true;
664 }
665 }
666 }
667 return false;
668}
669
670static bool IsTypeName( std::u16string_view rName, const uno::Type& rType )
671{
672 return rName == rType.getTypeName();
673}
674
675static bool lcl_ValidReturnType( const uno::Reference<reflection::XIdlClass>& xClass )
676{
677 // this must match with ScUnoAddInCall::SetResult
678
679 if ( !xClass.is() ) return false;
680
681 switch (xClass->getTypeClass())
682 {
683 case uno::TypeClass_ANY: // variable type
684 case uno::TypeClass_ENUM: //TODO: ???
685 case uno::TypeClass_BOOLEAN:
686 case uno::TypeClass_CHAR:
687 case uno::TypeClass_BYTE:
688 case uno::TypeClass_SHORT:
689 case uno::TypeClass_UNSIGNED_SHORT:
690 case uno::TypeClass_LONG:
691 case uno::TypeClass_UNSIGNED_LONG:
692 case uno::TypeClass_FLOAT:
693 case uno::TypeClass_DOUBLE:
694 case uno::TypeClass_STRING:
695 return true; // values or string
696
697 case uno::TypeClass_INTERFACE:
698 {
699 // return type XInterface may contain a XVolatileResult
700 //TODO: XIdlClass needs getType() method!
701
702 OUString sName = xClass->getName();
703 return (
706 }
707
708 default:
709 {
710 // nested sequences for arrays
711 //TODO: XIdlClass needs getType() method!
712
713 OUString sName = xClass->getName();
714 return (
715 IsTypeName( sName, cppu::UnoType<uno::Sequence< uno::Sequence<sal_Int32> >>::get() ) ||
716 IsTypeName( sName, cppu::UnoType<uno::Sequence< uno::Sequence<double> >>::get() ) ||
717 IsTypeName( sName, cppu::UnoType<uno::Sequence< uno::Sequence<OUString> >>::get() ) ||
718 IsTypeName( sName, cppu::UnoType<uno::Sequence< uno::Sequence<uno::Any> >>::get() ) );
719 }
720 }
721}
722
723static ScAddInArgumentType lcl_GetArgType( const uno::Reference<reflection::XIdlClass>& xClass )
724{
725 if (!xClass.is())
726 return SC_ADDINARG_NONE;
727
728 uno::TypeClass eType = xClass->getTypeClass();
729
730 if ( eType == uno::TypeClass_LONG ) //TODO: other integer types?
731 return SC_ADDINARG_INTEGER;
732
733 if ( eType == uno::TypeClass_DOUBLE )
734 return SC_ADDINARG_DOUBLE;
735
736 if ( eType == uno::TypeClass_STRING )
737 return SC_ADDINARG_STRING;
738
739 //TODO: XIdlClass needs getType() method!
740 OUString sName = xClass->getName();
741
742 if (IsTypeName( sName, cppu::UnoType<uno::Sequence< uno::Sequence<sal_Int32> >>::get() ))
744
745 if (IsTypeName( sName, cppu::UnoType<uno::Sequence< uno::Sequence<double> >>::get() ))
747
748 if (IsTypeName( sName, cppu::UnoType<uno::Sequence< uno::Sequence<OUString> >>::get() ))
750
751 if (IsTypeName( sName, cppu::UnoType<uno::Sequence< uno::Sequence<uno::Any> >>::get() ))
753
756
759
761 return SC_ADDINARG_CALLER;
762
763 if (IsTypeName( sName, cppu::UnoType<uno::Sequence<uno::Any>>::get() ))
764 return SC_ADDINARG_VARARGS;
765
766 return SC_ADDINARG_NONE;
767}
768
769void ScUnoAddInCollection::ReadFromAddIn( const uno::Reference<uno::XInterface>& xInterface )
770{
771 uno::Reference<sheet::XAddIn> xAddIn( xInterface, uno::UNO_QUERY );
772 uno::Reference<lang::XServiceName> xName( xInterface, uno::UNO_QUERY );
773 if ( !(xAddIn.is() && xName.is()) )
774 return;
775
776 // Even if GetUseEnglishFunctionName() would return true, do not set the
777 // locale to en-US to get English function names as that also would mix in
778 // English descriptions and parameter names. Also, setting a locale will
779 // reinitialize the Add-In completely, so switching back and forth isn't a
780 // good idea either.
781 xAddIn->setLocale( Application::GetSettings().GetUILanguageTag().getLocale());
782
783 // Instead, in a second run with 'en-US' obtain English names.
784 struct FuncNameData
785 {
786 OUString aFuncU;
788 };
789 std::vector<FuncNameData> aFuncNameData;
790
791 OUString aServiceName( xName->getServiceName() );
792 ScUnoAddInHelpIdGenerator aHelpIdGenerator( aServiceName );
793
794 //TODO: pass XIntrospection to ReadFromAddIn
795
796 uno::Reference<uno::XComponentContext> xContext = comphelper::getProcessComponentContext();
797
798 uno::Reference<beans::XIntrospection> xIntro = beans::theIntrospection::get( xContext );
799 uno::Any aObject;
800 aObject <<= xAddIn;
801 uno::Reference<beans::XIntrospectionAccess> xAcc = xIntro->inspect(aObject);
802 if (!xAcc.is())
803 return;
804
805 uno::Sequence< uno::Reference<reflection::XIdlMethod> > aMethods =
806 xAcc->getMethods( beans::MethodConcept::ALL );
807 tools::Long nNewCount = aMethods.getLength();
808 if ( !nNewCount )
809 return;
810
811 tools::Long nOld = nFuncCount;
812 nFuncCount = nNewCount+nOld;
813 if ( nOld )
814 {
815 std::unique_ptr<std::unique_ptr<ScUnoAddInFuncData>[]> ppNew(new std::unique_ptr<ScUnoAddInFuncData>[nFuncCount]);
816 for (tools::Long i=0; i<nOld; i++)
817 ppNew[i] = std::move(ppFuncData[i]);
818 ppFuncData = std::move(ppNew);
819 }
820 else
821 ppFuncData.reset(new std::unique_ptr<ScUnoAddInFuncData>[nFuncCount]);
822
823 //TODO: adjust bucket count?
824 if ( !pExactHashMap )
825 pExactHashMap.reset( new ScAddInHashMap );
826 if ( !pNameHashMap )
827 pNameHashMap.reset( new ScAddInHashMap );
828 if ( !pLocalHashMap )
829 pLocalHashMap.reset( new ScAddInHashMap );
830 if ( !pEnglishHashMap )
831 pEnglishHashMap.reset( new ScAddInHashMap );
832
833 const uno::Reference<reflection::XIdlMethod>* pArray = aMethods.getConstArray();
834 for (tools::Long nFuncPos=0; nFuncPos<nNewCount; nFuncPos++)
835 {
836 ppFuncData[nFuncPos+nOld] = nullptr;
837
838 uno::Reference<reflection::XIdlMethod> xFunc = pArray[nFuncPos];
839 if (xFunc.is())
840 {
841 // leave out internal functions
842 uno::Reference<reflection::XIdlClass> xClass =
843 xFunc->getDeclaringClass();
844 bool bSkip = true;
845 if ( xClass.is() )
846 {
847 //TODO: XIdlClass needs getType() method!
848 OUString sName = xClass->getName();
849 bSkip = (
858 }
859 if (!bSkip)
860 {
861 uno::Reference<reflection::XIdlClass> xReturn =
862 xFunc->getReturnType();
863 if ( !lcl_ValidReturnType( xReturn ) )
864 bSkip = true;
865 }
866 if (!bSkip)
867 {
868 OUString aFuncU = xFunc->getName();
869
870 // stored function name: (service name).(function)
871 OUString aFuncName = aServiceName + "." + aFuncU;
872
873 bool bValid = true;
874 tools::Long nVisibleCount = 0;
875 tools::Long nCallerPos = SC_CALLERPOS_NONE;
876
877 uno::Sequence<reflection::ParamInfo> aParams =
878 xFunc->getParameterInfos();
879 tools::Long nParamCount = aParams.getLength();
880 const reflection::ParamInfo* pParArr = aParams.getConstArray();
881 tools::Long nParamPos;
882 for (nParamPos=0; nParamPos<nParamCount; nParamPos++)
883 {
884 if ( pParArr[nParamPos].aMode != reflection::ParamMode_IN )
885 bValid = false;
886 uno::Reference<reflection::XIdlClass> xParClass =
887 pParArr[nParamPos].aType;
888 ScAddInArgumentType eArgType = lcl_GetArgType( xParClass );
889 if ( eArgType == SC_ADDINARG_NONE )
890 bValid = false;
891 else if ( eArgType == SC_ADDINARG_CALLER )
892 nCallerPos = nParamPos;
893 else
894 ++nVisibleCount;
895 }
896 if (bValid)
897 {
898 sal_uInt16 nCategory = lcl_GetCategory(
899 xAddIn->getProgrammaticCategoryName( aFuncU ) );
900
901 OUString sHelpId = aHelpIdGenerator.GetHelpId( aFuncU );
902
903 OUString aLocalName;
904 try
905 {
906 aLocalName = xAddIn->
907 getDisplayFunctionName( aFuncU );
908 }
909 catch(uno::Exception&)
910 {
911 aLocalName = "###";
912 }
913
914 OUString aDescription;
915 try
916 {
917 aDescription = xAddIn->
918 getFunctionDescription( aFuncU );
919 }
920 catch(uno::Exception&)
921 {
922 aDescription = "###";
923 }
924
925 std::unique_ptr<ScAddInArgDesc[]> pVisibleArgs;
926 if ( nVisibleCount > 0 )
927 {
928 ScAddInArgDesc aDesc;
929 pVisibleArgs.reset(new ScAddInArgDesc[nVisibleCount]);
930 tools::Long nDestPos = 0;
931 for (nParamPos=0; nParamPos<nParamCount; nParamPos++)
932 {
933 uno::Reference<reflection::XIdlClass> xParClass =
934 pParArr[nParamPos].aType;
935 ScAddInArgumentType eArgType = lcl_GetArgType( xParClass );
936 if ( eArgType != SC_ADDINARG_CALLER )
937 {
938 OUString aArgName;
939 try
940 {
941 aArgName = xAddIn->
942 getDisplayArgumentName( aFuncU, nParamPos );
943 }
944 catch(uno::Exception&)
945 {
946 aArgName = "###";
947 }
948 OUString aArgDesc;
949 try
950 {
951 aArgDesc = xAddIn->
952 getArgumentDescription( aFuncU, nParamPos );
953 }
954 catch(uno::Exception&)
955 {
956 aArgDesc = "###";
957 }
958
959 bool bOptional =
960 ( eArgType == SC_ADDINARG_VALUE_OR_ARRAY ||
961 eArgType == SC_ADDINARG_VARARGS );
962
963 aDesc.eType = eArgType;
964 aDesc.aName = aArgName;
965 aDesc.aDescription = aArgDesc;
966 aDesc.bOptional = bOptional;
967 //TODO: initialize aInternalName only from config?
968 aDesc.aInternalName = pParArr[nParamPos].aName;
969
970 pVisibleArgs[nDestPos++] = aDesc;
971 }
972 }
973 OSL_ENSURE( nDestPos==nVisibleCount, "wrong count" );
974 }
975
976 ppFuncData[nFuncPos+nOld].reset( new ScUnoAddInFuncData(
977 aFuncName, aLocalName, aDescription,
978 nCategory, sHelpId,
979 xFunc, aObject,
980 nVisibleCount, pVisibleArgs.get(), nCallerPos ) );
981
982 ScUnoAddInFuncData* pData = ppFuncData[nFuncPos+nOld].get();
983 pExactHashMap->emplace(
984 pData->GetOriginalName(),
985 pData );
986 pNameHashMap->emplace(
987 pData->GetUpperName(),
988 pData );
989 pLocalHashMap->emplace(
990 pData->GetUpperLocal(),
991 pData );
992
993 aFuncNameData.push_back({aFuncU, pData});
994 }
995 }
996 }
997 }
998
999 const LanguageTag aEnglishLanguageTag(LANGUAGE_ENGLISH_US);
1000 xAddIn->setLocale( aEnglishLanguageTag.getLocale());
1001 for (const auto& rFunc : aFuncNameData)
1002 {
1003 OUString aEnglishName;
1004 try
1005 {
1006 aEnglishName = xAddIn->getDisplayFunctionName( rFunc.aFuncU );
1007 }
1008 catch(uno::Exception&)
1009 {
1010 }
1011 if (aEnglishName.isEmpty()
1012 && rFunc.pData->GetExcelName( aEnglishLanguageTag, aEnglishName, false /*bFallbackToAny*/))
1013 {
1014 // Check our known suffixes and append if not present. Note this
1015 // depends on localization (that should not add such suffix, but..)
1016 // and is really only a last resort.
1017 if (rFunc.pData->GetLocalName().endsWith("_ADD") && !aEnglishName.endsWith("_ADD"))
1018 aEnglishName += "_ADD";
1019 else if (rFunc.pData->GetLocalName().endsWith("_EXCEL2003") && !aEnglishName.endsWith("_EXCEL2003"))
1020 aEnglishName += "_EXCEL2003";
1021 SAL_WARN("sc.core", "obtaining English name for " << rFunc.pData->GetLocalName() << " "
1022 << rFunc.pData->GetOriginalName() << " as ExcelName '" << aEnglishName << "'");
1023 }
1024 SAL_WARN_IF(aEnglishName.isEmpty(), "sc.core", "no English name for "
1025 << rFunc.pData->GetLocalName() << " " << rFunc.pData->GetOriginalName());
1026 rFunc.pData->SetEnglishName(aEnglishName); // takes care of handling empty
1027 pEnglishHashMap->emplace( rFunc.pData->GetUpperEnglish(), rFunc.pData);
1028 }
1029}
1030
1031static void lcl_UpdateFunctionList( const ScFunctionList& rFunctionList, const ScUnoAddInFuncData& rFuncData,
1032 bool bEnglishFunctionNames )
1033{
1034 // as used in FillFunctionDescFromData
1035 const OUString& aCompare = (bEnglishFunctionNames ? rFuncData.GetUpperEnglish() : rFuncData.GetUpperLocal());
1036
1037 sal_uLong nCount = rFunctionList.GetCount();
1038 for (sal_uLong nPos=0; nPos<nCount; nPos++)
1039 {
1040 const ScFuncDesc* pDesc = rFunctionList.GetFunction( nPos );
1041 if ( pDesc && pDesc->mxFuncName && *pDesc->mxFuncName == aCompare )
1042 {
1043 ScUnoAddInCollection::FillFunctionDescFromData( rFuncData, *const_cast<ScFuncDesc*>(pDesc),
1044 bEnglishFunctionNames);
1045 break;
1046 }
1047 }
1048}
1049
1050static const ScAddInArgDesc* lcl_FindArgDesc( const ScUnoAddInFuncData& rFuncData, std::u16string_view rArgIntName )
1051{
1052 tools::Long nArgCount = rFuncData.GetArgumentCount();
1053 const ScAddInArgDesc* pArguments = rFuncData.GetArguments();
1054 for (tools::Long nPos=0; nPos<nArgCount; nPos++)
1055 {
1056 if ( pArguments[nPos].aInternalName == rArgIntName )
1057 return &pArguments[nPos];
1058 }
1059 return nullptr;
1060}
1061
1062void ScUnoAddInCollection::UpdateFromAddIn( const uno::Reference<uno::XInterface>& xInterface,
1063 std::u16string_view rServiceName )
1064{
1065 const bool bEnglishFunctionNames = SC_MOD()->GetFormulaOptions().GetUseEnglishFuncName();
1066 uno::Reference<lang::XLocalizable> xLoc( xInterface, uno::UNO_QUERY );
1067 if ( xLoc.is() ) // optional in new add-ins
1068 xLoc->setLocale( Application::GetSettings().GetUILanguageTag().getLocale());
1069
1070 // if function list was already initialized, it must be updated
1071
1072 ScFunctionList* pFunctionList = nullptr;
1074 pFunctionList = ScGlobal::GetStarCalcFunctionList();
1075
1076 // only get the function information from Introspection
1077
1078 uno::Reference<uno::XComponentContext> xContext = comphelper::getProcessComponentContext();
1079
1080 uno::Reference<beans::XIntrospection> xIntro = beans::theIntrospection::get(xContext);
1081 uno::Any aObject;
1082 aObject <<= xInterface;
1083 uno::Reference<beans::XIntrospectionAccess> xAcc = xIntro->inspect(aObject);
1084 if (!xAcc.is())
1085 return;
1086
1087 const uno::Sequence< uno::Reference<reflection::XIdlMethod> > aMethods =
1088 xAcc->getMethods( beans::MethodConcept::ALL );
1089 for (const uno::Reference<reflection::XIdlMethod>& xFunc : aMethods)
1090 {
1091 if (xFunc.is())
1092 {
1093 OUString aFuncU = xFunc->getName();
1094
1095 // stored function name: (service name).(function)
1096 OUString aFuncName = OUString::Concat(rServiceName) + "." + aFuncU;
1097
1098 // internal names are skipped because no FuncData exists
1099 ScUnoAddInFuncData* pOldData = const_cast<ScUnoAddInFuncData*>( GetFuncData( aFuncName ) );
1100 if ( pOldData )
1101 {
1102 // Create new (complete) argument info.
1103 // As in ReadFromAddIn, the reflection information is authoritative.
1104 // Local names and descriptions from pOldData are looked up using the
1105 // internal argument name.
1106
1107 bool bValid = true;
1108 tools::Long nVisibleCount = 0;
1109 tools::Long nCallerPos = SC_CALLERPOS_NONE;
1110
1111 const uno::Sequence<reflection::ParamInfo> aParams =
1112 xFunc->getParameterInfos();
1113 tools::Long nParamCount = aParams.getLength();
1114 const reflection::ParamInfo* pParArr = aParams.getConstArray();
1115 for (tools::Long nParamPos=0; nParamPos<nParamCount; nParamPos++)
1116 {
1117 if ( pParArr[nParamPos].aMode != reflection::ParamMode_IN )
1118 bValid = false;
1119 uno::Reference<reflection::XIdlClass> xParClass =
1120 pParArr[nParamPos].aType;
1121 ScAddInArgumentType eArgType = lcl_GetArgType( xParClass );
1122 if ( eArgType == SC_ADDINARG_NONE )
1123 bValid = false;
1124 else if ( eArgType == SC_ADDINARG_CALLER )
1125 nCallerPos = nParamPos;
1126 else
1127 ++nVisibleCount;
1128 }
1129 if (bValid)
1130 {
1131 std::unique_ptr<ScAddInArgDesc[]> pVisibleArgs;
1132 if ( nVisibleCount > 0 )
1133 {
1134 ScAddInArgDesc aDesc;
1135 pVisibleArgs.reset(new ScAddInArgDesc[nVisibleCount]);
1136 tools::Long nDestPos = 0;
1137 for (const auto& rParam : aParams)
1138 {
1139 uno::Reference<reflection::XIdlClass> xParClass =
1140 rParam.aType;
1141 ScAddInArgumentType eArgType = lcl_GetArgType( xParClass );
1142 if ( eArgType != SC_ADDINARG_CALLER )
1143 {
1144 const ScAddInArgDesc* pOldArgDesc =
1145 lcl_FindArgDesc( *pOldData, rParam.aName );
1146 if ( pOldArgDesc )
1147 {
1148 aDesc.aName = pOldArgDesc->aName;
1149 aDesc.aDescription = pOldArgDesc->aDescription;
1150 }
1151 else
1152 aDesc.aName = aDesc.aDescription = "###";
1153
1154 bool bOptional =
1155 ( eArgType == SC_ADDINARG_VALUE_OR_ARRAY ||
1156 eArgType == SC_ADDINARG_VARARGS );
1157
1158 aDesc.eType = eArgType;
1159 aDesc.bOptional = bOptional;
1160 //TODO: initialize aInternalName only from config?
1161 aDesc.aInternalName = rParam.aName;
1162
1163 pVisibleArgs[nDestPos++] = aDesc;
1164 }
1165 }
1166 OSL_ENSURE( nDestPos==nVisibleCount, "wrong count" );
1167 }
1168
1169 pOldData->SetFunction( xFunc, aObject );
1170 pOldData->SetArguments( nVisibleCount, pVisibleArgs.get() );
1171 pOldData->SetCallerPos( nCallerPos );
1172
1173 if ( pFunctionList )
1174 lcl_UpdateFunctionList( *pFunctionList, *pOldData, bEnglishFunctionNames );
1175 }
1176 }
1177 }
1178 }
1179}
1180
1181OUString ScUnoAddInCollection::FindFunction( const OUString& rUpperName, bool bLocalFirst )
1182{
1183 if (!bInitialized)
1184 Initialize();
1185
1186 if (nFuncCount == 0)
1187 return OUString();
1188
1189 if ( bLocalFirst )
1190 {
1191 // Only scan local names (used for entering formulas).
1192
1193 ScAddInHashMap::const_iterator iLook( pLocalHashMap->find( rUpperName ) );
1194 if ( iLook != pLocalHashMap->end() )
1195 return iLook->second->GetOriginalName();
1196 }
1197 else
1198 {
1199 // First scan international programmatic names (used when calling a
1200 // function).
1201
1202 ScAddInHashMap::const_iterator iLook( pNameHashMap->find( rUpperName ) );
1203 if ( iLook != pNameHashMap->end() )
1204 return iLook->second->GetOriginalName();
1205
1206 // Then scan English names (as FunctionAccess API could expect).
1207
1208 iLook = pEnglishHashMap->find( rUpperName );
1209 if ( iLook != pEnglishHashMap->end() )
1210 return iLook->second->GetOriginalName();
1211
1212 // After that, scan all local names; either to allow replacing old
1213 // AddIns with Uno, or for functions where the AddIn did not provide an
1214 // English name.
1215
1216 iLook = pLocalHashMap->find( rUpperName );
1217 if ( iLook != pLocalHashMap->end() )
1218 return iLook->second->GetOriginalName();
1219 }
1220
1221 return OUString();
1222}
1223
1224const ScUnoAddInFuncData* ScUnoAddInCollection::GetFuncData( const OUString& rName, bool bComplete )
1225{
1226 if (!bInitialized)
1227 Initialize();
1228
1229 // rName must be the exact internal name
1230
1231 ScAddInHashMap::const_iterator iLook( pExactHashMap->find( rName ) );
1232 if ( iLook != pExactHashMap->end() )
1233 {
1234 const ScUnoAddInFuncData* pFuncData = iLook->second;
1235
1236 if ( bComplete && !pFuncData->GetFunction().is() ) //TODO: extra flag?
1237 LoadComponent( *pFuncData );
1238
1239 return pFuncData;
1240 }
1241
1242 return nullptr;
1243}
1244
1246{
1247 if (!bInitialized)
1248 Initialize();
1249
1250 if (nIndex < nFuncCount)
1251 return ppFuncData[nIndex].get();
1252 return nullptr;
1253}
1254
1256{
1257 if (!bInitialized)
1258 Initialize();
1259
1260 // modify rName - input: exact name
1261
1262 ScAddInHashMap::const_iterator iLook( pExactHashMap->find( rName ) );
1263 if ( iLook != pExactHashMap->end() )
1264 rName = iLook->second->GetUpperLocal(); //TODO: upper?
1265}
1266
1268{
1269 if (!bInitialized)
1270 Initialize();
1271
1272 return nFuncCount;
1273}
1274
1275bool ScUnoAddInCollection::FillFunctionDesc( tools::Long nFunc, ScFuncDesc& rDesc, bool bEnglishFunctionNames )
1276{
1277 if (!bInitialized)
1278 Initialize();
1279
1280 if (nFunc >= nFuncCount || !ppFuncData[nFunc])
1281 return false;
1282
1283 const ScUnoAddInFuncData& rFuncData = *ppFuncData[nFunc];
1284
1285 return FillFunctionDescFromData( rFuncData, rDesc, bEnglishFunctionNames );
1286}
1287
1289 bool bEnglishFunctionNames )
1290{
1291 rDesc.Clear();
1292
1293 bool bIncomplete = !rFuncData.GetFunction().is(); //TODO: extra flag?
1294
1295 tools::Long nArgCount = rFuncData.GetArgumentCount();
1296 if ( nArgCount > SAL_MAX_UINT16 )
1297 return false;
1298
1299 if ( bIncomplete )
1300 nArgCount = 0; // if incomplete, fill without argument info (no wrong order)
1301
1302 // nFIndex is set from outside
1303
1304 rDesc.mxFuncName = (bEnglishFunctionNames ? rFuncData.GetUpperEnglish() : rFuncData.GetUpperLocal());
1305 rDesc.nCategory = rFuncData.GetCategory();
1306 rDesc.sHelpId = rFuncData.GetHelpId();
1307
1308 OUString aDesc = rFuncData.GetDescription();
1309 if (aDesc.isEmpty())
1310 aDesc = rFuncData.GetLocalName(); // use name if no description is available
1311 rDesc.mxFuncDesc = aDesc ;
1312
1313 // AddInArgumentType_CALLER is already left out in FuncData
1314
1315 rDesc.nArgCount = static_cast<sal_uInt16>(nArgCount);
1316 if ( nArgCount )
1317 {
1318 bool bMultiple = false;
1319 const ScAddInArgDesc* pArgs = rFuncData.GetArguments();
1320
1321 rDesc.maDefArgNames.clear();
1322 rDesc.maDefArgNames.resize(nArgCount);
1323 rDesc.maDefArgDescs.clear();
1324 rDesc.maDefArgDescs.resize(nArgCount);
1325 rDesc.pDefArgFlags = new ScFuncDesc::ParameterFlags[nArgCount];
1326 for ( tools::Long nArg=0; nArg<nArgCount; nArg++ )
1327 {
1328 rDesc.maDefArgNames[nArg] = pArgs[nArg].aName;
1329 rDesc.maDefArgDescs[nArg] = pArgs[nArg].aDescription;
1330 rDesc.pDefArgFlags[nArg].bOptional = pArgs[nArg].bOptional;
1331
1332 // no empty names...
1333 if ( rDesc.maDefArgNames[nArg].isEmpty() )
1334 {
1335 OUString aDefName = "arg" + OUString::number( nArg+1 );
1336 rDesc.maDefArgNames[nArg] = aDefName;
1337 }
1338
1339 // last argument repeated?
1340 if ( nArg+1 == nArgCount && ( pArgs[nArg].eType == SC_ADDINARG_VARARGS ) )
1341 bMultiple = true;
1342 }
1343
1344 if ( bMultiple )
1345 rDesc.nArgCount += VAR_ARGS - 1; // VAR_ARGS means just one repeated arg
1346 }
1347
1348 rDesc.bIncomplete = bIncomplete;
1349
1350 return true;
1351}
1352
1354 tools::Long nParamCount ) :
1355 mrDoc( rDoc ),
1356 bValidCount( false ),
1357 nErrCode( FormulaError::NoCode ), // before function was called
1358 bHasString( true ),
1359 fValue( 0.0 ),
1360 xMatrix( nullptr )
1361{
1362 pFuncData = rColl.GetFuncData( rName, true ); // need fully initialized data
1363 OSL_ENSURE( pFuncData, "Function Data missing" );
1364 if ( !pFuncData )
1365 return;
1366
1367 tools::Long nDescCount = pFuncData->GetArgumentCount();
1368 const ScAddInArgDesc* pArgs = pFuncData->GetArguments();
1369
1370 // is aVarArg sequence needed?
1371 if ( nParamCount >= nDescCount && nDescCount > 0 &&
1372 pArgs[nDescCount-1].eType == SC_ADDINARG_VARARGS )
1373 {
1374 tools::Long nVarCount = nParamCount - ( nDescCount - 1 ); // size of last argument
1375 aVarArg.realloc( nVarCount );
1376 bValidCount = true;
1377 }
1378 else if ( nParamCount <= nDescCount )
1379 {
1380 // all args behind nParamCount must be optional
1381 bValidCount = true;
1382 for (tools::Long i=nParamCount; i<nDescCount; i++)
1383 if ( !pArgs[i].bOptional )
1384 bValidCount = false;
1385 }
1386 // else invalid (too many arguments)
1387
1388 if ( bValidCount )
1389 aArgs.realloc( nDescCount ); // sequence must always match function signature
1390}
1391
1393{
1394 // pFuncData is deleted with ScUnoAddInCollection
1395}
1396
1398{
1399 if ( pFuncData )
1400 {
1402 const ScAddInArgDesc* pArgs = pFuncData->GetArguments();
1403
1404 // if last arg is sequence, use "any" type
1405 if ( nCount > 0 && nPos >= nCount-1 && pArgs[nCount-1].eType == SC_ADDINARG_VARARGS )
1407
1408 if ( nPos < nCount )
1409 return pArgs[nPos].eType;
1410 }
1411 return SC_ADDINARG_VALUE_OR_ARRAY; //TODO: error code !!!!
1412}
1413
1415{
1417}
1418
1419void ScUnoAddInCall::SetCaller( const uno::Reference<uno::XInterface>& rInterface )
1420{
1421 xCaller = rInterface;
1422}
1423
1425{
1426 if (pObjSh)
1427 {
1428 uno::Reference<uno::XInterface> xInt( pObjSh->GetBaseModel(), uno::UNO_QUERY );
1429 SetCaller( xInt );
1430 }
1431}
1432
1434{
1435 if ( !pFuncData )
1436 return;
1437
1439 const ScAddInArgDesc* pArgs = pFuncData->GetArguments();
1440 if ( nCount > 0 && nPos >= nCount-1 && pArgs[nCount-1].eType == SC_ADDINARG_VARARGS )
1441 {
1442 tools::Long nVarPos = nPos-(nCount-1);
1443 if ( nVarPos < aVarArg.getLength() )
1444 aVarArg.getArray()[nVarPos] = rValue;
1445 else
1446 {
1447 OSL_FAIL("wrong argument number");
1448 }
1449 }
1450 else if ( nPos < aArgs.getLength() )
1451 aArgs.getArray()[nPos] = rValue;
1452 else
1453 {
1454 OSL_FAIL("wrong argument number");
1455 }
1456}
1457
1459{
1460 if ( !pFuncData )
1461 return;
1462
1464 const ScAddInArgDesc* pArgs = pFuncData->GetArguments();
1465 if ( nCount > 0 && pArgs[nCount-1].eType == SC_ADDINARG_VARARGS )
1466 {
1467 // insert aVarArg as last argument
1468 //TODO: after inserting caller (to prevent copying twice)?
1469
1470 OSL_ENSURE( aArgs.getLength() == nCount, "wrong argument count" );
1471 aArgs.getArray()[nCount-1] <<= aVarArg;
1472 }
1473
1475 {
1476 uno::Any aCallerAny;
1477 aCallerAny <<= xCaller;
1478
1479 tools::Long nUserLen = aArgs.getLength();
1480 tools::Long nCallPos = pFuncData->GetCallerPos();
1481 if (nCallPos>nUserLen) // should not happen
1482 {
1483 OSL_FAIL("wrong CallPos");
1484 nCallPos = nUserLen;
1485 }
1486
1487 tools::Long nDestLen = nUserLen + 1;
1488 uno::Sequence<uno::Any> aRealArgs( nDestLen );
1489 uno::Any* pDest = aRealArgs.getArray();
1490
1491 pDest = std::copy_n(std::cbegin(aArgs), nCallPos, pDest);
1492 *pDest = aCallerAny;
1493 std::copy(std::next(std::cbegin(aArgs), nCallPos), std::cend(aArgs), std::next(pDest));
1494
1495 ExecuteCallWithArgs( aRealArgs );
1496 }
1497 else
1499}
1500
1501void ScUnoAddInCall::ExecuteCallWithArgs(uno::Sequence<uno::Any>& rCallArgs)
1502{
1503 // rCallArgs may not match argument descriptions (because of caller)
1504
1505 uno::Reference<reflection::XIdlMethod> xFunction;
1506 uno::Any aObject;
1507 if ( pFuncData )
1508 {
1509 xFunction = pFuncData->GetFunction();
1510 aObject = pFuncData->GetObject();
1511 }
1512
1513 if ( !xFunction.is() )
1514 return;
1515
1516 uno::Any aAny;
1517 nErrCode = FormulaError::NONE;
1518
1519 try
1520 {
1521 aAny = xFunction->invoke( aObject, rCallArgs );
1522 }
1523 catch(lang::IllegalArgumentException&)
1524 {
1525 nErrCode = FormulaError::IllegalArgument;
1526 }
1527 catch(const reflection::InvocationTargetException& rWrapped)
1528 {
1529 if ( rWrapped.TargetException.getValueType().equals(
1531 nErrCode = FormulaError::IllegalArgument;
1532 else if ( rWrapped.TargetException.getValueType().equals(
1534 nErrCode = FormulaError::NoConvergence;
1535 else
1536 nErrCode = FormulaError::NoValue;
1537 }
1538 catch(uno::Exception&)
1539 {
1540 nErrCode = FormulaError::NoValue;
1541 }
1542
1543 if (nErrCode == FormulaError::NONE)
1544 SetResult( aAny ); // convert result to Calc types
1545}
1546
1547template <typename T>
1548static sal_Int32 lcl_GetMaxColCount(const uno::Sequence< uno::Sequence<T> >* pRowSeq)
1549{
1550 if (!pRowSeq->hasElements())
1551 return 0;
1552
1553 auto pRow = std::max_element(pRowSeq->begin(), pRowSeq->end(),
1554 [](const uno::Sequence<T>& a, const uno::Sequence<T>& b) {
1555 return a.getLength() < b.getLength(); });
1556 return pRow->getLength();
1557}
1558
1560{
1561 nErrCode = FormulaError::NONE;
1562 xVarRes = nullptr;
1563
1564 // Reflection* pRefl = rNewRes.getReflection();
1565
1566 uno::TypeClass eClass = rNewRes.getValueTypeClass();
1567 const uno::Type& aType = rNewRes.getValueType();
1568 switch (eClass)
1569 {
1570 case uno::TypeClass_VOID:
1571 nErrCode = FormulaError::NotAvailable; // #NA
1572 break;
1573
1574 case uno::TypeClass_ENUM:
1575 case uno::TypeClass_BOOLEAN:
1576 case uno::TypeClass_CHAR:
1577 case uno::TypeClass_BYTE:
1578 case uno::TypeClass_SHORT:
1579 case uno::TypeClass_UNSIGNED_SHORT:
1580 case uno::TypeClass_LONG:
1581 case uno::TypeClass_UNSIGNED_LONG:
1582 case uno::TypeClass_FLOAT:
1583 case uno::TypeClass_DOUBLE:
1584 {
1585 uno::TypeClass eMyClass;
1587 bHasString = false;
1588 }
1589 break;
1590
1591 case uno::TypeClass_STRING:
1592 {
1593 rNewRes >>= aString;
1594 bHasString = true;
1595 }
1596 break;
1597
1598 case uno::TypeClass_INTERFACE:
1599 {
1600 //TODO: directly extract XVolatileResult from any?
1601 uno::Reference<uno::XInterface> xInterface;
1602 rNewRes >>= xInterface;
1603 if ( xInterface.is() )
1604 xVarRes.set( xInterface, uno::UNO_QUERY );
1605
1606 if (!xVarRes.is())
1607 nErrCode = FormulaError::NoValue; // unknown interface
1608 }
1609 break;
1610
1611 default:
1612 if ( aType.equals( cppu::UnoType<uno::Sequence< uno::Sequence<sal_Int32> >>::get() ) )
1613 {
1614 const uno::Sequence< uno::Sequence<sal_Int32> >* pRowSeq = nullptr;
1615
1616 //TODO: use pointer from any!
1617 uno::Sequence< uno::Sequence<sal_Int32> > aSequence;
1618 if ( rNewRes >>= aSequence )
1619 pRowSeq = &aSequence;
1620
1621 if ( pRowSeq )
1622 {
1623 sal_Int32 nRowCount = pRowSeq->getLength();
1624 sal_Int32 nMaxColCount = lcl_GetMaxColCount(pRowSeq);
1625 if ( nMaxColCount && nRowCount )
1626 {
1627 const uno::Sequence<sal_Int32>* pRowArr = pRowSeq->getConstArray();
1628 xMatrix = new ScMatrix(
1629 static_cast<SCSIZE>(nMaxColCount),
1630 static_cast<SCSIZE>(nRowCount), 0.0);
1631 for (sal_Int32 nRow=0; nRow<nRowCount; nRow++)
1632 {
1633 sal_Int32 nColCount = pRowArr[nRow].getLength();
1634 const sal_Int32* pColArr = pRowArr[nRow].getConstArray();
1635 for (sal_Int32 nCol=0; nCol<nColCount; nCol++)
1636 xMatrix->PutDouble( pColArr[nCol],
1637 static_cast<SCSIZE>(nCol),
1638 static_cast<SCSIZE>(nRow) );
1639 for (sal_Int32 nCol=nColCount; nCol<nMaxColCount; nCol++)
1640 xMatrix->PutDouble( 0.0,
1641 static_cast<SCSIZE>(nCol),
1642 static_cast<SCSIZE>(nRow) );
1643 }
1644 }
1645 }
1646 }
1647 else if ( aType.equals( cppu::UnoType<uno::Sequence< uno::Sequence<double> >>::get() ) )
1648 {
1649 const uno::Sequence< uno::Sequence<double> >* pRowSeq = nullptr;
1650
1651 //TODO: use pointer from any!
1652 uno::Sequence< uno::Sequence<double> > aSequence;
1653 if ( rNewRes >>= aSequence )
1654 pRowSeq = &aSequence;
1655
1656 if ( pRowSeq )
1657 {
1658 sal_Int32 nRowCount = pRowSeq->getLength();
1659 sal_Int32 nMaxColCount = lcl_GetMaxColCount(pRowSeq);
1660 if ( nMaxColCount && nRowCount )
1661 {
1662 const uno::Sequence<double>* pRowArr = pRowSeq->getConstArray();
1663 xMatrix = new ScMatrix(
1664 static_cast<SCSIZE>(nMaxColCount),
1665 static_cast<SCSIZE>(nRowCount), 0.0);
1666 for (sal_Int32 nRow=0; nRow<nRowCount; nRow++)
1667 {
1668 sal_Int32 nColCount = pRowArr[nRow].getLength();
1669 const double* pColArr = pRowArr[nRow].getConstArray();
1670 for (sal_Int32 nCol=0; nCol<nColCount; nCol++)
1671 xMatrix->PutDouble( pColArr[nCol],
1672 static_cast<SCSIZE>(nCol),
1673 static_cast<SCSIZE>(nRow) );
1674 for (sal_Int32 nCol=nColCount; nCol<nMaxColCount; nCol++)
1675 xMatrix->PutDouble( 0.0,
1676 static_cast<SCSIZE>(nCol),
1677 static_cast<SCSIZE>(nRow) );
1678 }
1679 }
1680 }
1681 }
1682 else if ( aType.equals( cppu::UnoType<uno::Sequence< uno::Sequence<OUString> >>::get() ) )
1683 {
1684 const uno::Sequence< uno::Sequence<OUString> >* pRowSeq = nullptr;
1685
1686 //TODO: use pointer from any!
1687 uno::Sequence< uno::Sequence<OUString> > aSequence;
1688 if ( rNewRes >>= aSequence )
1689 pRowSeq = &aSequence;
1690
1691 if ( pRowSeq )
1692 {
1693 sal_Int32 nRowCount = pRowSeq->getLength();
1694 sal_Int32 nMaxColCount = lcl_GetMaxColCount(pRowSeq);
1695 if ( nMaxColCount && nRowCount )
1696 {
1697 const uno::Sequence<OUString>* pRowArr = pRowSeq->getConstArray();
1698 xMatrix = new ScMatrix(
1699 static_cast<SCSIZE>(nMaxColCount),
1700 static_cast<SCSIZE>(nRowCount), 0.0);
1701 for (sal_Int32 nRow=0; nRow<nRowCount; nRow++)
1702 {
1703 sal_Int32 nColCount = pRowArr[nRow].getLength();
1704 const OUString* pColArr = pRowArr[nRow].getConstArray();
1705 for (sal_Int32 nCol=0; nCol<nColCount; nCol++)
1706 {
1707 xMatrix->PutString(
1708 mrDoc.GetSharedStringPool().intern(pColArr[nCol]),
1709 static_cast<SCSIZE>(nCol), static_cast<SCSIZE>(nRow));
1710 }
1711 for (sal_Int32 nCol=nColCount; nCol<nMaxColCount; nCol++)
1712 {
1713 xMatrix->PutString(
1715 static_cast<SCSIZE>(nCol), static_cast<SCSIZE>(nRow));
1716 }
1717 }
1718 }
1719 }
1720 }
1721 else if ( aType.equals( cppu::UnoType<uno::Sequence< uno::Sequence<uno::Any> >>::get() ) )
1722 {
1724 }
1725
1726 if (!xMatrix) // no array found
1727 nErrCode = FormulaError::NoValue; //TODO: code for error in return type???
1728 }
1729}
1730
1731/* 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:1548
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:1031
static bool IsTypeName(std::u16string_view rName, const uno::Type &rType)
Definition: addincol.cxx:670
#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:723
static bool lcl_ValidReturnType(const uno::Reference< reflection::XIdlClass > &xClass)
Definition: addincol.cxx:675
#define CFG_FUNCPROP_DESCRIPTION
Definition: addincol.cxx:346
static const ScAddInArgDesc * lcl_FindArgDesc(const ScUnoAddInFuncData &rFuncData, std::u16string_view rArgIntName)
Definition: addincol.cxx:1050
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:328
static const CharClass * GetCharClassEnglish()
Definition: compiler.cxx:230
SC_DLLPUBLIC svl::SharedStringPool & GetSharedStringPool()
Definition: documen2.cxx:601
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
OUString sHelpId
HelpId of function.
Definition: funcdesc.hxx:226
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
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:993
sal_uInt32 GetCount() const
Definition: funcdesc.hxx:247
static ScFunctionList * GetStarCalcFunctionList()
Definition: global.cxx:626
static bool HasStarCalcFunctionList()
Definition: global.cxx:621
static SC_DLLPUBLIC const CharClass & getCharClass()
Definition: global.cxx:1064
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:358
ScUnoAddInCall(ScDocument &rDoc, ScUnoAddInCollection &rColl, const OUString &rName, tools::Long nParamCount)
Definition: addincol.cxx:1353
ScMatrixRef xMatrix
Definition: addincol.hxx:209
void SetResult(const css::uno::Any &rNewRes)
Definition: addincol.cxx:1559
ScAddInArgumentType GetArgType(tools::Long nPos)
Definition: addincol.cxx:1397
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:1414
void ExecuteCall()
Definition: addincol.cxx:1458
void SetCaller(const css::uno::Reference< css::uno::XInterface > &rInterface)
Definition: addincol.cxx:1419
void ExecuteCallWithArgs(css::uno::Sequence< css::uno::Any > &rCallArgs)
Definition: addincol.cxx:1501
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:1433
css::uno::Reference< css::uno::XInterface > xCaller
Definition: addincol.hxx:201
void SetCallerFromObjectShell(const SfxObjectShell *pSh)
Definition: addincol.cxx:1424
std::unique_ptr< ScAddInHashMap > pLocalHashMap
localized name upper
Definition: addincol.hxx:151
void LocalizeString(OUString &rName)
modify rName - input: exact name
Definition: addincol.cxx:1255
bool FillFunctionDesc(tools::Long nFunc, ScFuncDesc &rDesc, bool bEnglishFunctionNames)
Definition: addincol.cxx:1275
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:1224
void ReadFromAddIn(const css::uno::Reference< css::uno::XInterface > &xInterface)
Definition: addincol.cxx:769
void UpdateFromAddIn(const css::uno::Reference< css::uno::XInterface > &xInterface, std::u16string_view rServiceName)
Definition: addincol.cxx:1062
static bool FillFunctionDescFromData(const ScUnoAddInFuncData &rFuncData, ScFuncDesc &rDesc, bool bEnglishFunctionNames)
Definition: addincol.cxx:1288
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:641
void LoadComponent(const ScUnoAddInFuncData &rFuncData)
Definition: addincol.cxx:608
tools::Long GetFuncCount()
Definition: addincol.cxx:1267
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:632
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:1181
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
const OUString & GetHelpId() const
Definition: addincol.hxx:128
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
ScUnoAddInFuncData(const OUString &rNam, const OUString &rLoc, OUString aDesc, sal_uInt16 nCat, OUString, 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 OUString & GetUpperLocal() const
Definition: addincol.hxx:118
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
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
OUString GetHelpId(std::u16string_view 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
OUString sName
#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 LanguageTag & getLocale()
Reference< XMultiServiceFactory > getProcessServiceFactory()
Reference< XComponentContext > getProcessComponentContext()
Reference< XComponentContext > getComponentContext(Reference< XMultiServiceFactory > const &factory)
int i
bool equalsAscii(std::u16string_view s1, std::string_view s2)
long Long
#define ID_FUNCTION_GRP_ADDINS
Definition: scfuncs.hxx:31
#define SC_MOD()
Definition: scmod.hxx:247
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