JAVA将Excel中的报表导出为图片格式(二)实现思路

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

接上文,一封类似于下方设计的Excel报表,如何将它指定的区域导出为样式一模一样的JPG图片呢?

要实现这个功能没有现成的解决方案,谷歌度娘了好久也没有,最终自己想了几条思路:

思路1:将报表中的背景、边框等截图下来作为模型图片,需要定时更新的数据通过JDBC读取Oracle中的数据绘制到模型图片上

否定原因:不具可行性,所有数据的坐标点需要有规则方便绘图时循环绘制,工程量巨大,耦合性巨高,表格数据牵一发而动全身,并且不利于扩展。

思路2:不需要报表原型,生成Excel报表后,使用jxl或者poi一个单元一个单元读取报表内所有单元格,包括单元格的数据和格式,边框、宽度、高度、字体前景色、背景色都要读取出来,然后通过java绘图,最终生成JPG格式的报表。

否定原因:具有一定的可行性,但是代码量巨大,读取和绘制费时费力,但是有一定的优点,可以在不忙的时间里编写一个通用的程序,一劳永逸的解决所有导出问题。

思路3:比较奇葩,属于博主突发奇想的招式,通过wps或者Office打开Excel,编写Robot机器人将鼠标移动到两个指定坐标所覆盖指定区域,Robot模拟敲击Ctrl+C,接着将剪贴板上的数据绘图,导出到JPG文件。

最终实现了思路3,有一定的好处也有弊端,好处是简单便捷,可操作性高,代码量低,扩展性强,换其他报表只需要提供另一组坐标参数即可

弊端是完全牺牲了JAVA的跨平台性,甚至如果运行在分辨率较低的服务器上,有可能导致复制操作无法执行

另一个弊端是线程变得不安全了,如果服务器负载较重,无法正确预计Office打开报表的时间,也有可能导致复制操作无法执行

或者多个生成报表截图的任务同时执行时,显然使用Robot会导致冲突。

下面提供思路3的实现代码,以后有时间会使用思路2写一个通用的程序

packagecom.newflypig.excel;importjava.awt.Graphics;importjava.awt.Image;importjava.awt.Robot;importjava.awt.Toolkit;importjava.awt.datatransfer.DataFlavor;importjava.awt.datatransfer.Transferable;importjava.awt.event.InputEvent;importjava.awt.event.KeyEvent;importjava.awt.image.BufferedImage;importjava.io.File;importjava.text.SimpleDateFormat;importjava.util.Date;importjavax.imageio.ImageIO;publicclassOpenExcelDemo {publicstaticvoidmain(String[] args)throwsException {

openExcel("d:\\新增积分月报表.xlsx");

copyRectByPix(37, 207, 1215, 665); //给定两个坐标点的数据,圈定截图范围

createImageFileFromClip("d:/" + getTimeStr() + ".jpg");

closeExcel((int)Toolkit.getDefaultToolkit().getScreenSize().getWidth() - 15, 12); //需要模拟关闭事件,将Excel关闭,以便下次能正确打开报表

}PRivatestaticvoidcloseExcel(inti,intj)throwsException {

Robot robot=newRobot();

robot.delay(500);

robot.mouseMove(i,j);

robot.delay(500);

robot.mousePress(InputEvent.BUTTON1_MASK);

robot.delay(500);

robot.mouseRelease(InputEvent.BUTTON1_MASK);

robot.delay(500);

robot.keyPress(KeyEvent.VK_ENTER);

}publicstaticvoidopenExcel(String dir)throwsException {

Runtime.getRuntime().exec("cmd /k " + dir + "");

}publicstaticvoidcopyRectByPix(intfromX,intfromY,inttoX,inttoY)throwsException {

Robot robot=newRobot();

robot.delay(3000);//延时3000毫秒robot.mouseMove(fromX, fromY);

robot.delay(500);

robot.mousePress(InputEvent.BUTTON1_MASK);

robot.delay(500);

robot.mouseMove(toX, toY);

robot.delay(500);

robot.mouseRelease(InputEvent.BUTTON1_MASK);

robot.setAutoDelay(200);

robot.keyPress(KeyEvent.VK_CONTROL);

robot.keyPress(KeyEvent.VK_C);

robot.keyRelease(KeyEvent.VK_CONTROL);

robot.keyRelease(KeyEvent.VK_C);

}publicstaticvoidcreateImageFileFromClip(String dir)throwsException {

Transferable t=Toolkit.getDefaultToolkit().getSystemClipboard()

.getContents(null);if(null!= t &&t.isDataFlavorSupported(DataFlavor.imageFlavor)) {

Image image=(Image) t.getTransferData(DataFlavor.imageFlavor);

savePic(image, dir);

}

}publicstaticString savePic(Image iamge, String dir)throwsException {intw = iamge.getWidth(null);inth = iamge.getHeight(null);//首先创建一个BufferedImage变量,因为ImageIO写图片用到了BufferedImage变量。BufferedImage bi =newBufferedImage(w, h, BufferedImage.TYPE_3BYTE_BGR);//再创建一个Graphics变量,用来画出来要保持的图片,及上面传递过来的Image变量Graphics g =bi.getGraphics();

g.drawImage(iamge,0, 0,null);//将BufferedImage变量写入文件中。ImageIO.write(bi, "jpg",newFile(dir));returndir;

}publicstaticString getTimeStr() {

String time=newSimpleDateFormat("yyyyMMddHHmmss").format(newDate());returntime;

}

}

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航