Run a for Loop in Access Query - ms-access

I have a Query that generates a list of 2% finance or service charges on completed orders whose balance is overdue this works fine. I then have a second query that totals the finance charges per customer (this bit also works fine) what I would like to get in that second totals query is a comma (or semicolon or space or pipe or ...) separated list of orders in another field
so for the first query I have:
CustomerID OrderID ContactName FinanceChargeAmmount
218 31901 Joe Schmoe Construction 23.43
218 31927 Joe Schmoe Construction 15.78
218 31929 Joe Schmoe Construction 8.91
231 33403 Billy Bob Construction 0.43
258 33369 XYZ Corp 0.77
258 33546 XYZ Corp 1.23
and the second I have:
CustomerID ContactName SumOfFinanceChargeAmmount
218 Joe Schmoe Construction 48.12
231 Billy Bob Construction 0.43
258 XYZ Corp 2.00
I would like to add another column to the second table like:
CustomerID ContactName SumOfFinanceChargeAmmount Orders
218 Joe Schmoe Construction 48.12 31901, 31927, 31929
231 Billy Bob Construction 0.43 33403
258 XYZ Corp 2.00 33369, 33546
but can't figure out a way to loop in the query or get a list of the summed values and while I understand that I should be able to do this in VBA I'm trying to avoid doing so if possible

I know you said you want to avoid VBA, but I don't see another way to do it. So here is a proposal:
public function concatOrders(customerId as Integer) as String
On Error GoTo Oops
dim db as DAO.database, rec as DAO.recordSet
dim ans as String : ans = ""
dim first as Boolean : first = true
dim strSQL = "select orderId from [yourTable] " & _
"where customerID=" & customerId & " order by orderId";
set db = currentDb()
set rec = db.openRecordset(strSQL, dbOpenDynaset, dbReadOnly)
with rec
.moveFirst
do
if first then
first = false
else
strSQL = strSQL & ", "
end if
strSQL = strSQL & !orderId
.moveNext
loop until .EOF
.close
end with
db.close
function_exit:
concatOrders = ans
set rec = Nothing
set db = Nothing
exit function
Oops:
' Handle the errors here
goto function_exit
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;

Concatenation of multiple entries in one row

I am trying to concatenate a list of attributes for same products which are in different rows.
For example:
Column A (fruit_name) has fruit names and Column B (fruit_colors) has colors.
I want fruit color on the same row as the fruit.
|**fruit_name** | **fruit_colors** |
|----------------|------------------|
|Apple |Red |
|Apple |Yellow |
|Apple |Green |
|Apple |White |
|Banana |Red |
|Banana |Yellow |
|Banana |Green |
|Banana |White |
|Plum |White |
|Plum |Bluish |
|Plum |Purple |
The result should be:
|**name** | **colors** |
|----------------|---------------------------|
|Apple | Red, Yellow, Green, White |
|Banana | Red, Yellow, Green, White |
|Plum | White, Bluish, Purple |
This is what I have:
Set fruit_name = rstsource.Fields("fruits")
Set source_fruit = rstsource.Fields("fruits_list_type")
rstsource.MoveFirst
count = rstsource.RecordCount
counter = 0
fruit_name = source_fruit
result = source_table
Do
Do
counter = counter + 1
result = result & ", " & source_table
rstsource.MoveNext
Loop Until counter = count Or fruit_name <> source_fruit
rstdest.AddNew
rstdest.Fields("names") = fruit_name
rstdest.Fields("colors") = result
rstdest.Update
fruit_name = source_fruit
result = " "
Loop Until rstsource.EOF
This is the result - Some has comma on the front.
Banana - White, White
Apple - ,Yelow, Red
Banana- ,Red
Banana - White, White
Apple , Green
Plum - ,Green
Plum - ,Red
Banana - ,Red
At the end there is a
Run time error 3021.
I would have a read and download of Allen Browne's Concat function http://allenbrowne.com/func-concat.html - It will do exactly what you want.
This will be for report or display purposes only - you shouldn't store the data like this.
How to create this query to combine values?
I have a table with the following structure and values:
EventID PersonName
----------- ------------
1 John
1 Peter
1 Sylvia
2 John
2 Sylvia
3 Peter
3 June
I'd like to run a query and get results in the following format:
EventID PersonNames
-------- ---------------
1 John, Peter, Sylvia
2 John, Sylvia
3 Peter, June
Is there a query that will accomplish this?
Concatenate fields in same table
Author(s) Dev Ashish
(Q) I need to concatenate a field in the format "Value1; Value2; Value3" etc. for each unique value of another field in the same table. How can I do this?
(A) Using the fConcatFld function, in the Northwind database, the following query should return a concatenated list of all CustomerIDs if you group by ContactTitle.
SELECT ContactTitle, fConcatFld("Customers","ContactTitle","CustomerID","string",[ContactTitle]) AS CustomersFROM CustomersGROUP BY ContactTitle;
'************ Code Start **********
'This code was originally written by Dev Ashish
'It is not to be altered or distributed,
'except as part of an application.
'You are free to use it in any application,
'provided the copyright notice is left unchanged.
'
'Code Courtesy of
'Dev Ashish
'
Function fConcatFld(stTable As String, _
stForFld As String, _
stFldToConcat As String, _
stForFldType As String, _
vForFldVal As Variant) _
As String
'Returns mutiple field values for each unique value
'of another field in a single table
'in a semi-colon separated format.
'
'Usage Examples:
' ?fConcatFld(("Customers","ContactTitle","CustomerID", _
' "string","Owner")
'Where Customers = The parent Table
' ContactTitle = The field whose values to use for lookups
' CustomerID = Field name to concatenate
' string = DataType of ContactTitle field
' Owner = Value on which to return concatenated CustomerID
'
Dim lodb As Database, lors As Recordset
Dim lovConcat As Variant, loCriteria As String
Dim loSQL As String
Const cQ = """"
On Error GoTo Err_fConcatFld
lovConcat = Null
Set lodb = CurrentDb
loSQL = "SELECT [" & stFldToConcat & "] FROM ["
loSQL = loSQL & stTable & "] WHERE "
Select Case stForFldType
Case "String":
loSQL = loSQL & "[" & stForFld & "] =" & cQ & vForFldVal & cQ
Case "Long", "Integer", "Double": 'AutoNumber is Type Long
loSQL = loSQL & "[" & stForFld & "] = " & vForFldVal
Case Else
GoTo Err_fConcatFld
End Select
Set lors = lodb.OpenRecordset(loSQL, dbOpenSnapshot)
'Are we sure that duplicates exist in stFldToConcat
With lors
If .RecordCount <> 0 Then
'start concatenating records
Do While Not .EOF
lovConcat = lovConcat & lors(stFldToConcat) & "; "
.MoveNext
Loop
Else
GoTo Exit_fConcatFld
End If
End With
'That's it... you should have a concatenated string now
'Just Trim the trailing ;
fConcatFld = Left(lovConcat, Len(lovConcat) - 2)
Exit_fConcatFld:
Set lors = Nothing: Set lodb = Nothing
Exit Function
Err_fConcatFld:
MsgBox "Error#: " & Err.Number & vbCrLf & Err.Description
Resume Exit_fConcatFld
End Function
'************ Code End **********
Copy and paste the fConcatFld( ) function into a code module. Change the
following VBA line of code:
lovConcat = lovConcat & lors(stFldToConcat) & "; "
to:
lovConcat = lovConcat & lors(stFldToConcat) & ", "
... then save it and compile the code.
Next, create a new query and open the query in SQL View and paste the
following SQL statement into the SQL View pane:
SELECT EventID, fConcatFld("MyTable","EventID","PersonName","Long", EventID)
AS PersonNames
FROM MyTable
GROUP BY EventID;
... and replace "MyTable" with the name of your table. If the "EventID"
data type isn't Long, then you'll need to replace this in the SQL statement,
too, with whatever data type your field is using.
Save and run the query. Voila! Comma separated list.

how to convert one column data into multiple rows in ms access using ms access query

What I have in ms access table is below
Number purchase
101 product1 product2 product3
102 product1 product2
And I want to convert it into below format using ms access query(using select query only)
Number purchase
101 product1
101 product2
101 Product3
102 product1
102 product2
I am not able to the conversion column into rows ,in table i have a column in which multiple values are separated by the space and I have to convert it into row by row in ms access select query
please any one can help me
If you are willing to use code then it is quite easy
Use the following code to count the number of spaces
Public Function calculateSplits(InputRecord as String)
Dim recordWithoutSpaces as String
Dim noOfSpaces as Integer
recordWithoutSpaces = Replace(InputRecord," ","")
noOfSpaces =Len(InputRecord) -Len(recordWithoutSpaces )
calculateSplits = noOfSpaces
End Function
Then use the following code to Split the Records
Public Function ParseText(TextIn As String, x As Byte, Optional MyDelim As String) As Variant
On Error Resume Next
If Len(MyDelim) > 0 Then
ParseText = Split(TextIn, MyDelim)(x)
Else
ParseText = Split(TextIn, " ")(x)
End If
End Function
Then you just create a function that reads your table and appends records to another table splitted as you want
According to your latest code
Private Sub Command0_Click()
Dim myDelim As String
Dim strSQL As String ' want to insert the ParseText value into the new cust_info table
Dim ParseText As String
myDelim = " "
If Len(myDelim) > 0 Then
For i = 0 To 3 ' <-- n+1 CalculateSplits e.g if you have found 3 splits (spaces) then i =0 to 4
ParseText = Split("101 product1 product2 product3", myDelim)(i)
strSQL = "INSERT INTO cust_info([cust_id], [cust_prods]) VALUES ('" & i + 1 & "','" & ParseText & "');"
DoCmd.RunSQL strSQL
Next
End If
End Sub
Just pay attention to my comment about the upper threshold of i counter.

VBA to get employee costs per month

I have a table that contains information about when employees started and ended and I want to get a report on how much was spent each month over time.
Here's the table (I'm simplifying a bit here for clarity)
Example:
EmployeeID, Name, Position, StartDate, EndDate, MonthlySalary
1, John Doe, Intern, 2/1/2010, 1/1/2013, $1,000
2, Jane Doe, CEO, 1/1/2010, , $10,000
3, Bob Doe, CFO, 2/1/2010, 2/1/2013, $8,000
...
The output I would like to get is a table that looks like this:
ExpenseDate, Amount, EmployeeCount
1/1/2010, $10,000, 1
2/1/2010, $11,000, 2
3/1/2010, $11,000, 2
4/1/2010, $19,000, 3
...
1/1/2013, $18,000, 2 -- intern left
2/1/2013, $10,000, 1 -- CFO left
...
3/1/2014, $10,000, 1 -- no end date for CEO
If the information was in this format below, I could pivot it pretty easily to get what I need above:
EmployeeID, ExpenseDate, Amount
1, 2/1/2010, $1,000
1, 3/1/2010, $1,000
1, 4/1/2010, $1,000
...
2, 2/1/2010, $10,000
2, 3/1/2010, $10,000
2, 4/1/2010, $10,000
...
Could one of these tables be created using some VBA code?
I'm using Access 2010 if it matters
The following code will use your existing data to build a table of payments for each employee, for each month employed. You need to address what to do for partial months pay (divide by 30?)
Option Compare Database
Option Explicit
Function Build_Emo_Pay_Table()
Dim strSQL As String
Dim dbs As DAO.Database
Dim rsIN As DAO.Recordset
Dim rsOT As DAO.Recordset
Dim iMonths As Integer
Dim iLoop As Integer
Dim datLast As Date
Set dbs = CurrentDb
On Error Resume Next
' !! NOTE !! Decide how to 'maintain' pay table. Choices are rebuild each time,
' or add new months, or adjust previous 'partial month'
' This code deletes table 'tblEmpPay' each time and rebuilds.
Debug.Print dbs.TableDefs("tblEmpPay").Name ' To raise error
If Err.Number = 0 Then
Debug.Print Err.Number & vbTab & Err.Description
dbs.TableDefs.Delete ("tblEmpPay")
End If
On Error GoTo 0
strSQL = "CREATE TABLE tblEmpPay (PayEmpID INT, PayDate Date, PayEmpPaid long);"
dbs.Execute strSQL
strSQL = "CREATE UNIQUE INDEX PayKey ON tblEmpPay (PayEmpID, PayDate) WITH DISALLOW NULL;"
dbs.Execute strSQL
strSQL = "select * from tblEmployee Order by EmpID;"
Set rsIN = dbs.OpenRecordset(strSQL)
Set rsOT = dbs.OpenRecordset("tblEmpPay", adOpenDynamic)
' Process each employee record
Do While Not rsIN.EOF
If IsDate(rsIN!empLeave) Then
datLast = rsIN!empLeave
Else
datLast = Date
End If
iMonths = DateDiff("m", rsIN!empStart, datLast) ' Get Months employeed (note will not get partial month!)
Debug.Print rsIN!empName & vbTab & rsIN!empStart & vbTab & rsIN!empLeave & vbTab & DateDiff("m", rsIN!empStart, rsIN!empLeave)
'!! NOTE !! Depending on how you want to handle partial months, change next line. i.e. If employee leaves
' on first day of month, or during the month, what is your formula for how much do they get paid?
For iLoop = 0 To iMonths - 1
rsOT.AddNew
rsOT!PayEmpID = rsIN!empId
rsOT!PayDate = DateAdd("m", iLoop, rsIN!empStart)
rsOT!PayEmpPaid = rsIN!empsalary
rsOT.Update
Next iLoop
rsIN.MoveNext
Loop
rsIN.Close
Set rsIN = Nothing
Set dbs = Nothing
End Function

Access: Grouping in Reports

I have a report in my Access database containing multiple fields, e.g., it looks like as follows:
Name John
Number 18
Place somewhere
Name John
Number 19
Place somewhere
Name John
Number 20
Place somewhere
Name Bogo
Number 30
Place somewhere
John can have multiple Numbers. As you can see, "John" is listed multiple times, each with a different Number. I would like to get just one detail row with the name "John", something like the following:
Name John
Number 18; 19; 20
Place somewhere
Name Bogo
Number 30
Place somewhere
How can I achieve this?
The solution is to use VBA code in an Access Module to "string together" the repeated values ("Number" in your case). The general form of the code is:
Option Compare Database
Option Explicit
Public Function ListChildNames(ParentID As Long) As String
Dim cdb As DAO.Database, rst As DAO.Recordset, rtn As String
Const separator = "; "
Set cdb = CurrentDb
Set rst = cdb.OpenRecordset( _
"SELECT [ChildName] FROM [ChildTable] " & _
"WHERE ID=" & ParentID, _
dbOpenSnapshot)
rtn = ""
Do While Not rst.EOF
rtn = rtn & rst![ChildName] & separator
rst.MoveNext
Loop
rst.Close
Set rst = Nothing
Set cdb = Nothing
If Len(rtn) > 0 Then
rtn = Left(rtn, Len(rtn) - Len(separator)) '' trim trailing separator
End If
ListChildNames = rtn
End Function
(You will have to tweak the table and column names to match your table structures.)
Then, in the Record Source for your report, instead of using...
SELECT [Name], [Number] ... FROM ...
...you would use something like...
SELECT [Name], ListChildNames([Name]) AS Numbers ... FROM ...
...to retrieve the [Name] and the (concatenated list of) [Number] values in a single row.