Access VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


1679 / 2272 ツリー ←次へ | 前へ→

【5751】1日を越えた時間はどうすれば良いのでしょ... わん 05/8/4(木) 13:40 質問[未読]
【5752】Re:1日を越えた時間はどうすれば良いので... 小僧 05/8/4(木) 14:27 発言[未読]
【5753】Re:1日を越えた時間はどうすれば良いので... わん 05/8/4(木) 15:35 質問[未読]
【5754】Re:1日を越えた時間はどうすれば良いので... 小僧 05/8/4(木) 16:46 回答[未読]
【5755】Re:1日を越えた時間はどうすれば良いので... わん 05/8/4(木) 19:05 質問[未読]
【5756】Re:1日を越えた時間はどうすれば良いので... 小僧 05/8/4(木) 19:30 回答[未読]
【5757】Re:1日を越えた時間はどうすれば良いので... わん 05/8/4(木) 20:28 質問[未読]
【5760】Re:1日を越えた時間はどうすれば良いので... 小僧 05/8/5(金) 11:11 回答[未読]
【5768】Re:1日を越えた時間はどうすれば良いので... 小僧 05/8/5(金) 13:53 発言[未読]
【5776】Re:1日を越えた時間はどうすれば良いので... わん 05/8/6(土) 20:30 お礼[未読]
【5777】Re:1日を越えた時間はどうすれば良いので... わん 05/8/7(日) 14:17 お礼[未読]
【5783】Re:1日を越えた時間はどうすれば良いので... 小僧 05/8/8(月) 11:49 発言[未読]
【5784】Re:1日を越えた時間はどうすれば良いので... 小僧 05/8/8(月) 12:59 発言[未読]
【5822】Re:1日を越えた時間はどうすれば良いので... わん 05/8/10(水) 20:08 お礼[未読]

【5751】1日を越えた時間はどうすれば良いのでしょ...
質問  わん  - 05/8/4(木) 13:40 -

引用なし
パスワード
   タイムレコーダーを使用した時間管理をしようと思うのですが、
1日を越えると上手くいきません。
どこを修正すれば良いのでしょうか?

コードは以下のようになっております。

Private Sub Cls社員氏名()
Me.社員番号 = Null
Me.社員氏名 = Null
End Sub
Private Sub 退勤_Click()
 If IsNull(Me.社員番号) Then
 MsgBox "社員番号を入力して下さい。"
  Me.社員番号.SetFocus
 Exit Sub
 End If
 If DCount("*", "社員労働時間", "社員番号=Forms!タイムレコーダー!社員番号 And 打刻日付=Date()") = 0 Then
   MsgBox "出勤処理が済んでいません。"
   Call Cls社員氏名
   Exit Sub
 End If
  If DCount("*", "社員労働時間", "社員番号=Forms!タイムレコーダー!社員番号 And 打刻日付=Date()" & "And Not IsNull(退勤時間)") > 0 Then
   MsgBox "すでに退勤済みとなっています。"
   Call Cls社員氏名
   Exit Sub
 End If
 DoCmd.SetWarnings False
 DoCmd.OpenQuery "退勤打刻"
 Call Cls社員氏名
 DoCmd.SetWarnings True
End Sub

多分、ここら辺に修正を加えるのではないかと思うのですが?
If DCount("*", "社員労働時間", "社員番号=Forms!タイムレコーダー!社員番号 And 打刻日付=Date()") = 0 Then

どなたか教えて頂けますでしょうか。
お願いします。

【5752】Re:1日を越えた時間はどうすれば良いので...
発言  小僧  - 05/8/4(木) 14:27 -

引用なし
パスワード
   ▼わん さん:
こんにちは。

わんさん の働いていらっしゃる環境によって
色々考えなければならないと思います。

例えば当方の環境ですと午前中の退勤は夜勤明けしかありえませんので

Dim MyDate As Date

とでもして、変数「MyDate」に

「退勤ボタンを押す時間が12:00より早かったら Date() - 1」
「                    以降だったら  Date()  」

というロジックを組めば問題がないのですが、
・午前半休・午後半休がある
・夜勤明け残業で12:00を超える事がある(おいおい…って感じですが(笑))
・3交代制で微妙な時間がある
etc…

という訳で必ずしもうまく行くというわけでもないです。

【5753】Re:1日を越えた時間はどうすれば良いので...
質問  わん  - 05/8/4(木) 15:35 -

引用なし
パスワード
   小僧さん:
早速のご返答ありがとうございます。
労働環境のことに触れておりましたが、
例を挙げると
本日午後12:00〜翌日午前1:00の労働時間の場合があります。
(あまり笑えないですが・・・)
休憩時間は後でクエリで計算しますので気にしなくて構いません。

ですから、
>Dim MyDate As Date
>
>とでもして、変数「MyDate」に
>
>「退勤ボタンを押す時間が12:00より早かったら Date() - 1」
>「                    以降だったら  Date()  」
で良いと思います。

具体的にはどのように書き込めばよろしいのでしょうか?
お恥ずかしいのですがよくわかりません。
どうか宜しくお願いしします。

Private Sub 退勤_Click()
 Dim MyDate As Date
 ・
 ・
 ・
 If DCount("*", "社員労働時間", "社員番号=Forms!社員用タイムレコーダー!社員番号 And 打刻日付=Date()") = 0 Then
   MsgBox "出勤処理が済んでいません。"
   Call Cls社員氏名
   Exit Sub
 End If
  If DCount("*", "社員労働時間", "社員番号=Forms!社員用タイムレコーダー!社員番号 And 打刻日付=Date()" & "And Not IsNull(退勤時間)") > 0 Then
   MsgBox "すでに退勤済みとなっています。"
   Call Cls社員氏名
   Exit Sub
 End If
 ・
 ・
 ・
 End Sub

【5754】Re:1日を越えた時間はどうすれば良いので...
回答  小僧  - 05/8/4(木) 16:46 -

引用なし
パスワード
   ▼わん さん:
こんにちは。

>翌日午前1:00の労働時間の場合があります。

わん さんの職場は、午前5時に日付が替わるとすると

Dim MyDate As Date
  If Hour(Now()) < 5 Then
    MyDate = Date - 1
  Else
    MyDate = Date
  End If

これで変数「MyDate」に日付が入ります。

> If DCount("*", "社員労働時間", "社員番号=Forms!社員用タイムレコーダー!社員番号 " _
>      & "And 打刻日付=Date()") = 0 Then

ここの Date関数を先ほどの「MyDate」に置き換えるのですが、
日付型なので「#」で括る事になります。

  If DCount("*", "社員労働時間", "社員番号=Forms!社員用タイムレコーダー!社員番号 " _
      & "And 打刻日付 = #" & MyDate & "#") = 0 Then

もう一箇所の Date 関数も同じ事をしてあげてください。

もし説明が解り難いようでしたら再度ご質問下さい。

【5755】Re:1日を越えた時間はどうすれば良いので...
質問  わん  - 05/8/4(木) 19:05 -

引用なし
パスワード
   小僧さん:
 大変解りやすくご説明いただきありがとうございます。
 時間の考え方も理解できました。

教えて頂いた通り実際にやってみました。
2つ問題点が発生しました。

1つめは、
こちらでストップしてしまいます。
コードの書き方が悪いのでしょうか?
If DCount("*", "社員労働時間", "社員番号=Forms!社員用タイムレコーダー!社員番号 And 打刻日付=#" & MyDate & "#") " & "And Not IsNull(退勤時間)") > 0 Then

2つめは、
上のコードを書きかえずに、教えていただいたコードだけを書きかえて実行したところ止まることはなかったのですが、テーブルに書き込まれませんでした。
ちなみにテーブルは以下のようになっています。
勤怠ID 社員番号  打刻日付   出勤時間  退勤時間 
1    太郎   2005年8月1日  9:50:00  22:10:10
2    花子   2005年8月1日  9:55:00  22:10:30
3    一郎   2005年8月1日  11:50:20        ←ここが問題です。
・     ・      ・      ・
・     ・      ・      ・
・     ・      ・      ・     

出勤時(追加クエリ)と退勤時(更新クエリ)となっています。
お忙しいとは思いますが宜しくお願いします。


▼小僧 さん:
>▼わん さん:
>こんにちは。
>
>>翌日午前1:00の労働時間の場合があります。
>
>わん さんの職場は、午前5時に日付が替わるとすると
>
>Dim MyDate As Date
>  If Hour(Now()) < 5 Then
>    MyDate = Date - 1
>  Else
>    MyDate = Date
>  End If
>
>これで変数「MyDate」に日付が入ります。
>
>> If DCount("*", "社員労働時間", "社員番号=Forms!社員用タイムレコーダー!社員番号 " _
>>      & "And 打刻日付=Date()") = 0 Then
>
>ここの Date関数を先ほどの「MyDate」に置き換えるのですが、
>日付型なので「#」で括る事になります。
>
>  If DCount("*", "社員労働時間", "社員番号=Forms!社員用タイムレコーダー!社員番号 " _
>      & "And 打刻日付 = #" & MyDate & "#") = 0 Then
>
>もう一箇所の Date 関数も同じ事をしてあげてください。
>
>もし説明が解り難いようでしたら再度ご質問下さい。

【5756】Re:1日を越えた時間はどうすれば良いので...
回答  小僧  - 05/8/4(木) 19:30 -

引用なし
パスワード
   ▼わん さん:
こんばんは。

>1つめは、
>If DCount("*", "社員労働時間", "社員番号=Forms!社員用タイムレコーダー!社員番号 And " _
>     & "打刻日付=#" & MyDate & "#") " & "And Not IsNull(退勤時間)") > 0 Then

閉じカッコの位置がおかしい…ですね。

If DCount("*", "社員労働時間", "社員番号=Forms!社員用タイムレコーダー!社員番号 And " _
     & "打刻日付=#" & MyDate & "# And Not IsNull(退勤時間)") > 0 Then


>2つめは、
>ちなみにテーブルは以下のようになっています。
>勤怠ID 社員番号  打刻日付   出勤時間  退勤時間 
>1    太郎   2005年8月1日  9:50:00  22:10:10
>2    花子   2005年8月1日  9:55:00  22:10:30
>3    一郎   2005年8月1日  11:50:20        ←ここが問題です。
>・     ・      ・      ・
>・     ・      ・      ・
>・     ・      ・      ・     
>
>出勤時(追加クエリ)と退勤時(更新クエリ)となっています。
>お忙しいとは思いますが宜しくお願いします。

直接の原因かどうかは解りませんが、「2005年8月1日」という表記ですと
打刻日付は「日付型」でなくて「テキスト型」でしょうか?
そうですと、「#」の部分が「'」となりますね。

あとは
>DoCmd.OpenQuery "退勤打刻"

にある「退勤打刻」クエリの中身ですが…。
ここにもDate関数を使っていませんでしょうか?

【5757】Re:1日を越えた時間はどうすれば良いので...
質問  わん  - 05/8/4(木) 20:28 -

引用なし
パスワード
   ▼小僧 さん:
早速のご返信感謝致します。
度々ですがお願いします。
打刻日付は日付型です。書式は日付(L)となっております。
先程教えていただいたコードも謝りがあったので訂正しました。

今度は、どちらにも構文エラーが発生しました。
 構文エラーの内容は以下の通りです。
 クエリ式
 社員番号=Forms!社員用タイムレコーダー!社員番号And打刻日付
 =#2005/08/01#'の構文エラー:演算子がありません


早速コードを見直して書き直しました。
確認のため、そのままをコピーします。

1つめ
If DCount("*", "社員労働時間", "社員番号=Forms!社員用タイムレコーダー!社員番号" & "And 打刻日付=#" & MyDate & "#") = 0 Then

2つめ
  If DCount("*", "社員労働時間", "社員番号=Forms!社員用タイムレコーダー!社員番号 And" & " 打刻日付=#" & MyDate & "# And Not IsNull(退勤時間)") > 0 Then

>あとは
>>DoCmd.OpenQuery "退勤打刻"
>
>にある「退勤打刻」クエリの中身ですが…。
>ここにもDate関数を使っていませんでしょうか?

クエリの中身は以下のようになっています。

「出勤打刻」
フィールド  式1:Forms!タイムレコーダー!社員番号   式2:Date()   式3:Now()
レコードの追加        社員番号            打刻日付    出勤時間

「退勤打刻」
フィールド   退勤時間   打刻日付     社員番号
レコードの更新   Now()              
抽出条件             Date()   Forms!タイムレコーダー!社員番号

情けないことですが、どうか宜しくお願いいたします。

【5760】Re:1日を越えた時間はどうすれば良いので...
回答  小僧  - 05/8/5(金) 11:11 -

引用なし
パスワード
   ▼わん さん:
おはようございます。

>情けないことですが、どうか宜しくお願いいたします。

いえいえ、わん さんだけでなく、同じ様な事で困っている他の方が
今後過去ログとして参考になさるかもしれません。

わん さんのご提示される内容も段々と当方に伝わりやすくなっていますよ。

>DCount("*", "社員労働時間", "社員番号=Forms!社員用タイムレコーダー!社員番号" _
>      & "And 打刻日付=#" & MyDate & "#") = 0

こちらは当方の検証不足でした。すみません。

「Forms!社員用タイムレコーダー!社員番号」も「"」の外に出す必要があります。
※フォーム名、コントロール名である事を明記する [ ] をつけてあります。

>>DCount("*", "社員労働時間", "社員番号 =" & Forms![社員用タイムレコーダー].[社員番号] _
>>       & "And 打刻日付 = #" & MyDate & "#") = 0 Then

>>DCount("*", "社員労働時間", "社員番号 =" & Forms![社員用タイムレコーダー].[社員番号] _
>>    & "And 打刻日付 = #" & MyDate & "# And Not IsNull(退勤時間)") > 0

退勤ボタンが「社員用タイムレコーダー」フォームにあるのであれば、

>>If DCount("*", "社員労働時間", "社員番号 = " & Me.社員番号 _
>>       & "And 打刻日付 = #" & MyDate & "#") = 0 Then

>>If DCount("*", "社員労働時間", "社員番号 = " & Me.社員番号 _
>>    & "And 打刻日付 = #" & MyDate & "# And Not IsNull(退勤時間)") > 0 Then


>クエリの中身は以下のようになっています。

見事に退勤打刻クエリに「Date」関数がいらっしゃいますね。

UPDATE 社員労働時間 SET 社員労働時間.退勤時間 = Now()
WHERE (((社員労働時間.社員番号)=[Forms]![社員用タイムレコーダー]![社員番号])
AND ((社員労働時間.打刻日付)=IIf(Hour(Now())>11,Date(),Date()-1)));

上記 SQL をクエリのSQLビューに貼り付けて確認されてみて下さい。

【5768】Re:1日を越えた時間はどうすれば良いので...
発言  小僧  - 05/8/5(金) 13:53 -

引用なし
パスワード
   ▼小僧 さん:
ごめんなさい。
11時を超えると日付が変わるかどうかを実験していたので(笑)
5時でしたら「Hour(Now())>5」です。

UPDATE 社員労働時間 SET 社員労働時間.退勤時間 = Now()
WHERE (((社員労働時間.社員番号)=[Forms]![社員用タイムレコーダー]![社員番号])
AND ((社員労働時間.打刻日付)=IIf(Hour(Now())>5,Date(),Date()-1)));

【5776】Re:1日を越えた時間はどうすれば良いので...
お礼  わん  - 05/8/6(土) 20:30 -

引用なし
パスワード
   小僧さん:


お返事が遅くなり申し訳ありませんでした。
出張に行っていたもので拝見することができませんでした。
今回もご丁寧な回答ありがとうございます。

早速、やってみます。
また、解らないことがありましたら
ご教授お願いいたします。

【5777】Re:1日を越えた時間はどうすれば良いので...
お礼  わん  - 05/8/7(日) 14:17 -

引用なし
パスワード
   小僧さん:

できました。長い間お付き合い下さりありがとうございました。
心より御礼申し上げます。

投稿する前に20冊以上の書籍を読みあさったのですが、
24時を超えて処理することに関する書籍が見つからなく大変困っておりました。
何しろAccessを始めて、まだ2週間足らずなもので、
それに加えて変数処理と合わせた応用がきかず混乱していまい、大変助かりました。

お世話になりついでに時間計算と時間表示について教えて頂きたいのですが、

過去の投稿で
【3605】日日をまたいだ時の時間の計算
【4411】時刻の切捨て切り上げについて
を読むと、

通常の計算方法と異なる処理が必要であることが書かれているようですが、
今回の場合は1日の起点を午前5時としているのでこの処理は必要なく、
一般的な計算式で計算されると考えてよろしいのでしょうか?

Time関数についてクエリで試してみたところ未定義関数となってしまいました。
これは使い方が間違っているからなのでしょうか。
(現在使用しているOSはWinXPPro、Access2000)
又、表示方法の問題だけならMod演算子、\演算子をよく勉強すれば、
Time関数なるものは使用しなくてもできるものなのでしょうか?

今後の参考のために、教えて頂けたら有り難いと思います。

今回は、本当に有難うございました。

【5783】Re:1日を越えた時間はどうすれば良いので...
発言  小僧  - 05/8/8(月) 11:49 -

引用なし
パスワード
   ▼わん さん:
こんにちは。

>お世話になりついでに時間計算と時間表示について教えて頂きたい

Access(VBA) の日付型に関してなのですがイミディエイトウィンドウ
(コードが表示されている状態で Ctrl + g)で確認してみましょう。

今日の日付がテーブルにあるとすると、その値は

>>>イミディエトウィンドウで「? CDbl(Date)」

「1900/01/01」からの差分である「38572」という数値になっています。

では時間はどうなっているのかとなると、

>>>「? CDbl(Now())」

小数がでてきましたよね。これが時間の部分になっています。


さて、[#3605]日日をまたいだ時の時間の計算の場合は

「PM5時」「AM1時30分」などの値が出てきますが、実際の値を調べてみると

>>>「? CDbl(#17:00#)」「? CDbl(#1:30#)」

と小数が表示されますが、整数部分は「0」になっています。
これは表示されている値は「17:00」ですが、
実際には「1899/12/30 1:30」という値が入っている事になります。

↑の方で「? CDbl(Date)」としましたが、
これも実際には「2005/08/08 00:00:00」という値ですね。

過去ログの方では「日付を持たない時間」を対象としているために

>DateDiff("n",[作業開始時間],[作業終了時間]+IIf([作業終了時間]<[作業開始時間],1,0))

となっていますが。今回は「Now()」で時間を代入しているため日付を持たせているので
そのまま「退勤時間」から「出勤時間」を引けば良いと思われます。

>>>「? DateDiff("n",#2005/08/08 12:00#,#2005/08/09 1:00#)」
>>>「? CDate(#2005/08/09 1:00# - #2005/08/08 12:00#)」

【5784】Re:1日を越えた時間はどうすれば良いので...
発言  小僧  - 05/8/8(月) 12:59 -

引用なし
パスワード
   ▼わん さん:
こんにちは。
続けて時間の丸めについてです。

>[#4411] 時刻の切捨て切り上げについて

>勤怠管理に役立つ時刻演算関数集
>http://www.f3.dion.ne.jp/~element/msaccess/AcTipsVbaCalcTimeFunctions.html
>こちらが参考になると思います。


YU-TANG さんのサイトが紹介されているので、
せっかくですから使わせて頂きましょう。

ここで紹介されている関数はユーザー定義関数なので、そのままでは使えません。
ページの中ほどにある「ダウンロード」の説明を読んでインポートしてみましょう。
(わんさんの環境がダウンロードをしてはいけない環境でしたらすみません)

SELECT 社員労働時間.社員番号, TimeRound([出勤時間],-1,15) AS 出勤丸め,
TimeRound([退勤時間],-1,15) AS 退勤丸め
FROM 社員労働時間;

SQL ビューで確認してみて下さい。15分を切り捨てで丸められていると思います。

>又、表示方法の問題だけならMod演算子、\演算子をよく勉強すれば、
>Time関数なるものは使用しなくてもできるものなのでしょうか?

ダウンロードできない環境の場合、ユーザ定義関数を使いたくない場合です。

SELECT 社員労働時間.社員番号,
DateAdd("n", - Minute([出勤時間]) Mod 15,[出勤時間]) AS 出勤丸め,
DateAdd("n", - Minute([退勤時間]) Mod 15,[退勤時間]) AS 退勤丸め
FROM 社員労働時間;

15分以下を切り捨てるようなクエリになっています。

余談ですが、大手ファーストフードで賃金30分未満切り捨てが問題になっていましたね。
http://headlines.yahoo.co.jp/hl?a=20050801-00000086-mai-soci

労働基準法を読んでいないので良く解りませんが、
勝手に切り捨てるのはまずいのでしょうか…(笑)

【5822】Re:1日を越えた時間はどうすれば良いので...
お礼  わん  - 05/8/10(水) 20:08 -

引用なし
パスワード
   小僧さん:
こんばんわ。

今回もとても丁寧で理解しやすい説明をありがとうございました。
早速、トライしてみます。

感謝の気持ちでいっぱいです。
これからも宜しくお願いします。

1679 / 2272 ツリー ←次へ | 前へ→
ページ:  ┃  記事番号:
1078259
(SS)C-BOARD v3.8 is Free