diff --git a/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/project/util/WordUtil.java b/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/project/util/WordUtil.java index 60e6ce743..f6945d179 100644 --- a/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/project/util/WordUtil.java +++ b/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/project/util/WordUtil.java @@ -20,14 +20,14 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.FileCopyUtils; +import javax.xml.bind.JAXBElement; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.io.OutputStream; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class WordUtil { private static final Logger log = LoggerFactory.getLogger(WordUtil.class); @@ -118,7 +118,16 @@ public class WordUtil { table.getContent().remove(rowNum - 1); } - public static void replacePicture(WordprocessingMLPackage wordMLPackage, String bookmarkName, Object text, byte[] bytes) throws Exception { + /** + * 通过书签识别需要插入的图片位置,并替换书签对应的文本为图片 + * @param wordMLPackage + * @param bookmarkName 书签名称 + * @param text 图片前需要加的文本 + * @param bytes 图片 + * @throws Exception + * @author liyawei + */ + public static void replacePictureBM(WordprocessingMLPackage wordMLPackage, String bookmarkName, Object text, byte[] bytes) throws Exception { try { MainDocumentPart mainDocumentPart = wordMLPackage.getMainDocumentPart(); Document wmlDoc = (Document)mainDocumentPart.getJaxbElement(); @@ -147,6 +156,125 @@ public class WordUtil { } + /** + * 通过 占位符的key 识别需要插入的图片位置,并替换占位符为图片 + * @param wordMLPackage + * @param key 占位符的key ${key} + * @param text 图片前需要加的文本 + * @param bytes 图片 + * @throws Exception + */ + public static void replacePicture(WordprocessingMLPackage wordMLPackage, String key, Object text, byte[] bytes) throws Exception { + try { + MainDocumentPart mainDocumentPart = wordMLPackage.getMainDocumentPart(); + Docx4jUtils.cleanDocumentPart(mainDocumentPart); + Document wmlDoc = (Document)mainDocumentPart.getJaxbElement(); + Body body = wmlDoc.getBody(); + Iterator var8 = getAllPlaceholderElementFromObject(body).iterator(); + + while(var8.hasNext()) { + Text bm = (Text) var8.next(); + if (bm.getValue().equals("${" + key + "}")) { + BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wordMLPackage, bytes); + Inline inline = imagePart.createImageInline("", "", 0, 1, true); + ObjectFactory factory = new ObjectFactory(); + R run = factory.createR(); + Drawing drawing = factory.createDrawing(); + drawing.getAnchorOrInline().add(inline); + run.getContent().add(drawing); + replaceTextToImage(bm, text, wordMLPackage, bytes); + } + } + } catch (Exception var17) { + log.error(var17.getMessage(), var17); + } + + } + + /** + * 通过 占位符的key 识别需要插入的图片位置,并替换占位符为图片 + * 批量替换 + * @param wordMLPackage + * @param picList + * @throws Exception + */ + public static void replacePictureBatch(WordprocessingMLPackage wordMLPackage, List> picList) throws Exception { + try { + MainDocumentPart mainDocumentPart = wordMLPackage.getMainDocumentPart(); + Docx4jUtils.cleanDocumentPart(mainDocumentPart); + Document wmlDoc = (Document)mainDocumentPart.getJaxbElement(); + Body body = wmlDoc.getBody(); + List textList = getAllPlaceholderElementFromObject(body); // 获取文档中所有占位符 + + for (Map picMap :picList) { + String key = (String) picMap.get("key"); + Object text = picMap.get("text"); + byte[] bytes = (byte[]) picMap.get("bytes"); + + for(Text bm : textList) { + if (bm.getValue().equals("${" + key + "}")) { + BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wordMLPackage, bytes); + Inline inline = imagePart.createImageInline("", "", 0, 1, true); + ObjectFactory factory = new ObjectFactory(); + R run = factory.createR(); + Drawing drawing = factory.createDrawing(); + drawing.getAnchorOrInline().add(inline); + run.getContent().add(drawing); + replaceTextToImage(bm, text, wordMLPackage, bytes); + } + } + } + } catch (Exception var17) { + log.error(var17.getMessage(), var17); + } + + } + + /** + * 发现docx文档包含占位符的文本节点 + * 未解决问题:两个连着的相同占位符会识别成一个。如 原文:${key1}${key1} + * @param obj + * @return + * @author liyawei + */ + private static List getAllPlaceholderElementFromObject(Object obj) { + List result = new ArrayList<>(); + Class toSearch = Text.class; + Text textPlaceholder; + if (obj instanceof JAXBElement) { + obj = ((JAXBElement) obj).getValue(); + } + if (obj.getClass().equals(toSearch)) { + textPlaceholder = (Text) obj; + if (isPlaceholder(textPlaceholder.getValue())) { + result.add((Text) obj); + } + } else if (obj instanceof ContentAccessor) { + List children = ((ContentAccessor) obj).getContent(); + for (Object child : children) { + result.addAll(getAllPlaceholderElementFromObject(child)); + } + } + return result; + + } + + /** + * 判断字符串是否有${}占位符 + * + * @param str 需要判断的字符串 + * @return 是否字符串是否有${}占位符 + * @author liyawei + */ + private static boolean isPlaceholder(String str) { + if (str != null && !str.isEmpty()) { + Pattern pattern = Pattern.compile("([$]\\{[A-Za-z0-9./ -]+\\})"); // 识别范围 认证模块专用 + Matcher m = pattern.matcher(str); + return m.find(); + } + return false; + } + /** * 在标签处插入替换内容 * @@ -217,6 +345,72 @@ public class WordUtil { } } + + /** + * 在占位符处插入替换内容 + * + * @param bm + * @param object + * @throws Exception + * @author liyawei + */ + public static void replaceTextToImage(Text bm, Object object, WordprocessingMLPackage wordMLPackage , byte[] bytes) throws Exception { + if (wordMLPackage == null) { + return; + } + + String text = object.toString(); + try { + List theList = null; + ParaRPr rpr = null; + if (bm.getParent() instanceof P) { + PPr pprTemp = ((P) (bm.getParent())).getPPr(); + if (pprTemp == null) { + rpr = null; + } else { + rpr = ((P) (bm.getParent())).getPPr().getRPr(); + } + theList = ((ContentAccessor) (bm.getParent())).getContent(); + } else { + R r = (R) bm.getParent(); + if (r.getParent() instanceof P) { + theList = ((ContentAccessor) (r.getParent())).getContent(); + + int rangeStart = -1; // 记录占位符run位置 + int i = 0; + for (Object ox : theList) { + Object listEntry = XmlUtils.unwrap(ox); + if (listEntry.equals(r)) { + rangeStart = i; + } + i++; + } + theList.remove(rangeStart); // 移除原占位符 + + BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wordMLPackage, bytes); + Inline inline = imagePart.createImageInline("", "", 0, 1, true); + ObjectFactory factory = Context.getWmlObjectFactory(); + R run = factory.createR(); + Drawing drawing = factory.createDrawing(); + if(text != null){ + Text txt = factory.createText(); + txt.setValue(text); + run.getContent().add(txt); + } + run.getContent().add(drawing); + drawing.getAnchorOrInline().add(inline); + theList.add(rangeStart, run); // 添加图片到原占位符位置 + + } else { + return; + } + } + + } catch (ClassCastException cce) { + log.error(cce.getMessage(), cce); + } + } + public static void replaceForTemplate(String templatePath, Map map, int tableNum, List> dataList, String outPath) throws Exception { WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(new File(templatePath)); MainDocumentPart mainDocumentPart = wordMLPackage.getMainDocumentPart();