整合營(yíng)銷(xiāo)服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          開(kāi)源easyHtml-導(dǎo)出html表格文件

          接上篇文章,導(dǎo)出html文件,我對(duì)這部分代碼進(jìn)行優(yōu)化,提交到github上,為初始版本,后面根據(jù)用戶需求與討論,會(huì)不斷更新優(yōu)化功能

          介紹

          • 功能

          導(dǎo)出Html 表格文件,簡(jiǎn)單易用

          • 地址

          https://github.com/CollectBugs/EasyHtml

          • 項(xiàng)目展示



          總結(jié)

          開(kāi)發(fā)此項(xiàng)目的靈感來(lái)源于一次項(xiàng)目開(kāi)發(fā),發(fā)現(xiàn)導(dǎo)出html表格文件需求,比較常見(jiàn),市面上開(kāi)源、成熟、免費(fèi)的方案沒(méi)有,如果每一家公司,都從零開(kāi)始開(kāi)發(fā),耗時(shí)又費(fèi)力,導(dǎo)致開(kāi)發(fā)周期變長(zhǎng),不如大家開(kāi)源共建此項(xiàng)目,讓后來(lái)人站在巨人的肩膀上進(jìn)行開(kāi)發(fā)與維護(hù),共享資源,其樂(lè)而不為,希望大家多多給與關(guān)注與討論哦!

          每天不斷更,精彩不停止,明天見(jiàn),我是行者

          記得留個(gè)關(guān)注、點(diǎn)贊、評(píng)論喲,讓我們一起去看星辰大海,品味代碼人生

          持原創(chuàng),共同進(jìn)步!請(qǐng)關(guān)注我,后續(xù)分享更精彩!

          概述

          項(xiàng)目中經(jīng)常有生成圖表報(bào)告的需求。實(shí)現(xiàn)的方式有很多,下面幾種方案,各有優(yōu)缺點(diǎn)。

          純java后端實(shí)現(xiàn):后端JFreeChart等繪制庫(kù)畫(huà)好圖表,再通過(guò)itext庫(kù)導(dǎo)出為pdf。該方案能實(shí)現(xiàn)簡(jiǎn)單的圖表功能,樣式、格式調(diào)整等可能會(huì)花大量時(shí)間。適合中小型報(bào)表開(kāi)發(fā)項(xiàng)目。

          前端繪制圖表,后端運(yùn)行時(shí)命令調(diào)用wkhtmltopdf生成pdf:后端通過(guò)運(yùn)行時(shí)命令調(diào)用node js,js使用wkhtmltopdf庫(kù)動(dòng)態(tài)訪問(wèn)報(bào)表url地址,HTML內(nèi)容渲染完成后生成pdf文件。該方案,使用純前端js繪制圖表,能實(shí)現(xiàn)復(fù)雜需求。但wkhtmltopdf庫(kù)對(duì)不同瀏覽器的js存在兼容性問(wèn)題,導(dǎo)出成pdf文件時(shí)存在各種坑,在單頁(yè)面技術(shù)支持還不太成熟。適合豐富報(bào)表的pdf導(dǎo)出,但兼容性問(wèn)題維護(hù)成本太高。

          前端繪制圖表,后端運(yùn)行時(shí)命令調(diào)用puppeteer生成pdf:后端通過(guò)運(yùn)行時(shí)命令調(diào)用node js,js使用puppeteer庫(kù)動(dòng)態(tài)訪問(wèn)報(bào)表url地址,HTML內(nèi)容渲染完成后生成pdf文件。該方案和wkhtmltopdf方案類(lèi)似,但兼容性更好。puppeteer是 Chrome 開(kāi)發(fā)團(tuán)隊(duì)在 2017 年發(fā)布的一個(gè) Node.js 包,用來(lái)模擬 Chrome 瀏覽器的運(yùn)行。可以在無(wú)界面的環(huán)境中運(yùn)行Chrome或通過(guò)命令行、程序語(yǔ)言操作 Chrome。理論上Chrome中顯示的圖表,就能通過(guò)該庫(kù)生成一致的pdf文件內(nèi)容,不用浪費(fèi)很多時(shí)間在頁(yè)面樣式和兼容性問(wèn)題上。

          本文選擇puppeteer方案介紹如何生成一個(gè)pdf報(bào)表。細(xì)心的小伙伴可能注意到了,既然puppeteer是js庫(kù),為什么不直接前端導(dǎo)出pdf,干嘛這么麻煩還通過(guò)后端繞一圈來(lái)實(shí)現(xiàn)?

          這主要出于需求和用戶體驗(yàn)的考慮,有些業(yè)務(wù)場(chǎng)景需要通過(guò)api接口動(dòng)態(tài)生成pdf報(bào)表,不需要用戶訪問(wèn)界面。如果生成的pdf的報(bào)表很大,直接在用戶端生成,可能占用大量客戶端資源,導(dǎo)致頁(yè)面崩潰或假死,從而影響使用體驗(yàn)。

          實(shí)現(xiàn)

          1.先安裝NodeJs,網(wǎng)上教程很多,本文不再贅述。

          2.安裝puppeteer依賴(lài),如果npm下載不成功就使用cnpm命令(cnpm需要先安裝)

          npm install puppeteer --save

          3.在安裝puppeteer依賴(lài)的目錄下創(chuàng)建page2pdf.js

          const puppeteer = require('puppeteer');
          const options = process.argv;
          var siteUrl;
          //執(zhí)行 node page2pdf.js https://www.baidu.com
          
          (async() => {
          if(options.length>=3){
              siteUrl=options[2];
              //types=options[3];
          	//console.log(siteUrl);
          }
          
          const browser = await puppeteer.launch();
          const page = await browser.newPage();
          
          //console.log(options.length);
          //console.log(options[0]);
          //console.log(options[1]);
          //console.log(options[2]);
          //console.log(options[3]);
          
          const userAgent = "Mozilla/5.0 (Linux; Android 8.1.0; MI 8 Build/OPM1.171019.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/62.0.3202.84 Mobile Safari/537.36";
          page.setUserAgent(userAgent);
          
          await page.setViewport({ width: 1000, height: 1080 });
          
          //await page.setViewport({ width: 480, height: 800,isMobile: true}); 
          
          //通過(guò)css樣式可見(jiàn),動(dòng)態(tài)設(shè)置站點(diǎn)加載完成標(biāo)識(shí)。
          //page.waitForSelector('img').then(() => console.log('siteUrl with page load success: ' + siteUrl));
          
          await page.goto(siteUrl, {timeout: 10*60000, waitUntil: 'networkidle2'});
          
          /**await page.goto(siteUrl, {timeout: 10*60000, waitUntil: 'networkidle2'})
          			.catch(e => {
          			  console.log(siteUrl+" is error:"+e);
          			  browser.close()
          			});*/
          
          const pdf = await page.pdf({
          		path: 'page.pdf', //便于測(cè)試驗(yàn)證,實(shí)際使用時(shí)可屏蔽
          		format: 'A4'
          	});
          	
          await browser.close();
          process.stdout.write(pdf);
          })();

          page2pdf.js文件引入puppeteer依賴(lài)庫(kù),通過(guò)傳入siteUrl參數(shù)訪問(wèn)HTML page頁(yè)面,page.pdf生成文件,再通過(guò)process.stdout.write(pdf)返回java后臺(tái)。

          4.創(chuàng)建java PuppeteerHtmlToPdf.java文件

          /**
           * 用谷歌提供的node實(shí)現(xiàn)的Puppeteer,實(shí)現(xiàn)網(wǎng)頁(yè)生成pdf文件
           */
          public class PuppeteerHtmlToPdf {
              /**
               * html轉(zhuǎn)pdf,直接通過(guò)流輸出到瀏覽器
               * @param response 瀏覽器響應(yīng)
               * @param fileName 文件名稱(chēng)
               * @param puppeteerjs 要采用哪個(gè)js文件執(zhí)行
               * @param webSiteUrl 要生成pdf的網(wǎng)頁(yè)
               */
              public static void parseHtml2Pdf(HttpServletResponse response, String fileName, String puppeteerjs, String webSiteUrl) {
                  try {
                      Runtime rt = Runtime.getRuntime();
                      Process p = rt.exec("node "+puppeteerjs+" "+webSiteUrl);
                      InputStream is = p.getInputStream();
                      BufferedInputStream bf=new BufferedInputStream(is);
                      byte[] data = IOUtils.toByteArray(bf);
                      fileName = URLEncoder.encode(fileName, "UTF-8");
                      response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
                      response.addHeader("Content-Length", "" + data.length);
                      response.setContentType("application/octet-stream;charset=UTF-8");
                      OutputStream outputStream = new BufferedOutputStream(response.getOutputStream());
                      outputStream.write(data);
                      outputStream.flush();
                      outputStream.close();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
          
              }
          }

          5.報(bào)表生成

          page2pdf.js頁(yè)面目錄打開(kāi)命令行,執(zhí)行指令。


          運(yùn)行指令,生成pdf

          node page2pdf.js https://www.baidu.com


          查看對(duì)應(yīng)目錄,已動(dòng)態(tài)生成了一個(gè)page.pdf文件


          打開(kāi)pdf文件,對(duì)應(yīng)HTML內(nèi)容已生成。

          小結(jié)

          本文介紹了報(bào)表導(dǎo)出pdf的3種方式,通過(guò)優(yōu)缺點(diǎn)分析,詳細(xì)闡述了puppeteer的實(shí)現(xiàn)方式。并通過(guò)百度頁(yè)面的pdf導(dǎo)出做了演示。

          希望本文對(duì)有類(lèi)似報(bào)表pdf導(dǎo)出需求的小伙伴有所參考和幫助。若存在不足或更好方案,請(qǐng)留言討論。

          數(shù)據(jù)分析中,將數(shù)據(jù)以表格的形式呈現(xiàn)出來(lái)是必不可少的環(huán)節(jié),Pandas 是一個(gè)非常強(qiáng)大的數(shù)據(jù)分析庫(kù),提供了很多方便的方法來(lái)處理和展示數(shù)據(jù)。今天,我們將學(xué)習(xí)如何使用 Pandas 自定義表格樣式并將其導(dǎo)出為 HTML 格式。

          通過(guò)這種方式,我們可以更好地組織和展示數(shù)據(jù),并在網(wǎng)頁(yè)上共享我們的分析結(jié)果,并且,掌握Pandas數(shù)據(jù)存儲(chǔ)和表格樣式自定義的方式,在日常工作過(guò)程中有更多應(yīng)用和實(shí)踐意義,將拓展我們的數(shù)據(jù)分析思路。

          導(dǎo)入數(shù)據(jù)

          首先,導(dǎo)入pandas庫(kù),并為其設(shè)置別名pd,使用pandas的read_excel函數(shù)讀取指定路徑下的Excel文件,并將其內(nèi)容存儲(chǔ)在DataFrame對(duì)象df中。

          import pandas as pd
          
          df = pd.read_excel(r'C:\Users\shangtianqiang\Desktop\2023年胡潤(rùn)百富榜.xlsx')
          #默認(rèn)顯示DataFrame的前五行。
          df.head()

          df.info()顯示DataFrame的簡(jiǎn)要信息,包括索引、列名、數(shù)據(jù)類(lèi)型和每列的非空值數(shù)量,這里顯示該數(shù)據(jù)表含有1241行數(shù)據(jù)。

          #數(shù)據(jù)預(yù)覽
          df.info()

          使用iloc方法篩選DataFrame的前100行數(shù)據(jù)。

          df=df.iloc[:100,:]#篩選前100行數(shù)據(jù)
          df

          自定義樣式

          定義一個(gè)樣式對(duì)象style,該對(duì)象用于生成HTML的樣式,這里對(duì)篩選出來(lái)的前100行的數(shù)據(jù)進(jìn)行了樣式設(shè)置,它定義了一個(gè)居中的標(biāo)題(h1標(biāo)簽),一個(gè)表格(table標(biāo)簽),以及表格中的表頭(th標(biāo)簽)和單元格(td標(biāo)簽)。

          • h1 標(biāo)簽:文本居中,字體大小為24像素,下邊距為10像素;
          • table 標(biāo)簽:邊框合并(border-collapse: collapse;),寬度為100%;
          • th, td 標(biāo)簽:邊框?yàn)?像素的實(shí)線,內(nèi)邊距為8像素,文本居中;
          • th 標(biāo)簽:背景顏色為淺灰色(#f2f2f2)。
          # 定義CSS樣式,添加標(biāo)題“2023年胡潤(rùn)百富榜”  
          style = """  
          <style> 
          h1 {  
              text-align: center;  
              font-size: 24px;  
              margin-bottom: 10px;  
          }  
          table {  
              border-collapse: collapse;  
              width: 100%;  
          }  
          th, td {  
              border: 1px solid black;  
              padding: 8px;  
              text-align: center;  
          }  
          th {  
              background-color: #f2f2f2;  
          }  
          </style>  
          <head><title>2023年胡潤(rùn)百富榜</title></head>
          <h1>2023年胡潤(rùn)百富榜</h1> 
          """  

          將DataFrame轉(zhuǎn)換為HTML代碼,并添加樣式,index=False來(lái)去除行索引 。

          # 將DataFrame轉(zhuǎn)換為HTML代碼,并添加樣式  
          html = style + df.to_html(index=False)  # 使用index=False來(lái)避免顯示行索引 

          將生成的HTML內(nèi)容寫(xiě)入到名為'2023年胡潤(rùn)百富榜.html'的文件中。

          # 將HTML代碼寫(xiě)入文件或打印到控制臺(tái)  
          with open('2023年胡潤(rùn)百富榜.html', 'w') as file:  
              file.write(html)  # 將HTML代碼寫(xiě)入文件output.html

          完整版的代碼如下所示。

          import pandas as pd
          
          df = pd.read_excel(r'C:\Users\shangtianqiang\Desktop\2023年胡潤(rùn)百富榜.xlsx')
          df=df.iloc[:100,:]#篩選前100行數(shù)據(jù)
            
          # 定義CSS樣式,添加標(biāo)題“2023年胡潤(rùn)百富榜”  
          style = """  
          <style> 
          h1 {  
              text-align: center;  
              font-size: 24px;  
              margin-bottom: 10px;  
          }  
          table {  
              border-collapse: collapse;  
              width: 100%;  
          }  
          th, td {  
              border: 1px solid black;  
              padding: 8px;  
              text-align: center;  
          }  
          th {  
              background-color: #f2f2f2;  
          }  
          </style>  
          <head><title>2023年胡潤(rùn)百富榜</title></head>
          <h1>2023年胡潤(rùn)百富榜</h1> 
          """  
            
          # 將DataFrame轉(zhuǎn)換為HTML代碼,并添加樣式  
          html = style + df.to_html(index=False)  # 使用index=False來(lái)避免顯示行索引  
            
          # 將HTML代碼寫(xiě)入文件或打印到控制臺(tái)  
          with open('2023年胡潤(rùn)百富榜.html', 'w') as file:  
              file.write(html)  # 將HTML代碼寫(xiě)入文件output.html

          導(dǎo)出的HTML表格樣式如下所示,整體圖表風(fēng)格較為簡(jiǎn)潔。

          導(dǎo)入數(shù)據(jù)

          html的格式數(shù)據(jù)也是數(shù)據(jù)存儲(chǔ)的一種方式,使用read_html命令可以將其很便捷地導(dǎo)入,從而進(jìn)行接下來(lái)的數(shù)據(jù)分析。

          import pandas as pd
          
          df_html=pd.read_html('2023年胡潤(rùn)百富榜.html',encoding='gbk')[0]
          df_html

          通過(guò)學(xué)習(xí)如何使用 Pandas 自定義表格樣式并將其導(dǎo)出為 HTML 格式,我們掌握了更豐富的數(shù)據(jù)處理和展示技巧,并且,還可以根據(jù)實(shí)際業(yè)務(wù)需求來(lái)自定義表格樣式,實(shí)現(xiàn)與他人共享數(shù)據(jù)的目的。


          主站蜘蛛池模板: 久久无码精品一区二区三区| 国产亚洲福利精品一区二区 | 99久久精品国产免看国产一区| 人妻久久久一区二区三区| 亚洲一区二区三区丝袜| 精品一区精品二区| 亚洲宅男精品一区在线观看| 国产精品视频免费一区二区| 国产精品小黄鸭一区二区三区 | 国产精品福利一区二区| 成人丝袜激情一区二区| 中文字幕无码免费久久9一区9| 精品一区二区三区波多野结衣| 日韩A无码AV一区二区三区| 精品久久一区二区| 2014AV天堂无码一区| 无码少妇丰满熟妇一区二区| 国产成人久久精品一区二区三区 | 色噜噜狠狠一区二区三区果冻| 亚洲国产AV无码一区二区三区 | 在线观看国产一区| 国模一区二区三区| 偷拍激情视频一区二区三区 | 无码人妻啪啪一区二区| 亚洲综合一区二区精品导航 | 国产拳头交一区二区| 亚洲国产一区二区三区青草影视| 国产一区二区三区在线电影| 一区二区亚洲精品精华液| 中文字幕乱码人妻一区二区三区 | 波多野结衣电影区一区二区三区| 爆乳无码AV一区二区三区| 在线免费观看一区二区三区| 制服美女视频一区| 日韩精品视频一区二区三区 | 3D动漫精品啪啪一区二区下载 | 亚洲中文字幕在线无码一区二区 | 国产日韩AV免费无码一区二区三区 | 亚洲AV无码一区二三区| 香蕉一区二区三区观| 日本一区二区免费看|