Skip to content

Commit 9d59b57

Browse files
Merge PR 785: Fixes enum behaviour and adds support for DescriptionAttribute when saving by template
2 parents eeb4f2c + 9162f51 commit 9d59b57

File tree

9 files changed

+276
-267
lines changed

9 files changed

+276
-267
lines changed

samples/xlsx/Issue527Template.xlsx

9.31 KB
Binary file not shown.

src/MiniExcel/Csv/CsvReader.cs

Lines changed: 98 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -7,108 +7,108 @@
77
using System.Text.RegularExpressions;
88
using System.Threading;
99
using System.Threading.Tasks;
10+
using MiniExcelLibs.Exceptions;
1011

1112
namespace MiniExcelLibs.Csv
1213
{
1314
internal class CsvReader : IExcelReader
1415
{
1516
private Stream _stream;
1617
private CsvConfiguration _config;
18+
1719
public CsvReader(Stream stream, IConfiguration configuration)
1820
{
19-
this._stream = stream;
20-
this._config = configuration == null ? CsvConfiguration.DefaultConfiguration : (CsvConfiguration)configuration;
21+
_stream = stream;
22+
_config = configuration == null ? CsvConfiguration.DefaultConfiguration : (CsvConfiguration)configuration;
2123
}
2224
public IEnumerable<IDictionary<string, object>> Query(bool useHeaderRow, string sheetName, string startCell)
2325
{
2426
if (startCell != "A1")
25-
throw new NotImplementedException("CSV not Implement startCell");
27+
throw new NotImplementedException("CSV does not implement parameter startCell");
28+
2629
if (_stream.CanSeek)
2730
_stream.Position = 0;
31+
2832
var reader = _config.StreamReaderFunc(_stream);
33+
var firstRow = true;
34+
var headRows = new Dictionary<int, string>();
35+
36+
string row;
37+
for (var rowIndex = 1; (row = reader.ReadLine()) != null; rowIndex++)
2938
{
30-
string[] read;
31-
var firstRow = true;
32-
Dictionary<int, string> headRows = new Dictionary<int, string>();
33-
string row;
34-
for (var rowIndex = 1; (row = reader.ReadLine()) != null; rowIndex++)
39+
string finalRow = row;
40+
if (_config.ReadLineBreaksWithinQuotes)
3541
{
36-
37-
string finalRow = row;
38-
if (_config.ReadLineBreaksWithinQuotes)
42+
while (finalRow.Count(c => c == '"') % 2 != 0)
3943
{
40-
while (finalRow.Count(c => c == '"') % 2 != 0)
44+
var nextPart = reader.ReadLine();
45+
if (nextPart == null)
4146
{
42-
var nextPart = reader.ReadLine();
43-
if (nextPart == null)
44-
{
45-
break;
46-
}
47-
finalRow = string.Concat(finalRow, _config.NewLine, nextPart);
47+
break;
4848
}
49+
finalRow = string.Concat(finalRow, _config.NewLine, nextPart);
4950
}
50-
read = Split(finalRow);
51+
}
52+
var read = Split(finalRow);
5153

52-
// invalid row check
53-
if (read.Length < headRows.Count)
54-
{
55-
var colIndex = read.Length;
56-
var headers = headRows.ToDictionary(x => x.Value, x => x.Key);
57-
var rowValues = read.Select((x, i) => new { Key = headRows[i], Value = x }).ToDictionary(x => x.Key, x => (object)x.Value);
58-
throw new Exceptions.ExcelColumnNotFoundException(null,
59-
headRows[colIndex], null, rowIndex, headers, rowValues, $"Csv read error, Column: {colIndex} not found in Row: {rowIndex}");
60-
}
54+
// invalid row check
55+
if (read.Length < headRows.Count)
56+
{
57+
var colIndex = read.Length;
58+
var headers = headRows.ToDictionary(x => x.Value, x => x.Key);
59+
var rowValues = read
60+
.Select((x, i) => new KeyValuePair<string, object>(headRows[i], x))
61+
.ToDictionary(x => x.Key, x => x.Value);
62+
63+
throw new ExcelColumnNotFoundException(columnIndex: null, headRows[colIndex], null, rowIndex, headers, rowValues, $"Csv read error: Column {colIndex} not found in Row {rowIndex}");
64+
}
6165

62-
//header
63-
if (useHeaderRow)
66+
//header
67+
if (useHeaderRow)
68+
{
69+
if (firstRow)
6470
{
65-
if (firstRow)
66-
{
67-
firstRow = false;
68-
for (int i = 0; i <= read.Length - 1; i++)
69-
headRows.Add(i, read[i]);
70-
continue;
71-
}
72-
73-
var cell = CustomPropertyHelper.GetEmptyExpandoObject(headRows);
71+
firstRow = false;
7472
for (int i = 0; i <= read.Length - 1; i++)
75-
cell[headRows[i]] = read[i];
76-
77-
yield return cell;
73+
headRows.Add(i, read[i]);
7874
continue;
7975
}
8076

77+
var headCell = CustomPropertyHelper.GetEmptyExpandoObject(headRows);
78+
for (int i = 0; i <= read.Length - 1; i++)
79+
headCell[headRows[i]] = read[i];
8180

82-
//body
83-
{
84-
// record first row as reference
85-
if (firstRow)
86-
{
87-
firstRow = false;
88-
for (int i = 0; i <= read.Length - 1; i++)
89-
headRows.Add(i, $"c{i + 1}");
90-
}
81+
yield return headCell;
82+
continue;
83+
}
9184

92-
var cell = CustomPropertyHelper.GetEmptyExpandoObject(read.Length - 1, 0);
93-
if (_config.ReadEmptyStringAsNull)
94-
{
95-
for (int i = 0; i <= read.Length - 1; i++)
96-
cell[ColumnHelper.GetAlphabetColumnName(i)] = read[i]?.Length == 0 ? null : read[i];
97-
}
98-
else
99-
{
100-
for (int i = 0; i <= read.Length - 1; i++)
101-
cell[ColumnHelper.GetAlphabetColumnName(i)] = read[i];
102-
}
85+
//body
86+
if (firstRow) // record first row as reference
87+
{
88+
firstRow = false;
89+
for (int i = 0; i <= read.Length - 1; i++)
90+
headRows.Add(i, $"c{i + 1}");
91+
}
10392

104-
yield return cell;
105-
}
93+
var cell = CustomPropertyHelper.GetEmptyExpandoObject(read.Length - 1, 0);
94+
if (_config.ReadEmptyStringAsNull)
95+
{
96+
for (int i = 0; i <= read.Length - 1; i++)
97+
cell[ColumnHelper.GetAlphabetColumnName(i)] = read[i]?.Length == 0 ? null : read[i];
10698
}
99+
else
100+
{
101+
for (int i = 0; i <= read.Length - 1; i++)
102+
cell[ColumnHelper.GetAlphabetColumnName(i)] = read[i];
103+
}
104+
105+
yield return cell;
107106
}
108107
}
109108
public IEnumerable<T> Query<T>(string sheetName, string startCell, bool hasHeader) where T : class, new()
110109
{
111-
return ExcelOpenXmlSheetReader.QueryImpl<T>(Query(false, sheetName, startCell), startCell, hasHeader, _config);
110+
var dynamicRecords = Query(false, sheetName, startCell);
111+
return ExcelOpenXmlSheetReader.QueryImpl<T>(dynamicRecords, startCell, hasHeader, _config);
112112
}
113113

114114
private string[] Split(string row)
@@ -119,9 +119,10 @@ private string[] Split(string row)
119119
}
120120
else
121121
{
122-
return Regex.Split(row, $"[\t{_config.Seperator}](?=(?:[^\"]|\"[^\"]*\")*$)")
123-
.Select(s => Regex.Replace(s.Replace("\"\"", "\""), "^\"|\"$", "")).ToArray();
124122
//this code from S.O : https://stackoverflow.com/a/11365961/9131476
123+
return Regex.Split(row, $"[\t{_config.Seperator}](?=(?:[^\"]|\"[^\"]*\")*$)")
124+
.Select(s => Regex.Replace(s.Replace("\"\"", "\""), "^\"|\"$", ""))
125+
.ToArray();
125126
}
126127
}
127128

@@ -143,56 +144,55 @@ public void Dispose()
143144
public IEnumerable<IDictionary<string, object>> QueryRange(bool useHeaderRow, string sheetName, string startCell, string endCell)
144145
{
145146
if (startCell != "A1")
146-
throw new NotImplementedException("CSV not Implement startCell");
147+
throw new NotImplementedException("CSV does not implement parameter startCell");
148+
147149
if (_stream.CanSeek)
148150
_stream.Position = 0;
151+
149152
var reader = _config.StreamReaderFunc(_stream);
153+
154+
string row;
155+
var firstRow = true;
156+
var headRows = new Dictionary<int, string>();
157+
158+
while ((row = reader.ReadLine()) != null)
150159
{
151-
var row = string.Empty;
152-
string[] read;
153-
var firstRow = true;
154-
Dictionary<int, string> headRows = new Dictionary<int, string>();
155-
while ((row = reader.ReadLine()) != null)
156-
{
157-
read = Split(row);
160+
var read = Split(row);
158161

159-
//header
160-
if (useHeaderRow)
162+
//header
163+
if (useHeaderRow)
164+
{
165+
if (firstRow)
161166
{
162-
if (firstRow)
163-
{
164-
firstRow = false;
165-
for (int i = 0; i <= read.Length - 1; i++)
166-
headRows.Add(i, read[i]);
167-
continue;
168-
}
169-
170-
var cell = CustomPropertyHelper.GetEmptyExpandoObject(headRows);
167+
firstRow = false;
171168
for (int i = 0; i <= read.Length - 1; i++)
172-
cell[headRows[i]] = read[i];
173-
174-
yield return cell;
169+
headRows.Add(i, read[i]);
175170
continue;
176171
}
177172

173+
var headCell = CustomPropertyHelper.GetEmptyExpandoObject(headRows);
174+
for (int i = 0; i <= read.Length - 1; i++)
175+
headCell[headRows[i]] = read[i];
178176

179-
//body
180-
{
181-
var cell = CustomPropertyHelper.GetEmptyExpandoObject(read.Length - 1, 0);
182-
for (int i = 0; i <= read.Length - 1; i++)
183-
cell[ColumnHelper.GetAlphabetColumnName(i)] = read[i];
184-
yield return cell;
185-
}
177+
yield return headCell;
178+
continue;
186179
}
180+
181+
//body
182+
var cell = CustomPropertyHelper.GetEmptyExpandoObject(read.Length - 1, 0);
183+
for (int i = 0; i <= read.Length - 1; i++)
184+
cell[ColumnHelper.GetAlphabetColumnName(i)] = read[i];
185+
186+
yield return cell;
187187
}
188188
}
189189
public IEnumerable<T> QueryRange<T>(string sheetName, string startCell, string endCel) where T : class, new()
190190
{
191191
return ExcelOpenXmlSheetReader.QueryImplRange<T>(QueryRange(false, sheetName, startCell, endCel), startCell, endCel, this._config);
192192
}
193-
public Task<IEnumerable<IDictionary<string, object>>> QueryAsyncRange(bool UseHeaderRow, string sheetName, string startCell, string endCel, CancellationToken cancellationToken = default)
193+
public Task<IEnumerable<IDictionary<string, object>>> QueryAsyncRange(bool useHeaderRow, string sheetName, string startCell, string endCel, CancellationToken cancellationToken = default)
194194
{
195-
return Task.Run(() => QueryRange(UseHeaderRow, sheetName, startCell, endCel), cancellationToken);
195+
return Task.Run(() => QueryRange(useHeaderRow, sheetName, startCell, endCel), cancellationToken);
196196
}
197197

198198
public Task<IEnumerable<T>> QueryAsyncRange<T>(string sheetName, string startCell, string endCel, bool hasHeader, CancellationToken cancellationToken = default) where T : class, new()

0 commit comments

Comments
 (0)