我在网上看到了很多关于如何使用OpenXML API获取单元数据的东西。但实际上并没有那么多特别简单明了。大多数似乎都是关于写入SpreadsheetML,而不是阅读...但即使这样也无济于事。 我有一个包含表格的电子表格。我知道表名是什么,我可以找出它所在的表,以及表中的列。但我无法弄清楚如何获取包含表中数据的行集合。
我有这个加载文档并获取工作簿的句柄:
SpreadsheetDocument document = SpreadsheetDocument.Open("file.xlsx", false);
WorkbookPart workbook = document.WorkbookPart;
我有这个找到表/表:
Table table = null;
foreach (Sheet sheet in workbook.Workbook.GetFirstChild<Sheets>())
{
WorksheetPart worksheetPart = (WorksheetPart)document.WorkbookPart.GetPartById(sheet.Id);
foreach (TableDefinitionPart tableDefinitionPart in worksheetPart.TableDefinitionParts)
{
if (tableDefinitionPart.Table.DisplayName == this._tableName)
{
table = tableDefinitionPart.Table;
break;
}
}
}
我可以通过对table.TableColumns进行预处理来迭代表中的列。
答案 0 :(得分:3)
使用OpenXML API阅读Excel 2007/2010电子表格真的很简单。不知何故,比使用OleDB更简单,因为我们总是像快速和快速一样。肮脏的解决此外,它不仅简单,而且详细,我认为如果必须对其进行评论和解释,将所有代码放在这里是没用的,所以我只会写一个摘要,我会链接一个好文章。阅读this article on MSDN,它解释了如何以非常简单的方式阅读XLSX文档。
总结一下你会这样做:
SpreadsheetDocument
打开SpreadsheetDocument.Open
。Sheet
中的LINQ查询获取所需的WorkbookPart
。WorksheetPart
的ID获取(最终!)Sheet
(您需要的对象)。在代码中,剥离注释和错误处理:
using (SpreadsheetDocument document = SpreadsheetDocument.Open(fileName, false))
{
Sheet sheet = document.WorkbookPart.Workbook
.Descendants<Sheet>()
.Where(s => s.Name == sheetName)
.FirstOrDefault();
WorksheetPart sheetPart =
(WorksheetPart)(document.WorkbookPart.GetPartById(theSheet.Id));
}
现在(但在使用中!)你要做的只是读取一个单元格值:
Cell cell = sheetPart.Worksheet.Descendants<Cell>().
Where(c => c.CellReference == addressName).FirstOrDefault();
如果你必须枚举行(并且它们很多),你首先要获得对SheetData
对象的引用:
SheetData sheetData = sheetPart.Worksheet.Elements<SheetData>().First();
现在您可以询问所有行和单元格:
foreach (Row row in sheetData.Elements<Row>())
{
foreach (Cell cell in row.Elements<Cell>())
{
string text = cell.CellValue.Text;
// Do something with the cell value
}
}
要简单地枚举普通电子表格,您可以使用Descendants<Row>()
对象的WorksheetPart
。
如果您需要更多关于OpenXML的资源,请查看OpenXML Developer,它包含很多很好的教程。
答案 1 :(得分:0)
可能有很多更好的方法可以对此进行编码,但我把它打成一片是因为我需要它,所以希望它能帮助其他人。
using DocumentFormat.OpenXml.Spreadsheet;
using DocumentFormat.OpenXml.Packaging;
private static DataTable genericExcelTable(FileInfo fileName)
{
DataTable dataTable = new DataTable();
try
{
using (SpreadsheetDocument doc = SpreadsheetDocument.Open(fileName.FullName, false))
{
Workbook wkb = doc.WorkbookPart.Workbook;
Sheet wks = wkb.Descendants<Sheet>().FirstOrDefault();
SharedStringTable sst = wkb.WorkbookPart.SharedStringTablePart.SharedStringTable;
List<SharedStringItem> allSSI = sst.Descendants<SharedStringItem>().ToList<SharedStringItem>();
WorksheetPart wksp = (WorksheetPart)doc.WorkbookPart.GetPartById(wks.Id);
foreach (TableDefinitionPart tdp in wksp.TableDefinitionParts)
{
QueryTablePart qtp = tdp.QueryTableParts.FirstOrDefault<QueryTablePart>();
Table excelTable = tdp.Table;
int colcounter = 0;
foreach (TableColumn col in excelTable.TableColumns)
{
DataColumn dcol = dataTable.Columns.Add(col.Name);
dcol.SetOrdinal(colcounter);
colcounter++;
}
SheetData data = wksp.Worksheet.Elements<SheetData>().First();
foreach (DocumentFormat.OpenXml.Spreadsheet.Row row in data)
{
if (isInTable(row.Descendants<Cell>().FirstOrDefault(), excelTable.Reference, true))
{
int cellcount = 0;
DataRow dataRow = dataTable.NewRow();
foreach (Cell cell in row.Elements<Cell>())
{
if (cell.DataType != null && cell.DataType.InnerText == "s")
{
dataRow[cellcount] = allSSI[int.Parse(cell.CellValue.InnerText)].InnerText;
}
else
{
dataRow[cellcount] = cell.CellValue.Text;
}
cellcount++;
}
dataTable.Rows.Add(dataRow);
}
}
}
}
//do whatever you want with the DataTable
return dataTable;
}
catch (Exception ex)
{
//handle an error
return dataTable;
}
}
private static Tuple<int, int> returnCellReference(string cellRef)
{
int startIndex = cellRef.IndexOfAny("0123456789".ToCharArray());
string column = cellRef.Substring(0, startIndex);
int row = Int32.Parse(cellRef.Substring(startIndex));
return new Tuple<int,int>(TextToNumber(column), row);
}
private static int TextToNumber(string text)
{
return text
.Select(c => c - 'A' + 1)
.Aggregate((sum, next) => sum * 26 + next);
}
private static bool isInTable(Cell testCell, string tableRef, bool headerRow){
Tuple<int, int> cellRef = returnCellReference(testCell.CellReference.ToString());
if (tableRef.Contains(":"))
{
int header = 0;
if (headerRow)
{
header = 1;
}
string[] tableExtremes = tableRef.Split(':');
Tuple<int, int> startCell = returnCellReference(tableExtremes[0]);
Tuple<int, int> endCell = returnCellReference(tableExtremes[1]);
if (cellRef.Item1 >= startCell.Item1
&& cellRef.Item1 <= endCell.Item1
&& cellRef.Item2 >= startCell.Item2 + header
&& cellRef.Item2 <= endCell.Item2) { return true; }
else { return false; }
}
else if (cellRef.Equals(returnCellReference(tableRef)))
{
return true;
}
else
{
return false;
}
}