Dcat 系统默认使用 Easy Excel 作为导出工具,支持导出 csvxlsxods 等格式文件。

使用前必须先安装 Easy Excel

composer require dcat/easy-excel

Easy Excel 最后一次更新是2年前,它所依赖的 box/spout 包已经停止维护, 在我们执行完 composer 指令后,能看到控制台有警告信息:

Package box/spout is abandoned, you should avoid using it. No replacement was suggested.

我有如下两个方法可以解决此问题。

方法一

经了解,box/spou 包2年前停止维护,现有一个替代包 openspout/openspout。根据 OpenSpout 的说明,要替换也很简单,只需2步:

Upgrade from box/spout:v3 to openspout/openspout:v3

  1. Replace box/spout with openspout/openspout in your composer.json
  2. Replace Box\Spout with OpenSpout in your code

我在 packagist.org 网站上找到了一个别人已经替换好的新包 sbr/easy-excel,安装如下:

# 移除旧包
composer remove dcat/easy-excel

# 安装新包
composer require sbr/easy-excel

无须更改之前的业务代码,导出功能可正常使用。且旧版导出中文文件名变成下划线的问题,也不再出现了!

方法二

参考 Dcat 文档中拓展导出功能的示例,我们可以自己新建一个导出类 app/Admin/Extensions/ExcelExporter.php

<?php

namespace App\Admin\Extensions;

use Dcat\Admin\Grid;
use Dcat\Admin\Grid\Exporters\AbstractExporter;
use OpenSpout\Common\Entity\Row;
use OpenSpout\Writer\AbstractWriter;
use OpenSpout\Writer\CSV\Writer as CSVWriter;
use OpenSpout\Writer\ODS\Writer as ODSWriter;
use OpenSpout\Writer\XLSX\Writer as XLSXWriter;

class ExcelExporter extends AbstractExporter
{
    private AbstractWriter $writer;

    public function export()
    {
        // 设置脚本允许使用的最大内存,根据自己项目情况设置
        ini_set('memory_limit', '512M');

        $this->writer = match ($this->extension) {
            'csv' => new CSVWriter(),
            'ods' => new ODSWriter(),
            'xlsx' => new XLSXWriter(),
        };

        $this->writer->openToBrowser($this->getFilename().'.'.$this->extension);

        $titles = $this->titles();
        $this->addTitles($titles);

        if ($this->scope === Grid\Exporter::SCOPE_ALL) {
            $page = 1;
            while ($rows = $this->buildData($page)) {
                $this->addRows($titles, $rows);
                $page++;
            }
        } else {
            $rows = $this->buildData();
            $rows && $this->addRows($titles, $rows);
        }

        $this->writer->close();

        exit;
    }

    private function addTitles(array $titles)
    {
        $rowFromValues = Row::fromValues($titles);
        $this->writer->addRow($rowFromValues);
    }

    private function addRows(array $titles, array $rows)
    {
        foreach ($rows as $row) {
            $values = [];
            foreach ($titles as $key => $title) {
                $values[$key] = $row[$key] ?? '';
            }
            $rowFromValues = Row::fromValues($values);
            $this->writer->addRow($rowFromValues);
        }
    }
}

这个导出类依赖于 openspout/openspout:v4,因此需要安装依赖包:

# 移除旧包
composer remove dcat/easy-excel

# 安装依赖包
composer require openspout/openspout:^4.0

接着,在 app/Admin/bootstrap.php 中加入下面的代码:

use App\Admin\Extensions\ExcelExporter;
use Dcat\Admin\Grid;

Grid::resolving(function (Grid $grid) {
    $grid->exporter()->resolve(new ExcelExporter());
});

这样,系统默认的导出类就变成了我们的自定义类,也不需要更改之前的业务代码了。