使用C#读取大型Excel文件并获取索引

时间:2018-08-07 23:02:18

标签: c# excel openxml excel-interop openxml-sdk

我尝试使用Microsoft.Office.Interop.Excel,但是在阅读大型excel文档时速度太慢(对我来说需要5分钟多的时间)。我读到DocumentFormat.OpenXml在读取大型excel文档时更快,但是在documentation中似乎无法存储列索引和行索引。

就目前而言,我也只对第一行中获取列标题感兴趣,并且我将通过一些逻辑来阅读文档的其余部分。我一直无法找到一种方法来仅读取一部分Excel文档。我想做类似的事情:

        int r = 1;  //row index
        int c = 1;  //column index
        while (xlRange.Cells[r,c] != null && xlRange.Cells[r, c].Value2 != null)
        {
            TagListData.Add(new TagClass { IsTagSelected = false, TagName = xlRange[r, c].Value2.toString(), rIndex = r, cIndex = c });
            c += 3;
        }

用户将通过openFileDialog选择excel文档,因此我没有固定的行数。有什么办法可以使我工作吗?

谢谢

1 个答案:

答案 0 :(得分:1)

在OpenXML中,如果一个单元格没有文本,则它可能会或可能不会出现在单元格列表中(取决于它是否有文本)。因此,while (...Value2 != null)类型的方法并不是在OpenXML中执行操作的真正安全方法。

这是一种读取第一行的非常简单的方法(使用LINQPad编写,因此使用MainDump)。请注意(简化)使用SharedStringTable来获取单元格的真实文本:

void Main()
{
    var fileName = @"c:\temp\openxml-read-row.xlsx";

    using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
    {
        using (SpreadsheetDocument doc = SpreadsheetDocument.Open(fs, false))
        {

            // Get the necessary bits of the doc
            WorkbookPart workbookPart = doc.WorkbookPart;
            SharedStringTablePart sstpart = workbookPart.GetPartsOfType<SharedStringTablePart>().First();
            SharedStringTable sst = sstpart.SharedStringTable;
            WorkbookStylesPart ssp = workbookPart.GetPartsOfType<WorkbookStylesPart>().First();
            Stylesheet ss = ssp.Stylesheet;

            // Get the first worksheet
            WorksheetPart worksheetPart = workbookPart.WorksheetParts.First();
            Worksheet sheet = worksheetPart.Worksheet;

            var rows = sheet.Descendants<Row>();
            var row = rows.First();
            foreach (var cell in row.Descendants<Cell>())
            {
                var txt = GetCellText(cell, sst);
                // LINQPad specific method .Dump()
                $"{cell.CellReference} = {txt}".Dump();
            }
        }
    }   
}

// Very basic way to get the text of a cell
private string GetCellText(Cell cell, SharedStringTable sst)
{
    if (cell == null)
        return "";

    if ((cell.DataType != null) && (cell.DataType == CellValues.SharedString))
    {
        int ssid = int.Parse(cell.CellValue.Text);
        string str = sst.ChildElements[ssid].InnerText;
        return str;
    }
    else if (cell.CellValue != null)
    {
        return cell.CellValue.Text;
    }
    return "";
}

但是... OpenXML可能涉及很多工作,因此建议您尝试使用ClosedXMLEPPlus之类的东西。

例如使用ClosedXML

using (var workbook = new XLWorkbook(fileName))
{
    var worksheet = workbook.Worksheets.First();
    var row = worksheet.Row(1);
    foreach (var cell in row.CellsUsed())
    {
        var txt = cell.Value.ToString();
        // LINQPad specific method .Dump()
        $"{cell.Address.ToString()} = {txt}".Dump();
    }
}