写点什么

phpExcel:Excel 数据导入导出最佳实战

用户头像
devpoint
关注
发布于: 3 小时前
phpExcel:Excel数据导入导出最佳实战

Excel 是常用的数据整理统计的工具,通常在一些信息化平台中为了更好的实现无纸化或者上云,需要对办公数据进行迁移,从办公电脑迁移到平台上,又或者将平台上的数据下载下来给非开发人员使用,势必会涉及到数据的导入导出,而数据格式非 Excel 不可。


本文将结合实际的开发需求,总结开发过程中 Excel 的导入和导出,涉及的开发框架:


  • ThinkPHP 3.2

  • phpExcel


代码仓库:https://github.com/QuintionTang/crayon-thinkphp

导入

数据的导入,开始之前需要定义导入数据的格式,而且必须严格按照规定的格式程序才能正确的解析数据。通常的数据导入只是纯文本的数据,本文将导入 Excel 中带图片的数据,以最大可能覆盖导入需求。

模板

模板是数据导入的基础,下面定义一个简单的数据模板,如下格式:



有文本,有图片,导入数据首选需要读取到 Excel 文件,因此还需要涉及文件的上传,文件上传成功之后,先检测图片列,直接看代码:


    public function excel_import(){            $usedfor = empty($_GET['usedfor']) ? 'picture' : trim($_GET['usedfor']);            $used_for = $usedfor;            import('ORG.Net.UploadFile');            $upload = $this->_upload_init(new \Org\Net\UploadFile(),$usedfor);// 实例化上传类            $attach = array();            $attachment = array();            $attach["success"] = 0;            $info = "";            if(!$upload->upload()) { // 上传错误提示错误信息                $upload_error = $upload->getErrorMsg();                $attach["msg"] = $upload_error;            }else{ // 上传成功 获取上传文件信息                $info =  $upload->getUploadFileInfo();            }            // 上传成功后开始处理            if(is_array($info)){                $info = $info[0];                // PHPExcel 类引入                import("Org.Util.PHPExcel");                import("Org.Util.PHPExcel.Reader.Excel5");                import("Org.Util.PHPExcel.Reader.Excel2007");                                import("Org.Util.PHPExcel.IOFactory.php");
$filePath = $info["savepath"] . $info["savename"]; $input_file_type = \PHPExcel_IOFactory::identify($filePath);
// 开始读取Excel数据 $objExcel = new \PHPExcel();
$objReader = \PHPExcel_IOFactory::createReader($input_file_type); // 加载Excel文件 $objPHPExcel = $objReader->load($filePath); $objWorksheet = $objPHPExcel->getActiveSheet(); $data = $objWorksheet->toArray(); $attach_path = C('attach_path'); $subpath = date('YmdHm', time()); // Excel图片存储路径 $imageFileRealPath = $attach_path . "excel_img/".$subpath ."/" ; mkdirs($imageFileRealPath); $i = 0; $rebarRows = array(); // 下面开始处理图片 foreach ($objWorksheet->getDrawingCollection() as $img) { list($startColumn, $startRow) = \PHPExcel_Cell::coordinateFromString($img->getCoordinates()); //获取图片所在行和列 $imageFileName = uniqid(); try { switch($img->getExtension()) { case 'jpg': case 'jpeg': $imageFileName .= '.jpeg'; $source = imagecreatefromjpeg($img->getPath()); imagejpeg($source, $imageFileRealPath.$imageFileName,100); break; case 'gif': $imageFileName .= '.gif'; $source = imagecreatefromgif($img->getPath()); $width = imagesx($source); $height = imagesy($source); if (function_exists("imagecreatetruecolor")) { $newImg = imagecreatetruecolor($width, $height); /* --- 用以处理缩放png图透明背景变黑色问题开始 --- */ $color = imagecolorallocate($newImg,255,255,255); imagecolortransparent($newImg,$color); imagefill($newImg,0,0,$color); ImageCopyResampled($newImg, $source, 0, 0, 0, 0, $width, $height, $width, $height); } else { $newImg = imagecreate($width, $height); ImageCopyResized($newImg, $source, 0, 0, 0, 0, $width, $height, $width, $height); } imagejpeg($source, $imageFileRealPath.$imageFileName,100); break; case 'png': $imageFileName .= '.png'; $source = imagecreatefrompng($img->getPath()); $width = imagesx($source); $height = imagesy($source); if (function_exists("imagecreatetruecolor")) { $newImg = imagecreatetruecolor($width, $height); /* --- 用以处理缩放png图透明背景变黑色问题开始 --- */ $color = imagecolorallocate($newImg,255,255,255); imagecolortransparent($newImg,$color); imagefill($newImg,0,0,$color); ImageCopyResampled($newImg, $source, 0, 0, 0, 0, $width, $height, $width, $height); } else { $newImg = imagecreate($width, $height); ImageCopyResized($newImg, $source, 0, 0, 0, 0, $width, $height, $width, $height); } imagejpeg($newImg, $imageFileRealPath.$imageFileName,100); break; } $startColumn = $this->ABC2decimal($startColumn); $data[$startRow-1][$startColumn] = $imageFileRealPath . $imageFileName; } catch (\Throwable $th) { throw $th; } } $rowsData = array(); foreach ($data as $key => $rowData) { $serial = safty_value($rowData[0],0,'intval'); // 第一列 序号 $title = safty_value($rowData[1],'','trim'); // 第二列 名称 $logo_save_path = safty_value($rowData[2],'','trim'); // logo图形保存路径 $remark = safty_value($rowData[3],'','trim'); //备注
if ($serial >0 && $logo_save_path!=="" && $title!==""){
array_push($rowsData,array( "serial"=>$serial, "title"=>$title, "logo_path"=>$logo_save_path, "remark"=>$remark )); } } // 将导入的数据生成文件缓存 $this->update_excel_data($rowsData); $upload_result = array( "count" => count($rowsData), "success" => 1, "state"=>"SUCCESS" ); } else { $upload_result = array( "message" => "上传失败!", "success" => 0 ); } echo json_encode($upload_result); }
复制代码


下面是操作流程,如下:



选择文件上传并导入,导出成功之后提示并刷当前列表页面。



导出成功后的列表:



至此,数据导入已经完成了。


不足,导入的 Excel 文件在数据导入后没有处理,因此建议最好删除掉

导出

现在就来将上面的数据导出,导出 Excel 的格式定义,先需要定义表头:


$first_cells = array(    array("serial","序号"),    array("title","名称"),    array("logo","logo"),    array("remark","描述"));
复制代码


接下来就是按照表头的格式,封装数据,如下:


foreach ($excel_data as $key => $row_info) {    array_push($first_rows_data,array(        "serial"=>$row_info['serial'],        "title"=>$row_info['title'],        "logo"=>$row_info['logo_path'],        "remark"=>$row_info['remark']    ));}
复制代码


至此,数据封装已经完成,完整代码如下:


    public function export(){        $excel_detail = array(            "author"=>"devpoint",            "date"=>join(" ",$artifacts_full)        );        // 定义导出Excel表格信息        $sheets = array(); // Excel表信息,一维代表一个数据表        // 定义表头        $first_cells = array(            array("serial","序号"),            array("title","名称"),            array("logo","logo"),            array("remark","描述")        );        // 为表增加数据        $excel_data = get_file_cache("excel_data");        $first_rows_data = array();        // 数据与上面表头对应        foreach ($excel_data as $key => $row_info) {            array_push($first_rows_data,array(                "serial"=>$row_info['serial'],                "title"=>$row_info['title'],                "logo"=>$row_info['logo_path'],                "remark"=>$row_info['remark']            ));        }        array_push($sheets,array(            "title"=>"前端项目流行框架",            "cells"=>$first_cells,            "rows"=>$first_rows_data        ));        $xlsName  = "Excel数据导出";        $xlsName = $xlsName  . date('YmdHis');        $this->exportExcel($xlsName,$sheets,$excel_detail);    }
复制代码


函数exportExcel将数据写入到 Excel,并定义表格的样式,完整代码如下:


    protected function exportExcel($expTitle,$xlsSheets,$detail){        import("Org.Util.PHPExcel");        import("Org.Util.PHPExcel.Writer.Excel5");        import("Org.Util.PHPExcel.IOFactory.php");        $fileName = $expTitle;        $objPHPExcel = new \PHPExcel();        $objPHPExcel->getDefaultStyle()->getFont()->setName('宋体');        // Excel列名称    $cellName = array('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','AA','AB','AC','AD','AE','AF','AG','AH','AI','AJ','AK','AL','AM','AN','AO','AP','AQ','AR','AS','AT','AU','AV','AW','AX','AY','AZ');        foreach ($xlsSheets as $index => $sheet_info) {            $sheet_title = $sheet_info['title'];            if ($index>0){                // Excel默认已经建好的数据表,超过一张需要执行这里创建一个工作表                $newSheet = new \PHPExcel_Worksheet($objPHPExcel, $sheet_title); //创建一个工作表                $objPHPExcel->addSheet($newSheet);            } else {                $objPHPExcel->getActiveSheet($index)->setTitle($sheet_title);            }            $expCellName = $sheet_info['cells'];            $expTableData = $sheet_info['rows'];            $cellNum = count($expCellName);            $dataNum = count($expTableData);            $cellmerget = "";            $cellWidths = array();            $sheet_head_title = $sheet_title;            // 下面需要为每个工作表定义宽度            switch ($index) {                case 1: // 每张表的索引从 0 开始计算                    $cellmerget = 'A1:E1';                    $cellWidths=array(16,16,16,28,16);                    break;                default:                    $cellmerget = 'A1:D1';                    $sheet_head_title = $sheet_title ;                    $cellWidths=array(16,16,16,36);                    break;            }            $activeSheet = $objPHPExcel->setActiveSheetIndex($index);
for($i=0;$i<$cellNum;$i++){ $currentCellName = $cellName[$i]; $activeSheet->getRowDimension(1)->setRowHeight(36); $activeSheet->getColumnDimension($currentCellName)->setWidth($cellWidths[$i]); $activeSheet->getStyle($currentCellName.'1')->getFont()->setSize(12)->setBold(true); $activeSheet->getStyle($currentCellName.'1')->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER); }
$activeSheet->mergeCells($cellmerget);//合并单元格 $activeSheet->setCellValue('A1', $sheet_head_title); $activeSheet->getStyle('A1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER); $activeSheet->getStyle('A1')->getFont()->setSize(20); $activeSheet->getRowDimension(1)->setRowHeight(50); $styleThinBlackBorderOutline = array( 'borders' => array ( 'outline' => array ( 'style' => \PHPExcel_Style_Border::BORDER_MEDIUM, //设置border样式 'color' => array ('argb' => 'FF9b9b9b'), //设置border颜色 ), ), ); for($i=0;$i<$cellNum;$i++){ $currentCellName = $cellName[$i]; $activeSheet->getRowDimension(2)->setRowHeight(36); $activeSheet->getColumnDimension($currentCellName)->setWidth($cellWidths[$i]); $activeSheet->setCellValue($currentCellName.'2', $expCellName[$i][1]); $activeSheet->getStyle($currentCellName.'2')->getFill()->setFillType(\PHPExcel_Style_Fill::FILL_SOLID); $activeSheet->getStyle($currentCellName.'2')->getFill()->getStartColor()->setARGB('FFc6efcd'); $activeSheet->getStyle($currentCellName.'2')->getFont()->setSize(12)->setBold(true); $activeSheet->getStyle($currentCellName.'2')->applyFromArray($styleThinBlackBorderOutline); $activeSheet->getStyle($currentCellName.'2')->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER); $activeSheet->freezePane($currentCellName.'3'); // 锁定表头,3 意味着锁定第3行上面的 } switch ($index) { case 1:
break; default: $start_row_index = 3; // 数据开始索引行 for($i1=0;$i1<$dataNum;$i1++){ $objPHPExcel->getActiveSheet()->getRowDimension($i1+3)->setRowHeight(60); for($j1=0;$j1<$cellNum;$j1++){ if ($j1===2){ $logo_path = $expTableData[$i1][$expCellName[$j1][0]]; if ($logo_path!=="" && file_exists($logo_path)){ $objDrawing = new \PHPExcel_Worksheet_Drawing(); $objDrawing->setPath($logo_path); $objDrawing->setHeight(60); $objDrawing->setWidth(60); $objDrawing->setOffsetX(5); $objDrawing->setOffsetY(5); $objDrawing->setCoordinates($cellName[$j1].($i1+$start_row_index)); $objDrawing->setWorksheet($objPHPExcel->getActiveSheet()); } else { $objPHPExcel->getActiveSheet()->setCellValue($cellName[$j1].($i1+$start_row_index), ""); $objPHPExcel->getActiveSheet()->getStyle($cellName[$j1].($i1+$start_row_index))->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER); $objPHPExcel->getActiveSheet()->getStyle($cellName[$j1].($i1+$start_row_index))->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT); $objPHPExcel->getActiveSheet()->getStyle($cellName[$j1].($i1+$start_row_index))->getAlignment()->setWrapText(true); } } else { $objPHPExcel->getActiveSheet()->setCellValue($cellName[$j1].($i1+$start_row_index), $expTableData[$i1][$expCellName[$j1][0]]); $objPHPExcel->getActiveSheet()->getStyle($cellName[$j1].($i1+$start_row_index))->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER); $objPHPExcel->getActiveSheet()->getStyle($cellName[$j1].($i1+$start_row_index))->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT); $objPHPExcel->getActiveSheet()->getStyle($cellName[$j1].($i1+$start_row_index))->getAlignment()->setWrapText(true); } } } break; } } $objPHPExcel->setActiveSheetIndex(0);
header('pragma:public'); header('Content-type:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8;name="'.$fileName.'.xlsx"'); header("Content-Disposition:attachment;filename=$fileName.xlsx"); // attachment新窗口打印inline本窗口打印 $objWriter = \PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007'); $objWriter->save('php://output'); exit; }
复制代码


导出后的格式如下:



发布于: 3 小时前阅读数: 9
用户头像

devpoint

关注

细节的追求者 2011.11.12 加入

专注前端开发,用技术创造价值!

评论

发布
暂无评论
phpExcel:Excel数据导入导出最佳实战