改变
积极的改变才意味着进步

Worksheet 类

当您阅读到文章的此处时,您已经了解了使用一个单独的工作表需要掌握的大多数概念。尽管 Worksheet 类提供了大量的成员,但是其大多数的属性、方法和事件与 Application 和(或) Workbook 类提供的成员是相同的或相似的。这一部分将集中探讨 Worksheet 类的重要成员及特定问题,这些问题是您在本文的其他部分所没有接触过的内容。(您可以在示例工作簿中的 Worksheet Object 工作表看到这一部分中的例子。)

不存在 Sheet 类

尽管 Excel 提供了一个 Sheets 集合作为 Workbook 对象的属性,但是在 Excel 中您找不到 Sheet 类。相反,Sheets 集合的每个成员都是 WorksheetChart 对象。您可以以这种方式考虑它:把 WorksheetChart 类看成内部 Sheet 类的特定实例(并且对无法访问源代码的人来说,将无法知道这种看法是否和实际的实现相符),但是 Sheet 类对外部不可用。

使用保护

通常,Excel 中的保护功能可以防止用户和(或)代码修改工作表内的对象。一旦您启用了对工作表保护功能,除非您预作安排,否则用户不能编辑或者修改工作表。在用户界面内,您可以使用 Tools|Protection|Protect Sheet 菜单项启用保护功能。当选择此项后会显示“保护工作表”对话框,如图 12 所示。您可以在此设置密码或者允许用户执行特定的操作。默认情况下,一旦启用保护功能,所有的单元格都会被锁定。此外,通过使用 Tools|Protection|Allow Users to Edit Ranges 菜单项(它会显示如图 13 所示的对话框),您可以让用户编辑特定区域。将这两个对话框结合使用,您可以锁定工作表,然后可以让用户编辑特定的功能和区域。


12. 在用户界面中,使用此对话框的控制保护。

a

13. 使用此对话框,您可以允许用户编辑特定的区域。

您可以使用工作表的 Protect 方法通过编程方法控制对工作表的保护。这个方法的语法如下面的例子所示,其中的每个参数都是可选的:

' Visual Basic
WorksheetObject.Protect(Password, DrawingObjects, Contents, _
Scenarios, UserInterfaceOnly, AllowFormattingCells, _
AllowFormattingColumns, AllowFormattingRows, _
AllowInsertingColumns, AllowInsertingRows, _
AllowInsertingHyperlinks, AllowDeletingColumns, _
AllowDeletingRows, AllowSorting, AllowFiltering, _
AllowUsingPivotTables)
// C#
WorksheetObject.Protect(Password, DrawingObjects, Contents,
Scenarios, UserInterfaceOnly, AllowFormattingCells,
AllowFormattingColumns, AllowFormattingRows,
AllowInsertingColumns, AllowInsertingRows,
AllowInsertingHyperlinks, AllowDeletingColumns,
AllowDeletingRows, AllowSorting, AllowFiltering,
AllowUsingPivotTables);

下面的列表描述了 Protect 方法的参数:

设置 Password 参数来指定一个区分大小写的字符串,这是取消保护工作表所需要的。如果您不指定这个参数,任何人都可以取消保护工作表。

DrawingObjects 参数设置为 True 来保护工作表的形状。默认值为 False。

Contents 参数设置为 True 来保护工作表的内容(单元格)。默认值为 True,您可能永远不会改变它。

Scenarios 参数设置为 True 来保护工作表中的方案。默认值为 True。

UserInterfaceOnly 参数设置为 True 可以允许通过代码修改,但是不允许通过用户界面修改。默认值为 False,这意味着通过代码和用户界面项都不可以修改受保护的工作表。这个属性设置只适用于当前会话。如果您想让代码可以在任何会话中都可以操作工作表,那么您需要每次工作簿打开的时候添加设置这个属性的代码。

AllowFormattingCells 参数、AllowFormattingColumns 参数和前面方法语法的完整列表中所示的其余参数允许特定的格式化功能,对应于对话框中(如图 12 所示)的选项。默认情况下,所有这些属性都是 False。

可以调用工作表的 Protect 方法来保护工作表,如下面的代码片段所示,这段代码设置了密码,并且只允许排序:

' Visual Basic
DirectCast(ThisApplication.Sheets(1), Excel.Worksheet). _
Protect("MyPassword", AllowSorting:=True)
// C#
((Excel.Worksheet)ThisApplication.Sheets[1]).Protect(
"MyPassword", Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, true, Type.Missing, Type.Missing);

提示很明显,在您的代码中硬编码密码并不是一个很好的主意。最常见的情况是,您需要从用户那里得到密码,然后将这个密码应用于工作簿,但不保存。通常,在源代码中您是不会看到硬编码密码的。

为了取消对工作表的保护,您可以使用下面的代码。这段代码假定有一个名称为 GetPasswordFromUser 的过程,这个过程要求用户输入一个密码,并且返回输入的密码值:

' Visual Basic
DirectCast(ThisApplication.Sheets(1), Excel.Worksheet). _
Unprotect(GetPasswordFromUser())
// C#
((Excel.Worksheet)ThisApplication.Sheets[1]).
Unprotect(GetPasswordFromUser());

Unprotect 方法将取消对工作表的保护,并让您提供一个可选的密码。

Excel 也提供其他两个对象,您将会发现,当使用保护的时候它们很有用:ProtectionAllowEditRange 对象。Protection 对象封装了您调用 Protect 方法时指定的所有信息,及未保护区域的信息。通过调用 Protect 方法设置共享的 Protection 对象的属性,这些对象提供了以下对应于 Protect 方法的参数的 Boolean 属性:

AllowDeletingColumns, AllowDeletingRows

AllowFiltering

AllowFormattingCells, AllowFormattingColumns, AllowFormattingRows

AllowInsertingColumns, AllowInsertingHyperlinks, AllowInsertingRows

AllowSorting

AllowUsingPivotTables

此外,Protection 类提供 AllowEditRanges 属性,它允许您指定工作表上的可编辑区域,对应于在 13 中所示的对话框中指定的信息。 AllowEditRanges 属性包含一个 AllowEditRange 对象集合,其中的每个对象都提供许多有用的属性,包括:

Range:获取或者设置对应于可编辑区域的范围

Title:获取或者设置可编辑区域的标题(用于在如 13 所示的对话框中显示)。

Users:获取或者设置 UserAccess 对象集合(有关 UserAccess 对象的更多信息,请参考联机文档)。

在示例工作簿上的 WorksheetObject 工作表(见 14)中,您可以试验一下通过编程实现的保护功能。单击 Protect 保护工作表,这样您就只能编辑处于阴影区域的内容(名称为 Information 和 Date 的两个范围)。单击 Unprotect取消保护工作表。


14. 测试工作表的保护功能。

在示例工作表中的链接会运行以下过程:

' Visual Basic
Private Sub ProtectSheet()
Dim ws As Excel.Worksheet = _
DirectCast(ThisApplication.ActiveSheet, Excel.Worksheet)
With ws.Protection.AllowEditRanges
.Add("Information", ThisApplication.Range("Information"))
.Add("Date", ThisApplication.Range("Date"))
End With
ws.Protect()
End Sub
Private Sub UnprotectSheet()
Dim ws As Excel.Worksheet = _
DirectCast(ThisApplication.Sheets("Worksheet Class"), _
Excel.Worksheet)
' Unprotect the sheet.
ws.Unprotect()
' Delete all protection ranges, just to clean up.
' You must loop through this using the index,
' backwards. This collection doesn't provide
' an enumeration method, and it doesn't handle
' being resized as you're looping in a nice way.
Dim i As Integer
With ws.Protection.AllowEditRanges
For i = .Count To 1 Step -1
.Item(i).Delete()
Next i
End With
End Sub
// C#
private void ProtectSheet()
{
Excel.Worksheet ws =
(Excel.Worksheet)ThisApplication.ActiveSheet;
Excel.AllowEditRanges ranges = ws.Protection.AllowEditRanges;
ranges.Add("Information",
ThisApplication.get_Range("Information", Type.Missing),
Type.Missing);
ranges.Add("Date",
ThisApplication.get_Range("Date", Type.Missing), Type.Missing);
ws.Protect(Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing,Type.Missing, Type.Missing,
Type.Missing,Type.Missing, Type.Missing, Type.Missing,
Type.Missing,Type.Missing,Type.Missing,
Type.Missing,Type.Missing);
}
private void UnprotectSheet()
{
Excel.Worksheet ws =
(Excel.Worksheet) ThisApplication.Sheets["Worksheet Class"];
ws.Unprotect(Type.Missing);
// Delete all protection ranges, just to clean up.
// You must loop through this using the index,
// backwards. This collection doesn't provide
// an enumeration method, and it doesn't handle
// being resized as you're looping in a nice way.
Excel.AllowEditRanges ranges = ws.Protection.AllowEditRanges;
for (int i = ranges.Count; i >= 1; i--)
{
ranges[i].Delete();
}
}

对象属性

Worksheet 类提供了几个返回对象的属性。下面的章节将介绍这些对象,并提供使用这些对象的例子。

批注

使用 Insert|Comment 菜单项,您可以在工作表的一个范围中插入附加的文本批注(见图 15)。在代码中使用 Range 对象的 AddComment 方法也可以达到相同目的。下面的代码删除与名为 Date 的范围相关联的批注(若存在批注),然后创建一个新的批注。最后,代码通过调用下一个代码示例所描述的 ShowOrHideComments 方法来显示工作表中的所有批注(见图 16):

' Visual Basic
Dim rng As Excel.Range = ThisApplication.Range("Date")
If Not rng.Comment Is Nothing Then
rng.Comment.Delete()
End If
rng.AddComment("Comment added " & DateTime.Now)
' Display all the comments:
ShowOrHideComments(Show:=True)
// C#
Excel.Range rng = ThisApplication.get_Range("Date", Type.Missing);
if (rng.Comment != null )
{
rng.Comment.Delete();
}
rng.AddComment("Comment added " + DateTime.Now);
// Display all the comments:
ShowOrHideComments(true);

15. 在用户界面中您可以方便地将一个新的批注插入到工作表中。


16. 在示例工作表中显示所有批注后

Worksheet 类提供了它的 Comments 属性,这个属性返回一个 Comments 对象。这个 Comment 对象集合允许您循环访问和 Worksheet 相关的所有 Comment 对象。 Comment 类并没有提供很多成员。可以使用 Comment 类的 Visible 属性来显示或者隐藏批注,或者使用 Delete 方法删除批注。此外,您可能发现 Text 方法很有用:这个方法允许您将文本添加到批注中,可以添加到现有文本的后面,也可以覆盖现有的文本。

添加一个批注后,您可能想要显示工作表中的批注。示例项目包含一个过程 ShowOrHideComments,这个过程会显示或者隐藏所有在活动工作表中的批注:

' Visual Basic
Private Sub ShowOrHideComments(ByVal Show As Boolean)
' Show or hide all the comments:
Dim ws As Excel.Worksheet = _
DirectCast(ThisApplication.Sheets("Worksheet Class"), _
Excel.Worksheet)
Dim i As Integer
For i = 1 To ws.Comments.Count
ws.Comments(i).Visible = Show
Next
End Sub
// C#
private void ShowOrHideComments(bool show)
{
// Show or hide all the comments:
Excel.Worksheet ws =
(Excel.Worksheet) ThisApplication.Sheets["Worksheet Class"];
for (int i = 1; i <= ws.Comments.Count; i++)
{
ws.Comments[i].Visible = show;
}
}

与 Excel 中的许多辅助集合类相似,Comments 集合没有提供一个默认的枚举器。也就是说,您将不能使用一个 For Each 循环来访问这个集合的所有元素。对于类似 Comment 集合的集合,您必须使用一个索引的循环来循环访问这个集合。

提纲

Excel通过使用提纲功能支持将不同行的数据进行分组。您也可以在代码中利用相同的功能。例如,给定如 17 所示的一组行,您可以添加提纲功能(在所示的图中已添加),这样您就能够将这些行进行折叠(如 18 所示),折叠的组如 19 所示。


17. 创建这些组


18. 折叠的组


19. 完全折叠的组

Worksheet 类提供了 Outline 属性,它本身就是一个 Outline 对象。 Outline 类并没有提供太多成员,下面的列表描述了您可能会使用到的成员:

AutomaticStyles (Boolean) 向 Excel 指示是否对提纲应用自动样式。

SummaryColumn (XlSummaryColumn) 获取或设置摘要列的位置。 XlSummaryColumn 枚举有两个可能使用的值:xlSummaryOnLeftxlSummaryOnRight

SummaryRow (XlSummaryRow) 获取或设置摘要行的位置。 XlSummaryRow 枚举具有两个可能使用的值:xlSummaryAbovexlSummaryBelow

ShowLevels 允许您折叠提纲组或者将其扩展到您想要的行级和(或)列级。您可以给这个方法传递两个参数,如下面的代码所示:

' Visual Basic
            Dim ws As Excel.Worksheet = _
            DirectCast(ThisApplication.ActiveSheet, Excel.Worksheet)
            ' Specify RowLevels and/or ColumnLevels parameters:
            ws.Outline.ShowLevels(RowLevels:=3)
            // C#
            Excel.Worksheet ws =
            (Excel.Worksheet) ThisApplication.ActiveSheet;
            // Specify RowLevels and/or ColumnLevels parameters:
            ws.Outline.ShowLevels(3, Type.Missing);
            

示例工作表包含对应于 2001 (Data2001) 和 2002 (Data2001) 年及整个行集 (AllData) 的数据的命名范围。这些命名范围覆盖工作表的整个范围;要想进行分组,您必须使用包含所有行的范围。对于 2003 的数据,没有一个和其关联的命名范围以便示例代码演示如何将所有的行作为范围使用。

创建组是很简单的:可以调用与一个或多个完整行相对应的一个范围的 Group 方法来创建组。(您可以指定 4 个可选的分组参数,包括:被分组的开始和终止值、按值分组和一个表明分组周期的 Boolean 值数组。该示例中没有使用这些可选参数,因为您很少会使用这些参数。)调用 Ungroup 方法可以取消分组。例如,单击示例工作表上的 WorkwithGroups 链接来运行下面的代码:

' Visual Basic
Private Sub WorkWithGroups()
Dim ws As Excel.Worksheet = _
DirectCast(ThisApplication.ActiveSheet, Excel.Worksheet)
' Set worksheet-level features for the outline.
' In this case, summary rows are below
' the data rows (so Excel knows where to put
' the summary rows), and we don't want Excel
' to format the summary rows--that's already been done.
ws.Outline.SummaryRow = Excel.XlSummaryRow.xlSummaryBelow
ws.Outline.AutomaticStyles = False
' Group the two named ranges. Each of these
' ranges extends across entire rows.
ThisApplication.Range("Data2001").Group()
ThisApplication.Range("Data2002").Group()
ThisApplication.Range("AllData").Group()
' The range of rows from 24 to 27 doesn't have
' a named range, so you can work with that
' range directly.
Dim rng As Excel.Range = _
DirectCast(ws.Rows("24:27"), Excel.Range)
rng.Group()
' Collapse to the second group level.
ws.Outline.ShowLevels(RowLevels:=2)
End Sub
// C#
private void WorkWithGroups()
{
Excel.Worksheet ws =
(Excel.Worksheet) ThisApplication.ActiveSheet;
// Set worksheet-level features for the outline.
// In this case, summary rows are below
// the data rows (so Excel knows where to put
// the summary rows), and we don't want Excel
// to format the summary rows--that's already been done.
ws.Outline.SummaryRow = Excel.XlSummaryRow.xlSummaryBelow;
ws.Outline.AutomaticStyles = false;
// Group the two named ranges. Each of these
// ranges extends across entire rows.
ThisApplication.get_Range("Data2001", Type.Missing).
Group(Type.Missing, Type.Missing, Type.Missing, Type.Missing);
ThisApplication.get_Range("Data2002", Type.Missing).
Group(Type.Missing, Type.Missing, Type.Missing, Type.Missing);
ThisApplication.get_Range("AllData", Type.Missing).
Group(Type.Missing, Type.Missing, Type.Missing, Type.Missing);
// The range of rows from 24 to 27 doesn't have
// a named range, so you can work with that
// range directly.
Excel.Range rng = (Excel.Range)ws.Rows["24:27", Type.Missing];
rng.Group(Type.Missing, Type.Missing, Type.Missing,
Type.Missing);
// Collapse to the second group level.
ws.Outline.ShowLevels(2, Type.Missing);
}

为了对三个命名范围分组,代码只是简单的调用相应范围的 Group 方法:

' Visual Basic
ThisApplication.Range("Data2001").Group()
// C#
ThisApplication.get_Range("Data2001", Type.Missing).
Group(Type.Missing, Type.Missing, Type.Missing, Type.Missing);

为了对未命名的范围分组,代码使用了工作表的 Rows 属性,给定行范围。这个属性返回一个对应于要使用的行的范围:

' Visual Basic
Dim rng As Excel.Range = _
DirectCast(ws.Rows("24:27"), Excel.Range)
rng.Group()
// C#
Excel.Range rng = (Excel.Range)ws.Rows["24:27", Type.Missing];
rng.Group(Type.Missing, Type.Missing, Type.Missing, Type.Missing);

单击示例工作表中的 Clear Groups 链接来运行类似代码,这样可以清除组:

' Visual Basic
Private Sub ClearGroups()
Dim ws As Excel.Worksheet = _
DirectCast(ThisApplication.ActiveSheet, Excel.Worksheet)
' Specify RowLevels and/or ColumnLevels parameters:
ws.Outline.ShowLevels(RowLevels:=3)
Dim rng As Excel.Range = _
DirectCast(ws.Rows("24:27"), Excel.Range)
rng.Ungroup()
ThisApplication.Range("Data2001").Ungroup()
ThisApplication.Range("Data2002").Ungroup()
ThisApplication.Range("AllData").Ungroup()
End Sub
// C#
private void ClearGroups()
{
Excel.Worksheet ws =
(Excel.Worksheet) ThisWorkbook.Sheets["Worksheet Class"];
// Specify RowLevels and/or ColumnLevels parameters:
ws.Outline.ShowLevels(3, Type.Missing);
Excel.Range rng = (Excel.Range) ws.Rows["24:27", Type.Missing];
rng.Ungroup();
ThisApplication.get_Range("Data2001", Type.Missing).Ungroup();
ThisApplication.get_Range("Data2002", Type.Missing).Ungroup();
ThisApplication.get_Range("AllData", Type.Missing).Ungroup();
}

通过使用这些方法,您可以创建和删除组,并且可以控制工作表中显示的组级。

posted on 2007-09-07 15:17  赵俊  阅读(1587)  评论(0)    收藏  举报