質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Access

Accessはマイクロソフトによるリレーショナルデータベース管理システムです。オブジェクト指向のアプリケーション作成に対応しており、テーブルや編集をはじめ、クエリ生成、入力フォーム作成、レポート作成など一通りの機能を備えています。

Q&A

解決済

4回答

10656閲覧

VBA Recordset の Sort でエラーになる

shigeru

総合スコア38

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Access

Accessはマイクロソフトによるリレーショナルデータベース管理システムです。オブジェクト指向のアプリケーション作成に対応しており、テーブルや編集をはじめ、クエリ生成、入力フォーム作成、レポート作成など一通りの機能を備えています。

0グッド

0クリップ

投稿2019/05/05 08:16

Excel VBA のRecordset でSort でエラーが出て実行できない

下記コードで .Sort でエラーとなり困っています

.Sort の行をコメントアウトすると問題なく実行できます。
(2時間ほどはまって困っております…)
間違っている個所をご指摘頂きたいと思いますのでどうぞよろしくお願いいたします。

Excel VBA Sub Connection() Dim con As New ADODB.Connection Dim rs As New ADODB.Recordset Const strFileName = "DB.accdb" con.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & strFileName & ";" rs.CursorLocation = adUseClient Set rs = con.Execute("select * from Q_DB") With rs .Sort = "Gr" .Filter = "Gr >= 1" End With ActiveCell.CopyFromRecordset rs rs.Close con.Close Set rs = Nothing End Sub

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

私もよくわかってないのですみませんが、

rs.CursorLocation = adUseClient
の1行を
Set rs = con.Execute("select * from Q_DB")
の次に入れ替えるか、

もしくは
Withの中に、
「.CursorLocation = adUseClient」として、
「.Sort」の前にもってきたら、

エラーにならないのではないでしょうか?

ダメだったらすみません。

※ご参考URL(Excelのですみませんが・・・)
https://excelwork.info/excel/adosort/

投稿2019/05/05 08:38

komugi3333

総合スコア94

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shigeru

2019/05/05 08:52

ダメでした・・・ エラー 「オブジェクトが開いている場合は、操作は許可されません。」となりました。
komugi3333

2019/05/05 11:27

大変申し訳ございません。 変数宣言で「NEW」してるので「SET=・・・」は要らなかったんですね。気が付いていませんでした。すみません。 なので、ご質問のコードのように「SET」の前に「rs.CursorLocation = adUseClient」を書くこと自体は間違っていなかったのですね。 当方でも(mdbですみませんが)少しテストをしてみましたら、「.CursorLocation = adUseClient」をExceuteのあとにやると、おっしゃるとおり、「オブジェクトが開いている場合は、操作は許可されません。」とエラーになりました。 でも、ということは、「Con」のほうの「Open」のほうは、ご質問のコードで間違ってないということになる気がします。 また、ADOのヘルプを読んでみましたら、「Sourceプロパティ」でSQLを使えるようですから、次のようにしてみたらどうなりますでしょうか? Sub Connection()   Dim con As New ADODB.Connection   Dim rs As New ADODB.Recordset   Const strFileName = "DB.accdb"   con.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & strFileName & ";" '  rs.CursorLocation = adUseClient '  Set rs = con.Execute("select * from Q_DB")   'レコードセットのプロパティの設定   With rs     .Source = "select * from Q_DB"     .CursorLocation = adUseClient     .ActiveConnection = con     .Sort = "Gr"     .Filter = "Gr >= 1"   End With   'レコードセットを開く(Withのなかでやればいいのですが)   rs.Open   ActiveCell.CopyFromRecordset rs   rs.Close   con.Close   Set rs = Nothing End Sub ちなみにですが、(当方では覗きに行くファイルがmdbしか作れなかったのでmdbですみませんが)、以下のコードで「D:\1\tes001.mdb」の「Sheet1」というテーブルのレコードが、並べ替えもフィルタも適用された状態で、Excelのシートに吸い込まれました。 Sub test01()   Dim con As New ADODB.Connection   Dim rs As New ADODB.Recordset '  '変数宣言でNEWすると、このSetが要らないっぽいです。 '  'Newをつけてないときは必要。 '  Set con = New ADODB.Connection      con.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\1\tes001.mdb;" '  '変数宣言でNEWすると、このSetが要らないっぽいです。 '  'Newをつけてないときは必要。 '  Set rs = New ADODB.Recordset      'レコードセット自体はNEWですでにできているっぽいので、   'Openする前に各プロパティを設定する。   'SQLはExceuteする以外に、   '.Sourceプロパティで設定しても良いっぽいです。   With rs     .Source = "select * from Sheet1;"     .ActiveConnection = con     .CursorLocation = adUseClient     .Sort = "金額 DESC"     .Filter = "金額 >= 15000"   End With      '※ ADOのヘルプには、   '『Source プロパティには、Command オブジェクト変数、   'SQL ステートメント、ストアド プロシージャ、   'またはテーブル名を設定できます。』とありました。   '「.CursorLocation = adUseClient」   'を、Openした後に実行すると、当方も   '「オブジェクトが開いている場合は、操作は許可されません。」   'となりました。Excelも同じかもしれません。   'ので、SortなどもまとめてOpenやの前にやったほうが   'いいのかもしれません。         'レコードセットを開く(Withの中でやってもいいのですが)   rs.Open   ActiveCell.CopyFromRecordset rs   rs.Close   con.Close   Set rs = Nothing    End Sub
komugi3333

2019/05/05 11:32

ごめんなさい。   '「.CursorLocation = adUseClient」   'を、Openした後に実行すると、当方も   '「オブジェクトが開いている場合は、操作は許可されません。」   'となりました。Excelも同じかもしれません。   'ので、SortなどもまとめてOpenやの前にやったほうが   'いいのかもしれません。 は   '「.CursorLocation = adUseClient」   'を、Openした後に実行すると、当方も   '「オブジェクトが開いている場合は、操作は許可されません。」   'となりました。   'Exceuteも同じかもしれませんので、   'SortなどはまとめてOpenやExceuteの前にやったほうが   'いいのかもしれません。 の誤りでした。
komugi3333

2019/05/05 11:34

何度もすみません。 最初のコードのほうは '  rs.CursorLocation = adUseClient '  Set rs = con.Execute("select * from Q_DB") の2行は不要なのでコメントアウトしてあります。
komugi3333

2019/05/05 11:57

結局、最初の回答された方と同じこと言ってるだけでした。申し訳ございませんでした。
shigeru

2019/05/05 11:57

ご丁寧にありがとうございます。 下記のコードで試してみましたが、やはりOpen でエラーとなります。 こうなるとコードの問題ではなく、Access側のデータと何らかの関係があるのでしょうか・・・ ただ、下の二つ目に記載しましたコードだと問題なく取込みができています。 Sub Openでエラーとなるコード() Dim con As New ADODB.Connection Dim rs As New ADODB.Recordset ' Connection Open Const strFileName = "確定DB.accdb" con.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & strFileName & ";" With rs .Source = "select * from Q_DB;" .ActiveConnection = con .CursorLocation = adUseClient .Sort = "Gr" .Filter = "Gr >= 1" .Filter = "年月 >= 201804" .Open End With ActiveCell.CopyFromRecordset rs, , 20 rs.Close con.Close Set rs = Nothing End Sub ----------------------------------------------------------------- 下記のコードは問題なく取り込めます。 Sub 実行可能なコード() Dim con As New ADODB.Connection Dim rs As New ADODB.Recordset ' Connection Open Const strFileName = "確定DB.accdb" con.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & strFileName & ";" Set rs = con.Execute("select * from Q_DB ORDER BY Gr,年月") With rs .Filter = "Gr >= 1" .Filter = "年月 >= 201804" End With ActiveCell.CopyFromRecordset rs, , 20 rs.Close con.Close Set rs = Nothing End Sub
komugi3333

2019/05/05 12:46

すみません!お恥ずかしながら、私もプログラミング初心者レベルなので詳しいことはわからないのですが・・・・ エラーメッセージの内容が最初のご回答をされたかたの時と同じでしたら、そのメッセージでGoogle検索してみましたら、日付型のフィールドの話や、以下のようなお話が出てきました。 https://blog.wakisaka-tsuyoshi.com/2013/03/adodbefail.html ここには .CursorLocation = adUseClient を .CursorLocation = adUseServer に変えるとうまくいったとあります。 一度試してみてはいかがでしょうか? あと、 https://docs.microsoft.com/ja-jp/sql/ado/reference/ado-api/open-method-ado-recordset?view=sql-server-2017 に、ADOの「Recordsetの」Openのヘルプがありますので、カーソルタイプ?のこととかも関係あるのかもしれません。 adUseServerやadUseClientなど、「CursorLocationEnum」についてはこちらに説明がありました。 https://docs.microsoft.com/ja-jp/sql/ado/reference/ado-api/cursorlocationenum?view=sql-server-2017 ヘルプはなかなか意味の把握がむずかしいですが、質問を作るときなどにもヒントになるかもしれません。 もともと、 「Connectionオブジェクト」用のメソッドの「Execute」と 「Recordsetオブジェクト」用のメソッドの「Open」 という違いもありますので、その2つの違いも調べる必要が恐らくですが、あるのではないかという気がします。 大した回答ができずにすみません。
shigeru

2019/05/05 13:08

色々と調べて頂きましてありがとうございました。じっくり一つ一つ調べてみる必要がありそうですね。とても助かりました!
komugi3333

2019/05/05 13:12

「ado recordset sort vba」でGoogle検索して、 https://tonari-it.com/excel-vba-access-recordset-sort/#toc5 がヒットしたので見てみましたら .CursorLocation = adUseClient は Openの前にやらないといけないっぽいですが、 Sort はOpenのあとにやってもいいようです。 こちらのテストでも(またもやmdbですみませんが)大丈夫でした。 FilterもOpenのあとで大丈夫でした。 なので、 With rs .Source = "select * from Q_DB;" .ActiveConnection = con .CursorLocation = adUseClient .Open .Sort = "Gr" .Filter = "Gr >= 1" .Filter = "年月 >= 201804" End With とOpenをWithの中の中間地点にもってきたらどうなるでしょうか? なので、 ActiveCell.CopyFromRecordset rs, , 20 の直前にやったらエラーはどうなりますでしょうか? Sortだけ
shigeru

2019/05/06 12:53

ようやく下記のコードでSort が実行できましたのでご報告いたします。 結果から言いますと、すいません・・・  Q_DB のデータに「#Num」のエラーデータが入っていたことが原因でした。  教えて頂いたサイトを参考に.Sortの行を変えてみたり、試したのですが実行できなかったので、データ側の問題を疑い、対象のSource(テーブルやクエリ)を色々と変えて検証しました。すると問題なく実行できるケースがあることが分かり、データの[#Num]が原因であることにたどり着きました。  また因みにですが、Accessのクエリ側で[ Like "*2" ] などワイルドカードを使っていると、コードは問題なく実行できるのですが取得レコード数が0件になってしまうことが分かりました(Access側のクエリはシンプルにしておいた方がよさそうです…)  .Sort は .Open の前後どちらでも実行可能でした^^ コードの質問をしていたにも関わらずデータ側の問題があり申し訳ありませんでした・・・。 Sub ようやく解決() Dim con As New ADODB.Connection Dim rs As New ADODB.Recordset Const strFileName = "DB.accdb" con.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & strFileName & ";" With rs .Source = "select * from Q_DB;" .ActiveConnection = con .CursorLocation = adUseClient .Filter = "Gr >= 1" .Filter = "年月 >= 201804" .Sort = "Gr" .Open End With ActiveCell.Offset(1).CopyFromRecordset rs, , 20 rs.Close con.Close Set rs = Nothing End Sub
komugi3333

2019/05/06 16:29

わ!良かったですね!! 私もほんとう、まだちゃんと色々わかってないので・・・ そのくせ回答などしてしまい・・・ でもほんとうによかったです。 お話をお聞きして、なるほど~と思いました。 逆に私も勉強になりました。ありがとうございました。^^
guest

0

Accessがある環境にてサンプルを作成し実行してわかったこと。

Sortのプロパティは使えない仕様である。

VBA

1Sub test1() 2 Dim cnn As ADODB.Connection 3 Dim rst As ADODB.Recordset 4 Dim strProvider As String 5 Dim strDataSource As String 6 Dim strSQL As String 7 8 9 Set cnn = CreateObject("ADODB.Connection") 10 strProvider = "Provider=Microsoft.ACE.OLEDB.12.0;" 11 strDataSource = "Data Source=C:\DATA\Access\db1.accdb;" 12 cnn.Open strProvider & strDataSource 13 14 Set rst = New ADODB.Recordset 15 With rst 16 .CursorLocation = adUseServer 17 .CursorType = adOpenForwardOnly 18 .LockType = adLockReadOnly 19' .Sort = "[f1]" 20 .Filter = "f3='日本'" 21 End With 22 23 rst.Open "select * from qry_SampleData1", cnn, , , adCmdText 24 25 Application.ActiveCell.CopyFromRecordset rst 26 27 rst.Close 28 Set rst = Nothing 29 cnn.Close 30 Set cnn = Nothing 31 32End Sub

これで、.Sortプロパティをコメントアウトするとすんなり実行できます。
外さず実行すると、
「実行時エラー '3251' 現在のプロバイダー並べ替え、またはフィルタリングに必要なインターフェイスをサポートしていません。」と素直にメッセージボックスっが表示されます。
ということは、もともと使えない機能を使おうとしていることです。

並べ替えは、Access側で事項するか、Excelにデータを代入した後に、ExcelのSortメソッドで実行するかの2択だと思います。

投稿2019/05/05 09:59

kai_keitai

総合スコア344

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shigeru

2019/05/05 10:19

私も最初は Access VBA が可能でExcel VBA では使用できないのかと思ったのですが、複数のサイト上にExcel VBA で紹介されているので実行可能かと思いました。
guest

0

rs.CursorLocation = adUseClient Set rs = con.Execute("select * from Q_DB")

という順番が気になりますね。con.Executeで新しいRecordSetオブジェクトが返されているんじゃないでしょうか。

上記2行を消して

With rs .Source = "Q_DB" .CursorLocation = adUseClient .Sort = "Gr" .Filter = "Gr >= 1" .Open End With

とかしてみては。

投稿2019/05/05 08:37

kabao

総合スコア648

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shigeru

2019/05/05 09:04 編集

ありがとうございます。記載いただいたコードで .Sort 行は実行できました。しかし、.Open 行でエラー「この操作を実行するために接続を実行できません。このコンテキストで閉じているかあるいは無効です。」となりました。
kabao

2019/05/05 09:07

あら失礼。Withの中に .ActiveConnection = con も必要かもしれません。
shigeru

2019/05/05 09:15 編集

入れてみましたら違う .Open 実行でエラーが返ってきました。 「データプロバイダーまたはほかのサービスが E_FAIL 状態を返しました。」初めて見るエラーです・・・。
kabao

2019/05/05 10:15

Errオブジェクトや、con.Errorsから、詳細な理由が取得できるかもしれません。
guest

0

Set rs = con.Execute("select * from Q_DB")
のSQL文にソートと抽出条件をつけ足せばいいのではと思います。

Set rs = con.Execute("select * from Q_DB as a where a.Gr>=1 order by a.Gr")

Accessが無いのでテストはしていないのですが、この程度でしたら、SQL文に全部条件を入れた方が良いと思います。

投稿2019/05/05 08:35

kai_keitai

総合スコア344

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shigeru

2019/05/05 08:59

おっしゃる通りSQL文でやってしまえばいいのですが、実際にはこんないにシンプルな抽出条件ではないため Recordset で実行したいと思っています。
Nor-Xor

2021/03/23 14:14 編集

今質問と回答を眺めていて感じたことを書きます。 私も最初、Recordsetの並び替えや抽出で悩みまくりました。 何をどういうふうに抽出したいのかがわからないので確定的なことは書けませんが、私は条件からSQLを自動生成するプログラムを別で組んで、パラメータ渡しだけで済むようにしました。 最終的にはSQLのコマンドを勉強したら驚くほど短い命令で済むことが多く、自力で作ったほうが速いしムダがないことがわかるのですが。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問