封装 x-spreadsheet 带样式导入导出

Posted lee576

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了封装 x-spreadsheet 带样式导入导出相关的知识,希望对你有一定的参考价值。

接上两篇

vue 下使用 exceljs + x-spreadsheet 带样式导入Excel

vue 下使用 exceljs + x-spreadsheet 带样式导出Excel

下面封装好一个组件

<template>
  <div ref="sheetContainer" v-bind:id="sheetContainerId" class="grid"></div>
</template>

<script>
import Spreadsheet from "x-data-spreadsheet";
import zhCN from "x-data-spreadsheet/src/locale/zh-cn";
import _ from "lodash";
import * as Excel from "exceljs/dist/exceljs";
import * as tinycolor from "tinycolor2";
import  Guid  from "js-guid";
export default 
  name: "xspreadsheet",
  props: 
    ColumnCount: 
      type: Number,
      default: () => 50,
    ,
    ColumnWidth: 
      type: Number,
      default: () => 100,
    ,
    RowCount: 
      type: Number,
      default: () => 9999,
    ,
    SheetName: 
      type: String,
      default: () => [],
    ,
    Headers: 
      type: Array,
      default: () => [],
    ,
    Records: 
      type: Array,
      default: () => [],
    ,
    /*表头样式*/
    HeaderStyle: 
      type: Object,
      default: () => 
        return 
          //bgcolor: "#f4f5f8",
          textwrap: true,
          color: "#900b09",
          align: "center",
          valign: "middle",
          border: 
            top: ["thin", "#1E1E1E"],
            bottom: ["thin", "#1E1E1E"],
            right: ["thin", "#1E1E1E"],
            left: ["thin", "#1E1E1E"],
          ,
          font: 
            bold: true,
          ,
        ;
      ,
    ,
    /*表体样式*/
    RecordStyle: 
      type: Object,
      default: () => 
        return 
          //bgcolor: "#f4f5f8",
          textwrap: true,
          color: "#900b09",
          align: "left",
          valign: "middle",
          border: 
            top: ["thin", "#1E1E1E"],
            bottom: ["thin", "#1E1E1E"],
            right: ["thin", "#1E1E1E"],
            left: ["thin", "#1E1E1E"],
          ,
          font: 
            bold: false,
          ,
        ;
      ,
    ,
    File: 
      type: null,
      default: () => null,
    ,
    ExportJsonProperties: 
      type: Array,
      default: () => [],
    ,
  ,
  data() 
    return 
      xs: null,
      sheetContainerId: Guid.newGuid().toString(),
      DataSource: []
    ;
  ,
  mounted() 
    this.$nextTick(() => 
      this.init();
    );
  ,
  watch: 
    File: 
      handler(newV, oldV) 
        this.$nextTick(() => 
          this.loadExcelFile(newV);
        );
      ,
    ,
    Headers: 
      deep: true,
      handler(newV) 
        let result = [];
        if (Array.isArray(newV) && newV.length > 0) 
          let headerRow =  cells: [] ;
          for (let i = 0; i < newV.length; i++) 
            headerRow.cells.push(
              text: newV[i],
              editable: false,
              style: 0,
            );
          
          result.push(headerRow);
        
        if (Array.isArray(this.Records) && this.Records.length > 0) 
          for (let i = 0; i < this.Records.length; i++) 
            let recordRow =  cells: [] ;
            if (JSON.stringify(this.Records[i]) != "") 
              for(let k=0; k < this.ExportJsonProperties.length; k++) 
                recordRow.cells.push(
                  text: this.Records[i][this.ExportJsonProperties[k]] + "",
                  editable: true,
                  style: 1,
                );
              
             else 
              for (let i = 0; i < this.ColumnCount; i++) 
                recordRow.cells.push(
                  text: "",
                  editable: true,
                  style: 1,
                );
              
            
            result.push(recordRow);
          
        
        this.DataSource = result;
      ,
    ,
    Records: 
      deep: true,
      handler(newV) 
        let result = [];
        if (Array.isArray(this.Headers) && this.Headers.length > 0) 
          let headerRow =  cells: [] ;
          for (let i = 0; i < this.Headers.length; i++) 
            headerRow.cells.push(
              text: this.Headers[i],
              editable: false,
              style: 0,
            );
          
          result.push(headerRow);
        
        if (Array.isArray(newV) && newV.length > 0) 
          for (let i = 0; i < newV.length; i++) 
            let recordRow =  cells: [] ;
            if (JSON.stringify(newV[i]) != "") 
              for(let k=0; k < this.ExportJsonProperties.length; k++) 
                recordRow.cells.push(
                  text: newV[i][this.ExportJsonProperties[k]] + "",
                  editable: true,
                  style: 1,
                );
              
             else 
              for (let i = 0; i < this.ColumnCount; i++) 
                recordRow.cells.push(
                  text: "",
                  editable: true,
                  style: 1,
                );
              
            
            result.push(recordRow);
          
        
        this.DataSource = result;
      
    ,
    DataSource : 
      deep : true,
      handler(newW) 
        if (this.xs) 
          console.log(newW)
          this.xs.loadData([
            
              name: this.SheetName,
              styles: [this.HeaderStyle, this.RecordStyle],
              rows: newW,
            ,
          ]);
        
      
    
  ,
  methods: 
    // 初始化表格
    init() 
      if (
        this.$refs.sheetContainer &&
        this.$refs.sheetContainer.offsetHeight &&
        this.$refs.sheetContainer.offsetWidth
      ) 
        //设置中文
        Spreadsheet.locale("zh-cn", zhCN);
        this.xs = new Spreadsheet(
          document.getElementById(this.sheetContainerId),
          
            mode: "edit",
            showToolbar: true,
            showGrid: true,
            showContextmenu: true,
            showBottomBar: true,
            view: 
              height: () =>
                this.$refs.sheetContainer &&
                this.$refs.sheetContainer.offsetHeight &&
                _.isNumber(this.$refs.sheetContainer.offsetHeight)
                  ? this.$refs.sheetContainer.offsetHeight
                  : 0,
              width: () =>
                this.$refs.sheetContainer &&
                this.$refs.sheetContainer.offsetWidth &&
                _.isNumber(this.$refs.sheetContainer.offsetWidth)
                  ? this.$refs.sheetContainer.offsetWidth
                  : 0,
            ,
            formats: [],
            fonts: [],
            formula: [],
            row: 
              len: this.RowCount,
              height: 25,
            ,
            col: 
              len: this.ColumnCount,
              width: this.ColumnWidth,
              indexWidth: 60,
              minWidth: 60,
            ,
          
        );
        this.loadData();
      
    ,
    loadData() 
      if (this.xs) 
        this.xs.loadData([
          
            name: this.SheetName,
            styles: [this.HeaderStyle, this.RecordStyle],
            rows: this.DataSource,
          ,
        ]);
      
    ,
    // 导入excel
    loadExcelFile(file) 
      if (file) 
        const wb = new Excel.Workbook();
        const reader = new FileReader();
        reader.readAsArrayBuffer(file);
        reader.onload = () => 
          const buffer = reader.result;
          // 微软的 Excel ColorIndex 一个索引数字对应一个颜色
          const indexedColors = [
            "000000",
            "FFFFFF",
            "FF0000",
            "00FF00",
            "0000FF",
            "FFFF00",
            "FF00FF",
            "00FFFF",
            "000000",
            "FFFFFF",
            "FF0000",
            "00FF00",
            "0000FF",
            "FFFF00",
            "FF00FF",
            "00FFFF",
            "800000",
            "008000",
            "000080",
            "808000",
            "800080",
            "008080",
            "C0C0C0",
            "808080",
            "9999FF",
            "993366",
            "FFFFCC",
            "CCFFFF",
            "660066",
            "FF8080",
            "0066CC",
            "CCCCFF",
            "000080",
            "FF00FF",
            "FFFF00",
            "00FFFF",
            "800080",
            "800000",
            "008080",
            "0000FF",
            "00CCFF",
            "CCFFFF",
            "CCFFCC",
            "FFFF99",
            "99CCFF",
            "FF99CC",
            "CC99FF",
            "FFCC99",
            "3366FF",
            "33CCCC",
            "99CC00",
            "FFCC00",
            "FF9900",
            "FF6600",
            "666699",
            "969696",
            "003366",
            "339966",
            "003300",
            "333300",
            "993300",
            "993366",
            "333399",
            "333333",
          ];
          wb.xlsx.load(buffer).then((workbook) => 
            let workbookData = [];
            workbook.eachSheet((sheet, sheetIndex) => 
              // 构造x-data-spreadsheet 的 sheet 数据源结构
              let sheetData = 
                name: sheet.name,
                styles: [],
                rows: ,
                merges: [],
              ;
              // 收集合并单元格信息
              let mergeAddressData = [];
              for (let mergeRange in sheet._merges) 
                sheetData.merges.push(sheet._merges[mergeRange].shortRange);
                let mergeAddress = ;
                // 合并单元格起始地址
                mergeAddress.startAddress = sheet._merges[mergeRange].tl;
                // 合并单元格终止地址
                mergeAddress.endAddress = sheet._merges[mergeRange].br;
                // Y轴方向跨度
                mergeAddress.YRange =
                  sheet._merges[mergeRange].model.bottom -
                  sheet._merges[mergeRange].model.top;
                // X轴方向跨度
                mergeAddress.XRange =
                  sheet._merges[mergeRange].model.right -
                  sheet._merges[mergeRange].model.left;
                mergeAddressData.push(mergeAddress);
              
              sheetData.cols = ;
              for (let i = 0; i < sheet.columns.length; i++) 
                sheetData.cols[i.toString()] = ;
                if (sheet.columns[i].width) 
                  // 不知道为什么从 exceljs 读取的宽度显示到 x-data-spreadsheet 特别小, 这里乘以8
                  sheetData.cols[i.toString()].width =
                    sheet.columns[i].width * 8;
                 else 
                  // 默认列宽
                  sheetData.cols[i.toString()].width = 100;
                
              

              // 遍历行
              sheet.eachRow((row, rowIndex) => 
                sheetData.rows[(rowIndex - 1).toString()] =  cells:  ;
                //includeEmpty = false 不包含空白单元格
                row.eachCell(
                   includeEmpty: true ,
                  function (cell, colNumber) 
                    let cellText = "";
                    if (cell.value && cell.value.result) 
                      // Excel 单元格有公式
                      cellText = cell.value.result;
                     else if (cell.value && cell.value.richText) 
                      // Excel 单元格是多行文本
                      for (let text in cell.value.richText) 
                        // 多行文本做累加
                        cellText += cell.value.richText[text].text;
                      
                     else 
                      // Excel 单元格无公式
                      cellText = cell.value;
                    

                    //解析单元格,包含样式
                    //*********************单元格存在背景色******************************
                    // 单元格存在背景色
                    let backGroundColor = null;
                    if (
                      cell.style.fill &&
                      cell.style.fill.fgColor &&
                      cell.style.fill.fgColor.argb
                    ) 
                      // 8位字符颜色先转rgb再转16进制颜色
                      backGroundColor = ((val) => 
                        val = val.trim().toLowerCase(); //去掉前后空格
                        let color = ;
                        try 
                          let argb =
                            /^#?([a-f\\d]2)([a-f\\d]2)([a-f\\d]2)([a-f\\d]2)$/i.exec(
                              val
                            );
                          color.r = parseInt(argb[2], 16);
                          color.g = parseInt(argb[3], 16);
                          color.b = parseInt(argb[4], 16);
                          color.a = parseInt(argb[1], 16) / 255;
                          return tinycolor(
                            `rgba($color.r, $color.g, $color.b, $color.a)`
                          ).toHexString();
                         catch (e) 
                          console.log(e);
                        
                      )(cell.style.fill.fgColor.argb);
                    

                    if (backGroundColor) 
                      cell.style.bgcolor = backGroundColor;
                    
                    //*************************************************************************** */

                    //*********************字体存在背景色******************************
                    // 字体颜色
                    let fontColor = null;
                    if (
                      cell.style.font &&
                      cell.style.font.color &&
                      cell.style.font.color.argb
                    ) 
                      // 8位字符颜色先转rgb再转16进制颜色
                      fontColor = ((val) => 
                        val = val.trim().toLowerCase(); //去掉前后空格
                        let color = ;
                        try 
                          let argb =
                            /^#?([a-f\\d]2)([a-f\\d]2)([a-f\\d]2)([a-f\\d]2)$/i.exec(
                              val
                            );
                          color.r = parseInt(argb[2], 16);
                          color.g = parseInt(argb[3], 16);
                          color.b = parseInt(argb[4], 16);
                          color.a = parseInt(argb[1], 16) / 255;
                          return tinycolor(
                            `rgba($color.r, $color.g, $color.b, $color.a)`
                          ).toHexString();
                         catch (e) 
                          console.log(e);
                        
                      )(cell.style.font.color.argb);
                    
                    if (fontColor) 
                      //console.log(fontColor)
                      cell.style.color = fontColor;
                    
                    //************************************************************************ */

                    // exceljs 对齐的格式转成 x-date-spreedsheet 能识别的对齐格式
                    if (
                      cell.style.alignment &&
                      cell.style.alignment.horizontal
                    ) 
                      cell.style.align = cell.style.alignment.horizontal;
                      cell.style.valign = cell.style.alignment.vertical;
                    

                    //处理合并单元格
                    let mergeAddress = _.find(mergeAddressData, function (o) 
                      return o.startAddress == cell._address;
                    );
                    if (mergeAddress) 
                      // 遍历的单元格属于合并单元格
                      if (cell.master.address != mergeAddress.startAddress) 
                        // 不是合并单元格中的第一个单元格不需要计入数据源
                        return;
                      
                      // 说明是合并单元格区域的起始单元格
                      sheetData.rows[(rowIndex - 1).toString()].cells[
                        (colNumber - 1).toString()
                      ] = 
                        text: cellText,
                        style: 0,
                        merge: [mergeAddress.YRange, mergeAddress.XRange],
                      ;

                      //解析单元格,包含样式
                      let xsCellStyle = _.cloneDeep(cell.style);
                      xsCellStyle.border = ;
                      // 边框线
                      if (
                        cell.style.border &&
                        JSON.stringify(cell.style.border) != ""
                      ) 
                        let coloneStyle = cell.style.border;
                        xsCellStyle.border = ;
                        if (coloneStyle.bottom) 
                          xsCellStyle.border.bottom = [];
                          xsCellStyle.border.bottom[0] =
                            coloneStyle.bottom.style;
                          if (_.isString(coloneStyle.bottom.color)) 
                            xsCellStyle.border.bottom[1] =
                              coloneStyle.bottom.color;
                           else 
                            xsCellStyle.border.bottom[1] = "#000000";
                          
                        
                        if (coloneStyle.right) 
                          xsCellStyle.border.right = [];
                          xsCellStyle.border.right[0] = coloneStyle.right.style;
                          if (_.isString(coloneStyle.right.color)) 
                            xsCellStyle.border.right[1] =
                              coloneStyle.right.color;
                           else 
                            xsCellStyle.border.right[1] = "#000000";
                          
                        
                        if (coloneStyle.left) 
                          xsCellStyle.border.left = [];
                          xsCellStyle.border.left[0] = coloneStyle.left.style;
                          if (_.isString(coloneStyle.left.color)) 
                            xsCellStyle.border.left[1] = coloneStyle.left.color;
                           else 
                            xsCellStyle.border.left[1] = "#000000";
                          
                        
                        if (coloneStyle.top) 
                          xsCellStyle.border.top = [];
                          xsCellStyle.border.top[0] = coloneStyle.top.style;
                          if (_.isString(coloneStyle.top.color)) 
                            xsCellStyle.border.top[1] = coloneStyle.top.color;
                           else 
                            xsCellStyle.border.top[1] = "#000000";
                          
                        
                      

                      sheetData.styles.push(xsCellStyle);
                      //对应的style存放序号
                      sheetData.rows[(rowIndex - 1).toString()].cells[
                        (colNumber - 1).toString()
                      ].style = sheetData.styles.length - 1;
                     else 
                      // 非合并单元格
                      sheetData.rows[(rowIndex - 1).toString()].cells[
                        (colNumber - 1).toString()
                      ] =  text: cellText, style: 0 ;
                      //解析单元格,包含样式
                      let xsCellStyle = _.cloneDeep(cell.style);
                      xsCellStyle.border = ;

                      // 边框线
                      if (
                        cell.style.border &&
                        JSON.stringify(cell.style.border) != ""
                      ) 
                        let coloneStyle = cell.style.border;
                        xsCellStyle.border = ;
                        if (coloneStyle.bottom) 
                          xsCellStyle.border.bottom = [];
                          xsCellStyle.border.bottom[0] =
                            coloneStyle.bottom.style;
                          if (_.isString(coloneStyle.bottom.color)) 
                            xsCellStyle.border.bottom[1] =
                              coloneStyle.bottom.color;
                           else 
                            xsCellStyle.border.bottom[1] = "#000000";
                          
                        
                        if (coloneStyle.right) 
                          xsCellStyle.border.right = [];
                          xsCellStyle.border.right[0] = coloneStyle.right.style;
                          if (_.isString(coloneStyle.right.color)) 
                            xsCellStyle.border.right[1] =
                              coloneStyle.right.color;
                           else 
                            xsCellStyle.border.right[1] = "#000000";
                          
                        
                        if (coloneStyle.left) 
                          xsCellStyle.border.left = [];
                          xsCellStyle.border.left[0] = coloneStyle.left.style;
                          if (_.isString(coloneStyle.left.color)) 
                            xsCellStyle.border.left[1] = coloneStyle.left.color;
                           else 
                            xsCellStyle.border.left[1] = "#000000";
                          
                        
                        if (coloneStyle.top) 
                          xsCellStyle.border.top = [];
                          xsCellStyle.border.top[0] = coloneStyle.top.style;
                          if (_.isString(coloneStyle.top.color)) 
                            xsCellStyle.border.top[1] = coloneStyle.top.color;
                           else 
                            xsCellStyle.border.top[1] = "#000000";
                          
                        
                      

                      sheetData.styles.push(xsCellStyle);
                      //对应的style存放序号
                      sheetData.rows[(rowIndex - 1).toString()].cells[
                        (colNumber - 1).toString()
                      ].style = sheetData.styles.length - 1;
                    
                  
                );
              );
              workbookData.push(sheetData);
            );
            this.xs.loadData(workbookData);
          );
        ;
      
    ,
    // 导出excel
    exportExcel(fileName) 
      const exceljsWorkbook = new Excel.Workbook();
      exceljsWorkbook.modified = new Date();
      this.xs.getData().forEach(function (xws) 
        let rowobj = xws.rows;
        // 构造exceljs文档结构
        const exceljsSheet = exceljsWorkbook.addWorksheet(xws.name);
        // 读取列宽
        let sheetColumns = [];
        let colIndex = 0;
        for (let col in xws.cols) 
          if (xws.cols[col].width) 
            sheetColumns.push(
              header: colIndex + "",
              key: colIndex + "",
              width: xws.cols[col].width / 8,
            );
          
          colIndex++;
        
        exceljsSheet.columns = sheetColumns;
        for (let ri = 0; ri < rowobj.len; ++ri) 
          let row = rowobj[ri];
          if (!row) continue;
          // 构造exceljs的行(如果尚不存在,则将返回一个新的空对象)
          const exceljsRow = exceljsSheet.getRow(ri + 1);
          Object.keys(row.cells).forEach(function (k) 
            let idx = +k;
            if (isNaN(idx)) return;
            const exceljsCell = exceljsRow.getCell(Number(k) + 1);
            exceljsCell.value = row.cells[k].text;
            
            if (
              xws.styles[row.cells[k].style]
            ) 
              // 垂直对齐方式
              if (xws.styles[row.cells[k].style].valign) 
                if (
                  exceljsCell.alignment == undefined ||
                  exceljsCell.alignment == null
                ) 
                  exceljsCell.alignment = ;
                
                exceljsCell.alignment.vertical = 
                  xws.styles[row.cells[k].style].valign;
              
              // 水平对齐方式
              if (xws.styles[row.cells[k].style].align) 
                if (
                  exceljsCell.alignment == undefined ||
                  exceljsCell.alignment == null
                ) 
                  exceljsCell.alignment = ;
                
                exceljsCell.alignment.horizontal =
                  xws.styles[row.cells[k].style].align;
                
              // exceljsSheet.getCell(exceljsCell._address).alignment =  vertical: xws.styles[row.cells[k].style].valign, horizontal: xws.styles[row.cells[k].style].align 
            

            // 边框
            if (
              JSON.stringify(xws.styles[row.cells[k].style]) != "" &&
              JSON.stringify(xws.styles[row.cells[k].style].border) != ""
            ) 
              //exceljsCell.border = xws.styles[row.cells[k].style].border;
              exceljsCell.border = ;
              // bottom
              if (
                xws.styles[row.cells[k].style].border.bottom &&
                Array.isArray(xws.styles[row.cells[k].style].border.bottom) &&
                xws.styles[row.cells[k].style].border.bottom.length == 2
              ) 
                exceljsCell.border.bottom = ;
                exceljsCell.border.bottom.style =
                  xws.styles[row.cells[k].style].border.bottom[0];
                exceljsCell.border.bottom.color = ;
                //exceljsCell.border.bottom.color.indexed = 64
                exceljsCell.border.bottom.color =
                  xws.styles[row.cells[k].style].border.bottom[1];
              
              // left
              if (
                xws.styles[row.cells[k].style].border.left &&
                Array.isArray(xws.styles[row.cells[k].style].border.left) &&
                xws.styles[row.cells[k].style].border.left.length == 2
              ) 
                exceljsCell.border.left = ;
                exceljsCell.border.left.style =
                  xws.styles[row.cells[k].style].border.left[0];
                exceljsCell.border.left.color = ;
                //exceljsCell.border.left.color.indexed = 64
                exceljsCell.border.left.color =
                  xws.styles[row.cells[k].style].border.left[1];
              
              // right
              if (
                xws.styles[row.cells[k].style].border.right &&
                Array.isArray(xws.styles[row.cells[k].style].border.right) &&
                xws.styles[row.cells[k].style].border.right.length == 2
              ) 
                exceljsCell.border.right = ;
                exceljsCell.border.right.style =
                  xws.styles[row.cells[k].style].border.right[0];
                exceljsCell.border.right.color = ;
                //exceljsCell.border.right.color.indexed = 64
                exceljsCell.border.right.color =
                  xws.styles[row.cells[k].style].border.right[1];
              
              // top
              if (
                xws.styles[row.cells[k].style].border.top &&
                Array.isArray(xws.styles[row.cells[k].style].border.top) &&
                xws.styles[row.cells[k].style].border.top.length == 2
              ) 
                exceljsCell.border.top = ;
                exceljsCell.border.top.style =
                  xws.styles[row.cells[k].style].border.top[0];
                exceljsCell.border.top.color = ;
                //exceljsCell.border.right.color.indexed = 64
                exceljsCell.border.top.color =
                  xws.styles[row.cells[k].style].border.top[1];
              
            

            // 背景色
            if (xws.styles[row.cells[k].style].bgcolor) 
              let rgb = tinycolor(
                xws.styles[row.cells[k].style].bgcolor
              ).toRgb();
              let rHex = parseInt(rgb.r).toString(16).padStart(2, "0");
              let gHex = parseInt(rgb.g).toString(16).padStart(2, "0");
              let bHex = parseInt(rgb.b).toString(16).padStart(2, "0");
              let aHex = parseInt(rgb.a).toString(16).padStart(2, "0");
              let _bgColor = aHex + rHex + gHex + bHex;
              // 设置exceljs背景色
              exceljsCell.fill = 
                type: "pattern",
                pattern: "solid",
                fgColor:  argb: _bgColor ,
              ;
            
            // 字体
            exceljsCell.font = xws.styles[row.cells[k].style].font;
            // 字体颜色
            if (xws.styles[row.cells[k].style].color) 
              let rgb = tinycolor(xws.styles[row.cells[k].style].color).toRgb();
              let rHex = parseInt(rgb.r).toString(16).padStart(2, "0");
              let gHex = parseInt(rgb.g).toString(16).padStart(2, "0");
              let bHex = parseInt(rgb.b).toString(16).padStart(2, "0");
              let aHex = parseInt(rgb.a).toString(16).padStart(2, "0");
              let _fontColor = aHex + rHex + gHex + bHex;
              exceljsCell.font.color =  argb: _fontColor ;
            
            // 合并单元格
            if (row.cells[k].merge) 
              // 开始行
              let startRow = ri + 1;
              // 结束行,加上Y轴跨度
              let endRow = startRow + row.cells[k].merge[0];
              // 开始列
              let startColumn = Number(k) + 1;
              // 结束列,加上X轴跨度
              let endColumn = startColumn + row.cells[k].merge[1];
              // 按开始行,开始列,结束行,结束列合并
              exceljsSheet.mergeCells(startRow, startColumn, endRow, endColumn);
            
          );
        
      );
      // writeBuffer 把写好的excel 转换成 ArrayBuffer 类型
      exceljsWorkbook.xlsx.writeBuffer().then((data) => 
        const link = document.createElement("a");
        // Blob 实现下载excel
        const blob = new Blob([data], 
          type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8",
        );
        link.href = window.URL.createObjectURL(blob);
        link.download = `$fileName.xlsx`;
        link.click();
      );
    ,
    // 导出json
    exportJson() 
      let sheetsData = this.xs.getData();
      let rows = Object.entries(sheetsData[0].rows);
      let jsonData = [];
      if (Array.isArray(this.ExportJsonProperties) && this.ExportJsonProperties.length > 0) 
        // 遍历数据,跳过第一行表头
        for (let i = 1; i < rows.length; i++) 
          if (rows[i] && rows[i][1] && rows[i][1].cells) 
            let row = Object.entries(rows[i][1].cells);
            // 构造行对象
            let JsonRow = ;
            for (let k = 0; k < row.length; k++) 
              let cells = row[k];
              JsonRow[this.ExportJsonProperties[k]] = cells[1].text;
            
            jsonData.push(JsonRow);
          
        
      
      return jsonData;
    ,
  ,
  destroyed() ,
;
</script>
<style>
</style>

调用组件的页面

<template>
  <div class="container">
    <div class="toolbar">
      <input
        type="file"
        class="choose"
        @change="loadExcelFile"
        accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel"
      />
      <el-button @click="exportJson">导出JSON</el-button>
      <el-button @click="exportExcel">导出xlsx</el-button>
    </div>
    <Sheet ref="Sheet" SheetName="调配订单变量" :ExportJsonProperties="JsonProperties" :File="file" :Headers="headers" :ColumnCount="headers.length" :ColumnWidth="300" :RowCount="records.length + 1" :Records="records"></Sheet>
  </div>
</template>

<script>
import Sheet from "@/components/SpreadSheet.vue";
export default 
  components:  Sheet ,
  data() 
    return 
      file : null,
      headers : ['序号','订单号','产品名称','订单状态','计划生产数量','实际生产数量','单位','计划开始时间','计划结束时间','调配罐',
      'TK101出油比率','TK101出油数量',
      'TK102出油比率','TK102出油数量',
      'TK103出油比率','TK103出油数量',
      'TK104出油比率','TK104出油数量',
      'TK108出油比率','TK108出油数量',
      'TK109出油比率','TK109出油数量',
      '添加剂1','添加剂2'],
      records: [,,,,,,,,,,],
      // 定义导出的Json结构
      JsonProperties: [
        'Index',
        'OrderNo',
        'ProductName',
        'ProductStatus',
        'PlanQuantity',
        'RealQuantity',
        'Unit',
        'StartDate',
        'EndDate',
        'MixTank',
        'TK101Rate',
        'TK101Quantity',
        'TK102Rate',
        'TK102Quantity',
        'TK103Rate',
        'TK103Quantity',
        'TK104Rate',
        'TK104Quantity',
        'TK108Rate',
        'TK108Quantity',
        'TK109Rate',
        'TK109Quantity',
        'Additive1',
        'Additive2'
      ]
    
  ,
  mounted() ,
  methods: 
    loadExcelFile(e) 
      this.file = e.target.files[0]
    ,
    exportJson() 
      let json = this.$refs.Sheet.exportJson()
      console.log(json)
    ,
    exportExcel() 
      this.$refs.Sheet.exportExcel('调配订单变量')
    ,
  ,
;
</script>
<style lang="less" scoped>
.container 
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  .toolbar 
    width: 100%;
    height: 50px;
  
  .grid 
    width: 100%;
    height: calc(100% - 80px);
  
  /deep/ .x-spreadsheet-toolbar 
    padding: 0px;
    width: calc(100% - 2px) !important;
  

.choose::-webkit-file-upload-button 
  color: white;
  display: inline-block;
  background: #409EFF;
  border: none;
  padding: 12px 20px;
  width: 100px;
  height: 40px;
  border-radius: 3px;
  white-space: nowrap;
  cursor: pointer;
  font-size: 10pt;

</style>

效果如图,目前“导出Json”还没有做 

以上是关于封装 x-spreadsheet 带样式导入导出的主要内容,如果未能解决你的问题,请参考以下文章

vue 下使用 exceljs + x-spreadsheet 带样式导出Excel

vue 下使用 exceljs + x-spreadsheet 带样式导出Excel

vue 下使用 exceljs + x-spreadsheet 带样式导入Excel

vue 下使用 exceljs + x-spreadsheet 带样式导入Excel

pads2007导入orcad导出的asc网表,找不到元件封装,但orcad的封装和PADS中的封装名字是一样的,

Vue前端实现excel的导入导出打印功能