首先,我用的项目环境是 lumen 6.0X, php 7.4,下一步lumen是需要安装 phpexcel扩展的,至于步骤,随便百度一下就有很多,只是简单写一下
导出文件 ,对于没有安装的,懒得百度的,可以走一遍这个流程
1、安装 maatwebsite/excel
composer require maatwebsite/excel
2、在bootstrap/app.php中加入 (就是注册)
$app->register(Maatwebsite\Excel\ExcelServiceProvider::class);
3、修改配置获取方式 (在配置里加些东西,理论上加不加应该都可以,会有默认值)
Maatwebsite\Excel\Readers\LaravelExcelReader.php 查找 Config::get 替换为 config
4、走完上面三步,就可以使用了,不过有一个令人头疼的地方就是,镜像是国内的话,会很慢,当初我也是用的国外的代理。
懒得改代码了,就说一下业务场景吧,我们是做考试系统的,里面有excel 导入试题,我们是后端只负责接收excel路径,前端会有专门接口上传文件,我们要做的就是获取前端传过来的 excel,咳咳,有点跑题了,说导入呢
下面贴导入代码:
validate($request, [
'period_id' => 'required|string',
'ques_url' => 'required|string',
]);
} catch (\Exception $e) {
throw new CommonapiException('param_error');
}
$input = $request->post();
$file = $request->post('ques_url');
//下载到本地
$localName = '/tmp/' . time() . mt_rand(1000, 9999) . '.xls';
$fp_input = fopen($file, 'r');
file_put_contents($localName, $fp_input);
header("Content-type: text/html; charset='utf-8'");
//读取excel内容
$res = [];
error_reporting(0);
Excel::load($localName, function ($objPHPExcel) use (&$res) {
$sheet = $objPHPExcel->getSheet(0); //指定的表
$highestRow = $sheet->getHighestDataRow(); // 取得总行数
$highestColumn = $sheet->getHighestDataColumn(); // 取得总列数
$arr = array();
$ques = array();
//从2行开始读起
for ($i = 2; $i <= $highestRow; $i++) {
if (($sheet->getCell("A" . $i)->getValue()) != NULL) {
$questype = trim($sheet->getCell("A" . $i)->getValue());
$ques[$i]['ques_type'] = $this->quesTypeBack($questype);
if($highestColumn == "L"){
$ques_diff = $this->str_rep($sheet->getCell("J" . $i)->getValue());
$is_pratice = $this->str_rep($sheet->getCell("K" . $i)->getValue());
$ques_diff = $this-> quesDiffBack($ques_diff);
$is_pratice = $this-> quesTestBack($is_pratice);
$ques[$i]['ques_body'] = $this->str_rep($sheet->getCell("B" . $i)->getValue());
$ques[$i]['ques_choice_a'] = $this->str_rep($sheet->getCell("C" . $i)->getValue());
$ques[$i]['ques_choice_b'] = $this->str_rep($sheet->getCell("D" . $i)->getValue());
$ques[$i]['ques_choice_c'] = $this->str_rep($sheet->getCell("E" . $i)->getValue());
$ques[$i]['ques_choice_d'] = $this->str_rep($sheet->getCell("F" . $i)->getValue());
$ques[$i]['ques_answer'] = $this->str_rep($sheet->getCell("G" . $i)->getValue());
$ques[$i]['ques_answer_key'] = $this->str_rep($sheet->getCell("H" . $i)->getValue());
$ques[$i]['ques_score'] = $this->str_rep($sheet->getCell("I" . $i)->getValue());
$ques[$i]['ques_difficulty'] = $ques_diff;
$ques[$i]['is_pratice'] = $is_pratice;
$ques[$i]['ques_memo'] = $this->str_rep($sheet->getCell("L" . $i)->getValue());
}
$answer = $ques[$i]['ques_answer'];
//字母全角转半角
if ($questype == "单选题" || $questype == "多选题" || $questype == "判断题") {
$ques[$i]['ques_answer'] = trim($this->SBC_DBC($answer, 1));
}
if ($questype == "判断题") {
if ($answer == '对' || $answer == '是' || $answer == '正确') {
$ques[$i]['ques_answer'] = "A";
}
if ($answer == '错' || $answer == '否' || $answer == '错误') {
$ques[$i]['ques_answer'] = "B";
}
}
//防止填空题答案为空
if ($questype == "填空题") {
if ($answer == '') {
$ques[$i]['ques_answer'] = '*空*';
} else {
$answer = preg_replace('/\s/', '', $answer);//填空题答案去空格
$answer = preg_replace('/,/', ',', $answer);//填空题中文逗号变英文逗号
$ques[$i]['ques_answer'] = $answer;
}
}
//防止问答题答案为空
if ($questype == '问答题') {
if ($answer == '') {
$ques[$i]['ques_answer'] = '*答案略*';
}
}
}
}
$res['ques'] = $ques;
});
$res['period_id'] = $request->post('period_id');
$result = $this->tklibInnerObj->revokeurl($this->sysname, 'ques/quesImport', $res);
$status = $result['code'] ?? '';
if (empty($status) || $status != 1) {
return $this->render([], '获取失败', 0);
}
return $this->render($result['data']);
}
}
代码太废了,说主要的,先引入
use Maatwebsite\Excel\Facades\Excel;
然后就是使用 excel
Excel::load($localName, function ($objPHPExcel) use (&$res) {
$sheet = $objPHPExcel->getSheet(0); //指定的表
$highestRow = $sheet->getHighestDataRow(); // 取得总行数
$highestColumn = $sheet->getHighestDataColumn(); // 取得总列数
......你的逻辑代码
}
我写的代码有些low,见谅以前用CI3版本的,用习惯了,导入的话自然而然也就按照以前方式来了,值得注意的是:
$sheet = $objPHPExcel->getSheet(0); //指定的表
$highestRow = $sheet->getHighestDataRow(); // 取得总行数
$highestColumn = $sheet->getHighestDataColumn(); // 取得总列数
这三行,有时候我获取excel内的列数、行数总是不准的,尤其是列数,有可能出来的不是数字,是两个字母,头疼了小半天,最后决定牺牲一些效率,用这种方法获取总行数跟列数:getHighestDataRow、getHighestDataColumn 就好了
当然了还有其他简单的方法,直接将每行每列搞成数组去处理,也可以,就像这样
public function uploadUni(Request $request)
{
$file = $request->post('file');
//下载到本地
$localName = '/tmp/' . time() . mt_rand(1000, 9999) . '.xls';
$fp_input = fopen($file, 'r');
file_put_contents($localName, $fp_input);
header("Content-type: text/html; charset=gbk");
//读取excel内容
$res = [];
Excel::load($localName, function ($reader) use (&$res) {
$reader = $reader->getSheet(0);
$res = $reader->toArray();
});
//删除文件
@unlink($localName);
//开启事务,插入多个表
DB::beginTransaction();
try {
//插表啊啊啊啊啊啊啊
DB::commit();
} catch (Exception $e) {
DB::rollback();
return $this->render([], '操作失败', 0);
}
}
其中 $res 就是一个二维数组,随便你怎么处理(删除文件下面的代码就不用看了,跟导入无关,是我跑题了)
导出excel的话,我有列表页接口,前端会在本地建一个excel,多次调用列表页接口,追加到excel就行,最后前端下载,这样不会有服务器端的超时问题
导出代码(导入都写了,导出随便搜一个吧)
public function cand_export(){
$cellData = [
[' 学号 ',' 姓名 ',' 编号'],
['10001','AAAAA','100001'],
['10002','BBBBB','100002'],
];
Excel::create ('score',function ($excel) use ($cellData){
$excel->sheet('score', function($sheet) use ($cellData){
$sheet->rows($cellData);
});
})->export('xls');
}