プロが教えるわが家の防犯対策術!

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で表示だけされるようにしています。

A 回答 (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での入力の制御は、実に色んな問題を孕んでいます。
肝心なのは、終始一貫したルールを全ての入力フォームに適用することです。
質問者は、その探求の入り口に立ったばかり。
頑張って下さい。
    • good
    • 0
この回答へのお礼

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

お礼日時:2008/02/12 21:15

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

この回答への補足

ご回答ありがとうございます。
そのまま貼り付けてみたのですがなぜか何もおこりません。
勉強不足で大変申し訳ないのですが
KR = Dblookup("管理","商品マスタ","[商品コード]=" & Me.商品コード)
の部分の解説をしていただけると助かります。
入力した商品コードを元に"商品マスタ"の"管理"を見る?ということでしょうか。

あとPrivate Sub 詳細_AfterUpdate()とは
新しいレコードに移る前にメッセージboxが表示されるようになるということでしょうか。
詳細プロパティのイベントタブでみることはできますか?

本当に初心者な質問な上、質問の内容もよくわからなくて申し訳ありません。

補足日時:2008/02/10 01:40
    • good
    • 0

すいませんNo2で回答したものです。



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

管理が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
    • good
    • 0
この回答へのお礼

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

お礼日時:2008/02/10 00:43

商品マスター:



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、入力フォームを閉じた時に、不具合レコードをチェックし警告・削除することです。

上述のような警告システムはユーザの自在な入力を阻害するだけです。
    • good
    • 0
この回答へのお礼

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

お礼日時:2008/02/10 00:20

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています