Следующая читает в текстовом файле в исполняемом пути (не стесняйтесь изменять его) в DataTable, который используется как DataSour ce BindingSource (см. комментарии), тогда BindingSource настроен как DataSource DataGridView, где не определены столбцы. После загрузки данных я использую BindingSource для поиска и размещения строки в DataGridView на основе идентификатора поля. Button1 записывает текущие данные обратно в тот же файл. Button2 показывает, как получить первое имя для текущей строки в DataGridView.Button3, здесь мы изменим значение поля из DataTable. Button4 мы позиционируем поле, основанное на поиске, а затем позицию на него, если он найден.
Я всецело контролировал под общим именем, не стесняйтесь переименовывать их.
Если вам нужны имена столбцов, которые также легко добавить.
Конечно, мы могли бы использовать другие контейнеры для данных, например. List (Of T), но в этом случае, кажется, следующие работы для этой задачи очень хорошо.
Если есть вероятность, что идентификатор отсутствует, потребуется некоторое утверждение, но звучит так, должно быть, если не использовать Integer.TryParse в первую очередь.
Код
Public Class Form1
' provides easy method to find, position, view, add, edit, remove
Private bs As New BindingSource
Private fileName As String = IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "TextFile1.txt")
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' make sure file exists
If IO.File.Exists(fileName) Then
Dim dt As New DataTable
dt.Columns.Add(New DataColumn With {.ColumnName = "ID", .DataType = GetType(Integer)})
dt.Columns.Add(New DataColumn With {.ColumnName = "FirstName", .DataType = GetType(String)})
dt.Columns.Add(New DataColumn With {.ColumnName = "LastName", .DataType = GetType(String)})
' cycle through data and add rows to data table
Using Reader As New Microsoft.VisualBasic.FileIO.TextFieldParser(fileName)
Reader.TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.Delimited
Reader.Delimiters = New String() {","}
Dim Row As String()
While Not Reader.EndOfData
Try
Row = Reader.ReadFields()
dt.Rows.Add(New Object() {CInt(Row(0)), Row(1), Row(2)})
Catch ex As Microsoft.VisualBasic.FileIO.MalformedLineException
MsgBox("Line " & ex.Message & " is invalid. Skipping")
End Try
End While
End Using
bs.DataSource = dt
DataGridView1.DataSource = bs
' let's see if id 3 exists and if so move to it
Dim pos As Integer = bs.Find("ID", 3)
If pos > -1 Then
bs.Position = pos
End If
End If
End Sub
''' <summary>
''' Write current data to file
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks></remarks>
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
If bs.DataSource IsNot Nothing Then
Dim dt As DataTable = CType(bs.DataSource, DataTable)
Dim sb As New System.Text.StringBuilder
For Each row As DataRow In dt.Rows
sb.AppendLine(String.Join(",", row.ItemArray))
Next
IO.File.WriteAllText(fileName, sb.ToString)
End If
End Sub
''' <summary>
''' example how to get back a field value
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks></remarks>
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
If bs.DataSource IsNot Nothing Then
If bs.Current IsNot Nothing Then
MessageBox.Show(CType(bs.Current, DataRowView).Row.Field(Of String)("FirstName"))
End If
End If
End Sub
''' <summary>
''' Change a field value
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks></remarks>
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
If bs.DataSource IsNot Nothing Then
If bs.Current IsNot Nothing Then
If Not String.IsNullOrWhiteSpace(TextBox1.Text) Then
CType(bs.Current, DataRowView).Row.SetField(Of String)("LastName", TextBox1.Text)
End If
End If
End If
End Sub
''' <summary>
''' Find and position based on a field value
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks></remarks>
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
If bs.DataSource IsNot Nothing Then
If Not String.IsNullOrWhiteSpace(TextBox2.Text) Then
Dim pos As Integer = bs.Find("FirstName", TextBox2.Text)
If pos > -1 Then
bs.Position = pos
Else
MessageBox.Show(TextBox2.Text & " not found")
End If
End If
End If
End Sub
End Class
Пример текстового файла
1,Karen,Payne
2,Kevin,Gallagher
3,Mary,Williams
4,Lisa,Miller
5,Betty,Moore
6,Laura,Jackson
7,Jon,Wright
Наконец, если вы хотите экспортировать из DataGridView здесь является метод расширения языка (метод расширения идут в модули кода)
IO.File.WriteAllLines(fileName, DataGridView1.DelimitedRows(","))
...
<System.Diagnostics.DebuggerStepThrough()> _
<Runtime.CompilerServices.Extension()> _
Public Function ExportRows(ByVal sender As DataGridView, ByVal Delimiter As String) As String()
Return (From row In sender.Rows Where Not DirectCast(row, DataGridViewRow).IsNewRow Let RowItem = String.Join(Delimiter, Array.ConvertAll(DirectCast(row, DataGridViewRow).Cells.Cast(Of DataGridViewCell).ToArray, Function(c As DataGridViewCell) If(c.Value Is Nothing, "", c.Value.ToString))) Select RowItem).ToArray
End Function
Новое Эта версия создает строки данных, первый перед чтением во всех линиях.
текстовый файл
1,Karen,Payne
2,Kevin,Gallagher
3,Mary,Williams
4,Lisa,Miller
78,Bill,Jenkins
10,Jim,Clime
5,Betty,Moore
6,Laura,Jackson
7,Jon,Wright
Пересмотренный код
Public Class Form1
' provides easy method to find, position, view, add, edit, remove
Private bs As New BindingSource
Private fileName As String = IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "TextFile1.txt")
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
If IO.File.Exists(fileName) Then
Dim Identifier As Integer = 0
Dim dt As New DataTable
' row with identifier but we are hiding it, feel free to show
dt.Columns.Add(New DataColumn With {
.ColumnName = "ID",
.DataType = GetType(Integer),
.AutoIncrement = True,
.AutoIncrementSeed = 1,
.ColumnMapping = MappingType.Hidden
}
)
' optional, show # in front of ID - feel free to discard
dt.Columns.Add(New DataColumn With
{
.ColumnName = "Identifier",
.DataType = GetType(String),
.Expression = "'#' + ID"
}
)
dt.Columns.Add(New DataColumn With
{
.ColumnName = "FirstName",
.DataType = GetType(String)
}
)
dt.Columns.Add(New DataColumn With
{
.ColumnName = "LastName",
.DataType = GetType(String)
}
)
Dim HighIdentifier As Integer = 0
Dim IdentifierList As New List(Of Integer)
' get highest identifier
Using Reader As New Microsoft.VisualBasic.FileIO.TextFieldParser(fileName)
Reader.TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.Delimited
Reader.Delimiters = New String() {","}
Dim Row As String()
While Not Reader.EndOfData
Row = Reader.ReadFields()
If Integer.TryParse(Row(0), Identifier) Then
IdentifierList.Add(Identifier)
End If
End While
End Using
HighIdentifier = IdentifierList.Max
' add rows equal to highest identifier
For x As Integer = 0 To HighIdentifier - 1
dt.Rows.Add(New Object() {Nothing, "", ""})
Next
bs.DataSource = dt
' cycle through data and add rows to data table
Using Reader As New Microsoft.VisualBasic.FileIO.TextFieldParser(fileName)
Reader.TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.Delimited
Reader.Delimiters = New String() {","}
Dim Row As String()
Dim Index As Integer = 0
While Not Reader.EndOfData
Try
Row = Reader.ReadFields()
' find/update row if first field is truly an integer
' we could go another route rather than BindingSource.Find
' so feel free to change it e.g. DataTable.Find, DataTable.Select
If Integer.TryParse(Row(0), Identifier) Then
Index = bs.Find("ID", Identifier)
If Index > -1 Then
bs.Position = Index
CType(bs.Current, DataRowView).Row.SetField(Of String)("FirstName", Row(1))
CType(bs.Current, DataRowView).Row.SetField(Of String)("LastName", Row(2))
End If
End If
Catch ex As Microsoft.VisualBasic.FileIO.MalformedLineException
MessageBox.Show("Line " & ex.Message & " is invalid. Skipping")
End Try
End While
End Using
DataGridView1.DataSource = bs
bs.Position = 0
End If
End Sub
''' <summary>
''' Write current data to file
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks></remarks>
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
If bs.DataSource IsNot Nothing Then
Dim dt As DataTable = CType(bs.DataSource, DataTable)
Dim sb As New System.Text.StringBuilder
For Each row As DataRow In dt.Rows
sb.AppendLine(String.Join(",", row.ItemArray))
Next
IO.File.WriteAllText(fileName, sb.ToString)
End If
' IO.File.WriteAllLines(fileName, DataGridView1.DelimitedRows(","))
End Sub
''' <summary>
''' example how to get back a field value
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks></remarks>
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
If bs.DataSource IsNot Nothing Then
If bs.Current IsNot Nothing Then
MessageBox.Show(CType(bs.Current, DataRowView).Row.Field(Of String)("FirstName"))
End If
End If
End Sub
''' <summary>
''' Change a field value
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks></remarks>
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
If bs.DataSource IsNot Nothing Then
If bs.Current IsNot Nothing Then
If Not String.IsNullOrWhiteSpace(TextBox1.Text) Then
CType(bs.Current, DataRowView).Row.SetField(Of String)("LastName", TextBox1.Text)
End If
End If
End If
End Sub
''' <summary>
''' Find and position based on a field value
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks></remarks>
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
If bs.DataSource IsNot Nothing Then
If Not String.IsNullOrWhiteSpace(TextBox2.Text) Then
Dim pos As Integer = bs.Find("FirstName", TextBox2.Text)
If pos > -1 Then
bs.Position = pos
Else
MessageBox.Show(TextBox2.Text & " not found")
End If
End If
End If
End Sub
End Class
В реальной базе данных, которую CSV не вы Арент должны заботиться, где хранятся данные ... вы обычно даже не знаю. Добавьте данные по мере необходимости, затем сортируйте DGV по этому столбцу, и он поместит их в порядок – Plutonix
Что относительно строки 3,4,5, ..., 29? Все числа существуют в файлах? Что относительно пробелов в файле, пробелы появляются только после id? А как насчет запятых? Все строки имеют две запятые, и имя и фамилия присутствуют? –
Reza. Текстовый файл всегда будет содержать одинаковое количество столбцов и разделяется запятой, поэтому в случае строки, которая не содержит имени, файл будет показывать «4,, smith». Мне все равно, показаны ли строки, которые не содержат данных (3-29 в моем примере выше). Plutonix, я надеюсь добавить данные с помощью строки выбора, и именно поэтому я надеюсь, что идентификационный номер соответствует номеру строки. –