C#winform使用NOPI读取Excel读取图片
需求:在Winform使用NOPI做导入时候,需要导入数据的同时导入图片。
虽然代码方面不适用(我好像也没仔细看过代码),但是感谢大佬给了灵感http://www.wjhsh.net/IT-Ramon-p-13100039.html,将excel后缀修改成Zip,解压,在其中找到图片的xml位置信息,以及对应的xml图片
效果图:
1、核心读取代码
System.Data.DataTable dt;
private void btnImport_Click(object sender, EventArgs e)
{
dt = null;
string copyAfterFileName = DateTime.Now.ToString("yyyyMMddHHssmm");//文件名 以及解压后的文件夹名
string copyAfterFileNameExt = ".zip";//压缩后缀
string modelExlPath = Environment.CurrentDirectory + "\\Temp\\Cache";//缓存文件
if (!Directory.Exists(modelExlPath)) { Directory.CreateDirectory(modelExlPath); }//创建缓存文件夹
string copyAfterFullName = Path.Combine(modelExlPath, copyAfterFileName + copyAfterFileNameExt);//移动到该目录并改为压缩包
string copyDirFullName = Path.Combine(modelExlPath, copyAfterFileName);//解压后的文件夹位置 OpenFileDialog openfile = new OpenFileDialog();
openfile.Filter = "导入Excel(*.xls,*.xlsx)|*.xls;*.xlsx";
openfile.FilterIndex = 0;
openfile.RestoreDirectory = true;
openfile.Title = "导入文件路径";
//openfile.ShowDialog();
if (openfile.ShowDialog() != DialogResult.OK)
{
return;
} Common.ShowWaitForm();//正在加载..窗口
FileInfo fi1 = new FileInfo(openfile.FileName);
fi1.CopyTo(copyAfterFullName);//移动文件,并修改称为yyyyMMddHHssmm.zip try
{
wsDr wsDrModel = null;
if (!Directory.Exists(copyDirFullName)) { Directory.CreateDirectory(copyDirFullName); }
//解压到当前文件夹
if (SharpZip.UnpackFiles(copyAfterFullName, copyDirFullName) == false)//yyyyMMddHHssmm.zip为文件夹yyyyMMddHHssmm
{
Common.ShowErrorDialog("导入失败!");
LogHelper.Instance.Error("产品导入失败," + copyDirFullName + "自解压失败!");
return;
}
else
{
wsDrModel = GetImgLoaction(copyDirFullName);//读取excel图片信息,对应位置,对应的绝对路径,对应的图片实体
} string msg = "";
dt = ExcelUtil.ExcelToTable(openfile.FileName, wsDrModel, ref msg);//获得Excel
if (!string.IsNullOrEmpty(msg))
{
Common.ShowInfoDialog(msg);
}
if (dt == null || dt.Rows.Count <= 0)
{
Common.ShowSuccessTip("导入失败!");
return;
}
LoadList();//刷新表格
}
catch (Exception ex)
{
Common.ShowErrorDialog("导入错误!" + ex.Message);
}
finally
{
Common.HideWaitForm();//隐藏正在加载..窗口
}
} private wsDr GetImgLoaction(string copydirfullname)
{
//copydirfullname = "E:\\administrator\\Desktop\\test\\yyyyMMddHHssmm";
string pathMap = Path.Combine(copydirfullname, "xl\\drawings\\drawing1.xml");
var doc = XDocument.Load(pathMap);
//清理大部分命名空间,blip属性中的情况只能手动指定了
doc.Descendants().Attributes().Where(x => x.IsNamespaceDeclaration).Remove();
foreach (var elem in doc.Descendants())
{
elem.Name = elem.Name.LocalName;
}
doc.Save(pathMap);
wsDr model = XmlHelper.XmlToModelFile<wsDr>(pathMap);
Relationships relationships = GetImg(copydirfullname); if (model.twoCellAnchorList.Count > 0)
{
//将图片路径,图片实体保存在图片位置表(wsDr)中
foreach (var item in model.twoCellAnchorList)
{
item.pic1.nvPicPr1.cNvPr1.img = relationships.Relationship.SingleOrDefault(a => a.Id == item.pic1.blipFill1.blip1.imgid).img;
item.pic1.nvPicPr1.cNvPr1.imgUrl = relationships.Relationship.SingleOrDefault(a => a.Id == item.pic1.blipFill1.blip1.imgid).imgUrl;
}
}
return model;
}
private Relationships GetImg(string copydirfullname)
{
string pathMap = Path.Combine(copydirfullname, "xl\\drawings\\_rels\\drawing1.xml.rels");//获取图片所在目录的xml.rels
FileInfo fi = new FileInfo(pathMap); string newpathMap = Path.Combine(copydirfullname, "xl\\drawings\\_rels\\drawing1.xml");//转换为xml,不然不可读取
if (fi.Exists)
{
fi.MoveTo(newpathMap);
} //代码可用
var doc = XDocument.Load(newpathMap);
doc.Descendants().Attributes().Where(x => x.IsNamespaceDeclaration).Remove();//移除大部分命名空间
foreach (var elem in doc.Descendants())
elem.Name = elem.Name.LocalName;
doc.Save(newpathMap); Relationships model = XmlHelper.XmlToModelFile<Relationships>(newpathMap);//获取图片所在目录的xml
string pathMap1 = Path.Combine(copydirfullname, "xl\\drawings\\drawing1.xml");//../media/image1.png 是以xl/drawings文件夹的基础上,而不是xl/drawings/_rels
foreach (var item in model.Relationship)
{
string newpath = GetPath(Path.GetFullPath(pathMap1), item.Target);//获取 yyyyMMddHHssmm\xl\drawings target ../media/image1.png 转换为yyyyMMddHHssmm\xl\media\image1.png
//保存路径,该路径在上传图片时使用
item.imgUrl = newpath;
//以流形式读取图片,不占用图片
using (var stream = new FileStream(newpath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete))
{
item.img = Image.FromStream(stream);
}
}
return model;
}
private string GetPath(string sourPath, string path)
{
string[] pathT = path.Split('/');
string newpath = sourPath;
for (int i = 0; i < pathT.Length; i++)
{ if (pathT[i] == "..")
{
DirectoryInfo di = new DirectoryInfo(Path.GetDirectoryName(newpath)); newpath = di.Parent.FullName;
}
else
{
newpath = Path.GetFullPath(Path.Combine(newpath, pathT[i]));
}
}
return newpath;
}
2、根据xml生成的实体,并处理后
#region 主要实体
//实体主要部分,根据xml生成
[Serializable]
public class wsDr
{
[XmlElement(ElementName = "twoCellAnchor")]//指定节点名称
public List<twoCellAnchor> twoCellAnchorList { get; set; } }
//读取图片实体
public class Relationships
{
[XmlElement("Relationship")]
public List<Relationship> Relationship { get; set; } }
#endregion
#region 其他实体
public class from
{
//这里列名称和节点名称相同,不需要特意指定xml节点名称
public int col { get; set; }
public int row { get; set; } }
public class to
{
public int col { get; set; }
public int row { get; set; }
}
public class cNvPr
{
[XmlAttribute( "id")]
public string _id { get; set; }
[XmlAttribute("name")]
public string _name { get; set; }
public Image img { get; set; }
public string imgUrl { get; set; }
}
public class blip
{
/*手动指定xml命名空间,该命名空间使用..Where(x => x.IsNamespaceDeclaration).Remove()移除不了。
* 注:xml中这块读取出来后不认为它是命名空间,因为是子级特意指定的
*/
[XmlAttribute("embed",Namespace= "http://schemas.openxmlformats.org/officeDocument/2006/relationships")]
public string imgid { get; set; } }
public class blipFill
{
[XmlElement("blip")]
public blip blip1 { get; set; } }
public class nvPicPr
{
[XmlElement(ElementName = "cNvPr")]
public cNvPr cNvPr1 { get; set; } }
public class pic
{
[XmlElement(ElementName = "nvPicPr")]
public nvPicPr nvPicPr1 { get; set; }
[XmlElement("blipFill")]
public blipFill blipFill1 { get; set; }
}
public class twoCellAnchor
{
[XmlElement(ElementName = "from")]
public from from1 { get; set; }
[XmlElement(ElementName = "to")]
public to to1 { get; set; }
[XmlElement(ElementName = "pic")]
public pic pic1 { get; set; } } public class Relationship
{
[XmlAttribute("Id")]
public string Id { get; set; }
[XmlAttribute("Target")]
public string Target { get; set; }
public Image img { get; set; }
public string imgUrl { get; set; }
}
#endregion
3、使用NOPI读取Excel内容
private static ISheet ExcelToSheet(string file)
{
IWorkbook workbook;
string fileExt = Path.GetExtension(file).ToLower();
using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read))
{
//XSSFWorkbook 适用XLSX格式,HSSFWorkbook 适用XLS格式
if (fileExt == ".xlsx") { workbook = new XSSFWorkbook(fs); } else if (fileExt == ".xls") { workbook = new HSSFWorkbook(fs); } else { workbook = null; }
if (workbook == null) { return null; }
ISheet sheet = workbook.GetSheetAt(0);
return sheet;
}
}
/// <summary>
/// Excel导入成Datable
/// </summary>
/// <param name="file">导入路径(包含文件名与扩展名)</param>
/// <returns></returns>
public static DataTable ExcelToTable(string file, wsDr wsDrModel, ref string msg)
{
try
{
ISheet sheet = ExcelToSheet(file);
DataTable dt = new DataTable();
//表头
IRow header = sheet.GetRow(sheet.FirstRowNum);
//List<int> columns = new List<int>();
int columnsCount = 1;
dt.Columns.Add(new DataColumn("Id"));
dt.Columns.Add(new DataColumn("dnxh"));
dt.Columns.Add(new DataColumn("dwxh"));
dt.Columns.Add(new DataColumn("zwmc"));
dt.Columns.Add(new DataColumn("ywmc"));
dt.Columns.Add(new DataColumn("cplx"));
dt.Columns.Add(new DataColumn("dw"));
dt.Columns.Add(new DataColumn("sfwgcp"));
dt.Columns.Add(new DataColumn("sflscp"));
dt.Columns.Add(new DataColumn("mlj"));
dt.Columns.Add(new DataColumn("Img", typeof(Image)));
dt.Columns.Add(new DataColumn("cpcc"));
dt.Columns.Add(new DataColumn("cpjz"));
dt.Columns.Add(new DataColumn("ImgUrl")); for (int i = 1; i <= sheet.LastRowNum; i++)
{
DataRow dr = dt.NewRow();
object dnxh = sheet.GetRow(i).GetCell(0).GetRealValue();//对内型号
if (dnxh == null || string.IsNullOrEmpty(dnxh.ToString()))
{
msg += "请填写第" + i + "行的【对内型号】!";
break;
}
dr["dnxh"] = dnxh;
object dwxh = sheet.GetRow(i).GetCell(1).GetRealValue();//对外型号
if (dwxh == null || string.IsNullOrEmpty(dwxh.ToString()))
{
msg += "请填写第" + i + "行的【对外型号】!";
break;
}
dr["dwxh"] = dwxh;
object zwmc = sheet.GetRow(i).GetCell(2).GetRealValue();//zwmc
if (zwmc == null || string.IsNullOrEmpty(zwmc.ToString()))
{
msg += "请填写第" + i + "行的【中文名称】!";
break;
}
dr["zwmc"] = zwmc;
object ywmc = sheet.GetRow(i).GetCell(3).GetRealValue();//英文名称
if (ywmc == null || string.IsNullOrEmpty(ywmc.ToString()))
{
msg += "请填写第" + i + "行的【英文名称】!";
break;
}
dr["ywmc"] = ywmc;
object cplx = sheet.GetRow(i).GetCell(4).GetRealValue();//产品类型
if (cplx == null || string.IsNullOrEmpty(cplx.ToString()))
{
msg += "请填写第" + i + "行的【产品类型】!";
break;
}
dr["cplx"] = cplx;
object dw = sheet.GetRow(i).GetCell(5).GetRealValue();//单位
if (dw == null || string.IsNullOrEmpty(dw.ToString()))
{
msg += "请填写第" + i + "行的【单位】!";
break;
}
dr["dw"] = dw;
object sfwgcp = sheet.GetRow(i).GetCell(6).GetRealValue();//是否外购
if (sfwgcp == null)
{
msg += "请填写第" + i + "行的【是否外购】!";
break;
}
if (sfwgcp.ToString() != "自制" && sfwgcp.ToString() != "外购")
{
msg += "请填写第" + i + "行的【是否外购】自制/外购,请勿填写其他内容!";
break;
}
dr["sfwgcp"] = sfwgcp;
object sflscp = sheet.GetRow(i).GetCell(7).GetRealValue();//是否临时产品
if (sflscp == null)
{
msg += "请填写第" + i + "行的【是否临时产品】!";
break;
}
if (sflscp.ToString() != "是" && sflscp.ToString() != "否")
{
msg += "请填写第" + i + "行的【是否临时产品】是/否,请勿填写其他内容!";
break;
}
dr["sflscp"] = sflscp;
object mljobj = sheet.GetRow(i).GetCell(8).GetRealValue();//目录价
decimal mlj = 0;
if (mljobj != null)
{
if (!decimal.TryParse(mljobj.ToString(), out mlj))
{
msg += "第" + i + "行的【目录价】数值错误,请正确填写!";
break;
}
}
dr["mlj"] = mlj;
object cpcc = sheet.GetRow(i).GetCell(10).GetRealValue();//产品尺寸
dr["cpcc"] = cpcc;
object cpjz = sheet.GetRow(i).GetCell(11).GetRealValue();//净重
dr["cpjz"] = cpjz;
dr["id"] = Guid.NewGuid().ToString();
//-----------获取图片
//产品主图 第9列
int col = 9;
if (wsDrModel != null && wsDrModel.twoCellAnchorList.Count > 0)
{
var list = wsDrModel.twoCellAnchorList.Where(a => i >= a.from1.row && col >= a.from1.col && i <= a.to1.row && col <= a.to1.col).ToList();
if (list.Count > 0)
{
dr["Img"] = (Image)list[0].pic1.nvPicPr1.cNvPr1.img;
dr["ImgUrl"] = list[0].pic1.nvPicPr1.cNvPr1.imgUrl; }
}
//XmlHelper.SetValue
//XmlHelper.XmlToModel<>(pathMap);
//-----------
dt.Rows.Add(dr);
}
return dt;
}
catch (Exception ex)
{
LogHelper.Instance.Info(ex.ToString());
throw ex;
}
}
4、保存信息
private void btnSave_Click(object sender, EventArgs e)
{
List<Model.Product> listProduct = new List<Model.Product>(); foreach (DataRow item in dt.Rows)
{
Model.Product model = new Model.Product();
//组建信息保存到实体
listProduct.Add(model);
}
if (listProduct.Count <= 0)
{
Common.ShowInfoTip("没有需要保存的信息!请先导入");
return;
}
Loading2.Show(this, new Action(() => UpLoadImage(listProduct)), new Action(() => this.Close()));//这个Loading异步加载在其他文章有
}
bool isSuccess = false;
private void UpLoadImage(List<Model.Product> listProduct)
{
List<CommandInfo> commandInfos = new List<CommandInfo>();
foreach (var item in listProduct)
{
item.Cpzp = CommonUtil.UploadFile(item.Cpzp);//上传后转换成服务器路径 \\Upload\Image\202211030918546.png commandInfos.Add(BLLService.Instance.BaseProducts.AddSql(item));
}
try
{
if (BLLService.DoTran(commandInfos))//事务执行insert产品信息
{
Common.ShowSuccessTip("导入成功!");
dt = null;
isSuccess = true;
}
else
{
Common.ShowErrorDialog("导入失败!");
}
}
catch (Exception ex)
{
LogHelper.Instance.Error("导入失败!" + ex);
Common.ShowErrorDialog("导入失败!" + ex);
}
}
过程:
将Excel后缀换成zip解压得到文件夹。
其中xl\drawings\drawing1.xml记录了图片位置信息和id。对应xl\drawings\_rels\drawing1.xml.rels中图片位置和名称
根据图片位置,找到xl\media\image1.png
作者:兮去博客
出处:https://www.cnblogs.com/bklsj/p/16784749.html
版权:本文版权归作者和博客园共有
转载:欢迎转载,但未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任
C#winform使用NOPI读取Excel读取图片的更多相关文章
- PHP读取Excel内的图片
今天接到了一个从Excel内读取图片的需求,在网上查找了一些资料,基本实现了自己的需求,不过由于查到的一些代码比较久远,不能直接移植到自己的项目里,需要稍加改动一下. 这里介绍一下分别使用phpspr ...
- 10.ODBC创建/读取Excel QT4
看到一篇MFC的参考链接:https://blog.csdn.net/u012319493/article/details/50561046 改用QT的函数即可 创建Excel //创建Excel v ...
- Aspose.cells 读取Excel表中的图片问题
一.说明 本文主要是讲解,怎么使用aspose.cells读取Excel表中的图片,并把图片转换成流或是image对象. 二.开发环境说明 开发工具vs2012,c#语言, 三.Aspose.cell ...
- Open Xml 读取Excel中的图片
在我的一个项目中,需要分析客户提供的Excel, 读出其中的图片信息(显示在Excel的第几行,第几列,以及图片本身). 网络上有许多使用Open Xml插入图片到Word,Excel的文章, 但 ...
- Python读取excel中的图片
作为Java程序员,Java自然是最主要的编程语言.但是Java适合完成大型项目,对于平时工作中小的工作任务,需要快速完成,易于修改和调试,使用Java显得很繁琐,需要进行类的设计,打成jar包,出现 ...
- poi读取Excel文件和图片
首先得说一下,Excel文件是有03版和07版的区别的,也就是.xls和.xlsx,这两个文件需要分开读取. 其它的废话就不说了,直接贴代码: package util; import java.io ...
- winform下读取excel文件并绑定datagridview例子
首先我要读取这个excel文件然后生成Datable 用winform编程的方式 前台界面: 后台的代码 using System; using System.Collections.Generic; ...
- WinForm 读取Excel 数据显示到窗体中
最近教学中,需要用到WinForm 读取Excel数据,于是就做了一个简单的,废话不多说,直接codding... //读取Excel的帮助类 class SqExcellHelper { publi ...
- java--poi读取excel图片和内容(支持03版本)
有的时候需要将excel中所包含的图片在导入的时候取出来存到服务器中, 详细实现代码如下: package com.liuf.util; import java.io.BufferedInputStr ...
- thinkphp用phpexcel读取excel,并修改列中的值,再导出excel,带往excel里写入图片
<?php class GetpriceAction extends AdministratorAction { // 文件保存路径 protected $savepath; // 允许上传的文 ...
随机推荐
- Windows编程之线程同步
本笔记整理自:<Windows核心编程(第五版)> 目录 什么是线程同步 用户方式中的线程同步 原子访问:Interlocked系列函数 CRITICAL_SECTION:关键段 内核对象 ...
- sklearn中MLPClassifier源码解析
神经网络 .fit() 首先传入类私用方法._fit() 确定hidden_layer_size是可迭代的 调用_validate_hyperparameters验证超参数是否合法 验证输入的x和y是 ...
- 新增一个Redis 从节点为什么与主节点的key数量不一样呢?
在日常的 Redis 运维过程中,经常会发生重载 RDB 文件操作,主要情形有: 主从架构如果主库宕机做高可用切换,原从库会挂载新主库重新获取数据 主库 QPS 超过10万,需要做读写分离,重新添加从 ...
- Linux下进行Oracle数据库安装
一般来说我们Windows下进行安装Oracle都很简单,但Linux下却要输入很多命令,以下的安装步骤是本人经过多次安装Linux下的Oracle经验,希望能帮到大家 一.在Linux服务器上创建o ...
- k8s-ingress配置websocket支持
具体来说,使用的ingress-controller不一样,有关的设置也不太一样 Kubernetes Ingress Controller (k8s官方) 参考 http://github.com/ ...
- 第二章:视图层 - 10:动态生成PDF文件
可以通过开源的Python PDF库ReportLab来实现PDF文件的动态生成. 一.安装ReportLab ReportLab库在PyPI上提供,可以使用pip来安装: $ pip install ...
- 9. Fluentd部署:日志
Fluentd是用来处理其他系统产生的日志的,它本身也会产生一些运行时日志.Fluentd包含两个日志层:全局日志和插件级日志.每个层次的日志都可以进行单独配置. 日志级别 Fluentd的日志包含6 ...
- 1_Linux
一. Linux介绍 1.1 引言 在学习Linux之前, 大家先了解开发环境,生产,测试环境 开发环境: 平时大家大多是在Windows或者Mac操作系统下去编写代码进行开发,在开发环境中安装大量的 ...
- js动态获取当前时间(年、月、日、上午/下午、时、分、秒)
//获取动态时间function mytime() { var mydate = new Date(); var year = mydate.getFullYear(); var month = my ...
- 【Java8新特性】- Optional应用
Java8新特性 - Optional应用 生命不息,写作不止 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 一个有梦有戏的人 @怒放吧德德 分享学习心得,欢迎指正,大家一起学习成长! ...