网上已经存在很多从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个字节,所以就是用了字节长度。
最后,导出的效果如下图所示:
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最后导出的效果如下图所示:
时间不早了,希望园子里的朋友能给出更好的解决方案,谢谢了!
作者:田念明
出处:http://www.cnblogs.com/nianming/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
分享到: QQ空间 新浪微博 人人网 开心网 更多
从DataSet导出Txt
TAG: