最近这段时间一直在琢磨将图片和GridView里的数据一块导入Excel,并保存到客户端磁盘上。试验了好几种方法,要不就是只能将图片插入Excel中,要不只能将GridView的数据导入到Excel,两者总是不能一块实现,一个大的原因就是GridView中存在复杂表头、上下标等问题。
下面就讲一下如何将图片和GridView中的单行简单表头导入到Excel中,也是参照了网上高手将GridView中的数据导出到Excel中的方法,然后又通过自己的努力实现自己最终需要的导出Excel功能。客户之所以提出这样的需求,主要是因为一个网页的上面部分实现主要数据的图形绘制,下面通过表格实现详细数据的显示。如果采用水晶报表开发,这样的功能很容易实现。但是水晶报表在绘制一些特殊的图形时存在不能满足客户的需求,显示的效果也不尽人意,所以就借助的第三方Dundas Chart控件开发了图形。
导出Excel代码如下:
1 /// <summary>
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中,如果有专家曾经做过这样的,指导一下。
如果有人遇到以上问题,或者做过类似的,欢迎交流、指导~~~
宝贵知识就是拿来分享 促使共同进步 节省他人时间就是在节省自己时间~~~
作者:zeke
出处:http://zhf.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。