[英]Generate a designed PDF report from a web application
我想從Web應用程序生成PDF報告。 PDF應包含圖表(餅圖,條形圖),表格,不同的字體和顏色。
應用程序的服務器端是Java,客戶端是AngularJS(當然還有CSS3和HTML)。
兩個主要選項:
在Java世界中,我發現了iText和JFreeChart之類的東西 ,例如here 。 這里的問題是,圖表的設計在示例中看起來很糟糕,我不知道是否可以將其更改為由我擁有的樣式指南(可以通過CSS輕松完成的設計)進行設計。
在JS世界中,我發現了html2canvas和pdfMake,例如here 。 這里的問題是我不確定從HTML到canvas再到PDF的轉換在Angular應用程序中是否能正常工作。 而且我不確定它是否可以轉換復雜的DOM元素,例如svg中的圖表或canvas元素。
您對這些軟件包有經驗嗎? 您是否知道針對此任務,客戶端或服務器的其他推薦軟件包?
想要分享我的解決方案...我選擇了客戶端解決方案。
我從jsPDF開始,但是有一些問題。 例如,很難用我想要的樣式轉換表。
我選擇pdfMake為PDF生成, html2canvas采取復雜設計的部件的屏幕截圖,並canvg為d3js圖表(SVG圖表)轉化為畫布(pdfMake可以為圖像添加畫布文檔)。
我編寫了一個函數,該函數獲取要轉換為PDF的部件的HTML根的CSS類(請記住它是單頁應用程序),並且還獲取有關哪個HTML節點的元數據(同樣,通過其CSS類)應該添加到PDF(節點是什么類型-table / text / image / svg)。
然后,通過DOM遍歷,我瀏覽了要添加到PDF的元素,並按其類型處理了每個元素。 代碼的一部分(按類型遍歷和切換情況):
$(htmlRootSelector).contents().each(function processNodes(index, element) {
var classMeta = getMetaByClass(element.className);
if (!classMeta) {
$(element).contents().each(processNodes);
return;
}
var pdfObj = {};
pdfObj.width = classMeta.width || angular.undefined;
pdfObj.height = classMeta.height || angular.undefined;
pdfObj.style = classMeta.style || angular.undefined;
pdfObj.pageBreak = classMeta.pageBreak || angular.undefined;
switch (classMeta.type) {
case 'text':
pdfObj.text = element.innerText;
pdfDefinition.content.push(pdfObj);
break;
case 'table':
var tableArray = [];
var headerArray = [];
var headers = $(element).find('th');
var rows = $(element).find('tr');
$.each(headers, function (i, header) {
headerArray.push({text: header.innerHTML, style: classMeta.style + '-header'});
});
tableArray.push(headerArray);
$.each(rows, function (i, row) {
var rowArray = [];
var cells = $(row).find('td');
if (cells.length) {
$.each(cells, function (j, cell) {
rowArray.push(i % 2 === 1 ? {text: cell.innerText, style: classMeta.style + '-odd-row'} : cell.innerText);
});
tableArray.push(rowArray);
}
});
pdfObj.table = {
widths: $.map(headers, function (d, i) {
return i === 0 ? 80 : '*';
}),
body: tableArray
};
pdfDefinition.content.push(pdfObj);
break;
case 'image':
html2CanvasCount++;
htmlToCanvas(element, pdfObj);
pdfDefinition.content.push(pdfObj);
break;
case 'svg':
svgToCanvas(element, pdfObj);
pdfDefinition.content.push(pdfObj);
break;
default:
break;
}
$(element).contents().each(processNodes);
});
這通常是解決方案。 希望它會幫助某人。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.