从工作簿事件

时间:2017-04-19 13:49:35

标签: excel vba excel-vba

我有一个Worksheet_SelectionChange事件需要知道在更改事件运行之前范围内的详细信息。为此,事件的一部分记录当前状态,另一部分查看事件运行的上一次记录,并使用它们。我将日志保存为全局变量。我的代码步骤如下:

'Declarations:
Private oldT() As Double
Private oldHigh As Range
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
'''
'1) Read range stored in oldHigh
'''
Dim newHigh as Range
Dim newT() As Double
Set newHigh= Target 'range we are currently working on
ReDim newT(1 To newHigh.Cells.Count, 1 To 3) '
'''
'2) Loop through each Cell in newHigh and pass 3 details to newT()
'   This saves the current state
'''
'3) Make temporary change to newHigh
'''
'4) Loop through oldHigh, using the values saved in oldT() to reset it
'''
Set oldHigh = newHigh'log where you made the temporary changes
oldT = newT 'and what the cells were before the changes
End Sub

我没有使用Workbook_Open初始化变量,而是在我的选择更改代码(步骤1之前)中进行错误检查,以防oldHigh为空。

这一切都很好,除了我现在意识到如果我保存并退出,最后的重置动作不会发生。所以我决定在4)事件中执行步骤Workbook_BeforeSave,这样工作簿就不会保存临时更改(使其永久化) 该代码如下所示:

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
    Dim i As Long
    Dim subCell As Range
    Dim oldHigh As Range: Set oldHigh = [a1]
    For i = 1 To lastCol 'reset
        Set subCell = oldHigh(1, i)
        With subCell.Interior
            .Color = oldT(i, 3)
            .TintAndShade = oldT(i, 2)
            .Pattern = oldT(i, 1)
        End With
    Next i
    Set oldHigh = Nothing 'Required if user saves but does not exit,
                          'This makes the workbook look as if it is freshly opened 
                          'Which is what my code is designed to handle
End Sub

(如您所见,保存的数据是填充信息,我暂时更改填充以突出显示选择,然后将其更改回之后的状态)

问题

当我运行该保存事件时,代码无法访问oldT()oldHigh。我猜这是因为它们是Private所以我制作了它们Public,但这会产生以下错误: Error message

如何从工作簿事件中访问这些电子表格变量?

实际代码:

避免混淆。注意newHigh在此处称为highRng

Private oldT() As Double
Private oldHigh As Range

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim myTbl As ListObject
Dim oldHighTest As Boolean
Set myTbl = Me.ListObjects(1)
If oldHigh Is Nothing Then
    oldHighTest = True
Else
    oldHighTest = Intersect(oldHigh, Target) Is Nothing
End If
If Not Intersect(Target, myTbl.Range) Is Nothing And oldHighTest Then ' highlight cells in table only when new row of table is selected
    appMod False
    On Error GoTo e
    Dim tl As Range, highRng As Range, subCell As Range
    Dim newT() As Double, lastCol As Long, i As Long
    Set tl = myTbl.HeaderRowRange(1)
    Set highRng = Me.Range(Cells(Target.Row, tl.Column), Cells(Target.Row, tl.Column + myTbl.ListColumns.Count - 1))
    lastCol = highRng.Columns.Count
    ReDim newT(1 To lastCol, 1 To 3) '
    For i = 1 To lastCol 'save
        Set subCell = highRng(1, i)
        With subCell.Interior
            newT(i, 1) = .Pattern
            newT(i, 2) = .TintAndShade
            newT(i, 3) = .Color
        End With
    Next i
    With highRng.Interior 'highlight
        .Pattern = xlSolid
        .TintAndShade = 1
        .Color = 4189681
    End With
    For i = 1 To lastCol 'reset last highlight using last save
        Set subCell = oldHigh(1, i)
        With subCell.Interior
            .Color = oldT(i, 3)
            .TintAndShade = oldT(i, 2)
            .Pattern = oldT(i, 1)
        End With
    Next i

e:  appMod True
    Set oldHigh = highRng
    oldT = newT
End If

End Sub

放在Sheet1代码中,并突出显示一行table1(或页面中的第一个ListObject,以防我更改表名)  appMod调用的地方

Public Sub appMod(t As Boolean)
With Application
    .EnableEvents = t
    .ScreenUpdating = t
End With
End Sub

更改

时出现问题
Private oldT()

Public oldT()

但是oldHigh Public没有问题,只是在ThisWorkbook代码中仍未找到它(如果不是,则会被视为空白)

1 个答案:

答案 0 :(得分:0)

如我的评论中所述,将指令插入新模块而不是sheet1

public oldT()

错误消息提到对象模块中不允许使用公共数组。我在msdn上找不到更多信息。