スケジュール管理表を作成 ⑥ セルのダブルクリックで終了時刻を15分単位で入力
先日から、スケジュール管理表をExcelで作成している。
infoment.hatenablog.com
今日も、前回の続きから。
その案件が終わって、終了時刻を入力するとき。手入力するならば都度、
時計に目を向けねばならない。また、タイプミスが起きる恐れもある。
そこで、ダブルクリックで終了時刻を入力することにした。
例えば、11:07分にその案件を終えたとき。人毎に様々な考え方があって、
私は1分単位で管理する必要は無いと思っている。大まかに仕事の予定と
実績(予実)を管理するならば、15分単位ぐらいで良い。従って
- 11:07 ⇒ 11:00
- 11:08 ⇒ 11:15
のように七捨八入することにした。Excelでは、MRound関数を用いる。
support.microsoft.com
これを、シートのダブルクリックイベントに設定してみよう。
↓ シートモジュール。
Private Property Get Tb() As ListObject Set Tb = Me.ListObjects(1) End Property
Private Function wf() As WorksheetFunction Set wf = WorksheetFunction End Function
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean) If Intersect(Target, Tb.ListColumns("終了時刻").DataBodyRange) Is Nothing Then Exit Sub ElseIf Target.Offset(-1) = vbNullString Then MsgBox "一つ前の項目が未だ終わっていません。" Cancel = True Exit Sub End If Target = wf.MRound(Time, "00:15") Cancel = True End Sub
では、実際にやってみよう。
想定通り、15分単位で入力することができた。
ところで、以下の三つは今までユーザー定義関数で算出していた。
- 終了予定時刻
- 残り時間
- 実際作業時間
引数もなく、単にセルに「=tm終了予定時刻()」のように入力してあって、
考えてみると値がセットしてあるのと何ら変わりがない。むしろ、再計算
のタイミングに気を遣う必要があるなどで、デメリットの方が多いような
気がしてきた。
そこで思い切って、UpdateTableに全て盛り込むことにした。
↓ 標準モジュール。
Private Function wf() As WorksheetFunction Set wf = WorksheetFunction End Function
Public Sub UpdateTable() ' 無限ループ回避のため、シートのチェンジイベントを一時停止。 Application.EnableEvents = False Application.ScreenUpdating = False On Error GoTo er: Dim Tb As ListObject Set Tb = ActiveSheet.ListObjects(1) ' 罫線クリア。 Tb.DataBodyRange.Borders.LineStyle = xlNone Dim arr As Variant arr = Tb.DataBodyRange Dim i As Long For i = 1 To UBound(arr) ' 終了予定時刻。 If arr(i, en実施内容) = vbNullString Then arr(i, en終了予定時刻) = vbNullString ElseIf i = 1 Then arr(i, en終了予定時刻) = CDate(arr(i, en作業予定時間)) + tm始業時刻 ElseIf arr(i - 1, en終了時刻) = vbNullString Then arr(i, en終了予定時刻) = CDate(arr(i, en作業予定時間)) + CDate(arr(i - 1, en終了予定時刻)) Else arr(i, en終了予定時刻) = CDate(arr(i, en作業予定時間)) + CDate(arr(i - 1, en終了時刻)) End If ' 残り時間。 If arr(i, en終了予定時刻) = vbNullString Or _ arr(i, 列名.en終了時刻) <> vbNullString Then arr(i, en残り時間) = vbNullString ElseIf CDate(arr(i, en終了予定時刻)) >= Time Then arr(i, en残り時間) = Format(CDate(arr(i, en終了予定時刻)) - Time, "hh:mm") Else arr(i, en残り時間) = Format(Time - CDate(arr(i, en終了予定時刻)), "-hh:mm") End If ' 実際作業時間。 If arr(i, en終了時刻) = vbNullString Then arr(i, en実際作業時間) = vbNullString ElseIf i = 1 Then arr(i, en実際作業時間) = CDate(arr(i, en終了時刻)) - tm始業時刻 Else arr(i, en実際作業時間) = CDate(arr(i, en終了時刻)) - CDate(arr(i - 1, en終了時刻)) End If Next i ' 更新後の値セット。 Tb.DataBodyRange = arr ' 数式の再セット。 Tb.ListColumns(enNo).DataBodyRange = "=ROW()-ROW(" & Tb.Range(1).Address & ")" Tb.ListColumns(en●).DataBodyRange = "=IF([@作業予定時間]="""","""",""●"")" Tb.ListColumns(en予実比率).DataBodyRange = "=IF([@実際作業時間]="""","""",[@実際作業時間]/[@作業予定時間])" Dim ListRow As Excel.ListRow For Each ListRow In Tb.ListRows With ListRow ' ●のサイズ修正。 .Range(en●).Font.Size = wf.MRound(6 * (Hour(.Range(en作業予定時間)) + _ Minute(.Range(en作業予定時間)) / 60) + 1, 2) ' 残り時間の文字色設定。 Select Case Left(.Range(en残り時間), 1) Case "-" .Range(en残り時間).Font.Color = 192 Case Else .Range(en残り時間).Font.Color = vbBlack End Select End With Next ' 罫線の再描画。 For Each ListRow In Tb.ListRows If ListRow.Range(en終了予定時刻) >= tm終業予定 Then ListRow.Range.Borders.Item(xlEdgeBottom).Weight = xlThin Exit For End If Next er: Application.EnableEvents = True Application.ScreenUpdating = True End Sub
Public Property Get tm始業時刻() As Date If ActiveSheet.Range("始業時刻") = vbNullString Then tm始業時刻 = TimeValue("8:00") Else tm始業時刻 = Range("始業時刻") End If End Property
Public Property Get tm終業予定() As Date If ActiveSheet.Range("終業予定") = vbNullString Then tm終業予定 = TimeValue("17:00") Else tm終業予定 = Range("終業予定") End If End Property
実は先程のGIFアニメは、上記置き換え後のものだ。今のところ、
- 作業予定時間
- 終了時刻
のどちらかが変わった時点で更新することとしている。
Private Sub Worksheet_Change(ByVal Target As Range) Dim ListRow As Excel.ListRow Select Case Target.Column - Tb.Range(1).Column + 1 Case 列名.en作業予定時間, 列名.en終了時刻 Call UpdateTable End Select End Sub
今回は、ここまで。
次回は、案件追加用のフォーム作成に挑戦です。
参考まで。
スケジュール管理表を作成 ⑤ その日に出来る範囲を把握してみる
先日から、スケジュール管理票をExcelで作成している。
infoment.hatenablog.com
今日も、先日の続きから。
これから少し、シートの塗りつぶしなどによる見える化も行っていく予定。
そのために、見た目は極力質素にしておきたい。
ということで、見た目を少し変えてみた。
ところで、このスケジュールには問題がある。日本全体の問題と言っても
良いかもしれない。それは「終わり時間を気にしていない」という問題だ。
一日は、有限だ。終わり時間を決めて、その日に出来る範囲を線引きして
おきたい。
Public Sub UpdateTable() ' スケジュール表。 Dim Tb As ListObject Set Tb = ActiveSheet.ListObjects(1) ' ループ用。 Dim ListRow As Excel.ListRow ' 更新前の罫線を削除。 Tb.DataBodyRange.Borders.LineStyle = xlNone ' 終業時刻を超える案件に罫線を引く。 On Error Resume Next For Each ListRow In Tb.ListRows If ListRow.Range(列名.en終了予定時刻) >= Range("終業予定") Then ListRow.Range.Borders.Item(xlEdgeBottom).Weight = xlThin Exit For End If Next On Error GoTo 0 End Sub
この更新は、作業予定時間または終了時刻が更新されたことを切っ掛けに
実行するとしよう。
↓ シートモジュール。
Private Sub Worksheet_Change(ByVal Target As Range) Dim ListRow As Excel.ListRow Select Case Target.Column - Tb.Range(1).Column + 1 Case 列名.en作業予定時間 For Each ListRow In Tb.ListRows With ListRow .Range(列名.en●).Font.Size = wf.MRound(6 * (Hour(.Range(列名.en作業予定時間)) + _ Minute(.Range(列名.en作業予定時間)) / 60) + 1, 2) End With Next Case 列名.en作業予定時間, 列名.en終了時刻 Call UpdateTable End Select End Sub
結果、本日の終業予定を17:00とした場合、案件H以降は明日以降に回さざるを
得ないことが視覚的にわかる。
※その結果を受けて、リスケジューリングするのか、或いは優先順位を変えるか
を考えることになる。
ところで、案件によっては昼休みをまたぐものも出てくるだろう。そこで、
昼休みボタンを設けることにした。
これを押すことで、現在進行中の案件を一旦中断し、昼休みののちに再開する
ようなスケジュールの引き直しが出来る。またそれに、終業予定時刻が追従し
変更される。
↓ シートモジュール。
Private Sub cb昼休み_Click() Call SetLunchBreak End Sub
↓ 標準モジュール。
Public Sub SetLunchBreak() Dim Tb As ListObject Set Tb = ActiveSheet.ListObjects(1) Tb.DataBodyRange.Interior.Color = xlNone ' 直近の終了時刻セル。 Dim LatestRange As Range Set LatestRange = Tb.ListRows(Tb.ListRows.Count).Range(列名.en終了時刻).End(xlUp) If LatestRange >= TimeValue("13:00") Then MsgBox "既に昼休み以降の作業を実施中です。" Exit Sub Else LatestRange.Offset(1) = "12:00" End If ' 直近の終了時刻セルの、テーブル内の行番号。 Dim RowIndex As Long RowIndex = LatestRange.Row - Tb.Range(1).Row Dim ListRow As Excel.ListRow Set ListRow = Tb.ListRows.Add(RowIndex + 2) With ListRow .Range(列名.en実施内容) = "昼休み" .Range(列名.en作業予定時間) = "1:00" .Range(列名.en終了時刻) = "13:00" .Range.Interior.Color = RGB(240, 240, 240) End With Set ListRow = Tb.ListRows.Add(RowIndex + 3) ListRow.Range(列名.en実施内容) = Tb.ListRows(RowIndex + 1).Range(列名.en実施内容) ListRow.Range(列名.en作業予定時間) = Tb.ListRows(RowIndex + 1).Range(列名.en作業予定時間) ListRow.Range(列名.en備考) = Tb.ListRows(RowIndex + 1).Range(列名.en備考) End Sub
結果は、以下のとおり。
本来1時間30分を見込んだE案件は30分で一旦終了し、昼休みを挟んで
再スタートとなっている。昼前の30分を引いて、昼からは残りの1時間
とするかどうか迷ったが、ややこくなるので引かないままとした。
今日はここまで。
次回こそは、前回予告した終了時刻の記入方法簡素化などに挑戦です。
参考まで。
スケジュール管理表を作成 ④ 見込み時間の長短を視覚でとらえる
先日から、スケジュール管理表をExcelで作成している。
infoment.hatenablog.com
今日も、昨日の続きから。
先日から作成しているスケジュール表は、今のところ見た目は文字と数字の
羅列であり、ガントチャートのような視覚に訴える効果は無い。
実は昨日突如登場した4列目の「●」は、その解消を意図して用意したもの。
掛かる時間の長短に併せて●の大小を追従させ、直感的にその作業に掛かる
時間を把握しようと試みてみた。
例えば、↓こんな感じだ。
作業予定時間に比例して丸が大きくなっていることが、お判りいただけた
だろうか。ちなみにこの●は、単純な式で表示させている。
なお、フォントサイズの変更は、WorkSheetChangeイベントで行うものとする。
※ ↓ は全て、スケジュール表のシートモジュールに記載。
※ 「列名.en●」は、昨日紹介したEnumから使用。
Private Property Get Tb() As ListObject Set Tb = Me.ListObjects(1) End Property Private Function wf() As WorksheetFunction Set wf = WorksheetFunction End Function Private Sub Worksheet_Change(ByVal Target As Range) Dim ListRow As Excel.ListRow Select Case Target.Column - Tb.Range(1).Column + 1 Case 列名.en作業予定時間 For Each ListRow In Tb.ListRows With ListRow .Range(列名.en●).Font.Size = wf.MRound(6 * (Hour(.Range(列名.en作業予定時間)) + _ Minute(.Range(列名.en作業予定時間)) / 60) + 1, 2) End With Next End Select End Sub
大した仕掛ではないし、これで完璧とも思わないが、それなりに役に立ちそうだ。
今日は、ここまで。次回は、終了時刻の記入方法の簡易化などに挑戦です。
参考まで。
スケジュール管理表を作成 ③ 列名をEnumで管理
先日から、スケジュール管理表をExcelで作成している。
infoment.hatenablog.com
今日も、昨日の続きから。
昨日作成したユーザー定義関数で、一つ大きな抜けがあった。
関数自体に抜けがあったわけではなく、関数に使用したEnumを掲載して
いなかったのだ。
例えば
Enum 列名 実施内容=2 End Enum
としておくと、以下の二つは同じ列を指しているが、後者の方が圧倒的に
読み易い(※個人の感想です)。
Columns(2).Select
Columns(列名.実施内容).Select
テーブルに於いては、ラベル名称を変えられてもエラーにならない。ただし、
列順の入れ替えには追従しないので、Enum側の編集が必要となる。逆に
Dim Tb As ListObject Set Tb = ActiveSheet.ListObjects(1) Tb.ListColumns("実施内容").DataBodyRange.Select
のようにラベル名称で選択することも可能で、この場合は列の入れ替えに
コードが左右されない利点がある。ただし、ラベル名称を変更されると
途端にエラーになるのが難点だ。
どちらを選ぶも一長一短があって、今回はEnumを選択した。
Enum 列名 enNo = 1 en実施内容 en作業予定時間 en● en実際作業時間 en終了予定時刻 en残り時間 en終了時刻 en予実比率 en備考 [_eLast] End Enum
なお今回はD列として、前回に無かった列「●」を追加しており、Enumにも
それが反映されている。これについては、次回紹介する。
ということで、現時点で最新のレイアウトがこちらになる。
先日述べたように、開始時刻を外出しにしてみた。会社によっては9時開始
だったり、午後から出社する日もあると考え、柔軟に対応できるようにして
みた。
終業予定については、定時に帰ることもあれば、残業することもある。毎日
決まった時間にはならないだろうから、終業「予定」とした。
なお、具体的な時間が入っているセルは、各々「開始時刻」「終業予定」と
名前をつけてある。
それでは、今回新たに作成した「実際作業時間」を求めるためのユーザー定義
関数と併せて、今まで作成した関数を紹介する。
※開始時刻の外出し対応済み。
' 実際作業時間 Public Function tm実際作業時間() Application.Volatile ' 数式がセットされたセル。 Dim TargetRange As Range Set TargetRange = Application.ThisCell ' 数式がセットされたセルを含むテーブル。 Static Tb As ListObject If Tb Is Nothing Then Set Tb = TargetRange.ListObject End If ' 数式がセットされたセルの、テーブルにおける行番号。 Dim RowIndex As Long RowIndex = TargetRange.Row - Tb.Range(1).Row With Tb.ListRows(RowIndex) If .Range(列名.en終了時刻) = vbNullString Then tm実際作業時間 = vbNullString ElseIf RowIndex = 1 Then tm実際作業時間 = .Range(列名.en終了時刻) - Range("始業時刻") Else tm実際作業時間 = .Range(列名.en終了時刻) _ - Tb.ListRows(RowIndex - 1).Range(列名.en終了時刻) End If End With End Function ' 終了予定時刻 Public Function tm終了予定時刻() Application.Volatile ' 数式がセットされたセル。 Dim TargetRange As Range Set TargetRange = Application.ThisCell ' 数式がセットされたセルを含むテーブル。 Static Tb As ListObject If Tb Is Nothing Then Set Tb = TargetRange.ListObject End If ' 数式がセットされたセルの、テーブルにおける行番号。 Dim RowIndex As Long RowIndex = TargetRange.Row - Tb.Range(1).Row With Tb.ListRows(RowIndex) If .Range(列名.en実施内容) = vbNullString Then tm終了予定時刻 = vbNullString ElseIf RowIndex = 1 Then tm終了予定時刻 = .Range(列名.en作業予定時間) + Range("始業時刻") ElseIf Tb.ListRows(RowIndex - 1).Range(列名.en終了時刻) = vbNullString Then tm終了予定時刻 = .Range(列名.en作業予定時間) _ + Tb.ListRows(RowIndex - 1).Range(列名.en終了予定時刻) Else tm終了予定時刻 = .Range(列名.en作業予定時間) _ + Tb.ListRows(RowIndex - 1).Range(列名.en終了時刻) End If End With End Function ' 残り時間。 Public Function tm残り時間() As Variant Application.Volatile ' 数式がセットされたセル。 Dim TargetRange As Range Set TargetRange = Application.ThisCell ' 数式がセットされたセルを含むテーブル。 Static Tb As ListObject If Tb Is Nothing Then Set Tb = TargetRange.ListObject End If ' 数式がセットされたセルの、テーブルにおける行番号。 Dim RowIndex As Long RowIndex = TargetRange.Row - Tb.Range(1).Row ' 終了予定時刻と現在の時刻の大小関係から、数式を決定する。 ' ※引いた結果がマイナスの場合、エラーになることへの処置。 With Tb.ListRows(RowIndex) If .Range(列名.en終了予定時刻) = vbNullString Or _ .Range(列名.en終了時刻) <> vbNullString Then tm残り時間 = vbNullString ElseIf .Range(列名.en終了予定時刻) >= Time Then tm残り時間 = Format(.Range(列名.en終了予定時刻) - Time, "hh:mm") TargetRange.Font.Color = vbBlack Else tm残り時間 = Format(Time - .Range(列名.en終了予定時刻), "-hh:mm") ' 負時間の色。赤より少し暗くしている(任意に変更可)。 TargetRange.Font.Color = 192 End If End With End Function
予実比率は、予定と実際の比率を計算している。例えば1時間を見込んだ作業が
30分で終われば「50%」、2時間で終われば「200%」と表示することで、進捗を
はかる目安となる。また自分が行った見積もりの精度を振り返るための材料にも
なる。さほど複雑な計算ではないため、こちらはセルに直接計算式を入力した。
実際に案件を入力してみると、このような感じになる。
必要な情報が大分揃ってきたが、機能としてはまだまだ足りない。
ということで次回は、今回追加した「●」の説明などを行います。
参考まで。
スケジュール管理表を作成 ② ユーザー定義関数でIF文の多重入れ子解消
昨日から、スケジュール管理表をExcelで作成している。
infoment.hatenablog.com
今日は、昨日の続きから。
昨日は、数式で以って終了予定時刻を算出した。
実はこれに、もう少し条件の追加が必要だ。しかしこれ以上、IF文の多重
入れ子構造になると、ぱっと見で理解できなくなる。それは回避したい。
ということで、ユーザー定義関数を作成することにした。
【終了予定時刻】の条件
- 実施内容が未記載の場合、何も表示しない。
- 表の一行目である場合、始業時刻+作業予定時間とする。
- 表のn行目であって且つ
① n-1行目の案件が終わっていない場合、
n行目の作業予定時間 + n-1行目の終了予定時刻とする。
② n-1行目の案件が終わっている場合、
n行目の作業予定時間 + n-1行目の終了時刻とする。
ユーザー定義関数にすると、こんな感じだ。
' 終了予定時刻 Public Function tm終了予定時刻() Application.Volatile ' 数式がセットされたセル。 Dim TargetRange As Range Set TargetRange = Application.ThisCell ' 数式がセットされたセルを含むテーブル。 Static Tb As ListObject If Tb Is Nothing Then Set Tb = TargetRange.ListObject End If ' 数式がセットされたセルの、テーブルにおける行番号。 Dim RowIndex As Long RowIndex = TargetRange.Row - Tb.Range(1).Row With Tb.ListRows(RowIndex) If .Range(列名.en実施内容) = vbNullString Then tm終了予定時刻 = vbNullString ElseIf RowIndex = 1 Then tm終了予定時刻 = .Range(列名.en作業予定時間) + TimeValue("8:00") ElseIf Tb.ListRows(RowIndex - 1).Range(列名.en終了時刻) = vbNullString Then tm終了予定時刻 = .Range(en作業予定時間) + _ Tb.ListRows(RowIndex - 1).Range(en終了予定時刻) Else tm終了予定時刻 = .Range(en作業予定時間) + _ Tb.ListRows(RowIndex - 1).Range(en終了時刻) End If End With End Function
同様に、残り時間もユーザー定義関数で作成する。
なお、残り時間に関しては以下の仕様とする。
- 終了予定時刻前に終わった場合は、残り時間をhh:mmの書式とし、
その文字色を黒とする。 - 終了予定時刻超で終わった場合は、残り時間を-hh:mmの書式とし、
その文字色を赤とする。
注意点として、時間差を求めた結果がマイナスとなった場合、エラーになる。
従って、予め引かれる側が引く側より大きくなるよう、確認が必要だ。
' 残り時間。 Public Function tm残り時間() As Variant Application.Volatile ' 数式がセットされたセル。 Dim TargetRange As Range Set TargetRange = Application.ThisCell ' 数式がセットされたセルを含むテーブル。 Static Tb As ListObject If Tb Is Nothing Then Set Tb = TargetRange.ListObject End If ' 数式がセットされたセルの、テーブルにおける行番号。 Dim RowIndex As Long RowIndex = TargetRange.Row - Tb.Range(1).Row ' 終了予定時刻と現在の時刻の大小関係から、数式を決定する。 ' ※引いた結果がマイナスの場合、エラーになることへの処置。 With Tb.ListRows(RowIndex) If .Range(列名.en終了予定時刻) = vbNullString Or _ .Range(列名.en終了時刻) <> vbNullString Then tm残り時間 = vbNullString ElseIf .Range(列名.en終了予定時刻) >= Time Then tm残り時間 = Format(.Range(列名.en終了予定時刻) - Time, "hh:mm") TargetRange.Font.Color = vbBlack Else tm残り時間 = Format(Time - .Range(列名.en終了予定時刻), "-hh:mm") ' 負時間の色。赤より少し暗くしている(任意に変更可)。 TargetRange.Font.Color = 192 End If End With End Function
例えば、↓ の最初の時点で案件Bの終了予定時刻は9:30であるが、
案件Aが予定から30分遅れて9:30に終了した場合、案件Bの終了予定時刻は
自動的に10:00に繰り下げられている(残り時間も同様)。
また例えば案件Dの優先度を案件Cより上げた場合も、案件D以降の終了予定
時刻は自動的に再設定されることになる。
次回は、
- 実際作業時間
- 予実比率
などの設定に挑戦です。
参考まで。
スケジュール管理表を作成 ① 案件の追加と差し込み
一年の計は元旦にあり。ということで、元旦を10日も過ぎてしまったが、
スケジュール管理表を作成してみよう。
個人的に、予定管理において特に重要な項目は、以下の三つと考える。
- 時間管理
- 予実管理
- 優先度管理
そこで、管理項目を以下に書き出してみた。
- 実施内容
- 作業予定時間(実施内容に掛かる見込み時間)
- 実際作業時間(実施内容に掛かった実際時間)
- 終了予定時刻(予定時間から求めた終了時刻)
- 残り時間(現時刻から終了予定時刻迄の残り)
- 終了時刻(実施内容が実際に終了した時刻)
- 予実比率(予定時間と実際時間の比率)
- 備考
表にすると、こんな感じ。
扱い易さのため、テーブルにしてみよう。
まず、No.には通し番号が入る。行番号を取得するRow関数を設定しよう。
以下の3つは直接入力なので後回しにして、終了予定時刻の計算を考える。
とここで、禁じ手に手を染める。テーブルは1行1レコードであって前後の
レコードと相関関係があってはいけないと思うのだが、都合上止むを得ず、
直前レコードの終了予定時刻を参照することになる。
数式中の"8:00"は、朝8時からスケジュールが開始されることを想定している。
後ほど、管理しやすいよう外出しするかもしれない。
ここで、案件DとEが追加されたとする。各々の作業予定時刻は30分。
案件Dはさほど急ぎではないが、案件Eは案件Aの次ぐらいに重要だ。
すると、追加作業の様子はこのようになる。
これにより、各案件の変更後の終了時刻(目安)が容易に変更可能となった。
各案件の作業予定時刻を前もって見積もる習慣が付く、という利点もある。
今回はここまで。
次回は、残り時間の算出などを行います。
参考まで。
表で累積を表示したい
職場で、「Excelの表で累積を表示したい」という相談を受けた。
さて、どうしたものか。
今回は、以下二つの制約があった。
- 表は、2行がセル結合で1レコードになっている。
- 途中のレコードを削除する場合がある。
例えば、こんな感じだ。
良し悪しはさておき、セルが結合されているため、テーブルとして
書式設定することはできない。マクロ使用はNGではないとのこと
だったが、であれば、なるべく避けた方が良かろう。
例えば、一つ上と左隣を足していく、という方法がある。
1レコード目のさらに一つ上はラベル行であるため、足し算すると
エラーになる。従って、エラー回避としてIFERRORを使用している。
しかしこれだと、途中の行を削除した際、参照先が失われて空振り
が発生する。
さて、どうしたものか。あーでもない、こーでもないと議論・検討を
重ねた結果、今回はこれに落ち着いた。
- Row関数-2で、自身の二行上の行番号を得る。
- Column関数で、自身の列番号を得る。
- 1と2からAddress関数で、自身の二行上のアドレスを得る。
- 3とIndirect関数で、自身の二行上の値を得る。
- 4と左隣を足し算する。
この場合、自分自身を基準にして加算対象セルを指定しているため、途中の
レコードを行ごと削除しても、先程のような空振りは発生しない。
他にSumif関数を使用する案などもあったが、取り敢えずこれに落ち着いた。
でもきっと、もっといい方法があるに違いない。
参考まで。