Skip to content

Commit

Permalink
Read empty string as null (#555) (#556)
Browse files Browse the repository at this point in the history
Co-authored-by: Paweł Szybiak <pawel.szybiak@vsoft.pl>
  • Loading branch information
pszybiak and Paweł Szybiak authored Jan 7, 2024
1 parent 55153d8 commit 3d63587
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 2 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1255,7 +1255,16 @@ var config = new MiniExcelLibs.Csv.CsvConfiguration()
MiniExcel.SaveAs(path, value,excelType:ExcelType.CSV, configuration: config);
```

#### Read empty string as null

By default, empty values are mapped to string.Empty. You can modify this behavior

```csharp
var config = new MiniExcelLibs.Csv.CsvConfiguration()
{
ReadEmptyStringAsNull = true
};
```


### DataReader
Expand Down
1 change: 1 addition & 0 deletions src/MiniExcel/Csv/CsvConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public class CsvConfiguration : Configuration

public char Seperator { get; set; } = ',';
public string NewLine { get; set; } = "\r\n";
public bool ReadEmptyStringAsNull { get; set; } = false;
public bool AlwaysQuote { get; set; } = false;
public Func<string, string[]> SplitFn { get; set; }
public Func<Stream, StreamReader> StreamReaderFunc { get; set; } = (stream) => new StreamReader(stream, _defaultEncoding);
Expand Down
13 changes: 11 additions & 2 deletions src/MiniExcel/Csv/CsvReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,17 @@ public IEnumerable<IDictionary<string, object>> Query(bool useHeaderRow, string
//body
{
var cell = CustomPropertyHelper.GetEmptyExpandoObject(read.Length - 1, 0);
for (int i = 0; i <= read.Length - 1; i++)
cell[ColumnHelper.GetAlphabetColumnName(i)] = read[i];
if (_config.ReadEmptyStringAsNull)
{
for (int i = 0; i <= read.Length - 1; i++)
cell[ColumnHelper.GetAlphabetColumnName(i)] = read[i]?.Length == 0 ? null : read[i];
}
else
{
for (int i = 0; i <= read.Length - 1; i++)
cell[ColumnHelper.GetAlphabetColumnName(i)] = read[i];
}

yield return cell;
}
}
Expand Down
50 changes: 50 additions & 0 deletions tests/MiniExcelTests/MiniExcelCsvAsycTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -269,5 +269,55 @@ await MiniExcel.SaveAsAsync(path, new[] {

File.Delete(path);
}

[Fact()]
public async Task CsvReadEmptyStringAsNullTest()
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.csv");
await MiniExcel.SaveAsAsync(path, new[] {
new { c1 = "A1" ,c2 = (string)null},
new { c1 = (string)null ,c2 = (string)null},
});

using (var stream = File.OpenRead(path))
{
var rows = stream.Query<Test>(excelType: ExcelType.CSV).ToList();
Assert.Equal("A1", rows[0].c1);
Assert.Equal(string.Empty, rows[0].c2);
Assert.Equal(string.Empty, rows[1].c1);
Assert.Equal(string.Empty, rows[1].c2);
}

{
var rows = MiniExcel.Query<Test>(path, excelType: ExcelType.CSV).ToList();
Assert.Equal("A1", rows[0].c1);
Assert.Equal(string.Empty, rows[0].c2);
Assert.Equal(string.Empty, rows[1].c1);
Assert.Equal(string.Empty, rows[1].c2);
}

var config = new MiniExcelLibs.Csv.CsvConfiguration()
{
ReadEmptyStringAsNull = true
};
using (var stream = File.OpenRead(path))
{
var rows = stream.Query<Test>(excelType: ExcelType.CSV, configuration: config).ToList();
Assert.Equal("A1", rows[0].c1);
Assert.Null(rows[0].c2);
Assert.Null(rows[1].c1);
Assert.Null(rows[1].c2);
}

{
var rows = MiniExcel.Query<Test>(path, excelType: ExcelType.CSV, configuration: config).ToList();
Assert.Equal("A1", rows[0].c1);
Assert.Null(rows[0].c2);
Assert.Null(rows[1].c1);
Assert.Null(rows[1].c2);
}

File.Delete(path);
}
}
}

0 comments on commit 3d63587

Please sign in to comment.