Example #1
0
        private void Worker_DoWork(object sender, DoWorkEventArgs e)
        {
            double total = Students.Count;
            double count = 0;

            _worker.ReportProgress(0);

            List <string> studentIDs = Students.Select(x => x.ID).ToList();

            #region 快取資料

            //獎勵
            // 1.依學生編號、開始日期、結束日期,取得學生獎勵紀錄
            // 2.依學生編號進行分群
            Dictionary <string, List <JHMeritRecord> > meritCache = new Dictionary <string, List <JHMeritRecord> >();
            foreach (JHMeritRecord record in JHMerit.Select(studentIDs, _config.StartDate, _config.EndDate, null, null, null, null))
            {
                if (!meritCache.ContainsKey(record.RefStudentID))
                {
                    meritCache.Add(record.RefStudentID, new List <JHMeritRecord>());
                }
                meritCache[record.RefStudentID].Add(record);
            }

            //懲戒
            // 1.依學生編號、開始日期、結束日期,取得學生懲戒紀錄
            // 2.依學生編號進行分群
            Dictionary <string, List <JHDemeritRecord> > demeritCache = new Dictionary <string, List <JHDemeritRecord> >();
            foreach (JHDemeritRecord record in JHDemerit.Select(studentIDs, _config.StartDate, _config.EndDate, null, null, null, null))
            {
                if (!demeritCache.ContainsKey(record.RefStudentID))
                {
                    demeritCache.Add(record.RefStudentID, new List <JHDemeritRecord>());
                }
                demeritCache[record.RefStudentID].Add(record);
            }

            //缺曠
            // 1.依學生編號、開始日期、結束日期,取得學生缺曠紀錄
            // 2.依學生編號進行分群
            Dictionary <string, List <JHAttendanceRecord> > attendanceCache = new Dictionary <string, List <JHAttendanceRecord> >();
            foreach (JHAttendanceRecord record in JHAttendance.Select(studentIDs, _config.StartDate, _config.EndDate, null, null, null))
            {
                if (!attendanceCache.ContainsKey(record.RefStudentID))
                {
                    attendanceCache.Add(record.RefStudentID, new List <JHAttendanceRecord>());
                }
                attendanceCache[record.RefStudentID].Add(record);
            }

            // 建立平時評量與修課成績Idx Key studentID
            Dictionary <string, List <JHSCAttendRecord> > _studAttendRecDict = new Dictionary <string, List <JHSCAttendRecord> >();


            //修課紀錄
            // 1.依學生編號、學年度、學期,取得修課紀錄
            // 2.
            List <string> courseIDs = new List <string>();
            List <string> attendIDs = new List <string>();
            Dictionary <string, List <string> > scCache = new Dictionary <string, List <string> >();
            foreach (var attend in JHSCAttend.Select(studentIDs, null, null, "" + _config.SchoolYear, "" + _config.Semester))
            {
                attendIDs.Add(attend.ID);
                if (!scCache.ContainsKey(attend.RefStudentID))
                {
                    scCache.Add(attend.RefStudentID, new List <string>());
                }
                scCache[attend.RefStudentID].Add(attend.RefCourseID);
                if (!courseIDs.Contains(attend.RefCourseID))
                {
                    courseIDs.Add(attend.RefCourseID);
                }

                // 建立評量與修課成績
                if (_studAttendRecDict.ContainsKey(attend.RefStudentID))
                {
                    _studAttendRecDict[attend.RefStudentID].Add(attend);
                }
                else
                {
                    List <JHSCAttendRecord> atten = new List <JHSCAttendRecord>();
                    atten.Add(attend);
                    _studAttendRecDict.Add(attend.RefStudentID, atten);
                }
            }

            //課程
            // 1.依課程編號取得課程紀錄
            // 2.略過不列入成績計算的課程
            JHCourse.RemoveByIDs(courseIDs);
            Dictionary <string, JHCourseRecord> courseCache = JHCourse.SelectByIDs(courseIDs).Where(x => x.CalculationFlag != "2").ToDictionary(x => x.ID);

            //試別資訊: 取得所有試別
            Dictionary <string, JHExamRecord> examCache = JHExam.SelectAll().ToDictionary(x => x.ID);

            // 取得社團ExamID
            List <string> NExamIDList = new List <string> ();
            foreach (JHExamRecord rec in JHExam.SelectAll())
            {
                if (rec.Name.IndexOf("社團") > -1)
                {
                    NExamIDList.Add(rec.ID);
                }
            }

            //評量成績
            // 1.依修課記錄及所有試別取得評量成績
            // 2.依第1點的評量成績取得試別編號 (實際學生評量成績中的試別編號)
            // 3.依學生編號進行分群
            Dictionary <string, List <KH.JHSCETakeRecord> > sceScoreCache = new Dictionary <string, List <KH.JHSCETakeRecord> >();
            List <string> validExamIDs = new List <string>();

            // 檢查有修課才讀取成績
            if (attendIDs.Count > 0 && examCache.Count > 0)
            {
                foreach (JHSCETakeRecord record in JHSCETake.Select(null, null, examCache.Keys, null, attendIDs))
                {
                    if (!NExamIDList.Contains(record.RefExamID))
                    {
                        if (!validExamIDs.Contains(record.RefExamID))
                        {
                            validExamIDs.Add(record.RefExamID);
                        }
                    }

                    if (!sceScoreCache.ContainsKey(record.RefStudentID))
                    {
                        sceScoreCache.Add(record.RefStudentID, new List <KH.JHSCETakeRecord>());
                    }
                    sceScoreCache[record.RefStudentID].Add(new KH.JHSCETakeRecord(record));
                }
            }

            //將『所有試別編號』與『實際學生評量成績中的試別編號』做交集,以取得使用管理的試別次序
            //假設『所有試別編號』為1,4,3,5
            //假設『實際學生評量成績中的試別編號』為3,4,1
            //交集後的結果為1,4,3
            validExamIDs = examCache.Keys.Intersect(validExamIDs).ToList();

            validExamIDs.Add("平時評量");
            //validExamIDs.Add("課程總成績");

            // 取得學生成績計算規則
            // 如果學生沒有計算規則一律用預設,預設進位方式取到小數點第2位
            ScoreCalculator defaultScoreCalculator = new ScoreCalculator(null);
            //key: ScoreCalcRuleID
            Dictionary <string, ScoreCalculator> calcCache = new Dictionary <string, ScoreCalculator>();
            //key: StudentID, val: ScoreCalcRuleID
            Dictionary <string, string> calcIDCache = new Dictionary <string, string>();

            List <string> scoreCalcRuleIDList = new List <string>();

            // 取得學生計算規則的ID,建立對照表
            // 如果學生身上有指定成績計算規則,就以學生身上成績計算規則為主
            // 如果學生身上沒有指定成績計算規則,就以學生所屬班級成績計算規則為主
            foreach (JHStudentRecord student in _config.Students)
            {
                string calcID = string.Empty;
                if (!string.IsNullOrEmpty(student.OverrideScoreCalcRuleID))
                {
                    calcID = student.OverrideScoreCalcRuleID;
                }
                else if (student.Class != null && !string.IsNullOrEmpty(student.Class.RefScoreCalcRuleID))
                {
                    calcID = student.Class.RefScoreCalcRuleID;
                }

                if (!string.IsNullOrEmpty(calcID))
                {
                    calcIDCache.Add(student.ID, calcID);
                }
            }
            // 取得計算規則建立成績進位器
            foreach (JHScoreCalcRuleRecord record in JHScoreCalcRule.SelectByIDs(calcIDCache.Values))
            {
                if (!calcCache.ContainsKey(record.ID))
                {
                    calcCache.Add(record.ID, new ScoreCalculator(record));
                }
            }

            #endregion


            #region 判斷領域是否需要展開
            //判斷領域是否展開對照表
            //Key:領域名稱
            //Value:false=展開,true=不展開
            //展開: 詳列該領域下所有科目成績
            //不展開: 只列該領域成績
            Dictionary <string, bool> domains = new Dictionary <string, bool>();

            DomainSubjectSetup domainSubjectSetup = _config.DomainSubjectSetup;
            //使用者設定"只列印領域"
            if (domainSubjectSetup == DomainSubjectSetup.Domain)
            {
                //預設從領域資料管理來的領域名稱皆不展開
                foreach (var domain in JHSchool.Evaluation.Subject.Domains)
                {
                    domains.Add(domain, DomainSubjectExpand.展開);
                }
                //彈性課程一定展開
                if (!domains.ContainsKey(""))
                {
                    domains.Add("", DomainSubjectExpand.展開);
                }
            }
            //使用者設定"只列印科目"
            else if (domainSubjectSetup == DomainSubjectSetup.Subject)
            {
                //預設從領域資料管理來的領域名稱皆展開
                foreach (var domain in JHSchool.Evaluation.Subject.Domains)
                {
                    domains.Add(domain, DomainSubjectExpand.展開);
                }
                //彈性課程一定展開
                if (!domains.ContainsKey(""))
                {
                    domains.Add("", DomainSubjectExpand.展開);
                }
            }
            else
            {
                throw new Exception("請重新儲存一次列印設定");
            }

            _config.PrintDomains = domains;
            #endregion

            #region 建立節次對照
            Dictionary <string, string> periodMapping = JHPeriodMapping.SelectAll().ToDictionary(x => x.Name, y => y.Type);
            #endregion

            #region 假別列表
            List <string> absenceList = JHAbsenceMapping.SelectAll().Select(x => x.Name).ToList();
            #endregion

            #region 依評量試別重新劃分範本
            //如有不懂自求多福
            int             rowCount        = 0;
            DocumentBuilder templateBuilder = new DocumentBuilder(_template);
            templateBuilder.MoveToMergeField("各次評量");
            Font   font       = templateBuilder.Font;
            Cell   examsCell  = templateBuilder.CurrentParagraph.ParentNode as Cell;
            Table  table      = examsCell.ParentRow.ParentTable;
            double width      = examsCell.CellFormat.Width;
            double examWidth  = width / (double)validExamIDs.Count;
            double scoreWidth = width / (double)validExamIDs.Count / 2.0;

            //計算有幾個 Score Row
            foreach (Row row in table.Rows)
            {
                if (row.Cells.Count > 3)
                {
                    rowCount++;
                }
            }

            #region Header Cell
            //建立評量欄位對照表
            Dictionary <string, int> columnMapping = new Dictionary <string, int>();
            int columnShift = 3;
            int columnIndex = 0;

            table.Rows[0].LastCell.Remove();
            table.Rows[1].LastCell.Remove();

            foreach (string examID in validExamIDs)
            {
                columnMapping.Add(examID, columnIndex + columnShift);

                Cell topHeaderCell = new Cell(_template);
                if (examID == "平時評量" || examID == "課程總成績")
                {
                    WordHelper.Write(topHeaderCell, font, examID);
                }
                else
                {
                    WordHelper.Write(topHeaderCell, font, examCache[examID].Name);
                }
                table.Rows[0].Cells.Add(topHeaderCell);

                Cell subHeaderCell1 = new Cell(_template);
                WordHelper.Write(subHeaderCell1, font, "分數", "評量");
                table.Rows[1].Cells.Add(subHeaderCell1);
                columnIndex++;

                Cell subHeaderCell2 = new Cell(_template);
                WordHelper.Write(subHeaderCell2, font, "努力", "程度");
                table.Rows[1].Cells.Add(subHeaderCell2);
                columnIndex++;

                topHeaderCell.CellFormat.Width  = examWidth;
                subHeaderCell1.CellFormat.Width = subHeaderCell2.CellFormat.Width = scoreWidth;

                topHeaderCell.CellFormat.VerticalAlignment  = CellVerticalAlignment.Center;
                subHeaderCell1.CellFormat.VerticalAlignment = CellVerticalAlignment.Center;
                subHeaderCell2.CellFormat.VerticalAlignment = CellVerticalAlignment.Center;
            }

            WordHelper.MergeVerticalCell(table.Rows[0].Cells[1], 2);
            #endregion

            #region Content Cell
            int shift = 2; //Header has 2 rows
            for (int i = 0; i < rowCount; i++)
            {
                table.Rows[i + shift].LastCell.Remove();

                for (int j = 0; j < validExamIDs.Count * 2; j++)
                {
                    Cell contentCell = new Cell(_template);
                    contentCell.CellFormat.Width             = scoreWidth;
                    contentCell.CellFormat.VerticalAlignment = CellVerticalAlignment.Center;

                    table.Rows[i + shift].Cells.Add(contentCell);
                }
            }
            #endregion

            #endregion

            #region 依節權數設定,在畫面上顯示
            string pcDisplay = string.Empty;
            if (_config.PrintPeriod && _config.PrintCredit)
            {
                pcDisplay = "節/權數";
            }
            else if (_config.PrintPeriod)
            {
                pcDisplay = "節數";
            }
            else if (_config.PrintCredit)
            {
                pcDisplay = "權數";
            }

            templateBuilder.MoveToMergeField("節權數");
            templateBuilder.Write(pcDisplay);
            #endregion

            // 取得學期歷程
            Config._StudSemesterHistoryItemDict.Clear();

            List <JHSemesterHistoryRecord> semHisRec = JHSemesterHistory.SelectByStudents(Students);
            // 當畫面學期歷程內的學年度學期與畫面上設定相同,加入
            foreach (JHSemesterHistoryRecord rec in semHisRec)
            {
                foreach (K12.Data.SemesterHistoryItem shi in rec.SemesterHistoryItems)
                {
                    if (shi.SchoolYear == _config.SchoolYear && shi.Semester == _config.Semester)
                    {
                        if (!Config._StudSemesterHistoryItemDict.ContainsKey(shi.RefStudentID))
                        {
                            Config._StudSemesterHistoryItemDict.Add(shi.RefStudentID, shi);
                        }
                    }
                }
            }

            // 取得學生服務學習時數
            Config._SRDict.Clear();
            List <string> sidList = (from data in Students select data.ID).ToList();
            Config._SRDict = Utility.GetServiceLearningDetail(sidList, _config.SchoolYear, _config.Semester);


            #region 產生
            foreach (JHStudentRecord student in Students)
            {
                count++;

                Document        each    = (Document)_template.Clone(true);
                DocumentBuilder builder = new DocumentBuilder(each);

                #region 學生基本資料
                StudentBasicInfo basicInfo = new StudentBasicInfo(builder);
                basicInfo.SetStudent(student);
                #endregion


                #region 各評量成績
                List <KH.JHSCETakeRecord> sceScoreList = null;
                if (sceScoreCache.ContainsKey(student.ID))
                {
                    sceScoreList = sceScoreCache[student.ID];
                }
                else
                {
                    sceScoreList = new List <KH.JHSCETakeRecord>();
                }

                ScoreCalculator studentCalculator = defaultScoreCalculator;
                if (calcIDCache.ContainsKey(student.ID) && calcCache.ContainsKey(calcIDCache[student.ID]))
                {
                    studentCalculator = calcCache[calcIDCache[student.ID]];
                }

                // 課程成績
                Dictionary <string, JHSCAttendRecord> attendRecDict = new Dictionary <string, JHSCAttendRecord>();
                // 領域成績(平時)
                Dictionary <string, decimal?> domainScDict = new Dictionary <string, decimal?>();
                //// 領域成績(總)
                //Dictionary<string, decimal> domainScDictTT = new Dictionary<string, decimal>();

                if (_studAttendRecDict.ContainsKey(student.ID))
                {
                    foreach (JHSCAttendRecord rec in _studAttendRecDict[student.ID])
                    {
                        if (!attendRecDict.ContainsKey(rec.Course.Subject))
                        {
                            attendRecDict.Add(rec.Course.Subject, rec);
                        }
                    }


                    List <string> tName = (from xx in _studAttendRecDict[student.ID] select xx.Course.Domain).Distinct().ToList();

                    foreach (string Name in tName)
                    {
                        decimal?sc = 0, co = 0;
                        foreach (JHSCAttendRecord rec in _studAttendRecDict[student.ID])
                        {
                            if (rec.Course.Domain == Name)
                            {
                                if (rec.OrdinarilyScore.HasValue && rec.Course.Credit.HasValue)
                                {
                                    sc += (rec.OrdinarilyScore.Value * rec.Course.Credit.Value);
                                    // 有成績才算入
                                    co += rec.Course.Credit.Value;
                                }
                            }
                        }

                        if (co.HasValue && sc.HasValue)
                        {
                            if (co.Value > 0)
                            {
                                if (!domainScDict.ContainsKey(Name))
                                {
                                    domainScDict.Add(Name, (sc.Value / co.Value));
                                }
                            }
                        }
                    }
                }

                //StudentExamScore examScore = new StudentExamScore(builder, _config, courseCache, attendRecDict,domainScDict,domainScDictTT);
                StudentExamScore examScore = new StudentExamScore(builder, _config, courseCache, attendRecDict, domainScDict);
                if (scCache.ContainsKey(student.ID))
                {
                    examScore.SetSubjects(scCache[student.ID]);
                }
                examScore.SetColumnMap(columnMapping);
                examScore.SetEffortMapper(_effortMapper);
                examScore.SetCalculator(studentCalculator);
                examScore.SetData(sceScoreList);
                #endregion

                #region 缺曠獎懲
                List <JHMeritRecord>      meritList      = null;
                List <JHDemeritRecord>    demeritList    = null;
                List <JHAttendanceRecord> attendanceList = null;

                meritList      = (meritCache.ContainsKey(student.ID)) ? meritCache[student.ID] : new List <JHMeritRecord>();
                demeritList    = (demeritCache.ContainsKey(student.ID)) ? demeritCache[student.ID] : new List <JHDemeritRecord>();
                attendanceList = (attendanceCache.ContainsKey(student.ID)) ? attendanceCache[student.ID] : new List <JHAttendanceRecord>();

                StudentMoralScore moral = new StudentMoralScore(builder, _config, periodMapping, absenceList);
                moral.SetData(meritList, demeritList, attendanceList);
                #endregion

                foreach (Section sec in each.Sections)
                {
                    _doc.Sections.Add(_doc.ImportNode(sec, true));
                }

                //回報進度
                _worker.ReportProgress((int)(count * 100.0 / total));
            }

            #region 全域 MergeField
            List <string> globalFieldName  = new List <string>();
            List <object> globalFieldValue = new List <object>();

            globalFieldName.Add("學校名稱");
            globalFieldValue.Add(K12.Data.School.ChineseName);

            globalFieldName.Add("學年度");
            globalFieldValue.Add(_config.SchoolYear.ToString());
            //globalFieldValue.Add(K12.Data.School.DefaultSchoolYear);

            globalFieldName.Add("學期");
            globalFieldValue.Add(_config.Semester.ToString());
            //globalFieldValue.Add(K12.Data.School.DefaultSemester);

            globalFieldName.Add("統計期間");
            globalFieldValue.Add(_config.StartDate.ToShortDateString() + " ~ " + _config.EndDate.ToShortDateString());

            globalFieldName.Add("列印日期");
            globalFieldValue.Add(DateConvert.CDate(DateTime.Now.ToString("yyyy/MM/dd")) + " " + DateTime.Now.ToString("HH:mm:ss"));

            string chancellor, eduDirector, stuDirector;
            chancellor = eduDirector = stuDirector = string.Empty;

            XmlElement schoolInfo         = K12.Data.School.Configuration["學校資訊"].PreviousData;
            XmlElement chancellorElement  = (XmlElement)schoolInfo.SelectSingleNode("ChancellorChineseName");
            XmlElement eduDirectorElement = (XmlElement)schoolInfo.SelectSingleNode("EduDirectorName");
            XmlElement stuDirectorElement = (XmlElement)schoolInfo.SelectSingleNode("StuDirectorName");

            if (chancellorElement != null)
            {
                chancellor = chancellorElement.InnerText;
            }
            if (eduDirectorElement != null)
            {
                eduDirector = eduDirectorElement.InnerText;
            }
            if (stuDirectorElement != null)
            {
                stuDirector = stuDirectorElement.InnerText;
            }

            globalFieldName.Add("校長");
            globalFieldValue.Add(chancellor);

            globalFieldName.Add("教務主任");
            globalFieldValue.Add(eduDirector);

            globalFieldName.Add("學務主任");
            globalFieldValue.Add(stuDirector);

            _doc.MailMerge.Execute(globalFieldName.ToArray(), globalFieldValue.ToArray());
            #endregion

            #endregion
        }
Example #2
0
        public ImportStartupForm()
        {
            InitializeComponent();
            InitializeSemesters();

            _effortMapper = new EffortMapper();

            // 載入預設儲存值
            LoadConfigData();

            _worker = new BackgroundWorker();
            _worker.WorkerReportsProgress = true;
            _worker.ProgressChanged      += delegate(object sender, ProgressChangedEventArgs e)
            {
                lblMessage.Text = "" + e.UserState;
            };
            _worker.DoWork += delegate(object sender, DoWorkEventArgs e)
            {
                #region Worker DoWork
                _worker.ReportProgress(0, "檢查讀卡文字格式…");

                #region 檢查文字檔
                ValidateTextFiles  vtf      = new ValidateTextFiles(intStudentNumberLenght.Value);
                ValidateTextResult vtResult = vtf.CheckFormat(_files);
                if (vtResult.Error)
                {
                    e.Result = vtResult;
                    return;
                }
                #endregion

                //文字檔轉 RawData
                RawDataCollection rdCollection = new RawDataCollection();
                rdCollection.ConvertFromFiles(_files);

                //RawData 轉 DataRecord
                DataRecordCollection drCollection = new DataRecordCollection();
                drCollection.ConvertFromRawData(rdCollection);

                _rawDataValidator    = new DataValidator <RawData>();
                _dataRecordValidator = new DataValidator <DataRecord>();

                #region 取得驗證需要的資料
                JHCourse.RemoveAll();
                _worker.ReportProgress(0, "取得學生資料…");
                List <JHStudentRecord> studentList = GetInSchoolStudents();

                List <string> s_ids = new List <string>();
                Dictionary <string, List <string> > studentNumberToStudentIDs = new Dictionary <string, List <string> >();
                foreach (JHStudentRecord student in studentList)
                {
                    string sn = SCValidatorCreator.GetStudentNumberFormat(student.StudentNumber);
                    if (!studentNumberToStudentIDs.ContainsKey(sn))
                    {
                        studentNumberToStudentIDs.Add(sn, new List <string>());
                    }
                    studentNumberToStudentIDs[sn].Add(student.ID);
                }
                foreach (var dr in drCollection)
                {
                    if (studentNumberToStudentIDs.ContainsKey(dr.StudentNumber))
                    {
                        s_ids.AddRange(studentNumberToStudentIDs[dr.StudentNumber]);
                    }
                }

                studentList.Clear();

                _worker.ReportProgress(0, "取得課程資料…");
                List <JHCourseRecord>    courseList = JHCourse.SelectBySchoolYearAndSemester(SchoolYear, Semester);
                List <JHAEIncludeRecord> aeList     = JHAEInclude.SelectAll();

                //List<JHSCAttendRecord> scaList = JHSCAttend.SelectAll();
                var c_ids = from course in courseList select course.ID;
                _worker.ReportProgress(0, "取得修課資料…");
                //List<JHSCAttendRecord> scaList2 = JHSCAttend.SelectByStudentIDAndCourseID(s_ids, c_ids.ToList<string>());
                List <JHSCAttendRecord> scaList = new List <JHSCAttendRecord>();
                FunctionSpliter <string, JHSCAttendRecord> spliter = new FunctionSpliter <string, JHSCAttendRecord>(300, 3);
                spliter.Function = delegate(List <string> part)
                {
                    return(JHSCAttend.Select(part, c_ids.ToList <string>(), null, SchoolYear.ToString(), Semester.ToString()));
                };
                scaList = spliter.Execute(s_ids);

                _worker.ReportProgress(0, "取得試別資料…");
                List <JHExamRecord> examList = JHExam.SelectAll();
                #endregion

                #region 註冊驗證
                _worker.ReportProgress(0, "載入驗證規則…");
                _rawDataValidator.Register(new SubjectCodeValidator());
                _rawDataValidator.Register(new ClassCodeValidator());
                _rawDataValidator.Register(new ExamCodeValidator());

                SCValidatorCreator scCreator = new SCValidatorCreator(JHStudent.SelectByIDs(s_ids), courseList, scaList);
                _dataRecordValidator.Register(scCreator.CreateStudentValidator());
                _dataRecordValidator.Register(new ExamValidator(examList));
                _dataRecordValidator.Register(scCreator.CreateSCAttendValidator());
                _dataRecordValidator.Register(new CourseExamValidator(scCreator.StudentCourseInfo, aeList, examList));
                #endregion

                #region 進行驗證
                _worker.ReportProgress(0, "進行驗證中…");
                List <string> msgList = new List <string>();

                foreach (RawData rawData in rdCollection)
                {
                    List <string> msgs = _rawDataValidator.Validate(rawData);
                    msgList.AddRange(msgs);
                }
                if (msgList.Count > 0)
                {
                    e.Result = msgList;
                    return;
                }

                foreach (DataRecord dataRecord in drCollection)
                {
                    List <string> msgs = _dataRecordValidator.Validate(dataRecord);
                    msgList.AddRange(msgs);
                }
                if (msgList.Count > 0)
                {
                    e.Result = msgList;
                    return;
                }
                #endregion

                #region 取得學生的評量成績
                _deleteScoreList.Clear();
                _addScoreList.Clear();

                //var student_ids = from student in scCreator.StudentNumberDictionary.Values select student.ID;
                //List<string> course_ids = scCreator.AttendCourseIDs;

                var scaIDs = from sca in scaList select sca.ID;

                Dictionary <string, JHSCETakeRecord>      sceList    = new Dictionary <string, JHSCETakeRecord>();
                FunctionSpliter <string, JHSCETakeRecord> spliterSCE = new FunctionSpliter <string, JHSCETakeRecord>(300, 3);
                spliterSCE.Function = delegate(List <string> part)
                {
                    return(JHSCETake.Select(null, null, null, null, part));
                };
                foreach (JHSCETakeRecord sce in spliterSCE.Execute(scaIDs.ToList()))
                {
                    string key = GetCombineKey(sce.RefStudentID, sce.RefCourseID, sce.RefExamID);
                    if (!sceList.ContainsKey(key))
                    {
                        sceList.Add(key, sce);
                    }
                }

                Dictionary <string, JHExamRecord>     examTable = new Dictionary <string, JHExamRecord>();
                Dictionary <string, JHSCAttendRecord> scaTable  = new Dictionary <string, JHSCAttendRecord>();

                foreach (JHExamRecord exam in examList)
                {
                    if (!examTable.ContainsKey(exam.Name))
                    {
                        examTable.Add(exam.Name, exam);
                    }
                }

                foreach (JHSCAttendRecord sca in scaList)
                {
                    string key = GetCombineKey(sca.RefStudentID, sca.RefCourseID);
                    if (!scaTable.ContainsKey(key))
                    {
                        scaTable.Add(key, sca);
                    }
                }

                foreach (DataRecord dr in drCollection)
                {
                    JHStudentRecord       student = student = scCreator.StudentNumberDictionary[dr.StudentNumber];
                    JHExamRecord          exam    = examTable[dr.Exam];
                    List <JHCourseRecord> courses = new List <JHCourseRecord>();
                    foreach (JHCourseRecord course in scCreator.StudentCourseInfo.GetCourses(dr.StudentNumber))
                    {
                        if (dr.Subjects.Contains(course.Subject))
                        {
                            courses.Add(course);
                        }
                    }

                    foreach (JHCourseRecord course in courses)
                    {
                        string key = GetCombineKey(student.ID, course.ID, exam.ID);

                        if (sceList.ContainsKey(key))
                        {
                            _deleteScoreList.Add(sceList[key]);
                        }

                        JHSCETakeRecord    jh     = new JHSCETakeRecord();
                        KH.JHSCETakeRecord sceNew = new KH.JHSCETakeRecord(jh);
                        sceNew.RefCourseID   = course.ID;
                        sceNew.RefExamID     = exam.ID;
                        sceNew.RefSCAttendID = scaTable[GetCombineKey(student.ID, course.ID)].ID;
                        sceNew.RefStudentID  = student.ID;
                        sceNew.Score         = dr.Score;
                        sceNew.Effort        = _effortMapper.GetCodeByScore(dr.Score);
                        _addScoreList.Add(sceNew.AsJHSCETakeRecord());
                    }
                }
                #endregion

                e.Result = null;
                #endregion
            };
            _worker.RunWorkerCompleted += delegate(object sender, RunWorkerCompletedEventArgs e)
            {
                #region Worker Completed
                if (e.Error == null && e.Result == null)
                {
                    if (!_upload.IsBusy)
                    {
                        //如果學生身上已有成績,則提醒使用者
                        if (_deleteScoreList.Count > 0)
                        {
                            _warn.RunWorkerAsync();
                        }
                        else
                        {
                            lblMessage.Text = "成績上傳中…";
                            FISCA.Presentation.MotherForm.SetStatusBarMessage("成績上傳中…", 0);
                            counter = 0;
                            _upload.RunWorkerAsync();
                        }
                    }
                }
                else
                {
                    ControlEnable = true;

                    if (e.Error != null)
                    {
                        MsgBox.Show("匯入失敗。" + e.Error.Message);
                        SmartSchool.ErrorReporting.ReportingService.ReportException(e.Error);
                    }
                    else if (e.Result != null && e.Result is ValidateTextResult)
                    {
                        ValidateTextResult    result = e.Result as ValidateTextResult;
                        ValidationErrorViewer viewer = new ValidationErrorViewer();
                        viewer.SetTextFileError(result.LineIndexes, result.ErrorFormatLineIndexes, result.DuplicateLineIndexes);
                        viewer.ShowDialog();
                    }
                    else if (e.Result != null && e.Result is List <string> )
                    {
                        ValidationErrorViewer viewer = new ValidationErrorViewer();
                        viewer.SetErrorLines(e.Result as List <string>);
                        viewer.ShowDialog();
                    }
                }
                #endregion
            };

            _upload = new BackgroundWorker();
            _upload.WorkerReportsProgress = true;
            _upload.ProgressChanged      += new ProgressChangedEventHandler(_upload_ProgressChanged);
            //_upload.ProgressChanged += delegate(object sender, ProgressChangedEventArgs e)
            //{
            //    counter += double.Parse("" + e.ProgressPercentage);
            //    FISCA.Presentation.MotherForm.SetStatusBarMessage("成績上傳中…", (int)(counter * 100f / (double)_addScoreList.Count));
            //};
            _upload.DoWork += new DoWorkEventHandler(_upload_DoWork);

            //_upload.DoWork += delegate
            //{


            //#region Upload DoWork
            //Framework.MultiThreadWorker<JHSCETakeRecord> multi = new Framework.MultiThreadWorker<JHSCETakeRecord>();
            //multi.MaxThreads = 3;
            //multi.PackageSize = 500;
            //multi.PackageWorker += delegate(object sender, Framework.PackageWorkEventArgs<JHSCETakeRecord> e)
            //{
            //    JHSCETake.Delete(e.List);
            //};
            //multi.Run(_deleteScoreList);

            //Framework.MultiThreadWorker<JHSCETakeRecord> multi2 = new Framework.MultiThreadWorker<JHSCETakeRecord>();
            //multi2.MaxThreads = 3;
            //multi2.PackageSize = 500;
            //multi2.PackageWorker += delegate(object sender, Framework.PackageWorkEventArgs<JHSCETakeRecord> e)
            //{
            //    JHSCETake.Insert(e.List);
            //    lock (_upload)
            //    {
            //        _upload.ReportProgress(e.List.Count);
            //    }
            //};
            //multi2.Run(_addScoreList);
            //#endregion
            //};


            _upload.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_upload_RunWorkerCompleted);

            _warn = new BackgroundWorker();
            _warn.WorkerReportsProgress = true;
            _warn.DoWork += delegate(object sender, DoWorkEventArgs e)
            {
                _warn.ReportProgress(0, "產生警告訊息...");

                Dictionary <string, string> examDict = new Dictionary <string, string>();
                foreach (JHExamRecord exam in JHExam.SelectAll())
                {
                    if (!examDict.ContainsKey(exam.ID))
                    {
                        examDict.Add(exam.ID, exam.Name);
                    }
                }

                WarningForm form  = new WarningForm();
                int         count = 0;
                foreach (JHSCETakeRecord sce in _deleteScoreList)
                {
                    // 當成績資料是空值跳過
                    if (sce.Score.HasValue == false && sce.Effort.HasValue == false && string.IsNullOrEmpty(sce.Text))
                    {
                        continue;
                    }

                    count++;

                    JHStudentRecord student = JHStudent.SelectByID(sce.RefStudentID);
                    JHCourseRecord  course  = JHCourse.SelectByID(sce.RefCourseID);
                    string          exam    = (examDict.ContainsKey(sce.RefExamID) ? examDict[sce.RefExamID] : "<未知的試別>");

                    string s = "";
                    if (student.Class != null)
                    {
                        s += student.Class.Name;
                    }
                    if (!string.IsNullOrEmpty("" + student.SeatNo))
                    {
                        s += " " + student.SeatNo + "號";
                    }
                    if (!string.IsNullOrEmpty(student.StudentNumber))
                    {
                        s += " (" + student.StudentNumber + ")";
                    }
                    s += " " + student.Name;

                    form.Add(student.ID, s, string.Format("學生在「{0}」課程「{1}」中已有成績。", course.Name, exam));
                    _warn.ReportProgress((int)(count * 100 / _deleteScoreList.Count), "產生警告訊息...");
                }

                e.Result = form;
            };
            _warn.RunWorkerCompleted += delegate(object sender, RunWorkerCompletedEventArgs e)
            {
                WarningForm form = e.Result as WarningForm;

                if (form.ShowDialog() == DialogResult.OK)
                {
                    lblMessage.Text = "成績上傳中…";
                    FISCA.Presentation.MotherForm.SetStatusBarMessage("成績上傳中…", 0);
                    counter = 0;
                    _upload.RunWorkerAsync();
                }
                else
                {
                    this.DialogResult = DialogResult.Cancel;
                }
            };
            _warn.ProgressChanged += delegate(object sender, ProgressChangedEventArgs e)
            {
                FISCA.Presentation.MotherForm.SetStatusBarMessage("" + e.UserState, e.ProgressPercentage);
            };

            _files           = new List <FileInfo>();
            _addScoreList    = new List <JHSCETakeRecord>();
            _deleteScoreList = new List <JHSCETakeRecord>();
        }
Example #3
0
        private void Worker_DoWork(object sender, DoWorkEventArgs e)
        {
            double total = Students.Count;
            double count = 0;

            _worker.ReportProgress(0);

            List <string> studentIDs = Students.Select(x => x.ID).ToList();

            //List<string> student_ids = new List<string>();
            //foreach (JHStudentRecord item in Students)
            //    student_ids.Add(item.ID);

            #region 快取資料

            //獎勵
            // 1.依學生編號、開始日期、結束日期,取得學生獎勵紀錄
            // 2.依學生編號進行分群
            Dictionary <string, List <JHMeritRecord> > meritCache = new Dictionary <string, List <JHMeritRecord> >();
            foreach (JHMeritRecord record in JHMerit.Select(studentIDs, _config.StartDate, _config.EndDate, null, null, null, null))
            {
                if (!meritCache.ContainsKey(record.RefStudentID))
                {
                    meritCache.Add(record.RefStudentID, new List <JHMeritRecord>());
                }
                meritCache[record.RefStudentID].Add(record);
            }
            //Dictionary<string, List<JHMeritRecord>> meritCache = new Dictionary<string, List<JHMeritRecord>>();
            //foreach (JHMeritRecord record in JHMerit.SelectByStudentIDs(student_ids))
            //{
            //    if (record.OccurDate < _config.StartDate) continue;
            //    if (record.OccurDate > _config.EndDate) continue;

            //    if (!meritCache.ContainsKey(record.RefStudentID))
            //        meritCache.Add(record.RefStudentID, new List<JHMeritRecord>());
            //    meritCache[record.RefStudentID].Add(record);
            //}

            //懲戒
            // 1.依學生編號、開始日期、結束日期,取得學生懲戒紀錄
            // 2.依學生編號進行分群
            Dictionary <string, List <JHDemeritRecord> > demeritCache = new Dictionary <string, List <JHDemeritRecord> >();
            foreach (JHDemeritRecord record in JHDemerit.Select(studentIDs, _config.StartDate, _config.EndDate, null, null, null, null))
            {
                if (!demeritCache.ContainsKey(record.RefStudentID))
                {
                    demeritCache.Add(record.RefStudentID, new List <JHDemeritRecord>());
                }
                demeritCache[record.RefStudentID].Add(record);
            }

            //Dictionary<string, List<JHDemeritRecord>> demeritCache = new Dictionary<string, List<JHDemeritRecord>>();
            //foreach (JHDemeritRecord record in JHDemerit.SelectByStudentIDs(student_ids))
            //{
            //    if (record.OccurDate < _config.StartDate) continue;
            //    if (record.OccurDate > _config.EndDate) continue;

            //    if (!demeritCache.ContainsKey(record.RefStudentID))
            //        demeritCache.Add(record.RefStudentID, new List<JHDemeritRecord>());
            //    demeritCache[record.RefStudentID].Add(record);
            //}


            ////缺曠
            //// 1.依學生編號、開始日期、結束日期,取得學生缺曠紀錄
            //// 2.依學生編號進行分群
            //Dictionary<string, List<JHAttendanceRecord>> attendanceCache = new Dictionary<string, List<JHAttendanceRecord>>();
            //foreach (JHAttendanceRecord record in JHAttendance.Select(studentIDs, _config.StartDate, _config.EndDate, null, null, null))
            //{
            //    if (!attendanceCache.ContainsKey(record.RefStudentID))
            //        attendanceCache.Add(record.RefStudentID, new List<JHAttendanceRecord>());
            //    attendanceCache[record.RefStudentID].Add(record);
            //}
            //Dictionary<string, List<JHAttendanceRecord>> attendanceCache = new Dictionary<string, List<JHAttendanceRecord>>();
            //foreach (JHAttendanceRecord record in JHAttendance.SelectByStudentIDs(student_ids))
            //{
            //    if (record.OccurDate < _config.StartDate) continue;
            //    if (record.OccurDate > _config.EndDate) continue;

            //    if (!attendanceCache.ContainsKey(record.RefStudentID))
            //        attendanceCache.Add(record.RefStudentID, new List<JHAttendanceRecord>());
            //    attendanceCache[record.RefStudentID].Add(record);
            //}

            //List<string> studentIDs = new List<string>();
            //foreach (var stu in _config.Students)
            //    studentIDs.Add(stu.ID);

            //缺曠
            // 1.依學生編號、開始日期、結束日期,取得學生缺曠紀錄
            // 2.依學生編號進行分群
            Dictionary <string, List <JHAttendanceRecord> > attendanceCache = new Dictionary <string, List <JHAttendanceRecord> >();
            foreach (JHAttendanceRecord record in JHAttendance.Select(studentIDs, _config.StartDate, _config.EndDate, null, null, null))
            {
                if (!attendanceCache.ContainsKey(record.RefStudentID))
                {
                    attendanceCache.Add(record.RefStudentID, new List <JHAttendanceRecord>());
                }
                attendanceCache[record.RefStudentID].Add(record);
            }



            //修課紀錄
            // 1.依學生編號、學年度、學期,取得修課紀錄
            // 2.
            List <string> courseIDs = new List <string>();
            List <string> attendIDs = new List <string>();
            Dictionary <string, List <string> > scCache = new Dictionary <string, List <string> >();
            foreach (var attend in JHSCAttend.Select(studentIDs, null, null, "" + _config.SchoolYear, "" + _config.Semester))
            {
                attendIDs.Add(attend.ID);
                if (!scCache.ContainsKey(attend.RefStudentID))
                {
                    scCache.Add(attend.RefStudentID, new List <string>());
                }
                scCache[attend.RefStudentID].Add(attend.RefCourseID);
                if (!courseIDs.Contains(attend.RefCourseID))
                {
                    courseIDs.Add(attend.RefCourseID);
                }
            }

            //課程
            // 1.依課程編號取得課程紀錄
            // 2.略過不列入成績計算的課程
            JHCourse.RemoveByIDs(courseIDs);
            Dictionary <string, JHCourseRecord> courseCache = JHCourse.SelectByIDs(courseIDs).Where(x => x.CalculationFlag != "2").ToDictionary(x => x.ID);

            //試別資訊: 取得所有試別
            Dictionary <string, JHExamRecord> examCache = JHExam.SelectAll().ToDictionary(x => x.ID);

            // 取得社團ExamID
            List <string> NExamIDList = new List <string>();
            foreach (JHExamRecord rec in JHExam.SelectAll())
            {
                if (rec.Name.IndexOf("社團") > -1)
                {
                    NExamIDList.Add(rec.ID);
                }
            }

            //評量成績
            // 1.依修課記錄及所有試別取得評量成績
            // 2.依第1點的評量成績取得試別編號 (實際學生評量成績中的試別編號)
            // 3.依學生編號進行分群
            Dictionary <string, List <HC.JHSCETakeRecord> > sceScoreCache = new Dictionary <string, List <HC.JHSCETakeRecord> >();
            List <string> validExamIDs = new List <string>();

            //  檢查當有修課紀錄才取成績資料
            if (attendIDs.Count > 0 && examCache.Count > 0)
            {
                foreach (JHSCETakeRecord record in JHSCETake.Select(null, null, examCache.Keys, null, attendIDs))
                {
                    if (!NExamIDList.Contains(record.RefExamID))
                    {
                        if (!validExamIDs.Contains(record.RefExamID))
                        {
                            validExamIDs.Add(record.RefExamID);
                        }
                    }

                    if (!sceScoreCache.ContainsKey(record.RefStudentID))
                    {
                        sceScoreCache.Add(record.RefStudentID, new List <HC.JHSCETakeRecord>());
                    }
                    sceScoreCache[record.RefStudentID].Add(new HC.JHSCETakeRecord(record));
                }
            }

            //將『所有試別編號』與『實際學生評量成績中的試別編號』做交集,以取得使用管理的試別次序
            //假設『所有試別編號』為1,4,3,5
            //假設『實際學生評量成績中的試別編號』為3,4,1
            //交集後的結果為1,4,3
            validExamIDs = examCache.Keys.Intersect(validExamIDs).ToList();



            // 取得學生成績計算規則
            // 如果學生沒有計算規則一律用預設,預設進位方式取到小數點第2位
            ScoreCalculator defaultScoreCalculator = new ScoreCalculator(null);
            //key: ScoreCalcRuleID
            Dictionary <string, ScoreCalculator> calcCache = new Dictionary <string, ScoreCalculator>();
            //key: StudentID, val: ScoreCalcRuleID
            Dictionary <string, string> calcIDCache = new Dictionary <string, string>();

            List <string> scoreCalcRuleIDList = new List <string>();

            // 取得學生計算規則的ID,建立對照表
            // 如果學生身上有指定成績計算規則,就以學生身上成績計算規則為主
            // 如果學生身上沒有指定成績計算規則,就以學生所屬班級成績計算規則為主
            foreach (JHStudentRecord student in _config.Students)
            {
                string calcID = string.Empty;
                if (!string.IsNullOrEmpty(student.OverrideScoreCalcRuleID))
                {
                    calcID = student.OverrideScoreCalcRuleID;
                }
                else if (student.Class != null && !string.IsNullOrEmpty(student.Class.RefScoreCalcRuleID))
                {
                    calcID = student.Class.RefScoreCalcRuleID;
                }

                if (!string.IsNullOrEmpty(calcID))
                {
                    calcIDCache.Add(student.ID, calcID);
                }
            }
            // 取得計算規則建立成績進位器
            foreach (JHScoreCalcRuleRecord record in JHScoreCalcRule.SelectByIDs(calcIDCache.Values))
            {
                if (!calcCache.ContainsKey(record.ID))
                {
                    calcCache.Add(record.ID, new ScoreCalculator(record));
                }
            }


            ////修課紀錄
            //// 1.依學生編號、學年度、學期,取得修課紀錄
            //// 2.
            //List<string> courseIDs = new List<string>();
            //foreach (var attend in JHSCAttend.SelectByStudentIDs(studentIDs))
            //{
            //    if (!courseIDs.Contains(attend.RefCourseID))
            //        courseIDs.Add(attend.RefCourseID);
            //}

            //int schoolYear = _config.SchoolYear;
            //int semester = _config.Semester;
            //List<JHCourseRecord> courses = JHCourse.SelectByIDs(courseIDs);

            ////課程
            //Dictionary<string, JHCourseRecord> courseCache = new Dictionary<string, JHCourseRecord>();
            //foreach (JHCourseRecord record in JHCourse.SelectByIDs(courseIDs))
            //{
            //    if ("" + record.SchoolYear != "" + schoolYear) continue;
            //    if ("" + record.Semester != "" + semester) continue;
            //    if (record.CalculationFlag == "2") continue;
            //    //if (string.IsNullOrEmpty(record.Domain)) continue; //沒有填領域

            //    if (!courseCache.ContainsKey(record.ID))
            //        courseCache.Add(record.ID, record);
            //}

            ////試別資訊
            //Dictionary<string, JHExamRecord> examCache = new Dictionary<string, JHExamRecord>();
            //foreach (JHExamRecord exam in JHExam.SelectAll())
            //{
            //    if (!examCache.ContainsKey(exam.ID))
            //        examCache.Add(exam.ID, exam);
            //}
            //List<string> validExamIDs = new List<string>();

            ////評量成績
            //Dictionary<string, List<HC.JHSCETakeRecord>> sceScoreCache = new Dictionary<string, List<HC.JHSCETakeRecord>>();
            //foreach (JHSCETakeRecord record in JHSCETake.SelectByStudentIDs(student_ids))
            //{
            //    if (examCache.ContainsKey(record.RefExamID))
            //    {
            //        if (!validExamIDs.Contains(record.RefExamID))
            //            validExamIDs.Add(record.RefExamID);
            //    }
            //    else
            //        continue;

            //    if (!sceScoreCache.ContainsKey(record.RefStudentID))
            //        sceScoreCache.Add(record.RefStudentID, new List<HC.JHSCETakeRecord>());
            //    sceScoreCache[record.RefStudentID].Add(new HC.JHSCETakeRecord(record));
            //}
            //// TODO: 這邊的排序有可能再改
            //validExamIDs.Sort(delegate(string x, string y)
            //{
            //    int ix, iy;
            //    if (!int.TryParse(x, out ix))
            //        ix = int.MaxValue;
            //    if (!int.TryParse(y, out iy))
            //        iy = int.MaxValue;
            //    return ix.CompareTo(iy);
            //});

            //學期歷程
            //Dictionary<string, K12.Data.SemesterHistoryItem> historyCache = new Dictionary<string, K12.Data.SemesterHistoryItem>();
            //foreach (JHSemesterHistoryRecord record in JHSemesterHistory.SelectByStudentIDs(student_ids))
            //{
            //    foreach (K12.Data.SemesterHistoryItem item in record.SemesterHistoryItems)
            //    {
            //        if ("" + item.SchoolYear != K12.Data.School.DefaultSchoolYear) continue;
            //        if ("" + item.Semester != K12.Data.School.DefaultSemester) continue;

            //        if (!historyCache.ContainsKey(record.RefStudentID))
            //            historyCache.Add(record.RefStudentID, item);
            //    }
            //}
            #endregion

            #region 判斷領域是否需要展開
            //判斷領域是否展開對照表
            //Key:領域名稱
            //Value:false=展開,true=不展開
            //展開: 詳列該領域下所有科目成績
            //不展開: 只列該領域成績
            Dictionary <string, bool>           domains  = new Dictionary <string, bool>();
            Dictionary <string, List <string> > subjects = new Dictionary <string, List <string> >();

            List <JHCourseRecord> courseList = new List <JHCourseRecord>(courseCache.Values);
            courseList.Sort(delegate(JHCourseRecord x, JHCourseRecord y)
            {
                return(JHSchool.Evaluation.Subject.CompareSubjectOrdinal(x.Subject, y.Subject));
                //List<string> list = new List<string>(new string[] { "國語文", "國文", "英文", "英語", "數學", "歷史", "地理", "公民", "理化", "生物" });
                //int ix = list.IndexOf(x.Subject);
                //int iy = list.IndexOf(y.Subject);

                //if (ix >= 0 && iy >= 0)
                //    return ix.CompareTo(iy);
                //else if (ix >= 0)
                //    return -1;
                //else if (iy >= 0)
                //    return 1;
                //else
                //    return x.Subject.CompareTo(y.Subject);
            });

            DomainSubjectSetup domainSubjectSetup = _config.DomainSubjectSetup;
            //使用者設定"只列印領域"
            if (domainSubjectSetup == DomainSubjectSetup.Domain)
            {
                //預設從領域資料管理來的領域名稱皆不展開
                foreach (var domain in JHSchool.Evaluation.Subject.Domains)
                {
                    domains.Add(domain, DomainSubjectExpand.展開);
                }
                if (domains.ContainsKey("語文"))
                {
                    domains["語文"] = DomainSubjectExpand.展開;
                }

                //彈性課程一定展開
                if (!domains.ContainsKey(""))
                {
                    domains.Add("", DomainSubjectExpand.展開);
                }
                //if (!domains.ContainsKey("彈性課程")) domains.Add("彈性課程", false);
            }
            //使用者設定"只列印科目"
            else if (domainSubjectSetup == DomainSubjectSetup.Subject)
            {
                //預設從領域資料管理來的領域名稱皆展開
                foreach (var domain in JHSchool.Evaluation.Subject.Domains)
                {
                    domains.Add(domain, DomainSubjectExpand.展開);
                }
                //彈性課程一定展開
                if (!domains.ContainsKey(""))
                {
                    domains.Add("", DomainSubjectExpand.展開);
                }
                //if (!domains.ContainsKey("彈性課程")) domains.Add("彈性課程", false);
            }
            else
            {
                throw new Exception("請重新儲存一次列印設定");
            }

            //foreach (var domain in JHSchool.Evaluation.Subject.Domains)
            //    subjects.Add(domain, new List<string>());

            //if (!subjects.ContainsKey("")) subjects.Add("", new List<string>());
            //if (!subjects.ContainsKey("彈性課程")) subjects.Add("彈性課程", new List<string>());

            //foreach (var course in courseList)
            //{
            //    if (!subjects.ContainsKey(course.Domain))
            //        subjects.Add(course.Domain, new List<string>());
            //    if (!subjects[course.Domain].Contains(course.Subject))
            //        subjects[course.Domain].Add(course.Subject);
            //}

            //_config.SetPrintDomains(domains);
            //_config.SetPrintSubjects(subjects);
            _config.PrintDomains = domains;
            #endregion

            #region 建立節次對照
            Dictionary <string, string> periodMapping = JHPeriodMapping.SelectAll().ToDictionary(x => x.Name, y => y.Type);
            //Dictionary<string, string> periodMapping = new Dictionary<string, string>();
            //foreach (JHPeriodMappingInfo info in JHPeriodMapping.SelectAll())
            //{
            //    if (!periodMapping.ContainsKey(info.Name))
            //        periodMapping.Add(info.Name, info.Type);
            //}
            #endregion

            #region 假別列表
            List <string> absenceList = JHAbsenceMapping.SelectAll().Select(x => x.Name).ToList();
            //List<string> absenceList = new List<string>();
            //foreach (JHAbsenceMappingInfo info in JHAbsenceMapping.SelectAll())
            //    absenceList.Add(info.Name);
            #endregion

            #region 依評量試別重新劃分範本
            int             rowCount        = 0;
            DocumentBuilder templateBuilder = new DocumentBuilder(_template);
            templateBuilder.MoveToMergeField("各次評量");
            Font   font       = templateBuilder.Font;
            Cell   examsCell  = templateBuilder.CurrentParagraph.ParentNode as Cell;
            Table  table      = examsCell.ParentRow.ParentTable;
            double width      = examsCell.CellFormat.Width;
            double examWidth  = width / (double)validExamIDs.Count;
            double scoreWidth = width / (double)validExamIDs.Count / 3.0;

            //計算有幾個 Score Row
            foreach (Row row in table.Rows)
            {
                if (row.Cells.Count > 3)
                {
                    rowCount++;
                }
            }

            #region Header Cell
            //建立評量欄位對照表
            Dictionary <string, int> columnMapping = new Dictionary <string, int>();
            int columnShift = 3;
            int columnIndex = 0;

            table.Rows[0].LastCell.Remove();
            table.Rows[1].LastCell.Remove();
            foreach (string examID in validExamIDs)
            {
                columnMapping.Add(examID, columnIndex + columnShift);

                Cell topHeaderCell = new Cell(_template);
                WordHelper.Write(topHeaderCell, font, examCache[examID].Name);
                table.Rows[0].Cells.Add(topHeaderCell);

                Cell subHeaderCell1 = new Cell(_template);
                WordHelper.Write(subHeaderCell1, font, "定期", "評量");
                table.Rows[1].Cells.Add(subHeaderCell1);
                columnIndex++;

                Cell subHeaderCell2 = new Cell(_template);
                WordHelper.Write(subHeaderCell2, font, "平時", "評量");
                table.Rows[1].Cells.Add(subHeaderCell2);
                columnIndex++;

                Cell subHeaderCell3 = new Cell(_template);
                WordHelper.Write(subHeaderCell3, font, "總成績");
                table.Rows[1].Cells.Add(subHeaderCell3);
                columnIndex++;

                topHeaderCell.CellFormat.Width  = examWidth;
                subHeaderCell1.CellFormat.Width = scoreWidth;
                subHeaderCell2.CellFormat.Width = scoreWidth;
                subHeaderCell3.CellFormat.Width = scoreWidth;

                topHeaderCell.CellFormat.VerticalAlignment  = CellVerticalAlignment.Center;
                subHeaderCell1.CellFormat.VerticalAlignment = CellVerticalAlignment.Center;
                subHeaderCell2.CellFormat.VerticalAlignment = CellVerticalAlignment.Center;
                subHeaderCell3.CellFormat.VerticalAlignment = CellVerticalAlignment.Center;
            }
            WordHelper.MergeVerticalCell(table.Rows[0].Cells[1], 2);
            #endregion

            #region Content Cell
            int shift = 2; //Header has 2 rows
            for (int i = 0; i < rowCount; i++)
            {
                table.Rows[i + shift].LastCell.Remove();

                for (int j = 0; j < validExamIDs.Count * 3; j++)
                {
                    Cell contentCell = new Cell(_template);
                    contentCell.CellFormat.Width             = scoreWidth;
                    contentCell.CellFormat.VerticalAlignment = CellVerticalAlignment.Center;

                    table.Rows[i + shift].Cells.Add(contentCell);
                }
            }
            #endregion

            #endregion

            #region 依節權數設定,在畫面上顯示
            string pcDisplay = string.Empty;
            if (_config.PrintPeriod && _config.PrintCredit)
            {
                pcDisplay = "節/權數";
            }
            else if (_config.PrintPeriod)
            {
                pcDisplay = "節數";
            }
            else if (_config.PrintCredit)
            {
                pcDisplay = "權數";
            }

            templateBuilder.MoveToMergeField("節權數");
            templateBuilder.Write(pcDisplay);
            #endregion

            //#region 取得學生成績計算規則

            //ScoreCalculator defaultScoreCalculator = new ScoreCalculator(null);

            ////key: ScoreCalcRuleID
            //Dictionary<string, ScoreCalculator> calcCache = new Dictionary<string, ScoreCalculator>();
            ////key: StudentID, val: ScoreCalcRuleID
            //Dictionary<string, string> calcIDCache = new Dictionary<string, string>();

            //List<string> scoreCalcRuleIDList = new List<string>();

            //foreach (JHStudentRecord student in _config.Students)
            //{
            //    string calcID = string.Empty;
            //    if (!string.IsNullOrEmpty(student.OverrideScoreCalcRuleID))
            //        calcID = student.OverrideScoreCalcRuleID;
            //    else if (student.Class != null && !string.IsNullOrEmpty(student.Class.RefScoreCalcRuleID))
            //        calcID = student.Class.RefScoreCalcRuleID;

            //    if (!string.IsNullOrEmpty(calcID))
            //        calcIDCache.Add(student.ID, calcID);
            //}
            //foreach (JHScoreCalcRuleRecord record in JHScoreCalcRule.SelectByIDs(calcIDCache.Values))
            //{
            //    if (!calcCache.ContainsKey(record.ID))
            //        calcCache.Add(record.ID, new ScoreCalculator(record));
            //}
            //#endregion

            // 取得學期歷程
            Config._StudSemesterHistoryItemDict.Clear();

            List <JHSemesterHistoryRecord> semHisRec = JHSemesterHistory.SelectByStudents(Students);
            // 當畫面學期歷程內的學年度學期與畫面上設定相同,加入
            foreach (JHSemesterHistoryRecord rec in semHisRec)
            {
                foreach (K12.Data.SemesterHistoryItem shi in rec.SemesterHistoryItems)
                {
                    if (shi.SchoolYear == _config.SchoolYear && shi.Semester == _config.Semester)
                    {
                        if (!Config._StudSemesterHistoryItemDict.ContainsKey(shi.RefStudentID))
                        {
                            Config._StudSemesterHistoryItemDict.Add(shi.RefStudentID, shi);
                        }
                    }
                }
            }

            // 取得學生服務學習時數
            Config._SRDict.Clear();
            List <string> sidList = (from data in Students select data.ID).ToList();
            Config._SRDict = Utility.GetServiceLearningDetail(sidList, _config.SchoolYear, _config.Semester);

            #region 產生
            foreach (JHStudentRecord student in Students)
            {
                count++;

                Document        each    = (Document)_template.Clone(true);
                DocumentBuilder builder = new DocumentBuilder(each);

                #region 學生基本資料
                StudentBasicInfo basicInfo = new StudentBasicInfo(builder);
                basicInfo.SetStudent(student);
                #endregion

                //#region 班導師
                //builder.MoveToMergeField("班導師");
                //if (historyCache.ContainsKey(student.ID))
                //    builder.Write(historyCache[student.ID].Teacher);
                //else
                //    builder.Write(string.Empty);
                //#endregion

                #region 各評量成績
                List <HC.JHSCETakeRecord> sceScoreList = null;
                if (sceScoreCache.ContainsKey(student.ID))
                {
                    sceScoreList = sceScoreCache[student.ID];
                }
                else
                {
                    sceScoreList = new List <HC.JHSCETakeRecord>();
                }

                ScoreCalculator studentCalculator = defaultScoreCalculator;
                if (calcIDCache.ContainsKey(student.ID) && calcCache.ContainsKey(calcIDCache[student.ID]))
                {
                    studentCalculator = calcCache[calcIDCache[student.ID]];
                }

                try {
                    StudentExamScore examScore = new StudentExamScore(builder, _config, courseCache);
                    if (scCache.ContainsKey(student.ID))
                    {
                        examScore.SetSubjects(scCache[student.ID]);
                    }
                    examScore.SetColumnMap(columnMapping);
                    examScore.SetCalculator(studentCalculator);
                    examScore.SetData(sceScoreList);
                } catch (Exception erro)
                {
                    e.Cancel = true;
                }

                #endregion

                #region 缺曠獎懲
                List <JHMeritRecord>      meritList      = null;
                List <JHDemeritRecord>    demeritList    = null;
                List <JHAttendanceRecord> attendanceList = null;

                meritList      = (meritCache.ContainsKey(student.ID)) ? meritCache[student.ID] : new List <JHMeritRecord>();
                demeritList    = (demeritCache.ContainsKey(student.ID)) ? demeritCache[student.ID] : new List <JHDemeritRecord>();
                attendanceList = (attendanceCache.ContainsKey(student.ID)) ? attendanceCache[student.ID] : new List <JHAttendanceRecord>();

                StudentMoralScore moral = new StudentMoralScore(builder, _config, periodMapping, absenceList);
                moral.SetData(meritList, demeritList, attendanceList);
                #endregion

                foreach (Section sec in each.Sections)
                {
                    _doc.Sections.Add(_doc.ImportNode(sec, true));
                }

                //回報進度
                _worker.ReportProgress((int)(count * 100.0 / total));
            }

            #region 全域 MergeField
            List <string> globalFieldName  = new List <string>();
            List <object> globalFieldValue = new List <object>();

            globalFieldName.Add("學校名稱");
            globalFieldValue.Add(K12.Data.School.ChineseName);

            globalFieldName.Add("學年度");
            //globalFieldValue.Add(K12.Data.School.DefaultSchoolYear);
            globalFieldValue.Add(_config.SchoolYear.ToString());

            globalFieldName.Add("學期");
            //globalFieldValue.Add(K12.Data.School.DefaultSemester);
            globalFieldValue.Add(_config.Semester.ToString());

            globalFieldName.Add("統計期間");
            globalFieldValue.Add(_config.StartDate.ToShortDateString() + " ~ " + _config.EndDate.ToShortDateString());

            globalFieldName.Add("列印日期");
            globalFieldValue.Add(DateConvert.CDate(DateTime.Now.ToString("yyyy/MM/dd")) + " " + DateTime.Now.ToString("HH:mm:ss"));

            string chancellor, eduDirector, stuDirector;
            chancellor = eduDirector = stuDirector = string.Empty;

            XmlElement schoolInfo         = K12.Data.School.Configuration["學校資訊"].PreviousData;
            XmlElement chancellorElement  = (XmlElement)schoolInfo.SelectSingleNode("ChancellorChineseName");
            XmlElement eduDirectorElement = (XmlElement)schoolInfo.SelectSingleNode("EduDirectorName");
            XmlElement stuDirectorElement = (XmlElement)schoolInfo.SelectSingleNode("StuDirectorName");

            if (chancellorElement != null)
            {
                chancellor = chancellorElement.InnerText;
            }
            if (eduDirectorElement != null)
            {
                eduDirector = eduDirectorElement.InnerText;
            }
            if (stuDirectorElement != null)
            {
                stuDirector = stuDirectorElement.InnerText;
            }

            globalFieldName.Add("校長");
            globalFieldValue.Add(chancellor);

            globalFieldName.Add("教務主任");
            globalFieldValue.Add(eduDirector);

            globalFieldName.Add("學務主任");
            globalFieldValue.Add(stuDirector);

            _doc.MailMerge.Execute(globalFieldName.ToArray(), globalFieldValue.ToArray());
            #endregion

            #endregion
        }