前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >PhpSpreadsheet导出Excel表格,长数字自动转科学计数法

PhpSpreadsheet导出Excel表格,长数字自动转科学计数法

作者头像
宣言言言
发布2019-12-19 13:55:25
4.3K1
发布2019-12-19 13:55:25
举报

原代码

public function down($data)
{
    $spreadsheet = new Spreadsheet();
    $sheet       = $spreadsheet->getActiveSheet();

    $lieCount = count($data['data'][0]);
    # 全部设为自动列宽
    for($i=65;$i< (65 +$lieCount);$i++){
        $sheet->getColumnDimension(strtoupper(chr($i)))->setAutoSize(true);
    }
    # 最快捷设置数据
    $sheet->fromArray($data['data']);
    # 导出
    $writer = new Xlsx($spreadsheet);
    $writer->save('php://output');
}

这样子就可以实现传入一个数组data,然后快速导出成Excel表格了。 但是遇到长数字的时候,就会被转成科学计数法的数字,并且会丢失最后的精度 全部转成了 0

原因:

凡数字超过11位数,Excel 表格就会用科学记数法显示。如果要输入超过11位的数,得把单元格设为文本形式或在输入数字前先输入一个英文单引号(’)。(单引号在英文输入法下输入)

也就是在传入data之前先遍历 添加符号

但是这样子在我们程序自动导出是不能生效的,需要我们再 双击单元格 它才会转成文本形式。

导出后的效果为 '11111111111111

网上的方案 ( PHPExcel 旧版的 )

    1. 在数据前后加上 \t' 差不多
    1. $objActSheet->setCellValueExplicit(‘A1’, ‘330602198804224688’, PHPExcel_Cell_DataType::TYPE_STRING);
    1. $objActSheet->setCellValue(‘A1’, ‘ ‘.’330602198804224688’);

PhpSpreadsheet 解决

当然是除了拼接字符串的方案了! 以下划重点 要考!

PhpSpreadsheet也有它的前驱者PHPExcel一样的方式,可以通过setCellValueExplicit指定方案。

所以将原来的程序改造成以下

    private $mustStringArray = [];

    /**
     * 将列强制设置成文本,避免长文本出现转科学计数法
     * @param array $array
     */
    function setMustString(Array $array)
    {
        $this->mustStringArray = $array;
    }

    /**
     * 导出表格
     * @todo 弹窗导出表格
     * @param $data array 数组 可选:filename文件名,data数据(二维数组),
     * @return bool
     * @throws \PhpOffice\PhpSpreadsheet\Exception
     * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
     */
    public function down($data)
    {
        if (empty($data)) return false;

        $filename = !empty($data['filename']) ? $data['filename'] . ".xlsx" : date('Y-m-d H:i:s') . ".xlsx";

        header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
        header('Content-Disposition: attachment;filename="' . $filename . '"');
        header('Cache-Control: max-age=0');

        $spreadsheet = new Spreadsheet();
        $sheet       = $spreadsheet->getActiveSheet();

        $lieCount = count($data['data'][0]);
        for($i=65;$i< (65 +$lieCount);$i++){
            $sheet->getColumnDimension(strtoupper(chr($i)))->setAutoSize(true);
        }

        // 以下代码基于fromArray改造
        // 开始列和开始行数,默认全部
        $startColumn = 'A';
        $startRow = '1';

        foreach ($data['data'] as $rowData) {
            $currentColumn = $startColumn;
            foreach ($rowData as $cellValue) {
                    if ($cellValue !== null) {
                        if (in_array($currentColumn, $this->mustStringArray)){
                            $sheet->getCell($currentColumn . $startRow)->setValueExplicit($cellValue,'s');
                        }else{
                            $sheet->getCell($currentColumn . $startRow)->setValue($cellValue);
                        }
                    }
                ++$currentColumn;
            }
            ++$startRow;
        }

        $writer = new Xlsx($spreadsheet);
        $writer->save('php://output');
    }

关键代码

$sheet->getCell($currentColumn . $startRow)->setValueExplicit($cellValue,'s');

第二个参数其实也是要传入一个类的静态变量,然后我追踪了它的代码,直接将值给写进去了~

有兴趣的同学可以查看这个类文件 PhpOffice\PhpSpreadsheet\Cell\DataType 里面还有其他几个类型的常量列表

// Data types
const TYPE_STRING2 = 'str';
const TYPE_STRING = 's';
const TYPE_FORMULA = 'f';
const TYPE_NUMERIC = 'n';
const TYPE_BOOL = 'b';
const TYPE_NULL = 'null';
const TYPE_INLINE = 'inlineStr';
const TYPE_ERROR = 'e';
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019.08.30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 原代码
  • 网上的方案 ( PHPExcel 旧版的 )
  • PhpSpreadsheet 解决
  • 关键代码
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档