之前也看了很多关于单元格合并的代码,但实现的东西都与我自己的需求大相径庭,以为我的需求是根据B列相同名称,合并E列的数据。效果和代码都会发在下方,技术栈:angular+ts(技术没那么重要,主要是思路吧)
效果如下:根据站点名相同,合并TS评分数据
html代码如下:
<div class="row-label-layout">
<nz-table #rowSelectionTable [nzBordered]="true" [nzShowPagination]="false" nzShowSizeChanger
[nzData]="tableListData" nzTableLayout="fixed" nzSize="small" class="table-overflow-y test-panel-list"
[nzScroll]="{ y:'1px' }">
<thead>
<tr>
<th nzWidth="140px">时效</th>
<th nzWidth="140px">站名</th>
<th nzWidth="140px" [nzSortFn]="true" (nzSortOrderChange)="onSortChange('abs',$event)" *ngIf="arealRainfallChecked.indexOf('abs') !== -1">绝对误差</th>
<th nzWidth="140px" [nzSortFn]="true" (nzSortOrderChange)="onSortChange('rel',$event)" *ngIf="arealRainfallChecked.indexOf('rel') !== -1">相对误差</th>
<th nzWidth="140px" [nzSortFn]="true" (nzSortOrderChange)="onSortChange('ts',$event)" *ngIf="arealRainfallChecked.indexOf('ts') !== -1">TS评分</th>
<th nzWidth="140px" [nzSortFn]="true" (nzSortOrderChange)="onSortChange('blur_score',$event)" *ngIf="arealRainfallChecked.indexOf('blur_score') !== -1">模糊评分</th>
</tr>
</thead>
<tbody>
<tr *ngFor=" let item of tableListData">
<td nzWidth="140px">{{item.time}}</td>
<td nzWidth="140px">{{item.region}}</td>
<td nzWidth="140px" *ngIf="arealRainfallChecked.indexOf('abs') !== -1">{{item.abs == -999 ? '暂无数据' : item.abs}}</td>
<td nzWidth="140px" *ngIf="arealRainfallChecked.indexOf('rel') !== -1">{{item.rel == -999 ? '暂无数据' : item.rel}}</td>
<ng-container *ngFor="let t of mergeColumns;">
<ng-container *ngIf="item[t]!==undefined">
<td nzWidth="140px" *ngIf="arealRainfallChecked.indexOf('ts') !== -1" [attr.rowspan]="item[rowspan+t]">{{ item[t] == -999 ? '暂无数据' : item[t]}}</td>
</ng-container>
</ng-container>
<!-- <td nzWidth="140px" *ngIf="arealRainfallChecked.indexOf('ts') !== -1">{{item.ts == -999 ? '暂无数据' : item.ts}}</td> -->
<td nzWidth="140px" *ngIf="arealRainfallChecked.indexOf('blur_score') !== -1">{{item.blur_score == -999 ? '暂无数据' : item.blur_score}}</td>
</tr>
</tbody>
</nz-table>
</div>
html主要呈现代码:
<ng-container *ngFor="let t of mergeColumns;">
<ng-container *ngIf="item[t]!==undefined">
<td nzWidth="140px" *ngIf="arealRainfallChecked.indexOf('ts') !== -1" [attr.rowspan]="item[rowspan+t]">{{ item[t] == -999 ? '暂无数据' : item[t]}}</td>
</ng-container>
</ng-container>
js/ts代码如下:
// 表格合拼 (所需变量)
rowspan: any;
mergeColumns: any = ['ts'];
// 数据源格式为[{},{},{}]
disposeTableData(dataOrigin: any) { // 处理合并数据源 将数据源根据名称转为 二维数组
let data: any = [];
let transferData: any = [];
dataOrigin.forEach((item: any) => {
if (transferData.length === 0) {
transferData[0] = []
transferData[0].push(item)
} else {
let flag: any = -1;
for (let i = 0; i < transferData.length;i++ ) {
if(transferData[i][0].region === item.region) {
transferData[i].push(item)
break
}
if ((i + 1) === transferData.length) {
flag = transferData.length;
}
}
if (flag !== -1) {
transferData[flag] = []
transferData[flag].push(item)
flag = -1
}
}
})
for (let i = 0; i < transferData.length; i++) {
this.sortAndMerge(transferData[i]).forEach((item) => {
data.push(item)
})
// data.push(this.sortAndMerge(transferData[i]))
}
return data
}
sortAndMerge(rawDataList): any[] { // 处理合并数据 (处理二维数组中的子组数据 进行返回)
const rowspan = this.rowspan, mergeColumns = this.mergeColumns;
if (rawDataList.length > 1) {//长度大于1才有资格进一步处理
const sortColumn = Object.keys(rawDataList[0]), // 字段名称 ['region', 'time', 'rel', 'abs', 'ts', 'blur_score']
keySort = raw => {
for (let i = raw.length - 1; i > 0; i--) {
let newObj = {}, tmpObj = raw[i]; // raw[i]是单条数据
sortColumn.forEach(s => {
// s 为 ['region', 'time', 'rel', 'abs', 'ts', 'blur_score'] 中的每一项
newObj[s] = tmpObj[s]
});
console.log(newObj);
raw[i] = newObj;
}
return raw;
},
compare = (a, b, c = sortColumn[0], i = 0) => {
if (a[c] === b[c]) { //等于的话进行判断是否还有后续字段需要排序,没有则返回0;有则递归进行后续字段排序处理。
if (i === sortColumn.length - 1) {//没有后续字段
return i = 0;
}
i++;
return compare(a, b, sortColumn[i], i);//递归排序后续字段
} else if (a[c] > b[c]) { //大于返回1
return 1;
} else { //小于返回-1
return -1;
}
},
arr = keySort(JSON.parse(JSON.stringify(rawDataList))),
aLen = arr.length;
for (let i = mergeColumns.length - 1; i >= 0; i--) {//先迭代待合并列
let index = 0;
let title = mergeColumns[i];
let span = 1;//合并列属性默认为1
for (let j = 0; j < aLen; j++) {
let comp = arr[index][title];
let compRegion = arr[index]['region']; // 拿到名称
// if (arr[j][title] === comp) {
if (arr[j][title] === comp && arr[j]['region'] === compRegion) {
j !== index && (delete arr[j][title], span++);
j === aLen - 1 && (arr[index][rowspan + title] = span);
} else {
span > 1 && (arr[index][rowspan + title] = span, span = 1);
index = j;
}
}
}
return arr;
}
return rawDataList;
}
this.tableListData = this.disposeTableData(JSON.parse(JSON.stringify(this.tradingvolumeListData))) // 处理合并数据 赋值 html展示