Private Sub 検索実行_Click()
DoSearch acFirst
End Sub
Private Sub 次へ_Click()
DoSearch acNext
End Sub
Private Sub 前へ_Click()
DoSearch acPrevious
End Sub
Private Sub DoSearch(Rec As AcRecord)
If Nz(Me.検索.Value) = "" Then
MsgBox "検索テキストボックスに入力してください。"
Exit Sub
End If
If Not Me.検索.Value Like "*[!0-9]*" Then
DoCmd.SearchForRecord , , Rec, "社員番号 = " & Me!検索
ElseIf Not Me.検索.Value Like "*[!あ-ん]*" Then
DoCmd.SearchForRecord , , Rec, "せい = '" & Me!検索 & "'"
Else
DoCmd.SearchForRecord , , Rec, "姓 = '" & Me!検索 & "'"
End If
End Sub
Public Function IncludWords(sText, Words) As Boolean
If Nz(sText, "") = "" Or Nz(Words, "") = "" Then Exit Function
Dim Word
For Each Word In Split(Words, " ")
If sText Like "*" & Word & "*" Then
IncludWords = True
Exit For
End If
Next
End Function
ありがとうございます。社員番号はテキスト型でした。
ご回答いただいたコードで、社員番号検索が不可能なことを承知の上で試したところ、
せいでは、検索できる人とできない人がいます。条件は不明です。
姓では全て検索できました。また、前へ、次へのボタンも問題なく動作しました。
社員番号フィールドのデータ型はなんでしょうか。テキスト型または数値型どちらですか。
私の回答したコードも試してもらえますか。
いつもありがとうございます。
現在、クエリで社員番号昇順で表示されます。
質問に記載した条件ですと、
検索ボックスが空白だった場合ですが、
次へを押すことで、社員番号を1つ飛ばしで表示されることがわかりました。
原因はわからないのですが、コードの訂正を試みています。
鈴木の姓が3人いると仮定して、
検索ボックス内が、
すずき でも 鈴木 でも、
前後できるようにしたいのですが、
すずきだとレコードの移動ができるのに、
鈴木だとできない、といった具合です。
自分が書くなら下記のようなコードになります。
社員番号フィールドのデータ型は数値型の前提です。
完全一致の場合は、Like ではなく = の方がいいでしょう。
検索ボックスのテキストが数字だけなら
社員番号
、ひらがなだけならせい
、それ以外なら姓
を対象に検索するようにしてます。お返事遅くなりまして、申し訳ございません。
Set rs = Me.subForm.Form.Recordset.Clone
にしたらうまく動作しました。
ご指摘の点も注意きたします。
サンプルを作成して提示のコードで試してみましたが、前へボタンで戻れないという症状は再現できませんでした。
そのレコードより前に該当レコードがあるのに移動しないのでしょうか。
その場合、検索ボックスにはどのようなデータが入力されてますか。
提示のコードですが、行儀のいいコードではないので、下記の手順で修正してください。
そうすることで、不具合の原因を追究しやすくバグの発生しにくいものになります。
まず、VBAウィンドウのメニューの[ツール]-[参照設定]をクリックして
Microsoft Excel 16.0 Object Library
(数字部分はバージョンによって異なる)にチェックを入れて[OK]をクリックしてください。[ツール]-[オプション]をクリックして開くダイアログで[編集]タブの[変数の宣言を強制する]にチェックを入れて[OK]をクリック。
提示のコードが記述してあるモジュールの先頭に下記の1行を挿入。(既にある場合はそのままで)
これの意味は変数を使う場合は必ず宣言することを強制します。
ここでメニューの[デバッグ]-[`*****`のコンパイル]をクリックします。(
*****
はプロジェクト名)もし、構文間違いや変数宣言がないとその部分を指摘してくれます。
提示のコードには、xlApp、xlBook の変数宣言がないので、ここでエラーが出るはずです。
でないなら、モジュールの先頭か、標準モジュールの先頭で宣言しているはずです。
その変数宣言を削除してください。(そのような場所で宣言する変数をグローバル変数といいますがこれはバグの元ですのでなるべく使用しないようにします。)
クリック時のイベントプロシージャの先頭で、この変数の宣言をします。
Dim xlApp As Object
というように宣言することもできますが、上記のように宣言するのを推奨します。そうすると
xlApp.
まで入力するとプロパティやメソッドがリスト表示されますので入力が楽になるしタイプミスが減らせます。以上、を試してみてください。
簡単なサンプルを作成して、実験してみました。
でも、問題なく動作しました。
うまくいかない原因は他にあると思われます。
アドバイスありがとうございます。
月曜日に試してみます。
すみません、もう1点教えてください。
MyFocusという関数で、ScreenUpdating 、Calculation等のプロパティを設定していますが、
タイミングの違いで、DisplayAlertだけこのMyFocusという関数で定義できず、スマートな
コーディングができません。
確か、CalculationプロパティはBookを開いてから閉じる間に書かなければならないが、
DisplayAlertはBookを保存する前後に入れなければならなかったと思います。
この点アドナイスいただけますと幸いです。
よろしくお願いいたします。
お返事書かせてしまってすみません。
書いて下さった情報は貴重なので覚えておきます。
たびたびのご助言、本当にありがとうござました。
2Bの方法は件数か多いと重いかもしれません。選択リストをテキストで保存してますので、検索や削除処理が重くなりそうです。リストをDictionaryオブジェクトに格納すると、検索/削除は高速になるので8000件ぐらいならいいかも知れません。
テーブルに格納するなら、フロントエンド側のワークテーブルにする設計にするのが楽だし、速度的にも有利かと。
バックエンドに格納してしまうと複数ユーザーの更新の衝突の危険性が増してしまいます。
※投稿してから、上の投稿に気が付きました。
自己レスです。
「ベストが明らかだという感じがしない」と書きましたが、
考えてみれば特別な業務以外で True の数が大きくなることはないので、
やはり hatena さんの方法で行けそうな気がします。
そちらで納得したいと思います。
ありがとうございました。
ご回答ありがとうございます。
いわゆるひとり情シスなもので、助言があるだけでありがたいのですが、
hatena さんのような Access 界の有名人からは特別な感じがします。
書き損なってすみませんでしたが、
有線 LAN・共有人数一桁でした。
バックエンド非連結くずしは、
正規化に対する正規化くずしのように加減が分かりにくい世界だと
認識しておりまして、
TOP 句と外部結合を使った SQL から
2, 30 レコードぐらいのワークテーブルを作って、
帳票フォームでページを切り替えていかないといけないのかどうか、
ずっと悩んでおりました。
がしかしそこは、おかげさまで解決です。
ところで、上記 "2b" につき、リンク先拝読しました。
ただ、テーブルに 8,000 件ぐらいはあって今後も増え続けるので、
十分な速度が出(続け)るか分からないところはあります。
「テーブルに Yea/No型のフィールドを追加して、チェックボックスをそれと連結させましょう」の場合、
ユーザ人数分のフィールドをバックエンドに持つか、
ローカルで生成してリンクテーブルと結合になりそうですが、
個人的にはベストが明らかだという感じがしません。
ご意見を伺えれば幸いです。
なんとなくその辺があやしそうそうな気がしたのですか、当たったようですね。
というようにしてみたらどうだろう。
RecordsetClone
とRecordset.Clone
の違いは下記を参照してください。フォームの Recordset, RecorsetClone, RecordSet.Clone の違いとは? - hatena chips
普通に定義済みクエリを指定してレコードセットを開くと問題ないです。
一方、サブフォームのRecordsetConeプロパティを元にレコードセットを開くと動かなくなりますね。
の部分のコメント行を下記のように入れ替えたらどうなりますか。
共有する人数、更新の頻度、ネットワーク環境(有線/無線など)によって異なるので、一概には言えません。
共有人数が一桁で閲覧のみなら、データベース分割、連結フォームでたいていは問題なく運用できると思います。
b に関しては下記で紹介している方法が使えます。
a に関しては、1で示した条件内なら普通に連結で問題ないと思います。
実際運用してみて、頻繁に破損したり不具合が出るなら、上の非連結チェックボックスでチェックして、更新クエリでまとめて更新するという運用にするといいでしょう。その場合は、トランザクションをかけておくとより安全です。
共有人数か何十人もいるなら、そもそもAccdbでは無理なので、SQL Server等の本格的なRDBMSへの移行を検討すべきでしょう。
問題のコードを提示してもらえますか。
質問は編集できますので、質問の方に追記してもらうと後々見やすいです。
あと、「切替のダイアログ」とは具体的にどのようなダイアログでしょうか。
どうもありがとうございます。
キーブレイク処理ですか。
一瞬で採番できてしまったのでビックリしました。
縦を横展開もクロス集計で解決しました。
どうもありがとうございます。、
DCountでの連番演算は重い処理になります。
テーブルに、Gid フィールドを追加して、VBAで連番を入力するようにすると高速になります。
下記で、自動で連番を入力する関数を紹介していますので、それを使うといいでしょう。
それができたら、関係者社員番号の横展開は、クロス集計クエリで可能です。
ありがとうございました。
すみません、勘違いをしておりました。
レポートヘッダーとページヘッダーを勘違いをしていました。(テストレポートにレポートヘッダーを作ったつもりだったのがページヘッダーしか作ってありませんでした。)申し訳ありません。うまくできました。
ありがとうございます。
AccessはOffice365の32bit版です。
ご提示していただいている確認用コードを、コピペしただけのテスト用レポートを作って、プレビュー、印刷実行を行いましたが、すべて、「プレビューのみです」が返ってきてしまいます。
ありがとうございます。できました!!
うまくいきませんとは、具体的にどのようにうまくいかないのですか。
Officeは、32bit版ですか、64bit版ですか。
32bit版なら、2013でも問題なくいけるはずです。
64bit版の場合は、標準モジュールの宣言部のAPIの参照のコードを下記のように書き換えてください。
ありがとうございます!できました!
理解力が低い私のために、懇切丁寧に教えて下さり、本当にありがとうございました!
これで、カウントミスや間違った入力を見つけることができそうです。
誠にありがとうございました!
基本的な考え方は「7日間だけ抽出する」「連続して7日出勤しているなら7レコードあるはずだ」です。
連続3日ということは「4日前は休み=レコードがない」なのでその日までの7日分だけ抽出したら最大でも6レコードしかないはずで「抽出条件:7」で表示されるのはおかしいとなります。
Dcount関数の条件指定を正せばいいのですが、おかしい原因は
のどれかです。
そこで、おかしいレコードで「7日間だけ抽出する」して、抽出されたレコードを直接見て原因をつかもうというのが>> 3です。
社員CD7 4月2週目 1、連続3日目
なら(月曜から出勤として対象日は4/10日)社員CDの抽出条件に「7」
日付の抽出条件に「>#2019/04/10#-7 And <=#2019/04/10#」
でクエリを表示すると7レコード以上表示されるはずです。
この場合のSQLを記載しますので、新規にクエリを作成し、SQLビューで以下を張り付けてデータシートビューで確認してみてください。
表示されたレコードに「おかしい結果」に該当するものがあった場合はそれを弾く条件の追加が必要です。
「おかしい結果」が無い場合はDcount関数の条件が間違っています。最初の式と同じものを記載しますのでコピーしてみてください。
DateAdd("m",1,[日付]) では?
勘ですが(汗)
ありがとうございます。
DateAdd("m",1,"日付")
と入力しましたが、データ型が一致しませんというエラーになります。
DateAdd("m",1,#日付#)
としてみましたが、こちらもエラーになってしまいます。
何かほかに必要でしょうか?よろしくお願い致します。
ご回答ありがとうございます。
間違って表示されているパターンは下記の通りでした。
社員CD7 4月2週目 1、連続3日目
2、連続4日目
※連続5日目は表示されていませんでした。
社員CD9 4月の最終週 1、連続3日目
2、連続4日目
3、連続5日目
※連続6日目は出勤自体がないため表示されていませんでした。
社員CD19 5月最終週 1、連続2日目
2、連続1日目(1日休んだ後に出勤)
3、連続2日目
その他にもパターンが全く違う社員が出ている状況です。
もちろん日付が重複しているレコードはない状態です。
賢くない私には、パターン化が見えない状況です。
非常にお手数を取らせてしまい申し訳ありませんが、
よろしくお願いいたします。
DateAdd関数を使うと簡単ですよ。
DateAdd関数 …日時に時間を加算する - Officeのチカラ
直接「T_出退勤」テーブルを見ているわけではないので何ともですが、間違って表示されてしまう人の条件でクエリを表示すると何かわかるかもしれません。
たとえば
間違って表示されてしまう人の社員CDが「3」
表示されてしまう4日目が「2019/5/16」
なら
新しく作ったフィールド(今日まで7日間の出勤数)の抽出条件を削除
社員CDの抽出条件に「3」
日付の抽出条件に「>#2019/05/16#-7 And <=#2019/05/16#」
として表示すると7件以上のレコードが表示されるはずです。
日付が重複しているレコードがあったり、7日間に含まれない日付があったりしませんか?
早速お答えくださり、ありがとうございます。
新しいフィールドに、教えていただいた式を入力させていただいたのですが、
7日連続勤務ではない数字が出てきてしまう状況です。
危惧されている、一日2回入力することはない状況なのですが、
4日目で表示されてしまう人がいる状況です。
引き続き教えていただければ幸いに存じます。
どうぞ、よろしくお願いいたします。
条件を指定してレコードを数える方法としてDCount関数が使えます。
「今日」を基準として7日間の出勤記録が7個あればいいので、新しく作るクエリにフィールドを追加して
今日まで7日間の出勤数: DCount("社員CD","T_出退勤","社員CD=" & [社員CD] & " and 日付>#" & [日付]-7 & "# and 日付<=#" & [日付] & "#")
抽出条件:7
とすれば抽出できます。
※出退勤の記録は1日1回までを前提としています。中休みを入れて午前午後で2回記録がついたりするなんてことがある場合は日付をグループ化したりする必要が出ると思います。
別案
クエリで定義域集計関数を使うと重くなるので「T_出退勤」に連続出勤日数フィールドを用意して出退勤を記録するフォームで入力時に連続出勤日数を記録するといいと思います。
自作関数勉強になります。仕事で使っているmdbは、ORACLEとのリンクテーブルでしてフィールドのを追加する事が出来ませんがこの知識は今後役に立ちそうです。有難う御座いました。
VBAで自作関数を作成する場合の方法です。
標準モジュールに下記の関数を作成してください。
クエリで下記のように設定してください。
フィールド 式1: IncludWords([対象フィード], "○○ □□ △△")
抽出条件 False
上記のように禁止ワードを空白区切りで入力します。
これで、○○、□□、 △△ のどれかを含むものは除外されます。
抽出条件を True にすればどれかを含むものが抽出されます。
やっぱりクエリでやろうとすることがスマートじゃないんじゃないかなぁと思いつつ
クエリにフィールドを一つ増やして
Eval(BuildCriteria("'" & [対象フィールド] & "'",10,"*" & Replace([検索文字列],",","* or *") & "*"))
抽出条件:false
目的も状況もわからずスマートではないと思っているのでとりあえず解説はありません
色々ご教示頂き有難う御座いました。テーブル試しに作ってやってみます。有難う御座いました。
Like "*[!ABC]*"
ではだめなら、Like演算子のみでは無理です。上の回答の方法か、VBAで自作関数を作成することになります。
禁止ワードテーブルを作成したほうが、ワードの編集、追加は楽だと思います。
複数のクエリで使用する場合も一か所の編集で済みます。
*
で囲まれた範囲は、フォントを斜体にするいう意味になりますので、そのようなコードや式を記述する場合は、バッククォート
`
で囲んでください。バッククォートは、Shift+@ で入力できます。
`Like "[○,○,・・・]"
`