This is easily doable in VBA and possibly doable just using queries.
Since you're in VBA, the easy way would be to create a recordset that selects people and workshops, sorted by people. This will give you one record for each workshop attended. Then in a loop read one record at a time while tracking a single person. One way or another, and there are many ways, while tracking that person determine whether they attended all of the workshops that were selected in the multi-select listbox.
As far as doing this with just queries, the way to accomplish this would be to have one query for each workshop. The record set of the query will have a set of all of the people that attended that workshop. Then INNER join your person table to each of the workshops queries that need to be included. Group by your person identifier so you only have the person listed once. Of course this could get rather ugly depending on how many workshops you have. You could dynamically build the queries as needed to keep from having to have a query for each workshop. Or you could write the subqueries right into the SQL. e.g.
SELECT tblPeople.personID, tblPeople.PersonName
FROM (tblPeople INNER JOIN (Select personID From tblWorkshops where WorkShopID = listboxselecteditem(1)) AS WS1 ON tblPeople.personID = WS1.personID) [Continue INNER JOINing as necessary] ...
GROUP BY tblPeople.PersonID;
Watch out for balancing those parentheses!!!
Since you say you want to "list all people who attended", I assume you want to list them elsewhere on the form. The query method will allow set the Record/Row Source of whatever object you're listing those people in. But keep in mind that if you're listing those names in a list box or combo box you can set the Row Source Type to "Value List" and build the Row Source yourself in VBA.
There's probably another solution out there somewhere.
Randall J Weers
Membership Vice President
Pacific NorthWest Access Developers Group