CaiWuXiTong/modules/EcommerceFinance/Services/SupplierPayableImportTemplate.php

90 lines
4.3 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace Modules\EcommerceFinance\Services;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Style\Border;
use PhpOffice\PhpSpreadsheet\Style\Fill;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use Symfony\Component\HttpFoundation\StreamedResponse;
class SupplierPayableImportTemplate
{
/** @param array<string,array{label:string,type:string}> $fields */
public function download(string $title, array $fields): StreamedResponse
{
return response()->streamDownload(function () use ($title, $fields): void {
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->setTitle($this->sheetTitle($title));
$headers = array_merge(['记录标识'], array_column($fields, 'label'));
$sheet->fromArray($headers, null, 'A1');
$lastColumn = Coordinate::stringFromColumnIndex(count($headers));
$headerRange = 'A1:' . $lastColumn . '1';
$sheet->getStyle($headerRange)->applyFromArray([
'font' => ['bold' => true, 'color' => ['rgb' => 'FFFFFF']],
'fill' => ['fillType' => Fill::FILL_SOLID, 'startColor' => ['rgb' => '856632']],
'alignment' => ['horizontal' => Alignment::HORIZONTAL_CENTER, 'vertical' => Alignment::VERTICAL_CENTER],
'borders' => ['allBorders' => ['borderStyle' => Border::BORDER_THIN, 'color' => ['rgb' => 'D8D2C7']]],
]);
$sheet->getRowDimension(1)->setRowHeight(24);
$sheet->freezePane('A2');
$sheet->setAutoFilter($headerRange);
$sheet->getColumnDimension('A')->setWidth(38);
$columnIndex = 2;
foreach ($fields as $definition) {
$column = Coordinate::stringFromColumnIndex($columnIndex);
$width = max(14, min(30, mb_strlen($definition['label']) * 2 + 4));
$sheet->getColumnDimension($column)->setWidth($width);
if ($definition['type'] === 'number') {
$sheet->getStyle($column . '2:' . $column . '10001')->getNumberFormat()->setFormatCode('0.0000');
} else {
$sheet->getStyle($column . '2:' . $column . '10001')->getNumberFormat()->setFormatCode('@');
}
$columnIndex++;
}
$sheet->getStyle('A2:A10001')->getNumberFormat()->setFormatCode('@');
$instructions = $spreadsheet->createSheet();
$instructions->setTitle('填写说明');
$instructions->fromArray([
['项目', '说明'],
['记录标识', '必填。请从本页面导出的文件中复制,不能修改。'],
['日期', '请填写 YYYY-MM-DD,例如 2026-09-17。'],
['月份', '请填写 YYYY-MM,例如 2026-09。'],
['数字', '最多支持 4 位小数;金额可直接填写数字。'],
['空白单元格', '导入后将清空该字段,请确认后再导入。'],
], null, 'A1');
$instructions->getStyle('A1:B1')->applyFromArray([
'font' => ['bold' => true, 'color' => ['rgb' => 'FFFFFF']],
'fill' => ['fillType' => Fill::FILL_SOLID, 'startColor' => ['rgb' => '856632']],
]);
$instructions->getColumnDimension('A')->setWidth(18);
$instructions->getColumnDimension('B')->setWidth(58);
$instructions->getStyle('A1:B6')->getAlignment()->setVertical(Alignment::VERTICAL_CENTER)->setWrapText(true);
foreach (range(1, 6) as $row) {
$instructions->getRowDimension($row)->setRowHeight($row === 1 ? 24 : 32);
}
$spreadsheet->setActiveSheetIndex(0);
(new Xlsx($spreadsheet))->save('php://output');
$spreadsheet->disconnectWorksheets();
}, $title . '_导入模板_' . now()->format('Ymd') . '.xlsx', [
'Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'Cache-Control' => 'private, no-store',
]);
}
private function sheetTitle(string $title): string
{
$title = str_replace(['\\', '/', '?', '*', '[', ']', ':'], '', $title) ?: '导入模板';
return mb_substr($title, 0, 31);
}
}