原创大约 5 分钟
接着我们进入第二阶段,上个阶段仅仅完成了学生信息管理系统,现在继续完成成绩部分

数据库创建
接着创建课程表和成绩表。
sqlserver
use student_manage;
-- 创建课程表
CREATE TABLE tb_course(
cno VARCHAR(10), -- 课程号
cname VARCHAR(30), -- 课程名
teacher VARCHAR(100), -- 教师
score INT, -- 学分
PRIMARY KEY (cno)
);
GO
-- 插入课程数据
INSERT INTO tb_course VALUES('1001', '高数', '王老师', 5);
INSERT INTO tb_course VALUES('1002', '数据库原理', '李老师', 4);
GO
-- 创建成绩表
CREATE TABLE tb_score(
sno VARCHAR(20), -- 学号
cno VARCHAR(10), -- 课程号
score INT, -- 分数
PRIMARY KEY (cno, sno)
);
GO
-- 插入成绩数据
INSERT INTO tb_score VALUES('2024001', '1001', 50);
INSERT INTO tb_score VALUES('2024001', '1002', 85);
INSERT INTO tb_score VALUES('2024002', '1001', 68);
INSERT INTO tb_score VALUES('2024002', '1002', 89);
GO
-- 添加外键约束(学生-成绩)
ALTER TABLE tb_score ADD CONSTRAINT frn_stu_score
FOREIGN KEY(sno) REFERENCES tb_student (sno);
GO
-- 添加外键约束(课程-成绩)
ALTER TABLE tb_score ADD CONSTRAINT frn_cou_score
FOREIGN KEY(cno) REFERENCES tb_course (cno);
GO
mysql
create table tb_course(
cno varchar(10), -- 课程号
cname varchar(30), -- 课程名
teacher varchar(100), -- 教师
score int, -- 学分
PRIMARY KEY (`cno`)
);
insert into tb_course values('1001','高数','王老师','5');
insert into tb_course values('1002','数据库原理','李老师','4');
create table tb_score(
sno varchar(20), -- 学号
cno varchar(10), -- 课程号
score int, -- 分数
PRIMARY KEY (`cno`,`sno`)
);
insert into tb_score values('2024001','1001','50');
insert into tb_score values('2024001','1002','85');
insert into tb_score values('2024002','1001','68');
insert into tb_score values('2024002','1002','89');
alter table tb_score add CONSTRAINT frn_stu_score
FOREIGN KEY(sno) REFERENCES tb_student (sno);
alter table tb_score add CONSTRAINT frn_cou_score
FOREIGN KEY(cno) REFERENCES tb_course (cno);
课程管理实现
参考学生管理增删改查实现
成绩管理实现
实现成绩的增删改查功能
导出excel
使用mysql需要下载mysql的驱动,下载NPOI.dll
using NPOI.SS.UserModel;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.OleDb;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MyAutoApp
{
class ExcelUtils
{
/// <summary>
/// 导出到excel
/// </summary>
/// <param name="dgvUseName"></param>
/// <param name="name"></param>
public static void DataTableToExcel(DataGridView dgvUseName, string name)
{
if (dgvUseName.Rows.Count == 0)
{
MessageBox.Show("请您检查是否有数据导出", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
//提示用户保存文件位置
SaveFileDialog saveFileDialog = new SaveFileDialog();
//定义格式
saveFileDialog.Filter = "Excel files (*.xls)|*.xls";
//设置导出的sheet
saveFileDialog.FilterIndex = 0;
saveFileDialog.RestoreDirectory = true;
saveFileDialog.CreatePrompt = true;
//设置导出窗口的标题
saveFileDialog.Title = "导出Excel文件到";
//默认设置导出文件名称为空,让用户重新填写
saveFileDialog.FileName = name;
//显示导出框
DialogResult result = DialogResult.Cancel;
Thread t = new Thread((ThreadStart)(() => {
result = saveFileDialog.ShowDialog();//获取点击取消保存excel文件的按钮事件
}));
t.SetApartmentState(ApartmentState.STA);
t.Start();
t.Join();
if (result == DialogResult.Cancel) return;//点击取消
//打开文件流 开始写入
Stream myStream = saveFileDialog.OpenFile();
StreamWriter sw = new StreamWriter(myStream, System.Text.Encoding.GetEncoding("gb2312"));
string str = "";
try
{
//写标题
for (int i = 0; i < dgvUseName.ColumnCount; i++)
{
if (i > 0)
{
str += "\t";
}
str += dgvUseName.Columns[i].HeaderText;
}
sw.WriteLine(str);
//写内容
for (int j = 0; j < dgvUseName.Rows.Count; j++)
{
string tempStr = "";
for (int k = 0; k < dgvUseName.Columns.Count; k++)
{
if (k > 0)
{
tempStr += "\t";
}
if (dgvUseName.Rows[j].Cells[k].Value != null)
{
tempStr += dgvUseName.Rows[j].Cells[k].Value.ToString();
}
tempStr += "";
}
sw.WriteLine(tempStr);
}
MessageBox.Show("成功导出Excel表");
sw.Close();
myStream.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
finally
{
sw.Close();
myStream.Close();
}
}
}
}
成绩统计查询图表
实现成绩统计查询(利用AI实现)
laodData()实现
//统计
// 检查是否选择了特定课程
bool isSpecificCourseSelected = !string.IsNullOrEmpty(cno.SelectedValue?.ToString());
// 统计数据结构
DataTable statsTable = new DataTable();
if (!isSpecificCourseSelected)
{
// 情况1:未选择具体课程 - 计算各科目及格率
statsTable.Columns.Add("课程名");
statsTable.Columns.Add("及格率", typeof(double));
var courseGroups = dt.AsEnumerable()
.GroupBy(row => row.Field<string>("课程名"));
foreach (var courseGroup in courseGroups)
{
string courseName = courseGroup.Key;
int totalCount = courseGroup.Count();
int passCount = courseGroup.Count(row => {
object scoreObj = row["分数"];
double score = Convert.IsDBNull(scoreObj) ? 0 : Convert.ToDouble(scoreObj);
return score >= 60;
});
double passRate = totalCount > 0 ? Math.Round((passCount * 100.0) / totalCount, 2) : 0;
statsTable.Rows.Add(courseName, passRate);
}
}
else
{
// 情况2:选择了具体课程 - 统计分数段人数
statsTable.Columns.Add("分数段");
statsTable.Columns.Add("人数", typeof(int));
// 定义分数段
var scoreRanges = new[] {
new { Min = 0, Max = 29, Name = "0-29分" },
new { Min = 30, Max = 49, Name = "30-49分" },
new { Min = 50, Max = 59, Name = "50-59分" },
new { Min = 60, Max = 69, Name = "60-69分" },
new { Min = 70, Max = 79, Name = "70-79分" },
new { Min = 80, Max = 89, Name = "80-89分" },
new { Min = 90, Max = 100, Name = "90-100分" }
};
// 初始化人数统计
int[] counts = new int[scoreRanges.Length];
// 统计每个分数段的人数
foreach (DataRow row in dt.Rows)
{
object scoreObj = row["分数"];
if (Convert.IsDBNull(scoreObj)) continue;
double score = Convert.ToDouble(scoreObj);
for (int i = 0; i < scoreRanges.Length; i++)
{
if (score >= scoreRanges[i].Min && score <= scoreRanges[i].Max)
{
counts[i]++;
break;
}
}
}
// 填充统计结果
for (int i = 0; i < scoreRanges.Length; i++)
{
statsTable.Rows.Add(scoreRanges[i].Name, counts[i]);
}
}
// 配置Chart控件显示统计结果
chart1.Series.Clear();
chart1.Titles.Clear();
// 添加主标题
chart1.Titles.Add(isSpecificCourseSelected ?
"课程成绩分布分析" : "各科目及格率统计");
chart1.Titles[0].Font = new Font("微软雅黑", 12, FontStyle.Bold);
// 创建数据系列
Series series = new Series
{
Name = isSpecificCourseSelected ? "学生人数" : "及格率",
ChartType = SeriesChartType.Column,
IsValueShownAsLabel = true,
Color = Color.SteelBlue
};
// 根据统计类型设置不同格式
if (!isSpecificCourseSelected)
{
series.LabelFormat = "0.##'%'";
}
else
{
series.LabelFormat = "#人";
// 添加数据点标签角度
series["BarLabelStyle"] = "Center";
}
// 绑定数据
foreach (DataRow row in statsTable.Rows)
{
string name = row.Field<string>(0);
double value = Convert.ToDouble(row[1]);
series.Points.AddXY(name, value);
// 为及格率统计添加颜色区分
if (!isSpecificCourseSelected && name.Contains("及格"))
{
int pointIndex = series.Points.Count - 1;
series.Points[pointIndex].Color = value >= 60 ? Color.Green : Color.Orange;
}
}
chart1.Series.Add(series);
// 设置坐标轴样式
chart1.ChartAreas[0].AxisX.Title = isSpecificCourseSelected ? "分数段" : "课程";
chart1.ChartAreas[0].AxisY.Title = isSpecificCourseSelected ? "学生人数" : "及格率 (%)";
if (!isSpecificCourseSelected)
{
// 及格率统计的设置
chart1.ChartAreas[0].AxisY.Maximum = 100;
chart1.ChartAreas[0].AxisY.Minimum = 0;
chart1.ChartAreas[0].AxisY.Interval = 20;
}
// 使X轴标签倾斜45度避免重叠
chart1.ChartAreas[0].AxisX.LabelStyle.Angle = -45;
// 调整图例位置
chart1.Legends.Clear();