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

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

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

Q&A

解決済

2回答

607閲覧

ExcelVBAにて図の挿入について

kazuuumi

総合スコア4

0グッド

0クリップ

投稿2023/09/18 02:40

編集2023/09/18 03:58

実現したいこと

Excelのリボンタグから挿入→図→正方形を選択
の部分まで行いたいと思っております。

前提

前提としてVBAで実装予定です。
Shapes.AddPictureで作成される図の場合該当処理をした時点で作成が完了されてしまうのですが、行いたいのはマウスで作成する動作になります。

試したこと

現在下記のサイトを参考に挿入タブまで選択できたのですが知識が不足しているためそちら以降の作業が分かっておりません。
https://www.ka-net.org/blog/?p=4624

###ソース

VBA

1Option Explicit 2 3Public Sub Sample() 4 SelectRibbonTab "挿入" 5End Sub 6 7Public Sub SelectRibbonTab(ByVal tabName As String) 8'リボンのタブを選択 9 Dim uiAuto As UIAutomationClient.CUIAutomation 10 Dim elmRibbon As UIAutomationClient.IUIAutomationElement 11 Dim elmRibbonTab As UIAutomationClient.IUIAutomationElement 12 Dim cndProperty As UIAutomationClient.IUIAutomationCondition 13 Dim aryRibbonTab As UIAutomationClient.IUIAutomationElementArray 14 Dim ptnAcc As UIAutomationClient.IUIAutomationLegacyIAccessiblePattern 15 Dim accRibbon As Office.IAccessible 16 Dim i As Long 17 18 Set elmRibbonTab = Nothing '初期化 19 Set uiAuto = New UIAutomationClient.CUIAutomation 20 Set accRibbon = Application.CommandBars("Ribbon") 21 Set elmRibbon = uiAuto.ElementFromIAccessible(accRibbon, 0) 22 Set cndProperty = uiAuto.CreatePropertyCondition(UIA_ClassNamePropertyId, "NetUIRibbonTab") 23 Set aryRibbonTab = elmRibbon.FindAll(TreeScope_Subtree, cndProperty) 24 For i = 0 To aryRibbonTab.Length - 1 25 Debug.Print "CurrentName" & aryRibbonTab.GetElement(i).CurrentName 26 If aryRibbonTab.GetElement(i).CurrentName = tabName Then 27 Set elmRibbonTab = aryRibbonTab.GetElement(i) 28 Exit For 29 End If 30 Next 31 If elmRibbonTab Is Nothing Then Exit Sub 32 Set ptnAcc = elmRibbonTab.GetCurrentPattern(UIA_LegacyIAccessiblePatternId) 33 ptnAcc.DoDefaultAction 34 35 36End Sub

有識者の方、または試したことがあるかたよろしければ助言をいただきたいです。

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

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

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

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

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

meg_

2023/09/18 03:54

> 現在下記のサイトを参考に挿入タブまで選択できた コードを質問に追記してください。
kazuuumi

2023/09/18 03:56

すみません追記いたします。
guest

回答2

0

SaYGOさんの指摘から若干の修正。
現状開いているアクティブブックを指定して図形を取得するよう修正

vb

1 2Option Explicit 3 4Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) 5'途中でコメントアウトしているSleep関数を使う場合は↑のコメントを外す 6Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" ( _ 7 ByVal lpClassName As String, ByVal lpWindowName As String) As Long 8'FindWindowを使用できるようにするため追加 9 10 11Public Sub 正方形選択() 12 13 On Error GoTo ErrorLabel 14 15 Dim uia As New CUIAutomation 16 Dim rootElement As IUIAutomationElement 17 Dim Hwnd As Long 18 Dim WinName As String 19 WinName = ActiveWorkbook.name & " - Excel" 20 Hwnd = FindWindow(vbNullString, WinName) 21 Set rootElement = uia.ElementFromHandle(ByVal Hwnd) 22 'Set rootElement = uia.GetRootElement 元処理 23 24 'クイックアクセスツールバーに追加しておく必要がある 25 Dim element As IUIAutomationElement 26 Set element = GetSayGOChildElement(uia, rootElement, "図形", "NetUIAnchor") 27 Dim menupane As IUIAutomationExpandCollapsePattern 28 '図形メニューペーンを展開する。 29 Set menupane = element.GetCurrentPattern(UIA_ExpandCollapsePatternId) 30 menupane.Expand 31 32 Sleep 100 'うまく選択されない場合はここと冒頭のコメントを外して調整。 33 DoEvents 'クリック扱いになるのを防ぐ 34 35 Set element = GetSayGOChildElement(uia, element, "正方形/長方形", "NetUIGalleryButton") 36 37 'IUIAutomationInvokePattern だと図形が挿入されてしまう。 38 Dim invokePattern As IUIAutomationSelectionItemPattern 39 Set invokePattern = element.GetCurrentPattern(UIA_SelectionItemPatternId) 40 invokePattern.Select 41 42 43ErrorLabel: 44 Debug.Print Err.Number & " " & Err.Description 45 46End Sub 47 48 49'指定したエレメント名、クラス名に該当する子要素を返す 50Private Function GetSayGOChildElement( _ 51 ByRef uia As CUIAutomation, _ 52 ByRef parentElement As IUIAutomationElement, _ 53 elementName As String, _ 54 className As String _ 55 ) As IUIAutomationElement 56 57 Dim element As IUIAutomationElement 58 Dim cndName As IUIAutomationCondition 59 Dim cndClassName As IUIAutomationCondition 60 Dim cndNameAndClassName As IUIAutomationCondition 61 62 Set element = Nothing 63 Set cndName = uia.CreatePropertyCondition(UIA_NamePropertyId, elementName) 64 Set cndClassName = uia.CreatePropertyCondition(UIA_ClassNamePropertyId, className) 65 Set cndNameAndClassName = uia.CreateAndCondition(cndName, cndClassName) 66 Set element = parentElement.FindFirst(TreeScope_Subtree, cndNameAndClassName) 67 68 If element Is Nothing Then 69 Set GetSayGOChildElement = Nothing 70 Call Err.Raise(90000, "GetSayGOChildElement", "エラー:名前:「" & elementName & "」、クラス名「" & className & "」に該当するエレメントが見つかりませんでした") 71 End If 72 Set GetSayGOChildElement = element 73 74End Function 75 76 77 78

投稿2023/09/19 04:24

kazuuumi

総合スコア4

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

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

0

ベストアンサー

質問中にあるようなコードは、リボン内のメニュー構造にかなり依存します。
つまり、異なるバージョンのエクセル(アップデート含む)では、メニュー構造やクラス名が異なってしまうため、バージョンごとにinspecter等で構造を調べコードを適切に組み替えないとすぐ動かなくなります。
(構造だけではなく、処理依存で出現するモーダルダイアログの処理や、コンポーネントごとにクリックや選択の挙動が全然異なるということもあります。ですので個人的にこの手のオートメーションを自作で行うのは茨の道と思っています。)

なお下記は参考として、自分の環境(Windows 11 Pro 64bit のMicrosoft 365 EXCEL バージョン2308)で動くコードです。
(実行するとカーソルが十字になって四角形描画モードになります)

vb

1 2'Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) 3'途中でコメントアウトしているSleep関数を使う場合は↑のコメントを外す 4 5Public Sub 正方形選択() 6 7 Dim uia As New CUIAutomation 8 Dim rootElement As IUIAutomationElement 9 Set rootElement = uia.GetRootElement 10 11 Dim element As IUIAutomationElement 12 '以下は環境依存。inspecter.exeなどで調べる。 13 Set element = GetSayGOChildElement(uia, rootElement, "図形", "NetUIAnchor") 14 '図形メニューペーンを展開する。 15 Dim menupane As IUIAutomationExpandCollapsePattern 16 Set menupane = element.GetCurrentPattern(UIA_ExpandCollapsePatternId) 17 menupane.expand 18 19 'Sleep 100 'うまく選択されない場合はここと冒頭のコメントを外して調整。 20 DoEvents 'クリック扱いになるのを防ぐ。 21 22 ' 以下は環境依存。inspecter.exeなどで調べる。 23 Set element = GetSayGOChildElement(uia, element, "図形", "NetUIToolWindow") 24 Set element = GetSayGOChildElement(uia, element, "図形", "NetUIGalleryContainer") 25 Set element = GetSayGOChildElement(uia, element, "四角形", "NetUIGalleryCategoryContainer") 26 Set element = GetSayGOChildElement(uia, element, "正方形/長方形", "NetUIGalleryButton") 27 28 'IUIAutomationInvokePattern だと図形が挿入されてしまう。 29 Dim invokePattern As IUIAutomationSelectionItemPattern 30 Set invokePattern = element.GetCurrentPattern(UIA_SelectionItemPatternId) 31 invokePattern.Select 32 33End Sub 34 35 36'指定したエレメント名、クラス名に該当する子要素を返す 37Private Function GetSayGOChildElement( _ 38 ByRef uia As CUIAutomation, _ 39 ByRef parentElement As IUIAutomationElement, _ 40 elementName As String, _ 41 className As String _ 42 ) As IUIAutomationElement 43 44 Dim element As IUIAutomationElement 45 Dim cndName As IUIAutomationCondition 46 Dim cndClassName As IUIAutomationCondition 47 Dim cndNameAndClassName As IUIAutomationCondition 48 49 Set element = Nothing 50 Set cndName = uia.CreatePropertyCondition(UIA_NamePropertyId, elementName) 51 Set cndClassName = uia.CreatePropertyCondition(UIA_ClassNamePropertyId, className) 52 Set cndNameAndClassName = uia.CreateAndCondition(cndName, cndClassName) 53 Set element = parentElement.FindFirst(TreeScope_Subtree, cndNameAndClassName) 54 55 If element Is Nothing Then 56 Set GetSayGOChildElement = Nothing 57 Debug.Print "エラー:名前:「" & elementName & "」、クラス名「" & className & "」に該当するエレメントが見つかりませんでした") 58 End If 59 Set GetSayGOChildElement = element 60 61End Function

投稿2023/09/18 12:28

編集2023/09/18 21:08
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

kazuuumi

2023/09/18 14:13

ご指摘ありがとうございます。 まだまだ知識不足の面がありますが上記参考ソースをもとにこちらで試したところわたくしの環境(windows11 64bit Microsoft Office Personal 2021) でも同様の挙動をするところまで修正できました。 inspecterも入れるところからでしたので少し苦労いたしましたがおかげさまで構造把握が進んだ気がします。 ちなみにですが上記のようなソースは何を参考にされたか、もしくはどういった勉強をしたのか教えていただくことは可能でしょうか?
退会済みユーザー

退会済みユーザー

2023/09/18 21:05 編集

上手くいったようでよかったです。 UIAutomation自体昨日初めて知った機能でしたので、まず記事のソースコードを皮切りに、キーワードで検索していろんなサイトのコードやMicrosoftの公式ドキュメント、vbaのオブジェクトブラウザを参照しながら片っ端から試して挙動を見て、少しずつ希望の動作にしていった感じです。 一番参考になったのは、 https://note.com/char0059/n/nf86b57b735ab です。(この中にあるサンプルマクロが大変参考になった) あとはinspecterとともに、uiAutomationSpyというツールです。 コードをすっきりさせるため関数化した部分(GetSayGOChildElement関数)は丸コピペとかではなくほぼ完全なオリジナルです。 あと図形ボタンを描画してしまわない(十字カーソル出現状態にする)ようにするためにはペーンを開いた状態でDoEventsを置き、かつIUIAutomationInvokePatternではなくIUIAutomationSelectionItemPatternを使うとうまくいく、というのも偶然見つけました。 4~5時間くらいで突貫で作ったものなので、まだまだブラッシュアップの余地はあると思います(たとえば現状のコードは、デスクトップ上の全ウィンドウから「図形」のボタンを検索するので、起動の動作が遅い) 追記: バージョン違いでもある程度安定させる方法として、「正方形/長方形」のボタンをクイックツールバーに登録しておいて、クイックツールバーのエレメント経由で呼び出すという方法もあるな、と今さら思いました。
kazuuumi

2023/09/19 00:17

はい!!ありがとうございました。 基本的に調べて書き出しを繰り返した形ですね。。 まだまだ調べる力が浅いと実感いたしました。 uiAutomationSpyに関しては少し自分も確認してみようと思います。 改善の余地があるとのことなので自分も少し調べてみたいと思います!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.31%

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

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

質問する

関連した質問