Spreadjs v14 实现全局统一复制粘贴功能

249 阅读2分钟

监听组件级别的复制粘贴事件

...
mounted(){
    // 使用$el拿到当前组件的dom实例
    // 监听复制
    this.$el.addEventListener('copy',async (event) => {
      // 阻止默认的复制行为
      event.preventDefault();
      var selection = document.getSelection();
      // 自定义spread的复制动作
      // 判断实例是否存在
      if(this.spread){
          // 获取当前激活sheet
          let sheet = this.spread.getActiveSheet();
          // customCopy详见后续
          selection = await spreadUtils.customCopy(sheet);
      }
      // 赋值到剪贴板
      event.clipboardData.setData("text/plain", selection.toString());
    });
    
    // 监听粘贴
    this.$el.addEventListener('paste', (event) => {
      // 阻止默认的粘贴行为
      event.preventDefault();

      // 获取粘贴的内容
      const pasteData = (event.clipboardData || window.clipboardData).getData('text');
      if(this.spread){
        let sheet = this.spread.getActiveSheet();
        if(sheet){
          // customPaste详见后续
          spreadUtils.customPaste(sheet,pasteData);
        }
      }
    });
},
unmounted(){
    this.$el.removeEventListener('copy');
    this.$el.removeEventListener('paste');
}
...

自定义复制功能

export function customCopy(sheet){
  return new Promise((resolve,reject)=>{
    var result = '';
    try{
      const selections = sheet.getSelections();
      if (selections.length > 0) {
        const selection = selections[0];
        const startRow = selection.row;
        const startCol = selection.col;
        const colCount = selection.colCount;
        const rowCount = selection.rowCount;

        for (let i = 0; i < rowCount; i++) {
          for (let j = 0; j < colCount; j++) {
            if(sheet.getFormula(startRow + i, startCol+j)){
              result += "="+sheet.getFormula(startRow + i, startCol+j);
            }else{
              result += sheet.getValue(startRow + i, startCol+j);
            }
            if(j!==colCount-1){
              result += '\t';
            }
          }
          if(i!==rowCount-1){
            result += '\n';
          }
        }
      }
    }catch(err){
      console.log(err)
    }finally{
      resolve(result);
    }
  })
}

自定义粘贴功能

export function customPaste(sheet,text){
  try{
    const selections = sheet.getSelections();
    if (selections.length > 0) {
      const selection = selections[0];
      const startRow = selection.row;
      const startCol = selection.col;

      const rows = text.split('\n');
      rows.forEach((rowText, rowIndex) => {
          const cells = rowText.split('\t');
          cells.forEach((cellText, colIndex) => {
            if(isFormula(cellText)){
              sheet.setFormula(startRow + rowIndex, startCol + colIndex, cellText);
            }else{
              sheet.setFormula(startRow + rowIndex, startCol + colIndex, undefined);
              sheet.setValue(startRow + rowIndex, startCol + colIndex, cellText);
            }
          });
      });
    }
  }catch(err){
    console.log(err)
  }
}

复制粘贴集成到spreadjs右键菜单中

复制

export function customCopyMenu(spread){
  var name = "复制";
  spread.commandManager().register(name,
  {
    canUndo: true,
    execute: async(context, options, isUndo)=> {
      var Commands = GC.Spread.Sheets.Commands;
      if (isUndo) {
        Commands.undoTransaction(context, options);
        return true;
      } else {
        Commands.startTransaction(context, options);
        // 触发原有复制事件,保留单元格复制效果
        context.commandManager().execute({ cmd: "copy", sheetName: context.getActiveSheet().name() });
        // 触发自定义复制事件
        const result = await common.customCopy(context.getActiveSheet());
        // 将复制结果写入系统剪贴板
        navigator.clipboard.writeText(result);
        Commands.endTransaction(context, options);
        return true;
      }
    }
  });
  return {
    text:name,
    name: name,
    command: name,
    workArea: "viewportcolHeaderrowHeaderslicercornerpivotTable"
  }
}

粘贴

export function customPasteMenu(spread){
  var name = "粘贴";
  spread.commandManager().register(name,
  {
    canUndo: true,
    execute: async (context, options, isUndo)=> {
      var Commands = GC.Spread.Sheets.Commands;
      if (isUndo) {
        Commands.undoTransaction(context, options);
        return true;
      } else {
        Commands.startTransaction(context, options);
        // 激活原生的粘贴事件(此处可实现部分走原生粘贴逻辑)
        context.commandManager().execute({ cmd: "paste", sheetName: context.getActiveSheet().name() });
        // 获取剪贴板内容
        const text = await navigator.clipboard.readText();
        // 自定义粘贴
        common.customPaste(context.getActiveSheet(),text);
        Commands.endTransaction(context, options);
        return true;
      }
    }
  });
  return {
    text:name,
    name: name,
    command: name,
    workArea: "viewportcolHeaderrowHeaderslicercornerpivotTable"
  }
}

至此,可以实现全局的复制粘贴功能的统一,但是类似公式无法进行自适应,只能粘贴后手动进行修改,目前没有找到官方的api进行复制粘贴。