C#導(dǎo)入EXCEL時如何讀取單元格中的圖片(WPS)
C#導(dǎo)入EXCEL時讀取單元格中的圖片(WPS)
起因
最新要做一個excel批量導(dǎo)入商品的功能,但是文本內(nèi)容好讀取,但是圖片文件在網(wǎng)上沒有找到比較好的解決辦法
解決方案1
(不推薦)先導(dǎo)入excel數(shù)據(jù),再通過文件夾/壓縮包的方式導(dǎo)入圖片,但是這樣比較麻煩,如果說excel表格后續(xù)還需要維護(hù)的話,對于做excel表格的同學(xué)來說不太友好
解決方案2
解壓縮excel文件,可以得到對應(yīng)的文件夾,如下圖所示的內(nèi)容,其中xl文件夾下存在幾個數(shù)據(jù)文件,可以手動拼接起來,下面著重說一下該如何一步步實現(xiàn)指定單元格的文件讀取
1)上傳excel文件
定義好接受類,我的類是這樣,可以根據(jù)自己需要進(jìn)行修改
/// <summary> /// 導(dǎo)入產(chǎn)品dto /// </summary> public class ImportSoftProductDto:PrimaryKey { /// <summary> /// 供應(yīng)商編號 /// </summary> [ExcelColumnIndex("A")] public string SupplierNo { get; set; } /// <summary> /// 產(chǎn)品編號 /// </summary> [ExcelColumnIndex("B")] public string ProductNo { get; set; } /// <summary> /// 產(chǎn)品名稱 /// </summary> [ExcelColumnIndex("C")] public string ProductName { get; set; } /// <summary> /// 主分類 /// </summary> [ExcelColumnIndex("D")] public string MainCategory { get; set; } /// <summary> /// 次分類 /// </summary> [ExcelColumnIndex("E")] public string SubCategory { get; set; } /// <summary> /// 采購單價 /// </summary> [ExcelColumnIndex("F")] public decimal PurchasePrice { get; set; } /// <summary> /// 銷售單價 /// </summary> [ExcelColumnIndex("G")] public decimal SalesPrice { get; set; } /// <summary> /// 單位 /// </summary> [ExcelColumnIndex("H")] public string Unit { get; set; } /// <summary> /// 尺寸 /// </summary> [ExcelColumnIndex("I")] public string Size { get; set; } /// <summary> /// 材質(zhì)報價 /// </summary> [ExcelColumnIndex("J")] public string Texture { get; set; } /// <summary> /// 備注說明 /// </summary> [ExcelColumnIndex("K")] public string Explain { get; set; } /// <summary> /// 圖片_DISPIMG函數(shù)字符串 /// </summary> [ExcelColumnIndex("L")] public string IMG_DISPIMG { get; set; } //= DISPIMG("ID_498B62A4F63D447D9F9E1640DAF57A45", 1) public string DISPIMG_Id { get { if (!string.IsNullOrWhiteSpace(IMG_DISPIMG)) { var split = IMG_DISPIMG.Split('"'); return split[1]; } else { return ""; } } } /// <summary> /// 圖片原始路徑 /// </summary> public string ImgOriginalUrl { get; set; } /// <summary> /// 圖片最終路徑 /// </summary> public string ImgFinalUrl { get; set; } public string ImgSuffix { get { if (!string.IsNullOrWhiteSpace(ImgOriginalUrl)) { return Path.GetExtension(ImgOriginalUrl).ToLower().Replace(".", ""); } else { return string.Empty; } } } }
2)讀取excel文件內(nèi)容,這里使用的是MiniExcel,可以在nuget中安裝
注意:wps嵌入的圖片可以通過string得到如下的字符串=DISPIMG("ID_8C72DF5CE3FA413298278785876E9D65",1),其中,ID_8C72DF5CE3FA413298278785876E9D65是我們需要的東東
var rows = MiniExcel.Query<ImportSoftProductDto>(absoluteUrl, startCell: "A3").ToList();
3)解壓縮excel
需要用到命名空間:System.IO.Compression,這里,我是直接以該excel的文件名作為解壓文件夾的
var zipFileDirectory = absoluteUrl.Substring(0, absoluteUrl.LastIndexOf(".")); ZipFile.ExtractToDirectory(absoluteUrl, zipFileDirectory);
4)讀取cellimages.xml內(nèi)容,該文件位于xl文件夾下
var cellimagesXML = File.ReadAllText(Path.Combine(zipFileDirectory, "xl/cellimages.xml"));
5)讀取cellimages.xml.rels內(nèi)容
var cellimagesXMLRels = File.ReadAllText(Path.Combine(zipFileDirectory, "xl/_rels/cellimages.xml.rels"));
6)結(jié)合2個文件內(nèi)容和圖片資源名稱
計算出第二步中ID_8C72DF5CE3FA413298278785876E9D65對應(yīng)的圖片,這里也可以自己解析xml內(nèi)容,主要是為了獲得他們直接的對應(yīng)關(guān)系
var imgList = new List<ImportSoftProductImgDto>(); var nodes_XML = XElement.Parse(cellimagesXML); foreach (var xNode in nodes_XML.DescendantNodes().OfType<XCData>().ToList()) { xNode.Parent.Add(xNode.Value); xNode.Remove(); } var json_XML = JObject.Parse(JsonConvert.SerializeXNode(nodes_XML, Formatting.Indented)); foreach (var item in json_XML["etc:cellImages"]["etc:cellImage"]) { var DISPIMG_Id = item["xdr:pic"]["xdr:nvPicPr"]["xdr:cNvPr"]["@name"].ToString(); var id = item["xdr:pic"]["xdr:blipFill"]["a:blip"]["@r:embed"].ToString(); imgList.Add(new ImportSoftProductImgDto { Id = id, Target = string.Empty, DISPIMG_Id = DISPIMG_Id }); } var nodes_XMLRels = XElement.Parse(cellimagesXMLRels); foreach (var xNode in nodes_XMLRels.DescendantNodes().OfType<XCData>().ToList()) { xNode.Parent.Add(xNode.Value); xNode.Remove(); } var json_XMLRels = JObject.Parse(JsonConvert.SerializeXNode(nodes_XMLRels, Formatting.Indented)); foreach (var item in json_XMLRels["Relationships"]["Relationship"]) { var id = item["@Id"].ToString(); var target = item["@Target"].ToString(); //可能公用一張圖片 foreach (var imgItem in imgList.Where(o => o.Id == id)) { imgItem.Target = target; } }
7)遍歷賦值圖片路徑
foreach (var item in rows) { item.ImgOriginalUrl = imgList.FirstOrDefault(o => o.DISPIMG_Id == item.DISPIMG_Id)?.Target; }
8)接下來就是圖片上傳到新地址的方式了
這里是我的上傳實現(xiàn)
foreach (var item in rows) { if (!string.IsNullOrWhiteSpace(item.ImgOriginalUrl)) { var suffix = Path.GetExtension(item.ImgOriginalUrl).ToLower().Replace(".", "");//文件后綴 var relativePath = Path.Combine("uploads", suffix, DateTime.Now.ToString("yyyyMM"));//相對路徑 var fileName = Guid.NewGuid().ToString("N") + "." + suffix;//圖片重命名 var absolutePath = Path.Combine(App.HostEnvironment.ContentRootPath, relativePath);//絕對路徑 if (!Directory.Exists(absolutePath)) { Directory.CreateDirectory(absolutePath); } FileInfo file = new FileInfo(Path.Combine(zipFileDirectory, "xl", item.ImgOriginalUrl)); if (file.Exists) //可以判斷源文件是否存在 { // 這里是true的話覆蓋 file.CopyTo(Path.Combine(absolutePath, fileName), true); item.ImgFinalUrl = Path.Combine(_appInfo.Host, relativePath, fileName).Replace("\\", "/"); } } }
9)至此,就可以往數(shù)據(jù)庫里插入數(shù)據(jù)了
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
c# 網(wǎng)址壓縮簡單實現(xiàn)短網(wǎng)址
短網(wǎng)址,忽然一下子就冒出來的東西,長長的一個URL,提交過去,出來就只有短短的一個URL了,看起來似乎挺神奇,其實簡單分析一下,明白其中的原理,也是一件很簡單的事情,需要的朋友可以了解下2012-12-12c# 實現(xiàn)IComparable、IComparer接口、Comparer類的詳解
本篇文章是對c#中實現(xiàn)IComparable、IComparer接口、Comparer類進(jìn)行了詳細(xì)的分析詳解,需要的朋友參考下2013-05-05