良い一日、
私は少し単純なVBAで問題を抱えています。テキストクエリ(入力パラメータがないため、実際のユーザー操作やSQLインジェクションなどがない)を取得し、データベースに対して実行して、新しいワークシートにダンプするスクリプトを作成しました。これは、一部の開発者分析では1回限りの単純なものであるため、機能は非常に単純です。
クエリがすべての列の値を返す場合、問題はありません。ただし、クエリにnull値が含まれている場合(私の場合はROLLUP()の結果として)、サブルーチン全体がMoveNextで失敗します(注:セルへのnull値の割り当てではありません)。元々、null行にアクセスする前に、スクリプトは失敗していました。
Range(Cells(2, 1), Cells(rsData.RecordCount + 1, rsData.Fields.Count)).NumberFormat = "@"
これはコメント化され、現在のセルがnullであるかどうかのチェックを追加する目的でセルごとに移動されました(インターネット上で最も一般的な提案)。
クエリはバックエンドSQLエディタを使用して検証されており、正しいです。私が読んだ他のすべての記事は、製品に固有のものであるか、該当しないものです。したがって、問題は単純です。レコードセットでnull値をどのように処理するのでしょうか。このサブは多くの異なるクエリに使用され、クエリに一連のNVL()ステートメントを追加する必要があるという考えは非常に不快であるため、データベース側でnullを削除することは避けたいと思います。
よろしくお願いします。完全なコードは次のとおりです。
Sub runReport(query As String, sheetName As String)
Dim cnDatabase As ADODB.Connection
Dim rsData As ADODB.Recordset
Dim row As Integer
Dim column As Integer
'Create new worksheet
Sheets.Add.Name = sheetName
Excel.Application.Worksheets(sheetName).Select
'Connect to database
Set cnDatabase = New Connection
cnDatabase.ConnectionString = "Provider=OraOLEDB.Oracle;Data Source=DB.EXAMPLE.COM;User ID=FOO;Password=BAR;ChunkSize=1000;FetchSize=100;"
cnDatabase.Open
'Retrieve dataset
Set rsData = New Recordset
Set rsData.ActiveConnection = cnDatabase
rsData.Source = query
rsData.CursorLocation = adUseClient
rsData.CursorType = adOpenStatic
rsData.Open
'Output header row
For column = 1 To rsData.Fields.Count
Cells(1, column).Value = rsData.Fields(column - 1).Name
Rows(1).Font.Bold = True
Next
'Set all fields as text
'Range(Cells(2, 1), Cells(rsData.RecordCount + 1, rsData.Fields.Count)).NumberFormat = "@"
'Output retrieved data from database
row = 2
While Not rsData.EOF
For column = 1 To rsData.Fields.Count
Cells(row, column).NumberFormat = "@"
Cells(row, column).Value = rsData.Fields(column - 1).Value
Next
rsData.MoveNext
row = row + 1
Wend
cnDatabase.Close
End Sub