Java tutorial
/* * Copyright (c) 2018, vindell (https://github.com/vindell). * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package org.docx4j.template.utils; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.xml.bind.JAXBException; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.docx4j.XmlUtils; import org.docx4j.jaxb.Context; import org.docx4j.openpackaging.contenttype.ContentType; import org.docx4j.openpackaging.exceptions.Docx4JException; import org.docx4j.openpackaging.packages.WordprocessingMLPackage; import org.docx4j.openpackaging.parts.PartName; import org.docx4j.openpackaging.parts.WordprocessingML.AlternativeFormatInputPart; import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart; import org.docx4j.relationships.Relationship; import org.docx4j.wml.CTAltChunk; import org.docx4j.wml.ContentAccessor; import org.docx4j.wml.P; import org.docx4j.wml.Tbl; import org.docx4j.wml.Text; import org.docx4j.wml.Tr; /** * TODO * @author <a href="https://github.com/vindell">vindell</a> */ @SuppressWarnings("unchecked") public class WMLPackageUtils { protected static String CONTENT_TYPE = ""; /* * ??word?Word??template.docx?word * ??docx4j????? */ public static WordprocessingMLPackage getWMLPackageTemplate(String filepath) throws Docx4JException, FileNotFoundException { WordprocessingMLPackage template = WordprocessingMLPackage.load(new FileInputStream(new File(filepath))); return template; } public static <T> List<T> getChildrenElements(Object source, Class<T> targetClass) { List<T> result = new ArrayList<T>(); //? Object target = XmlUtils.unwrap(source); //if (target.getClass().equals(targetClass)) { if (targetClass.isAssignableFrom(target.getClass())) { result.add((T) target); } else if (target instanceof ContentAccessor) { List<?> children = ((ContentAccessor) target).getContent(); //if (children.getClass().equals(targetClass)) { if (targetClass.isAssignableFrom(children.getClass())) { result.add((T) children); } } return result; } /* * Java?Docx4J API??wordDocx4J??? * ???????JAXB * ?????????? */ public static <T> List<T> getTargetElements(Object source, Class<T> targetClass) { List<T> result = new ArrayList<T>(); //? Object target = XmlUtils.unwrap(source); //if (target.getClass().equals(targetClass)) { if (targetClass.isAssignableFrom(target.getClass())) { result.add((T) target); } else if (target instanceof ContentAccessor) { List<?> children = ((ContentAccessor) target).getContent(); for (Object child : children) { result.addAll(getTargetElements(child, targetClass)); } } return result; } /* * ?????SJ_EX1???name??? * docx4jorg.docx4j.wml.Text??????? */ public static void replacePlaceholder(WordprocessingMLPackage template, String name, String placeholder) { //?Text List<Text> texts = getTargetElements(template.getMainDocumentPart(), Text.class); //Text? for (Text text : texts) { Text textElement = (Text) text; if (textElement.getValue().equals(placeholder)) { textElement.setValue(name); } } } public static void writeDocxToStream(WordprocessingMLPackage template, String target) throws IOException, Docx4JException { File f = new File(target); template.save(f); } /* * ?? ????????????????????Text???????Docx4j?? ??? ??? ?? ??? ?? * ****************************************************************** */ public static void replaceParagraph(String placeholder, String textToAdd, WordprocessingMLPackage template, ContentAccessor addTo) { // 1. get the paragraph List<P> paragraphs = getTargetElements(template.getMainDocumentPart(), P.class); P toReplace = null; for (P p : paragraphs) { List<Text> texts = getTargetElements(p, Text.class); for (Text t : texts) { Text content = (Text) t; if (content.getValue().equals(placeholder)) { toReplace = (P) p; break; } } } // we now have the paragraph that contains our placeholder: toReplace // 2. split into seperate lines String as[] = StringUtils.splitPreserveAllTokens(textToAdd, '\n'); for (int i = 0; i < as.length; i++) { String ptext = as[i]; // 3. copy the found paragraph to keep styling correct P copy = (P) XmlUtils.deepCopy(toReplace); // replace the text elements from the copy List<?> texts = getTargetElements(copy, Text.class); if (texts.size() > 0) { Text textToReplace = (Text) texts.get(0); textToReplace.setValue(ptext); } // add the paragraph to the document addTo.getContent().add(copy); } // 4. remove the original one ((ContentAccessor) toReplace.getParent()).getContent().remove(toReplace); } /* * ?????map??addRowToTable getTemplateTable?? */ public static Tbl getTable(List<Tbl> tables, String placeholder) throws Docx4JException { for (Iterator<Tbl> iterator = tables.iterator(); iterator.hasNext();) { Tbl tbl = iterator.next(); //?table?text List<Text> textElements = getTargetElements(tbl, Text.class); for (Text text : textElements) { Text textElement = (Text) text; // if (textElement.getValue() != null && textElement.getValue().equals(placeholder)) { return (Tbl) tbl; } } } return null; } public static void replaceTable(String[] placeholders, List<Map<String, String>> textToAdd, WordprocessingMLPackage template) throws Docx4JException, JAXBException { List<Tbl> tables = getTargetElements(template.getMainDocumentPart(), Tbl.class); // 1. find the table Tbl tempTable = getTable(tables, placeholders[0]); List<Tr> rows = getTargetElements(tempTable, Tr.class); // first row is header, second row is content if (rows.size() == 2) { // this is our template row Tr templateRow = (Tr) rows.get(1); for (Map<String, String> replacements : textToAdd) { // 2 and 3 are done in this method addRowToTable(tempTable, templateRow, replacements); } // 4. remove the template row tempTable.getContent().remove(templateRow); } } public static void addRowToTable(Tbl reviewtable, Tr templateRow, Map<String, String> replacements) { Tr workingRow = (Tr) XmlUtils.deepCopy(templateRow); List<?> textElements = getTargetElements(workingRow, Text.class); for (Object object : textElements) { Text text = (Text) object; String replacementValue = (String) replacements.get(text.getValue()); if (replacementValue != null) text.setValue(replacementValue); } reviewtable.getContent().add(workingRow); } public static InputStream mergeDocx(final List<InputStream> streams) throws Docx4JException, IOException { WordprocessingMLPackage target = null; final File generated = File.createTempFile("generated", ".docx"); int chunkId = 0; Iterator<InputStream> it = streams.iterator(); while (it.hasNext()) { InputStream is = it.next(); if (is != null) { if (target == null) { // Copy first (master) document OutputStream os = new FileOutputStream(generated); os.write(IOUtils.toByteArray(is)); os.close(); target = WordprocessingMLPackage.load(generated); } else { // Attach the others (Alternative input parts) insertDocx(target.getMainDocumentPart(), IOUtils.toByteArray(is), chunkId++); } } } if (target != null) { target.save(generated); return new FileInputStream(generated); } else { return null; } } // ? private static void insertDocx(MainDocumentPart main, byte[] bytes, int chunkId) { try { AlternativeFormatInputPart afiPart = new AlternativeFormatInputPart( new PartName("/part" + chunkId + ".docx")); afiPart.setContentType(new ContentType(CONTENT_TYPE)); afiPart.setBinaryData(bytes); Relationship altChunkRel = main.addTargetPart(afiPart); CTAltChunk chunk = Context.getWmlObjectFactory().createCTAltChunk(); chunk.setId(altChunkRel.getId()); main.addObject(chunk); } catch (Exception e) { e.printStackTrace(); } } /* * ??. * @param file ?? * @return ?? * @throws FileNotFoundException * @throws IOException */ public static byte[] imageToByteArray(File file) throws FileNotFoundException, IOException { InputStream is = new FileInputStream(file); long length = file.length(); // ?long, ?int. if (length > Integer.MAX_VALUE) { System.out.println("File too large!!"); } byte[] bytes = new byte[(int) length]; int offset = 0; int numRead = 0; while (offset < bytes.length && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) { offset += numRead; } // ? if (offset < bytes.length) { System.out.println("Could not completely read file " + file.getName()); } is.close(); return bytes; } }