上一篇介绍了使用Java的Robot机器人实现截图,然后将剪贴板上的数据流生成PNG图片

但是经过博主的不断测试,在完全依赖远程桌面的没有终端显示器的服务器上

使用截图方式是不可行的,因为一旦使用了远程桌面,再断开桌面,系统后台执行的截图程序会全部截到黑屏

所以博主不得已去用另一种通用方式生成PNG

这就是要使用Apache公司的POI工具,对整个excel进行解析

将excel的每一个单元格,数据,格式,边框全都读取出来

其中需要考虑到单元格的合并,行列的隐藏等等复杂的问题

最终使用JAVA 2d将读取到的数据绘制到PNG图片上。

第一张是Excel原样截图

下面一张是使用JAVA 2D绘制出来的报表:

贴上源代码,其中涉及到使用POI读取单元格背景色,字体前景色等颜色操作,还是比较复杂的。

package com.newflyig.jpg;/*** width:pix=getColumnWidthInPixels*1.15* height:pix=getHeightInPoints*96/72* * 本示例用来读取Excel报表文件,并力图将报表无差别转化成PNG图片* 使用POI读取Excel各项数据* 使用JAVA 2D绘制PNG* TODO 本示例基本实现了常见Excel的所有样式输出,但Office2007以后的版本添加了条件样式功能,因为POI的API无法读取条件样式,所以无法实现* 今后可以通过关键字标注等方法,在Excel中需要加入条件样式的单元格用注解标明,使用JAVA计算得出样式再绘制出来*/import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;import javax.imageio.ImageIO;import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFFont;import sun.awt.SunHints;public class DrawFromExcel {public static void main(String[] args) throws Exception {// 给定两个初始值,标志出导出区域,两个行列组合的单元格int[] fromIndex = { 0, 0 };int[] toIndex = { 17, 20 };int imageWidth = 0;int imageHeight = 0;Workbook wb = WorkbookFactory.create(new File("d:/2014年1月营销活动报表140116.xlsx"));Sheet sheet = wb.getSheet("test");List<CellRangeAddress> rangeAddress = sheet.getMergedRegions(); // 获取整个sheet中合并单元格组合的集合// 首先做初步的边界检测,如果指定区域是不合法的则抛出异常int rowSum = sheet.getPhysicalNumberOfRows();int colSum = sheet.getRow(0).getPhysicalNumberOfCells();if (fromIndex[0] > rowSum || fromIndex[0] > toIndex[0] || toIndex[0] > rowSum) {throw new Exception("the rowIndex of the area is wrong!");}if (fromIndex[1] > colSum || fromIndex[1] > toIndex[1] || toIndex[1] > colSum) {throw new Exception("the colIndex of the area is wrong!");}// 计算实际需要载入内存的二维Cell数组的大小,剔除隐藏行列int rowSize = toIndex[0]+1;int colSize = toIndex[1]+1;// 遍历需要扫描的区域UserCell[][] cells = new UserCell[rowSize][colSize];int[] rowPixPos = new int[rowSize + 1];rowPixPos[0] = 0;int[] colPixPos = new int[colSize + 1];colPixPos[0] = 0;for (int i = 0; i < rowSize; i++) {for (int j = 0; j < colSize; j++) {cells[i][j] = new UserCell();cells[i][j].setCell(sheet.getRow(i).getCell(j));cells[i][j].setRow(i);cells[i][j].setCol(j);boolean ifShow=(i>=fromIndex[0]) && (j>=fromIndex[1]);  //首先行列要在指定区域之间ifShow=ifShow && !(sheet.isColumnHidden(j) || sheet.getRow(i).getZeroHeight());  //其次行列不可以隐藏cells[i][j].setShow(ifShow);// 计算所求区域宽度float widthPix = !ifShow ? 0 : sheet.getColumnWidthInPixels(j); // 如果该单元格是隐藏的,则置宽度为0if (i == fromIndex[0]) {imageWidth += widthPix;}colPixPos[j+1] = (int) (widthPix * 1.15 + colPixPos[j]);}// 计算所求区域高度boolean ifShow=(i>=fromIndex[0]); //行序列在指定区域中间ifShow=ifShow && !sheet.getRow(i).getZeroHeight(); //行序列不能隐藏float heightPoint = !ifShow ? 0 : sheet.getRow(i).getHeightInPoints(); // 如果该单元格是隐藏的,则置高度为0imageHeight += heightPoint;           rowPixPos[i+1] = (int) (heightPoint * 96 / 72) + rowPixPos[i];}imageHeight = imageHeight * 96 / 72;imageWidth = imageWidth * 115 / 100;wb.close();List<Grid> grids = new ArrayList<Grid>();for (int i = 0; i < rowSize; i++) {for (int j = 0; j < colSize; j++) {Grid grid = new Grid();// 设置坐标和宽高grid.setX(colPixPos[j]);grid.setY(rowPixPos[i]);grid.setWidth(colPixPos[j + 1] - colPixPos[j]);grid.setHeight(rowPixPos[i + 1] - rowPixPos[i]);grid.setRow(cells[i][j].getRow());grid.setCol(cells[i][j].getCol());grid.setShow(cells[i][j].isShow());// 判断是否为合并单元格int[] isInMergedStatus = isInMerged(grid.getRow(), grid.getCol(), rangeAddress);if (isInMergedStatus[0] == 0 && isInMergedStatus[1] == 0) {// 此单元格是合并单元格,并且不是第一个单元格,需要跳过本次循环,不进行绘制continue;} else if (isInMergedStatus[0] != -1 && isInMergedStatus[1] != -1) {// 此单元格是合并单元格,并且属于第一个单元格,则需要调整网格大小                   int lastRowPos=isInMergedStatus[0]>rowSize-1?rowSize-1:isInMergedStatus[0];int lastColPos=isInMergedStatus[1]>colSize-1?colSize-1:isInMergedStatus[1];                  grid.setWidth(colPixPos[lastColPos + 1] - colPixPos[j]);grid.setHeight(rowPixPos[lastRowPos + 1] - rowPixPos[i]);}// 单元格背景颜色CellStyle cs = cells[i][j].getCell().getCellStyle();if (cs.getFillPattern() == CellStyle.SOLID_FOREGROUND)grid.setBgColor(cells[i][j].getCell().getCellStyle().getFillForegroundColorColor());// 设置字体org.apache.poi.ss.usermodel.Font font = wb.getFontAt(cs.getFontIndex());grid.setFont(font);// 设置字体前景色if (font instanceof XSSFFont) {XSSFFont xf = (XSSFFont) font;grid.setFtColor(xf.getXSSFColor());}// 设置文本String strCell = "";switch (cells[i][j].getCell().getCellType()) {case HSSFCell.CELL_TYPE_NUMERIC:                                      strCell = String.valueOf(cells[i][j].getCell().getNumericCellValue());break;case HSSFCell.CELL_TYPE_STRING:strCell = cells[i][j].getCell().getStringCellValue();break;case HSSFCell.CELL_TYPE_BOOLEAN:strCell = String.valueOf(cells[i][j].getCell().getBooleanCellValue());break;case HSSFCell.CELL_TYPE_FORMULA:try {strCell = String.valueOf(cells[i][j].getCell().getNumericCellValue());} catch (IllegalStateException e) {strCell = String.valueOf(cells[i][j].getCell().getRichStringCellValue());}break;default:strCell = "";}if(cells[i][j].getCell().getCellStyle().getDataFormatString().contains("0.00%")){try{double dbCell=Double.valueOf(strCell);strCell=new DecimalFormat("#.00").format(dbCell*100)+"%";}catch(NumberFormatException e){}                    }grid.setText(strCell.matches("\\w*\\.0") ? strCell.substring(0, strCell.length() - 2) : strCell);grids.add(grid);}}BufferedImage image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB);Graphics2D g2d = image.createGraphics();// 平滑字体g2d.setRenderingHint(SunHints.KEY_ANTIALIASING, SunHints.VALUE_ANTIALIAS_OFF);g2d.setRenderingHint(SunHints.KEY_TEXT_ANTIALIASING, SunHints.VALUE_TEXT_ANTIALIAS_DEFAULT);g2d.setRenderingHint(SunHints.KEY_STROKE_CONTROL, SunHints.VALUE_STROKE_DEFAULT);g2d.setRenderingHint(SunHints.KEY_TEXT_ANTIALIAS_LCD_CONTRAST, 140);g2d.setRenderingHint(SunHints.KEY_FRACTIONALMETRICS, SunHints.VALUE_FRACTIONALMETRICS_OFF);g2d.setRenderingHint(SunHints.KEY_RENDERING, SunHints.VALUE_RENDER_DEFAULT);g2d.setColor(Color.white);g2d.fillRect(0, 0, imageWidth, imageHeight);// 绘制表格for (Grid g : grids) {if (!g.isShow())continue;// 绘制背景色g2d.setColor(g.getBgColor() == null ? Color.white : g.getBgColor());g2d.fillRect(g.getX(), g.getY(), g.getWidth(), g.getHeight());// 绘制边框g2d.setColor(Color.black);g2d.setStroke(new BasicStroke(1));g2d.drawRect(g.getX(), g.getY(), g.getWidth(), g.getHeight());// 绘制文字,居中显示g2d.setColor(g.getFtColor());Font font = g.getFont();FontMetrics fm = g2d.getFontMetrics(font);int strWidth = fm.stringWidth(g.getText());// 获取将要绘制的文字宽度g2d.setFont(font);g2d.drawString(g.getText(),g.getX() + (g.getWidth() - strWidth) / 2,g.getY() + (g.getHeight() - font.getSize()) / 2 + font.getSize());}g2d.dispose();ImageIO.write(image, "png", new File("d:/test.png"));System.out.println("Output to PNG file Success!");}/*** 判断Excel中的单元格是否为合并单元格* * @param row* @param col* @param rangeAddress* @return 如果不是合并单元格返回{-1,-1},如果是合并单元格并且是一个单元格返回{lastRow,lastCol},*         如果是合并单元格并且不是第一个格子返回{0,0}*/private static int[] isInMerged(int row, int col, List<CellRangeAddress> rangeAddress) {int[] isInMergedStatus = { -1, -1 };for (CellRangeAddress cra : rangeAddress) {if (row == cra.getFirstRow() && col == cra.getFirstColumn()) {isInMergedStatus[0] = cra.getLastRow();isInMergedStatus[1] = cra.getLastColumn();return isInMergedStatus;}if (row >= cra.getFirstRow() && row <= cra.getLastRow()) {if (col >= cra.getFirstColumn() && col <= cra.getLastColumn()) {isInMergedStatus[0] = 0;isInMergedStatus[1] = 0;return isInMergedStatus;}}}return isInMergedStatus;}
}

  

转载于:https://www.cnblogs.com/newflydd/p/4912662.html

JAVA将Excel中的报表导出为图片格式(三)换一种实现相关推荐

  1. JAVA将Excel中的报表导出为图片格式(一)问题背景

    如题所示,先抛出一个问题,如何使用JAVA将Excel中的报表导出为图片格式? 首先说一下这个问题的背景,也就是为什么博主会碰到这个问题 随着微信,易信之流大行其道,企业内部的办公交流.绩效考评甚至考 ...

  2. python3 excel 图表导出图片_使用python代码将excel中的图表导出为图片

    python导出Excel图表类 前期准备就绪,网上已有类似的导出Excel图表类,但是在后面的使用中发现问题,即关键函数已在下面代码中标红: 调用代码: 执行成功,接下来到上面设置的导出路径查看导出 ...

  3. vue中table表格导出为图片格式

    vue中table表格点击下载为图片格式 实现思路:给页面中需要导出为图片的内容添加id名,调用封好的方法即可直接导出.以下是具体的实现方法 1.安装依赖 npm install --save htm ...

  4. java 从excel中读取数据_在Java中读取Excel文件的内容和导出数据到Excel文件中

    转自www.chianjavaworld.net 原作者:SonyMusic 读:rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr 在Java ...

  5. Java Web 后台中餐饮业报表系统开发实例

    本期葡萄城公开课,我们诚邀石家庄品智技术有限公司,高级软件工程师--刘永政先生,为大家在线分享餐饮业报表系统设计模式,以及在 HTML5 报表浏览器.Java 架构中跨平台使用ActiveReport ...

  6. 在Java生成的html页面加水印,Java在Excel中添加水印的实现(单一水印、平铺水印)...

    在Excel中没有直接添加水印的功能,但依旧可以通过一定方式来实现类似水印效果.本文通过Java程序代码介绍具体实现方法.可添加单一水印效果,即水印是以单个文本字样来呈现:也可添加多个平铺水印效果,即 ...

  7. poi读取excel中的内容(带图片)

    项目中有一需求:需要读取excel中的信息,带图片,需要将每一行的图片,做对应,整理方法如下: 主要逻辑: 1,获取excel对象, 2,读取excel中所有的图片流,将图片所处的位置和图片流存在ma ...

  8. python亿级mysql数据库导出_Python实现将MySQL数据库表中的数据导出生成csv格式文件的方法...

    本文实例讲述了python实现将MySQL数据库表中的数据导出生成csv格式文件的方法.分享给大家供大家参考,具体如下: #!/usr/bin/env python # -*- coding:utf- ...

  9. Excel中数据透视表数据源更新的三种方式

    Excel中数据透视表数据源更新的三种方式 1.在原有的基础上重新选择数据源 2.变数据源为表格形式,在创建一个透视表,之后如果添加的数据,选中透视表右键刷新即可 3.利用更新过的数据源再重新创建一个 ...

最新文章

  1. jenkins-git-gradle配置项目
  2. struts——struts在升级,作为程序员,该怎样以不变应万变?
  3. Oracle- 数据库的备份
  4. APK加壳【2】内存加载dex实现详解
  5. Python中__new__和__init__的区别与联系
  6. 利用java反射调用类的的私有方法--转
  7. oracle xe gentoo,Oracle在gentoo下安装
  8. 在思科模拟器上完成基于服务器的AAA实验
  9. .net OADate 转javascript的Datetime js 5位 日期 转换
  10. mysql_config缺失_安装 mysqlclient 报 mysql_config not found
  11. Visio使用经验汇集
  12. zec挖矿(zcash挖矿)鱼池跟蚂蚁矿池的比较到底哪个好?哪个收益高? (二)
  13. Android 项目使用 Jenkins 打包时的异常问题 AAPT: C:\Windows\System32\config\systemprofile\.gradle\caches
  14. 清华师哥封神之作!RocketMQ核心笔记疯传Ali内网
  15. win10 家庭版cmd命令打开超级管理员和关闭超级管理员
  16. Titan XP值不值?教你如何挑选深度学习GPU
  17. 目标检测:速度和准确性比较(Fater R-CNN,R-FCN,SSD,FPN,RetinaNet和YOLOv3)
  18. Python性能分析利器pyinstrument讲解
  19. redhat安装配置Apache服务
  20. 为何敢称万物追焦?小米12 系列CyberFocus技术详解

热门文章

  1. C语言基础函数(二)
  2. c 结构体 函数 指针
  3. Arm 架构下的中断
  4. 很多IP摄像头厂商都在用的固件中存在多个严重漏洞
  5. CloudFlare CDNJS 漏洞差点造成大规模的供应链攻击
  6. SAP SolMan 严重漏洞的自动化 exploit 代码遭公开
  7. 苹果修复三个已遭利用的 iOS 0day
  8. 刚刚,微软发出警告:这个 IE 0day 影响所有 Windows 版本,已遭用且无补丁!
  9. 想多赚钱就要多培养自己脖子以上的能力
  10. 献给初学者,[winform]中如何设计高效全局的快捷键?[ShortcutKeys]