`
IvanLi
  • 浏览: 604628 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

扩展dhtmlGrid,使其支持自定义公式和动态列,表头合并

阅读更多
dhtmlGrid是一个功能比较齐全的html Grid控件,在其profesonal版中生成支持公式编辑到cell级别,我只想动态求任意列的和
,又不想花钱,就自己扩展了一下dhtmlgrid,使其支持在任意cell上添加求和公式,同时如果没个cell的值发生了改变,那么关联的
公式项会自动变化,跟excell有点像了,当然他的功能远不及excell强大。
1:扩展eXcell
eXcell是dhmtlGrid所有的cell的基类,所有的cell都是扩展自eXcell,dhtml中自带的类型有readOnly(eXcell_ro),editable(eXcell_ed)
图片,link,等等可以自己看它的doc有介绍,我扩展的类就叫eXcell_formulas
2:扩展eXcell步骤:
function eXcell_formulas(cell){
		try{
			this.cell = cell;
			this.grid = this.cell.parentNode.grid;
		}catch(er){}
		/**
		*	@desc: method called by grid to start editing
		*/
		this.edit = function(){
					
			}
		/**
		*	@desc: get real value of the cell
		*/
		this.getValue = function(){
				return "";
			}
		/**
		*	@desc: set formated value to the cell
		*/
		this.setValue = function(val){
				if(val.toString().trim()=="")
					val = " ";
				this.cell.innerHTML = val;
			}
		/**
		*	@desc: this method called by grid to close editor
		*/
		this.detach = function(){
				this.setValue(this.obj.value);
				return this.val!=this.getValue();
			}
}
eXcell_formulas.prototype = new eXcell;

这是扩展的骨架,要实现setValue,getValue,edit,detach四个方法,也可以继承已有的类
看看我的代码吧
/*==== add by ivan li math begin====*/
function eXcell_formulas(cell)
{
 	try
	{
		this.cell = cell;
		//指向grid控件
		this.grid = this.cell.parentNode.grid;
		
	}catch(er){}
}
//再这里我扩展自eXcell_ed
eXcell_formulas.prototype = new eXcell_ed;
//这个方法接受外界传来的cell的值,在这里是公式的值,
//当让,在这里cell是可以编辑的,如果输入的是公式那么要以=号开头
eXcell_formulas.prototype.setValue = function(val)
{
	if((typeof(val)!="number")&& val.toString()._dhx_trim()=="")
	{
 		val=" "
 		this.cell._clearCell=true;
	}
	
	if(val.toString()._dhx_trim().indexOf('=') != -1)
	{
		//以=号开头,说明是公式,那么存下来公式
		this.cell._val = val.toString()._dhx_trim();
		this.cell.innerHTML="formulas";
		
	}
	else
	{
		//如果不是以=号开头那么仍然保留原来的公式
		this.cell.innerHTML=val.toString()._dhx_trim();
	}
	//add cell observer
	//prototype.addCellObserver()
	//计划在此处把用obserer模式存下targetCell ->this,但是现在没成功,
        //主要式在callBack时不能调用存下的this.calcVale方法
}
//就算公式的值并显示
eXcell_formulas.prototype.calcValue = function()
{
	var innerFormulas;
	//如果没有存公式那么就不用计算了
	if(!this.cell._val)
	{
		return;
	}
	else
	{
		innerFormulas = this.cell._val.substr(1);
	}
	var cellAr = innerFormulas.split(',');
	
	var formulasResult = 0;
	for(icell=0; icell<cellAr.length;icell++)
	{
		
		cellChild = cellAr[icell].split('^');
		//得到targetCell对象
		var ex = this.grid.cells(cellChild[0],cellChild[1]);
		//目前只实现了加法,对于公式的解析还有待实现
		formulasResult= Number(formulasResult)+Number(ex.getValue());
	}
	this.cell.innerHTML = formulasResult;
	//如果有公式,那么把cell的颜色设置成黄色,以做提示
	this.setBgColor("yellow");
}
//此处添加CellObserver
eXcell_formulas.prototype.addCellObserver = function()
{
	var cellAr = this.cell._val.split(',');
	for(i = 0; i< cellAr.length; i++)
	{
		//if already has observer on the cell
		if(this.grid.formulasObserver.hasKey(cellAr[i]))
		{
			formulasCellAr = this.grid.formulasObserver.getValue(cellAr[i]);
			var hasRegistered = false;
			
			for(j = 0; j<formulasCellAr.length;j++)
			{
				if(this._val == formulasCellAr[j]._val)
				{
					hasRegistered = true;
					break;
				}
			}
			//if has not registered then add this formulascell in
			if(!hasRegistered)
			{
				formulasCellAr.push(this);
			}
		}
		//if no observer on the cell then add a new one
		else
		{
			var cellObservers = new Array();
			cellObservers.push(this);
			
			this.grid.formulasObserver.add(cellAr[i], cellObservers);
		}
	}
}

/*====add by ivan li math end====*/

3:修改grid部分
/*add by Ivan Li 2006-10-20 begin*/
	this.calcFormulas = function()
	{
		for(i = 0; i<this.getColumnCount();i++)
		{
			if("formulas" == this.getColType(i))
			{
				this._calcFormulasCol(i)
			}
		}
	};
	this._calcFormulasCol = function(colIdx)
	{
		for(j = 0; j < this.getRowsNum(); j++)
		{
			this.cells2(j, colIdx).calcValue();
		}
	};
	this.notifyCellChange = function(rowId,cellInd)
	{
		
		formulasCells = this.formulasObserver.getValue(rowId+"^"+cellInd);
		
		for(i = 0; i<formulasCells.length; i++)
		{
			
			//formulasCells[i] is eXcell_formulas type
			formulasCells[i].calcValue();
		}
	};
	/*add by Ivan Li 2006-10-20 end*/

有关dhtmlGrid可以自己到http://www.scbr.com/docs/products/dhtmlxGrid/index.shtml下载
分享到:
评论
9 楼 lipengch 2006-11-27  
老大能把dhtmlxGrid1.1 pro版里面的setSerializationLevel(userData,fullXML,config,changedAttr,onlyChanged)函数提取出来吗?
非常感激!
8 楼 IvanLi 2006-11-03  
今天不太忙,我把从xml里配置header的js搞出来了,这也是它的pro版才提供的功能哦
在dhtmXGrid.js里加上这个方法,
dhtmlXGridObject.prototype._parseHeader = function(headCols)
{
	var arLab = new Array(0);
	var arWdth = new Array(0);
	var arTyp = new Array(0);
	var arAlg = new Array(0);
	var arSrt = new Array(0);
	for (var i=0; i < headCols.length; i++) 
	{
		arLab[arLab.length] = headCols[i].firstChild?headCols[i].firstChild.data:"col"+(i+1);
		arWdth[arWdth.length] = headCols[i].getAttribute("width");
		arTyp[arTyp.length] = headCols[i].getAttribute("type");
 		arAlg[arAlg.length] = headCols[i].getAttribute("align");
		arSrt[arSrt.length] = headCols[i].getAttribute("sort");
	}
	
	this.setHeader(arLab.join(','));
	this.setInitWidths(arWdth.join(','));
	this.setColTypes(arTyp.join(','));
	this.setColAlign(arAlg.join(','));
	this.setColSorting(arSrt.join(','));
	this.init();
}

然后在parseXML方法里
var ar = new Array();
var idAr = new Array();

的上一行加上这几句
        // add by ivan li 2006-11-03 begin for config header in xml begin
	var headCol = this.xmlLoader.doXPath("//rows/head/column", xmlDoc);
	if(headCol.length > 0)
	{// have config the rowheader in the xml
		this._parseHeader(headCol);
	}
	// add by ivan li 2006-11-03 begin for config header in xml end

就搞定了
现在的xml里可以这样配置了
<?xml version="1.0" encoding="utf-8"?>
<rows>
	<head>
		<column width="50" type="ro" align="right"  sort="str">a</column>
		<column width="50" type="ro" align="right"  sort="str">b</column>
		<column width="50" type="ro" align="right"  sort="str">c</column>
		<column width="50" type="ro" align="right"  sort="str">d</column>
		<column width="50" type="ro" align="right"  sort="str">e</column>
		<column width="50" type="ro" align="right"  sort="str">f</column>
		<column width="50" type="ro" align="right"  sort="str">g</column>
		<column width="50" type="ro" align="right"  sort="str">h</column>
	</head>
 	<row id="1">
		<cell>-1500</cell>
		<cell>A Time to Kill</cell>
		<cell><![CDATA[gavin king]]></cell>
		<cell>=2^3,3^3</cell>
		<cell>1</cell>
		<cell>24</cell>
		<cell>=1^4,1^3,2^4</cell>
		<cell>05/01/1998</cell>
	</row>
	<row id="2">
		<cell>1000</cell>
		<cell>Blood and Smoke</cell>
		<cell><![CDATA[<font color="red">Ste</font>phen King]]></cell>
		<cell>0</cell>
		<cell>1</cell>
		<cell>24</cell>
		<cell>=2^4,2^3</cell>
		<cell>01/01/2000</cell>
	</row>
</rows>

在页面里只需要
        mygrid = new dhtmlXGridObject('gridbox');
	mygrid.setImagePath("../imgs/");
        mygrid.init();
	mygrid.loadXML("formulas.xml");

就可以了,这个功能的实现对于要生成动态列的用户来说提供了很大的方便,在我们系统里就要求表格的列是动态的,原来必须把动态的列用taglib打到页面上去,例如
mygrid.setHeader('<bean:write name="myform" property="headerData"/>');

感觉很丑陋,现在好了,只要在后台构建好xml就搞定了
7 楼 IvanLi 2006-10-30  
我也出现过这个问题,但是在1.0版本中,不论是ie 还是ff, reload都能正常工作
6 楼 poiuyt373 2006-10-30  
没有试过firefox,ie下即使采用http也必须注释那句
5 楼 IvanLi 2006-10-27  
这个问题我跟作者交流了好几次,他说是ie在处理http://和file://文件不一样,如果用firefox就没事
4 楼 poiuyt373 2006-10-27  
测试reloaddata,发现同样的xml也报错,"LoadXML Incorrect XML",跟踪了一下发现
dhtmlXCommon.js中
dtmlXMLLoaderObject.prototype.getXMLTopNode=function(tagName){
if(this.xmlDoc.responseXML){
var temp=this.xmlDoc.responseXML.getElementsByTagName(tagName);
var z=temp[0];
}else
var z=this.xmlDoc.documentElement;
if(z)
return z;

if((_isIE)&&(!this._retry)){

var xmlString=this.xmlDoc.responseText;
this._retry=true;
this.xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
this.xmlDoc.async=false;
this.xmlDoc.loadXML(xmlString);
return this.getXMLTopNode(tagName);
}

dhtmlxError.throwError("LoadXML","Incorrect XML",[this.xmlDoc])
return document.createElement("DIV");
};


必须把this._retry=true;这句注释掉才行,不清楚_retry有什么用


3 楼 poiuyt373 2006-10-25  
居然不支持中文
2 楼 IvanLi 2006-10-23  
pro 版的还可以在xml里定义table的header,现在的还不可以,等我有时间了,搞一搞
1 楼 jerry.li 2006-10-20  
很不错的组件,可以用在以后的财务模块。

相关推荐

    QTableWidget QTableView 自定义复杂表头(多行表头,表头合并) 、冻结、固定特定的行

    至于表头的合并,`QTableView`同样不直接支持,但可以通过设置相同的列标题和调整`QHeaderView`的几何形状来实现。如果要实现真正的合并,可能需要重绘表头并处理点击事件,以正确地响应用户操作。 冻结或固定特定...

    Excel导出、自定义表头、锁定首行、合并、字体、边框

    在Excel中,我们可以在“开始”选项卡的“对齐”区域找到“合并和居中”按钮,单击即可合并选中的单元格。合并后的单元格内容将占据所有合并单元格的空间,并保持居中。 设置字体和边框能显著提升表格的专业外观。...

    devexpress 自定义合并单元格和表头

    通过研究这个示例,你可以更好地理解和应用DevExpress GridControl的自定义单元格合并和表头功能。记得将此示例代码与自己的项目需求相结合,以创建符合业务逻辑的定制化数据展示方案。 总之,掌握DevExpress的...

    复杂JTable-跨列表头

    2. **GroupableTableHeader**: 这个类扩展了JTable的默认表头JTableHeader,添加了支持列合并的功能。它会维护列分组信息,并与GroupableTableHeaderUI协同工作,确保正确的显示效果。 3. **TableHeaderRenderer**:...

    GridView动态表头合并,表头合并

    这个示例可能包含一个ASP.NET Web Forms页面,以及相关的后台代码文件,通过运行和调试这个项目,你可以直观地看到动态表头合并的效果,同时也能更深入地理解背后的实现逻辑。 总之,GridView动态表头合并是一个...

    GridView动态创建列头丶自定义多行合并表头

    ### GridView动态创建列头与自定义多行合并表头 #### 一、概述 在Web开发中,`GridView` 控件被广泛应用于显示表格数据。它不仅提供了强大的数据绑定功能,还支持各种自定义设置,使得开发者能够根据具体需求灵活...

    dataGridView表头合并列

    首先,我们要明白,`DataGridView`控件本身并不直接支持表头的合并功能。但是,我们可以通过一些技巧来模拟这个效果。一种常见方法是利用自定义绘制(Custom Painting)功能,覆盖`DataGridViewHeaderCell`的默认...

    自定义QTableView的表头QHeaderView实现多行表头

    1.自定义了一个表格View(TcTableView),支持继承重载相关虚函数, 2.TcTabelView支持设置多行横向表头(默认2行), 3.可以添加多张表格,每个表格是独立的,它们都有属于自己的自定义表头。 4.表头的右键操作我是自己写...

    C# DataGrid表头合并和单元格内容合并

    本教程将详细介绍如何在C#中实现DataGrid的表头合并和单元格内容合并,以及如何创建一个具有多层表头的示例(Demo)。 首先,我们要理解表头合并的概念。在DataGrid中,表头合并允许我们将多个列的标题合并成一个大...

    Gridcontrol合并表头、合并行、冻结列

    总结起来,DevExpress GridControl提供了强大的功能来满足复杂的数据展示需求,包括表头合并、行合并和冻结列。开发者可以根据项目需求灵活运用这些特性,提升应用的用户体验。在实际操作中,理解并熟练掌握这些方法...

    wpf 动态合并datagrid表头单元格

    要实现动态合并,我们需要扩展DataGrid的默认列类型。创建一个新的类,如`MergeableDataGridColumn`,继承自`DataGridBoundColumn`或`DataGridTemplateColumn`。在这个自定义列中,我们将处理表头的合并逻辑,通过...

    GridView实现多表头合并

    GridView控件本身并不直接支持多级表头的合并,但可以通过自定义代码来实现这一功能。以下是实现步骤: 1. **数据绑定**:首先,你需要准备合适的数据源,这可以是数据库查询结果、数组、集合或其他数据结构。数据...

    DataGrid表头合并和单元格内容合并-升级版

    这个“DataGrid表头合并和单元格内容合并-升级版”主题主要聚焦于如何在DataGrid中实现复杂的表头和单元格合并功能,以适应多层结构的数据展示需求。 首先,我们要理解在DataGrid中进行表头合并的意义。通常,当...

    JTable表头合并

    而"JTable表头合并"是Swing中的一个高级特性,允许开发者创建具有复杂结构的表头,以更好地呈现和组织数据。这种功能特别适用于那些需要将相关列分组或分类的情况。 表头合并是通过`DefaultTableColumnModel`的`...

    自定义表格,表头可合并单元格,自定义列数据

    然而,对于一些更复杂的需求,比如动态改变列宽、自定义渲染、表头合并等,就需要深入理解Qt的模型视图体系,并对其进行扩展和定制。Qt的模型视图架构允许我们将数据模型(如QStandardItemModel)与视图(如...

    element-ui表格el-table动态合并单元格(合并行和列)以及给表头添加斜线

    实现功能点 1.行的合并 2.列的合并 3.给表头添加斜线 4.动态生成列

    dev_GridView多表头合并.rar

    多表头合并可以使数据更容易理解,提供更好的阅读体验。实现GridView的多表头合并主要涉及以下几个关键步骤: 1. **创建多级表头**:首先,在GridView的HeaderRow中,可以添加额外的Row来模拟多级表头。通过编程...

    支持多表头及单元格合并的StringGrid

    支持多层表头、表头斜线 单元格合并、拆分; 每个单元格可单独设置字体、颜色、对齐等格式 随意行、列锁定 指定表格背景图片,格线顔色 对每行数据提供状态管理(Modified,Inserted,Deleted,Unmodified) 动态插入、...

    DataGrid 实现复杂表头和合并行源码与示例

    五、支持自定义转换器(IValueConverter); 六、支持对象集合(ICollection)和支持动态字典集合(ICollection, object&gt;&gt;)的绑定 ; 七、对象集合使用 AddBindingPathTemplateColumn 函数,字典集合使用 ...

    extjs3合并表头 rowspan

    7. **CSS Styling**: 为了使合并后的表头看起来正常,你可能还需要调整CSS样式,例如,确保合并的表头在视觉上与其他单元格对齐,以及处理边框和背景色。 8. **Event Handling**: 考虑到交互性,可能需要监听并处理...

Global site tag (gtag.js) - Google Analytics