background

Before some revising labeling requirements, at the time of export question bank hope can look at the word is derived, by the way, convenient offline preview effect of finished product, because it was just used to preview and in order to continue to use the style of the front end, the plan is to directly generate HTML, write a word file header, so that you can use word to open view, file header is as follows:

<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
</html>
Copy the code

However, such word has a fatal defect (the client machine must be connected to the Internet, otherwise the pictures in Word cannot be loaded). Moreover, with the development of business, the client wants to import the exported Word into the system again, and this HTML format cannot be recognized normally. I need to export word in standard format and incidentally I want the latex formulas in annotations to be editable in Word

Common Word export schemes

  • Apache POI
  • The FreeMark template engine generates documents in XML format
  • Aspose Word (Commercial payment)
  • Spire.doc (commercial and free)

AsposePDF for JAVA supports Latex formulas from V19.4. To use Apache POI, we basically convert Latex into mathMl and then write it into Word. We need to use two JAR packages of Fmath. I found some online, but didn’t find any formal channels, so I first passed. FreeMark writes also use fmath, requiring latex to be converted into MathML and written into word’s XML template, but the engine called for the secondary processing does not support XML-encoded Word, so this solution also passes

Export Word that supports editing latex formulas using spire.doc

Rely on

<dependency>
    <groupId>e-iceblue</groupId>
    <artifactId>spire.doc.free</artifactId>
    <version>3.9.0</version>
</dependency>
Copy the code

Create the Document object and Section

Document document = new Document();
Section section = document.addSection();
Copy the code

Create a paragraph and set the front and back margins

Paragraph paragraph = section.addParagraph();
paragraph.getFormat().setLineSpacing(15);
paragraph.getFormat().setBeforeSpacing(20);
Copy the code

Write text and set Chinese and English fonts

TextRange textRange = paragraph.appendText(text);
textRange.getCharacterFormat().setFontNameFarEast("宋体");
textRange.getCharacterFormat().setFontNameNonFarEast("Times New Roman");
Copy the code

Write the latex formula

OfficeMath math = new OfficeMath(paragraph.getDocument());
paragraph.getItems().add(math);
math.fromLatexMathCode(latexFormat(innerPojo.latex));

/** * Spire. Doc has some defects. It does not support symbols very well, such as greater than or equal to less than or equal to. Spire.doc does not support rendering with Latex formulas in Chinese, so the version may be too low to render properly and display images directly */
private String latexFormat(String latex) {
    if (latex.contains("leqslant")) {
        latex = latex.replace("leqslant"."leq");
    }
    if (latex.contains("geqslant")) {
        latex = latex.replace("geqslant"."geq");
    }
    StringBuilder latexBuilder = new StringBuilder();
    boolean isChinese = false;
    String regexStr = "[\u4E00-\u9FA5]";
    for (Character c : latex.toCharArray()) {
        Matcher chineseMatch = Pattern.compile(regexStr).matcher(c.toString());
        if (chineseMatch.find()) {
            if (isChinese) {
                latexBuilder.append(c);
            } else {
                latexBuilder.append("\\mbox{").append(c);
                isChinese = true;
            }
            continue;
        } else {
            if (isChinese) {
                isChinese = false;
                latexBuilder.append("}"); } latexBuilder.append(c); }}return latexBuilder.toString();
}
Copy the code

In spire.doc, you can’t add a table to a paragraph directly. You need to add a text box first, and then add the table inside the text box

TextBox textBox = paragraph.appendTextBox(500.20 * innerPojo.rows);
textBox.getFormat().setHorizontalAlignment(ShapeHorizontalAlignment.Inside);
textBox.getFormat().setNoLine(true);
Table table = textBox.getBody().addTable(true);
table.resetCells(innerPojo.rows, innerPojo.lines);
for (int i = 0; i < innerPojo.rowLines.size(); i++) {
    List<String> rowLine = innerPojo.rowLines.get(i);
    for (int j = 0; j < rowLine.size(); j++) { appendWithFont(rowLine.get(j), table.get(i, j).addParagraph()); }}// Set the text box style to embed type
textBox.setTextWrappingStyle(TextWrappingStyle.Inline);
Copy the code

This version of the API search, did not find a way to make the height of the text box adaptive, perhaps the paid version will be much better

Insert the picture to control the width of the picture should not exceed 500 and the height should not exceed 300

DocPicture picture = paragraph.appendPicture(innerPojo.getImage());
log.info("pictureSize,Width:{},Height:{}", picture.getWidth(), picture.getHeight());
if (picture.getWidth() > 500) {
    BigDecimal rate = BigDecimal.valueOf(500).divide(BigDecimal.valueOf(picture.getWidth()), 8, BigDecimal.ROUND_DOWN);
    picture.setHeight(picture.getHeight() * rate.floatValue());
    picture.setWidth(500);
} else if (picture.getHeight() > 300) {
    BigDecimal rate = BigDecimal.valueOf(300).divide(BigDecimal.valueOf(picture.getHeight()), 8, BigDecimal.ROUND_DOWN);
    picture.setWidth(picture.getWidth() * rate.floatValue());
    picture.setHeight(300);
}
Copy the code

The export effect is shown as follows:

Later, I will try the formula derivation of POI method

Refer to the connection

www.e-iceblue.cn/spiredocfor…