Example #1
0
        public unsafe void SetRenderer(Renderer renderer, uint numParams, Parameter[] parameters)
        {
            if (disposed)
            {
                throw new ObjectDisposedException("Library", "Cannot access a disposed object.");
            }

            if (renderer == null)
            {
                throw new ArgumentNullException("renderer");
            }

            if (parameters == null)
            {
                throw new ArgumentNullException("parameters");
            }

            ParameterRec[] paramRecs = new ParameterRec[parameters.Length];            //parameters.Select(x => x.Record).ToArray();
            for (int i = 0; i < paramRecs.Length; i++)
                paramRecs[i] = parameters[i].Record;

            fixed(void *ptr = paramRecs)
            {
                Error err = FT.FT_Set_Renderer(Reference, renderer.Reference, numParams, (IntPtr)ptr);

                if (err != Error.Ok)
                {
                    throw new FreeTypeException(err);
                }
            }
        }
        private void btnExport_Click(object sender, EventArgs e)
        {
            btnExport.Enabled = false;
            if (!bgWorker.IsBusy)
            {
                ParameterRec data = new ParameterRec();

                data.ClassIDs = string.Join(",", listClassID);

                bgWorker.RunWorkerAsync(data);
            }
        }
        private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            ParameterRec data = (ParameterRec)e.Argument;

            Document doc = new Document();

            doc.RemoveAllChildren();
            int progress = 0;
            // 取得學年度學期班級學生領域成績
            DataTable dt = GetClassStudentDomainScore(data);

            bgWorker.ReportProgress(progress += 10);
            // 資料解析
            ParseData(dt);
            bgWorker.ReportProgress(progress += 10);
            // 資料填寫
            DataTable table = FillMergeFiledData(data);

            bgWorker.ReportProgress(progress += 10);

            int p = 0;

            if (table.Rows.Count > 0)
            {
                p = 70 / table.Rows.Count;
            }
            foreach (DataRow row in table.Rows)
            {
                Document eachDoc = new Document();
                eachDoc.Sections.Clear();
                Section section = (Section)eachDoc.ImportNode(docTemplate.FirstSection, true);
                eachDoc.AppendChild(section);
                eachDoc.MailMerge.CleanupOptions = MailMergeCleanupOptions.RemoveEmptyParagraphs;
                eachDoc.MailMerge.Execute(row);

                doc.Sections.Add(doc.ImportNode(eachDoc.Sections[0], true));
                bgWorker.ReportProgress(progress += p);
            }

            string path = $"{Application.StartupPath}\\Reports\\班級成績預警通知單.docx";
            int    i    = 1;

            while (File.Exists(path))
            {
                string docName = Path.GetFileNameWithoutExtension(path);
                string newPath = $"{Path.GetDirectoryName(path)}\\成績預警通知單{i++}{Path.GetExtension(path)}";

                path = newPath;
            }

            doc.Save(path, SaveFormat.Docx);
            e.Result = path;
        }
        private void btnExport_Click(object sender, EventArgs e)
        {
            if (!bgWorker.IsBusy)
            {
                ParameterRec data = new ParameterRec();
                data.SchoolYear = cbxSchoolYear.SelectedItem.ToString();
                data.Semester   = cbxSemester.SelectedItem.ToString();
                data.Range      = cbxRange.SelectedItem.ToString();

                bgWorker.RunWorkerAsync(data);
            }
        }
        private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            ParameterRec data     = (ParameterRec)e.Argument;
            int          progress = 0;

            // 取得各年級領域成績
            DataTable dt = GetDomainScore(data.SchoolYear, data.Semester);

            bgWorker.ReportProgress(progress += 15);

            // 資料解析
            ParseData(dt, data.Range);
            bgWorker.ReportProgress(progress += 15);

            if (listDomainFromData.Count > 0)
            {
                Workbook wb = FillWorkBookData(data);
                bgWorker.ReportProgress(progress += 25);

                string path = $"{Application.StartupPath}\\Reports\\領域不及格人數統計表.xlsx";
                int    i    = 1;
                while (File.Exists(path))
                {
                    string docName = Path.GetFileNameWithoutExtension(path);
                    string newPath = $"{Path.GetDirectoryName(path)}\\領域不及格人數統計表{i++}{Path.GetExtension(path)}";
                    path = newPath;
                }

                wb.Save(path, SaveFormat.Xlsx);
                bgWorker.ReportProgress(100);
                e.Result = path;
            }
            else
            {
                bgWorker.ReportProgress(100);
                e.Result = "";
            }
        }
        private DataTable FillMergeFiledData(ParameterRec data)
        {
            DataTable dt = CreateMergeFiledTable();

            foreach (string classID in dicClassNameByID.Keys)
            {
                DataRow row = dt.NewRow();

                row["school_name"] = School.ChineseName;
                row["class_name"]  = dicClassNameByID[classID];

                // 班級領域清單
                List <string> listDomain = dicDomainNameByClassID[classID];
                // 根據領域對照表做排序
                listDomain.Sort(delegate(string a, string b)
                {
                    int aIndex = listDomainName.FindIndex(domain => domain == a);
                    int bIndex = listDomainName.FindIndex(domain => domain == b);

                    if (aIndex > bIndex)
                    {
                        return(1);
                    }
                    else if (aIndex == bIndex)
                    {
                        return(0);
                    }
                    else
                    {
                        return(-1);
                    }
                });
                // 目前樣板最多支援8個領域 多的不顯示
                if (listDomain.Count > 8)
                {
                    listDomain.RemoveRange(8, listDomain.Count - 8);
                }

                // 領域
                {
                    int d = 1;
                    foreach (string domain in listDomain)
                    {
                        row[$"domain_{d}"] = domain;

                        d++;
                    }
                }

                // 學生
                Dictionary <string, Dictionary <string, ScoreRec> > dicStuDomainScore = dicClassStuDomainScore[classID];
                int s = 1;

                foreach (string stuID in dicStuDomainScore.Keys)
                {
                    StudentRec stuRec = dicStuRecByID[stuID];
                    row[$"seat_no_{s}"] = stuRec.SeatNo;
                    row[$"name_{s}"]    = stuRec.Name;

                    int     d          = 1;
                    int     sc         = 0;
                    int     passCount  = 0;
                    decimal totalPower = 0;
                    decimal totalScore = 0;
                    // 領域成績
                    foreach (string domain in listDomain)
                    {
                        if (dicStuDomainScore[stuID].ContainsKey(domain))
                        {
                            string score       = dicStuDomainScore[stuID][domain].Score;
                            string originScore = dicStuDomainScore[stuID][domain].OriginScore;
                            string power       = dicStuDomainScore[stuID][domain].Power;
                            row[$"stu_{s}_domain_{d}"] = score == originScore ? score : $"{score}";


                            //totalScore += FloatParser(score) * FloatParser(power);
                            //totalPower += FloatParser(power);

                            // 最後平均使用算術平均不使用加權平均
                            totalScore += DecimalParser(score);
                            totalPower += 1;

                            if (DecimalParser(score) >= 60)
                            {
                                passCount++;
                            }
                            sc++;
                        }
                        d++;
                    }



                    if (sc > 0)
                    {
                        // 沒有權重就不幫你算
                        if (totalPower > 0)
                        {
                            // 成績計算規則
                            ScoreCalculator defaultScoreCalculator = new ScoreCalculator(null);
                            ScoreCalculator studentCalculator      = defaultScoreCalculator;
                            if (calcIDCache.ContainsKey(stuID) && calcCache.ContainsKey(calcIDCache[stuID]))
                            {
                                studentCalculator = calcCache[calcIDCache[stuID]];
                            }

                            //// 平均成績
                            //row[$"stu_{s}_avg_score"] = studentCalculator.ParseGraduateScore(totalScore / totalPower);   // Math.Round(totalScore / totalPower, 2);
                            List <decimal> scoreList = new List <decimal>();
                            if (StudentSemsDomainScoreSumDict.ContainsKey(stuID) && StudentSemsCreditSumDict.ContainsKey(stuID))
                            {
                                foreach (string sms in StudentSemsDomainScoreSumDict[stuID].Keys)
                                {
                                    // 各學期做加權平均
                                    if (StudentSemsCreditSumDict[stuID].ContainsKey(sms))
                                    {
                                        decimal ss = StudentSemsDomainScoreSumDict[stuID][sms];
                                        decimal cc = StudentSemsCreditSumDict[stuID][sms];
                                        if (cc > 0)
                                        {
                                            // 使用領域計算規則進位
                                            scoreList.Add(studentCalculator.ParseDomainScore(ss / cc));
                                        }
                                    }
                                }
                            }

                            // 最後再做算術平均在四捨五入
                            row[$"stu_{s}_avg_score"] = studentCalculator.ParseGraduateScore(scoreList.Average());   // Math.Round(totalScore / totalPower, 2);
                        }
                        // 領域及格數
                        row[$"stu_{s}_pass_count"] = passCount;
                    }
                    s++;
                }

                dt.Rows.Add(row);
            }

            return(dt);
        }
        private DataTable GetClassStudentDomainScore(ParameterRec data)
        {
            //            string sql = string.Format(@"
            //WITH data_row AS (
            //    SELECT
            //        {0}::INT AS school_year
            //        , {1}::INT AS semester
            //), target_student AS(
            //	SELECT
            //		*
            //	FROM
            //		student
            //	WHERE
            //		ref_class_id IN ({2})
            //        AND status IN(1, 2)
            //)
            //SELECT
            //    student.id
            //    , student.name
            //    , student.seat_no
            //    , class.id AS class_id
            //    , class.class_name
            //	, sems_subj_score_ext.semester
            //	, sems_subj_score_ext.school_year
            //	, array_to_string(xpath('/Domain/@原始成績', subj_score_ele), '')::text AS 原始成績
            //	, array_to_string(xpath('/Domain/@成績', subj_score_ele), '')::text AS 成績
            //	, array_to_string(xpath('/Domain/@領域', subj_score_ele), '')::text AS 領域
            //    , array_to_string(xpath('/Domain/@權數', subj_score_ele), '')::text AS 權數
            //FROM (
            //		SELECT
            //			sems_subj_score.*
            //			, unnest(xpath('/root/Domains/Domain', xmlparse(content '<root>' || score_info || '</root>'))) as subj_score_ele
            //		FROM
            //			sems_subj_score
            //			INNER JOIN target_student
            //				ON target_student.id = sems_subj_score.ref_student_id
            //	) as sems_subj_score_ext
            //    LEFT OUTER JOIN student
            //        ON student.id = sems_subj_score_ext.ref_student_id
            //    LEFT OUTER JOIN class
            //        ON class.id = student.ref_class_id
            //    INNER JOIN data_row
            //      ON data_row.school_year = sems_subj_score_ext.school_year
            //      AND data_row.semester = sems_subj_score_ext.semester
            //ORDER BY
            //	sems_subj_score_ext.grade_year
            //    , class.display_order
            //    , student.seat_no
            //                ", data.SchoolYear, data.Semester, data.ClassIDs);

            //return qh.Select(sql);

            // 取得班級學生含研修
            QueryHelper qh1 = new QueryHelper();
            string      qry = @"SELECT student.id,student.name,student.seat_no,class.id AS class_id,class.class_name FROM student INNER JOIN class on student.ref_class_id = class.id WHERE student.status IN(1,2) AND class.id IN(" + data.ClassIDs + @") ORDER BY class.grade_year,class.display_order,class.class_name,student.seat_no";

            DataTable dtStudent = qh1.Select(qry);

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

            foreach (DataRow dr in dtStudent.Rows)
            {
                StudentIDList.Add(dr["id"].ToString());
            }

            // 取得學生學期成績,即時計算使用
            List <JHSemesterScoreRecord> StudentSemesterScoreList = JHSemesterScore.SelectByStudentIDs(StudentIDList);

            // 建立成績資料索引
            Dictionary <string, List <JHSemesterScoreRecord> > StudentSemesterScoreDict = new Dictionary <string, List <JHSemesterScoreRecord> >();

            foreach (JHSemesterScoreRecord rec in StudentSemesterScoreList)
            {
                if (!StudentSemesterScoreDict.ContainsKey(rec.RefStudentID))
                {
                    StudentSemesterScoreDict.Add(rec.RefStudentID, new List <JHSemesterScoreRecord>());
                }

                StudentSemesterScoreDict[rec.RefStudentID].Add(rec);
            }


            DataTable dt = new DataTable();

            dt.Columns.Add("id");
            dt.Columns.Add("name");
            dt.Columns.Add("seat_no");
            dt.Columns.Add("class_id");
            dt.Columns.Add("class_name");
            dt.Columns.Add("semester");
            dt.Columns.Add("school_year");
            dt.Columns.Add("原始成績");
            dt.Columns.Add("成績");
            dt.Columns.Add("領域");
            dt.Columns.Add("權數");

            // 各領域學期成績
            Dictionary <string, List <decimal> > domainnScoreDict = new Dictionary <string, List <decimal> >();



            // 各領域學期成績原始
            Dictionary <string, List <decimal> > domainnScoreOrignDict = new Dictionary <string, List <decimal> >();

            // 各領域成績(算術平均)
            Dictionary <string, decimal> domainnScoreAvgDict = new Dictionary <string, decimal>();
            // 各領域成績(算術平均)(原始)
            Dictionary <string, decimal> domainnScoreAvgOrignDict = new Dictionary <string, decimal>();

            // 各領域學分
            Dictionary <string, List <decimal> > domainCreditDict = new Dictionary <string, List <decimal> >();

            // 各領域學分平均
            Dictionary <string, decimal> domainAvgCreditDict = new Dictionary <string, decimal>();

            #region 取得學生成績計算規則
            ScoreCalculator defaultScoreCalculator = new ScoreCalculator(null);

            //key: ScoreCalcRuleID
            calcCache.Clear();

            //key: StudentID, val: ScoreCalcRuleID
            calcIDCache.Clear();

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

            List <StudentRecord> StudentRecList = K12.Data.Student.SelectByIDs(StudentIDList);
            foreach (StudentRecord student in StudentRecList)
            {
                //calcCache.Add(student.ID, new ScoreCalculator(student.ScoreCalcRule));
                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

            // 計算畢業成績使用
            StudentSemsDomainScoreSumDict.Clear();
            StudentSemsCreditSumDict.Clear();

            // 開始填資料
            foreach (DataRow dr in dtStudent.Rows)
            {
                string sid = dr["id"].ToString();

                //DataRow newRow = dt.NewRow();
                //newRow["id"] = sid;
                //newRow["name"] = dr["name"].ToString();
                //newRow["seat_no"] = dr["seat_no"].ToString();
                //newRow["class_id"] = dr["class_id"].ToString();
                //newRow["class_name"] = dr["class_name"].ToString();
                //newRow["semester"] = "";
                //newRow["school_year"] = "";

                //newRow["原始成績"] = "0";
                //newRow["成績"] = "0";
                //newRow["領域"] = "0";
                //newRow["權數"] = "0";

                // 即時計算領域成績
                if (StudentSemesterScoreDict.ContainsKey(sid))
                {
                    // 成績計算規則
                    ScoreCalculator studentCalculator = defaultScoreCalculator;
                    if (calcIDCache.ContainsKey(sid) && calcCache.ContainsKey(calcIDCache[sid]))
                    {
                        studentCalculator = calcCache[calcIDCache[sid]];
                    }

                    domainnScoreDict.Clear();

                    domainnScoreOrignDict.Clear();
                    domainnScoreAvgDict.Clear();
                    domainnScoreAvgOrignDict.Clear();
                    domainCreditDict.Clear();

                    if (!StudentSemsDomainScoreSumDict.ContainsKey(sid))
                    {
                        StudentSemsDomainScoreSumDict.Add(sid, new Dictionary <string, decimal>());
                    }

                    if (!StudentSemsCreditSumDict.ContainsKey(sid))
                    {
                        StudentSemsCreditSumDict.Add(sid, new Dictionary <string, decimal>());
                    }

                    // 整理各學期領域成績
                    foreach (JHSemesterScoreRecord rec in StudentSemesterScoreDict[sid])
                    {
                        string key = rec.SchoolYear + "_" + rec.Semester;

                        if (!StudentSemsDomainScoreSumDict[sid].ContainsKey(key))
                        {
                            StudentSemsDomainScoreSumDict[sid].Add(key, 0);
                        }

                        if (!StudentSemsCreditSumDict[sid].ContainsKey(key))
                        {
                            StudentSemsCreditSumDict[sid].Add(key, 0);
                        }

                        // 讀取成績
                        foreach (string dName in rec.Domains.Keys)
                        {
                            // 加入領域成績
                            if (rec.Domains[dName].Score.HasValue)
                            {
                                if (!domainnScoreDict.ContainsKey(dName))
                                {
                                    domainnScoreDict.Add(dName, new List <decimal>());
                                }
                                domainnScoreDict[dName].Add(rec.Domains[dName].Score.Value);

                                if (rec.Domains[dName].Credit.HasValue)
                                {
                                    StudentSemsDomainScoreSumDict[sid][key] += (rec.Domains[dName].Score.Value * rec.Domains[dName].Credit.Value);
                                }
                            }

                            // 加入領域原始
                            if (rec.Domains[dName].ScoreMakeup.HasValue)
                            {
                                if (!domainnScoreOrignDict.ContainsKey(dName))
                                {
                                    domainnScoreOrignDict.Add(dName, new List <decimal>());
                                }
                                domainnScoreOrignDict[dName].Add(rec.Domains[dName].ScoreMakeup.Value);
                            }

                            // 加入權數
                            if (rec.Domains[dName].Credit.HasValue)
                            {
                                if (!domainCreditDict.ContainsKey(dName))
                                {
                                    domainCreditDict.Add(dName, new List <decimal>());
                                }

                                domainCreditDict[dName].Add(rec.Domains[dName].Credit.Value);

                                StudentSemsCreditSumDict[sid][key] += rec.Domains[dName].Credit.Value;
                            }
                        }
                    }

                    // 計算成績
                    foreach (string dName in domainnScoreDict.Keys)
                    {
                        // 使用畢業成績計算規則四捨五入方式,即時計算平均
                        decimal avgScore = studentCalculator.ParseGraduateScore(domainnScoreDict[dName].Average());
                        if (!domainnScoreAvgDict.ContainsKey(dName))
                        {
                            domainnScoreAvgDict.Add(dName, avgScore);
                        }
                    }

                    foreach (string dName in domainnScoreOrignDict.Keys)
                    {
                        // 使用畢業成績計算規則四捨五入方式,即時計算平均(原始)
                        decimal avgScore = studentCalculator.ParseGraduateScore(domainnScoreOrignDict[dName].Average());
                        if (!domainnScoreAvgOrignDict.ContainsKey(dName))
                        {
                            domainnScoreAvgOrignDict.Add(dName, avgScore);
                        }
                    }

                    // 處理學分

                    foreach (string dName in domainCreditDict.Keys)
                    {
                        // 使用畢業成績計算規則四捨五入方式,即時計算平均(原始)
                        decimal avgScore = studentCalculator.ParseGraduateScore(domainCreditDict[dName].Average());
                        if (!domainAvgCreditDict.ContainsKey(dName))
                        {
                            domainAvgCreditDict.Add(dName, avgScore);
                        }
                    }

                    foreach (string domainName in domainnScoreAvgDict.Keys)
                    {
                        // 填資料
                        DataRow newRow = dt.NewRow();
                        newRow["id"]          = sid;
                        newRow["name"]        = dr["name"].ToString();
                        newRow["seat_no"]     = dr["seat_no"].ToString();
                        newRow["class_id"]    = dr["class_id"].ToString();
                        newRow["class_name"]  = dr["class_name"].ToString();
                        newRow["semester"]    = "";
                        newRow["school_year"] = "";

                        newRow["原始成績"] = "";
                        if (domainnScoreAvgOrignDict.ContainsKey(domainName))
                        {
                            newRow["原始成績"] = domainnScoreAvgOrignDict[domainName];
                        }

                        newRow["成績"] = domainnScoreAvgDict[domainName];
                        newRow["領域"] = domainName;
                        newRow["權數"] = "";
                        if (domainAvgCreditDict.ContainsKey(domainName))
                        {
                            newRow["權數"] = domainAvgCreditDict[domainName];
                        }

                        dt.Rows.Add(newRow);
                    }
                }
            }

            return(dt);
        }
        private Workbook FillWorkBookData(ParameterRec data)
        {
            Workbook prototype = new Workbook();

            prototype.Copy(wbTemplate);
            Worksheet ps = prototype.Worksheets[0];

            Workbook wb = new Workbook();

            wb.Copy(prototype);
            Worksheet ws = wb.Worksheets[0];

            Range colRange = ps.Cells.CreateRange(2, 1, 1, 1);
            Range rowRange = ps.Cells.CreateRange(3, 1, false);

            int rowIndex    = 0;
            int colIndex    = 0;
            int domainCount = listDomainFromData.Count;

            string title = cbxIsSchoolYear.Checked ? $"{data.SchoolYear}學年度 領域不及格人數統計表"
                    : $"{data.SchoolYear}學年度 {data.Semester}學期 領域不及格人數統計表";

            ws.Cells.Merge(rowIndex, 0, 1, domainCount * 2);
            ws.Cells[rowIndex++, 0].PutValue(title);

            // 各學習領域學生成績評量情形
            {
                ws.Cells.Merge(1, 1, 1, domainCount);

                Range range = ws.Cells.CreateRange(1, 1, 1, domainCount);
                range.SetOutlineBorders(CellBorderType.Thin, Color.Black);
                range.PutValue("各學習領域學生成績評量情形", false, false);

                Cell  cell  = ws.Cells.GetCell(1, 1);
                Style style = cell.GetStyle();
                style.HorizontalAlignment = TextAlignmentType.Center;
                cell.SetStyle(style);
            }
            // 學生成績評量不及格領域數情形
            {
                ws.Cells.Merge(1, domainCount + 1, 1, domainCount);

                Range range = ws.Cells.CreateRange(1, domainCount + 1, 1, domainCount);
                range.SetOutlineBorders(CellBorderType.Thin, Color.Black);
                range.PutValue("學生成績評量不及格領域數情形", false, false);

                Cell  cell  = ws.Cells.GetCell(1, domainCount + 1);
                Style style = cell.GetStyle();
                style.HorizontalAlignment = TextAlignmentType.Center;
                cell.SetStyle(style);
            }
            rowIndex++;

            colIndex = 1;
            // 領域
            foreach (string domain in listDomainFromData)
            {
                Range range = ws.Cells.CreateRange(rowIndex, colIndex, 1, 1);
                range.CopyStyle(colRange);
                range.ColumnWidth = colRange.ColumnWidth;
                ws.Cells[rowIndex, colIndex++].PutValue(domain);
            }

            // 不及格數
            for (int i = 1; i <= listDomainFromData.Count; i++)
            {
                Range range = ws.Cells.CreateRange(rowIndex, colIndex, 1, 1);
                range.CopyStyle(colRange);
                range.ColumnWidth = colRange.ColumnWidth;
                ws.Cells[rowIndex, colIndex++].PutValue($"{i}個學習領域不及格人數");
            }

            rowIndex++;
            // 年級
            foreach (string gradeYear in listGradeYear)
            {
                colIndex = 0;

                if (rowIndex > 3)
                {
                    ws.Cells.InsertRow(rowIndex);
                }
                ws.Cells.CreateRange(rowIndex, 1, false).CopyStyle(rowRange);
                ws.Cells[rowIndex, colIndex++].PutValue($"{gradeYear}年級");

                // 領域不及格人數
                foreach (string domain in listDomainFromData)
                {
                    Range range = ws.Cells.CreateRange(rowIndex, colIndex, 1, 1);
                    range.CopyStyle(colRange);

                    if (dicUnPassCountByDomainGradeYear[gradeYear].ContainsKey(domain))
                    {
                        int unPassCount = dicUnPassCountByDomainGradeYear[gradeYear][domain];
                        ws.Cells[rowIndex, colIndex++].PutValue(unPassCount);
                    }
                    else
                    {
                        ws.Cells[rowIndex, colIndex++].PutValue(0);
                    }
                }

                // 不及格領域人數
                for (int i = 1; i <= listDomainFromData.Count; i++)
                {
                    Range range = ws.Cells.CreateRange(rowIndex, colIndex, 1, 1);
                    range.CopyStyle(colRange);

                    if (dicUnPassCountByUnPassGradeYear.ContainsKey(gradeYear))
                    {
                        if (dicUnPassCountByUnPassGradeYear[gradeYear].ContainsKey(i))
                        {
                            int unPassCount = dicUnPassCountByUnPassGradeYear[gradeYear][i];
                            ws.Cells[rowIndex, colIndex++].PutValue(unPassCount);
                        }
                        else
                        {
                            ws.Cells[rowIndex, colIndex++].PutValue(0);
                        }
                    }
                    else
                    {
                        ws.Cells[rowIndex, colIndex++].PutValue(0);
                    }
                }
                rowIndex++;
            }

            colIndex = 1;
            // 總計 領域
            foreach (string domain in listDomainFromData)
            {
                Range range = ws.Cells.CreateRange(rowIndex, colIndex, 1, 1);
                range.CopyStyle(colRange);

                ws.Cells[rowIndex, colIndex++].PutValue(dicTotalCountByDomain[domain]);
            }
            // 總計 不及格領域數
            foreach (int i in dicTotalCountByUnPass.Keys)
            {
                Range range = ws.Cells.CreateRange(rowIndex, colIndex, 1, 1);
                range.CopyStyle(colRange);

                ws.Cells[rowIndex, colIndex++].PutValue(dicTotalCountByUnPass[i]);
            }
            rowIndex++;

            int year  = DateTime.Now.Year - 1911;
            int month = DateTime.Now.Month;
            int day   = DateTime.Now.Day;

            ws.Cells[rowIndex, 0].PutValue($"列印日期: {year}年{month}月{day}日");
            return(wb);
        }