<?php namespace app\common\util; use PhpOffice\PhpSpreadsheet\IOFactory; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Style\Alignment; class ExcelUtil { static private $error = ''; // 导入获取数据 static public function read($filepath = '', $cols = [],$row = 2){ // $cols = ['id','name','class']; $e = explode('.',$filepath); $ext = $e[count($e)-1]; if($ext == 'xls'){ $objread = IOFactory::createReader('Xls'); }else{ $objread = IOFactory::createReader('Xlsx'); } $newArr=['xls','xlsx']; if(!in_array($ext,$newArr)){ return false; } $objspreadsheet = $objread->load($filepath); $ret = $objspreadsheet->getActiveSheet()->toArray(); $ret = $ret?$ret:[]; $nret = []; foreach ($ret as $k=>$v){ if($k + 1 < $row){ continue; } if($cols){ foreach ($cols as $kk=>$vv){ $a[$vv] = $v[$kk]; } $nret[] = $a; }else{ $nret[] = $v; } } return $nret; } // 导出 static public function export($filename,$header = [],$data = [],$savepath = ''){ // $header = [ // header格式,title和name必须存在 // ['title' => '编号', 'name' => 'id','width'=>'20'], // ['title' => '姓名', 'name' => 'name','width'=>'20'], // ['title' => '班级', 'name' => 'class','width'=>'20'], // ]; $spreadsheet = new Spreadsheet(); $worksheet = $spreadsheet->getActiveSheet(); $worksheet->setTitle($filename); $widths = []; $titles = []; $names = []; foreach ($header as $k=>$v){ $width = isset($v['width'])&&$v['width'] > 0 ?$v['width']:20; $widths[] = $width; $titles[] = isset($v['title'])?$v['title']:''; $names[] = $v['name']; } $char = ['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']; $lins = []; for( $i=0;$i<count($header);$i++ ){ $r1 = $i%26; $r2 = floor($i/26); if($r2 == 0){ $lins[] = $char[$r1]; }else if($r2 == 1){ $lins[] = 'A'.$char[$r1]; }else if($r2 == 2){ $lins[] = 'B'.$char[$r1]; }else if($r2 == 3){ $lins[] = 'C'.$char[$r1]; }else if($r2 == 4){ $lins[] = 'D'.$char[$r1]; }else if($r2 == 5){ $lins[] = 'E'.$char[$r1]; }else if($r2 == 6){ $lins[] = 'F'.$char[$r1]; } } $lists = self::chunkData($data); foreach ($lists as $k=>$v){ if($k > 0){ $sheet = $spreadsheet->createSheet($k+1)->setTitle($filename.($k+1)); }else{ $sheet = $worksheet; } self::writeSheet($sheet,$v,$titles,$widths,$lins,$names); } if(!$lists){ self::writeSheet($worksheet,[],$titles,$widths,$lins,$names); } $writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Xlsx'); if($savepath){ $res = $writer->save($savepath); halt($res); }else{ $path = $filename.'_'.date('YmdHis').'.xlsx'; header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); header('Content-Disposition: attachment;filename="'.$path.'"'); header('Cache-Control: max-age=0'); $writer->save('php://output'); } } // 数据分段 static private function chunkData($data,$length = 50000){ $ret = []; $arr = []; foreach ($data as $k=>$v){ $arr[] = $v; if(count($arr) == $length){ $ret[] = $arr; $arr = []; } } if($arr){ $ret[] = $arr; } return $ret; } // 多sheet导出,不用数据分段 static public function exportBySheet($filename,$header = [],$sheets = [],$data = [],$savepath = ''){ // $header = [ // header格式,title和name必须存在 // ['title' => '编号', 'name' => 'id','width'=>'20'], // ['title' => '姓名', 'name' => 'name','width'=>'20'], // ['title' => '班级', 'name' => 'class','width'=>'20'], // ]; // $sheets = ['sheet1','sheet2']; // $data = [['id'=>1,'name'=>'aaa']]; 二维数组 $spreadsheet = new Spreadsheet(); $worksheet = $spreadsheet->getActiveSheet(); $widths = []; $titles = []; $names = []; foreach ($header as $k=>$v){ $width = isset($v['width'])&&$v['width'] > 0 ?$v['width']:20; $widths[] = $width; $titles[] = isset($v['title'])?$v['title']:''; $names[] = $v['name']; } $char = ['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']; $lins = []; for( $i=0;$i<count($header);$i++ ){ $r1 = $i%26; $r2 = floor($i/26); if($r2 == 0){ $lins[] = $char[$r1]; }else if($r2 == 1){ $lins[] = 'A'.$char[$r1]; }else if($r2 == 2){ $lins[] = 'B'.$char[$r1]; }else if($r2 == 3){ $lins[] = 'C'.$char[$r1]; }else if($r2 == 4){ $lins[] = 'D'.$char[$r1]; }else if($r2 == 5){ $lins[] = 'E'.$char[$r1]; }else if($r2 == 6){ $lins[] = 'F'.$char[$r1]; } } $lists = $data; foreach ($lists as $k=>$v){ if($k > 0){ $sheet = $spreadsheet->createSheet($k+1)->setTitle($sheets[$k]); }else{ $worksheet->setTitle($sheets[$k]); $sheet = $worksheet; } self::writeSheet($sheet,$v,$titles,$widths,$lins,$names); } $writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Xlsx'); if($savepath){ $res = $writer->save($savepath); halt($res); }else{ $path = $filename.'_'.date('YmdHis').'.xlsx'; header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); header('Content-Disposition: attachment;filename="'.$path.'"'); header('Cache-Control: max-age=0'); $writer->save('php://output'); } } // 按sheet写入数据 static private function writeSheet($sheet,$data,$titles,$widths,$lins,$names){ foreach ($titles as $key => $value) { $sheet->setCellValueByColumnAndRow($key+1, 1, $value); } $styleArray = [ 'font' => [ 'bold' => true ], 'alignment' => [ 'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER, ], ]; $styleArray2 = [ 'alignment' => [ 'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER, ], ]; foreach ($lins as $k=>$v){ $sheet->getStyle($v.'1')->applyFromArray($styleArray)->getFont()->setSize(12); $sheet->getStyle($v)->applyFromArray($styleArray2)->getAlignment()->setWrapText(true);//换行 $sheet->getColumnDimension($v)->setWidth($widths[$k]); } foreach ($data as $k=>$v){ foreach ($names as $kk=>$vv){ $sheet->setCellValueByColumnAndRow($kk+1, $k + 2, self::filterEmoji($v[$vv])); } } } // 过滤表情 static private function filterEmoji($str){ $str = preg_replace_callback('/./u',function ($match){ return strlen($match[0]) >= 4?'':$match[0]; },$str); return $str; } // 导入excel,获取excel数据 static public function importExcel($name,$cols,$row = 2){ $config = config('app.max_upload_excel'); $file = request()->file($name); if(!$file){ self::$error = '未上传文件'; return false; } // $mime = $file->getMime(); $info = $file->validate($config)->move(env('root_path') . 'public' . DIRECTORY_SEPARATOR . 'uploads'. DIRECTORY_SEPARATOR . 'files'); if(!$info){ self::$error = $file->getError(); return false; } $img = '/uploads/files/' . $info->getSaveName(); $imgpath = str_replace('\\', '/', $img); $ret = env('root_path') . 'public'.$imgpath; if($ret === false){ self::$error = $file->getError(); return false; } $data = self::read($ret,$cols,$row); if($data === false){ self::$error = "后缀类型错误"; return false; } @unlink($ret); return $data; } static public function getError(){ return self::$error; } }