簡體   English   中英

使用OPENXML讀取時Excel電子表格行單元格亂序

[英]Excel spreadsheet row cells out of order when read with OPENXML

我需要閱讀一個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();
            }
        }

在使用示例代碼閱讀的示例Excel文件中找到了示例文件

下面是我訪問存儲在該行單元格中的值的方式的類型。

 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();

我嘗試使用單元格引用來訪問單元格內文

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;
    }
}

在各個單元上進行迭代時,需要查看CellReference屬性(這是XML文件中單元r屬性)。 它包含A1格式的單元格地址,其中A是列,1是行。

例如,第68行的233列為HY68。 您可能會發現此問題對如何生成列字母很有用。 然后,您可以檢查每個單元格的CellReference ,該單元格是您要檢查的行的后代,提取列字母並使用switch語句填充ItemDetail的相關部分

我看到避免迭代單個單元格的唯一明顯方法可能是使用XPath直接從基礎XML / .xslx文件中提取它們。 雖然不確定如何使用SpreadsheetDocument對象及其后代在C#中執行此操作。

您還可以通過CellReference屬性對現有查詢之一進行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為參數並返回包含InnerText或空字符串的String的函數中,可能會比較整齊

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM