• ベストアンサー

SQLのSelect文をfor nextしたい

Select from where文で A1~A〇(〇は可変)セルに記入されているものを検索対象にしたく、 構文を無視して希望したい完成形を大雑把に書くと aaa = Range("A1").End(xlDown).Row SQL = Select * from TBL  for i = 1 to aaa where Fld = cells(i,1) next i こうなるのですが、当然動くはずもなく。 ORやINでも予め検索する個数が固定されていないとダメなような気がするのですが どのように文を書くとよろしいのでしょうか?

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

  • ベストアンサー
  • piroin654
  • ベストアンサー率75% (692/917)
回答No.5

遅くなりました。 Accessという言葉が出てこないので、 てっきりexcelのデータのみを対象としている と思っていました。 buf = adoRs.GetRows 補足になどが出てきたので、ひょっとして http://okwave.jp/qa/q8776430.html の続きですかね。 そういうことであれば、たとえば、Sheet2のF列に     12     45     36 などの年齢が数値として設定してあるとして、 Accessのテーブルに、 ID  名前  住所   年齢 1   田中  東京   34 2   佐藤  大阪   12 3   西田  東京   20 4   三村  名古屋  45 5   織田  福岡   50 6   石川  熊本   36 のようなデータがあるとします。Sheet2のデータの 年齢と一致するレコードをSheet1に縦横を反転させて、 2   4    6 佐藤 三村  石川 大阪 名古屋 熊本 12  45    36 のようにデータを抽出したい、ということで いいのでしょうか。そいうことであればこのように 書いていただくとすべての話がつながるのですが。 変数は、      Dim strSQL As String   Dim i As Long   Dim j As Long   Dim k As Long   Dim m As Long   Dim n As Long とします。途中を省略します。   j = Sheet2.Range("F1").End(xlDown).Row   k = rs.Fields.Count   n = 1   Do Until rs.EOF     For i = 1 To j     If Worksheets("Sheet2").Cells(i, 6).Value = rs!年齢 Then       For m = 1 To k         Worksheets("Sheet1").Cells(m, n) = rs.Fields(m - 1)       Next m       n = n + 1     End If     Next i   rs.MoveNext   Loop      '後始末   rs.Close: Set rs = Nothing   cn.Close: Set cn = Nothing のようにすれば、AccessのデータがSheet1に抽出されます。

fwod
質問者

お礼

回答ありがとうございます、説明不足で本当に申し訳ありません、URLの続きで合っています。 Excelのみで完結することでもADOを使えることを知りませんでした。 教えて頂いたコードでデータは抽出することができました ありがとうございます。 このままでもそこまで支障はないのですが selectには検索対象のフィールドも入れないとエラーが発生するので、そのフィールドを入れたのですが これですと、抽出に検索対象のフィールドもでてきますが、でてこないようにはなりませんか? 上でいうと、年齢で検索し、年齢を除いたID名前住所を抽出するイメージです。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (6)

  • piroin654
  • ベストアンサー率75% (692/917)
回答No.7

ExcelでADOを使ってデータを加工するものと 思っていました。途中で何だかはずしているのかな、 という感じがしていました。失礼しました。 補足に関しては、Accessのデータを取り出す SQL文が、   SELECT * FROM テーブル名 となっていて、「*」を使うとすべてのフィールドを 対象とします。したがって取り出すフィールド名を 「*」のかわりに羅列すればいいのですが、一方で 「年齢」のフィールドレコードの検索対象にしていますから 「年齢」のフィールドを含めてデータを取り出す 必要があります。したがって、コードの中で「年齢」の フィールドデータをはじきながらSheetに格納ということで、     If Worksheets("Sheet2").Cells(i, 8).Value = rs!年齢 Then       For m = 1 To k         If Not rs.Fields(m - 1).Name = "年齢" Then            Worksheets("Sheet1").Cells(m, n) = rs.Fields(m - 1)         End If       Next m       n = n + 1     End If のように、     If Not rs.Fields(m - 1).Name = "年齢" Then     End If で、     Worksheets("Sheet1").Cells(m, n) = rs.Fields(m - 1) を挟み込みます。これで「年齢」というフィールドのデータは Sheetには格納されません。 なお、新しく立てられた質問、 http://okwave.jp/qa/q8792437.html に関しては、また違った方法を取るようになります。 たぶん、出来るとは思いますが、確認してみます。 ひとまずは、上記のことを確認してみてください。

全文を見る
すると、全ての回答が全文表示されます。
  • piroin654
  • ベストアンサー率75% (692/917)
回答No.6

No5に追加してください。    strSQL = "SELECT * FROM テーブル名" を、変数宣言の後に設定しておいてください。 当然ながら「テーブル名」とはAccessのテーブル名 です。 このテーブルをExcelのSheetのデータと思っていました。 これが話がかみ合わなかった原因ですかね。失礼しました。

fwod
質問者

お礼

ありがとうございます、試せる環境がなく 連続投稿できないokwaveの仕様で返事が遅れてしまいました。 コードを書いたところ、自分の思い描いた動きをしてくれました。 辛抱強く付き合ってくださり、本当にありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。
  • piroin654
  • ベストアンサー率75% (692/917)
回答No.4

補足内容に、こちらがおいついていない 感じで。 SELECT * FROM [Sheet2$A3:B6] 上記のSQL文はFROM以下の [Sheet2$A3:B6] が、対象となるデータが存在するテーブルを 意味します。 SELECT * は、指定されたテーブル中の全てのフィールドを 選択する、という意味です。 SQL文の解読は後ろから解読されます。 Excelのバージョンと接続文字列については、 http://support.microsoft.com/kb/257819/ja http://sorceryforce.net/WordPress/?p=154 なお、OSなどの環境によっては参照設定でAD0のバージョンを 下げる必要があることもありえます。 補足中の、 >また、回答してくださったものにはテーブル名が入っていないのですが、これでよろしいのでしょうか? >(ちなみに、SQL文を >SQL = _ >"select * from TBL [シート$F" & i & ":F" & j & "]" において、「TBL」については何か変数宣言なりオブジェクトの 設定なりをされているのですか?

fwod
質問者

補足

うーん・・ちょっと話がかみ合ってないですね。 説明不足だったのでもう一度質問内容を詳しく言うと Accessデータベースから特定のテーブルに特定のフィールドの中にある 値を含む行を抽出したいのです。 そしてその値はマクロによりコンボボックスから複数選択し、 エクセルのA1から下に追加されていきます。 A1 2000 A2 4530 と入っているとすると そのテーブルの特定のフィールド内に2000と4530がある行のデータを 抽出したいのです。 なので、回答して頂いたものであると自分の期待していたものとはちょっと違うものが抽出されることが予想されますし、何よりそれ以前にエラーがでます。 上の補足にある「TBL」はテーブル名をさします。

全文を見る
すると、全ての回答が全文表示されます。
  • piroin654
  • ベストアンサー率75% (692/917)
回答No.3

オートメーションエラー以外に、補足の以下のような 使い方はしません。たぶん、型が違うというエラーが 起こります。 >i = 45 >j = 44 + Worksheets("シート名").Range("B47") 'Fの45行目からB47に記入されている数字の行分だけ取得 >strSQLgenyu = _ >"select * from [シート名$F" & i & ":F" & j & "]" No1の回答をよくみてください。 i = 3 j = 6 strSQL = "SELECT * FROM [Sheet2$A" & i & ":B" & j & "]" や、 i = 1 j = Sheet2.Range("A1").End(xlDown).Row strSQL = "SELECT * FROM [Sheet2$A" & i & ":B" & j & "]" のようにiやjには数値がはいります。また、 strSQL = "SELECT * FROM [Sheet2$A" & i & ":B" & j & "]" に実際の数値を入れてかきなおせば、 i = 3 j = 6 strSQL = "SELECT * FROM [Sheet2$A" & i & ":B" & j & "]" と、 strSQL = "SELECT * FROM [Sheet2$A3:B6]" は、同じです。つまり、Sheet2のA3からB6の範囲のデータを 対象とする意味です。

fwod
質問者

補足

回答ありがとうございます。 [Sheet2$A" & i & ":B" & j & "]" の意味は理解しているつもりです。 >j = 44 + Worksheets("シート名").Range("B47") 'Fの45行目からB47に記入されている数字の行分だけ取得 のB47には数値が入っております。 ちなみに j = 48と、数値を入れてみても同様の結果となりました。 (また、補足ではSQLgenyuとstrSQLが混在していますが、これは質問用にリネームしているだけなので実際には同じ名称を使っております。混乱させてしまい申し訳ありません)

全文を見る
すると、全ての回答が全文表示されます。
  • piroin654
  • ベストアンサー率75% (692/917)
回答No.2

コード表の参照設定で、ADOにチェックが入っているか、 参照設定が「不可」になっているものがないか、ある場合は チェックをはずす、あるいは、ADOのバージョンが妥当な ものか、などをまず確認してみてください。

fwod
質問者

補足

回答ありがとうございます、ADOを使用して、検索対象を可変ではなく、where ORを使用して 1つや2つ等指定してあげると抽出されるので、問題ないかと思います。 verはMicrosoft.jet.OLEDB.4.0ですが、Ace.OLEDB.12.0でないと動かないものでしょうか? また、回答してくださったものにはテーブル名が入っていないのですが、これでよろしいのでしょうか? (ちなみに、SQL文を SQL = _ "select * from TBL [シート$F" & i & ":F" & j & "]" adoRs.Open SQL, adoCn, adOpenKeyset tmpFldCnt = adoRs.Fields.Count '9 tmpRecCnt = adoRs.RecordCount '4 Range("M28:DG31").ClearContents ReDim buf(tmpFldCnt - 1, tmpRecCnt - 1) buf = adoRs.GetRows Range(Cells(28, 13), Cells(28 + tmpFldCnt - 1, 13 + tmpRecCnt - 1)) = buf とすると、そのテーブルにある全ての情報がM28から書き込まれます。)

全文を見る
すると、全ての回答が全文表示されます。
  • piroin654
  • ベストアンサー率75% (692/917)
回答No.1

たとえば、Sheet2にA1を起点に以下のような データがあるとして、 東京  関東 名古屋 中部 大阪  関西 神戸  関西 岡山  中国 広島  中国 福岡  九州 熊本  九州 このデータの大阪から広島までのデータを 取得するならば、簡単な方法としては、 Dim i As Long Dim j As Long i = 3 j = 6 strSQL = "SELECT * FROM [Sheet2$A" & i & ":B" & j & "]" のようにします。質問の場合は、たとえば、東京から最後の 熊本までデータを取得するならば、 Dim i As Long Dim j As Long i = 1 j = Sheet2.Range("A1").End(xlDown).Row strSQL = "SELECT * FROM [Sheet2$A" & i & ":B" & j & "]" のようにします。 取得したデータは、ADOやDAOなどのRecordsetオブジェクトを使って、Sheet1に 貼り付けるなどの処理をします。

fwod
質問者

補足

回答ありがとうございます、ADOを用いて試してみたのですが (宣言、DB接続省略) Dim i As Long Dim j As Long i = 45 j = 44 + Worksheets("シート名").Range("B47") 'Fの45行目からB47に記入されている数字の行分だけ取得 strSQLgenyu = _ "select * from [シート名$F" & i & ":F" & j & "]" adoRs.Open strSQL, adoCn, adOpenKeyset  'ここでエラー 上記の場所でオートメーションエラーがおきてしまいます。 原因は何でしょうか?

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • ストアドのselect文で別テーブルのカウントを取得するには

    こんばんは。 以下のようなことをするのにどう記述していいのか わかりません。 入力パラメータ test1,test2に一致するテーブル1のレコードの 項目1と項目2の値と test1,test2に一致するテーブル2のレコードの カウントを 返したいと考えていますがどう記述したら テーブル2のカウントを返せるのかわかりません。 以下、考え中の内容を記述したものです。 テーブルTBL_AとテーブルTBL_Bがある。 TBL_Aの項目はFLD_1,FLD_2,FLD_3 TBL_Bの項目はFLD_1,FLD_2,FLD_3,FLD_4 TBL_AとTBL_Bには同一のフィールドFLD_1,FLD_2があり、 select FLD_1,FLD_2,FLD_3 FROM TBL_A WHERE FLD_1 = test1 AND FLD_2 = test2(select文1) 上記のSQLでTBL_AのFLD_1,FLD_2を取得する ここに、 select count(*) FROM TBL_B WHERE FLD_1 = test1 AND FLD_2 = test2(select文2) このselect文2で取得した値を select文1に接続して値を戻したいのですが やり方がわかりません。 戻したい値はTBL_AのFLD_1,FLD_2,FLD_3とTBL_Bのカウントです。 お分かりになる方教えてください。よろしくお願いします。 なおoracleは9iを使っています。

  • SQL文について困っています

    ID(NUMBER型)と NUM(NUMBER型)と nenngetu (date型)を持ったテーブルAAAから、 ID=1000 のなかで日時が一番古い処理NOをselectするSQL文を書きましたが上手く実行されません。 select NUM from AAA where nenngetu = (select min(nenngetu) from AAA) and ID=1000; ID=1000の条件をはぶき、 select NUM from AAA where nenngetu = (select min(nenngetu) from AAA); でしたら、実行できました。 oracleで実行しようとしています。 どなたか、書き方を教えてください。

  • すっきりとしたSQL文にしたいのですが

    Oracle9iにてテーブルのデータを更新しようと思っています。 目的としてはAAAのカラムa1とBBBのカラムb1が同一なレコードである場合、 AAAのa2にBBBのb2を更新したいのですが、 <条件> AAA:テーブル1 BBB:テーブル2 a1:CHAR b1:CHAR a2:VERCHAR b2:VERCHAR すべて必須で桁数は10 UPDATE AAA SET AAA.a2 = ( SELECT BBB.b2 FROM BBB WHERE AAA.a1 = BBB.b1) WHERE AAA.a1 = ( SELECT BBB.b1 FROM BBB WHERE AAA.a1 = BBB.b1) ; いまはこんな無駄の多そうなSQLしか分かりません。 この他にも条件が2つ追加される予定なので もっとすっきり更新できる方法を教えていただけませんでしょうか? よろしくお願いします。

  • SQL文について

    TBL_A カラム1 |カラム2 |カラム3 |カラム4 | ---------|---------|---------|---------| 1    |AAA   |N    |1    | ---------|---------|---------|---------| 2    |AAA   |G    |1    | ---------|---------|---------|---------| 3    |BBB   |N    |0    | ---------|---------|---------|---------| 4    |CCC   |N    |0    | ---------|---------|---------|---------| TBL_B カラム1 |カラム2 | ---------|---------| AAA   |2    | ---------|---------| BBB   |0    | ---------|---------| CCC   |1    | ---------|---------| 上記のテーブル、TBL_A、TBL_Bがあるとします。 TBL_Aからカラム3='N'を抽出し、TBL_Bのカラム2でソートしたいのですが、 可能でしょうか? 結果 ---------|---------| BBB   |0    | ---------|---------| CCC   |1    | ---------|---------| AAA   |2    | ---------|---------| …となって欲しいのですが。。。 select TBL_A.カラム2 from TBL_A, TBL_B where TBL_A.カラム3='N' order by TBL_B.カラム2 では、うまくいきませんでした。 ※ TBL_A、TBL_Bは共にカラム1がキー値です。

  • oracleからSQL Serverへの移行

    oracleからSQL Serverへ移行することになったのですが、副問い合わせで定義したテーブル同士を外部結合するSQL構文が、うまく実現できず、ご教授して頂きたくよろしくお願いします。 下記、oracle 構文をSQL Server構文へ書き換えたい。 select * from (select cal1,cal2,cal3 from tbl1,tbl2 where cal1 >100) aaa, (select cal1,cal2,cal3 from tbl1,tbl2 where cal1 <=100) bbb, tbl3 where aaa.cal1 = bbb.cal1(+) and aaa.cal2 = bbb.cal2(+) and aaa.cal3 = bbb.cal3(+) and aaa.cal1 = tbl3.cal1 よろしくお願いします。

  • PL/SQL)Functionの引数(文字列)をWHERE文に記述する方法

    PL/SQLで、Functionの中で実行するselect文のWhereに、Functionの 引数で受けとった値をセットしようとしています。 この引数が文字列(VARCHAR2型)の場合、どのようにWHEREで、記述したらよいのでしょうか? ご教授のほどをよろしくお願いします。 CREATE OR REPLACE FUNCTION Fn_TBL_AAA (psCODE IN VARCHAR2) IS CURSOR TBL_AAA_CUR IS SELECT * FROM TBL_AAA WHERE BBB = psCODE ; TBL_AAA_REC TTBL_AAA_CUR%ROWTYPE;       :       : ※上記のように記述すると、実行ではエラーが発生しないのですが、  取得したい結果が返ってきません。TABLE(TBL_AAA)のBBBは、  VARCHAR2なので、通常のSQL*PLUSのSELECT文ではBBB = psCODE  はBBB = 'psCODE'のように [']で括るのですが、PL/SQLの  FUNCTION内ではどのように記述すればよいのかが  わかりません。 以上、よろしくお願いいたします。

  • ACCESSのSQLの書き方

    ACCESSでのSQL文の書き方を教えてください。 テーブルtbl_Aとテーブルtbl_Bがあり, tbl_Aで得られた数値とtbl_Bで得られた数値を加えたものを結果として表示します。 どう書けばよろしいのでしょうか。どうしてもエラーになってしまいます。 イメージとしてはこんな感じです。 select (select ~~ from tbl_A where ~~)+(select ~~ from tbl_B where ~~) (もしoracleならば,「from dual」というのを最後に付けるんですが。)

  • SQL : たしかに DELETE したの?

    ありがちな処理かと思いまして質問させていただきます。 SQLで DELETE を行う際、WHERE で絞り込んだ対象行がなくても、  「エラーは返ってこない」 ということですが、NOT FOUND判定はするのでしょうか。 ごく単純に、削除しようとしたデータが実際にあったのかを確認したいのです。 やろうとしている処理は、次のようなものです。 DELETE FROM a_tbl WHERE NOT EXISTS (SELECT row1 FROM b_tbl WHERE row1 = 'input_data' ) AND NOT EXISTS (SELECT row1 FROM c_tbl WHERE row1 = 'input_data' ); ようするに、他のテーブルに、すでにない行であることが前提で、 a_tbl から DELETE したことを確認したいのです。 Pro*C内で実行するのですが、一般に同じだと思います。 キホンのキかもしれませんが、よろしくお教えください。

  • SELECT * FROM tbl WHERE a = ?;

    SELECT * FROM tbl WHERE a = ?; 上記のSQL文で、?の部分がnullだとWHERE条件を無い状態に(SELECT * FROM tbl) のようにするにはどうすればいいでしょうか?

  • SQL文について

    OracleやSQLについてはまだ初心者のレベルで理解が浅いので言葉足らずかもしれませんがよろしくお願いします。 以下のようなテーブル(名称:TBL)があったとします。 SHOP_CODE------SHOP_NUMBER----MONEY1------MONEY2 A ---------------- 1 ---------------- 100 ------------- 200 B ---------------- 2 ---------------- 300 ------------- 400 C ---------------- 3 ---------------- 500 ------------- 600 D ---------------- 4 ---------------- 700 ------------- 800 例えば、SHOP_CODEがA~Dのどれかの行(レコード)はそのまま抽出して、残った行(レコード)はMONEY1およびMONEY2を0に変更して抽出しようとした場合、 SELECT * FROM TBL WHERE SHOP_CODE = 'ここはA~Dのどれかを代入' UNION SELECT SHOP_CODE, SHOP_NUMBER, 0, 0 FROM TBL WHERE SHOP_CODE <> 'A~Dのどれかを代入' このようなSQL文を考えてみました。 しかし、比較的簡単な例ならばよいのですが、UNION前のSELECT文が複雑になってきた場合のことを考え以下のような文の作りかたができないかと思いました。 SELECT * FROM TBL WHERE SHOP_CODE = 'ここはA~Dのどれかを代入'・・・『この時点で抽出した塊になんらかの名称をつける(例:tbl)』 UNION SELECT SHOP_CODE, SHOP_NUMBER, 0, 0 FROM TBL WHERE SHOP_CODE <> tbl.SHOP_CODE・・・『このようにUNION以前に抽出した塊の名称を利用して条件を作成』 このような方法ができるとした場合、前段階で抽出した塊にどのような方法で名称をつけるのか分かりませんでした。(汗)そもそもできるかどうかもわかりませんが、、、(^^; 最初のSQL文がベターな方法なのかも分かりませんが、上記に示した方法で抽出することが可能でしょうか?もしできるのならば、前述したように名称をつけて条件を作成する方法等を教えていただきたいと思います。 おおよそ話を分かっていただければよいのですが、ものすごく簡単に言うと一つのテーブルのある行とある行に別々の処理をして再構成したいというようなイメージです。(今回はMONEYを0にすると仮定しました) できれば上記の方法に沿った考えで回答をいただけると私も助かりますが、もっと良い方法があれば是非伺いたいと思います。お時間の方ありましたらよろしくお願いします。

専門家に質問してみよう