none
Save to File xml

    Question

  • I have 3 TextBox and 2 Listbox on Form.I try this code but when Read xml all line of data Listbox1 go to into 2 listbox. I want to save ALL control - 3 textbox and 2 listbox into another form.

    Thank.

       Private Sub SaveValue(ByVal Path As String)
    
            Dim ToSave(1) As String
            Dim index As Integer = 0
    
            For Each Control As Control In Me.Controls
                If TypeOf Control Is TextBox Then
                    ToSave(index) = Control.Text
                    index += 1
                    ReDim Preserve ToSave(index)
                End If
            Next
    
            ReDim Preserve ToSave(index + ListBox1.Items.Count)
            ListBox1.Items.CopyTo(ToSave, index)
            ReDim Preserve ToSave(index + ListBox2.Items.Count)
            ListBox2.Items.CopyTo(ToSave, index)
    
            Dim writer As New System.Xml.Serialization.XmlSerializer(GetType(String()))
            Dim file As New System.IO.StreamWriter(Path)
            writer.Serialize(file, ToSave)
            file.Close()
        End Sub
    
        Private Sub Button3_Click(sender As System.Object, e As System.EventArgs) Handles Button3.Click
            Dim save As New SaveFileDialog
            With save
                .Filter = "xml Files (*.xml)|*.xml|All Files (*.*)|*.*"
                .InitialDirectory = "C:\"
                .Title = "save XML"
            End With
            If save.ShowDialog = Windows.Forms.DialogResult.OK Then
                SaveValue(save.FileName)
            End If
    
        End Sub
    
    
    Private Sub ReadValue(ByVal Path As String)
    
            Dim reader As New System.Xml.Serialization.XmlSerializer(GetType(String()))
            Dim file As New System.IO.StreamReader(Path)
            Dim ToRead() As String = CType(reader.Deserialize(file), String())
            file.Close()
            Dim index As Integer = 0
    
            For Each Control As Control In Me.Controls
                If TypeOf Control Is TextBox Then
                    Control.Text = ToRead(index)
                    index += 1
                End If
            Next
    
            For x As Integer = index To ToRead.GetUpperBound(0) - 1
                ListBox1.Items.Add(ToRead(x))
            Next
            For y As Integer = index To ToRead.GetUpperBound(0) - 1
                ListBox2.Items.Add(ToRead(y))
            Next
        End Sub
        Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
            Dim save As New OpenFileDialog
            With save
                .Filter = "xml Files (*.xml)|*.xml|All Files (*.*)|*.*"
                .InitialDirectory = "C:\"
                .Title = "save XML"
            End With
            If save.ShowDialog = Windows.Forms.DialogResult.OK Then
                ReadValue(save.FileName)
            End If
        End Sub


    • Edited by mipakteh Sunday, April 16, 2017 2:49 PM Add
    Sunday, April 16, 2017 2:47 PM

Answers


  • Frank can you give some example.

    Thank.

    Ok I came up with a nonsensical example but it will hopefully do what you want which is to save the data from your ListBoxes to an XML file and then retrieve them from the XML and populate them back.

    If you feel like it, you can duplicate it on your end:

    The controls are named:

    • ListBox1
    • ListBox2
    • btn_ExportToXML
    • btn_ClearContents
    • btn_ImportFromXML

    The program is set up so that the buttons will only be enabled once you click the button which is above it. It's pointless, but it's just for testing.

    This is what it looks like when it's first loaded:

    Next I click the button to export it to XML:

    It will put the XML in a small file on your desktop. The XML generated is shown below:

    <?xml version="1.0" encoding="utf-8"?>
    <ListBoxes>
      <ListBox Name="ListBox1">
        <Item>this</Item>
        <Item>that</Item>
        <Item>the other</Item>
      </ListBox>
      <ListBox Name="ListBox2">
        <Item>the</Item>
        <Item>rain</Item>
        <Item>in</Item>
        <Item>Spain</Item>
      </ListBox>
    </ListBoxes>

    Now I click the button to clear the contents (of the ListBoxes):

    Finally then, I click the button to import the data back in from the XML file and re-populate the ListBoxes:

    The code follows:

    Option Strict On Option Explicit On Option Infer Off Public Class Form1 Private desktop As String = _ Environment.GetFolderPath(Environment.SpecialFolder.Desktop) Private Sub Form1_Load(sender As System.Object, _ e As System.EventArgs) _ Handles MyBase.Load ListBox1.Items.AddRange(New String() {"this", "that", "the other"}) ListBox2.Items.AddRange(New String() {"the", "rain", "in", "Spain"}) btn_ClearContents.Enabled = False btn_ImportFromXML.Enabled = False End Sub Private Sub _ btn_ExportToXML_Click(sender As System.Object, _ e As System.EventArgs) _ Handles btn_ExportToXML.Click With btn_ExportToXML .Enabled = False .Refresh() End With Dim listBoxes() As ListBox = GetListBoxes() If listBoxes IsNot Nothing Then Dim filePath As String = _ IO.Path.Combine(desktop, "ListBoxes.xml") ExportListBoxContents(listBoxes, filePath) End If btn_ClearContents.Enabled = True End Sub Private Sub _ btn_ClearContents_Click(sender As System.Object, _ e As System.EventArgs) _ Handles btn_ClearContents.Click With btn_ClearContents .Enabled = False .Refresh() End With Dim listBoxes() As ListBox = GetListBoxes() If listBoxes IsNot Nothing Then For Each lb As ListBox In listBoxes lb.Items.Clear() Next End If btn_ImportFromXML.Enabled = True End Sub Private Sub _ btn_ImportFromXML_Click(sender As System.Object, _ e As System.EventArgs) _ Handles btn_ImportFromXML.Click With btn_ImportFromXML .Enabled = False .Refresh() End With Dim listBoxes() As ListBox = GetListBoxes() If listBoxes IsNot Nothing Then Dim filePath As String = _ IO.Path.Combine(desktop, "ListBoxes.xml") ImportXML(listBoxes, filePath) End If End Sub Private Sub _ ExportListBoxContents(ByVal listboxes() As ListBox, _ ByVal filePath As String) Try If listboxes IsNot Nothing AndAlso listboxes.Length > 0 Then If Not String.IsNullOrWhiteSpace(filePath) Then Dim xDoc As XElement = _ <ListBoxes> <%= From lb As ListBox In listboxes Select _ <ListBox> <%= New XAttribute("Name", lb.Name) %> <%= From items As Object In lb.Items Select _ <Item> <%= items.ToString %> </Item> %> </ListBox> %> </ListBoxes> xDoc.Save(filePath) End If End If 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 Private Sub ImportXML(ByVal listboxes() As ListBox, _ ByVal filePath As String) Try If listboxes IsNot Nothing AndAlso listboxes.Length > 0 Then If Not String.IsNullOrWhiteSpace(filePath) Then If IO.File.Exists(filePath) Then Dim xDoc As XElement = XElement.Load(filePath) For Each info As XElement In xDoc...<ListBox> Dim name As String = info.@Name Dim qry As IEnumerable(Of ListBox) = _ From lb As ListBox In listboxes _ Where lb.Name = name If qry.Count = 1 Then Dim lb As ListBox = DirectCast(qry.First, ListBox) lb.Items.Clear() For Each itemInfo As XElement In info...<Item> lb.Items.Add(itemInfo.Value) Next End If Next End If End If End If 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 Private Function GetListBoxes() As ListBox() Dim retVal() As ListBox = Nothing Dim ctrls As New List(Of Control) Dim qry As System.Linq.IOrderedEnumerable(Of Control) = _ From ctrl As Control In _ FindControlRecursive(ctrls, Me, GetType(ListBox)) _ Order By ctrl.Name If qry.Count > 0 Then Dim tempList As New List(Of ListBox) For Each ctrl As Control In qry tempList.Add(DirectCast(ctrl, ListBox)) Next retVal = tempList.ToArray End If Return retVal End Function Private Function _ FindControlRecursive(ByVal list As List(Of Control), _ ByVal parent As Control, _ ByVal ctrlType As System.Type) As List(Of Control) If parent Is Nothing Then Return list If parent.GetType Is ctrlType Then list.Add(parent) End If For Each child As Control In parent.Controls FindControlRecursive(list, child, ctrlType) Next Return list End Function End Class

    ***** EDIT *****

    I forgot to mention that I put one of the ListBoxes inside a GroupBox just to test that it would find it in a container control. It's not needed - it was just for testing.


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



    • Edited by Frank L. Smith Sunday, April 23, 2017 9:49 AM
    • Marked as answer by mipakteh Monday, April 24, 2017 12:52 PM
    Sunday, April 23, 2017 9:43 AM
  • Continued from previous post

     

     

    mip,

    Continuing, I’ve put together a test program that I hope you’ll download and run.

    I have the project folder zipped up and uploaded to my site here:

    http://www.fls-online.net/VBNet_Forum/04-30-17/Demo_WinFormsControlsPersistence.zip

    The assembly (the .dll file) is in that but if you only want the .dll by itself, I have that zipped up and uploaded here:

    http://www.fls-online.net/VBNet_Forum/04-30-17/ControlsPersistence.zip

     

    *****

     

    The demo program has a tab control with five (5) tab pages, one for each supported control type. When you first turn it on, look through the controls; they have [mostly] already been populated:

    The RichTextBox needs some attention.

    When you look on that tab, you’ll see two buttons. If you have a local file which is formatted as RTF, pick that but if not then there’s another button that will stream an RTF file that I put on my site for this purpose:

    Please also notice the status shown on the status bar. Nothing has yet been saved (persisted) so there’s no data to show about it. Given that, the menu choices are limited:

    Once you’ve done that and confirmed that there’s data to be persisted on all tabs, use the menu and ‘save’ it:

    Nothing exciting so far, but to prove that it actually worked, click to ‘clear’ everything:

    Look at the last few screenshots and the text of the status bar shows that there’s data saved now. So once you’ve cleared everything, let’s test it: Load it back in:

    If you’d like to see where it’s been save to, use the menu bar and go have a look:

     

    *****

     

    In conclusion then, in your actual program it’s nothing more than adding a reference to the assembly (the .dll file) and using “Save” and “Restore” when needed. Be sure to include that .dll file when distributing your program, the same as you’d do with any other third-party assembly.

     

     

    I hope that you find this helpful and I’d appreciate if you’d let me know how you make out with it. :)


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

    • Marked as answer by mipakteh Monday, May 01, 2017 5:55 AM
    Sunday, April 30, 2017 5:16 PM

All replies

  • mip,

    I didn't read through all of that but know this: A form's control isn't serializable, but then again you don't need them to be.

    The designer has the primary things (like location and size and all that), so I'm guessing that you need to persist the contents of the various control? That's a much easier thing to do.

    If so, let me know what all you're trying to persist.

    ***** EDIT *****

    You might also want to look into setting up and using Application Settings:

    https://msdn.microsoft.com/en-us/library/k4s6c3a0(v=vs.110).aspx

    It serializes the data to an XML file and manages it for you. Give that a look before you do your own.


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


    Sunday, April 16, 2017 4:19 PM
  • Hi Frank,

    Bellow the Form want to save to another Form.

    without Command Button.

    Frank can you give some example.

    Thank.

    • Edited by mipakteh Sunday, April 23, 2017 6:02 AM add
    Sunday, April 23, 2017 1:44 AM

  • Frank can you give some example.

    Thank.

    Ok I came up with a nonsensical example but it will hopefully do what you want which is to save the data from your ListBoxes to an XML file and then retrieve them from the XML and populate them back.

    If you feel like it, you can duplicate it on your end:

    The controls are named:

    • ListBox1
    • ListBox2
    • btn_ExportToXML
    • btn_ClearContents
    • btn_ImportFromXML

    The program is set up so that the buttons will only be enabled once you click the button which is above it. It's pointless, but it's just for testing.

    This is what it looks like when it's first loaded:

    Next I click the button to export it to XML:

    It will put the XML in a small file on your desktop. The XML generated is shown below:

    <?xml version="1.0" encoding="utf-8"?>
    <ListBoxes>
      <ListBox Name="ListBox1">
        <Item>this</Item>
        <Item>that</Item>
        <Item>the other</Item>
      </ListBox>
      <ListBox Name="ListBox2">
        <Item>the</Item>
        <Item>rain</Item>
        <Item>in</Item>
        <Item>Spain</Item>
      </ListBox>
    </ListBoxes>

    Now I click the button to clear the contents (of the ListBoxes):

    Finally then, I click the button to import the data back in from the XML file and re-populate the ListBoxes:

    The code follows:

    Option Strict On Option Explicit On Option Infer Off Public Class Form1 Private desktop As String = _ Environment.GetFolderPath(Environment.SpecialFolder.Desktop) Private Sub Form1_Load(sender As System.Object, _ e As System.EventArgs) _ Handles MyBase.Load ListBox1.Items.AddRange(New String() {"this", "that", "the other"}) ListBox2.Items.AddRange(New String() {"the", "rain", "in", "Spain"}) btn_ClearContents.Enabled = False btn_ImportFromXML.Enabled = False End Sub Private Sub _ btn_ExportToXML_Click(sender As System.Object, _ e As System.EventArgs) _ Handles btn_ExportToXML.Click With btn_ExportToXML .Enabled = False .Refresh() End With Dim listBoxes() As ListBox = GetListBoxes() If listBoxes IsNot Nothing Then Dim filePath As String = _ IO.Path.Combine(desktop, "ListBoxes.xml") ExportListBoxContents(listBoxes, filePath) End If btn_ClearContents.Enabled = True End Sub Private Sub _ btn_ClearContents_Click(sender As System.Object, _ e As System.EventArgs) _ Handles btn_ClearContents.Click With btn_ClearContents .Enabled = False .Refresh() End With Dim listBoxes() As ListBox = GetListBoxes() If listBoxes IsNot Nothing Then For Each lb As ListBox In listBoxes lb.Items.Clear() Next End If btn_ImportFromXML.Enabled = True End Sub Private Sub _ btn_ImportFromXML_Click(sender As System.Object, _ e As System.EventArgs) _ Handles btn_ImportFromXML.Click With btn_ImportFromXML .Enabled = False .Refresh() End With Dim listBoxes() As ListBox = GetListBoxes() If listBoxes IsNot Nothing Then Dim filePath As String = _ IO.Path.Combine(desktop, "ListBoxes.xml") ImportXML(listBoxes, filePath) End If End Sub Private Sub _ ExportListBoxContents(ByVal listboxes() As ListBox, _ ByVal filePath As String) Try If listboxes IsNot Nothing AndAlso listboxes.Length > 0 Then If Not String.IsNullOrWhiteSpace(filePath) Then Dim xDoc As XElement = _ <ListBoxes> <%= From lb As ListBox In listboxes Select _ <ListBox> <%= New XAttribute("Name", lb.Name) %> <%= From items As Object In lb.Items Select _ <Item> <%= items.ToString %> </Item> %> </ListBox> %> </ListBoxes> xDoc.Save(filePath) End If End If 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 Private Sub ImportXML(ByVal listboxes() As ListBox, _ ByVal filePath As String) Try If listboxes IsNot Nothing AndAlso listboxes.Length > 0 Then If Not String.IsNullOrWhiteSpace(filePath) Then If IO.File.Exists(filePath) Then Dim xDoc As XElement = XElement.Load(filePath) For Each info As XElement In xDoc...<ListBox> Dim name As String = info.@Name Dim qry As IEnumerable(Of ListBox) = _ From lb As ListBox In listboxes _ Where lb.Name = name If qry.Count = 1 Then Dim lb As ListBox = DirectCast(qry.First, ListBox) lb.Items.Clear() For Each itemInfo As XElement In info...<Item> lb.Items.Add(itemInfo.Value) Next End If Next End If End If End If 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 Private Function GetListBoxes() As ListBox() Dim retVal() As ListBox = Nothing Dim ctrls As New List(Of Control) Dim qry As System.Linq.IOrderedEnumerable(Of Control) = _ From ctrl As Control In _ FindControlRecursive(ctrls, Me, GetType(ListBox)) _ Order By ctrl.Name If qry.Count > 0 Then Dim tempList As New List(Of ListBox) For Each ctrl As Control In qry tempList.Add(DirectCast(ctrl, ListBox)) Next retVal = tempList.ToArray End If Return retVal End Function Private Function _ FindControlRecursive(ByVal list As List(Of Control), _ ByVal parent As Control, _ ByVal ctrlType As System.Type) As List(Of Control) If parent Is Nothing Then Return list If parent.GetType Is ctrlType Then list.Add(parent) End If For Each child As Control In parent.Controls FindControlRecursive(list, child, ctrlType) Next Return list End Function End Class

    ***** EDIT *****

    I forgot to mention that I put one of the ListBoxes inside a GroupBox just to test that it would find it in a container control. It's not needed - it was just for testing.


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



    • Edited by Frank L. Smith Sunday, April 23, 2017 9:49 AM
    • Marked as answer by mipakteh Monday, April 24, 2017 12:52 PM
    Sunday, April 23, 2017 9:43 AM
  • Yea it is a little bit difficult described on MSDN but the Applications settings file (config sys) is an XML file

    http://stackoverflow.com/questions/10712407/simple-way-to-save-and-load-data-visual-basic


    Success
    Cor


    Like I suggested to him a week ago today then?

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

    Sunday, April 23, 2017 1:23 PM
  • Frank,

    Sorry, I missed that text, I changed my text and will propose that reply as answer, 


    Success
    Cor


    I once started a class library that would serialize the "user-changeable" parts of several controls like TextBoxes, for example.

    For what it was, it worked, but I never finished it.


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

    Sunday, April 23, 2017 2:33 PM
  • Thank you very much,Code working.
    Monday, April 24, 2017 12:52 PM
  • Thank you very much,Code working.

    Sorry for the delay.

    I'm glad that it helped. :)

    *****

    If I develop a new class library to make the persistence much easier on your end, would you be willing to test it and let me know your thoughts about using it?


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

    Monday, April 24, 2017 5:03 PM
  • Thank you very Frank for helping.I 'm really need you show a new Class Library.At least for my knowledge.

    Sunday, April 30, 2017 4:16 AM
  • Thank you very Frank for helping.I 'm really need you show a new Class Library.At least for my knowledge.

    I had started on this the other day, then I got busy with work and never went back to it.

    I didn't know there was any interest though, so I'll continue with it and post something in the next few days.


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

    Sunday, April 30, 2017 12:45 PM
  • ok

    Sunday, April 30, 2017 1:51 PM
  • ok



    mip,

    I haven’t “finished” but this is the sort of thing that probably never can be complete. For what I do have though, it seems to work well but needs to be thoroughly tested. It’s a class library that I’ve put together (ergo, a .dll file) and once you have that referenced in your program it will help to persist the state of several Windows Forms controls.

    I need to explain what it does (and by that, what it doesn’t do) so that there’s no misunderstanding here; it doesn’t persist anything that’s in the designer file (like the size, location, color, etc.) and it also doesn’t know or look at the code that you’ve used to initialize anything.

    Instead it saves and restores very specific data for each of five (5) Winforms controls as follows:

    TextBoxes

    • Name (used for identification when restoring)
    • Text

    RichTextBoxes

    • Name (used for identification when restoring)
    • Text
    • RTF

    ListBoxes

    • Name (used for identification when restoring)
    • Items (as an internal collection of System.Object)

    ComboBoxes

    • Name (used for identification when restoring)
    • Items (as an internal collection of System.Object)

    ListViews

    • Name (used for identification when restoring)
    • ListViewItems (as an internal collection of System.Windows.Forms.ListViewItem)

     

     

    I could (and may, if there’s any interest) add many more but that’s what I currently have.

    I have some rudimentary documentation shown on my website here. The only part that I currently have documented to any real extent is “Persistence” as shown here. Notice in that last link that there are only two public methods: Save and Restore.

    When you invoke the “Save” method, it will look through the controls of the specified parent control (usually your form) and if it’s supported, it will then ‘read’ the data and add it to what’s to be persisted.

    It continues until all controls have been evaluated, then it writes the data to a binary file.

    There are some caveats:

    Note that the properties have some ‘global’ options and, what’s more, you can get a little more specific in the methods themselves. I’ll explain:

    Look again at the properties for that last link, specifically the “Public Properties” and toward the end of the list you’ll see five (5) properties starting with the word “Save”.

    Maybe you don’t want to save ComboBoxes, for example. The default is Boolean True but if you set that to False then it will ignore all ComboBoxes.

    Sometimes though, you might want to save all ComboBoxes with the exception of one or two. If so, when you use the “Save” method, there’s an optional parameter – a ParamArray – and using that, you can specify exactly which ones to omit.

    The “Restore” method reverses that and also has its own specifics as shown as “OPTIONAL” near the bottom of that link.

    Hopefully with all of the options that I’ve put in there, you have a lot of flexibility in what it does.

    The file that’s saved is a compressed file and given the possibility of a fair amount of redundancy (with RTF files), I think that’s a good idea.

    Lastly, know that the calling assembly and the parent control’s id are also persisted. If you were to try to restore it to some other program (or even some other form of the same program), for example, it will throw an exception and refuse to go further.

     

    *****

     

    Since I’m quite sure that none of that made any sense at all, I’ve put together a “test” program that uses this class library and with that, I think you’ll get a good idea about what it does and also how easy it is compared to writing your own methods like the XML that I showed.

    I’ll explain that next.

     

    Continued in the next post

     


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

    Sunday, April 30, 2017 5:15 PM
  • Continued from previous post

     

     

    mip,

    Continuing, I’ve put together a test program that I hope you’ll download and run.

    I have the project folder zipped up and uploaded to my site here:

    http://www.fls-online.net/VBNet_Forum/04-30-17/Demo_WinFormsControlsPersistence.zip

    The assembly (the .dll file) is in that but if you only want the .dll by itself, I have that zipped up and uploaded here:

    http://www.fls-online.net/VBNet_Forum/04-30-17/ControlsPersistence.zip

     

    *****

     

    The demo program has a tab control with five (5) tab pages, one for each supported control type. When you first turn it on, look through the controls; they have [mostly] already been populated:

    The RichTextBox needs some attention.

    When you look on that tab, you’ll see two buttons. If you have a local file which is formatted as RTF, pick that but if not then there’s another button that will stream an RTF file that I put on my site for this purpose:

    Please also notice the status shown on the status bar. Nothing has yet been saved (persisted) so there’s no data to show about it. Given that, the menu choices are limited:

    Once you’ve done that and confirmed that there’s data to be persisted on all tabs, use the menu and ‘save’ it:

    Nothing exciting so far, but to prove that it actually worked, click to ‘clear’ everything:

    Look at the last few screenshots and the text of the status bar shows that there’s data saved now. So once you’ve cleared everything, let’s test it: Load it back in:

    If you’d like to see where it’s been save to, use the menu bar and go have a look:

     

    *****

     

    In conclusion then, in your actual program it’s nothing more than adding a reference to the assembly (the .dll file) and using “Save” and “Restore” when needed. Be sure to include that .dll file when distributing your program, the same as you’d do with any other third-party assembly.

     

     

    I hope that you find this helpful and I’d appreciate if you’d let me know how you make out with it. :)


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

    • Marked as answer by mipakteh Monday, May 01, 2017 5:55 AM
    Sunday, April 30, 2017 5:16 PM
  • Frank, Thank you very much.For your teach and advice.
    Monday, May 01, 2017 5:55 AM
  • Frank, Thank you very much.For your teach and advice.

    I'm glad that it helped. :)

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

    Monday, May 01, 2017 11:21 AM