从HTML表格下载CSV

时间:2018-08-18 23:53:49

标签: html csv ecmascript-6

这是一个自我解答的问题。


如何在浏览器中以CSV格式下载HTML <table>?假设HTML表格的实际数据中没有逗号。

这是我的HTML表格:

<table style="width:100%">
  <tr>
    <th>Firstname</th>
    <th>Lastname</th> 
    <th>Age</th>
  </tr>
  <tr>
    <td>Jill</td>
    <td>Smith</td> 
    <td>50</td>
  </tr>
  <tr>
    <td>Eve</td>
    <td>Jackson</td> 
    <td>94</td>
  </tr>
</table>

我不在乎较旧的浏览器,而在乎完全支持ES6的现代浏览器。

2 个答案:

答案 0 :(得分:1)

只需循环遍历HTML行tr,用逗号,将各列连接起来,并使用换行符/n将各行连接起来。

然后在HTML标头th上循环,并用逗号,将每个标头连接起来。

然后使用换行符/n连接标题字符串和行字符串。

从那时起,只需使用包含<a>组CSV字符串的超链接Blob并强制.click()即可开始下载。

下面是一个可以在Chrome 68,FF 58,MacOS Safari 11上正常运行的示例:

const tableToCSV = table => {
  const headers = Array.from(table.querySelectorAll('th'))
    .map(item => item.innerText).join(',')

  const rows = Array.from(table.querySelectorAll('tr'))
    .reduce((arr, domRow) => {
      if (domRow.querySelector('th')) return arr

      const cells = Array.from(domRow.querySelectorAll('td'))
        .map(item => item.innerText)
        .join(',')

      return arr.concat([cells])
    }, [])

  return headers + '\n' + rows.join('\n')
}

const downloadCSV = csv => {
  const csvFile = new Blob([csv], { type: 'text/csv' })
  const downloadLink =  document.createElement('a')

  downloadLink.download = `CSV-${new Date().toDateString()}.csv`
  downloadLink.href = window.URL.createObjectURL(csvFile)
  downloadLink.style.display = 'none'
  document.body.appendChild(downloadLink)

  downloadLink.click()
}

document.querySelector('button').addEventListener('click', () => {
  const table = document.querySelector('table')
  const csv = tableToCSV(table)
  
  return downloadCSV(csv)
})
table, th, td {
  border: 1px solid black;
  border-collapse: collapse;
}

th, td {
  padding: 15px;
  text-align: left;
}

table#t01 {
  width: 100%;    
  background-color: #f1f1c1;
}
<table style="width:100%">
  <tr>
    <th>Firstname</th>
    <th>Lastname</th> 
    <th>Age</th>
  </tr>
  <tr>
    <td>Jill</td>
    <td>Smith</td> 
    <td>50</td>
  </tr>
  <tr>
    <td>Eve</td>
    <td>Jackson</td> 
    <td>94</td>
  </tr>
</table>

<button on-click="download()">Download CSV</button>

答案 1 :(得分:0)

使用上面的答案,但根据我的需要进行了更改。我使用了以下功能,并将其导入到需要下载csv文件的 REACT 文件中。

我的th个文件中有一个span标签。添加了对大多数功能/方法的注释。

import { tableToCSV, downloadCSV } from './../Helpers/exportToCSV';


export function tableToCSV(){
  let tableHeaders = Array.from(document.querySelectorAll('th'))
    .map(item => {
      // title = splits elem tags on '\n',
      // then filter out blank "" that appears in array.
      // ex ["Timestamp", "[Full time]", ""]
      let title = item.innerText.split("\n").filter(str => (str !== 0)).join(" ")
      return title
    }).join(",")

  const rows = Array.from(document.querySelectorAll('tr'))
  .reduce((arr, currRow) => {
    // if tr tag contains th tag.
    // if null return array.
    if (currRow.querySelector('th')) return arr

    // concats individual cells into csv format row.
    const cells = Array.from(currRow.querySelectorAll('td'))
      .map(item => item.innerText)
      .join(',')
    return arr.concat([cells])
  }, [])

return tableHeaders + '\n' + rows.join('\n')
}

export function downloadCSV(csv){
  const csvFile = new Blob([csv], { type: 'text/csv' })
  const downloadLink =  document.createElement('a')
  // sets the name for the download file
  downloadLink.download = `CSV-${currentDateUSWritten()}.csv`
  // sets the url to the window URL created from csv file above
  downloadLink.href = window.URL.createObjectURL(csvFile)
  // creates link, but does not display it.
  downloadLink.style.display = 'none'
  // add link to body so click function below works
  document.body.appendChild(downloadLink)

  downloadLink.click()
}

当用户单击导出到csv时,它会在react中触发以下功能。

  handleExport = (e) => {
    e.preventDefault();
    const csv = tableToCSV()
    return downloadCSV(csv)
  }

示例html表元素。

  <table id="datatable">
        <tbody>
          <tr id="tableHeader" className="t-header">
            <th>Timestamp
              <span className="block">full time</span></th>
            <th>current rate
              <span className="block">alt view</span>
            </th>
            <th>Battery Voltage
              <span className="block">current voltage
              </span>
            </th>
            <th>Temperature 1
              <span className="block">[C]</span>
            </th>
            <th>Temperature 2
              <span className="block">[C]</span>
            </th>
            <th>Time & Date </th>
          </tr>

        </tbody>
        <tbody>
          {this.renderData()}
        </tbody>
      </table>
    </div>