zoukankan      html  css  js  c++  java
  • 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图片
  • 相关阅读:
    netlink(todo)
    【拓展】如何画好架构图
    【JS】527- 关于 JS 中的浮点计算
    【CSS】526- CSS 控制图标颜色
    【拓展】一个故事讲完CPU的工作原理
    【面试题】525- 阿里 P6 的面经
    【生活】你在第几楼?80后、90后扎心图鉴
    【JS】524- 三分钟迁移 Ant Design 4
    【Web技术】522- 设计体系的响应式设计
    【适配】521- 移动端开发各种兼容适配问题(屏幕、图像、字体与布局等)
  • 原文地址:https://www.cnblogs.com/Nadim/p/4644658.html
Copyright © 2011-2022 走看看