ExcelDna: 如何判断普通工作表是否为活动工作表?

后端开发 2026-07-09

我有一个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提供的五种工作表类型的工作簿: enter image description here

并让以下代码运行:

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

因此要获取真正的工作表类型名称,必须同时检查 TypeTypeName,并在遇到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导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章