Using textbox values in IN statement - sql

I'm trying to get this to work? How can I set a textbox to be used in an IN() statement? I would like users to be able to list out countries they'd like to query on
SELECT *
FROM Table
WHERE CountryID IN (forms!frmImport!txtCountries)

You can't just put the name of the textbox directly into the SQL string.
Instead, you need to use the content of the textbox to build a SQL string like this:
SELECT * FROM Table WHERE CountryID IN (1,2,3)
If your users enter a comma-separated list of CountryIDs into the textbox, you can build the SQL like this:
Dim SQL As String
SQL = "SELECT * FROM Table WHERE CountryID IN (" & Forms!frmImport!txtCountries & ")"
But I wouldn't do it this way because it's simple, but prone to input errors and SQL injection.
A better way would be to use a list box, set the Multi Select property (so that multiple entries can be selected) and fill it with a list of all available countries.
Then, the user can select the ones that he wants, and you can build the SQL string using the selected items from the listbox:
Dim ListItem As Variant
Dim CountryList As String
Dim SQL As String
For Each ListItem In Forms!frmImport!lstCountries.ItemsSelected
If CountryList > "" Then
CountryList = CountryList & ","
End If
CountryList = CountryList & ListItem
Next
SQL = "SELECT * FROM Table WHERE CountryID IN (" & CountryList & ")"

Related

How to use a query as a control source for a textbox on a form?

I have a form myForm that's binded to a table tbl in my database. (I don't know if binded is the correct term, but It shows records from tbl on by one.)
In the form:
contact: textbox, binded to tbl.contact.
dailyCount: textbox, should show the amount of contacts entered today.
In the table:
contact
dateEntry
The query I want to use is:
SELECT count(*)
FROM tbl
WHERE contact = currentContact
AND month(dateEntry) = month(now)
AND day(dateEntry) = day(now)
AND ear (dateEntry) = year(now)
Where currentContact is the contact that is showing on the form now.
I tried putting the query in the dailyCount dataSource, but It's not working. When I click on the three dots on datasource to access the wizard, I get a window to build functions and not queries.
How do I get the currentContact showing on the form into the query?
There are multiple ways to do this. For a couple of reasons, I don't like to hardcode queries in the datasource of a specific field, and I mostly build/assign all my queries in VBA. So here's how I would do it.
In the load event of you form :
Private Sub Form_Load()
Dim SQL As String
Dim RST As Recordset
dim theCOntact as string ' Change accordingly
theCOntact = Me.currentContact ' I don't know how your fields are named, so change accordingly
SQL = "SELECT count(*) AS cnt FROM tbl WHERE contact = " & theContact & "' AND month(dateEntry) = month(now) AND day(dateEntry) = day(now) AND Year(dateEntry) = year(now)"
Set RST = CurrentDb.OpenRecordset(RST)
If RST.BOF Then
dailyCount.Value = RST!cnt
Else
dailyCount.Value = 0
End If
End Sub
Assuming your contact field is string, if its a number remove the quotes in the SQL
Probably the simplest approach is to use the DLookup function with an associated query:
Create and save a named query with your SQL code or equivalent. Let's call it "qryDailyCount". Note that it should be modified to look something like this (in particular, name the column and change the record reference to a GROUP BY for now):
SELECT count(*) as DailyCount
FROM tbl
WHERE month(dateEntry) = month(now)
AND day(dateEntry) = day(now)
AND year (dateEntry) = year(now)
GROUP BY contact
In the dailyCount textbox, set the Control Source to something like this:
=DLookUp("Count";"qryDailyCount";"contact = [contact]")
(Note that if the contact field is a text field, you must enclose it with single quotes.)

Create Variable or Method to use value in multiple forms

Fairly new to VBA. I have a list box on a form within Access which is populated with data from a table. Selecting a value from the list box gives and ID which is then used to perform a query. I need this ID to be available for use in another form to perform a query based on the Value. What is the best way of achieving this?
`Dim IDValue As String
IDValue = Me.lstBoxCompanyName.Value
CompDetailSQL = "SELECT * FROM Companies WHERE Companies.CompanyID = " & IDValue`
In a module
Dim IDValue AS Integer
Sub setIDValue(id As Integer)
IDValue = id
End Sub
Function getIDValue() As Integer
getIDValue = IDValue
End Function
Then from any of your code
'This will set you ID
setIDValue YOUR_VALUE
'This will retrieve the value
getIDValue
'so your code could be
setIDValue Me.Me.lstBoxCompanyName.Value
CompDetailSQL = "SELECT * FROM Companies WHERE Companies.CompanyID = " & getIDValue
Obviously this could use some Error Handling in the event that No IDValue is set. Also I used integer even though I see you are using a String the data type should be the same type as CompanyID so you can change Integer to String if needed but your will also have to change your query to SELECT * FROM Companies WHERE Companies.CompanyID = '" & getIDValue & "' because your query implies a number currently.
You can gain access to another forms controls by specifying the full path. Example :
Forms!MyFormsName!MyControlsName.Value
and
Forms!frmCustomer!CboCustomer.Column(0)
So if you want to access a value in VBA that is contained in another form and use it as part of a query it would look like:
CompDetailSQL = "SELECT * " & _
"FROM Companies " & _
"WHERE CompanyID = " & Forms!frmCustomer!lstBoxCompanyName.Value
in ms Access you can also simply use form_NAMEofFORM.NAMEofCONTROL
Example you can reference
dim myAmount as double
myAmount = form_receipt.total
to access the value showing on form receipt textbox total.

MS Access Query from form for multiple records in text box

I have created a form in Access which queries a single record in a set date range. This works beautifully. My question is how can I query multiple records from a form text box.
Something Similar to the SQL function
IN ('XXX','XXX','XXX')
I want my users to be able enter multiple values on the form and it will spit out the corresponding Data.
Try the Split() function. Something like this:
Dim arr() As String
Dim MySQL as String
If Len(Me!MyTextbox) > 1 Then
MySQL = "SELECT * FROM MyTable WHERE MyField in ("
arr = Split(Me!MyTextbox.Text, ",")
For i = LBound(arr) To UBound(arr)
MySQL = MySQL & "'" & arr(i) & "', "
Next
MySQL = Left(MySQL, Len(MySQL) - 2) & ")"
Me.RecordSource = MySQL
Else
MsgBox "There are no values to search for."
EndIf
You would just loop through the array and add each value to a WHERE string. You would have to instruct your users (via a label on the form) to separate values using a comma.
When you want to allow multiple entries it's generally better to have a datasheet subform where users can enter data one per row. Then you use the subform data in queries just like a regular table.

Using a VBA array in a SQL statement

I am trying to write some code that uses SQL to delete rows from several tables.
A user would type type numbers into a textbox that are separated by a comma which is used in the WHERE clause of a SQL DELETE statement.
I have managed to split the string into a variant array and now I want to insert it into my SQL statement.
How do I insert the variable into the SQL statement and have it run through every element of the array?
EDIT: A bit more digging has taught me about For Each Next statements. This is probably what im looking for.
I suggest you build your query in VBA, then your list of numbers can be an IN statement:
sSQL = "DELETE FROM table WHERE ID In (" & MyList & ")"
Where MyList = "1,2,3,4" or such like.
As you can see, you do not need an array and a textbox would be more suitable than a combobox. If you wish to allow your users to select by say, a name, then a listbox is useful. You can iterate through the selected items in the listbox and build a string from IDs to be used in the Delete statement. ( MS Access 2007 - Cycling through values in a list box to grab id's for a SQL statement )
You can then execute the sql against an instance of a database. For example:
Dim db As Database
Set db = CurrentDB
db.Execute sSQL, dbFailOnError
MsgBox "You deleted " & db.RecordsAffected & " records."
A generic approach
WHERE
','+Array+',' like '%,'+col+',%'
It will consider all the numbers available in your Array
You could make it simple and elaborate a string, something like
stringBuilder sb = StringBuilder("DELETE FROM YOURTABLE WHERE ");
foreach(string st in stringArray){
sb.append("YOURFIELD='" + st + "'");
//If it is not the last element, add an "OR"
if (st != stringArray[stringArray.length -1]) sb.append(" OR ");
}
//Now, you have a string like
//DELETE FROM YOURTABLE WHERE YOURFIELD='hello' OR YOURFIELD='YES'
//... do something with the command
This method will fail if you want to run SQL query on two (or multiple) columns using array values from two different arrays. .e.g
where col1=array1(i) and col2=array2(i)

MS access SELECT INTO in vba

I'm having some issues with some functionality of my application. There is a particular instance where I have an instance of a 'pending class' on a form for an administrator to review. The form is populated with students associated with this pending class. After their grades are finished, I have a button at the footer that will delete this class from my 'pending' table and add the grades to all of the students. This works.
However, I want to essentially copy this pending class, which just has the class name, date, and teacher to a completed class table before it's deleted from pending. Since no data about this class other than the primary key(class number) persists throughout this form, I can't populate the other fields(class name, date) of the row into my completed class table.
I am trying a "SELECT INTO" operation in VBA to get these values. It's going like this:
dim cname as String
dim classdate as Date
dim pid as integer
dim teacher as String
dim qry as String
pid = [Forms]![frmClasses]![txtID]
qry = "Select className INTO cname FROM tblPending WHERE tblPending.id = " & " ' " & pid & " ' " & ";"
db.execute qry
debug.print qry
debug.print cname
From here, I do the same operations for each other variable, build my INSERT query, and execute it. The problem is-- my select into's are not working. Debug.print shows that the local variables were never initialized from the SELECT INTO statement. Any thoughts?
First, having all classes in one table and just setting a "NotPending" or "Completed" column would be better.
Having two identical tables for classes and moving values from one into the other to indicate status changes is bad database design.
If you really need to do this by using two tables and copying rows, then you need an INSERT INTO query (and not SELECT INTO), as already mentioned by Remou in the comments, because SELECT INTO creates a new table (or overwrites an existing one with the same name, if already there).
The syntax for INSERT INTO looks like this:
INSERT INTO CompletedClassTable (ClassName, Teacher)
SELECT ClassName, Teacher FROM tblPending WHERE id = 123
And finally, you asked this in a comment:
So SELECT INTO is completely different in Access than Oracle? In Oracle and PL/SQL, you can select a row into a variable OR a table. In Access can you not select into a variable?
To load a row into a variable, you need to use a Recordset.
Example code to load your query into a Recordset and output the ClassName field:
Dim RS As DAO.Recordset
Set RS = CurrentDb.OpenRecordset("SELECT * FROM tblPending WHERE id = 123")
If Not RS.EOF Then
Debug.Print RS("classname")
End If
RS.Close
Set RS = Nothing
Seems you want to retrieve a text value, className, from tblPending where tblPending.id matches the value found in your text box, txtID, and store that text value in a string variable named cname.
If that interpretation is correct, you needn't bother with a query and recordset. Just use the DLookup Function to retrieve the value, similar to this untested code sample.
Dim cname As String
Dim pid As Integer
Dim strCriteria As String
pid = [Forms]![frmClasses]![txtID]
strCriteria = "id = " & pid
cname = Nz(DLookup("className", "tblPending", strCriteria), vbNullString)
Debug.Print "cname: '" & cname & "'"
Notes:
I assumed the data type of the id field in tblPending is numeric. If it is actually text data type, change strCriteria like this:
strCriteria = "id = '" & pid & "'"
DLookup() returns Null if no match found. Since we are assigning the function's return value to a string variable, I used Nz() to convert Null to an empty string. Alternatively, you could declare cname As Variant (so that it can accept a Null value) and get rid of Nz().