最近这段时间一直在琢磨将图片和GridView里的数据一块导入Excel,并保存到客户端磁盘上。试验了好几种方法,要不就是只能将图片插入Excel中,要不只能将GridView的数据导入到Excel,两者总是不能一块实现,一个大的原因就是GridView中存在复杂表头、上下标等问题。
下面就讲一下如何将图片和GridView中的单行简单表头导入到Excel中,也是参照了网上高手将GridView中的数据导出到Excel中的方法,然后又通过自己的努力实现自己最终需要的导出Excel功能。客户之所以提出这样的需求,主要是因为一个网页的上面部分实现主要数据的图形绘制,下面通过表格实现详细数据的显示。如果采用水晶报表开发,这样的功能很容易实现。但是水晶报表在绘制一些特殊的图形时存在不能满足客户的需求,显示的效果也不尽人意,所以就借助的第三方Dundas Chart控件开发了图形。
导出Excel代码如下:


2 /// 导出Excel,并保存本地
3 /// </summary>
4 /// <param name="dt"> 数据表DataTable </param>
5 /// <param name="AbosultedFilePath"> 图片、Excel文件保存路径 </param>
6 /// <param name="fileName"> 文件名称 </param>
7 /// <param name="cWidth"> 图片宽度 </param>
8 /// <param name="cHeight"> 图片高度 </param>
9 /// <returns> 返回true </returns>
10 public static bool ExportToExcel(DataTable dt, string AbosultedFilePath, string fileName, float cWidth, float cHeight)
11 {
12 object m_objOpt = System.Reflection.Missing.Value;
13
14 // 检查数据表是否为空,如果为空,则退出
15 if (dt == null )
16 return false ;
17
18 // 创建Excel应用程序对象,如果未创建成功则退出
19 Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
20 if (xlApp == null )
21 {
22 System.Web.HttpContext.Current.Response.Write( " 无法创建Excel对象,可能你的电脑未装Excel " );
23 return false ;
24 }
25
26 Microsoft.Office.Interop.Excel.Workbooks workbooks = xlApp.Workbooks;
27 Microsoft.Office.Interop.Excel.Workbook workbook = workbooks.Add(Microsoft.Office.Interop.Excel.XlWBATemplate.xlWBATWorksheet);
28 Microsoft.Office.Interop.Excel.Worksheet worksheet = (Microsoft.Office.Interop.Excel.Worksheet)workbook.Worksheets[ 1 ]; // 取得sheet1
29 Microsoft.Office.Interop.Excel.Range range = null ;
30
31 // ---插入图片第一种方法--- //
32 // range = worksheet.get_Range("A1", m_objOpt); // A1:代表Excel中单元格位置
33 // range.Select();
34 // Excel.Pictures pics = (Excel.Pictures)worksheet.Pictures(m_objOpt);
35 // pics.Insert(AbosultedFilePath + fileName + ".jpg", m_objOpt);
36
37 // ---插入图片第二中方法--- //
38 worksheet.Shapes.AddPicture(AbosultedFilePath + fileName + " .jpg " , MsoTriState.msoFalse, MsoTriState.msoTrue, 2 , 2 , cWidth, cHeight);
39
40 object aa = worksheet.Rows.Height;
41 long totalCount = dt.Rows.Count;
42 long rowRead = 0 ;
43 float percent = 0 ;
44 // 定义图片所占的行数
45 int rowIndex = Convert.ToInt32(cHeight / 13.5 ) + 2 ;
46 // 定义存放表头名称的数组
47 ArrayList arrheadName = new ArrayList();
48 string cellText = "" ;
49
50 // ---获取dt中表头的名称,也可以换成获取GridView中表头的名称--- //
51 arrheadName.Clear();
52 for ( int col = 0 ;col < dt.Columns.Count;col ++ )
53 {
54 arrheadName.Add(dt.Columns[col].ColumnName);
55 }
56
57 // 写入标题
58 for ( int i = 0 ; i < arrheadName.Count; i ++ )
59 {
60 // 写入表头名称
61 worksheet.Cells[rowIndex, i + 1 ] = arrheadName[i].ToString();
62
63 // 设置标题的样式
64 range = (Microsoft.Office.Interop.Excel.Range)worksheet.Cells[rowIndex, i + 1 ];
65 range.Font.Bold = true ; // 粗体
66 range.HorizontalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignCenter; // 居中
67 range.WrapText = true ; // 换行
68 range.BorderAround(Microsoft.Office.Interop.Excel.XlLineStyle.xlContinuous, Microsoft.Office.Interop.Excel.XlBorderWeight.xlThin, Microsoft.Office.Interop.Excel.XlColorIndex.xlColorIndexAutomatic, null ); // 背景色
69 // range.Borders[Microsoft.Office.Interop.Excel.XlBordersIndex.xlInsideHorizontal].Weight = Microsoft.Office.Interop.Excel.XlBorderWeight.xlThin;
70 range.EntireColumn.AutoFit(); // 自动设置列宽
71 range.EntireRow.AutoFit(); // 自动设置行高
72 }
73
74 // 写入DataTable中数据的内容
75 for ( int r = 0 ; r < dt.Rows.Count; r ++ )
76 {
77 for ( int c = 0 ; c < dt.Columns.Count; c ++ )
78 {
79 // 写入内容
80 worksheet.Cells[r + rowIndex + 1 , c + 1 ] = dt.Rows[r][c].ToString();
81 // 设置样式
82 range = (Microsoft.Office.Interop.Excel.Range)worksheet.Cells[r + rowIndex + 1 , c + 1 ];
83 range.Font.Size = 9 ; // 字体大小
84 range.BorderAround(Microsoft.Office.Interop.Excel.XlLineStyle.xlContinuous, Microsoft.Office.Interop.Excel.XlBorderWeight.xlThin, Microsoft.Office.Interop.Excel.XlColorIndex.xlColorIndexAutomatic, null ); // 加边框
85 range.EntireColumn.AutoFit(); // 自动调整列宽
86 }
87 rowRead ++ ;
88 percent = (( float )( 100 * rowRead)) / totalCount;
89 System.Windows.Forms.Application.DoEvents();
90 }
91 range.Borders[Microsoft.Office.Interop.Excel.XlBordersIndex.xlInsideHorizontal].Weight = Microsoft.Office.Interop.Excel.XlBorderWeight.xlThin;
92 if (dt.Columns.Count > 1 )
93 {
94 range.Borders[Microsoft.Office.Interop.Excel.XlBordersIndex.xlInsideVertical].Weight = Microsoft.Office.Interop.Excel.XlBorderWeight.xlThin;
95 }
96
97 try
98 {
99 // ---首先将Excel保存到服务器文件夹中--- //
100 workbook.Saved = true ;
101 workbook.SaveCopyAs(AbosultedFilePath + fileName + " .xls " );
102
103 }
104 catch (Exception ex)
105 {
106 System.Web.HttpContext.Current.Response.Write( " 导出文件时出错,文件可能正被打开!\n " + ex.ToString());
107 return false ;
108 }
109
110 workbooks.Close();
111
112 if (xlApp != null )
113 {
114 xlApp.Workbooks.Close();
115 xlApp.Quit();
116
117 int generation = System.GC.GetGeneration(xlApp);
118 System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);
119
120 xlApp = null ;
121 System.GC.Collect(generation);
122 }
123 GC.Collect(); // 强行销毁
124
125 #region 强行杀死最近打开的Excel进程
126 System.Diagnostics.Process[] excelProc = System.Diagnostics.Process.GetProcessesByName( " EXCEL " );
127 System.DateTime startTime = new DateTime();
128 int m, killID = 0 ;
129 for (m = 0 ; m < excelProc.Length; m ++ )
130 {
131 if (startTime < excelProc[m].StartTime)
132 {
133 startTime = excelProc[m].StartTime;
134 killID = m;
135 }
136 }
137 if (excelProc[killID].HasExited == false )
138 {
139 excelProc[killID].Kill();
140 }
141 #endregion
142
143 // ---删除控件保存的图片--- //
144 if (File.Exists(AbosultedFilePath + fileName + " .jpg " ))
145 {
146 File.Delete(AbosultedFilePath + fileName + " .jpg " );
147 }
148 // ---将保存的Excel下载到本地--- //
149 if (saveExcel(AbosultedFilePath + fileName + " .xls " ))
150 {
151 return true ;
152 }
153 return false ;
154 }
155
156 /// <summary>
157 /// Excel文件下载本地磁盘
158 /// </summary>
159 /// <param name="FileName"> 路径+文件名 </param>
160 /// <returns> 返回true </returns>
161 public static bool saveExcel( string FileName)
162 {
163 try
164 {
165 string FullFileName = FileName;
166 // FileName--要下载的文件名
167 FileInfo DownloadFile = new FileInfo(FullFileName);
168 if (DownloadFile.Exists)
169 {
170 System.Web.HttpContext curContext = System.Web.HttpContext.Current;
171 curContext.Response.Clear();
172 curContext.Response.ClearHeaders();
173 curContext.Response.Buffer = false ;
174 curContext.Response.ContentType = " application/octet-stream " ;
175 curContext.Response.AppendHeader( " Content-Disposition " , " attachment;filename= " + HttpUtility.UrlEncode(DownloadFile.FullName, System.Text.Encoding.ASCII));
176 curContext.Response.AppendHeader( " Content-Length " , DownloadFile.Length.ToString());
177 curContext.Response.WriteFile(DownloadFile.FullName);
178 curContext.Response.Flush();
179 curContext.Response.End();
180 DownloadFile.Delete(); // 这个删除无作用
181 return true ;
182 }
183 else
184 {
185 // 文件不存在
186 return false ;
187 }
188 }
189 catch
190 {
191 // 打开时异常了
192 return false ;
193 }
194 }
通过上面的方法导出Excel后,打开Excel发现了一个问题,图片的高度和宽度是按像素取值,但是保存到Excel中明显看到图片被放大了,查看图片的大小和属性,发现高度和宽度都变成了133%,查了好久也不知道是什么原因造成的,最终只能试着将传入图片的高度和宽度进行了处理:
float width = Convert.ToSingle(cWidth - cWidth * 0.25);//cWidth:图片宽度
float height = Convert.ToSingle(cHeight - cHeight * 0.25);//cHeight :图片高度
经过这样,插入的图片才达到了原始效果。有没有高手遇到这种情况的,指导一下~~~
需要注意的地方:
在调用ExportToExcel();这个方法后,要记得删除服务器 path + fileName + ".xls" 这个临时文件,不然会占用大量磁盘空间。
path:服务器保存的目录
fileName:文件名称
另外一种导出Excel的方法:
就是先将Excel文件保存成xml文件,然后通过解析xml文件实现将复杂表头和数据导出到Excel文件,但是目前还没有将图片采用这种方式导出到Excel中,不知道可不可以将图片采用文件流的形式写入到Excel中,如果有专家曾经做过这样的,指导一下。
如果有人遇到以上问题,或者做过类似的,欢迎交流、指导~~~
宝贵知识就是拿来分享 促使共同进步 节省他人时间就是在节省自己时间~~~