VUE组件系列8:Excel上传

首先安装 

npm install -save xlsx

关键步骤如下:

1、引入

var XLSX = require("xlsx");

2、html部分

   ...........
    <div>
      <input
        type="file"
        @change="importExcel(this)"
        id="imFile"
        style="display: none"
        accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"
      />
    </div>
   ...........

3、JS部分

    ........
    uploadFile:function(){      
      // 加 判断      
      // document.getElementById("imFile").click();      
      // 点击导入按钮      
      this.imFile.click();
    },
    importExcel(file) {
      // 导入Excel并解析      
      this.fullloading = true;
      let obj = this.imFile;
      if (!obj.files) {
        this.fullloading = false;
        return;
      }
      var f = obj.files[0];
      const types = f.name.split('.')[1];
      // console.log('文件类型 '+types);
      const fileType = ['xlsx', 'xlc', 'xlm', 'xls', 'xlt', 'xlw', 'csv'].some(item => item === types);      
      if (!fileType) {
        this.fullloading = false;
        this.msg_obj={'showtype':'warning','note':'格式错误!请重新选择'};          
        return
      }      
      var reader = new FileReader();
      let $t = this;
      reader.onload = function(e) {
        var data = e.target.result;
        if ($t.rABS) {
          $t.wb = XLSX.read(btoa(this.fixdata(data)), {
            // 手动转化
            type: "base64"
          });
        } else {
          $t.wb = XLSX.read(data, {
            type: "binary"
          });
        }
        let json = XLSX.utils.sheet_to_json($t.wb.Sheets[$t.wb.SheetNames[0]]);
        // console.log(typeof json);
        // console.log(json); //这一步已经 把数据取到
        $t.dealFile($t.changdata(json)); // 解析导入数据
      };
      if (this.rABS) {
        reader.readAsArrayBuffer(f);
      } else {
        reader.readAsBinaryString(f);
      }
    },
    ........

 

整体源码

 <template>
  <div class="my_excelup">
    <button @click="uploadFile">打开Excel</button>
    <div>
      <input
        type="file"
        @change="importExcel(this)"
        id="imFile"
        style="display: none"
        accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"
      />
    </div>
    <div class="pre_more">
      <span class="pre_excel_up_bg" @click="closeshow"></span>
      <div class="pre_excel_up_conten">
        <span class="pre_more_close">
          <img src="../../assets/image/shan1.png" @click="closeshow" />
        </span>
        <div class="pre_upload">
          <div class="pre_leve_one">
            <button class="pre_btn_ok" @click="uploaddata">上传</button>
            <button class="pre_btn_ok" @click="cancel_uploaddata">取消</button>
          </div>
          <div class="pre_leve_two">
            <!-- table部分 -->
            <div class="pre_tab">
              <table class="pre_dataintable">
                <thead>
                  <slot name="tab_excelup_title"></slot>
                </thead>
                <tbody>
                  <slot
                    name="tab_excelup_tr"
                    v-for="data_tr in show_Data"
                    :item="data_tr"
                  ></slot>
                </tbody>
              </table>
            </div>
            <!-- 分页部分 -->
            <div class="pre_page" v-show="show_page">
              <ul style="text-align: right; margin-right: 20px;">
                <li>
                  当前页:<label>{{ nowpage }}</label
                  >&nbsp; 合计页:<label>{{ maxpage }}</label
                  >&nbsp;&nbsp; <a href="#" @click="firstpage">首页</a>|
                  <a href="#" @click="beforepage">上一页</a>|
                  <a href="#" @click="nextpage">下一页</a>|
                  <a href="#" @click="lastpage">尾页</a>
                  <input type="text" v-model="jumppage" value="" /><a
                    href="#"
                    @click="gopage"
                    class="go"
                    >Go</a
                  >
                </li>
              </ul>
            </div>
          </div>

          <a id="downlink"></a>
          <a id="loodlink" target="_blank"></a>

          <!-- 弹出向导层 end-->
        </div>
      </div>
    </div>
    <!-- 放置自定义组件 -->
    <per-message :message_data="msg_obj" />
    <pre-loading :pre_show_loading="fullloading" />
  </div>
</template> 

<script>
/*
名称:导入Excel 
日期:2019-06-06
作者:hj
目标:
1、默认展示一个按钮,
2、上传Excel并检查格式。样式表格通过slot设定。
3、通过则上传数据到数据库,取消则关闭展示界面
4、通过props绑定上传业务类别,以便于后台区分。
*/
// 引入xlsx
var XLSX = require("xlsx");

import { base_encode } from "@/utils/base64.js";
import { GetShort,BackSpecial,DeleteSpecialWord } from "@/utils/localstore.js";
import { BrowserGet } from '@/utils/systemSelect.js';

export default {
  name: "pre_excel_up",
  components: {    
    'per-message':()=>import("./pre_message.vue"),
    'pre-loading':()=>import("./pre_loading.vue")
  },
  data() {
    return {
      fullloading:false,
      show_exceldata:false,
      imFile: "", // 导入文件el
      xlsxJson:'',
      errorDialog: false, // 错误信息弹窗
      errorMsg: "", // 错误信息内容
      excelData:[], // 总的Excel信息
      show_Data:[], // 展示Excel信息 
      
      show_page:false,
      maxpage:'',
      nowpage:'',
      jumppage:'',
      perpage:15,
      api_url:'',
      post_data:'',

      msg_obj:{},
      errnum:''
    };
  },  
  props: {
    /* 指定上级类别 */
    pre_uplevel:{ type:Object,default:null },
    /* 指定传输类别 */
    pre_type:{ type:String,default:'' },
    /* 指定角色类别 */
    pre_role:{ type:Array,default:null },
    /* 指定步骤类别 */
    pre_step:{ type:Array,default:null },
  },
  created:function(){
      this.nowpage=1;
      this.api_url='/Data_Back';
  },
  mounted(){
    this.imFile = document.getElementById("imFile");
  },
  methods: {
    uploadFile:function(){      
      // 判断
      if(this.pre_type=='business'){        
        console.log(this.pre_uplevel.id+' '+this.pre_uplevel.name);
        if(this.pre_uplevel.id==undefined || this.pre_uplevel.name==undefined){
          this.msg_obj={'showtype':'warning','note':'请选择上级业务类别'}; 
          return;
        }  
      }else{
        this.msg_obj={'showtype':'warning','note':'没有设置传输Excel 类型'}; 
        return;
      }
      // document.getElementById("imFile").click();      
      // 点击导入按钮      
      this.imFile.click();
    },
    importExcel(file) {
      // 导入Excel并解析      
      this.fullloading = true;
      let obj = this.imFile;
      if (!obj.files) {
        this.fullloading = false;
        return;
      }
      var f = obj.files[0];
      const types = f.name.split('.')[1];
      // console.log('文件类型 '+types);
      const fileType = ['xlsx', 'xlc', 'xlm', 'xls', 'xlt', 'xlw', 'csv'].some(item => item === types);      
      if (!fileType) {
        this.fullloading = false;
        this.msg_obj={'showtype':'warning','note':'格式错误!请重新选择'};          
        return
      }      
      var reader = new FileReader();
      let $t = this;
      reader.onload = function(e) {
        var data = e.target.result;
        if ($t.rABS) {
          $t.wb = XLSX.read(btoa(this.fixdata(data)), {
            // 手动转化
            type: "base64"
          });
        } else {
          $t.wb = XLSX.read(data, {
            type: "binary"
          });
        }
        let json = XLSX.utils.sheet_to_json($t.wb.Sheets[$t.wb.SheetNames[0]]);
        // console.log(typeof json);
        // console.log(json); //这一步已经 把数据取到
        $t.dealFile($t.changdata(json)); // 解析导入数据
      };
      if (this.rABS) {
        reader.readAsArrayBuffer(f);
      } else {
        reader.readAsBinaryString(f);
      }
    },
    dealFile: function(data) {
      // 处理导入的数据
      this.imFile.value = "";
      this.fullloading = false;
      if (data.length <= 0) {        
        this.msg_obj={'showtype':'warning','note':'导入数据长度为0,请检查'};          
      } else {
        this.excelData = data;                
        this.loaddata();  
      }
    },
    changdata:function(data){
      // 转换到指定格式
      this.errnum=0;
      // console.log(this.pre_role);
      // console.log(this.pre_step);
      if(this.pre_type=='business'){
        // console.log('开始转换');
        var temp_data=[];
        for(var i=0;i<data.length;i++){
          var to={};          
          to.upid=this.pre_uplevel.id;
          to.upname=this.pre_uplevel.name
          to.name=data[i].name;
          var t_role={};
          t_role=this.checkrole(data[i].role);
          to.role_id=t_role.id;
          to.role=t_role.name;
          var t_type={};
          t_type=this.checktype(data[i].type);          
          to.type_id=t_type.id;
          to.type=t_type.name;
          to.days=data[i].days;
          // console.log(to);
          temp_data[i]=to;
        }
        data=[];
        data=temp_data;
      }
      return data;
    },
    checkrole:function(role){
      // 检查类型1
      var o={};
      var t=false;
      for(var j=0;j<this.pre_role.length;j++){
        if(this.pre_role[j].val==role){
          o.id=this.pre_role[j].id;      
          t=true;
          break;
        }
      }
      if(t){
        o.name=role;
      }else{
        o.name='[格式错误]'+role;
        this.errnum+=1;        
      }
      return o;
    },
    checktype:function(parm){
      // 检查类型2
      var o={};
      var t=false;
      for(var j=0;j<this.pre_step.length;j++){
        if(this.pre_step[j].val==parm){
          o.id=this.pre_step[j].id;      
          t=true;
          break;
        }
      }
      if(t){
        o.name=parm;
      }else{
        o.name='[格式错误]'+parm;
        this.errnum+=1;        
      }
      return o;
    },
    s2ab: function(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;
    },
    getCharCol: function(n) {
      // 将指定的自然数转换为26进制表示。映射关系:[0-25] -> [A-Z]。
      let s = "";
      let m = 0;
      while (n > 0) {
        m = (n % 26) + 1;
        s = String.fromCharCode(m + 64) + s;
        n = (n - m) / 26;
      }
      return s;
    },
    fixdata: function(data) {
      // 文件流转BinaryString
      var o = "";
      var l = 0;
      var 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;
    },
    importExcel2(file) {
      // console.log('导入');
      // console.log(file);
      var file_exp=document.getElementById("imFile");
      file = document.getElementById("imFile").files[0]; // 使用传统的input方法需要加上这一步

      const types = file.name.split('.')[1];
      const fileType = ['xlsx', 'xlc', 'xlm', 'xls', 'xlt', 'xlw', 'csv'].some(item => item === types);
      if (!fileType) {
        alert('格式错误!请重新选择')
        return
      }
      this.fullscreenLoading=true;
      this.file2Xce(file).then(tabJson => {
        if (tabJson && tabJson.length > 0) {
          this.xlsxJson = tabJson;
          console.log(tabJson);
          // console.log(this.xlsxJson[0].sheet);
          // console.log(JSON.stringify(this.xlsxJson[0].sheet));
          // this.filedata=JSON.stringify(this.xlsxJson[0].sheet);
          // this.savefile();
          var data=[];
          for(var i=0;i<tabJson.length;i++){
            var obj={};
            obj.sheet=tabJson[i].sheet;
            obj.sheetName=tabJson[i].sheetName;
            data[i]=obj;
          }
          this.filedata=JSON.stringify(data);          
          // xlsxJson就是解析出来的json数据,数据格式如下
          // [
          //   {
          //     sheetName: sheet1
          //     sheet: sheetData
          //   }
          // ]
        }
      })
    },
    file2Xce(file) {
      // 传统方式上传
      return new Promise(function(resolve, reject) {
        const reader = new FileReader()
        reader.onload = function(e) {
          const data = e.target.result
          this.wb = XLSX.read(data, {
            type: 'binary'
          })
          const result = []
          this.wb.SheetNames.forEach((sheetName) => {
            result.push({
              sheetName: sheetName,
              sheet: XLSX.utils.sheet_to_json(this.wb.Sheets[sheetName])
            })
          })
          resolve(result)
        }
        // reader.readAsBinaryString(file.raw)
        reader.readAsBinaryString(file) // 传统input方法
      })
    },
    openshow:function(){
      // console.log('状态改变 == '+this.show_filedown);      
      var Hg = $(document).height();
      // 设置背景高度
      $(".pre_excel_up_bg").height(Hg);        
      // 设置展示动画 第一次有慢入动作,第二次没有:原因是当前页面被缓存,除非重开
      $(".pre_excel_up_bg").fadeIn("3000");
      $(".pre_excel_up_conten").fadeIn("3000");         
    },
    closeshow:function(){
      $(".pre_excel_up_bg").fadeOut("3000");
      $(".pre_excel_up_conten").fadeOut("3000");         
    }, 
    firstpage:function(){
        if(Number(this.nowpage)>1){
            this.nowpage=1;
            this.loaddata();
        }else{
            this.msg_obj={'showtype':'warning','note':'已经是第一页'};
        }
    },
    beforepage:function(){
        if(Number(this.nowpage)>1){
            this.nowpage--;
            this.loaddata();
        }else{
            this.msg_obj={'showtype':'warning','note':'已经是第一页'};
        }
    },
    nextpage:function(){
        if(Number(this.nowpage)<Number(this.maxpage)){
            this.nowpage++;
            this.loaddata();
        }else{            
            this.msg_obj={'showtype':'warning','note':'已经是最后一页'};
        }
    },
    lastpage:function(){
        if(Number(this.nowpage)<Number(this.maxpage)){
            this.nowpage=this.maxpage;
            this.loaddata();
        }else{
            this.msg_obj={'showtype':'warning','note':'已经是最后一页'};
        }
    },
    gopage:function(){
        console.log('跳转到='+this.jumppage);
        if(Number(this.jumppage)>0 && Number(this.jumppage)<=Number(this.maxpage)){
            this.nowpage=this.jumppage;
            this.loaddata();
        }else{
            this.msg_obj={'showtype':'warning','note':'跳转页数不在规定范围内,请检查'+this.jumppage};
        }
    },
    loaddata:function(){
      this.openshow();
      if(this.excelData.length>this.perpage){
        this.show_page=true;
      }else{
        this.show_page=false;
      }
      this.show_Data=[];
      var j=0
      for(var i=0;i<this.excelData.length;i++){
        if(i>=((this.nowpage-1)*this.perpage)&&i<(this.nowpage*this.perpage-1)){
          this.show_Data[j]=this.excelData[i];
          j++;
        }
      }
      console.log(this.show_Data);
    },
    uploaddata:function(){
      console.log('上传检查');
      if (this.errnum > 0) {        
        this.msg_obj={'showtype':'warning','note':'发现格式错误'+this.errnum+'处,请检查'};          
        return;
      }
      console.log('上传通过');
      this.post_data='';
      if(this.pre_type=='business'){
        var tdata='[';
        for(var i=0;i<this.excelData.length;i++){
          tdata +=
            '{"name":"'+DeleteSpecialWord(this.excelData[i].name)+
            '","upid":"' +DeleteSpecialWord(this.excelData[i].upid) +          
            '","rid":"' +DeleteSpecialWord(this.excelData[i].role_id) +          
            '","tid":"' +DeleteSpecialWord(this.excelData[i].type_id) +          
            '","day":"' +DeleteSpecialWord(this.excelData[i].days) +'"},';
        }
        tdata=tdata.substring(0,(tdata.length-1));
        tdata+=']'
        this.post_data ='{"method":"Excel_Data","data":"' + base_encode(tdata) + '"}';
      }      
      this.neworupdate();
    },
    cancel_uploaddata:function(){
      console.log('取消上传');
      this.excelData=[];
      this.pre_step=[];
      this.pre_role=[];
      this.post_data='';
      this.closeshow();
    },
    neworupdate:function() {
      // console.log(this.api_url);
      // console.log(this.pre_post_upd);         
      if (this.post_data =='') {        
        this.msg_obj={'showtype':'warning','note':'上传数据为空,请检查'};          
        return;
      }

      this.fullloading=true;
      this.$post(
        this.api_url,
        this.post_data,
      ).then(res => {
        this.fullloading=false;
        try {         
          console.log(res);
          res=JSON.parse(res); 
          console.log(res.data);         
          if (res.status == 1) {
            this.msg_obj={'showtype':'ok','note':res.msg};
            // this.loaddata();
            this.RefreshData();
            this.closeshow();
          } else {
            this.msg_obj={'showtype':'err','note':res.msg};
          }
          // this.initTable();
        } catch (ex) {
          this.msg_obj={'showtype':'warning','note':"查询失败"+ex};
        }
      });
    },
    RefreshData:function(){
      console.log(this.pre_uplevel);
      var t='';
      for(var i=0;i<(Math.random()*10);i++){
        t+=' '
      }
      this.$emit("my-excel",'',this.pre_uplevel.name+t,this.pre_uplevel);   
    }
  }
};

</script>


<style scoped>
.my_excelup {
  display: inline-block;
  margin-left: 10px;
}
.pre_excel_up_bg {
  width: 100%;
  background: #000000;
  opacity: 0.5;
  position: fixed;
  top: 0;
  left: 0;
  height: 1340px;
  display: none;
  z-index: 99;
}

.pre_more {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
}

.pre_excel_up_conten {
  width: 70%;
  height: auto;
  margin: 0 auto;
  background: #faf5f5;
  position: fixed;
  top: 20%;
  border-radius: 3px;
  display: none;
  z-index: 999;
  /* left: 40%; */
  left: 15%;
  /* text-align: center; */
}
.pre_more_close {
  position: absolute !important;
  right: -8px !important;
  top: -6px !important;
  font-size: 30px !important;
  color: #b4b4b4;
  cursor: pointer;
  font-weight: normal;
}

.pre_excel_up_conten > div {
  /* margin-top: 15px; */
  width: 100%;
  text-align: center;
  padding-left: 5px;
  padding-right: 5px;
}
.pre_excel_up_conten > div > * {
  /* display: inline-block; */
  border-radius: 5px;
  /* line-height: 15px; */
}

.pre_excel_up_conten > div > span {
  width: 100px;
  /* margin-left: -40px; */
  text-align: right;
}
.pre_excel_up_conten > div > input {
  width: 168px;
  margin-right: 32px;
}
.pre_excel_up_conten > div > button {
  /* margin-left: 20%; */
  background-color: rgba(68, 70, 238, 0.986);
  color: white;
  font-optical-sizing: 16px;
  cursor: pointer;
}

.pre_upload {
  width: 100%;
  min-height: 200px;
  height: 100%;
  background-color: azure;
  text-align: center;
  /* padding: 10px 20px 10px 20px; */
}
.pre_leve_one {
  height: 25px;
  text-align: left;
  padding-top: 18px;
  padding-left: 15px;
}
.pre_leve_one > button {
  margin-left: 10px;
  border-radius: 2px;
  background-color: #fff;
  color: #000000;
  padding: 2px 10px 2px 10px;
}

.pre_leve_two {
  /* padding: 5px; */
  margin: 15px;
  margin-top: 15px;
  border: 1px solid #191970;
  min-height: 200px;
  height: auto;
}

.pre_dataintable {
  margin-top: 15px;
  border-collapse: collapse;
  border: 1px solid #aaa;
  width: 95%;
  /* padding 没有作用 */
  /* padding: 0px 5px 10px 5px; */
  position: relative;
  left: 2%;
}
.pre_dataintable th {
  vertical-align: baseline;
  padding: 5px 15px 5px 6px;
  background-color: rgb(87, 201, 230);
  border: 1px solid #3f3f3f;
  text-align: left;
  color: #000000;
  font-size: 16px;
  font-weight: bolder;
}
.pre_dataintable td {
  /* vertical-align: center; */
  text-align: left;
  padding: 6px 15px 6px 6px;
  border: 1px solid #aaa;
}
.pre_dataintable tr:nth-child(odd) {
  background-color: #f5f5f5;
}
.pre_dataintable tr:nth-child(even) {
  background-color: #fff;
}

.pre_tab_name {
  cursor: pointer;
  width: 100px;
  text-align: left;
  /* white-space: nowrap; */
  word-break: break-all;
  overflow: hidden;
  /* text-overflow: ellipsis; */
  /* display: -webkit-box; */
  /* -webkit-line-clamp: auto; */
  /* -webkit-box-orient: vertical; */
}
.pre_tab_name:hover {
  cursor: pointer;
  background-color: #aaa;
}

.td_btn {
  text-align: center !important;
}

.td_btn > button {
  border-radius: 3px;
  width: 100px;
  height: 28px;
  padding: 1px 2px 2px 2px;
}
.td_btn > button:hover {
  background-color: rgba(155, 222, 231, 0.986);
  cursor: pointer;
}

/* 翻页样式 */
.pre_block {
  width: 100%;
  margin-top: 5px;
  margin-bottom: 5px;
}
.pre_block > ul {
  text-align: right;
  list-style: none;
}
.pre_block > ul > li > a {
  text-decoration: none;
}
.pre_block > ul > li > .go {
  display: inline-block;
  width: 40px;
  height: 20px;
  border: 1px solid #cccccc;
  background: #024aee;
  color: #fff;
  border-radius: 4px;
  text-align: center;
  margin-left: 5px;
}
.pre_block > ul > li > a:hover {
  color: #394656;
}
.pre_btn_ok {
  background: rgba(68, 70, 238, 0.986);
  color: white;
  font-optical-sizing: 16px;
  cursor: pointer;
}
.pre_btn_ok:hover {
  background: rgba(161, 161, 192, 0.986);
}
</style>

 

转载于:https://my.oschina.net/qingqingdego/blog/3060547

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值