Export Class To Excel

PHOTO EMBED

Fri Aug 26 2022 07:14:42 GMT+0000 (Coordinated Universal Time)

Saved by @HristoT #c#

// 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; }
}
content_copyCOPY