Access (VBA) |
![]() ![]() |
(Windows 10全般 : Access 2016)
マルチユーザー使用に耐えうるフォームを作りたい
投稿日時: 22/12/27 19:19:29
投稿者: おーさん0729
|
---|---|
このために、
|
![]() |
投稿日時: 23/01/05 09:40:42
投稿者: Suzu
|
---|---|
引用: 引用: 1:編集前の表示の画面では、サーバーテーブルのレコードを表示 その中から編集するレコード指定 2:編集画面を開く際に、サーバーかローカルに 当該レコードをコピー 編集画面にはローカルのコピーしたレコードを表示 になります。 2: で表示するレコードが 1件のみであれば、単票フォームになるでしょうから 連結フォームにするメリットがありません。非連結フォームで十分です。 非連結フォームを処理する流れとしては 1:編集前の表示の画面では、サーバーテーブルのレコードを表示 その中から編集するレコード指定 ここは一緒。 2:非連結フォームの、各コントロールに 1で指定した レコードの値を代入。 (編集を行う 単票フォームのレコードソースやレコードセットには何も指定せず コントロールのコントロールソースにも何も指定しません) 保存ボタンを押した際に、画面上の値を サーバーの当該レコードの各フィールドの値として保存します。 ローカルテーブルは必要ありません。 これが、 https://www.moug.net/faq/viewtopic.php?t=81934 で 引用: の意図です。 |
![]() |
投稿日時: 23/01/05 22:12:16
投稿者: おーさん0729
|
---|---|
引用: 引用: Suzu様、いつもありがとうございます! このやり方だと帳票フォームと入力フォームを分ける必要がありませんか? 編集前の表示の画面(帳票フォーム)上で入力・更新といった編集をしたいです。 ※使用者が編集前の表示の画面(帳票フォーム)から変わらず使っているという認識ができていれば、大丈夫です。(なので、別の新たな編集画面等はダメになります。) 現状の使用方法は、レコードを選択したら、編集用フォームやサブフォーム等が出てくるといったことはなく、 帳票フォーム上に表示されているレコードをそのまま編集します。 |
![]() |
投稿日時: 23/01/06 08:59:23
投稿者: Suzu
|
---|---|
おーさん0729 さんの引用: 分ける事になります。 分ける事で、編集しようとするレコードをローカルにコピーする事をユーザーに気づかせない事も意図しています。 今回の質問は 前回のスレッド コントロールソースを別テーブルに動的設定したい https://www.moug.net/faq/viewtopic.php?t=81934 からの続きと認識しています。 そうであるなら 同一レコードに対し、同時に複数ユーザーが 別のフィールドのValue を更新する が前提条件と認識しています。 前回のスレッドでもご説明していますが 連結フォームで、レコードに対し編集状態に入ると当該レコードのレコードロック状態になります。 その編集状態に入ったユーザー以外の編集は制限される状態です つまり、複数人が同一レコード中の 別々のフィールドを編集する事はできません。 サーバーサイドテーブルをレコードソースとした 帳票フォーム においては 使用者に対し、質問者さんの 希望の動作(になっている様に見せかける)を実現させる方法を 当方は知り得ません。 |
![]() |
投稿日時: 23/01/06 17:20:18
投稿者: hatena
|
---|---|
引用: ローカルテーブルへのコピーはせずにということでしょうか。 だとすると、リンクテーブルになりますが、約13万件となると最新データの表示にはそれなりに時間がかかると思いますが、現状は問題ないですか。 コピーする場合とリンクテーブルでの表示の処理時間の比較をしたうえでの質問でしょうか。 リンクテーブルで処理時間に問題がないということなら、 引用: 帳票フォームのカレントレコードに非連結のポップアップフォームを重ねて表示させることで、ユーザーには帳票フォーム上で編集しているように見せることは可能です。 WinAPIを使って、フォーカスのあるテキストボックスの座標を取得することができますので、それからカレントレコードの位置を計算して非連結フォームを重ねて表示させればいいでしょう。 非連結フォームの使い方はSuzuさんの回答を参考にしてください。 WinAPIを使って入力テキストボックスの座標を取得する方法は下記で利用してますので参考にしてください。 カレンダーダイアログ日付入力関数の改良版 - hatena chips https://hatenachips.blog.fc2.com/blog-entry-116.html |
![]() |
投稿日時: 23/01/06 21:28:52
投稿者: おーさん0729
|
---|---|
いつも返信ありがとうございます。
|
![]() |
投稿日時: 23/01/10 09:48:41
投稿者: Suzu
|
---|---|
引用: 記述されている処理の内容が理解できかねます。 その処理の目的・意図は何でしょうか? 表示するレコードをローカルに依存できるという事は、 表示するレコードを決定する 表示フラグをローカルテーブルに持つ? そうなら、 引用:この言い回しにはならないでしょう。 と言う事は、表示フラグを持つのは サーバーテーブルの当該テーブル内のフィールド そのサーバーのフィールドを参照し、ローカルテーブルに追加クエリを使い追加 ※1 でも、直接サーバーテーブルを編集 と言っていますから、レコードソースは変わらずに サーバーテーブル であるなら、※1 の処理は何の為? 方法.A 帳票フォームのレコードソース を ※1 の処理にて得たローカルテーブルにするのであれば レコードソースは ローカルになりますから、「直接サーバーテーブルを編集」の表現にはなりません。 方法.B 引用: 引用: から ※1 の処理の意図を推測すると、 ローカルテーブルに、表示したい ID の値を保存。 その ID を、 SELECT * FROM サーバーテーブル INNER JOIN ローカルテーブル ON サーバーテーブル.ID = ローカルテーブル.ID の様な感じに使いたい。 とも読めるのですが、 そうであるなら、ローカルテーブルにフィルターを適用するだけで、※1 の必要性がありません。 また、方法A、方法B どちらにしろ、 フォームのレコードソースは サーバーテーブル です。 当方の前提条件は ・複数人ユーザーによる ・同一レコードにおいて、それぞれのフィールドの値を、それぞれ別のユーザーが同時に編集状態に入る (フィールドA は ユーザーA、フィールドB は ユーザーB、・・・)があり得る ・を 帳票フォーム(帳票フォームの様に見えるを含む)で処理する であり、 先のスレッド https://www.moug.net/faq/viewtopic.php?t=81934 引用: の実現を前提として検討しています。 23/01/06 08:59:23 引用: をお聞きしていますが、その回答を得られていません。 前提条件が違うのかどうなのか、説明をお願いします。 ---------------------------------------------------------------------------------------- その前提条件が同じで、 同一レコードに対し、別ユーザーが別フィールドに値を更新する為に 23/01/06 21:28:52 の仕組みをお考えなら、先に説明した様に、 レコードソースがサーバーテーブルである以上、実現できません。 前提条件が別で、 23/01/06 21:28:52 の仕組みをお考えなら、その意図をお聞かせください 他の方の質問の中でも、うまくいきません の様な 記載がある事が多いです。 でも うまくいかない だけでは、回答者には、何が希望と違うのかが判らず 原因も答えようがない事が多いです。 その様な事も考慮し、記載する事をお願いします。 |
![]() |
投稿日時: 23/01/10 18:58:35
投稿者: おーさん0729
|
---|---|
ありがとうございます。
引用: 表示されているレコードを直接編集できるようになるのではないかという意図です。 サーバーテーブルに表示フラグを持たせると、複数人使用時に検索結果の画面が同じになってしまう(レコードソースがサーバー手ブルのため、使用者Aの検索結果が使用者Bの画面に出てくる)ので、ローカルテーブルで表示フラグを持たせて、それを使ってフィルター設定すれば、検索結果w使用者Aと使用者Bで分けることができるかなと。 表示はサーバーテーブル、編集もサーバーテーブル、フィルター(検索結果)はローカルテーブルと同じ内容、としたいです。 引用: したいことはこの方法Bが近い(と思う)のですが、この設定の仕方がわかりませんでした。 引用: ・複数人ユーザーによる使用 は最低限必要です。 ・全ユーザーが全フィールドを編集する可能性がある こともあり、また、同時編集は実現できなさそうですので、 あとで編集したデータが優先される仕組み、もしくは、「編集できなかった」と表示される仕組みを作れれば、良さそうです。 ---------------------------------------------------------------------------------------- 引用: 一番上の回答で返事になっていますかね? 引用: すみません。自分でも、うまく表現できず、あまり分かっていないので、情報を小出しにしてしまっているなという思いはあります。 いつもいつもありがとうございます。お手数をおかけして、すみません。 |
![]() |
投稿日時: 23/01/11 02:58:17
投稿者: hatena
|
---|---|
1. 常に最新のサーバーテーブルを表示するようにしたい
|
![]() |
投稿日時: 23/01/11 14:42:58
投稿者: Suzu
|
---|---|
同一レコード に対し、複数人ユーザーが 別々のフィールドを編集する 事を前提に回答していましたが
引用: これも、更新時に同様の趣旨のメッセージが表示されます。 それでも、先の方法にこだわるのであれば、不満がおありなのだと思います 不満の内容は何でしょうか? -------------------------------------------------------------------------------------- 抽出にしても、帳票フォームに対し、フォームフィルター を適用する事で事足りると思います。 検索条件を入れるにしても ・フォームォームヘッダーへ配置し、フォームフィルターを適用する ・単票フォームに条件を入れ、そこから帳票フォームを開くにしても Docmd.OprnForm の WhereCondition 引数 へ その条件を渡せば フォームフィルターへ適用できます。 ・単票フォーム に、条件を入れる 各コントロールとサブフォームコントロールを配置 サブフォームコントロールのコントロールソースをを帳票フォームとし、 リンク親子 を、条件を入れる各コントロール 等の方法もあります。 抽出条件を別のフォームやレポートで利用したいなら、 その 抽出条件 を 設定する事になる Me.Filter プロパティー の 値 を 対象となる オブジェクトの Filterプロパティに渡す 対象となる オブジェクトを開く際の WhereCondition引数に渡す で実現できます。 レコードソースとなるテーブルに 表示フラグを持たせる方法を採るにしても 引用: これは、表示フラグ Yes/No型 で考えていますよね? Yes/No型 ではなく、「ユーザー名」またはユーザーを特定する数値を入れるフィールドを配置 その 値 で抽出する様にすれば 良いです。 何にしても、前スレッドで提案した、ローカルテーブルを持たせる手法は 【 同一レコードに対し、複数人がそれぞれ別フィールドの値を同時に更新する 】 を実現させる為に提案しています。 そうでないなら、サーバーテーブル(にリンクしたリンクテーブル)をソースにした 帳票フォームを作成すれば良いと思います。 |
![]() |
投稿日時: 23/01/11 15:18:32
投稿者: hatena
|
---|---|
「あとで編集したデータが優先される仕組み、もしくは、「編集できなかった」と表示される仕組み」とあるので、
|
![]() |
投稿日時: 23/01/11 23:57:50
投稿者: おーさん0729
|
---|---|
Suzu さんの引用: 依頼主(会社の先輩)の要望といいますか、別のスレッド(一般機能の方)でも質問していたのですが、FileMakerからAccessへの移植をしてまして、基本的には完全移植を望まれています。 ですので、FileMakerの画面表示の仕方ありきになってしまうのです。 上記の処理方法がまだ近いのかなといった感じでした。 -------------------------------------------------------------------------------------- 引用: 調べながら試してみます。 表示フラグ Yes/No型でしてますが、フィールドが1つしかないと個別の値にしても、使用者AとBの検索結果がかぶったときに上書きされて、最初の人は表示されなくなりませんか? 引用: 「サーバーテーブル(にリンクしたリンクテーブル)をソースに」が何とリンクさせているのか、いまいちよく分かっていません... |
![]() |
投稿日時: 23/01/12 00:06:53
投稿者: おーさん0729
|
---|---|
hatena さんの引用: 現時点では、保存ボタンの作成は考えていません。理由はひとつ前の回答に書いていますが、「FileMakerからAccessへの移植」がベースになっているからです。 ですので、レコードのフィールドを編集できる方法を考えていました。 保存ボタンを使わず、フィールド編集で「更新時にロックされていて更新に失敗したら少し時間を置いて再トライするという処理」ができれば、一つ解決できる気がします! |
![]() |
投稿日時: 23/01/12 08:20:21
投稿者: hatena
|
---|---|
引用: 保存ボタンは一例として提示しただけで、それにこだわる必要はないです。 FileMakerは使ったことがないので、どのようなUIかは分かりませんが、例えば最後のテキストボックス入力後にEnterキーまたはTabキーを押したら保存処理開始とするなどご希望にあわせてください。 レコード単位ではなく、フィールド毎に更新されたらそく反映させたいという場合なら、テキストボックスの更新後処理で保存処理を実行すればいいでしょう。 引用: 「表示フラグ」の必要性が理解できてませんが、必要なら、ユーザー毎に表示フラグを持たせる場合、自分なら、クライアント側に ID と 表示フラグ(Yes/No型) のフィールドのみのテーブルを作成しておいて、サーバーのリンクテーブルとIDで外部結合させればいいでしょう。 一対一関係になりますので扱いにちょっとこつがいりますが、下記を参考にしてみてください。 一対一関係のテーブル設計 - hatena chips https://hatenachips.blog.fc2.com/blog-entry-29.html |
![]() |
投稿日時: 23/01/12 10:47:36
投稿者: hatena
|
---|---|
フィールド毎に更新されたらそく反映する場合、
Private Sub 連結テキストボックス_Enter() Me.非連結テキストボックス.SetFocus End Sub Private Sub 非連結テキストボックス_AfterUpdate() Me.Refresh Me.連結テキストボックス.Value = Me.非連結テキストボックス.Value Me.Refresh End Sub 競合した場合は、Accessがなんらかのエラーを出すと思いますので、エラー処理で少し待機するとかすればいいと思います。 実際に運用で使用したことがないので、実用的かは分かりませんが、試してみる価値はあると思います。 |
![]() |
投稿日時: 23/01/12 13:25:45
投稿者: Suzu
|
---|---|
もう一度 良く読み返し
引用: が抜けているのを理解しました。 特定条件で検索後、特に表示したいレコードについてチェックボックス等でフラグを入れ 同一フォーム上で、そのフラグのあるレコードを表示した上で、表示されたレコードに対し編集を行う と言う事ですよね。 検索や更新等の処理後の表示について https://www.moug.net/faq/viewtopic.php?t=81859 でも、言っていますし 今回、hatenaさんも同じ方法を提案しています。 引用: チェックボックスは、連結にすると面倒なので非連結にし、 チェック時に、VBAでフィールドに値を入れる事になります。 引用: そうですね。 単に、使用者名を入れるだけなら、そうなります。 テクニックですが 方法1. 使用者1,使用者2,・・・ の様に、ある区切り文字をもって 識別する 抽出は、『Like "*使用者1*"』や、InStr関数 を使う 方法2. 使用者1 → 1、使用者2 → 3、使用者3 → 5 の様に 2^n +1 づつ割り当て、 フィールド に 1なら 使用者1、 4なら 使用者1 と 使用者2 6なら 使用者1 と 使用者3 或いは 使用者1 → 1、使用者2 → 10、使用者3→ 100 の様に 10^n を割り当てる なんて方法もあります。 でも、基本は別にテーブルを持った方が良いでしょう。 引用: 混乱させる様な書き方をしてしまいました。 PC-サーバー : サーバーテーブル ↓ PC-ローカル : サーバーテーブルにリンクしたリンクテーブル が基本です。 (ローカルに、サーバーのテーブルにリンクしたリンクテーブルを持たずに フォームに直接 サーバーのテーブルをソースとした連結フォームにする事が可能なので 先の様な表現になりました。 メリットとしては、オブジェクトとして、テーブルがテーブル一覧に表示されないので ユーザーには簡単には開かれないので、セキュリティーが若干上がる程度と認識すれば良いです。 処理速度が低下する等のデメリットもあるので、こちらはお忘れください。) |
![]() |
投稿日時: 23/01/12 17:12:25
投稿者: hatena
|
---|---|
面白そうだったので、投稿日時: 23/01/12 10:47:36 の回答の方法のサンプルを作成してみました。
Option Compare Database Option Explicit Private OldValue Private Function FocusChange() Me("txt" & Me.ActiveControl.Name).SetFocus End Function Private Function txtGotFocus() MyRefresh OldValue = Me.ActiveControl.Value End Function Private Function txtAfterUpdate() Dim NewValue, CurValue Me.Refresh '最新データ読み込み NewValue = Me(Mid(Me.ActiveControl.Name, 4)).Value If NewValue <> OldValue Then If MsgBox("他のユーザーがこのフィールドを更新しました。編集した値で上書きしてもいいですか。", vbYesNo) = vbNo Then MyRefresh Exit Function End If End If Me(Mid(Me.ActiveControl.Name, 4)).Value = CurValue MyRefresh End Function Public Sub MyRefresh() Me.Refresh '最新データ読み込み '↓非連結テキストボックスを最新データに更新 Dim ctl As Control For Each ctl In Me.Controls If ctl.Name Like "txt*" Then ctl.Value = Me(Mid(ctl.Name, 4)).Value End If Next End Sub ID以外の連結テキストボックスを選択した状態で、プロパティのフォーカス取得時に =FocusChange() と設定。 非連結テキストボックスを選択した状態で、プロパティのフォーカス取得後に =txtGotFocus() 更新後処理に =txtAfterUpdate() と設定。 上記のようにすると、イベントとFunctionプロシージャを関連付けることができるので、各コントロールのイベント処理を共通化できます。(Accessはクラスを使わなくてもこのような方法で共通化できるので楽です。) このあと、連結テキストボックスの上に非連結テキストボックスを重ねて、非連結テキストボックスを背面に移動させれば完成です。 これで動作確認をしてみましたが、いちおう想定通りに動作してます。 フォームとテーブルを同時に開いて、フォームで編集中に、テーブルを更新するなどして、確認しました。 ただ、一人での確認ですので、実際にサーバーのリンクテーブルで複数人で共有して同一フィールドを同時更新したときに、どうなるのか、までは確認できませんので、その場合の対処法はそちらで実装してください。(もし、この方法を採用するならですが) |
![]() |
投稿日時: 23/01/12 22:22:27
投稿者: おーさん0729
|
---|---|
hatena さんの引用: よくわからずに、モジュールに書いたFunctionをCallで呼び出してたのですが、もっと簡単にできるってことですよね? イコールで呼び出してるからしてることとしてはあまり違いはないんですかね? 回答のコードについては、理解が追い付いてないので調べながら試してみます! |
![]() |
投稿日時: 23/01/13 08:29:18
投稿者: hatena
|
---|---|
引用: はい、そうですね。 イベントプロシージャ内のCallで呼び出すと、テキストボックスの数だけイベントプロシージャが必要になりますが、 プロパティに関数を直接設定して関連付ける方法なら、その必要はなくなります。 ただし、イベントプロシージャの引数を受け取ることができませんので、それを必要とする処理には使えません。例えば、キークリック時は、 Private Sub F1_KeyDown(KeyCode As Integer, Shift As Integer) となりますが、この KeyCodeなどは受け取れません。 |
![]() |
投稿日時: 23/01/14 00:21:25
投稿者: おーさん0729
|
---|---|
hatena さんの引用: 同じように作成したのですが、NewValue=""となってしまい、入力後に空欄になってしまいました。 |
![]() |
投稿日時: 23/01/14 00:33:24
投稿者: おーさん0729
|
---|---|
一番の課題は、検索した後の表示レコードの表示の仕方だと気付きました。
引用: 参考に一対一のリレーションは(たぶん)できたのですが、リンクの例で言うと、 @フォームに従のレコード表示ができない(ソースの設定がうまくいかない?) A従のレコードを使用したフィルター設定ができない で困っています。 また以前、言ってました表示フラグ関係の話はAに近いと思っています。 従のテーブルレコード=クライアントテーブルレコードと考えて、 リンク先で言うと、給与額や査定結果のフィールドを使ってフィルター設定をしたいです。 |
![]() |
投稿日時: 23/01/14 11:12:23
投稿者: hatena
|
---|---|
おーさん0729 さんの引用: あっ、すみません。いろいろ修正していたのですが、修正する前のもの貼り付けていたようです。 Function txtAfterUpdate()内の下記の部分を修正してください。 Me(Mid(Me.ActiveControl.Name, 4)).Value = CurValue ↓ Me(Mid(Me.ActiveControl.Name, 4)).Value = Me.ActiveControl.Value |
![]() |
投稿日時: 23/01/14 11:18:41
投稿者: hatena
|
---|---|
おーさん0729 さんの引用: 検索(抽出)処理はうまくできているということですか。(処理速度的にも問題ないですか。) 抽出した後、さらに、チェックボックスで表示するレコードを絞り込むということでしょうか。 おーさん0729 さんの引用: リンク先を参考にクエリを作成したのでしょうか。 そのクエリのSQL文を提示してもらえますか。 |
![]() |
投稿日時: 23/01/16 19:22:19
投稿者: おーさん0729
|
---|---|
hatena さんの引用:おーさん0729 さんの引用: できました!ありがとうございます! |
![]() |
投稿日時: 23/01/16 20:02:59
投稿者: おーさん0729
|
---|---|
hatena さんの引用: 検索(抽出)処理はできていますが、 すみません。説明が足りてなかったと思います。 @サーバーレコードを特定検索(自作処理) A該当するレコードをローカルレコード(ID、表示フラグ)に追加。 Bそのローカルレコードと同じサーバーレコードだけを表示。(フィルター設定?) です。 したいことは「ローカルレコードに存在するレコードと同じサーバーレコードの表示」です。 もしくは、「抽出条件をローカルレコードにしたサーバーレコードの表示」です。 あくまでも、表示するのはサーバーレコードです。 投稿日時: 23/01/11 14:42:58や投稿日時: 23/01/12 08:20:21でも触れている内容です。 表示フラグにこだわりません。表示するレコードがサーバーレコードであり、複数の使用者で共用にならなければ、大丈夫だと思います。 意図は使用者Aと使用者Bで検索結果を各自表示したいからです。(このときに編集を行い、検索結果次第ではAとBに同じレコードが表示されるため、同時編集の話もしていました) 引用: 表示したいフォームのレコードソースに設定している文です。 SELECT サーバーテーブル.*, ローカルテーブル.表示1 FROM サーバーテーブル INNER JOIN ローカルテーブル ON サーバーテーブル.[ID] = ローカルテーブル.[ID]; 「ローカルテーブル.表示1」が表示したいレコードとして、もたせている表示フラグです。 よろしくお願いします。 |
![]() |
投稿日時: 23/01/16 21:48:18
投稿者: hatena
|
---|---|
おーさん0729 さんの引用: @サーバーレコードを特定検索(自作処理)とは、具体的にどのような処理なのでしょう。 抽出条件を生成してフィルターをかけるということでしょうか。 もし、そうならその時点で目的のサーバーレコードの絞り込みはできているということではないですか。 その抽出条件を帳票フォームのフィルターに設定すれば済む話だと思いますが。あるいは、抽出条件を設定したクエリをレコードソースに設定すればいいと思いますが。 ローカルテーブルが必要になる必然性が分かりません。 抽出条件の生成ではないのなら、@サーバーレコードを特定検索(自作処理)[/color]の具体的に内容を説明してください。 |
![]() |
投稿日時: 23/01/16 22:32:14
投稿者: おーさん0729
|
---|---|
引用: ちょっと前のをコピペしました。フィールド名が今現在とは違うくらいです。 宣言は基本的にstringかLongです。 @検索用フォームに検索ワードを入力する。複数入力、and,or可能(見た目は表示用フォームと同じ) A対応するフィールドで検索ワードを使い、抽出。 B表示フラグを持たせる C表示フラグでフィルター設定 のはずです。 表示フラグをサーバーレコードに持たせると、複数人使用時の検索結果が同一になってしまうので、ローカルに持たせて検索結果を各々にしたいという意図です。 Private Sub フィルター2(KeyCode As Integer, Shift As Integer) 'On Error GoTo err_cmd Dim db As Database 'テーブル Dim rsa As Recordset 'テーブルのレコード Dim rsb As Recordset '検索用テーブルのレコード Dim txtken As String Dim i As Long Dim j As Long Me.Requery Picnt = 0 Picnt = DCount("ID", "サーバーテーブル") If Picnt > 0 Then 'Pstrfilter = 検索条件を"and"でもつ '対象:画面表示されているレコードセットをもつ Set db = CurrentDb Set rsa = db.OpenRecordset("サーバーテーブル", dbOpenDynaset) 'レコードの総数を変数でもつ rsa.MoveLast rsa.MoveFirst PrecordC = rsa.RecordCount 'レコードの[フィルター外]をリセット = "" 'レコードの[表示]をリセット = "false" For Picnt = 1 To PrecordC rsa.Edit rsa.Fields(表示) = "false" rsa.Update rsa.MoveNext Next Picnt Pstrfilter = "" Forms.フォーム.Filter = "" Me.Refresh Set rsb = db.OpenRecordset("検索用テーブル", dbOpenDynaset) '検索用テーブルレコードの総数を変数でもつ If Not rsb.RecordCount = 0 Then rsb.MoveLast rsb.MoveFirst PrecordC2 = rsb.RecordCount Pvarfilter = Array("Pstrfilter1", "Pstrfilter2", "Pstrfilter3", "Pstrfilter4", "Pstrfilter5", "Pstrfilter6", "Pstrfilter7", "Pstrfilter8", "Pstrfilter9", "Pstrfilter10") rsb.MoveFirst Else MsgBox "検索ワードがありません" DoCmd.Close Exit Sub End If For i = 1 To PrecordC2 If Not rsb![品種] = "" Then Pvarfilter(i) = Pvarfilter(i) & " and " & BuildCriteria("品種", dbText, rsb![品種] & "*") End If If Not rsb![規格] = "" Then Pvarfilter(i) = Pvarfilter(i) & " and " & BuildCriteria("規格", dbText, rsb![規格] & "*") End If ※同様にフォームに存在するテキストボックス分あり Pvarfilter(i) = Mid(Pvarfilter(i), 17) If Pvarfilter(i) = "" Then MsgBox "検索ワードがありません" DoCmd.Close Exit Sub Else End If Select Case rsb![検索] Case 1 txtken = "or " Case 2 txtken = "and not " End Select If i = 1 Then If txtken = "or " Then Pvarfilter(1) = " and " & Pvarfilter(1) Else Pvarfilter(1) = " and " & " not " & Pvarfilter(1) End If Else Pvarfilter(i) = " and " & txtken & Pvarfilter(i) End If rsb.MoveNext Next i DoCmd.OpenForm "お待ちください" DoEvents If Not rsb.RecordCount = 0 Then Call 検索1 End If If IsNull(Pcurrentform.[ID].Value) Then MsgBox "レコードがありません" DoCmd.Close acForm, "" & Me.Name & "" DoCmd.Close acForm, "" & PfnameRe & "" DoCmd.Close acForm, "お待ちください" DoCmd.OpenForm "" & PfnameRe & "" '変数の解放 Set db = Nothing Set rsa = Nothing ReDim Pvarfilter(i) DoCmd.Close acForm, "お待ちください" Call 全表示 Exit Sub Else End If DoCmd.Close acForm, "検索用フォーム" Pbk = Pcurrentform.[ID].Value Else MsgBox "レコードがありません" DoCmd.Close acForm, "" & Me.Name & "" DoCmd.Close acForm, "" & PfnameRe & "" DoCmd.Close acForm, "お待ちください" DoCmd.OpenForm "" & PfnameRe & "" Call 全表示 End If '変数の解放 Set db = Nothing Set rsa = Nothing ReDim Pvarfilter(i) DoCmd.Close acForm, "お待ちください" Exit Sub Callで呼んでいるのが、 Public Sub 検索1() On Error GoTo err_cmd Dim db As Database Dim rs As Recordset '元となるテーブル Dim rsa As Recordset '画面表示されているテーブルのレコード Dim rsf As Recordset 'フィルター実行テーブル Dim rsb As Recordset '追加するテーブル '元のフォームにより、分岐する DoEvents '対象のレコードセットをもつ Set rsa = Pcurrentform.Recordset If rsa.RecordCount = 0 Then MsgBox "レコードがありません" Pcurrentform.反転用.Value = False Pcurrentform.Filter = "" Pcurrentform.FilterOn = False Pcurrentform.ソート状況 = "未ソート" Else Call 検索処理 Call 表示 End If DoEvents '変数の解放 Set db = Nothing Set rs = Nothing Set rsa = Nothing Set rsb = Nothing Set rsf = Nothing Pfil = "on" Exit Sub Public Sub 検索処理() On Error GoTo err_cmd Dim db As Database Set db = CurrentDb Select Case PrecordC2 '検索 Case 1 PmySQL(1) = "UPDATE 引当File SET 引当File." & Pusecount & " = True WHERE " & Mid(Pvarfilter(1), 6) & "; " db.Execute PmySQL(1) Case 2 PmySQL(1) = "UPDATE 引当File SET 引当File." & Pusecount & " = True WHERE " & Mid(Pvarfilter(1), 6) & " " PmySQL(1) = PmySQL(1) & "" & Mid(Pvarfilter(2), 6) & "; " db.Execute PmySQL(1) ※同様にCase7まであり End Select Exit Sub Public Sub 表示() 'On Error GoTo err_cmd '"[表示]=true"を表示 Pcurrentform.Filter = "表示=true" Pcurrentform.FilterOn = True Pcurrentform.OrderByOn = False Pcurrentform.OrderBy = "[ID]" Pcurrentform.OrderByOn = True Exit Sub Public Sub 全表示() 'On Error GoTo err_cmd Dim db As Database 'テーブル Dim rsa As Recordset 'テーブルのレコード '再描画しない Echo False DoEvents Set db = CurrentDb Set rsa = Pcurrentform.Recordset PCuReF = False Pcurrentform.Refresh Pstrfilter = "" Pcurrentform.Filter = "" Pfil = Pcurrentform.Filter Pcurrentform.OrderBy = "" Psort = Pcurrentform.OrderBy Pcurrentform.OrderByOn = False Pcurrentform.FilterOn = False Pcurrentform.反転用.Value = False '流用時注意 DoEvents ' Pcurrentform.RecordSource = "" DoEvents '全レコードの[表示]をfalseにする PmySQL(1) = "UPDATE " & Ptname & " SET " & Ptname & ".表示 = false " PmySQL(1) = PmySQL(1) & "WHERE (((" & Ptname & ".表示)=True)); " db.Execute PmySQL(1) DoEvents Pcurrentform.OrderBy = "[ID]" Pcurrentform.OrderByOn = True Pcurrentform.ソート状況 = "未ソート" Pfil = "" Psort = "" DoEvents Pbkstr = "ID= " & Pbk Pcurrentform.Recordset.FindFirst Pbkstr PCuReF = True DoEvents '対象:テーブル全体のレコードセットをもつ PmySQL(1) = "SELECT * FROM " & Ptname & "; " Pcurrentform.RecordSource = PmySQL(1) DoEvents '再描画する Echo True Exit Sub よろしくお願いします。 |
![]() |
投稿日時: 23/01/17 09:22:03
投稿者: hatena
|
---|---|
コードを提示していただいたので、解読を試みたが、とてもじゃなけど読めません。
引用: @Aで抽出ができている、つまり、抽出条件が生成できているので、それを帳票フォームにフィルターに設定するだけのこと。 BCは不要です。 これが理解できないなら、私とは次元の違う位置にいると思われますので、これ以上の私からのアドバイスはないです。 |
![]() |
投稿日時: 23/01/17 11:11:21
投稿者: Suzu
|
---|---|
テーブル
|
![]() |
投稿日時: 23/01/17 23:15:44
投稿者: おーさん0729
|
---|---|
hatena さんの引用: 長期にわたり、ありがとうございました! |
![]() |
投稿日時: 23/01/18 19:20:50
投稿者: おーさん0729
|
---|---|
Suzu さんの引用: 完全再現はできなかったのですが、4から6を一緒に処理するのが理想かもです。 5の必要がなく、検索結果が表示されれば、良いです。 また、ボタン一つで検索結果の反対(False)レコードの表示やフィルターのリセット(レコードソースの設定?)もしたいです。 引用: 以前にも教えていただいてました。 こっちの問題が進まなくて、手直しできてないです... |
![]() |
投稿日時: 23/01/19 09:01:05
投稿者: Suzu
|
---|---|
そもそもFileMaker と Access は違うものであり、当然GUIも違います。
引用: 5の必要が無い?? 抽出条件 を指定し、抽出結果を表示、更にその抽出結果に対し、表示するレコードを「選択」し 画面に表示するのではなかったのでしょうか? それなのに、その「選択」が必要ないのですか? 当方は 大まかな処理の流れを提示させて頂いただけであり、 希望とそぐわない部分があれば、希望の動作になる様に、修正すれば良いです。 おおまかな流れについての当方の認識は、 引用:違うのであれば、どう動かしたいのか説明くさい。質問者さんの理想が、どうあるのか当方には判りません。 当方は、処理を行うための大まかな流れや、部分的なコードは提示するかもしれませんが 希望の動作そのものをする全体コードは提示しませんので、ご承知ください。 |
![]() |
投稿日時: 23/01/19 20:06:49
投稿者: おーさん0729
|
---|---|
Suzu さんの引用: すみません。まったた同じは誇張した表現でした。 見た目は少なくとも同じ感じ。処理は同じように処理できれば大丈夫です。 例えば、レコードが100件あり、IDは1〜100として、 帳票フォームで全件100件表示状態から、検索用フォームを使い、偶数を抽出(検索)する。 2,4,6,...と偶数50件を帳票フォームに表示する。 50件表示状態から再抽出しても、全件から再抽出できるように。 がしたいことです。 なので、抽出結果をそのまま表示だけできればよく、選択する必要はありません。 引用: 部分的なコードでも大変助かっております。 少し別件なのですが、 ここの即効テクニック→Access一般機能→データ操作→他のテーブルのデータを直接参照する にあるDlookUp関数をコントロールソースにしたデータはフィルター設定にできないですか? =DLookUp("[ローカル用.表示]","[ローカル用]","[ローカル用].[ID]=[サーバー].[ID]") を帳票フォームに配置して、これをフィルターかけれたら、解決するのではと思っています。 よろしくお願いします。 |
![]() |
投稿日時: 23/01/23 09:29:59
投稿者: Suzu
|
---|---|
引用: 承知しました。 1. 引用: 「検索用フォーム」にて 抽出条件を指定 これは判ります 念のため・・ これは、抽出条件のみを入れる、非連結単票フォームですよね? 2. 引用: 「帳票フォーム」に抽出条件に一致したレコード表示 ここまでは判るのですよ。 3. 引用: ??? 2.で、50件は表示されているのですよね? 同じレコードを表示する? 2. と何が違うのでしょうか? 抽出条件が変わるのですか? 表示するフォームが変わるのですか? 引用: 抽出したい 値を持つコントロールを選択し、手動で、抽出が適用できれば Filter で出来るでしょう。 |
![]() |
投稿日時: 23/01/23 20:45:34
投稿者: おーさん0729
|
---|---|
引用: 帳票フォームをコピーしてコントロールを非連結にしている"非連結帳票フォーム"にしてます。 メニュー→表示フォーム→検索フォーム→表示フォームです。 また、"非連結単票フォーム"タイプのものもあります。 こちらは、メニュー→検索フォーム→表示フォームで使っています。 引用: 偶数50件表示状態から、 @「12」だけ、A「12」の○○(他条件)だけ、B「5」だけ、等 といったいろんな検索条件に対応するためです。 「12」は偶数50件から抽出できても、「5」は100件から抽出しないとできませんよね? ※一応、フィルター設定等をリセットするボタンはありますが、抽出状態から再抽出人もいます。 もしかして、設定を間違っているだけで、常に全件から抽出できるんですかね?(表示されているレコードから抽出されるものだと思ってました。) 引用: リボンにあるフィルターの詳細設定からフィルターを設定して実行(抽出は成功しました)、それをクエリ→SQL化したものをフィルター条件に設定したら、エラーが出ました。 |
![]() |
投稿日時: 23/01/24 10:03:42
投稿者: Suzu
|
---|---|
引用: 抽出条件を入力させるフォームが 検索フォームなのですね。 (非連結 の 帳票フォーム は 作成できません。 非連結にした段階で単票になるはずです。) 引用: レコードソース全件からの抽出です。 あくまで、レコードソースとなっているテーブル/クエリ に対し 条件を設定し抽出します。 フィルター適用済み の 表示中のみのレコードから 更に抽出する為には、 フィルター に 更に 抽出条件を追加する事で実現します。 フィルターの文字列は、SQLのWHERE句と同様。 1.フィルターを適用 (仮に、【 区分="AA" 】とします) この時のコードは Forms![フォーム].Filter = "区分="AA"" 2.条件【 区分2="いい" 】を追加したい場合には フィルター には、【 区分="AA" And 区分2 = "いい" 】 を渡します この時のコードは Dim strWhere As String strWhere = Forms![フォーム].Filter 'フィルタープロパティーが適用済みか判断 If Len(strWhere) > 0 AND Forms![フォーム].FilterOn = True Then 'フィルター適用済み '既存のフィルターに【 区分2="いい" 】を追加 Forms![フォーム].Filter = Forms![フォーム].Filter & " And 区分2=""いい""" Else 'フィルター適用なし 'フィルターに【 区分2="いい" 】を渡す Forms![フォーム].Filter = "区分2=""いい""" End If Forms![フォーム].FilterOn = True こんな感じになろうかと。 引用: 先にも言いましたが、SQL WHERE句 以降と同じ構文です。 フィルター適用済みのフォームに対し 引用:とでもして Filterの内容を確認しましょう。 保存した クエリの SQL の WHERE句 以降と同じはずです。 先のコードでも示しましたが、 変数 = Forms![フォーム].Filter とでもすれば、Filter の文字列を退避できます。 必要な時に、 Forms![フォーム].Filter = 変数 と戻せばFilterの抽出を再現できます。 質問者さんは、Filter の処理の 認識が違うので 引用: この動作が必要と感じたのでしょうが、 そもそも、全件からの抽出になるので、処理自体必要無いと言う事で良いでしょうか? ----------------------------------------------------------------------------------- VBA は、手動操作 を 自動化します。 手動で操作を行っている事を 楽にする為 或いは、 ユーザーインターフェイスとして、ボタンやテキストボタンを配置しユーザー操作の簡易化を図ります。 ですから、Accessにどんな機能があるか 動作がどうなるか を知ったうえで使った方が良いです。 また、手動できちんと動作する事を確認し、 その上で、VBAでどう自動化するかを考えましょう。 一般的には、一般機能を知った上で、VBAを使い操作します。 対し、 質問者 さん は 一般機能 についての 理解が不足している様に思います。 回答者としては コードでこの機能を使っているのであれば、この辺りは理解しているだろうと 推測する部分について 質問者の 理解が 不十分であったり、間違っている事で 表現に対し認識の齟齬が発生している状況です。 手動で、操作し動作する事を確認しましょう。 |
![]() |
投稿日時: 23/01/24 18:56:15
投稿者: おーさん0729
|
---|---|
引用: すみません。 検索用テーブルを作り、それと連結させていました! そのフィールドの値を変数に持たせて、検索ワードで使っています。 引用: この辺を参考になんとか形にできました。 フィルターが働いていなかった原因は、別のところで違うレコードソースを設定していたからみたいです。 引用: フィルターの設定の仕方が悪かったものだと思われます!なんとかなりました! 引用: 本などで調べるよりも先に実際に使っていたので、基本的な使い方や知識が少ないです。 そのまま業務外で自習することもほとんどしてこなかったので...(言い訳ですが...) |
![]() |
投稿日時: 23/01/25 10:07:38
投稿者: Suzu
|
---|---|
質問者さんの 希望の動作が出来た様で何よりです。
引用: そういう事ですか。 それが判ると、過去レスにもそれらしき記載はありますね・・ 回答者としては、前提条件として認識すべきなのでしょうが認識できていませんでした。 とても 遠回りをさせてしまい すみませんでした。 引用: 引用: 結局、勘違いや、設定違い ですか・・ 今までの 時間は・・ それも、結局は 気付けなかった自分自身も悪いのですが・・ SQL JOIN に別テーブルを指定し、その別テーブルに抽出条件となるキーワードを設定 確かに、在りますね 上記を採ると、一致条件が完全一致になり ユーザー目線で使いたいと思える、 【フィールドの内容の一部に 指定したキーワードが含まれいる部分一致の抽出】 に不向きであり、思考の枠外においていました。 とりあえず、今回の質問に関しては解決された様でなによりです。 |
![]() |
投稿日時: 23/01/25 19:02:04
投稿者: おーさん0729
|
---|---|
Suzu さんの引用: ありがとうございました! 自作でいろんな処理を作っていたので、記載した内容だけではわからないと思います。 ここまで付き合っていただき本当にありがとうございます。 無理やり検索ワードの後ろに「*」をつけて、前方一致にしています。 足して足してで作っているので、いろんなところで齟齬が出てきて、把握しきれてないですw 今でも、わからないところがあるので、すぐにまた聞きに来そうです。 |
![]() |
投稿日時: 23/01/26 09:00:45
投稿者: Suzu
|
---|---|
マルチユーザーによる使用について VBAで作成するのは 難易度として高い部類です。
|
![]() |
投稿日時: 23/01/27 00:28:11
投稿者: おーさん0729
|
---|---|
Suzu さんの引用: 調べながらでしたので、拾ってきた情報をそのまま流用して、帳尻を合わせて行き当たりばったりに作っていた感じです。なので、いろいろ支障をきたしています。 会社の人には週一で進捗を報告して、ある程度進み具合は理解してもらっているつもりです。 この件で進んでないことも知っています。 そのうえで、遅れをどうするつもりだ、できるまで「自主的に」したらどうだ、いった感じです。(それが当たり前なことかは存じませんが...) |
![]() |
投稿日時: 23/01/27 17:03:07
投稿者: Suzu
|
---|---|
引用: 参考にしたコードの処理内容を理解できれば、修正もできるでしょう。 少なくとも『どこが問題なのか』について、原因調査を出来るスキルをお持ちであると思います。 Accessの機能についての知識が不足している事で 対策の選択肢が狭まっているのであろうと思います。 このまま進めても、いつかは 希望に近い成果物もできるであろうと思います。 質問者さんの 他の業務や、システムとしての進捗も判りかねますので 当方から言える事としては、 このままの進め方で進めたとき、その成果物がいつ頃になりそうか 見通しを含め 上司 に相談 でしょうか。 いきなり、 他のアプリケーションで動作していたものを、別のアプリケーションで再現する様に 言われ 暗中模索で進めなければならなかったのは、無茶振りだなとは思います。 進め方として、Access一般機能をではなく、Access VBA でゴリゴリ進めようとすると Accessである事の必要があるのか? 逆に Accessである事が コードゴリゴリで進めようとする時に、ネックになっているのかもしれませんね。 今更 ではあるかもしれませんが、 ・Accessを選んだ理由 ・求める機能 (単純に、FileMakerでしている事をそのまま出来る ではなく もっと具体的な 処理内容) ・質問者さんが 開発を担当する理由(外に出さない理由、質問者さんが開発する事で何を期待するのか) : 単に、やらされれている から では なく、上司の方と相談してみてはどうでしょうか。 |