Lesson 12 · String Manipulation

String Manipulation

Master Visual Basic 2026's comprehensive text-processing toolkit — concatenation, extraction (Left, Right, Mid), searching (InStr, Contains, IndexOf), transformation (UCase, LCase, Trim, Replace), splitting and joining, string interpolation, StringBuilder for performance, and .NET 10 improvements — with GitHub Copilot assistance throughout.

Key Takeaway: Strings in VB 2026 are immutable reference types — every operation creates a new string rather than modifying the original. For simple operations use the String class methods; for building strings in a loop use StringBuilder for much better performance. VB 2026 / .NET 10 adds string interpolation ($"…{expr}…") as the preferred way to build formatted strings, plus raw string literals and span-based methods for high-performance text processing.

12.1 String Concatenation

VB 2026 provides two concatenation operators: & and +. Always prefer & for string concatenation — it works safely with any data type by converting it to string first. The + operator performs addition when both operands are numeric, which can cause unexpected bugs.

Concatenation.vb — Visual Basic 2026
' ── & operator — safe, always concatenates ─────────────
Dim firstName As String = "Alice"
Dim lastName  As String = "Wong"
Dim fullName  = firstName & " " & lastName   ' "Alice Wong"

' ── + operator — risky with mixed types ────────────────
Dim result1 = "Score: " + 95.ToString()     ' ✔ OK — explicit ToString()
Dim result2 = "Value: " & 42               ' ✔ & converts 42 to "42" automatically

' ── String interpolation — the modern VB 2026 way ──────
Dim age   = 25
Dim score = 95
Dim gpa   = 3.85

lblInfo.Text = $"{firstName} {lastName} — Age: {age}, Score: {score}, GPA: {gpa:F2}"
' → "Alice Wong — Age: 25, Score: 95, GPA: 3.85"

' Interpolation with expressions and format specs
Dim price = 29.9D
lblPrice.Text = $"Total: {price * 1.06:C}"     ' currency format → "Total: RM31.65"
lblDate.Text  = $"Today: {DateTime.Today:dd/MM/yyyy}"

' ── += to append to existing string ────────────────────
Dim report As String = ""
report &= "Name: Alice" & vbCrLf
report &= "Score: 95"  & vbCrLf
txtReport.Text = report

12.2 Essential String Functions

📏 Length & Info
Len(s) / s.LengthLen("Hello") → 5
s.IsNullOrEmpty()IsNullOrEmpty("") → True
s.IsNullOrWhiteSpace()IsNullOrWhiteSpace(" ") → True
s.Chars(i)"Hello".Chars(1) → 'e'
✂ Extraction
Left(s, n)Left("Hello",3) → "Hel"
Right(s, n)Right("Hello",3) → "llo"
Mid(s, start, n)Mid("Hello",2,3) → "ell"
s.Substring(i, n)"Hello".Substring(1,3) → "ell"
🔍 Searching
InStr(s, find)InStr("Hello","ll") → 3
s.IndexOf(find)"Hello".IndexOf("l") → 2 (0-based)
s.Contains(sub)"Hello".Contains("ell") → True
s.StartsWith(p)"Hello".StartsWith("He") → True
s.EndsWith(p)"Hello".EndsWith("lo") → True
🔄 Transformation
UCase(s) / s.ToUpper()"hello" → "HELLO"
LCase(s) / s.ToLower()"HELLO" → "hello"
StrConv(s, ProperCase)"hello world" → "Hello World"
s.Replace(old, new)"cat".Replace("c","b") → "bat"
s.ToTitleCase().NET 10: "hello" → "Hello"
✂ Trim & Pad
Trim(s) / s.Trim()" hi " → "hi"
LTrim(s) / s.TrimStart()" hi " → "hi "
RTrim(s) / s.TrimEnd()" hi " → " hi"
s.PadLeft(n)"42".PadLeft(5) → " 42"
s.PadRight(n, char)"A".PadRight(4,'.')
🔀 Split & Join
s.Split(","c)"a,b,c".Split(",") → {"a","b","c"}
String.Join(sep, arr)Join("-",{"a","b"}) → "a-b"
s.Split(delims, opts)Remove empty entries
Environment.NewLinePlatform-safe line break

Important Difference: VB Functions vs .NET Methods

VB 2026 supports both the classic VB string functions (Left, Mid, InStr, Len) and .NET String methods (.Substring(), .IndexOf(), .Length). The key difference is indexing: VB functions use 1-based positions; .NET methods use 0-based positions.

VBvsNET.vb — Index comparison
Dim s = "Visual Basic 2026"

' ── VB functions — 1-based ─────────────────────────────
Dim vbLen   = Len(s)                  ' 17
Dim vbLeft  = Left(s, 6)             ' "Visual" (first 6 chars)
Dim vbRight = Right(s, 4)            ' "2026" (last 4 chars)
Dim vbMid   = Mid(s, 8, 5)           ' "Basic" (start at pos 8, take 5)
Dim vbFind  = InStr(s, "Basic")       ' 8 (1-based position)

' ── .NET String methods — 0-based ─────────────────────
Dim netLen    = s.Length              ' 17
Dim netLeft   = s.Substring(0, 6)    ' "Visual" (start 0, length 6)
Dim netRight  = s.Substring(s.Length - 4)   ' "2026"
Dim netMid    = s.Substring(7, 5)    ' "Basic" (0-based start = 7)
Dim netFind   = s.IndexOf("Basic")   ' 7 (0-based index)

' ── Consistency tip: pick one style and stick to it ────
' .NET methods work everywhere; VB functions need Imports Microsoft.VisualBasic
⚠ 1-Based vs 0-Based — The #1 String Bug

Mid("Hello", 1, 3) returns "Hel" (VB, starts at 1). "Hello".Substring(0, 3) also returns "Hel" (.NET, starts at 0). Mixing styles causes off-by-one errors. VB 2026 best practice: use .NET methods (.Substring(), .IndexOf()) for new code — they work everywhere including Blazor and MAUI. Use VB functions (Mid, InStr) only when working with legacy VB code.

Try It — Simulation 12.1: String Extraction Explorer

Type a string and use Left/Right/Mid/Substring to extract portions — the visualiser highlights exactly which characters are selected.

String Extraction Explorer
Input string (txtInput):
Function:
n / length:
start pos:

12.3 Searching Strings

StringSearch.vb — Visual Basic 2026
Dim email = "[email protected]"

' ── Contains / StartsWith / EndsWith ──────────────────
If email.Contains("@") Then
    lblResult.Text = "Valid email format"
End If

If email.EndsWith(".com") Then
    lblDomain.Text = "Commercial domain"
End If

' ── IndexOf — find position (0-based), -1 if not found ─
Dim atPos  = email.IndexOf("@")           ' 10
Dim dotPos = email.LastIndexOf(".")         ' 18 (last dot)

' Extract username and domain using IndexOf
If atPos > 0 Then
    Dim username = email.Substring(0, atPos)           ' "alice.wong"
    Dim domain   = email.Substring(atPos + 1)           ' "example.com"
    lblUser.Text   = $"User: {username}"
    lblDomain.Text = $"Domain: {domain}"
End If

' ── InStr — VB-style search (1-based, 0 if not found) ─
Dim pos = InStr(email, "@")              ' 11 (1-based)
If pos > 0 Then
    Dim user = Left(email, pos - 1)        ' "alice.wong"
End If

' ── Case-insensitive comparison ────────────────────────
If String.Compare(email, "[email protected]", True) = 0 Then
    ' Third arg True = ignore case
End If

' ── OrdinalIgnoreCase (most reliable for comparisons) ──
If email.Equals("[email protected]", StringComparison.OrdinalIgnoreCase) Then
    lblResult.Text = "Emails match (case-insensitive)"
End If

12.4 Transforming Strings

StringTransform.vb — Visual Basic 2026
Dim input = "  Hello, Visual Basic 2026!  "

' ── Case conversion ────────────────────────────────────
Dim upper  = input.ToUpper()           ' "  HELLO, VISUAL BASIC 2026!  "
Dim lower  = input.ToLower()           ' "  hello, visual basic 2026!  "
Dim proper = StrConv(input, VbStrConv.ProperCase)   ' "  Hello, Visual Basic 2026!  "

' ── Trim whitespace ────────────────────────────────────
Dim trimmed  = input.Trim()            ' "Hello, Visual Basic 2026!" (both ends)
Dim trimLeft = input.TrimStart()       ' removes leading spaces only
Dim trimEnd  = input.TrimEnd()         ' removes trailing spaces only
' Good practice: always Trim() user input from TextBoxes
Dim name = txtName.Text.Trim()

' ── Replace ────────────────────────────────────────────
Dim phone   = "012-345-6789"
Dim noHyphen = phone.Replace("-", "")   ' "0123456789" — remove all hyphens
Dim masked   = phone.Replace(phone.Substring(3, 3), "***")  ' mask middle digits

' ── PadLeft / PadRight ─────────────────────────────────
Dim id      = "42"
Dim padded  = id.PadLeft(6, "0"c)        ' "000042" — zero-pad to 6 digits
Dim padR    = "Alice".PadRight(12, "."c)  ' "Alice......." — table alignment

' ── Reverse a string (no built-in, use LINQ) ───────────
Dim rev = New String(input.Trim().Reverse().ToArray())
' → "!6202 cisaB lausiV ,olleH"
Try It — Simulation 12.2: String Transformer

Apply transformation functions to your text — case conversion, trim, replace, pad, and reverse.

String Transformer
Input string:
Find:
Replace with:
Total width:
Pad char:

12.5 Split and Join

Split() breaks a string into an array using a delimiter — perfect for parsing CSV data, user input lists, file paths, and email addresses. String.Join() does the reverse, assembling an array back into a single string with a separator.

SplitJoin.vb — Visual Basic 2026
' ── Split by single delimiter ──────────────────────────
Dim csv     = "Alice,Bob,Charlie,Diana,Eve"
Dim names() = csv.Split(","c)               ' {"Alice","Bob","Charlie","Diana","Eve"}

For Each name As String In names
    lstNames.Items.Add(name)
Next

' ── Split with multiple delimiters ────────────────────
Dim data    = "Name:Alice;Age:25;City:KL"
Dim pairs() = data.Split({";"c, ":"c})       ' {"Name","Alice","Age","25","City","KL"}

' ── Split with options — remove empty entries ──────────
Dim messy   = "one,,two,,,three"
Dim clean() = messy.Split({","c}, StringSplitOptions.RemoveEmptyEntries)
' {"one","two","three"} — empty parts removed

' ── Parse CSV line into structured data ────────────────
Dim record  = "STU001,Alice Wong,85,92,78"
Dim fields  = record.Split(","c)
Dim id      = fields(0)              ' "STU001"
Dim student = fields(1)             ' "Alice Wong"
Dim mark1   = CInt(fields(2))        ' 85

' ── Join — reverse of split ────────────────────────────
Dim parts() = {"Visual", "Basic", "2026"}
Dim joined  = String.Join(" ", parts)    ' "Visual Basic 2026"
Dim path    = String.Join("/", {"C:", "Users", "Alice", "Documents"})
' "C:/Users/Alice/Documents"

' ── Split path components ──────────────────────────────
Dim filePath  = "C:\Users\Alice\report.docx"
Dim pathParts = filePath.Split("\"c)
Dim fileName  = pathParts(pathParts.Length - 1)   ' "report.docx"
Try It — Simulation 12.3: Split & Join Lab

Enter a delimited string, choose a delimiter, split it apart — then re-join with a different separator.

Split & Join Lab
Input string:
Split delimiter:
Join with separator:

12.6 StringBuilder — High-Performance String Building

Because strings are immutable, every &= in a loop creates a new string object and copies all previous characters. For a loop of N iterations this is O(N²) work. StringBuilder uses a mutable internal buffer — appending is O(1) amortized. Use it whenever you build a string inside a loop.

StringBuilder.vb — Visual Basic 2026
Imports System.Text

' ── The SLOW way — creates thousands of string objects ─
Dim report As String = ""
For i = 1 To 1000
    report &= $"Line {i}: data{vbCrLf}"    ' ✘ slow — 1000 new string objects
Next

' ── The FAST way — StringBuilder with mutable buffer ───
Dim sb As New StringBuilder()
For i = 1 To 1000
    sb.AppendLine($"Line {i}: data")        ' ✔ fast — appends to internal buffer
Next
Dim result = sb.ToString()                  ' one string at the end

' ── StringBuilder methods ──────────────────────────────
Dim sb2 As New StringBuilder("Hello")
sb2.Append(", World")                       ' "Hello, World"
sb2.AppendLine("!")                          ' appends + newline
sb2.Insert(5, " Beautiful")                ' "Hello Beautiful, World\n!"
sb2.Replace("World", "VB 2026")            ' find/replace in buffer
sb2.Remove(0, 6)                            ' remove 6 chars from pos 0
Dim len = sb2.Length                          ' current length
sb2.Clear()                                   ' reset to empty

' ── Practical: generate HTML table ────────────────────
Dim html As New StringBuilder()
html.AppendLine("<table>")
For Each row As String In dataRows
    html.AppendLine($"  <tr><td>{row}</td></tr>")
Next
html.AppendLine("</table>")
txtOutput.Text = html.ToString()

12.7 New in VB 2026 / .NET 10

NewStringFeatures.vb — Visual Basic 2026 / .NET 10
' ── Raw string literals (multi-line, no escape needed) ─
Dim json = """
{
    "name": "Alice",
    "age": 25,
    "city": "Kuala Lumpur"
}
"""
' Triple quotes — no need to escape internal quotes

' ── String.Equals with OrdinalIgnoreCase ───────────────
Dim isMatch = "Hello".Equals("hello", StringComparison.OrdinalIgnoreCase)   ' True

' ── Span-based methods — zero-allocation parsing ───────
Dim line   = "Alice,25,KL".AsSpan()
Dim comma1 = line.IndexOf(","c)
Dim name   = line.Slice(0, comma1).ToString()   ' "Alice" — no string allocation

' ── String.Create — efficient string construction ──────
Dim id = String.Create(8, "user", Sub(span, prefix)
    prefix.CopyTo(span)
    "0001".CopyTo(span.Slice(prefix.Length))
End Sub)
' id = "user0001" — no intermediate strings

' ── SearchValues — fast multi-char scanning (.NET 10) ──
Dim digits   = System.Buffers.SearchValues.Create("0123456789")
Dim phone    = "Call 012-345-6789 now"
Dim firstNum = phone.AsSpan().IndexOfAny(digits)    ' 5 — first digit position

' ── String.IsNullOrWhiteSpace — essential input guard ──
If String.IsNullOrWhiteSpace(txtName.Text) Then
    lblError.Text = "Name is required"
    Return
End If
💡 VB 2026 String Best Practices
  • Always Trim() user input from TextBoxes before any processing
  • Use String.IsNullOrWhiteSpace() instead of = "" to guard against Nothing and whitespace-only input
  • Prefer string interpolation ($"…{expr}…") over & chains — more readable and slightly faster in .NET 10
  • Use StringBuilder when building strings in a loop with more than ~10 iterations
  • Use StringComparison.OrdinalIgnoreCase for case-insensitive comparisons — it is faster and culturally safe
  • Use & (not +) for string concatenation to avoid type confusion bugs
Try It — Simulation 12.4: Email and Name Parser

Parse an email address into components using IndexOf, Substring, and Split. Also parse a full name into first/last using string functions.

Email & Name Parser
Email Parser
Email address:
Name Formatter
Full name (first last):
Try It — Simulation 12.5: Complete String Analyser

Enter any text and get a full analysis — length, word count, character frequencies, InStr search, and palindrome detection.

String Analyser
Text to analyse:
Search for:

12.8 GitHub Copilot — String Assistance

GitHub Copilot — CSV Parser
You typed: ' Parse a CSV line "id,name,age,score" from txtCSV. Validate each field, then display in 4 Labels'
' Parse a CSV line "id,name,age,score" from txtCSV. Validate each field, then display in 4 Labels
Dim line   = txtCSV.Text.Trim()
Dim fields = line.Split(","c)

If fields.Length < 4 Then
    lblError.Text = $"⚠ Expected 4 fields, got {fields.Length}"
    Return
End If

Dim id    = fields(0).Trim()
Dim name  = fields(1).Trim()
Dim age   As Integer
Dim score As Double

If Not Integer.TryParse(fields(2).Trim(), age) Then
    lblError.Text = "⚠ Age must be a whole number."
    Return
End If
If Not Double.TryParse(fields(3).Trim(), score) Then
    lblError.Text = "⚠ Score must be a number."
    Return
End If

lblID.Text    = $"ID: {id}"
lblName.Text  = $"Name: {name}"
lblAge.Text   = $"Age: {age}"
lblScore.Text = $"Score: {score:F1}"
GitHub Copilot — Password Strength Checker
You typed: ' Check password strength: at least 8 chars, contains uppercase, lowercase, digit, and special char. Show strength as Weak/Fair/Strong/Very Strong'
' Check password strength: at least 8 chars, contains uppercase, lowercase, digit, and special char. Show strength as Weak/Fair/Strong/Very Strong
Dim pwd = txtPassword.Text

Dim hasUpper   = pwd.Any(Function(c) Char.IsUpper(c))
Dim hasLower   = pwd.Any(Function(c) Char.IsLower(c))
Dim hasDigit   = pwd.Any(Function(c) Char.IsDigit(c))
Dim hasSpecial = pwd.Any(Function(c) Not Char.IsLetterOrDigit(c))
Dim isLong     = pwd.Length >= 8

Dim score = ({isLong, hasUpper, hasLower, hasDigit, hasSpecial}).Count(Function(b) b)

Dim strength = Select Case score
    Case 0, 1  : "Weak"
    Case 2, 3  : "Fair"
    Case 4     : "Strong"
    Case Else   : "Very Strong"
End Select

lblStrength.Text = $"Strength: {strength} ({score}/5 criteria met)"
💡 Copilot Chat Prompts for This Lesson

Try these in the Copilot Chat panel while working with strings:

  • "Validate a Malaysian phone number format (012-345-6789) using Contains, StartsWith, and Length checks"
  • "Parse a full name 'firstname middlename lastname' and create initials like 'A.M.W.'"
  • "Build a word frequency counter for the text in a RichTextBox using Split and Dictionary(Of String, Integer)"
  • "Use StringBuilder to generate a formatted report of student marks with name, score, and grade columns"

📘 Lesson Summary

  • Use & (not +) for string concatenation — it safely converts any type to String automatically. Prefer string interpolation ($"…{expr}…") for readable, formatted strings.
  • VB functions (Left, Right, Mid, InStr) use 1-based positions. .NET methods (Substring, IndexOf) use 0-based positions — never mix the two styles in the same expression.
  • Contains(), StartsWith(), EndsWith() are the most readable search methods. Use IndexOf() when you need the actual position; it returns -1 if not found.
  • Always call .Trim() on user input from TextBoxes. Use String.IsNullOrWhiteSpace() as the guard check — it handles Nothing, empty string, and whitespace-only strings.
  • Split(","c) converts a delimited string to an array. String.Join(sep, array) reverses this. Use StringSplitOptions.RemoveEmptyEntries to clean up empty tokens.
  • Use StringBuilder in loops — it avoids creating N² string copies. Call .AppendLine(), .Insert(), .Replace(), and .ToString() at the end.
  • VB 2026 / .NET 10 adds raw string literals (triple-quoted, no escape needed), Span-based methods for zero-allocation parsing, and SearchValues for fast multi-character scanning.
  • For case-insensitive comparisons use StringComparison.OrdinalIgnoreCase — it is faster and avoids culture-specific bugs (e.g. Turkish lowercase İ).

Exercises

Exercise 12.1 — Text Processing App

  • Build a form with a multiline TextBox for input and a Label/TextBox area for output
  • Add buttons for: ToUpper, ToLower, ProperCase, Trim All Lines, Count Words, Count Characters (no spaces)
  • Add a Find/Replace section with two TextBoxes and a Replace button that uses .Replace()
  • Display word count by splitting on spaces and using StringSplitOptions.RemoveEmptyEntries
  • Copilot challenge: Ask Copilot to "add a character frequency table showing how many times each letter appears, sorted by frequency"

Exercise 12.2 — CSV Student Record Parser

  • Let the user paste a CSV line in the format: ID,Name,Math,Science,English
  • Use Split(","c) to parse the fields. Validate each field with TryParse where appropriate
  • Calculate the average mark and display a formatted report using string interpolation
  • Use PadRight() on the name column and PadLeft() on number columns for table alignment
  • Copilot challenge: Ask Copilot to "let the user paste multiple CSV lines and process them all into a ListBox report"

Exercise 12.3 — Password Strength Meter

  • Build a password input TextBox that checks strength in real-time as the user types
  • Check for: Length ≥ 8, Has uppercase, Has lowercase, Has digit, Has special character
  • Show a coloured ProgressBar or label: Weak (red), Fair (orange), Strong (yellow), Very Strong (green)
  • Use Char.IsUpper(), Char.IsLower(), Char.IsDigit(), and Char.IsLetterOrDigit()
  • Copilot challenge: Ask Copilot to "add a 'Show/Hide password' CheckBox that toggles between PasswordChar = '*' and empty"

Next: Lesson 13 — If..Then..Else

Learn to control program flow with conditional logic — If..Then, If..Then..Else, ElseIf chains, nested conditions, and the ternary If() operator in Visual Basic 2026.

Continue ❯

Related Resources


Featured Books

Visual Basic 2022 Made Easy

Visual Basic 2022 Made Easy

by Dr. Liew Voon Kiong

Comprehensive coverage of string manipulation functions with step-by-step text-processing projects and practical applications.

View on Amazon →
VB Programming With Code Examples

VB Programming With Code Examples

by Dr. Liew Voon Kiong

48 fully-explained VB.NET programs including text editors, CSV parsers, and string-intensive data processing applications.

View on Amazon →