简体   繁体   English

如何将由新行和逗号分隔的字符串转换为C#中的DataTable

[英]How to convert string separated by new line and comma to DataTable in C#

I have a string like this: 我有一个像这样的字符串:

"Product,Price,Condition Cd,13,New Book,9,Used "

Which is being passed like this: 这是通过这样的:

"Product,Price,Condition\\r\\Cd,13,New\\r\\nBook,9,Used"

How could I convert it to DataTable? 我怎么能把它转换为DataTable?

Trying to do it with this helper function: 尝试使用此辅助函数执行此操作:

            DataTable dataTable = new DataTable();
            bool columnsAdded = false;
            foreach (string row in data.Split(new string[] { "\r\n" }, StringSplitOptions.None))
            {
                DataRow dataRow = dataTable.NewRow();
                foreach (string cell in row.Split(','))
                {
                    string[] keyValue = cell.Split('~');
                    if (!columnsAdded)
                    {
                        DataColumn dataColumn = new DataColumn(keyValue[0]);
                        dataTable.Columns.Add(dataColumn);
                    }
                    dataRow[keyValue[0]] = keyValue[1];
                }
                columnsAdded = true;
                dataTable.Rows.Add(dataRow);
            }
            return dataTable;

However I don't get that "connecting cells with appropriate columns" part - my cells don't have ~ in string[] keyValue = cell.Split('~'); 但是,我没有得到“连接具有适当列的单元格”部分 - 我的单元格中没有~string[] keyValue = cell.Split('~'); and I obviously get an IndexOutOfRange at DataColumn dataColumn = new DataColumn(keyValue[0]); 我显然在DataColumn dataColumn = new DataColumn(keyValue[0]);获得了一个IndexOutOfRange DataColumn dataColumn = new DataColumn(keyValue[0]);

You can split given string into flattened string array in one call. 您可以在一次调用中将给定的字符串拆分为扁平字符串数组。 Then you can iterate through the array and populate list of objects. 然后,您可以遍历数组并填充对象列表。

That part is optional, since you can immediately populate DataTable but I think it's way easier (more maintainable) to work with strongly-typed objects when dealing with DataTable . 该部分是可选的,因为您可以立即填充DataTable但我认为在处理DataTable时使用强类型对象更容易(更易于维护)。

string input = "Product,Price,Condition\r\nCd,13,New\r\nBook,9,Used";

string[] deconstructedInput = input.Split(new string[] { "\r\n", "," }, StringSplitOptions.None);

List<Product> products = new List<Product>();
for (int i = 3; i < deconstructedInput.Length; i += 3)
{
    products.Add(new Product
    {
        Name = deconstructedInput[i],
        Price = Decimal.Parse(deconstructedInput[i + 1]),
        Condition = deconstructedInput[i + 2]
    });
}

public class Product
{
    public string Name { get; set; }

    public decimal Price { get; set; }

    public string Condition { get; set; }
}

So, products collection holds 2 objects which you can easily iterate over and populate your DataTable . 因此, products集合包含2个对象,您可以轻松地迭代并填充DataTable

Note: This requires further checks to avoid possible runtime exceptions, also it is not dynamic. 注意:这需要进一步检查以避免可能的运行时异常,也不是动态的。 That means, if you have differently structured input it won't work. 这意味着,如果你有不同的结构输入,它将无法正常工作。

DataTable dataTable = new DataTable();

dataTable.Columns.Add(new DataColumn(nameof(Product.Name)));
dataTable.Columns.Add(new DataColumn(nameof(Product.Price)));
dataTable.Columns.Add(new DataColumn(nameof(Product.Condition)));

foreach (var product in products)
{
    var row = dataTable.NewRow();
    row[nameof(Product.Name)] = product.Name;
    row[nameof(Product.Price)] = product.Price;
    row[nameof(Product.Condition)] = product.Condition;
    dataTable.Rows.Add(row);
}

You can do that simply with Linq (and actually there is LinqToCSV on Nuget, maybe you would prefer that): 你可以简单地使用Linq(实际上Nuget上有LinqToCSV,也许你更喜欢这样):

void Main()
{
    string data = @"Product,Price,Condition
Cd,13,New
Book,9,Used
";
    var table = ToTable(data);
    Form f = new Form();
    var dgv = new DataGridView { Dock = DockStyle.Fill, DataSource = table };
    f.Controls.Add(dgv);
    f.Show();
}

private DataTable ToTable(string CSV)
{
    DataTable dataTable = new DataTable();
    var lines = CSV.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
    foreach (var colname in lines[0].Split(','))
    {
        dataTable.Columns.Add(new DataColumn(colname));
    }
    foreach (var row in lines.Where((r, i) => i > 0))
    {
        dataTable.Rows.Add(row.Split(','));
    }
    return dataTable;
}

Based on your implementation, I have written the code for you, I have not tested it. 根据您的实现,我已经为您编写了代码,我还没有测试过。 But you can use the concept. 但你可以使用这个概念。

DataRow dataRow = dataTable.NewRow();
int i = 0;
foreach (string cell in row.Split(','))
{
    if (!columnsAdded)
    {
        DataColumn dataColumn = new DataColumn(cell);
        dataTable.Columns.Add(dataColumn);
    }
    else
    {
        dataRow[i] = cell;
    }
    i++;
}
if(columnsAdded)
{
    dataTable.Rows.Add(dataRow);
}
columnsAdded = true;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM