这应该是一个比较全的示例了,更加复杂的功能可以在此基础上扩展。此示例基于apache的POI类库,相关jar包就不列举了。这个类库很通用,网上很好找。
1、不包含单元格合并的写excel
/**
* excel导出到输出流
* 谁调用谁负责关闭输出流
* @param os 输出流
* @param excelExtName excel文件的扩展名,支持xls和xlsx,不带点号
* @param data
* @throws IOException
*/
public static void writeExcel(OutputStream os, String excelExtName, Map<String, List<List<String>>> data) throws IOException{
Workbook wb = null;
try {
if ("xls".equals(excelExtName)) {
wb = new HSSFWorkbook();
} else if ("xlsx".equals(excelExtName)) {
wb = new XSSFWorkbook();
} else {
throw new Exception("当前文件不是excel文件");
}
for (String sheetName : data.keySet()) {
Sheet sheet = wb.createSheet(sheetName);
List<List<String>> rowList = data.get(sheetName);
for (int i = 0; i < rowList.size(); i++) {
List<String> cellList = rowList.get(i);
Row row = sheet.createRow(i);
for (int j = 0; j < cellList.size(); j++) {
Cell cell = row.createCell(j);
cell.setCellValue(cellList.get(j));
}
}
}
wb.write(os);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (wb != null) {
wb.close();
}
}
}
2、包含单元格合并的写excel
辅助vo
class ExcelData{
private String value;//单元格的值
private int colSpan = 1;//单元格跨几列
private int rowSpan = 1;//单元格跨几行
private boolean alignCenter;//单元格是否居中,默认不居中,如果选择是,则水平和上下都居中
public boolean isAlignCenter() {
return alignCenter;
}
public void setAlignCenter(boolean alignCenter) {
this.alignCenter = alignCenter;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public int getColSpan() {
return colSpan;
}
public void setColSpan(int colSpan) {
this.colSpan = colSpan;
}
public int getRowSpan() {
return rowSpan;
}
public void setRowSpan(int rowSpan) {
this.rowSpan = rowSpan;
}
}
写excel文件的逻辑
/**
* excel导出到输出流
* 谁调用谁负责关闭输出流
* @param os 输出流
* @param excelExtName excel文件的扩展名,支持xls和xlsx,不带点号
* @param data excel数据,map中的key是标签页的名称,value对应的list是标签页中的数据。list中的子list是标签页中的一行,子list中的对象是一个单元格的数据,包括是否居中、跨几行几列以及存的值是多少
* @throws IOException
*/
public static void testWrite(OutputStream os, String excelExtName, Map<String, List<List<ExcelData>>> data) throws IOException{
Workbook wb = null;
CellStyle cellStyle = null;
boolean isXls;
try {
if ("xls".equals(excelExtName)) {
wb = new HSSFWorkbook();
isXls = true;
} else if ("xlsx".equals(excelExtName)) {
wb = new XSSFWorkbook();
isXls = false;
} else {
throw new Exception("当前文件不是excel文件");
}
cellStyle = wb.createCellStyle();
if (isXls) {
cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
} else {
cellStyle.setAlignment(XSSFCellStyle.ALIGN_CENTER);
cellStyle.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);
}
for (String sheetName : data.keySet()) {
Sheet sheet = wb.createSheet(sheetName);
List<List<ExcelData>> rowList = data.get(sheetName);
//i 代表第几行 从0开始
for (int i = 0; i < rowList.size(); i++) {
List<ExcelData> cellList = rowList.get(i);
Row row = sheet.createRow(i);
int j = 0;//j 代表第几列 从0开始
for (ExcelData excelData : cellList) {
if (excelData != null) {
if (excelData.getColSpan() > 1 || excelData.getRowSpan() > 1) {
CellRangeAddress cra = new CellRangeAddress(i, i + excelData.getRowSpan() - 1, j, j + excelData.getColSpan() - 1);
sheet.addMergedRegion(cra);
}
Cell cell = row.createCell(j);
cell.setCellValue(excelData.getValue());
if (excelData.isAlignCenter()) {
cell.setCellStyle(cellStyle);
}
j = j + excelData.getColSpan();
} else {
j++;
}
}
}
}
wb.write(os);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (wb != null) {
wb.close();
}
}
}
测试代码
public static void main(String[] args) throws IOException {
Map<String, List<List<ExcelData>>> data = new LinkedHashMap<>();
List<List<ExcelData>> sheet1 = new ArrayList<>();//第一页
List<ExcelData> list1 = new ArrayList<>();//第一行
ExcelData excelData = new ExcelData();//第一个单元格
excelData.setColSpan(6);
excelData.setRowSpan(1);
excelData.setValue("xxx");
excelData.setAlignCenter(true);
list1.add(excelData);
List<ExcelData> list2 = new ArrayList<>();//第二行
excelData = new ExcelData();//第一个单元格
excelData.setColSpan(1);
excelData.setRowSpan(1);
excelData.setValue("a");
list2.add(excelData);
excelData = new ExcelData();//第二个单元格
excelData.setColSpan(1);
excelData.setRowSpan(1);
excelData.setValue("b");
list2.add(excelData);
excelData = new ExcelData();//第三个单元格
excelData.setColSpan(2);
excelData.setRowSpan(4);
excelData.setValue("c");
excelData.setAlignCenter(true);
list2.add(excelData);
excelData = new ExcelData();//第四个单元格
excelData.setColSpan(2);
excelData.setRowSpan(2);
excelData.setValue("d");
excelData.setAlignCenter(true);
list2.add(excelData);
List<ExcelData> list3 = new ArrayList<>();//第三行
excelData = new ExcelData();//第一个单元格
excelData.setColSpan(1);
excelData.setRowSpan(1);
excelData.setValue("e");
list3.add(excelData);
excelData = new ExcelData();//第二个单元格
excelData.setColSpan(1);
excelData.setRowSpan(1);
excelData.setValue("f");
list3.add(excelData);
list3.add(null);//第三个单元格
list3.add(null);//第四个单元格
list3.add(null);//第五个单元格
list3.add(null);//第六个单元格
List<ExcelData> list4 = new ArrayList<>();//第四行
excelData = new ExcelData();//第一个单元格
excelData.setColSpan(1);
excelData.setRowSpan(1);
excelData.setValue("i");
list4.add(excelData);
excelData = new ExcelData();//第二个单元格
excelData.setColSpan(1);
excelData.setRowSpan(1);
excelData.setValue("j");
list4.add(excelData);
list4.add(null);//第三个单元格
list4.add(null);//第四个单元格
excelData = new ExcelData();//第五个单元格
excelData.setRowSpan(1);
excelData.setColSpan(1);
excelData.setValue("g");
list4.add(excelData);
excelData = new ExcelData();//第六个单元格
excelData.setRowSpan(1);
excelData.setColSpan(1);
excelData.setValue("h");
list4.add(excelData);
List<ExcelData> list5 = new ArrayList<>();//第五行
excelData = new ExcelData();//第一个单元格
excelData.setColSpan(1);
excelData.setRowSpan(1);
excelData.setValue("k");
list5.add(excelData);
excelData = new ExcelData();//第二个单元格
excelData.setColSpan(1);
excelData.setRowSpan(1);
excelData.setValue("l");
list5.add(excelData);
list5.add(null);//第三个单元格
list5.add(null);//第四个单元格
excelData = new ExcelData();//第五个单元格
excelData.setRowSpan(1);
excelData.setColSpan(1);
excelData.setValue("m");
list5.add(excelData);
excelData = new ExcelData();//第六个单元格
excelData.setRowSpan(1);
excelData.setColSpan(1);
excelData.setValue("n");
list5.add(excelData);
sheet1.add(list1);
sheet1.add(list2);
sheet1.add(list3);
sheet1.add(list4);
sheet1.add(list5);
data.put("表1", sheet1);
testWrite(new FileOutputStream(new File("D:/temp/my.xlsx")), "xlsx", data);
}
}
3、读取excel,这个方法的返回值带有一点业务逻辑,适用于没有单元格合并的excel,并且第一行是title的情况。返回的结果中,把第一行之外的每一个单元格包装成一个map,key是这个单元格的第一行的数值,也就是标题,value是这个单元格的值。逻辑有些绕,直接看代码。
/**
* 适用于第一行是标题行的excel,例如
* 姓名 年龄 性别 身高
* 张三 25 男 175
* 李四 22 女 160
* 每一行构成一个map,key值是列标题,value是列值。没有值的单元格其value值为null
* 返回结果最外层的list对应一个excel文件,第二层的list对应一个sheet页,第三层的map对应sheet页中的一行
* @throws Exception
*/
public static List<List<Map<String, String>>> readExcelWithTitle(String filepath) throws Exception{
String fileType = filepath.substring(filepath.lastIndexOf(".") + 1, filepath.length());
InputStream is = null;
Workbook wb = null;
try {
is = new FileInputStream(filepath);
if (fileType.equals("xls")) {
wb = new HSSFWorkbook(is);
} else if (fileType.equals("xlsx")) {
wb = new XSSFWorkbook(is);
} else {
throw new Exception("读取的不是excel文件");
}
List<List<Map<String, String>>> result = new ArrayList<List<Map<String,String>>>();//对应excel文件
int sheetSize = wb.getNumberOfSheets();
for (int i = 0; i < sheetSize; i++) {//遍历sheet页
Sheet sheet = wb.getSheetAt(i);
List<Map<String, String>> sheetList = new ArrayList<Map<String, String>>();//对应sheet页
List<String> titles = new ArrayList<String>();//放置所有的标题
int rowSize = sheet.getLastRowNum() + 1;
for (int j = 0; j < rowSize; j++) {//遍历行
Row row = sheet.getRow(j);
if (row == null) {//略过空行
continue;
}
int cellSize = row.getLastCellNum();//行中有多少个单元格,也就是有多少列
if (j == 0) {//第一行是标题行
for (int k = 0; k < cellSize; k++) {
Cell cell = row.getCell(k);
titles.add(cell.toString());
}
} else {//其他行是数据行
Map<String, String> rowMap = new HashMap<String, String>();//对应一个数据行
for (int k = 0; k < titles.size(); k++) {
Cell cell = row.getCell(k);
String key = titles.get(k);
String value = null;
if (cell != null) {
value = cell.toString();
}
rowMap.put(key, value);
}
sheetList.add(rowMap);
}
}
result.add(sheetList);
}
return result;
} catch (FileNotFoundException e) {
throw e;
} finally {
if (wb != null) {
wb.close();
}
if (is != null) {
is.close();
}
}
}
4、读取excel,适合于没有合并单元格且没有标题行的情况
/**
* 适用于没有标题行的excel,例如
* 张三 25岁 男 175cm
* 李四 22岁 女 160cm
* 每一行构成一个map,key值是列标题,value是列值。没有值的单元格其value值为null
* 返回结果最外层的list对应一个excel文件,第二层的list对应一个sheet页,第三层的map对应sheet页中的一行
* @throws Exception
*/
public static List<List<List<String>>> readExcelWithoutTitle(String filepath) throws Exception{
String fileType = filepath.substring(filepath.lastIndexOf(".") + 1, filepath.length());
InputStream is = null;
Workbook wb = null;
try {
is = new FileInputStream(filepath);
if (fileType.equals("xls")) {
wb = new HSSFWorkbook(is);
} else if (fileType.equals("xlsx")) {
wb = new XSSFWorkbook(is);
} else {
throw new Exception("读取的不是excel文件");
}
List<List<List<String>>> result = new ArrayList<List<List<String>>>();//对应excel文件
int sheetSize = wb.getNumberOfSheets();
for (int i = 0; i < sheetSize; i++) {//遍历sheet页
Sheet sheet = wb.getSheetAt(i);
List<List<String>> sheetList = new ArrayList<List<String>>();//对应sheet页
int rowSize = sheet.getLastRowNum() + 1;
for (int j = 0; j < rowSize; j++) {//遍历行
Row row = sheet.getRow(j);
if (row == null) {//略过空行
continue;
}
int cellSize = row.getLastCellNum();//行中有多少个单元格,也就是有多少列
List<String> rowList = new ArrayList<String>();//对应一个数据行
for (int k = 0; k < cellSize; k++) {
Cell cell = row.getCell(k);
String value = null;
if (cell != null) {
value = cell.toString();
}
rowList.add(value);
}
sheetList.add(rowList);
}
result.add(sheetList);
}
return result;
} catch (FileNotFoundException e) {
throw e;
} finally {
if (wb != null) {
wb.close();
}
if (is != null) {
is.close();
}
}
}