{"id":19414762,"url":"https://github.com/hughbe/excel-mapper","last_synced_at":"2025-04-07T05:06:59.431Z","repository":{"id":37405605,"uuid":"96175737","full_name":"hughbe/excel-mapper","owner":"hughbe","description":"Fluently map excel rows to C# objects","archived":false,"fork":false,"pushed_at":"2024-09-21T09:12:24.000Z","size":704,"stargazers_count":166,"open_issues_count":17,"forks_count":19,"subscribers_count":10,"default_branch":"main","last_synced_at":"2025-03-31T04:04:03.902Z","etag":null,"topics":["csv","excel","xlsx"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hughbe.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-07-04T04:38:40.000Z","updated_at":"2025-02-19T10:25:42.000Z","dependencies_parsed_at":"2024-11-17T13:02:03.845Z","dependency_job_id":"69b0eaff-d2fe-44cf-8570-74c7e9396533","html_url":"https://github.com/hughbe/excel-mapper","commit_stats":{"total_commits":140,"total_committers":7,"mean_commits":20.0,"dds":0.06428571428571428,"last_synced_commit":"ededd87b2fd5253753f71194ef47b79f61fed4e4"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hughbe%2Fexcel-mapper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hughbe%2Fexcel-mapper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hughbe%2Fexcel-mapper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hughbe%2Fexcel-mapper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hughbe","download_url":"https://codeload.github.com/hughbe/excel-mapper/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247595333,"owners_count":20963943,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csv","excel","xlsx"],"created_at":"2024-11-10T12:39:37.390Z","updated_at":"2025-04-07T05:06:59.371Z","avatar_url":"https://github.com/hughbe.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ExcelMapper\n\nA library that reads a row of an Excel sheet and maps it to an object. A flexible and extensible fluent mapping system allows you to customize the way the row is mapped to an object.\n\n![.NET Core](https://github.com/hughbe/excel-mapper/workflows/.NET%20Core/badge.svg)\n[![Nuget](https://img.shields.io/nuget/v/ExcelDataReader.Mapping)](https://www.nuget.org/packages/ExcelDataReader.Mapping/)\n\n## Basic Mapping\n\nExcelMapper will go through each public property or field and attempt to map the value of the cell in the column with the name of the member. If the column cannot be found or mapped, an exception will be thrown.\n\n| Name          | Location         | Attendance | Date       | Link                    | Revenue | Successful | Cause   |\n|---------------|------------------|------------|------------|-------------------------|---------|------------|---------|\n| Pub Quiz      | The Blue Anchor  | 20         | 18/07/2017 | http://eventbrite.com   | 100.2   | TRUE       | Charity |\n| Live Music    | The Raven        | 15         | 17/07/2017 | http://ticketmaster.com | 105.6   | FALSE      | Profit  |\n| Live Football | The Rutland Arms | 45         | 16/07/2017 | http://facebook.com     | 263.9   | TRUE       | Profit  |\n\n\n```cs\npublic enum EventCause\n{\n    Profit,\n    Charity\n}\n\npublic class Event\n{\n    public string Name { get; set; }\n    public string Location { get; set; }\n    public int Attendance { get; set; }\n    public DateTime Date { get; set; }\n    public Uri Link { get; set; }\n    public EventCause Cause { get; set; }\n}\n\n// ...\n\nusing var stream = File.OpenRead(\"Pub Events.xlsx\");\nusing var importer = new ExcelImporter(stream);\n\nExcelSheet sheet = importer.ReadSheet();\nEvent[] events = sheet.ReadRows\u003cEvent\u003e().ToArray();\nConsole.WriteLine(events[0].Name); // Pub Quiz\nConsole.WriteLine(events[1].Name); // Live Music\nConsole.WriteLine(events[2].Name); // Live Football\n```\n\nYou can skip blank lines by setting `importer.Configuration.SkipBlankLines = true`. This is off by default for performance reasons.\n\n## Attribute Mapping\n\n### Custom Column Names\nExcelMapper supports specifying a custom column name with the `ExcelColumnName` attribute. This is useful for cases where we want to map a column name that is different from the property name in the data structure, for example the column name contains whitespace or the column name contains characters that can't be represented in C#.\n\n| Full Name      | #Age |\n|----------------|------|\n| Donald Trump   | 73   |\n| Barack Obama   | 58   |\n\n```cs\npublic class President\n{\n    [ExcelColumnName(\"Full Name\")]\n    public string Name { get; set; }\n\n    [ExcelColumnName(\"#Age\")]\n    public int Age { get; set; }\n}\n\n\n// ...\n\nusing var stream = File.OpenRead(\"Presidents.xlsx\");\nusing var importer = new ExcelImporter(stream);\n\nExcelSheet sheet = importer.ReadSheet();\nPresident[] president = sheet.ReadRows\u003cPresident\u003e().ToArray();\nConsole.WriteLine(president[0].Name); // Donald Trump\nConsole.WriteLine(president[0].Age); // 73\nConsole.WriteLine(president[1].Name); // Barack Obama\nConsole.WriteLine(president[1].Age); // 58\n```\n\n### Ignoring Properties\nExcelMapper supports ignoring properties when deserializing with the `ExcelIgnoreAttribute` attribute. This is useful for cases where the the data structure is recursive, or the property is missing data and you don't want to create a custom mapper and call `MakeOptional`.\n\n| Name           | Age |\n|----------------|-----|\n| Donald Trump   | 73  |\n| Barack Obama   | 58  |\n\n```cs\npublic class President\n{\n    public string Name { get; set; }\n\n    // If you want to ignore a property that exists for any reason.\n    [ExcelIgnore]\n    public int Age { get; set; }\n\n    // If you want to ignore a property that doesn't exist for any reason.\n    [ExcelIgnore]\n    public object NoSuchColumn { get; set; }\n\n    // If the data structure is recursive\n    [ExcelIgnore]\n    public President PreviousPresident { get; set; }\n}\n\n\n// ...\n\nusing var stream = File.OpenRead(\"Presidents.xlsx\");\nusing var importer = new ExcelImporter(stream);\n\nExcelSheet sheet = importer.ReadSheet();\nPresident[] president = sheet.ReadRows\u003cPresident\u003e().ToArray();\nConsole.WriteLine(president[0].Name); // Donald Trump\nConsole.WriteLine(president[0].Age); // 0\nConsole.WriteLine(president[0].NoSuchColumn); // null\nConsole.WriteLine(president[0].PreviousPresident); // null\nConsole.WriteLine(president[1].Name); // Barack Obama\nConsole.WriteLine(president[1].Age); // 0\nConsole.WriteLine(president[1].NoSuchColumn); // null\nConsole.WriteLine(president[1].PreviousPresident); // null\n```\n\n## Defining a custom mapping\n\nExcelMapper allows customizing the class map used when mapping a row in an Excel sheet to an object.\n\nCustom class maps allow you to change the column used to map a cell or make that column optional. You can also change the default map of the class, adding custom conversions.\n\n| Name           | Marrital Status | Number of Children | Approval Rating (%) | Date of Birth |\n|----------------|-----------------|--------------------|---------------------|---------------|\n| Donald Trump   | Twice Married   | 5                  | 60%                 | 1946-06-14    |\n| Barack Obama   | Married         | 2                  | 50                  | 04/08/1961    |\n| Ronald Reagan  | Divorced        | 5                  | 75                  | 06/03/1911    |\n| James Buchanan | Single          | 0                  | 100                 | 1791-04-23    |\n\n\n\n```cs\npublic enum MaritalStatus\n{\n    Married,\n    Divorced,\n    Single\n}\n\npublic class President\n{\n    public string Name { get; set; }\n    public MaritalStatus MaritalStatus { get; set; }\n    public int NumberOfChildren { get; set; }\n    public float ApprovalRating { get; set; }\n    public DateTime DateOfBirth { get; set; }\n\n    public int NumberOfTerms { get; set; }\n}\n\npublic class PresidentClassMap : ExcelClassMap\u003cPresident\u003e\n{\n    public PresidentClassMap()\n    {\n        // Simple mapping.\n        Map(president =\u003e president.Name);\n\n        // Map invalid unknown value to a known value.\n        Map(president =\u003e president.MaritalStatus)\n            .WithColumnName(\"Marrital Status\")\n            .WithMapping(new Dictionary\u003cstring, MaritalStatus\u003e\n            {\n                { \"Twice Married\", MaritalStatus.Married    }\n            });\n\n        // Read from a column index.\n        Map(president =\u003e president.NumberOfChildren)\n            .WithColumnIndex(2);\n\n        // Read with a custom converter delegate.\n        Map(president =\u003e president.ApprovalRating)\n            .WithConverter(value =\u003e int.Parse(value) / 100f)\n            .WithColumnName(\"Approval Rating (%)\");\n\n        // Read a date with one or more formats.\n        Map(president =\u003e president.DateOfBirth)\n            .WithColumnName(\"Date of Birth\")\n            .WithDateFormats(\"yyyy-MM-dd\", \"g\");\n\n        // Read a missing column.\n        Map(president =\u003e president.NumberOfTerms)\n            .MakeOptional();\n    }\n}\n\n// ...\n\nusing (var stream = File.OpenRead(\"Presidents.xlsx\"))\nusing (var importer = new ExcelImporter(stream))\n{\n    // You can register class maps by type.\n    importer.Configuration.RegisterClassMap\u003cPresidentClassMap\u003e();\n\n    // Or by namespace.\n    importer.RegisterMapperClassesByNamespace(\"My.Namespace\");\n\n    ExcelSheet sheet = importer.ReadSheet();\n    President[] president = sheet.ReadRows\u003cPresident\u003e().ToArray();\n    Console.WriteLine(president[0].Name); // Donald Trump\n    Console.WriteLine(president[1].Name); // Barack Obama\n    Console.WriteLine(president[2].Name); // Ronald Reagan\n    Console.WriteLine(president[2].Name); // James Buchanan\n}\n```\n\n## Nullables and fallbacks\n\nExcelMapper will set nullable values to `null` if the value of the cell is empty. By default an exception will be thrown if the value of the cell is invalid and cannot be mapped to the type of the property or field.\n\nYou can customize the fallback to use a fixed value if the value of a cell is empty or the value of the cell cannot be mapped.\n\n| Name           | Marrital Status | Number of Children | Date of Birth |\n|----------------|-----------------|--------------------|---------------|\n| Donald Trump   | Twice Married   | invalid            | invalid       |\n| Barack Obama   |                 |                    |               |\n| Ronald Reagan  | Divorced        | 5                  | 06/03/1911    |\n| James Buchanan | Single          | 0                  | 1791-04-23    |\n\n\n```cs\npublic enum MaritalStatus\n{\n    Married,\n    Single,\n    Invalid,\n    Unknown\n}\n\npublic class President\n{\n    public string Name { get; set; }\n    public MaritalStatus MaritalStatus { get; set; }\n    public int? NumberOfChildren { get; set; }\n    public DateTime? DateOfBirth { get; set; }\n}\n\npublic class PresidentClassMap : ExcelClassMap\u003cPresident\u003e\n{\n    public PresidentClassMap()\n    {\n        Map(president =\u003e president.Name);\n\n        Map(president =\u003e president.MaritalStatus)\n            .WithColumnName(\"Marrital Status\")\n            .WithEmptyFallback(MaritalStatus.Unknown)\n            .WithInvalidFallback(MaritalStatus.Invalid);\n\n        Map(president =\u003e president.NumberOfChildren)\n            .WithColumnIndex(2)\n            .WithInvalidFallback(-1);\n\n        Map(president =\u003e president.DateOfBirth)\n            .WithColumnName(\"Date of Birth\")\n            .WithDateFormats(\"yyyy-MM-dd\", \"g\")\n            .WithInvalidFallback(null);\n    }\n}\n\n// ...\n\n\nusing (var stream = File.OpenRead(\"Presidents.xlsx\"))\nusing (var importer = new ExcelImporter(stream))\n{\n    // You can register class maps by type.\n    importer.Configuration.RegisterClassMap\u003cPresidentClassMap\u003e();\n\n    // Or by namespace.\n    importer.RegisterMapperClassesByNamespace(\"My.Namespace\");\n\n    ExcelSheet sheet = importer.ReadSheet();\n    President[] president = sheet.ReadRows\u003cPresident\u003e().ToArray();\n    Console.WriteLine(president[0].Name); // Donald Trump\n    Console.WriteLine(president[1].Name); // Barack Obama\n    Console.WriteLine(president[2].Name); // Ronald Reagan\n    Console.WriteLine(president[2].Name); // James Buchanan\n}\n```\n\n## Mapping enums\n\nExcelMapper supports mapping string values to an enum. By default this is case sensitive matching the behaviour of the .NET Framework, but this case be overriden in a custom map.\n\n| Name           | Marrital Status | Number of Children | Date of Birth |\n|----------------|-----------------|--------------------|---------------|\n| Donald Trump   | Married         | invalid            | invalid       |\n| Barack Obama   |                 |                    |               |\n| Ronald Reagan  | diVorCED        | 5                  | 06/03/1911    |\n| James Buchanan | Single          | 0                  | 1791-04-23    |\n\n\n```cs\npublic enum MaritalStatus\n{\n    Married,\n    Single,\n    Invalid,\n    Unknown\n}\n\npublic class President\n{\n    public string Name { get; set; }\n    public MaritalStatus MaritalStatus { get; set; }\n}\n\npublic class PresidentClassMap : ExcelClassMap\u003cPresident\u003e\n{\n    public PresidentClassMap()\n    {\n        Map(president =\u003e president.Name);\n\n        Map(president =\u003e president.MaritalStatus, ignoreCase: true)\n            .WithColumnName(\"Marrital Status\")\n            .WithEmptyFallback(MaritalStatus.Unknown)\n            .WithInvalidFallback(MaritalStatus.Invalid);\n    }\n}\n\n// ...\n\n\nusing (var stream = File.OpenRead(\"Presidents.xlsx\"))\nusing (var importer = new ExcelImporter(stream))\n{\n    // You can register class maps by type.\n    importer.Configuration.RegisterClassMap\u003cPresidentClassMap\u003e();\n\n    // Or by namespace.\n    importer.RegisterMapperClassesByNamespace(\"My.Namespace\");\n\n    ExcelSheet sheet = importer.ReadSheet();\n    President[] president = sheet.ReadRows\u003cPresident\u003e().ToArray();\n    Console.WriteLine(president[0].Name); // Donald Trump\n    Console.WriteLine(president[1].Name); // Barack Obama\n    Console.WriteLine(president[2].Name); // Ronald Reagan\n    Console.WriteLine(president[2].Name); // James Buchanan\n}\n```\n\n## Mapping enumerables\n\nExcelMapper supports mapping enumerables and lists. If no column names or column indices are supplied then the value of the cell will be split with the `','` separator.\n\n| Name         | Children Names | First Election | Second Election | First Inauguration | Second Inauguration |\n|--------------|----------------|----------------|-----------------|--------------------|---------------------|\n| Barack Obama | Malia,Sasha    | 04/11/2008     | 06/11/2012      | 2009-01-20         | 20/01/2013          |\n\n```cs\npublic class President\n{\n    public string Name { get; set; }\n    public IEnumerable\u003cstring\u003e ChildrenNames { get; set; }\n    public IEnumerable\u003cDateTime\u003e Elections { get; set; }\n    public IEnumerable\u003cDateTime\u003e Inaugurations { get; set; }\n}\n\npublic class PresidentClassMap : ExcelClassMap\u003cPresident\u003e\n{\n    public PresidentClassMap()\n    {\n        Map(president =\u003e president.Name);\n\n        // Default: splits with \",\".\n        Map(president =\u003e president.ChildrenNames)\n            .WithColumnName(\"Children Names\");\n\n        // Reads the values of multiple columns in order given.\n        Map(president =\u003e president.Elections)\n            .WithColumnNames(\"First Election\", \"Second Election\");\n\n        // Reads the values of multiple columns in order given.\n        Map(president =\u003e president.Inaugurations)\n            .WithColumnIndices(4, 5)\n            .WithElementMap(m =\u003e m\n                .WithDateFormats(\"yyyy-MM-dd\", \"g\")\n            );\n    }\n}\n\n// ...\n\n\nusing (var stream = File.OpenRead(\"Presidents.xlsx\"))\nusing (var importer = new ExcelImporter(stream))\n{\n    // You can register class maps by type.\n    importer.Configuration.RegisterClassMap\u003cPresidentClassMap\u003e();\n\n    // Or by namespace.\n    importer.RegisterMapperClassesByNamespace(\"My.Namespace\");\n\n    ExcelSheet sheet = importer.ReadSheet();\n    President[] president = sheet.ReadRows\u003cPresident\u003e().ToArray();\n    Console.WriteLine(president[0].Name); // Barack Obama\n    Console.WriteLine(president[0].ChildrenNames); // [Malia, Sasha]\n    Console.WriteLine(president[0].Elections); // [2008-11-04, 2012-11-06]\n    Console.WriteLine(president[0].Inaugurations); // [2009-01-20, 2013-01-20]\n}\n```\n\n## Mapping nested objects\n\nExcelMapper supports mapping nested objects. If no column names or class map is supplied, then the nested object is automatically mapped based on the names of it's public properties and fields.\n\n\n| Name         | First Elected | Electoral College Votes |\n|--------------|---------------|-------------------------|\n| Barack Obama | 04/11/2008    | 365                     |\n\n```cs\npublic class Election\n{\n    public DateTime Date { get; set; }\n    public int ElectoralCollegeVotes { get; set; }\n}\n\npublic class President\n{\n    public string Name { get; set; }\n    public Election ElectionInformation { get; set; }\n}\n\npublic class PresidentClassMap : ExcelClassMap\u003cPresident\u003e\n{\n    public PresidentClassMap()\n    {\n        Map(president =\u003e president.ElectionInformation.Date)\n            .WithColumnName(\"First Elected\");\n\n        Map(president =\u003e president.ElectionInformation.ElectoralCollegeVotes)\n            .WithColumnName(\"Electoral College Votes\");\n    }\n}\n\n// ...\n\nusing (var stream = File.OpenRead(\"Presidents.xlsx\"))\nusing (var importer = new ExcelImporter(stream))\n{\n    // You can register class maps by type.\n    importer.Configuration.RegisterClassMap\u003cPresidentClassMap\u003e();\n\n    // Or by namespace.\n    importer.RegisterMapperClassesByNamespace(\"My.Namespace\");\n\n    ExcelSheet sheet = importer.ReadSheet();\n    President[] president = sheet.ReadRows\u003cPresident\u003e().ToArray();\n    Console.WriteLine(president[0].Name); // Barack Obama\n    Console.WriteLine(president[0].ElectionInformation.Date) // 2008-11-04\n    Console.WriteLine(president[0].ElectionInformation.ElectoralCollegeVotes) // 365\n}\n```\n\n## Mapping Dictionaries and ExpandObject\n\nExcelMapper supports mapping dictionaries and Expando Object. If no column names are supplied, then the dictionary will contain all columns.\n\n| Name           | Age\n|----------------|----|\n| Barack Obama   | 58 |\n| Michelle Obama | 56 |\n\n### Dictionaries\n\nNote that\n```cs\nusing var stream = File.OpenRead(\"Presidents.xlsx\");\nusing var importer = new ExcelImporter(stream);\n\nExcelSheet sheet = importer.ReadSheet();\nDictionary\u003cstring, string\u003e[] results = sheet.ReadRows\u003cDictionary\u003cstring, string\u003e\u003e().ToArray();\nConsole.WriteLine(results[0].Count); // 2: { { name: \"Barack Obama\" }, { age: \"58\" } }\nConsole.WriteLine(results[1].Count); // 2: { { name: \"Michelle Obama\" }, { age: \"56\" } }\n```\n\n### Field Dictionaries\n\nNote that\n```cs\npublic class DataClass\n{\n    public Dictionary\u003cstring, string\u003e Values { get; set; }\n    // Or\n    public ExpandoObject Values { get; set; }\n}\n\npublic class DataClassMap : ExcelClassMap\u003cDataClass\u003e\n{\n    public DataClass()\n    {\n        // Default: reads all column names.\n        Map(d =\u003e d.Values);\n\n        // Read custom column names.\n        Map(d =\u003e d.Values)\n            .WithColumnNames(\"Name\", \"Age\");\n    }\n}\n\n// ...\n\nusing var stream = File.OpenRead(\"Presidents.xlsx\");\nusing var importer = new ExcelImporter(stream);\n\n// You can register class maps by type.\nimporter.Configuration.RegisterClassMap\u003cDataClassMap\u003e();\n\n// Or by namespace.\nimporter.RegisterMapperClassesByNamespace(\"My.Namespace\");\n\nExcelSheet sheet = importer.ReadSheet();\nDataClass[] results = sheet.ReadRows\u003cDataClass\u003e().ToArray();\nConsole.WriteLine(results[0].Values.Count); // 2: { { name: \"Barack Obama\" }, { age: \"58\" } }\nConsole.WriteLine(results[1].Values.Count); // 2: { { name: \"Michelle Obama\" }, { age: \"56\" } }\n```\n\n# Mapping sheets without headers\n\nBy default, ExcelMapper will read the first row of a sheet as a file header. This can be controlled by setting the boolean property `ExcelSheet.HasHeading`.\nExcelMapper will go through each public property or field and attempt to map the value of the cell in the column with the name of the member. If the column cannot be found or mapped, an exception will be thrown.\n\n|               |                  |\n|---------------|------------------|\n| Pub Quiz      | The Blue Anchor  |\n| Live Music    | The Raven        |\n| Live Football | The Rutland Arms |\n\n```cs\npublic class Event\n{\n    public string Name { get; set; }\n    public string Location { get; set; }\n}\n\npublic class EventClassMap : ExcelClassMap\u003cEvent\u003e\n{\n    public EventClassMap()\n    {\n        // Read from a column index.\n        Map(event =\u003e event.Name)\n            .WithColumnIndex(0);\n\n        Map(event =\u003e event.Location)\n            .WithColumnIndex(1);\n    }\n}\n\n// ...\n\nusing (var stream = File.OpenRead(\"Pub Events.xlsx\"))\nusing (var importer = new ExcelImporter(stream))\n{\n    importer.Configuration.RegisterClassMap\u003cEventClassMap\u003e();\n\n    ExcelSheet sheet = importer.ReadSheet();\n    sheet.HasHeading = false;\n\n    Event[] events = sheet.ReadRows\u003cEvent\u003e().ToArray();\n    Console.WriteLine(events[0].Name); // Pub Quiz\n    Console.WriteLine(events[1].Name); // Live Music\n    Console.WriteLine(events[2].Name); // Live Football\n}\n```\n\n# Reading Sheets\n\nExcelMapper supports multiple sheets and provides APIs to read particular sheets.\n\n## Enumerating through all sheets\n\nUse the `ReadSheets` method to enumerate through all sheets in a document. Enumeration is reset at the end.\n\n```cs\nusing (var stream = File.OpenRead(\"Sheet.xlsx\"))\nusing (var importer = new ExcelImporter(stream))\n{\n    foreach (ExcelSheet sheet in importer.ReadSheets())\n    {\n        // Do something with the sheet.\n    }\n}\n```\n\n## Getting the next sheet\n\nUse the `ReadSheet()` method to read the next sheet. This will throw if there are no more sheets. Use the `TryReadSheet(out ExcelSheet sheet)` method to avoid throwing behaviour.\n\n```cs\nusing (var stream = File.OpenRead(\"Sheet.xlsx\"))\nusing (var importer = new ExcelImporter(stream))\n{\n    // Either:\n    ExcelSheet sheet = importer.ReadSheet();\n\n    // Or:\n    bool success = importer.TryReadSheet(out ExcelSheet sheet);\n}\n```\n\n## Getting a sheet by name\n\nUse the `ReadSheet(string sheetName)` method to read a particular sheet by name. This will throw if the sheet is not found. Use the `TryReadSheet(string sheetName, out ExcelSheet sheet)` method to avoid throwing behaviour.\n\n```cs\nusing (var stream = File.OpenRead(\"Sheet.xlsx\"))\nusing (var importer = new ExcelImporter(stream))\n{\n    // Either:\n    ExcelSheet sheet = importer.ReadSheet(\"Sheet Name\");\n\n    // Or:\n    bool success = importer.TryReadSheet(\"Sheet Name\", out ExcelSheet sheet);\n}\n```\n\n## Getting a sheet by index\n\nUse the `ReadSheet(int sheetIndex)` method to read a particular sheet at the given zero-based index. This will throw if the sheet is not found. Use the `TryReadSheet(int sheetIndex, out ExcelSheet sheet)` method to avoid throwing behaviour.\n\n```cs\nusing (var stream = File.OpenRead(\"Sheet.xlsx\"))\nusing (var importer = new ExcelImporter(stream))\n{\n    // Either:\n    ExcelSheet sheet = importer.ReadSheet(0);\n\n    // Or:\n    bool success = importer.TryReadSheet(0, out ExcelSheet sheet);\n}\n```\n\n# Mapping sheets where the header is not the first row\n\nExcelMapper supports reading headers which are not in the first row. Set the property `ExcelSheet.HeadingIndex` to the zero-based index of the header. All data preceding the header will be skipped and will not be mapped.\n\n|               |                  |\n|---------------|------------------|\n|               |                  |\n|               |                  |\n| Name          | Location         |\n| Pub Quiz      | The Blue Anchor  |\n| Live Music    | The Raven        |\n| Live Football | The Rutland Arms |\n\n```cs\npublic class Event\n{\n    public string Name { get; set; }\n    public string Location { get; set; }\n}\n\n// ...\n\nusing (var stream = File.OpenRead(\"Pub Events.xlsx\"))\nusing (var importer = new ExcelImporter(stream))\n{\n    ExcelSheet sheet = importer.ReadSheet();\n    sheet.HeadingIndex = 3;\n\n    Event[] events = sheet.ReadRows\u003cEvent\u003e().ToArray();\n    Console.WriteLine(events[0].Name); // Pub Quiz\n    Console.WriteLine(events[1].Name); // Live Music\n    Console.WriteLine(events[2].Name); // Live Football\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhughbe%2Fexcel-mapper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhughbe%2Fexcel-mapper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhughbe%2Fexcel-mapper/lists"}