Private Sub btn_検索_Click()
Dim StartDueDate As String
Dim EndDueDate As String
StartDueDate = Trim(Nz(Me.txb_納期検索1.Value, ""))
EndDueDate = Trim(Nz(Me.txb_納期検索2.Value, ""))
If StartDueDate & EndDueDate = "" Then
MsgBox "納期期限の開始日または終了日を入力してください。"
Me.txb_納期検索1.SetFocus
Exit Sub
End If
If Not IsDate(Format("20" & StartDueDate, "0000/00/00")) Then
MsgBox "日付としてありえない値です。yymmddの書式で日付を入力してください。"
Me.txb_納期検索1.SetFocus
Exit Sub
End If
If Not IsDate(Format("20" & EndDueDate, "0000/00/00")) Then
MsgBox "日付としてありえない値です。yymmddの書式で日付を入力してください。"
Me.txb_納期検索1.SetFocus
Exit Sub
End If
Me.Refresh
Dim strFilter As String
If StartDueDate <> "" Then
strFilter = " And [納期] >='" & StartDueDate & "'"
End If
If EndDueDate <> "" Then
strFilter = strFilter & " And [納期] <='" & EndDueDate & "'"
End If
Me.Filter = Mid(strFilter, 6)
Me.FilterOn = (strFilter <> "")
Me.btn_解除.SetFocus
End Sub
StartDueDate = Trim(Nz([txb_納期検索1], ""))
If StartDueDate Like "######" Then
If Not IsDate(Format("20" & StartDueDate, "0000/00/00")) Then
MsgBox "日付としてありえない値です。yymmddの書式で日付を入力してください。"
txb_納期検索1.SetFocus
Exit Sub
End If
Else
MsgBox "数字6桁で入力してください。"
txb_納期検索1.SetFocus
Exit Sub
End If
'EndDueDate も同様にチェック
StartDueDate = Trim(Nz([txb_納期検索1], ""))
If Not IsDate(Format("20" & StartDueDate, "0000/00/00")) Then
MsgBox "日付としてありえない値です。yymmddの書式で日付を入力してください。"
txb_納期検索1.SetFocus
Exit Sub
End If
proKey1はスコープが異なるのでKeyCodeという「名前」はproKey1の中で自由に(新たに)使えます。解説目的(質問への回答目的ではない)でcと表記していますが、普通に組んだらPrivate Sub proKey1(KeyCode As Integer)とする(そうなるよう記述する)と思います
プロシージャ内で宣言された変数(引数も含む)は、そのプロシージャ内でのみ有効、つまり他からは参照できないです。
スコープは Sub から End Sub までの範囲です。
つまり、コンボ_KeyDown内で宣言された変数(引数も含む)と、proKey1内で宣言された変数(引数も含む)ではスコープが異なるので、同じ変数名でも問題ないです。もちろん違っても問題ないです。
数字だけのフィールド、数字で始まるフィールド名以外にも、スペースを含むフィールド名、予約語のフィールド名、特殊記号を含むフィールド名などを使うとエラーになります。
Access データベースで特殊文字を使用したエラー - Microsoft 365 Apps | Microsoft Learn
そのような名前を使わないようにするのが原則ですが、どうしても使わなければならないときは、
[
]
で囲むと使用できます。質問したばかりで申し訳ないです。
全角数字は禁止と認識していましたが、数字だけ、もしくはフィールド名の先頭に数字を使ってもエラーになるみたいでした。
多少面倒ですが、先頭にアルファベット1文字加ええることで、回避できました。
ならば[F_在庫品作成依頼]が連結フォームである必要はないのではないでしょうか。
いわゆる CRUD 機能を Access の非連結フォームに実装する場合、
「新規レコードの追加」を行う手法については、大別して次の 3 種類の方法が挙げられます。
保存済みの追加クエリを実行するマクロまたはプロシージャを呼び出す。
任意の SQL 文(この場合は INSERT INTO ... ステートメント)を実行するマクロまたはプロシージャを呼び出す。
DAO または ADO の Recordset オブジェクトによって任意のテーブルを参照し、AddNew メソッドを呼び出して新規レコードを作成し、そのレコードの各フィールドの値を編集し、Update メソッドを呼び出してそのレコードをテーブルに保存する――という一連の操作を実行するプロシージャを呼び出す。
挙げられた方法は上記 1 に該当します。
ごくありふれた操作なのですね。初めてだったので安心しました。
txb_品名コード、txb_現在庫数ともに非連結のテキストボックスです。
フォームのレコードソースをクエリを元にしたテーブルにして、クエリのデータを追加して、フォームでのデータ編集後に
更新クエリで書き戻すのはいかがでしょうか?
直接編集はリスクが大きい気がします。
ここで問題となるのは、[txb_品名コード]と[txb_現在庫数]が
連結テキストボックスであるか、それとも非連結テキストボックスであるか、
ということです。
[txb_品名コード]のコントロールソースがテーブル[00作成]のフィールド[品番]、
[txb_現在庫数]のコントロールソースがテーブル[00作成]のフィールド[現在庫数]
であるならば、それらのテキストボックスに対して値を入力する操作は
そのままコントロールソースであるフィールドに対しての入力となります。
その際のフォームのカレントレコードが新規レコードなのであれば、
カレントレコードが保存された段階でそのレコードはテーブル[00作成]に
追加されます。
カレントレコードが既存のレコードなのであれば、参照中のレコードが
更新(上書き)されます。
「連結フォームのカレントレコードに対する入力操作」によって
テーブル[00作成]のレコードの追加/更新が成されているのであれば、
それとは別に(独自に)「追加クエリを用いたレコードの追加」という操作を
実行する必要はありません。
後者の操作を行う必要があるとすれば、それは[F_在庫品作成依頼]が
非連結フォーム(どのテーブルとも連結していない)である場合か、
「連結フォームのカレントレコードに対する入力操作」とは別に
何か特殊なレコードの追加処理を実行しなければならないような場合
ぐらいでしょう。
「各フィールドに出力する値(リテラルや式の結果)をリストで指定して
任意のテーブルに 1 件のレコードを追加する操作」という自体は、
データベースシステムにおいてごくありふれた操作です。
多くの場合は INSERT INTO ... VALUES ... ステートメントを使用します。
Access の場合は SQL ビューでこのステートメントを用いた追加クエリを
作成することができますが、デザインビューに切り替えてクエリを上書き保存すると
INSERT INTO ... SELECT ... ステートメントに置き換わってしまいます。
別スレを見ていて思ったのですが、テーブル構造(主キーなど)の提示、フォームのスクリーンショットの提示が必要ではないかしら?
フォーカスを移動させて値が保存されたらデータシートビューで値が表示される、という認識でしたので、移動させても値が表示されないのはおかしいなあと思って質問させて頂いた次第です。実行するとちゃんと在庫数に入力した数が追加されているので問題はないのですが。原因が気になったもので。。
とりあえず動いているのでよしとします、お手数をお掛け致しました。
フォーカスを移動させてからクエリーを開いても表示されませんか?
ちょっと原因は分からないのですが、実行したら値がきちんと入るのなら問題はないのでは?
はい、デザインビューからデータシートビューに切り替えた際、値が表示されませんでした。
はい、当該のフォームは開いた状態で、txb_現在庫数から他のボタンへフォーカスを移動させてみても、データシートビューに値が出ませんでした。
早速のご回答、ありがとうございます。
ちょっとレコード数が多いのですが、まずは試しに設定してみます。
ありがとうございました。
デザインビューからデータシートビューを表示させる操作をしたということですか。
そのとき、
式1: [Forms]![F_受注品作成依頼]![txb_現在庫数]
と設定したフィールドに値が表示されていないということですが。上記の認識で間違いないなら下記のことを確認してください。
その時に、「F_受注品作成依頼」フォームは開いている状態ですか。
また、「txb_現在庫数」に入力したあと、Enterキー(Tabキー)を押下する、あるいは他のコントロールをクリックするなどして、フォーカス移動をしてますか。
はい、ボタンを押すと、入力項目が不足していないか等のif文を通り、問題なければElseに分岐してDocmdでクエリが実行されます。
クエリはQ_作成手配分追加のことです。
このクエリが正しく作れているかの確認のため、クエリのデータシートビューを見たところ、フォーム上ではテキストボックスに値が正しく入っている(仮に「1000」と入力していたとします)が、データシートビューでは値が入っていませんでした。その状態でクエリを実行すると、きちんとT_作成の現在庫数フィールドに値(1000)が入っています。
「btn_作成手配」ボタンのクリック時で"Q_作成手配分追加"クエリを実行するようになっているということですか。
このクエリは"Q_作成手配分追加"のことですか。
このクエリをデザインビュー(あるいはSQLビュー)で開いてから、データシートビューで表示させるという操作をしているとうことですか。
クエリをデータシートビューで見るとこれから追加する値が表示されると思うのですが、それの現在庫数フィールドの値が表示されない、ということです。
「値がクエリに表示されない」というのが良く分かりません。
「txb_現在庫数"(非連結)」に反映されない、というのであれば分かるのですが。
もし上記が正の場合、画面をリフレッシュすればいいのではないでしょうか(違っていたらすみません)
部品の合計金額をDSum関数で取得すればいいでしょう。
クエリのフィールドに
テーブル名、フィールド名は実際のものに変更してください。
また、リンクフィールド(製品ID)はテキスト型の場合です。
すみません自己解決してしまいました。
objExcel.workbooks.Openでアドインファイルを開いて、その後該当ファイルを開くとうまくいきました。
ありがとうございました。
ちなみに、自分がするなら、
テキストボックスの定型入力プロパティに
000000;;_
と設定しておいて下記のコードにします。
回答ありがとうございます!
意図しない入力を防ぐ仕組みも必要ということですね。
ということなら、下記のような感じで入力チェックするといいかと思います。
そうしないと、正しくない値が入力されたときに、抽出結果も正しいものになりません。
あるいは、テキストボックスの定型入力プロパティに
000000;;_
と設定しておくと数字6桁の入力が強制されますので、日付チェックのみで済みます。
なるほど、想定していない(この場合だと6桁以外の数字)入力内容だった場合にエラーを回避するための処理ということですね。勉強になります。
Hatenaさん、お手数をおかけしてしまい申し訳ありません。
ありがとうございます。
反応がないようなので、管理者権限で削除しておきました。
それぞれの非連結テキストボックスの値の中に含まれている
シングルクォーテーション( ' )を Replace 関数によって
'' に置換し、更に囲み記号としての ' で囲って 1 つの
文字列リテラルとして解釈されるようにしています。
前述の例ではフィルター条件式における文字列リテラルの囲み記号として
シングルクォーテーションを用いていますが、その場合において
「文字列としてのシングルクォーテーション」を文字列リテラルに含めるには
'' のように 2 つ続けて記述しなければなりません。
それぞれの非連結テキストボックスにシングルクォーテーションを含む文字列が
入力された場合、上記のようにエスケープ処理をしておかないと
「文字列としての ' 」ではなく「文字列リテラルの囲み記号の ' 」として
解釈されてしまい、構文エラーが発生する可能性が高くなります。
skさん、回答ありがとうございます。
思う通りに動作するようになりました。
これはどのような操作なのでしょうか?
リアクションでは何を伝えたいのか分かりませんので文章にしていただきますようよろしくお願い致します。
客先から受け取るCSVデータをインポートすると短いテキスト型になっており、値も"240311”の6桁です。
では、とりあえず以下のように修正してみて下さい。
納期のデータ型は短いテキスト型です。
まずフィールド[納期]のデータ型を明記されることをお奨めします。
明日勉強して頑張ってみようと思ってましたが、回答していただけてました! ありがとうございます。
これ絶対ADOを使う案件だと思ってました。
いつものことながら、ありがとうございます。
hirotonさん・hatenaさん ありがとうございました。納得しました。参照渡しでしておいたら同じ名前でも違う名前でも共有できるのですね。スコープとは関係のない事でしたね。
こつこつ勉強していきます。
質問内容の経緯から、適切な宣言と、それに従った運用が必要であると示すためです
以下、要点を挙げてみると
(参照渡しの)引数によって、スコープを跨いで同じデータを扱うこと。
プロシージャを作ると、新たなスコープが作られること。
異なるスコープでは、そのスコープで使える名前を正しく把握する必要があること。
proKey1
で名前だけ同じKeyCode
を記述しても、それはコンボ_KeyDown
のKeyCode
ではないということですね。(そうなるよう記述しなければ)proKey1
はスコープが異なるのでKeyCode
という「名前」はproKey1
の中で自由に(新たに)使えます。解説目的(質問への回答目的ではない)でc
と表記していますが、普通に組んだらPrivate Sub proKey1(KeyCode As Integer)
とする(そうなるよう記述する)と思いますフォームが連結フォームなら、この方法でいいですね。
ADDやらDAO、SQLを使う必要はまたっくないです。
フォームを開いたときに、テーブルもレコードセットとして開かれているので。
プロシージャ内で宣言された変数(引数も含む)は、そのプロシージャ内でのみ有効、つまり他からは参照できないです。
スコープは Sub から End Sub までの範囲です。
つまり、コンボ_KeyDown内で宣言された変数(引数も含む)と、proKey1内で宣言された変数(引数も含む)ではスコープが異なるので、同じ変数名でも問題ないです。もちろん違っても問題ないです。
同じ名前を使うか、異なる名前にするかは、プログラマーの好みだと思います。
私は、参照渡しの場合は、同じものを共有することになるので、同じ名前にしておくことが多いです。
hirotonさん・hatenaさん 丁寧な解説ありがとうございます。大変参考になります。まだまださわりしか理解してませんが自分なりにイメージしました。今回の流れはおおざっぱには下記でしょうか?(間違いならすみません)
1:コンボキーダウン時に(プロシージャ)proKey1を呼び出し押されたキー内容を(変数)KeyCodeに入れてproKey1に引数として渡す
2:proKey1はKeyCodeを受取りそれは共有できている引数Cとして条件分岐をする
3:2の結果をコンボキーダウン時に返す。
hirotonさんのproKey1の引数CとしてKeyCodeと共有させているのはスコープ(範囲)対策でKeyCodeという変数を使わない様にするためでしょうか?(この解釈も間違いならすみません)
ACCESSの便利さが好きで自分で色々制御できるといいなと思い勉強中です。少しづつの理解しか出来ませんが頂いた回答はネットや本には載ってないような達人の生の意見は本当に貴重に思ってます。
アレです。正直何も分からないままやってしまってもいいんじゃないかなって内容なんですよね。デフォルトがByRefだからとかそういうのも
VBAの使い始めなんかそのくらい適当でいいと思っているので
エラーが出ないのが不思議だと何回か指摘していますが、「なんでもかんでも
On Error~
していてうまくいっていないのにどこが原因か分からない」と同じ匂いを感じるんですよね。普通にやっていればそもそも動かないってこけているはずなのでhiroton自身も特別なとは言っていますが、イベントプロシージャの引数は別に他のプロシージャと比較して特別なモノでもないんじゃないですかね。それこそ「記述を省略した参照渡し」なので
大元の参照元(コントロールのイベント実行)から呼び出されるにあたって、「参照渡し」で引数を定義しているので、このプロシージャ内で操作した結果は元になるイベントの情報をそのまま書き換えている。と、それだけかと
大元の参照元が隠されているというだけで、プロシージャとしての動きは特別なモノでもないと思います
もうちょっと具体的に説明できたほうがいいと思いますが
ってことですかね