Skip to content

Commit

Permalink
⭐ Add NPOI
Browse files Browse the repository at this point in the history
  • Loading branch information
ntxinh committed Nov 23, 2023
1 parent b13c36e commit 89b5992
Show file tree
Hide file tree
Showing 11 changed files with 215 additions and 10 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ podman-compose stop
- [x] Notifications
- [x] Webhook
- [x] Task scheduling & Queues: Quartz
- [x] NPOI
- [ ] Autofac or Scrutor
- [ ] Bogus
- [ ] Scaffold
Expand Down
1 change: 1 addition & 0 deletions Src/DDD.Domain/DDD.Domain.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="NPOI" Version="2.6.2" />
<PackageReference Include="Quartz.AspNetCore" Version="3.7.0" />
<PackageReference Include="Refit.HttpClientFactory" Version="6.0.38" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace DDD.Domain.Providers.Http
{
public class HttpService : IHttpService
public class HttpProvider : IHttpProvider
{
public async Task<T> GetAsync<T>(HttpClient httpClient, string url, Dictionary<string, string> queryParams = null, Dictionary<string, string> headers = null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace DDD.Domain.Providers.Http
{
public interface IHttpService
public interface IHttpProvider
{
Task<T> GetAsync<T>(HttpClient httpClient, string url, Dictionary<string, string> queryParams = null, Dictionary<string, string> headers = null);
Task<T> PostAsJsonAsync<T>(HttpClient httpClient, string url, object data, Dictionary<string, string> queryParams = null, Dictionary<string, string> headers = null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace DDD.Domain.Providers.Mail
{
public interface IMailService
public interface IMailProvider
{
Task Send(MailMessage message);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@

namespace DDD.Domain.Providers.Mail
{
public class MailService : IMailService
public class MailProvider : IMailProvider
{
private readonly IConfiguration _configuration;
// private readonly string devOpsEmail;
// private readonly ISendGridClient _sendGridClient;

public MailService(IConfiguration configuration/*, ISendGridClient sendGridClient*/)
public MailProvider(IConfiguration configuration/*, ISendGridClient sendGridClient*/)
{
_configuration = configuration;
// _sendGridClient = sendGridClient;
Expand Down
13 changes: 13 additions & 0 deletions Src/DDD.Domain/Providers/Office/ExcelFormat.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace DDD.Domain.Providers.Office;

public class ExcelFormat
{
public string ColId { get; set; }
public string ColName { get; set; }
public int ColIndex { get; set; }
public int Width { get; set; }
public bool IsBold { get; set; }
public bool IsCurrency { get; set; }
public bool IsDate { get; set; }
public bool IsHide { get; set; }
}
9 changes: 9 additions & 0 deletions Src/DDD.Domain/Providers/Office/IOfficeProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System.Collections.Generic;
using System.Threading.Tasks;

namespace DDD.Domain.Providers.Office;

public interface IOfficeProvider
{
Task<string> ExportAndUploadExcel<T>(IList<T> data, IList<ExcelFormat> formats, string fileName);
}
181 changes: 181 additions & 0 deletions Src/DDD.Domain/Providers/Office/OfficeProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;

namespace DDD.Domain.Providers.Office;

public class OfficeProvider : IOfficeProvider
{
public async Task<string> ExportAndUploadExcel<T>(IList<T> data, IList<ExcelFormat> formats, string fileName)
{
var dt = ToDataTable<T>(data);
// dt.TableName = "";
var dataSet = new DataSet();
dataSet.Tables.Add(dt);

var str = await ExportExcel(dataSet, formats, fileName);
return str;
}

private async Task<string> ExportExcel(DataSet dataSet, IList<ExcelFormat> formats, string fileName)
{
using (IWorkbook workbook = new XSSFWorkbook())
{
for (var tableIndex = 0; tableIndex < dataSet.Tables.Count; tableIndex++)
{
var dt = dataSet.Tables[tableIndex];
CreateSheetFromDataTable(workbook, tableIndex, dt, formats);
}

var stream = new MemoryStream();
workbook.Write(stream, leaveOpen: true);

// TODO: Upload

stream.Close();

return string.Empty;
}
}

private static void CreateSheetFromDataTable(IWorkbook workbook, int dataTableIndex, DataTable dataTable, IList<ExcelFormat> formats)
{
var tableName = string.IsNullOrEmpty(dataTable.TableName) ? $"Sheet {dataTableIndex}" : dataTable.TableName;
var sheet = (XSSFSheet)workbook.CreateSheet(tableName);
var columnCount = dataTable.Columns.Count;
var rowCount = dataTable.Rows.Count;

//create the format instance
IDataFormat format = workbook.CreateDataFormat();

// add column headers
var row = sheet.CreateRow(0);
for (var columnIndex = 0; columnIndex < columnCount; columnIndex++)
{
var col = dataTable.Columns[columnIndex];

var colFormat = formats.FirstOrDefault(x => x.ColId == col.ColumnName);
if (colFormat is null)
{
row.CreateCell(columnIndex).SetCellValue(col.ColumnName);
continue;
}

if (colFormat.IsHide) continue;

var cell = row.CreateCell(columnIndex);

if (!string.IsNullOrEmpty(colFormat.ColName))
{
cell.SetCellValue(colFormat.ColName);
}
// if (colFormat.IsBold)
// {
// var font = workbook.CreateFont();
// font.IsBold = true;
// cell.CellStyle.SetFont(font);
// }
}

// add data rows
for(var rowIndex = 0; rowIndex < rowCount; rowIndex++)
{
var dataRow = dataTable.Rows[rowIndex];
var sheetRow = sheet.CreateRow(rowIndex + 1);

for (var columnIndex = 0; columnIndex < columnCount; columnIndex++)
{
var cellRawValue = dataRow[columnIndex];
if (string.IsNullOrEmpty(cellRawValue.ToString()))
{
continue;
}

var col = dataTable.Columns[columnIndex];
var colFormat = formats.FirstOrDefault(x => x.ColId == col.ColumnName);
if (colFormat is null)
{
sheetRow.CreateCell(columnIndex).SetCellValue(cellRawValue.ToString());
continue;
}

if (colFormat.IsHide) continue;

var cell = sheetRow.CreateCell(columnIndex);

if (col.DataType == typeof(String))
{
cell.SetCellValue(cellRawValue.ToString());
}
else if (col.DataType == typeof(Double) || col.DataType == typeof(Decimal))
{
SetValueAndFormat(workbook, cell, (double)cellRawValue, format.GetFormat("$#,##"));
}
else if (col.DataType == typeof(Int16) || col.DataType == typeof(Int32) || col.DataType == typeof(Int64))
{
SetValueAndFormat(workbook, cell, (int)cellRawValue, format.GetFormat("0.00"));
}
else if (col.DataType == typeof(DateTime))
{
SetValueAndFormat(workbook, cell, (DateTime)cellRawValue, format.GetFormat("mm/dd/yyyy"));
}
}
}

// auto size columns
for (var columnIndex = 0; columnIndex < columnCount; columnIndex++)
{
sheet.AutoSizeColumn(columnIndex);
}
}

private DataTable ToDataTable<T>(IList<T> data)
{
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
DataTable table = new DataTable();
foreach (PropertyDescriptor prop in properties)
{
table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
}
foreach (T item in data)
{
DataRow row = table.NewRow();
foreach (PropertyDescriptor prop in properties)
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
table.Rows.Add(row);
}
return table;
}

static void SetValueAndFormat(IWorkbook workbook, ICell cell, int value, short formatId)
{
cell.SetCellValue(value);
ICellStyle cellStyle = workbook.CreateCellStyle();
cellStyle.DataFormat = formatId;
cell.CellStyle = cellStyle;
}

static void SetValueAndFormat(IWorkbook workbook, ICell cell, double value, short formatId)
{
cell.SetCellValue(value);
ICellStyle cellStyle = workbook.CreateCellStyle();
cellStyle.DataFormat = formatId;
cell.CellStyle = cellStyle;
}

static void SetValueAndFormat(IWorkbook workbook, ICell cell, DateTime value, short formatId)
{
//set value for the cell
cell.SetCellValue(value);

ICellStyle cellStyle = workbook.CreateCellStyle();
cellStyle.DataFormat = formatId;
cell.CellStyle = cellStyle;
}
}
Empty file.
10 changes: 5 additions & 5 deletions Src/DDD.Infra.CrossCutting.IoC/NativeInjectorBootStrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.DependencyInjection;
using DDD.Domain.Providers.Crons;
using DDD.Domain.Providers.Office;

namespace DDD.Infra.CrossCutting.IoC
{
Expand Down Expand Up @@ -55,14 +56,13 @@ public static void RegisterServices(IServiceCollection services)
services.AddScoped<IRequestHandler<UpdateCustomerCommand, bool>, CustomerCommandHandler>();
services.AddScoped<IRequestHandler<RemoveCustomerCommand, bool>, CustomerCommandHandler>();

// Domain - 3rd parties
services.AddScoped<IHttpService, HttpService>();
services.AddScoped<IMailService, MailService>();

// Domain - Providers
// Domain - Providers, 3rd parties
services.AddScoped<IHttpProvider, HttpProvider>();
services.AddScoped<IMailProvider, MailProvider>();
services.AddScoped<INotificationProvider, NotificationProvider>();
services.AddScoped<IWebhookProvider, WebhookProvider>();
services.AddScoped<ICronProvider, CronProvider>();
services.AddScoped<IOfficeProvider, OfficeProvider>();

// Infra - Data
services.AddScoped<ICustomerRepository, CustomerRepository>();
Expand Down

0 comments on commit 89b5992

Please sign in to comment.