C#winform使用NOPI读取Excel读取图片

打印 上一主题 下一主题

主题 532|帖子 532|积分 1596

需求:在Winform使用NOPI做导入时候,需要导入数据的同时导入图片。
虽然代码方面不适用(我好像也没仔细看过代码),但是感谢大佬给了灵感http://www.wjhsh.net/IT-Ramon-p-13100039.html,将excel后缀修改成Zip,解压,在其中找到图片的xml位置信息,以及对应的xml图片
效果图:

 1、核心读取代码
  1.         System.Data.DataTable dt;
  2.         private void btnImport_Click(object sender, EventArgs e)
  3.         {
  4.             dt = null;
  5.             string copyAfterFileName = DateTime.Now.ToString("yyyyMMddHHssmm");//文件名 以及解压后的文件夹名
  6.             string copyAfterFileNameExt = ".zip";//压缩后缀
  7.             string modelExlPath = Environment.CurrentDirectory + "\\Temp\\Cache";//缓存文件
  8.             if (!Directory.Exists(modelExlPath)) { Directory.CreateDirectory(modelExlPath); }//创建缓存文件夹
  9.             string copyAfterFullName = Path.Combine(modelExlPath, copyAfterFileName + copyAfterFileNameExt);//移动到该目录并改为压缩包
  10.             string copyDirFullName = Path.Combine(modelExlPath, copyAfterFileName);//解压后的文件夹位置
  11.             OpenFileDialog openfile = new OpenFileDialog();
  12.             openfile.Filter = "导入Excel(*.xls,*.xlsx)|*.xls;*.xlsx";
  13.             openfile.FilterIndex = 0;
  14.             openfile.RestoreDirectory = true;
  15.             openfile.Title = "导入文件路径";
  16.             //openfile.ShowDialog();
  17.             if (openfile.ShowDialog() != DialogResult.OK)
  18.             {
  19.                 return;
  20.             }
  21.            Common.ShowWaitForm();//正在加载..窗口
  22.             FileInfo fi1 = new FileInfo(openfile.FileName);
  23.             fi1.CopyTo(copyAfterFullName);//移动文件,并修改称为yyyyMMddHHssmm.zip
  24.             try
  25.             {
  26.                 wsDr wsDrModel = null;
  27.                 if (!Directory.Exists(copyDirFullName)) { Directory.CreateDirectory(copyDirFullName); }
  28.                 //解压到当前文件夹
  29.                 if (SharpZip.UnpackFiles(copyAfterFullName, copyDirFullName) == false)//yyyyMMddHHssmm.zip为文件夹yyyyMMddHHssmm
  30.                 {
  31.                     Common.ShowErrorDialog("导入失败!");
  32.                     LogHelper.Instance.Error("产品导入失败," + copyDirFullName + "自解压失败!");
  33.                     return;
  34.                 }
  35.                 else
  36.                 {
  37.                     wsDrModel = GetImgLoaction(copyDirFullName);//读取excel图片信息,对应位置,对应的绝对路径,对应的图片实体
  38.                 }
  39.                 string msg = "";
  40.                 dt = ExcelUtil.ExcelToTable(openfile.FileName, wsDrModel, ref msg);//获得Excel
  41.                 if (!string.IsNullOrEmpty(msg))
  42.                 {
  43.                    Common.ShowInfoDialog(msg);
  44.                 }
  45.                 if (dt == null || dt.Rows.Count <= 0)
  46.                 {
  47.                    Common.ShowSuccessTip("导入失败!");
  48.                     return;
  49.                 }
  50.                 LoadList();//刷新表格
  51.             }
  52.             catch (Exception ex)
  53.             {
  54.                Common.ShowErrorDialog("导入错误!" + ex.Message);
  55.             }
  56.             finally
  57.             {
  58.                 Common.HideWaitForm();//隐藏正在加载..窗口
  59.             }
  60.         }
  61.         private wsDr GetImgLoaction(string copydirfullname)
  62.         {
  63.             //copydirfullname = "E:\\administrator\\Desktop\\test\\yyyyMMddHHssmm";
  64.             string pathMap = Path.Combine(copydirfullname, "xl\\drawings\\drawing1.xml");
  65.             var doc = XDocument.Load(pathMap);
  66.             //清理大部分命名空间,blip属性中的情况只能手动指定了
  67.             doc.Descendants().Attributes().Where(x => x.IsNamespaceDeclaration).Remove();
  68.             foreach (var elem in doc.Descendants())
  69.             {
  70.                 elem.Name = elem.Name.LocalName;
  71.             }
  72.             doc.Save(pathMap);
  73.             wsDr model = XmlHelper.XmlToModelFile<wsDr>(pathMap);
  74.             Relationships relationships = GetImg(copydirfullname);
  75.             if (model.twoCellAnchorList.Count > 0)
  76.             {
  77.                 //将图片路径,图片实体保存在图片位置表(wsDr)中
  78.                 foreach (var item in model.twoCellAnchorList)
  79.                 {
  80.                     item.pic1.nvPicPr1.cNvPr1.img = relationships.Relationship.SingleOrDefault(a => a.Id == item.pic1.blipFill1.blip1.imgid).img;
  81.                     item.pic1.nvPicPr1.cNvPr1.imgUrl = relationships.Relationship.SingleOrDefault(a => a.Id == item.pic1.blipFill1.blip1.imgid).imgUrl;
  82.                 }
  83.             }
  84.             return model;
  85.         }
  86.         private Relationships GetImg(string copydirfullname)
  87.         {
  88.             string pathMap = Path.Combine(copydirfullname, "xl\\drawings\\_rels\\drawing1.xml.rels");//获取图片所在目录的xml.rels
  89.             FileInfo fi = new FileInfo(pathMap);
  90.             string newpathMap = Path.Combine(copydirfullname, "xl\\drawings\\_rels\\drawing1.xml");//转换为xml,不然不可读取
  91.             if (fi.Exists)
  92.             {
  93.                 fi.MoveTo(newpathMap);
  94.             }
  95.             //代码可用
  96.             var doc = XDocument.Load(newpathMap);
  97.             doc.Descendants().Attributes().Where(x => x.IsNamespaceDeclaration).Remove();//移除大部分命名空间
  98.             foreach (var elem in doc.Descendants())
  99.                 elem.Name = elem.Name.LocalName;
  100.             doc.Save(newpathMap);
  101.             Relationships model = XmlHelper.XmlToModelFile<Relationships>(newpathMap);//获取图片所在目录的xml
  102.             string pathMap1 = Path.Combine(copydirfullname, "xl\\drawings\\drawing1.xml");//../media/image1.png 是以xl/drawings文件夹的基础上,而不是xl/drawings/_rels
  103.             foreach (var item in model.Relationship)
  104.             {
  105.                 string newpath = GetPath(Path.GetFullPath(pathMap1), item.Target);//获取 yyyyMMddHHssmm\xl\drawings target ../media/image1.png 转换为yyyyMMddHHssmm\xl\media\image1.png
  106.                 //保存路径,该路径在上传图片时使用
  107.                 item.imgUrl = newpath;
  108.                 //以流形式读取图片,不占用图片
  109.                 using (var stream = new FileStream(newpath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete))
  110.                 {
  111.                     item.img = Image.FromStream(stream);
  112.                 }
  113.             }
  114.             return model;
  115.         }
  116.         private string GetPath(string sourPath, string path)
  117.         {
  118.             string[] pathT = path.Split('/');
  119.             string newpath = sourPath;
  120.             for (int i = 0; i < pathT.Length; i++)
  121.             {
  122.                 if (pathT[i] == "..")
  123.                 {
  124.                     DirectoryInfo di = new DirectoryInfo(Path.GetDirectoryName(newpath));
  125.                     newpath = di.Parent.FullName;
  126.                 }
  127.                 else
  128.                 {
  129.                     newpath = Path.GetFullPath(Path.Combine(newpath, pathT[i]));
  130.                 }
  131.             }
  132.             return newpath;
  133.         }
复制代码
2、根据xml生成的实体,并处理后
  1.   #region 主要实体
  2.     //实体主要部分,根据xml生成
  3.     [Serializable]
  4.     public class wsDr
  5.     {
  6.         [XmlElement(ElementName = "twoCellAnchor")]//指定节点名称
  7.         public List<twoCellAnchor> twoCellAnchorList { get; set; }
  8.     }
  9.     //读取图片实体
  10.     public class Relationships
  11.     {
  12.         [XmlElement("Relationship")]
  13.         public List<Relationship> Relationship { get; set; }
  14.     }
  15.     #endregion
  16.     #region 其他实体
  17.     public class from
  18.     {
  19.         //这里列名称和节点名称相同,不需要特意指定xml节点名称
  20.         public int col { get; set; }
  21.         public int row { get; set; }
  22.     }
  23.     public class to
  24.     {
  25.         public int col { get; set; }
  26.         public int row { get; set; }
  27.     }
  28.     public class cNvPr
  29.     {
  30.         [XmlAttribute( "id")]
  31.         public string _id { get; set; }
  32.         [XmlAttribute("name")]
  33.         public string _name { get; set; }
  34.         public Image img { get; set; }
  35.         public string imgUrl { get; set; }
  36.     }
  37.     public class blip
  38.     {
  39.         /*手动指定xml命名空间,该命名空间使用..Where(x => x.IsNamespaceDeclaration).Remove()移除不了。
  40.          * 注:xml中这块读取出来后不认为它是命名空间,因为是子级特意指定的
  41.          */
  42.         [XmlAttribute("embed",Namespace= "http://schemas.openxmlformats.org/officeDocument/2006/relationships")]
  43.         public string imgid { get; set; }
  44.     }
  45.     public class blipFill
  46.     {
  47.         [XmlElement("blip")]
  48.         public blip blip1 { get; set; }
  49.     }
  50.     public class nvPicPr
  51.     {
  52.         [XmlElement(ElementName = "cNvPr")]
  53.         public cNvPr cNvPr1 { get; set; }
  54.       
  55.     }
  56.     public class pic
  57.     {
  58.         [XmlElement(ElementName = "nvPicPr")]
  59.         public nvPicPr nvPicPr1 { get; set; }
  60.         [XmlElement("blipFill")]
  61.         public blipFill blipFill1 { get; set; }
  62.     }
  63.     public class twoCellAnchor
  64.     {
  65.         [XmlElement(ElementName = "from")]
  66.         public from from1 { get; set; }
  67.         [XmlElement(ElementName = "to")]
  68.         public to to1 { get; set; }
  69.         [XmlElement(ElementName = "pic")]
  70.         public pic pic1 { get; set; }
  71.     }
  72.   
  73.     public class Relationship
  74.     {
  75.         [XmlAttribute("Id")]
  76.         public string Id { get; set; }
  77.         [XmlAttribute("Target")]
  78.         public string Target { get; set; }
  79.         public Image img { get; set; }
  80.         public string imgUrl { get; set; }
  81.     }
  82.     #endregion
复制代码
3、使用NOPI读取Excel内容
  1. private static ISheet ExcelToSheet(string file)
  2.         {
  3.             IWorkbook workbook;
  4.             string fileExt = Path.GetExtension(file).ToLower();
  5.             using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read))
  6.             {
  7.                 //XSSFWorkbook 适用XLSX格式,HSSFWorkbook 适用XLS格式
  8.                 if (fileExt == ".xlsx") { workbook = new XSSFWorkbook(fs); } else if (fileExt == ".xls") { workbook = new HSSFWorkbook(fs); } else { workbook = null; }
  9.                 if (workbook == null) { return null; }
  10.                 ISheet sheet = workbook.GetSheetAt(0);
  11.                 return sheet;
  12.             }
  13.         }
  14.         /// <summary>
  15.         /// Excel导入成Datable
  16.         /// </summary>
  17.         /// <param name="file">导入路径(包含文件名与扩展名)</param>
  18.         /// <returns></returns>
  19.         public static DataTable ExcelToTable(string file, wsDr wsDrModel, ref string msg)
  20.         {
  21.             try
  22.             {
  23.                 ISheet sheet = ExcelToSheet(file);
  24.                 DataTable dt = new DataTable();
  25.                 //表头  
  26.                 IRow header = sheet.GetRow(sheet.FirstRowNum);
  27.                 //List<int> columns = new List<int>();
  28.                 int columnsCount = 1;
  29.                 dt.Columns.Add(new DataColumn("Id"));
  30.                 dt.Columns.Add(new DataColumn("dnxh"));
  31.                 dt.Columns.Add(new DataColumn("dwxh"));
  32.                 dt.Columns.Add(new DataColumn("zwmc"));
  33.                 dt.Columns.Add(new DataColumn("ywmc"));
  34.                 dt.Columns.Add(new DataColumn("cplx"));
  35.                 dt.Columns.Add(new DataColumn("dw"));
  36.                 dt.Columns.Add(new DataColumn("sfwgcp"));
  37.                 dt.Columns.Add(new DataColumn("sflscp"));
  38.                 dt.Columns.Add(new DataColumn("mlj"));
  39.                 dt.Columns.Add(new DataColumn("Img", typeof(Image)));
  40.                 dt.Columns.Add(new DataColumn("cpcc"));
  41.                 dt.Columns.Add(new DataColumn("cpjz"));
  42.                 dt.Columns.Add(new DataColumn("ImgUrl"));
  43.                 for (int i = 1; i <= sheet.LastRowNum; i++)
  44.                 {
  45.                     DataRow dr = dt.NewRow();
  46.                     object dnxh = sheet.GetRow(i).GetCell(0).GetRealValue();//对内型号
  47.                     if (dnxh == null || string.IsNullOrEmpty(dnxh.ToString()))
  48.                     {
  49.                         msg += "请填写第" + i + "行的【对内型号】!";
  50.                         break;
  51.                     }
  52.                     dr["dnxh"] = dnxh;
  53.                     object dwxh = sheet.GetRow(i).GetCell(1).GetRealValue();//对外型号
  54.                     if (dwxh == null || string.IsNullOrEmpty(dwxh.ToString()))
  55.                     {
  56.                         msg += "请填写第" + i + "行的【对外型号】!";
  57.                         break;
  58.                     }
  59.                     dr["dwxh"] = dwxh;
  60.                     object zwmc = sheet.GetRow(i).GetCell(2).GetRealValue();//zwmc
  61.                     if (zwmc == null || string.IsNullOrEmpty(zwmc.ToString()))
  62.                     {
  63.                         msg += "请填写第" + i + "行的【中文名称】!";
  64.                         break;
  65.                     }
  66.                     dr["zwmc"] = zwmc;
  67.                     object ywmc = sheet.GetRow(i).GetCell(3).GetRealValue();//英文名称
  68.                     if (ywmc == null || string.IsNullOrEmpty(ywmc.ToString()))
  69.                     {
  70.                         msg += "请填写第" + i + "行的【英文名称】!";
  71.                         break;
  72.                     }
  73.                     dr["ywmc"] = ywmc;
  74.                     object cplx = sheet.GetRow(i).GetCell(4).GetRealValue();//产品类型
  75.                     if (cplx == null || string.IsNullOrEmpty(cplx.ToString()))
  76.                     {
  77.                         msg += "请填写第" + i + "行的【产品类型】!";
  78.                         break;
  79.                     }
  80.                     dr["cplx"] = cplx;
  81.                     object dw = sheet.GetRow(i).GetCell(5).GetRealValue();//单位
  82.                     if (dw == null || string.IsNullOrEmpty(dw.ToString()))
  83.                     {
  84.                         msg += "请填写第" + i + "行的【单位】!";
  85.                         break;
  86.                     }
  87.                     dr["dw"] = dw;
  88.                     object sfwgcp = sheet.GetRow(i).GetCell(6).GetRealValue();//是否外购
  89.                     if (sfwgcp == null)
  90.                     {
  91.                         msg += "请填写第" + i + "行的【是否外购】!";
  92.                         break;
  93.                     }
  94.                     if (sfwgcp.ToString() != "自制" && sfwgcp.ToString() != "外购")
  95.                     {
  96.                         msg += "请填写第" + i + "行的【是否外购】自制/外购,请勿填写其他内容!";
  97.                         break;
  98.                     }
  99.                     dr["sfwgcp"] = sfwgcp;
  100.                     object sflscp = sheet.GetRow(i).GetCell(7).GetRealValue();//是否临时产品
  101.                     if (sflscp == null)
  102.                     {
  103.                         msg += "请填写第" + i + "行的【是否临时产品】!";
  104.                         break;
  105.                     }
  106.                     if (sflscp.ToString() != "是" && sflscp.ToString() != "否")
  107.                     {
  108.                         msg += "请填写第" + i + "行的【是否临时产品】是/否,请勿填写其他内容!";
  109.                         break;
  110.                     }
  111.                     dr["sflscp"] = sflscp;
  112.                     object mljobj = sheet.GetRow(i).GetCell(8).GetRealValue();//目录价
  113.                     decimal mlj = 0;
  114.                     if (mljobj != null)
  115.                     {
  116.                         if (!decimal.TryParse(mljobj.ToString(), out mlj))
  117.                         {
  118.                             msg += "第" + i + "行的【目录价】数值错误,请正确填写!";
  119.                             break;
  120.                         }
  121.                     }
  122.                     dr["mlj"] = mlj;
  123.                     object cpcc = sheet.GetRow(i).GetCell(10).GetRealValue();//产品尺寸
  124.                     dr["cpcc"] = cpcc;
  125.                     object cpjz = sheet.GetRow(i).GetCell(11).GetRealValue();//净重
  126.                     dr["cpjz"] = cpjz;
  127.                     dr["id"] = Guid.NewGuid().ToString();
  128.                     //-----------获取图片
  129.                     //产品主图 第9列
  130.                     int col = 9;
  131.                     if (wsDrModel != null && wsDrModel.twoCellAnchorList.Count > 0)
  132.                     {
  133.                         var list = wsDrModel.twoCellAnchorList.Where(a => i >= a.from1.row && col >= a.from1.col && i <= a.to1.row && col <= a.to1.col).ToList();
  134.                         if (list.Count > 0)
  135.                         {
  136.                             dr["Img"] = (Image)list[0].pic1.nvPicPr1.cNvPr1.img;
  137.                             dr["ImgUrl"] = list[0].pic1.nvPicPr1.cNvPr1.imgUrl;
  138.                         }
  139.                     }
  140.                     //XmlHelper.SetValue
  141.                     //XmlHelper.XmlToModel<>(pathMap);
  142.                     //-----------
  143.                     dt.Rows.Add(dr);
  144.                 }
  145.                 return dt;
  146.             }
  147.             catch (Exception ex)
  148.             {
  149.                 LogHelper.Instance.Info(ex.ToString());
  150.                 throw ex;
  151.             }
  152.         }
复制代码
过程:
将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
版权:本文版权归作者和博客园共有
转载:欢迎转载,但未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

美丽的神话

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表