Skip to content

Commit 8d86a2c

Browse files
committed
Fixing excel download.
1 parent c22800d commit 8d86a2c

File tree

2 files changed

+239
-120
lines changed

2 files changed

+239
-120
lines changed

eFormAPI/Plugins/BackendConfiguration.Pn/BackendConfiguration.Pn/Services/ExcelService/ExcelService.cs

Lines changed: 214 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -222,154 +222,240 @@ public async Task<OperationDataResult<Stream>> GenerateExcelDashboard(List<OldRe
222222
}
223223

224224
public async Task<OperationDataResult<Stream>> GenerateExcelDashboard(List<ReportEformModel> reportModel)
225+
{
226+
try
225227
{
226-
try
228+
Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), "results"));
229+
var timeStamp = $"{DateTime.UtcNow:yyyyMMdd}_{DateTime.UtcNow:hhmmss}";
230+
var resultDocument = Path.Combine(Path.GetTempPath(), "results", $"{timeStamp}_.xlsx");
231+
232+
using (var spreadsheetDocument = SpreadsheetDocument.Create(resultDocument, SpreadsheetDocumentType.Workbook))
227233
{
228-
// Create a directory for results if it doesn't exist
229-
Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), "results"));
230-
var timeStamp = $"{DateTime.UtcNow:yyyyMMdd}_{DateTime.UtcNow:hhmmss}";
231-
var resultDocument = Path.Combine(Path.GetTempPath(), "results", $"{timeStamp}_.xlsx");
234+
var workbookPart = spreadsheetDocument.AddWorkbookPart();
235+
workbookPart.Workbook = new Workbook();
232236

233-
using (var spreadsheetDocument =
234-
SpreadsheetDocument.Create(resultDocument, SpreadsheetDocumentType.Workbook))
235-
{
236-
var workbookPart = spreadsheetDocument.AddWorkbookPart();
237-
workbookPart.Workbook = new Workbook();
237+
// Create Stylesheet for bold headers and date format
238+
var stylesPart = workbookPart.AddNewPart<WorkbookStylesPart>();
239+
stylesPart.Stylesheet = CreateStylesheet();
240+
stylesPart.Stylesheet.Save();
238241

239-
var sheets = workbookPart.Workbook.AppendChild(new Sheets());
240-
var worksheetNames = new List<string>();
241-
var duplicateNumber = 0;
242+
var sheets = workbookPart.Workbook.AppendChild(new Sheets());
243+
var worksheetNames = new List<string>();
244+
var duplicateNumber = 0;
242245

243-
foreach (var eformModel in reportModel)
246+
foreach (var eformModel in reportModel)
247+
{
248+
foreach (var reportEformGroupModel in eformModel.GroupEform)
244249
{
245-
foreach (var reportEformGroupModel in eformModel.GroupEform)
250+
if (eformModel.FromDate != null)
246251
{
247-
if (eformModel.FromDate != null)
252+
var sheetName = eformModel.GroupEform.Count > 1
253+
? $"{eformModel.GroupTagName} - {reportEformGroupModel.CheckListId}"
254+
: $"{eformModel.GroupTagName}";
255+
256+
sheetName = CreateSafeSheetName(sheetName);
257+
258+
// Check for duplicate sheet names
259+
if (worksheetNames.Contains(sheetName))
260+
{
261+
duplicateNumber++;
262+
sheetName = $"({duplicateNumber}){sheetName}";
263+
sheetName = sheetName.Substring(0, Math.Min(31, sheetName.Length));
264+
}
265+
else
248266
{
249-
var sheetName = eformModel.GroupEform.Count > 1
250-
? $"{eformModel.GroupTagName} - {reportEformGroupModel.CheckListId}"
251-
: $"{eformModel.GroupTagName}";
267+
worksheetNames.Add(sheetName);
268+
}
252269

253-
sheetName = CreateSafeSheetName(sheetName);
270+
var worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
271+
worksheetPart.Worksheet = new Worksheet(new SheetData());
272+
var sheetData = worksheetPart.Worksheet.GetFirstChild<SheetData>();
254273

255-
// Check for duplicate sheet names
256-
if (worksheetNames.Contains(sheetName))
257-
{
258-
duplicateNumber++;
259-
sheetName = $"({duplicateNumber}){sheetName}";
260-
sheetName = sheetName.Substring(0, Math.Min(31, sheetName.Length));
261-
}
262-
else
263-
{
264-
worksheetNames.Add(sheetName);
265-
}
274+
var sheet = new Sheet
275+
{
276+
Id = workbookPart.GetIdOfPart(worksheetPart),
277+
SheetId = (uint)(sheets.Count() + 1),
278+
Name = sheetName
279+
};
280+
sheets.Append(sheet);
266281

267-
var worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
268-
worksheetPart.Worksheet = new Worksheet(new SheetData());
269-
var sheetData = worksheetPart.Worksheet.GetFirstChild<SheetData>();
282+
// Create header row with bold formatting
283+
var headerRow = new Row();
284+
var headers = new List<Cell>
285+
{
286+
ConstructCell(localizationService.GetString("Id"), CellValues.String, 1),
287+
ConstructCell(localizationService.GetString("Property"), CellValues.String, 1),
288+
ConstructCell(localizationService.GetString("SubmittedDate"), CellValues.String, 1),
289+
ConstructCell(localizationService.GetString("DoneBy"), CellValues.String, 1),
290+
ConstructCell(localizationService.GetString("EmployeeNo"), CellValues.String, 1),
291+
ConstructCell(localizationService.GetString("ItemName"), CellValues.String, 1)
292+
};
270293

271-
var sheet = new Sheet
272-
{
273-
Id = workbookPart.GetIdOfPart(worksheetPart),
274-
SheetId = (uint)(sheets.Count() + 1),
275-
Name = sheetName
276-
};
277-
sheets.Append(sheet);
278-
279-
// Create header row
280-
var headerRow = new Row();
281-
headerRow.Append(
282-
ConstructCell(localizationService.GetString("Id"), CellValues.String),
283-
ConstructCell(localizationService.GetString("Property"), CellValues.String),
284-
ConstructCell(localizationService.GetString("SubmittedDate"), CellValues.String),
285-
ConstructCell(localizationService.GetString("DoneBy"), CellValues.String),
286-
ConstructCell(localizationService.GetString("EmployeeNo"), CellValues.String),
287-
ConstructCell(localizationService.GetString("ItemName"), CellValues.String)
288-
);
294+
foreach (var itemHeader in reportEformGroupModel.ItemHeaders)
295+
{
296+
headers.Add(ConstructCell(itemHeader.Value, CellValues.String, 1));
297+
}
289298

290-
foreach (var itemHeader in reportEformGroupModel.ItemHeaders)
291-
{
292-
headerRow.Append(ConstructCell(itemHeader.Value, CellValues.String));
293-
}
299+
headerRow.Append(headers);
300+
sheetData.AppendChild(headerRow);
294301

295-
sheetData.AppendChild(headerRow);
302+
// Populate data rows
303+
foreach (var dataModel in reportEformGroupModel.Items)
304+
{
305+
var dataRow = new Row();
306+
dataRow.Append(
307+
ConstructCell(dataModel.MicrotingSdkCaseId.ToString(), CellValues.String),
308+
ConstructCell(dataModel.PropertyName, CellValues.String),
309+
ConstructCell(dataModel.MicrotingSdkCaseDoneAt?.ToString("dd.MM.yyyy HH:mm:ss"),
310+
CellValues.String),
311+
ConstructCell(dataModel.DoneBy, CellValues.String),
312+
ConstructCell(dataModel.EmployeeNo, CellValues.String),
313+
ConstructCell(dataModel.ItemName, CellValues.String)
314+
);
296315

297-
// Populate data rows
298-
foreach (var dataModel in reportEformGroupModel.Items)
316+
foreach (var dataModelCaseField in dataModel.CaseFields)
299317
{
300-
var dataRow = new Row();
301-
dataRow.Append(
302-
ConstructCell(dataModel.MicrotingSdkCaseId.ToString(), CellValues.String),
303-
ConstructCell(dataModel.PropertyName, CellValues.String),
304-
ConstructCell(dataModel.MicrotingSdkCaseDoneAt?.ToString("dd.MM.yyyy HH:mm:ss"),
305-
CellValues.String),
306-
ConstructCell(dataModel.DoneBy, CellValues.String),
307-
ConstructCell(dataModel.EmployeeNo, CellValues.String),
308-
ConstructCell(dataModel.ItemName, CellValues.String)
309-
);
310-
311-
foreach (var dataModelCaseField in dataModel.CaseFields)
318+
var value = dataModelCaseField.Value switch
319+
{
320+
"checked" => "1",
321+
"unchecked" => "0",
322+
_ => dataModelCaseField.Value
323+
};
324+
325+
switch (dataModelCaseField.Key)
312326
{
313-
var value = dataModelCaseField.Value switch
314-
{
315-
"checked" => "1",
316-
"unchecked" => "0",
317-
_ => dataModelCaseField.Value
318-
};
319-
320-
switch (dataModelCaseField.Key)
321-
{
322-
case "date":
323-
if (DateTime.TryParse(value, out var dateValue))
324-
{
325-
dataRow.Append(ConstructCell(dateValue.ToString("dd.MM.yyyy"),
326-
CellValues.String));
327-
}
328-
else
329-
{
330-
dataRow.Append(ConstructCell(value, CellValues.String));
331-
}
332-
333-
break;
334-
case "number":
335-
if (double.TryParse(value, out var numberValue))
336-
{
337-
dataRow.Append(ConstructCell(
338-
numberValue.ToString(CultureInfo.InvariantCulture),
339-
CellValues.Number));
340-
}
341-
else
342-
{
343-
dataRow.Append(ConstructCell(value, CellValues.String));
344-
}
345-
346-
break;
347-
default:
327+
case "date":
328+
if (DateTime.TryParse(value, out var dateValue))
329+
{
330+
dataRow.Append(ConstructCell(dateValue.ToString("dd.MM.yyyy"),
331+
CellValues.String));
332+
}
333+
else
334+
{
348335
dataRow.Append(ConstructCell(value, CellValues.String));
349-
break;
350-
}
351-
}
336+
}
352337

353-
sheetData.AppendChild(dataRow);
338+
break;
339+
case "number":
340+
if (double.TryParse(value, out var numberValue))
341+
{
342+
dataRow.Append(ConstructCell(
343+
numberValue.ToString(CultureInfo.InvariantCulture),
344+
CellValues.Number));
345+
}
346+
else
347+
{
348+
dataRow.Append(ConstructCell(value, CellValues.String));
349+
}
350+
351+
break;
352+
default:
353+
dataRow.Append(ConstructCell(value, CellValues.String));
354+
break;
355+
}
354356
}
357+
358+
sheetData.AppendChild(dataRow);
355359
}
360+
361+
// Apply autofilter and table formatting
362+
ApplyTableFormatting(sheet, worksheetPart, sheetData);
356363
}
357364
}
358-
359-
workbookPart.Workbook.Save();
360365
}
361366

362-
Stream result = File.Open(resultDocument, FileMode.Open);
363-
return new OperationDataResult<Stream>(true, result);
367+
workbookPart.Workbook.Save();
364368
}
365-
catch (Exception e)
369+
370+
Stream result = File.Open(resultDocument, FileMode.Open);
371+
return new OperationDataResult<Stream>(true, result);
372+
}
373+
catch (Exception e)
374+
{
375+
logger.LogError(e.Message);
376+
return new OperationDataResult<Stream>(false,
377+
localizationService.GetString("ErrorWhileCreatingExcelFile"));
378+
}
379+
}
380+
381+
382+
383+
private Stylesheet CreateStylesheet()
384+
{
385+
return new Stylesheet(
386+
new Fonts(
387+
new Font( // Default font
388+
new FontSize() { Val = 11 },
389+
new FontName() { Val = "Calibri" }),
390+
new Font( // Bold font
391+
new Bold(),
392+
new FontSize() { Val = 11 },
393+
new FontName() { Val = "Calibri" })
394+
),
395+
new Fills(
396+
new Fill(new PatternFill() { PatternType = PatternValues.None }), // Default fill
397+
new Fill(new PatternFill() { PatternType = PatternValues.Gray125 }) // Gray fill
398+
),
399+
new Borders(new Border()), // Default border
400+
new CellFormats(
401+
new CellFormat(), // Default format
402+
new CellFormat { FontId = 1, ApplyFont = true } // Bold format
403+
),
404+
new NumberingFormats( // Custom number format for date
405+
new NumberingFormat()
406+
{
407+
NumberFormatId = 164, // Number format IDs between 164 and 255 are custom
408+
FormatCode = "dd/MM/yyyy"
409+
}
410+
)
411+
);
412+
}
413+
414+
private void ApplyTableFormatting(Sheet sheet, WorksheetPart worksheetPart, SheetData sheetData)
415+
{
416+
// Define the range for the table
417+
var columns = sheetData.Elements<Row>().First().Elements<Cell>().Count();
418+
var rows = sheetData.Elements<Row>().Count();
419+
string range = $"A1:{GetColumnLetter(columns)}{rows}";
420+
421+
// Apply auto filter
422+
AutoFilter autoFilter = new AutoFilter() { Reference = range };
423+
worksheetPart.Worksheet.InsertAfter(autoFilter, sheetData);
424+
425+
// Define table
426+
TableDefinitionPart tablePart = worksheetPart.AddNewPart<TableDefinitionPart>();
427+
Table table = new Table()
366428
{
367-
logger.LogError(e.Message);
368-
return new OperationDataResult<Stream>(false,
369-
localizationService.GetString("ErrorWhileCreatingExcelFile"));
429+
Id = (uint)new Random().Next(1, 10000),
430+
Name = "Table1",
431+
DisplayName = "Table1",
432+
Reference = range,
433+
AutoFilter = new AutoFilter() { Reference = range }
434+
};
435+
436+
TableColumns tableColumns = new TableColumns() { Count = (uint)columns };
437+
for (uint i = 1; i <= columns; i++)
438+
{
439+
tableColumns.Append(new TableColumn() { Id = i, Name = $"Column{i}" });
370440
}
441+
442+
table.Append(tableColumns);
443+
table.Append(new TableStyleInfo() { Name = "TableStyleMedium2", ShowFirstColumn = false, ShowLastColumn = false, ShowRowStripes = true, ShowColumnStripes = false });
444+
tablePart.Table = table;
445+
table.Save();
371446
}
372447

448+
private string GetColumnLetter(int columnIndex)
449+
{
450+
string columnLetter = "";
451+
while (columnIndex > 0)
452+
{
453+
int modulo = (columnIndex - 1) % 26;
454+
columnLetter = Convert.ToChar(65 + modulo) + columnLetter;
455+
columnIndex = (columnIndex - modulo) / 26;
456+
}
457+
return columnLetter;
458+
}
373459

374460
private static string CreateSafeSheetName(string sheetName)
375461
{
@@ -449,6 +535,16 @@ private Cell ConstructCell(string value, CellValues dataType)
449535
};
450536
}
451537

538+
private Cell ConstructCell(string value, CellValues dataType, uint styleIndex)
539+
{
540+
return new Cell
541+
{
542+
CellValue = new CellValue(value),
543+
DataType = new EnumValue<CellValues>(dataType),
544+
StyleIndex = styleIndex // Applies the formatting (e.g., bold)
545+
};
546+
}
547+
452548
public Task<Stream> GenerateTaskTracker(List<TaskTrackerModel> model)
453549
{
454550
try

0 commit comments

Comments
 (0)