C# 使用OPENXML读取Excel电子表格行单元格时出现错误

C# 使用OPENXML读取Excel电子表格行单元格时出现错误,c#,excel,openxml,C#,Excel,Openxml,我需要阅读excel文档并将单元格中包含的数据放入数据库。然而,我注意到的问题是,当我从行中读取数据时,它们并没有按照它们在表单中出现的顺序出现。请问我该怎么算 public void getrowdata(){ IEnumerable<Row> dataRows = from row in s.worksheetpart.Worksheet.Descendants<Row>()

我需要阅读excel文档并将单元格中包含的数据放入数据库。然而,我注意到的问题是,当我从行中读取数据时,它们并没有按照它们在表单中出现的顺序出现。请问我该怎么算

public void getrowdata(){

 IEnumerable<Row> dataRows = from row in s.worksheetpart.Worksheet.Descendants<Row>()
                                                where row.RowIndex > 6
                                                select row;

// extract the data in the row in order 
                foreach (Row row in dataRows)
                { 
                    var cellValues = from cell in row.Descendants<Cell>()
                                     select ((cell.CellValue != null && cell.DataType != null && cell.DataType.HasValue)
                                         && (sharedString.HasChildren && int.Parse(cell.CellValue.InnerText) < sharedString.ChildElements.Count)
                                         ? sharedString.ChildElements[int.Parse(cell.CellValue.InnerText)].InnerText
                                         : ((cell.CellValue != null && cell.CellValue.InnerText != null) ? cell.CellValue.InnerText : String.Empty));


//--cellValues.toArray() and then access each cell via index in array


}

  public void ReadDSheetsToBuffer()
        {
            try
            { 
                //Open the Excel workbook.
                using (SpreadsheetDocument document = SpreadsheetDocument.Open(file.FullName, true))
                {
                    //References to the workbook and Shared String Table.
                    workBook = document.WorkbookPart.Workbook;
                    workSheets = workBook.Descendants<Sheet>();
                    sharedStrings = document.WorkbookPart.SharedStringTablePart.SharedStringTable; 
                    ExtractSheetstoMemory2(document);

                }
            }
            catch (Exception ex)
            {
                throw ex.GetBaseException();
            }
        }
我尝试使用单元格引用访问单元格内部文本

foreach (Row row in dataRows)
{
    if (row.RowIndex > 6)
    {
        String theCell = row.Descendants<Cell>().Where(c => c.CellReference == ExcelColumnFromNumber(1) + row.RowIndex.ToString()).FirstOrDefault().InnerText;
        String theCell2 = row.Descendants<Cell>().Where(c => c.CellReference == ExcelColumnFromNumber(2) + row.RowIndex.ToString()).FirstOrDefault().InnerText;
        String theCell3 = row.Descendants<Cell>().Where(c => c.CellReference == ExcelColumnFromNumber(3) + row.RowIndex.ToString()).FirstOrDefault().InnerText;
        String theCell4 = row.Descendants<Cell>().Where(c => c.CellReference == ExcelColumnFromNumber(4) + row.RowIndex.ToString()).FirstOrDefault().InnerText;
        String theCell5 = row.Descendants<Cell>().Where(c => c.CellReference == ExcelColumnFromNumber(5) + row.RowIndex.ToString()).FirstOrDefault().InnerText;
        String theCell6 = row.Descendants<Cell>().Where(c => c.CellReference == ExcelColumnFromNumber(6) + row.RowIndex.ToString()).FirstOrDefault().InnerText;
        String theCell7 = row.Descendants<Cell>().Where(c => c.CellReference == ExcelColumnFromNumber(7) + row.RowIndex.ToString()).FirstOrDefault().InnerText;
        String theCell8 = row.Descendants<Cell>().Where(c => c.CellReference == ExcelColumnFromNumber(8) + row.RowIndex.ToString()).FirstOrDefault().InnerText;
        String theCell9 = row.Descendants<Cell>().Where(c => c.CellReference == ExcelColumnFromNumber(9) + row.RowIndex.ToString()).FirstOrDefault().InnerText;
        String theCell10 = row.Descendants<Cell>().Where(c => c.CellReference == ExcelColumnFromNumber(10) + row.RowIndex.ToString()).FirstOrDefault().InnerText;
        String theCell11 = row.Descendants<Cell>().Where(c => c.CellReference == ExcelColumnFromNumber(11) + row.RowIndex.ToString()).FirstOrDefault().InnerText;
        String theCell112 = row.Descendants<Cell>().Where(c => c.CellReference == ExcelColumnFromNumber(12) + row.RowIndex.ToString()).FirstOrDefault().InnerText;
        String theCell13 = row.Descendants<Cell>().Where(c => c.CellReference == ExcelColumnFromNumber(13) + row.RowIndex.ToString()).FirstOrDefault().InnerText;
        String theCell14 = row.Descendants<Cell>().Where(c => c.CellReference == ExcelColumnFromNumber(14) + row.RowIndex.ToString()).FirstOrDefault().InnerText;
        String theCell15 = row.Descendants<Cell>().Where(c => c.CellReference == ExcelColumnFromNumber(15) + row.RowIndex.ToString()).FirstOrDefault().InnerText;
    }
}
foreach(数据行中的行)
{
如果(row.RowIndex>6)
{
字符串theCell=row.substands()。其中(c=>c.CellReference==ExcelColumnFromNumber(1)+row.RowIndex.ToString()).FirstOrDefault().InnerText;
字符串theCell2=row.subjections()。其中(c=>c.CellReference==ExcelColumnFromNumber(2)+row.RowIndex.ToString()).FirstOrDefault().InnerText;
字符串theCell3=row.substands()。其中(c=>c.CellReference==ExcelColumnFromNumber(3)+row.RowIndex.ToString()).FirstOrDefault().InnerText;
字符串theCell4=row.subjections()。其中(c=>c.CellReference==ExcelColumnFromNumber(4)+row.RowIndex.ToString()).FirstOrDefault().InnerText;
字符串theCell5=row.substands()。其中(c=>c.CellReference==ExcelColumnFromNumber(5)+row.RowIndex.ToString()).FirstOrDefault().InnerText;
字符串theCell6=row.substands()。其中(c=>c.CellReference==ExcelColumnFromNumber(6)+row.RowIndex.ToString()).FirstOrDefault().InnerText;
字符串theCell7=row.subjections()。其中(c=>c.CellReference==ExcelColumnFromNumber(7)+row.RowIndex.ToString()).FirstOrDefault().InnerText;
字符串theCell8=row.subjections()。其中(c=>c.CellReference==ExcelColumnFromNumber(8)+row.RowIndex.ToString()).FirstOrDefault().InnerText;
字符串theCell9=row.subjections()。其中(c=>c.CellReference==ExcelColumnFromNumber(9)+row.RowIndex.ToString()).FirstOrDefault().InnerText;
字符串theCell10=row.subjections()。其中(c=>c.CellReference==ExcelColumnFromNumber(10)+row.RowIndex.ToString()).FirstOrDefault().InnerText;
字符串theCell11=row.subjections()。其中(c=>c.CellReference==ExcelColumnFromNumber(11)+row.RowIndex.ToString()).FirstOrDefault().InnerText;
字符串theCell112=row.substands()。其中(c=>c.CellReference==ExcelColumnFromNumber(12)+row.RowIndex.ToString()).FirstOrDefault().InnerText;
字符串theCell13=row.subjections()。其中(c=>c.CellReference==ExcelColumnFromNumber(13)+row.RowIndex.ToString()).FirstOrDefault().InnerText;
字符串theCell14=row.subjections()。其中(c=>c.CellReference==ExcelColumnFromNumber(14)+row.RowIndex.ToString()).FirstOrDefault().InnerText;
字符串theCell15=row.subjections()。其中(c=>c.CellReference==ExcelColumnFromNumber(15)+row.RowIndex.ToString()).FirstOrDefault().InnerText;
}
}

在遍历单个单元格时,需要查看
CellReference
属性(这是XML文件中单元格的
r
属性)。它包含A1格式的单元格地址,其中A为列,1为行

例如,第68行上的233列将是HY68。您可能会发现如何生成列字母很有用。然后,您可以检查作为所检查行后代的每个单元格的
CellReference
,提取列字母,并使用
switch
语句填充
itemdail

我能看到的避免迭代单个单元格的唯一明显方法可能是使用XPath直接从底层XML/.xslx文件中提取它们。但不知道如何在C#中使用
SpreadsheetDocument
对象及其子对象来实现这一点

您还可以通过
CellReference
属性对一个现有查询进行排序,该属性将使单元格有序,但可能会导致空单元格出现问题(即返回的第10个单元格可能不是第10列中的单元格)


编辑:处理缺少的单元格/空引用只需要在访问
.InnerText
属性之前检查引用

Cell theCell = row.Descendants<Cell>().Where(c => c.CellReference == ExcelColumnFromNumber(1) + row.RowIndex.ToString()).FirstOrDefault();

String theCellValue = "";

if (theCell != null)
{
  theCellValue = theCell.InnerText;
}
Cell theCell=row.subjects()。其中(c=>c.CellReference==ExcelColumnFromNumber(1)+row.RowIndex.ToString()).FirstOrDefault();
字符串theCellValue=“”;
if(theCell!=null)
{
cell值=cell.InnerText;
}

用一个函数来包装这一部分可能会更整洁,该函数将
单元格
作为参数,并返回一个
字符串
,该字符串包含
内部文本
或一个空字符串

您能上传一个示例excel文件吗?所以我会看一看,我已经上传了这个文件,行号是“x:row”元素的“r”属性。您可能必须使用它将它们映射回正确的位置,而不是假设它们使用存储顺序来隐式定位它们。我不一定关心我正在处理的行,而是处理行中值的另一行。是否有某种行索引功能允许我访问行中的元素行直接获取该值,而不必一次迭代一个单元格?我尝试通过cellreference访问,但当它命中“缺失”单元格时,似乎抛出了“null reference”异常。我至少注意到它发生在我的一些(不是全部)行的G列上。因此,通过单元格引用进行访问似乎是一种困难的方法,或者您是否有某种方法可以做到这一点?请看我的例子。用一种处理空引用的方法更新了答案
Cell theCell = row.Descendants<Cell>().Where(c => c.CellReference == ExcelColumnFromNumber(1) + row.RowIndex.ToString()).FirstOrDefault();

String theCellValue = "";

if (theCell != null)
{
  theCellValue = theCell.InnerText;
}