VBA check for ENTER character from clipboard - vba

First of all I have little to no knowledge about VBA.. probably none at all. However I was asked to create a VBA program that paste text from clipboard in different cells. My text has the following format:
seminar: name of Seminar (in cell(1,1))
first name: participant's first name (in cell(1,2))
last name: participant's last name (in cell(1,3)) etc..
So far I was able to read the text from clipboard. Then I found the position of the ":" in order to paste only what is AFTER it in the cell.
At this point I thought to find the position of the RETURN character in order to know where the first line ends(ex. "name of Seminar") with this line of code which I found online:
end_str = InStr(str, vbCrLf) - 1
and with the Right (string, length) function to get the relative text.
This is not working. I think because there are not return character in the string variable that holds the data? I don't know.
My question is: Is it possible to check the RETURN character somehow or Is there a better way to create this program?
Thank you in advance.

An easy way would be to use the split function to get each line separately:
Suppose you have a function called ClipBoard_GetData that returns the text from ClipBoard, you could use something like this:
Dim lines() As String
lines = Split(ClipBoard_GetData, vbNewLine)
For Each Line In lines
' Parse each line to get whatever parts you want
Next
This should work fine.. and if you don't -already have a function that gets what's in the clipboard, you could refer to this link
Hope that helps :)

Most likely the Ascii code you're after is 10 (ie newline). So you could find the position of the newline like so:
i = Instr(str, Chr(10))
However, are you aware that you don't need to parse that clipboard text at all. You can write arrays directly into worksheet cells. So all you'd need to do is use the Split function. The procedure below will complete everything you need:
Public Sub PasteText(str As String)
Dim arr() As String
Dim cols As Integer
arr = Split(str, Chr(10))
cols = UBound(arr) + 1
Sheet1.Range("A1").Resize(, cols).Value = arr
End Sub

Related

How to count the number of empty spaces in front of a String in VBA?

I have a YAML file which I am reading using VBA Excel plugin. I am getting a String of each line. I need to count the number of empty spaces in the front of the first line so that it will be a marker to find the next key. Let me know how to do that.
Option Explicit
Function empty_spaces(str_input)
empty_spaces = Len(str_input) - Len(LTrim(str_input))
End Function
harun24hr, your answer does not work with " My String " and similar.

VBA error: A value used in the formula is the wrong data type?

I'm trying to create a function which generates a secret encoded message. It takes in three things: a string, for example, "testingtestingonetwothree", as well as the desired number of characters, for example 5, and the desired number of words, for example 5. It generates the message by starting at the first character, and extracting every fifth character through the string, putting these characters into a codeword, then starting at the second character and extracting every fifth character through the string, putting these into a second codeword, and so on. It just outputs a string, with the codewords separated by a space. So for this example it would produce: "tntnt egieh stntr tegwe isooe".
I'm okay at coding but new to VBA. I've made what I think is a valid function, but when it's used in the spreadsheet I get a #VALUE! error: "A value used in the formula is the wrong data type". This is the user defined function I made:
Function encode(strng, numchars, numwords)
Dim word As Integer
Dim step As Integer
Dim temp As String
Dim output As String
For word = 1 To numchars
step = word
temp = ""
Do While step <= Len(strng)
temp = temp & Mid(strng, 1, step)
step = step + numchars
Loop
If word = 1 Then output = temp Else output = output & " " & temp
Next word
encode = output
End Function
And when it's used in the spreadsheet I just call it, as in
=encode(A16,A7,A10)
Where A16 contains testingtestingonetwothree, A7 contains 5 and A10 contains 5.
Does my function seem okay? And is there anything you guys can see which could be giving the value error? Any help would be greatly appreciated, thanks a lot for reading.
EDIT: This now outputs a value, but the wrong value. It outputs: "ttestintestingtesttestingtestingontestingtestingonetwot tetestingtestingtestitestingtestingonetestingtestingonetwoth ", when it should output: "tntnt egieh stntr tegwe isooe". Is there anything you guys can see that my function is doing wrong?
EDIT2: After fixing the Mid function, to
temp = temp & Mid(strng, step, 1)
as per vacip's answer, the function now produces the correct answer.
Ok, everyone says it works, but for me, it doesn't produce the desired output. What the...???
Anyway, I think your Mid function is in the wrong order, try it like this:
temp = temp & Mid(strng, step, 1)
Also, make sure to properly declare your variables, like this:
Function encode(strng As String, numchars As Integer, numwords As Integer) As String
I have also rewritten your IF statement, that one-line thing is strange for me...
If word = 1 Then
output = temp
Else
output = output & " " & temp
End If
This way it worked for me.
Other people have addressed the type problem. Here is a different suggestion. The cipher that you are describing is a simple transposition cipher, specifically a columnar transposition ( https://en.wikipedia.org/wiki/Transposition_cipher#Columnar_transposition )
The way people did this pre-computer was to write the characters into a grid row by row then read them off column by column. In fact -- this is probably still the easiest way to implement it even with computers. Declare a variant which can be redimensioned to be an array with e.g. 5 columns (where 5 is the skip between letters) and the number of rows is chosen to be large enough so that the grid can hold the string. After you load up the characters row by row, read them off column by column using nested for loops.
Once you get a basic example working, you can try to implement a version which uses a key to determine the order that you read off the columns for added security.
Coding classical cryptography/cryptanalysis as an excellent way to learn a programming language. Almost the first thing I do when I try to learn a new language is to implement a Vigenere cipher in it. Even though it is long out of print and can be somewhat tricky to translate to modern dialects of Basic the book "Cryptanalysis for Microcomputers" by Caxton Foster is great fun and can be purchased for just a few dollars from online used bookstores.
You need to define your Function's type. So in this case I believe you would want
Function encode(strng, numchars, numwords) As String
I tested your code exactly as it is, and it worked fine.
So, your problem may be:
A certain argument of your function is not the right type. (I bet the len method is the problem in there).
Check if A16 is really a string. If not, consider converting it to a string before if you want to pass numbers too:
Function encode(strng as variant, numchars as integer, numwords as integer) as string
strng = str(strng)
Check also if A7 and A10 are really integers.

Isolate a a substring within quotes from an entire line

To start here is an example of a line I am trying to manipulate:
trait slot QName(PrivateNamespace("*", "com.company.assembleegameclient.ui:StatusBar"), "_-0IA") type QName(PackageNamespace(""), "Boolean") value False() end
I wrote a code that will go through and read through each line and stop at the appropriate line. What I am trying to achieve now is to read through the characters and save just the
_-0IA
to a new string. I tried using Trim(), Replace(), and indexof so far but I am having a ton of difficulties because of the quotation marks. Has anyone deal with this issue before?
Assuming your source string will always follow a strict format with only some data changes, something like this might work:
'Split the string by "," and extract the 3rd element. Trim the space and _
quotation mark from the front and extract the first 5 characters.
Dim targetstr As String = sourcestr.Split(","c)(2).TrimStart(" """.ToCharArray).Substring(0, 5)
If the length of the target string is variable it can be done like this:
Dim temp As String = teststr.Split(","c)(2).TrimStart(" """.ToCharArray)
'Use the index of the next quotation mark instead of a fixed length
Dim targetstr As String = temp.Substring(0, temp.IndexOf(""""c))

A Perfectly good Substring Error

Im having a problem parsing a string array of Directories. The end goal is to query the path tied to the [global].MyDataDir & "\saved" to get all folders in this directory. However the actual foldernames, the last bit of text after the last indexof "\" holds the name of a plugin that I need to compare against an enumerated list of plugins for further functionality I won't get into here. The problem here is my last bit of code wont work. The Dim foldername as String = (etc...), It returns an error saying Index and length must refer to a location within the string. Parameter name: length.
Can any of you wizards, help me out here. Much appreciated.
Dim dirList As String() = System.IO.Directory.GetDirectories([global].MyDataDir & "\saved")
For dir As Integer = 0 To dirList.Length - 1
If IO.Directory.GetFiles(dirList(dir)).Length > 0 Then
For Each file As String In IO.Directory.GetFiles(dirList(dir))
Dim folderName As String = dirList(dir).ToString.Substring(dirList(dir).ToString.LastIndexOf("\"), dirList(dir).ToString.Length - 1)
Next
End If
Next
Semper Fi.
Use System.IO.Path.GetDirectoryName() instead.
Next time use the VB.NET Left() convenience function to avoid getting this wrong.
I found the reason....
The problem lies in the arguments of Substring(starting index, length of copy from starting index). I was under the impression, the length argument would take into account the entire string when calculating the length. Instead the second argument of this function acts upon the results of the first argument, not the entire string. So the length of the string is actually much longer than what exists after taking an index of it.
Thanks for the help.

Trim file after a blank line

I have a text file that has multiple blank lines and Im trying to return all the lines between two of them specifically
so if I have a file that looks like this:
____________________________
1########################
2##########################
3
4########################
5##########################
6#######################
7
8#########################
9##########################
10#######################
11####################
12########################
13#########################
14
15##########################
----------------------------
I would like to grab lines 8-13. Unfortunately, it might not always be 8-13 as it could be 9-20 or 7-8, but it will however always be between the 2nd and 3rd line break.
I know how to trim characters and pull out singular lines, but I have no idea how to trim entire sections.
Any help would be appreciated, even if you just point me to a tutorial.
Thanks in advance.
The basic idea here is to get the entire thing as a string, split it into groups at the double line breaks, and then reference the group you want (in your case, the third one).
Dim value As String = File.ReadAllText("C:\test.txt")
Dim breakString As String = Environment.NewLine & Environment.NewLine
Dim groups As String() = value.Split({breakString}, StringSplitOptions.None)
Dim desiredString As String = groups(2)
MsgBox(desiredString)
Edit:
In response to the question in your comment -
Environment.NewLine is a more dynamic way of specifying a line break. Assuming you're running on windows - you could use VbCrLf as well. The idea is that if you were to compile the same code on Linux, it Environment.NewLine would generate a Lf instead. You can see here for more information: http://en.wikipedia.org/wiki/Newline
The reason I used Environment.NewLine & Environment.NewLine is because you want to break your information where there are two line breaks (one at the end of the last line of a paragraph, and one for the blank line before the next paragraph)
What I ended up doing was trimming the last part and searching for what I needed in the first part (I know I didnt include the searching part in the question, but I was just trying to figure out a way to narrow down the search results as it would have had repeated results). Im posting this incase anyone else stumbles upon this looking for some answers.
Dim applist() = System.IO.File.ReadAllLines("C:\applist.txt")
Dim findICSName As String = "pid"
Dim ICSName As New Regex("\:.*?\(")
Dim x = 0
Do Until applist(x).Contains("Total PSS by OOM adjustment:")
If applist(x).Contains(findICSName) Then
app = ICSName.Match(applist(x)).Value
app = app.TrimStart(CChar(": "))
app = app.TrimEnd(CChar("("))
ListBox1.Items.Add(app)
End If
x = x + 1
Loop
End If
How this works is that it looks through each line for the regex until it reaches first word in the breakpoint "Total PSS by OOM adjustment:"