8000 [Bug] 合并单元格内如果是图片,图片所在单元格未合并 · Issue #4123 · VisActor/VTable · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
[Bug] 合并单元格内如果是图片,图片所在单元格未合并 #4123
Closed
@jindazhen

Description

@jindazhen

Version

1.19.1

Link to Minimal Reproduction

jin13303813911@163.com

Steps to Reproduce

1、使用xlsxjs 解析一个excel表格,表格内容不限
2、拿到解析到的数据,使用vtable渲染
3、我使用cellType + fieldFormat 来处理可能出现图片的单元格,合并单元格用customMergeCell 来处理
整体效果不理想,1、图片无法定义宽高、2、合并单元格含有图片的时候,本该合并的单元格未合并,且每个单元格都加载了图片

Current Behavior

用vtable渲染excel表格,数据量可能很大,所以选择了vtable

Expected Behavior

主要代码如下
async loadOnlineExcel(excelUrl) {
this.fileOrigin = excelUrl.split('file-server')[0]
const response = await axios.get(excelUrl, { responseType: 'arraybuffer' })
// 解析 Excel
const workbook = XLSX.read(response.data, {
type: 'array'
// row: true,
// blankrows: false,
// cellStyles: true,
// cellHTML: true,
})

    this.workbook = workbook
    const sheetNames = workbook.SheetNames
    console.log(`🚀 ~ sheetNames:`, sheetNames)

    this.sheetNames = sheetNames
    const firstSheetName = workbook.SheetNames[0]
    const worksheet = workbook.Sheets[firstSheetName]

    const startRow = this.getStartRow(worksheet)

    // 获取合并单元格信息
    this.merges = worksheet['!merges'] || []

    // 转换为 JSON 数据
    const jsonData = XLSX.utils.sheet_to_json(worksheet, {
      header: 1,
      row: true,
      blankrows: true,
      range: worksheet['!ref']
    })
    // 添加起始空白行
    const newRow = new Array(jsonData[0].length).fill('')
    for (let i = 0; i < startRow; i++) {
      jsonData.unshift(newRow)
    }
    this.fillMergedCells(jsonData)

    this.initExcelData(jsonData)
},
initExcelData(jsonData) {
  const that = this
  console.log(`🚀 ~ jsonData:`, jsonData)
  this.mergedCells = this.workbook.Sheets[this.sheetNames[this.currentSheet]]['!merges'] || []
  if (jsonData.length > 0) {
    const headers = [''] // 第一行作为表头
    const strArr = [] // A-Z
    for (let i = 65; i <= 90; i++) {
      const letter = String.fromCharCode(i) // A, B, C, ..., Z
      // console.log(letter);
      strArr.push(letter)
    }
    jsonData[0].map((col, index) => {
      let str = ''
      if (index < 26) {
        str = strArr[index]
      } else if (index < 26 * 26) {
        const beforeStr = Math.floor(index / 26) - 1
        str = strArr[beforeStr] + strArr[index % 26]
      } else {
        str = index + 1
      }
      // console.log(str)
      headers.push(str)
    })
    this.headers = headers
    this.data = jsonData // 其余行作为数据

    this.vColumns = this.headers.map((header, headerIndex) => {
      return {
        title: header || '',
        field: header || 'myIndex',
        cellType(args) {
          if (!header) return 'text'
          const value = jsonData[args.row - 1][headerIndex] || ''
          if (value && String(value).includes('IMAGE:')) {
            return 'image'
          }
          return 'text';
        },
        fieldFormat(record) {
          if (!header) return record.myIndex
          let content = record[header]
          if (content && content.includes('IMAGE:')) {
            content = that.fileOrigin + content.replace(/^IMAGE:/, '')
          }

          return content
        },
        width: 'auto',
        height: 200,
        imageOptions: {
          width: 100,
          height100: 100,
          maxWidth: 200,     // 最大宽度
          maxHeight: 150,    // 最大高度
          minWidth: 50,      // 最小宽度
          style: {           // 自定义样式
            objectFit: 'contain', // 保持比例填充
            border: '1px solid #eee'
          },
          keepAspectRatio: true
        },
        keepAspectRatio: true
      }
    })
    this.vData = this.data.map((item, index) => {
      const row = {}
      this.headers.map((col, colIndex) => {
        row[col || 'myIndex'] = col ? item[colIndex] : (index + 1)
      })
      return row
    })
    console.log(this.vData)
    console.log(this.mergedCells)
    // const tableMerges = this.convertExcelMerges(this.mergedCells)

    const tableInstance = new VTable.ListTable(this.$refs.vTable, {
      columns: this.vColumns,
      records: this.vData,
      widthMode:'autoWidth',
      disableHtmlEscape: true, imageOptions: { 
        width: 120,
        height: 80,
        keepAspectRatio: true,
        placeholder: 'data:image/svg+xml;base64,...', // 加载占位图
        margin: 5
      },
      customMergeCell: that.mergedCells.map(merge => {
        console.log(`${merge.s.r},${merge.s.c}--${merge.e.r},${merge.e.c}`)
        
        const isImage = jsonData[merge.s.r][merge.s.c].startsWith('IMAGE:')
        const styleObj ={}
        isImage && (styleObj.width = '150px')
        const obj = {
          range: {
            start: { row: merge.s.r + 1, col: merge.s.c },
            end: { row: merge.e.r + 1, col: merge.e.c },
          },
          // 可以添加自定义样式
          style: {
            bgColor: '#fff',
            textAlign: 'center',
            ...styleObj
          }
        }
        if(isImage) {
          obj.html = `<img src="${that.fileOrigin + jsonData[merge.s.r][merge.s.c].replace(/^IMAGE:/, '')}" style="width: 100px" />`
        } else {
          obj.text = jsonData[merge.s.r][merge.s.c]
        }
        return obj
      })
    });
    this.loading = false

  } else {
    this.data = []
  }
},

Environment

- OS:
- Browser:
- Framework:

Any additional comments?

我尝试使用customRender也未达到理想效果

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinggood first issueGood for newcomers

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0