I have a problem of SQL syntax which I have been struggling for days.
I have created an MS Access 2010 Form called IP Country Form into which I want to insert into a TextBox called Country the Country obtained from the following query which queries a table called IPLocation which contains the Countries according to IP Numbers with the fields:
IPNS IPNE CY2(2 letter Country Code) CY3(3 Letter country Code) Country (full Country Name)
The table rows looks like this:
IPNS | IPNE | CY2 | CY3 | COUNTRY
19791872 | 19922943 | TH | THA | THAILAND
The form calculates the IP Number from the IP address and places it in a TextBox called IPNumber, which I then use in an SQL Query to obtained the Country which corresponds to it.
My current query is:
SELECT IPLocation.IPNS, IPLocation.IPNE, IPLocation.CY2, IPLocationCY3, IP.Location.Country
FROM IPLocation
WHERE (((IPLocation.IPNS)<" & [Forms]![IP Country Form]![IPNumber])
And ((IPLocation.IPNE) > " & [Forms]![IP Country Form]![IPNumber]))
IPNS, IPNE are Numbers as is IPNumber
Essentially the query is designed to find the Country where the IPNumber lies between IPNS and IPNE.
Any help would be much appreciated.
A test query I use:
Set rst = dbs.OpenRecordset("
SELECT IPLocation.IPNS, IPLocation.IPNE, IPLocation.CY2, IPLocation.CY3,
IPLocation.Country
FROM IPLocation
WHERE (((IPLocation.IPNS)>19791871)
AND ((IPLocation.IPNE)<19922944))
")
Works fine and returns the correct country
On the query you use on your code you have the comparison operators reversed on the AND clause.
IPLocation.IPNS) > " & [Forms]![IP Country Form]![IPNumber]
IPLocation.IPNE) < " & [Forms]![IP Country Form]![IPNumber]
Should be:
SELECT IPLocation.IPNS, IPLocation.IPNE, IPLocation.CY2, IPLocationCY3,
IP.Location.Country
FROM IPLocation
WHERE (((IPLocation.IPNS) > " & [Forms]![IP Country Form]![IPNumber])
And ((IPLocation.IPNE) < " & [Forms]![IP Country Form]![IPNumber]))
Related
I have an Access DB, along with tables and forms.
In one table I have customers and in a second table as a subdatasheet on the first table I have tags.
I have created a form which shows the customer list along with the subdatasheet which displays all the tags that a customer has.
I would like to filter based on a field of the main datasheet, and on the subdatasheet for a tag.
E.g. where customer_name = "Peter" and tag ="Neighbor"
I saw this code but when trying to use it fails.
Filter on Subdatasheet
When trying Set mainDS = Me.Controls(dataSheetName).Form where do I find the datasheetName?
I tried entering Form Name, Table Name, I searched in form properties but didn't manage to find a solution.
Based on your question it sounds like you are new to Access and you should review table normalization.
Everything starts with a normalized table structure. Unfortunately you are starting with the relatively difficult Many to Many Relationship. Each Customer can have many tags which is a One to Many Relationship, but there wouldn't be much point to comparing customers unless they could have the same tags, which means each tag can have many customers as well. For example, create your tables with the corresponding primary and foreign keys and tell access about the relationhip by hitting the ribbon and selecting the relationships tool:
The raw data in the CustomersTags table is what you are interested in, but it is not userfriendly
----------------------------------------------------------------
| CustomerTagID | CustomerID | TagID |
----------------------------------------------------------------
| 1 | 1 | 1 |
----------------------------------------------------------------
| 2 | 3 | 1 |
----------------------------------------------------------------
| 3 | 2 | 3 |
----------------------------------------------------------------
| 4 | 2 | 4 |
----------------------------------------------------------------
| 5 | 2 | 5 |
----------------------------------------------------------------
| 6 | 3 | 1 |
----------------------------------------------------------------
| 7 | 2 | 1 |
----------------------------------------------------------------
| 8 | 3 | 5 |
----------------------------------------------------------------
| 9 | 2 | 2 |
This is why we use forms for entering and viewing the data. For speeds sake select CustomersTags and hit create table:
This is not user friendly so we don't show primary keys and replace (right-click and select change to) all the i'ds with user friendly combo-boxes. I also change the forms format to Data sheet.
I continue making the form prettier and add two unbound combo boxes to the header to filter the form with. You can do this with listboxes or checkboxes, or etc as well. For instance a multi-select list box so you can select multiple tags. In all cases you just set the forms filter
Option Compare Database
Option Explicit
'select the combobox afterupdate property to get these events
'you can use macro's if you want
'the exact code is very dependent on things like whether you have default values. I just show the most necessary case
Private Sub cmbCustomer_AfterUpdate()
If (IsNull(Me.cmbCustomer) Or IsNull(Me.cmbTag)) Then
'do nothing
Else
'filter the forms record source
Me.filter = "(CustomerID = " & Me.cmbCustomer & ") AND TagID = " & Me.cmbTag
Me.FilterOn = True
End If
End Sub
Private Sub cmbTag_AfterUpdate()
If (IsNull(Me.cmbCustomer) Or IsNull(Me.cmbTag)) Then
'do nothing
Else
'the filter is just the WHERE PART of an sql statement without the where
Me.filter = "(CustomerID = " & Me.cmbCustomer & ") AND TagID = " & Me.cmbTag
Me.FilterOn = True
End If
End Sub
Next, I switch the forms format to continuous forms and continue prettyifying because to my surprise the datasheet format was blocking setting the filter string.
Here is some guidance for making comboboxes, comboboxes are used for displaying userfriendly values instead of IDs. For instance instead of displaying the raw CustomerID we display the Customer_name but the value in the combobox is the CustomerID. The unbound combobox's value is the CustomerID corresponding to the user friendly Customer_Name the user selects. Whether the combobox is bound or unbound you set them up in the same way. Select a bunch of columns from some table or query then declare how many columns you are showing and their width. To hide a column set it's width to 0. The order of the columns determines the order of the numbers. I bound to the tables and both tables go ID then user friendly description so column-widths is 0,1
This example allows selecting impossible combinations of Customer and tag which will cause an error. One way to avoid this would be to set the rowsource of the alternate combobox when you choose a value on the first. For instance, when you pick a customer you restrict the tags which can be selected in the next combobox. This is cascading comboboxes:
Option Compare Database
Option Explicit
Private Sub cmbCustomer_AfterUpdate()
'it helps to use the query designer to get the sql right
Me.cmbTag.RowSource = "SELECT Tags.TagID, Tags.FriendlyDescription" & _
" FROM Tags INNER JOIN (Customers INNER JOIN CustomersTags ON Customers.CustomerID = CustomersTags.CustomerID)" & _
" ON Tags.TagID = CustomersTags.TagID WHERE (((CustomersTags.CustomerID)= " & Me.cmbCustomer & "))"
Me.cmbTag.Visible = True
End Sub
Private Sub cmbTag_AfterUpdate()
Me.filter = "(CustomerID = " & Me.cmbCustomer & ") AND TagID = " & Me.cmbTag
Me.FilterOn = True
Me.cmbCustomer.SetFocus
Me.cmbTag.Visible = False 'quick and dirty reset 'can't invis a focused control
Me.Refresh
End Sub
I'm currently making a database for a (fake) DVD Rental business for a school assignment.
I have created a table which links genre and DVD information, as well as separating any instances of two genres in one field. This looks like the following image:
I have created a query to contain the DVD names (linked by genre_ID) and the related genres, and that is shown below:
I have now moved the query into a form, shown here:
The combobox at the top is intended to be used for searching for genres, but I cannot figure out how to achieve that (preferably using VBA), so it will filter any searched for genres and show all films that match them (regardless of what field they are in).
I don't think the teacher will care too much that the database cannot handle films with 3 genres, so I won't need to change that.
This is only first problem appeared due bad database design. This is typical many-to-many relation and it would be better to use 3 tables instead of one.
But if you still need filtering by more than one field, just change RecorSource property in AfterUpdate event of combobox, WHERE clause should contain all fields with conditions connected by OR operator:
"WHERE genre1 = '" & Me.cboSearch & "' OR genre2 = '" & Me.cboSearch & "' OR genre3 = '" & Me.cboSearch & "'"
The same way you can change Filter property instead of RecordSource
You should have such configuration which allows you to add >=0 genres per movie.
+---------------+-------------+-------------------------------------+
| DVD table | Genre Table | DVD_VS_GENRE_TABLE |
+---------------+-------------+-------------------------------------+
| dvd_id | genre_id | DVD_ID(foreignkey to dvd table) |
| Name | genre | GENRE_ID(foreignkey to genre table) |
| other columns | | |
+---------------+-------------+-------------------------------------+
and then its the matter of your SQL code to filter
mSQL=Select tbl_dvd.name, tbl_genre.genre
from (tbl_dvd left join tbl_dvd_vs_genre on tbl_dvd.dvd_id = tbl_dvd_vs_genre.dvd_id) left join tbl_genre on tbl_dvd_vs_genre.genre_id = tbl_genre.genre_id
WHERE (genre like "*" & yourcombo.value & "*")
me.yoursubform.form.recordset := msql
and you can assign this code to your on change event which will filter while typing..
ps: haven't tested the code but you get the logic.
I Have a database called Capitals4
I have a table called Capitals
I have created 3 columns called Country, Capital, Population
I have 4 TextBox's and a button on my windows form
When I type the name of a country which is in my database in to 1 of the TextBox's and hit the button I want it to search my database and display all information in the row for that country.
I named 1 of my TextBox's TextBoxSearch
This is where I will type in the name of a country. Below is the sql statement I thought was right
sql = "SELECT * FROM Capitals WHERE Country='" & TextBoxSearch.Text & "'"
Country.Text = CStr(ds.Tables("Capitals4").Rows(0).Item(1))
I named the 3 TextBox's that I want the data displayed in
Country
Capital
Population
I don't know if my sql statement above is correct as you can see above because I have put a line in like
Country.Text = CStr(ds.Tables("Capitals4").Rows(0).Item(1))
It simply lists whatever country is on Row0 item 1
Can anyone help me out?
Thanks
Country.Text = CStr(ds.Tables("Capitals4").Rows(0).Item(1))
I am trying to create a search form that can search from one table at a time based on the table selected by the user from a combo-box. I have a text box called searchCriteria and the combo-box is called TableList. The idea is that if the user wanted to search customer_table, she would select “customer_table” in the combo box, enter her search criteria in the text box, and press the search button. If she wanted to search order_table, she would select that table from the combo-box and so on. I would like the query to return all full records pertaining to the criteria entered. So, for example, if the user searched “James” from the customer table, I would like the full records (all fields) returned where the criteria “James” is present:
Company | First Name | Last Name | Account # | Sales Rep
Jammy Juice | James | Dan | 555 | Jim Halbert
Jameson Car Shop | Tom | Cramb | 556 | Dwight Smiles
Landon Refrigeration | Bob | McVance | 557 | James Bland
From my understanding, this will require some VBA to write a query…
I am assuming the query would be something like the following:
SELECT t.* FROM customer_table t WHERE (t.*)::text LIKE '%James%';
Where the string entered (James) and the table name (customer_table) are entered by the user.
Simply, I'm having trouble getting the form data (the table name and search text) into my query.
Does anyone know how to implement this in Microsoft Access 2010? Any insight would be appreciated.
The any sequence of characters wildcard in Access is * not %. If you want to search all fields in Access then you could concatenate all the fields:
WHERE [FirstName] & [Surname] & [City] & [Address]
LIKE "'*" & Forms!frmSearch!txtFind & "*'"
You might separate the fields with a distinct character, to prevent finding words that overlap between the fields.
Or, individually, but less efficient:
WHERE [FirstName] Like "'*" & Forms!frmSearch!txtFind & "*'"
OR [Surname] Like "'*" & Forms!frmSearch!txtFind & "*'"
OR [Address] Like "'*" & Forms!frmSearch!txtFind & "*'"
(I don't know where (t.*)::text came from, but it is not Access.)
So you will firstly need to discover all the field-names for the table they have selected. You can obtain the TableDef for the table-name they have selected and loop through its Fields collection to obtain the field-names. There are other ways to do this. For example, GetSchema.
Here is the LAZY way of doing this in Access 2010:
Create a continuous form
In the form Properties, set Navigation Buttons = Yes
When you open the form, you will see a Search box:
Type what you want to search for. Hit Enter to see further matches.
Notes:
This searches all fields displayed on the form
This does not restrict records to the search term
This is probably not a good idea for very large recordsets
There might be a need to do some user training for this feature
To refer text selected in combo-box
Me.TableList.Column(0)
To refer text in text box
Me.searchCriteria.Text
So your VBA command will look like
DoCmd.RunSQL("SELECT t.* FROM " & Me.TableList.Column(0) & " t WHERE (t.*)::text LIKE '%" & Me.searchCriteria.Text & "%'")
I need to run a query that would pull information from a field that has 2 types of data .
Field is address and has 123 avenue as data and bb#yahoo.com.
I need to make 2 fields one for email and one STaddress from table customer and field address?
anyone can i assis..
its access and vb query
I thought of this
Select customer.address from customer where address like "#"
but still i need to display the the data of address field to 2 different fields...
Here is the query that fetches the two different fields:
select iif(field like '*#*', field, NULL) as email,
iif(field like '*#*, NULL, field) as address
from t
The usage of like in Access is a bit different from other databases.
I would suggest that you create a view with this logic. If you actually want to modify the table, you will have to add columns and populate them with logic like the above.
Based on this question and your duplicate question, I understand your table has a field which includes both the street address and email address and you want to split those into separate fields.
So your table includes this ...
YourField
------------------------------
1234 ave willie haha#yahoo.com
123 avenue bb#yahoo.com
And you want this ...
YourField street_address email_address
------------------------------ --------------- --------------
1234 ave willie haha#yahoo.com 1234 ave willie haha#yahoo.com
123 avenue bb#yahoo.com 123 avenue bb#yahoo.com
If that is correct, you can use the InstrRev() function to determine the position of the last space in YourField. Everything before the last space is the street address; everything after is the email address.
SELECT
y.YourField,
Left(y.YourField, InstrRev(y.YourField, ' ') -1) AS street_address,
Mid(y.YourField, InstrRev(y.YourField, ' ') +1) AS email_address
FROM YourTable AS y;
You may need to add a WHERE clause to ensure the query only tries to evaluate rows which include your expected YourField value patterns.
Try something like this:
select *,
(case locate('#', address) when 0 then null else address) as email,
(case locate('#', address) when 0 then address else null) as street
from table;
You'd probably need to adjust the name of "locate" function - I'm not sure if it is the same in access database.
If you have a street address and then an email address in the same field, and want to split them, then use this.
We'll call your original field Addy, and the new fields Street & Email.
SELECT Left(Addy, InStrRev(Addy, " ", InStr(Addy, "#")) - 1) AS Street, mid(Addy, InStrRev(Addy, " ", InStr(Addy, "#")) + 1) AS Email.
What this does is look for the #, then go backwards and look for the first space. The first function takes every left of that space and calls it Street, while the second function takes everything to the right.
The function is really 3 functions nested together. To really understand what it's doing, I'll dissect it.
I = InStr(Addy, "#")
J = InStrRev(Addy, " ", I)
Street = Left(Addy,J-1)