• 多表导出csv功能


      最近公司需求做一个直接根据数据库表导出csv的功能,要求可以多个表同时导入到一个csv文件里,通过查阅相关资料后,终于实现了该功能,期间也遇到过一些问题在此总结一二。

      首先为了要获得数据库的表数据,写了一个通用方法,代码如下:

     1  public static DataSet GetTableAll(List<string> tableAll)
     2         {
     3            
     4             using (SqlConnection conn = new SqlConnection(connectionString))
     5             {
     6                 DataSet ds = new DataSet();
     7                 foreach (string table in tableAll)
     8                 {
     9                     DataTable dt = new DataTable();  
    10                     using (SqlDataAdapter da = new SqlDataAdapter("Select * from  " + table, conn))
    11                     {
    12                         da.Fill(dt);
    13                     }
    14                     ds.Tables.Add(dt);
    15                 }
    16                 return ds;
    17             }
    18         }

    返回的是一个ds集合,参数用的是List集合,这样就可以返回需要导出的表的集合。调用方法代码如下:

                List<string> tableAll = new List<string>();
                tableAll.Add("tableName");
                tableAll.Add("tableName");
                DataSet tableName = CommonClass.GetTableAll(tableAll);    
           CSVUtility.GetCSV(tableName, this.Page, 文件名);

    代码比较简单就不在赘述了。最后就是最重要的导出方法了,代码如下:

     public static void GetCSV(DataSet data, Page page,String fileName)
            {
                MemoryStream stream = new MemoryStream();
                foreach (DataTable dt in data.Tables)
                {
                    string[] filedsToExport = new string[dt.Columns.Count];
                    for (int i = 0; i < dt.Columns.Count; i++)
                    {
                        filedsToExport[i] = dt.Columns[i].ColumnName;
    
                    }
                    GetCSV(filedsToExport, dt, stream);
    
                }
                page.Response.ContentType = "application/csv";
                page.Response.Clear();
                page.Response.Buffer = true;
                page.Response.ContentEncoding = Encoding.UTF8;
                page.Response.Charset = "UTF-8";
                page.Response.AddHeader("Content-Disposition", "attachment;filename=" + fileName);
                page.Response.Cache.SetCacheability(HttpCacheability.NoCache);
               //防止中文乱码
                page.Response.BinaryWrite(new byte[] { 0xEF, 0xBB, 0xBF });
                page.Response.BinaryWrite(stream.ToArray());
                page.Response.Flush();
                page.Response.End();
            }

    上面方法也比较简单,就是注释下面那行代码必须加上,否则会出现中文乱码现象,因为csv是纯文本文件,有个BOM方式编码问题。在上面方法中还调用了一个方法,通过MemoryStream对象流把数据写入了内存,具体代码如下:

     private static void GetCSV(string[] filedsToExport, DataTable data, MemoryStream stream)
            {
                using (var sw = new StreamWriterX(stream, false))
                {
                    for (int i = 0; i < filedsToExport.Length; i++)
                    {
                        if (i != 0)
                        {
                            sw.Write(",");
                        }
                        sw.Write("\"");
                        sw.Write(filedsToExport[i].Replace("\"", "\"\""));
                        sw.Write("\"");
                    }
                    sw.Write("\n");
    
                    foreach (DataRow row in data.Rows)
                    {
                        for (int i = 0; i < filedsToExport.Length; i++)
                        {
                            if (i != 0)
                            {
                                sw.Write(",");
                            }
                            sw.Write("\"");
                            sw.Write(row[filedsToExport[i]].ToString()
                                .Replace("\"", "\"\""));
                            sw.Write("\"");
                        }
    
                        sw.Write("\n");
    
                    }
                    sw.WriteLine("****************************The End********************************");
                }
    
            }
    
    
            //防止Writer关闭的时候自动关闭数据流
            class StreamWriterX : StreamWriter
            {
                public StreamWriterX(Stream stream, Boolean closeable)
                    : base(stream)
                {
                    var fi = typeof(StreamWriter).GetField("closable", BindingFlags.Instance | BindingFlags.NonPublic);
                    if (fi != null) fi.SetValue(this, closeable);
                }
            }

    上面这个方法其实有几个地方需要讲述下,第一个就是write的时候要注意csv转换格式的问题,我在末尾的时候加了一个WriteLine,因为多个表数据写入到同一个csv的时候,需要区分表与数据字段(暂时需求),比较重要的是SreamWriterX这个类,因为在Writer关闭的时候会自动关闭数据流,导致程序出错。这个问题折腾了好久,最后通过高人指导才算解决了这个问题,有人说通过重写Disponse也可以实现,不过具体的还没有测试过。

      虽然是一个小功能,期间尝试了各种方法,折腾了也挺蛮久的,不过确实收获了一些,所以分享出来与大家共勉,如果你有更好的解决方案,不吝赐教!

  • 相关阅读:
    zoj 1649 Rescue
    poj 1659 Frogs' Neighborhood
    hdu 1385 Minimum Transport Cost
    hdu 2680 Choose the best route
    写了一下午的dijkstra。突然发现我写的根本不是dijkstra。。。。是没优化过的BFS.......
    hdu 1548 A strange lift
    hdu 2066 一个人的旅行
    hdu 2544 最短路
    洛谷 P3253 [JLOI2013]删除物品 解题报告
    洛谷 P10P1343 地震逃生 改错
  • 原文地址:https://www.cnblogs.com/gcr1314/p/2850658.html
Copyright © 2020-2023  润新知