c# - 允许用户选择要导入的列标题

标签 c# linq csv linqtocsv

我在允许用户从 CSV 文件导入订单的程序中使用 LINQtoCSV。我的所有代码都可以正常工作,但是,如果 CSV 文件没有确切的列标题,那么它就不起作用。

下面是 LINQtoCSV 读入的我的类 -

public class orderProduct
{
    public orderProduct() { }
    public string product { get; set; }
    public string price { get; set; }
    public string orderQty { get; set; }
    public string value { get; set; }

    public string calculateValue()
    {
        return (Convert.ToDouble(price) * Convert.ToDouble(orderQty)).ToString();
    }
}

如果 CSV 文件没有确切的标题,它将无法工作。我实际上只需要的数据是前 4 个字符串。

下面是我实际读取数据的函数。

private void csvParse()
{
    // order.Clear();
    string fileName = txt_filePath.Text.ToString().Trim();

    try
    {
        CsvContext cc = new CsvContext();

        CsvFileDescription inputFileDescription = new CsvFileDescription
        {
            SeparatorChar = ',',
            FirstLineHasColumnNames = true
        };

        IEnumerable<orderProduct> fromCSV = cc.Read<orderProduct>(fileName, inputFileDescription);

        foreach (var d in fromCSV)
        {
            MessageBox.Show($@"Product:{d.product},Quantity:""{d.orderQty}"",Price:""{d.price}""");
            orderReturn.Add(d);                
        }
        this.DialogResult = DialogResult.Yes;
        this.Close();
    }
    catch (Exception ex)
    {
        if (ex.ToString().Contains("being used by another process"))
        {
            MessageBox.Show("Error: Please close the file in Excel and try again");
        }
        else
        {
            MessageBox.Show(ex.ToString());
        }
    }
}

我希望用户能够只传入一个文件,然后选择与相应值相关的相关列,然后读入数据,忽略任何未选择的列。

希望这一切都有意义,在 LINQtoCSV 中是否可能实现这样的事情

最佳答案

您必须将 IgnoreUnknownColumns = true 添加到您的 CsvFileDescription

CSV:

product,price,someColumn,orderQty,value,otherColumn
my product,$123,xx,2,$246,aa
my other product,$10,yy,3,$30,bb

工作代码(我稍微修改了你的代码,以便在控制台中运行它)

using System;
using System.Collections.Generic;
using LINQtoCSV;

namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
            csvParse();
            Console.ReadLine();
        }

        private static void csvParse()
        {
            string fileName = "../../../test.csv"; // provide a valid path to the file

            CsvContext cc = new CsvContext();

            CsvFileDescription inputFileDescription = new CsvFileDescription
            {
                SeparatorChar = ',',
                FirstLineHasColumnNames = true,
                IgnoreUnknownColumns = true // add this line
            };

            IEnumerable<orderProduct> fromCSV = cc.Read<orderProduct>(fileName, inputFileDescription);

            foreach (var d in fromCSV)
            {
                Console.WriteLine($@"Product:{d.product},Quantity:""{d.orderQty}"",Price:""{d.price}""");
            }
        }
    }

    public class orderProduct
    {
        public orderProduct() { }
        public string product { get; set; }
        public string price { get; set; }
        public string orderQty { get; set; }
        public string value { get; set; }

        public string calculateValue()
        {
            return (Convert.ToDouble(price) * Convert.ToDouble(orderQty)).ToString();
        }
    }
}

输出:

Product:my product,Quantity:"2",Price:"$123"
Product:my other product,Quantity:"3",Price:"$10"

如果您的属性与 CSV 列的名称不同,您应该使用 CsvColumn 属性:

public class OrderProduct
{
    [CsvColumn(Name = "product")]
    public string Product { get; set; }

    [CsvColumn(Name = "price")]
    public string Price { get; set; }

    [CsvColumn(Name = "orderQty")]
    public string OrderQuantity { get; set; }

    public string Value { get; set; }

    public string calculateValue()
    {
        return (Convert.ToDouble(Price) * Convert.ToDouble(OrderQuantity)).ToString();
    }
}

或者如果您更喜欢按索引映射列:

public class OrderProduct
{
    [CsvColumn(FieldIndex = 0)]
    public string Product { get; set; }

    [CsvColumn(FieldIndex = 1)]
    public string Price { get; set; }

    [CsvColumn(FieldIndex = 2)]
    public string OrderQuantity { get; set; }

    public string Value { get; set; }

    public string calculateValue()
    {
        return (Convert.ToDouble(Price) * Convert.ToDouble(OrderQuantity)).ToString();
    }
}

如果您必须即时指定列,唯一的方法似乎是读取原始数据并自行处理(解决方案基于 this article ):

internal class DataRow : List<DataRowItem>, IDataRow
{
}
...
int productColumnIndex = 0; // your users will provide it
var fromCSV = cc.Read<DataRow>(fileName);
foreach (var row in fromCSV)
{
    var orderProduct = new OrderProduct
    {
        Product = row[productColumnIndex].Value,
    };

    Console.WriteLine(orderProduct.Product);
}

关于c# - 允许用户选择要导入的列标题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53062669/

相关文章:

c# - C# 中的 JSON.NET 反序列化导致空对象

c# - 填充 TreeView 时出现 "Out of Memory"

c# - 在 ASP.NET Core 3 中使用 id_token

c# - linq 查询中的垃圾回收

c# - 如何使用 LINQ 加入、分组和选择?

python - 从提取的 JSON 数据追加和/或写入 CSV

linux - linux中的数据操作

c# - 从 ServiceStack.Redis 管道读取值

c# - 使用 linq 对相关列表进行分组

r - 使用 "fread",如何从 csv 中删除注释行?