Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,247 +17,76 @@ ms.localizationpriority: high
---
# Retrieve a list of the hidden rows or columns in a spreadsheet document

This topic shows how to use the classes in the Open XML SDK for Office to programmatically retrieve a list of hidden rows or columns in a Microsoft Excel 2010 or Microsoft Excel 2013 worksheet, without
loading the document into Excel. It contains an example **GetHiddenRowsOrCols** method to illustrate this task.
This topic shows how to use the classes in the Open XML SDK for Office to programmatically retrieve a list of hidden rows or columns in a Microsoft Excel worksheet. It contains an example **GetHiddenRowsOrCols** method to illustrate this task.



---------------------------------------------------------------------------------

## GetHiddenRowsOrCols Method

You can use the **GetHiddenRowsOrCols** method
to retrieve a list of the hidden rows or columns in a worksheet. The
**GetHiddenRowsOrCols** method accepts three
parameters, indicating the following:
You can use the **GetHiddenRowsOrCols** method to retrieve a list of the hidden rows or columns in a worksheet. The method returns a list of unsigned integers that contain each index for the hidden rows or columns, if the specified worksheet contains any hidden rows or columns (rows and columns are numbered starting at 1, rather than 0). The **GetHiddenRowsOrCols** method accepts three parameters:

- The name of the document to examine (string).

- The name of the sheet to examine (string).

- Whether to detect rows (true) or columns (false) (Boolean).

### [C#](#tab/cs-0)
```csharp
public static List<uint> GetHiddenRowsOrCols(
string fileName, string sheetName, bool detectRows)
```

### [Visual Basic](#tab/vb-0)
```vb
Public Function GetHiddenRowsOrCols(
ByVal fileName As String, ByVal sheetName As String,
ByVal detectRows As Boolean) As List(Of UInteger)
```
***


---------------------------------------------------------------------------------

## Calling the GetHiddenRowsOrCols Method

The method returns a list of unsigned integers that contain each index for the hidden rows or columns, if the specified worksheet contains any hidden rows or columns (rows and columns are numbered starting at 1, rather than 0.) To call the method, pass all the parameter values, as shown in the following example code.

### [C#](#tab/cs-1)
```csharp
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());
```

### [Visual Basic](#tab/vb-1)
```vb
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())
```
***


---------------------------------------------------------------------------------

## How the Code Works

The code starts by creating a variable, **itemList**, that will contain the return value.

### [C#](#tab/cs-2)
```csharp
List<uint> itemList = new List<uint>();
```

### [Visual Basic](#tab/vb-2)
```vb
Dim itemList As New List(Of UInteger)
```
***


Next, the code opens the document, by using the [SpreadsheetDocument.Open](https://msdn.microsoft.com/library/office/documentformat.openxml.packaging.spreadsheetdocument.open.aspx) method and indicating that the document should be open for read-only access (the final **false** parameter value). Next the code retrieves a reference to the workbook part, by using the [WorkbookPart](https://msdn.microsoft.com/library/office/documentformat.openxml.packaging.spreadsheetdocument.workbookpart.aspx) property of the document.
The code opens the document, by using the [SpreadsheetDocument.Open](https://msdn.microsoft.com/library/office/documentformat.openxml.packaging.spreadsheetdocument.open.aspx) method and indicating that the document should be open for read-only access (the final **false** parameter value). Next the code retrieves a reference to the workbook part, by using the [WorkbookPart](https://msdn.microsoft.com/library/office/documentformat.openxml.packaging.spreadsheetdocument.workbookpart.aspx) property of the document.

### [C#](#tab/cs-3)
```csharp
using (SpreadsheetDocument document =
SpreadsheetDocument.Open(fileName, false))
{
WorkbookPart wbPart = document.WorkbookPart;
// Code removed here...
}
```
[!code-csharp[](../../samples/spreadsheet/retrieve_a_list_of_the_hidden_rows_or_columns/cs/Program.cs#snippet1)]

### [Visual Basic](#tab/vb-3)
```vb
Using document As SpreadsheetDocument =
SpreadsheetDocument.Open(fileName, False)

Dim wbPart As WorkbookPart = document.WorkbookPart
' Code removed here...
End Using
```
[!code-vb[](../../samples/spreadsheet/retrieve_a_list_of_the_hidden_rows_or_columns/vb/Program.vb#snippet1)]
***


To find the hidden rows or columns, the code must first retrieve a reference to the specified sheet, given its name. This is not as easy as you might think. The code must look through all the sheet-type descendants of the workbook part's [Workbook](https://msdn.microsoft.com/library/office/documentformat.openxml.packaging.workbookpart.workbook.aspx) property, examining the [Name](https://msdn.microsoft.com/library/office/documentformat.openxml.spreadsheet.sheet.name.aspx) property of each sheet that it finds.
Note that this search simply looks through the relations of the workbook, and does not actually find a worksheet part. It simply finds a reference to a [Sheet](https://msdn.microsoft.com/library/office/documentformat.openxml.spreadsheet.sheet.aspx) object, which contains information such as the name and [Id](https://msdn.microsoft.com/library/office/documentformat.openxml.spreadsheet.sheet.id.aspx) property of the sheet. The simplest way to accomplish this is to use a LINQ query.

### [C#](#tab/cs-4)
```csharp
Sheet theSheet = wbPart.Workbook.Descendants<Sheet>().
Where((s) => s.Name == sheetName).FirstOrDefault();
if (theSheet == null)
{
throw new ArgumentException("sheetName");
}
```
[!code-csharp[](../../samples/spreadsheet/retrieve_a_list_of_the_hidden_rows_or_columns/cs/Program.cs#snippet2)]

### [Visual Basic](#tab/vb-4)
```vb
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")
```
[!code-vb[](../../samples/spreadsheet/retrieve_a_list_of_the_hidden_rows_or_columns/vb/Program.vb#snippet2)]
***


The [FirstOrDefault](https://msdn2.microsoft.com/library/bb358452) method returns either the first matching reference (a sheet, in this case) or a null reference if no match was found. The code checks for the
null reference, and throws an exception if you passed in an invalid sheet name. Now that you have information about the sheet, the code must retrieve a reference to the corresponding worksheet part. The sheet
information you already retrieved provides an **Id** property, and given that **Id** property, the code can retrieve a reference to the corresponding [WorksheetPart](https://msdn.microsoft.com/library/office/documentformat.openxml.spreadsheet.worksheet.worksheetpart.aspx) property by calling the [GetPartById](https://msdn.microsoft.com/library/office/documentformat.openxml.packaging.openxmlpartcontainer.getpartbyid.aspx) method of the [WorkbookPart](https://msdn.microsoft.com/library/office/documentformat.openxml.packaging.workbookpart.aspx) object.
The sheet information you already retrieved provides an **Id** property, and given that **Id** property, the code can retrieve a reference to the corresponding [WorksheetPart](https://msdn.microsoft.com/library/office/documentformat.openxml.spreadsheet.worksheet.worksheetpart.aspx) property by calling the [GetPartById](https://msdn.microsoft.com/library/office/documentformat.openxml.packaging.openxmlpartcontainer.getpartbyid.aspx) method of the [WorkbookPart](https://msdn.microsoft.com/library/office/documentformat.openxml.packaging.workbookpart.aspx) object.

### [C#](#tab/cs-5)
```csharp
else
{
// The sheet does exist.
WorksheetPart wsPart =
(WorksheetPart)(wbPart.GetPartById(theSheet.Id));
Worksheet ws = wsPart.Worksheet;
// Code removed here...
}
```
[!code-csharp[](../../samples/spreadsheet/retrieve_a_list_of_the_hidden_rows_or_columns/cs/Program.cs#snippet3)]

### [Visual Basic](#tab/vb-5)
```vb
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
```
[!code-vb[](../../samples/spreadsheet/retrieve_a_list_of_the_hidden_rows_or_columns/vb/Program.vb#snippet3)]
***


---------------------------------------------------------------------------------

## Retrieving the List of Hidden Row or Column Index Values

The code uses the **detectRows** parameter that
you specified when you called the method to determine whether to
retrieve information about rows or columns.

### [C#](#tab/cs-6)
```csharp
if (detectRows)
{
// Retrieve hidden rows.
// Code removed here...
}
else
{
// Retrieve hidden columns.
// Code removed here...
}
```

### [Visual Basic](#tab/vb-6)
```vb
If detectRows Then
' Retrieve hidden rows.
' Code removed here...
Else
' Retrieve hidden columns.
' Code removed here...
End If
```
***


The code that actually retrieves the list of hidden rows requires only a single line of code.
The code uses the **detectRows** parameter that you specified when you called the method to determine whether to retrieve information about rows or columns.The code that actually retrieves the list of hidden rows requires only a single line of code.

### [C#](#tab/cs-7)
```csharp
itemList = ws.Descendants<Row>().
Where((r) => r.Hidden != null && r.Hidden.Value).
Select(r => r.RowIndex.Value).ToList<uint>();
```
[!code-csharp[](../../samples/spreadsheet/retrieve_a_list_of_the_hidden_rows_or_columns/cs/Program.cs#snippet4)]

### [Visual Basic](#tab/vb-7)
```vb
itemList = ws.Descendants(Of Row).
Where(Function(r) r.Hidden IsNot Nothing AndAlso
r.Hidden.Value).
Select(Function(r) r.RowIndex.Value).ToList()
```
[!code-vb[](../../samples/spreadsheet/retrieve_a_list_of_the_hidden_rows_or_columns/vb/Program.vb#snippet4)]
***


This single line accomplishes a lot, however. It starts by calling the [Descendants](https://msdn.microsoft.com/library/office/documentformat.openxml.openxmlelement.descendants.aspx) method of the worksheet, retrieving a list of all the rows. The [Where](https://msdn2.microsoft.com/library/bb301979) method limits the results to only those rows where the [Hidden](https://msdn.microsoft.com/library/office/documentformat.openxml.spreadsheet.row.hidden.aspx) property of the item is not null and the value of the **Hidden** property is **True**. The [Select](https://msdn2.microsoft.com/library/bb357126) method projects the return value for each row, returning the value of the [RowIndex](https://msdn.microsoft.com/library/office/documentformat.openxml.spreadsheet.row.rowindex.aspx) property. Finally, the [ToList\<TSource\>](https://msdn2.microsoft.com/library/bb342261) method converts the resulting [IEnumerable\<T\>](https://msdn2.microsoft.com/library/9eekhta0) interface into a [List\<T\>](https://msdn2.microsoft.com/library/6sh2ey19) object of unsigned integers. If there are no hidden rows, the returned list is empty.

Retrieving the list of hidden columns is a bit trickier, because Excel collapses groups of hidden columns into a single element, and provides [Min](https://msdn.microsoft.com/library/office/documentformat.openxml.spreadsheet.column.min.aspx) and [Max](https://msdn.microsoft.com/library/office/documentformat.openxml.spreadsheet.column.max.aspx) properties that describe the first and last columns in the group. Therefore, the code that retrieves the list of hidden columns starts the same as the code that retrieves hidden rows. However, it must iterate through the index values (looping each item in the collection of hidden columns, adding each index from the **Min** to the **Max** value, inclusively).

### [C#](#tab/cs-8)
```csharp
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);
}
}
```
[!code-csharp[](../../samples/spreadsheet/retrieve_a_list_of_the_hidden_rows_or_columns/cs/Program.cs#snippet5)]

### [Visual Basic](#tab/vb-8)
```vb
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
```
[!code-vb[](../../samples/spreadsheet/retrieve_a_list_of_the_hidden_rows_or_columns/vb/Program.vb#snippet5)]
***


Expand All @@ -268,10 +97,10 @@ Retrieving the list of hidden columns is a bit trickier, because Excel collapses
The following is the complete **GetHiddenRowsOrCols** code sample in C\# and Visual Basic.

### [C#](#tab/cs)
[!code-csharp[](../../samples/spreadsheet/retrieve_a_list_of_the_hidden_rows_or_columns/cs/Program.cs)]
[!code-csharp[](../../samples/spreadsheet/retrieve_a_list_of_the_hidden_rows_or_columns/cs/Program.cs#snippet0)]

### [Visual Basic](#tab/vb)
[!code-vb[](../../samples/spreadsheet/retrieve_a_list_of_the_hidden_rows_or_columns/vb/Program.vb)]
[!code-vb[](../../samples/spreadsheet/retrieve_a_list_of_the_hidden_rows_or_columns/vb/Program.vb#snippet0)]

---------------------------------------------------------------------------------

Expand Down
Original file line number Diff line number Diff line change
@@ -1,73 +1,61 @@
// <Snippet0>
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using System;
using System.Collections.Generic;
using System.Linq;

List<uint>? items = null;

if (args is [{ } fileName, { } sheetName, { } detectRows])
{
items = GetHiddenRowsOrCols(fileName, sheetName, detectRows);
}
else if (args is [{ } fileName2, { } sheetName2])
{
items = GetHiddenRowsOrCols(fileName2, sheetName2);
}

if (items is null)
{
throw new ArgumentException("Invalid arguments.");
}

foreach (uint item in items)
{
Console.WriteLine(item);
}

static List<uint> GetHiddenRowsOrCols(string fileName, string sheetName, string detectRows = "false")
{
// 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.

// <Snippet1>
List<uint> itemList = new List<uint>();

using (SpreadsheetDocument document = SpreadsheetDocument.Open(fileName, false))
{
if (document is not null)
{
WorkbookPart wbPart = document.WorkbookPart ?? document.AddWorkbookPart();
// </Snippet1>

// <Snippet2>
Sheet? theSheet = wbPart.Workbook.Descendants<Sheet>().FirstOrDefault((s) => s.Name == sheetName);

if (theSheet is null)
if (theSheet is null || theSheet.Id is null)
{
throw new ArgumentException("sheetName");
}
// </Snippet2>
else
{
string id = theSheet.Id?.ToString() ?? string.Empty;
// <Snippet3>

// The sheet does exist.
WorksheetPart? wsPart = wbPart.GetPartById(id) as WorksheetPart;
WorksheetPart? wsPart = wbPart.GetPartById(theSheet.Id!) as WorksheetPart;
Worksheet? ws = wsPart?.Worksheet;
// </Snippet3>

if (ws is not null)
{
if (detectRows.ToLower() == "true")
{
// <Snippet4>
// Retrieve hidden rows.
itemList = ws.Descendants<Row>()
.Where((r) => r?.Hidden is not null && r.Hidden.Value)
.Select(r => r.RowIndex?.Value)
.Cast<uint>()
.ToList();
// </Snippet4>
}
else
{
// Retrieve hidden columns.
// <Snippet5>
var cols = ws.Descendants<Column>().Where((c) => c?.Hidden is not null && c.Hidden.Value);

foreach (Column item in cols)
Expand All @@ -80,11 +68,34 @@ static List<uint> GetHiddenRowsOrCols(string fileName, string sheetName, string
}
}
}
// </Snippet5>
}
}
}
}
}

return itemList;
}
}
// </Snippet0>

List<uint>? items = null;

if (args is [{ } fileName, { } sheetName, { } detectRows])
{
items = GetHiddenRowsOrCols(fileName, sheetName, detectRows);
}
else if (args is [{ } fileName2, { } sheetName2])
{
items = GetHiddenRowsOrCols(fileName2, sheetName2);
}

if (items is null)
{
throw new ArgumentException("Invalid arguments.");
}

foreach (uint item in items)
{
Console.WriteLine(item);
}
Loading