实现复制导入excel数据与前端导出excel

news/2024/7/21 5:23:09 标签: excel, 前端, javascript
import { utils, write } from 'xlsx'
import Papa from 'papaparse'

// 获取合并头部的数据 level: 头部分有几行
function mergeHeader(worksheet, cellList, level = 3) {
  // 并获取 列名
  const colName = []
  for (const key of Object.keys(worksheet)) {
    // 根据第一行的数据
    if (key.slice(-1) === '1' && isNaN(Number(key.slice(-2, -1)))) {
      colName.push(key.slice(0, -1))
    } else {
      break
    }
  }

  // 合并行 axle true 行 false 列
  function getSpaceNumber(dataCopy, rowIndex, colIndex, axle) {
    const data = JSON.parse(JSON.stringify(dataCopy))

    let count = 0
    axle ? (rowIndex += 1) : (colIndex += 1)
    count = isSpaceString(data[rowIndex][colIndex], axle, count)

    function isSpaceString(value, axle, count) {
      if (value === '' && axle && rowIndex < level) {
        // 行合并
        count += 1
        rowIndex += 1

        if (rowIndex >= data.length - 1) {
          return count
        }

        return isSpaceString(data[rowIndex][colIndex], axle, count)
      } else if (value === '' && !axle && colIndex < colName.length) {
        // 列合并
        count += 1
        colIndex += 1

        if (colIndex >= colName.length) {
          return count
        }

        return isSpaceString(data[rowIndex][colIndex], axle, count)
      } else {
        return count
      }
    }

    return count
  }

  const merges = []
  for (const rowIndex in cellList) {
    if (rowIndex > level - 1) {
      break
    }

    const rowCurrnetIndex = Number(rowIndex) + 1
    for (const cellIndex in cellList[rowIndex]) {
      if (cellIndex > colName.length - 1) {
        break
      }

      if (cellList[rowIndex][cellIndex] !== '') {
        const colCurrnetIndex = Number(cellIndex)

        let colCount = 0
        let rowCount = 0

        // 单独判断一列(特殊情况)
        if (cellList[rowIndex][cellIndex] === '其中:三次分配(奖项/专项)') {
          // 列合并
          rowCount = getSpaceNumber(cellList, Number(rowIndex), Number(cellIndex), true)
        } else {
          // 列合并
          colCount = getSpaceNumber(cellList, Number(rowIndex), Number(cellIndex), false)
          // 行合并
          rowCount = getSpaceNumber(cellList, Number(rowIndex), Number(cellIndex), true)
        }

        if (colCount || rowCount) {
          merges.push(
            `${colName[colCurrnetIndex]}${rowCurrnetIndex}:${colName[colCurrnetIndex + colCount]}${
              rowCurrnetIndex + rowCount
            }`
          )
        }
      }
    }
  }

  return merges
}

export default function pasteToFile(event) {
  // 判断是否有粘贴的数据
  if (event.clipboardData || event.originalEvent) {
    const clipboardData = event.clipboardData || window.clipboardData

    // 获取粘贴的数据并解析
    const xlsxText = Papa.parse(clipboardData.getData('text'), { delimiter: '\t', linebreak: '\r\n' }).data

    // 两行及以下的数据不处理
    if (xlsxText.length < 1) {
      return
    }

    // windows 最后一行全是空格, 手动去掉
    xlsxText[xlsxText.length - 1].every(item => item === '') && xlsxText.pop()

    // 去掉全是空格的行
    const allIsSpace = []
    for (const index in xlsxText) {
      xlsxText[Number(index)].every(item => item === '') && allIsSpace.push(index)
    }
    for (const index of allIsSpace) {
      xlsxText.splice(Number(index), 1)
    }

    // 创建一个新的工作簿
    const workbook = utils.book_new()

    // 创建一个工作表
    const worksheet = utils.aoa_to_sheet(xlsxText)

    // 合并单元格
    // const merges = mergeHeader(worksheet, xlsxText)

    // // 判断是否有需要合并的单元格
    // if (merges.length > 0) {
    //   if (!worksheet['!merges']) {
    //     worksheet['!merges'] = []
    //   }

    //   // 将合并的单元格添加到工作表
    //   merges.forEach(item => {
    //     worksheet['!merges'].push(utils.decode_range(item))
    //   })
    // }

    // 将工作表添加到工作簿
    utils.book_append_sheet(workbook, worksheet, 'Sheet1')

    // 将工作簿保存为Excel文件
    // writeFile(workbook, "data.xlsx");

    // 将工作簿保存为ArrayBuffer
    const data = write(workbook, { type: 'array', bookType: 'xlsx' })

    // 将ArrayBuffer转为Blob
    return new Blob([data])
  }
}

http://www.niftyadmin.cn/n/5425294.html

相关文章

Kafka MQ 生产者

Kafka MQ 生产者 生产者概览 尽管生产者 API 使用起来很简单&#xff0c;但消息的发送过程还是有点复杂的。图 3-1 展示了向 Kafka 发送消息的主要步骤。 我们从创建一个 ProducerRecord 对象开始&#xff0c;ProducerRecord 对象需要包含目标主题和要发送的内容。我们还可以…

【C++教程从0到1入门编程】第九篇:STL中Vector类

一、vector的介绍 1.vector的介绍 vector是表示可变大小数组的序列容器。 就像数组一样&#xff0c;vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问&#xff0c;和数组一样高效。但是又不像数组&#xff0c;它的大小是可以动态改变的&…

IPsec vpn 实验

FW1 FW3与FW1的源目地址反过来&#xff0c;其他均一样 源目安全区域选择local&#xff0c;需要放通udp的500端口和esp服务 FW1 FW3 协商成功 在安全区域中放通10.0.2.0/24和192.168.1.0/24网段 创建nat策略&#xff0c;让10.0.2.0/24访问192.168.1.0/24的流量不进行nat转换,…

linux ssh 连接速度慢

1.在server上/etc/ssh/sshd_config文件中修改或加入“UseDNS no&#xff0c;GSSAPIAuthentication no” 在linux中&#xff0c;默认就是开启了SSH的反向DNS解析,这个会消耗大量时间&#xff0c;因此需要关闭。在配置文件中&#xff0c;虽然UseDNS yes是被注释的&#xff0c;但默…

设计模式一 ---单例设计模式(动力节点,JavaSE基础)

设计模式 1.什么是设计模式&#xff1f; 2.设计模式的分类 单例设计模式就是GoF模式中的一种。 3.GoF设计模式的分类&#xff1a; 单例设计模式&#xff1a; 顾名思义&#xff1a;单个实例的设计模式&#xff01;

iPhone, Android 手机是如何收到推送通知的?

本文转自 公众号 ByteByteGo&#xff0c;如有侵权&#xff0c;请联系&#xff0c;立即删除 iPhone, Android 手机是如何收到推送通知的&#xff1f; 我们的手机或电脑是如何收到推送通知的&#xff1f; 通常我们可以使用消息解决方案 Firebase 来支持通知推送。下图显示了 Fi…

网络安全攻击数据的多维度可视化分析

简介 本研究项目通过应用多种数据处理与可视化技术&#xff0c;对网络安全攻击事件数据集进行了深度分析。首先&#xff0c;利用Pandas库读取并预处理数据&#xff0c;包括检查缺失值、剔除冗余信息以及将时间戳转化为日期时间格式以利于后续时间序列分析。 研究步骤 数据分析…

对GIS与游戏引擎(UE4 或 U3D)结合的看法

GIS与游戏引擎结合&#xff0c;这在6年前就已经很多公司在进行探索了&#xff0c;经过这几年的发展&#xff0c;结合当前的政策&#xff0c;从以下几方面说一下我的看法&#xff1a; 1.GIS客户都是特殊单位及领域。2018年后&#xff0c;国内已经对国产化有明确要求了&#xff0…