目錄問(wèn)題:
解決word模板目錄在第一次打開不更新就不顯示目錄問(wèn)題的原因:之前是通過(guò)動(dòng)態(tài)替換域代碼toc的形式,生成了一段域代碼放置在Word的目錄行,打開的時(shí)候無(wú)法直接觸發(fā)渲染和更新。
方案:通過(guò)插入-文檔組件-域組件-目錄和索引,將當(dāng)前的模板的目錄直接生成到文檔的目錄中,在數(shù)據(jù)替換的時(shí)候,由于目錄用的也是正文的內(nèi)容,所以直接就替換掉了。
上述方案解決了需要手動(dòng)更新才能顯示,否則空白的問(wèn)題。但是也存在缺點(diǎn):只能更新目錄的內(nèi)容,目錄的頁(yè)碼無(wú)法正確更新顯示,是當(dāng)時(shí)模板的頁(yè)碼。
------------------------------------------分界線-------------------------------------------------------------------------
項(xiàng)目時(shí)間允許之際,又做了方案調(diào)研,用以下方案,完美解決:
1、spire.doc
有收費(fèi)版本和免費(fèi)版本,免費(fèi)的版本只能讀取500行的內(nèi)容,并生成目錄,所以不全,不用;
收費(fèi)版本的生成word后,會(huì)在文檔第一行顯示試用提示,將該行用poi刪除即可;
先用poi-tl的模板生成word,然后用spire.doc打開,并更新域,再保存到原文件路徑即可,最后將第一行刪掉:
public class Demo4 {
public static void main (String[] args) throws IOException {
//加載已設(shè)置大綱級(jí)別的測(cè)試文檔
long start = System.currentTimeMillis();
Document doc = new Document("D:\\project\\util\\src\\main\\resources\\poi\\report.docx");
doc.updateTableOfContents();
doc.saveToFile("目錄2222311.docx", FileFormat.Docx_2010);
restWord("目錄2222311.docx");
System.out.println((System.currentTimeMillis()-start)/1000);
}
private static void restWord(String docFilePath) {
try (FileInputStream in = new FileInputStream(docFilePath)) {
XWPFDocument doc = new XWPFDocument(OPCPackage.open(in));
List<XWPFParagraph> paragraphs = doc.getParagraphs();
if (paragraphs.size() < 1) return;
XWPFParagraph firstParagraph = paragraphs.get(0);
if (firstParagraph.getText().contains("Spire.Doc")) {
doc.removeBodyElement(doc.getPosOfParagraph(firstParagraph));
}
OutputStream out = new FileOutputStream(docFilePath);
doc.write(out);
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
2、aspose.word
aspose.word只有收費(fèi)版本,如果公司允許,可以買了再用,沒有預(yù)算的,可以找一個(gè)破解jar包引入即可,如果找不到,可以私信我:
先用poi-tl的模板生成word,然后用aspose.word打開,并更新域,再保存到原文件路徑即可:
public class Demo5 {
public static void main (String[] args) throws Exception {
//加載已設(shè)置大綱級(jí)別的測(cè)試文檔
long start = System.currentTimeMillis();
Document doc = new Document("D:\\project\\util\\src\\main\\resources\\poi\\report.docx");
doc.updateFields();
doc.save("33333.pdf", SaveFormat.PDF);//這里執(zhí)行操作
// restWord("目錄33331221.docx");
System.out.println((System.currentTimeMillis()-start)/1000);
}
private static void restWord(String docFilePath) {
try (FileInputStream in = new FileInputStream(docFilePath)) {
XWPFDocument doc = new XWPFDocument(OPCPackage.open(in));
List<XWPFParagraph> paragraphs = doc.getParagraphs();
if (paragraphs.size() < 1) {
return;
}
XWPFParagraph firstParagraph = paragraphs.get(0);
XWPFParagraph lastParagraph = paragraphs.get(paragraphs.size() - 1);
if (firstParagraph.getText().contains("Aspose.Words")) {
doc.removeBodyElement(doc.getPosOfParagraph(firstParagraph));
doc.removeBodyElement(doc.getPosOfParagraph(lastParagraph));
}
OutputStream out = new FileOutputStream(docFilePath);
doc.write(out);
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
總結(jié),公司允許用破解版的,可以用aspose.word,效率高,生成PDF也給力;spire.doc是國(guó)內(nèi)的產(chǎn)品,操作word耗時(shí)長(zhǎng),700+頁(yè)的文檔需要130s+的耗時(shí),不能忍。
-------------------------------------------分界線----------------------------------------------------------------------
以上方案已經(jīng)解決了目錄精確問(wèn)題,在大文件word生成的時(shí)候,還存在2個(gè)問(wèn)題:
1、并發(fā)調(diào)用會(huì)導(dǎo)致線程卡住,卡在new Document()
2、大文件更新目錄的時(shí)候特別慢,也會(huì)出現(xiàn)卡死現(xiàn)象
解決方案:
1、添加synchronized同步鎖,每次只有一個(gè)生成;文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-516621.html
2、判斷文件大小超過(guò)nMB時(shí),不調(diào)用精確方法,小于的時(shí)候才調(diào)用,避免不可用問(wèn)題文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-516621.html
到了這里,關(guān)于Java的POI-word模板生成目錄自動(dòng)更新--完美解決的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!