求助:Moodle插件中无需类库实现PHP数据导出至Excel
无需第三方库实现Moodle插件数据导出Excel的方案
核心思路
利用CSV格式导出数据——Excel原生支持打开CSV文件,无需依赖任何第三方类库,完全通过PHP原生函数和Moodle内置API实现。
步骤实现
1. 添加导出按钮到页面
在渲染HTML表格的代码之前,添加导出按钮,点击后触发导出请求:
// 添加导出按钮 $exporturl = new moodle_url('/local/gradebook_sync/sync.php', ['courseid' => $courseid, 'syncid' => $syncid, 'export' => 'excel']); echo $OUTPUT->single_button($exporturl, get_string('exportexcel', 'local_gradebook_sync'), 'get');
同时在插件的语言文件lang/en/local_gradebook_sync.php中添加对应字符串:
$string['exportexcel'] = '导出为Excel';
2. 处理导出请求逻辑
在页面开头(require_once('../../config.php');之后)添加导出判断逻辑,当检测到export=excel参数时,直接生成CSV文件并输出,跳过页面渲染:
// 处理导出请求 $export = optional_param('export', '', PARAM_ALPHANUM); if ($export === 'excel') { $gradebook_sync = $DB->get_record('local_gradebook_sync', ['id' => $syncid]); $destination_course = get_course($gradebook_sync->destinationcourseid); // 获取源课程模块数据 $source_course_modules_sql = <<<SQL SELECT cm.id, m.name AS 'module', cm.instance AS 'instance', cs.section, cm.idnumber FROM {course_modules} cm JOIN {course_sections} cs ON cs.id = cm.section JOIN {modules} m ON m.id = cm.module WHERE cm.course = :course AND m.name NOT IN ('book', 'resource', 'folder', 'imscp', 'label', 'page','url') SQL; $source_course_modules_variables = ['course' => $gradebook_sync->sourcecourseid]; $source_course_modules = $DB->get_records_sql($source_course_modules_sql, $source_course_modules_variables); foreach($source_course_modules as $source_course_module) { $source_course_module->activitytitle = $DB->get_record_sql('SELECT name FROM {' . $source_course_module->module . '} WHERE id = :id', ['id' => $source_course_module->instance])->name; } // 获取目标课程模块数据 $destination_course_modules_sql = <<<SQL SELECT cm.id, cs.section, IFNULL(NULLIF(cs.name, ''), IF(cs.section = 0, 'General', CONCAT('Topic ', cs.section))) AS 'sectiontitle', m.name AS 'module', cm.instance AS 'instance', cm.idnumber FROM {course_modules} cm JOIN {course_sections} cs ON cs.id = cm.section JOIN {modules} m ON m.id = cm.module WHERE cm.course = :course AND m.name NOT IN ('book', 'resource', 'folder', 'imscp', 'label', 'page','url') SQL; $destination_course_modules_variables = ['course' => $gradebook_sync->destinationcourseid]; $destination_course_modules = $DB->get_records_sql($destination_course_modules_sql, $destination_course_modules_variables); // 组织导出数据 $export_data = []; $export_data[] = ['Section', 'Activity', 'Activity type', 'Status']; // 表头 foreach($destination_course_modules as $destination_course_module) { $destination_course_module->activitytitle = $DB->get_record_sql('SELECT name FROM {' . $destination_course_module->module . '} WHERE id = :id', ['id' => $destination_course_module->instance])->name; // 映射活动类型 switch($destination_course_module->module) { case 'assign': $activitytype = 'Assignment'; break; case 'assignment': $activitytype = 'Assignment 2.2'; break; case 'chat': $activitytype = 'Chat'; break; case 'checklist': $activitytype = 'Checklist'; break; case 'choice': $activitytype = 'Choice'; break; case 'data': $activitytype = 'Database'; break; case 'feedback': $activitytype = 'Feedback'; break; case 'forum': $activitytype = 'Forum'; break; case 'glossary': $activitytype = 'Glossary'; break; case 'h5pactivity': case 'hvp': $activitytype = 'H5P'; break; case 'lesson': $activitytype = 'Lesson'; break; case 'lti': $activitytype = 'External tool'; break; case 'questionnaire': $activitytype = 'Questionnaire'; break; case 'quiz': $activitytype = 'Quiz'; break; case 'scorm': $activitytype = 'SCORM package'; break; case 'survey': $activitytype = 'Survey'; break; case 'wiki': $activitytype = 'Wiki'; break; case 'workshop': $activitytype = 'Workshop'; break; default: $activitytype = 'Unknown'; } // 判定状态 $status = 'INVALID'; foreach($source_course_modules AS $source_course_module) { if((trim($source_course_module->activitytitle) == trim($destination_course_module->activitytitle)) && ($source_course_module->section == $destination_course_module->section) && ($source_course_module->module == $destination_course_module->module)) { $status = 'VALID'; break; } } $export_data[] = [ $destination_course_module->sectiontitle, $destination_course_module->activitytitle, $activitytype, $status ]; } // 设置HTTP响应头,触发浏览器下载 header('Content-Type: application/vnd.ms-excel'); header('Content-Disposition: attachment;filename="'.$destination_course->shortname.'_gradebook_sync.xls"'); header('Cache-Control: max-age=0'); // 生成CSV内容并输出 $output = fopen('php://output', 'w'); foreach ($export_data as $row) { // 转换编码确保中文正常显示 foreach ($row as &$cell) { $cell = mb_convert_encoding($cell, 'GB2312', 'UTF-8'); } fputcsv($output, $row, "\t"); } fclose($output); exit; // 终止脚本,避免输出页面多余内容 }
3. 优化建议
将数据获取和处理的逻辑封装成独立函数(比如get_sync_records($syncid)),在页面渲染和导出逻辑中复用,减少代码冗余,提升可维护性。
内容的提问来源于stack exchange,提问作者Kayd martin
相关产品推荐
相关产品推荐

