VBA練習問題
VBA100本ノック 70本目:ステータスバーに1秒ごとに時刻が表示

VBAを100本の練習問題で鍛えます
公開日:2021-01-19 最終更新日:2021-09-22

VBA100本ノック 70本目:ステータスバーに1秒ごとに時刻が表示


ブックが開かれたら、ステータスバーに1秒ごとに時刻を表示する問題です。


ツイッター連動企画です。
ツイートでの見やすさを考慮して、ブック・シート指定等を適宜省略しています。

VBAテスト用のサンプルデータはご自身でご用意ください。


出題

出題ツイートへのリンク

#VBA100本ノック 70本目
ブックが開かれたら、自動的にステータスバーに1秒ごとに時刻が表示されるようにしてください。
ただし、1分後には時刻表示を終了してください。
※セル入力中は、時刻は更新されなくて構いません。


VBA作成タイム

この下に頂いた回答へのリンクと解説を掲載しています。
途中まででも良いので、できるだけ自分でVBAを書いてみましょう。


他の人の回答および解説を見て、書いたVBAを見直してみましょう。


頂いた回答

解説

「セル入力中は、時刻は更新されなくて構いません。」
つまりこれは時刻表示している間もセル入力出来なければならないという事です。
普通の方法としては2通りあります。
DoEvents関数
Application.OnTimeメソッド
まずはDoEvents関数から
時間計算と1秒ごとにする部分は様々だと思います。

Private Sub Workbook_Open()
  Dim dtStart As Date: dtStart = Now()
  Dim dtStop As Date: dtStop = DateAdd("s", 60, dtStart)
  Dim dtNext As Date: dtNext = dtStart
  
  Do While Now() <= dtStop
    If Now() >= dtNext Then
      dtNext = DateAdd("s", 1, dtNext)
      Application.StatusBar = Format(Now(), "hh:mm:ss")
    End If
    DoEvents
  Loop
  
  Application.StatusBar = False
End Sub


Application.OnTimeは、マクロが起動される時刻を指定します。
1秒ごとにマクロを起動することで時刻表示させることが出来ます。
DoEventsとOnTimeは、どちらも一長一短はあります。
OnTimeのサンプルVBAと若干の解説を記事補足に書きました。

※2021/09/21現在、Office365で上記が正しく動作しなくなっています。
補足の下に「追記」に対応VBAを掲載しました。


補足

時刻取得にはNow()を使っています。
TimeやTimerを使った回答も見受けられましたが、これらは午前0時からの時刻なので0時を挟む可能性がある場合は都合が悪いことになります。

DoEvents関数
Application.OnTimeメソッド
実行中の大きな違いとしては、
・CPU使用
・カーソルのちらつき
・セル編集中の時刻更新
・VBE編集可否

DoEvents
・CPUの1スレッドを占有
・カーソルはちらつかない
・セル編集中も時刻更新される
・VBE編集はできない

マクロ VBA 100本ノック

OnTime
・時刻表示する一瞬だけ
・カーソルがちらつく
・セル編集中は時刻更新されない
・VBE編集できる

環境により若干の違いがあるかもしれませんが、概ねこのような違いがあります。
一長一短はありますが、1秒ごとに1分間ということならどちらでも良いと思います。
もし1分ごとに1時間というような場合は、DoEventsでは1時間マクロが動きっぱなしになってしまいますので、いささか都合が緩いように思います。
このような場合は、Application.OnTimeを使ったほうが良いでしょう。

Application.OnTimeは、マクロが起動される時刻を指定するものです。
したがって、1秒後の指定は、
Now() + 1秒
このように指定します。
※1秒の書き方はいろいろあります。

ブックモジュール
Private Sub Workbook_Open()
  Call VBA100_70_01
End Sub

標準モジュール
Public Sub VBA100_70_01()
  Static dtStart As Date
  If dtStart = 0 Then dtStart = Now()
  If Now() > dtStart + DateSerial(0, 0, 60) Then
    Application.StatusBar = False
    Exit Sub
  End If
  Application.StatusBar = Format(Now(), "hh:mm:ss")
  Call Application.OnTime(Now() + TimeSerial(0, 0, 1), "VBA100_70_01")
End Sub

上記では、Static変数を使っていますが、モジュールレベル変数を使っても良いでしょう。


追記

マクロ VBA100本ノック
https://twitter.com/yamaoka_ss/status/1440344244267282453

現象確認しました。
最近のupdateで挙動が変化したようです。
本来、添付画像のようにOnTimeで切り離した方が良いのですが、本解答作成時には問題なかったので先の掲載のとうりとしていました。
※記事には本件を追記します。
※現在でも365以外(2019,2013,2010で確認)では問題なく動いています。

ThisWorkbook
Private Sub Workbook_Open()
  Application.OnTime [Now()+"0:0:0.1"], "VBA100_70_01"
End Sub

標準モジュール
Sub VBA100_70_01()
  Dim dtStart As Date: dtStart = Now()
  Dim dtStop As Date: dtStop = DateAdd("s", 60, dtStart)
  Dim dtNext As Date: dtNext = dtStart
 
  Do While Now() <= dtStop
    If Now() >= dtNext Then
      dtNext = DateAdd("s", 1, dtNext)
      Application.StatusBar = Format(Now(), "hh:mm:ss")
    End If
    DoEvents
  Loop
 
  Application.StatusBar = False
End Sub

上記の通りですが、もともと最初に掲載したVBAはWorkbook_Openの途中で停止させているので、あまりよろしくおりません。
Workbook_OpenでApplication.OnTimeを使うことにより次のプロシージャーを切り離しています。

Application.OnTimeは、そこで停止することなくプロージシャーの起動予約をするだけで次に進みます。
したがってWorkbook_Openを抜けて終了するので、期待した通りに動作するようになります。


サイト内関連ページ

第120回.OnTimeメソッド|VBA入門
・OnTimeメソッドの構文 ・OnTimeメソッドの使用例 ・OnTimeメソッドの実践例
時刻になったら音を鳴らして知らせる(OnTime)
・作成するシート ・標準モジュールのVBAコード ・VBAコードの解説 ・ビープ音を変更したい場合 ・時刻になったら音を鳴らして知らせる最後に
文字列としてのプロシージャー名を起動する方法(Run,OnTime)
文字列変数の中にプロシージャー名が入っていて、そのプロシージャーを起動したい場合になります、実際には、そのような構造が良いとは思えませんが、知っていればプログラミングの幅が広がります。使うのは、OnTimeメソッドorRunメソッドになります。
VBAでのタイマー処理(SetTimer,OnTime)
・Application.OnTime メソッド ・WindowsAPI:SetTimer関数 ・最後に




同じテーマ「VBA100本ノック」の記事

67本目:ComboBoxとListBox

・出題 ・頂いた回答 ・解説 ・補足 ・サイト内関連ページ
68本目:全テキストボックスの転記
・出題 ・頂いた回答 ・解説 ・補足 ・サイト内関連ページ
69本目:ダブルクリックでセル結合を解除
・出題 ・頂いた回答 ・解説 ・補足 ・サイト内関連ページ
70本目:ステータスバーに1秒ごとに時刻が表示
71本目:パワーポイントへグラフを貼り付け
・出題 ・頂いた回答 ・解説 ・補足 ・サイト内関連ページ
72本目:ITをDXに変換(文字列操作)
・出題 ・頂いた回答 ・解説 ・補足 ・サイト内関連ページ
73本目:新規ブックにボタン作成しマクロ登録
・出題 ・頂いた回答 ・解説 ・補足 ・サイト内関連ページ
74本目:1シート複数表をDB形式に変換
・出題 ・頂いた回答 ・解説 ・補足 ・サイト内関連ページ
75本目:ログインフォームの作成
・出題 ・頂いた回答 ・解説 ・補足 ・サイト内関連ページ
76本目:ボタンの表示名の位置へ移動
・出題 ・頂いた回答 ・解説 ・補足 ・サイト内関連ページ
77本目:シート挿入イベント
・出題 ・頂いた回答 ・解説 ・補足 ・サイト内関連ページ


新着記事NEW ・・・新着記事一覧を見る

VBA10大躓きポイント(初心者が躓きやすいポイント)|VBA技術解説(2024-03-05)
テンキーのスクリーンキーボード作成|ユーザーフォーム入門(2024-02-26)
無効な前方参照か、コンパイルされていない種類への参照です。|エクセル雑感(2024-02-17)
初級脱出10問パック|VBA練習問題(2024-01-24)
累計を求める数式あれこれ|エクセル関数応用(2024-01-22)
複数の文字列を検索して置換するSUBSTITUTE|エクセル入門(2024-01-03)
いくつかの数式の計算中にリソース不足になりました。|エクセル雑感(2023-12-28)
VBAでクリップボードへ文字列を送信・取得する3つの方法|VBA技術解説(2023-12-07)
難しい数式とは何か?|エクセル雑感(2023-12-07)
スピらない スピル数式 スピらせる|エクセル雑感(2023-12-06)


アクセスランキング ・・・ ランキング一覧を見る

1.最終行の取得(End,Rows.Count)|VBA入門
2.RangeとCellsの使い方|VBA入門
3.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
4.繰り返し処理(For Next)|VBA入門
5.変数宣言のDimとデータ型|VBA入門
6.ブックを閉じる・保存(Close,Save,SaveAs)|VBA入門
7.並べ替え(Sort)|VBA入門
8.条件分岐(IF)|VBA入門
9.セルのクリア(Clear,ClearContents)|VBA入門
10.マクロとは?VBAとは?VBAでできること|VBA入門




このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。


記述には細心の注意をしたつもりですが、
間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
掲載のVBAコードは動作を保証するものではなく、あくまでVBA学習のサンプルとして掲載しています。
掲載のVBAコードは自己責任でご使用ください。万一データ破損等の損害が発生しても責任は負いません。



このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
本文下部へ