1.html上的Table跟Chart的導出(後臺使用ssm框架)

最近在工做中遇到的一個問題,要將html標籤裏的Table跟echarts生成報表導出到excel裏面,沒有搞過各類谷歌!-_-,還好解決了,就分享一下此次踩坑的經驗了.html

所使用的jar包:前端

commons-codec-1.9.jar
commons-lang3-3.3.2.jar
jsoup-1.8.3.jar
poi-3.9.jar
slf4j-api-1.7.7.jar
slf4j-simple-1.7.7.jar
table-to-xls-0.0.1-RELEASE.jar//這個能夠在oscchina的git上找到的謝謝大神的代碼了


首先說一說實現的思路:java

  1. 前端用jquery獲取Table標籤的內容跟echarts報表的圖片的base64----->2.ajax的post傳輸數據到後臺----->3將獲取到的數據分別處理,表格生成excel再將base64還原成圖片插入到生成的excel裏面jquery

具體實現:git

第一步:ajax

        首先說明一下echarts在生成圖表以前都要先初始化一個東西因此base64能夠根據這個來獲取json

var showCharts=[];//這是個全局變量用來接收每一個chart對象的

//在每一個chart初始化的時候將初始化的對象放進數組
var myChart = echarts.init(document.getElementById(tagid));
showCharts.push(myChart);

第二步:經過頁面上的一個按鈕觸發一個函數(click事件)
api

function export2Excel(tableId){
   var tableContext =$("#"+tableId).html();
   var datas={}
   if(tableContext.length>37){//這裏爲何判斷長度大於37由於表格動態生成的默認長度就有36!!:)
     tableContext="<table>"+tableContext+"</table>";
     datas.tableContext=tableContext;
   }
	  	
   if(showCharts.length!=0){
	 var imgUrls = [];
	 for(var x  =0; x<showCharts.length;x++){
	   imgUrls.push(showCharts[x].getDataURL("png"));
	 }
	datas.imgUrls=imgUrls;
    }
	  	
   if(datas.tableContext){
	 $.ajax({
	    url:url,//發送到後臺處理這些數據的控制器地址(這個只是負責發送數據到後臺)
	    type: "POST",
	    dataType: "json",
	    data: $.param(datas,true),//發送數組這樣的數據格式必用這個東西否則極可能出問題
	    success: function (result) {
	      if(parseInt(result.status)==0){
		 location.href=url+fileName//用來處理下載請求的控制器地址跟下載的文件名,爲啥要有這一步呢由於ajax不支持下載的瀏覽器是彈不出那個保存文件的框的(有沒有草泥馬)
	      }
	    },
	    failure: function (err) {
		 alert("ajax產生了錯誤!");
	     }
	   });
	 }else{
	    alert("必須有表格或者圖表才能下載");
	  }

第三步:後臺處理數組

//這個控制器是用來預處理ajax的post請求提交過來的數據的
@RequestMapping(value = "preExportToExcel",method=RequestMethod.POST)
@ResponseBody
public  AjaxData<Map<String,String>> preExportToExcel(String tableContext, String[] imgUrls,HttpServletRequest req,HttpServletResponse rep) throws Exception {
      AjaxData<Map<String,String>> ajax = new AjaxData<Map<String,String>>();
      tableContext=HtmlUtils.htmlUnescape(tableContext);
      String filePath=req.getSession().getServletContext().getRealPath("/")+"temp";
      filePath = filePath.replace("\\","/")+"/";
      HtmlTableToExcel html = new HtmlTableToExcel(imgUrls, filePath, tableContext);//這個對象會將傳遞過來的數據生成excel
      String xlsFileName = html.mergePicAndExcel();
      Map<String,String> map = new HashMap<String,String>();
      map.put("xlsFileName", xlsFileName);
      ajax.setData(map);
      return ajax;
}

//這個控制器纔是真正的下載控制器對應ajax裏面的location.href那句代碼
//採用servlet這種方式下載的緣由就是能夠在下載完成的時候能夠將文件刪掉
@RequestMapping(value = "exportToExcel",method=RequestMethod.GET)
@ResponseBody
public void exportToExcel(String xlsFileName, HttpServletResponse rep) throws Exception {
		OutputStream out = null;
		try {
			rep.reset();
			rep.setContentType("application/vnd.ms-excel");
			rep.setHeader("Content-Disposition","attachment; filename=" + xlsFileName.substring(xlsFileName.lastIndexOf("/") + 1));
			out = rep.getOutputStream();
			System.out.println(xlsFileName);
			out.write(FileUtils.readFileToByteArray(new File(xlsFileName)));
			out.flush();
			File file = new File(xlsFileName.substring(0,xlsFileName.lastIndexOf("/")));
			File[] files= file.listFiles();
			for (File file2 : files) {
				FileUtils.deleteFile(file2.getAbsolutePath());
			}
		} catch (IOException e) {
			throw new RuntimeException(e.getMessage() + "文件下載失敗");
		} finally {
			if (out != null) {
				try {
					out.close();
				} catch (IOException e) {
					throw new RuntimeException(e.getMessage() + "文件下載失敗");
				}
			}
		}
	}

所用類的代碼:瀏覽器

值得注意的是圖片的後綴名必須是.png結尾的額否則透明背景的圖片插入到excel裏面是要變成黑乎乎的

/**
 * 將圖片的base64碼解密並還原圖片(只支持支持格式"png","jpg",支持多張圖片)
 *
 */
public class Base64ToImage {
 /**
  * Logger for this class
  */
 private static final Logger logger = Logger.getLogger(Base64ToImage.class);
 
 /**
  * 枚舉類用來選擇模式
  *
  */
 public static enum PictureType {
 //png的圖片類型
 TYPE_PNG,TYPE_JPG;
 }
 
 /**
  * 
  * @param imgUrls  多張圖片的base64碼組
  * @param filePath 保存文件的路徑
  * @param type     生成文件的模式
  * @return         返回生成的圖片的名字
  */
 public static List<String> base64ToPicture(String[] imgUrls,String filePath,Base64ToImage.PictureType type){
 String suffix="";
 
 //判斷傳入的圖片類型
 if(type==PictureType.TYPE_PNG) suffix=suffix+".png";
 if(type==PictureType.TYPE_JPG) suffix=suffix+".jpg";
 
 //判斷空值以及0值
 if(imgUrls.length==0||imgUrls==null||StringUtils.isBlank(filePath)){
 return null;
 }
 
 List<String> fileNameList= new ArrayList<String>();
 for (String imgUrl : imgUrls) {
 String fileName = UUID.randomUUID().toString();
 String realFileName=filePath+fileName;
 if(isCreatePic(imgUrl, realFileName,suffix)) fileNameList.add(fileName+suffix);
 logger.info(fileName);
 }
 return fileNameList;
 }
 /**
  * 
  * @param imgsURl 圖片的base64碼
  * @param fileName 圖片名稱
  * @return 是否生成圖片成功
  */
 private static boolean isCreatePic(String imgsURl, String fileName,String suffix){
 BASE64Decoder decoder = new BASE64Decoder();
 boolean flag = true;
 OutputStream out=null;
 try {
 String[] url = imgsURl.split(",");
 String u = url[1];
 // Base64解碼
 byte[] buffer = new BASE64Decoder().decodeBuffer(u);
 // 生成圖片
 out= new FileOutputStream(new File(fileName + suffix));
 out.write(buffer);
 out.flush();
 } catch (Exception e) {
 flag = false;
 }finally{
 try {
 if(out!=null)out.close();
 } catch (IOException e) {
 flag=false;
 }
 }
 return flag;
 }
}
  

 // 將頁面上的html 表格導出(支持頁面上的報表圖片導出,只支持單表的導出,只支持png格式圖片插入)
public class HtmlTableToExcel {
 private static final Logger logger = Logger.getLogger(HtmlTableToExcel.class);
 
 //圖片的base64碼
 private String[] imgUrls;
 
 //存放生成文件的路徑
 private String filePath;
 
 //生成的文件名字
// private String fileName=UUID.randomUUID().toString();
 
 private String tableContext;

 public HtmlTableToExcel(String[] imgUrls,String filePath, String tableContext) {
 this.imgUrls = imgUrls;
 this.tableContext = tableContext;
 this.filePath=filePath;
 }
 
 public String createExcel(){
 FileOutputStream fout=null;
 try {
 String xlsFileName =this.filePath+UUID.randomUUID().toString()+".xls";
 fout = new FileOutputStream(xlsFileName);
 TableToXls.process(tableContext, fout);
 return xlsFileName;
 } catch (FileNotFoundException e) {
 e.printStackTrace();
 }finally{
 try {
 if(fout!=null)fout.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 return null;
 }
 
 public String mergePicAndExcel(){
 String xlsFileName=createExcel();
 if(imgUrls!=null){
 List<String>fileNames = Base64ToImage.base64ToPicture(this.imgUrls, this.filePath, PictureType.TYPE_PNG);
 for(int x = 0;x < fileNames.size();x++){
 drawPiceToExcel(xlsFileName, this.filePath+fileNames.get(x),x);
 }
 }
 return xlsFileName;
 }
 
 private void drawPiceToExcel(String xlsFileName,String picFileName,int position){
 FileOutputStream fileOut = null;
 BufferedImage bufferImg = null;
 FileInputStream in = null;
 Workbook wb = null;
 try {

 // 先把讀進來的圖片放到一個ByteArrayOutputStream中,以便產生ByteArray
 ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
 bufferImg = ImageIO.read(new File(picFileName));
 ImageIO.write(bufferImg, "png", byteArrayOut);

 // 打開一個工做薄
 in = new FileInputStream(xlsFileName);
 POIFSFileSystem fs = new POIFSFileSystem(in);
 wb = new HSSFWorkbook(fs);
 HSSFSheet sheet = (HSSFSheet) wb.getSheetAt(0);
 HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
 HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 1023, 100, (short) 0, sheet.getLastRowNum()+5*position+27*position,
 (short) (sheet.getRow(0).getPhysicalNumberOfCells()+8), sheet.getLastRowNum()+5*position+27*(position+1));
 // 插入圖片
patriarch.createPicture(anchor,wb.addPicture(byteArrayOut.toByteArray(),HSSFWorkbook.PICTURE_TYPE_JPEG));

 fileOut = new FileOutputStream(xlsFileName);
 // 寫入excel文件
 wb.write(fileOut);
 fileOut.close();

 } catch (IOException io) {
 throw new RuntimeException(io.getMessage()+"讀取文件出問題");
 } finally {
 if (fileOut != null) {
 try {
 fileOut.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 }
 }
}
相關文章
相關標籤/搜索