记录一次使用thinkphp使用PhpSpreadsheet扩展导出数据,解决身份证号码等信息科学计数法问题处理

PhpSpreadsheet官网

PhpSpreadsheet安装

composer require phpoffice/phpspreadsheet

使用composer安装时一定要下载php对应的版本,下载之前使用php -v检查当前php版本

简单使用

<?php
require 'vendor/autoload.php';

use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;

// 创建Spreadsheet对象
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();

// 动态表头
$headers = ['ID', '姓名', '性别', '职业', '新增字段', '新增字段2', '新增字段3', '新增字段4', '新增字段5', '新增字段6', '新增字段7', '新增字段8', '新增字段9', '新增字段10', '新增字段11', '新增字段12', '新增字段13', '新增字段14', '新增字段15', '新增字段16', '新增字段17', '新增字段18', '新增字段19', '新增字段20', '新增字段21', '新增字段22', '新增字段23', '新增字段24', '新增字段25', '新增字段26', '新增字段27', '新增字段28', '新增字段29', '新增字段30'];

// 动态数据
$data = [
    [1, '李云龙', '男', '军人', '1427141544485854854485', '字段1', '字段2', '字段3', '字段4', '字段5', '字段6', '字段7', '字段8', '字段9', '字段10', '字段11', '字段12', '字段13', '字段14', '字段15', '字段16', '字段17', '字段18', '字段19', '字段20', '字段21', '字段22', '字段23', '字段24', '字段25', '字段26', '字段27', '字段28', '字段29', '字段30'],
    [2, '苏乞儿', '男', '乞丐', '值2', '字段1', '字段2', '字段3', '字段4', '字段5', '字段6', '字段7', '字段8', '字段9', '字段10', '字段11', '字段12', '字段13', '字段14', '字段15', '字段16', '字段17', '字段18', '字段19', '字段20', '字段21', '字段22', '字段23', '字段24', '字段25', '字段26', '字段27', '字段28', '字段29', '字段30'],
    [3, '周星驰', '男', '导演', '值3', '字段1', '字段2', '字段3', '字段4', '字段5', '字段6', '字段7', '字段8', '字段9', '字段10', '字段11', '字段12', '字段13', '字段14', '字段15', '字段16', '字段17', '字段18', '字段19', '字段20', '字段21', '字段22', '字段23', '字段24', '字段25', '字段26', '字段27', '字段28', '字段29', '字段30'],
    [4, '林允儿', '女', '演员', '值4', '字段1', '字段2', '字段3', '字段4', '字段5', '字段6', '字段7', '字段8', '字段9', '字段10', '字段11', '字段12', '字段13', '字段14', '字段15', '字段16', '字段17', '字段18', '字段19', '字段20', '字段21', '字段22', '字段23', '字段24', '字段25', '字段26', '字段27', '字段28', '字段29', '字段30'],
];

// 设置表头和数据
$allData = array_merge([$headers], $data);
$sheet->fromArray($allData, null, 'A1');

// 设置表头样式
$styleArray = [
    'alignment' => [
        'horizontal' => 'center',
        'vertical' => 'center',
    ],
    'font' => [
        'name' => '宋体',
        // 'bold' => true,
        // 'size' => 22
    ]
];

$headerRange = 'A1:' . chr(ord('A') + count($headers) - 1) . '1';
$sheet->getStyle($headerRange)
    ->getNumberFormat()  // 先获取NumberFormat对象
    ->setFormatCode(NumberFormat::FORMAT_TEXT)
    ->applyFromArray($styleArray);

// 保存文件
$writer = new Xlsx($spreadsheet);
$writer->save('dynamic_example.xlsx');



?>

在thinkphp项目中使用

// 如果将该扩展直接安装到thinkphp6项目中提示找不到Class 'PhpOffice\\PhpSpreadsheet\\Spreadsheet' not found,将该扩展放置项目根目录的extend文件夹中(参考下图),随后打开下行代码
// require_once app()->getRootPath() . 'extend/PhpSpreadsheet/autoload.php';
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\Cell\DataType;

public function export_data($data){
    // 获取所有要查询的字段和名称
    $header_arr = [];
    $fields_arr = [];
    foreach($data['export_data'] as $key=>$val){
        array_push($header_arr, $val['label']);
        array_push($fields_arr, $val['field']);
    } 
    // 文件存储目录
    $public = app()->getRootPath().'public/';
    $path = 'uploads/export_data/';
    if(!file_exists($path)){
        mkdir($path, 0777);
    }

    // 文件名
    $res_file = $file_name . '_all.xlsx';
    $finalFile = $public . $path . $res_file;

    $currentRow = 1; // 当前写入行
    
    $spreadsheet = new Spreadsheet();
    $sheet = $spreadsheet->getActiveSheet();
    // 3. 计算列范围 - 安全方法
    $lastColumn = Coordinate::stringFromColumnIndex(count($header_arr));
    $headerRange = 'A:' . $lastColumn;

    // $sheet->setTitle('Sheet1');
    // 如果是第一次运行,创建新文件并写入头部
    if (!file_exists($finalFile)) {
        $spreadsheet = new Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();
        $sheet->getStyle($headerRange)
            ->getNumberFormat()
            ->setFormatCode(NumberFormat::FORMAT_TEXT);

        // 写入头部
        $sheet->fromArray([$header_arr], null, 'A1');
        $currentRow = 2;

        // 设置表头样式
        $styleArray = [
            'alignment' => [
                'horizontal' => 'center',
                'vertical' => 'center',
            ],
            // 'font' => [
                // 'name' => '宋体',
                // 'bold' => true,
                // 'size' => 22
            // ]
        ];
        // $headerRange = 'A1:' . chr(ord('A') + count($header_arr) - 1) . '1';
        $sheet->getStyle($headerRange)->applyFromArray($styleArray);
        
        // 保存文件
        $writer = new Xlsx($spreadsheet);
        $writer->save($finalFile);
        // echo "创建新文件并写入头部\n";
    }

    // 分批导出并追加数据
    $totalBatches = 3; // 假设总共3批
    for ($batch = 1; $batch <= $totalBatches; $batch++) {
        // 加载现有文件
        $reader = IOFactory::createReader('Xlsx');
        $spreadsheet = $reader->load($finalFile);
        $sheet = $spreadsheet->getActiveSheet();
        
        // 获取当前最后一行
        $currentRow = $sheet->getHighestRow() + 1;
        
        // 生成测试数据 - 实际应用中从数据库获取
        $data = [];
        $perBatch = 10000;
        $start = ($batch - 1) * $perBatch + 1;
        $end = $batch * $perBatch;
        
        for ($i = $start; $i <= $end; $i++) {
            $data[] = [
                $i,
                "姓名{$i}",
                ($i % 2) ? '男' : '女',
                "职业{$i}"
            ];
        }
        // 追加数据
        $stringContent = array_map(function($row) use ($sheet, $currentRow) {
            return array_map(function($cell) {
                return (string)$cell; // 只返回值,不返回类型
            }, $row);
        }, $data);
        
        // 先设置数据
        $sheet->fromArray($stringContent, null, "A{$currentRow}");

        // 部分列强制文本格式
        $forceTextColumns = ['CI', 'AQ', 'AH']; // 需要强制文本的列
        for ($row = $currentRow; $row <= $highestRow; $row++) {
            foreach ($forceTextColumns as $col) {
                $cell = $sheet->getCell($col.$row);
                $cell->setValueExplicit(
                    $cell->getValue(),
                    DataType::TYPE_STRING
                );
                $sheet->getStyle($col.$row)->getNumberFormat()->setFormatCode('@');
            }
        }
        
        // 保存文件
        $writer = new Xlsx($spreadsheet);
        $writer->save($finalFile);
        
        echo "批次 {$batch} 数据已追加到 {$finalFile} (行 {$currentRow}-" . ($currentRow + count($data) - 1) . ")\n";
    }

    echo "所有数据已导出到 {$finalFile}\n";
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值