Hello
You may try the script listed below. To use it, select messages in Mail.app, run the script and it will hopefully generate an CSV file on desktop named after "scores_YYYY-MM-DD_HHMMSS.csv" with contents like the following.
"name","email","score","correct","incorrect","unanswered"
"justin baker","hidden1@email.com","100%","5","0","0"
"justin baker","hidden2@email.com","80%","4","0","1"
"jane bloggs","hidden3@email.com","80%","4","0","1"
I included email field to distinguish students with the same name.
Briefly tested with Mail v4.6 under OS X 10.6.8.
* It may or may not work with your messages, for text returned by Mail.app can be different than my test data.
Hope this may help,
H
--APPLESCRIPT
_main()
on _main()
set mm to {}
tell application "Mail"
repeat with m in (get selection)
set mm's end to m's content & linefeed
end repeat
end tell
set r to my _retrieve_data(mm)
do shell script "printf '%s' " & r's quoted form & " > ~/desktop/$(date +scores_%F_%H%M%S.csv)"
return r
end _main
on _retrieve_data(mm)
(*
list mm : list of message text
*)
script o
property pp : mm
property qq : {}
property rr : {}
property boundary : do shell script "uuidgen" without altering line endings -- UUID & LF
property batch : 50 -- number of messages to be processed at once; combined text should not exceed ca. 200K
-- divide messages into batches
repeat with i from 1 to count my pp by batch
set j to i + batch - 1
if j > (count my pp) then set j to -1
set my qq's end to my pp's items i thru j
end repeat
-- retrieve data per batch
repeat with q in my qq
set my rr's end to do shell script "perl -CSDA -w <<'EOF' - " & boundary's quoted form & "
use strict;
local $\\ = qq(\\n);
local $, = qq(,);
my $boundary = shift;
my @data = ();
my ($new, $complete, $i) = (1, 0, -1);
while (<DATA>) {
next if ! ($new ||= $_ =~ /^$boundary$/) && $complete;
if ( $new ) {
($new, $complete) = (0, 0);
++$i;
}
/^Student Name:\\s*(.+?)\\s*$/o && do { $data[$i]{name} = $1; next; };
/^Student eMail Address:\\s*(.+?)\\s*$/o && do { $data[$i]{email} = $1; next; };
/with a final grade of ([0-9.]+%)/o && do { $data[$i]{score} = $1; next; };
/^ \\s* ([0-9]+) \\s* correct \\s* \\( [0-9.]+% \\)/ox && do { $data[$i]{correct} = $1; next; };
/^ \\s* ([0-9]+) \\s* incorrect \\s* \\( [0-9.]+% \\)/ox && do { $data[$i]{incorrect} = $1; next; };
/^ \\s* ([0-9]+) \\s* unanswered \\s* \\( [0-9.]+% \\)/ox && do { $data[$i]{unanswered} = $1; next; };
$complete = (0 + keys %{$data[$i]} == 6);
}
my @keys = ('name', 'email', 'score', 'correct', 'incorrect', 'unanswered');
print map { s/\"/\"\"/og; qq(\"$_\") } @keys;
for (@data) {
print map { $_ = '' unless defined $_; s/\"/\"\"/og; qq(\"$_\") } @{$_}{@keys};
}
__END__
" & _join(q, boundary) & "
EOF" without altering line endings
end repeat
-- combine data from each batch
set r to my rr's item 1 -- include header
repeat with i from 2 to count my rr -- exclude header for rest
set r to r & my rr's item i's text from paragraph 2 to text -1
end repeat
return r
end script
tell o to run
end _retrieve_data
on _join(tt, d)
(*
list tt : source list
string d : separator
return string : tt joined with d
*)
local astid0, t
try
set {astid0, AppleScript's text item delimiters} to {AppleScript's text item delimiters, {} & d}
set t to "" & tt
set AppleScript's text item delimiters to astid0
on error errs number errn
set AppleScript's text item delimiters to astid0
error errs number errn
end try
return t
end _join
--END OF APPLESCRIPT
EDIT: modified code so that it may accept decimal percents.