Magicodes.ExporterAndImporter: A .NET Library for Excel Import and Export Operations

Generic Import/Export Library

Magicodes.ExporterAndImporter is a generic import/export library developed by the Xinlai team, which is continuously being refined and improved.

GitHub Repository: https://github.com/xin-lai/Magicodes.ExporterAndImporter

Features

  • Provides encapsulation for import/export operations, currently supporting Excel only (CSV, PDF, and other formats could be added)
  • Uses configuration attributes to control logic and display results without modifying core code
  • Recommended to be used with Import/Export DTOs
  • Export supports custom header handling for scenarios like multilingual support
  • Export supports custom text filtering or processing
  • Import supports automatic generation of import templates based on DTOs with template validation
  • Import supports data validation logic
  • Import supports data dropdown selections
  • Import supports adding comments

Export Demos

Basic Export


public class ProductData
{
    public string ProductId { get; set; }
    public string ProductName { get; set; }
    public decimal Price { get; set; }
    public int Quantity { get; set; }
}

var exportResult = await ExcelExporter.Export(filePath, new List<productdata>()
{
    new ProductData()
    {
        ProductId = "P001",
        ProductName = "Laptop",
        Price = 999.99m,
        Quantity = 10
    },
    new ProductData()
    {
        ProductId = "P002",
        ProductName = "Mouse",
        Price = 19.99m,
        Quantity = 50
    }
});
</productdata>

Attribute-Based Export


[ExcelExporter(Name = "Product Report", TableStyle = "Medium10")]
public class ProductReportData
{
    [ExporterHeader(DisplayName = "Product ID", IsBold = true)]
    public string Id { get; set; }

    [ExporterHeader(DisplayName = "Product Name")]
    public string Name { get; set; }

    [ExporterHeader(DisplayName = "Unit Price", Format = "$#,##0.00")]
    public decimal Price { get; set; }

    [ExporterHeader(DisplayName = "Stock", IsAutoFit = true)]
    public int StockQuantity { get; set; }
}

var exportResult = await ExcelExporter.Export(filePath, new List<productreportdata>()
{
    new ProductReportData()
    {
        Id = "P001",
        Name = "Laptop Computer",
        Price = 999.99m,
        StockQuantity = 15
    },
    new ProductReportData()
    {
        Id = "P002",
        Name = "Wireless Mouse",
        Price = 29.99m,
        StockQuantity = 45
    }
});
</productreportdata>

Custom Header Handling and Multilingual Support


[ExcelExporter(Name = "Sales Report", TableStyle = "Light10")]
public class SalesData
{
    [ExporterHeader(DisplayName = "Sale Date")]
    public DateTime Date { get; set; }

    [ExporterHeader(DisplayName = "Customer Name")]
    public string Customer { get; set; }

    [ExporterHeader(DisplayName = "Amount", Format = "#,##0.00")]
    public decimal TotalAmount { get; set; }

    [ExporterHeader(DisplayName = "Status")]
    public string Status { get; set; }
}

ExcelBuilder.Create()
    .WithLocalStringFunc((key) => 
    {
        if (key.Contains("Date")) return "Fecha";
        if (key.Contains("Customer")) return "Cliente";
        if (key.Contains("Amount")) return "Monto";
        if (key.Contains("Status")) return "Estado";
        return key;
    })
    .Build();

var exportResult = await ExcelExporter.Export(filePath, new List<salesdata>()
{
    new SalesData()
    {
        Date = DateTime.Now,
        Customer = "John Doe",
        TotalAmount = 1250.75m,
        Status = "Completed"
    },
    new SalesData()
    {
        Date = DateTime.Now.AddDays(-1),
        Customer = "Jane Smith",
        TotalAmount = 890.50m,
        Status = "Pending"
    }
});
</salesdata>

Import Demos

The import functionality uses several key components:

  • ImporterHeader attributes:
    • Name (string): Display name for the column header (required)
    • Description (string): Comment to add to the header
    • Author (string): Comment author, default is "X.M"
  • ImportModel<T>: Contains:
    • Data: IList<T> of imported data
    • ValidationResults: IList<ValidationResultModel> for validasion results
    • HasValidTemplate: bool indicating if template validation passed
  • ValidationResultModel: Contains:
    • Index: int for the row with errors
    • Errors: IDictionary<string, string> for Excel-wide errors
    • FieldErrors: IDictionary<string, string> for field-specific validation errors

Basic Template

Template Generation


public class CustomerImportDto
{
    /// <summary>
    /// Customer full name
    /// </summary>
    [ImporterHeader(Name = "Full Name")]
    public string FullName { get; set; }

    /// <summary>
    /// Customer email address
    /// </summary>
    [ImporterHeader(Name = "Email Address")]
    public string Email { get; set; }

    /// <summary>
    /// Customer phone number
    /// </summary>
    [ImporterHeader(Name = "Phone Number")]
    public string Phone { get; set; }

    /// <summary>
    /// Customer registration date
    /// </summary>
    [ImporterHeader(Name = "Registration Date")]
    public DateTime RegistrationDate { get; set; }
}

Multiple Data Types

Template Generation


public class ProductImportDto
{
    /// <summary>
    /// Product name
    /// </summary>
    [ImporterHeader(Name = "Product Name")]
    public string Name { get; set; }

    /// <summary>
    /// Product SKU
    /// </summary>
    [ImporterHeader(Name = "Product SKU")]
    public string Sku { get; set; }

    /// <summary>
    /// Product barcode
    /// </summary>
    [ImporterHeader(Name = "Barcode")]
    public string Barcode { get; set; }

    /// <summary>
    /// Category ID
    /// </summary>
    [ImporterHeader(Name = "Category ID")]
    public int CategoryId { get; set; }

    /// <summary>
    /// Product model
    /// </summary>
    [ImporterHeader(Name = "Model")]
    public string Model { get; set; }

    /// <summary>
    /// Unit price
    /// </summary>
    [ImporterHeader(Name = "Unit Price")]
    public decimal UnitPrice { get; set; }

    /// <summary>
    /// Currency
    /// </summary>
    [ImporterHeader(Name = "Currency")]
    public string Currency { get; set; }

    /// <summary>
    /// Brand name
    /// </summary>
    [ImporterHeader(Name = "Brand")]
    public string Brand { get; set; }

    /// <summary>
    /// Dimensions
    /// </summary>
    [ImporterHeader(Name = "Dimensions (LxWxH)")]
    public string Dimensions { get; set; }

    /// <summary>
    /// Weight in kilograms
    /// </summary>
    [ImporterHeader(Name = "Weight (KG)")]
    public double Weight { get; set; }

    /// <summary>
    /// Product category
    /// </summary>
    [ImporterHeader(Name = "Category")]
    public ProductCategory Category { get; set; }

    /// <summary>
    /// Is active
    /// </summary>
    [ImporterHeader(Name = "Active")]
    public bool IsActive { get; set; }
}

public enum ProductCategory
{
    [Display(Name = "Electronics")]
    Electronics,

    [Display(Name = "Clothing")]
    Clothing,

    [Display(Name = "Home & Garden")]
    HomeAndGarden,

    [Display(Name = "Sports")]
    Sports
}

Data Validation

Template Generation

Required fields are marked in red in the header


public class ValidatedOrderImportDto
{
    /// <summary>
    /// Order number
    /// </summary>
    [ImporterHeader(Name = "Order Number", Description = "Required")]
    [Required(ErrorMessage = "Order number is required")]
    public string OrderNumber { get; set; }

    /// <summary>
    /// Customer ID
    /// </summary>
    [ImporterHeader(Name = "Customer ID", Description = "Maximum 10 characters")]
    [MaxLength(10, ErrorMessage = "Customer ID cannot exceed 10 characters")]
    public string CustomerId { get; set; }

    /// <summary>
    /// Product code
    /// </summary>
    [ImporterHeader(Name = "Product Code", Description = "Required, alphanumeric only")]
    [Required(ErrorMessage = "Product code is required")]
    [RegularExpression(@"^[a-zA-Z0-9]*$", ErrorMessage = "Product code must be alphanumeric")]
    public string ProductCode { get; set; }

    /// <summary>
    /// Quantity
    /// </summary>
    [ImporterHeader(Name = "Quantity", Description = "Required, minimum 1")]
    [Range(1, int.MaxValue, ErrorMessage = "Quantity must be at least 1")]
    public int Quantity { get; set; }

    /// <summary>
    /// Unit price
    /// </summary>
    [ImporterHeader(Name = "Unit Price", Description = "Required, must be positive")]
    [Range(0.01, double.MaxValue, ErrorMessage = "Unit price must be positive")]
    public decimal UnitPrice { get; set; }

    /// <summary>
    /// Order date
    /// </summary>
    [ImporterHeader(Name = "Order Date", Description = "Required")]
    [Required(ErrorMessage = "Order date is required")]
    public DateTime OrderDate { get; set; }

    /// <summary>
    /// Delivery method
    /// </summary>
    [ImporterHeader(Name = "Delivery Method")]
    public DeliveryMethod DeliveryMethod { get; set; }

    /// <summary>
    /// Is urgent
    /// </summary>
    [ImporterHeader(Name = "Urgent Order")]
    public bool IsUrgent { get; set; }
}

public enum DeliveryMethod
{
    [Display(Name = "Standard")]
    Standard,

    [Display(Name = "Express")]
    Express,

    [Display(Name = "Overnight")]
    Overnight
}

Using in Docker

Required Libraries

To use Excel export functionality in Docker, you need to install the libgdiplus library:


# Install libgdiplus library for Excel export
RUN apt-get update && apt-get install -y libgdiplus libc6-dev
RUN ln -s /usr/lib/libgdiplus.so /usr/lib/gdiplus.dll

Dockerfile Example


FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
# Install libgdiplus library for Excel export
RUN apt-get update && apt-get install -y libgdiplus libc6-dev
RUN ln -s /usr/lib/libgdiplus.so /usr/lib/gdiplus.dll
WORKDIR /app
EXPOSE 80

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["src/web/Admin.Host/Admin.Host.csproj", "src/web/Admin.Host/"]
COPY ["src/web/Admin.Web.Core/Admin.Web.Core.csproj", "src/web/Admin.Web.Core/"]
COPY ["src/application/Admin.Application/Admin.Application.csproj", "src/application/Admin.Application/"]
COPY ["src/core/Magicodes.Admin.Core/Magicodes.Admin.Core.csproj", "src/core/Magicodes.Admin.Core/"]
COPY ["src/data/Magicodes.Admin.EntityFrameworkCore/Magicodes.Admin.EntityFrameworkCore.csproj", "src/data/Magicodes.Admin.EntityFrameworkCore/"]
COPY ["src/core/Magicodes.Admin.Core.Custom/Magicodes.Admin.Core.Custom.csproj", "src/core/Magicodes.Admin.Core.Custom/"]
COPY ["src/application/Admin.Application.Custom/Admin.Application.Custom.csproj", "src/application/Admin.Application.Custom/"]
RUN dotnet restore "src/web/Admin.Host/Admin.Host.csproj"
COPY . .
WORKDIR "/src/src/web/Admin.Host"
RUN dotnet build "Admin.Host.csproj" -c Release -o /app

FROM build AS publish
RUN dotnet publish "Admin.Host.csproj" -c Release -o /app

FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "Magicodes.Admin.Web.Host.dll"]

Tags: .NET C# Excel Import/Export Data Processing

Posted on Fri, 22 May 2026 17:34:06 +0000 by alecodonnell