【发布时间】:2015-11-30 09:00:30
【问题描述】:
所以我有一个包含多个表的访问数据库,用于存储公司的数据。我在 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 为真或当前记录已被删除”。
我的所有其他查询都有此代码,但仅对于此查询,记录集为空。它是我唯一拥有的那种类型的查询(它确实与带有内部连接的查询和表相匹配)。
编辑:
我想知道问题是 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 中却不行。
【问题讨论】:
-
对于 Access 中的此类查询,我倾向于使用命令类型 adCmdTable 而不是 adCmdStoredProce。你可以试试看是否可行。
-
是的,我已经尝试过了,但它不起作用。我现在尝试直接在 Excel 中编写 SQL 语句,这样做时我也得到了一个空记录集。我还简化了 SQL 语句以包含 NO 参数(这样记录集将返回数据库中的所有内容),但记录集为空(EOF 或 BOF 为真)。当我将 SQL 语句粘贴到 ACCESS 的 sql 视图中并执行它时,它工作正常,并且我以表格格式获取所有信息。
-
我经常在数据中发现 NULL 的问题,所以我倾向于在我的查询中放置一个 IFNULL 测试并在这种情况下返回一个空白字符串“”。
标签: excel vba parameter-passing ado recordset