查看: 67|回覆: 3

[教程] PHP使用PHPExcel读取excel数据并批量上传到数据库

[複製鏈接]

2

主題

0

回帖

0

積分

热心网友

金币
0
閲讀權限
220
精華
0
威望
0
贡献
0
在線時間
0 小時
註冊時間
2011-10-15
發表於 2026-5-3 17:28:21 | 顯示全部樓層 |閲讀模式

应用场景

当遇到需要批量导入数据的时候,前端会上传一个excel表格,由后端读取数据并存入数据库。前端代码就不介绍了,这是一个前后端分离的项目,主要是讲解后端读取excel表格的数据。前端上传文件就可以了。

PHPExcel 是什么

是用来操作office excel 文档的一个PHP类库,它基于微软的OpenXML标准和PHP语言。可以使用它来读取、写入不同格式的电子表格,如Excel(BIFF).xls,Excel 2007 (OfficeOpenXML),.xlsx,CSV,Libre/OpenOffice Calc .ods, Gnumeric, PDF, HTML等等。

要求

PHP 5.2.0 版本及以上

PHP extension php_zip 开启 (如果你需要使用 PHPExcel 来操作 .xlsx .ods or .gnumeric 文件)

PHP extension php_xml 开启

PHP extension php_gd2 开启(选填, 如果需要计算准确的列宽需要开启此扩展)

PHP 读取文件写入数据库

<?php
header("Content-type:text/html; charset=utf-8");

// 制定允许其他域名访问
header("Access-Control-Allow-Origin:*");
// 响应类型
header('Access-Control-Allow-Methods:POST');
// 响应头设置
header('Access-Control-Allow-Headers:x-requested-with, content-type');
// 数据库配置文件
include './config/config.php';
// 下载 PHPExcel 放入项目内,引入即可
include "./PHPExcel-1.8/Classes/PHPExcel/IOFactory.php";


// 获取前端传入的文件
$file = $_FILES['file'];
//临时文件存放路径
$fileTmp = $file['tmp_name'];
$fileSize = $file['size'];
$fileName = $file['name'];
//错误,输出0,表示文件提交成功
$fileError = $file['error'];


if($fileError==0) {
	$inputFileName = $fileTmp;
	date_default_timezone_set('PRC');
	// 读取excel文件
	try {
	    $inputFileType = PHPExcel_IOFactory::identify($inputFileName);
	    $objReader = PHPExcel_IOFactory::createReader($inputFileType);
	    $objPHPExcel = $objReader->load($inputFileName);
	} catch(Exception $e) {

	}

	// 确定要读取的sheet,什么是sheet,看excel的右下角
	$sheet = $objPHPExcel->getSheet(0);
	$highestRow = $sheet->getHighestRow();
	$highestColumn = $sheet->getHighestColumn();

	$time = date('Y-m-d h:i:s', time());
	// 把数据处理后存入数组
	$array = array();
	$time = date('Y-m-d h:i:s', time());
	for ($row = 2; $row <= $highestRow; $row++) {
		$rowData = $sheet->rangeToArray('A' . $row . ':' . $highestColumn . $row, NULL, TRUE, FALSE);
		// 重复数据不插入数据库
		$falg = $rowData[0][0];
		$sqlIf = "SELECT codes FROM tablef where codes = '$falg'";
		$querySQL = mysqli_query($conn,$sqlIf);
		$arrSQL = mysqli_fetch_array($querySQL);
		if($arrSQL == null) {
			// 获取到 Excel 每行的数据插入数据库,需根据你自己的表格进行调整
			$sql="insert into tablef(codes,year,month,idcode,type,timese) values('".$rowData[0][0]."','" .($rowData[0][1])."','".$rowData[0][2]."','".$rowData[0][3]."','".$rowData[0][4]."','".$time."')";

			$query=mysqli_query($conn,$sql);//函数执行一条 MySQL 查询。
		}
	}

	// 成功后返回给前端
	echo json_encode(["msg" => 'ok']);
}else {
	echo json_encode(["msg" => 'no']);
}


// 断开数据库连接
$conn->close();   


?>

结语

这是原生PHP使用的一个方式,我PHP的话只会一个 ThinkPHP 框架,这边我测试的话 ThinkPHP 使用起来跟这个也是差不多的,至于有些其他的php框架的话我没有用过,但是基本都差不多。现在前后端分离占主导地位,对于一些做后台的兄弟们来说,这些批量导入数据的是很常见的,这边就分享一个简单的,对于一些sql语句的话是需要修改的,这里面的sql语句是不安全的,这里提醒一下大家,测试的时候使用这些SQL语句为啥问题,生产环境切记不能这样用。

回覆

使用道具 舉報

0

主題

720

回帖

4441

積分

琼殿精英

金币
3721
閲讀權限
220
精華
0
威望
0
贡献
0
在線時間
0 小時
註冊時間
2011-10-11
發表於 2026-5-3 19:51:27 | 顯示全部樓層
感谢楼主的分享!

正好最近项目里也用到批量导入Excel的功能,看完你的帖子感觉收获不少。PHPExcel确实是处理Excel数据的神器,操作起来比想象中简单。

关于安全性的一些小建议:

看到你在结语里也提到了SQL注入的问题,这里再补充几点:
1. 建议使用预处理语句(Prepared Statements)来防止SQL注入
2. 对用户上传的文件类型要做严格校验
3. 文件大小也要做限制,避免内存溢出
  1. // 预处理语句示例
  2. $stmt = $conn->prepare("INSERT INTO tablef (codes, year, month, idcode, type, timese) VALUES (?, ?, ?, ?, ?, ?)");
  3. $stmt->bind_param("ssssss", $rowData[0][0], $rowData[0][1], $rowData[0][2], $rowData[0][3], $rowData[0][4], $time);
  4. $stmt->execute();
複製代碼

另外有个小问题想请教:

如果Excel数据量比较大(比如上万条),一次性循环插入会不会比较慢?有没有什么优化的思路?

再次感谢博主,写的很详细,对新手很友好!
回覆

使用道具 舉報

0

主題

66

回帖

71

積分

琼殿精英

金币
5
閲讀權限
220
精華
0
威望
0
贡献
0
在線時間
0 小時
註冊時間
2012-4-30
發表於 2026-5-3 19:51:32 | 顯示全部樓層
楼主这篇分享太及时了!正好最近在搞后台数据导入功能,看了你的思路清晰多了。友情提示一下,PHPExcel官方早就停止维护了,如果项目允许的话,强烈建议升级到PhpSpreadsheet,底层逻辑差不多但支持PHP8和新版Excel格式,内存优化也更好。

批量入库的时候记得分批处理,别一次性全塞进数据库,不然数据量一大直接超时或者撑爆内存。可以参考这种写法:
  1. [math]batchSize = 500;
  2. [/math]data = [];
  3. foreach ([math]rows as [/math]row) {
  4.     [math]data[] = [/math]row;
  5.     if (count([math]data) >= [/math]batchSize) {
  6.         [math]db->batchInsert([/math]data);
  7.         [math]data = [];
  8.     }
  9. }
  10. if (!empty([/math]data)) {
  11.     [math]db->batchInsert([/math]data);
  12. }
複製代碼


另外导入前最好加个数据校验和事务回滚,避免脏数据入库。楼主写得挺详细的,期待后续更新完整示例!顶一个,大家一起交流进步~
回覆

使用道具 舉報

0

主題

0

回帖

98

積分

琼殿精英

金币
97
閲讀權限
220
精華
0
威望
0
贡献
0
在線時間
0 小時
註冊時間
2012-5-8
發表於 2026-5-6 14:18:34 | 顯示全部樓層
哇这帖子太实用了,楼主分享的思路很清晰,楼上大佬提醒的换PhpSpreadsheet还有分批插入也超有用!我之前做类似功能踩过几个坑也补充下给大家避坑:
  • 碰到带公式的单元格别直接取值,不然会拿到公式文本,要拿计算结果的话用getCalculatedValue()就行,复杂公式多的话开个计算缓存速度能提不少;
  • 分批插入的时候最好套上事务,某一批数据有问题直接全量回滚,不会出现一半导入成功一半失败的尴尬情况,后续排查也方便;
  • 导入前一定要加表头校验!先判断第一行的列名是不是和预期完全匹配,不然用户传错表格或者弄反列序,导进去一堆脏数据清理起来真的要疯;
  • 要是允许传大体积Excel,记得提前调整PHP的最大执行时间、上传文件大小、POST包大小这些配置,不然很容易传到一半就中断,要求更高的话可以做前端分片上传。

如果对导入速度要求特别高的场景,也可以让用户上传csv格式,用原生fgetcsv读取速度比用类库快超多哦[s:ac:goodjob]
回覆

使用道具 舉報

您需要登錄後才可以回帖 登錄 | 立即注册

本版積分規則

相关侵权、举报、投诉及建议等,请发 E-mail:qiongdian@foxmail.com

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部