一:创建数据库:
关于示例数据请看附件的sql文件
二:核心算法
本算法主要是利用递归实现把树形结构的每条从根节点到叶子节点的路径放到一个二维String数组中,当有些路径的元素个数不能达到最大深度的时候,此路径元素个数与最多元素个数相差num,那么这个位置就用c_num填补。
三:应用jquery实现每列相同文本的单元格合并:
三:为了增加适用性,我用了jquery的ajax效果
四:显示效果:
数据库数据存储:
[img]http://dl.iteye.com/upload/picture/pic/71020/711f9c80-8d3f-353e-8f80-3f83f46dfbfc.bmp[/img]
jquery等待:
[img]http://dl.iteye.com/upload/picture/pic/71016/24189eb1-4b82-36b9-8185-455e425ce975.bmp[/img]
生成表格示例:
[img]http://dl.iteye.com/upload/picture/pic/71018/973d65ed-2e03-3c2b-9c01-3c3d8ebaba5f.bmp[/img]
create database InterViewTest1
use InterViewTeat1;
create table Category
(
id int(10) auto_increment,
name varchar(50),
code varchar(50),
parentCode varchar(50),
serNum int,--排序号
primary key(id)
)ENGINE=INNODB DEFAULT CHARSET=gbk;
关于示例数据请看附件的sql文件
二:核心算法
本算法主要是利用递归实现把树形结构的每条从根节点到叶子节点的路径放到一个二维String数组中,当有些路径的元素个数不能达到最大深度的时候,此路径元素个数与最多元素个数相差num,那么这个位置就用c_num填补。
private String rootName;
private int height;//树的深度
private int width;//树的叶子个数
private String[][] array=null;
private CategoryService cs=null;
public CategoryOp(String rootName){
this.rootName=rootName;
}
private void getAllNode(List<String> list,Category[] c){
if(c!=null){
for(int i=0;i<c.length;i++){
list.add(c[i].getName());
if(c[i].getChildCategory().length!=0){
getAllNode(list,c[i].getChildCategory());
}else{
int k=0;
for(String str:list){
array[this.width][k]=str;
k++;
}
for(int j=k;j<this.height;j++){
array[this.width][j] ="c_"+ (this.height+1-k);
}
this.width++;
}
list.remove(list.size()-1);
}
}
}
private void getNum(List<String> list,Category[] c){
if(c!=null){
for(int i=0;i<c.length;i++){
list.add(c[i].getName());
if(c[i].getChildCategory().length!=0){
getNum(list,c[i].getChildCategory());
}else{
if(this.height<list.size()){
this.height=list.size();
}
this.width++;
}
list.remove(list.size()-1);
}
}
}
public String getWidthAndHeight(){
cs=new CategoryService(this.rootName);
Category[] category=cs.getAllCategory();
this.width=0;
this.height=0;
List<String> list=new ArrayList<String>();
this.getNum(list, category);
return this.height+","+this.width;
}
public String[][] initArray(){
this.array=null;
this.width=0;
this.height=0;
this.getWidthAndHeight();
array=new String[this.width][this.height];
cs = new CategoryService(this.rootName);
Category[] c = cs.getAllCategory();
// this.height = 0;
this.width = 0;
List<String> list = new ArrayList<String>();
this.getAllNode(list, c);
return array;
}
public String getTable(){
this.initArray();
int w=this.width;
int h=this.height;
int num=0;
for(int i=0;i<w;i++){//这是为了合并表头
for(int j=0;j<h;j++){
if(array[i][j].startsWith("c_")){
String temp=array[i][j].substring(2);
if(this.isNumeric(temp)!=-1&&this.isNumeric(temp)>num){
num=this.isNumeric(temp);
}
}
}
}
StringBuilder sb=new StringBuilder();
sb.append("<table id=\"data\" border=\"1\" style=\"float\">");
sb.append("<tr>");
sb.append("<td align=\"center\">项目</td>");
sb.append("<td colspan=\""+num+1+"\" align=\"center\">科目</td>");
sb.append("</tr>");
for(int i=0;i<w;i++){
sb.append("<tr>");
for(int j=0;j<h;j++){
if (j < h - 1 && array[i][j + 1].startsWith("c_"))
{
String tmp = array[i][j + 1].substring(2);
sb.append("<td align='center' colspan='" + (this.isNumeric(tmp) + 1) + "'>" + array[i][j] + "</td>");
break;
}
else
{
sb.append("<td align='center' >" + array[i][j] + "</td>");
}
}
sb.append("</tr>");
}
sb.append("</table>");
return sb.toString();
}
三:应用jquery实现每列相同文本的单元格合并:
function _w_table_lefttitle_rowspan(_w_table_id,_w_table_mincolnum,_w_table_maxcolnum){
if(_w_table_mincolnum == void 0){_w_table_mincolnum=1;}
if(_w_table_maxcolnum == void 0){_w_table_maxcolnum=_w_table_mincolnum;}
if(_w_table_mincolnum>_w_table_maxcolnum){
return "";
}else{
var _w_table_splitrow=new Array();
for(iLoop=_w_table_mincolnum;iLoop<=_w_table_maxcolnum;iLoop++){
_w_table_onerowspan(iLoop);
}
}
function _w_table_onerowspan(_w_table_colnum){
_w_table_firstrow = 0;//前一列合并区块第一行
_w_table_SpanNum = 0;//合并单元格时的,单元格Span个数
_w_table_splitNum = 0;//数组的_w_table_splitrow的当前元素下标
_w_table_Obj = $(_w_table_id + " tr td:nth-child(" + _w_table_colnum + ")");
_w_table_curcol_rownum = _w_table_Obj.length-1;//此列最后一行行数
if(_w_table_splitrow.length==0){_w_table_splitrow[0] = _w_table_curcol_rownum;}
_w_table_lastrow = _w_table_splitrow[0];//前一列合并区块最后一行
var _w_table_firsttd;
var _w_table_currenttd;
var _w_table_curcol_splitrow=new Array();
_w_table_Obj.each(function(i){
if(i==_w_table_firstrow){
_w_table_firsttd = $(this);
_w_table_SpanNum = 1;
}else{
_w_table_currenttd = $(this);
if(_w_table_firsttd.text()==_w_table_currenttd.text()){
_w_table_SpanNum++;
_w_table_currenttd.hide(); //remove();
_w_table_firsttd.attr("rowSpan",_w_table_SpanNum);
}else{
_w_table_firsttd = $(this);
_w_table_SpanNum = 1;
setTableRow(i-1);
}
if(i==_w_table_lastrow){setTableRow(i);}
}
function setTableRow(_splitrownum){
if(_w_table_lastrow<=_splitrownum&&_w_table_splitNum++<_w_table_splitrow.length){
//_w_table_firstrow=_w_table_lastrow+1;
_w_table_lastrow=_w_table_splitrow[_w_table_splitNum];
}
_w_table_curcol_splitrow[_w_table_curcol_splitrow.length]=_splitrownum;
if(i<_w_table_curcol_rownum){_w_table_firstrow=_splitrownum+1;}
}
_w_table_splitrow=_w_table_curcol_splitrow;
});
}
}
三:为了增加适用性,我用了jquery的ajax效果
function btnCreate(){
$("#ajax").html("<img src=\"images/spinner3-greenie.gif\"/>");
$.ajax({
type:"post",
url:"create.action",
data:"",
complete:function(){},
success:function(data){
$("#ajax").html(data);
_w_table_lefttitle_rowspan("#data",1,90);
}
});
}
四:显示效果:
数据库数据存储:
[img]http://dl.iteye.com/upload/picture/pic/71020/711f9c80-8d3f-353e-8f80-3f83f46dfbfc.bmp[/img]
jquery等待:
[img]http://dl.iteye.com/upload/picture/pic/71016/24189eb1-4b82-36b9-8185-455e425ce975.bmp[/img]
生成表格示例:
[img]http://dl.iteye.com/upload/picture/pic/71018/973d65ed-2e03-3c2b-9c01-3c3d8ebaba5f.bmp[/img]