工作中设计树结构增删改查,导入,导出操作,搜索 POI导入导出树结构Excle 相关博客较少,故写博客用以记录分享。
注: 博主树结构为8级结构,因业务关系,故分为两张表。此表分为4级结构如下:
楼栋 — 单元 — 楼层 — 房间
导入导出Excel表格第一列项目名不在此表范围内,忽略此列即可
表仅截取几个树结构相关字段,业务字段根据需求自己添加即可。
导出Excel样式如下。
private List<****> children = new ArrayList<SysDeptInfoTreeVo>();
public int getLeftNum(){
int count = 0 ;
if (children.isEmpty()){
return 1;
}else{
for (**** s : children){
count+= s.getLeftNum();
}
}
return count;
}
//根据项目id获取此项目下全部数据
List<SysDeptInfoTreeVo> sysDeptInfoTreeVoList = deptInfoMapper.selectListByDeptId(sysDeptInfoDto.getDeptId());
//获取父节点
List<SysDeptInfoTreeVo> collect = sysDeptInfoTreeVoList.stream().filter(sysDeptInfoTreeVo -> sysDeptInfoTreeVo.getParentId() == 0).map(s -> {
s.setChildren(getChildren(s, sysDeptInfoTreeVoList));
return s;
}).sorted(Comparator.comparing(SysDeptInfoTreeVo::getId)).collect(Collectors.toList());
/**
* 递归查询子节点
* @param sysDeptInfoTreeVo 根节点
* @param sysDeptInfos 所有节点
* @return 根节点信息
*/
public static List<SysDeptInfoTreeVo> getChildren(SysDeptInfoTreeVo sysDeptInfoTreeVo, List<SysDeptInfoTreeVo> sysDeptInfos) {
List<SysDeptInfoTreeVo> children = sysDeptInfos.stream().filter(s -> sysDeptInfoTreeVo.getId().equals(s.getParentId())).map(sysDeptInfo -> {
System.out.println("'sysDeptInfo' = " + sysDeptInfo.toString());
sysDeptInfo.setChildren(getChildren(sysDeptInfo,sysDeptInfos));
return sysDeptInfo;
}).sorted(Comparator.comparing(SysDeptInfoTreeVo::getId)).collect(Collectors.toList());
return children;
}
新增入参实体需有 parentId 父节点id
新增根据具体业务进行校验
新增需判断是否为第一级节点,
若是第一级节点,则 父节点id为0 祖级列表为 0 , 等级为 1
否则 根据 父节点id 先查询父节点,从父节点获取id作为 parentId ,父节点祖级列表+父节点id 作为祖级列表参数,等级 为 父节点等级+1
新增操作分级处理即可,无示例代码
//根据id获取此项目
SysDeptInfo sysDeptInfo = deptInfoMapper.selectById(id);
Assert.isNull(sysDeptInfo,"未查询到项目信息");
//获取此项目子级集合
List<SysDeptInfo> sysDeptInfoList = deptInfoMapper.selectList(new QueryWrapper<SysDeptInfo>().eq("dept_id",sysDeptInfo.getDeptId()));
//此项目下所有子孙级list
List<SysDeptInfo> list = new ArrayList();
list.add(sysDeptInfo);
//调用递归方法
list = getChildrenList(sysDeptInfo, sysDeptInfoList,list);
/**
* 递归查询子节点
* @param sysDeptInfo 根节点
* @param sysDeptInfoList 与根节点同属一个项目下的所有数据list
* @param list 返回list
* @return sysDeptInfoList 所有子节点的list集合
*/
public static List<SysDeptInfo> getChildrenList(SysDeptInfo sysDeptInfo, List<SysDeptInfo> sysDeptInfoList,List<SysDeptInfo> list) {
List<SysDeptInfo> resList = sysDeptInfoList.stream().filter(s -> sysDeptInfo.getId().equals(s.getParentId())).map(s -> {
list.add(s);
List<SysDeptInfo> childrenList = getChildrenList(s, sysDeptInfoList, list);
return s;
}).collect(Collectors.toList());
return list;
}
Excel导入导出参考下方链接根据需求修改完善即可: Java POI完成Excel导入导出示例
参考博主poi版本较低,若用4.开头poi需修改版本不一致某些方法修改的问题,下方代码已修正。
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.List;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.zensun.system.domain.vo.SysDeptInfoTreeVo;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Component;
/**
* @program: family-file-pc-b
* @description: Excel树结构导出Util
* @author: LYK
* @create: 2021-05-20 08:37
**/
@Component
public class ExcelExportUtil {
private int cols = 9;//excel里表格列
private String sheetTitle = "项目房间信息";
public void setCols(int cols) {
this.cols = cols;
}
public void setSheetTitle(String sheetTitle) {
this.sheetTitle = sheetTitle;
}
/**
* POI : 导出数据,存放于Excel中
*
* @param os
* 输出流 (action: OutputStream os = response.getOutputStream();)
* @param sysDeptInfoTreeVo
* 要导出的数据(根数据)
*/
public void exportTaskSumPoi(OutputStream os, SysDeptInfoTreeVo sysDeptInfoTreeVo) {
//取出数据源;
String headTitle = sheetTitle;//标题;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
try {
// 创建Excel工作薄
Workbook book = null;
try {
book = new XSSFWorkbook();//excell2007
} catch (Exception ex) {
book = new HSSFWorkbook();//excell2003
}
// 在Excel工作薄中建一张工作表;
Sheet sheet = book.createSheet(sheetTitle);
//设置标题和表头;
createTitle(book, sheet, headTitle);
createHead(book, sheet);
int startCellCount = -1 ; //控制第几个单元格开始字段
int endCellCount = 0;
int rowCount = 2 ; //控制创建行数字段
//从第三行开始创建一行 --- 项目信息
Row row = sheet.createRow(rowCount);
//创建一个单元格 ---- 项目信息
Cell cell0 = row.createCell(0);
cell0.setCellValue(sysDeptInfoTreeVo.getDeptName()==null?"null":sysDeptInfoTreeVo.getDeptName());
//获取第一级所有子节点数量,+1是单元格 是从第三行开始
int i = sysDeptInfoTreeVo.getLeftNum()+ 1;
//合并项目单元格 四个参数分别为 第一个单元格的行号,第二个单元格行号,第一个单元格列号,第二个单元格的列号
sheet.addMergedRegion(new CellRangeAddress(2,sysDeptInfoTreeVo.getLeftNum()+1,0,0));
// 获取楼栋信息
ExcelChildrenNew(row,sysDeptInfoTreeVo, sheet, startCellCount,endCellCount,rowCount);
// 写入数据 把相应的Excel 工作簿存盘
book.write(os);
book.close();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 递归获取子级并对子级设置行列
*
* @param sheet
*/
private void ExcelChildrenNew(Row row,SysDeptInfoTreeVo sysDeptInfoTreeVo, Sheet sheet, int startCellCount,int endCellCount,int rowCount) {
Row newRow = row;
//各自+2目的 各个子级占用2个单元格。
startCellCount= startCellCount+2;
endCellCount= endCellCount+2;
List<SysDeptInfoTreeVo> children = sysDeptInfoTreeVo.getChildren();
if (CollectionUtils.isNotEmpty(children)){
for (int i=0; i<children.size(); i++){
if (i==0){
//此处表明 第一个子节点应该与父节点在Excel同一行
Cell cell0 = newRow.createCell(startCellCount);
Cell cell1 = newRow.createCell(endCellCount);
cell0.setCellValue(children.get(i).getDeptName()==null?"null":children.get(i).getDeptName());
cell1.setCellValue(children.get(i).getRoomTypeName()==null?"null":children.get(i).getRoomTypeName());
//只有插入的行号< 行号+所有子节点的数量-1才可合并 即 不是叶子节点才能合并
if (rowCount<rowCount+children.get(i).getLeftNum()-1){
sheet.addMergedRegion(new CellRangeAddress(rowCount,rowCount+children.get(i).getLeftNum()-1,startCellCount,startCellCount));
sheet.addMergedRegion(new CellRangeAddress(rowCount,rowCount+children.get(i).getLeftNum()-1,endCellCount,endCellCount));
}
}else{
//此处表示 获取所有上级节点的叶子节点数量作为行数 for循环为订正内容删除for即可
// for (int j = 1 ; j<= i ; j++){
rowCount += children.get(j-1).getLeftNum();
// }
newRow = sheet.createRow(rowCount);
Cell cell0 = newRow.createCell(startCellCount);
Cell cell1 = newRow.createCell(endCellCount);
cell0.setCellValue(children.get(i).getDeptName()==null?"null":children.get(i).getDeptName());
cell1.setCellValue(children.get(i).getRoomTypeName()==null?"null":children.get(i).getRoomTypeName());
if (rowCount<rowCount+children.get(i).getLeftNum()-1){
sheet.addMergedRegion(new CellRangeAddress(rowCount,rowCount+children.get(i).getLeftNum()-1,startCellCount,startCellCount));
sheet.addMergedRegion(new CellRangeAddress(rowCount,rowCount+children.get(i).getLeftNum()-1,endCellCount,endCellCount));
}
}
ExcelChildren(newRow,children.get(i),sheet,startCellCount,endCellCount,rowCount);
}
}
}
/**
* 给excel设置标题
*
* @param sheet
*/
public void createTitle(Workbook book, Sheet sheet, String headTitle) {
CellStyle style = createTitleStyle(book);
Row row = sheet.createRow(0);// 创建第一行,设置表的标题;
row.setHeightInPoints(36);//设置行的高度是34个点
Cell cell = row.createCell(0);
cell.setCellValue(headTitle);
cell.setCellStyle(style);
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, cols-1));//第一行跨表所有列;
}
/**
* 设置导出表的表头
*
* @param book
* @param sheet
*/
private void createHead(Workbook book, Sheet sheet) {
// 设置单元格格式(文本)
// 第二行为表头行
String title = "";
CellStyle style = createHeadStyle(book);
Row row = sheet.createRow(1);// 创建第一行
row.setHeightInPoints(22);//设置行的高度是20个点
for (int j = 0; j < cols; j++) {
Cell cell = row.createCell(j);
cell.setCellType(CellType.STRING);
if (j == 0) {
title = "项目名";
sheet.setColumnWidth(j, title.getBytes().length * 2 * 256);
}
if (j == 1) {
title = "楼栋";
sheet.setColumnWidth(j, title.getBytes().length * 2 * 256);
}
if (j == 2) {
title = "业态";
}
if (j == 3) {
title = "单元";
sheet.setColumnWidth(j, title.getBytes().length * 2 * 256);
}
if (j == 4) {
title = "业态";
}
if (j == 5) {
title = "楼层";
}
if (j == 6) {
title = "业态";
}
if (j == 7) {
title = "房间";
}
if (j == 8) {
title = "业态";
}
cell.setCellValue(title);
cell.setCellStyle(style);
}
}
/**
* 创建标题样式
* @param book
* @return
*/
public CellStyle createTitleStyle(Workbook book) {
CellStyle cellStyle = book.createCellStyle();
cellStyle.setBorderTop(BorderStyle.THIN);//上边框
cellStyle.setBorderBottom(BorderStyle.THIN);//下边框
cellStyle.setBorderLeft(BorderStyle.THIN);//左边框
cellStyle.setBorderRight(BorderStyle.THIN);//右边框
cellStyle.setAlignment(HorizontalAlignment.CENTER);//水平居中
cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);//垂直居中
Font font = book.createFont();
font.setFontHeightInPoints((short) 20); // 字体大小
font.setFontName("宋体");
cellStyle.setFont(font);
return cellStyle;
}
/**
* 创建表头样式
* @param book
* @return
*/
public CellStyle createHeadStyle(Workbook book) {
CellStyle cellStyle = book.createCellStyle();
cellStyle.setBorderTop(BorderStyle.THIN);//上边框
cellStyle.setBorderBottom(BorderStyle.THIN);//下边框
cellStyle.setBorderLeft(BorderStyle.THIN);//左边框
cellStyle.setBorderRight(BorderStyle.THIN);//右边框
cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); // 填充单元格
cellStyle.setFillForegroundColor(HSSFColor.HSSFColorPredefined.LIGHT_TURQUOISE.getIndex()); // 填浅蓝色
cellStyle.setAlignment(HorizontalAlignment.CENTER);//水平居中
cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);//垂直居中
Font font = book.createFont();
font.setFontHeightInPoints((short) 11); // 字体大小
font.setFontName("黑体");
cellStyle.setFont(font);
return cellStyle;
}
/**
* 创建内容部分前8列单元格样式
* @param book
* @return
*/
public CellStyle createContentStyle(Workbook book) {
CellStyle cellStyle = book.createCellStyle();
cellStyle.setBorderTop(BorderStyle.THIN);//上边框
cellStyle.setBorderBottom(BorderStyle.THIN);//下边框
cellStyle.setBorderLeft(BorderStyle.THIN);//左边框
cellStyle.setBorderRight(BorderStyle.THIN);//右边框
cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); // 填充单元格
cellStyle.setFillForegroundColor(HSSFColor.HSSFColorPredefined.LIGHT_TURQUOISE.getIndex()); // 填浅蓝色
cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);//垂直居中
cellStyle.setWrapText(true);//自动换行
Font font = book.createFont();
font.setFontHeightInPoints((short) 11); // 字体大小
font.setFontName("宋体");
cellStyle.setFont(font);
return cellStyle;
}
/**
* 创建内容其它部分单元格样式
* @param book
* @return
*/
public CellStyle createOtherStyle(Workbook book) {
CellStyle cellStyle = book.createCellStyle();
cellStyle.setBorderTop(BorderStyle.THIN);//上边框
cellStyle.setBorderBottom(BorderStyle.THIN);//下边框
cellStyle.setBorderLeft(BorderStyle.THIN);//左边框
cellStyle.setBorderRight(BorderStyle.THIN);//右边框
cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);//垂直居中
cellStyle.setWrapText(true);//自动换行
Font font = book.createFont();
font.setFontHeightInPoints((short) 11); // 字体大小
font.setFontName("宋体");
cellStyle.setFont(font);
return cellStyle;
}
/**
* 设置字符串内注解样式;
* @param book
* @param str 传入的待处理字符串;
* @return
*/
public RichTextString noteFontStyle(Workbook book, String str) {
//定义字体
Font hFont = book.createFont();
hFont.setFontHeightInPoints((short) 10);//字体大小
hFont.setFontName("楷体");
RichTextString richString = null;
try {//2007版excel
richString = new XSSFRichTextString(str);//2007版excel
} catch (Exception e) {
richString = new HSSFRichTextString(str);//2003版excel
}
if (str.indexOf("(") == -1) {
return richString;
}
//字体样式设置到字符串中;
richString.applyFont(str.indexOf("("), str.indexOf(")"), hFont);
return richString;
}
/**
* 设置日期格式;
* @param book
* @return
*/
public CellStyle setDateStyle(Workbook book) {
CellStyle style = book.createCellStyle();
try {//2007版excel
DataFormat format = book.createDataFormat();
style.setDataFormat(format.getFormat("yyyy年MM月dd日"));
} catch (Exception e) {//2003版excel
style.setDataFormat(HSSFDataFormat.getBuiltinFormat("yyyy年MM月dd日"));
}
return style;
}
}
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.ss.usermodel.BuiltinFormats;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.xssf.eventusermodel.ReadOnlySharedStringsTable;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.StylesTable;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.springframework.stereotype.Component;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
/**
* @description: ExcelImportUtil
* @author: LYK
* @create: 2021-05-21 08:09
**/
public class ExcelImportUtil {
//excll中存在的样式;
enum xssfDataType {
BOOL, ERROR, FORMULA, INLINESTR, SSTINDEX, NUMBER;
}
/**
*/
class MyXSSFSheetHandler extends DefaultHandler {
/**
* 表样式
*/
private StylesTable stylesTable;
/**
* 表中独特的字符串
*/
private ReadOnlySharedStringsTable sharedStringsTable;
/**
* 数据输出
*/
private final PrintStream output;
/**
* 最大列数
*/
private final int minColumnCount;
// 当看到v start元素时设置
private boolean vIsOpen;
// 当单元格开始元素出现时设置;
//当看到cell close元素时使用。
private xssfDataType nextDataType;
// 用于设置数值单元格值的格式
private short formatIndex;
private String formatString;
private final DataFormatter formatter;
private int thisColumn = -1;
// 打印到输出流的最后一列
private int lastColumnNumber = -1;
// 收集所看到的角色
private StringBuffer value;
private String[] record;
private List<String[]> rows = new ArrayList<String[]>();
private boolean isCellNull = false;
/**
* 接受分析时所需的对象。
* @param styles
* @param strings 共享字符串
* @param cols 要显示的最小列数
* @param target
*/
public MyXSSFSheetHandler(StylesTable styles, ReadOnlySharedStringsTable strings, int cols, PrintStream target) {
this.stylesTable = styles;
this.sharedStringsTable = strings;
this.minColumnCount = cols;
this.output = target;
this.value = new StringBuffer();
this.nextDataType = xssfDataType.NUMBER;
this.formatter = new DataFormatter();
record = new String[this.minColumnCount];
rows.clear();// 每次读取都清空行集合
}
/*
* 第一个执行方法,用于设定单元格的数字类型(如日期、数字、字符串等等);
*/
public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException {
if ("inlineStr".equals(name) || "v".equals(name)) {
vIsOpen = true;
// Clear contents cache
value.setLength(0);
}
// c => cell
else if ("c".equals(name)) {
// Get the cell reference
String r = attributes.getValue("r");
int firstDigit = -1;
for (int c = 0; c < r.length(); ++c) {
if (Character.isDigit(r.charAt(c))) {
firstDigit = c;
break;
}
}
thisColumn = nameToColumn(r.substring(0, firstDigit));
// Set up defaults.
this.nextDataType = xssfDataType.NUMBER;
this.formatIndex = -1;
this.formatString = null;
String cellType = attributes.getValue("t");
String cellStyleStr = attributes.getValue("s");
if ("b".equals(cellType))
nextDataType = xssfDataType.BOOL;
else if ("e".equals(cellType))
nextDataType = xssfDataType.ERROR;
else if ("inlineStr".equals(cellType))
nextDataType = xssfDataType.INLINESTR;
else if ("s".equals(cellType))
nextDataType = xssfDataType.SSTINDEX;
else if ("str".equals(cellType))
nextDataType = xssfDataType.FORMULA;
else if (cellStyleStr != null) {
// It's a number, but almost certainly one
// with a special style or format
int styleIndex = Integer.parseInt(cellStyleStr);
XSSFCellStyle style = stylesTable.getStyleAt(styleIndex);
this.formatIndex = style.getDataFormat();
this.formatString = style.getDataFormatString();
if (this.formatString == null)
this.formatString = BuiltinFormats.getBuiltinFormat(this.formatIndex);
}
}
}
/*
* 最后一个执行方法;
*/
public void endElement(String uri, String localName, String name) throws SAXException {
String thisStr = null;
// v => contents of a cell
if ("v".equals(name)) {
// 根据需要处理值内容。
// 这时characters()方法可能会被调用多次
switch (nextDataType) {
case BOOL:
char first = value.charAt(0);
thisStr = first == '0' ? "FALSE" : "TRUE";
break;
case ERROR:
thisStr = "\"ERROR:" + value.toString() + '"';
break;
case FORMULA:
// A formula could result in a string value,
// so always add double-quote characters.
thisStr = '"' + value.toString() + '"';
break;
case INLINESTR:
// TODO: have seen an example of this, so it's untested.
XSSFRichTextString rtsi = new XSSFRichTextString(value.toString());
thisStr = '"' + rtsi.toString() + '"';
break;
//字符串
case SSTINDEX:
String sstIndex = value.toString();
try {
int idx = Integer.parseInt(sstIndex);
//根据idx索引值获取内容值
XSSFRichTextString rtss = new XSSFRichTextString(sharedStringsTable.getEntryAt(idx));
thisStr = rtss.toString();
} catch (NumberFormatException ex) {
output.println("Failed to parse SST index '" + sstIndex + "': " + ex.toString());
}
break;
case NUMBER:
String n = value.toString();
// 判断是否是日期格式
if (HSSFDateUtil.isADateFormat(this.formatIndex, n)) {
Double d = Double.parseDouble(n);
Date date = HSSFDateUtil.getJavaDate(d);
thisStr = formateDateToString(date);
} else if (this.formatString != null)
thisStr = formatter.formatRawCellContents(Double.parseDouble(n), this.formatIndex,
this.formatString);
else
thisStr = n;
break;
default:
thisStr = "(TODO: Unexpected type: " + nextDataType + ")";
break;
}
// Output after we've seen the string contents
// Emit commas for any fields that were missing on this row
if (lastColumnNumber == -1) {
lastColumnNumber = 0;
}
//判断单元格的值是否为空
if (thisStr == null || "".equals(isCellNull)) {
isCellNull = true;// 设置单元格是否为空值
}
record[thisColumn] = thisStr;
// Update column
if (thisColumn > -1)
lastColumnNumber = thisColumn;
} else if ("row".equals(name)) {
// Print out any missing commas if needed
if (minColumns > 0) {
// Columns are 0 based
if (lastColumnNumber == -1) {
lastColumnNumber = 0;
}
boolean recordflag = record[0] != null;
for (int i = 1; i < minColumns; i++) {
recordflag = recordflag || (record[i] != null);
}
if (isCellNull == false && recordflag)// 判断是否空行
{
rows.add(record.clone());
isCellNull = false;
for (int i = 0; i < record.length; i++) {
record[i] = null;
}
}
}
lastColumnNumber = -1;
}
}
public List<String[]> getRows() {
return rows;
}
public void setRows(List<String[]> rows) {
this.rows = rows;
}
/**
* 仅在打开适当的元素时捕获字符。最初只是“v”;扩展为inlinestr
*/
public void characters(char[] ch, int start, int length) throws SAXException {
if (vIsOpen)
value.append(ch, start, length);
}
/**
* 将Excel列名(如“C”)转换为从零开始的索引
*
* @param name
* @return 与指定名称对应的索引
*/
private int nameToColumn(String name) {
int column = -1;
for (int i = 0; i < name.length(); ++i) {
int c = name.charAt(i);
column = (column + 1) * 26 + c - 'A';
}
return column;
}
private String formateDateToString(Date date) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd日");//格式化日期
return sdf.format(date);
}
}
private OPCPackage xlsxPackage;
private int minColumns;
private PrintStream output;
private String sheetName;
/**
* 创建新的XLSX->csv转换器
*
* @param pkg
* 要处理的XLSX包
* @param output
* 要将csv输出到的打印流
* @param minColumns
* 要输出的最小列数,或-1表示无最小值
*/
public ExcelImportUtil(OPCPackage pkg, PrintStream output, String sheetName, int minColumns) {
this.xlsxPackage = pkg;
this.output = output;
this.minColumns = minColumns;
this.sheetName = sheetName;
}
/**
*使用指定的样式和共享字符串表解析和显示一个工作表的内容。
*
* @param styles
* @param strings
* @param sheetInputStream
*/
public List<String[]> processSheet(StylesTable styles, ReadOnlySharedStringsTable strings,
InputStream sheetInputStream) throws IOException, ParserConfigurationException, SAXException {
InputSource sheetSource = new InputSource(sheetInputStream);
SAXParserFactory saxFactory = SAXParserFactory.newInstance();
SAXParser saxParser = saxFactory.newSAXParser();
XMLReader sheetParser = saxParser.getXMLReader();
MyXSSFSheetHandler handler = new MyXSSFSheetHandler(styles, strings, this.minColumns, this.output);
sheetParser.setContentHandler(handler);
//解析excel的每条记录,在这个过程中startElement()、characters()、endElement()这三个函数会依次执行
sheetParser.parse(sheetSource);
return handler.getRows();
}
/**
* 初始化这个处理程序 将
*
* @throws IOException
* @throws OpenXML4JException
* @throws ParserConfigurationException
* @throws SAXException
*/
public List<String[]> process() throws IOException, OpenXML4JException, ParserConfigurationException, SAXException {
ReadOnlySharedStringsTable strings = new ReadOnlySharedStringsTable(this.xlsxPackage);
XSSFReader xssfReader = new XSSFReader(this.xlsxPackage);
List<String[]> list = null;
StylesTable styles = xssfReader.getStylesTable();
XSSFReader.SheetIterator iter = (XSSFReader.SheetIterator) xssfReader.getSheetsData();
int index = 0;
while (iter.hasNext()) {
InputStream stream = iter.next();
String sheetNameTemp = iter.getSheetName();
if (this.sheetName.equals(sheetNameTemp)) {
list = processSheet(styles, strings, stream);
stream.close();
++index;
}
}
return list;
}
/**
* 读取Excel
*
* @param inIo
* 文件流
* @param sheetName
* sheet名称
* @param minColumns
* 列总数
* @return
* @throws SAXException
* @throws ParserConfigurationException
* @throws OpenXML4JException
* @throws IOException
*/
public static List<String[]> readerExcel(InputStream inIo, String sheetName, int minColumns) throws IOException,
OpenXML4JException, ParserConfigurationException, SAXException {
OPCPackage p = OPCPackage.open(inIo);
ExcelImportUtil xlsx2csv = new ExcelImportUtil(p, System.out, sheetName, minColumns);
List<String[]> list = xlsx2csv.process();
p.close();
return list;
}
}
@Override
public void importExcel(MultipartFile file, HttpServletRequest req, HttpServletResponse resp)throws IOException, OpenXML4JException, ParserConfigurationException, SAXException {
List<String[]> strings = ExcelImportUtil.readerExcel(file.getInputStream(), "项目房间信息", 9);
//导入项目房间信息所属项目的id
Integer deptId = 0;
//此map集合用于保存 父级 对象。
Map<String,SysDeptInfo> sysDeptInfoMap = new HashMap<>();
for (int i = 0; i < strings.size() ; i++) {
if (i>1){
//数组转换为集合
List<String> list = Arrays.asList(strings.get(i));
if (StringUtils.isNotBlank(list.get(0))){
// 此处主要做校验,判断所属项目存不存在,获取项目id 方便数据插入时表明所属项目
}
if (StringUtils.isNotBlank(list.get(1)) && StringUtils.isNotBlank(list.get(2))){
//楼栋操作
//插入楼栋信息
deptInfoMapper.insert(sysDeptInfo);
//将楼栋存入Maop
sysDeptInfoMap.put("LD",LD);
}
if (StringUtils.isNotBlank(list.get(3))){
//获取父级楼栋信息
SysDeptInfo father = sysDeptInfoMap.get("LD");
//单元
SysDeptInfo sysDeptInfo = new SysDeptInfo();
sysDeptInfo.setParentId(father.getId());
sysDeptInfo.setAncestors(father.getAncestors() + "," + sysDeptInfo.getParentId());
sysDeptInfo.setLevel(father.getLevel() + 1);
//插入单元信息
deptInfoMapper.insert(sysDeptInfo);
//将单元存入Map
sysDeptInfoMap.put("DY",sysDeptInfo);
}
if (StringUtils.isNotBlank(list.get(5))){
//楼层
//获取父级信息
SysDeptInfo father = sysDeptInfoMap.get("DY");
//楼层
SysDeptInfo sysDeptInfo = new SysDeptInfo();
sysDeptInfo.setParentId(father.getId());
sysDeptInfo.setAncestors(father.getAncestors() + "," + sysDeptInfo.getParentId());
//插入楼层信息
deptInfoMapper.insert(sysDeptInfo);
//将楼层存入Map
sysDeptInfoMap.put("LC",sysDeptInfo);
}
if (StringUtils.isNotBlank(list.get(7)) && StringUtils.isNotBlank(list.get(8))){
//房间
//获取父级信息
SysDeptInfo father = sysDeptInfoMap.get("LC");
//房间
SysDeptInfo sysDeptInfo = new SysDeptInfo();
sysDeptInfo.setParentId(father.getId());
sysDeptInfo.setAncestors(father.getAncestors() + "," + sysDeptInfo.getParentId());
sysDeptInfo.setLevel(father.getLevel() + 1);
//插入房间信息
deptInfoMapper.insert(sysDeptInfo);
}
}
}
sysDeptInfoMap.clear();
}