【问题标题】:OpenXML - Not reading a blank Cell from a row C#OpenXML - 不从行 C# 中读取空白单元格
【发布时间】:2017-05-02 05:22:18
【问题描述】:

我有一个 .xlsx 文件,其中 3 列 SrNumber、Name、Active 分别位于 A、B 和 C 列。

我正在使用以下问题的答案中给出的源代码在 DataTable 中读取此文件的内容

From Excel to DataTable in C# with Open XML

我也做了 Sourabh 建议的修改

当我的内容如下时效果很好

    A           B       C
1   SrNumber    Name    Active
2   1           test1   Yes
3   2           test2   Yes
4   3           test3   Yes
5   4           test4   Yes

现在,当我尝试在第 6 位添加一行时,我只在 B6 和 C6 单元格中输入数据。 我没有碰过A6 Cell。

运行该代码后,我的 DataTable 填充如下

您可以看到在 B6 中输入的值在第一列,在 C6 中输入的值在第二列。 同样row.Descendants<Cell>() 只为新输入的行返回 2 个单元格。

如果对源代码进行任何修改,请告诉我。

【问题讨论】:

  • 请贴出您实际使用的代码。那么你的问题将是独立的。
  • 问题stackoverflow.com/questions/3321082/…的相同答案代码有54个赞成票。根据用户 Sourabh(8 Upvotes) 的建议进行修改..
  • 我认为代码有问题是因为我在answer here 中列出的原因。如果我有时间,我会为此或您的链接问题添加答案。
  • 您链接到的示例代码是旧的。我建议你宁愿使用 ClosedXml NuGet 包nuget.org/packages/ClosedXML 它有一个更好的与 Excel 文档交互的 api,并且不需要安装 Office。我用过很多次,我推荐它。
  • 相关帖子here.

标签: c# openxml openxml-sdk


【解决方案1】:
//Read the first Sheet from Excel file.
            IXLWorksheet workSheet = workBook.Worksheet(1);

            //Create a new DataTable.
            DataTable dt = new DataTable();

            //Loop through the Worksheet rows.
            bool firstRow = true;
            foreach (IXLRow row in workSheet.Rows())
            {
                //Use the first row to add columns to DataTable.
                if (firstRow)
                {
                    foreach (IXLCell cell in row.Cells())
                    {
                        dt.Columns.Add(cell.Value.ToString());
                    }
                    firstRow = false;
                }
                else
                {
                    //Add rows to DataTable.
                    dt.Rows.Add();
                    int i = 0;
                    //for (IXLCell cell in row.Cells())
                    for (int j=1;j<= dt.Columns.Count;j++)
                    {
                        if (string.IsNullOrEmpty(row.Cell(j).Value.ToString()))
                            dt.Rows[dt.Rows.Count - 1][i] = "";
                        else
                            dt.Rows[dt.Rows.Count - 1][i] = row.Cell(j).Value.ToString();
                        i++;
                    }
                }
            }

【讨论】:

    【解决方案2】:

    下面的代码应该可以为您解决问题。 CellReferenceToIndex 非常重要,当我们遇到空单元格时,它会计算实际的单元格索引:

    using System;
    using System.Data;
    using System.Linq;
    using DocumentFormat.OpenXml.Packaging;
    using DocumentFormat.OpenXml.Spreadsheet;
    
    public static DataTable ReadAsDataTable(string fileName)
    {
        DataTable dataTable = new DataTable();
        using (SpreadsheetDocument spreadSheetDocument = SpreadsheetDocument.Open(fileName, false))
        {
            WorkbookPart workbookPart = spreadSheetDocument.WorkbookPart;
            IEnumerable<Sheet> sheets = spreadSheetDocument.WorkbookPart.Workbook.GetFirstChild<Sheets>().Elements<Sheet>();
            string relationshipId = sheets.First().Id.Value;
            WorksheetPart worksheetPart = (WorksheetPart)spreadSheetDocument.WorkbookPart.GetPartById(relationshipId);
            Worksheet workSheet = worksheetPart.Worksheet;
            SheetData sheetData = workSheet.GetFirstChild<SheetData>();
            IEnumerable<Row> rows = sheetData.Descendants<Row>();
    
            foreach (Cell cell in rows.ElementAt(0))
            {
                dataTable.Columns.Add(GetCellValue(spreadSheetDocument, cell));
            }
    
            foreach (Row row in rows)
            {
                DataRow dataRow = dataTable.NewRow();
                for (int i = 0; i < row.Descendants<Cell>().Count(); i++)
                {
                     Cell cell = row.Descendants<Cell>().ElementAt(i);
                     int actualCellIndex = CellReferenceToIndex(cell);
                     dataRow[actualCellIndex] = GetCellValue(spreadSheetDocument, cell);
                }
    
                dataTable.Rows.Add(dataRow);
            }
    
        }
        dataTable.Rows.RemoveAt(0);
    
        return dataTable;
    }
    
    private static string GetCellValue(SpreadsheetDocument document, Cell cell)
    {
        SharedStringTablePart stringTablePart = document.WorkbookPart.SharedStringTablePart;
        string value = cell.CellValue.InnerXml;
    
        if (cell.DataType != null && cell.DataType.Value == CellValues.SharedString)
        {
            return stringTablePart.SharedStringTable.ChildElements[Int32.Parse(value)].InnerText;
        }
        else
        {
            return value;
        }
    }
    
    private static int CellReferenceToIndex(Cell cell)
    {
        int index = 0;
        string reference = cell.CellReference.ToString().ToUpper();
        foreach (char ch in reference)
        {
            if (Char.IsLetter(ch))
            {
                int value = (int)ch - (int)'A';
                index = (index == 0) ? value : ((index + 1) * 26) + value;
            }
            else
                return index;
        }
        return index;
    }
    

    【讨论】:

      猜你喜欢
      • 2021-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多