意外と簡単!ExcelVBAでカウントダウンタイマーを作る方法
作ってみたら意外と少ないコードでできるもんだなぁと思ったのでご紹介。わたしは当時Excel2003で作りましたが、そんなに特殊なコードは使ってないので恐らく2007以降でも動く…はずです(たぶん)。実用的かどうかはさておき、勉強のとっかかりにどうぞー。
実装
標準モジュール
ではまず、B2セル
に分、D2セル
に秒の数値が入るようにシートに記入して(枠はなくても構いません)、こちらの記事を参考にプログラム起動用のボタンを作ってみてください。標準モジュールに書くコードはこちらです。
Public rng As Double '一時停止時間格納用 Sub timer() Dim limit As Date, cnt_d As Double limit = DateAdd("s", Range("D2"), Time) '現在時刻に指定秒を足す limit = DateAdd("n", Range("B2"), limit) '現在時刻に指定分を足す rng = 0 '一時停止の時間リセット UserForm1.Show vbModeless 'タイマーをモードレス表示 UserForm1.Repaint '強制表示 Do cnt_d = (DateDiff("s", Time, limit) + rng) / 60 '指定時刻 - 現在時刻 (+ 一時停止) を秒で表して60で割ったもの UserForm1.TextBox1 = Int(cnt_d) & ":" & Format(Round((cnt_d - Int(cnt_d)) * 60, 0), "00") '分:秒 で表示 If UserForm1.TextBox1 = "0:00" Then Exit Do 'ゼロになったらDoを抜ける DoEvents 'イベントを実行 Loop End Sub
コピペして貼り付けてください。プロシージャ名が「timer」なので、ボタンへの登録の際ご注意くださいね。
ユーザーフォーム
Visual Basic Editorの[挿入]→[ユーザーフォーム]を選択すると、空のUserForm1
というものができます。
図のようにツールボックスから、ラベル、テキストボックス、コマンドボタンをひとつずつ配置します。(ラベルはプログラム上使っていないので、なくても動きます)
※ツールボックスが出ていない場合は、[表示]→[ツールボックス]を押してみてください。
ユーザーフォームのコード
図の部分のUserFrom1を右クリック→[コードの表示]をクリックして、そこに以下をコピペします。
Private Sub CommandButton1_Click() Dim rng_s As Date rng_s = Time 'ストップボタンを押した時刻を取得 MsgBox ("再開する場合はボタンを押してください") 'メッセージボックス rng = rng + DateDiff("s", rng_s, Time) 'ストップしていた間の秒数を取得して上書き End Sub Private Sub UserForm_Terminate() End '終了時にDoを抜ける End Sub
はい、できました!
Excelに戻って、分と秒にお好きな数値を入れて、スタートボタンを押してみてください。意外と簡単ですよね?
解説
主に、3つの変数で出来ています。
- limit … 現在時刻に指定分・指定秒を足した、到達時刻
- cnt_d … 到達時刻から現在時刻を引いた秒数(一時停止時間もあればプラス)/60
- rng … 一時停止していた秒数
limit
からTime(現在時刻)
を引いて、のちの計算のため60で割ってあるのがcnt_d
です。日付や時間の差を計算してくれる関数、DateDiff
は分、秒など特定の形式でしか表せないため、秒で出したものを60で割ったりなんかごねごねして、分:秒の形に成形しています。もしかしてもっとスマートなやり方あるのかな_(┐「ε:)_
そのため、秒が1桁になったときに頭にゼロがつかないのがちょっと気持ち悪いところです。条件つけて1桁だったら頭にゼロを、ってことも出来るんですが、それで無駄なタイムラグとか生まれるのがやだなーと思って実装しませんでした。
やっぱり、Format(なかみ, "00")
で括って1桁でも頭にゼロがつくようにしてみました。ちょっと入れ子すぎな感じもしますがw、やっぱゼロがあったほうが見た目が良いですねー。
rng
はストップボタンを押してから再開するまでの秒数を格納しています。モジュールとユーザーフォーム両方で使う変数なので、Public変数
で宣言しています。
一時停止機能がいらなければ、rng
の変数宣言も、ユーザーフォームのコードもほとんどいらないですね。10~12行目のフォームが閉じるときのEnd
だけは必要です。
いかがでしたでしょうか?良かったら作ってみてくださいね!
追記
分:秒の形に成形するために60で割ったりなんだりやってたんですが、もっとシンプルな方法があるようでして、その部分を書き直しました。
標準モジュール
Public rng As Double '一時停止時間格納用 Sub timer() Dim limit As Date, cnt_d As Double limit = DateAdd("s", Range("D2"), Time) '現在時刻に指定秒を足す limit = DateAdd("n", Range("B2"), limit) '現在時刻に指定分を足す rng = 0 '一時停止の時間リセット UserForm1.Show vbModeless 'タイマーをモードレス表示 UserForm1.Repaint '強制表示 Do cnt_d = DateDiff("s", Time, limit) + rng '指定時刻 - 現在時刻 (+ 一時停止) UserForm1.TextBox1 = Format(TimeSerial(0, 0, cnt_d), "nn:ss") '分:秒 で表示 If UserForm1.TextBox1 = "00:00" Then Exit Do 'ゼロになったらDoを抜ける DoEvents 'イベントを実行 Loop End Sub
ハイライト部分が変更されています。TimeSerial
という関数があるんですね…!しらなかった…!
こちらの回答コードより勉強させて頂きました。私のコードは役に立たなかったようで…すみません(;´Д`)
2017/9/12追記
一時停止中もシートの操作ができるようにというリクエストをいただいたので、そちらの書き方もコメント欄に追記しました。
ExcelVBAに興味をお持ちの方は、こちらの記事もどうぞ!
- これからExcelのマクロを始めたいという方に!簡単な練習問題作りました。
- 私がExcelVBAでよく使う便利なコード・スニペットまとめ
- プログラム初心者さんへ贈る、エラーが起きたら試してみて欲しいこと
- ExcelVBAのクラスモジュールって何?という人向けの使い方まとめ
書籍を執筆しています。
7件のコメント
参考になりましたが、一時停止している間にエクセルシートを障ることが出来ません。(メッセージボックス表示の為)なにかメッセージボックスの表示でなく、フォームのボタンで再開できないでしょうか
藤田さん、コメントありがとうございます。
以下のようにすればできるんじゃないかと思います。
UserForm1
のLabel1
をメッセージ用に使います。Module↓
UserForm↓
ありがとうございます。やってみます。
できました!!
ばっちりです。
ありがとうございました。
よかったですー!
すぐに返事をしていただいてたのに見てなくてすみませんでした。どんなかたかブログ全体を拝見させていただいたら、なんとウエブでいろいろ検索しているときに拝見したページばかりでした。すごくお世話になっていました。漫画もツィッターで見かけたと思います。お忙しい中、著名な方に個人的な対応していただいて感謝しています。
そんなそんな、滅相もございません。レスポンスもらえることって少ないので嬉しかったです。ほかの記事もお役に立てていたようで光栄です(*´ω`*)
コメントは承認制ですので、反映までしばらくお待ち下さい。(稀にスパムの誤判定にて届かないこともあるようですので、必要な際はお問い合わせからお願い致します。)
YouTubeでQ&Aコンテンツを企画しています
運営しているYouTubeチャンネルで、ご相談やご質問を募集しています。動画のコメントやお問い合わせページからお気軽にご相談をお寄せください。