Apache POI是用Java编写的免费开源的跨平台的Java API,Apache POI提供API给Java程序对Microsoft Office格式档案读和写的功能,其中使用最多的就是使用POI操作Excel文件。
POI结构:
HSSF - 提供读写Microsoft Excel XLS格式档案的功能 XSSF - 提供读写Microsoft Excel OOXML XLSX格式档案的功能(我们使用) HWPF - 提供读写Microsoft Word DOC格式档案的功能 HSLF - 提供读写Microsoft PowerPoint格式档案的功能 HDGF - 提供读Microsoft Visio格式档案的功能 HPBF - 提供读Microsoft Publisher格式档案的功能 HSMF - 提供读Microsoft Outlook格式档案的功能 HSSFWorkbook hk = new HSSFWorkbook();// XLS XSSFWorkbook xk = new XSSFWorkBook();//XLSX我们使用:XSSF - 提供读写Microsoft Excel OOXML XLSX格式档案的功能
POI操作Excel表格封装了几个核心对象:
XSSFWorkbook:工作簿
XSSFSheet:工作表
XSSFRow:行
XSSFCell:单元格
Apache POI批量导入预约设置操作Excel文件
批量导入预约设置信息操作过程:
第一步、点击模板下载按钮下载Excel模板文件【文件下载】
第二步、将预约设置信息录入到模板文件中
第三步、点击上传文件按钮将录入完信息的模板文件上传到服务器【文件上传】
第四步、通过POI读取上传文件的数据并保存到数据库【poi导入】
1.maven依赖坐标
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.14</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.14</version>
</dependency>
2.POJO类
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 预约设置
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class OrderSetting implements Serializable{
private Integer id ;
private Date orderDate; //预约设置日期
private int number; //可预约人数
private int reservations; //已预约人数
}
3.POIUtils 工具类
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
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.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;
//POIUtils 工具类
public class POIUtils {
private final static String xls = "xls";
private final static String xlsx = "xlsx";
public final static String DATE_FORMAT = "yyyy/MM/dd";
/**
* 读入excel文件,解析后返回
* @param file
* @throws IOException
* return List<String[]> List<每行的数据>
*/
public static List<String[]> readExcel(MultipartFile file) throws IOException {
//检查文件
checkFile(file);
//获得Workbook工作薄对象
Workbook workbook = getWorkBook(file);
//创建返回对象,把每行中的值作为一个数组,所有行作为一个集合返回
List<String[]> list = new ArrayList<String[]>();
if(workbook != null){
//getNumberOfSheets 共有多个工作表
for(int sheetNum = 0;sheetNum < workbook.getNumberOfSheets();sheetNum++){
//获得当前sheet工作表
Sheet sheet = workbook.getSheetAt(sheetNum);
if(sheet == null){
//跳过,执行下一个循环
continue;
}
//获得当前sheet的开始行
int firstRowNum = sheet.getFirstRowNum();
//获得当前sheet的结束行
int lastRowNum = sheet.getLastRowNum();
//循环除了第一行的所有行
for(int rowNum = firstRowNum+1;rowNum <= lastRowNum;rowNum++){
//获得当前行
Row row = sheet.getRow(rowNum);
if(row == null){
continue;
}
//获得当前行的开始列
int firstCellNum = row.getFirstCellNum();
//获得当前行的列数
int lastCellNum = row.getPhysicalNumberOfCells();
String[] cells = new String[row.getPhysicalNumberOfCells()];
//循环当前行
for(int cellNum = firstCellNum; cellNum < lastCellNum;cellNum++){
Cell cell = row.getCell(cellNum);
cells[cellNum] = getCellValue(cell);
}
list.add(cells);
}
}
workbook.close();
}
return list;
}
//校验文件是否合法
public static void checkFile(MultipartFile file) throws IOException{
//判断文件是否存在
if(null == file){
throw new FileNotFoundException("文件不存在!");
}
//获得文件名
String fileName = file.getOriginalFilename().toLowerCase();
//判断文件是否是excel文件
if(!fileName.endsWith(xls) && !fileName.endsWith(xlsx)){
throw new IOException(fileName + "不是excel文件");
}
}
public static Workbook getWorkBook(MultipartFile file) {
//获得文件名
String fileName = file.getOriginalFilename();
//创建Workbook工作薄对象,表示整个excel
Workbook workbook = null;
try {
//获取excel文件的io流
InputStream is = file.getInputStream();
//根据文件后缀名不同(xls和xlsx)获得不同的Workbook实现类对象
if(fileName.endsWith(xls)){
//2003
workbook = new HSSFWorkbook(is);
}else if(fileName.endsWith(xlsx)){
//2007
workbook = new XSSFWorkbook(is);
}
} catch (IOException e) {
e.printStackTrace();
}
return workbook;
}
public static String getCellValue(Cell cell){
String cellValue = "";
if(cell == null){
return cellValue;
}
//如果当前单元格内容为日期类型,需要特殊处理
String dataFormatString = cell.getCellStyle().getDataFormatString();
if(dataFormatString.equals("m/d/yy")){
cellValue = new SimpleDateFormat(DATE_FORMAT).format(cell.getDateCellValue());
return cellValue;
}
//把数字当成String来读,避免出现1读成1.0的情况
if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC){
cell.setCellType(Cell.CELL_TYPE_STRING);
}
//判断数据的类型
switch (cell.getCellType()){
case Cell.CELL_TYPE_NUMERIC: //数字
cellValue = String.valueOf(cell.getNumericCellValue());
break;
case Cell.CELL_TYPE_STRING: //字符串
cellValue = String.valueOf(cell.getStringCellValue());
break;
case Cell.CELL_TYPE_BOOLEAN: //Boolean
cellValue = String.valueOf(cell.getBooleanCellValue());
break;
case Cell.CELL_TYPE_FORMULA: //公式
cellValue = String.valueOf(cell.getCellFormula());
break;
case Cell.CELL_TYPE_BLANK: //空值
cellValue = "";
break;
case Cell.CELL_TYPE_ERROR: //故障
cellValue = "非法字符";
break;
default:
cellValue = "未知类型";
break;
}
return cellValue;
}
}
4.Controller层:批量导入预约设置
private static final Logger log = LoggerFactory.getLogger(OrderSettingController.class);
@Autowired
private OrderSettingService orderSettingService;
/**
* 批量导入预约设置
* @param excelFile
* @return
*/
@PostMapping("/upload")
public Result upload(MultipartFile excelFile){
//1. POIUtils读取excel内容
try {
List<String[]> dataList = POIUtils.readExcel(excelFile);
// 【注意取反!】如果dataList集合不为空,且dataList有值
if(!CollectionUtils.isEmpty(dataList)) {
//2. List<String[]> 转成List<OrderSetting>
List<OrderSetting> osList = new ArrayList<>();
SimpleDateFormat sdf = new SimpleDateFormat(POIUtils.DATE_FORMAT);
for (String[] stringArr : dataList) {
//0: 日期
String orderDateStr = stringArr[0];
//1: 可预约数量
Integer number = Integer.valueOf(stringArr[1]);
OrderSetting os = new OrderSetting();
os.setNumber(number);
// 要转成日期类型
os.setOrderDate(sdf.parse(orderDateStr));
// 加入到list
osList.add(os);
}
//3. 调用业务,batchImport批量导入
orderSettingService.batchImport(osList);
//4. 返回成功
return new Result(true, MessageConstant.IMPORT_ORDERSETTING_SUCCESS);
}
} catch (Exception e) {
log.error("批量导入预约设置失败", e);
}
return new Result(false, MessageConstant.IMPORT_ORDERSETTING_FAIL);
}
5.Service层:接口
import com.itheima.pojo.OrderSetting;
import java.util.List;
/**
* 预约设置业务层接口
*/
public interface OrderSettingService {
/**
* 往预约设置表 批量预约设置(保存数据)
* @param orderSettingList
*/
void batchImport(List<OrderSetting> orderSettingList);
}
6.Service层:接口的实现类
@Service
@Transactional
public class OrderSettingServiceImpl implements OrderSettingService {
@Autowired
private OrderSettingDao orderSettingDao;
/**
* 往预约设置表 批量预约设置(保存数据)
* @param orderSettingList
*/
@Override
public void batchImport(List<OrderSetting> orderSettingList) {
//1 循环遍历预约设置数据
if (!CollectionUtils.isEmpty(orderSettingList)) {
for (OrderSetting orderSetting : orderSettingList) {
//2 根据预约日期查询t_ordersetting表记录是否存在
Date orderDate = orderSetting.getOrderDate();
int count = orderSettingDao.findCountByOrderDate(orderDate);
//3 存在 根据预约日期更新最大可预约人数
if(count>0){
orderSettingDao.updateNumberByOrderDate(orderSetting);
}else {
//4 不存在 直接保存预约数据
orderSettingDao.add(orderSetting);
}
}
}
}
}
7.dao层
import com.pojo.OrderSetting;
import java.util.Date;
/**
* 预约设置持久层接口
*/
public interface OrderSettingDao {
/**
*根据预约日期查询t_ordersetting表记录是否存在
* @param orderDate
* @return
*/
int findCountByOrderDate(Date orderDate);
/**
*根据预约日期更新最大可预约人数
* @param orderSetting
*/
void updateNumberByOrderDate(OrderSetting orderSetting);
/**
* 直接保存预约数据
* @param orderSetting
*/
void add(OrderSetting orderSetting);
}
8.Mapper映射文件:OrderSettingDao.xml并提供相关SQL
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dao.OrderSettingDao">
<!-- jdbcType=DATE 指定mybatis操作数据库时使用的数据类型DATE, 因为人家类型就是DATE,
如果不指定,mybatis默认使用timestamp(带时分秒), 如果时分秒不为0,则会导致查询不到记录 -->
<select id="findByOrderDate" parameterType="date" resultType="OrderSetting">
select * from t_ordersetting where orderDate=#{orderDate, jdbcType=DATE}
</select>
<insert id="add" parameterType="orderSetting">
insert into t_ordersetting(orderDate, number, reservations)
values(#{orderDate, jdbcType=DATE},#{number},#{reservations})
</insert>
<update id="updateNumber" parameterType="ordersetting">
update t_ordersetting
set number=#{number}
where orderDate=#{orderDate, jdbcType=DATE}
</update>
</mapper>
版权声明:本文为m0_61601521原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。