202 lines
7.0 KiB
C#
202 lines
7.0 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.ComponentModel;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Reflection;
|
||
using System.Threading.Tasks;
|
||
using OfficeOpenXml;
|
||
using OfficeOpenXml.Style;
|
||
using LicenseContext = OfficeOpenXml.LicenseContext;
|
||
|
||
|
||
namespace _0_Framework.Excel;
|
||
|
||
public class ExcelGenerator
|
||
{
|
||
public ExcelGenerator()
|
||
{
|
||
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
|
||
}
|
||
public static byte[] GenerateExcel<T>(List<T> obj, string date = "") where T : class
|
||
{
|
||
var templatePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "Test", "template (2).xlsx");
|
||
|
||
// Open the template
|
||
FileInfo fileInfo = new FileInfo(templatePath);
|
||
using ExcelPackage package = new ExcelPackage(fileInfo);
|
||
ExcelWorksheet worksheet = package.Workbook.Worksheets[0];
|
||
|
||
var titles = GetNonEmptyDisplayNames<T>(obj);
|
||
var col = 1;
|
||
for (int i = 0; i < titles.Count; i++)
|
||
{
|
||
worksheet.Cells[1, col].Value = titles[i];
|
||
col++;
|
||
}
|
||
|
||
int row = 2;
|
||
foreach (var item in obj)
|
||
{
|
||
int column = 1;
|
||
foreach (var prop in typeof(T).GetProperties())
|
||
{
|
||
var displayNameAttr = prop.GetCustomAttribute<DisplayNameAttribute>();
|
||
if (displayNameAttr != null && titles.Contains(displayNameAttr.DisplayName))
|
||
{
|
||
var value = prop.GetValue(item);
|
||
|
||
worksheet.Cells[row, column].Value = value?.ToString();
|
||
column++;
|
||
}
|
||
}
|
||
|
||
row++;
|
||
}
|
||
|
||
worksheet.View.RightToLeft = true;
|
||
worksheet.HeaderFooter.OddHeader.LeftAlignedText = !string.IsNullOrWhiteSpace(date)
|
||
? $"تاریخ: {date}\r\nشماره ثبت: 1727"
|
||
: "شماره ثبت: 1727";
|
||
return package.GetAsByteArray();
|
||
}
|
||
|
||
public static byte[] CreateExcel<T>(List<T> dataList)
|
||
{
|
||
using (var package = new ExcelPackage())
|
||
{
|
||
var worksheet = package.Workbook.Worksheets.Add("Sheet1");
|
||
|
||
// Add property names as sub-header using DisplayName attribute
|
||
var properties = typeof(T).GetProperties();
|
||
for (int i = 0; i < properties.Length; i++)
|
||
{
|
||
var displayNameAttribute = properties[i].GetCustomAttribute<DisplayNameAttribute>();
|
||
var displayName = displayNameAttribute != null ? displayNameAttribute.DisplayName : properties[i].Name;
|
||
worksheet.Cells[3, i + 1].Value = displayName;
|
||
}
|
||
|
||
// Populate data and calculate column widths
|
||
for (int i = 0; i < dataList.Count; i++)
|
||
{
|
||
for (int j = 0; j < properties.Length; j++)
|
||
{
|
||
var cellValue = properties[j].GetValue(dataList[i]);
|
||
worksheet.Cells[i + 4, j + 1].Value = cellValue;
|
||
}
|
||
}
|
||
|
||
// Calculate total width of all filled columns
|
||
worksheet.Cells.AutoFitColumns(); // AutoFit columns to calculate their widths correctly
|
||
double totalDataWidth = 0;
|
||
for (int i = 1; i <= properties.Length; i++)
|
||
{
|
||
totalDataWidth += worksheet.Column(i).Width;
|
||
}
|
||
double headerWidth = totalDataWidth / 3.0;
|
||
|
||
// Create dynamic headers with adjusted widths
|
||
int totalColumns = properties.Length;
|
||
int colEnd1 = (int)Math.Floor((double)totalColumns / 3.0);
|
||
int colStart2 = colEnd1 + 1;
|
||
int colEnd2 = colStart2 + (int)Math.Floor((double)totalColumns / 3.0) - 1;
|
||
int colStart3 = colEnd2 + 1;
|
||
int colEnd3 = totalColumns;
|
||
|
||
worksheet.Cells[1, 1, 2, colEnd1].Merge = true;
|
||
worksheet.Cells[1, 1, 2, colEnd1].Value = "Dynamic Header 1";
|
||
worksheet.Column(1).Width = headerWidth;
|
||
|
||
worksheet.Cells[1, colStart2, 2, colEnd2].Merge = true;
|
||
worksheet.Cells[1, colStart2, 2, colEnd2].Value = "Dynamic Header 2";
|
||
worksheet.Column(colStart2).Width = headerWidth;
|
||
|
||
worksheet.Cells[1, colStart3, 2, colEnd3].Merge = true;
|
||
worksheet.Cells[1, colStart3, 2, colEnd3].Value = "Dynamic Header 3";
|
||
worksheet.Column(colStart3).Width = headerWidth;
|
||
|
||
// Add footer
|
||
worksheet.Cells[dataList.Count + 4, 1].Value = "Footer";
|
||
worksheet.Cells[dataList.Count + 4, 1, dataList.Count + 4, totalColumns].Merge = true;
|
||
|
||
// Return as byte array
|
||
return package.GetAsByteArray();
|
||
}
|
||
}
|
||
|
||
public static List<string> GetDisplayNames<T>(List<T> obj)
|
||
{
|
||
return typeof(T).GetProperties()
|
||
.Select(prop => prop.GetCustomAttribute<DisplayNameAttribute>())
|
||
.Where(attr => attr != null)
|
||
.Select(attr => attr.DisplayName)
|
||
.ToList();
|
||
}
|
||
|
||
public static List<string> GetNonEmptyDisplayNames<T>(List<T> obj)
|
||
{
|
||
var displayNames = new List<string>();
|
||
|
||
var item = obj.FirstOrDefault();
|
||
foreach (var prop in typeof(T).GetProperties())
|
||
{
|
||
var displayNameAttr = prop.GetCustomAttribute<DisplayNameAttribute>();
|
||
|
||
if (displayNameAttr != null)
|
||
{
|
||
var value = prop.GetValue(item) as string;
|
||
if (!string.IsNullOrEmpty(value))
|
||
{
|
||
displayNames.Add(displayNameAttr.DisplayName);
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
|
||
return displayNames.Distinct().ToList(); // Using Distinct to avoid duplicate display names
|
||
}
|
||
|
||
public record ExcelTestVm(long Id, string Name, DateTime DateTime);
|
||
|
||
public List<ExcelTestVm> GetDataFromExcel(Stream fileStream)
|
||
{
|
||
var resultList = new List<ExcelTestVm>();
|
||
|
||
using var package = new ExcelPackage(fileStream);
|
||
var worksheet = package.Workbook.Worksheets[0]; // Assuming first sheet
|
||
|
||
int rows = worksheet.Dimension.Rows;
|
||
for (int row = 2; row <= rows; row++) // Skipping the header row
|
||
{
|
||
var idCell = worksheet.Cells[row, 1].Text;
|
||
var nameCell = worksheet.Cells[row, 2].Text;
|
||
var birthDateCell = worksheet.Cells[row, 3].Text;
|
||
|
||
// Validation
|
||
if (string.IsNullOrEmpty(idCell) || string.IsNullOrEmpty(nameCell) ||
|
||
string.IsNullOrEmpty(birthDateCell))
|
||
{
|
||
throw new Exception($"Row {row}: Missing required data.");
|
||
}
|
||
|
||
if (!int.TryParse(idCell, out int id))
|
||
{
|
||
throw new Exception($"Row {row}: Invalid data type for ID.");
|
||
}
|
||
|
||
if (!DateTime.TryParse(birthDateCell, out DateTime birthDate))
|
||
{
|
||
throw new Exception($"Row {row}: Invalid date format for Birth Date.");
|
||
}
|
||
|
||
var data = new ExcelTestVm(id, nameCell, birthDate);
|
||
|
||
resultList.Add(data);
|
||
}
|
||
|
||
return resultList;
|
||
}
|
||
|
||
|
||
} |