VBspeed / String / WordWrap
VBspeed © 2000-10, updated: 18-mar-2005

Function WordWrap
Wraps a string to a given number of characters using a line break character.
Note, that our function is a wrapper based on character counting; we are not measuring the rendered text width within a given device context. By the way, "LineWrap" is another, slightly better, term for what the function does: wrapping lines at word boundaries; nevertheless, "WordWrap" is more common.

   Function WordWrap( _
      ByRef Text As String, _
      ByVal Width As Long, _
      Optional ByRef CountLines As Long) As String
Note the following points:
  1. Text can be wrapped at space (ASCII 32) and hyphen (ASCII 45) characters.
  2. Words that are longer than Width are cut.
  3. We wrap lossless: no string characters of the original string are replaced, so that the output is fully revertible to the input by simply removing the line break characters. To achieve this, lines wrapped at a space character will end in that space character (see examples below). In other words, the space behaves exactly as a wrapping hyphen.
  4. The line break character is fixed to 2-byte vbCrLf (ASCII 13 & ASCII 10).
  5. No line breaks are added to the very end of the output (see last example below).
  6. Any line break characters in the original string are ignored. It's the responsability of the caller to take care of removing them.
  7. If Width is 0 the function returns an empty string.
  8. CountLines is an optional return argument that's handy when you need to know the height of the wrapped string returned or whether anything has been wrapped (CountLines > 1).
Examples (the comma stands for vbCrLf):
  WordWrap("ab cdef ghi", 2)       --> "ab ,cd,ef ,gh,i"
  WordWrap("ab cdef ghi", 3)       --> "ab ,cde,f ,ghi"
  WordWrap("ab cdef ghi", 4)       --> "ab ,cdef ,ghi"
  WordWrap("ab-cdef-ghi", 4)       --> "ab-,cdef-,ghi"
  WordWrap("abcedef", 0)           --> ""
  WordWrap("abcedef", 1)           --> "a,b,c,d,e,f,g"
  WordWrap("abcedef", 2)           --> "ab,cd,ef,g"
  WordWrap("abcedef", 3)           --> "abc,def,g"
  WordWrap("a ", 1)                --> "a " (not "a ,")

Use this function (VB5/6-compatible) to verify the correctness of your code.
Public Function WordWrap01( _
    ByRef Text As String, _
    ByVal Width As Long, _
    Optional ByRef CountLines As Long) As String
' by Donald, donald@xbeat.net, 20040913
  Dim i As Long
  Dim lenLine As Long
  Dim posBreak As Long
  Dim cntBreakChars As Long
  Dim abText() As Byte
  Dim abTextOut() As Byte
  Dim ubText As Long

  ' no fooling around
  If Width <= 0 Then
    CountLines = 0
    Exit Function
  End If
  If Len(Text) <= Width Then  ' no need to wrap
    CountLines = 1
    WordWrap01 = Text
    Exit Function
  End If
  abText = StrConv(Text, vbFromUnicode)
  ubText = UBound(abText)
  ReDim abTextOut(ubText * 3) 'dim to potential max
  For i = 0 To ubText
    Select Case abText(i)
    Case 32, 45 'space, hyphen
      posBreak = i
    Case Else
    End Select
    abTextOut(i + cntBreakChars) = abText(i)
    lenLine = lenLine + 1
    If lenLine > Width Then
      If posBreak > 0 Then
        ' don't break at the very end
        If posBreak = ubText Then Exit For
        ' wrap after space, hyphen
        abTextOut(posBreak + cntBreakChars + 1) = 13  'CR
        abTextOut(posBreak + cntBreakChars + 2) = 10  'LF
        i = posBreak
        posBreak = 0
        ' cut word
        abTextOut(i + cntBreakChars) = 13     'CR
        abTextOut(i + cntBreakChars + 1) = 10 'LF
        i = i - 1
      End If
      cntBreakChars = cntBreakChars + 2
      lenLine = 0
    End If
  CountLines = cntBreakChars \ 2 + 1
  ReDim Preserve abTextOut(ubText + cntBreakChars)
  WordWrap01 = StrConv(abTextOut, vbUnicode)
End Function
Author: by Marzo Junior, marzojr_NO~SPAM_@taskmail.com.br, 20041027
Doping: FastString TLB (cf. Dope'n'Declarations)
Code: Class-wrapped. The class is waiting for you here.
1Text = Replicate(5, "Many a mickle makes a muckle. ")
Width = 5
2Text = Replicate(5, "Many a mickle makes a muckle. ")
Width = 72
3Text = Replicate(50, "Many a mickle makes a muckle. ")
Width = 5
4Text = Replicate(50, "Many a mickle makes a muckle. ")
Width = 72
 VB5 Charts
WordWrap01 Donald  
WordWrap02 MarzoAPI,TLB 
Call 1
Call 2
Call 3
Call 4
 VB6 Charts
WordWrap01 Donald  
WordWrap02 MarzoAPI,TLB 
Call 1
Call 2
Call 3
Call 4
Notes & Conclusions
Got comments? How to read all those numbers


VBspeed © 2000-10 by Donald Lessau