Newer
Older
smart-metering-front / src / views / business / lab / excelEdit / methods / file.ts
dutingting on 28 Apr 6 KB 需求开发,bug修复
/**
 * 文件公共方法
 */

import * as GC from '@grapecity-software/spread-sheets'
// 文件类型常量定义
const FileType = {
  SJS: 'sjs',
  Excel: 'xlsx',
  SSJson: 'ssjson',
}

/**
 * 获取文件类型
 * @param file 文件
 * @returns
 */
export function getFileType(file: Blob) {
  console.log('getFileType: ', file)
  if (!file) {
    return
  }
  if (!isBlob(file)) {
    console.log('不是blob文件', file)
    return
  }
  console.log('是blob文件:', file, '文件类型为', file.type)
  const extensionName = file.type
  if (extensionName === 'sjs') {
    return FileType.SJS
  }
  else if (extensionName === 'xlsx' || extensionName === 'xlsm') {
    return FileType.Excel
  }
  else if (extensionName === 'ssjson' || extensionName === 'json') {
    return FileType.SSJson
  }
  else {
    console.log('getFileType:未获取到文件类型')
  }
}
/**
 * 判断文件是否是blob类型
 * @param file
 * @returns
 */
function isBlob(file: unknown): file is Blob {
  return file instanceof Blob
}

/**
 * @param spread spread实例
 * @param file 文件
 * @param fileTypeParam 文件类型
 * @returns
 */
export async function importFile(spread: any, file: Blob, fileTypeParam = '') {
  let fileType = fileTypeParam!
  if (!fileTypeParam) {
    fileType = getFileType(file)!
  }
  console.log('获取到的文件类型', fileTypeParam, fileType)

  return new Promise((resolve) => {
    if (fileType === FileType.SJS) {
      spread.open(
        file,
        () => {
          console.log('importFile-open:导入sjs文件成功')
          resolve('')
        },
        (e: any) => {
          console.log('importFile-open:上传sjs文件发生错误', e)
        },
      )
    }
    else {
      const type
        = fileType === 'xlsx' ? 'excel' : fileType === 'ssjson' ? 'ssjson' : 'csv'
      spread.import(
        file,
        () => {
          console.log('importFile-import:导入文件成功')
          resolve('')
        },
        (e: any) => {
          console.log('importFile-import:上传文件发生错误', e)
        },
        {
          fileType: fileType === 'xlsm' ? null : GC.Spread.Sheets.FileType[type],
        },
      )
    }
  })
}

/**
 *
 * @param spread 工作簿实例
 */
export function handleTableToRange(spread: any) {
  // 获取 sheet 页数量
  const sheetCount = spread.getSheetCount()
  for (let i = 0; i < sheetCount; i++) {
    const sheet = spread.getSheet(i) // 获取sheet页
    const tables = sheet.tables.all() // 获取这个sheet页所有的表格
    // 检查工作表中是否有表格
    if (tables.length === 0) {
      console.log(`工作表 ${sheet.name()} 中没有表格`)
      continue
    }
    // 遍历该工作表中的所有表格
    for (let j = 0; j < tables.length; j++) {
      const table = tables[j]
      try {
        spread.commandManager().execute({
          cmd: 'tableToRange',
          sheetName: sheet.name(),
          tableName: table.name(),
        })
        console.log(
          `工作表 ${sheet.name()} 中表格 ${table.name()} 转换为区域操作成功`,
        )
      }
      catch (error) {
        console.error(
          `执行工作表 ${sheet.name()} 中表格 ${table.name()} 转换为区域操作时出错:`,
          error,
        )
      }
    }
  }
}

// 获取文件导出选项
function getExportOptions(fileType: any) {
  return {
    fileType: GC.Spread.Sheets.FileType[fileType],
    // 包含绑定数据源,文件中包含数据绑定时,是否导出绑定数据
    includeBindingSource: true,
    // 是否保存为视图
    // 如果需要确保导出的文件与用户在视图中看到的内容一致(包括格式化后的数据显示),可以将 saveAsView 设置为 true。
    // 如果需要避免特定控件(如日期范围控件)的值类型发生变化,可以将 saveAsView 设置为 false
    saveAsView: false,
    // 导出文件时是否包含样式
    includeStyles: true,
    // 导出文件时是否包含公式
    // 如果 includeFormulas 设置为 true(默认值),则导出的文件将包含公式;如果设置为 false,则公式将被忽略,仅导出计算结果或静态数据。
    includeFormulas: true,
    // 包含未使用名称,导出文件时是否包含无用的名称管理器,若文件中包含大量无用的名称管理器,设置为true可减小文件大小
    includeUnusedNames: true,
    // 包含有样式但无数据的最小范围单元格,是否导出无用的空单元格,文件中包含大量空白单元格,希望提升导出效率时,建议开启。
    includeEmptyRegionCells: true,
    // 包含自动合并的单元格,导出文件是否将自动合并的单元格视为真实合并单元格,当文件中包含自动合并的单元格,导出Excel时,希望成为真实的合并单元格时,建议开启
    includeAutoMergedCells: true,
    // 决定是否包含计算引擎缓存。如果设置为 true,导出的文件将包含计算引擎的缓存数据,这可以帮助在重新加载文件时加快计算速度,因为一些计算结果已经被缓存。
    includeCalcModelCache: false,
  }
}

/**
 * 下载文件操作
 * @param blob 文件blob
 * @param filename 文件名称
 */
function saveAs(blob: Blob, filename: string) {
  const link = document.createElement('a')
  link.href = URL.createObjectURL(blob)
  link.download = filename
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
}

/**
 * 文件导出
 * @param spread
 * @param fileType 文件类型
 * @param getFileName 导出文件名称
 * @param onlyFetchFile 仅获取文件, 不进行导出下载
 */
export function exportFile(
  spread: any,
  fileType: string,
  onlyFetchFile = false,
  getFileName = 'exportFile',
) {
  handleTableToRange(spread)
  const options = getExportOptions(fileType)
  const fileName = `${getFileName}.${fileType}`
  return new Promise((resolve) => {
    // 根据文件类型调用不同的导出方法
    if (fileType === FileType.SJS) {
      spread.save(
        (blob: Blob) => {
          if (!onlyFetchFile) {
            saveAs(blob, fileName)
          }
          console.log('导出成功回调', blob)
          resolve(blob)
        },
        (error: any) => {
          console.log('导出失败回调', error)
        },
        options,
      )
    }
    else {
      spread.export(
        (blob: Blob) => {
          if (!onlyFetchFile) {
            saveAs(blob, fileName)
          }
          console.log('导出成功回调', blob)
          resolve(blob)
        },
        (error: any) => {
          console.log('导出失败回调', error)
        },
        options,
      )
    }
  })
}