using NPOI.HSSF.UserModel; using NPOI.SS.UserModel; using YBEE.EQM.Core; namespace YBEE.EQM.Application; /// /// 导出成绩服务 /// /// /// /// /// /// public class ExamScoreExportService(IRepository rep, ISqlRepository sqlRep, IExamGradeService examGradeService, IExamCourseService examCourseService, IExportExcelService exportExcelService) : IExamScoreExportService, ITransient { /// /// 导出TQES输入文件 /// /// /// /// public async Task<(string, byte[])> ExportTqesFile(ExamScoreExportTqesFileInput input) { var examPlan = await rep.Change().DetachedEntities.ProjectToType().FirstOrDefaultAsync(t => t.Id == input.ExamPlanId) ?? throw Oops.Oh(ErrorCode.E2001, "监测计划"); var examGrades = await examGradeService.GetListByExamPlanId(input.ExamPlanId); var examCourses = await examCourseService.GetListByExamPlanId(input.ExamPlanId); // 临时存放目录 string fileRoot = Path.Combine(FileUtil.GetTempFileRoot(), $"{Guid.NewGuid()}"); Directory.CreateDirectory(fileRoot); string filePath = Path.Combine(fileRoot, $"{examPlan.Name}-TQES导入数据"); Directory.CreateDirectory(filePath); try { foreach (var examGrade in examGrades) { for (int i = 0; i < 2; i++) { HSSFWorkbook wb = new(); var cellStyles = exportExcelService.GetCellStyle(wb); ExamSampleType? examSampleType = i == 1 ? ExamSampleType.DISTRICT : null; var ecs = examCourses.Where(t => t.ExamGradeId == examGrade.Id).OrderBy(t => t.CourseId).ToList(); await ExportToTqesSheet(input, examGrade.GradeId, examSampleType, ecs, wb, cellStyles); MemoryStream ms = new(); wb.Write(ms, false); ms.Flush(); string fn = i == 0 ? "全员" : "抽测"; await File.WriteAllBytesAsync(Path.Combine(filePath, $"{examGrade.EducationStage.GetDescription()}-{examGrade.Grade.Name2}-监测成绩-{fn}.xls"), ms.ToArray()); if (!examGrade.IsRequiredSample) { break; } } } string outFileName = $"{examPlan.Name}-TQES导入数据-{DateTime.Now.Ticks}.zip"; string outFilePath = Path.Combine(fileRoot, outFileName); ICSharpCode.SharpZipLib.Zip.FastZip zip = new(); zip.CreateZip(outFilePath, filePath, true, string.Empty); var retBytes = await File.ReadAllBytesAsync(outFilePath); return (outFileName, retBytes); } catch (Exception ex) { throw new Exception("导出错误", ex); } finally { Directory.Delete(fileRoot, true); } } #region 导出方法 /// /// 导出到表格 /// /// /// /// /// /// /// /// private async Task ExportToTqesSheet(ExamScoreExportTqesFileInput input, short gradeId, ExamSampleType? examSampleType, List examCourses, HSSFWorkbook wb, ExportExcelCellStyle cellStyles) { ISheet sheet = wb.CreateSheet("监测成绩"); sheet.DisplayGridlines = false; sheet.CreateFreezePane(0, 1); int rowNum = 0; #region 列头 IRow headerRow = sheet.CreateRow(rowNum++); int ci = 0; exportExcelService.AddCell("学校", headerRow, ci++, cellStyles.ColumnFillHeaderStyle, sheet, 20); exportExcelService.AddCell("学校ID", headerRow, ci++, cellStyles.ColumnFillHeaderStyle, sheet, 10); exportExcelService.AddCell("考号", headerRow, ci++, cellStyles.ColumnFillHeaderStyle, sheet, 13); exportExcelService.AddCell("年级", headerRow, ci++, cellStyles.ColumnFillHeaderStyle, sheet, 8); exportExcelService.AddCell("班级", headerRow, ci++, cellStyles.ColumnFillHeaderStyle, sheet, 8); exportExcelService.AddCell("身份证号码", headerRow, ci++, cellStyles.ColumnFillHeaderStyle, sheet, 20); exportExcelService.AddCell("姓名", headerRow, ci++, cellStyles.ColumnFillHeaderStyle, sheet, 18); foreach (var c in examCourses) { exportExcelService.AddCell(c.Course.Name, headerRow, ci++, cellStyles.ColumnFillHeaderStyle, sheet, 8); } #endregion #region 数据 var totalList = await GetTotalList(input.ExamPlanId, gradeId, examSampleType); var scoreList = await GetScoreList(input.ExamPlanId, gradeId, examSampleType); foreach (var stu in totalList) { IRow row = sheet.CreateRow(rowNum++); ci = 0; exportExcelService.AddCell(stu.SysOrgName, row, ci++, cellStyles.LeftCellStyle); exportExcelService.AddCell(stu.TqesId, row, ci++, cellStyles.CenterCellStyle); exportExcelService.AddCell(stu.ExamNumber, row, ci++, cellStyles.CenterCellStyle); exportExcelService.AddCell(stu.GradeNumber, row, ci++, cellStyles.CenterCellStyle); exportExcelService.AddCell(stu.ClassNumber, row, ci++, cellStyles.CenterCellStyle); exportExcelService.AddCell(stu.IdNumber, row, ci++, cellStyles.CenterCellStyle); exportExcelService.AddCell(stu.Name, row, ci++, cellStyles.CenterCellStyle); var scores = scoreList.Where(t => t.ExamStudentId == stu.ExamStudentId).GroupBy(d => d.CourseId).Select(d => new ExamScoreExportTqesDto { CourseId = d.Key, Score = d.Max(s => s.Score), IsSpecial = d.FirstOrDefault()?.IsSpecial ?? false, IsAbsent = d.FirstOrDefault()?.IsAbsent ?? false, }).ToDictionary(d => d.CourseId); foreach (var c in examCourses) { if (stu.IsSpecial) { exportExcelService.AddCell("特殊", row, ci++, cellStyles.CenterCellStyle); continue; } if (scores.TryGetValue(c.CourseId, out ExamScoreExportTqesDto score)) { if (score.IsSpecial) { exportExcelService.AddCell("特殊", row, ci++, cellStyles.CenterCellStyle); } else if ((score.IsAbsent || input.IsZeroToAbsent) && score.Score == 0) { exportExcelService.AddCell("缺考", row, ci++, cellStyles.CenterCellStyle); } else { exportExcelService.AddCell(score.Score, row, ci++, cellStyles.CenterCellStyle); } } else { exportExcelService.AddCell(null, row, ci++, cellStyles.CenterCellStyle); } } } #endregion } #endregion #region 获取数据 /// /// 获取学生列表 /// /// /// /// /// private async Task> GetTotalList(int examPlanId, short gradeId, ExamSampleType? examSampleType) { var items = await sqlRep.SqlQueriesAsync($@" SELECT T1.sys_org_id, T2.`name` AS sys_org_name, T2.tqes_id, T1.exam_number, T3.grade_number, T1.class_number, CASE WHEN T4.id_number = '' OR T4.id_number IS NULL THEN RIGHT(CONCAT('00000000', T1.exam_plan_id, '-', T1.exam_number), 18) ELSE T4.id_number END AS id_number, T4.`name`, T1.exam_student_id, T1.exam_sample_type, T1.is_special FROM exam_score_total AS T1 JOIN sys_org AS T2 ON T1.sys_org_id = T2.id JOIN base_grade AS T3 ON T1.grade_id = T3.id JOIN exam_student AS T4 ON T1.exam_student_id = T4.id WHERE T1.exam_plan_id = @examPlanId AND T1.grade_id = @gradeId AND (T1.exam_sample_type = @examSampleType OR @examSampleType = 0) ORDER BY T1.sys_org_id, T1.grade_id, T1.class_number ;", new { ExamPlanId = examPlanId, GradeId = gradeId, ExamSampleType = examSampleType.HasValue ? (short)examSampleType : 0 }); return items; } /// /// 获取成绩列表 /// /// /// /// /// private async Task> GetScoreList(int examPlanId, short gradeId, ExamSampleType? examSampleType) { var items = await sqlRep.SqlQueriesAsync($@" SELECT T1.exam_student_id, T1.course_id, T1.is_absent, T1.is_special, T1.score FROM exam_score AS T1 WHERE T1.exam_plan_id = @examPlanId AND T1.grade_id = @gradeId AND (T1.exam_sample_type = @examSampleType OR @examSampleType = 0) ;", new { ExamPlanId = examPlanId, GradeId = gradeId, ExamSampleType = examSampleType.HasValue ? (short)examSampleType : 0 }); return items; } #endregion }