前提:有个需求需要实现带图片的excel数据导入数据库中,发现PHPExcel - Excel 操作库已经停止维护,在PHP8的版本中,有些语法不支持,报错一堆,改了一堆,又还有一堆。所以决定找个替代的扩展:phpoffice/phpspreadsheet
技术背景前提:
- ThinkPHP8.0
- php8.0.2nts
- "phpoffice/phpspreadsheet": "^1.20.0"
在composer.json中加入"phpoffice/phpspreadsheet": "^1.20.0"
后composer update
,如果选择的phpoffice/phpspreadsheet版本不同,可能又有不同的坑存在,得进行一一排查。这里记录下。
实现步骤看代码注释部分,实现代码如下:
php
/**
* 字母序列化为数字
*/
public function ABC2decimal($abc)
{
$ten = 0;
$len = strlen($abc);
for ($i = 1; $i <= $len; $i++) {
$char = substr($abc, 0 - $i, 1);//反向获取单个字符
$int = ord($char);
$ten += ($int - 65) * pow(26, $i - 1);
}
return $ten;
}
public function excel()
{
if ($file = request()->file('excel')) {
try {
$saveName = Filesystem::disk('public')->putFile('/static/upload/excels', $file);
if (!is_file($saveName)) {
return json(['code' => 1, 'msg' => '文件不存在', 'data' => null]);
}
$ext = pathinfo($saveName, PATHINFO_EXTENSION);
// xls不支持图片导入
// if (!in_array($ext, ['xlsx', 'xls'])) {
if (!in_array($ext, ['xlsx'])) {
return json(['code' => 1, 'msg' => '文件类型不正确', 'data' => null]);
}
// 有两种格式,xlsx和xls
if ($ext == 'xlsx') {
$objReader = IOFactory::createReader('Xlsx');
} else {
$objReader = IOFactory::createReader('Xls');
}
// 图片保存路径
$imageFilePath1 = root_path() . '/public/'; // 图片保存目录
$imageFilePath2 = 'static/upload/images/' . date("Ymd") . '/';
$imageFilePath = $imageFilePath1 . $imageFilePath2;
if (!file_exists($imageFilePath)) {
mkdir("$imageFilePath", 0777, true);
}
// 载入excel文件
$excel = $objReader->load($saveName);
// 读取第一张表
$sheet = $excel->getActiveSheet();
// 读取总行数
$highestRow = $sheet->getHighestRow();
// 读取第一张表转换成数组
$data = $sheet->toArray();
// 处理图片
foreach ($sheet->getDrawingCollection() as $drawing) {
list($startColumn, $startRow) = Coordinate::coordinateFromString($drawing->getCoordinates());
$imageFileName = $drawing->getIndexedFilename(); // 获取文件名
switch ($drawing->getExtension()) {
case 'jpg':
case 'jpeg':
$source = imagecreatefromjpeg($drawing->getPath());
imagejpeg($source, $imageFilePath . $imageFileName);
break;
case 'gif':
$source = imagecreatefromgif($drawing->getPath());
imagegif($source, $imageFilePath . $imageFileName);
break;
case 'png':
$source = imagecreatefrompng($drawing->getPath());
imagepng($source, $imageFilePath . $imageFileName);
break;
}
$startColumn = $this->ABC2decimal($startColumn);
$data[$startRow - 1][$startColumn] = $imageFilePath2 . $imageFileName;
}
// 数据写入数据库
$add_data = [];
for ($i = 1; $i <= $highestRow - 1; $i++) {
$add_data[$i]['institution'] = $data[$i][0];
$add_data[$i]['name'] = $data[$i][1];
$add_data[$i]['sex'] = $data[$i][2];
$add_data[$i]['phone'] = $data[$i][3];
$add_data[$i]['id_type'] = $data[$i][4];
$add_data[$i]['id_no'] = $data[$i][5];
$add_data[$i]['occupation'] = $data[$i][6];
$add_data[$i]['job'] = $data[$i][7];
$add_data[$i]['skill_level'] = $data[$i][8];
$add_data[$i]['certificate_no'] = $data[$i][9];
$add_data[$i]['create_time'] = $data[$i][10];
$add_data[$i]['start_time'] = $data[$i][11];
$add_data[$i]['end_time'] = $data[$i][12];
$add_data[$i]['path'] = $data[$i][13];
}
// 数据插入数据库
$success_count = Db::table('certificate')->insertAll($add_data);
if ($success_count > 0) {
return json(['code' => 0, 'msg' => '数据插入成功', 'data' => null]);
} else {
return json(['code' => 1, 'msg' => '数据插入失败', 'data' => null]);
}
} catch (\Exception $e) {
return json(['code' => 1, 'msg' => $e->getMessage(), 'data' => null]);
}
} else {
return json(['code' => 1, 'msg' => '上传文件不能为空', 'data' => null]);
}
}