有没有办法从数据网格视图中删除空白/空单元格?
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鹰派专栏订购时的样子。我试图让所有列匹配,以便我可以并排比较数据。
我尝试搜索类似问题,但遇到了一些问题。我认为最接近的是将数据导入List。
更新:我尝试了以下尝试将两列分开,但这也不起作用:
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);
}
答案 0 :(得分:0)
你把这个空白添加到你的数据库之前你可以在数据库中写入后打开DataGridView你看不到任何空白
答案 1 :(得分:0)
我确信发布的代码是“创建”您要删除的空单元格。如果您跟踪代码,您将看到为每个团队添加行,只需将每个团队移动到一列。我猜你在添加下一个团队时应该回到网格的顶部。鉴于此,您要删除的单元格是“创建”的,而不是将下一个团队移动到第一行。代码只是在三(3)个foreach
循环中添加一个新行。
从“大局”看,你似乎从一些网站上获得了一些NBA数据/统计数据。数据/统计信息以特定方式格式化。目标是“解析”数据/统计数据,使得数据可以以可读的方式显示给用户。我希望我有这个权利。
为了提供帮助,我建议您创建一个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--;
}}