Java Excel转图片
看到一篇好用的excel转图片的代码,封装和改动了一部分
原文https://www.cnblogs.com/newflydd/p/4912662.html#top
调整可以导出带图片的excel,支持表达式
用到jar包
<dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.17</version>
</dependency>
<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.17</version>
</dependency>
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.12.0</version>
</dependency>
不多说了,直接上代码
package com.example.excel;import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
import org.apache.poi.hssf.usermodel.HSSFPicture;
import org.apache.poi.hssf.usermodel.HSSFShape;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.*;
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker;import javax.imageio.ImageIO;
import java.awt.Color;
import java.awt.Font;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** width:pix=getColumnWidthInPixels*1.15* height:pix=getHeightInPoints*96/72* <p>* 本示例用来读取Excel报表文件,并力图将报表无差别转化成PNG图片* 使用POI读取Excel各项数据* 使用JAVA 2D绘制PNG* 本示例基本实现了常见Excel的所有样式输出,但Office2007以后的版本添加了条件样式功能,,所以无法实现* 今后可以通过关键字标注等方法,在Excel中需要加入条件样式的单元格用注解标明,使用JAVA计算得出样因为POI的API无法读取条件样式式再绘制出来* 中文乱码问题请查看excel中字体 在本地是否安装* 可以导出图片* <p>*/
public class DrawFromExcel {/*** excel转图片** @param excelUrl excel路径* @param path 图片存储路径* @throws IOException,InvalidFormatException 异常*/public static void excelToImage(String excelUrl, String path) throws IOException, InvalidFormatException {Workbook wb = WorkbookFactory.create(new File(excelUrl));wb.close();// 获取每个Sheet表for (int sheetIndex = 0; sheetIndex < wb.getNumberOfSheets(); sheetIndex++) {// 图片宽度int imageWidth;// 图片高度int imageHeight;//第一个工作表Sheet sheet = wb.getSheetAt(sheetIndex);// 获取工作表是否存在图片Map<String, PictureData> maplist = null;if (excelUrl.endsWith(".xls")) {maplist = getPictures1((HSSFSheet) sheet);} else if (excelUrl.endsWith(".xlsx")) {maplist = getPictures2((XSSFSheet) sheet);}// 获取整个sheet中合并单元格组合的集合List<CellRangeAddress> rangeAddress = sheet.getMergedRegions();//检查区域内是否存在数据int rowSize = sheet.getPhysicalNumberOfRows();int colSize = sheet.getRow(0).getPhysicalNumberOfCells();if (rowSize == 0 || colSize == 0) {continue;}// 遍历需要扫描的区域UserCell[][] cells = new UserCell[rowSize][colSize];int[] rowPixPos = new int[rowSize + 1];rowPixPos[0] = 0;int[] colPixPos = new int[colSize + 1];colPixPos[0] = 0;float height = 0f;float width = 0f;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 = !(sheet.isColumnHidden(j) || sheet.getRow(i).getZeroHeight());cells[i][j].setShow(ifShow);// 计算所求区域宽度 如果该单元格是隐藏的,则置宽度为0float widthPix = !ifShow ? 0 : sheet.getColumnWidthInPixels(j);if (i == 0) {width += widthPix;}colPixPos[j + 1] = (int) (widthPix * 1.15 + colPixPos[j]);}// 计算所求区域高度 行序列不能隐藏boolean ifShow = !sheet.getRow(i).getZeroHeight();// 如果该单元格是隐藏的,则置高度为0float heightPoint = !ifShow ? 0 : sheet.getRow(i).getHeightInPoints();height += heightPoint;rowPixPos[i + 1] = (int) (heightPoint * 96 / 72) + rowPixPos[i];}imageHeight = (int) (height * 96 / 72);imageWidth = (int) (width * 115 / 100);List<Grid> grids = getGrids(wb, rangeAddress, rowSize, colSize, cells, rowPixPos, colPixPos, maplist);// 绘图draw(imageWidth, imageHeight, grids, path);}}/*** 根据表格制作网格** @param wb excel* @param rangeAddress 合并单元格组合* @param rowSize 行大小* @param colSize 列大小* @param cells 单元格* @param rowPixPos 需要扫描的行大小* @param colPixPos 需要扫描的列大小* @return 网格数据*/private static List<Grid> getGrids(Workbook wb, List<CellRangeAddress> rangeAddress, int rowSize, int colSize, UserCell[][] cells, int[] rowPixPos, int[] colPixPos, Map<String, PictureData> dataMap) {List<Grid> grids = new ArrayList<>();for (int i = 0; i < rowSize; i++) {for (int j = 0; j < colSize; j++) {//当前表格Cell cell = cells[i][j].getCell();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 (cell == null || (isInMergedStatus[0] == 0 && isInMergedStatus[1] == 0)) {continue;} else if (isInMergedStatus[0] != -1 && isInMergedStatus[1] != -1) {// 此单元格是合并单元格,并且属于第一个单元格,则需要调整网格大小int lastRowPos = Math.min(isInMergedStatus[0], rowSize - 1);int lastColPos = Math.min(isInMergedStatus[1], colSize - 1);grid.setWidth(colPixPos[lastColPos + 1] - colPixPos[j]);grid.setHeight(rowPixPos[lastRowPos + 1] - rowPixPos[i]);}// 单元格背景颜色CellStyle cs = cell.getCellStyle();if (cs.getFillPatternEnum() == FillPatternType.SOLID_FOREGROUND) {grid.setBgColor(cell.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;if (cell.getCellTypeEnum() == CellType.NUMERIC) {if (DateUtil.isCellDateFormatted(cell)) {strCell = DateFormatUtils.format(cell.getDateCellValue(), "yyyy-MM-dd");} else {NumberFormat nf = NumberFormat.getInstance();strCell = String.valueOf(nf.format(cell.getNumericCellValue())).replace(",", "");}} else if (cell.getCellTypeEnum() == CellType.STRING) {strCell = String.valueOf(cell.getStringCellValue());} else if (cell.getCellTypeEnum() == CellType.BOOLEAN) {strCell = String.valueOf(cell.getBooleanCellValue());} else if (cell.getCellTypeEnum() == CellType.ERROR) {strCell = "错误类型";} else {strCell = "";}// 如果为空可能单元格是图片if ("".equals(strCell)) {PictureData pictureData = dataMap.get(i + "-" + j);if (pictureData != null) {grid.setData(pictureData.getData());}}if (cell.getCellStyle().getDataFormatString().contains("0.00%")) {try {double dbCell = Double.parseDouble(strCell);strCell = new DecimalFormat("#.00").format(dbCell * 100) + "%";} catch (NumberFormatException ignored) {}}grid.setText(strCell.matches("\\w*\\.0") ? strCell.substring(0, strCell.length() - 2) : strCell);grids.add(grid);}}return grids;}/*** 绘图** @param imageWidth 图片宽度* @param imageHeight 图片高度* @param grids 绘制图片的内容*/public static void draw(int imageWidth, int imageHeight, List<Grid> grids, String path) throws IOException {BufferedImage image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB);Graphics2D g2d = image.createGraphics();// 平滑字体g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT);g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT);g2d.setRenderingHint(RenderingHints.KEY_TEXT_LCD_CONTRAST, 140);g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_OFF);g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.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);// 图片if (g.getData() != null && g.getData().length > 0) {InputStream inputStream = new ByteArrayInputStream(g.getData());BufferedImage bg = ImageIO.read(inputStream);g2d.drawImage(bg.getScaledInstance(g.getWidth(), g.getHeight(), Image.SCALE_DEFAULT),g.getX(),g.getY(), null);}// 文字else {g2d.drawString(g.getText(),g.getX() + (g.getWidth() - strWidth) / 2,g.getY() + (g.getHeight() - font.getSize()) / 2 + font.getSize());}}g2d.dispose();//生成图片String imgUrl = path + File.separator + System.currentTimeMillis() + ".png";ImageIO.write(image, "png", new File(imgUrl));}/*** 判断Excel中的单元格是否为合并单元格** @param row 当前行号* @param col 当前列号* @param rangeAddress 整个sheet中合并单元格组合的集合* @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() && col >= cra.getFirstColumn() && col <= cra.getLastColumn()) {isInMergedStatus[0] = 0;isInMergedStatus[1] = 0;return isInMergedStatus;}}return isInMergedStatus;}/*** 获取图片和位置 (xls)** @param sheet -* @return -* Z*/public static Map<String, PictureData> getPictures1(HSSFSheet sheet) {Map<String, PictureData> map = new HashMap<>();List<HSSFShape> list = sheet.getDrawingPatriarch().getChildren();for (HSSFShape shape : list) {if (shape instanceof HSSFPicture) {HSSFPicture picture = (HSSFPicture) shape;HSSFClientAnchor cAnchor = (HSSFClientAnchor) picture.getAnchor();PictureData pdata = picture.getPictureData();// 行号-列号String key = cAnchor.getRow1() + "-" + cAnchor.getCol1();map.put(key, pdata);}}return map;}/*** 获取图片和位置 (xlsx)** @param sheet -* @return -*/public static Map<String, PictureData> getPictures2(XSSFSheet sheet) {Map<String, PictureData> map = new HashMap<>();List<POIXMLDocumentPart> list = sheet.getRelations();for (POIXMLDocumentPart part : list) {if (part instanceof XSSFDrawing) {XSSFDrawing drawing = (XSSFDrawing) part;List<XSSFShape> shapes = drawing.getShapes();for (XSSFShape shape : shapes) {XSSFPicture picture = (XSSFPicture) shape;XSSFClientAnchor anchor = picture.getPreferredSize();CTMarker marker = anchor.getFrom();// 行号-列号String key = marker.getRow() + "-" + marker.getCol();map.put(key, picture.getPictureData());}}}return map;}}
package com.example.excel;import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.xssf.usermodel.XSSFColor;import java.awt.*;public class Grid {/*** 是否显示*/private boolean show;/*** 对应Excel中的row,也可以理解为cells[i][j]的i*/private int row;/*** 对应Excel中的col,也可以理解为cells[i][j]的j*/private int col;/*** x坐标*/private int x;/*** y坐标*/private int y;private int width;private int height;private String text;private byte[] data;/*** 字体 new Font("微软雅黑", Font.PLAIN, 12);*/private Font font;private Color bgColor = null;private Color ftColor = null;public int getRow() {return row;}public void setRow(int row) {this.row = row;}public int getCol() {return col;}public void setCol(int col) {this.col = col;}public int getX() {return x;}public void setX(int x) {this.x = x;}public int getY() {return y;}public void setY(int y) {this.y = y;}public boolean isShow() {return show;}public void setShow(boolean show) {this.show = show;}public int getWidth() {return width;}public void setWidth(int width) {this.width = width;}public int getHeight() {return height;}public void setHeight(int height) {this.height = height;}public String getText() {return text;}public void setText(String text) {this.text = text;}public byte[] getData() {return data;}public void setData(byte[] data) {this.data = data;}public Color getBgColor() {return bgColor;}/*** 将poi.ss.usermodel.Color 转换成 java.awt.Color* <a href="http://home.cnblogs.com/u/309701/" target="_blank">@param</a> color*/public void setBgColor(org.apache.poi.ss.usermodel.Color color) {this.bgColor = poiColor2awtColor(color);}public void setBgColor(java.awt.Color color) {this.bgColor = color;}public Color getFtColor() {return ftColor;}public void setFtColor(org.apache.poi.ss.usermodel.Color color) {this.ftColor = poiColor2awtColor(color);}public Font getFont() {return font;}public void setFont(org.apache.poi.ss.usermodel.Font font) {if (font != null) {this.font = new java.awt.Font(font.getFontName(), Font.BOLD, font.getFontHeight() / 20 + 2);}}private java.awt.Color poiColor2awtColor(org.apache.poi.ss.usermodel.Color color) {java.awt.Color awtColor = null;//.xlsxif (color instanceof XSSFColor) {XSSFColor xc = (XSSFColor) color;String rgbHex = xc.getARGBHex();if (rgbHex != null) {awtColor = new Color(Integer.parseInt(rgbHex.substring(2), 16));}}//.xlselse if (color instanceof HSSFColor) {HSSFColor hc = (HSSFColor) color;short[] s = hc.getTriplet();if (s != null) {awtColor = new Color(s[0], s[1], s[2]);}}return awtColor;}
}
package com.example.excel;import org.apache.poi.ss.usermodel.Cell;import java.awt.*;public class UserCell implements Comparable<UserCell> {private Cell cell;private int row;private int col;private boolean show;private String text = "";private Color color = null;public Cell getCell() {return cell;}public void setCell(Cell cell) {this.cell = cell;}public int getRow() {return row;}public void setRow(int row) {this.row = row;}public int getCol() {return col;}public void setCol(int col) {this.col = col;}public boolean isShow() {return show;}public void setShow(boolean show) {this.show = show;}public String getText() {return text;}public void setText(String text) {this.text = text;}public Color getColor() {return color;}public void setColor(Color color) {this.color = color;}@Overridepublic int compareTo(UserCell uc) {try {double meDouble = Double.parseDouble(this.getText().replace("%", ""));double heDouble = Double.parseDouble(uc.getText().replace("%", ""));if (meDouble < heDouble) {return -1;} else if (meDouble > heDouble) {return 1;}} catch (Exception ignored) {}return 0;}
}
Java Excel转图片相关推荐
- java excel复制图片_java实现图片用Excel画出来
本文实例为大家分享了java用Excel将图片画出来的具体代码,供大家参考,具体内容如下 能够将任何图片在excel上利用单元格背景完整的描绘出来. 像网络上出现的用excel画出超级玛丽等等,各种图 ...
- Java excel大批量图片数据导出解决内存溢出问题
如果使用poi直接将所有图片一张张写到excel里,最后excel里图片达到10000张之后,内存就快爆掉了,所以,使用该方法将图片写到磁盘里,最后一次性替换掉,目前没有找到更好的方法,暂时使用该方法 ...
- Java Excel 插入图片
在POI中有HSSFPatriarch对象,该对象为画图的顶级管理器,它的createPicture(anchor, pictureIndex)方法就能够在Excel插入一张图片.所以要在Excel中 ...
- java excel poi 图片大小_Apache POI Excel工作表:在保持比例的同时调整图片大小
// Excel width, not character width width = Truncate([{Number of Visible Characters} * {Maximum Digi ...
- java excel 导出图片_JAVA 使用 POI 导出 EXCEL 自定义背景颜色
开发中常用表格导入和导出 Excel 是常见的功能. 在这里分享下使用 POI 导出表格的简单实现,也是为大家提供个思路吧,抛砖引玉,话不多说直接上代码. 1.项目引入 maven 依赖 <!- ...
- java 导出excel 附带图片
java 导出excel 附带图片,思路将后台数据里保存的图片url转为file ,添加到excel里导出 代码示例 String imgPath = filePath +item.getFilePa ...
- Java中world、PDF、Excel转图片
相对来说world.pdf转图片还是比较简单的,world.pdf转html坑是最多的.不过我们这篇文章只写world.pdf转图片,后者我将会用另一篇文章就行讲述. 原理: world.Excel转 ...
- java导出excel插入图片
首项需要的jar包有: 1.poi-3.8-20120326.jar 2.commons-codec-1.10.jar 代码:package com.demo; import java.awt.ima ...
- java导出excel带图片_JAVA的poi实现模版导出excel(带图片).doc
JAVA的poi实现模版导出excel(带图片) 下面是本人使用java的poi实现使用模板到处excel,内容包含图片,使用两种不同的方式实现其到处excel.但是使用jxl实现到处excel只能到 ...
- java下载附件给(pdf、pptx、word、excel、图片)添加水印
java下载附件给(pdf.pptx.word.excel.图片)添加水印 使用组件 poi itext spire.xls ooxml-schemas twelvemonkeys.imageio 等 ...
最新文章
- java使用ireport生成报表_JasperReport(3)——Java简单使用IReport生成的文件建立报表...
- [转]pthread用于进程间通信
- 推荐几本对创业者很有用的书籍
- php curl和file get,PHP cURL与file_get_contents
- 【Java】我的第一个 JAVA 程序:Hello,world!
- Spark Structured SQL报错:Stream stream joins without equality predicate is not supported
- Python计算从n个元素中任选i个的组合数C(n,i)
- 关于域名系统DNS解析IP地址的一些总结
- CNN 卷积神经网络 池化层Pooling 动手学深度学习v2 pytorch
- 机器学习十大算法简介
- Ant Design 遭删库!
- “你还有什么事想问”——作为程序员如何回答面试官的问题
- 雷军,扎克伯格,乔布斯等巨佬的办公桌
- Termux解析公网ipv6——从全世界各地连接你的Termux
- 花旗软件DWH实习回顾
- java基础面试题-
- css调颜色,CSS3 简单的调色板
- python代码中的中文语法错误:SyntaxError: Non-ASCII character ‘\xe5‘ in file trade.py on line 7
- SM8S36CA-汽车TVS瞬态抑制二极管
- canvas插件 fabric.js 使用
热门文章
- 夏书祥-淘宝考试最新答案
- uni-app 生成安卓证书
- 西门子S7-200SMART四种密码解密软件
- BeyondCompare3提示许可密钥过期完美解决方法
- MOSFET知识小结
- 易用宝项目记录day1-springdatajpa
- 矿井下无线基站和地面服务器,煤矿井下无线通信系统_矿井通信
- loadrunner压力测试一般使用流程
- 计算机数据库技术的应用现状,计算机数据库技术的发展及应用
- 自然语言处理NLP技术里程碑、知识结构、研究方向和机构导师(公号回复“NLP总结”下载彩标PDF典藏版资料)