diff --git a/composer.json b/composer.json index b9a9255..215f672 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,6 @@ { "require": { - "phpoffice/phpspreadsheet": "^3.5" + "phpoffice/phpspreadsheet": "^3.5", + "soundasleep/html2text": "^2.1" } } diff --git a/composer.lock b/composer.lock index c7b5644..5fd9dc3 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "94fc9216e5758e59b249edbc838bebaf", + "content-hash": "5a6414864f5fcd93d59b027740e52298", "packages": [ { "name": "maennchen/zipstream-php", @@ -504,6 +504,61 @@ "source": "https://github.com/php-fig/simple-cache/tree/3.0.0" }, "time": "2021-10-29T13:26:27+00:00" + }, + { + "name": "soundasleep/html2text", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/soundasleep/html2text.git", + "reference": "83502b6f8f1aaef8e2e238897199d64f284b4af3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/soundasleep/html2text/zipball/83502b6f8f1aaef8e2e238897199d64f284b4af3", + "reference": "83502b6f8f1aaef8e2e238897199d64f284b4af3", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "php": "^7.3|^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.9", + "phpunit/phpunit": "^7.0|^8.0|^9.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Soundasleep\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jevon Wright", + "homepage": "https://jevon.org", + "role": "Developer" + } + ], + "description": "A PHP script to convert HTML into a plain text format", + "homepage": "https://github.com/soundasleep/html2text", + "keywords": [ + "email", + "html", + "php", + "text" + ], + "support": { + "email": "support@jevon.org", + "issues": "https://github.com/soundasleep/html2text/issues", + "source": "https://github.com/soundasleep/html2text/tree/2.1.0" + }, + "time": "2023-01-06T09:28:15+00:00" } ], "packages-dev": [], diff --git a/details.php b/details.php index 696958e..dc105e8 100644 --- a/details.php +++ b/details.php @@ -11,6 +11,11 @@ require_once('vendor/autoload.php'); use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Writer\Xlsx; +use PhpOffice\PhpSpreadsheet\Style\Border; +use PhpOffice\PhpSpreadsheet\Style\Color; +use PhpOffice\PhpSpreadsheet\Style\Fill; +use PhpOffice\PhpSpreadsheet\Style\Alignment; +use Soundasleep\Html2Text; admin_externalpage_setup('report_usergrades_details', '', null, '', array('capability' => 'report/usergrades:view')); @@ -26,29 +31,46 @@ if ($data = $mform->get_data()) { $courses = enrol_get_users_courses($user->id, true); $questions = $DB->get_records('question'); - if (isset($data->exportxls)) { // Assume a form field named 'exportxls' for Excel export action + if (isset($data->exportxls)) { // // Create a new Spreadsheet object $spreadsheet = new Spreadsheet(); $sheet = $spreadsheet->getActiveSheet(); + + // Set default font and size + $spreadsheet->getDefaultStyle()->getFont()->setName('Arial')->setSize(10); + $row = 1; // Add the user details - $sheet->setCellValue('A' . $row, get_string('username', 'report_usergrades')); - $sheet->setCellValue('B' . $row, $user->username); + $headers = [ + get_string('field', 'report_usergrades'), + get_string('value', 'report_usergrades'), + ]; + + $details = [ + [get_string('username', 'report_usergrades'), $user->username], + [get_string('firstname', 'report_usergrades'), $user->firstname], + [get_string('lastname', 'report_usergrades'), $user->lastname], + [get_string('email', 'report_usergrades'), $user->email] + ]; + + // Apply header styling + $sheet->fromArray($headers, NULL, 'A' . $row); + $sheet->getStyle('A' . $row . ':B' . $row)->getFont()->setBold(true); + $sheet->getStyle('A' . $row . ':B' . $row)->getFill()->setFillType(Fill::FILL_SOLID)->getStartColor()->setARGB("ff808080"); $row++; - $sheet->setCellValue('A' . $row, get_string('firstname', 'report_usergrades')); - $sheet->setCellValue('B' . $row, $user->firstname); - $row++; - $sheet->setCellValue('A' . $row, get_string('lastname', 'report_usergrades')); - $sheet->setCellValue('B' . $row, $user->lastname); - $row++; - $sheet->setCellValue('A' . $row, get_string('email', 'report_usergrades')); - $sheet->setCellValue('B' . $row, $user->email); + + // Fill in the user details + foreach ($details as $detail) { + $sheet->fromArray($detail, NULL, 'A' . $row); + $row++; + } $row += 2; // Extra space before courses // Start iterating the courses foreach ($courses as $course) { $sheet->setCellValue('A' . $row, get_string('course', 'report_usergrades') . ': ' . $course->fullname); + $sheet->getStyle('A' . $row)->getFont()->setBold(true); $row++; $quizzes = $DB->get_records('quiz', array('course' => $course->id)); @@ -59,15 +81,22 @@ if ($data = $mform->get_data()) { if ($quiz_attempts) { $sheet->setCellValue('A' . $row, get_string('quiz', 'report_usergrades') . ': ' . $quiz->name); + $sheet->getStyle('A' . $row)->getFont()->setBold(true); $row++; foreach ($quiz_attempts as $attempt) { $sheet->setCellValue('A' . $row, get_string('attempt', 'report_usergrades') . ' ' . $attempt->attempt); + $sheet->getStyle('A' . $row)->getFont()->setItalic(true); $row++; - $sheet->setCellValue('A' . $row, get_string('question', 'report_usergrades')); - $sheet->setCellValue('B' . $row, get_string('response', 'report_usergrades')); - $sheet->setCellValue('C' . $row, get_string('grade', 'report_usergrades')); + $attempt_header = [ + get_string('question', 'report_usergrades'), + get_string('response', 'report_usergrades'), + get_string('grade', 'report_usergrades') + ]; + $sheet->fromArray($attempt_header, NULL, 'A' . $row); + $sheet->getStyle('A' . $row . ':C' . $row)->getFont()->setBold(true)->getColor()->setARGB(Color::COLOR_WHITE); + $sheet->getStyle('A' . $row . ':C' . $row)->getFill()->setFillType(Fill::FILL_SOLID)->getStartColor()->setARGB(Color::COLOR_DARKBLUE); $row++; $question_usages = $DB->get_records('question_usages', array('id' => $attempt->uniqueid)); @@ -83,9 +112,12 @@ if ($data = $mform->get_data()) { foreach ($question_grades as $question_grade) { if ($question_grade->fraction) { - $sheet->setCellValue('A' . $row, $question->name . ': ' . $question->questiontext); - $sheet->setCellValue('B' . $row, $response); - $sheet->setCellValue('C' . $row, $question_grade->fraction); + $data = [ + $question->name . ': ' . Html2Text::convert($question->questiontext), + $response, + $question_grade->fraction + ]; + $sheet->fromArray($data, NULL, 'A' . $row); $row++; } } @@ -94,6 +126,7 @@ if ($data = $mform->get_data()) { $total_grade = $DB->get_record('quiz_grades', array('quiz' => $quiz->id, 'userid' => $user->id)); $sheet->setCellValue('A' . $row, get_string('totalgrade', 'report_usergrades') . ': ' . $total_grade->grade . ' / ' . $quiz->grade); + $sheet->getStyle('A' . $row . ':C' . $row)->getFont()->setBold(true); $row += 2; // Extra space before next attempt or quiz } } @@ -102,6 +135,10 @@ if ($data = $mform->get_data()) { $row += 2; // Extra space between courses } + $sheet->getColumnDimension('A')->setWidth(50); + $sheet->getColumnDimension('B')->setWidth(50); + $sheet->getColumnDimension('C')->setWidth(10); + // Create writer and output the file $writer = new Xlsx($spreadsheet); $filename = 'user_grades_' . $user->id . '.xlsx';