Untitled
unknown
plain_text
9 months ago
9.4 kB
6
Indexable
public class ExcelUtility
{
// ... (keep all existing code) ...
public byte[] ExportToExcel(IEnumerable<BookingOrderVM> orders, IEnumerable<TruckType> truckTypes, string uom)
{
using (var workbook = new XLWorkbook())
{
var worksheet = workbook.Worksheets.Add("Booking Portal");
var currentRow = 1;
var dropdownSheet = workbook.Worksheets.Add("Dropdowns");
CreateDropdownLists(dropdownSheet, truckTypes);
// Add a hidden helper sheet for tracking row configurations
var helperSheet = workbook.Worksheets.Add("RowConfig");
helperSheet.Hide();
AddHeaders(worksheet, ref currentRow, true, uom);
worksheet.Row(1).Style.Protection.SetLocked(true);
foreach (var order in orders)
{
var orderStartRow = currentRow;
AddDispatchRow(worksheet, ref currentRow, order, uom);
worksheet.Row(orderStartRow).Style.Protection.SetLocked(true);
// Store order start row in helper sheet
helperSheet.Cell(orderStartRow, 1).Value = "OrderStart";
AddHeaders(worksheet, ref currentRow, false, uom);
worksheet.Row(currentRow - 1).Style.Protection.SetLocked(true);
foreach (var booking in order.Bookings)
{
AddBookingRow(worksheet, ref currentRow, booking, uom, orderStartRow);
// Mark booking rows in helper sheet
helperSheet.Cell(currentRow - 1, 1).Value = "Booking";
helperSheet.Cell(currentRow - 1, 2).Value = orderStartRow;
}
for (int i = 0; i < 3; i++)
{
AddBookingRow(worksheet, ref currentRow, new Booking(), uom, orderStartRow);
// Mark empty booking rows in helper sheet
helperSheet.Cell(currentRow - 1, 1).Value = "Booking";
helperSheet.Cell(currentRow - 1, 2).Value = orderStartRow;
}
// Add the button row before remaining row
AddButtonRow(worksheet, ref currentRow, orderStartRow);
AddRemainingRow(worksheet, ref currentRow, orderStartRow, uom);
worksheet.Row(currentRow - 1).Style.Protection.SetLocked(true);
// Mark remaining row in helper sheet
helperSheet.Cell(currentRow - 1, 1).Value = "Remaining";
helperSheet.Cell(currentRow - 1, 2).Value = orderStartRow;
currentRow++;
}
// Add worksheet change event handling formula
AddWorksheetChangeHandler(worksheet, helperSheet);
AddDropdowns(worksheet, truckTypes);
worksheet.Columns().AdjustToContents();
// Modify protection to allow using formulas
worksheet.Protect()
.AllowElement(XLSheetProtectionElements.SelectLockedCells)
.AllowElement(XLSheetProtectionElements.SelectUnlockedCells)
.AllowElement(XLSheetProtectionElements.FormatCells)
.AllowElement(XLSheetProtectionElements.InsertRows)
.AllowElement(XLSheetProtectionElements.DeleteRows)
.AllowElement(XLSheetProtectionElements.UseAutoFilter)
.AllowElement(XLSheetProtectionElements.Sort)
.AllowElement(XLSheetProtectionElements.UsePivotTables);
using (var stream = new MemoryStream())
{
workbook.SaveAs(stream);
return stream.ToArray();
}
}
}
private void AddButtonRow(IXLWorksheet worksheet, ref int currentRow, int orderStartRow)
{
var addButtonCell = worksheet.Cell(currentRow, 1);
addButtonCell.Value = "➕ Add Row";
addButtonCell.Style.Fill.BackgroundColor = XLColor.FromArgb(200, 230, 201);
addButtonCell.Style.Border.OutsideBorder = XLBorderStyleValues.Thin;
addButtonCell.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
addButtonCell.Style.Font.Bold = true;
var comment = addButtonCell.CreateComment();
comment.AddText("To add a new row:");
comment.AddNewLine();
comment.AddText("1. Select this row");
comment.AddNewLine();
comment.AddText("2. Right-click → Insert → Copy formulas from above");
worksheet.Range(currentRow, 1, currentRow, 3).Merge();
var deleteInstructionCell = worksheet.Cell(currentRow, 4);
deleteInstructionCell.Value = "✖ Delete: Select row → Right-click → Delete";
deleteInstructionCell.Style.Fill.BackgroundColor = XLColor.FromArgb(255, 205, 210);
deleteInstructionCell.Style.Border.OutsideBorder = XLBorderStyleValues.Thin;
deleteInstructionCell.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
deleteInstructionCell.Style.Font.Bold = true;
worksheet.Range(currentRow, 4, currentRow, 7).Merge();
currentRow++;
}
private void AddWorksheetChangeHandler(IXLWorksheet worksheet, IXLWorksheet helperSheet)
{
// Add a named range for the entire used range
var usedRange = worksheet.RangeUsed();
worksheet.Workbook.NamedRanges.Add("UsedRange", usedRange);
// Add a worksheet-level formula to detect changes
var formulaCell = worksheet.Cell(1, worksheet.ColumnCount() + 1);
formulaCell.FormulaA1 = "=IF(ROW()>1,INDIRECT(\"RC[-1]\",FALSE),\"\")";
formulaCell.Style.Protection.SetLocked(true);
// Add helper formulas for row operations
var helperFormula = helperSheet.Cell(1, 3);
helperFormula.FormulaA1 = "=COUNTA(UsedRange)";
// Add auto-configuration formula for new rows
for (int row = 2; row <= usedRange.RowCount(); row++)
{
var configCell = helperSheet.Cell(row, 3);
configCell.FormulaA1 = $"=IF(AND(ROW()>1,INDIRECT(\"A\"&ROW())=\"Booking\"),ConfigureNewRow(ROW()),\"\")";
}
}
// Helper function to configure new rows (called by Excel formulas)
private string ConfigureNewRow(int row)
{
var worksheet = (IXLWorksheet)Workbook.Worksheet("Booking Portal");
var helperSheet = (IXLWorksheet)Workbook.Worksheet("RowConfig");
// Get order start row from helper sheet
var orderStartRow = int.Parse(helperSheet.Cell(row, 2).Value.ToString());
// Copy validations and formulas from row above
CopyRowConfiguration(worksheet, row - 1, row, orderStartRow);
return "Configured";
}
private void CopyRowConfiguration(IXLWorksheet worksheet, int sourceRow, int targetRow, int orderStartRow)
{
// Copy data validation
CopyDataValidation(worksheet.Row(sourceRow), worksheet.Row(targetRow));
// Copy formulas and formatting
CopyFormulasAndFormatting(worksheet.Row(sourceRow), worksheet.Row(targetRow));
// Update remaining calculations
UpdateRemainingCalculations(worksheet, targetRow, orderStartRow);
}
private void CopyDataValidation(IXLRow sourceRow, IXLRow targetRow)
{
// Trip dropdown
var tripValidation = targetRow.Cell(3).SetDataValidation();
tripValidation.List("=TripNumbers");
// Truck type dropdown
var truckTypeValidation = targetRow.Cell(4).SetDataValidation();
truckTypeValidation.List("=TruckTypes");
// Time picker
var timeValidation = targetRow.Cell(5).SetDataValidation();
timeValidation.List("=TimePicker");
targetRow.Cell(5).Style.NumberFormat.Format = "HH:mm";
}
private void CopyFormulasAndFormatting(IXLRow sourceRow, IXLRow targetRow)
{
for (int col = 1; col <= sourceRow.Worksheet.ColumnCount(); col++)
{
var sourceCell = sourceRow.Cell(col);
var targetCell = targetRow.Cell(col);
if (sourceCell.HasFormula)
{
targetCell.FormulaA1 = sourceCell.FormulaA1;
}
targetCell.Style = sourceCell.Style;
}
}
private void UpdateRemainingCalculations(IXLWorksheet worksheet, int row, int orderStartRow)
{
// Update the remaining row calculations
var remainingRow = FindRemainingRow(worksheet, orderStartRow);
if (remainingRow > 0)
{
UpdateRemainingRowFormulas(worksheet, remainingRow, orderStartRow);
}
}
private int FindRemainingRow(IXLWorksheet worksheet, int orderStartRow)
{
var currentRow = orderStartRow + 1;
while (!worksheet.Row(currentRow).IsEmpty())
{
if (worksheet.Cell(currentRow, 1).Value.ToString() == "Remaining")
{
return currentRow;
}
currentRow++;
}
return -1;
}
// ... (keep rest of existing code) ...
}Editor is loading...
Leave a Comment