有没有办法使用OpenXml从列中获取最后填充的行单元格值

时间:2019-04-04 19:51:51

标签: c# console-application openxml

我正在使用一个控制台应用程序,该应用程序只是从指定的单元格中获取值并将其显示在控制台上。我想修改代码并获取列中最后一个单元格的值。我可以获取指定的单元格的值,但是我只希望获取最后一个填充的单元格(因为当工作表更新为更多行时,addressName可能会更改)。我目前正在使用下面的代码通过addressName获取值。有人可以指出我正确的方向还是举个例子。请,谢谢。

using System;
using System.Linq;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;

namespace ConsoleApp5
{
 class Program
  {
    static void Main(string[] args)
    {
        string fileName = @"C:\Temp\myTempDoc\bigexcel.xlsx";
        string sheetName = "sheet1";
        string addressName = "B25";
        var cellVall =GetCellValue(fileName, sheetName, addressName);
        Console.WriteLine(cellVall);
        Console.ReadKey();
    }
    public static string GetCellValue(string fileName,string sheetName,string addressName)
    {
        string value = null;
        // Open the spreadsheet document for read-only access.
        using (SpreadsheetDocument document =
            SpreadsheetDocument.Open(fileName, false))
        {
            // Retrieve a reference to the workbook part.
            WorkbookPart wbPart = document.WorkbookPart;
            // Find the sheet with the supplied name, and then use that 
            // Sheet object to retrieve a reference to the first worksheet.
            Sheet theSheet = wbPart.Workbook.Descendants<Sheet>().
              Where(s => s.Name == sheetName).FirstOrDefault();
            // Throw an exception if there is no sheet.
            if (theSheet == null)
            {
                throw new ArgumentException("sheetName");
            }
            // Retrieve a reference to the worksheet part.
            WorksheetPart wsPart =
                (WorksheetPart)(wbPart.GetPartById(theSheet.Id));
            // Use its Worksheet property to get a reference to the cell 
            // whose address matches the address you supplied.
            Cell theCell = wsPart.Worksheet.Descendants<Cell>().
              Where(c => c.CellReference ==addressName ).FirstOrDefault();
            // If the cell does not exist, return an empty string.
            if (theCell != null)
            {
                value = theCell.InnerText;
                // If the cell represents an integer number, you are done. 
                // For dates, this code returns the serialized value that 
                // represents the date. The code handles strings and 
                // Booleans individually. For shared strings, the code 
                // looks up the corresponding value in the shared string 
                // table. For Booleans, the code converts the value into 
                // the words TRUE or FALSE.
                if (theCell.DataType != null)
                {
                    switch (theCell.DataType.Value)
                    {
                        case CellValues.SharedString:

                            // For shared strings, look up the value in the
                            // shared strings table.
                            var stringTable =
                                wbPart.GetPartsOfType<SharedStringTablePart>()
                                .FirstOrDefault();

                            // If the shared string table is missing, something 
                            // is wrong. Return the index that is in
                            // the cell. Otherwise, look up the correct text in 
                            // the table.
                            if (stringTable != null)
                            {
                                value =
                                    stringTable.SharedStringTable
                                    .ElementAt(int.Parse(value)).InnerText;
                            }
                            break;
                        case CellValues.Boolean:
                            switch (value)
                            {
                                case "0":
                                    value = "FALSE";
                                    break;
                                default:
                                    value = "TRUE";
                                    break;
                            }
                            break;
                    }
                }
            }
        }
        return value;
    }
  }
 }

2 个答案:

答案 0 :(得分:0)

我不清楚您是选择Cell中最后一个Row还是最后一个Cell的最后一个Row。但这两种方法非常相似,因此我将展示如何做。

基本原理是首先找到要追捕的Row,然后从该Cell抓取孩子Row

如果您想要工作表的最后一个Cell,那么我们只需要最后一个Row

//grab the last row
Row row = wsPart.Worksheet.Descendants<Row>().LastOrDefault();

但是,如果您希望能够传递一个行号并获取该Cell的最后一个Row,则可以使用类似的方法(此处的变量{{1} }表示您想要最后一个rowIndex的{​​{1}}的索引:

Row

一旦有了Cell,这就是使用与上面类似的代码来获取//find the row that matches the rowNumber we're after Row row = wsPart.Worksheet.Descendants<Row>() .Where(r => r.RowIndex == rowIndex).FirstOrDefault(); 中最后一个Row的情况:

Cell

答案 1 :(得分:0)

我遇到了同样的问题,发现空白的excel(OpenXml)行具有后代= 1:

std::vector<double> vec( static_cast<int *>( a ), static_cast<int *>( a ) + n); 

,因此您可以继续读取行并忽略空行,直到最后一行。