I found some example of开发者_如何转开发 how to read the XML from an Excel spreadsheet >> HERE <<, and I am trying to get the code to work for me. I have to write a routine that takes the data from 4 of the 15 sheets in the workbook, and use that data to populate our database. Anyway....
This code is throwing an InvalidOperationException
exception every time I attempt to query my Excel spreadsheet:
static XElement GetWorksheet(string sheetName, PackagePartCollection allParts) {
XElement element = null;
try {
PackagePart worksheetPart = (from part in allParts
where part.Uri.OriginalString.Equals(String.Format("/xl/worksheets/{0}.xml", sheetName))
select part).Single();
element = XElement.Load(XmlReader.Create(worksheetPart.GetStream()));
} catch (Exception err) { // catches InvalidOperationException
Console.WriteLine(err.Message);
}
return element;
}
The specific error is, "Sequence contains no elements"
I'm really not sure how to go about debugging it, because I'm not sure what the code is trying to do.
Could someone help me write it in Standard" C# before I try to implement the fancy LINQ expression? (that is LINQ, right?)
[Solved]
Using the snippet provided by JeffN825, I was able to create this:
static XElement GetWorksheet(string sheetName, PackagePartCollection allParts) {
string xmlCompare = string.Format("/xl/worksheets/{0}.xml", sheetName);
foreach (PackagePart part in allParts) {
string original = part.Uri.OriginalString;
if (original == xmlCompare) {
XElement element = XElement.Load(XmlReader.Create(part.GetStream()));
return element;
}
}
return null;
}
It turns out that even though my sheet names in Excel are "HV", "M2", "CB" and "CC", I still have to specify them as "sheet2", "sheet3", "sheet4" and "sheet5".
I had to step through 161 PackagePart
objects to see this.
LINQ is just so damn efficient that it can be hard to debug when there are problems.
The .Single()
is what's throwing the exception. Either your query is returning no items or it's returning > 1 item. If you're not sure of the number of items you're expecting, you should be using FirstOrDefault()
which will return the first match or null if no matches are found.
The non-LINQ equivalent is something like this
PackagePart worksheetPart = null
foreach(var part in allParts)
{
if (part.Uri.OriginalString.Equals(String.Format("/xl/worksheets/{0}.xml", sheetName))))
{
if (part != null) throw new InvalidOperationException(); // > 1 match
worksheetPart = part;
}
}
if (part == null) throw new InvalidOperationException(); // no match
It's basically doing this.
PackagePart worksheetPart;
foreach(PackagePart part in allParts)
{
if(part.Uri.OriginalString.Equals(String.Format("/xl/worksheets/{0}.xml", sheetName)))
{
worksheetPart = part;
break;
}
}
In your version, try replacing .Single() with .FirstOrDefault().
It's failing because there is no match.
(from part in allParts
where part.Uri.OriginalString.Equals(String.Format("/xl/worksheets/{0}.xml", sheetName))
select part).Single();
Your error is in Single()
. If your query has no values in it, Single() throws that exception. What you should use instead is SingleOrDefault()
, which will return null
if there's no values from the query.
精彩评论