Converting a String into a Single - vba

My question might sound stupid but I tried several solutions exposed on internet without any success. I'm totally new to VBA.
Problem:
I am extracting data from a txt file. That data is stored into a String and I need to store that value into a Single variable.
Context:
I am using Microsoft Excel 2010, the code is done under Microsoft Visual Basic for Applications.
Solutions that i tried:
In all these cases, valueToRead is equal to "1.580000".
1) realAngle = CSng(valueToRead)
I get the execution error '13', type incompatibility
2) realAngle = Single.Parse(valueToRead)
Compilation error, syntax error
3) realAngle = Single.Parse(valueToRead, System.Globalization.NumberFormatInfo.InvariantInfo)
Compilation error, syntax error
4) realAngle = Convert.ToSingle(valueToRead)
Execution error '424': object required
My code is below :
Sub macro_test()
' File to read data from
Dim logFile As String
' Variable containing a line from the file
Dim textLine As String
' Variable containing a part of the line
Dim ReadValue As Variant
' Variable containing a part of ReadValue
Dim ReadValue2 As Variant
' Desperate variable in order to be sure to have a String value
Dim valueToRead As String
' Angle value stored in the file
Dim realAngle As Single
' Number of elements separated by " | " in the lien
Dim Size As Integer
' Initialize variables
Size = 0
realAngle = 0
logFile = "FilePathAndName"
' Open the txt file
Open logFile For Input As #1
' Read until the end of the file
Do Until EOF(1)
' Get a line of text from the file
Line Input #1, textLine
' Split the line with " | " separator
ReadValue = Split(textLine, " | ")
' Count the number of elements
Size = UBound(ReadValue) - LBound(ReadValue) + 1
' If the line have enough elements then it may be of interest
If Size > 9 Then
' if this is the correct line thanks to a correct identificator
If ReadValue(3) = "MyIdentificator" Then
' Split the line with the " = " sign
ReadValue2 = Split(ReadValue(8), " = ")
' Storing the value into a String
valueToRead = ReadValue2(1)
realAngle = CSng(valueToRead)
'realAngle = Single.Parse(valueToRead)
'realAngle = Convert.ToSingle(valueToRead)
'realAngle = Single.Parse(valueToRead, System.Globalization.NumberFormatInfo.InvariantInfo)
End If
End If
Loop
Close #1
End Sub
Thank you in advance for your help!
edit: Here is an exemple of the line that I get in the file:
Log Level: LogLevel | File name: X:\Folder1\Folder2\Folder3\Folder4\Folder5\Folder6\FileName.h | Function name: FunctionName| Line number: XXXX | Information: MYINFO | BLABLA | VALUE1 = 32768 | VALUE2 = 0.000000 | VALUE3 = 1.580000 | VALUE4 = 0.000000 | VALUE5 = 3581.941895 | VALUE6 = 36349.941406
I am currently trying to get VALUE3.

Just guessing that you are not in USA/UK. In Germany, you have , and not . as a regional setting. Thus, add this to the string, before casting:
Public Function change_commas(ByVal myValue As Variant) As String
Dim str_temp As String
str_temp = CStr(myValue)
change_commas = Replace(str_temp, ",", ".")
End Function

Related

VB.net Read Specific Lines From a Text File That Start With and Stop Reading When Start With

I'm looking to read lines from a text file that start with certain characters and stop when the line starts with other characters. So in my example I would like to start reading at line AB and stop at line EF however not all lines will contain the CD line. There will always be a AB line and EF line, however the number of lines in between is unknown.
Here is an example of the lines in a text file I would be reading. You can see that this will create two rows in the DataGridView however the first row is missing the CD line and should be blank.
AB-id1
EF-address1
AB-id2
CD-name1
EF-address2
Here is the code I have so far:
Dim lines() As String = File.ReadAllLines(textfile)
For i As Integer = 0 To lines.Length - 1
If lines(i).StartsWith("AB") Then
Dim nextLines As String() = lines.Skip(i + 1).ToArray
Dim info As String = nextLines.FirstOrDefault(Function(Line) Line.StartsWith("CD"))
Dim name As String = "Yes"
Dim info2 As String = nextLines.FirstOrDefault(Function(Line) Line.StartsWith("EF"))
Dim address As String = "Yes"
End If
DataGridView.Rows.Add(name,address)
Next
Now the output I currently get is:
|Yes|Yes|
|Yes|Yes|
And I should be getting:
||Yes|
|Yes|Yes|
It looks like it's reading too far down the text file and I need it to stop reading at EF. I've tried Do while and Do Until with no success. Any suggestions?
You could use the Array.FindIndex function to get the index of the next line starting with your prefix. This way you don't have to skip lines and create a new array each time.
Try this out instead:
Dim lines() As String = File.ReadAllLines(textFile)
For i As Integer = 0 To lines.Length - 1
If lines(i).StartsWith("AB") Then
Dim addressIndex As Integer = Array.FindIndex(lines, i + 1, Function(Line) Line.StartsWith("EF"))
Dim address As String = If(addressIndex <> -1, lines(addressIndex).Substring(3), "") ' Get everything past the "-"
Dim name As String = ""
If addressIndex <> -1 Then
Dim nameIndex As Integer = Array.FindIndex(lines, i + 1, addressIndex - i, Function(line) line.StartsWith("CD"))
If nameIndex <> -1 Then
name = lines(nameIndex).Substring(3) ' Get everything past the "-"
End If
End If
DataGridView.Rows.Add(name, address)
End If
Next

How can I Parse text document in VB,Net for values?

I'm looking to parse this text file into strings to insert them into a database.
Source Text File gets read as the following string:
Line of unwanted text
Another line of unwanted data
Timestamp: 1/1/10 12:00 PM
ID: 1
Details: All data processed. Length will vary.
I'd like to just read Timestamp, ID and Details and place them into separate strings to insert them into a data table. What is the best method of capturing everything after the : and to the end of the line?
Dim Details as String = TextFile.Substring(Message.IndexOf("Details:"), X)
If you have to use a String as input, you can use String.Split to break it up into lines, and process each line. String.Substring can be used to extract the rest of the line - I've just hardcoded the starting positions below.
Dim timestamp As String = Nothing
Dim id As String = Nothing
Dim details As String = Nothing
For Each line In input.Split({vbCrLf, vbCr, vbLf}, StringSplitOptions.None)
If line.StartsWith("timestamp:", StringComparison.OrdinalIgnoreCase) Then
timestamp = line.Substring(10).Trim()
ElseIf line.StartsWith("id:", StringComparison.OrdinalIgnoreCase) Then
id = line.Substring(3).Trim()
ElseIf line.StartsWith("details:", StringComparison.OrdinalIgnoreCase) Then
details = line.Substring(8).Trim()
End If
Next
If you can change how you read the data, then the loop could just be:
For each line In File.ReadLines("your\file\name.txt")
...
Next
Assuming your files are flawless... One way to do it :
Imports System.IO
Dim AllLines() As String = File.ReadAllLines(FilePath)
Dim DatasIndex As Int32 = -1
For i As Int32 = 0 To AllLines.Length - 1
If AllLines(i).StartsWith("T") OrElse AllLines(i).StartsWith("t") Then
If AllLines(i).ToUpper().StartsWith("TIMESTAMP: ") Then
DatasIndex = i
Exit For
End If
End If
Next
If DatasIndex > -1 Then
' Dim ReadDate As Date = Date.Parse(AllLines(DatasIndex).Substring(11))
' Dim ReadID As Int32 = Integer.Parse(AllLines(DatasIndex + 1).Substring(4))
Dim ReadDate As String = AllLines(DatasIndex).Substring(11)
Dim ReadID As String = AllLines(DatasIndex + 1).Substring(4)
Dim ReadDetails As String = AllLines(DatasIndex + 2).Substring(9)
' send to database
End If
You didn't tell if Timestamp: , ID: and Details: Strings are always in the same order and has a trailing space after each property name.

Nested Loop Not Working vb.net

I am trying to read file names from source directory and then read a separate file to rename and move files to target directory. Below code reads the file names but the problem is it only reading the contents of app.ini file only once i.e. for first file name. Code is not looping app.ini as soon as for loops switches to second file name.
Dim di As New IO.DirectoryInfo("D:\Transcend")
Dim diar1 As IO.FileInfo() = di.GetFiles()
Dim dra As IO.FileInfo
If (di.GetFiles.Count > 0) Then
Dim a As Integer = 1
Dim b As Integer = 1
For Each dra In diar1
ComboBox1.Items.Add(dra.FullName.ToString)
Using reader2 As New IO.StreamReader("D:\Transcend\test\app.ini")
Do While reader2.Peek() >= 0
Dim line2 = reader2.ReadLine
Do Until line2 Is Nothing
'line2 = reader2.ReadLine()
'ComboBox1.Items.Add(line2.ToString)
'Label1.Text = line2
If line2 <> Nothing Then
If line2.Contains("filename" + a.ToString) Then
Dim values() As String = line2.Split(CChar(":")).ToArray
Dim values2() As String = values(1).Split(CChar(";")).ToArray() 'full filename
Dim values3() As String = values(2).Split(CChar(";")).ToArray() 'keyword to be replaced in filename
Dim values4() As String = values(3).Split(CChar(";")).ToArray() 'fullname in place of keyword
Dim values5() As String = values(4).Split(CChar(";")).ToArray 'destination drive letter
Dim values6() As String = values(5).Split(CChar(";")).ToArray 'destination path after drive letter
ComboBox1.Items.Add(values2(0))
ComboBox1.Items.Add(values3(0))
ComboBox1.Items.Add(values4(0))
ComboBox1.Items.Add(values5(0) + ":" + values6(0))
'Label1.Text = dra.Name.ToString
If dra.Name.ToString.Contains(values2(0)) Then
Dim n As String = dra.Name.Replace(values3(0), values4(0))
File.Copy(dra.FullName, values5(0) + ":" + values6(0) + n)
End If
End If
End If
Exit Do
Loop
a = a + 1
Loop
reader2.Close()
End Using
b = b + 1
Next
Label1.Text = b
Else
MsgBox("No files!")
End
End If
ouput image:
Above image is to show the output and error, first line is the filename1 and the next 8 lines are the output of the app.ini file. As you can see as soon as the filename1 changes to the next file name i.e. Autorun.inf in the 9th line of the above image the same 8 lines of app.ini(line 2nd to 9th in the above image) should be reiterated after Autorun.inf file name but app.ini is not getting to read after file name increments to Autorun.inf and then to FreeSoftware(JF).htm.
The only difference between the first and the second file are the a and b values.
On the first run a will start from 1 and it will be incremented for each line in the app.ini file. After reading 8 lines, the final value of a will be 9.
For the second file, the value a isn't reset so it's value will still be 9. This means that the following condition will never be true because the first run only found value from 1 to 8 *.
If line2.Contains("filename" + a.ToString) Then
To fix your issue, you must set the a variable value back to 1 between each file:
Using reader2 As New IO.StreamReader("D:\Transcend\test\app.ini")
a = 1
Do While reader2.Peek() >= 0
* I'm assuming that the filename in your .ini file are sorted (i.e. line containing filename9 isn't listed before filename2) and that no external process changed the content of your .ini file between the first and the second file.

Free up Memory: How to delete variables once am don with them- VBA VB ACCESS

How do i free up Memory?
Say I have a string
Dim TestStri As String
TestStri = "Test"
' What do i have to type up to get rid of the variable?
' I know
TestStri = Nothing
' will give it the default value, but the variable is still there.
Can I use the same Method for other variables i.e. Long, int etc.
I'm assuming you are referring to VB6 and VBA as indicated by your title, not VB.Net, as indicated by a keyword.
In VB6 and VBA the memory consumption of a string variable consists of a fixed part for the string's length and a terminator and a variable length part for the string contents itself. See http://www.aivosto.com/vbtips/stringopt2.html#memorylayout for a good explanation of this.
So, when you set the string variable to an empty string or vbNullString, you will be freeing up the variable part of the string but not the fixed part.
Other types like long, int, bool and date consume a fixed amount of memory.
You can't "free" local variables in VB completely (come to think of it, is there ANY programming language where you can do that?), and for the most part, you wouldn't care because the local variables themselves (the fixed portion) is usually very small.
The only case I can think of where the memory consumption of local varibles could get big is if you have recursive function calls with deep recursion/wide recursion.
I went a differs route :
I was hoping MemoryUsage would be useful. It wasn't, apparently...
I run a vba script that goes through multiple files (since access cannot handle anything too large); and append them to a table, transform it and then spit out a summary.
The script loops through files and runs macros against each of them.
The quick answer is to pull the memory usage from the task manager and then if it exceeds 1 GB; pause the subroutine so no corrupt records get in.
How do we do this?
Insert this memory usage Function with the readfile function.
You will need to create an if statement in your code that says:
dim memory as long
memory = memory_usage
' 1000000 ~ 1 GB
If memory > 1000000 then
End Sub
end if
=================================================
[path to file] = "C:\….\ShellOutputfile.txt"
Function Memory_Usage() as Long
Dim lines As Long
Dim linestring As String
Shell "tasklist /fi " & """IMAGENAME EQ MSACCESS.EXE""" & ">" & """[path to file]"""
'get_list_data
lines = CInt(get_listing_data("[path to file]", 1, 0))
linestring = get_listing_data("[path to file]", 2, 4)
linestring = Right(linestring, 11)
linestring = Replace(linestring, " K", "") ' K
linestring = Replace(linestring, " ", "")
lines = CLng(linestring)
Memory_Usage = lines
End Function
=============================
Public Function get_listing_data(PATH As String, Choice As Integer, typeofreading As Integer) As String
' parse in the variable, of which value you need.
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Dim tmp_var_str As String
Dim fso, ts, fileObj, filename
Dim textline As String
Dim tmp_result As String
Dim TMP_PATH As String
Dim tmpchoice As Integer
Dim tor As Integer
Dim counter As Integer
' type of reading determines what loop is used
' type of reading = 0; to bypass; > 0, you are choosing a line to read.
counter = 0
TMP_PATH = PATH
tmp_var_str = var_str
tmp_result = ""
tor = typeofreading
' choice = 1 (count the lines)
' choice = 2 (read a specific line)
tmpchoice = Choice
' Create the file, and obtain a file object for the file.
If Right(PATH, 1) = "\" Then TMP_PATH = Left(PATH, Len(PATH) - 1)
filename = TMP_PATH '& "\Profit_Recognition.ini"
Set fso = CreateObject("Scripting.FileSystemObject")
Set fileObj = fso.GetFile(filename)
' Open a text stream for output.
Set ts = fileObj.OpenAsTextStream(ForReading, TristateUseDefault)
Do While ts.AtEndOfStream <> True
If tmpchoice = 1 Then
counter = counter + 1
textline = ts.ReadLine
tmp_result = CStr(counter)
End If
If tmpchoice = 2 Then
counter = counter + 1
tmp_result = ts.ReadLine
If counter = tor Then
Exit Do
End If
End If
Loop
get_listing_data = tmp_result
End Function

Extract characters from a long string and reformat the output to CSV by using keywords with VB.net

I am new to VB.Net 2008. I have a task to resolve, it is regading extracting characters from a long string to the console, the extracted text shall be reformatted and saved into a CSV file. The string comes out of a database.
It looks something like: UNH+RAM6957+ORDERS:D:96A:UN:EGC103'BGM+38G::ZEW+REQEST6957+9'DTM+Z05:0:805'DTM+137:20100930154
The values are seperated by '.
I can query the database and display the string on the console, but now I need to extract the
Keyword 'ORDERS' for example, and lets say it's following 5 Characters. So the output should look like: ORDERS:D:96A then I need to extract the keyword 'BGM' and its following five characters so the output should look like: BGM+38G:
After extracting all the keywords, the result should be comma seperated and look like:
ORDERS:D:96A,BGM+38G: it should be saved into a CSV file automatically.
I tried already:
'Lookup for containing KeyWords
Dim FoundPosition1 = p_EDI.Contains("ORDERS")
Console.WriteLine(FoundPosition1)
Which gives the starting position of the Keyword.
I tried to trim the whole thing around the keyword "DTM". The EDI variable holds the entire string from the Database:
Dim FoundPosition2 = EDI
FoundPosition2 = Trim(Mid(EDI, InStr(EDI, "DTM")))
Console.WriteLine(FoundPosition2)
Can someone help please?
Thank you in advance!
To illustrate the steps involved:
' Find the position where ORDERS is in the string.'
Dim foundPosition = EDI.IndexOf("ORDERS")
' Start at that position and extract ORDERS + 5 characters = 11 characters in total.'
Dim ordersData = EDI.SubString(foundPosition, 11)
' Find the position where BGM is in the string.'
Dim foundPosition2 = EDI.IndexOf("BGM")
' Start at that position and extract BGM + 5 characters = 8 characters in total.'
Dim bgmData = EDI.SubString(foundPosition2, 8)
' Construct the CVS data.'
Dim cvsData = ordersData & "," & bgmData
I don't have my IDE here, but something like this will work:
dim EDI as string = "UNH+RAM6957+ORDERS:D:96A:UN:EGC103'BGM+38G::ZEW+REQEST6957+9'DTM+Z05:0:805'DTM+137:20100930154"
dim result as string = KeywordPlus(EDI, "ORDER", 5) + "," _
+ KeywordPlus(EDI, "BGM", 5)
function KeywordPlus(s as string, keyword as string, length as integer) as string
dim index as integer = s.IndexOf(keyword)
if index = -1 then return ""
return s.substring(index, keyword.length + length)
end function
for the interrested people among us, I have put the code together, and created
a CSV file out of it. Maybe it can be helpful to others...
If EDI.Contains("LOC") Then
Dim foundPosition1 = EDI.IndexOf("LOC")
' Start at that position and extract ORDERS + 5 characters = 11 characters in total.'
Dim locData = EDI.Substring(foundPosition1, 11)
'Console.WriteLine(locData)
Dim FoundPosition2 = EDI.IndexOf("QTY")
Dim qtyData = EDI.Substring(FoundPosition2, 11)
'Console.WriteLine(qtyData)
' Construct the CSV data.
Dim csvData = locData & "," & qtyData
'Console.WriteLine(csvData)
' Creating the CSV File.
Dim csvFile As String = My.Application.Info.DirectoryPath & "\Test.csv"
Dim outFile As IO.StreamWriter = My.Computer.FileSystem.OpenTextFileWriter(csvFile, True)
outFile.WriteLine(csvData)
outFile.Close()
Console.WriteLine(My.Computer.FileSystem.ReadAllText(csvFile))
End IF
Have fun!