简介
word编程最重要的类是org.apache.poi.xwpf.usermodel.xwpfdocument。涉及的东西十分复杂。而且apache poi操作word的技术非常不成熟。代码中本身有很多bug。
maven的依赖为
<dependency>
<groupid>org.apache.poi</groupid>
<artifactid>poi-ooxml</artifactid>
<version>5.0.0</version>
</dependency>
以下代码创建一个空word文档。
public class emptyword {
public static void main(string[] args) throws ioexception {
xwpfdocument document = new xwpfdocument();
file file = new file("test.word");
document.write(new fileoutputstream(file));
}
}
段落
首先看看段落与字体设置。
假设有需要生成一个一级标题,利用document创建段落。每个段落又有多个run组成。run不能继续拆分,一个run拥有共同的字体。如以下代码创建一个段落:
final xwpfparagraph paragraph = document.createparagraph();
paragraph.setnumilvl(biginteger.valueof(1l));
final xwpfrun run = paragraph.createrun();
run.settext("老了");
run.setfontsize(10);
run.setcolor("ffff00");
run.setfontfamily("宋书");
而段落的大纲级别的设置比较复杂,代码如下
ctppr ppr = paragraph.getctp().getppr();
if (ppr == null) {
ppr = paragraph.getctp().addnewppr();
}
final ctdecimalnumber ctdecimalnumber = ppr.addnewoutlinelvl();
ctdecimalnumber.setval(biginteger.valueof(1));
ppr.setoutlinelvl(ctdecimalnumber);
这里有一个难懂的概念,什么是ctp。
其效果如下:

页头与页脚
页头与页脚测试时发现生成的页头和页脚只能在word中看到,在wps里看不到。这可能是poi的一个bug。生成页头和页脚都比较简单。
final xwpfdocument document = new xwpfdocument();
final xwpfheader header = document.createheader(headerfootertype.default);
final xwpfparagraph paragraph = header.createparagraph();
final xwpfrun run = paragraph.createrun();
run.settext("我是页头");
run.setfontsize(12);
run.setcolor("ff00ff");
system.out.println(header.gettext());
页脚为:
// 页脚呢
final xwpffooter footer = document.createfooter(headerfootertype.default);
final xwpfparagraph footerparagraph = footer.createparagraph();
final xwpfrun footerparagraphrun = footerparagraph.createrun();
footerparagraphrun.settext("页脚");
footerparagraphrun.setfontsize(12);
完整效果如下:

页码
生成页码的方法比较复杂。但是值得挑战一下。
final xwpffooter footer = document.createfooter(headerfootertype.default);
xwpfparagraph paragraph = footer.createparagraph();
xwpfrun run = paragraph.createrun();
run.settext("第");
run = paragraph.createrun();
ctfldchar ctfldchar = run.getctr().addnewfldchar();
ctfldchar.setfldchartype(stfldchartype.begin);
// 又一段
run = paragraph.createrun();
cttext cttext = run.getctr().addnewinstrtext();
cttext.setstringvalue("page \\* mergeformat");
cttext.setspace(spaceattribute.space.enum.forstring("preserve"));
ctfldchar = run.getctr().addnewfldchar();
ctfldchar.setfldchartype(stfldchartype.end);
run = paragraph.createrun();
run.settext("页 总共");
run = paragraph.createrun();
ctfldchar = run.getctr().addnewfldchar();
ctfldchar.setfldchartype(stfldchartype.begin);
run = paragraph.createrun();
cttext = run.getctr().addnewinstrtext();
cttext.setstringvalue("numpages \\* mergeformat");
cttext.setspace(spaceattribute.space.enum.forstring("preserve"));
ctfldchar = run.getctr().addnewfldchar();
ctfldchar.setfldchartype(stfldchartype.end);
run = paragraph.createrun();
run.settext("页");
同样,兼容word,不兼容wps。
效果如下:

表格
word里插入表格,是非常常见的功能。
final xwpfdocument document = new xwpfdocument();
final xwpftable table = document.createtable(3, 3);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
table.getrow(i).getcell(j).settext(i+"-"+j);
}
}
表格有点丑,但是勉强可以用哈:

图片
插入图片也是必要的功能啊,代码示例如下:
string imagepath = "image.png"; // 图片路径
fileinputstream imagestream = new fileinputstream(imagepath);
// 设置图片尺寸(单位:emu)
int width = units.toemu(300); // 宽度(约4厘米)
int height = units.toemu(200); // 高度
final xwpfparagraph paragraph = document.createparagraph();
final xwpfrun run = paragraph.createrun();
// 插入图片
run.addpicture(
imagestream,
xwpfdocument.picture_type_png, // 图片格式
"image.png", // 描述文本
width,
height
);
imagestream.close();
插入图片效果:

批注
word编程加批注是十分困难的、十分复杂的。在poi里,有同名的包,不能导错,以下是正确的包:
import org.openxmlformats.schemas.wordprocessingml.x2006.main.ctcomment; import org.openxmlformats.schemas.wordprocessingml.x2006.main.ctcomments; import org.openxmlformats.schemas.wordprocessingml.x2006.main.cttext;
首先要写一个辅助类,辅助类倒是比较简单:
public class myxwpfcommentsdocument extends poixmldocumentpart {
private ctcomments ctcomments;
private myxwpfcommentsdocument(packagepart part) {
super(part);
ctcomments = commentsdocument.factory.newinstance().addnewcomments();
}
public ctcomments getctcomments() {
return ctcomments;
}
@override
protected void commit() throws ioexception {
xmloptions xmloptions = new xmloptions(poixmltypeloader.default_xml_options);
xmloptions.setsavesyntheticdocumentelement(new qname(ctcomments.type.getname().getnamespaceuri(), "comments"));
packagepart part = getpackagepart();
outputstream out = part.getoutputstream();
ctcomments.save(out, xmloptions);
out.close();
}
public static myxwpfcommentsdocument createcommentsdocument(xwpfdocument document) throws exception {
opcpackage opcpackage = document.getpackage();
packagepartname partname = packagingurihelper.createpartname("/word/comments.xml");
packagepart part = opcpackage.createpart(partname, "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml");
myxwpfcommentsdocument myxwpfcommentsdocument = new myxwpfcommentsdocument(part);
string rid = "rid" + (document.getrelationparts().size()+1);
document.addrelation(rid, xwpfrelation.comment, myxwpfcommentsdocument);
return myxwpfcommentsdocument;
}
}
以下是加入批注的方法:
myxwpfcommentsdocument myxwpfcommentsdocument = myxwpfcommentsdocument.createcommentsdocument(document);
ctcomments comments = myxwpfcommentsdocument.getctcomments();
ctcomment ctcomment;
xwpfparagraph paragraph;
//first comment
biginteger cid = biginteger.zero;
ctcomment = comments.addnewcomment();
cttext cttext = ctcomment.addnewp().addnewr().addnewt();
cttext.setstringvalue("the first comment.");
ctcomment.setauthor("axel ríchter");
ctcomment.setinitials("ar");
ctcomment.setid(cid);
paragraph = document.createparagraph();
paragraph.getctp().addnewcommentrangestart().setid(cid);
xwpfrun run;
run = paragraph.createrun();
run.settext("paragraph with the first comment.");
paragraph.getctp().addnewcommentrangeend().setid(cid);
paragraph.getctp().addnewr().addnewcommentreference().setid(cid);
以下是批注的效果:

文本框
文本框的插入也是比较复杂,代码如下:
xwpfparagraph paragraph = document.createparagraph();
xwpfrun run=paragraph.createrun();
run.settext("the body text: ");
ctgroup ctgroup = ctgroup.factory.newinstance();
ctshape ctshape = ctgroup.addnewshape();
ctshape.setstyle("width:100pt;height:24pt");
cttxbxcontent cttxbxcontent = ctshape.addnewtextbox().addnewtxbxcontent();
cttxbxcontent.addnewp().addnewr().addnewt().setstringvalue("the textbox text...");
node ctgroupnode = ctgroup.getdomnode();
ctpicture ctpicture = ctpicture.factory.parse(ctgroupnode);
run=paragraph.createrun();
ctr ctr = run.getctr();
ctr.addnewpict();
ctr.setpictarray(0, ctpicture);
简单展示下效果:

目录
目录本来就一句话doc.createtoc(),但是很容易失败。使用ctppr可以设置段落的大纲级别,以下是代码:
try (xwpfdocument document = new xwpfdocument()) {
document.createtoc();
final xwpfparagraph paragraph = document.createparagraph();
// 获取段落属性,若不存在则新建
ctppr ppr = paragraph.getctp().issetppr() ? paragraph.getctp().getppr() : paragraph.getctp().addnewppr();
// 设置大纲级别为 1
ctdecimalnumber outlinelvl = ppr.issetoutlinelvl() ? ppr.getoutlinelvl() : ppr.addnewoutlinelvl();
outlinelvl.setval(biginteger.valueof(1));
final xwpfrun run = paragraph.createrun();
run.settext("标题一");
run.setfontsize(10);
run.setfontfamily("宋书");
file file = new file("toc.docx");
document.write(files.newoutputstream(file.topath()));
}
虽然代码运行不报错,但是结果是生成不了目录。以下是效果图:

图表
英文叫chart,chart是需要关联excel表格的。所以这个特别复杂。完整代码如下:
// create the data
string[] categories = new string[] { "lang 1", "lang 2", "lang 3" };
double[] valuesa = new double[] { 10d, 20d, 30d };
double[] valuesb = new double[] { 15d, 25d, 35d };
// create the chart
xwpfchart chart = doc.createchart(15 * units.emu_per_centimeter, 10 * units.emu_per_centimeter);
// create data sources
int numofpoints =categories. length;
string categorydatarange = chart.formatrange(new cellrangeaddress(1, numofpoints, 0, 0));
string valuesdatarangea = chart.formatrange(new cellrangeaddress(1, numofpoints, 1, 1));
string valuesdatarangeb = chart.formatrange(new cellrangeaddress(1, numofpoints, 2, 2));
xddfdatasource<string> categoriesdata = xddfdatasourcesfactory.fromarray(categories, categorydatarange, 0);
xddfnumericaldatasource<double> valuesdataa = xddfdatasourcesfactory.fromarray(valuesa, valuesdatarangea, 1);
xddfnumericaldatasource<double> valuesdatab = xddfdatasourcesfactory.fromarray(valuesb, valuesdatarangeb, 2);
// create axis
xddfcategoryaxis bottomaxis = chart.createcategoryaxis(axisposition.bottom);
xddfvalueaxis leftaxis = chart.createvalueaxis(axisposition.left);
leftaxis.setcrosses(axiscrosses.auto_zero);
// set axiscrossbetween, so the left axis crosses the category axis between the categories.
// else first and last category is exactly on cross points and the bars are only half visible.
leftaxis.setcrossbetween(axiscrossbetween.between);
// create chart data
xddfchartdata data = chart.createdata(charttypes.bar, bottomaxis, leftaxis);
((xddfbarchartdata) data).setbardirection(bardirection.col);
// create series
// if only one series do not vary colors for each bar
((xddfbarchartdata) data).setvarycolors(false);
xddfchartdata.series series = data.addseries(categoriesdata, valuesdataa);
// xddfchart.setsheettitle is buggy. it creates a table but only half way and incomplete.
// excel cannot opening the workbook after creatingg that incomplete table.
// so updating the chart data in word is not possible.
//series.settitle("a", chart.setsheettitle("a", 1));
series.settitle("a", settitleindatasheet(chart, "a", 1));
/*
// if more than one series do vary colors of the series
((xddfbarchartdata)data).setvarycolors(true);
series = data.addseries(categoriesdata, valuesdatab);
//series.settitle("b", chart.setsheettitle("b", 2));
series.settitle("b", settitleindatasheet(chart, "b", 2));
*/
// plot chart data
chart.plot(data);
// create legend
xddfchartlegend legend = chart.getoraddlegend();
legend.setposition(legendposition.left);
legend.setoverlay(false);
还有一个私有方法:
static cellreference settitleindatasheet(xwpfchart chart, string title, int column) throws exception {
xssfworkbook workbook = chart.getworkbook();
xssfsheet sheet = workbook.getsheetat(0);
xssfrow row = sheet.getrow(0);
if (row == null)
row = sheet.createrow(0);
xssfcell cell = row.getcell(column);
if (cell == null)
cell = row.createcell(column);
cell.setcellvalue(title);
return new cellreference(sheet.getsheetname(), 0, column, true, true);
}
运行效果如下:

以上就是java操作word的全面指南的详细内容,更多关于java操作word的资料请关注代码网其它相关文章!
发表评论