saving configs into a text file then reloading?

Hi,

Please kindly assist how can we store the configs to a text file and reload then?

all objects are combo boxes. saving what the user selected into a text file and so that next time he runs the application
changes are save.

cmbLateTimeInHrs.AddItem "--", 0
cmbLateTimeInHrs.AddItem "1h", 1
cmbLateTimeInHrs.AddItem "2h", 2
cmbLateTimeInHrs.AddItem "3h", 3

Thanks.
RyanBankAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

vinnyd79Commented:
Something like this?



Private Sub Command1_Click()
Call SaveComboBoxes("C:\Cfg.txt")
End Sub

Private Sub Command2_Click()
Call LoadComboBoxes("C:\Cfg.txt")
End Sub

Private Sub SaveComboBoxes(CfgFile As String)
Dim Ctl As Control, ff As Integer, i As Long
ff = FreeFile
Open CfgFile For Output As #ff
For Each Ctl In Me.Controls
    If TypeOf Ctl Is ComboBox Then
        Print #ff, "~" & Ctl.Name
            Print #ff, "  " & Ctl.Text
    End If
Next
End Sub

Private Sub LoadComboBoxes(CfgFile As String)
Dim Ctl As Control, ff As Integer, i As Long, Ln As String, CtlName As String
ff = FreeFile
Open CfgFile For Input As #ff
Do Until EOF(ff)
Line Input #ff, Ln
If Left$(Ln, 1) = "~" Then
    CtlName = Trim$(Mid$(Ln, 2))
    GoTo GetNext
End If
For Each Ctl In Me.Controls
    If TypeOf Ctl Is ComboBox Then
        If CtlName = Ctl.Name Then
           Ctl.Text = Trim$(Ln)
        End If
    End If
Next
GetNext:
DoEvents
Loop
Close #ff
End Sub

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
vinnyd79Commented:
Forgot to close the file in the Save routine. It should be:

Private Sub SaveComboBoxes(CfgFile As String)
Dim Ctl As Control, ff As Integer, i As Long
ff = FreeFile
Open CfgFile For Output As #ff
For Each Ctl In Me.Controls
    If TypeOf Ctl Is ComboBox Then
        Print #ff, "~" & Ctl.Name
            Print #ff, "  " & Ctl.Text
    End If
Next
Close #ff
End Sub
vinnyd79Commented:

Here is an example that uses a "|" as a delimiter in the file and then uses the split function in the load routine:

Private Sub Command1_Click()
Call SaveComboBoxes("C:\Cfg.txt")
End Sub

Private Sub Command2_Click()
Call LoadComboBoxes("C:\Cfg.txt")
End Sub

Private Sub SaveComboBoxes(CfgFile As String)
Dim Ctl As Control, ff As Integer, i As Long
ff = FreeFile
Open CfgFile For Output As #ff
For Each Ctl In Me.Controls
    If TypeOf Ctl Is ComboBox Then
        Print #ff, Ctl.Name & "|" & Ctl.Text
    End If
Next
Close #ff
End Sub

Private Sub LoadComboBoxes(CfgFile As String)
Dim Ctl As Control, ff As Integer, Ln As String
Dim arrLn() As String, CtlName As String
ff = FreeFile
Open CfgFile For Input As #ff
Do Until EOF(ff)
Line Input #ff, Ln
If InStr(Ln, "|") Then
arrLn = Split(Ln, "|")
CtlName = arrLn(0)
For Each Ctl In Me.Controls
    If TypeOf Ctl Is ComboBox Then
        If CtlName = Ctl.Name Then
           Ctl.Text = arrLn(1)
        End If
    End If
Next
End If
DoEvents
Loop
Close #ff
End Sub
Big Business Goals? Which KPIs Will Help You

The most successful MSPs rely on metrics – known as key performance indicators (KPIs) – for making informed decisions that help their businesses thrive, rather than just survive. This eBook provides an overview of the most important KPIs used by top MSPs.

RyanBankAuthor Commented:
vinnyd79,

Amazing, how do we load into the combo box? how do load for each combo box?

cmbLateTimeInHrs.AddItem "--", 0
cmbLateTimeInHrs.AddItem "1h", 1
cmbLateTimeInHrs.AddItem "2h", 2
cmbLateTimeInHrs.AddItem "3h", 3


Thanks
vinnyd79Commented:
The above should handle all comboboxes on the form. If you want to load specific comboboxes only you can add an optional argument to the load routine to supply the Comboname.Maybe something like this:


Private Sub Command1_Click()
Call SaveComboBoxes("C:\Cfg.txt")
End Sub

Private Sub Command2_Click()
Call LoadComboBoxes("C:\Cfg.txt")  ' to load all the combo's on form
Call LoadComboBoxes("C:\Cfg.txt", "Combo1")  ' to just load combo1
End Sub

Private Sub SaveComboBoxes(CfgFile As String)
Dim Ctl As Control, ff As Integer, i As Long
ff = FreeFile
Open CfgFile For Output As #ff
For Each Ctl In Me.Controls
    If TypeOf Ctl Is ComboBox Then
        Print #ff, Ctl.Name & "|" & Ctl.Text
    End If
Next
Close #ff
End Sub

Private Sub LoadComboBoxes(CfgFile As String, Optional ComboName As String)
Dim Ctl As Control, ff As Integer, Ln As String
Dim arrLn() As String, CtlName As String
ff = FreeFile
Open CfgFile For Input As #ff
Do Until EOF(ff)
Line Input #ff, Ln
If Trim$(ComboName) = "" Then
If InStr(Ln, "|") Then
arrLn = Split(Ln, "|")
CtlName = arrLn(0)
For Each Ctl In Me.Controls
    If TypeOf Ctl Is ComboBox Then
        If CtlName = Ctl.Name Then
           Ctl.Text = arrLn(1)
        End If
    End If
Next
End If
Else
CtlName = Trim$(Left$(Ln, InStr(Ln, "|") - 1))
If Trim$(ComboName) = CtlName Then
    For Each Ctl In Me.Controls
    If TypeOf Ctl Is ComboBox Then
        If Ctl.Name = Trim$(ComboName) Then
           Ctl.Text = Trim$(Mid$(Ln, InStr(Ln, "|") + 1))
        End If
    End If
    Next
End If
End If

DoEvents
Loop
Close #ff
End Sub
dancebertCommented:
I have a class that does what you want, except that it saves the vaues in a PropertyBag (a binary file, it's a built in part of VB).  Call it at form_unload to save the settings, call it at form_load to reset controls from saved values.  If there are no saved values, it does nothing.  

It works with the following controls: ComboBox, TextBox, OptionButton, DriveListBox, DirListBox, CheckBox, ListBox.  It's easy to modify the code to save just the controls you want, or to add other control types.

Intro to PropertyBags at http://www.developer.com/net/vb/article.php/10926_1537081_5  Scroll down to the heading "PropertyBag Objects"

=====  form code ====

Private Sub Form_Load()
   <put any control initialization here>
   
    Dim o As New cControlSettings
    o.LoadSettings Me, "c:\settings.pb"   ' .pb is the usual extension for a PropertyBag
End Sub

Private Sub Form_Unload(Cancel As Integer)
    Dim o As New cControlSettings
    o.SaveSettings Me, "c:\settings.pb"
End Sub


=== cControlSetings.cls ===

Option Explicit

'' Save control contents to a PropertyBag, reload from there.
'' Works with: TextBox,OptionButton,DriveListBox,DirListBox,CheckBox,ListBox,ComboBox
'' Sample calling code at bottom


Private Declare Function SendMessage Lib "user32" _
    Alias "SendMessageA" (ByVal hwnd As Long, _
    ByVal wMsg As Long, ByVal wParam As Long, _
    lParam As Any) As Long

Private Const LB_GETSELITEMS = &H191
Private Const cnIGNORE_KEY As String = "SETTINGS"
Private Const cnIGNORE_VALUE As String = "NO"


Public Sub SaveSettings(ByVal p_frm As Form _
                , ByVal p_sPathAndFileName As String)
   
    Dim pb As PropertyBag: Set pb = New PropertyBag
    Dim vContents As Variant
    Dim ii As Long
   
    With pb
        Dim o As Control
        For Each o In p_frm.Controls
           
            If InStr(ReadTag(o.Tag, cnIGNORE_KEY), cnIGNORE_VALUE) = 0 Then
   
                If TypeOf o Is TextBox Then
                    .WriteProperty o.Name, o.Text
                ElseIf TypeOf o Is OptionButton Then
                    .WriteProperty o.Name, o.Value
                ElseIf TypeOf o Is DriveListBox Then
                    .WriteProperty o.Name, o.Drive
                ElseIf TypeOf o Is DirListBox Then
                    .WriteProperty o.Name, o.Path
                ElseIf TypeOf o Is CheckBox Then
                    .WriteProperty o.Name, o.Value
                ElseIf TypeOf o Is ListBox Then
                    If o.MultiSelect <> 0 Then
                        Dim sItems As String: sItems = SelectedListboxMultiItems(o)
                        Dim v_ As Variant: v_ = Split(sItems, "|")
                        For ii = LBound(v_) To UBound(v_)
                            .WriteProperty o.Name & CStr(ii), CStr(v_(ii))
                        Next
                    Else
                        .WriteProperty o.Name, SelectedListboxItem(o)
                    End If
   
                ElseIf TypeOf o Is ComboBox Then
                    .WriteProperty o.Name, o.ListIndex
                Else
'                    Debug.Print "ElseIf TypeOf o Is  " & Left(o.Name, Len(o.Name) - 1)
                End If

            End If  '' If InStr(ReadTag(o.Tag, cnIGNORE_KEY), cnIGNORE_VALUE) = 0 Then
        Next
       
        vContents = .Contents
    End With

   
    ' Save to a text file.
    If Not Dir(p_sPathAndFileName) = "" Then
        Kill p_sPathAndFileName
    End If
   
    Dim lFree As Long: lFree = FreeFile
    Open p_sPathAndFileName For Binary As #lFree
    Put #lFree, , vContents
    Close #lFree

End Sub

Public Sub LoadSettings(p_frm As Form _
            , p_sPathAndFileName As String)

    On Error GoTo Oops
   
    If Dir(p_sPathAndFileName) = "" Then
        Exit Sub
    End If

    Dim vTemp As Variant
    Dim lFree As Long: lFree = FreeFile
    Open p_sPathAndFileName For Binary As #lFree
    Get #lFree, , vTemp
    Close #lFree

    Dim byteAry() As Byte
    byteAry = vTemp
    Dim pb As PropertyBag
    Set pb = New PropertyBag
    pb.Contents = byteAry
   
    On Error GoTo Bogus
   
    Dim s As String
    With pb
        Dim o As Control
        For Each o In p_frm.Controls
            If InStr(ReadTag(o.Tag, cnIGNORE_KEY), cnIGNORE_VALUE) = 0 Then
           
                If TypeOf o Is TextBox Then
                    s = pb.ReadProperty(o.Name)
                    o.Text = s
                ElseIf TypeOf o Is OptionButton Then
                    s = pb.ReadProperty(o.Name)
                    o.Value = s
                ElseIf TypeOf o Is DriveListBox Then
                    s = pb.ReadProperty(o.Name)
                    o.Drive = s
                ElseIf TypeOf o Is DirListBox Then
                    s = pb.ReadProperty(o.Name)
                    o.Path = s
                ElseIf TypeOf o Is CheckBox Then
                    s = pb.ReadProperty(o.Name)
                    o.Value = s
                ElseIf TypeOf o Is ListBox Then
                    If o.MultiSelect <> 0 Then
                        HighlightListboxMultiItems o, pb
                    Else
                        HighlightListboxItem o, pb.ReadProperty(o.Name)
                    End If
               
                ElseIf TypeOf o Is ComboBox Then
                    s = pb.ReadProperty(o.Name)
                    o.ListIndex = CLng(s)
                Else
                    'nop
                End If
            End If  '' InStr(ReadTag(o.Tag, cnIGNORE_KEY), cnIGNORE_VALUE) = 0 Then
           
            GoTo Continue
Bogus:
            ' 327 Property bag contains an element with a control name that is not on p_frm
            ' 68 Drive doesn't exist
            If Err.Number = 327 Or Err.Number = 68 Then
                Err.Clear
            Else
                GoTo Oops
            End If
Continue:
        Next
    End With
   
Exit Sub

Oops:
    Err.Raise Err.Number
End Sub

Private Function SelectedListboxMultiItems(p_lstBox As ListBox) _
                As String
   
    ' Returns pipe delimited string of selected items from a listbox
                   
    With p_lstBox
        If .MultiSelect <> 0 Then
            ' API Parameters - dont change the datatype
            Dim ItemIndexes() As Long
            Dim iNumItems As Integer: iNumItems = .SelCount
            ' end API Parameters
            Dim ii As Long
            Dim sReturn As String
       
            If iNumItems > 0 Then
                ReDim ItemIndexes(iNumItems - 1)
                SendMessage p_lstBox.hwnd, LB_GETSELITEMS, iNumItems, ItemIndexes(0)
       
                For ii = 0 To iNumItems - 1
                    sReturn = sReturn & .List(ItemIndexes(ii)) & "|"
                Next ii
       
                ' Remove trailing comma
                Dim lLenReturn As Long: lLenReturn = Len(sReturn)
                If lLenReturn > 0 Then
                    sReturn = Left(sReturn, lLenReturn - 1)
                End If
            End If
        End If
    End With

    SelectedListboxMultiItems = sReturn

End Function


Private Function SelectedListboxItem(p_lstBox As ListBox) _
                As String
   
    ' Returns item selected in a non-multiselect listbox
               
    Dim ii As Long
    Dim sReturn As String
    With p_lstBox
        For ii = 0 To .ListCount - 1
            If .Selected(ii) Then
                sReturn = .List(ii)
            End If
        Next ii
    End With
   
    SelectedListboxItem = sReturn

End Function

Private Function HighlightListboxItem(p_lstBox As ListBox _
            , ByVal p_sSelected As String)
           
    '    Compare members of listbox to p_sSelected.  Highlight (select) the matching one.
    'Works on non-multiselect listboxes

    Dim ii As Long
    For ii = 0 To p_lstBox.ListCount - 1
        If InStr(p_sSelected, p_lstBox.List(ii)) > 0 Then
            p_lstBox.Selected(ii) = True
        Else
            p_lstBox.Selected(ii) = False
        End If
    Next

End Function



Private Sub HighlightListboxMultiItems(p_lstBox As ListBox, pb As PropertyBag)

    '    Compare members of listbox to propertybag.  Highlight (select) the matching ones.
    ' Works on multi-select listboxes.
   
    With p_lstBox
        If .MultiSelect <> 0 Then
            ' for each item in the list
            On Error Resume Next
            Dim sProp As String
            Dim ii As Long, jj As Long
            For ii = 0 To .ListCount - 1
                ' for each potential property
                .Selected(ii) = False
                For jj = 0 To .ListCount - 1
                    sProp = ""
                    sProp = pb.ReadProperty(.Name & CStr(jj))
                    If .List(ii) = sProp Then
                        .Selected(ii) = True
                        Exit For
                    End If
                Next
            Next
        End If
        On Error GoTo 0
    End With

End Sub

Private Function ReadTag(ByVal p_sSource As String _
            , ByVal p_sKey As String) _
            As Variant
           
    '   Parse contents of control.tag, searching  for desired key and it's associated values.
    ' Expected format: <key>,<value>| ...
    '           eg  Color,black|
    '       Delimiters are hard coded.  Anyone else using .Tag better conform to these
    'conventions or we're hosed.
    '
    ' Returns comma delimited string <value>s for specified <key>
    '       Return = Empty if key not found or Key doesn't have associated <value>s
    '       Elements are one for each <value>
   
    On Error GoTo Oops
   
    Dim vReturn As Variant
   
    ' Split KeyValue pairs into array elements containing <key>,<value>[<value>,...]
    Dim vPairs_ As Variant: vPairs_ = Split(p_sSource, "|")
   
    If UBound(vPairs_) = -1 Then
        vReturn = Empty
    Else
        ' Search <key> portion for target key, if found return value(s)
        Dim i As Integer
        Dim iDelimCol As Integer
        For i = 0 To UBound(vPairs_)
            iDelimCol = InStr(vPairs_(i), ",")
            If iDelimCol = 0 Then
                vReturn = Empty
            Else
                '' The -2 in iDelimCol - 2 cuts off the + or - in the key
                If Trim(UCase(p_sKey)) = Trim(UCase(Mid$(vPairs_(i), 1, iDelimCol - 1))) Then
                    'vReturn = Mid$(vPairs_(i), iDelimCol - 1, 1) & "," & Mid$(vPairs_(i), iDelimCol + 1)
                    'vReturn = Mid$(vPairs_(i), iDelimCol + 1)
                    vReturn = Trim(Mid$(vPairs_(i), iDelimCol + 1))
                    Exit For
                End If
            End If
        Next
    End If
       
    ReadTag = vReturn
   
    Exit Function
   
Oops:

        Err.Raise Err.Number, TypeName(Me) & "::" & "ReadTag" _
                        & IIf(Erl = 0, "", ", at or after line " & CStr(Erl))
End Function

' ==== debug only
'Public Sub DebugPrintListOfControlNames(ByVal p_frm As Form)
'        Dim o As Control
'        For Each o In p_frm.Controls
'
'        Next
'End Sub
'







HTorresCommented:

huh thats a lot of code.

maybe:

savesetting "myapp","config","lastvalue1", "1"
lastvalue = getsetting ("myapp","config","lastvalue1",defaultsetting)

will do the trick
HTorresCommented:
save:
savesetting "myapp", "config","cbo1-lastvalue",me.combo1.listindex
savesetting "myapp", "config","cbo2-lastvalue",me.combo2.listindex
savesetting "myapp", "config","cbo3-lastvalue",me.combo3.listindex
savesetting "myapp", "config","cbo4-lastvalue",me.combo4.listindex

load:
combo1.listindex = getsetting("myapp","config","cbo1-lastvalue",-1
combo2.listindex = getsetting("myapp","config","cbo2-lastvalue",-1
combo3.listindex = getsetting("myapp","config","cbo3-lastvalue",-1
combo4.listindex = getsetting("myapp","config","cbo4-lastvalue",-1

hope this helps





dancebertCommented:
>huh thats a lot of code.

Actually, thats a lot of reusable code.  No matter what form or what contents of that form, the code to save the settings is always the same:

Dim o As New cControlSettings
o.LoadSettings Me, "<filename>"

Using your method, every time one saves a setting, one has to hardcode a line of code for each control on each form.

It's obvious which one is easier to use.
HTorresCommented:
maybe if you put this in the procedure
...
...
Savedefaults()
...
...

or Getdefaults()

...

and in a module

Sub SaveDefaults()
savesetting "myapp", "config","cbo1-lastvalue",frmSome.combo1.listindex
savesetting "myapp", "config","cbo2-lastvalue",frmSome.combo2.listindex
savesetting "myapp", "config","cbo3-lastvalue",frmSome.combo3.listindex
savesetting "myapp", "config","cbo4-lastvalue",frmSome.combo4.listindex
end sub

Sub GetDefaults()
   frmSome.combo1.listindex = getsetting("myapp","config","cbo1-lastvalue",-1
   frmSome.combo2.listindex = getsetting("myapp","config","cbo2-lastvalue",-1
   frmSome.combo3.listindex = getsetting("myapp","config","cbo3-lastvalue",-1
   frmSome.combo4.listindex = getsetting("myapp","config","cbo4-lastvalue",-1
end sub

its 13 keys and some cut and paste.

hope this helps RyanBank

:)
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Web Languages and Standards

From novice to tech pro — start learning today.