Sri Ramakrishna Sharadadevi Vidyamandira

SA-2 Calculations Process

Steps to Process SA-2 Bulk Results

  • Download the SA-2 bulk results file from the website.
  • Open the downloaded file in Excel
  • Press Alt + F11 (or Alt + Fn + F11 on some laptops) to open the VBA editor
  • In the editor, click Insert > Module.
  • Copy and paste the code provided below into the module window.
  • Run the code.
  • When prompted, enter the maximum marks for each subject you conducted during the SA-2 exam.
Sub DetectConvertAndCopyToNewSheetRounded()
    Dim ws As Worksheet
    Dim newSheet As Worksheet
    Dim header As String
    Dim i As Integer
    Dim maxValue As Double
    Dim max1Value As Double
    Dim lastRow As Long
    Dim cell As Range
    Dim inputMaxValue As Variant
    Dim inputMax1Value As Variant
    Dim copyColumn As Integer
    Dim multiplier As Double
    
    ' Set the active sheet
    Set ws = ActiveSheet
    
    ' Create or activate the new sheet named "80marks SA1"
    On Error Resume Next
    Set newSheet = ThisWorkbook.Worksheets("80marks SA1")
    On Error GoTo 0
    If newSheet Is Nothing Then
        Set newSheet = ThisWorkbook.Worksheets.Add
        newSheet.Name = "80marks SA1"
    Else
        newSheet.Cells.Clear ' Clear existing content if the sheet already exists
    End If
    
    ' Copy columns A to D from the original sheet to the new sheet
    ws.Range("A:D").Copy Destination:=newSheet.Range("A1")
    
    ' Loop through the first 80 columns to check for "max" or "max1" in headers
    copyColumn = 5 ' Start copying calculated columns to column E in the new sheet
    For i = 1 To 80
        header = LCase(Trim(ws.Cells(1, i).Value))
        
        ' Check if the column header contains "max" (but not "max1")
        If InStr(header, "max") > 0 And InStr(header, "max1") = 0 Then
            ' Prompt for input max value for "max" columns
            inputMaxValue = InputBox("Enter the desired max value for column '" & ws.Cells(1, i).Value & "':", "Enter Max Value", 80)
            If inputMaxValue = "" Or Not IsNumeric(inputMaxValue) Then
                MsgBox "Invalid input or operation canceled for column '" & ws.Cells(1, i).Value & "'.", vbExclamation
                Exit Sub
            End If
            maxValue = CDbl(inputMaxValue)
            
            ' Determine multiplier based on user input:
            ' For 40: multiplier = 80/40 = 2  (same as marks*(8/4))
            ' For 50: multiplier = 80/50 = 1.6 (marks*(8/5))
            ' For 60: multiplier = 80/60 ≈ 1.33 (marks*(8/6))
            ' For 70: multiplier = 80/70 ≈ 1.14 (marks*(8/7))
            ' For 80: multiplier = 80/80 = 1   (marks*(8/8))
            ' For 25: multiplier = 4 (marks*4)
            ' For 20: multiplier = 5 (marks*5)
            If maxValue = 25 Then
                multiplier = 4
            ElseIf maxValue = 20 Then
                multiplier = 5
            Else
                multiplier = 80 / maxValue
            End If
            
            ' Copy header from the original column to the new sheet
            newSheet.Cells(1, copyColumn).Value = ws.Cells(1, i).Value
            
            ' Get the last row in the "max" column
            lastRow = ws.Cells(ws.Rows.Count, i).End(xlUp).Row
            
            ' Calculate and store the adjusted values, rounded to 1 decimal place
            For Each cell In ws.Range(ws.Cells(2, i), ws.Cells(lastRow, i))
                If IsNumeric(cell.Value) And cell.Value > 0 Then
                    newSheet.Cells(cell.Row, copyColumn).Value = Round(cell.Value * multiplier, 1)
                End If
            Next cell
            
            ' Move to the next column in the new sheet
            copyColumn = copyColumn + 1
            
        ' Check if the column header contains "max1"
        ElseIf InStr(header, "max1") > 0 Then
            ' Prompt for input max1 value for "max1" columns
            inputMax1Value = InputBox("Enter the desired max1 value for column '" & ws.Cells(1, i).Value & "':", "Enter Max1 Value", 100)
            If inputMax1Value = "" Or Not IsNumeric(inputMax1Value) Then
                MsgBox "Invalid input or operation canceled for column '" & ws.Cells(1, i).Value & "'.", vbExclamation
                Exit Sub
            End If
            max1Value = CDbl(inputMax1Value)
            
            ' Determine multiplier based on user input for max1 value
            If max1Value = 25 Then
                multiplier = 4
            ElseIf max1Value = 20 Then
                multiplier = 5
            Else
                multiplier = 80 / max1Value
            End If
            
            ' Copy header from the original column to the new sheet
            newSheet.Cells(1, copyColumn).Value = ws.Cells(1, i).Value
            
            ' Get the last row in the "max1" column
            lastRow = ws.Cells(ws.Rows.Count, i).End(xlUp).Row
            
            ' Calculate and store the adjusted values, rounded to 1 decimal place
            For Each cell In ws.Range(ws.Cells(2, i), ws.Cells(lastRow, i))
                If IsNumeric(cell.Value) And cell.Value > 0 Then
                    newSheet.Cells(cell.Row, copyColumn).Value = Round(cell.Value * multiplier, 1)
                End If
            Next cell
            
            ' Move to the next column in the new sheet
            copyColumn = copyColumn + 1
        End If
    Next i
    
    ' Sort the new sheet data based on the student names in column B (alphabetic order)
    With newSheet
        lastRow = .Cells(.Rows.Count, "B").End(xlUp).Row
        With .Sort
            .SortFields.Clear
            .SortFields.Add Key:=.Parent.Range("B2:B" & lastRow), Order:=xlAscending
            .SetRange .Parent.Range("A1").CurrentRegion
            .Header = xlYes
            .Apply
        End With
    End With
    
    MsgBox "Marks have been updated, copied to the new sheet '80marks SA1', and student names in column B are sorted alphabetically." & vbCrLf & "Calculated values are rounded to 1 decimal place.", vbInformation
End Sub

In step-2

  • Copy the code below and run it to round up the marks.

CSS Code Example

This is a sample CSS snippet

  • Styling elements
  • Modern design
  • Responsive layout
div {
  color: red;
}
Sub RoundDecimals()
    Dim ws As Worksheet
    Dim cell As Range
    Dim lastRow As Long, lastCol As Long
    Dim decimalPart As Double
    
    ' Set the active sheet to ws
    Set ws = ActiveSheet
    
    ' Find the last row and last column with data
    lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
    lastCol = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column
    
    ' Loop through each column and each row in the used range
    For Each cell In ws.Range(ws.Cells(1, 1), ws.Cells(lastRow, lastCol))
        ' Check if the cell has a numeric value
        If IsNumeric(cell.Value) Then
            ' Check if it has a decimal part
            If cell.Value <> Int(cell.Value) Then
                ' Get the decimal part of the cell value
                decimalPart = cell.Value - Int(cell.Value)
                
                ' Round down if less than 0.5, round up if 0.5 or more
                If decimalPart < 0.5 Then
                    cell.Value = WorksheetFunction.RoundDown(cell.Value, 0)
                Else
                    cell.Value = WorksheetFunction.RoundUp(cell.Value, 0)
                End If
            End If
        End If
    Next cell
    
    MsgBox "Rounding process complete."
End Sub

In step-3

  • Copy the calculated marks of FA-3, FA-4, and SA-2 into a new sheet.
  • Then, copy and run the code below.
Sub CalculateSubjectScores()
    Dim ws As Worksheet
    Dim numSubjects As Integer
    Dim i As Integer
    Dim fa1Col As Range, fa2Col As Range, sa1Col As Range, resultCol As Range
    Dim lastRow As Integer
    Dim subjectTitle As String
    
    ' Set active worksheet
    Set ws = ActiveSheet
    
    ' Ask for the number of subjects
    numSubjects = Application.InputBox("Enter the number of subjects:", Type:=1)
    If numSubjects <= 0 Then Exit Sub
    
    ' Loop through each subject to get column selections
    For i = 1 To numSubjects
        subjectTitle = Application.InputBox("Enter the subject title for Subject " & i & ":", Type:=2)
        Application.StatusBar = "Select columns for " & subjectTitle
        
        ' Select FA1 column
        On Error Resume Next
        Set fa1Col = Application.InputBox("Select FA1 column for " & subjectTitle, Type:=8)
        If fa1Col Is Nothing Then Exit Sub
        
        ' Select FA2 column
        Set fa2Col = Application.InputBox("Select FA2 column for " & subjectTitle, Type:=8)
        If fa2Col Is Nothing Then Exit Sub
        
        ' Select SA1 column
        Set sa1Col = Application.InputBox("Select SA1 column for " & subjectTitle, Type:=8)
        If sa1Col Is Nothing Then Exit Sub
        
        ' Select column for calculated data
        Set resultCol = Application.InputBox("Select result column for " & subjectTitle, Type:=8)
        If resultCol Is Nothing Then Exit Sub
        
        ' Set subject title in the result column header
        ws.Cells(1, resultCol.Column).Value = subjectTitle & " Score"
        
        ' Find last row in FA1 column
        lastRow = ws.Cells(ws.Rows.Count, fa1Col.Column).End(xlUp).Row
        
        ' Apply new formula: SA1 + FA1 + FA2
        ws.Range(resultCol.Cells(2, 1), resultCol.Cells(lastRow, 1)).FormulaR1C1 = _
            "=RC[" & (sa1Col.Column - resultCol.Column) & "] + RC[" & (fa1Col.Column - resultCol.Column) & "] + RC[" & (fa2Col.Column - resultCol.Column) & "]"
    Next i
    
    ' Clear status bar and show completion message
    Application.StatusBar = False
    MsgBox "Calculation completed!", vbInformation
End Sub

In step 4

For class 1-3

  • Copy and run the code below to calculate T2 marks
    (FA-1: 10 marks + FA-2: 10 marks + SA-2: 80 marks).
    
                        
                        Option Explicit

Sub ProcessData()
    Dim wsSource As Worksheet, wsSorted As Worksheet, wsOutput As Worksheet, wsRound As Worksheet
    Dim lastRow As Long, lastCol As Long, i As Long, j As Long
    Dim headerRow As Range
    
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    
    '---------------------------
    ' Step 1. Use the active sheet as the source data.
    Set wsSource = ActiveSheet
    
    '---------------------------
    ' Step 2. Ensure Sheet2 exists for sorted data.
    On Error Resume Next
    Set wsSorted = Worksheets("Sheet2")
    If wsSorted Is Nothing Then
        Set wsSorted = Worksheets.Add(After:=wsSource)
        wsSorted.Name = "Sheet2"
    Else
        wsSorted.Cells.Clear
    End If
    
    '---------------------------
    ' Step 3. Ensure Sheet3 exists for final output.
    Set wsOutput = Worksheets("Sheet3")
    If wsOutput Is Nothing Then
        Set wsOutput = Worksheets.Add(After:=wsSorted)
        wsOutput.Name = "Sheet3"
    Else
        wsOutput.Cells.Clear
    End If
    On Error GoTo 0
    
    '---------------------------
    ' Step 4. Delete empty Remark columns from wsSource.
    lastCol = wsSource.Cells(1, wsSource.Columns.Count).End(xlToLeft).Column
    Set headerRow = wsSource.Range(wsSource.Cells(1, 1), wsSource.Cells(1, lastCol))
    For j = lastCol To 1 Step -1
        If InStr(1, wsSource.Cells(1, j).Value, "Remark", vbTextCompare) > 0 Then
            ' Delete if only the header is nonblank.
            If Application.WorksheetFunction.CountA(wsSource.Columns(j)) = 1 Then
                wsSource.Columns(j).Delete
            End If
        End If
    Next j
    
    '---------------------------
    ' Step 5. Copy cleaned data to Sheet2 and sort by Student Name.
    wsSource.UsedRange.Copy Destination:=wsSorted.Range("A1")
    
    ' Find the Student Name column.
    lastCol = wsSorted.Cells(1, wsSorted.Columns.Count).End(xlToLeft).Column
    Dim colStudentName As Long: colStudentName = 0
    For j = 1 To lastCol
        If InStr(1, wsSorted.Cells(1, j).Value, "Student Name", vbTextCompare) > 0 Then
            colStudentName = j
            Exit For
        End If
    Next j
    
    If colStudentName > 0 Then
        lastRow = wsSorted.Cells(wsSorted.Rows.Count, colStudentName).End(xlUp).Row
        wsSorted.Range("A1").CurrentRegion.Sort Key1:=wsSorted.Cells(2, colStudentName), Order1:=xlAscending, Header:=xlYes
    Else
        MsgBox "Student Name column not found in Sheet2!", vbExclamation
        GoTo CleanUp
    End If
    
    '---------------------------
    ' Step 6. Copy sorted data to Sheet3 for further processing.
    wsSorted.UsedRange.Copy Destination:=wsOutput.Range("A1")
    lastRow = wsOutput.Cells(wsOutput.Rows.Count, 1).End(xlUp).Row
    
    '---------------------------
    ' Step 7. (Removed Average Calculation)
    ' Instead of calculating any averages, we now use the subject columns as they appear.
    ' We assume that columns A to D are identifiers and that subjects start from column E.
    
    '---------------------------
    ' Step 8. Append Overall Totals.
    ' First, determine the subject range: from column E (column 5) to the last column in wsOutput.
    lastCol = wsOutput.Cells(1, wsOutput.Columns.Count).End(xlToLeft).Column
    Dim subjectStart As Long, subjectEnd As Long, subjectCount As Long, maxTotalMarks As Long
    subjectStart = 5
    subjectEnd = lastCol
    subjectCount = subjectEnd - 4  ' Excluding the first 4 identifier columns.
    
    If subjectCount <= 0 Then
        MsgBox "No subject columns found from column E onward.", vbCritical
        GoTo CleanUp
    End If
    
    maxTotalMarks = subjectCount * 100  ' Assuming each subject is out of 100.
    
    ' Append Total Marks, Total Percentage, and Overall Grade columns.
    Dim colTotalMarks As Long, colPercentage As Long, colOverallGrade As Long
    colTotalMarks = lastCol + 1
    wsOutput.Cells(1, colTotalMarks).Value = "Total Marks"
    colPercentage = colTotalMarks + 1
    wsOutput.Cells(1, colPercentage).Value = "Total Percentage"
    colOverallGrade = colPercentage + 1
    wsOutput.Cells(1, colOverallGrade).Value = "Overall Grade"
    
    Dim totalMarks As Double, totalPercentage As Double
    For i = 2 To lastRow
        totalMarks = 0
        For j = subjectStart To subjectEnd
            totalMarks = totalMarks + Val(wsOutput.Cells(i, j).Value)
        Next j
        wsOutput.Cells(i, colTotalMarks).Value = totalMarks
        totalPercentage = (totalMarks / maxTotalMarks) * 100
        wsOutput.Cells(i, colPercentage).Value = Round(totalPercentage, 2)
        wsOutput.Cells(i, colOverallGrade).Value = GetGrade(CustomRound(totalPercentage))
    Next i
    
    '---------------------------
    ' Step 9. Create Sheet4: First apply rounding to calculated columns, then insert Grade columns.
    On Error Resume Next
    Set wsRound = Worksheets("Sheet4")
    If wsRound Is Nothing Then
        Set wsRound = Worksheets.Add(After:=wsOutput)
        wsRound.Name = "Sheet4"
    Else
        wsRound.Cells.Clear
    End If
    On Error GoTo 0
    
    ' Copy all data from Sheet3 to Sheet4.
    wsOutput.UsedRange.Copy Destination:=wsRound.Range("A1")
    lastRow = wsRound.Cells(wsRound.Rows.Count, 1).End(xlUp).Row
    lastCol = wsRound.Cells(1, wsRound.Columns.Count).End(xlToLeft).Column
    
    ' First, apply the custom rounding on calculated columns.
    Dim headerVal As String
    For j = 1 To lastCol
        headerVal = wsRound.Cells(1, j).Value
        ' Process columns with "Average" or "Total" (exclude any column already containing "Grade").
        If (InStr(1, headerVal, "Average", vbTextCompare) > 0 Or _
            InStr(1, headerVal, "Total", vbTextCompare) > 0) And _
           (InStr(1, headerVal, "Grade", vbTextCompare) = 0) Then
           
            For i = 2 To lastRow
                If IsNumeric(wsRound.Cells(i, j).Value) Then
                    wsRound.Cells(i, j).Value = CustomRound(wsRound.Cells(i, j).Value)
                End If
            Next i
        End If
    Next j
    
    ' --- Recalculate Total Percentage and Overall Grade in Sheet4 based on Total Marks ---
    Dim colTotalMarksS4 As Long, colPercS4 As Long, colGradeS4 As Long
    For j = 1 To lastCol
        Select Case wsRound.Cells(1, j).Value
            Case "Total Marks": colTotalMarksS4 = j
            Case "Total Percentage": colPercS4 = j
            Case "Overall Grade": colGradeS4 = j
        End Select
    Next j
    
    ' Set maximum total marks based on subject count.
    Dim maxTotal As Double: maxTotal = subjectCount * 100
    If colTotalMarksS4 > 0 And colPercS4 > 0 And colGradeS4 > 0 Then
        For i = 2 To lastRow
            Dim totMarks As Double, perc As Double
            totMarks = wsRound.Cells(i, colTotalMarksS4).Value
            perc = (totMarks / maxTotal) * 100
            wsRound.Cells(i, colPercS4).Value = CustomRound(perc)
            wsRound.Cells(i, colGradeS4).Value = GetGrade(CustomRound(perc))
        Next i
    End If
    
    ' Now, insert Grade columns for each subject column.
    ' We assume that subject columns are from column E (5) to the subjectEnd.
    ' Loop backward from the last subject column to avoid shifting issues.
    For j = subjectEnd To subjectStart Step -1
        headerVal = wsRound.Cells(1, j).Value
        ' Exclude identifier columns.
        If InStr(1, headerVal, "Roll Number", vbTextCompare) = 0 And _
           InStr(1, headerVal, "Student Name", vbTextCompare) = 0 And _
           InStr(1, headerVal, "Class", vbTextCompare) = 0 And _
           InStr(1, headerVal, "Section", vbTextCompare) = 0 Then
           
           wsRound.Columns(j + 1).Insert Shift:=xlToRight
           wsRound.Cells(1, j + 1).Value = headerVal & " Grade"
           For i = 2 To lastRow
               Dim cellVal As Double
               cellVal = Val(wsRound.Cells(i, j).Value)
               wsRound.Cells(i, j + 1).Value = GetGrade(cellVal)
           Next i
        End If
    Next j
    
CleanUp:
    Application.Calculation = xlCalculationAutomatic
    Application.ScreenUpdating = True
    MsgBox "Processing complete!", vbInformation
End Sub

'---------------------------
' Helper function: Finds the column number where the header cell contains headerText.
Function FindColumn(ws As Worksheet, headerText As String) As Long
    Dim lastCol As Long, j As Long
    lastCol = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column
    For j = 1 To lastCol
        If InStr(1, ws.Cells(1, j).Value, headerText, vbTextCompare) > 0 Then
            FindColumn = j
            Exit Function
        End If
    Next j
    FindColumn = 0
End Function

'---------------------------
' Grade scale function using your provided grading scale.
Function GetGrade(marks As Double) As String
    Select Case marks
        Case 91 To 100
            GetGrade = "A+"
        Case 81 To 90
            GetGrade = "A"
        Case 71 To 80
            GetGrade = "B+"
        Case 61 To 70
            GetGrade = "B"
        Case 51 To 60
            GetGrade = "C+"
        Case 41 To 50
            GetGrade = "C"
        Case 33 To 40
            GetGrade = "D"
        Case 0 To 32
            GetGrade = "E"
        Case Else
            GetGrade = ""
    End Select
End Function

'---------------------------
' Custom rounding function:
' If the fractional part is less than 0.5, return the integer part.
' If the fractional part is 0.5 or greater, return the integer part plus one.
Function CustomRound(val As Double) As Long
    Dim intPart As Long, frac As Double
    intPart = Fix(val)
    frac = val - intPart
    If frac >= 0.5 Then
        CustomRound = intPart + 1
    Else
        CustomRound = intPart
    End If
End Function

For class 4-5

  • Copy and run the code below to calculate T2 marks
    (FA-1: 10 marks + FA-2: 10 marks + SA-2: 80 marks).
    
                        
                       Option Explicit

Sub ProcessData()
    Dim wsSource As Worksheet, wsSorted As Worksheet, wsOutput As Worksheet, wsRound As Worksheet
    Dim lastRow As Long, lastCol As Long, i As Long, j As Long
    Dim headerRow As Range
    
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    
    '---------------------------
    ' Step 1. Use the active sheet as the source data.
    Set wsSource = ActiveSheet
    
    '---------------------------
    ' Step 2. Ensure Sheet2 exists for sorted data.
    On Error Resume Next
    Set wsSorted = Worksheets("Sheet2")
    If wsSorted Is Nothing Then
        Set wsSorted = Worksheets.Add(After:=wsSource)
        wsSorted.Name = "Sheet2"
    Else
        wsSorted.Cells.Clear
    End If
    
    '---------------------------
    ' Step 3. Ensure Sheet3 exists for final output (without grade columns).
    Set wsOutput = Worksheets("Sheet3")
    If wsOutput Is Nothing Then
        Set wsOutput = Worksheets.Add(After:=wsSorted)
        wsOutput.Name = "Sheet3"
    Else
        wsOutput.Cells.Clear
    End If
    On Error GoTo 0
    
    '---------------------------
    ' Step 4. Delete empty Remark columns from wsSource.
    lastCol = wsSource.Cells(1, wsSource.Columns.Count).End(xlToLeft).Column
    Set headerRow = wsSource.Range(wsSource.Cells(1, 1), wsSource.Cells(1, lastCol))
    For j = lastCol To 1 Step -1
        If InStr(1, wsSource.Cells(1, j).Value, "Remark", vbTextCompare) > 0 Then
            ' Delete if only the header is nonblank.
            If Application.WorksheetFunction.CountA(wsSource.Columns(j)) = 1 Then
                wsSource.Columns(j).Delete
            End If
        End If
    Next j
    
    '---------------------------
    ' Step 5. Copy cleaned data to Sheet2 and sort by Student Name.
    wsSource.UsedRange.Copy Destination:=wsSorted.Range("A1")
    
    ' Find the Student Name column.
    lastCol = wsSorted.Cells(1, wsSorted.Columns.Count).End(xlToLeft).Column
    Dim colStudentName As Long: colStudentName = 0
    For j = 1 To lastCol
        If InStr(1, wsSorted.Cells(1, j).Value, "Student Name", vbTextCompare) > 0 Then
            colStudentName = j
            Exit For
        End If
    Next j
    
    If colStudentName > 0 Then
        lastRow = wsSorted.Cells(wsSorted.Rows.Count, colStudentName).End(xlUp).Row
        wsSorted.Range("A1").CurrentRegion.Sort Key1:=wsSorted.Cells(2, colStudentName), Order1:=xlAscending, Header:=xlYes
    Else
        MsgBox "Student Name column not found in Sheet2!", vbExclamation
        GoTo CleanUp
    End If
    
    '---------------------------
    ' Step 6. Copy sorted data to Sheet3 for further processing.
    wsSorted.UsedRange.Copy Destination:=wsOutput.Range("A1")
    lastRow = wsOutput.Cells(wsOutput.Rows.Count, 1).End(xlUp).Row
    
    '---------------------------
    ' Step 7. Insert Calculated Column for English Average.
    Dim english1Col As Long, english2Col As Long, colEnglishAvg As Long
    english1Col = FindColumn(wsOutput, "English 1")
    english2Col = FindColumn(wsOutput, "English 2")
    If english1Col > 0 And english2Col > 0 Then
        wsOutput.Columns(english2Col + 1).Insert Shift:=xlToRight
        wsOutput.Cells(1, english2Col + 1).Value = "English Average"
        colEnglishAvg = english2Col + 1
        For i = 2 To lastRow
            wsOutput.Cells(i, colEnglishAvg).Value = CustomRound((Val(wsOutput.Cells(i, english1Col).Value) + _
                                                                  Val(wsOutput.Cells(i, english2Col).Value)) / 2)
        Next i
    Else
        Dim colEnglishAlt As Long
        colEnglishAlt = FindColumn(wsOutput, "English")
        If colEnglishAlt > 0 Then
            wsOutput.Columns(colEnglishAlt + 1).Insert Shift:=xlToRight
            wsOutput.Cells(1, colEnglishAlt + 1).Value = "English Average"
            colEnglishAvg = colEnglishAlt + 1
            For i = 2 To lastRow
                wsOutput.Cells(i, colEnglishAvg).Value = CustomRound(Val(wsOutput.Cells(i, colEnglishAlt).Value))
            Next i
        Else
            MsgBox "No English columns found.", vbCritical
            GoTo CleanUp
        End If
    End If
    
    '---------------------------
    ' Step 8. Append Overall Totals.
    Dim colTotalMarks As Long, colPercentage As Long, colOverallGrade As Long
    lastCol = wsOutput.Cells(1, wsOutput.Columns.Count).End(xlToLeft).Column
    colTotalMarks = lastCol + 1
    wsOutput.Cells(1, colTotalMarks).Value = "Total Marks"
    colPercentage = colTotalMarks + 1
    wsOutput.Cells(1, colPercentage).Value = "Total Percentage"
    colOverallGrade = colPercentage + 1
    wsOutput.Cells(1, colOverallGrade).Value = "Overall Grade"
    
    Dim englishScore As Double, kannadaScore As Double, hindiScore As Double, mathsScore As Double
    Dim socialScore As Double, scienceScore As Double, computerScore As Double
    Dim gkScore As Double, moralScore As Double, drawingScore As Double
    Dim totalMarks As Double, totalPercentage As Double
    Dim subjectCount As Long, maxTotalMarks As Long
    
    Dim colKannada As Long, colMaths As Long, colComputer As Long
    Dim colHindi As Long, colGK As Long, colMoral As Long, colDrawing As Long
    Dim colSocial As Long, colScience As Long
    colKannada = FindColumn(wsOutput, "Kannada")
    colHindi = FindColumn(wsOutput, "Hindi")
    colMaths = FindColumn(wsOutput, "Maths")
    colSocial = FindColumn(wsOutput, "Social")
    colScience = FindColumn(wsOutput, "Science")
    colComputer = FindColumn(wsOutput, "Computer")
    colGK = FindColumn(wsOutput, "GK")
    colMoral = FindColumn(wsOutput, "Moral")
    colDrawing = FindColumn(wsOutput, "Drawing")
    
    ' Essential subjects check.
    If colEnglishAvg = 0 Or colKannada = 0 Or colHindi = 0 Or colMaths = 0 Or _
       colSocial = 0 Or colScience = 0 Or colComputer = 0 Or colGK = 0 Or _
       colMoral = 0 Or colDrawing = 0 Then
        MsgBox "One or more required subject columns (English, Kannada, Hindi, Maths, Social, Science, Computer, GK, Moral, Drawing) not found.", vbCritical
        GoTo CleanUp
    End If
    
    ' Count subjects (should be 10 subjects).
    subjectCount = 10
    maxTotalMarks = subjectCount * 100
    
    For i = 2 To lastRow
        englishScore = Val(wsOutput.Cells(i, colEnglishAvg).Value)
        kannadaScore = Val(wsOutput.Cells(i, colKannada).Value)
        hindiScore = Val(wsOutput.Cells(i, colHindi).Value)
        mathsScore = Val(wsOutput.Cells(i, colMaths).Value)
        socialScore = Val(wsOutput.Cells(i, colSocial).Value)
        scienceScore = Val(wsOutput.Cells(i, colScience).Value)
        computerScore = Val(wsOutput.Cells(i, colComputer).Value)
        gkScore = Val(wsOutput.Cells(i, colGK).Value)
        moralScore = Val(wsOutput.Cells(i, colMoral).Value)
        drawingScore = Val(wsOutput.Cells(i, colDrawing).Value)
        
        totalMarks = englishScore + kannadaScore + hindiScore + mathsScore + socialScore + scienceScore + computerScore + gkScore + moralScore + drawingScore
        wsOutput.Cells(i, colTotalMarks).Value = totalMarks
        totalPercentage = (totalMarks / maxTotalMarks) * 100
        wsOutput.Cells(i, colPercentage).Value = Round(totalPercentage, 2)
        wsOutput.Cells(i, colOverallGrade).Value = GetGrade(CustomRound(totalPercentage))
    Next i
    
    '---------------------------
    ' Step 9. Create Sheet4: First apply rounding to calculated columns, then insert Grade columns.
    On Error Resume Next
    Set wsRound = Worksheets("Sheet4")
    If wsRound Is Nothing Then
        Set wsRound = Worksheets.Add(After:=wsOutput)
        wsRound.Name = "Sheet4"
    Else
        wsRound.Cells.Clear
    End If
    On Error GoTo 0
    
    ' Copy all data from Sheet3 to Sheet4.
    wsOutput.UsedRange.Copy Destination:=wsRound.Range("A1")
    lastRow = wsRound.Cells(wsRound.Rows.Count, 1).End(xlUp).Row
    lastCol = wsRound.Cells(1, wsRound.Columns.Count).End(xlToLeft).Column
    
    ' First, apply the custom rounding on calculated columns.
    Dim headerVal As String
    For j = 1 To lastCol
        headerVal = wsRound.Cells(1, j).Value
        ' Process columns with "Average" or "Total" (exclude any column already containing "Grade").
        If (InStr(1, headerVal, "Average", vbTextCompare) > 0 Or _
            InStr(1, headerVal, "Total", vbTextCompare) > 0) And _
           (InStr(1, headerVal, "Grade", vbTextCompare) = 0) Then
           
            For i = 2 To lastRow
                If IsNumeric(wsRound.Cells(i, j).Value) Then
                    wsRound.Cells(i, j).Value = CustomRound(wsRound.Cells(i, j).Value)
                End If
            Next i
        End If
    Next j
    
    ' --- Recalculate Total Percentage and Overall Grade in Sheet4 based on Total Marks ---
    Dim colTotalMarksS4 As Long, colPercS4 As Long, colGradeS4 As Long
    For j = 1 To lastCol
        Select Case wsRound.Cells(1, j).Value
            Case "Total Marks": colTotalMarksS4 = j
            Case "Total Percentage": colPercS4 = j
            Case "Overall Grade": colGradeS4 = j
        End Select
    Next j
    
    ' Set maximum total marks to 1000 (10 subjects × 100 marks each).
    Dim maxTotal As Double: maxTotal = 1000
    If colTotalMarksS4 > 0 And colPercS4 > 0 And colGradeS4 > 0 Then
        For i = 2 To lastRow
            Dim totMarks As Double, perc As Double
            totMarks = wsRound.Cells(i, colTotalMarksS4).Value
            perc = (totMarks / maxTotal) * 100
            wsRound.Cells(i, colPercS4).Value = CustomRound(perc)
            wsRound.Cells(i, colGradeS4).Value = GetGrade(CustomRound(perc))
        Next i
    End If
    
    ' Now, insert Grade columns for each calculated subject column.
    ' Define the keywords to determine which columns get a grade column.
    Dim keywords As Variant
    keywords = Array("English", "Kannada", "Hindi", "Social", "Science", _
                     "Maths", "Computer", "GK", "Moral", "Drawing", "Average", "Total")
    
    ' Loop backward from the last column to avoid shifting issues.
    lastCol = wsRound.Cells(1, wsRound.Columns.Count).End(xlToLeft).Column
    For j = lastCol To 1 Step -1
        headerVal = wsRound.Cells(1, j).Value
        ' Exclude identifier columns.
        If InStr(1, headerVal, "Total", vbTextCompare) = 0 And _
           InStr(1, headerVal, "Roll Number", vbTextCompare) = 0 And _
           InStr(1, headerVal, "Student Name", vbTextCompare) = 0 And _
           InStr(1, headerVal, "Class", vbTextCompare) = 0 And _
           InStr(1, headerVal, "Section", vbTextCompare) = 0 And _
           InStr(1, headerVal, "Grade", vbTextCompare) = 0 Then
           
           Dim qualifies As Boolean: qualifies = False
           Dim k As Integer
           For k = LBound(keywords) To UBound(keywords)
               If InStr(1, headerVal, keywords(k), vbTextCompare) > 0 Then
                   qualifies = True
                   Exit For
               End If
           Next k
           
           If qualifies Then
               wsRound.Columns(j + 1).Insert Shift:=xlToRight
               wsRound.Cells(1, j + 1).Value = headerVal & " Grade"
               For i = 2 To lastRow
                   Dim cellVal As Double
                   cellVal = Val(wsRound.Cells(i, j).Value)
                   wsRound.Cells(i, j + 1).Value = GetGrade(cellVal)
               Next i
           End If
        End If
    Next j
    
CleanUp:
    Application.Calculation = xlCalculationAutomatic
    Application.ScreenUpdating = True
    MsgBox "Processing complete!", vbInformation
End Sub

'---------------------------
' Helper function: Finds the column number where the header cell contains headerText.
Function FindColumn(ws As Worksheet, headerText As String) As Long
    Dim lastCol As Long, j As Long
    lastCol = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column
    For j = 1 To lastCol
        If InStr(1, ws.Cells(1, j).Value, headerText, vbTextCompare) > 0 Then
            FindColumn = j
            Exit Function
        End If
    Next j
    FindColumn = 0
End Function

'---------------------------
' Grade scale function using your provided grading scale.
Function GetGrade(marks As Double) As String
    Select Case marks
        Case 91 To 100
            GetGrade = "A+"
        Case 81 To 90
            GetGrade = "A"
        Case 71 To 80
            GetGrade = "B+"
        Case 61 To 70
            GetGrade = "B"
        Case 51 To 60
            GetGrade = "C+"
        Case 41 To 50
            GetGrade = "C"
        Case 33 To 40
            GetGrade = "D"
        Case 0 To 32
            GetGrade = "E"
        Case Else
            GetGrade = ""
    End Select
End Function

'---------------------------
' Custom rounding function:
' If the fractional part is less than 0.5, return the integer part.
' If the fractional part is 0.5 or greater, return the integer part plus one.
Function CustomRound(val As Double) As Long
    Dim intPart As Long, frac As Double
    intPart = Fix(val)
    frac = val - intPart
    If frac >= 0.5 Then
        CustomRound = intPart + 1
    Else
        CustomRound = intPart
    End If
End Function

For class 6-8

  • Copy and run the code below to calculate T2 marks
    (FA-1: 10 marks + FA-2: 10 marks + SA-2: 80 marks).
    
                        
                        Option Explicit

Sub ProcessData()
    Dim wsSource As Worksheet, wsSorted As Worksheet, wsOutput As Worksheet, wsRound As Worksheet
    Dim lastRow As Long, lastCol As Long, i As Long, j As Long
    Dim headerRow As Range
    
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    
    '---------------------------
    ' Step 1. Use the active sheet as the source data.
    Set wsSource = ActiveSheet
    
    '---------------------------
    ' Step 2. Ensure Sheet2 exists for sorted data.
    On Error Resume Next
    Set wsSorted = Worksheets("Sheet2")
    If wsSorted Is Nothing Then
        Set wsSorted = Worksheets.Add(After:=wsSource)
        wsSorted.Name = "Sheet2"
    Else
        wsSorted.Cells.Clear
    End If
    
    '---------------------------
    ' Step 3. Ensure Sheet3 exists for final output (without grade columns).
    Set wsOutput = Worksheets("Sheet3")
    If wsOutput Is Nothing Then
        Set wsOutput = Worksheets.Add(After:=wsSorted)
        wsOutput.Name = "Sheet3"
    Else
        wsOutput.Cells.Clear
    End If
    On Error GoTo 0
    
    '---------------------------
    ' Step 4. Delete empty Remark columns from wsSource.
    lastCol = wsSource.Cells(1, wsSource.Columns.Count).End(xlToLeft).Column
    Set headerRow = wsSource.Range(wsSource.Cells(1, 1), wsSource.Cells(1, lastCol))
    For j = lastCol To 1 Step -1
        If InStr(1, wsSource.Cells(1, j).Value, "Remark", vbTextCompare) > 0 Then
            ' Delete if only the header is nonblank.
            If Application.WorksheetFunction.CountA(wsSource.Columns(j)) = 1 Then
                wsSource.Columns(j).Delete
            End If
        End If
    Next j
    
    '---------------------------
    ' Step 5. Copy cleaned data to Sheet2 and sort by Student Name.
    wsSource.UsedRange.Copy Destination:=wsSorted.Range("A1")
    
    ' Find the Student Name column.
    lastCol = wsSorted.Cells(1, wsSorted.Columns.Count).End(xlToLeft).Column
    Dim colStudentName As Long: colStudentName = 0
    For j = 1 To lastCol
        If InStr(1, wsSorted.Cells(1, j).Value, "Student Name", vbTextCompare) > 0 Then
            colStudentName = j
            Exit For
        End If
    Next j
    
    If colStudentName > 0 Then
        lastRow = wsSorted.Cells(wsSorted.Rows.Count, colStudentName).End(xlUp).Row
        wsSorted.Range("A1").CurrentRegion.Sort Key1:=wsSorted.Cells(2, colStudentName), Order1:=xlAscending, Header:=xlYes
    Else
        MsgBox "Student Name column not found in Sheet2!", vbExclamation
        GoTo CleanUp
    End If
    
    '---------------------------
    ' Step 6. Copy sorted data to Sheet3 for further processing.
    wsSorted.UsedRange.Copy Destination:=wsOutput.Range("A1")
    lastRow = wsOutput.Cells(wsOutput.Rows.Count, 1).End(xlUp).Row
    
    '---------------------------
    ' Step 7. Insert Average Columns for subject groups.
    Dim english1Col As Long, english2Col As Long, colEnglishAvg As Long
    Dim hiscivCol As Long, geographyCol As Long, colHisCivAvg As Long
    Dim colPhysics As Long, colChemistry As Long, colBiology As Long, colChemBioPhyAvg As Long
    
    '--- For English Average (from English 1 and English 2) ---
    english1Col = FindColumn(wsOutput, "English 1")
    english2Col = FindColumn(wsOutput, "English 2")
    If english1Col > 0 And english2Col > 0 Then
        wsOutput.Columns(english2Col + 1).Insert Shift:=xlToRight
        wsOutput.Cells(1, english2Col + 1).Value = "English Average"
        colEnglishAvg = english2Col + 1
        For i = 2 To lastRow
            wsOutput.Cells(i, colEnglishAvg).Value = CustomRound((Val(wsOutput.Cells(i, english1Col).Value) + _
                                                                  Val(wsOutput.Cells(i, english2Col).Value)) / 2)
        Next i
    Else
        Dim colEnglishAlt As Long
        colEnglishAlt = FindColumn(wsOutput, "English")
        If colEnglishAlt > 0 Then
            wsOutput.Columns(colEnglishAlt + 1).Insert Shift:=xlToRight
            wsOutput.Cells(1, colEnglishAlt + 1).Value = "English Average"
            colEnglishAvg = colEnglishAlt + 1
            For i = 2 To lastRow
                wsOutput.Cells(i, colEnglishAvg).Value = CustomRound(Val(wsOutput.Cells(i, colEnglishAlt).Value))
            Next i
        Else
            MsgBox "No English columns found.", vbCritical
            GoTo CleanUp
        End If
    End If
    
    '--- For His/Civ Average (from His/Civ and Geography) ---
    hiscivCol = FindColumn(wsOutput, "His/Civ")
    geographyCol = FindColumn(wsOutput, "Geography")
    If hiscivCol > 0 And geographyCol > 0 Then
        wsOutput.Columns(geographyCol + 1).Insert Shift:=xlToRight
        wsOutput.Cells(1, geographyCol + 1).Value = "His/Civ Average"
        colHisCivAvg = geographyCol + 1
        For i = 2 To lastRow
            wsOutput.Cells(i, colHisCivAvg).Value = CustomRound((Val(wsOutput.Cells(i, hiscivCol).Value) + _
                                                                  Val(wsOutput.Cells(i, geographyCol).Value)) / 2)
        Next i
    Else
        Dim colSocialScience As Long
        colSocialScience = FindColumn(wsOutput, "Social Science")
        If colSocialScience > 0 Then
            wsOutput.Columns(colSocialScience + 1).Insert Shift:=xlToRight
            wsOutput.Cells(1, colSocialScience + 1).Value = "His/Civ Average"
            colHisCivAvg = colSocialScience + 1
            For i = 2 To lastRow
                wsOutput.Cells(i, colHisCivAvg).Value = CustomRound(Val(wsOutput.Cells(i, colSocialScience).Value))
            Next i
        Else
            MsgBox "Neither History/Geography nor Social Science columns found.", vbCritical
            GoTo CleanUp
        End If
    End If
    
    '--- For Chem/Bio/Phy Average (from Physics, Chemistry and Biology) ---
    colPhysics = FindColumn(wsOutput, "Physics")
    colChemistry = FindColumn(wsOutput, "Chemistry")
    colBiology = FindColumn(wsOutput, "Biology")
    If colPhysics > 0 And colChemistry > 0 And colBiology > 0 Then
        Dim maxGroupCol As Long
        maxGroupCol = Application.WorksheetFunction.Max(colPhysics, colChemistry, colBiology)
        wsOutput.Columns(maxGroupCol + 1).Insert Shift:=xlToRight
        wsOutput.Cells(1, maxGroupCol + 1).Value = "Chem/Bio/Phy Average"
        colChemBioPhyAvg = maxGroupCol + 1
        For i = 2 To lastRow
            wsOutput.Cells(i, colChemBioPhyAvg).Value = CustomRound((Val(wsOutput.Cells(i, colPhysics).Value) + _
                                                                      Val(wsOutput.Cells(i, colChemistry).Value) + _
                                                                      Val(wsOutput.Cells(i, colBiology).Value)) / 3)
        Next i
    Else
        Dim colEVS As Long
        colEVS = FindColumn(wsOutput, "EVS")
        If colEVS > 0 Then
            wsOutput.Columns(colEVS + 1).Insert Shift:=xlToRight
            wsOutput.Cells(1, colEVS + 1).Value = "Chem/Bio/Phy Average"
            colChemBioPhyAvg = colEVS + 1
            For i = 2 To lastRow
                wsOutput.Cells(i, colChemBioPhyAvg).Value = CustomRound(Val(wsOutput.Cells(i, colEVS).Value))
            Next i
        Else
            MsgBox "Neither Chemistry/Physics/Biology nor EVS column found.", vbCritical
            GoTo CleanUp
        End If
    End If
    
    '---------------------------
    ' Step 8. Append Overall Totals.
    Dim colTotalMarks As Long, colPercentage As Long, colOverallGrade As Long
    lastCol = wsOutput.Cells(1, wsOutput.Columns.Count).End(xlToLeft).Column
    colTotalMarks = lastCol + 1
    wsOutput.Cells(1, colTotalMarks).Value = "Total Marks"
    colPercentage = colTotalMarks + 1
    wsOutput.Cells(1, colPercentage).Value = "Total Percentage"
    colOverallGrade = colPercentage + 1
    wsOutput.Cells(1, colOverallGrade).Value = "Overall Grade"
    
    Dim englishScore As Double, kannadaScore As Double, hindiScore As Double, mathsScore As Double
    Dim hiscivScore As Double, chemBioPhyScore As Double, computerScore As Double
    Dim gkScore As Double, moralScore As Double, drawingScore As Double
    Dim totalMarks As Double, totalPercentage As Double
    Dim subjectCount As Long, maxTotalMarks As Long
    Dim avgSubjectCount As Long, remainingSubjectCount As Long
    
    Dim colKannada As Long, colMaths As Long, colComputer As Long
    colKannada = FindColumn(wsOutput, "Kannada")
    colMaths = FindColumn(wsOutput, "Maths")
    colComputer = FindColumn(wsOutput, "Computer")
    ' Essential subjects check:
    If colKannada = 0 Or colMaths = 0 Or colComputer = 0 Or colEnglishAvg = 0 Then
        MsgBox "One or more essential columns (English, Kannada, Maths, Computer) not found.", vbCritical
        GoTo CleanUp
    End If
    
    ' Optional subject columns (if available).
    Dim colHindi As Long, colGK As Long, colMoral As Long, colDrawing As Long
    colHindi = FindColumn(wsOutput, "Hindi")
    colGK = FindColumn(wsOutput, "GK")
    colMoral = FindColumn(wsOutput, "Moral")
    colDrawing = FindColumn(wsOutput, "Drawing")
    
    ' Count subjects in two groups:
    ' Group A: Averaged subjects (each counts as one) — English Average, His/Civ Average, Chem/Bio/Phy Average.
    avgSubjectCount = 3
    
    ' Group B: Remaining subjects (individual marks).
    remainingSubjectCount = 0
    remainingSubjectCount = remainingSubjectCount + 1 ' Kannada
    If colHindi <> 0 Then remainingSubjectCount = remainingSubjectCount + 1
    remainingSubjectCount = remainingSubjectCount + 1 ' Maths
    remainingSubjectCount = remainingSubjectCount + 1 ' Computer
    If colGK <> 0 Then remainingSubjectCount = remainingSubjectCount + 1
    If colMoral <> 0 Then remainingSubjectCount = remainingSubjectCount + 1
    If colDrawing <> 0 Then remainingSubjectCount = remainingSubjectCount + 1
    
    subjectCount = avgSubjectCount + remainingSubjectCount
    maxTotalMarks = subjectCount * 100
    
    For i = 2 To lastRow
        englishScore = Val(wsOutput.Cells(i, colEnglishAvg).Value)
        kannadaScore = Val(wsOutput.Cells(i, colKannada).Value)
        If colHindi <> 0 Then
            hindiScore = Val(wsOutput.Cells(i, colHindi).Value)
        Else
            hindiScore = 0
        End If
        mathsScore = Val(wsOutput.Cells(i, colMaths).Value)
        hiscivScore = Val(wsOutput.Cells(i, colHisCivAvg).Value)
        chemBioPhyScore = Val(wsOutput.Cells(i, colChemBioPhyAvg).Value)
        computerScore = Val(wsOutput.Cells(i, colComputer).Value)
        If colGK <> 0 Then
            gkScore = Val(wsOutput.Cells(i, colGK).Value)
        Else
            gkScore = 0
        End If
        If colMoral <> 0 Then
            moralScore = Val(wsOutput.Cells(i, colMoral).Value)
        Else
            moralScore = 0
        End If
        If colDrawing <> 0 Then
            drawingScore = Val(wsOutput.Cells(i, colDrawing).Value)
        Else
            drawingScore = 0
        End If
        
        totalMarks = englishScore + kannadaScore + hindiScore + mathsScore + hiscivScore + chemBioPhyScore + computerScore + gkScore + moralScore + drawingScore
        wsOutput.Cells(i, colTotalMarks).Value = totalMarks
        totalPercentage = (totalMarks / maxTotalMarks) * 100
        wsOutput.Cells(i, colPercentage).Value = Round(totalPercentage, 2)
        wsOutput.Cells(i, colOverallGrade).Value = GetGrade(CustomRound(totalPercentage))
    Next i
    
    '---------------------------
    ' Step 9. Create Sheet4: First apply rounding to calculated columns, then insert Grade columns.
    On Error Resume Next
    Set wsRound = Worksheets("Sheet4")
    If wsRound Is Nothing Then
        Set wsRound = Worksheets.Add(After:=wsOutput)
        wsRound.Name = "Sheet4"
    Else
        wsRound.Cells.Clear
    End If
    On Error GoTo 0
    
    ' Copy all data from Sheet3 to Sheet4.
    wsOutput.UsedRange.Copy Destination:=wsRound.Range("A1")
    lastRow = wsRound.Cells(wsRound.Rows.Count, 1).End(xlUp).Row
    lastCol = wsRound.Cells(1, wsRound.Columns.Count).End(xlToLeft).Column
    
    ' First, apply the custom rounding on calculated columns.
    Dim headerVal As String
    For j = 1 To lastCol
        headerVal = wsRound.Cells(1, j).Value
        ' Process columns with "Average" or "Total" (exclude any column already containing "Grade").
        If (InStr(1, headerVal, "Average", vbTextCompare) > 0 Or _
            InStr(1, headerVal, "Total", vbTextCompare) > 0) And _
           (InStr(1, headerVal, "Grade", vbTextCompare) = 0) Then
           
            For i = 2 To lastRow
                If IsNumeric(wsRound.Cells(i, j).Value) Then
                    wsRound.Cells(i, j).Value = CustomRound(wsRound.Cells(i, j).Value)
                End If
            Next i
        End If
    Next j
    
    ' --- NEW BLOCK: Recalculate Total Percentage and Overall Grade in Sheet4 based on Total Marks ---
    Dim colTotalMarksS4 As Long, colPercS4 As Long, colGradeS4 As Long
    For j = 1 To lastCol
        Select Case wsRound.Cells(1, j).Value
            Case "Total Marks": colTotalMarksS4 = j
            Case "Total Percentage": colPercS4 = j
            Case "Overall Grade": colGradeS4 = j
        End Select
    Next j
    
    ' Set maximum total marks to 1000 (10 subjects × 100 marks each).
    Dim maxTotal As Double: maxTotal = 1000
    If colTotalMarksS4 > 0 And colPercS4 > 0 And colGradeS4 > 0 Then
        For i = 2 To lastRow
            Dim totMarks As Double, perc As Double
            totMarks = wsRound.Cells(i, colTotalMarksS4).Value
            perc = (totMarks / maxTotal) * 100
            ' Use CustomRound for percentage rounding: if fractional part is <0.5 round down, >=0.5 round up.
            wsRound.Cells(i, colPercS4).Value = CustomRound(perc)
            wsRound.Cells(i, colGradeS4).Value = GetGrade(CustomRound(perc))
        Next i
    End If
    
    ' Now, insert Grade columns for each calculated subject column.
    ' Define the keywords to determine which columns get a grade column.
    Dim keywords As Variant
    keywords = Array("English", "Kannada", "Hindi", "His/Civ", "Geography", "Social Science", _
                     "Maths", "Physics", "Chemistry", "Biology", "Computer", "Average", _
                     "EVS", "GK", "Moral", "Drawing")
    
    ' Loop backward from the last column to avoid shifting issues.
    lastCol = wsRound.Cells(1, wsRound.Columns.Count).End(xlToLeft).Column
    For j = lastCol To 1 Step -1
        headerVal = wsRound.Cells(1, j).Value
        ' Exclude identifier columns.
        If InStr(1, headerVal, "Total", vbTextCompare) = 0 And _
           InStr(1, headerVal, "Roll Number", vbTextCompare) = 0 And _
           InStr(1, headerVal, "Student Name", vbTextCompare) = 0 And _
           InStr(1, headerVal, "Class", vbTextCompare) = 0 And _
           InStr(1, headerVal, "Section", vbTextCompare) = 0 And _
           InStr(1, headerVal, "Grade", vbTextCompare) = 0 Then
           
           Dim qualifies As Boolean: qualifies = False
           Dim k As Integer
           For k = LBound(keywords) To UBound(keywords)
               If InStr(1, headerVal, keywords(k), vbTextCompare) > 0 Then
                   qualifies = True
                   Exit For
               End If
           Next k
           
           If qualifies Then
               wsRound.Columns(j + 1).Insert Shift:=xlToRight
               wsRound.Cells(1, j + 1).Value = headerVal & " Grade"
               For i = 2 To lastRow
                   Dim cellVal As Double
                   cellVal = Val(wsRound.Cells(i, j).Value)
                   wsRound.Cells(i, j + 1).Value = GetGrade(cellVal)
               Next i
           End If
        End If
    Next j
    
CleanUp:
    Application.Calculation = xlCalculationAutomatic
    Application.ScreenUpdating = True
    MsgBox "Processing complete!", vbInformation
End Sub

'---------------------------
' Helper function: Finds the column number where the header cell contains headerText.
Function FindColumn(ws As Worksheet, headerText As String) As Long
    Dim lastCol As Long, j As Long
    lastCol = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column
    For j = 1 To lastCol
        If InStr(1, ws.Cells(1, j).Value, headerText, vbTextCompare) > 0 Then
            FindColumn = j
            Exit Function
        End If
    Next j
    FindColumn = 0
End Function

'---------------------------
' Grade scale function using your provided grading scale.
Function GetGrade(marks As Double) As String
    Select Case marks
        Case 91 To 100
            GetGrade = "A+"
        Case 81 To 90
            GetGrade = "A"
        Case 71 To 80
            GetGrade = "B+"
        Case 61 To 70
            GetGrade = "B"
        Case 51 To 60
            GetGrade = "C+"
        Case 41 To 50
            GetGrade = "C"
        Case 33 To 40
            GetGrade = "D"
        Case 0 To 32
            GetGrade = "E"
        Case Else
            GetGrade = ""
    End Select
End Function

'---------------------------
' Custom rounding function:
' If the fractional part is less than 0.5, return the integer part.
' If the fractional part is 0.5 or greater, return the integer part plus one.
Function CustomRound(val As Double) As Long
    Dim intPart As Long, frac As Double
    intPart = Fix(val)
    frac = val - intPart
    If frac >= 0.5 Then
        CustomRound = intPart + 1
    Else
        CustomRound = intPart
    End If
End Function

For class 9-10

  • Copy and run the code below to calculate T2 marks
    (FA-1: 10 marks + FA-2: 10 marks + SA-2: 80 marks).
    
                        
                        Option Explicit

Sub ProcessData()
    Dim wsSource As Worksheet, wsSorted As Worksheet, wsOutput As Worksheet, wsRound As Worksheet
    Dim lastRow As Long, lastCol As Long, i As Long, j As Long
    Dim headerRow As Range
    
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    
    '---------------------------
    ' Step 1. Use the active sheet as the source data.
    Set wsSource = ActiveSheet
    
    '---------------------------
    ' Step 2. Ensure Sheet2 exists for sorted data.
    On Error Resume Next
    Set wsSorted = Worksheets("Sheet2")
    If wsSorted Is Nothing Then
        Set wsSorted = Worksheets.Add(After:=wsSource)
        wsSorted.Name = "Sheet2"
    Else
        wsSorted.Cells.Clear
    End If
    
    '---------------------------
    ' Step 3. Ensure Sheet3 exists for final output (without grade columns).
    Set wsOutput = Worksheets("Sheet3")
    If wsOutput Is Nothing Then
        Set wsOutput = Worksheets.Add(After:=wsSorted)
        wsOutput.Name = "Sheet3"
    Else
        wsOutput.Cells.Clear
    End If
    On Error GoTo 0
    
    '---------------------------
    ' Step 4. Delete empty Remark columns from wsSource.
    lastCol = wsSource.Cells(1, wsSource.Columns.Count).End(xlToLeft).Column
    Set headerRow = wsSource.Range(wsSource.Cells(1, 1), wsSource.Cells(1, lastCol))
    For j = lastCol To 1 Step -1
        If InStr(1, wsSource.Cells(1, j).Value, "Remark", vbTextCompare) > 0 Then
            ' Delete if only the header is nonblank.
            If Application.WorksheetFunction.CountA(wsSource.Columns(j)) = 1 Then
                wsSource.Columns(j).Delete
            End If
        End If
    Next j
    
    '---------------------------
    ' Step 5. Copy cleaned data to Sheet2 and sort by Student Name.
    wsSource.UsedRange.Copy Destination:=wsSorted.Range("A1")
    
    ' Find the Student Name column.
    lastCol = wsSorted.Cells(1, wsSorted.Columns.Count).End(xlToLeft).Column
    Dim colStudentName As Long: colStudentName = 0
    For j = 1 To lastCol
        If InStr(1, wsSorted.Cells(1, j).Value, "Student Name", vbTextCompare) > 0 Then
            colStudentName = j
            Exit For
        End If
    Next j
    
    If colStudentName > 0 Then
        lastRow = wsSorted.Cells(wsSorted.Rows.Count, colStudentName).End(xlUp).Row
        wsSorted.Range("A1").CurrentRegion.Sort Key1:=wsSorted.Cells(2, colStudentName), Order1:=xlAscending, Header:=xlYes
    Else
        MsgBox "Student Name column not found in Sheet2!", vbExclamation
        GoTo CleanUp
    End If
    
    '---------------------------
    ' Step 6. Copy sorted data to Sheet3 for further processing.
    wsSorted.UsedRange.Copy Destination:=wsOutput.Range("A1")
    lastRow = wsOutput.Cells(wsOutput.Rows.Count, 1).End(xlUp).Row
    
    '---------------------------
    ' Step 7. Insert Average Columns for subject groups.
    Dim english1Col As Long, english2Col As Long, colEnglishAvg As Long
    Dim hiscivCol As Long, geographyCol As Long, colHisCivAvg As Long
    Dim colPhysics As Long, colChemistry As Long, colBiology As Long, colChemBioPhyAvg As Long
    
    '--- For English Average (from English 1 and English 2) ---
    english1Col = FindColumn(wsOutput, "English 1")
    english2Col = FindColumn(wsOutput, "English 2")
    If english1Col > 0 And english2Col > 0 Then
        wsOutput.Columns(english2Col + 1).Insert Shift:=xlToRight
        wsOutput.Cells(1, english2Col + 1).Value = "English Average"
        colEnglishAvg = english2Col + 1
        For i = 2 To lastRow
            wsOutput.Cells(i, colEnglishAvg).Value = CustomRound((Val(wsOutput.Cells(i, english1Col).Value) + _
                                                                  Val(wsOutput.Cells(i, english2Col).Value)) / 2)
        Next i
    Else
        Dim colEnglishAlt As Long
        colEnglishAlt = FindColumn(wsOutput, "English")
        If colEnglishAlt > 0 Then
            wsOutput.Columns(colEnglishAlt + 1).Insert Shift:=xlToRight
            wsOutput.Cells(1, colEnglishAlt + 1).Value = "English Average"
            colEnglishAvg = colEnglishAlt + 1
            For i = 2 To lastRow
                wsOutput.Cells(i, colEnglishAvg).Value = CustomRound(Val(wsOutput.Cells(i, colEnglishAlt).Value))
            Next i
        Else
            MsgBox "No English columns found.", vbCritical
            GoTo CleanUp
        End If
    End If
    
    '--- For His/Civ Average (from His/Civ and Geography) ---
    hiscivCol = FindColumn(wsOutput, "His/Civ")
    geographyCol = FindColumn(wsOutput, "Geography")
    If hiscivCol > 0 And geographyCol > 0 Then
        wsOutput.Columns(geographyCol + 1).Insert Shift:=xlToRight
        wsOutput.Cells(1, geographyCol + 1).Value = "His/Civ Average"
        colHisCivAvg = geographyCol + 1
        For i = 2 To lastRow
            wsOutput.Cells(i, colHisCivAvg).Value = CustomRound((Val(wsOutput.Cells(i, hiscivCol).Value) + _
                                                                  Val(wsOutput.Cells(i, geographyCol).Value)) / 2)
        Next i
    Else
        Dim colSocialScience As Long
        colSocialScience = FindColumn(wsOutput, "Social Science")
        If colSocialScience > 0 Then
            wsOutput.Columns(colSocialScience + 1).Insert Shift:=xlToRight
            wsOutput.Cells(1, colSocialScience + 1).Value = "His/Civ Average"
            colHisCivAvg = colSocialScience + 1
            For i = 2 To lastRow
                wsOutput.Cells(i, colHisCivAvg).Value = CustomRound(Val(wsOutput.Cells(i, colSocialScience).Value))
            Next i
        Else
            MsgBox "Neither History/Geography nor Social Science columns found.", vbCritical
            GoTo CleanUp
        End If
    End If
    
    '--- For Chem/Bio/Phy Average (from Physics, Chemistry and Biology) ---
    colPhysics = FindColumn(wsOutput, "Physics")
    colChemistry = FindColumn(wsOutput, "Chemistry")
    colBiology = FindColumn(wsOutput, "Biology")
    If colPhysics > 0 And colChemistry > 0 And colBiology > 0 Then
        Dim maxGroupCol As Long
        maxGroupCol = Application.WorksheetFunction.Max(colPhysics, colChemistry, colBiology)
        wsOutput.Columns(maxGroupCol + 1).Insert Shift:=xlToRight
        wsOutput.Cells(1, maxGroupCol + 1).Value = "Chem/Bio/Phy Average"
        colChemBioPhyAvg = maxGroupCol + 1
        For i = 2 To lastRow
            wsOutput.Cells(i, colChemBioPhyAvg).Value = CustomRound((Val(wsOutput.Cells(i, colPhysics).Value) + _
                                                                      Val(wsOutput.Cells(i, colChemistry).Value) + _
                                                                      Val(wsOutput.Cells(i, colBiology).Value)) / 3)
        Next i
    Else
        Dim colEVS As Long
        colEVS = FindColumn(wsOutput, "EVS")
        If colEVS > 0 Then
            wsOutput.Columns(colEVS + 1).Insert Shift:=xlToRight
            wsOutput.Cells(1, colEVS + 1).Value = "Chem/Bio/Phy Average"
            colChemBioPhyAvg = colEVS + 1
            For i = 2 To lastRow
                wsOutput.Cells(i, colChemBioPhyAvg).Value = CustomRound(Val(wsOutput.Cells(i, colEVS).Value))
            Next i
        Else
            MsgBox "Neither Chemistry/Physics/Biology nor EVS column found.", vbCritical
            GoTo CleanUp
        End If
    End If
    
    '---------------------------
    ' Step 8. Append Overall Totals.
    Dim colTotalMarks As Long, colPercentage As Long, colOverallGrade As Long
    lastCol = wsOutput.Cells(1, wsOutput.Columns.Count).End(xlToLeft).Column
    colTotalMarks = lastCol + 1
    wsOutput.Cells(1, colTotalMarks).Value = "Total Marks"
    colPercentage = colTotalMarks + 1
    wsOutput.Cells(1, colPercentage).Value = "Total Percentage"
    colOverallGrade = colPercentage + 1
    wsOutput.Cells(1, colOverallGrade).Value = "Overall Grade"
    
    Dim englishScore As Double, kannadaScore As Double, mathsScore As Double
    Dim hiscivScore As Double, chemBioPhyScore As Double, computerScore As Double
    Dim totalMarks As Double, totalPercentage As Double
    Dim subjectCount As Long, maxTotalMarks As Long
    Dim avgSubjectCount As Long, remainingSubjectCount As Long
    
    Dim colKannada As Long, colMaths As Long, colComputer As Long
    colKannada = FindColumn(wsOutput, "Kannada")
    colMaths = FindColumn(wsOutput, "Maths")
    colComputer = FindColumn(wsOutput, "Computer")
    ' Essential subjects check:
    If colKannada = 0 Or colMaths = 0 Or colComputer = 0 Or colEnglishAvg = 0 Then
        MsgBox "One or more essential columns (English, Kannada, Maths, Computer) not found.", vbCritical
        GoTo CleanUp
    End If
    
    ' Count subjects in two groups:
    ' Group A: Averaged subjects (each counts as one) — English Average, His/Civ Average, Chem/Bio/Phy Average.
    avgSubjectCount = 3
    ' Group B: Remaining subjects (individual marks) — Kannada, Maths, Computer.
    remainingSubjectCount = 3
    subjectCount = avgSubjectCount + remainingSubjectCount
    maxTotalMarks = subjectCount * 100
    
    For i = 2 To lastRow
        englishScore = Val(wsOutput.Cells(i, colEnglishAvg).Value)
        kannadaScore = Val(wsOutput.Cells(i, colKannada).Value)
        mathsScore = Val(wsOutput.Cells(i, colMaths).Value)
        hiscivScore = Val(wsOutput.Cells(i, colHisCivAvg).Value)
        chemBioPhyScore = Val(wsOutput.Cells(i, colChemBioPhyAvg).Value)
        computerScore = Val(wsOutput.Cells(i, colComputer).Value)
        
        totalMarks = englishScore + kannadaScore + mathsScore + hiscivScore + chemBioPhyScore + computerScore
        wsOutput.Cells(i, colTotalMarks).Value = totalMarks
        totalPercentage = (totalMarks / maxTotalMarks) * 100
        wsOutput.Cells(i, colPercentage).Value = Round(totalPercentage, 2)
        wsOutput.Cells(i, colOverallGrade).Value = GetGrade(CustomRound(totalPercentage))
    Next i
    
    '---------------------------
    ' Step 9. Create Sheet4: First apply rounding to calculated columns, then insert Grade columns.
    On Error Resume Next
    Set wsRound = Worksheets("Sheet4")
    If wsRound Is Nothing Then
        Set wsRound = Worksheets.Add(After:=wsOutput)
        wsRound.Name = "Sheet4"
    Else
        wsRound.Cells.Clear
    End If
    On Error GoTo 0
    
    ' Copy all data from Sheet3 to Sheet4.
    wsOutput.UsedRange.Copy Destination:=wsRound.Range("A1")
    lastRow = wsRound.Cells(wsRound.Rows.Count, 1).End(xlUp).Row
    lastCol = wsRound.Cells(1, wsRound.Columns.Count).End(xlToLeft).Column
    
    ' First, apply the custom rounding on calculated columns.
    Dim headerVal As String
    For j = 1 To lastCol
        headerVal = wsRound.Cells(1, j).Value
        ' Process columns with "Average" or "Total" (exclude any column already containing "Grade").
        If (InStr(1, headerVal, "Average", vbTextCompare) > 0 Or _
            InStr(1, headerVal, "Total", vbTextCompare) > 0) And _
           (InStr(1, headerVal, "Grade", vbTextCompare) = 0) Then
           
            For i = 2 To lastRow
                If IsNumeric(wsRound.Cells(i, j).Value) Then
                    wsRound.Cells(i, j).Value = CustomRound(wsRound.Cells(i, j).Value)
                End If
            Next i
        End If
    Next j
    
    ' --- Recalculate Total Percentage and Overall Grade in Sheet4 based on Total Marks ---
    Dim colTotalMarksS4 As Long, colPercS4 As Long, colGradeS4 As Long
    For j = 1 To lastCol
        Select Case wsRound.Cells(1, j).Value
            Case "Total Marks": colTotalMarksS4 = j
            Case "Total Percentage": colPercS4 = j
            Case "Overall Grade": colGradeS4 = j
        End Select
    Next j
    
    ' Set maximum total marks to 600 (6 subjects × 100 marks each).
    Dim maxTotal As Double: maxTotal = 600
    If colTotalMarksS4 > 0 And colPercS4 > 0 And colGradeS4 > 0 Then
        For i = 2 To lastRow
            Dim totMarks As Double, perc As Double
            totMarks = wsRound.Cells(i, colTotalMarksS4).Value
            perc = (totMarks / maxTotal) * 100
            wsRound.Cells(i, colPercS4).Value = CustomRound(perc)
            wsRound.Cells(i, colGradeS4).Value = GetGrade(CustomRound(perc))
        Next i
    End If
    
    ' Now, insert Grade columns for each calculated subject column.
    ' Define the keywords to determine which columns get a grade column.
    Dim keywords As Variant
    keywords = Array("English", "Kannada", "His/Civ", "Geography", "Social Science", _
                     "Maths", "Physics", "Chemistry", "Biology", "Computer", "Average", "EVS")
    
    ' Loop backward from the last column to avoid shifting issues.
    lastCol = wsRound.Cells(1, wsRound.Columns.Count).End(xlToLeft).Column
    For j = lastCol To 1 Step -1
        headerVal = wsRound.Cells(1, j).Value
        ' Exclude identifier columns.
        If InStr(1, headerVal, "Total", vbTextCompare) = 0 And _
           InStr(1, headerVal, "Roll Number", vbTextCompare) = 0 And _
           InStr(1, headerVal, "Student Name", vbTextCompare) = 0 And _
           InStr(1, headerVal, "Class", vbTextCompare) = 0 And _
           InStr(1, headerVal, "Section", vbTextCompare) = 0 And _
           InStr(1, headerVal, "Grade", vbTextCompare) = 0 Then
           
           Dim qualifies As Boolean: qualifies = False
           Dim k As Integer
           For k = LBound(keywords) To UBound(keywords)
               If InStr(1, headerVal, keywords(k), vbTextCompare) > 0 Then
                   qualifies = True
                   Exit For
               End If
           Next k
           
           If qualifies Then
               wsRound.Columns(j + 1).Insert Shift:=xlToRight
               wsRound.Cells(1, j + 1).Value = headerVal & " Grade"
               For i = 2 To lastRow
                   Dim cellVal As Double
                   cellVal = Val(wsRound.Cells(i, j).Value)
                   wsRound.Cells(i, j + 1).Value = GetGrade(cellVal)
               Next i
           End If
        End If
    Next j
    
CleanUp:
    Application.Calculation = xlCalculationAutomatic
    Application.ScreenUpdating = True
    MsgBox "Processing complete!", vbInformation
End Sub

'---------------------------
' Helper function: Finds the column number where the header cell contains headerText.
Function FindColumn(ws As Worksheet, headerText As String) As Long
    Dim lastCol As Long, j As Long
    lastCol = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column
    For j = 1 To lastCol
        If InStr(1, ws.Cells(1, j).Value, headerText, vbTextCompare) > 0 Then
            FindColumn = j
            Exit Function
        End If
    Next j
    FindColumn = 0
End Function

'---------------------------
' Grade scale function using your provided grading scale.
Function GetGrade(marks As Double) As String
    Select Case marks
        Case 91 To 100
            GetGrade = "A+"
        Case 81 To 90
            GetGrade = "A"
        Case 71 To 80
            GetGrade = "B+"
        Case 61 To 70
            GetGrade = "B"
        Case 51 To 60
            GetGrade = "C+"
        Case 41 To 50
            GetGrade = "C"
        Case 33 To 40
            GetGrade = "D"
        Case 0 To 32
            GetGrade = "E"
        Case Else
            GetGrade = ""
    End Select
End Function

'---------------------------
' Custom rounding function:
' If the fractional part is less than 0.5, return the integer part.
' If the fractional part is 0.5 or greater, return the integer part plus one.
Function CustomRound(val As Double) As Long
    Dim intPart As Long, frac As Double
    intPart = Fix(val)
    frac = val - intPart
    If frac >= 0.5 Then
        CustomRound = intPart + 1
    Else
        CustomRound = intPart
    End If
End Function

JavaScript Code Example

This is a sample JavaScript snippet

  • Console output
  • Basic logging
  • Debugging friendly
console.log("Hello World");