POI匯出word,增強方案
poi匯出word方案
poi匯出word的常規使用方式
先看看常規使用poi生成word的一些方法
// 建立文件物件
XWPFDocument docxDocument = new XWPFDocument();
// 建立段落物件
XWPFParagraph paragraphX = docxDocument.createParagraph();
// 建立文字物件
XWPFRun runX = paragraphX.createRun();
設計思路
主要是思路是將某個模板(自己定義的)上傳至伺服器,然後解析成對應的ftl檔案,之後服務在做報告時,就可以直接拿取對應的ftl檔案來生成報告。這種方式會比較靈活,現在用的也比較多。但是對於一份簡單的,不需要ftl的檔案來作為中間生成檔案時,那麼可能會比較難了。比如,接下來我們要學習的,使用word的模板作為報告模板,然後直接生成需要的報告。這個思路大概是:使用者直接設計一個word模板,然後上傳至伺服器,伺服器將其直接儲存到對應的資料夾下;在要生成報告時,直接拿word的模板來填充資料。這樣,好像也不是很難,但是想想細節上的地方,可能很多東西就不好做了。
問題所在
我們在使用word作為一份模板時,第一步要解決的就是向模板中定義的欄位替換成自己要填充的資料,如:${name}要換成自己的名字;其次就是word中也有表格,如何向word上直接畫出表格;再次,表格的行列要怎麼合併; 這些都是我們開發中會遇到的問題。
程式碼演示
public void replaceParagraph(XWPFParagraph xWPFParagraph, Map<String, Object> parametersMap) {
List<XWPFRun> runs = xWPFParagraph.getRuns ();
String xWPFParagraphText = xWPFParagraph.getText();
//正則匹配字串{****}
String regEx = "\\{.+?\\}";
Pattern pattern = Pattern.compile(regEx);
Matcher matcher = pattern.matcher(xWPFParagraphText);
if (matcher.find()) {
// 查詢到有標籤才執行替換
int beginRunIndex = xWPFParagraph.searchText("{", new PositionInParagraph()).getBeginRun();// 標籤開始run位置
int endRunIndex = xWPFParagraph.searchText("}", new PositionInParagraph()).getEndRun();// 結束標籤
StringBuffer key = new StringBuffer();
if (beginRunIndex == endRunIndex) {
// {**}在一個run標籤內
XWPFRun beginRun = runs.get(beginRunIndex);
String beginRunText = beginRun.text();
int beginIndex = beginRunText.indexOf("{");
int endIndex = beginRunText.indexOf("}");
int length = beginRunText.length();
if (beginIndex == 0 && endIndex == length - 1) {
// 該run標籤只有{**}
XWPFRun insertNewRun = xWPFParagraph.insertNewRun(beginRunIndex);
insertNewRun.getCTR().setRPr(beginRun.getCTR().getRPr());
// 設定文字
key.append(beginRunText.substring(1, endIndex));
insertNewRun.setText(getValueBykey(key.toString(), parametersMap));
xWPFParagraph.removeRun(beginRunIndex + 1);
} else {
// 該run標籤為**{**}** 或者 **{**} 或者{**}**,替換key後,還需要加上原始key前後的文字
XWPFRun insertNewRun = xWPFParagraph.insertNewRun(beginRunIndex);
insertNewRun.getCTR().setRPr(beginRun.getCTR().getRPr());
// 設定文字
key.append(beginRunText.substring(beginRunText.indexOf("{") + 1, beginRunText.indexOf("}")));
String textString = beginRunText.substring(0, beginIndex) + getValueBykey(key.toString(), parametersMap)
+ beginRunText.substring(endIndex + 1);
insertNewRun.setText(textString);
xWPFParagraph.removeRun(beginRunIndex + 1);
}
} else {
// {**}被分成多個run
// 先處理起始run標籤,取得第一個{key}值
XWPFRun beginRun = runs.get(beginRunIndex);
String beginRunText = beginRun.text();
int beginIndex = beginRunText.indexOf("{");
if (beginRunText.length() > 1) {
key.append(beginRunText.substring(beginIndex + 1));
}
ArrayList<Integer> removeRunList = new ArrayList<Integer>();//需要移除的run
// 處理中間的run
for (int i = beginRunIndex + 1; i < endRunIndex; i++) {
XWPFRun run = runs.get(i);
String runText = run.text();
key.append(runText);
removeRunList.add(i);
}
// 獲取endRun中的key值
XWPFRun endRun = runs.get(endRunIndex);
String endRunText = endRun.text();
int endIndex = endRunText.indexOf("}");
//run中**}或者**}**
if (endRunText.length() > 1 && endIndex != 0) {
key.append(endRunText.substring(0, endIndex));
}
// 取得key值後替換標籤
// 先處理開始標籤
if (beginRunText.length() == 2) {
// run標籤內文字{
XWPFRun insertNewRun = xWPFParagraph.insertNewRun(beginRunIndex);
insertNewRun.getCTR().setRPr(beginRun.getCTR().getRPr());
// 設定文字
insertNewRun.setText(getValueBykey(key.toString(), parametersMap));
xWPFParagraph.removeRun(beginRunIndex + 1);//移除原始的run
} else {
// 該run標籤為**{**或者 {** ,替換key後,還需要加上原始key前的文字
XWPFRun insertNewRun = xWPFParagraph.insertNewRun(beginRunIndex);
insertNewRun.getCTR().setRPr(beginRun.getCTR().getRPr());
// 設定文字
String textString = beginRunText.substring(0, beginRunText.indexOf("{")) + getValueBykey(key.toString(), parametersMap);
// 分行處理 有#的時候分行(給一個標記)
if (textString.contains("#")) {
String[] textStrings = textString.split("#");
for (int i = 0; i < textStrings.length; i++) {
insertNewRun.setText(textStrings[i]);
insertNewRun.addBreak();// 換行
}
} else {
insertNewRun.setText(textString);
}
xWPFParagraph.removeRun(beginRunIndex + 1);//移除原始的run
}
// 處理結束標籤
if (endRunText.length() == 1) {
// run標籤內文字只有}
XWPFRun insertNewRun = xWPFParagraph.insertNewRun(endRunIndex);
insertNewRun.getCTR().setRPr(endRun.getCTR().getRPr());
// 設定文字
insertNewRun.setText("");
xWPFParagraph.removeRun(endRunIndex + 1);//移除原始的run
} else {
// 該run標籤為**}**或者 }** 或者**},替換key後,還需要加上原始key後的文字
XWPFRun insertNewRun = xWPFParagraph.insertNewRun(endRunIndex);
insertNewRun.getCTR().setRPr(endRun.getCTR().getRPr());
// 設定文字
String textString = endRunText.substring(endRunText.indexOf("}") + 1);
insertNewRun.setText(textString);
xWPFParagraph.removeRun(endRunIndex + 1);//移除原始的run
}
// 處理中間的run標籤
for (int i = 0; i < removeRunList.size(); i++) {
XWPFRun xWPFRun = runs.get(removeRunList.get(i));//原始run
XWPFRun insertNewRun = xWPFParagraph.insertNewRun(removeRunList.get(i));
insertNewRun.getCTR().setRPr(xWPFRun.getCTR().getRPr());
insertNewRun.setText("");
xWPFParagraph.removeRun(removeRunList.get(i) + 1);//移除原始的run
}
}// 處理${**}被分成多個run
replaceParagraph(xWPFParagraph, parametersMap);
}
}
poi-tl 處理word
表格的操作方式和上面的程式碼也是大同小異,也是要寫一個標籤,才能知道哪裡需要迴圈,從上面的程式碼就可以看出用原生poi操作word顯得非常複雜,這個時候我就要給大家推薦一種新的poi的操作, poi-template-language.
模板和外掛構建了整個Poi-tl 的核心。
基於Apache POI進行了一些增強封裝,如合併多個Word文件、合併單元格、圖片處理等,外掛機制使得可以基於模板引擎特性擴展出更豐富的功能。
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.4.2</version>
</dependency>
2分鐘快速入門
從一個超級簡單的例子開始:把{{title}}替換成"Poi-tl 模板引擎"。
- 新建文件template.docx,包含文字{{title}}
- TDO模式:Template + data-model = output
// 核心API採用了極簡設計,只需要一行程式碼
XWPFTemplate template = XWPFTemplate.compile("~/template.docx").render(new HashMap<String, Object>(){{
put("title", "Poi-tl 模板引擎");
}});
FileOutputStream out = new FileOutputStream("out_template.docx");
template.write(out);
out.flush();
out.close();
template.close();
基本語法
所有的語法結構都是以 {{ 開始,以 }} 結束。
文字模板 {{var}}
TextRenderData
或String
資料模型,繼承模板樣式的同時,也可以自定義顏色、字型等樣式。
Map<String, Object> datas = new HashMap<String, Object>();
datas.put("author", new TextRenderData("00FF00", "Sayi卅一"));
datas.put("introduce", "http://www.deepoove.com");
圖片模板 {{@var}}
//本地圖片
put("localPicture", new PictureRenderData(120, 120, "src/test/resources/sayi.png"));
//本地圖片byte資料
put("localBytePicture", new PictureRenderData(100, 120, ".png", BytePictureUtils.getLocalByteArray(new File("src/test/resources/logo.png"))));
表格模板 {{#var}}
RowRenderData header = RowRenderData.build(new TextRenderData("FFFFFF", "姓名"), new TextRenderData("FFFFFF", "學歷"));
RowRenderData row = RowRenderData.build("張三", "研究生");
put("table", new MiniTableRenderData(header, Arrays.asList(row)));
列表模板 {{*var}}
put("feature", new NumbericRenderData(new ArrayList<TextRenderData>() {
{
add(new TextRenderData("Plug-in grammar, add new grammar by yourself"));
add(new TextRenderData("Supports word text, header, footer..."));
add(new TextRenderData("Templates, not just templates, but also style templates"));
}
}));
文件模板 {{+var}}
DocxRenderData
資料模型,支援Word文件的合併,文件模板(重複文件段落)被集合資料迴圈渲染後合併。
List<SegmentData> segments = new ArrayList<SegmentData>();
SegmentData s1 = new SegmentData();
s1.setTitle("經常抱怨的自己");
s1.setContent("每個人生活得都不容易,經常向別人抱怨的人,說白了就是把對方當做“垃圾場”,你一股腦地將自己的埋怨與不滿倒給別人,自己倒是爽了,你有考慮過對方的感受嗎?對方的臉上可能一笑了之,但是心裡可能有一萬隻草泥馬奔騰而過。");
segments.add(s1);
SegmentData s2 = new SegmentData();
s2.setTitle("拖拖拉拉的自己");
s2.setContent("能夠今天做完的事情,不要拖到明天,你的事情沒有任何人有義務去幫你做;不要做“宅男”、不要當“宅女”,放假的日子約上三五好友出去轉轉;經常動手做家務,既能分擔伴侶的負擔,又有一個乾淨舒適的環境何樂而不為呢?");
segments.add(s2);
put("docx_word", new DocxRenderData(new File("~/segment.docx"), segments));
詳細示例
有如下付款通知書模板,我們現在要動態填充內容
/**
* 付款通知書:表格操作示例
*/
public class PaymentExample {
PaymentData datas = new PaymentData();
Style headTextStyle = new Style();
TableStyle headStyle = new TableStyle();
TableStyle rowStyle = new TableStyle();
@Before
public void init() {
headTextStyle.setFontFamily("Hei");
headTextStyle.setFontSize(9);
headTextStyle.setColor("7F7F7F");
headStyle.setBackgroundColor("F2F2F2");
headStyle.setAlign(STJc.CENTER);
rowStyle = new TableStyle();
rowStyle.setAlign(STJc.CENTER);
datas.setNO("KB.6890451");
datas.setID("ZHANG_SAN_091");
datas.setTaitou("深圳XX家裝有限公司");
datas.setConsignee("丙丁");
datas.setSubtotal("8000");
datas.setTax("600");
datas.setTransform("120");
datas.setOther("250");
datas.setUnpay("6600");
datas.setTotal("總共:7200");
RowRenderData header = RowRenderData.build(new TextRenderData("日期", headTextStyle),
new TextRenderData("訂單編號", headTextStyle), new TextRenderData("銷售代表", headTextStyle),
new TextRenderData("離岸價", headTextStyle), new TextRenderData("發貨方式", headTextStyle),
new TextRenderData("條款", headTextStyle), new TextRenderData("稅號", headTextStyle));
header.setStyle(headStyle
相關推薦
POI匯出word,增強方案
poi匯出word方案
poi匯出word的常規使用方式
設計思路
問題所在
程式碼演示
poi-tl 處理word
2分鐘快速入門
基本語法
文字模板 {{var}}
POI匯出word
private static void exportPOI(List<SourceCard> cards ) {
//空白文件
XWPFDocument doc =new XWPFDocument();
try {
FileOutputStream fos=
java POI匯出Word文件
public class TestPOIWordOut {
public static void main(String[] args) {
//Blank Document
XWPFDocument document= new XWPFDocument();
使用POI匯出Word(含表格)的實現方式及操作Word的工具類
轉載請註明出處:https://www.cnblogs.com/sun-flower1314/p/10128796.html
本篇是關於利用Apache 的POI匯出Word的實現步驟。採用XWPFDocument匯出Word,結構和樣式完全由程式碼控制,操作起來還是非常的不太方便,只能夠建立簡
Java使用POI匯出Word文件
package com.iflytek.chy;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io
POI匯出word設定頁面大小及邊距
/** ==========文件建立====開始======== */
CustomXWPFDocument docx = new CustomXWPFDocument();
// 設定頁面大小間距
POI 匯出 Word 表格
package com.yhksxt.util;
import java.io.IOException;
import java.math.BigInteger;
import javax.servlet.http.HttpServletResponse;
import org.apache.poi.
poi-tl匯出word出錯
注意大多數是包依賴缺失
好多教程裡寫的是加入
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifa
POI根據word模板替換匯出setText內容不能換行問題。
//word模板路徑
String inFile = rootPath+"報告.docx";
//word輸出路徑
String outFile = rootPath + "輸出報告.docx";
XWPFDocument doc;
//params 引數
Map<
POI使用word模板檔案迴圈輸出行並匯出word
說明
最近工作被臨時安排了一個給同事們報銷的差事,要知道報銷這個事情對於一個開發人員是真的麻煩透頂,數目金額等等都要核對。。。。想我一個根正苗紅的正宗java開發工程師,是萬萬忍受不了讓我一個個的填寫資訊的,所以就有了這篇文章。
那就開始吧
在這裡我要吐槽
poi匯出word2003(動態資料,不用模板,且生成word能再次匯入)
一、場景需求:
有個專案需要將某個題庫裡面的題目匯出word2003,之前框架裡面沒有匯出word2003的工具類。倒是見過匯出txt,excel的,但是word的沒有。
二、技術選型
網上找了一通,匯出word的有幾個技術方案,不過對於word2003版
目前java匯出word的6種解決方案
最近做的專案,需要將一些資訊匯出到word中。在網上找了好多解決方案,現在將這幾天的總結分享一下。
目前來看,java匯出word大致有6種解決方案: 1:Jacob是Java-COM Bridge的縮寫,它在Java與微軟的COM元件之間構建一座橋樑。使用Jacob自
POI匯出簡單的帶有圖片的Word文件
由於匯出的文件中需要插入圖片,因此需要新建類來處理由於插入圖片引進的錯誤即“匯出的word文件在開啟時會報內容出現錯誤,無法開啟檔案”
新建處理類為:
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import j
java poi匯出Excel表格超大資料量解決方案
Java實現匯出excel表格功能,大部分都會使用apache poi,apache poi API 地址
POI之前的版本不支援大資料量處理,如果資料過多則經常報OOM錯誤,有時候調整JVM大小效果也不是太好。3.8版本的POI新出來了SXSSFWorkbo
【Apache POI】Java Web根據模板匯出word檔案
最近工作中遇到一個需求:根據word模板文件匯出word檔案。
查閱了一些資料,發現Apache POI可以實現文件讀寫的功能,於是就研究了一下,總結如下:
POI詳細介紹:
Apache POI是一個開源的Java讀寫Excel、WORD等微軟OLE2元件
POI操作word和html相互轉化
image com 文件 ali cto gpa jar包 nsf fun 下面是裏兩個類:第一個類是html轉為word,第二個是word轉html(最下面附上jar包下載鏈接)
package com.wz.poi.wordHtml;
/** * 2018/4/24 *
菜鳥調錯——POI匯出Excel報錯No such file or directory
場景重現
Apache POI
Linux
Tomcat
如上所示,當時在linux+tomcat的環境下,使用apache的poi匯出excel的時候就會報“No such file or directory”的錯誤。
錯誤資訊
java.la
POI匯出excel表格優化
package com.ywj.excel;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java
HSSFWorkbook(poi)匯出excel表格
本文與另一篇文章關聯:
csv格式匯出excel報表
其中:
String accountDate 入參(日期)
AccountInfoEntityResp accountInfoEntityResp 匯出的xml報文內容(轉換成obj物件)
xml報文解析見另一篇:x
Java呼叫POI匯出資料庫資訊
資料庫連結包:連結:https://pan.baidu.com/s/18VhAHNoDF-gacq04AnBr4w 密碼:vjlr
POI呼叫包:連結:https://pan.baidu.com/s/1Jhz6HlJc9gutRBwWE4KU-g 密碼:dnzq
java程式碼:
impo