帶圖片的Excel表格導入/Excel中png圖片的獲取

需求:Excel表格是學校的很多信息,包括基本信息,專業信息等,有多個sheet;需以此表格爲依據導入到數據庫生成一個學校;或者更新一個學校的信息;

難點: Excel表格中 學校的logo 是圖片;是jpg,png,等格式;png格式是 如何正確獲取到這張圖片。

使用的第三方處理excel表格的庫爲:

\PhpOffice\PhpSpreadsheet

代碼:

public static function importExcelWithImage($filePath, $startRow = 1)
    {
        $reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx();
        if (!$reader->canRead($filePath))
        {
            $reader = new \PhpOffice\PhpSpreadsheet\Reader\Xls();
            // setReadDataOnly Set read data only 只讀單元格的數據,不格式化 e.g. 讀時間會變成一個數據等
            if (!$reader->canRead($filePath))
            {
                throw new NotFoundHttpException('不能讀取Excel');
            }
        }

        $spreadsheet = $reader->load($filePath);
        $sheetCount = $spreadsheet->getSheetCount();// 獲取sheet的數量

        // 獲取所有的sheet表格數據
        $images = [];
        $excleDatas = [];
        $emptyRowNum = 0;
        for ($i = 0; $i < $sheetCount; $i++)
        {
            $currentSheet = $spreadsheet->getSheet($i); // 讀取excel文件中的第一個工作表
            $allColumn = $currentSheet->getHighestColumn(); // 取得最大的列號
            $allColumn = Coordinate::columnIndexFromString($allColumn); // 由列名轉爲列數('AB'->28)
            $allRow = $currentSheet->getHighestRow(); // 取得一共有多少行

            $arr = [];
            for ($currentRow = $startRow; $currentRow <= $allRow; $currentRow++)
            {
                // 從第1列開始輸出
                for ($currentColumn = 1; $currentColumn <= $allColumn; $currentColumn++)
                {
                    $cellObj = $currentSheet->getCellByColumnAndRow($currentColumn, $currentRow);
                    $type = $cellObj->getDataType();
                    $val = $cellObj->getValue();


                    $arr[$currentRow][] = trim($val);
                }

                // $arr[$currentRow] = array_filter($arr[$currentRow]);
                // 統計連續空行
                if (empty($arr[$currentRow]) && $emptyRowNum <= 50)
                {
                    $emptyRowNum++ ;
                }
                else
                {
                    $emptyRowNum = 0;
                }
                // 連續50行數據爲空,不再讀取後面行的數據,防止讀滿內存
                if ($emptyRowNum > 50)
                {
                    break;
                }
            }
            //開始處理圖片

            foreach ($currentSheet->getDrawingCollection() as $drawing) {
                if ($drawing instanceof MemoryDrawing) {
                    switch ($drawing->getMimeType()) {
                        case MemoryDrawing::MIMETYPE_PNG :
                            $extension = 'png';
                            break;
                        case MemoryDrawing::MIMETYPE_GIF :
                            $extension = 'gif';
                            break;
                        case MemoryDrawing::MIMETYPE_JPEG :
                            $extension = 'jpg';
                            break;
                    }


                    $gdRes = $drawing->getImageResource();
                    ob_start();
                    if($extension == 'png'){
                        //設置透明
                        imagesavealpha($gdRes,true);
                    }

                    call_user_func(
                        $drawing->getRenderingFunction(),
                        $gdRes //$drawing->getImageResource()
                    );

                    $imageContents = ob_get_contents();
                    ob_end_clean();

                } else {
                    $zipReader = fopen($drawing->getPath(), 'r');
                    $imageContents = '';
                    while (!feof($zipReader)) {
                        $imageContents .= fread($zipReader, 1024);
                    }
                    fclose($zipReader);
                    $extension = $drawing->getExtension();
                }

                //列從 0開始,行從1開始 和數據保持一致
                list($imageStartColumn, $imageStartRow) = Coordinate::coordinateFromString($drawing->getCoordinates());
                $imageStartColumn = Coordinate::columnIndexFromString($imageStartColumn) -1 ;

                $folder_name = sys_get_temp_dir();

                $myFileName = time() . '_' . mt_rand(100000, 999999) . '.' . $extension;

                $images[] = $arr[$imageStartRow][$imageStartColumn] = $folder_name.'/'.$myFileName;
                file_put_contents("{$folder_name}/{$myFileName}", $imageContents);

            }



            $excleDatas[$i] = $arr; // 多個sheet的數組的集合
        }

        return array('data' => $excleDatas, 'images' => $images);

    }

注意的地方:

$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xls();
// setReadDataOnly Set read data only 只讀單元格的數據,不格式化 e.g. 讀時間會變成一個數據等

不要對 $read 進行 setReadDataOnly的設置爲true 這樣做會使下邊無法獲取到圖片資源,也會對時間等內容產生影響;

難點的解決代碼:

$gdRes = $drawing->getImageResource();
ob_start();
if($extension == 'png'){
    //設置透明
    imagesavealpha($gdRes,true);
}

解決的思路:

1. 查看PhpSpreadsheet 的文檔查找對 png格式特殊處理的函數;結果沒有找到!

2. 斷點調試代碼打印 $gdRes 對象;結果發現它就是 gd庫的圖片資源類型;這就說明可以使用原始的gd庫的方法 imagesavealpha()來設置透明瞭

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章