《RabbitMQ》《Spring》《SpringMVC》《项目实战》
文章目录
- 前言
- 一、EasyExcel转CSV
- 二、分割建表入库
- 总结
前言
本文主要介绍使用EasyExcel读取Excel内数据并转换为csv格式数据(String字符串),然后实现字符串分割,分割出属性名和属性值建表插入MySQL数据库中。
一、EasyExcel转CSV
使用EasyExcel读取Excel文件,转换为csv数据,也就是转化为一个字符串。
工具类:
/**
* @Version: 1.0.0
* @Author: Dragon_王
* @ClassName: ExcelUtils
* @Description: Excel相关工具类
* @Date: 2024/3/9 11:24
*/
import cn.hutool.core.collection.CollUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* Excel 相关工具类
*/
@Slf4j
public class ExcelUtils {
/**
* excel 转 csv
*
* @param multipartFile
* @return
*/
public static String excelToCsv(MultipartFile multipartFile) {
// 读取数据
List<Map<Integer, String>> list = null;
try {
list = EasyExcel.read(multipartFile.getInputStream()).excelType(ExcelTypeEnum.XLSX).sheet().headRowNumber(0).doReadSync();
} catch (IOException e) {
log.error("表格处理错误", e);
}
if (CollUtil.isEmpty(list)) {
return "";
}
// 转换为 csv
StringBuilder stringBuilder = new StringBuilder();
// 读取表头
LinkedHashMap<Integer, String> headerMap = (LinkedHashMap) list.get(0);
List<String> headerList = headerMap.values().stream().filter(ObjectUtils::isNotEmpty).collect(Collectors.toList());
stringBuilder.append(StringUtils.join(headerList, ",")).append("\n");
// 读取数据
for (int i = 1; i < list.size(); i++) {
LinkedHashMap<Integer, String> dataMap = (LinkedHashMap) list.get(i);
List<String> dataList = dataMap.values().stream().filter(ObjectUtils::isNotEmpty).collect(Collectors.toList());
stringBuilder.append(StringUtils.join(dataList, ",")).append("\n");
}
return stringBuilder.toString();
}
}
实际运用中,只需要如下调用:
//传入的是Excel文件,不是路径哦
ExcelUtils.excelToCsv(Excel文件);
Excel文件格式如下:
读取的数据如下格式(这里我用加号拼接更清晰,实际上就是一个包含换行符的字符串,并不包含+号):
"日期,阅读量\n" +
"3,253\n" +
"4,408\n" +
"5,363\n" +
"6,955\n" +
"7,496\n" +
"8,1310\n" +
"9,748";
二、分割建表入库
- 将获取的csv数据,其实这里就是一个String字符串,记住现在是字符串不是数组。
- 首先我们分析一下,如何从字符串从分割出属性名(日期、阅读量)以及插入表中的每行属性值(3 253;4 408…):
- 找出第一个换行符(\n)的位置index,然后从第一位切割到index,这时候就得到属性名的字符串。再以英文逗号为分割符进行分割,得到属性名数组。
- 从index切割到字符串最后的位置就是全部属性值,那么如何分割得到每行的属性值呢?同样以换行符为分割符进行分割得到每行属性值的数组。(这里注意一下,数组中的每个元素是一个包含一行值的字符串,如:“3,253”)
- 分割得到的属性值数组内的每个元素再以英文逗号为分割符进行分割得到每行属性值,如"3"和"253"
- 最后根据属性名和属性值动态构建sql语句进行创建表,插入值的操作。
分割csv数据并调用自定义建表和插入函数:
//定义表名
String tableName = "test";
//获取第一个换行符的索引
int index = csvData.indexOf("\n");
//分割出属性名字符串,如"日期,阅读量"
String colum = csvData.substring(0,index);
//得到属性名数组,如{"日期","阅读量"}
String[] colums = colum.split(",");
//得到全部属性值字符串,如"3,253\n4,408\n5,363\n6,955\n7,496\n8,1310\n9,748"
String data = csvData.substring(index).trim();
//得到全部属性值数组,如:{"3,253","4,408","5,363""6,955".......}
String[] split_data = data.split("\n");
//调用建表
tableCreationUtils.createTable(tableName,colums);
//调用插入
tableCreationUtils.Dynamicinsert(tableName,colums,split_data);
动态构造建表sql和插入sql工具类:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;
import java.sql.SQLException;
/**
* 构建生成表sql
*
* @version 1.0.0
* @Author: dragon_王
* @Date: 2024/3/11 20:45:16
*/
@Component
public class TableCreationUtils {
private final JdbcTemplate jdbcTemplate;
@Autowired
public TableCreationUtils(DataSource dataSource){
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
/**
* 动态构建创建表的sql语句并执行
*
* @param tableName 表名字符串
* @param columnNames 属性名数组
* @return: void
* @Date: 2024-03-13 23:23:36
*/
public void createTable(String tableName, String[] columnNames) {
String sql = "CREATE TABLE " + tableName + " (";
for (int i = 0; i < columnNames.length; i++) {
sql += columnNames[i] + " VARCHAR(255)";
if (i < columnNames.length - 1) {
sql += ", ";
}
}
sql += ");";
jdbcTemplate.execute(sql);
}
/**
* 动态构建插入sql语句并执行
*
* @param tableName 表名字符串
* @param columnName 属性名数组,如{"日期","阅读"}
* @param rowData 属性值数组,如{"3,253","4,408","5,363""6,955".......}
* @return: void
* @Date: 2024-03-13 23:24:09
*/
public void Dynamicinsert(String tableName, String[] columnName,String[] rowData) throws SQLException {
//属性值为空就抛出异常
if (rowData == null || rowData.length == 0) {
throw new IllegalArgumentException("Row data must not be null or empty");
}
for (int i = 0;i < rowData.length;i++){
//传进来的是所有属性值数组,如:{"3,253","4,408","5,363""6,955".......}
//所以以将每个元素取出以英文逗号分割,得到插入的每行元素如["3","253"]
String[] row = rowData[i].split(",");
// 构建占位符
StringBuilder columnNames = new StringBuilder();
StringBuilder placeholders = new StringBuilder();
for (int j = 0; j < row.length; j++) {
if (j > 0) {
columnNames.append(", ");
placeholders.append(", ");
}
columnNames.append(columnName[j]);
placeholders.append("?"); // 使用?作为PreparedStatement的占位符
}
// 构建完整的SQL语句
String sql = "INSERT INTO " + tableName + " (" + columnNames + ") VALUES (" + placeholders + ")";
// 使用JdbcTemplate执行插入操作,如第一次循环:insert into tablename (日期,阅读) values (?,?)
//row:["3","253"]
jdbcTemplate.update(sql,row);
}
}
}
上面代码有以上面EXcel数据为例子的详细讲解,我就不再赘诉,很简单的思路。
总结
以上就是使用EasyExcel读取Excel内数据并转换为csv格式数据(String字符串),然后实现字符串分割,分割出属性名和属性值建表插入MySQL数据库中的详细讲解。