Skip to content

Commit 05f4b8f

Browse files
Add a way to gather unmapped cells
1 parent ff42b20 commit 05f4b8f

7 files changed

Lines changed: 79 additions & 7 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,8 @@ var excel = new ExcelQueryFactory("excelFileName");
215215
excel.StrictMapping = StrictMappingType.Both;
216216
```
217217

218+
If you are using `None` or `ClassStrict` mapping, you can retain unmapped columns by implementing the `IContainsUnmappedCells` interface. This will put all values from the unmapped columns into a dictionary on your class named `UnmappedCells`.
219+
218220
## Manually setting the database engine
219221

220222
LinqToExcel can use the Jet or Ace database engine, and it automatically determines the database engine to use by the file extension. You can manually set the database engine with the `DatabaseEngine` property
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+

2+
using System.Collections.Generic;
3+
4+
namespace LinqToExcel.Tests
5+
{
6+
class CompanyNameWithUnmappedCells : IContainsUnmappedCells
7+
{
8+
public CompanyNameWithUnmappedCells()
9+
{
10+
UnmappedCells = new Dictionary<string, Cell>();
11+
}
12+
13+
public string Name { get; set; }
14+
public IDictionary<string, Cell> UnmappedCells { get; private set; }
15+
}
16+
}

src/LinqToExcel.Tests/ExcelQueryFactoryTests.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,24 @@ public void StrictMapping_Not_Explicitly_Set_with_additional_class_properties_do
284284
Assert.AreEqual(1, companies.Count);
285285
}
286286

287+
[Test]
288+
public void IContainsUnmappedCells_FillsInUnmappedCells()
289+
{
290+
var excel = new ExcelQueryFactory(_excelFileName, new LogManagerFactory());
291+
excel.AddMapping<Company>(x => x.IsActive, "Active");
292+
293+
var companies = (from c in excel.Worksheet<CompanyNameWithUnmappedCells>()
294+
where c.Name == "ACME"
295+
select c).ToList();
296+
297+
Assert.AreEqual(1, companies.Count);
298+
Assert.AreEqual("ACME", companies[0].Name);
299+
Assert.AreEqual(3, companies.First().UnmappedCells.Count);
300+
Assert.AreEqual("Bugs Bunny", companies.First().UnmappedCells["CEO"].Value);
301+
Assert.AreEqual(25, companies.First().UnmappedCells["EmployeeCount"].Cast<int>());
302+
Assert.AreEqual(new DateTime(1918, 11, 11), companies.First().UnmappedCells["StartDate"].Cast<DateTime>());
303+
}
304+
287305
[Test]
288306
public void TrimSpaces_Start_TrimsWhiteSpacesAtTheBeginning()
289307
{

src/LinqToExcel.Tests/LinqToExcel.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
<Compile Include="CompanyNullable.cs" />
9393
<Compile Include="CompanyWithColumnAnnotations.cs" />
9494
<Compile Include="CompanyWithCity.cs" />
95+
<Compile Include="CompanyNameWithUnmappedCells.cs" />
9596
<Compile Include="ConfiguredWorksheetName_SQLStatements_UnitTests.cs" />
9697
<Compile Include="ConfiguredWorksheetName_IntegrationTests.cs" />
9798
<Compile Include="Convention_SQLStatements_UnitTests.cs" />
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System.Collections.Generic;
2+
3+
namespace LinqToExcel
4+
{
5+
/// <summary>
6+
/// Implement this interface to receive values for cells that
7+
/// were not mapped.
8+
/// </summary>
9+
public interface IContainsUnmappedCells
10+
{
11+
IDictionary<string, Cell> UnmappedCells { get; }
12+
}
13+
}

src/LinqToExcel/LinqToExcel.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484
<ItemGroup>
8585
<Compile Include="Attributes\ExcelColumnAttribute.cs" />
8686
<Compile Include="Domain\Cell.cs" />
87+
<Compile Include="Domain\IContainsUnmappedCells.cs" />
8788
<Compile Include="Domain\RowNoHeader.cs" />
8889
<Compile Include="Domain\StrictMappingException.cs" />
8990
<Compile Include="Exceptions\ExcelException.cs" />

src/LinqToExcel/Query/ExcelQueryExecutor.cs

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -316,29 +316,50 @@ private IEnumerable<object> GetTypeResults(IDataReader data, IEnumerable<string>
316316
var props = fromType.GetProperties();
317317
if (_args.StrictMapping.Value != StrictMappingType.None)
318318
this.ConfirmStrictMapping(columns, props, _args.StrictMapping.Value);
319+
var gatherUnmappedCells = typeof(IContainsUnmappedCells).IsAssignableFrom(fromType);
319320

320321
var currentRowNumber = 0;
321322
while (data.Read())
322323
{
323324
currentRowNumber++;
324325
var result = Activator.CreateInstance(fromType);
325-
foreach (var prop in props)
326+
327+
var propMapping = props.Select(prop => new
326328
{
327-
var columnName = (_args.ColumnMappings.ContainsKey(prop.Name)) ?
329+
prop,
330+
columnName = (_args.ColumnMappings.ContainsKey(prop.Name)) ?
328331
_args.ColumnMappings[prop.Name] :
329-
prop.Name;
332+
prop.Name
333+
});
334+
335+
foreach (var mapping in propMapping)
336+
{
330337
try
331338
{
332-
if (columns.Contains(columnName))
339+
if (columns.Contains(mapping.columnName))
333340
{
334-
var value = GetColumnValue(data, columnName, prop.Name).Cast(prop.PropertyType);
341+
var value = GetColumnValue(data, mapping.columnName, mapping.prop.Name).Cast(mapping.prop.PropertyType);
335342
value = TrimStringValue(value);
336-
result.SetProperty(prop.Name, value);
343+
result.SetProperty(mapping.prop.Name, value);
337344
}
338345
}
339346
catch (Exception exception)
340347
{
341-
throw new Exceptions.ExcelException(currentRowNumber, columnName, exception);
348+
throw new Exceptions.ExcelException(currentRowNumber, mapping.columnName, exception);
349+
}
350+
}
351+
352+
if (gatherUnmappedCells)
353+
{
354+
var gatherer = (IContainsUnmappedCells)result;
355+
if (gatherer.UnmappedCells != null)
356+
{
357+
foreach (var col in columns.Except(propMapping.Select(x => x.columnName)))
358+
{
359+
var value = data[col];
360+
value = TrimStringValue(value);
361+
gatherer.UnmappedCells[col] = new Cell(value);
362+
}
342363
}
343364
}
344365
results.Add(result);

0 commit comments

Comments
 (0)