V2.0 - 插件 在线选题生成试卷(A4) / 通过模板文件生成word
下载插件包,放到 /plugins 目录下,支持扩展 16K 等,只要上传模板即可
安装扩展管理
https://github.com/PHPOffice/PHPWord
PHP Code复制内容到剪贴板
- composer require phpoffice/phpword:dev-master
1、根据现有的word模板,生成word,仅限文字版,不含图片
例:生成审计通知书
PHP Code复制内容到剪贴板
- <?php
- namespace plugins\GenerateWord\components;
- use backend\models\Project;
- use backend\models\ProjectInstruments;
- use common\modules\user\models\Department;
- use common\modules\user\models\User;
- use PhpOffice\PhpWord\TemplateProcessor;
- use yii\base\Model;
- class GenerateDocByProject
- {
- /**
- * @var string 试卷模板
- */
- public $template;
- private $model;
- public function __construct(Model $model, $type = 1)
- {
- $this->model = $model;
- // 不支持doc
- $this->template = dirname(__DIR__) . '/resources/project_template_' . $type . '.docx';
- }
- /**
- * 下载审计通知书
- * @return string
- * @throws \PhpOffice\PhpWord\Exception\CopyFileException
- * @throws \PhpOffice\PhpWord\Exception\CreateTemporaryFileException
- * @throws \PhpOffice\PhpWord\Exception\Exception
- */
- public function downloadNotice(){
- $company = \Yii::$app->config->get("sitename"); // 最上面第一行标题
- $code = $this->model->code; // 第三行,系统编号
- $audit = "我司审计处"; // 审计处名称,内容第一个变量
- $audited_object = " "; // 被审计对象,内容第二个变量
- $projectModel = Project::findOne(["id"=>$this->model->project_id]);
- $audit_users = $projectModel->getMembersToList();// 审计组成员
- $description = $this->model->description; // 中间内容
- $title = $projectModel->title; // 项目名称,内容第三个变量
- if($projectModel->audit_type == 1 && $projectModel->audit_users){
- // 如果是对人员审计并且有选择人员的话
- $useIds = explode(",",$projectModel->audit_users);
- $users = User::find()->where(["in","id",$useIds])->asArray()->all();
- $users = array_map(function ($user) {
- return $user["true_name"]?$user["true_name"]:$user["username"];
- }, $users);
- $audited_object = implode("、",$users);
- }else if($projectModel->audit_type == 0 && $projectModel->audit_department_id){
- // 0是部门
- $audited_object = Department::find()->select("title")->where(["id"=>$projectModel->audit_department_id])->scalar();
- }
- if(!$description){
- // 默认内容
- $startTime = date("Y年m月d日",strtotime($projectModel->start_time));
- $description = "自".$startTime."起,对".$audited_object."进行审计(".$title."),必要时将追溯到相关年度或者延伸审计(调查)。请予以配合,并提供有关资料(包括电子数据资料)和必要的工作条件。";// 通知书主体默认内容
- }
- $audit_users_text = [];
- foreach ($audit_users as $k => $v){
- $item = $v["name"] . ":";
- foreach ($v["users"] as $kk => $u){
- $item .= $u["true_name"]?$u["true_name"]:$u["username"];
- $kk == 0 ? ($item.=""):($item.=' ');
- }
- $audit_users_text[]["line"] = $item;
- }
- $templateProcessor = new TemplateProcessor($this->template);
- $templateProcessor->setValue('company', $company);
- $templateProcessor->setValue('code', $code);
- $templateProcessor->setValue('audit', $audit);
- $templateProcessor->setValue('audited_object', $audited_object);
- $templateProcessor->setValue('title', $title);
- $templateProcessor->setValue('description', $description);
- $templateProcessor->setValue('today', date("Y年m月d日"));
- $templateProcessor->cloneBlock('audit_users', 0, true, false, $audit_users_text);
- return $templateProcessor->save();
- }
- /**
- * 下载审计调查了解函
- */
- public function downloadInvestigationLetter(){
- $company = \Yii::$app->config->get("sitename"); // 最上面第一行标题
- $code = $this->model->code; // 第三行,系统编号
- $audit = "我司审计处"; // 审计处名称,内容第一个变量
- $audited_object = " "; // 被审计对象,内容第二个变量
- $projectModel = Project::findOne(["id"=>$this->model->project_id]);
- $audit_users = $projectModel->getMembersToList();// 审计组成员
- $description = $this->model->description; // 中间内容
- $title = $projectModel->title; // 项目名称,内容第三个变量
- if($projectModel->audit_type == 1 && $projectModel->audit_users){
- // 如果是对人员审计并且有选择人员的话
- $useIds = explode(",",$projectModel->audit_users);
- $users = User::find()->where(["in","id",$useIds])->asArray()->all();
- $users = array_map(function ($user) {
- return $user["true_name"]?$user["true_name"]:$user["username"];
- }, $users);
- $audited_object = implode("、",$users);
- }else if($projectModel->audit_type == 0 && $projectModel->audit_department_id){
- // 0是部门
- $audited_object = Department::find()->select("title")->where(["id"=>$projectModel->audit_department_id])->scalar();
- }
- if(!$description){
- // 默认内容
- $startTime = date("Y年m月d日",strtotime($projectModel->start_time));
- $description = "根据审计署工作安排,我办".$startTime."对".$audited_object."进行审计(".$title."),在审计实施前需要对相关情况进行调查。请予以配合,并提供有关资料(包括电子数据资料)和必要的工作条件。";// 通知书主体默认内容
- }
- $audit_users_text = [];
- foreach ($audit_users as $k => $v){
- $item = $v["name"] . ":";
- foreach ($v["users"] as $kk => $u){
- $item .= $u["true_name"]?$u["true_name"]:$u["username"];
- $kk == 0 ? ($item.=""):($item.=' ');
- }
- $audit_users_text[]["line"] = $item;
- }
- $templateProcessor = new TemplateProcessor($this->template);
- $templateProcessor->setValue('company', $company);
- $templateProcessor->setValue('code', $code);
- $templateProcessor->setValue('audit', $audit);
- $templateProcessor->setValue('audited_object', $audited_object);
- $templateProcessor->setValue('title', $title);
- $templateProcessor->setValue('description', $description);
- $templateProcessor->setValue('today', date("Y年m月d日"));
- $templateProcessor->cloneBlock('audit_users', 0, true, false, $audit_users_text);
- return $templateProcessor->save();
- }
- }
模板文件参考:
支持遍历,如果有错,检查是不是有空格影响的
2、根据图片以及文字,生成word
PHP Code复制内容到剪贴板
- <?php
- namespace plugins\education\components;
- use backend\modules\document\models\Cate;
- use backend\modules\document\models\Exercise;
- use common\models\Paper;
- use PhpOffice\PhpWord\PhpWord;
- use PhpOffice\PhpWord\Settings;
- use PhpOffice\PhpWord\TemplateProcessor;
- use yii\helpers\Json;
- class PaperDoc
- {
- /**
- * @var string 试卷模板
- */
- public $template;
- private $paper;
- private $phpWord;
- private $section;
- private $fileName;
- public function __construct(Paper $paper, $type = 1)
- {
- $this->paper = $paper;
- $this->phpWord = new PhpWord();
- $this->section = $this->phpWord->addSection();
- $this->fileName = tempnam(Settings::getTempDir(), 'PhpWord');
- }
- public function buildHeader()
- {
- // , 'name' => 'Times New Roman'
- $titleStyle = ['bold' => true, 'size' => '15', 'line-height' => '2'];
- $subTitleStyle = ['bold' => true, 'size' => '18', 'name' => '黑体'];
- $titlePStyle = ['alignment' => 'center', 'textAlignment' => 'center'];
- $this->phpWord->addTitleStyle(1, $titleStyle, $titlePStyle);
- $this->phpWord->addTitleStyle(2, $subTitleStyle, $titlePStyle);
- $this->section->addTitle($this->paper->title, 1);
- $this->section->addTitle($this->paper->title_sub, 2);
- // $this->section->addText("考试范围:xxx;考试时间:{$this->paper->test_time}分钟;命题人:xxx", [], ['alignment' => 'center']);
- $this->section->addText("注意事项:");
- $this->section->addText("1.答题前填写好自己的姓名、班级、考号等信息:");
- $this->section->addText("2.请将答案正确填写在答题卡上:");
- }
- private function buildContent()
- {
- $titleStyle = ['bold' => true, 'size' => '12', 'line-height' => '2', 'name' => '宋体 (中文标题)'];
- $titlePStyle = ['alignment' => 'center'];
- $this->section->addText("第I卷(选择题)", $titleStyle, $titlePStyle);
- $questionTitlePStyle = [];
- $this->section->addText("单选题", $titleStyle, $questionTitlePStyle);
- $exercises = $this->paper->exercise;
- $radioQuestionsKey = 0; // 选择题号
- foreach ($exercises as $key => $exercise) {
- if ($exercise->type == Exercise::TYPE_RADIO) {
- // 选择题
- $radioQuestionsKey++;
- // 题目
- $questionNameText = $this->parseSimpleText($radioQuestionsKey ."、". $exercise->question_analysis);
- // 写题目
- $this->section->addTextBreak(1); //换一行
- $this->writeComplexInline($questionNameText);
- // 选项
- if ($exercise->options) {
- $this->section->addTextBreak(1); //换一行
- $optionsSimpleText = "";
- $op = Json::decode($exercise->options);
- foreach ($op as $kk => $opt) {
- $optionsSimpleText .= $opt["num"] . ". " . $opt["text"] . " ";
- }
- $this->writeComplexInline($this->parseSimpleText($optionsSimpleText));
- }
- }
- }
- }
- private function parseSimpleText($text)
- {
- if (preg_match_all('/\[\[(.+?)\]\]/', $text, $matches) !== false) {
- $images = $matches[1];
- } else {
- $images = [];
- }
- $result = [];
- foreach (preg_split("/\[\[|\]\]/", $text) as $item) {
- if (in_array($item, $images)) {
- $result[] = [
- 'type' => 'image',
- 'content' => $item
- ];
- } else {
- $result[] = [
- 'type' => 'text',
- 'content' => $item
- ];
- }
- }
- return $result;
- }
- private function writeComplexInline($complexText)
- {
- $pStyle = ['textAlignment' => 'center'];
- $inline = $this->section->addTextRun($pStyle);
- foreach ($complexText as $item) {
- if ($item['type'] == 'text') {
- $inline->addText($item['content']);
- } else {
- $inline->addImage($item['content']/*, ['height' => '50']*/);
- }
- }
- }
- public function build()
- {
- $this->buildHeader();
- $this->buildContent();
- }
- public function save($fileName)
- {
- $this->build();
- $this->phpWord->save($fileName);
- }
- public function download()
- {
- $tmpFile = tempnam(Settings::getTempDir(), 'PhpWord');
- $this->save($tmpFile);
- return $tmpFile;
- }
- }
在上传题目的时候,需要对题目处理一下,如果是公式编辑器上传的base64图片,改为:
PHP Code复制内容到剪贴板
- public function beforeSave($insert)
- {
- parent::beforeSave($insert);
- // if($insert) {
- // //执行添加的情况
- // } else {
- // //执行更新的情况
- // }
- // 筛出所有图片
- $question = $this->processingEditorContent($this->question);
- // 筛出所有图片
- $answer = $this->processingEditorContent($this->answer);
- $this->question_analysis = $question; // 答案解析
- $this->answer_analysis = $answer; // 答案解析
- // $this->save();
- return true;
- }
- /**
- * 转换编辑器内容
- * @param $content
- * @return string|string[]|null
- */
- public static function ProcessingEditorContent($content){
- $text = preg_replace_callback('/<img.*?src="(.*?)".*?\/>/', function ($matches) {
- $image = $matches[1];
- if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $image, $result)) {
- $path = date("Ymd")."/";
- $url = Attachment::uploadFromBase64($path,$image);
- return '[[' . $url . ']]';
- }else{
- return '[[' . $image . ']]';
- }
- }, $content);
- $text = strip_tags($text);
- $text = str_replace(" ","",$text);
- return $text;
- }
- /**
- * 上传base64图片
- * @param $base64Img
- * @return mixed
- */
- private function uploadBase64Image($base64Img)
- {
- $path = date("Ymd")."/";
- $url= Attachment::uploadFromBase64($path,$base64Img);
- return $url;
- }
上一篇 V2.0 - API