VBA code lower case to upper case using Mid string - vba

I've gotten stuck with this VBA code. Any help would be greatly appreciated. I'm trying to change the first letters of 2 words from lower case to upper case. Also, how should I take the space in between these two words into consideration in the code?
I haven't been able to execute the code as I keep getting this compile error: "Argument not optional".
Function Properword(Text)
Dim rText
rText = Len(rText)
If rText(Mid(1, 1)) = LCase(Str) Then
rText = UCase(Str)
If rText(Mid(6, 1)) = LCase(Str) Then
rText = UCase
End If
End Function
Cheers!

First of all, you don't have to use UDF. Simply use inbuilt WorksheetFunction.Proper function to achieve ProperCase.
If you still want to create UDF, an example would be
Function Properword(strTxt)
Dim arrTxt
arrTxt = Split(strTxt, " ")
For i = LBound(arrTxt) To UBound(arrTxt)
arrTxt(i) = UCase(Left(arrTxt(i), 1)) & Mid(arrTxt(i), 2)
Next
Properword = Join(arrTxt, " ")
End Function
Finally, issues with your code
rText = Len(rText) ~~ this means rText will contain a numeric value because Len returns the lenght of the string
If rText(Mid(1, 1)) = LCase(Str) Then ~~ Mid takes the string as first argument followed by start point and then end point (optional).
not sure what you were trying to do in the following lines.
rText = UCase(Str)
If rText(Mid(6, 1)) = LCase(Str) Then
rText = UCase

In addition to the Excel function PROPER
str = WorksheetFunction.Proper("UPPER lower") ' "Upper Lower"
There is also the VBA.StrConv function:
str = StrConv("UPPER lower", vbProperCase) ' "Upper Lower"
To convert only parts of the string to uppercase, you can use RegEx, or the Mid statement:
Mid(str, 1, 1) = UCase(Mid(str, 1, 1)) ' makes the first letter uppercase

Related

Searching for String inside another (with interruptions), on Excel

I'm trying to check whether the main string contains the entire substring, even if there are interruptions.
For example:
main string = 12ab34cd,
substring = 1234d
should return a positive, since 1234d is entirely contained in my main string, even though there are extra characters.
Since InStr doesn't take wildcards, I wrote my own VBA using the mid function, which works well if there are extra characters at the start/end, but not with extra characters in the middle.
In the above example, the function I wrote
works if the main string is ab1234dc,
but not if it's 12ab34cd.
Is there a way to accomplish what I'm trying to do using VBA?
Note Both of the methods below are case sensitive. To make them case insensitive, you can either use Ucase (or Lcase) to create phrases with the same case, or you can prefix the routine with the Option Compare Text statement.
Although this can be done with regular expressions, here's a method using Mid and Instr
Option Explicit
Function ssFind(findStr, mainStr) As Boolean
Dim I As Long, J As Long
I = 1: J = 1
Do Until I > Len(findStr)
J = InStr(J, mainStr, Mid(findStr, I, 1))
If J = 0 Then
ssFind = False
Exit Function
End If
I = I + 1: J = J + 1
Loop
ssFind = True
End Function
Actually, you can shorten the code further using Like:
Option Explicit
Function ssFind(findStr, mainStr) As Boolean
Dim I As Long
Dim S As String
For I = 1 To Len(findStr)
S = S & "*" & Mid(findStr, I, 1)
Next I
S = S & "*"
ssFind = mainStr Like S
End Function
Assuming you have 3 columns "SUBSTR","MAIN" and "CHECK" and your "Substring" data range is named "SUBSTR"
Sub check_char()
Dim c As Range
For Each c In Range("SUBSTR")
a = 1
test = ""
For i = 1 To Len(c.Offset(0, 1))
If Mid(c.Offset(0, 1), i, 1) = Mid(c, a, 1) Then
test = test & Mid(c.Offset(0, 1), i, 1)
a = a + 1
End If
Next i
If test = c Then
c.Offset(0, 2) = "MATCH"
Else
c.Offset(0, 2) = "NO MATCH"
End If
Next
End Sub

Remove all initial numbers from string until non-numerical character is reached

I am trying to remove the first numbers of a string of characters (remove all numbers until first non-numerical character is reached). Some strings have starting numbers formatted in the form of "14 214" where it should read 14214. This is the special space for separating numbers, and if the string in A1 starts by 14 214 then
ISNUMBER(LEFT(A1,3)*1)=TRUE
So that means that the space is not a problem, I just have to check for the first non-numerical character.
I thought of the following VBA function:
Function RemoveNumbers(Txt As String) As String
i = 1
Do While i < 9
If (IsError(Left(Txt, i) * 1)) = "False" Then
i = i + 1
Else
RemoveNumbers = Right(Txt, Len(Txt) - i)
End If
Loop
End Function
But it returns #VALUE!
Is the function correctly written? Do you have any suggestions?
Thanks
Walk along the string from left to right, looking at each character.
If the char is a space do nothing, if its a number replace it with a space otherwise return the string with leading spaces removed:
Function RemoveNumbers(txt As String) As String
Dim i As Long
For i = 1 To Len(txt)
Select Case Mid$(txt, i, 1)
Case " ":
Case "0" To "9": Mid$(txt, i, 1) = " "
Case Else
Exit For
End Select
Next
RemoveNumbers = LTrim$(txt)
End Function
Good solution from Alex K.
I would just like to add that the basic problem with the original program was that iserror does not catch the number conversion error - as soon as that occurs the whole function exits and you just get a value error because RemoveNumbers is not set. Also the error doesn't occur when you have left(txt,i)="14 ", but only on the next character when you have left(txt,i)="14 2". To make it work you would have to do something like this
Function RemoveNumbers(Txt As String) As String
On Error GoTo Handler
i = 1
Do While i <= Len(Txt)
firstNumber = Left(Txt, i) * 1
i = i + 1
Loop
Handler:
RemoveNumbers = Right(Txt, Len(Txt) - i + 1)
End Function

Excel VBA Using wildcard to replace string within string

I have a difficult situation and so far no luck in finding a solution.
My VBA collects number figures like $80,000.50. and I'm trying to get VBA to remove the last period to make it look like $80,000.50 but without using right().
The problem is after the last period there are hidden spaces or characters which will be a whole lot of new issue to handle so I'm just looking for something like:
replace("$80,000.50.",".**.",".**")
Is this possible in VBA?
I cant leave a comment so....
what about InStrRev?
Private Sub this()
Dim this As String
this = "$80,000.50."
this = Left(this, InStrRev(this, ".") - 1)
Debug.Print ; this
End Sub
Mid + Find
You can use Mid and Find functions. Like so:
The Find will find the first dot . character. If all the values you are collecting are currency with 2 decimals, stored as text, this will work well.
The formula is: =MID(A2,1,FIND(".",A2)+2)
VBA solution
Function getStringToFirstOccurence(inputUser As String, FindWhat As String) As String
getStringToFirstOccurence = Mid(inputUser, 1, WorksheetFunction.Find(FindWhat, inputUser) + 2)
End Function
Other possible solutions, hints
Trim + Clear + Substitute(Char(160)): Chandoo -
Untrimmable Spaces – Excel Formula
Ultimately, you can implement Regular expressions into Excel UDF: VBScript’s Regular Expression Support
How about:
Sub dural()
Dim r As Range
For Each r In Selection
s = r.Text
l = Len(s)
For i = l To 1 Step -1
If Mid(s, i, 1) = "." Then
r.Value = Mid(s, 1, i - 1) & Mid(s, i + 1)
Exit For
End If
Next i
Next r
End Sub
This will remove the last period and leave all the other characters intact. Before:
and after:
EDIT#1:
This version does not require looping over the characters in the cell:
Sub qwerty()
Dim r As Range
For Each r In Selection
If InStr(r.Value, ".") > 0 Then r.Characters(InStrRev(r.Text, "."), 1).Delete
Next r
End Sub
Shortest Solution
Simply use the Val command. I assume this is meant to be a numerical figure anyway? Get rid of commas and the dollar sign, then convert to value, which will ignore the second point and any other trailing characters! Robustness not tested, but seems to work...
Dim myString as String
myString = "$80,000.50. junk characters "
' Remove commas and dollar signs, then convert to value.
Dim myVal as Double
myVal = Val(Replace(Replace(myString,"$",""),",",""))
' >> myVal = 80000.5
' If you're really set on getting a formatted string back, use Format:
myString = Format(myVal, "$000,000.00")
' >> myString = $80,000.50
From the Documentation,
The Val function stops reading the string at the first character it can't recognize as part of a number. Symbols and characters that are often considered parts of numeric values, such as dollar signs and commas, are not recognized.
This is why we must first remove the dollar sign, and why it ignores all the junk after the second dot, or for that matter anything non numerical at the end!
Working with Strings
Edit: I wrote this solution first but now think the above method is more comprehensive and shorter - left here for completeness.
Trim() removes whitespace at the end of a string. Then you could simply use Left() to get rid of the last point...
' String with trailing spaces and a final dot
Dim myString as String
myString = "$80,000.50. "
' Get rid of whitespace at end
myString = Trim(myString)
' Might as well check if there is a final dot before removing it
If Right(myString, 1) = "." Then
myString = Left(myString, Len(myString) - 1)
End If
' >> myString = "$80,000.50"

Shift letters to the end of a string Visual Basic

I'm trying to shift letters to the end of the word. Like the sample output I have in the image.
Using getchar and remove function, I was able to shift 1 letter.
mychar = GetChar(word, 1) 'Get the first character
word = word.Remove(0, 1) 'Remove the first character
input.Text = mychar
word = word & mychar
output.Text = word
This is my code for shifting 1 letter.
I.E. for the word 'Star Wars', it currently shifts 1 letter, and says 'tar WarsS'
How can I make this move 3 characters to the end? Like in the sample image.
intNumChars = input.text
output.text = mid(word,4,len(word)) & left(word,3)
I wanted it to be easy for you to read but you can set the intNumChars variable to the value in your text box and replace the 4 with intNumChars + 1 and the 3 with intNumChars.
The mid() function can return a section of text in the middle of a string mid(string,start,finish). The len() function returns the length of a string so that the code will work on texts that are different lengths. The left function returns characters from the left() of a string.
I hope this is of some help.
You could write a that as a sort of permute, which maps each char-index to a new place in the range [0, textLength[
In order to do that you'll have to write a custom modulus as the Mod operator is more a remainder than a modulus (from a mathematical point of view, regarding how negative are handled)
With that you just need to loop over your string indexes and map each one to it's "offsetted" value modulo the length of the text
' Can be made local to Shift method if needed
Function Modulus(dividend As Integer, divisor As Integer) As Integer
dividend = dividend Mod divisor
Return If(dividend < 0, dividend + divisor, dividend)
End Function
Function Shift(text As String, offset As Integer) As String
' validation omitted
Dim length = text.Length
Dim arr(length - 1) As Char
For i = 0 To length - 1
arr(Modulus(i + offset, length) Mod length) = text(i)
Next
Return new String(arr)
End Function
That way you can easily handle negative values or values greater than the length of the text.
Note, the same thing is possible with a StringBuilder instead of an array ; I'm not sure which one is "better"
Function Shift(text As String, offset As Integer) As String
Dim builder As New StringBuilder(text)
Dim length = text.Length
For i = 0 To length - 1
builder(Modulus(i + offset, length) Mod length) = text(i)
Next
Return builder.ToString
End Function
Using Gordon's code did the trick. The left function visual studio tried to create a stub of the function, so I used the fully qualified function name when calling it. But this worked perfectly.
intNumChars = shiftnumber.Text
output.Text = Mid(word, intNumChars + 1, Len(word)) & Microsoft.VisualBasic.Left(word, intNumChars)
n = 3
output.Text = Right(word, Len(word) - n) & Left(word, n)

Longest Common substring breaking issue

Hi I have a function that finds the longest common substring between two strings. It works great except it seems to break when it reaches any single quote mark: '
This causes it to not truly find the longest substring sometimes.
Could anyone help me adjust this function so it includes single quotes in the substring? I know it needs to be escaped someplace I'm just not sure where.
Example:
String 1: Hi there this is jeff's dog.
String 2: Hi there this is jeff's dog.
After running the function the longest common substring would be:
Hi there this is jeff
Edit: seems to also happen with "-" as well.
It will not count anything after the single quote as part of the substring.
Here's is the function:
Public Shared Function LongestCommonSubstring(str1 As String, str2 As String, ByRef subStr As String)
Try
subStr = String.Empty
If String.IsNullOrEmpty(str1) OrElse String.IsNullOrEmpty(str2) Then
Return 0
End If
Dim num As Integer(,) = New Integer(str1.Length - 1, str2.Length - 1) {}
Dim maxlen As Integer = 0
Dim lastSubsBegin As Integer = 0
Dim subStrBuilder As New StringBuilder()
For i As Integer = 0 To str1.Length - 1
For j As Integer = 0 To str2.Length - 1
If str1(i) <> str2(j) Then
num(i, j) = 0
Else
If (i = 0) OrElse (j = 0) Then
num(i, j) = 1
Else
num(i, j) = 1 + num(i - 1, j - 1)
End If
If num(i, j) > maxlen Then
maxlen = num(i, j)
Dim thisSubsBegin As Integer = i - num(i, j) + 1
If lastSubsBegin = thisSubsBegin Then
subStrBuilder.Append(str1(i))
Else
lastSubsBegin = thisSubsBegin
subStrBuilder.Length = 0
subStrBuilder.Append(str1.Substring(lastSubsBegin, (i + 1) - lastSubsBegin))
End If
End If
End If
Next
Next
subStr = subStrBuilder.ToString()
Return subStr
Catch e As Exception
Return ""
End Try
End Function
I tried it with dotnetfiddle and there it is working with your Code you posted. Please activate your warnings in your project. You have function with no return value and you return an integer or a string. This is not correct. How are you calling your function?
Here is my example I tested for you:
https://dotnetfiddle.net/mVBDQp
Your code works perfectly like Regex! As far as I can see, there is really nothing wrong with your code.
Here I even tested it under more severe case:
Public Sub Main()
Dim a As String = ""
Dim str1 As String = "Hi there this is jeff''s dog.-do you recognize this?? This__)=+ is m((a-#-&&*-ry$##! <>Hi:;? the[]{}re this|\ is jeff''s dog." 'Try to trick the logic!
Dim str2 As String = "Hi there this is jeff''s dog. ^^^^This__)=+ is m((a-#-&&*-ry$##! <>Hi:;? the[]{}re this|\ is jeff''s dog."
LongestCommonSubstring(str1, str2, a)
Console.WriteLine(a)
Console.ReadKey()
End Sub
Note that I put '-$#^_)=+&|\{}[]?!;:.<> all there. Plus I tried to trick your code by giving early result.
But the result is excellent!
You could probably put more actual samples on the inputs which give you problems. Else, you could possibly describe the environment that you use/deploy your code into. Maybe the problem lies elsewhere and not in the code.
The quickest way to solve this would be to use an escape code and replace all the ' with whatever escape code you use