所在的位置: html >> html优势 >> DataTable转HTML实现单元

DataTable转HTML实现单元

白癜风诊疗康复 https://wapjbk.39.net/yiyuanfengcai/yyjs_bjzkbdfyy/

在关系型数据库中,数据往往是以列表的形式存储,但实际上物理结构上并列的数据存在逻辑上的关系,比如父子关系的树形结构等。同样数据库存储的数据在界面上展示时也需要将类似的关系展现出来,比如表格中常用的单元格合并。

1.单元格在什么条件下可以合并

在Excel中单元格的合并是由使用者操控的,并没有什么前置条件,但如果要通过代码实现单元格合并,就必须有一系列能让计算机读懂的规则。常见的的需要合并单元格的情况是:多个相邻的单元格有相同的值,同时相邻区域应该是长方形,如宽高为1*2、2*1、4*2等。

2.DataTable转换为HTML并自动合并单元格

后端代码遍历DataTable中的数据,拼接成HTML,并在处理过程中合并单元格,输出给前端。

///summary///数据表转换为HTML并自动合并单元格////summary///paramname="dt"数据表/param///paramname="tableId"标识/param///paramname="isAddSort"是否添加序号/param///returns/returnspublicstringConvertTableToHtmlWithMergeCells(DataTabledt,stringtableId,boolisAddSort){//先行后列,建立单元格值字典Dictionarystring,Listint[]dicInit=newDictionarystring,Listint[]();for(inti=0;idt.Rows.Count;i++){for(intj=0;jdt.Columns.Count;j++){if(!string.IsNullOrWhiteSpace(dt.Rows[i][j].ToString())){vark=dt.Rows[i][j].ToString();if(!dicInit.ContainsKey(k)){dicInit.Add(k,newListint[]{newint[2]{i,j}});}else{varv=dicInit[k];dicInit.Remove(k);v.Add(newint[2]{i,j});dicInit.Add(k,v);}}}}//过滤出具有相同值且需要合并的单元格Dictionarystring,Listint[]dic=newDictionarystring,Listint[]();foreach(varkindicInit){if(IsNeedMerge(k.Value)){dic.Add(k.Key,k.Value);}}//构造数据表StringBuilderhtmlBuilder=newStringBuilder();htmlBuilder.Append("tablecellspacing=\"0\"cellpadding=\"0\"width=\"%\"id=\""+tableId+"\"");htmlBuilder.Append("tbody");//首行htmlBuilder.Append("trclass=\"firstRow\"");if(isAddSort)//是否增加序号列{htmlBuilder.Append("td序号/td");}for(inti=0;idt.Columns.Count;i++)//列{htmlBuilder.Append("td");htmlBuilder.Append(dt.Columns[i].ColumnName);htmlBuilder.Append("/td");}htmlBuilder.Append("/tr");//遍历数据表并拼接内容for(inti=0;idt.Rows.Count;i++)//行{htmlBuilder.Append("tr");introwNum=i+1;//行序号if(isAddSort)//是否增加行序号{htmlBuilder.Append("td"+rowNum+"/td");}for(intj=0;jdt.Columns.Count;j++)//列{stringcellValue=dt.Rows[i][j].ToString();if(!string.IsNullOrEmpty(cellValue)dic.ContainsKey(cellValue)){vararrys=dic[cellValue];int[]firstCell=arrys[0];int[]lastCell=arrys[arrys.Count-1];introw=lastCell[0]-firstCell[0]+1;//行数intcol=lastCell[1]-firstCell[1]+1;//列数if(i==firstCell[0]j==firstCell[1])//需要合并的单元格中,只保留首行首列的一个{htmlBuilder.Append("tdrowspan=\""+row+"\"colspan=\""+col+"\"");htmlBuilder.Append(cellValue);htmlBuilder.Append("/td");}}else{htmlBuilder.Append("td");htmlBuilder.Append(cellValue);htmlBuilder.Append("/td");}}htmlBuilder.Append("/tr");}htmlBuilder.Append("/tbody");htmlBuilder.Append("/table");stringstrHtml=htmlBuilder.ToString().Replace("\"","");returnstrHtml;}///summary///判断是否需要合并单元格////summary///paramname="arrys"/param///returns/returnsprivateboolIsNeedMerge(Listint[]arrys){boolresult=false;intnum=arrys.Count;//具有相同值的单元格总数if(num1)//移除只出现值只出现过一次的单元格{int[]firstCell=arrys[0];int[]lastCell=arrys[arrys.Count-1];introw=lastCell[0]-firstCell[0]+1;//行数intcol=lastCell[1]-firstCell[1]+1;//列数if(row*col==num)//若行数与列数之积等于单元格总数,则说明具有相同值的单元格相邻分布,可以合并{result=true;}}returnresult;}

这里的思路有点类似倒排索引,为数据表中的所有非空值建立索引表,记录每个值在数据表中出现的位置。首先进行一次过滤,将索引表中只出现过一次的值去除掉,只出现一次是肯定不需要合并单元格的,也能减少查询过程。然后循环遍历数据表,开始拼接HTML字符串,如果单元格的值在索引表中,说明需要拼接单元格。同时索引表中值的位置是按照行、列的顺序记录的,所以能确保位置列表中的第一个位置是需要合并单元格的第一个,只要设置这个单元格的跨行、跨列属性即可。

需要注意的是这个方法还存在以下问题:

只适用于具有相同值的单段连续单元格,多段间隔连续的单元格则无法分别合并。再进一步优化的思路是索引表在记录位置的基础上记录两个相同值单元格的间隔步长。

只适用于字符串类型的单元格值。在进一步优化的思路是对于数字类型的单元格值,要么不合并,要么除了合并单元格外,还要计算数字之和。

ludewig




转载请注明:http://www.aierlanlan.com/grrz/499.html

  • 上一篇文章:
  •   
  • 下一篇文章: