OpenXml Excel:在邮件地址之后的任何字中引发错误

我使用OpenXml读取Excel文件。 所有工作正常,但如果电子表格包含一个单元格有一个地址邮件,并在其后面有一个空格和另一个单词,如:

abc@abc.com abc

它在电子表格开始时立即引发exception:

var _doc = SpreadsheetDocument.Open(_filePath, false); 

例外:

DocumentFormat.OpenXml.Packaging.OpenXmlPackageException
附加信息:
无效的超链接:格式错误的URI作为超文本链接embedded到文档中。

在与此问题相关的OpenXml论坛上有一个公开的问题: 格式错误的超链接导致exception

在这篇文章中,他们讨论了在Word文档中遇到一个格式错误的“mailto:”超链接的问题。

他们提出了一个解决方法 : 解决畸形的超链接exception

解决方法本质上是一个小的控制台应用程序,它定位无效的URL并用硬编码的值replace它; 这里是他们的样本代码片段,replace; 你可以增加这个代码来尝试纠正传递的brokenUri:

 private static Uri FixUri(string brokenUri) { return new Uri("http://broken-link/"); } 

我遇到的问题实际上是一个Excel文档(就像你),它必须做一个格式不正确的http URL; 我惊喜地发现,他们的代码对我的Excel文件工作得很好。

这里是整个解决scheme的源代码,以防万一这些链接在未来消失:

  void Main(string[] args) { var fileName = @"C:\temp\corrupt.xlsx"; var newFileName = @"c:\temp\Fixed.xlsx"; var newFileInfo = new FileInfo(newFileName); if (newFileInfo.Exists) newFileInfo.Delete(); File.Copy(fileName, newFileName); WordprocessingDocument wDoc; try { using (wDoc = WordprocessingDocument.Open(newFileName, true)) { ProcessDocument(wDoc); } } catch (OpenXmlPackageException e) { e.Dump(); if (e.ToString().Contains("The specified package is not valid.")) { using (FileStream fs = new FileStream(newFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite)) { UriFixer.FixInvalidUri(fs, brokenUri => FixUri(brokenUri)); } } } } private static Uri FixUri(string brokenUri) { brokenUri.Dump(); return new Uri("http://broken-link/"); } private static void ProcessDocument(WordprocessingDocument wDoc) { var elementCount = wDoc.MainDocumentPart.Document.Descendants().Count(); Console.WriteLine(elementCount); } } public static class UriFixer { public static void FixInvalidUri(Stream fs, Func<string, Uri> invalidUriHandler) { XNamespace relNs = "http://schemas.openxmlformats.org/package/2006/relationships"; using (ZipArchive za = new ZipArchive(fs, ZipArchiveMode.Update)) { foreach (var entry in za.Entries.ToList()) { if (!entry.Name.EndsWith(".rels")) continue; bool replaceEntry = false; XDocument entryXDoc = null; using (var entryStream = entry.Open()) { try { entryXDoc = XDocument.Load(entryStream); if (entryXDoc.Root != null && entryXDoc.Root.Name.Namespace == relNs) { var urisToCheck = entryXDoc .Descendants(relNs + "Relationship") .Where(r => r.Attribute("TargetMode") != null && (string)r.Attribute("TargetMode") == "External"); foreach (var rel in urisToCheck) { var target = (string)rel.Attribute("Target"); if (target != null) { try { Uri uri = new Uri(target); } catch (UriFormatException) { Uri newUri = invalidUriHandler(target); rel.Attribute("Target").Value = newUri.ToString(); replaceEntry = true; } } } } } catch (XmlException) { continue; } } if (replaceEntry) { var fullName = entry.FullName; entry.Delete(); var newEntry = za.CreateEntry(fullName); using (StreamWriter writer = new StreamWriter(newEntry.Open())) using (XmlWriter xmlWriter = XmlWriter.Create(writer)) { entryXDoc.WriteTo(xmlWriter); } } } } } 

我没有使用OpenXml,但如果没有使用它的具体原因,那么我强烈build议从LinqToExcel LinqToExcel 。 代码示例如下:

 var sheet = new ExcelQueryFactory("filePath"); var allRows = from r in sheet.Worksheet() select r; foreach (var r in allRows) { var cella = r["Header"].ToString(); }