Excel BOF或EOF为true,无法获取OLEObjects属性
我正在编写一个函数,它以起始行、结束行、列和字符串值作为输入。然后,该函数使用字符串值查询数据库,以获得与以下查询匹配的结果列表。从这里开始,从开始到最后的每一行都将添加一个组合框,并填充结果查询数据 当我试着运行这段代码时,它会以以下几种方式之一失败。以下是我的错误:Excel BOF或EOF为true,无法获取OLEObjects属性,excel,vba,Excel,Vba,我正在编写一个函数,它以起始行、结束行、列和字符串值作为输入。然后,该函数使用字符串值查询数据库,以获得与以下查询匹配的结果列表。从这里开始,从开始到最后的每一行都将添加一个组合框,并填充结果查询数据 当我试着运行这段代码时,它会以以下几种方式之一失败。以下是我的错误: 运行时错误'1021:BOF或EOF为真,或者当前记录已被删除。请求的操作需要当前记录。 或 无法获取工作表类的OLEObjects属性。 它有时适用于添加组合的第一列,只在第二列中途失败 调用函数: For i = 0 To
运行时错误'1021:BOF或EOF为真,或者当前记录已被删除。请求的操作需要当前记录。
或
无法获取工作表类的OLEObjects属性。
它有时适用于添加组合的第一列,只在第二列中途失败
调用函数:
For i = 0 To numMembers - 1
For j = 0 To UBound(toolNames) - 1
Call AddCombos(5 + j * 5, 9 + j * 5, 5 + i * 5, Cells(5 + j * 5, 1).value)
Next j
Next i
Function AddCombos(ByVal startRow As Integer, ByVal LastRow As Integer, ByVal columnNum As Integer, ByVal Tool As String)
Dim MyLeft As Double
Dim MyTop As Double
Dim MyHeight As Double
Dim MyWidth As Double
Dim cnn As New ADODB.Connection
Dim rst As New ADODB.Recordset
Dim curcombo As Object
Dim StrDBPath As String
strSQL = "SELECT qryCurrent.txtLevel AS [Current], [qrylstNames-LPMi].strFullName as [Full Name], tblWCMTools.txtWCMTool" & vbNewLine & _
"FROM (((tblPeopleWCMSkillsByYear" & vbNewLine & _
"LEFT JOIN tblSkillLevels AS qryCurrent ON tblPeopleWCMSkillsByYear.bytCurrentID = qryCurrent.atnSkillLevelID)" & vbNewLine & _
"INNER JOIN [qrylstNames-LPMi] ON tblPeopleWCMSkillsByYear.intPeopleID = [qrylstNames-LPMi].atnPeopleRecID)" & vbNewLine & _
"INNER JOIN tblWCMTools ON tblPeopleWCMSkillsByYear.intWCMSkillID = tblWCMTools.atnWCMToolID)" & vbNewLine & _
"WHERE (((tblPeopleWCMSkillsByYear.bytYearID)=Year(Date())-2012) AND qryCurrent.txtLevel >='4' AND tblWCMTools.txtWCMTool = '" & Tool & "') ORDER BY strFullName;"
'database path
StrDBPath = "C:\Users\T6050R0\Desktop\WCMDB_be.accdb"
'open database
cnn.Open "Provider=Microsoft.Ace.OLEDB.12.0;" & _
"Data Source=" & StrDBPath & ";" & _
"Jet OLEDB:Engine Type=5;" & _
"Persist Security Info=False;"
rst.Open strSQL, cnn, adOpenStatic
'Iterate through each row
For i = startRow To LastRow
'If it's empty, than add a checkbox
If IsEmpty(Cells(i, columnNum)) Then
If (Cells(i, columnNum).ColumnWidth <> 20) Then
Cells(i, columnNum).ColumnWidth = 20
End If
'set position of checkbox (compared with cell that will be linked)
MyLeft = Cells(i, columnNum).Left
MyTop = Cells(i, columnNum).Top + 2.75
'set size of checkbox (compared with cell that will be linked)
MyHeight = Cells(i, columnNum).Height - 5
MyWidth = Cells(i, columnNum).Width
'add checkbox
Set curcombo = ActiveSheet.OLEObjects.Add(ClassType:="Forms.ComboBox.1", Link:=True, _
DisplayAsIcon:=False, Left:=MyLeft, Top:=MyTop, Width:=MyWidth, Height _
:=MyHeight + 1.5)
'Add a blank option first
curcombo.Object.AddItem ""
With Worksheets("Sheet1").OLEObjects(curcombo.Name)
.LinkedCell = Cells(i, columnNum).Address
'Move to first record in set
If (i > startRow) Then
MsgBox "yay"
rst.MoveFirst
End If
'add choices to dropdown
For k = 1 To rst.RecordCount
If rst.EOF Then
GoTo EndForLoop
End If
.Object.AddItem rst![Full Name]
If Not rst.EOF Then
rst.MoveNext
Else
GoTo EndForLoop
End If
Next k
EndForLoop:
End With
End If
Next i
End Function
添加组合功能:
For i = 0 To numMembers - 1
For j = 0 To UBound(toolNames) - 1
Call AddCombos(5 + j * 5, 9 + j * 5, 5 + i * 5, Cells(5 + j * 5, 1).value)
Next j
Next i
Function AddCombos(ByVal startRow As Integer, ByVal LastRow As Integer, ByVal columnNum As Integer, ByVal Tool As String)
Dim MyLeft As Double
Dim MyTop As Double
Dim MyHeight As Double
Dim MyWidth As Double
Dim cnn As New ADODB.Connection
Dim rst As New ADODB.Recordset
Dim curcombo As Object
Dim StrDBPath As String
strSQL = "SELECT qryCurrent.txtLevel AS [Current], [qrylstNames-LPMi].strFullName as [Full Name], tblWCMTools.txtWCMTool" & vbNewLine & _
"FROM (((tblPeopleWCMSkillsByYear" & vbNewLine & _
"LEFT JOIN tblSkillLevels AS qryCurrent ON tblPeopleWCMSkillsByYear.bytCurrentID = qryCurrent.atnSkillLevelID)" & vbNewLine & _
"INNER JOIN [qrylstNames-LPMi] ON tblPeopleWCMSkillsByYear.intPeopleID = [qrylstNames-LPMi].atnPeopleRecID)" & vbNewLine & _
"INNER JOIN tblWCMTools ON tblPeopleWCMSkillsByYear.intWCMSkillID = tblWCMTools.atnWCMToolID)" & vbNewLine & _
"WHERE (((tblPeopleWCMSkillsByYear.bytYearID)=Year(Date())-2012) AND qryCurrent.txtLevel >='4' AND tblWCMTools.txtWCMTool = '" & Tool & "') ORDER BY strFullName;"
'database path
StrDBPath = "C:\Users\T6050R0\Desktop\WCMDB_be.accdb"
'open database
cnn.Open "Provider=Microsoft.Ace.OLEDB.12.0;" & _
"Data Source=" & StrDBPath & ";" & _
"Jet OLEDB:Engine Type=5;" & _
"Persist Security Info=False;"
rst.Open strSQL, cnn, adOpenStatic
'Iterate through each row
For i = startRow To LastRow
'If it's empty, than add a checkbox
If IsEmpty(Cells(i, columnNum)) Then
If (Cells(i, columnNum).ColumnWidth <> 20) Then
Cells(i, columnNum).ColumnWidth = 20
End If
'set position of checkbox (compared with cell that will be linked)
MyLeft = Cells(i, columnNum).Left
MyTop = Cells(i, columnNum).Top + 2.75
'set size of checkbox (compared with cell that will be linked)
MyHeight = Cells(i, columnNum).Height - 5
MyWidth = Cells(i, columnNum).Width
'add checkbox
Set curcombo = ActiveSheet.OLEObjects.Add(ClassType:="Forms.ComboBox.1", Link:=True, _
DisplayAsIcon:=False, Left:=MyLeft, Top:=MyTop, Width:=MyWidth, Height _
:=MyHeight + 1.5)
'Add a blank option first
curcombo.Object.AddItem ""
With Worksheets("Sheet1").OLEObjects(curcombo.Name)
.LinkedCell = Cells(i, columnNum).Address
'Move to first record in set
If (i > startRow) Then
MsgBox "yay"
rst.MoveFirst
End If
'add choices to dropdown
For k = 1 To rst.RecordCount
If rst.EOF Then
GoTo EndForLoop
End If
.Object.AddItem rst![Full Name]
If Not rst.EOF Then
rst.MoveNext
Else
GoTo EndForLoop
End If
Next k
EndForLoop:
End With
End If
Next i
End Function
函数AddCombos(ByVal startRow为整数,ByVal LastRow为整数,ByVal columnNum为整数,ByVal Tool为字符串)
将我的左半身变暗为双半身
将我的上衣调暗为双色
我的身高是双倍
将MyWidth设置为双精度
将cnn设置为新的ADODB.连接
将rst设置为新ADODB.Recordset
Dim curcombo作为对象
作为字符串的Dim StrDBPath
strSQL=“选择qryCurrent.txtLevel作为[Current],[qrylstNames LPMi].strFullName作为[Full Name],tblWCMTools.txtWCMTool”&vbNewLine&_
“FROM”((TBLPeopelewcmskillsbyyear)和vbNewLine&_
“在tblPeopleWCMSkillsByYear.bytCurrentID=qryCurrent.atnSkillLevelID上将TblSkillLevel作为qryCurrent左连接”&vbNewLine&_
“tblPeopleWCMSkillsByYear.intPeopleID=[qrylstNames LPMi].atnPeopleRecID]上的内部联接[qrylstNames LPMi]”&vbNewLine&_
“TblPeoplewcmsskillsbyyear.intWCMSkillID=tblWCMTools.atnWCMToolID上的内部联接tblWCMTools”&vbNewLine&_
“其中((tblpeoplewcsmskillsbyyear.bytYearID)=年(日期())-2012)和qryCurrent.txtLevel>='4'和tblwcmtool.txtWCMTool='”&Tool&“)按strFullName排序;”
'数据库路径
StrDBPath=“C:\Users\T6050R0\Desktop\WCMDB_be.accdb”
"开放数据库",
cnn.Open“Provider=Microsoft.Ace.OLEDB.12.0;”_
“数据源=”&StrDBPath&“;”&_
“喷气式OLEDB:发动机类型=5;”和_
“持久化安全信息=False;”
rst.打开strSQL、cnn、adOpenStatic
'遍历每一行
对于i=开始到最后一行
'如果为空,则添加复选框
如果是空的(单元格(i,columnNum)),那么
如果(单元格(i,columnNum).ColumnWidth 20),则
单元格(i,columnNum)。ColumnWidth=20
如果结束
'设置复选框的位置(与将链接的单元格进行比较)
MyLeft=单元格(i,columnNum).Left
MyTop=单元格(i,columnNum).Top+2.75
'设置复选框的大小(与将链接的单元格相比)
MyHeight=单元格(i,columnNum)。高度-5
MyWidth=单元格(i,columnNum).Width
'添加复选框
设置curcombo=ActiveSheet.OLEObjects.Add(类类型:=“Forms.ComboBox.1”,链接:=True_
DisplayAsIcon:=False,左:=MyLeft,Top:=MyTop,Width:=MyWidth,Height_
:=我的身高+1.5)
'首先添加一个空白选项
curcombo.Object.AddItem“”
带有工作表(“Sheet1”).OLEObjects(curcombo.Name)
.LinkedCell=单元格(i,columnNum).Address
'移动到集合中的第一条记录
如果(i>startRow)那么
MsgBox“耶”
rst.MoveFirst
如果结束
'将选项添加到下拉列表
对于k=1到rst.RecordCount
如果rst.EOF,则
转到EndForLoop
如果结束
.Object.AddItem rst![全名]
如果不是rst.EOF,则
rst.MoveNext
其他的
转到EndForLoop
如果结束
下一个k
EndForLoop:
以
如果结束
接下来我
端函数
希望这能比我的评论解释得更多:GetDatabaseReference函数只返回对数据库的引用-它将根据Excel版本更改引用 TestDatabaseConnection过程的重要一点是打开记录集后的代码——它会在遍历记录然后关闭记录集之前检查一切是否正常
Sub TestDatabaseConnection()
Dim oDB As Object
Dim rstMyRecordSet As Object
'Just a reference so my SQL will work.
Dim sName As String
sName = "Darren"
'This is the first time the reference runs, so it creates the reference.
Set oDB = GetDatabaseReference(oDB)
'oDB already holds a value now, so it's not created again - just passed straight back.
'No need to add this line - just an example. Usually oDB would be a global variable.
Set oDB = GetDatabaseReference(oDB)
Set rstMyRecordSet = CreateObject("ADODB.RecordSet")
rstMyRecordSet.CursorType = 2
rstMyRecordSet.Open "SELECT ID FROM tbl_TeamMembers WHERE User_Name = '" & sName & "' AND IsActive = TRUE", oDB
'This is the important bit - check you've got records.
If Not rstMyRecordSet Is Nothing Then
With rstMyRecordSet
If Not .EOF And Not .BOF Then
.MoveFirst
Do While Not .EOF
Debug.Print .Fields("User_Name")
.MoveNext
Loop
End If
End With
End If
rstMyRecordSet.Close
Set rstMyRecordSet = Nothing
End Sub
'----------------------------------------------------------------------------------
' Procedure : GetDatabaseReference
' Author : Darren Bartrup-Cook
' Date : 28/05/2015
' Purpose : Sets a reference to the Outlook database.
'-----------------------------------------------------------------------------------
Public Function GetDatabaseReference(ExistingConnection As Object) As Object
Dim cn As Object
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'Only set a reference to the database if it doesn't already exist. '
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
If ExistingConnection Is Nothing Then
Set cn = CreateObject("ADODB.Connection")
Select Case Val(Application.Version)
Case 11
'Access 2003
cn.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=S:\Database\Outlook.mdb"
Case 14
'Access 2010
cn.Open "Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=S:\Database\Outlook.mdb;" & _
"Persist Security Info=False;"
End Select
If Not cn Is Nothing Then
Set GetDatabaseReference = cn
End If
Else
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'oDB already has a reference, so ensure it's maintained. '
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Set GetDatabaseReference = ExistingConnection
End If
End Function
虽然在这种情况下这可能对您没有帮助,但这里有一个关于格式化SQL的建议
Public Sub aa(ByRef a As String, ByVal b As String)
a = a & vbCrLf & b
End Sub
a = ""
aa a, " SELECT CUR.txtLevel AS [Current] "
aa a, " , NLPMi.strFullName AS [Full Name] "
aa a, " , TOOLS.txtWCMTool "
aa a, " FROM ( ( ( tblPeopleWCMSKILLSByYear AS SKILLS"
aa a, " LEFT JOIN tblSkillLevels AS CUR "
aa a, " ON SKILLS.bytCurrentID = CUR.atnSkillLevelID
aa a, " ) "
aa a, " INNER JOIN [qrylstNames-LPMi] AS NLPMi "
aa a, " ON SKILLS.intPeopleID = NLPMi.atnPeopleRecID
aa a, " )"
aa a, " INNER JOIN tblWCMTools AS TOOLS "
aa a, " ON SKILLS.intWCMSkillID = TOOLS.atnWCMToolID"
aa a, " ) "
aa a, " WHERE ( ( (SKILLS.bytYearID) = YEAR(DATE())-2012 ) "
aa a, " AND CUR.txtLevel >= '4' "
aa a, " AND TOOLS.txtWCMTool = 'Tool'"
aa a, " ) "
aa a, " ORDER BY NLPMi.strFullName"
aa a, " ;"
PS我在中使用实用程序将查询生成器中的SQL格式化为这种格式,请指出哪些代码行产生了错误。@MatthewD它没有说明,也没有在后面突出显示这些行。我可以看到几件事-第一件事是在SQL字符串中使用vbNewLine,每行末尾没有空格。例如,我会将SQL中的FROM行更改为“FROM”((tblPeopleWCMSkillsByYear)&\-注意结尾处的空格,没有vbNewLine。我看到的第二件事是,您没有检查是否返回了任何记录-在
rst之后。打开行添加一个检查-如果不是rst.BOF而不是rst.EOF,那么…如果
,则继续代码结尾的其余部分。第三项-'1到rst.RecordCount'并不总是返回正确的记录ct计数。使用DO而不是rst.EOF
循环。@DarrenBartrup Cook感谢您的反馈!我将看看这会如何改变errors@DarrenBartrup-Cook修复了一个错误,但不是无法获取OLEObjects属性….
我明白你关于验证那里是否有记录的意思。这部分解决了我的问题,其他问题r部分问题由Excel开发人员解决,注释:尝试将“替换为工作表(“Sheet1”).OLEObjects(curcombo.Name)”替换为“替换为curcombo.Objec”