Java word通過html設置樣式(Spire Docx)


 

Java  word通過html設置樣式(Spire Docx)

<dependencies>
    <!-- Apache POI dependency for Word -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>5.2.3</version>
    </dependency>
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.11.0</version>
    </dependency>
    <dependency>
        <groupId>e-iceblue</groupId>
        <artifactId>spire.office.free</artifactId>
        <version>5.3.1</version>
    </dependency>
</dependencies>

 

 

<repositories>
    <repository>
        <id>com.e-iceblue</id>
        <name>e-iceblue</name>
        <url>https://repo.e-iceblue.cn/repository/maven-public/</url>
    </repository>
</repositories>

 






import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.spire.doc.*;
import com.spire.doc.documents.BorderStyle;
import com.spire.doc.documents.Paragraph;
import com.spire.doc.documents.RowAlignment;
import com.spire.doc.fields.DocPicture;
import com.spire.doc.formatting.ParagraphFormat;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Api(tags = "test")
@Slf4j
@Controller
@RequestMapping("/test")
public class HouseSalesController extends BaseController {

    //resources/templates/word
    private final String RESOURCE_WORD_URL = FileUtils.getResourceUrl("templates/word") + "/";

    private static final String POINT = " • ";
    private static final String FONT_FAMILY = "Arial";//Malgun Gothic or Gotham or Arial
    private static final int TEXT_FONT_SIZE = 8;//px
    private static final int TITLE_FONT_SIZE = 12;//px

    @PostMapping(value = "/downloadList")
    public void download(@RequestBody Param param, HttpServletRequest request, HttpServletResponse response) throws IOException, InterruptedException {

        //Word path
        final String templateFilePath = RESOURCE_WORD_URL + "test.docx";

        //destination file
        final String destinationFileName = "test_" + System.currentTimeMillis() + ".docx";
        final String destinationFilePath = RESOURCE_WORD_URL + destinationFileName;


        Map<String, String> maps = Maps.newHashMap();

        //searchkey, replaceValue
        maps.put(HouseSalesFields.TITLE.getValue(), "Viewing Schedule");
        maps.put(HouseSalesFields.NAME.getValue(), "Miss Cherry Wong");
        maps.put(HouseSalesFields.PRINT_DATE.getValue(), DateUtil.dateToString(new Date(), DateUtil.DATE_FORMAT_EN));
        maps.put(HouseSalesFields.AGENT_NAME.getValue(), "Teresa Chan");
        maps.put(HouseSalesFields.OFFICE.getValue(), "+852 28424492");
        maps.put(HouseSalesFields.MOBILE.getValue(), "+852 94037026");
        maps.put(HouseSalesFields.LICENCE_NO.getValue(), "S-269983");
        maps.put(HouseSalesFields.EMAIL.getValue(), "[email protected]");
        maps.put(HouseSalesFields.DEPARTMENT.getValue(), "Residential Sales");
        maps.put(HouseSalesFields.HOUSE_SALES_LIST.getValue(), RESOURCE_WORD_URL + "viewsheet_viewing_schedule.html");

        //Replace Word Header
        WordFileUtils.replaceWordContentDocx(templateFilePath, destinationFilePath, maps);

        Document doc = new Document(destinationFilePath);

        List<String> dataList = Lists.newArrayList();
        dataList.add("1");
        dataList.add("2");
        dataList.add("3");
        dataList.add("4");
        dataList.add("5");
        dataList.add("6");
        dataList.add("7");
        dataList.add("8");
        dataList.add("9");
        dataList.add("10");
        dataList.add("11");
        dataList.add("12");
//        dataList.add("13");

        for(int dataNum=1;dataNum<=dataList.size(); dataNum++) {
            Section sec = doc.getSections().get(0);
            Table table = sec.addTable();
            int rowsNum = 5;
            int columnsNum = 7;
            int borders = 2;
            if(dataNum == dataList.size()){
                --rowsNum;
                --borders;
            }
            if (getNextMultipleOfFour(dataNum)) {
                // 4的倍數
                if(dataNum != dataList.size()){
                    ++rowsNum;
                    ++borders;
                }
                table.resetCells(rowsNum, columnsNum);//指定嵌套表格行數、列數
            }else{
                table.resetCells(rowsNum, columnsNum);//指定嵌套表格行數、列數
            }
            //最後一行添加下邊框
            for(int i=0;i<columnsNum;i++){
                TableCell tcell = table.getRows().get(rowsNum-borders).getCells().get(i);
                tcell.getCellFormat().getBorders().getBottom().setBorderType(BorderStyle.Single);
            }
            table.setPreferredWidth(new PreferredWidth(WidthType.Percentage, (short) 100));
            table.getRows().get(0).setHeight(50f);
//            table.getRows().get(1).setHeight(10f);
            table.getRows().get(2).setHeight(38f);
            table.getRows().get(3).setHeight(30f);
            table.getTableFormat().setHorizontalAlignment(RowAlignment.Center);//設置嵌套表格在單元格中的對齊方式
            int setWidth = 300;
            table.getRows().get(rowsNum-1).getCells().get(1).setWidth(100);
            table.getRows().get(rowsNum-1).getCells().get(2).setWidth(setWidth);
            table.getRows().get(rowsNum-1).getCells().get(3).setWidth(setWidth);
            table.getRows().get(rowsNum-1).getCells().get(4).setWidth(setWidth);
            table.getRows().get(rowsNum-1).getCells().get(5).setWidth(setWidth);
//            table.getRows().get(0).getCells().get(6).setWidth(10);

            table.applyHorizontalMerge(0, 2, 4);
            table.applyHorizontalMerge(3, 2, 5);
            table.applyVerticalMerge(1,0,1);
            table.applyVerticalMerge(2,1,2);
            table.applyVerticalMerge(3,1,2);
            table.applyVerticalMerge(4,1,2);
            table.applyVerticalMerge(5,1,2);

            DocPicture picture = (DocPicture) table.getRows().get(0).getCells().get(1).addParagraph().appendPicture("D://Property Photo.png");
            picture.setHorizontalAlignment(ShapeHorizontalAlignment.Left);
            picture.setWidth(98f);
            picture.setHeight(60f);
            //填充數組內容到嵌套表格
            for (int i = 0; i < rowsNum; i++) {
                TableRow dataRow = table.getRows().get(i);
                for (int j = 0; j < columnsNum; j++) {
                    Paragraph paragraph = dataRow.getCells().get(j).addParagraph();
                    // 插入HTML內容到表格
                    if(i==0 && j==5){
                        String html = "<dev><dev style=\"font-family:" + FONT_FAMILY + ";font-size:" + TITLE_FONT_SIZE + "px;line-height:0.2px;\"><b>HKD400,000</b><br></dev>" +
                                "<dev style=\"font-family:" + FONT_FAMILY + ";font-size:" + TEXT_FONT_SIZE + "px;\">Saleable(實用)<br></dev>" +
                                "<dev style=\"font-family:" + FONT_FAMILY + ";font-size:" + TITLE_FONT_SIZE + "px;\"><b>3,461 平方尺</b><br></dev>" +
                                "<dev style=\"font-family:" + FONT_FAMILY + ";font-size:" + TEXT_FONT_SIZE + "px;\">@HKD115.57 平方尺</dev></dev>";
                        paragraph.appendHTML(html);
                    }
                    if(i==0 && j==2){
                        String html = "<dev><dev style=\"font-family:" + FONT_FAMILY + ";font-size:" + TITLE_FONT_SIZE + "px;line-height:0.2px;\"><b>34 Island Road(香島道34),House B(B)</b><br></dev>" +
                                "<dev style=\"font-family:" + FONT_FAMILY + ";font-size:" + TEXT_FONT_SIZE + "px;\">34 Island Road,34 Island Road,Deep Water Bay.Hong Kong<br>" +
                                "<dev style=\"font-family:" + FONT_FAMILY + ";font-size:" + TEXT_FONT_SIZE + "px;\">(香港南區深水灣香道道34)<br></dev>";
                        paragraph.appendHTML(html);
                    }
                    if(i==1 && j==2){
                        String html = "<dev><dev style=\"font-family:" + FONT_FAMILY + ";font-size:" + TEXT_FONT_SIZE + "px;line-height:0.2px;\"><b>ROOM DETAILS </b>房間詳情<br>" +
                                "房間詳情內容<br>" +
                                "房間詳情內容<br>" +
                                "房間詳情內容" +
                                "</dev>";
                        paragraph.appendHTML(html);
                    }
                    if(i==1 && j==3){
                        String html = "<dev><dev style=\"font-family:" + FONT_FAMILY + ";font-size:" + TEXT_FONT_SIZE + "px;line-height:0.2px;\"><b>KEY FEATURES </b>主要特色<br>" +
                                POINT + "主要特色內容<br>" +
                                POINT + "主要特色內容<br>" +
                                POINT + "主要特色內容<br>" +
                                "</dev>";
                        paragraph.appendHTML(html);
                    }
                    if(i==1 && j==4){
                        String html = "<dev><dev style=\"font-family:" + FONT_FAMILY + ";font-size:" + TEXT_FONT_SIZE + "px;line-height:0.2px;\"><br>" +
                                POINT + "內容<br>" +
                                POINT + "內容<br>" +
                                POINT + "內容" +
                                "</dev>";
                        paragraph.appendHTML(html);
                    }
                    if(i==1 && j==5){
                        String html = "<dev><dev style=\"font-family:" + FONT_FAMILY + ";font-size:" + TEXT_FONT_SIZE + "px;line-height:0.2px;\"><b>PROPERTY DETAIL </b>物業詳情<br>" +
                                "Govt Rate 差餉:全包<br>" +
                                "Mgmt Fee 管理費:全包<br>" +
                                "Possession Type Vacant 交吉" +
                                "</dev>";
                        paragraph.appendHTML(html);
                    }
                    if(i==2 && j==1){
                        paragraph.appendHTML("<dev style=\"font-family:" + FONT_FAMILY + ";font-size:" + TEXT_FONT_SIZE + "px;\">Listing ID 參考編號:<br>2023313714</dev>");
                    }
                    if(i==3 && j==1){
                        paragraph.appendHTML("<dev style=\"font-family:" + FONT_FAMILY + ";font-size:" + TEXT_FONT_SIZE + "px;background-color:#c90c0f;color:#FFFFFF\">&nbsp;Lead Agent 首席代理&nbsp;</dev>");
                    }
                    if(i==3 && j==2){
                        String html = "<dev><dev style=\"font-family:" + FONT_FAMILY + ";font-size:" + TEXT_FONT_SIZE + "px;\"><b>REMARK </b>評論<br>" +
                                "" +
                                "</dev>";
                        paragraph.appendHTML(html);
                    }

                    ParagraphFormat format = paragraph.getFormat();
                    format.setLineSpacingRule(LineSpacingRule.Exactly);
                    format.setLineSpacing(10f);
                }

            }

        }

        //保存文檔
        doc.saveToFile(destinationFilePath,FileFormat.Docx);

        //download file
        File destinationFile = new File(destinationFilePath);
        FileUtils.downLoadFile(response, destinationFileName, destinationFile);

        //Check file is exists.
        if (destinationFile.exists()) {
            //File delete.
            boolean isDeleted = destinationFile.delete();
            if (isDeleted) {
                log.info("Delete word file done" + destinationFilePath);
            } else {
                log.info("Delete word file failed" + destinationFilePath);
            }
        } else {
            log.info("Delete word file is not exists" + destinationFilePath);
        }

    }
}

 

 

public static void downLoadFile(HttpServletResponse response, String fileName, File file) throws IOException {

    //文件下載
    //設置兩個響應頭文件
    //給瀏覽器設置響應頭:Content-Disposition   告訴瀏覽器以附件的形式打開這個文件
    response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
    //給瀏覽器設置響應頭:文件類型    response.setContentType(mimetype);
    //獲取文件的mimeType
    response.setContentType(new MimetypesFileTypeMap().getContentType(file));
    //3.設置兩個流,進行流拷貝操作
    //讀取文件資源
    FileInputStream fileInputStream = new FileInputStream(file);
    //response中獲取輸出流
    ServletOutputStream outputStream = response.getOutputStream();
    //流拷貝
    int len = 0;
    byte[] arr = new byte[1024];

    while ((len = fileInputStream.read(arr)) != -1) {
        outputStream.write(arr, 0, len);

    }
    //隨着response關閉
    fileInputStream.close();
    outputStream.close();
}
public static void replaceWordContentDocx(String templateFilePath, String destinationFilePath, Map<String, String> replaceMaps) throws IOException{

    //is exists?
    File templateFile = new File(templateFilePath);
    if(!templateFile.exists()){
        log.error("The " + templateFilePath + " template is not exists.");
    }

    //copy
    copyWord(templateFilePath, destinationFilePath);

    //set data
    for(String searchKey : replaceMaps.keySet()){
        replaceText(destinationFilePath, searchKey, replaceMaps.get(searchKey));
    }

    log.info("replaceWordContentForDoc ===== Done =====");
}

 


 
import org.apache.poi.xwpf.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;

/**
 * @Author Robert
 * @Date 2024/4/7 11:55
 * @Version 1.0
 * @Param 
 * @return 
 */

public class WordFileUtils {
    private static final Logger log = LoggerFactory.getLogger(ListingServiceImpl.class);

    public static void replaceWordContentDocxUnderline(String templateFilePath, String destinationFilePath, Map<String, String> replaceMaps) throws IOException{

        //is exists?
        File templateFile = new File(templateFilePath);
        if(!templateFile.exists()){
            log.error("The " + templateFilePath + " template is not exists.");
        }

        //copy
        copyWord(templateFilePath, destinationFilePath);

        //set data
        for(String searchKey : replaceMaps.keySet()){
            replaceTextUnderline(destinationFilePath, searchKey, replaceMaps.get(searchKey));
        }

        log.info("replaceWordContentForDoc ===== Done =====");
    }

    public static void replaceWordContentDocx(String templateFilePath, String destinationFilePath, Map<String, String> replaceMaps) throws IOException{

        //is exists?
        File templateFile = new File(templateFilePath);
        if(!templateFile.exists()){
            log.error("The " + templateFilePath + " template is not exists.");
        }

        //copy
        copyWord(templateFilePath, destinationFilePath);

        //set data
        for(String searchKey : replaceMaps.keySet()){
            replaceText(destinationFilePath, searchKey, replaceMaps.get(searchKey));
        }

        log.info("replaceWordContentForDoc ===== Done =====");
    }

    public static void copyWord(String templateFilePath, String destinationFilePath){
        try (InputStream in = new FileInputStream(templateFilePath);
             XWPFDocument document = new XWPFDocument(in);
             OutputStream out = new FileOutputStream(destinationFilePath)) {

            document.write(out);
            out.close();
            in.close();
            log.info("Word copy Done");
        } catch (IOException e) {
            log.info("Word copy Faild" + e.getMessage());
            e.printStackTrace();
        }
    }

    public static void replaceTextUnderline(String filePath, String textToFind, String textToReplace) throws IOException {
        FileInputStream fis = new FileInputStream(filePath);
        XWPFDocument document = new XWPFDocument(fis);
        // 遍歷文檔中的段落並替換文本
        for (XWPFParagraph para : document.getParagraphs()) {
            replaceInParaUnderline(para, textToFind, textToReplace);
        }
        // 遍歷文檔中的表格
        for (XWPFTable table : document.getTables()) {
            for (XWPFTableRow row : table.getRows()) {
                for (XWPFTableCell cell : row.getTableCells()) {
                    for (XWPFParagraph para : cell.getParagraphs()) {
                        replaceInPara(para, textToFind, textToReplace);
                    }
                }
            }
        }
        // 關閉輸入流並寫入新內容到文件
        fis.close();
        FileOutputStream fos = new FileOutputStream(filePath);
        document.write(fos);
        fos.close();
    }

    public static void replaceText(String filePath, String textToFind, String textToReplace) throws IOException {
        FileInputStream fis = new FileInputStream(filePath);
        XWPFDocument document = new XWPFDocument(fis);
        // 遍歷文檔中的段落並替換文本
        for (XWPFParagraph para : document.getParagraphs()) {

            replaceInPara(para, textToFind, textToReplace);

            replaceInParaHeader(document, textToFind, textToReplace);

        }
        // 遍歷文檔中的表格
        for (XWPFTable table : document.getTables()) {
            for (XWPFTableRow row : table.getRows()) {
                for (XWPFTableCell cell : row.getTableCells()) {
                    for (XWPFParagraph para : cell.getParagraphs()) {
                        replaceInPara(para, textToFind, textToReplace);
                    }
                }
            }
        }
        // 關閉輸入流並寫入新內容到文件
        fis.close();
        FileOutputStream fos = new FileOutputStream(filePath);
        document.write(fos);
        fos.close();
    }
    private static void replaceInPara(XWPFParagraph para, String textToFind, String textToReplace) {
        for (XWPFRun run : para.getRuns()) {
            String text = run.getText(run.getTextPosition());
            String textToFindEscape = notEmpty(textToFind) && textToFind.contains("\\") ? textToFind.replace("\\","") : textToFind;
            if (text != null && text.contains(textToFindEscape) && textToReplace != null && textToReplace != null) {
                log.info("replaceInPara:text=" + text + "|textToFind="+textToFind + "|textToReplace=" + textToReplace);
                text = text.replaceAll(textToFind, textToReplace);
                run.setText(text, 0);
            }
        }
    }
    private static void replaceInParaUnderline(XWPFParagraph para, String textToFind, String textToReplace) {
        for (XWPFRun run : para.getRuns()) {
            String text = run.getText(run.getTextPosition());
            String textToFindEscape = notEmpty(textToFind) && textToFind.contains("\\") ? textToFind.replace("\\","") : textToFind;
            if (text != null && text.contains(textToFindEscape) && textToReplace != null && textToReplace != null) {
                log.info("replaceInParaUnderline:text=" + text + "|textToFind="+textToFind + "|textToReplace=" + textToReplace);
                text = text.replaceAll(textToFind, textToReplace);
                run.setText(text, 0);
                run.setUnderline(UnderlinePatterns.SINGLE);
            }
        }
    }
    private static void replaceInParaHeader(XWPFDocument document, String textToFind, String textToReplace) {
        List<XWPFHeader> headers = document.getHeaderList();

        // 遍歷每個段落
        for (XWPFHeader header : headers) {
            List<XWPFParagraph> paragraphs = header.getParagraphs();
            for(XWPFParagraph paragraph:paragraphs){
                replaceInPara(paragraph, textToFind, textToReplace);
                // 遍歷所有段落,找到表格
                for (IBodyElement element : header.getBodyElements()) {
                    if (element instanceof XWPFTable) {
                        XWPFTable table = (XWPFTable) element;

                        for (XWPFTableRow row : table.getRows()) {
                            for (XWPFTableCell cell : row.getTableCells()) {
                                for (XWPFParagraph para : cell.getParagraphs()) {
                                    replaceInPara(para, textToFind, textToReplace);
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    public static Boolean getNextMultipleOfFour(int number) {
        // 使用%運算符找到餘數,然後通過加上足夠的4的倍數來獲取下一個4的倍數

        int remainder = number % 4;
        if (remainder == 0 && number != 0) {
            // 如果本身就是4的倍數,則直接返回
            return true;
        } else {
            // 不是4的倍數,則加上足夠的4的倍數
            return false;
        }
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章