ThinkPHP使用PHPExcel导入导出数据处理
本次以ThinkPHP3.2为例(实际使用XCRM系统)。
一、导入,更新数据库(数据表, 文件真实路径)
public function xlsin($db, $file){
//导入PHPExcel类库,因为PHPExcel没有用命名空间,只能inport导入 import("Org.Util.PHPExcel"); //要导入的xls文件,位于根目录下的Public文件夹 $filename = $file ? $file : "./Public/1.xls"; //创建PHPExcel对象,注意,不能少了\ $PHPExcel = new \PHPExcel(); //如果excel文件后缀名为.xls,导入这个类 import("Org.Util.PHPExcel.Reader.Excel5"); //如果excel文件后缀名为.xlsx,导入这下类 //import("Org.Util.PHPExcel.Reader.Excel2007"); //$PHPReader=new \PHPExcel_Reader_Excel2007(); $PHPReader = new \PHPExcel_Reader_Excel5(); //载入文件 $PHPExcel = $PHPReader->load($filename); //获取表中的第一个工作表,如果要获取第二个,把0改为1,依次类推 $currentSheet = $PHPExcel->getSheet(0); //获取总列数 $allColumn = $currentSheet->getHighestColumn(); //获取总行数 $allRow = $currentSheet->getHighestRow(); //循环获取表中的数据,$currentRow表示当前行,从哪行开始读取数据,索引值从0开始 for($currentRow = 1; $currentRow <= $allRow; $currentRow++){ //从哪列开始,A表示第一列 for($currentColumn='A'; $currentColumn <= $allColumn; $currentColumn++){ //数据坐标 // $address = $currentColumn.$currentRow; //读取到的数据,保存到数组$arr中 // $info[$currentRow][$currentColumn] = $currentSheet->getCell($address)->getValue(); // -- 本来上面更精简的,奈何下面才正确 $val = $currentSheet->getCellByColumnAndRow(ord($currentColumn) - 65, $currentRow)->getValue(); if(is_object($val)){ //解决object(PHPExcel_RichText)问题 $val= $val->__toString(); } $info[$currentRow][] = $val; } } $DB = M($db); $data = array(); for ($i = 2; $i <= count($info); $i ++) { for ($j = 0; $j < count($info[$i]); $j ++) { for ($k = 0; $k < count($info[1]); $k ++) { $data[$i][$info[1][$k]] = $info[$i][$k] ? $info[$i][$k] : ''; } } } $datalist = array_values($data); //开启事务 $DB->startTrans(); $result = $DB->addAll($datalist); //返回插入的第一条数据ID // echo $DB->getLastSql();exit; unlink($file); //删除上传的导入文件 if ($result) { $DB->commit(); //获取插入之后最大的ID,用于记录插入数目 $max_later_id = $DB->max('id'); return $max_later_id-$result+1; //返回影响的条数 }else{ $DB->rollback(); return false; } }
调用方式:(数据库表单数据以Excel形式导出)
//先上传文件,以获取文件真实路径
$upload = new \Think\Upload(); $upload->savePath = C('UPLOAD_SAVEPATH').'files_upload/'; $info = $upload->upload(); $filename = 'Uploads/'.str_replace('./', '', $info['upfile']['savepath'].$info['upfile']['savename']); $db = $this->dbname; $res = $this->xlsin($db, $filename);
二、导出,获取Excel表数据 (文件名, 文件标头, 数据)
public function xlsout($filename='数据表',$headArr,$list){ //导入PHPExcel类库,因为PHPExcel没有用命名空间,只能import导入 import("Org.Util.PHPExcel"); import("Org.Util.PHPExcel.Writer.Excel5"); import("Org.Util.PHPExcel.IOFactory.php"); $this->getExcel($filename,$headArr,$list); } public function getExcel($fileName,$headArr,$data){ //对数据进行检验 if(empty($data) || !is_array($data)){ die("data must be a array"); } //检查文件名 if(empty($fileName)){ exit; } $date = date("Y_m_d",time()); $fileName .= "_{$date}.xls"; //创建PHPExcel对象,注意,不能少了\ $objPHPExcel = new \PHPExcel(); $objProps = $objPHPExcel->getProperties(); //设置表头 $key = 0; //print_r($headArr);exit; foreach($headArr as $v){ //注意,不能少了。将列数字转换为字母\ $colum = \PHPExcel_Cell::stringFromColumnIndex($key); $objPHPExcel->setActiveSheetIndex(0) ->setCellValue($colum.'1', $v); $key += 1; } $column = 2; $objActSheet = $objPHPExcel->getActiveSheet(); foreach($data as $key => $rows){ //行写入 $span = 0; foreach($rows as $keyName=>$value){// 列写入 $j = \PHPExcel_Cell::stringFromColumnIndex($span); $objActSheet->setCellValue($j.$column, $value); $span++; } $column++; } $fileName = iconv("utf-8", "gb2312", $fileName); //重命名表 // $objPHPExcel->getActiveSheet()->setTitle('test'); //设置活动单指数到第一个表,所以Excel打开这是第一个表 $objPHPExcel->setActiveSheetIndex(0); ob_end_clean();//清除缓冲区,避免乱码 header('Content-Type: application/vnd.ms-excel'); header("Content-Disposition: attachment;filename=\"$fileName\""); header('Cache-Control: max-age=0'); $objWriter = \PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5'); $objWriter->save('php://output'); //文件通过浏览器下载 exit; }
调用方式:(用于Excel数据导入数据库)
$list = $model->where($map)->field('id,type,name,age,moblie,addname,addtime,remark')->select(); $headArr=array('ID','类型','姓名','年龄','手机号码','添加人','添加时间','备注'); $filename='测试员列表'; $this->xlsout($filename,$headArr,$list);
三、导入,返回Array数据(input直接传入 $_FILES)
PHPExcel文件夹位于Core/Library/Org/Util/PHPEXcel/
Cell.php、IOFactory.php、Writer/Excel2007/、Writer/Excel5/等皆位于PHPExcel目录下
public function get_import_data($file){ if (! empty ( $file['name'] )) { $tmp_file = $file['tmp_name']; $file_types = explode ( ".", $file['name'] ); $file_type = $file_types [count ( $file_types ) - 1]; /*判别是不是.xls文件,判别是不是excel文件*/ if (strtolower ( $file_type ) != "xls" ){ print('不是Excel文件,重新上传'); } /*设置上传路径*/ $savePath = "Uploads/Public/files_data/"; /*以时间来命名上传的文件*/ $str = date ( 'Ymdhis' ); $file_name = $str . "." . $file_type; /*是否上传成功*/ if (! copy ( $tmp_file, $savePath . $file_name )) { //$this->error ( '上传失败' ); print('上传失败'); } $filename = $savePath . $file_name; /**读取excel $filename 路径文件名 $encode 返回数据的编码 默认为utf8 以下基本都不要修改 */ import("Org.Util.PHPExcel");
//因版本关系可能会引发import()的问题,import()默认会给文件添加 '.class.php'的后缀。同时将 '.' 替换为 '/',导致文件路径也解析错误。出现问题可尝试使用以下方式。 // import("Org.Util.PHPExcel.Writer.Excel5", "", ".php"); // import("Org.Util.PHPExcel.Cell", "", ".php"); // import("Org.Util.PHPExcel.IOFactory", "", ".php");
if (strtolower ( $file_type ) == "xls" ){
$objReader = \PHPExcel_IOFactory::createReader('Excel5'); //必须以 '\' 开头,命名空间之类的!
}else if(strtolower ( $file_type ) == "xlsx"){
$objReader = \PHPExcel_IOFactory::createReader('Excel2007');
} $objReader->setReadDataOnly(true); $objPHPExcel = $objReader->load($filename); $objWorksheet = $objPHPExcel->getActiveSheet(); $highestRow = $objWorksheet->getHighestRow(); $highestColumn = $objWorksheet->getHighestColumn(); $highestColumnIndex = \PHPExcel_Cell::columnIndexFromString($highestColumn); $excelData = array(); for ($row = 1; $row <= $highestRow; $row++) { for ($col = 0; $col < $highestColumnIndex; $col++) { $excelData[$row][] =(string)$objWorksheet->getCellByColumnAndRow($col, $row)->getValue(); } }//echo '<pre>' ; print_r($excelData);exit; unlink($filename); return $excelData; } }
调用方式:(用于解决Excel迭代与额外处理问题)
$excelData = $this->get_import_data($_FILES['upfile']); dump($excelData);
注:若数据库插入过程中出现错误,unlink()操作将不会执行,已上传文件需要手动清理。