Microsoft Access 掲示板

views
4 フォロー
6,283 件中 5,921 から 5,960 までを表示しています。
5

ありがとうございます。社員番号はテキスト型でした。
ご回答いただいたコードで、社員番号検索が不可能なことを承知の上で試したところ、
せいでは、検索できる人とできない人がいます。条件は不明です。
姓では全て検索できました。また、前へ、次へのボタンも問題なく動作しました。

4

社員番号フィールドのデータ型はなんでしょうか。テキスト型または数値型どちらですか。

私の回答したコードも試してもらえますか。

3

いつもありがとうございます。

現在、クエリで社員番号昇順で表示されます。
質問に記載した条件ですと、
検索ボックスが空白だった場合ですが、
次へを押すことで、社員番号を1つ飛ばしで表示されることがわかりました。
原因はわからないのですが、コードの訂正を試みています。

鈴木の姓が3人いると仮定して、
検索ボックス内が、
すずき でも 鈴木 でも、
前後できるようにしたいのですが、
すずきだとレコードの移動ができるのに、
鈴木だとできない、といった具合です。

2

自分が書くなら下記のようなコードになります。
社員番号フィールドのデータ型は数値型の前提です。
完全一致の場合は、Like ではなく = の方がいいでしょう。
検索ボックスのテキストが数字だけなら 社員番号、ひらがなだけなら せい、それ以外なら を対象に検索するようにしてます。

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
8
みずき 2019/06/20 (木) 13:57:59 a63a9@dbd20

お返事遅くなりまして、申し訳ございません。

Set rs = Me.subForm.Form.Recordset.Clone

にしたらうまく動作しました。

ご指摘の点も注意きたします。

1

サンプルを作成して提示のコードで試してみましたが、前へボタンで戻れないという症状は再現できませんでした。
そのレコードより前に該当レコードがあるのに移動しないのでしょうか。
その場合、検索ボックスにはどのようなデータが入力されてますか。

7

提示のコードですが、行儀のいいコードではないので、下記の手順で修正してください。
そうすることで、不具合の原因を追究しやすくバグの発生しにくいものになります。

  • まず、VBAウィンドウのメニューの[ツール]-[参照設定]をクリックしてMicrosoft Excel 16.0 Object Library(数字部分はバージョンによって異なる)にチェックを入れて[OK]をクリックしてください。

  • [ツール]-[オプション]をクリックして開くダイアログで[編集]タブの[変数の宣言を強制する]にチェックを入れて[OK]をクリック。

  • 提示のコードが記述してあるモジュールの先頭に下記の1行を挿入。(既にある場合はそのままで)

    Option Compare Database
    Option Explicit    'この行の挿入
    

    これの意味は変数を使う場合は必ず宣言することを強制します。

  • ここでメニューの[デバッグ]-[`*****`のコンパイル]をクリックします。(*****はプロジェクト名)
    もし、構文間違いや変数宣言がないとその部分を指摘してくれます。

  • 提示のコードには、xlApp、xlBook の変数宣言がないので、ここでエラーが出るはずです。
    でないなら、モジュールの先頭か、標準モジュールの先頭で宣言しているはずです。
    その変数宣言を削除してください。(そのような場所で宣言する変数をグローバル変数といいますがこれはバグの元ですのでなるべく使用しないようにします。)

  • クリック時のイベントプロシージャの先頭で、この変数の宣言をします。

Private Sub Excel出力_Click()
    Dim xlApp As Excel.Application
    Dim xlBook As Excel.Workbook 

    '以下略

Dim xlApp As Object というように宣言することもできますが、上記のように宣言するのを推奨します。
そうすると xlApp.まで入力するとプロパティやメソッドがリスト表示されますので入力が楽になるしタイプミスが減らせます。

  • MyFocus関数はとりあえず削除してください。高速化のためのものですが、今回の処理にはなくても影響は少ないと思います。うまく動作しない場合は、なるべく余計なことはしないようにした方が原因を特定しやすいです。安定して動作するようになってから、処理が重たいと感じたなら、その時に導入すればいいでしょう。

以上、を試してみてください。

6
hatena 2019/06/15 (土) 06:45:15 修正

簡単なサンプルを作成して、実験してみました。

Set rs = Me.subForm.Form.RecordsetClone

でも、問題なく動作しました。
うまくいかない原因は他にあると思われます。

5
みずき 2019/06/14 (金) 21:46:23 5ec36@d6973

アドバイスありがとうございます。
月曜日に試してみます。

すみません、もう1点教えてください。

MyFocusという関数で、ScreenUpdating 、Calculation等のプロパティを設定していますが、
タイミングの違いで、DisplayAlertだけこのMyFocusという関数で定義できず、スマートな
コーディングができません。
確か、CalculationプロパティはBookを開いてから閉じる間に書かなければならないが、
DisplayAlertはBookを保存する前後に入れなければならなかったと思います。

この点アドナイスいただけますと幸いです。

よろしくお願いいたします。

5

お返事書かせてしまってすみません。
書いて下さった情報は貴重なので覚えておきます。
たびたびのご助言、本当にありがとうござました。

4
hatena 2019/06/14 (金) 19:53:56 修正

2Bの方法は件数か多いと重いかもしれません。選択リストをテキストで保存してますので、検索や削除処理が重くなりそうです。リストをDictionaryオブジェクトに格納すると、検索/削除は高速になるので8000件ぐらいならいいかも知れません。
テーブルに格納するなら、フロントエンド側のワークテーブルにする設計にするのが楽だし、速度的にも有利かと。
バックエンドに格納してしまうと複数ユーザーの更新の衝突の危険性が増してしまいます。

※投稿してから、上の投稿に気が付きました。

3

自己レスです。

「ベストが明らかだという感じがしない」と書きましたが、
考えてみれば特別な業務以外で True の数が大きくなることはないので、
やはり hatena さんの方法で行けそうな気がします。

そちらで納得したいと思います。
ありがとうございました。

2

ご回答ありがとうございます。
いわゆるひとり情シスなもので、助言があるだけでありがたいのですが、
hatena さんのような Access 界の有名人からは特別な感じがします。

書き損なってすみませんでしたが、
有線 LAN・共有人数一桁でした。
バックエンド非連結くずしは、
正規化に対する正規化くずしのように加減が分かりにくい世界だと
認識しておりまして、
TOP 句と外部結合を使った SQL から
2, 30 レコードぐらいのワークテーブルを作って、
帳票フォームでページを切り替えていかないといけないのかどうか、
ずっと悩んでおりました。
がしかしそこは、おかげさまで解決です。

ところで、上記 "2b" につき、リンク先拝読しました。
ただ、テーブルに 8,000 件ぐらいはあって今後も増え続けるので、
十分な速度が出(続け)るか分からないところはあります。
「テーブルに Yea/No型のフィールドを追加して、チェックボックスをそれと連結させましょう」の場合、
ユーザ人数分のフィールドをバックエンドに持つか、
ローカルで生成してリンクテーブルと結合になりそうですが、
個人的にはベストが明らかだという感じがしません。
ご意見を伺えれば幸いです。

4

一方、サブフォームのRecordsetConeプロパティを元にレコードセットを開くと動かなくなりますね。

なんとなくその辺があやしそうそうな気がしたのですか、当たったようですね。

   Set rs = Me.subForm.Form.Recordset.Clone

というようにしてみたらどうだろう。

RecordsetCloneRecordset.Clone の違いは下記を参照してください。

フォームの Recordset, RecorsetClone, RecordSet.Clone の違いとは? - hatena chips

3
みずき 2019/06/14 (金) 16:46:28 a63a9@dbd20

普通に定義済みクエリを指定してレコードセットを開くと問題ないです。

一方、サブフォームのRecordsetConeプロパティを元にレコードセットを開くと動かなくなりますね。

2
    'レコードセットを開く
'    Set rs = db.OpenRecordset("サンプルクロス集計クエリ")

    Set rs = Me.subForm.Form.RecordsetClone

の部分のコメント行を下記のように入れ替えたらどうなりますか。

    'レコードセットを開く
    Set rs = db.OpenRecordset("サンプルクロス集計クエリ")

'    Set rs = Me.subForm.Form.RecordsetClone
1

1 データを一覧として閲覧(のみ。CRUD の R のみ)

共有する人数、更新の頻度、ネットワーク環境(有線/無線など)によって異なるので、一概には言えません。
共有人数が一桁で閲覧のみなら、データベース分割、連結フォームでたいていは問題なく運用できると思います。

2 例外的に、各行が持つチェックボックスのチェック。このチェックボックスには 2 タイプあって、
 a 論理削除のように、バックエンドにも要るもの。
 b 各ユーザが自分が印刷したいレコード(複数)を指定する時に使うフィールドのように、バックエンドには要らないもの。

b に関しては下記で紹介している方法が使えます。

非連結のチェックボックスでレコードを選択する
帳票フォームでチェックボックスを配置して、チェックしたレコードのみ選択して印刷したいのですが、一つのレコードをチェックするとすべてのレコードが選択されてしまいます。 掲示板でたまにみかける質問です。気持ちは分かりますが、非連結コントロールでの更新はすべてのレコードに反映されてしまいます。一つのコントロールにプロパティ値は一つしかもてませんので。各レコード毎にプロパティ値を持つような設計にしたら大量...
fc2

a に関しては、1で示した条件内なら普通に連結で問題ないと思います。
実際運用してみて、頻繁に破損したり不具合が出るなら、上の非連結チェックボックスでチェックして、更新クエリでまとめて更新するという運用にするといいでしょう。その場合は、トランザクションをかけておくとより安全です。

共有人数か何十人もいるなら、そもそもAccdbでは無理なので、SQL Server等の本格的なRDBMSへの移行を検討すべきでしょう。

1

問題のコードを提示してもらえますか。
質問は編集できますので、質問の方に追記してもらうと後々見やすいです。

あと、「切替のダイアログ」とは具体的にどのようなダイアログでしょうか。

2
みずき 2019/06/13 (木) 22:00:14 a63a9@dbd20

どうもありがとうございます。

キーブレイク処理ですか。
一瞬で採番できてしまったのでビックリしました。

縦を横展開もクロス集計で解決しました。

どうもありがとうございます。、

1
hatena 2019/06/13 (木) 12:32:51 修正

DCountでの連番演算は重い処理になります。
テーブルに、Gid フィールドを追加して、VBAで連番を入力するようにすると高速になります。

下記で、自動で連番を入力する関数を紹介していますので、それを使うといいでしょう。

グループ毎連番を自動入力する関数
クエリで連番を表示する場合、DCount関数やサブクエリを利用する方法はあちこちで紹介されています。 しかし、この方法は自分より前のレコード件数をカウントするというロジックなのでレコード件数が多くなると幾何級数的に重くなります。また、グループ毎に連番を振るという仕様になると、条件式も複雑になってきます。 クエリは使わずにテーブルに連番フィールドを持たせて、そこに VBA で連番を書きこむようにすると高速...
fc2

それができたら、関係者社員番号の横展開は、クロス集計クエリで可能です。

3

すみません、勘違いをしておりました。
レポートヘッダーとページヘッダーを勘違いをしていました。(テストレポートにレポートヘッダーを作ったつもりだったのがページヘッダーしか作ってありませんでした。)申し訳ありません。うまくできました。

2

ありがとうございます。

AccessはOffice365の32bit版です。
ご提示していただいている確認用コードを、コピペしただけのテスト用レポートを作って、プレビュー、印刷実行を行いましたが、すべて、「プレビューのみです」が返ってきてしまいます。

4
あや 2019/06/08 (土) 22:46:42 38bd8@d57aa

ありがとうございます。できました!!

1

うまくいきませんとは、具体的にどのようにうまくいかないのですか。

Officeは、32bit版ですか、64bit版ですか。
32bit版なら、2013でも問題なくいけるはずです。

64bit版の場合は、標準モジュールの宣言部のAPIの参照のコードを下記のように書き換えてください。

Declare PtrSafe Function apiIsWindowEnabled Lib "user32" _
    Alias "IsWindowEnabled" (ByVal hwnd As LongPtr) As Long
6
ゆか 2019/06/07 (金) 13:14:20 26d08@f2a60

ありがとうございます!できました!

理解力が低い私のために、懇切丁寧に教えて下さり、本当にありがとうございました!
これで、カウントミスや間違った入力を見つけることができそうです。

誠にありがとうございました!

5
名前なし 2019/06/07 (金) 12:01:33 7f2b8@f966d

基本的な考え方は「7日間だけ抽出する」「連続して7日出勤しているなら7レコードあるはずだ」です。
連続3日ということは「4日前は休み=レコードがない」なのでその日までの7日分だけ抽出したら最大でも6レコードしかないはずで「抽出条件:7」で表示されるのはおかしいとなります。

Dcount関数の条件指定を正せばいいのですが、おかしい原因は

  1. 同じ日付が複数ある
  2. 「出勤」以外の日付のレコードがある
  3. 8日以上離れた日付がある

のどれかです。
そこで、おかしいレコードで「7日間だけ抽出する」して、抽出されたレコードを直接見て原因をつかもうというのが>> 3です。

社員CD7  4月2週目  1、連続3日目なら(月曜から出勤として対象日は4/10日)
社員CDの抽出条件に「7」
日付の抽出条件に「>#2019/04/10#-7 And <=#2019/04/10#」
でクエリを表示すると7レコード以上表示されるはずです。
この場合のSQLを記載しますので、新規にクエリを作成し、SQLビューで以下を張り付けてデータシートビューで確認してみてください。

SELECT [T_出退勤].[社員CD], [T_出退勤].日付
FROM T_出退勤
WHERE ((([T_出退勤].[社員CD])=7) AND (([T_出退勤].日付)>#4/10/2019#-7 And ([T_出退勤].日付)<=#4/10/2019#));

表示されたレコードに「おかしい結果」に該当するものがあった場合はそれを弾く条件の追加が必要です。
「おかしい結果」が無い場合はDcount関数の条件が間違っています。最初の式と同じものを記載しますのでコピーしてみてください。

今日まで7日間の出勤数: DCount("社員CD","T_出退勤","社員CD=" & [社員CD] & " and 日付>#" & [日付]-7 & "# and 日付<=#" & [日付] & "#")
3
shige 2019/06/07 (金) 11:24:08 efb60@b63e8

DateAdd("m",1,[日付]) では?
勘ですが(汗)

2
あや 2019/06/07 (金) 10:41:56 38bd8@d57aa

ありがとうございます。

DateAdd("m",1,"日付")
と入力しましたが、データ型が一致しませんというエラーになります。
DateAdd("m",1,#日付#)
としてみましたが、こちらもエラーになってしまいます。
何かほかに必要でしょうか?よろしくお願い致します。

4
ゆか 2019/06/07 (金) 09:27:12 26d08@f2a60

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

間違って表示されているパターンは下記の通りでした。
社員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日目
その他にもパターンが全く違う社員が出ている状況です。
もちろん日付が重複しているレコードはない状態です。

賢くない私には、パターン化が見えない状況です。
非常にお手数を取らせてしまい申し訳ありませんが、
よろしくお願いいたします。

3
名前なし 2019/06/06 (木) 16:53:46 f52ac@f966d

直接「T_出退勤」テーブルを見ているわけではないので何ともですが、間違って表示されてしまう人の条件でクエリを表示すると何かわかるかもしれません。

たとえば
間違って表示されてしまう人の社員CDが「3」
表示されてしまう4日目が「2019/5/16」
なら
新しく作ったフィールド(今日まで7日間の出勤数)の抽出条件を削除
社員CDの抽出条件に「3」
日付の抽出条件に「>#2019/05/16#-7 And <=#2019/05/16#」

として表示すると7件以上のレコードが表示されるはずです。
日付が重複しているレコードがあったり、7日間に含まれない日付があったりしませんか?

2
ゆか 2019/06/06 (木) 13:42:59 26d08@f2a60

早速お答えくださり、ありがとうございます。

新しいフィールドに、教えていただいた式を入力させていただいたのですが、
7日連続勤務ではない数字が出てきてしまう状況です。
危惧されている、一日2回入力することはない状況なのですが、
4日目で表示されてしまう人がいる状況です。

引き続き教えていただければ幸いに存じます。
どうぞ、よろしくお願いいたします。

1
名前なし 2019/06/06 (木) 12:57:29 f52ac@f966d

条件を指定してレコードを数える方法としてDCount関数が使えます。

「今日」を基準として7日間の出勤記録が7個あればいいので、新しく作るクエリにフィールドを追加して

今日まで7日間の出勤数: DCount("社員CD","T_出退勤","社員CD=" & [社員CD] & " and 日付>#" & [日付]-7 & "# and 日付<=#" & [日付] & "#")
抽出条件:7

とすれば抽出できます。
※出退勤の記録は1日1回までを前提としています。中休みを入れて午前午後で2回記録がついたりするなんてことがある場合は日付をグループ化したりする必要が出ると思います。

別案
クエリで定義域集計関数を使うと重くなるので「T_出退勤」に連続出勤日数フィールドを用意して出退勤を記録するフォームで入力時に連続出勤日数を記録するといいと思います。

10

自作関数勉強になります。仕事で使っているmdbは、ORACLEとのリンクテーブルでしてフィールドのを追加する事が出来ませんがこの知識は今後役に立ちそうです。有難う御座いました。

9
hatena 2019/06/04 (火) 14:59:45 修正

VBAで自作関数を作成する場合の方法です。

標準モジュールに下記の関数を作成してください。

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: IncludWords([対象フィード], "○○ □□ △△")
抽出条件  False

上記のように禁止ワードを空白区切りで入力します。
これで、○○、□□、 △△ のどれかを含むものは除外されます。

抽出条件を True にすればどれかを含むものが抽出されます。

8
名前なし 2019/06/04 (火) 14:58:11 1a3c7@f966d

やっぱりクエリでやろうとすることがスマートじゃないんじゃないかなぁと思いつつ
クエリにフィールドを一つ増やして
Eval(BuildCriteria("'" & [対象フィールド] & "'",10,"*" & Replace([検索文字列],",","* or *") & "*"))
抽出条件:false
目的も状況もわからずスマートではないと思っているのでとりあえず解説はありません

7

色々ご教示頂き有難う御座いました。テーブル試しに作ってやってみます。有難う御座いました。

6

Like "*[!ABC]*" ではだめなら、Like演算子のみでは無理です。

上の回答の方法か、VBAで自作関数を作成することになります。

禁止ワードテーブルを作成したほうが、ワードの編集、追加は楽だと思います。
複数のクエリで使用する場合も一か所の編集で済みます。

5

*で囲まれた範囲は、フォントを斜体にするいう意味になりますので、
そのようなコードや式を記述する場合は、バッククォート ` で囲んでください。
バッククォートは、Shift+@ で入力できます。

`Like "[○,○,・・・]"`