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

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

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

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

C#

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

Q&A

解決済

2回答

2904閲覧

EXCEL VBA でデスクトップスクリーン画像を、セルに表記させる方法

yuujiMotoki

総合スコア90

VBA

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

C#

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

0グッド

2クリップ

投稿2020/02/27 10:16

#内容

EXCELシート上に、デスクトップ画面のスクリーンショットを
SHAPE画像で表示させるプログラムを作成しました。

#検討内容

結局のところ、VBA単体では難しかったので、C#でdllを書きました。

C#のDLLで、戻り値をBASE64の文字列にしています。
VBA側は、BASE64をファイルに落としてデコードしています。

結局のところ、ライブラリを作っても、ファイルに落とさないと
これが実現できないので、スマートではないと思っています。

#相談事項

C#の戻り値を、EXCELのSHAPEオブジェクトにして、
直接、VBAからSHAPEの貼り付けはできないものでしょうか?

どうもc#側で、EXCELのオブジェクトを扱う方法が分かりません。

#PS

今回、初めてc#を触ったので、そもそもDLLも初めてです。
ただし、感触としてはVBAをこね回すよりも、C#側でやりたいことを増やした方が良いように思います。

いままでCOMの操作だけでは、満足いくものができなかったのですが
少し、プログラムの幅が広がりそうな気がします。

すみませんが、初学者にアドバイスをお願い致します。

C#

1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Net; 5using System.Runtime.InteropServices; 6using System.Text; 7using System.Threading.Tasks; 8using System.Drawing.Imaging; 9using System.Diagnostics; 10using System.Drawing; 11using System.Windows.Forms; 12using System.IO; 13 14namespace ClassLibraryForVBA 15{ 16 [Guid(ScreenShot.ClassId)] 17 public class ScreenShot 18 { 19 public const string ClassId = "9E873B7A-6636-4448-B9BB-23BE3AE1F28B"; 20 public string GetScreen(int number) 21 { 22 Rectangle rc = System.Windows.Forms.Screen.AllScreens[number].WorkingArea; 23 Bitmap bmp = new Bitmap(rc.Width, rc.Height, PixelFormat.Format32bppArgb); 24 using (Graphics g = Graphics.FromImage(bmp)) 25 { 26 g.CopyFromScreen(rc.X, rc.Y, 0, 0, rc.Size, CopyPixelOperation.SourceCopy); 27 } 28 29 var SigBase64 = ""; 30 using (var ms = new MemoryStream()) 31 { 32 bmp.Save(ms, ImageFormat.Bmp); 33 SigBase64 = Convert.ToBase64String(ms.GetBuffer()); 34 } 35 return SigBase64; 36 } 37 public int Count() 38 { 39 return Screen.AllScreens.Length; 40 } 41 public int Height(int number) 42 { 43 return System.Windows.Forms.Screen.AllScreens[number].WorkingArea.Height; 44 } 45 public int Width(int number) 46 { 47 return System.Windows.Forms.Screen.AllScreens[number].WorkingArea.Width; 48 } 49 } 50}

VBA

1Option Explicit 2 3Sub GetPageHtml() 4 5 ' .NETライブラリのクラスをインスタンス化 6Dim wp As New ClassLibraryForVBA.ScreenShot 7Dim arr 8 9arr = wp.getscreen(0) 10Debug.Print wp.Height(0), wp.Width(0) 11put_shape (arr) 12 13arr = wp.getscreen(1) 14Debug.Print wp.Height(1), wp.Width(1) 15put_shape (arr) 16 17End Sub 18 19 20Sub put_shape(arr) 21Dim strTempPath 22strTempPath = Application.ActiveWorkbook.Path & "\temp.png" 23Open strTempPath For Binary As #1 24Put #1, 1, DecodeBase64(arr) 25Close #1 26 27Sheets("Sheet1").Pictures.Insert strTempPath 28 29End Sub 30 31 32Private Function DecodeBase64(ByVal strData As String) As Byte() 33 34 Dim objXML As Object 'MSXML2.DOMDocument 35 Dim objNode As Object 'MSXML2.IXMLDOMElement 36 37 'get dom document 38 Set objXML = CreateObject("MSXML2.DOMDocument") 39 40 'create node with type of base 64 and decode 41 Set objNode = objXML.createElement("b64") 42 objNode.DataType = "bin.base64" 43 objNode.Text = strData 44 DecodeBase64 = objNode.nodeTypedValue 45 46 'clean up 47 Set objNode = Nothing 48 Set objXML = Nothing 49 50End Function 51 52

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

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

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

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

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

guest

回答2

0

自己解決

結局はc#側でcomライブラリを実装することになりました。
ファイル名を渡して、そこに保存させており
引き渡し等は考えないことにいたしました。

c#

1 2using System; 3using System.Runtime.InteropServices; 4using System.Drawing; 5using System.Drawing.Imaging; 6 7 8namespace ExcelVbaExt 9{ 10 [ComVisible(true)] 11 public interface IScreenCapture 12 { 13 void CaptureWindowToFile(int whdl, string filename); 14 } 15 16 [ClassInterface(ClassInterfaceType.None)] 17 public class ScreenCapture : IScreenCapture 18 { 19 public void CaptureWindowToFile(int whdl, string filename) 20 { 21 22 IntPtr handle=new IntPtr(whdl); 23 Image img = CaptureWindow(handle); 24 img.Save(filename); 25 } 26 private Image CaptureWindow(IntPtr handle) 27 { 28 IntPtr hdcSrc = User32.GetWindowDC(handle); 29 User32.RECT windowRect = new User32.RECT(); 30 User32.GetWindowRect(handle, ref windowRect); 31 int width = windowRect.right - windowRect.left; 32 int height = windowRect.bottom - windowRect.top; 33 IntPtr hdcDest = GDI32.CreateCompatibleDC(hdcSrc); 34 IntPtr hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc, width, height); 35 IntPtr hOld = GDI32.SelectObject(hdcDest, hBitmap); 36 37 GDI32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, GDI32.SRCCOPY); 38 GDI32.SelectObject(hdcDest, hOld); 39 GDI32.DeleteDC(hdcDest); 40 User32.ReleaseDC(handle, hdcSrc); 41 Image img = Image.FromHbitmap(hBitmap); 42 GDI32.DeleteObject(hBitmap); 43 return img; 44 } 45 46 private class GDI32 47 { 48 public const int SRCCOPY = 0x00CC0020; // BitBlt dwRop parameter 49 [DllImport("gdi32.dll")] 50 public static extern bool BitBlt(IntPtr hObject, int nXDest, int nYDest, 51 int nWidth, int nHeight, IntPtr hObjectSource, 52 int nXSrc, int nYSrc, int dwRop); 53 [DllImport("gdi32.dll")] 54 public static extern IntPtr CreateCompatibleBitmap(IntPtr hDC, int nWidth, 55 int nHeight); 56 [DllImport("gdi32.dll")] 57 public static extern IntPtr CreateCompatibleDC(IntPtr hDC); 58 [DllImport("gdi32.dll")] 59 public static extern bool DeleteDC(IntPtr hDC); 60 [DllImport("gdi32.dll")] 61 public static extern bool DeleteObject(IntPtr hObject); 62 [DllImport("gdi32.dll")] 63 public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject); 64 } 65 66 67 private class User32 68 { 69 [StructLayout(LayoutKind.Sequential)] 70 public struct RECT 71 { 72 public int left; 73 public int top; 74 public int right; 75 public int bottom; 76 } 77 [DllImport("user32.dll")] 78 public static extern IntPtr GetDesktopWindow(); 79 [DllImport("user32.dll")] 80 public static extern IntPtr GetWindowDC(IntPtr hWnd); 81 [DllImport("user32.dll")] 82 public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC); 83 [DllImport("user32.dll")] 84 public static extern IntPtr GetWindowRect(IntPtr hWnd, ref RECT rect); 85 } 86 } 87 } 88

投稿2020/04/24 12:43

yuujiMotoki

総合スコア90

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

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

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問