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#調(diào)用執(zhí)行外部程序的實現(xiàn)方法
這篇文章主要介紹了C#調(diào)用執(zhí)行外部程序的實現(xiàn)方法,涉及C#進(jìn)程調(diào)用的相關(guān)使用技巧,非常簡單實用,需要的朋友可以參考下2015-04-04
C# 調(diào)用 Win32 API的實現(xiàn)示例
Win32 API是微軟為 Windows 操作系統(tǒng)提供的底層編程接口,包含了操作系統(tǒng)的核心功能,本文就來詳細(xì)的介紹一下C# 調(diào)用 Win32 API的實現(xiàn)示例,感興趣的可以了解一下2026-01-01
C# 使用動態(tài)庫DllImport("kernel32")讀寫ini文件的步驟
kernel32.dll是Windows中非常重要的32位動態(tài)鏈接庫文件,屬于內(nèi)核級文件,這篇文章主要介紹了C# 利用動態(tài)庫DllImport("kernel32")讀寫ini文件,需要的朋友可以參考下2023-05-05

