How to run a SQL select statement in VB - vba

I have been looking around but can't seem to find out how to do this.
I'm trying to execute a SELECT sql statement in VB that takes in a parameter from a form. For example the user selects a From and a To date and the SQL should take what they selected.
I know that you cannot use the DoCmd.Execute method for SELECT SQL so I would need to open the record set - but how? This is what I have tried so far
Dim recordSet As DAO.recordSet
Dim SQL As String
SQL = "SELECT * FROM tblWebMeetingData"
Set recordSet = CurrentDb.OpenRecordset(SQL)
'More code in here
recordSet.Close
Set recordSet = Nothing
Because this executes without an error I assume it's actually getting the results - so is there a way to see what it is actually returning?
Thanks

First: It's a good advice to rename the recordset to rs, for example, because "recordset" is a reserved name. This is misunderstandable.
This recordset contains the records you queried by your SQL statement. You may access those data by rs.fields("fieldname").value. Move to the next recordset with rs.movenext.
To incorporate the form's control value I use the way to build the full SQL statement prior to opening the recordset. Say the form is named "myform" and the control "mycontrol", you may write some kind of
SQL = "SELECT * FROM tblWebMeetingData WHERE myfield = " & forms!myform.mycontrol.value
Please be sure the form only contains valid values, because any wrong formatted value will directly lead to an SQL execution error.
I hope it was this, what you wanted.

Here you have come sample code about iterating trought RecordSet and using values from it( I hope it helps a bit):
Dim i As Integer
Do While Not rs.EOF
Sheets("D_" & day).Cells(i, 1) = rs.Fields(0).Value
Sheets("D_" & day).Cells(i, 2) = rs.Fields(1).Value
rs.MoveNext
i = i + 1
Loop
rs.Close

Related

Using the Month function as criteria in an Access SQL query

I'm trying to extract data from an Access 2016 database using SQL and VBA. Below is the code I'm trying to use and every time I run it, I get a "No value given for one or more parameters". I've also shown what I see in the immediate window.
vsql = "SELECT [ResDate],[ResNanme],[ResStart],[ResEnd] FROM [TrainingRoom] where Month([ResDate]) = " & MonNo
Set RecSet1 = Connection.Execute(vsql, dbrows, adCmdText)
Immediate Window:
SELECT [ResDate],[ResNanme],[ResStart],[ResEnd] FROM [TrainingRoom] where(Month([ResDate])) = 11
I don't see anything wrong but I'm sure this is user error. The "MonNo" variable is declared as an integer.
Any suggestions would be greatly appreciated. Thanks for the help.....
I've never used Execute method to open ADO recordset, only Open.
Assuming Connection is a declared and set variable - but it is a reserved word and really should not use as a variable. If code is behind same db pulling data from, could just use CurrentDb with DAO recordset variable and OpenRecordset method. Example that accepts default parameters for optional arguments:
Dim RecSet1 As DAO.Recordset
Set RecSet1 = CurrentDb.OpenRecordset(vsql)

SQL Query in Access not applying WHERE clause

I am an amateur vba programmer currently struggling with the following:
I wrote a simple SQL Query for my VBA program to extract data from an existing Query (GroupedData) in Access:
Dim strSQL as string
Dim db as dao.database
dim rs as dao.recordset
strSQL = "SELECT GroupedData.EmployeeID, GroupedData.End, GroupedData.LOB, GroupedData.Position, GroupedData.WorkStatus " & _
"FROM GroupedData WHERE (((GroupedData.End) Is Null) AND ((GroupedData.Position)=0) AND ((GroupedData.WorkStatus)=0));"
Set db = OpenDatabase(MY_DB, dbOpenDynaset)
Set rs = db.openrecordset(strSQL, dbOpenSnapshot)
Do While Not rs.EOF
ListBox1.AddItem rs!EmployeeID
rs.MoveNext
Loop
So my problem is that SQL is running smoothly but is not applying any filters (that is where clause - it produces records where workstatus and position contain values above 0)
I have done such queries in the past without having any issues. This time however I am stuck
Any help would be much appreciated!
Thank you
Ok i have fixed the issue. Here is what happened:
I have made a separate function that was retrieving Employee Name based on EmployeeID. But in that function i had recordset and database declared the same way, that is: rs and db. What happened when i ran the query was it was taking the first record filtered but then the rest of them were unfiltered because they were based on the recordset within the function (which is of course all of the employees) Such a silly mistake :) Thanks anyways

Delete all of a table's records and replace them with another table's records using VBA

I'm not quite sure why this isn't working. Debug is giving me an error: Item not found for rs2.Fields(fld) = rs1.Fields(fld)
Here's my code:
CurrentDb.Execute "DELETE * FROM " & appendTo_text.Value & ";", dbFailOnError
Set db = CurrentDb()
Dim fld As DAO.Field
Set rs1 = db.OpenRecordset(tableName_text.Value)
Set rs2 = db.OpenRecordset(appendTo_text.Value)
For Each fld In rs1.Fields
rs2.AddNew
rs2.Fields(fld) = rs1.Fields(fld)
rs2.Update
Next
Set fld = Nothing
rs1.Close
rs2.Close
Where's the part where you loop through all the rows? Plus, you're adding a new row for each field, rather than for each row. Finally, the problem is that fld inside the loop is an object, which when treated as a string will implicitly convert, returning the default property of Value. So you're trying to select the field via the field value from the other recordset--you should be using the field name from the other recordset.
Do While Not SourceRecordset.Eof
TargetRecordset.AddNew
For Each Field In SourceRecordset.Fields
TargetRecordset.Fields(Field.Name).Value = Field.Value
Next
TargetRecordset.Update
Loop
Also, could you please not name the variables rs1 and rs2? At least name them SourceRecordset and TargetRecordset. You don't want the developer coming after you to lie awake at night fantasizing about hunting you down and doing bad things to you.
If you are doing a lot of rows, you may also want to look into UpdateBatch and how to disconnect the recordset, so that you have decent performance.
Finally, if you do still have performance problems, recognize that the syntax Recordset.Fields(Field.Name).Value is slow. (If you were using ADODB, the fastest method would be to pass in an array of values directly in the AddNew method). However, you can still get a speed boost by obtaining a reference to each field like so:
Dim SourceOrderID As DAO.Field
Set SourceOrderID = SourceRecordset.Fields("OrderID")
Dim TargetOrderID As DAO.Field
Set TargetOrderID = TargetRecordset.Fields("OrderID")
Then instead of using For Each inside the Do While loop, just assign:
TargetOrderID.Value = SourceOrderID.Value
TargetOrderDate.Value = SourceOrderDate.Value
I guarantee this will be faster.
Also, if you are looking for speed improvements, if you've used With like in examples found in online in Microsoft documentation for DAO, try it without With to see if it's faster.

Importing specific Access table data into Excel using Excel as the front end

I am trying to store and retrieve data that is entered into Excel into Access. I am an Access newbie and already have an Excel program on the front end, leading me to drive the import from Excel. I have successfully figured out how to save my Excel Named Range into the desired Access table, but now I need to figure out how to pull specific data from that Access table back into Excel. I know I can simply use the Get External Data feature from Excel to import the entire Access table into Excel, but I need to be able to only import a specific portion of the table into Excel based upon a predetermined set of parameters. Is this possible to do?
As a background to the program, basically it stores data from part number runs. Not only do I need to save new part runs into an Access database (which I figured out), but I also need to be able to pull previous part number runs from Access back into Excel to perform further analysis. That is why I need to figure out how to import only a specific portion of the table. I'm not sure what code, if any, I can post since I'm basically looking for code from scratch; but if there's any code you think you need from my Excel program I'm happy to provide it. Thanks for your help. Below is the code:
Sub GetSpecData()
Application.ScreenUpdating = False
'*******************************************************************************
'Open the connection to the data source.
Set Connection = New ADODB.Connection
Connection.Open "Provider=Microsoft.Jet.OLEDB.4.0; " & "Data Source=\\Server2013\network_shared\QC SHARED\Databases\P&Q_Tracking_Data_Storage.mdb;"
'*******************************************************************************
'Create the new RecordSet.
Set Recordset = New ADODB.Recordset
With Recordset
'Define the appropriate Filter(s) and notify the user of the selection criteria.
Src = "Select * from Raw_Data where Tag = 'GHI' "
Src = Src & "or Tag = 'DEF' "
Src = Src & "or Tag = 'LMN'"
.Open Source:=Src, ActiveConnection:=Connection
'Write the field names.
For ODCol = 0 To .Fields.Count - 1
Tracking.Sheets("Selected Past Data").Range("B7").Offset(0, ODCol).Value = .Fields(ODCol).Name
Next
'Write the recordset.
Tracking.Sheets("Selected Past Data").Range("B7").Offset(1, 0).CopyFromRecordset Recordset
End With
Set Recordset = Nothing
Connection.Close
Set Connection = Nothing
'*******************************************************************************
'Create and format the table from the Recordset.
With Tracking.Sheets("Selected Past Data")
DataLastRow = .Range("A" & Rows.Count).End(xlUp).row
.ListObjects.Add(xlSrcRange, Range("B7:M" & DataLastRow), , xlYes).Name = "INC2tbl"
.ListObjects("INC2tbl").ShowTotals = True
End With
Application.ScreenUpdating = True
'*******************************************************************************
End Sub
After googling the suggestion in the comment below, I have a couple questions. First, the code above seems to filter access data by three keys: GHI, DEF, and LMN. Am I interpreting that correctly? Second, where it says "Select * from Raw_Data where Tag = 'GHI' ", since that's in quotes, that's not actual code that will be executed, correct? That's simply a prompt or something like it, correct?
SELECT * FROM TABLE; OUTPUT TO TABLEName.EXL
FORMAT sql;
First, the code above seems to filter access data by three
keys: GHI, DEF, and LMN. Am I interpreting that correctly?
Second,
where it says "Select * from Raw_Data where Tag = 'GHI' ", since
that's in quotes, that's not actual code that will be executed,
correct? That's simply a prompt or something like it, correct?
First and second questions relate closely, so I'll answer as one. The basic idea here is that there is a connection to the database you defined (in the Connection.Open statement). The connection itself does nothing then that; establish a connection. The actual communication with the database is done in a specific language, named SQL (there are many dialects, but for simplicity sake, call it SQL for now). So your code in in the VBA language, but the communication with the database is done in SQL. The VBA code has to produce SQL statements (and those are strings, so you need the quotes). That's what the Src variable holds; and SQL statement. In this case:
"Select * from Raw_Data where Tag = 'GHI' or Tag = 'DEF' or Tag = 'LMN'"
I think this is not the place to teach you SQL, but there is plenty information on the net about it. What this statement does is:
select all columns from table "Raw_Data", but only those rows of data that has 'GHI', 'DEF' or 'LMN' in the Tag column.
So to receive all the data from table "part_numbers", you would have to use:
"SELECT * FROM part_numbers;"
And if you need to import only columns "col_1" and "col_2", you would use:
"SELECT col_1,col_2 FROM part_numbers;"
And if you need to import only columns "col_1" and "col_2", and only rows with "part_id" lower than 1000, you would use:
"SELECT col_1,col_2 FROM part_numbers WHERE part_id < 1000;"
That's it really. Now if your recordset (think of it as an array that holds the data you asked for) has queried the database, you can loop it to parse the data. Something like:
Set Recordset = Connection.Execute(Src)
Do until Recordset.EOF
debug.print Recordset!col_1
Recordset.movenext
loop
Again, google something like: "vba excel adodb access", and you'll hit plenty examples.
After researching SQL code formatting more I have made more sense of the subject. Thanks for the help.

Checkbox to SQL Database

I have a problem which I'm struggling to fix.
I have a form with many checkboxes containing email addresses, the result of which is sent to another page.
This page will send out newsletters.
This is working at the moment, but what I would like to do is include their name.
From the form received I get the results (xx#xx.com, yy#yy.com etc...)
I have managed to separate the results and put them into an array, but now I need to access the SQL db and find the names to the email address. This is where I'm struggling. Here is the code that I've tried to use:
name = request.form("list")
If name = "" Then
Response.redirect ("batchselect.asp")
End If
Dim your_name()
Dim mode
Dim mode_a
Dim i
mode=Request("list")
mode_a=split(mode,",")
For i=LBound(mode_a) to UBound(mode_a)
Next
i = i - 1
Redim PRESERVE your_name(i)
For t = 0 to i
Set conn = Server.CreateObject("ADODB.Connection")
conn.open connStr
strSQL = "SELECT name FROM emails WHERE emails = '" & mode_a(t) & "'"
Set rs = conn.Execute(strSQL)
your_name(t) = rs("name")
Next
If I try and run this I get this error:
Error Type:
ADODB.Field (0x800A0BCD)
Either BOF or EOF is True, or the current record has been deleted. Requested operation requires a current record.
I know the problem is in the SQL Query 'mode_a(t)', because if take out the for... next and change this to mode_a(0) or mode_a(1) it works no problem.
I'm using MS SQL and classic asp
Thanks in advance
Not sure why you are doing this:
For i=LBound(mode_a) to UBound(mode_a)
Next
i = i - 1
Surely this would be enough, and you get rid of any ambiguity in the value of i:
i = UBound(mode_a) - 1
If you are not dealing with too many email addresses I would consider trying to use an IN statement with sql and just bring back all the records for the emails. It would be so much quicker and save you a number of db calls.
If you did this then you could just return the email address with the name in the recordset row and use that to match up.
As for your actual question though I would check the value of i and make sure that it is not being set to -1 or some other value that doesn't actually point to an index. Because your error is happening because there are no results being returned. You should consider checking for EOF before you actually use the recordset.