產品期望實現【公文管理】其中發文擬文一塊內容,用戶上傳正文(word),再選擇不同套紅模板,最后拼接為一個對外發文,的公文格式。
基于上次使用vue實現在線編輯功能,產品不太滿意,重新學習java如何操作word文檔,之前地址:(vue使用Tinymce富文本模擬在線word文檔)juejin.cn/post/723665…
有兩個文件test1.docx (作為紅頭模板)和test2.docx(作為正文);期望實現效果:用戶選擇紅頭模板加上自己寫的正文內容,最終生成可編輯的word文檔。
create_table.docx 合并之后最終效果“
test1.docx 紅頭模板:
test2.docx 正文(用戶撰寫上傳的內容):
如標題所示,最終采用Apache POI來實現這個功能主要原因:
主要是對于我這種初學者來說是非常友好的,太復雜玩不轉。Apache POI 的使用非常簡單,只需添加它的 jar 包到項目中,并調用相應的 API 即可實現文檔讀寫。同時,Apache POI 提供了豐富的文檔和官方網站上的文檔也很詳細。
Apache POI,分別為 Word、Excel、PowerPoint 等各種格式提供不同的類方法,我們需要操作Word文檔的功能,所以使用(Java API for Microsoft Documents)中的XWPFDocument類,實現文檔合并功能。
整理不同格式文檔操作類
注意:word文檔目前有兩種不同格式,一種是以doc結尾的,另一種以docx結尾,本次功能主要講解docx格式文檔操作,doc格式文檔調用的類和函數HWPF開頭。
兩者區別:doc是Word2007及以下版的文件擴展名,而docx是Word2007及以上版本的文件擴展名,docx版本兼容性較高,而且比doc文件所占用空間更小。
在pom.xml文件中引入maven依賴,
<!-- WordToHtml .doc .odcx poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>4.1.2</version>
</dependency>
<!-- 操作excel的庫 注意版本保持一致 poi poi-ooxml poi-scratchpad -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
<!--poi-ooxml和*poi-ooxml-schemas*是poi對2007及以上版本的擴充。-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>4.1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
簡化整體流程,創建兩個word文件test1.docx和test2.docx。將下列file對應的文件路徑換成自己創建的文件路徑創,建單個java文件(帶main),直接運行main方法輸出creat_table.docx文件。 先上代碼,再進行講解:
package org.ssssssss.magicboot;
import org.apache.poi.xwpf.usermodel.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.List;
public class WordDocumentTest {
public static void main(String[] args) throws Exception
{
//獲取文件轉io流
File file1 = new File("D:/IDM/test1.docx");
File file2 = new File("D:/IDM/test2.docx");
FileInputStream fis1 = new FileInputStream(file1);
FileInputStream fis2 = new FileInputStream(file2);
//最終文件輸出的路徑
FileOutputStream out = new FileOutputStream(new File("D:/IDM/create_table.docx"));
//轉為word文檔元素
XWPFDocument dcx1 = new XWPFDocument(fis1);
XWPFDocument dcx2 = new XWPFDocument(fis2);
//創建一個新的文檔
XWPFDocument document= new XWPFDocument();
//將第一個文檔元素復制新創建的文檔中;
document = dcx1;
//換行 document.createParagraph().createRun().addBreak();
//將第二個docx內容添加到新創建的文檔中
mergeParagraphs(dcx2.getParagraphs(), document);
//結束關閉io流
document.write(out);
out.close();
fis1.close();
fis2.close();
System.out.println("create_table document written success.");
}
// 合并文本段落
private static void mergeParagraphs(List<XWPFParagraph> paragraphs, XWPFDocument outDoc) {
for (XWPFParagraph para : paragraphs) {
XWPFParagraph newPara = outDoc.createParagraph();
newPara.getCTP().setPPr(para.getCTP().getPPr());
//判斷是否是文本、段落、圖片 //.getRPr() para.tables !=null ,iruns 獲取圖片
for (XWPFRun run : para.getRuns()) {
XWPFRun newRun = newPara.createRun();
newRun.getCTR().setRPr(run.getCTR().getRPr());
newRun.setText(run.getText(0));
}
}
}
實現流程主要看代碼中的注釋,包含以下幾個步驟
核心重點將第二個docx內容添加到新創建的文檔中封裝mergeParagraphs方法,在這個方法中傳入了兩個參數(List paragraphs, XWPFDocument outDoc) 其中List<XWPFParagraph> paragraphs = dcx2.getParagraphs() 意思是將dcx2文檔所有段落取出來用一個數組存放,再進行循環段落;通過XWPFParagraph newPara = outDoc.createParagraph();給新的文檔創建一個新的段落;給新的段落添加對應的樣式newPara.getCTP().setPPr(para.getCTP().getPPr());最后由于段落中會劃分不同的XWPFRun再進行循環設置文本的字體、大小、顏色、加粗、斜體、下劃線等格式。 官方api介紹
剛才對XWPFRun沒有進行很好的解釋,這里重新舉例說明下,例如以下標紅的段落
按照正常理解這一個段落內容應該是一個東西,其實在XWPF中會劃分為不同的XWPFRun,使用idea打斷點查看數據
可以看出它將一段文字劃分為不同模塊,為什么會這樣,在一段文字中也存在不同的區別,例如文字的字體,像下圖中“根據”“2023”屬于不同的字體,所以會劃分為不同的XWPFRun,理解這個概念后同理明白為什么一個段落會劃分為29模塊
在前面其實已經實現第一個模塊最終效果的docx文檔合并的功能,所以在這個模塊講解在實現這個過程中記錄有意思的內容。
接著上面講XWPFRun這個函數,XWPFRun用于在 Word 文檔中添加或修改單個本 Run 或 Run 中的文字格式。它是文本段落(XWPFParagraph)中的最小單元,用于精細控制文本的格式和樣式。可以使用 XWPFRun 類的各種方法來設置文本的字體、大小、顏色、加粗、斜體、下劃線等格式。 下列是在使用過程中記錄的一些屬性,以及這些屬性對應能夠設置的格式注釋。
XWPFRun run = firstParagraph.createRun();
XWPFRun tempRun = xwpfRuns.get(i);
//默認:宋體(wps)/等線(office2016) 5號 兩端對齊 單倍間距
run.setText(tempRun.text());
//加粗
run.setBold(tempRun.isBold());
//我也不知道這個屬性做啥的
run.setCapitalized(tempRun.isCapitalized());
//設置顏色--十六進制
run.setColor(tempRun.getColor());
//這個屬性報錯
run.setCharacterSpacing(tempRun.getCharacterSpacing());
//浮雕字體----效果和印記(懸浮陰影)類似
run.setEmbossed(tempRun.isEmbossed());
//雙刪除線
run.setDoubleStrikethrough(tempRun.isDoubleStrikeThrough());
run.setEmphasisMark(tempRun.getEmphasisMark().toString());
//字體,//字體,范圍----效果不詳
run.setFontFamily(tempRun.getFontFamily());
//字體大小,沒有設置默認是-1,
if(tempRun.getFontSize() != -1){
run.setFontSize(tempRun.getFontSize());
}
//印跡(懸浮陰影)---效果和浮雕類似
run.setImprinted(tempRun.isImprinted());
//斜體(字體傾斜)
run.setItalic(tempRun.isItalic());
//字距調整----這個好像沒有效果
run.setKerning(tempRun.getKerning());
//陰影---稍微有點效果(陰影不明顯)
run.setShadow(tempRun.isShadowed());
//小型股------效果不清楚
run.setSmallCaps(tempRun.isSmallCaps());
//單刪除線(廢棄)
run.setStrike(tempRun.isStrike());
//單刪除線(新的替換Strike)
run.setStrikeThrough(tempRun.isStrikeThrough());
//下標(吧當前這個run變成下標)---枚舉
run.setSubscript(tempRun.getSubscript());
//設置兩行之間的行間距
run.setTextPosition(tempRun.getTextPosition());
//各種類型的下劃線(枚舉)
run.setUnderline(tempRun.getUnderline());
run.setVerticalAlignment(tempRun.getVerticalAlignment().toString());
run.setVanish(tempRun.isVanish());
run.setUnderlineThemeColor(tempRun.getUnderlineColor());
run.setUnderlineColor(tempRun.getUnderlineColor());
run.setTextScale(tempRun.getTextScale());
run.setTextPosition(tempRun.getTextPosition());
run.setTextHighlightColor(tempRun.getTextHightlightColor().toString());
// run.setStyle(tempRun.gets); 沒找到這個屬性
run.setLang(tempRun.getLang());
XWPFParagraph 是 Apache POI 庫中 XWPF 模塊的一部分,用于創建或修改 Word 文檔中的段落。它可以添加不同的文本格式,并且可以添加圖片、表格、超鏈接等內容。XWPFParagraph 類可以控制段落的樣式和格式,包括字體、字號、行距、首行縮進、對齊方式等。可以使用 XWPFParagraph 類的各種方法來設置段落的格式和樣式。
常用方法:
//創建一個新的 XWPFRun 對象,用于在段落中添加文本或修改文本格式。
createRun()
//設置段落的對齊方式,align 參數可以是 LEFT、CENTER、RIGHT、JUSTIFY 等值。
setAlignment(ParagraphAlignment align)
//設置段落的行距和行距規則,lineSpacing 參數是行距大小(以磅為單位),lineSpacingRule 參數可以是 EXACT、AT_LEAST、AUTO 等值。
setSpacingBetween(int lineSpacing, LineSpacingRule lineSpacingRule)
//設置段落的左縮進大小(以磅為單位)。
setIndentationLeft(int indentation)
//設置段落的右縮進大小(以磅為單位)。
setIndentationRight(int indentation)
//設置段落的編號 ID。
setNumID(BigInteger numId)
//設置段落的編號格式,numFmt 參數可以是 DECIMAL、LOWERCASE_LETTER、UPPERCASE_LETTER 等值。
setNumFmt(NumberFormat numFmt)
//在段落中添加圖片,pictureType 參數是圖片類型,filename 參數是圖片文件名,width 和 height 參數是圖片寬度和高度。
createPicture(XWPFRun run, int pictureType, String filename, int width, int height)
其他方法:
//指定應顯示在左邊頁面指定段周圍的邊界。
setBorderBottom(Borders.APPLES);
//指定應顯示在下邊頁面指定段周圍的邊界。
setBorderLeft(Borders.APPLES);
//指定應顯示在右側的頁面指定段周圍的邊界。
setBorderRight(Borders.ARCHED_SCALLOPS);
//指定應顯示上方一組有相同的一組段邊界設置的段落的邊界。這幾個是對段落之間的格式的統一,相當于格式刷
setBorderTop(Borders.ARCHED_SCALLOPS);
//---正文寬度會稍微變窄
p1.setFirstLineIndent(99);
//---段落的對齊方式 1左 2中 3右 4往上 左 不可寫0和負數
p1.setFontAlignment(1);
//---首行縮進,指定額外的縮進,應適用于父段的第一行。
p1.setIndentationFirstLine(400);
//---首行前進,指定的縮進量,應通過第一行回到開始的文本流的方向上移動縮進從父段的第一行中刪除。
p1.setIndentationHanging(400);
//---整段右移
p1.setIndentFromLeft(400);
//--此方法提供了樣式的段落,這非常有用。
p1.setStyle("");
//--此元素指定是否消費者應中斷超過一行的文本范圍,通過打破這個詞 (打破人物等級) 的兩行或通過移動到下一行 (在詞匯層面上打破) 這個詞的拉丁文字。
p1.setWordWrapped(true);
//---指定的文本的垂直對齊方式將應用于此段落中的文本
p1.setVerticalAlignment(TextAlignment.CENTER);
//--指定行之間的間距如何計算存儲在行屬性中。
p1.setSpacingLineRule(LineSpacingRule.AT_LEAST);
//--指定應添加在此線單位在文檔中的段落的第一行之前的間距。
p1.setSpacingBeforeLines(6);
//--指定應添加上面這一段文檔中絕對單位中的第一行的間距。
p1.setSpacingBefore(6);
//--指定應添加在此線單位在文檔中的段落的最后一行之后的間距。
p1.setSpacingAfterLines(6);
//--指定應添加在文檔中絕對單位這一段的最后一行之后的間距。
p1.setSpacingAfter(6);
//--指定當渲染此分頁視圖中的文檔,這一段的內容都呈現在文檔中的新頁的開始。
p1.setPageBreak(true);
剛在展示活動內容都是根據自身的需求寫小demo,實際項目遠遠不止這些內容,其中還是存在不足之處,例如word中的表格、圖片都是需要單獨處理,表格有個專門類XWPFTable;圖片也有XWPFPictureData、 XWPFPicture,
Apache POI 官方網站提供了完整的 API 文檔:poi.apache.org/apidocs/dev…
Apache POI 的 GitHub 倉庫中查看示例代碼和文檔:github.com/apache/poi
Java POI 生成Word文檔:blog.csdn.net/qq_34755766…
Apache POI 中文版download.csdn.net/download/qq…
作者:沐游虞
轉自:https://juejin.cn/post/7237487091554730021
來源:稀土掘金
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
用Word宏來實現批量將HTML轉換成DOC
環境:OFFICE WORD 2007
打開WORD,在菜單的“視圖”->“宏”->“查看宏”->“創建”
Sub 宏1()
Dim MyFile As String
Dim Arr(1000) As String'一次處理最大的文件數量,根據需要修改數字1000改為需要處理的數量
Dim count As Integer
MyFile = Dir("F:\待處理的HTML目錄\" & "*.html")
count = count + 1
Arr(count) = MyFile
Do While MyFile <> ""
MyFile = Dir
If MyFile = "" Then
Exit Do
End If
count = count + 1
Arr(count) = MyFile '將文件的名字存在數組中
Loop
For i = 1 To count
Documents.Open FileName:="F:\待處理的HTML目錄\" & Arr(i), ConfirmConversions:=False, ReadOnly:= _
False, AddToRecentFiles:=False, PasswordDocument:="", PasswordTemplate:= _
"", Revert:=False, WritePasswordDocument:="", WritePasswordTemplate:="", _
Format:=wdOpenFormatAuto, XMLTransform:=""
ActiveDocument.SaveAs FileName:="F:\處理后DOC保存的目錄\" & Replace(Arr(i), ".html", ".doc"), FileFormat:=wdFormatDocument, _
LockComments:=False, Password:="", AddToRecentFiles:=True, WritePassword _
:="", ReadOnlyRecommended:=False, EmbedTrueTypeFonts:=False, _
SaveNativePictureFormat:=False, SaveFormsData:=False, SaveAsAOCELetter:= _
False
ActiveDocument.Close
Next
End Sub
*請認真填寫需求信息,我們會在24小時內與您取得聯系。