• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:複数フィールドへ時間帯別のデータ入力)

複数フィールドへ時間帯別のデータ入力

このQ&Aのポイント
  • 複数のフィールドに、複数行のデータを反映させる方法について質問します。
  • 現在は動作しているが、より効率的な方法があれば教えてほしい。
  • フォームの入力フィールドに受付日、受付時間、キュウリ、トマト、ナスのデータがあり、登録ボタンをクリックすると、データがT_MAINに反映されます。どのようにしたら複数行のデータを一度に反映させることができるでしょうか。

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

  • ベストアンサー
  • DexMachina
  • ベストアンサー率73% (1287/1744)
回答No.2

No.1です。 一応、こちらで簡単なテストをした結果では、テキストボックスに 「1*」や「^1」といったデータが入力され、かつ、その値を「'」で 括らなかった場合に、同じエラーが発生することを確認しました。 ・・・すみません、こちらこそ言葉足らずだったかもしれません(汗) 前回、コード上のコメントとして『実際のデータ型が不明のため、 値は一律で「'」で括っています』と記しましたが、実はこれは、   「とりあえず文字列の場合を例示した」のではなくて、   「数値型でも日付型でも動作するようにした」 つもりでした。 (例えば数値型のフィールドに対して、SQL文などで「数値に  みなし得る文字列」を設定しようとした場合、文字列として  弾かれるのではなく、数値に読み替えられて設定されます) つまり、追加先のフィールドが「文字列・数値・日付/時刻」の いづれの型であっても、「'」で括った形のSQL文で動作する、 ということです。 (本当は、DAOのTableDefオブジェクトやFieldオブジェクトを  使用して、データ型に合わせて「'」の有無を切り替える方が  推奨されるのですが、前回回答は手を抜いている、と(汗)) ※『実データが提示サンプルのように全て数値なら、「'」は不要』  というのが頭にあってのコメントでした。 ただ、仮に「'」で括ったとしても、上記の「1*」等のようなデータを 数値型フィールドに入れようとすると、   値要求ありなら「すべてのレコードを追加できません」のエラー   値要求なしの場合はフィールドの値が「Null」での追加 という結果になってしまい、根本的な解決にはなりません(汗) 実際のエラーメッセージは   「クエリ式 '○○' の 構文エラー : 演算子がありません」 といった形になるようなので、まずはこの「○○」にあたる部分に ついて、生成されたSQL文の見直しが必要かと思います。 (テキストボックスへの入力値が、フィールドのデータ型に沿って  いるか、「cFields」として記述した内容に間違いがないか、等) ちなみに、VBA上で組んだSQL文でエラーが発生した場合に、私が よく採る確認手段がありますので、参考までにご紹介します: 1)「DoCmd.RunSQL sSQL」の前に以下の一行を追加  Debug.Print sSQL 2)フォームに記述した処理を実行し、エラーを発生させる 3)そのまま処理を終了させた後、Ctrlキー+Gキーの同時押しで  『イミディエイト ウィンドウ』を表示させる 4)エラー発生時のSQL文が、同ウィンドウの一番下に表示されて  いるので、それをコピー  (VBAの定数vbCrLfを使用してSQL文に改行を入れている場合、  複数行に亘ることになるので注意) 5)新規クエリをデザインビューで開く(テーブルの追加などはしない) 6)SQLビューに切り替え、「4」でコピーしたSQL文を貼り付け 7)リボン又はツールバーの実行ボタンなどから、このSQL文を実行 8)「2」で発生したのと同じエラーが出るので、Okボタンをクリック 9)エラーの種類によっては、SQL文の問題箇所を反転表示にして  くれるので、それをヒントにSQL文を見直し、VBA上の式に  反映させる ・・・以上です。 長文、失礼致しました(汗)

usas
質問者

お礼

お忙しい中、たびたびご回答いただき ありがとうございます。 ご指示いただいた方法に従い、エラー発声後『イミディエイト ウィンドウ』で 詳細を確認してみましたところ、下記のように表示されました。 Insert Into T_MAIN ([受付日],[受付時間],[キュウリ],[トマト],[ナス]) Values('130130','9','','1',''); Insert Into T_MAIN ([受付日],[受付時間],[キュウリ],[トマト],[ナス]) Values(130130','9','','1','','130130','10','','7',''); valuesする値の先頭にアポストロフィ「'」が抜けていることに気付き、 下記のように単純なコードを追加してみました。 '先頭の余分な「,」を削除 sFields = Mid(sFields, 2) '追加した分 If n >= 10 Then sFields = "'" & sFields End If 実行後、狙い通りにアポストロフィは追加され、今まで表示されていたエラー表示は なくなったたのですが…… Insert Into T_MAIN ([受付日],[受付時間],[キュウリ],[トマト],[ナス]) Values('130130','9','','1',''); Insert Into T_MAIN ([受付日],[受付時間],[キュウリ],[トマト],[ナス]) Values('130130','9','','1','','130130','10','','7',''); 二行目のValues実行時にエラーになっています。 「実行時エラー3346 クエリと値と出力するフィールドの数が一致しません。」 一行目のValues実行はテーブル登録されていますが、ご覧のとおり二行目はフォームとValuesのデータ数が 一致しないため登録不能となります。 For NextのStepで設定している分だけのデータを 二行目の先頭で削除しなければいけないことは、なんとなくわかるのですが…… 実際の運用で、登録文字数が定数になるとは限らないのため、バイト数でざっくり減らすという ことはできそうにありません。 また、現在は確認のため、9時台と10時台のみで実行していますが、 こちらも実際の運用では9時~21時までのデータを入力して実行するため、 別な解決方法が必要になりそうです。 お忙しいと思いますので、何か良い解決方法があれば、お時間あるときにでも ご回答いただければと存じます。 毎回、貴重なお時間を割いていただき、本当にありがとうございます。

usas
質問者

補足

いまさらですが…… 質問時に不足していた情報を下記に追記いたします。 Access:2003および2007 使用OS:WindowsXP、Vista、7 実際にテキストボックスへ入力されるデータは、 日付、時間 …… 日時 他、実運用では、担当者名がはいるため、テキストタイプで設定。 他は数値タイプで設定しています。

その他の回答 (1)

  • DexMachina
  • ベストアンサー率73% (1287/1744)
回答No.1

【要旨】 改善策としては  a)各フィールドを配列化して、ループ処理にする  b)作業テーブルを新規作成し、当該フォームのレコードソースとし、   正規テーブルへの登録はテーブル間でのInsertにする の2つの方法が考えられます。 【詳細】 提示されているコードにはレコード移動が含まれていないことからすると、 非連結フォームに非連結テキストボックスを配置している、ということで よろしいでしょうか。 (非連結: 『レコードソース』(→フォームの場合)、『コントロールソース』  (→コントロールの場合)プロパティの値が、それぞれ空白のもの) この場合は、やはりValuesを使用したSQL文で対応するのが妥当かと 思います。 (DAOまたはADOのRecordsetにAddNewで追加として、各レコードの  追加時に値の妥当性や競合有無の確認、という方法もありますが、  「複数レコード分を一度に追加」という形を採っていることを考えると、  「個別の追加時」よりは「事前」のチェックで対応するべきだろう、と) ただ、現状ではレコード毎にコードを用意されているようですので、冒頭 「a」で示したように、ループ処理化するという改善策が考えられます。   Dim vFields As Variant, sFields As String   Dim n As Long, m As Long, sSQL As String   Const cFields As String = "テキスト1 テキスト2 テキスト3 ・・・"   '→「・・・」部には、実際のテキストボックス名をSpace区切りで羅列   'cFieldsの各要素を配列化   vFields = Split(cFields)   'レコード毎のループ(「Step 5」は、1レコード当たり5フィールドのため)   For n = LBound(vFields) To UBound(vFields) Step 5     '「テキスト1,テキスト2・・・」部分の作成     '(コントロール名ではなくそこの値が必要なため、Me.Controlsを使用。     ' 実際のデータ型が不明のため、値は一律で「'」で括っています)     For m = 0 To 4       sFields = sFields & ",'" & Me.Controls(vFields(n + m)).Value & "'"     Next     '先頭の余分な「,」を削除     sFields = Mid(sFields, 2)     sSQL = "Insert Into T_MAIN (受付日,受付時間,キュウリ,トマト,ナス)" _       & " Values(" & sFields & ");"     DoCmd.RunSQL sSQL   Next また、別の方法としては、フォームが大幅改変になりますが(汗)、T_MAIN テーブルと同じフィールド構成のテーブルを新規作成して、これをフォームの レコードソースとする、というものです。 これであれば、テーブル間でのレコード追加となるので、上記のようなループ 処理をしなくても、1回のSQL文の実行ですべてのレコードが追加できます。 なお、「1時間毎に1レコードとしているので、レコードの追加/削除をされては 困る」という場合は、フォームの『追加の許可』と『削除の許可』のプロパティを 「いいえ」にするとともに、作業テーブルに必要な数のレコードを登録しておき、 ユーザーにはこのレコードへの上書で作業をしてもらう、という手もあります。 (『受付時間』以外のすべてのフィールドの値をNullにする更新クエリを用意  しておき、フォームの開閉時にこれを実行。また、フォーム上に『初期化』  ボタンを新設して、ユーザーがこれをクリックしたときにもこれを実行すれば、  『受付時間』以外をすべて空白に戻すこともできるようになります) ※この方法を使用する場合は、フォームを開くとき及び『初期化』ボタンの  クリック時には、フォームの再クエリが必要です。  (それをしないと「#Delete」のエラー表示になります)  また、レコード表示のわかりやすさ(?)からすると、この方法の場合は  サブフォームを新設して、作業用テーブルもそのサブフォームのレコード  ソースとした方がいいかもしれません。  (この場合、再クエリはサブフォームに対して行います) 一応、以前のQ&Aも参考までに挙げておきます(No.8及びNo.9): http://okwave.jp/qa/q7819996.html

usas
質問者

お礼

丁寧なご回答をいただき、ありがとうございました。 ご回答いただいた通り、aを試してみたのですが、実行時に 「構文エラー 演算子がありません」 という表示が出てしまい、最初の1行しかテーブル登録することが できませんでした。 ※黄色く反転しているのは「DoCmd.RunSQL sSQL」です。 DexMachinaさんの回答は、私が言うまでもなく素晴らしい物でしたが、 解決に結びつける知識が私になかった……ということのようです。 フォームもテキストボックスも、こちらの言葉足りずの状況を 加味していただけけていて(非連結)、尚且つ、データ形式の 説明不足まで補っていただけているのに、本当に情けないです。 一行だけの登録であれば、さほど難しくなかったので 複数行もできると思いましたが、これほどの難易度とは 思いもしませんでした。 このような問題に丁寧に向き合っていただき、 本当にありがとうございました。

関連するQ&A