File size: 3,953 Bytes
e414cdf
b956a4c
e414cdf
75845be
e414cdf
a146115
e414cdf
08a9c69
b59f6c6
e414cdf
 
a146115
e414cdf
 
 
 
 
 
 
 
a146115
e414cdf
 
 
 
 
a146115
e414cdf
 
 
75845be
a146115
08a9c69
 
 
 
75845be
 
a146115
75845be
08a9c69
 
 
 
75845be
 
9472d3b
b59f6c6
9472d3b
a146115
9472d3b
b59f6c6
 
a146115
09d1bbf
6e3c696
 
b59f6c6
 
 
 
 
 
08a9c69
b59f6c6
 
08a9c69
0ea2809
 
b59f6c6
08a9c69
834dfa1
 
08a9c69
 
 
a146115
 
 
 
08a9c69
a146115
e414cdf
08a9c69
e414cdf
834dfa1
 
 
 
08a9c69
834dfa1
 
75845be
e414cdf
0ea2809
 
 
a146115
 
75845be
e414cdf
a146115
e414cdf
08a9c69
 
e414cdf
 
a146115
e414cdf
a146115
08a9c69
b59f6c6
 
08a9c69
e414cdf
 
 
 
 
 
b59f6c6
 
08a9c69
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75845be
e414cdf
08a9c69
b59f6c6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
import streamlit as st
import pandas as pd
import plotly.express as px
import io

st.set_page_config(page_title="Excel β†’ Management Insights", layout="wide")

st.title("πŸ“Š Excel β†’ Interactive Management Dashboard")
st.caption("PASS if Grade β‰₯ C | FAIL if C- / D / F")

# -----------------------------
# Grade logic
# -----------------------------
def grade_pass_fail(g):
    if pd.isna(g):
        return "Unknown"
    g = str(g).strip().upper()
    if g.startswith(("D", "E", "F")):
        return "Fail"
    if g.startswith("C"):
        return "Fail" if g.startswith("C-") else "Pass"
    if g.startswith(("A", "B")):
        return "Pass"
    return "Unknown"


def normalize_headers(df):
    df.columns = [str(c).strip() for c in df.columns]
    return df


def pick_grade_column(df):
    for c in df.columns:
        if "grade" in c.lower():
            return c
    return df.columns[-1]


def ensure_sno(df):
    for c in df.columns:
        if c.lower() in ["sno", "id", "studentid"]:
            return df, c
    df.insert(0, "Sno", range(1, len(df) + 1))
    return df, "Sno"


# -----------------------------
# Upload section (CORRECT)
# -----------------------------
uploaded = st.file_uploader("Upload Excel (.xlsx)", type=["xlsx"])

file_bytes = None  # βœ… ALWAYS defined

if uploaded is None:
    st.info("Upload an Excel file to begin.")
    st.stop()

if st.button("βœ… Load file"):
    try:
        file_bytes = uploaded.read()
    except Exception as e:
        st.error(f"Failed to read file: {e}")
        st.stop()

# β›” Stop if button not clicked or file not read
if file_bytes is None:
    st.warning("Click **Load file** after uploading.")
    st.stop()

if file_bytes == b"":
    st.error("Uploaded file is empty.")
    st.stop()

# -----------------------------
# Read Excel (force openpyxl)
# -----------------------------
try:
    bio = io.BytesIO(file_bytes)
    xls = pd.ExcelFile(bio, engine="openpyxl")
except Exception as e:
    st.error(f"Invalid Excel file. Please upload a real .xlsx file.\n\n{e}")
    st.stop()

sheet = st.selectbox("Select sheet", xls.sheet_names)

try:
    bio = io.BytesIO(file_bytes)
    raw = pd.read_excel(bio, sheet_name=sheet, engine="openpyxl")
except Exception as e:
    st.error(f"Cannot read selected sheet.\n\n{e}")
    st.stop()

raw = normalize_headers(raw)

# -----------------------------
# Build dataframe
# -----------------------------
grade_col = pick_grade_column(raw)
df = raw.copy()
df, sno_col = ensure_sno(df)

df["Grade"] = df[grade_col].astype(str).str.strip().str.upper()
df["PassFail"] = df["Grade"].apply(grade_pass_fail)
df["Pass"] = df["PassFail"] == "Pass"
df["Fail"] = df["PassFail"] == "Fail"

# -----------------------------
# KPIs
# -----------------------------
c1, c2, c3, c4 = st.columns(4)
c1.metric("Students", len(df))
c2.metric("Pass", int(df["Pass"].sum()))
c3.metric("Fail", int(df["Fail"].sum()))
c4.metric("Pass Rate", f"{df['Pass'].mean()*100:.1f}%")

st.divider()

# -----------------------------
# Views
# -----------------------------
view = st.sidebar.radio("View", ["Executive", "Risk", "Student", "Export"])

if view == "Executive":
    g = df["Grade"].value_counts().reset_index()
    g.columns = ["Grade", "Count"]
    st.plotly_chart(px.bar(g, x="Grade", y="Count"), use_container_width=True)

    p = df["PassFail"].value_counts().reset_index()
    p.columns = ["Status", "Count"]
    st.plotly_chart(px.pie(p, names="Status", values="Count"), use_container_width=True)

elif view == "Risk":
    st.subheader("Failing Students")
    st.dataframe(df[df["Fail"]][[sno_col, "Grade", "PassFail"]], use_container_width=True)

elif view == "Student":
    sid = st.selectbox("Select student", df[sno_col])
    st.dataframe(df[df[sno_col] == sid], use_container_width=True)

else:
    csv = df.to_csv(index=False).encode("utf-8")
    st.download_button("⬇️ Download CSV for Power BI", csv, "analysis_for_powerbi.csv", "text/csv")