前面提到过工作台(《EXT.NET复杂布局(一)——工作台》)了,不知道各位看过之后有什么感想。这次就介绍介绍使用EXT.NET画几个报表。
看图写作从小学就开始了,如图:
图一
图二
图三(1)
图三(2)
各位看官,不要以为这报表画起来很难,其实使用EXT.NET来画的话,还是挺简单方便的。
1)下面就从图一开始。
这个报表实现,本人采用的是最原始的手写代码(之所以这么说,是因为没怎么偷懒,老老实实的写的,因为这是刚接触EXT.NET的时候画的)
先上代码,然后再说话吧。其实注释挺全的,所以也不需要说什么话了:
<%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %> <style type="text/css"> .total-field { background-color: #fff; font-weight: bold !important; color: #000; border: solid 1px silver; padding: 2px; margin-right: 5px; } .headRows1 { color: Green; font-weight: bolder; } .headRows2 { color: Blue; font-weight: bolder; } </style> <script type="text/javascript"> function getYear() { return <%=txtYear.ClientID %>.getValue(); } function getMonth() { return <%=cboMonth.ClientID %>.getValue(); } </script> <ext:ResourceManager ID="ResourceManager1" runat="server"> </ext:ResourceManager> <ext:Viewport runat="server" ID="Viewport1" Layout="Fit"> <Items> <ext:GridPanel ID="GridPanel1" Width="400" Height="230" TrackMouseOver="true" runat="server" StripeRows="true" Title="店铺状态统计表" Header="false" AutoExpandColumn="RptId" Frame="true"> <Store> <ext:Store ID="Store1" ShowWarningOnFailure="false" AutoLoad="false" runat="server"> <Proxy> <ext:HttpProxy runat="server" Method="POST" Url="/Ajax/Reports.ashx"> </ext:HttpProxy> </Proxy> <Reader> <ext:JsonReader IDProperty="RptId" TotalProperty="total" Root="data"> <Fields> <%--RptId 标识 店铺状态统计表--%> <ext:RecordField Name="RptId" /> <%--报表年份--%> <ext:RecordField Name="RptYear" /> <%--报表月份--%> <ext:RecordField Name="RptMonth" /> <%--新概念店目标--%> <ext:RecordField Name="TargetNewEntrant" /> <%--其他品牌转新概念店目标--%> <ext:RecordField Name="TargetOM" /> <%--家乐福店目标--%> <ext:RecordField Name="TargetC4" /> <%--总数目标--%> <ext:RecordField Name="TargetTotal" /> <%--新概念店开店数--%> <ext:RecordField Name="NewStoreNewEntrant" /> <%--其他品牌转新概念店开店数--%> <ext:RecordField Name="NewStoreOM" /> <%--家乐福开店数--%> <ext:RecordField Name="NewStoreC4" /> <%--新概念店开店总数--%> <ext:RecordField Name="NewStoreNCSTotal" /> <%--美丽健康店开店数--%> <ext:RecordField Name="NewStoreHB" /> <%--开店总数--%> <ext:RecordField Name="NewStoreTotal" /> <%--新概念店签约数--%> <ext:RecordField Name="ContractSignedNCS" /> <%--美丽健康店签约数--%> <ext:RecordField Name="ContractSignedHB" /> <%--签约总数--%> <ext:RecordField Name="ContractSignedTotal" /> <%--新概念店施工数--%> <ext:RecordField Name="UnderDecoNCS" /> <%--美丽康店施工数--%> <ext:RecordField Name="UnderDecoHB" /> <%--施工总数--%> <ext:RecordField Name="UnderDecoTotal" /> <%--改型店目标--%> <ext:RecordField Name="UpgradingTarget" /> <%--改型店数--%> <ext:RecordField Name="UpgradingInOperation" /> <%--改型店签约数--%> <ext:RecordField Name="UpgradingContractSigned" /> <%--改型店施工数--%> <ext:RecordField Name="UpgradingUnderDeco" /> <%--自动解约数--%> <ext:RecordField Name="ClosureNonPerform" /> <%--公司解约数--%> <ext:RecordField Name="ClosureForcedAttrition" /> <%--解约总数--%> <ext:RecordField Name="ClosureTotal" /> <%--净店数--%> <ext:RecordField Name="StoreStatusNetStore" /> <%--新概念店总数--%> <ext:RecordField Name="StoreStatusStoreNoNCS" /> <%--美丽健康店总数--%> <ext:RecordField Name="StoreStatusStoreNoHB" /> <%--老店总数--%> <ext:RecordField Name="StoreStatusStoreNoOld" /> <%--总店数--%> <ext:RecordField Name="StoreStatusStoreNoTotal" /> <%--报表创建日期--%> <ext:RecordField Name="RptDate" Type="Date" /> <ext:RecordField Name="DisplayMonth" /> </Fields> </ext:JsonReader> </Reader> <BaseParams> <ext:Parameter Name="type" Value="ShopStatus" Mode="Value" /> <ext:Parameter Name="Year" Value="getYear()" Mode="Raw" /> <ext:Parameter Name="Month" Value="getMonth()" Mode="Raw" /> </BaseParams> </ext:Store> </Store> <ColumnModel ID="ColumnModel1" runat="server"> <Columns> <%--National:Start--%> <ext:Column Header="Year" Hideable="true" DataIndex="DisplayMonth" Locked="true" /> <ext:Column Header="ID" ColumnID="RptId" Hidden="true" DataIndex="RptId" /> <%--National:End--%> <%--<ext:Column Header="报表年份" Hidden="true" DataIndex="RptYear" />--%> <%--NewStore:Start--%> <%-----------Target:Start--%> <ext:Column Header="NewEntrant" Hideable="true" DataIndex="TargetNewEntrant" /> <ext:Column Header="OM" Hideable="true" DataIndex="TargetOM" /> <ext:Column Header="C4" Hideable="true" DataIndex="TargetC4" /> <ext:Column Header="Total" Hideable="true" DataIndex="TargetTotal" /> <%-----------Target:End--%> <%-----------Actual Store opened:Start--%> <ext:Column Header="NewEntrant" Hideable="true" DataIndex="NewStoreNewEntrant" /> <ext:Column Header="OM" Hideable="true" DataIndex="NewStoreOM" /> <ext:Column Header="C4" Hideable="true" DataIndex="NewStoreC4" /> <ext:Column Header="Total" Hideable="true" DataIndex="NewStoreNCSTotal" /> <ext:Column Header="H&B" Hideable="true" DataIndex="NewStoreHB" /> <ext:Column Header="Total" Hideable="true" DataIndex="NewStoreTotal" /> <%-----------Actual Store opened:End--%> <%----------- Contract Signed:Start--%> <ext:Column Header="NCS" Hideable="true" DataIndex="ContractSignedNCS" /> <ext:Column Header="H&B" Hideable="true" DataIndex="ContractSignedHB" /> <ext:Column Header="Total" Hideable="true" DataIndex="ContractSignedTotal" /> <%----------- Contract Signed:End--%> <%----------- Under Deco.:Start--%> <ext:Column Header="NCS" Hideable="true" DataIndex="UnderDecoNCS" /> <ext:Column Header="H&B" Hideable="true" DataIndex="UnderDecoHB" /> <ext:Column Header="Total" Hideable="true" DataIndex="UnderDecoTotal" /> <%----------- Under Deco.:End--%> <%--NewStore:End--%> <%--Upgrading:Start--%> <ext:Column Header="Target" Hideable="true" DataIndex="UpgradingTarget" /> <ext:Column Header="InOperation" Hideable="true" DataIndex="UpgradingInOperation" /> <ext:Column Header="ContractSigned" Hideable="true" DataIndex="UpgradingContractSigned" /> <ext:Column Header="UnderDeco" Hideable="true" DataIndex="UpgradingUnderDeco" /> <%--Upgrading:End--%> <%--Closure:Start--%> <%----------- Drop-Out:Start--%> <ext:Column Header="NonPerform" Hideable="true" DataIndex="ClosureNonPerform" /> <ext:Column Header="ForcedAttrition" Hideable="true" DataIndex="ClosureForcedAttrition" /> <ext:Column Header="Total" Hideable="true" DataIndex="ClosureTotal" /> <%----------- Drop-Out:End--%> <%--Closure:End--%> <%--Store Status:Start--%> <ext:Column Header="NetStore" Hideable="true" DataIndex="StoreStatusNetStore" /> <%----------- Store No.:Start--%> <ext:Column Header="NCS" Hideable="true" DataIndex="StoreStatusStoreNoNCS" /> <ext:Column Header="H&B" Hideable="true" DataIndex="StoreStatusStoreNoHB" /> <ext:Column Header="Old" Hideable="true" DataIndex="StoreStatusStoreNoOld" /> <ext:Column Header="Total" Hideable="true" DataIndex="StoreStatusStoreNoTotal" /> <%----------- Store No.:End--%> <%--Store Status:End--%> <ext:DateColumn Header="报表创建日期" Hidden="true" DataIndex="RptDate" Format="yyyy-MM-dd" /> </Columns> </ColumnModel> <LoadMask ShowMask="true" /> <View> <ext:GroupingView runat="server"> <%--隐藏列在分组标头中,仍占用列数--%> <%--一个HeaderGroupRows表示一行--%> <HeaderGroupRows> <ext:HeaderGroupRow> <Columns> <ext:HeaderGroupColumn Header="<font class='headRows1'>National</font>" Align="Center" /> <ext:HeaderGroupColumn Align="Center" Header="<font class='headRows1'>New Store</font>" ColSpan="17" /> <ext:HeaderGroupColumn Align="Center" Header="<font class='headRows1'>Upgrading</font>" ColSpan="4" /> <ext:HeaderGroupColumn Align="Center" Header="<font class='headRows1'>Closure</font>" ColSpan="3" /> <ext:HeaderGroupColumn Align="Center" Header="<font class='headRows1'>Store Status</font>" ColSpan="5" /> <ext:HeaderGroupColumn Align="Center" /> </Columns> </ext:HeaderGroupRow> </HeaderGroupRows> <HeaderGroupRows> <ext:HeaderGroupRow> <Columns> <ext:HeaderGroupColumn Align="Center" Header="<font class='headRows2'>Year/Month</font>" /> <ext:HeaderGroupColumn Align="Center" Header="<font class='headRows2'>Target</font>" ColSpan="5" /> <ext:HeaderGroupColumn Align="Center" Header="<font class='headRows2'>Actual Store opened</font>" ColSpan="6" /> <ext:HeaderGroupColumn Align="Center" Header="<font class='headRows2'>Contract Signed</font>" ColSpan="3" /> <ext:HeaderGroupColumn Align="Center" Header="<font class='headRows2'>Under Deco</font>" ColSpan="3" /> <ext:HeaderGroupColumn Align="Center" ColSpan="4" /> <ext:HeaderGroupColumn Align="Center" Header="<font class='headRows2'>Drop-Out</font>" ColSpan="3" /> <ext:HeaderGroupColumn Align="Center" /> <ext:HeaderGroupColumn Align="Center" Header="<font class='headRows2'>Store No.</font>" ColSpan="4" /> <ext:HeaderGroupColumn Align="Center" /> </Columns> </ext:HeaderGroupRow> </HeaderGroupRows> </ext:GroupingView> </View> <TopBar> <ext:Toolbar ID="Toolbar1" runat="server"> <Items> <ext:ToolbarSpacer Width="10" runat="server" /> <ext:NumberField runat="server" LabelWidth="74" ID="txtYear" Width="162" MinLength="4" MinLengthText="输入的年份必须为四位数!" MaxLength="4" FieldLabel="请输入年份" /> <ext:ToolbarSpacer ID="ToolbarSpacer1" Width="10" runat="server" /> <ext:ComboBox ID="cboMonth" LabelWidth="74" EmptyText="请选择月份!" FieldLabel="请选择月份" Editable="false" runat="server"> <Items> <ext:ListItem Text="01" Value="1" /> <ext:ListItem Text="02" Value="2" /> <ext:ListItem Text="03" Value="3" /> <ext:ListItem Text="04" Value="4" /> <ext:ListItem Text="05" Value="5" /> <ext:ListItem Text="06" Value="6" /> <ext:ListItem Text="07" Value="7" /> <ext:ListItem Text="08" Value="8" /> <ext:ListItem Text="09" Value="9" /> <ext:ListItem Text="10" Value="10" /> <ext:ListItem Text="11" Value="11" /> <ext:ListItem Text="12" Value="12" /> <ext:ListItem Text="ALL" Value=" " /> </Items> </ext:ComboBox> <ext:ToolbarSpacer ID="ToolbarSpacer2" Width="10" runat="server" /> <ext:Button ID="btnSearch" runat="server" Text="搜索" Icon="PageRefresh"> <Listeners> <Click Handler="if(#{txtYear}.getValue()==''){Ext.MessageBox.alert('温馨提示', '请输入年份!');}else{#{Store1}.reload();#{GridPanel1}.getColumnModel().setColumnHeader(0,#{txtYear}.getValue());}" /> </Listeners> </ext:Button> <ext:ToolbarFill runat="server" /> <ext:Button ID="btnExport" runat="server" Text="导出Excel" Icon="PageExcel"> <Listeners> <Click Handler=" var downLoadUrl='/FormServerTemplates/DownLoad.aspx?year='+#{txtYear}.getValue()+'&month='+#{cboMonth}.getValue(); try { window.open(downLoadUrl,'_newtab'); }catch(e) { window.lcation.href=downLoadUrl; } " /> </Listeners> </ext:Button> </Items> </ext:Toolbar> </TopBar> </ext:GridPanel> </Items> </ext:Viewport>
然后只需要完善Httphandler类就好了。这个报表只是在列头的组合上稍微有点难度,其实也没难度,看我的代码,应该是很清晰的。
2)现在开始说第二个报表了。再看看图二:
这个报表难度其实也不大,主要有这么几个地方值得注意:
- 列头合并。前面以后说过了。很简单的配置。
- 列合计。待会看源码。
- 过滤掉0。如果是0,则什么都不显示,否则显示蓝色的数字。因为这个报表测试数据干了,我又懒,所以大家想象一下数据就好了。据说画饼充饥是有效果的,当然不是我说的。信不信由你,反正我是相信了。
- 注意列头的HTML编码。别把任意字符都往列头加,列头会表示有压力的,并且会导致页面空白而且无异常。所以注意把特殊字符进行编码。
这个报表虽然复杂了一点点,但是也很简单。现在一起来ViewCode:
<%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %> <ext:ResourceManager ID="ResourceManager1" runat="server" /> <style type="text/css"> .total-field { background-color: #fff; font-weight: bold !important; color: #000; padding: 2px; margin-right: 5px; } .headRows1 { color: Green; font-weight: bolder; } .headRows2 { color: Blue; font-weight: bolder; } .x-grid3-cell-inner { font-family: "segoe ui" ,tahoma, arial, sans-serif; } .x-grid-group-hd div { font-family: "segoe ui" ,tahoma, arial, sans-serif; } .x-grid3-hd-inner { font-family: "segoe ui" ,tahoma, arial, sans-serif; font-size: 12px; } .x-grid3-body .x-grid3-td-Cost { background-color: #f1f2f4; } .x-grid3-summary-row .x-grid3-td-Cost { background-color: #e1e2e4; } </style> <script type="text/javascript"> var template = '<b style="color:blue;">{0}</b>'; var fifterZero = function (value, metadata, record, rowIndex, colIndex, store) { if (value > 0) return String.format(template, value); else return ''; }; var updateTotal = function (grid) { var fbar = grid.getBottomToolbar(), column, field, width, data = {}, c, cs = grid.view.getColumnData(); for (var j = 0, jlen = grid.store.getCount(); j < jlen; j++) { var r = grid.store.getAt(j); for (var i = 0, len = cs.length; i < len; i++) { c = cs[i]; if (j == 0) data[c.name] = 0; if (c.name == "Region") data[c.name] = "总计:"; else data[c.name] += r.get(c.name); } } for (var i = 0; i < grid.getColumnModel().columns.length; i++) { column = grid.getColumnModel().columns[i]; if (column.dataIndex != grid.store.groupField) { field = fbar.findBy(function (item) { return item.dataIndex === column.dataIndex; })[0]; c = cs[i]; fbar.remove(field, false); fbar.insert(i, field); width = grid.getColumnModel().getColumnWidth(i); field.setWidth(width - 5); field.setValue((column.summaryRenderer || c.renderer)(data[c.name], {}, {}, 0, i, grid.store)); } } fbar.doLayout(); } </script> <ext:GridPanel ID="GridPanel1" AutoScroll="true" TrackMouseOver="true" runat="server" ColumnLines="true" StripeRows="true" AutoHeight="true" Title="Decoration Status" Icon="Bookmark"> <Store> <ext:Store ID="Store1" ShowWarningOnFailure="false" AutoLoad="true" runat="server"> <Reader> <ext:JsonReader> <Fields> <ext:RecordField Name="Region" /> <ext:RecordField Name="ncsnew" Type="Int" /> <ext:RecordField Name="h_bnew" Type="Int" /> <ext:RecordField Name="updatencs" Type="Int" /> <ext:RecordField Name="updateh_b" Type="Int" /> <ext:RecordField Name="ncsnewnext1" Type="Int" /> <ext:RecordField Name="h_bnewnext1" Type="Int" /> <ext:RecordField Name="updatencsnext1" Type="Int" /> <ext:RecordField Name="updateh_bnext1" Type="Int" /> <ext:RecordField Name="ncsnewnext2" Type="Int" /> <ext:RecordField Name="h_bnewnext2" Type="Int" /> <ext:RecordField Name="updatencsnext2" Type="Int" /> <ext:RecordField Name="updateh_bnext2" Type="Int" /> <ext:RecordField Name="ncsnewnext3" Type="Int" /> <ext:RecordField Name="h_bnewnext3" Type="Int" /> <ext:RecordField Name="updatencsnext3" Type="Int" /> <ext:RecordField Name="updateh_bnext3" Type="Int" /> <ext:RecordField Name="ncsnewCertificated" Type="Int" /> <ext:RecordField Name="h_bnewCertificated" Type="Int" /> <ext:RecordField Name="updatencsCertificated" Type="Int" /> <ext:RecordField Name="updateh_bCertificated" Type="Int" /> </Fields> </ext:JsonReader> </Reader> </ext:Store> </Store> <LoadMask ShowMask="true" /> <ColumnModel ID="ctl120"> <Columns> <ext:Column DataIndex="Region" Header="Region" /> <ext:Column DataIndex="ncsnew" Header="New NCS"> <Renderer Fn="fifterZero" Args="value, metadata, record, rowIndex, colIndex, store" /> </ext:Column> <ext:Column DataIndex="h_bnew" Header="New H&B"> <Renderer Fn="fifterZero" Args="value, metadata, record, rowIndex, colIndex, store" /> </ext:Column> <ext:Column DataIndex="updatencs" Header="Upgrading NCS"> <Renderer Fn="fifterZero" Args="value, metadata, record, rowIndex, colIndex, store" /> </ext:Column> <ext:Column DataIndex="updateh_b" Header="Upgrading H&B"> <Renderer Fn="fifterZero" Args="value, metadata, record, rowIndex, colIndex, store" /> </ext:Column> <ext:Column DataIndex="ncsnewnext1" Header="New NCS"> <Renderer Fn="fifterZero" Args="value, metadata, record, rowIndex, colIndex, store" /> </ext:Column> <ext:Column DataIndex="h_bnewnext1" Header="New H&B"> <Renderer Fn="fifterZero" Args="value, metadata, record, rowIndex, colIndex, store" /> </ext:Column> <ext:Column DataIndex="updatencsnext1" Header="Upgrading NCS"> <Renderer Fn="fifterZero" Args="value, metadata, record, rowIndex, colIndex, store" /> </ext:Column> <ext:Column DataIndex="updateh_bnext1" Header="Upgrading H&B"> <Renderer Fn="fifterZero" Args="value, metadata, record, rowIndex, colIndex, store" /> </ext:Column> <ext:Column DataIndex="ncsnewnext2" Header="New NCS"> <Renderer Fn="fifterZero" Args="value, metadata, record, rowIndex, colIndex, store" /> </ext:Column> <ext:Column DataIndex="h_bnewnext2" Header="New H&B"> <Renderer Fn="fifterZero" Args="value, metadata, record, rowIndex, colIndex, store" /> </ext:Column> <ext:Column DataIndex="updatencsnext2" Header="Upgrading NCS"> <Renderer Fn="fifterZero" Args="value, metadata, record, rowIndex, colIndex, store" /> </ext:Column> <ext:Column DataIndex="updateh_bnext2" Header="Upgrading H&B"> <Renderer Fn="fifterZero" Args="value, metadata, record, rowIndex, colIndex, store" /> </ext:Column> <ext:Column DataIndex="ncsnewnext3" Header="New NCS"> <Renderer Fn="fifterZero" Args="value, metadata, record, rowIndex, colIndex, store" /> </ext:Column> <ext:Column DataIndex="h_bnewnext3" Header="New H&B"> <Renderer Fn="fifterZero" Args="value, metadata, record, rowIndex, colIndex, store" /> </ext:Column> <ext:Column DataIndex="updatencsnext3" Header="Upgrading NCS"> <Renderer Fn="fifterZero" Args="value, metadata, record, rowIndex, colIndex, store" /> </ext:Column> <ext:Column DataIndex="updateh_bnext3" Header="Upgrading H&B"> <Renderer Fn="fifterZero" Args="value, metadata, record, rowIndex, colIndex, store" /> </ext:Column> <ext:Column DataIndex="ncsnewCertificated" Header="New NCS"> <Renderer Fn="fifterZero" Args="value, metadata, record, rowIndex, colIndex, store" /> </ext:Column> <ext:Column DataIndex="h_bnewCertificated" Header="New H&B"> <Renderer Fn="fifterZero" Args="value, metadata, record, rowIndex, colIndex, store" /> </ext:Column> <ext:Column DataIndex="updatencsCertificated" Header="Upgrading NCS"> <Renderer Fn="fifterZero" Args="value, metadata, record, rowIndex, colIndex, store" /> </ext:Column> <ext:Column DataIndex="updateh_bCertificated" Header="Upgrading H&B"> <Renderer Fn="fifterZero" Args="value, metadata, record, rowIndex, colIndex, store" /> </ext:Column> </Columns> </ColumnModel> <Listeners> <ColumnResize Handler="updateTotal(this);" /> <AfterRender Handler="updateTotal(this);" Delay="100" /> </Listeners> <View> <ext:GroupingView ID="gvColumns" runat="server" /> </View> <BottomBar> <ext:Toolbar ID="Toolbar1" runat="server"> <Items> <ext:DisplayField ID="DisplayField1" runat="server" Cls="total-field" Text="-" DataIndex="Region" /> <ext:DisplayField ID="DisplayField2" runat="server" Cls="total-field" Text="-" DataIndex="ncsnew" /> <ext:DisplayField ID="DisplayField3" runat="server" Cls="total-field" Text="-" DataIndex="h_bnew" /> <ext:DisplayField ID="DisplayField4" runat="server" Cls="total-field" Text="-" DataIndex="updatencs" /> <ext:DisplayField ID="DisplayField5" runat="server" Cls="total-field" Text="-" DataIndex="updateh_b" /> <ext:DisplayField ID="DisplayField6" runat="server" Cls="total-field" Text="-" DataIndex="ncsnewnext1" /> <ext:DisplayField ID="DisplayField7" runat="server" Cls="total-field" Text="-" DataIndex="h_bnewnext1" /> <ext:DisplayField ID="DisplayField8" runat="server" Cls="total-field" Text="-" DataIndex="updatencsnext1" /> <ext:DisplayField ID="DisplayField9" runat="server" Cls="total-field" Text="-" DataIndex="updateh_bnext1" /> <ext:DisplayField ID="DisplayField10" runat="server" Cls="total-field" Text="-" DataIndex="ncsnewnext2" /> <ext:DisplayField ID="DisplayField11" runat="server" Cls="total-field" Text="-" DataIndex="h_bnewnext2" /> <ext:DisplayField ID="DisplayField12" runat="server" Cls="total-field" Text="-" DataIndex="updatencsnext2" /> <ext:DisplayField ID="DisplayField13" runat="server" Cls="total-field" Text="-" DataIndex="updateh_bnext2" /> <ext:DisplayField ID="DisplayField14" runat="server" Cls="total-field" Text="-" DataIndex="ncsnewnext3" /> <ext:DisplayField ID="DisplayField15" runat="server" Cls="total-field" Text="-" DataIndex="h_bnewnext3" /> <ext:DisplayField ID="DisplayField16" runat="server" Cls="total-field" Text="-" DataIndex="updatencsnext3" /> <ext:DisplayField ID="DisplayField17" runat="server" Cls="total-field" Text="-" DataIndex="updateh_bnext3" /> <ext:DisplayField ID="DisplayField18" runat="server" Cls="total-field" Text="-" DataIndex="ncsnewCertificated" /> <ext:DisplayField ID="DisplayField19" runat="server" Cls="total-field" Text="-" DataIndex="h_bnewCertificated" /> <ext:DisplayField ID="DisplayField20" runat="server" Cls="total-field" Text="-" DataIndex="updatencsCertificated" /> <ext:DisplayField ID="DisplayField21" runat="server" Cls="total-field" Text="-" DataIndex="updateh_bCertificated" /> </Items> </ext:Toolbar> </BottomBar> </ext:GridPanel>
该说的都说了,注释也懒得写了。现在想说的是下面几点:
- 首先来看记录集(RecordField)。注意字段的类型(Type="Int")。比如你的数据中有DateTime类型、Int类型的数据,最好设置下类型,这样的话,就可以避免出现undefined。而且也方便格式转换。
- Store。这个Store为什么没有设置URL呢?在《EXT.NET高效开发(一)——概述》我说过,“7)数据交换更简单”。应该是“数据交互”,本人比较懒,只在这里更正申明下好了,我也是刚看到。这里的Store,是在后台赋值的。如下面代码:
var qList = _db.SelectReportMonthDataForUnderDeco().ToList(); Store1.DataSource = qList; Store1.DataBind();
- 统计怎么算的?注意updateTotal函数。“总计”两个字是怎么加上去的,答曰:“敲上去的”。再注意BottomBar(想当然的,这就是底部工具条),这里就是显示统计的数据的。
- 估计看官会有这么一个疑问,列头分组怎么分的,木有见代码。代码是有的,只是还木有贴出来,因为我写在后台,这种方式也挺直观方便的。当然萝卜白菜各有所爱了:
var _headGroupRow = new HeaderGroupRow() { Columns = { new HeaderGroupColumn() { Header = "<font class='headRows1'></font>", Align = Alignment.Center, ColSpan = 1 } } }; _headGroupRow.Columns.Add(new HeaderGroupColumn() { Header = string.Format("<font class='headRows1'>{0}</font>", "Under Deco."), Align = Alignment.Center, ColSpan = 4, }); var _currentMonth = Convert.ToInt32(qList.First().monthnum.Trim()); for (int i = 0; i < 3; i++) { _headGroupRow.Columns.Add(new HeaderGroupColumn() { Header = string.Format("<font class='headRows1'>{0}</font>", GetEnglishMonth((_currentMonth + i).ToString())), Align = Alignment.Center, ColSpan = 4, }); } _headGroupRow.Columns.Add(new HeaderGroupColumn() { Header = string.Format("<font class='headRows1'>{0}</font>", "Certificated"), Align = Alignment.Center, ColSpan = 4, }); gvColumns.HeaderGroupRows.Add(_headGroupRow);
这个就说到这里了。
3)这个相对来说,比上两个都复杂。但是我画起来,比上两个都快。一个是更熟练了,第二个是生成了很多东西。
先看页面代码(页面代码很简洁):
<%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %> <style type="text/css"> .headRows1 { color: Green; font-weight: bolder; } .headRows2 { color: Purple; font-weight: bolder; } </style> <script type="text/javascript"> var template = '<b style="color:blue;">{0}</b>'; var fifterZero = function(value) { if (value > 0) return String.format(template, value); else return ''; }; function search() { if (ddlArea.getValue() != '' && ddlYear.getValue() != '' && ddlMonth.getValue() != '') { window.location.href = '<%=CurrentUrl %>' + "?newarea=" + escape(ddlArea.getValue()) + "&newyear=" + ddlYear.getValue() + "&newmonth=" + ddlMonth.getValue(); } else { alert("请选择区域-年份-月份!"); } } </script> <div style="margin-left:10px;"> <ext:ResourceManager ID="ResourceManager1" runat="server" /> <ext:FieldSet Collapsible="true" ID="Panel1" Border="true" Width="800" runat="server" Title="搜索条件" AutoHeight="true"> <Items> <ext:TableLayout ID="TableLayout1" runat="server" Columns="3"> <Cells> <ext:Cell> <ext:ComboBox ID="ddlArea" Width="235" IDMode="Static" FieldLabel="区域" Editable="false" runat="server" /> </ext:Cell> <ext:Cell> <ext:ComboBox ID="ddlYear" Width="235" IDMode="Static" FieldLabel="年份" Editable="false" runat="server" /> </ext:Cell> <ext:Cell> <ext:ComboBox ID="ddlMonth" Width="235" IDMode="Static" FieldLabel="月份" Editable="false" runat="server" /> </ext:Cell> </Cells> </ext:TableLayout> </Items> <BottomBar> <ext:Toolbar ID="tbSearch" runat="server"> <Items> <ext:Button ID="btnSearch" runat="server" Text="查询" Icon="ArrowRefresh" LabelAlign="Left" Type="Button" AutoPostBack="false"> <Listeners> <Click Handler="search();" /> </Listeners> </ext:Button> </Items> </ext:Toolbar> </BottomBar> </ext:FieldSet> <ext:GridPanel ID="GridPanel1" AutoScroll="true" TrackMouseOver="true" runat="server" ColumnLines="true" StripeRows="true" AutoHeight="true" Title="ShopStatus" Icon="Date"> <Store> <ext:Store ID="Store1" ShowWarningOnFailure="false" AutoLoad="true" runat="server" /> </Store> <LoadMask ShowMask="true" /> <ColumnModel ID="ctl120" /> <View> <ext:GroupingView ID="gvColumns" runat="server" /> </View> <BottomBar> <ext:Toolbar ID="Toolbar1" runat="server" Margins="0,0,0,0"> <Items> <ext:GridPanel ID="gpItems" AutoScroll="true" TrackMouseOver="true" runat="server" Margins="0,0,0,0" HideHeaders="true" ColumnLines="true" StripeRows="true" AutoHeight="true" Title="Jun" Icon="DateGo"> <Store> <ext:Store ID="storeItems" ShowWarningOnFailure="false" AutoLoad="true" runat="server" /> </Store> <LoadMask ShowMask="true" /> <ColumnModel /> </ext:GridPanel> </Items> </ext:Toolbar> </BottomBar> </ext:GridPanel> </div> <script type="text/javascript"> Ext.onReady(function() { $(function() { setTimeout("setLabelClass()", 300); }); }); function setLabelClass() { $("table.x-table-layout").attr("width", "100%"); } </script>
仔细看起来,发现这个页面代码并没啥东西。只能隐约的看到,一个GridPanel底部放了一个GridPanel。看来真不是个东西。这里暂不作解释,继续贴码:
/// <summary> /// 获取当前URL /// </summary> public string CurrentUrl { get { return Request.Path; } } protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { ResourceManager1.BuildAllPrivilegesForExtNET(); //注册JQuery脚本 this.Page.ClientScript.RegisterClientScriptInclude("JQuery4.4", "/js/jquery-1.4.4.min.js"); #region 绑定年月 for (int i = 0; i < 20; i++) { ddlYear.Items.Add(new ListItem(DateTime.Now.AddYears(-i).Year.ToString())); } for (int i = 1; i <= 12; i++) { ddlMonth.Items.Add(new ListItem(i.ToString())); } #endregion #region 绑定区域 using (var _db = new NBShopDataContext()) { var _lstArea = _db.SelectArea().ToList(); foreach (var areaResult in _lstArea) { ddlArea.Items.Add(new ListItem(areaResult.AreaName)); } ddlArea.Items.Add(new ListItem("全国")); } #endregion var _cm = new CommonService(); #region 获取搜索条件 var _month = string.IsNullOrEmpty(Request.QueryString["newmonth"]) ? (Request.QueryString["month"] ?? DateTime.Now.Month.ToString()) : Request.QueryString["newmonth"]; var _areaName = string.IsNullOrEmpty(Request.QueryString["newarea"]) ? (Request.QueryString["area"] ?? "全国") : Request.QueryString["newarea"]; var _year = string.IsNullOrEmpty(Request.QueryString["newyear"]) ? (Request.QueryString["year"] ?? DateTime.Now.Year.ToString()) : Request.QueryString["newyear"]; var _dic = new Dictionary<string, string>() { {"@areaname", _areaName}, {"@monthnum", _month}, {"@yearnum", _year} }; #endregion #region 选择相应的值 ddlArea.SelectedItem.Value = _areaName; ddlMonth.SelectedItem.Value = _month; ddlYear.SelectedItem.Value = _year; #endregion #region 如果不是全国,区域就无法选择 if (Request.QueryString["area"] != "全国") { ddlArea.Disabled = true; } #endregion #region 获取数据 DataTable _dt = _cm.SelectReportByStoredName("SelectMonthDataAndWeekData", _dic); if (_dt == null || _dt.Rows.Count == 0) { X.Msg.Alert("温馨提示", "没有数据可供显示!").Show(); GridPanel1.RemoveAll(); return; } #endregion #region 绑定数据 BingData(_dt.AsEnumerable().Where(p => p[0].ToString().IndexOf("-") == -1 && p[0].ToString() != "MTD" && p[0].ToString() != "Drop Out" && p[0].ToString() != "Net").AsDataView(), GridPanel1, Store1); BingData(_dt.AsEnumerable().Where(p => p[0].ToString().Contains("-") || p[0].ToString() == "MTD" || p[0].ToString() == "Drop Out" || p[0].ToString() == "Net").AsDataView(), gpItems, storeItems); #endregion GridPanel1.Header = false; //绑定子版块标题(当前月) gpItems.Title = GetEnglishMonth(_month); #region 设置列头 if (GridPanel1.ColumnModel.Columns.Count >= 17) { GridPanel1.ColumnModel.Columns[0].Header = _areaName; GridPanel1.ColumnModel.Columns[1].Header = "NCS"; GridPanel1.ColumnModel.Columns[2].Header = Server.HtmlEncode("H&B"); GridPanel1.ColumnModel.Columns[3].Header = Server.HtmlEncode("Others"); GridPanel1.ColumnModel.Columns[4].Header = Server.HtmlEncode("Total Franchise"); GridPanel1.ColumnModel.Columns[5].Header = Server.HtmlEncode("New Prospects / Application Completed"); GridPanel1.ColumnModel.Columns[6].Header = Server.HtmlEncode("Contract Approved/ No Deco."); GridPanel1.ColumnModel.Columns[7].Header = Server.HtmlEncode("Under Deco"); GridPanel1.ColumnModel.Columns[8].Header = Server.HtmlEncode("New Prospects / Application Completed"); GridPanel1.ColumnModel.Columns[9].Header = Server.HtmlEncode("Contract Approved/ No Deco."); GridPanel1.ColumnModel.Columns[10].Header = Server.HtmlEncode("Under Deco"); GridPanel1.ColumnModel.Columns[11].Header = Server.HtmlEncode("New Prospects / Application Completed"); GridPanel1.ColumnModel.Columns[12].Header = Server.HtmlEncode("Contract Approved/ No Deco."); GridPanel1.ColumnModel.Columns[13].Header = Server.HtmlEncode("Under Deco"); GridPanel1.ColumnModel.Columns[14].Header = Server.HtmlEncode("New Prospects / Application Completed"); GridPanel1.ColumnModel.Columns[15].Header = Server.HtmlEncode("Contract Approved/ No Deco."); GridPanel1.ColumnModel.Columns[16].Header = Server.HtmlEncode("Under Deco"); GridPanel1.ColumnModel.Columns[17].Header = Server.HtmlEncode("New NCS"); GridPanel1.ColumnModel.Columns[18].Header = Server.HtmlEncode("New H&B"); GridPanel1.ColumnModel.Columns[19].Header = Server.HtmlEncode("Upgrading"); GridPanel1.ColumnModel.Columns[20].Header = Server.HtmlEncode("Upgrading H&B"); } #endregion #region 设置合并的列头 var _headGroupRow = new HeaderGroupRow() { Columns = { new HeaderGroupColumn() { Header = "<font class='headRows1'></font>", Align = Alignment.Center, ColSpan = 1 } } }; _headGroupRow.Columns.Add(new HeaderGroupColumn() { Header = string.Format("<font class='headRows1'>{0}</font>", "In operation"), Align = Alignment.Center, ColSpan = 4, }); _headGroupRow.Columns.Add(new HeaderGroupColumn() { Header = string.Format("<font class='headRows2'>{0}</font>", "New NCS"), Align = Alignment.Center, ColSpan = 3, }); _headGroupRow.Columns.Add(new HeaderGroupColumn() { Header = string.Format("<font class='headRows2'>{0}</font>", Server.HtmlEncode("New H&B")), Align = Alignment.Center, ColSpan = 3, }); _headGroupRow.Columns.Add(new HeaderGroupColumn() { Header = string.Format("<font class='headRows2'>{0}</font>", "Upgrades--NCS"), Align = Alignment.Center, ColSpan = 3, }); _headGroupRow.Columns.Add(new HeaderGroupColumn() { Header = string.Format("<font class='headRows2'>{0}</font>", Server.HtmlEncode("Upgrades--H&B")), Align = Alignment.Center, ColSpan = 3, }); _headGroupRow.Columns.Add(new HeaderGroupColumn() { Header = string.Format("<font class='headRows1'>{0}</font>", "Certificated"), Align = Alignment.Center, ColSpan = 4, }); gvColumns.HeaderGroupRows.Add(_headGroupRow); #endregion _dt.Dispose(); } } /// <summary> /// 生成字段和列,并绑定数据源 /// </summary> /// <param name="_rptData"></param> /// <param name="_gp"></param> /// <param name="_store"></param> private void BingData(System.Data.DataView _rptData, GridPanel _gp, Store _store) { var _jsonReader = new JsonReader(); foreach (DataColumn _dataColumn in _rptData.Table.Columns) { //创建字段 if (_dataColumn.ColumnName == "timecol") { _jsonReader.Fields.Add(new RecordField(_dataColumn.ColumnName)); } else { _jsonReader.Fields.Add(new RecordField(_dataColumn.ColumnName)); } //创建列 var _column = new Column { Header = _dataColumn.ColumnName, DataIndex = _dataColumn.ColumnName, }; //过滤0,调用fifterZero函数 if (_column.Header != "timecol") { _column.Renderer.Fn = "fifterZero"; _column.Renderer.Args = new string[] { "value" }; } _gp.ColumnModel.Columns.Add(_column); } _store.Reader.Add(_jsonReader); _store.DataSource = _rptData; _store.DataBind(); }
代码贴上去了,发现木有,也不是很多,这里我顺便解释解释:
-
点击【查询】按钮后,刷新页面获取数据。当然您也可以改成不刷新的,也很简单的,这里我是为了更简单。
不过在这方面,我要说一下:你可以使用X.IsAjaxRequest来判断是否是EXT的Ajax请求,别重复执行了Page_load事件里面的代码。
-
数据源是直接绑的,使用的是DataTable。然后在绑定的时候,使用LINQ to DataTable进行了过滤。这个报表不会有多少数据。
当然如果你喜欢2.0的话,也可以用那个Select啊,DataView的RowFilter等来过滤。
-
数据集、字段、列是动态加的,列头是手动写的。因为列头不一样,而且有特殊字符。也就是说,如果可以,你完全可以动态生成整个GridPanel。
-
最后说点。Extjs与JQuery框架是不冲突的,井水不犯河水。
封装点函数,整个动态生成,也是一种高效的开发,这也是我EXT.NET高效开发系列所推崇的(EXT.NET高效开发(二)——封装函数)。
也许有人会说点性能问题什么的,我个人认为,生活总是有所取舍的,至于如何取舍,就需要根据个人的环境来判断了,不要捡了芝麻丢了西瓜就行了。
再套用一句,勿以BUG小而为之,勿以Code小而不为。
总算写完了。有时间的话,我会继续…