|
|
|
|
@ -34,17 +34,27 @@ class SurveyExport
|
|
|
|
|
$detail = $book->createSheet()->setTitle('问题详细表');
|
|
|
|
|
$attachments = $book->createSheet()->setTitle('附件清单');
|
|
|
|
|
self::row($summary, 1, ['答卷ID', '问卷名称', '答题人姓名', '学号', '公司', '职务', '首次提交时间', '最近提交时间']);
|
|
|
|
|
self::row($detail, 1, ['答卷ID', '答题人姓名', '章节', '题号', '题目', '子题/维度', '题型', '题目说明', '所有选项', '答案', '补充说明', '状态']);
|
|
|
|
|
self::row($detail, 1, ['答卷ID', '答题人姓名', '章节', '题号', '题目', '子题/维度', '答案', '补充说明', '题型', '题目说明', '所有选项']);
|
|
|
|
|
self::row($attachments, 1, ['答卷ID', '答题人姓名', '题目', '原文件名', '压缩包内路径', '状态']);
|
|
|
|
|
$sr = $dr = $ar = 2;
|
|
|
|
|
$hasSections = $hasDimensions = false;
|
|
|
|
|
$replyRanges = $sectionRanges = $questionRanges = $plainRows = [];
|
|
|
|
|
$current = $survey->courseContentEvaluationAsks()->orderBy('sort')->orderBy('id')->get()->toArray();
|
|
|
|
|
foreach ($survey->courseContentEvaluationForms()->with('user')->lazyById(100) as $reply) {
|
|
|
|
|
$name = $reply->user->name ?? '未填写姓名';
|
|
|
|
|
self::row($summary, $sr++, [$reply->id, $reply->snapshot['title'] ?? $survey->title, $name, $reply->user->no ?? '', $reply->user->company_name ?? '', $reply->user->company_position ?? '', $reply->created_at, $reply->updated_at]);
|
|
|
|
|
$replyStart = $sectionStart = $dr;
|
|
|
|
|
$section = '';
|
|
|
|
|
$number = 0;
|
|
|
|
|
foreach (SurveySchema::replyQuestions($current, $reply->data, $reply->snapshot) as $q) {
|
|
|
|
|
if ($q['edit_input'] === 'section') { $section = $q['name']; continue; }
|
|
|
|
|
if ($q['edit_input'] === 'section') {
|
|
|
|
|
if ($section !== '' && $dr > $sectionStart) $sectionRanges[] = [$sectionStart, $dr - 1];
|
|
|
|
|
$sectionStart = $dr;
|
|
|
|
|
$section = $q['name'];
|
|
|
|
|
$hasSections = true;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
$questionStart = $dr;
|
|
|
|
|
$hidden = !empty($q['hidden']);
|
|
|
|
|
$position = $hidden ? '' : ++$number;
|
|
|
|
|
$extra = $hidden ? '' : ($q['other_text'] ?? '');
|
|
|
|
|
@ -55,8 +65,12 @@ class SurveyExport
|
|
|
|
|
$fields = $q['edit_input'] === 'multi_dimension' ? ($q['dimensions'] ?? []) : [$q];
|
|
|
|
|
foreach ($fields as $field) {
|
|
|
|
|
$options = array_map(fn ($o) => $o['value'].(isset($o['score']) ? '('.$o['score'].'分)' : ''), $field['select_item'] ?? []);
|
|
|
|
|
self::row($detail, $dr++, [$reply->id, $name, $section, $position, $q['name'], $q['edit_input'] === 'multi_dimension' ? $field['name'] : '', self::TYPES[$field['edit_input']] ?? $field['edit_input'], $field['help'] ?? $q['help'] ?? '', implode("\n", $options), $hidden ? '' : ($field['display_value'] ?? ''), $extra, $hidden ? '条件未满足,未显示' : '已显示']);
|
|
|
|
|
self::row($detail, $dr++, [$reply->id, $name, $section, $position, $q['name'], $q['edit_input'] === 'multi_dimension' ? $field['name'] : '', $hidden ? '' : ($field['display_value'] ?? ''), $extra, self::TYPES[$field['edit_input']] ?? $field['edit_input'], $field['help'] ?? $q['help'] ?? '', implode("\n", $options)]);
|
|
|
|
|
}
|
|
|
|
|
if ($q['edit_input'] === 'multi_dimension' && $dr > $questionStart) {
|
|
|
|
|
$hasDimensions = true;
|
|
|
|
|
$questionRanges[] = [$questionStart, $dr - 1];
|
|
|
|
|
} elseif ($dr > $questionStart) $plainRows[] = $questionStart;
|
|
|
|
|
if ($hidden || $q['edit_input'] !== 'file') continue;
|
|
|
|
|
foreach ($q['value'] ?? [] as $item) {
|
|
|
|
|
$file = Upload::find($item['id'] ?? null);
|
|
|
|
|
@ -67,7 +81,25 @@ class SurveyExport
|
|
|
|
|
self::row($attachments, $ar++, [$reply->id, $name, $q['name'], $original, $valid ? $entry : '', $valid ? '已打包' : '文件缺失,未打包']);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ($dr > $replyStart) $replyRanges[] = [$replyStart, $dr - 1];
|
|
|
|
|
if ($section !== '' && $dr > $sectionStart) $sectionRanges[] = [$sectionStart, $dr - 1];
|
|
|
|
|
}
|
|
|
|
|
if (!$hasDimensions) $detail->removeColumn('F');
|
|
|
|
|
if (!$hasSections) $detail->removeColumn('C');
|
|
|
|
|
$titleColumn = $hasSections ? 'E' : 'D';
|
|
|
|
|
$numberColumn = $hasSections ? 'D' : 'C';
|
|
|
|
|
$dimensionColumn = $hasSections ? 'F' : 'E';
|
|
|
|
|
foreach ($replyRanges as [$start, $end]) {
|
|
|
|
|
self::merge($detail, 'A', $start, $end);
|
|
|
|
|
self::merge($detail, 'B', $start, $end);
|
|
|
|
|
}
|
|
|
|
|
if ($hasSections) foreach ($sectionRanges as [$start, $end]) self::merge($detail, 'C', $start, $end);
|
|
|
|
|
foreach ($questionRanges as [$start, $end]) {
|
|
|
|
|
self::merge($detail, $titleColumn, $start, $end);
|
|
|
|
|
self::merge($detail, $numberColumn, $start, $end);
|
|
|
|
|
}
|
|
|
|
|
// In mixed questionnaires a plain question spans the unused dimension cell.
|
|
|
|
|
if ($hasDimensions) foreach ($plainRows as $row) $detail->mergeCells($titleColumn.$row.':'.$dimensionColumn.$row);
|
|
|
|
|
foreach ($book->getAllSheets() as $sheet) {
|
|
|
|
|
$sheet->freezePane('C2');
|
|
|
|
|
$sheet->setAutoFilter($sheet->calculateWorksheetDimension());
|
|
|
|
|
@ -75,6 +107,7 @@ class SurveyExport
|
|
|
|
|
$sheet->getStyle($sheet->calculateWorksheetDimension())->getAlignment()->setWrapText(true)->setVertical('top');
|
|
|
|
|
foreach (range(1, Coordinate::columnIndexFromString($sheet->getHighestColumn())) as $col) $sheet->getColumnDimensionByColumn($col)->setWidth($col < 3 ? 18 : 32);
|
|
|
|
|
}
|
|
|
|
|
foreach ($detail->getMergeCells() as $range) $detail->getStyle($range)->getAlignment()->setVertical('center');
|
|
|
|
|
(new Xlsx($book))->save($base.'.xlsx');
|
|
|
|
|
$zip->addFile($base.'.xlsx', '问卷答卷明细.xlsx');
|
|
|
|
|
if (!$zip->close()) throw new \RuntimeException('导出压缩包生成失败');
|
|
|
|
|
@ -90,6 +123,11 @@ class SurveyExport
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static function merge($sheet, string $column, int $start, int $end): void
|
|
|
|
|
{
|
|
|
|
|
if ($end > $start) $sheet->mergeCells($column.$start.':'.$column.$end);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static function row($sheet, int $row, array $values): void
|
|
|
|
|
{
|
|
|
|
|
foreach ($values as $index => $value) {
|
|
|
|
|
|