C#从datagridview中删除空白单元格

时间:2018-03-07 17:32:14

标签: c# datagridview cells

有没有办法从数据网格视图中删除空白/空单元格?

    private void button1_Click(object sender, EventArgs e)
    {

        DataTable dvpdt = new DataTable();

        HtmlAgilityPack.HtmlDocument doc;
        doc = new HtmlWeb().Load("https://rotogrinders.com/grids/nba-defense-vs-position-cheat-sheet-1493632?site=fanduele");
        HtmlNode node = doc.DocumentNode.SelectSingleNode("//section[@class='bdy content article full cflex reset long table-page']/following-sibling::script[1]");
        //Atlanta DVP: 
        int atlantastart = node.InnerText.IndexOf("Atlanta Hawks");
        int atlantalength = node.InnerText.IndexOf("Boston Celtics") - atlantastart;
        string atlantaoutput = node.InnerText.Substring(atlantastart, atlantalength).Replace("TEAM", "").Replace("\"", "").Replace("{:", "").Replace("FPPG:", "").Trim();
        string[] atlantasplit = atlantaoutput.Split(',');


        DataColumn dc = new DataColumn("Atlanta Hawks");
        DataColumn bdc = new DataColumn("Boston Celtics");
        DataColumn brdc = new DataColumn("Brooklyn Nets");



        dvpdt.Columns.Add(dc);
        DataRow dr = dvpdt.NewRow();


        foreach (string atlantaitem in atlantasplit)
        {
            dr = dvpdt.NewRow();
            dr["Atlanta Hawks"] = atlantaitem;
            dvpdt.Rows.Add(dr);

        }

        //Boston DVP:
        int bostonstart = node.InnerText.IndexOf("Boston Celtics");
        int bostonlength = node.InnerText.IndexOf("Brooklyn Nets") - bostonstart;
        string bostonoutput = node.InnerText.Substring(bostonstart, bostonlength).Replace("TEAM", "").Replace("\"", "").Replace("{:", "").Replace("FPPG:", "").Trim();
        string[] bostonsplit = bostonoutput.Split(',');


        dvpdt.Columns.Add(bdc);

        foreach (string bostonitem in bostonsplit)
        {
            dr = dvpdt.NewRow();
            dr["Boston Celtics"] = bostonitem;
            dvpdt.Rows.Add(dr);
        }

        //Brooklyn DVP:
        int brooklynstart = node.InnerText.IndexOf("Brooklyn Nets");
        int brooklynlength = node.InnerText.IndexOf("Charlotte Hornets") - brooklynstart;
        string brooklynoutput = node.InnerText.Substring(brooklynstart, brooklynlength).Replace("TEAM", "").Replace("\"", "").Replace("{:", "").Replace("FPPG:", "").Trim();
        string[] brooklynsplit = brooklynoutput.Split(',');
        dvpdt.Columns.Add(brdc);

        foreach (string brooklynitem in brooklynsplit)
        {
            dr = dvpdt.NewRow();
            dr["Brooklyn Nets"] = brooklynitem;
            dvpdt.Rows.Add(dr);
        }

        //end team load
        //Bind Datasource
        dataGridView2.DataSource = dvpdt;

        foreach (DataGridViewRow row in dataGridView2.Rows)
        {

            string t = row.Cells[0].Value == null ? String.Empty : row.Cells[0].Value.ToString();
            string a = row.Cells[1].Value == null ? String.Empty : row.Cells[1].Value.ToString();
            string b = row.Cells[2].Value == null ? String.Empty : row.Cells[2].Value.ToString();

            if (t.Contains("PG RK"))
            {
                dataGridView2.Rows.Remove(row);
            }
            if (t.Contains("SG RK"))
            {
                dataGridView2.Rows.Remove(row);
            }
            if (t.Contains("C RK"))
            {
                dataGridView2.Rows.Remove(row);
            }
            if (t.Contains("PF RK"))
            {
                dataGridView2.Rows.Remove(row);
            }
            if (t.Contains("SF RK"))
            {
                dataGridView2.Rows.Remove(row);
            }


            if (a.Contains("PG RK"))
            {
                dataGridView2.Rows.Remove(row);
            }
            if (a.Contains("SG RK"))
            {
                dataGridView2.Rows.Remove(row);
            }
            if (a.Contains("C RK"))
            {
                dataGridView2.Rows.Remove(row);
            }
            if (a.Contains("PF RK"))
            {
                dataGridView2.Rows.Remove(row);
            }
            if (a.Contains("SF RK"))
            {
                dataGridView2.Rows.Remove(row);
            }


            if (b.Contains("PG RK"))
            {
                dataGridView2.Rows.Remove(row);
            }
            if (b.Contains("SG RK"))
            {
                dataGridView2.Rows.Remove(row);
            }
            if (b.Contains("C RK"))
            {
                dataGridView2.Rows.Remove(row);
            }
            if (b.Contains("PF RK"))
            {
                dataGridView2.Rows.Remove(row);
            }
            if (b.Contains("SF RK"))
            {
                dataGridView2.Rows.Remove(row);
            }



        }




    }

这是一个屏幕截图,展示了当时由atlanta鹰派专栏订购时的样子。我试图让所有列匹配,以便我可以并排比较数据。

dgv

我尝试搜索类似问题,但遇到了一些问题。我认为最接近的是将数据导入List。

enter image description here

更新:我尝试了以下尝试将两列分开,但这也不起作用:

 private void button1_Click(object sender, EventArgs e)
    {

        DataTable dvpdt = new DataTable();

        HtmlAgilityPack.HtmlDocument doc;
        doc = new HtmlWeb().Load("https://rotogrinders.com/grids/nba-defense-vs-position-cheat-sheet-1493632?site=fanduele");
        HtmlNode node = doc.DocumentNode.SelectSingleNode("//section[@class='bdy content article full cflex reset long table-page']/following-sibling::script[1]");

        DataColumn dc = new DataColumn("Atlanta Hawks");
        DataColumn bdc = new DataColumn("Boston Celtics");
        DataColumn brdc = new DataColumn("Brooklyn Nets");
        DataRow dr = dvpdt.NewRow();

        //Add Columns 
        dvpdt.Columns.Add(dc);
        dvpdt.Columns.Add(bdc);



        //Atlanta DVP: 
        int atlantastart = node.InnerText.IndexOf("Atlanta Hawks");
        int atlantapglength = node.InnerText.IndexOf("PG RK") - atlantastart;
        int atlantasglength = node.InnerText.IndexOf("SG RK") - atlantastart;
        int atlantasflength = node.InnerText.IndexOf("SF RK") - atlantastart;
        int atlantapflength = node.InnerText.IndexOf("PF RK") - atlantastart;
        int atlantaclength = node.InnerText.IndexOf("C RK") - atlantastart;
        string atlantapgoutput = node.InnerText.Substring(atlantastart, atlantapglength).Replace("TEAM", "").Replace("\"", "").Replace("{:", "").Replace("FPPG:", "").Replace("Atlanta Hawks", "");
        string[] atlantapgsplit = atlantapgoutput.Split(',');
        string atlantasgoutput = node.InnerText.Substring(atlantastart, atlantasglength).Replace("TEAM", "").Replace("\"", "").Replace("{:", "").Replace("FPPG:", "").Replace("Atlanta Hawks", "");
        string[] atlantasgsplit = atlantasgoutput.Split(',');

        foreach (string atlantaitem in atlantasgsplit)
        {
            dr = dvpdt.NewRow();
            dr["Atlanta Hawks"] = atlantaitem;
            dvpdt.Rows.Add(dr);

        }



        //Boston DVP:
        int bostonstart = node.InnerText.IndexOf("Boston Celtics");
        int bostonpglength = node.InnerText.IndexOf("PG RK") - atlantastart;
        string bostonpgoutput = node.InnerText.Substring(bostonstart, bostonpglength).Replace("TEAM", "").Replace("\"", "").Replace("{:", "").Replace("FPPG:", "").Replace("Boston Celtics", "");
        string[] bostonpgsplit = bostonpgoutput.Split(',');

        foreach (string bostonitem in bostonpgsplit)
        {
            dr = dvpdt.NewRow();
            dr["Boston Celtics"] = bostonitem;
            dvpdt.Rows.Add(dr);

        }

enter image description here

4 个答案:

答案 0 :(得分:0)

你把这个空白添加到你的数据库之前你可以在数据库中写入后打开DataGridView你看不到任何空白

答案 1 :(得分:0)

我确信发布的代码是“创建”您要删除的空单元格。如果您跟踪代码,您将看到为每个团队添加行,只需将每个团队移动到一列。我猜你在添加下一个团队时应该回到网格的顶部。鉴于此,您要删除的单元格是“创建”的,而不是将下一个团队移动到第一行。代码只是在三(3)个foreach循环中添加一个新行。

从“大局”看,你似乎从一些网站上获得了一些NBA数据/统计数据。数据/统计信息以特定方式格式化。目标是“解析”数据/统计数据,使得数据可以以可读的方式显示给用户。我希望我有这个权利。

enter image description here

为了提供帮助,我建议您创建一个TeamStat类。当你需要获得统计数据或团队时,它会使事情变得更容易。目前,代码只是将值(TeamStats)添加到DataTable。课程可以简单如下。

public class TeamStat {
  public string TeamName { get; set; }
  public List<string> TeamStats { get; set; }

  public TeamStat(string teamName) {
    TeamName = teamName;
    TeamStats = new List<string>();
  }

  public TeamStat() {
    TeamName = "";
    TeamStats = new List<string>();
  }
}

接下来,当代码从网站获取数据时,继续调用网站获取数据似乎是多余的。一次挑选一个团队似乎是不必要的。我建议你抓取所有数据,因为你可以利用它的格式。 “利用”,意味着我们希望将统计数据分解(拆分)为团队!

仔细检查网站上返回的字符串后,似乎“}”字符位于每个团队统计数据的末尾。这将允许代码在每个团队中“拆分”。关键是,当前代码只是为每个团队所需的数据子集抓取。

我猜测使用List<TeamStat>可能会派上用场。通过这种方法,我正在考虑抓取所有数据,并为所有团队填充List TeamStat秒。通过这种方法,您可以以任何方式显示团队,而无需为每个团队调用网站。毫无疑问,这将更容易管理,从此列表中创建DataTable您的选择将是不成熟的。

GetAllStatsDataString方法返回所有团队数据/统计数据的半格式化字符串。 “开始”和“结束”索引来自对返回字符串的仔细检查。格式保持最小,并进行了编辑,以便能够将字符串“拆分”为“团队”,以便每个团队的统计数据以“}”(紧密括号)字符结束。

private string GetAllStatsDataString() {
  HtmlAgilityPack.HtmlDocument doc = new HtmlWeb().Load("https://rotogrinders.com/grids/nba-defense-vs-position-cheat-sheet-1493632?site=fanduele");
  HtmlNode node = doc.DocumentNode.SelectSingleNode("//section[@class='bdy content article full cflex reset long table-page']/following-sibling::script[1]");
  int TeamStart = node.InnerText.IndexOf("TEAM") + 4;
  int TeamsEnd = node.InnerText.IndexOf("];") - TeamStart;
  return node.InnerText.Substring(TeamStart, TeamsEnd).Replace("TEAM", "").Replace("\"", "").Replace("{","").Trim();
}

接下来,GetAllTeamStats(string data)是从上面返回的字符串,并将其拆分为“}”字符,以获得每个团队统计信息的字符串数组。每个字符串数组条目都是团队名称及其数据/统计信息。创建一个List<TeamStat> stats来保存每个团队的统计信息。在将团队添加到列表之前,我们需要将字符串转换为TeamStat对象。这是通过GetTeamStat方法完成的。

private List<TeamStat> GetAllTeamStats(string data) {
  List<TeamStat> stats = new List<TeamStat>();
  string[] teamSplit = data.Split('}');
  TeamStat curTeamStat;
  foreach (string curTeam in teamSplit) {
    if (curTeam != "") {
      curTeamStat = GetTeamStat(curTeam);
      stats.Add(curTeamStat);
    }
  }
  return stats;
}

GetTeamStat方法接受一个字符串,然后将该字符串解析为一个新的TeamStat对象,并返回该TeamStat个对象,该对象又将被添加到List<TeamStat>上一个方法中的TeamStat

private TeamStat GetTeamStat(string teamString) {
  string[] statSplit = teamString.Substring(1).Split(',');
  string tName = statSplit[0].Replace(":", "").Trim();
  TeamStat teamStat = new TeamStat(tName);
  for (int i = 1; i < statSplit.Length; i++) {
    if (statSplit[i] != null && statSplit[i] != "") {
      teamStat.TeamStats.Add(statSplit[i]);
    }
  }
  return teamStat;
}

在此阶段,我们现在有一个TeamStat个对象列表,每个团队一个。您可以将其用作数据源,但如前所述,使用团队统计信息列表创建DataTable并不困难。这里唯一的问题是决定在DataTable中显示哪些团队。在下面的代码中,我只使用了所有团队,但是,只显示用户想要的团队并不困难。

考虑到这一点,不一定知道要显示多少列;因此,代码只是遍历列表中的所有团队,每个团队一列。下一个问题是假设每个团队之间的统计数量可能不同,表格需要多少行。为确保显示所有统计信息,请进行检查以获取所有团队中最大的统计信息列表。这将确定所需的行数。最后,使用List<TeamStat> TeamStats中的数据填充这些行。以下是返回DataTable

的代码
private DataTable GetGridDT() {
  DataTable dt = new DataTable();
  SetDataTableColumnsAndRows(dt);
  FillRows(dt);
  return dt;
}

private void SetDataTableColumnsAndRows(DataTable dt) {
  int totalRows = 0;
  foreach(TeamStat curTeam in TeamStats) {
    dt.Columns.Add(curTeam.TeamName, typeof(string));
    totalRows = Math.Max(totalRows, curTeam.TeamStats.Count);
  }
  // set rows here to max length to avoid having to check for different length stats
  for (int i = 0; i < totalRows; i++) {
    dt.Rows.Add();
  }
}

注意:此处的“拆分”是将统计名称和统计数据分开。例如,统计数据的格式为“PG RK:26”...在将此字符串拆分为“:”后,我们可以获取名称或值。

private void FillRows(DataTable dt) {
  int currentColumn = 0;
  int currentRow;
  string[] splitArray;
  foreach (TeamStat curTeam in TeamStats) {
    currentRow = 0;
    foreach (string curStat in curTeam.TeamStats) {
      splitArray = curStat.Split(':');
      dt.Rows[currentRow][currentColumn] = splitArray[1].Trim();
      currentRow++;
    }
    currentColumn++;
  }
}

最后,最后一个问题是为每个统计数据添加网格的行标题。每个stat单元格当前都具有统计信息“name”,这是用于行标题的内容。注意:在设置网格数据源之后调用此方法。

private void SetGridRowHeaders() {
  int rowIndex = 0;
  string[] splitArray;
  foreach (string curHeader in TeamStats[0].TeamStats) {
    splitArray = curHeader.Split(':');
    dataGridView1.Rows[rowIndex].HeaderCell.Value =  splitArray[0].Trim();
    rowIndex++;
  }
}

最后将表单加载方法放在一起......

DataTable TeamDataTable;
string AllStatsString;
List<TeamStat> TeamStats;

public Form_NBA_Stats() {
  InitializeComponent();
}

private void Form_NBA_Stats_Load(object sender, EventArgs e) {
  AllStatsString = GetAllStatsDataString();
  TeamStats = GetAllTeamStats(AllStatsString);
  TeamDataTable = GetGridDT();
  dataGridView1.DataSource = TeamDataTable;
  SetGridRowHeaders();
}

希望这有帮助。

答案 2 :(得分:0)

你可以尝试这样的事情,我没时间测试这个,但是它应该有效,如果它在一些变化之后不起作用它可能有效,这可能会让你知道如何去做。

        for (int i = dataGridView1.Rows.Count; i > -1; --i)
        {
            DataGridViewRow row = dataGridView1.Rows[i];
            if (!row.IsNewRow && row.Cells[0].Value == null)
            {
                dataGridView1.Rows.RemoveAt(i);
            }

            DataGridViewColumn clmn = dataGridView1.Columns[i];
            if (row.Cells[0].Value == null)
            {
                dataGridView1.Columns.RemoveAt(i);
            }
        }

答案 3 :(得分:0)

如果您要删除任何空行或任何行包含空单元格,则可以使用以下代码:

 for (int i = 0;i<dataGridView1.Rows.count-1;i++)
        {
            
                if (dataGridView1.Rows[i].Cells[0].Value.ToString() =="" | dataGridView1.Rows[i].Cells[1].Value.ToString()==""| dataGridView1.Rows[i].Cells[2].Value.ToString()=="")
                {
                    dataGridView1.Rows.RemoveAt(i);
                    i--;
                }}