MS Access query to separate commas - html

my project contains a MS Acces 2003 database, The table in the database contains a column called students name. The single column contains n numbers of names of student. For eg. John, Jim, Johny, Tom etc. They are dynamically added. Now what I want is, I want a complete list of all the names in the column.
Like for eg. if the column is
Student_name
John, Jim, Johny, Tom, Jack
I want output as:
Student_name
John
Jim
Johny
Tom
Jack
The query must support MS Access. as i'm fetching the data in html file and I've attached that html file to MS Aacess database

Sorry, but MS Access doesn't provide functionality to run query in recursive mode as CTE does. It's possible to use VBA macro to proceed through the collection of students to split comma separated values into set of records ;)
Let say, you have got table Student with fields:
ID (numeric - integer),
Students (string - char)
Sample data:
Id Students
1 John, Jim, Johny, Tom, Jack
2 Paula, Robert, Tim, Dorothy
5 Frank, Ramona, Giorgio, Teresa, Barbara
19 Isabell, Eve, Ewelina, Tadit
You need to create another table to store results of macro.
CREATE TABLE CTE1
(
ID INT,
OrigValue CHAR(255),
SingleValue CHAR(255),
Remainder CHAR(255)
);
To add macro, please do the following steps:
go to Visual Basic code Pane
insert new module
copy below code and paste it into previously added module
move the mouse cursor into **ModifyMyData** procedure by clicking whenever inside its body
run code (F5)
Option Compare Database
Option Explicit
'need reference to Microsoft ActiveX Data Object 2.8 Library
Sub ModifyMyData()
Dim sSQL As String
Dim rst As ADODB.Recordset
Dim vArray As Variant
Dim i As Integer
'clear CTE table
sSQL = "DELETE * FROM CTE;"
CurrentDb.Execute sSQL
'initial query
sSQL = "INSERT INTO CTE (ID, OrigValue, SingleValue, Remainder)" & vbCr & _
"SELECT ID, Students AS OrigValue, TRIM(LEFT(Students, InStr(1,Students,',')-1)) AS SingleValue, " & _
"TRIM(RIGHT(Students,LEN(Students)-InStr(1,Students,','))) AS Remainder" & vbCr & _
"FROM Student;"
CurrentDb.Execute sSQL
sSQL = "SELECT ID, OrigValue, SingleValue, Remainder" & vbCr & _
"FROM CTE"
Set rst = New ADODB.Recordset
rst.Open sSQL, CurrentProject.Connection, adOpenStatic
With rst
'fill rst object
.MoveLast
.MoveFirst
'proccess through the
Do While Not rst.EOF
'Split Remainder into array
vArray = Split(.Fields("Remainder"), ",")
'add every single value
For i = LBound(vArray) To UBound(vArray)
sSQL = "INSERT INTO CTE (ID, OrigValue, SingleValue, Remainder)" & vbCr & _
"VALUES(" & .Fields("ID") & ", '" & .Fields("OrigValue") & "','" & vArray(i) & "','" & GetRemainder(vArray, i + 1) & "');"
CurrentDb.Execute sSQL
Next
.MoveNext
Loop
.Close
End With
Set rst = Nothing
MsgBox "Ready!"
DoCmd.OpenTable "CTE"
End Sub
Function GetRemainder(vList As Variant, startpos As Integer) As String
Dim i As Integer, sTmp As String
For i = startpos To UBound(vList)
sTmp = sTmp & vList(i) & ","
Next
If Len(sTmp) > 0 Then sTmp = Left(sTmp, Len(sTmp) - 1)
GetRemainder = sTmp
End Function

Related

Table showing "Wrong" Record, but Query returns "Correct" data?

Alright, so here's what happened :
I had a wide table, that needed to be a long table. I used the code below (CODE 1) to fix that problem:
It seemed to have worked, though I am now finding minor errors in the data, while I will need to resolve those, that isn't what this question is about.
In the end, my table looks correctly, and here is an actual record from the database, in fact it is the record that called my attention to the issues:
tbl_CompletedTrainings:
ID
Employee
Training
CompletedDate
306
Victoria
Clozaril
5/18/2016
306
20
8
5/18/2016
the second row is to show what the database is actually seeing (FK with both Employee and Training tables) Those tables have the following formats:
tbl_employeeInformation:
ID
LastName
FirstName
Address
Line2
City
State
Zip
Site1
Site2
Site3
20
A.
Victoria
6 Street
City
State
00000
3NNNN
4
Eric
A.
15 Street
City
State
00000
3nnnnn
tbl_Trainings:
AutoID
TrainingName
Expiration
6
Bloodborne
Annual
8
Clozaril
Annual
When the query in (CODE 2) is run on this table, the following record is returned
report Query:
LastName
FirstName
Training
CompletedDate
Site1
Site2
Site3
ID
Accccc
Eric
Bloodborne Pathogens
5/18/2016
3NN-NN
N/A
N/A
306
Notice that the ID in the report Query is only there as I was checking records, and is called from the tbl_CompletedTrainings. So here's the question, What is happening?! If the record was just wrong, and not pulled I could understand it, but that's not what's happening. Worse still is the date is the correct date for the training the query returns, but not for the training listed in the table.
Related issue, possibly, I had noticed that when I queried the table with a call on the foreign key, it returns records that are 2 off of the requested training number. Notice that this is the case here as well. The training listed, Clozaril, is exactly two further down the line than the training Bloodborne Pathogens, Key 8 and 6 respectively.
Any help would be very much appreciated in this matter, as I can't seem to catch what is causing the issue. Yet it must be something.
(CODE 1)
Option Compare Database
Option Explicit
Sub unXtab()
On Error GoTo ErrHandler
Dim db As DAO.Database
Dim rsxtab As DAO.Recordset
Dim rsutab As DAO.Recordset
Dim counter As Integer
Dim loopint As Integer
Dim qryGetNameID As DAO.Recordset
Dim qryGetTrainingNameID As DAO.Recordset
Dim expires As Date
Dim namevar As String
Dim lname As String
Dim fname As String
Set db = CurrentDb
Set rsxtab = db.OpenRecordset("SELECT * FROM [Employee Training Log];")
If Not (rsxtab.BOF And rsxtab.EOF) Then
db.Execute "DELETE * FROM tbl_CompletedTrainings;"
Set rsutab = db.OpenRecordset("SELECT * FROM tbl_CompletedTrainings WHERE 1 = 2;")
counter = rsxtab.Fields.Count - 1
Do
For loopint = 2 To counter
namevar = rsxtab.Fields(loopint).Name
lname = rsxtab("[Last Name]")
fname = rsxtab("[First Name]")
Select Case namevar
Case "First Name"
Case "Last Name"
Case "Date of Hire"
Case Else
If rsxtab.Fields(loopint) <> "" Or Not IsNull(rsxtab.Fields(loopint)) Then
Set qryGetTrainingNameID = db.OpenRecordset("SELECT AutoID FROM Trainings WHERE [Training Name] = " & Chr(34) & namevar & Chr(34) & ";")
Set qryGetNameID = db.OpenRecordset("SELECT ID FROM tbl_EmployeeInformation WHERE LastName = " & Chr(34) & lname & Chr(34) & _
" AND " & Chr(34) & fname & Chr(34) & ";")
rsutab.AddNew
Debug.Print lname
Debug.Print fname
Debug.Print namevar
Debug.Print qryGetNameID.Fields(0)
Debug.Print qryGetTrainingNameID.Fields(0)
rsutab.AddNew
rsutab("Employee") = qryGetNameID.Fields(0)
rsutab("Training") = qryGetTrainingNameID.Fields(0)
rsutab("CompletedDate") = rsxtab.Fields(loopint)
rsutab.Update
End If
End Select
Next loopint
rsxtab.MoveNext
Loop Until rsxtab.EOF
End If
exitSub:
On Error Resume Next
rsxtab.Close
rsutab.Close
Set rsxtab = Nothing
Set rsutab = Nothing
Set db = Nothing
Exit Sub
ErrHandler:
MsgBox Err.Number & " : " & Err.Description & vbCrLf & vbCrLf & " on this field: " & namevar, vbOKOnly + vbCritical
End Sub
(CODE 2)
SELECT EI.LastName, EI.FirstName, T.TrainingName AS Training, CT.CompletedDate, EI.Site1, EI.Site2, EI.Site3, CT.ID
FROM tbl_EmployeeInformation AS EI
INNER JOIN (tbl_CompletedTrainings AS CT
INNER JOIN tbl_Trainings AS T ON CT.Training = T.AutoID) ON EI.ID = CT.Employee;

SELECT Queries in Access VBA

I have an Access database consisting of two tables, Individuals & Pairs. Individuals consists two columns; 'Bird_ID' and 'Parents_Pair_number' and Pairs consists of three columns; 'Pair', 'Female_ID' and 'Male_ID'. 'Parents_Pair_number' and 'Pair' have a Many-to-one relationship. Via this relation one can check the parents of an individual.
But now I was thinking of making automatized family trees using a form. My plan was to make a field (Bird_ID_Field) in which you can find a certain individual and that other fields such as Father, Mother, Fathers father etc. etc. would auto-fill based on that entry.
I tried to auto-fill the Father_ID (Field) using the following VBA code:
Dim strSQL As String
Dim strBird_ID As String
If Bird_ID_Field <> "" Then
strBird_ID = Bird_ID_Field
strSQL = "SELECT Pairs.[Male_ID] " & _
"FROM Pairs " & _
"WHERE PAIR = (SELECT Individuals.[Parents_Pair_number] FROM Individuals WHERE Individuals.[Bird_ID]= '" & strBird_ID & "');"
DoCmd.OpenQuery strSQL
Father_ID = strSQL
End If
But after updating the Bird_ID_Field I get the following error: Microsoft Access can't find the object ''.
Do you have any idea what's wrong?
Thanks in forward!
Jeroen
You should use recordsets:
Dim rst As Recordset
Dim strSQL As String
If Nz(Bird_ID_Field,"") <> "" Then
strBird_ID = Nz(Bird_ID_Field, "")
strSQL = "SELECT Pairs.[Male_ID] " & _
"FROM Pairs " & _
"WHERE PAIR = (SELECT Individuals.[Parents_Pair_number] FROM Individuals WHERE Individuals.[Bird_ID]= '" & strBird_ID & "');"
Set rst = CurrentDb.OpenRecordset(strSQL)
If rst.RecordCount > 0 Then
Father_ID = rst![Male_ID]
End If
End If
rst.Close
Set rst = Nothing
And also I would recommend to use JOIN for tables joining instead of subquery.

Display multiple specific records in a report

Let's say I have a single table called "Customers". It contains 2 fields:
Name
Address
I want users to be able to select multiple records by selecting their names. For example something like having a list box containing all the names of the records in the database. I want users to be able to select multiple items like:
Dave Richardson
Bob Smith
Sophie Parker
And then only display records with these names in the report.
You can use the WhereCondition option of the DoCmd.OpenReport Method to filter your report as needed.
Const cstrReport As String = "YourReportNameHere"
Dim custNames As String
Dim lItem As Variant
Dim strWhereCondition As String
With Me.yourListBoxName
For Each lItem In .ItemsSelected
custNames = custNames & ",'" & Replace(.ItemData(lItem), "'", "''") & "'"
Next
End With
If Len(custNames) > 0 Then
custNames = Mid(custNames, 2)
strWhereCondition = "[Name] IN (" & custNames & ")"
End If
DoCmd.OpenReport ReportName:=cstrReport, View:=acViewPreview, _
WhereCondition:=strWhereCondition
Note this approach has features in common with PaulFrancis' answer. In fact, I copied his code and modified it. The key difference is that this approach does not require you to revise a saved query in order to filter the report.
The setup I would I have is, a Form with a SubForm and a ListBox, the Listbox will have the names of all your customers. So the RowSource would be,
SELECT
customerNameFieldName
FROM
yourTableName;
The Multi Select property will be setup to Extended. Then a button will have the following code that will generate the SQL for the SubForm's recordsource.
Private Sub buttonName_Click()
Dim lItem As Varaint, strSQL As String
Dim custNames As String, whereStr As String
Dim dbObj As dao.Database
Dim tmpQryDef As QueryDef
Set dbObj = CurrentDb()
For Each lItem In Me.yourListBoxName.ItemsSelected
custNames = custNames & "'" & Me.yourListBoxName.ItemData(lItem) & "', "
Next
Id Len(custNames) <> 0 Then
custNames = Left(custNames, Len(custNames) - 2)
whereStr = "WHERE customerNameFieldName IN (" & custNames & ")"
End If
strSQL = "SELECT someFields FROM someTable " & whereStr
Set tmpQryDef = dbObj.QueryDefs("Summary 3 Q1")
tmpQryDef.SQL = strSQL
DoCmd.OpenReport "yourReportName", acViewNormal
Set dbObj = Nothing
Set tmpQryDef = Nothing
End Sub
So now the SubForm will have the RecordSource based on all the information you have selected in the ListBox.

Access 2010 - Check data in recordset before adding new record

I'm new to Access so bear with me here.
I have a form that allows me to add new data to a table
ID | Name | City | Zip Code
1 | John | Newark | 12340
2 | Alex | Boston | 98760
So on and so forth...
Before proceeding to add a new record with the above data fields, I need to create a check that will look at the table to determine if the combinations of Name, City and Zip Code already exist. If they do, I want it to Exit Sub; Else continue with the rest of the macro.
I've been looking to build this using some form of the OpenRecordset command, but I'm not sure where to begin. Can someone point me in the right direction? Thanks!
I just wrote this code to recreate your situation and it worked fine. You just need to rename your columns and your table in the query.
Dim strSQL As String
Dim qdf As QueryDef
'if these columns are not text change to approriate type
strSQL = "PARAMETERS [NameToCheck] Text(255),[CityToCheck] Text(255),[Zip] Text(255); "
'change table name and column names here
strSQL = strSQL & "SELECT Count(*) FROM address " _
& "WHERE FName = [NameToCheck] AND City = [CityToCheck] AND ZipCode = [Zip];"
Set qdf = CurrentDb.CreateQueryDef("", strSQL)
qdf("NameToCheck") = txtName.Value 'change to that textfield on form
qdf("CityToCheck") = txtCity.Value 'change to that textfield on form
qdf("Zip") = txtZipCode.Value 'change to that textfield on form
If qdf.OpenRecordset(dbOpenSnapshot)(0) > 0 Then
MsgBox "This record is already in the database"
Else
'Insert statement goes here.
End If
If you want to use recordsets as you requested then you would need to use a SQL statement to select all or use it to find something by name.
Dim myR as Recordset
Dim strSQL as String
'run a SQL statement to select a record with the same info
strSQL = "SELECT [Name], [City], [Zip Code] FROM table_name_here " & _
"WHERE [Name] = '" & form_control_name & "' " & _
"AND [City] = '" & form_control_city & "' " & _
"AND [Zip Code] = '" & form_control_zip & "'"
'set your recordset to the SQL statment
Set myR = CurrentDb.OpenRecordset(strSQL, dbOpenDynaset)
'if your count is greater than 0, then you'll have a duplicate
If myR.RecordCount > 0 then
MsgBox "This already exists"
Else
MsgBox "All clear"
End if
Set myR = Nothing

Simple access query

I'm trying to create a query in Access.
Let's say, for example, I have four fields: Numbers 1-26, Letters A-Z, 26 Names, and 26 Cities, so one record might be: 2, B, Jane, New York
I want to create and save a new query with:
the numbers field, the letters field, and the names field. I want the letters field to be filtered on "A" or "B", and the names field to have an expression so it's always 0.
This will become a loop, so it'll create 13 queries (A/B, C/D, etc).
It seems like having this process in VBA as opposed to the Access macro builder would be better since not only do I have to loop this process, but there are also 2 similar tables (same field names, different values) that I need to run it on.
You can run your queries in VBA using a recordset and then work with the data from there:
Sub YourQueries(ByVal pstrCol1 As String, ByVal pstrCol2 As String, ByVal pstrCol3 As String, ByVal pstrCol4 As String)
Dim rs As Recordset
Dim strSQL As String
' Change types above to match what's actually in the table
strSQL = "SELECT YourColumn1, YourColumn2, YourColumn3, YourColumn4 "
strSQL = strSQL & " WHERE "
strSQL = strSQL & "YourColumn1='" & pstrCol1 & "'"
strSQL = strSQL & " AND YourColumn1='" & pstrCol1 & "'"
strSQL = strSQL & " AND YourColumn1='" & pstrCol1 & "'"
strSQL = strSQL & " AND YourColumn1='" & pstrCol1 & "'"
Set rs = CurrentDb.OpenRecordset(strSQL, dbOpenSnapshot)
While Not rs.EOF
For i = 0 To 3
Debug.Print rs.Fields(i) & " is Column" & Format(i)
Next i
rs.MoveNext
Wend
rs.Close
Set rs = Nothing
End Sub