I normally vlookup my data against a table (database) in another workbook. (Excel to Excel --that's normally everyone does).
Since my table (database) grows more than 1.4 million rows therefore I need to transfer it to SQL Table in MS SQL Database.
I cannot move regular excel files just for Vlookup to SQL.
How do I vlookup excel against SQL tables.
Any solution with visual basic OR TSQL to fulfill requirement.
thanks
Yes, obviously, the limitation is just over a million rows, so you can use a Power Pivot Table to connect to multiple CSV files, aggregate the date you need, even if the total number of rows is over a million, and consolidate everything in one worksheet.
See the links below for more ideas of how to do this.
https://powerpivotpro.com/2017/01/import-csv-files-folder-filenames-excel/
http://sfmagazine.com/post-entry/january-2016-excel-combining-many-csv-files/
https://support.office.com/en-us/article/create-a-pivottable-with-an-external-data-source-db50d01d-2e1c-43bd-bfb5-b76a818a927b
You would use the 'Where' clause!
Sub ImportFromSQLServer()
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_here"
Database_Name = "your_DB_name_here"
'User_ID = "******"
'Password = "****"
SQLStr = "select * from dbo.TBL Where EMPID = '2'" 'and PostingDate = '2006-06-08'"
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")
.ClearContents
.CopyFromRecordset RS
End With
RS.Close
Set RS = Nothing
Cn.Close
Set Cn = Nothing
End Sub
Yes, you should be able to do that:
googling "excel connect to sql server" brings the result (description how to connect to a sql data source, to long to cite it here)
https://support.office.com/en-us/article/connect-a-sql-server-database-to-your-workbook-power-query-22c39d8d-5b60-4d7e-9d4b-ce6680d43bad
Then, when you have the connection, write your own lookup function in VBA, doing whatever you like.
Related
My vba code pulls data of last "11" hours from Database.
I want to pull data of my own time like "between (1/4/19 1:30 & 13/4/19 1:30)".Also want to add the data in sheet 1 like a table.
May i know how to add this custom time & make it a table using macro code.
Option Explicit
Sub DbConnection()
' NA Query connection with DB
Dim cn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim strConn As String
Dim mssql As String
strConn = "Driver={Redshift (x86)};Server=abc;Database=xyz;UID=abc;PWD=12345; Port=1234"
cn.Open strConn
cn.CommandTimeout = 60
mssql = "(using this line in SQL query here)"
where review_completed_timestamp_utc::TIMESTAMP > current_timestamp - interval'11 hour'
rs.Open mssql, cn
Sheets(1).Range("A2").CopyFromRecordset rs
End Sub
For the SQL part, since you didn't provide the names, you can do somenthing like this:
SELECT column_name(s)
FROM table_name
WHERE column_name BETWEEN value1 AND value2;
I've been tasked to get data from a SQL DB based off the values in Column A Row 3 onwards.
Example of Excel Sheet:
ITEM | QTY TO PICK | QTY ON ORDER | Column 2 | Column 3 etc
PART 1 | 5 | <Data will be populated here>
PART 2 | 12 | <Data will be populated here>
This code runs through a Command Button.
The data pulled from SQL will be populated starting in C3 onwards.
However, my below code only returns one row at a time.
I know where I need to make changes, I just don't know what. After at least 2 hours googling, I'm thoroughly stumped.
ItemNumber = Range("A3").Value
I've tried amending to ("A3:A100").Value but I just get errors.
Full code below;
Private Sub CommandButton2_Click()
' Create a connection object.
Dim cn As ADODB.Connection
Set cn = 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 & "server=<server name>;INITIAL CATALOG=<DB Name>;"
'Use an integrated login.
strConn = strConn & " INTEGRATED SECURITY=sspi;"
'Now open the connection.
cn.Open strConn
'
'
ActiveSheet.Range("C3:G10000").Clear ' clear out existing data
Dim ItemNumber As String
ItemNumber = Range("A3").Value
' Create a recordset object.
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
SQLStr = "Select * from vw_WorksOrder WHERE ITEMNO = " & ItemNumber & ""
rs.Open SQLStr, cn
' Copy the records into cell A1 on Sheet1.
Sheet4.Range("C3").CopyFromRecordset rs
' Tidy up
rs.Close
cn.Close
Set rs = Nothing
Set cn = Nothing
You could try building the SQL like so
"Select * from vw_WorksOrder WHERE ITEMNO in (" & _
join(application.transpose(range("a1:a5").Value),",") & ")"
or, for strings.
"Select * from vw_WorksOrder WHERE ITEMNO in ('" & _
join(application.transpose(range("a1:a5").Value),"','") & "')"
My advise is:
1.)
Create a table on SQL Server which contains parameters for your sql statement (itemnumber = 1)
2.)
Write a cycle which loops tru the ranges and adds values one by one to the table like:
i = 1
while cells(i,3).value <> ""
... Insert into temptable values (parameter1,parameter2, etc)
i = i+1
wend
3.)
Modify your sql statement for the recordset joining the table with the parameters and the data you would like to pull and paste that data.
Why is this code not working? Sorry for the generic question....
I am tasked with generating reports with reference information that needs to be drawn from an access database and an excel spreadsheet.
Basically in my role I'm responsible for providing service to people who live in a community; the record of all the people I provide service for is contained in an access database. There's reference information; address, name, situation, and other information needed for regular reports to funders or the board of directors.
I also provide service to local businesses; this information is contained within a spreadsheet, and not a database. The information could be put into a relational database, with the two related together; but there is resistance at the organization for significant changes to the system, nor is there really the knowledge of how to do this.
So I'm trying to move forward with a spreadsheet - if I provide service to person A or organization B, that this spreadsheet will check both the access database, and the excel spreadsheet to see whether that person or organization is entered; if it is, it should populate a table with that information, and assign it a unique code.
The unique code is determined on the basis of the database; whether or not the person or organization has been entered into the database before.
The spreadsheet I am working at the base with is this:
The bottom table I am looking to be a 'lookup' table. Its name is Lookup. The code I want to run with it looks like this (but obv not is this):
Sub getUserID()
Dim myTable As ListObject
Set myTable = Sheets("Client Codes").ListObjects("Lookup")
If myTable.ListRows.Count >= 1 Then
myTable.DataBodyRange.Delete
End If
With Sheets("Client Codes").ListObjects("Lookup").Add(SourceType:=0, Source:=Array(Array("ODBC;DSN=MS Access Database;DBQ=C:\database\here\test.accdb;DefaultDir=F:\Housing;DriverId=25;FIL=MS Access;MaxBufferSize=2048;PageTimeo"), Array("ut=5;")), Destination:=myTable.Range(Cells(1, 1)))
.CommandText = Array("SELECT Clients.ID, Clients.LastName, Clients.FirstName " & Chr(13) & "" & Chr(10) & "FROM `C:\database\here\test.accdb`.Clients Clients" & Chr(13) & "" & Chr(10) & "WHERE (Clients.LastName='" & Range("b1").End(xlDown) & "') AND (Clients.FirstName='" & Range("c1").End(xlDown) & "')")
End With
With Sheets("Client Codes").ListObjects("Lookup").Add(SourceType:=0, Source:=Array(Array("ODBC;DSN=Excel Files;DBQ=C:\spreadsheet\here\text.xlsx;DefaultDir=c:\spreadsheet;DriverId=1046;MaxBufferSize=2"), Array("048;PageTimeout=5;")), Destination:=myTable.Range(Cells(1, 1)))
.CommandText = Array("SELECT `Businesses$`.Operation" & Chr(13) & "" & Chr(10) & "FROM `C:\spreadsheet\here\test.xlsx`.`Businesses$` `Businesses$`" & Chr(13) & "" & Chr(10) & "WHERE (`Businesses$`.Operation='" & Range("b1").End(xlDown) & "')")
End With
End Sub
The hope is to be able to query the database on the basis of either a persons first and last name, or to query the spreadsheet on the basis of organization name; and if there is a value that is found, to add some information to the table 'Lookup'. If nothing is found, then I will know its a new entry, and enter in the information as such.
For reference, the database has 3 fields (ID, LastName, FirstName); and the spreadsheet has 1 column (Operation).
Really the confusion is focused here:
How to 'add' the information based on a query to the listobject to a pre-existing table
How to do this both with an access database and an Excel spreadsheet
Any suggestions on other ways how this can be done would be appreciated; pull information from multiple data sources into one table so that it can be validated in that table.
EDIT: If I did this through Access or another database program, I would do an INNERJOIN on two tables; one of people, the other of businesses. I'm looking to keep excel though - I find it to be more user friendly.
EDIT: Code based on Ian's response....generates the following error message:
'run time error -2147467259, could not find installable ISAM'
Research on the internet seems to indicate the following:
1) People have gotten this error before
2) There might not be a proper DLL installed - not certain this is the case, because I'm trying to access access from excel, and it doesn't seem like there is a DLL for access here: https://support.microsoft.com/en-us/kb/209805
3) There might be issue of how the connection string is framed. The data source might need to be in quotes, the JET OLEDB needs to be used not ACE, the connection string needs to be extended to include 'extended properties' here: Error: "Could Not Find Installable ISAM"
The last one is obviously the biggest target (and has the most error about it).
Option Explicit
Sub getUserID()
Dim cmd As New ADODB.Command
Dim conn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim strConn As String
Dim strSQL As String
Dim firstName As String
Dim lastName As String
firstName = "John"
lastName = "Smith"
strConn = "Provider = Microsoft.ACE.OLEDB.12.0;'DataSource=F:\Housing\bpTest.accdb'"
conn.Open strConn
strSQL = "SELECT * FROM Table Where FirstName = '" & firstName & "' AND LastName = '" & lastName & "';"
'& ... ' or You could put your InnerJoin SQL here
rs.Open strSQL, conn, adOpenDynamic, adLockOptimistic
If rs.EOF Then 'If the returned RecordSet is empty
MsgBox ("No record found")
Else
MsgBox (rs.Index)
End If
end sub
You will most like want to use ActiveX Data Objects to accomplish this. This will let you to pull data from the access database and also update the records in the access database from Excel.
Here is the Microsoft reference material: https://msdn.microsoft.com/en-us/library/ms677497(v=vs.85).aspx
And some sample code:
Dim cmd As New adodb.Command
Dim conn As New adodb.Connection
Dim rs As New adodb.Recordset
Dim strConn As String
strConn = "Provider = Microsoft.ACE.OLEDB.12.0;" _
& "Data Source=C:\AccessDatabse.accdb"
conn.Open strConn
strSQL = "SELECT * FROM Table Where FristName =" & strName & ... ' or You could put your InnerJoin SQL here
rs.Open strSQL, conn, adOpenDynamic, adLockOptimistic
If rs.EOF then 'If the returned RecordSet is empty
'...there is no match in database
Else
'the rs object will hold the ID you are looking for
End If
you can add a new records to the Access Database with:
myFieldList = Array("ID", "FirstName", "LastName")
myValues = Array(IDValue, FirstNameValue, LastNameValue)
rs.AddNew myFieldList, myValues
I am new to MS Access. I have been trying to import data from a Teradata table to MS Access database. I could establish the connection between the two using VBA. However, I am not being able to write the contents to the access database.
For Excel, we generally use objects like sheets and range to populate the values. What are Access counterparts of these objects?
Given below is the code that I have been using:
Sub TBEN_PR_DSM_SEAS()
Dim cn As ADODB.Connection
Set cn = New ADODB.Connection
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
Dim cmdSQLData As ADODB.Command
Set cmdSQLData = New ADODB.Command
Dim query As String
cn.Open "DRIVER={Teradata}; DBCNAME=ABC2; Persist Security Info=True; User ID= ******; Password=******; Session Mode=ANSI;"
Set cmdSQLData.ActiveConnection = cn
query = "SELECT * FROM PRODBBYCIADHOCWRK.TBEN_PR_DSM_SEAS;"
cmdSQLData.CommandText = query
cmdSQLData.CommandType = adCmdText
cmdSQLData.CommandTimeout = 0
Set rs = cmdSQLData.Execute()
End Sub
Can anyone please help me out with the rest of the part? I am using Access 2007-2010.
Thanks and regards,
Nirvik
MS Access is an interesting piece of software as it can serve as both a RDMS database and GUI console to a database. By default, it connects to the Jet/ACE SQL Engine (Windows .dll files) which would compare to SQLite another file-level RDMS. However, with MSAccess.exe Office program, this default can be switched or supplemented with any other ODBC/OLEDB compliant database including the server-level RDMS (Oracle, SQL Server, MySQL, Sybase, even Teradata) using linked tables. And in connecting to external backends it would compare to MySQL's phpmyadmin, SQL Server's Management Studio, PostgreSQL's pgAdmin, and other consoles.
Therefore, consider creating a linked table to Teradata using DoCmd.TransferDatabase where changes reflect on both ends without constant import and export of table data:
DoCmd.TransferDatabase acLink, "ODBC Database", _
"ODBC;DRIVER={Teradata}; DBCNAME=ABC2; Persist Security Info=True; User ID= ******;" _
& "Password=******; Session Mode=ANSI;", acTable, "TBEN_PR_DSM_SEAS", "NewAccessTable"
And for a static, local copy (which would add redundancy to your application needs) you can run an append or make-table query in Query Window or VBA's DoCmd.RunSQL or CurrentDb.Execute to a local Access table using above linked table.
INSERT INTO NewAccessTable SELECT * FROM [TBEN_PR_DSM_SEAS]
SELECT * INTO NewAccessTable FROM [TBEN_PR_DSM_SEAS]
Insert the data in the recordset into the Access table, using new recordset, Connection and Command objects.
Sub TBEN_PR_DSM_SEAS()
Dim cn As ADODB.Connection
Set cn = New ADODB.Connection
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
Dim cmdSQLData As ADODB.Command
Set cmdSQLData = New ADODB.Command
Dim query As String
cn.Open "DRIVER={Teradata}; DBCNAME=ABC2; Persist Security Info=True; User ID= ******; Password=******; Session Mode=ANSI;"
Set cmdSQLData.ActiveConnection = cn
query = "SELECT * FROM PRODBBYCIADHOCWRK.TBEN_PR_DSM_SEAS;"
cmdSQLData.CommandText = query
cmdSQLData.CommandType = adCmdText
cmdSQLData.CommandTimeout = 0
Set rs = cmdSQLData.Execute()
'Up to here is your code.
'Asuming you have a table in Access with identical number of fields, and field names:
dim dRst as dao.Recordset, fld as Variant
set dRst = CurrentDb.("AccessTable")
Do While Not Rs.EOF
dRst.AddNew
For Each fld in dRst.Fields
dRst.Fields(fld.Name) = rs.Fields(fld.Name)
Next
'Update an entire record:
dRst.Update
Rs.MoveNext: Loop
End Sub
Tables are Sheets and Queries select Ranges.
Fields are Columns and Records are Rows.
'Loop through Records
Do Until rs.EOF
'rs.Fields(0) is the first field returned from the Teradata query
'executed in your initial question.
Debug.Print rs.Fields(0)
rs.MoveNext
Loop
'Append to Table
'Have to create Table1 in Access database.
'Table1
'Field Name: Column1
'Data Type: Text
If rs.BOF = False Then rs.MoveFirst 'BOF = Beginning of file
DoCmd.SetWarnings False
Do Until rs.EOF 'EOF = End of file
DoCmd.RunSQL ("INSERT INTO Table1 (Column1) SELECT '" & rs.Fields(0) & "'")
rs.MoveNext
Loop
DoCmd.SetWarnings True
cn.Close
Set cn = Nothing
Seems a common enough problem this, but most solutions refer to concatenating multiple SQL commands, something which I believe can't be done with ADO/VBA (I'll be glad to be shown wrong in this regard however).
I currently insert my new record then run a select query using (I hope) enough fields to guarantee that only the newly inserted record can be returned. My databases are rarely accessed by more than one person at a time (negligible risk of another insert happening between queries) and due to the structure of the tables, identifying the new record is normally pretty easy.
I'm now trying to update a table that does not have much scope for uniqueness, other than in the artificial primary key. This means there is a risk that the new record may not be unique, and I'm loathe to add a field just to force uniqueness.
What's the best way to insert a record into an Access table then query the new primary key from Excel in this situation?
Thanks for the replies. I have tried to get ##IDENTITY working, but this always returns 0 using the code below.
Private Sub getIdentityTest()
Dim myRecordset As New ADODB.Recordset
Dim SQL As String, SQL2 As String
SQL = "INSERT INTO tblTasks (discipline,task,owner,unit,minutes) VALUES (""testDisc3-3"",""testTask"",""testOwner"",""testUnit"",1);"
SQL2 = "SELECT ##identity AS NewID FROM tblTasks;"
If databaseConnection Is Nothing Then
createDBConnection
End If
With databaseConnection
.Open dbConnectionString
.Execute (SQL)
.Close
End With
myRecordset.Open SQL2, dbConnectionString, adOpenStatic, adLockReadOnly
Debug.Print myRecordset.Fields("NewID")
myRecordset.Close
Set myRecordset = Nothing
End Sub
Anything stand out being responsible?
However, given the caveats helpfully supplied by Renaud (below) there seems nearly as much risk with using ##IDENTITY as with any other method, so I've resorted to using SELECT MAX for now. For future reference though I would be interested to see what is wrong with my attempt above.
About your question:
I'm now trying to update a table that
does not have much scope for
uniqueness, other than in the
artificial primary key. This means
there is a risk that the new record
may not be unique, and I'm loathe to
add a field just to force uniqueness.
If you are using an AutoIncrement for your primary key, then you have uniqueness and you could use SELECT ##Identity; to get the value of the last autogenerated ID (see caveats below).
If you are not using autoincrement, and you are inserting the records from Access but you want to retrieve the last one from Excel:
make sure your primary key is sortable, so you can get the last one using a query like either of these:
SELECT MAX(MyPrimaryField) FROM MyTable;
SELECT TOP 1 MyPrimaryField FROM MyTable ORDER BY MyPrimaryField DESC;
or, if sorting your primary field wouldn't give you the last one, you would need to add a DateTime field (say InsertedDate) and save the current date and time every time you create a new record in that table so you could get the last one like this:
SELECT TOP 1 MyPrimaryField FROM MyTable ORDER BY InsertedDate DESC;
In either of these cases, I think you would find adding an AutoIncrement primary key as being a lot easier to deal with:
It's not going to cost you much
It's going to guarantee you uniqueness of your records without having to think about it
It's going to make it easier for you to pick the most recent record, either using ##Identity or through sorting by the primary key or getting the Max().
From Excel
To get the data into Excel, you have a couple of choices:
create a data link using a query, so you can use the result directly in a Cell or a range.
query from VBA:
Sub GetLastPrimaryKey(PrimaryField as string, Table as string) as variant
Dim con As String
Dim rs As ADODB.Recordset
Dim sql As String
con = "Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source= ; C:\myDatabase.accdb"
sql = "SELECT MAX([" & PrimaryField & "]) FROM [" & MyTable & "];"
Set rs = New ADODB.Recordset
rs.Open sql, con, adOpenStatic, adLockReadOnly
GetLastPrimaryKey = rs.Fields(0).Value
rs.Close
Set rs = Nothing
End Sub
Note about ##Identity
You have to be careful of the caveats when using ##Identity in standard Access databases(*):
It only works with AutoIncrement Identity fields.
It's only available if you use ADO and run SELECT ##IDENTITY;
It returns the latest used counter, but that's for all tables. You can't use it to return the counter for a specific table in MS Access (as far as I know, if you specify a table using FROM mytable, it just gets ignored).
In short, the value returned may not be at all the one you expect.
You must query it straight after an INSERT to minimize the risk of getting a wrong answer.
That means that if you are inserting your data at one time and need to get the last ID at another time (or another place), it won't work.
Last but not least, the variable is set only when records are inserted through programming code.
This means that is the record was added through the user interface, ##IDENTITY will not be set.
(*): just to be clear, ##IDENTITY behaves differently, and in a more predictive way, if you use ANSI-92 SQL mode for your database.
The issue though is that ANSI 92 has a slightly different syntax than
the ANSI 89 flavour supported by Access and is meant to increase compatibility with SQL Server when Access is used as a front end.
If the artificial key is an autonumber, you can use ##identity.
Note that with both these examples, the transaction is isolated from other events, so the identity returned is the one just inserted. You can test this by pausing the code at Debug.Print db.RecordsAffected or Debug.Print lngRecs and inserting a record manually into Table1, continue the code and note that the identity returned is not that of the record inserted manually, but of the previous record inserted by code.
DAO Example
'Reference: Microsoft DAO 3.6 Object Library '
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = CurrentDb
db.Execute ("INSERT INTO table1 (field1, Crdate ) " _
& "VALUES ( 46, #" & Format(Date, "yyyy/mm/dd") & "#)")
Debug.Print db.RecordsAffected
Set rs = db.OpenRecordset("SELECT ##identity AS NewID FROM table1")
Debug.Print rs.Fields("NewID")
ADO Example
Dim cn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Set cn = CurrentProject.Connection
cn.Execute ("INSERT INTO table1 (field1, Crdate ) " _
& "VALUES ( 46, #" & Format(Date, "yyyy/mm/dd") & "#)"), lngRecs
Debug.Print lngRecs
rs.Open "SELECT ##identity AS NewID FROM table1", cn
Debug.Print rs.Fields("NewID")
Re: "I have tried to get ##IDENTITY working, but this always returns 0 using the code below."
Your code sends SQL and SQL2 through different connection objects. I don't think ##identity will return anything other than zero unless you ask from the same connection where you executed your INSERT statement.
Try changing this:
myRecordset.Open SQL2, dbConnectionString, adOpenStatic, adLockReadOnly
to:
myRecordset.Open SQL2, databaseConnection, adOpenStatic, adLockReadOnly
Here's my solution that does not use ##index or MAX.
Const connectionString = "Provider=SQLOLEDB; Data Source=SomeSource; Initial Catalog=SomeDB; User Id=YouIDHere; Password=YourPassword"
Const RecordsSQL = "SELECT * FROM ThatOneTable"
Private Sub InsertRecordAndGetID()
Set connection = New ADODB.connection
connection.connectionString = connectionString
connection.Open
Set recordset = New ADODB.recordset
recordset.Open SQL, connection, adOpenKeyset, adLockOptimistic
With recordset
.AddNew
!Field1 = Value1
!Field2 = Value2
End With
recordset.MoveLast
ID = recordset.Fields("id")
End Sub
Enjoy!
Try following macro code.First add a command button to the sheet from the control box and paste following codes in the code window
Private Sub CommandButton1_Click()
MsgBox GetLastPrimaryKey
End Sub
Private Function GetLastPrimaryKey() As String
Dim con As String
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim sql As String
con = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\myaccess.mdb;Persist Security Info=False"
sql = "SELECT MAX(id) FROM tblMyTable"
Set cn = New ADODB.Connection
Set rs = New ADODB.Recordset
cn.Open con
rs.Open sql, cn, 3, 3, 1
If rs.RecordCount <> 0 Then
GetLastPrimaryKey = rs.Fields(0).Value
End If
rs.Close
cn.Close
Set rs = Nothing
Set cn = Nothing
End Function
8 years late to the party... The problem you are having is that you are using dbConnectionString to create a new connection. ##identity is specific to the connection you are using.
First, don't close the original connection
'.Close
replace
myRecordset.Open SQL2, dbConnectionString, adOpenStatic, adLockReadOnly
with the connection you previously used for the insert
myRecordset.Open SQL2, databaseConnection, adOpenStatic, adLockReadOnly
and you'd have been all set. In fact, you don't even need to specify the table:
SQL2 = "SELECT ##identity AS NewID"