[[20211109112431]] 『別ブックのユーザーフォームにチェックを入れたい』(ななな) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『別ブックのユーザーフォームにチェックを入れたい』(ななな)

現在作成中の「Book1.xlsm」と既存のツール「Tool.xlsm」があります。
「Tool.xlsm」は開くとユーザーフォーム(Form1)がモードレスで立ち上がるように
なっています。

やりたいことは
1.「Book1.xlsm」から「Tool.xlsm」を起動
2.「Tool.xlsm」で表示されたユーザーフォームのCheckBox1にチェックを入れる
3.「Tool.xlsm」で表示されたユーザーフォームのCommandButton1をクリックする
の3つです。

1はWorkbooks.Openで済むので問題ないのですが、
2と3をやる方法がわかりません。
「Tool.xlsm」自体のコードを触ることはできません。
「Tool.xlsm」で表示されたユーザーフォームのCheckBox1はFrame1内にあります。

「Book1.xlsm」から以上のことを行いたいのですがどのようにしたらいいでしょうか?みなさまのお知恵を貸してください。

< 使用 Excel:Excel2016、使用 OS:Windows10 >


 >「Tool.xlsm」自体のコードを触ることはできません。
 ということだと、別なアプリを操作するようなものなので、かなり厳しいです。

 コードを触ることができないのに、CheckBox1 とか、CommandButton1 とか
 コントロールの名前がわかっているのはなぜですか?

 編集しちゃいけなくても、コードを見れるなら、ごっそりコードをコピーすれば
 いくらでも好きに改造できるとおもいますが。
(´・ω・`) 2021/11/09(火) 13:57

「Tool.xlsm」は私が作成したものではないのですが、
仕様書によりコントロール名は判別できています。

「Tool.xlsm」は汎用的に使用されているもので
私どもの一存で改修等入れることはできないものです。

ですので、改造はおろか、コードそのものも見ることができません。

ハンドルの取得も検討したのですが、Frame以外のコントロールの
ハンドルは取得できずで困っています。

(ななな) 2021/11/09(火) 14:22


 >改造はおろか、コードそのものも見ることができません。
 Tool.xlsmに、独自のSubプロシジャを追加できるなら簡単ですが、
 それができないなら、私にはいい方法がありません

 UserFormのコマンドボタンをクリックしたあとに実行されるプロシジャが
 もし標準モジュールにあるなら、ワンチャンあるかもという感じです。

 >ハンドルの取得も検討したのですが、Frame以外のコントロールの
 >ハンドルは取得できずで困っています。 
 Windows API は私は全く詳しくないので、お力になれずすみません

 詳しい回答者が登場されるのをお待ち下さい。
(´・ω・`) 2021/11/09(火) 14:41

(´・ω・`)様、ありがとうございます。

 > UserFormのコマンドボタンをクリックしたあとに実行されるプロシジャ

についても、フォームモジュール内の様でしたので直接実行することも
叶いませんでした。

(ななな) 2021/11/09(火) 14:49


 そこまで詳しくないので無理ならばすまない。

 >1.「Book1.xlsm」から「Tool.xlsm」を起動
 ということであればWorkbooks.Open時にWorkbookオブジェクト変数に開いたブックを代入する。
 で、
 >CheckBox1
 >CommandButton1
 ということはActiveXコントロールだと思うので上記のWorkbookオブジェクトを通してCommandButton1_Clickプロシージャなどを
 実行できないだろうか?
(ねむねむ) 2021/11/09(火) 14:51

 ねむねむさん
 シート上に配置されたコントロールであれば可能性はあるかもしれません(未検証です)が、
 UserForm上のコントロールは見えないんです
(´・ω・`) 2021/11/09(火) 14:56

 WindowsAPIのUser32.dllを使ってマウスの自動操作を考えてみました。
 ユーザフォームの位置が常に同じ位置に表示されないとうまく動かないと思いますが一案として。
API初めて使ったので色々間違ってるかも知れません…。

 ---------------------------------------------------------
 'カーソル位置設定
 Declare PtrSafe Function SetCursorPos Lib "user32" (ByVal x As Long, ByVal y As Long) As Long

 'マウス操作
 Declare PtrSafe Sub mouse_event Lib "user32" ( _
     ByVal dwFlags As Long, _
     Optional ByVal dx As Long = 0, _
     Optional ByVal dy As Long = 0, _
     Optional ByVal dwData As Long = 0, _
     Optional ByVal dwExtractInfo As Long = 0)

 Sub test()

     '-----------------------------------------------------------
     '事前にTool.xlsmのウィンドウをアクティブ化、最大化しておく
     '-----------------------------------------------------------

     'カーソル移動
     'ユーザフォームの表示位置はTool.xlsmのウィンドウ位置に対して一定だと思うので、
     'これの引数をCheckBox1、ComboBox1の位置になるよう調整する。
     'この例では200がモニタ左端からのピクセル数、
     '500がモニタ上からのピクセル数を示しています。
     SetCursorPos 200, 500

     'マウス左ボタン押下
     mouse_event 2

     'マウス左ボタン離す(押下と併せて1回クリック)
     mouse_event 4

 End Sub
(さくさくアジフライ) 2021/11/09(火) 15:25

 余談ですが、Tool.xlsmを編集できる場合の方法の一つです

  Tool.xlsm のVBE画面で、 ツール→ VBAProjectのプロパティでプロジェクト名を設定
 UserFormをエクスポートして、UserForm1.frm をテキストエディタで開いて
 以下の設定にする(全部Trueにしないといけないかどうかはよくわからないけどとりあえず全部True)

  Attribute VB_Name = "UserForm1"
  Attribute VB_GlobalNameSpace = True
  Attribute VB_Creatable = True
  Attribute VB_PredeclaredId = True
  Attribute VB_Exposed = True

  UserForm1.frmをインポートし直す
 
 Book1.xlsmで、 Tool.xlsm を参照設定する
 そうすると、
 Book1.xlsmでは、

   Dim f As TestProject.UserForm1       ' プロジェクト名は、最初に設定したプロジェクト名
   Set f = New TestProject.UserForm1
   f.Show

  と、できます
 こんな感じです

  Tool.xlsm に必要なSubプロシジャを追加してそれをCallするのが一番簡単ですが... 
(´・ω・`) 2021/11/09(火) 16:28

返信が遅くなってすみません。

さくさくアジフライさん、
ユーザーによってモニタが複数台あって表示位置が全員同じ位置とはなりませんでした。

(´・ω・`)さん、
Dim f As TestProject.UserForm1
のところで「ユーザー定義型は定義されません。」と怒られます。
TestProject. の中にUserForm1がなく(Sheet1とかはある)、先に進めませんでした。

ねむねむさんもありがとうございます。
(ななな) 2021/11/11(木) 16:45


 TABキーでユーザーフォーム上のコントロールを巡回できる仕様なら
 単純にSendKeysで何とかなる場合もあったりなかったり...?

    '===============================================================================================
    '[UserForm1]モジュール(Tool.xlsm) --------------------------------------------------------------
    Option Explicit
    Private WithEvents CommandButton1 As MSForms.CommandButton
    Private CheckBox1 As MSForms.CheckBox

    Private Sub CommandButton1_Click()
        MsgBox "CommandButton1_Click"
    End Sub

    Private Sub UserForm_Initialize()
        Set CheckBox1 = Me.Controls.Add("Forms.CheckBox.1", "CheckBox1")
        With CheckBox1
            .Top = 3
            .Left = 3
            .Width = 96
            .Caption = .Name
        End With
        Set CommandButton1 = Me.Controls.Add("Forms.CommandButton.1", "CommandButton1")
        With CommandButton1
            .Top = 24
            .Left = 3
            .Width = 96
            .Caption = .Name
        End With
    End Sub
    '[ThisWorkbook]モジュール(Tool.xlsm) -----------------------------------------------------------
    Option Explicit
    Private Sub Workbook_Open()
        UserForm1.Show vbModeless
    End Sub
    '===============================================================================================

    '標準モジュール(Book1.xlsm) --------------------------------------------------------------------
    Sub test()
        Workbooks.Open "C:\xxx\Tool.xlsm"
        Application.SendKeys " {TAB} " 'CheckBox1でスペース → タブ → CommandButton1でスペース
    End Sub

(白茶) 2021/11/11(木) 18:33


 ユーザフォームのウィンドウハンドルを取得して、
 ユーザフォームの左上の位置を特定、
 そこから相対的に操作したいコントロールの位置を
 指定する方法にしてみました。

 ----
 Option Explicit

 Private Type POINTAPI
     x As Long
     y As Long
 End Type

 Private Type RECT
     Left As Long
     Top As Long
     Right As Long
     Bottom As Long
 End Type

 Private Type WINDOWSPLACEMENT
     Length As Long
     flags As Long
     showCmd As Long
     ptMinPosition As POINTAPI
     ptMaxPosition As POINTAPI
     rcNormalPosition As RECT
 End Type

 'ハンドルを取得
 Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" ( _
     ByVal lpClassName As String, _
     ByVal lpWindowName As String) _
 As Long

 'ウィンドウ位置を取得
 Private Declare PtrSafe Function GetWindowPlacement Lib "user32" ( _
     ByVal hwnd As Long, _
     lpwndpl As WINDOWSPLACEMENT) _
 As Long

 'カーソル位置設定
 Declare PtrSafe Function SetCursorPos Lib "user32" ( _
     ByVal x As Long, _
     ByVal y As Long) _
 As Long

 'マウス操作
 Declare PtrSafe Sub mouse_event Lib "user32" ( _
     ByVal dwFlags As Long, _
     Optional ByVal dx As Long = 0, _
     Optional ByVal dy As Long = 0, _
     Optional ByVal dwData As Long = 0, _
     Optional ByVal dwExtractInfo As Long = 0)

 Sub test()

     Dim myHwnd As Long
     Dim myWindowPlacement As WINDOWSPLACEMENT

     'ハンドル取得
     '------------------------------------------------------------
     '「★★★」にフォームのタイトルバーに表示されている名称を記入
     '------------------------------------------------------------
     myHwnd = FindWindow(vbNullString, "★★★")

     'ハンドルに対応するウィンドウ位置取得
     GetWindowPlacement myHwnd, myWindowPlacement

     With myWindowPlacement.rcNormalPosition

         'カーソル移動
         '------------------------------------------------------------------------
         '◆、■の値を調整して操作したい項目の上にカーソルが来るようにしてください
         '------------------------------------------------------------------------
         SetCursorPos .Left + ◆, .Top + ■

     End With

     '------------------------------------------------------------------------
     '押下処理はカーソル位置が調整できてからコメント解除した方がいいと思います
     '------------------------------------------------------------------------
 '    'マウス左ボタン押下
 '    mouse_event 2
 '
 '    'マウス左ボタン離す(押下と併せて1回クリック)
 '    mouse_event 4

 End Sub
(さくさくアジフライ) 2021/11/12(金) 09:41

 他の方の提案で、やりたいことが… 実現出来なかった場合は参考にしてください。*_ _))ペコ								

 >「Tool.xlsm」は開くとユーザーフォーム(Form1)がモードレスで立ち上がるように								
 > なっています。								

 えと〜もしかしたら? ですが…								
 モーダル( vbModal )と、モードレス ( vbModeless )では違いがあるのではないでしょうか?								

 [ThisWorkbook] モジュール ( Tool.xlsm ) において								

 Option Explicit								
 Private Sub Workbook_Open()								
   UserForm1.Show vbModeless								
 End Sub								

 ↑これだとエラー連発で								
 実行エラー'91 オブジェクト変数または With ブロック変数が設定されていません								

 ですが、 UserForm1.Show なら下記のコードで								
 CheckBox1 の [ ON or OFF ] 切替が可能でした。								
 App = "C:\Users\user\Desktop\Tool.xlsm" ← ここは「摘便」変更してください。								

 Option Explicit								
 Sub Sample()								
   Dim App As String								
   Dim AppTool As Object								
   Dim VBProject As Object								
   App = "C:\Users\user\Desktop\Tool.xlsm"								
   Set AppTool = Workbooks.Open(App)								
  'Application.Run								
   AppTool.VBProject.VBComponents("UserForm1").Designer.Controls("CheckBox1").Value = True  '' True or False								

   Dim buf As String '' VBProjectの操作								
   With ActiveWorkbook								
      buf = buf & .VBProject.Name & vbCrLf								
      buf = buf & .VBProject.Filename & vbCrLf								
      buf = buf & .VBProject.Protection & vbCrLf								
   End With								
      MsgBox buf								
 End Sub								

 現在、私が思う有力な方法としては、(´・ω・`)さんのおっしゃっている方法で								
 > Tool.xlsm に必要なSubプロシジャを追加してそれをCallするのが一番簡単ですが...								
 と同じような意味なのですが…								

 UserForm1.Show vbModeless ←部分をVBAで置換する、または、削除して								
 UserForm1.Show にして								
 Tool.xlsm に必要なSubプロシジャを追加するか、Sample のようなコードで操作するかですかね?								

(あみな) 2021/11/12(金) 12:47


コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.