I have a procedure, that generates a random string without any delimiter. I store return value of this as a string, but I would like to split this text into characters and after that examine each characters. I try to use above code to split string into characters, but it gives Type mismatch error.
Sub gen()
Dim s As String
s = textgen(4000, 5)
Dim buff() As String
ReDim buff(Len(s) - 1)
For i = 1 To Len(s)
buff(i - 1) = Mid$(s, i, 1)
Next
MsgBox (buff) ' type mismatch
End Sub
The type of buff is string() - an array of strings (VBA doesn't have a Char type).
MsgBox wants a String message, not an array of these; you'll have to Join the elements:
MsgBox Join(buff) 'no error
Related
When multiple PowerPoint slide numbers are entered in the input box (ex: 3, 5, 6), I want to create a macro that selects the slides of the entered number, but an error occurs.
Sub test()
Dim strresponse2 As String
Dim iresponse2 As String
strresponse2 = InputBox("page number" & vbCr & "ex) 2,4,11,5")
If IsNumeric(strresponse2) Then
iresponse2 = strresponse2
End If
ActiveWindow.Selection.Unselect
ActivePresentation.slides.Range(Array(iresponse2)).Select
'error here
'How to fix it so it doesn't get an error
'ActivePresentation.Slides.Range(Array(2, 4, 11,5)).Select
'no error
End Sub
Several issues here.
a) If you enter 2, 4, 5, the check for IsNumeric(strresponse2) will fail because the function tries to convert the whole string into one single number.
b) Array(iresponse2) will not convert the string into an array (of 3 numbers). It will convert the single string 2, 4, 5 into an string array with 1 (not 3) member.
In your case, you can use the Split-function to split the input string into an array of strings.
c) If you want to access the slides by number, the input needs to be of a numeric type, not of string (even if the strings contain numbers). You will need to convert the string array into a numeric array (if you pass a string or an array of strings as parameter, VBA will look for members with the name, not the index).
Have a look to the following piece of code and check if it does what you need - it's only half tested (as I have no Powerpoint VBA available, only Excel, but the priniple is the same)
Dim answer As String
answer = InputBox("page number" & vbCr & "ex) 2,4,11,5")
Dim pagesS() As String
pagesS = Split(answer, ",") ' Split the answer into an array of strings.
ReDim pagesN(0 To UBound(pagesS)) As Long ' Create an empty numeric array
Dim countS As Long, countN As Long
For countS = 0 To UBound(pagesS) ' Loop over all strings
If IsNumeric(pagesS(countS)) Then ' String is Numeric
Dim pageNo As Long
pageNo = Val(pagesS(countS)) ' Convert string to number
If pageNo > 0 And pageNo <= ActivePresentation.slides.Count Then
pagesN(countN) = pageNo ' When number is within valid range, copy it
countN = countN + 1 ' Count the number of valid page numbers
End If
End If
Next countS
If countN > 0 Then ' At least one number found
ReDim Preserve pagesN(0 To countN - 1) ' Get rid of unused elements
ActivePresentation.Slides.Range(pagesN).Select
End If
I need to separate following strings into Name and Number: e.g.
evil333 into evil and 333
bili454 into bili and 454
elvis04 into elvis and 04
Split(String, "#") ' don't work here because numbers are unknown
similarly
Mid(String, 1, String - #) ' don't work because Numbers length is unknown
so what should be the best way to start? Just want to keep it simple as possible
Update:
For further info follow - https://youtu.be/zjF7oLLgtms
Two more ways for solving this:
Sub test()
Dim sInputString As String
Dim i As Integer
Dim lFirstNumberPos As Long
sInputString = "evil333"
'loop through text in input string
'if value IsNumeric (digit), stop looping
For i = 1 To Len(sInputString)
If IsNumeric(Mid(sInputString, i, 1)) Then
lFirstNumberPos = i
Exit For
End If
Next i
Dim Name As String
Dim Number As String
'return result
Name = Left$(sInputString, lFirstNumberPos - 1)
Number = Mid$(sInputString, lFirstNumberPos)
End Sub
Or another method:
Sub test2()
'if you are going to have too long string it would maybe better to use "instr" method
Dim sInputString As String
Dim lFirstNumberPos As Long
Dim i As Integer
sInputString = "evil333"
Dim lLoopedNumber as Long
LoopedNumber = 0
lFirstNumberPos = Len(sInputString) + 1
'loop through digits 0-9 and stop when any of the digits will be found
For i = 0 To 9
LoopedNumber = InStr(1, sInputString, cstr(i), vbTextCompare)
If LoopedNumber > 0 Then
lFirstNumberPos = Application.Min(LoopedNumber,lFirstNumberPos)
End If
Next i
Dim Name As String
Dim Number As String
'return result
Name = Left$(sInputString, lFirstNumberPos - 1)
Number = Mid$(sInputString, lFirstNumberPos)
End Sub
You should regular expressions (regex) to match the two parts of your strings. The following regex describes how to match the two parts:
/([a-z]+)([0-9]+)/
Their use in VBA is thorougly explained in Portland Runner's answer to How to use Regular Expressions (Regex) in Microsoft Excel both in-cell and loops
I have a VBA code that's designed to search a CSV String and add Carriage Returns where they should exist. I've split it up into two seperate functions - one to search the string and put the index of where the CRs should go into an array and a second function to actually add the CRs.
The issue I'm running into is that the value in the immediate window/in the watch window for the functions is correct within the function itself, but it assigns the result variable a blank string.
'*****************Import CSV**********************
'Took this straight off the internet because it was reading Jet.com files as one single line
'
Sub ImportCSVFile(filepath As String)
.....
line = SearchString(line, "SALE")
.....
End Sub
'****************Search String***************************
'This is search the string for something - It will then call a function to insert carriage returns
Function SearchString(source As String, target As String) As String
Dim i As Integer
Dim k As Integer
Dim myArray() As Variant
Dim resultString As String
Do
i = i + 1
If Mid(source, i, Len(target)) = target Then
ReDim Preserve myArray(k)
myArray(k) = i
k = k + 1
End If
DoEvents
Loop Until i = Len(source)
resultString = addCarriageReturns(source, myArray) 'resultString here is assigned a blank string
SearchString = resultString
End Function
'***************Add Carraige Returns**************************
'Cycle through the indices held in the array and place carriage returns into the string
Function addCarriageReturns(source As String, myArray As Variant) As String
Dim i As Integer
Dim resultString As String
resultString = source
For i = 0 To UBound(myArray, 1)
resultString = Left(resultString, myArray(i) + i) & Chr(13) & Right(resultString, Len(resultString) - myArray(i) + i)
Next i
addCarraigeReturns = resultString 'The value of addCarriageReturn is correct in the immediate window here
End Function
In the function the value is not blank
...but when it passes it back, it says the value is blank
I'm just curious, why do you want separate functions like this?
Can you just use:
line = Replace(line, "SALE", "SALE" & Chr(13))
I am trying to write a function using Excel VBA to convert a string to its respective ASCII number. For example:
"ABCD" => "65666768"
I have written this code but it's failed to do the conversion:
Public Function asciien(s As String) As String
' Returns the string to its respective ascii numbers
Dim i As Integer
For i = 1 To Len(s)
asciien = asciien & CStr(Asc(Mid(s, x, 1)))
Next i
End Function
This line
asciien = asciien & CStr(Asc(Mid(s, x, 1)))
should read
asciien = asciien & CStr(Asc(Mid(s, i, 1)))
"x" has no value
How can I split a string in VBA after a certain amount of the same delimiter?
For example : {"Josh","Green"},{"Peter","John"}.
Here I would like {"Josh","Green"} as the first record in an array and {"Peter","John"} as the second. I want to avoid parsing the string character by character.
There are several ways to do this, my suggestion:
Replace },{ with something else before the split, to create a new delimiter.
For example:
Option Explicit
Sub Test()
Const c As String = "{""Josh"",""Green""},{""Peter"",""John""}"
Dim s As String
Dim v As Variant
s = Replace(c, "},{", "}#,#{", 1)
v = Split(s, "#,#")
Debug.Print v(0) '{"Josh","Green"}
Debug.Print v(1) '{"Peter","John"}
End Sub
That will split s into a Variant-array v with two strings, v(0) and v(1), instead of four strings, which you would get if you split the original string with just , as a delimiter.