案例
一、引入依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.6</version>
</dependency>
二、创建模板excel文件,放入工程中
三、编写代码
/**
* @author: huangshuai
* @Description 打印装车清单
* @date 2021/9/7 11:50
*/
public class PrintLoadedWagons {
//指定装车清单模板文件路径
private static final String MODE_FILE_PATH = "templates/装车清单模板.xlsx";
//往excel填充的数据
private Map<String, Object> dataMap;
public PrintLoadedWagons(Map<String, Object> dataMap) {
this.dataMap = dataMap;
}
/**
* 生成pdf文件
*/
public boolean generatePsPdfFile() {
InputStream modelFileIn = null;
ByteArrayInputStream swapStream = null;
ByteArrayOutputStream outputStream = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ByteArrayOutputStream bos2 = new ByteArrayOutputStream();
ByteArrayInputStream printStream = null;
ByteArrayInputStream bis = null;
InputStream imageStream = null;
try {
modelFileIn = FileUtil.getResourcesStream(MODE_FILE_PATH);
ExcelWriter excelWriter = EasyExcel.write(baos).withTemplate(modelFileIn).build();
WriteSheet writeSheet = EasyExcel.writerSheet().build();
excelWriter.fill(dataMap, writeSheet);
excelWriter.finish();
//excel文件的输入流
swapStream = new ByteArrayInputStream(baos.toByteArray());
BufferedImage bufferedImage = BarcodeUtils.insertWords(BarcodeUtils.getBarCode(dataMap.get("batch").toString(), 220, 80), "*" + dataMap.get("batch").toString() + "*");
imageStream = getImageStream(bufferedImage);
//将条形码图片插入到excel中
outputStream = insBarcodeInExcel(imageStream, swapStream);
bis = new ByteArrayInputStream(outputStream.toByteArray());
//将excel转为pdf
Excel2PdfUtil.excel2pdf(bis, bos2);
printStream = new ByteArrayInputStream(bos2.toByteArray());
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (baos != null) {
baos.close();
}
if (bos2 != null) {
bos2.close();
}
if (swapStream != null) {
swapStream.close();
}
if (imageStream != null) {
imageStream.close();
}
if (outputStream != null) {
outputStream.close();
}
if (bis != null) {
bis.close();
}
if (printStream != null) {
printStream.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return true;
}
/**
* @param imageInput 条形码图片的输入流
* @param sourceInput excel文件的输入流
*/
public static ByteArrayOutputStream insBarcodeInExcel(InputStream imageInput, InputStream sourceInput) {
XSSFWorkbook wb = null;
XSSFSheet sheet = null;
ByteArrayOutputStream baos = null;
try {
wb = new XSSFWorkbook(sourceInput);
sheet = wb.getSheetAt(0);
byte[] bytes = IOUtils.toByteArray(imageInput);
int pictureIdx = wb.addPicture(bytes, Workbook.PICTURE_TYPE_PNG);
CreationHelper helper = wb.getCreationHelper();
ClientAnchor anchor = helper.createClientAnchor();
anchor.setCol1(2);//设置条形码的横坐标位置
anchor.setRow1(40);//设置条形码的纵坐标位置
Picture pict = sheet.createDrawingPatriarch().createPicture(anchor, pictureIdx);
pict.resize();
baos = new ByteArrayOutputStream();
wb.write(baos);
return baos;
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (imageInput != null) {
imageInput.close();
}
if (sourceInput != null) {
sourceInput.close();
}
if (baos != null) {
baos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
/**
* 将BufferedImage转为InputStream
*/
public static InputStream getImageStream(BufferedImage bimage) {
InputStream is = null;
ByteArrayOutputStream bs = new ByteArrayOutputStream();
ImageOutputStream imOut;
try {
imOut = ImageIO.createImageOutputStream(bs);
ImageIO.write(bimage, "jpg", imOut);
is = new ByteArrayInputStream(bs.toByteArray());
} catch (IOException e) {
e.printStackTrace();
}
return is;
}
}
将excel转成pdf的工具类如下:
public class Excel2PdfUtil {
public static void excel2pdf(InputStream sourceFileStream, OutputStream destFileStream) {
if (!getLicense()) { // 验证License 若不验证则转化出的pdf文档会有水印产生
return;
}
try {
Workbook wb = new Workbook(sourceFileStream);// 原始excel路径
PdfSaveOptions pdfSaveOptions = new PdfSaveOptions();
pdfSaveOptions.setOnePagePerSheet(false);
int[] autoDrawSheets = {3};
//当excel中对应的sheet页宽度太大时,在PDF中会拆断并分页。此处等比缩放。
// autoDraw(wb,autoDrawSheets);
int[] showSheets = {0};
//隐藏workbook中不需要的sheet页。
printSheetPage(wb, showSheets);
wb.save(destFileStream, pdfSaveOptions);
destFileStream.flush();
destFileStream.close();
} catch (Exception e) {
throw new RuntimeException("Excel转PDF异常!", e);
}
}
/**
* 获取license 去除水印
*
* @return
*/
private static boolean getLicense() {
boolean result = false;
try {
InputStream is = Excel2PdfUtil.class.getClassLoader().getResourceAsStream("\license.xml");
License aposeLic = new License();
aposeLic.setLicense(is);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 隐藏workbook中不需要的sheet页。
*
* @param wb
* @param page 显示页的sheet数组
*/
private static void printSheetPage(Workbook wb, int[] page) {
for (int i = 1; i < wb.getWorksheets().getCount(); i++) {
wb.getWorksheets().get(i).setVisible(false);
}
if (null == page || page.length == 0) {
wb.getWorksheets().get(0).setVisible(true);
} else {
for (int i = 0; i < page.length; i++) {
wb.getWorksheets().get(i).setVisible(true);
}
}
}
}
生成条形码和二维码的工具类如下:
/**
* @author: huangshuai
* @Description 生成条形码工具类
* @date 2021/7/26 10:48
*/
public class BarcodeUtils {
private static final String CHARSET = "utf-8";
/**
* 条形码宽度
*/
private static final int WIDTH = 220;
/**
* 条形码高度
*/
private static final int HEIGHT = 80;
/**
* 字体大小
*/
private static final int FONT_SIZE = 28;
/**
* 加文字 条形码
*/
private static final int WORD_HEIGHT = HEIGHT + FONT_SIZE;
/**
* 文字间距
*/
private static final int WORD_DISTANCE = 17;
/**
* 文字编写相对纵坐标
*/
private static final int WORD_Y = 21;
/**
* 设置 条形码参数
*/
private static Map<EncodeHintType, Object> hints = new HashMap<>(5);
static {
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
hints.put(EncodeHintType.MARGIN, 1);
}
/**
* 生成条形码图片
* @param vaNumber 条形码的内容
* @param width 条形码的宽度
* @param height 条形码的高度
*/
public static BufferedImage getBarCode(String vaNumber, int width, int height) {
try {
Code128Writer writer = new Code128Writer();
// 编码内容, 编码类型, 宽度, 高度, 设置参数
BitMatrix bitMatrix = writer.encode(vaNumber, BarcodeFormat.CODE_128, width, height, hints);
return MatrixToImageWriter.toBufferedImage(bitMatrix);
} catch (WriterException e) {
e.printStackTrace();
}
return null;
}
/**
* 图片下边插入文字,并且文字与图片对齐
* @param image 条形码图片
* @param words 待插入的文字
*/
public static BufferedImage insertWords(BufferedImage image, String words) {
// 新的图片,把带logo的二维码下面加上文字
if (!StringUtils.isEmpty(words)) {
BufferedImage outImage = new BufferedImage(WIDTH, WORD_HEIGHT, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = outImage.createGraphics();
// 抗锯齿
setGraphics2D(g2d);
// 设置白色
setColorWhite(g2d);
// 画条形码到新的面板
g2d.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null);
// 画文字到新的面板
g2d.setColor(Color.BLACK);
// 字体、字型、字号
g2d.setFont(new Font("黑体", Font.PLAIN, FONT_SIZE));
int wordStartY = HEIGHT + 21;
String content = words.substring(1, words.length() - 1);
int inputWidth = new Code128Writer().encode(content).length;
int fullWidth = inputWidth + 1;
int outputWidth = Math.max(WIDTH, fullWidth);
int multiple = outputWidth / fullWidth;
int leftPadding = (outputWidth - (inputWidth * multiple)) / 2;
int x = leftPadding;
String[] split = words.split("");
int len = split.length;
int step = new Long(Math.round(WIDTH - leftPadding * 2) / words.length()).intValue();
for (int i = 0; i < len; i++) {
g2d.drawString(split[i], x, wordStartY);
x = x + step;
}
outImage.flush();
return outImage;
}
return null;
}
/**
* 设置 Graphics2D 属性 (抗锯齿)
*
* @param g2d Graphics2D提供对几何形状、坐标转换、颜色管理和文本布局更为复杂的控制
*/
private static void setGraphics2D(Graphics2D g2d) {
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT);
Stroke s = new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER);
g2d.setStroke(s);
}
/**
* 设置背景为白色
*
* @param g2d Graphics2D提供对几何形状、坐标转换、颜色管理和文本布局更为复杂的控制
*/
private static void setColorWhite(Graphics2D g2d) {
g2d.setColor(Color.WHITE);
// 填充整个屏幕
g2d.fillRect(0, 0, 600, 600);
// 设置笔刷
g2d.setColor(Color.BLACK);
}
/**
* 将imageInput图片输入流插入到excel文件中
* @param imageInput 条形码图片的输入流
* @param sourceInput excel文件的输入流
* @param x 图片插入excel的横坐标
* @param y 图片插入excel的纵坐标
*/
public static ByteArrayOutputStream insBarcodeInExcel(InputStream imageInput,
InputStream sourceInput,
int x,
int y) {
XSSFWorkbook wb = null;
XSSFSheet sheet = null;
ByteArrayOutputStream baos = null;
try {
wb = new XSSFWorkbook(sourceInput);
sheet = wb.getSheetAt(0);
byte[] bytes = IOUtils.toByteArray(imageInput);
int pictureIdx = wb.addPicture(bytes, Workbook.PICTURE_TYPE_PNG);
CreationHelper helper = wb.getCreationHelper();
ClientAnchor anchor = helper.createClientAnchor();
anchor.setCol1(x);//设置条形码的横坐标位置
anchor.setRow1(y);//设置条形码的纵坐标位置
Picture pict = sheet.createDrawingPatriarch().createPicture(anchor, pictureIdx);
pict.resize();
baos = new ByteArrayOutputStream();
wb.write(baos);
return baos;
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (imageInput != null) {
imageInput.close();
}
if (sourceInput != null) {
sourceInput.close();
}
if (baos != null) {
baos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
/**
* 将BufferedImage转为InputStream
*/
public static InputStream getImageStream(BufferedImage bimage) {
InputStream is = null;
ByteArrayOutputStream bs = new ByteArrayOutputStream();
ImageOutputStream imOut;
try {
imOut = ImageIO.createImageOutputStream(bs);
ImageIO.write(bimage, "jpg", imOut);
is = new ByteArrayInputStream(bs.toByteArray());
} catch (IOException e) {
e.printStackTrace();
}
return is;
}
/**
* 图片下边插入文字,并且文字相对图片居中
* @param image 图片
* @param words 待插入的文字
* @param width 图片宽度
* @param height 图片高度
*/
public static BufferedImage insertWordsIntoImage(BufferedImage image,
String words,
int width,
int height) {
// 新的图片,把带logo的二维码下面加上文字
if (!StringUtils.isEmpty(words)) {
BufferedImage outImage = new BufferedImage(width, height + FONT_SIZE, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = outImage.createGraphics();
// 抗锯齿
setGraphics2D(g2d);
// 设置白色
setColorWhite(g2d);
// 画条形码到新的面板
g2d.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null);
// 画文字到新的面板
g2d.setColor(Color.BLACK);
// 字体、字型、字号
g2d.setFont(new Font("黑体", Font.PLAIN, FONT_SIZE));
int inputWidth = new Code128Writer().encode(words).length;
int fullWidth = inputWidth + 1;
int outputWidth = Math.max(width, fullWidth);
int multiple = outputWidth / fullWidth;
int leftPadding = (outputWidth - inputWidth * multiple) / 2;//条形码左边留白距离
String[] split = words.split("");
int len = split.length;
int x = leftPadding + (width - 2 * leftPadding - len * WORD_DISTANCE) / 2;//文字开始写的横坐标
int wordStartY = height + WORD_Y;//条形码下方文字的纵坐标
for (int i = 0; i < len; i++) {
g2d.drawString(split[i], x, wordStartY);
x = x + WORD_DISTANCE;
}
outImage.flush();
return outImage;
}
return null;
}
}
效果如下: