• ベストアンサー

【Access】 VBA 入力漏れを防ぎたい

Access&VBA初心者です。 商品の入出庫状況をACCESSで管理しようとしています。 ある項目の入力漏れを防ぐためにメッセージが出るようにしたいのですがどのようにしたらいいかわかりません。 【商品マスターテーブル】 商品コード 商品名 管理・・・yes/no型(yesの場合はロットと期限の管理が必要) 【入力フォーム】 商品コード 入庫数 出庫数 ロット 期限(タブストップしない) 商品マスタで「管理」がYesになっている場合で「ロット」もしくは「期限」が入力されていない場合、 次のレコードに移る前に「ロット又は期限が入力されていません」というメッセージボックスを表示し、 「ロット」と「期限」を入力するようにしたいと思っています。 現在はネットで調べて「ロット」を入力したら「期限」を入力するように Private Sub ロット_AfterUpdate()   If IsNull(Me.期限) Then     MsgBox "期限を確認してください"     Me.期限.SetFocus   End If End Sub というかんじにしてみたのですが、 「ロット」を入力し忘れてしまったり、「管理」がNoであっても「ロット」を入力することがあるので 改善をしたいと思っていますがVBAの使い方がわからないためこの先にすすめません。 何か良い方法がありましたらアドバイスをお願いします。 ※入力フォームにはテキストボックスを貼り付けて「管理」が-1もしくは0で表示だけされるようにしています。

  • mbwd
  • お礼率71% (5/7)

質問者が選んだベストアンサー

  • ベストアンサー
noname#140971
noname#140971
回答No.5

商品マスターの情報に基づいて入力するフィールドを制限する仕組みと未入力チェックを組み合わせ、かつ、レコードを登録する際にチェック機能を起動するのが最適。 しかし、これには、全体のイベントの意味やそれぞれの仕掛けの相互関連の理解が課題。 少し、難しいかも知れませんね。 <Dlookup関数> ? DBLookup("管理", "商品マスター", "商品コード='A-102'",False) False ? DBLookup("管理", "商品マスター", "商品コード='A-102'","Not Found!") Not Found! ? DLookup("管理", "商品マスター", "商品コード='A-102'") Null ? Nz(DLookup("管理", "商品マスター", "商品コード='A-102'"),False) False ところで、このように Access の DLookup関数は、Null値を返します。 ですから、Nz関数を併用するかDBLookup関数を使う必要があるかも知れません。 なぜなら、 DBLookup関数はNull値の置換を指示することが可能だからです。 なお、DBLookup関数の類は自作することになります。 さて、入力するフィールドを制限する仕組みを前提にしない場合のチェックコードは僅か5行。 ここでは、未入力か否かをフィールドに入力されている値+""の長さが0か否かで判断しています。 ここら辺りは好みの問題です。 Private Sub Form_AfterUpdate()   If Nz(DLookup("管理", "商品マスター", "ID=" & Me.商品マスター_ID), False) Then     If Not Len(Me.ロット & Me.期限 & "") Then       MsgBox "[ロット]ないし[期限]が未入力です。", vbExclamation, " 警告"     End If   End If End Sub Private Sub Form_AfterUpdate()    If DBLookup("管理", "商品マスター", "商品コード='" & Me.商品コード & "'"), False) Then     If Not Len(Me.ロット & Me.期限 & "") Then       MsgBox "[ロット]ないし[期限]が未入力です。", vbExclamation, " 警告"     End If   End If End Sub さて、確かに僅か5行程度のコードで目的は達成されると思います。 しかし、これじゃ、管理不要の場合の入力の有無チェックをしなきゃ片手落ち。 Private Sub Form_AfterUpdate()   If Nz(DLookup("管理", "商品マスター", "ID=" & Me.商品マスター_ID), False) Then     If Not Len(Trim(Me.ロット & Me.期限) & "") Then       MsgBox "[ロット]ないし[期限]が未入力です。", vbExclamation, " 警告"     End If   Else     If Len(Trim(Me.ロット & Me.期限) & "") Then       MsgBox "[ロット]と[期限]の不要データをクリアします。", vbInformation, " お知らせ"       Me.ロット = Null       Me.期限 = Null     End If   End If End Sub そういうことで、先の5行を多少修正することになります。 しかし、これで、現場のユーザが納得するかどうかです。 「そもそも入力が必要の無いフィールドを無効にしてくれないか?」と言い出すかもしれません。 こうして、徐々に先の回答へと回帰していきます。 しかし、それさえも使い勝手の問題で否定されるでしょう。 このように、VBAでの入力の制御は、実に色んな問題を孕んでいます。 肝心なのは、終始一貫したルールを全ての入力フォームに適用することです。 質問者は、その探求の入り口に立ったばかり。 頑張って下さい。

mbwd
質問者

お礼

丁寧なご回答ありがとうございます。 やはり奥が深いというか難しいのですね。 >全体のイベントの意味やそれぞれの仕掛けの相互関連の理解が課題 まさにおっしゃる通りです。 今回は前任者が紙ベースで管理していたものをデータベース上での管理に変更しようとしたのが始まりだったので、 今後私から後任者に引き継ぎをする前までに使い勝手のよいものを作成していこうと思います。

その他の回答 (4)

  • mshr1962
  • ベストアンサー率39% (7418/18948)
回答No.4

Private Sub 詳細_AfterUpdate() KR = Dblookup("管理","商品マスタ","[商品コード]=" & Me.商品コード) If KR = VbYes Then If IsNull(Me.ロット) Or IsNull(Me.期限) Then MsgBox "ロット又は期限が入力されていません" If IsNull(Me.ロット) Then Me.ロット.SetFocus Else Me.期限.SetFocus End If End If End If End Sub

mbwd
質問者

補足

ご回答ありがとうございます。 そのまま貼り付けてみたのですがなぜか何もおこりません。 勉強不足で大変申し訳ないのですが KR = Dblookup("管理","商品マスタ","[商品コード]=" & Me.商品コード) の部分の解説をしていただけると助かります。 入力した商品コードを元に"商品マスタ"の"管理"を見る?ということでしょうか。 あとPrivate Sub 詳細_AfterUpdate()とは 新しいレコードに移る前にメッセージboxが表示されるようになるということでしょうか。 詳細プロパティのイベントタブでみることはできますか? 本当に初心者な質問な上、質問の内容もよくわからなくて申し訳ありません。

回答No.3

すいませんNo2で回答したものです。 よく確認してませんでした。入力した段階でもうチェックしてるんですね。 入力系をチェックするならいちいちその都度きくよりも 最後にまとめてチェックする方が親切ですよ。 ネットなんかで登録する時も最後の決定ボタン押した時に 間違ってますよ~て注意してくるじゃないですか。

回答No.2

管理がYESかNOのどっちなのかは、表示されてる-1,0で判断するって事ですか? もしそうなら下の方法で良いと思います。 もし管理の値をまだ取得していないなら 商品コードをキーにしてADOやDAOでチェックしてあげれば良いです。 ???にはテキストボックスの名前、-1がYes,0がNoと考えてます。 Private Sub ロット_AfterUpdate()   If Me!??? = -1 then    If IsNull(Me.期限) or IsNull(Me.ロット) Then      MsgBox "ロット又は期限が入力されていません"      Me.期限.SetFocus    End If   End If End Sub

mbwd
質問者

お礼

ご回答ありがとうございます。 ロットの更新後処理→フォーカス喪失時にしてみたところ うまくメッセージボックスが表示されました。 エクセルのIF関数と違うのでIFの使い方がわからなくて困っていたのですが、疑問が解決されました。 ただ、メッセージボックス表示後フォーカスの移動がうまいこといかなかったので検討の上、後日会社で再度試してみようと思います。

noname#140971
noname#140971
回答No.1

商品マスター: ID__商品コード__品名___________管理 1___A-101________OO-OOO___No 2___B-121________XX-XXX_____Yes 入出庫履歴: ID__入出庫区分__商品マスター_ID__数量_____ロット 期限 1_________________1_____________________1_______10_______0 2_________________1_____________________2_______10_______0 3_________________2_____________________1_________5_______0 4_________________2_____________________2_________5_______0 まず、列[入出庫区分]を設けた方が良いかも知れません。 1=入庫、2=出庫、3=調節、9=その他 将来、棚卸誤差等の調節等の入力が必要になった場合の対応が容易です。 ID__入出庫区分__商品マスター_ID__数量__ロット__期限 1_____________入庫__A-101________________10_______0 2_____________入庫__B-121________________10_______0 3_____________出庫__A-101__________________5_______0 4_____________出庫__B-121__________________5_______0 ところで、質問の回答はちょっとややこしいです。 つまり、どのように仕掛けるかという工夫の問題だからです。 例えば、商品マスターの情報に応じて入力フィールドの有効・無効を設定するのも手。 この場合、有効なフィールドが入力されているか否かをテストすれば良いことに。 その場合、既存レコードの設定もしなきゃおかしな現象になります。 また、有効・無効で変更できなくなる列の初期化も忘れてはいけません。 以上のようなことを実現するサンプルコードは次のようです。 Private Sub Form_Current()   If Not Me.NewRecord Then     SetEnabled Me.商品マスター_ID   End If End Sub Private Sub Form_AfterUpdate()   Dim ctl As Control      For Each ctl In Me.Controls     If ctl.ControlType = acTextBox Or ctl.ControlType = acComboBox Then       If ctl.Enabled And (Len(ctl.Value & "") = 0) Then         Warning ctl.name & " が未入力です!"         Exit For       End If     End If   Next ctl End Sub Private Sub 商品マスター_ID_LostFocus()   Dim lngGoodsID As Long   lngGoodsID = Val(Me.商品マスター_ID & "")   SetEnabled Me.商品マスター_ID   If lngGoodsID = 0 Then     Message "商品コードを選択して下さい!"   End If End Sub Private Sub SetEnabled(ByVal lngGoodsID As Long)   Dim isKanri As Boolean   isKanri = (DLookup("管理", "商品マスター", "ID=" & lngGoodsID) = True)   Me.ロット.Enabled = isKanri   Me.期限.Enabled = isKanri   If Not isKanri And Len(Me.ロット & Me.期限 & "") Then     Me.ロット = Null     Me.期限 = Null   End If End Sub <標準モジュール> Public Sub Message(ByVal Msg As String)   MsgBox Msg, vbInformation, " お知らせ" End Sub Public Sub Warning(ByVal Msg As String)   MsgBox Msg, vbExclamation, " 警告" End Sub Q、何か良い方法がありましたらアドバイスをお願いします。 A、入力フォームを閉じた時に、不具合レコードをチェックし警告・削除することです。 上述のような警告システムはユーザの自在な入力を阻害するだけです。

mbwd
質問者

お礼

ご回答ありがとうございます。 なにぶん初心者というかVBAを全く知らないまま質問をしてしまったものでコードの解読に少し時間がかかりそうです。 参考にさせていただきます。

関連するQ&A

  • アクセスのMeについて

    アクセスの本の中で,Meが出てきました。 問題は,フォームに得点と結果のテキストボックスを作成します。そして,テキストボックスに得点を入力します。コマンドボタンに次のイベントで,得点が合格か不合格かを判定し,結果のテキストボックスに出力するものです。フォームにMeを入力していないのですが,VBAで突然現れてきました。このMeは,どんなときに使うのでしょうか。教えていただければ幸いです。 Private Sub 実行_Click() If Me.得点 >= 100 Then Me.結果 = "合格" Else Me.結果 = "不合格" End If End Sub

  • アクセスでの日付入力

    アクセスの初心者です。 2000を使っているのですが、フォーム上にチェックボックスと納品日のテキストボックス?を作りチェックボックスにチェックを入れると自動的に納品日(本日の日付)が入るようにしようと思い、自分でいちを作成してみました。 ただ、チェックを入れると日付は入るのですが、チェックを外しても日付が入ったままなのです。チェックを外したら日付も消えるようにする事はできるのでしょうか? チェックボックスのイベント→クリック時に下のようなVBAを入れてます。 Private Sub チェック12_Click() If Me!チェック12 = True Then Me!納品日 = Date End If End Sub

  • Access レコードのロック

    Access2000 フォームを読み込んだとき,テキストボックス"受付No."欄が 入力されている場合,テキストボックス"件名"欄をデータの変更が 出来ないようにロックを掛けたいのです。 下記のイベントプロシージャを組んだのですが,全くロックされません。 VBA初心者なので多分とんでもない間違いをしていると思いますが, どこが違うのかご指摘下さい。 Private Sub Form_Load() If Me.受付No. <> "" Then Me.件名.Locked = True Me.件名.Enabled = False End If End Sub

  • コンボBOXで抽出した値をテキストBOXに表示したい

    入力用フォームで注文フォームを作成しているのですが、コンボBOXで商品Noを抽出し、テキストBOXに商品名を表示したいのですが、 Private Sub コンボ1_AfterUpdate() Me!テキスト1 = Me!コンボ1.column(1) End Sub と入力したのですが、他の行にも同じ商品名が表示されます。 商品NoをコンボBOXで指定し、数量を手入力という入力フォームを作成したいのです。 作成方法を教えてください。 よろしくおねがいします

  • (ACCESS)入力フォームについて

    こんにちはmynannです またまた困っているのでよかったらヒントを いただきたいと思い質問させていただきます まずテーブルが二つあり 商品マスタには管理番号(主キー)と価格の二つの項目があります。 もうひとつは販売マスタというのがあり フィールドは管理番号、販売可(チェックボックス) の二つです。 この二つはリレーションシップの関係にあります そしてこの二つを一つにした 販売可商品マスタクエリがあります 商品マスタにはすでに多くのデータがあり それ専用の入力フォームもあります 今販売マスタの入力フォームを作りたいのです どのようなものかといいますと 管理番号を入力すると価格用のテキストボックスに 自動的に入力された管理番号の価格(商品マスタから調べると思うのですが)を表示するようにしたいのです 管理番号[       ]←ここに値を入力 価格[       ]←管理番号が入力されると自動的にでる 販売可 □ ←自分でチェックする イメージはこのような感じです 更新後処理を使うということはなんとなくわかるのですが どのような処理をさせていいかわかりません 助けてください!お願いします!

  • ACCESS

    現在以下のシステムを検討しています。 (1)ログインフォームと(2)トップフォーム(3)注文フォームが別々に存在しており、 (1)ログインフォームは  ・ログインID入力用のテキストボックスが一個  ・パスワード入力用のテキストボックスが一個  ・ログインボタンが1個  設置されています。 以下はログインボタンクリック時に動作するプログラムです。 Private Sub cmdLogIn_Click() Dim Res If IsNull(Me.txtID) Then MsgBox "IDを入力してください" Me.txtID.SetFocus Exit Sub End If If IsNull(Me.txtPass) Then MsgBox "パスワードを入力してください" Me.txtPass.SetFocus Exit Sub End If Res = DLookup("パスワード", "T顧客", _ "顧客ID='" & Replace(Me.txtID, "'", "''") & "'") If IsNull(Res) Then MsgBox "該当するIDはありません。正しいIDを入力してください。" Me.txtID.SetFocus Exit Sub End If If Res = Me.txtPass Then DoCmd.OpenForm "注文フォーム" '----ID,pass合致でフォームを開く。 Me.txtID = Me.txtID2 Me.txtPass = Me.txtPass2 DoCmd.Close acForm, "Fログイン" Else MsgBox "パスワードが異なります。", vbOKOnly + vbCritical Me.txtPass.SetFocus End If End Sub (2)トップフォームは  商品のリストが画像付き(商品一個につき画像一個)  で示され、画像を押すと商品別に作成してある注文フォームに進むのですが、  ログイン完了していないとログインを促すメッセージが出て注文フォームが開かないよう  にしています。  トップフォームにはテキストボックスを2個不可視の状態で配置しております。  以下は商品画像に埋め込んであるコマンドです。 Private Sub 商品画像 1_Click() Dim Res If IsNull(Me.txtID) Then MsgBox "ログインしてください" Exit Sub End If If IsNull(Me.txtPass) Then MsgBox "ログインしてください" Exit Sub End If If Res = Me.txtPass Then DoCmd.OpenForm "商品名" '----ID,pass合致で注文フォームを開く。 End If End Sub   (3)注文フォームは  ・数量選択のコントロールボックス  ・注文ボタン  ・キャンセルボタン  を設置しています。 【以下が質問内容になります】 「ロフインフォーム」内の入力値(テキストボックスに入力されていたIDやパスワード値)を注文フォーム内のテキストボックスに取得させる(あるいは設定させる)にはどのようにすればよいのでしょうか? 注文フォームにはテキストボックス2個( ID入力用と Password入力用)を不可視で配置しています。こちらのテキストボックス2個については手動入力は行わず、注文フォームが開いた際にログイン時の ID, Paswordがテキストボックスの中に自動的に入力あるいは設定されるようにしたいのですが、どのようにすればよいかがわかりません。 因みにログイン ID,Passwordは複数セットあり、ユーザーがログイン完了後、注文フォームを閉じるまでの間は 同一のID, Paswordの内容を保持したいと考えています。 上記の中にID,Paswordを保持させるようなコードを入れることは可能でしょうか? 注文フォームを開く際のコードに何か入れることができるのではないかと考えていたの ですが、よい案が浮かびません。 他によいやり方などがあれば教えていただけますでしょうか? よろしくお願いします。

  • vbaで帳票フォームで開きたい アクセス

    vbaでフォームを開くときに 既定のビューを指定してるのですが 指定したとおりになりません。 Private Sub Form_Load() Me.DefaultView = 1 '帳票フォーム End Sub としてもデータシートビューで開かれてしまいます。 Private Sub Form_Load() Me.DefaultView = 1 '帳票フォーム MsgBox Me.DefaultView End Sub とすると、1が返るのに やっぱりデータシートビューになってしまいます。 なぜでしょうか? エラーにもなりません。

  • アクセスのフォームからレコード入力空欄回避のVBA

    アクセス初心者です。 帳票式フォームからテーブルへのレコード入力において、次のレコード入力ボタンで空欄を防止するためのVBAを作っていますが、うまく行きません。空欄があれば警告は出ますがそのままテーブルへ記録されてしまいます。 テーブルに記録されずに空欄が入力できるようにするにはどうすればよいのでしょうか? また、次を入力するときにフォームの製品名の内容だけ消えずに残したいのですが、そのプログラムについても教えていただきたいです。 なかなかうまく行かずに大変困っています。 どなたかVBAの達人の方、初心者にわかりやすくお教え下さい。 「入力内容を登録して次を入力」ボタンで作ったVBAは次の通りです。 つぎはぎなので、不要なプログラムもあるかもしれません。 Private Sub コマンド9次のレコードに_Click() On Error GoTo Err_コマンド9次のレコードに_Click DoCmd.GoToRecord , , acNext Exit_コマンド9次のレコードに_Click: Exit Sub Dim Rst As DAO.Recordset Set Rst = CurrentDb.OpenRecordset("T_指定材料表", dbOpenTable) With Rst .AddNew .Fields("製品名") = Me!製品名 .Fields("回路記号") = Me!回路記号 .Fields("部品名") = Me!部品名 .Fields("員数") = Me!員数 .Update If IsNull(Me!製品名) Then MsgBox ("製品名が空欄です。") Resume Exit_コマンド9次のレコードに_Click End If If IsNull(Me!回路記号) Then MsgBox ("回路記号が空欄です。") Resume Exit_コマンド9次のレコードに_Click End If If IsNull(Me!部品名) Then MsgBox ("部品名が空欄です。") Resume Exit_コマンド9次のレコードに_Click End If If IsNull(Me!員数) Then MsgBox ("員数が空欄です。") Resume Exit_コマンド9次のレコードに_Click End If End With On Error Resume Next DoCmd.GoToRecord DataForm, "T_指定材料表", acNew Rst.Close Set Rst = Nothing Call ClearControls End Sub

  • accessフォームチェックボックス→トルグ文字

    (access 2003) (メインとサブがあり、メインフォームです。) フォームのチェックボックス(yes/no型)をコントロールの種類変更よりトルグボタンに変更し、 トルグボタンで入力しています。 yesなら、「仮」 noなら「普通」としたいと思い、下記の式を試して見ましたが、下記のようになります。 ページ移動ごとに凸凹は変わるのですが、トルグボタンに表記させている文字が「仮」から変わりません。 ボタンを押した時だけ「普通」に変わるのですが、ページを移動すると今度は「普通」ばかりの表記になってしまいます。 よろしくお願い致します。 Private Sub T2伝票仮_AfterUpdate() If Me![T2伝票仮].Value = True Then Me![T2伝票仮].Caption = "仮" Me![T2伝票仮].ForeColor = 255 Else Me![T2伝票仮].Caption = "普通" Me![T2伝票仮].ForeColor = 16711680 End If End Sub

  • Access 97 VBAについて

    Access VBAについて教えてください。 初心者ですが、レポートに表示されるテキストボックスの”項目名”と”内容”プロパティーに重複データ非表示にしています。そして、非表示となった部分に”〃”を表示するため別のテキストボックス、”隠しオブジェクト1”及び”隠しオブジェクト2”を配置しています。???にどんな記述が必要かわかりません。”項目名”だけであれば問題なく表示されるのですが”内容”についても同様に処理したいのです。 どうぞ宜しくお願いいたします。 Option Compare Database Option Explicit '値を保持するために外側に変数を定義します。 Dim varA As Variant --------------------------------------------------- Private Sub 詳細_Print(Cancel As Integer, PrintCount As Integer)   If Me.項目名 = varA Then    Me.隠しオブジェクト1.Visible = True Else Me.隠しオブジェクト1.Visible = False End If varA = Me.項目名 ???? If Me.内容 = varA Then Me.隠しオブジェクト2.Visible = True Else Me.隠しオブジェクト2.Visible = False End If varA = Me.内容 End Sub

専門家に質問してみよう