locked
Boilerplate text switchboard. RRS feed

  • Question

  • Dear all.

    I'm an absolute beginner at this, so I'm sorry it this sounds too basic. 

    I'm trying to write a program that will function as a boilerplate menu, so I can insert text strings into Word. 

    Let me describe it in more detail. I will have a window docked on the right side of the screen, which will contain a number of check boxes with symptoms, such as "decreased appetite", "fatigue", and so forth. I want to be able to click to select any number of symptoms, and then concatenate all of those strings into a list of symptoms separated by commas, then finally ending with a period at the end of the statement. The sentence will then be inserted into a word document, or into an active field in whatever active window.

    Any thoughts on how to do this?

    Thanks
    Niels
    Sunday, February 7, 2010 9:20 PM

Answers

  • To start with I guess the simplest thing would be to add a listbox to a form and fill it with these symptoms.  Then when the user clicks a button to "process" these selections you can iterate through the SelectedItems collection on the listbox and concatenate the string values that were selected.

    The code below illustrates this very simply.  Please note that I am just showing you how to get the selected items and create a comma-separated string out of the values.  I do not really work with Word automation so I am not including it.  I would strongly suggest you start a new thread for the Word part when you get to it.  Also note that I am using a StringBuilder to concatenate.  While you coud just use the "&=" operator to continually add to a string variable, this is a bad practice and can hurt app performance when you are working with large numbers of strings.  So I am trying to show you a habit that is worth getting used to.
     
    *To run this code just create a new forms project and paste this code behind the empty Form1.  Do not add a ny controls to the form - it is done for you here in the code.
     

     
    Public Class Form1
        Private WithEvents ListBox1 As New ListBox
        Private WithEvents Button1 As New Button
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    
            'Dynamically setting up the controls...
            Me.Size = New Size(500, 300)
            Me.Controls.Add(ListBox1)
            ListBox1.Width = 350
            ListBox1.Dock = DockStyle.Right
            ListBox1.SelectionMode = SelectionMode.MultiExtended
    
            Button1.Text = "Click Me"
            Button1.Location = New Point(30, 30)
            Me.Controls.Add(Button1)
    
            ListBox1.Items.AddRange(New String() {"decreased appetite", "fatigue", "chest pains", "irritated bowels", "excessive hairiness", "extra digits", "crotch itch"})
    
        End Sub
    
        Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
            If ListBox1.SelectedItems.Count = 0 Then
                MsgBox("please select at least one item from the list")
            Else
                Dim sb As New System.Text.StringBuilder
                Dim count As Int32 = ListBox1.SelectedItems.Count
                For i As Int32 = 0 To count - 1
                    If i = count - 1 Then
                        sb.Append(" and ")
                    End If
                    sb.Append(ListBox1.SelectedItems(i).ToString)
                    If i < count - 1 Then
                        sb.Append(",")
                    Else
                        sb.Append(".")
                    End If
                Next
                MsgBox("The symptoms you have selected: are " & sb.ToString)
            End If
        End Sub
    End Class
    

     
     
     
    • Marked as answer by Berserk1977 Tuesday, February 9, 2010 11:40 PM
    Sunday, February 7, 2010 9:53 PM
  • The example below creates a checkbox for each symptom.  The symptoms are read in from a file, which is a plain text file with each symptom on one line.  That means you can change the list without changing the program. You will need to consider where this file is to be located, and adjust the reference accordingly.

    The checkboxes are laid out under the button, at the left margin, for as many as required.  They have an arbitrary width.  I have indicated where your code to pass the result back to Word needs to go.


    Public Class Form1
        
    Private WithEvents Button1 As New Button
        
    Dim BoilerPlates() As String
        Dim CheckBoxes As List(Of CheckBox) = New List(Of CheckBox)
        
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

            
    'Dynamically setting up the controls...
            Button1.Text = "Create"
            Button1.Location = New Point(20, 10)
            
    AddHandler Button1.Click, AddressOf Button1_Click
            
    Me.Controls.Add(Button1)

            
    Dim StrLines = My.Computer.FileSystem.ReadAllText("C:\Users\Public\Symptoms.txt")
            
    Dim Sep() As String = {vbCrLf}
            BoilerPlates = StrLines.Split(Sep, System.StringSplitOptions.RemoveEmptyEntries)

            
    Dim V As Integer = Button1.Top + Button1.Height * 1.1
            
    For I As Integer = 0 To BoilerPlates.Count - 1
                
    Dim C As CheckBox = New CheckBox
                C.Location = 
    New Point(Button1.Left, V)
                C.Size = 
    New Size(120, C.Height)
                C.Text = BoilerPlates(I)
                C.AutoSize = 
    False
                Me.Controls.Add(C)
                CheckBoxes.Add(C)
                V += C.Height
            
    Next I
        
    End Sub

        Private Sub Button1_Click(ByVal sender As ObjectByVal e As System.EventArgs)
            
    Dim S As String = ""
            For I As Integer = 0 To CheckBoxes.Count - 1
                
    Dim C As CheckBox = CheckBoxes(I)
                
    If C.Checked Then
                    If S = "" Then
                        S = BoilerPlates(I)
                    
    Else
                        S &= ", " & BoilerPlates(I)
                    
    End If
                End If
            Next
            If S <> "" Then S &= "."
            'now insert S into the document
            MsgBox(S)
        
    End Sub

    End
     Class

    • Marked as answer by Berserk1977 Tuesday, February 9, 2010 11:40 PM
    Monday, February 8, 2010 7:28 AM

All replies

  • To start with I guess the simplest thing would be to add a listbox to a form and fill it with these symptoms.  Then when the user clicks a button to "process" these selections you can iterate through the SelectedItems collection on the listbox and concatenate the string values that were selected.

    The code below illustrates this very simply.  Please note that I am just showing you how to get the selected items and create a comma-separated string out of the values.  I do not really work with Word automation so I am not including it.  I would strongly suggest you start a new thread for the Word part when you get to it.  Also note that I am using a StringBuilder to concatenate.  While you coud just use the "&=" operator to continually add to a string variable, this is a bad practice and can hurt app performance when you are working with large numbers of strings.  So I am trying to show you a habit that is worth getting used to.
     
    *To run this code just create a new forms project and paste this code behind the empty Form1.  Do not add a ny controls to the form - it is done for you here in the code.
     

     
    Public Class Form1
        Private WithEvents ListBox1 As New ListBox
        Private WithEvents Button1 As New Button
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    
            'Dynamically setting up the controls...
            Me.Size = New Size(500, 300)
            Me.Controls.Add(ListBox1)
            ListBox1.Width = 350
            ListBox1.Dock = DockStyle.Right
            ListBox1.SelectionMode = SelectionMode.MultiExtended
    
            Button1.Text = "Click Me"
            Button1.Location = New Point(30, 30)
            Me.Controls.Add(Button1)
    
            ListBox1.Items.AddRange(New String() {"decreased appetite", "fatigue", "chest pains", "irritated bowels", "excessive hairiness", "extra digits", "crotch itch"})
    
        End Sub
    
        Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
            If ListBox1.SelectedItems.Count = 0 Then
                MsgBox("please select at least one item from the list")
            Else
                Dim sb As New System.Text.StringBuilder
                Dim count As Int32 = ListBox1.SelectedItems.Count
                For i As Int32 = 0 To count - 1
                    If i = count - 1 Then
                        sb.Append(" and ")
                    End If
                    sb.Append(ListBox1.SelectedItems(i).ToString)
                    If i < count - 1 Then
                        sb.Append(",")
                    Else
                        sb.Append(".")
                    End If
                Next
                MsgBox("The symptoms you have selected: are " & sb.ToString)
            End If
        End Sub
    End Class
    

     
     
     
    • Marked as answer by Berserk1977 Tuesday, February 9, 2010 11:40 PM
    Sunday, February 7, 2010 9:53 PM
  • You want to build an addin for Word, and you'd better go to the Office Forums, I think.
    please, mark this as answer if it is THE answer
    ----------------
    Diego Cattaruzza
    Microsoft MVP - Visual Basic: Development
    blog: http://community.visual-basic.it/Diego
    web site: http://www.visual-basic.it
    Sunday, February 7, 2010 9:56 PM
  • @ Dig-Boy -> Good advice as always.

    Tell me this (not to be taking this thread the wrong way so hopefully it'll be only a slight diversion): It's my understanding that the stringbuilder is a more memory efficient way rather than direct concatenation of strings using the ampersand ... but tell me why?

    Thanks :)
    Sunday, February 7, 2010 10:15 PM
  • This is great! Very close to what I want. Thank you so much!

    How do I change the list items to individual checkboxes?

    Thanks

    Niels
    Sunday, February 7, 2010 10:27 PM
  • @Frank:  Exactly, the stringbuilder is more memory efficient.  I'm not the best on teh topic of memory management but my understanding is that every time you concatenate a string it is allocating extra memory for both strings being concatenated - and the resulting string.  StringBuilders keep the allocations down to a minimum and allow for a more efficient and faster way to join moderate to large amounts of strings.  No time now but I'll try to find a link that describes the difference in more detail.  I've seen it written in many threads in this forum alone.

    @Toucan:  Try using the CheckedListBox control instead -- but be aware that it has different properties (i.e. CheckedItems rather than SelectedItems - if I remember correctly).
    Sunday, February 7, 2010 11:37 PM
  • @Frank:  Exactly, the stringbuilder is more memory efficient.  I'm not the best on teh topic of memory management but my understanding is that every time you concatenate a string it is allocating extra memory for both strings being concatenated - and the resulting string.  StringBuilders keep the allocations down to a minimum and allow for a more efficient and faster way to join moderate to large amounts of strings.  No time now but I'll try to find a link that describes the difference in more detail.  I've seen it written in many threads in this forum alone.


    Thanks :)
    Sunday, February 7, 2010 11:39 PM
  • Here's a CodeProject article that seems to provide some hard data on the comparisons.  Interestingly there are some times when the StringBuilder is not as optimal.

    http://www.codeproject.com/KB/cs/StringBuilder_vs_String.aspx

    Monday, February 8, 2010 1:05 AM
  • Here's a CodeProject article that seems to provide some hard data on the comparisons.  Interestingly there are some times when the StringBuilder is not as optimal.

    http://www.codeproject.com/KB/cs/StringBuilder_vs_String.aspx




    ".NET Strings are immutable which is the reason why a new string object is created every time we alter it (insert, append, remove, etc.)."

    That is interesting - although it sounds to me like the stringbuilder is still more "memory concise". I wonder though - if you put your routine in a sub so that all declarations are done there, then it simply updates a class-level string when done (maybe a function for that matter), would the memory used be restored?

    Well either way, I don't want to nor did I mean to encroach on this thread so I'll leave it at that, but thanks for your input and helpful information. :)
    Monday, February 8, 2010 1:25 AM
  • That testing referred to speed only, but, as you note, memory efficiency is often promoted as a reason for using stringbuilder. 

    If StringBuilder is more memory efficient, it would only be during the actual processing.  String manipulation creates a new string for every change made to a string, but the memory occupied by the old string is quickly recovered.  No additional action is required to ensure that this memory is recovered.  If a reference to the original string is being retained, such as

      strA = strB & strC

    then the memory usage of string and stringbuilder is going to be the same.  If the original string is discarded -

      StrA &= StrB

    then the space it used will be recovered, but string might use more memory during the concat operation than a stringbuilder would - it depends on the details of the implementation.  But the final result would be the same.
    Monday, February 8, 2010 1:50 AM
  • That testing referred to speed only, but, as you note, memory efficiency is often promoted as a reason for using stringbuilder. 

    If StringBuilder is more memory efficient, it would only be during the actual processing.  String manipulation creates a new string for every change made to a string, but the memory occupied by the old string is quickly recovered.  No additional action is required to ensure that this memory is recovered.  If a reference to the original string is being retained, such as

      strA = strB & strC

    then the memory usage of string and stringbuilder is going to be the same.  If the original string is discarded -

      StrA &= StrB

    then the space it used will be recovered, but string might use more memory during the concat operation than a stringbuilder would - it depends on the details of the implementation.  But the final result would be the same.


    All the more interesting!

    @Niels -> My apologies for starting this - I'm sure that you'll get everything answered here ... you're in good company with these pro's! :)
    Monday, February 8, 2010 1:53 AM
  • The example below creates a checkbox for each symptom.  The symptoms are read in from a file, which is a plain text file with each symptom on one line.  That means you can change the list without changing the program. You will need to consider where this file is to be located, and adjust the reference accordingly.

    The checkboxes are laid out under the button, at the left margin, for as many as required.  They have an arbitrary width.  I have indicated where your code to pass the result back to Word needs to go.


    Public Class Form1
        
    Private WithEvents Button1 As New Button
        
    Dim BoilerPlates() As String
        Dim CheckBoxes As List(Of CheckBox) = New List(Of CheckBox)
        
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

            
    'Dynamically setting up the controls...
            Button1.Text = "Create"
            Button1.Location = New Point(20, 10)
            
    AddHandler Button1.Click, AddressOf Button1_Click
            
    Me.Controls.Add(Button1)

            
    Dim StrLines = My.Computer.FileSystem.ReadAllText("C:\Users\Public\Symptoms.txt")
            
    Dim Sep() As String = {vbCrLf}
            BoilerPlates = StrLines.Split(Sep, System.StringSplitOptions.RemoveEmptyEntries)

            
    Dim V As Integer = Button1.Top + Button1.Height * 1.1
            
    For I As Integer = 0 To BoilerPlates.Count - 1
                
    Dim C As CheckBox = New CheckBox
                C.Location = 
    New Point(Button1.Left, V)
                C.Size = 
    New Size(120, C.Height)
                C.Text = BoilerPlates(I)
                C.AutoSize = 
    False
                Me.Controls.Add(C)
                CheckBoxes.Add(C)
                V += C.Height
            
    Next I
        
    End Sub

        Private Sub Button1_Click(ByVal sender As ObjectByVal e As System.EventArgs)
            
    Dim S As String = ""
            For I As Integer = 0 To CheckBoxes.Count - 1
                
    Dim C As CheckBox = CheckBoxes(I)
                
    If C.Checked Then
                    If S = "" Then
                        S = BoilerPlates(I)
                    
    Else
                        S &= ", " & BoilerPlates(I)
                    
    End If
                End If
            Next
            If S <> "" Then S &= "."
            'now insert S into the document
            MsgBox(S)
        
    End Sub

    End
     Class

    • Marked as answer by Berserk1977 Tuesday, February 9, 2010 11:40 PM
    Monday, February 8, 2010 7:28 AM
  • Amazing, Acamar!!!
    Thank you so much!
    Niels
    Tuesday, February 9, 2010 5:10 PM
  • If any of the above responses answered your question, could you please mark them as answers so that people do no tneed to continue monitoring this thread.  Thanks.
    Tuesday, February 9, 2010 10:06 PM