2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Excel-DNAで非同期処理の関数をつくる

Posted at

今回はExcel-DNAで非同期処理をつくってみます。
Excel-DNAの使い方は以下。

非同期処理を追加する

必要ファイルの追加

このファイルをそのまま使います。

AsyncTaskUtil.cs
using System;
using System.Threading;
using System.Threading.Tasks;
using ExcelDna.Integration;

namespace ExcelDna.Registration.Utils
{
    // Helpers for creating and using Task-based functions with Excel-DNA's RTD-based IObservable support
    public static class AsyncTaskUtil
    {
        public static object RunTask<TResult>(string callerFunctionName, object callerParameters, Func<Task<TResult>> taskSource)
        {
            return ExcelAsyncUtil.RunTask(callerFunctionName, callerParameters, taskSource);
        }

        // Careful - this might only work as long as the task is not shared between calls, since cancellation cancels that task
        public static object RunTaskWithCancellation<TResult>(string callerFunctionName, object callerParameters, Func<CancellationToken, Task<TResult>> taskSource)
        {
            return ExcelAsyncUtil.RunTaskWithCancellation(callerFunctionName, callerParameters, taskSource);
        }

        public static object RunAsTask<TResult>(string callerFunctionName, object callerParameters, Func<TResult> function)
        {
            return ExcelAsyncUtil.RunAsTask(callerFunctionName, callerParameters, function);
        }

        public static object RunAsTaskWithCancellation<TResult>(string callerFunctionName, object callerParameters, Func<CancellationToken, TResult> function)
        {
            return ExcelAsyncUtil.RunAsTaskWithCancellation(callerFunctionName, callerParameters, function);
        }
    }
}

非同期処理の関数

指定ミリ秒待機して、指定文字列を返します。

ExcelDnaAddin.cs
using ExcelDna.Integration;
using ExcelDna.Registration.Utils;

namespace TestExcelDna;

public static class MyFunctions
{
    [ExcelFunction(Description = "非同期関数です。ミリ秒待機して文字列を返します。")]
    public static object SayDelay(string targetValue, int msTime)
    {
        var functionName = nameof(SayDelayBefore);
        var parameters = new object[] { targetValue, msTime };
        return AsyncTaskUtil.RunTask(functionName, parameters, async () =>
        {
            return await DnaDelayedTask(targetValue, msTime);
        });
    }
    
    public static async Task<string> DnaDelayedTask(string targetValue, int msDelay)
    {
        await Task.Delay(msDelay);
        return targetValue + msDelay;
    }
}

非同期処理中のセル表示

上記の方法だと処理中のセルに#N/Aと表示されて、処理後に結果が表示される。
そのため、処理中なのかエラーなのかが分かりにくくなります。
以下へ変更する事で、処理中だと分かるようにセルへ表示するようにします。

以下を参考にしました。
https://groups.google.com/g/exceldna/c/3t8Q616k8QA

  • private static readonly object ReturnNA = new();を追加
  • var result = AsyncTaskUtil.RunTask(で結果を受け取るようにしておき、if (result.Equals(ExcelError.ExcelErrorNA))とする
  • これにより処理中は、Busy...と表示されて、処理完了すればその結果が表示されるようになります
private static readonly object ReturnNA = new();
[ExcelFunction(Description = "非同期関数です。ミリ秒待機して文字列を返します。")]
public static string SayDelay(string targetValue, int msTime)
{
    var functionName = nameof(SayDelay);
    var parameters = new object[] { targetValue, msTime };
    var result = AsyncTaskUtil.RunTask(functionName, parameters, async () =>
      {
          return await DnaDelayedTask(targetValue, msTime);
      });

    if (result.Equals(ReturnNA))
    {
        return ExcelError.ExcelErrorNA.ToString();
    }
    if (result.Equals(ExcelError.ExcelErrorNA))
        return "Busy...";
    else
        return (string)result;
}

呼び出し結果

  • セル表示の変更前
    testDelayBefore.gif

  • セル表示の変更後
    testDelay.gif

参考

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?