iT邦幫忙

0

【PHP】請幫忙介紹一些實用的PhpSpreadsheet範例或者教材

  • 分享至 

  • xImage

PS~感謝各位的協助,目前測試出錯誤畫面,發現正式環境是5.6版本,所以才會一直無法正常顯示,現在我再找資料研究PHPExcel看看。


因為本人PHP方面熟練度不是很高,所以對於一些套件並不是很熟悉。

最近公司終於答應了可以使用套件的部分來開發匯入EXCEL到MySQL的功能,我查了資料發現現在好像用PhpSpreadsheet的居多,但是找不到太多資料。

我試驗了一些範例都沒有辦法正常執行,所以想請問各位大神,有沒有什麼文獻、範例可以參考的?

我想先測試將EXCEL檔案匯入之後,先在網頁上列印出來,然後在研究怎樣把資料寫入資料庫,差不多是這個方向。

還請大神若是有資源的話,可以指教我一下,非常感激!

PS~有沒有一個可以直接讀取EXCEL檔案(XLSX),然後直接使用PHP列印出來的範例呢?

2021/09/13 10:15追加
測試範例
出處:
https://github.com/PHPOffice/PhpSpreadsheet/blob/master/samples/Reader/03_Simple_file_reader_using_the_IOFactory_to_return_a_reader.php

<?

require 'vendor/autoload.php';

use PhpOffice\PhpSpreadsheet\IOFactory;
//use PhpOffice\PhpSpreadsheet\Spreadsheet;
//use PhpOffice\PhpSpreadsheet\Writer\Xlsx;

$inputFileType = 'Xls';
$inputFileName = 'example1.xls';

$helper->log('Loading file ' . pathinfo($inputFileName, PATHINFO_BASENAME) . ' using IOFactory with a defined reader type of ' . $inputFileType);
$reader = IOFactory::createReader($inputFileType);
$spreadsheet = $reader->load($inputFileName);

$sheetData = $spreadsheet->getActiveSheet()->toArray(null, true, true, true);
var_dump($sheetData);

?>

執行時沒有看到有列印出資料

看更多先前的討論...收起先前的討論...
淺水員 iT邦大師 6 級 ‧ 2021-09-11 23:56:08 檢舉
我是直接看官網
https://phpspreadsheet.readthedocs.io/en/latest/
先確認 Getting started 的範例能跑後,Reading Files 的主題連結如下
https://phpspreadsheet.readthedocs.io/en/latest/topics/reading-files/
淺水員 iT邦大師 6 級 ‧ 2021-09-11 23:57:39 檢舉
「試驗了一些範例都沒有辦法正常執行」
可以說說看試了什麼,然後顯示甚麼錯誤
MySQL 是可以匯入csv 的. 你要不要再思考一下,整件事的方法.
alan0219 iT邦新手 5 級 ‧ 2021-09-12 11:43:13 檢舉
公司要的是能匯入XLSX檔案,之前我也有考慮用CSV,但就得讓操作人員多一個轉檔的步驟了
alan0219 iT邦新手 5 級 ‧ 2021-09-12 11:47:14 檢舉
TO 淺水員:就是我找的範例基本上都卡在沒有辦法成功地按照範例秀出資料或者是有的乾脆連資料庫連線都會失敗(我檢查了參數都沒問題)
淺水員 iT邦大師 6 級 ‧ 2021-09-12 16:49:02 檢舉
可以說說看試了什麼,然後顯示甚麼錯誤
mayyola iT邦研究生 1 級 ‧ 2021-09-13 08:56:42 檢舉
https://github.com/Maatwebsite/Laravel-Excel
youtube教學
https://www.youtube.com/watch?v=7iHmrxfy9dY
alan0219 iT邦新手 5 級 ‧ 2021-09-13 09:37:28 檢舉
已確認確認 Getting started 的範例能跑
alan0219 iT邦新手 5 級 ‧ 2021-09-13 09:47:39 檢舉
謝謝 mayyola,但是並沒有要使用Laravel框架
alan0219 iT邦新手 5 級 ‧ 2021-09-13 10:14:14 檢舉
這個範例執行的時候沒有SHOW出結果

03_Simple_file_reader_using_the_IOFactory_to_return_a_reader.php
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
0
小魚
iT邦大師 1 級 ‧ 2021-09-12 10:16:14

應該是可以用才對,
哪邊出了問題呢?

看更多先前的回應...收起先前的回應...
alan0219 iT邦新手 5 級 ‧ 2021-09-12 11:45:57 檢舉

我也不太清楚,我就用composer下載了套件,然後就找了一些範例來測試,但是執行時都沒有出現甚麼反應,頂多Show出了抓到多少列等等,但是卻沒有輸出資料

小魚 iT邦大師 1 級 ‧ 2021-09-13 00:25:21 檢舉

所以到底是寫了甚麼? 出現了甚麼?

alan0219 iT邦新手 5 級 ‧ 2021-09-13 17:25:07 檢舉

現在的程式碼(然後沒有列印出東西)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>PhpSpreadsheet</title>
</head>
<body>
    
</body>

測試 EXCEL:<br />

<?
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);


require 'vendor/autoload.php';

use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
use PhpOffice\PhpSpreadsheet\Reader\Xls;

use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\IOFactory;




echo importExecl('test.xlsx');

/**
 * 使用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['format'])) {
                    /* 獲取格式 */
                    $format = $cell->getStyle()->getNumberFormat()->getFormatCode();
                    /* 記錄格式 */
                    $options['format'][$_row][$cellName] = $format;
                }

                if (isset($options['formula'])) {
                    /* 獲取公式,公式均為=號開頭資料 */
                    $formula = $currSheet->getCell($cellId)->getValue();

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

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

                $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;
    }
}
?>
</html>
小魚 iT邦大師 1 級 ‧ 2021-09-13 20:06:38 檢舉

我記得,
欄位讀出來應該會是類似'A', 'B', 'C'之類的,
要先經過轉換,
或是用.來連接字串,
接出來可能是類似'A1'之類的,
這篇 這樣

或是類似這樣的方式

$value = $worksheet->getCellByColumnAndRow(1, $row)->getValue();

但是要先把欄位名稱轉成數字

淺水員 iT邦大師 6 級 ‧ 2021-09-13 22:19:06 檢舉

Coordinate 應該會出錯吧
少了 use PhpOffice\PhpSpreadsheet\Cell\Coordinate;

另外 $file = iconv("utf-8", "gb2312", $file); 不確定有沒有必要,我在 windows10 電腦檔名直接給 utf-8 的中文是沒問題的。轉碼反而會找不到檔案。

最後是 importExecl 回傳的是 array,沒辦法直接 echo

alan0219 iT邦新手 5 級 ‧ 2021-09-15 13:58:56 檢舉

現在修正程式碼如下,還是無法執行

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>PhpSpreadsheet</title>
</head>
<body>
    
</body>

測試 EXCEL:<br />

<?
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);


require 'vendor/autoload.php';

use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
use PhpOffice\PhpSpreadsheet\Reader\Xls;

use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\IOFactory;

use PhpOffice\PhpSpreadsheet\Cell\Coordinate;


/**
 * 使用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['format'])) {
                    /* 獲取格式 */
                    $format = $cell->getStyle()->getNumberFormat()->getFormatCode();
                    /* 記錄格式 */
                    $options['format'][$_row][$cellName] = $format;
                }

                if (isset($options['formula'])) {
                    /* 獲取公式,公式均為=號開頭資料 */
                    $formula = $currSheet->getCell($cellId)->getValue();

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

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

                $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;
    }
}
?>

<?
var_dump(importExecl('test.xlsx'));
?>

</html>
2

如果你不會用就直接說。
要不然就先PO你寫的範例或是用的範例是什麼。

有錯誤就直接列出來。

不要讓大家練習通靈能力。

alan0219 iT邦新手 5 級 ‧ 2021-09-13 09:49:28 檢舉

的確是不會用~所以我都是找網上的範例直接貼上執行,怎麼貼範例我不會....我研究一下

0
淺水員
iT邦大師 6 級 ‧ 2021-09-13 16:20:08

前面加上這三行,讓 PHP 顯示所有錯誤,再依照錯誤訊息除錯

<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

//其他程式碼(略)

雖然肉眼去看,那個 $helper 因為不知道哪來的,就會出問題了。
但感覺目前先學會從錯誤訊息中去找答案會比較重要。

看更多先前的回應...收起先前的回應...
alan0219 iT邦新手 5 級 ‧ 2021-09-13 17:22:33 檢舉

加上了~還是沒有訊息出現@@

淺水員 iT邦大師 6 級 ‧ 2021-09-14 17:18:24 檢舉

因為你程式碼貼在小魚那邊
我就在那邊回應了
現在解決了嗎?

alan0219 iT邦新手 5 級 ‧ 2021-09-15 13:59:36 檢舉

我回在小魚那邊了,按照您說的修改過後,還是無法順利執行輸出資料@@

alan0219 iT邦新手 5 級 ‧ 2021-09-15 16:14:30 檢舉

To 潛水員:感謝您的協助,目前測試出錯誤畫面,發現正式環境是5.6版本,所以才會一直無法正常顯示,現在我在找資料研究PHPExcel看看。

淺水員 iT邦大師 6 級 ‧ 2021-09-15 16:19:51 檢舉

測試出錯誤畫面

好喔,有錯誤訊息就比較好找原因了

我要發表回答

立即登入回答