none
HELP: Trying to implement a save and load feature for my DataGridView RRS feed

  • Question

  • So I am making an event reminder to try and learn different things I can do with data grids and one of the things I want to do is be able to save the information in my data grid and be able to load them later. This is my code so far:

        Dim thisFilename As String = Application.StartupPath & "\MyData.dat"

        Private Sub saveBtn_Click(sender As Object, e As EventArgs) Handles saveBtn.Click
            Me.SaveGridData(DataGridView1, thisFilename)
        End Sub

        Private Sub BtnLoad_Click(sender As Object, e As EventArgs) Handles BtnLoad.Click
            Me.LoadGridData(DataGridView1, thisFilename)
        End Sub

        Private Sub SaveGridData(ByRef ThisGrid As DataGridView, ByVal Filename As String)
            ThisGrid.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableWithoutHeaderText
            ThisGrid.SelectAll()
            IO.File.WriteAllText(Filename, ThisGrid.GetClipboardContent().GetText.TrimEnd)
            ThisGrid.ClearSelection()
        End Sub

        Private Sub LoadGridData(ByRef ThisGrid As DataGridView, ByVal Filename As String)
            ThisGrid.Rows.Clear()
            For Each THisLine In My.Computer.FileSystem.ReadAllText(Filename).Split(Environment.NewLine)
                ThisGrid.Rows.Add(Split(THisLine, " "))
            Next
        End Sub

    End Class

    -----------------------------------------------------------------------------------------------------------------------------------------------------

    I don't know why but when I try and save the program this line: 

    IO.File.WriteAllText(Filename, ThisGrid.GetClipboardContent().GetText.TrimEnd) 

    pops up an error that says NullReferenceException was unhandled.

    If you know why this is messing up please let me know and please help me with a fix. Any comment is appreciated and any help will be amazing. 


    Monday, May 8, 2017 12:28 AM

All replies

  • So I am making an event reminder to try and learn different things I can do with data grids and one of the things I want to do is be able to save the information in my data grid and be able to load them later. This is my code so far:

    I have never seen a file save done like this, and I suspect it won't work.  Your actual problem is that you haven't set anything onto the clipboard, so there is nothing to be saved. See:
    https://msdn.microsoft.com/en-us/library/e2z694z2(v=vs.100).aspx

    The usual construction for this type of task is to establish a data source, such as a data table, or a collection of class instances.  That's what gets saved and restored.  The DGV is updated from the data source as required.  For an example that could be adapted, see:
    https://vbdotnetblog.wordpress.com/examples/data-entry-save-and-restore/

    The point of the example is that if you build your application with this structure then it is easy to change the form of the data source, the form of the data display, and the type of persistent storage, as the components are kept separate, with explicit connections where required.  That will become important when you add features like editing an appointment, deleting, sorting, searching etc.

    Monday, May 8, 2017 12:41 AM
  • Hi

    First point: please post code by using the code block tool in the toolbar as it makes things much easier to read.

    '

    Second point: if you use a DataTable to hold your data, you can bind the DataTable to the DataGridView very easily and, the saving and loading of data is the a single line of code for each.

    '

    There are many other advantages in using a DataTable bound to a DataGridView as well.

    '

    Here is some example code. It shows the creation, saving,loading of all data as well as a few other things that were already part of this code.

    ' This example needs a Form1 with
    ' a blank DataGridView1, TextBox1,
    ' Button1, Button2, Button3
    ' and ListBox1
    Option Strict On
    Option Explicit On
    Public Class Form1
        ' set path for example save/load data
        Dim DataPath As String = My.Computer.FileSystem.SpecialDirectories.Desktop & "\MyData.xml"
    
        Dim myTable As New DataTable("Freddy")
        Dim view As New DataView(myTable)
        Dim Prs As New List(Of Pr)
        Dim Hcol As Color = Color.DarkRed
        Dim Hfnt As Font = New Font("Arial", 12, FontStyle.Bold)
        Dim defCol As Color = Color.Black
        Dim defFnt As Font = Nothing
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            '  add some dummy data 
            ' (not needed once a Save has been done)
            With myTable
                .Columns.Add("Name", GetType(String))
                .Columns.Add("Roll Number", GetType(String))
                .Columns.Add("Subject1", GetType(String))
                .Columns.Add("Subject2", GetType(String))
                .Columns.Add("Score", GetType(String))
                .Rows.Add("N1", 5, "Math", "Phy", 20.7456D)
                .Rows.Add("N2", 3, "Social", "Chem", 15.5D)
                .Rows.Add("N1", 1, "Math", "Phy", 11.5D)
                .Rows.Add("N2", 3, "Social", "Math", 25.7D)
                .Rows.Add("N1", 2, "Math", "Phy", 20.9D)
                .Rows.Add("N2", 1, "Social", "Math", 18.5D)
                .Rows.Add("N1", 2, "English", "Phy", 23.5D)
                .Rows.Add("N2", 3, "Social", "Math", 25.7D)
            End With
            ' adjust DGV properties
            With DataGridView1
                .DataSource = view
                .MultiSelect = False
                .RowHeadersWidth = 24
                .ColumnHeadersDefaultCellStyle.WrapMode = DataGridViewTriState.True
                .ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
                .AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill
                .SelectionMode = DataGridViewSelectionMode.CellSelect
                For i As Integer = 0 To 4
                    .Columns(i).DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
                Next
            End With
            ' grab initial font
            defFnt = DataGridView1.DefaultCellStyle.Font
        End Sub
        Sub Srch(s As String)
            ListBox1.Items.Clear()
            Prs.Clear()
            DataGridView1.ClearSelection()
            For Each r As DataGridViewRow In DataGridView1.Rows
                If Not r.Index = DataGridView1.NewRowIndex Then
                    For Each c As DataGridViewCell In r.Cells
                        If s.Length > 0 AndAlso c.Value.ToString.ToLower.Contains(s.ToLower) Then
                            c.Style.ForeColor = Hcol
                            c.Style.Font = Hfnt
                            ListBox1.Items.Add("Row " & c.RowIndex.ToString & " Col " & c.ColumnIndex.ToString & " Title " & c.OwningColumn.HeaderText)
                            Prs.Add(New Pr With {.Row = c.RowIndex, .Column = c.ColumnIndex})
                        Else
                            c.Style.ForeColor = defCol
                            c.Style.Font = defFnt
                        End If
                    Next
                End If
            Next
        End Sub
        Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
            Srch(Trim(TextBox1.Text))
        End Sub
        Private Sub ListBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ListBox1.SelectedIndexChanged
            Dim lb As ListBox = DirectCast(sender, ListBox)
            DataGridView1.ClearSelection()
            DataGridView1(Prs(ListBox1.SelectedIndex).Column, Prs(ListBox1.SelectedIndex).Row).Selected = True
            TextBox1.Select()
        End Sub
        Class Pr
            Property Row As Integer
            Property Column As Integer
        End Class
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            ' save all the data
            myTable.WriteXml(DataPath)
        End Sub
    
        Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
            ' load all data
            myTable.ReadXml(DataPath)
        End Sub
    
        Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
            ' clear out all data
            myTable.Clear()
        End Sub
    End Class


    Regards Les, Livingston, Scotland

    Monday, May 8, 2017 12:47 AM
  • Hi R3DSTON3R,

    I agree with Acamar's opinion, I suggest you to use DataGridView DataSource property to load data.

    More detailed info about DataGridView.DataSuorce, please refer to:

    https://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.datasource(v=vs.110).aspx

    And where are you going to save data from DataGridView?

    Best Regards,

    Cherry Bu


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, May 8, 2017 5:44 AM
    Moderator
  • Hi. Thank you for the reply. I am saving the file under the name and file type "MyData.dat". This allows me to open the .dat in notepad and view the contents that way. I don' want to do anything to hard and I thought saving the datagridview information in a file that could be opened in notepad would be a lot easier for me.
    Monday, May 8, 2017 7:48 AM
  • I don' want to do anything to hard and I thought saving the datagridview information in a file that could be opened in notepad would be a lot easier for me.

    It's only easier if you can find a way to actually do it.  It will take a lot more effort to get that clipboard method to work, and I believe that you will end up converting each line of the DGV to a string anyway, so it won't save you any code.

    If you want to use the DGV as your data source then use code like that in the example to convert each line of the DGV to a single string, and write it to a text file line-by-line.  See:
    https://msdn.microsoft.com/en-us/library/6ka1wd3w%28v=vs.110%29.aspx

    Monday, May 8, 2017 8:11 AM
  • R3,

    Everyone here doesn't agree with me about this, but in my opinion the DataGridView is just a control that displays the data; it's not the data itself.

    As Acamar showed, the data itself is what should be persisted and in my version, it's saved as XML. Also, I'm using the Application Data directory because that's what it's there for.

    To do that, I set up a collection class. The class takes care of the details and has a method that will hand you back a BindingSource. The BindingSource in turn is the DataSource for the DGV.

    You can have a look at the class on a page of my website here and the following shows my testing of it:

    Option Strict On Option Explicit On Option Infer Off Public Class Form1 Private eventData As NonRecurringEventData Private WithEvents tmr As Timer Private Sub Form1_Load(sender As System.Object, _ e As System.EventArgs) _ Handles MyBase.Load eventData = New NonRecurringEventData SetupDGV() PopulateDGV() tmr = New Timer _ With {.Interval = 10000, _ .Enabled = True} End Sub Private Sub _ tmr_Tick(sender As Object, _ e As System.EventArgs) _ Handles tmr.Tick tmr.Enabled = False CreateData() End Sub Private Sub SetupDGV() With DataGridView1 .AllowUserToAddRows = False .AllowUserToDeleteRows = False .AllowUserToOrderColumns = False .AllowUserToResizeRows = False .AlternatingRowsDefaultCellStyle.BackColor = Color.Aquamarine .ReadOnly = True .SelectionMode = DataGridViewSelectionMode.FullRowSelect .MultiSelect = False .RowHeadersVisible = False .RowTemplate.Height = 50 .EnableHeadersVisualStyles = False With .ColumnHeadersDefaultCellStyle .Font = New Font("Tahoma", 9, FontStyle.Bold) .BackColor = Color.LightGreen .WrapMode = DataGridViewTriState.True .Alignment = DataGridViewContentAlignment.MiddleCenter End With .ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing .ColumnHeadersHeight = 50 .DataSource = Nothing .Enabled = False End With End Sub Private Sub PopulateDGV(Optional ByVal bs As BindingSource = Nothing) With BindingNavigator1 .BindingSource = Nothing .Enabled = False End With With DataGridView1 .DataSource = Nothing .Enabled = False End With If bs IsNot Nothing Then With DataGridView1 .SuspendLayout() .DataSource = bs .Columns(0).Visible = False With .Columns(1) .Width = 200 .DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter End With With .Columns(2) .Width = 150 With .DefaultCellStyle .Alignment = DataGridViewContentAlignment.MiddleCenter .Format = "MM/dd/yyy hh:mm tt" End With End With With .Columns(3) .Width = 150 With .DefaultCellStyle .Alignment = DataGridViewContentAlignment.MiddleCenter .Format = "MM/dd/yyy hh:mm tt" End With .AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill End With .ResumeLayout() .Enabled = True End With With BindingNavigator1 .BindingSource = bs .Enabled = True End With End If End Sub Private Sub CreateData() Try With eventData .Add("Dinner With Alice", #5/9/2017 6:30:00 PM#, #5/9/2017 8:00:00 PM#) .Add("Jessica's Birthday", #5/12/2017#, #5/12/2017 11:59:59 PM#) .SaveToXML() End With PopulateDGV(eventData.GetBindingSource) Catch ex As Exception MessageBox.Show(String.Format("An error occurred:{0}{0}{1}", _ vbCrLf, ex.Message), _ "Exception Thrown", _ MessageBoxButtons.OK, _ MessageBoxIcon.Warning) End Try End Sub End Class




    I put the timer in there so I could see how the DGV and BindingNavigator look before I populate it but it's not important to this really. This is what it looks like:

    The XML is "readable" as shown here.

    I don't know what you have in mind for an event reminder but maybe this will give you a head start.

    I hope it hellps. :)


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Monday, May 8, 2017 11:12 AM
  • You are not the first one asking this, therefore we have made a sample on our website how this could easily be done using a dataset written as XML.

    http://www.vb-tips.com/WindowsFormsSchedulerDataGridView.ASPX


    Success
    Cor

    Monday, May 8, 2017 11:31 AM
  • Here is an option.

    Form code

    Public Class Form1
        Private Sub Form1_FormClosing() Handles Me.FormClosing
            My.Operations.Save()
        End Sub
        Private Sub Form1_Load() Handles MyBase.Load
            My.Operations.FileName = IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "MyPeople.txt")
            My.Operations.DataGridView = DataGridView1
            My.Operations.Read()
        End Sub
        Private Sub cmdClose_Click(sender As Object, e As EventArgs) Handles cmdClose.Click
            Close()
        End Sub
    End Class

    Code module

    Namespace My
        <Global.System.ComponentModel.EditorBrowsable(Global.System.ComponentModel.EditorBrowsableState.Never)> _
        Partial Friend Class _MyOperations
            ''' <summary>
            ''' Used to read and write data
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public Property FileName As String
            ''' <summary>
            ''' DataGridView to populate from FileName
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public Property DataGridView As DataGridView
    
            ''' <summary>
            ''' Save rows in DataGridView to FileName
            ''' </summary>
            ''' <remarks></remarks>
            Public Sub Save()
                Dim Lines As List(Of String) = DataGridView.RowsArray.ToList
                IO.File.WriteAllLines(FileName, Lines.ToArray)
            End Sub
            ''' <summary>
            ''' Save rows in DataGridView to FileName
            ''' </summary>
            ''' <remarks></remarks>
            Public Sub ExportToTextFile()
                Save()
            End Sub
            ''' <summary>
            ''' Read rows in FileName into the DataGridView
            ''' </summary>
            ''' <remarks></remarks>
            Public Sub Read()
                If IO.File.Exists(My.Operations.FileName) Then
                    Dim Contents As String() = IO.File.ReadAllLines(My.Operations.FileName)
    
                    Dim PeopleData =
                        (
                            From line In Contents
                            Where line.Length > 0 AndAlso line.Contains(",")
                        ).ToList
    
                    Dim Items As String() = {}
    
                    For Each line In PeopleData
                        Items = line.Split(","c)
                        DataGridView.Rows.Add(
                            If(String.IsNullOrWhiteSpace(Items(0)), False, CBool(Items(0))),
                            Items(1),
                            Items(2))
                    Next
                    DataGridView.ExpandColumns()
                Else
                    '
                    ' Your recovery plan goes here
                    '
                End If
            End Sub
        End Class
        <Global.Microsoft.VisualBasic.HideModuleName()> _
        Friend Module KP_Operations
            Private instance As New ThreadSafeObjectProvider(Of _MyOperations)
            ReadOnly Property Operations() As _MyOperations
                Get
                    Return instance.GetInstance()
                End Get
            End Property
        End Module
    End Namespace
    Module DataGridViewExtensions
        <System.Diagnostics.DebuggerStepThrough()> _
        <Runtime.CompilerServices.Extension()> _
        Public Function RowsArray(ByVal sender As DataGridView) As String()
            Return (From row In sender.Rows Where Not DirectCast(row, DataGridViewRow).IsNewRow Let RowItem = String.Join(",", 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
        <System.Diagnostics.DebuggerStepThrough()> _
        <Runtime.CompilerServices.Extension()> _
        Public Function RowsArray(ByVal sender As DataGridView, ByVal Separater As Char) As String()
            Return (From row In sender.Rows Where Not DirectCast(row, DataGridViewRow).IsNewRow Let RowItem = String.Join(Separater, 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
        <System.Diagnostics.DebuggerHidden()> _
        <System.Runtime.CompilerServices.Extension()> _
        Public Sub ExpandColumns(ByVal sender As DataGridView)
            For Each col As DataGridViewColumn In sender.Columns
                col.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells
            Next
        End Sub
    End Module
    


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites

    Monday, May 8, 2017 3:18 PM
    Moderator
  • could a possible issue be that the program doesn't have permissions to save the file to my computer? Because it does highlight the save button code. If that's the case is there a way I could program it to override permissions and save the file?
    Monday, May 8, 2017 10:53 PM
  • could a possible issue be that the program doesn't have permissions to save the file to my computer? Because it does highlight the save button code. If that's the case is there a way I could program it to override permissions and save the file?

    If it were permissions (which might come up next), it would throw a System.UnauthorizedAccessException.

    *****

    I encourage you to rethink this..


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Monday, May 8, 2017 11:01 PM


  • Regards Les, Livingston, Scotland

    Monday, May 8, 2017 11:06 PM
  • could a possible issue be that the program doesn't have permissions to save the file to my computer? Because it does highlight the save button code. If that's the case is there a way I could program it to override permissions and save the file?

    Hi

    Where are you trying to save the data to? There are some places which are protected and really shouldn't be used for saving user data.


    Regards Les, Livingston, Scotland

    Monday, May 8, 2017 11:09 PM

  • Hi

    Where are you trying to save the data to? There are some places which are protected and really shouldn't be used for saving user data.


    Regards Les, Livingston, Scotland

    He's trying to save it to the executable path which will be the next problem.

    The exception is a null reference exception.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Monday, May 8, 2017 11:15 PM
  • Christian,

    I'm taking off for the day.

    You have a lot of good information here so think it through.

    I wish you luck with it. :)


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Monday, May 8, 2017 11:37 PM
  • could a possible issue be that the program doesn't have permissions to save the file to my computer?

    No.  The problem is that there is nothing to be saved because you have not placed anything onto the clipboard.

    It's not clear where you got that code from, but it is unlikely that you will get it to work.

    Choose one of the solutions posted above and re-do that part of your code.

    Monday, May 8, 2017 11:39 PM
  • I really dislike going the route you want and never used GetClipboardContent but figured I would slap something together so you can see even if you get to work (like I did with the code below) it's not simple.

    I get data as you are, remove the first tab and save to a text file. Upon reading data back in it's un-typed, all elements are of type string into a List(Of String()) and display to the IDE console.

    Form code

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim ops = New LoadSave
        DataGridView1.SelectAll()
        ops.Save(DataGridView1.GetClipboardContent.GetText)
    
        DataGridView1.ClearSelection()
    End Sub
    
    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        Dim ops = New LoadSave
        If ops.Read() Then
            If ops.RowCellData.Count > 0 Then
                For Each rowArray As String() In ops.RowCellData
                    Console.WriteLine(String.Join(vbTab, rowArray))
                Next
            End If
        End If
    End Sub

    Class to read/write to disk

    Public Class LoadSave
        Public Property FileName As String = IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Data.txt")
        Public Property ErrorList As List(Of String)
        Public Property RowCellData As List(Of String())
        Public Sub New()
            ErrorList = New List(Of String)
            RowCellData = New List(Of String())
        End Sub
        Public Sub Save(ByVal contents As String)
            Dim Lines = contents.Split(CType(Environment.NewLine, Char()))
            For line As Integer = 0 To Lines.Length - 1
                Lines(line) = Lines(line).TrimStart(Chr(9)).TrimStart
            Next
    
            Dim CleanLines = From line In Lines
                             Where Not String.IsNullOrWhiteSpace(line)
                             Select line
    
            IO.File.WriteAllLines(FileName, CleanLines)
        End Sub
        Public Function Read() As Boolean
    
            If Not IO.File.Exists(FileName) Then
                Return False
            End If
    
            Dim errorCount As Integer = 0
            Dim data = IO.File.ReadAllLines(FileName)
    
            Using MyReader As New TextFieldParser(FileName)
    
                MyReader.TextFieldType = FieldType.Delimited
                MyReader.Delimiters = New String() {vbTab}
                Dim currentRow As String()
    
                While Not MyReader.EndOfData
                    Try
                        currentRow = MyReader.ReadFields()
                        RowCellData.Add(currentRow)
                    Catch ex As MalformedLineException
                        errorCount += 1
                    End Try
                End While
            End Using
    
            Return errorCount = 0
    
        End Function
    End Class

    There is parts missing and on purpose, you need to place commas into the returning data then use SomeDataGridView.Rows.Add(... with an array split by comma which originally split by TAB. 

    I prefer methods such as the one presented earlier as we don't need to deal with selecting and deselecting rows along with the manipulation of data.


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites

    Tuesday, May 9, 2017 12:06 AM
    Moderator
  • I just want to save it as a .dat file to my computer
    Tuesday, May 9, 2017 1:52 AM
  •     Private Sub SaveGridData(ByRef ThisGrid As DataGridView, ByVal thisFilename As String)
            ThisGrid.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableWithoutHeaderText
            ThisGrid.SelectAll()
            IO.File.WriteAllText(thisFilename, ThisGrid.GetClipboardContent().GetText.TrimEnd)
            ThisGrid.ClearSelection()
    Thats what this private sub was for. I thought this would just copy the datagridview to the clipboard.
    Tuesday, May 9, 2017 1:54 AM
  • Thats what this private sub was for. I thought this would just copy the datagridview to the clipboard.

    It will.  But that's not what you are trying to save.  Your file save statement is saving text, not a DGV.  If you want to save the contents of the DGV (which is what I think you are trying to do because you have stated "This allows me to open the .dat in notepad and view the contents that way") then you need to save each line of the DGV as text - that code won't do it, and converting a DGV object on the clipboard to multiple text lines just isn't worth the trouble.  Use one of the suggestions posted above, either automatically creating the file as XML, as a database table, or by manually by processing each line of the DGV into a single string.

    Tuesday, May 9, 2017 2:01 AM