EOF或BOF都为真(记录集为空) - ADO连接Excel VBA / ACCESS

时间:2015-11-30 09:00:31

标签: excel-vba parameter-passing ado eof recordset

所以我有一个包含多个表的访问数据库,我将数据存储在公司中。我在Access中设计了几个查询来提取一些信息。

从Excel VBA,我使用ADO连接连接到Access数据库并拉出存储的查询。我已经好几次这样做了,它运行正常。但是我的一个查询没有返回任何结果:记录集返回“EOF或BOF为真”。

当我在ACCESS中打开查询时,ACCESS会提示我输入参数“GICS_SUB_INDUSTRY_NAME”,如果输入参数,它会返回一个包含值的表。因此,查询在ACCESS中工作正常,但不是从Excel VBA。

以下是查询的SQL语句:

PARAMETERS GICS_SUB_INDUSTRY_NAME Text ( 255 );
SELECT STOCK_STATIC.NAME, Focus_MAXHistoryDate.MaxOfHistory_Date, Focus_MAXHistoryDate.Isin, STOCK_DYNAMIC.CUR_MKT_CAP, STOCK_HIST_IS_BS_CF.BS_TOT_LIAB2, STOCK_HIST_IS_BS_CF.PREFERRED_EQUITY__MINORITY_INT, STOCK_HIST_IS_BS_CF.BS_CASH_NEAR_CASH_ITEM, STOCK_STATIC.GICS_SUB_INDUSTRY_NAME
FROM ((Focus_MAXHistoryDate INNER JOIN STOCK_HIST_IS_BS_CF ON (Focus_MAXHistoryDate.Isin = STOCK_HIST_IS_BS_CF.Isin) AND (Focus_MAXHistoryDate.MaxOfHistory_Date = STOCK_HIST_IS_BS_CF.History_Date)) INNER JOIN STOCK_STATIC ON Focus_MAXHistoryDate.Isin = STOCK_STATIC.ISIN) INNER JOIN STOCK_DYNAMIC ON Focus_MAXHistoryDate.Isin = STOCK_DYNAMIC.Isin
WHERE (((STOCK_STATIC.GICS_SUB_INDUSTRY_NAME)=[GICS_SUB_INDUSTRY_NAME]));

这是我在Excel VBA中的代码:

Sub Pull_Stock_Peers_Leverage()

'define general variables
Dim Connection As ADODB.Connection
Dim Command As ADODB.Command
Dim GICS_SUB_INDUSTRY_NAME As ADODB.Parameter
Dim RecordSetL As ADODB.RecordSet
Dim iField As Integer
Dim Workbook As Excel.Workbook
Set Workbook = Excel.ActiveWorkbook
Dim Start As Excel.Worksheet
Set Start = ActiveWorkbook.Sheets("Start")
Dim GICS4_Range As Excel.Range
Set GICS4_Range = Excel.Range("GICS4_LookUp")

'Open connection to the AMSIR database
Set Connection = New ADODB.Connection
With Connection
    .Provider = "Microsoft.ACE.OLEDB.12.0"
    .Open "N:\Switzerland\Others\_AMSIR_Company_Database\AMSIR_Company_Database.accdb"
End With

'Open command object and pass a parameter (criteria) to the query
'The parameter name should match the parameter clause in the SQL statement?
Set Command = New ADODB.Command
With Command
    .ActiveConnection = Connection
    .CommandText = "Pull_Peers_Leverage"
    .CommandType = adCmdStoredProc
    .Parameters.Append .CreateParameter("GICS_SUB_INDUSTRY_NAME", adVarWChar, adParamInput, Len(GICS4_Range))
    .Parameters("GICS_SUB_INDUSTRY_NAME") = GICS4_Range
End With

'Create recordset by executing the command
Set RecordSetL = New ADODB.RecordSet
RecordSetL.CursorLocation = adUseClient
RecordSetL.CursorType = adOpenStatic
RecordSetL.Open Command

'Write fields from record set
Dim TargetRangeL As Excel.Range
Set TargetRangeL = Start.Range("PEERS_LEVERAGE")
Dim FieldCount As Integer
Dim i, j As Integer

FieldCount = RecordSetL.Fields.Count
i = 28
j = 37
For iField = 1 To FieldCount
    Start.Cells(i + iField, j).Value = RecordSetL.Fields(iField - 1).Name
Next

'Transpose recordset values and paste into array
Dim recArray As Variant
Dim recCount As Long

recArray = RecordSetL.GetRows
recCount = UBound(recArray, 2) + 1

TargetRangeP.Resize(FieldCount, recCount).Value = recArray

Connection.Close

End Sub

所以我确实得到了代码中的记录集,我实际上可以循环到记录集并提取字段名称,但字段没有值,并且变为“BOF或EOF都为真或者当前记录已被删除”。< / p>

我的所有其他查询都有此代码,但仅针对此查询,记录集为空。它是我所拥有的那种类型的唯一查询(它确实匹配查询和具有内部关节的表)。

编辑:

我想知道问题是ADO还是我传递参数的方式所以我决定只将SQL语句传递给ACCESS而不放任何参数;所以我通常应该得到一个包含所有可用值的记录集。

我试过了:

Sub Test1()

Dim Connection As New ADODB.Connection
Dim Command As ADODB.Command
Dim RecordSetUF As New ADODB.RecordSet
Dim Workbook As Excel.Workbook
Set Workbook = Excel.ActiveWorkbook
Dim Start As Excel.Worksheet
Set Start = ActiveWorkbook.Sheets("Start")
Dim GICS4_Range As Excel.Range
Set GICS4_Range = Excel.Range("GICS4_LookUp")

'Open connection to the AMSIR database
Set Connection = New ADODB.Connection
With Connection
'    .Provider = "SQLOLEDB"
    .Provider = "Microsoft.ACE.OLEDB.12.0"
'    .Provider = "Microsoft.Jet.OLEDB.4.0"
    .Properties("Data Source") = "N:\Switzerland\Others\_AMSIR_Company_Database\AMSIR_Company_Database.accdb"
    .Open
End With

'Place sql statement and match it to newly created recordset
Set Command = New ADODB.Command
Command.ActiveConnection = Connection
Set RecordSetUF = New ADODB.RecordSet
Dim sql1 As String
'ACCESS accepts * for empty values but Excel VBA needs % as wild card in an SQL queryIf CompF.Text = "" Then CompF.Text = ""

sql1 = "SELECT STOCK_STATIC.NAME, Focus_MAXHistoryDate.MaxOfHistory_Date, Focus_MAXHistoryDate.Isin, STOCK_DYNAMIC.CUR_MKT_CAP, STOCK_HIST_IS_BS_CF.BS_TOT_LIAB2, STOCK_HIST_IS_BS_CF.PREFERRED_EQUITY__MINORITY_INT, STOCK_HIST_IS_BS_CF.BS_CASH_NEAR_CASH_ITEM, STOCK_STATIC.GICS_SUB_INDUSTRY_NAME FROM ((Focus_MAXHistoryDate INNER JOIN STOCK_HIST_IS_BS_CF ON (Focus_MAXHistoryDate.MaxOfHistory_Date = STOCK_HIST_IS_BS_CF.History_Date) AND (Focus_MAXHistoryDate.Isin = STOCK_HIST_IS_BS_CF.Isin)) INNER JOIN STOCK_STATIC ON Focus_MAXHistoryDate.Isin = STOCK_STATIC.ISIN) INNER JOIN STOCK_DYNAMIC ON Focus_MAXHistoryDate.Isin = STOCK_DYNAMIC.Isin;"

Command.CommandText = sql1
'Debug.Print sql1
'Debug.Print returns an SQL statement that works fine in Access!
Command.Execute

RecordSetUF.Open Command

所以基本上我有一个在ACCESS中工作正常的sql语句,但在excel VBA中没有。

1 个答案:

答案 0 :(得分:0)

您使用的是一种名为“Jet-SQL”的SQL方言,在MS-Access中工作。

您现在使用Jet-SQL在Excel中工作,并且缺少MS-Access主机应用程序为Jet执行的所有操作:

  • 您无权访问VBA本机功能(仅限Jet-SQL) 本机函数,类似于一些的VBA字符串和 类型转换函数)
  • 您无权访问Access编写的VBA函数 开发人员并在MS-Access数据库中全局声明;
  • 在FROM子句中声明的子查询最好是表,或 没有VBA的查询。
  • 星号通配符不会为您静默转换为'%' (我认为你有)

这些事情无声地失败,或者有误导性的错误消息 - “BOF或EOF都是真的或当前记录已被删除” - 而不是你想要的'缺失参数'或'错误的列名'错误...

但是我开始寻找一个空记录集的地方并没有解释是FROM子句:要么是明显的“无MS-Access”问题之一,要么是更为微妙的涉及无法匹配NULL或空字符串 - 这可能是MS-Access包装器在后台管理的另一个问题。

关于Null处理的快速说明:您没有IFNULL或NZ,因此测试IIF(tbl.[Field] IS NULL是您最好的选择。