简体   繁体   English

将特定单词后路径中的图像添加到 MS Word

[英]Add images from the path after specific word to MS Word

I need to insert each images from the path after each specific word.我需要在每个特定单词之后插入路径中的每个图像。 I don't know what is wrong, and why this code doesn't work.我不知道出了什么问题,也不知道为什么这段代码不起作用。 this code runs with success but the images does not added to the document.此代码成功运行,但图像未添加到文档中。

Here is my code.这是我的代码。 ` `

public class ImageWord {
    public static void main(String[] args) throws Exception {
        // Open the MS Office document
        XWPFDocument doc = new XWPFDocument(new FileInputStream("C:\\test\\image.doc"));

        // Iterate through the paragraphs in the document
        List<XWPFParagraph> paragraphs = doc.getParagraphs();
        int imageCounter = 0;
        File[] images = new File("C:\\Users\\Screenshots\\").listFiles();
        for (XWPFParagraph paragraph : paragraphs) {
            // Iterate through the runs in the paragraph
            List<XWPFRun> runs = paragraph.getRuns();
            for (XWPFRun run : runs) {
                // Check if the run contains the word we want to insert the image after
                String text = run.getText(0);
                if (text != null && text.contains("word")) {
                    // Create a new run for the image
                    XWPFRun imageRun = paragraph.insertNewRun(runs.indexOf(run) + 1);

                    // Add the image to the run
                    String imgFile = images[imageCounter].getAbsolutePath();
                    imageRun.addPicture(new FileInputStream(imgFile), XWPFDocument.PICTURE_TYPE_PNG, imgFile, 200, 200);
                    imageCounter++;
                    if (imageCounter >= images.length) {
                        imageCounter = 0;
                    }
                    // Add a line break after the image
                    imageRun.addBreak();
                }
            }
        }
        FileOutputStream out = new FileOutputStream("C:\\test\\images.doc");
        doc.write(out);
        out.close();
    }
}

Your code你的代码

imageRun.addPicture(new FileInputStream(imgFile), XWPFDocument.PICTURE_TYPE_PNG, imgFile, 200, 200);

adds a picture to the XWPFRun which is 200 EMU width and 200 EMU high.XWPFRun添加一张图片,宽度为 200 EMU,高度为 200 EMU。

What is EMU?什么是动车组? See: http://polymathprogrammer.com/2009/10/22/english-metric-units-and-open-xml/ and https://en.wikipedia.org/wiki/Office_Open_XML_file_formats#DrawingML请参阅: http://polymathprogrammer.com/2009/10/22/english-metric-units-and-open-xml/https://en.wikipedia.org/wiki/Office_Open_XML_file_formats#DrawingML

A DrawingML graphic's dimensions are specified in English Metric Units (EMUs). DrawingML 图形的尺寸以英制单位 (EMU) 指定。 It is so called because it allows an exact common representation of dimensions originally in either English or Metric units—defined as 1/360,000 of a centimeter, and thus there are 914,400 EMUs per inch, and 12,700 EMUs per point, to prevent round-off in calculations.之所以这样命名,是因为它允许最初以英制或公制单位精确通用表示尺寸——定义为 1/360,000 厘米,因此每英寸有 914,400 个 EMU,每点有 12,700 个 EMU,以防止四舍五入在计算中。

So your added picture is very small.所以你添加的图片很小 It is not even a pixel (or a point) width and high.它甚至不是一个像素(或一个点)的宽度和高度。 So it is not visible.所以它是不可见的。

As documented in XWPFRun.addPicture :XWPFRun.addPicture中所述:

public XWPFPicture addPicture... public XWPFPicture addPicture...

Adds a picture to the run.将图片添加到运行中。 This method handles attaching the picture data to the overall file.此方法处理将图片数据附加到整个文件。

Parameters: ...参数: ...

width - width in EMUs. width - 动车组的宽度。 To convert to / from points use Units要转换为/从点使用单位

height - height in EMUs. height - EMU 中的高度。 To convert to / from points use Units要转换为/从点使用单位

So try using:所以尝试使用:

imageRun.addPicture(new FileInputStream(imgFile), XWPFDocument.PICTURE_TYPE_PNG, imgFile, Units.pixelToEMU(200), Units.pixelToEMU(200));

if the 200 means pixel.如果 200 表示像素。

Or或者

imageRun.addPicture(new FileInputStream(imgFile), XWPFDocument.PICTURE_TYPE_PNG, imgFile, Units.toEMU(200), Units.toEMU(200));

if the 200 means points.如果200意味着积分。


The above is one problem.以上是一个问题。 But seeing your code I doubt it is the only one.但是看到你的代码我怀疑它是唯一的。

The code line for (XWPFRun run: runs) { should throw java.util.ConcurrentModificationException when the code in if (text.= null && text.contains("word")) {...} gets reached.当达到if (text.= null && text.contains("word")) {...}中的代码时for (XWPFRun run: runs) {的代码行应该抛出java.util.ConcurrentModificationException XWPFRun run: runs internally uses an Iterator which gets damaged if paragraph.insertNewRun inserts a new XWPFRun in paragraph . XWPFRun run: runs内部运行使用迭代器,如果paragraph.insertNewRunparagraph中插入新的 XWPFRun,该Iterator会损坏。 So if there is no error, then text.contains("word") never gets true.因此,如果没有错误,则text.contains("word")永远不会为真。 Try debugging:尝试调试:

...
                String text = run.getText(0);
                System.out.println(text);
                if (text != null && text.contains("word")) {
                    System.out.println(text + " contains word");
...

Is there a run which contains "word"?是否有包含“单词”的运行?

To avoid the java.util.ConcurrentModificationException do using:要避免java.util.ConcurrentModificationException ,请使用:

...
            //for (XWPFRun run : runs) {
            for (int r = 0; r < runs.size(); r++) {
                XWPFRun run = runs.get(r);
                // Check if the run contains the word we want to insert the image after
                String text = run.getText(0);
                System.out.println(text);
                if (text != null && text.contains("word")) {
                    System.out.println(text + " contains word");
                    // Create a new run for the image
                    XWPFRun imageRun = paragraph.insertNewRun(runs.indexOf(run) + 1);
 
                    // Add the image to the run
                    String imgFile = images[imageCounter].getAbsolutePath();
                    //imageRun.addPicture(new FileInputStream(imgFile), XWPFDocument.PICTURE_TYPE_PNG, imgFile, 200, 200);
                    imageRun.addPicture(new FileInputStream(imgFile), XWPFDocument.PICTURE_TYPE_PNG, imgFile, Units.pixelToEMU(200), Units.pixelToEMU(200));
                    imageCounter++;
                    if (imageCounter >= images.length) {
                        imageCounter = 0;
                    }
                    // Add a line break after the image
                    imageRun.addBreak();
                }
            }
...

If (text.= null && text.contains("word")) never gets true, then it might be that no stored text run in the Word document fully contains the text "word".如果(text.= null && text.contains("word"))永远不会为真,则可能是在 Word 文档中运行的存储文本中没有完全包含文本“word”。 Word is very special in splitting text in text runs. Word 在文本运行中拆分文本非常特殊。 Not only formatting leads to split text runs.不仅格式化会导致拆分文本运行。 Also spell checker splits text in different text runs to mark errors.拼写检查器还会拆分不同文本运行中的文本以标记错误。 And sometimes Word is just crazy in how it splits text in text runs.有时 Word 在文本运行中拆分文本的方式非常疯狂。 So it can be that the text "word" is stored so: <r>w</r<r>ord</r> .因此,文本“word”可能是这样存储的: <r>w</r<r>ord</r>

To overcome those issues, TextSegment was introduced in Apache POI.为了克服这些问题,在Apache POI 中引入了 TextSegment。 It can be got via XWPFParagraph.searchText .它可以通过XWPFParagraph.searchText获得。

Using this, following code should be a better working version of your code sample:使用这个,下面的代码应该是你的代码示例的更好的工作版本:

import java.io.*;

import org.apache.poi.xwpf.usermodel.*;
import org.apache.poi.util.Units;

import java.util.List;

public class ImageWord {

    public static void main(String[] args) throws Exception {
 
         // Open the MS Office document
        XWPFDocument doc = new XWPFDocument(new FileInputStream("./image.docx"));

        List<XWPFParagraph> paragraphs = doc.getParagraphs();
        int imageCounter = 0;
        File[] images = new File("./images/").listFiles();
        String textToFind = "word";
        
        // Iterate through the paragraphs in the document
        for (XWPFParagraph paragraph : paragraphs) {
            TextSegment foundTextSegment = null;
            PositionInParagraph startPos = new PositionInParagraph(0, 0, 0);
            // Search all text segments having text to find
            while((foundTextSegment = paragraph.searchText(textToFind, startPos)) != null) {
                List<XWPFRun> runs = paragraph.getRuns();
                XWPFRun endRun = runs.get(foundTextSegment.getEndRun());

                System.out.println("Run " + endRun + " contains " + textToFind);
                
                // Create a new run for the image
                XWPFRun imageRun = paragraph.insertNewRun(runs.indexOf(endRun) + 1);
                runs = paragraph.getRuns();
                // Add the image to the run
                String imgFile = images[imageCounter].getAbsolutePath();
                imageRun.addPicture(new FileInputStream(imgFile), XWPFDocument.PICTURE_TYPE_PNG, imgFile, Units.pixelToEMU(200), Units.pixelToEMU(200));
                imageCounter++;
                if (imageCounter >= images.length) {
                    imageCounter = 0;
                }
                // Add a line break after the image
                imageRun.addBreak();
                // Get the next start position for search after new inserted image run
                startPos = new PositionInParagraph(runs.indexOf(imageRun), 0, 0);
            }
        }
        
        FileOutputStream out = new FileOutputStream("./images.docx");
        doc.write(out);
        out.close();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM