いつもお世話になっております。
hatenaさん、りんごさん、
数週間前に「テーブル変更後、読み込まなくなりました」というタイトルで
相談に乗って頂きありがとうございました。
その際、基本を学ぶようアドバイスを頂き、一から作り直すことも考えたのですが
仕事の都合、今回のシステムで運用をすることになりそうです。
勤務先の基幹システムとリンクを貼る際に、色々と難関がありましたが、
なんとか完成に辿り着けそうです。お二人のおかげです!
さて、今回もVBAの相談です。
(基本を学ぶようアドバイス頂いているのにスミマセン😅)
題記のエラーが発生しています。
以前、こちらで同じような相談をしたばかりなのですが
ご教授ください!
今回も本を参考に打ち込んだつもりなのですが、、、。
Private Sub btn追加_Click()
If IsNull(Me.cmb依頼者.Value) Or IsNull(Me.cmb希望処置.Value) _
Or IsNull(Me.txtW_No.Value) Then
MsgBox "必要項目が入力されていません", vbInformation, "確認"
Exit Sub
End If
Dim sqlList As Collection
Set sqlList = New Collection
Dim strSQL As String
strSQL = _
"INSERT INTO T_依頼 ([依頼日], [依頼者], [W_No], [W_Noロット], [品名], [希望処置], [補足説明]) " & _
"VALUES(" & _
"#" & Me.txt依頼日.Value & "#, " & _
"'" & Me.cmb依頼者.Value & "', " & _
"'" & Me.txtW_No.Value & "', " & _
"'" & Me.txtW_Noロット.Value & "', " & _
"'" & Me.txt品名.Value & "', " & _
"'" & Me.cmb希望処置.Value & "', " & _
"'" & Me.txt補足説明.Value & "');"
sqlList.Add strSQL
Dim errMsg As String
errMsg = tryExecute(sqlList)
If errMsg <> "" Then
MsgBox errMsg, vbCritical, "エラー"
Exit Sub
End If
Set sqlList = New Collection
Me.txt依頼ID.Value = DMax("依頼ID", "T_依頼")
Dim i As Long
For i = 1 To 10
If Not IsNull(Me("cmb1依頼理由" & i).Value) Then
strSQL = _
"INSERT INTO T_依頼詳細([依頼ID], [ロット番号], [ロット枝], [依頼理由_1], [依頼理由_2], [依頼理由_3], [詳細補足説明], [最終更新日]) " & _
"VALUES(" & _
Me.txt依頼ID.Value & ", " & _
"'" & Me("txtロット番号" & i).Value & "', " & _
Me("cmbロット枝" & i).Value & ", " & _
Me("cmb1依頼理由" & i).Value & ", " & _
Me("cmb2依頼理由" & i).Value & ", " & _
Me("cmb3依頼理由" & i).Value & ", " & _
Me("txt巻き長さ" & i).Value & ", " & _
Me("txt詳細補足説明" & i).Value & ");"
sqlList.Add strSQL
End If
Next i
errMsg = tryExecute(sqlList)
If errMsg <> "" Then
MsgBox errMsg, vbCritical, "エラー"
Exit Sub
End If
Call loadForm
MsgBox "追加しました", vbInformation, "完了"
End Sub
そのエラーが出たとき、デバッグボタンを押すと、どの行がハイライトされますか。
あと、tryExecute という関数はないので、ユーザー定義関数と思いますが、そのコードも提示してください。
hatenaさん、お世話になります。
ハイライトされなくて困っております。
下記がtryExecuteになります。
よろしくお願いします。
SQL実行時のエラーメッセージなので実際に実行されるSQL文を確認しましょう
Excel VBA 入門講座 - イミディエイトウィンドウ(pc-users.netさん)
ありがちなのは入力チェック漏れでNULLが指定されてて
VALUES(1234,,'ABC')
みたいな文になってるとかですね後半のSQL文ですが
'
特に最後の2項目、間違っていませんか?
ついでにエラーについて
このコードではプログラムが中断されるようなエラーは発生していません。記述通りに動作して、
MsgBox errMsg, vbCritical, "エラー"
の文が実行されメッセージボックスが表示されているだけです。当然「デバッグ」ボタンも表示されませんし、ハイライト表示もできません「そのようにプログラミングされている」ことを理解する必要があるでしょう
On Error GoTo ErrorHandler
でエラー処理しているので、エラー場所はわからなくなります。
デバッグするときは、この行はコメントアウトしてから、実行するとエラー箇所がハイライトされるはずです。
おそらく、
daoDb.Execute strSQL
がハイライトされるはずです。
ここで、strSQLに格納されているSQL文が間違っているのではと推測できます。
あとは、hirotonさんのご指摘を確認してみてください。
hirotonさん、
ありがとうございます!
後半のSQL文、最後の2項目
確かに間違っていました。
まずはSQL文自体を理解していないと
今回の間違いは見つけられないと
思います。発見まで暫く時間帯が
掛かりそうです😅
hatenaさん、
コメントアウトしたら、見事に
ハイライトされました。
先程も書きましたが
やはりSQL文を勉強をしないと
お二人から折角アドバイスを受けても
噛み砕けないままになってしまい
そうです。
もう少し勉強したのち、
今回のものを見直してみます!
ありがとうございました!
VBA内でのSQL文、めんどくさいですよね。
& でつなげなければいけない
データ型によって、
#
や'
で囲まなければならない未入力だったばあい Null に変換したりする必要がある
など・・・
最初のSQLの場合は、1件のレコードを追加するだけですので、自分なら、
recordset.AddNew
を使いますね。そうすると下記のようなコードですみます。
どうでしょうか。こちらの方がはるかにシンプルで読みやすいと思いませんか。
さらに、テキストボックス名をフィールド名と同じにしておけば、下記のようにいちいちフィールド名やテキストボックス名を記述する必要もなくなります。
2つめのSQL文は下記のようになります。
テキストボックス名は、
フィールド名の後に1~10の数字を付加したものにしておいて、
hatenaさん
ご丁寧な解説、本当に助かります!
前回相談にのって頂いたdbも、最初このSQLで躓き
別の本に載っていた「recordset.AddNew」で試したところ、
上手くいったので、もしや?と思っておりましたが
その“もしや”をご提案いただき、やっぱり!となりました。
さて、早速実践してみましたが、エラーです。
実行時エラー’2465’:
指定した式で参照されている’L0000002'フィールドが見つかりません。
下の文がデバックで黄色になります。
fld.Value = Me(依頼ID).Value
間違っていますね・・・😅
今現在、下記内容になっております
fld.Value = Now は無視してください。
下記の部分でエラーということですね。
前回の回答で、
一つずつ、フィールドに対応するテキストボックスの値を代入する方法と、
フィールド名とテキストボックスを同じにしておいて、いちいち指定せずにループで代入しておく方法、
の2つを提案したのですが、それを混ぜ和せてしまっては正常に動きません。
前者の方法でいくなら、上記のコードは、下記のようになります。(フィールド名とテキストボックス名は同じにしてあるという前提です)
後者の方法なら、下記のコードになります。
入力しないフィールドがある場合 "フィールド1,フィールド2" とカンマ区切りで指定してください。
全てのフィールドに入力するならIf文は不要です。
すっきりして見やすいですねぇなんて思いながら見てましたが、
OpenRecordset
にはSQL文も指定できるのでハイブリッドでやるのもいいかなぁと思いました不要な分を弾く処理よりは必要分を記述していくほうが分かりやすいかと
単純なSELECT文なので間違いも起きにくいですし
それから、エイリアス使ってひねってやるとフィールド名とコントロール名が別でも良かったりしますね
フォームに配置できないフィールド名(詳細)とかはこの手法で
質問だと後半のINSERTは「依頼ID」が共通で最大10レコード登録な処理ですかね(追記内容だと「依頼ID」にも
i
がついているので真実は不明)これの時は、別入力処理も使っていくことになりそうです
更新日時のような計算で求めるものも外に出して個別に処理ですかねぇ
Like
判定は誤動作しそうで怖い。完全一致で判定(Select Case
で列挙するとか)したくなりますお二方、ありがとうございます!
まずは、hatenaさん。
ご提案の文を使わせていただいたところ、T_依頼にはレコードが入りますが、
子レコード側を入力したのち、追加ボタンを押すと
実行時エラー’3022’インデックス、主キー、またはリレーションで重複する値が、、、
が表示され、下記がエラーとなりました。
よろしくお願いします!
hirotonさん
ご提案の文を使わせて頂きました。
“コンパイルエラー 変数が定義されていません。”
初歩的な質問で、大変恐縮ですが
間違えを指摘していただけますか?
コンパイルエラーなのでコンパイルをしてみましょう
エラーの場所が反転してわかると思います
回答はコード案の一部を記載したものなので、前後の処理や必要な変数宣言は別途記述する必要があります。変数の使いまわしもしてるので記述を整理する必要もあるでしょう
プロシージャをすべて記述するなら
「更新日時」フィールドは例示のための記述なので削除しました
T_依頼 の主キーフィールドはなんでしょうか。
エラーメッセージのとおりだと思いますので、主キーフィールドの値が重複していないか、確認してみてください。
hirotonさん、ありがとうございます。
再度挑戦しました。
すると「パラメーターが少なすぎます。9を指定してください。」です。
hatenaさん、ありがとうございます。
実行時エラー’3022’は、同じ主キーで一生懸命、登録を試みてました😅
スミマセン😅😅
で、再度挑戦しました。
すると「バリアント型ではない変数にNull値を代入しようとしました」です。
親テーブル「T_依頼」
子テーブル「T_依頼詳細」
パラメーターエラーは、念の為、SQL文の不備から見直してみるのはどうでしょう?
Null値代入エラーは、取り敢えず、For Each〜Nextを使わないコードに戻してみるのはどうでしょう?
これで解決しない、もしくは、新しいエラーが出た場合は、For i = 1 To 10 〜Nextを使わないコードに戻してみるのはどうでしょう?
それでも駄目なら、兎にも角にも、まずは、繰り返し処理を使わないコードを泥臭く書かないと色々難しいでしょう。
最後に、今回のシステムに関して質問を続ける場合や別のシステムに関して質問をする場合、リレーションシップの画面をスクリーンショットして提示して下さい。リレーションシップが設定されていない場合、質問する意味がありませんので、これが大事です。
上記のコード、私が前に指摘した、
一つずつ、フィールドに対応するテキストボックスの値を代入する方法と、
フィールド名とテキストボックスを同じにしておいて、いちいち指定せずにループで代入しておく方法、
が、ごちゃまぜになってます。
一つずつ、フィールドに対応するテキストボックスの値を代入する方法に書き換えましょう。
後者の方法はまだちょっと敷居が高いようです。
そのうえでエラーが出たら、エラーメッセージとどの行でエラーが出たか提示してください。
hatenaさん、
ありがとうございました!
上手くいきました👍
hirotonさん、
ありがとうございます!
りんごさん、
ご指摘ありがとうございます!
今後はリレーションなど、詳細も提示しつつ
質問するようにします。
今回は仕事の都合、時間もないので
hatenaさんのご提案のやり方で進めてみます。
皆さま、ご協力有り難うございました。
SQLはいまの私には難易度高いですね💦
勉強します!
最低限の保証を確認しておかないと危険です。これまでのチグハグな様子を見ていると、このシステムは最初から全部壊れている可能性が高いと、容易に予想出来ます。立ち止まって、再考するのはどうでしょう?努力と時間はもっと大切に。