[[20160328213502]] 『C#のTimerのような機能』(ゲン) ページの最後に飛ぶ

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

 

『C#のTimerのような機能』(ゲン)

C#のTimerのような機能を探していますがなかなか見つかりません。

似たようなものでOnTimerというものを見つけましたが、
C#のTimerのようなプロパティを設定するには独自でクラス化しなければなりません。

私を含めて数人でVBAプログラムを作る予定なので、なるべくC#のTimerのような
説明しやすい簡素な形の機能を探しております。

ないものは作るしかありませんがどなたかご存じないでしょうか。

OnTimerを使っていた時にセルの入力中は呼び出しプロシージャが起動せずに、
入力完了後にプロシージャが起動しました。これはOnTimerの設定によって
入力中にセルの値が更新されることもあるのでしょうか。

< 使用 Excel:Excel2007、使用 OS:Windows7 >


 > OnTimerを使っていた時にセルの入力中は呼び出しプロシージャが起動せずに、 
 > 入力完了後にプロシージャが起動しました。これはOnTimerの設定によって 
 > 入力中にセルの値が更新されることもあるのでしょうか。

 入力編集中は、タイマーに限らず、マクロ全般を動作させることはできません。仕様です。

 前半部分は、
 まずは、C#のコードと機能を説明してみてはどうでしょうか?

 # 一定時間後にマクロ実行したり、
 # タイマーをリセットすることは簡単なコードでできるので、
 # クラスとして再構成する必要が殆どない、というのが実感じゃないでしょうか。
 # 見かけたことはないですね。どなたかご存じでしたら。
 # 必要とされるかたが作るのが原則でしょうね。 

(γ) 2016/03/28(月) 22:34


説明が足らずすみませんでした。

C#のTimerはプロパティからTimerイベントの機能の有効、無効。
プロシージャ呼び出し秒数(ミリ秒)の設定ができるのですが、OnTimerそのものには
そのような機能がありません。

なのでそのようなプロパティを内蔵したクラスを作る必要があるのですが、
そこまでする必要があるのか確認するためにコメントを書き込みました。

うーむ。やはり見たことがないですか。難しいですが自作クラス作成を覚悟した方がよさそうですね。
(ゲン) 2016/03/28(月) 23:38


OnTimerというのは知りませんが、OnTimeなら少しはわかります。
ミリ秒ではなく秒なら、タイマー予約、無効設定、プロシージャの指定は可能ですね。
ミリ秒に重点があるなら、たしかにOnTimeでミリ秒までの指定はできませんね。
"excel vba ontime ミリ秒"で検索すると、関連情報がありますので確認してください。

この際、是非作成してもらって、こちらで公開してもらうと有り難いですね。

(γ) 2016/03/29(火) 06:21


 >>うーむ。やはり見たことがないですか。難しいですが自作クラス作成を覚悟した方がよさそうですね。 

 失礼します。

 γさんは、このあたりのことは、もちろん すべて把握されたうえで、コメントしておられると思います。
 ただ、そのために、「クラス化」なんてしなくても、簡単にできるんじゃないですかと指摘しておられるんだと思いますよ。

 私自身は C#の知識が皆無ですので、そこで実現できていることが、どういうものなのかがわからず、
 コメントをすることができなかったのですが、もしかしたらということで。

 「SetTimer」で検索してみてください。ネット全体の検索でもいいですし、「学校」の全文検索から検索されても
 たくさんの記事がでてきます。
 もし、この機能のことを言っておられるなら、ミリ秒単位の設定もできますし、セル編集中の実行も可能ですし 必要なら編集の強制解除も可能です。

 要件を勘違いしていたらごめんなさい です。

(β) 2016/03/29(火) 06:44


 ミリ秒といえば、知っているのこれぐらい(>_<)違いますね。

 Option Explicit
 Declare Function GetTickCount Lib "KERNEL32.DLL" () As Long '■時間計測(ミリ秒)
 Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) '★処理を停止(ミリ秒)
 Sub test()
     Dim StartTime As Long: StartTime = GetTickCount '■時間計測開始(ミリ秒)
     Dim i As Integer, str As String
     str = vbCrLf & _
           "春眠不覚暁" & vbCrLf & _
           "しゅんみんあかつきをおぼえず" & vbCrLf & _
                                            vbCrLf & _
           "処処聞啼鳥" & vbCrLf & _
           "しょしょていちょうをきく" & vbCrLf & _
                                        vbCrLf & _
           "夜来風雨声" & vbCrLf & _
           "やらいふううのこえ" & vbCrLf & _
                                  vbCrLf & _
           "花落知多少" & vbCrLf & _
           "はなおつることしるたしょうぞ" & vbCrLf & ""

     ReDim arr(1 To Len(str))
     Shell "Notepad.exe", 1
     For i = 1 To UBound(arr)
         arr(i) = Mid(str, i, 1)
         SendKeys arr(i)
         Sleep 100 '★処理を停止(ミリ秒)
     Next i
     SendKeys "{Enter}"

     SendKeys "3" & vbCrLf
     SendKeys "{Enter}"
     Sleep 1000
     SendKeys "2" & vbCrLf
     SendKeys "{Enter}"
     Sleep 1000
     SendKeys "1" & vbCrLf
     SendKeys "{Enter}"
     Sleep 1000

     SendKeys "%{F4}{RIGHT}{Enter}" '保存しないで、メモ帳を閉じる。
     MsgBox "テキスト入力処理時間:" & _
            (GetTickCount - StartTime) & "[ミリ秒]" '■時間計測終了(ミリ秒)
 End Sub

(マリオ) 2016/03/29(火) 07:07


検索しましたら、こういうものがあるようです。
http://www.h3.dion.ne.jp/~sakatsu/Excel_Tips15.htm
SetTiemr利用のものですね。
1000倍して秒としてつかっているので、1000倍しなければ使えるのか、
なにがしかの問題がありうるので、あえて秒にしているのでしょうか?

(γ) 2016/03/29(火) 07:10


Excelは表計算アプリであり、システム開発用の高級言語とは違いますので、ミリ秒単位の処理は不要と思います。
どのようなシーンで、ミリ秒が欲しいのでしょうか? 場合によっては、既知の方法で対応できるかも知れません。

まず、VBAにはTimer関数が標準で備わっており、小数点以下2桁の秒まで得ることができます。
ただしこれは、0時を起点とした経過秒なので、日またぎする場合を考慮した処理にする必要があります。

次に、ご存じなのはこちらと思いますが、Application.OnTime メソッドで、割り込み処理のように、時間指定で
プロシジャ起動できる機能があります。現在時間を指定する事で、即時実行させることもできますが、基本的に秒単位になります。

もっと細かい単位が必要な場合、APIを使ってシステム時刻を得る事になります。開始時と終了時に値を得る事で、
ストップウォッチ程度ならば簡単にミリ秒の精度が得られます。または、APIのSleep命令でミリ秒のウェイトを
実現できますが、この場合は処理時間分ずつ起点がずれる事を考慮しなければなりません。

どうしても割り込み処理にしたいならば、クラスを自作する事で実現できそうですが、そこまでするより、
ミリ秒単位の処理は素直にC#で作成して、結果だけ別周期でExcel表示してはいかがでしょうか?
(???) 2016/03/29(火) 09:37


 失礼します。

 >>Application.OnTime メソッドで、割り込み処理のように、時間指定で  プロシジャ起動できる機能があります

 ゲンさんのコメントで

 >>セルの入力中は呼び出しプロシージャが起動せずに、 入力完了後にプロシージャが起動しました

 ということがありましたので、セル編集中でも、プロシジャを実行させたいのかなと。
 VBAの世界でそれを実現しようとすれば、たとえば SetTimer だと思うのですが。

(β) 2016/03/29(火) 09:42


ごめんなさい。
昨日一度コメントを書き込んだのですが、更新できておらずすみませんでした。
知り合いと相談した結果、難しそうなのでONTimeを使うことで了承を得ました。
みなさま回答ありがとうございます。
(ゲン) 2016/03/30(水) 21:33

知り合いがどうこうということはこの際関係ないです。
Timerイベントの機能の有効、無効、イベントプロシージャの指定等、
結局どのようなコードで対応することにしたのですか?
それは問題なく把握されているのですか?

ミリセカンドは必要だったのか、必要なかったのか、
必要だとすれば、どんな使い方だったのか。
クラス化するのに何が障害だったのか、
それらについて、簡単にコメントいただきたい。
(γ) 2016/03/31(木) 00:25


 「クラス化」というわれている、そのクラスでどんな機能を実現されようとしているのか、そこが不明ですが
 たとえば、こんなことなのかなぁとコードを書いてみました。

 以下のTestを実行すると 5000ミリ秒後の CheckProc 実行を予約しますが、同時に A1 を編集状態にします。
 OnTime であれば 5秒どころか 100年たってもCheckProcは実行されませんが、以下のコードでは確実に実行されます。
 で、その時にセルが編集中であれば、強制解除した上で A1 を書き換えています。

 Private Declare Function SetTimer Lib "user32" _
  (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerfunc As Long) As Long
 Private Declare Function KillTimer Lib "user32" _
  (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long

 Sub test()
    SetTimer 0, 0, 5000, AddressOf CheckProc  'セル編集中でもマクロを実行
    With Range("A1")
      .Value = "Hello"
      .Select
    End With
    Application.SendKeys "{F2}" 'セルを編集状態にする
 End Sub

 Private Function CheckProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal idEvent As Long, ByVal SysTime As Long) As Long
    KillTimer 0, idEvent
    If Not Application.CommandBars.FindControl(ID:=18).Enabled Then
        MsgBox "セル編集中です。強制解除して値を書きこみます"
        Application.SendKeys "{ESC}"
        DoEvents
    End If
    Range("A1").Value = "GoodBye"
 End Function

(β) 2016/03/31(木) 11:03


ありがとうございます。こういうのを待ってました。

実は知り合いからはOnTimerはあるけど使いづらいから
別のクラスを探してほしいといわれたのですが、
VBAのタイマ回りのことは全く知らなかったので戸惑ってました。

OnTimerで定期更新ができることはできたのですが、入力中に他のセルの値が
変わらないので方法はないのか探したのですが見つからなかったので尋ねてみました。

本当にありがとうございます。

(ゲン) 2016/03/31(木) 20:55


コメント返信:

[ 一覧(最新更新順) ]


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