using _0_Framework.Excel; using _0_Framework.Application; using CompanyManagment.App.Contracts.RollCall; using OfficeOpenXml; using OfficeOpenXml.Drawing; using System; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; namespace CompanyManagement.Infrastructure.Excel.RollCall; public class RollCallExcelGenerator : ExcelGenerator { public static byte[] CaseHistoryExcelForEmployee(CaseHistoryRollCallExcelForEmployeeViewModel data) { OfficeOpenXml.ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization"); using var package = new OfficeOpenXml.ExcelPackage(); var worksheet = package.Workbook.Worksheets.Add("Sheet1"); var rollCalls = data.RollCalls; var row = 6; worksheet.Cells.Style.Locked = false; // Merge cells from row 1 to 4, covering columns A to G worksheet.Cells["A1:H4"].Merge = true; // Add the image to the merged cell var headerImagePath = Path.Combine("wwwroot", "Excel", "header", "21.png"); using (var stream = new FileStream(headerImagePath, FileMode.Open, FileAccess.Read)) { var picture = worksheet.Drawings.AddPicture("HeaderImage", stream); picture.SetPosition(0, 0, 0, 0); // Set position to the merged picture.ChangeCellAnchor(eEditAs.TwoCell); picture.EditAs = eEditAs.Absolute; } // Add border to the merged cell var mergedCell = worksheet.Cells["A1:H4"]; mergedCell.Style.Border.Top.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin; mergedCell.Style.Border.Bottom.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin; mergedCell.Style.Border.Left.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin; mergedCell.Style.Border.Right.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin; // Add merged cells below the image worksheet.Cells["A5:C5"].Merge = true; // ماه worksheet.Cells["D5:F5"].Merge = true; // نام کارمند worksheet.Cells["G5:H5"].Merge = true; // شماره پرسنلی // Add data from ViewModel worksheet.Cells["A5"].Value = $"{data.PersianMonthName} {data.PersianYear}"; // ماه و سال worksheet.Cells["D5"].Value = data.EmployeeFullName; // نام کارمند worksheet.Cells["G5"].Value = $"شماره پرسنلی: {data.PersonnelCode}"; // شماره پرسنلی // Style merged cells for (int i = 5; i <= 5; i++) { worksheet.Cells[$"A{i}:B{i}"].Style.Font.Bold = true; worksheet.Cells[$"A{i}:B{i}"].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center; worksheet.Cells[$"A{i}:B{i}"].Style.VerticalAlignment = OfficeOpenXml.Style.ExcelVerticalAlignment.Center; worksheet.Cells[$"A{i}:B{i}"].Style.Font.Size = 14; // Larger font size worksheet.Cells[$"C{i}:E{i}"].Style.Font.Bold = true; worksheet.Cells[$"C{i}:E{i}"].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center; worksheet.Cells[$"C{i}:E{i}"].Style.VerticalAlignment = OfficeOpenXml.Style.ExcelVerticalAlignment.Center; worksheet.Cells[$"C{i}:E{i}"].Style.Font.Size = 14; // Larger font size worksheet.Cells[$"F{i}:G{i}"].Style.Font.Bold = true; worksheet.Cells[$"F{i}:G{i}"].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center; worksheet.Cells[$"F{i}:G{i}"].Style.VerticalAlignment = OfficeOpenXml.Style.ExcelVerticalAlignment.Center; worksheet.Cells[$"F{i}:G{i}"].Style.Font.Size = 14; // Larger font size } //add border to headers worksheet.Cells["A5"].Style.Border.Left.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin; worksheet.Cells["H5"].Style.Border.Right.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin; worksheet.Cells["A6"].Style.Border.Left.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin; worksheet.Cells["H6"].Style.Border.Right.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin; worksheet.Cells["B6:C6"].Merge = true; // Lock cells A1 to H6 worksheet.Cells["A1:H6"].Style.Locked = true; // Set worksheet protection with password worksheet.Protection.IsProtected = true; worksheet.Protection.SetPassword("Gozareshgir2049"); // Set your desired password here worksheet.Protection.AllowSelectLockedCells = true; // Unlock all other cells // Add headers worksheet.Cells["A6"].Value = "ردیف"; worksheet.Cells["B6"].Value = "تاریخ"; worksheet.Cells["D6"].Value = "تاخیر در ورود"; worksheet.Cells["E6"].Value = "ورود"; worksheet.Cells["F6"].Value = "خروج"; worksheet.Cells["G6"].Value = "تعجیل در خروج"; worksheet.Cells["H6"].Value = "مجموع ساعات کاری"; // Style headers using (var range = worksheet.Cells[row, 1, row, 8]) { range.Style.Font.Bold = true; range.Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid; range.Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.LightGray); range.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center; range.Style.Border.Right.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin; range.Style.Border.Left.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin; range.Style.Border.Bottom.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin; range.Style.Border.Top.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin; } // Add data for (int i = 0; i < rollCalls.Count; i++) { var rollCall = rollCalls[i]; worksheet.Cells[i + row + 1, 1].Value = i + 1; worksheet.Cells[i + row + 1, 2].Value = rollCall.DayOfWeekFa; worksheet.Cells[i + row + 1, 3].Value = rollCall.DateFa; worksheet.Cells[i + row + 1, 4].Value = rollCall.EnterTimeDifferences; worksheet.Cells[i + row + 1, 5].Value = rollCall.StartsItems; worksheet.Cells[i + row + 1, 6].Value = rollCall.EndsItems; worksheet.Cells[i + row + 1, 7].Value = rollCall.ExitTimeDifferences; worksheet.Cells[i + row + 1, 8].Value = rollCall.TotalWorkingHours == string.Empty ? "ندارد" : rollCall.TotalWorkingHours; // Style data cells for (int j = 1; j <= 8; j++) { var cell = worksheet.Cells[i + row + 1, j]; cell.Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Thin); cell.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center; cell.Style.VerticalAlignment = OfficeOpenXml.Style.ExcelVerticalAlignment.Center; if (j == 5 || j == 6) { cell.Style.WrapText = true; } } } // Merge the last row int lastRow = rollCalls.Count + row +1; worksheet.Cells[$"A{lastRow}:G{lastRow}"].Merge = true; worksheet.Cells[$"A{lastRow}"].Value = $"مجموع کل ساعات کاری : {data.TotalWorkingHoursFa}"; // Replace with your actual data worksheet.Cells[$"A{lastRow}"].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Left; // Align left worksheet.Cells[$"A{lastRow}"].Style.Font.Bold = true; // Add border to the merged last row worksheet.Cells[$"A{lastRow}:G{lastRow}"].Style.Border.Top.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin; worksheet.Cells[$"A{lastRow}:G{lastRow}"].Style.Border.Bottom.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin; worksheet.Cells[$"A{lastRow}:G{lastRow}"].Style.Border.Left.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin; worksheet.Cells[$"A{lastRow}:G{lastRow}"].Style.Border.Right.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin; worksheet.Cells[$"H{lastRow}"].Value = data.TotalWorkingTimeSpan; worksheet.Cells[$"H{lastRow}"].Style.Font.Bold = true; worksheet.Cells[$"H{lastRow}"].Style.Border.Top.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin; worksheet.Cells[$"H{lastRow}"].Style.Border.Bottom.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin; worksheet.Cells[$"H{lastRow}"].Style.Border.Left.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin; worksheet.Cells[$"H{lastRow}"].Style.Border.Right.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin; worksheet.Cells[$"H{lastRow}"].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center; // Adjust column widths worksheet.Cells[worksheet.Dimension.Address].AutoFitColumns(); // Set the sheet to A4 size worksheet.PrinterSettings.PaperSize = ePaperSize.A4; worksheet.PrinterSettings.Orientation = eOrientation.Portrait; // or Landscape worksheet.PrinterSettings.FitToWidth = 1; worksheet.PrinterSettings.FitToHeight = 0; worksheet.View.RightToLeft = true; // Repeat headers on every page worksheet.PrinterSettings.RepeatRows = new OfficeOpenXml.ExcelAddress("1:6"); // Repeat rows 1 to 6 on every page return package.GetAsByteArray(); } public static byte[] CaseHistoryExcelForOneDay(CaseHistoryRollCallForOneDayViewModel data) { OfficeOpenXml.ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization"); using var package = new OfficeOpenXml.ExcelPackage(); var worksheet = package.Workbook.Worksheets.Add("Sheet1"); var rollCalls = data.RollCalls; var row = 6; worksheet.Cells.Style.Locked = false; // Merge cells from row 1 to 4, covering columns A to H worksheet.Cells["A1:H4"].Merge = true; // Add the image to the merged cell var headerImagePath = Path.Combine("wwwroot", "Excel", "header", "21.OneDay.png"); using (var stream = new FileStream(headerImagePath, FileMode.Open, FileAccess.Read)) { var picture = worksheet.Drawings.AddPicture("HeaderImage", stream); picture.SetPosition(0, 0, 0, 0); // Set position to the merged cell //picture.SetSize(600, 75); // Adjust the size as needed } // Add border to the merged cell var mergedCell = worksheet.Cells["A1:H4"]; mergedCell.Style.Border.Top.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin; mergedCell.Style.Border.Bottom.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin; mergedCell.Style.Border.Left.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin; mergedCell.Style.Border.Right.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin; // Add merged cells below the image worksheet.Cells["A5:H5"].Merge = true; // Add data from ViewModel worksheet.Cells["A5"].Value = $"پرینت حضور و غیاب کل پرسنل به تاریخ {data.DateFa}"; // تاریخ // Style merged cells var mergedHeaderCell = worksheet.Cells["A5:H5"]; mergedHeaderCell.Style.Font.Bold = true; mergedHeaderCell.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center; mergedHeaderCell.Style.VerticalAlignment = OfficeOpenXml.Style.ExcelVerticalAlignment.Center; mergedHeaderCell.Style.Font.Size = 14; // Larger font size // Add border to header cell worksheet.Cells["A5"].Style.Border.Left.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin; worksheet.Cells["H5"].Style.Border.Right.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin; // Add headers worksheet.Cells[row, 1].Value = "ردیف"; worksheet.Cells[row, 2].Value = "نام و نام خانوادگی"; worksheet.Cells[row, 3].Value = "شماره پرسنلی"; worksheet.Cells[row, 4].Value = "تاخیر در ورود"; worksheet.Cells[row, 5].Value = "ورود"; worksheet.Cells[row, 6].Value = "خروج"; worksheet.Cells[row, 7].Value = "تعجیل در خروج"; worksheet.Cells[row, 8].Value = "مجموع ساعات کاری"; // Style headers with left and right borders worksheet.Cells[row, 1].Style.Border.Right.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin; // Right border for first column worksheet.Cells[row, 8].Style.Border.Left.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin; // Left border for last column // Style headers using (var range = worksheet.Cells[row, 1, row, 8]) { range.Style.Font.Bold = true; range.Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid; range.Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.LightGray); range.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center; range.Style.Border.Right.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin; range.Style.Border.Left.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin; range.Style.Border.Bottom.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin; range.Style.Border.Top.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin; } // Lock cells A1 to H6 worksheet.Cells["A1:H6"].Style.Locked = true; // Set worksheet protection with password worksheet.Protection.IsProtected = true; worksheet.Protection.SetPassword("Gozareshgir2049"); // Add data for (int i = 0; i < rollCalls.Count; i++) { var rollCall = rollCalls[i]; worksheet.Cells[i + row + 1, 1].Value = i + 1; worksheet.Cells[i + row + 1, 2].Value = rollCall.EmployeeFullName; worksheet.Cells[i + row + 1, 3].Value = rollCall.PersonnelCode; worksheet.Cells[i + row + 1, 4].Value = "-"; worksheet.Cells[i + row + 1, 5].Value = rollCall.StartsItems; worksheet.Cells[i + row + 1, 6].Value = rollCall.EndsItems; worksheet.Cells[i + row + 1, 7].Value = "-"; worksheet.Cells[i + row + 1, 8].Value = rollCall.TotalWorkingHours; // Style data cells for (int j = 1; j <= 8; j++) { var cell = worksheet.Cells[i + row + 1, j]; cell.Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Thin); cell.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center; cell.Style.VerticalAlignment = OfficeOpenXml.Style.ExcelVerticalAlignment.Center; if (j == 5 || j == 6) { cell.Style.WrapText = true; } } } // Adjust column widths worksheet.Cells[worksheet.Dimension.Address].AutoFitColumns(); // Set the sheet to A4 size worksheet.PrinterSettings.PaperSize = ePaperSize.A4; worksheet.PrinterSettings.Orientation = eOrientation.Portrait; worksheet.PrinterSettings.FitToPage = true; worksheet.PrinterSettings.FitToWidth = 1; worksheet.PrinterSettings.FitToHeight = 0; worksheet.PrinterSettings.Scale = 85; // Scale to fit content within A4 width worksheet.View.RightToLeft = true; // Repeat headers on every page worksheet.PrinterSettings.RepeatRows = new OfficeOpenXml.ExcelAddress("1:6"); // Repeat rows 1 to 6 on every page return package.GetAsByteArray(); } public static byte[] CaseHistoryExcelForEmployee(List data, string titleId) { if (!Regex.IsMatch(titleId, @"^\d{4}_\d{2}$")) throw new ArgumentException("Invalid titleId format.", nameof(titleId)); var splitDate = titleId.Split("_"); var year = Convert.ToInt32(splitDate.First()); var month = Convert.ToInt32(splitDate.Last()); var startDateFa = $"{year:D4}/{month:D2}/01"; var startDate = startDateFa.ToGeorgianDateTime(); var endDateFa = startDateFa.FindeEndOfMonth(); var endDate = endDateFa.ToGeorgianDateTime(); var dateRange = (int)(endDate.Date - startDate.Date).TotalDays + 1; var dates = Enumerable.Range(0, dateRange).Select(x => startDate.AddDays(x)).ToList(); var safeData = data ?? new List(); var first = safeData.FirstOrDefault(); var totalWorkingTime = new TimeSpan(safeData.Sum(x => x.TotalWorkingTime.Ticks)); var viewModel = new CaseHistoryRollCallExcelForEmployeeViewModel { EmployeeId = first?.EmployeeId ?? 0, DateGr = startDate, PersonnelCode = first?.PersonnelCode, EmployeeFullName = first?.EmployeeFullName, PersianMonthName = month.ToFarsiMonthByIntNumber(), PersianYear = year.ToString(), TotalWorkingHoursFa = totalWorkingTime.ToFarsiHoursAndMinutes("-"), TotalWorkingTimeSpan = $"{(int)totalWorkingTime.TotalHours}:{totalWorkingTime.Minutes:00}", RollCalls = dates.Select((date, index) => { var item = index < safeData.Count ? safeData[index] : null; var records = item?.Records ?? new List(); return new RollCallItemForEmployeeExcelViewModel { DateGr = date, DateFa = date.ToFarsi(), DayOfWeekFa = date.DayOfWeek.DayOfWeeKToPersian(), PersonnelCode = item?.PersonnelCode, EmployeeFullName = item?.EmployeeFullName, IsAbsent = item?.Status == RollCallRecordStatus.Absent, HasLeave = item?.Status == RollCallRecordStatus.Leaved, IsHoliday = false, TotalWorkingHours = (item?.TotalWorkingTime ?? TimeSpan.Zero).ToFarsiHoursAndMinutes("-"), StartsItems = JoinRecords(records, r => r.StartTime), EndsItems = JoinRecords(records, r => r.EndTime), EnterTimeDifferences = JoinRecords(records, r => FormatSignedTimeSpan(r.EntryTimeDifference)), ExitTimeDifferences = JoinRecords(records, r => FormatSignedTimeSpan(r.ExitTimeDifference)) }; }).ToList() }; return CaseHistoryExcelForEmployee(viewModel); } public static byte[] CaseHistoryExcelForOneDay(List data, string titleId) { if (!Regex.IsMatch(titleId, @"^\d{4}/\d{2}/\d{2}$")) throw new ArgumentException("Invalid titleId format.", nameof(titleId)); var dateGr = titleId.ToGeorgianDateTime(); var safeData = data ?? new List(); var viewModel = new CaseHistoryRollCallForOneDayViewModel { DateFa = titleId, DateGr = dateGr, DayOfWeekFa = dateGr.DayOfWeek.DayOfWeeKToPersian(), RollCalls = safeData.Select(item => { var records = item.Records ?? new List(); return new RollCallItemForOneDayExcelViewModel { EmployeeFullName = item.EmployeeFullName, PersonnelCode = item.PersonnelCode, StartsItems = JoinRecords(records, r => r.StartTime), EndsItems = JoinRecords(records, r => r.EndTime), TotalWorkingHours = item.TotalWorkingTime.ToFarsiHoursAndMinutes("-") }; }).ToList() }; return CaseHistoryExcelForOneDay(viewModel); } private static string JoinRecords(IEnumerable records, Func selector) { var safeRecords = records ?? Enumerable.Empty(); var values = safeRecords.Select(selector).Where(x => !string.IsNullOrWhiteSpace(x)).ToList(); return values.Count == 0 ? string.Empty : string.Join(Environment.NewLine, values); } private static string FormatSignedTimeSpan(TimeSpan value) { if (value == TimeSpan.Zero) return "-"; var abs = value.Duration(); var sign = value.Ticks < 0 ? "-" : "+"; return $"{(int)abs.TotalHours}:{abs.Minutes:00}{sign}"; } private string CalculateExitMinuteDifference(TimeSpan early, TimeSpan late) { if (early == TimeSpan.Zero && late == TimeSpan.Zero) { return "-"; } else if (late != TimeSpan.Zero) { var minutes = late.TotalMinutes > 999 ? "999" : late.TotalMinutes.ToString(); return $"{minutes}+"; } else if (early != TimeSpan.Zero) { var minutes = early.TotalMinutes > 999 ? "999" : early.TotalMinutes.ToString(); return $"{minutes}-"; } else { return $""; } } private string CalculateEntryMinuteDifference(TimeSpan early, TimeSpan late) { if (early == TimeSpan.Zero && late == TimeSpan.Zero) { return "-"; } else if (late != TimeSpan.Zero) { var minutes = late.TotalMinutes > 999 ? "999" : late.TotalMinutes.ToString(); return $"{minutes}-"; } else if (early != TimeSpan.Zero) { var minutes = early.TotalMinutes > 999 ? "999" : early.TotalMinutes.ToString(); return $"{minutes}+"; } else { return $""; } } }