JavaScript导出Excel实例详解


Posted in Javascript onNovember 25, 2014

本文实例讲述了JavaScript导出Excel的方法。分享给大家供大家参考。具体实现方法如下:

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>

<title>WEB页面导出为EXCEL文档的方法</title>

</head>

<body>

<table id="tableExcel" width="100%" border="1" cellspacing="0" cellpadding="0">

<tr>

<td colspan="5" align="center">WEB页面导出为EXCEL文档的方法</td>

</tr>

<tr>

<td>列标题1</td>

<td>列标题2</td>

<td>列标题3</td>

<td>列标题4</td>

<td>列标题5</td>

</tr>

<tr>

<td>aaa</td>

<td>bbb</td>

<td>ccc</td>

<td>ddd</td>

<td>eee</td>

</tr>

<tr>

<td>AAA</td>

<td>BBB</td>

<td>CCC</td>

<td>DDD</td>

<td>EEE</td>

</tr>

<tr>

<td>FFF</td>

<td>GGG</td>

<td>HHH</td>

<td>III</td>

<td>JJJ</td>

</tr>

</table>

<input type="button" onclick="javascript:method1('tableExcel');" value="第一种方法导入到EXCEL">

<input type="button" onclick="javascript:method2('tableExcel');" value="第二种方法导入到EXCEL">

<input type="button" onclick="javascript:getXlsFromTbl('tableExcel',null);" value="第三种方法导入到EXCEL">

<SCRIPT LANGUAGE="javascript">

function method1(tableid) {//整个表格拷贝到EXCEL中

var curTbl = document.getElementByIdx_x_x(tableid);

var oXL = new ActiveXObject("Excel.Application");

//创建AX对象excel

var oWB = oXL.Workbooks.Add();

//获取workbook对象

var oSheet = oWB.ActiveSheet;

//激活当前sheet

var sel = document.body.createTextRange();

sel.moveToElementText(curTbl);

//把表格中的内容移到TextRange中

sel.select();

//全选TextRange中内容

sel.execCommand("Copy");

//复制TextRange中内容

oSheet.Paste();

//粘贴到活动的EXCEL中

oXL.Visible = true;

//设置excel可见属性

}

function method2(tableid) //读取表格中每个单元到EXCEL中

{

var curTbl = document.getElementByIdx_x_x(tableid);

var oXL = new ActiveXObject("Excel.Application");

//创建AX对象excel

var oWB = oXL.Workbooks.Add();

//获取workbook对象

var oSheet = oWB.ActiveSheet;

//激活当前sheet

var Lenr = curTbl.rows.length;

//取得表格行数

for (i = 0; i < Lenr; i++)

{

var Lenc = curTbl.rows(i).cells.length;

//取得每行的列数

for (j = 0; j < Lenc; j++)

{

oSheet.Cells(i + 1, j + 1).value = curTbl.rows(i).cells(j).innerText;

//赋值

}

}

oXL.Visible = true;

//设置excel可见属性

}

function getXlsFromTbl(inTblId, inWindow) {

try {

var allStr = "";

var curStr = "";

//alert("getXlsFromTbl");

if (inTblId != null && inTblId != "" && inTblId != "null") {

curStr = getTblData(inTblId, inWindow);

}

if (curStr != null) {

allStr += curStr;

}

else {

alert("你要导出的表不存在!");

return;

}

var fileName = getExcelFileName();

doFileExport(fileName, allStr);

}

catch(e) {

alert("导出发生异常:" + e.name + "->" + e.description + "!");

}

}

function getTblData(inTbl, inWindow) {

var rows = 0;

//alert("getTblData is " + inWindow);

var tblDocument = document;

if (!!inWindow && inWindow != "") {

if (!document.all(inWindow)) {

return null;

}

else {

tblDocument = eval_r(inWindow).document;

}

}

var curTbl = tbldocument.getElementByIdx_x_x(inTbl);

var outStr = "";

if (curTbl != null) {

for (var j = 0; j < curTbl.rows.length; j++) {

//alert("j is " + j);

for (var i = 0; i < curTbl.rows[j].cells.length; i++) {

//alert("i is " + i);

if (i == 0 && rows > 0) {

outStr += "  ";

rows -= 1;

}

outStr += curTbl.rows[j].cells[i].innerText + " ";

if (curTbl.rows[j].cells[i].colSpan > 1) {

for (var k = 0; k < curTbl.rows[j].cells[i].colSpan - 1; k++) {

outStr += "  ";

}

}
if (i == 0) {

if (rows == 0 && curTbl.rows[j].cells[i].rowSpan > 1) {

rows = curTbl.rows[j].cells[i].rowSpan - 1;

}

}

}

outStr += " ";

}

}

else {

outStr = null;

alert(inTbl + "不存在!");

}

return outStr;

}
function getExcelFileName() {

var d = new Date();

var curYear = d.getYear();

var curMonth = "" + (d.getMonth() + 1);

var curDate = "" + d.getDate();

var curHour = "" + d.getHours();

var curMinute = "" + d.getMinutes();

var curSecond = "" + d.getSeconds();

if (curMonth.length == 1) {

curMonth = "0" + curMonth;

}
if (curDate.length == 1) {

curDate = "0" + curDate;

}
if (curHour.length == 1) {

curHour = "0" + curHour;

}
if (curMinute.length == 1) {

curMinute = "0" + curMinute;

}
if (curSecond.length == 1) {

curSecond = "0" + curSecond;

}
var fileName = "leo_zhang" + "_" + curYear + curMonth + curDate + "_"

+ curHour + curMinute + curSecond + ".csv";

//alert(fileName);

return fileName;

}
function doFileExport(inName, inStr) {

var xlsWin = null;

if (!!document.all("glbHideFrm")) {

xlsWin = glbHideFrm;

}
else {

var width = 6;

var height = 4;

var openPara = "left=" + (window.screen.width / 2 - width / 2)

+ ",top=" + (window.screen.height / 2 - height / 2)

+ ",scrollbars=no,width=" + width + ",height=" + height;

xlsWin = window.open("", "_blank", openPara);
}

xlsWin.document.write(inStr);

xlsWin.document.close();

xlsWin.document.execCommand('Saveas', true, inName);

xlsWin.close();

}

</SCRIPT>

</body>

</html>

下面是处理excel 进程关闭问题

// JavaScript中的析构问题(ActiveX Object示例)

//---------------------------------------------------------

<script>

var strSaveLocation = 'file:///E:/1.xls'

function createXLS() {

  var excel = new ActiveXObject("Excel.Application");

  var wk = excel.Workbooks.Add();

  wk.SaveAs(strSaveLocation);

  wk.Saved = true;
  excel.Quit();

}
function writeXLS() {

  var excel = new ActiveXObject("Excel.Application");

  var wk = excel.Workbooks.Open(strSaveLocation);

  var sheet = wk.Worksheets(1);

  sheet.Cells(1, 1).Value = '测试字符串';

  wk.SaveAs(strSaveLocation);

  wk.Saved = true;
  excel.Quit();

}

</script>
<body>

  <button onclick="createXLS()">创建</button>

  <button onclick="writeXLS()">重写</button>

</body>

在这个例子中,在本地文件操作时并不会出现异常。——最多只是有一些内存垃圾而已。然而,如果strSaveLocation是一个远程的URL,这时本地将会保存一个文件存取权限的凭证,而且同时只能一个(远程的)实例来开启该excel文档并存储。于是如果反复点击"重写"按钮,就会出现异常。

——注意,这是在SPS中操作共享文件时的一个实例的简化代码。因此,它并非“学术的”无聊讨论,而且工程中的实际问题。

解决这个问题的方法很复杂。它涉及到两个问题:
① 本地凭证的释放
② ActiveX Object实例的释放

下面我们先从JavaScript中对象的“失效”问题说起。简单的说:
① 一个对象在其生存的上下文环境之外,即会失效。
② 一个全局的对象在没有被执用(引用)的情况下,即会失效。

例如:

//---------------------------------------------------------

// JavaScript对象何时失效

//---------------------------------------------------------

function testObject() {

  var _obj1 = new Object();

}
function testObject2() {

  var _obj2 = new Object();

  return _obj2;

}
// 示例1

testObject();
// 示例2

testObject2()
// 示例3

var obj3 = testObject2();

obj3 = null;
// 示例4

var obj4 = testObject2();

var arr = [obj4];

obj3 = null;

arr = [];

在这四个示例中:
- “示例1”在函数testObject()中构造了_obj1,但是在函数退出时,它就已经离开了函数的上下文环境,因此_obj1失效了;
- “示例2”中,testObject2()中也构造了一个对象_obj2并传出,因此对象有了“函数外”的上下文环境(和生存周期),然而由于函数的返回值没有被其它变量“持有”,因此_obj2也立即失效了;
- “示例3”中,testObject2()构造的_obj2被外部的变量obj3持用了,这时,直到“obj3=null”这行代码生效时,_obj2才会因为引用关系消失而失效。
- 与示例3相同的原因,“示例4”中的_obj2会在“arr=[]”这行代码之后才会失效。

但是,对象的“失效”并不等会“释放”。在JavaScript运行环境的内部,没有任何方式来确切地告诉用户“对象什么时候会释放”。这依赖于JavaScript的内存回收机制。——这种策略与.NET中的回收机制是类同的。

在前面的Excel操作示例代码中,对象的所有者,也就是"EXCEL.EXE"这个进程只能在“ActiveX Object实例的释放”之后才会发生。而文件的锁,以及操作系统的权限凭证是与进程相关的。因此如果对象仅是“失效”而不是“释放”,那么其它进程处理文件和引用操作系统的权限凭据时就会出问题。

——有些人说这是JavaScript或者COM机制的BUG。其实不是,这是OS、IE和JavaScript之间的一种复杂关系所导致的,而非独立的问题。

Microsoft公开了解决这种问题的策略:主动调用内存回收过程。

在(微软的)JScript中提供了一个CollectGarbage()过程(通常简称GC过程),GC过程用于清理当前IE中的“失效的对象失例”,也就是调用对象的析构过程。

在上例中调用GC过程的代码是:

//---------------------------------------------------------

// 处理ActiveX Object时,GC过程的标准调用方式

//---------------------------------------------------------

function writeXLS() {

  //(略...)
  excel.Quit();

  excel = null;

  setTimeout(CollectGarbage, 1);

}

第一行代码调用excel.Quit()方法来使得excel进程中止并退出,这时由于JavaScript环境执有excel对象实例,因此excel进程并不实际中止。

第二行代码使excel为null,以清除对象引用,从而使对象“失效”。然而由于对象仍旧在函数上下文环境中,因此如果直接调用GC过程,对象仍然不会被清理。

第三行代码使用setTimeout()来调用CollectGarbage函数,时间间隔设为'1',只是使得GC过程发生在writeXLS()函数执行完之后。这样excel对象就满足了“能被GC清理”的两个条件:没有引用和离开上下文环境。

GC过程的使用,在使用了ActiveX Object的JS环境中很有效。一些潜在的ActiveX Object包括XML、VML、OWC(Office Web Componet)、flash,甚至包括在JS中的VBArray。

从这一点来看,ajax架构由于采用了XMLHTTP,并且同时要满足“不切换页面”的特性,因此在适当的时候主动调用GC过程,会得到更好的效率用UI体验。

事实上,即使使用GC过程,前面提到的excel问题仍然不会被完全解决。因为IE还缓存了权限凭据。使页的权限凭据被更新的唯一方法,只能是“切换到新的页面”,因此事实上在前面提到的那个SPS项目中,我采用的方法并不是GC,而是下面这一段代码:

//---------------------------------------------------------

// 处理ActiveX Object时采用的页面切换代码

//---------------------------------------------------------

function writeXLS() {

  //(略...)
  excel.Quit();

  excel = null;

 

  // 下面代码用于解决IE call Excel的一个BUG, MSDN中提供的方法:

  //   setTimeout(CollectGarbage, 1);

  // 由于不能清除(或同步)网页的受信任状态, 所以将导致SaveAs()等方法在

  // 下次调用时无效.

  location.reload();

}

最后之最后,关于GC的一个补充说明:在IE窗体被最小化时,IE将会主动调用一次
CollectGarbage()函数。这使得IE窗口在最小化之后,内存占用会有明显改善。

希望本文所述对大家基于javascript的web程序设计有所帮助。

Javascript 相关文章推荐
一些常用的JS功能函数(2009-06-04更新)
Jun 04 Javascript
前端开发的开始---基于面向对象的Ajax类
Sep 17 Javascript
setTimeout()与setInterval()方法区别介绍
Dec 24 Javascript
JavaScript实现给按钮加上双重动作的方法
Aug 14 Javascript
Bootstrap每天必学之响应式导航、轮播图
Apr 25 Javascript
javascript类型系统——undefined和null全面了解
Jul 13 Javascript
JavaScript 轮播图和自定义滚动条配合鼠标滚轮分享代码贴
Oct 28 Javascript
Bootstrap导航条的使用和理解3
Dec 14 Javascript
canvas绘制万花筒效果(代码分享)
Jan 20 Javascript
vue之将echart封装为组件
Jun 02 Javascript
基于Vue实现微信小程序的图文编辑器
Jul 25 Javascript
Vue使用虚拟dom进行渲染view的方法
Dec 26 Javascript
JS倒计时代码汇总
Nov 25 #Javascript
jquery中push()的用法(数组添加元素)
Nov 25 #Javascript
Jquery焦点图实例代码
Nov 25 #Javascript
jQuery事件绑定和委托实例
Nov 25 #Javascript
2014最热门的JavaScript代码高亮插件推荐
Nov 25 #Javascript
JS跨域问题详解
Nov 25 #Javascript
javascript 中__proto__和prototype详解
Nov 25 #Javascript
You might like
php 利用socket发送HTTP请求(GET,POST)
2015/08/24 PHP
javascript温习的一些笔记 基础常用知识小结
2011/06/22 Javascript
jQuery侧边栏随窗口滚动实现方法
2013/03/04 Javascript
jquery文字上下滚动的实现方法
2013/03/22 Javascript
jQuery.holdReady()使用方法
2014/05/20 Javascript
关于JavaScript的变量的数据类型的判断方法
2015/08/14 Javascript
JavaScript+html5 canvas实现本地截图教程
2020/04/16 Javascript
基于jQuery的AJAX和JSON实现纯html数据模板
2016/08/09 Javascript
利用js编写响应式侧边栏
2016/09/17 Javascript
微信小程序 下拉菜单简单实例
2017/04/13 Javascript
Vue框架中正确引入JS库的方法介绍
2017/07/30 Javascript
label+input实现按钮开关切换效果的实例
2017/08/16 Javascript
webpack 模块热替换原理
2018/04/09 Javascript
详解Vue-axios 设置请求头问题
2018/12/06 Javascript
使用 node.js 模仿 Apache 小部分功能
2019/07/07 Javascript
微信公众号平台接口开发 获取微信服务器IP地址方法解析
2019/08/14 Javascript
vue实现简单加法计算器
2020/10/22 Javascript
mustache.js实现首页元件动态渲染的示例代码
2020/12/28 Javascript
[47:55]Ti4第二日主赛事败者组 NaVi vs EG 1
2014/07/20 DOTA
详解Python中的join()函数的用法
2015/04/07 Python
Python输出9*9乘法表的方法
2015/05/25 Python
恢复百度云盘本地误删的文件脚本(简单方法)
2017/10/21 Python
python+ffmpeg批量去视频开头的方法
2019/01/09 Python
python django 原生sql 获取数据的例子
2019/08/14 Python
PyTorch之图像和Tensor填充的实例
2019/08/18 Python
python时间日期操作方法实例小结
2020/02/06 Python
windows+vscode安装paddleOCR运行环境的步骤
2020/11/11 Python
基于 HTML5 的 WebGL 3D 版俄罗斯方块的示例代码
2018/05/28 HTML / CSS
three.js模拟实现太阳系行星体系功能
2019/09/03 HTML / CSS
临床医学专业个人的自我评价
2013/09/27 职场文书
网上开店必备创业计划书
2014/01/26 职场文书
安全责任书范文
2014/08/25 职场文书
工程合作意向书范本
2015/05/09 职场文书
邓小平文选读书笔记
2015/06/29 职场文书
想创业成功,需要掌握这些要点
2019/12/06 职场文书
Matplotlib绘制条形图的方法你知道吗
2022/03/21 Python