I have an array ListBoxContents(), it will contain the items like '15', '16','25'..upto 10 items. I'm trying to retrieve data in the column Bnumber where data of length >6 and starting with('15', '16','25'...) i.e those items specified in listbox .And trying to query these listbox items in where cluase of the sql statement
Table column Bnumber contains
Bnumber
152
156
1523
16417
AA454
CC654
18A16
1826
18A16
25A76
54A16
54235A68
My VBA code
Private Sub arraywhere()
Dim qry As String
Dim Size As Integer
Size = Form_Input_From.lstdigits.ListCount - 1
ReDim ListBoxContents(0 To Size) As String
ReDim LContents(0 To 30) As String
Dim m As Integer
For m = 0 To Size
ListBoxContents(m) = Form_Input_From.lstdigits.ItemData(m)
Next m
For m = 0 To Size
qry = "SELECT col1,col2,Bnumber " & _
"FROM table WHERE (Len([table].[Bnumber]))>6) AND (Left
([table].[Bnumber],2))=(" & ListBoxContents(m) & ");"
Next m
Debug.Print qry
Application.CurrentDb.QueryDefs("[arrayqry]").sql = qry
DoCmd.OpenQuery "[arrayqry]"
End Sub
But my WHERE clause reads only last array item only. How do i specify array in where clause?
Try something like
" ... ([table].[Bnumber],2)) in ('" & Join(ListBoxContents,"','") & "');"
You are setting qry to a new statement with each iteration of your for loop. Instead you need to concatenate a string based on your list box contents that will look like ("x", "y", "z") and replace = with in.
Finish by setting your query once it will look similar to this:
qry = "SELECT col1,col2,Bnumber " & _
"FROM table WHERE (Len([table].[Bnumber]))>6) AND (Left
([table].[Bnumber],2)) in (" & commaSeperatedContents & ");"
Where commaSeperatedContents is a String that is like ("x", "y", "z") but of course has your values.
Try this one:
Dim inPart As String
For m = 0 To Size
inPart = inPart & "'" & ListBoxContents(m) & "',"
Next m
inPart = Left(inPart, Len(inPart) - 1)
qry = "SELECT col1,col2,Bnumber " & _
"FROM [table] WHERE Len([table].[Bnumber])>6 AND " & _
"Left([table].[Bnumber],2) In (" & inPart & ");"
Debug.Print qry
CurrentDb.QueryDefs("[arrayqry]").SQL = qry
DoCmd.OpenQuery "arrayqry"
The list of items in your array actually seems to be coming from the Form_Import_From_PMT.lstdigits control. Is this control bound to a data source? If so, you can simply join your table to that data source with a join clause that specifies that only rows with Bnumber values starting with the digits in the joined table are to be selected:
select col1, col2, Bnumber
from table as t
inner join tblDigits as d
on left(t.Bnumber, 2) = d.Digits
where len(t.Bnumber) > 6
If the control is not bound to a data source, then bind it now (creating a new table tblDigits to hold the digits, as shown above), and you'll be able to use the above query.
In short, data binding is how you 'use an array in a where clause' in Access.
Related
This code is written in Excel2010 VBA and queries PostGreSQL tables
I have the following code in VBA that creates a variable that I would like to use in my SQL query, but I cannot get the SQL query to accept the VBA variable using the IN clause
This code creates the variable I want to use and works fine. It allows me to select specific cells I need to query
Dim StaffID As Range
Dim ID As Range
Dim LR As Long
Dim SelectedID As String
'Count number of rows to search
LR = Worksheets("Sheet1").Range("A" & Rows.Count).End(xlUp).Row
On Error Resume Next 'if only 1 row
'Store Data from here
Set StaffID = ThisWorkbook.Sheets("Sheet1").Range("B2:B" & LR)
'Loop through each cell in Range and look for any character in column A
'then store offset cell value using comma delimiter
For Each ID In Worksheets("Sheet1").Range("A2:A" & LR).Cells
If ID.Value > 0 Then
SelectedID = SelectedID & "," & ID.Offset(, 1).Value
End If
Next ID
'Remove first delimiter from string (,)
SelectedID = Right(SelectedID, Len(SelectedID) - 1)
OUTPUT EXAMPLE of SelectedID = 6,7,8,6452
I now want to add this to my query using the IN clause, but it just doesn't work. Does anyone have a solution or workaround.
Sheets("Sheet2").Select
Range("A1").Select
Dim rs As Recordset
Dim t As String
t = "SELECT DISTINCT s.entity_id, u.login_name, s.role " _
& "FROM staff s INNER JOIN user u ON s.entity_id=u.staff_id " _
& "WHERE u.staff_id IN (SelectedID) " _
Set rs = conn.Execute(t)
With ActiveSheet.QueryTables.Add(Connection:=rs, Destination:=Range("A1"))
.Refresh
End With
rs.Close
At the moment you're putting the string 'SelectedID' directly into your query. You'll need something like this in your VBA:
t = "SELECT DISTINCT s.entity_id, u.login_name, s.role " _
& "FROM staff s INNER JOIN user u ON s.entity_id=u.staff_id " _
& "WHERE u.staff_id IN (" & SelectedID & ")"
Rows.Count should be fully qualified and With ThisWorkbook.Worksheets("Sheet1") and fully qualifying will make your code read better.
Function getSelectedIDSQL() As String
Dim ID As Range, StaffID As Range
Dim SelectedID As String
With ThisWorkbook.Worksheets("Sheet1")
For Each ID In .Range("A2" & .Range("A" & .Rows.Count).End(xlUp))
If ID.Value > 0 Then SelectedID = SelectedID & "," & ID.Offset(, 1).Value
Next
End With
If Len(SelectedID) Then getSelectedIDSQL = Right(SelectedID, Len(SelectedID) - 1)
End Function
I need help; I have created a table that stores the premium based on the following criteria:
Table_Policy_Premium
1. Category: A
2. Min Age: 0
3. Max Age: 20
4. Premium: USD1000
The same category may have other ranges of age, min 21 max 64, and premium in the next field.
I have another table namely employee_data, where there is a premium field; I want that to be updated from a TPP table based on the following criteria against each employee.
If Table_Policy_Premium - Category Matches with Category in employee_data, and If the age in employee_data is between 0-20, update the premium field in Employee_Table from Table_Policy_Premium with the appropriate premium.
Simply create public function in module that you will call in query (or on form), that will return premium value for given category and age.
Public Function getPremium(strCat As String, intAge as Integer) As Double
'variables
Dim strQuery As String
Dim rstQuery As dao.Recordset
Dim dbs As dao.Database
'set database
Set dbs = CurrentDb
'prepare query
strQuery = "SELECT Premium " & _
"FROM Table_Policy_Premium " & _
"WHERE Category = '" & strCat & "' AND " & _
"[Min Age] <= " & intAge & " AND " & _
"[Max Age] >= " & intAge & ";"
'open recordset
Set rstQuery = dbs.OpenRecordset(strQuery)
'check if there is a record
If rstQuery.EOF Then
'no record - set premium to 0
getPremium = 0
Else
'record found
getPremium = rstQuery!Premium
End If
Set rstQuery = Nothing
Set dbs = Nothing
End Function
Simply call function by inserting this as field in query: getPremium([category],[age])
I am looking for any advice on how i can read a single column in excel that contains 500 user_id's and query a database to display results in a WPF application. A user can own or rent so the SQL would look like;
SELECT * FROM users WHERE own= 'user_id' or rent= 'user_id'
This is fine for one user but i want to read each user_id and concatenate it to the SQL statement to pull out all results from the database. Any one have any easy way of doing this?
Replace the range as necessary, credit to brettdj on the join - Simple VBA array join not working
Sub test()
Dim strQuery As String
Dim strVals As String
Dim rngTarget As Range
Set rntTarget = Range("A1:A7")
Dim varArr
Dim lngRow As Long
Dim myArray()
varArr = rntTarget.Value2
ReDim myArray(1 To UBound(varArr, 1))
For lngRow = 1 To UBound(varArr, 1)
myArray(lngRow) = varArr(lngRow, 1)
Next
strVals = "('" & Join$(myArray, "','") & "') "
strQuery = "SELECT * FROM users WHERE own in " _
& strVals & "or rent in " & strVals
End Sub
VBA noob here (as of this mourning),
In MS Access I wrote a test function to find the value of a record base on some criteria you pass in.
The function seems to work fine except in cases where there is a lookup in the column that I am searching.
Basically it might return "19" and 19 corresponds to some other table value.
It seems that the RowSource of the column is what Im after so I can do a second query to find the true value.
Can someone point me in the right direction on finding the RowSource assuming I know the column name and then utilizing it to find the value Im after?
Edit: It seems that Im not explaining myself clearly, Here is a picture of what I trying to get programatically
Try this -- I think I finally understand why you are looking for the RowSource -- sorry I didn't "get" it at first. The field you're trying to pull is a foreign key into a description table.
This function should work as a general solution for all such fields (assuming the RowSource always has the primary key first, and the description second). If there is no RowSource, it will just pull the value of the field.
It's based on your original code, rather than the changes proposed by #ron, but it should set you in the right direction. You should fix it to make it parameterized, and allow for variant data types, as ron suggests (+1 ron)
As an aside, use the ampersand (&) to join strings together in VBA to avoid things like this: abc = "1" + 1, where abc is now equal to 2 instead of "11" as you would expect if both items were intended to be strings.
Public Function lookUpColumnValue(Database As Database, column As String, table As String, lookUpColumn As String, lookUpValue As String) As String
Dim sql As String
Dim recordSet As DAO.recordSet
Dim result As String
lookUpColumnValue = "" 'Return a blank string if no result
On Error Resume Next
sql = "SELECT [" & table & "].[" & column & "] FROM [" & table & "] WHERE [" & table & "].[" & lookUpColumn & "] = '" & lookUpValue & "'"
Set recordSet = Database.OpenRecordset(sql)
If Not recordSet.EOF Then
Dim td As DAO.TableDef
'this gives your number - say, 19
result = recordSet(column)
Set td = Database.TableDefs(table)
'Get the rowsource
Dim p As DAO.Property
For Each p In td.Fields(column).Properties
If p.Name = "RowSource" Then
RowSource = Replace(td.Fields(column).Properties("RowSource"), ";", "")
Exit For
End If
Next
If Not RowSource = "" Then
Dim rs2 As DAO.recordSet
Dim qd As DAO.QueryDef
Set qd = Database.CreateQueryDef("", RowSource)
Set rs2 = Database.OpenRecordset(RowSource)
If rs2.EOF Then Exit Function
PKField = rs2.Fields(0).Name
rs2.Close
qd.Close
sql = "SELECT * FROM (" & RowSource & ") WHERE [" & PKField & "]=[KeyField?]"
Set qd = Database.CreateQueryDef("", sql)
qd.Parameters("KeyField?").Value = result
Set rs2 = qd.OpenRecordset()
If Not rs2.EOF Then
'NOTE: This assumes your RowSource *always* has ID first, description 2nd. This should usually be the case.
lookUpColumnValue = rs2.Fields(1)
End If
Else
'Return the field value if there is no RowSource
lookUpColumnValue = recordSet.Fields(column)
End If
End If
End Function
If I understand your question correctly, I think using a parameter query will solve your problem. Using parameters is good practice since they will perform implicit data type casts and also prevent injection attacks.
Notice in the following function, I changed the lookupValue to a Variant type, which allows you to pass any type of value to the function.
Public Function lookUpColumnValue( _
database As DAO.database, _
column As String, _
table As String, _
lookUpColumn As String, _
lookUpValue As Variant) As String
Dim sql As String
Dim recordSet As DAO.recordSet
Dim result As String
Dim qd As QueryDef
Set qd = database.CreateQueryDef("")
sql = "SELECT [" + table + "].[" + column + "] FROM [" + table + "] " & _
"WHERE [" + table + "].[" + lookUpColumn + "] = [parm1];"
qd.sql = sql
qd.Parameters![parm1] = lookUpValue
Set recordSet = qd.OpenRecordset()
result = recordSet(column)
EDIT
lookUpColumnValue = DLookup("Space Use Description", "Space Use Codes", result)
End Function
So, we have imported data which we have queried and then created a pivot table off that query. It is essentially a list of files, each having unique ID numbers, and various attributes (file extension, type of document, hash, etc). In any case, this data is based off "hits" on keyword searches from a different program. This means that there might be multiple records for the same Unique ID since there are multiple hits.
The pivot table allows us to illustrate/manipulate via filtering out certain criteria (e.g. we don't want certain file extensions or we don't want records with FIELD X or FIELD Y0. The report is fine, but we want to make a form/query/report/whatever that will pull a "count" (based off unique ID) which ignores duplicates. For example, once all the filters are set in the pivot table, based on the filters/output of the pivot table, we want something like this:
.PDF Files: 200 | total for field x | total field y | etc
.DOCX files: 320 | total for field x | total for field y | etc
Obviously, we want to ignore duplicates of the same Unique ID in the counts.
What is the best way to do this considering we will be manipulating the pivot table dynamically and often? The ideal scenario would to have the pivot table and another object (form/report/etc) open, and as the pivot table is manipulated whatever is displaying counts changes as well.
Here are some very rough notes notes. They are only minimally tested, and using IN would be a disaster with a lot of values, however, it would be easy enough to switch this round and use an excluded list. Perhaps you can get some ideas.
Dim oPTable ''PivotTable
Dim oPM ''PivotMember
Dim oFUpd ''PivotFilterUpdate
Dim oChildren ''ChildMembers
Dim fset ''FieldSet
Dim sWhere As String
Dim sTemp As String
Dim sSQL As String
Dim sDelim As String
Dim aStates As Variant
Dim i As Integer
Dim rs As DAO.Recordset
sDelim = """"
aStates = Array("Cleared", "Checked") ''Possible states
Set oPTable = Forms(0).PivotTable.ActiveView
sWhere = vbNullString
For Each fset In oPTable.FieldSets
sTemp = vbNullString
Set oChildren = oPTable.FieldSets(fset).Member.ChildMembers
For i = 0 To oChildren.Count - 1
Set oPM = oChildren(i)
Set oFUpd = oPM.Field.FieldSet.CreateFilterUpdate
If aStates(oFUpd.StateOf(oPM) - 1) = "Checked" Then
Select Case fset.BoundField.DataType
Case adChar, adLongVarWChar
sTemp = sTemp & "," & sDelim & oPM.Caption & sDelim
Case adInteger
sTemp = sTemp & "," & oPM.Caption
Case adDate
sTemp = sTemp & ",#" & oPM.Caption & "#"
Case Else
'' The above is a very short list.
'' Stop
End Select
End If
Next
If sTemp > vbNullString Then
sWhere = sWhere _
& " AND [" & fset.Name & "] IN ( " & Mid(sTemp, 2) & ")"
End If
Next
sSQL = "SELECT DISTINCT ID FROM [" & oPTable.Control.DataMemberCaption & "] "
sSQL = sSQL & "WHERE 1=1" & sWhere
Set rs = CurrentDb.OpenRecordset(sSQL)
MsgBox "Unique: " & rs.RecordCount
if that helps:
http://lazyvba.blogspot.com/2010/11/improve-your-pivot-table-to-count.html
it will get you the unique count of ID numbers by numbers you want, and you can still manipulate the pivot