Ext的gridview分组没有小计及合计,自己搞了一周,才弄明白一点,发到网上,供EXT的学习者和研究者一个参考
用法:建一个gridpanel,把gridpanel中的view 换成Ext.ux.grid.SumGroupingView这个view,把xiaojiColumn设置上值就可以了,要注意xiaojiColumn的值要和record中名一样。
///<reference path="../vswd-ext_2.0.2.js" />
Ext.namespace("Ext.ux.grid");
Ext.ux.grid.SumGroupingView = Ext.extend(Ext.grid.GroupingView, {
//是否显示小计
displayXJ: true,
//小计的列
xiaojiColumn: [],
forceFit: true,
startCollapsed: true,
//重写getRows方法
getRows: function() {
if (!this.enableGrouping) {
return Ext.grid.GroupingView.superclass.getRows.call(this);
}
var r = [];
var g, gs = this.getGroups();
for (var i = 0, len = gs.length; i < len; i++) {
//排除掉小计的行,否则会把它认为是合计行
if (!gs[i].flag == undefined && gs[i].flag == "xiaoji") {
}
else if (gs[i].childNodes.length >= 2) {
g = gs[i].childNodes[1].childNodes;
for (var j = 0, jlen = g.length; j < jlen; j++) {
r[r.length] = g[j];
}
}
}
return r;
},
//重新写doGroupEnd,加小计行
doGroupEnd: function(buf, g, cs, ds, colCount) {
if (this.displayXJ && this.xiaojiColumn != null && this.xiaojiColumn.length > 0) {
var ts = this.templates, ct = ts.cell, rt = ts.row, last = colCount - 1;
var tstyle = 'width:' + this.getTotalWidth() + ';';
var cb, c, rp = { tstyle: tstyle }, r;
var cb = [];
var rt = new Ext.Template(
'<div class="x-grid3-row {alt}" style="{tstyle}" flag="xiaoji" ><table class="x-grid3-row-table" border="0" cellspacing="0" cellpadding="0" flag="xiaoji" style="{tstyle}" >',
'<tbody><tr style="font-style: italic;font-style: italic;">{cells}</tr>',
'</tbody></table></div>'
);
for (var k = 0; k < colCount; k++) {
c = cs[k];
var p = {};
var x;
p.id = c.id;
p.css = k == 0 ? 'x-grid3-cell-first ' : (k == last ? 'x-grid3-cell-last ' : '');
p.attr = p.cellAttr = "";
if (p.id == "numberer" && k == 0) {
p.value = 'S';
}
else if (k == 0) {
p.value = 'S';
}
for (var i = 0; i < this.xiaojiColumn.length; i++) {
x = this.xiaojiColumn[i];
if (c.name == x.name) {
p.value = this.calculations[x.compute](g.rs, c.name, x.format);
break;
}
}
p.style = c.style;
if (p.value == undefined || p.value === "") p.value = " "; //;
cb[cb.length] = ct.apply(p);
}
rp.alt = "";
rp.cells = cb.join("");
rp.tstyle += "background-color:#eee;";
buf[buf.length] = this.endGroup;
buf[buf.length] = rt.apply(rp);
}
else {
buf[buf.length] = this.endGroup;
}
},
//拼出合计的HTML
doHeji: function(cs, ds, colCount) {
var ts = this.templates, ct = ts.cell, rt = ts.row, last = colCount - 1;
var tstyle = 'width:' + this.getTotalWidth() + ';';
var cb, c, rp = { tstyle: tstyle }, r;
var cb = [];
var rt = new Ext.Template(
'<div class="x-grid3-row {alt}" style="{tstyle}" flag="heji" ><table class="x-grid3-row-table" border="0" cellspacing="0" cellpadding="0" flag="heji" style="{tstyle}" >',
'<tbody><tr style="font-style: italic;font-style: italic;">{cells}</tr>',
'</tbody></table></div>'
);
for (var k = 0; k < colCount; k++) {
c = cs[k];
var p = {};
var x;
p.id = c.id;
p.css = k == 0 ? 'x-grid3-cell-first ' : (k == last ? 'x-grid3-cell-last ' : '');
p.attr = p.cellAttr = "";
if (p.id == "numberer" && k == 0) {
p.value = 'T';
}
else if (k == 0) {
p.value = 'T';
}
for (var i = 0; i < this.xiaojiColumn.length; i++) {
x = this.xiaojiColumn[i];
if (c.name == x.name) {
p.value = this.calculations[x.compute](ds.data.items, c.name, x.format);
break;
}
}
p.style = c.style;
if (p.value == undefined || p.value === "") p.value = " "; //;
cb[cb.length] = ct.apply(p);
}
rp.alt = "";
rp.cells = cb.join("");
rp.tstyle += "background-color:#d0d0d0;";
return rt.apply(rp);
},
//重新updateGroupWidths,设置小计合计行列的宽度
updateGroupWidths: function() {
if (!this.enableGrouping || !this.hasRows()) {
return;
}
var tw = Math.max(this.cm.getTotalWidth(), this.el.dom.offsetWidth - this.scrollOffset) + 'px';
var gs = this.getGroups();
for (var i = 0, len = gs.length; i < len; i++) {
gs[i].firstChild.style.width = tw;
if (gs[i].flag && (gs[i].flag == 'xiaoji' || gs[i].flag == 'heji')) {
gs[i].style.width = tw;
gs[i].firstChild.style.width = tw;
for (var j = 1, tdlen = this.cm.getColumnCount(); j < tdlen; j++) {
gs[i].firstChild.childNodes[0].childNodes[0].childNodes[j].style.width = this.cm.getColumnWidth(j);
}
}
}
},
//重新doRender方法,加入合计行
doRender: function(cs, rs, ds, startRow, colCount, stripe) {
if (rs.length < 1) {
return '';
}
var groupField = this.getGroupField();
var colIndex = this.cm.findColumnIndex(groupField);
this.enableGrouping = !!groupField;
if (!this.enableGrouping || this.isUpdating) {
return Ext.grid.GroupingView.superclass.doRender.apply(
this, arguments);
}
var gstyle = 'width:' + this.getTotalWidth() + ';';
var gidPrefix = this.grid.getGridEl().id;
var cfg = this.cm.config[colIndex];
var groupRenderer = cfg.groupRenderer || cfg.renderer;
var prefix = this.showGroupName ?
(cfg.groupName || cfg.header) + ': ' : '';
var groups = [], curGroup, i, len, gid;
for (i = 0, len = rs.length; i < len; i++) {
var rowIndex = startRow + i;
var r = rs[i],
gvalue = r.data[groupField],
g = this.getGroup(gvalue, r, groupRenderer, rowIndex, colIndex, ds);
if (!curGroup || curGroup.group != g) {
gid = gidPrefix + '-gp-' + groupField + '-' + Ext.util.Format.htmlEncode(g);
var isCollapsed = typeof this.state[gid] !== 'undefined' ? !this.state[gid] : this.startCollapsed;
var gcls = isCollapsed ? 'x-grid-group-collapsed' : '';
curGroup = {
group: g,
gvalue: gvalue,
text: prefix + g,
groupId: gid,
startRow: rowIndex,
rs: [r],
cls: gcls,
style: gstyle
};
groups.push(curGroup);
} else {
curGroup.rs.push(r);
}
r._groupId = gid;
}
var buf = [];
for (i = 0, len = groups.length; i < len; i++) {
var g = groups[i];
this.doGroupStart(buf, g, cs, ds, colCount);
buf[buf.length] = Ext.grid.GroupingView.superclass.doRender.call(
this, cs, g.rs, ds, g.startRow, colCount, stripe);
this.doGroupEnd(buf, g, cs, ds, colCount);
}
if (this.displayXJ) {
//加合计
buf[buf.length] = this.doHeji(cs, ds, colCount);
}
return buf.join('');
},
onLayout: function() {
Ext.ux.grid.SumGroupingView.superclass.onLayout.call(this);
//展开第一个合计分组
this.expandFirstGroup();
},
expandFirstGroup: function() {
var firstgroup = this.hasRows() ? this.mainBody.dom.childNodes[0] : null;
if (firstgroup != null) {
this.toggleGroup(firstgroup, true);
}
},
//计算方法
calculations: {
'sum': function(values, field, format) {
var v = 0;
for (var i = 0; i < values.length; i++) {
v += Ext.num(parseFloat(values[i].data[field]), 0);
}
if (format) {
return Ext.util.Format.formatNumber(v, format);
}
else {
return v.toString();
}
;
},
'count': function(values, field, format) {
return values.length;
},
'max': function(values, field, format) {
var max = 0;
var v = 0;
for (var i = 0; i < values.length; i++) {
v = Ext.num(parseFloat(values[i].data[field]), 0);
max = max > v ? max : v;
}
if (format) {
return Ext.util.Format.formatNumber(max, format);
}
else {
return max.toString();
}
},
'min': function(values, field, format) {
var min = 0;
var v = 0;
for (var i = 0; i < values.length; i++) {
v = Ext.num(parseFloat(values[i].data[field]), 0);
min = min < v ? min : v;
}
if (format) {
return Ext.util.Format.formatNumber(min, format);
}
else {
return min.toString();
}
},
'average': function(values, field, format) {
var v = 0;
if (values.length > 0) {
for (var i = 0; i < values.length; i++) {
v += Ext.num(values[i].data[field], 0);
}
v = (v * 1.0000 / values.length);
}
if (format) {
return Ext.util.Format.formatNumber(v, format);
}
else {
return v.toString();
}
}
}
});
用法:建一个gridpanel,把gridpanel中的view 换成Ext.ux.grid.SumGroupingView这个view,把xiaojiColumn设置上值就可以了,要注意xiaojiColumn的值要和record中名一样。
///<reference path="../vswd-ext_2.0.2.js" />
Ext.namespace("Ext.ux.grid");
Ext.ux.grid.SumGroupingView = Ext.extend(Ext.grid.GroupingView, {
//是否显示小计
displayXJ: true,
//小计的列
xiaojiColumn: [],
forceFit: true,
startCollapsed: true,
//重写getRows方法
getRows: function() {
if (!this.enableGrouping) {
return Ext.grid.GroupingView.superclass.getRows.call(this);
}
var r = [];
var g, gs = this.getGroups();
for (var i = 0, len = gs.length; i < len; i++) {
//排除掉小计的行,否则会把它认为是合计行
if (!gs[i].flag == undefined && gs[i].flag == "xiaoji") {
}
else if (gs[i].childNodes.length >= 2) {
g = gs[i].childNodes[1].childNodes;
for (var j = 0, jlen = g.length; j < jlen; j++) {
r[r.length] = g[j];
}
}
}
return r;
},
//重新写doGroupEnd,加小计行
doGroupEnd: function(buf, g, cs, ds, colCount) {
if (this.displayXJ && this.xiaojiColumn != null && this.xiaojiColumn.length > 0) {
var ts = this.templates, ct = ts.cell, rt = ts.row, last = colCount - 1;
var tstyle = 'width:' + this.getTotalWidth() + ';';
var cb, c, rp = { tstyle: tstyle }, r;
var cb = [];
var rt = new Ext.Template(
'<div class="x-grid3-row {alt}" style="{tstyle}" flag="xiaoji" ><table class="x-grid3-row-table" border="0" cellspacing="0" cellpadding="0" flag="xiaoji" style="{tstyle}" >',
'<tbody><tr style="font-style: italic;font-style: italic;">{cells}</tr>',
'</tbody></table></div>'
);
for (var k = 0; k < colCount; k++) {
c = cs[k];
var p = {};
var x;
p.id = c.id;
p.css = k == 0 ? 'x-grid3-cell-first ' : (k == last ? 'x-grid3-cell-last ' : '');
p.attr = p.cellAttr = "";
if (p.id == "numberer" && k == 0) {
p.value = 'S';
}
else if (k == 0) {
p.value = 'S';
}
for (var i = 0; i < this.xiaojiColumn.length; i++) {
x = this.xiaojiColumn[i];
if (c.name == x.name) {
p.value = this.calculations[x.compute](g.rs, c.name, x.format);
break;
}
}
p.style = c.style;
if (p.value == undefined || p.value === "") p.value = " "; //;
cb[cb.length] = ct.apply(p);
}
rp.alt = "";
rp.cells = cb.join("");
rp.tstyle += "background-color:#eee;";
buf[buf.length] = this.endGroup;
buf[buf.length] = rt.apply(rp);
}
else {
buf[buf.length] = this.endGroup;
}
},
//拼出合计的HTML
doHeji: function(cs, ds, colCount) {
var ts = this.templates, ct = ts.cell, rt = ts.row, last = colCount - 1;
var tstyle = 'width:' + this.getTotalWidth() + ';';
var cb, c, rp = { tstyle: tstyle }, r;
var cb = [];
var rt = new Ext.Template(
'<div class="x-grid3-row {alt}" style="{tstyle}" flag="heji" ><table class="x-grid3-row-table" border="0" cellspacing="0" cellpadding="0" flag="heji" style="{tstyle}" >',
'<tbody><tr style="font-style: italic;font-style: italic;">{cells}</tr>',
'</tbody></table></div>'
);
for (var k = 0; k < colCount; k++) {
c = cs[k];
var p = {};
var x;
p.id = c.id;
p.css = k == 0 ? 'x-grid3-cell-first ' : (k == last ? 'x-grid3-cell-last ' : '');
p.attr = p.cellAttr = "";
if (p.id == "numberer" && k == 0) {
p.value = 'T';
}
else if (k == 0) {
p.value = 'T';
}
for (var i = 0; i < this.xiaojiColumn.length; i++) {
x = this.xiaojiColumn[i];
if (c.name == x.name) {
p.value = this.calculations[x.compute](ds.data.items, c.name, x.format);
break;
}
}
p.style = c.style;
if (p.value == undefined || p.value === "") p.value = " "; //;
cb[cb.length] = ct.apply(p);
}
rp.alt = "";
rp.cells = cb.join("");
rp.tstyle += "background-color:#d0d0d0;";
return rt.apply(rp);
},
//重新updateGroupWidths,设置小计合计行列的宽度
updateGroupWidths: function() {
if (!this.enableGrouping || !this.hasRows()) {
return;
}
var tw = Math.max(this.cm.getTotalWidth(), this.el.dom.offsetWidth - this.scrollOffset) + 'px';
var gs = this.getGroups();
for (var i = 0, len = gs.length; i < len; i++) {
gs[i].firstChild.style.width = tw;
if (gs[i].flag && (gs[i].flag == 'xiaoji' || gs[i].flag == 'heji')) {
gs[i].style.width = tw;
gs[i].firstChild.style.width = tw;
for (var j = 1, tdlen = this.cm.getColumnCount(); j < tdlen; j++) {
gs[i].firstChild.childNodes[0].childNodes[0].childNodes[j].style.width = this.cm.getColumnWidth(j);
}
}
}
},
//重新doRender方法,加入合计行
doRender: function(cs, rs, ds, startRow, colCount, stripe) {
if (rs.length < 1) {
return '';
}
var groupField = this.getGroupField();
var colIndex = this.cm.findColumnIndex(groupField);
this.enableGrouping = !!groupField;
if (!this.enableGrouping || this.isUpdating) {
return Ext.grid.GroupingView.superclass.doRender.apply(
this, arguments);
}
var gstyle = 'width:' + this.getTotalWidth() + ';';
var gidPrefix = this.grid.getGridEl().id;
var cfg = this.cm.config[colIndex];
var groupRenderer = cfg.groupRenderer || cfg.renderer;
var prefix = this.showGroupName ?
(cfg.groupName || cfg.header) + ': ' : '';
var groups = [], curGroup, i, len, gid;
for (i = 0, len = rs.length; i < len; i++) {
var rowIndex = startRow + i;
var r = rs[i],
gvalue = r.data[groupField],
g = this.getGroup(gvalue, r, groupRenderer, rowIndex, colIndex, ds);
if (!curGroup || curGroup.group != g) {
gid = gidPrefix + '-gp-' + groupField + '-' + Ext.util.Format.htmlEncode(g);
var isCollapsed = typeof this.state[gid] !== 'undefined' ? !this.state[gid] : this.startCollapsed;
var gcls = isCollapsed ? 'x-grid-group-collapsed' : '';
curGroup = {
group: g,
gvalue: gvalue,
text: prefix + g,
groupId: gid,
startRow: rowIndex,
rs: [r],
cls: gcls,
style: gstyle
};
groups.push(curGroup);
} else {
curGroup.rs.push(r);
}
r._groupId = gid;
}
var buf = [];
for (i = 0, len = groups.length; i < len; i++) {
var g = groups[i];
this.doGroupStart(buf, g, cs, ds, colCount);
buf[buf.length] = Ext.grid.GroupingView.superclass.doRender.call(
this, cs, g.rs, ds, g.startRow, colCount, stripe);
this.doGroupEnd(buf, g, cs, ds, colCount);
}
if (this.displayXJ) {
//加合计
buf[buf.length] = this.doHeji(cs, ds, colCount);
}
return buf.join('');
},
onLayout: function() {
Ext.ux.grid.SumGroupingView.superclass.onLayout.call(this);
//展开第一个合计分组
this.expandFirstGroup();
},
expandFirstGroup: function() {
var firstgroup = this.hasRows() ? this.mainBody.dom.childNodes[0] : null;
if (firstgroup != null) {
this.toggleGroup(firstgroup, true);
}
},
//计算方法
calculations: {
'sum': function(values, field, format) {
var v = 0;
for (var i = 0; i < values.length; i++) {
v += Ext.num(parseFloat(values[i].data[field]), 0);
}
if (format) {
return Ext.util.Format.formatNumber(v, format);
}
else {
return v.toString();
}
;
},
'count': function(values, field, format) {
return values.length;
},
'max': function(values, field, format) {
var max = 0;
var v = 0;
for (var i = 0; i < values.length; i++) {
v = Ext.num(parseFloat(values[i].data[field]), 0);
max = max > v ? max : v;
}
if (format) {
return Ext.util.Format.formatNumber(max, format);
}
else {
return max.toString();
}
},
'min': function(values, field, format) {
var min = 0;
var v = 0;
for (var i = 0; i < values.length; i++) {
v = Ext.num(parseFloat(values[i].data[field]), 0);
min = min < v ? min : v;
}
if (format) {
return Ext.util.Format.formatNumber(min, format);
}
else {
return min.toString();
}
},
'average': function(values, field, format) {
var v = 0;
if (values.length > 0) {
for (var i = 0; i < values.length; i++) {
v += Ext.num(values[i].data[field], 0);
}
v = (v * 1.0000 / values.length);
}
if (format) {
return Ext.util.Format.formatNumber(v, format);
}
else {
return v.toString();
}
}
}
});