ms Access: Looping through array of DAO recordsets results in element always being missing - arrays

I have some vba code that 'attempts' to loop through an array of DAO recordsets. When running the loop, I get a runtime error 'Oject required' at rst.MoveFirst. It seems that rst is not properly initialized but I'm not sure how to fix it. Maybe looping through an array of recordsets isnt even possible in this way I have never tried it before. The code runs from a custom class module. There is a bunch more code in the module but most of the important stuff I post below. A couple things I tried:
Set rst to a new recordset instance manually:
Set rst = New DAO.Recordset
Declaring the array outside the loop:
Set recordsets = Array(rstRechenwerte, rstZwischenwerte, rstZutaten)
' Loop through each recordset and insert data into Excel file
For Each rst In recordsets
Setting rst to an open recordset right before rst.MoveFirst:
For Each rst In Array(rstRechenwerte, rstZwischenwerte, rstZutaten)
Set rst = rst.OpenRecordset()
rst.MoveFirst
The three recordsets in the array are properly initialized, set and are not Nothing. I had previously written the code for each of the three recordsets seperately and it works that way. I am aware that I need to change the variable name XLColumn, but thats not really an issue atm. Its probably something bassic but I couldn't figure it out for a while now so I thought I'd just ask.
I am using the following libraries for which references are properly set:
Visual Basic for Applications
Microsoft Access 16.0 Object Library
OLE Automation
Microsoft Office 16.0 Access database engine Object
Library
Microsoft Excel 16.0 Object Library
Microsoft Office 16.0 Object Library
My version of Access:
Microsoft® Access® für Microsoft 365 MSO (Version 2301 Build 16.0.16026.20002) 32 Bit
The code:
Option Compare Database
Option Explicit
Dim xlApp As Object
Dim xlWB As Object
Dim xlSheet As Object
Dim rsRes As DAO.Recordset 'rs of temp table (Output)
Dim rsZwi As DAO.Recordset 'rs of temp table (Zwischenwerte)
Dim rsRec As DAO.Recordset 'rs clone of subform Rechenwerte
Dim Recordset As Recordset
Dim rstRechenwerte As DAO.Recordset 'rs of tblRechenwerte
Dim rstZwischenwerte As DAO.Recordset 'rs of tblZwischenwerte
Dim rstZutaten As DAO.Recordset 'rs of tblZutaten
Dim RezeptID As Integer 'Current form active RezeptID
Dim RechengruppeID As Integer 'Current Form active RechengruppeID
Dim xlColumn As String 'Excel Column of Zutaten
Dim xlLastRow As Long 'Excel last row number after insertion
Dim xlColumn2 As String 'Excel Column one to the right of Zutaten
Dim k As Integer
Dim Export As Boolean 'Export the Excel File
Dim ExclExportPath As String 'Export location as string
Sub Calculate()
'***************************************************************************
'Purpose: Calculate a recipe based on Rechenwerte,
'save them temporarily and display them on a form.
'Inputs: None
'***************************************************************************
'***********************************************************************
' Preparations
'***********************************************************************
'Disable user input
Call mdlMiscFunctions.DisableKeyboardMouse(True)
'Clear temporary data tables for Results and Zwischenwerte
If Not rsRes.EOF Then Call ClearTableOnClose("tblTempResults")
If Not rsZwi.EOF Then Call ClearTableOnClose("tblTempZwischenwerte")
'Prevent prompt to save changes to excel
xlApp.DisplayAlerts = False
xlApp.Visible = False
'***********************************************************************
' Insert Data into Excel File
'***********************************************************************
Dim rst As DAO.Recordset
Dim xlCell As String
Dim xlFormula As String
Dim xlColumn As String
' Loop through each recordset and insert data into Excel file
For Each rst In Array(rstRechenwerte, rstZwischenwerte, rstZutaten)
rst.MoveFirst
If Not rst.EOF Then
Do Until rst.EOF
xlCell = rst!xlCell
xlSheet.Range(xlCell).Value = rst.Fields(1)
If rst.Fields.Count > 2 Then
xlFormula = rst!xlFormula
xlSheet.Range(xlCell).Offset(0, 1).Formula = xlFormula
xlSheet.Range(xlCell).Offset(0, 1).Value = xlSheet.Range(xlCell).Offset(0, 1).Value
Else
xlSheet.Range(xlCell).Offset(0, 1).Value = rst.Fields(2)
End If
rst.MoveNext
Loop
Else
Select Case rst.Name
Case "rstRechenwerte"
MsgBox "Error: Keine Rechenwerte vorhanden!", vbCritical
Case "rstZwischenwerte"
MsgBox "Error: Keine Zwischenwerte vorhanden!", vbCritical
Case "rstZutaten"
MsgBox "Error: Keine Zutaten vorhanden!", vbCritical
End Select
End If
Next rst
Class initialization is the following:
Private Sub Class_Initialize()
'***************************************************************************
'Purpose: Sub for initializing class variables
'Inputs: None
'***************************************************************************
'Values for variables 1 (Neccesary for recordsets)
RezeptID = Forms.frmCalcBatch.RezeptID 'RezeptID on current form
RechengruppeID = Forms.frmCalcBatch.RechengruppeID 'Rechengruppe on Current Form
'Initialize Objects
Set xlApp = CreateObject("Excel.Application")
Set xlWB = xlApp.Workbooks.Add
Set xlSheet = xlWB.Sheets("Tabelle1") 'Set xlSheet to the first sheet in the workbook
Set rsRes = CurrentDb.OpenRecordset("tblTempResults", dbOpenDynaset)
Set rsZwi = CurrentDb.OpenRecordset("tblTempZwischenwerte", dbOpenDynaset)
Set rsRec = Forms.frmCalcBatch.frmSubRechenwerteBox.Form.Recordset.Clone 'rs clone of Rechenwerte subform
Set rstRechenwerte = CurrentDb.OpenRecordset("SELECT Rechenwert, WertBezeichnung, XLCell FROM tblRechenwerte WHERE RechengruppeID = " & RechengruppeID)
Set rstZwischenwerte = CurrentDb.OpenRecordset("SELECT ZWBezeichnung, XLFormula, XLCell FROM tblZwischenwerte WHERE RezeptID = " & RezeptID)
Set rstZutaten = CurrentDb.OpenRecordset("SELECT Zutat, XLFormula, XLCell FROM tblZutaten WHERE RezeptID = " & RezeptID)
'Values for Variables 2 (recordsets neccesary for variables)
xlColumn2 = Split(rstZutaten!xlCell, "1")(0) 'extract excel column denominator for Zutaten
xlColumn2 = Chr(Asc(xlColumn2) + 1) 'Move one column to the right using Asc (A->B etc.)
'Settings:
If Forms.frmCalcBatch.cbExport = True Then
Export = True
ExclExportPath = GetExportPath
Else
Export = False
ExclExportPath = ""
End If
End Sub

You cannot New up a DAO.Recordset, the code will not even compile.
To loop through an array of recordsets, each recordset must initialized before it is added to the array.
For example:
Dim r1 As DAO.Recordset, r2 As DAO.Recordset, r3 As DAO.Recordset
Set r1 = CurrentDb().OpenRecordset("YourTableOrQueryName")
Set r2 = CurrentDb().OpenRecordset("YourTableOrQueryName")
Set r3 = CurrentDb().OpenRecordset("YourTableOrQueryName")
Put the recordsets now in the array.
Dim arr As Variant
arr = Array(r1, r2, r3)
To loop, you need to use a For loop and either access the recordset from the array directly, or declare another recordset variable to hold the iterating recordset.
Through an iterator variable:
Dim r As DAO.Recordset, i As Integer
For i = LBound(arr) To UBound(arr)
Set r = arr(i)
If Not r.EOF Then
r.MoveFirst
Debug.Print r.RecordCount
End If
Next i
Access it directly from the array:
For i = LBound(arr) To UBound(arr)
If Not arr(i).EOF Then
arr(i).MoveFirst
Debug.Print arr(i).RecordCount
End If
Next i
Though I fail to see why you need to have 3 recordsets in memory at the same time. Personally, I would offload the work that needs to be done in the loop to a separate function and pass the recordset as parameter. The function itself would return a success/failed status, so you can take the appropriate action based on the result.
Another approach would be to store the source names in the array, and create the recordset on demand during the loop.
Hope this helps.

Related

Attempting to connect to SQL Server to query data using VBA but running into constant problems. Issues with code?

Here is the VBA code I have in the module:
Private Sub Workbook_Open()
Dim adoDBConn As New ADODB.connection
Dim adoDbRs As New ADODB.Recordset
Dim selectCmd As New ADODB.Command
adoDBConn.Open "Provider=SQLOLEDB;Data Source=LAPTOP-N0CT1GQ5;Initial Catalog=Interest_Analysis;User Id = ***;Password = ***;"
selectCmd.ActiveConnection = adoDBConn
selectCmd.CommandText = "County, cntyvtd, Name, Votes FROM 2020_General_Election_Returns_import_to_SQL"
Set adoDbRs = selectCmd.Execute(, , adCmdText)
Dim cellRange As Range
Set cellRange = Range(Cells(2, 2), Cells(Row.Count, 1)).EntireRow
cellRange.ClearContents
'The Worksheet tab is called "Data"
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Data")
ws.Activate
If adoDbRs.EOF = False Then ws.Cells(2, 2).CopyFromRecordset adoDbRs
ws.Cells(1, 2) = "County"
ws.Cells(1, 3) = "cntyvtd"
ws.Cells(1, 4) = "Name"
ws.Cells(1, 5) = "Votes"
adoDbRs.Close
Set adoDbRs = Nothing
Set selectCmd = Nothing
adoDBConn.Close
Set adoDBConn = Nothing
End Sub
What I'm doing is using an ADODB connection to connect to SQL Server in Microsoft Excel and using VBA code to interact with the server so that the data can populate in an Excel sheet. I got much of the code template from a website, but have been running into a lot of errors and the debugger keeps pointing at different lines. Right now, it's pointing at the Set adoDbRs = selectCmd.Execute() line and saying Incorrect syntax near ',' and it would also go to the If adoDbRs.EOF = False and say Object not found. I might be missing a foundational statement or something I need to start with, so let me know what the issue is. Thank you!
To debug VBA and figure out how to pull SQL server data into an Excel spreadsheet.
This worked fine for me (against Oracle, but SQL server should work the same way)
Private Sub SOTest()
Dim adoDBConn As New adodb.Connection
Dim adoDbRs As adodb.Recordset 'no `New` here
Dim selectCmd As New adodb.Command
Dim ws As Worksheet, f As adodb.Field
Set ws = ThisWorkbook.Worksheets("Data")
adoDBConn.Open "connection string here"
selectCmd.ActiveConnection = adoDBConn
selectCmd.CommandText = "select * from myTable"
Set adoDbRs = selectCmd.Execute(, , adCmdText)
'clear the output range
ws.Range(ws.Cells(1, 2), ws.Cells(ws.Rows.Count, 15)).ClearContents
ResultsToSheet adoDbRs, ws.Cells(1, 2)
ws.Activate
adoDbRs.Close
adoDBConn.Close
End Sub
'Place a recordset contents on a worksheet (incl. headers)
' starting at `rng`
Sub ResultsToSheet(rs As adodb.Recordset, rng As Range)
Dim c As Range, f As adodb.Field
Set c = rng.Cells(1) ' top left
For Each f In rs.Fields
c.Value = f.Name 'write the field header
Set c = c.Offset(0, 1) 'next header cell
Next f
If Not rs.EOF Then
'write the data starting on the next row
rng.Cells(1).Offset(1).CopyFromRecordset rs
End If
End Sub

Encountering Null value while loading record set into the array in Word VBA, throws Invalid use of Null (using ADODB connection with EXCEL)

Most important thing is that the code is written in Word VBA Editor and it's lunched from Word .docm file.
From this Word .docm file I'm connecting into the Excel file (using ADODB connection), which serves as a client database, and I'm reading whole sheet from that file (sheet name = "data") into a dynamic array which will be searched later.
Option Explicit
Private Sub UseADOSelect()
Dim connection As New ADODB.connection
Dim recSet As New ADODB.Recordset 'All the results of the query are placed in a record set;
Dim exclApp As Excel.Application
Dim exclWorkbk As Excel.Workbook
Dim mySheet As Excel.Worksheet
Dim wordDoc As Word.Document
Dim cntCntrl As ContentControl
Dim strPESELfromWord As String
Dim strQuery As String
Dim intWiersz As Integer
Dim intRemainder As Integer
Dim intRow As Integer
Dim arraySize As Long 'previously was integer = -32,768 to 32,767
Dim strSexDigit As String
Dim strArray() As String 'Dim strArray() As Long 'Dim strArray() As String
Dim i As Long
Set wordDoc = Word.ActiveDocument
Debug.Print wordDoc
'Set mySheet = exclApp.ActiveWorkbook.Sheets("sample")
'Debug.Print mySheet.Name
strPESELfromWord = Trim(Selection.Text)
Debug.Print strPESELfromWord
Word.Application.Visible = True
strSexDigit = Mid(strPESELfromWord, 10, 1) 'Extract 10th digit from PESEL number
Debug.Print strSexDigit
intRemainder = strSexDigit Mod 2
Debug.Print intRemainder
connection.Open "Provider = Microsoft.ACE.OLEDB.12.0;Data Source = X:\Roesler\Excel\FW 1\custdb.xlsm;" & _
"Extended Properties=""Excel 12.0 Macro;HDR=YES;IMEX=1;"";" 'now it works
'strQuery = "SELECT * From [Simple$]" '[Simple$] is the table name; in this case it's the sheet name;
strQuery = "SELECT * From [data$]" '[data$] is the table name; in this case it's the sheet name;
When the record set is read from the Excel file I need to write it into VBA array.
The problem I'm encountering is that: when I'm looping through the values in the record set, while loading this record set into the array in Word VBA Editor, Run-time error 94 - Invalid use of Null pops up when the first Null value is drawn from the record set into the array.
'recSet.Open strQuery, connection
recSet.Open strQuery, connection, adOpenStatic ' Or specify adOpenStatic in the Open method directly.
Debug.Print " RecordCount = " & recSet.RecordCount 'https://www.geeksengine.com/article/recordcount-ado-recordset-vba.html
Debug.Print recSet.EOF 'Returns a value that indicates whether the current record position is after the last record in a Recordset object.
'At the moment the value is "False".
Debug.Print recSet.BOF 'The BOF property returns a Boolean value that indicates if the current position in a Recordset object is just before the first record.
'If True, you are at BOF. If False, you are at or beyond the first record, but still inside the Recordset.
If recSet.BOF = True Then
recSet.MoveFirst
End If
'recSet.Open strQuery, connection
'recSet.CursorType = adOpenStatic
Debug.Print " RecordCount = " & recSet.RecordCount 'https://www.geeksengine.com/article/recordcount-ado-recordset-vba.html
arraySize = recSet.RecordCount 'I wanted to assign total number of records to arraySize variable to use it later in ReDim statement.
Debug.Print arraySize
ReDim strArray(1 To arraySize)
For i = 1 To arraySize
strArray(i) = recSet(i) 'Here the code crashes when the first Null value is encountered, during loading data into the array.
Next i
intRow = 2
' For Each cntCntrl In ActiveDocument.ContentControls
' If cntCntrl.Title = "02KlientPelneImie" Then cntCntrl.Range.Text = objExcel.Sheets("data").Cells(intWiersz, 4)
' If cntCntrl.Title = "02KlientNrDowodu" Then cntCntrl.Range.Text = objExcel.Sheets("data").Cells(intWiersz, 9)
' Next
What am I suppose to do with this.
There are empty cells in the Excel sheet I'm connecting to via ADODB connection with EXCEL. Nothing I can do about it.
How can I load a worksheet into a record set and later this record set into an array in Word VBA, while I have Null values inside??

Access VBA - method or data member not found error

I'm new to Access and thank you for reading this first.
I'm exporting a query in Access to a pipe delimited CSV file. The query is from a table which is ODBCed from SQL.
I've been getting for the line dbs.Recordset : Method or data member not found error.
Huge thanks for any suggestion to fix this.
Option Compare Database
Option Explicit
Sub Command12_Click()
Dim dbs As DAO.database
Dim rst As DAO.Recordset
Dim intFile As Integer
Dim strFilePath As String
Dim intCount As Integer
Dim strHold
strFilePath = "C:\temp\TEST.csv"
Set dbs = CurrentDb
Set rst = db.OpenRecordset("T_Export_CSV", dbOpenForwardOnly)
intFile = FreeFile
Open strFilePath For Output As #intFile
Do Until rst.EOF
For intCount = 0 To rst.Fields.Count - 1
strHold = strHold & rst(intCount).Value & "|"
Next
If Right(strHold, 1) = "|" Then
strHold = Left(strHold, Len(strHold) - 1)
End If
Print #intFile, strHold
rst.MoveNext
strHold = vbNullString
Loop
Close intFile
rst.Close
Set rst = Nothing
MsgBox ("Export Completed Successfully")
End Sub
Thank you so so much for your time and please leave any comment below for any clarification if needed. I will try my best to be responsive!
Office 15.0 object library is the one you need to include in the references for O365 objects or Office 2013 Access VBA

Manipulating data from a field with multi-valuable

I have a table with a field containing multi-valuable as shown below:
In the form, I want to let the user enter a NCR_Num in the textbox then using VBA to do some input validation then add it to the "text_Pool" as shown below:
This Text_Pool has the NCR_Num as the control source so if there is a NCR number added or deleted from it, it will automatically update the NCR_Num field.
I am not quite sure how to handle this data type.
In VBA, I cannot obtain the value from the Text_Pool because I think I need to treat it as an array or recordset
Below is an example of me trying the recordset attempt but obviously I am quite confused on what I am doing:
Public Function get_NCR_Num(SCAR_Num As Integer) As Integer()
Dim dbsMain As DAO.Database
Dim rstMain As DAO.Recordset
Dim childRS As Recordset
Dim sSearchField, sCriteria As String
Set dbsMain = CurrentDb
Set rstMain = dbsMain.OpenRecordset("tbl_SCAR", dbOpenDynaset, dbReadOnly)
Set childRS = rstMain!NCR_Num.Value
sSearchField = "[SCAR_Num]"
sCriteria = sSearchField & " = " & [SCAR_Num]
With rstMain
.MoveLast
.FindFirst (sCriteria)
With childRS
Do While (Not .EOF)
MsgBox (childRS!NCR_Num.Value)
.MoveNext
Loop
End With
End With
rstMain.Close
dbsMain.Close
Set rstMain = Nothing
Set dbsMain = Nothing
End Function
Any help will be appreciated!
I misunderstood your question, and have updated the answer with the following code. This should do what you want. Replace the code you have in subroutine 'Command_LinkNCR_Click' with the following.
This will: (a) validate nbr exists; (b) add if not present; (c) remove if present;
WARNING!! This code only addresses the one issue you were trying to overcome. However, it makes an update of the same recordset as you are viewing on the form, so there may be an issue if your form is 'Dirty'.
Give this a try and let me know if you have questions.
Private Sub Command_LinkNCR_Click()
Dim dbs As DAO.Database
Dim rsMain As DAO.Recordset
Dim rsChild As DAO.Recordset
Dim strSQL As String
Dim blnMatch As Boolean
If IsNull(Me.Text_NCR) Or Me.Text_NCR = "" Then
MsgBox "No value entered for NCR_Num", vbOKOnly, "Missing Value"
Exit Sub
End If
blnMatch = False
Set dbs = CurrentDb
' Only need to work on the current record
strSQL = "select * from tbl_SCAR where SCAR_Num = " & Me!SCAR_Num & ";"
Set rsMain = dbs.OpenRecordset(strSQL, dbOpenDynaset)
If rsMain.EOF Then
' Should never happen
Else
Set rsChild = rsMain!NCR_Num.Value
If rsChild.EOF Then ' If no values yet, add this new one
MsgBox "Add item"
Else
Do While Not rsChild.EOF
' See if we have a match...
If Int(rsChild.Fields(0)) = Int(Me.Text_NCR) Then
blnMatch = True
rsChild.Delete ' Delete item
Exit Do
End If
rsChild.MoveNext
Loop
If blnMatch = False Then ' Need to Add it
rsMain.Edit
rsChild.AddNew
rsChild.Fields(0) = Me.Text_NCR
rsChild.Update
rsMain.Update
End If
End If
End If
'rsChild.Close
rsMain.Close
dbs.Close
Set rsMain = Nothing
Set rsChild = Nothing
Set dbs = Nothing
Me.Refresh
End Sub

SQL Server 2008 Import Data Wizard doesnt recognize Integer data for a column

I have an excel sheet with 10 columns with headers. For a column I can have the data as "FF5" or else 620. The sheet name is IODE.
I am trying to import this data from SSIS Import data wizard into the database of table IODE.
On selecting source and destination in the wizard, when I click on PREVIEW DATA in Select Source Tables and Views window, I see the column with 620 as null. After importing this data, the table will have the NULL Instead of 620.
The data type for this column in table is nvarchar(50), I tried many data types like varchar(100), text/..
Only alpha numeric data is accepting.
I didn't write any code for this.. I am just trying to import data from excel sheet to a table.
Please help me in solving this
Thanks
Ramm
Do you mean that you have either FF5 or 620 as the values for that column meaning you have one or the other and nothing else or are there blank fields in that column as well?
I tried reading the excel by using the Excel library reference in VB6.0.
As SSIS Import Wizard treats NUMERIC as NULL when the data is exported to the SQL Table.
This procedure works very well for the data insertion and also for the other database operations.
Private Sub AccessExcelData()
On Error GoTo errHandler
Dim oXLApp As Excel.Application'Declare the object variable
Dim oXLBook As Excel.Workbook
Dim oXLSheet As Excel.worksheet
Dim strFileName As String
Dim lCount As Long
Dim strSCDName As String
Dim strICDName As String
Dim intSource_Index As Integer
Dim strInput_Port As String
Dim strLabel As String
Dim strSDI_CID As String
Dim intWordBitNO As Integer
Dim strFilter_Type As String
Dim strPgroup_Input As String
Dim strParagraph_Input As String
Dim strSQL As String
Dim sConnString As String
Dim cnTest As New ADODB.Connection
Dim rsTempRecordset As New ADODB.Recordset
Dim objDataAccess As New FmmtDataAccess.clsDataAccess
Dim strxmlResult As String
objDataAccess.Intialize ConString
strFileName = App.Path & "\IODE.xls"
sConnString = "Server=uasql\commonsql;Database=accounts;Driver=SQL Server;Trusted_Connection=Yes;DSN=uasql\commonsql"
With cnTest
.ConnectionString = sConnString
.ConnectionTimeout = 4
.CursorLocation = adUseClient
.Open
End With
' Creating part of the excel sheet.
Set oXLApp = CreateObject("Excel.Application")
'Create a new instance of Excel
oXLApp.Visible = False
'Donot Show it to the user
Set oXLBook = oXLApp.Workbooks.Open(strFileName) 'Open an existing workbook
Set oXLSheet = oXLBook.Worksheets(1) 'Work with the first worksheet oXLSheet.Activate
With oXLApp
For lCount = 2 To oXLSheet.UsedRange.Rows.Count
strSCDName = .Cells(lCount, 1).Value
strICDName = .Cells(lCount, 2).Value
intSource_Index = .Cells(lCount, 3).Value
strInput_Port = .Cells(lCount, 4).Value
strLabel = .Cells(lCount, 5).Value
strSDI_CID = .Cells(lCount, 6).Value
intWordBitNO = .Cells(lCount, 7).Value
strFilter_Type = .Cells(lCount, 8).Value
strPgroup_Input = .Cells(lCount, 9).Value
strParagraph_Input = .Cells(lCount, 10).Value
'strSQL = "Insert into XYX () values (strSCDName ..... ) Here any DB related queries can be used
rsTempRecordset.Open strSQL, cnTest, adOpenForwardOnly, adLockReadOnly Next
End With
' Closing part of the excel sheet.
oXLApp.Visible = False 'Donot Show it to the user
Set oXLSheet = Nothing 'Disconnect from all Excel objects (let the user take over)
oXLBook.Close SaveChanges:=False 'Save (and disconnect from) the Workbook
Set oXLBook = Nothing
oXLApp.Quit 'Close (and disconnect from) Excel
Set oXLApp = Nothing
Exit SuberrHandler:
MsgBox Err.Description
Screen.MousePointer = vbNormalEnd Sub
With this procedure the excel records can be read from vb applicatoin and can be inserted into existing table in the SQL database.
Thanks
Ramm

Resources