none
Wrapping text at the 55'th character

    Question

  • Hi guys,

    I have some trouble with cutting a label in half.
    The max. Characters of the label is 110, im trying to cut it in half at 55 characters so the text is spread on 2 lines. So it fits on A4 paper.

    Dim CharactersInLabel As Integer = Len(Label1.text)
    If CharactersInLabel >= "55" Then
    
    Label1.Text = FirstHalf & Environment.NewLine & SecondHalf
    
    
    End If

    So i found That "Len()" counts the characters but i really have no clue how to loop the characters and cut it at 55.
    I hope someone can help me out a bit!

    Regards Kevin


    Friday, April 28, 2017 8:34 PM

Answers

  • You mean something like this?

    The first test is actually redundant:

        Private Function WrapLabelText(String1 As String) As String)
            Dim Count As Integer = String1.Length
    
            If Count <= 55 Then
                Return String1
            Else
                Return String1.SubString(0, 55) & Environment.NewLine & String1.Substring(55)
            End If
        End Function
    
        Label1.Text = WrapLabelText(Label1.Text)

    Use it like this:

            Label1.Text = WrapLabelText(Label1.Text)

    The MSDN documentation takes a bit of getting used to, but once you start using it then it becomes a lot more obvious.




    • Edited by AcamarMVP Saturday, April 29, 2017 1:00 AM sp
    • Marked as answer by Kevin Kastelein Saturday, April 29, 2017 9:17 AM
    Saturday, April 29, 2017 12:57 AM

All replies

  • Kevin,

    "Len" is a leftover -- use Substring:

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


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

    Friday, April 28, 2017 8:37 PM
  • Kevin (Orange),

    In thinking about this, it matters what the text is - at least whether or not it's one single contiguous string or words, so maybe try something like this and see how you make out?

    Option Strict On
    Option Explicit On
    Option Infer Off
    
    Public Class Form1
        Private Sub Form1_Load(ByVal sender As System.Object, _
                               ByVal e As System.EventArgs) _
                               Handles MyBase.Load
    
            Const text As String = _
                "My dog has fleas"
    
            Dim result As StringHalves = _
                StringHalves.GetStringHalves(text)
    
            Stop
    
        End Sub
    End Class
    
    
    
    
    
    Public NotInheritable Class StringHalves
        Private _firstHalf As String
        Private _secondHalf As String
    
        Private Sub New(ByVal first As String, _
                        ByVal second As String)
    
            _firstHalf = first
            _secondHalf = second
    
        End Sub
    
        Public Shared Function GetStringHalves(ByVal stringToCut As String) As StringHalves
    
            Dim retVal As StringHalves = Nothing
    
            Try
                If String.IsNullOrWhiteSpace(stringToCut) Then
                    Throw New ArgumentException("The string to cut cannot be null or empty.")
    
                ElseIf stringToCut.Length < 2 Then
                    Throw New ArgumentOutOfRangeException("String Length", "The string to cut must have at least 2 characters." & vbCrLf)
    
                Else
                    Dim s As String = stringToCut.Trim
                    Dim l As Integer = CInt(s.Length / 2)
    
                    If s.Contains(" "c) Then
                        Dim stringList As New List(Of String)
    
                        Dim words() As String = s.Split(" "c)
    
                        If words.Length > 0 Then
                            Dim sb1 As New System.Text.StringBuilder
                            Dim sb2 As New System.Text.StringBuilder
    
                            For Each sText As String In words
                                If sb1.Length + sText.Length < l Then
                                    sb1.Append(sText & " "c)
                                Else
                                    sb2.Append(sText & " "c)
                                End If
                            Next
    
                            retVal = New StringHalves(sb1.ToString.Trim, sb2.ToString.Trim)
                        End If
    
                    Else
                        retVal = New StringHalves(s.Substring(0, l), s.Substring(l))
                    End If
                End If
    
            Catch ex As Exception
                Throw
            End Try
    
            Return retVal
    
        End Function
    
        Public ReadOnly Property FirstHalf As String
            Get
                Return _firstHalf
            End Get
        End Property
    
        Public ReadOnly Property SecondHalf As String
            Get
                Return _secondHalf
            End Get
        End Property
    End Class


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

    Friday, April 28, 2017 9:11 PM
  • Using the same class but I changed the test (in the .Load event sub):

        Private Sub Form1_Load(ByVal sender As System.Object, _
                               ByVal e As System.EventArgs) _
                               Handles MyBase.Load
    
            Const text1 As String = _
                "My dog has fleas"
    
            Dim result As StringHalves = _
                StringHalves.GetStringHalves(text1)
    
            Stop
    
            Const text2 As String = _
                "Abracadabra"
    
            result = _
                StringHalves.GetStringHalves(text2)
    
            Stop
    
        End Sub

    I think this will show my earlier point about words versus contiguous text:


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

    Friday, April 28, 2017 9:23 PM
  • Thanks frank for all your effort!! But i think this is too complicated for what im trying to do.

    The reason to cut this label at 55 characters is to fit it onto an A4 paper. It should only be cutted if its above 55 characters.

    Besides that i'll try your code and try to understand whats going on!

    Thanks again!


    Friday, April 28, 2017 9:59 PM
  • The reason to cut this label at 55 characters is to fit it onto an A4 paper. It should only be cutted if its above 55 characters.

    So you are not actually cutting in half - you are wrapping the text at the 55'th character.  Use Substring as described above. You will need to first check that it is more than 55 characters, using the .Length property of your string.   If it is, use substring to get everything from 0 for a length of 55, append your newline character, and append everything from position 55 to the end.

    Friday, April 28, 2017 10:03 PM
  • Thanks frank for all your effort!! But i think this is too complicated for what im trying to do.

    The reason to cut this label at 55 characters is to fit it onto an A4 paper. It should only be cutted if its above 55 characters.

    Besides that i'll try your code and try to understand whats going on!

    Thanks again!


    Do you just want the first 55 characters?

    If so, use SubString(0, 55) but that leaves the rest in the dustpan.

    *****

    You could also take the concept that I started and continue to build lines of text, but please be sure to use a StringBuilder rather than a String directly. A StringBuilder is mutable; a String is not.


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

    Friday, April 28, 2017 10:14 PM
  • Thanks!, I'll change the title of this question to make it more clear!

    I'll try to figure out what you told me!

    Regards

    Friday, April 28, 2017 10:26 PM
  • Thanks!, I'll change the title of this question to make it more clear!

    I'll try to figure out what you told me!

    Regards

    I don't know who you're talking to but ... think it through:

        Private Sub SomeMethod()
    
            ' Kevin,
            ' 
            ' 
            ' Several years ago, I set this up
            ' so that I could type in text and
            ' have my little procedure here
            ' figure out where to wrap it to
            ' thusly put it on another line.
            ' 
            ' There are a few caveats: What if
            ' a particular word's length is -
            ' by itself - too long to wrap?
            ' 
            ' Work through that in your design
            ' and then write it. It's not
            ' really all that much to it once
            ' you get going.
            ' 
            ' :-)
    
        End Sub


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

    Friday, April 28, 2017 10:40 PM
  • Thanks frank, You helped me alot before i really appreciate you effort.

    I'm trying to understand the code you gave me, and it seem verry understandable for such a noob like me.

    So i try to figure this out and i thought i did understand it but after all it seem a bit abracadabra too me.

    I hope im not bothering you!

     Public Shared Function GetStringHalves(ByVal stringToCut As String) As StringHalves
    
            Dim retVal As StringHalves = Nothing
    
            Try
                If String.IsNullOrWhiteSpace(stringToCut) Then
                    Throw New ArgumentException("The string to cut cannot be null or empty.")
    
                ElseIf stringToCut.Length < 2 Then
                    Throw New ArgumentOutOfRangeException("String Length", "The string to cut must have at least 2 characters." & vbCrLf)
    
                Else
                    Dim s As String = stringToCut.Trim 'IN THIS CASE THIS WOULD BE LABEL1.TEXT
                    Dim l As Integer = CInt(s.Length / 2)
    
                    If s.Contains(" "c) Then 'IF IT CONTAINS SPACES THEN STRING HAS MULTIPLE WORDS
                        Dim stringList As New List(Of String) 'WHY MAKE A LIST OF WORDS
    
                        Dim words() As String = s.Split(" "c) 'THIS I DONT REALLY UNDERSTAND YET
    
                        If words.Length > 0 Then 'ISNT THIS ALWAYS ABOVE 0?
                            Dim sb1 As New System.Text.StringBuilder
                            Dim sb2 As New System.Text.StringBuilder
    
                            For Each sText As String In words
                                If sb1.Length + sText.Length < l Then 'ISNT THIS ALWAYS ABOVE 1? FROM HERE IT SEEM PRETTY ABRACADABRA TO ME
                                    sb1.Append(sText & " "c)
                                Else
                                    sb2.Append(sText & " "c)
                                End If
                            Next
    
                            retVal = New StringHalves(sb1.ToString.Trim, sb2.ToString.Trim)
                        End If
    
                    Else
                        retVal = New StringHalves(s.Substring(0, l), s.Substring(l))
                    End If
                End If
    
            Catch ex As Exception
                Throw
            End Try
    
            Return retVal
    
        End Function


    Sorry for the messy notes :/

    Regards

    Friday, April 28, 2017 10:56 PM
  • Kevin,

    Start with this:

    Throw that class away -- you need a function that will return a string. The string may or may not have multiple lines.

    When you wanted "halves", I used a class so that you'd have the first line and the second line. Now that's not needed.


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


    • Edited by Frank L. Smith Friday, April 28, 2017 11:00 PM ...reworded
    Friday, April 28, 2017 11:00 PM
  • So i try to figure this out and i thought i did understand it but after all it seem a bit abracadabra too me.

    Did you check out the link:
    https://msdn.microsoft.com/en-us/library/system.string.substring(v=vs.110).aspx

    That pretty much gives you the code you need to insert into the line of code from your first post.

    Complete it with the prior check on the length of the string, and it's done.
    https://msdn.microsoft.com/en-us/library/system.string.length(v=vs.110).aspx

    Friday, April 28, 2017 11:27 PM
  • Yeah i tryed to figure it out but it seem not exactly what i mean. Or i just dont get it yet.

    It should output something like this

    String: Hello my name is kevin, im from the netherlands! this is an example.

    Should get wrapped at least like this:

    String1 = Hello my name is kevin, im from the netherlands! this i
    String2 = s an example.

    So i can use it like: 

    Label1.text = string1 & Environment.NewLine & string2

    Im still trying to get this done with the links you told me!

    Friday, April 28, 2017 11:47 PM
  • Kevin,

    You'll never know how many lines, so your method needs to be more flexible than that.

    I'll do it if, by the end of the weekend, you don't get it but working through it really will show you what's going on.

    Set up a method that accepts two parameter: A string to be cut up and a maximum character count per line.

    Now, using a StringBuilder, you'll do ........ what?

    Work through it. ;-)


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

    Friday, April 28, 2017 11:55 PM
  • So i can use it like: 

    Label1.text = string1 & Environment.NewLine & string2

    What is the code you are using to create string1 and string2?

    The code you have posted should display the result the way you want.

    Friday, April 28, 2017 11:58 PM
  • Thats the part im looking for!

    Thanks and regards!

    Saturday, April 29, 2017 12:02 AM
  • So i can use it like: 

    Label1.text = string1 & Environment.NewLine & string2

    What is the code you are using to create string1 and string2?

    The code you have posted should display the result the way you want.

    And if the total character count is greater than 110 then.........what?

    It should handle any string of any length and return a string with everything intact, notwithstanding how many lines of text it took.

    There's a provision to be worked through though which is that if a single string element (ergo, a word) is longer than the specified max, then there can be no solution.


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

    Saturday, April 29, 2017 12:05 AM
  • Hi frank,

    The string is given by the user in a Richtextbox with MaxLength 110.
    So we do know that it will be max. 2 lines.

    i'll try some more things!

    Thanks again and regards :)

    Saturday, April 29, 2017 12:06 AM
  • Hi frank,

    The string is given by the user in a Richtextbox with MaxLength 110.
    So we do know that it will be max. 2 lines.

    i'll try some more things!

    Thanks again and regards :)

    Ok then it's really simple:

    Start at zero and go to 55 (that's the first line)

    Start at 56 through the end (that's the second line)


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

    Saturday, April 29, 2017 12:08 AM
  • Ok then it's really simple: - For an expert like you!
    Saturday, April 29, 2017 12:11 AM
  • Ok then it's really simple: - For an expert like you!

    I guess you're talking to me?

    If so then know that I'm far from an expert. ;-)

    *****

    If you have a maximum of 110 characters and two lines ... work through it.

    First, what if it's only one character? You can't split that up.

    What if it's more than one but fewer than 55? No second line or an empty second line?

    *****

    Working through it yourself will help you in the long run - I am sure of it!

    :)


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

    Saturday, April 29, 2017 12:16 AM
  • For me you're an expert for sure! At least at being helpfull!

    You mean something like this?

            Dim String1 As String = Label1.Text
            Dim Count As Integer = String1.Length
    
            If Count = 0 Then
                Exit Sub
            ElseIf Count <= "55" Then
                Exit Sub
            Else
                'WRAP TEXT
            End If

    Im trying to learn as fast as possible.. Perhaps thats not the right way!

    Regards!


    Saturday, April 29, 2017 12:36 AM
  • You mean something like this?

    The first test is actually redundant:

        Private Function WrapLabelText(String1 As String) As String)
            Dim Count As Integer = String1.Length
    
            If Count <= 55 Then
                Return String1
            Else
                Return String1.SubString(0, 55) & Environment.NewLine & String1.Substring(55)
            End If
        End Function
    
        Label1.Text = WrapLabelText(Label1.Text)

    Use it like this:

            Label1.Text = WrapLabelText(Label1.Text)

    The MSDN documentation takes a bit of getting used to, but once you start using it then it becomes a lot more obvious.




    • Edited by AcamarMVP Saturday, April 29, 2017 1:00 AM sp
    • Marked as answer by Kevin Kastelein Saturday, April 29, 2017 9:17 AM
    Saturday, April 29, 2017 12:57 AM
  • Oh my G.. Am I really that noobisch.. Okay i see that i was on the right way, but still gotta learn alot.

    Thanks again, I realy appreciate your effort!

    Kind regards to Acamar & Frank!

    Saturday, April 29, 2017 8:50 AM
  • Kevin,

    I wasn't up for staying up last night to do this, but in case you or someone else who later finds this might find it helpful, I've put something together for you, shown below.

    I have it as a class mainly just so you can reuse it more easily. There are two shared methods so you can all but ignore the fact that it's in a class.

    The code for the class:

    Option Strict On Option Explicit On Option Infer Off Public NotInheritable Class TextFunctions Private Sub New() End Sub Public Shared Function _ GetParagraph(ByVal textToTrim As String, _ ByVal maxCharCountPerLine As Integer) As String Dim retVal As String = Nothing Try If String.IsNullOrWhiteSpace(textToTrim) Then Throw New ArgumentException("The text to trim cannot be null or empty.") ElseIf maxCharCountPerLine <= 0 Then Throw New ArgumentOutOfRangeException("Maximum Character Count Per Line", "Must be a postive value." & vbCrLf) Else Dim textToUse As String = textToTrim.Trim Dim wordsList As New List(Of String) Dim linesList As New List(Of String) Dim maxCharsPerLine As Integer = maxCharCountPerLine If textToUse.Contains(" "c) Then Dim words() As String = _ textToUse.Split(New String() {" "c}, _ StringSplitOptions.RemoveEmptyEntries) If words IsNot Nothing AndAlso words.Length > 0 Then wordsList.AddRange(words) End If Else wordsList.Add(textToUse) End If Dim largest As Integer = ((From s As String In wordsList Select s.Length).Max) + 2 If largest > maxCharCountPerLine Then Throw New ArgumentException("The length of one or more words in the text" & vbCrLf & _ "exceeds the maximum character count per line.") Else Dim sb As New System.Text.StringBuilder For i As Integer = 0 To wordsList.Count - 1 If wordsList(i).Trim = "" Then If sb.ToString.Length > 0 Then linesList.Add(sb.ToString.Trim) End If linesList.Add("") sb.Length = 0 Else If i < wordsList.Count - 1 Then If (wordsList(i + 1).Length + 3) + wordsList(i).Length + sb.ToString.Length > maxCharsPerLine Then sb.Append(" " & wordsList(i)) linesList.Add(sb.ToString.Trim) sb.Length = 0 Else sb.Append(" " & wordsList(i)) End If Else sb.Append(" " & wordsList(i)) End If End If Next If sb.ToString.Length > 0 Then linesList.Add(sb.ToString.Trim) End If sb.Length = 0 If linesList.Count > 0 Then For Each line As String In linesList sb.AppendLine(line) Next If sb.Length > 2 Then sb.Remove(sb.Length - 2, 2) End If retVal = sb.ToString End If End If End If Catch ex As Exception Throw End Try Return retVal End Function Public Shared Function _ GetEnumeratedString(ByVal textToTrim As String, _ ByVal maxCharCountPerLine As Integer) As IEnumerable(Of String) Dim retVal As IEnumerable(Of String) = Nothing Try If String.IsNullOrWhiteSpace(textToTrim) Then Throw New ArgumentException("The text to trim cannot be null or empty.") ElseIf maxCharCountPerLine <= 0 Then Throw New ArgumentOutOfRangeException("Maximum Character Count Per Line", "Must be a postive value." & vbCrLf) Else Dim textToUse As String = textToTrim.Trim Dim wordsList As New List(Of String) Dim linesList As New List(Of String) Dim maxCharsPerLine As Integer = maxCharCountPerLine If textToUse.Contains(" "c) Then Dim words() As String = _ textToUse.Split(New String() {" "c}, _ StringSplitOptions.RemoveEmptyEntries) If words IsNot Nothing AndAlso words.Length > 0 Then wordsList.AddRange(words) End If Else wordsList.Add(textToUse) End If Dim largest As Integer = ((From s As String In wordsList Select s.Length).Max) + 2 If largest > maxCharCountPerLine Then Throw New ArgumentException("The length of one or more words in the text" & vbCrLf & _ "exceeds the maximum character count per line.") Else Dim sb As New System.Text.StringBuilder For i As Integer = 0 To wordsList.Count - 1 If wordsList(i).Trim = "" Then If sb.ToString.Length > 0 Then linesList.Add(sb.ToString.Trim) End If linesList.Add("") sb.Length = 0 Else If i < wordsList.Count - 1 Then If (wordsList(i + 1).Length + 3) + wordsList(i).Length + sb.ToString.Length > maxCharsPerLine Then sb.Append(" " & wordsList(i)) linesList.Add(sb.ToString.Trim) sb.Length = 0 Else sb.Append(" " & wordsList(i)) End If Else sb.Append(" " & wordsList(i)) End If End If Next If sb.ToString.Length > 0 Then linesList.Add(sb.ToString.Trim) End If sb.Length = 0 If linesList.Count > 0 Then retVal = linesList.ToArray End If End If End If Catch ex As Exception Throw End Try Return retVal End Function End Class


    Testing it in Form1's .Load event handler sub:

    Option Strict On Option Explicit On Option Infer Off Public Class Form1 Private Sub Form1_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles MyBase.Load ' The following is based on something that I put ' together several years ago which was designed so that ' I could format comments. ' ' In fact, that's what I'm using now to create this ' comment. ' ' The "Stop" will cause the program to halt, just the ' same as though you'd put a breakpoint in. When it ' does, hover your mouse over any variable that's then ' in scope and you can see the value of it. ' ' ***** ' ' The following has three strings (text1, text2, and ' text3). They're all perfectly valid strings but ' because I set the maximum character count per line to ' a value of 35, text3 won't fit. An exception will be ' thrown and I've intentionally not handled it. Run it ' and you'll see what happens. ' ' Following that, comment out "result3" and continue. ' ' The class has two shared methods: ' ' 1) GetParagraph returns the entire string as a single ' string with lines wrapped based on the specified ' maximum character count per line. ' ' 2) GetEnumeratedString returns the same thing - BUT - ' as an IEnumerable(Of String). That way, you can get ' any line that you want based on the index (just the ' same as though it'd returned a List(Of String) but ' with this, you can't add, remove, or insert; it's ' read-only). ' ' So give it a try and hopefully you'll find this ' useful. :) Const text1 As String = "TRUE! --nervous --very, very dreadfully nervous I had been and am; but why will you say that I am mad? The disease had sharpened my senses --not destroyed --not dulled them. Above all was the sense of hearing acute. I heard all things in the heaven and in the earth. I heard many things in hell. How, then, am I mad? Hearken! and observe how healthily --how calmly I can tell you the whole story." Const text2 As String = "Abracadabra" Const text3 As String = "Pneumonoultramicroscopicsilicovolcanoconiosis" Dim result1 As String = TextFunctions.GetParagraph(text1, 35) Dim result2 As String = TextFunctions.GetParagraph(text2, 35) Stop ' The following will throw an exception: ' Dim result3 As String = TextFunctions.GetParagraph(text3, 35) ' After you run it, comment out "result3" and run it again ' to continue: Dim result4 As IEnumerable(Of String) = _ TextFunctions.GetEnumeratedString(text1, 35) Dim result5 As IEnumerable(Of String) = _ TextFunctions.GetEnumeratedString(text2, 35) Stop End Sub End Class


    I hope you find it helpful. :)


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

    • Proposed as answer by Frank L. Smith Saturday, April 29, 2017 5:08 PM
    Saturday, April 29, 2017 1:39 PM
  • Kevin,

    I wasn't up for staying up last night to do this, but in case you or someone else who later finds this might find it helpful, I've put something together for you, shown below.


    Frank,

    I've seen how much work you made of this question. I saw them all and would have done it the same way as Acamar. 

    However, because of your work I did not proposed his reply this time as answer. 

    Be aware just about the question of the OP, not what it could have been if the rows where bad formed.


    Success
    Cor



    Saturday, April 29, 2017 5:04 PM
  • Kevin,

    I wasn't up for staying up last night to do this, but in case you or someone else who later finds this might find it helpful, I've put something together for you, shown below.


    Frank,

    I've seen how much work you made of this question. I saw them all and would have done it the same way as Acamar. 

    However, because of your work I did not proposed his reply this time as answer. 

    Be aware just about the question of the OP, not what it could have been if the rows where bad formed.


    Success
    Cor



    To each their own.

    I like it! :)


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

    Saturday, April 29, 2017 5:08 PM

  • To each their own.

    I like it! :)



    Frank,

    Thanks for giving me a lesson in American English, I like this one. 


    Seriously
    Cor


    Saturday, April 29, 2017 7:18 PM