首先spire.doc
是收費(fèi)的(網(wǎng)上有說收費(fèi)版沒500個限制,但有水印风喇,親測不購買還是有水印與500段落限制)臂港,所以我們只能用spire.doc.free
免費(fèi)版(注意:免費(fèi)版的有限制500個段落锋谐,超出就需要購買收費(fèi)的虎眨,這里我提供一個2.2.0.jar下載包 : 鏈接:https://share.weiyun.com/0ET3aRiz 密碼:v7tit6
,雖然導(dǎo)出后有水印您单,但500段落沒限制梯投,去水印的網(wǎng)上方式很多稻薇,這里就不提供了),放在d盤葵萎,安裝命令
mvn install:install-file -Dfile=D:/spire.doc-2.2.0.jar -DgroupId=e-iceblue -DartifactId=spire.doc -Dversion=2.2.0 -Dpackaging=jar
導(dǎo)包
<repositories>
<!-- 必須添加這個鏡像地址 -->
<repository>
<id>com.e-iceblue</id>
<url>https://repo.e-iceblue.cn/repository/maven-public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.29</version>
</dependency>
<!--spire.doc 操作word文檔-->
<!-- <dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.doc.free</artifactId>
<version>5.2.0</version>
</dependency>-->
<!--spire.doc 操作word文檔-->
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.doc</artifactId>
<version>2.2.0</version>
</dependency>
</dependencies>
我這里由于一直下載包失敗导犹,所以就直接去中央倉庫下載jar包了,由于需要下載網(wǎng)絡(luò)圖片的二進(jìn)制所以用了Hutool工具
也需要導(dǎo)入一下包羡忘。接下來新建工具類 WordUtil.java
package com.demo2.util;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.http.HttpUtil;
import com.spire.doc.Body;
import com.spire.doc.Document;
import com.spire.doc.FieldType;
import com.spire.doc.FileFormat;
import com.spire.doc.HeaderFooter;
import com.spire.doc.Section;
import com.spire.doc.documents.BreakType;
import com.spire.doc.documents.BuiltinStyle;
import com.spire.doc.documents.HorizontalAlignment;
import com.spire.doc.documents.Paragraph;
import com.spire.doc.documents.ParagraphStyle;
import com.spire.doc.documents.TextWrappingStyle;
import com.spire.doc.fields.DocPicture;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
/** word書籍生成
* author xiaochi
* date 2024/8/15
*/
@Slf4j
public class WordUtil {
private String title;//標(biāo)題
private String author;// 作者
private String outlineName;// 目錄名稱
private List<WordUtil.Outline> outlines = new ArrayList<>();// 目錄
private List<WordUtil.Content> contents = new ArrayList<>();// 正文
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getOutlineName() {
return outlineName;
}
public void setOutlineName(String outlineName) {
this.outlineName = outlineName;
}
public List<WordUtil.Outline> getOutlines() {
return outlines;
}
public void setOutlines(List<WordUtil.Outline> outlines) {
this.outlines = outlines;
}
public List<WordUtil.Content> getContents() {
return contents;
}
public void setContents(List<WordUtil.Content> contents) {
this.contents = contents;
}
/**
* 導(dǎo)出word
* @param response 相應(yīng)對象(為null則生成文件谎痢,不為null則輸出到瀏覽器)
* @param filePath 文件路徑
* @throws IOException
*/
public void export(HttpServletResponse response,String filePath) throws IOException {
//Create a Document object
Document doc = new Document();
//標(biāo)題樣式
ParagraphStyle titleStyle = new ParagraphStyle(doc);
titleStyle.setName("titleStyle");
titleStyle.getParagraphFormat().setHorizontalAlignment(HorizontalAlignment.Center);
titleStyle.getCharacterFormat().setBold(true);
titleStyle.getCharacterFormat().setTextColor(Color.black);
titleStyle.getCharacterFormat().setFontName("微軟雅黑");
titleStyle.getCharacterFormat().setFontSize(32f);
doc.getStyles().add(titleStyle);
// 目錄一級樣式
ParagraphStyle outlineStyle = new ParagraphStyle(doc);
outlineStyle.setName("outlineStyle");
outlineStyle.getParagraphFormat().setHorizontalAlignment(HorizontalAlignment.Left);
outlineStyle.getCharacterFormat().setBold(false);
outlineStyle.getCharacterFormat().setTextColor(Color.black);
outlineStyle.getCharacterFormat().setFontName("Times New Roman");// Times New Roman
outlineStyle.getCharacterFormat().setFontSize(12f);
doc.getStyles().add(outlineStyle);
// 目錄二級樣式
ParagraphStyle outlineSubStyle = new ParagraphStyle(doc);
outlineSubStyle.setName("outlineSubStyle");
outlineSubStyle.getParagraphFormat().setHorizontalAlignment(HorizontalAlignment.Left);
outlineSubStyle.getCharacterFormat().setBold(false);
outlineSubStyle.getCharacterFormat().setTextColor(Color.black);
outlineSubStyle.getCharacterFormat().setFontName("Times New Roman");// Times New Roman
outlineSubStyle.getCharacterFormat().setFontSize(12f);
doc.getStyles().add(outlineSubStyle);
// 正文標(biāo)題樣式
ParagraphStyle bodyTitleStyle = new ParagraphStyle(doc);
bodyTitleStyle.setName("bodyTitleStyle");
bodyTitleStyle.getParagraphFormat().setHorizontalAlignment(HorizontalAlignment.Center);
bodyTitleStyle.getCharacterFormat().setBold(true);
bodyTitleStyle.getCharacterFormat().setTextColor(Color.BLACK);
bodyTitleStyle.getCharacterFormat().setFontName("微軟雅黑");// Times New Roman
bodyTitleStyle.getCharacterFormat().setFontSize(16f);
bodyTitleStyle.getCharacterFormat().setBold(true);
bodyTitleStyle.getParagraphFormat().setBeforeSpacing(12);
//bodyTitleStyle.getParagraphFormat().setAfterSpacing(10);
doc.getStyles().add(bodyTitleStyle);
// 正文小結(jié)標(biāo)題樣式
ParagraphStyle bodyTitleSubStyle = new ParagraphStyle(doc);
bodyTitleSubStyle.setName("bodyTitleSubStyle");
bodyTitleSubStyle.getParagraphFormat().setHorizontalAlignment(HorizontalAlignment.Center);
bodyTitleSubStyle.getCharacterFormat().setBold(true);
bodyTitleSubStyle.getCharacterFormat().setTextColor(Color.BLACK);
bodyTitleSubStyle.getCharacterFormat().setFontName("Times New Roman");// Times New Roman
bodyTitleSubStyle.getCharacterFormat().setFontSize(14f);
bodyTitleSubStyle.getCharacterFormat().setBold(false);
bodyTitleSubStyle.getParagraphFormat().setBeforeSpacing(10);
bodyTitleSubStyle.getParagraphFormat().setAfterSpacing(10);
doc.getStyles().add(bodyTitleSubStyle);
//正文樣式
ParagraphStyle bodyStyle = new ParagraphStyle(doc);
bodyStyle.setName("bodyStyle");
bodyStyle.getCharacterFormat().setFontName("Times New Roman");
bodyStyle.getCharacterFormat().setTextColor(Color.BLACK);
bodyStyle.getCharacterFormat().setFontSize(12);
doc.getStyles().add(bodyStyle);
//Add a section
Section section = doc.addSection();
//Set the page margins
section.getPageSetup().getMargins().setAll(40f);
section.getPageSetup().setRestartPageNumbering(true);
section.getPageSetup().setPageStartingNumber(1);
//Add a paragraph as title
Paragraph para = section.addParagraph();
para.appendText(this.getTitle());
para.getFormat().setHorizontalAlignment(HorizontalAlignment.Center);
para.getFormat().setAfterSpacing(10);
para.applyStyle("titleStyle");
// 添加作者
para = section.addParagraph();
para = section.addParagraph();
para.appendText("作者:"+this.getAuthor());
para.applyStyle(BuiltinStyle.Heading_3);
para.getFormat().setHorizontalAlignment(HorizontalAlignment.Center);
Body body = doc.getLastSection().getBody();
body.getLastParagraph().appendBreak(BreakType.Page_Break);
// 添加目錄
para = section.addParagraph();
para.appendText("目錄");
para.applyStyle("bodyTitleStyle");
para.getFormat().setHorizontalAlignment(HorizontalAlignment.Center);
for (int i = 0,len = this.getOutlines().size(); i < len; i++) {
// 添加一級標(biāo)題
WordUtil.Outline outline = this.getOutlines().get(i);
para = section.addParagraph();
para.appendText("第"+ outline.getSort() +"章 "+ outline.getName());
para.applyStyle("outlineStyle");
if (outline.getChildren() != null && !outline.getChildren().isEmpty()){
for (int j = 0,lenth = outline.getChildren().size(); j < lenth; j++) {
// 添加二級標(biāo)題
WordUtil.Outline outlineSub = outline.getChildren().get(j);
para = section.addParagraph();
para.appendText("第"+ outlineSub.getSort() +"節(jié) "+ outlineSub.getName());
para.applyStyle("outlineSubStyle");
para.getFormat().setFirstLineIndent(16);
}
}
}
/*// 添加一級標(biāo)題
para = section.addParagraph();
para.appendText("一級標(biāo)題1");
para.applyStyle("outlineStyle");
// 添加二級標(biāo)題
para = section.addParagraph();
para.appendText("二級標(biāo)題2");
para.applyStyle("outlineSubStyle");
para.getFormat().setFirstLineIndent(16);*/
//---------------- 開始新的一頁 -----------------------
Body bodyOutline = doc.getLastSection().getBody();
// Insert a page break after the last paragraph in the body
bodyOutline.getLastParagraph().appendBreak(BreakType.Page_Break);
double h = NumberUtil.div(NumberUtil.mul(section.getPageSetup().getClientWidth(), 720), 1280);
//正文
for (int i = 0,len = this.getContents().size(); i < len; i++) {
WordUtil.Content content = this.getContents().get(i);
para = section.addParagraph();
para.appendText("第"+ content.getSort() +"章 "+content.getTitle());
para.applyStyle("bodyTitleStyle");
for (int j = 0,length = content.getChildren().size(); j < length; j++) {
WordUtil.Content child = content.getChildren().get(j);
para = section.addParagraph();
para.appendText("第"+ child.getSort() +"節(jié)"+child.getTitle());
para.applyStyle("bodyTitleSubStyle");
// 小節(jié)內(nèi)容
if (!Objects.equals(child.getText(),null) && !"".equals(child.getText())){
para = section.addParagraph();
para.appendText(child.getText());
para.applyStyle("bodyStyle");
}
// 插入小節(jié)圖片
for (int k = 0,lent = child.getImage().size(); k < lent; k++) {
// 創(chuàng)建圖片對象
DocPicture picture = para.appendPicture(HttpUtil.downloadBytes(child.getImage().get(k)));
picture.setTextWrappingStyle(TextWrappingStyle.Inline);
picture.setWidth(section.getPageSetup().getClientWidth());
picture.setHeight((float) h);
}
}
}
/*para = section.addParagraph();
para.appendText("第二章 標(biāo)題");
para.applyStyle("bodyTitleStyle");
para = section.addParagraph();
para.appendText("第二章第一節(jié) 子標(biāo)題");
para.applyStyle("bodyTitleSubStyle");
// 第二頁內(nèi)容
//Add two paragraphs as body
para = section.addParagraph();
para.getFormat().setFirstLineIndent(50);
para.applyStyle("bodyStyle");
for (int i = 0; i < 15; i++) {
para.appendText("我是內(nèi)容我是內(nèi)容我是內(nèi)容我是內(nèi)容我是內(nèi)容我是內(nèi)容我是內(nèi)容我是內(nèi)容我是內(nèi)容我是內(nèi)容我是內(nèi)容我是內(nèi)容");
DocPicture picture = para.appendPicture(HttpUtil.downloadBytes("https://www.toopic.cn/public/uploads/small/1658043292312165804329268.png"));
picture.setWidth(section.getPageSetup().getClientWidth());
picture.setHeight((float)NumberUtil.div(NumberUtil.mul(section.getPageSetup().getClientWidth(), 720), 1280));
}*/
//添加頁碼
HeaderFooter footer = section.getHeadersFooters().getFooter();
footer.getChildObjects().clear();
Paragraph footerParagraph = footer.addParagraph();
footerParagraph.appendField("頁碼", FieldType.Field_Page);
//footerParagraph.appendText("/" + doc.getPageCount());
footerParagraph.appendText("/");
footerParagraph.appendField("頁數(shù)", FieldType.Field_Num_Pages);
footerParagraph.getStyle().getCharacterFormat().setFontSize(9f);
footerParagraph.getStyle().getCharacterFormat().setFontName("宋體");
footerParagraph.getFormat().setHorizontalAlignment(HorizontalAlignment.Center);
//Save to file
if (response == null){
doc.saveToFile(filePath + ".docx", FileFormat.Docx_2013);
doc.close();
return;
}
ServletOutputStream out = response.getOutputStream();
try {
response.reset();
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0);
response.setContentType("application/octet-stream");
response.setHeader("Content-disposition", "inline; filename=" + DateUtil.format(new Date(), "yyyyMMddHHmmss") + ".docx");
doc.saveToStream(out, FileFormat.Docx_2013);
}catch (Exception e){
log.info("word導(dǎo)出異常,{}",e);
}finally {
doc.close();
out.flush();
out.close();
}
}
/**
* 目錄
*/
public static class Outline{
private String name;
private int sort;// 序號
private java.util.List<WordUtil.Outline> children;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSort() {
return sort;
}
public void setSort(int sort) {
this.sort = sort;
}
public java.util.List<WordUtil.Outline> getChildren() {
return children;
}
public void setChildren(java.util.List<WordUtil.Outline> children) {
this.children = children;
}
}
/**
* 正文大綱entrty
*/
public static class Content{
private String title;// 標(biāo)題
private int sort;// 序號
private String text;// 正文
private java.util.List<String> image;// 章節(jié)下面的小節(jié)才有圖片 網(wǎng)絡(luò)圖片地址:https://www.toopic.cn/public/uploads/small/1658043292312165804329268.png
private java.util.List<WordUtil.Content> children;// 章節(jié)下面的小節(jié)
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getSort() {
return sort;
}
public void setSort(int sort) {
this.sort = sort;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public java.util.List<String> getImage() {
return image;
}
public void setImage(java.util.List<String> image) {
this.image = image;
}
public java.util.List<WordUtil.Content> getChildren() {
return children;
}
public void setChildren(List<WordUtil.Content> children) {
this.children = children;
}
}
public static void main(String[] args) throws IOException {
WordUtil wordUtil = new WordUtil();
wordUtil.setTitle("start的一生");
wordUtil.setAuthor("start");
wordUtil.setOutlineName("目錄");
java.util.List<WordUtil.Outline> outlines = new ArrayList<>();
java.util.List<WordUtil.Content> contents = new ArrayList<>();
for (int i = 0; i < 10; i++) {
String title = "小二" + (i + 1);
WordUtil.Outline outline = new WordUtil.Outline();
outline.setName(title);
outline.setSort(i+1);
WordUtil.Content content = new WordUtil.Content();
content.setTitle(title);
content.setSort(i+1);
java.util.List<WordUtil.Content> contentChildren = new ArrayList<>();
java.util.List<WordUtil.Outline> children = new ArrayList<>();
for (int k = 0; k < 10; k++) {
String childTitle = "小二k" + (k + 1);
WordUtil.Outline childOutline = new WordUtil.Outline();
childOutline.setName(childTitle);
childOutline.setSort(k + 1);
children.add(childOutline);
WordUtil.Content childContent = new WordUtil.Content();
childContent.setTitle(childTitle);
childContent.setSort(k + 1);
childContent.setText("我是第"+i+"章第"+k+"節(jié)的內(nèi)容.....");
java.util.List<String> images = new ArrayList<>();
images.add("https://www.toopic.cn/public/uploads/small/1658043292312165804329268.png");
childContent.setImage(images);
contentChildren.add(childContent);
}
outline.setChildren(children);
outlines.add(outline);
content.setChildren(contentChildren);
contents.add(content);
}
wordUtil.setOutlines(outlines);
wordUtil.setContents(contents);
wordUtil.export(null,null);
}
}
main
方法里直接調(diào)用就可以生成word了。