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

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

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

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

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

解決済

1回答

6728閲覧

ADODB.Recordset.Filterで実行時エラー3001

woria

総合スコア36

VBA

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

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

0グッド

0クリップ

投稿2020/02/18 01:07

編集2020/02/18 01:31

前提・実現したいこと

ExcelテーブルからSQLでインプットしたRecordsetに対して複数条件でFilterをかけたい

発生している問題・エラーメッセージ

実行時エラー3001 引数が間違った型、許容範囲外、または競合しています。

該当のソースコード

Class:TableOperator

VBA

1 2Dim adoConn As ADODB.Connection 3Dim adoRs As ADODB.Recordset 4 5Private inputTable_ As ListObject 6Private filter_ As String 7 8Private Sub Class_Initialize() 9 Set adoConn = CreateObject("ADODB.Connection") 10 Set adoRs = CreateObject("ADODB.Recordset") 11End Sub 12 13Public Property Set InputTable(Table As ListObject) 14 Set inputTable_ = Table 15 Dim ws As Worksheet: Set ws = Table.Parent 16 With adoConn 17 .Provider = "Microsoft.ACE.OLEDB.12.0" 18 .ConnectionString = "Data Source = " & ThisWorkbook.FullName & _ 19 ";Extended Properties =Excel 12.0;" 20 .Open 21 22 With adoRs 23 .CursorLocation = 3 'adUseClient 24 .CursorType = adOpenStatic 25 .Open "SELECT [従業員CD],[従業員名],[最新所属名],[職種名],[残業時間],[休出時間],[年間残業時間],[年間残業時間] + [年間休出時間] AS [総残業時間] FROM [" & ws.Name & "$" & ws.ListObjects(inputTable_.Name).Range.Address(False, False) & "]", adoConn, adOpenDynamic 26 End With 27 28 End With 29End Property 30 31Public Property Let Filter(ByVal inputValue As String) 32 filter_ = inputValue 33 adoRs.Filter = filter_ 34End Property 35 36

Module1

VBA

1Sub Main() 2 With New TableOperator 3 Set .InputTable = ThisWorkbook.Sheets("DATA").ListObjects(1) 4 .Filter = "(([残業時間] >= 40 AND [残業時間] <= 45) OR ([年間残業時間] >= 350 AND [年間残業時間] <= 360) OR [総残業時間] >= 700) AND 最新所属名 = 'ブロックA'" 5 End With 6End Sub

試したこと

Filterの条件を減らすとエラーが無くなる

  • [総残業時間] >= 700 AND 最新所属名 = 'ブロックA'
    OK
  • ([残業時間] >= 40 AND [残業時間] <= 45) OR ([年間残業時間] >= 350 AND [年間残業時間] <= 360)

OK

  • (([年間残業時間] >= 350 AND [年間残業時間] <= 360) OR [総残業時間] >= 700) AND 最新所属名 = 'ブロックA'

NG

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

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

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

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

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

guest

回答1

0

ベストアンサー

括弧の数があってないから?

SQL

1([年間残業時間] >= 350 AND [年間残業時間] <= 360) OR [総残業時間] >= 700) AND 最新所属名 = 'ブロックA' 23(([年間残業時間] >= 350 AND [年間残業時間] <= 360) OR [総残業時間] >= 700) AND 最新所属名 = 'ブロックA' 4

括弧の数はコピペミスですかね。失礼しました。
MSのドキュメントを見ると、以下のようにあります。

AND と OR の間に優先順位はありません。句はかっこでグループにまとめることができます。ただし、次のように、 OR で句を結合してできた句のグループを、 AND を使ってさらに別の句と結合することはできません。

この条件に合致していそうです。

また同じような問題で困っている人のページではFilerを並べて書くことで解決しています。
次のように書くことで解消できないでしょうか。

VBA

1Sub Main() 2 With New TableOperator 3 Set .InputTable = ThisWorkbook.Sheets("DATA").ListObjects(1) 4 .Filter = "最新所属名 = 'ブロックA'" 5 .Filter = "([残業時間] >= 40 AND [残業時間] <= 45) OR ([年間残業時間] >= 350 AND [年間残業時間] <= 360) OR [総残業時間] >= 700" 6 End With 7End Sub

投稿2020/02/18 01:26

編集2020/02/18 01:58
ttyp03

総合スコア17000

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

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

woria

2020/02/18 01:30

かっこの数は何度か見直しましたが、エラーの解決にはなりませんでした。
ttyp03

2020/02/18 01:59

回答を追記しました。 解決できるかはわかりませんが、ご確認ください。
woria

2020/02/18 02:14

試しましたが、Filterを並べて書いた場合、後から記入したFilterが優先され、先に書かれたFilterの条件が無視されました。 また、SELECTしたRecordsetに対してFilterをかけるのではなく、OpenのSQLの時点でWHERE文を使って検索しようとしましたが、これも複数条件を指定した時にエラーになりました。
woria

2020/02/18 02:16

>AND と OR の間に優先順位はありません。句はかっこでグループにまとめることができます。ただし、次のように、 OR で句を結合してできた句のグループを、 AND を使ってさらに別の句と結合することはできません。 ということであれば、Recordset以外の方法でデータ出力を試してみます。
ttyp03

2020/02/18 02:24

ダメでしたか。 あとは条件の書き方を見直すとかですかね。 ORのグループをANDするのがダメなので、次のような感じにしたらいけるのでは。ちょっと冗長ですが。 .Filter = "([残業時間] >= 40 AND [残業時間] <= 45 AND 最新所属名 = 'ブロックA') OR ([年間残業時間] >= 350 AND [年間残業時間] <= 360 AND 最新所属名 = 'ブロックA') OR ([総残業時間] >= 700 AND 最新所属名 = 'ブロックA')"
woria

2020/02/18 06:52

クラスの汎用性とか諸々無視しましたが、無事解決しました。 adoRs.Open "SELECT [従業員CD],[従業員名],[最新所属名],[職種名],[残業時間],[休出時間],[年間残業時間],[年間残業時間] + [年間休出時間] AS [総残業時間] FROM [" & ws.Name & "$" & ws.ListObjects(inputTable_.Name).Range.Address(False, False) & "] WHERE [残業時間] BETWEEN 40 AND 45 OR [年間残業時間] BETWEEN 350 AND 360 OR [年間残業時間] + [年間休出時間] >= 700;", adoConn, adOpenDynamic と、Open時点でWHERE文を記入し、 .Filter = "最新所属名 = 'ブロックA'" として、WHEREとFilterを両採用することで、無事フィルタ処理ができました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問