Access VBA質問箱 IV

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

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


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

【5829】時間の計算について わん 05/8/11(木) 14:01 質問[未読]
【5831】Re:時間の計算について 小僧 05/8/11(木) 14:35 回答[未読]
【5833】Re:時間の計算について わん 05/8/11(木) 15:17 お礼[未読]
【5850】Re:時間の計算について わん 05/8/12(金) 13:42 質問[未読]
【5851】Re:時間の計算について 小僧 05/8/12(金) 16:02 発言[未読]
【5852】Re:時間の計算について わん 05/8/13(土) 15:26 お礼[未読]
【5858】Re:時間の計算について 小僧 05/8/15(月) 13:23 発言[未読]
【5859】Re:時間の計算について わん 05/8/15(月) 14:47 お礼[未読]
【5865】Re:時間の計算について わん 05/8/17(水) 11:05 質問[未読]
【5867】Re:時間の計算について 小僧 05/8/17(水) 11:26 発言[未読]
【5869】Re:時間の計算について わん 05/8/17(水) 12:37 質問[未読]
【5872】Re:時間の計算について 小僧 05/8/17(水) 13:45 発言[未読]
【5873】Re:時間の計算について わん 05/8/17(水) 14:16 発言[未読]
【5879】Re:時間の計算について 小僧 05/8/17(水) 15:39 発言[未読]
【5886】Re:時間の計算について わん 05/8/17(水) 17:16 お礼[未読]
【5891】Re:時間の計算について 小僧 05/8/17(水) 18:19 発言[未読]
【5894】Re:時間の計算について わん 05/8/18(木) 2:23 質問[未読]
【5900】Re:時間の計算について 小僧 05/8/18(木) 12:02 回答[未読]
【5901】Re:時間の計算について わん 05/8/18(木) 12:51 お礼[未読]
【5906】Re:時間の計算について わん 05/8/18(木) 16:12 お礼[未読]
【5908】Re:時間の計算について 小僧 05/8/18(木) 16:54 発言[未読]
【5910】Re:時間の計算について わん 05/8/18(木) 17:20 質問[未読]
【5912】Re:時間の計算について 小僧 05/8/18(木) 18:02 発言[未読]
【5922】Re:時間の計算について わん 05/8/19(金) 2:51 発言[未読]
【5939】Re:時間の計算について 小僧 05/8/21(日) 8:05 発言[未読]
【5942】Re:時間の計算について わん 05/8/21(日) 22:00 質問[未読]
【5946】Re:時間の計算について 小僧 05/8/22(月) 9:51 回答[未読]
【5965】Re:時間の計算について わん 05/8/22(月) 20:42 お礼[未読]

【5829】時間の計算について
質問  わん  - 05/8/11(木) 14:01 -

引用なし
パスワード
   小僧さんお願いします。

前回の投稿が長くなったので、
新規投稿に変えました。
質問内容は、前回の続きと考えております。

現在の自分のレベルを考慮し、ユーザー定義関数を使用しないでやってみました。

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

↑について問題なくできました。

繰り上げにトライしたのですが上手くいきません。
単純に-を+にしただけではダメなのですね。

DateAdd関数、Mod演算子については少し理解できましたが、
コード自体の意味を完全に理解できていないからだと思います。
(何とも自分が情けなく、お恥ずかしい限りです)

度々で申し訳ありませんが教えて頂きたいと思います。
宜しくお願いします。

【5831】Re:時間の計算について
回答  小僧  - 05/8/11(木) 14:35 -

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

>小僧さんお願いします。

他の回答者の方が答え難くなっちゃいますよ ^^;


>コード自体の意味を完全に理解できていないからだと思います。

では前回のおさらいからという事で…。

出勤時間   分 Mod 15    補正された時間
xx:10      10     →    xx:00   
xx:15      0     →    xx:15   
xx:37      7     →    xx:30   
xx:59      14     →    xx:45

>>DateAdd("n", - Minute([出勤時間]) Mod 15,[出勤時間]) AS 出勤丸め,

「出勤時間」 から 「出勤時間の[分]を15で割った余り」 を 
「引いたもの(実際には−をつけたものを足しています。)が補正された時間です。

>繰り上げにトライしたのですが上手くいきません。
>単純に-を+にしただけではダメなのですね。

さて、こちらの方ですが

出勤時間   分 Mod 15     切捨てた時間   切り上げた時間
xx:10        10     →    xx:00      (xx:15)
xx:15        0     →    xx:15      (xx:30)
xx:37       7     →    xx:30      (xx:45)
xx:59       14     →    xx:45      (xx:00)繰り上がって

「切上」と考えるとややこしくなりますがちょっと発想を変えると
切捨てた時間に15分足せば良い事に気が付きませんか?

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

切捨てと切上げを見比べてみて下さい。

【5833】Re:時間の計算について
お礼  わん  - 05/8/11(木) 15:17 -

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

小僧さんはホントに素晴らしい!!
私のような初心者にこんなに解りやすく
親切丁寧に説明していただけるなんて有難うございます。
感激です。
時間や日付に関する考え方がかなり理解できました。
あとは、実際の時間計算だけですね。
何とか自力でできるよう頑張ってみます。

>他の回答者の方が答え難くなっちゃいますよ ^^;
失礼致しました。
基本をしっかり身につけるのには、状況を把握してくださっている方に
教えて頂く方が賢明かと思ったものですから。
ここのルールに反していたら申し訳ありません。

【5850】Re:時間の計算について
質問  わん  - 05/8/12(金) 13:42 -

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

時間計算をしていましたが行き詰まりました。
労働時間、残業時間はできたのですが、
22:00以降の残業計算で頭がこんがらがってしまいました。
(計算に用いている時間は数値が細かくなり過ぎないように切捨て、切上げしているものを使用しています。)

現在のSQLビューの全文は以下のようになっています。

SELECT 社員労働時間.社員番号, 社員労働時間.打刻日付, 社員労働時間.出勤時間, 社員労働時間.退勤時間,
DateAdd("n",15-Minute([出勤時間]) Mod 15,[出勤時間]) AS 出勤,
DateAdd("n",-Minute([退勤時間]) Mod 15,[退勤時間]) AS 退勤,
(DateDiff("n",[出勤],[退勤])-60)/60 AS 労働時間,
(DateDiff("n",[出勤],[退勤])-540)/60 AS 残業時間,
IIf(Hour([退勤])<=22,0,IIf(((DateDiff("n",[出勤],[退勤])-60)/60)>=540,(Hour([退勤])-22))) AS 深夜残業
FROM 社員労働時間;

IIf(Hour([退勤])<=22,0,IIf(((DateDiff("n",[出勤],[退勤])-60)/60)>=540,(Hour([退勤])-22))) AS 深夜残業

一応↑のように考えてみたのですが、22:00前は0で表示されますが、
22:00以降は未表示になります。
また、今のままでは正確に22:00を過ぎた状態から計算されていません。

もしかしたら、
IIfではなくBetween #〜# And #〜# で考えなければいけないような気もするのですが、
混乱してきました。

何処に誤りがあるのかご指摘をお願いします。
宜しくお願いします。

【5851】Re:時間の計算について
発言  小僧  - 05/8/12(金) 16:02 -

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

>22:00以降の残業計算で頭がこんがらがってしまいました。
>混乱してきました。

業務の合間に作っているのですが
同じく混乱中です…。

深夜残業: IIf(DateDiff("n",[出勤],[退勤])<600 Or Hour([退勤]) Between 5 And 22,0,DateDiff("n",CDate([打刻日付] & ' 22:00'),[退勤]))/60

でできたと思ったのですが、

残業 > 深夜残業

の処理が抜けてました…。

[退勤] - [出勤] > 8h 以上
[退勤] > 22:00
[残業] > [深夜残業]  であれば[退勤] - [打刻日付の22:00]


[退勤] - [出勤] > 8h 以上
[退勤] > 22:00
[残業] < [深夜残業]  であれば[残業]

その他 0

の3パターンなのですが、ちょっと複雑すぎるので
もう少し整理できたらまた回答させて頂きます。

【5852】Re:時間の計算について
お礼  わん  - 05/8/13(土) 15:26 -

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

その後、落ち着いて考えてみました。

基本勤務形態として 09:00〜18:00、12:00〜21:00、15:00〜00:00であり、
深夜は必ずしも残業とは限らず、深夜残業として考えると難しくなるので、
単純に深夜勤務として考えてみました。


残業時間は算出されているので、
↓のように深夜勤務22:00〜5:00の勤務時間を算出してみました。

深夜勤務: IIf(Hour([退勤]) Between 5 And 22,0,DateDiff("n",CDate([打刻日付] & ' 22:00'),[退勤]))/60

あとは、残業の割増率と深夜勤務の割増率から増加分を算出し、
合算する方法を検討しています。

他にもっと簡単な方法があればご教授下さい。
宜しくお願いします。

【5858】Re:時間の計算について
発言  小僧  - 05/8/15(月) 13:23 -

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

>その後、落ち着いて考えてみました。
同じく落ち着いて考えてみました。

SELECT 社員労働時間.社員番号,
    社員労働時間.打刻日付,
    DateAdd("n",15-Minute([出勤時間]) Mod 15,[出勤時間]) AS 出勤,
    DateAdd("n",-Minute([退勤時間]) Mod 15,[退勤時間]) AS 退勤,
    DateDiff("n",[出勤],[退勤])/60-1 AS 労働時間,
    IIf(Hour([退勤]) Between 5 And 22,DateDiff("n",[出勤],[退勤]),
          DateDiff("n",[出勤],CDate([打刻日付] & ' 22:00')))/60-1 AS 日勤,
    IIf(Hour([退勤]) Between 5 And 22,0,
          DateDiff("n",CDate([打刻日付] & ' 22:00'),[退勤]))/60 AS 夜勤,
    IIf([日勤]>8,[日勤]-8,0) AS 日勤残業,
    IIf([労働時間]>9,DateDiff("n",[出勤],[退勤])/60-[日勤残業]-9,0) AS 夜勤残業
FROM 社員労働時間;

10件くらい色々データを入れて検証した結果は問題なさそうなのですが、
わんさん の実際使われているデータでも問題なければ良いのですが…。

【5859】Re:時間の計算について
お礼  わん  - 05/8/15(月) 14:47 -

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

一応、私のSQLでも大丈夫でしたが、
その後の給与計算のためのクエリ数が増えて、
更にクエリ中の計算式も確かに多く面倒です。

早速、小僧さん方式を試してみます。
一目見て、小僧さん方式が後々のことも考慮されており、
スッキリしていることが解るようになりました。

今回のご指導で日付・時間だけでなく、クエリについてや変換関数についても
深く理解できました。

本当にありがとうございました。
只今、出勤、退勤以外に休憩入及び休憩出のコマンドを追加してトライしています。

今までの応用をきかせて頑張ります。
また、何か問題が発生した場合はお願い致します。

ありがとうございました。

【5865】Re:時間の計算について
質問  わん  - 05/8/17(水) 11:05 -

引用なし
パスワード
   >小僧さん
>こんにちわ。
その後、全て時間計算についてのデータベースが出来上がりました。

お礼を兼ねてご報告申し上げます。
本当にありがとうございました。

ところで、過去ログ【5570】について教えて頂きたいのですが、
私も、同じように今回の時間計算結果の確認用として
フォームを使って複数検索をやって見たのですが上手くいきません。

フォームの元になるデータはクエリです。

↓のようにしてみたのですがMe.Filter = Kensakuで引っかかってしまいます。
何がいけないのでしょうか?
テキスト検索:テキストボックス
検索:コマンドボタン

Private Sub 検索_Click()
 Dim Kensaku As String
Dim S As Variant
Dim I As Long
  If InStr(1, Me.テキスト検索.Value, ",") > 0 Then
    S = Split(Me.テキスト検索.Value, ",")
      For I = 0 To UBound(S, 1)
        Kensaku = Kensaku & "([月度] And [氏名] LIKE '*" & S(I) & "*') And "
      Next
    Kensaku = Left(Kensaku, Len(Kensaku) - 4)
  Else
    Kensaku = "[月度] and [氏名] LIKE '*" & Me.テキスト検索.Value & "*'"
  End If
  
  Me.Filter = Kensaku
  Me.FilterOn = True
End Sub

お忙しいところ申し訳ありませんが宜しくお願いします。

【5867】Re:時間の計算について
発言  小僧  - 05/8/17(水) 11:26 -

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

>複数検索

[#5570]で質問をされた方の場合、

>一つのテキストボックスに、検索wordをカンマで区切って
>入力していくようなことってできますか?

という事でしたので、「鈴木,佐藤」と入力すると
鈴木さんと佐藤さんのデータの抽出ができるような方法でしたので、

>[月度] And [氏名]

という場合とちょっと違いますよね。

月度、氏名と別々のテキスト(コンボ)ボックスから抽出で宜しければ、
先ほど他の方へ回答させて頂いた

[#5863]検索用フォームの作成

あたりが参考になるかと思われます。

同じテキストボックスにカンマ区切りで抽出したいのであれば
結構面倒な処理になりそうです…。(月が数字で名前が文字列になるので…)

【5869】Re:時間の計算について
質問  わん  - 05/8/17(水) 12:37 -

引用なし
パスワード
   小僧さん
早速のご返信ありがとうございます。

私も[#5863]検索用フォームの作成を試してみました。
これで問題なくできると思います。

1つ疑問なのですが、
コンボボックスの利用というのはどの位の件数までが妥当なのでしょうか?

仮に、ポジションに相当するものを月度とし、年齢に相当するものを名前とすると
月度は1年に12個ずつ増えて、名前に関しては100人以上います。
それでも、コンボボックスの方が良いのでしょうか。

【5872】Re:時間の計算について
発言  小僧  - 05/8/17(水) 13:45 -

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

>コンボボックスの利用というのはどの位の件数までが妥当なのでしょうか?

これは使う人によるので何とも言えないのですが…。

コンボボックスによる利点として、もちろんユーザの手間を省けるという点がありますが、
作り手にとっても大きなポイントがあります。ユーザに自分勝手な入力をさせない点(笑)です。

こちらとしては「2005/08」と入れて欲しいのに「2005.08」「2005/8」の様に
入力して結果が返ってこない等という事が多々ありますが、そうなると作り手は

・こちらの意図としないものは全部エラーで返す
・「.」は「/」に自動変換、桁数は補正

余計な手間が増えることになります。年と月を選ぶだけなのに…。

という事で「月度」はコンボボックスがお勧めです。

>名前に関しては100人以上います。

こちらはテキストボックスが良さそうですね…。
以前「あ」「か」「さ」「た」「な」…ボタンを配置して、コンボボックスの表示を
絞ったものを作った事があるのですが、ユーザから「直接入力の方が早い」と
ボツになった事もありました…。

>月度は1年に12個ずつ増えて

このへんは運用面の問題だと思います。
例えば去年のタイムカードを今年になってから見る事があるのでしょうか?

あるのでしたら「年」「月」の2つのコンボボックスで、
ないのでしたら「2005年度給与.mdb」「2006年度給与.mdb」のように
別mdb での運用もありだと思います。

【5873】Re:時間の計算について
発言  わん  - 05/8/17(水) 14:16 -

引用なし
パスワード
   小僧さん:
早速ありがとうございます。

「月度」をコンボボックスにするのは最もだと思います。

ただ、今回は前回の打刻日付をもとに1つのクエリで集計しており、
年度別にわけることなく、そのまま利用できないかと考えました。

あるのでしたら「年」「月」の2つのコンボボックスで、
↑おっしゃる通りこれができれば一番良いと思います。
****年**月と1つになっているものを「年」「月」とわけて
コンボ検索することは可能なのでしょうか?

また、コンボ検索とテキストボックスでの「名前」検索の組合せは、
どのようにコードを書けば良いのでしょうか?

先程の【#5863】を例にして、
仮に、ポジションをテキストボックスに変更すると、
何を変更するのかを教えて頂けると助かります。

Private Sub 検索ボタン_Click()
  Me.Filter = "ポジション = '" & Me.cmbポジション & "' AND 年齢 = " & Me.cmb年齢
  Me.FilterOn = True
  Me.txt人数 = Me.Recordset.RecordCount
End Sub

宜しくお願いします。

【5879】Re:時間の計算について
発言  小僧  - 05/8/17(水) 15:39 -

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


>****年**月と1つになっているものを「年」「月」とわけて
>コンボ検索することは可能なのでしょうか?

[#5863]の例ですと、「ポジション」と「年齢」で抽出していましたが、このへんを
「打刻日付の左4文字」  と 「年コンボ」
「打刻日付の6、7文字目」 と 「月コンボ」

を比較すれば可能ですね。この場合は文字列での比較になります。


>また、コンボ検索とテキストボックスでの「名前」検索の組合せは、
>どのようにコードを書けば良いのでしょうか?
>先程の【#5863】を例にして、
>仮に、ポジションをテキストボックスに変更すると、
>何を変更するのかを教えて頂けると助かります。

実は…何も変更無しです(笑)
テキストボックスでもリストボックスでもコンボボックスでも記述は同じだったりします。

>そのまま利用できないかと考えました。
100人の社員が月22日出勤で12ヶ月 → 26400レコード

レコード数が増えると、使用されている環境によりますがAccessの動作が遅くなります。
当方の環境で12万件のレコードから Dcount関数を使って抽出するテストを
行ってみたのですが、体感で1.5秒位です。(遅いのか早いのか微妙ですね^^;)

わん さんの環境でも、同じレコードを コピー&ペースト でがんがん増やして
5万件位のレコードで速度に問題があるようでしたら(クエリの表示、抽出など)
テーブルの設計等を少し考え直す必要があるかもしれません。

【5886】Re:時間の計算について
お礼  わん  - 05/8/17(水) 17:16 -

引用なし
パスワード
   小僧さん:
いつもありがとうございます。

なるほど、ここでLeft関数、Right関数を利用するのですね。

>[#5863]の例ですと、「ポジション」と「年齢」で抽出していましたが、このへんを
>「打刻日付の左4文字」  と 「年コンボ」
>「打刻日付の6、7文字目」 と 「月コンボ」
>を比較すれば可能ですね。この場合は文字列での比較になります。
↑は何とかできそうです。

>テキストボックスでもリストボックスでもコンボボックスでも記述は同じだったりします。
若干、xls.VBAとは異なるのですね。

>レコード数が増えると、使用されている環境によりますがAccessの動作が遅くなります。
>5万件位のレコードで速度に問題があるようでしたら(クエリの表示、抽出など)
>テーブルの設計等を少し考え直す必要があるかもしれません。

過去ログを読むとかなりのデータ量でも耐えられるような気がしますが。
私としては、データを年度末若しくは月末に清算できるような
マクロ記述により別テーブルを作成するようなことができればいいと
考えているのですが難しいのでしょうか?
それとも、基本のテーブル設計をより良いものに考え直す方がいいのでしょうか?

今回の場合は、仮にテーブル設計を考え直すとするとどうすればいいのでしょうか?
抽象的な質問になってしまい申し訳ありません。

【5891】Re:時間の計算について
発言  小僧  - 05/8/17(水) 18:19 -

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

>>レコード数が増えると、使用されている環境によりますがAccessの動作が遅くなります。
>>5万件位のレコードで速度に問題があるようでしたら(クエリの表示、抽出など)
>>テーブルの設計等を少し考え直す必要があるかもしれません。
>
>過去ログを読むとかなりのデータ量でも耐えられるような気がしますが。

一般的に言われていることですが、文字列操作(Left、Instrなど)を使ったり
クエリからクエリを呼び出したりすると動作が重くなるそうです。

また以前他の方の回答であったのですが
検索の際にレコードが多いと画面が固まってしまう事があったそうです。
(レコード件数はどれくらいか解りませんが)

何件を超えると…というデータがある訳ではないので、
現在のところ推定これだけは使いそうだ、×1.2くらいのレコード数で
一応実験しておいた方が無難かもしれません。

給与計算のところで Iif をクエリで使いましたが、
本当はあれもあまり良くないですね…。

>私としては、データを年度末若しくは月末に清算できるような
>マクロ記述により別テーブルを作成するようなことができればいいと
>考えているのですが難しいのでしょうか?
>それとも、基本のテーブル設計をより良いものに考え直す方がいいのでしょうか?

月ごとのテーブルを持たせるメリットとデメリットがはっきりしていれば
そう難しくない話だと思います。

メリット :扱うデータ量が少ないので処理が軽い!
デメリット:1) 月をまたぐ処理(15日から翌月15日までとか…)の処理に手間がかかる。
      2) テーブル数が多くなるので必然的にmdbの容量が増える。
      3) テーブル名を直接記述できない。

当方が使っているmdbですと、
・過去月のデータを見るのは1年に数回
・前年以前のデータはまず見ない

事から、

・mdbは年度単位
・テーブルは「今月テーブル」「先月以前テーブル」(もちろん名前は違いますが)

として、

・今月の処理(参照、更新)は速い
・先月以前の参照は呼び出すのに3秒くらい時間がかかる場合がある
・前年以前はその年のmdbを開き直せ

という感じですね。

【5894】Re:時間の計算について
質問  わん  - 05/8/18(木) 2:23 -

引用なし
パスワード
   小僧さん:
こんばんわ。
ずーっと、トライしましたが上手くいきません。
一体、どこが悪いのでしょうか?

[#5863]の例ですと、「ポジション」と「年齢」で抽出していましたが、このへんを
「打刻日付の左4文字」  と 「年コンボ」
「打刻日付の6、7文字目」 と 「月コンボ」
を比較すれば可能ですね。この場合は文字列での比較になります。

まずは、[#5863]からトライしたのですが上手くいきません。
T_選手
背番号  :数値型(主キー)
選手名  :テキスト型
ポジション:テキスト型
年齢   :数値型
年棒   :通貨型

背番号  選手名  ポジション  年齢  年棒
2      もとき  内野手   34  \12,000
5      きよはら 内野手   38  \45,000
6      こくぼ  内野手   34  \21,000
8       にし   内野手   34  \15,300
18      くわた  投手    37  \30,500
20      ろおず  外野手  37  \54,000
33      えとう  内野手   35  \21,500
47      くどう  投手    42  \28,000

これに、入団日を付け加えてトライしました。
入団日:日付型
フィールドには適当な年月日を入力

【コンボ年】:コンボボックス
   値集合ソース:SELECT Left(選手1.入団日,4) FROM 選手1 GROUP BY Left(選手1.入団日,4); 
【コンボ月】:コンボボックス
   値集合ソース:SELECT Mid(選手1.入団日,6,2) FROM 選手1 GROUP BY Mid(選手1.入団日,6,2);   
【テキストポジション】:テキストボックス
【テキスト人数】:テキストボックス
【検索ボタン】:コマンドボタン

Private Sub 検索ボタン_Click()
Me.Filter = "入団日 = '" & Me.コンボ年
  Me.FilterOn = True
  Me.テキスト人数 = Me.Recordset.RecordCount
End Sub

何度やっても上手く行かないので1つずつ確認しながら実行するために短くしました。

これで、実行すると
“このオブジェクトに値を代入することはできません。”となってしまいます。
Dim〜As Stringを使うのかとも考え、やってみたのですが結果は同じでした。
どこがいけないのでしょうか?
宜しくお願いします。


給与計算のところで Iif をクエリで使いましたが、
本当はあれもあまり良くないですね…。

他に方法を知らないのですが・・・。


・mdbは年度単位
・テーブルは「今月テーブル」「先月以前テーブル」(もちろん名前は違いますが)

できることならそうしたいですが、どの書籍も詳細から書き始めて
結果的にこうなるというような書き方をしているものが多く、
Access全体を把握しきれていない私には根本的にどう作り上げていくのか考えが及びません。
情けないですが・・・。

【5900】Re:時間の計算について
回答  小僧  - 05/8/18(木) 12:02 -

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

>どこがいけないのでしょうか?
>宜しくお願いします。

値集合ソースでやった事をフィルタにもやってあげましょう。

  Me.Filter = "Left(入団日,4) = '" & Me.コンボ年 & _
     "' AND MID(入団日,6,2) = '" & Me.コンボ月 & "'"

>>給与計算のところで Iif をクエリで使いましたが、
>>本当はあれもあまり良くないですね…。
>他に方法を知らないのですが・・・。

>>・mdbは年度単位
>>・テーブルは「今月テーブル」「先月以前テーブル」(もちろん名前は違いますが)
>できることならそうしたいですが、

まずは骨格を決める為に、処理速度を考えずに作られた方が良いかもですね。
処理速度を気にするようになる頃には わん さん の Access のスキルも
あがっていると思いますし、段々良いアイデアが出てくると思います。
「処理速度をあげるには」という感じで改めてご質問されても良いですしね。
(ExcelVBAの掲示板の方にたまにありますよね)

【5901】Re:時間の計算について
お礼  わん  - 05/8/18(木) 12:51 -

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

回答ありがとうございます。

色々試してやっとこさ自力でできたことをご報告しようと思ったところです。
どうやら、コード内の 「"」、「'」の付け方や半角空ける等の基本的なところが
適切でなかったために上手くいかなかったようです。
ご迷惑おかけしました。

今度は名前入力(ここではポジション入力)のためのテキストボックスについて
つまずいてます。
昨日、教えて頂いた内容ですとテキストボックスでも同様だということなので
また、書き方が間違っていないか検証中です。

1つ素朴な疑問なのですが、コンボ等に類似するものには、
集合値ソースが必要なのになぜテキストボックスには要らないのですかね??


>まずは骨格を決める為に、処理速度を考えずに作られた方が良いかもですね。
>処理速度を気にするようになる頃には わん さん の Access のスキルも
>あがっていると思いますし、段々良いアイデアが出てくると思います。
>「処理速度をあげるには」という感じで改めてご質問されても良いですしね。
>(ExcelVBAの掲示板の方にたまにありますよね)

はい、とりあえず今回作成中のものを最後まで作り上げるなかで
経験しながら、全体像を把握して処理速度のことも考えられるようになりたいと思います。
遠回りかもしれませんが、はじめは仕方ないと思って頑張るしかありません。

とりあえずは、抽出ができるようにし、
その後、○○件のレコードを入れて試験をして見たいと思います。

先は長そうです。ふぅ〜。

【5906】Re:時間の計算について
お礼  わん  - 05/8/18(木) 16:12 -

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

色々と初歩的なことに、お付き合いして頂きありがとうございました。
感謝の気持ちでいっぱいです。

何とかできました。
お忙しいとは思いますが、確認して頂けますでしょうか?

Private Sub 検索ボタン_Click()
 If IsNull(Me.コンボ年) Then
 MsgBox "入団年数を入力して下さい。"
  Me.コンボ年.SetFocus
  Exit Sub
 End If
 If IsNull(Me.コンボ月) Then
 MsgBox "入団月数を入力して下さい。"
  Me.コンボ月.SetFocus
  Exit Sub
 End If
 If IsNull(Me.テキストポジション) Then
 MsgBox "ポジションを入力して下さい。"
  Me.テキストポジション.SetFocus
  Exit Sub
 End If
Me.Filter = "Left(入団日, 4) = '" & Me.コンボ年 & "' AND mid(入団日,6,2) = " & Me.コンボ月 & "AND ポジション = '" & Me.テキストポジション & "' "
Me.FilterOn = True
  Me.テキスト人数 = Me.Recordset.RecordCount
End Sub

もし、何かおかしいところがあればご指摘していただきたいと思います。
宜しくお願い致します。

【5908】Re:時間の計算について
発言  小僧  - 05/8/18(木) 16:54 -

引用なし
パスワード
   ▼わん さん:
ご提示されたコード確認致しました。
こちらの環境でも問題なく動作しております。

ところで当方がコードを作成するとしたら…
根っからの横着モノなので

>If IsNull(Me.コンボ年) Then
>  MsgBox "入団年数を入力して下さい。"
>  Me.コンボ年.SetFocus
>  Exit Sub
>End If

と3回(くらいならいいかな…)も同じコードを書くのが面倒くさいので、

Dim strCtrl(1 To 3) As Variant
Dim I As Long
  strCtrl(1) = "コンボ年"
  strCtrl(2) = "コンボ月"
  strCtrl(3) = "テキストポジション"
  
  For I = 1 To 3
    If IsNull(Me.Controls(strCtrl(I))) Then
      MsgBox strCtrl(I) & "を入力してください。"
      Me.Controls(strCtrl(I)).SetFocus
      Exit Sub
    End If
  Next

とでもします(笑)。
このままですとメッセージボックスの表示が良くないので
コントロール名自体も変えちゃうと思います。

今回は「Null」チェックが3回でそのままでも良いのですが、
もっと多い場合には有効になると思います。

【5910】Re:時間の計算について
質問  わん  - 05/8/18(木) 17:20 -

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

有難うございます。
こういう時にこういう使い方ができるんですね。
直ぐに修正します。やっぱり、コードの長さも処理速度と関係しているんでしょうね。
これでまた少し、他の投稿等をみても理解ができるようになりました。
今更ながら奥が深いと思いました。

早速、本題の給与計算に応用したところ、
1つ問題が発見されました。
存在しない検索(主に名前になるのでしょうが)をすると、
全く何も表示されなくなってしまいます。

殆ど、こういうことをするヒトはいないと思いたいですが、
実際に使用するのは本当の素人なものですから何をするのか
検討がつかない為に処理を加えたいと思います。

例えば、

存在しない検索をしたらMsgBoxに存在しませんと表示。
OKボタンで最初の画面に戻る。

というようにしたいのですがどのようにしたら宜しいですか?

今回は全く想像ができず、何を調べたらいいのかもわかりません。
度々で申し訳ありませんが宜しくお願いします。

【5912】Re:時間の計算について
発言  小僧  - 05/8/18(木) 18:02 -

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

>在しない検索(主に名前になるのでしょうが)をすると、
>全く何も表示されなくなってしまいます。

以前ありましたが、コンボボックスだとこういった事がないんですよね。

テキストボックスの場合はそういったチェックも必要になってきます。
(コンボボックスもドロップダウンリストから選ばないで直接入力できるので必要ですが)

さきほどの選手1の使ってみますね。

Private Sub 検索ボタン_Click()
'※要参照設定 Microsoft DAO x.x Object Library

'----------------------------<<SQLを発行した結果が0件>>-------------------
Dim RS As DAO.Recordset
Dim SQLCode As String
  
  SQLCode = "SELECT * FROM 選手1 WHERE ポジション = '" & Me.テキストポジション & "'"
  Set RS = CurrentDb.OpenRecordset(SQLCode, dbOpenSnapshot)
    If RS.EOF Then
      MsgBox "そんなポジションないよ"
    End If
    RS.Close
  Set RS = Nothing
  
'----------------------------<<定義域集計関数を使用>>---------------------
  If DCount("*", "選手1", "ポジション ='" & Me.ポジション & "'") Then
    MsgBox "そんなポジションないってば"
    Exit Sub
  End If

End Sub

良く使われる例を2つあげてみました。
定義域集計関数はフォームやレポートを作る際に知っていると便利な関数ですので
この機会に使いこなせるようにされてみるのが良いと思います。

【5922】Re:時間の計算について
発言  わん  - 05/8/19(金) 2:51 -

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

昨日、教えて頂いたコードを試したところ上手く動作しなかったので、
(検索実行すると常に"そんなポジションないってば"が表示されてしまいます)

その後、色々調べてみました。(DAOについては、基本を理解してからと思い試していませんが)

'----------------------------<<定義域集計関数を使用>>---------------------
  If DCount("*", "選手1", "ポジション ='" & Me.ポジション & "'") Then
    MsgBox "そんなポジションないってば"
    Exit Sub
  End If
End Sub

自分なりに考えてみました。こんな感じで宜しいでしょうか?

If DCount("*", "選手1", "ポジション = '" & Me.テキストポジション & "'") = 0 Then
  MsgBox "そんなポジションないってば"
  Exit Sub
 End If

後、最終的に検索結果が0件の時、若しくは3つの条件が揃っていない時に
MsgBoxが表示されるようにはできないでしょうか?

Me.Filter = ・・・・・・
↑Me.FilterOn = True
↑  ↑
のところを修正するのでしょうか?

又は、↓のようなものも見つけましたがこれでもできるのでしょうか?
DoCmd.ApplyFilter ,

どちらにしても、IF 〜 Then 〜 Else では上手くできませんでした。
ご意見やお知恵をお貸し下さい。
ここまで、できれば後はレポート出力だけです。

まとめて質問することもできず、
後から何度何度も長々と申し訳ありません。
宜しくお願い致します。

追伸、
最終的な給与計算後の試験を行ったところ(1万件強)
抽出に時間がかかるのではなく、
フォームが立ち上がるまでの時間がかかりました。
約2秒程です。(これが長いのか短いのかは私には判断できませんが)

この件は、完成後考えていきたいと思います。

【5939】Re:時間の計算について
発言  小僧  - 05/8/21(日) 8:05 -

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

業務が忙しくなってしまい返信が遅くなってしまいました。
すみません。

>If DCount("*", "選手1", "ポジション = '" & Me.テキストポジション & "'") = 0 Then

その通りです。0と比較しなきゃいけなかったですね。

>後、最終的に検索結果が0件の時、若しくは3つの条件が揃っていない時に
>MsgBoxが表示されるようにはできないでしょうか?

これは順々で良いのではないでしょうか。

検索ボタンクリック

NULLチェック

結果0件チェック

フィルタ処理


>約2秒程です。(これが長いのか短いのかは私には判断できませんが)

当方でしたら…一度フォームが立ち上がれば後は軽ければ気になりませんし、
何を操作するにも2秒ずつ時間がかかるのでしたら改善しようと考えますね。
(ちょっと気が短いですかね…)

【5942】Re:時間の計算について
質問  わん  - 05/8/21(日) 22:00 -

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

自分なりに考えてみました。

>検索ボタンクリック
>↓
>NULLチェック

ここまでは、今まで教えて頂いたやり方でOKですね。
問題は次ですね。↓のようにしてみました。

If DCount("*", "選手1", "Left(入団日, 4) = '" & Me.コンボ年 & "'") = 0 Then
   MsgBox "そんな入団年ないよ"
  ElseIf DCount("*", "選手1", "mid(入団日,6,2) = '" & Me.コンボ月 & "'") = 0 Then
   MsgBox "そんな入団月ないですよ〜"
  ElseIf DCount("*", "選手1", "ポジション = '" & Me.テキストポジション & "'") = 0 Then
   MsgBox "そんなポジションないってば"
  Else
   Me.Filter = "Left(入団日, 4) = '" & Me.コンボ年 & "' AND mid(入団日,6,2) = " & Me.コンボ月 & "AND ポジション = '" & Me.テキストポジション & "'"
   Me.FilterOn = True
   Me.テキスト人数 = Me.Recordset.RecordCount

これで上手くいくのですが、検索結果が“0”のときにMsgBoxが表示されません。
表示させたいのですがどのようにすれば良いのでしょうか?

あと、違った質問になってしまうのですが、
仮に全く同じ条件の人が2人いたとしたら当然検索結果は2となります。
その時に、最下部のレコードの操作ではなく、フォーム上にコマンドボタンか何かのコントロールで
検索できるようにすることは可能なのでしょうか?
もし、できるならどのようにすれば良いのでしょうか?

極力、使用する側がAccessについて知らなくても使用できるように
完成させたいと思っています。

何卒、どうかどうか宜しくお願い致します。

追伸、
前回の処理速度は、コピー&ペーストを実施後、直ぐのために時間がかかったようですが、
その後は立ち上がりも処理も問題なく瞬時に行われていました。

【5946】Re:時間の計算について
回答  小僧  - 05/8/22(月) 9:51 -

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

>If DCount("*", "選手1", "Left(入団日, 4) = '" & Me.コンボ年 & "'") = 0 Then
>   MsgBox "そんな入団年ないよ"
>  ElseIf DCount("*", "選手1", "mid(入団日,6,2) = '" & Me.コンボ月 & "'") = 0 Then
>   MsgBox "そんな入団月ないですよ〜"
>  ElseIf DCount("*", "選手1", "ポジション = '" & Me.テキストポジション & "'") = 0 Then
>   MsgBox "そんなポジションないってば"
>  Else

DCount関数の第3引数の条件式は「AND」条件でつなげる事ができるので、

DCount("*", "選手1", "ポジション = '" & Me.テキストポジション & "' AND " _
         & "Left(入団日,7) = '" & Me.コンボ年 & "/" & Me.コンボ月 & "'")

でフィルタを掛ける前に件数を求めることができます。

また、Filterの後に「Me.Recordset.RecordCount」で結果が何件かを調べる事ができるので、

If Me.Recordset.RecordCount = 0 Then
    Msgbox "結果0件ですね"
    Me.FilterOn = False
End If

なんていうのもありかと思います。

>最下部のレコードの操作ではなく、フォーム上にコマンドボタンか何かのコントロールで
>検索できるようにすることは可能なのでしょうか?

[表示] → [ツールバー] → [ツールボックス] でツールボックスを表示させると、
テキストボックスやコンボボックスなどと共に
「コントロールウィザード」というアイコンが出現します。

これを押した状態でコマンドボタンを配置すると、
Accessのウィザードでレコードの移動ボタンが作れます。

クリック時のイベントを見ると変なエラー処理がついていますが、

DoCmd.GoToRecord , , acNext
DoCmd.GoToRecord , , acPrevious

こんな記述ができていると思います。

【5965】Re:時間の計算について
お礼  わん  - 05/8/22(月) 20:42 -

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

長い間、右も左もわからない私にお付き合い頂き、
ありがとうございました。
今回の回答を通じて、基本的なことを理解することができました。

なんとか、考えていたものに完成させることができました。
↓のようにしてみました。

Private Sub 検索ボタン_Click()
Dim strCtrl(1 To 3) As Variant
Dim I As Long
  strCtrl(1) = "入団年"
  strCtrl(2) = "入団月"
  strCtrl(3) = "ポジション"
 
  For I = 1 To 3
    If IsNull(Me.Controls(strCtrl(I))) Then
      MsgBox strCtrl(I) & "を入力してください。"
      Me.Controls(strCtrl(I)).SetFocus
      Exit Sub
    End If
  Next
  If DCount("*", "選手1", "Left(入団日, 4) = '" & Me.入団年 & "'") = 0 Then
  MsgBox "選択された入団年は存在しません。"
  ElseIf DCount("*", "選手1", "mid(入団日,6,2) = '" & Me.入団月 & "'") = 0 Then
  MsgBox "選択された入団月は存在しません。"
  ElseIf DCount("*", "選手1", "ポジション = '" & Me.ポジション & "'") = 0 Then
  MsgBox "記入されたポジションは登録されておりません。"
  ElseIf DCount("*", "選手1", "ポジション = '" & Me.ポジション & "' AND " & "Left(入団日,7) = '" & Me.入団年 & "/" & Me.入団月 & "'") = 0 Then
  MsgBox "結果は0件です。"
  Else
  Me.Filter = "Left(入団日, 4) = '" & Me.入団年 & "' AND mid(入団日,6,2) = " & Me.入団月 & "AND ポジション = '" & Me.ポジション & "'"
  Me.FilterOn = True
  End If
End Sub
Private Sub レコード移動_Click()
On Error GoTo Err_レコード移動_Click
  DoCmd.GoToRecord , , acNext
Exit_レコード移動_Click:
  Exit Sub
Err_レコード移動_Click:
  MsgBox Err.Description
  Resume Exit_レコード移動_Click
End Sub


お時間のあるときにでもみて頂けると有り難いと思います。

どうやら、ANDの時にカッコの使い方が不十分なためできていなかったようです。

実は、今回Recordset.RecordCount についての理解がよくできませんでしたが、
じっくり時間をかけてトライして生きたいと思います。

実は、[#5863]検索用フォームの作成の
【txt人数】:テキストボックスに件数が表示されなかったのです。

私の手違いかと思いますので、
まず、ここに表示させることができるようになったら、

If Me.Recordset.RecordCount = 0 Then
      Msgbox "結果0件ですね"
      Me.FilterOn = False
  End If
を取り入れたやり方を試してみたいと思います。

本当に長い間、お忙しいところ、
的確なご意見とご教授有難うございました。
いつか、自分の力だけでできるように精進して参ります。

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