Если вы используете пустой конструктор для создания DataColumn
без имени, в документации указано ...
При создании объект DataColumn
не имеет по умолчанию ColumnName
или Caption
. Когда вы добавляете его к DataColumnCollection
, будет сгенерировано имя по умолчанию ("Column1"
, "Column2"
и т. Д.), Если имя не было присвоено ColumnName
.
... поэтому создание и загрузка DataTable
вот так ...
const string Input = @"1 | 05/01/2020 Fri | ABC | XYZ | ...
2 | 05/01/2020 Fri | AAA | WKV | ...
3 | 05/02/2020 Sat | BCD | OPQ | ...
4 | 05/03/2020 Sun | CDE | RST | ...
5 | 05/03/2020 Sun | EFA | FAY | ...
6 | 05/03/2020 Sun | AXG | EAS | ...
7 | 05/04/2020 Mon | DEF | LMN | ...
8 | 05/04/2020 Mon | SXA | YTR | ...
9 | 05/05/2020 Tue | DAF | AAG | ...";
DtFromExcel = new DataTable();
for (int i = 0; i < 5; i++)
{
DataColumn column = new DataColumn();
Console.WriteLine($"Column {i} has ColumnName \"{column.ColumnName}\"");
DtFromExcel.Columns.Add(column);
Console.WriteLine($"Column {i} has ColumnName \"{column.ColumnName}\"");
}
foreach (string line in Input.Split("\r\n"))
{
string[] fields = line.Split(" | ");
DtFromExcel.Rows.Add(fields);
}
... производит этот вывод ...
Column 0 has ColumnName ""
Column 0 has ColumnName "Column1"
Column 1 has ColumnName ""
Column 1 has ColumnName "Column2"
Column 2 has ColumnName ""
Column 2 has ColumnName "Column3"
Column 3 has ColumnName ""
Column 3 has ColumnName "Column4"
Column 4 has ColumnName ""
Column 4 has ColumnName "Column5"
... чтобы вы могли всегда используйте эти имена по умолчанию. Кроме того, тот факт, что в ваших входных данных не указаны имена столбцов / полей, не означает, что вы не можете этого сделать после того, как они были загружены в DataTable
...
DtFromExcel.Columns[1].ColumnName = "MyDateColumn";
В любом случае вы у вас будет известное имя, по которому вы можете ссылаться на этот столбец.
Что касается вашего комментария о нежелании «l oop через весь DataTable
», не ясно, имеете ли вы в виду из-за дополнительный код или, возможно, влияние на производительность, но до последнего пункта, даже если вы явно не l oop через и тестируете каждый DataRow
, Select()
будет . В этой заметке, поскольку вы говорите, что строки упорядочены по дате, вы можете использовать это с помощью LINQ , чтобы остановить сканирование строк, как только будет найдена дата за пределами диапазона поиска ...
private static DateTime GetRowDate(DataRow row) => DateTime.ParseExact(
(string) row["MyDateColumn"], "MM/dd/yyyy ddd", null
);
private void DeleteRows(DateTime maxDate)
{
DataRow[] rowsToRemove = DtFromExcel.AsEnumerable()
.TakeWhile(row => GetRowDate(row) <= maxDate)
.ToArray();// Required to prevent "Collection was modified" exception in foreach below
foreach (DataRow row in rowsToRemove)
DtFromExcel.Rows.Remove(row);
}
Если не гарантируется сортировка строк по дате, вы можете заменить Where()
на TakeWhile()
, и это будет работать точно так же.
Что касается вашего исходного запроса на использование DateTable.Select()
, я не уверен, что это вообще возможно, поскольку ваши даты, похоже, хранятся как string
, а не DateTime
, в вашем DataColumn
. Я вижу, что синтаксис выражения поддерживает CONVERT()
функцию , которая может преобразовывать между String
и DateTime
, но я не могу представить, что это было бы более производительным или читаемым чем LINQ, поэтому я бы не стал этим заниматься, если в этом нет крайней необходимости.