打开 XML 电子表格读取表

Posted

技术标签:

【中文标题】打开 XML 电子表格读取表【英文标题】:Open XML Spreadsheet read table 【发布时间】:2019-07-16 18:46:19 【问题描述】:

我有一个需要能够导入的 Excel 电子表格。该电子表格在一张表中有许多命名表,这些表具有一些不同的模式以及整个表中的一些其他随机数据。我需要能够读取每个单独的表中的数据。

我已经弄清楚如何获取可用表的列表以及如何读取它们的列标题,但我不确定如何访问数据。

以下是我用于读取标题的代码示例。我真的不需要这些信息(因为我会将这些信息放入模型中并且已经知道列的顺序),它确实显示了我正在使用的内容。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using System.Data;

...

public static DataTable GetNamedDataTable(SpreadsheetDocument spreadsheetDocument, string cellRange, string DataTableName)

    var dataTable = new DataTable();

    Workbook woorkbook = spreadsheetDocument.WorkbookPart.Workbook;
    //Sheet 
    var bustedCellRange = BustCellRange(cellRange);
    Sheet sheet = woorkbook.Descendants<Sheet>().Where(s => s.Name == bustedCellRange["sheetName"]).FirstOrDefault();
    SharedStringTable sharedStringTable = woorkbook.WorkbookPart.SharedStringTablePart.SharedStringTable;
    List<SharedStringItem> allSharedStringItems= sharedStringTable.Descendants<SharedStringItem>().ToList();
    WorksheetPart worksheetPart = (WorksheetPart)spreadsheetDocument.WorkbookPart.GetPartById(sheet.Id);

    TableDefinitionPart tableDefinitionPart = worksheetPart.TableDefinitionParts.FirstOrDefault(r => r.Table.Name == DataTableName);
    QueryTablePart queryTablePart = tableDefinitionPart.QueryTableParts.FirstOrDefault();
    Table excelTable = tableDefinitionPart.Table;
    int columnCounter = 0;
    foreach(TableColumn column in excelTable.TableColumns)
    
        DataColumn dataColumn = dataTable.Columns.Add(column.Name);
        dataColumn.SetOrdinal(columnCounter);
        columnCounter++;
    
    return dataTable;


【问题讨论】:

This thread 有点老了,但我认为这里的内容仍然与您相关。 @JacobH 的问题在于它正在读取整个工作表,我所拥有的是一张包含许多表格和一些随机数据的工作表。我将更新问题,使其更加明确。 数据是否与表头在工作表的同一区域/表中?比如,数据是否已经在excelTable 中?如果是这样,只需遍历 rows 并将它们作为新数据行添加到 dataTable @JacobH,除非我遗漏了 DocumentFormat.OpenXml.Spreadsheet.Table 对象没有行集合的内容。你知道我如何访问它,因为这将是一个完美的解决方案。 你可以通过将表传递给它的构造函数来使用 sheetdata 类吗? (其实我也不知道,我只用过Excel XML方法)。 【参考方案1】:

我终于想出了如何做到这一点。如果您遇到同样的问题,请参见下文,请注意,我确实计划在我自己的项目中对此进行大量清理,但这应该会让您继续前进。


public static DataTable GetNamedDataTable(SpreadsheetDocument spreadsheetDocument, string DataTableName)

    var dataTable = new DataTable();
    Workbook woorkbook = spreadsheetDocument.WorkbookPart.Workbook;
    Sheet sheet = woorkbook.Descendants<Sheet>().Where(s => s.Name == "SheetName").FirstOrDefault();
    SharedStringTable sharedStringTable = woorkbook.WorkbookPart.SharedStringTablePart.SharedStringTable;
    List<SharedStringItem> allSharedStringItems= sharedStringTable.Descendants<SharedStringItem>().ToList();
    WorksheetPart worksheetPart = (WorksheetPart)spreadsheetDocument.WorkbookPart.GetPartById(sheet.Id);
    TableDefinitionPart tableDefinitionPart = worksheetPart.TableDefinitionParts.FirstOrDefault(r => r.Table.Name == DataTableName);
    QueryTablePart queryTablePart = tableDefinitionPart.QueryTableParts.FirstOrDefault();
    Table excelTable = tableDefinitionPart.Table;
    int columnCounter = 0;
    foreach(TableColumn column in excelTable.TableColumns)
    
       DataColumn dataColumn = dataTable.Columns.Add(column.Name);
       dataColumn.SetOrdinal(columnCounter);
       columnCounter++;
    

    var newCellRange = excelTable.Reference;
    var startCell = newCellRange.Value.Split(':')[0];
    var endCell = newCellRange.Value.Split(':')[1];

    uint firstRowNum = GetRowIndex(startCell);
    uint lastRowNum = GetRowIndex(endCell);
    string firstColumn = GetColumnName(startCell);
    string lastColumn = GetColumnName(endCell);

    var columnIndex = 0;
    foreach (Row row in worksheetPart.Worksheet.Descendants<Row>().Where(r => r.RowIndex.Value > firstRowNum && r.RowIndex.Value <= lastRowNum))
    
        var dataRow = dataTable.NewRow();
        foreach (Cell cell in row)
                        
            string columnName = GetColumnName(cell.CellReference.Value);
            if (CompareColumn(columnName, firstColumn) >= 0 && CompareColumn(columnName, lastColumn) <= 0)
            
                if (cell.CellValue != null)
                
                    dataRow[columnIndex] = cell.CellValue.Text;
                
                columnIndex++;
            
        
        dataTable.Rows.Add(dataRow);
        columnIndex = 0;
        Console.WriteLine("");
    

    return dataTable;


private static uint GetRowIndex(string cellName)

    // Create a regular expression to match the row index portion the cell name.
    Regex regex = new Regex(@"\d+");
    Match match = regex.Match(cellName);
    return uint.Parse(match.Value);


// Given a cell name, parses the specified cell to get the column name.
private static string GetColumnName(string cellName)

    // Create a regular expression to match the column name portion of the cell name.
    Regex regex = new Regex("[A-Za-z]+");
    Match match = regex.Match(cellName);
    return match.Value;


// Given two columns, compares the columns.
private static int CompareColumn(string column1, string column2)

    if (column1.Length > column2.Length)
    
        return 1;
    
    else if (column1.Length < column2.Length)
    
        return -1;
    
    else
    
        return string.Compare(column1, column2, true);
    

此答案的信用必须转到以下站点,因为它是导致我能够弄清楚这一点的原因。 https://docs.microsoft.com/en-us/office/open-xml/how-to-calculate-the-sum-of-a-range-of-cells-in-a-spreadsheet-document

【讨论】:

谢谢,只是想补充一下,您需要allSharedStringItems 将文本单元格的值转换为字符串

以上是关于打开 XML 电子表格读取表的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Perl 创建或读取 OpenOffice 电子表格?

怎样做电子表格

读取 OpenOffice 电子表格时出错

无法从谷歌电子表格中读取

Excel电子表格无法打开请问是啥原因,提示只读、服务器没有响应

电子表格中如何将男女筛选并统计出人数?