前言
·场景:需要将excel中的数据导入到oracle数据库中
·问题:虽然PL/SQL中有一个ODBC import工具可以实现场景中描述的需求,但是如果excel中存在合并单元格
的情况存在或者空行
等情况,该工具就不是特别的好用,需要自己提前手动处理好excel文件
·需要解决:
- 1.自动识别和填充合并单元格的内容 (代码核心价值)
- 2.识别空行并将之排除
- 3.将数据插入到指定数据库
代码实现
/**
* 用于将excle表中得数据插入到指定数据库中
* 前提条件:指定好excel文件路径,sheet表名称,数据库信息(表名称,连接地址,账号密码)
* 输出:数据将插入到指定得表中
* 存在价值:可以解决excel表中合并单元格得问题 会自动识别和填充合并单元格中每格得内容
* 注意:如果整行为空 将不插入数据库
*/
public class ExcelJDBC {
private static String oracleTable; //插入得表名称
private static String sheetName; //sheet表名称
private static String oracleUrl; //连接地址
private static String user; //用户名
private static String passWord; //密码
private static String excelPath; //excel文件路径
public ExcelJDBC(String p_oracleTable,String p_sheetName,String p_oracleUrl,String p_user,String p_passWord,String p_excelPath){
this.oracleTable = p_oracleTable;
this.sheetName = p_sheetName;
this.oracleUrl = p_oracleUrl;
this.user = p_user;
this.passWord = p_passWord;
this.excelPath = p_excelPath;
}
//总的一个执行逻辑方法
public void excelDeal() throws SQLException, IOException {
File xlsFile = new File(excelPath);//excel路径
// 获得工作簿
Workbook workbook = WorkbookFactory.create(xlsFile);
// 获得工作表个数
int sheetCount = workbook.getNumberOfSheets();
// 获取工作表
Sheet sheet = workbook.getSheet(sheetName);
// 获得行数
int rows = sheet.getLastRowNum() + 1;
// 获得列数,先获得一行,再得到该行列数
org.apache.poi.ss.usermodel.Row tmp = sheet.getRow(0);
if (tmp == null) {
System.out.println("首行没有数据");
return;
}
int cols = (tmp).getPhysicalNumberOfCells();//获取列数
String[][] cellsTemp = new String[rows][cols];//用于保存数据
// 读取数据
for (int row = 1; row < rows; row++) {
org.apache.poi.ss.usermodel.Row r = sheet.getRow(row);
for (int col = 0; col < cols; col++) {
//判断是否为合并单元格
Result resultTemp = isMergedRegion(sheet, row, col);
//获取单元格内容
String content = r.getCell(col) == null ? "" : r.getCell(col).toString();
//如果这个单元格是合并单元格且没有被赋值 则说明这个单元格是第一个
if (resultTemp.merged) {
String sTemp = cellsTemp[row][col];
//不等于null则说明这个是合并单元格 且已经被附过值
if (sTemp != null) {
continue;
}
//获取合并的行数和列数
int colnum = resultTemp.endCol - resultTemp.startCol;
int rownum = resultTemp.endRow - resultTemp.startRow;
//这个不等于0 则说明是向下合并单元格
if (colnum != 0) {
for (int j = 0; j <= colnum; j++) {
cellsTemp[row][col + j] = content;
}
}
//这个不等于0 则说明横向合并单元格
if (rownum != 0) {
for (int j = 0; j <= rownum; j++) {
cellsTemp[row + j][col] = content;
}
}
//如果都不为0 那么就说明跨行跨列合并单元格
if (colnum != 0 && rownum != 0) {
for (int j = 1; j <= colnum; j++) {
for (int p = 1; p <= rownum; p++) {
cellsTemp[row + p][col + j] = content;
}
}
}
} else {
cellsTemp[row][col] = content;
}
}
}
//控制台打印出数据
//printData(cellsTemp);
//执行sql,将数据插入到数据库
StringBuilder sb = runSql(cellsTemp);
System.out.println("未成功执行数据为:" + sb.toString());
System.out.println("操作结束");
}
//region 以下为被调用的方法
/**
* 打印数据
* @param p_Data data
*/
public static void printData(String[][] p_Data){
for (int k = 0; k < p_Data.length; k++){
for (int q = 0; q < p_Data[k].length; q++){
System.out.printf("%10s", p_Data[k][q]);
}
System.out.println();
}
}
/**
* 判断是否为合并单元格
* @param sheet 表
* @param row 所在行
* @param column 所在列
* @return
*/
private static Result isMergedRegion(Sheet sheet, int row, int column) {
int sheetMergeCount = sheet.getNumMergedRegions();
for (int i = 0; i < sheetMergeCount; i++) {
CellRangeAddress range = sheet.getMergedRegion(i);
int firstColumn = range.getFirstColumn();
int lastColumn = range.getLastColumn();
int firstRow = range.getFirstRow();
int lastRow = range.getLastRow();
if (row >= firstRow && row <= lastRow) {
if (column >= firstColumn && column <= lastColumn) {
return new Result(true, firstRow + 1, lastRow + 1, firstColumn + 1, lastColumn + 1);
}
}
}
return new Result(false, 0, 0, 0, 0);
}
/**
* 获取oracle数据库连接
* @return
*/
public static Connection getConnection() {
Connection connection = null;// 创建一个数据库连接
try
{
// 加载Oracle驱动程序
Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
System.out.println("开始尝试连接数据库!");
String url = "jdbc:oracle:thin:@" + oracleUrl;//Oracle的默认数据库名
connection = DriverManager.getConnection(url, user, passWord);// 获取连接
System.out.println("数据库连接成功!");
return connection;
}
catch (Exception e)
{
e.printStackTrace();
return null;
}
}
/**
* 拼接并执行sql语句
* @param p_Data
* @return 执行异常的sql语句
*/
public static StringBuilder runSql(String[][] p_Data) throws SQLException {
List<String> sqlList = new ArrayList<>();
StringBuilder errorSql = new StringBuilder();
for (int k = 0; k < p_Data.length; k++){
String _value = "";
int emptyNum = 0;//一行中含有空值得数量
for (int q = 0; q < p_Data[k].length; q++){
_value += "'" + p_Data[k][q] + "',";
if(p_Data[k][q] == null || p_Data[k][q] == "") emptyNum++;
}
_value = _value.substring(0,_value.lastIndexOf(","));
if(emptyNum == p_Data[k].length) continue;//如果整行为空 则不进行插入动作
sqlList.add("insert into " + oracleTable + " values(" + _value + ")");
}
Connection con = getConnection();
for (String s:
sqlList) {
Statement statement = con.createStatement();
int modifyNum = statement.executeUpdate(s);
if(modifyNum == 0){
errorSql.append(s);
}
System.out.println("成功执行得sql语句为:" + s);
}
return errorSql;
}
/**
* 内部类
*/
static class Result{
public boolean merged;//是否为合并单元格 true-shi,false-fou
public int startRow;//开始的行
public int endRow;//结束的行
public int startCol;//开始的列
public int endCol;//结束的列
public Result(boolean merged,int startRow,int endRow
,int startCol,int endCol){
this.merged = merged;
this.startRow = startRow;
this.endRow = endRow;
this.startCol = startCol;
this.endCol = endCol;
}
}
//endregion
}
使用方法:
1.声明类对象ExcelJDBC
2.调用方法excelDeal
即可
示例如下:
public static void main(String args[]) throws IOException, SQLException {
//region 以下内容需要使用者根据实际情况进行更改
String oracleTable = "tableName";//插入得表名称,例:HANTEST
String sheetName = "sheetName";//sheet表名称,例:Sheet1
String oracleUrl = "ip:port:dataName";//数据库连接地址,例:127.0.0.1:1521:orcl
String user = "ueserName";//数据库用户名,例:root
String passWord = "passWord";//数据库密码,例:root123
String excelPath = "excelPath";//excel文件路径,例:D:\\Han\\test.xlsx
//endregion
//声明对象 传入参数
ExcelJDBC excelJDBC = new ExcelJDBC(oracleTable,sheetName,oracleUrl,user,passWord,excelPath);
调用方法 执行操作
excelJDBC.excelDeal();
}
实际使用效果对比
使用的excel表格结构:
数据库原始表结构:
使用PL/SQL的ODBC import工具的数据库导入效果:
使用
上述程序数据库导入效果:
结语
由于在工作中接到相关的任务,在手动导入数据时十分痛苦。故写了上述程序以此来解放劳动力,时间上耗时5H左右。所以会在代码规范,程序性能的方面上有些纰漏,望读者在使用的过程中可以根据实际来自我优化。
这篇文章适用于希望快速解决问题人群,避免重复造轮子。
转载请备明出处,LOVE & PEACE ! — By HAN
今天的文章Java实现将Excel中的数据导入到oracle数据库中分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:http://bianchenghao.cn/23015.html