I'm still getting used to working with SQL & Access with VBA.
I'm looking to run a query which will return just AccountNumber & BorrowerName from our Access database. When I run 'SELECT AccountNumber, BorrowerName', it only returns the AccountNumbers and without the heading in column A. Does anyone have a solution to this issue?
'runs an sql query
Sub RunQueryOnAccess()
Dim conn As New Connection, rec As New Recordset
Dim DBPATH, PRVD, connString, query As String
'Declaring fully qualified name of database. Change it with your database's location and name.
DBPATH = "Z:\Danny Tool Test Folder\Database\MasterFile_February2021.accdb"
'This is the connection provider. Remember this for your interview.
PRVD = "Microsoft.ace.OLEDB.12.0;"
'This is the connection string that you will require when opening the the connection.
connString = "Provider=" & PRVD & "Data Source=" & DBPATH
'opening the connection
conn.Open connString
'the query I want to run on the database.
query = "SELECT Accountnumber, BorrowerName from CaseManagers;"
'running the query on the open connection. It will get all the data in the rec object.
rec.Open query, conn
'clearing the content of the cells
Cells.ClearContents
'getting data from the recordset if any and printing it in column A of excel sheet.
If (rec.RecordCount <> 0) Then
Do While Not rec.EOF
Range("A" & Cells(Rows.count, 1).End(xlUp).Row).Offset(1, 0).Value2 = _
rec.Fields(1).value
rec.MoveNext
Loop
End If
'closing the connections
rec.Close
conn.Close
End Sub
Related
I am building a patient record export system to extract data from SQL Server. The customer would like the data in the form of an Excel workbook.
The way that the data is held is such that the tables in the database are created dynamically and the column names change depending on the export parameters.
What I want to do is enumerate the tables in the database then export (or import) those tables (including column headers) to Excel in separate sheets into a single workbook.
SO:-
If Database is:-
dbo.table1 (name, address, postcode)
dbo.table2 (height, weight, headcirc)
I end up with an Excel workbook:-
Sheet1: Name Address Postcode
Sheet2: Height Weight, Headcirc
At the moment, every method I have looked at requires Excel to know the structure of the data it is receiving in advance. For a given export it is impossible to know the number of tables or the names of the columns in those tables in advance.
For example OPENROWSET requires column headers to be present in the Excel workbook.
SSIS seems to require fixed mappings to both the SQL Table columns and the Excel Workbook columns.
The only other approach I can think of is to export all tables to CSV using a dynamic BCP process, then to see if I can find some VBA that would allow me to assimilate all CSV files from a folder into a single Excel workbook as separate sheets - but this seems very clunky.
I am sure this must be possible - has anyone achieved this? What method would work?
There are probably multiple ways to do this kind of thing. Some of these techniques may work, or may not work, depending on your setup, what versions of Excel and SQL Server you have installed, what other software you have installed, etc...
1) Export data to existing EXCEL file from SQL Server table
insert into OPENROWSET('Microsoft.Jet.OLEDB.4.0',
'Excel 8.0;Database=D:\testing.xls;',
'SELECT * FROM [SheetName$]') select * from SQLServerTable
2) If you don't want to create an EXCEL file in advance and want to export data to it, use
EXEC sp_makewebtask
#outputfile = 'd:\testing.xls',
#query = 'Select * from Database_name..SQLServerTable',
#colheaders =1,
#FixedFont=0,#lastupdated=0,#resultstitle='Testing details'
32-bit and 64-bit drivers:
https://www.microsoft.com/en-us/download/details.aspx?id=13255
You can run this VBA in Excel.
Sub TestMacro()
' Create a connection object.
Dim cnPubs As ADODB.Connection
Set cnPubs = New ADODB.Connection
' Provide the connection string.
Dim strConn As String
'Use the SQL Server OLE DB Provider.
strConn = "PROVIDER=SQLOLEDB;"
'Connect to the Pubs database on the local server.
strConn = strConn & "DATA SOURCE=(local);INITIAL CATALOG=Name_of_your_DB;"
'Use an integrated login.
strConn = strConn & " INTEGRATED SECURITY=sspi;"
'Now open the connection.
cnPubs.Open strConn
' Create a recordset object.
Dim rsPubs As ADODB.Recordset
Set rsPubs = New ADODB.Recordset
With rsPubs
' Assign the Connection object.
.ActiveConnection = cnPubs
' Extract the required records.
.Open "SELECT * FROM Categories"
' Copy the records into cell A1 on Sheet1.
Sheet1.Range("A1").CopyFromRecordset rsPubs
' Tidy up
.Close
End With
cnPubs.Close
Set rsPubs = Nothing
Set cnPubs = Nothing
End Sub
Or...
Sub ADOExcelSQLServer()
Dim Cn As ADODB.Connection
Dim Server_Name As String
Dim Database_Name As String
Dim User_ID As String
Dim Password As String
Dim SQLStr As String
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
Server_Name = "your_server_name" ' Enter your server name here
Database_Name = "your_database_name" ' Enter your database name here
User_ID = "" ' enter your user ID here
Password = "" ' Enter your password here
SQLStr = "SELECT * FROM Orders" ' Enter your SQL here
Set Cn = New ADODB.Connection
Cn.Open "Driver={SQL Server};Server=" & Server_Name & ";Database=" & Database_Name & _
";Uid=" & User_ID & ";Pwd=" & Password & ";"
rs.Open SQLStr, Cn, adOpenStatic
With Worksheets("Sheet1").Range("A1:Z500")
.ClearContents
.CopyFromRecordset rs
End With
rs.Close
Set rs = Nothing
Cn.Close
Set Cn = Nothing
End Sub
I'm using Excel VBA code to connect to a CSV file (24,179,689 rows) via ADODB connection. The macro runs and gets data from the excel with a specific filter on one column. With this filter that I'm trying now, it should return about 1500 rows of data.
I have checked this by loading the CSV manually somewhere else, and the data is actually there. But when I use the ADODB connection, my recordset remains empty.
I did some extra test: count(*) on the complete CSV file, and there I see the error: it only returns 155,535 rows. So probably the specific filter that I'm applying is not in that data and therefore it returns 0 rows.
This is my code:
Public adoConn As ADODB.Connection
Public adoRS As ADODB.Recordset
Sub getdata()
Set adoConn = New ADODB.Connection
Set adoRS = New ADODB.Recordset
Dim rawFile As String
Dim strSQL As String
'The xlsx file to treat as a database
rawFile = "myPathName"
'Open a connection to the workbook
sconnect = "Provider=Microsoft.ACE.OLEDB.16.0;Data Source=" & rawFile & ";Extended Properties='text;HDR=YES;FMT=Delimited'"
'Write the SQL necessary to get the data you want
sql2 = "SELECT count(*) from [MyFileName.csv]"
'Now we open up our recordset using the connection and the sql statement
adoRS.Open sql2, adoConn, adOpenStatic
Debug.Print (adoRS.EOF)
'Last, we dump the results in this viz sheet
Blad1.Range("A1").CopyFromRecordset adoRS
adoRS.Close
adoConn.Close
End Sub
So then it returns the 155,535.
I also tried by creating a ADODB command and not using the connection as above. Or with connection timeouts. No results.
Is this a memory issue or something else? How can it be solved?
Please try this and see if it does what you want. Also, set a Reference to Microsoft ActiveX Data Objects 2.8 Library.
Sub sbADO()
Dim sSQLQry As String
Dim ReturnArray
Dim Conn As New ADODB.Connection
Dim mrs As New ADODB.Recordset
Dim DBPath As String, sconnect As String
DBPath = "C:\your_path_here\"
sconnect = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & DBPath & ";Extended Properties='text;HDR=YES;FMT=Delimited'"
Conn.Open sconnect
sSQLSting = "SELECT * From CSV1.csv WHERE ID = 2"
mrs.Open sSQLSting, Conn
ActiveSheet.Range("A2").CopyFromRecordset mrs
'Close Recordset
mrs.Close
Conn.Close
My CSV looks like this.
I have a little over a million rows in my CSV; I can't put in 23 million rows! Anyway, in my test, with just over a million rows, I got the exact results that I expected, in about 1 second, and my computer is super-super-super-slow!!
I want to make a simple function that will open and read from a database (and mdb file). As simply and cleanly as possible. Preferably using only ADODB.
For now I need this from excel/vba and I will later migrate to vb.net
First the structure of my database
A single mdb file (actually, accdb, it doesn't matter I hope)
It has a single table called "myParts"
This table has 3 columns: id, part number, part description
Here is how the function I want to make
function GetPartDescription (PartNumber as string) as string
The part number should exist only once in the entire table.
So this function should, open the database, find the row with the exact matching part number and then return whatever is in the "part description" column for that row
How should I do this ? I tried getting started by just choosing which api, I get lost ! DAO , ADO, ACEDAO, ADODB, ADO.NET, OLEDB ??? What a nightmare !
IMO this question should be closed as too broad but let's give it a try
The following function will connect to a Access database via ADODbD
Function ConnectToDB(ByVal fileName As String)
Dim conn As New ADODB.Connection
If Dir(fileName) = "" Then
MsgBox "Could not find file " & fileName
Exit Function
End If
Dim connectionString As String
' https://www.connectionstrings.com/access/
connectionString = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source=" _
& fileName & ";Persist Security Info=False;"
conn.Open connectionString
Set ConnectToDB = conn
End Function
And this might give you what you want. You need a sheet with the codename shRepAllRecords to make it work.
Option Explicit
Sub ReadFromDB()
' Get datbase name
Dim dbName As String
dbName = <fule filename of the database>
' Connect to the databse
Dim conn As ADODB.Connection
Set conn = ConnectToDB(dbName)
' read the data
Dim rs As New ADODB.Recordset
Dim query As String
' First example to use an SQL statement
query = "SELECT * From myParts WHERE PartNumber = '123'"
' Second example to use a query name defined in the database itself
' query = "qryCustomer"
rs.Open query, conn
' shRepAllRecords is the codename of the sheet where the
' data is written to
' Write header
Dim i As Long
For i = 0 To rs.Fields.Count - 1
'shRepAllRecords.Cells(1, i + 1).Value = rs.Fields(i).Name
shRepAllRecords.Range("A1").Offset(0, i) = rs.Fields(i).Name
Next i
' Write Data
shRepAllRecords.Range("A2").CopyFromRecordset rs
shRepAllRecords.Activate
' clean up
conn.Close
End Sub
You need to adjust the code in order to get excatly what you need but I leave that to you.
I have an access file with over 3 milion records. I would would like that excel will be able to perfrom a vlookup serach in the access table and give me the result on excel. Any simple way to do that?
Thank's!
That would be a terribly inefficient way to do it.
In a database you can use queries with JOINs to do this. If you tell us, what the table looks like and what you want to achieve, we can give you more info.
As Andre451 said - you need SQL rather than Excel functions to get data out of the database.
This code will dump the query results into the immediate window. It should show you how to extract data from Access though.
Note - I usually make the oDB variable global if I'm planning on querying the database a lot. Also without knowing the name of your database or table structure I've just shown an example of the query used - you'll have to add code to get the employee number and year from the user.
Tip - Write your query in Access using the query editor, view it as SQL and then copy to Excel.
Sub ReturnValues()
Dim oDB As Object
Dim rst As Object
Set oDB = GetDatabaseReference
Set rst = CreateObject("ADODB.RecordSet")
With rst
.CursorType = 2
.Open "SELECT Salary FROM tbl_SomeTable WHERE Emp=1 AND Year=2015", oDB
If Not rst Is Nothing Then
If Not .BOF And Not .EOF Then
.MoveFirst
Do
Debug.Print rst.Fields("Salary")
.MoveNext
Loop While Not .EOF
End If
End If
End With
End Sub
Public Function GetDatabaseReference() As Object
Dim cn As Object
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'Only set a reference to the database if it doesn't already exist. '
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
If oDB Is Nothing Then
Set cn = CreateObject("ADODB.Connection")
Select Case Val(Application.Version)
Case 11
'Access 2003
cn.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source =C:<Full Path To Database>.mdb;"
'Could use:
'"Data Source=" & ThisWorkbook.Path & "\Database\Database.mdb"
Case 14
'Access 2010
cn.Open "Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source =C:<Full Path To Database>.mdb;" & _
"Persist Security Info=False;"
''Could use:
'"Data Source=" & ThisWorkbook.Path & "\Database\Database.mdb;" & _
'"Persist Security Info=False;"
End Select
If Not cn Is Nothing Then
Set GetDatabaseReference = cn
End If
Else
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'oDB already has a reference, so ensure it's maintained. '
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Set GetDatabaseReference = oDB
End If
End Function
I hope someone can help.
I've developed an excel package that updates a .mdb access database through the connection string "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=\"
The database is shared.
I have a Mitel telephony system that checks the database every 10 seconds or so to check for a new entry.
The database is updated with
Dim q As New ADODB.Command
Dim cn As New ADODB.Connection
Dim SQL As String
SQL = "INSERT INTO tbl1LinkAuths (DateTimeAdded, DateEntered, AddedBy, REG, OrderNo,AccountNumber, CentreNumber, EmailAddress, Callback, "
SQL = SQL & "MakeText, "...............
cn.Open cnDB
q.ActiveConnection = cn
q.CommandText = SQL
'Excecute the above SQL to insert the new job record
q.Execute
Set rs = Nothing
Set cn = Nothing
Dim db As Access.Application
Set db = New Access.Application
db.Application.Visible = False
db.OpenCurrentDatabase "\\kffcis02\VWM Share\TelephonyDB.mdb", False
db.CloseCurrentDatabase
The INSERT statement updates the database fine, but I find I have to open and close the database to get it to update in time.
This package is used heavily by around 5 people at a time, making about 2 entries per minute.
It comes up with the error "file already in use", especially when using excel 2013, a lot of the time. I think this is because I have to open/close the database every time I update.
Does anybody know of a different way I can get the database to update quicker?
I've got the actual database setting to update ADODB every second and the database is shared.
I'm now desperate, as this package has went live. I didn't have any problems during testing because there wasn't as many people using it and none of them were on office 2013.
Wrong driver: Assuming a reference to activex data objects...
dim conn as adodb.connection 'module level variable
const DBNAME = "your name here"
const DBLOC = "Your dir here"
Sub UpdateDb()
dim sql as string
openconnectionroutine
sql = "INSERT INTO tbl1LinkAuths (DateTimeAdded, DateEntered, AddedBy, "
'etc
'if you want to check it worked : otherwise ditch numrecs
dim numrecs as long
conn.execute sql, numrecs
msgbox "You added " & numrecs & " records",vbokonly,"Done"
end sub
sub Openconnectionroutine()
if conn is nothing then set conn = new adodb.connection
if conn.connectionstring = "" then
conn.ConnectionString = "Driver={Microsoft Access Driver (*.mdb)};" & _
"Dbq=" & DBNAME & ";" & _
"DefaultDir=" & DBLOC & ";" & _
"Uid=Admin;Pwd=;"
end if
if conn.state = adstateopen then
else
conn.Open
end if
End sub