再会,
我一直有一些简单的 VBA 的问题。我编写了一个脚本来进行文本查询(没有输入参数,因此没有真正的用户交互、SQL 注入等),针对数据库运行它,然后将其转储到新的工作表中。这是一些开发人员分析的简单一次性,因此功能非常简单。
如果查询返回每一列的值,则没有问题。但是,如果查询中有任何空值(在我的例子中是 ROLLUP() 的结果),整个子例程将在 MoveNext 处失败(注意:不是将空值分配给单元格)。最初,脚本在空行被访问之前就失败了
Range(Cells(2, 1), Cells(rsData.RecordCount + 1, rsData.Fields.Count)).NumberFormat = "@"
对此进行了评论并将其移至逐个单元格,目的是添加检查当前单元格是否为空(迄今为止互联网上最常见的建议)。
查询已使用后端 SQL 编辑器进行验证,并且是正确的。我读过的所有其他文章要么特定于某个产品,要么不适用。那么,问题很简单:应该如何处理 Recordset 中的空值?我想避免删除数据库端的空值,因为这个 sub 用于许多不同的查询,并且不得不用一堆 NVL() 语句来填充我的查询的想法非常令人不快。
提前感谢您的任何帮助。完整代码如下:
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