• ExtAspNet应用技巧(十) Grid导出为Excel文件(续)



    轻车熟路
    书接上文,如何在使用ExtAspNet控件库的页面将Grid内容导出为Excel文件?

    1. 页面声明
        <ext:PageManager ID="PageManager1" runat="server" />
        Grid Control in ExtAspNet:
        <ext:Grid ID="Grid1" Title="表格" ShowBorder="true" ShowHeader="true" Width="900px"
            AutoHeight="true" runat="server" EnableCheckBoxSelect="true" DataKeyNames="Id,Year,MyText"
            EnableRowNumber="True">
            <Columns>
                <ext:BoundField DataTooltipField="MyText" Width="200px" DataField="MyText" DataFormatString="{0}"
                    HeaderText="MyText" ExpandUnusedSpace="True" />
                <ext:BoundField ColumnId="column1" Width="100px" DataField="MyValue" HeaderText="MyValue" />
                <ext:BoundField Width="60px" DataField="Year" HeaderText="Year" />
                <ext:CheckBoxField DataTooltipField="MyText" Width="60px" RenderAsStaticField="true"
                    DataField="MyCheckBox" HeaderText="CheckBox" />
                <ext:HyperLinkField DataTooltipField="MyText" Width="200px" HeaderText="HyperLink"
                    DataTextField="MyText" DataTextFormatString="{0}" DataNavigateUrlFields="Id,MyValue"
                    DataNavigateUrlFormatString="http://www.google.com/?id={0}&page={1}" Target="_blank"
                    NavigateUrl="~/alert.aspx" Text="链接" />
                <ext:TemplateField HeaderText="TemplateField">
                    <ItemTemplate>
                        <%# GetMyValue(DataBinder.Eval(Container.DataItem, "[MyValue]")) %>
                    </ItemTemplate>
                </ext:TemplateField>
                <ext:ImageField DataTooltipField="MyText" Width="60px" DataImageUrlField="MyValue"
                    DataImageUrlFormatString="~/images/16/{0}.gif" HeaderText="Image"></ext:ImageField>
            </Columns>
        </ext:Grid>
        <br />
        <ext:Button ID="Button1" EnableAjax="false" 
            runat="server" Text="导出ExtAspNet控件Grid到Excel文件" OnClick="Button1_Click">
        </ext:Button>
        

    这里需要说明一点:因为点击“导出”按钮会改变响应消息头,使用AJAX就不合适了。所以我们设置Button的EnableAjax="false",当然你也可以设置PageManager的这个属性,那会影响整个页面。

    2. 后台数据绑定。这个同样省略,无非是从数据库读出一个DataTable或者List绑定到Grid控件。

    3. 生成的页面: 


    4. 点击导出按钮的事件处理
        protected void Button1_Click(object sender, EventArgs e)
        {
            Response.ClearContent();
            Response.AddHeader("content-disposition", "attachment; filename=MyExcelFile.xls");
            Response.ContentType = "application/excel";
            StringWriter sw = new StringWriter();
            HtmlTextWriter htw = new HtmlTextWriter(sw);
            Grid1.RenderControl(htw);
            Response.Write(sw.ToString());
            Response.End();
        }
        


    5. 生成的MyExcelFile.xls文件(用记事本打开):
        <div id="Grid1_wrapper" style="display:inline;"></div>
        




    问题出现

    如果你理解Extjs的工作原理的话,这个结果并不奇怪。
    Grid渲染到页面中的只有一个简单的DIV标签,至于内部的所有的内容都是通过JavaScript来生成的,这个JavaScript就隐藏在页面的底部,如果你观察过ExtAspNet生成的页面的话,你能看到类似的Grid初始化代码: 


    看来对于使用extjs的ExtAspNet控件而言,我们不能照搬Asp.Net中的GridView的模式,我们需要...



    另辟蹊径

    仔细观察Button1_Click事件处理函数,它做的事情很简单 - 向输出流写入一个字符串,这个字符串就是一个HTML的表格。那我们何不手工来生成这个表格?

    不用怕,问题没有你想的那么复杂:
        protected void Button1_Click(object sender, EventArgs e)
        {
            Response.ClearContent();
            Response.AddHeader("content-disposition", "attachment; filename=MyExcelFile.xls");
            Response.ContentType = "application/excel";
            Response.Write(GetGridTableHtml(Grid1));
            Response.End();
        }
        private string GetGridTableHtml(Grid grid)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("<table cellspacing=\"0\" rules=\"all\" border=\"1\" style=\"border-collapse:collapse;\">");
            sb.Append("<tr>");
            foreach (GridColumn column in grid.Columns)
            {
                sb.AppendFormat("<td>{0}</td>", column.HeaderText);
            }
            sb.Append("</tr>");
    
            foreach (GridRow row in grid.Rows)
            {
                sb.Append("<tr>");
                foreach (object value in row.Values)
                {
                    string html = value.ToString();
                    sb.AppendFormat("<td>{0}</td>", html);
                }
                sb.Append("</tr>");
            }
            sb.Append("</table>");
            return sb.ToString();
        }
        


    不就是生成一个HTML的表格嘛,这个事情我做过无数次了,拍拍手来看下成果: 




    继续优化

    还是两个地方不满意,我们看下CheckBox的那个地方生成的HTML代码:
        <!-- 选中的CheckBox -->
        <div ext:qtip="item2" class="box-grid-static-checkbox">
        </div>
        <!-- 没有选中的CheckBox -->
        <div ext:qtip="item3,我是一个很厉害的程序员。" class="box-grid-static-checkbox box-grid-static-checkbox-uncheck">
        </div>
        

    可见这里并没有像Asp.Net的GridView那样生成 input type="checkbox" 的标签,而是通过CSS样式来控制是否选中(说白了就是不同的背景图片)。

    有了这些认识后,优化也很简单:

        private string GetGridTableHtml(Grid grid)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("<table cellspacing=\"0\" rules=\"all\" border=\"1\" style=\"border-collapse:collapse;\">");
            sb.Append("<tr>");
            foreach (GridColumn column in grid.Columns)
            {
                sb.AppendFormat("<td>{0}</td>", column.HeaderText);
            }
            sb.Append("</tr>");
    
            foreach (GridRow row in grid.Rows)
            {
                sb.Append("<tr>");
                foreach (object value in row.Values)
                {
                    string html = value.ToString();
                    // 处理CheckBox
                    if (html.Contains("box-grid-static-checkbox"))
                    {
                        if (html.Contains("box-grid-static-checkbox-uncheck"))
                        {
                            html = "×";
                        }
                        else
                        {
                            html = "√";
                        }
                    }
                    // 处理图片
                    if (html.Contains("<img"))
                    {
                        html = html.Replace("src=\"/extaspnet/", "src=\"http://localhost/extaspnet/");
                    }
                    sb.AppendFormat("<td>{0}</td>", html);
                }
                sb.Append("</tr>");
            }
            sb.Append("</table>");
            return sb.ToString();
        }
        


    再来看下生成的XLS文件,这已经是我们想要的结果了。 



    修正一个小BUG

    还有一个小问题,就是在导出文件之后,按钮不可点击了,如下所示: 


    其实这是ExtAspNet的一个内置特性,是为了防止重复点击同一个按钮两次。一般情况下在AJAX之后系统会自动让此按钮可点击(非AJAX页面会刷新)。

    但是这里有点特殊,导出Excel文件并没有导致页面刷新,所以我们需要给Button设置一个属性,使其在点击时不要变灰。
        <ext:Button ID="Button1" EnableAjax="false" DisableControlBeforePostBack="false"
            runat="server" Text="导出ExtAspNet控件Grid到Excel文件" OnClick="Button1_Click">
        </ext:Button>
        



    全部源代码可以从这里下载,在文件夹data\grid_excel_run.aspx中。
    注意:如果想运行本章中提到的程序,ExtAspNet版本需大于v2.0.6。
  • 相关阅读:
    阻止事件传播的常用方法
    原生JS获取元素的位置与尺寸
    FileReader 与canvas结合使用显示图片
    dot.js使用心得
    时间格式转换
    JS对象操作
    vue-awesome-swipe 基于vue使用的轮播组件 使用(改)
    vscode 插件推荐
    chrome 发送请求出现:Provisional headers are shown 提示
    手机端
  • 原文地址:https://www.cnblogs.com/sanshi/p/1552804.html
Copyright © 2020-2023  润新知