この小さなC#テストDLLはUnmanagedExports(NuGetパッケージとして入手)を使って書かれていますが正常に動作しています。しかし、どうすればVBAラッパー関数でSplit()でなければならない文字列を返すのではなく、すぐにString()配列を返すことができるのだろうかと思います。VBAのC#dllの文字列[]を返す
つまり、注目点はメソッドGetFilesWithExtension()です。 DLLの他のメソッドは、正しいエンコーディングで文字列を渡す方法を考えながら作成した小さなテストです。
DLLはx64と.NET 4.5.2をターゲットにしていますが、x86用にもビルドすることができます(したがって、VBAの関数宣言を変更する必要があります)。
C#クラスライブラリ(TestDll.dll):
using System;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using RGiesecke.DllExport;
namespace TestDll
{
public class Class1
{
[DllExport(nameof(Addition), CallingConvention.StdCall)]
public static int Addition(int a, int b)
{
return a + b + 100;
}
[DllExport(nameof(LinqAddition), CallingConvention.StdCall)]
public static int LinqAddition(int a, int b)
{
return new int[] {a, b, 1, 4, 5, 6, 7, 8 }.Sum();
}
[DllExport(nameof(LinqAdditionString), CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.AnsiBStr)]
public static string LinqAdditionString(int a, int b)
{
return new int[] { a, b, 1, 4, 5, 6, 7, 8 }.Sum() + "";
}
[DllExport(nameof(GetFilesWithExtension), CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.AnsiBStr)]
public static string GetFilesWithExtension([MarshalAs(UnmanagedType.AnsiBStr)] string folderPath, [MarshalAs(UnmanagedType.AnsiBStr)] string extension, bool includeSubdirectories)
{
//Debug
//File.WriteAllText(@"C:\Users\johanb\Source\Repos\TestDll\output.txt", $"folderPath: {folderPath}, extension: {extension}, includeSubdirectories: {includeSubdirectories}");
try
{
if (!Directory.Exists(folderPath))
return "";
extension = extension.Trim('.');
return string.Join(";",
Directory.GetFiles(folderPath, "*.*",
includeSubdirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly)
.Where(
f =>
Path.GetExtension(f)?
.Trim('.')
.Equals(extension, StringComparison.InvariantCultureIgnoreCase) ?? false)
.ToArray());
}
catch (Exception ex)
{
return ex.ToString();
}
}
}
}
(エクセルでテスト)VBAモジュール:私はかなりのExcelにオブジェクトを返さない飽きない可能性があり
Attribute VB_Name = "TestDll"
Option Explicit
Public Declare PtrSafe Function Addition Lib "C:\Users\johanb\Source\Repos\TestDll\TestDll\bin\Debug\TestDll.dll" (ByVal a As Long, ByVal b As Long) As Long
Public Declare PtrSafe Function LinqAddition Lib "C:\Users\johanb\Source\Repos\TestDll\TestDll\bin\Debug\TestDll.dll" (ByVal a As Long, ByVal b As Long) As Long
Public Declare PtrSafe Function LinqAdditionString Lib "C:\Users\johanb\Source\Repos\TestDll\TestDll\bin\Debug\TestDll.dll" (ByVal a As Long, ByVal b As Long) As String
Public Declare PtrSafe Function GetFilesWithExt Lib "C:\Users\johanb\Source\Repos\TestDll\TestDll\bin\Debug\TestDll.dll" Alias "GetFilesWithExtension" (ByVal folderPath As String, ByVal extension As String, ByVal includeSubdirs As Boolean) As String
Sub Test()
Dim someAddition As Long
Dim someLinqAddition As Long
Dim someLinqAdditionAsString As String
Dim files() As String
Dim i As Long
someAddition = Addition(5, 3)
Debug.Print someAddition
someLinqAddition = LinqAddition(5, 3)
Debug.Print someLinqAddition
someLinqAdditionAsString = LinqAdditionString(5, 3)
Debug.Print someLinqAddition
files = GetFilesWithExtension("C:\Tradostest\Project 4", "sdlxliff", True)
For i = 0 To UBound(files)
Debug.Print files(i)
Next i
End Sub
Function GetFilesWithExtension(folderPath As String, extension As String, includeSubdirs As Boolean) As String()
GetFilesWithExtension = Split(GetFilesWithExt(folderPath, extension, includeSubdirs), ";")
End Function
VBAが 'string()'を返すと宣言されているinterop関数を処理する方法を覚えていませんが(実際には存在しないので)、 'out'パラメータで配列を返して、 TLBが存在するCOMシナリオの 'string()'戻り型を残してしまい、そのようなことは自然に機能します。 – GSerg
ああ、良いアイデア。他の応答がない場合は、outパラメータで試してみます。 GSergに感謝します。 – Jbjstam
VBA intは32ビットbtwではなく16ビットです。 –