使用OPENXML读取时,Excel电子表格行单元格无序

时间:2012-10-04 10:14:47

标签: c# excel openxml spreadsheet

我需要读取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();
            }
        }

Sample Excel File I read with the code

找到示例文件

以下是我访问存储在行中单元格中的值的方式。 。 。

 if (values[228] != null)
                itemdetail.Custom1 = rowvalues[228].Trim();
            if (values[229] != null)
                itemdetail.Custom2 = rowvalues[229].Trim();
            if (values[230] != null)
                itemdetail.Custom3 = rowvalues[230].Trim();
            if (values[231] != null)
                itemdetail.Custom4 = rowvalues[231].Trim();
            if (values[232] != null)
                itemdetail.Custom5 = rowvalues[232].Trim();
            if (values[233] != null)
                itemdetail.Custom6 = rowvalues[233].Trim();

我尝试使用单元格引用访问单元格innertext

 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;

}
}

1 个答案:

答案 0 :(得分:0)

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

第233行,例如第68行是HY68。您可能会发现this question对于如何生成列字母非常有用。然后,您可以检查每个单元格的CellReference,该单元格是您正在检查的行的后代,提取列字母并使用switch语句填充ItemDetail <的相关部分/ p>

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

您还可以通过CellReference属性订购一个现有查询,这样可以按顺序获取单元格,但可能会导致空单元格出现问题(即返回的第10个单元格可能不是第10列中的单元格)< / p>


编辑:处理缺少的单元格/空引用只需要在访问.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作为参数并返回包含String或空字符串<{p>}的InnerText的函数中可能更整洁