[[20160608022050]] 『ボタン作成後ユーザーフォームが表示されない』(まろ) ページの最後に飛ぶ

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

 

『ボタン作成後ユーザーフォームが表示されない』(まろ)

下記のコードでファイルを開いた際にsheet1にボタンを1つ作成し、ユーザーフォームをモードレスで表示させたいのですがユーザーフォームが開かずうまくいきません。(ボタンは作成されます)

modal表示ならユーザーフォームが表示されること、ボタン作成コードなしならモードレスでも正しく表示されることは確認済みです。
ユーザーフォームはテスト用に何もコードを記入していないものを使用しています。
表示されない理由、改善方法等ありましたら宜しくお願いします。

Private Sub Workbook_Open()

    With Sheet1.OLEObjects.Add(ClassType:="Forms.CommandButton.1", _
      Link:=False, _
      DisplayAsIcon:=False, _
      Left:=5, _
      Top:=5, _
      Width:=114, _
      Height:=45)
    End With
    UserForm1.Show 0
End Sub

< 使用 Excel:Excel2003、使用 OS:WindowsXP >


 Workbook_Openが終了した後に時間差実行をしてはいかがですか。

   UserForm1.Show 0

 これをやめて

    Application.OnTime Now(), "ThisWorkbook.FormShow"

 で、ThisWorkbookモジュールに以下を追加。

 Sub FormShow()
    UserForm1.Show vbModeless
 End Sub

 ところで、シート上の図形はいったんセットすれば、削除しない限りシート上に残るわけですが
 なぜ、ブックを開くたびに、CommandButtonを 新規作成するのでしょうか?
 シートにあらかじめ(手作業で)挿入しておけば、VBA処理は不要ですよねぇ。

(β) 2016/06/08(水) 05:49


 追伸です。

 モーダル表示のユーザーフォームが、力強い健康優良児であるのに比べ、モードレス表示のユーザーフォームは
 少し、ひよわな深層の令嬢といったイメージでしょうか。
 Workbook_Open は、まだブックが開かれきっていないというか、このプロシジャが End Sub になってはじめて
 スタンバイになるというか、End Sub時にVBAプロジェクトのリセットが行われるようです。
 (Workbook_Open で、このプロジェクト内で定義したモジュールレベル、あるいはプロジェクトレベルの変数に、値を格納しても
  ブックが立ち上がった時には、その変数は初期化されています)

 プロジェクトリセットが発生しても、健康優良児のモーダルフォームはびくともしませんが、
 ひよわなモードレスフォームは、消されてしまうようですね。

(β) 2016/06/08(水) 06:00


早速のコメントありがとうございます。
理由がわからずに悩んでましたが、ひよわなご令嬢ならしょうがないです。
Application.OnTime Now(), "ThisWorkbook.FormShow"
を使用する事で期待してた動作が得られました。

コマンドボタン作成については使用中に誤って削除する事を考えて、起動時にボタン有無の判定後無ければ作るような感じにできたらと思っています。
果たして書き方は正しいのか、もう少し有無の判定のスマートな書き方が出来ればとは思いますが。

ユーザーフォーム表示時はボタンを非表示、ユーザーフォーム非表示時はボタンを表示する等の為にuserform1やWorkbook_Openのコード中にsheet1.test.visible = true,false等書いていたのですがボタン作成時はもともとそんなボタンがなかった為かエラーがでてしまい試行錯誤中です…。

Dim A As Integer
Dim i As Integer
Dim X As Boolean
A = Sheet1.OLEObjects.Count
X = False

 If A <> 0 Then
  For i = 1 To A
    If Sheet1.OLEObjects(i).Name = "test" Then
     X = True
    End If
  Next i
 End If
 If X = False Then
 〜ボタン作成〜
 End if
(まろ) 2016/06/08(水) 06:58

 そういう要件であれば、ループさせず、以下のように強引に有無判定することも可能ですね。

    Dim ck As Shape

    On Error Resume Next
    Set ck = ActiveSheet.Shapes("test")
    On Error GoTo 0

    If ck Is Nothing Then
        'ボタン作成
    End If

 それと、昨今のPC環境では 整数を As Integer と記述する意味は全くといっていいほどありません。
 行関連の変数の場合、逆に その値が Integer変数の最大値を超える可能性もある環境(2003 の 65536 でも 超えてしまいます)
 ですので、何も考えず、整数は As Long と記述するようにしたほうがよろしいかと思います。

(β) 2016/06/08(水) 08:15


 >End Sub時にVBAプロジェクトのリセットが行われるようです。
 > (Workbook_Open で、このプロジェクト内で定義したモジュールレベル、あるいはプロジェクトレベルの変数に、
 >値を格納してもブックが立ち上がった時には、その変数は初期化されています)

 これは一般論ではない。「リセット」は、ワークシート上にアクティブXコントロールをプログラムで動的に作成
 しているためだ。通常はPublic変数の値は保持される。

 ただし、ヘルプには「プロシージャの実行が終了したら、Public変数の値の保持は保証されない」旨の記述が
 あるから、「通常はPublic変数の値は保持される」と思ってプログラムを書くのもあまり好ましくない。
 まあ、要はスコープは必要最小限に絞った方が良いということだ。

 なお、上記のリセット動作自体は一種のバグみたいなものとの見方もある。

(とおりすがり) 2016/06/08(水) 08:50


 あぁ、そうですね!。
 ろくに検証しないで(一応したのですが検証の仕方がわるかっったです)
 申し訳ありません。

 とおりすがりさん指摘のとおり、プロジェクトリセットは ActiveXの生成で引き起ったものですね。

 いずれにしても

 >>使用中に誤って削除する事を考えて

 確かに正論かもしれませんが、これを考えるときりがないと思いますが?
 たとえば、"一覧表"という名前のシートを相手にする処理コードを書いた。
 でも、操作者が、うっかりと そのシート名を変更したり、削除したりするかもしれない。
 なので、ブックオープン時に、そういったものがちゃんとあるかどうかチェックする??

 ふつうはそうしませんよね。

 勝手に変更させたくない場合は、ブックの保護やシートの保護、セルのロック、コントロールのロック。
 こういったものを組み合わせて設定しておくのが常道ではないですか?

(β) 2016/06/08(水) 14:22


とおりすがりさん、βさんコメントありがとうございます。
有無の判定方法、型指定の件勉強になります。
確かにありとあらゆる可能性を考えたらきりがないですし、動的なボタン作成等はひとまず置いて考えようと思います。
また何かありましたら宜しくお願いします。
ありがとうございました。
(まろ) 2016/06/08(水) 23:19

コメント返信:

[ 一覧(最新更新順) ]


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