定制软件开发项目中遇到表格单元格定制软件开发合并的需求,定制软件开发在此记录整个解决过程。
定制软件开发项目使用的是 Element UI,定制软件开发表格使用的是 table 组件。Element UI 的 table 定制软件开发表格组件中对单元格进行合并,需要使用 table 组件的 span-method 属性。
先看一张成果图(完整代码放在末尾):
解决思路:
1、格式化后台返回的数据(根据实际数据格式处理)
项目后台返回的数据格式为,这里做简化展示:
- [
- {
- 'column1': '111',
- 'column2': '222',
- 'column3': '333',
- 'children1': [
- {
- 'column6': 666,
- 'column4': '4440',
- 'column5': '5550',
- 'children2': [
- {
- 'column7': '77701',
- 'column8': '88801',
- 'column9': '99901'
- }
- ]
- }
- ]
- }
- ]
需要先将树结构数据转为一维数组:
- // table 表格数据初始化处理,将树结构数据转为一维数组
- handleData(data, parentId) {
- data.map((res, index) => {
- var obj = {
- id: parentId
- }
- for (const key in res) {
- const isarr = Object.values(res).find((age) => {
- return Array.isArray(age)
- })
- if (isarr) {
- if (Array.isArray(res[key])) {
- for (let i = 0; i < res[key].length; i++) {
- Object.assign(obj, res[key][i])
- data.push(obj)
- res[key].splice(i, 1)
- if (res[key].length === 0) {
- data.splice(index, 1)
- }
- this.handleData(data, parentId)
- }
- } else {
- Object.assign(obj, { [key]: res[key] })
- }
- }
- }
- })
- return data
- }
因为后台返回的数据里没有唯一标识符,所以需要单独添加一个唯一标识表示转换为一维数组的数据是出自同一组树结构里。故此处在展开时单独加了一个 id 属性,用来代替唯一标识。如果后台返回的数据格式就是一个一维数组,可跳过数据格式化步骤。
2、在 data 中定义数据,需要合并几列就定义几个数组和索引
- data() {
- return {
- tableData: [],
- // 合并单元格
- column1Arr: [], // column1
- column1Index: 0, // column1索引
- column2Arr: [], // column2
- column2Index: 0, // column2索引
- column3Arr: [], // column3
- column3Index: 0, // column3索引
- column4Arr: [], // column4
- column4Index: 0, // column4
- column5Arr: [], // column5
- column5Index: 0, // column5索引
- column6Arr: [], // column6
- column6Index: 0 // column6索引
- }
- }
3、定义合并函数
以第一行为基准,一层层对比,参数 data 就是格式化以后的表格数据,以每个数据里的唯一标识 id 作为合并的参照字段:
- // 初始化合并行数组
- mergeInit() {
- this.column1Arr = [] // column1
- this.column1Index = 0 // column1索引
- this.column2Arr = [] // column2
- this.column2Index = 0 // column2索引
- this.column3Arr = [] // column3
- this.column3Index = 0 // column3索引
- this.column4Arr = [] // column4
- this.column4Index = 0 // column4索引
- this.column5Arr = [] // column5
- this.column5Index = 0 // column5索引
- this.column6Arr = [] // column6
- this.column6Index = 0 // column6索引
- },
- // 合并表格
- mergeTable(data) {
- this.mergeInit()
- if (data.length > 0) {
- for (var i = 0; i < data.length; i++) {
- if (i === 0) {
- // 第一行必须存在,以第一行为基准
- this.column1Arr.push(1) // column1
- this.column1Index = 0
-
- this.column2Arr.push(1) // column2
- this.column2Index = 0
-
- this.column3Arr.push(1) // column3
- this.column3Index = 0
-
- this.column4Arr.push(1) // column4
- this.column4Index = 0
-
- this.column5Arr.push(1) // column5
- this.column5Index = 0
-
- this.column6Arr.push(1) // column6
- this.column6Index = 0
- } else {
- // 判断当前元素与上一元素是否相同
- // column1
- if (
- data[i].column1 === data[i - 1].column1 &&
- data[i].id === data[i - 1].id
- ) {
- this.column1Arr[this.column1Index] += 1
- this.column1Arr.push(0)
- } else {
- this.column1Arr.push(1)
- this.column1Index = i
- }
-
- // column2
- if (
- data[i].column2 === data[i - 1].column2 &&
- data[i].id === data[i - 1].id
- ) {
- this.column2Arr[this.column2Index] += 1
- this.column2Arr.push(0)
- } else {
- this.column2Arr.push(1)
- this.column2Index = i
- }
-
- // column3
- if (
- data[i].column3 === data[i - 1].column3 &&
- data[i].id === data[i - 1].id
- ) {
- this.column3Arr[this.column3Index] += 1
- this.column3Arr.push(0)
- } else {
- this.column3Arr.push(1)
- this.column3Index = i
- }
-
- // column4
- if (
- data[i].column4 === data[i - 1].column4 &&
- data[i].id === data[i - 1].id
- ) {
- this.column4Arr[this.column4Index] += 1
- this.column4Arr.push(0)
- } else {
- this.column4Arr.push(1)
- this.column4Index = i
- }
-
- // column5
- if (
- data[i].column5 === data[i - 1].column5 &&
- data[i].column4 === data[i - 1].column4 &&
- data[i].id === data[i - 1].id
- ) {
- this.column5Arr[this.column5Index] += 1
- this.column5Arr.push(0)
- } else {
- this.column5Arr.push(1)
- this.column5Index = i
- }
-
- // column6
- if (
- data[i].column6 === data[i - 1].column6 &&
- data[i].column4 === data[i - 1].column4 &&
- data[i].id === data[i - 1].id
- ) {
- this.column6Arr[this.column6Index] += 1
- this.column6Arr.push(0)
- } else {
- this.column6Arr.push(1)
- this.column6Index = i
- }
- }
- }
- }
- },
注意,同一组数据里可能会有多个 children1 或者 children2,这时合并的时候会有多个条件进行判断:
4、table 组件属性 span-method 的单元格合并方法:
- handleSpanMethod({ row, column, rowIndex, columnIndex }) {
- if (columnIndex === 0 || columnIndex === 1) {
- // 第一列 column1
- const _row_1 = this.column1Arr[rowIndex]
- const _col_1 = _row_1 > 0 ? 1 : 0
- return {
- rowspan: _row_1,
- colspan: _col_1
- }
- } else if (columnIndex === 2) {
- // 第二列 column2
- const _row_2 = this.column2Arr[rowIndex]
- const _col_2 = _row_2 > 0 ? 1 : 0
- return {
- rowspan: _row_2,
- colspan: _col_2
- }
- } else if (columnIndex === 3) {
- // 第三列 column3
- const _row_2 = this.column3Arr[rowIndex]
- const _col_2 = _row_2 > 0 ? 1 : 0
- return {
- rowspan: _row_2,
- colspan: _col_2
- }
- } else if (columnIndex === 4) {
- // 第四列 column4
- const _row_2 = this.column4Arr[rowIndex]
- const _col_2 = _row_2 > 0 ? 1 : 0
- return {
- rowspan: _row_2,
- colspan: _col_2
- }
- } else if (columnIndex === 5) {
- // 第五列 column5
- const _row_2 = this.column5Arr[rowIndex]
- const _col_2 = _row_2 > 0 ? 1 : 0
- return {
- rowspan: _row_2,
- colspan: _col_2
- }
- } else if (columnIndex === 6) {
- // 第六列 column6
- const _row_2 = this.column6Arr[rowIndex]
- const _col_2 = _row_2 > 0 ? 1 : 0
- return {
- rowspan: _row_2,
- colspan: _col_2
- }
- }
- }
至此,整个单元格合并就完成了!
如果觉得写得还不错,还请点赞支持,感谢感谢感谢!!!
完整代码:
- <template>
- <div class="table-wrap">
- <el-table
- :data="tableData"
- :span-method="handleSpanMethod"
- :cell-style="{ background: '#FFFFFF' }"
- border
- style="width: 100%"
- >
- <el-table-column prop="id" label="序号" align="center" width="80">
- <template slot-scope="scope">
- {{ scope.row.id + 1 }}
- </template>
- </el-table-column>
- <el-table-column prop="column1" label="column1" align="center" />
- <el-table-column prop="column2" label="column2" align="center" />
- <el-table-column prop="column3" label="column3" align="center" />
- <el-table-column prop="column4" label="column4" align="center" />
- <el-table-column prop="column5" label="column5" align="center" />
- <el-table-column prop="column6" label="column6" align="center" />
- <el-table-column prop="column7" label="column7" align="center" />
- <el-table-column prop="column8" label="column8" align="center" />
- <el-table-column prop="column9" label="column9" align="center" />
- </el-table>
- </div>
- </template>
-
- <script>
- export default {
- name: 'CellMerge',
- data() {
- return {
- tableData: [],
- // 合并单元格
- column1Arr: [], // column1
- column1Index: 0, // column1索引
- column2Arr: [], // column2
- column2Index: 0, // column2索引
- column3Arr: [], // column3
- column3Index: 0, // column3索引
- column4Arr: [], // column4
- column4Index: 0, // column4
- column5Arr: [], // column5
- column5Index: 0, // column5索引
- column6Arr: [], // column6
- column6Index: 0 // column6索引
- }
- },
- mounted() {
- this.initTableData()
- },
- methods: {
- // 初始化表格数据
- initTableData() {
- const newTableData = [
- {
- 'column1': '111',
- 'column2': '222',
- 'column3': '333',
- 'children1': [
- {
- 'column6': 666,
- 'column4': '4440',
- 'column5': '5550',
- 'children2': [
- {
- 'column7': '77701',
- 'column8': '88801',
- 'column9': '99901'
- },
- {
- 'column7': '77702',
- 'column8': '88802',
- 'column9': '99902'
- },
- {
- 'column7': '77703',
- 'column8': '88803',
- 'column9': '99903'
- }
- ]
- },
- {
- 'column6': 666,
- 'column4': '4441',
- 'column5': '5551',
- 'children2': [
- {
- 'column7': '77711',
- 'column8': '88811',
- 'column9': '99911'
- }
- ]
- },
- {
- 'column6': 666,
- 'column4': '4442',
- 'column5': '5552',
- 'children2': [
- {
- 'column7': '77721',
- 'column8': '88821',
- 'column9': '99921'
- },
- {
- 'column7': '77722',
- 'column8': '88822',
- 'column9': '99922'
- }
- ]
- }
- ]
- },
- {
- 'column1': '111',
- 'column2': '222',
- 'column3': '333',
- 'children1': [
- {
- 'column6': 666,
- 'column4': '4440',
- 'column5': '5550',
- 'children2': [
- {
- 'column7': '77701',
- 'column8': '88801',
- 'column9': '99901'
- }
- ]
- },
- {
- 'column6': 666,
- 'column4': '4441',
- 'column5': '5551',
- 'children2': [
- {
- 'column7': '77711',
- 'column8': '88811',
- 'column9': '99911'
- },
- {
- 'column7': '77712',
- 'column8': '88812',
- 'column9': '99912'
- }
- ]
- }
- ]
- },
- {
- 'column1': '111',
- 'column2': '222',
- 'column3': '333',
- 'children1': [
- {
- 'column6': 666,
- 'column4': '4440',
- 'column5': '5550',
- 'children2': [
- {
- 'column7': '77701',
- 'column8': '88801',
- 'column9': '99901'
- },
- {
- 'column7': '77702',
- 'column8': '88802',
- 'column9': '99902'
- },
- {
- 'column7': '77703',
- 'column8': '88803',
- 'column9': '99903'
- }
- ]
- },
- {
- 'column6': 666,
- 'column4': '4441',
- 'column5': '5551',
- 'children2': [
- {
- 'column7': '77711',
- 'column8': '88811',
- 'column9': '99911'
- }
- ]
- }
- ]
- }
- ]
- this.tableData = []
- newTableData.map((res, index) => {
- const parentId = index
- this.tableData.push.apply(
- this.tableData,
- this.handleData([res], parentId)
- )
- })
- this.mergeTable(this.tableData)
- },
- // table 表格数据初始化处理,将树结构数据转为一维数组
- handleData(data, parentId) {
- data.map((res, index) => {
- var obj = {
- id: parentId
- }
- for (const key in res) {
- const isarr = Object.values(res).find((age) => {
- return Array.isArray(age)
- })
- if (isarr) {
- if (Array.isArray(res[key])) {
- for (let i = 0; i < res[key].length; i++) {
- Object.assign(obj, res[key][i])
- data.push(obj)
- res[key].splice(i, 1)
- if (res[key].length === 0) {
- data.splice(index, 1)
- }
- this.handleData(data, parentId)
- }
- } else {
- Object.assign(obj, { [key]: res[key] })
- }
- }
- }
- })
- return data
- },
- // 初始化合并行数组
- mergeInit() {
- this.column1Arr = [] // column1
- this.column1Index = 0 // column1索引
- this.column2Arr = [] // column2
- this.column2Index = 0 // column2索引
- this.column3Arr = [] // column3
- this.column3Index = 0 // column3索引
- this.column4Arr = [] // column4
- this.column4Index = 0 // column4索引
- this.column5Arr = [] // column5
- this.column5Index = 0 // column5索引
- this.column6Arr = [] // column6
- this.column6Index = 0 // column6索引
- },
- // 合并表格
- mergeTable(data) {
- this.mergeInit()
- if (data.length > 0) {
- for (var i = 0; i < data.length; i++) {
- if (i === 0) {
- // 第一行必须存在,以第一行为基准
- this.column1Arr.push(1) // column1
- this.column1Index = 0
-
- this.column2Arr.push(1) // column2
- this.column2Index = 0
-
- this.column3Arr.push(1) // column3
- this.column3Index = 0
-
- this.column4Arr.push(1) // column4
- this.column4Index = 0
-
- this.column5Arr.push(1) // column5
- this.column5Index = 0
-
- this.column6Arr.push(1) // column6
- this.column6Index = 0
- } else {
- // 判断当前元素与上一元素是否相同
- // column1
- if (
- data[i].column1 === data[i - 1].column1 &&
- data[i].id === data[i - 1].id
- ) {
- this.column1Arr[this.column1Index] += 1
- this.column1Arr.push(0)
- } else {
- this.column1Arr.push(1)
- this.column1Index = i
- }
-
- // column2
- if (
- data[i].column2 === data[i - 1].column2 &&
- data[i].id === data[i - 1].id
- ) {
- this.column2Arr[this.column2Index] += 1
- this.column2Arr.push(0)
- } else {
- this.column2Arr.push(1)
- this.column2Index = i
- }
-
- // column3
- if (
- data[i].column3 === data[i - 1].column3 &&
- data[i].id === data[i - 1].id
- ) {
- this.column3Arr[this.column3Index] += 1
- this.column3Arr.push(0)
- } else {
- this.column3Arr.push(1)
- this.column3Index = i
- }
-
- // column4
- if (
- data[i].column4 === data[i - 1].column4 &&
- data[i].id === data[i - 1].id
- ) {
- this.column4Arr[this.column4Index] += 1
- this.column4Arr.push(0)
- } else {
- this.column4Arr.push(1)
- this.column4Index = i
- }
-
- // column5
- if (
- data[i].column5 === data[i - 1].column5 &&
- data[i].column4 === data[i - 1].column4 &&
- data[i].id === data[i - 1].id
- ) {
- this.column5Arr[this.column5Index] += 1
- this.column5Arr.push(0)
- } else {
- this.column5Arr.push(1)
- this.column5Index = i
- }
-
- // column6
- if (
- data[i].column6 === data[i - 1].column6 &&
- data[i].column4 === data[i - 1].column4 &&
- data[i].id === data[i - 1].id
- ) {
- this.column6Arr[this.column6Index] += 1
- this.column6Arr.push(0)
- } else {
- this.column6Arr.push(1)
- this.column6Index = i
- }
- }
- }
- }
- },
- handleSpanMethod({ row, column, rowIndex, columnIndex }) {
- if (columnIndex === 0 || columnIndex === 1) {
- // 第一列 column1
- const _row_1 = this.column1Arr[rowIndex]
- const _col_1 = _row_1 > 0 ? 1 : 0
- return {
- rowspan: _row_1,
- colspan: _col_1
- }
- } else if (columnIndex === 2) {
- // 第二列 column2
- const _row_2 = this.column2Arr[rowIndex]
- const _col_2 = _row_2 > 0 ? 1 : 0
- return {
- rowspan: _row_2,
- colspan: _col_2
- }
- } else if (columnIndex === 3) {
- // 第三列 column3
- const _row_2 = this.column3Arr[rowIndex]
- const _col_2 = _row_2 > 0 ? 1 : 0
- return {
- rowspan: _row_2,
- colspan: _col_2
- }
- } else if (columnIndex === 4) {
- // 第四列 column4
- const _row_2 = this.column4Arr[rowIndex]
- const _col_2 = _row_2 > 0 ? 1 : 0
- return {
- rowspan: _row_2,
- colspan: _col_2
- }
- } else if (columnIndex === 5) {
- // 第五列 column5
- const _row_2 = this.column5Arr[rowIndex]
- const _col_2 = _row_2 > 0 ? 1 : 0
- return {
- rowspan: _row_2,
- colspan: _col_2
- }
- } else if (columnIndex === 6) {
- // 第六列 column6
- const _row_2 = this.column6Arr[rowIndex]
- const _col_2 = _row_2 > 0 ? 1 : 0
- return {
- rowspan: _row_2,
- colspan: _col_2
- }
- }
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- .table-wrap {
- width: 100%;
- height: 100%;
- padding: 20px;
- }
- </style>