poi生成word文件,插入圖片,echar報表生成到word,word表格
阿新 • • 發佈:2019-01-09
java程式碼:<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.15</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.15</version> </dependency> </dependencies>
EchartsController.java
package com.lyq.web; import com.lyq.util.ExportWordUtil; import org.apache.commons.io.FileUtils; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import sun.misc.BASE64Decoder; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.FileOutputStream; import java.io.IOException; import java.util.Calendar; import java.util.HashMap; import java.util.Map; /** * * * 建立人:lyq * 建立時間:2017-9-13 下午12:49:52 * 修改備註: * @version * */ @Controller @RequestMapping("/echarts") public class EchartsController { private static final Logger logger = LoggerFactory.getLogger(EchartsController.class); @RequestMapping(value="/viewEcharts") @ResponseBody public Map<String, Object> echartsMap(HttpServletRequest request, HttpServletResponse response) { Map<String, Object> map = new HashMap<String, Object>(); map.put("category", new String[]{"70年代人數","80年代人數","90年代人數","00年代人數"}); map.put("child", new int[] {10000,20000,30000,40000}); map.put("old", new int[] {30000,25000,20000,15000}); map.put("man", new int[]{1000000,1500000,1550000,1600000}); return map; } @RequestMapping("/goEchart") public String goEchart(HttpServletRequest request, HttpServletResponse response) { return "/echart"; } /** * 報警分析報表下載 */ @RequestMapping("/exportReport") @ResponseBody public Map<String,String> exportReport(HttpServletResponse response, HttpServletRequest request, String picBase64Info1) { Map<String,String> map = new HashMap(); try { byte[] base64Info1 = decodeBase64(picBase64Info1); XWPFDocument xdoc = new ExportWordUtil().export(base64Info1); Calendar c = Calendar.getInstance(); String fileName = "生成分析報告" + c.get(Calendar.YEAR) + to2String(String.valueOf((c.get(Calendar.MONTH) + 1))) + c.get(Calendar.DAY_OF_MONTH) + c.get(Calendar.HOUR_OF_DAY) + c.get(Calendar.MILLISECOND) + ".docx"; //獲取存放路徑 String classPath = FileUtils.class.getClassLoader().getResource("/").getPath(); String os_name = System.getProperties().get("os.name").toString().toLowerCase(); if (os_name.indexOf("windows") != -1) { classPath = classPath.substring(1, classPath.indexOf("/WEB-INF/classes")) + "/upload/"; } else if (os_name.indexOf("linux") != -1) { classPath = FileUtils.class.getProtectionDomain().getCodeSource().getLocation().getPath(); classPath = "/" + classPath.substring(1, classPath.indexOf("/WEB-INF/")) + "/upload/"; } logger.info("==============report================" + classPath + fileName); FileOutputStream fos = new FileOutputStream(classPath + fileName); xdoc.write(fos); fos.close(); map.put("ret", "/upload/" + fileName); return map; } catch (Exception e) { logger.error(e.getMessage(), e); map.put("ret", "faild"); return map; } } /** * 解析base64,返回圖片所在路徑 * * @param base64Info * @return */ private byte[] decodeBase64(String base64Info) { if (StringUtils.isEmpty(base64Info)) { return null; } BASE64Decoder decoder = new BASE64Decoder(); if (!base64Info.contains("base64,")) return null; String[] arr = base64Info.split("base64,"); // 資料中:data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABI4AAAEsCAYAAAClh/jbAAA // ... 在"base64,"之後的才是圖片資訊 try { return decoder.decodeBuffer(arr[1]); } catch (IOException e) { logger.info(e.getMessage(), e); return null; } } private String to2String(String str) { if (str.length() > 2) { str = str.substring(0, 2); } else { str = "0" + str; } return str; } }
ExportWordUtil.java
/** * */ package com.lyq.util; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy; import org.apache.poi.xwpf.usermodel.*; import org.openxmlformats.schemas.wordprocessingml.x2006.main.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.imageio.stream.FileImageInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.math.BigInteger; import java.text.DecimalFormat; /** * 匯出Excel公共方法 * * @author lyq */ public class ExportWordUtil { private static final Logger logger = LoggerFactory.getLogger(ExportWordUtil.class); /** * 匯出word * @param base64Info1 報表圖片資料 * @return */ public XWPFDocument export(byte[] base64Info1) { try { CustomXWPFDocument xdoc = new CustomXWPFDocument(); // 建立頁首 createCtp(xdoc); // 標題 createTitle(xdoc); XWPFTable dTable = xdoc.createTable(4, 3); createBaseInfoTable(dTable, xdoc, "未來科技", "謝謝儂", "1024", "生成報表201709120056251"); // 標題一、未來科技資料統計分析 createTitle(xdoc, "一、 未來科技資料統計分析"); // 報表資料分析 XWPFTable dataReportTable = xdoc.createTable(4, 2); createDataReportTable(dataReportTable, xdoc, base64Info1); return xdoc; } catch (Exception e) { logger.error(e.getMessage(), e); throw new RuntimeException("生成檔案失敗"); } } /** * 在cell 裡面插入圖片 * @param xdoc * @param paragraph * @param imageByte */ private void createPic(CustomXWPFDocument xdoc, XWPFParagraph paragraph, byte[] imageByte) { try { xdoc.addPictureData(imageByte, XWPFDocument.PICTURE_TYPE_JPEG); } catch (InvalidFormatException e) { e.printStackTrace(); } xdoc.createPicture(paragraph, xdoc.getAllPictures().size() - 1, 300, 200, " "); } // 圖片到byte陣列 public byte[] image2byte(String path) { byte[] data = null; FileImageInputStream input = null; try { input = new FileImageInputStream(new File(path)); ByteArrayOutputStream output = new ByteArrayOutputStream(); byte[] buf = new byte[1024]; int numBytesRead = 0; while ((numBytesRead = input.read(buf)) != -1) { output.write(buf, 0, numBytesRead); } data = output.toByteArray(); output.close(); input.close(); } catch (FileNotFoundException ex1) { ex1.printStackTrace(); } catch (IOException ex1) { ex1.printStackTrace(); } return data; } /** * 建立標題 */ private void createTitle(CustomXWPFDocument xdoc) { // 標題 XWPFParagraph titleMes = xdoc.createParagraph(); titleMes.setAlignment(ParagraphAlignment.CENTER); XWPFRun r1 = titleMes.createRun(); r1.setBold(true); r1.setFontFamily("華文仿宋"); r1.setText("未來科技平臺統計分析報告");// 活動名稱 r1.setFontSize(18); r1.setColor("333333"); r1.setBold(true); } /** * 生成頁首 */ public void createCtp(CustomXWPFDocument document) { CTSectPr sectPr = document.getDocument().getBody().addNewSectPr(); XWPFHeaderFooterPolicy policy = new XWPFHeaderFooterPolicy(document, sectPr); // 新增頁首 CTP ctpHeader = CTP.Factory.newInstance(); CTR ctrHeader = ctpHeader.addNewR(); CTText ctHeader = ctrHeader.addNewT(); String headerText = "我的報表我做主 在我的地盤聽我的"; ctHeader.setStringValue(headerText); XWPFParagraph headerParagraph = new XWPFParagraph(ctpHeader, document); // 設定為左對齊 headerParagraph.setAlignment(ParagraphAlignment.BOTH); XWPFParagraph[] parsHeader = new XWPFParagraph[1]; parsHeader[0] = headerParagraph; try { policy.createHeader(XWPFHeaderFooterPolicy.DEFAULT, parsHeader); } catch (IOException e) { e.printStackTrace(); } } /** * 生成基礎資訊Table * * @param table * @param xdoc */ public void createBaseInfoTable(XWPFTable table, CustomXWPFDocument xdoc, String dateStr, String unitName, String machineNum, String reportNo) { String bgColor = "111111"; CTTbl ttbl = table.getCTTbl(); CTTblPr tblPr = ttbl.getTblPr() == null ? ttbl.addNewTblPr() : ttbl.getTblPr(); CTTblWidth tblWidth = tblPr.isSetTblW() ? tblPr.getTblW() : tblPr.addNewTblW(); tblWidth.setW(new BigInteger("8600")); tblWidth.setType(STTblWidth.AUTO); // STTblWidth.AUTO 自動長度 mergeCellsVertically(table, 0, 0, 3); setCellText(xdoc, getCellHight(table, 0, 0, 2400), "基 礎 信 息", bgColor, 600, 14, "仿宋"); setCellText(xdoc, getCellHight(table, 0, 1, 600), "報告週期", bgColor, 1800, 14, "仿宋"); setCellText(xdoc, getCellHight(table, 0, 2, 600), dateStr, bgColor, 6200, 14, "仿宋"); setCellText(xdoc, getCellHight(table, 1, 1, 600), "單位名稱", bgColor, 1800, 14, "仿宋"); if (unitName == null) unitName = ""; setCellText(xdoc, getCellHight(table, 1, 2, 600), unitName, bgColor, 6200, 14, "仿宋"); setCellText(xdoc, getCellHight(table, 2, 1, 600), "主機數量", bgColor, 1800, 14, "仿宋"); setCellText(xdoc, getCellHight(table, 2, 2, 600), machineNum, bgColor, 6200, 14, "仿宋"); setCellText(xdoc, getCellHight(table, 3, 1, 600), "報告編號", bgColor, 1800, 14, "仿宋"); setCellText(xdoc, getCellHight(table, 3, 2, 600), reportNo, bgColor, 6200, 14, "仿宋"); } /** * 生成標題 * * @param xdoc * @param titleText */ public void createTitle(CustomXWPFDocument xdoc, String titleText) { XWPFParagraph headLine2 = xdoc.createParagraph(); headLine2.setAlignment(ParagraphAlignment.CENTER); XWPFRun runHeadLine2 = headLine2.createRun(); runHeadLine2.setText(titleText); runHeadLine2.setFontSize(16); runHeadLine2.setFontFamily("華文仿宋"); runHeadLine2.setBold(true); runHeadLine2.setColor("333333"); } /** * 報表資料分析 * * @param table * @param xdoc */ public void createDataReportTable(XWPFTable table, CustomXWPFDocument xdoc, byte[] base64Info1) { String bgColor = "111111"; CTTbl ttbl = table.getCTTbl(); CTTblPr tblPr = ttbl.getTblPr() == null ? ttbl.addNewTblPr() : ttbl.getTblPr(); CTTblWidth tblWidth = tblPr.isSetTblW() ? tblPr.getTblW() : tblPr.addNewTblW(); tblWidth.setW(new BigInteger("8600")); tblWidth.setType(STTblWidth.AUTO); // STTblWidth.AUTO 自動長度 // mergeCellsVertically(table, 0, 0, 3); mergeCellsHorizontal(table, 0, 0, 1); String str = ""; Double sss = 0.6666666666666666; DecimalFormat df = new DecimalFormat("0.00"); str = "(一)報告時間內誤報率"+df.format((sss * 100))+"%"; setCellText(xdoc, getCellHight(table, 0, 0, 1200), str, bgColor, 8600, 14, "仿宋"); setCellText(xdoc, getCellHight(table, 1, 0, 1200), "報表資料", bgColor, 4300, 14, "仿宋"); setCellText(xdoc, getCellHight(table, 1, 1, 1200), "報表資料", bgColor, 4300, 14, "仿宋"); // 自動報警數量環比 報表 if(base64Info1 == null || base64Info1.length < 100){ setCellText(xdoc, getCellHight(table, 2, 0, 1200), "暫無資料", bgColor, 4300, 14, "仿宋"); } else { setCellPic(xdoc, getCellHight(table, 2, 0, 1200), base64Info1); } // 自動報警數量同比 報表 if(base64Info1 == null || base64Info1.length < 100){ setCellText(xdoc, getCellHight(table, 2, 1, 1200), "暫無資料", bgColor, 4300, 14, "仿宋"); } else { setCellPic(xdoc, getCellHight(table, 2, 1, 1200), base64Info1); } mergeCellsHorizontal(table, 3, 0, 1); setCellText(xdoc, getCellHight(table, 3, 0, 1200), "資料彙總\n1:@@@@@@@@@@@@@@@@@@@@@\n2!!!!!!!!!!!!!!!!!!!!!!!!", bgColor, 4300, 14, "仿宋", ParagraphAlignment.LEFT,true); } // 設定表格高度 private XWPFTableCell getCellHight(XWPFTable xTable, int rowNomber, int cellNumber, int hight) { XWPFTableRow row = null; row = xTable.getRow(rowNomber); row.setHeight(hight); XWPFTableCell cell = null; cell = row.getCell(cellNumber); cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER); return cell; } /** * 建立圖片 */ private void setCellPic(CustomXWPFDocument xdoc, XWPFTableCell cell, byte[] imageByte) { createPic(xdoc, cell.addParagraph(), imageByte); } private void setCellText(CustomXWPFDocument xDocument, XWPFTableCell cell, String text, String bgcolor, int width, int fontSize, String textType) { setCellText(xDocument, cell, text, bgcolor, width, fontSize, textType, ParagraphAlignment.CENTER); } /** * * @param xDocument * @param cell * @param text * @param bgcolor * @param width */ private void setCellText(CustomXWPFDocument xDocument, XWPFTableCell cell, String text, String bgcolor, int width, int fontSize, String textType, ParagraphAlignment align) { setCellText(xDocument, cell, text, bgcolor, width, fontSize, textType, align, false); } private void setCellText(CustomXWPFDocument xDocument, XWPFTableCell cell, String text, String bgcolor, int width, int fontSize, String textType, ParagraphAlignment align, boolean isBold) { CTTc cttc = cell.getCTTc(); CTTcPr cellPr = cttc.addNewTcPr(); cellPr.addNewTcW().setW(BigInteger.valueOf(width)); XWPFParagraph pIO = cell.addParagraph(); if (null == align) { pIO.setAlignment(ParagraphAlignment.CENTER); } else { pIO.setAlignment(align); } cell.removeParagraph(0); if (text.contains("\n")) { String[] myStrings = text.split("\n"); for (int i = 0; i < myStrings.length; i++) { String temp = myStrings[i]; if (isBold) { if (i == 0) { setTextStyle(pIO, textType, bgcolor, fontSize, temp, true, true); } else { setTextStyle(pIO, textType, bgcolor, fontSize, " " + temp, true, false); } } else { setTextStyle(pIO, textType, bgcolor, fontSize, temp, true, false); } } } else { setTextStyle(pIO, textType, bgcolor, fontSize, text, false, false); } } private void setTextStyle(XWPFParagraph pIO, String textType, String bgcolor, int fontSize, String text, boolean isEntery, boolean isBold) { XWPFRun rIO = pIO.createRun(); if (textType == null || textType.equals("")) { rIO.setFontFamily("微軟雅黑"); } else { rIO.setFontFamily(textType); } if (bgcolor == null || bgcolor.equals("")) { rIO.setColor("000000"); } else { rIO.setColor(bgcolor); } rIO.setFontSize(fontSize); rIO.setText(text); if (isBold) rIO.setBold(true); if (isEntery) rIO.addBreak(); } // 設定表格間的空行 public void setEmptyRow(CustomXWPFDocument xdoc, XWPFRun r1) { XWPFParagraph p1 = xdoc.createParagraph(); p1.setAlignment(ParagraphAlignment.CENTER); p1.setVerticalAlignment(TextAlignment.CENTER); r1 = p1.createRun(); } // word跨列合併單元格 public void mergeCellsHorizontal(XWPFTable table, int row, int fromCell, int toCell) { for (int cellIndex = fromCell; cellIndex <= toCell; cellIndex++) { XWPFTableCell cell = table.getRow(row).getCell(cellIndex); if (cellIndex == fromCell) { // The first merged cell is set with RESTART merge value cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART); } else { // Cells which join (merge) the first one, are set with CONTINUE cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.CONTINUE); } } } // word跨行並單元格 public void mergeCellsVertically(XWPFTable table, int col, int fromRow, int toRow) { for (int rowIndex = fromRow; rowIndex <= toRow; rowIndex++) { XWPFTableCell cell = table.getRow(rowIndex).getCell(col); if (rowIndex == fromRow) { // The first merged cell is set with RESTART merge value cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.RESTART); } else { // Cells which join (merge) the first one, are set with CONTINUE cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.CONTINUE); } } } }
CustomXWPFDocument.java
package com.lyq.util;
/**
* Created by lyq on 2017/9/7.
* POI 匯出圖片bug修復
*/
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlToken;
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline;
import java.io.IOException;
import java.io.InputStream;
/**
*
*/
public class CustomXWPFDocument extends XWPFDocument {
public CustomXWPFDocument(InputStream in) throws IOException {
super(in);
}
public CustomXWPFDocument() {
super();
}
/**
* @param pkg
* @throws IOException
*/
public CustomXWPFDocument(OPCPackage pkg) throws IOException {
super(pkg);
} // picAttch 圖片後面追加的字串 可以是空格
public void createPicture(XWPFParagraph paragraph,int id, int width, int height,String picAttch) {
final int EMU = 9525;
width *= EMU;
height *= EMU;
String blipId = getAllPictures().get(id).getPackageRelationship()
.getId();
CTInline inline = paragraph.createRun().getCTR()
.addNewDrawing().addNewInline();
paragraph.createRun().setText(picAttch);
String picXml = ""
+ "<a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\">"
+ " <a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">"
+ " <pic:pic xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">"
+ " <pic:nvPicPr>" + " <pic:cNvPr id=\""
+ id
+ "\" name=\"Generated\"/>"
+ " <pic:cNvPicPr/>"
+ " </pic:nvPicPr>"
+ " <pic:blipFill>"
+ " <a:blip r:embed=\""
+ blipId
+ "\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"/>"
+ " <a:stretch>"
+ " <a:fillRect/>"
+ " </a:stretch>"
+ " </pic:blipFill>"
+ " <pic:spPr>"
+ " <a:xfrm>"程式碼下載地址
+ " <a:off x=\"0\" y=\"0\"/>"
+ " <a:ext cx=\""
+ width
+ "\" cy=\""
+ height
+ "\"/>"
+ " </a:xfrm>"
+ " <a:prstGeom prst=\"rect\">"
+ " <a:avLst/>"
+ " </a:prstGeom>"
+ " </pic:spPr>"
+ " </pic:pic>"
+ " </a:graphicData>" + "</a:graphic>";
inline.addNewGraphic().addNewGraphicData();
XmlToken xmlToken = null;
try {
xmlToken = XmlToken.Factory.parse(picXml);
} catch (XmlException xe) {
xe.printStackTrace();
}
inline.set(xmlToken);
// graphicData.set(xmlToken);
inline.setDistT(0);
inline.setDistB(0);
inline.setDistL(0);
inline.setDistR(0);
CTPositiveSize2D extent = inline.addNewExtent();
extent.setCx(width);
extent.setCy(height);
CTNonVisualDrawingProps docPr = inline.addNewDocPr();
docPr.setId(id);
docPr.setName("圖片" + id);
docPr.setDescr("");
}
}
echar.jsp程式碼:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<html>
<head>
<link type="text/css" rel="stylesheet" media="all" href="<%=path %>/static/styles/styles.css" />
<script type="text/javascript" src="<%=path %>/js/jquery-3.2.1.min.js"></script>
<script type="text/javascript" src="<%=path %>/js/echarts.min.js"></script>
</head>
<style>
*{
margin:0px;
padding:0px;
}
#form {
padding-top:600px;
width:400px;
height:500px;
}
#btn {
padding:8px 20px;
color:#fff;
background:#141414;
border-radius:4px;
transition: all 1s ease;
}
#btn:hover{
background:#60c;transition: all 1s ease;
}
</style>
<body>
<!-- 為ECharts準備一個具備大小(寬高)的Dom -->
<div id="echart" style="height:400px;width:500px">
<h1>歡迎來到echart首頁</h1>
</div>
<input type ="button" value="下載" onclick="fn()"/>
<!-- ECharts單檔案引入 -->
</body>
<script type="text/javascript">
var myChart ;
$(function(){
//獲得後臺資料
var category;//年代
var child;//孩子
var old;//老人
var man;//大人
$.ajax({
url:'<%=path%>/echarts/viewEcharts.html',
async:false,
dataType: "json",
cache: false,
success: function(data){
category=data.category;
child=data.child;
old=data.old;
man=data.man;
// 基於準備好的dom,初始化echarts圖表
myChart = echarts.init(document.getElementById('echart'),"echart");
var option = {
tooltip: {//提示框,滑鼠懸浮互動時的資訊提示
show: true
},
toolbox:{//定義工具按鈕
show : true,
feature : {
dataView : {show: true, readOnly: false},//資料資訊按鈕
magicType : {show: true, //顯示折線、柱狀圖等切換按鈕
type: ['line', 'bar','stack', 'tiled']}
}
},
legend: {//圖例
data:['孩子','老人','大人']
},
xAxis : [//x軸設定
{
type : 'category',//x軸顯示類別
data : category//年代
}
],
yAxis : [//y軸設定
{
type : 'value'///y軸顯示資料值
}
],
series : [
{
"name":"孩子",
"type":"bar",
"data":child
},
{
"name":"老人",
"type":"bar",
"data":old
},
{
"name":"大人",
"type":"bar",
"data":man
}
]
};
// 為echarts物件載入資料
myChart.setOption(option);
}
})
});
function fn () {
var data = {};
data.picBase64Info1 = myChart.getDataURL();
$.ajax({
url:'<%=path%>/echarts/exportReport.html',
type:"post",
data:data,
dataType:"json",
success:function(data1){
if('faild' == data1.ret){
alert('下載失敗請重試...');
}else{
window.location.href = '../'+data1.ret;
}
}
});
}
// function down(ec){
// var data={};
// var myChart = ec.init(document.getElementById('echart'),"dark");
//
// }
</script>
</html>
主要程式碼如上所示,沒有啥好說的,沒啥難得,看看例子就能明白。