JAVA生成EXCEL图表

跟据客户的要求,需要开发一套包括图形的报表,还需要导出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图片

 

posted @ 2015-08-07 17:48  Nadim  阅读(5933)  评论(1编辑  收藏  举报