检索电子表格文档中单元格的值
本主题演示如何使用 Open XML SDK for Office 中的类以编程方式检索电子表格文档中单元格的值。 它包含演示此任务的示例 GetCellValue
方法。
GetCellValue 方法
可以使用 GetCellValue
方法检索工作簿中单元格的值。 该方法需要以下三个参数:
一个包含要检查的文档的名称的字符串。
一个包含要检查的工作表的名称的字符串。
一个包含要从中检索值的单元格地址(例如 A1、B12)的字符串。
如果可以找到指定单元格的值,则该方法将返回该值。 以下示例代码显示方法签名。
static string GetCellValue(string fileName, string sheetName, string addressName)
代码的工作方式
该代码先创建一个放置返回值的变量,然后将其初始化为空。
string? value = null;
访问单元格
接下来,代码使用 Open 方法打开文档,指示应打开文档以 (最终 false
参数) 进行只读访问。 接下来,代码使用 WorkbookPart 文档的 属性检索对工作簿部件的引用。
// 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;
为查找请求的单元格,该代码必须先检索对工作表的引用(假定已提供其名称)。 代码必须搜索工作簿部件工作簿元素的所有工作表类型后代,并检查 Name 它找到的每个工作表的属性。 请注意,此搜索只会检查工作簿的关系,而不会实际查找工作表部分。 它会查找对 Sheet的引用,该引用包含工作表的名称和 Id 等信息。 为此,最简单的方法是使用 LINQ 查询,如下面的代码示例所示。
// 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 is null || theSheet.Id is null)
{
throw new ArgumentException("sheetName");
}
请注意, FirstOrDefault 该方法返回第一个匹配引用 (工作表(在本例中为) ),如果未找到匹配项,则返回 null 引用。 代码检查 null 引用,如果传入了无效的工作表名称,则会引发异常。现在,你已获得有关工作表的信息,代码必须检索对相应工作表部分的引用。 已检索的工作表信息提供了一个Id属性,并且给定该 Id 属性,代码可以通过调用工作簿部件GetPartById方法检索对相应 WorksheetPart 的引用。
// Retrieve a reference to the worksheet part.
WorksheetPart wsPart = (WorksheetPart)wbPart!.GetPartById(theSheet.Id!);
与查找命名工作表时一样,在查找命名单元格时,代码使用 Descendants 方法,搜索属性等于指定的第一个匹配 CellReference 项
addressName
参数。 在该方法调用后,名为 theCell
的变量将包含对单元格的引用或将包含空引用。
// 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();
检索值
此时,名为 theCell
的变量包含空引用或对所请求单元格的引用。 如果检查 Open XML 内容 (即 theCell.OuterXml
单元格) ,将找到如下所示的 XML。
<x:c r="A1">
<x:v>12.345000000000001</x:v>
</x:c>
属性 InnerText 包含单元格的内容,因此下一个代码块将检索此值。
// If the cell does not exist, return an empty string.
if (theCell is null || theCell.InnerText.Length < 0)
{
return string.Empty;
}
value = theCell.InnerText;
现在,示例方法必须解释该值。 实际上,该代码将处理数字和日期、字符串和布尔值。 必要时,可扩展示例。 类型 Cell 提供一个 DataType 属性,该属性指示单元格中的数据的类型。 对于数值和日期类型, DataType
属性值为 null。 它包含字符串的值 CellValues.SharedString
和 CellValues.Boolean
布尔值的值。
DataType
如果 属性为 null,则代码返回单元格的值, (它是数值) 。 否则,代码将根据数据类型来进行分支以继续。
// 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 is not null)
{
if (theCell.DataType.Value == CellValues.SharedString)
{
DataType
如果 属性包含 CellValues.SharedString
,则代码必须检索对单个 SharedStringTablePart的引用。
// For shared strings, look up the value in the
// shared strings table.
var stringTable = wbPart.GetPartsOfType<SharedStringTablePart>().FirstOrDefault();
接下来,如果字符串表 (存在,如果不存在,则工作簿会损坏,示例代码将索引返回字符串表中而不是字符串本身,) 代码返回 InnerText
它在指定索引处找到的元素的属性, (首先将 value 属性转换为整数) 。
// 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 is not null)
{
value = stringTable.SharedStringTable.ElementAt(int.Parse(value)).InnerText;
}
DataType
如果 属性包含 CellValues.Boolean
,则代码会将它在单元格值中找到的 0 或 1 转换为相应的文本字符串。
switch (value)
{
case "0":
value = "FALSE";
break;
default:
value = "TRUE";
break;
}
最后,过程返回变量 value
,其中包含请求的信息。
示例代码
下面是 C# 和 Visual Basic 中的完整 GetCellValue
代码示例。
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 is null || theSheet.Id is 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 is null || theCell.InnerText.Length < 0)
{
return string.Empty;
}
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 is not null)
{
if (theCell.DataType.Value == 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 is not null)
{
value = stringTable.SharedStringTable.ElementAt(int.Parse(value)).InnerText;
}
}
else if (theCell.DataType.Value == CellValues.Boolean)
{
switch (value)
{
case "0":
value = "FALSE";
break;
default:
value = "TRUE";
break;
}
}
}
}
return value;
}