using System; using System.Collections.Generic; using System.IO; using System.Linq; using Microsoft.EntityFrameworkCore; using ClosedXML.Excel; using ClosedXML.Excel.Drawings; using Microsoft.AspNetCore.Hosting; using PSTW_CentralSystem.Areas.OTcalculate.Models; using PSTW_CentralSystem.Models; using PSTW_CentralSystem.DBContext; namespace PSTW_CentralSystem.Areas.OTcalculate.Services { public class OvertimeExcel { private readonly CentralSystemContext _centralDbContext; private readonly IWebHostEnvironment _env; public OvertimeExcel(CentralSystemContext centralDbContext, IWebHostEnvironment env) { _centralDbContext = centralDbContext; _env = env; } public MemoryStream GenerateOvertimeExcel( List records, UserModel user, decimal userRate, DateTime? selectedMonth = null, bool isHoU = false, bool isHoD = false, bool isManager = false, string? flexiHour = null, byte[]? logoImage = null, bool isSimplifiedExport = false, OtStatusModel? otStatus = null) { bool isAdminUser = IsAdmin(user.Id); bool showStationColumn = user.Department?.DepartmentId == 3 || user.Department?.DepartmentId == 2 || isAdminUser; var stream = new MemoryStream(); using (var workbook = new XLWorkbook()) { var worksheet = workbook.Worksheets.Add("Overtime Report"); worksheet.ShowGridLines = true; int currentRow = 1; int logoBottomRow = 0; if (logoImage != null) { using (var ms = new MemoryStream(logoImage)) { var picture = worksheet.AddPicture(ms) .MoveTo(worksheet.Cell(currentRow, 1)) .WithPlacement(XLPicturePlacement.FreeFloating); picture.Name = "Company Logo"; picture.Scale(0.3); logoBottomRow = currentRow + 2; } } currentRow = logoBottomRow + 1; DateTime displayMonth = selectedMonth ?? (records.Any() ? records.First().OtDate : DateTime.Now); var allDatesInMonth = GetAllDatesInMonth(displayMonth); records = records.OrderBy(r => r.OtDate).ToList(); worksheet.Cell(currentRow, 1).Value = $"Name: {user.FullName}"; worksheet.Cell(currentRow, 1).Style.Font.SetBold(); currentRow++; worksheet.Cell(currentRow, 1).Value = $"Department: {user.Department?.DepartmentName ?? "N/A"}"; worksheet.Cell(currentRow, 1).Style.Font.SetBold(); currentRow++; if (!string.IsNullOrEmpty(flexiHour)) { worksheet.Cell(currentRow, 1).Value = $"Flexi Hour: {flexiHour}"; worksheet.Cell(currentRow, 1).Style.Font.SetBold(); currentRow++; } worksheet.Cell(currentRow, 1).Value = $"Overtime Report: {displayMonth:MMMM yyyy}"; worksheet.Cell(currentRow, 1).Style.Font.SetBold(); currentRow++; currentRow++; if (isSimplifiedExport) { AddSimplifiedHeaders(worksheet, ref currentRow, showStationColumn); } else { if (isHoU || isHoD || isManager) // If HoU, HoD, or Manager, hide salary details { if (showStationColumn) { AddHoUPSTWAirHeaders(worksheet, ref currentRow); // This already excludes salary info } else { AddHoUNonPSTWAirHeaders(worksheet, ref currentRow); // This already excludes salary info } } else // For other users (who are not HoU, HoD, or Manager) { if (showStationColumn) { AddNonHoUPSTWAirHeaders(worksheet, ref currentRow); } else { AddNonHoUNonPSTWAirHeaders(worksheet, ref currentRow); } } } var userSetting = _centralDbContext.Hrusersetting .Include(us => us.State) .FirstOrDefault(us => us.UserId == user.Id); var publicHolidays = _centralDbContext.Holidays .Where(h => userSetting != null && h.StateId == userSetting.State.StateId) .ToList(); var publicHolidayDates = publicHolidays.Select(h => h.HolidayDate.Date).ToList(); var recordsGroupedByDate = records .GroupBy(r => r.OtDate.Date) .ToDictionary(g => g.Key, g => g.ToList()); decimal totalAllBreaksMinutes = 0; decimal totalAllOtMinutes = 0; decimal totalOfficeBreak = 0; decimal totalAfterBreak = 0; decimal totalOtHrsOffice = 0; decimal totalOtHrsAfterOffice = 0; decimal totalNdOt = 0; decimal totalOdUnder4 = 0; decimal totalOd4to8 = 0; decimal totalOdAfter = 0; decimal totalRdUnder4 = 0; decimal totalRd4to8 = 0; decimal totalRdAfter = 0; decimal totalPhUnder8 = 0; decimal totalPhAfter = 0; decimal grandTotalOt = 0; decimal grandTotalNdOd = 0; decimal grandTotalRd = 0; decimal grandTotalPh = 0; decimal grandTotalOtAmount = 0; // UserRate is now interpreted as Basic Salary var basicSalary = userRate; var orp = CalculateOrp(basicSalary); // ORP = Basic Salary / 26 var hrp = CalculateHrp(orp); // HRP = ORP / 8 bool hasPrintedSalaryDetails = false; DateTime? previousDate = null; foreach (var date in allDatesInMonth) { recordsGroupedByDate.TryGetValue(date, out var dateRecords); var recordsToShow = dateRecords ?? new List { new OtRegisterModel { OtDate = date } }; recordsToShow = recordsToShow.OrderBy(r => r.OfficeFrom ?? r.AfterFrom).ToList(); foreach (var record in recordsToShow) { int col = 1; if (isSimplifiedExport) { var dayCell = worksheet.Cell(currentRow, col); var dateCell = worksheet.Cell(currentRow, col + 1); if (record.OtDate.Date != previousDate?.Date) { dayCell.Value = record.OtDate.ToString("ddd"); dateCell.Value = record.OtDate.ToString("dd-MM-yyyy"); } else { dayCell.Value = ""; dateCell.Value = ""; } ApplyDayTypeStyle(dayCell, record.OtDate, userSetting?.State?.WeekendId, publicHolidayDates); ApplyDayTypeStyle(dateCell, record.OtDate, userSetting?.State?.WeekendId, publicHolidayDates); col += 2; worksheet.Cell(currentRow, col++).Value = record.OfficeFrom?.ToString(@"hh\:mm") ?? ""; worksheet.Cell(currentRow, col++).Value = record.OfficeTo?.ToString(@"hh\:mm") ?? ""; worksheet.Cell(currentRow, col++).Value = FormatAsHourMinute(record.OfficeBreak, isMinutes: true); worksheet.Cell(currentRow, col++).Value = record.AfterFrom?.ToString(@"hh\:mm") ?? ""; worksheet.Cell(currentRow, col++).Value = record.AfterTo?.ToString(@"hh\:mm") ?? ""; worksheet.Cell(currentRow, col++).Value = FormatAsHourMinute(record.AfterBreak, isMinutes: true); var currentRecordTotalOtMinutes = (CalculateTimeDifferenceInMinutes(record.OfficeFrom, record.OfficeTo) - record.OfficeBreak.GetValueOrDefault(0)) + (CalculateTimeDifferenceInMinutes(record.AfterFrom, record.AfterTo) - record.AfterBreak.GetValueOrDefault(0)); currentRecordTotalOtMinutes = Math.Max(0, currentRecordTotalOtMinutes); worksheet.Cell(currentRow, col++).Value = FormatAsHourMinute(currentRecordTotalOtMinutes, isMinutes: true); totalAllOtMinutes += currentRecordTotalOtMinutes; var currentRecordTotalBreakMinutes = record.OfficeBreak.GetValueOrDefault(0) + record.AfterBreak.GetValueOrDefault(0); worksheet.Cell(currentRow, col++).Value = FormatAsHourMinute(currentRecordTotalBreakMinutes, isMinutes: true); totalAllBreaksMinutes += currentRecordTotalBreakMinutes; if (showStationColumn) { worksheet.Cell(currentRow, col++).Value = record.Stations?.StationName ?? ""; } var descriptionCell = worksheet.Cell(currentRow, col); descriptionCell.Value = record.OtDescription ?? ""; descriptionCell.Style.Alignment.WrapText = true; descriptionCell.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Left; descriptionCell.Style.Alignment.Vertical = XLAlignmentVerticalValues.Top; col++; var rowRange = worksheet.Range(currentRow, 1, currentRow, col - 1); rowRange.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); rowRange.Style.Border.InsideBorder = XLBorderStyleValues.Thin; rowRange.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center; rowRange.Style.Alignment.Vertical = XLAlignmentVerticalValues.Center; descriptionCell.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Left; } else // Not simplified export { var dayType = GetDayType(date, userSetting?.State?.WeekendId, publicHolidayDates); var classified = ClassifyOt(record, hrp, publicHolidayDates, userSetting?.State?.WeekendId); decimal currentNdOt = decimal.TryParse(classified["ndAfter"], out decimal ndOtVal) ? ndOtVal : 0; decimal currentOdUnder4 = decimal.TryParse(classified["odUnder4"], out decimal odUnder4Val) ? odUnder4Val : 0; decimal currentOd4to8 = decimal.TryParse(classified["odBetween4And8"], out decimal od4to8Val) ? od4to8Val : 0; decimal currentOdAfter = decimal.TryParse(classified["odAfter"], out decimal odAfterVal) ? odAfterVal : 0; decimal currentRdUnder4 = decimal.TryParse(classified["rdUnder4"], out decimal rdUnder4Val) ? rdUnder4Val : 0; decimal currentRd4to8 = decimal.TryParse(classified["rdBetween4And8"], out decimal rd4to8Val) ? rd4to8Val : 0; decimal currentRdAfter = decimal.TryParse(classified["rdAfter"], out decimal rdAfterVal) ? rdAfterVal : 0; decimal currentPhUnder8 = decimal.TryParse(classified["phUnder8"], out decimal phUnder8Val) ? phUnder8Val : 0; decimal currentPhAfter = decimal.TryParse(classified["phAfter"], out decimal phAfterVal) ? phAfterVal : 0; decimal currentRowTotalOt = currentNdOt + currentOdUnder4 + currentOd4to8 + currentOdAfter + currentRdUnder4 + currentRd4to8 + currentRdAfter + currentPhUnder8 + currentPhAfter; decimal currentRowTotalNdOd = currentNdOt + currentOdUnder4 + currentOd4to8 + currentOdAfter; decimal currentRowTotalRd = currentRdUnder4 + currentRd4to8 + currentRdAfter; decimal currentRowTotalPh = currentPhUnder8 + currentPhAfter; decimal otAmtValParsed = 0; string otAmt = ""; if (!isHoU && !isHoD && !isManager) // Only calculate and show OT amount if not HoU, HoD, or Manager { otAmt = CalculateOtAmount(record, hrp, publicHolidayDates, userSetting?.State?.WeekendId); otAmtValParsed = decimal.TryParse(otAmt, out decimal val) ? val : 0; } totalOfficeBreak += (decimal)record.OfficeBreak.GetValueOrDefault(0); totalAfterBreak += (decimal)record.AfterBreak.GetValueOrDefault(0); totalOtHrsOffice += ConvertTimeToDecimal(CalculateOfficeOtHours(record)); totalOtHrsAfterOffice += ConvertTimeToDecimal(CalculateAfterOfficeOtHours(record)); totalNdOt += currentNdOt; totalOdUnder4 += currentOdUnder4; totalOd4to8 += currentOd4to8; totalOdAfter += currentOdAfter; totalRdUnder4 += currentRdUnder4; totalRd4to8 += currentRd4to8; totalRdAfter += currentRdAfter; totalPhUnder8 += currentPhUnder8; totalPhAfter += currentPhAfter; grandTotalOt += currentRowTotalOt; grandTotalNdOd += currentRowTotalNdOd; grandTotalRd += currentRowTotalRd; grandTotalPh += currentRowTotalPh; grandTotalOtAmount += otAmtValParsed; // Only add if it was calculated if (!isHoU && !isHoD && !isManager) // Only show if not HoU, HoD, or Manager { // Basic Salary worksheet.Cell(currentRow, col).Value = !hasPrintedSalaryDetails ? basicSalary.ToString("N2") : ""; worksheet.Cell(currentRow, col++).Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center; // ORP worksheet.Cell(currentRow, col).Value = !hasPrintedSalaryDetails ? orp.ToString("N2") : ""; worksheet.Cell(currentRow, col++).Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center; // HRP worksheet.Cell(currentRow, col).Value = !hasPrintedSalaryDetails ? hrp.ToString("N2") : ""; worksheet.Cell(currentRow, col++).Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center; } hasPrintedSalaryDetails = true; // Ensure these are printed only once if visible var dayCell = worksheet.Cell(currentRow, col); var dateCell = worksheet.Cell(currentRow, col + 1); if (record.OtDate.Date != previousDate?.Date) { dayCell.Value = record.OtDate.ToString("ddd"); dateCell.Value = record.OtDate.ToString("dd-MM-yyyy"); } else { dayCell.Value = ""; dateCell.Value = ""; } ApplyDayTypeStyle(dayCell, record.OtDate, userSetting?.State?.WeekendId, publicHolidayDates); ApplyDayTypeStyle(dateCell, record.OtDate, userSetting?.State?.WeekendId, publicHolidayDates); col += 2; worksheet.Cell(currentRow, col++).Value = record.OfficeFrom?.ToString(@"hh\:mm") ?? ""; worksheet.Cell(currentRow, col++).Value = record.OfficeTo?.ToString(@"hh\:mm") ?? ""; worksheet.Cell(currentRow, col++).Value = FormatAsHourMinute(record.OfficeBreak, isMinutes: true); worksheet.Cell(currentRow, col++).Value = record.AfterFrom?.ToString(@"hh\:mm") ?? ""; worksheet.Cell(currentRow, col++).Value = record.AfterTo?.ToString(@"hh\:mm") ?? ""; worksheet.Cell(currentRow, col++).Value = FormatAsHourMinute(record.AfterBreak, isMinutes: true); worksheet.Cell(currentRow, col++).Value = CalculateOfficeOtHours(record); worksheet.Cell(currentRow, col++).Value = CalculateAfterOfficeOtHours(record); worksheet.Cell(currentRow, col++).Value = currentNdOt > 0 ? currentNdOt.ToString("N2") : ""; worksheet.Cell(currentRow, col++).Value = currentOdUnder4 > 0 ? currentOdUnder4.ToString("N2") : ""; worksheet.Cell(currentRow, col++).Value = currentOd4to8 > 0 ? currentOd4to8.ToString("N2") : ""; worksheet.Cell(currentRow, col++).Value = currentOdAfter > 0 ? currentOdAfter.ToString("N2") : ""; worksheet.Cell(currentRow, col++).Value = currentRdUnder4 > 0 ? currentRdUnder4.ToString("N2") : ""; worksheet.Cell(currentRow, col++).Value = currentRd4to8 > 0 ? currentRd4to8.ToString("N2") : ""; worksheet.Cell(currentRow, col++).Value = currentRdAfter > 0 ? currentRdAfter.ToString("N2") : ""; worksheet.Cell(currentRow, col++).Value = currentPhUnder8 > 0 ? currentPhUnder8.ToString("N2") : ""; worksheet.Cell(currentRow, col++).Value = currentPhAfter > 0 ? currentPhAfter.ToString("N2") : ""; worksheet.Cell(currentRow, col++).Value = currentRowTotalOt > 0 ? currentRowTotalOt.ToString("N2") : ""; worksheet.Cell(currentRow, col++).Value = currentRowTotalNdOd > 0 ? currentRowTotalNdOd.ToString("N2") : ""; worksheet.Cell(currentRow, col++).Value = currentRowTotalRd > 0 ? currentRowTotalRd.ToString("N2") : ""; worksheet.Cell(currentRow, col++).Value = currentRowTotalPh > 0 ? currentRowTotalPh.ToString("N2") : ""; if (!isHoU && !isHoD && !isManager) // Only show if not HoU, HoD, or Manager { worksheet.Cell(currentRow, col++).Value = otAmt == "0.00" ? "" : otAmt; } if (showStationColumn) { worksheet.Cell(currentRow, col++).Value = record.Stations?.StationName ?? ""; } var descriptionCell = worksheet.Cell(currentRow, col); descriptionCell.Value = record.OtDescription ?? ""; descriptionCell.Style.Alignment.WrapText = true; descriptionCell.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Left; descriptionCell.Style.Alignment.Vertical = XLAlignmentVerticalValues.Top; col++; var rowRange = worksheet.Range(currentRow, 1, currentRow, col - 1); rowRange.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); rowRange.Style.Border.InsideBorder = XLBorderStyleValues.Thin; rowRange.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center; rowRange.Style.Alignment.Vertical = XLAlignmentVerticalValues.Center; descriptionCell.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Left; } currentRow++; previousDate = record.OtDate.Date; } } var totalsRowRange = worksheet.Range(currentRow, 1, currentRow, worksheet.LastColumnUsed().ColumnNumber()); totalsRowRange.Style.Font.SetBold(); foreach (var cell in totalsRowRange.Cells()) { ApplyHeaderStyle(cell, 5); } totalsRowRange.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); totalsRowRange.Style.Border.InsideBorder = XLBorderStyleValues.Thin; if (isSimplifiedExport) { int totalLabelStartColumnIndex = 1; int totalLabelEndColumnIndex = 2; worksheet.Range(currentRow, totalLabelStartColumnIndex, currentRow, totalLabelEndColumnIndex).Merge(); worksheet.Cell(currentRow, totalLabelStartColumnIndex).Value = "TOTAL"; worksheet.Cell(currentRow, totalLabelStartColumnIndex).Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center; int currentTotalCol = totalLabelEndColumnIndex + 1; currentTotalCol += 6; worksheet.Cell(currentRow, currentTotalCol++).Value = FormatAsHourMinute(totalAllOtMinutes, isMinutes: true); worksheet.Cell(currentRow, currentTotalCol++).Value = FormatAsHourMinute(totalAllBreaksMinutes, isMinutes: true); if (showStationColumn) { currentTotalCol++; } } else { int totalLabelStartColumnIndex = 1; int totalLabelEndColumnIndex; if (!isHoU && !isHoD && !isManager) // If not HoU, HoD, or Manager, include salary columns in merge { totalLabelEndColumnIndex = 3; } else { totalLabelEndColumnIndex = 2; } worksheet.Range(currentRow, totalLabelStartColumnIndex, currentRow, totalLabelEndColumnIndex).Merge(); worksheet.Cell(currentRow, totalLabelStartColumnIndex).Value = "TOTAL"; worksheet.Cell(currentRow, totalLabelStartColumnIndex).Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center; int colOfficeBreakIndex = 0; int colAfterBreakIndex = 0; int colNdOtIndex = 0; int colOdUnder4Index = 0; int colOd4to8Index = 0; int colOdAfterIndex = 0; int colRdUnder4Index = 0; int colRd4to8Index = 0; int colRdAfterIndex = 0; int colPhUnder8Index = 0; int colPhAfterIndex = 0; int colTotalOtIndex = 0; int colTotalNdOdIndex = 0; int colTotalRdIndex = 0; int colTotalPhIndex = 0; int colOtAmtIndex = 0; if (!isHoU && !isHoD && !isManager) { colOfficeBreakIndex = 8; colAfterBreakIndex = 11; colNdOtIndex = 14; colOdUnder4Index = 15; colOd4to8Index = 16; colOdAfterIndex = 17; colRdUnder4Index = 18; colRd4to8Index = 19; colRdAfterIndex = 20; colPhUnder8Index = 21; colPhAfterIndex = 22; colTotalOtIndex = 23; colTotalNdOdIndex = 24; colTotalRdIndex = 25; colTotalPhIndex = 26; colOtAmtIndex = 27; } else { colOfficeBreakIndex = 5; colAfterBreakIndex = 8; colNdOtIndex = 11; colOdUnder4Index = 12; colOd4to8Index = 13; colOdAfterIndex = 14; colRdUnder4Index = 15; colRd4to8Index = 16; colRdAfterIndex = 17; colPhUnder8Index = 18; colPhAfterIndex = 19; colTotalOtIndex = 20; colTotalNdOdIndex = 21; colTotalRdIndex = 22; colTotalPhIndex = 23; } worksheet.Cell(currentRow, colOfficeBreakIndex).Value = string.IsNullOrEmpty(FormatAsHourMinute(totalOfficeBreak, isMinutes: true)) ? "0:00" : FormatAsHourMinute(totalOfficeBreak, isMinutes: true); worksheet.Cell(currentRow, colAfterBreakIndex).Value = string.IsNullOrEmpty(FormatAsHourMinute(totalAfterBreak, isMinutes: true)) ? "0:00" : FormatAsHourMinute(totalAfterBreak, isMinutes: true); worksheet.Cell(currentRow, colNdOtIndex).Value = totalNdOt.ToString("N2"); worksheet.Cell(currentRow, colOdUnder4Index).Value = totalOdUnder4.ToString("N2"); worksheet.Cell(currentRow, colOd4to8Index).Value = totalOd4to8.ToString("N2"); worksheet.Cell(currentRow, colOdAfterIndex).Value = totalOdAfter.ToString("N2"); worksheet.Cell(currentRow, colRdUnder4Index).Value = totalRdUnder4.ToString("N2"); worksheet.Cell(currentRow, colRd4to8Index).Value = totalRd4to8.ToString("N2"); worksheet.Cell(currentRow, colRdAfterIndex).Value = totalRdAfter.ToString("N2"); worksheet.Cell(currentRow, colPhUnder8Index).Value = totalPhUnder8.ToString("N2"); worksheet.Cell(currentRow, colPhAfterIndex).Value = totalPhAfter.ToString("N2"); worksheet.Cell(currentRow, colTotalOtIndex).Value = grandTotalOt.ToString("N2"); worksheet.Cell(currentRow, colTotalNdOdIndex).Value = grandTotalNdOd.ToString("N2"); worksheet.Cell(currentRow, colTotalRdIndex).Value = grandTotalRd.ToString("N2"); worksheet.Cell(currentRow, colTotalPhIndex).Value = grandTotalPh.ToString("N2"); if (!isHoU && !isHoD && !isManager) { worksheet.Cell(currentRow, colOtAmtIndex).Value = Math.Round(grandTotalOtAmount, MidpointRounding.AwayFromZero).ToString("F2"); } } currentRow++; if (!isSimplifiedExport && otStatus != null) { currentRow++; worksheet.Cell(currentRow, 1).Value = "Approval Summary:"; worksheet.Cell(currentRow, 1).Style.Font.SetBold(); currentRow++; int signatureStartCol = 1; int signatureColWidth = 5; int remarksStartColumn = worksheet.LastColumnUsed().ColumnNumber() - 2; void AddApproverSignature(int column, string role, string status, DateTime? submitDate, int? approverUserId) { if (status == "Approved") { var approverUser = _centralDbContext.Users.FirstOrDefault(u => u.Id == approverUserId); if (approverUser != null) { var approvedByCell = worksheet.Cell(currentRow, column); approvedByCell.Value = $"Approved by:"; approvedByCell.Style.Font.SetBold(); approvedByCell.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Left; worksheet.Cell(currentRow + 1, column).Value = approverUser.FullName; worksheet.Cell(currentRow + 1, column).Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Left; worksheet.Cell(currentRow + 1, column).Style.Font.SetFontName("Brush Script MT"); worksheet.Cell(currentRow + 1, column).Style.Font.SetFontSize(18); worksheet.Cell(currentRow + 2, column).Value = approverUser.FullName; worksheet.Cell(currentRow + 2, column).Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Left; worksheet.Cell(currentRow + 3, column).Value = submitDate?.ToString("dd MMMM yyyy") ?? "N/A"; worksheet.Cell(currentRow + 3, column).Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Left; } } } var approvalFlow = _centralDbContext.Hrusersetting .Include(us => us.Approvalflow) .ThenInclude(af => af.HeadOfUnit) .Include(us => us.Approvalflow) .ThenInclude(af => af.HeadOfDepartment) .Include(us => us.Approvalflow) .ThenInclude(af => af.ManagerUser) .Include(us => us.Approvalflow) .ThenInclude(af => af.HRUser) .Where(us => us.UserId == user.Id) .Select(us => us.Approvalflow) .FirstOrDefault(); if (approvalFlow != null) { int currentSignatureCol = signatureStartCol; bool hasAnyApprovedSignature = false; if (otStatus.HouStatus == "Approved") { AddApproverSignature(currentSignatureCol, "Head of Unit", otStatus.HouStatus, otStatus.HouSubmitDate, approvalFlow.HoU); currentSignatureCol += signatureColWidth; hasAnyApprovedSignature = true; } if (otStatus.HodStatus == "Approved") { AddApproverSignature(currentSignatureCol, "Head of Department", otStatus.HodStatus, otStatus.HodSubmitDate, approvalFlow.HoD); currentSignatureCol += signatureColWidth; hasAnyApprovedSignature = true; } if (otStatus.ManagerStatus == "Approved") { AddApproverSignature(currentSignatureCol, "Manager", otStatus.ManagerStatus, otStatus.ManagerSubmitDate, approvalFlow.Manager); currentSignatureCol += signatureColWidth; hasAnyApprovedSignature = true; } if (otStatus.HrStatus == "Approved") { AddApproverSignature(currentSignatureCol, "HR", otStatus.HrStatus, otStatus.HrSubmitDate, approvalFlow.HR); currentSignatureCol += signatureColWidth; hasAnyApprovedSignature = true; } int remarksColorStartRow = currentRow - 1; var phColorCell = worksheet.Cell(remarksColorStartRow, remarksStartColumn); phColorCell.Value = " "; phColorCell.Style.Fill.BackgroundColor = XLColor.FromHtml("FFC0CB"); phColorCell.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); worksheet.Cell(remarksColorStartRow, remarksStartColumn + 1).Value = " Public Holiday"; worksheet.Cell(remarksColorStartRow, remarksStartColumn + 1).Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Left; var weekendColorCell = worksheet.Cell(remarksColorStartRow + 1, remarksStartColumn); weekendColorCell.Value = " "; weekendColorCell.Style.Fill.BackgroundColor = XLColor.FromHtml("ADD8E6"); weekendColorCell.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); worksheet.Cell(remarksColorStartRow + 1, remarksStartColumn + 1).Value = " Weekend"; worksheet.Cell(remarksColorStartRow + 1, remarksStartColumn + 1).Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Left; int holidayListRow = remarksColorStartRow + 3; worksheet.Cell(holidayListRow, remarksStartColumn).Value = $"Public Holidays in {displayMonth:MMMM yyyy}:"; worksheet.Cell(holidayListRow, remarksStartColumn).Style.Font.SetBold(); holidayListRow++; if (publicHolidays != null && publicHolidays.Any()) { var monthHolidays = publicHolidays .Where(h => h.HolidayDate.Year == displayMonth.Year && h.HolidayDate.Month == displayMonth.Month) .OrderBy(h => h.HolidayDate.Day) .ToList(); if (monthHolidays.Any()) { foreach (var holiday in monthHolidays) { worksheet.Cell(holidayListRow, remarksStartColumn).Value = $"- {holiday.HolidayDate:dd MMMM}: {holiday.HolidayName}"; worksheet.Cell(holidayListRow, remarksStartColumn).Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Left; holidayListRow++; } } else { worksheet.Cell(holidayListRow, remarksStartColumn).Value = "No public holidays recorded for this month."; worksheet.Cell(holidayListRow, remarksStartColumn).Style.Font.SetItalic(); holidayListRow++; } } else { worksheet.Cell(holidayListRow, remarksStartColumn).Value = "No public holiday data found."; worksheet.Cell(holidayListRow, remarksStartColumn).Style.Font.SetItalic(); holidayListRow++; } if (hasAnyApprovedSignature) { int messageRow = holidayListRow + 2; int lastContentColumn = worksheet.LastColumnUsed().ColumnNumber(); var messageCellRange = worksheet.Range(messageRow, 1, messageRow, lastContentColumn); messageCellRange.Merge(); messageCellRange.Value = "This is an automatically generated document. No signature is required for validation."; messageCellRange.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center; messageCellRange.Style.Alignment.Vertical = XLAlignmentVerticalValues.Center; messageCellRange.Style.Font.SetItalic(); messageCellRange.Style.Font.SetFontSize(10); messageCellRange.Style.Font.FontColor = XLColor.Gray; currentRow = messageRow + 1; } currentRow = Math.Max(currentRow, holidayListRow); } } else if (isSimplifiedExport) { AddRemarksSection(worksheet, ref currentRow, displayMonth, userSetting?.State?.WeekendId, publicHolidays.Select(h => new CalendarModel { HolidayDate = h.HolidayDate, HolidayName = h.HolidayName }).ToList()); } worksheet.Columns().AdjustToContents(); if (isSimplifiedExport) { worksheet.Column(1).Width = 10; worksheet.Column(2).Width = 12; worksheet.Column(3).Width = 9; worksheet.Column(4).Width = 9; worksheet.Column(5).Width = 9; worksheet.Column(6).Width = 9; worksheet.Column(7).Width = 9; worksheet.Column(8).Width = 9; worksheet.Column(9).Width = 15; worksheet.Column(10).Width = 10; int descCol = 11; if (showStationColumn) { worksheet.Column(11).Width = 15; descCol = 12; } worksheet.Column(descCol).Width = 60; } else { if (!isHoU && !isHoD && !isManager) // If not HoU, HoD, or Manager, include salary columns in width adjustment { worksheet.Column(1).Width = 15; // Basic Salary worksheet.Column(2).Width = 10; // ORP worksheet.Column(3).Width = 10; // HRP worksheet.Column(4).Width = 10; // Day worksheet.Column(5).Width = 12; // Date worksheet.Column(6).Width = 9; // Office From worksheet.Column(7).Width = 9; // Office To worksheet.Column(8).Width = 9; // Office Break worksheet.Column(9).Width = 9; // After From worksheet.Column(10).Width = 9; // After To worksheet.Column(11).Width = 9; // After Break worksheet.Column(12).Width = 15; // OT Hrs (Office Hour) worksheet.Column(13).Width = 18; // OT Hrs (After Office Hour) for (int i = 14; i <= 27; i++) { worksheet.Column(i).Width = 12; } int descColIndex = showStationColumn ? 29 : 28; worksheet.Column(descColIndex).Width = 60; } else // If HoU, HoD, or Manager, adjust columns without salary info { worksheet.Column(1).Width = 10; worksheet.Column(2).Width = 12; worksheet.Column(3).Width = 9; worksheet.Column(4).Width = 9; worksheet.Column(5).Width = 9; worksheet.Column(6).Width = 9; worksheet.Column(7).Width = 9; worksheet.Column(8).Width = 9; worksheet.Column(9).Width = 15; worksheet.Column(10).Width = 18; for (int i = 11; i <= 23; i++) // Adjust based on new column count { worksheet.Column(i).Width = 12; } int descColIndex = showStationColumn ? 25 : 24; // Adjust based on new column count worksheet.Column(descColIndex).Width = 60; } } workbook.SaveAs(stream); } stream.Position = 0; return stream; } private void AddSimplifiedHeaders(IXLWorksheet worksheet, ref int rowIndex, bool showStationColumn) { int startRowIndex = rowIndex; int currentCol = 1; var cellDay = worksheet.Cell(rowIndex, currentCol); cellDay.Value = "Day"; ApplyHeaderStyle(cellDay, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellDate = worksheet.Cell(rowIndex, currentCol); cellDate.Value = "Date"; ApplyHeaderStyle(cellDate, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellOfficeHour = worksheet.Cell(rowIndex, currentCol); cellOfficeHour.Value = "Office Hour"; ApplyHeaderStyle(cellOfficeHour, 2); var mergedRangeOfficeHour = worksheet.Range(rowIndex, currentCol, rowIndex, currentCol + 2).Merge(); mergedRangeOfficeHour.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); mergedRangeOfficeHour.Style.Border.InsideBorder = XLBorderStyleValues.Thin; currentCol += 3; var cellAfterOfficeHour = worksheet.Cell(rowIndex, currentCol); cellAfterOfficeHour.Value = "After Office Hour"; ApplyHeaderStyle(cellAfterOfficeHour, 2); var mergedRangeAfterOfficeHour = worksheet.Range(rowIndex, currentCol, rowIndex, currentCol + 2).Merge(); mergedRangeAfterOfficeHour.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); mergedRangeAfterOfficeHour.Style.Border.InsideBorder = XLBorderStyleValues.Thin; currentCol += 3; var cellTotalOTHrs = worksheet.Cell(rowIndex, currentCol); cellTotalOTHrs.Value = "Total OT Hours"; ApplyHeaderStyle(cellTotalOTHrs, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellBreakMin = worksheet.Cell(rowIndex, currentCol); cellBreakMin.Value = "Break (min)"; ApplyHeaderStyle(cellBreakMin, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; if (showStationColumn) { var cellStation = worksheet.Cell(rowIndex, currentCol); cellStation.Value = "Station"; ApplyHeaderStyle(cellStation, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; } var cellDescription = worksheet.Cell(rowIndex, currentCol); cellDescription.Value = "Description"; ApplyHeaderStyle(cellDescription, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var headerRow1Range = worksheet.Range(startRowIndex, 1, startRowIndex, worksheet.LastColumnUsed().ColumnNumber()); headerRow1Range.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); headerRow1Range.Style.Border.InsideBorder = XLBorderStyleValues.Thin; rowIndex++; currentCol = 1; currentCol += 2; var cellOfficeFrom = worksheet.Cell(rowIndex, currentCol++); cellOfficeFrom.Value = "From"; ApplyHeaderStyle(cellOfficeFrom, 3); var cellOfficeTo = worksheet.Cell(rowIndex, currentCol++); cellOfficeTo.Value = "To"; ApplyHeaderStyle(cellOfficeTo, 3); var cellOfficeBreak = worksheet.Cell(rowIndex, currentCol++); cellOfficeBreak.Value = "Break"; ApplyHeaderStyle(cellOfficeBreak, 3); var cellAfterFrom = worksheet.Cell(rowIndex, currentCol++); cellAfterFrom.Value = "From"; ApplyHeaderStyle(cellAfterFrom, 3); var cellAfterTo = worksheet.Cell(rowIndex, currentCol++); cellAfterTo.Value = "To"; ApplyHeaderStyle(cellAfterTo, 3); var cellAfterBreak = worksheet.Cell(rowIndex, currentCol++); cellAfterBreak.Value = "Break"; ApplyHeaderStyle(cellAfterBreak, 3); currentCol += 2; if (showStationColumn) { currentCol++; } currentCol++; var headerRow2Range = worksheet.Range(rowIndex, 1, rowIndex, worksheet.LastColumnUsed().ColumnNumber()); headerRow2Range.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); headerRow2Range.Style.Border.InsideBorder = XLBorderStyleValues.Thin; rowIndex++; } private void ApplyHeaderStyle(IXLCell cell, int styleType) { cell.Style.Font.SetBold(); cell.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center; cell.Style.Alignment.Vertical = XLAlignmentVerticalValues.Center; cell.Style.Alignment.WrapText = true; cell.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); cell.Style.Border.InsideBorder = XLBorderStyleValues.Thin; switch (styleType) { case 1: cell.Style.Fill.BackgroundColor = XLColor.FromHtml("#78aafa"); cell.Style.Font.FontColor = XLColor.Black; break; case 2: cell.Style.Fill.BackgroundColor = XLColor.FromHtml("#DDEBF7"); cell.Style.Font.FontColor = XLColor.Black; break; case 3: cell.Style.Fill.BackgroundColor = XLColor.FromHtml("#C6E0B4"); cell.Style.Font.FontColor = XLColor.Black; break; case 4: cell.Style.Fill.BackgroundColor = XLColor.FromHtml("#F8CBAD"); cell.Style.Font.FontColor = XLColor.Black; break; case 5: cell.Style.Fill.BackgroundColor = XLColor.FromHtml("D8D1F5"); cell.Style.Font.FontColor = XLColor.Black; break; case 6: cell.Style.Fill.BackgroundColor = XLColor.FromHtml("#FF69B4"); cell.Style.Font.FontColor = XLColor.Black; break; default: cell.Style.Fill.BackgroundColor = XLColor.FromHtml("#A9D08E"); cell.Style.Font.FontColor = XLColor.Black; break; } } private void ApplyDayTypeStyle(IXLCell cell, DateTime date, int? weekendId, List publicHolidays) { uint styleIndex = GetDayCellColorStyleIndex(date, weekendId, publicHolidays); cell.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center; cell.Style.Alignment.Vertical = XLAlignmentVerticalValues.Center; cell.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); cell.Style.Border.InsideBorder = XLBorderStyleValues.Thin; switch (styleIndex) { case 18: cell.Style.Fill.BackgroundColor = XLColor.FromHtml("FFC0CB"); break; case 19: cell.Style.Fill.BackgroundColor = XLColor.FromHtml("ADD8E6"); break; default: cell.Style.Fill.BackgroundColor = XLColor.NoColor; break; } } private void AddNonHoUPSTWAirHeaders(IXLWorksheet worksheet, ref int rowIndex) { int startRowIndex = rowIndex; int currentCol = 1; currentCol = 1; var cellA = worksheet.Cell(rowIndex, currentCol); cellA.Value = "Basic Salary (RM)"; ApplyHeaderStyle(cellA, 6); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellB = worksheet.Cell(rowIndex, currentCol); cellB.Value = "ORP"; ApplyHeaderStyle(cellB, 6); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellC = worksheet.Cell(rowIndex, currentCol); cellC.Value = "HRP"; ApplyHeaderStyle(cellC, 6); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellD = worksheet.Cell(rowIndex, currentCol); cellD.Value = "Day"; ApplyHeaderStyle(cellD, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellE = worksheet.Cell(rowIndex, currentCol); cellE.Value = "Date"; ApplyHeaderStyle(cellE, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellF = worksheet.Cell(rowIndex, currentCol); cellF.Value = "Office Hour"; ApplyHeaderStyle(cellF, 2); var mergedRangeF = worksheet.Range(rowIndex, currentCol, rowIndex, currentCol + 2).Merge(); mergedRangeF.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); mergedRangeF.Style.Border.InsideBorder = XLBorderStyleValues.Thin; currentCol += 3; var cellI = worksheet.Cell(rowIndex, currentCol); cellI.Value = "After Office Hour"; ApplyHeaderStyle(cellI, 2); var mergedRangeI = worksheet.Range(rowIndex, currentCol, rowIndex, currentCol + 2).Merge(); mergedRangeI.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); mergedRangeI.Style.Border.InsideBorder = XLBorderStyleValues.Thin; currentCol += 3; var cellL = worksheet.Cell(rowIndex, currentCol); cellL.Value = "OT Hrs (Office Hour)"; ApplyHeaderStyle(cellL, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellM = worksheet.Cell(rowIndex, currentCol); cellM.Value = "OT Hrs (After Office Hour)"; ApplyHeaderStyle(cellM, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellN = worksheet.Cell(rowIndex, currentCol); cellN.Value = "Normal Day (After Office)"; ApplyHeaderStyle(cellN, 2); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellO = worksheet.Cell(rowIndex, currentCol); cellO.Value = "Off Day"; ApplyHeaderStyle(cellO, 2); var mergedRangeO = worksheet.Range(rowIndex, currentCol, rowIndex, currentCol + 2).Merge(); mergedRangeO.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); mergedRangeO.Style.Border.InsideBorder = XLBorderStyleValues.Thin; currentCol += 3; var cellR = worksheet.Cell(rowIndex, currentCol); cellR.Value = "Rest Day"; ApplyHeaderStyle(cellR, 2); var mergedRangeR = worksheet.Range(rowIndex, currentCol, rowIndex, currentCol + 2).Merge(); mergedRangeR.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); mergedRangeR.Style.Border.InsideBorder = XLBorderStyleValues.Thin; currentCol += 3; var cellU = worksheet.Cell(rowIndex, currentCol); cellU.Value = "Public Holiday"; ApplyHeaderStyle(cellU, 2); var mergedRangeU = worksheet.Range(rowIndex, currentCol, rowIndex, currentCol + 1).Merge(); mergedRangeU.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); mergedRangeU.Style.Border.InsideBorder = XLBorderStyleValues.Thin; currentCol += 2; var cellW = worksheet.Cell(rowIndex, currentCol); cellW.Value = "Total OT"; ApplyHeaderStyle(cellW, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellX = worksheet.Cell(rowIndex, currentCol); cellX.Value = "Total ND & OD"; ApplyHeaderStyle(cellX, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellY = worksheet.Cell(rowIndex, currentCol); cellY.Value = "Total RD"; ApplyHeaderStyle(cellY, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellZ = worksheet.Cell(rowIndex, currentCol); cellZ.Value = "Total PH"; ApplyHeaderStyle(cellZ, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellAA = worksheet.Cell(rowIndex, currentCol); cellAA.Value = "OT Amt (RM)"; ApplyHeaderStyle(cellAA, 6); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellAB = worksheet.Cell(rowIndex, currentCol); cellAB.Value = "Station"; ApplyHeaderStyle(cellAB, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellAC = worksheet.Cell(rowIndex, currentCol); cellAC.Value = "Description"; ApplyHeaderStyle(cellAC, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var headerRow1Range = worksheet.Range(startRowIndex, 1, startRowIndex, worksheet.LastColumnUsed().ColumnNumber()); headerRow1Range.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); headerRow1Range.Style.Border.InsideBorder = XLBorderStyleValues.Thin; rowIndex++; currentCol = 1; currentCol += 5; var cellF_sub = worksheet.Cell(rowIndex, currentCol++); cellF_sub.Value = "From"; ApplyHeaderStyle(cellF_sub, 3); var cellG_sub = worksheet.Cell(rowIndex, currentCol++); cellG_sub.Value = "To"; ApplyHeaderStyle(cellG_sub, 3); var cellH_sub = worksheet.Cell(rowIndex, currentCol++); cellH_sub.Value = "Break"; ApplyHeaderStyle(cellH_sub, 3); var cellI_sub = worksheet.Cell(rowIndex, currentCol++); cellI_sub.Value = "From"; ApplyHeaderStyle(cellI_sub, 3); var cellJ_sub = worksheet.Cell(rowIndex, currentCol++); cellJ_sub.Value = "To"; ApplyHeaderStyle(cellJ_sub, 3); var cellK_sub = worksheet.Cell(rowIndex, currentCol++); cellK_sub.Value = "Break"; ApplyHeaderStyle(cellK_sub, 3); currentCol += 2; var cellN_sub = worksheet.Cell(rowIndex, currentCol++); cellN_sub.Value = "ND OT"; ApplyHeaderStyle(cellN_sub, 3); var cellO_sub = worksheet.Cell(rowIndex, currentCol++); cellO_sub.Value = "OD < 4"; ApplyHeaderStyle(cellO_sub, 3); var cellP_sub = worksheet.Cell(rowIndex, currentCol++); cellP_sub.Value = "OD 4-8"; ApplyHeaderStyle(cellP_sub, 3); var cellQ_sub = worksheet.Cell(rowIndex, currentCol++); cellQ_sub.Value = "OD After"; ApplyHeaderStyle(cellQ_sub, 3); var cellR_sub = worksheet.Cell(rowIndex, currentCol++); cellR_sub.Value = "RD < 4"; ApplyHeaderStyle(cellR_sub, 3); var cellS_sub = worksheet.Cell(rowIndex, currentCol++); cellS_sub.Value = "RD 4-8"; ApplyHeaderStyle(cellS_sub, 3); var cellT_sub = worksheet.Cell(rowIndex, currentCol++); cellT_sub.Value = "RD After"; ApplyHeaderStyle(cellT_sub, 3); var cellU_sub = worksheet.Cell(rowIndex, currentCol++); cellU_sub.Value = "PH < 8"; ApplyHeaderStyle(cellU_sub, 3); var cellV_sub = worksheet.Cell(rowIndex, currentCol++); cellV_sub.Value = "PH After"; ApplyHeaderStyle(cellV_sub, 3); currentCol += 7; var headerRow2Range = worksheet.Range(rowIndex, 1, rowIndex, worksheet.LastColumnUsed().ColumnNumber()); headerRow2Range.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); headerRow2Range.Style.Border.InsideBorder = XLBorderStyleValues.Thin; rowIndex++; } private void AddNonHoUNonPSTWAirHeaders(IXLWorksheet worksheet, ref int rowIndex) { int startRowIndex = rowIndex; int currentCol; currentCol = 1; var cellA = worksheet.Cell(rowIndex, currentCol); cellA.Value = "Basic Salary (RM)"; ApplyHeaderStyle(cellA, 6); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellB = worksheet.Cell(rowIndex, currentCol); cellB.Value = "ORP"; ApplyHeaderStyle(cellB, 6); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellC = worksheet.Cell(rowIndex, currentCol); cellC.Value = "HRP"; ApplyHeaderStyle(cellC, 6); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellD = worksheet.Cell(rowIndex, currentCol); cellD.Value = "Day"; ApplyHeaderStyle(cellD, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellE = worksheet.Cell(rowIndex, currentCol); cellE.Value = "Date"; ApplyHeaderStyle(cellE, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellF = worksheet.Cell(rowIndex, currentCol); cellF.Value = "Office Hour"; ApplyHeaderStyle(cellF, 2); var mergedRangeF = worksheet.Range(rowIndex, currentCol, rowIndex, currentCol + 2).Merge(); mergedRangeF.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); mergedRangeF.Style.Border.InsideBorder = XLBorderStyleValues.Thin; currentCol += 3; var cellI = worksheet.Cell(rowIndex, currentCol); cellI.Value = "After Office Hour"; ApplyHeaderStyle(cellI, 2); var mergedRangeI = worksheet.Range(rowIndex, currentCol, rowIndex, currentCol + 2).Merge(); mergedRangeI.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); mergedRangeI.Style.Border.InsideBorder = XLBorderStyleValues.Thin; currentCol += 3; var cellL = worksheet.Cell(rowIndex, currentCol); cellL.Value = "OT Hrs (Office Hour)"; ApplyHeaderStyle(cellL, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellM = worksheet.Cell(rowIndex, currentCol); cellM.Value = "OT Hrs (After Office Hour)"; ApplyHeaderStyle(cellM, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellN = worksheet.Cell(rowIndex, currentCol); cellN.Value = "Normal Day (After Office)"; ApplyHeaderStyle(cellN, 2); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellO = worksheet.Cell(rowIndex, currentCol); cellO.Value = "Off Day"; ApplyHeaderStyle(cellO, 2); var mergedRangeO = worksheet.Range(rowIndex, currentCol, rowIndex, currentCol + 2).Merge(); mergedRangeO.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); mergedRangeO.Style.Border.InsideBorder = XLBorderStyleValues.Thin; currentCol += 3; var cellR = worksheet.Cell(rowIndex, currentCol); cellR.Value = "Rest Day"; ApplyHeaderStyle(cellR, 2); var mergedRangeR = worksheet.Range(rowIndex, currentCol, rowIndex, currentCol + 2).Merge(); mergedRangeR.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); mergedRangeR.Style.Border.InsideBorder = XLBorderStyleValues.Thin; currentCol += 3; var cellU = worksheet.Cell(rowIndex, currentCol); cellU.Value = "Public Holiday"; ApplyHeaderStyle(cellU, 2); var mergedRangeU = worksheet.Range(rowIndex, currentCol, rowIndex, currentCol + 1).Merge(); mergedRangeU.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); mergedRangeU.Style.Border.InsideBorder = XLBorderStyleValues.Thin; currentCol += 2; var cellW = worksheet.Cell(rowIndex, currentCol); cellW.Value = "Total OT"; ApplyHeaderStyle(cellW, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellX = worksheet.Cell(rowIndex, currentCol); cellX.Value = "Total ND & OD"; ApplyHeaderStyle(cellX, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellY = worksheet.Cell(rowIndex, currentCol); cellY.Value = "Total RD"; ApplyHeaderStyle(cellY, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellZ = worksheet.Cell(rowIndex, currentCol); cellZ.Value = "Total PH"; ApplyHeaderStyle(cellZ, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellAA = worksheet.Cell(rowIndex, currentCol); cellAA.Value = "OT Amt (RM)"; ApplyHeaderStyle(cellAA, 6); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellAB = worksheet.Cell(rowIndex, currentCol); cellAB.Value = "Description"; ApplyHeaderStyle(cellAB, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var headerRow1Range = worksheet.Range(startRowIndex, 1, startRowIndex, worksheet.LastColumnUsed().ColumnNumber()); headerRow1Range.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); headerRow1Range.Style.Border.InsideBorder = XLBorderStyleValues.Thin; rowIndex++; currentCol = 1; currentCol += 5; var cellF_sub = worksheet.Cell(rowIndex, currentCol++); cellF_sub.Value = "From"; ApplyHeaderStyle(cellF_sub, 3); var cellG_sub = worksheet.Cell(rowIndex, currentCol++); cellG_sub.Value = "To"; ApplyHeaderStyle(cellG_sub, 3); var cellH_sub = worksheet.Cell(rowIndex, currentCol++); cellH_sub.Value = "Break"; ApplyHeaderStyle(cellH_sub, 3); var cellI_sub = worksheet.Cell(rowIndex, currentCol++); cellI_sub.Value = "From"; ApplyHeaderStyle(cellI_sub, 3); var cellJ_sub = worksheet.Cell(rowIndex, currentCol++); cellJ_sub.Value = "To"; ApplyHeaderStyle(cellJ_sub, 3); var cellK_sub = worksheet.Cell(rowIndex, currentCol++); cellK_sub.Value = "Break"; ApplyHeaderStyle(cellK_sub, 3); currentCol += 2; var cellN_sub = worksheet.Cell(rowIndex, currentCol++); cellN_sub.Value = "ND OT"; ApplyHeaderStyle(cellN_sub, 3); var cellO_sub = worksheet.Cell(rowIndex, currentCol++); cellO_sub.Value = "OD < 4"; ApplyHeaderStyle(cellO_sub, 3); var cellP_sub = worksheet.Cell(rowIndex, currentCol++); cellP_sub.Value = "OD 4-8"; ApplyHeaderStyle(cellP_sub, 3); var cellQ_sub = worksheet.Cell(rowIndex, currentCol++); cellQ_sub.Value = "OD After"; ApplyHeaderStyle(cellQ_sub, 3); var cellR_sub = worksheet.Cell(rowIndex, currentCol++); cellR_sub.Value = "RD < 4"; ApplyHeaderStyle(cellR_sub, 3); var cellS_sub = worksheet.Cell(rowIndex, currentCol++); cellS_sub.Value = "RD 4-8"; ApplyHeaderStyle(cellS_sub, 3); var cellT_sub = worksheet.Cell(rowIndex, currentCol++); cellT_sub.Value = "RD After"; ApplyHeaderStyle(cellT_sub, 3); var cellU_sub = worksheet.Cell(rowIndex, currentCol++); cellU_sub.Value = "PH < 8"; ApplyHeaderStyle(cellU_sub, 3); var cellV_sub = worksheet.Cell(rowIndex, currentCol++); cellV_sub.Value = "PH After"; ApplyHeaderStyle(cellV_sub, 3); currentCol += 6; var headerRow2Range = worksheet.Range(rowIndex, 1, rowIndex, worksheet.LastColumnUsed().ColumnNumber()); headerRow2Range.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); headerRow2Range.Style.Border.InsideBorder = XLBorderStyleValues.Thin; rowIndex++; } private void AddHoUPSTWAirHeaders(IXLWorksheet worksheet, ref int rowIndex) { int startRowIndex = rowIndex; int currentCol = 1; currentCol = 1; var cellA = worksheet.Cell(rowIndex, currentCol); cellA.Value = "Day"; ApplyHeaderStyle(cellA, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellB = worksheet.Cell(rowIndex, currentCol); cellB.Value = "Date"; ApplyHeaderStyle(cellB, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellC = worksheet.Cell(rowIndex, currentCol); cellC.Value = "Office Hour"; ApplyHeaderStyle(cellC, 2); var mergedRangeC = worksheet.Range(rowIndex, currentCol, rowIndex, currentCol + 2).Merge(); mergedRangeC.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); mergedRangeC.Style.Border.InsideBorder = XLBorderStyleValues.Thin; currentCol += 3; var cellF = worksheet.Cell(rowIndex, currentCol); cellF.Value = "After Office Hour"; ApplyHeaderStyle(cellF, 2); var mergedRangeF = worksheet.Range(rowIndex, currentCol, rowIndex, currentCol + 2).Merge(); mergedRangeF.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); mergedRangeF.Style.Border.InsideBorder = XLBorderStyleValues.Thin; currentCol += 3; var cellI = worksheet.Cell(rowIndex, currentCol); cellI.Value = "OT Hrs (Office Hour)"; ApplyHeaderStyle(cellI, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellJ = worksheet.Cell(rowIndex, currentCol); cellJ.Value = "OT Hrs (After Office Hour)"; ApplyHeaderStyle(cellJ, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellK = worksheet.Cell(rowIndex, currentCol); cellK.Value = "Normal Day (After Office)"; ApplyHeaderStyle(cellK, 2); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellL = worksheet.Cell(rowIndex, currentCol); cellL.Value = "Off Day"; ApplyHeaderStyle(cellL, 2); var mergedRangeL = worksheet.Range(rowIndex, currentCol, rowIndex, currentCol + 2).Merge(); mergedRangeL.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); mergedRangeL.Style.Border.InsideBorder = XLBorderStyleValues.Thin; currentCol += 3; var cellO = worksheet.Cell(rowIndex, currentCol); cellO.Value = "Rest Day"; ApplyHeaderStyle(cellO, 2); var mergedRangeO = worksheet.Range(rowIndex, currentCol, rowIndex, currentCol + 2).Merge(); mergedRangeO.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); mergedRangeO.Style.Border.InsideBorder = XLBorderStyleValues.Thin; currentCol += 3; var cellR = worksheet.Cell(rowIndex, currentCol); cellR.Value = "Public Holiday"; ApplyHeaderStyle(cellR, 2); var mergedRangeR = worksheet.Range(rowIndex, currentCol, rowIndex, currentCol + 1).Merge(); mergedRangeR.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); mergedRangeR.Style.Border.InsideBorder = XLBorderStyleValues.Thin; currentCol += 2; var cellT = worksheet.Cell(rowIndex, currentCol); cellT.Value = "Total OT"; ApplyHeaderStyle(cellT, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellU = worksheet.Cell(rowIndex, currentCol); cellU.Value = "Total ND & OD"; ApplyHeaderStyle(cellU, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellV = worksheet.Cell(rowIndex, currentCol); cellV.Value = "Total RD"; ApplyHeaderStyle(cellV, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellW = worksheet.Cell(rowIndex, currentCol); cellW.Value = "Total PH"; ApplyHeaderStyle(cellW, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellX = worksheet.Cell(rowIndex, currentCol); cellX.Value = "Station"; ApplyHeaderStyle(cellX, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellY = worksheet.Cell(rowIndex, currentCol); cellY.Value = "Description"; ApplyHeaderStyle(cellY, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var headerRow1Range = worksheet.Range(startRowIndex, 1, startRowIndex, worksheet.LastColumnUsed().ColumnNumber()); headerRow1Range.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); headerRow1Range.Style.Border.InsideBorder = XLBorderStyleValues.Thin; rowIndex++; currentCol = 1; currentCol += 2; var cellC_sub = worksheet.Cell(rowIndex, currentCol++); cellC_sub.Value = "From"; ApplyHeaderStyle(cellC_sub, 3); var cellD_sub = worksheet.Cell(rowIndex, currentCol++); cellD_sub.Value = "To"; ApplyHeaderStyle(cellD_sub, 3); var cellE_sub = worksheet.Cell(rowIndex, currentCol++); cellE_sub.Value = "Break"; ApplyHeaderStyle(cellE_sub, 3); var cellF_sub = worksheet.Cell(rowIndex, currentCol++); cellF_sub.Value = "From"; ApplyHeaderStyle(cellF_sub, 3); var cellG_sub = worksheet.Cell(rowIndex, currentCol++); cellG_sub.Value = "To"; ApplyHeaderStyle(cellG_sub, 3); var cellH_sub = worksheet.Cell(rowIndex, currentCol++); cellH_sub.Value = "Break"; ApplyHeaderStyle(cellH_sub, 3); currentCol += 2; var cellK_sub = worksheet.Cell(rowIndex, currentCol++); cellK_sub.Value = "ND OT"; ApplyHeaderStyle(cellK_sub, 3); var cellL_sub = worksheet.Cell(rowIndex, currentCol++); cellL_sub.Value = "OD < 4"; ApplyHeaderStyle(cellL_sub, 3); var cellM_sub = worksheet.Cell(rowIndex, currentCol++); cellM_sub.Value = "OD 4-8"; ApplyHeaderStyle(cellM_sub, 3); var cellN_sub = worksheet.Cell(rowIndex, currentCol++); cellN_sub.Value = "OD After"; ApplyHeaderStyle(cellN_sub, 3); var cellO_sub = worksheet.Cell(rowIndex, currentCol++); cellO_sub.Value = "RD < 4"; ApplyHeaderStyle(cellO_sub, 3); var cellP_sub = worksheet.Cell(rowIndex, currentCol++); cellP_sub.Value = "RD 4-8"; ApplyHeaderStyle(cellP_sub, 3); var cellQ_sub = worksheet.Cell(rowIndex, currentCol++); cellQ_sub.Value = "RD After"; ApplyHeaderStyle(cellQ_sub, 3); var cellR_sub = worksheet.Cell(rowIndex, currentCol++); cellR_sub.Value = "PH < 8"; ApplyHeaderStyle(cellR_sub, 3); var cellS_sub = worksheet.Cell(rowIndex, currentCol++); cellS_sub.Value = "PH After"; ApplyHeaderStyle(cellS_sub, 3); currentCol += 5; var headerRow2Range = worksheet.Range(rowIndex, 1, rowIndex, worksheet.LastColumnUsed().ColumnNumber()); headerRow2Range.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); headerRow2Range.Style.Border.InsideBorder = XLBorderStyleValues.Thin; rowIndex++; } private void AddHoUNonPSTWAirHeaders(IXLWorksheet worksheet, ref int rowIndex) { int startRowIndex = rowIndex; int currentCol; currentCol = 1; var cellA = worksheet.Cell(rowIndex, currentCol); cellA.Value = "Day"; ApplyHeaderStyle(cellA, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellB = worksheet.Cell(rowIndex, currentCol); cellB.Value = "Date"; ApplyHeaderStyle(cellB, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellC = worksheet.Cell(rowIndex, currentCol); cellC.Value = "Office Hour"; ApplyHeaderStyle(cellC, 2); var mergedRangeC = worksheet.Range(rowIndex, currentCol, rowIndex, currentCol + 2).Merge(); mergedRangeC.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); mergedRangeC.Style.Border.InsideBorder = XLBorderStyleValues.Thin; currentCol += 3; var cellF = worksheet.Cell(rowIndex, currentCol); cellF.Value = "After Office Hour"; ApplyHeaderStyle(cellF, 2); var mergedRangeF = worksheet.Range(rowIndex, currentCol, rowIndex, currentCol + 2).Merge(); mergedRangeF.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); mergedRangeF.Style.Border.InsideBorder = XLBorderStyleValues.Thin; currentCol += 3; var cellI = worksheet.Cell(rowIndex, currentCol); cellI.Value = "OT Hrs (Office Hour)"; ApplyHeaderStyle(cellI, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellJ = worksheet.Cell(rowIndex, currentCol); cellJ.Value = "OT Hrs (After Office Hour)"; ApplyHeaderStyle(cellJ, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellK = worksheet.Cell(rowIndex, currentCol); cellK.Value = "Normal Day (After Office)"; ApplyHeaderStyle(cellK, 2); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellL = worksheet.Cell(rowIndex, currentCol); cellL.Value = "Off Day"; ApplyHeaderStyle(cellL, 2); var mergedRangeL = worksheet.Range(rowIndex, currentCol, rowIndex, currentCol + 2).Merge(); mergedRangeL.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); mergedRangeL.Style.Border.InsideBorder = XLBorderStyleValues.Thin; currentCol += 3; var cellO = worksheet.Cell(rowIndex, currentCol); cellO.Value = "Rest Day"; ApplyHeaderStyle(cellO, 2); var mergedRangeO = worksheet.Range(rowIndex, currentCol, rowIndex, currentCol + 2).Merge(); mergedRangeO.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); mergedRangeO.Style.Border.InsideBorder = XLBorderStyleValues.Thin; currentCol += 3; var cellR = worksheet.Cell(rowIndex, currentCol); cellR.Value = "Public Holiday"; ApplyHeaderStyle(cellR, 2); var mergedRangeR = worksheet.Range(rowIndex, currentCol, rowIndex, currentCol + 1).Merge(); mergedRangeR.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); mergedRangeR.Style.Border.InsideBorder = XLBorderStyleValues.Thin; currentCol += 2; var cellT = worksheet.Cell(rowIndex, currentCol); cellT.Value = "Total OT"; ApplyHeaderStyle(cellT, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellU = worksheet.Cell(rowIndex, currentCol); cellU.Value = "Total ND & OD"; ApplyHeaderStyle(cellU, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellV = worksheet.Cell(rowIndex, currentCol); cellV.Value = "Total RD"; ApplyHeaderStyle(cellV, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellW = worksheet.Cell(rowIndex, currentCol); cellW.Value = "Total PH"; ApplyHeaderStyle(cellW, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var cellX = worksheet.Cell(rowIndex, currentCol); cellX.Value = "Description"; ApplyHeaderStyle(cellX, 1); worksheet.Range(rowIndex, currentCol, rowIndex + 1, currentCol).Merge(); currentCol++; var headerRow1Range = worksheet.Range(startRowIndex, 1, startRowIndex, worksheet.LastColumnUsed().ColumnNumber()); headerRow1Range.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); headerRow1Range.Style.Border.InsideBorder = XLBorderStyleValues.Thin; rowIndex++; currentCol = 1; currentCol += 2; var cellC_sub = worksheet.Cell(rowIndex, currentCol++); cellC_sub.Value = "From"; ApplyHeaderStyle(cellC_sub, 3); var cellD_sub = worksheet.Cell(rowIndex, currentCol++); cellD_sub.Value = "To"; ApplyHeaderStyle(cellD_sub, 3); var cellE_sub = worksheet.Cell(rowIndex, currentCol++); cellE_sub.Value = "Break"; ApplyHeaderStyle(cellE_sub, 3); var cellF_sub = worksheet.Cell(rowIndex, currentCol++); cellF_sub.Value = "From"; ApplyHeaderStyle(cellF_sub, 3); var cellG_sub = worksheet.Cell(rowIndex, currentCol++); cellG_sub.Value = "To"; ApplyHeaderStyle(cellG_sub, 3); var cellH_sub = worksheet.Cell(rowIndex, currentCol++); cellH_sub.Value = "Break"; ApplyHeaderStyle(cellH_sub, 3); currentCol += 2; var cellK_sub = worksheet.Cell(rowIndex, currentCol++); cellK_sub.Value = "ND OT"; ApplyHeaderStyle(cellK_sub, 3); var cellL_sub = worksheet.Cell(rowIndex, currentCol++); cellL_sub.Value = "OD < 4"; ApplyHeaderStyle(cellL_sub, 3); var cellM_sub = worksheet.Cell(rowIndex, currentCol++); cellM_sub.Value = "OD 4-8"; ApplyHeaderStyle(cellM_sub, 3); var cellN_sub = worksheet.Cell(rowIndex, currentCol++); cellN_sub.Value = "OD After"; ApplyHeaderStyle(cellN_sub, 3); var cellO_sub = worksheet.Cell(rowIndex, currentCol++); cellO_sub.Value = "RD < 4"; ApplyHeaderStyle(cellO_sub, 3); var cellP_sub = worksheet.Cell(rowIndex, currentCol++); cellP_sub.Value = "RD 4-8"; ApplyHeaderStyle(cellP_sub, 3); var cellQ_sub = worksheet.Cell(rowIndex, currentCol++); cellQ_sub.Value = "RD After"; ApplyHeaderStyle(cellQ_sub, 3); var cellR_sub = worksheet.Cell(rowIndex, currentCol++); cellR_sub.Value = "PH < 8"; ApplyHeaderStyle(cellR_sub, 3); var cellS_sub = worksheet.Cell(rowIndex, currentCol++); cellS_sub.Value = "PH After"; ApplyHeaderStyle(cellS_sub, 3); currentCol += 4; var headerRow2Range = worksheet.Range(rowIndex, 1, rowIndex, worksheet.LastColumnUsed().ColumnNumber()); headerRow2Range.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); headerRow2Range.Style.Border.InsideBorder = XLBorderStyleValues.Thin; rowIndex++; } private uint GetDayCellColorStyleIndex(DateTime date, int? weekendId, List publicHolidays) { if (publicHolidays.Contains(date.Date)) return 18; DayOfWeek dayOfWeek = date.DayOfWeek; if ((weekendId == 1 && (dayOfWeek == DayOfWeek.Friday || dayOfWeek == DayOfWeek.Saturday)) || (weekendId == 2 && (dayOfWeek == DayOfWeek.Saturday || dayOfWeek == DayOfWeek.Sunday))) return 19; return 11; } private bool IsAdmin(int userId) { var userRoles = _centralDbContext.UserRoles .Where(ur => ur.UserId == userId) .Join(_centralDbContext.Roles, ur => ur.RoleId, r => r.Id, (ur, r) => r.Name) .ToList(); return userRoles.Any(role => role.Contains("SuperAdmin") || role.Contains("SystemAdmin")); } private List GetAllDatesInMonth(DateTime month) { return Enumerable.Range(1, DateTime.DaysInMonth(month.Year, month.Month)) .Select(day => new DateTime(month.Year, month.Month, day)) .ToList(); } private string GetDayType(DateTime date, int? weekendId, List publicHolidays) { if (publicHolidays.Contains(date.Date)) { return "Public Holiday"; } DayOfWeek dayOfWeek = date.DayOfWeek; if ((weekendId == 1 && (dayOfWeek == DayOfWeek.Friday || dayOfWeek == DayOfWeek.Saturday)) || (weekendId == 2 && (dayOfWeek == DayOfWeek.Saturday || dayOfWeek == DayOfWeek.Sunday))) { if ((weekendId == 1 && dayOfWeek == DayOfWeek.Friday) || (weekendId == 2 && dayOfWeek == DayOfWeek.Saturday)) { return "Off Day"; } if ((weekendId == 1 && dayOfWeek == DayOfWeek.Saturday) || (weekendId == 2 && dayOfWeek == DayOfWeek.Sunday)) { return "Rest Day"; } } return "Normal Day"; } // ORP = Basic Salary / 26 private decimal CalculateOrp(decimal basicSalary) { return basicSalary / 26m; } // HRP = ORP / 8 private decimal CalculateHrp(decimal orp) { return orp / 8m; } private string FormatAsHourMinute(decimal? totalMinutes, bool isMinutes = false) { if (totalMinutes == null || totalMinutes == 0) return ""; TimeSpan ts; if (isMinutes) { ts = TimeSpan.FromMinutes((double)totalMinutes.Value); } else { ts = TimeSpan.FromMinutes((double)(totalMinutes.Value * 60)); } if (ts.TotalMinutes < 0) { return $"-{Math.Abs((int)ts.TotalHours)}:{Math.Abs(ts.Minutes):D2}"; } int hours = (int)ts.TotalHours; int minutes = ts.Minutes; return $"{hours}:{minutes:D2}"; } private decimal ConvertTimeToDecimal(string time) { if (string.IsNullOrEmpty(time)) return 0; var parts = time.Split(':'); if (parts.Length != 2) return 0; if (int.TryParse(parts[0], out int hours) && int.TryParse(parts[1], out int minutes)) { return hours + (minutes / 60m); } return 0; } private decimal CalculateTimeDifferenceInMinutes(TimeSpan? from, TimeSpan? to) { if (!from.HasValue || !to.HasValue) return 0; double fromTotalMinutes = from.Value.TotalMinutes; double toTotalMinutes = to.Value.TotalMinutes; double totalMinutes = toTotalMinutes - fromTotalMinutes; if (totalMinutes < 0) { totalMinutes += 24 * 60; } return (decimal)Math.Max(0, totalMinutes); } private string CalculateOfficeOtHours(OtRegisterModel record) { if (!record.OfficeFrom.HasValue || !record.OfficeTo.HasValue) return ""; var duration = record.OfficeTo.Value - record.OfficeFrom.Value; var totalMinutes = duration.TotalMinutes - (record.OfficeBreak ?? 0); totalMinutes = Math.Max(0, totalMinutes); int hours = (int)(totalMinutes / 60); int minutes = (int)(totalMinutes % 60); return $"{hours}:{minutes:D2}"; } private string CalculateAfterOfficeOtHours(OtRegisterModel record) { if (!record.AfterFrom.HasValue || !record.AfterTo.HasValue) return ""; var duration = record.AfterTo.Value - record.AfterFrom.Value; var totalMinutes = duration.TotalMinutes - (record.AfterBreak ?? 0); totalMinutes = Math.Max(0, totalMinutes); int hours = (int)(totalMinutes / 60); int minutes = (int)(totalMinutes % 60); return $"{hours}:{minutes:D2}"; } private Dictionary ClassifyOt(OtRegisterModel record, decimal hrp, List publicHolidays, int? weekendId) { var officeRaw = CalculateOfficeOtHours(record); var afterRaw = CalculateAfterOfficeOtHours(record); var officeHrs = ConvertTimeToDecimal(officeRaw); var afterHrs = ConvertTimeToDecimal(afterRaw); var toFixedOrEmpty = (decimal num) => num > 0 ? num.ToString("N2") : ""; var dayType = GetDayType(record.OtDate, weekendId, publicHolidays); var result = new Dictionary { ["ndAfter"] = "", ["odUnder4"] = "", ["odBetween4And8"] = "", ["odAfter"] = "", ["rdUnder4"] = "", ["rdBetween4And8"] = "", ["rdAfter"] = "", ["phUnder8"] = "", ["phAfter"] = "" }; switch (dayType) { case "Normal Day": result["ndAfter"] = toFixedOrEmpty(afterHrs); break; case "Off Day": if (officeHrs > 0) { if (officeHrs <= 4) result["odUnder4"] = toFixedOrEmpty(officeHrs); else if (officeHrs > 4 && officeHrs <= 8) result["odBetween4And8"] = toFixedOrEmpty(officeHrs); } result["odAfter"] = toFixedOrEmpty(afterHrs); break; case "Rest Day": if (officeHrs > 0) { if (officeHrs <= 4) result["rdUnder4"] = toFixedOrEmpty(officeHrs); else if (officeHrs > 4 && officeHrs <= 8) result["rdBetween4And8"] = toFixedOrEmpty(officeHrs); } result["rdAfter"] = toFixedOrEmpty(afterHrs); break; case "Public Holiday": if (officeHrs > 0) { if (officeHrs <= 8) result["phUnder8"] = toFixedOrEmpty(officeHrs); } result["phAfter"] = toFixedOrEmpty(afterHrs); break; } return result; } private string CalculateTotalOtHrs(OtRegisterModel record, decimal hrp, List publicHolidays, int? weekendId) { var classified = ClassifyOt(record, hrp, publicHolidays, weekendId); decimal total = 0; foreach (var value in classified.Values) { if (decimal.TryParse(value, out decimal num)) { total += num; } } return total > 0 ? total.ToString("N2") : ""; } private string CalculateNdOdTotal(OtRegisterModel record, decimal hrp, List publicHolidays, int? weekendId) { var classified = ClassifyOt(record, hrp, publicHolidays, weekendId); var nd = decimal.TryParse(classified["ndAfter"], out decimal ndVal) ? ndVal : 0; var od1 = decimal.TryParse(classified["odUnder4"], out decimal od1Val) ? od1Val : 0; var od2 = decimal.TryParse(classified["odBetween4And8"], out decimal od2Val) ? od2Val : 0; var od3 = decimal.TryParse(classified["odAfter"], out decimal od3Val) ? od3Val : 0; var total = nd + od1 + od2 + od3; return total > 0 ? total.ToString("N2") : ""; } private string CalculateRdTotal(OtRegisterModel record, decimal hrp, List publicHolidays, int? weekendId) { var classified = ClassifyOt(record, hrp, publicHolidays, weekendId); var total = (decimal.TryParse(classified["rdUnder4"], out decimal rd1) ? rd1 : 0) + (decimal.TryParse(classified["rdBetween4And8"], out decimal rd2) ? rd2 : 0) + (decimal.TryParse(classified["rdAfter"], out decimal rd3) ? rd3 : 0); return total > 0 ? total.ToString("N2") : ""; } private string CalculatePhTotal(OtRegisterModel record, decimal hrp, List publicHolidays, int? weekendId) { var classified = ClassifyOt(record, hrp, publicHolidays, weekendId); var total = (decimal.TryParse(classified["phUnder8"], out decimal ph1) ? ph1 : 0) + (decimal.TryParse(classified["phAfter"], out decimal ph2) ? ph2 : 0); return total > 0 ? total.ToString("N2") : ""; } private string CalculateOtAmount(OtRegisterModel record, decimal hrp, List publicHolidays, int? weekendId) { var orp = CalculateOrp(hrp * 208); var dayType = GetDayType(record.OtDate, weekendId, publicHolidays); var officeRaw = CalculateOfficeOtHours(record); var afterRaw = CalculateAfterOfficeOtHours(record); var officeHours = ConvertTimeToDecimal(officeRaw); var afterOfficeHours = ConvertTimeToDecimal(afterRaw); decimal amountOffice = 0; decimal amountAfter = 0; if (officeHours > 0) { if (dayType == "Off Day" || dayType == "Rest Day") { if (officeHours <= 4) { amountOffice = 0.5m * orp; } else if (officeHours > 4 && officeHours <= 8) { amountOffice = 1 * orp; } } else if (dayType == "Public Holiday") { amountOffice = 2 * orp; } } if (afterOfficeHours > 0) { switch (dayType) { case "Normal Day": case "Off Day": amountAfter = 1.5m * hrp * afterOfficeHours; break; case "Rest Day": amountAfter = 2 * hrp * afterOfficeHours; break; case "Public Holiday": amountAfter = 3 * hrp * afterOfficeHours; break; } } var totalAmount = amountOffice + amountAfter; return totalAmount.ToString("N2"); } private void AddRemarksSection(IXLWorksheet worksheet, ref int currentRow, DateTime displayMonth, int? weekendId, List publicHolidays) { int remarksStartColumn = 1; int remarksRow = currentRow + 1; var phColorCell = worksheet.Cell(remarksRow, remarksStartColumn); phColorCell.Value = " "; phColorCell.Style.Fill.BackgroundColor = XLColor.FromHtml("FFC0CB"); phColorCell.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); worksheet.Cell(remarksRow, remarksStartColumn + 1).Value = " Public Holiday"; worksheet.Cell(remarksRow, remarksStartColumn + 1).Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Left; remarksRow++; var weekendColorCell = worksheet.Cell(remarksRow, remarksStartColumn); weekendColorCell.Value = " "; weekendColorCell.Style.Fill.BackgroundColor = XLColor.FromHtml("ADD8E6"); weekendColorCell.Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin); worksheet.Cell(remarksRow, remarksStartColumn + 1).Value = " Weekend"; worksheet.Cell(remarksRow, remarksStartColumn + 1).Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Left; remarksRow++; remarksRow++; worksheet.Cell(remarksRow, remarksStartColumn).Value = $"Public Holidays in {displayMonth:MMMM yyyy}:"; worksheet.Cell(remarksRow, remarksStartColumn).Style.Font.SetBold(); remarksRow++; if (publicHolidays != null && publicHolidays.Any()) { var monthHolidays = publicHolidays .Where(h => h.HolidayDate.Year == displayMonth.Year && h.HolidayDate.Month == displayMonth.Month) .OrderBy(h => h.HolidayDate.Day) .ToList(); if (monthHolidays.Any()) { foreach (var holiday in monthHolidays) { worksheet.Cell(remarksRow, remarksStartColumn).Value = $"- {holiday.HolidayDate:dd MMMM}: {holiday.HolidayName}"; worksheet.Cell(remarksRow, remarksStartColumn).Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Left; remarksRow++; } } else { worksheet.Cell(remarksRow, remarksStartColumn).Value = "No public holidays recorded for this month."; worksheet.Cell(remarksRow, remarksStartColumn).Style.Font.SetItalic(); remarksRow++; } } else { worksheet.Cell(remarksRow, remarksStartColumn).Value = "No public holiday data found."; worksheet.Cell(remarksRow, remarksStartColumn).Style.Font.SetItalic(); remarksRow++; } currentRow = remarksRow; } private string GetWeekendDefinition(int? weekendId) { if (!weekendId.HasValue) return "N/A"; switch (weekendId) { case 1: return "Friday & Saturday"; case 2: return "Saturday & Sunday"; default: return "Unknown"; } } } }