Java tutorial
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package com.viettel.util.doc; 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.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Base64; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Random; import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.Resource; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.poi.xwpf.converter.pdf.PdfConverter; import org.apache.poi.xwpf.converter.pdf.PdfOptions; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.docx4j.XmlUtils; import org.docx4j.dml.wordprocessingDrawing.Inline; import org.docx4j.jaxb.Context; import org.docx4j.openpackaging.exceptions.Docx4JException; import org.docx4j.openpackaging.io.SaveToZipFile; import org.docx4j.openpackaging.packages.WordprocessingMLPackage; import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage; import org.docx4j.wml.ContentAccessor; import org.docx4j.wml.Drawing; import org.docx4j.wml.ObjectFactory; import org.docx4j.wml.P; import org.docx4j.wml.R; import org.docx4j.wml.Tbl; import org.docx4j.wml.Tc; import org.docx4j.wml.Text; import org.docx4j.wml.Tr; import org.springframework.context.MessageSource; /** * * @author BVN-PC */ @SuppressWarnings("deprecation") public class DocsUtility { @Resource(name = "configSource") public MessageSource configSource; WordprocessingMLPackage wordMLPackage; String pathTemp; public DocsUtility(String file, String pathTemp) { try { this.wordMLPackage = getTemplate(file); this.pathTemp = pathTemp; } catch (Docx4JException | FileNotFoundException ex) { Logger.getLogger(DocsUtility.class.getName()).log(Level.SEVERE, null, ex); } } private WordprocessingMLPackage getTemplate(String name) throws Docx4JException, FileNotFoundException { WordprocessingMLPackage template = WordprocessingMLPackage.load(new FileInputStream(new File(name))); return template; } public List<Object> getAllElementFromObject(Object obj, Class<?> toSearch) { List<Object> result = new ArrayList<>(); if (obj instanceof JAXBElement) { obj = ((JAXBElement<?>) obj).getValue(); } if (obj.getClass().equals(toSearch)) { result.add(obj); } else if (obj instanceof ContentAccessor) { List<?> children = ((ContentAccessor) obj).getContent(); children.forEach((child) -> { result.addAll(getAllElementFromObject(child, toSearch)); }); } return result; } public void replacePlaceholder(String content, String placeholder) { List<Object> texts = getAllElementFromObject(wordMLPackage.getMainDocumentPart(), Text.class); texts.stream().map((text) -> (Text) text) .filter((textElement) -> (textElement.getValue().equals(placeholder))) .forEachOrdered((textElement) -> { if (placeholder.contains("AZ_I")) { textElement.setValue(""); R parent = (R) textElement.getParent(); File file = new File(content); try { ObjectFactory factory = Context.getWmlObjectFactory(); org.docx4j.wml.Drawing drawing = factory.createDrawing(); parent.getContent().add(drawing); drawing.getAnchorOrInline().add(createInlineImage(file)); } catch (Exception ex) { Logger.getLogger(DocsUtility.class.getName()).log(Level.SEVERE, null, ex); } } else { textElement.setValue(content); } }); } public void replaceValues(HashMap<String, String> maps) { maps.forEach((t, u) -> { replacePlaceholder(u, t); }); } public void replaceParagraph(String placeholder, String textToAdd) { // 1. get the paragraph List<Object> paragraphs = getAllElementFromObject(wordMLPackage.getMainDocumentPart(), P.class); P toReplace = null; for (Object p : paragraphs) { List<Object> texts = getAllElementFromObject(p, Text.class); for (Object 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 (String ptext : as) { // 3. copy the found paragraph to keep styling correct P copy = (P) XmlUtils.deepCopy(toReplace); // replace the text elements from the copy List<?> texts = getAllElementFromObject(copy, Text.class); if (texts.size() > 0) { Text textToReplace = (Text) texts.get(0); textToReplace.setValue(ptext); } wordMLPackage.getMainDocumentPart().getContent().add(copy); } // 4. remove the original one ((ContentAccessor) toReplace.getParent()).getContent().remove(toReplace); } public void replaceTable(String[] placeholders, List<Map<String, String>> textToAdd) throws Docx4JException, JAXBException { List<Object> tables = getAllElementFromObject(wordMLPackage.getMainDocumentPart(), Tbl.class); // 1. find the table Tbl tempTable = getTemplateTable(tables, placeholders[0]); List<Object> rows = getAllElementFromObject(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); textToAdd.forEach((replacements) -> { // 2 and 3 are done in this method addRowToTable(tempTable, templateRow, replacements); }); // 4. remove the template row tempTable.getContent().remove(templateRow); } } public Tbl getTemplateTable(List<Object> tables, String templateKey) throws Docx4JException, JAXBException { for (Object tbl : tables) { List<?> textElements = getAllElementFromObject(tbl, Text.class); for (Object text : textElements) { Text textElement = (Text) text; if (textElement.getValue() != null && textElement.getValue().equals(templateKey)) { return (Tbl) tbl; } } } return null; } @SuppressWarnings("rawtypes") public void addRowToTable(Tbl reviewtable, Tr templateRow, Map<String, String> replacements) { Tr workingRow = (Tr) XmlUtils.deepCopy(templateRow); List<?> textElements = getAllElementFromObject(workingRow, Tc.class); textElements.stream().map((object) -> object).forEachOrdered((cell) -> { Tc tc = (Tc) cell; List texts = getAllElementFromObject(tc, Text.class); for (Object textObj : texts) { Text text = (Text) textObj; String replacementValue = (String) replacements.get(text.getValue()); if (text.getValue().contains("AZ_I")) { text.setValue(""); File file = new File(replacementValue); P paragraphWithImage; try { paragraphWithImage = addInlineImageToParagraph(createInlineImage(file)); tc.getContent().add(paragraphWithImage); } catch (Exception ex) { Logger.getLogger(DocsUtility.class.getName()).log(Level.SEVERE, null, ex); } } else { text.setValue(replacementValue); } } }); reviewtable.getContent().add(workingRow); } private P addInlineImageToParagraph(Inline inline) { // Now add the in-line image to a paragraph ObjectFactory factory = new ObjectFactory(); P paragraph = factory.createP(); R run = factory.createR(); paragraph.getContent().add(run); Drawing drawing = factory.createDrawing(); run.getContent().add(drawing); drawing.getAnchorOrInline().add(inline); return paragraph; } private Inline createInlineImage(File file) throws Exception { byte[] bytes = convertImageToByteArray(file); BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wordMLPackage, bytes); int docPrId = 1; int cNvPrId = 2; return imagePart.createImageInline("Filename hint", "Alternative text", docPrId, cNvPrId, false); } private byte[] convertImageToByteArray(File file) throws FileNotFoundException, IOException { InputStream is = new FileInputStream(file); long length = file.length(); // You cannot create an array using a long, it needs to be an 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; } // Ensure all the bytes have been read if (offset < bytes.length) { System.out.println("Could not completely read file " + file.getName()); } is.close(); return bytes; } /** * Create image, without specifying width * * @param wordMLPackage * @param bytes * @param filenameHint * @param altText * @param id1 * @param id2 * @return * @throws java.lang.Exception */ public org.docx4j.wml.P newImage(byte[] bytes, String filenameHint, String altText, int id1, int id2) throws Exception { BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wordMLPackage, bytes); Inline inline = imagePart.createImageInline(filenameHint, altText, id1, id2, false); // Now add the inline in w:p/w:r/w:drawing org.docx4j.wml.ObjectFactory factory = Context.getWmlObjectFactory(); org.docx4j.wml.P p = factory.createP(); org.docx4j.wml.R run = factory.createR(); p.getContent().add(run); org.docx4j.wml.Drawing drawing = factory.createDrawing(); run.getContent().add(drawing); drawing.getAnchorOrInline().add(inline); return p; } /** * Create image, specifying width in twips * * @param wordMLPackage * @param bytes * @param filenameHint * @param altText * @param id1 * @param id2 * @param cx * @return * @throws java.lang.Exception */ public P newImage(byte[] bytes, String filenameHint, String altText, int id1, int id2, long cx) throws Exception { BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wordMLPackage, bytes); Inline inline = imagePart.createImageInline(filenameHint, altText, id1, id2, cx, false); // Now add the inline in w:p/w:r/w:drawing org.docx4j.wml.ObjectFactory factory = Context.getWmlObjectFactory(); org.docx4j.wml.P p = factory.createP(); org.docx4j.wml.R run = factory.createR(); p.getContent().add(run); org.docx4j.wml.Drawing drawing = factory.createDrawing(); run.getContent().add(drawing); drawing.getAnchorOrInline().add(inline); return p; } public void saveToFile(String file) { try { SaveToZipFile saver = new SaveToZipFile(wordMLPackage); saver.save(file); } catch (Docx4JException ex) { Logger.getLogger(DocsUtility.class.getName()).log(Level.SEVERE, null, ex); } } public String saveToWord() { Random rand = new Random(); int n = rand.nextInt(1000) + 1; SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddhhmmss"); String fileName = pathTemp + sdf.format(new Date()) + n + ".docx"; File f = new File(fileName); try { wordMLPackage.save(f); return fileName; } catch (Docx4JException e) { // TODO Auto-generated catch block e.printStackTrace(); } return ""; } public String getBase64Word() throws IOException { String pathFile = saveToWord(); try (InputStream is = new FileInputStream(pathFile)) { String dataFile = Base64.getEncoder().encodeToString(IOUtils.toByteArray(is)); new File(pathFile).delete(); return dataFile; } } public String saveToPdf() throws IOException { //configSource.getMessage("path.tempFolder", null, null) String pathWord = saveToWord(); Random rand = new Random(); int n = rand.nextInt(1000) + 1; SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddhhmmss"); String fileName = pathTemp + sdf.format(new Date()) + n + ".pdf"; InputStream in = new FileInputStream(new File(pathWord)); XWPFDocument documentPdf = new XWPFDocument(in); OutputStream out = new FileOutputStream(fileName); PdfOptions options = PdfOptions.create(); PdfConverter.getInstance().convert(documentPdf, out, options); new File(pathWord).delete(); return fileName; } public String getBase64Pdf() throws IOException { String pdfFile = saveToPdf(); String base64File = ""; try (InputStream is = new FileInputStream(pdfFile)) { base64File = Base64.getEncoder().encodeToString(IOUtils.toByteArray(is)); } new File(pdfFile).delete(); return base64File; } }