2015-01-02 2 views
1

Я пишу очень простой подпроцесс, чтобы присвоить класс букв цифровым значениям класса. У меня есть цикл, и я пытаюсь установить значение ячейки для вывода моей функции. Это кажется очень простой задачей, но первые две итерации моих циклов не присваивают никаких значений. Моя петля проходит только 4 строки.Итерация VBA, не возвращающая значение

Function get_letter(grade As Double) 
    Select Case grade 
     Case 0 To 59: letter = "F" 
     Case 60 To 69: letter = "D" 
     Case 70 To 79: letter = "C" 
     Case 80 To 89: letter = "B" 
     Case 90 To 100: letter = "A" 
    End Select 
    get_letter = letter 
End Function 

Sub assign_letter_grade() 
    Dim x As Integer 
    Dim grade As Range 
    Dim letter As Range 

    num_rows = Range("A2", Range("A2").End(xlDown)).Rows.Count 

    Set grade = Range("J2") 
    Set letter = Range("K2") 

    For x = 1 To num_rows 
     letter.Value = get_letter(grade.Value) 
     Set grade = grade.Offset(1, 0) 
     Set letter = letter.Offset(1, 0) 
    Next 
End Sub 

Почему это не задает значения моих первых двух строк в цикле?

+0

Что происходит, когда вы кладете '= get_letter (J2)' в K2 и заполняете? Могут ли значения в столбце J быть текстовыми, маскирующимися как числа? – Jeeped

+0

Значение J2 представляет собой расчет - = IF (SUM (C2: F2) /400*0.2*100+MAX (G2: H2) /100*0.8*100> 100, 100, SUM (C2: F2)/400 * 0.2 * 100 + MAX (G2: H2) /100*0.8*100) – Ptrkcon

+0

Просто, чтобы быть уверенным, что я выбрал значение с помощью CDbl и все тот же результат – Ptrkcon

ответ

3

Попробуйте это:

Function get_letter(grade As Double) As String 
    if grade < 60 Then 
     get_letter = "F" 
    Elseif grade < 70 Then 
     get_letter = "D" 
    Elseif grade < 80 Then 
     get_letter = "C" 
    Elseif grade < 90 Then 
     get_letter = "B" 
    Else 
     get_letter = "A" 
    End If 
End Function 
1

Проблема возникает из оценок, которые НЕ включены в диапазон. Для VBA оценка от 79.25 не падает в любом случае C или B. Вы можете попробовать, чтобы увидеть, если ниже будет решить эту проблему:

Function get_letter(grade As Double) 
Select Case grade 
    Case 0 To 59.99: letter = "F" 
    Case 60 To 69.99: letter = "D" 
    Case 70 To 79.99: letter = "C" 
    Case 80 To 89.99: letter = "B" 
    Case 90 To 100.99: letter = "A" ' assuming student can get a score over 100 
End Select 
get_letter = letter 
End Function 
+0

Работает. Есть ли лучший способ изменить диапазон в аргументе case? Это просто выглядит уродливо для меня. – Ptrkcon

+0

Существует функция Round(), которую вы можете использовать на счетах перед тем, как перейти к макросу, где вы можете сохранить исходный код, но зависит от того, как вы его определяете ... Я имею в виду, что 79.25 считается B или C? (Я бы сказал B, если я студент) – Alex

+0

Посмотрите на ответ Джин, это может быть лучший выбор – Alex

-1

Потому что вы начинаете в строке 2:

Set grade = Range("J2") 
Set letter = Range("K2") 

, а затем сразу компенсировано 1 строку в цикле:

Set grade = grade.Offset(1, 0) 
Set letter = letter.Offset(1, 0) 

поэтому недостающие строки 1 по 2 и, начиная с Row 3. Используйте переменную x в цикле, чтобы исправить эту проблему:

For x = 1 To num_rows 
    letter.Value = get_letter(grade.Value) 
    Set grade = Range("J" & x) 
    Set letter = Range("K" & x) 
Next 
1

Или с помощью INDEX/MATCH

Function get_letter(grade As Double) As String 
get_letter = Evaluate("INDEX({""F"",""D"",""C"",""B"",""A""},MATCH(" & grade & ",{0,60,70,80,90,100}))") 
End Function 

образец

Sub b() 
Debug.Print get_letter(59.99) 
Debug.Print get_letter(60) 
End Sub