Excel vba ошибка при захвате старого значения - PullRequest
1 голос
/ 19 июня 2019

Я получаю сообщение об ошибке при попытке получить старое значение из ячейки: ошибка времени выполнения '13' Несоответствие типов.

Это код, который я использую:

Dim oldValue As Variant

Private Sub Worksheet_SelectionChange(ByVal Target As Range)

oldValue = Target(1, 1).Value
MsgBox oldValue

End Sub

Private Sub Worksheet_Change(ByVal Target As Range)

'check if one of the target columns is changed
If Target.Cells.Column = 6 Or Target.Cells.Column = 9 Or Target.Cells.Column = 10 Or Target.Cells.Column = 11 Then

'Set variables
    Dim LogActivity As String
    Dim cRow As Integer
    Dim pRowCount As Integer

    Dim wsPBS As Worksheet
    Dim wsHistoric As Worksheet

    Set wsPBS = Sheets("PBS")
    Set wsHistoric = Sheets("Historic")
    cRow = Target.Cells.Row
    pRowCount = wsHistoric.Range("A" & Rows.Count).End(xlUp).Row + 1

'Check for blanks on PBS sheet and exit if entry is not complete
    Dim BlankCount As Integer
    BlankCount = 0

    If wsPBS.Range("D" & cRow).Value = "" Then BlankCount = BlankCount + 1
    If wsPBS.Range("E" & cRow).Value = "" Then BlankCount = BlankCount + 1
    If wsPBS.Range("F" & cRow).Value = "" Then BlankCount = BlankCount + 1
    If wsPBS.Range("H" & cRow).Value = "" Then BlankCount = BlankCount + 1
    If wsPBS.Range("I" & cRow).Value = "" Then BlankCount = BlankCount + 1
    If wsPBS.Range("J" & cRow).Value = "" Then BlankCount = BlankCount + 1

    If BlankCount >= 1 Then Exit Sub

    Application.ScreenUpdating = False
    Application.DisplayAlerts = False

        If Target.Cells.Column = 6 Then LogActivity = "Owner change"
        If Target.Cells.Column = 9 Then LogActivity = "Status change"
        If Target.Cells.Column = 10 Then LogActivity = "Priority change"
        If Target.Cells.Column = 11 Then LogActivity = "Completion rate"

    Range("C" & cRow & ":O" & cRow).Select
        Selection.Copy

    wsHistoric.Select
    wsHistoric.Range("F" & pRowCount).Select
        Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
        Application.CutCopyMode = False

    wsHistoric.Range("A" & pRowCount).Value = Date
    wsHistoric.Range("B" & pRowCount).Value = Time
    wsHistoric.Range("C" & pRowCount).Value = Application.UserName
    wsHistoric.Range("D" & pRowCount).Value = LogActivity
    wsHistoric.Range("E" & pRowCount).Value = oldValue

    Application.ScreenUpdating = True
    Application.DisplayAlerts = True

End If

End Sub

Предполагается, что значение будет храниться в глобальном dim, называемом oldValue, чтобы я мог использовать его позже в своем коде.Ячейка, по которой я щелкаю, содержит строку.

Есть предложения?

Ответы [ 2 ]

1 голос
/ 19 июня 2019

Основной выпуск:

Вы Select участвуете в событии Worksheet_Change.

Range("C" & cRow & ":O" & cRow).Select
Selection.Copy

Это снова вызывает событие Selection_Change, перезаписывая oldValue.

Нет необходимости Select здесь. См. Как избежать использования Select в Excel VBA .

Range("C" & cRow & ":O" & cRow).Copy

Вторичный (но все еще очень важный вопрос):

В вашей исходной версии изменения выбора:

Dim oldValue As String

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    oldValue = Target.Value
End Sub

Это приведет к ошибке несоответствия типов, если Target не содержит String или что-то, что может быть приведено к String.

В вашем случае это было потому, что Target на самом деле было несколькими ячейками: Range("C" & cRow & ":O" & cRow). Но ваш код также выдаст ошибку, если вы выберете ячейку со значением ошибки (#N/A, #DIV/0 и т. Д.).


Исправление:

Прежде всего, избегайте использования Select, как уже отмечалось.

Если по какой-либо (редкой) причине вам абсолютно необходимо Select, то включайте и выключайте события:

Private Worksheet_Change(ByVal Target As Range)
    Application.EnableEvents = False
    ... do your stuff
    Application.EnableEvents = True
End Sub

Наконец, при изменении выбора вместо того, чтобы предполагать, что вы выберете только строку или только одну ячейку, добавьте некоторую проверку.

Dim oldValue As Variant

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    If Target.CountLarge <> 1 Then Exit Sub ' ignore a multi-cell selection
    If IsError(Target.Value) Then Exit Sub ' ignore selection of errors

    oldValue = Target.Value
End Sub
0 голосов
/ 19 июня 2019

Попробуйте определить одну ячейку с помощью Target:

oldValue = Target(1,1).Value
...