This is what I use (SQL report). It doesn't include a grade but it does show activities completed vs assigned. Because Feedback doesn't show up in the gradebook, it won't be counted in completed/assigned activities. There is specical code in there to also give a link to the course listed. I don't think you can get completed without SQL. The Where clause specifies student role, where the student id is the same as the person asking for the report (this allows your student to get their list, not someone else's or everyone's) and it links student to specific role assignments and context so you get everything. You may (or may not) have to replace the prefix_ with mdl_...just depends on your installation. When I run the report on the site, I use prefix but if I run it in Adminer, I use mdl...
SELECT u.firstname AS 'First Name'
,
u.lastname AS 'Last Name'
,
concat('<a target="_new" href="%%WWWROOT%%/course/view.php?id=',c.id,'">',c.fullname,'</a>') AS 'Course'
,
IFNULL((SELECT COUNT(gg.finalgrade)
FROM prefix_grade_grades AS gg
JOIN prefix_grade_items AS gi ON gg.itemid=gi.id
WHERE gi.courseid=c.id
AND gg.userid=u.id
AND gi.itemtype='mod'
GROUP BY u.id,c.id),'0') AS 'Activities Completed'
,
IFNULL((SELECT COUNT(gi.itemname)
FROM prefix_grade_items AS gi
WHERE gi.courseid = c.id
AND gi.itemtype='mod'), '0') AS 'Activities Assigned'
,
/*show 100% complete and date if course completion record exists. show incomplete otherwise*/
(SELECT IF(cc.timecompleted<>0,
(SELECT CONCAT('100% completed ', FROM_UNIXTIME(MAX(cc.timecompleted),'%m/%d/%Y'))
FROM prefix_course_completions
WHERE prefix_course_completions.course=c.id
AND prefix_course_completions.userid=u.id), 'incomplete')) AS 'Date Completed'
FROM prefix_user u
JOIN prefix_user_enrolments ue ON ue.userid=u.id
JOIN prefix_enrol e ON e.id=ue.enrolid
JOIN prefix_course c ON c.id = e.courseid
RIGHT JOIN prefix_course_completions cc ON cc.course=c.id and cc.userid=u.id
JOIN prefix_context AS ctx ON ctx.instanceid = c.id
JOIN prefix_role_assignments AS ra ON ra.contextid = ctx.id
###JOIN prefix_role AS r ON r.id = e.roleid
RIGHT join prefix_course_info_data hrs on
c.id = hrs.courseid
WHERE ra.userid=u.id
AND ctx.instanceid=c.id
AND u.id=%%USERID%%
/*AND ue.status='0'*/ ### "0" for active, "1" for suspended. Leave commented out to include both.
AND ra.roleid='5' ### "5" = student
AND c.visible='1' ### "1" for course visible, "0" for hidden
AND c.startdate = '1372654800'
GROUP BY u.id, c.id
ORDER BY u.lastname, u.firstname, c.fullname