使用Open XML从C#中的Excel到DataTable

Ras*_*tro 38 c# openxml import-from-excel openxml-sdk

我正在使用Visual Studio 2008,我需要DataTable使用Open XML SDK 2.0从Excel工作表创建一个.我需要使用带有工作表第一行的DataTable列创建它,并使用其余值完成它.

有没有人有一个示例代码或链接可以帮助我这样做?

小智 61

我认为这应该做你所要求的.如果您有共享字符串,那么另一个函数就是处理,我假设您在列标题中执行此操作.不确定这是完美的,但我希望它有所帮助.

static void Main(string[] args)
{
    DataTable dt = new DataTable();

    using (SpreadsheetDocument spreadSheetDocument = SpreadsheetDocument.Open(@"..\..\example.xlsx", 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))
        {
            dt.Columns.Add(GetCellValue(spreadSheetDocument, cell));
        }

        foreach (Row row in rows) //this will also include your header row...
        {
            DataRow tempRow = dt.NewRow();

            for (int i = 0; i < row.Descendants<Cell>().Count(); i++)
            {
                tempRow[i] = GetCellValue(spreadSheetDocument, row.Descendants<Cell>().ElementAt(i-1));
            }

            dt.Rows.Add(tempRow);
        }

    }
    dt.Rows.RemoveAt(0); //...so i'm taking it out here.

}


public 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这似乎跳过了空单元格,所以你可能最终在`tempRow`中将A1,D1和G1放在一起.在某些情况下,`CellValue`为null,我在`GetCellValue`的第二行得到一个异常. (3认同)
  • @RahulNikate,你的链接带你到这个页面! (2认同)
  • 如果单元格值为空,以下将引发异常。字符串值 = cell.CellValue.InnerXml; 在它之前添加一行检查是否为空: Checklace if (cell.CellValue == null) { return ""; } (2认同)

小智 14

嗨以上代码工作正常,除了一个更改

替换下面的代码行

tempRow[i] = GetCellValue(spreadSheetDocument, row.Descendants<Cell>().ElementAt(i-1));
Run Code Online (Sandbox Code Playgroud)

tempRow[i] = GetCellValue(spreadSheetDocument, row.Descendants<Cell>().ElementAt(i));
Run Code Online (Sandbox Code Playgroud)

如果使用(i-1),它将抛出异常:

specified argument was out of the range of valid values. parameter name index.
Run Code Online (Sandbox Code Playgroud)


小智 5

此解决方案适用于没有空单元格的电子表格。

要处理空单元格,您需要替换此行:

tempRow[i] = GetCellValue(spreadSheetDocument, row.Descendants<Cell>().ElementAt(i-1));
Run Code Online (Sandbox Code Playgroud)

像这样:

Cell cell = row.Descendants<Cell>().ElementAt(i);
int index = CellReferenceToIndex(cell);
tempRow[index] = GetCellValue(spreadSheetDocument, cell);
Run Code Online (Sandbox Code Playgroud)

并添加此方法:

private static int CellReferenceToIndex(Cell cell)
{
    int index = -1;
    string reference = cell.CellReference.ToString().ToUpper();
    foreach (char ch in reference)
    {
        if (Char.IsLetter(ch))
        {
            int value = (int)ch - (int)'A';
            index = (index + 1) * 26 + value;
        }
        else
            return index;
    }
    return index;
}
Run Code Online (Sandbox Code Playgroud)