如何从网页导出表格到Excel

98

我如何从网页导出表格到Excel?我希望导出的内容包含所有格式和颜色。


9
最简单的方法可能是导出一个HTML文档,Excel可以打开。 - Pekka
3
@user,你在哪里声明列大小等信息?我对将数据导出到Excel不是非常熟悉,但你可能需要内联声明它们,例如 <td style="background-color: ... - Pekka
@user - 这里至少有两个不同的问题:1)格式化数据以便在Excel中正确显示,2)使用Javascript导出数据以便设置mime类型,提示用户保存文件。您是想解决这两个问题吗? - nrabinowitz
@user,你找到了回答问题的解决方案吗?如果是这样,你能接受吗? - bpeterson76
10
为什么这被认为是“基于观点的”?这是一个非常直接的技术问题。 - brandizzi
显示剩余4条评论
14个回答

75

迄今为止,从表格导出到Excel最干净,最简单的方法是使用Jquery DataTables Table Tools插件。 你可以得到一个排序、过滤、排序和分页数据的网格,只需添加几行额外的代码和两个小文件,便可导出Excel、PDF、CSV、复制到剪贴板和打印。

这就是所需的所有代码:

  $(document).ready( function () {
    $('#example').dataTable( {
        "sDom": 'T<"clear">lfrtip',
        "oTableTools": {
            "sSwfPath": "/swf/copy_cvs_xls_pdf.swf"
        }
    } );
} );

因此,它可以快速部署,没有浏览器限制,不需要服务器端语言,最重要的是非常容易理解。这是一个双赢局面。然而,它的唯一限制是对列的严格格式限制。

如果格式和颜色绝对不能妥协,我发现唯一可靠的跨浏览器方法是使用服务器端语言从代码中处理正确的Excel文件。我选择的解决方案是 PHPExcel。到目前为止,我发现它是唯一能够在任何浏览器上将带有格式的内容正面地导出到最新版本的Excel的解决方案,只需提供HTML。但请让我澄清一下,它绝对不像第一个解决方案那样容易,并且还会消耗一定的资源。但是,好的一面是它也可以直接输出PDF。一旦配置好了,它就可以每次都正常工作。

更新-2016年9月15日: TableTools已停止支持,转而推出一个名为“buttons”的新插件。这些工具执行与旧TableTools扩展相同的功能,但安装要容易得多,并且它们利用HTML5下载现代浏览器,具有回退到原始Flash下载的功能,供不支持HTML5标准的浏览器使用。从我在2011年发布此响应以来的许多评论中可以看出,TableTools的主要弱点得到了解决。对于开发人员和用户都可以轻松处理大量数据,我仍然极力推荐DataTables。


2
DataTables是完全使用Javascript编写的。只有TableTools元素使用Flash,而且它非常小。我绝对不会在我的任何产品中自愿使用Flash! - bpeterson76
16
我理解并同意。但即使是微小的.swf对象也存在,它无法在没有Flash的情况下运行。 - magma
8
这是一个很棒的解决方案,但遗憾的是它需要使用Flash。 - jnthnclrk
1
@PramodGaikwad,不,Datatables将取代NG-table。它们实际上具有相同的功能,但Datatables更加成熟,并且拥有许多更多的功能。有一个Datatables的分支专门为Angular创建:http://l-lin.github.io/angular-datatables/#/welcome - bpeterson76
好的。@bpeterson76 谢谢建议。 - Pramod Gaikwad
显示剩余4条评论

42

很久以前,我发现如果我们以Excel内容类型发送HTML文件,Excel会打开其中的表格。考虑上面的文档:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title>Java Friends</title>
</head>
<body>
  <table style="font-weight: bold">
    <tr style="background-color:red"><td>a</td><td>b</td></tr>
    <tr><td>1</td><td>2</td></tr>
  </table>    
</body>
</html>

我在它上面运行了以下书签:

javascript:window.open('data:application/vnd.ms-excel,'+document.documentElement.innerHTML);

实际上,我已将其下载为Excel文件。但是,我没有得到预期的结果 - 该文件在OpenOffice.org Writer中打开。这就是我的问题:在此计算机上没有Excel,因此我无法更好地尝试它。此外,这个技巧大约六年前使用旧版浏览器和古董版本的MS Office 工作得更好,所以我真的不能确定它今天是否可行。

无论如何,在上面的文档中,我添加了一个按钮,理论上可以将整个文档下载为Excel文件:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title>Java Friends</title>
</head>
<body>
  <table style="font-weight: bold">
    <tr style="background-color:red"><td>a</td><td>b</td></tr>
    <tr><td>1</td><td>2</td></tr>
    <tr>
      <td colspan="2">
        <button onclick="window.open('data:application/vnd.ms-excel,'+document.documentElement.innerHTML);">
            Get as Excel spreadsheet
        </button>
      </td>
    </tr>
  </table>    
</body>
</html>

将它保存在一个文件中,然后单击按钮。我非常希望知道它是否奏效,所以我请您评论,即使只是说它没有奏效。


11
在结尾添加一个“replace”语句,使其能够正常工作: window.open('data:application/vnd.ms-excel,' + document.getElementById('table').outerHTML.replace(/ /g, '%20')); 该代码将打开一个包含名为"table"的HTML元素的Excel文件。在结尾处使用了一个"replace"语句,目的是将HTML元素中的空格替换为"%20",以确保其在Excel文件中正确呈现。 - VSP
6
备选方法(推荐): window.open('data:application/vnd.ms-excel,' + encodeURIComponent(document.getElementById('table').outerHTML));该代码段是用于在网页中导出HTML表格为Excel文件的备选方法。其中,window.open()是JavaScript中的一个函数,用于打开一个新的浏览器窗口。'data:application/vnd.ms-excel,'是一种数据格式,表示将要导出的数据类型为Excel文件。encodeURIComponent()函数将HTML表格元素编码为字符串,以便作为参数传递给window.open()函数。最终结果是在新窗口中以Excel文件的形式展示HTML表格。 - VSP
5
在Firefox中完美运行,将您的表格包装在一个div中,然后使用document.getElementById('id').innerHTML调用ID以仅选择性地抓取表格,否则所有内容都会被导出到电子表格中。但在旧版IE中无法工作,只会在标题中打开一个包含所有HTML的新窗口。 - Abraham Brookes
1
这个简单的解决方案完全有效。看看这个重复的问题,以便能够设置文件名,并设置工作表名称。同样类型的解决方案; https://dev59.com/U2Qn5IYBdhLWcg3wETo5 - Espen Schulstad
2
由于更加严格的安全措施,此功能在Office 365中已不再可用。Excel文件必须是真正的Excel文档,否则打开时会出现错误。 - Phil
显示剩余6条评论

12

可以使用旧的Excel 2003 XML格式(即OpenXML之前)创建一个包含所需XML的字符串,然后在客户端上使用数据URI使用XSL MIME类型打开文件,或者从服务器端以Excel MIME类型“Content-Type:application/vnd.ms-excel”将文件发送到客户端。

  1. Open Excel and create a worksheet with your desired formatting and colors.
  2. Save the Excel workbook as "XML Spreadsheet 2003 (*.xml)"
  3. Open the resulting file in a text editor like notepad and copy the value into a string in your application
  4. Assuming you use the client side approach with a data uri the code would look like this:
    
    <script type="text/javascript">
    var worksheet_template = '<?xml version="1.0"?><ss:Workbook xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">'+
                 '<ss:Styles><ss:Style ss:ID="1"><ss:Font ss:Bold="1"/></ss:Style></ss:Styles><ss:Worksheet ss:Name="Sheet1">'+
                 '<ss:Table>{{ROWS}}</ss:Table></ss:Worksheet></ss:Workbook>';
    var row_template = '<ss:Row ss:StyleID="1"><ss:Cell><ss:Data ss:Type="String">{{name}}</ss:Data></ss:Cell></ss:Row>';
    </script>
    
    
  5. Then you can use string replace to create a collection of rows to be inserted into your worksheet template
    
    <script type="text/javascript">
    var rows = document.getElementById("my-table").getElementsByTagName('tr'),
      row_data = '';
    for (var i = 0, length = rows.length; i < length; ++i) {
    row_data += row_template.replace('{{name}}', rows[i].getElementsByTagName('td')[0].innerHTML);
    }
    </script>
    
    
  6. Once you have the information collected, create the final string and open a new window using the data URI

    
    <script type="text/javascript">
    var worksheet = worksheet_template.replace('{{ROWS}}', row_data);

    window.open('data:application/vnd.ms-excel,'+worksheet); </script>

值得注意的是,旧版浏览器不支持数据URI方案,因此您可能需要在服务器端为那些不支持它的浏览器生成文件。
您还可能需要对数据URI内容执行base64编码,这可能需要使用js库,并在数据URI中的MIME类型后添加字符串“;base64”。

虽然使用OpenXML很不错,但如果表格具有colspan或rowspan,则此解决方案将需要在JavaScript生成器上进行大量工作才能正常运行。 - Eduardo Molteni
1
谢谢你教我东西而不是告诉我使用插件,非常感激。值得一提的是,这种方法今天仍然很有效。 - Benjamin Gruenbaum
有趣的是,我尝试了这种方法。但我只得到了整个**<?xml version="1.0"?><ss:Workbook xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">'+ 'ss:Styles<ss:Style ss:ID="1"><ss:Font ss:Bold="1"/></ss:Style></ss:Styles><ss:Worksheet ss:Name="Sheet1">'+ 'ss:Table**值,我的字符串都写在一个单元格中,包括所有行都在一个单元格中。我错过了什么? - CromeX

6
Excel有一个鲜为人知的功能叫做“Web查询”,它可以让你从几乎每个网页中检索数据,而无需编写额外的程序。基本上,Web查询直接在Excel中运行HTTP请求,并将收到的一些或所有数据(以及可选的格式)复制到工作表中。
在定义了Web查询之后,您可以随时刷新它,甚至不必离开Excel。因此,您不必实际“导出”数据并将其保存到文件中 - 您可以像从数据库中刷新数据一样刷新数据。
您甚至可以利用URL参数,让Excel提示您进行某些筛选条件等...
然而,我目前注意到的缺点有:
动态加载的数据是无法访问的,因为JavaScript没有被执行
URL长度受限制 这里有一个关于如何在Excel中创建Web查询的问题。它链接到一个Microsoft帮助站点,介绍如何从Web页面获取外部数据

如果URL在登录墙后面,这种方法也行不通。 - Achshar
它可以与基本身份验证和基于表单的身份验证一起使用,但对于后者,您可能需要单击“编辑查询”以重新输入凭据并不时获取新cookie。 - HAL 9000

5
这是一个 PHP 代码,但你可能可以将其转换为 JavaScript:
<?php>
$colgroup = str_repeat("<col width=86>",5);
$data = "";
$time = date("M d, y g:ia");
$excel = "<html xmlns:o=\"urn:schemas-microsoft-com:office:office\" xmlns:x=\"urn:schemas-microsoft-com:office:excel\" xmlns=\"http://www.w3.org/TR/REC-html40\">
<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
<html>
<head>
<meta http-equiv=\"Content-type\" content=\"text/html;charset=utf-8\" />
<style id=\"Classeur1_16681_Styles\">
.xl4566 {
color: red;
}
</style>
</head>
<body>
<div id=\"Classeur1_16681\" align=center x:publishsource=\"Excel\">
<table x:str border=0 cellpadding=0 cellspacing=0 style=\"border-collapse: collapse\">
<colgroup>$colgroup</colgroup>
<tr><td class=xl2216681><b>Col1</b></td><td class=xl2216681><b>Col2</b></td><td class=xl2216681 ><b>Col3</b></td><td class=xl2216681 ><b>Col4</b></td><td class=xl2216681 ><b>Col5</b></td></tr>
<tr><td class=xl4566>1</td><td>2</td><td>3</td><td>4</td><td>5</td></tr>
</table>
</div>
</body>
</html>";
  $fname = "Export".time().".xls";
  $file = fopen($fname,"w+");
  fwrite($file,$excel);
  fclose($file);
  header('Content-Type: application/vnd.ms-excel');
  header('Content-Disposition: attachment; filename="'.basename($fname).'"');
  readfile($fname);
  unlink($fname); ?>    

5
首先,我不建议尝试导出HTML并希望用户的Excel实例能够接收它。我的经验是,这种解决方案存在很多问题,包括与Macintosh客户端不兼容以及向用户抛出文件不符合指定格式的错误。最可靠、用户友好的解决方案是使用服务器端库构建实际的Excel文件,并将其发送回用户。下一个最好的解决方案和更通用的解决方案是使用Open XML格式。我遇到了一些与旧版本的Excel兼容性问题,但总体来说,这应该为您提供一个在任何版本的Excel上都能工作的解决方案,包括Mac电脑。
Open XML:链接至http://msdn.microsoft.com/en-us/library/aa338205.aspx

4

mozilla仍然支持base 64 URI。这使您可以使用javascript动态地组合二进制内容:

<a href="data:application/vnd.ms-excel<base64 encoded binary excel content here>"> download xls</a>

如果您的Excel文件不太复杂(没有图表、公式、宏等),您可以深入了解其格式,组合文件字节,然后用base64编码并放入href中。

参考https://developer.mozilla.org/en/data_URIs


2

这段代码只适用于IE浏览器,因此仅在您了解所有用户将使用IE的情况下才有用(例如,在某些企业环境中)。

<script Language="javascript">
function ExportHTMLTableToExcel()
{
   var thisTable = document.getElementById("tbl").innerHTML;
   window.clipboardData.setData("Text", thisTable);
   var objExcel = new ActiveXObject ("Excel.Application");
   objExcel.visible = true;

   var objWorkbook = objExcel.Workbooks.Add;
   var objWorksheet = objWorkbook.Worksheets(1);
   objWorksheet.Paste;
}
</script>

我尝试使用这段代码,它确实在Excel中打开了表格,但格式不正确,看起来只是将HTML代码复制到了表格中。就像这样:<TD class=" " bgColor=#ed9fff>SARTIN, DAN </TD> <TD class=" " bgColor=#ed9fff>BALAEZ, BARBARA </TD> 有什么建议吗? - Fahad
那是因为他使用了innerHTML。他获取的元素是表格,所以应该使用outerHTML。我进行了编辑。 - user1566694
我在创建ActiveXObject时遇到了“自动化服务器无法创建对象”的错误。我该如何修复它? - Nk SP

2

假设:

  1. 给定URL

  2. 转换必须在客户端完成

  3. 系统为Windows、Mac和Linux

Windows解决方案:

Python代码打开IE窗口并访问它: theurl变量包含URL(“http://”)

ie = Dispatch("InternetExplorer.Application")
ie.Visible = 1
ie.Navigate(theurl)

注意:如果页面不能直接访问,而需要登录,则需要通过输入表单数据并使用Python模拟用户操作来处理此问题。
这里是示例。
from win32com.client import Dispatch
ie.Document.all('username').value=usr
ie.Document.all('password').value=psw

使用相同的方式来检索网页中的数据。假设具有id为“el1”的元素包含数据。 将元素文本检索到变量中。
el1 = ie.Document.all('el1').value

当数据存储在Python变量中时,您可以使用类似的方式在Python中打开Excel界面:

from win32com.client import Dispatch
xlApp = Dispatch("Excel.Application")
xlWb = xlApp.Workbooks.Open("Read.xls")
xlSht = xlWb.WorkSheets(1)
xlSht.Cells(row, col).Value = el1

Mac解决方案:

小提示:使用AppleScript - 它具有与win32com.client Dispatch相似的简单API

Linux解决方案:

java.awt.Robot可能适用于此,它具有点击、按键(可以使用热键),但我所知道的没有像AppleScript那样简单易用的Linux API。


2
这其实比你想象的要简单:“只需”将HTML表格(即:表格的HTML代码)复制到剪贴板中。Excel知道如何解码HTML表格;它甚至会尝试保留属性。
困难的部分是“将表格复制到剪贴板”,因为没有标准的方法可以从JavaScript访问剪贴板。请参阅此博客文章:使用JavaScript访问系统剪贴板 - 圣杯? 现在,你所需要的就是HTML格式的表格。我建议使用jQuery和html()方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接