如何:在电子表格文档中检索隐藏行或隐藏列的列表
本主题演示如何使用 Open XML SDK 2.0 for Microsoft Office 中的类以编程方式检索 Microsoft Office Excel 2007 或 Microsoft Excel 2010 工作表中隐藏行或列的列表,而无需将文档加载到 Excel 中。本主题包含一个演示此任务的示例 GetHiddenRowsOrCols 方法。
上次修改时间: 2011年11月17日
适用范围: Excel 2010 | Office 2010 | PowerPoint 2010 | Word 2010
本文内容
GetHiddenRowsOrCols 方法
调用 GetHiddenRowsOrCols 方法
代码的工作方式
检索隐藏的行或列的索引值的列表
示例代码
必须安装 Open XML SDK 2.0(该链接可能指向英文页面) 才能使用本主题中的示例代码。必须在项目中明确引用以下程序集:
WindowsBase
DocumentFormat.OpenXml(由 Open XML SDK 安装)
还必须使用以下 using 指令或 Imports 语句编译本主题中的代码。
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
Imports System.IO
Imports DocumentFormat.OpenXml.Packaging
Imports DocumentFormat.OpenXml.Spreadsheet
GetHiddenRowsOrCols 方法
您可以使用 GetHiddenRowsOrCols 方法检索工作表中隐藏行或列的列表。GetHiddenRowsOrCols 方法接受三个参数,分别指示以下内容:
要检查的文档的名称(字符串)。
要检查的工作表的名称(字符串)。
是检测行 (True) 还是列 (False)(布尔值)。
public static List<uint> GetHiddenRowsOrCols(
string fileName, string sheetName, bool detectRows)
Public Function GetHiddenRowsOrCols(
ByVal fileName As String, ByVal sheetName As String,
ByVal detectRows As Boolean) As List(Of UInteger)
调用 GetHiddenRowsOrCols 方法
如果指定的工作表包含任何隐藏的行或列(行和列的编号从 1 而不是从 0 开始),那么该方法将返回包含隐藏行或列的每个索引的无符号整数的列表。若要调用该方法,请传递所有参数值,如下面的示例代码所示。
const string fileName = @"C:\users\public\documents\RetrieveHiddenRowsCols.xlsx";
List<uint> items = GetHiddenRowsOrCols(fileName, "Sheet1", true);
var sw = new StringWriter();
foreach (var item in items)
sw.WriteLine(item);
Console.WriteLine(sw.ToString());
Const fileName As String = "C:\Users\Public\Documents\RetrieveHiddenRowsCols.xlsx"
Dim items As List(Of UInteger) =
GetHiddenRowsOrCols(fileName, "Sheet1", True)
Dim sw As New StringWriter
For Each item In items
sw.WriteLine(item)
Next
Console.WriteLine(sw.ToString())
代码的工作方式
代码首先创建变量 itemList,该变量将包含返回值。
List<uint> itemList = new List<uint>();
Dim itemList As New List(Of UInteger)
接下来,此代码使用 SpreadsheetDocument.Open 方法打开文档,并指示此文档应打开供只读访问(最后一个 false 参数值)。紧接着,此代码使用文档的 WorkbookPart 属性检索对工作簿部分的引用。
using (SpreadsheetDocument document =
SpreadsheetDocument.Open(fileName, false))
{
WorkbookPart wbPart = document.WorkbookPart;
// Code removed here...
}
Using document As SpreadsheetDocument =
SpreadsheetDocument.Open(fileName, False)
Dim wbPart As WorkbookPart = document.WorkbookPart
' Code removed here...
End Using
为了查找隐藏行或列,代码必须首先检索对指定工作表的引用(假设知道工作表的名称)。这可不像您想象的那么简单。代码必须浏览工作簿部件的 Workbook 属性的所有工作表类型后代,分析找到的每个工作表的 Name 属性。请注意,这种搜索只是简单地浏览工作簿的关系,并不实际查找工作表部件。它只是查找对 Sheet 对象的引用,该对象包含诸如工作表名称和 Id 属性之类的信息。完成此操作最简单的方法是使用 LINQ 查询。
Sheet theSheet = wbPart.Workbook.Descendants<Sheet>().
Where((s) => s.Name == sheetName).FirstOrDefault();
if (theSheet == null)
{
throw new ArgumentException("sheetName");
}
Dim theSheet As Sheet = wbPart.Workbook.Descendants(Of Sheet)().
Where(Function(s) s.Name = sheetName).FirstOrDefault()
If theSheet Is Nothing Then
Throw New ArgumentException("sheetName")
FirstOrDefault 方法返回第一个匹配的引用(在此示例中为工作表)或者一个空引用(如果未找到匹配项)。代码将检查空引用,如果您传递的工作表名称无效,代码将引发异常。现在,您已具有有关工作表的信息,代码必须检索对相应工作表部件的引用。您已检索的工作表信息提供一个 Id 属性,有了该 Id 属性,代码便可以通过调用 WorkbookPart 对象的 GetPartById 方法检索对相应 WorksheetPart 属性的引用。
else
{
// The sheet does exist.
WorksheetPart wsPart =
(WorksheetPart)(wbPart.GetPartById(theSheet.Id));
Worksheet ws = wsPart.Worksheet;
// Code removed here...
}
Else
' The sheet does exist.
Dim wsPart As WorksheetPart =
CType(wbPart.GetPartById(theSheet.Id), WorksheetPart)
Dim ws As Worksheet = wsPart.Worksheet
' Code removed here...
End If
检索隐藏的行或列的索引值的列表
代码使用您在调用方法以确定是检索有关行还是列的信息时指定的 detectRows 参数。
if (detectRows)
{
// Retrieve hidden rows.
// Code removed here...
}
else
{
// Retrieve hidden columns.
// Code removed here...
}
If detectRows Then
' Retrieve hidden rows.
' Code removed here...
Else
' Retrieve hidden columns.
' Code removed here...
End If
检索隐藏行列表的代码实际上只需要一行。
itemList = ws.Descendants<Row>().
Where((r) => r.Hidden != null && r.Hidden.Value).
Select(r => r.RowIndex.Value).ToList<uint>();
itemList = ws.Descendants(Of Row).
Where(Function(r) r.Hidden IsNot Nothing AndAlso
r.Hidden.Value).
Select(Function(r) r.RowIndex.Value).ToList()
但是这一行代码会完成很多任务,它首先调用工作表的 Descendants 方法,检索所有行的列表。Where 方法将结果限制为那些其项目的 Hidden 属性不为空且 Hidden 属性的值为 True 的行。Select 方法投影每行的返回值,并返回 RowIndex 属性的值。最后,ToList<TSource> 方法将生成的 IEnumerable<T> 接口转换为无符号整数的 List<T> 对象。如果不存在隐藏的行,则返回的列表将为空。
检索隐藏列的列表则有些复杂,因为 Excel 将多组隐藏列折叠成一个元素,并提供描述该组中第一列和最后一列的 Min 和 Max 属性。因此,检索隐藏列的列表的代码的开始部分与检索隐藏行的代码相同。不过,它必须循环访问索引值(循环访问隐藏列集合中的每个项目,添加介于 Min 和 Max 值之间(含这两个值)的每个索引)。
var cols = ws.Descendants<Column>().
Where((c) => c.Hidden != null && c.Hidden.Value);
foreach (Column item in cols)
{
for (uint i = item.Min.Value; i <= item.Max.Value; i++)
{
itemList.Add(i);
}
}
Dim cols = ws.Descendants(Of Column).
Where(Function(c) c.Hidden IsNot Nothing AndAlso
c.Hidden.Value)
For Each item As Column In cols
For i As UInteger = item.Min.Value To item.Max.Value
itemList.Add(i)
Next
Next
示例代码
下面是 C# 和 Visual Basic 中的完整 GetHiddenRowsOrCols 示例代码。
public static List<uint> GetHiddenRowsOrCols(
string fileName, string sheetName, bool detectRows)
{
// Given a workbook and a worksheet name, return
// either a list of hidden row numbers, or a list
// of hidden column numbers. If detectRows is true, return
// hidden rows. If detectRows is false, return hidden columns.
// Rows and columns are numbered starting with 1.
List<uint> itemList = new List<uint>();
using (SpreadsheetDocument document =
SpreadsheetDocument.Open(fileName, false))
{
WorkbookPart wbPart = document.WorkbookPart;
Sheet theSheet = wbPart.Workbook.Descendants<Sheet>().
Where((s) => s.Name == sheetName).FirstOrDefault();
if (theSheet == null)
{
throw new ArgumentException("sheetName");
}
else
{
// The sheet does exist.
WorksheetPart wsPart =
(WorksheetPart)(wbPart.GetPartById(theSheet.Id));
Worksheet ws = wsPart.Worksheet;
if (detectRows)
{
// Retrieve hidden rows.
itemList = ws.Descendants<Row>().
Where((r) => r.Hidden != null && r.Hidden.Value).
Select(r => r.RowIndex.Value).ToList<uint>();
}
else
{
// Retrieve hidden columns.
var cols = ws.Descendants<Column>().
Where((c) => c.Hidden != null && c.Hidden.Value);
foreach (Column item in cols)
{
for (uint i = item.Min.Value; i <= item.Max.Value; i++)
{
itemList.Add(i);
}
}
}
}
}
return itemList;
}
Public Function GetHiddenRowsOrCols(
ByVal fileName As String, ByVal sheetName As String,
ByVal detectRows As Boolean) As List(Of UInteger)
' Given a workbook and a worksheet name, return either
' a list of hidden row numbers, or a list of hidden
' column numbers. If detectRows is True, return
' hidden rows. If detectRows is False, return hidden columns.
' Rows and columns are numbered starting with 1.
Dim itemList As New List(Of UInteger)
Using document As SpreadsheetDocument =
SpreadsheetDocument.Open(fileName, False)
Dim wbPart As WorkbookPart = document.WorkbookPart
Dim theSheet As Sheet = wbPart.Workbook.Descendants(Of Sheet)().
Where(Function(s) s.Name = sheetName).FirstOrDefault()
If theSheet Is Nothing Then
Throw New ArgumentException("sheetName")
Else
' The sheet does exist.
Dim wsPart As WorksheetPart =
CType(wbPart.GetPartById(theSheet.Id), WorksheetPart)
Dim ws As Worksheet = wsPart.Worksheet
If detectRows Then
' Retrieve hidden rows.
itemList = ws.Descendants(Of Row).
Where(Function(r) r.Hidden IsNot Nothing AndAlso
r.Hidden.Value).
Select(Function(r) r.RowIndex.Value).ToList()
Else
' Retrieve hidden columns.
Dim cols = ws.Descendants(Of Column).
Where(Function(c) c.Hidden IsNot Nothing AndAlso
c.Hidden.Value)
For Each item As Column In cols
For i As UInteger = item.Min.Value To item.Max.Value
itemList.Add(i)
Next
Next
End If
End If
End Using
Return itemList
End Function