### Fetch Example (Dynamic) Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/excelmapper-api-reference.md Example demonstrating how to fetch dynamic objects from a sheet and access their properties. ```csharp var products = mapper.Fetch(); foreach (var product in products) Console.WriteLine(product.Name); ``` -------------------------------- ### Fetch Example (Generic) Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/excelmapper-api-reference.md Example demonstrating how to fetch strongly-typed objects from a sheet and iterate over them. ```csharp var mapper = new ExcelMapper("products.xlsx"); var products = mapper.Fetch(); foreach (var product in products) Console.WriteLine(product.Name); ``` -------------------------------- ### Full Example: Read, Modify, Save with Attributes Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/quick-reference.md A comprehensive example demonstrating how to define a `Product` class with column mapping and data formatting attributes, read data from an Excel file, modify it, and save it to a new file. ```csharp using Ganss.Excel; public class Product { [Column("Product Name")] public string Name { get; set; } [Column("Price")] [DataFormat("$#,##0.00")] public decimal Price { get; set; } [Column("In Stock")] public int Quantity { get; set; } [Ignore] public DateTime ImportedAt { get; set; } } // Read var mapper = new ExcelMapper("products.xlsx"); mapper.TrackObjects = true; var products = mapper.Fetch().ToList(); // Modify products[0].Price *= 1.1m; products[0].ImportedAt = DateTime.Now; // Save mapper.Save("products_updated.xlsx", "Products"); ``` -------------------------------- ### Example: Configuring Header Row and Data Range Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/configuration.md Shows how to set HeaderRowNumber to a specific row and MinRowNumber to start data processing after the header. ```csharp var mapper = new ExcelMapper("products.xlsx"); mapper.HeaderRowNumber = 2; // Headers in row 3 (zero-based: 2) mapper.MinRowNumber = 3; // Data starts in row 4 var products = mapper.Fetch(); ``` -------------------------------- ### Install ExcelMapper via NuGet Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/quick-reference.md Install the ExcelMapper package using the NuGet Package Manager Console. ```powershell NuGet: Install-Package ExcelMapper ``` -------------------------------- ### Example: Saving Tracked Objects to File Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/excelmapper-api-reference.md Demonstrates how to enable object tracking, modify tracked objects, and then save them to an Excel file. ```csharp mapper.TrackObjects = true; var products = mapper.Fetch().ToList(); products[0].Price += 1; mapper.Save("output.xlsx", "Products"); ``` -------------------------------- ### Install ExcelMapper Package Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/README.md Add the ExcelMapper NuGet package to your .NET project using the dotnet CLI. ```bash dotnet add package ExcelMapper ``` -------------------------------- ### Use ExcelMapper with Object Tracking Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/configuration.md Example demonstrating how to use TrackObjects to fetch, modify, and save objects. Modifications are preserved when saving. ```csharp var mapper = new ExcelMapper("products.xlsx"); mapper.TrackObjects = true; var products = mapper.Fetch().ToList(); products[0].Price += 1.0m; // Save tracked objects without re-passing the list mapper.Save("output.xlsx", "Products"); ``` -------------------------------- ### Example: Using HeaderRow and Column Mapping Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/configuration.md Demonstrates setting HeaderRow to true for files with headers and false for files requiring column index mapping. ```csharp // Excel file has headers in row 1 var mapper = new ExcelMapper("products.xlsx"); mapper.HeaderRow = true; var products = mapper.Fetch(); // Excel file has no headers mapper.HeaderRow = false; mapper.AddMapping(1, p => p.Name); mapper.AddMapping(2, p => p.Price); var products = mapper.Fetch(); ``` -------------------------------- ### DataFormat Attribute Examples Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/attributes.md Shows how to set Excel number or date formats for properties using the DataFormatAttribute. ```csharp [DataFormat(0x0f)] ``` ```csharp [DataFormat("0%")] ``` -------------------------------- ### Column Attribute Examples Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/attributes.md Demonstrates mapping properties to Excel columns using the ColumnAttribute by name, index, or letter. ```csharp [Column("Name")] ``` ```csharp [Column(1)] ``` ```csharp [Column(Letter="C")] ``` -------------------------------- ### Custom Value Conversion Example Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/types.md Example of using a custom value converter function to modify cell values during fetching. This allows for on-the-fly data transformation, such as applying a markup to prices. ```csharp var converter = new Func(args => { if (args.ColumnName == "Price" && args.CellValue is double d) { return d * 1.1; // Add 10% markup } return args.CellValue; }); var products = mapper.Fetch(valueConverter: converter); ``` -------------------------------- ### Example: Skipping Blank Rows Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/configuration.md Shows how to enable or disable skipping of entirely blank rows during data fetching. ```csharp var mapper = new ExcelMapper("products.xlsx"); mapper.SkipBlankRows = true; // Skip empty rows var products = mapper.Fetch().ToList(); // Result: Only rows with data ``` -------------------------------- ### Create TypeMapper from Type Example Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/types.md Demonstrates how to create a TypeMapper instance for a specific .NET type and access its column mappings by name. ```csharp var typeMapper = mapper.TypeMapperFactory.Create(typeof(Product)); var nameMappings = typeMapper.ColumnsByName["Name"]; ``` -------------------------------- ### Custom ITypeMapperFactory Implementation Example Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/types.md Shows how to replace the default TypeMapperFactory with a custom implementation, useful for advanced caching or creation logic. ```csharp mapper.TypeMapperFactory = new CustomTypeMapperFactory(); // Replace with custom ``` -------------------------------- ### Handle ExcelMapperConvertException Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/types.md Example of catching and handling ExcelMapperConvertException to provide user-friendly error messages about conversion failures. ```csharp try { var products = mapper.Fetch(); } catch (ExcelMapperConvertException ex) { Console.WriteLine($"Failed to convert '{ex.CellValue}' to {ex.TargetType.Name}"); Console.WriteLine($"Location: Row {ex.Line + 1}, Column {ex.Column + 1}"); } ``` -------------------------------- ### Dynamic Object Mapping Example Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/types.md Demonstrates fetching data as dynamic objects, allowing property access without a predefined type. Useful for loosely structured Excel files. ```csharp var products = mapper.Fetch(); // Returns IEnumerable foreach (dynamic product in products) { Console.WriteLine(product.Name); // Property accessed dynamically } ``` -------------------------------- ### Example: Handling Blank Cells Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/configuration.md Illustrates the behavior difference when SkipBlankCells is true (ignores empty cells) versus false (overwrites properties with empty cells). ```csharp var mapper = new ExcelMapper("products.xlsx"); mapper.SkipBlankCells = true; // Empty cells are ignored var products = mapper.Fetch().ToList(); mapper.SkipBlankCells = false; // Empty cells clear properties var products = mapper.Fetch().ToList(); ``` -------------------------------- ### Add Before Mapping Hook Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/quick-reference.md Execute a custom action before a Product object is mapped, for example, to set an 'ImportedAt' timestamp. ```csharp mapper.AddBeforeMapping((p, index) => { p.ImportedAt = DateTime.UtcNow; }); ``` -------------------------------- ### Add After Mapping Hook Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/quick-reference.md Execute a custom action after a Product object is mapped, for example, to populate a 'FullDescription' property. ```csharp mapper.AddAfterMapping((p, index) => { p.FullDescription = $"{p.Name}: {p.Price}"; }); ``` -------------------------------- ### Example: Reading a Specific Row Range Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/configuration.md Illustrates setting MinRowNumber and MaxRowNumber to process only a subset of rows in an Excel sheet. ```csharp var mapper = new ExcelMapper("report.xlsx"); mapper.HeaderRowNumber = 0; // Headers in row 1 mapper.MinRowNumber = 1; // Data starts row 2 (skip row 1 header) mapper.MaxRowNumber = 100; // Only read up to row 101 var products = mapper.Fetch(); ``` -------------------------------- ### Set Column Widths Before Saving Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/types.md Example of handling the Saving event to set column widths on the sheet before data is written. This ensures optimal column sizing for readability. ```csharp mapper.Saving += (sender, e) => { // Set column widths before saving e.Sheet.SetColumnWidth(0, 5000); e.Sheet.SetColumnWidth(1, 3000); }; mapper.Save("output.xlsx", products, "Sheet1"); ``` -------------------------------- ### Map Property from Excel Only Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/types.md Example demonstrating how to map a property from Excel exclusively, ignoring it during export. This is useful for properties that should only be read. ```csharp // Map PriceString from Excel only, ignoring when saving [Column("Price", MappingDirections.ExcelToObject)] public string PriceString { get; set; } // Or using fluent API mapper.AddMapping("Price", p => p.PriceString) .FromExcelOnly(); ``` -------------------------------- ### Fluent API Configuration for Excel Mapping Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/attributes.md Configure Excel mapping using fluent API methods on ColumnInfo. This example shows mapping, setting as formula, and ignoring properties. ```csharp mapper.AddMapping("Name", p => p.Name); mapper.AddMapping("Price", p => p.Price).AsFormula(); mapper.Ignore(p => p.ComputedValue); ``` -------------------------------- ### Name Normalization Use Case Example Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/quick-reference.md Illustrates how name normalization can map Excel column names like 'Product Name' and 'Unit Price' to C# property names 'ProductName' and 'UnitPrice', which can then be matched with attributes like `[Column("ProductName")]`. ```csharp // Excel: "Product Name", "Unit Price" // Normalized to: "ProductName", "UnitPrice" // Matches attributes: [Column("ProductName")] ``` -------------------------------- ### Example: Limiting Data Read to Max Row Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/configuration.md Demonstrates using MaxRowNumber to restrict reading to a specific number of rows, excluding subsequent rows. ```csharp var mapper = new ExcelMapper("products.xlsx"); mapper.MinRowNumber = 1; mapper.MaxRowNumber = 50; // Read rows 2-51 (zero-based 1-50) var products = mapper.Fetch(); ``` -------------------------------- ### Save Data with Missing Headers Created Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/configuration.md Example showing how to enable CreateMissingHeaders to add new columns during the save operation. The 'NewField' column is created if it doesn't exist. ```csharp var mapper = new ExcelMapper("products.xlsx"); mapper.CreateMissingHeaders = true; mapper.HeaderRow = true; var products = new List { new Product { Name = "Widget", Price = 9.99m, NewField = "value" } }; mapper.Save("output.xlsx", products, "Products"); // If "NewField" column doesn't exist, it will be created ``` -------------------------------- ### Column Attribute Inheritance Behavior Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/attributes.md Demonstrates how the ColumnAttribute is inherited by derived classes, with an example of disabling inheritance for a specific property. ```csharp public class BaseEntity { [Column("ID", Inherit = false)] public int Id { get; set; } } public class Product : BaseEntity { // Id property is NOT mapped by attribute in derived class public string Name { get; set; } } ``` -------------------------------- ### ColumnAttribute Inheritance Control Example Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/attributes.md Illustrates how to control attribute inheritance using the 'Inherit' property. Setting 'Inherit = false' prevents the attribute from being applied to derived classes. ```csharp public class BaseProduct { [Column("Name", Inherit = false)] // Don't inherit to derived class public virtual string Name { get; set; } } public class DerivedProduct : BaseProduct { [Column("ProductName")] // New mapping for this class public override string Name { get; set; } } ``` -------------------------------- ### ColumnAttribute with Letter Property Example Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/attributes.md Demonstrates mapping a property to an Excel column using the 'Letter' property, which is equivalent to using the 'Index' property. ```csharp [Column("Price")] public decimal Price { get; set; } // Equivalent: [Column(Letter = "C")] ``` -------------------------------- ### ColumnAttribute by Index and Name Example Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/attributes.md Maps a property to an Excel column using both its 1-based index and header name. This provides a more specific mapping. ```csharp public class Product { [Column(2, "Product Name")] public string Name { get; set; } } ``` -------------------------------- ### ColumnAttribute by Index Example Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/attributes.md Maps properties to Excel columns using their 1-based index. This is useful when column headers are not consistent or when mapping to specific positions. ```csharp public class Product { [Column(1)] public string Name { get; set; } [Column(2)] public int NumberInStock { get; set; } [Column(3)] public decimal Price { get; set; } } ``` -------------------------------- ### Read Data by Column Index (No Headers) Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/examples.md Map Excel data to a class by specifying column indexes using the [Column] attribute when the Excel file lacks a header row. Set 'mapper.HeaderRow = false'. The 'data.xlsx' file is expected to have data starting from the first row. ```csharp public class Record { [Column(1)] public string Id { get; set; } [Column(2)] public string Name { get; set; } [Column(3)] public decimal Amount { get; set; } [Column(4)] public DateTime Date { get; set; } } var mapper = new ExcelMapper("data.xlsx"); mapper.HeaderRow = false; // No header row var records = mapper.Fetch().ToList(); foreach (var r in records) { Console.WriteLine($"{r.Id}: {r.Name} - {r.Amount:C} on {r.Date:d}"); } ``` -------------------------------- ### Basic Read from File or Stream Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/quick-reference.md Fetch data into a list of Product objects from an Excel file or a stream. Ensure the Product class is defined. ```csharp using Ganss.Excel; // From file var products = new ExcelMapper("file.xlsx").Fetch(); // From stream using var stream = File.OpenRead("file.xlsx"); var products = new ExcelMapper(stream).Fetch(); ``` -------------------------------- ### Get TypeMapper Type Property Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/excelmapper-api-reference.md Retrieves the type that is currently being mapped by the TypeMapper. ```csharp public Type Type { get; private set; } ``` -------------------------------- ### DataFormatter Property Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/excelmapper-api-reference.md Gets or sets the NPOI DataFormatter for formatting cell values during reading. ```csharp public DataFormatter DataFormatter { get; set; } ``` -------------------------------- ### Get TypeMapper ColumnsByIndex Property Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/excelmapper-api-reference.md Accesses the mapping of 0-based column indexes to ColumnInfo objects. ```csharp public Dictionary> ColumnsByIndex { get; set; } ``` -------------------------------- ### Simple Product Import with Column Mapping Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/examples.md Import products from an Excel file by mapping columns to object properties using the [Column] attribute. Ensure the 'products.xlsx' file exists with the specified columns. ```csharp using Ganss.Excel; public class Product { [Column("Product Name")] public string Name { get; set; } [Column("SKU")] public string Sku { get; set; } [Column("Unit Price")] public decimal Price { get; set; } [Column("Stock Quantity")] public int Quantity { get; set; } [Column("Last Restock")] public DateTime LastRestockDate { get; set; } } // Read products var mapper = new ExcelMapper("products.xlsx"); var products = mapper.Fetch().ToList(); foreach (var product in products) { Console.WriteLine($"{product.Name}: {product.Price:C} ({product.Quantity} in stock)"); } ``` -------------------------------- ### Basic Write to Excel Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/quick-reference.md Save a list of Product objects to an Excel file named 'output.xlsx' on a sheet named 'Sheet1'. ```csharp var products = new List { ... }; new ExcelMapper().Save("output.xlsx", products, "Sheet1"); ``` -------------------------------- ### Get TypeMapper ColumnsByName Property Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/excelmapper-api-reference.md Accesses the mapping of column names to ColumnInfo objects, which is case-insensitive. ```csharp public Dictionary> ColumnsByName { get; set; } ``` -------------------------------- ### Basic Excel Read Operation Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/README.md Demonstrates how to read data from an Excel file into a list of custom objects. Ensure the Product class properties match the Excel column headers. ```csharp using Ganss.Excel; public class Product { [Column("Product Name")] public string Name { get; set; } [Column("Price")] public decimal Price { get; set; } } var products = new ExcelMapper("file.xlsx").Fetch(); ``` -------------------------------- ### Initialize ExcelMapper with File Path Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/excelmapper-api-reference.md Initializes and loads an Excel file from the specified path. Throws FileNotFoundException if the file does not exist. ```csharp var mapper = new ExcelMapper("products.xlsx"); var products = mapper.Fetch(); ``` -------------------------------- ### DateFormat Property Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/excelmapper-api-reference.md Gets or sets the date format for DateTime cells using NPOI builtin format index. ```csharp public short DateFormat { get; set; } ``` -------------------------------- ### Basic Excel Write Operation Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/README.md Shows how to write a list of objects to an Excel file. The data is saved to a sheet named 'Products'. ```csharp var data = new List { ... }; new ExcelMapper().Save("file.xlsx", data, "Products"); ``` -------------------------------- ### Custom Object Factory for Interface Types Source: https://github.com/mganss/excelmapper/blob/master/README.md Illustrates using a custom object factory to create instances of interface types. This is useful when direct instantiation is not possible or requires specific initialization. ```csharp public class Person { public string Name { get; set; } public IAddress Address { get; set; } } ``` ```csharp excel.CreateInstance(() => new Address()); ``` -------------------------------- ### ColumnAttribute by Name Example Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/attributes.md Maps a property to an Excel column using its header name. The mapping direction can also be specified. ```csharp public class Product { [Column("Product Name")] public string Name { get; set; } [Column("In Stock", MappingDirections.ExcelToObject)] public int StockCount { get; set; } } ``` -------------------------------- ### DefaultDateFormat Property Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/excelmapper-api-reference.md Gets or sets the default date format for all ExcelMapper instances. Defaults to 0x16 (m/d/yy h:mm). ```csharp public static short DefaultDateFormat { get; set; } = 0x16; ``` -------------------------------- ### Configure Mapper Before Operation Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/README.md Illustrates setting mapper configurations like enabling the header row and skipping blank rows before fetching data. These settings affect the import process. ```csharp var mapper = new ExcelMapper("file.xlsx"); mapper.HeaderRow = true; // Before Fetch/Save mapper.SkipBlankRows = true; var products = mapper.Fetch(); ``` -------------------------------- ### Initialize ExcelMapper with Stream Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/excelmapper-api-reference.md Initializes and loads an Excel file from a stream. Ensure the stream is properly disposed after use. ```csharp using var stream = File.OpenRead("products.xlsx"); var mapper = new ExcelMapper(stream); var products = mapper.Fetch(); ``` -------------------------------- ### ExcelMapper Constructors Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/excelmapper-api-reference.md Provides different ways to initialize the ExcelMapper, including loading from a file, a stream, an NPOI workbook, or a default instance. ```APIDOC ## ExcelMapper() ### Description Initializes a new instance of the `ExcelMapper` class without attaching a workbook. You must call `Attach()` before using `Fetch()` or `Save()`. ### Constructor `public ExcelMapper()` ### Example ```csharp var mapper = new ExcelMapper(); mapper.Attach("products.xlsx"); var products = mapper.Fetch(); ``` ``` ```APIDOC ## ExcelMapper(IWorkbook workbook) ### Description Initializes the `ExcelMapper` with a provided NPOI `IWorkbook` object, enabling in-memory Excel operations. ### Constructor `public ExcelMapper(IWorkbook workbook)` ### Parameters - **workbook** (NPOI.SS.UserModel.IWorkbook) - The NPOI workbook object to use. ### Example ```csharp var workbook = new XSSFWorkbook(); var mapper = new ExcelMapper(workbook); mapper.Save(stream, objects, "Sheet1"); ``` ``` ```APIDOC ## ExcelMapper(string file) ### Description Initializes the `ExcelMapper` and loads an Excel file from the specified file path. ### Constructor `public ExcelMapper(string file)` ### Parameters - **file** (string) - The path to the Excel file (.xlsx or .xls). ### Throws - `System.IO.FileNotFoundException` - If the specified file does not exist. ### Example ```csharp var mapper = new ExcelMapper("products.xlsx"); var products = mapper.Fetch(); ``` ``` ```APIDOC ## ExcelMapper(Stream stream) ### Description Initializes the `ExcelMapper` and loads an Excel file from the provided stream. ### Constructor `public ExcelMapper(Stream stream)` ### Parameters - **stream** (System.IO.Stream) - The stream containing the Excel data. ### Example ```csharp using var stream = File.OpenRead("products.xlsx"); var mapper = new ExcelMapper(stream); var products = mapper.Fetch(); ``` ``` -------------------------------- ### Data Format Configuration with Attribute Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/mapping-patterns.md Use the [DataFormat("format_string")] attribute to specify how data should be formatted when read from Excel, e.g., dates, currency, percentages. ```csharp public class Invoice { public string Number { get; set; } [DataFormat(0x0f)] // d-mmm-yy public DateTime InvoiceDate { get; set; } [DataFormat("$#,##0.00")] // Currency public decimal Amount { get; set; } [DataFormat("0%")] // Percentage public decimal TaxRate { get; set; } } var mapper = new ExcelMapper("invoices.xlsx"); var invoices = mapper.Fetch(); ``` -------------------------------- ### Property Mapping by Convention Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/quick-reference.md When Excel headers exactly match property names, no explicit mapping configuration is needed. ```csharp // Excel headers match property names exactly var products = mapper.Fetch(); ``` -------------------------------- ### Object Factory for Complex Initialization Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/mapping-patterns.md Allows customization of object creation for properties, even when a default constructor exists. Useful for setting default values or performing complex initialization. ```csharp public class Product { public string Name { get; set; } public ProductMetadata Metadata { get; set; } } public class ProductMetadata { public DateTime CreatedAt { get; set; } public string CreatedBy { get; set; } public ProductMetadata() { CreatedAt = DateTime.UtcNow; CreatedBy = Environment.UserName; } } var mapper = new ExcelMapper("products.xlsx"); // Default factory works, but can be customized: mapper.CreateInstance(() => new ProductMetadata()); var products = mapper.Fetch(); ``` -------------------------------- ### Example of Disabling Nested Type Mapping Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/configuration.md Illustrates fetching data with and without nested types being mapped. When IgnoreNestedTypes is true, nested properties are ignored. ```csharp public class Order { public string Number { get; set; } public Customer Customer { get; set; } // Nested type } public class Customer { public string Name { get; set; } public string Email { get; set; } } // With default IgnoreNestedTypes = false var mapper = new ExcelMapper("orders.xlsx"); var orders = mapper.Fetch(); // Order.Customer will be populated if columns match // Disable nested mapping mapper.IgnoreNestedTypes = true; var orders = mapper.Fetch(); // Order.Customer will not be mapped ``` -------------------------------- ### Map through method calls Source: https://github.com/mganss/excelmapper/blob/master/README.md Configures mappings programmatically using the AddMapping method. ```C# var excel = new ExcelMapper("products.xls"); excel.AddMapping("Number", p => p.NumberInStock); excel.AddMapping(1, p => p.NumberInStock); excel.AddMapping(typeof(Product), "Number", "NumberInStock"); excel.AddMapping(typeof(Product), ExcelMapper.LetterToIndex("A"), "NumberInStock"); ``` -------------------------------- ### Select JSON Serialization for Column Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/excelmapper-api-reference.md Use this method to enable JSON serialization for a property's value in a column. An example demonstrates its usage with the AddMapping method. ```csharp public ColumnInfo AsJson() ``` ```csharp mapper.AddMapping("Items", o => o.Items).AsJson(); ``` -------------------------------- ### Property Mapping by Attribute Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/quick-reference.md Use attributes like [Column] and [Ignore] to configure property mapping by header name, column index, column letter, or to exclude properties. ```csharp public class Product { [Column("Product Name")] // By header name public string Name { get; set; } [Column(1)] // By column index public decimal Price { get; set; } [Column(Letter = "C")] // By column letter public int Stock { get; set; } [Ignore] // Skip this property public string Ignored { get; set; } } ``` -------------------------------- ### Custom Value Conversion Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/configuration.md Configure ExcelMapper to use a custom value converter function for processing cell values. This example demonstrates trimming whitespace from string cells. ```csharp var mapper = new ExcelMapper("products.xlsx"); var converter = new Func(args => { // Trim whitespace from string cells if (args.CellValue is string s) return s.Trim(); return args.CellValue; }); var products = mapper.Fetch(valueConverter: converter); ``` -------------------------------- ### Log All Conversions with a Custom Value Converter Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/errors.md Implement a simple value converter that logs each cell's value and column name before it's processed. This helps in understanding the data flow and identifying values at the point of conversion. ```csharp var converter = new Func(args => { Console.WriteLine($"Converting [{args.ColumnName}] = {args.CellValue}"); return args.CellValue; }); var products = mapper.Fetch(valueConverter: converter).ToList(); ``` -------------------------------- ### Attach File Method Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/excelmapper-api-reference.md Loads and attaches an Excel file from a specified file path. ```csharp public void Attach(string file) ``` -------------------------------- ### Configure Column Formatting with Fluent API Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/mapping-patterns.md Use the fluent API to map properties and apply built-in formats like currency to Excel columns. ```csharp var mapper = new ExcelMapper("invoices.xlsx"); mapper.AddMapping("Amount", i => i.Amount) .BuiltinFormat = 7; // Currency format (or use property) mapper.AddMapping("TaxRate", i => i.TaxRate); // Access ColumnInfo to set format ``` -------------------------------- ### Inspect Raw Data Before Type Fetching Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/errors.md Read data as dynamic objects first to inspect the raw values and structure before attempting to fetch strongly-typed objects. This is useful for understanding unexpected data formats. ```csharp // Read as dynamic first to inspect raw data var dynamic = mapper.Fetch().ToList(); foreach (var row in dynamic) { Console.WriteLine($"Row: {string.Join(", ", row.Keys)} = {string.Join(", ", row.Values)}"); } // Then fetch with proper type var products = mapper.Fetch().ToList(); ``` -------------------------------- ### Register Action Before Mapping Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/excelmapper-api-reference.md Registers an action to execute before each object is mapped. The action receives the object and its index. ```csharp public ExcelMapper AddBeforeMapping(Action action) ``` ```csharp mapper.AddBeforeMapping((p, index) => { p.ImportedAt = DateTime.UtcNow; }); ``` -------------------------------- ### Initialize ExcelMapper without Workbook Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/excelmapper-api-reference.md Initializes a new ExcelMapper instance without attaching a workbook. Use Attach() before Fetch() or Save(). ```csharp var mapper = new ExcelMapper(); mapper.Attach("products.xlsx"); var products = mapper.Fetch(); ``` -------------------------------- ### Handle Cell Parsing Errors Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/types.md Example of handling the ErrorParsingCell event to log conversion errors and suppress exceptions. This allows the mapping process to continue even if some cells cannot be parsed correctly. ```csharp mapper.ErrorParsingCell += (sender, e) => { Console.WriteLine($"Conversion error at [{e.Error.Line}:{e.Error.Column}]: {e.Error.Message}"); e.Cancel = true; // Don't throw, continue mapping with null/default }; var products = mapper.Fetch(); ``` -------------------------------- ### Global Name Normalization Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/quick-reference.md Apply a global function to normalize all column and property names, for example, by converting them to lowercase and trimming whitespace. This helps in matching Excel headers to C# property names. ```csharp mapper.NormalizeUsing(name => name.ToLower().Trim()); ``` -------------------------------- ### Performance Tip: Reuse Mapper Instance Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/quick-reference.md Reuse an existing `ExcelMapper` instance to benefit from cached type mappers. This avoids redundant initialization and improves performance when mapping multiple different types. ```csharp var mapper = new ExcelMapper(); var products = mapper.Fetch(); var orders = mapper.Fetch(); // Reuses cached mappers ``` -------------------------------- ### Handle Conversion Errors with Exception Properties Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/quick-reference.md Catch `ExcelMapperConvertException` to get detailed information about conversion errors, including the cell's location (line and column), the problematic cell value, and the target type. ```csharp try { var data = mapper.Fetch(); } catch (ExcelMapperConvertException ex) { Console.WriteLine($"Cell [{ex.Line}:{ex.Column}]: {ex.CellValue}"); Console.WriteLine($"Target type: {ex.TargetType}"); } ``` -------------------------------- ### Define Excel Formula Property Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/attributes.md Use the Formula attribute on a string property to indicate that its value should be saved as an Excel formula. The property value should not start with '=', as ExcelMapper adds it automatically. This attribute only affects saving. ```csharp public class Spreadsheet { [Formula] public string TotalFormula { get; set; } } var data = new Spreadsheet { TotalFormula = "SUM(B1:B10)" // Note: no = prefix }; mapper.Save("output.xlsx", new[] { data }, "Sheet1"); // Cell will contain formula: =SUM(B1:B10) ``` -------------------------------- ### Independent ExcelMapper Instances Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/configuration.md Demonstrates that each ExcelMapper instance has its own independent configuration. Changes to one instance do not affect others. ```csharp var mapper1 = new ExcelMapper(); mapper1.HeaderRow = false; var mapper2 = new ExcelMapper(); // Separate instance // mapper2.HeaderRow = true (default, not inherited) ``` -------------------------------- ### Configure ColumnInfo Class Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/excelmapper-api-reference.md Represents the configuration for a property-to-column mapping in ExcelMapper. ```csharp public class ColumnInfo ``` -------------------------------- ### Import Namespaces for ExcelMapper Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/README.md Includes the necessary namespaces for using the ExcelMapper library and its exception types. ```csharp using Ganss.Excel; using Ganss.Excel.Exceptions; ``` -------------------------------- ### Create TypeMapper by Analyzing Type Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/excelmapper-api-reference.md Creates a TypeMapper instance by analyzing the properties of a given type. This is the typical way to instantiate a TypeMapper for a specific class. ```csharp public static TypeMapper Create(Type type) ``` ```csharp var typeMapper = TypeMapper.Create(typeof(Product)); ``` -------------------------------- ### Catching ExcelMapperConvertException Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/errors.md Demonstrates how to catch and log specific details about a conversion error during the Fetch operation. This is useful for user feedback or debugging. ```csharp try { var products = mapper.Fetch(); } catch (ExcelMapperConvertException ex) { Console.WriteLine($"Row {ex.Line + 1}, Column {ex.Column + 1}: " + $"Cannot convert '{ex.CellValue}' to {ex.TargetType.Name}"); Console.WriteLine($"Error: {ex.Message}"); } ``` -------------------------------- ### Property Mapping by Fluent API Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/quick-reference.md Configure property mapping and ignore properties using the fluent API methods AddMapping and Ignore. ```csharp mapper.AddMapping("Name", p => p.Name); mapper.AddMapping(2, p => p.Price); mapper.Ignore(p => p.Ignored); ``` -------------------------------- ### Use Async for I/O Operations Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/README.md Utilize asynchronous methods like FetchAsync for I/O-bound operations to prevent blocking the main thread. This is essential for maintaining application responsiveness when dealing with large files. ```csharp var data = await mapper.FetchAsync("large_file.xlsx"); ``` -------------------------------- ### AddBeforeMapping Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/excelmapper-api-reference.md Registers an action to execute before each object is mapped. This allows for pre-processing of data before properties are set. ```APIDOC ## AddBeforeMapping(Action action) ### Description Registers an action to execute before each object is mapped (before properties are set). ### Method ```csharp public ExcelMapper AddBeforeMapping(Action action) ``` ### Parameters #### Path Parameters - **action** (Action) - Required - Called with object and index ### Return `ExcelMapper` — For fluent chaining ### Example ```csharp mapper.AddBeforeMapping((p, index) => { p.ImportedAt = DateTime.UtcNow; }); ``` ``` -------------------------------- ### Async Read with Configuration Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/configuration.md Configure ExcelMapper for asynchronous reading of Excel data. Object tracking is typically disabled for async operations to optimize performance. ```csharp var mapper = new ExcelMapper(); mapper.HeaderRow = true; mapper.SkipBlankRows = true; mapper.TrackObjects = false; // Don't track for async var products = await mapper.FetchAsync("products.xlsx"); ``` -------------------------------- ### Track and update objects Source: https://github.com/mganss/excelmapper/blob/master/README.md Fetches objects from an Excel file, modifies them, and saves the changes back to a new file. ```C# var products = new ExcelMapper("products.xlsx").Fetch().ToList(); products[1].Price += 1.0m; excel.Save("products.out.xlsx"); ``` -------------------------------- ### Data Formatting with Attributes Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/quick-reference.md Apply data formatting to properties using the [DataFormat] attribute with built-in or custom format strings. ```csharp [DataFormat(0x0f)] // Builtin format (date) [DataFormat("$#,##0.00")] // Custom format (currency) public decimal Price { get; set; } ``` -------------------------------- ### Attach Workbook Method Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/excelmapper-api-reference.md Attaches an NPOI workbook for operations. Requires an instance of NPOI.SS.UserModel.IWorkbook. ```csharp public void Attach(IWorkbook workbook) ``` -------------------------------- ### Configure Excel Mappings with Fluent API Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/examples.md Dynamically configure column mappings at runtime using the fluent AddMapping method. This is useful when column names or target properties vary. ```csharp public class Customer { public string FirstName { get; set; } public string LastName { get; set; } public string EmailAddress { get; set; } public string PhoneNumber { get; set; } } var mapper = new ExcelMapper("customers.xlsx"); // Configure mappings fluently mapper.AddMapping("First Name", c => c.FirstName); mapper.AddMapping("Last Name", c => c.LastName); mapper.AddMapping("Email", c => c.EmailAddress); mapper.AddMapping("Phone", c => c.PhoneNumber); var customers = mapper.Fetch().ToList(); foreach (var customer in customers) { Console.WriteLine($"{customer.FirstName} {customer.LastName}: {customer.EmailAddress}"); } ``` -------------------------------- ### Specify File Format for Saving Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/quick-reference.md Explicitly define the output file format (.xlsx or .xls) when saving data by using the `xlsx` parameter. ```csharp mapper.Save("file.xlsx", data, "Sheet", xlsx: true); // .xlsx mapper.Save("file.xls", data, "Sheet", xlsx: false); // .xls ``` -------------------------------- ### Dynamic mapping Source: https://github.com/mganss/excelmapper/blob/master/README.md Fetches data as a collection of dynamic objects without requiring a static class definition. ```C# var products = new ExcelMapper("products.xlsx").Fetch(); // -> IEnumerable products.First().Price += 1.0; ``` -------------------------------- ### Standard Excel with Headers Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/configuration.md Configure ExcelMapper for a standard Excel file where the first row contains headers. Uses default settings for row ranges and blank row skipping. ```csharp var mapper = new ExcelMapper("products.xlsx"); // All defaults: // - HeaderRow = true (first row has headers) // - HeaderRowNumber = 0 (headers in row 1) // - MinRowNumber = 0, MaxRowNumber = int.MaxValue // - SkipBlankRows = true // - TrackObjects = true var products = mapper.Fetch(); ``` -------------------------------- ### Track Objects and Save Modifications Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/excelmapper-api-reference.md Enables tracking of fetched objects, allowing modifications to be saved back to an Excel file without re-specifying the object list. ```csharp var mapper = new ExcelMapper("products.xlsx"); var products = mapper.Fetch().ToList(); products[0].Price += 1.0m; mapper.Save("products.out.xlsx"); // Saves modified tracked objects ``` -------------------------------- ### Handle Formula Cells Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/examples.md Demonstrates reading calculated values from Excel cells using the `[FormulaResult]` attribute and writing formulas using the `[Formula]` attribute. ```csharp public class Spreadsheet { public decimal Value1 { get; set; } public decimal Value2 { get; set; } [FormulaResult] // For string: read result, not formula public string TotalCalculation { get; set; } [FormulaResult] public decimal ComputedTotal { get; set; } } var mapper = new ExcelMapper("calculations.xlsx"); var sheets = mapper.Fetch().ToList(); // If Excel cell contains "=SUM(A1:A5)" with result 150: // TotalCalculation = "150" (string) // ComputedTotal = 150.0 (decimal) // When saving with formula cells: var data = new Spreadsheet { Value1 = 50, Value2 = 100, ComputedTotal = 150, TotalCalculation = "SUM(A1:A2)" }; [Formula] public string SumFormula { get; set; } // This would be saved as formula mapper.Save("output.xlsx", new[] { data }, "Results"); ``` -------------------------------- ### Read, Modify, and Save Workflow Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/quick-reference.md A common pattern involving reading data, enabling object tracking, modifying objects in memory, and then saving the changes back to a new Excel file. ```csharp mapper.TrackObjects = true; var products = mapper.Fetch().ToList(); products[0].Price *= 1.1m; mapper.Save("output.xlsx", "Products"); ``` -------------------------------- ### Excel without Headers, Using Column Indexes Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/configuration.md Configure ExcelMapper for files that do not have headers. Column mapping is done using explicit column indexes defined via the Column attribute. ```csharp public class Product { [Column(1)] public string Name { get; set; } [Column(2)] public decimal Price { get; set; } [Column(3)] public int Quantity { get; set; } } var mapper = new ExcelMapper("products.xlsx"); mapper.HeaderRow = false; var products = mapper.Fetch(); ``` -------------------------------- ### Register Action After Mapping Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/excelmapper-api-reference.md Registers an action to execute after each object is mapped. The action receives the object and its index. ```csharp public ExcelMapper AddAfterMapping(Action action) ``` -------------------------------- ### Enable Object Tracking for Modifications Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/README.md Enables object tracking to modify fetched objects and save changes without re-passing the data. Changes to tracked objects are automatically persisted. ```csharp mapper.TrackObjects = true; var products = mapper.Fetch().ToList(); products[0].Price *= 1.1m; mapper.Save("output.xlsx"); // No need to pass products again ``` -------------------------------- ### Templated Output Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/quick-reference.md Use an existing Excel file as a template for output. ExcelMapper preserves the template's formatting, structure, and sheets while populating it with new data. ```csharp var mapper = new ExcelMapper("template.xlsx"); mapper.TrackObjects = true; mapper.Fetch(); // Modify mapped objects... mapper.Save("output.xlsx"); // Preserves template formatting ``` -------------------------------- ### Implement Mapping Hooks Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/examples.md Uses `AddAfterMapping` to execute custom logic after properties are mapped, such as computing derived fields or performing data validation and population. ```csharp public class Employee { public string FirstName { get; set; } public string LastName { get; set; } public string Email { get; set; } public DateTime HireDate { get; set; } [Ignore] public string FullName { get; set; } [Ignore] public int YearsEmployed { get; set; } } var mapper = new ExcelMapper("employees.xlsx"); mapper.AddAfterMapping((employee, index) => { // Compute full name after properties are set employee.FullName = $"{employee.FirstName} {employee.LastName}"; // Compute tenure employee.YearsEmployed = (DateTime.Now - employee.HireDate).Days / 365; // Generate email if missing if (string.IsNullOrEmpty(employee.Email)) employee.Email = $"{employee.FirstName.ToLower()}.{employee.LastName.ToLower()}@company.com"; }); var employees = mapper.Fetch().ToList(); foreach (var emp in employees) { Console.WriteLine($"{emp.FullName} ({emp.Email}) - {emp.YearsEmployed} years"); } ``` -------------------------------- ### Implementing a Custom Value Converter Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/errors.md Provides a custom function to handle value conversions, allowing for specific logic, fallbacks, or error handling for particular columns or data types. ```csharp var converter = new Func(args => { try { // Custom conversion logic if (args.ColumnName == "Date" && args.CellValue is string s) { if (DateTime.TryParse(s, out var dt)) return dt; return DateTime.MinValue; // Fallback } } catch { // Handle errors } return args.CellValue; }); var products = mapper.Fetch(valueConverter: converter); ``` -------------------------------- ### Read, Modify, and Save Excel Data Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/examples.md Read data from an Excel file, modify specific properties (e.g., price), and save the changes back to a new file. Enable object tracking with 'mapper.TrackObjects = true' for modifications. The 'products.xlsx' file is read, and 'products_updated.xlsx' is created. ```csharp var mapper = new ExcelMapper("products.xlsx"); mapper.TrackObjects = true; // Enable object tracking // Read products var products = mapper.Fetch().ToList(); // Modify foreach (var product in products) { product.Price *= 1.10m; // 10% price increase product.LastUpdated = DateTime.Now; } // Save tracked objects mapper.Save("products_updated.xlsx", "Products"); Console.WriteLine($"Updated {products.Count} products"); ``` -------------------------------- ### Enable Object Tracking in ExcelMapper Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/configuration.md Set TrackObjects to true to enable tracking of fetched objects. This allows modifications to be saved without re-specifying the object list. Defaults to true. ```csharp public bool TrackObjects { get; set; } = true; ``` -------------------------------- ### Initialize ExcelMapper with NPOI Workbook Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/excelmapper-api-reference.md Initializes ExcelMapper with an NPOI IWorkbook object for in-memory operations. Used for saving objects to a stream. ```csharp var workbook = new XSSFWorkbook(); var mapper = new ExcelMapper(workbook); mapper.Save(stream, objects, "Sheet1"); ``` -------------------------------- ### Map Nested Objects to Record Hierarchy Source: https://github.com/mganss/excelmapper/blob/master/README.md Shows how to map Excel data to C# records with nested structures. Records provide immutability and concise syntax. ```csharp public record Person(string Name, DateTime Birthday, Address Address); public record Address(string Street, string City, string Zip); ``` -------------------------------- ### Set Per-Instance Data Format Source: https://github.com/mganss/excelmapper/blob/master/_autodocs/quick-reference.md Set the date format for a specific ExcelMapper instance. ```csharp mapper.DateFormat = 0x0f; ```