/// <summary> /// /// </summary> /// <param name="excelApp"> /// Приложение Excel, в котором открыты книги /// <paramref name="wbkTarget"/> и <paramref name="wbkTemplates"/> /// </param> /// <param name="wbkTarget"> /// Книга, в которую добавляется отчёт. Добавление всегда происходит в конец /// </param> /// <param name="wbkTemplates"> /// Книга с шаблонами отчётов /// </param> /// <returns></returns> public override bool CreateReport(MSExcel.Application excelApp, MSExcel.Workbook wbkTarget, MSExcel.Workbook wbkTemplates) { List <CTeamWithMembersItem> TeamReportData = new List <CTeamWithMembersItem>(); foreach (CTeamForReportItem item in CurTask.m_Teams) { TeamReportData.Add(new CTeamWithMembersItem() { m_TeamInfo = item }); } // Копируем в конец новой книги лист-шаблон MSExcel.Worksheet wsh = null; lock (DBManagerApp.m_AppSettings.m_SettingsSyncObj) { wsh = wbkTemplates.Worksheets[DBManagerApp.m_AppSettings.m_Settings.ExcelSettings.dictReportTemplates[enReportTypes.Team]]; } wsh.Copy(After: wbkTarget.Worksheets[wbkTarget.Worksheets.Count]); // Лист, в который нужно будет вставлять данные wsh = wbkTarget.Worksheets[wbkTarget.Worksheets.Count]; wsh.Name = Properties.Resources.resTeamReportSheetName; DateTime?MinDate = null, MaxDate = null; wsh.Range[RN_WOMEN_IN_GROUP].Value = CurTask.m_WomenInGroup; wsh.Range[RN_MEN_IN_GROUP].Value = CurTask.m_MenInGroup; bool HasLeadReport = CurTask.m_LeadReportInfo.m_wbkLeadReport != null; string UnknownLeadTeams = ""; #region Подсчёт статистики в трудности if (HasLeadReport) { // Проходим все листы трудности - все группы foreach (KeyValuePair <long, CGroupItem> LeadGroupInfo in CurTask.m_LeadReportInfo.m_dictLeadGroupInfos) { if (MinDate == null || LeadGroupInfo.Value.StartDate < MinDate) { MinDate = LeadGroupInfo.Value.StartDate; } if (LeadGroupInfo.Value.EndDate != null) { if (MaxDate == null || LeadGroupInfo.Value.EndDate > MaxDate) { MaxDate = LeadGroupInfo.Value.EndDate; } } MSExcel.Worksheet wshLead = CurTask.m_LeadReportInfo.m_wbkLeadReport.Worksheets[LeadGroupInfo.Value.LeadSheetIndex + 1]; List <CPersonalItem> LeadMembers = new List <CPersonalItem>(); for (int Row = 0; wshLead.Cells[Row + CurTask.m_LeadReportInfo.m_FirstMemberRow, CurTask.m_LeadReportInfo.m_PlaceColumnIndex].Value != null && !string.IsNullOrWhiteSpace(wshLead.Cells[Row + CurTask.m_LeadReportInfo.m_FirstMemberRow, CurTask.m_LeadReportInfo.m_PlaceColumnIndex].Value.ToString()); Row++) { int PlaceInLead; if (!int.TryParse(wshLead.Cells[Row + CurTask.m_LeadReportInfo.m_FirstMemberRow, CurTask.m_LeadReportInfo.m_PlaceColumnIndex].Value.ToString(), out PlaceInLead)) { // У участника какое-то неонятное место => пропускаем continue; } string[] arrNameAndSurname; string SurnameAndName = GlobalDefines.CorrectSurnameAndName(wshLead.Cells[Row + CurTask.m_LeadReportInfo.m_FirstMemberRow, CurTask.m_LeadReportInfo.m_PersonalDataColumnIndex].Value, out arrNameAndSurname); // Ищем команду в списке string TeamNameInLead = wshLead.Cells[Row + CurTask.m_LeadReportInfo.m_FirstMemberRow, CurTask.m_LeadReportInfo.m_TeamColumnIndex].Value; TeamNameInLead = GlobalDefines.CorrectTeam(TeamNameInLead); CTeamWithMembersItem TeamInfo = TeamReportData.Find(arg => arg.m_TeamInfo.Subteams.FirstOrDefault(arg1 => arg1.Name == TeamNameInLead) != null); if (TeamInfo == null) { // Такой команды нет => запоминаем её название, чтобы потом вывести его в сообщении // Но из рассмотрения этого участника не выкидываем, т.к. нужно посчитать заработанные им баллы UnknownLeadTeams += string.Format("\t {0} {1} {2};\n", GlobalDefines.BULLET_CHAR_IN_MSG_BOX, SurnameAndName, TeamNameInLead); } // Заносим участника в LeadMembers, чтобы потом посчитать его баллы CPersonalItem Member = new CPersonalItem() { m_Place = PlaceInLead, m_GroupId = LeadGroupInfo.Value.id, m_SurnameAndName = SurnameAndName, m_Sex = LeadGroupInfo.Value.Sex }; LeadMembers.Add(Member); if (TeamInfo != null) { List <CPersonalItem> GroupLeadMembers; if (TeamInfo.m_dictLeadMembers.TryGetValue(Member.m_GroupId, out GroupLeadMembers)) { if (GroupLeadMembers.Count < (LeadGroupInfo.Value.Sex == enSex.Male ? CurTask.m_MenInGroup : CurTask.m_WomenInGroup)) { // Группа ещё не заполнена GroupLeadMembers.Add(Member); } } else { GroupLeadMembers = new List <CPersonalItem>(); GroupLeadMembers.Add(Member); TeamInfo.m_dictLeadMembers.Add(Member.m_GroupId, GroupLeadMembers); } } } MakeBallsForPlaces(LeadMembers); // Считаем баллы за места в трудности LeadMembers.Clear(); } // Удаляем команды, которых нет в трудности, т.к. для командного зачёта необходим результат команды и в трудности, и в скорости TeamReportData.RemoveAll(arg => arg.m_dictLeadMembers.Count == 0); if (!string.IsNullOrWhiteSpace(UnknownLeadTeams)) { // Есть команды, которых нет в TeamReportData => сообщаем об этом // Оставляем не более 10 записей, чтобы не раздувать сообщение List <string> Lines = UnknownLeadTeams.Split('\n').ToList(); Lines.RemoveAt(Lines.Count - 1); // Последняя строка будет всегда пустой if (Lines.Count > 10) { UnknownLeadTeams = ""; for (int i = 0; i < 10; i++) { UnknownLeadTeams += Lines[i] + "\n"; } UnknownLeadTeams += "...\n"; } MessageBox.Show(string.Format(Properties.Resources.resfmtUnknownTeamsInLead, UnknownLeadTeams), DBManagerApp.MainWnd.Title, MessageBoxButton.OK, MessageBoxImage.Error); } } #endregion #region Подсчитываем статистику в скорости bool IsFirstGroup = true; foreach (groups GroupInDB in CurTask.m_CompDesc.groups) { CCompSettings CompSettings = new CCompSettings(GroupInDB); if (IsFirstGroup) { IsFirstGroup = false; wsh.Range[RN_COMP_NAME].Value = CompSettings.CompName; wsh.Range[RN_MAIN_JUDGE].Value = CompSettings.MainJudge; wsh.Range[RN_MAIN_SECRETARY].Value = CompSettings.MainSecretary; } if (MinDate == null || CompSettings.StartDate.Date < MinDate) { MinDate = CompSettings.StartDate.Date; } if (CompSettings.EndDate != null) { if (MaxDate == null || CompSettings.EndDate.Date > MaxDate) { MaxDate = CompSettings.EndDate.Date; } } // Раскидываем участников по командам foreach (CPersonalItem Member in (from member in DBManagerApp.m_Entities.members join part in DBManagerApp.m_Entities.participations on member.id_member equals part.member where part.Group == GroupInDB.id_group && part.result_place.HasValue && part.results_speed.Count(arg => arg.balls.HasValue && arg.balls.Value > 0) == 1 // Выбираем только те группы, у которых расставлены баллы orderby part.result_place select new CPersonalItem() { m_Place = part.result_place.Value, m_GroupId = part.Group, m_SurnameAndName = member.surname + " " + member.name, m_Sex = (enSex)member.sex, m_Balls = (from result in part.results_speed where result.balls.HasValue select result.balls.Value).FirstOrDefault(), m_Team = CompSettings.SecondColNameType == enSecondColNameType.Coach ? part.coach : part.team }).ToList()) { string TeamName = ""; if (CompSettings.SecondColNameType == enSecondColNameType.Coach) { TeamName = DBManagerApp.m_Entities.coaches.First(arg => arg.id_coach == Member.m_Team).name; } else { TeamName = DBManagerApp.m_Entities.teams.First(arg => arg.id_team == Member.m_Team).name; } CTeamWithMembersItem TeamInfo = TeamReportData.Find(arg => arg.m_TeamInfo.Subteams.FirstOrDefault(arg1 => arg1.Name == TeamName) != null); List <CPersonalItem> GroupSpeedMembers; if (TeamInfo.m_dictSpeedMembers.TryGetValue(Member.m_GroupId, out GroupSpeedMembers)) { if (GroupSpeedMembers.Count < (Member.m_Sex == enSex.Male ? CurTask.m_MenInGroup : CurTask.m_WomenInGroup)) { // Группа ещё не заполнена GroupSpeedMembers.Add(Member); } } else { GroupSpeedMembers = new List <CPersonalItem>(); GroupSpeedMembers.Add(Member); TeamInfo.m_dictSpeedMembers.Add(Member.m_GroupId, GroupSpeedMembers); } } } // Удаляем команды, которых нет в скорости, т.к. для командного зачёта необходим результат команды и в трудности, и в скорости TeamReportData.RemoveAll(arg => arg.m_dictSpeedMembers.Count == 0); #endregion // Выводим дату соревнований wsh.Range[RN_ROUND_DATE].Value = GlobalDefines.CreateCompDate(MinDate.Value, MaxDate); // Сортируем команды по убыванию заработанных баллов TeamReportData.Sort((lhs, rhs) => { if (GlobalDefines.IsFloatsEqu(lhs.TotalBalls, rhs.TotalBalls, 1e-3)) { return(0); } else if (lhs.TotalBalls < rhs.TotalBalls) { return(1); } else { return(-1); } }); TeamReportData.ForEach(team => { // Сортируем группы по полу: сначала девочки, потом мальчики, а потом по годам рождения team.m_dictLeadMembers = (from GroupMembers in team.m_dictLeadMembers orderby GroupMembers.Value[0].m_Sex descending, DBManagerApp.m_Entities.groups.FirstOrDefault(gr => gr.id_group == GroupMembers.Key).start_year descending select GroupMembers).ToDictionary(key => key.Key, value => value.Value); team.m_dictSpeedMembers = (from GroupMembers in team.m_dictSpeedMembers orderby GroupMembers.Value[0].m_Sex descending, DBManagerApp.m_Entities.groups.FirstOrDefault(gr => gr.id_group == GroupMembers.Key).start_year descending select GroupMembers).ToDictionary(key => key.Key, value => value.Value); }); #region Выводим отчёт int FirstRow = wsh.Range[RN_FIRST_DATA_ROW].Row; int CurPlace = 1; float?PrevResult = null; // Такого результата не может быть for (int i = 0; i < TeamReportData.Count; i++) { if (TeamReportData[i].TotalBalls != PrevResult) { CurPlace = i + 1; } wsh.Cells[i + FirstRow, EXCEL_PLACE_COL_NUM].Value = GlobalDefines.EncodePlace((byte)CurPlace); wsh.Cells[i + FirstRow, EXCEL_TEAM_COL_NUM].Value = TeamReportData[i].m_TeamInfo.Name; string MembersList = ""; if (HasLeadReport) { foreach (KeyValuePair <long, List <CPersonalItem> > GroupMembers in TeamReportData[i].m_dictLeadMembers) { GroupMembers.Value.ForEach(member => { MembersList += string.Format("{0} ({1}) ", member.m_SurnameAndName, member.m_Balls); }); MembersList += "\n"; } wsh.Range[RN_LEAD].Offset[i].Cells[1, EXCEL_TEAM_MEMBERS_OFS + 1].Value = MembersList.Left(MembersList.Length - 1); wsh.Range[RN_LEAD].Offset[i].Cells[1, EXCEL_TEAM_BALLS_OFS + 1].Value = TeamReportData[i].LeadBalls; } MembersList = ""; foreach (KeyValuePair <long, List <CPersonalItem> > GroupMembers in TeamReportData[i].m_dictSpeedMembers) { GroupMembers.Value.ForEach(member => { MembersList += string.Format("{0} ({1}) ", member.m_SurnameAndName, member.m_Balls); }); MembersList += "\n"; } wsh.Range[RN_SPEED].Offset[i].Cells[1, EXCEL_TEAM_MEMBERS_OFS + 1].Value = MembersList.Left(MembersList.Length - 1); wsh.Range[RN_SPEED].Offset[i].Cells[1, EXCEL_TEAM_BALLS_OFS + 1].Value = TeamReportData[i].SpeedBalls; if (HasLeadReport) { wsh.Range[RN_RESULT].Offset[i].Value = TeamReportData[i].TotalBalls; } else { wsh.Range[RN_RESULT].Offset[i].FormulaR1C1 = "=RC[-3] + RC[-1]"; } PrevResult = TeamReportData[i].TotalBalls; } // Удаляем лишние строки wsh.Rows[(FirstRow + TeamReportData.Count).ToString() + ":" + (EXCEL_MAX_LINES_IN_TEAM_REPORT + FirstRow - 1).ToString()].Delete(MSExcel.XlDirection.xlUp); #endregion return(true); }