ExcelDna: 如何判断普通工作表是否为活动工作表?
我有一个VBA函数,用来检查当前活动的工作表类型。这个函数始终返回正确的结果:
Sub CheckSheetType()
' 1 = Worksheet
' 2 = Chart
' 3 = Macro sheet
' 4 = Info window if active
' 5 = Reserved
' 6 = Module
' 7 = Dialog
Debug.Print ExecuteExcel4Macro("GET.DOCUMENT(3)")
End Sub
对于我的加载项,我希望只有当一个 普通 工作表处于活动状态时,功能区才启用,在其他所有情况下都应禁用。因此我写了这个函数:
Private Function IsNormalWorksheetActive() As Boolean
Try
Dim app = ExcelDna.Integration.ExcelDnaUtil.Application
If app Is Nothing OrElse app.Workbooks.Count = 0 Then
Return False
End If
Dim result As Object = app.ExecuteExcel4Macro("GET.DOCUMENT(3)")
If result Is Nothing Then Return False
Dim sheetType As Integer = CInt(result)
Return sheetType = 1
Catch
Return False
End Try
End Function
不幸的是,这个函数总是返回FALSE。因此,作为替代,我尝试了一个COM方案:
Private Function IsNormalWorksheetActive() As Boolean
Try
Dim app As Microsoft.Office.Interop.Excel.Application =
CType(ExcelDna.Integration.ExcelDnaUtil.Application,
Microsoft.Office.Interop.Excel.Application)
If app Is Nothing OrElse app.Workbooks.Count = 0 Then
Return False
End If
Dim sheet As Object = app.ActiveSheet
If sheet Is Nothing Then Return False
If TypeOf sheet Is Microsoft.Office.Interop.Excel.Worksheet Then
Dim typeName As String = Microsoft.VisualBasic.TypeName(sheet)
Return String.Equals(typeName, "Worksheet", StringComparison.OrdinalIgnoreCase)
End If
Return False
Catch
Return False
End Try
End Function
然而,这个函数并不能区分工作表和宏工作表,因此我的功能区在宏工作表上也会启用。
请问有人能给出解决方案吗?
解决方案
在Tim的注释之后,我以为检查工作表的 type-属性就足够了(参见 https://learn.microsoft.com/en-us/office/vba/api/excel.xlsheettype)。结果发现这只是事实的一半。
我创建了一个包含Office 365提供的五种工作表类型的工作簿:

并让以下代码运行:
Dim sh As Object ' (There is no basic sheet type, so we need Object)
For Each sh In ThisWorkbook.Sheets
Dim typ As String
typ = "unknown"
On Error Resume Next
typ = sh.Type
On Error GoTo 0
Debug.Print sh.name, typ, TypeName(sh)
Next
这是结果:
Sheet1 -4167 Worksheet
Dialog1 unknown DialogSheet
Macro1 3 Worksheet
Macro2 4 Worksheet
Chart1 3 Chart
3个惊喜:
- 图表工作表的类型是3(
xlExcel4MacroSheet),而不是 -4109(xlChart)。 - DialogSheet没有
Type属性。 - 宏工作表的TypeName是
Worksheet
因此要获取真正的工作表类型名称,必须同时检查 Type 和 TypeName,并在遇到DialogSheet时捕捉可能产生的异常。
Function getSheetTypeName(sh As Object)
Dim typ As Long, sheetTypeName As String
On Error Resume Next
typ = sh.Type
sheetTypeName = TypeName(sh)
On Error GoTo 0
Select Case typ
Case xlWorksheet:
getSheetTypeName = "Worksheet"
Case 0:
getSheetTypeName = sheetTypeName ' Should be DialogSheet
Case xlExcel4MacroSheet:
' Handle the fact the type of Chart is xlExcel4MacroSheet, not xlChart
getSheetTypeName = IIf(sheetTypeName = "Worksheet", "Excel4Macro", sheetTypeName)
Case xlExcel4IntlMacroSheet:
getSheetTypeName = "Excel4MacroInternational"
Case Else
getSheetTypeName = "Unknown: Type=" & typ & " TypeName=" & sheetTypeName
End Select
End Function
然而,要简单地检查你是否在处理工作表,只需检查 Type-属性(遇到DialogSheet时会抛出异常,请捕捉)。
Function isWorksheet(sh As Object) As Boolean
On Error Resume Next
isWorksheet = sh.Type = xlWorksheet
End Function
将我的测试代码输出修改为
Debug.Print sh.name, typ, TypeName(sh), isWorksheet(sh), getSheetTypeName(sh)
得到如下结果:
Sheet1 -4167 Worksheet True Worksheet
Dialog1 unknown DialogSheet False DialogSheet
Macro1 3 Worksheet False Excel4Macro
Macro2 4 Worksheet False Excel4MacroInternational
Chart1 3 Chart False Chart
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。