Free Lessons
Courses
Seminars
TechHelp
Fast Tips
Templates
Topic Index
Forum
ABCD
 
Home   Courses   TechHelp   Help   Contact   Merch   Join   Order   Logon   Forums   
 
Back to Access Forum    Comments List
Upload Images | @Reply | Bookmark | Link | Email | Next Unseen |
Concatenate items from 1many
Tim Gilbert 
    
4 years ago
Is there practical way to concatenate multiple items from a one to many relationship?

More specifically, I am transitioning an Excel workbook for logging continuing education sessions to MS Access.  Each session might have one or more presenters so I created a table for the presenters with a foreign key to the session table.  Also, since these are technical presenters (engineering), many, but not all, of the presenters have one or more professional credentials as part of their name (e.g. "Jane Q. Doe, PE, SE, PMP").

I am able to parse the Excel data into separate fields for first name, middle initial, last name, and suffix.  I am also able to parse the suffix into individual parts (e.g. "PE", "SE", and "PMP") as individual items.  Because many of the suffix credentials are repeated among the presenters (e.g. there are many with "PE"), it seems like this might be an opportunity to further normalize the data by making a suffix table and using a one to many relationship for the relevant presenters to the suffix table.  

If I do this, how can I recombine the name and full suffix for forms and reports to display as one line of text (I know I can use a continuous subform below the name to show each suffix, but just looks wrong to me).

It there a practical way to recombine the items from a one to many relationship or should I just forget about parsing out the suffixes?
Alex Hedley  @Reply  
           
4 years ago
If it's in SQL Server: STRING_AGG

SELECT
    Id, STRING_AGG(FirstName, ',') UsersName
FROM UserT
Tim Gilbert OP  @Reply  
    
4 years ago
Thanks Alex - It's not SQL Server, only a usual accdb file.
Alex Hedley  @Reply  
           
4 years ago
Have you done much with VBA and Recordsets (Using Recordsets) yet?
Maggie M  @Reply  
     
4 years ago
Watch the TechHelp Helper Data video & the extended cut.
Tim Gilbert OP  @Reply  
    
4 years ago
@Alex - I'm OK with some VBA (I've written custom VBA functions for both Access and Exel...the debugging process is a learning experience). "Recordsets" is a term I've heard, but I have a limited understanding - my basic impression is that a recordset is a thing in VBA (not sure if "object" is the correct term) that is similar to an array. I have the impression that among other things, a table or query can be a recordset.  
Plus, if the  over my head, I'm willing to learn as long as its within reach.
Alex Hedley  @Reply  
           
4 years ago
See if you can have a go creating a simple table, and use a recordset to loop through each item and append it to a string.
Kevin Yip  @Reply  
     
4 years ago
I second Alex's suggestion: loop through the suffix recordset to get all the suffices.  Sample code is below.  This function returns a comma-delimited string containing all the suffices:

Function GetAllSuffices() As String
    ' Declare variable for the recordset.
    Dim r As Recordset
    
    ' Declare string variable and assign it an empty string.
    Dim s As String
    s = ""
        
    ' Assign data source to the recordset variable.
    Set r = CurrentDb.OpenRecordset("SELECT Suffix FROM SuffixT WHERE NameID = " & [NameID])

    ' Move to the first record.
    r.MoveFirst
    
    ' If the last record has not been reached, run the do loop below.
    Do While Not r.EOF
    
        ' If the suffix is not blank
        If Len(Trim(r!Suffix & "")) > 0 Then
        
            ' If s is not empty, add a comma.
            If Len(s) > 0 Then s = s & ", "
            
            ' Concatenate suffix to the string s.
            s = s & r!Suffix
            
        End If
        
        ' Move to the next record.
        r.MoveNext
    Loop
    
    ' Return the resulting string.
    GetAllSuffices = s
    
End Function
Kevin Yip  @Reply  
     
4 years ago
There is actually a way to get all rows of data with one line of code:

Dim arr As Variant
arr = r.GetRows(r.RecordCount)

This will put all the data of the recordset into a multi-dimensional array (arr).  The problem is that multi-dimensional arrays are kind of unwieldy.  And it would yield, in this case, more complicated code than looping through the recordset.  But keep this method in your back pocket in case you need it.
Tim Gilbert OP  @Reply  
    
4 years ago
Thank you Alex and Kevin!  
Kevin - I truly appreciate the comment lines in your code sample!
Tim Gilbert OP  @Reply  
    
4 years ago
Thanks again for all the help.  

I made a few updates to get it to work in my circumstances.  Since each presenter might have zero, one or more suffixes, I have a junction table to create the many-to-many relationship between the presenter and the suffix.  Because of that I revised Kevin's function so that the recordset is a query based on a SQL string (I just made the query & copied the SQL text from the SQL view).  I also added a check to bypass the Do-Loop if the recordset is empty.

The current version is below. It seem to work.  Please let me know if you see any opportunity to improve it.

Function ConcatenateSuffixes(NameID As Long) As String
    
    ' Declare variable for the recordset.
    Dim rs As Recordset
    
    'Declare string variable to hold SQL statement for Query
    Dim strSQL As String
    strSQL = "SELECT TPresenter.PresenterID, TSuffix.Suffix " _
            & "FROM (TPresenter INNER JOIN JTPresenterSuffix ON TPresenter.PresenterID = JTPresenterSuffix.PresenterID) " _
            & "INNER JOIN TSuffix ON JTPresenterSuffix.SuffixID = TSuffix.SuffixID " _
            & "WHERE (((TPresenter.PresenterID)=" & NameID & "));"
            
            'Debug.Print strSQL

    ' Declare string variable to hold the concatenated suffixes and assign it an empty string.
    Dim s As String
    s = ""
    
    ' Assign data source to the recordset variable based on the SQL string
    Set rs = CurrentDb.OpenRecordset(strSQL)

    'Check that recordset is not empty and skip Do Loop if it is empty
    If rs.BOF And rs.EOF Then GoTo LastStep
    
    ' Move to the first record.
    rs.MoveFirst
    
    ' If the last record has not been reached, run the do loop below.
    Do While Not rs.EOF
    
        ' If the suffix is not blank
        If Len(Trim(rs!Suffix & "")) > 0 Then
        
            ' If s is not empty, add a comma.
            If Len(s) > 0 Then s = s & ", "
            
            ' Concatenate suffix to the string s.
            s = s & rs!Suffix
            
        End If
        
        ' Move to the next record.
        rs.MoveNext
    Loop

LastStep:
    
    ' Return the resulting string.
    ConcatenateSuffixes = s
      
End Function
Tim Gilbert OP  @Reply  
    
4 years ago
One follow-up question: Before ending the function, should I set the recordset to nothing?
Scott Axton  @Reply  
      
4 years ago
Yes it is always a good idea to close your recordset.  Access is pretty good about handling memory but not always.
Common practice is to issue Set rs = Nothing just prior to your End Function statement.

That will help to prevent memory leaks.
Kevin Yip  @Reply  
     
4 years ago
Recordsets are automatically closed if they go "out of scope" or when execution ends.  I rarely explicitly close recordsets in VBA because Access now does a better job cleaning up the memory than past versions of Access.  But I do close recordsets in error handling.  Suppose an error occurs while the code is looping through a recordset; the error is trapped and sent to an error handler.  It would be good practice for the error handler to close the recordset so things wouldn't be left hanging.  If your recordset uses some kind of record-locking, then you definitely need to close it when it errors out, so it won't affect the ensuing code execution (if any).  

Another thing to watch out for is that r.Close would cause a run-time error if r isn't really an opened recordset.  So the error handler needs to check whether r is an object before attempting to close it.  In the code below, r would be nothing if an error occurs at OpenRecordset():

    Dim r As Recordset
    On Error GoTo 10
    Set r = CurrentDb.OpenRecordset("Table1", , dbDenyRead)
    r.MoveFirst
    Do While Not r.EOF
        MsgBox r!field1
        r.MoveNext
    Loop
    Exit Sub
    
10:
    Msgbox "An error has occurred."
    If Not (r Is Nothing) Then
        r.Close
        Set r = Nothing
    End If
    GoTo Somewhere

This thread is now CLOSED. If you wish to comment, start a NEW discussion in Access Forum.
 

Next Unseen

 
 
What's This?

 

The following is a paid advertisement
Computer Learning Zone is not responsible for any content shown or offers made by these ads.
 

Learn
 
Access - index
Excel - index
Word - index
Windows - index
PowerPoint - index
Photoshop - index
Visual Basic - index
ASP - index
Seminars
More...
Customers
 
Login
My Account
My Courses
Lost Password
Memberships
Student Databases
Change Email
Info
 
Latest News
New Releases
User Forums
Topic Glossary
Tips & Tricks
Search The Site
Code Vault
Collapse Menus
Help
 
Customer Support
Web Site Tour
FAQs
TechHelp
Consulting Services
About
 
Background
Testimonials
Jobs
Affiliate Program
Richard Rost
Free Lessons
Mailing List
PCResale.NET
Order
 
Video Tutorials
Handbooks
Memberships
Learning Connection
Idiot's Guide to Excel
Volume Discounts
Payment Info
Shipping
Terms of Sale
Contact
 
Contact Info
Support Policy
Mailing Address
Phone Number
Fax Number
Course Survey
Email Richard
[email protected]
Blog RSS Feed    YouTube Channel

LinkedIn
Copyright 2026 by Computer Learning Zone, Amicron, and Richard Rost. All Rights Reserved. Current Time: 11/8/2026 10:23:49 PM. PLT: 1s