跟据客户的要求,需要开发一套包括图形的报表,还需要导出WORD
图表需要这样:
这样:
这样:
还有这样:
接下来是实现思路:
以往用的最多的就是JFreechart,手上也有实现各种图形的资源,但是领导说用它做的图形太丑了, 所以没什么卵用。
FusionCharts到是漂亮,但是没有办法实现上述图表,客户也不能接受替代方案,同样没什么卵用
然后就是百度ECharts,漂亮、功能强大、灵活性强(JS/HTML5实现,可以随意更改源码), 但是有些功能不支待IE8, 还是没什么卵用
想了很多方法,最后又回到了原点,客户要生成Office, 就让Office给我们做,虽然Java对操作图表还没有什么好的方法,但是jacob是可以操作宏,我们通过宏实现所有图表功能。
1、 制作Excel图表模板
制作图表看起来简单,但是做起来相当的慢,好在客户提供一些类似图表,我做了一些调整就可以了 膜拜。。。。。
还有就是网上一堆的制作图表的教程,就不记录了。
2、 通过POI填充数据到Excel
1 /**
2 * 通过填充excel 生成图表
3 * @param list 图标数据
4 * @param inFile 模板文件
5 * @param outFile 输出文件
6 * @return
7 * @throws Exception
8 */
9 public static void createChart(List<Map> list, String inFile,String outFile) {
10 if(list == null) list = new ArrayList();
11
12 System.out.println("图表个数" + list.size());
13 System.out.println("源文件路径" + inFile);
14 System.out.println("图表个数" + outFile);
15
16 try {
17 // 读取模板
18 FileInputStream is = new FileInputStream(inFile);
19 HSSFWorkbook wbs = new HSSFWorkbook(is);
20
21 int sheetIndex;
22 HSSFSheet sheet; //sheet
23 int rowIndex;
24 HSSFRow row; //行
25 int cellIndex;
26 HSSFCell cell; //列
27 String value;
28 float fvalue;
29 String valStr = "^[-+]?(([0-9]+)([.]([0-9]+))?|([.]([0-9]+))?)$";
30
31 List<Integer> sheetList = new ArrayList();
32 for(Map tempMap:list) {
33 // 读取工作表(data)
34 sheetIndex = Integer.parseInt(tempMap.get("SHEETINDEX") + "");
35 sheet = wbs.getSheetAt(sheetIndex-1);
36 sheetList.add(sheetIndex);
37
38 /*
39 int i = 0;
40 List<HSSFPictureData> pictures = wbs.getAllPictures();
41 for (HSSFPictureData picData : pictures) {
42 String ext = picData.suggestFileExtension();
43 byte[] data = picData.getData();
44 System.out.println(data.length);
45
46
47 //savePic(row, picData);
48 /*
49 String ext = picData.suggestFileExtension();
50
51 byte[] data = picData.getData();
52 if (ext.equals("jpeg")) {
53 FileOutputStream out = new FileOutputStream(
54 "D:\\Users\\Fancy1_Fan\\桌面\\work\\pict" + i + ".jpg");
55 out.write(data);
56 out.close();
57 }
58 if (ext.equals("png")) {
59 FileOutputStream out = new FileOutputStream(
60 "D:\\Users\\Fancy1_Fan\\桌面\\work\\pict" + i + ".png");
61 out.write(data);
62 out.close();
63 }*//*
64 i++;
65 }*/
66
67 //添加行
68 rowIndex = Integer.parseInt(tempMap.get("ROWINDEX") + "");
69 row = sheet.getRow(rowIndex-1);
70 if(row == null) row = sheet.createRow(rowIndex-1);
71
72 //列
73 cellIndex = Integer.parseInt(tempMap.get("CELLINDEX") + "");
74 cell = row.getCell(cellIndex-1);
75
76 value = tempMap.get("DATAINFO") + "";
77 if(value.matches(valStr)) {
78 fvalue = Float.parseFloat(value);
79
80 cell.setCellValue(fvalue);
81 } else {
82 cell.setCellValue(value);
83 }
84 //cell.setCellValue(tempMap.get("DATAINFO") + ""); //数据列
85 }
86 for(int temp:sheetList) {
87 sheet = wbs.getSheetAt(temp-1);
88 sheet.setForceFormulaRecalculation(true);
89 }
90
91 // 输出文件
92 FileOutputStream os = new FileOutputStream(outFile);
93 wbs.write(os);
94 is.close();
95 os.close();
96 } catch (Exception e) {
97 e.printStackTrace();
98 }
99 }
操作EXCEL,填充数据
3、 生成宏
我的基本思路是把所有生成的图片复至到一个指定Sheet, 然后Java代码只要到这个Sheet里获取图形
Sheets("QPLJYFJWXSQK").Select
ActiveSheet.ChartObjects("图表 1").Activate
ActiveChart.PlotArea.Select
ActiveChart.ChartArea.Copy
Sheets("CHART").Select
Range("A41").Select
ActiveSheet.Pictures.Paste.Select
ActiveCell.FormulaR1C1 = "QPLJYFJWXSQK"
复制图表生成图形
Sheets("QGJYFJLXSQK").Select
Range("J13:S20").Select
' 复制位图
Selection.CopyPicture Appearance:=xlScreen, Format:=xlBitmap
Sheets("CHART").Select
Range("AA1").Select
'粘贴为图片(问题:复制的位图自动添加边框线,通过裁减的方式删除边框线)
ActiveSheet.Paste
Selection.ShapeRange.PictureFormat.Crop.PictureOffsetX = -1
Selection.ShapeRange.PictureFormat.Crop.PictureOffsetY = -1
Selection.Copy
Range("A1").Select
ActiveSheet.Pictures.Paste.Select
ActiveCell.FormulaR1C1 = "QGJYFJLXSQK"
复制单元格生成图形
只要会VBA 基本语法,其它的如果不会,可以通过录制宏得到
4、 调用宏
先提供工具类
1 package com.wiseda.fc.utils;
2
3 import com.jacob.activeX.ActiveXComponent;
4 import com.jacob.com.ComThread;
5 import com.jacob.com.Dispatch;
6 import com.jacob.com.Variant;
7
8 public class JacobExcelUtils {
9 private static ActiveXComponent xl = null; //Excel对象(防止打开多个)
10 private static Dispatch workbooks = null; //工作簿对象
11 private Dispatch workbook = null; //具体工作簿
12 private Dispatch sheets = null;// 获得sheets集合对象
13 private Dispatch currentSheet = null;// 当前sheet
14
15 public ActiveXComponent getXl() {
16 return xl;
17 }
18
19 public Dispatch getWorkbooks() {
20 return workbooks;
21 }
22
23 public Dispatch getWorkbook() {
24 return workbook;
25 }
26
27 /**
28 * 打开excel文件
29 * @param filepath 文件路径名称
30 * @param visible 是否显示打开
31 * @param readonly 是否只读方式打开
32 */
33 public void OpenExcel(String filepath, boolean visible, boolean readonly) {
34 try {
35 initComponents(); //清空原始变量
36 ComThread.InitSTA();
37 if(xl==null)
38 xl = new ActiveXComponent("Excel.Application"); //Excel对象
39 xl.setProperty("Visible", new Variant(visible));//设置是否显示打开excel
40 if(workbooks==null)
41 workbooks = xl.getProperty("Workbooks").toDispatch(); //工作簿对象
42 workbook = Dispatch.invoke( //打开具体工作簿
43 workbooks,
44 "Open",
45 Dispatch.Method,
46 new Object[] { filepath, new Variant(false),
47 new Variant(readonly) },// 是否以只读方式打开
48 new int[1]).toDispatch();
49 } catch (Exception e) {
50 e.printStackTrace();
51 releaseSource();
52 }
53 }
54
55 /**
56 * 工作簿另存为
57 * @param filePath 另存为的路径
58 */
59 public void SaveAs(String filePath){
60 Dispatch.invoke(workbook, "SaveAs", Dispatch.Method,
61 new Object[] { filePath,
62 new Variant(44) }, new int[1]);
63 }
64
65 /**
66 * 关闭excel文档
67 * @param f 含义不明 (关闭是否保存?默认false)
68 */
69 public void CloseExcel(boolean f,boolean quitXl) {
70 try {
71 Dispatch.call(workbook, "Save");
72 Dispatch.call(workbook, "Close", new Variant(f));
73 } catch (Exception e) {
74 e.printStackTrace();
75 } finally {
76 if(quitXl){
77 releaseSource();
78 }
79 }
80 }
81
82 /**
83 * 释放资源
84 */
85 public static void releaseSource(){
86 if(xl!=null){
87 xl.invoke("Quit", new Variant[] {});
88 xl = null;
89 }
90 workbooks = null;
91 ComThread.Release();
92 System.gc();
93 }
94
95 /**
96 * 添加新的工作表(sheet),(添加后为默认为当前激活的工作表)
97 */
98 public Dispatch addSheet() {
99 return Dispatch.get(Dispatch.get(workbook, "sheets").toDispatch(), "add").toDispatch();
100 }
101
102 /**
103 * 修改当前工作表的名字
104 * @param newName
105 */
106 public void modifyCurrentSheetName(String newName) {
107 Dispatch.put(getCurrentSheet(), "name", newName);
108 }
109
110 /**
111 * 得到当前工作表的名字
112 * @return
113 */
114 public String getCurrentSheetName() {
115 return Dispatch.get(getCurrentSheet(), "name").toString();
116 }
117
118 /**
119 * 得到工作薄的名字
120 * @return
121 */
122 public String getWorkbookName() {
123 if(workbook==null)
124 return null;
125 return Dispatch.get(workbook, "name").toString();
126 }
127
128 /**
129 * 得到sheets的集合对象
130 * @return
131 */
132 public Dispatch getSheets() {
133 if(sheets==null)
134 sheets = Dispatch.get(workbook, "sheets").toDispatch();
135 return sheets;
136 }
137
138 /**
139 * 得到当前sheet
140 * @return
141 */
142 public Dispatch getCurrentSheet() {
143 currentSheet = Dispatch.get(workbook, "ActiveSheet").toDispatch();
144 return currentSheet;
145 }
146
147 /**
148 * 通过工作表名字得到工作表
149 * @param name sheetName
150 * @return
151 */
152 public Dispatch getSheetByName(String name) {
153 return Dispatch.invoke(getSheets(), "Item", Dispatch.Get, new Object[]{name}, new int[1]).toDispatch();
154 }
155
156 /**
157 * 通过工作表索引得到工作表(第一个工作簿index为1)
158 * @param index
159 * @return sheet对象
160 */
161 public Dispatch getSheetByIndex(Integer index) {
162 return Dispatch.invoke(getSheets(), "Item", Dispatch.Get, new Object[]{index}, new int[1]).toDispatch();
163 }
164
165 /**
166 * 得到sheet的总数
167 * @return
168 */
169 public int getSheetCount() {
170 int count = Dispatch.get(getSheets(), "count").toInt();
171 return count;
172 }
173
174 /**
175 * 调用excel宏
176 * @param macroName 宏名
177 */
178 public void callMacro(String macroName){
179 Dispatch.call(xl, "Run",new Variant(macroName));
180 }
181
182 /**
183 * 单元格写入值
184 * @param sheet 被操作的sheet
185 * @param position 单元格位置,如:C1
186 * @param type 值的属性 如:value
187 * @param value
188 */
189 public void setValue(Dispatch sheet, String position, String type, Object value) {
190
191 Dispatch cell = Dispatch.invoke(sheet, "Range",
192 Dispatch.Get, new Object[] { position }, new int[1])
193 .toDispatch();
194 Dispatch.put(cell, type, value);
195 }
196
197 /**
198 * 单元格读取值
199 * @param position 单元格位置,如: C1
200 * @param sheet
201 * @return
202 */
203 public Variant getValue(String position, Dispatch sheet) {
204 Dispatch cell = Dispatch.invoke(sheet, "Range", Dispatch.Get,
205 new Object[] { position }, new int[1]).toDispatch();
206 Variant value = Dispatch.get(cell, "Value");
207 return value;
208 }
209
210 private void initComponents(){
211 workbook = null;
212 currentSheet = null;
213 sheets = null;
214 }
215 }
jacob工具类
调用宏代码
1 public void excelPictureGrab() throws Exception {
2 this.targetFile = new File(targetFilePath);
3
4 //复制文件
5 FileUtils.copyFile(xlsFile, targetFile);
6
7 logger.info("文件复至完成");
8
9 //生成带图形的 excel
10 JacobExcelUtils tool = new JacobExcelUtils();
11 try {
12 tool.OpenExcel(targetFilePath, false, false);
13
14 logger.info("打开Excel");
15
16 //执行宏 复制为图片
17 tool.callMacro("copyImg");
18
19 logger.info("处理宏完成");
20 } catch (Exception e) {
21 throw new Exception("执行宏出错," + e.getMessage());
22 // TODO: handle exception
23 } finally {
24 // 关闭流
25 tool.CloseExcel(false, true);
26 }
27 }
5、 获取图表
1 //获取图片字节流
2 public static String getPic(String fileUrl,String backupUrl) throws Exception {
3 StringBuffer results = new StringBuffer();
4
5 File tfdir = new File(backupUrl);
6 if (!tfdir.exists()) tfdir.mkdirs();
7
8 InputStream inp = new FileInputStream(fileUrl);
9 HSSFWorkbook workbook = (HSSFWorkbook) WorkbookFactory.create(inp);
10
11 List<HSSFPictureData> pictures = workbook.getAllPictures();
12 HSSFSheet sheet = (HSSFSheet) workbook.getSheetAt(0); //所有图片都存在第一页
13
14 int i = 0;
15 for (HSSFShape shape : sheet.getDrawingPatriarch().getChildren()) {
16 HSSFClientAnchor anchor = (HSSFClientAnchor) shape.getAnchor();
17
18 if (shape instanceof HSSFPicture) {
19 HSSFPicture pic = (HSSFPicture) shape;
20 int pictureIndex = pic.getPictureIndex()-1;
21
22 //图片名称
23 int row = anchor.getRow1();
24
25 System.out.println(anchor.getCol1());
26
27 HSSFCell picCell = sheet.getRow(row).getCell(anchor.getCol1());
28
29 String picName = "";
30 if(picCell != null) {
31 picName = picCell.getStringCellValue();
32 }
33
34
35 logger.info(i + "--->row." + anchor.getRow1() + ":cell." + anchor.getCol1() + ":pictureIndex." + pictureIndex);
36
37 HSSFPictureData picData = pictures.get(pictureIndex);
38
39 //备份并返回 图片
40 if(picName != null && !"".equals(picName)) {
41 String result = BackupPic(picName, picData,backupUrl);
42 results.append(result);
43 results.append(",");
44 }
45 }
46 i++;
47 }
48
49 return results.toString();
50 }
51
52 //备份图片
53 private static String BackupPic(String picName,PictureData pic,String backupUrl) throws Exception {
54 String result = "";
55
56 String pngImgUrl,jpgImgUrl;
57 String ext = pic.suggestFileExtension();
58 byte[] data = pic.getData();
59 if (ext.equals("png")) {
60
61 pngImgUrl = backupUrl + picName + "." + ext;
62 FileOutputStream out = new FileOutputStream(
63 pngImgUrl);
64 out.write(data);
65 out.close();
66
67 //转为 jpg
68 jpgImgUrl = backupUrl + picName + ".jpg";
69 ConvertPngToJpg(pngImgUrl,jpgImgUrl);
70
71 result = picName + ":" + DatatypeConverter.printBase64Binary(data);
72 }
73
74 return result;
75 }
76
77 //压缩图片 把PND图片转JPG
78 private static void ConvertPngToJpg(String pngImgUrl,String jpgImgUrl) {
79 BufferedImage bufferedImage;
80 try {
81
82 //read image file
83 bufferedImage = ImageIO.read(new File(pngImgUrl));
84
85 // create a blank, RGB, same width and height, and a white background
86 BufferedImage newBufferedImage = new BufferedImage(bufferedImage.getWidth(),
87 bufferedImage.getHeight(), BufferedImage.TYPE_INT_RGB);
88 newBufferedImage.createGraphics().drawImage(bufferedImage, 0, 0, Color.WHITE, null);
89
90 // write to jpeg file
91 ImageIO.write(newBufferedImage, "jpg", new File(jpgImgUrl));
92
93 } catch (IOException e) {
94
95 e.printStackTrace();
96
97 }
98 }
获得excel图片
1 //获取图片字节流
2 public static String getPic(String fileUrl,String backupUrl) throws Exception {
3 StringBuffer results = new StringBuffer();
4
5 File tfdir = new File(backupUrl);
6 if (!tfdir.exists()) tfdir.mkdirs();
7
8 InputStream inp = new FileInputStream(fileUrl);
9 HSSFWorkbook workbook = (HSSFWorkbook) WorkbookFactory.create(inp);
10
11 List<HSSFPictureData> pictures = workbook.getAllPictures();
12 HSSFSheet sheet = (HSSFSheet) workbook.getSheetAt(0); //所有图片都存在第一页
13
14 int i = 0;
15 for (HSSFShape shape : sheet.getDrawingPatriarch().getChildren()) {
16 HSSFClientAnchor anchor = (HSSFClientAnchor) shape.getAnchor();
17
18 if (shape instanceof HSSFPicture) {
19 HSSFPicture pic = (HSSFPicture) shape;
20 int pictureIndex = pic.getPictureIndex()-1;
21
22 //图片名称
23 int row = anchor.getRow1();
24
25 System.out.println(anchor.getCol1());
26
27 HSSFCell picCell = sheet.getRow(row).getCell(anchor.getCol1());
28
29 String picName = "";
30 if(picCell != null) {
31 picName = picCell.getStringCellValue();
32 }
33
34
35 logger.info(i + "--->row." + anchor.getRow1() + ":cell." + anchor.getCol1() + ":pictureIndex." + pictureIndex);
36
37 HSSFPictureData picData = pictures.get(pictureIndex);
38
39 //备份并返回 图片
40 if(picName != null && !"".equals(picName)) {
41 String result = BackupPic(picName, picData,backupUrl);
42 results.append(result);
43 results.append(",");
44 }
45 }
46 i++;
47 }
48
49 return results.toString();
50 }
51
52 //备份图片
53 private static String BackupPic(String picName,PictureData pic,String backupUrl) throws Exception {
54 String result = "";
55
56 String pngImgUrl,jpgImgUrl;
57 String ext = pic.suggestFileExtension();
58 byte[] data = pic.getData();
59 if (ext.equals("png")) {
60
61 pngImgUrl = backupUrl + picName + "." + ext;
62 FileOutputStream out = new FileOutputStream(
63 pngImgUrl);
64 out.write(data);
65 out.close();
66
67 //转为 jpg
68 jpgImgUrl = backupUrl + picName + ".jpg";
69 ConvertPngToJpg(pngImgUrl,jpgImgUrl);
70
71 result = picName + ":" + DatatypeConverter.printBase64Binary(data);
72 }
73
74 return result;
75 }
76
77 //压缩图片 把PND图片转JPG
78 private static void ConvertPngToJpg(String pngImgUrl,String jpgImgUrl) {
79 BufferedImage bufferedImage;
80 try {
81
82 //read image file
83 bufferedImage = ImageIO.read(new File(pngImgUrl));
84
85 // create a blank, RGB, same width and height, and a white background
86 BufferedImage newBufferedImage = new BufferedImage(bufferedImage.getWidth(),
87 bufferedImage.getHeight(), BufferedImage.TYPE_INT_RGB);
88 newBufferedImage.createGraphics().drawImage(bufferedImage, 0, 0, Color.WHITE, null);
89
90 // write to jpeg file
91 ImageIO.write(newBufferedImage, "jpg", new File(jpgImgUrl));
92
93 } catch (IOException e) {
94
95 e.printStackTrace();
96
97 }
98 }
获得excel图片