Either queries or vba (which really shouldn't be perceptibly slower) are the way to go, for sure, especially for the kind of thing you're talking about here.
Here's a little function to send a single query
Function MailTheQuery()
Dim strMsg As String
Call DoCmd.SendObject(acSendQuery, "qryPartition", _
acFormatXLS, "jwallace@tiaa-cref.org", , , "Partition Query", _
"Here's that query.", False)
End Function
What I'd do in your case is set up a tbl that stores the states each rep has, then loop through the a recrodset of all the reps, gathering all of the states into a comma-delimited string and use that in the where query of an sql string, which you would make be the sql of some pre-saved query, which would get sent to the rep, then loop to the next rep and do it all over.
The table would just have two fields RepID and State.
It would look something like this in structure (though this is NOT code, and clearly hasn't been tested). I just finished writing. It's far from usable, most of it's just in English, but this basic structure should work for you.
Let us know if you have specific problems.
Function SendRepsTheirData
dim variables: db, strSql, rst1, rst1, strStateList, qdf
set db
strsql = select reps from tblperson
set rst1 = strsql
do until rst1.eof
strsql = select states for this rep from that new table
set rst2 = strsql
do until rst2.eof
strStateList = strstatelist & ", " & rst2!Statelist
rst2.movenext
loop
strStatelist = mid(2,strstatellist) [wrong syntax]
strsql = Select stuff to send where State In (" _
& strstatelist & "

"
set qdf = db.queries("YourQueryName"

[?syntax?]
qdf.sql = strsql
call sendobject [send the named query to the e-mail
addy of the rep in rst1.
rst1.movenext
loop
Now clean up all your object variables, like a good kid
End Function
=============
Jeremy Wallace
Designing, Developing, and Deploying Access databases since 1995.