606 lines
21 KiB
PHP
606 lines
21 KiB
PHP
<?php
|
||
|
||
namespace app\mzl\modules\phpoffice\service;
|
||
|
||
use support\Db;
|
||
// use support\Log;
|
||
use support\exception\BusinessException;
|
||
use app\api\model\PracticeItemsModel;
|
||
use app\api\model\PracticeItemsScoreModel;
|
||
use app\api\model\PracticeModel;
|
||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
||
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||
use PhpOffice\PhpSpreadsheet\Style\Alignment;
|
||
use PhpOffice\PhpSpreadsheet\Style\Border;
|
||
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing;
|
||
// use PhpOffice\PhpSpreadsheet\Style\Fill;
|
||
// use PhpOffice\PhpSpreadsheet\Shared\Drawing as SharedDrawing;
|
||
// use PhpOffice\PhpSpreadsheet\Writer\Pdf\Dompdf as PdfWriter;
|
||
use PhpOffice\PhpSpreadsheet\Worksheet\PageSetup;
|
||
use PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf as PdfWriter;
|
||
use Mpdf\Config\ConfigVariables;
|
||
use Mpdf\Config\FontVariables;
|
||
use PhpOffice\PhpSpreadsheet\Writer\Pdf\Tcpdf as TcPdfWriter;
|
||
|
||
class ExcelService
|
||
{
|
||
|
||
// 配置
|
||
protected $config = [];
|
||
|
||
public function __construct()
|
||
{
|
||
$this->config = getConfig('/mzl/modules/phpoffice/config/excel_import.php');
|
||
}
|
||
|
||
/**
|
||
* 导入Excel数据
|
||
*/
|
||
public function importToData(string $template_key, string $filePath): array
|
||
{
|
||
$config = $this->config[$template_key] ?? null;
|
||
if (!$config) {
|
||
throw new BusinessException("未找到模板配置:$template_key");
|
||
}
|
||
$spreadsheet = IOFactory::load($filePath);
|
||
$sheet = $spreadsheet->getActiveSheet();
|
||
$rows = $sheet->toArray(null, true, true, true);
|
||
$callback = $this->callback($template_key) ?? null;
|
||
return $this->toData($rows, $config['column_map'], $callback);
|
||
}
|
||
|
||
/**
|
||
* 条件回调
|
||
*/
|
||
public function callback(string $template_key)
|
||
{
|
||
switch ($template_key) {
|
||
case 'student':
|
||
$callback = function ($row, $i) {
|
||
return $i < 3 || empty($row['C']);
|
||
};
|
||
break;
|
||
case 'user':
|
||
$callback = function ($row, $i) {
|
||
return $i < 2 || empty($row['D']);
|
||
};
|
||
break;
|
||
}
|
||
return $callback;
|
||
}
|
||
|
||
/**
|
||
* 获取数据
|
||
*/
|
||
public function toData(array $rows = [], array $columnMap = [], $callback = null)
|
||
{
|
||
$data = [];
|
||
foreach ($rows as $i => $row) {
|
||
if ($callback && $callback($row, $i)) {
|
||
continue;
|
||
}
|
||
$item = [];
|
||
foreach ($columnMap as $excelKey => $dbField) {
|
||
$item[$dbField] = trim((string)($row[$excelKey] ?? ''));
|
||
}
|
||
$data[] = $item;
|
||
}
|
||
return $data;
|
||
}
|
||
|
||
/**
|
||
* 导入practice
|
||
*/
|
||
public function importPractice(string $filePath)
|
||
{
|
||
Db::beginTransaction();
|
||
try {
|
||
$spreadsheet = IOFactory::load($filePath);
|
||
$sheet = $spreadsheet->getSheet(0);
|
||
$rows = $sheet->toArray();
|
||
|
||
// 解析标题行
|
||
$titleRow = trim($rows[0][0]);
|
||
preg_match('/(.*?)\s+([A-Za-z0-9-]+\/[A-Za-z0-9]+)$/', $titleRow, $matches);
|
||
|
||
$practice = PracticeModel::create([
|
||
'sn' => generateRandomSN(),
|
||
'title' => $matches[1] ?? '未知标题',
|
||
'code' => $matches[2] ?? '未编号'
|
||
]);
|
||
|
||
$currentItem = null;
|
||
|
||
foreach ($rows as $index => $row) {
|
||
// 跳过表头前两行(标题行+列头行)
|
||
if ($index < 2 || empty(array_filter($row))) continue;
|
||
|
||
// 处理主检查项
|
||
if (!empty($row[0]) && is_numeric($row[0])) {
|
||
$currentItem = PracticeItemsModel::create([
|
||
'practice_id' => $practice->id,
|
||
'index' => $row[0],
|
||
'exam_content' => $row[1],
|
||
'scoring_element' => $row[2],
|
||
'score_allocation' => $row[3]
|
||
]);
|
||
}
|
||
|
||
// 处理评分标准
|
||
if ($currentItem && !empty($row[4])) {
|
||
PracticeItemsScoreModel::create([
|
||
'practice_item_id' => $currentItem->id,
|
||
'scoring_criteria' => $row[4],
|
||
'max_deduction' => $row[5],
|
||
'single_deduction' => $row[6]
|
||
]);
|
||
}
|
||
}
|
||
|
||
DB::commit();
|
||
return true;
|
||
} catch (\Throwable $e) {
|
||
DB::rollBack();
|
||
return false;
|
||
}
|
||
}
|
||
|
||
|
||
// ====== ====== ====== 公共方法 ====== ====== ======
|
||
private function setColumnWidths($sheet, array $widths)
|
||
{
|
||
foreach ($widths as $column => $width) {
|
||
$sheet->getColumnDimension($column)->setWidth($width);
|
||
}
|
||
}
|
||
private function setRowHeights($sheet, array $heights)
|
||
{
|
||
foreach ($heights as $row => $height) {
|
||
$sheet->getRowDimension($row)->setRowHeight($height);
|
||
}
|
||
}
|
||
private function centerAlignAllCells($sheet)
|
||
{
|
||
$maxRow = $sheet->getHighestRow();
|
||
$maxCol = $sheet->getHighestColumn();
|
||
$sheet->getStyle("A1:{$maxCol}{$maxRow}")->applyFromArray([
|
||
'alignment' => [
|
||
'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
|
||
'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER,
|
||
]
|
||
]);
|
||
}
|
||
private function setGlobalFont($sheet, $start = null, $end = null, $name = '宋体', $size = 10)
|
||
{
|
||
if ($start && $end) {
|
||
$fw = "{$start}:{$end}";
|
||
} else {
|
||
$maxRow = $sheet->getHighestRow();
|
||
$maxCol = $sheet->getHighestColumn();
|
||
$fw = "A1:{$maxCol}{$maxRow}";
|
||
}
|
||
$sheet->getStyle($fw)->applyFromArray([
|
||
'font' => [
|
||
'name' => $name,
|
||
'size' => $size,
|
||
],
|
||
]);
|
||
}
|
||
// ====== ====== ====== 公共方法 ====== ====== ======
|
||
|
||
|
||
/**
|
||
* 导出 班级总结
|
||
*/
|
||
public function exportClassSummary2(array $data, string $outputPath = '班级总结', ?string $signatureImage = null)
|
||
{
|
||
$spreadsheet = new Spreadsheet();
|
||
$sheet = $spreadsheet->getActiveSheet();
|
||
|
||
// ====== 1. 标题 & 基础信息 ======
|
||
$sheet->setCellValue('A1', $data['title'] ?? 'XX(班级名称)班级信息');
|
||
// 标题行立即合并
|
||
$sheet->mergeCells('A1:C1');
|
||
|
||
$basicInfo = [
|
||
['开班地点', 'location'],
|
||
['开班类型', 'type'],
|
||
['培训项目', 'program'],
|
||
['授课老师', 'teacher'],
|
||
['培训时间', 'time'],
|
||
['参培学员', 'students'],
|
||
['合格人员', 'passed'],
|
||
['通过率', 'pass_rate'],
|
||
];
|
||
$row = 2;
|
||
foreach ($basicInfo as $info) {
|
||
[$label, $key] = $info;
|
||
$sheet->setCellValue("A{$row}", $label);
|
||
$sheet->setCellValue("B{$row}", $data[$key] ?? '');
|
||
$sheet->mergeCells("B{$row}:C{$row}");
|
||
$row++;
|
||
}
|
||
|
||
// ====== 2. 理论考试 ======
|
||
if (! empty($data['theory_exams'])) {
|
||
foreach ($data['theory_exams'] as $idx => $exam) {
|
||
$subject = $exam['subject'] ?? "科目" . ($idx + 1);
|
||
$fields = [
|
||
'考试时间' => 'time',
|
||
'考试地点' => 'location',
|
||
'主监考' => 'main_invigilator',
|
||
'监考人员' => 'invigilators',
|
||
'不及格人数' => 'fail_count',
|
||
'合格率' => 'pass_rate',
|
||
];
|
||
$blockSize = count($fields);
|
||
$startRow = $row;
|
||
$endRow = $row + $blockSize - 1;
|
||
|
||
$sheet->mergeCells("A{$startRow}:A{$endRow}");
|
||
$sheet->setCellValue("A{$startRow}", "理论考试信息({$subject})");
|
||
|
||
$r = $startRow;
|
||
foreach ($fields as $label => $key) {
|
||
$sheet->setCellValue("B{$r}", $label);
|
||
$sheet->setCellValue("C{$r}", $exam[$key] ?? '');
|
||
$r++;
|
||
}
|
||
|
||
$row = $endRow + 1;
|
||
}
|
||
}
|
||
|
||
// ====== 3. 实操考试 ======
|
||
if (! empty($data['practice_exams'])) {
|
||
foreach ($data['practice_exams'] as $idx => $exam) {
|
||
$subject = $exam['subject'] ?? "实操" . ($idx + 1);
|
||
$fields = [
|
||
'考试科目' => 'subject',
|
||
'考试时间' => 'time',
|
||
'考试地点' => 'location',
|
||
'不及格人数' => 'fail_count',
|
||
'合格率' => 'pass_rate',
|
||
];
|
||
$blockSize = count($fields);
|
||
$startRow = $row;
|
||
$endRow = $row + $blockSize - 1;
|
||
|
||
$sheet->mergeCells("A{$startRow}:A{$endRow}");
|
||
$sheet->setCellValue("A{$startRow}", "实操考试信息({$subject})");
|
||
|
||
$r = $startRow;
|
||
foreach ($fields as $label => $key) {
|
||
$sheet->setCellValue("B{$r}", $label);
|
||
$sheet->setCellValue("C{$r}", $exam[$key] ?? '');
|
||
$r++;
|
||
}
|
||
|
||
$row = $endRow + 1;
|
||
}
|
||
}
|
||
|
||
// ====== 5. 样式:合并、边框、对齐、行高、字体 ======
|
||
$lastRow = $row;
|
||
|
||
// 全区域合并边框
|
||
$sheet->getStyle("A1:C{$lastRow}")->applyFromArray([
|
||
'borders' => ['allBorders'=>['borderStyle'=>Border::BORDER_THIN]],
|
||
]);
|
||
|
||
// 对齐
|
||
$maxCol = $sheet->getHighestColumn();
|
||
$sheet->getStyle("A1:{$maxCol}{$lastRow}")->applyFromArray([
|
||
'alignment'=>[
|
||
'horizontal'=>\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
|
||
'vertical' =>\PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER,
|
||
]
|
||
]);
|
||
|
||
// 字体
|
||
// 标题行
|
||
$sheet->getStyle('A1')->applyFromArray([
|
||
'font'=>['name'=>'黑体','size'=>22],
|
||
]);
|
||
// 正文字体
|
||
$sheet->getStyle("A2:C{$lastRow}")->applyFromArray([
|
||
'font'=>['name'=>'宋体','size'=>10],
|
||
]);
|
||
// 班主任行单独字号 12
|
||
$sheet->getStyle("A{$row}:C{$row}")->applyFromArray([
|
||
'font'=>['name'=>'宋体','size'=>12],
|
||
]);
|
||
|
||
// 行高
|
||
$sheet->getRowDimension(1)->setRowHeight(36);
|
||
for ($r = 2; $r < $lastRow; $r++) {
|
||
$sheet->getRowDimension($r)->setRowHeight(21.75);
|
||
}
|
||
$sheet->getRowDimension($lastRow)->setRowHeight(54);
|
||
|
||
// 列宽
|
||
$sheet->getColumnDimension('A')->setWidth(30);
|
||
$sheet->getColumnDimension('B')->setWidth(30);
|
||
$sheet->getColumnDimension('C')->setWidth(24);
|
||
|
||
// ====== 4. 班主任签名(水平+垂直居中) ======
|
||
$sheet->setCellValue("A{$row}", '班主任');
|
||
// 合并 B、C 列
|
||
$sheet->mergeCells("B{$row}:C{$row}");
|
||
|
||
if ($signatureImage && file_exists($signatureImage)) {
|
||
$drawing = new Drawing();
|
||
$drawing->setPath($signatureImage);
|
||
// 先指定高度,等比例缩放宽度
|
||
$drawing->setHeight(40);
|
||
$drawing->setResizeProportional(true);
|
||
// 锚定到 B{$row} 单元格
|
||
$drawing->setCoordinates("B{$row}");
|
||
// 必须先 add 到工作表,才能正确计算后续的 getWidth()/getHeight()
|
||
$drawing->setWorksheet($sheet);
|
||
|
||
// —— 计算区域像素尺寸 ——
|
||
// 列宽单位转像素近似:1 单位 ≈ 7px
|
||
// 行高点(pt)转像素近似:1pt ≈ 96/72 px
|
||
$pxPerWidth = 7;
|
||
$pxPerPoint = 96 / 72;
|
||
|
||
$widthB = $sheet->getColumnDimension('B')->getWidth();
|
||
$widthC = $sheet->getColumnDimension('C')->getWidth();
|
||
$totalWidthPx = ($widthB + $widthC) * $pxPerWidth;
|
||
|
||
$rowHeightPt = $sheet->getRowDimension($row)->getRowHeight();
|
||
$totalHeightPx = $rowHeightPt * $pxPerPoint;
|
||
|
||
// 这时 getWidth()/getHeight() 才会返回渲染后的像素值
|
||
$imageWidthPx = $drawing->getWidth();
|
||
$imageHeightPx = $drawing->getHeight();
|
||
|
||
// 计算居中偏移
|
||
$offsetX = max(0, ($totalWidthPx - $imageWidthPx) / 2);
|
||
$offsetY = max(0, ($totalHeightPx - $imageHeightPx) / 2);
|
||
|
||
$drawing->setOffsetX($offsetX);
|
||
$drawing->setOffsetY($offsetY);
|
||
} else {
|
||
$sheet->setCellValue("B{$row}", $data['class_teacher'] ?? '');
|
||
}
|
||
|
||
// 最后保存
|
||
$writer = new Xlsx($spreadsheet);
|
||
$writer->save($outputPath);
|
||
}
|
||
|
||
|
||
public function exportClassSummary(array $data, string $outputPath = '班级总结', ?string $signatureImage = null)
|
||
{
|
||
$spreadsheet = $this->buildClassSummarySpreadsheet($data, $signatureImage);
|
||
$writer = new Xlsx($spreadsheet);
|
||
$writer->save($outputPath);
|
||
}
|
||
|
||
/**
|
||
* 构建班级总结的 Spreadsheet 对象(复用给 XLSX 和 PDF)
|
||
*
|
||
* @param array $data
|
||
* @param string|null $signatureImage
|
||
* @return Spreadsheet
|
||
*/
|
||
protected function buildClassSummarySpreadsheet(array $data, ?string $signatureImage = null): Spreadsheet
|
||
{
|
||
$spreadsheet = new Spreadsheet();
|
||
$sheet = $spreadsheet->getActiveSheet();
|
||
|
||
//
|
||
// 1. 标题 & 基础信息
|
||
//
|
||
$sheet->setCellValue('A1', $data['title'] ?? 'XX(班级名称)班级信息');
|
||
$sheet->mergeCells('A1:C1');
|
||
|
||
$basicInfo = [
|
||
['开班地点', 'location'],
|
||
['开班类型', 'type'],
|
||
['培训项目', 'program'],
|
||
['授课老师', 'teacher'],
|
||
['培训时间', 'time'],
|
||
['参培学员', 'students'],
|
||
['合格人员', 'passed'],
|
||
['通过率', 'pass_rate'],
|
||
];
|
||
$row = 2;
|
||
foreach ($basicInfo as $info) {
|
||
[$label, $key] = $info;
|
||
$sheet->setCellValue("A{$row}", $label);
|
||
$sheet->setCellValue("B{$row}", $data[$key] ?? '');
|
||
$sheet->mergeCells("B{$row}:C{$row}");
|
||
$row++;
|
||
}
|
||
|
||
//
|
||
// 2. 理论考试(theory_exams)
|
||
//
|
||
if (! empty($data['theory_exams']) && is_array($data['theory_exams'])) {
|
||
foreach ($data['theory_exams'] as $idx => $exam) {
|
||
$subject = $exam['subject'] ?? '科目' . ($idx + 1);
|
||
$fields = [
|
||
'考试时间' => 'time',
|
||
'考试地点' => 'location',
|
||
'主监考' => 'main_invigilator',
|
||
'监考人员' => 'invigilators',
|
||
'不及格人数' => 'fail_count',
|
||
'合格率' => 'pass_rate',
|
||
];
|
||
$blockSize = count($fields);
|
||
$startRow = $row;
|
||
$endRow = $row + $blockSize - 1;
|
||
|
||
$sheet->mergeCells("A{$startRow}:A{$endRow}");
|
||
$sheet->setCellValue("A{$startRow}", "理论考试信息({$subject})");
|
||
|
||
$r = $startRow;
|
||
foreach ($fields as $label => $key) {
|
||
$sheet->setCellValue("B{$r}", $label);
|
||
$sheet->setCellValue("C{$r}", $exam[$key] ?? '');
|
||
$r++;
|
||
}
|
||
|
||
$row = $endRow + 1;
|
||
}
|
||
}
|
||
|
||
//
|
||
// 3. 实操考试(practice_exams)
|
||
//
|
||
if (! empty($data['practice_exams']) && is_array($data['practice_exams'])) {
|
||
foreach ($data['practice_exams'] as $idx => $exam) {
|
||
$subject = $exam['subject'] ?? '实操' . ($idx + 1);
|
||
$fields = [
|
||
'考试科目' => 'subject',
|
||
'考试时间' => 'time',
|
||
'考试地点' => 'location',
|
||
'不及格人数' => 'fail_count',
|
||
'合格率' => 'pass_rate',
|
||
];
|
||
$blockSize = count($fields);
|
||
$startRow = $row;
|
||
$endRow = $row + $blockSize - 1;
|
||
|
||
$sheet->mergeCells("A{$startRow}:A{$endRow}");
|
||
$sheet->setCellValue("A{$startRow}", "实操考试信息({$subject})");
|
||
|
||
$r = $startRow;
|
||
foreach ($fields as $label => $key) {
|
||
$sheet->setCellValue("B{$r}", $label);
|
||
$sheet->setCellValue("C{$r}", $exam[$key] ?? '');
|
||
$r++;
|
||
}
|
||
|
||
$row = $endRow + 1;
|
||
}
|
||
}
|
||
|
||
//
|
||
// 4. 样式预设:列宽、行高、边框、对齐、字体
|
||
//
|
||
// 列宽
|
||
$sheet->getColumnDimension('A')->setWidth(30);
|
||
$sheet->getColumnDimension('B')->setWidth(30);
|
||
$sheet->getColumnDimension('C')->setWidth(24);
|
||
|
||
// 当前签名行号
|
||
$lastRow = $row;
|
||
|
||
// 行高
|
||
$sheet->getRowDimension(1)->setRowHeight(36);
|
||
for ($r = 2; $r < $lastRow; $r++) {
|
||
$sheet->getRowDimension($r)->setRowHeight(21.75);
|
||
}
|
||
$sheet->getRowDimension($lastRow)->setRowHeight(54);
|
||
|
||
// 边框 + 对齐 + 正文字体
|
||
$sheet->getStyle("A1:C{$lastRow}")->applyFromArray([
|
||
'borders' => ['allBorders' => ['borderStyle' => Border::BORDER_THIN]],
|
||
'alignment' => [
|
||
'horizontal' => Alignment::HORIZONTAL_CENTER,
|
||
'vertical' => Alignment::VERTICAL_CENTER,
|
||
],
|
||
'font' => ['name' => '宋体', 'size' => 10],
|
||
]);
|
||
|
||
// 标题行字体
|
||
$sheet->getStyle('A1')->applyFromArray([
|
||
'font' => ['name' => '黑体', 'size' => 22],
|
||
]);
|
||
|
||
//
|
||
// 5. 班主任签名 & 图片居中
|
||
//
|
||
$sheet->setCellValue("A{$lastRow}", '班主任');
|
||
$sheet->mergeCells("B{$lastRow}:C{$lastRow}");
|
||
|
||
if ($signatureImage && file_exists($signatureImage)) {
|
||
$drawing = new Drawing();
|
||
$drawing->setPath($signatureImage);
|
||
$drawing->setResizeProportional(true);
|
||
$drawing->setHeight(40);
|
||
$drawing->setCoordinates("B{$lastRow}");
|
||
$drawing->setWorksheet($sheet);
|
||
|
||
// 近似像素转换系数
|
||
$pxPerColWidth = 7;
|
||
$pxPerPoint = 96 / 72;
|
||
|
||
// 区域宽度 & 高度
|
||
$wB = $sheet->getColumnDimension('B')->getWidth();
|
||
$wC = $sheet->getColumnDimension('C')->getWidth();
|
||
$areaW = ($wB + $wC) * $pxPerColWidth;
|
||
$hPt = $sheet->getRowDimension($lastRow)->getRowHeight();
|
||
$areaH = $hPt * $pxPerPoint;
|
||
|
||
// 图片渲染后尺寸
|
||
$imgW = $drawing->getWidth();
|
||
$imgH = $drawing->getHeight();
|
||
|
||
// 计算偏移并应用
|
||
$drawing->setOffsetX(max(0, ($areaW - $imgW) / 2));
|
||
$drawing->setOffsetY(max(0, ($areaH - $imgH) / 2));
|
||
} else {
|
||
// 文字班主任行单独字号
|
||
$sheet->getStyle("B{$lastRow}:C{$lastRow}")->applyFromArray([
|
||
'font' => ['name' => '宋体', 'size' => 12],
|
||
]);
|
||
$sheet->setCellValue("B{$lastRow}", $data['class_teacher'] ?? '');
|
||
}
|
||
|
||
return $spreadsheet;
|
||
}
|
||
|
||
/**
|
||
* 导出 PDF 文件
|
||
*
|
||
* @param array $data
|
||
* @param string $pdfPath
|
||
* @param string|null $signatureImage
|
||
*/
|
||
public function exportClassSummaryPdf(array $data, string $pdfPath, ?string $signatureImage = null)
|
||
{
|
||
// 1. 复用生成表格的逻辑
|
||
$spreadsheet = $this->buildClassSummarySpreadsheet($data, $signatureImage);
|
||
|
||
// // 2) mPDF 默认目录和字体数据
|
||
// $configVars = new ConfigVariables();
|
||
// $fontDirs = $configVars->getDefaults()['fontDir'];
|
||
// $fontVars = new FontVariables();
|
||
// $fontData = $fontVars->getDefaults()['fontdata'];
|
||
// $myFontDir = base_path('resources/fonts');
|
||
// $mpdfConfig = [
|
||
// 'mode' => 'utf-8',
|
||
// 'format' => 'A4',
|
||
// 'fontDir' => array_merge($fontDirs, [$myFontDir]),
|
||
// 'fontdata' => array_merge($fontData, [
|
||
// 'sourcehansc' => [
|
||
// 'R' => 'SourceHanSans-Regular.ttf',
|
||
// 'B' => 'SourceHanSans-Bold.ttf',
|
||
// ]
|
||
// ]),
|
||
// 'default_font'=> 'sourcehansc',
|
||
// 'autoScriptToLang'=> true,
|
||
// 'autoLangToFont' => true,
|
||
// ];
|
||
// // 2. 用 mPDF Writer 输出 PDF
|
||
// $pdfWriter = new PdfWriter($spreadsheet, $mpdfConfig);
|
||
// $pdfWriter->setFont('宋体');
|
||
// $pdfWriter->setPaperSize(PageSetup::PAPERSIZE_A4);
|
||
// $pdfWriter->setOrientation(PageSetup::ORIENTATION_PORTRAIT);
|
||
// $pdfWriter->save($pdfPath);
|
||
|
||
|
||
// 2. 用 TCPDF Writer 输出 PDF
|
||
$tcpdfWriter = new TcPdfWriter($spreadsheet);
|
||
$tcpdfWriter->setFont('cid0cs');
|
||
$tcpdfWriter->setPaperSize(PageSetup::PAPERSIZE_A4);
|
||
$tcpdfWriter->setOrientation(PageSetup::ORIENTATION_PORTRAIT);
|
||
$tcpdfWriter->save($pdfPath);
|
||
}
|
||
} |