跟据客户的要求,需要开发一套包括图形的报表,还需要导出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图表的更多相关文章
-
java 生成Excel开门篇
本随笔的Excel所用的poi jar包(3.17版本)链接: https://pan.baidu.com/s/1gaa3dJueja8IraUDYCSLIQ 提取密码: 9xr7 简单实现:两个类: ...
-
oracle PL/SQL调用Java生成Excel
现在有个需求, 要求编写oracle存储过程生成Excel文件到指定目录, 但是oracle自己的API貌似不太给力, 所以只能通过另一种更强大的语言来实现了 ——Java.有一个Java框架 ...
-
JAVA生成EXCEL模板
JAVA生成excel模板,支持1.必填字段前加 红色 * 2.定义可选值下拉列表 valList3.定义名称并通过名称设置可选值 refName(名称在sheet2,sheet2自动隐藏)4.支持设 ...
-
使用poi和jfreechart生成excel图表图片
最近项目在频繁的操作excel,里边涉及到很多和图表有关的东西.有时候需要使用java操作excel自带的图标,比较复杂的我们都是使用excel模板的形式实现. 除此之外,也有一些功能只需要生成对应的 ...
-
[转]java生成 excel 并导出文件
原文:https://blog.csdn.net/xunwei0303/article/details/53213130 目前,比较常用的实现Java导入.导出Excel的技术有两种Jakarta P ...
-
两种方式实现java生成Excel
Web应用中难免会遇到需要将数据导出并生成excel文件的需求.同样,对于本博客中的总结,也是建立在为了完成这样的一个需求,才开始去了解其实现形式,并且顺利完成需求的开发,先将实现过程总结于此.本博文 ...
-
Java生成excel导出文件(使用poi+JXL)
1.使用poi生成文件 package com.mi.entity; import java.util.Date; public class Student { private int id; pri ...
-
python生成Excel图表(通过xlsxwriter)
前面介绍了pandas的简单用法,pandas的数据可以通过matlab第三方包将数据生成报表,但是我想将报表生成在Excel中,这时候就可以借助xlsxwriter第三方包来生成图标 缺点:xl ...
-
java生成excel报表文件
此次简单的操作将数据从数据库导出生成excel报表以及将excel数据导入数据库 首先建立数据库的连接池: package jdbc; import java.io.FileInputStream; ...
随机推荐
-
Android中通过线程实现更新ProgressDialog(对话进度条)
作为开发者我们需要经常站在用户角度考虑问题,比如在应用商城下载软件时,当用户点击下载按钮,则会有下载进度提示页面出现,现在我们通过线程休眠的方式模拟下载进度更新的演示,如图(这里为了截图方便设置对话进 ...
-
SSL handshake alert: unrecognized_name error since upgrade to Java 1.7
今天将jdk从1.6升级到1.7,但是HttpUrlConnection连接https出现问题了. javax.net.ssl.SSLProtocolException: handshake aler ...
-
大数据每日干货第四天(linux基础之一目录结构与常用命令)
为了和qq空间同步,也写的第四天,前面几天明天会发布,本来打算把每天学的东西记录下来,通过朋友给的建议要发的话稍微系统化下,从大数据需要的linux基础,到离线数据分析包括hadoop. ...
-
Java连接Redis (key-value存储系统)
Redis简介: redis是一个性能非常优秀的内存数据库,通过key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表). ...
-
禁止Android的StatusBar下拉
Android中有许多隐藏的Service,StatusBarManager就是其中一个,在Context.java中可以看到: /** * Use with {@link #getSystemSer ...
-
this 关键字
导读 本文将列举C#中this关键字的用途 1.this 含义 2.用this 关键字避免参数与字段的混淆 3.用this关键字串联构造器 4.索引器 6.Visitor 模式 this 含义 C# ...
-
JavaScript中的面向对象程序设计
本文内容目录顺序: 1.Object概念讲述: 2.面向对象程序设计特点: 3.JavaScript中类和实例对象的创建: 4.原型概念: 5.原型API: 6.原型对象的具体使用:7.深入理解使用原 ...
-
socket.io 入门篇(三)
本文原文地址:https://www.limitcode.com/detail/5926e3a056fba70278bf2044.html 前言 上篇我们介绍了 socket.io 中room的概念和 ...
-
十个 PHP 开发者最容易犯的错误
PHP 语言让 WEB 端程序设计变得简单,这也是它能流行起来的原因.但也是因为它的简单,PHP 也慢慢发展成一个相对复杂的语言,层出不穷的框架,各种语言特性和版本差异都时常让搞的我们头大,不得不浪费 ...
-
Linux之DHCP搭建命令集锦
systemctl start dhcpd //启动DHCP systemctl enable dhcpd //配置服务开机启动 ps aux | grep ...