我尝试使用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文档,因此我没有固定数量的列可以使用。有没有办法让这项工作成功?
谢谢
在OpenXML中,如果单元格没有文本,它可能会也可能不会出现在单元格列表中(取决于它是否有文本)。因此,while (...Value2 != null)
类型的方法在OpenXML中实际上并不是一种安全的方法。
这是一个非常简单的方法来读取第一行(使用LINQPad编写,因此Main
和Dump
)。注意(简化)使用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可能涉及很多工作,你建议你尝试使用像ClosedXML或EPPlus这样的东西。
例如,使用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();
}
}