浏览代码

Logic for generating report.

master
NikolaJovanovic 3 年前
父节点
当前提交
bb592c8729

+ 8
- 1
BlackRockReportFunction/BlackRockReportFunction.csproj 查看文件

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
@@ -7,12 +7,19 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Azure.Storage.Blobs" Version="12.12.0" />
<PackageReference Include="Azure.Storage.Queues" Version="12.10.0" />
<PackageReference Include="GemBox.Spreadsheet" Version="37.3.30.1110" />
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.9" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Storage" Version="4.0.4" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Timer" Version="4.1.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.3.0" OutputItemType="Analyzer" />
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.6.0" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.SendGrid" Version="3.0.2" />
<PackageReference Include="System.Core" Version="3.5.21022.801" />
<PackageReference Include="System.Drawing.Common" Version="6.0.0" />
<PackageReference Include="System.IO.Packaging" Version="6.0.0" />
<PackageReference Include="System.Windows.Forms" Version="4.0.0" />
</ItemGroup>
<ItemGroup>
<None Update="host.json">

+ 219
- 0
BlackRockReportFunction/Bussines/ReportGenerator.cs 查看文件

@@ -0,0 +1,219 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GemBox.Spreadsheet;
using BlackRockReportFunction.Models;
using BlackRockReportFunction.Helpers;
using System.Windows.Forms;

namespace BlackRockReportFunction.Bussines
{
internal class ReportGenerator
{
public static async Task<ExcelFile> GenerateReportContent()
{
string licenseKey = "E0YU-JKLB-WFCE-N52P";
SpreadsheetInfo.SetLicense(licenseKey);

var testObject = new ClockifyReport
{
reportName = "BlackRockReport_20220615",
reportDescription = "Total (13/06/2022 - 15/06/2022)",
reportPeople = new List<Person>
{
new Person
{
fullName = "Nikola Jovanovic",
records = new List<ClockifyRecord>
{
new ClockifyRecord
{
recordDescription = "Description1",
recordTime = new TimeOnly(3,15,44),
amount = 200
},
new ClockifyRecord
{
recordDescription = "Description1",
recordTime = new TimeOnly(3,15,44),
amount = 150
}
}
},
new Person
{
fullName = "Boris Stevanovic",
records = new List<ClockifyRecord>
{
new ClockifyRecord
{
recordDescription = "Description1",
recordTime = new TimeOnly(3,15,44),
amount = 300
},
new ClockifyRecord
{
recordDescription = "Description1",
recordTime = new TimeOnly(3,15,44),
amount = 100
},
new ClockifyRecord
{
recordDescription = "Description1",
recordTime = new TimeOnly(3,15,44),
amount = 120
}
}
},
new Person
{
fullName = "Dunja Stevanovic",
records = new List<ClockifyRecord>
{
new ClockifyRecord
{
recordDescription = "Description1",
recordTime = new TimeOnly(3,15,44),
amount = 50
},
new ClockifyRecord
{
recordDescription = "Description1",
recordTime = new TimeOnly(3,15,44),
amount = 500
}
}
}
}
};

var excelFile = new ExcelFile();
var ws = excelFile.Worksheets.Add("Content");

var sectionStyle = new CellStyle
{
Font =
{
Weight = ExcelFont.BoldWeight,
Size = 250,
},
VerticalAlignment = VerticalAlignmentStyle.Center,
HorizontalAlignment = HorizontalAlignmentStyle.Center,
};

var mainDetailsStyle = new CellStyle
{
Font =
{
Weight = ExcelFont.BoldWeight,
Size = 200,
}
};

await AddReportItems(testObject, ws, sectionStyle, mainDetailsStyle);

// Autofit
excelFile = await AutoFitReport(excelFile);

return excelFile;
}

public static async Task AddReportItems(ClockifyReport reportObject, ExcelWorksheet ws, CellStyle sectionStyle, CellStyle mainDetailsStyle)
{
int row = 0;
string[] sectionNames = { "User", "Description", "Time (h)", "Time (decimal)", "Amount (USD)" };
decimal totalAmountSum = 0;

for (int i = 0; i < sectionNames.Length; i++)
{
ws.Cells[row, i].Style = sectionStyle;
ws.Cells[row, i].Value = sectionNames[i];
ws.Cells[row, i].Style.Borders[IndividualBorder.Right].LineStyle = LineStyle.Medium;
ws.Cells[row, i].Style.Borders[IndividualBorder.Bottom].LineStyle = LineStyle.Thick;
}

row++;

foreach (var reportPerson in reportObject.reportPeople)
{
ws.Cells[row, 0].Style = mainDetailsStyle;
ws.Cells[row, 0].Value = reportPerson.fullName;

var sumOfRecordHours = Formaters.getSumOfRecordTimes(reportPerson.records.Select(record => record.recordTime).ToList());
ws.Cells[row, 2].Style = mainDetailsStyle;
ws.Cells[row, 2].Style.HorizontalAlignment = HorizontalAlignmentStyle.Right;
ws.Cells[row, 2].Value = sumOfRecordHours;

ws.Cells[row, 3].Style = mainDetailsStyle;
ws.Cells[row, 3].Style.HorizontalAlignment = HorizontalAlignmentStyle.Right;
ws.Cells[row, 3].Value = Formaters.getDecimalHours(sumOfRecordHours);

ws.Cells[row, 4].Style = mainDetailsStyle;
ws.Cells[row, 4].Style.HorizontalAlignment = HorizontalAlignmentStyle.Right;
ws.Cells[row, 4].Value = string.Format("{0} USD", reportPerson.records.Sum(record => record.amount).ToString("0.00"));
totalAmountSum += reportPerson.records.Sum(record => record.amount);

row++;

foreach (var personRecord in reportPerson.records)
{
ws.Cells[row, 1].Value = personRecord.recordDescription;

ws.Cells[row, 2].Value = Formaters.getRecordTime(personRecord.recordTime);
ws.Cells[row, 2].Style.HorizontalAlignment = HorizontalAlignmentStyle.Right;

ws.Cells[row, 3].Value = Formaters.getDecimalHours(personRecord.recordTime);
ws.Cells[row, 3].Style.HorizontalAlignment = HorizontalAlignmentStyle.Right;

ws.Cells[row, 4].Value = string.Format("{0} USD", personRecord.amount.ToString("0.00"));
ws.Cells[row, 4].Style.HorizontalAlignment = HorizontalAlignmentStyle.Right;

row++;
}
}

ws.Cells.GetSubrangeAbsolute(row, 0, row, 1).Merged = true;
ws.Cells.GetSubrangeAbsolute(row, 0, row, 1).Style = mainDetailsStyle;
ws.Cells.GetSubrangeAbsolute(row, 0, row, 1).Value = reportObject.reportDescription;

var totalSum = Formaters.getTotalSum(
reportObject.reportPeople.Select(
person => Formaters.getSumOfRecordTimes(
person.records.Select(record => record.recordTime).ToList()
)
).ToList()
);

ws.Cells[row, 2].Style = mainDetailsStyle;
ws.Cells[row, 2].Style.HorizontalAlignment = HorizontalAlignmentStyle.Right;
ws.Cells[row, 2].Value = totalSum;

ws.Cells[row, 3].Style = mainDetailsStyle;
ws.Cells[row, 3].Style.HorizontalAlignment = HorizontalAlignmentStyle.Right;
ws.Cells[row, 3].Value = Formaters.getDecimalHours(totalSum);

ws.Cells[row, 4].Style = mainDetailsStyle;
ws.Cells[row, 4].Style.HorizontalAlignment = HorizontalAlignmentStyle.Right;
ws.Cells[row, 4].Value = string.Format("{0} USD", totalAmountSum.ToString("0.00"));
}

public static async Task<ExcelFile> AutoFitReport(ExcelFile excelFile)
{
var localFile = excelFile;

foreach (var sheet in localFile.Worksheets)
{
//var columnCount = sheet.CalculateMaxUsedColumns() - 1;

//for (int i = 0; i < columnCount; i++)
//{
// sheet.Columns[i].AutoFit(1, sheet.Rows[0], sheet.Rows[sheet.Rows.Count - 1]);
//}
}

return localFile;
}
}
}

+ 102
- 0
BlackRockReportFunction/Helpers/Formaters.cs 查看文件

@@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;

namespace BlackRockReportFunction.Helpers
{
public static class Formaters
{
public static string getSumOfRecordTimes(List<TimeOnly> recordTimes)
{
int totalHours = 0;
int totalMinutes = 0;
int totalSeconds = 0;

// Calculate Seconds
int totalRecordsSeconds = recordTimes.Sum(record => record.Second);
totalSeconds = totalRecordsSeconds % 60;
totalMinutes += totalRecordsSeconds / 60;

// Calculate Minutes
int totalRecordsMinutes = recordTimes.Sum(record => record.Minute);

totalMinutes = totalMinutes + (totalRecordsMinutes % 60);
totalHours += totalRecordsMinutes / 60;

// Calculate Hours
int totalRecordHours = recordTimes.Sum(record => record.Hour);
totalHours += totalRecordHours;

return string.Format("{0}:{1}:{2}",
totalHours > 9 ? totalHours : string.Format("0{0}", totalHours),
totalMinutes > 9 ? totalMinutes : string.Format("0{0}", totalMinutes),
totalSeconds > 9 ? totalSeconds : string.Format("0{0}", totalSeconds));
}

public static string getDecimalHours(string recordHoursSum)
{
var components = recordHoursSum.Split(':').ToList();

var hours = (components[0].Length == 2 && components[0].First() == '0')
? components[0].ToCharArray()[1].ToString()
: components[0];

var minutesPercent = (Convert.ToInt32(components[1]) * 100 / 60).ToString();
if (minutesPercent.Length == 1)
{
minutesPercent = string.Format("0{0}", minutesPercent);
}

return string.Format("{0}:{1}", hours, minutesPercent);
}

public static string getDecimalHours(TimeOnly recordTime)
{
return getDecimalHours(string.Format("{0}:{1}:{2}", recordTime.Hour, recordTime.Minute, recordTime.Second));
}

public static string getRecordTime(TimeOnly recordTime)
{
return string.Format("{0}:{1}:{2}", recordTime.Hour, recordTime.Minute, recordTime.Second);
}

public static string getTotalSum(List<string> personsSums)
{
var totalHours = 0;
var totalMinutes = 0;
var totalSeconds = 0;

foreach(var personSum in personsSums)
{
var components = personSum.Split(':').Select(Int32.Parse).ToList();

//add new person time
totalSeconds += components[2] % 60;
totalMinutes += components[2] / 60;

//clean up new sum
totalMinutes += totalSeconds / 60;
totalSeconds = totalSeconds % 60;

//add new person time
totalMinutes += components[1] % 60;
totalHours += components[1] / 60;

//clean up new time
totalHours += totalMinutes / 60;
totalMinutes = totalMinutes % 60;

//add new person time
totalHours += components[0];
}

return string.Format("{0}:{1}:{2}",
totalHours > 9 ? totalHours : string.Format("0{0}", totalHours),
totalMinutes > 9 ? totalMinutes : string.Format("0{0}", totalMinutes),
totalSeconds > 9 ? totalSeconds : string.Format("0{0}", totalSeconds));
}
}
}

+ 11
- 10
BlackRockReportFunction/MailSenderFunction.cs 查看文件

@@ -20,19 +20,20 @@ namespace BlackRockReportFunction
[Function("MailSenderFunction")]
public SendGridMessage Run([BlobTrigger("report-container/{name}", Connection = "AzureWebJobsStorage")] string fileData, string fileName)
{
_logger.LogInformation($"C# Blob trigger function Processed blob\n Name: {fileName} \n Data: {fileData}");
_logger.LogInformation($"C# Blob trigger function Processed blob\n New file detected with name: {fileName}");

var msg = new SendGridMessage()
{
From = new EmailAddress("[email protected]", "Nikola Jovanovic"),
Subject = "Test SendGrid Azure Function",
PlainTextContent = String.Format("If you read this text, then congratulations," +
" you did it! :)")
};
return null;
//var msg = new SendGridMessage()
//{
// From = new EmailAddress("[email protected]", "Nikola Jovanovic"),
// Subject = "Test SendGrid Azure Function",
// PlainTextContent = String.Format("If you read this text, then congratulations," +
// " you did it! :)")
//};

msg.AddTo(new EmailAddress("[email protected]", "Nikola Jovanovic"));
//msg.AddTo(new EmailAddress("[email protected]", "Nikola Jovanovic"));

return msg;
//return msg;
}
}
}

+ 4
- 4
BlackRockReportFunction/Models/ClockifyRecord.cs 查看文件

@@ -6,10 +6,10 @@ using System.Threading.Tasks;

namespace BlackRockReportFunction.Models
{
internal class ClockifyRecord
public class ClockifyRecord
{
string recordDescription { get; set; }
TimeOnly recordTime { get; set; }
decimal amount { get; set; }
public string recordDescription { get; set; }
public TimeOnly recordTime { get; set; }
public decimal amount { get; set; }
}
}

+ 4
- 4
BlackRockReportFunction/Models/ClockifyReport.cs 查看文件

@@ -6,10 +6,10 @@ using System.Threading.Tasks;

namespace BlackRockReportFunction.Models
{
internal class ClockifyReport
public class ClockifyReport
{
string ReportName { get; set; }
string ReportDescription { get; set; }
List<Person> reportPeople { get; set; }
public string reportName { get; set; }
public string reportDescription { get; set; }
public List<Person> reportPeople { get; set; }
}
}

+ 3
- 3
BlackRockReportFunction/Models/Person.cs 查看文件

@@ -6,9 +6,9 @@ using System.Threading.Tasks;

namespace BlackRockReportFunction.Models
{
internal class Person
public class Person
{
string FullName { get; set; }
List<ClockifyRecord> records { get; set; }
public string fullName { get; set; }
public List<ClockifyRecord> records { get; set; }
}
}

+ 32
- 3
BlackRockReportFunction/ReportGeneratorFunction.cs 查看文件

@@ -1,6 +1,13 @@
using System;
using System.IO;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;
using Microsoft.Azure.WebJobs;
using GemBox.Spreadsheet;
using BlackRockReportFunction.Models;
using BlackRockReportFunction.Helpers;
using Azure.Storage.Blobs;
using BlackRockReportFunction.Bussines;

namespace BlackRockReportFunction
{
@@ -14,9 +21,31 @@ namespace BlackRockReportFunction
}

[Function("ReportGeneratorFunction")]
public void Run([QueueTrigger("queue1")] string myQueueItem)
[BlobOutput("report-container/BlackRock_Report.xslx", Connection = "AzureWebJobsStorage")]
public async Task Run([QueueTrigger("queue1")] string myQueueItem)
{
_logger.LogInformation($"C# Queue trigger function processed: {myQueueItem}");
}
_logger.LogInformation($"C# Queue trigger function processed: {myQueueItem}, gemboxKey: {"E0YU - JKLB - WFCE - N52P"}");

var reportFile = await ReportGenerator.GenerateReportContent();

string connection = Environment.GetEnvironmentVariable("AzureWebJobsStorage");
string containerName = "report-container";

_logger.LogInformation(connection);

var blobClient = new BlobContainerClient(connection, containerName);
var blob = blobClient.GetBlobClient($"BlackRockReport_{DateTime.Now.ToString("f")}.xlsx");

Stream memoryStream = new MemoryStream();
reportFile.Save(memoryStream, new XlsxSaveOptions
{
Type = XlsxType.Xlsx
});

memoryStream.Position = 0;
await blob.UploadAsync(memoryStream);

_logger.LogInformation("File uploaded successfully!");
}
}
}

正在加载...
取消
保存