本文假定 Excel 文件中保存的是員工數(shù)據(jù),并且數(shù)據(jù)中帶有員工的頭像。代碼支持的圖片格式有png、bmp、jpg、gif。但是這里需要注意,有些網(wǎng)站上下載的圖片雖然后綴名是 jpg,但是文件二進(jìn)制內(nèi)容的格式是 WebP 的。Java8 目前官方api不支持 WebP ,本文不涉及webp相關(guān)話題,本文代碼也不支持 WebP 格式。
另外我還遇到個(gè)坑,POI 5.2.5 在處理部分 jpg 格式圖片的時(shí)候,無法把圖片輸出到 Excel 文件。為了解決這個(gè)問題,我在代碼中把所有圖片強(qiáng)行轉(zhuǎn)成 png,保存為硬盤上的臨時(shí)文件,再重新輸出到 Excel 文件中。這個(gè)問題我沒有在 POI 4.1.2 版本遇到過。
POI 的接口是線程不安全的,多個(gè)線程同時(shí)向一個(gè)文件輸出會(huì)造成錯(cuò)誤。如果讀者想要在多線程環(huán)境(比如網(wǎng)站后端)使用下面的代碼,要么使用鎖,要么確保各個(gè)線程輸出不同的文件。
本文的代碼計(jì)算了圖片的縮放比例,并且使用 picture.resize(scaleX, scaleY);
方法來設(shè)置圖片縮放比例。這也與 POI 4.1.2 版本不同。POI 4.1.2 版本使用 picture.resize(1, 1);
會(huì)自動(dòng)縮放圖片調(diào)整成合適大小。
pom.xml 文件中添加的依賴:
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.5</version>
</dependency>
員工的 DTO 類:
/**
* 員工DTO
*/
public class EmployeeDTO {
// 工號(hào)
private String no;
// 姓名
private String name;
// 性別
private String gender;
// 頭像
private String portrait;
@Override
public String toString() {
final StringBuffer sb = new StringBuffer("Employee{");
sb.append("no='").append(no).append('\'');
sb.append(", name='").append(name).append('\'');
sb.append(", gender='").append(gender).append('\'');
sb.append(", portrait='").append(portrait).append('\'');
sb.append('}');
return sb.toString();
}
public String getNo() {
return no;
}
public void setNo(String no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getPortrait() {
return portrait;
}
public void setPortrait(String portrait) {
this.portrait = portrait;
}
}
用來生成Excel 文件的 ImageExcelUtils 類文章來源:http://www.zghlxwxcb.cn/news/detail-756057.html
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.Drawing;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.Picture;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import javax.imageio.ImageIO;
public class ImageExcelUtils {
/**
* 讀取jpg圖片
* @param path 圖片文件路徑
* @return BufferedImage
*/
public static BufferedImage readBufferedImage(String path) {
BufferedImage originImage = null;
BufferedImage result = null;
try {
File file = new File(path);
originImage = ImageIO.read(file);
// 確保圖片顏色只有RGB,沒有alpha透明度
result = new BufferedImage(
originImage.getWidth(),
originImage.getHeight(),
BufferedImage.TYPE_INT_RGB
);
result.getGraphics().drawImage(originImage, 0, 0, null);
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
/**
* 設(shè)置excel文件的圖片
* @param workbook 工作簿
* @param sheet sheet頁
* @param imgFilePath 圖片文件路徑
* @param row1 圖片起始的行
* @param col1 圖片起始的列
* @param tempFilePath 臨時(shí)文件路徑
*/
public static void setExcelImg(Workbook workbook, Sheet sheet, String imgFilePath,
int row1, int col1, int width, int height, String tempFilePath) {
File file = new File(imgFilePath);
if (!file.exists()) {
return;
}
// 臨時(shí)文件
File tempFile = new File(tempFilePath);
if (tempFile.exists()) {
tempFile.delete();
}
FileInputStream inputStream = null;
boolean isClose = false;
try {
BufferedImage bufferedImage = readBufferedImage(imgFilePath);
int imageWidth = bufferedImage.getWidth();
int imageHeight = bufferedImage.getHeight();
ImageIO.write(bufferedImage, "png", tempFile);
inputStream = new FileInputStream(tempFile);
//利用POI提供的工具類把文件流轉(zhuǎn)化成二進(jìn)制數(shù)據(jù)
byte[] bytes = IOUtils.toByteArray(inputStream);
//向POI內(nèi)存中添加一張圖片,返回圖片在圖片集合中的索引
int pictureIndex = workbook.addPicture(bytes, Workbook.PICTURE_TYPE_PNG);//參數(shù)一:圖片的二進(jìn)制數(shù)據(jù),參數(shù)二:圖片類型
//從Workbook中得到繪制圖片的工具類
CreationHelper helper = workbook.getCreationHelper();
//創(chuàng)建錨點(diǎn),設(shè)置圖片坐標(biāo)
ClientAnchor clientAnchor = helper.createClientAnchor();
clientAnchor.setAnchorType(ClientAnchor.AnchorType.DONT_MOVE_AND_RESIZE);
clientAnchor.setRow1(row1); // 設(shè)置起始行
clientAnchor.setCol1(col1); // 設(shè)置起始列
//從sheet對(duì)象中得到一個(gè)繪圖對(duì)象
Drawing<?> drawingPatriarch = sheet.createDrawingPatriarch();
//繪制圖片,錨點(diǎn),圖片在內(nèi)存中的位置
Picture picture = drawingPatriarch.createPicture(clientAnchor, pictureIndex);
// 使用固定的長(zhǎng)寬比例系數(shù)
double scaleX = 1.0;
double scaleY = 1.0;
if (imageWidth <= width && imageHeight <= height) {
scaleX = 1.0;
scaleY = 1.0;
} else {
scaleX = (double) width / (double) imageWidth;
scaleY = (double) height / (double) imageHeight;
double min = Math.min(scaleX, scaleY);
scaleX = scaleY = min;
}
picture.resize(scaleX, scaleY);//自適應(yīng)渲染圖片
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (inputStream != null && !isClose) {
inputStream.close();
}
tempFile.delete();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 創(chuàng)建Excel文件
* @param employeeDTOList 員工列表
* @param file 輸出的 Excel 文件
* @param tempFilePath 臨時(shí)文件路徑
*/
public static void createExcelFile(List<EmployeeDTO> employeeDTOList, File file, String tempFilePath) {
//創(chuàng)建工作簿,excel2007版本的,如果是excel2003的話。創(chuàng)建的對(duì)象是:HSSFWorkbook
Workbook workbook = new SXSSFWorkbook();
//創(chuàng)建sheet
Sheet sheet = workbook.createSheet("picture sheet");
// 列寬分別是25個(gè)字符和40個(gè)字符,一字符等于 6.107 像素
sheet.setColumnWidth(0, 25 * 256);
sheet.setColumnWidth(1, 25 * 256);
sheet.setColumnWidth(2, 25 * 256);
sheet.setColumnWidth(3, 40 * 256);
// 行高是 120 磅,1磅是 1.34039 像素
sheet.setDefaultRowHeightInPoints(120f);
// 設(shè)置字體,黑體
Font font = workbook.createFont();
font.setFontName("黑體");
// 字體加粗
font.setBold(true);
CellStyle cellStyle = workbook.createCellStyle();
cellStyle.setFont(font);
cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
cellStyle.setAlignment(HorizontalAlignment.CENTER);
// 表格標(biāo)題行
Row firstRow = sheet.createRow(0);
Cell r0c0 = firstRow.createCell(0);
r0c0.setCellValue("工號(hào)");
Cell r0c1 = firstRow.createCell(1);
r0c1.setCellValue("姓名");
Cell r0c2 = firstRow.createCell(2);
r0c2.setCellValue("性別");
Cell r0c3 = firstRow.createCell(3);
r0c3.setCellValue("頭像");
r0c0.setCellStyle(cellStyle);
r0c1.setCellStyle(cellStyle);
r0c2.setCellStyle(cellStyle);
r0c3.setCellStyle(cellStyle);
int size = employeeDTOList.size();
for (int i = 0; i < size; i++) {
EmployeeDTO dto = employeeDTOList.get(i);
int rowIndex = i + 1;
Row row = sheet.createRow(rowIndex);
Cell c0 = row.createCell(0);
Cell c1 = row.createCell(1);
Cell c2 = row.createCell(2);
Cell c3 = row.createCell(3);
// 向excel中輸入圖片
String portrait = dto.getPortrait();
if (null != portrait && portrait.trim().length() > 0) {
portrait = portrait.trim();
setExcelImg(workbook, sheet, portrait, rowIndex, 3, 244, 160, tempFilePath);
}
c0.setCellValue(dto.getNo());
c1.setCellValue(dto.getName());
c2.setCellValue(dto.getGender());
}
//創(chuàng)建文件輸入流
FileOutputStream out = null;
//創(chuàng)建文件輸出流
try {
out = new FileOutputStream(file);
//調(diào)用工作簿的write創(chuàng)建excel
workbook.write(out);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.flush();
out.close();
out = null;
}
} catch (IOException e) {
e.printStackTrace();
}
} // end finally
}
}
包含 main 方法的 Test 類,測(cè)試具體效果文章來源地址http://www.zghlxwxcb.cn/news/detail-756057.html
import java.io.File;
import java.util.List;
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
List<EmployeeDTO> employeeDTOList = new ArrayList<>();
EmployeeDTO emp_1 = new EmployeeDTO();
emp_1.setNo("1");
emp_1.setName("張三");
emp_1.setGender("男");
emp_1.setPortrait("D:/1715284526222417922.jpg");
EmployeeDTO emp_2 = new EmployeeDTO();
emp_2.setNo("2");
emp_2.setName("李四");
emp_2.setGender("男");
emp_2.setPortrait("D:\\bmptest.bmp");
EmployeeDTO emp_3 = new EmployeeDTO();
emp_3.setNo("3");
emp_3.setName("王二");
emp_3.setGender("女");
emp_3.setPortrait("D:\\113.jpg");
EmployeeDTO emp_4 = new EmployeeDTO();
emp_4.setNo("4");
emp_4.setName("涂軍");
emp_4.setGender("男");
emp_4.setPortrait("D:\\309446533.gif");
employeeDTOList.add(emp_1);
employeeDTOList.add(emp_2);
employeeDTOList.add(emp_3);
employeeDTOList.add(emp_4);
File file = new File("D:\\ws\\tmpdir\\out.xlsx");
String tempFilePath = "D:\\ws\\tmpdir\\temp.png";
ImageExcelUtils.createExcelFile(employeeDTOList, file, tempFilePath);
}
}
到了這里,關(guān)于【193】Java8調(diào)用POI 5.2.5生成帶圖片的Excel文件的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!