繁体   English   中英

在C#中切换for循环的情况

[英]Switch case in for loop in C#

我正在逐行读取excel。各列标题位于第2行。 但数据从第4行开始。 我想首先检查列标题,并将第4行的值分别放到关联的模型属性中。

在此输入图像描述

所以我想在for循环中使用case语句而不是if else检查。

但它仅在第一种情况下破裂。 我知道这是有意的,但还有其他更有效的方法吗?

ListGroupMembershipUploadInput gl = new ListGroupMembershipUploadInput();

for (int rw = 4; rw <= ws.Dimension.End.Row; rw++)
{
    //Dictionary<string, string> groupMembershipUploadDict = new Dictionary<string, string>();

    int headerCol = 2;

    GroupMembershipUploadInput gm = new GroupMembershipUploadInput();

    for (int col = ws.Dimension.Start.Column; col <= ws.Dimension.End.Column; col++)
    {
        string val = ws.Cells[headerCol, col].Value.ToString();

        switch (ws.Cells[headerCol, col].Value.ToString())
        {
            case "Code for the particular Chapter(example,'12345' )" :
                gm.chpt_cd = (ws.Cells[rw, col].Value ?? null).ToString();
                break;
            case "Existing Constituent Master Id" :
                gm.cnst_mstr_id = (ws.Cells[rw, col].Value ?? null).ToString();
                break;
            case "Prefix of the constituent(Mr, Mrs etc)" :
                gm.cnst_prefix_nm = (ws.Cells[rw, col].Value ?? null).ToString();
                break;
            case "First Name of the constituent(Mike)" :
                gm.cnst_first_nm = (ws.Cells[rw, col].Value ?? null).ToString();
                break;
            case "Middle Name of the constituent(R.)" :
                gm.cnst_middle_nm = (ws.Cells[rw, col].Value ?? null).ToString();
                break;
            case "Last Name of the constituent(Andrien)" :
                gm.cnst_last_nm = (ws.Cells[rw, col].Value ?? null).ToString();
                break;
            case "Address Line 1(Home) - (431 Washington Blvd)" :
                gm.cnst_addr1_street1 = (ws.Cells[rw, col].Value ?? null).ToString();
                break;
            }

            gl.GroupMembershipUploadInputList.Add(gm);
        }

    }

这是我建立的模型类。

public class GroupMembershipUploadInput
{

    public string chpt_cd {get;set;}
    public string cnst_mstr_id {get;set;}
    public string cnst_prefix_nm {get;set;}
    public string cnst_first_nm {get;set;}
    public string cnst_middle_nm {get;set;}
    public string cnst_last_nm {get;set;}
    public string cnst_addr1_street1 {get;set;}
}

public class ListGroupMembershipUploadInput
{
    public List<GroupMembershipUploadInput> GroupMembershipUploadInputList { get; set; }
}

所以我想将excel数据转换为具有空值的模型对象列表。

你执行

 gl.GroupMembershipUploadInputList.Add(gm);

在内部for循环内部。 这意味着在评估每列后添加对象。 因此,对象可以多次添加到列表中。

在内部for循环之后移动将对象添加到列表的行。

此外,你不初始化属性GroupMembershipUploadInputListListGroupMembershipUploadInput类。 因此它为null,并且在尝试将第一个对象添加到列表时,您将获得NullReferenceException

您需要创建列表:

public class ListGroupMembershipUploadInput
{
    public List<GroupMembershipUploadInput> GroupMembershipUploadInputList { get; set; } = new List<GroupMembershipUploadInput>();
}

你需要做这样的事情来摆脱switch语句:

ListGroupMembershipUploadInput gl = new ListGroupMembershipUploadInput();

int headerCol = 2;

Dictionary<string, int> map = Enumerable
    .Range(ws.Dimension.Start.Column, ws.Dimension.End.Column - ws.Dimension.Start.Column + 1)
    .ToDictionary(col => ws.Cells[headerCol, col].Value.ToString(), col => col);

for (int rw = 4; rw <= ws.Dimension.End.Row; rw++)
{
    gl.GroupMembershipUploadInputList.Add(new GroupMembershipUploadInput()
    {
        chpt_cd = ws.Cells[rw, map["Code for the particular Chapter(example,'12345' )"]].Value.ToString(),
        cnst_mstr_id = ws.Cells[rw, map["Existing Constituent Master Id"]].Value.ToString(),
        cnst_prefix_nm = ws.Cells[rw, map["Prefix of the constituent(Mr, Mrs etc)"]].Value.ToString(),
        cnst_first_nm = ws.Cells[rw, map["First Name of the constituent(Mike)"]].Value.ToString(),
        cnst_middle_nm = ws.Cells[rw, map["Middle Name of the constituent(R.)"]].Value.ToString(),
        cnst_last_nm = ws.Cells[rw, map["Last Name of the constituent(Andrien)"]].Value.ToString(),
        cnst_addr1_street1 = ws.Cells[rw, map["Address Line 1(Home) - (431 Washington Blvd)"]].Value.ToString(),
    });
}

这有效地移动了gl.GroupMembershipUploadInputList.Add(gm); 在内部for循环之外。

它还使您的代码更小,更易于阅读。

回答你的问题“还有其他更有效的方法吗?”

1)如果要使用Office Interop,逐个单元格读取不是最有效的方法。 人们常常不了解一种不那么明显的方式。

这将一次性返回二维数组,然后循环进行循环。 您仍然需要手动跳过第二行,空值并处理转换。 但是,这将是更快 ,更清洁:

Worksheets("Sheet1").Range("A1:D10").Value

2)最有效的方法是使用OleDB,然后你不需要安装Office ,只需免费组件Microsoft Access Database Engine 2010 Redistributable (注意:有x86和x64版本,必须使用你的应用程序)

下面是我编译的代码草案/片段,很可能不会起作用,但这些都涉及到缅因州的和平。 这个想法是你使用excel中的数据,比如数据库和表。 最好的部分是你获得了IDataReader,因此你逐个读取行而不将所有内容加载到内存中,所以除了速度之外,这也是RAM-wise。

private IDataReader OpenReader()
{
    _strConn = String.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 12.0;HDR={1};IMEX=1;TypeGuessRows=0;ImportMixedTypes=Text\"",
                                _fileName, Configuration.HasHeaders ? "Yes" : "No");

    conn = new OleDbConnection(_strConn);
    conn.Open();

    var schemaTable = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
    string sheet = schemaTable.Rows[0]["TABLE_NAME"].ToString();
    var schemaTableColumns = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Columns, new object[] { null, null, sheet, null });

    // I am taking 1-st sheet here for simplicity
    string sheetName = schemaTable
      .Rows[0]["TABLE_NAME"].ToString();

    var cmd = new OleDbCommand(String.Format("SELECT * FROM [{0}]", sheetName), conn);

    cmd.CommandType = CommandType.Text;

    return cmd
       .ExecuteReader(CommandBehavior.Default);
}

PS。 我决定追求最后一个选项如果需要,我可以在这里给你更多信息。

暂无
暂无

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

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