I am trying to export a table from Excel to a table in an Access DB, but I keep getting an error "Database or Object is read only". Here is the code in qestion.
dbWB = Application.ActiveWorkbook.FullName
dbWS = Application.ActiveSheet.Name
dsh = "[" & dbWS & "$]"
Set DB = CreateObject("ADODB.Connection")
dbPath = "\\Corpaa.aa.com\CampusHome\IOCADHome02\758673\Projects\Global Analysis Tool\MX Analysis DB\Global Line MX Hub Review DB.accdb"
scn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & dbPath
DB.Open scn
DB.Execute "DELETE * FROM tblNewSchedule;"
SQLInsert = "INSERT INTO tblNewSchedule "
SQLSelect = "SELECT * "
SQLFrom = "FROM [Excel 8.0; HDR=YES; DATABASE= " & dbWB & "]." & dsh & " "
strQry = SQLInsert & SQLSelect & SQLFrom & ";"
DB.Execute strQry
DB.Close
The DELETE qry executes just fine with no errors. The problem is the strQry execution. I believe it is refrencing that the WB is read-only, but I am running the code from the WB. I am running Office 2010. Thank you for your assistance.
so, after continuing my search, I discovered a different approach that worked perfectly. I found it on this here
Here is my new working code. Thanks for the assistance.
dbWB = Application.ActiveWorkbook.FullName
dbWS = Application.ActiveSheet.Name
dsh = "[" & dbWS & "$]"
Set DB = CreateObject("ADODB.Connection")
dbPath = "\\Corpaa.aa.com\CampusHome\IOCADHome02\758673\Projects\Global Analysis Tool\MX Analysis DB\Global Line MX Hub Review DB.accdb"
scn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & dbPath
DB.Open scn
Dim rs As ADODB.Recordset
Dim r As Long
Dim y As Long
y = TWB.Cells(1, 1).End(xlDown).Row
r = TWB.Cells(1, 1).End(xlToRight).Column
DB.Execute "DELETE * FROM tblNewSchedule;"
Set rs = New ADODB.Recordset
rs.Open "tblNewSchedule", DB, adOpenKeyset, adLockOptimistic, adCmdTable
For i = 2 To y
With rs
.AddNew
For j = 1 To r
fName = TWB.Cells(1, j)
fData = TWB.Cells(i, j)
.Fields(fName) = fData
Next j
End With
Next i
DB.Close
Related
I am unable to execute a simple sql statement. - sorry I am sure this is simple and I am missing something small. Error says missing the object.
dbPath = "C:\Users\User\Documents\test0419.accdb"
tblName = "Wait_Data_Table"
strcon = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source='" & dbPath & "';"
conn.Open strcon
Set wrkSpaceNew = DBEngine.CreateWorkspace("Check", "admin", "", dbUseJet)
rcdDetail = ("SELECT order.ord_id, order.job_id, order.bc_desc, order.ord_amount, order.ord_diff FROM Order")
Set rs = DBEngine.BeginTrans(rcdDetail)
You can use either DAO or ADODB, not normally both. See difference-between-ado-and-dao
Option Explicit
Sub UseDAO()
Const SQL = " SELECT order.ord_id, order.job_id, order.bc_desc, " & _
" order.ord_amount, order.ord_diff " & _
" FROM [Order]"
Const dbpath = "C:\Users\User\Documents\test0419.accdb"
Dim wkspace As workspace, db As DAO.Database, rs As DAO.Recordset
Set wkspace = DBEngine.CreateWorkspace("Check", "admin", "", dbUseJet)
Set db = wkspace.OpenDatabase(dbpath)
Set rs = db.OpenRecordset(SQL)
Sheet1.Range("A1").CopyFromRecordset rs
db.Close
Set db = Nothing
wkspace.Close
Set wkspace = Nothing
MsgBox "Results on sheet " & Sheet1.Name, vbInformation, "DAO"
End Sub
Sub UseADODB()
Const SQL = " SELECT order.ord_id, order.job_id, order.bc_desc, " & _
" order.ord_amount, order.ord_diff " & _
" FROM [Order]"
Const dbpath = "C:\Users\User\Documents\test0419.accdb"
Dim strConn As String, conn As ADODB.Connection, rs As ADODB.Recordset
strConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source='" & dbpath & "';"
Set conn = New ADODB.Connection
conn.Open strConn
Set rs = conn.Execute(SQL)
Sheet1.Range("A1").CopyFromRecordset rs
conn.Close
MsgBox "Results on sheet " & Sheet1.Name, vbInformation, "ADODB"
End Sub
Don't forget to add Activex Data Object in Reference Section
Dim baglanti As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim sunucu, veritabani, id, sifre, sorgu As String
sunucu = "DESKTOP-GF32DLC\SQLEXPRESS"
veritabani = "AdventureWorks2014"
id = ""
sifre = ""
sorgu = "SELECT * FROM [HumanResources].[Department] Where [GroupName]='Manufacturing'"
baglanti.Open "Driver={SQL SERVER};Server=" & sunucu & ";Database=" & veritabani & _
";Uid=" & id & ";Pwd=" & sifre & ";"
rs.Open sorgu, baglanti, adOpenStatic
With Range("A1:AA1000")
.ClearContents
.CopyFromRecordset rs
End With
rs.Close
baglanti.Close
This way you can make a healthy sql connection.
I used to use it to connect sql in the past
I've created below Excel function which connects to an access database with ADODB (approx 10k lines).
It generally works but there are two main issues:
It is unreliable: often it returns 0 while the result should be different
It is definitely slow
Any suggestion on how to improve?
Public Function TotaleSQL(Cat As String, SubCat As String, Anno As Integer) As Long
On Error Resume Next
Dim cn As Object, rs As Object, output As String, sql As String
Dim src As String
Dim Total As Long
Dim CatLong As String
src = "Z:\Report.accdb"
'---Connecting to the Data Source---
Set cn = CreateObject("ADODB.Connection")
With cn
.Provider = "Microsoft.ACE.OLEDB.12.0"
.connectionstring = "Data Source=" & src & ";Persist Security Info=False"
.Open
End With
'---Run the SQL SELECT Query---
CatLong = "'" & Cat & ":" & SubCat & "'"
sql = "SELECT Report.Withdrawal, Report.Deposit, Report.Category, Report.Date FROM Report WHERE (((Report.Category)=" & CatLong & ") AND ((Year([date]))=" & Anno & "));"
'sql = "SELECT * FROM [Sheet1$]"
Set rs = cn.Execute(sql)
Total = 0
Do
Total = Total + Val(rs(1) & "") - Val(rs(0) & "")
rs.Movenext
Loop Until rs.EOF
'---Clean up---
rs.Close
cn.Close
Set cn = Nothing
Set rs = Nothing
TotaleSQL = Total
End Function
If Cat, SubCat or Anno are user inputs it is more secure to use parameters in your query. For example
Public Function TotaleSQL(Cat As String, SubCat As String, Anno As Integer)
Const DATABASE = "Z:\Report.accdb"
Const TABLE_NAME = "Report"
Const SQL = " SELECT SUM(iif(Deposit is null,0,Deposit) " & _
" - iif(Withdrawal is null,0,Withdrawal)) " & _
" FROM " & TABLE_NAME & _
" WHERE Category = ? " & _
" AND YEAR(ddate)= ? "
Dim cn As Object, cmd As Object, rs As Object
'---Connecting to the Data Source---
Set cn = CreateObject("ADODB.Connection")
With cn
.Provider = "Microsoft.ACE.OLEDB.12.0"
.connectionstring = "Data Source=" & DATABASE & ";Persist Security Info=False"
.Open
End With
' create command
Set cmd = CreateObject("ADODB.Command")
With cmd
.ActiveConnection = cn
.CommandText = SQL
.CommandType = 1 'adCmdText
.Parameters.Append .CreateParameter("P1", 200, 1, 50) ' 1=adParamInput 200=adVarChar
.Parameters.Append .CreateParameter("P2", 3, 1) ' 3=adInteger
End With
' execute with parameters
With cmd
.Parameters(0).Value = Cat & ":" & SubCat
.Parameters(1).Value = Anno
Set rs = .Execute
End With
TotaleSQL = rs(0)
rs.Close
cn.Close
Set cn = Nothing
Set rs = Nothing
Set cmd = Nothing
End Function
Sub test()
Debug.Print TotaleSQL("Cat", "SubCat", 2020)
End Sub
I'm trying to use DCount to see if records exist in a table before inserting the data into the database but I keep getting a type mismatch error on "Customer Number" and have no idea why. The code is below:
Public Sub ExportData()
Set cn = CreateObject("ADODB.Connection")
dbPath = Application.ActiveWorkbook.Path & "\PRID.mdb"
dbWb = Application.ActiveWorkbook.FullName
dbWs = Application.ActiveSheet.Name
scn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & dbPath
dsh = "[" & Application.ActiveSheet.Name & "$]"
cn.Open scn
ssql = "INSERT INTO [Investment Data] ([Customer Number])"
ssql = ssql & "SELECT [Customer Number] FROM [Excel 8.0;HDR=YES;DATABASE=" & dbWb & "]." & dsh
If Application.WorksheetFunction.DCount("Customer Number", "Investment Data", "[Customer Number]=" & Range("A2")) > 0 Then
MsgBox ("A similar entry has been detected within the PRID database, please make sure that this is a new entry before you continue.")
Else
MsgBox ("Entry has been entered into the database.")
cn.Execute ssql
Exit Sub
End If
Any help would be appreciated thanks.
This should resolve your problem
You can add a WHERE clause to your query that will skip the [Customer Number] that already exists in the [Investment Data] table.
ssql = ssql & _
" WHERE [Customer Number] NOT IN(SELECT [Customer Number] FROM [Investment Data]);)"
You can then use Connection.Execute to return the number of records added.
Results = cN.Execute(ssql)
MsgBox Results & " Records were added " & (allRecordsCount - Results) & "Records Were Skipped"
If you want to alert the user before you insert the records you'll need two queries.
ssql = ssql & "SELECT [Customer Number] FROM [Excel 8.0;HDR=YES;DATABASE=" & dbWb & "]." & dsh & _
ssql & " WHERE [Customer Number] IN(SELECT [Customer Number] FROM [Investment Data]);)"
Set rs = CreateObject("ADODB.Recordset")
Set rs = cN.Execute(ssql)
If Not rs.BOF AND Not rs.EOF Then
msg = msg & vbCrLf & rs.Fields("Customer Number").Value
rs.MoveNext
End If
If msg <> "" Then
MsgBox "These Records Are Duplicates" & vbCrLf & msg
Exit Sub
End If
This should answer your question
You are getting the "DCount Type Mismatch Error VBA" because you are trying to query an external Access Database using the Excel WorksheetFunction DCount.
Test Queries
Public Sub TestQueries()
Set cN = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
dbPath = Application.ActiveWorkbook.path & "\PRID.mdb"
'dbPath = "C:\Users\best buy\Downloads\stackoverfow\Sample Data File\test.mdb"
dbWb = Application.ActiveWorkbook.FullName
dbWs = Application.ActiveSheet.Name
scn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & dbPath
dsh = "[" & Application.ActiveSheet.Name & "$]"
cN.Open scn
ssql = ssql & "SELECT [Customer Number] FROM [Excel 8.0;HDR=YES;DATABASE=" & dbWb & "]." & dsh
Set rs = cN.Execute(ssql)
Do While Not rs.BOF And Not rs.EOF
msg = msg & vbCrLf & rs.FIelds(0).Value
rs.MoveNext
Loop
MsgBox msg, vbInformation, "Results Query Without Where Clause"
ssql = ssql & _
" WHERE [Customer Number] IN(SELECT CDbl([Customer Number]) FROM [Investment Data])"
msg = ""
Set rs = cN.Execute(ssql)
Do While Not rs.BOF And Not rs.EOF
msg = msg & vbCrLf & rs.FIelds(0).Value
rs.MoveNext
Loop
MsgBox msg, vbInformation, "Results Query With Where Clause"
End Sub
I'm trying to join two CSV files.
Currently I'm trying to add the following code. I added a validation if the connection was open with the "If Not objConnection Is Nothing Then" but supposedly the connection is open. When I run the code I get the following error message:
which roughly translates to:
An error has occurred '2147217904 (80040e10)' in execution time:
Some required values have not been specified.
I have the following libraries loaded:
The code is as follows:
Dim objConnection As ADODB.Connection
Dim objrecordset As ADODB.Recordset
fNameAndPath = Application.GetOpenFilename(FileFilter:="CSV File (*.csv),(*.csv)", Title:="Select first CSV file")
If fNameAndPath = False Then
Exit Sub
End If
fNameAndPath2 = Application.GetOpenFilename(FileFilter:="CSV File (*.csv),(*.csv)", Title:="Select second CSV file")
If fNameAndPath2 = False Then
Exit Sub
End If
Set objConnection = CreateObject("ADODB.Connection")
Set objrecordset = CreateObject("ADODB.Recordset")
strPath = Left(fNameAndPath, InStrRev(fNameAndPath, "\") - 1)
Filename = Mid(fNameAndPath, InStrRev(fNameAndPath, "\") + 1)
strPath2 = Left(fNameAndPath2, InStrRev(fNameAndPath2, "\") - 1)
Filename2 = Mid(fNameAndPath2, InStrRev(fNameAndPath2, "\") + 1)
With objConnection
.Provider = "Microsoft.Jet.OLEDB.4.0"
.ConnectionString = "Data Source=" & strPath & _
";Extended Properties=""text;HDR=Yes;FMT=Delimited"";"
.Open
End With
strSql = "SELECT * FROM " & Filename & " as file1, " _
& "" & Filename2 & " as file2" _
& " WHERE file1.[APOYO] = file2.[APOYO]"
If Not objConnection Is Nothing Then
If (objConnection.State And adStateOpen) = adStateOpen Then
Set objrecordset = objConnection.Execute(strSql)
End If
End If
Restarted from scratch.
This code works:
Sub leerCSV()
On Error Resume Next
Const adOpenStatic = 3
Const adLockOptimistic = 3
Const adCmdText = &H1
Set objConnection = CreateObject("ADODB.Connection")
Set objRecordset = CreateObject("ADODB.Recordset")
strPathtoTextFile = "C:\"
objConnection.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & strPathtoTextFile & ";" & _
"Extended Properties=""text;HDR=YES;FMT=Delimited"""
strSql = "SELECT * FROM file.csv F1 " _
& " LEFT JOIN file2.csv F2 ON F1.[c1] = F2.[c1] "
objRecordset.Open strSql, objConnection, adOpenStatic, adLockOptimistic, adCmdText
MsgBox "Registros: " & objRecordset.RecordCount
Debug.Print Now
Do Until objRecordset.EOF
Debug.Print "Name: " & objRecordset.Fields.Item("APOYO") & " Department: " & objRecordset.Fields.Item("O&D") & " Extension: " & objRecordset.Fields.Item("FECHA")
objRecordset.MoveNext
Loop
''Tidy up
objRecordset.Close
objConnection.Close
End Sub
How to execute a query in MS Access db from Excel VBA code or macro.
MS-Access query accepts some parameters, that needs to be passed from Excel.
Thanks
Here is one possibility:
Dim cn As Object
Dim strFile As String
Dim strCon As String
Dim strSQL As String
strFile = "C:\docs\Test.mdb"
strCon = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & strFile
''Late binding, so no reference is needed
Set cn = CreateObject("ADODB.Connection")
cn.Open strCon
strSQL = "INSERT INTO ATable (AField) " _
& "VALUES (" & Sheet1.[A1] & ")"
cn.Execute strSQL
cn.Close
Set cn = Nothing
You can also refer in-line in the sql to a dataset from Excel.
EDIT re comments
Using a command:
strSQL = "SELECT * FROM ATable " _
& "WHERE AField = #AField"
With cmd
Set .ActiveConnection = cn
.CommandText = strSQL
.CommandType = 1 'adCmdText
''ADO Datatypes are often very particular
''adSmallInt = 2 ; adParamInput = 1
.Parameters.Append .CreateParameter("#AField", 2, 1, , Sheet1.[A1])
End With
Set rs = cmd.Execute
See also: http://support.microsoft.com/kb/181782
This uses ADODB.
Set m_Connection = New Connection
If Application.Version = "12.0" Then
m_Connection.Provider = "Microsoft.ACE.OLEDB.12.0"
Else
m_Connection.Provider = "Microsoft.Jet.OLEDB.4.0"
End If
m_Connection.Open <full path to Access DB>
If m_Connection.State > 0 Then
Dim rsSource As New Recordset
rsSource.Open strQuery, m_Connection, adOpenForwardOnly, adLockReadOnly
Dim result As Long
Dim rngTarget As Range
rngTarget = ThisWorkbook.Worksheets(m_SheetName).Range("A1")
If Not rsSource.BOF Then
result = rngTarget.CopyFromRecordset(rsSource)
End If
If rsSource.State Then rsSource.Close
Set rsSource = Nothing
End If
So it runs the query and puts it where you like. strQuery is the name of a query in the db or an SQL string.