使用C#与Microsoft.Office.Interop.Excel实现Excel自动化:图片插入问题
解决C# Excel自动化导出数据库图片(byte[])的问题
首先你的代码存在一处明显错误:循环里的excelWorksheet = excelWorkbook.Sheets[i] as Worksheet;会错误切换工作表,而非填充当前行的单元格数据。以下是修复后并支持图片导出的完整实现:
修改后的完整代码
string currentdatetime = DateTime.Now.ToString("yyyyMMddHHmmss"); string connectionString = Settings.Default["ConnectionString"].ToString(); string queryString = Settings.Default["Query"].ToString(); SaveFileDialog save = new SaveFileDialog(); save.OverwritePrompt = true; save.Filter = "Excel 文件 |.xlsx| Excel 文件 |.xls"; // 修复逻辑判断:用&&替代||,避免空值/空字符串误判 if (!string.IsNullOrEmpty(Settings.Default.Query)) { if (save.ShowDialog() == DialogResult.OK) { try { Application excelApp = new Application(); Workbook excelWorkbook = excelApp.Workbooks.Add(); Worksheet excelWorksheet = excelWorkbook.Worksheets[1]; using (SqlConnection connection = new SqlConnection(connectionString)) { connection.Open(); using (SqlCommand command = new SqlCommand(queryString, connection)) { using (SqlDataReader reader = command.ExecuteReader()) { // 写入表头 int col = 1; for (int i = 0; i < reader.FieldCount; i++) { excelWorksheet.Cells[1, col].Value2 = reader.GetName(i); // 自动调整列宽(可选优化) excelWorksheet.Columns[col].AutoFit(); col++; } // 写入数据行 int row = 2; while (reader.Read()) { col = 1; for (int i = 0; i < reader.FieldCount; i++) { var fieldValue = reader[i]; if (fieldValue is DBNull) { excelWorksheet.Cells[row, col].Value2 = string.Empty; } else if (fieldValue is byte[] imageBytes) { // 处理数据库中的图片字节数据 using (MemoryStream ms = new MemoryStream(imageBytes)) { Image img = Image.FromStream(ms); // 在对应单元格位置插入图片 var shape = excelWorksheet.Shapes.AddPicture( ms, Microsoft.Office.Core.MsoTriState.msoFalse, Microsoft.Office.Core.MsoTriState.msoTrue, excelWorksheet.Cells[row, col].Left, excelWorksheet.Cells[row, col].Top, img.Width, img.Height ); // 设置图片随单元格移动、调整大小 shape.Placement = Microsoft.Office.Interop.Excel.XlPlacement.xlMoveAndSize; } // 调整行高适配图片 excelWorksheet.Rows[row].Height = excelWorksheet.Cells[row, col].Height * (img.Height / excelWorksheet.Cells[row, col].Height); } else { // 普通数据类型直接写入单元格 excelWorksheet.Cells[row, col].Value2 = fieldValue; } col++; } row++; } } } } // 保存并清理Excel资源 excelWorkbook.SaveAs(save.FileName); excelWorkbook.Close(); excelApp.Quit(); // 释放COM对象,避免Excel进程后台残留 System.Runtime.InteropServices.Marshal.ReleaseComObject(excelWorksheet); System.Runtime.InteropServices.Marshal.ReleaseComObject(excelWorkbook); System.Runtime.InteropServices.Marshal.ReleaseComObject(excelApp); using (FileStream stream = new FileStream(save.FileName, FileMode.Open)) { ExcelSpread.LoadDocument(stream); } Cursor.Current = Cursors.Default; } catch (Exception exception) { MessageBox.Show(exception.Message); } } } else { if (XtraMessageBox.Show("请先从数据库设置选项卡的查询编写区域输入要使用的查询语句。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Warning) == DialogResult.OK) { Forms.WriteQuery wq = new Forms.WriteQuery(); wq.Show(); } }
关键修改说明
- 修复逻辑判断:将原错误的
||改为!string.IsNullOrEmpty,避免空值/空字符串的误判。 - 图片处理逻辑:判断字段值是否为
byte[],通过MemoryStream转换为Image后,调用Shapes.AddPicture插入到对应单元格位置。 - 图片适配优化:设置图片随单元格移动、调整大小,同时自动调整行高适配图片尺寸。
- COM资源释放:添加
Marshal.ReleaseComObject释放Excel相关COM对象,防止后台残留Excel进程。
注意事项
- 确保项目已引用
Microsoft.Office.Interop.Excel程序集。 - 数据库中的
byte[]必须是有效的图片格式(如JPG、PNG),否则Image.FromStream会抛出异常。 - 若图片体积过大,建议先压缩再插入,避免Excel文件体积超标。
内容的提问来源于stack exchange,提问作者Ahmet Enes Söylemez
相关产品推荐
相关产品推荐

