package com.barcode.util;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Random;
import org.docx4j.TraversalUtil;
import org.docx4j.dml.wordprocessingDrawing.Inline;
import org.docx4j.finders.RangeFinder;
import org.docx4j.jaxb.Context;
import org.docx4j.model.structure.SectionWrapper;
import org.docx4j.openpackaging.exceptions.InvalidFormatException;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.Part;
import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage;
import org.docx4j.openpackaging.parts.WordprocessingML.FooterPart;
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
import org.docx4j.org.apache.poi.util.IOUtils;
import org.docx4j.relationships.Relationship;
import org.docx4j.wml.Body;
import org.docx4j.wml.CTBookmark;
import org.docx4j.wml.Document;
import org.docx4j.wml.Drawing;
import org.docx4j.wml.FooterReference;
import org.docx4j.wml.HdrFtrRef;
import org.docx4j.wml.Jc;
import org.docx4j.wml.JcEnumeration;
import org.docx4j.wml.ObjectFactory;
import org.docx4j.wml.P;
import org.docx4j.wml.PPr;
import org.docx4j.wml.R;
import org.docx4j.wml.SectPr;
import org.jbarcode.JBarcode;
import org.jbarcode.encode.CodabarEncoder;
import org.jbarcode.paint.BaseLineTextPainter;
import org.jbarcode.paint.WideRatioCodedPainter;
import org.jbarcode.util.ImageUtil;
import com.tg.dc.client.util.FileOprtUtil;
public class BarcodeUtil {
private static final ObjectFactory factory = Context.getWmlObjectFactory();
/**
* Method Description:生成条形码
*
* @param templatePath
* word文档模板(路径 + 文件名)
* @param bookmarkName
* 书签名
* @return 条形码
*/
public String insertBarcode(String templatePath, String bookmarkName) {
String inputCode = ""; // 13位条形码随机数
Properties prop = new Properties();
try {
String barcodePath = ""; // 条形码临时生成存放路径
// 读取属性文件
InputStream in = getClass().getResourceAsStream(
"barcode.properties");
prop.load(in); // /加载属性列表
Iterator<String> it = prop.stringPropertyNames().iterator();
while (it.hasNext()) {
String key = it.next();
if ("barcodePath".equals(key)) {
barcodePath = prop.getProperty(key);
}
}
if (in != null) {
in.close();
}
// 删除上次生成的临时文件
FileOprtUtil fileOprtUtil = new FileOprtUtil();
fileOprtUtil.deleteFileAndDirectory(barcodePath);
// 生成13位随机数
Random random = new Random();
inputCode += random.nextInt(9) + 1;
for (int i = 0; i < 12; i++) {
inputCode += random.nextInt(10);
}
this.insertPicture(templatePath, templatePath, bookmarkName,
this.getImageFullpath(inputCode, barcodePath));
} catch (Exception e) {
System.out.println("条形码插入word文档失败!");
System.out.println(e);
}
return inputCode;
}
/**
* Method Description:生成条形码
*
* @param inputCode
* 条形码串
* @param barcodePath
* 条形码存放路径
* @return 全路径(路径 + 文件名)
*/
private String getImageFullpath(String inputCode, String barcodePath) {
String fileName = "";
// 文件保存位置
File saveDir = new File(barcodePath);
if (!saveDir.exists()) {
saveDir.mkdir();
}
try {
JBarcode localJBarcode = new JBarcode(CodabarEncoder.getInstance(),
WideRatioCodedPainter.getInstance(),
BaseLineTextPainter.getInstance());
BufferedImage localBufferedImage = localJBarcode
.createBarcode(inputCode);
fileName = inputCode + ".png";
this.saveToPNG(barcodePath, localBufferedImage, fileName);
} catch (Exception localException) {
localException.printStackTrace();
}
return barcodePath + fileName;
}
/**
* Method Description:保存条形码到图片的png格式
*
* @param barcodePath
* 条形码存放路径
* @param paramBufferedImage
* BufferedImage对象
* @param paramString
* 条形码串
*/
private void saveToPNG(String barcodePath,
BufferedImage paramBufferedImage, String paramString) {
this.saveToFile(barcodePath, paramBufferedImage, paramString, "png");
}
/**
* Method Description:保存图片到文件夹
*
* @param barcodePath
* 条形码存放路径
* @param paramBufferedImage
* BufferedImage对象
* @param paramString1
* 条形码串
* @param paramString2
* 图片类型
*/
private void saveToFile(String barcodePath,
BufferedImage paramBufferedImage, String paramString1,
String paramString2) {
try {
FileOutputStream localFileOutputStream = new FileOutputStream(
barcodePath + paramString1);
ImageUtil.encodeAndWrite(paramBufferedImage, paramString2,
localFileOutputStream, 84, 32);
if (localFileOutputStream != null) {
localFileOutputStream.flush();
localFileOutputStream.close();
}
} catch (Exception localException) {
localException.printStackTrace();
}
}
/**
* 创建页脚
*
* @param wPackage
* @return
* @throws Exception
*/
private FooterPart createFooter(WordprocessingMLPackage wPackage)
throws Exception {
FooterPart footerPart = new FooterPart();
Relationship rel = wPackage.getMainDocumentPart().addTargetPart(
footerPart);
this.createFooterReference(wPackage, rel);
return footerPart;
}
/**
* 创建页脚引用关系
*
* @param wPackage
* @param relationship
* @throws InvalidFormatException
*/
private void createFooterReference(WordprocessingMLPackage wPackage,
Relationship relationship) throws InvalidFormatException {
List<SectionWrapper> sections = wPackage.getDocumentModel()
.getSections();
SectPr sectPr = sections.get(sections.size() - 1).getSectPr();
// There is always a section wrapper, but it might not contain a sectPr
if (sectPr == null) {
sectPr = factory.createSectPr();
wPackage.getMainDocumentPart().addObject(sectPr);
sections.get(sections.size() - 1).setSectPr(sectPr);
}
FooterReference footerReference = factory.createFooterReference();
footerReference.setId(relationship.getId());
footerReference.setType(HdrFtrRef.DEFAULT);
sectPr.getEGHdrFtrReferences().add(footerReference);
}
/**
* 创建包含图片的内容
*
* @param word
* @param sourcePart
* @param imageFilePath
* @return
* @throws Exception
*/
public static P newImage(WordprocessingMLPackage word, Part sourcePart,
String imageFilePath) throws Exception {
BinaryPartAbstractImage imagePart = BinaryPartAbstractImage
.createImagePart(word, sourcePart, new File(imageFilePath));
Inline inline = imagePart.createImageInline(null, null, 0, 0, false,
1200);
Drawing drawing = factory.createDrawing();
drawing.getAnchorOrInline().add(inline);
R r = factory.createR();
r.getContent().add(drawing);
P p = factory.createP();
PPr pPr = new PPr();
Jc jc = new Jc();
// 单元格居中对齐
jc.setVal(JcEnumeration.CENTER);
pPr.setJc(jc);
p.setPPr(pPr);
p.getContent().add(r);
return p;
}
/**
* Method Description:使用docx4j插入图片
*
* @param templatePath
* 模板文件路径
* @param targetPath
* 生成的文件路径
* @param bookmarkName
* 书签名
* @param imagePath
* 图片路径
* @throws Exception
*/
private void insertPicture(String templatePath, String targetPath,
String bookmarkName, String imagePath) throws Exception {
InputStream templateFileIs = new FileInputStream(templatePath);
// 载入模板文件
WordprocessingMLPackage wPackage = WordprocessingMLPackage
.load(templateFileIs);
/*
// 提取正文
MainDocumentPart mainDocumentPart = wPackage.getMainDocumentPart();
Document wmlDoc = (Document) mainDocumentPart.getJaxbElement();
Body body = wmlDoc.getBody();
// 提取正文中所有段落
List<Object> paragraphs = body.getContent();
// 提取书签并创建书签的游标
RangeFinder rt = new RangeFinder("CTBookmark", "CTMarkupRange");
new TraversalUtil(paragraphs, rt);
// 遍历书签
for (CTBookmark bm : rt.getStarts()) {
// 这儿可以对单个书签进行操作,也可以用一个map对所有的书签进行处理
if (bm.getName().startsWith(bookmarkName)) {
// 读入图片并转化为字节数组,因为docx4j只能字节数组的方式插入图片
InputStream is = new FileInputStream(imagePath);
byte[] bytes = IOUtils.toByteArray(is);
// 创建一个行内图片
BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wPackage, bytes);
// createImageInline函数的前四个参数我都没有找到具体啥意思
// 最有一个是限制图片的宽度,缩放的依据
Inline inline = imagePart.createImageInline(null, null, 0, 1, false, 2400);
// 获取该书签的父级段落
P p = (P) (bm.getParent());
ObjectFactory factory = new ObjectFactory();
// R对象是匿名的复杂类型,然而我并不知道具体啥意思,估计这个要好好去看看ooxml才知道
R run = factory.createR();
// drawing理解为画布
Drawing drawing = factory.createDrawing();
drawing.getAnchorOrInline().add(inline);
run.getContent().add(drawing);
p.getContent().add(run);
}
}
*/
// 创建页脚
FooterPart footerPart = createFooter(wPackage);
// //添加图片
footerPart.getContent().add(newImage(wPackage, footerPart, imagePath));
OutputStream os = new FileOutputStream(targetPath);
wPackage.save(os);
if (os != null) {
os.close();
}
if (templateFileIs != null) {
templateFileIs.close();
}
}
}