@@ -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