SSブログ

勤務管理表 [コンピューター]

エクセルで作成した勤務管理表について整理します。

001.jpg

【エクセルシート】
・A2-A32セル:日を表示します。表示形式は"d"です。
  A2セル:その月の1日を「yyyy/mm/dd」の形式で入力します。例えば「2014/7/1」のように。
  A3セル:「=A2+1」の式が入っています。2日を表します。
      |
  A32セル:「=A31+1」の式が入っています。31日を表します。

・B2-B32セル:曜日を表示します。表示形式は"aaa"です。
  日曜日のセルをピンクで塗るため、=TEXT(A2,"aaa")="日"の条件付き書式を設定しています。
  土曜日のセルを水色で塗るため、=TEXT(A2,"aaa")="土"の条件付き書式を設定しています。
  B2セル:「=A2」の式が入っています。1日の曜日を表します。
  B3セル:「=A3」の式が入っています。2日の曜日を表します。
      |
  B32セル:「=A32」の式が入っています。31日の曜日を表します。

・C2-C32セル:出社時刻を入力します。表示形式は"h:mm"です。
・D2-D32セル:退社時刻を入力します。表示形式は"h:mm"です。
  "0:00"から"8:30"までの時刻を入力した場合、翌日退社扱いとなります。

・E2-E32セル:作業時間(60進)を表示します。
  ・名前:"作業時間"
  ・表示形式:"h:mm"
・F2-F32セル:作業時間(10進)を表示します。表示形式は"0.00"です。
・G2-G32セル:残業時間(60進)を表示します。表示形式は"h:mm"です。
・H2-H32セル:深夜時間(60進)を表示します。
  ・名前:"深夜時間"
  ・表示形式:"h:mm"

・E33セル:(A)作業時間(60進)の合計を表示します。
  ・式:=SUM(E2:E32)
  ・表示形式:[h]:mm
・F33セル:(B)作業時間(10進)の合計を表示します。
  ・式:=SUM(F2:F32)
  ・表示形式:0.00
・G33セル:(C)残業時間(60進)の合計を表示します。
  ・式:=SUM(G2:G32)
  ・表示形式:[h]:mm
・H33セル:(D)深夜時間(60進)の合計を表示します。
  ・式:=SUM(H2:H32)
  ・表示形式:[h]:mm

・E37セル:昼休みの開始時刻をリストから選択します。
  ・名前:"昼休開始"
  ・元の値:=$G$37:$H$37
・E38セル:残業の開始時刻をリストから選択します。
  ・名前:"残業開始"
  ・元の値:=$G$38:$H$38
・E39セル:深夜残業の開始時刻をリストから選択します。
  ・名前:"深夜開始"
  ・元の値:=$G$39

・J2セル:年月を表示します。
  ・表示形式:yyyy"年"m"月"
  ・式:=A2

・L3セル:(E)作業日数を表示します。
  ・式:=COUNTA(作業時間)

・L4セル:(E)作業日数に7.75h(1日の標準作業時間)を掛けた値(F)を計算します。24で割っているのは10進⇒60進変換のため(エクセルは24hを1とするシリアル値で時間を管理しているため)。
  ・表示形式:[h]:mm
  ・式:=L3*7.75/24

・L5セル:(A)から(F)を引いた値(G)を表示します。(C)残業時間と同じ値になります。
  ・表示形式:[h]:mm
  ・式:=E33-L4

・L6セル:(H)深夜日数を表示します。
  ・式:=COUNTA(深夜時間)

【マクロ】
・出社時刻、退社時刻が入力されたら、マクロを自動起動します。
・出社時刻、退社時刻は、時刻のみ入力します。24:00以降に退社しても計算できるように、
  ・出社時刻:2014年4月1日を足す。
  ・退社時刻:2014年4月1日を足す。但し、0:00から8:30までの場合、さらに1日足して2014年4月2日とする。
  として、作業時間、残業時間、深夜時間を計算します。

・コード
' このマクロはシートに置くこと
Private Sub Worksheet_Change(ByVal Target As Range)
  If Intersect(Target, Range("出社退社")) Is Nothing Then
    ' 変化が無ければ抜ける
    Exit Sub
  Else
    ' 画面更新の停止
    Application.ScreenUpdating = False
    ' 変数の定義
    Dim Time1(20) As Date ' 時刻シリアル値(定義時刻)
    Dim Time2(10) As Date ' 時刻シリアル値(出社時刻、退社時刻)
    Dim Time4(10) As Date ' 時刻シリアル値(昼休時刻、残業開始)
    Dim n As Integer ' 整数
    Dim i As Integer ' 整数
    n = 32 ' 31日の行番号
    ' n = Cells(Rows.Count, "A").End(xlUp).Row ' A列の最終日の行
    ' 時刻定義
    Time1(0) = DateSerial(2014, 4, 1) ' 2014年4月1日
    Time1(1) = Time1(0) + TimeSerial(0, 0, 0) ' 2014年4月1日 0時0分
    Time1(2) = Time1(0) + TimeSerial(8, 30, 0) ' 2014年4月1日 8時30分
    Time1(3) = Time1(0) + TimeSerial(11, 45, 0) ' 2014年4月1日 11時45分
    Time1(4) = Time1(0) + TimeSerial(12, 0, 0) ' 2014年4月1日 12時0分
    Time1(5) = Time1(0) + TimeSerial(12, 45, 0) ' 2014年4月1日 12時45分
    Time1(6) = Time1(0) + TimeSerial(13, 0, 0) ' 2014年4月1日 13時0分
    Time1(7) = Time1(0) + TimeSerial(17, 15, 0) ' 2014年4月1日 17時15分
    Time1(8) = Time1(0) + TimeSerial(17, 30, 0) ' 2014年4月1日 17時30分
    Time1(9) = Time1(0) + TimeSerial(18, 30, 0) ' 2014年4月1日 18時30分
    Time1(10) = Time1(0) + TimeSerial(19, 0, 0) ' 2014年4月1日 19時0分
    Time1(11) = Time1(0) + TimeSerial(21, 30, 0) ' 2014年4月1日 21時30分
    Time1(12) = Time1(0) + TimeSerial(22, 0, 0) ' 2014年4月1日 22時0分
    Time1(13) = DateSerial(2014, 4, 2) ' 2014年4月2日
    Time1(14) = Time1(13) + TimeSerial(2, 15, 0) ' 2014年4月2日 2時15分
    Time1(15) = Time1(13) + TimeSerial(2, 45, 0) ' 2014年4月2日 2時45分
    Time1(16) = Time1(13) + TimeSerial(8, 15, 0) ' 2014年4月2日 8時15分
    Time1(17) = Time1(13) + TimeSerial(8, 30, 0) ' 2014年4月2日 8時30分
    ' 昼休み時間の定義
    Select Case Range("昼休開始").Value
      Case TimeSerial(11, 45, 0)
        Time4(0) = Time1(3) ' 昼休み開始(11:45)
        Time4(1) = Time1(5) ' 昼休み終了(12:45)
      Case TimeSerial(12, 0, 0)
        Time4(0) = Time1(4) ' 昼休み開始(12:00)
        Time4(1) = Time1(6) ' 昼休み終了(13:00)
      Case Else
        Time4(0) = Time1(4) ' 昼休み開始(12:00)
        Time4(1) = Time1(6) ' 昼休み終了(13:00)
      End Select
    ' 残業開始時刻の定義
    Select Case Range("残業開始").Value
      Case TimeSerial(17, 30, 0)
        Time4(2) = Time1(8) ' 残業開始(17:30)
      Case TimeSerial(19, 0, 0)
        Time4(2) = Time1(10) ' 残業開始(19:00)
      Case Else
        Time4(2) = Time1(8) ' 残業開始(17:30)
    End Select
    ' 作業時間の計算
    For i = 2 To n ' 1日から31日まで
      If IsEmpty(Cells(i, 3)) = False Then
        ' 出社時刻が入力されていれば、2014年4月1日を足す
        Time2(0) = Time1(0) + Cells(i, 3).Value ' 出社時刻
      End If
      If IsEmpty(Cells(i, 4)) = False Then
        ' 退社時刻が入力されていれば、2014年4月1日を足す
        Time2(1) = Time1(0) + Cells(i, 4).Value ' 退社時刻
        ' 退社時刻が「2014年4月1日 0時0分」から「2014年4月1日 8時30分」なら、1日ずらす(翌日退社)
        If (Time2(1) >= Time1(1)) And (Time2(1) <= Time1(2)) Then
          Time2(1) = DateAdd("d", 1, Time2(1))
          Cells(i, 4).Font.ColorIndex = 3 ' 文字色を赤に
        Else
          Cells(i, 4).Font.ColorIndex = 1 ' 文字色を黒に
        End If
      End If
      If (IsEmpty(Cells(i, 3)) = True) Or (IsEmpty(Cells(i, 4)) = True) Then
        ' 出社時刻 or 退社時刻のいずれかが空白なら、作業時間、残業時間、深夜時間に空白を代入
        Cells(i, 5).Value = "" ' 作業時間(60進)(E列)
        Cells(i, 6).Value = "" ' 作業時間(10進)(F列)
        Cells(i, 7).Value = "" ' 残業時間(60進)(G列)
        Cells(i, 8).Value = "" ' 深夜時間(60進)(H列)
      ElseIf Time2(0) > Time2(1) Then
        ' 出社時刻>退社時刻だったら、作業時間に空白を代入
        Cells(i, 5).Value = "" ' 作業時間(60進)(E列)
        Cells(i, 6).Value = "" ' 作業時間(10進)(F列)
        Cells(i, 7).Value = "" ' 残業時間(60進)(G列)
        Cells(i, 8).Value = "" ' 深夜時間(60進)(H列)
        MsgBox "出社時刻>退社時刻(" & i - 1 & "日[" & i & "行目])"
      Else
        ' 作業時間、残業時間、深夜時間の代入
        ' 作業時間(E, F列)
        If mySagyouTime1(Time1, Time2, Time4) <> 0 Then
          Cells(i, 5).Value = mySagyouTime1(Time1, Time2, Time4)
          Cells(i, 6).Value = mySagyouTime1(Time1, Time2, Time4) * 24
        Else
          Cells(i, 5).Value = ""
          Cells(i, 6).Value = ""
        End If
        ' 残業時間(G列)
        If myZangyouTime1(Time1, Time2, Time4) <> 0 Then
          Cells(i, 7).Value = myZangyouTime1(Time1, Time2, Time4)
        Else
          Cells(i, 7).Value = ""
        End If
        ' 深夜時間(H列)
        If myShinyaTime1(Time1, Time2) <> 0 Then
          Cells(i, 8).Value = myShinyaTime1(Time1, Time2)
        Else
          Cells(i, 8).Value = ""
        End If
        ' 【注】
        ' 作業時間合計のセルの表示形式を「[hh]:mm」にしておくこと。
        ' [hh]としておくことで、24以上の時間を表示できる。
      End If
    Next i
    ' セルに色を塗る
    Call Iro1
    ' 画面更新の再開
    Application.ScreenUpdating = True
  End If
End Sub

' 作業時間を算出
Function mySagyouTime1(ByRef Time1() As Date, ByRef Time2() As Date, _
ByRef Time4() As Date) As Date
  Dim Time3 As Date ' 時刻シリアル値
  Time3 = Time2(1) - Time2(0) ' 退社時刻 - 出社時刻
  ' 昼休み(11:45-12:45 or 12:00-13:00)
  If Time2(0) <= Time4(0) Then
    If Time2(1) >= Time4(1) Then
      ' 退社時刻 >= 昼休終了(12:45 or 13:00)
      Time3 = Time3 - TimeSerial(1, 0, 0)
    Else
      ' 退社時刻 < 昼休終了(12:45 or 13:00)
      Time3 = Time3 - (Time2(1) - Time4(0))
    End If
  End If
  ' 休憩(17:15-17:30)
  If Time2(0) <= Time1(7) And Time2(1) >= Time1(8) Then
    Time3 = Time3 - TimeSerial(0, 15, 0)
  End If
  ' 休憩(18:30-19:00)
  If Time2(0) <= Time1(9) And Time2(1) >= Time1(10) Then
    Time3 = Time3 - TimeSerial(0, 30, 0)
  End If
  ' 休憩(21:30-22:00)
  If Time2(0) <= Time1(11) And Time2(1) >= Time1(12) Then
    Time3 = Time3 - TimeSerial(0, 30, 0)
  End If
  ' 休憩(2:15-2:45)
  If Time2(0) <= Time1(14) And Time2(1) >= Time1(15) Then
    Time3 = Time3 - TimeSerial(0, 30, 0)
  End If
  ' 休憩(8:15-8:30)
  If Time2(0) <= Time1(16) And Time2(1) >= Time1(17) Then
    Time3 = Time3 - TimeSerial(0, 15, 0)
  End If
  mySagyouTime1 = Time3
End Function

' 残業時間を算出
Function myZangyouTime1(ByRef Time1() As Date, ByRef Time2() As Date, _
ByRef Time4() As Date) As Date
  Dim Time3(2) As Date ' 時刻シリアル値
  ' 残業の有無判定
  Time3(1) = DateAdd("n", 15, Time4(2)) ' 残業開始15分後(17:45 or 19:15)
  ' 残業開始(17:30 or 19:00)から15分以上、勤務していたら残業ありと判定
  If Time2(0) <= Time4(2) And Time2(1) >= Time3(1) Then
    Time3(0) = Time2(1) - Time4(2) ' 残業時間(休憩時間含む)
    ' 休憩(18:30-19:00)
    ' 残業開始が19:00より前、かつ、出社が18:30以前、退社が19:00以降
    If (Time4(2) < Time1(10)) And _
    (Time2(0) <= Time1(9)) And (Time2(1) >= Time1(10)) Then
      Time3(0) = Time3(0) - TimeSerial(0, 30, 0)
    End If
    ' 休憩(21:30-22:00)
    If Time2(0) <= Time1(11) And Time2(1) >= Time1(12) Then
      Time3(0) = Time3(0) - TimeSerial(0, 30, 0)
    End If
    ' 休憩(2:15-2:45)
    If Time2(0) <= Time1(14) And Time2(1) >= Time1(15) Then
      Time3(0) = Time3(0) - TimeSerial(0, 30, 0)
    End If
    ' 休憩(8:15-8:30)
    If Time2(0) <= Time1(16) And Time2(1) >= Time1(17) Then
      Time3(0) = Time3(0) - TimeSerial(0, 15, 0)
    End If
    myZangyouTime1 = Time3(0)
  Else
    myZangyouTime1 = 0
  End If
End Function

' 深夜時間を算出
Function myShinyaTime1(ByRef Time1() As Date, ByRef Time2() As Date) As Date
  Dim Time3(1) As Date ' 時刻シリアル値
  Time3(1) = DateAdd("n", 15, Time1(12)) ' 2014年4月1日 22時15分
  ' 22時0分から22時15分の間、勤務していたら深夜ありと判定
  If Time2(0) <= Time1(12) And Time2(1) >= Time3(1) Then
    Time3(0) = Time2(1) - Time1(12) ' 深夜時間(休憩時間含む)
    ' 休憩(2:15-2:45)
    If Time2(0) <= Time1(14) And Time2(1) >= Time1(15) Then
      Time3(0) = Time3(0) - TimeSerial(0, 30, 0)
    End If
    ' 休憩(8:15-8:30)
    If Time2(0) <= Time1(16) And Time2(1) >= Time1(17) Then
      Time3(0) = Time3(0) - TimeSerial(0, 15, 0)
    End If
    myShinyaTime1 = Time3(0)
  Else
    myShinyaTime1 = 0
  End If
End Function

' 作業時間、残業時間、深夜時間に着色する
Sub Iro1()
  ' 画面更新の停止
  Application.ScreenUpdating = False
  ' 変数
  Dim n As Integer ' 整数
  Dim i, j As Integer ' 整数
  Dim myRange(8) As Range
  ' myRange(0), myRange(1) : 作業時間(60進)あり/なし
  ' myRange(2), myRange(3) : 作業時間(10進)あり/なし
  ' myRange(4), myRange(5) : 残業時間(60進)あり/なし
  ' myRange(6), myRange(7) : 深夜時間(60進)あり/なし
  Dim myFlag1() As Variant ' myRangeに値がsetされたら1になるフラグ
  Dim mySelect As Range ' 選択されているセル
  Dim myColor1() As Variant ' 色番号
  myColor1() = Array(13434777, 13434777, 6750207, 6750207)
  n = 32 ' 31日の行番号
  ' n = Cells(Rows.Count, "A").End(xlUp).Row ' A列の最終日の行
  ' 作業時間あり/なし、残業時間あり/なし、深夜時間あり/なしのmyRangeのフラグ
  myFlag1() = Array(0, 0, 0, 0, 0, 0, 0, 0)
  For i = 2 To n ' 1日から31日まで
    ' 作業時間(60進)(E列)、作業時間(10進)(F列)、残業時間(60進)(G列)、深夜時間(60進)(H列)の
    ' 各セルの値を調べて、myRangeに格納
    For j = 0 To 3
      Call myChkCell1(myRange(), myFlag1(), Cells(i, j + 5), j * 2)
    Next j
    ' 現在選択されているセル
    Set mySelect = Selection
    ' セルに色を塗る
    For j = 0 To 3
      Call SetIro1(myRange(), myFlag1(), j * 2, myColor1(j)) ' 時間あり
      Call SetIro2(myRange(), myFlag1(), j * 2 + 1) ' 時間なし
    Next j
    ' セル選択を元に戻す
    mySelect.Select
  Next i
  ' 画面更新の再開
  Application.ScreenUpdating = True
End Sub

' 作業時間あり/なし、残業時間あり/なし、深夜時間あり/なしをセルごとに確認して、myRangeにセル番号を格納
Sub myChkCell1(ByRef myRange() As Range, ByRef myFlag1() As Variant, ByVal Cell1 As Range, ByVal No1 As Integer)
  ' myRange() : 作業時間あり/なし、残業時間あり/なし、深夜時間あり/なしのRange
  ' myFlag1() : myRangeに値がsetされたら1になるフラグ
  ' Cells1 : 値を確認するセルのRange
  ' No1 : myRange, myFlag1の添字
  If Cell1.Value > 0 Then
    ' 時間あり(>0)
    If myFlag1(No1) = 0 Then
      Set myRange(No1) = Cell1 ' 1セル目をセット
      myFlag1(No1) = 1 ' フラグをセット
    Else
      Set myRange(No1) = Union(myRange(No1), Cell1) ' 2セル目以降をセット
    End If
  Else
    ' 時間なし(=0)
    If myFlag1(No1 + 1) = 0 Then
      Set myRange(No1 + 1) = Cell1 ' 1セル目をセット
      myFlag1(No1 + 1) = 1 ' フラグをセット
    Else
      Set myRange(No1 + 1) = Union(myRange(No1 + 1), Cell1) ' 2セル目以降をセット
    End If
  End If
End Sub

' 選択されたセルの色を塗る
Sub SetIro1(ByRef myRange() As Range, ByRef myFlag1() As Variant, ByVal No1 As Integer, ByVal myColor1 As Long)
  If myFlag1(No1) = 1 Then
    myRange(No1).Select ' セル選択
    With Selection.Interior
      .Pattern = xlSolid
      .PatternColorIndex = xlAutomatic
      .Color = myColor1
      .TintAndShade = 0
    End With
  End If
End Sub

' 選択されたセルの色を塗る(色無し)
Sub SetIro2(ByRef myRange() As Range, ByRef myFlag1() As Variant, ByVal No1 As Integer)
  If myFlag1(No1) = 1 Then
    myRange(No1).Select ' セル選択
    With Selection.Interior
      .Pattern = xlNone
      .TintAndShade = 0
      .PatternTintAndShade = 0
    End With
  End If
End Sub
タグ:エクセル VBA
ヤバイぜ!(8)  コメント(1)  トラックバック(0) 
共通テーマ:日記・雑感

ヤバイぜ! 8

コメント 1

cheese999

「ヤバイぜ!」 ありがとうございます。[__猫]
最近、お返しが遅れていて、「記事にnice!がつきました。」メールが溜まり続けています。
申し訳ございません。
by cheese999 (2014-08-10 22:08) 

コメントを書く

お名前:[必須]
URL:
コメント:
画像認証:
下の画像に表示されている文字(英大文字の「オー」、英小文字の「ユー」、アラビア数字の「ハチ」、アラビア数字の「イチ」、アラビア数字の「ニ」)を入力してください。

Facebook コメント

トラックバック 0

トラックバックの受付は締め切りました

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。