Как проверить несколько ячеек и изменить значения в зависимости от условия? - PullRequest
1 голос
/ 17 июня 2019

Я пытаюсь использовать этот код, чтобы преобразовать оценки в проходные или неудачные значения для нескольких учащихся и нескольких предметов;однако, по некоторым причинам, это работает, когда я делаю это для одной ячейки за раз, но выдает ошибку, когда я использую диапазон.Я знаю, что это очень простой код, но любая помощь будет оценена

Private Sub CommandButton1_Click()
    If Sheets("sheet1").Range("B3:E7").Value < 35 Then
        Sheets("sheet1").Range("B3:E7").Value = "Fail"
    Else: Sheets("sheet1").Range("B3:E7").Value = "Pass"

    End If

End Sub

ошибка времени выполнения 13 Несоответствие типов

Ответы [ 3 ]

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

@ Ответ RobertTodar может быть сокращен до:

For Each Cell In Target
    Cell = IIf(Cell < 35, "Fail", "Pass")
Next Cell
0 голосов
/ 17 июня 2019

Sheets("sheet1").Range("B3:E7").Value < 35 в этой строке вы пытаетесь сравнить весь диапазон, что не совсем так.

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

Как и другие предлагали, цикл необходим, если вы хотите сделать это в VBA, хотя некоторые формулы могли бы выполнить аналогичную работу, или условное форматирование, если вы просто хотелисм. отображаемые результаты.

См. больше комментариев в коде, надеюсь, это поможет:

Private Sub CommandButton1_Click()

Dim ws As Worksheet
Set ws = ActiveWorkbook.Sheets("Sheet5") 'declare and allocate the sheet to a variable

Dim lRow As Long
lRow = ws.Cells(Rows.Count, "A").End(xlUp).Row 'get last row at column A, assuming student names there

Dim arrData As Variant
arrData = ws.Range("B1:E" & lRow) 'declare and allocate your data to an array

Dim R As Long, C As Long
For R = LBound(arrData) + 2 To UBound(arrData) 'for each row in your data, starting at row 3
    For C = LBound(arrData, 2) To UBound(arrData, 2) 'for each column in your data
        If arrData(R, C) <> "" And IsNumeric(arrData(R, C)) Then 'only want a fail/pass for an actual number
            If arrData(R, C) < 34 Then
                arrData(R, C) = "Fail"
            ElseIf arrData(R, C) >= 35 Then
                arrData(R, C) = "Pass"
            End If
        End If
    Next C
Next R

ws.Range("B1:E" & lRow) = arrData 'allocate the data back to the sheet

End Sub

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

По сути, чем меньше вы взаимодействуете с листом, тем лучше.В приведенном выше примере доступ к листу возможен только дважды: один раз для чтения данных и один раз для их записи, а все остальное выполняется в памяти.

0 голосов
/ 17 июня 2019

То, как вы написали свой код, было бы попыткой рекурсивного программирования , и вы не можете сделать это таким образом в VBA. Что вам нужно в вашем коде, так это простой цикл.

Чтобы зациклить Range, вам нужна переменная с типом данных Range. Я назову эту переменную Cell.

Теперь в вашем цикле вы можете использовать Cell, чтобы проверить, проходит ли он или нет, и у вас есть возможность обновить его значение.

Dim Target As Range
Set Target = Worksheets("sheet1").Range("B3:E7")

Dim Cell As Range
For Each Cell In Target
    If Cell.Value < 35 Then
        Cell.Value = "Fail"
    Else
        Cell.Value = "Pass"
    End If
Next Cell

Еще одна вещь, на которую вы, возможно, захотите взглянуть, - это отказаться от жесткого кодирования вашего диапазона от Range("B3:E7") до более динамического диапазона на случай, если что-то изменится. Вы можете сделать что-то вроде поиска последней использованной строки в столбце E. Вот пример получения этого:

Set Target = Worksheets("sheet1").Range("B3", Range("E" & Rows.Count).End(xlUp))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...