多個sheet Excel 數(shù)據(jù)導(dǎo)入數(shù)據(jù)庫的實現(xiàn)方法
多個sheet Excel 數(shù)據(jù) 導(dǎo)入數(shù)據(jù)庫 如何實現(xiàn)?
將 Excel 文件中的多個 sheet 導(dǎo)入數(shù)據(jù)庫,一般有以下幾種實現(xiàn)方式:
- 使用 JDBC 直接插入。可以使用 Java 的 JDBC 接口直接連接數(shù)據(jù)庫,然后讀取 Excel 文件中的數(shù)據(jù),并將數(shù)據(jù)插入到數(shù)據(jù)庫中。這種方式比較直接,但需要編寫大量的 JDBC 代碼,對 Excel 文件格式的支持也比較有限。
- 使用第三方庫。市面上有很多 Java 的第三方庫可以用來讀取 Excel 文件,如 Apache POI、JExcelAPI、EasyExcel 等。這些庫通常都提供了比較簡單易用的 API,可以方便地讀取 Excel 文件中的數(shù)據(jù),并將數(shù)據(jù)插入到數(shù)據(jù)庫中。
- 先將 Excel 文件轉(zhuǎn)換成 CSV 文件,再導(dǎo)入數(shù)據(jù)庫。Excel 文件可以先轉(zhuǎn)換成 CSV 文件,然后使用 JDBC 直接將數(shù)據(jù)插入到數(shù)據(jù)庫中。CSV 文件相對于 Excel 文件來說,結(jié)構(gòu)更加簡單,處理起來也更加方便。
無論使用哪種方式,都需要注意以下幾個問題:
Excel 文件格式的兼容性問題。不同版本的 Excel 文件可能存在格式差異,需要進(jìn)行測試和兼容性處理。
數(shù)據(jù)的類型和格式問題。Excel 文件中的數(shù)據(jù)類型和格式可能需要進(jìn)行轉(zhuǎn)換和處理,以適配數(shù)據(jù)庫中的數(shù)據(jù)類型和格式要求。
數(shù)據(jù)的一致性問題。如果 Excel 文件中的數(shù)據(jù)有重復(fù)或沖突,需要進(jìn)行處理,以保證數(shù)據(jù)的一致性和完整性。
綜上所述,將 Excel 文件中的多個 sheet 導(dǎo)入數(shù)據(jù)庫的實現(xiàn)方式有多種,具體使用哪種方式,還需要根據(jù)實際情況進(jìn)行評估和選擇。
傳統(tǒng)方式
處理 普通數(shù)據(jù)的 Excel 文件,需要考慮到內(nèi)存和性能的問題,以下是一個基于流式讀取和寫入的示例代碼:
// 獲取 Excel 文件輸入流
InputStream is = new BufferedInputStream(new FileInputStream(filePath));
Workbook workbook = WorkbookFactory.create(is);
// 遍歷每個 Sheet
for (int sheetIndex = 0; sheetIndex < workbook.getNumberOfSheets(); sheetIndex++) {
Sheet sheet = workbook.getSheetAt(sheetIndex);
String sheetName = sheet.getSheetName();
System.out.println("開始處理 Sheet:" + sheetName);
// 準(zhǔn)備寫入的輸出流
OutputStream os = new BufferedOutputStream(new FileOutputStream(outputDir + "/" + sheetName + ".xlsx"));
// 設(shè)置寫入的 Sheet 名稱
SXSSFWorkbook writer = new SXSSFWorkbook(new XSSFWorkbook(), 10000);
SXSSFSheet outSheet = writer.createSheet(sheetName);
// 讀取并寫入 Sheet 的標(biāo)題行
Row titleRow = sheet.getRow(0);
Row outTitleRow = outSheet.createRow(0);
for (int i = 0; i < titleRow.getLastCellNum(); i++) {
outTitleRow.createCell(i).setCellValue(titleRow.getCell(i).getStringCellValue());
}
// 逐行讀取并寫入數(shù)據(jù)
for (int i = 1; i <= sheet.getLastRowNum(); i++) {
Row row = sheet.getRow(i);
Row outRow = outSheet.createRow(i);
for (int j = 0; j < row.getLastCellNum(); j++) {
Cell cell = row.getCell(j);
if (cell != null) {
switch (cell.getCellType()) {
case BLANK:
outRow.createCell(j, CellType.BLANK);
break;
case BOOLEAN:
outRow.createCell(j, CellType.BOOLEAN).setCellValue(cell.getBooleanCellValue());
break;
case ERROR:
outRow.createCell(j, CellType.ERROR).setCellValue(cell.getErrorCellValue());
break;
case FORMULA:
outRow.createCell(j, CellType.FORMULA).setCellFormula(cell.getCellFormula());
break;
case NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {
outRow.createCell(j, CellType.NUMERIC).setCellValue(cell.getDateCellValue());
} else {
outRow.createCell(j, CellType.NUMERIC).setCellValue(cell.getNumericCellValue());
}
break;
case STRING:
outRow.createCell(j, CellType.STRING).setCellValue(cell.getStringCellValue());
break;
default:
outRow.createCell(j, CellType.BLANK);
break;
}
}
}
// 每隔 10000 行進(jìn)行一次緩存寫入
if (i % 10000 == 0) {
((SXSSFSheet) outSheet).flushRows();
}
}
// 最后寫入緩存的數(shù)據(jù)
writer.write(os);
os.flush();
os.close();
writer.dispose();
System.out.println("處理 Sheet:" + sheetName + " 完成");
}
// 關(guān)閉輸入流
is.close();
上述示例代碼使用了 Apache POI 的流式讀取和寫入方式,可以有效地處理大量數(shù)據(jù)。為了避免內(nèi)存溢出,采用了緩存寫入的方式,每隔一定數(shù)量的行進(jìn)行一次寫入操作。
Apache POI
使用 Apache POI 實現(xiàn)將 Excel 文件中的多個 sheet 導(dǎo)入到數(shù)據(jù)庫的 Java 代碼:
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
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;
public class ExcelImporter {
private static final String DB_URL = "jdbc:mysql://localhost:3306/mydatabase";
private static final String DB_USER = "myuser";
private static final String DB_PASSWORD = "mypassword";
private static final String INSERT_SQL = "INSERT INTO mytable (col1, col2, col3) VALUES (?, ?, ?)";
public static void main(String[] args) {
try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) {
FileInputStream file = new FileInputStream("myexcel.xlsx");
Workbook workbook = new XSSFWorkbook(file);
int numSheets = workbook.getNumberOfSheets();
for (int i = 0; i < numSheets; i++) {
Sheet sheet = workbook.getSheetAt(i);
for (Row row : sheet) {
String col1 = null;
String col2 = null;
int col3 = 0;
for (Cell cell : row) {
int columnIndex = cell.getColumnIndex();
switch (columnIndex) {
case 0:
col1 = cell.getStringCellValue();
break;
case 1:
col2 = cell.getStringCellValue();
break;
case 2:
col3 = (int) cell.getNumericCellValue();
break;
default:
// Ignore other columns
break;
}
}
PreparedStatement statement = conn.prepareStatement(INSERT_SQL);
statement.setString(1, col1);
statement.setString(2, col2);
statement.setInt(3, col3);
statement.executeUpdate();
}
}
System.out.println("Import successful");
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
在上面的代碼中,首先通過 FileInputStream 和 Workbook 對象讀取 Excel 文件中的數(shù)據(jù),然后通過 for 循環(huán)遍歷每個 sheet 和每行數(shù)據(jù),并將數(shù)據(jù)插入到數(shù)據(jù)庫中。在讀取單元格數(shù)據(jù)時,可以根據(jù)單元格的列索引和數(shù)據(jù)類型進(jìn)行類型轉(zhuǎn)換和賦值。最后通過 PreparedStatement 執(zhí)行 SQL 插入語句,將數(shù)據(jù)插入到數(shù)據(jù)庫中。
需要注意的是,上面的代碼只是一個簡單的示例,還需要根據(jù)實際情況進(jìn)行修改和完善,比如加入異常處理、事務(wù)管理等功能。
JExcelAPI
使用 JExcelAPI 實現(xiàn)將 Excel 文件中的多個 sheet 導(dǎo)入到數(shù)據(jù)庫的 Java 代碼:
import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;
public class ExcelImporter {
private static final String DB_URL = "jdbc:mysql://localhost:3306/mydatabase";
private static final String DB_USER = "myuser";
private static final String DB_PASSWORD = "mypassword";
private static final String INSERT_SQL = "INSERT INTO mytable (col1, col2, col3) VALUES (?, ?, ?)";
public static void main(String[] args) {
try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) {
Workbook workbook = Workbook.getWorkbook(new File("myexcel.xls"));
int numSheets = workbook.getNumberOfSheets();
for (int i = 0; i < numSheets; i++) {
Sheet sheet = workbook.getSheet(i);
for (int j = 1; j < sheet.getRows(); j++) {
String col1 = null;
String col2 = null;
int col3 = 0;
for (int k = 0; k < sheet.getColumns(); k++) {
Cell cell = sheet.getCell(k, j);
switch (k) {
case 0:
col1 = cell.getContents();
break;
case 1:
col2 = cell.getContents();
break;
case 2:
col3 = Integer.parseInt(cell.getContents());
break;
default:
// Ignore other columns
break;
}
}
PreparedStatement statement = conn.prepareStatement(INSERT_SQL);
statement.setString(1, col1);
statement.setString(2, col2);
statement.setInt(3, col3);
statement.executeUpdate();
}
}
System.out.println("Import successful");
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
在上面的代碼中,首先通過 Workbook 對象讀取 Excel 文件中的數(shù)據(jù),然后通過 for 循環(huán)遍歷每個 sheet 和每行數(shù)據(jù),并將數(shù)據(jù)插入到數(shù)據(jù)庫中。在讀取單元格數(shù)據(jù)時,可以根據(jù)單元格的行索引、列索引和數(shù)據(jù)類型進(jìn)行類型轉(zhuǎn)換和賦值。最后通過 PreparedStatement 執(zhí)行 SQL 插入語句,將數(shù)據(jù)插入到數(shù)據(jù)庫中。
需要注意的是,上面的代碼只是一個簡單的示例,還需要根據(jù)實際情況進(jìn)行修改和完善,比如加入異常處理、事務(wù)管理等功能。另外,JExcelAPI 只支持舊版的 .xls 格式,不支持 .xlsx 格式。
EasyExcel
使用 EasyExcel 實現(xiàn)將 Excel 文件中的多個 sheet 導(dǎo)入到數(shù)據(jù)庫的 Java 代碼:
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.metadata.Sheet;
import java.util.ArrayList;
import java.util.List;
public class ExcelImporter {
private static final String DB_URL = "jdbc:mysql://localhost:3306/mydatabase";
private static final String DB_USER = "myuser";
private static final String DB_PASSWORD = "mypassword";
private static final String INSERT_SQL = "INSERT INTO mytable (col1, col2, col3) VALUES (?, ?, ?)";
public static void main(String[] args) {
List<List<Object>> data = new ArrayList<>();
EasyExcel.read("myexcel.xlsx", new MyEventListener()).sheet().doRead();
try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) {
PreparedStatement statement = conn.prepareStatement(INSERT_SQL);
for (List<Object> row : data) {
statement.setString(1, (String) row.get(0));
statement.setString(2, (String) row.get(1));
statement.setInt(3, (Integer) row.get(2));
statement.addBatch();
}
statement.executeBatch();
System.out.println("Import successful");
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
static class MyEventListener extends AnalysisEventListener<Object> {
private List<Object> row = new ArrayList<>();
@Override
public void invoke(Object data, AnalysisContext context) {
row.add(data);
if (context.getCurrentRowNum() == 0) {
// Ignore the header row
row.clear();
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// Ignore
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// Ignore
}
}
}
在上面的代碼中,首先通過 EasyExcel 對象讀取 Excel 文件中的數(shù)據(jù),然后通過 AnalysisEventListener 監(jiān)聽器將每行數(shù)據(jù)存儲到一個 List 中,最后將 List 中的數(shù)據(jù)插入到數(shù)據(jù)庫中。需要注意的是,在處理每行數(shù)據(jù)時,需要根據(jù)數(shù)據(jù)類型進(jìn)行類型轉(zhuǎn)換和賦值。此外,EasyExcel 支持 .xlsx 和 .xls 格式的 Excel 文件,但由于 .xlsx 格式的文件在讀取時需要占用大量內(nèi)存,因此建議在處理大量數(shù)據(jù)時使用 .xls 格式。
需要注意的是,上面的代碼只是一個簡單的示例,還需要根據(jù)實際情況進(jìn)行修改和完善,比如加入異常處理、事務(wù)管理等功能。另外,EasyExcel 還提供了很多高級功能,比如讀取大量數(shù)據(jù)時的分頁讀取、讀取時的數(shù)據(jù)轉(zhuǎn)換和驗證等??梢愿鶕?jù)實際需求進(jìn)行使用。
總結(jié)
除了使用 Apache POI 和 EasyExcel 這兩個庫之外,還有其他的實現(xiàn)方式,比如:
使用 OpenCSV:OpenCSV 是一個輕量級的 CSV 格式文件讀寫庫,也支持讀寫 Excel 文件。與 Apache POI 相比,它的內(nèi)存占用更少,但功能相對較少。
使用 JExcelAPI:JExcelAPI 是一個老牌的 Java Excel 文件讀寫庫,也支持讀寫多個 sheet。與 Apache POI 相比,它的內(nèi)存占用更少,但功能相對較少。
使用 Excel Streaming Reader:Excel Streaming Reader 是一個基于 SAX 的 Excel 文件讀取庫,能夠高效地讀取大型 Excel 文件。與 Apache POI 相比,它的內(nèi)存占用更少,但功能相對較少。
使用 CSV 文件代替 Excel 文件:如果數(shù)據(jù)量不是很大,并且不需要使用 Excel 特有的功能,可以將 Excel 文件轉(zhuǎn)換為 CSV 格式文件,然后使用 OpenCSV 或其他的 CSV 文件讀寫庫進(jìn)行讀寫。
需要根據(jù)實際情況選擇合適的實現(xiàn)方式,綜合考慮內(nèi)存占用、性能、功能等因素。
結(jié)語
到此這篇關(guān)于多個sheet Excel 數(shù)據(jù)導(dǎo)入數(shù)據(jù)庫的實現(xiàn)方法的文章就介紹到這了,更多相關(guān)多個sheet Excel 數(shù)據(jù)導(dǎo)入數(shù)據(jù)庫內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java常用HASH算法總結(jié)【經(jīng)典實例】
這篇文章主要介紹了Java常用HASH算法,結(jié)合實例形式總結(jié)分析了Java常用的Hash算法,包括加法hash、旋轉(zhuǎn)hash、FNV算法、RS算法hash、PJW算法、ELF算法、BKDR算法、SDBM算法、DJB算法、DEK算法、AP算法等,需要的朋友可以參考下2017-09-09
手把手帶你分析SpringBoot自動裝配完成了Ribbon哪些核心操作
這篇文章主要介紹了詳解Spring Boot自動裝配Ribbon哪些核心操作的哪些操作,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-08-08
java 中使用maven shade plugin 打可執(zhí)行Jar包
這篇文章主要介紹了java 中使用maven shade plugin 打可執(zhí)行Jar包的相關(guān)資料,需要的朋友可以參考下2017-05-05
java 實現(xiàn)簡單圣誕樹的示例代碼(圣誕節(jié)快樂)
這篇文章主要介紹了java 實現(xiàn)簡單圣誕樹的示例代碼(圣誕節(jié)快樂),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12

