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
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
//! # Right Function
//!
//! Returns a String containing a specified number of characters from the right side of a string.
//!
//! ## Syntax
//!
//! ```vb
//! Right(string, length)
//! ```
//!
//! ## Parameters
//!
//! - `string` - Required. String expression from which the rightmost characters are returned.
//! - `length` - Required. Long indicating how many characters to return. If 0, a zero-length string ("") is returned. If greater than or equal to the number of characters in `string`, the entire string is returned.
//!
//! ## Return Value
//!
//! Returns a `String` containing the specified number of characters from the right side of the string.
//!
//! ## Remarks
//!
//! The `Right` function extracts a substring from the end of a string. It is commonly used for:
//! - Extracting file extensions
//! - Getting the last N characters of a string
//! - Parsing fixed-width data from the right
//! - Removing prefixes or extracting suffixes
//!
//! **Important Notes**:
//! - If `length` is 0, an empty string ("") is returned
//! - If `length` >= Len(string), the entire string is returned
//! - If `string` is Null, Right returns Null
//! - If `length` is negative, a runtime error occurs (Error 5: Invalid procedure call or argument)
//! - The function is 1-based (counts from position 1, not 0)
//!
//! **Behavior with Different Length Values**:
//!
//! | Length Value | Result |
//! |--------------|--------|
//! | 0 | Empty string ("") |
//! | 1 to Len(string) | Rightmost N characters |
//! | > Len(string) | Entire string |
//! | Negative | Runtime error (Error 5) |
//!
//! ## Typical Uses
//!
//! 1. **File Extensions**: Extract file extension from filename
//! 2. **Data Parsing**: Extract rightmost fields from fixed-width data
//! 3. **String Validation**: Check string endings/suffixes
//! 4. **Number Formatting**: Get last digits of numbers
//! 5. **Path Manipulation**: Extract filename from path
//! 6. **Text Processing**: Remove prefixes, keep suffixes
//! 7. **Data Extraction**: Get trailing characters from codes/IDs
//! 8. **String Truncation**: Keep only the rightmost portion
//!
//! ## Basic Examples
//!
//! ### Example 1: Extract File Extension
//! ```vb
//! Dim filename As String
//! Dim extension As String
//!
//! filename = "document.txt"
//! extension = Right(filename, 4) ' Returns ".txt"
//! ```
//!
//! ### Example 2: Get Last N Characters
//! ```vb
//! Dim accountNumber As String
//! Dim lastFour As String
//!
//! accountNumber = "1234567890"
//! lastFour = Right(accountNumber, 4) ' Returns "7890"
//! ```
//!
//! ### Example 3: Check String Ending
//! ```vb
//! Dim filename As String
//!
//! filename = "report.pdf"
//! If Right(filename, 4) = ".pdf" Then
//! MsgBox "This is a PDF file"
//! End If
//! ```
//!
//! ### Example 4: Extract from Fixed-Width Data
//! ```vb
//! Dim record As String
//! Dim zipCode As String
//!
//! record = "John Doe New York 10001"
//! zipCode = Right(record, 5) ' Returns "10001"
//! ```
//!
//! ## Common Patterns
//!
//! ### Pattern 1: `GetFileExtension`
//! ```vb
//! Function GetFileExtension(filename As String) As String
//! ' Extract file extension including the dot
//! Dim dotPos As Integer
//!
//! dotPos = InStrRev(filename, ".")
//!
//! If dotPos > 0 Then
//! GetFileExtension = Right(filename, Len(filename) - dotPos + 1)
//! Else
//! GetFileExtension = ""
//! End If
//! End Function
//! ```
//!
//! ### Pattern 2: `GetLastNChars`
//! ```vb
//! Function GetLastNChars(text As String, n As Long) As String
//! ' Safely get last N characters (won't error if string is too short)
//! If n <= 0 Then
//! GetLastNChars = ""
//! ElseIf n >= Len(text) Then
//! GetLastNChars = text
//! Else
//! GetLastNChars = Right(text, n)
//! End If
//! End Function
//! ```
//!
//! ### Pattern 3: `EndsWithString`
//! ```vb
//! Function EndsWithString(text As String, suffix As String, _
//! Optional caseSensitive As Boolean = True) As Boolean
//! ' Check if string ends with a specific suffix
//! Dim textEnd As String
//! Dim suffixLen As Long
//!
//! suffixLen = Len(suffix)
//!
//! If suffixLen > Len(text) Then
//! EndsWithString = False
//! Exit Function
//! End If
//!
//! textEnd = Right(text, suffixLen)
//!
//! If caseSensitive Then
//! EndsWithString = (textEnd = suffix)
//! Else
//! EndsWithString = (UCase(textEnd) = UCase(suffix))
//! End If
//! End Function
//! ```
//!
//! ### Pattern 4: `RemovePrefix`
//! ```vb
//! Function RemovePrefix(text As String, prefixLen As Long) As String
//! ' Remove prefix by keeping rightmost characters
//! If prefixLen >= Len(text) Then
//! RemovePrefix = ""
//! Else
//! RemovePrefix = Right(text, Len(text) - prefixLen)
//! End If
//! End Function
//! ```
//!
//! ### Pattern 5: `PadLeftToLength`
//! ```vb
//! Function PadLeftToLength(text As String, totalLength As Long, _
//! Optional padChar As String = " ") As String
//! ' Pad string on the left to reach desired length
//! Dim currentLen As Long
//! Dim padding As String
//!
//! currentLen = Len(text)
//!
//! If currentLen >= totalLength Then
//! PadLeftToLength = Right(text, totalLength)
//! Else
//! padding = String(totalLength - currentLen, padChar)
//! PadLeftToLength = padding & text
//! End If
//! End Function
//! ```
//!
//! ### Pattern 6: `GetFilenameFromPath`
//! ```vb
//! Function GetFilenameFromPath(fullPath As String) As String
//! ' Extract filename from full path
//! Dim slashPos As Integer
//!
//! slashPos = InStrRev(fullPath, "\")
//!
//! If slashPos > 0 Then
//! GetFilenameFromPath = Right(fullPath, Len(fullPath) - slashPos)
//! Else
//! GetFilenameFromPath = fullPath
//! End If
//! End Function
//! ```
//!
//! ### Pattern 7: `TruncateLeft`
//! ```vb
//! Function TruncateLeft(text As String, maxLength As Long, _
//! Optional ellipsis As String = "...") As String
//! ' Truncate from left, keeping rightmost characters
//! Dim textLen As Long
//!
//! textLen = Len(text)
//!
//! If textLen <= maxLength Then
//! TruncateLeft = text
//! Else
//! TruncateLeft = ellipsis & Right(text, maxLength - Len(ellipsis))
//! End If
//! End Function
//! ```
//!
//! ### Pattern 8: `FormatAccountNumber`
//! ```vb
//! Function FormatAccountNumber(accountNum As String) As String
//! ' Format account number showing only last 4 digits
//! Dim lastFour As String
//!
//! If Len(accountNum) > 4 Then
//! lastFour = Right(accountNum, 4)
//! FormatAccountNumber = "****" & lastFour
//! Else
//! FormatAccountNumber = accountNum
//! End If
//! End Function
//! ```
//!
//! ### Pattern 9: `ExtractDomainExtension`
//! ```vb
//! Function ExtractDomainExtension(url As String) As String
//! ' Extract domain extension (.com, .org, etc.)
//! Dim dotPos As Integer
//!
//! ' Find last dot
//! dotPos = InStrRev(url, ".")
//!
//! If dotPos > 0 Then
//! ExtractDomainExtension = Right(url, Len(url) - dotPos + 1)
//! Else
//! ExtractDomainExtension = ""
//! End If
//! End Function
//! ```
//!
//! ### Pattern 10: `GetTrailingDigits`
//! ```vb
//! Function GetTrailingDigits(text As String) As String
//! ' Extract trailing numeric characters
//! Dim i As Integer
//! Dim digitCount As Integer
//!
//! digitCount = 0
//!
//! For i = Len(text) To 1 Step -1
//! If IsNumeric(Mid(text, i, 1)) Then
//! digitCount = digitCount + 1
//! Else
//! Exit For
//! End If
//! Next i
//!
//! If digitCount > 0 Then
//! GetTrailingDigits = Right(text, digitCount)
//! Else
//! GetTrailingDigits = ""
//! End If
//! End Function
//! ```
//!
//! ## Advanced Usage
//!
//! ### Example 1: File Extension Validator
//! ```vb
//! ' Comprehensive file extension validation and management
//! Class FileExtensionValidator
//! Private m_validExtensions As Collection
//!
//! Public Sub Initialize()
//! Set m_validExtensions = New Collection
//! End Sub
//!
//! Public Sub AddValidExtension(extension As String)
//! Dim ext As String
//!
//! ' Normalize extension (add dot if missing)
//! If Left(extension, 1) <> "." Then
//! ext = "." & extension
//! Else
//! ext = extension
//! End If
//!
//! On Error Resume Next
//! m_validExtensions.Add ext, UCase(ext)
//! On Error GoTo 0
//! End Sub
//!
//! Public Function IsValidFile(filename As String) As Boolean
//! Dim ext As String
//! Dim dotPos As Integer
//!
//! dotPos = InStrRev(filename, ".")
//!
//! If dotPos = 0 Then
//! IsValidFile = False
//! Exit Function
//! End If
//!
//! ext = Right(filename, Len(filename) - dotPos + 1)
//!
//! On Error Resume Next
//! Dim temp As String
//! temp = m_validExtensions(UCase(ext))
//! IsValidFile = (Err.Number = 0)
//! On Error GoTo 0
//! End Function
//!
//! Public Function GetExtension(filename As String) As String
//! Dim dotPos As Integer
//!
//! dotPos = InStrRev(filename, ".")
//!
//! If dotPos > 0 Then
//! GetExtension = Right(filename, Len(filename) - dotPos + 1)
//! Else
//! GetExtension = ""
//! End If
//! End Function
//!
//! Public Function ChangeExtension(filename As String, newExt As String) As String
//! Dim dotPos As Integer
//! Dim baseName As String
//! Dim ext As String
//!
//! dotPos = InStrRev(filename, ".")
//!
//! If dotPos > 0 Then
//! baseName = Left(filename, dotPos - 1)
//! Else
//! baseName = filename
//! End If
//!
//! ' Normalize new extension
//! If Left(newExt, 1) <> "." Then
//! ext = "." & newExt
//! Else
//! ext = newExt
//! End If
//!
//! ChangeExtension = baseName & ext
//! End Function
//!
//! Public Function GetValidExtensions() As String
//! Dim ext As Variant
//! Dim result As String
//!
//! result = ""
//!
//! For Each ext In m_validExtensions
//! If result <> "" Then result = result & ", "
//! result = result & ext
//! Next ext
//!
//! GetValidExtensions = result
//! End Function
//! End Class
//! ```
//!
//! ### Example 2: Path Parser Module
//! ```vb
//! ' Parse and manipulate file paths
//! Module PathParser
//! Public Function GetFilename(fullPath As String) As String
//! ' Extract filename from full path
//! Dim slashPos As Integer
//!
//! slashPos = InStrRev(fullPath, "\")
//!
//! If slashPos > 0 Then
//! GetFilename = Right(fullPath, Len(fullPath) - slashPos)
//! Else
//! GetFilename = fullPath
//! End If
//! End Function
//!
//! Public Function GetDirectory(fullPath As String) As String
//! ' Extract directory from full path
//! Dim slashPos As Integer
//!
//! slashPos = InStrRev(fullPath, "\")
//!
//! If slashPos > 0 Then
//! GetDirectory = Left(fullPath, slashPos - 1)
//! Else
//! GetDirectory = ""
//! End If
//! End Function
//!
//! Public Function GetFilenameWithoutExtension(fullPath As String) As String
//! ' Get filename without extension
//! Dim filename As String
//! Dim dotPos As Integer
//!
//! filename = GetFilename(fullPath)
//! dotPos = InStrRev(filename, ".")
//!
//! If dotPos > 0 Then
//! GetFilenameWithoutExtension = Left(filename, dotPos - 1)
//! Else
//! GetFilenameWithoutExtension = filename
//! End If
//! End Function
//!
//! Public Function GetExtension(fullPath As String) As String
//! ' Get file extension including dot
//! Dim filename As String
//! Dim dotPos As Integer
//!
//! filename = GetFilename(fullPath)
//! dotPos = InStrRev(filename, ".")
//!
//! If dotPos > 0 Then
//! GetExtension = Right(filename, Len(filename) - dotPos + 1)
//! Else
//! GetExtension = ""
//! End If
//! End Function
//!
//! Public Function CombinePath(directory As String, filename As String) As String
//! ' Combine directory and filename
//! If Right(directory, 1) = "\" Then
//! CombinePath = directory & filename
//! Else
//! CombinePath = directory & "\" & filename
//! End If
//! End Function
//!
//! Public Function GetParentDirectory(fullPath As String) As String
//! ' Get parent directory
//! Dim dir As String
//! Dim slashPos As Integer
//!
//! dir = GetDirectory(fullPath)
//! slashPos = InStrRev(dir, "\")
//!
//! If slashPos > 0 Then
//! GetParentDirectory = Left(dir, slashPos - 1)
//! Else
//! GetParentDirectory = ""
//! End If
//! End Function
//! End Module
//! ```
//!
//! ### Example 3: String Suffix Matcher
//! ```vb
//! ' Match and validate string suffixes
//! Class StringSuffixMatcher
//! Private m_caseSensitive As Boolean
//!
//! Public Sub Initialize(Optional caseSensitive As Boolean = True)
//! m_caseSensitive = caseSensitive
//! End Sub
//!
//! Public Function EndsWith(text As String, suffix As String) As Boolean
//! ' Check if string ends with suffix
//! Dim textEnd As String
//! Dim suffixLen As Long
//!
//! suffixLen = Len(suffix)
//!
//! If suffixLen > Len(text) Then
//! EndsWith = False
//! Exit Function
//! End If
//!
//! textEnd = Right(text, suffixLen)
//!
//! If m_caseSensitive Then
//! EndsWith = (textEnd = suffix)
//! Else
//! EndsWith = (UCase(textEnd) = UCase(suffix))
//! End If
//! End Function
//!
//! Public Function EndsWithAny(text As String, suffixes() As String) As Boolean
//! ' Check if string ends with any of the provided suffixes
//! Dim i As Integer
//!
//! For i = LBound(suffixes) To UBound(suffixes)
//! If EndsWith(text, suffixes(i)) Then
//! EndsWithAny = True
//! Exit Function
//! End If
//! Next i
//!
//! EndsWithAny = False
//! End Function
//!
//! Public Function RemoveSuffix(text As String, suffix As String) As String
//! ' Remove suffix if present
//! If EndsWith(text, suffix) Then
//! RemoveSuffix = Left(text, Len(text) - Len(suffix))
//! Else
//! RemoveSuffix = text
//! End If
//! End Function
//!
//! Public Function GetMatchingSuffix(text As String, suffixes() As String) As String
//! ' Return the matching suffix, or empty string
//! Dim i As Integer
//!
//! For i = LBound(suffixes) To UBound(suffixes)
//! If EndsWith(text, suffixes(i)) Then
//! GetMatchingSuffix = suffixes(i)
//! Exit Function
//! End If
//! Next i
//!
//! GetMatchingSuffix = ""
//! End Function
//!
//! Public Function ReplaceSuffix(text As String, oldSuffix As String, _
//! newSuffix As String) As String
//! ' Replace suffix if present
//! If EndsWith(text, oldSuffix) Then
//! ReplaceSuffix = Left(text, Len(text) - Len(oldSuffix)) & newSuffix
//! Else
//! ReplaceSuffix = text
//! End If
//! End Function
//! End Class
//! ```
//!
//! ### Example 4: Account Number Formatter
//! ```vb
//! ' Format and mask account numbers securely
//! Class AccountNumberFormatter
//! Private m_maskChar As String
//! Private m_visibleDigits As Integer
//!
//! Public Sub Initialize(Optional maskChar As String = "*", _
//! Optional visibleDigits As Integer = 4)
//! m_maskChar = maskChar
//! m_visibleDigits = visibleDigits
//! End Sub
//!
//! Public Function FormatAccountNumber(accountNum As String) As String
//! ' Format account number showing only last N digits
//! Dim lastDigits As String
//! Dim maskedLength As Integer
//!
//! If Len(accountNum) <= m_visibleDigits Then
//! FormatAccountNumber = accountNum
//! Exit Function
//! End If
//!
//! lastDigits = Right(accountNum, m_visibleDigits)
//! maskedLength = Len(accountNum) - m_visibleDigits
//!
//! FormatAccountNumber = String(maskedLength, m_maskChar) & lastDigits
//! End Function
//!
//! Public Function FormatWithSpaces(accountNum As String, _
//! Optional groupSize As Integer = 4) As String
//! ' Format with spaces every N characters
//! Dim formatted As String
//! Dim i As Integer
//! Dim maskedNum As String
//!
//! maskedNum = FormatAccountNumber(accountNum)
//! formatted = ""
//!
//! For i = 1 To Len(maskedNum) Step groupSize
//! If i > 1 Then formatted = formatted & " "
//! formatted = formatted & Mid(maskedNum, i, groupSize)
//! Next i
//!
//! FormatWithSpaces = formatted
//! End Function
//!
//! Public Function GetLastDigits(accountNum As String) As String
//! ' Get only the visible digits
//! If Len(accountNum) <= m_visibleDigits Then
//! GetLastDigits = accountNum
//! Else
//! GetLastDigits = Right(accountNum, m_visibleDigits)
//! End If
//! End Function
//!
//! Public Function ValidateAccountNumber(accountNum As String, _
//! minLength As Integer, _
//! maxLength As Integer) As Boolean
//! ' Validate account number length
//! Dim numLen As Integer
//!
//! numLen = Len(accountNum)
//! ValidateAccountNumber = (numLen >= minLength And numLen <= maxLength)
//! End Function
//!
//! Public Sub SetMaskChar(maskChar As String)
//! m_maskChar = maskChar
//! End Sub
//!
//! Public Sub SetVisibleDigits(visibleDigits As Integer)
//! m_visibleDigits = visibleDigits
//! End Sub
//! End Class
//! ```
//!
//! ## Error Handling
//!
//! The `Right` function generates runtime errors in specific situations:
//!
//! **Error 5: Invalid procedure call or argument**
//! - Occurs when `length` parameter is negative
//!
//! **Error 94: Invalid use of Null**
//! - Occurs when `string` parameter is Null
//!
//! Example error handling:
//!
//! ```vb
//! On Error Resume Next
//! result = Right(userInput, charCount)
//! If Err.Number <> 0 Then
//! MsgBox "Error extracting characters: " & Err.Description
//! result = ""
//! End If
//! On Error GoTo 0
//! ```
//!
//! Best practice for safe usage:
//!
//! ```vb
//! Function SafeRight(text As String, length As Long) As String
//! If IsNull(text) Then
//! SafeRight = ""
//! Exit Function
//! End If
//!
//! If length < 0 Then
//! SafeRight = ""
//! Exit Function
//! End If
//!
//! If length = 0 Then
//! SafeRight = ""
//! ElseIf length >= Len(text) Then
//! SafeRight = text
//! Else
//! SafeRight = Right(text, length)
//! End If
//! End Function
//! ```
//!
//! ## Performance Considerations
//!
//! - `Right` is a very fast string function
//! - Performance is O(n) where n is the length parameter
//! - More efficient than using Mid to extract from the end
//! - For large strings, consider caching Len(string) if called multiple times
//! - No significant performance difference between Right and string slicing
//!
//! ## Best Practices
//!
//! 1. **Validate Length**: Check that length parameter is valid before calling
//! 2. **Handle Null**: Check for Null strings if data source is uncertain
//! 3. **Use with `InStrRev`**: Combine with `InStrRev` for finding from right
//! 4. **Document Intent**: Make clear why extracting from right vs left
//! 5. **Consider Edge Cases**: Handle empty strings, length = 0, length > string length
//! 6. **Use for File Extensions**: Preferred method for extracting file extensions
//! 7. **Combine with Trim**: Often useful to Trim before using Right
//! 8. **Cache String Length**: If using Len(string) multiple times, cache it
//! 9. **Avoid Magic Numbers**: Use named constants for length values
//! 10. **Test Boundary Conditions**: Test with length = 0, 1, Len(string), Len(string)+1
//!
//! ## Comparison with Related Functions
//!
//! | Function | Purpose | Parameters | Use Case |
//! |----------|---------|------------|----------|
//! | **Right** | Extract from right | ```(string, length)``` | Get last N characters, file extensions |
//! | **Left** | Extract from left | ```(string, length)``` | Get first N characters, prefixes |
//! | **Mid** | Extract from middle | ```(string, start, [length])``` | Get substring from any position |
//! | **`InStrRev`** | Find from right | ```(string, substring)``` | Find position searching from right |
//! | **Len** | String length | ```(string)``` | Get total length |
//! | **`RTrim`** | Remove right spaces | ```(string)``` | Remove trailing whitespace |
//!
//! ## Platform and Version Notes
//!
//! - Available in all versions of VB6 and VBA
//! - Behavior consistent across all platforms
//! - In VB.NET, replaced by String.Substring or string slicing
//! - `RightB` and `RightB`$ variants exist for byte data
//! - Right$ returns String type, Right returns Variant
//!
//! ## Limitations
//!
//! - Cannot use negative length to count from a different position
//! - No built-in way to extract "all but first N" characters (use Len arithmetic)
//! - Raises error on negative length instead of returning empty string
//! - No case-insensitive comparison built-in
//! - No Unicode-aware variant (uses ANSI/DBCS)
//!
//! ## Related Functions
//!
//! - `Left`: Returns characters from the left side of a string
//! - `Mid`: Returns characters from any position in a string
//! - `InStrRev`: Finds position of substring searching from right to left
//! - `Len`: Returns the length of a string
//! - `RTrim`: Removes trailing spaces from a string
//! - `InStr`: Finds position of substring searching from left to right
use crate::;
use right_dollar;
/// Returns the specified number of characters from the right side of the string.
///
/// A `length` of 0 returns an empty string; a `length` greater than the number
/// of characters returns the entire string. Characters are counted as Unicode
/// scalar values.
///
/// `Right` is the Variant-returning counterpart of `Right$`; a `Null` input
/// propagates as `Null`.
///
/// # Errors
///
/// Returns error 5 (`Invalid procedure call or argument`) when `length` is negative.