2015-07-24 3 views
1

Я пытаюсь создать приложение, содержащее html-таблицы.PDFmake - таблица html в таблицу pdfmake?

Я хочу кнопку загрузки и событие onClick, загружает файл PDF, содержащий все html-таблицы в нем.

Можно ли это сделать?

Может ли кто-нибудь помочь мне с функцией, которая преобразует таблицу html в объект, чтобы ее можно было вставить в файл PDF через pdfmake?

+0

Вы можете попробовать http://www.mpdf1.com/mpdf/ index.php – Fahad

+0

Вы также можете попробовать: https://pdfcrowd.com/html-to-pdf-api/ – boszlo

ответ

8

я нашел рабочий раствор над здесь: https://github.com/bpampuch/pdfmake/issues/205

function ParseContainer(cnt, e, p, styles) { 
var elements = []; 
var children = e.childNodes; 
if (children.length != 0) { 
    for (var i = 0; i < children.length; i++) p = ParseElement(elements, children[i], p, styles); 
} 
if (elements.length != 0) {    
    for (var i = 0; i < elements.length; i++) cnt.push(elements[i]); 
} 
return p; 
} 

function ComputeStyle(o, styles) { 
for (var i = 0; i < styles.length; i++) { 
    var st = styles[i].trim().toLowerCase().split(":"); 
    if (st.length == 2) { 
     switch (st[0]) { 
      case "font-size":{ 
       o.fontSize = parseInt(st[1]); 
       break; 
      } 
      case "text-align": { 
       switch (st[1]) { 
        case "right": o.alignment = 'right'; break; 
        case "center": o.alignment = 'center'; break; 
       } 
       break; 
      } 
      case "font-weight": { 
       switch (st[1]) { 
        case "bold": o.bold = true; break; 
       } 
       break; 
      } 
      case "text-decoration": { 
       switch (st[1]) { 
        case "underline": o.decoration = "underline"; break; 
       } 
       break; 
      } 
      case "font-style": { 
       switch (st[1]) { 
        case "italic": o.italics = true; break; 
       } 
       break; 
      } 
     } 
    } 
} 
} 

function ParseElement(cnt, e, p, styles) { 
if (!styles) styles = []; 
if (e.getAttribute) { 
    var nodeStyle = e.getAttribute("style"); 
    if (nodeStyle) { 
     var ns = nodeStyle.split(";"); 
     for (var k = 0; k < ns.length; k++) styles.push(ns[k]); 
    } 
} 

switch (e.nodeName.toLowerCase()) { 
    case "#text": { 
     var t = { text: e.textContent.replace(/\n/g, "") }; 
     if (styles) ComputeStyle(t, styles); 
     p.text.push(t); 
     break; 
    } 
    case "b":case "strong": { 
     //styles.push("font-weight:bold"); 
     ParseContainer(cnt, e, p, styles.concat(["font-weight:bold"])); 
     break; 
    } 
    case "u": { 
     //styles.push("text-decoration:underline"); 
     ParseContainer(cnt, e, p, styles.concat(["text-decoration:underline"])); 
     break; 
    } 
    case "i": { 
     //styles.push("font-style:italic"); 
     ParseContainer(cnt, e, p, styles.concat(["font-style:italic"])); 
     //styles.pop(); 
     break; 
     //cnt.push({ text: e.innerText, bold: false }); 
    } 
    case "span": { 
     ParseContainer(cnt, e, p, styles); 
     break; 
    } 
    case "br": { 
     p = CreateParagraph(); 
     cnt.push(p); 
     break; 
    } 
    case "table": 
     { 
      var t = { 
       table: { 
        widths: [], 
        body: [] 
       } 
      } 
      var border = e.getAttribute("border"); 
      var isBorder = false; 
      if (border) if (parseInt(border) == 1) isBorder = true; 
      if (!isBorder) t.layout = 'noBorders'; 
      ParseContainer(t.table.body, e, p, styles); 

      var widths = e.getAttribute("widths"); 
      if (!widths) { 
       if (t.table.body.length != 0) { 
        if (t.table.body[0].length != 0) for (var k = 0; k < t.table.body[0].length; k++) t.table.widths.push("*"); 
       } 
      } else { 
       var w = widths.split(","); 
       for (var k = 0; k < w.length; k++) t.table.widths.push(w[k]); 
      } 
      cnt.push(t); 
      break; 
     } 
    case "tbody": { 
     ParseContainer(cnt, e, p, styles); 
     //p = CreateParagraph(); 
     break; 
    } 
    case "tr": { 
     var row = []; 
     ParseContainer(row, e, p, styles); 
     cnt.push(row); 
     break; 
    } 
    case "td": { 
     p = CreateParagraph(); 
     var st = {stack: []} 
     st.stack.push(p); 

     var rspan = e.getAttribute("rowspan"); 
     if (rspan) st.rowSpan = parseInt(rspan); 
     var cspan = e.getAttribute("colspan"); 
     if (cspan) st.colSpan = parseInt(cspan); 

     ParseContainer(st.stack, e, p, styles); 
     cnt.push(st); 
     break; 
    } 
    case "div":case "p": { 
     p = CreateParagraph(); 
     var st = {stack: []} 
     st.stack.push(p); 
     ComputeStyle(st, styles); 
     ParseContainer(st.stack, e, p); 

     cnt.push(st); 
     break; 
    } 
    default: { 
     console.log("Parsing for node " + e.nodeName + " not found"); 
     break; 
    } 
} 
return p; 
} 

function ParseHtml(cnt, htmlText) { 
var html = $(htmlText.replace(/\t/g, "").replace(/\n/g, "")); 
var p = CreateParagraph(); 
for (var i = 0; i < html.length; i++) ParseElement(cnt, html.get(i), p); 
} 

function CreateParagraph() { 
var p = {text:[]}; 
return p; 
} 

//currently should be wraped in tag div or span 
var simpleHtm = "<div>"; 
simpleHtm += "This is <u>simple</u> html parser demo.<br>"; 
simpleHtm += "<p style='font-size:20px; text-align:center'>You can set font  
size and align from style</p>"; 
simpleHtm += "<table border='1'><tr><td>you</td><td>can</td></tr><tr> <td>use</td><td>tables</td></tr></table>" 
simpleHtm += "<table border='1' widths='30%,60%'><tr><td>or</td><td>set</td></tr><tr><td>table</td><td>width from html</td></tr></table><br>" 
simpleHtm += "<table border='1' widths='20%,50%'><tr><td>nested</td><td>table</td></tr><tr><td><table border='1'><tr><td>1</td><td>2</td></tr><tr><td>3</td><td>4</td></tr></table></td><td></td></tr></table>" 

simpleHtm += "</div>"; 
content = []; 
ParseHtml(content, simpleHtm); 
pdfMake.createPdf({content: content}).download(); 

Вы можете получить HTML-код любого HTML-элемента (я показываю таблицу), используя следующий код & вызовите функцию ParseHTML:

var simpleHtm = $('#TableID').prop('outerHTML'); 
      ParseHtml(tablecontent, simpleHtm); 
+0

Был обновлен, и вот [jsFidle] (http://jsfiddle.net/mychn9bo/75/) с фактическим рабочим кодом выше. – mjwrazor

+0

Это хорошее начало для того, что мне нужно для использования pdfmake. К сожалению, этот парсер не имеет дело с colspan в таблицах. Кто-нибудь сделал эту часть ??? – davewhirlwind

+0

@mjwrazor Я получаю эту ошибку «Не могу прочитать свойство« _span »неопределенного ' – Joyston

3

Глядя на getting started странице PDFMake, вы должны отформатировать таблицу, как это:

var docDefinition = { 
    content: [{ 
     table: { 
      // headers are automatically repeated if the table spans over multiple pages 
      // you can declare how many rows should be treated as headers 
      headerRows: 1, 
      widths: [ '*', 'auto', 100, '*' ], 

      body: [ 
       [ 'First', 'Second', 'Third', 'The last one' ], 
       [ 'Value 1', 'Value 2', 'Value 3', 'Value 4' ], 
       [ { text: 'Bold value', bold: true }, 'Val 2', 'Val 3', 'Val 4' ] 
      ] 
     } 
    }] 
}; 

Таким образом, вы бы ваш стол и получить а ширину каждого столбца, а затем цикл по строкам, чтобы создать тело массив:

function createTableDoc() { 
    var table = document.getElementById("table"); 
    var wdths; 
    for (var i = 0; i < table.rows[0].cells.length; i++) { 
     var cell = table.rows[0].cells[i]; 
     widths[i] = (cell.style.width != ""? cell.style.width : cell.style.offsetWidth); //if the cell's style width is not set, get its' actual width 
    } 

    var bdy; 
    for (var y = 0; y < table.rows.length; y++) 
     for (var x = 0; x < table.rows[y].cells.length; x++) { 
      body[y][x] = table.rows[y].cells[x].innerHTML; 

    var docDef = { content: [{ table: { headerRows: 1, widths: wdths, body: bdy } }] }; 
    return docDef; 
} 
+0

Это дает мне ошибку, которая не может установить свойство «0» неопределенного. –

+0

@ vbuser2004 проверьте вышеприведенное решение, он отлично работает :) –

+0

@TanujDhaundiyal - мой плохой! Я пропустил это как-то. Удалено исходный комментарий. Txs. – vbuser2004

0

Полный рабочий раствор из here. Попробуйте запустить здесь пример. Если у вас есть основной контейнер div с id="test", с этим набором функций вам просто нужно позвонить pdfForElement('test').download();

function pdfForElement(id) { 
 
    function ParseContainer(cnt, e, p, styles) { 
 
    var elements = []; 
 
    var children = e.childNodes; 
 
    if (children.length != 0) { 
 
     for (var i = 0; i < children.length; i++) p = ParseElement(elements, children[i], p, styles); 
 
    } 
 
    if (elements.length != 0) { 
 
     for (var i = 0; i < elements.length; i++) cnt.push(elements[i]); 
 
    } 
 
    return p; 
 
    } 
 

 
    function ComputeStyle(o, styles) { 
 
    for (var i = 0; i < styles.length; i++) { 
 
     var st = styles[i].trim().toLowerCase().split(":"); 
 
     if (st.length == 2) { 
 
     switch (st[0]) { 
 
      case "font-size": 
 
      { 
 
       o.fontSize = parseInt(st[1]); 
 
       break; 
 
      } 
 
      case "text-align": 
 
      { 
 
       switch (st[1]) { 
 
       case "right": 
 
        o.alignment = 'right'; 
 
        break; 
 
       case "center": 
 
        o.alignment = 'center'; 
 
        break; 
 
       } 
 
       break; 
 
      } 
 
      case "font-weight": 
 
      { 
 
       switch (st[1]) { 
 
       case "bold": 
 
        o.bold = true; 
 
        break; 
 
       } 
 
       break; 
 
      } 
 
      case "text-decoration": 
 
      { 
 
       switch (st[1]) { 
 
       case "underline": 
 
        o.decoration = "underline"; 
 
        break; 
 
       } 
 
       break; 
 
      } 
 
      case "font-style": 
 
      { 
 
       switch (st[1]) { 
 
       case "italic": 
 
        o.italics = true; 
 
        break; 
 
       } 
 
       break; 
 
      } 
 
     } 
 
     } 
 
    } 
 
    } 
 

 
    function ParseElement(cnt, e, p, styles) { 
 
    if (!styles) styles = []; 
 
    if (e.getAttribute) { 
 
     var nodeStyle = e.getAttribute("style"); 
 
     if (nodeStyle) { 
 
     var ns = nodeStyle.split(";"); 
 
     for (var k = 0; k < ns.length; k++) styles.push(ns[k]); 
 
     } 
 
    } 
 

 
    switch (e.nodeName.toLowerCase()) { 
 
     case "#text": 
 
     { 
 
      var t = { 
 
      text: e.textContent.replace(/\n/g, "") 
 
      }; 
 
      if (styles) ComputeStyle(t, styles); 
 
      p.text.push(t); 
 
      break; 
 
     } 
 
     case "b": 
 
     case "strong": 
 
     { 
 
      //styles.push("font-weight:bold"); 
 
      ParseContainer(cnt, e, p, styles.concat(["font-weight:bold"])); 
 
      break; 
 
     } 
 
     case "u": 
 
     { 
 
      //styles.push("text-decoration:underline"); 
 
      ParseContainer(cnt, e, p, styles.concat(["text-decoration:underline"])); 
 
      break; 
 
     } 
 
     case "i": 
 
     { 
 
      //styles.push("font-style:italic"); 
 
      ParseContainer(cnt, e, p, styles.concat(["font-style:italic"])); 
 
      //styles.pop(); 
 
      break; 
 
      //cnt.push({ text: e.innerText, bold: false }); 
 
     } 
 
     case "span": 
 
     { 
 
      ParseContainer(cnt, e, p, styles); 
 
      break; 
 
     } 
 
     case "br": 
 
     { 
 
      p = CreateParagraph(); 
 
      cnt.push(p); 
 
      break; 
 
     } 
 
     case "table": 
 
     { 
 
      var t = { 
 
      table: { 
 
       widths: [], 
 
       body: [] 
 
      } 
 
      } 
 
      var border = e.getAttribute("border"); 
 
      var isBorder = false; 
 
      if (border) 
 
      if (parseInt(border) == 1) isBorder = true; 
 
      if (!isBorder) t.layout = 'noBorders'; 
 
      ParseContainer(t.table.body, e, p, styles); 
 

 
      var widths = e.getAttribute("widths"); 
 
      if (!widths) { 
 
      if (t.table.body.length != 0) { 
 
       if (t.table.body[0].length != 0) 
 
       for (var k = 0; k < t.table.body[0].length; k++) t.table.widths.push("*"); 
 
      } 
 
      } else { 
 
      var w = widths.split(","); 
 
      for (var k = 0; k < w.length; k++) t.table.widths.push(w[k]); 
 
      } 
 
      cnt.push(t); 
 
      break; 
 
     } 
 
     case "tbody": 
 
     { 
 
      ParseContainer(cnt, e, p, styles); 
 
      //p = CreateParagraph(); 
 
      break; 
 
     } 
 
     case "tr": 
 
     { 
 
      var row = []; 
 
      ParseContainer(row, e, p, styles); 
 
      cnt.push(row); 
 
      break; 
 
     } 
 
     case "td": 
 
     { 
 
      p = CreateParagraph(); 
 
      var st = { 
 
      stack: [] 
 
      } 
 
      st.stack.push(p); 
 

 
      var rspan = e.getAttribute("rowspan"); 
 
      if (rspan) st.rowSpan = parseInt(rspan); 
 
      var cspan = e.getAttribute("colspan"); 
 
      if (cspan) st.colSpan = parseInt(cspan); 
 

 
      ParseContainer(st.stack, e, p, styles); 
 
      cnt.push(st); 
 
      break; 
 
     } 
 
     case "div": 
 
     case "p": 
 
     { 
 
      p = CreateParagraph(); 
 
      var st = { 
 
      stack: [] 
 
      } 
 
      st.stack.push(p); 
 
      ComputeStyle(st, styles); 
 
      ParseContainer(st.stack, e, p); 
 

 
      cnt.push(st); 
 
      break; 
 
     } 
 
     default: 
 
     { 
 
      console.log("Parsing for node " + e.nodeName + " not found"); 
 
      break; 
 
     } 
 
    } 
 
    return p; 
 
    } 
 

 
    function ParseHtml(cnt, htmlText) { 
 
    var html = $(htmlText.replace(/\t/g, "").replace(/\n/g, "")); 
 
    var p = CreateParagraph(); 
 
    for (var i = 0; i < html.length; i++) ParseElement(cnt, html.get(i), p); 
 
    } 
 

 
    function CreateParagraph() { 
 
    var p = { 
 
     text: [] 
 
    }; 
 
    return p; 
 
    } 
 
    content = []; 
 
    ParseHtml(content, document.getElementById(id).outerHTML); 
 
    return pdfMake.createPdf({ 
 
    content: content 
 
    }); 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.32/pdfmake.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.32/vfs_fonts.js"></script> 
 
<div id="test"> 
 
    This is <u>simple</u> html parser demo. 
 
    <br> 
 
    <p style='font-size:20px; text-align:center'>You can set font size and align from style</p> 
 
    <table border='1'> 
 
    <tr> 
 
     <td>you</td> 
 
     <td>can</td> 
 
    </tr> 
 
    <tr> 
 
     <td>use</td> 
 
     <td>tables</td> 
 
    </tr> 
 
    </table> 
 
    <table border='1' widths='30%,60%'> 
 
    <tr> 
 
     <td>or</td> 
 
     <td>set</td> 
 
    </tr> 
 
    <tr> 
 
     <td>table</td> 
 
     <td>width from html</td> 
 
    </tr> 
 
    </table> 
 
    <br> 
 
    <table border='1' widths='20%,50%'> 
 
    <tr> 
 
     <td>nested</td> 
 
     <td>table</td> 
 
    </tr> 
 
    <tr> 
 
     <td> 
 
     <table border='1'> 
 
      <tr> 
 
      <td>1</td> 
 
      <td>2</td> 
 
      </tr> 
 
      <tr> 
 
      <td>3</td> 
 
      <td>4</td> 
 
      </tr> 
 
     </table> 
 
     </td> 
 
     <td></td> 
 
    </tr> 
 
    </table> 
 
</div> 
 
<br> 
 
<input type="button" value="Download PDF" onclick="pdfForElement('test').download();">