繁体   English   中英

.CSV到DataGridView行在VB.NET中变为空白

[英].CSV to DataGridView Rows coming up blank in VB.NET

这是我要导入到VB.NET应用程序中的CSV数据:

原始数据

但是,当我通过应用程序运行它时,它只会填充最后一行:

产量

这是导入的代码:

Private Sub btnBrowse_Click(sender As Object, e As EventArgs) Handles btnBrowse.Click
    DataGridView1.ClearSelection()
    ofd.Filter = "(*csv)|*.csv"
    If ComboBox1.Text = "zVBImportTEST" Then
        If (ofd.ShowDialog() = DialogResult.OK) Then
            txtbxFilePath.Text = ofd.FileName
        End If
        Dim colsexpected As Integer = 6
        Dim thereader As New StreamReader(txtbxFilePath.Text, Encoding.ASCII)
        Dim sline As String = ""
        thereader.ReadLine()
        Do
            sline = thereader.ReadLine
            If sline Is Nothing Then Exit Do
            Dim words() As String = sline.Split(",")
            DataGridView1.Rows.Add("")
            For ix As Integer = 0 To 5
                DataGridView1.Rows(DataGridView1.Rows.Count - 1).Cells(ix).Value = words(ix)
            Next

        Loop
        thereader.Close()
    Else
        MessageBox.Show("Please select a project.", "Warning!", MessageBoxButtons.OK, MessageBoxIcon.Asterisk)
    End If
End Sub

我似乎无法弄清楚为什么其他行变成空白。 如果有人可以帮助我,将不胜感激。

我不建议尝试通过StreamReader读取数据,而是在传递CSV文件的连接字符串时使用OleDb类。

这是一个基于CSV文件内容返回DataTable的函数的快速示例:

Private Function ConvertCSVToDataTable(ByVal path As String) As DataTable
    Dim dt As DataTable = New DataTable()
    Using con As OleDb.OleDbConnection = New OleDb.OleDbConnection()
        Try
            con.ConnectionString = String.Format("Provider={0};Data Source={1};Extended Properties=""Text;HDR=YES;FMT=Delimited""", "Microsoft.Jet.OLEDB.4.0", IO.Path.GetDirectoryName(path))
            Using cmd As OleDb.OleDbCommand = New OleDb.OleDbCommand("SELECT * FROM " & IO.Path.GetFileName(path), con)
                Using da As OleDb.OleDbDataAdapter = New OleDb.OleDbDataAdapter(cmd)
                    con.Open()
                    da.Fill(dt)
                    con.Close()
                End Using
            End Using
        Catch ex As Exception
            Console.WriteLine(ex.ToString())
        Finally
            If con IsNot Nothing AndAlso con.State = ConnectionState.Open Then
                con.Close()
            End If
        End Try
    End Using

    Return dt
End Function

接下来是绑定DataGridView的方法:

DataGridView1.DataSource = Me.ConvertCSVToDataTable(ofd.FileName)

更新

由于您要指定DataColumn的数据类型,因此可以声明一个DataTable并将其分配给自定义函数,但是要事后修改特定列的数据类型。 这是一个快速的示例(自由类型且未经测试):

Dim csv As DataTable = Me.ConvertCSVToDataTable(ofd.FileName)
With csv.Columns
    .Items(0).DataType = GetType(Int32)
    .Items(1).DataType = GetType(Int32)
    .Items(4).DataType = GetType(Int32)
    .Items(5).DataType = GetType(Int32)
End With

DataGridView1.DataSource = csv

这是C#,但是代码段显示了您当前正在做什么,以及如何进行操作以使其正常工作。

using System.Collections.Generic;
using System.Windows.Forms;

namespace DataGridNoBinding_47308996
{
    public partial class Form1 : Form
    {

        DataGridView dgv = new DataGridView();
        public Form1()
        {
            InitializeComponent();
            dgv.Dock = DockStyle.Fill;
            dgv.AutoGenerateColumns = false;
            dgv.Columns.Add("Key","Key");
            dgv.Columns.Add("Value", "Value");
            this.Controls.Add(dgv);

            Dictionary<string, string> dgvdata = new Dictionary<string, string>();
            for (int i = 0; i < 10; i++)
            {
                dgvdata.Add($"key{i}", $"value{i}");
            }

            //AddToGridNoWork(dgvdata);
            AddToGridDoesWork(dgvdata);

        }

        /// <summary>
        /// This method does not work. This emulates what you are currently doing.
        /// </summary>
        /// <param name="dgvdata"></param>
        private void AddToGridNoWork(Dictionary<string, string> dgvdata)
        {
            foreach (KeyValuePair<string, string> item in dgvdata)
            {
                dgv.Rows.Add();
                dgv.Rows[dgv.Rows.Count - 1].Cells[0].Value = item.Key;
                dgv.Rows[dgv.Rows.Count - 1].Cells[1].Value = item.Value;
                dgv.Refresh();
            }
        }


        /// <summary>
        /// This method does work.
        /// Add a new row to the Grid and store the new row index in rowindex
        /// Then use the variable rowindex to update the correct row
        /// </summary>
        /// <param name="dgvdata"></param>
        private void AddToGridDoesWork(Dictionary<string, string> dgvdata)
        {
            foreach (KeyValuePair<string, string> item in dgvdata)
            {
                int rowindex = dgv.Rows.Add();
                dgv.Rows[rowindex].Cells[0].Value = item.Key;
                dgv.Rows[rowindex].Cells[1].Value = item.Value;
            }
        }
    }
}

在您的VB.net应用程序中,可能只是做这样的事情

dim newRowIndex as Integer
newRowIndex = DataGridView1.Rows.Add("")
For ix As Integer = 0 To 5
    DataGridView1.Rows(newRowIndex).Cells(ix).Value = words(ix)
Next

改用DataDriver,这是我的代码,使用数据驱动程序代替StreamReader旋转

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Data.OleDb;
using System.Data;

namespace DataGridNoBinding_47308996
{
    public partial class Form1 : Form
    {

        DataGridView dgv = new DataGridView();
        public Form1()
        {
            InitializeComponent();
            dgv.Dock = DockStyle.Fill;
            this.Controls.Add(dgv);

            Dictionary<string, string> dgvdata = new Dictionary<string, string>();
            for (int i = 0; i < 10; i++)
            {
                dgvdata.Add($"key{i}", $"value{i}");
            }

            //AddToGridNoWork(dgvdata);
            //AddToGridDoesWork(dgvdata);
            //AddToGridUsingDataDriver(@"M:\StackOverflowQuestionsAndAnswers\DataGridNoBinding_47308996\SampleData.csv");
            AddToGridByBindingTheWholeTable(@"M:\StackOverflowQuestionsAndAnswers\DataGridNoBinding_47308996\SampleData.csv");

        }

        /// <summary>
        /// This method will do what you want using a Data Driver instead of a StreamReader
        /// Though, this method binds the whole DataTable to the DataGridView instead of manually creating 1 row per data row
        /// </summary>
        /// <param name="dataFilePath"></param>
        private void AddToGridByBindingTheWholeTable(string dataFilePath)
        {
            dgv.AutoGenerateColumns = true;

            string connstring = $"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={System.IO.Path.GetDirectoryName(dataFilePath)};Extended Properties=\"Text;HDR=NO;FMT=Delimited\"";
            OleDbConnection conn = new OleDbConnection(connstring);
            OleDbCommand command = new OleDbCommand($"select * from {System.IO.Path.GetFileName(dataFilePath)}", conn);
            OleDbDataAdapter dataAdapter = new OleDbDataAdapter(command);
            DataTable dt = new DataTable();
            conn.Open();
            dataAdapter.Fill(dt);
            conn.Close();

            dgv.DataSource = dt;
        }



        /// <summary>
        /// This method will do what you want using a Data Driver instead of a StreamReader
        /// In this method, we are actively creating 1 DataGridRow for each DataRow in the DataTable
        /// </summary>
        /// <param name="dataFilePath"></param>
        private void AddToGridUsingDataDriver(string dataFilePath)
        {
            dgv.AutoGenerateColumns = false;
            dgv.Columns.Add("Key", "Key");
            dgv.Columns.Add("Value", "Value");

            string connstring = $"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={System.IO.Path.GetDirectoryName(dataFilePath)};Extended Properties=\"Text;HDR=NO;FMT=Delimited\"";
            OleDbConnection conn = new OleDbConnection(connstring);
            OleDbCommand command = new OleDbCommand($"select * from {System.IO.Path.GetFileName(dataFilePath)}", conn);
            OleDbDataAdapter dataAdapter = new OleDbDataAdapter(command);
            DataTable dt = new DataTable();
            conn.Open();
            dataAdapter.Fill(dt);
            conn.Close();

            if (dt != null && dt.Rows.Count > 0)
            {
                foreach (DataRow item in dt.Rows)
                {
                    int newrowid = dgv.Rows.Add();
                    dgv.Rows[newrowid].Cells[0].Value = item.Field<string>(0);
                    dgv.Rows[newrowid].Cells[1].Value = item.Field<string>(1);
                }
            }
            dgv.Refresh();
        }

        /// <summary>
        /// This method does not work. This emulates what you are currently doing.
        /// </summary>
        /// <param name="dgvdata"></param>
        private void AddToGridNoWork(Dictionary<string, string> dgvdata)
        {
            dgv.AutoGenerateColumns = false;
            dgv.Columns.Add("Key","Key");
            dgv.Columns.Add("Value", "Value");

            foreach (KeyValuePair<string, string> item in dgvdata)
            {
                dgv.Rows.Add();
                dgv.Rows[dgv.Rows.Count - 1].Cells[0].Value = item.Key;
                dgv.Rows[dgv.Rows.Count - 1].Cells[1].Value = item.Value;
                dgv.Refresh();
            }
        }


        /// <summary>
        /// This method does work.
        /// Add a new row to the Grid and store the new row index in rowindex
        /// Then use the variable rowindex to update the correct row
        /// </summary>
        /// <param name="dgvdata"></param>
        private void AddToGridDoesWork(Dictionary<string, string> dgvdata)
        {
            dgv.AutoGenerateColumns = false;
            dgv.Columns.Add("Key", "Key");
            dgv.Columns.Add("Value", "Value");

            foreach (KeyValuePair<string, string> item in dgvdata)
            {
                int rowindex = dgv.Rows.Add();
                dgv.Rows[rowindex].Cells[0].Value = item.Key;
                dgv.Rows[rowindex].Cells[1].Value = item.Value;
            }
        }
    }
}

暂无
暂无

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

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