1.程序内部生成Excel表格
1.1 表头和数据分离
//表头存储格式
List<String[]> headerGoodsOrderList
String[] h1 = new String[2];
h1[0] = "id";
h1[1] = "序号";
headorder.add(h1);
String[] h2 = new String[2];
h2[0] = "orderNo";
h2[1] = "订单号";
headorder.add(h2);
//数据存储格式
List<Map<String, Object>> list
个人觉得,表头存储格式的好处在于,可以自定义一些属性,包括后续有可能的合并单元格,背景色等等,都可以预先定义,然后在公共类中或者相应的方法中进行处理
至于数据,由于想做成通用方法,所以采用了map数组结构。
public static InputStream createExcel(List<String[]> headerList, List<Map<String,Object>> dataList){
InputStream excelStream = null;
ByteArrayOutputStream out = new ByteArrayOutputStream();
//创建HSSFWorkbook对象(excel的文档对象)
HSSFWorkbook wb = new HSSFWorkbook();
// 建立新的sheet对象(excel的表单)
HSSFSheet sheet = wb.createSheet("sheet1");
// 在sheet里创建第一行,参数为行索引(excel的行),可以是0~65535之间的任何一个
HSSFRow row = sheet.createRow(0);
// 第四步,创建单元格,并设置值表头 设置表头居中
HSSFCellStyle style = wb.createCellStyle();
HSSFCell cell = row.createCell((short) 0);
//设置表头--h[0]英文匹配名,h[1]中文显示字段
for(int i=0;i<headerList.size();i++){
String [] arrays = headerList.get(i);
sheet.setColumnWidth(i, 20 * 256);
if(i!=0){
cell = row.createCell((short) i);
}
cell.setCellValue(arrays[1]);
cell.setCellStyle(style);
}
//编辑数据--表头匹配
for(int j=0;j<dataList.size();j++){
//另起一行
row = sheet.createRow((int) j + 1);
Map<String,Object> maps = dataList.get(j);
for(int k=0;k<headerList.size();k++){
String [] arr = headerList.get(k);
row.createCell((short) k).setCellValue(maps.get(arr[0])!=null?maps.get(arr[0]).toString():"");
}
}
try {
wb.write(out);
excelStream = new ByteArrayInputStream(out.toByteArray());
out.close();
}catch (IOException e) {
e.printStackTrace();
}
return excelStream;
}
首先,将定义的表头list集合在单元格中定义,取集合中的list[1],后续list[0]中的英文名做为和数据中的key进行匹配,这样可以减少非必要的循环,增加速度。
循环装载数据时,需要另起一行
row = sheet.createRow((int) j + 1);
此行代码在循环基础上加一,避过表头另起一行
一般没有什么要求直接页面输出的话可以酌情去除我try catch中的代码,但是我这边是要拿到输出流对象上传阿里云接口,然后拿到下载链接返回前端,所以需要转换一下。
String fileName = UUID.randomUUID().toString().replace("-", "").toLowerCase()+".xls";
生成UUID做为文件名,然后正常调用阿里云上传接口即可,可以去查询阿里云上传接口文档。
public byte[] downloadFiles(TmpFile tmpFile) {
log.info("文件下载,传入文件ID为{}", tmpFile);
OSSClient client = Upload.getOSSClient();
String fileName = tmpFile.getFileUrl().substring(tmpFile.getFileUrl().lastIndexOf("/")+1,tmpFile.getFileUrl().length());
InputStream inputStream = Upload.getOSS2InputStream(client,bucketName,diskNameTmp,fileName);
try {
ByteArrayOutputStream output = new ByteArrayOutputStream();
byte[] buffer = new byte[1024*4];
int n = 0;
while (-1 != (n = inputStream.read(buffer))) {
output.write(buffer, 0, n);
}
return output.toByteArray();
}catch (IOException e){
e.printStackTrace();
}finally {
try {
inputStream.close();
}catch (IOException e){
e.printStackTrace();
}
}
return null;
}
这里我把文件下载的方法记录一下,远程下载链接后,解析位byte数组
InputStream inputStream = new ByteArrayInputStream(fileByte);
转为输出流后解析即可
/**
* 读入excel文件,解析后返回
* @param in inputStream
* @param fileName 文件名
*/
public static List<String[]> readExcel(InputStream in,String fileName) {
//获得Workbook工作薄对象
Workbook workbook = getWorkBook(in,fileName);
//创建返回对象,把每行中的值作为一个数组,所有行作为一个集合返回
List<String[]> list = new ArrayList<String[]>();
if(workbook != null){
for(int sheetNum = 0;sheetNum < workbook.getNumberOfSheets();sheetNum++){
//获得当前sheet工作表
Sheet sheet = workbook.getSheetAt(sheetNum);
if(sheet == null){
continue;
}
//获得当前sheet的开始行
int firstRowNum = sheet.getFirstRowNum();
//获得当前sheet的结束行
int lastRowNum = sheet.getLastRowNum();
//循环除了第一行的所有行
for(int rowNum = firstRowNum+1;rowNum <= lastRowNum;rowNum++){
//获得当前行
Row row = sheet.getRow(rowNum);
if(row == null){
continue;
}
//获得当前行的开始列
int firstCellNum = row.getFirstCellNum();
//获得当前行的列数
int lastCellNum = row.getLastCellNum();
String[] cells = new String[lastCellNum];
//循环当前行
for(int cellNum = firstCellNum; cellNum < lastCellNum;cellNum++){
Cell cell = row.getCell(cellNum);
cells[cellNum] = getCellValue(cell);
}
list.add(cells);
}
}
// workbook.close();
}
return list;
}
public static Workbook getWorkBook(InputStream is,String fileName) {
//创建Workbook工作薄对象,表示整个excel
Workbook workbook = null;
try {
//获取excel文件的io流
//根据文件后缀名不同(xls和xlsx)获得不同的Workbook实现类对象
if(fileName.endsWith(xls)){
//2003
workbook = new HSSFWorkbook(is);
}else if(fileName.endsWith(xlsx)){
//2007 及2007以上
workbook = new XSSFWorkbook(is);
}
} catch (IOException e) {
log.error(e.getMessage());
throw new MyException(Messages.ERROR);
}/*finally {
if(is !=null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}*/
return workbook;
}
对于Excel的解析,以及文件间的上传下载其实都很畏惧,其实,静下心来仔细看看,或许就是新的天地...