关于js-xlsx的简单使用

关于js-xlsx的简单使用


最近要做一个东西用到对excel的操作,就是在前端将excel加载进来,操作后再生成excel,在网上找了很多种办法,能够实现的demo是下面这个:

纯前端利用 js-xlsx 实现 Excel 文件导入导出功能示例


官方的文档请看这:js-xlsx


以下是我自己实现的功能,前端框架使用的是bootstrap;

使用时上传excel文件,进行自己的操作,然后点击下载,具体的细节还要根据自己的需求来改,这里只是一个例子


我的excel格式:



demo:

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
    <meta name="description" content="">
    <meta name="author" content="">
    <link rel="icon" href="favicon.ico">
    <title>demo</title>
    <!-- Bootstrap core CSS -->
    <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
    <script src="http://oss.sheetjs.com/js-xlsx/xlsx.full.min.js"></script>

    <style type="text/css">
        /*
         * Base structure
         */
        /* Move down content because we have a fixed navbar that is 50px tall */
        body {
          padding-top: 50px;
        }
        /*
         * Global add-ons
         */
        .sub-header {
          padding-bottom: 10px;
          border-bottom: 1px solid #eee;
        }
        /*
         * Top navigation
         * Hide default border to remove 1px line.
         */
        .navbar-fixed-top {
          border: 0;
        }
        /*
         * Sidebar
         */
        /* Hide for mobile, show later */
        .sidebar {
          display: none;
        }
        @media (min-width: 768px) {
          .sidebar {
            position: fixed;
            top: 51px;
            bottom: 0;
            left: 0;
            z-index: 1000;
            display: block;
            padding: 20px;
            overflow-x: hidden;
            overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */
            background-color: #f5f5f5;
            border-right: 1px solid #eee;
          }
        }
        /* Sidebar navigation */
        .nav-sidebar {
          margin-right: -21px; /* 20px padding + 1px border */
          margin-bottom: 20px;
          margin-left: -20px;
        }
        .nav-sidebar > li > a {
          padding-right: 20px;
          padding-left: 20px;
        }
        .nav-sidebar > .active > a,
        .nav-sidebar > .active > a:hover,
        .nav-sidebar > .active > a:focus {
          color: #fff;
          background-color: #428bca;
        }
        /*
         * Main content
         */
        .main {
          padding: 20px;
        }
        @media (min-width: 768px) {
          .main {
            padding-right: 40px;
            padding-left: 40px;
          }
        }
        .main .page-header {
          margin-top: 0;
        }
        /*
         * Placeholder dashboard ideas
         */
        .placeholders {
          margin-bottom: 30px;
          text-align: center;
        }
        .placeholders h4 {
          margin-bottom: 0;
        }
        .placeholder {
          margin-bottom: 20px;
        }
        .placeholder img {
          display: inline-block;
          border-radius: 50%;
        }
    </style>

    <script type="text/javascript">
    	// 为所有checkbox添加点击事件,不用就去掉
        function iCheck(id) {
            var table = document.getElementById("myTable");
            var row = table.getElementsByTagName("tr");
            var col = row[0].getElementsByTagName("th");

            var idEle = document.getElementById(id);
            var idTds = idEle.getElementsByTagName("td");
            var idInput = idTds[idTds.length - 1].getElementsByTagName("input");
            // 往上查找同组的
            for (var i = id; i > 0; --i) {
                var ele = document.getElementById(i);
                var tds = ele.getElementsByTagName("td");
                var input = tds[tds.length - 1].getElementsByTagName("input");
                if(idInput[0].checked == true)
                  input[0].checked = true;
                else
                  input[0].checked = false;
                if(tds[1].innerHTML != "")
                  break;
            }
            // 往下查找同组的
            for (var i = id + 1; i < row.length; ++i) {
                var ele = document.getElementById(i);
                var tds = ele.getElementsByTagName("td");
                if(tds[1].innerHTML != "")
                  break;
                var input = tds[tds.length - 1].getElementsByTagName("input");
                if(idInput[0].checked == true)
                  input[0].checked = true;
                else
                  input[0].checked = false;
            }
        } 

        /*
        table -> json -> excel
        */
        $(function() {
            $("#mainButton").click(function() {
	          var json = Table2Json("myTable");

	          function Table2Json(tableid) {
	            var txt = "[";
	            var table = document.getElementById(tableid);
	            var row = table.getElementsByTagName("tr");
	            var col = row[0].getElementsByTagName("th");
	            for (var j = 1; j < row.length; j++) {
	              var tds = row[j].getElementsByTagName("td");
	              var input = tds[tds.length - 1].getElementsByTagName("input");
	              var r = "{";
	              for (var i = 1; i < col.length - 1; i++) {
	                r += "\"" + col[i].innerHTML + "\"\:\"" + tds[i].innerHTML + "\",";
	              }
	              if(input[0].checked == true)
	              {
	                r += "\"" + col[col.length - 1].innerHTML + "\"\:\"" + 1 + "\",";
	              }
	              else
	              {
	                r += "\"" + col[col.length - 1].innerHTML + "\"\:\"" + 0 + "\",";
	              }
	              r = r.substring(0, r.length - 1)
	              r += "},";
	              txt += r;
	            }
	            txt = txt.substring(0, txt.length - 1);
	            txt += "]";
	            return txt;
	          }

	          downloadExl(JSON.parse(json));
            });
      });

      /*
      excel -> json -> table
      FileReader共有4种读取方法:
      1.readAsArrayBuffer(file):将文件读取为ArrayBuffer。
      2.readAsBinaryString(file):将文件读取为二进制字符串
      3.readAsDataURL(file):将文件读取为Data URL
      4.readAsText(file, [encoding]):将文件读取为文本,encoding缺省值为'UTF-8'
      */
      var wb;//读取完成的数据
      var rABS = false; //是否将文件读取为二进制字符串

      function importf(obj) {//导入
          if(!obj.files) {
              return;
          }
          var f = obj.files[0];
          var reader = new FileReader();
          reader.onload = function(e) {
              var data = e.target.result;
              if(rABS) {
                  wb = XLSX.read(btoa(fixdata(data)), {//手动转化
                      type: 'base64'
                  });
              } else {
                  wb = XLSX.read(data, {
                      type: 'binary'
                  });
              }
              //wb.SheetNames[0]是获取Sheets中第一个Sheet的名字
              //wb.Sheets[Sheet名]获取第一个Sheet的数据
              //document.getElementById("demo").innerHTML= JSON.stringify( XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]) );
              var jsonArray = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);
              document.getElementById("myTableBody").innerHTML = "";
              for(var i = 0; i < jsonArray.length; ++i)
              {
                  var temp = jsonArray[i];
                  if(temp.StepName == null)
                    temp.StepName = "";
                  if(i == 1 || i == 2)
                    document.getElementById("myTableBody").innerHTML += '<tr id="' + i + '"><td>'+ (i + 1) + '</td><td>' + temp.StepName + '</td><td>' + temp.NodeName + 
                        '</td><td><input type="checkbox" checked="true" οnclick="iCheck(' + i + ')" disabled="disabled" /></td></tr>';
                  else
                    document.getElementById("myTableBody").innerHTML += '<tr id="' + i + '"><td>'+ (i + 1) + '</td><td>' + temp.StepName + '</td><td>' + temp.NodeName + 
                        '</td><td><input type="checkbox" οnclick="iCheck(' + i + ')" /></td></tr>';
              }
          };
          if(rABS) {
              reader.readAsArrayBuffer(f);
          }else {
              reader.readAsBinaryString(f);
          }
      }

      function fixdata(data) { //文件流转BinaryString
          var o = "",
              l = 0,
              w = 10240;
          for(; l < data.byteLength / w; ++l) o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w, l * w + w)));
          o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w)));
          return o;
      }

      var tmpDown; //导出的二进制对象
      function downloadExl(json, type) {
          var tmpdata = json[0];
          json.unshift({});
          var keyMap = []; //获取keys
          for (var k in tmpdata) {
              keyMap.push(k);
              json[0][k] = k;
          }
          var tmpdata = [];//用来保存转换好的json 
          json.map((v, i) => keyMap.map((k, j) => Object.assign({}, {
              v: v[k],
              position: (j > 25 ? getCharCol(j) : String.fromCharCode(65 + j)) + (i + 1)
          }))).reduce((prev, next) => prev.concat(next)).forEach((v, i) => tmpdata[v.position] = {
              v: v.v
          });
          var outputPos = Object.keys(tmpdata); //设置区域,比如表格从A1到D10
          var tmpWB = {
              SheetNames: ['updateProcess'], //保存的表标题
              Sheets: {
                  'updateProcess': Object.assign({},
                      tmpdata, //内容
                      {
                          '!ref': outputPos[0] + ':' + outputPos[outputPos.length - 1] //设置填充区域
                      })
              }
          };
          tmpDown = new Blob([s2ab(XLSX.write(tmpWB, 
              {bookType: (type == undefined ? 'xlsx':type),bookSST: false, type: 'binary'}//这里的数据是用来定义导出的格式类型
              ))], {
              type: ""
          }); //创建二进制对象写入转换好的字节流
          var href = URL.createObjectURL(tmpDown); //创建对象超链接
          var a = document.getElementById("hf");

          var dateObj = new Date();
          var year = dateObj.getFullYear();
          var month = dateObj.getMonth()+1;//月  (注意:月份+1)
          var date = dateObj.getDate();//日
          var day = dateObj.getDay();
          var hours = dateObj.getHours();//小时
          var minutes = dateObj.getMinutes();//分钟
          var seconds = dateObj.getSeconds();//秒

          a.href = href; //绑定a标签
          a.download = "updateStep" + "-" + year + "-" + month + "-" + date + "-" + 
                              hours + "-" + minutes + "-" + seconds + ".xlsx";
          a.click(); //模拟点击实现下载
          setTimeout(function() { //延时释放
              URL.revokeObjectURL(tmpDown); //用URL.revokeObjectURL()来释放这个object URL
          }, 100);
      }

      function s2ab(s) { //字符串转字符流
          var buf = new ArrayBuffer(s.length);
          var view = new Uint8Array(buf);
          for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
          return buf;
      }
       // 将指定的自然数转换为26进制表示。映射关系:[0-25] -> [A-Z]。
      function getCharCol(n) {
          let temCol = '',
          s = '',
          m = 0
          while (n > 0) {
              m = n % 26 + 1
              s = String.fromCharCode(m + 64) + s
              n = (n - m) / 26
          }
          return s
      }

    </script>

  </head>

  <body>
    <!-- 导航条 -->
    <nav class="navbar navbar-inverse navbar-fixed-top">
      <div class="container-fluid">
        <div class="navbar-header">
          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
          <a class="navbar-brand" href="#">demo</a>
        </div>
        <div id="navbar" class="navbar-collapse collapse">
          <ul class="nav navbar-nav navbar-right">
          <li class="active"><a href="#">Home Page<span class="sr-only">(current)</span></a></li>
          	<li><a href="">demo</a></li>
            <li><a href="">demo</a></li>
            <li class="dropdown">
          	  <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">demo<span class="caret"></span></a>
	          <ul class="dropdown-menu">
	            
	          </ul>
        	</li>
          </ul>
          <form class="navbar-form navbar-right">
            <input type="text" class="form-control" placeholder="Search...">
          </form>
        </div>
      </div>
    </nav>

    <!-- 内容 -->
    <div class="container-fluid">
      <div class="row">

        <!-- 侧边栏 -->
        <div class="col-sm-3 col-md-2 sidebar">
          <ul class="nav nav-sidebar">
            <li class="active"><a href="#"><span class="badge">#</span> demo<span class="sr-only">(current)</span></a></li>
            <li><a href="#"><span class="badge">1</span> demo</a></li>
            <li><a href="#"><span class="badge">2</span> demo</a></li>
            <li><a href="#"><span class="badge">3</span> demo</a></li>
          </ul>
          <ul class="nav nav-sidebar">
            <li class="active"><a href="#"><span class="badge">#</span> have a try<span class="sr-only">(current)</span></a></li>
            <li><object type="application/x-shockwave-flash" style="outline:none;" data="http://cdn.abowman.com/widgets/ballclock/ballclock.swf?" width="340" height="220"><param name="movie" value="http://cdn.abowman.com/widgets/ballclock/ballclock.swf?"></param><param name="AllowScriptAccess" value="always"></param><param name="wmode" value="opaque"></param></object></li>
          </ul>
        </div>

        <!-- 主体 -->
        <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
          <div class="page-header">
  			<h2>1.上传excel文件(<a href="#">没有文件点击这里下载,请忽略</a>)</h2>
		  </div>
          <div class="form-group">
            <input type="file" id="inputFile" οnchange="importf(this)">
            <p class="help-block">注意格式:excel内容表头前2列请使用StepName,NodeName</p>
          </div>
          <br/>

          <div class="page-header">
  			<h2>2.demo</h2>
		  </div>
          <div class="table-responsive">
            <table class="table table-striped table-bordered" id="myTable">
              <thead>
                <tr>
                  <th>demo1</th>
                  <th>demo2</th>
                  <th>demo3</th>
                  <th>demo4</th>
                </tr>
              </thead>
              <tbody id="myTableBody">
                <tr>
                  <td>1</td>
                  <td>demo</td>
                  <td>demo</td>
                  <td><input type="checkbox" /></td>
                </tr>
                <tr>
                  <td>2</td>
                  <td>demo</td>
                  <td>demo</td>
                  <td><input type="checkbox" /></td>
                </tr>
                <tr>
                  <td>3</td>
                  <td>demo</td>
                  <td>demo</td>
                  <td><input type="checkbox" /></td>
                </tr>
                <tr>
                  <td>4</td>
                  <td>demo</td>
                  <td>demo</td>
                  <td><input type="checkbox" /></td>
                </tr>
                <tr>
                  <td>3</td>
                  <td>demo</td>
                  <td>demo</td>
                  <td><input type="checkbox" /></td>
                </tr>
                <tr>
                  <td>4</td>
                  <td>demo</td>
                  <td>demo</td>
                  <td><input type="checkbox" /></td>
                </tr>
              </tbody>
            </table>
          </div>
          <br/>

          <div class="page-header">
  			<h2>3.点击生成excel文件</h2>
		  </div>
          <button type="button" class="btn btn-primary btn-lg btn-block" id="mainButton">生成Excel</button>
          <!--
          <a class="btn btn-warning btn-lg btn-block" href="/cgi-bin/test.py" role="button">Python生成Excel</a>
          -->
          <a href="" download="updateStep.xlsx" id="hf">
        </div>

      </div>

    </div>

    <!-- Bootstrap core JavaScript
    ================================================== -->
    <!-- Placed at the end of the document so the pages load faster -->
    <script>window.jQuery || document.write('<script src="../../assets/js/vendor/jquery.min.js"><\/script>')</script>
    <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <!-- Just to make our placeholder images work. Don't actually copy the next line! -->
  </body>
</html>


题外话,大神js小游戏:http://abowman.com/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
js-xlsx 是一个用于解析和生成 Excel 文件的 JavaScript 库,它可以将 Excel 文件转换为 JSON 对象,也可以将 JSON 对象转换为 Excel 文件。export2excel 是一个基于 js-xlsx 的插件,它简化了导出 Excel 文件的过程。 要实现简单Excel 导入功能,可以使用 js-xlsx 的功能。首先,需要在 HTML 中引入 js-xlsx 和导入 Excel 文件的输入框。然后,监听文件输入框的 change 事件,在事件处理函数中使用 FileReader 对象读取选中的 Excel 文件,然后利用 js-xlsx 的工具函数将 Excel 文件转换为 JSON 对象,最后可以将 JSON 对象用于后续的操作。 要实现简单Excel 导出功能,可以使用 export2excel 插件。首先,需要引入 js-xlsx、export2excel 和生成 Excel 按钮到 HTML 页面上。然后,在 JavaScript 中定义要导出的数据,将数据转换为 JSON 格式。接着,定义导出 Excel 的事件处理函数,其中使用了 export2excel 插件的相关方法。在事件处理函数中,将 JSON 数据转换为 Excel 文件,然后将文件下载到本地。 综上所述,基于 js-xlsx 和 export2excel 插件实现简单Excel 导入与导出功能的步骤如下: 1. 引入 js-xlsx 和 export2excel 的库文件以及相关的 HTML 元素和按钮。 2. 编写 Excel 导入功能的事件处理函数,监听文件输入框的 change 事件,利用 FileReader 读取 Excel 文件并将其转换为 JSON 对象。 3. 编写 Excel 导出功能的事件处理函数,将要导出的数据转换为 JSON 格式,然后使用 export2excel 插件将其转换为 Excel 文件并下载到本地。 4. 根据需求,可以对导入和导出的 Excel 进行一些额外的处理,比如数据校验、格式转换等。 通过以上步骤,就可以基于 js-xlsx 和 export2excel 插件实现简单Excel 导入与导出功能了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值