I am trying to use recordset code to loop through all the fields in a table and debug.print their values and field names in an order you would naturally read the table ie from left to right across columns then onto the row below
I have accomplished what I'm trying to do but only for the first row. This is the code:
Sub RecordSets()
Dim db As Database
Dim rs As Recordset
Dim i As Long
Set db = CurrentDb
Set rs = db.OpenRecordset("tbl1")
For i = 0 To rs.Fields.Count - 1
Debug.Print rs.Fields(i).Name
Debug.Print rs.Fields(i).Value
Next
rs.Close
db.Close
End Sub
Immediate window produces following result:
Category
Clothing
Item
Shirt
Price
5
This is the top row and is exactly as I want. But I cannot get any code to work accomplish this exact same thing for the other rows. I am 99% sure I need to use a Do Until .EOF loop in conjunction with the For...Next loop but I can't get the results whatever I try or I lock access up in an infinite query.
Thanks for your help
Untested:
Sub RecordSets()
Const SEP as String = vbTab
Dim db As Database
Dim rs As Recordset, numFlds As Long
Dim i As Long, s As String, sp as string
Set db = CurrentDb
Set rs = db.OpenRecordset("tbl1")
numFlds = rs.Fields.Count
'print the headers (field names)
For i = 0 To numFlds - 1
s = s & sp & rs.Fields(i).Name
sp = SEP '<< add separator for subsequent items
Next
Debug.Print s
'print the data
sp = "" '<< clear the separator
Do While Not rs.EOF
For i = 0 To numFlds - 1
s = s & sp & rs.Fields(i).Name
sp = SEP
Next
Debug.Print s
rs.MoveNext
Loop
rs.Close
db.Close
End Sub
Related
Here is the full code:
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim frm As Access.Form
Dim i As Long
'For readability
Set frm = Forms!Frm_JobTicket
'Open Tbl_Schedule for adding Schedule Dates
Set db = CurrentDb
Set rs = db.OpenRecordset("Tbl_Schedule", dbOpenDynaset, dbAppendOnly)
'Creates loop for fields 1-14. Sets Date_ScheduledX = Forms!Frm_JobTicket!Txt_DateScheduledX. Runs through Loop then closes recordset
rs.AddNew
For i = 1 To 14
If (Not IsNull(frm("Txt_DateScheduled" & i & "_JobTicket"))) Then
rs("Date_Scheduled" & i) = frm("Txt_DateScheduled" & i & "_JobTicket")
End If
Next i
'Adds in Sales Order Number to Tbl_Schedule
rs!Sales_Order_Number = frm("Sales_Order_Number")
'Adds in Part Number to Tbl_Schedule
rs!Part_Number = frm("Part_Number")
'Adds updates and closes table
rs.Update
rs.Close
'Shows message box to inform the User if item was Scheduled
MsgBox "Item Scheduled."
'Runs Private Sub above. Clears all values from DateScheduled1-14 on Frm_JobTicket to null
ClearFields
'Clears DB and RS to null
Set db = Nothing
Set rs = Nothing
The line that doesn't work is this rs("Date_Scheduled" & i) = frm("Txt_DateScheduled" & i & "_JobTicket"). Sometimes it will run perfectly fine, and other times it gives me an endless flow of 3421 Data type conversion errors. I do not know what could be going wrong, none of the fields have default values, all of the fields in the table side are Date/Time with this same format, and now I am checking for nulls.
Any help would be greatly appreciated!!
Maybe something like
If Len(Me.Txt_DateScheduled & vbNullString) > 0 Then
rs("Date_Scheduled" & i) = frm("Txt_DateScheduled" & i & "_JobTicket")
Else
rs("Date_Scheduled" & i) = ""
End If
This is completely untested, but I think you should get the concept.
I have a table (tblParts) with a PartNumber field (Short Text) which stores 6 digit part numbers for parts belonging to several families. The families are denoted by the first 2 digits of the part number (00, 01, 02, etc).
(NOTE: I did not create this table and am not able to change it at this time)
I need to find gaps in the numbering in order to fill in unused part numbers. If I have a project starting that needs 6 consecutive part numbers in a specific family, I want to find the first unused number in the first gap of that size or greater within that family.
Here is a small subset of the data.
PartNumber
020001
020002
020003
020004
020005
020006
020007
020009
020010
020011
020012
020013
020014
020019
020101
If I needed a single number, the query should find 020008. If I needed 3 numbers, it should find 0200015 and if I needed 10 numbers it should find 020020.
My SQL knowledge is very limited but I am trying to learn. I realize this would be much easier if the information was stored properly but I have no control over it.
I once wrote an article on the subject:
Find and Generate Missing Values in an Access Table
but that will fill up any gap until all new numbers were established. So, that code will need an expansion with an outer loop to ensure juxtaposed numbers at all times.
Private Sub btnSearch_Click()
' Read table/query sequentially to
' record all missing IDs.
' Fill a ListBox with missing values.
' A reference to Microsoft DAO must be
' present.
' Define search table or query.
Const cstrTable As String = "Orders"
Const cstrField As String = "OrderID"
Dim dbs As DAO.Database
Dim rst As DAO.Recordset
Dim lst As ListBox
Dim col As Collection
Dim strSQL As String
Dim strList As String
Dim lngLast As Long
Dim lngNext As Long
Dim lngMiss As Long
strSQL = "Select " & cstrField & "" _
& " From " & cstrTable & _
& " Order By 1;"
Set lst = Me!lstMissing
Set col = New Collection
Set dbs = CurrentDb
Set rst = dbs.OpenRecordset(strSQL)
If rst.RecordCount = 0 Then
'The recordset is empty.
'Nothing to do.
Else
lngLast = rst(cstrField).Value
rst.MoveNext
While rst.EOF = False
lngNext = rst(cstrField).Value
For lngMiss = lngLast + 1 To _
lngNext - 1
col.Add (lngMiss)
Next
lngLast = lngNext
rst.MoveNext
Wend
'Generate next value in sequence.
'Discard if collecting only
'missing values.
col.Add (lngLast + 1)
End If
rst.Close
'Populate list box from collection.
For lngMiss = 1 To col.Count
If Len(strList) > 0 Then
strList = strList & ";"
End If
strList = strList & col(lngMiss)
Debug.Print col(lngMiss)
Next
lst.RowSource = strList
Debug.Print strList
Set rst = Nothing
Set dbs = Nothing
Set col = Nothing
Set lst = Nothing
End Sub
I'm developing an Access database and have some code on a form button that takes the contents of a recordset and exports it to an excel document. The following code works however I have been asked that the export data be reversed on the worksheet.
Set qdef = db.QueryDefs("Inspection_Detail_Crosstab")
qdef![Tag_No_Param] = Tag_Number.Value
Set rs = qdef.OpenRecordset()
EquipmentCellSt = (Col & EquipmentCell)
With wsheet
.Range(EquipmentCellSt).CopyFromRecordset rs
End With
So rather than(as it does right now):
- item 1
- item 2
- item 3
it exports:
- item 3
- item 2
- item 1
I thought a method of doing this would be to:
With wsheet
rs.MoveLast
.Range(EquipmentCellSt).CopyFromRecordset rs
rs.MovePrevious
End With
But adding the MoveLast and MovePrevious just seems to lock up the program.
You can manually export the recordset by iterating through the records in reverse:
Dim rowNum as Long
Dim columnNum As Long
Dim fld As Field
columnNum = 0
rowNum = 0
'stupid client-side sorting, because management
rs.MoveLast
Do While Not rs.BOF
For Each fld In rs.Fields
wsheet.Range(EquipmentCellSt).Offset(rowNum, columnNum).Value = fld.Value
columnNum = columnNum + 1
Next
rowNum = rowNum + 1
columnNum = 0
rs.MovePrevious
Loop
Im using Access 2013 and Excel 2013. In terms of References, I am using Microsoft Office 15.0 Access database engine Object Library.
So I am trying to run an INSERT INTO query from VBA. The worksheet has a list of part numbers, which I used this code to convert into an array.
Function partArray()
Dim partList() As Variant
Dim partArr(10000) As Variant
Dim x As Long
partList = ActiveWorkbook.Worksheets("Parts").ListObjects("Parts").ListColumns("Part Number").DataBodyRange.Value
For x = LBound(partList) To UBound(partList)
partArr(x) = partList(x, 1)
Next x
partArray = partArr
End Function
Now I am trying to use an INSERT INTO query to input these part numbers into a table in access. Any idea how I can do this?
You should use ADO to connect between Excel and Access. It will be a reference under Tools/References in the VBE. Using ADO you can run SQL statements. You can define your table in Excel as the origin table and then read data from that, put them into a recordset and then write the recordset into an Access table. There are plenty of examples on the internet. You can start with this: https://www.exceltip.com/import-and-export-in-vba/export-data-from-excel-to-access-ado-using-vba-in-microsoft-excel.html
Whoa! I think your approach is totally wrong. Try something like this.
Sub ADOFromExcelToAccess()
' exports data from the active worksheet to a table in an Access database
' this procedure must be edited before use
Dim cn As ADODB.Connection, rs As ADODB.Recordset, r As Long
' connect to the Access database
Set cn = New ADODB.Connection
cn.Open "Provider=Microsoft.Jet.OLEDB.4.0; " & _
"Data Source=C:\FolderName\DataBaseName.mdb;"
' open a recordset
Set rs = New ADODB.Recordset
rs.Open "TableName", cn, adOpenKeyset, adLockOptimistic, adCmdTable
' all records in a table
r = 3 ' the start row in the worksheet
Do While Len(Range("A" & r).Formula) > 0
' repeat until first empty cell in column A
With rs
.AddNew ' create a new record
' add values to each field in the record
.Fields("FieldName1") = Range("A" & r).Value
.Fields("FieldName2") = Range("B" & r).Value
.Fields("FieldNameN") = Range("C" & r).Value
' add more fields if necessary...
.Update ' stores the new record
End With
r = r + 1 ' next row
Loop
rs.Close
Set rs = Nothing
cn.Close
Set cn = Nothing
End Sub
Or, this.
Sub DAOFromExcelToAccess()
' exports data from the active worksheet to a table in an Access database
' this procedure must be edited before use
Dim db As Database, rs As Recordset, r As Long
Set db = OpenDatabase("C:\FolderName\DataBaseName.mdb")
' open the database
Set rs = db.OpenRecordset("TableName", dbOpenTable)
' get all records in a table
r = 3 ' the start row in the worksheet
Do While Len(Range("A" & r).Formula) > 0
' repeat until first empty cell in column A
With rs
.AddNew ' create a new record
' add values to each field in the record
.Fields("FieldName1") = Range("A" & r).Value
.Fields("FieldName2") = Range("B" & r).Value
.Fields("FieldNameN") = Range("C" & r).Value
' add more fields if necessary...
.Update ' stores the new record
End With
r = r + 1 ' next row
Loop
rs.Close
Set rs = Nothing
db.Close
Set db = Nothing
End Sub
Of course you could use the TransferSpreadsheet method if you want.
Option Explicit
Sub AccImport()
Dim acc As New Access.Application
acc.OpenCurrentDatabase "C:\Users\Public\Database1.accdb"
acc.DoCmd.TransferSpreadsheet _
TransferType:=acImport, _
SpreadSheetType:=acSpreadsheetTypeExcel12Xml, _
TableName:="tblExcelImport", _
Filename:=Application.ActiveWorkbook.FullName, _
HasFieldNames:=True, _
Range:="Folio_Data_original$A1:B10"
acc.CloseCurrentDatabase
acc.Quit
Set acc = Nothing
End Sub
I have an access database with vba code that is attempting to access an excel sheet and copy the data to a recordset using DAO.recordset. If all of the column (assocId) is integer the import works wonderfully if all are strings it works but if you have a mixed back (eg 111111 | Vinny | etc and then on row two you have JOE-1 | Joe | etc) the import will fail. It says "You cannot record your changes because a value you entered violates the settings defined for this table"
Here is the offending sub:
Public Sub LoadFileInfo()
'Load information from selected file
On Error GoTo ErrorHappened
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim i As Integer
Dim lastTransType As String
Dim transactionCounter As Integer
Dim currentRecord As CurrentImportRecord
Dim wtf As Variant
Set db = CurrentDb()
Set rs = db.OpenRecordset(selectTransTypesSql & GetSetting("PayrollManualImportExportTransactionTypes") & ")")
ReDim transTypes(DCount("TransType", "MasterTransactionTypes", "IsActive <> 0")) As MasterTransactionTypes
rs.MoveFirst
Do While Not rs.EOF
'Add each transaction type and desc to the Private Type and increment the appropriate counter
GetMasterTransactionTypes rs!TransType, rs!TransDesc, i
rs.MoveNext
i = i + 1
Loop
rs.Close
Set db = OpenDatabase(importFileName, False, True, "Excel 12.0;HDR=Yes")
Set rs = db.OpenRecordset("SELECT * FROM " & "[" & GetSheetName(importFileName) & "$]" & " ORDER BY TransType")
rs.MoveLast
importFields = vbNullString
For i = 0 To rs.Fields.count - 1
importFields = importFields & rs.Fields(i).Name & ","
Next
fullImport = (rs.Fields.count > 4)
i = 0
transactionCounter = 1
lblFile.Caption = "File name: " & importFileName
Dim rowNum As Variant
rowNum = rs.RecordCount
wtf = rs.GetRows(rowNum)
ReDim ledgerEntries(rs.RecordCount) As PayrollLedgerImport
'Check to see if the recordset actually contains rows; if so push transaction objects to private type array
rs.MoveFirst
Do While Not rs.EOF
currentRecord.associateId = CStr(rs!assocId)
currentRecord.transactionType = rs!TransType
currentRecord.transactionNotes = CStr(rs!TransNotes)
If lastTransType = CStr(currentRecord.transactionType) Then
transactionCounter = transactionCounter + 1
Else
transactionCounter = 1
End If
If IsValidTransType(currentRecord.transactionType) Then
If Not fullImport Then
currentRecord.transactionAmount = rs!TransAmount
GetPayrollTransactions currentRecord.associateId, currentRecord.transactionType, currentRecord.transactionAmount, currentRecord.transactionNotes, i, transactionCounter
Else
currentRecord.transactionAmount = rs!TransAmt
GetPayrollTransactions currentRecord.associateId, currentRecord.transactionType, currentRecord.transactionAmount, currentRecord.transactionNotes, i, transactionCounter
End If
Else
MsgBox (currentRecord.transactionType & ": Not A Valid Transaction Type")
End If
lastTransType = rs!TransType
rs.MoveNext
i = i + 1
Loop
FormatFileInformationWindow
cmdImportFile.Enabled = True
End Sub
I've been at this for hours. I've tried casting all the columns when I take them in and I get the same issue. Works fine for all ints or all strings but in reality some of our employees have string and some have int for employee ID. I tried taking them all in as string converting where necessary but that didn't work either. Only thing that works is two sheets - one containing strings one containing ints.