Rowset does not support scrolling backward
adOpenDynamic
is not declared in VBScript and therefore equals Empty
, which gets converted to 0
when you assign the CursorType
property.0
is adOpenForwardOnly
, and forward only does not support moving backwards, an ability the Find
method wants.
You should replace adOpenDynamic
with its literal value:
Recordset.CursorType = 2 'adOpenDynamic
To avoid this class of errors altogether, place Option Explicit
as the first line of your script.
Recordset.Find Error: Rowset does not support scrolling backward with Stored Procedure
The problem lies not in the keys.CursorType
statement, but in the keys.CursorLocation
statement.
I replaced keys.CursorLocation = adUseServer
with keys.CursorLocation = adUseClient
, which immediately resolved the issue.
The working code has become
Private Sub maintablebox_Change()
Dim cnn As ADODB.Connection
Dim keys As ADODB.Recordset
Set cnn = New ADODB.Connection
connstring = "omitted"
cnn.Open connstring
Set keys = New ADODB.Recordset
keys.CursorLocation = adUseClient
query = "EXEC sp_fkeys @fktable_name = 'astAssets'"
keys.Open query, connstring, adOpenDynamic, adLockReadOnly
keys.Find "PKTABLE_NAME = 'astAssetTypes'"
Debug.Print keys.Fields("FKCOLUMN_NAME")
End Sub
I found the solution on this vbforums thread. I noticed the OP using a stored procedure just like I am, so the error code I was presented with may be due to that factor.
I have only limited knowledge of ADODB recordsets, so if someone would be willing to explain why setting the cursorlocation to adUseClient fixed my problem, please be my guest.
VBA rowset does not support fetching backward error with .cursertype adjusted
The problem is caused by using conn.Execute to fill the recordset. Setting the recordset's activeconnection to the ADODB.Connection and using the recordset's open method will fix the issue.
Function ConnectServer() As String()
'Working SQL Server connection
Dim conn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim sConnString As String
Dim strSqlQuery As String
Dim iCols As Long
' Create the connection string.
sConnString = "Provider=SQLOLEDB;Data Source=wait;" & _
"Initial Catalog=what;" & _
"User Id=foo;" & _
"Password=bar;"
' Create the Connection and Recordset objects.
Set conn = New ADODB.Connection
conn.ConnectionString = sConnString
conn.Open
Set rs = New ADODB.Recordset
With rs
.ActiveConnection = conn
.CursorType = adOpenDynamic
.LockType = adLockOptimistic
.Source = "SELECT * FROM b"
.Open
End With
' Check we have data.
If Not rs.EOF Then
rs.MoveLast
Debug.Print rs.RecordCount
'Read into array and cleanup...
End If
End Function
You can use Recordset.GetRows() to fill the array. No need to dim it. GetRows Method (ADO)
How verify if a data exist in a recordset with an external variable? VBA
For DAO, try with:
filter2 = "[Nom] = '" & oLookFullName & "'"
rs.FindFirst filter2
If rs.NoMatch Then
Debug.Print oLookFullName & " is not found."
End If
For ADO, try with:
filter2 = "[Nom] = '" & oLookFullName & "'"
rs.MoveFirst
rs.Find filter2
If rs.EOF Then
Debug.Print oLookFullName & " is not found."
End If
recordset.movefirst Rowset position cannot be restarted
There is usually no reason to MoveFirst
if you have not previously navigated the record set.
The overflow
is unrelated to the database code and is caused by rs!ID
not fitting in a VBA integer
(16 bit) so make temp
a Long
instead (32 bit) and remove MoveFirst
.
XML rowset and MsXML2
Given a table like:
SELECT TOP 5 * FROM [actor.txt]
----------------------------------------------------------------
|actor_id|first_name|last_name |last_update |
| 1|PENELOPE |GUINESS |2/15/2006 4:34:33 AM|
| 2|NICK |WAHLBERG |2/15/2006 4:34:33 AM|
| 3|ED |CHASE |2/15/2006 4:34:33 AM|
| 4|JENNIFER |DAVIS |2/15/2006 4:34:33 AM|
| 5|JOHNNY |LOLLOBRIGIDA|2/15/2006 4:34:33 AM|
----------------------------------------------------------------
in an ADO (classic, tested with version 2.8) accessible database, you
can save the resultset to XML using
oRS.Save sFSpec, adPersistXML
That gives you XML like:
<xml xmlns:s='uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882'
xmlns:dt='uuid:C2F41010-65B3-11d1-A29F-00AA00C14882'
xmlns:rs='urn:schemas-microsoft-com:rowset'
xmlns:z='#RowsetSchema'>
<s:Schema id='RowsetSchema'>
<s:ElementType name='row' content='eltOnly'>
<s:AttributeType name='actor_id' rs:number='1' rs:nullable='true' rs:maydefer='true' rs:writeunknown='true'>
<s:datatype dt:type='i2' dt:maxLength='2' rs:precision='5' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='first_name' rs:number='2' rs:nullable='true' rs:maydefer='true' rs:writeunknown='true'>
<s:datatype dt:type='string' dt:maxLength='45'/>
</s:AttributeType>
<s:AttributeType name='last_name' rs:number='3' rs:nullable='true' rs:maydefer='true' rs:writeunknown='true'>
<s:datatype dt:type='string' dt:maxLength='45'/>
</s:AttributeType>
<s:AttributeType name='last_update' rs:number='4' rs:nullable='true' rs:maydefer='true' rs:writeunknown='true'>
<s:datatype dt:type='dateTime' rs:dbtype='variantdate' dt:maxLength='16' rs:fixedlength='true'/>
</s:AttributeType>
<s:extends type='rs:rowbase'/>
</s:ElementType>
</s:Schema>
<rs:data>
<z:row actor_id='1' first_name='PENELOPE' last_name='GUINESS' last_update='2006-02-15T04:34:33'/>
<z:row actor_id='2' first_name='NICK' last_name='WAHLBERG' last_update='2006-02-15T04:34:33'/>
<z:row actor_id='3' first_name='ED' last_name='CHASE' last_update='2006-02-15T04:34:33'/>
<z:row actor_id='4' first_name='JENNIFER' last_name='DAVIS' last_update='2006-02-15T04:34:33'/>
<z:row actor_id='5' first_name='JOHNNY' last_name='LOLLOBRIGIDA' last_update='2006-02-15T04:34:33'/>
</rs:data>
</xml>
To read that data, start with (local, console) code like:
Dim oFS : Set oFS = CreateObject( "Scripting.FileSystemObject" )
Dim sDDir : sDDir = oFS.GetAbsolutePathName( "..\Data" )
Dim sFSpec : sFSpec = oFS.GetAbsolutePathName( "..\Data\actor.xml" )
Dim oXDoc : Set oXDoc = CreateObject("msxml2.domdocument")
Dim sXPath, ndFnd, ndlFnd, attrX, nIdx
oXDoc.async = False
oXDoc.validateOnParse = False
oXDoc.resolveExternals = False
oXDoc.setProperty "SelectionLanguage", "XPath"
oXDoc.setProperty "SelectionNamespaces", Join( Array( _
"xmlns:s='uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882'" _
, "xmlns:dt='uuid:C2F41010-65B3-11d1-A29F-00AA00C14882'" _
, "xmlns:rs='urn:schemas-microsoft-com:rowset'" _
, "xmlns:z='#RowsetSchema'" _
), " ")
If oXDoc.load(sFSpec) Then
WScript.Echo sFSpec, "looks good."
For Each sXPath In Array( _
"/xml" _
, "/xml/s:Schema" _
, "/xml/rs:data" _
, "/xml/rs:data/z:row[@actor_id=""2""]" _
)
WScript.Stdout.Write "|" & sXPath & "| => "
Set ndFnd = oXDoc.selectSingleNode( sXPath )
If ndFnd Is Nothing Then
WScript.Stdout.WriteLine "not found"
Else
WScript.Stdout.WriteLine "found a(n) " & ndFnd.tagName
End If
Next
WScript.Echo "-----------------------"
'<rs:data>
' <z:row actor_id='1' first_name='PENELOPE' last_name='GUINESS' last_update='2006-02-15T04:34:33'/>
' ...
'</rs:data>
sXPath = "/xml/rs:data/z:row[@actor_id=""3""]"
Set ndFnd = oXDoc.selectSingleNode( sXPath )
If ndFnd Is Nothing Then
WScript.Echo "|", sXPath, "| not found"
Else
For Each attrX In ndFnd.Attributes
WScript.Echo attrX.Name, attrX.Value
Next
End If
WScript.Echo "-----------------------"
sXPath = "/xml/rs:data/z:row"
Set ndlFnd = oXDoc.selectNodes( sXPath )
If ndlFnd Is Nothing Then
WScript.Echo "ndlFnd Is Nothing"
Else
If 0 = ndlFnd.Length Then
WScript.Echo "ndlFnd is empty"
Else
For Each ndFnd In ndlFnd
WScript.Echo TypeName(ndFnd)
For Each attrX In ndFnd.Attributes
WScript.Echo "", attrX.Name, attrX.Value
Next
Next
End If
End If
Else
WScript.Echo "Bingo!"
WScript.Echo oXDoc.parseError.reason
End If
The important steps:
- For developing/testing avoid the extra complexity of using a server;
if cscript readxml.vbs succeeds, it's easy to 'port' the working code
to .asp (and deal with server specific problems separately) - Create an msxml2.domdocument
- Configure it; especially copy the namespaces from the xml tag to the
SelectionNamespaces - Load the file, check for errors
- Specify your XPath expressions (carefully!, try to 'translate' XML from your sample to XPATH)
- Check the results of .selectSingleNode() and .selectNodes()
- Access the attributes holding the data
Related Topics
How to Use a Dynamic Parameter in a in Clause of a JPA Named Query
How to Transform Comma Separated Column into Multiples Rows in Db2
How to Use Alias in Where Clause
How to Get a List Column Names and Datatypes of a Table in Postgresql
How to Batch SQL Statements with Package Database/Sql
How to Quickly Edit Values in Table in SQL Server Management Studio
How to Ignore "Duplicate Key" Error in T-SQL (SQL Server)
Select a Column If Other Column Is Null
Finding Unmatched Records with SQL
Removing Duplicate Rows (Based on Values from Multiple Columns) from SQL Table
Adding Primary Key to SQL View
How to Handle Optional Parameters in SQL Query
Does Assigning Stored Procedure Input Parameters to Local Variables Help Optimize the Query
Selecting Column Names That Have Specified Value
How to Change Db Schema to Dbo