// The class: ExportHandler
/// <summary>
// Подава се лист от модели и генерира Xcel файл, като колоните се подреждат според реда на пропъртитата в класа
/// Модела в листа трябва задължително да има атрибут (XcelHeader) със стойност за колоните, които ще се генерират
// </summary>
public static CheckResult SaveExcelByClass<T>(List<T> models, string sheetName)
{
var modelType = typeof(T); // типа на обекта
var props = modelType.GetProperties().Where(x => Attribute.IsDefined(x, typeof(XcelHeaderAttribute))).ToList(); // всички пропъртита с атрибута
if (props.Count == 0) // Ако няма нито един атрибут - излизаме
{
return CheckResult.Error("Липсват колони за ексел файла.");
}
string exportFileName = ""; // файла, където ще запазваме Xcel-а
using (var dlg = new SaveFileDialog())
{
dlg.DefaultExt = ".xlsx";
if (dlg.ShowDialog() != DialogResult.OK)
{
return CheckResult.Default;
}
exportFileName = dlg.FileName;
}
SplashScreenManager.ShowDefaultWaitForm("Експорт", "Данни"); // Показваме съобщение, че вършим работата
JFileHelper.ExcelWork((book) =>
{
var sheet = book.Worksheets[0]; // първия лист на ексела, който ще попълваме
sheet.Name = sheetName;
for (int i = 0; i < props.Count; i++) // въртим всички пропъртита, които сме извлекли от класа
{
var currentProp = props[i]; // текущото пропърти
// атрибута закачен за пропъртито
var attr = (XcelHeaderAttribute)currentProp
.GetCustomAttributes(typeof(XcelHeaderAttribute), false)
.FirstOrDefault();
// извличаме всички стойности на пропъртито от листа и взимаме дължината на най-дългата стойност в него
var maxLengthFromAllProps = models.Select(x => x.GetType().GetProperties().Where(x => x.Name == currentProp.Name)
.Select(y => y.GetValue(x)).FirstOrDefault()?.ToString()?.Length)
.Max();
// 13 е по дефолт, за да не са сплескани клетките. Ако дължината е по-голяма, взимаме нея + 2, за да има отстъп
var columnWidth = (maxLengthFromAllProps.HasValue && maxLengthFromAllProps.Value > 13) ? maxLengthFromAllProps.Value + 2 : 13;
var column = ((char)(65 + i)).ToString(); // Взимаме името на колоната (А,B,C,D...)
sheet.Columns[column].ColumnWidthInCharacters = columnWidth; // Сетваме дължината на колоната
var colCell = sheet.Cells[0, i];
colCell.Value = attr.HeaderName; // Слагаме хедъра на ексела
colCell.FillColor = Color.LightBlue; // Цвета на клетката
colCell.Alignment.WrapText = true; // да се чупи на нов ред ако не се събира в клетката, а не да изчезва
colCell.Borders.SetAllBorders(Color.Black, BorderLineStyle.Thin);
sheet.AutoFilter.Apply(sheet[$"{column}1"]); // Слагаме филтър на всяка една колона
// Въртим всички модели и взимаме стойностите на пропъртитата за текущата колона, която правим
for (int j = 0; j < models.Count; j++)
{
var row = models[j];
var propValue = currentProp.GetValue(row);
var rowCell = sheet.Cells[j + 1, i];
rowCell.Value = propValue?.ToString();
rowCell.Borders.SetAllBorders(Color.Black, BorderLineStyle.Thin);
}
}
SplashScreenManager.CloseDefaultSplashScreen();
book.SaveAndAskShow(exportFileName);
});
return CheckResult.Default;
}
// JFileHelper.ExcelWork:
public static void ExcelWork(Action<Workbook> book)
{
using (Workbook excel = new Workbook())
{
book(excel);
}
}
// The book extension
public static void SaveAndAskShow(this Workbook book, string filePath)
{
book.SaveDocument(filePath);
book.Dispose();
Mess.boxConfirm("Желаете ли да отворите файла?", () =>
{
ProcessStartInfo info = new ProcessStartInfo(filePath);
info.UseShellExecute = true;
Process.Start(info);
});
}
// Example Model
public class HonorariumBM
{
public int AcodeID { get; set; }
public string Acode { get; set; }
public int AcodePos { get; set; }
public string Acodename { get; set; }
[XcelHeader("ID доктор")]
public int doctorid { get; set; }
[XcelHeader("Имена")]
public string doctor_name { get; set; }
public int serviceid { get; set; }
public int external_code { get; set; }
[XcelHeader("Име на услугата")]
public string service_or_cp_name { get; set; }
[XcelHeader("Твърда сума")]
public decimal hard_price { get; set; }
[XcelHeader("Процент")]
public decimal percent { get; set; }
public decimal cost_price { get; set; }
[XcelHeader("юрид. лице")]
public int hospitalinfoid { get; set; }
public bool IsNew { get; set; }
public bool IsEdit { get; set; }
public bool IsDelete { get; set; }
}
// Attribute
public class XcelHeaderAttribute : Attribute
{
public XcelHeaderAttribute(string headerName)
{
this.HeaderName = headerName;
}
public string HeaderName { get; set; }
}