spingboot+layui+poi实现excel导入功能,并批量插入数据库

1、maven的pom文件添加下面jar包

        <dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi</artifactId>
			<version>3.17</version>
		</dependency>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml</artifactId>
			<version>3.17</version>
		</dependency>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml-schemas</artifactId>
			<version>3.17</version>
		</dependency>
		<dependency>
			<groupId>org.apache.xmlbeans</groupId>
			<artifactId>xmlbeans</artifactId>
			<version>2.4.0</version>
		</dependency>
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-collections4</artifactId>
			<version>4.1</version>
		</dependency>

2、前端页面定义layui按钮,弹出导入页面

//定义按钮
<button class="layui-btn layui-btn-sm" lay-event="uploadExcel">Excel上传</button>
//弹出层位置
 <table class="layui-table"  id="currentTableId" lay-filter="currentTableFilter"></table>
//toolbar监听事件
table.on('toolbar(currentTableFilter)', function (obj) {
         if(obj.event === 'uploadExcel'){
            layer.open({
                    type: 2,
                    title: 'Excel上传',
                    shadeClose: true,
                    shade: 0.8,
                    area: ['500px', '50%'],
                    content: 'uploadHtml',
                    btn: ['确定', '取消'],
                    yes: function (index) {
                    var formSubmit = layer.getChildFrame('form', index);
                        var submited = formSubmit.find('button')[0];
                        submited.click();
                        $('.layui-laypage-btn').click();
                    }
                });
            }
        });

3、弹出框页面代码

  <!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="utf-8">
    <title>导入excel数据</title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <link rel="stylesheet" href="/static/layui/lib/layui-v2.6.3/css/layui.css" media="all">
    <script src="/static/layui/lib/layui-v2.6.3/layui.js" charset="utf-8"></script>
    <script src="static/assets/js/jquery.min.js"></script>
</head>
<body class="layui-layout-body">
 
<div class="layui-upload" align="center">
    <fieldset class="layui-elem-field layui-field-title" style="margin-top: 30px;" align="center">
        <legend>请选择您要上传的Excel文件</legend>
    </fieldset>
 
    <div style="margin-top: 30px" align="center">
        <button id="importData" class="layui-btn layui-btn-normal">导入</button>
    </div>
</div>
 
 
<script src="../../layui/layui.js" th:src="@{/layui/layui.js}"></script>
<script th:src="@{/js/jquery-3.4.0.min.js}"></script>
 
<script th:inline="javascript">
 
    ctxPath = /*[[@{/}]]*/ '';
 
    layui.use(["element", "layer", "upload"], function () {
        var layer = layui.layer;
        layui.upload.render({
            elem: "#importData",
            url: '/upload',
            size: '800',
            accept: "file",
            exts: 'xls|xlsx',
            before: function () {
                layer.load();
            },
            done: function (result) {
                if (result.code === 0) {
                    layer.msg(result.msg, {icon: 1, time: 1000}, function () {
                        var index = parent.layer.getFrameIndex(window.name);
                        parent.layer.close(index);
                        parent.$('.layui-laypage-btn').click();
                    });
                } else if (result.code === -1) {
                    layer.msg(result.msg, {icon: 5, time: 2500}, function () {
                        var index = parent.layer.getFrameIndex(window.name);
                        parent.layer.close(index);
                        parent.$('.layui-laypage-btn').click();
                    });
                }
                layer.closeAll('loading');
            }
        });
    });
 
</script>
</body>
</html>
 

4、后端controller

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.xxx.bean.Unit;
import com.xxx.common.ReadDataByExcel;
import com.xxx.service.UnitService;
import com.xxx.util.JsonResult;
import com.xxx.util.UtilTool;

import lombok.extern.slf4j.Slf4j;
@Controller
@Slf4j
public class UploadController {
	@Autowired
	private UnitService unitService;
       
       //弹出页面
	@RequestMapping("/uploadHtml")
	public String uploadHtml(String mode,Model model) {
		return "upload/upload";
		
	}
	//批量数据添加
	@Transactional
    @ResponseBody
    @PostMapping(value = "upload")
    public JsonResult upload(@RequestParam MultipartFile file) {
		System.out.println(file.getOriginalFilename());
        log.info("Excel批量上传信息");
        try {
            InputStream inputStream = file.getInputStream();
            List<Map<String, Object>> list = ReadDataByExcel.readExcel(inputStream);//自定义读取excel
            List<Unit> unitsList = new ArrayList<>();
            for (Map<String, Object> map : list) {
                Set<String> keySet = map.keySet();
                Unit unit = new Unit();
                for (String string : keySet) {
                    String stt = (String) map.get(string);
                    String str = stt.trim();
                     if (string.equals("单位")) {
						unit.setUnit(str);
					}else if (string.equals("地区")) {
						unit.setRegin(str);
					}else if (string.equals("地域")) {
						unit.setReach(str);
					}else if (string.equals("情况说明")) {
						unit.setRemark(str);
					}
                }
                unit.setRegin(UtilTool.getRegin(unit.getRegin()));
                unit.setReach(UtilTool.getReach(unit.getRegin(), unit.getReach()));
                unitsList.add(unit);
            }
            
            
            //批量插入
            boolean i = unitService.saveBatch(unitsList);
            if (i) {
                log.info("数据导入成功");
                return JsonResult.success("数据导入成功");
            } else {
                log.error("数据导入失败!");
                return JsonResult.error(-1,"数据导入失败!");
            }
        } catch (Exception e) {
            log.error("数据导入出现异常:{}", e.getMessage());
            return JsonResult.error(-1,"数据导入失败,请检查模板数据格式!");
        }
    }
}

5、自定义读取excel 里面数据 (poi)


import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class ReadDataByExcel {
	public static List<Map<String, Object>> readExcel(InputStream inputStream) {
		List<Map<String, Object>> list = new ArrayList<>();
		try {
			XSSFWorkbook wb0 = new XSSFWorkbook(inputStream);
			// 循环Sheets,默认取0,第一个sheet
			// 获得Excel表的sheet的数目
			int numberOfSheets = wb0.getNumberOfSheets();
			for (int i = 0; i < numberOfSheets; i++) {
				//获取sheet工作表
				Sheet sheet = wb0.getSheetAt(i);
				//获取sheet中第一行行号,表头行  0
	    		int firstRowNum = sheet.getFirstRowNum();
	    		//获取最后一行行号 ,从0开始,20行  ==0---19
				int lastRowNum = sheet.getLastRowNum();
				// 获取表头数据行
				Row rowHead = sheet.getRow(firstRowNum);
				for (int j = firstRowNum; j < lastRowNum; j++) {  //表头不用参与遍历,所有循环少一次
					Row row = sheet.getRow(j + 1);//获取第二行
					if (rowHead!=null && !isRowEmpty(row)) {
						Map<String, Object> map = new LinkedHashMap<>();
						//rowHead.getLastCellNum()获取最后一个不为空的列是第几个 从0开始,比实际大一 如:10列==0--10
						//rowHead.getPhysicalNumberOfCells()获取不为空的列的个数
						for (int k = 0; k < rowHead.getLastCellNum(); k++) {
							// 获取表头和数据
							Cell cellHead = rowHead.getCell(k);
							Cell cell = row.getCell(k);
							String cellValue = null;
							String headValue = null;
							// 处理各种带空数据
							if(cellHead!=null) {
							headValue = cellHead.toString().trim().replaceAll(" ", "");
							}else {
							headValue="";	
							}
							if (cell != null && !cell.toString().trim().isEmpty()) {
								cellValue = cell.toString().trim().replaceAll(" ", "");
							} else {
								cellValue = "";
							}

							// map封装
							map.put(headValue, cellValue);
						}
						// list封装
						list.add(map);
					}
				}
			}
			try {
				inputStream.close();
			} catch (Exception e) {
				log.error("exception:", e);
			}
		} catch (Exception e) {
			log.error("exception:", e);
		}
		return list;
	}
	
	//判断表行是否为空
	public static boolean isRowEmpty(Row row) {
		for(int i = row.getFirstCellNum();i<row.getLastCellNum();i++) {
			Cell cell =row.getCell(i);
			if(cell!=null&&cell.getCellType()!=Cell.CELL_TYPE_BLANK) {
				return false;
			}		
		}
		return true;
	}

}

如果在读取excel数据的时候关于一大片的合并区域,poi只会返回左上角第一个cell的数据,其余的全都返回空

注意:
HSSFWorkbook:是操作Excel2003以前(包括2003)的版本,扩展名是.xls;

XSSFWorkbook:是操作Excel2007后的版本,扩展名是.xlsx;

SXSSFWorkbook:是操作Excel2007后的版本,扩展名是.xlsx;

当数据量超出65536条后,在使用HSSFWorkbook或XSSFWorkbook,程序会报OutOfMemoryError:Javaheap space;内存溢出错误。这时应该用SXSSFworkbook。

判断excel版本除了后缀判断,也可以使用一下方法判断

      /**
 * 优化excel类型判断
 * 注意可能会获取报错 getFileMagic() only operates on streams which support mark(int)
 * 原因InputStream中markSupported方法返回值为false造成的,BufferedInputStream中返回值是true,所以改为InputStream is = new BufferedInputStream(multipartFile.getInputStream())
 */
//InputStream is = new BufferedInputStream(multipartFile.getInputStream());
 FileMagic fileMagic = FileMagic.valueOf(inputStream);
 if (Objects.equals(fileMagic, FileMagic.OLE2)) {
            return EXCEL2003;
 } else if (Objects.equals(fileMagic, FileMagic.OOXML)) {
            return EXCEL2007;

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现 excel 数据导入功能,需要完成以下步骤: 1. 前端页面实现文件上传功能,可以使用 vue-upload-component 组件实现。 2. 后端使用 Spring Boot 框架,导入 poi 依赖,使用 poi 解析 Excel 文件,获取数据并保存到数据库中。 下面是具体的实现步骤: 1. 前端页面 在 vue 组件中,使用 vue-upload-component 组件实现文件上传功能。具体实现代码如下: ``` <template> <div> <input type="file" ref="file" @change="handleFileChange"> <button @click.prevent="submit">上传</button> </div> </template> <script> import UploadComponent from 'vue-upload-component' export default { components: { UploadComponent }, data () { return { file: null } }, methods: { handleFileChange () { this.file = this.$refs.file.files[0] }, submit () { const formData = new FormData() formData.append('file', this.file) this.$http.post('/upload', formData) .then(res => { console.log(res) }) .catch(err => { console.log(err) }) } } } </script> ``` 2. 后端实现 2.1 添加依赖 在 Spring Boot 项目的 pom.xml 文件中添加 poi 依赖: ``` <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.1.2</version> </dependency> ``` 2.2 实现文件上传接口 在 Spring Boot 项目中,实现文件上传的接口: ``` @PostMapping("/upload") public void upload(MultipartFile file) throws Exception { Workbook workbook = WorkbookFactory.create(file.getInputStream()); Sheet sheet = workbook.getSheetAt(0); List<Data> dataList = new ArrayList<>(); for (int i = 1; i <= sheet.getLastRowNum(); i++) { Row row = sheet.getRow(i); if (row == null) { continue; } Data data = new Data(); data.setName(row.getCell(0).getStringCellValue()); data.setAge((int) row.getCell(1).getNumericCellValue()); dataList.add(data); } dataRepository.saveAll(dataList); } ``` 其中,Data 是保存数据的实体类,dataRepository 是数据访问接口。 3. 完整示例 前端页面代码: ``` <template> <div> <input type="file" ref="file" @change="handleFileChange"> <button @click.prevent="submit">上传</button> </div> </template> <script> import UploadComponent from 'vue-upload-component' export default { components: { UploadComponent }, data () { return { file: null } }, methods: { handleFileChange () { this.file = this.$refs.file.files[0] }, submit () { const formData = new FormData() formData.append('file', this.file) this.$http.post('/upload', formData) .then(res => { console.log(res) }) .catch(err => { console.log(err) }) } } } </script> ``` 后端代码: ``` @RestController public class ExcelController { @Autowired private DataRepository dataRepository; @PostMapping("/upload") public void upload(MultipartFile file) throws Exception { Workbook workbook = WorkbookFactory.create(file.getInputStream()); Sheet sheet = workbook.getSheetAt(0); List<Data> dataList = new ArrayList<>(); for (int i = 1; i <= sheet.getLastRowNum(); i++) { Row row = sheet.getRow(i); if (row == null) { continue; } Data data = new Data(); data.setName(row.getCell(0).getStringCellValue()); data.setAge((int) row.getCell(1).getNumericCellValue()); dataList.add(data); } dataRepository.saveAll(dataList); } } @Entity public class Data { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private Integer age; // getter and setter } ``` 注意,需要在 application.properties 中配置数据库连接等信息。另外,需要在 Vue 项目中使用 axios 来发送请求。 这样,就完成了 Spring Boot + Vue 实现 excel 数据导入功能的示例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值