C#通过特定的DataRow索引拆分DataTable

时间:2018-09-19 13:12:02

标签: c# linq

我试图找到关于stackoverflow的任何解决方案,但没有找到。

我有一个 DataTable ,该数据是从excel工作表获取的。该表不清楚,它包含许多子表(以标题开头)以及它们之上的其他必要信息(可能包含空行)。例如:

Line1 : Other data...
[empty line]
Line2: Other data...
[empty line]
...................   
ColA   |   ColB   |   Type   |
------------------------------
AAA    |   BBB    |   IN     |
AAA    |   BBB    |   OUT    |
AAA    |   BBB    |   IN     |

Line1 : Other data...
[empty line]
Line2: Other data...
[empty line]
...................    
ColA   |   ColB   |   Type   |
------------------------------
AAA    |   BBB    |   IN     |
AAA    |   BBB    |   OUT    |
AAA    |   BBB    |   OUT    |

我想将数据表拆分为多个数据表,这些数据表以许多行的必要信息开始,然后是表本身,并以空行结束。结果,我必须获取DataTable []数据类型。

我试图获取数据表各节的最后一行的索引(如果DataRow包含“ in”或“ out”,而下一个索引包含空行),但是我不知道这是否是一个好的代码,并且进一步拆分数据表的好方法:

var indexes = dataTable.AsEnumerable()
    .Where(x => x.ItemArray.All(rowCell => rowCell.ToString() == string.Empty))
    .Where(
       x => dataTable.Rows[dataTable.Rows.IndexOf(x) - 1].ItemArray.Any(
             item => Regex.Match(
                   item.ToString(),
                   "^in|out$",
                   RegexOptions.IgnoreCase).Success))
    .Select(x => dataTable.Rows.IndexOf(x)).ToArray();

我有两个 哪里 linq条件,用于检查是否存在包含“ in ”或“ out < / em>”字。

如何通过这些索引拆分 DataTable ?为此,我想找到一个类似的 Linq Expression 。结果,我必须获得以下表格:

表#1

Line1 : Other data...
[empty line]
Line2: Other data...
[empty line]
...................   
ColA   |   ColB   |   Type   |
------------------------------
AAA    |   BBB    |   IN     |
AAA    |   BBB    |   OUT    |
AAA    |   BBB    |   IN     |

表#2

Line1 : Other data...
[empty line]
Line2: Other data...
[empty line]
...................    
ColA   |   ColB   |   Type   |
------------------------------
AAA    |   BBB    |   IN     |
AAA    |   BBB    |   OUT    |
AAA    |   BBB    |   OUT    |

我知道如何进一步处理这些数据,但是我不知道如何拆分数据表。

2 个答案:

答案 0 :(得分:0)

var selectedIndexes = from row in dataTable.AsEnumerable()
                          where (row.Text.Equals("IN") || row.Text.Equals("OUT"))
                                 && dataTable.Rows[dataTable.Rows.IndexOf(row) - 1]
                          select dataTable.Rows.IndexOf(row);

尽管这是未经测试的代码,但可能会达到目的。

编辑:

由于更新后的问题告诉我您正在处理csv文件,因此我强烈建议您使用CSVHelper Nuget。

文档可以在这里找到:

https://joshclose.github.io/CsvHelper/

答案 1 :(得分:0)

最后,我找到了解决方案。我对以下问题的回答感到鼓舞:Split datatable into multiple fixed sized tables

根据 MwBakker 用户的建议,我对索引标识代码进行了一些更改。

LocationInformationCalloutView

我创建了扩展方法,该方法通过索引将数据表的行分割为

var indexes = dataTable.AsEnumerable()
      .Where(x => x.ItemArray.All(rowCell => rowCell.ToString() == string.Empty))
      .Where(
         x => dataTable.Rows[dataTable.Rows.IndexOf(x) - 1].ItemArray.Any(
           item => string.Equals(item.ToString(), "In")
                   || string.Equals(item.ToString(), "Out")))
      .Select(x => dataTable.Rows.IndexOf(x)).ToArray();

接下来,我做了一个foreach循环:

public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> enumerable, int[] indexes)
    {
        // Sort array.
        indexes = indexes.OrderBy(x => x).ToArray();
        var itemsReturned = 0;
        var list = enumerable.ToList();
        var count = list.Count;
        short i = 0;

        while (itemsReturned < count)
        {
            int currentChunkSize = i < indexes.Length
                                       ? Math.Min(indexes[i] - itemsReturned, count - itemsReturned)
                                       : count - itemsReturned;
            yield return list.GetRange(itemsReturned, currentChunkSize);
            itemsReturned += currentChunkSize;
            i++;
        }
    }