public async Task <IActionResult> GetMonthlyReport(int managerId, DateTime date) { var report = await _reportService.GetMonthlyReportAsync(managerId, date); byte[] fileContents; using (var package = new ExcelPackage()) { var worksheet = package.Workbook.Worksheets.Add("Часы"); //Header var header = new List <string>() { "№", "ФИО", "Ставка", "Норма часов", "Итого" }; using (ExcelRange range = worksheet.Cells[1, 1, 1, header.Count]) { //формируется статическая шапка, задаются стили range.LoadFromArrays(new List <string[]>(new[] { header.ToArray() })); AddColorForRangeCells(range, Color.FromArgb(204, 204, 255)); range.Style.Font.Bold = true; using (ExcelRange headerRange = worksheet.Cells[1, 3, 1, header.Count]) { headerRange.Style.TextRotation = 90; } } // к шапке добавляются проекты и типы отпусков работников for (int i = 0; i < report.Events.Count(); i++) { var item = report.Events.ElementAt(i); var cell = worksheet.Cells[1, header.Count + 1 + i]; cell.Value = item.Name; cell.Style.TextRotation = 90; cell.Style.Font.Bold = true; Color color; // в зависимости от типа, назначается цвет switch (item.EventType) { case EventType.ManagerProject: color = Color.LightGreen; break; case EventType.NotManagerProject: color = Color.FromArgb(255, 255, 204); break; case EventType.Vacation: color = Color.FromArgb(255, 204, 0); break; case EventType.AnotherLeave: color = Color.FromArgb(204, 153, 255); break; default: color = Color.White; break; } AddColorForRangeCells(cell, color); } //Header Two, формируется вторая шапка под первой, которая содержит суммы часов по проектам worksheet.Cells[2, 2].Value = "Итого"; worksheet.Cells[2, 2].Style.Font.Bold = true; using (ExcelRange range = worksheet.Cells[2, header.Count, 2, header.Count + report.Events.Count()]) { for (int column = 1; column <= range.Columns; column++) { var cell = worksheet.Cells[range.Start.Row, column + header.Count - 1]; var startCell = cell.Start; // формула для сложения все часов за элемент в шапке один (вертикальный столбец) cell.Formula = $"SUM({worksheet.Cells[startCell.Row + 1, startCell.Column].Address}:{worksheet.Cells[startCell.Row + report.Users.Count(), startCell.Column].Address})"; } range.Style.Font.Bold = true; } AddColorForRangeCells(worksheet, 2, 1, 2, header.Count + report.Events.Count(), Color.FromArgb(153, 204, 255)); //Формирование списка пользователей var userIndex = 1; foreach (var user in report.Users) { using (ExcelRange range = worksheet.Cells[2 + userIndex, 1, 3 + userIndex, header.Count + report.Events.Count()]) { var row = new List <string> { userIndex.ToString(), $"{user.FirstName} {user.Surname}", user.Rate.ToString(CultureInfo.InvariantCulture), user.NormHours.ToString(CultureInfo.InvariantCulture) }; range.LoadFromArrays(new List <string[]>(new[] { row.ToArray() })); var currentCell = worksheet.Cells[2 + userIndex, 5]; currentCell.Formula = $"SUM({worksheet.Cells[2 + userIndex, currentCell.Start.Column + 1].Address}:{worksheet.Cells[2 + userIndex, range.End.Column].Address})"; currentCell.Style.Fill.PatternType = ExcelFillStyle.Solid; currentCell.Style.Fill.BackgroundColor.SetColor(Color.FromArgb(204, 204, 255)); // проставляются часы по проектам в соответствующие ячейки using (ExcelRange headerProjectRange = worksheet.Cells[1, header.Count + 1, 1, header.Count + report.Events.Count()]) { foreach (var project in user.Projects) { var eventCell = headerProjectRange.FirstOrDefault(h => (string)h.Value == project.ProjectName); if (eventCell == null) { throw new Exception(); } if (project.Hours > 0) { worksheet.Cells[2 + userIndex, eventCell.Start.Column].Value = project.Hours; } } } // проставляются часы по отпускам в соответствующие ячейки using (ExcelRange headerProjectRange = worksheet.Cells[1, header.Count + 1, 1, header.Count + report.Events.Count()]) { foreach (var leave in user.Leaves) { var eventCell = headerProjectRange.FirstOrDefault(h => (string)h.Value == leave.Name); if (eventCell == null) { throw new Exception(); } worksheet.Cells[2 + userIndex, eventCell.Start.Column].Value = leave.Hours; } } userIndex++; } } // стилизация ячеек с часами using (ExcelRange range = worksheet.Cells[3, header.Count + 1, 3 + report.Users.Count() - 1, header.Count + report.Events.Count()]) { AddColorForRangeCells(range, Color.FromArgb(204, 255, 204)); } //общаяя стилизация листа using (ExcelRange range = worksheet.Cells[1, 1, report.Users.Count() + 2, report.Events.Count() + 5]) { range.Style.Border.Top.Style = ExcelBorderStyle.Thin; range.Style.Border.Left.Style = ExcelBorderStyle.Thin; range.Style.Border.Right.Style = ExcelBorderStyle.Thin; range.Style.Border.Bottom.Style = ExcelBorderStyle.Thin; range.Style.Font.Size = 10; } //атоподбор размеров ячеек worksheet.Cells.AutoFitColumns(); fileContents = package.GetAsByteArray(); } if (fileContents == null || fileContents.Length == 0) { return(NotFound()); } return(File(fileContents, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", $"monthly_report_{date.Year}_{date.Month}.xlsx")); }