vb6parse 1.0.0

vb6parse is a library for parsing and analyzing VB6 code, from projects, to controls, to modules, and forms.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="VB6Parse Library Reference - mid - String">
    <title>mid - String - VB6Parse Library Reference</title>
    <link rel="stylesheet" href="../../../assets/css/style.css">
    <link rel="stylesheet" href="../../../assets/css/docs-style.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github-dark.min.css">
    <script src="../../../assets/js/theme-switcher.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/vbnet.min.js"></script>
    <script>hljs.highlightAll();</script>
</head>
<body>
    <header class="docs-header">
        <div class="container">
            <h1><a href="../../../index.html">VB6Parse</a> / <a href="../../../library/index.html">Library</a> / <a href="../../../library/functions/string/index.html">String</a> / mid</h1>
            <p class="tagline">VB6 Library Reference</p>
        </div>
    </header>

    <nav class="docs-nav">
        <div class="container">
            <a href="../../../index.html">Home</a>
            <a href="../../../library/index.html">Library Reference</a>
            <a href="../../../documentation.html">Documentation</a>
            <a href="https://docs.rs/vb6parse" target="_blank">API Docs</a>
            <a href="https://github.com/scriptandcompile/vb6parse" target="_blank">GitHub</a>
            <button id="theme-toggle" class="theme-toggle" aria-label="Toggle theme">
                <span class="theme-icon">🌙</span>
            </button>
        </div>
    </nav>

    <main class="container">
        
        <article class="library-item">
            <h1 id="mid-function">Mid Function</h1>
<p>Returns a Variant (String) containing a specified number of characters from a string.</p>
<h2 id="syntax">Syntax</h2>
<pre><code class="language-vbnet">Mid(string, start, [length])</code></pre>
<h2 id="parameters">Parameters</h2>
<ul>
<li><code>string</code> (Required): String expression from which characters are returned</li>
<li>Can be any valid string expression</li>
<li>If Null, returns Null</li>
<li>If empty string, returns empty string</li>
<li><code>start</code> (Required): Long. Character position in string where the desired part begins</li>
<li>Uses 1-based indexing (first character is position 1)</li>
<li>If start &gt; Len(string), returns empty string</li>
<li>If start &lt; 1, error 5 (Invalid procedure call or argument)</li>
<li><code>length</code> (Optional): Long. Number of characters to return</li>
<li>If omitted or &gt; characters available, returns all characters from start to end</li>
<li>If length &lt; 0, error 5 (Invalid procedure call or argument)</li>
<li>If length = 0, returns empty string</li>
</ul>
<h2 id="return-value">Return Value</h2>
<p>Returns a Variant (String):
- Substring of specified length starting at start position
- Uses 1-based indexing (first character is 1, not 0)
- Returns empty string if start &gt; string length
- Returns remaining characters if length extends past end of string
- Returns Null if input string is Null
- Returns empty string if input string is empty
- Returns empty string if length = 0</p>
<h2 id="remarks">Remarks</h2>
<p>The Mid function extracts a substring:
- <strong>1-based indexing</strong>: First character is at position 1 (not 0 like in many languages)
- <strong>Optional length</strong>: If omitted, returns from start to end of string
- <strong>Bounds handling</strong>: If start or length exceed string bounds, adjusts gracefully
- <strong>No error on overflow</strong>: Returns available characters without error
- <strong>Null propagation</strong>: Returns Null if input is Null
- <strong>Common use</strong>: Extract portions of strings, parse data, substring operations
- <strong>Related statement</strong>: Mid statement assigns to substring (Mid(s, 1, 3) = "abc")
- <strong>Similar to</strong>: Left (from start), Right (from end), <code>InStr</code> (find position)
- <strong>Performance</strong>: Fast operation, optimized in VB6
- <strong>String immutability</strong>: Returns new string, does not modify original
- <strong>Unicode support</strong>: Works with Unicode strings in VB6
- <strong>Type conversion</strong>: Automatically converts numeric strings
- <strong>Available in</strong>: All VB versions, VBA, <code>VBScript</code></p>
<h2 id="typical-uses">Typical Uses</h2>
<ol>
<li><strong>Extract Substring</strong></li>
</ol>
<pre><code class="language-vbnet">   middle = Mid(&quot;Hello World&quot;, 7, 5)  &#x27; Returns &quot;World&quot;
   ```
2. **Parse Fixed-Width Data**
   ```vb
   customerID = Mid(record, 1, 10)
   customerName = Mid(record, 11, 30)
   ```
3. **Extract from Position to End**
   ```vb
   remainder = Mid(text, 5)  &#x27; From position 5 to end
   ```
4. **Parse Delimited Data**
   ```vb
   pos = InStr(data, &quot;,&quot;)
   firstField = Mid(data, 1, pos - 1)
   ```
5. **Skip Characters**
   ```vb
   withoutPrefix = Mid(text, 4)  &#x27; Skip first 3 characters
   ```
6. **Extract Single Character**
   ```vb
   char = Mid(text, i, 1)  &#x27; Get character at position i
   ```
7. **Data Validation**
   ```vb
   areaCode = Mid(phoneNumber, 2, 3)  &#x27; Extract area code
   ```
8. **String Manipulation**
   ```vb
   modified = Left(s, 5) &amp; &quot;***&quot; &amp; Mid(s, 9)  &#x27; Mask middle
   ```
## Basic Examples
### Example 1: Basic Usage</code></pre>
<p>vb
Dim result As String
Dim text As String
text = "Hello World"
' Extract with length
result = Mid(text, 1, 5)   ' Returns "Hello"
result = Mid(text, 7, 5)   ' Returns "World"
result = Mid(text, 3, 3)   ' Returns "llo"
' Extract to end (no length parameter)
result = Mid(text, 7)      ' Returns "World"
result = Mid(text, 1)      ' Returns "Hello World"
' Edge cases
result = Mid(text, 20)     ' Returns "" (start past end)
result = Mid(text, 7, 100) ' Returns "World" (length past end)
result = Mid(text, 5, 0)   ' Returns "" (zero length)</p>
<pre><code>### Example 2: Parse Fixed-Width Record</code></pre>
<p>vb
Sub ParseFixedWidthRecord()
    Dim record As String
    Dim customerID As String
    Dim customerName As String
    Dim city As String
    Dim state As String
    Dim zipCode As String
    ' Example: "CUST001   John Smith            New York    NY12345"
    record = "CUST001   John Smith            New York    NY12345"
    ' Parse fixed-width fields
    customerID = RTrim(Mid(record, 1, 10))     ' Positions 1-10
    customerName = RTrim(Mid(record, 11, 22))  ' Positions 11-32
    city = RTrim(Mid(record, 33, 12))          ' Positions 33-44
    state = Mid(record, 45, 2)                  ' Positions 45-46
    zipCode = Mid(record, 47, 5)                ' Positions 47-51
    Debug.Print "ID: " &amp; customerID
    Debug.Print "Name: " &amp; customerName
    Debug.Print "City: " &amp; city
    Debug.Print "State: " &amp; state
    Debug.Print "Zip: " &amp; zipCode
End Sub</p>
<pre><code>### Example 3: Extract File Extension</code></pre>
<p>vb
Function GetFileExtension(ByVal filename As String) As String
    Dim dotPos As Long
    ' Find last dot
    dotPos = InStrRev(filename, ".")
    If dotPos &gt; 0 Then
        ' Extract extension (without dot)
        GetFileExtension = Mid(filename, dotPos + 1)
    Else
        GetFileExtension = ""
    End If
End Function
' Usage:
' ext = GetFileExtension("document.txt")      ' Returns "txt"
' ext = GetFileExtension("photo.jpg")         ' Returns "jpg"
' ext = GetFileExtension("archive.tar.gz")    ' Returns "gz"
' ext = GetFileExtension("README")            ' Returns ""</p>
<pre><code>### Example 4: Parse Delimited String</code></pre>
<p>vb
Sub ParseCSVLine(ByVal line As String)
    Dim pos1 As Long, pos2 As Long
    Dim field1 As String, field2 As String, field3 As String
    ' Parse: "Smith,John,123 Main St"
    ' Find first comma
    pos1 = InStr(line, ",")
    If pos1 &gt; 0 Then
        field1 = Mid(line, 1, pos1 - 1)
        ' Find second comma
        pos2 = InStr(pos1 + 1, line, ",")
        If pos2 &gt; 0 Then
            field2 = Mid(line, pos1 + 1, pos2 - pos1 - 1)
            field3 = Mid(line, pos2 + 1)  ' Rest of string
        Else
            field2 = Mid(line, pos1 + 1)  ' No third field
            field3 = ""
        End If
    Else
        field1 = line
        field2 = ""
        field3 = ""
    End If
    Debug.Print "Last Name: " &amp; field1
    Debug.Print "First Name: " &amp; field2
    Debug.Print "Address: " &amp; field3
End Sub</p>
<pre><code>## Common Patterns
### Pattern 1: `SafeMid` (handle Null)</code></pre>
<p>vb
Function SafeMid(ByVal text As Variant, _
                 ByVal start As Long, _
                 Optional ByVal length As Long = -1) As String
    If IsNull(text) Then
        SafeMid = ""
    ElseIf length = -1 Then
        SafeMid = Mid(text, start)
    Else
        SafeMid = Mid(text, start, length)
    End If
End Function</p>
<pre><code>### Pattern 2: `GetChar` (extract single character)</code></pre>
<p>vb
Function GetChar(ByVal text As String, ByVal position As Long) As String
    If position &gt;= 1 And position &lt;= Len(text) Then
        GetChar = Mid(text, position, 1)
    Else
        GetChar = ""
    End If
End Function</p>
<pre><code>### Pattern 3: `SkipChars` (remove prefix)</code></pre>
<p>vb
Function SkipChars(ByVal text As String, ByVal count As Long) As String
    If count &gt;= Len(text) Then
        SkipChars = ""
    ElseIf count &lt;= 0 Then
        SkipChars = text
    Else
        SkipChars = Mid(text, count + 1)
    End If
End Function</p>
<pre><code>### Pattern 4: `ExtractBetween`</code></pre>
<p>vb
Function ExtractBetween(ByVal text As String, _
                        ByVal startPos As Long, _
                        ByVal endPos As Long) As String
    If endPos &gt;= startPos And startPos &gt;= 1 Then
        ExtractBetween = Mid(text, startPos, endPos - startPos + 1)
    Else
        ExtractBetween = ""
    End If
End Function</p>
<pre><code>### Pattern 5: `MaskMiddle` (hide sensitive data)</code></pre>
<p>vb
Function MaskMiddle(ByVal text As String, _
                    ByVal visibleStart As Long, _
                    ByVal visibleEnd As Long) As String
    Dim textLen As Long
    textLen = Len(text)
    If textLen &lt;= visibleStart + visibleEnd Then
        MaskMiddle = text
    Else
        MaskMiddle = Left(text, visibleStart) &amp; _
                    String(textLen - visibleStart - visibleEnd, "*") &amp; _
                    Right(text, visibleEnd)
    End If
End Function</p>
<pre><code>### Pattern 6: `ParseFixedField`</code></pre>
<p>vb
Function ParseFixedField(ByVal record As String, _
                        ByVal startPos As Long, _
                        ByVal fieldWidth As Long) As String
    ParseFixedField = RTrim(Mid(record, startPos, fieldWidth))
End Function</p>
<pre><code>### Pattern 7: `GetSubstringAfter`</code></pre>
<p>vb
Function GetSubstringAfter(ByVal text As String, _
                          ByVal delimiter As String) As String
    Dim pos As Long
    pos = InStr(text, delimiter)
    If pos &gt; 0 Then
        GetSubstringAfter = Mid(text, pos + Len(delimiter))
    Else
        GetSubstringAfter = ""
    End If
End Function</p>
<pre><code>### Pattern 8: `GetSubstringBefore`</code></pre>
<p>vb
Function GetSubstringBefore(ByVal text As String, _
                           ByVal delimiter As String) As String
    Dim pos As Long
    pos = InStr(text, delimiter)
    If pos &gt; 0 Then
        GetSubstringBefore = Mid(text, 1, pos - 1)
    Else
        GetSubstringBefore = text
    End If
End Function</p>
<pre><code>### Pattern 9: `ReplaceMiddle`</code></pre>
<p>vb
Function ReplaceMiddle(ByVal text As String, _
                      ByVal start As Long, _
                      ByVal length As Long, _
                      ByVal replacement As String) As String
    ReplaceMiddle = Left(text, start - 1) &amp; _
                   replacement &amp; _
                   Mid(text, start + length)
End Function</p>
<pre><code>### Pattern 10: `ExtractWord`</code></pre>
<p>vb
Function ExtractWord(ByVal text As String, ByVal wordNum As Long) As String
    Dim words() As String
    words = Split(Trim(text))
    If wordNum &gt;= 1 And wordNum &lt;= UBound(words) + 1 Then
        ExtractWord = words(wordNum - 1)
    Else
        ExtractWord = ""
    End If
End Function</p>
<pre><code>## Advanced Examples
### Example 1: Fixed-Width File Parser</code></pre>
<p>vb
' Class: FixedWidthParser
Private Type FieldDefinition
    Name As String
    StartPos As Long
    Length As Long
    TrimSpaces As Boolean
End Type
Private m_fields() As FieldDefinition
Private m_fieldCount As Long
Public Sub AddField(ByVal name As String, _
                    ByVal startPos As Long, _
                    ByVal length As Long, _
                    Optional ByVal trimSpaces As Boolean = True)
    m_fieldCount = m_fieldCount + 1
    ReDim Preserve m_fields(1 To m_fieldCount)
    With m_fields(m_fieldCount)
        .Name = name
        .StartPos = startPos
        .Length = length
        .TrimSpaces = trimSpaces
    End With
End Sub
Public Function ParseRecord(ByVal record As String) As Collection
    Dim result As New Collection
    Dim i As Long
    Dim value As String
    For i = 1 To m_fieldCount
        With m_fields(i)
            value = Mid(record, .StartPos, .Length)
            If .TrimSpaces Then
                value = Trim(value)
            End If
            result.Add value, .Name
        End With
    Next i
    Set ParseRecord = result
End Function
Public Sub ParseFile(ByVal filename As String, _
                    ByVal outputCollection As Collection)
    Dim fileNum As Integer
    Dim line As String
    Dim recordData As Collection
    fileNum = FreeFile
    Open filename For Input As #fileNum
    Do While Not EOF(fileNum)
        Line Input #fileNum, line
        Set recordData = ParseRecord(line)
        outputCollection.Add recordData
    Loop
    Close #fileNum
End Sub</p>
<pre><code>### Example 2: String Tokenizer</code></pre>
<p>vb
' Class: StringTokenizer
Private m_text As String
Private m_position As Long
Private m_length As Long
Public Sub Initialize(ByVal text As String)
    m_text = text
    m_position = 1
    m_length = Len(text)
End Sub
Public Function HasMoreTokens() As Boolean
    HasMoreTokens = (m_position &lt;= m_length)
End Function
Public Function NextToken(ByVal delimiter As String) As String
    Dim delimPos As Long
    Dim token As String
    If m_position &gt; m_length Then
        NextToken = ""
        Exit Function
    End If
    ' Find next delimiter
    delimPos = InStr(m_position, m_text, delimiter)
    If delimPos = 0 Then
        ' No more delimiters, return rest of string
        token = Mid(m_text, m_position)
        m_position = m_length + 1
    Else
        ' Extract token
        token = Mid(m_text, m_position, delimPos - m_position)
        m_position = delimPos + Len(delimiter)
    End If
    NextToken = token
End Function
Public Function PeekToken(ByVal delimiter As String) As String
    Dim savedPos As Long
    savedPos = m_position
    PeekToken = NextToken(delimiter)
    m_position = savedPos
End Function
Public Sub Reset()
    m_position = 1
End Sub
Public Property Get Position() As Long
    Position = m_position
End Property
Public Property Let Position(ByVal newPos As Long)
    If newPos &gt;= 1 And newPos &lt;= m_length + 1 Then
        m_position = newPos
    End If
End Property</p>
<pre><code>### Example 3: String Masking Utility</code></pre>
<p>vb
' Module: StringMasking
Public Function MaskCreditCard(ByVal cardNumber As String) As String
    ' Show last 4 digits: <strong><em>* </em></strong><em> </em><strong><em> 1234
    Dim cleaned As String
    cleaned = Replace(cardNumber, " ", "")
    cleaned = Replace(cleaned, "-", "")
    If Len(cleaned) &gt;= 4 Then
        MaskCreditCard = String(Len(cleaned) - 4, "</em>") &amp; Mid(cleaned, Len(cleaned) - 3)
    Else
        MaskCreditCard = String(Len(cleaned), "*")
    End If
End Function
Public Function MaskSSN(ByVal ssn As String) As String
    ' Show last 4 digits: </strong><em>-</em><em>-1234
    Dim cleaned As String
    cleaned = Replace(ssn, "-", "")
    If Len(cleaned) = 9 Then
        MaskSSN = "</em><strong>-</strong>-" &amp; Mid(cleaned, 6)
    Else
        MaskSSN = String(Len(ssn), "<em>")
    End If
End Function
Public Function MaskEmail(ByVal email As String) As String
    ' Show first 2 chars and domain: jo</em><strong><em>@example.com
    Dim atPos As Long
    Dim localPart As String
    Dim domainPart As String
    atPos = InStr(email, "@")
    If atPos &gt; 2 Then
        localPart = Mid(email, 1, 2) &amp; String(atPos - 3, "</em>")
        domainPart = Mid(email, atPos)
        MaskEmail = localPart &amp; domainPart
    Else
        MaskEmail = String(Len(email), "*")
    End If
End Function
Public Function MaskPhone(ByVal phoneNumber As String) As String
    ' Show area code and last 2: (123) </strong><em>-</em><em>34
    Dim cleaned As String
    cleaned = Replace(phoneNumber, "(", "")
    cleaned = Replace(cleaned, ")", "")
    cleaned = Replace(cleaned, " ", "")
    cleaned = Replace(cleaned, "-", "")
    If Len(cleaned) = 10 Then
        MaskPhone = "(" &amp; Mid(cleaned, 1, 3) &amp; ") </em><strong>-</strong>" &amp; Mid(cleaned, 9)
    Else
        MaskPhone = String(Len(phoneNumber), "*")
    End If
End Function</p>
<pre><code>### Example 4: CSV Parser with Quoted Fields</code></pre>
<p>vb
' Module: CSVParser
Public Function ParseCSVLine(ByVal line As String) As Variant
    Dim fields() As String
    Dim fieldCount As Long
    Dim position As Long
    Dim length As Long
    Dim inQuote As Boolean
    Dim currentField As String
    Dim ch As String
    length = Len(line)
    position = 1
    fieldCount = 0
    inQuote = False
    currentField = ""
    Do While position &lt;= length
        ch = Mid(line, position, 1)
        Select Case ch
            Case """"  ' Quote
                If inQuote Then
                    ' Check for escaped quote
                    If position &lt; length Then
                        If Mid(line, position + 1, 1) = """" Then
                            currentField = currentField &amp; """"
                            position = position + 1
                        Else
                            inQuote = False
                        End If
                    Else
                        inQuote = False
                    End If
                Else
                    inQuote = True
                End If
            Case ","
                If inQuote Then
                    currentField = currentField &amp; ch
                Else
                    ' End of field
                    fieldCount = fieldCount + 1
                    ReDim Preserve fields(1 To fieldCount)
                    fields(fieldCount) = currentField
                    currentField = ""
                End If
            Case Else
                currentField = currentField &amp; ch
        End Select
        position = position + 1
    Loop
    ' Add last field
    fieldCount = fieldCount + 1
    ReDim Preserve fields(1 To fieldCount)
    fields(fieldCount) = currentField
    ParseCSVLine = fields
End Function
Public Function GetCSVField(ByVal line As String, _
                           ByVal fieldIndex As Long) As String
    Dim fields As Variant
    fields = ParseCSVLine(line)
    If fieldIndex &gt;= LBound(fields) And fieldIndex &lt;= UBound(fields) Then
        GetCSVField = fields(fieldIndex)
    Else
        GetCSVField = ""
    End If
End Function</p>
<pre><code>## Error Handling</code></pre>
<p>vb
' Error 5: Invalid procedure call or argument
' - start &lt; 1
' - length &lt; 0
' Safe extraction with error handling
Function SafeExtract(ByVal text As String, _
                    ByVal start As Long, _
                    ByVal length As Long) As String
    On Error GoTo ErrorHandler
    If IsNull(text) Then
        SafeExtract = ""
    ElseIf start &lt; 1 Or length &lt; 0 Then
        SafeExtract = ""
    ElseIf start &gt; Len(text) Then
        SafeExtract = ""
    Else
        SafeExtract = Mid(text, start, length)
    End If
    Exit Function
ErrorHandler:
    SafeExtract = ""
End Function
' Handle Null values
Function MidSafe(ByVal text As Variant, _
                 ByVal start As Long, _
                 Optional ByVal length As Variant = Empty) As String
    If IsNull(text) Then
        MidSafe = ""
    ElseIf IsEmpty(length) Then
        MidSafe = Mid(text, start)
    Else
        MidSafe = Mid(text, start, length)
    End If
End Function</p>
<pre><code>## Performance Considerations
- **Fast Operation**: String extraction is highly optimized in VB6
- **Creates New String**: Does not modify original (immutable)
- **Avoid in Tight Loops**: Cache result if using multiple times
- **Better than**: Repeated Left/Right operations for complex parsing
- **Consider Split**: For delimited data, Split may be faster
- **String Builder**: For concatenating many Mid results, use `StringBuilder` pattern
## Best Practices
1. **Remember 1-based indexing** - First character is position 1, not 0
2. **Validate inputs** - Check start and length before calling Mid
3. **Handle Null gracefully** - Use `IsNull` check for Variant inputs
4. **Omit length when extracting to end** - More readable: Mid(s, 5) vs Mid(s, 5, Len(s)-4)
5. **Combine with Trim** - Clean whitespace from extracted fields
6. **Use with `InStr`** - Find position, then extract with Mid
7. **Cache Len results** - If using Len(string) multiple times
8. **Document field positions** - For fixed-width parsing, use constants
9. **Test edge cases** - Empty strings, start past end, Null values
10. **Consider alternatives** - Split for delimited data, Left/Right for ends
## Comparison with Related Functions
| Function | Extracts From | Parameters | Use Case |
|----------|--------------|------------|----------|
| **Mid** | Any position | ```(string, start, [length])``` | General substring extraction |
| **Left** | Beginning | ```(string, length)``` | Get first N characters |
| **Right** | End | ```(string, length)``` | Get last N characters |
| **`InStr`** | N/A (finds) | ```[start,] string1, string2``` | Find position of substring |
## Mid vs Left vs Right</code></pre>
<p>vb
Dim text As String
text = "Hello World"
' Mid - extract from any position
Debug.Print Mid(text, 7, 5)    ' "World" (position 7, length 5)
Debug.Print Mid(text, 3, 3)    ' "llo" (position 3, length 3)
Debug.Print Mid(text, 7)       ' "World" (from position 7 to end)
' Left - extract from beginning
Debug.Print Left(text, 5)      ' "Hello" (first 5 characters)
' Right - extract from end
Debug.Print Right(text, 5)     ' "World" (last 5 characters)
' Equivalent operations
Debug.Print Mid(text, 1, 5)    ' "Hello" (same as Left(text, 5))
Debug.Print Mid(text, 7)       ' "World" (same as Right(text, 5))</p>
<pre><code>## Mid Function vs Mid Statement</code></pre>
<p>vb
Dim text As String
text = "Hello World"
' Mid Function - returns substring (does not modify)
Dim result As String
result = Mid(text, 1, 5)       ' result = "Hello", text unchanged
' Mid Statement - modifies string in place
Mid(text, 1, 5) = "Goodbye"    ' text = "GoodbyWorld" (replaces 5 chars)
Mid(text, 7, 5) = "Earth"      ' text = "Hello Earth" (replaces 5 chars)
' Note: Mid statement exists but is less commonly used
' Mid function is much more common for extraction</p>
<pre><code>## 1-Based vs 0-Based Indexing</code></pre>
<p>vb
' VB6 Mid uses 1-based indexing
Dim text As String
text = "ABCDE"
Debug.Print Mid(text, 1, 1)    ' "A" (first character is position 1)
Debug.Print Mid(text, 2, 1)    ' "B" (second character is position 2)
Debug.Print Mid(text, 5, 1)    ' "E" (fifth character is position 5)
' Compare to 0-based languages (JavaScript, C#, etc.)
' text[0]   // "A" (first character is index 0)
' text[1]   // "B" (second character is index 1)
' text[4]   // "E" (fifth character is index 4)
' When converting between languages:
' VB6: Mid(text, n, 1)
' C#:  text[n-1]
```</p>
<h2 id="platform-notes">Platform Notes</h2>
<ul>
<li>Available in all VB6 versions</li>
<li>Part of VBA core library</li>
<li>Available in <code>VBScript</code></li>
<li>Works with ANSI and Unicode strings</li>
<li><strong>1-based indexing</strong> (first character is 1)</li>
<li>Returns new string (original unchanged)</li>
<li>Handles Null by returning Null</li>
<li>No error if start or length exceed bounds (adjusts gracefully)</li>
<li>Same behavior across all Windows versions</li>
</ul>
<h2 id="limitations">Limitations</h2>
<ul>
<li><strong>1-based indexing</strong>: Not 0-based like most modern languages</li>
<li><strong>Creates new string</strong>: Cannot modify string in place (use Mid statement for that)</li>
<li><strong>No negative indices</strong>: Cannot count from end like Python</li>
<li><strong>No regex support</strong>: For pattern matching, use <code>RegExp</code> object</li>
<li><strong>Error on invalid start</strong>: start &lt; 1 causes error 5</li>
<li><strong>Error on negative length</strong>: length &lt; 0 causes error 5</li>
</ul>
<h2 id="related-functions">Related Functions</h2>
<ul>
<li><code>Left</code>: Returns leftmost characters from string</li>
<li><code>Right</code>: Returns rightmost characters from string</li>
<li><code>InStr</code>: Finds position of substring</li>
<li><code>InStrRev</code>: Finds position of substring from end</li>
<li><code>Len</code>: Returns string length</li>
<li><code>LTrim</code>/<code>RTrim</code>/<code>Trim</code>: Removes spaces</li>
<li><code>Split</code>: Splits string into array</li>
<li><code>Replace</code>: Replaces substring occurrences</li>
<li><code>Mid</code> statement: Replaces characters within string</li>
</ul>
        </article>
        
        <div style="margin-top: 3rem; padding-top: 2rem; border-top: 1px solid var(--border-color);">
            <p>
                <a href="index.html">← Back to String</a> |
                <a href="../index.html">View all functions</a>
            </p>
        </div>

    </main>

    <footer>
        <div class="container">
            <p>&copy; 2024-2026 VB6Parse Contributors. Licensed under the MIT License.</p>
        </div>
    </footer>
</body>
</html>