[[20090601090523]] 『点滅とタイマ−の両方のマクロを作動させたい』(みこ) ページの最後に飛ぶ

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

 

『点滅とタイマ−の両方のマクロを作動させたい』(みこ)

 以前、点滅とタイマ−のマクロを
ご教授していただきました。
どちらも、個別に作動してくれるのですが、
両方のコ−ドを入力すると、
タイマ−のみしか作動しないのです。
シ−トを開いたら 両方作動させるには、
どのようにしたらよいのでしょうか?
ご教授よろしくお願いします。
まだまだ、マクロは精進中です。

[[20090420091851]] 『指定のセルの点滅停止ボタン』(みこ)

[[20090513133425]] 『タイマ-を表示させたい』(みこ)


 両方とも開始から終了までが一つのループ処理になっているので処理が終わらないと、
 他のマクロ処理ができるようになっていません。

 一つのループの中で、両方の処理を行うようにすることも可能ですが、このような場合
 は OnTime メソッドを使用すれば独立した処理として実現できます。

 (1)ThisWorkbook モジュールの下に下記を置きます。
 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
 Private Sub Workbook_Open()
    ActiveSheet.Protect Password:="pass", DrawingObjects:=True, contents:=True, UserInterfaceonly:=True
    startTimer
    startBlink
 End Sub
 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

 (2)標準モジュールの下に下記を置きます。
 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
  Option Explicit

 '--- 点滅用大域変数 ---------
    Public Const BLINK_CELLS = "A11,G1"
    Public Const ON_COLOR = 3
    Public Const OFF_COLOR = 2

    Public blinkOn As Boolean
    Public originalFonts() As Variant
    Public objRange As Range
    Public nextBTime As Variant

 '--- タイマー用大域変数 ---------
    Public nextTTime As Variant
    Public startTime As Variant

 '------------------------------------------------------
 Sub startBlink()
 '------------------------------------------------------
    MsgBox "今日は、" & Day(Now) & "日です。入力する場合は、日付点滅を解除して入力してください。", _
    vbInformation, Year(Now) & "年" & Month(Now) & "月"

    Set objRange = ActiveSheet.Range(BLINK_CELLS)
    ReDim originalFonts(1 To objRange.Count)
    Dim r As Range
    Dim i As Long
    i = 1
    For Each r In objRange
        originalFonts(i) = r.Font.ColorIndex
        i = i + 1
    Next
    Blink
 End Sub

 '------------------------------------------------------
 Sub stopBlink()
 '------------------------------------------------------
    On Error Resume Next
    Application.OnTime nextBTime, "Blink", , False
    On Error GoTo 0
    Dim r As Range
    Dim i As Long
    i = 1
    For Each r In objRange
        r.Font.ColorIndex = originalFonts(i)
        i = i + 1
    Next

 End Sub

 '------------------------------------------------------
 Sub Blink()
 '------------------------------------------------------
    Dim color As Integer
    Dim r As Range

    If blinkOn = True Then
        color = ON_COLOR
        blinkOn = False
    Else
        color = OFF_COLOR
        blinkOn = True
    End If
    For Each r In objRange
        r.Font.ColorIndex = color
    Next
    nextBTime = Now + TimeValue("0:0:01")
    Application.OnTime nextBTime, "Blink"
 End Sub

 '------------------------------------------------------
 Sub startTimer()
 '------------------------------------------------------
    startTime = Now
    printTimer
 End Sub

 '------------------------------------------------------
 Sub stopTimer()
 '------------------------------------------------------
    On Error Resume Next
    Application.OnTime nextTTime, "printTimer", , False
    On Error GoTo 0
 End Sub

 '------------------------------------------------------
 Sub printTimer()
 '------------------------------------------------------
    .TextBoxes("w_text").Text = Format(Now - startTime, "h:mm:ss")
    nextTTime = Now + TimeValue("0:0:01")
    Application.OnTime nextTTime, "printTimer"
 End Sub
 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

 (3)Sheetモジュールの下に下記を置きます。
 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
 Private Sub CommandButton1_Click()
    stopBlink
 End Sub

 Private Sub CommandButton2_Click()
    stopTimer
 End Sub
 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

 ボタンの名前や表示対象は適宜変更してください。
 (Mook)


 このようなコードを記述しても、
 >タイマ−のみしか作動しないのです。
 というコードを記述して下さい。そうしないとこのような掲示板の意味が半減してしまいますよ!!

 新規ブックにて試してみてください。

 標準モジュール(Module1)に

 '=================================================================
 Sub 準備()
    Dim r As Range
    With Worksheets("sheet1")
       Set r = .Range("l2:m3")
       With .Buttons.Add(r.Left, r.Top, r.Width, r.Height)
          .Caption = "停止"
          .OnAction = "stop_tenmetu"
       End With
       With .TextBoxes.Add([d1].Left, [d1].Top, [d1].Width, [d1].Height)
          .Name = "w_text"
          .HorizontalAlignment = xlRight
          .LockedText = False
       End With
       .Range("a11,g1").Value = "ichinose"
    End With
    Set r = Nothing
 End Sub

 まず上記の「準備」を実行してください。

 Sheet1に
 停止用ボタンと時刻表示用のテキストボックスが作成されます(点滅対象は、A11とg1です)

 上記の準備を実行した後に別の標準モジュール(Module2)に
 点滅を管理するプロシジャー群

 '=============================================================================
 Option Explicit
 Private t_selr As Range
 Private t_cid(1 To 2) As Long
 Private t_scid() As Long
 Sub tenmetu_init(ByVal rng As Range, ByVal col1 As Long, ByVal col2 As Long)  '点滅準備処理
    Dim crng As Range
    Dim g0 As Long
    Set t_selr = rng '点滅させるセル範囲
    t_cid(1) = col1                   '点滅色
    t_cid(2) = col2                   ' 〃
    ReDim t_scid(1 To t_selr.Count)
    g0 = 1
    For Each crng In t_selr
       t_scid(g0) = crng.Font.ColorIndex
       g0 = g0 + 1
    Next
    t_selr.Font.ColorIndex = t_cid(1)
 End Sub
 '=============================================================================
 Sub tenmetu_exe() '点滅実行
    With t_selr.Font
       .ColorIndex = .ColorIndex Xor (t_cid(1) Xor t_cid(2))
    End With
 End Sub
 '=============================================================================
 Sub tenmetu_term()  '点滅終了処理
    Dim g0 As Long
    Dim crng As Range
    g0 = 1
    For Each crng In t_selr
       crng.Font.ColorIndex = t_scid(g0)
       g0 = g0 + 1
    Next
    Set t_selr = Nothing
    Erase t_cid()
    Erase t_scid()
 End Sub

 別の標準モジュール(Module3)に点滅と時刻表示を行ったり、停止したりするプロシジャー

  Option Explicit
 '===========================================================================
 Private stop_mv As Boolean
 Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
 Sub tenmetu_and_time()
    Dim nw As Date
    ActiveSheet.Protect Password:="pass", DrawingObjects:=True, _
        contents:=True, UserInterfaceonly:=True
    MsgBox "今日は、" & Day(Now) & "日です。入力する場合は、日付点滅を解除して入力してください。", _
        vbInformation, Year(Now) & "年" & Month(Now) & "月"
    Call tenmetu_init(Range("a11,g1"), 3, 2)
    stop_mv = False
    nw = Now()
    With ActiveSheet
       Do Until stop_mv
          Call tenmetu_exe
          DoEvents
          .TextBoxes("w_text").Text = Format(Now() - nw, "h:mm:ss")
          Sleep 100
          DoEvents
       Loop
    End With
    Call tenmetu_term
 End Sub
 '==================================================================
 Sub stop_tenmetu()
    stop_mv = True
 End Sub

 最後にThisworkbookのモジュールにシートがアクティブになったときのイベント

 Option Explicit
 Private Sub Workbook_SheetActivate(ByVal Sh As Object)
    If Sh Is Worksheets("sheet1") Then tenmetu_and_time
 End Sub
 '==================================================================
 Private Sub Workbook_WindowActivate(ByVal Wn As Window)
    If Wn.ActiveSheet Is Worksheets("sheet1") Then tenmetu_and_time
 End Sub

 一度保存して閉じた後、再度開いて確認してください。

 ichinose


Mook様、ichinose様、

回答ありがとうございました。

Mook様、

Sub printTimer()

 '------------------------------------------------------
    .TextBoxes("w_text").Text = Format(Now - startTime, "h:mm:ss")
    nextTTime = Now + TimeValue("0:0:01")
    Application.OnTime nextTTime, "printTimer"
 End Sub

エラ−表示がでるのですが..

ichinose様、

 >というコードを記述して下さい。

最初はコードを記述したのですが、

未読表示が付かなかったものですから、

このような形文になってしまい申し訳ありません。

ichinose様、いつもながら 解りやすい回答をいただき

感銘しています。

出来ました。

更に質問なのですが

点滅とタイマ−の停止ボタンを

別々にすることは可能なのでしょうか?

そして、

Columns("I:I").ColumnWidth = 0

 Columns("L:L").ColumnWidth = 0

このコ−ドは、

どこにいれたらよいのでしょうか?

もう一点、

点滅の速度のコ−ドってあるのでしょうか?

よろしくお願いします。

(みこ)


 前のソースをコピーしただけなので、不備があったようです。
 Worksheets("Shhet1").TextBoxes("w_text").Text = Format(Now - startTime, "h:mm:ss")
 にしてください(w_text というテキストボックスがある前提ですが)。
 (Mook)


 では、改めて新規ブック(Sheet1というシート名が存在する)にて試してください。

 標準モジュール(Module1)に

 '========================================================================
 Sub 準備()
    Dim r As Range
    With ActiveSheet
       Set r = .Range("n2:o3")
       With .Buttons.Add(r.Left, r.Top, r.Width, r.Height)
          .Caption = "点滅停止"
          .OnAction = "stop_tenmetu"
       End With
       Set r = .Range("n5:o6")
       With .Buttons.Add(r.Left, r.Top, r.Width, r.Height)
          .Caption = "タイマー停止"
          .OnAction = "stop_watch"
       End With
       With .TextBoxes.Add([d1].Left, [d1].Top, [d1].Width, [d1].Height)
          .Name = "w_text"
          .HorizontalAlignment = xlRight
          .LockedText = False
       End With
       .Range("a11,g1").Value = "ichinose"
       .Columns("i:i").Hidden = True
       .Columns("L:L").Hidden = True
    End With
    Set r = Nothing
 End Sub

 まず上記の「準備」を実行してください。

 Sheet1に
 点滅停止用ボタンとタイマー停止用ボタンと時刻表示用のテキストボックスが作成されます
(点滅対象は、A11とg1です)。又、

 Columns("I:I").ColumnWidth = 0 

 Columns("L:L").ColumnWidth = 0
 これと同類コードは、準備に入れました。(シートの体裁を整えるコードだと解釈しました)

 上記の準備を実行した後に別の標準モジュール(Module2)に
 点滅を管理するプロシジャー群

 '==================================================================================
 Option Explicit
 Private t_selr As Range
 Private t_cid(1 To 2) As Long
 Private t_scid() As Long
 '==================================================================================
 Sub tenmetu_init(ByVal rng As Range, ByVal col1 As Long, ByVal col2 As Long) '点滅準備処理
    Dim crng As Range
    Dim g0 As Long
    Set t_selr = rng '点滅させるセル範囲
    t_cid(1) = col1                   '点滅色
    t_cid(2) = col2                   ' 〃
    ReDim t_scid(1 To t_selr.Count)
    g0 = 1
    For Each crng In t_selr
       t_scid(g0) = crng.Font.ColorIndex
       g0 = g0 + 1
    Next
    t_selr.Font.ColorIndex = t_cid(1)
 End Sub
 '==================================================================================
 Sub tenmetu_exe() '点滅実行
    With t_selr.Font
       .ColorIndex = .ColorIndex Xor (t_cid(1) Xor t_cid(2))
    End With
 End Sub
 '==================================================================================
 Sub tenmetu_term() '点滅終了処理
    Dim g0 As Long
    Dim crng As Range
    On Error Resume Next
    g0 = 1
    For Each crng In t_selr
       crng.Font.ColorIndex = t_scid(g0)
       g0 = g0 + 1
    Next
    Set t_selr = Nothing
    Erase t_cid()
    Erase t_scid()
    On Error GoTo 0
 End Sub

 別の標準モジュール(Module3)に点滅と時刻表示を行ったり、それぞれを停止したりするプロシジャー

 '==========================================================================
 Option Explicit
 '===========================================================================
 Private loop_tmt As Boolean
 Private loop_wth As Boolean
 Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
 Sub chk_and_start()
    If loop_tmt = False And loop_wth = False Then
       tenmetu_and_time
    ElseIf loop_tmt = False Then
       loop_tmt = True
    ElseIf loop_wth = False Then
       loop_wth = True
    End If
 End Sub
 '===================================================================================
 Sub tenmetu_and_time()
    Dim nw As Date
    Dim f_false As Long
    ActiveSheet.Protect Password:="pass", DrawingObjects:=True, _
        contents:=True, UserInterfaceonly:=True
    MsgBox "今日は、" & Day(Now) & "日です。入力する場合は、日付点滅を解除して入力してください。", _
        vbInformation, Year(Now) & "年" & Month(Now) & "月"
    Call tenmetu_init(Range("a11,g1"), 3, 2)
    loop_tmt = True
    loop_wth = True
    nw = Now()
    With ActiveSheet
       Do Until loop_tmt = False And loop_wth = False  '変更
          If loop_tmt Then
             If f_false = 1 Then
                Call tenmetu_init(Range("a11,g1"), 3, 2)
             End If
             f_false = 0
             Call tenmetu_exe
          Else
             If f_false = 0 Then
                Call tenmetu_term
                f_false = 1
             End If
          End If
          DoEvents
          If loop_wth Then .TextBoxes("w_text").Text = Format(Now() - nw, "h:mm:ss")
          Sleep 400
'      ↑この400を100〜500の間で変更してみてください。値が少ないほど点滅が速くなります
          DoEvents
       Loop
    End With
    Call tenmetu_term
 End Sub
 '==================================================================
 Sub stop_tenmetu()
    loop_tmt = False
 End Sub
 '==================================================================
 Sub stop_watch()
    loop_wth = False
 End Sub

 最後にThisworkbookのモジュールにシートがアクティブになったときのイベント

 '=================================================================
 Option Explicit
 '=================================================================
 Private Sub Workbook_SheetActivate(ByVal Sh As Object)
    If Sh Is Worksheets("sheet1") Then Call chk_and_start
 End Sub
 '==================================================================
 Private Sub Workbook_WindowActivate(ByVal Wn As Window)
    If Wn.ActiveSheet Is Worksheets("sheet1") Then Call chk_and_start
 End Sub

 一度保存して閉じた後、再度開いて確認してください。

 ichinose


 まぁこのレベルのプログラムでしたら、どのような方法でも動けばよいのだと思いますが、
 OnTime は1秒単位でしか制御できません。
 なので、これより細かい精度では処理できませんが、これを使用する利点はいくつもの
 処理を独立して設定できるという点(処理の追加や削除が簡単)と、処理を占有しません
 ので、これを実行している間も他のマクロ処理を実行できるという点です。

 他にマクロの処理する必要がなく、1秒以下の制御をしたいということであれば、
 ichinose さんのを使用されるとよいかと思います。
 (Mook)

Mook様、

助言ありがとうございました。

ichinose様、

思い通りに出来ました。

詳しく説明して下さって、

嬉しく思っています。

更に閉じる列を増やして記述する場合、

例えばJ列を増やしたい

標準モジュール(Module1)の

.Range("a11,g1").Value = "ichinose"

       .Columns("i:i").Hidden = True
       .Columns("L:L").Hidden = True
    End With
    Set r = Nothing
 End Sub
 
           ↓

.Range("a11,g1").Value = "ichinose"

       .Columns("i:i").Hidden = True
       .Columns("L:L").Hidden = True
       .Columns("J:J").Hidden = True  ←
    End With
    Set r = Nothing
 End Sub
作動させましたが、動作してくれません。

そこで、

標準モジュール(Module1)の

.Range("a11,g1").Value = "ichinose"

                      ←削除
    End With
    Set r = Nothing
 End Sub

標準モジュール(Module3)の

Sub tenmetu_and_time()

    Dim nw As Date
    Dim f_false As Long
    ActiveSheet.Protect Password:="pass", DrawingObjects:=True, _
        contents:=True, UserInterfaceonly:=True

Sub tenmetu_and_time()

Columns("I:I").ColumnWidth = 0 ←

Columns("L:L").ColumnWidth = 0 ←

Columns("J:J").ColumnWidth = 0 ←

    Dim nw As Date
    Dim f_false As Long
    ActiveSheet.Protect Password:="pass", DrawingObjects:=True, _
        contents:=True, UserInterfaceonly:=True

に入れてみました。

動作しました。

問題はないですよね。

ichinose様、Mook様

まだまだ

未熟な私ですが、

今後とも

ご指導宜しくお願いします。

(みこ)


 解決されたみたいですが・・・、

 Columns("I:I").ColumnWidth = 0 ← 

 Columns("L:L").ColumnWidth = 0 ← 

 Columns("J:J").ColumnWidth = 0 ← 

 これらのコードをどのような事情で追加したいのか? の説明がないのではっきり
 どこに挿入すればよい とは言えないのです。

 私は、最初のシートレイオウトをそのようにしたいのであろう と予想して準備というプロシジャーに
 入れました。ここは、シートに初期設定を行うプロシジャーですから、一度実行すれば、
 基本的にはその後は 実行されるフローにはなっていません。

 tenmetu_and_timeに挿入したとの事ですが、隠した列は、再表示される可能性があるのなら、ここでよいですね!!

 >まぁこのレベルのプログラムでしたら

 私は、今回の 「このレベルのプログラム」で 四苦八苦していました。

 この事例ような繰り返し処理では、Excelのキャパシティとの調整が大変なんです。

 私も繰り返しのインターバルが5分とか10分なら、さほど迷わずにOntimeメソッドを選択したと思います。
 今回の場合、単独仕様の場合から考慮すると・・・、

 1 点滅

 1秒以内の繰り返し処理を想像したため、どうしようか? ここで悩みました。
 取りあえず、長い時間の点滅ではないのだろうと勝手に予測し、ループ処理で行うことを決めました。
 この時点では、Ontimeという方法も捨てきれないなあ という思いを残しながら決断です。

 2 タイマー
 この仕様では、割と簡単にループ処理で行くことを決定。
 一つは、長い時間の処理ではないのだろうという予想と秒以下の場合(拡張された場合)
 の対処も簡単そうという理由です。

 今回は、上記の理由でループで処理しました。

 ループという手法を使うと処理を独占という問題にぶつかります。
 これが、Excelの限界なのです。但し、今回のループ処理でも
 Doevent とSleep(API)の使用でCPUの占有率を下げています
 (これがSleepでないと駄目なんです。application.waitでは、占有率は下がらない)
 更にブックの既存イベントをトリガーにループ処理が開始されていますから、
 他のマクロの実行も可能にしています。というより、そのための上記の施しなのですから・・・。

 が、それでも不安定感は否めません。これが取り除かれれば、ループ処理で監視した
 独自イベントが実務でも使えますが、まだその決心がついていません。

 今回の仕様でループ処理にしたもう一つの理由は、ループでの監視というアルゴリズムで
 どれだけ通用するかを質問者さんに試していただきたかったからです。
 この結果は、もう少し時間が経たなければ出てこないかもしれません。

 ichinose


ichinose様、

貴重な時間をさいて下さって、

感謝しています。

新しい予定表を作成している段階で、

まだまだ、隠した列は出てくると思います。

 >隠した列は、再表示される可能性があるのなら、ここでよいですね!!

回答ありがとうございます。

ichinose様、

新しい予定表の完成まで

まだまだ

時間がかかりますが

運用出来たあかっきには、

報告させていただきます。

ichinose様、

本当に

ありがとうございました。

(みこ)


 リンクを修正しました(kazu) 2009/08/04


コメント返信:

[ 一覧(最新更新順) ]


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