質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

2回答

1297閲覧

C# で作ったOPENCV汎用DLLに、VBAからアクセス

yuujiMotoki

総合スコア90

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

1クリップ

投稿2020/03/19 08:36

編集2020/03/23 07:29

#VBAで3つのファイルパスを文字列引数として渡したい

C#で作ったCOMライブラリを呼び出しています。

引数を渡す部分で、エラーになります。

C#から呼び出したTEST.EXEでは問題なく、受け渡しができていました。
VBAで実施すると下記のエラーが出ます。

error

1 2実行時エラー '-2147467261(80004003)' 3値をNullすることができません。パラメータ名:path 4

#課題

文字列3つを参照渡しして、戻り値のx,y座標をPOINT構造体で受け取る予定です。
DLLのコールの仕方は初めてなのでよくわかりません。

何か参考になるソースがあれば、教えて頂きたく思います。

VBA

1Option Explicit 2 3Public Type Point 4x As Integer 5y As Integer 6End Type 7 8 9Sub test() 10 Dim file1, file2, file3 11 Dim shot 12 Dim x 13 14 str file1 = "C:\Users\mm05162\Desktop\after.bmp" 15 str file2 = "C:\Users\mm05162\Desktop\before.bmp" 16 str file3 = "C:\Users\mm05162\Desktop\drop.bmp" 17 Set shot = New ScreenShot 18 x = shot.Imagediff(file1, file2, file3) 19 20End Sub 21

C#

1 2using System; 3using System.Collections.Generic; 4using System.Drawing; 5using System.IO; 6using System.Linq; 7using System.Runtime.InteropServices; 8using OpenCvSharp; 9using Point = OpenCvSharp.Point; 10 11namespace ClassLibraryForVBA 12{ 13 [Guid(ScreenShot.ClassId)] 14 public class ScreenShot 15 { 16 public const string ClassId = "74EA63A0-15B2-42F4-9603-A5033599C4D6"; 17 private OpenCvSharp.Point[][] contours; 18 19 public System.Drawing.Point Imagediff(string a, string b, string c) 20 { 21 string file1 = Path.GetFullPath(a); 22 string file2 = Path.GetFullPath(b); 23 string file3 = Path.GetFullPath(c); 24 using (Mat image1 = Cv2.ImRead(file1)) 25 using (Mat image2 = Cv2.ImRead(file2)) 26 using (Mat image_drop = Cv2.ImRead(file3)) 27 using (Mat diff = new Mat(new OpenCvSharp.Size(image1.Cols, image1.Rows), MatType.CV_8UC3)) 28 29 try 30 { 31 Cv2.Absdiff(image1, image2, diff); 32 var result = new Mat(); 33 Mat mask = Mat.Zeros(image_drop.Size(), MatType.CV_8UC3); 34 Cv2.MatchTemplate(diff, image_drop, result, TemplateMatchModes.CCoeffNormed); 35 Cv2.Threshold(result, result, 0.8, 1.0, ThresholdTypes.Binary); 36 Cv2.MinMaxLoc(result, out OpenCvSharp.Point minPoint, out OpenCvSharp.Point maxPoint); 37 Rect rect = new Rect(maxPoint.X, maxPoint.Y, image_drop.Width, image_drop.Height); 38 Cv2.Rectangle(diff, rect, new OpenCvSharp.Scalar(0, 0, 0), -1); 39 Cv2.CvtColor(diff, diff, ColorConversionCodes.BGR2GRAY); 40 Cv2.Threshold(diff, diff, 20, 255, ThresholdTypes.Binary); 41 diff.FindContours(out contours, out HierarchyIndex[] hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple); 42 43 List<Point> points = new List<Point>(); 44 for (int idx_cnt = 0; idx_cnt < contours.GetLength(0); ++idx_cnt) 45 { 46 if (hierarchy[idx_cnt].Parent != -1) { continue; } 47 points.AddRange(contours[idx_cnt]); 48 } 49 var avgPoint = new System.Drawing.Point 50 { 51 X = (int)Math.Round(points.Average(p => p.X)), 52 Y = (int)Math.Round(points.Average(p => p.Y)) 53 }; 54 return avgPoint; 55 } 56 catch (Exception) 57 { 58 var ans = new System.Drawing.Point 59 { 60 X = 0, 61 Y = 0 62 }; 63 return ans; 64 } 65 } 66 } 67} 68

c#

1 2テストコード 3 4using System.Runtime.InteropServices; 5using System.IO; 6using System.Drawing; 7using ClassLibraryForVBA; 8 9 10namespace im_test 11{ 12 class Program 13 { 14 static void Main() 15 { 16 string file1 = Path.GetFullPath(@"C:\Users\mm05162\Desktop\after.bmp"); 17 string file2 = Path.GetFullPath(@"C:\Users\mm05162\Desktop\before.bmp"); 18 string file3 = Path.GetFullPath(@"C:\Users\mm05162\Desktop\drop.bmp"); 19 var shot = new ScreenShot(); 20 Point x = shot.Imagediff(file1, file2, file3); 21 22 } 23 } 24}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Y.H.

2020/03/23 07:11

VBAのタグを追加してください。
guest

回答2

0

自己解決

結局ですが、構造体での受け渡しをやめることにしました。

変数が多いのが、不格好ではありますが、いまはこれしか私にはできませんでした。

DLL側(C#)
bool Imagediff(string file1, string file2, string file3, ref int x, ref int y, ref int w, ref int h);

呼び出し側(VBA)
p = win.Imagediff(f1, f2, f3, x, y, w, h)

配列やジェネリックを扱うには、まだまだ修行が足りません。

投稿2020/04/12 00:14

yuujiMotoki

総合スコア90

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

たぶん変数宣言して初期化しているつもりなのでしょうが…

VBA

1str file1 = "C:\Users\mm05162\Desktop\after.bmp" 2str file2 = "C:\Users\mm05162\Desktop\before.bmp" 3str file3 = "C:\Users\mm05162\Desktop\drop.bmp"

Str関数をCALLし結果を捨ててます。

結果として、file1,file2,file3は初期化されてないです。
単純に代入でいいのでは?

VBA

1file1 = "C:\Users\mm05162\Desktop\after.bmp" 2file2 = "C:\Users\mm05162\Desktop\before.bmp" 3file3 = "C:\Users\mm05162\Desktop\drop.bmp"

投稿2020/03/23 07:09

編集2020/03/25 10:56
Y.H.

総合スコア7914

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問