Skip to content

Commit

Permalink
Merge pull request #39 from IowaComputerGurus/feature/updates
Browse files Browse the repository at this point in the history
Rollup of feedback items
  • Loading branch information
mitchelsellers authored Dec 30, 2022
2 parents fe905f5 + 34da96d commit 1b6a7e1
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,23 @@ public void ParseDocument_ShouldReturnProperData()
Assert.Equal("John Smith", firstRecord.Name);
Assert.Equal(55, firstRecord.Age);
}

[Fact]
public void ParseDocument_ShouldReturnProperData_BySheetName()
{
//Arrange
var filePath = "../../../SampleFiles/ImportSample.xlsx";
var expectedCount = 3;

//Act
var result = _spreadsheetParser.ParseDocument<PersonRecord>(File.OpenRead(filePath), "Test Sheet", true);

//Assert
Assert.Equal(expectedCount, result.Count);
var firstRecord = result.First();
Assert.Equal("John Smith", firstRecord.Name);
Assert.Equal(55, firstRecord.Age);
var lastRecord = result.Last();
Assert.Equal("Adam", lastRecord.Name);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

namespace ICG.NetCore.Utilities.Spreadsheet.Tests;

Expand Down Expand Up @@ -99,7 +100,7 @@ public class DifferentTestExportRecord
[SpreadsheetImportColumn(1)]
public int Id { get; set; }

[SpreadsheetColumn(displayName: "Company")]
[Display(Name = "Testing This Out")]
[SpreadsheetImportColumn(2)]
public string Company { get; set; } = "";

Expand Down
Binary file not shown.
18 changes: 18 additions & 0 deletions src/NetCore.Utilities.Spreadsheet.Tests/TypeDiscovererTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using Bogus.DataSets;
using FluentAssertions;
using Xunit;

Expand Down Expand Up @@ -39,6 +41,16 @@ public void Sets_DisplayName_From_SpreadsheetColumn_Attribute()
results.First().DisplayName.Should().Be("Some Prop Name");
}

[Fact]
public void Sets_DisplayName_From_Display_Attribute()
{
var results = TypeDiscoverer.GetProps(typeof(Sets_DisplayName_From_DisplayAttribute_Attribute_TestCase));

results.Should().HaveCount(1);

results.First().DisplayName.Should().Be("Some Prop Name");
}

[Fact]
public void Property_Excluded_From_SpreadsheetIgnore_Attribute()
{
Expand Down Expand Up @@ -81,6 +93,12 @@ private class Sets_DisplayName_From_SpreadsheetColumn_Attribute_TestCase
public string SomeProp { get; set; }
}

private class Sets_DisplayName_From_DisplayAttribute_Attribute_TestCase
{
[Display(Name = "Some Prop Name")]
public string SomeProp { get; set; }
}

private class Property_Excluded_From_SpreadsheetColumn_Attribute_TestCase
{
[SpreadsheetColumn(ignore: true)]
Expand Down
10 changes: 10 additions & 0 deletions src/NetCore.Utilities.Spreadsheet/ISpreadsheetParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,14 @@ public interface ISpreadsheetParser
/// <param name="skipHeaderRow">If set to true will skip the first row of data as header information</param>
/// <returns>The parsed information</returns>
List<T> ParseDocument<T>(Stream fileStream, int worksheetNumber, bool skipHeaderRow) where T : new();

/// <summary>
/// Parses the provided document and returns a list of T objects based on the input data, using the specific worksheet by name
/// </summary>
/// <typeparam name="T">The type to use for importing</typeparam>
/// <param name="fileStream">The contents of the Excel File (XLSX format</param>
/// <param name="worksheetName"></param>
/// <param name="skipHeaderRow">If set to true will skip the first row of data as header information</param>
/// <returns></returns>
List<T> ParseDocument<T>(Stream fileStream, string worksheetName, bool skipHeaderRow) where T : new();
}
34 changes: 29 additions & 5 deletions src/NetCore.Utilities.Spreadsheet/OpenXmlSpreadsheetParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,18 @@ public class OpenXmlSpreadsheetParser : ISpreadsheetParser

/// <inheritdoc />
public List<T> ParseDocument<T>(Stream fileStream, int worksheetNumber, bool skipHeaderRow) where T : new()
{
return ParseDocumentInternal<T>(fileStream, worksheetNumber, string.Empty, skipHeaderRow);
}

/// <inheritdoc />
public List<T> ParseDocument<T>(Stream fileStream, string worksheetName, bool skipHeaderRow) where T : new()
{
return ParseDocumentInternal<T>(fileStream, null, worksheetName, skipHeaderRow);
}

private List<T> ParseDocumentInternal<T>(Stream fileStream, int? worksheetNumber, string worksheetName,
bool skipHeaderRow) where T : new()
{
//Validate object is properly created
var importColumnDefinitions = typeof(T)
Expand All @@ -49,13 +61,24 @@ public class OpenXmlSpreadsheetParser : ISpreadsheetParser
var workbookPart = excelDoc.WorkbookPart;
if (workbookPart == null) throw new SpreadsheetParserException("Spreadsheet has no WorkbookPart");

var sheet = workbookPart.Workbook.Descendants<Sheet>().Skip(worksheetNumber - 1).FirstOrDefault();
if (sheet == null) throw new SpreadsheetParserException($"Workbook does not have {worksheetNumber} sheets");
Sheet sheet;
if (worksheetNumber.HasValue)
{
sheet = workbookPart.Workbook.Descendants<Sheet>().Skip(worksheetNumber.Value - 1).FirstOrDefault();
if (sheet == null) throw new SpreadsheetParserException($"Workbook does not have {worksheetNumber} sheets");
}
else
{
sheet = workbookPart.Workbook.Descendants<Sheet>().First(s => s.Name == worksheetName);
if (sheet == null)
throw new SpreadsheetParserException($"Workbook does not have a sheet named '{worksheetName}'");
}

if (sheet.Id == null || !sheet.Id.HasValue || sheet.Id.Value == null) throw new SpreadsheetParserException($"Sheet {worksheetNumber} has a null Id");

if (workbookPart.GetPartById(sheet.Id.Value) is not WorksheetPart wsPart)
if (workbookPart.GetPartById(sheet.Id.Value) is not WorksheetPart wsPart)
throw new SpreadsheetParserException($"Sheet {worksheetNumber} with Id {sheet.Id.Value} is not in the workbook");

var collection = new Collection<T>();
var skipRows = skipHeaderRow ? 1 : 0;
var expectedColumns = importColumnDefinitions.Max(c => c.Column) - 1;
Expand Down Expand Up @@ -86,8 +109,9 @@ public class OpenXmlSpreadsheetParser : ISpreadsheetParser


return collection.ToList();

}


private static bool IsOfType<T>(Type t)
{
var typeToCheck = typeof(T);
Expand Down
6 changes: 6 additions & 0 deletions src/NetCore.Utilities.Spreadsheet/TypeDiscoverer.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Text.RegularExpressions;

namespace ICG.NetCore.Utilities.Spreadsheet;
Expand Down Expand Up @@ -48,6 +49,11 @@ public static IList<PropDetail> GetProps(Type t)
propName = sca.DisplayName ?? propName;
width = sca.Width;
}
else if (attr is DisplayAttribute display)
{
if (!string.IsNullOrEmpty(display.Name))
propName = display.Name;
}
}

if (ignored) continue;
Expand Down

0 comments on commit 1b6a7e1

Please sign in to comment.