プロが教えるわが家の防犯対策術!

エクセル初心者です。
勤務時間が自動計算できる表を作ろうとしています。
A1に出勤時間、B1に退社時間を入れ、C1に勤務時間が自動で入る…といったものです。

http://oshiete.goo.ne.jp/qa/8754769.htmlを参考にして、
下記マクロを入れるところまではできました。

If Intersect(Target, Range("A:B")) Is Nothing Or Target.Count > 1 Then Exit Sub
With Target
If .Value <> "" Then
If IsNumeric(.Value) Then
If .Value < 2400 And .Value Mod 100 < 60 Then
Application.EnableEvents = False
.Value = TimeSerial(Int(.Value / 100), .Value Mod 100, 0)
.NumberFormatLocal = "h:mm"
Application.EnableEvents = True
Else
MsgBox "入力値が不正です"
.Select
.ClearContents
End If

ここまではよかったのですが、同じシートで三名分の出退勤を管理するために
上記マクロをコピペしてRange(”A:B”)の数値だけ変えてみてもダメでした。
どのように変更すればいいのでしょうか。

わかりにくい質問ですがご教授ください。

A 回答 (4件)

こんにちは。



>A1に出勤時間、B1に退社時間を入れ、C1に勤務時間が自動で入る
質問としては、A列/B列に入れたら、C列が自動的に出てくるのをマクロで行うという意味なのでしょうか?
それは、少しやっかいですね。それらにまつわる時間の休み時間とか、どうするのでしょうか?
日をまたぐ計算も出てくるのでしょうか?

昼の休憩は、1時間(12~13時)、夜休憩は、18~19:30分というところかな。
深夜もありますね。深夜は省略します。残業時間などの計算もまだ含まれていません。
マクロの専門の人なら、どうということもありませんが、マクロ処理は、なかなか難しくなってしまうからです。

たぶん、私のマクロは、もう4~5回、同じようなものを書いていますが、毎度同じ使われないとは思うのですが、こんなようになると感じていただければ幸いです。

>(A1,B1,C1)、(E1,F1,G1)、(I1,J1,K1)
>という風になり、参照先の列が変わってしまうのです
つまり、私の方法では、D列, H列には値は入れられません。

TimeDiff(Time1, Time2) ユーザー定義関数のところで、細かな計算をしていきます。

この項目の最後は、カーソルが右に動かすためのボタン用のマクロです。トグルになっていますから、もう一度実行すれば、カーソルは下に行くようになります。


'//シートモジュール
Private Sub Worksheet_Change(ByVal Target As Range)
 Dim myTime As Variant
 With Target
 If .Count > 1 Then Exit Sub
 If .Value = "" Then Exit Sub
 If Not IsNumeric(.Value) Then Exit Sub
 If .Column Mod 4 = 0 Then .ClearContents: Exit Sub
  Application.EnableEvents = False
  If .Column Mod 4 > 0 Then
   .ClearFormats
   .NumberFormatLocal = "[h]:mm"
   .Value = Num2Time(.Value2)
  End If
  If .Column Mod 4 = 2 Then
   .Offset(, 1).ClearFormats
   .Offset(, 1).NumberFormatLocal = "[h]:mm"
   .Offset(, 1).Value = TimeDiff(.Offset(, -1).Value, .Value)
  End If
  Application.EnableEvents = True
 End With
End Sub

Private Function Num2Time(ByVal myValue As Variant)
'数値時間変換
Dim myTime As Variant
Dim myH As Long
If Len(myValue) > 4 Then myTime = Left(myValue, 4)
 myTime = Format$(myValue, "00:00")
 myH = Mid(myTime, 1, 2)
 If myH >= 24 Then
  myTime = (myH \ 24) + (myH Mod 24) / 24 + Mid(myValue, 4, 2) / (24 * 60#)
 Else
   myTime = (myH Mod 24) / 24 + Mid(myTime, 4, 2) / (24 * 60#)
 End If
 Num2Time = myTime
End Function

Private Function TimeDiff(Time1, Time2)
'時間計算 Time1:出社時間 Time2:退社時間
Dim BeginT As Double: BeginT = TimeValue("8:30") '始業
Dim EndT As Double: EndT = TimeValue("17:30") '終業
Dim sDBreak As Double: sDBreak = TimeValue("12:00") '昼始め
Dim eDBreak As Double: eDBreak = TimeValue("13:00") '昼終わり
Dim diff1 As Double
Dim diff2 As Double
If Time1 < 1 Then
 diff1 = sDBreak - Application.Min(Time1, sDBreak)
 diff2 = EndT - Application.Min(Time2, eDBreak)
 TimeDiff = diff1 + diff2
Else
 '夜交代制用
End If
End Function

Sub ChangeDirect() 'これは、別途ボタンに付けるとよいでしょう。
'右にカーソルが進んだり、下に進んだりする設定マクロ・これはトグルになっています。
 With Application
  If .MoveAfterReturnDirection = xlToRight Then
   .MoveAfterReturnDirection = xlDown
   MsgBox "カーソルが下に進みます"
  Else
   .MoveAfterReturnDirection = xlToRight
   MsgBox "カーソルが右に進みます"
  End If
 End With
End Sub
'///
    • good
    • 0

No.1です。



>そのため(出社、退社、勤務時間)がそれぞれ
>(A1,B1,C1)、(E1,F1,G1)、(I1,J1,K1)
>という風になり

すでにNo.2さんが回答されていますので、余計なお世話かもしれませんが

If Intersect(Target, Range("A:B,E:F,I:J")) Is Nothing Or Target.Count > 1 Then Exit Sub
でも大丈夫だと思います。

※ 1か月分というコトですので、範囲をもっと限定し
Range("A1:B31,E1:F31,I1:J31")
とすれば同列の他のセルは通常の表示になります。

※ C・G・K列は前回のような数式で処理します。m(_ _)m
    • good
    • 0

If Intersect(Target, Range("A:B")) Is Nothing Or Target.Count > 1 Then Exit Sub



の部分を

If Intersect(Target, Union(Range("A:B"), Range("E:F"), Range("I:J"))) Is Nothing Or Target.Count > 1 Then Exit Sub

にしてください。
    • good
    • 0

こんばんは!



>A1に出勤時間、B1に退社時間を入れ、C1に勤務時間が自動で入る…といったものです。
すなわちA・B列に時刻を入力すればC列に自動で勤務時間を表示させたい!というコトでしょうか?

そうであればお示しのコードそのままで
C1セル(セルの表示形式やユーザー定義から [h]:mm としておく)に
=IF(COUNT(A1:B1)=2,B1-A1,"")
という数式を入れフィルハンドルで下へ3行分コピーしてみてはどうでしょうか?

※ 休憩時間(昼食時間)等引き算が必要な場合、仮に1時間の休憩時間がある場合は
=IF(COUNT(A1:B1)=2,B1-A1-"1:00","")
のように適宜変更してみてください。

※ 3名分だけというコトなので、ChangeイベントはA・B列すべてに適応するのでなく
>Range("A:B")
の部分を
>Range("A1:B3")
のように変更しても良いと思います。

通常、1行目は項目行にするのが一般的ですので、実際データ入力はA2~B4の範囲だと
>Range("A2:B4")
のように変更してください。
当然のコトですが、C列の数式は2行目以降に入るコトになり
=IF(COUNT(A2:B2)=2,B2-A2-"1:00","")
になると思います。m(_ _)m
    • good
    • 0
この回答へのお礼

丁寧な回答ありがとうございます!

質問が説明不足で申し訳ないのですが
タテに1ヶ月分の勤怠表をヨコに3名分並べたいです。
そのため(出社、退社、勤務時間)がそれぞれ
(A1,B1,C1)、(E1,F1,G1)、(I1,J1,K1)
という風になり、参照先の列が変わってしまうのです。

この場合でも対処法はあるのでしょうか。
重ねての質問になりすみません。

お礼日時:2015/08/27 23:32

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!