跟据客户的要求,需要开发一套包括图形的报表,还需要导出WORD

图表需要这样:

这样:

  

这样:

  

还有这样:

  

接下来是实现思路:

  以往用的最多的就是JFreechart,手上也有实现各种图形的资源,但是领导说用它做的图形太丑了, 所以没什么卵用。

  FusionCharts到是漂亮,但是没有办法实现上述图表,客户也不能接受替代方案,同样没什么卵用

  然后就是百度ECharts,漂亮、功能强大、灵活性强(JS/HTML5实现,可以随意更改源码), 但是有些功能不支待IE8, 还是没什么卵用

想了很多方法,最后又回到了原点,客户要生成Office, 就让Office给我们做,虽然Java对操作图表还没有什么好的方法,但是jacob是可以操作宏,我们通过宏实现所有图表功能。

1、 制作Excel图表模板
  制作图表看起来简单,但是做起来相当的慢,好在客户提供一些类似图表,我做了一些调整就可以了  膜拜。。。。。

  还有就是网上一堆的制作图表的教程,就不记录了。

2、 通过POI填充数据到Excel

 /**
* 通过填充excel 生成图表
* @param list 图标数据
* @param inFile 模板文件
* @param outFile 输出文件
* @return
* @throws Exception
*/
public static void createChart(List<Map> list, String inFile,String outFile) {
if(list == null) list = new ArrayList(); System.out.println("图表个数" + list.size());
System.out.println("源文件路径" + inFile);
System.out.println("图表个数" + outFile); try {
// 读取模板
FileInputStream is = new FileInputStream(inFile);
HSSFWorkbook wbs = new HSSFWorkbook(is); int sheetIndex;
HSSFSheet sheet; //sheet
int rowIndex;
HSSFRow row; //行
int cellIndex;
HSSFCell cell; //列
String value;
float fvalue;
String valStr = "^[-+]?(([0-9]+)([.]([0-9]+))?|([.]([0-9]+))?)$"; List<Integer> sheetList = new ArrayList();
for(Map tempMap:list) {
// 读取工作表(data)
sheetIndex = Integer.parseInt(tempMap.get("SHEETINDEX") + "");
sheet = wbs.getSheetAt(sheetIndex-);
sheetList.add(sheetIndex); /*
int i = 0;
List<HSSFPictureData> pictures = wbs.getAllPictures();
for (HSSFPictureData picData : pictures) {
String ext = picData.suggestFileExtension();
byte[] data = picData.getData();
System.out.println(data.length); //savePic(row, picData);
/*
String ext = picData.suggestFileExtension(); byte[] data = picData.getData();
if (ext.equals("jpeg")) {
FileOutputStream out = new FileOutputStream(
"D:\\Users\\Fancy1_Fan\\桌面\\work\\pict" + i + ".jpg");
out.write(data);
out.close();
}
if (ext.equals("png")) {
FileOutputStream out = new FileOutputStream(
"D:\\Users\\Fancy1_Fan\\桌面\\work\\pict" + i + ".png");
out.write(data);
out.close();
}*//*
i++;
}*/ //添加行
rowIndex = Integer.parseInt(tempMap.get("ROWINDEX") + "");
row = sheet.getRow(rowIndex-);
if(row == null) row = sheet.createRow(rowIndex-); //列
cellIndex = Integer.parseInt(tempMap.get("CELLINDEX") + "");
cell = row.getCell(cellIndex-); value = tempMap.get("DATAINFO") + "";
if(value.matches(valStr)) {
fvalue = Float.parseFloat(value); cell.setCellValue(fvalue);
} else {
cell.setCellValue(value);
}
//cell.setCellValue(tempMap.get("DATAINFO") + ""); //数据列
}
for(int temp:sheetList) {
sheet = wbs.getSheetAt(temp-);
sheet.setForceFormulaRecalculation(true);
} // 输出文件
FileOutputStream os = new FileOutputStream(outFile);
wbs.write(os);
is.close();
os.close();
} catch (Exception e) {
e.printStackTrace();
}
}

操作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 = -
Selection.ShapeRange.PictureFormat.Crop.PictureOffsetY = -
Selection.Copy
Range("A1").Select
ActiveSheet.Pictures.Paste.Select
ActiveCell.FormulaR1C1 = "QGJYFJLXSQK"

复制单元格生成图形

只要会VBA 基本语法,其它的如果不会,可以通过录制宏得到

4、  调用宏

  先提供工具类

 package com.wiseda.fc.utils;

 import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant; public class JacobExcelUtils {
private static ActiveXComponent xl = null; //Excel对象(防止打开多个)
private static Dispatch workbooks = null; //工作簿对象
private Dispatch workbook = null; //具体工作簿
private Dispatch sheets = null;// 获得sheets集合对象
private Dispatch currentSheet = null;// 当前sheet public ActiveXComponent getXl() {
return xl;
} public Dispatch getWorkbooks() {
return workbooks;
} public Dispatch getWorkbook() {
return workbook;
} /**
* 打开excel文件
* @param filepath 文件路径名称
* @param visible 是否显示打开
* @param readonly 是否只读方式打开
*/
public void OpenExcel(String filepath, boolean visible, boolean readonly) {
try {
initComponents(); //清空原始变量
ComThread.InitSTA();
if(xl==null)
xl = new ActiveXComponent("Excel.Application"); //Excel对象
xl.setProperty("Visible", new Variant(visible));//设置是否显示打开excel
if(workbooks==null)
workbooks = xl.getProperty("Workbooks").toDispatch(); //工作簿对象
workbook = Dispatch.invoke( //打开具体工作簿
workbooks,
"Open",
Dispatch.Method,
new Object[] { filepath, new Variant(false),
new Variant(readonly) },// 是否以只读方式打开
new int[]).toDispatch();
} catch (Exception e) {
e.printStackTrace();
releaseSource();
}
} /**
* 工作簿另存为
* @param filePath 另存为的路径
*/
public void SaveAs(String filePath){
Dispatch.invoke(workbook, "SaveAs", Dispatch.Method,
new Object[] { filePath,
new Variant() }, new int[]);
} /**
* 关闭excel文档
* @param f 含义不明 (关闭是否保存?默认false)
*/
public void CloseExcel(boolean f,boolean quitXl) {
try {
Dispatch.call(workbook, "Save");
Dispatch.call(workbook, "Close", new Variant(f));
} catch (Exception e) {
e.printStackTrace();
} finally {
if(quitXl){
releaseSource();
}
}
} /**
* 释放资源
*/
public static void releaseSource(){
if(xl!=null){
xl.invoke("Quit", new Variant[] {});
xl = null;
}
workbooks = null;
ComThread.Release();
System.gc();
} /**
* 添加新的工作表(sheet),(添加后为默认为当前激活的工作表)
*/
public Dispatch addSheet() {
return Dispatch.get(Dispatch.get(workbook, "sheets").toDispatch(), "add").toDispatch();
} /**
* 修改当前工作表的名字
* @param newName
*/
public void modifyCurrentSheetName(String newName) {
Dispatch.put(getCurrentSheet(), "name", newName);
} /**
* 得到当前工作表的名字
* @return
*/
public String getCurrentSheetName() {
return Dispatch.get(getCurrentSheet(), "name").toString();
} /**
* 得到工作薄的名字
* @return
*/
public String getWorkbookName() {
if(workbook==null)
return null;
return Dispatch.get(workbook, "name").toString();
} /**
* 得到sheets的集合对象
* @return
*/
public Dispatch getSheets() {
if(sheets==null)
sheets = Dispatch.get(workbook, "sheets").toDispatch();
return sheets;
} /**
* 得到当前sheet
* @return
*/
public Dispatch getCurrentSheet() {
currentSheet = Dispatch.get(workbook, "ActiveSheet").toDispatch();
return currentSheet;
} /**
* 通过工作表名字得到工作表
* @param name sheetName
* @return
*/
public Dispatch getSheetByName(String name) {
return Dispatch.invoke(getSheets(), "Item", Dispatch.Get, new Object[]{name}, new int[]).toDispatch();
} /**
* 通过工作表索引得到工作表(第一个工作簿index为1)
* @param index
* @return sheet对象
*/
public Dispatch getSheetByIndex(Integer index) {
return Dispatch.invoke(getSheets(), "Item", Dispatch.Get, new Object[]{index}, new int[]).toDispatch();
} /**
* 得到sheet的总数
* @return
*/
public int getSheetCount() {
int count = Dispatch.get(getSheets(), "count").toInt();
return count;
} /**
* 调用excel宏
* @param macroName 宏名
*/
public void callMacro(String macroName){
Dispatch.call(xl, "Run",new Variant(macroName));
} /**
* 单元格写入值
* @param sheet 被操作的sheet
* @param position 单元格位置,如:C1
* @param type 值的属性 如:value
* @param value
*/
public void setValue(Dispatch sheet, String position, String type, Object value) { Dispatch cell = Dispatch.invoke(sheet, "Range",
Dispatch.Get, new Object[] { position }, new int[])
.toDispatch();
Dispatch.put(cell, type, value);
} /**
* 单元格读取值
* @param position 单元格位置,如: C1
* @param sheet
* @return
*/
public Variant getValue(String position, Dispatch sheet) {
Dispatch cell = Dispatch.invoke(sheet, "Range", Dispatch.Get,
new Object[] { position }, new int[]).toDispatch();
Variant value = Dispatch.get(cell, "Value");
return value;
} private void initComponents(){
workbook = null;
currentSheet = null;
sheets = null;
}
}

jacob工具类

  调用宏代码

 public void excelPictureGrab() throws Exception {
this.targetFile = new File(targetFilePath); //复制文件
FileUtils.copyFile(xlsFile, targetFile); logger.info("文件复至完成"); //生成带图形的 excel
JacobExcelUtils tool = new JacobExcelUtils();
try {
tool.OpenExcel(targetFilePath, false, false); logger.info("打开Excel"); //执行宏 复制为图片
tool.callMacro("copyImg"); logger.info("处理宏完成");
} catch (Exception e) {
throw new Exception("执行宏出错," + e.getMessage());
// TODO: handle exception
} finally {
// 关闭流
tool.CloseExcel(false, true);
}
}

5、  获取图表

 //获取图片字节流
public static String getPic(String fileUrl,String backupUrl) throws Exception {
StringBuffer results = new StringBuffer(); File tfdir = new File(backupUrl);
if (!tfdir.exists()) tfdir.mkdirs(); InputStream inp = new FileInputStream(fileUrl);
HSSFWorkbook workbook = (HSSFWorkbook) WorkbookFactory.create(inp); List<HSSFPictureData> pictures = workbook.getAllPictures();
HSSFSheet sheet = (HSSFSheet) workbook.getSheetAt(0); //所有图片都存在第一页 int i = 0;
for (HSSFShape shape : sheet.getDrawingPatriarch().getChildren()) {
HSSFClientAnchor anchor = (HSSFClientAnchor) shape.getAnchor(); if (shape instanceof HSSFPicture) {
HSSFPicture pic = (HSSFPicture) shape;
int pictureIndex = pic.getPictureIndex()-1; //图片名称
int row = anchor.getRow1(); System.out.println(anchor.getCol1()); HSSFCell picCell = sheet.getRow(row).getCell(anchor.getCol1()); String picName = "";
if(picCell != null) {
picName = picCell.getStringCellValue();
} logger.info(i + "--->row." + anchor.getRow1() + ":cell." + anchor.getCol1() + ":pictureIndex." + pictureIndex); HSSFPictureData picData = pictures.get(pictureIndex); //备份并返回 图片
if(picName != null && !"".equals(picName)) {
String result = BackupPic(picName, picData,backupUrl);
results.append(result);
results.append(",");
}
}
i++;
} return results.toString();
} //备份图片
private static String BackupPic(String picName,PictureData pic,String backupUrl) throws Exception {
String result = ""; String pngImgUrl,jpgImgUrl;
String ext = pic.suggestFileExtension();
byte[] data = pic.getData();
if (ext.equals("png")) { pngImgUrl = backupUrl + picName + "." + ext;
FileOutputStream out = new FileOutputStream(
pngImgUrl);
out.write(data);
out.close(); //转为 jpg
jpgImgUrl = backupUrl + picName + ".jpg";
ConvertPngToJpg(pngImgUrl,jpgImgUrl); result = picName + ":" + DatatypeConverter.printBase64Binary(data);
} return result;
} //压缩图片 把PND图片转JPG
private static void ConvertPngToJpg(String pngImgUrl,String jpgImgUrl) {
BufferedImage bufferedImage;
try { //read image file
bufferedImage = ImageIO.read(new File(pngImgUrl)); // create a blank, RGB, same width and height, and a white background
BufferedImage newBufferedImage = new BufferedImage(bufferedImage.getWidth(),
bufferedImage.getHeight(), BufferedImage.TYPE_INT_RGB);
newBufferedImage.createGraphics().drawImage(bufferedImage, 0, 0, Color.WHITE, null); // write to jpeg file
ImageIO.write(newBufferedImage, "jpg", new File(jpgImgUrl)); } catch (IOException e) { e.printStackTrace(); }
}

获得excel图片

JAVA生成EXCEL图表的更多相关文章

  1. java 生成Excel开门篇

    本随笔的Excel所用的poi jar包(3.17版本)链接: https://pan.baidu.com/s/1gaa3dJueja8IraUDYCSLIQ 提取密码: 9xr7 简单实现:两个类: ...

  2. oracle PL/SQL调用Java生成Excel

    现在有个需求,  要求编写oracle存储过程生成Excel文件到指定目录,  但是oracle自己的API貌似不太给力,  所以只能通过另一种更强大的语言来实现了  ——Java.有一个Java框架 ...

  3. JAVA生成EXCEL模板

    JAVA生成excel模板,支持1.必填字段前加 红色 * 2.定义可选值下拉列表 valList3.定义名称并通过名称设置可选值 refName(名称在sheet2,sheet2自动隐藏)4.支持设 ...

  4. 使用poi和jfreechart生成excel图表图片

    最近项目在频繁的操作excel,里边涉及到很多和图表有关的东西.有时候需要使用java操作excel自带的图标,比较复杂的我们都是使用excel模板的形式实现. 除此之外,也有一些功能只需要生成对应的 ...

  5. [转]java生成 excel 并导出文件

    原文:https://blog.csdn.net/xunwei0303/article/details/53213130 目前,比较常用的实现Java导入.导出Excel的技术有两种Jakarta P ...

  6. 两种方式实现java生成Excel

    Web应用中难免会遇到需要将数据导出并生成excel文件的需求.同样,对于本博客中的总结,也是建立在为了完成这样的一个需求,才开始去了解其实现形式,并且顺利完成需求的开发,先将实现过程总结于此.本博文 ...

  7. Java生成excel导出文件(使用poi+JXL)

    1.使用poi生成文件 package com.mi.entity; import java.util.Date; public class Student { private int id; pri ...

  8. python生成Excel图表(通过xlsxwriter)

    前面介绍了pandas的简单用法,pandas的数据可以通过matlab第三方包将数据生成报表,但是我想将报表生成在Excel中,这时候就可以借助xlsxwriter第三方包来生成图标   缺点:xl ...

  9. java生成excel报表文件

    此次简单的操作将数据从数据库导出生成excel报表以及将excel数据导入数据库 首先建立数据库的连接池: package jdbc; import java.io.FileInputStream; ...

随机推荐

  1. SQL 表锁(转)

    其实你可以使用事务处理   比方说在一个字段里面添加一个boolean 的字段当你要处理该字段的时候就 True 哪么别的人都不可以进行操作 如果是False 哪么就可以进行操作--呵可--我是这样的 ...

  2. Java中的递归原理分析

    解释:程序调用自身的编程技巧叫做递归.        程序调用自身的编程技巧称为递归( recursion).递归做为一种算法在程序设计语言中广泛应用. 一个过程或函数在其定义或说明中有直接或间接调用 ...

  3. cocos2d-x 缓动曲线

    转自:http://blog.csdn.net/cocos2der/article/details/7261808 在实现运动中,我们常常需要实现一些加速度或者减速度的效果,cocos2d-x引擎为我 ...

  4. Telnet端口测试

    $IP ="220.181.111.142"$Port ="801" Function Port-Test ($IP,$Port){ $Timeout = 10 ...

  5. pjsip视频通信开发(上层应用)之拨号界面整体界面功能实现

    在前面的几章里面写了显示.键盘.拨号.删除功能,这里我将他们进行组合,形成一个拨号键盘全部功能.首先是布局 <LinearLayout xmlns:android="http://sc ...

  6. Web APP 随笔

    自Iphone和Android这两个牛逼的手机操作系统发布以来,在互联网界从此就多了一个新的名词-WebApp(意为基于WEB形式的应用程序,运行在高端的移动终端设备). 开发者们都知道在高端智能手机 ...

  7. Ruby on Rails Tutorial 第四章 Rails背后的Ruby 之 类

    Ruby和其他面向对象的语言一样,使用类来组织方法,然后实例化类,创建对象.1.构造方法使用双引号是字符串的字面构造方法,也可以使用“具名构造方法”,即在类名上调用new方法 >> s=& ...

  8. Advice on improving your programming skills

    Programming is cool. But behind the scenes it's also difficult for many people. Many people are defe ...

  9. 把旧的项目改变名称重新部署到tomcat下发现项目名称还是原来的项目名称,解决方案

    选中项目右键点击properties 在type file text 中输入web 选择web在右边可以看到web-context-root 把里面的项目名称改成你最新的就ok了

  10. 观察者模式(二)--《Head First DesignPattern》

    我们用Java中自带的观察者模式接口来重写前面的例子. 先看一下类图: 这里用到了一个setChanged函数,它用来标记状态已经改变的事实,好让notifyObservers()知道当它调用时就应该 ...