AsyncReturnHandler of 1.9.0 not working

29 views
Skip to first unread message

Snake David

unread,
Dec 9, 2025, 1:23:17 AM (6 days ago) Dec 9
to Excel-DNA
Hello,Govert.

I'm sorry for bothering you,but i had a issue when I update my addsin to version 1.9.0.

I tried the sample of AsyncReturnHandler.cs on your github and  found there's no tranditional codes like this:

static ParameterConversionConfiguration GetPostAsyncReturnConversionConfig()
{

     var rval = ExcelError.ExcelErrorGettingData;
    return new ParameterConversionConfiguration()
        .AddReturnConversion((type, customAttributes) => type != typeof(object) ? null : (Expression<Func<object, object>>)
                                        ((returnValue) => returnValue.Equals(ExcelError.ExcelErrorNA) ? rval : returnValue));

}

public void AutoOpen()
{
      var postAsyncReturnConfig = GetPostAsyncReturnConversionConfig();
    ExcelRegistration.GetExcelFunctions()
        .ProcessAsyncRegistrations(nativeAsyncIfAvailable: false)
        .ProcessParameterConversions(postAsyncReturnConfig)
        .ProcessParamsRegistrations()
        .RegisterFunctions();
  }

However,without the codes above,the default return information during calculation will be "#N/A" ,and if I use the tranditional async  return value codes,the new function of optional  parameter value won't be working,instead it performs like previous version which the parameter will retain the default initial value for variables of this type.

is there any mistake I made?Hope to receive you response.

Thank you so much

Govert van Drimmelen

unread,
Dec 9, 2025, 4:09:37 PM (6 days ago) Dec 9
to exce...@googlegroups.com

With v1.9.0 we have some simpler ways of configuring the ‘extended registration’ used if you want to customize your functions.

 

Here is an example that defines an `ExcelAsyncDefault` attribute that you can use on function, and then a `FunctionExecutionHandler` that can customize the function return value, including a selector to decide when to apply the ExecutionHandler.

 

If you wanted to apply a pre-determined default return value to all your function, you would change the selector to do so.

 

-Govert

 

 

using ExcelDna.Integration;

using ExcelDna.Registration;

 

namespace TestTaskReturnOverride

{

    public static class MyFunctions

    {

        [ExcelFunction(Description = "My first .NET function")]

        public static string SayHello(string name)

        {

            return "Hello " + name;

        }

 

        [ExcelFunction]

        [return: ExcelAsyncDefault("<WAIT>")]

        public static async Task<string> SayHelloAsync(string name, string more = "More", int delayMs = 1000)

        {

            // Simulate an asynchronous operation

            await Task.Delay(delayMs);

            return "Hello (async) " + name + " " + more;

        }

 

        [ExcelFunction]

        [return: ExcelAsyncDefault()]   // Will use ExcelErrorGettingData as busy return value

        public static async Task<string> SleepAWhile(int delayMs = 1000)

        {

            // Simulate an asynchronous operation

            await Task.Delay(delayMs);

            return "Done sleeping";

        }

 

    }

 

    [AttributeUsage(AttributeTargets.ReturnValue, AllowMultiple = false)]

    public class ExcelAsyncDefaultAttribute : Attribute

    {

        internal object DefaultReturnValue;

 

        // This attribute can be used to mark functions that should return a default value when the result is not available

        // It can be applied to methods that return Task<T> or IObservable<T>

        public ExcelAsyncDefaultAttribute()

        {

            DefaultReturnValue = ExcelError.ExcelErrorGettingData;

        }

 

        public ExcelAsyncDefaultAttribute(object defaultReturnValue)

        {

            DefaultReturnValue = defaultReturnValue;

        }

    }

 

    internal class AsyncReturnHandler : FunctionExecutionHandler

    {

        object _defaultValue;

        public AsyncReturnHandler(object defaultValue)

        {

            _defaultValue = defaultValue;

        }

 

        public override void OnSuccess(FunctionExecutionArgs args)

        {

            if (args.ReturnValue.Equals(ExcelError.ExcelErrorNA))

                args.ReturnValue = _defaultValue;

        }

 

        // This method can be inside any class

        // It is called for every function to optionally return an additional handler for that function

        [ExcelFunctionExecutionHandlerSelector]

        public static IFunctionExecutionHandler AsyncReturnHandlerSelector(IExcelFunctionInfo functionInfo)

        {

            // We need to decide whether to apply a FunctionExecutionHandler to this particular function.

            // For this example, we only accept functions that are marked with

            // [return: ExcelAsyncDefault(...)]

 

            var defaultAtt = (ExcelAsyncDefaultAttribute)functionInfo.Return.CustomAttributes.FirstOrDefault(ca => ca is ExcelAsyncDefaultAttribute);

            if (defaultAtt == null)

            {

                // No attribute to indicate we want the default overridden

                // So no ExecutionHandler to add to the function

                return null;

            }

 

            return new AsyncReturnHandler(defaultAtt.DefaultReturnValue);

--
You received this message because you are subscribed to the Google Groups "Excel-DNA" group.
To unsubscribe from this group and stop receiving emails from it, send an email to exceldna+u...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/exceldna/8f72287b-4e61-433d-b67c-12759ec8b3f3n%40googlegroups.com.

Snake David

unread,
Dec 10, 2025, 1:30:51 AM (5 days ago) Dec 10
to Excel-DNA

It worked! Thanks for your help.

and I want to know is the sample codes in github obsoleted or something?
Reply all
Reply to author
Forward
0 new messages