With help from our Qlik guy Stephen, we resolved the issue.
The key is using both USERID & GROUP in the same table with the alternate field populated with asterisk.
Seems it is necessary to use the subfield() technique in 2.1, this generates a separate row for each code.
set vAllCities = 'D,S,M,H,A,P,C,B';
// Grant 'sa_scheduler' admin to enable data reload task
load ACCESS ,USERID ,GROUP ,subfield(CITYCODE, ',') as CITYCODE
[ACCESS, USERID, GROUP, CITYCODE
'ADMIN' ,'INTERNAL\sa_scheduler' ,'*' ,"$(vAllCities)"
// Load user list from secure .xls
"Access" as ACCESS,
"UserID" as USERID,
'*' as GROUP,
subfield("City Code", ',') as CITYCODE
FROM [lib://QSContent/App Access by user.xlsx]
(ooxml, embedded labels, table is Sheet1);
// default users to their home state
ACCESS, USERID, GROUP, CITYCODE
USER, *, D_employees, D
USER, *, S_employees, S
USER, *, B_employees, B
USER, *, C_employees, C
USER, *, A_employees, A
USER, *, H_employees, H
USER, *, M_employees, M
USER, *, P_employees, P
Load * InLine [
Hopefully this will be of help to other newbies.