0% found this document useful (0 votes)
20 views

Python code for Data Analysis Tool in excel

The document outlines a Python script that creates an Excel-based class assessment tool using the openpyxl library. It includes functionalities for setting up sheets for marks, summary analysis, and a dashboard, along with data validation, conditional formatting, and formulas for calculating averages and grades. The tool is designed to facilitate data entry and analysis for student assessments.

Uploaded by

Patrick Kamfwa
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
20 views

Python code for Data Analysis Tool in excel

The document outlines a Python script that creates an Excel-based class assessment tool using the openpyxl library. It includes functionalities for setting up sheets for marks, summary analysis, and a dashboard, along with data validation, conditional formatting, and formulas for calculating averages and grades. The tool is designed to facilitate data entry and analysis for student assessments.

Uploaded by

Patrick Kamfwa
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 11

import openpyxl

from openpyxl.styles import Font, PatternFill, Alignment, Border, Side


from openpyxl.styles.differential import DifferentialStyle
from openpyxl.formatting.rule import Rule, FormulaRule
from openpyxl.chart import BarChart, PieChart, Reference
from openpyxl.chart.label import DataLabelList
from openpyxl.chart.series import DataPoint
from openpyxl.worksheet.datavalidation import DataValidation
from openpyxl.utils import get_column_letter
from openpyxl.drawing.image import Image
import datetime
import os

def create_class_assessment_tool(output_file="Class_Assessment_Tool.xlsx"):
"""Create an Excel class assessment tool with three sheets for data entry,
analysis, and dashboard."""

# Create a new workbook


wb = openpyxl.Workbook()

# Create sheets
mark_sheet = wb.active
mark_sheet.title = "Mark Schedule"
summary_sheet = wb.create_sheet("Summary Analysis")
dashboard_sheet = wb.create_sheet("Dashboard")

# Set up Mark Schedule sheet


setup_mark_schedule(mark_sheet)

# Set up Summary Analysis sheet


setup_summary_analysis(summary_sheet, mark_sheet)

# Set up Dashboard sheet


setup_dashboard(dashboard_sheet, mark_sheet, summary_sheet)

# Apply general workbook formatting and settings


for sheet in wb.sheetnames:
wb[sheet].sheet_properties.tabColor = "1072BA"

# Add documentation sheet


instruction_sheet = wb.create_sheet("Instructions", 0)
setup_instructions(instruction_sheet)

# Save the workbook


wb.save(output_file)
print(f"Excel assessment tool created successfully: {output_file}")

return output_file

def setup_mark_schedule(ws):
"""Set up the Mark Schedule sheet with headers, formulas, and formatting."""
# Set column widths
ws.column_dimensions['A'].width = 5 # SN
ws.column_dimensions['B'].width = 30 # Name
ws.column_dimensions['C'].width = 8 # Sex
ws.column_dimensions['D'].width = 15 # Assessment 1
ws.column_dimensions['E'].width = 15 # Assessment 2
ws.column_dimensions['F'].width = 15 # Assessment 3
ws.column_dimensions['G'].width = 15 # Average
ws.column_dimensions['H'].width = 12 # Grade
ws.column_dimensions['I'].width = 18 # Remark

# Add title
ws.merge_cells('A1:I1')
ws['A1'] = "CLASS ASSESSMENT RECORD"
ws['A1'].font = Font(size=16, bold=True)
ws['A1'].alignment = Alignment(horizontal='center', vertical='center')
ws.row_dimensions[1].height = 30

# Add subtitle with date


ws.merge_cells('A2:I2')
ws['A2'] = f"Generated on: {datetime.datetime.now().strftime('%Y-%m-%d')}"
ws['A2'].font = Font(size=10, italic=True)
ws['A2'].alignment = Alignment(horizontal='center')

# Set up headers
headers = ["SN", "Name", "Sex", "Assessment 1", "Assessment 2", "Assessment 3",
"Average", "Grade", "Remark"]
for col, header in enumerate(headers, 1):
cell = ws.cell(row=4, column=col)
cell.value = header
cell.font = Font(bold=True)
cell.alignment = Alignment(horizontal='center')
cell.fill = PatternFill(start_color="D3D3D3", end_color="D3D3D3",
fill_type="solid")

# Add thin borders to header


thin_border = Border(left=Side(style='thin'), right=Side(style='thin'),
top=Side(style='thin'), bottom=Side(style='thin'))

for row in ws.iter_rows(min_row=4, max_row=4, min_col=1, max_col=9):


for cell in row:
cell.border = thin_border

# Add data validation for gender (Sex) column


gender_validation = DataValidation(type="list", formula1='"M,F"',
allow_blank=True)
gender_validation.add('C5:C104') # Apply to rows 5-104
ws.add_data_validation(gender_validation)

# Add data validation for assessment scores (0-100)


score_validation = DataValidation(type="decimal", formula1='0', formula2='100',
operator='between', allow_blank=True)
score_validation.add('D5:F104') # Apply to all three assessment columns
ws.add_data_validation(score_validation)

# Auto-generate SN and add formulas for 100 students


for row in range(5, 105): # Rows 5-104 (100 students)
# SN
ws.cell(row=row, column=1).value = row - 4
ws.cell(row=row, column=1).alignment = Alignment(horizontal='center')

# Add formulas
# Average formula
avg_cell = ws.cell(row=row, column=7)
avg_cell.value = f'=IF(COUNTA(D{row}:F{row})=0,"",AVERAGE(D{row}:F{row}))'
avg_cell.number_format = '0.00'
# Grade formula
grade_cell = ws.cell(row=row, column=8)
grade_cell.value =
(f'=IF(G{row}="","",IF(G{row}>=75,"ONE",IF(G{row}>=70,"TWO",'

f'IF(G{row}>=65,"THREE",IF(G{row}>=60,"FOUR",IF(G{row}>=55,"FIVE",'

f'IF(G{row}>=50,"SIX",IF(G{row}>=45,"SEVEN",IF(G{row}>=40,"EIGHT",'
f'IF(G{row}>=0,"NINE","X"))))))))))')

# Remark formula
remark_cell = ws.cell(row=row, column=9)
remark_cell.value =
(f'=IF(H{row}="","",IF(H{row}="X","ABSENT",IF(H{row}="NINE","UNSATISFACTORY",'

f'IF(OR(H{row}="SEVEN",H{row}="EIGHT"),"SATISFACTORY",'
f'IF(OR(H{row}="FIVE",H{row}="SIX"),"CREDIT",'

f'IF(OR(H{row}="THREE",H{row}="FOUR"),"MERIT","DISTINCTION"))))))')

# Add borders to all cells in the row


for col in range(1, 10):
ws.cell(row=row, column=col).border = thin_border

# Add conditional formatting for grades


# Define colors for different grades
colors = {
'DISTINCTION': 'A7C942', # Green for ONE-TWO (DISTINCTION)
'MERIT': 'FFEB9C', # Yellow for THREE-FOUR (MERIT)
'CREDIT': 'ADD8E6', # Light Blue for FIVE-SIX (CREDIT)
'SATISFACTORY': 'D8D8D8', # Light Gray for SEVEN-EIGHT (SATISFACTORY)
'UNSATISFACTORY': 'FF9999', # Light Red for NINE (UNSATISFACTORY)
'ABSENT': 'C0C0C0' # Gray for X (ABSENT)
}

# Apply conditional formatting to grade column


ws.conditional_formatting.add(f'H5:H104',
FormulaRule(formula=['OR(H5="ONE",H5="TWO")'],

fill=PatternFill(start_color=colors['DISTINCTION'],

end_color=colors['DISTINCTION'],
fill_type='solid')))
ws.conditional_formatting.add(f'H5:H104',
FormulaRule(formula=['OR(H5="THREE",H5="FOUR")'],

fill=PatternFill(start_color=colors['MERIT'],

end_color=colors['MERIT'],
fill_type='solid')))
ws.conditional_formatting.add(f'H5:H104',
FormulaRule(formula=['OR(H5="FIVE",H5="SIX")'],

fill=PatternFill(start_color=colors['CREDIT'],

end_color=colors['CREDIT'],
fill_type='solid')))
ws.conditional_formatting.add(f'H5:H104',
FormulaRule(formula=['OR(H5="SEVEN",H5="EIGHT")'],
fill=PatternFill(start_color=colors['SATISFACTORY'],

end_color=colors['SATISFACTORY'],
fill_type='solid')))
ws.conditional_formatting.add(f'H5:H104',
FormulaRule(formula=['H5="NINE"'],

fill=PatternFill(start_color=colors['UNSATISFACTORY'],

end_color=colors['UNSATISFACTORY'],
fill_type='solid')))
ws.conditional_formatting.add(f'H5:H104',
FormulaRule(formula=['H5="X"'],

fill=PatternFill(start_color=colors['ABSENT'],

end_color=colors['ABSENT'],
fill_type='solid')))

# Also apply same conditional formatting to remark column


ws.conditional_formatting.add(f'I5:I104',
FormulaRule(formula=['I5="DISTINCTION"'],

fill=PatternFill(start_color=colors['DISTINCTION'],

end_color=colors['DISTINCTION'],
fill_type='solid')))
ws.conditional_formatting.add(f'I5:I104',
FormulaRule(formula=['I5="MERIT"'],

fill=PatternFill(start_color=colors['MERIT'],

end_color=colors['MERIT'],
fill_type='solid')))
ws.conditional_formatting.add(f'I5:I104',
FormulaRule(formula=['I5="CREDIT"'],

fill=PatternFill(start_color=colors['CREDIT'],

end_color=colors['CREDIT'],
fill_type='solid')))
ws.conditional_formatting.add(f'I5:I104',
FormulaRule(formula=['I5="SATISFACTORY"'],

fill=PatternFill(start_color=colors['SATISFACTORY'],

end_color=colors['SATISFACTORY'],
fill_type='solid')))
ws.conditional_formatting.add(f'I5:I104',
FormulaRule(formula=['I5="UNSATISFACTORY"'],

fill=PatternFill(start_color=colors['UNSATISFACTORY'],

end_color=colors['UNSATISFACTORY'],
fill_type='solid')))
ws.conditional_formatting.add(f'I5:I104',
FormulaRule(formula=['I5="ABSENT"'],
fill=PatternFill(start_color=colors['ABSENT'],

end_color=colors['ABSENT'],
fill_type='solid')))

# Add a note about data entry


ws.merge_cells('A3:I3')
ws['A3'] = "Enter student information and assessment scores below (scores must
be between 0-100)"
ws['A3'].font = Font(italic=True)
ws['A3'].alignment = Alignment(horizontal='center')

def setup_summary_analysis(ws, mark_sheet):


"""Set up the Summary Analysis sheet with summary tables and statistics."""
# Set column widths
for col in range(1, 10):
ws.column_dimensions[get_column_letter(col)].width = 15

# Add title
ws.merge_cells('A1:G1')
ws['A1'] = "SUMMARY ANALYSIS"
ws['A1'].font = Font(size=16, bold=True)
ws['A1'].alignment = Alignment(horizontal='center', vertical='center')
ws.row_dimensions[1].height = 30

# Add subtitle with date


ws.merge_cells('A2:G2')
ws['A2'] = f"Generated on: {datetime.datetime.now().strftime('%Y-%m-%d')}"
ws['A2'].font = Font(size=10, italic=True)
ws['A2'].alignment = Alignment(horizontal='center')

# Table 1: Grade Distribution by Gender


ws['A4'] = "Table 1: Grade Distribution by Gender"
ws['A4'].font = Font(bold=True)

# Headers for Table 1


headers = ["Grade", "Male Count", "Male %", "Female Count", "Female %", "Total
Count", "Total %"]
for col, header in enumerate(headers, 1):
cell = ws.cell(row=5, column=col)
cell.value = header
cell.font = Font(bold=True)
cell.alignment = Alignment(horizontal='center')
cell.fill = PatternFill(start_color="D3D3D3", end_color="D3D3D3",
fill_type="solid")

# Add thin borders to header


thin_border = Border(left=Side(style='thin'), right=Side(style='thin'),
top=Side(style='thin'), bottom=Side(style='thin'))

for row in ws.iter_rows(min_row=5, max_row=5, min_col=1, max_col=7):


for cell in row:
cell.border = thin_border

# Grade rows for Table 1


grades = ["ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN", "EIGHT",
"NINE", "X", "TOTAL"]

for idx, grade in enumerate(grades):


row_num = 6 + idx
ws.cell(row=row_num, column=1).value = grade
ws.cell(row=row_num, column=1).alignment = Alignment(horizontal='center')

if grade != "TOTAL":
# Male Count
ws.cell(row=row_num, column=2).value = f'=COUNTIFS(\'Mark Schedule\'!
$C$5:$C$104,"M",\'Mark Schedule\'!$H$5:$H$104,"{grade}")'

# Male Percentage
ws.cell(row=row_num, column=3).value = f'=IF(COUNTIF(\'Mark Schedule\'!
$C$5:$C$104,"M")=0,0,B{row_num}/COUNTIF(\'Mark Schedule\'!$C$5:$C$104,"M"))'
ws.cell(row=row_num, column=3).number_format = '0.00%'

# Female Count
ws.cell(row=row_num, column=4).value = f'=COUNTIFS(\'Mark Schedule\'!
$C$5:$C$104,"F",\'Mark Schedule\'!$H$5:$H$104,"{grade}")'

# Female Percentage
ws.cell(row=row_num, column=5).value = f'=IF(COUNTIF(\'Mark Schedule\'!
$C$5:$C$104,"F")=0,0,D{row_num}/COUNTIF(\'Mark Schedule\'!$C$5:$C$104,"F"))'
ws.cell(row=row_num, column=5).number_format = '0.00%'

# Total Count
ws.cell(row=row_num, column=6).value = f'=B{row_num}+D{row_num}'

# Total Percentage
ws.cell(row=row_num, column=7).value = f'=IF(COUNT(\'Mark Schedule\'!
$C$5:$C$104)=0,0,F{row_num}/COUNT(\'Mark Schedule\'!$C$5:$C$104))'
ws.cell(row=row_num, column=7).number_format = '0.00%'
else:
# Total row calculations
ws.cell(row=row_num, column=2).value = f'=SUM(B6:B15)'
ws.cell(row=row_num, column=3).value = f'=IF(COUNTIF(\'Mark Schedule\'!
$C$5:$C$104,"M")=0,0,B{row_num}/COUNTIF(\'Mark Schedule\'!$C$5:$C$104,"M"))'
ws.cell(row=row_num, column=3).number_format = '0.00%'

ws.cell(row=row_num, column=4).value = f'=SUM(D6:D15)'


ws.cell(row=row_num, column=5).value = f'=IF(COUNTIF(\'Mark Schedule\'!
$C$5:$C$104,"F")=0,0,D{row_num}/COUNTIF(\'Mark Schedule\'!$C$5:$C$104,"F"))'
ws.cell(row=row_num, column=5).number_format = '0.00%'

ws.cell(row=row_num, column=6).value = f'=SUM(F6:F15)'


ws.cell(row=row_num, column=7).value = f'=IF(COUNT(\'Mark Schedule\'!
$C$5:$C$104)=0,0,F{row_num}/COUNT(\'Mark Schedule\'!$C$5:$C$104))'
ws.cell(row=row_num, column=7).number_format = '0.00%'

# Add borders to all cells in the row


for col in range(1, 8):
ws.cell(row=row_num, column=col).border = thin_border

# Table 2: Performance Categories Summary


ws['A18'] = "Table 2: Performance Categories Summary"
ws['A18'].font = Font(bold=True)

# Headers for Table 2


headers = ["Performance", "Male Count", "Male %", "Female Count", "Female %",
"Total Count", "Total %"]
for col, header in enumerate(headers, 1):
cell = ws.cell(row=19, column=col)
cell.value = header
cell.font = Font(bold=True)
cell.alignment = Alignment(horizontal='center')
cell.fill = PatternFill(start_color="D3D3D3", end_color="D3D3D3",
fill_type="solid")

# Add thin borders to header


for row in ws.iter_rows(min_row=19, max_row=19, min_col=1, max_col=7):
for cell in row:
cell.border = thin_border

# Performance categories for Table 2


performance_categories = ["DISTINCTION", "MERIT", "CREDIT", "SATISFACTORY",
"UNSATISFACTORY", "ABSENT", "TOTAL"]

for idx, category in enumerate(performance_categories):


row_num = 20 + idx
ws.cell(row=row_num, column=1).value = category
ws.cell(row=row_num, column=1).alignment = Alignment(horizontal='center')

if category != "TOTAL":
# Male Count
ws.cell(row=row_num, column=2).value = f'=COUNTIFS(\'Mark Schedule\'!
$C$5:$C$104,"M",\'Mark Schedule\'!$I$5:$I$104,"{category}")'

# Male Percentage
ws.cell(row=row_num, column=3).value = f'=IF(COUNTIF(\'Mark Schedule\'!
$C$5:$C$104,"M")=0,0,B{row_num}/COUNTIF(\'Mark Schedule\'!$C$5:$C$104,"M"))'
ws.cell(row=row_num, column=3).number_format = '0.00%'

# Female Count
ws.cell(row=row_num, column=4).value = f'=COUNTIFS(\'Mark Schedule\'!
$C$5:$C$104,"F",\'Mark Schedule\'!$I$5:$I$104,"{category}")'

# Female Percentage
ws.cell(row=row_num, column=5).value = f'=IF(COUNTIF(\'Mark Schedule\'!
$C$5:$C$104,"F")=0,0,D{row_num}/COUNTIF(\'Mark Schedule\'!$C$5:$C$104,"F"))'
ws.cell(row=row_num, column=5).number_format = '0.00%'

# Total Count
ws.cell(row=row_num, column=6).value = f'=B{row_num}+D{row_num}'

# Total Percentage
ws.cell(row=row_num, column=7).value = f'=IF(COUNT(\'Mark Schedule\'!
$C$5:$C$104)=0,0,F{row_num}/COUNT(\'Mark Schedule\'!$C$5:$C$104))'
ws.cell(row=row_num, column=7).number_format = '0.00%'
else:
# Total row calculations
ws.cell(row=row_num, column=2).value = f'=SUM(B20:B25)'
ws.cell(row=row_num, column=3).value = f'=IF(COUNTIF(\'Mark Schedule\'!
$C$5:$C$104,"M")=0,0,B{row_num}/COUNTIF(\'Mark Schedule\'!$C$5:$C$104,"M"))'
ws.cell(row=row_num, column=3).number_format = '0.00%'

ws.cell(row=row_num, column=4).value = f'=SUM(D20:D25)'


ws.cell(row=row_num, column=5).value = f'=IF(COUNTIF(\'Mark Schedule\'!
$C$5:$C$104,"F")=0,0,D{row_num}/COUNTIF(\'Mark Schedule\'!$C$5:$C$104,"F"))'
ws.cell(row=row_num, column=5).number_format = '0.00%'
ws.cell(row=row_num, column=6).value = f'=SUM(F20:F25)'
ws.cell(row=row_num, column=7).value = f'=IF(COUNT(\'Mark Schedule\'!
$C$5:$C$104)=0,0,F{row_num}/COUNT(\'Mark Schedule\'!$C$5:$C$104))'
ws.cell(row=row_num, column=7).number_format = '0.00%'

# Add borders to all cells in the row


for col in range(1, 8):
ws.cell(row=row_num, column=col).border = thin_border

# Table 3: Key Performance Indicators


ws['A28'] = "Table 3: Key Performance Indicators"
ws['A28'].font = Font(bold=True)

# Headers for Table 3


headers = ["KPI", "Male", "Female", "Overall"]
for col, header in enumerate(headers, 1):
cell = ws.cell(row=29, column=col)
cell.value = header
cell.font = Font(bold=True)
cell.alignment = Alignment(horizontal='center')
cell.fill = PatternFill(start_color="D3D3D3", end_color="D3D3D3",
fill_type="solid")

# Add thin borders to header


for row in ws.iter_rows(min_row=29, max_row=29, min_col=1, max_col=4):
for cell in row:
cell.border = thin_border

# KPI rows for Table 3


kpis = [
("Percentage of students who achieved grades ONE to SIX",
f'=SUM(B6:B11)/COUNTIF(\'Mark Schedule\'!$C$5:$C$104,"M")',
f'=SUM(D6:D11)/COUNTIF(\'Mark Schedule\'!$C$5:$C$104,"F")',
f'=SUM(F6:F11)/COUNT(\'Mark Schedule\'!$C$5:$C$104)'),

("Percentage of students who achieved grades ONE to EIGHT",


f'=SUM(B6:B13)/COUNTIF(\'Mark Schedule\'!$C$5:$C$104,"M")',
f'=SUM(D6:D13)/COUNTIF(\'Mark Schedule\'!$C$5:$C$104,"F")',
f'=SUM(F6:F13)/COUNT(\'Mark Schedule\'!$C$5:$C$104)'),

("Percentage of students who failed (grade NINE)",


f'=B15/COUNTIF(\'Mark Schedule\'!$C$5:$C$104,"M")',
f'=D15/COUNTIF(\'Mark Schedule\'!$C$5:$C$104,"F")',
f'=F15/COUNT(\'Mark Schedule\'!$C$5:$C$104)'),

("Percentage of students who were absent (grade X)",


f'=B16/COUNTIF(\'Mark Schedule\'!$C$5:$C$104,"M")',
f'=D16/COUNTIF(\'Mark Schedule\'!$C$5:$C$104,"F")',
f'=F16/COUNT(\'Mark Schedule\'!$C$5:$C$104)'),

("Male to female ratio in the class",


f'=COUNTIF(\'Mark Schedule\'!$C$5:$C$104,"M")/COUNTIF(\'Mark Schedule\'!
$C$5:$C$104,"F")',
"",
""),

("Overall class average score",


"",
"",
f'=AVERAGE(\'Mark Schedule\'!$G$5:$G$104)')
]

for idx, (kpi, male_formula, female_formula, overall_formula) in


enumerate(kpis):
row_num = 30 + idx
ws.cell(row=row_num, column=1).value = kpi
ws.cell(row=row_num, column=1).alignment = Alignment(horizontal='left')

ws.cell(row=row_num, column=2).value = male_formula


ws.cell(row=row_num, column=2).number_format = '0.00%'

ws.cell(row=row_num, column=3).value = female_formula


ws.cell(row=row_num, column=3).number_format = '0.00%'

ws.cell(row=row_num, column=4).value = overall_formula


ws.cell(row=row_num, column=4).number_format = '0.00%'

# Add borders to all cells in the row


for col in range(1, 5):
ws.cell(row=row_num, column=col).border = thin_border

# Add a note about the data


ws.merge_cells('A3:G3')
ws['A3'] = "All data is derived from the 'Mark Schedule' sheet."
ws['A3'].font = Font(italic=True)
ws['A3'].alignment = Alignment(horizontal='center')

def setup_dashboard(ws, mark_sheet, summary_sheet):


"""Set up the Dashboard sheet with visual representations of the analysis."""
# Set column widths
for col in range(1, 10):
ws.column_dimensions[get_column_letter(col)].width = 15

# Add title
ws.merge_cells('A1:G1')
ws['A1'] = "DASHBOARD"
ws['A1'].font = Font(size=16, bold=True)
ws['A1'].alignment = Alignment(horizontal='center', vertical='center')
ws.row_dimensions[1].height = 30

# Add subtitle with date


ws.merge_cells('A2:G2')
ws['A2'] = f"Generated on: {datetime.datetime.now().strftime('%Y-%m-%d')}"
ws['A2'].font = Font(size=10, italic=True)
ws['A2'].alignment = Alignment(horizontal='center')

# Scorecard/KPI Section
ws['A4'] = "Scorecard/KPI Section"
ws['A4'].font = Font(bold=True)

# Add KPI labels and values


kpis = [
("Class average score (overall)", '=Summary Analysis!G36'),
("Class average by gender (Male)", '=Summary Analysis!B36'),
("Class average by gender (Female)", '=Summary Analysis!C36'),
("Pass rate (grades ONE-EIGHT)", '=Summary Analysis!G31'),
("Distinction rate (grades ONE-TWO)", '=Summary Analysis!G30'),
("Failure rate (grade NINE)", '=Summary Analysis!G33'),
("Absence rate (grade X)", '=Summary Analysis!G34'),
("Total students count", '=COUNT(\'Mark Schedule\'!$C$5:$C$104)'),
("Male students count", '=COUNTIF(\'Mark Schedule\'!$C$5:$C$104,"M")'),
("Female students count", '=COUNTIF(\'Mark Schedule\'!$C$5:$C$104,"F")')
]

for idx, (label, formula) in enumerate(kpis):


row_num = 5 + idx
ws.cell(row=row_num, column=1).value = label
ws.cell(row=row_num, column=1).alignment = Alignment(horizontal='left')

ws.cell(row=row_num, column=2).value = formula


ws.cell(row=row_num, column=2).number_format = '0.00%' if "%" in label else
'0.00'

# Grouped Bar Chart: Grade Distribution by Gender


chart1 = BarChart()
chart1.type = "col"
chart1.style = 10
chart1.title = "Grade Distribution by Gender"
chart1.y_axis.title = "Student Count"
chart1.x_axis.title = "Grade"

# Data for the chart


data = Reference(summary_sheet, min_col=2, min_row=5, max_col=6, max_row=15)
cats = Reference(summary_sheet, min_col=1, min_row=6, max_row=15)

chart1.add_data(data, titles_from_data=True)
chart1.set_categories(cats)

# Add the chart to the worksheet


ws.add_chart(chart1, "A18")

# Pie Charts: Performance Distribution


# Male Performance Distribution
chart2 = PieChart()
chart2.title = "Male Performance Distribution"

data = Reference(summary_sheet, min_col=2, min_row=20, max_row=25)


labels = Reference(summary_sheet, min_col=1, min_row=20, max_row=25)

chart2.add_data(data, titles_from_data=True)
chart2.set_categories(labels)

# Add the chart to the worksheet


ws.add_chart(chart2, "J5")

# Female Performance Distribution


chart3 = PieChart()
chart3.title = "Female Performance Distribution"

data = Reference(summary_sheet, min_col=4, min_row=20, max_row=25)


labels = Reference(summary_sheet, min_col=1, min_row=20, max_row=25)

chart3.add_data(data, titles_from_data=True)
chart3.set_categories(labels)

# Add the chart to the worksheet


ws.add_chart(chart3, "J20")
# Overall Performance Distribution
chart4 = PieChart()
chart4.title = "Overall Performance Distribution"

data = Reference(summary_sheet, min_col=6, min_row=20, max_row=25)


labels = Reference(summary_sheet, min_col=1, min_row=20, max_row=25)

chart4.add_data(data, titles_from_data=True)
chart4.set_categories(labels)

# Add the chart to the worksheet


ws.add_chart(chart4, "J35")

# Add a note about the data


ws.merge_cells('A3:G3')
ws['A3'] = "All data is derived from the 'Summary Analysis' sheet."
ws['A3'].font = Font(italic=True)
ws['A3'].alignment = Alignment(horizontal='center')

def setup_instructions(ws):
"""Set up the Instructions sheet with user guidance."""
# Set column widths
ws.column_dimensions['A'].width = 100

# Add title
ws.merge_cells('A1:A2')
ws['A1'] = "INSTRUCTIONS FOR USING THE CLASS ASSESSMENT TOOL"
ws['A1'].font = Font(size=16, bold=True)
ws['A1'].alignment = Alignment(horizontal='center', vertical='center')
ws.row_dimensions[1].height = 30

# Add instructions
instructions = [
"1. Enter student data in the 'Mark Schedule' sheet.",
"2. Ensure that the 'Sex' column contains only 'M' or 'F'.",
"3. Ensure that assessment scores are between 0 and 100.",
"4. The 'Average', 'Grade', and 'Remark' columns will be automatically
calculated.",
"5. View summary statistics and analysis in the 'Summary Analysis' sheet.",
"6. View visual representations of the data in the 'Dashboard' sheet.",
"7. Do not modify cells with formulas or conditional formatting.",
"8. Save the file after entering data to preserve changes."
]

for idx, instruction in enumerate(instructions, 3):


ws.cell(row=idx, column=1).value = instruction
ws.cell(row=idx, column=1).alignment = Alignment(horizontal='left')

# Add a note about the tool


ws.merge_cells('A12:A13')
ws['A12'] = "This tool is designed to simplify class assessment analysis and
reporting."
ws['A12'].font = Font(italic=True)
ws['A12'].alignment = Alignment(horizontal='center')

# Run the function to create the Excel tool


create_class_assessment_tool()

You might also like