I am trying to write some code that uses an excel template to upload data to an access DB. I'm somewhat new to VB so I got the code offline and tailored it to my needs. When I try to run it I am receiving a "Compile error: Do without loop" error message. Please advise as to what I am doing wrong.
All help is greatly appreciated!
Sub UploadtoAccess()
'
' UploadtoAccess Macro
'
'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.ace.oledb.12.0;" & _
"Data Source=C:\Users\filepath (full file path taken out)
' open a recordset
Set rs = New ADODB.Recordset
rs.Open "Expenses", cn, adOpenKeyset, adLockOptimistic, adCmdTable
' all records in a table
r = 2 ' the start row in the worksheet
Do While Len(Range(“A” & r).Formula) > 0
Do While Len(Range(“B” & r).Formula) > 0
Do While Len(Range(“C” & r).Formula) > 0
Do While Len(Range(“D” & 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("Expense_Type_ID") = Range("A" & r).Value
.Fields("Expense_Type") = Range(“B” & r).Value
.Fields(“Expense_Month”) = Range(“C” & r).Value
.Fields(“Expense_Amount”) = Range(“D” & 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
Related
the goal is to import all excel files in one folder to seperate sheets in access. I found this script and didnt know where to ask instead
Dim blnHasFieldNames as Boolean
Dim strWorksheet As String, strTable As String
Dim strPath As String, strPathFile As String
' Change this next line to True if the first row in EXCEL worksheet
' has field names
blnHasFieldNames = False
' Replace C:\Documents\ with the real path to the folder that
' contains the EXCEL files
strPath = "C:\Documents\"
' Replace worksheetname with the real name of the worksheet that is to be
' imported from each file
strWorksheet = "worksheetname"
' Import the data from each workbook file in the folder
strFile = Dir(strPath & "*.xls")
Do While Len(strFile) > 0
strPathFile = strPath & strFile
strTable = "tbl_" & Left(strFile, InStrRev(strFile, ".xls") - 1)
DoCmd.TransferSpreadsheet acImport, _
acSpreadsheetTypeExcel9, strTable, strPathFile, _
blnHasFieldNames, strWorksheet & "$"
' Uncomment out the next code step if you want to delete the
' EXCEL file after it's been imported
' Kill strPathFile
strFile = Dir()
Loop
here: http://www.accessmvp.com/KDSnell/EXCEL_Import.htm#ImpWktFilesSepTbls
I dont get how to use the code(turn it into a macro?) also is it possible to grab the 3rd row eg and take it as header ? Do you know where I can finde information about it ?
Thanks
You could export data from Excel to Access, and start on a specific row.
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, import everything like you are doing now, and run a small delete query on the table after doing the import.
Something like...Delete * from Table Where Field1 is "", or whatever.
The next effect is exactly the same.
UPDATED QUESTION:
I have Update sheet, this sheet contains unique ID that matched the access database ID, I'm trying to update the fields using excel values in "Update" sheet.
The ID is in the Column A the rest of the fields are stored from Column B to R. I'm trying to achieve the below, As follows:
Update the record(values from Column B to R) if Column A (ID) matched existing Access database ID. Then add text in Column S "Updated"
If the Column A (ID) did not found any match in the existing Access database ID, Then add text in Column S "ID NOT FOUND"
Loop to next value
So far, I have the below Sub for Update and Function for Existing ID (Import_Update Module), but I'm getting this error.
Sub Update_DB()
Dim dbPath As String
Dim lastRow As Long
Dim exportedRowCnt As Long
Dim NotexportedRowCnt As Long
Dim qry As String
Dim ID As String
'add error handling
On Error GoTo exitSub
'Check for data
If Worksheets("Update").Range("A2").Value = "" Then
MsgBox "Add the data that you want to send to MS Access"
Exit Sub
End If
'Variables for file path
dbPath = Worksheets("Home").Range("P4").Value '"W:\Edward\_Connection\Database.accdb" '##> This was wrong before pointing to I3
If Not FileExists(dbPath) Then
MsgBox "The Database file doesn't exist! Kindly correct first"
Exit Sub
End If
'find las last row of data
lastRow = Cells(Rows.Count, 1).End(xlUp).Row
Dim cnx As ADODB.Connection 'dim the ADO collection class
Dim rst As ADODB.Recordset 'dim the ADO recordset class
On Error GoTo errHandler
'Initialise the collection class variable
Set cnx = New ADODB.Connection
'Connection class is equipped with a —method— named Open
cnx.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & dbPath
'ADO library is equipped with a class named Recordset
Set rst = New ADODB.Recordset 'assign memory to the recordset
'##> ID and SQL Query
ID = Range("A" & lastRow).Value
qry = "SELECT * FROM f_SD WHERE ID = '" & ID & "'"
'ConnectionString Open '—-5 aguments—-
rst.Open qry, ActiveConnection:=cnx, _
CursorType:=adOpenDynamic, LockType:=adLockOptimistic, _
Options:=adCmdTable
'add the values to it
'Wait Cursor
Application.Cursor = xlWait
'Pause Screen Update
Application.ScreenUpdating = False
'##> Set exportedRowCnt to 0 first
UpdatedRowCnt = 0
IDnotFoundRowCnt = 0
If rst.EOF And rst.BOF Then
'Close the recordet and the connection.
rst.Close
cnx.Close
'clear memory
Set rst = Nothing
Set cnx = Nothing
'Enable the screen.
Application.ScreenUpdating = True
'In case of an empty recordset display an error.
MsgBox "There are no records in the recordset!", vbCritical, "No Records"
Exit Sub
End If
For nRow = 2 To lastRow
'##> Check if the Row has already been imported?
'##> Let's suppose Data is on Column B to R.
'If it is then continue update records
If IdExists(cnx, Range("A" & nRow).Value) Then
With rst
For nCol = 1 To 18
rst.Fields(Cells(1, nCol).Value2) = Cells(nRow, nCol).Value 'Using the Excel Sheet Column Heading
Next nCol
Range("S" & nRow).Value2 = "Updated"
UpdatedRowCnt = UpdatedRowCnt + 1
rst.Update
End With
Else
'##>Update the Status on Column S when ID NOT FOUND
Range("S" & nRow).Value2 = "ID NOT FOUND"
'Increment exportedRowCnt
IDnotFoundRowCnt = IDnotFoundRowCnt + 1
End If
Next nRow
'close the recordset
rst.Close
' Close the connection
cnx.Close
'clear memory
Set rst = Nothing
Set cnx = Nothing
If UpdatedRowCnt > 0 Or IDnotFoundRowCnt > 0 Then
'communicate with the user
MsgBox UpdatedRowCnt & " Drawing(s) Updated " & vbCrLf & _
IDnotFoundRowCnt & " Drawing(s) IDs Not Found"
End If
'Update the sheet
Application.ScreenUpdating = True
exitSub:
'Restore Default Cursor
Application.Cursor = xlDefault
'Update the sheet
Application.ScreenUpdating = True
Exit Sub
errHandler:
'clear memory
Set rst = Nothing
Set cnx = Nothing
MsgBox "Error " & Err.Number & " (" & Err.Description & ") in procedure Update_DB"
Resume exitSub
End Sub
Function to Check if the ID Exists
Function IdExists(cnx As ADODB.Connection, sId As String) As Boolean
'Set IdExists as False and change to true if the ID exists already
IdExists = False
'Change the Error handler now
Dim rst As ADODB.Recordset 'dim the ADO recordset class
Dim cmd As ADODB.Command 'dim the ADO command class
On Error GoTo errHandler
'Sql For search
Dim sSql As String
sSql = "SELECT Count(PhoneList.ID) AS IDCnt FROM PhoneList WHERE (PhoneList.ID='" & sId & "')"
'Execute command and collect it into a Recordset
Set cmd = New ADODB.Command
cmd.ActiveConnection = cnx
cmd.CommandText = sSql
'ADO library is equipped with a class named Recordset
Set rst = cmd.Execute 'New ADODB.Recordset 'assign memory to the recordset
'Read First RST
rst.MoveFirst
'If rst returns a value then ID already exists
If rst.Fields(0) > 0 Then
IdExists = True
End If
'close the recordset
rst.Close
'clear memory
Set rst = Nothing
exitFunction:
Exit Function
errHandler:
'clear memory
Set rst = Nothing
MsgBox "Error " & Err.Number & " :" & Err.Description
End Function
My below code is working fine. I tried to address your above three points in a different way.
##########################
IMPORTANT
1) I have removed your other validations; you can add them back.
2) DB path has been hard coded, you can set it to get from a cells again
3) My DB has only two fields (1) ID and (2) UserName; you will have obtain your other variables and update the UPDATE query.
Below is the code which is working fine to meet your all 3 requests...Let me know how it goes...
Tschüss :)
Sub UpdateDb()
'Creating Variable for db connection
Dim sSQL As String
Dim rs As ADODB.Recordset
Dim cn As ADODB.Connection
Set cn = New ADODB.Connection
cn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\test\db.accdb;"
Dim a, PID
'a is the row counter, as it seems your data rows start from 2 I have set it to 2
a = 2
'Define variable for the values from Column B to R. You can always add the direct ceel reference to the SQL also but it will be messy.
'I have used only one filed as UserName and so one variable in column B, you need to keep adding to below and them to the SQL query for othe variables
Dim NewUserName
'########Strating to read through all the records untill you reach a empty column.
While VBA.Trim(Sheet19.Cells(a, 1)) <> "" ' It's always good to refer to a sheet by it's sheet number, bcos you have the fleibility of changing the display name later.
'Above I have used VBA.Trim to ignore if there are any cells with spaces involved. Also used VBA pre so that code will be supported in many versions of Excel.
'Assigning the ID to a variable to be used in future queries
PID = VBA.Trim(Sheet19.Cells(a, 1))
'SQL to obtain data relevatn to given ID on the column. I have cnsidered this ID as a text
sSQL = "SELECT ID FROM PhoneList WHERE ID='" & PID & "';"
Set rs = New ADODB.Recordset
rs.Open sSQL, cn
If rs.EOF Then
'If the record set is empty
'Updating the sheet with the status
Sheet19.Cells(a, 19) = "ID NOT FOUND"
'Here if you want to add the missing ID that also can be done by adding the query and executing it.
Else
'If the record found
NewUserName = VBA.Trim(Sheet19.Cells(a, 2))
sSQL = "UPDATE PhoneList SET UserName ='" & NewUserName & "' WHERE ID='" & PID & "';"
cn.Execute (sSQL)
'Updating the sheet with the status
Sheet19.Cells(a, 19) = "Updated"
End If
'Add one to move to the next row of the excel sheet
a = a + 1
Wend
cn.Close
Set cn = Nothing
End Sub
You need to put the query inside the loop
Option Explicit
Sub Update_DB_1()
Dim cnx As New ADODB.Connection
Dim rst As New ADODB.Recordset
Dim qry As String, id As String, sFilePath As String
Dim lastRow As Long, nRow As Long, nCol As Long, count As Long
Dim wb As Workbook, ws As Worksheet
Set wb = ThisWorkbook
Set ws = wb.Sheets("Update")
lastRow = ws.Cells(Rows.count, 1).End(xlUp).Row
sFilePath = wb.Worksheets("Home").Range("P4").Value
cnx.open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & sFilePath
count = 0
For nRow = 2 To lastRow
id = Trim(ws.Cells(nRow, 1))
qry = "SELECT * FROM f_SD WHERE ID = '" & id & "'"
Debug.Print qry
rst.open qry, cnx, adOpenKeyset, adLockOptimistic
If rst.RecordCount > 0 Then
' Update RecordSet using the Column Heading
For nCol = 2 To 9
rst.fields(Cells(1, nCol).Value2) = Cells(nRow, nCol).Value
Next nCol
rst.Update
count = count + 1
ws.Range("S" & nRow).Value2 = "Updated"
Else
ws.Range("S" & nRow).Value2 = "ID NOT FOUND"
End If
rst.Close
Next nRow
cnx.Close
Set rst = Nothing
Set cnx = Nothing
MsgBox count & " records updated", vbInformation
End Sub
I'm new on this ADODB thing. I hope my question is not so silly. I open an ADODB connection from an Excel sheet (user interface) to another one ("database"). The code runs perfectly, but sometimes the updated or inserted data won't record in the database sheet. I don't know why and I don't know how to check it to avoid it happen. I do know that if I open the database sheet, save and then close, it works well again. Do someone know the reason for that?
The procedures of the code work well and the Excel VBA debugger does not get any error... Then I post some parts that I believe where the problem might be...
Public cn As ADODB.Connection
Public rst As ADODB.Recordset
Public sSQL As String
Public z, OP, Conf, TempoA, Setor As Double
Public FoundAp, FoundPar As Boolean
Private Sub txtCod_Exit(ByVal Cancel As MSForms.ReturnBoolean)
Set cn = New ADODB.Connection
Set rst = New ADODB.Recordset
If Val(Application.Version) <= 11 Then 'Excel 2003 ou anterior
cn.ConnectionString = _
"Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & EstaPasta_de_trabalho.DbPath & ";" & _
"Extended Properties=Excel 8.0;"
Else 'Excel 2007 ou superior
cn.ConnectionString = _
"Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=" & EstaPasta_de_trabalho.DbPath & ";" & _
"Extended Properties=Excel 12.0 Xml;"
End If
cn.Open
'Instrução Sql:
sSQL = "SELECT * FROM [tb_Db_Ops$] " & _
"WHERE Cod_Apont LIKE " & txtCod & ";"
rst.CursorLocation = adUseServer
rst.Open sSQL, cn, adOpenKeyset, adLockOptimistic, adCmdText
If Not rst.EOF And Not rst.BOF Then
OP = rst!OP
frmApontamento.Visible = True
txtApontA = txtCod.Text
txtOpA = OP
txtEtapa.Text = rst!Etapa
txtDocA = rst!Documento
txtObraA = Mid(rst!Obra, 12)
Setor = CDbl(rst!Setor)
If IsNull(rst!Status) = False Then
Status = rst!Status
End If
If Status = "FINALIZADO" Then
frmMsg.lblMsg.Caption = "OP já finalizada!"
frmMsg.Show
rst.Close
cn.Close
Set rst = Nothing
Set cn = Nothing
Exit Sub
ElseIf Status = "EM EXECUÇÃO" Then
FoundAp = True
FoundPar = False
ElseIf Status = "" Then
FoundAp = False
FoundPar = False
Else
FoundAp = True
FoundPar = True
End If
Else
frmMsg.lblMsg.Caption = "Apontamento NÃO encontrado na Base de Dados! Supervisão notificada! Tente novamente mais tarde!"
frmMsg.Show
Email.ErroBd = True
Email.ErroGrav = False
Email.Proced = "txtCod_Exit"
Call Email_Erros
rst.Close
cn.Close
Set rst = Nothing
Set cn = Nothing
Exit Sub
End If
rst.Close
sSQL = "UPDATE [tb_Apontamentos$] " & _
"SET dt_f = NOW(), dt = NOW() - dt_i " & _
"WHERE Cod_Apont LIKE " & txtApontR & " AND dt_f IS NULL;"
cn.Execute sSQL
Final:
If Not (rst Is Nothing) Then
If rst.State = 1 Then
rst.Close
End If
Set rst = Nothing
End If
If Not (cn Is Nothing) Then
If cn.State = 1 Then
cn.Close
End If
Set cn = Nothing
End If
end sub
It takes some values from userform textboxes. It runs on a 2013 32 bits Excel version in Windows 10. The Microsoft ActiveX Data Objects 6.1 and Microsoft ActiveX Data Objects Recordset 6.0 libraries are activated. The interface is .xlsm and database is .xlsx
It sounds like you are trying to import data from a closed workbook. I haven't tried this in quite a while, but it sounds like the Macro Recorder is aware or the workbook that you are recording in/from, so the local workbook, but not the foreign workbook, so it loses references to the foreign workbook. See the code samples below.
Import data from a closed workbook (ADO)
If you want to import a lot of data from a closed workbook you can do this with ADO and the macro below. If you want to retrieve data from another worksheet than the first worksheet in the closed workbook, you have to refer to a user defined named range. The macro below can be used like this (in Excel 2000 or later):
GetDataFromClosedWorkbook "C:\FolderName\WorkbookName.xls", "A1:B21", ActiveCell, False
GetDataFromClosedWorkbook "C:\FolderName\WorkbookName.xls", "MyDataRange", Range ("B3"), True
Sub GetDataFromClosedWorkbook(SourceFile As String, SourceRange As String, _
TargetRange As Range, IncludeFieldNames As Boolean)
' requires a reference to the Microsoft ActiveX Data Objects library
' if SourceRange is a range reference:
' this will return data from the first worksheet in SourceFile
' if SourceRange is a defined name reference:
' this will return data from any worksheet in SourceFile
' SourceRange must include the range headers
'
Dim dbConnection As ADODB.Connection, rs As ADODB.Recordset
Dim dbConnectionString As String
Dim TargetCell As Range, i As Integer
dbConnectionString = "DRIVER={Microsoft Excel Driver (*.xls)};" & _
"ReadOnly=1;DBQ=" & SourceFile
Set dbConnection = New ADODB.Connection
On Error GoTo InvalidInput
dbConnection.Open dbConnectionString ' open the database connection
Set rs = dbConnection.Execute("[" & SourceRange & "]")
Set TargetCell = TargetRange.Cells(1, 1)
If IncludeFieldNames Then
For i = 0 To rs.Fields.Count - 1
TargetCell.Offset(0, i).Formula = rs.Fields(i).Name
Next i
Set TargetCell = TargetCell.Offset(1, 0)
End If
TargetCell.CopyFromRecordset rs
rs.Close
dbConnection.Close ' close the database connection
Set TargetCell = Nothing
Set rs = Nothing
Set dbConnection = Nothing
On Error GoTo 0
Exit Sub
InvalidInput:
MsgBox "The source file or source range is invalid!", _
vbExclamation, "Get data from closed workbook"
End Sub
Another method that doesn't use the CopyFromRecordSet-method
With the macro below you can perform the import and have better control over the results returned from the RecordSet.
Sub TestReadDataFromWorkbook()
' fills data from a closed workbook in at the active cell
Dim tArray As Variant, r As Long, c As Long
tArray = ReadDataFromWorkbook("C:\FolderName\SourceWbName.xls", "A1:B21")
' without using the transpose function
For r = LBound(tArray, 2) To UBound(tArray, 2)
For c = LBound(tArray, 1) To UBound(tArray, 1)
ActiveCell.Offset(r, c).Formula = tArray(c, r)
Next c
Next r
' using the transpose function (has limitations)
' tArray = Application.WorksheetFunction.Transpose(tArray)
' For r = LBound(tArray, 1) To UBound(tArray, 1)
' For c = LBound(tArray, 2) To UBound(tArray, 2)
' ActiveCell.Offset(r - 1, c - 1).Formula = tArray(r, c)
' Next c
' Next r
End Sub
Private Function ReadDataFromWorkbook(SourceFile As String, SourceRange As String) As Variant
' requires a reference to the Microsoft ActiveX Data Objects library
' if SourceRange is a range reference:
' this function can only return data from the first worksheet in SourceFile
' if SourceRange is a defined name reference:
' this function can return data from any worksheet in SourceFile
' SourceRange must include the range headers
' examples:
' varRecordSetData = ReadDataFromWorkbook("C:\FolderName\SourceWbName.xls", "A1:A21")
' varRecordSetData = ReadDataFromWorkbook("C:\FolderName\SourceWbName.xls", "A1:B21")
' varRecordSetData = ReadDataFromWorkbook("C:\FolderName\SourceWbName.xls", "DefinedRangeName")
Dim dbConnection As ADODB.Connection, rs As ADODB.Recordset
Dim dbConnectionString As String
dbConnectionString = "DRIVER={Microsoft Excel Driver (*.xls)};ReadOnly=1;DBQ=" & SourceFile
Set dbConnection = New ADODB.Connection
On Error GoTo InvalidInput
dbConnection.Open dbConnectionString ' open the database connection
Set rs = dbConnection.Execute("[" & SourceRange & "]")
On Error GoTo 0
ReadDataFromWorkbook = rs.GetRows ' returns a two dim array with all records in rs
rs.Close
dbConnection.Close ' close the database connection
Set rs = Nothing
Set dbConnection = Nothing
On Error GoTo 0
Exit Function
InvalidInput:
MsgBox "The source file or source range is invalid!", vbExclamation, "Get data from closed workbook"
Set rs = Nothing
Set dbConnection = Nothing
End Function
See the link below.
https://www.erlandsendata.no/english/index.php?d=envbadacimportwbado
Check out this link as well.
https://www.rondebruin.nl/win/s3/win024.htm
I had read that exporting an Excel worksheet from Access will use the DoCmd object and the TransferSpreadsheet method, however, I need a macro that will run from my Excel VBA script.
So the steps would be as following:
Run macro in Excel
Convert access table into an Excel worksheet
Excel VBA code runs a script on the newly converted worksheet.
Or if there was a way to
Run macro in Excel
Perform script on access table, the better.
Well, your questions doesn't totally make sense, but I'm guessing that you want to import data from Access into Excel. Is that right?
Import data from Access to Excel (DAO)
CopyFromRecordset is probably the easiest method of getting data from an Access table to an Excel worksheet.
Sub DAOCopyFromRecordSet(DBFullName As String, TableName As String, _
FieldName As String, TargetRange As Range)
' Example: DAOCopyFromRecordSet "C:\FolderName\DataBaseName.mdb", _
"TableName", "FieldName", Range("C1")
Dim db As Database, rs As Recordset
Dim intColIndex As Integer
Set TargetRange = TargetRange.Cells(1, 1)
Set db = OpenDatabase(DBFullName)
Set rs = db.OpenRecordset(TableName, dbOpenTable) ' all records
'Set rs = db.OpenRecordset("SELECT * FROM " & TableName & _
" WHERE " & FieldName & _
" = 'MyCriteria'", dbReadOnly) ' filter records
' write field names
For intColIndex = 0 To rs.Fields.Count - 1
TargetRange.Offset(0, intColIndex).Value = rs.Fields(intColIndex).Name
Next
' write recordset
TargetRange.Offset(1, 0).CopyFromRecordset rs
Set rs = Nothing
db.Close
Set db = Nothing
End Sub
If you want more control with the data import, you can customize the macro below:
Sub DAOFromAccessToExcel(DBFullName As String, TableName As String, _
FieldName As String, TargetRange As Range)
' Example: DAOFromAccessToExcel "C:\FolderName\DataBaseName.mdb", _
"TableName", "FieldName", Range("B1")
Dim db As Database, rs As Recordset
Dim lngRowIndex As Long
Set TargetRange = TargetRange.Cells(1, 1)
Set db = OpenDatabase(DBFullName)
Set rs = db.OpenRecordset(TableName, dbOpenTable) ' all records
'Set rs = DB.OpenRecordset("SELECT * FROM " & _
TableName & " WHERE " & FieldName & _
" = 'MyCriteria'", dbReadOnly) ' filter records
lngRowIndex = 0
With rs
If Not .BOF Then .MoveFirst
While Not .EOF
TargetRange.Offset(lngRowIndex, 0).Formula = .Fields(FieldName)
.MoveNext
lngRowIndex = lngRowIndex + 1
Wend
End With
Set rs = Nothing
db.Close
Set db = Nothing
End Sub
Or...
Import data from Access to Excel (ADO)
With the procedure below you can import data from an Access table to a worksheet.
Sub ADOImportFromAccessTable(DBFullName As String, _
TableName As String, TargetRange As Range)
' Example: ADOImportFromAccessTable "C:\FolderName\DataBaseName.mdb", _
"TableName", Range("C1")
Dim cn As ADODB.Connection, rs As ADODB.Recordset, intColIndex As Integer
Set TargetRange = TargetRange.Cells(1, 1)
' open the database
Set cn = New ADODB.Connection
cn.Open "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" & _
DBFullName & ";"
Set rs = New ADODB.Recordset
With rs
' open the recordset
.Open TableName, cn, adOpenStatic, adLockOptimistic, adCmdTable
' all records
'.Open "SELECT * FROM " & TableName & _
" WHERE [FieldName] = 'MyCriteria'", cn, , , adCmdText
' filter records
RS2WS rs, TargetRange ' write data from the recordset to the worksheet
' ' optional approach for Excel 2000 or later (RS2WS is not necessary)
' For intColIndex = 0 To rs.Fields.Count - 1 ' the field names
' TargetRange.Offset(0, intColIndex).Value = rs.Fields(intColIndex).Name
' Next
' TargetRange.Offset(1, 0).CopyFromRecordset rs ' the recordset data
End With
rs.Close
Set rs = Nothing
cn.Close
Set cn = Nothing
End Sub
So basically I would like to be able to send date from excel to access, run some queries, and send the results back to excel, and do this all from excel VBA.
I would like to send my data, which is in an excel worksheet with sheet name "Enrollment Data Aggregate" to an access database H:\My file extension\Nameofdatabase.accdb and save it as a table with the name "Enrollment Data Aggregate".
I already have queries put together that run from the table "Enrollment Data Aggregate", so I think (hope) that I can delete that table, and when I pull in the new one from excel, the queries will still update. Then I would like access to run/update the queries and export them as separate tabs to my excel file.
Ideally, I would then like to continue doing other things in excel VBA. In other words, I'm really hoping that I can control all of this from excel. I have plenty of experience with excel and access, but I've only done about 4 VBA projects that were large like this (I've done lots of small macros) so I'm not super experienced. Any suggestions would be greatly appreciated.
To export data from Excel to Access:
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
To import data from Access to Excel:
Sub ADOImportFromAccessTable(DBFullName As String, _
TableName As String, TargetRange As Range)
' Example: ADOImportFromAccessTable "C:\FolderName\DataBaseName.mdb", _
"TableName", Range("C1")
Dim cn As ADODB.Connection, rs As ADODB.Recordset, intColIndex As Integer
Set TargetRange = TargetRange.Cells(1, 1)
' open the database
Set cn = New ADODB.Connection
cn.Open "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" & _
DBFullName & ";"
Set rs = New ADODB.Recordset
With rs
' open the recordset
.Open TableName, cn, adOpenStatic, adLockOptimistic, adCmdTable
' all records
'.Open "SELECT * FROM " & TableName & _
" WHERE [FieldName] = 'MyCriteria'", cn, , , adCmdText
' filter records
RS2WS rs, TargetRange ' write data from the recordset to the worksheet
' ' optional approach for Excel 2000 or later (RS2WS is not necessary)
' For intColIndex = 0 To rs.Fields.Count - 1 ' the field names
' TargetRange.Offset(0, intColIndex).Value = rs.Fields(intColIndex).Name
' Next
' TargetRange.Offset(1, 0).CopyFromRecordset rs ' the recordset data
End With
rs.Close
Set rs = Nothing
cn.Close
Set cn = Nothing
End Sub
Running an Access Query from Excel:
Sub CreateAndRunQuery()
'------------------------------------------------------------------------------------------
'This macro opens the Sample.accdb database, creates and runs an SQL query (filtering
'all the customers from Canada). Then, it copies selected fields back in the Excel sheet.
'The code uses late binding, so no reference to external library is required.
'Written By: Christos Samaras
'Date: 05/10/2013
'Last Updated: 29/11/2014
'E-mail: xristos.samaras#gmail.com
'Site: http://www.myengineeringworld.net
'------------------------------------------------------------------------------------------
'Declaring the necessary variables.
Dim con As Object
Dim rs As Object
Dim AccessFile As String
Dim strTable As String
Dim SQL As String
Dim i As Integer
'Disable screen flickering.
Application.ScreenUpdating = False
'Specify the file path of the accdb file. You can also use the full path of the file like:
'AccessFile = "C:\Users\Christos\Desktop\Sample.accdb"
AccessFile = ThisWorkbook.Path & "\" & "Sample.accdb"
'Set the name of the table you want to retrieve the data.
strTable = "Customers"
On Error Resume Next
'Create the ADODB connection object.
Set con = CreateObject("ADODB.connection")
'Check if the object was created.
If Err.Number <> 0 Then
MsgBox "Connection was not created!", vbCritical, "Connection Error"
Exit Sub
End If
On Error GoTo 0
'Open the connection.
con.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & AccessFile
'Create the SQL statement to retrieve the data from table.
'Get the necessary information (first name etc.) for all the Canadian customers.
SQL = "SELECT FirstName, LastName, Address, City, Phone FROM " & strTable & " WHERE COUNTRY='Canada'"
On Error Resume Next
'Create the ADODB recordset object.
Set rs = CreateObject("ADODB.Recordset")
'Check if the object was created.
If Err.Number <> 0 Then
'Error! Release the objects and exit.
Set rs = Nothing
Set con = Nothing
'Display an error message to the user.
MsgBox "Recordset was not created!", vbCritical, "Recordset Error"
Exit Sub
End If
On Error GoTo 0
'Set thee cursor location.
rs.CursorLocation = 3 'adUseClient on early binding
rs.CursorType = 1 'adOpenKeyset on early binding
'Open the recordset.
rs.Open SQL, con
'Check if the recordet is empty.
If rs.EOF And rs.BOF Then
'Close the recordet and the connection.
rs.Close
con.Close
'Release the objects.
Set rs = Nothing
Set con = Nothing
'Enable the screen.
Application.ScreenUpdating = True
'In case of an empty recordset display an error.
MsgBox "There are no records in the recordset!", vbCritical, "No Records"
Exit Sub
End If
'Copy the recordset headers.
For i = 0 To rs.Fields.Count - 1
Sheets("New Query").Cells(1, i + 1) = rs.Fields(i).Name
Next i
'Write the query values in the sheet.
Sheets("New Query").Range("A2").CopyFromRecordset rs
'Close the recordet and the connection.
rs.Close
con.Close
'Release the objects.
Set rs = Nothing
Set con = Nothing
'Adjust the columns' width.
Sheets("New Query").Columns("A:E").AutoFit
'Enable the screen.
Application.ScreenUpdating = True
'Inform the user that the macro was executed successfully.
MsgBox "The Canadian customers were successfully retrieved from the '" & strTable & "' table!", vbInformation, "Done"
End Sub
You will find more info here.
http://www.myengineeringworld.net/2013/10/running-access-queries-from-excel-vba.html