Excel VBAを使用した月次業績目標達成確認の自動リマインダーの作成方法では、future review時刻を一回登録し、targetが0でないことを確認してMsgBox表示とReviewed時刻を記録する。Application.OnTimeはExcel process内の予約で、PCが停止中なら実行保証はない。達成率は予約時ではなくreview時に最新cellから計算する。この記事はmonth key、target、actual、NextReview、procedure、review statusを一つの月次recordにするを判断軸にして、記事固有のコード、合否、停止条件、復元を順序立てて説明します。
mail送信ではなく、月次KPI reviewをExcel利用中に画面で促す。完了は「対象月の最新actual/targetから達成率が表示され、同じmonth keyがReviewedへ一度だけ遷移する」です。結果が空なら「targetまたは月次rowがない場合は予約せず、0除算をerror handlerへ流さない」として調べ、エラーを0件へ置き換えません。
target・actual・review時刻を確認
future review時刻を一回登録し、targetが0でないことを確認してMsgBox表示とReviewed時刻を記録する。月次業績レビューのExcelリマインダーでは、単にコマンドが終了したことではなく「対象月の最新actual/targetから達成率が表示され、同じmonth keyがReviewedへ一度だけ遷移する」を完了条件にします。mail送信ではなく、月次KPI reviewをExcel利用中に画面で促す。
target・actual・review時刻を確認に入る前に、対象、実行場所、権限、入力の由来を確認します。targetまたは月次rowがない場合は予約せず、0除算をerror handlerへ流さない。判定不能を成功へ丸めません。
target 0を除外
target 0を除外では「month key、target、actual、NextReview、procedure、review statusを一つの月次recordにする」という粒度で対象を特定します。Application.OnTimeはExcel process内の予約で、PCが停止中なら実行保証はない。達成率は予約時ではなくreview時に最新cellから計算する。表示名や先頭候補だけを採用しません。
月次業績レビューのExcelリマインダーの対象が複数なら、候補数と除外理由を残します。月次業績レビューのExcelリマインダーでは実行ユーザー、OS・製品版、locale、カレントディレクトリも結果の解釈へ影響するため同時に記録します。
OnTimeで一回予約
OnTimeで一回予約は変更や出力生成より先に行う観測です。month key、target、actual、NextReview、procedure、review statusを一つの月次recordにするを含む形で現状を保存し、後段のコードが同じ対象へ向くか確認します。
Option Explicit
Private Function QualifiedReviewProcedure() As String
QualifiedReviewProcedure = "'" & Replace(ThisWorkbook.Name, "'", "''") & "'!ShowMonthlyReview"
End Function
Private Function NewReviewAttemptId() As String
Dim typeLib As Object, raw As String, details As String
On Error GoTo Failed
Set typeLib = CreateObject("Scriptlet.TypeLib")
raw = Replace$(Replace$(CStr(typeLib.GUID), "{", vbNullString), "}", vbNullString)
If Len(raw) <> 36 Then Err.Raise 5, , "GUID length mismatch"
NewReviewAttemptId = "review-" & raw
Exit Function
Failed:
details = CStr(Err.Number) & " " & Err.Description
On Error GoTo 0
Err.Raise vbObjectError + 1890, "NewReviewAttemptId", "AttemptIDを生成できません。予約しません: " & details
End Function
Private Sub ValidateMonthlyValues(ByVal ws As Worksheet)
If Not IsNumeric(ws.Range("B2").Value2) Or Not IsNumeric(ws.Range("C2").Value2) Then Err.Raise 13, , "実績と目標は数値にします"
If CDbl(ws.Range("C2").Value2) <= 0 Or CDbl(ws.Range("B2").Value2) < 0 Then Err.Raise 5, , "目標は正、実績は0以上にします"
End Sub
Private Sub PersistReviewState(ByVal ws As Worksheet, ByVal expectedState As String, ByVal expectedMonthKey As String, ByVal expectedAttemptId As String, ByVal expectedEarliest As Date, ByVal expectedProcedure As String, ByVal expectedLatest As Date, ByVal requireTuple As Boolean)
Dim saveNumber As Long, saveDescription As String
If Len(ThisWorkbook.Path) = 0 Then Err.Raise 5, , "未保存workbookでは耐久状態を作れません"
If ThisWorkbook.ReadOnly Then Err.Raise 5, , "read-only workbookでは耐久状態を作れません"
On Error Resume Next
ThisWorkbook.Save
saveNumber = Err.Number
saveDescription = Err.Description
Err.Clear
On Error GoTo 0
If saveNumber <> 0 Then Err.Raise vbObjectError + 1891, "PersistReviewState", "ThisWorkbook.Save失敗: " & CStr(saveNumber) & " " & saveDescription
If Not ThisWorkbook.Saved Then Err.Raise vbObjectError + 1892, "PersistReviewState", "Save後もThisWorkbook.Saved=Falseです"
If StrComp(CStr(ws.Range("E2").Value2), expectedState, vbBinaryCompare) <> 0 Then Err.Raise 5, , "保存後state再読不一致"
If StrComp(CStr(ws.Range("H2").Value2), expectedMonthKey, vbBinaryCompare) <> 0 Then Err.Raise 5, , "保存後month key再読不一致"
If StrComp(CStr(ws.Range("J2").Value2), expectedAttemptId, vbBinaryCompare) <> 0 Then Err.Raise 5, , "保存後AttemptID再読不一致"
If requireTuple Then
If Not IsDate(ws.Range("F2").Value) Or Not IsDate(ws.Range("I2").Value) Then Err.Raise 13, , "保存後OnTime日時がありません"
If CDbl(CDate(ws.Range("F2").Value)) <> CDbl(expectedEarliest) Then Err.Raise 5, , "保存後EarliestTime再読不一致"
If StrComp(CStr(ws.Range("G2").Value2), expectedProcedure, vbBinaryCompare) <> 0 Then Err.Raise 5, , "保存後Procedure再読不一致"
If CDbl(CDate(ws.Range("I2").Value)) <> CDbl(expectedLatest) Then Err.Raise 5, , "保存後LatestTime再読不一致"
Else
If Len(CStr(ws.Range("F2").Value2)) > 0 Or Len(CStr(ws.Range("G2").Value2)) > 0 Or Len(CStr(ws.Range("I2").Value2)) > 0 Then Err.Raise 5, , "terminal保存後もOnTime tupleが残っています"
End If
End Sub
Private Sub AssertReviewScheduleIsClear(ByVal ws As Worksheet, ByVal monthKey As String)
Dim state As String
state = CStr(ws.Range("E2").Value2)
Select Case state
Case vbNullString, "Ready", "Cancelled", "Reviewed", "ExpiredNoReview", "NeedsReapproval"
Case Else
Err.Raise 5, , "未解決stateをinspect/reconcileしてください。自動再予約しません: " & state
End Select
If CStr(ws.Range("H2").Value2) = monthKey And state = "Reviewed" Then Err.Raise 5, , "同じmonth keyはreview済みです"
If state = "NeedsReapproval" And CStr(ws.Range("K2").Value2) <> "ApprovedNewReview:" & monthKey Then Err.Raise 5, , "K2へApprovedNewReview:<monthKey>の明示再承認が必要です"
If Len(CStr(ws.Range("F2").Value2)) > 0 Or Len(CStr(ws.Range("G2").Value2)) > 0 Or Len(CStr(ws.Range("I2").Value2)) > 0 Then Err.Raise 5, , "保存OnTime tupleが残っています"
End Sub
Sub InspectMonthlyTarget()
With ThisWorkbook.Worksheets("Monthly")
Debug.Print "actual=" & .Range("B2").Value2, "target=" & .Range("C2").Value2, "requested=" & .Range("D2").Value2
Debug.Print "status=" & .Range("E2").Value2, "earliest=" & .Range("F2").Value2, "procedure=" & .Range("G2").Value2
Debug.Print "monthKey=" & .Range("H2").Value2, "latest=" & .Range("I2").Value2, "attempt=" & .Range("J2").Value2, "resolutionApproval=" & .Range("K2").Value2
Debug.Print "reopenPolicy=inspect-only; no automatic OnTime registration"
End With
End Sub
Application.OnTimeはExcel process内の予約で、PCが停止中なら実行保証はない。達成率は予約時ではなくreview時に最新cellから計算する。月次業績レビューのExcelリマインダーでは取得不能、対象なし、値が空という三状態を分け、stderrや終了コードを捨てません。
達成率をreview時に再計算
達成率をreview時に再計算ではfuture review時刻を一回登録し、targetが0でないことを確認してMsgBox表示とReviewed時刻を記録する。月次業績レビューのExcelリマインダーのサンプルにあるパス、セル、ユーザー、時刻は検証用なので、直前に確認した承認値へ置き換えます。
Sub ScheduleMonthlyReview()
Dim ws As Worksheet, reviewAt As Date, latestAt As Date, monthKey As String, procedureName As String, attemptId As String, priorState As String
Dim failureText As String, persistText As String
Set ws = ThisWorkbook.Worksheets("Monthly")
ValidateMonthlyValues ws
If Not IsDate(ws.Range("D2").Value) Then Err.Raise 13, , "レビュー時刻が日付ではありません"
reviewAt = CDate(ws.Range("D2").Value)
latestAt = reviewAt + TimeSerial(0, 5, 0)
monthKey = Format$(reviewAt, "yyyymm")
procedureName = QualifiedReviewProcedure()
If reviewAt <= Now Then Err.Raise 5, , "未来のレビュー時刻が必要です"
priorState = CStr(ws.Range("E2").Value2)
AssertReviewScheduleIsClear ws, monthKey
attemptId = NewReviewAttemptId()
ws.Range("F2").Value2 = reviewAt
ws.Range("G2").Value2 = procedureName
ws.Range("H2").Value2 = monthKey
ws.Range("I2").Value2 = latestAt
ws.Range("J2").Value2 = attemptId
If priorState = "NeedsReapproval" Then
ws.Range("K2").Value2 = "ConsumedApproval:" & attemptId
Else
ws.Range("K2").Value2 = "InitialSchedule:" & attemptId
End If
ws.Range("E2").Value2 = "Scheduling"
PersistReviewState ws, "Scheduling", monthKey, attemptId, reviewAt, procedureName, latestAt, True
On Error GoTo ScheduleUnknown
Application.OnTime EarliestTime:=reviewAt, Procedure:=procedureName, LatestTime:=latestAt, Schedule:=True
ws.Range("E2").Value2 = "Scheduled"
PersistReviewState ws, "Scheduled", monthKey, attemptId, reviewAt, procedureName, latestAt, True
Exit Sub
ScheduleUnknown:
failureText = CStr(Err.Number) & " " & Err.Description
On Error Resume Next
Err.Clear
ws.Range("E2").Value2 = "ScheduleUnknown"
PersistReviewState ws, "ScheduleUnknown", monthKey, attemptId, reviewAt, procedureName, latestAt, True
If Err.Number <> 0 Then persistText = "; unknown-state save also failed: " & CStr(Err.Number) & " " & Err.Description
On Error GoTo 0
Err.Raise vbObjectError + 1893, "ScheduleMonthlyReview", "OnTime結果は未確定です。tupleを保持し自動再予約しません: " & failureText & persistText
End Sub
Sub ShowMonthlyReview()
Dim ws As Worksheet, achieved As Double, target As Double, reviewAt As Date, latestAt As Date
Dim monthKey As String, procedureName As String, attemptId As String, failureText As String, persistText As String
Set ws = ThisWorkbook.Worksheets("Monthly")
procedureName = QualifiedReviewProcedure()
If CStr(ws.Range("E2").Value2) <> "Scheduled" Then Err.Raise 5, , "durable ScheduledからだけReviewへ遷移できます"
If Not IsDate(ws.Range("F2").Value) Or Not IsDate(ws.Range("I2").Value) Then Err.Raise 5, , "保存OnTime tupleがありません"
reviewAt = CDate(ws.Range("F2").Value)
latestAt = CDate(ws.Range("I2").Value)
monthKey = Format$(reviewAt, "yyyymm")
attemptId = CStr(ws.Range("J2").Value2)
If CStr(ws.Range("G2").Value2) <> procedureName Or CStr(ws.Range("H2").Value2) <> monthKey Or Len(attemptId) = 0 Then Err.Raise 5, , "保存tuple、month key、AttemptIDが一致しません"
ValidateMonthlyValues ws
achieved = CDbl(ws.Range("B2").Value2)
target = CDbl(ws.Range("C2").Value2)
ws.Range("E2").Value2 = "Running"
PersistReviewState ws, "Running", monthKey, attemptId, reviewAt, procedureName, latestAt, True
On Error GoTo ReviewUnknown
MsgBox "達成率: " & Format$(achieved / target, "0.0%"), vbInformation
ws.Range("E2").Value2 = "Reviewed"
ws.Range("F2:G2").ClearContents
ws.Range("I2").ClearContents
PersistReviewState ws, "Reviewed", monthKey, attemptId, reviewAt, procedureName, latestAt, False
Exit Sub
ReviewUnknown:
failureText = CStr(Err.Number) & " " & Err.Description
On Error Resume Next
Err.Clear
ws.Range("F2").Value2 = reviewAt
ws.Range("G2").Value2 = procedureName
ws.Range("I2").Value2 = latestAt
ws.Range("E2").Value2 = "ReviewUnknown"
PersistReviewState ws, "ReviewUnknown", monthKey, attemptId, reviewAt, procedureName, latestAt, True
If Err.Number <> 0 Then persistText = "; unknown-state save also failed: " & CStr(Err.Number) & " " & Err.Description
On Error GoTo 0
Err.Raise vbObjectError + 1894, "ShowMonthlyReview", "Reviewまたはterminal save結果が未確定です: " & failureText & persistText
End Sub
同一月を重複OnTime登録しない。MsgBoxを無人serverの通知手段にしない。月次業績レビューのExcelリマインダーで変更が発生する場合は、新規出力、no-clobber、WhatIf、下書き表示など利用可能な安全機構を先に使います。
MsgBoxは画面表示だけ
MsgBoxは画面表示だけでは入力と出力を別々に再取得します。月次業績レビューのExcelリマインダーの合格は、対象月の最新actual/targetから達成率が表示され、同じmonth keyがReviewedへ一度だけ遷移することです。件数だけでなく識別値と内容も照合します。
Sub CancelMonthlyReview()
Dim ws As Worksheet, reviewAt As Date, latestAt As Date, procedureName As String, state As String
Dim monthKey As String, attemptId As String, failureText As String, persistText As String
Set ws = ThisWorkbook.Worksheets("Monthly")
state = CStr(ws.Range("E2").Value2)
Select Case state
Case "Scheduled", "Scheduling", "ScheduleUnknown", "Cancelling", "CancelUnknown"
Case Else
Err.Raise 5, , "取消可能なdurable予約状態ではありません"
End Select
If Not IsDate(ws.Range("F2").Value) Or Not IsDate(ws.Range("I2").Value) Then Err.Raise 5, , "保存OnTime日時がありません"
reviewAt = CDate(ws.Range("F2").Value)
latestAt = CDate(ws.Range("I2").Value)
procedureName = CStr(ws.Range("G2").Value2)
monthKey = CStr(ws.Range("H2").Value2)
attemptId = CStr(ws.Range("J2").Value2)
If procedureName <> QualifiedReviewProcedure() Or Len(monthKey) = 0 Or Len(attemptId) = 0 Then Err.Raise 5, , "保存Procedure、month key、AttemptIDが一致しません"
ws.Range("E2").Value2 = "Cancelling"
PersistReviewState ws, "Cancelling", monthKey, attemptId, reviewAt, procedureName, latestAt, True
On Error GoTo CancelUnknown
Application.OnTime EarliestTime:=reviewAt, Procedure:=procedureName, Schedule:=False
ws.Range("E2").Value2 = "Cancelled"
ws.Range("F2:G2").ClearContents
ws.Range("I2").ClearContents
PersistReviewState ws, "Cancelled", monthKey, attemptId, reviewAt, procedureName, latestAt, False
Exit Sub
CancelUnknown:
failureText = CStr(Err.Number) & " " & Err.Description
On Error Resume Next
Err.Clear
ws.Range("F2").Value2 = reviewAt
ws.Range("G2").Value2 = procedureName
ws.Range("I2").Value2 = latestAt
ws.Range("E2").Value2 = "CancelUnknown"
PersistReviewState ws, "CancelUnknown", monthKey, attemptId, reviewAt, procedureName, latestAt, True
If Err.Number <> 0 Then persistText = "; unknown-state save also failed: " & CStr(Err.Number) & " " & Err.Description
On Error GoTo 0
Err.Raise vbObjectError + 1895, "CancelMonthlyReview", "取消結果は未確定です。同じtupleを保持します: " & failureText & persistText
End Sub
Sub ReconcileMonthlyNoCallbackAfterLatestTime()
Dim ws As Worksheet, reviewAt As Date, latestAt As Date, procedureName As String, state As String
Dim monthKey As String, attemptId As String
Set ws = ThisWorkbook.Worksheets("Monthly")
state = CStr(ws.Range("E2").Value2)
Select Case state
Case "Scheduling", "ScheduleUnknown", "Cancelling", "CancelUnknown"
Case Else
Err.Raise 5, , "no-callback照合対象stateではありません"
End Select
If Not IsDate(ws.Range("F2").Value) Or Not IsDate(ws.Range("I2").Value) Then Err.Raise 5, , "保存OnTime tupleがありません"
reviewAt = CDate(ws.Range("F2").Value)
latestAt = CDate(ws.Range("I2").Value)
procedureName = CStr(ws.Range("G2").Value2)
monthKey = CStr(ws.Range("H2").Value2)
attemptId = CStr(ws.Range("J2").Value2)
If Now <= latestAt Then Err.Raise 5, , "LatestTime経過前は0件を確定できません"
If CStr(ws.Range("K2").Value2) <> "ConfirmNoCallback:" & attemptId Then Err.Raise 5, , "K2へConfirmNoCallback:<AttemptID>の明示確認が必要です"
ws.Range("E2").Value2 = "ExpiredNoReview"
ws.Range("F2:G2").ClearContents
ws.Range("I2").ClearContents
PersistReviewState ws, "ExpiredNoReview", monthKey, attemptId, reviewAt, procedureName, latestAt, False
End Sub
Sub ResolveMonthlyReviewAfterInspection()
Dim ws As Worksheet, reviewAt As Date, latestAt As Date, procedureName As String, state As String
Dim monthKey As String, attemptId As String, approval As String, terminalState As String
Set ws = ThisWorkbook.Worksheets("Monthly")
state = CStr(ws.Range("E2").Value2)
Select Case state
Case "Running", "ReviewUnknown"
Case Else
Err.Raise 5, , "review結果照合対象stateではありません"
End Select
If Not IsDate(ws.Range("F2").Value) Or Not IsDate(ws.Range("I2").Value) Then Err.Raise 5, , "保存review tupleがありません"
reviewAt = CDate(ws.Range("F2").Value)
latestAt = CDate(ws.Range("I2").Value)
procedureName = CStr(ws.Range("G2").Value2)
monthKey = CStr(ws.Range("H2").Value2)
attemptId = CStr(ws.Range("J2").Value2)
approval = CStr(ws.Range("K2").Value2)
If approval = "ConfirmDisplayed:" & attemptId Then
terminalState = "Reviewed"
ElseIf approval = "ReapproveReview:" & attemptId Then
terminalState = "NeedsReapproval"
Else
Err.Raise 5, , "K2へConfirmDisplayed:<AttemptID>またはReapproveReview:<AttemptID>が必要です"
End If
ws.Range("E2").Value2 = terminalState
ws.Range("F2:G2").ClearContents
ws.Range("I2").ClearContents
PersistReviewState ws, terminalState, monthKey, attemptId, reviewAt, procedureName, latestAt, False
End Sub
Sub VerifyMonthlyReview()
With ThisWorkbook.Worksheets("Monthly")
Debug.Print "status=" & .Range("E2").Value2, "monthKey=" & .Range("H2").Value2, "attempt=" & .Range("J2").Value2
Debug.Print "earliest=" & .Range("F2").Value2, "procedure=" & .Range("G2").Value2, "latest=" & .Range("I2").Value2
Debug.Print "autoRetry=False", "saved=" & ThisWorkbook.Saved, "path=" & ThisWorkbook.Path
End With
End Sub
targetまたは月次rowがない場合は予約せず、0除算をerror handlerへ流さない。月次業績レビューのExcelリマインダーの結果が期待と違えば追加変更を重ねず、入力、対象範囲、locale・時刻、権限、製品仕様の順に戻って調べます。
Excelが閉じている場合
同一月を重複OnTime登録しない。MsgBoxを無人serverの通知手段にしない。Excelが閉じている場合に当てはまるときは中止理由、対象識別子、終了コードまたはErr.Number、直前に成功した段階を保存します。
targetまたは月次rowがない場合は予約せず、0除算をerror handlerへ流さない。月次業績レビューのExcelリマインダーの再試行は原因を直し、同じ入力と対象を再確認してから行います。警告抑止や強制上書きで通しません。
同月の重複予約を防ぐ
未実行予約は同じNextReviewとprocedureで取消し、statusをCancelledへする。復元にも「month key、target、actual、NextReview、procedure、review statusを一つの月次recordにする」を用い、類似名の別対象へ処理しません。
- 月次業績レビューのExcelリマインダーの開始前状態
- 採用対象: month key、target、actual、NextReview、procedure、review statusを一つの月次recordにする
- 復元後の確認: 対象月の最新actual/targetから達成率が表示され、同じmonth keyがReviewedへ一度だけ遷移する
- 復元を止める条件: 同一月を重複OnTime登録しない。MsgBoxを無人serverの通知手段にしない
取消とReviewed記録
確実な組織通知が必要ならcalendarやworkflowを使い、Excel画面通知の限界を明示する。月次業績レビューのExcelリマインダーを反復するときは、正常、差分なし、対象なし、要承認、失敗を別の状態として記録します。
| 取消とReviewed記録の主キー | month key、target、actual、NextReview、procedure、review statusを一つの月次recordにする |
| 採用条件 | 対象月の最新actual/targetから達成率が表示され、同じmonth keyがReviewedへ一度だけ遷移する |
| 空結果 | targetまたは月次rowがない場合は予約せず、0除算をerror handlerへ流さない |
| 中止条件 | 同一月を重複OnTime登録しない。MsgBoxを無人serverの通知手段にしない |
target・actual・review時刻を確認から証跡化するOnTimeで一回予約
月次業績レビューのExcelリマインダーの証跡は「month key、target、actual、NextReview、procedure、review statusを一つの月次recordにする」を主キーにします。target・actual・review時刻を確認で確認した値と、実行直前・実行直後の値を同じ作業番号に保存し、表示名が似ている別対象や前回の結果を混ぜません。
target 0を除外で空結果を判定する達成率をreview時に再計算
月次業績レビューのExcelリマインダーの空結果は「targetまたは月次rowがない場合は予約せず、0除算をerror handlerへ流さない」として扱います。target 0を除外で入力自体が存在するか、権限で見えていないか、条件に一致しないだけかを分け、0件という表示だけで成功・失敗を決めません。
取消とReviewed記録から復旧可否を測るtarget・actual・review時刻を確認
月次業績レビューのExcelリマインダーの復旧判断では「未実行予約は同じNextReviewとprocedureで取消し、statusをCancelledへする」を採用します。取消とReviewed記録を再確認し、復旧後に「対象月の最新actual/targetから達成率が表示され、同じmonth keyがReviewedへ一度だけ遷移する」へ戻ったかを別の読み取り処理で測定します。
月次業績レビューのExcelリマインダーの事前確認では、month key、target、actual、NextReview、procedure、review statusを一つの月次recordにするを画面表示や標準出力だけで済ませず、実行日時と一緒に作業記録へ写します。Application.OnTimeはExcel process内の予約で、PCが停止中なら実行保証はない。達成率は予約時ではなくreview時に最新cellから計算するという仕様があるため、似た名前の別対象、前回実行時の値、キャッシュされた表示を今回の対象と取り違えないことが重要です。
月次業績レビューのExcelリマインダーのコードを実行した直後は、まず終了状態を保存し、その後に別の読み取り処理で「対象月の最新actual/targetから達成率が表示され、同じmonth keyがReviewedへ一度だけ遷移する」を確認します。月次業績レビューのExcelリマインダーでは同じコードの表示だけを合否判定に使うと部分成功や遅延反映を見逃すため、識別値、件数、内容の三点を照合します。
月次業績レビューのExcelリマインダーで結果が得られない場合は、targetまたは月次rowがない場合は予約せず、0除算をerror handlerへ流さない。月次業績レビューのExcelリマインダーではこの状態と、権限拒否、入力形式の不一致、接続先や時刻の違いを一緒にしません。月次業績レビューのExcelリマインダーの対象候補数、除外された候補、最後に成功した確認処理を残すと、再試行で同じ失敗を重ねずに済みます。
月次業績レビューのExcelリマインダーを元へ戻す必要があるときは、未実行予約は同じNextReviewとprocedureで取消し、statusをCancelledへする。月次業績レビューのExcelリマインダーの復元前にも変更後の識別値を再取得し、別担当者の更新が入っていないか確認します。月次業績レビューのExcelリマインダーの復元結果も通常処理と同じ完了条件で測り、戻したつもりという報告だけで閉じません。
月次業績レビューのExcelリマインダーを引き継ぐ記録には、確実な組織通知が必要ならcalendarやworkflowを使い、Excel画面通知の限界を明示する。特に「同一月を重複OnTime登録しない。MsgBoxを無人serverの通知手段にしない」に該当した場合は、実行を止めたこと自体を正しい結果として扱います。月次業績レビューのExcelリマインダーの次回担当者が承認範囲と未処理対象を区別できるよう、作業番号と対象識別子を対応付けます。
月次業績レビューのExcelリマインダーの作業記録には、開始前の対象候補、採用した識別値、実行したコード、終了後の実測、除外理由を同じ作業番号で保存します。「month key、target、actual、NextReview、procedure、review statusを一つの月次recordにする」を省くと別対象との比較になり得るため、日時、実行場所、製品版と一緒に残します。
Excel VBAを使用した月次業績目標達成確認の自動リマインダーの作成方法を定期運用へ組み込む場合も初回は対話的に確認します。正常は「対象月の最新actual/targetから達成率が表示され、同じmonth keyがReviewedへ一度だけ遷移する」、空結果は「targetまたは月次rowがない場合は予約せず、0除算をerror handlerへ流さない」、停止は「同一月を重複OnTime登録しない。MsgBoxを無人serverの通知手段にしない」として報告し、次の担当者が同じ条件で追試できるようにします。
OnTime登録前と実行時の両方で分母を検証する
C2の目標が数値かつ0より大きいこと、B2の実績が数値かつ0以上であることを確認してからOnTimeへ登録します。実行時までにセルが変わる可能性があるため、ShowMonthlyReviewでも同じ検証を繰り返します。
VerifyMonthlyReviewも0以下の分母では除算しません。これにより予約登録時だけ正常で、実行時に0除算となる経路を閉じます。
クラッシュ・再起動の必須fault-injection fixture
OnTime直後fixture:Application.OnTime直後かつScheduledのterminal save前に停止し、再起動後もSchedulingまたはScheduleUnknown、month key、EarliestTime、Procedure、LatestTime、AttemptIDがdiskに残ることを確認します。取消0件はLatestTime後にK2へConfirmNoCallback:<AttemptID>を入れてReconcileMonthlyNoCallbackAfterLatestTimeを通すまで再予約しません。
review直後fixture:MsgBox表示後かつReviewed save前に停止し、再起動後はRunningまたはReviewUnknownのままで同月を再表示・再予約しないことを確認します。ResolveMonthlyReviewAfterInspectionはK2のConfirmDisplayed:<AttemptID>でReviewed、ReapproveReview:<AttemptID>でNeedsReapprovalへ進め、新規予約にはさらにApprovedNewReview:<monthKey>を要求します。実workbookがない記事監査ではspecified-not-executedとして記録します。
公式情報・参考資料
月次業績レビューのExcelリマインダーのコマンド、API、対応範囲は次の公式一次資料で確認しました。確認日は2026年7月17日です。月次業績レビューのExcelリマインダーの実行環境にあるman、–help、VBA Object Browser、Get-Helpも併用してください。

コメント