今回はExcel-DNAで非同期処理をつくってみます。
Excel-DNAの使い方は以下。
非同期処理を追加する
- このページを参考に追加していきます
<PackageReference Include="ExcelDna.Addin" Version="1.8.0" />
必要ファイルの追加
このファイルをそのまま使います。
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;
}