简体   繁体   中英

C# Removing blank cells from datagridview

Is there a way to remove blank/null cells from datagrid view?

    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);
            }



        }




    }

Here is a screen shot demonstrating and example of what it looks like currently when ordering by the atlanta hawks column. I am trying to have all columns match up so I can compare the data side by side.

数字版

I tried searching for similar issues but having some issue. I think the closest thing I found was to import the data into a List.

在此处输入图片说明

Update: I tried the following to try to separate the two columns but this did not work either:

 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);

        }

在此处输入图片说明

You can try something like this, I do not have time to test this but it should work, if it does not work after some changings it may work, this may give you an idea about how to do it.

        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);
            }
        }

在打开 DataGridView 之后,您在数据库中写入之前,您将此空白添加到您的数据库中,您看不到任何空白

I am confident that the posted code is “creating” the empty cells that you want to remove. If you trace the code, you will see that you are adding rows for each team and simply moving each team over one column. I am guessing you should return to the top of the grid when adding the next team. Given this, the cells you want to remove are “created” from not moving the next team up to the first row. The code simply ADDS a new row in the three (3) foreach loops.

From a “big picture”, it appears you are getting some NBA data/stats from some website. The data/stats are formatted in a particular way. The goal is to “parse” the data/stats such that the data can be displayed to the user in a readable fashion. I hope I have this right.

在此处输入图片说明

To help, I would recommend you create a TeamStat Class. Reason being it will make things much easier when you have to get a stat or a team. Currently the code simply adds the values (TeamStats) to the DataTable . The Class could be simple like below.

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>();
  }
}

Next, when the code gets the data from the website, it appears redundant to keep calling the website for data. Picking one team at a time appears unnecessary. I recommend you grab all the data, since you can take advantage of its formatting. “Take advantage”, means we want to break (split) the stats into Teams!

Upon closer examination of the returned string from the website, it appears the “}” character is at the end of each teams stats. This will allow the code to be “split” on each team. The point being, that the current code is simply grabbing a subset of the data for each team needed.

I am guessing that using a List<TeamStat> may come in handy. With this approach, I am thinking of grabbing ALL the data, and fill a List with TeamStat s for all the teams. With this approach, you could display the teams any way you like without calling the website for each team. Without question, this will be easier to manage and it would be rudimentary to create a DataTable of your choice from this list.

The GetAllStatsDataString method returns a semi formatted string of ALL the teams data/stats. The “start” and “end” indexes come from a closer examination for the returned string. The formatting is kept to minimum, and was edited to facilitate the ability to “split” the string into “teams” such that each team's stats ends with the “}” (close bracket) character.

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();
}

Next, is the GetAllTeamStats(string data) that takes the string returned from above and splits it on the “}” character to get a string array with each teams stats. Each string array entry will be a team name and its data/stats. Create a List<TeamStat> stats to hold each teams stats. Before the team is added to the list, we need to convert the string into a TeamStat object. This is accomplished with the GetTeamStat method.

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;
}

The GetTeamStat method takes a string, then parses that string into a new TeamStat object, and returns that TeamStat object, which in turn will be added to the List<TeamStat> TeamStat in the previous method.

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;
}

At this stage, we now have a list of TeamStat objects, one for each team. You could possibly use this as a data source, however as stated earlier, it would not be difficult to create a DataTable using the list of team stats. The only problem here is deciding which teams to display in the DataTable . In the code below I simply use all the teams, however, it would not be difficult to display only the teams the user wanted.

Considering this, it is not necessarily known how many columns are to be displayed; therefore, the code simply loops through all the teams in the list, one column for each team. Next issue is how many rows is the table going to need assuming the number of stats between each team MAY be different. To ensure all stats are displayed, a check is made to get the largest stat list from all the teams. This will determine the number of rows needed. Lastly, fill those rows with data from the List<TeamStat> TeamStats . Below is the code to return the 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();
  }
}

NOTE: the “splitting” here is separating the stat name and the stat data. Example, the stat is of the form “PG RK:26”… after splitting this string on “:” we can get the name or the value.

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++;
  }
}

Finally, the last problem is to add the row headers for the grid for each stat. Each stat cell currently has the stats “name” and this is what is used for the row headers. NOTE: call this method AFTER you have set the grids data source.

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++;
  }
}

Lastly the form load method to put it all together…

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();
}

Hope this helps.

if you want to remove any empty row or any rows contains empty cell just you can use this code :

 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--;
                }}
         

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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