首先spire.doc
是收费的(网上有说收费版没500个限制,但有水印,亲测不购买还是有水印与500段落限制),所以我们只能用spire.doc.free
免费版(注意:免费版的有限制500个段落,超出就需要购买收费的,这里我提供一个2.2.0.jar下载包 : 链接:https://share.weiyun.com/0ET3aRiz 密码:v7tit6
,虽然导出后有水印,但500段落没限制,去水印的网上方式很多,这里就不提供了),放在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
导包
<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包了,由于需要下载网络图片的二进制所以用了Hutool工具
也需要导入一下包。接下来新建工具类 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;//标题
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;
}
/**
* 导出word
* @param response 相应对象(为null则生成文件,不为null则输出到浏览器)
* @param filePath 文件路径
* @throws IOException
*/
public void export(HttpServletResponse response,String filePath) throws IOException {
//Create a Document object
Document doc = new Document();
//标题样式
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);
// 正文标题样式
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);
// 正文小结标题样式
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++) {
// 添加一级标题
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++) {
// 添加二级标题
WordUtil.Outline outlineSub = outline.getChildren().get(j);
para = section.addParagraph();
para.appendText("第"+ outlineSub.getSort() +"节 "+ outlineSub.getName());
para.applyStyle("outlineSubStyle");
para.getFormat().setFirstLineIndent(16);
}
}
}
/*// 添加一级标题
para = section.addParagraph();
para.appendText("一级标题1");
para.applyStyle("outlineStyle");
// 添加二级标题
para = section.addParagraph();
para.appendText("二级标题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() +"节"+child.getTitle());
para.applyStyle("bodyTitleSubStyle");
// 小节内容
if (!Objects.equals(child.getText(),null) && !"".equals(child.getText())){
para = section.addParagraph();
para.appendText(child.getText());
para.applyStyle("bodyStyle");
}
// 插入小节图片
for (int k = 0,lent = child.getImage().size(); k < lent; k++) {
// 创建图片对象
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("第二章 标题");
para.applyStyle("bodyTitleStyle");
para = section.addParagraph();
para.appendText("第二章第一节 子标题");
para.applyStyle("bodyTitleSubStyle");
// 第二页内容
//Add two paragraphs as body
para = section.addParagraph();
para.getFormat().setFirstLineIndent(50);
para.applyStyle("bodyStyle");
for (int i = 0; i < 15; i++) {
para.appendText("我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容");
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("页数", 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导出异常,{}",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;// 标题
private int sort;// 序号
private String text;// 正文
private java.util.List<String> image;// 章节下面的小节才有图片 网络图片地址:https://www.toopic.cn/public/uploads/small/1658043292312165804329268.png
private java.util.List<WordUtil.Content> children;// 章节下面的小节
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+"节的内容.....");
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
方法里直接调用就可以生成word了。