首頁 >後端開發 >PHP問題 >如何使用PhpSpreadsheet導入導出Excel

如何使用PhpSpreadsheet導入導出Excel

醉折花枝作酒筹
醉折花枝作酒筹轉載
2021-05-25 17:10:153167瀏覽

本篇文章跟大家介紹一下使用PhpSpreadsheet匯入匯出Excel的方法。有一定的參考價值,有需要的朋友可以參考一下,希望對大家有幫助。

如何使用PhpSpreadsheet導入導出Excel

PHP對Excel導入&匯出操作

最近公司要做報表功能,各種財務報表、薪資報表、考勤報表等,複雜程度讓人頭大,於是特地封裝適用各大場景的導入&導出操作,希望各界大神支出不足之處,以便小弟繼續完善。

phpspreadsheet 引入

由於PHPExcel早就停止更新維護,所以適用phpspreadsheet。不知道如何透過composer拉取專案包的同學,可以查看Composer學習一文。引入方法:

composer require phpoffice/phpspreadsheet

引入命名空間

由於本人專案中需要居中、背景、單元格格式等各種操作,所以引入較多,大家使用的時候,可以根據自己實際需要引入。

use PhpOffice\PhpSpreadsheet\Reader\Xlsx;use PhpOffice\PhpSpreadsheet\Reader\Xls;use PhpOffice\PhpSpreadsheet\IOFactory;use PhpOffice\PhpSpreadsheet\Cell\Coordinate;use PhpOffice\PhpSpreadsheet\Spreadsheet;use PhpOffice\PhpSpreadsheet\Worksheet\PageSetup;use PhpOffice\PhpSpreadsheet\Cell\DataType;use PhpOffice\PhpSpreadsheet\Style\Fill;use PhpOffice\PhpSpreadsheet\Style\Color;use PhpOffice\PhpSpreadsheet\Style\Alignment;use PhpOffice\PhpSpreadsheet\Style\Border;use PhpOffice\PhpSpreadsheet\Style\NumberFormat;

Excel導入操作(importExcel)

除了單純的處理Excel資料外,還可以將Excel中的合併項目、公式項目、儲存格格式提取,提取後可根據業務需求做對應處理後儲存起來,以便後續的各種操作。

/**
 * 使用PHPEXECL导入
 *
 * @param string $file      文件地址
 * @param int    $sheet     工作表sheet(传0则获取第一个sheet)
 * @param int    $columnCnt 列数(传0则自动获取最大列)
 * @param array  $options   操作选项
 *                          array mergeCells 合并单元格数组
 *                          array formula    公式数组
 *                          array format     单元格格式数组
 *
 * @return array
 * @throws Exception
 */function importExecl(string $file = '', int $sheet = 0, int $columnCnt = 0, &$options = []){
    try {
        /* 转码 */
        $file = iconv("utf-8", "gb2312", $file);

        if (empty($file) OR !file_exists($file)) {
            throw new \Exception('文件不存在!');
        }

        /** @var Xlsx $objRead */
        $objRead = IOFactory::createReader('Xlsx');

        if (!$objRead->canRead($file)) {
            /** @var Xls $objRead */
            $objRead = IOFactory::createReader('Xls');

            if (!$objRead->canRead($file)) {
                throw new \Exception('只支持导入Excel文件!');
            }
        }

        /* 如果不需要获取特殊操作,则只读内容,可以大幅度提升读取Excel效率 */
        empty($options) && $objRead->setReadDataOnly(true);
        /* 建立excel对象 */
        $obj = $objRead->load($file);
        /* 获取指定的sheet表 */
        $currSheet = $obj->getSheet($sheet);

        if (isset($options['mergeCells'])) {
            /* 读取合并行列 */
            $options['mergeCells'] = $currSheet->getMergeCells();
        }

        if (0 == $columnCnt) {
            /* 取得最大的列号 */
            $columnH = $currSheet->getHighestColumn();
            /* 兼容原逻辑,循环时使用的是小于等于 */
            $columnCnt = Coordinate::columnIndexFromString($columnH);
        }

        /* 获取总行数 */
        $rowCnt = $currSheet->getHighestRow();
        $data   = [];

        /* 读取内容 */
        for ($_row = 1; $_row <= $rowCnt; $_row++) {
            $isNull = true;

            for ($_column = 1; $_column <= $columnCnt; $_column++) {
                $cellName = Coordinate::stringFromColumnIndex($_column);
                $cellId   = $cellName . $_row;
                $cell     = $currSheet->getCell($cellId);

                if (isset($options[&#39;format&#39;])) {
                    /* 获取格式 */
                    $format = $cell->getStyle()->getNumberFormat()->getFormatCode();
                    /* 记录格式 */
                    $options[&#39;format&#39;][$_row][$cellName] = $format;
                }

                if (isset($options[&#39;formula&#39;])) {
                    /* 获取公式,公式均为=号开头数据 */
                    $formula = $currSheet->getCell($cellId)->getValue();

                    if (0 === strpos($formula, &#39;=&#39;)) {
                        $options[&#39;formula&#39;][$cellName . $_row] = $formula;
                    }
                }

                if (isset($format) && &#39;m/d/yyyy&#39; == $format) {
                    /* 日期格式翻转处理 */
                    $cell->getStyle()->getNumberFormat()->setFormatCode(&#39;yyyy/mm/dd&#39;);
                }

                $data[$_row][$cellName] = trim($currSheet->getCell($cellId)->getFormattedValue());

                if (!empty($data[$_row][$cellName])) {
                    $isNull = false;
                }
            }

            /* 判断是否整行数据为空,是的话删除该行数据 */
            if ($isNull) {
                unset($data[$_row]);
            }
        }

        return $data;
    } catch (\Exception $e) {
        throw $e;
    }}

將資料處理好後,可以透過額外配置,將匯出的Excel做各種不同的配置,例如列印樣式、鎖定行、背景色、寬度等。

Excel匯出操作(exportExcel)

/**
 * Excel导出,TODO 可继续优化
 *
 * @param array  $datas      导出数据,格式[&#39;A1&#39; => &#39;XXXX公司报表&#39;, &#39;B1&#39; => &#39;序号&#39;]
 * @param string $fileName   导出文件名称
 * @param array  $options    操作选项,例如:
 *                           bool   print       设置打印格式
 *                           string freezePane  锁定行数,例如表头为第一行,则锁定表头输入A2
 *                           array  setARGB     设置背景色,例如[&#39;A1&#39;, &#39;C1&#39;]
 *                           array  setWidth    设置宽度,例如[&#39;A&#39; => 30, &#39;C&#39; => 20]
 *                           bool   setBorder   设置单元格边框
 *                           array  mergeCells  设置合并单元格,例如[&#39;A1:J1&#39; => &#39;A1:J1&#39;]
 *                           array  formula     设置公式,例如[&#39;F2&#39; => &#39;=IF(D2>0,E42/D2,0)&#39;]
 *                           array  format      设置格式,整列设置,例如[&#39;A&#39; => &#39;General&#39;]
 *                           array  alignCenter 设置居中样式,例如[&#39;A1&#39;, &#39;A2&#39;]
 *                           array  bold        设置加粗样式,例如[&#39;A1&#39;, &#39;A2&#39;]
 *                           string savePath    保存路径,设置后则文件保存到服务器,不通过浏览器下载
 */function exportExcel(array $datas, string $fileName = &#39;&#39;, array $options = []): bool{
    try {
        if (empty($datas)) {
            return false;
        }

        set_time_limit(0);
        /** @var Spreadsheet $objSpreadsheet */
        $objSpreadsheet = app(Spreadsheet::class);
        /* 设置默认文字居左,上下居中 */
        $styleArray = [
            &#39;alignment&#39; => [
                &#39;horizontal&#39; => Alignment::HORIZONTAL_LEFT,
                &#39;vertical&#39;   => Alignment::VERTICAL_CENTER,
            ],
        ];
        $objSpreadsheet->getDefaultStyle()->applyFromArray($styleArray);
        /* 设置Excel Sheet */
        $activeSheet = $objSpreadsheet->setActiveSheetIndex(0);

        /* 打印设置 */
        if (isset($options[&#39;print&#39;]) && $options[&#39;print&#39;]) {
            /* 设置打印为A4效果 */
            $activeSheet->getPageSetup()->setPaperSize(PageSetup:: PAPERSIZE_A4);
            /* 设置打印时边距 */
            $pValue = 1 / 2.54;
            $activeSheet->getPageMargins()->setTop($pValue / 2);
            $activeSheet->getPageMargins()->setBottom($pValue * 2);
            $activeSheet->getPageMargins()->setLeft($pValue / 2);
            $activeSheet->getPageMargins()->setRight($pValue / 2);
        }

        /* 行数据处理 */
        foreach ($datas as $sKey => $sItem) {
            /* 默认文本格式 */
            $pDataType = DataType::TYPE_STRING;

            /* 设置单元格格式 */
            if (isset($options[&#39;format&#39;]) && !empty($options[&#39;format&#39;])) {
                $colRow = Coordinate::coordinateFromString($sKey);

                /* 存在该列格式并且有特殊格式 */
                if (isset($options[&#39;format&#39;][$colRow[0]]) &&
                    NumberFormat::FORMAT_GENERAL != $options[&#39;format&#39;][$colRow[0]]) {
                    $activeSheet->getStyle($sKey)->getNumberFormat()
                        ->setFormatCode($options[&#39;format&#39;][$colRow[0]]);

                    if (false !== strpos($options[&#39;format&#39;][$colRow[0]], &#39;0.00&#39;) &&
                        is_numeric(str_replace([&#39;¥&#39;, &#39;,&#39;], &#39;&#39;, $sItem))) {
                        /* 数字格式转换为数字单元格 */
                        $pDataType = DataType::TYPE_NUMERIC;
                        $sItem     = str_replace([&#39;¥&#39;, &#39;,&#39;], &#39;&#39;, $sItem);
                    }
                } elseif (is_int($sItem)) {
                    $pDataType = DataType::TYPE_NUMERIC;
                }
            }

            $activeSheet->setCellValueExplicit($sKey, $sItem, $pDataType);

            /* 存在:形式的合并行列,列入A1:B2,则对应合并 */
            if (false !== strstr($sKey, ":")) {
                $options[&#39;mergeCells&#39;][$sKey] = $sKey;
            }
        }

        unset($datas);

        /* 设置锁定行 */
        if (isset($options[&#39;freezePane&#39;]) && !empty($options[&#39;freezePane&#39;])) {
            $activeSheet->freezePane($options[&#39;freezePane&#39;]);
            unset($options[&#39;freezePane&#39;]);
        }

        /* 设置宽度 */
        if (isset($options[&#39;setWidth&#39;]) && !empty($options[&#39;setWidth&#39;])) {
            foreach ($options[&#39;setWidth&#39;] as $swKey => $swItem) {
                $activeSheet->getColumnDimension($swKey)->setWidth($swItem);
            }

            unset($options[&#39;setWidth&#39;]);
        }

        /* 设置背景色 */
        if (isset($options[&#39;setARGB&#39;]) && !empty($options[&#39;setARGB&#39;])) {
            foreach ($options[&#39;setARGB&#39;] as $sItem) {
                $activeSheet->getStyle($sItem)
                    ->getFill()->setFillType(Fill::FILL_SOLID)
                    ->getStartColor()->setARGB(Color::COLOR_YELLOW);
            }

            unset($options[&#39;setARGB&#39;]);
        }

        /* 设置公式 */
        if (isset($options[&#39;formula&#39;]) && !empty($options[&#39;formula&#39;])) {
            foreach ($options[&#39;formula&#39;] as $fKey => $fItem) {
                $activeSheet->setCellValue($fKey, $fItem);
            }

            unset($options[&#39;formula&#39;]);
        }

        /* 合并行列处理 */
        if (isset($options[&#39;mergeCells&#39;]) && !empty($options[&#39;mergeCells&#39;])) {
            $activeSheet->setMergeCells($options[&#39;mergeCells&#39;]);
            unset($options[&#39;mergeCells&#39;]);
        }

        /* 设置居中 */
        if (isset($options[&#39;alignCenter&#39;]) && !empty($options[&#39;alignCenter&#39;])) {
            $styleArray = [
                &#39;alignment&#39; => [
                    &#39;horizontal&#39; => Alignment::HORIZONTAL_CENTER,
                    &#39;vertical&#39;   => Alignment::VERTICAL_CENTER,
                ],
            ];

            foreach ($options[&#39;alignCenter&#39;] as $acItem) {
                $activeSheet->getStyle($acItem)->applyFromArray($styleArray);
            }

            unset($options[&#39;alignCenter&#39;]);
        }

        /* 设置加粗 */
        if (isset($options[&#39;bold&#39;]) && !empty($options[&#39;bold&#39;])) {
            foreach ($options[&#39;bold&#39;] as $bItem) {
                $activeSheet->getStyle($bItem)->getFont()->setBold(true);
            }

            unset($options[&#39;bold&#39;]);
        }

        /* 设置单元格边框,整个表格设置即可,必须在数据填充后才可以获取到最大行列 */
        if (isset($options[&#39;setBorder&#39;]) && $options[&#39;setBorder&#39;]) {
            $border    = [
                &#39;borders&#39; => [
                    &#39;allBorders&#39; => [
                        &#39;borderStyle&#39; => Border::BORDER_THIN, // 设置border样式
                        &#39;color&#39;       => [&#39;argb&#39; => &#39;FF000000&#39;], // 设置border颜色
                    ],
                ],
            ];
            $setBorder = &#39;A1:&#39; . $activeSheet->getHighestColumn() . $activeSheet->getHighestRow();
            $activeSheet->getStyle($setBorder)->applyFromArray($border);
            unset($options[&#39;setBorder&#39;]);
        }

        $fileName = !empty($fileName) ? $fileName : (date(&#39;YmdHis&#39;) . &#39;.xlsx&#39;);

        if (!isset($options[&#39;savePath&#39;])) {
            /* 直接导出Excel,无需保存到本地,输出07Excel文件 */
            header(&#39;Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet&#39;);
            header(
                "Content-Disposition:attachment;filename=" . iconv(
                    "utf-8", "GB2312//TRANSLIT", $fileName
                )
            );
            header(&#39;Cache-Control: max-age=0&#39;);//禁止缓存
            $savePath = &#39;php://output&#39;;
        } else {
            $savePath = $options[&#39;savePath&#39;];
        }

        ob_clean();
        ob_start();
        $objWriter = IOFactory::createWriter($objSpreadsheet, &#39;Xlsx&#39;);
        $objWriter->save($savePath);
        /* 释放内存 */
        $objSpreadsheet->disconnectWorksheets();
        unset($objSpreadsheet);
        ob_end_flush();

        return true;
    } catch (Exception $e) {
        return false;
    }}

推薦學習:php影片教學

#

以上是如何使用PhpSpreadsheet導入導出Excel的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:csdn.net。如有侵權,請聯絡admin@php.cn刪除