詳解java封裝實(shí)現(xiàn)Excel建表讀寫操作
對(duì) Excel 進(jìn)行讀寫操作是生產(chǎn)環(huán)境下常見的業(yè)務(wù),網(wǎng)上搜索的實(shí)現(xiàn)方式都是基于POI和JXL第三方框架,但都不是很全面。小編由于這兩天剛好需要用到,于是就參考手寫了一個(gè)封裝操作工具,基本涵蓋了Excel表(分有表頭和無表頭)的創(chuàng)建,并對(duì)它們進(jìn)行讀寫操作。為方便大家,有需要者可以點(diǎn)擊文后點(diǎn)解下載直接使用哦,當(dāng)然也可以根據(jù)自己需求舉一反三自己定制,相信對(duì)于聰明的你也不是什么難事。話不多說,直接貼源碼
pom.xml 文件:
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.17</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.8.0-beta2</version> <scope>test</scope> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.8.0-beta2</version> </dependency> </dependencies>
建表工具類:ExcelBuider.java
/**
* 建表工具類
* @author Sherman
* email:1253950375@qq.com
* created in 2018/8/24
*/
@Slf4j
public class ExcelBuilder {
private static HSSFSheet sheet;
private static HSSFWorkbook wb;
private static boolean hasHeader;
/**
* 初始化
* @param excellName 表名
*/
public ExcelBuilder(String excellName) {
wb = new HSSFWorkbook();
sheet = wb.createSheet(excellName);
}
/**
* 設(shè)置表頭,裝配表頭數(shù)據(jù)
* @param value 字符串?dāng)?shù)組,用來作為表頭的值
*
*/
public ExcelBuilder header(String... value) {
if (value != null && value.length != 0) {
//設(shè)置表頭樣式
HSSFCellStyle cellStyle = wb.createCellStyle();
cellStyle.setFont(font("黑體", true, 12));
HSSFRow row = sheet.createRow(0);
for (int i = 0; i < value.length; i++) {
HSSFCell cell = row.createCell(i);
cell.setCellValue(value[i]);
cell.setCellStyle(cellStyle);
}
hasHeader = true;
}
return this;
}
/**
* excel 表內(nèi)容裝配
* @param content 待裝配表格內(nèi)容的二維數(shù)組
* @return
*/
public ExcelBuilder content(List<List<Object>> content) {
if (content != null && !content.isEmpty()) {
int index;
for (int i = 0; i < content.size(); i++) {
index = hasHeader == false ? i : i + 1;
HSSFRow row = sheet.createRow(index);
for (int j = 0; j < content.get(i).size(); j++) {
String r = "";
Object value = content.get(i).get(j);
//根據(jù)數(shù)據(jù)類型裝配
if (value instanceof String) {
r = (String) value;
} else if (value instanceof Number) {
r = String.valueOf(value);
} else if (value instanceof BigDecimal) {
r = String.valueOf(value);
} else {
if (!(value instanceof Date) && !(value instanceof Timestamp)) {
if (!(value instanceof ZonedDateTime) && !(value instanceof LocalDateTime)) {
if (value instanceof Enum) {
r = ((Enum) value).name();
} else if (value != null) {
log.info("Error of create row, Unknow field type: " + value.getClass().getName());
}
} else {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
r = formatter.format((TemporalAccessor) value);
}
} else {
DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
r = sdf.format(value);
}
}
row.createCell(j).setCellValue(r);
}
}
}
return this;
}
/**
* 自動(dòng)調(diào)整列寬大小
*/
public ExcelBuilder autoColumnWidth() {
for (int j = 0; j < sheet.getRow(0).getLastCellNum(); j++) {
int maxLength = 0;
for (int i = 0; i <= sheet.getLastRowNum(); i++) {
String value = sheet.getRow(i).getCell(j).getStringCellValue();
int length = 0;
if (value != null) {
length = value.getBytes().length;
}
if (length > maxLength) {
maxLength = length;
}
}
sheet.setColumnWidth(j, maxLength > 30 ? (30 * 256 + 186) : (maxLength * 256 + 186));
}
return this;
}
/**
* 實(shí)例化
* @param hasHeader 是否有表頭
* @return Excel表格
*/
public AbstractExcel build(Boolean hasHeader) {
return hasHeader ? new HeaderExcel(sheet) : new NoHeaderExcel(sheet);
}
/**
*
* @param fontName 字體名字
* @param isBold 是否粗體
* @param fontSize 字體大小
* @return 字體
*/
private HSSFFont font(String fontName, boolean isBold, int fontSize) {
HSSFFont font = wb.createFont();
if (fontName != null) font.setFontName(fontName);
else font.setFontName("黑體");
font.setBold(isBold);
font.setFontHeightInPoints((short) fontSize);
return font;
}
}
excel的抽象父類:
/**
* @author Sherman
* created in 2018/8/24
*/
public abstract class AbstractExcel {
private final HSSFSheet sheet;
public AbstractExcel() {
HSSFWorkbook wb = new HSSFWorkbook();
sheet = wb.createSheet();
}
public AbstractExcel(String sheetName){
HSSFWorkbook wb = new HSSFWorkbook();
sheet = wb.createSheet(sheetName);
}
public AbstractExcel(HSSFSheet sheet) {
this.sheet = sheet;
}
public abstract List<Map<String, String>> getPayload();
public void write(OutputStream op) throws IOException {
sheet.getWorkbook().write(op);
sheet.getWorkbook().close();
}
public String getStringFormatCellValue(HSSFCell cell) {
String cellVal = "";
DecimalFormat df = new DecimalFormat("#");
switch (cell.getCellTypeEnum()) {
case STRING:
cellVal = cell.getStringCellValue();
break;
case NUMERIC:
String dataFormat = cell.getCellStyle().getDataFormatString();
if (DateUtil.isCellDateFormatted(cell)) {
cellVal = df.format(cell.getDateCellValue());
} else if ("@".equals(dataFormat)) {
cellVal = df.format(cell.getNumericCellValue());
} else {
cellVal = String.valueOf(cell.getNumericCellValue());
df = new DecimalFormat("#.#########");
cellVal = df.format(Double.valueOf(cellVal));
}
break;
case BOOLEAN:
cellVal = String.valueOf(cell.getBooleanCellValue());
break;
case FORMULA:
cellVal = String.valueOf(cell.getCellFormula());
break;
default:
cellVal = "";
}
return cellVal;
}
}
有表頭實(shí)現(xiàn)類
/**
* @author Sherman
* created in 2018/8/24
*/
public class HeaderExcel extends AbstractExcel {
private final static boolean hasHeader = true;
private final HSSFSheet sheet;
public HeaderExcel(HSSFSheet sheet) {
super(sheet);
this.sheet = sheet;
}
public HeaderExcel(String sheetName, String excelPath) {
HSSFWorkbook wb = null;
try {
wb = new HSSFWorkbook(new POIFSFileSystem(new FileInputStream(excelPath)));
} catch (IOException e) {
e.printStackTrace();
}
sheet = sheetName == null || sheetName.isEmpty() ? wb.getSheetAt(0) : wb.getSheet(sheetName);
}
@Override
public List<Map<String, String>> getPayload() {
List<Map<String, String>> payLoad = new ArrayList<>();
HSSFRow headRow = sheet.getRow(0);
for (int i = 1; i <= sheet.getLastRowNum(); i++) {
HSSFRow currentRow = sheet.getRow(i);
Map<String, String> map = new HashMap<>();
for (int j = 0; j < sheet.getRow(i).getLastCellNum(); j++) {
map.put(getStringFormatCellValue(headRow.getCell(j)), getStringFormatCellValue(currentRow.getCell(j)));
}
payLoad.add(map);
}
return payLoad;
}
}
無表頭實(shí)現(xiàn)類
/**
* @author Sherman
* created in 2018/8/24
*/
public class NoHeaderExcel extends AbstractExcel {
private final static boolean hasHeader = false;
private HSSFSheet sheet;
public NoHeaderExcel(HSSFSheet sheet) {
super(sheet);
this.sheet = sheet;
}
public NoHeaderExcel(String sheetName, String excelPath) {
HSSFWorkbook wb = null;
try {
wb = new HSSFWorkbook(new POIFSFileSystem(new FileInputStream(excelPath)));
} catch (IOException e) {
e.printStackTrace();
}
sheet = sheetName == null || sheetName.isEmpty() ? wb.getSheetAt(0) : wb.getSheet(sheetName);
}
@Override
public List<Map<String, String>> getPayload() {
List<Map<String, String>> payLoad = new ArrayList<>();
for (int i = 0; i < sheet.getLastRowNum(); i++) {
HSSFRow currentRow = sheet.getRow(i);
Map<String, String> map = new HashMap<>();
for (int j = 0; j <= sheet.getRow(i).getLastCellNum(); j++) {
map.put(String.valueOf(j), getStringFormatCellValue(currentRow.getCell(j)));
}
payLoad.add(map);
}
return payLoad;
}
}
測(cè)試工具類:
/**
* Unit test for simple App.
*/
public class AppTest
{
/**
* 測(cè)試建表,寫表操作
*/
@Test
public void testExportExcel()
{
//測(cè)試數(shù)據(jù)
String[] headers = new String[]{"A","B","C","D","E"};
List<List<Object>> valueList = new LinkedList<>();
for (char i = 'A'; i <= 'E' ; i++) {
List<Object> rowList = new LinkedList<>();
for (int j = 0; j <= 4; j++) {
rowList.add(i+String.valueOf(j));
}
valueList.add(rowList);
}
AbstractExcel excel = new ExcelBuilder("報(bào)名表")
.header(headers)
.content(valueList)
.autoColumnWidth()
.build(true);
try {
File file = new File("E:\\excel\\test.xls");
FileOutputStream op = new FileOutputStream(file);
excel.write(op);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 測(cè)試讀取表數(shù)據(jù)操作
*/
@Test
public void testImportExcel(){
AbstractExcel excel = new HeaderExcel(null,"E:/excel/test.xls");
List<Map<String,String>> values = excel.getPayload();
values.forEach(stringStringMap -> {
stringStringMap.entrySet().forEach(stringStringEntry -> {
System.out.println(stringStringEntry.getKey()+"---->"+stringStringEntry.getValue());
});
});
}
}
附圖:
測(cè)試1

測(cè)試二:

看起來效果還不錯(cuò),當(dāng)然還有很多不完善的地方,有需要的朋友可以在此基礎(chǔ)上擴(kuò)展定制,例如讀取表數(shù)據(jù)結(jié)構(gòu)方式,實(shí)現(xiàn)行數(shù)增刪改查據(jù)或者創(chuàng)建表標(biāo)題等等。
或者有朋友有更好的實(shí)現(xiàn)方案,歡迎前來交流!
最后的最后,當(dāng)然忘不了附上笨工具的源碼啦!
相關(guān)文章
SpringBoot 下的 Static 文件夾打包成前端資源的示例代碼
這篇文章主要介紹了SpringBoot 下的 Static 文件夾如何打包成前端資源,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-06-06
elasticsearch中term與match的區(qū)別講解
今天小編就為大家分享一篇關(guān)于elasticsearch中term與match的區(qū)別講解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-02-02
帶你了解Java數(shù)據(jù)結(jié)構(gòu)和算法之鏈表
這篇文章主要為大家介紹了Java數(shù)據(jù)結(jié)構(gòu)和算法之鏈表 ,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-01-01
Java網(wǎng)絡(luò)編程之基于TCP協(xié)議
本文主要將Java基于TCP的網(wǎng)絡(luò)編程主要分解成5個(gè)功能:功能分解1:單向通信功能分解,2:雙向通信功能分解,3:對(duì)象流傳送功能分解,4:加入完整的處理異常方式功能分解,5:多線程接收用戶請(qǐng)求,需要的朋友可以參考下2021-05-05
Java C++題解leetcode 1684統(tǒng)計(jì)一致字符串的數(shù)目示例
這篇文章主要為大家介紹了Java C++題解leetcode 1684統(tǒng)計(jì)一致字符串的數(shù)目示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01

