PHP code example of businessg / laravel-excel

1. Go to this page and download the library: Download businessg/laravel-excel library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

businessg / laravel-excel example snippets




return [
    /*
    |----------------------------------------------------------------------
    | default — 默认驱动名称
    |----------------------------------------------------------------------
    | 对应下方 drivers 数组中的 key。目前仅支持 xlswriter。
    */
    'default' => 'xlswriter',

    /*
    |----------------------------------------------------------------------
    | drivers — 驱动配置
    |----------------------------------------------------------------------
    | class     : 驱动实现类
    | disk      : 文件系统磁盘名,对应 config/filesystems.php 中的 disks key
    | exportDir : 导出文件存放子目录(相对于 disk 根路径)
    | tempDir   : 临时文件目录,null 则使用 sys_get_temp_dir()
    */
    'drivers' => [
        'xlswriter' => [
            'class'     => \BusinessG\BaseExcel\Driver\XlsWriterDriver::class,
            'disk'      => 'local',
            'exportDir' => 'export',
            'tempDir'   => null,
        ],
    ],

    /*
    |----------------------------------------------------------------------
    | logging — 日志配置
    |----------------------------------------------------------------------
    | channel : 日志通道名称,对应 config/logging.php 中的 channels key
    */
    'logging' => [
        'channel' => 'stack',
    ],

    /*
    |----------------------------------------------------------------------
    | queue — 异步队列配置
    |----------------------------------------------------------------------
    | 仅当 ExportConfig/ImportConfig 中 isAsync = true 时生效。
    |
    | connection : 队列连接名,对应 config/queue.php 中的 connections key
    | channel    : 队列名称(Laravel 的 onQueue)
    */
    'queue' => [
        'connection' => 'default',
        'channel'    => 'default',
    ],

    /*
    |----------------------------------------------------------------------
    | progress — Redis 进度追踪配置
    |----------------------------------------------------------------------
    | enabled    : 是否启用进度追踪
    | prefix     : Redis key 前缀,最终格式 {prefix}:progress:{token}
    | ttl        : 进度数据过期时间(秒)
    | connection : Redis 连接名,对应 config/database.php 中 redis.connections 的 key
    */
    'progress' => [
        'enabled'    => true,
        'prefix'     => 'LaravelExcel',
        'ttl'        => 3600,
        'connection' => 'default',
    ],

    /*
    |----------------------------------------------------------------------
    | dbLog — 数据库日志配置
    |----------------------------------------------------------------------
    | enabled : 是否启用数据库日志记录
    | model   : Eloquent Model 类名
    */
    'dbLog' => [
        'enabled' => true,
        'model'   => \BusinessG\LaravelExcel\Db\Model\ExcelLog::class,
    ],

    /*
    |----------------------------------------------------------------------
    | 事件监听器(Laravel Event)
    |----------------------------------------------------------------------
    | 内置默认(始终启用,无需重复声明):
    |   - ProgressListener    进度追踪(受 progress.enabled 控制)
    |   - ExcelLogDbListener  数据库日志(受 dbLog.enabled 控制)
    |
    | 本项为**追加**监听器:
    |   - 未配置或 []:仅使用默认
    |   - 配置类名:在默认之后追加注册,自动按序去重
    |
    | 自定义监听器需继承 \BusinessG\BaseExcel\Listener\AbstractBaseListener。
    */
    'listeners' => [
        // \BusinessG\BaseExcel\Listener\ExcelLogListener::class,
    ],

    /*
    |----------------------------------------------------------------------
    | cleanup — 临时文件自动清理
    |----------------------------------------------------------------------
    | enabled  : 是否启用
    | maxAge   : 文件最大存活时间(秒)
    | interval : 清理任务执行间隔(秒)
    */
    'cleanup' => [
        'enabled'  => true,
        'maxAge'   => 1800,
        'interval' => 3600,
    ],

    /*
    |----------------------------------------------------------------------
    | http — HTTP 接口与响应配置
    |----------------------------------------------------------------------
    |
    | 路由注册(enabled = true 时生效):
    |   自动注册 {prefix}/excel/* 路由组,无需手写 Controller 和路由文件。
    |
    | enabled    : 是否自动注册路由
    | prefix     : 路由前缀,如 'api' → api/excel/export
    | middleware : 中间件数组,应用到整个路由组
    | domain     : 项目域名(含协议),用于 info 接口拼接动态模板 URL
    |
    | fieldNaming : 接口返回 JSON 的字段命名风格
    |               'camel'(默认)— 驼峰,如 sheetListProgress、isEnd、templateUrl
    |               'snake' — 下划线,如 sheet_list_progress、is_end、template_url
    |
    | response — 统一响应体构建(闭包):
    |   responseCallback : (可选)根据执行结果组装 HTTP 响应数组的闭包。
    |     签名: function(ResponseContext $context): array
    |     ResponseContext 属性:
    |       - isSuccess (bool)      — 本次调用是否成功
    |       - code (int|string)     — 组件错误码(成功时为 ExcelErrorCode::SUCCESS,即 0)
    |       - data (mixed)          — 载荷
    |       - message (string)      — 提示文案
    |     返回值经 JSON 编码即为接口响应体(或与框架包装配合)。
    |     未配置时使用默认闭包,返回 ['code' => $context->code, 'data' => $context->data, 'message' => $context->message]。
    |     若需对齐既有 API 规范,可在闭包中改写字段名或嵌套结构,例如:
    |       return ['errno' => $context->code, 'result' => $context->data, 'msg' => $context->message];
    |
    | upload — 文件上传配置:
    |   disk : 文件系统磁盘名,对应 config/filesystems.php 中的 disks key
    |   dir  : 导入文件存放目录(相对于 disk 根路径)
    */
    'http' => [
        'enabled'    => false,
        'prefix'     => 'api',
        'middleware'  => ['api'],
        'domain'     => env('APP_URL', 'http://localhost'),
        'fieldNaming' => 'camel',
        'response'   => [
            // 自定义响应构建闭包(可选,未配置时使用默认闭包)
            // 'responseCallback' => function(\BusinessG\BaseExcel\Data\ResponseContext $context): array {
            //     return ['code' => $context->code, 'data' => $context->data, 'message' => $context->message];
            // },
        ],
        'upload' => [
            'disk' => 'local',
            'dir'  => 'excel-import',
        ],
    ],
];

'listeners' => [
    \BusinessG\BaseExcel\Listener\ExcelLogListener::class,
],

use BusinessG\BaseExcel\Event\AfterExport;
use BusinessG\BaseExcel\Listener\AbstractBaseListener;

class MyExportListener extends AbstractBaseListener
{
    public function listen(): array
    {
        return [AfterExport::class];
    }

    public function afterExport(AfterExport $event): void
    {
        // $event->config 即当前导出配置
    }
}

'export' => [
    /*
    | key(如 'orderExport')即为 business_id,
    | 调用接口时传入此值触发对应的导出逻辑。
    |
    | config : ExportConfig 子类的完整类名(必填)
    */
    'orderExport' => [
        'config' => \App\Excel\OrderExportConfig::class,
    ],
],

'import' => [
    /*
    | key(如 'orderImport')即为 business_id。
    |
    | config : ImportConfig 子类的完整类名(必填)
    | info   : 可选,附加信息。前端通过 GET /excel/info?business_id=xxx 获取。
    |
    |   info.templateBusinessId — 动态模板(推荐)
    |     值为一个导出 business_id。info 接口会自动拼接为完整 URL:
    |       {http.domain}/{http.prefix}/excel/export?business_id={templateBusinessId}
    |     对应的导出配置必须满足: isAsync=false + outPutType='out'
    |
    |   info.templateUrl — 静态模板
    |     值为完整的 URL 地址,info 接口直接返回。
    |
    |   两者二选一。如同时配置,templateUrl 优先。
    */
    'orderImport' => [
        'config' => \App\Excel\OrderImportConfig::class,
        'info'   => [
            'templateBusinessId' => 'orderImportTemplate',
        ],
    ],
],

'http' => [
    'enabled'    => true,
    'prefix'     => 'api',
    'middleware'  => ['api'],
    'domain'     => env('APP_URL', 'http://localhost'),
    // ...
],



declare(strict_types=1);

namespace App\Excel;

use App\Models\Order;
use BusinessG\BaseExcel\Data\Export\Column;
use BusinessG\BaseExcel\Data\Export\ExportCallbackParam;
use BusinessG\BaseExcel\Data\Export\ExportConfig;
use BusinessG\BaseExcel\Data\Export\Sheet;

class OrderExportConfig extends ExportConfig
{
    public string $serviceName = '订单导出';
    public bool $isAsync = false;
    public string $outPutType = self::OUT_PUT_TYPE_UPLOAD;

    public function getSheets(): array
    {
        $this->setSheets([
            new Sheet([
                'name'     => '订单列表',
                'columns'  => [
                    new Column(['title' => '订单号',   'field' => 'order_no', 'width' => 20]),
                    new Column(['title' => '客户名称', 'field' => 'customer_name']),
                    new Column(['title' => '金额',     'field' => 'amount']),
                    new Column(['title' => '状态',     'field' => 'status_text']),
                    new Column(['title' => '创建时间', 'field' => 'created_at']),
                ],
                'count'    => $this->getDataCount(),
                'data'     => [$this, 'getData'],
                'pageSize' => 1000,
            ]),
        ]);
        return $this->sheets;
    }

    public function getDataCount(): int
    {
        return Order::count();
    }

    public function getData(ExportCallbackParam $param): array
    {
        return Order::query()
            ->offset(($param->page - 1) * $param->pageSize)
            ->limit($param->pageSize)
            ->get()
            ->map(fn ($order) => [
                'order_no'      => $order->order_no,
                'customer_name' => $order->customer_name,
                'amount'        => $order->amount,
                'status_text'   => $order->status === 1 ? '已完成' : '待处理',
                'created_at'    => $order->created_at->format('Y-m-d H:i:s'),
            ])
            ->toArray();
    }
}

'export' => [
    'orderExport' => [
        'config' => \App\Excel\OrderExportConfig::class,
    ],
],



declare(strict_types=1);

namespace App\Excel;

use BusinessG\BaseExcel\Data\Export\Column;
use BusinessG\BaseExcel\Data\Export\ExportConfig;
use BusinessG\BaseExcel\Data\Export\Sheet;
use BusinessG\BaseExcel\Data\Export\Style;

class OrderImportTemplateConfig extends ExportConfig
{
    public string $serviceName = '订单导入模板';
    public bool $isAsync = false;
    public string $outPutType = self::OUT_PUT_TYPE_OUT;

    public function getSheets(): array
    {
        $this->setSheets([
            new Sheet([
                'name' => 'sheet1',
                'columns' => [
                    new Column([
                        'title' => implode("\n", [
                            '1、订单号:必填',
                            '2、金额:必填,数字类型',
                            '3、请按照模板格式填写',
                        ]),
                        'field'       => 'order_no',
                        'height'      => 58,
                        'headerStyle' => new Style([
                            'wrap'      => true,
                            'fontColor' => 0x2972F4,
                            'fontSize'  => 10,
                            'bold'      => true,
                            'align'     => [Style::FORMAT_ALIGN_LEFT, Style::FORMAT_ALIGN_VERTICAL_CENTER],
                        ]),
                        'children' => [
                            new Column(['title' => '订单号', 'field' => 'order_no', 'width' => 30]),
                            new Column(['title' => '金额',   'field' => 'amount',   'width' => 20]),
                        ],
                    ]),
                ],
                'count'    => 0,
                'data'     => [],
                'pageSize' => 1,
            ]),
        ]);
        return $this->sheets;
    }
}



declare(strict_types=1);

namespace App\Excel;

use App\Models\Order;
use BusinessG\BaseExcel\Data\Import\Column;
use BusinessG\BaseExcel\Data\Import\ImportConfig;
use BusinessG\BaseExcel\Data\Import\ImportRowCallbackParam;
use BusinessG\BaseExcel\Data\Import\Sheet;
use BusinessG\BaseExcel\Exception\ExcelException;
use BusinessG\BaseExcel\ExcelFunctions;

class OrderImportConfig extends ImportConfig
{
    public string $serviceName = '订单导入';
    public bool $isAsync = false;

    public function getSheets(): array
    {
        $this->setSheets([
            new Sheet([
                'name'        => 'sheet1',
                'headerIndex' => 2,
                'columns'     => [
                    new Column(['title' => '订单号', 'field' => 'order_no']),
                    new Column(['title' => '金额',   'field' => 'amount']),
                ],
                'callback' => [$this, 'rowCallback'],
            ]),
        ]);
        return $this->sheets;
    }

    public function rowCallback(ImportRowCallbackParam $param): void
    {
        if (empty($param->row)) {
            return;
        }

        $rowNum  = $param->rowIndex + 3;
        $orderNo = $param->row['order_no'] ?? '';
        $amount  = $param->row['amount'] ?? '';

        if (empty($orderNo)) {
            throw new ExcelException("第{$rowNum}行: 订单号不能为空");
        }

        Order::create([
            'order_no' => $orderNo,
            'amount'   => (float) $amount,
        ]);

        if (ExcelFunctions::hasContainer()) {
            ExcelFunctions::progressPushMessage(
                $param->config->getToken(),
                "第{$rowNum}行: 订单 {$orderNo} 导入成功"
            );
        }
    }
}

'export' => [
    // ...
    'orderImportTemplate' => [
        'config' => \App\Excel\OrderImportTemplateConfig::class,
    ],
],

'import' => [
    'orderImport' => [
        'config' => \App\Excel\OrderImportConfig::class,
        'info'   => [
            'templateBusinessId' => 'orderImportTemplate',
        ],
    ],
],

'connections' => [
    'redis' => [
        'driver'      => 'redis',
        'connection'  => 'default',
        'queue'       => 'default',
        'retry_after' => 90,
    ],
],

'queue' => [
    'connection' => 'redis',
    'channel'    => 'excel',
],

class OrderAsyncExportConfig extends ExportConfig
{
    public bool $isAsync = true;                           // 开启异步
    public string $outPutType = self::OUT_PUT_TYPE_UPLOAD; // 异步必须用 UPLOAD
    // ...
}

public function getSheets(): array
{
    $this->setSheets([ new Sheet([...]) ]);
    return $this->sheets;
}

new Column([
    'title'       => "1、姓名:必填\n2、邮箱:必填",
    'field'       => 'name',
    'height'      => 58,
    'headerStyle' => new Style([
        'wrap'      => true,
        'fontColor' => 0x2972F4,
        'fontSize'  => 10,
        'bold'      => true,
        'align'     => [Style::FORMAT_ALIGN_LEFT, Style::FORMAT_ALIGN_VERTICAL_CENTER],
    ]),
    'children' => [
        new Column(['title' => '姓名', 'field' => 'name',  'width' => 20]),
        new Column(['title' => '邮箱', 'field' => 'email', 'width' => 30]),
    ],
])

use BusinessG\BaseExcel\Data\Export\Style;

$headerStyle = new Style([
    'bold'            => true,
    'fontSize'        => 12,
    'fontColor'       => 0x2972F4,
    'backgroundColor' => 0xF2F2F2,
    'backgroundStyle' => Style::PATTERN_SOLID,
    'border'          => Style::BORDER_THIN,
    'align'           => [Style::FORMAT_ALIGN_CENTER, Style::FORMAT_ALIGN_VERTICAL_CENTER],
]);

new Column([
    'title'       => '备注',
    'field'       => 'remark',
    'width'       => 40,
    'headerStyle' => $headerStyle,
    'style'       => new Style(['border' => Style::BORDER_THIN, 'wrap' => true]),
])

'disks' => [
    'local' => [
        'driver' => 'local',
        'root'   => storage_path('app'),
    ],
],

'redis' => [
    'client' => env('REDIS_CLIENT', 'phpredis'),
    'default' => [
        'host'     => env('REDIS_HOST', '127.0.0.1'),
        'password' => env('REDIS_PASSWORD', null),
        'port'     => env('REDIS_PORT', 6379),
        'database' => env('REDIS_DB', 0),
    ],
],

// config/queue.php
'connections' => [
    'redis' => [
        'driver'      => 'redis',
        'connection'  => 'default',
        'queue'       => 'default',
        'retry_after' => 90,
    ],
],
bash
php artisan vendor:publish --tag=excel-config
bash
php artisan migrate
bash
php artisan excel:export "App\Excel\OrderExportConfig"
bash
php artisan queue:work redis --queue=excel