以下是我尝试导入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
我似乎无法弄清楚为什么其他行会出现空白。 如果有人能帮助我,我将不胜感激。
答案 0 :(得分:1)
我不建议尝试通过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
答案 1 :(得分:0)
这是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;
}
}
}
}