国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

基于 SheetJS 的前端合并單元格復(fù)雜表頭導(dǎo)入

這篇具有很好參考價(jià)值的文章主要介紹了基于 SheetJS 的前端合并單元格復(fù)雜表頭導(dǎo)入。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

sheetjs,前端,excel

項(xiàng)目功能

  • 任意層級(jí)合并單元格復(fù)雜表頭解析

sheetjs,前端,excel

  • 自動(dòng)轉(zhuǎn)化為目標(biāo)層級(jí)的數(shù)據(jù)結(jié)構(gòu)

sheetjs,前端,excel

  • 自動(dòng)生成基于 antdv 的 table 列配置數(shù)據(jù) columns 及對(duì)于數(shù)據(jù)源 dataSource。在頁(yè)面端復(fù)現(xiàn) Excel 效果。

sheetjs,前端,excel

在線示例

  • 步驟零:如需快速測(cè)試,可點(diǎn)擊頂部的示例按鈕,可快速填充測(cè)試數(shù)據(jù),并自動(dòng)下載對(duì)應(yīng)的 Excel 文件,點(diǎn)擊上傳 Excel 文件即可復(fù)現(xiàn)整個(gè)使用流程

sheetjs,前端,excel

  • 步驟一:輸入「Excel 表頭結(jié)構(gòu)字符串」與「目標(biāo)數(shù)據(jù)結(jié)構(gòu) key」之間的映射關(guān)系

    sheetjs,前端,excel

    • "key" 為 Excel 表頭,每一列的所處層級(jí)關(guān)系。如「基礎(chǔ)信息.年齡」對(duì)應(yīng)的就是 Excel 表在第二列中的關(guān)系,第一級(jí)是「基礎(chǔ)信息」,第二級(jí)是「年齡」

    sheetjs,前端,excel

    • "value" 為需要轉(zhuǎn)換的目標(biāo)數(shù)據(jù)結(jié)構(gòu)的層級(jí)關(guān)系。「baseInfo.age」的意思是,將 Excel 表第二列的數(shù)據(jù),轉(zhuǎn)化為目標(biāo)對(duì)象中.baseInfo.age 這個(gè)屬性。

    sheetjs,前端,excel

    • 【特別注意一】"key":"value" 的映射關(guān)系,沒(méi)有順序的要求,無(wú)需要按 Excel 表的每一列的數(shù)據(jù)進(jìn)行排序。

    sheetjs,前端,excel

    • 【特別注意二】Excel 表的層級(jí)映射關(guān)系與目標(biāo)對(duì)象的層級(jí)映射關(guān)系,沒(méi)有強(qiáng)制約束和要求。如Excel 中的 "手機(jī)號(hào)",只有一層結(jié)構(gòu),但完全可以轉(zhuǎn)化為目標(biāo)對(duì)象中的 "contact.phone" 二級(jí)結(jié)構(gòu)。反之亦然。

    sheetjs,前端,excel

  • 步驟二:點(diǎn)擊右側(cè),上傳對(duì)應(yīng)的 Excel 文件,即可完成 Excel 解析。

    sheetjs,前端,excel

解析后的頁(yè)面介紹

sheetjs,前端,excel

  • 頂部為基于 antdv 的 table 組件的復(fù)現(xiàn)效果。復(fù)現(xiàn) Excel 表格中,合并完單元格后的效果。 table 組件用到的 columns 配置,及 dataSource 數(shù)據(jù),均由解析函數(shù)一并返回。無(wú)需要開(kāi)發(fā)者二次開(kāi)發(fā)及維護(hù)。

    sheetjs,前端,excel

  • 底部為解析函數(shù)解析后返回的三個(gè)數(shù)據(jù)結(jié)果。分別為

    • 解析后的 antdv columns 表格列的配置項(xiàng),直接傳遞給 table 組件的 columns 屬性使用。
    • 解析后的 antdv dataSource 表格數(shù)據(jù)源,直接傳遞給 table 組件的 data-source 屬性使用。

    sheetjs,前端,excel

    • 解析后的目標(biāo)數(shù)據(jù)結(jié)構(gòu)數(shù)組。即根據(jù)步驟一設(shè)置的映射表,將 Excel 各個(gè)單元格數(shù)據(jù),轉(zhuǎn)換后的目標(biāo)數(shù)據(jù)結(jié)構(gòu)。一般情況下,該數(shù)據(jù)結(jié)構(gòu),即為傳遞給后端的數(shù)據(jù)結(jié)構(gòu)。

    sheetjs,前端,excel

背景,解決什么問(wèn)題

  • 直接使用 SheetJS 的 XLSX.utils.sheet_to_json 函數(shù)進(jìn)行 excel 數(shù)據(jù)轉(zhuǎn)化時(shí),僅支持一行表頭的 Excel 表格數(shù)據(jù)解析(只識(shí)別 Excel 內(nèi)容的第一行作為標(biāo)題),無(wú)法識(shí)別表頭進(jìn)行過(guò)合并單元格的 Excel 數(shù)據(jù)解析

sheetjs,前端,excel

  • sheet_to_json 轉(zhuǎn)化的 JSON 數(shù)據(jù),是以中文為 key 的對(duì)象,不符合編程習(xí)慣,需要開(kāi)發(fā)者手動(dòng)進(jìn)行數(shù)據(jù)中英文 key 轉(zhuǎn)換,自行轉(zhuǎn)換為目標(biāo)數(shù)據(jù)結(jié)構(gòu)。

sheetjs,前端,excel

  • excel 表頭的組織與復(fù)現(xiàn),進(jìn)行 Excel 表上傳時(shí),通常需要在前端展現(xiàn)表格內(nèi)容,給用戶需要數(shù)據(jù)復(fù)現(xiàn)及確認(rèn)。這個(gè)過(guò)程需要開(kāi)發(fā)者手動(dòng)組織完成。
  • 最少知識(shí)原則,提供最小化 demo 示例,沒(méi)有腳手架,無(wú)需要安裝 npm 依賴包。純 html + js 文件??焖贉y(cè)試代碼可行性。邊改邊測(cè)進(jìn)行二次開(kāi)發(fā)。

sheetjs,前端,excel

具體函數(shù)使用方式

  • 示例遵循最少知識(shí)原則,項(xiàng)目中的 core.js 文件,即為轉(zhuǎn)換函數(shù)所在文件。里面一共不到 200 行代碼??梢灾苯诱迟N復(fù)制到所需項(xiàng)目里面。

sheetjs,前端,excel

  • 示例直接使用的 script 文件整體引入的方式。所以遷移到基于 npm 的項(xiàng)目中時(shí),需要將 core.js 中的 ‘XLSX.utils’ 全局變量使用方式,改為通過(guò)?import { utils } from 'xlsx'?的使用方式。

sheetjs,前端,excel

  • 如果本項(xiàng)目確實(shí)有幫助到小伙伴,小伙伴有需求的話,可以在 github 中提 issues,有需要的話,將補(bǔ)充基于 npm 的版本,以及帶上 ts 類型約束的版本。

sheetjs,前端,excel

轉(zhuǎn)換函數(shù)運(yùn)行邏輯

  • 獲取 Excel 所有單元格數(shù)據(jù)

    • 借用 SheetJS 的 'encode_cell' 方法,及 'format_cell' 方法,遍歷獲取每個(gè) sheet 中,每個(gè)單元格的數(shù)據(jù)。
/**
 * 獲取所有單元格數(shù)據(jù)
 * @param sheet sheet 對(duì)象
 * @returns 該 sheet 所有單元格數(shù)據(jù)
 */
function getSheetCells(sheet) {
  if (!sheet || !sheet['!ref']) {
    return []
  }
  const range = XLSX.utils.decode_range(sheet['!ref'])

  let allCells = []
  for (let rowIndex = range.s.r; rowIndex <= range.e.r; ++rowIndex) {
    let newRow = []
    allCells.push(newRow)
    for (let colIndex = range.s.c; colIndex <= range.e.c; ++colIndex) {
      const cell = sheet[XLSX.utils.encode_cell({
        c: colIndex,
        r: rowIndex
      })]
      let cellContent = ''
      if (cell && cell.t) {
        cellContent = XLSX.utils.format_cell(cell)
      }
      newRow.push(cellContent)
    }
  }
  return allCells
}
  • 根據(jù) map 映射表,獲取 Excel 表頭行數(shù)

    • 遍歷 map 中的每個(gè)中文 key,根據(jù)'點(diǎn)'關(guān)鍵字拆分層級(jí),找到 Excel 最高層級(jí)。從而得到 Excel 表頭的行數(shù)。區(qū)分那些行是表頭,那些行是數(shù)據(jù)。
  // 獲取菜單項(xiàng)在 Excel 中所占行數(shù)
  function getHeaderRowNum(textKeyMap) {
    let maxLevel = 1 // 最高層級(jí)
    Object.keys(textKeyMap).forEach(textStr => {
      maxLevel = Math.max(maxLevel, textStr.split('.').length)
    })
    return maxLevel
  }
  const headerRowNum = getHeaderRowNum(textKeyMap)
  • 通過(guò)容器,遞歸解析 Excel 表頭配置樹(shù)裝數(shù)據(jù)結(jié)構(gòu)

    • 通過(guò) lastHeaderLevelColumns 遍歷,保存在 Excel 中的每一行的最新容器。
    • 當(dāng)表頭遍歷到非空單元格時(shí),往上一級(jí)的容器中,加入本層級(jí)配置。
    • 從而遞歸解析,得到 table 表頭層級(jí)結(jié)構(gòu)數(shù)組。
  • 使用索引映射表,將 Excel 表頭對(duì)象格與 Excel 所在行索引進(jìn)行掛鉤

    • 在遞歸解析表頭層級(jí)結(jié)構(gòu)時(shí),通過(guò) columnIndexObjMap,記錄當(dāng)前表頭數(shù)據(jù),所在列。
let headerColumns = [] // 收集 table 組件中,表頭 columns 的對(duì)象數(shù)組結(jié)構(gòu)
  const lastHeaderLevelColumns = [] // 最近一個(gè) columns,用于收集單元格子表頭的內(nèi)容
  const textValueMaps = [] // 以中文字符串為 key 的對(duì)象數(shù)組,用于收集表格中的數(shù)據(jù)
  const columnIndexObjMap = [] // 表的列索引,對(duì)應(yīng)在對(duì)象中的位置,用于后續(xù)獲取表格數(shù)據(jù)時(shí),快速定位每一個(gè)單元格

  for (let colIndex = 0; colIndex < headerRows[0].length; colIndex++) {
    const headerCellList = headerRows.map(item => item[colIndex])
    headerCellList.forEach((headerCell, headerCellIndex) => {
      // 如果當(dāng)前單元格沒(méi)數(shù)據(jù),這證明是合并后的單元格,跳過(guò)其處理
      if (!headerCell) {
        return
      }
      const tempColumn = { title: headerCell }

      columnIndexObjMap[colIndex] = tempColumn // 通過(guò) columnIndexObjMap 記錄每一列數(shù)據(jù),對(duì)應(yīng)到那個(gè)對(duì)象中,實(shí)現(xiàn)一個(gè)映射表

      // 如果表頭數(shù)據(jù)第一輪就有值,這證明這是新起的一個(gè)表頭項(xiàng)目,往 headerColumns 中,新加入一條數(shù)據(jù)
      if (headerCellIndex === 0) {
        headerColumns.push(tempColumn)
        lastHeaderLevelColumns[headerCellIndex] = tempColumn // 記錄當(dāng)前層級(jí),最新的一個(gè)表格容器,可能在下一列數(shù)據(jù)時(shí)合并單元格,下一個(gè)層級(jí)需要往該容器中添加數(shù)據(jù)
      } else { // 不是第一列數(shù)據(jù),這證明是子項(xiàng)目,需要加入到上一層表頭的 children 項(xiàng),作為其子項(xiàng)目
        lastHeaderLevelColumns[headerCellIndex - 1].children = lastHeaderLevelColumns[headerCellIndex - 1].children || []
        lastHeaderLevelColumns[headerCellIndex - 1].children.push(tempColumn)
        lastHeaderLevelColumns[headerCellIndex] = tempColumn // 記錄當(dāng)前層級(jí)的容器索引,可能再下一層級(jí)中使用到
      }
    })
  }
  • 利用該索引表,遍歷 Excel 數(shù)據(jù)表的每一行,快速生成每行 Excel 的數(shù)據(jù)結(jié)構(gòu)

    • 利用 columnIndexObjMap,遍歷 Excel 數(shù)據(jù)表的每一行,往 headerColumns 配置中,插入 value 值,將其設(shè)置為特定行,對(duì)應(yīng)列的數(shù)據(jù)。
    • 通過(guò) Object.create 從 headerColumns 中生成一個(gè)對(duì)象副本。
// 將以數(shù)組形式記錄的對(duì)象信息,轉(zhuǎn)化為正常的對(duì)象結(jié)構(gòu)
  function transformListToObj(listObjs) {
    const resultObj = {}
    listObjs.forEach(item => {
      if (item.value) {
        resultObj[item.title] = item.value
        return
      }

      if (item.children && item.children.length > 0) {
        resultObj[item.title] = transformListToObj(item.children)
      }
    })
    return resultObj
  }

  // 以 headerColumns 為對(duì)象結(jié)構(gòu)模板,遍歷 excel 表數(shù)據(jù)中的所有數(shù)據(jù),并利用 columnIndexObjMap 的映射,快速填充每一項(xiàng)數(shù)據(jù)
  dataRows.forEach(dataRow => {
    dataRow.forEach((value, index) => {
      columnIndexObjMap[index].value = value
    })
    const titleObj = Object.create(headerColumns) // columnIndexObjMap 的指針?biāo)饕瑑H指向 headerColumns,以 headerColumns 為數(shù)據(jù)模板,復(fù)制一份數(shù)據(jù),獲得數(shù)據(jù)填充后的效果對(duì)象
    textValueMaps.push(transformListToObj(titleObj)) // 將 listObj 對(duì)象轉(zhuǎn)化化普通的對(duì)象
  })
  • 將 JSON 數(shù)據(jù)結(jié)構(gòu),進(jìn)行 key map 映射解析,生成目標(biāo)數(shù)據(jù)結(jié)構(gòu)
/**
 * 將以點(diǎn)拼接的扁平字符串對(duì)象,解析為具有深度的對(duì)象
 * @param dotStrObj 點(diǎn)拼接的扁平化字符串對(duì)象
 * @returns 具有深度的對(duì)象
 */
function parseDotStrObjToObj(dotStrObj) {
  const resultObj = {}
  Object.keys(dotStrObj).forEach(key => {
    let keys = key.split('.')
    keys.reduce((resultObj, curValue, currentIndex) => {
      resultObj[curValue] = currentIndex === keys.length - 1 ? dotStrObj[key] : resultObj[curValue] || {}
      return resultObj[curValue]
    }, resultObj)
  })
  return resultObj
}

/**
 * 將具有深度的對(duì)象扁平化,變成以點(diǎn)拼接的扁平字符串對(duì)象
 * @param targetObj 具有深度的對(duì)象
 * @returns 扁平化后,由點(diǎn)操作符拼接的對(duì)象
 */
function transformObjToDotStrObj(targetObj) {
  const resultObj = {}
  function transform(currentObj, preKeys) {
    Object.keys(currentObj).forEach(key => {
      if (Object.prototype.toString.call(currentObj[key]) !== '[object Object]') {
        resultObj[[...preKeys, key].join('.')] = currentObj[key]
      } else {
        transform(currentObj[key], [...preKeys, key])
      }
    })
  }
  transform(targetObj, [])
  return resultObj
}
// 將以中文為 key 的對(duì)象,通過(guò) textKeyMap 映射,找到對(duì)應(yīng)的 key,轉(zhuǎn)化為以 key 對(duì)鍵的對(duì)象,轉(zhuǎn)化為后端對(duì)應(yīng)的 json 對(duì)象
  function transformTextToKey(textDataList, textKeyMap) {
    const textDotStrDataList = textDataList.map(obj => transformObjToDotStrObj(obj))
    let textDotStrDataListStr = JSON.stringify(textDotStrDataList)
    Object.keys(textKeyMap).forEach(text => {
      const key = textKeyMap[text]
      textDotStrDataListStr = textDotStrDataListStr.replaceAll(`"${text}"`, `"${key}"`) // 在這里,通過(guò)字符串的替換,實(shí)現(xiàn)表頭數(shù)據(jù)層級(jí)結(jié)構(gòu),與實(shí)際對(duì)象將數(shù)據(jù)結(jié)構(gòu)的轉(zhuǎn)換
    })
    const keyDotStrDataList = JSON.parse(textDotStrDataListStr)
    const keyDataList = keyDotStrDataList.map(keyDotStrData => parseDotStrObjToObj(keyDotStrData))
    return keyDataList
  }
  • 返回給 antdv 復(fù)現(xiàn) table 用的 columns 配置,dataSource 表格數(shù)據(jù),以及 dataList 后端 JSON 數(shù)據(jù)

sheetjs,前端,excel

  • 上述源碼確實(shí)不太好懂,不太好描述,如果本項(xiàng)目確實(shí)能幫助到小伙伴,而小伙伴對(duì)源碼也感興趣的話。可以提 issues,我再后補(bǔ)運(yùn)行邏輯詳解及配圖

全部核心源碼

/**
 * 將以點(diǎn)拼接的扁平字符串對(duì)象,解析為具有深度的對(duì)象
 * @param dotStrObj 點(diǎn)拼接的扁平化字符串對(duì)象
 * @returns 具有深度的對(duì)象
 */
function parseDotStrObjToObj(dotStrObj) {
  const resultObj = {}
  Object.keys(dotStrObj).forEach(key => {
    let keys = key.split('.')
    keys.reduce((resultObj, curValue, currentIndex) => {
      resultObj[curValue] = currentIndex === keys.length - 1 ? dotStrObj[key] : resultObj[curValue] || {}
      return resultObj[curValue]
    }, resultObj)
  })
  return resultObj
}

/**
 * 將具有深度的對(duì)象扁平化,變成以點(diǎn)拼接的扁平字符串對(duì)象
 * @param targetObj 具有深度的對(duì)象
 * @returns 扁平化后,由點(diǎn)操作符拼接的對(duì)象
 */
function transformObjToDotStrObj(targetObj) {
  const resultObj = {}
  function transform(currentObj, preKeys) {
    Object.keys(currentObj).forEach(key => {
      if (Object.prototype.toString.call(currentObj[key]) !== '[object Object]') {
        resultObj[[...preKeys, key].join('.')] = currentObj[key]
      } else {
        transform(currentObj[key], [...preKeys, key])
      }
    })
  }
  transform(targetObj, [])
  return resultObj
}

/**
 * 獲取所有單元格數(shù)據(jù)
 * @param sheet sheet 對(duì)象
 * @returns 該 sheet 所有單元格數(shù)據(jù)
 */
function getSheetCells(sheet) {
  if (!sheet || !sheet['!ref']) {
    return []
  }
  const range = XLSX.utils.decode_range(sheet['!ref'])

  let allCells = []
  for (let rowIndex = range.s.r; rowIndex <= range.e.r; ++rowIndex) {
    let newRow = []
    allCells.push(newRow)
    for (let colIndex = range.s.c; colIndex <= range.e.c; ++colIndex) {
      const cell = sheet[XLSX.utils.encode_cell({
        c: colIndex,
        r: rowIndex
      })]
      let cellContent = ''
      if (cell && cell.t) {
        cellContent = XLSX.utils.format_cell(cell)
      }
      newRow.push(cellContent)
    }
  }
  return allCells
}

/**
 * 獲取表頭任意層級(jí)單元格合并后的表格內(nèi)容解析
 * @param sheet 一個(gè) sheet 中所有單元格內(nèi)容
 * @param textKeyMap 表頭中文與對(duì)應(yīng)英文 key 之間的映射表
 * @returns antdv 中的表格 column,dataSource,以及轉(zhuǎn)化后的,直接傳輸給后端的 json 對(duì)象數(shù)組
 */
function getSheetHeaderAndData(sheet, textKeyMap) {
  // 獲取菜單項(xiàng)在 Excel 中所占行數(shù)
  function getHeaderRowNum(textKeyMap) {
    let maxLevel = 1 // 最高層級(jí)
    Object.keys(textKeyMap).forEach(textStr => {
      maxLevel = Math.max(maxLevel, textStr.split('.').length)
    })
    return maxLevel
  }
  const headerRowNum = getHeaderRowNum(textKeyMap)

  const headerRows = sheet.slice(0, headerRowNum)
  const dataRows = sheet.slice(headerRowNum)

  let headerColumns = [] // 收集 table 組件中,表頭 columns 的對(duì)象數(shù)組結(jié)構(gòu)
  const lastHeaderLevelColumns = [] // 最近一個(gè) columns,用于收集單元格子表頭的內(nèi)容
  const textValueMaps = [] // 以中文字符串為 key 的對(duì)象數(shù)組,用于收集表格中的數(shù)據(jù)
  const columnIndexObjMap = [] // 表的列索引,對(duì)應(yīng)在對(duì)象中的位置,用于后續(xù)獲取表格數(shù)據(jù)時(shí),快速定位每一個(gè)單元格

  for (let colIndex = 0; colIndex < headerRows[0].length; colIndex++) {
    const headerCellList = headerRows.map(item => item[colIndex])
    // eslint-disable-next-line no-loop-func
    headerCellList.forEach((headerCell, headerCellIndex) => {
      // 如果當(dāng)前單元格沒(méi)數(shù)據(jù),這證明是合并后的單元格,跳過(guò)其處理
      if (!headerCell) {
        return
      }
      const tempColumn = { title: headerCell }

      columnIndexObjMap[colIndex] = tempColumn // 通過(guò) columnIndexObjMap 記錄每一列數(shù)據(jù),對(duì)應(yīng)到那個(gè)對(duì)象中,實(shí)現(xiàn)一個(gè)映射表

      // 如果表頭數(shù)據(jù)第一輪就有值,這證明這是新起的一個(gè)表頭項(xiàng)目,往 headerColumns 中,新加入一條數(shù)據(jù)
      if (headerCellIndex === 0) {
        headerColumns.push(tempColumn)
        lastHeaderLevelColumns[headerCellIndex] = tempColumn // 記錄當(dāng)前層級(jí),最新的一個(gè)表格容器,可能在下一列數(shù)據(jù)時(shí)合并單元格,下一個(gè)層級(jí)需要往該容器中添加數(shù)據(jù)
      } else { // 不是第一列數(shù)據(jù),這證明是子項(xiàng)目,需要加入到上一層表頭的 children 項(xiàng),作為其子項(xiàng)目
        lastHeaderLevelColumns[headerCellIndex - 1].children = lastHeaderLevelColumns[headerCellIndex - 1].children || []
        lastHeaderLevelColumns[headerCellIndex - 1].children.push(tempColumn)
        lastHeaderLevelColumns[headerCellIndex] = tempColumn // 記錄當(dāng)前層級(jí)的容器索引,可能再下一層級(jí)中使用到
      }
    })
  }

  // 運(yùn)行以上代碼,得到 headerColumns,以及 headerColumns 中,每個(gè)對(duì)象對(duì)應(yīng)在表格中的哪一行索引

  // 將以數(shù)組形式記錄的對(duì)象信息,轉(zhuǎn)化為正常的對(duì)象結(jié)構(gòu)
  function transformListToObj(listObjs) {
    const resultObj = {}
    listObjs.forEach(item => {
      if (item.value) {
        resultObj[item.title] = item.value
        return
      }

      if (item.children && item.children.length > 0) {
        resultObj[item.title] = transformListToObj(item.children)
      }
    })
    return resultObj
  }

  // 以 headerColumns 為對(duì)象結(jié)構(gòu)模板,遍歷 excel 表數(shù)據(jù)中的所有數(shù)據(jù),并利用 columnIndexObjMap 的映射,快速填充每一項(xiàng)數(shù)據(jù)
  dataRows.forEach(dataRow => {
    dataRow.forEach((value, index) => {
      columnIndexObjMap[index].value = value
    })
    const titleObj = Object.create(headerColumns) // columnIndexObjMap 的指針?biāo)饕?,僅指向 headerColumns,以 headerColumns 為數(shù)據(jù)模板,復(fù)制一份數(shù)據(jù),獲得數(shù)據(jù)填充后的效果對(duì)象
    textValueMaps.push(transformListToObj(titleObj)) // 將 listObj 對(duì)象轉(zhuǎn)化化普通的對(duì)象
  })


  // 根據(jù)表頭的 title 值,從 textKeyMap 中尋找映射關(guān)系,設(shè)置 headerColumn 對(duì)應(yīng)的 dataIndex
  function setHeaderColumnDataIndex(headerColumns, preTitle) {
    headerColumns.forEach(headerObj => {
      if (headerObj.children) {
        headerObj.children = setHeaderColumnDataIndex(headerObj.children, [...preTitle, headerObj.title])
      } else {
        const titleStr = [...preTitle, headerObj.title].join('.')
        headerObj.dataIndex = textKeyMap[titleStr]
      }
    })
    return headerColumns
  }

  // 將以中文為 key 的對(duì)象,通過(guò) textKeyMap 映射,找到對(duì)應(yīng)的 key,轉(zhuǎn)化為以 key 對(duì)鍵的對(duì)象,轉(zhuǎn)化為后端對(duì)應(yīng)的 json 對(duì)象
  function transformTextToKey(textDataList, textKeyMap) {
    const textDotStrDataList = textDataList.map(obj => transformObjToDotStrObj(obj))
    let textDotStrDataListStr = JSON.stringify(textDotStrDataList)
    Object.keys(textKeyMap).forEach(text => {
      const key = textKeyMap[text]
      textDotStrDataListStr = textDotStrDataListStr.replaceAll(`"${text}"`, `"${key}"`) // 在這里,通過(guò)字符串的替換,實(shí)現(xiàn)表頭數(shù)據(jù)層級(jí)結(jié)構(gòu),與實(shí)際對(duì)象將數(shù)據(jù)結(jié)構(gòu)的轉(zhuǎn)換
    })
    const keyDotStrDataList = JSON.parse(textDotStrDataListStr)
    const keyDataList = keyDotStrDataList.map(keyDotStrData => parseDotStrObjToObj(keyDotStrData))
    return keyDataList
  }

  headerColumns = setHeaderColumnDataIndex(headerColumns, [])
  const dataList = transformTextToKey(textValueMaps, textKeyMap)
  const dataSource = dataList.map(row => transformObjToDotStrObj(row)) // 將 JSON 對(duì)象轉(zhuǎn)化為 “點(diǎn).” 拼接的扁平對(duì)象,使得數(shù)據(jù)與 headerColumn 中的 dataIndex 相對(duì)應(yīng)。實(shí)現(xiàn) table 的數(shù)據(jù)填充

  return {
    headerColumns,
    dataList,
    dataSourceList: dataSource,
  }
}

這里還有 Excel 合并單元格復(fù)雜表頭導(dǎo)出解析示例

sheetjs,前端,excel文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-792300.html

到了這里,關(guān)于基于 SheetJS 的前端合并單元格復(fù)雜表頭導(dǎo)入的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 前端-layui動(dòng)態(tài)渲染表格行列與復(fù)雜表頭合并

    前端-layui動(dòng)態(tài)渲染表格行列與復(fù)雜表頭合并

    說(shuō)在前面: 最近一直在用layui處理表格 寫的有些代碼感覺(jué)還挺有用的,順便記錄下來(lái)方便以后查看使用; HTML處代碼 拿到id 渲染位置表格 CSS 重點(diǎn)來(lái)了 JS代碼 合并表頭需要在 cols中傳入[ [ ],[ ] ]這種數(shù)組類型的格式; 主要就是不合并的表頭都加上rowspan:2(代表行跨度為2) c

    2024年02月07日
    瀏覽(21)
  • 【vue導(dǎo)入導(dǎo)出Excel】vue簡(jiǎn)單實(shí)現(xiàn)導(dǎo)出和導(dǎo)入復(fù)雜表頭excel表格功能【純前端版本和配合后端版本】

    【vue導(dǎo)入導(dǎo)出Excel】vue簡(jiǎn)單實(shí)現(xiàn)導(dǎo)出和導(dǎo)入復(fù)雜表頭excel表格功能【純前端版本和配合后端版本】

    前言 這是一個(gè)常用的功能,就是導(dǎo)入和導(dǎo)出excel表格 但是時(shí)常會(huì)遇到一些復(fù)雜表頭的表格導(dǎo)出和導(dǎo)入 比如我這個(gè)案例里面的三層表頭的表格。 網(wǎng)上看了下發(fā)現(xiàn)了一個(gè)非常簡(jiǎn)單導(dǎo)出和導(dǎo)入方法 當(dāng)然這個(gè)是純前端的版本,會(huì)出現(xiàn)分頁(yè)不好下載的情況。所以實(shí)際工作中,導(dǎo)出還是

    2024年02月11日
    瀏覽(26)
  • 使用SheetJS讀寫Excel文件

    使用SheetJS讀寫Excel文件

    項(xiàng)目中有一個(gè)Excel轉(zhuǎn)JSON的工具,之前這個(gè)工具一直使用 Python 的 openpyxl 庫(kù)來(lái)編寫的,然后使用 pyinstaller 打包成 .exe 文件。之前這個(gè)工具只是個(gè)命令行工具,不帶界面的。現(xiàn)在項(xiàng)目升級(jí),打算使用Web前端方式重寫這個(gè)工具,調(diào)整部分功能并新增圖形界面。這篇文章中將使用 S

    2024年02月14日
    瀏覽(23)
  • vue項(xiàng)目如何使用 SheetJS(xlsx)插件?

    vue項(xiàng)目如何使用 SheetJS(xlsx)插件?

    SheetJS是一款非常好用的前端處理表格文件的工具。它分社區(qū)版和專業(yè)版,我們今天來(lái)介紹如何簡(jiǎn)單使用它的社區(qū)版。 SheetJS社區(qū)版官網(wǎng) 你應(yīng)該打開(kāi)官網(wǎng)瀏覽具體使用詳情。 打開(kāi)官網(wǎng)在如上圖的Installation板塊中可以找到各種運(yùn)行模塊的使用方式。 一般項(xiàng)目都是webpack或vite這種

    2024年02月12日
    瀏覽(29)
  • EasyExcel復(fù)雜表頭數(shù)據(jù)導(dǎo)入

    EasyExcel復(fù)雜表頭數(shù)據(jù)導(dǎo)入

    參考文章:EasyExcel動(dòng)態(tài)復(fù)雜表頭導(dǎo)出方法

    2024年02月06日
    瀏覽(18)
  • Excel通用表頭及單元格合并

    要在Java中實(shí)現(xiàn)XLS文件中的通用表頭合并和單元格合并,您可以使用Apache POI庫(kù)。下面是一個(gè)示例代碼,展示了如何實(shí)現(xiàn)這兩個(gè)功能: 上述代碼創(chuàng)建一個(gè)工作簿和工作表,并在工作表中創(chuàng)建通用表頭行和數(shù)據(jù)行。然后使用 addMergedRegion() 方法執(zhí)行表頭合并和單元格合并操作。 對(duì)

    2024年02月11日
    瀏覽(20)
  • poi+easypoi實(shí)現(xiàn)表頭多層循環(huán),多級(jí)動(dòng)態(tài)表頭、樹(shù)形結(jié)構(gòu)動(dòng)態(tài)表頭、縱向合并單元格、多個(gè)sheet導(dǎo)出

    poi+easypoi實(shí)現(xiàn)表頭多層循環(huán),多級(jí)動(dòng)態(tài)表頭、樹(shù)形結(jié)構(gòu)動(dòng)態(tài)表頭、縱向合并單元格、多個(gè)sheet導(dǎo)出

    我前面也寫過(guò)幾篇關(guān)于easypoi復(fù)雜表格導(dǎo)出的文章,什么一對(duì)多縱向合并、多級(jí)表頭、動(dòng)態(tài)表頭、多個(gè)sheet等,這些我寫那幾篇文章之前做項(xiàng)目都遇到過(guò),并且都實(shí)現(xiàn)出來(lái)了。 感興趣的可以看看: easypoi多級(jí)表頭、多個(gè)sheet導(dǎo)出,動(dòng)態(tài)導(dǎo)出列、動(dòng)態(tài)更改表頭 easypoi一對(duì)多,縱向合

    2024年02月08日
    瀏覽(18)
  • Vue結(jié)合el-table實(shí)現(xiàn)合并單元格(以及高亮單元表頭和指定行)

    Vue結(jié)合el-table實(shí)現(xiàn)合并單元格(以及高亮單元表頭和指定行)

    實(shí)現(xiàn)效果如下: 思路: 1.首先使用動(dòng)態(tài)表頭表格。 2.其次實(shí)現(xiàn)動(dòng)態(tài)計(jì)算合并單元格。(計(jì)算規(guī)則 傳遞需要合并的字段) 3.然后封裝公共的計(jì)算單元格方法 export導(dǎo)出供多個(gè)頁(yè)面使用。 4.同時(shí)需要封裝成公共的組件供多個(gè)頁(yè)面使用。 5.組件內(nèi)寫指定表頭行高亮顏色以及指定行高

    2024年04月10日
    瀏覽(23)
  • pandas數(shù)據(jù)分析40——讀取 excel 合并單元格的表頭

    pandas數(shù)據(jù)分析40——讀取 excel 合并單元格的表頭

    案例背景 真的很容易瘋....上班的單位的表格都是不同的人做的,所以就會(huì)出現(xiàn)各種合并單元格的情況,要知道我們用pandas讀取數(shù)據(jù)最怕合并單元格了,因?yàn)闆](méi)規(guī)律...可能前幾列沒(méi)合并,后面幾列又合并了....而且pandas對(duì)于索引很嚴(yán)格,這種合并單元讀取進(jìn)來(lái)就是空的,還怎么

    2024年02月12日
    瀏覽(39)
  • poi-tl導(dǎo)出word復(fù)雜表格(單元格合并,生成復(fù)雜表格)

    poi-tl導(dǎo)出word復(fù)雜表格(單元格合并,生成復(fù)雜表格)

    官方文檔地址:http://deepoove.com/poi-tl/ 源碼地址:https://github.com/Sayi/poi-tl poi-tl(poi template language)是Word模板引擎,使用Word模板和數(shù)據(jù)創(chuàng)建很棒的Word文檔。 最近在做項(xiàng)目時(shí)候有一個(gè)關(guān)于導(dǎo)出Word的文件的需求,需要導(dǎo)出的word文件較大,并且格式比較復(fù)雜,使用poi-tl可以很好的

    2024年02月16日
    瀏覽(23)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包