zoukankan      html  css  js  c++  java
  • 从DataSet导出Txt

    网上已经存在很多从DataSet导出到Word、Excel、Txt等的文章了,为什么还要写这篇文章呢,因为搜索了好长时间都没有找到符合要求的(不代表没有),只好自己动手写一个。后面我还遇到了问题,希望园子里的朋友帮忙解决一下,看有没有更好的办法。

    在这篇文章中,我涉及两个导出的问题。第一个问题是导出的每一列根据这一列的长度自动分配宽度,这样说还是不够明了,下面通过例子来看。

    首先,构造我们的DataSet。本来想从数据库中查询得到,这样虽然麻烦点,但是更直接。

    DataSet ds = new DataSet();
    DataTable table = new DataTable();
    DataColumn[] columns = new DataColumn[7];
    columns[0] = new DataColumn("EmpNo");
    columns[1] = new DataColumn("EmpName");
    columns[2] = new DataColumn("Dept");
    columns[3] = new DataColumn("Post");
    columns[4] = new DataColumn("Salary");
    columns[5] = new DataColumn("Bank");
    columns[6] = new DataColumn("BankNo");
    table.Columns.AddRange(columns);
    DataRow row1 = table.NewRow();
    row1["EmpNo"] = "1001";
    row1["EmpName"] = "刘德华";
    row1["Dept"] = "办公室";
    row1["Post"] = "总经理";
    row1["Salary"] = 6000;
    row1["Bank"] = "建设银行";
    row1["BankNo"] = "5475694879437594";
    DataRow row2 = table.NewRow();
    row2["EmpNo"] = "1002";
    row2["EmpName"] = "周迅";
    row2["Dept"] = "财务";
    row2["Post"] = "出纳";
    row2["Salary"] = 4000;
    row2["Bank"] = "建设银行";
    row2["BankNo"] = "5475695489548395";
    DataRow row3 = table.NewRow();
    row3["EmpNo"] = "1003";
    row3["EmpName"] = "abc";
    row3["Dept"] = "信息部";
    row3["Post"] = "程序员";
    row3["Salary"] = 5000;
    row3["Bank"] = "建设银行";
    row3["BankNo"] = "5475763489548395";
    table.Rows.Add(row1);
    table.Rows.Add(row2);
    table.Rows.Add(row3);
    ds.Tables.Add(table);

    在上面的代码中有三条数据。

    第二,写导出的方法。

    /// <summary>
    /// DataSet导出为Txt
    /// </summary>
    /// <param name="ds"></param>
    /// <param name="fileName">导出txt文件名</param>
    /// <param name="page"></param>
    public static void ToTxt(DataSet ds, string fileName, Page page)
    {
        StringBuilder sb = new StringBuilder();
        DataTable table = ds.Tables[0];
        DataRowCollection rows = table.Rows;
        DataColumnCollection columns = table.Columns;
        //行数
        int rowCount = rows.Count;
        //列数
        int columnCount = columns.Count;
        //每列的最大长度
        int[] columnMaxLength = new int[columnCount];
    
        //遍历所有的记录获得每列的最大长度
        for (int i = 0; i < columnCount; i++)
        {
            int[] tmps = new int[rowCount];
            for (int j = 0; j < rowCount; j++)
            {
                tmps[j] = System.Text.Encoding.Default.GetByteCount(rows[j][i].ToString());
            }
            columnMaxLength[i] = ArrayMaxValue(tmps);
        }
        //将上面取的最大长度与列名比较
        for (int i = 0; i < columnCount; i++)
        {
            if (columnMaxLength[i] < System.Text.Encoding.Default.GetByteCount(columns[i].ColumnName))
            {
                columnMaxLength[i] = System.Text.Encoding.Default.GetByteCount(columns[i].ColumnName);
            }
        }
        //将列名附加到字符串
        for (int i = 0; i < columnCount; i++)
        {
            int a = columnMaxLength[i] - System.Text.Encoding.Default.GetByteCount(columns[i].ColumnName);
            StringBuilder sb1 = new StringBuilder(a);
            //每列之间间隔3
            for (int j = 0; j < a + 3; j++)
            {
                sb1.Append(" ");
            }
            sb.Append(columns[i].ColumnName).Append(sb1.ToString());
        }
        sb.AppendLine();
        sb.AppendLine();
    
        //将记录附加到字符串
        for (int i = 0; i < rowCount; i++)
        {
            for (int j = 0; j < columnCount; j++)
            {
                int a = columnMaxLength[j] - System.Text.Encoding.Default.GetByteCount(rows[i][j].ToString());
                StringBuilder sb1 = new StringBuilder(a);
                for (int k = 0; k < a + 3; k++)
                {
                    sb1.Append(" ");
                }
    
                sb.Append(rows[i][j]).Append(sb1.ToString());
            }
            sb.AppendLine();
        }
    
        HttpContext.Current.Response.Clear();
        HttpContext.Current.Response.Buffer = false;
        HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.UTF8;
        HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment;filename=" + HttpContext.Current.Server.HtmlEncode(fileName) + ".txt");
        HttpContext.Current.Response.ContentType = "text/plain";
        page.EnableViewState = false;
        HttpContext.Current.Response.Write(sb.ToString());
        HttpContext.Current.Response.End();
    }
    
    /// <summary>
    /// 取数组的最大值
    /// </summary>
    /// <param name="arr"></param>
    /// <returns></returns>
    private static int ArrayMaxValue(int[] arr)
    {
        int maxInt = arr[0];
        for (int i = 0; i < arr.Length; i++)
        {
            if (arr[i] > maxInt)
            {
                maxInt = arr[i];
            }
        }
        return maxInt;
    }

    在上面的方法中,应该可以改正减少很多代码,如果感兴趣的朋友可以修改。方法中,我使用的是字符串的字节长度,而不是字符串的长度,如果使用字符串长度,一个英文字母和一个汉字的长度都是1,显然汉字要宽。我发现一个汉字的宽度和2个英文字母的宽度差不多(看着差不多),一个汉字又等于2个字节,所以就是用了字节长度。

    最后,导出的效果如下图所示:

    QQ截图20120105235429

    public static void ToTxt(DataSet ds, string fileName, Page page)
    {
        StringBuilder sb = new StringBuilder();
        DataTable table = ds.Tables[0];
        DataRowCollection rows = table.Rows;
        DataColumnCollection columns = table.Columns;
        int rowCount = rows.Count;
        int columnCount = columns.Count;
    
        int k = 1;
        for (int i = 0; i < rows.Count; i++)
        {
            decimal factSalary = Convert.ToDecimal(rows[i]["FactSalary"]);
            int a = (int)(factSalary - factSalary % 5000) / 5000;
            if (a > 0)
            {
                for (int j = 0; j < a; j++)
                {
                    sb.Append(i + k + j).Append(",");
                    sb.Append(rows[i]["BankNo"].ToString()).Append(",");
                    sb.Append(rows[i]["EmpName"].ToString()).Append(",");
                    sb.Append(5000).Append(",");
                    sb.Append("公务报销");
                    sb.AppendLine();
                }
                k += a;
                sb.Append(i + k).Append(",");
                sb.Append(rows[i]["BankNo"].ToString()).Append(",");
                sb.Append(rows[i]["EmpName"].ToString()).Append(",");
                sb.Append(factSalary % 5000).Append(",");
                sb.Append("公务报销");
                sb.AppendLine();
            }
            else
            {
                sb.Append(i + k).Append(",");
                sb.Append(rows[i]["BankNo"].ToString()).Append(",");
                sb.Append(rows[i]["EmpName"].ToString()).Append(",");
                sb.Append(rows[i]["FactSalary"]).Append(",");
                sb.Append("公务报销");
                sb.AppendLine();
            }
        }
        HttpContext.Current.Response.Clear();
        HttpContext.Current.Response.Buffer = false;
        HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.UTF8;
        HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment;filename=" + HttpContext.Current.Server.HtmlEncode(fileName) + ".txt");
        HttpContext.Current.Response.ContentType = "text/plain";
        page.EnableViewState = false;
        HttpContext.Current.Response.Write(sb.ToString());
        HttpContext.Current.Response.End();
    }

    第二个问题就是导出的每个TXT中,总的金额不能超过10万,单笔不能超过5000,如果超过5000,就要进行拆分。

    我写了一个方法实现了单笔超过5000的进行拆分,但是一个TXT中总金额不超过10万,还没有写,一种解决方案就是先创建一个文件,将不超过10万的导入到这个文件中,然后再创建一个文件,继续导入到这个文件中,如此,直到导出完成。

    稍微修改上面的DataSet数据,金额分别修改为6000,5001,10001最后导出的效果如下图所示:

    QQ截图20120106001544 

    时间不早了,希望园子里的朋友能给出更好的解决方案,谢谢了!

  • 相关阅读:
    绝对有效 IntelliJ IDEA2019.2下载、安装及破解教程
    SpringBoot 打包成war包,部署到tomcat
    Spring Boot 项目实战(一)Maven 多模块项目搭建
    ImportBeanDefinitionRegistrar接口实现bean动态注入
    FactoryBean的实现原理与作用
    ClassPathBeanDefinitionScanner 说明
    InstantiationAwareBeanPostProcessor 分析
    Google Guava Cache 全解析
    二十三、并发编程之深入解析Condition源码
    InheritableThreadLocal详解
  • 原文地址:https://www.cnblogs.com/nianming/p/2313837.html
Copyright © 2011-2022 走看看