• ベストアンサー

【Access2003】クエリで動作するSQLがVBAで動作せず困っています。

下記のソースを実行したところ、「パラメータが少なすぎます。2を指定してください。」というエラーが表示されました。 エラーが発生する箇所は「db.Execute strsql」です。 しかし、このstrsqlに書かれているSQL文をクエリで実行した所、問題なく動作しました。 なんとなく、クエリでは書けるものの、VBAでは書きない所があるのかなと思ったのですが、どのように修正すればよいか分かりませんでした。 その為、上記の現象について、ご教示いただける方がいらっしゃいましたら、よろしくお願いします。 【VBA】 Private Sub btn_Click() Dim db As DAO.Database Dim ws As DAO.Workspace Dim str As String Set ws = DBEngine.Workspaces(0) Set db = CurrentDb ' トランザクション開始 ws.BeginTrans strsql = "INSERT INTO T_W ( W_DAY )" strsql = strsql & "SELECT T_M.M_DAY" strsql = strsql & " FROM T_M" strsql = strsql & " WHERE (((Left([T_M].[M_DAY],4) & Mid([T_M].[M_DAY],6,2) & Right([T_M].[M_DAY],2))" strsql = strsql & " Between IIf(Nz([Forms]![F_1]![text_str])='',0,[Forms]![F_1]![text_end])" strsql = strsql & " And IIf(Nz([Forms]![F_1]![text_str])='',99999999,[Forms]![F_1]![text_end])))" strsql = strsql & " ORDER BY T_M.M_DAY" db.Execute strsql ws.CommitTrans End Sub 【フォーム:F_1】 テキストボックス:text_str テキストボックス:text_end コマンドボタン:btn 【データベース:T_M】 フィールド名:M_DAY    値  :2001/01/01    値  :2001/01/02    値  :2001/01/03 (以下略) 【データベース:T_W】 フィールド名:W_DAY    値  :なし よろしくお願いします。

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

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

原因は把握できていないのですが、再現は確認できました。 一応、その中で見つけた対処法をご紹介します。 その方法というのは、SQL文内のIIF関数で処理している部分を、先に文字列化 してしまう、というものです。 (なお、今回のエラーとは関係ありませんが、各句の区切りを、Spaceから改行  (vbCrLf)に変更しています) 宣言領域に  Dim strHead As String, strTail As String を追加した上で、SQL文の設定部分を以下のように変更してみて下さい。  'テキストボックスへの入力値の確認  strHead = IIf(Nz([Forms]![F_1]![Text_str]) = "", 0, [Forms]![F_1]![Text_End])  strTail = IIf(Nz([Forms]![F_1]![Text_str]) = "", 99999999, [Forms]![F_1]![Text_End])  '同じフォーム上でのVBAの記述であれば、以下でも可  'strHead = IIf(Nz(Text_str) = "", 0, Text_End)  'strTail = IIf(Nz(Text_str) = "", 99999999, Text_End)  'SQL文の設定  strSQL = "INSERT INTO T_W ( W_DAY )" & vbCrLf  strSQL = strSQL & "SELECT T_M.M_DAY" & vbCrLf  strSQL = strSQL & "FROM T_M" & vbCrLf  strSQL = strSQL & "WHERE (((Left([T_M].[M_DAY],4) & Mid([T_M].[M_DAY],6,2) & Right([T_M].[M_DAY],2))" & vbCrLf  strSQL = strSQL & "Between " & strHead & " And " & strTail & "))" & vbCrLf  strSQL = strSQL & "ORDER BY T_M.M_DAY;" ・・・以上です。

iroha_168
質問者

お礼

ご回答ありがとうございます。 ご提示いただいたソースで意図した動作が行われる事を確認しました。 Private Sub btn_Click() Dim db As DAO.Database Dim ws As DAO.Workspace Dim str As String Dim strHead As String Dim strTail As String Set ws = DBEngine.Workspaces(0) Set db = CurrentDb ws.BeginTrans strHead = IIf(Nz(Me.text_str) = "", 0, Me.text_str) strTail = IIf(Nz(Me.text_end) = "", 99999999, Me.text_end) strsql = "INSERT INTO T_W ( W_DAY )" strsql = strsql & "SELECT T_M.M_DAY" strsql = strsql & " FROM T_M" strsql = strsql & " WHERE (Left([T_M].[M_DAY],4) & Mid([T_M].[M_DAY],6,2) & Right([T_M].[M_DAY],2))" strsql = strsql & " Between " & strHead & " AND " & strTail strsql = strsql & " ORDER BY T_M.M_DAY" db.Execute strsql ws.CommitTrans End Sub 今後はSQL文内の条件分岐を予め文字列化しておくようにしようと思います。 このたびはどうもありがとうございました。 以上、よろしくお願いします。

その他の回答 (1)

  • 30246kiku
  • ベストアンサー率73% (370/504)
回答No.2

ご質問の現象についてではありません。 ちょっと気になったので > strsql = strsql & " Between IIf(Nz([Forms]![F_1]![text_str])='',0,[Forms]![F_1]![text_end])" > strsql = strsql & " And IIf(Nz([Forms]![F_1]![text_str])='',99999999,[Forms]![F_1]![text_end])))" 上記は正しいでしょうか。 上の行は、text_str で、下の行は、text_end になるのでは?と思います。 今のままでは、text_str が空白でなければ、text_end が両方の値になるような ( Between text_end And text_end )? 後、Where条件でフィールド側を加工するよりも、比較する値の方をフィールドに合わせた方が良いような気がします。 T_M.M_DAY が 2001/01/01 (テキスト型?)の値を持つのなら、 Format([Forms]![F_1]![text_str],"@@@@/@@/@@") にしたもので比較してはどうでしょう。 Between の条件を見ると、Between にこだわらずに、 必要な条件のみを、以上/以下( >= とか <= )で指定した方が楽なような気がします。 WHERE 部分の作成例) Dim sWhere As String sWhere = "" If (Len(Nz([Forms]![F_1]![text_str])) > 0) Then   sWhere = sWhere & " AND (T_M.M_DAY >= '" _         & Format([Forms]![F_1]![text_str], "@@@@/@@/@@") & "')" End If If (Len(Nz([Forms]![F_1]![text_end])) > 0) Then   sWhere = sWhere & " AND (T_M.M_DAY <= '" _         & Format([Forms]![F_1]![text_end], "@@@@/@@/@@") & "')" End If If (Len(sWhere) > 0) Then sWhere = " WHERE " & Mid(sWhere, 6) ※どちらか片方でも条件があり文字列が作られていた場合、 先頭に付けていた " AND " を削除した形で WHERE部分を生成 後は、以下のように組み合わせれば strsql = "INSERT INTO T_W ( W_DAY )" strsql = strsql & "SELECT T_M.M_DAY" strsql = strsql & " FROM T_M" strsql = strsql & sWhere & " ORDER BY T_M.M_DAY" ※個人的には、VBAでSQLを作る時には即値に展開しています。 (フォームを参照させないようにしています) ※T_M.M_DAYはテキスト型と仮定して、Formatの前後を ' ' で囲ってます。 ※実際に動かしてみていないので、、、

iroha_168
質問者

お礼

ご回答ありがとうございます。 > 上の行は、text_str で、下の行は、text_end になるのでは?と思います。 おっしゃるとおりです。 ご指摘ありがとうございます。 ちなみに、T_M.M_DAYは日付/時刻型となります。 ご指摘のソースを実行してみたところ、私の意図する動作とは下記が異なるようでした。 1. 条件未入力時、空白のレコードを持ってきてしまう (私が記載したBetweenのソースの場合、条件未入力時、0~99999999のレコードを取得し、 それ以外のレコード(例:空白)は対象外となります)。 2. 存在しない日付を入力の上、実行すると、日付の構文エラーになるのではと思いました。 【サンプル】 Private Sub btn_Click() Dim db As DAO.Database Dim ws As DAO.Workspace Dim str As String Dim strHead As String Dim strTail As String Set ws = DBEngine.Workspaces(0) Set db = CurrentDb ws.BeginTrans strHead = Format(Me.text_str, "@@@@/@@/@@") strTail = Format(Me.text_end, "@@@@/@@/@@") strsql = "INSERT INTO T_W ( W_DAY )" strsql = strsql & " SELECT T_M.M_DAY" strsql = strsql & " FROM T_M" strsql = strsql & " WHERE M_DAY Between #" & strHead & "# AND #" & strTail & "#" strsql = strsql & " ORDER BY T_M.M_DAY" db.Execute strsql ws.CommitTrans End Sub 今回は、20090000と20100000と入力された場合、 2009/00/00~2010/00/00の間に存在する日付を抽出したいと考えている為、 質問文のようなソースとなっております。 それと、20090101を2009/01/01に変換するのに 「Format(Me.text_str, "@@@@/@@/@@")」という書き方ができるのは知らなかったので、 参考になりました(今まではLeftとMidとRightを組み合わせていたので)。 また、下記の方法も今まで考えてもいなかった方法なので参考になりました。 > 先頭に付けていた " AND " を削除した形で WHERE部分を生成 以上、よろしくお願いします。

関連するQ&A

  • テキストボックスに入れた内容をAccessのテーブルに登録する方法を教えてください。

    はじめまして。 VBでフォームに作ったテキストボックス(text1、text2、text3)に値を入れてコマンドボタンを押したらAccessのテーブルに値を登録できるようにしたいのですが上手くいきません。自分で調べながらコーディングしたのですが上手く動かずどうすれば動くのかVBのコーディングを教えていただきたいです。よろしくお願いします。 [Accessのファイル名] db1.mdb [db1.mdbのテーブル名] ListName [ListNameの各項目] 名前、住所、生年月日 [VBのフォーム] text1.textbox、text2.textbox、text3.textbox Add.command [コーディングの内容] Microsoft DAO 3.6 Object Library参照設定 Private Sub Add_Click() Dim strSQL As String Dim dbName As String Dim dbs As DAO.Database Dim myset As DAO.Recordset Dim ws As DAO.Workspace Set ws = DBEngine.Workspaces(0) Set dbs = ws.OpenDatabase("C:\db1.mdb") If Dir("C:\db1.mdb") <> "" Then strSQL = "INSERT INTO Listname (名前,生年月日, _ 住所) values(text1.text, text2.text, text3.text)" Me.AutoRedraw = True Set myset = dbs.OpenRecordset(strSQL) End If End Sub ※無効な処理です。というエラーが出ます。

  • Access VBAでパラメータクエリをSQL文へ

    すみません、、初めて質問しますが、 お手柔らかに宜しくお願い致します。 1.集計クエリ1    ID--Group化 出庫数--合計 日付--Where条件 2..集計クエリ2  ID--Group化 入庫数--合計 日付--Where条件 3.出力用クエリ  ID 商品名 集計クエリ1の合計 集計クエリ2の合計  IDと左結合で、上記のクエリを作成 デザインビューでは1~3は完成しており、 VBA上で1と2を3のSQLに置き換えるところで悩んでおります。。 どなたか教えてください。 ちなみに1.集計クエリの下記のように試してみましたが、 Dim dbs As DAO.Database Dim qdf As QueryDef Dim rst As DAO.Recordset Set qdf = dbs.QueryDefs("Q_データ抽出をしたいクエリ") With qdf .Parameters("[Forms]![f_DataEx]![txt_YearStart]") = "2011" .Parameters("[Forms]![f_DataEx]![txt_MonthStart]") = "02" .Parameters("[Forms]![f_DataEx]![txt_DayStart]") = "23" .Parameters("[Forms]![f_DataEx]![txt_YearEnd]") = "2011" .Parameters("[Forms]![f_DataEx]![txt_MonthEnd]") = "02" .Parameters("[Forms]![f_DataEx]![txt_DayEnd]") = "23" Set rst = .OpenRecordset End With 上記で求めた"rstを基にSQL文が実行できれば、実現できそうなんですが、 うまく行きません。 言葉足らずの内容もあるかと思いますが、宜しくお願い致します。

  • ACCESS VBA クエリを開く

    ACCESS初心者です。 VBAはEXCELで独学した程度の知識です。 フォームから受注納期を入力し、クエリを抽出。 クエリでレコード毎に製品票の印刷枚数を計算し レポートで各レコード毎に求められた印刷枚数分を 印刷させたいのですが・・・ クエリを開く段階でつまずいており困っています。 Private Sub コマンド23_Click() Dim db As DAO.database Dim rs As DAO.Recordset Dim qdf As DAO.QueryDef Set db = CurrentDb() Set qdf = db.QueryDefs("受注クエリ") With qdf .Parameters("納期") = Format(Forms![受注データ一覧]![納期], "yyyy/mm/dd") Set rs = .OpenRecordset .Close End With MsgBox rs![注文番号] rs.Close End Sub パラメータクエリの開き方、上記コードで問題ないでしょうか? そしてこのコードを実行した際 実行時エラー3421 データ型の変換エラーが発生しましたと表示されます。 ローカルウィンドウで 変数rs = nothingとなっており クエリのレコードが読み込めていないようです。 (Msgbox rs!注文番号はデータが読み込めたかテストするために コードを書いています。) どうぞ宜しくお願いいたします。

  • 初歩的なSQLですが・・・

    私の環境はOS:Xp      ACCESS2000です。 宜しくお願いします 今AccessVBAで作業をしているのですが、 Dim ws As DAO.Workspace Dim DB As DAO.Database Dim rs As DAO.Recordset Dim sql As String Set ws = DBEngine.Workspaces(0) Set DB = ws.Databases(0) sql = "select MAX(銀行コード) from 銀行テーブル ;" Set rs = DB.OpenRecordset(sql) Me.合計 = rs このSQL文で銀行テーブルに入っている銀行コードの最大値を取得したいのですが、取得した後どのように記述したら「rs」から値を引っ張り出せるのでしょうか? 宜しくお願いします。

  • アクセスVBA 変数での抽出条件の書きかた

    顧客データテーブルからの抽出です。 変数を使った書き方がわかりません。 よろしくお願いします。 テーブルのレコードには [氏名]:鈴木 [telnum]:0123456789 が存在します。 Private Sub テキスト0_BeforeUpdate(Cancel As Integer) Dim db As DAO.Database Dim rs As DAO.Recordset Set db = CurrentDb Set rs = db.OpenRecordset("顧客マスタ", dbOpenDynaset) Dim str As String str = "0123456789" rs.Filter = "[telnum] = ' " & str & " ' " Set rs = rs.OpenRecordset MsgBox (rs!氏名) ’←エラーメッセージ”カレントレコードがありません。”が出ます End Sub

  • アクセスに登録した値を条件検索によりtextboxに反映させる方法を教えてください。

    はじめまして。お世話になります。 Accessで登録した値をVBのフォーム上のテキストボックスに 反映させる方法を教えてください。 [Accessのファイル名] db1.mdb [db1.mdbのテーブル名] ListName [ListNameの各項目] 日付、名前、住所、生年月日 [VBのフォーム] lbldate、text1.textbox、text2.textbox、text3.textbox、Select.command ※lbldateの内容は日付(テキスト型)でCaptionでとってきた値が「日付」項目に登録される。 3つのtextboxには入力した値は「名前」・「住所」・「生年月日」項目に登録される。(すべてテキスト型) [自分で調べ考えたコーディングの内容] Microsoft DAO 3.6 Object Library参照設定 Private Sub Select_Click() Dim strSQL As String Dim dbs As DAO.Database Dim myset As DAO.Recordset Dim ws As DAO.Workspace Set ws = DBEngine.Workspaces(0) Set dbs = ws.OpenDatabase("C:\db1.mdb") Me.AutoRedraw = True strSQL = "SELECT * FROM Listname where 日付 = '" & lbldate & "'; " Set myset = dbs.OpenRecordset(strSQL) Text1.Text = CStr(myset("名前")) Text2.Text = CStr(myset("生年月日")) Text3.Text = CStr(myset("住所")) myset.Close End Sub 上記の内容では上手くいきません。過去にテキストボックスに入力した値を教えていただきましたが今回は逆にレコードを検索して選択する方法が上手くいきません。 アドバイスをよろしくお願い致します。 ※求める機能としてlblnameに表示される値を条件にそれに対応するレコードを選択したいのですが検索時に該当する日付がなかった場合は3つのテキストボックスに値を何も返さないプログラムにしたいと思っています。よろしくお願い致します。

  • access97でのFunctionプロシージャの使い方

    Access97で作業しています。 以下の記述で定義したレコードセットを同一の*.mdbのなかで共有したい(他のイベントプローシージャで呼びたい)のですが、どのようにするのでしょうか? これをFunctionプローシージャにする? Public にする? それと、このプロシージャで定義した変数名は他のイベントプロシージャでも使えるのでしょうか? プロシージャの性質も良く判らない状態です。宜しくお願い致します。 Dim strSQL As String Dim i, j, TOL, cnt As Integer Dim rsFLT, rsTBL As DAO.RecordSet Dim DB As Database Set DB = CurrentDb strSQL = "SELECT * FROM [Q-Order用] WHERE ID='" & [Forms]![F-Order用]![IDbox] & "'" Set rsFLT = DB.OpenRecordset(strSQL)

  • 拡張子が.mdbでないアクセスファイルを開くには?

    拡張子が.mdbでない以下のようなアクセスファイルOSAKA.sffを開くにはどのようにしたらよいですか? 現状、 Set db の行で 実行時エラー3343“データベースの形式認識できません”とエラーが出ます。 Private Sub Command5_Click() Dim ws As DAO.Workspace Dim db As DAO.Database Dim rs As DAO.Recordset 'デフォルトのワークスペースを定義する Set ws = DBEngine.Workspaces(0) 'データベースを開く Set db = ws.OpenDatabase("C:\Data\OSAKA\OSAKA.sff") End Sub

  • ACCESS クエリーから件数取得

    下記のような記述でクエリーより件数を取得したいのですがうまくいきません。 rstBufの指定が悪いのだとは思い、調べてはいるのですがうまくいかない状態です。 どなたかご助言をお願い致します。 Dim rstBuf As DAO.Recordset Dim qryBuf As DAO.QueryDef strSQL=select xx from xx Set qryBuf = CurrentDb.CreateQueryDef(Q_RPT, strSQL) Set rstBuf = qryBuf.OpenRecordset(strSQL,dbOpenDynaset) If rstBuf.EOF = False Then rstBuf.MoveLast count = rstBuf.RecordCount End If rstBuf.Close Set rstBuf = Nothing

  • VB2008からAccess2007へのDAO接続でエラーになります。

    VB2008からAccess2007へのDAO接続でエラーになります。 VB2008EEからDAO3.6を利用し、Access2007(*.accdb)に接続しようとしていますが、 エラーが発生してしまい、接続できません。 エラーの内容は下記のとおりです。 実行時エラー '3343': データベースの形式 'XXX' を認識できません。 Access2000のデータベース(*.mdb)には普通に接続できています。 Accessのバージョンを問わずに接続したい場合、どうすればよいのでしょうか? 参考までに現在のコードを記載しておきます。 ※DAO3.6に参照設定してあります。 Imports dao Module modConnectDb Public Function DaoConnect(ByVal strDb As String) As Boolean 'strDb:データベースのファイルパス Dim Ws As dao.Workspace Dim DbE As dao.DBEngine Dim Db As dao.Database Dim strMsg As String Try DbE = New dao.DBEngine Ws = DbE.Workspaces(0) Db = Ws.OpenDatabase(strDb) Catch ex As Exception strMsg = "エラー番号 " & Str(Err.Number) & vbCrLf & _ Err.Source & " でエラーが発生しました。" & vbCrLf & Err.Description MsgBox(strMsg, vbExclamation, "エラー") End Try End Function End Module

専門家に質問してみよう