依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.10</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>ooxml-schemas</artifactId>
<version>1.4</version>
</dependency>
代码
package com.example.boottest.utils;
import cn.hutool.core.date.DateUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import cn.hutool.poi.excel.StyleSet;
import lombok.SneakyThrows;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
public class MyExcelUtil {
public static void webExport(HttpServletResponse response, String title, String waterMark, List<String> sheetNameList, List<List<?>> listList, Consumer<List<ExcelWriter>> extList) {
commonWebExport(response, title, waterMark, sheetNameList, listList, extList);
}
public static void webExport(HttpServletResponse response, String title, String waterMark, List<String> sheetNameList, List<List<?>> listList) {
commonWebExport(response, title, waterMark, sheetNameList, listList, null);
}
public static void fileExport(String path, String title, String waterMark, List<String> sheetNameList, List<List<?>> listList, Consumer<List<ExcelWriter>> extList) {
commonFileExport(path, title, waterMark, sheetNameList, listList, extList);
}
public static void fileExport(String path, String title, String waterMark, List<String> sheetNameList, List<List<?>> listList) {
commonFileExport(path, title, waterMark, sheetNameList, listList, null);
}
private static void commonFileExport(String path, String title, String waterMark, List<String> sheetNameList, List<List<?>> listList, Consumer<List<ExcelWriter>> extList) {
if (path.endsWith("\\")) {
final StringBuilder builder = new StringBuilder(path);
final int length = path.length();
builder.delete(length - 1, length);
path = builder.toString();
}
final String filename = String.format("%s\\%s_%s.xlsx", path, title, DateUtil.date().toString("yyyyMMddHHmmss"));
try( ExcelWriter writer = excelWriter(waterMark, sheetNameList, listList, extList); FileOutputStream out = new FileOutputStream(filename);) {
writer.flush(out, true);
} catch (IOException e) {
e.printStackTrace();
}
}
@SneakyThrows
private static void commonWebExport(HttpServletResponse response, String title, String waterMark, List<String> sheetNameList, List<List<?>> listList, Consumer<List<ExcelWriter>> extList) {
final String filename = String.format("%s_%s.xlsx", title, DateUtil.date().toString("yyyyMMddHHmmss"));
response.setContentType("application/vnd.ms-excel;charset=utf-8");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
try (ExcelWriter writer = excelWriter(waterMark, sheetNameList, listList, extList);ServletOutputStream out = response.getOutputStream()) {
writer.flush(out, true);
} catch (IOException e) {
e.printStackTrace();
}
}
private static ExcelWriter excelWriter(String waterMark, List<String> sheetNameList, List<List<?>> listList, Consumer<List<ExcelWriter>> extList) {
ExcelWriter writer;
int count = 0;
for (List<?> list : listList) {
count += list.size();
}
if (count > 10000) {
writer = ExcelUtil.getBigWriter();
} else {
writer = ExcelUtil.getWriter(true);
}
List<ExcelWriter> writers = new ArrayList<>();
for (int i = 0; i < sheetNameList.size(); i++) {
writer.setSheet(i);
writer = writer.renameSheet(i, sheetNameList.get(i));
writers.add(writer);
writer.setOnlyAlias(true).write(listList.get(i), true);
}
if (extList != null) {
extList.accept(writers);
}
Font font = writer.createFont();
font.setColor(IndexedColors.DARK_BLUE.index);
font.setBold(true);
font.setFontHeightInPoints((short) 13);
font.setFontName("宋体");
final StyleSet styleSet = writer.getStyleSet();
styleSet.getHeadCellStyle().setFont(font);
styleSet.getCellStyleForDate().setDataFormat(writer.getWorkbook().createDataFormat().getFormat("yyyy-MM-dd HH:mm:ss"));
final CellStyle cellStyle = styleSet.getCellStyle();
cellStyle.setAlignment(HorizontalAlignment.CENTER);
cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
final Sheet sheet = writer.getSheet();
int columnCount = writer.getColumnCount();
for (int i = 0; i < columnCount; i++) {
sheet.autoSizeColumn(i);
}
final Workbook workbook = writer.getWorkbook();
if (workbook instanceof XSSFWorkbook) {
ExcelWatermarkUtil.putWatermarkToWorkbook((XSSFWorkbook) workbook, waterMark);
}
if (workbook instanceof SXSSFWorkbook) {
ExcelWatermarkUtil.putWatermarkToWorkbook((SXSSFWorkbook) workbook, waterMark);
}
return writer;
}
}
package com.example.boottest.utils;
import cn.hutool.core.util.ReflectUtil;
import lombok.SneakyThrows;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.TargetMode;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFPictureData;
import org.apache.poi.xssf.usermodel.XSSFRelation;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
public class ExcelWatermarkUtil {
public static void putWatermarkToWorkbook(XSSFWorkbook workbook, String watermarkContent) {
try (ByteArrayOutputStream byteArrayOutputStream = createWaterMark(watermarkContent)) {
int pictureIdx = workbook.addPicture(byteArrayOutputStream.toByteArray(), Workbook.PICTURE_TYPE_PNG);
for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
XSSFSheet sheet = workbook.getSheetAt(i);
PackageRelationship pr = sheet.getPackagePart().addRelationship(workbook.getAllPictures().get(pictureIdx).getPackagePart().getPartName(), TargetMode.INTERNAL, XSSFRelation.IMAGES.getRelation(), null);
sheet.getCTWorksheet().addNewPicture().setId(pr.getId());
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void putWatermarkToWorkbook(SXSSFWorkbook workbook, String watermarkContent) {
try (ByteArrayOutputStream byteArrayOutputStream = createWaterMark(watermarkContent)) {
int pictureIdx = workbook.addPicture(byteArrayOutputStream.toByteArray(), Workbook.PICTURE_TYPE_PNG);
XSSFPictureData pictureData = (XSSFPictureData) workbook.getAllPictures().get(pictureIdx);
for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
SXSSFSheet sheet = workbook.getSheetAt(i);
XSSFSheet shReflect = (XSSFSheet) ReflectUtil.getFieldValue(sheet, "_sh");
PackageRelationship pr = shReflect.getPackagePart().addRelationship(pictureData.getPackagePart().getPartName(), TargetMode.INTERNAL, XSSFRelation.IMAGES.getRelation(), null);
shReflect.getCTWorksheet().addNewPicture().setId(pr.getId());
}
} catch (IOException e) {
e.printStackTrace();
}
}
@SneakyThrows
private static ByteArrayOutputStream createWaterMark(String content) {
BufferedImage waterMarkImage = new BufferedImage(WatermarkParam.WIDTH, WatermarkParam.HEIGHT, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics2d = waterMarkImage.createGraphics();
waterMarkImage = graphics2d.getDeviceConfiguration().createCompatibleImage(WatermarkParam.WIDTH, WatermarkParam.HEIGHT, Transparency.TRANSLUCENT);
graphics2d.dispose();
graphics2d = waterMarkImage.createGraphics();
graphics2d.setColor(WatermarkParam.COLOR);
graphics2d.setStroke(new BasicStroke(1));
Font font = createFont();
graphics2d.setFont(font);
graphics2d.rotate(WatermarkParam.THETA, (double) waterMarkImage.getWidth() / 2, (double) waterMarkImage.getHeight() / 2);
FontRenderContext context = graphics2d.getFontRenderContext();
Rectangle2D bounds = font.getStringBounds(content, context);
double x = (WatermarkParam.WIDTH - bounds.getWidth()) / 2;
double y = (WatermarkParam.HEIGHT - bounds.getHeight()) / 2;
double ascent = -bounds.getY();
double baseY = y + ascent;
graphics2d.drawString(content, (int) x, (int) baseY);
graphics2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
graphics2d.dispose();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ImageIO.write(waterMarkImage, WatermarkParam.FORMAT, byteArrayOutputStream);
return byteArrayOutputStream;
}
private static Font createFont() throws IOException {
Resource resource = new ClassPathResource("fonts/msyh.ttf");
int fontStyle = Font.PLAIN;
try (BufferedInputStream bs = new BufferedInputStream(resource.getInputStream())) {
Font font = Font.createFont(fontStyle, bs);
font = font.deriveFont(fontStyle, 30);
return font;
} catch (FontFormatException e) {
throw new RuntimeException(e);
}
}
public static final class WatermarkParam {
public final static int WIDTH = 300;
public final static int HEIGHT = 250;
public final static Color COLOR = new Color(0,0,0,20);
public final static double THETA = -0.5;
public final static String FORMAT = "png";
}
}