日常在做后臺(tái)系統(tǒng)的時(shí)候會(huì)很頻繁的遇到Excel導(dǎo)入導(dǎo)出的問(wèn)題,正好這次在做一個(gè)后臺(tái)系統(tǒng),就想著寫(xiě)一個(gè)公用工具來(lái)進(jìn)行Excel的導(dǎo)入導(dǎo)出。
一般我們?cè)趯?dǎo)出的時(shí)候都是導(dǎo)出的前端表格,而前端表格同時(shí)也會(huì)對(duì)應(yīng)的在后臺(tái)有一個(gè)映射類(lèi)。
所以在寫(xiě)這個(gè)工具的時(shí)候我們先理一下我們需要實(shí)現(xiàn)的效果:
導(dǎo)出方法接收一個(gè)list集合,和一個(gè)Class類(lèi)型,和HttpServletResponse 對(duì)象
導(dǎo)出是可能會(huì)有下拉列表,所以需要一個(gè)map存儲(chǔ)下拉列表數(shù)據(jù)源,傳入?yún)?shù)后只需一行代碼即可導(dǎo)出
導(dǎo)入方法需要傳入file文件,以及一個(gè)Class類(lèi)型,導(dǎo)入之后將會(huì)返回一個(gè)list集合,里面的對(duì)象就是傳入類(lèi)型的對(duì)象,傳入?yún)?shù)后只需一行代碼即可導(dǎo)入
實(shí)現(xiàn)過(guò)程:
首先需要?jiǎng)?chuàng)建三個(gè)注解
一個(gè)是EnableExport ,必須有這個(gè)注解才能導(dǎo)出
/**
* 設(shè)置允許導(dǎo)出
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface EnableExport {
String fileName();
}
然后就是EnableExportField,有這個(gè)注解的字段才會(huì)導(dǎo)出到Excel里面,并且可以設(shè)置列寬
/**
* 設(shè)置該字段允許導(dǎo)出
* 并且可以設(shè)置寬度
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface EnableExportField {
int colWidth() default 100;
String colName();
}
再就是ImportIndex,導(dǎo)入的時(shí)候設(shè)置Excel中的列對(duì)應(yīng)的序號(hào)
/**
* 導(dǎo)入時(shí)索引
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ImportIndex {
int index() ;
}
注解使用示例

三個(gè)注解創(chuàng)建好之后就需要開(kāi)始操作Excel了
首先,導(dǎo)入方法。在后臺(tái)接收到前端上傳的Excel文件之后,使用poi來(lái)讀取Excel文件
我們根據(jù)傳入的類(lèi)型上面的字段注解的順序來(lái)分別為不同的字段賦值,然后存入集合中,再返回
代碼如下:
/**
* 將Excel轉(zhuǎn)換為對(duì)象集合
* @param excel Excel 文件
* @param clazz pojo類(lèi)型
* @return
*/
public static List《Object》 parseExcelToList(File excel,Class clazz){
List《Object》 res = new ArrayList《》();
// 創(chuàng)建輸入流,讀取Excel
InputStream is = null;
Sheet sheet = null;
try {
is = new FileInputStream(excel.getAbsolutePath());
if (is != null) {
Workbook workbook = WorkbookFactory.create(is);
//默認(rèn)只獲取第一個(gè)工作表
sheet = workbook.getSheetAt(0);
if (sheet != null) {
//前兩行是標(biāo)題
int i = 2;
String values[] ;
Row row = sheet.getRow(i);
while (row != null) {
//獲取單元格數(shù)目
int cellNum = row.getPhysicalNumberOfCells();
values = new String[cellNum];
for (int j = 0; j 《= cellNum; j++) {
Cell cell = row.getCell(j);
if (cell != null) {
//設(shè)置單元格內(nèi)容類(lèi)型
cell.setCellType(Cell.CELL_TYPE_STRING );
//獲取單元格值
String value = cell.getStringCellValue() == null ? null : cell.getStringCellValue();
values[j]=value;
}
}
Field[] fields = clazz.getDeclaredFields();
Object obj = clazz.newInstance();
for(Field f : fields){
if(f.isAnnotationPresent(ImportIndex.class)){
ImportIndex annotation = f.getDeclaredAnnotation(ImportIndex.class);
int index = annotation.index();
f.setAccessible(true);
//此處使用了阿里巴巴的fastjson包里面的一個(gè)類(lèi)型轉(zhuǎn)換工具類(lèi)
Object val =TypeUtils.cast(values[index],f.getType(),null);
f.set(obj,val);
}
}
res.add(obj);
i++;
row=sheet.getRow(i);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return res;
}
接下來(lái)就是導(dǎo)出方法。
導(dǎo)出分為幾個(gè)步驟:
1.建立一個(gè)工作簿,也就是類(lèi)型新建一個(gè)Excel文件

2.建立一張sheet表

3.設(shè)置標(biāo)的行高和列寬

4.繪制標(biāo)題和表頭

這兩個(gè)方法是自定義方法,代碼會(huì)貼在后面
5.寫(xiě)入數(shù)據(jù)到Excel

6.創(chuàng)建下拉列表

7.寫(xiě)入文件到response

到這里導(dǎo)出工作就完成了
下面是一些自定義方法的代碼
/**
* 獲取一個(gè)基本的帶邊框的單元格
* @param workbook
* @return
*/
private static HSSFCellStyle getBasicCellStyle(HSSFWorkbook workbook){
HSSFCellStyle hssfcellstyle = workbook.createCellStyle();
hssfcellstyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
hssfcellstyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
hssfcellstyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
hssfcellstyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
hssfcellstyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
hssfcellstyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
hssfcellstyle.setWrapText(true);
return hssfcellstyle;
}
/**
* 獲取帶有背景色的標(biāo)題單元格
* @param workbook
* @return
*/
private static HSSFCellStyle getTitleCellStyle(HSSFWorkbook workbook){
HSSFCellStyle hssfcellstyle = getBasicCellStyle(workbook);
hssfcellstyle.setFillForegroundColor((short) HSSFColor.CORNFLOWER_BLUE.index); // 設(shè)置背景色
hssfcellstyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
return hssfcellstyle;
}
/**
* 創(chuàng)建一個(gè)跨列的標(biāo)題行
* @param workbook
* @param hssfRow
* @param hssfcell
* @param hssfsheet
* @param allColNum
* @param title
*/
private static void createTitle(HSSFWorkbook workbook, HSSFRow hssfRow , HSSFCell hssfcell, HSSFSheet hssfsheet,int allColNum,String title){
//在sheet里增加合并單元格
CellRangeAddress cra = new CellRangeAddress(0, 0, 0, allColNum);
hssfsheet.addMergedRegion(cra);
// 使用RegionUtil類(lèi)為合并后的單元格添加邊框
RegionUtil.setBorderBottom(1, cra, hssfsheet, workbook); // 下邊框
RegionUtil.setBorderLeft(1, cra, hssfsheet, workbook); // 左邊框
RegionUtil.setBorderRight(1, cra, hssfsheet, workbook); // 有邊框
RegionUtil.setBorderTop(1, cra, hssfsheet, workbook); // 上邊框
//設(shè)置表頭
hssfRow = hssfsheet.getRow(0);
hssfcell = hssfRow.getCell(0);
hssfcell.setCellStyle( getTitleCellStyle(workbook));
hssfcell.setCellType(HSSFCell.CELL_TYPE_STRING);
hssfcell.setCellValue(title);
}
/**
* 設(shè)置表頭標(biāo)題欄以及表格高度
* @param workbook
* @param hssfRow
* @param hssfcell
* @param hssfsheet
* @param colNames
*/
private static void createHeadRow(HSSFWorkbook workbook,HSSFRow hssfRow , HSSFCell hssfcell,HSSFSheet hssfsheet,List《String》 colNames){
//插入標(biāo)題行
hssfRow = hssfsheet.createRow(1);
for (int i = 0; i 《 colNames.size(); i++) {
hssfcell = hssfRow.createCell(i);
hssfcell.setCellStyle(getTitleCellStyle(workbook));
hssfcell.setCellType(HSSFCell.CELL_TYPE_STRING);
hssfcell.setCellValue(colNames.get(i));
}
}
/**
* excel添加下拉數(shù)據(jù)校驗(yàn)
* @param sheet 哪個(gè) sheet 頁(yè)添加校驗(yàn)
* @return
*/
public static void createDataValidation(Sheet sheet,Map《Integer,String[]》 selectListMap) {
if(selectListMap!=null) {
selectListMap.forEach(
// 第幾列校驗(yàn)(0開(kāi)始)key 數(shù)據(jù)源數(shù)組value
(key, value) -》 {
if(value.length》0) {
CellRangeAddressList cellRangeAddressList = new CellRangeAddressList(2, 65535, key, key);
DataValidationHelper helper = sheet.getDataValidationHelper();
DataValidationConstraint constraint = helper.createExplicitListConstraint(value);
DataValidation dataValidation = helper.createValidation(constraint, cellRangeAddressList);
//處理Excel兼容性問(wèn)題
if (dataValidation instanceof XSSFDataValidation) {
dataValidation.setSuppressDropDownArrow(true);
dataValidation.setShowErrorBox(true);
} else {
dataValidation.setSuppressDropDownArrow(false);
}
dataValidation.setEmptyCellAllowed(true);
dataValidation.setShowPromptBox(true);
dataValidation.createPromptBox(“提示”, “只能選擇下拉框里面的數(shù)據(jù)”);
sheet.addValidationData(dataValidation);
}
}
);
}
}
使用實(shí)例
導(dǎo)出數(shù)據(jù)

導(dǎo)入數(shù)據(jù)(返回對(duì)象List)

責(zé)任編輯:haq
-
Excel
+關(guān)注
關(guān)注
4文章
231瀏覽量
57698 -
數(shù)據(jù)導(dǎo)入
+關(guān)注
關(guān)注
0文章
3瀏覽量
7040
原文標(biāo)題:實(shí)現(xiàn) Excel 導(dǎo)入導(dǎo)出
文章出處:【微信號(hào):harmonyos_developer,微信公眾號(hào):harmonyos_developer】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
頁(yè)面導(dǎo)入導(dǎo)出功能怎么用?如何快速合并兩個(gè)工程,復(fù)制粘貼注意事項(xiàng)?
頁(yè)面導(dǎo)入導(dǎo)出功能怎么用?如何快速合并兩個(gè)工程,復(fù)制粘貼注意事項(xiàng)?
EtherCAT工具 SSC 工具 5.11版本 無(wú)法添加EtherCAT_IO模板導(dǎo)入
電能質(zhì)量在線監(jiān)測(cè)裝置的多維度統(tǒng)計(jì)報(bào)表支持遠(yuǎn)程訪問(wèn)導(dǎo)出嗎?
EXCEL導(dǎo)入—設(shè)計(jì)與思考
KiCad 已支持導(dǎo)入 Altium 工程(Project)
使用Word/Excel管理需求的10個(gè)痛點(diǎn)及解決方案Perforce ALM
如何導(dǎo)出Excel文件 -- excel_hm介紹 ##三方SDK##
【Banana Pi BPI-RV2開(kāi)發(fā)板試用體驗(yàn)】移植lrzsz以便從串口和ssh導(dǎo)入導(dǎo)出文件
Simcenter FLOEFD EDA Bridge模塊:使用導(dǎo)入的詳細(xì)PCB設(shè)計(jì)和IC熱特性來(lái)簡(jiǎn)化熱分析
TSolidX應(yīng)用:液晶掩膜結(jié)構(gòu)GDSⅡ文件的生成和導(dǎo)出
和 Dr Peter 一起學(xué) KiCad 4.9~4.10:導(dǎo)出Gerber并下單(收到成品)
Allegro Skill封裝功能-導(dǎo)出device文件介紹與演示
如何用一個(gè)公用工具來(lái)進(jìn)行Excel的導(dǎo)入導(dǎo)出
評(píng)論