网站导航网学 原创论文 原创专题 网站设计 最新系统 原创论文 论文降重 发表论文 论文发表 UI设计定制 论文答辩PPT格式排版 期刊发表 论文专题
返回网学首页
网学原创论文
最新论文 推荐专题 热门论文 论文专题
当前位置: 网学 > 设计资源 > .Net编程 > 正文

效率最高的Excel数据导入---(c#调用SSISPackage将数据库数据导入到Excel文件中【附源代码下载】)

论文降重修改服务、格式排版等 获取论文 论文降重及排版 论文发表 相关服务

本文目录:【本文示例源码下载】

   (一)背景

   (二)数据库数据导入到Excel的方法比较
   (三)SSIS的简介
   (四)数据库中存储过程示例(SSIS应用需要)

   (五)Excel模板的制作(这步这么简单,稍微介绍一下)
   (六)SSIS操作过程(生成Package,用来调用)(下一篇随笔将详细讲解制作Package包的过程,图片太多,篇幅过长,因此本文将直接采用生成的Package包进行应用)

   (七)C#中如何调用SSIS创建的Package和Excel模板(可以自己编写逻辑代码进行重复利用),用来生成Excel数据

   (八)总结

(一)背景

     如何将数据库中的数据导入到EXCEL文件中,我们经常会碰到。本文将比较常用的几种方法,并且将详细讲解基于SSIS的用法。笔者认为,基于SSIS的方法,对于海量数据来说,应该是效率最好的一种方法。这种方法是半年前刚入比亚迪不久,我师傅教的,哈哈。个人认为,这是一种值得推荐的方法,因此,本人决定将本人所知道的、以及自己总结的完整的写出来,一是提高一下自己的写作以及表达能力,二是让更多的读者能够在具体的应用中如何解决将海量数据导入到Excel中的效率问题。

 

(二)方法的比较

    方案一:SSIS(SQL Server数据集成服务),追求效率,Package制作过程复杂一点(容易出错)。

    方案二:采用COM.Excel组件。一般,对于操作能够基本满足,但对于数据量大时可能会慢点。下面的代码,本人稍微修改了下,如下所示:该方法主要是对单元格一个一个的循环写入,基本方法为 excel.WriteValue(ref vt, ref cf, ref ca, ref chl, ref rowIndex, ref colIndex, ref str, ref cellformat)。当数据量大时,肯定效率还是有影响的。

  1. public string DataExcels(System.Data.DataTable dts, string strTitle, string FilePath, Hashtable nameList,string titles)  
  2.  {  
  3.  COM.Excel.cExcelFile excel = new COM.Excel.cExcelFile();  
  4.  //当文件大于10的时候 清空所有文件!!!  
  5.  ClearFile(FilePath);  
  6.  //文件名  
  7.  string filename = strTitle+ DateTime.Now.ToString("yyyyMMddHHmmssff") + ".xls";  
  8.  //生成相应的文件  
  9.  excel.CreateFile(FilePath + filename);  
  10.  //设置margin  
  11.  COM.Excel.cExcelFile.MarginTypes mt1 = COM.Excel.cExcelFile.MarginTypes.xlsTopMargin;  
  12.  COM.Excel.cExcelFile.MarginTypes mt2 = COM.Excel.cExcelFile.MarginTypes.xlsLeftMargin;  
  13.  COM.Excel.cExcelFile.MarginTypes mt3 = COM.Excel.cExcelFile.MarginTypes.xlsRightMargin;  
  14.  COM.Excel.cExcelFile.MarginTypes mt4 = COM.Excel.cExcelFile.MarginTypes.xlsBottomMargin;  
  15.  double height = 2.2;  
  16.  excel.SetMargin(ref mt1, ref height);  
  17.  excel.SetMargin(ref mt2, ref height);  
  18.  excel.SetMargin(ref mt3, ref height);  
  19.  excel.SetMargin(ref mt4, ref height);  
  20.  //设置字体!!  
  21.  COM.Excel.cExcelFile.FontFormatting ff = COM.Excel.cExcelFile.FontFormatting.xlsNoFormat;  
  22.  string font = "宋体";  
  23.  short fontsize = 14;  
  24.  excel.SetFont(ref font, ref fontsize, ref ff);  
  25.  byte b1 = 1, b2 = 12;  
  26.  short s3 = 12;  
  27.  excel.SetColumnWidth(ref b1, ref b2, ref s3);  
  28.  
  29.  string header = "页眉";  
  30.  string footer = "页脚";  
  31.  excel.SetHeader(ref header);  
  32.  excel.SetFooter(ref footer);  
  33.  
  34.  COM.Excel.cExcelFile.ValueTypes vt = COM.Excel.cExcelFile.ValueTypes.xlsText;  
  35.  COM.Excel.cExcelFile.CellFont cf = COM.Excel.cExcelFile.CellFont.xlsFont0;  
  36.  COM.Excel.cExcelFile.CellAlignment ca = COM.Excel.cExcelFile.CellAlignment.xlsCentreAlign;  
  37.  COM.Excel.cExcelFile.CellHiddenLocked chl = COM.Excel.cExcelFile.CellHiddenLocked.xlsNormal;  
  38.  // 报表标题  
  39.  int cellformat = 1;   
  40. int rowIndex = 1;//起始行  
  41.  int colIndex = 0;  
  42.  foreach (System.Data.DataTable dt in dts)  
  43.  {   
  44. colIndex = 0;  
  45.  //取得列标题   
  46. foreach (DataColumn colhead in dt.Columns)  
  47.  {  
  48.  colIndex++;  
  49.  string name = colhead.ColumnName.Trim();  
  50.  object namestr = (object)name;  
  51.  excel.WriteValue(ref vt, ref cf, ref ca, ref chl, ref rowIndex, ref colIndex, ref namestr, ref cellformat);  
  52.  }  
  53.  //取得表格中的数据   
  54. foreach (DataRow row in dt.Rows)  
  55.  {  
  56.  rowIndex++;  
  57.  colIndex = 0;  
  58.  foreach (DataColumn col in dt.Columns)  
  59.  {  
  60.  colIndex++;  
  61.  if (col.DataType == System.Type.GetType("System.DateTime"))  
  62.  {   
  63. object str = (object)(Convert.ToDateTime(row[col.ColumnName].ToString())).ToString("yyyy-MM-dd"); ;  
  64.  excel.WriteValue(ref vt, ref cf, ref ca, ref chl, ref rowIndex, ref colIndex, ref str, ref cellformat);  
  65.  }  
  66.  else 
  67.  {  
  68.  object str = (object)row[col.ColumnName].ToString();  
  69.  excel.WriteValue(ref vt, ref cf, ref ca, ref chl, ref rowIndex, ref colIndex, ref str, ref cellformat);  
  70.  }  
  71.  }  
  72.  }  
  73.  rowIndex += 3 ;  
  74.  }  
  75.  int ret = excel.CloseFile();   
  76. return FilePath+filename;  
  77.  }  

方案三:采用Excel组件。一般,对于操作能够基本满足,但对于数据量大时可能会慢点。下面的代码,本人在原有基础上稍微修改了下,如下所示:

  1. public string OutputExceles(string strTitle, string FilePath, string typeName, System.Data.DataTable dtList, string smallTitleList)   
  2. {  
  3.  beforeTime = DateTime.Now;  
  4.  Excel.Application excel;  
  5.  Excel._Workbook xBk;  
  6.  Excel._Worksheet xSt;  
  7.  int rowIndex = 1;  
  8.  int colIndex = 1;  
  9.  excel = new Excel.ApplicationClass();  
  10.  xBk = excel.Workbooks.Add(true);  
  11.  xSt = (Excel._Worksheet)xBk.ActiveSheet;  
  12.  int add=0;  
  13.  foreach (System.Data.DataTable dt in dtList)  
  14.  {  
  15.  colIndex = 1;   
  16. //取得整个报表的标题   
  17. excel.Cells[rowIndex , 1] = smallTitle[add];  
  18.  add++;  
  19.  ////设置整个报表的标题格式   
  20. xSt.get_Range(excel.Cells[rowIndex, 1], excel.Cells[rowIndex , dt.Columns.Count]).Font.Bold = true;  
  21.  xSt.get_Range(excel.Cells[rowIndex, 1], excel.Cells[rowIndex , dt.Columns.Count]).Font.Size = 22;  
  22.  ////设置整个报表的标题为跨列居中   
  23. xSt.get_Range(excel.Cells[rowIndex , 1], excel.Cells[rowIndex , dt.Columns.Count]).Select();  
  24.  xSt.get_Range(excel.Cells[rowIndex , 1], excel.Cells[rowIndex, dt.Columns.Count]).HorizontalAlignment = Excel.XlHAlign.xlHAlignCenterAcrossSelection;  
  25.  rowIndex++;  
  26.  foreach (DataColumn col in dt.Columns)  
  27.  {  
  28.  excel.Cells[rowIndex, colIndex] = col.ColumnName;  
  29.  //设置标题格式为居中对齐  
  30.  xSt.get_Range(excel.Cells[rowIndex, colIndex], excel.Cells[rowIndex, colIndex]).Font.Bold = true;  
  31.  xSt.get_Range(excel.Cells[rowIndex, colIndex], excel.Cells[rowIndex, colIndex]).HorizontalAlignment = Excel.XlVAlign.xlVAlignCenter;  
  32.  xSt.get_Range(excel.Cells[rowIndex, colIndex], excel.Cells[rowIndex, colIndex]).Select();  
  33.  xSt.get_Range(excel.Cells[rowIndex, colIndex], excel.Cells[rowIndex, colIndex]).Interior.ColorIndex = titleColorindex; colIndex++;  
  34.  }  
  35.  //取得表格中的数据   
  36. foreach (DataRow row in dt.Rows)  
  37.  {  
  38.  rowIndex++;  
  39.  colIndex = 1;  
  40.  foreach (DataColumn col in dt.Columns)  
  41.  {  
  42.  if (col.DataType == System.Type.GetType("System.DateTime"))  
  43.  {  
  44.  if (!string.IsNullOrEmpty(row[col.ColumnName].ToString()))  
  45.  {  
  46.  excel.Cells[rowIndex, colIndex] = (Convert.ToDateTime(row[col.ColumnName].ToString())).ToString("yyyy-MM-dd");  
  47.  xSt.get_Range(excel.Cells[rowIndex, colIndex], excel.Cells[rowIndex, colIndex]).HorizontalAlignment = Excel.XlVAlign.xlVAlignCenter; }  
  48.  }  
  49.  else if (col.DataType == System.Type.GetType("System.String"))  
  50.  {  
  51.  excel.Cells[rowIndex, colIndex] = "'" + row[col.ColumnName].ToString();  
  52.  xSt.get_Range(excel.Cells[rowIndex, colIndex], excel.Cells[rowIndex, colIndex]).HorizontalAlignment = Excel.XlVAlign.xlVAlignCenter;r; }  
  53.  else 
  54.  {  
  55.  excel.Cells[rowIndex, colIndex] = row[col.ColumnName].ToString();  
  56.  xSt.get_Range(excel.Cells[rowIndex, colIndex], excel.Cells[rowIndex, colIndex]).HorizontalAlignment = Excel.XlVAlign.xlVAlignCenter; }  
  57.  colIndex++;  
  58.  }  
  59.  }  
  60.  rowIndex ++;  
  61.  }  
  62.  afterTime = DateTime.Now;  
  63.  xSt.Name = strTitle;  
  64.  string filename = typeName + DateTime.Now.ToString("yyyyMMdd") + ".xls";  
  65.  // excel.Save(FilePath+filename);  
  66.  excel.ActiveWorkbook.SaveCopyAs(FilePath + filename); 
  67. #region 结束Excel进程  
  68.  xBk.Close(nullnullnull);  
  69.  excel.Workbooks.Close();  
  70.  excel.Quit();
  71.  #endregion  
  72.  return filename;  
  73.  }  

方法四:采用DataGrid,GridView自带的属性。如下:

  1. private void ExportExcelFromDataGrid(string filename, System.Web.UI.WebControls.GridView ToExcelGrid)  
  2.  {  
  3.  Response.ClearHeaders();  
  4.  Response.Clear();  
  5.  Response.Expires = 0;  
  6.  Response.Buffer = true;  
  7.  Response.HeaderEncoding = System.Text.Encoding.UTF8;  
  8.  // Response.Charset = "utf-8";  
  9.  Response.AppendHeader("Content-Disposition""attachment;filename=" + Server.UrlEncode(filename));  
  10.  Response.ContentEncoding = System.Text.Encoding.Default;//设置输出流为简体中文   
  11. // Response.ContentType = "application/ms-excel";//设置输出文件类型为excel文件。   
  12. Response.ContentType = "Application/octet-stream";  
  13.  this.EnableViewState = false;  
  14.  System.Globalization.CultureInfo myCItrad = new System.Globalization.CultureInfo("zh-CHS"true);  
  15.  System.IO.StringWriter oStringWriter = new System.IO.StringWriter(myCItrad);  
  16.  System.Web.UI.HtmlTextWriter oHtmlTextWriter = new System.Web.UI.HtmlTextWriter(oStringWriter);  
  17.  ToExcelGrid.RenderControl(oHtmlTextWriter);  
  18.  Response.Write(oStringWriter.ToString());  
  19.  Response.End();  
  20.  } 

(三)SSIS的简介
    SQL Server 2005 提供的一个集成化的商业智能开发平台,主要包括:  
  *SQL Server Analysis Services(SQL Server数据分析服务,简称SSAS)  
  *SQL Server Reporting Services(SQL Server报表服务,简称SSRS)  
  *SQL Server Integration Services(SQL Server数据集成服务,简称SSIS)

    SQL Server 2005 Integration Services (SSIS) 提供一系列支持业务应用程序开发的内置任务、容器、转换和数据适配器。可以创建 SSIS 解决方案来使用 ETL 和商业智能解决复杂的业务问题,管理 SQL Server 数据库以及在 SQL Server 实例之间复制 SQL Server 对象。
 
(四)数据库中存储过程示例(SSIS应用过程中需要的,最好拿个本子把需要的内容记下) 
    在SQL SERVER 2005中,以SSISDataBase数据库作为应用,仅包括2张表City,Province.(主要是为了简单,便于讲解)

   

    其中存储过程如下:

  1. ALTER PROCEDURE [dbo].[ProvinceSelectedCityInfo]  
  2. (  
  3. @provinceId int=0  
  4. )   
  5. as 
  6. begin 
  7. select P.EName as 省份拼音,P.CName as 省份名,C.CName as 城市名 from City C left join Province P  
  8.  on C.ProvinceId = P.ProvinceId  
  9. where C.ProvinceId =@provinceId and @provinceId is not null or @provinceId is null or @provinceId=0  
  10. end 

 其中,在这一步中我们必须要记住相关的内容,如上标识(红色);为什么这么做?主要是在制作SSIS包的时候很容易混淆,建议拿个本子把需要的内容写好。

 (五)Excel模板的制作(这步这么简单,稍微介绍一下)   因为SSIS中列映射对应的是Excel的标题,与数据是一对一的关系。先不管这么多,看下我们的模板,如下图所示。我们应该能够发现,省份拼音、省份名、城市名,还有ProvinceCityInfoExcel.xls,Sheet1都被笔者标识了,当然这一步与数据库中的存储过程取出的数据也是一对一的。(名称一致,可以减少很多不必要的麻烦,不然的话,嘿嘿.自己去想,那不是哥的事)     等下,需要将创建的EXCEL模板放置到我们的项目文件目录中。(详见第七步) (六)SSIS操作过程(生成Package,用来调用)
    这一步是最主要的过程,当然,也是很容易出错的一步。笔者会另外详细介绍制作Package包的过程,本文将直接将生成的包放到VS项目中进行运用。
    利用SQL Server 2005数据库自带的SQL Server Business Intelligence Development Studio(SQL Server商业智能开发平台),最终生成的项目如下图所示:
 
     然后,将在SSIS项目中生成的Package.dtsx包复制到自己的项目文件目录中。这就是我们马上进入的步骤了---->(步骤七) (七)C#中调用SSIS创建的Package和Excel模板(可以自己编写逻辑代码进行重复利用),用来生成Excel数据    先看下我们的VS2008项目,如下图所示:     大家会发现,笔者将(五)(六)步骤生成的模板和Package包放置在项目中的“Excel导出”目录下,当然这些文件随便你放在哪里,这是不用再废话的,哈哈。    另外,笔者简单的设计了如下很粗糙的界面,目的是根据省份来显示城市的相关信息(其实大家都是很熟悉这些的,很多项目都是有省-市-县数据库表的),添加一个导出按钮,点击的时候,我们可以参考页面显示的内容和我们生成的客户端Excel中的内容是否一致。     现在我们的重头戏开始了,如下代码(点击将触发的代码内容):
  1. protected void btnSSISSearch_Click(object sender, EventArgs e)  
  2.  {  
  3.  //构造sql语句 作为参数传递给数据包  
  4.  string sqlParams = Jasen.SSIS.Core.SsisToExcel.BuildSql("dbo.ProvinceSelectedCityInfo""@provinceId"int.Parse(ddlProvice.SelectedValue));  
  5.  Jasen.SSIS.Core.SsisToExcel ssis = new Jasen.SSIS.Core.SsisToExcel();  
  6.  string rootPath = Request.PhysicalApplicationPath;  
  7.  string copyFilePath;  
  8.  //执行SSIS包的操作 生成EXCEL文件  
  9.  bool result = ssis.ExportDataBySsis(rootPath, sqlParams, out copyFilePath, "Package.dtsx""ProviceCityInfoExcel.xls""ProviceCityInfo");  
  10.  if (result == false){  
  11.  if (System.IO.File.Exists(copyFilePath)) System.IO.File.Delete(copyFilePath);   
  12.  }  
  13.  else 
  14.  {  
  15.  ssis.DownloadFile(this"ProviceCityInfoClientFile.xls", copyFilePath, true);  
  16.  }  
  17.  } 

 你肯定会说:“哥,你这个也太简单了吧?”。就是这么简单,不就是多写一个类给你调用就可以了吗。调用接口,这个你总会吧。不过你得了解各个参数才行。

    首先,我们必须引用2个DLL,Microsoft.SQLServer.ManagedDTS.dll和Microsoft.SqlServer.DTSPipelineWrap.dll(系统自带的)。先看下我们生成Excel文件数据的步骤,如下:

  1. /// <summary>  
  2.  /// 导出数据到EXCEL文件中  
  3.  /// </summary>  
  4.  /// <param name="rootPath"></param>  
  5.  /// <param name="sqlParams">执行包的传入参数</param>  
  6.  /// <param name="copyFile">生成的Excel的文件</param>  
  7.  /// <param name="packageName">SSIS包名称</param>  
  8.  /// <param name="execlFileName">SSIS EXCEL模板名称</param>  
  9.  /// <param name="createdExeclPreName">生成的Excel的文件前缀</param>  
  10.  /// <returns></returns>  
  11.  public bool ExportDataBySsis(string rootPath, string sqlParams, out string tempExcelName, string packageName, string execlFileName, string createdExeclPreName)  
  12.  {  
  13.  //数据包和EXCEL模板的存储路径  
  14.  string path = rootPath + @"Excel导出\";  
  15.  //强制生成目录  
  16.  if (!System.IO.Directory.Exists(path)) System.IO.Directory.CreateDirectory(path);  
  17.  //返回生成的文件名  
  18.  string copyFile = this.SaveAndCopyExcel(path, execlFileName, createdExeclPreName);  
  19.  tempExcelName = copyFile;  
  20.  //SSIS包路径  
  21.  string ssisFileName = path + packageName;  
  22.  //执行---把数据导入到Excel文件  
  23.  return ExecuteSsisDataToFile(ssisFileName, tempExcelName, sqlParams);  
  24.  } 

代码注释如此清楚,想必也不需要再多做解释了吧,下面就是最最最重要的一步,需要看清楚了----->

  1. private bool ExecuteSsisDataToFile(string ssisFileName, string tempExcelName, string sqlParams)  
  2.  {  
  3.  Application app = new Application();  
  4.  Package package = new Package();  
  5.  //加载SSIS包   
  6. package = app.LoadPackage(ssisFileName, null);  
  7.  //获取 数据库连接字符串  
  8.  package.Connections["AdoConnection"].ConnectionString = Jasen.SSIS.Common.SystemConst.ConnectionString;  
  9.  //目标Excel属性  
  10.  string excelDest = string.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties=\"EXCEL 8.0;HDR=YES\";", tempExcelName);  
  11.  package.Connections["ExcelConnection"].ConnectionString = excelDest;  
  12.  //给参数传值  
  13.  Variables vars = package.Variables;  
  14.  string str = vars["用户::SqlStr"].Value.ToString();  
  15.  vars["用户::SqlStr"].Value = sqlParams;  
  16.  //执行  
  17.  DTSExecResult result = package.Execute();  
  18.  if (result == DTSExecResult.Success){  
  19.  return true;  
  20.  }  
  21.  else{  
  22.  if (package.Errors.Count > 0){  
  23.  //在log中写出错误列表  
  24.  StringBuilder sb=new StringBuilder();  
  25.  for (int i = 0; i < package.Errors.Count; i++){  
  26.  sb.Append("Package error:" + package.Errors[i].Description +";");  
  27.  }  
  28.  throw new Exception(sb.ToString());  
  29.  }  
  30.  else{  
  31.  throw new Exception("SSIS Unknow error");  
  32.  }  
  33.  return false;  
  34.  }  
  35.  } 

 上面标注为红色的就是最重要的几个步骤了,相对来说,就是(1)加载包,(2)设置包的数据库连接串,(3)设置Excel的连接串,(4)设置参数变量,(5)执行操作  

      其次是如何巧妙的将Excel模板复制,使模板可以重复利用(当然也要注意将生成的文件下载到客户端后,将服务器上生成的Excel临时文件删除,你也可以写自己的算法进行清理不必要的Excel临时文件),如下代码所示,方法将复制模板,然后返回生成的临时文件的路径,如果需要删除该文件,System.IO.File.Delete(filePath)就可以删除文件了:

1  private string SaveAndCopyExcel(string sourcePath, string execlFileName, string createdExeclPreName)
2         {
3             string copyFile = sourcePath + createdExeclPreName + DateTime.Now.ToString("yyyyMMddHHMMss"+ ".xls";
4             if (File.Exists(copyFile)) File.Delete(copyFile);
5             File.Copy(sourcePath + execlFileName, copyFile, true);
6             return copyFile;
7         }        讲了这么多,来看下我们点击后生成的效果,     开始有点效果了,Excel终于可以下载到客户端了,我们保存该文件。我们是不是想核实一下,我们采用的SSIS方法来实现Excel数据导入是不是正确的,会不会生成错误的数据?    那我们看下下面的一张图,将它与上面的一张图比较一下,看下数据是不是一样的:     发现生成的数据是一模一样的。我们是将数据导入到服务器上的临时EXCEL文件中,将文件发送到客户端肯定是不会出错的,除了你RP太差以外。RP差,任何事情都可能发生,嘿嘿。 (八)总结    在上面的示例中,由于数据量不是太多,你还感觉不到该方法的优势(效率高)。但是当数据量很大的时候,你用其他方法还在那里慢慢地等待excel文件生成的时候,该方法早就已经将数据导入到Excel中,并且发送到客户端了。有时候时间相差几十秒也是有可能的。数据量越大,效果越明显。万科和比亚迪都在用,嘿嘿,其他的哥就不知道了..    接下来笔者将在另外一篇随笔中详细讲解SSIS package包的制作过程。这篇主要是SSIS应用篇。    希望各位能够在本随笔中有所收获。一口气写下来,还真不容易,写文章确实挺锻炼人的。当然,本文中肯定还有很多不足之处,希望各位多多指教。
设为首页 | 加入收藏 | 网学首页 | 原创论文 | 计算机原创
版权所有 网学网 [Myeducs.cn] 您电脑的分辨率是 像素
Copyright 2008-2020 myeducs.Cn www.myeducs.Cn All Rights Reserved 湘ICP备09003080号 常年法律顾问:王律师