jxl是一款java读写office——Excel文件的工具。通过java程序进行Excel文件的读写操作。
操作Excel首先应该明确操作过程中java针对Excel文件的对象分类
根据业务功能,制作适用于项目的工具类
1.创建的文件对象需要在服务器端形成才可以下载,大量浪费服务器资源,因此创建的文件只需要获取到流对象即可,使用jxl提供的创建可写工作表对象,绑定输出流对象
/** * 创建Excel文件流 * @return */ public static WritableWorkbook cWorkbook(OutputStream os){ try { return Workbook.createWorkbook(os); } catch (IOException e) { e.printStackTrace(); return null; } }
2.工作表创建时,需要指定工作表名称与其所在位置,因此,定义创建工作表方法,使其更符合中国人的开发习惯
/** * 创建工作表 * @param b * @param idx 工作表索引,从1开始 * @param name 工作表显示名称 * @return */ public static WritableSheet cSheet(WritableWorkbook b,int idx,String name){ return b.createSheet(name, idx-1); }
3.工作表的数据展示需要依赖于Label对象进行,根据中国人的习惯,第一个单元格为1行1列,改造适用的创建单元格的方法
/** * 创建单元格 * @param a 行 * @param b 列 * @param value 值 * @return */ public static Label cLabel(int a ,int b ,String value){ return new Label(b-1, a-1, value); }
4.Label对象创建完毕后,需要将其添加到工作表对象中,创建对应的方法,以add的首字母a进行命名
/** * 添加Label到Sheet * @param l label * @param s sheet */ public static void aLabelToSheet(Label l,WritableSheet s){ try { s.addCell(l); } catch (Exception e) { e.printStackTrace(); } }
此处不要将两个方法设置成一个方法,否则Label对象将无法进行样式修改
5.创建设置工作表单元格宽度与高度的方法,用于调整工作表的宽和高。此处以工作表显示单位为基准,宽度不进行修改,高度需要*20。注意设置宽度与高度不是绑定工作表,而是设置基准行与类,默认从0开始,修改成中国人的习惯。
/** * 设置工作表列宽 * @param s * @param idx 索引从1开始 * @param width 字符宽度 */ public static void sColumnSize(WritableSheet s,int idx,int width){ s.setColumnView(idx-1, width); } /** * 设置工作表高度 * @param s * @param idx 索引从1开始 * @param height 字符高度 */ public static void sRowSize(WritableSheet s,int idx,int height){ try { s.setRowView(idx-1, height*20); } catch (Exception e) { e.printStackTrace(); }
6.单元格合并操作在文件中很常见,设置对应的工具方法,快速使用,以中国人的习惯进行参数设置,从第A行,第B列合并到第C行,第D列
/** * 设置单元格合并 * @param a 起始单元格行 * @param b 起始单元格列 * @param c 终止单元格行 * @param d 终止单元格列 */ public static void sMerge(WritableSheet s,int a,int b,int c,int d){ try { s.mergeCells(b-1, a-1, d-1, c-1); } catch (Exception e) { e.printStackTrace(); } }
7.单元格样式是修饰的重点,该操作可以根据个人喜好进行设计
/** * 设置单元格样式 * @param l * @param fontName 字体:字符串,如"黑体" * @param fontSize 字号:数字,如24 * @param colour 字体颜色:Colour常量 * @param bgColour 单元格背景色:Colour常量 * @param align 对齐模式:0-左;1-中;2-右 * @param borderStyle 边框线样式:字符串,如0000代表上下左右都不要边框, * 如1100代表上下要边框,如0011代表左右要边框,如果0220代表左边和下边要粗边框 */ public static void sLabelStyle( Label l,String fontName,int fontSize, Colour colour,Colour bgColour, int align,String borderStyle){ try { if(colour == null) colour = Colour.BLACK; if(bgColour == null) bgColour = Colour.WHITE; WritableFont wf = new WritableFont( //设置字体 WritableFont.createFont(fontName), //设置字号 fontSize, //设置加粗 WritableFont.NO_BOLD, //设置倾斜 false, //设置下划线 UnderlineStyle.NO_UNDERLINE, //设置字体颜色 colour); WritableCellFormat wcf = new WritableCellFormat(wf); //设置背景色 wcf.setBackground(bgColour); //设置对其方式 wcf.setAlignment(Alignment.CENTRE); //设置边框 if(borderStyle != null && borderStyle.length() == 4){ char[] bs = borderStyle.toCharArray(); if(bs[0] == '1'){ wcf.setBorder(Border.TOP, BorderLineStyle.THIN,jxl.format.Colour.BLACK); }else if(bs[0] == '2'){ wcf.setBorder(Border.TOP, BorderLineStyle.MEDIUM,jxl.format.Colour.BLACK); } if(bs[1] == '1'){ wcf.setBorder(Border.BOTTOM, BorderLineStyle.THIN,jxl.format.Colour.BLACK); }else if(bs[1] == '2'){ wcf.setBorder(Border.BOTTOM, BorderLineStyle.MEDIUM,jxl.format.Colour.BLACK); } if(bs[2] == '1'){ wcf.setBorder(Border.LEFT, BorderLineStyle.THIN,jxl.format.Colour.BLACK); }else if(bs[2] == '2'){ wcf.setBorder(Border.LEFT, BorderLineStyle.MEDIUM,jxl.format.Colour.BLACK); } if(bs[3] == '1'){ wcf.setBorder(Border.RIGHT, BorderLineStyle.THIN,jxl.format.Colour.BLACK); }else if(bs[3] == '2'){ wcf.setBorder(Border.RIGHT, BorderLineStyle.MEDIUM,jxl.format.Colour.BLACK); } } l.setCellFormat(wcf); } catch (Exception e) { e.printStackTrace(); } }
8.源码
package org.sihai.qualitycontrol.util.jxl; import java.io.IOException; import java.io.OutputStream; import java.util.HashMap; import java.util.Map; import jxl.Workbook; import jxl.format.Alignment; import jxl.format.Border; import jxl.format.BorderLineStyle; import jxl.format.Colour; import jxl.format.UnderlineStyle; import jxl.write.Label; import jxl.write.WritableCellFormat; import jxl.write.WritableFont; import jxl.write.WritableSheet; import jxl.write.WritableWorkbook; //操作Excel文件工具类 public class JxlUtil { /** * 创建Excel文件流 * @return */ public static WritableWorkbook cWorkbook(OutputStream os){ try { return Workbook.createWorkbook(os); } catch (IOException e) { e.printStackTrace(); return null; } } /** * 创建工作表 * @param b * @param idx 工作表索引,从1开始 * @param name 工作表显示名称 * @return */ public static WritableSheet cSheet(WritableWorkbook b,int idx,String name){ return b.createSheet(name, idx-1); } /** * 创建单元格 * @param a 行 * @param b 列 * @param value 值 * @return */ public static Label cLabel(int a ,int b ,String value){ return new Label(b-1, a-1, value); } /** * 添加Label到Sheet * @param l label * @param s sheet */ public static void aLabelToSheet(Label l,WritableSheet s){ try { s.addCell(l); } catch (Exception e) { e.printStackTrace(); } } /** * 设置工作表列宽 * @param s * @param idx 索引从1开始 * @param width 字符宽度 */ public static void sColumnSize(WritableSheet s,int idx,int width){ s.setColumnView(idx-1, width); } /** * 设置工作表高度 * @param s * @param idx 索引从1开始 * @param height 字符高度 */ public static void sRowSize(WritableSheet s,int idx,int height){ try { s.setRowView(idx-1, height*20); } catch (Exception e) { e.printStackTrace(); } } /** * 设置单元格合并 * @param a 起始单元格行 * @param b 起始单元格列 * @param c 终止单元格行 * @param d 终止单元格列 */ public static void sMerge(WritableSheet s,int a,int b,int c,int d){ try { s.mergeCells(b-1, a-1, d-1, c-1); } catch (Exception e) { e.printStackTrace(); } } private static Map<Integer, Alignment> alignMap = new HashMap<Integer, Alignment>(); static{ alignMap.put(0, Alignment.LEFT); alignMap.put(1, Alignment.CENTRE); alignMap.put(2, Alignment.RIGHT); } /** * 设置单元格样式 * @param l * @param fontName 字体:字符串,如"黑体" * @param fontSize 字号:数字,如24 * @param colour 字体颜色:Colour常量 * @param bgColour 单元格背景色:Colour常量 * @param align 对齐模式:0-左;1-中;2-右 * @param borderStyle 边框线样式:字符串,如0000代表上下左右都不要边框, * 如1100代表上下要边框,如0011代表左右要边框,如果0220代表左边和下边要粗边框 */ public static void sLabelStyle( Label l,String fontName,int fontSize, Colour colour,Colour bgColour, int align,String borderStyle){ try { if(colour == null) colour = Colour.BLACK; if(bgColour == null) bgColour = Colour.WHITE; WritableFont wf = new WritableFont( //设置字体 WritableFont.createFont(fontName), //设置字号 fontSize, //设置加粗 WritableFont.NO_BOLD, //设置倾斜 false, //设置下划线 UnderlineStyle.NO_UNDERLINE, //设置字体颜色 colour); WritableCellFormat wcf = new WritableCellFormat(wf); //设置背景色 wcf.setBackground(bgColour); //设置对其方式 wcf.setAlignment(Alignment.CENTRE); //设置边框 if(borderStyle != null && borderStyle.length() == 4){ char[] bs = borderStyle.toCharArray(); if(bs[0] == '1'){ wcf.setBorder(Border.TOP, BorderLineStyle.THIN,jxl.format.Colour.BLACK); }else if(bs[0] == '2'){ wcf.setBorder(Border.TOP, BorderLineStyle.MEDIUM,jxl.format.Colour.BLACK); } if(bs[1] == '1'){ wcf.setBorder(Border.BOTTOM, BorderLineStyle.THIN,jxl.format.Colour.BLACK); }else if(bs[1] == '2'){ wcf.setBorder(Border.BOTTOM, BorderLineStyle.MEDIUM,jxl.format.Colour.BLACK); } if(bs[2] == '1'){ wcf.setBorder(Border.LEFT, BorderLineStyle.THIN,jxl.format.Colour.BLACK); }else if(bs[2] == '2'){ wcf.setBorder(Border.LEFT, BorderLineStyle.MEDIUM,jxl.format.Colour.BLACK); } if(bs[3] == '1'){ wcf.setBorder(Border.RIGHT, BorderLineStyle.THIN,jxl.format.Colour.BLACK); }else if(bs[3] == '2'){ wcf.setBorder(Border.RIGHT, BorderLineStyle.MEDIUM,jxl.format.Colour.BLACK); } } l.setCellFormat(wcf); } catch (Exception e) { e.printStackTrace(); } } }
根据业务功能,制作业务层方法,返回流对象,用于Action下载,而不要返回文件对象。
1.创建业务层方法,返回InputStream
2.创建字节数组输出流对象,用于读取创建出的Excel文件
3.读取要组织成Excel文件的数据
4.创建待显示数据对应的Excel写文件对象,并进行文件拼写
参看源码
5.将工作表对象写出到流
6.进行输出流转换输入流对象,否则struts2文件下载无法使用
Struts2提供文件下载功能的快速开发格式,可针对流数据进行转化,最终形成下载文件。
1.Action类中设置方法用于初始化下载文件对应的流对象,此处需要的是输入流对象
//下载excel报表 public String downloadExcelBill() throws Exception{ //将要下载的内容写入downloadExcelStreamn中 xlsName = "采购报表.xls"; downloadExcelStreamn = billEbi.getWriteExcelStream(bqm); return "downloadExcelBill"; }
2.设置对应的结果集,并设置返回类型为流对象
3.设置返回流对象,需要设置返回流对象名,并提供对应输入流对象getter方法
4.设置返回类型中的对象名
5.下载文件类型根据所下载文件不同,进行设置
如果不清楚下载文件类型设置内容,可以通过查看tomcat中核心web.xml获取对应的设置值
Tomcat安装目录下的conf目录下的web.xml文件查找对应类型
设置下载文件类型,并设置对应字符集
PS:记得声明字符集为iso-8859-1
6.设置下载文件显示名称
7.Action类中定义getter方法,用于获取文件名
记得文件名转码,否则无法显示中文
8.在Action中初始化要显示的文件名
9.初始化业务层提供的Excel文件流对象
10、文件下载源码
private InputStream downloadExcelStreamn; public InputStream getDownloadExcelStreamn() { return downloadExcelStreamn; } private String xlsName; public String getXlsName() throws UnsupportedEncodingException { //字符级要进行过滤 //xlsName->byte[]->string return new String(xlsName.getBytes("utf-8"),"iso8859-1"); } //下载excel报表 public String downloadExcelBill() throws Exception{ //将要下载的内容写入downloadExcelStreamn中 xlsName = "采购报表.xls"; downloadExcelStreamn = billEbi.getWriteExcelStream(bqm); return "downloadExcelBill"; }
package org.sihai.qualitycontrol.invoice.bill.business.ebo; import java.awt.Font; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.util.List; import javax.imageio.ImageIO; import jxl.Workbook; import jxl.format.Colour; import jxl.write.Label; import jxl.write.WritableSheet; import jxl.write.WritableWorkbook; import org.jfree.chart.ChartFactory; import org.jfree.chart.JFreeChart; import org.jfree.chart.StandardChartTheme; import org.jfree.chart.plot.PiePlot; import org.jfree.data.general.DefaultPieDataset; import org.sihai.qualitycontrol.invoice.bill.business.ebi.BillEbi; import org.sihai.qualitycontrol.invoice.bill.dao.dao.BillDao; import org.sihai.qualitycontrol.invoice.bill.vo.BillQueryModel; import org.sihai.qualitycontrol.invoice.goods.vo.GoodsModel; import org.sihai.qualitycontrol.invoice.orderdetail.vo.OrderDetailModel; import org.sihai.qualitycontrol.util.jxl.JxlUtil; public class BillEbo implements BillEbi{ static { StandardChartTheme theme = new StandardChartTheme("unicode") { public void apply(JFreeChart chart) { chart.getRenderingHints().put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); super.apply(chart); } }; theme.setExtraLargeFont(new Font("宋体", Font.PLAIN, 20)); theme.setLargeFont(new Font("宋体", Font.PLAIN, 14)); theme.setRegularFont(new Font("宋体", Font.PLAIN, 12)); theme.setSmallFont(new Font("宋体", Font.PLAIN, 10)); ChartFactory.setChartTheme(theme); } private BillDao billDao; public void setBillDao(BillDao billDao) { this.billDao = billDao; } public List<Object[]> getBuyBill(BillQueryModel bqm) { return billDao.getBuyBill(bqm); } public List<OrderDetailModel> getBuyBillDetail(BillQueryModel bqm) { return billDao.getBuyBillDetail(bqm); } public void writeJFreeChartToOs(OutputStream os,BillQueryModel bqm) throws Exception{ List<Object[]> temp = billDao.getBuyBill(bqm); //jfc->os DefaultPieDataset dataSet = new DefaultPieDataset(); for(Object[] objs:temp){ GoodsModel gm = (GoodsModel)objs[0]; Long sum = (Long) objs[1]; dataSet.setValue(gm.getName(), new Double(sum)); } //由数据生成图形 JFreeChart jfc = ChartFactory.createPieChart("采购报表", dataSet, true, false, false); PiePlot plot = (PiePlot) jfc.getPlot(); plot.setLabelFont(new Font("SansSerif", 0, 12)); plot.setNoDataMessage("无查询结果报表信息!"); plot.setCircular(true); plot.setLabelGap(0.02D); //jfc对象已经存在 BufferedImage bi = jfc.createBufferedImage(500, 370); ImageIO.write(bi, "PNG", os); } public InputStream getWriteExcelStream(BillQueryModel bqm) throws Exception { List<Object[]> temp = billDao.getBuyBill(bqm); //将excel文件写入流中 ByteArrayOutputStream bos = new ByteArrayOutputStream(); WritableWorkbook w = Workbook.createWorkbook(bos); WritableSheet s = w.createSheet("总括", 0); //设置单元格宽度 JxlUtil.sColumnSize(s, 1, 8); JxlUtil.sColumnSize(s, 2, 8); JxlUtil.sColumnSize(s, 3, 25); JxlUtil.sColumnSize(s, 4, 25); JxlUtil.sColumnSize(s, 5, 25); //设置单元格高度 JxlUtil.sRowSize(s, 1, 15); JxlUtil.sRowSize(s, 2, 37); JxlUtil.sRowSize(s, 3, 6); JxlUtil.sRowSize(s, 4, 23); //设置合并单元格 JxlUtil.sMerge(s, 2,2,2,4); JxlUtil.sMerge(s, 3,2,3,5); Label lab22 = JxlUtil.cLabel(2, 2, "进货统计报表"); JxlUtil.sLabelStyle(lab22, "黑体", 24, Colour.BLACK, Colour.LIGHT_BLUE, 1, "2020"); JxlUtil.aLabelToSheet(lab22, s); Label lab25 = JxlUtil.cLabel(2, 5, "不限"); JxlUtil.sLabelStyle(lab25, "黑体", 12, Colour.BLACK, Colour.LIGHT_BLUE, 1, "2002"); JxlUtil.aLabelToSheet(lab25, s); Label lab32 = JxlUtil.cLabel(3, 2, ""); JxlUtil.sLabelStyle(lab32, "黑体", 1, Colour.BLACK, Colour.GRAY_25, 1, "2022"); JxlUtil.aLabelToSheet(lab32, s); Label lab42 = JxlUtil.cLabel(4, 2, "编号"); JxlUtil.sLabelStyle(lab42, "黑体", 18, Colour.BLACK, Colour.WHITE, 1, "2220"); JxlUtil.aLabelToSheet(lab42, s); Label lab43 = JxlUtil.cLabel(4, 3, "厂商"); JxlUtil.sLabelStyle(lab43, "黑体", 18, Colour.BLACK, Colour.WHITE, 1, "2220"); JxlUtil.aLabelToSheet(lab43, s); Label lab44 = JxlUtil.cLabel(4, 4, "商品名"); JxlUtil.sLabelStyle(lab44, "黑体", 18, Colour.BLACK, Colour.WHITE, 1, "2220"); JxlUtil.aLabelToSheet(lab44, s); Label lab45 = JxlUtil.cLabel(4, 5, "数量"); JxlUtil.sLabelStyle(lab45, "黑体", 18, Colour.BLACK, Colour.WHITE, 1, "2222"); JxlUtil.aLabelToSheet(lab45, s); int row = 5; int i = 0; Long sumAll = 0L; for(Object[] objs:temp){ GoodsModel gm = (GoodsModel)objs[0]; Long sum = (Long)objs[1]; //设置行高 JxlUtil.sRowSize(s, row+i, 19); //创建所有单元格 Label lab_data_1 = JxlUtil.cLabel(row+i, 2, i+1+""); JxlUtil.sLabelStyle(lab_data_1, "宋体", 14, Colour.BLACK, Colour.WHITE, 1, "0120"); JxlUtil.aLabelToSheet(lab_data_1, s); Label lab_data_2 = JxlUtil.cLabel(row+i, 3, gm.getGtm().getSm().getName()); JxlUtil.sLabelStyle(lab_data_2, "宋体", 14, Colour.BLACK, Colour.WHITE, 1, "0110"); JxlUtil.aLabelToSheet(lab_data_2, s); Label lab_data_3 = JxlUtil.cLabel(row+i, 4, gm.getName()); JxlUtil.sLabelStyle(lab_data_3, "宋体", 14, Colour.BLACK, Colour.WHITE, 1, "0110"); JxlUtil.aLabelToSheet(lab_data_3, s); Label lab_data_4 = JxlUtil.cLabel(row+i, 5, sum.toString()); JxlUtil.sLabelStyle(lab_data_4, "宋体", 14, Colour.BLACK, Colour.WHITE, 1, "0112"); JxlUtil.aLabelToSheet(lab_data_4, s); i++; sumAll += sum; } //设置最后一行高度 JxlUtil.sRowSize(s, row+i , 25); //设置最后一行的合并 JxlUtil.sMerge(s, row+i, 2, row+i, 4); Label lab_tail_1 = JxlUtil.cLabel(row+i, 2, "总计:"); JxlUtil.sLabelStyle(lab_tail_1, "黑体", 18, Colour.BLACK, Colour.WHITE, 1, "2220"); JxlUtil.aLabelToSheet(lab_tail_1, s); Label lab_tail_2 = JxlUtil.cLabel(row+i, 5, sumAll.toString()); JxlUtil.sLabelStyle(lab_tail_2, "黑体", 18, Colour.BLACK, Colour.WHITE, 1, "2222"); JxlUtil.aLabelToSheet(lab_tail_2, s); w.write(); w.close(); //当前excel文件的内容已经写入到流os对象中,该流是一个输出流 //表现层需要的是输入流 //输出流转输入流 //ByteArrayOutputStream->inputStream ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); return bis; } }
如果想获取更多源码或者视频教程,欢迎关注我的微信公众号 好好学java
,在公众号里,回复: java基础、html5、javaEE基础、struts2、spring、redis、luncene、oracle
等,将可获得以上的优质视频教程及源码。