一、添加Nuget引用

二、弹框选择保存路径

         string fileName = $"记录_{DateTime.Now.ToString("yyyyMMdd_HHmmss")}";
string saveFileName = "";
SaveFileDialog saveFileDialog = new SaveFileDialog();
saveFileDialog.DefaultExt = "xls";
//saveFileDialog.Filter = "Excel 工作簿|*.xlsx|Excel 97-2003 工作簿|*.xls";
saveFileDialog.Filter = "Excel 97-2003 工作簿|*.xls";
saveFileDialog.FileName = fileName;
saveFileDialog.ShowDialog(); saveFileName = saveFileDialog.FileName;
if (saveFileName?.IndexOf(":") < 0) return;//点击了取消

三、主要代码:

        public enum StyleXlsEnum
{
Head,
ColumnHead,
Default
} private static IWorkbook m_workbook;
private static ISheet m_sheet;
private static List<string> m_sheets = new List<string>();
private static ICellStyle m_cellStyle;
private static IDataFormat m_dataStyle;
private static IFont m_font16;
private static IFont m_font12;
private static IFont m_font;
     /// <summary>
/// 导出Excel
/// </summary>
/// <param name="dt">DataTable数据</param>
/// <param name="saveFileName">Excel文件全路径</param>
/// <param name="sheetName">Sheet名称</param>
/// <param name="headerName">标题名称</param>
/// <returns></returns>
private bool ExportExcel(DataTable dt, string saveFileName, string sheetName, string headerName)
{
ICellStyle cellStyle = null;try
{
#region 创建Excel对象 //如果Excel存在就获取IWorkbook对象,否则就重新创建
if (File.Exists(saveFileName))
{
FileStream fs = new FileStream(saveFileName, FileMode.Open, FileAccess.Read);
m_workbook = new XSSFWorkbook(fs);
if (saveFileName.IndexOf(".xlsx") > 0) // 2007版本
m_workbook = new XSSFWorkbook(fs);
else if (saveFileName.IndexOf(".xls") > 0) // 2003版本
m_workbook = new HSSFWorkbook(fs);
}
else
{
//创建一个工作簿
m_workbook = new HSSFWorkbook();
} if (m_workbook != null)
{
//获取所有SheetName
int count = m_workbook.NumberOfSheets;
if (count < 1)
{
m_sheet = m_workbook.CreateSheet(sheetName);
}
else
{
m_sheets.Clear();
for (int i = 0; i < count; i++)
{
m_sheet = m_workbook.GetSheetAt(1);
m_sheets.Add(m_sheet.SheetName);
} if (m_sheets.Contains(sheetName))
{
m_sheet = m_workbook.CreateSheet(sheetName + System.DateTime.Now.ToString("HH-mm-ss") + "副本");
}
else
{
m_sheet = m_workbook.CreateSheet(sheetName);
}
}
}
else
{
return false;
} #endregion #region 设置表头 m_sheet.AddMergedRegion(new NPOI.SS.Util.CellRangeAddress(0, 0, 0, dt.Columns.Count - 1)); //合并单元格
IRow row0 = m_sheet.CreateRow(0); //创建一行
row0.Height = 50 * 20;
ICell icelltop0 = row0.CreateCell(0); //创建一个单元格
IFont font = m_workbook.CreateFont();
font.FontHeightInPoints = 30;
icelltop0.CellStyle = Getcellstyle(m_workbook, StyleXlsEnum.Head);
icelltop0.SetCellValue(headerName); #endregion // 设置列宽,excel列宽每个像素是1/256
m_sheet.SetColumnWidth(0, 9 * 256);
m_sheet.SetColumnWidth(1, 18 * 256);
m_sheet.SetColumnWidth(2, 36 * 256);
m_sheet.SetColumnWidth(3, 25 * 256);
m_sheet.SetColumnWidth(4, 20 * 256);
m_sheet.SetColumnWidth(5, 20 * 256);
m_sheet.SetColumnWidth(6, 20 * 256);
m_sheet.SetColumnWidth(7, 25 * 256);
m_sheet.SetColumnWidth(8, 25 * 256);
m_sheet.SetColumnWidth(9, 25 * 256);
m_sheet.SetColumnWidth(10, 25 * 256); #region 设置列
IRow rowH = m_sheet.CreateRow(1);
cellStyle = Getcellstyle(m_workbook, StyleXlsEnum.ColumnHead);
//设置列名
foreach (DataColumn col in dt.Columns)
{
//创建单元格并设置单元格内容
rowH.CreateCell(col.Ordinal).SetCellValue(col.Caption); //设置单元格格式
rowH.Cells[col.Ordinal].CellStyle = cellStyle;
}
#endregion #region 写入数据 cellStyle = Getcellstyle(m_workbook, StyleXlsEnum.Default);
for (int i = 0; i < dt.Rows.Count; i++)
{
//跳过前两行,第一行为标题,第二行为列名
IRow row = m_sheet.CreateRow(i + 2);
row.Height = 70 * 20;
ICell cell = row.CreateCell(0);
for (int j = 0; j < dt.Columns.Count; j++)
{
if (dt.Columns[j].ColumnName == "图片")
{
cell = row.CreateCell(j);
cell.CellStyle = cellStyle; saveFileName= Path.GetDirectoryName(saveFileName); //将图片文件读入一个字符串
byte[] bytess = System.IO.File.ReadAllBytes(dt.Rows[i]["图片"].ToString());
int pictureIdx = m_workbook.AddPicture(bytess, PictureType.JPEG);
HSSFPatriarch patriarch = (HSSFPatriarch)m_sheet.CreateDrawingPatriarch();

                //前四个参数(dx1,dy1,dx2,dy2)为图片在单元格的边距
                            //col1,col2表示图片插在col1和col2之间的单元格,索引从0开始
                            //row1,row2表示图片插在第row1和row2之间的单元格,索引从1开始
                // 参数的解析: HSSFClientAnchor(int dx1,int dy1,int dx2,int dy2,int col1,int row1,int col2,int row2)
                     //dx1:图片左边相对excel格的位置(x偏移) 范围值为:0~1023;即输100 偏移的位置大概是相对于整个单元格的宽度的100除以1023大概是10分之一
                     //dy1:图片上方相对excel格的位置(y偏移) 范围值为:0~256 原理同上。
                     //dx2:图片右边相对excel格的位置(x偏移) 范围值为:0~1023; 原理同上。
                     //dy2:图片下方相对excel格的位置(y偏移) 范围值为:0~256 原理同上。
                     //col1和row1 :图片左上角的位置,以excel单元格为参考,比喻这两个值为(1,1),那么图片左上角的位置就是excel表(1,1)单元格的右下角的点(A,1)右下角的点。
                     //col2和row2:图片右下角的位置,以excel单元格为参考,比喻这两个值为(2,2),那么图片右下角的位置就是excel表(2,2)单元格的右下角的点(B,2)右下角的点。
HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 0, 0, 8, i+2, 7, i + 3);
//把图片插到相应的位置
HSSFPicture pict = (HSSFPicture)patriarch.CreatePicture(anchor, pictureIdx);
}
else
{
cell = row.CreateCell(j);
cell.SetCellValue(dt.Rows[i][j].ToString());
cell.CellStyle = cellStyle;
}
}
} #endregion //创建一个 IO 流
MemoryStream ms = new MemoryStream(); //写入到流
m_workbook.Write(ms); //转换为字节数组
byte[] bytes = ms.ToArray(); //保存为Excel文件
using (FileStream fs = new FileStream(saveFileName, FileMode.Create, FileAccess.Write))
{
fs.Write(bytes, 0, bytes.Length);
fs.Flush();
} //释放资源
bytes = null; ms.Close();
ms.Dispose(); m_workbook.Close();
m_sheet = null;
m_workbook = null;
m_cellStyle = null;
m_dataStyle = null;
m_font = null;
m_font12 = null;
m_font16 = null;
return true;
}
catch (Exception e)
{
Console.WriteLine(e);
return false;
}
}
     private ICellStyle Getcellstyle(IWorkbook wb, StyleXlsEnum style)
{
try
{
//CreateFont()不能频繁创建,会导致打开EXCEL表的时候报如下错误:
//此文件中的某些文本格式可能已经更改,因为它已经超出最多允许的字体数。
if (m_font16 == null)
{
m_font16 = wb.CreateFont();
m_font16.FontHeightInPoints = 16;
m_font16.FontName = "微软雅黑";
m_font16.Boldweight = (short)FontBoldWeight.Bold;
}
if (m_font12 == null)
{
m_font12 = wb.CreateFont();
m_font12.FontHeightInPoints = 12;
m_font12.FontName = "微软雅黑";
m_font12.Boldweight = (short)FontBoldWeight.Bold;
}
if (m_font == null)
{
m_font = wb.CreateFont();
m_font.FontName = "微软雅黑";
} m_cellStyle = wb.CreateCellStyle();
//边框
m_cellStyle.BorderBottom = NPOI.SS.UserModel.BorderStyle.Medium;
m_cellStyle.BorderLeft = NPOI.SS.UserModel.BorderStyle.Medium;
m_cellStyle.BorderRight = NPOI.SS.UserModel.BorderStyle.Medium;
m_cellStyle.BorderTop = NPOI.SS.UserModel.BorderStyle.Medium;
//边框颜色
//m_cellStyle.BottomBorderColor = HSSFColor.OliveGreen.Blue.Index;
//m_cellStyle.TopBorderColor = HSSFColor.OliveGreen.Blue.Index; //背景图形
//m_cellStyle.FillForegroundColor = HSSFColor.White.Index;
//m_cellStyle.FillBackgroundColor = HSSFColor.Blue.Index; //水平对齐
m_cellStyle.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center; //垂直对齐
m_cellStyle.VerticalAlignment = VerticalAlignment.Center; //自动换行
m_cellStyle.WrapText = false; //缩进
//cellStyle.Indention = 0;
//}
//创建格式
if (m_dataStyle == null)
{
m_dataStyle = wb.CreateDataFormat();
} //上面基本都是设共公的设置
//下面列出了常用的字段类型
switch (style)
{
case StyleXlsEnum.Head:
//cellStyle.FillPattern = FillPatternType.LEAST_DOTS;
//设置为文本格式,也可以为 text,即 dataFormat.GetFormat("text");
m_cellStyle.DataFormat = m_dataStyle.GetFormat("@");
m_cellStyle.SetFont(m_font16);
break;
case StyleXlsEnum.ColumnHead:
m_cellStyle.DataFormat = m_dataStyle.GetFormat("@");
m_cellStyle.SetFont(m_font12);
break;
case StyleXlsEnum.Default:
m_cellStyle.SetFont(m_font);
break;
}
return m_cellStyle;
}
catch
{
return m_cellStyle;
}
}

四、效果图:

使用NPOI导出Excel,并在Excel指定单元格插入图片的更多相关文章

  1. 27.openpyxl 向指定单元格添加图片并修改图片大小 以及修改单元格行高列宽

    openpyxl 向指定单元格添加图片并修改图片大小 以及修改单元格行高列宽 from openpyxl import Workbook,load_workbook from openpyxl.dra ...

  2. NPOI 在指定单元格导入导出图片

    NPOI 在指定单元格导入导出图片 Intro 我维护了一个 NPOI 的扩展,主要用来导入导出 Excel 数据,最近有网友提出了导入 Excel 的时候解析图片的需求,于是就有了本文的探索 导入E ...

  3. 个人永久性免费-Excel催化剂功能第81波-指定单元格区域内容及公式填充

    在日常数据处理过程中,需要对缺失数据进行填充时,按一定逻辑规则进行处理,实现快速填充,规范数据源.此篇给大家带来多种填充数据的场景. 业务使用场景 对各种系统中导出的数据,很多时候存在数据缺失的情况, ...

  4. 使用VBA将Excel指定单元格数据、字符串或者图表对象插入到Word模板指定书签处

    准备工作: 1.首先需要提供一个word模板,并且标记好您要插入书签的位置,定义书签的命名.如图 2.模拟您要插入的Excel原始数据和图表对象 插入代码如下: Private Sub Command ...

  5. C#修改 Excel指定单元格的值

    /// <summary> /// 将指定字符串写入指定单元格中 /// </summary> /// <param name="data">要 ...

  6. vba打开excel文件遍历sheet的名字和指定单元格的值

    今天项目上有个应用,获取指定Excel文件下的所有sheet的名称以及当前sheet中指定单元格的值,并把他们写到固定的sheet中去,看了下,文件比较多,而且每个文件sheet的个数比较多,也不一样 ...

  7. C#实现对EXCEL指定单元格进行操作

    using System; using System.Collections.Generic; using System.Text; using Microsoft.Office.Interop.Ex ...

  8. 疑难杂症 | Excel VBA锁定指定单元格区域

    背景:锁定EXCEL表头 一.手动操作流程 其基本逻辑并不赋值,手动操作流程是: 1.取消所有单元格的"锁定"格式 CTRL+A,选中全部的单元格→单击右键→设置单元格格式→保护→ ...

  9. NPOI扩展--判断指定单元格是否为合并单元格和输出该单元格的行列跨度(维度)

    因工作需要用到跨合并单元格获取数据,所以写了个NPOI扩展类. 主要方法如下: 1.判断指定行/列索引(单元格)是否为合并单元格. 2.获取指定列索引的实际含有数据的单元格. 3.返回指定行/列索引的 ...

  10. c#操作Excel模板,替换命名单元格或关键字形成报表

    c#操作Excel模板,替换命名单元格或关键字形成报表 http://blog.sina.com.cn/s/blog_45eaa01a0102vqma.html一 建立Excel 模板文件 templ ...

随机推荐

  1. FX3U-3A-ADP模拟量和数字量之间转换

    简单的例子: 0-10V对应0-8,4-20mA对应0-30 以下是对上面例子的详解: 电压: 电压(0-10V) 0-10V对应着数字量0-4000 数字量与变频器HZ量之间的关系是(4000-0) ...

  2. [NSSRound#1 Basic]basic_check

    打开网站,发现啥也没有: 就用dirsearch扫了一遍.发现还是没有有用信息: 只有再另找方法: 再用nikto扫一次: 发现一个put方法,就用put上传一个一句话木马:可以用插件restlien ...

  3. NW排错

    fist date VM备份失败时: NW server上(linux): > nsradmin >p type : nsr recover > cd /nsr/logs >n ...

  4. angular,vue,react三大框架选型

    三大框架,本质都是基于js的web应用(前端做的都是web应用包括移动)框架,他们都是帮助我们解决问题的工具,具体用哪个,要结合具体场景. 这三者中,Angular的适用领域相对窄一些,React可以 ...

  5. http1.x,http2.0,https分别介绍以及他们的区别

    一.HTTP/1.x Http1.x 缺陷:线程阻塞,在同一时间,同一域名的请求有一定数量限制,超过限制数目的请求会被阻塞 http1.0 缺陷:浏览器与服务器只保持短暂的连接,浏览器的每次请求都需要 ...

  6. go语言写http踩得坑

    1.在运行http时,报错:panic: listen tcp: address xxxx: missing port in address, 初始 代码如下 func HelloWordHander ...

  7. MySQL 数据库表格创建、数据插入及获取插入的 ID:Python 教程

    创建表格 要在MySQL中创建表格,请使用"CREATE TABLE"语句. 确保在创建连接时定义了数据库的名称. 示例创建一个名为 "customers" 的 ...

  8. C语言中strchr()和index()

    一. C标准的一些问题 在ubuntu下rindex()函数使用没有问题,在minGW下会报错,undefined reference to `rindex',warning: implicit de ...

  9. Kafka 集群如何实现数据同步?

    哈喽大家好,我是咸鱼 最近这段时间比较忙,将近一周没更新文章,再不更新我那为数不多的粉丝量就要库库往下掉了 T﹏T 刚好最近在学 Kafka,于是决定写篇跟 Kafka 相关的文章(文中有不对的地方欢 ...

  10. C#使用SqlSugar操作MySQL数据库实现简单的增删改查

    公众号「DotNet学习交流」,分享学习DotNet的点滴. SqlSugar简介 SqlSugar 是一款 老牌 .NET 开源多库架构ORM框架(EF Core单库架构),由果糖大数据科技团队 维 ...