VBA - splitting a string based on length - vba

I have various strings in the similar format of XXX100XXX110XXX120XXX230XXX240
How can I split this into parts like XXX1000 etc. without printing it on excel?
I need to store the parts as variables.

That could be:
Value = "XXX100XXX110XXX120XXX230XXX240"
Parts = Split(Value, "XXX")
Part1 = "XXX" & CStr(Parts(1))
Part2 = "XXX" & CStr(Parts(2))
' etc.

Related

VBA - Converting a mixed row ( Data Type wise) to Date

I have an excel sheet, one of the columns is mixed with Dates and Dates that has been copied to it as text ( see below ).
I dont manage to convert the text type to Date type, i need to do it though VBA to add it to some automation im working on. is there a way to do this at all ?
I noticed excel is looking for format like this 03/09/2016 23:39:57 and it doesn't like 3/21/16 11:07:22 PM, apparently this is my case :) every look i run i get ( obviously data mismatch ), in the image bellow the spoken column is "C"
thx :)
ExcelSheet bad Date format
Assuming wvery bad dates are MM/DD/YYYY, then you could use the following code that I wrote for you:
Sub main()
Dim celda As Range
Dim s_date As String
Dim s_time As String
Dim validate_date As String
Dim valid_date As String
Dim date_arr() As String
Dim rango As Range
Dim limit As Long
limit = Columns("B").Find("", Cells(Rows.Count, "B")).Row - 1
Set rango = ActiveSheet.Range("B2:B" & limit)
' works only for date values, another value would return non expected values
For Each celda In rango
validate_date = Left(celda.Value, 1)
If validate_date <> "" Then
If Not celda.Rows.Hidden Then
If validate_date <> "0" Then
s_date = Trim(Mid(celda.Value, 1, InStr(1, celda.Value, " ") - 1))
s_time = Trim(Mid(celda.Value, InStr(1, celda.Value, " "), Len(celda.Value) - InStr(1, celda.Value, " ")))
date_arr = Split(s_date, "/")
valid_date = date_arr(1)
valid_date = valid_date & "/0" & date_arr(0)
valid_date = valid_date & "/" & date_arr(2)
valid_date = valid_date & " " & s_time
celda.Offset(0, 1).Value = CDate(valid_date)
End If
End If
End If
Next celda
End Sub
In order to use this code you should insert one empty column to the right from target. Second, you should to select entire C column and run the macro.
Edit 1. Ok, this macro autoselect column B. Select column dates is not necessary now.
Excel has parsed the dates according to your Windows Regional Settings short date format. Those that it could not parse (where the month>12) it left as text. Since there was initially a difference between the date format in the text file, and the date format in your Windows Regional settings, it is likely that many of the dates that appear as dates (or as unformatted numbers) were converted incorrectly.
You have a few options:
Import the text file using the Get External Data tab From Text option on the Data Ribbon. This will open up the text import wizard and allow you to specify the date format of the data being imported.
Change your Windows Regional settings short date format to match that in the text file.
Those are probably the two simplest options. The first can be automated through VBA. The second, not so much.

using IndexOf in Mid function

Perhaps this is a simple solution for most, but I can't get this to work like it should according to syntax.
I have this line of text "Part Number123456Price$50.00"
I want to pull the part number out of it, so I use this function...
str = Mid(str, str.IndexOf("Part Number") + 12, str.IndexOf("Price"))
My results are str = "123456Price$50.0" every time. I know the part number can vary in length so I need a solid solution of pulling this out.
It can be confusing to mix the legacy VB string methods (such as Mid) with the .Net string methods (like IndexOf). The VB methods use 1 as the index of the first character while the .Net methods use 0.
The following code will extract the part number from a string
Dim str As String = "Part Number123456Price$50.00"
Dim iPart As Integer = str.IndexOf("Part Number") + 11
Dim iPrice As Integer = str.IndexOf("Price")
str = str.Substring(iPart, iPrice - iPart).Trim
The Mid() function of Visual Basic is documented as having three arguments: (1) a string, (2) the beginning location in the string, and (3) the number of characters to copy.
So if your string is "Part Number123456Price$50.00" and you want to pull the part number as a series of digits, the "123456" part of the string, using the Mid() function then you need to find the beginning of the part number digit string and to then know the number of digits.
If your string is in the variable str then you can find the offset by something like str.IndexOf("Number") + len("Number") which will provide the offset to after the string "Number".
Next you need to find the number of digits so you would do something like str.IndexOf("Price") to find where the text "Price" begins and then subtract from that offset the offset of where the digits begin.
The result of all of this is you need a bit of code something like the following. I have not tested this source as I am not a VB programmer so it may need a tweak and you might want to put some checks on data validity as well.
Dim TextNumber as String = "Number"
Dim TextPrice as String = "Price"
iOffset = str.IndexOf(TextNumber) + len(TextNumber)
str = Mid(str, iOffset, str.IndexOf(TextPrice) - iOffset)
Alternatively, if Price is always the format $00.00, this will also work.
Dim str as String = "Part Number123456Price$50.00"
str = str.Remove(str.IndexOf("Price"))

Return the ISO code from a currency formatted cell

The user, through a userform, can insert a numeric value (say 1,000,000) and an ISO code (say USD). When he will validate, the value will be printed in range A1 and will be formatted as currency through the use of the following macro-recorded line of code:
.Range("A1").NumberFormat = _
"_-[$" & Me.ISOTextBox.Value & "] * #,##0.00_-;-[$" & Me.ISOTextBox.Value & "] * #,##0.00_-;_-[$" & Me.ISOTextBox & "] * ""-""??_-;_-#_-"
Basically, the above is the string to assign the .NumberFormat property; in the case of "USD", for example, the string will look like:
"_-[$USD] * #,##0.00_-;-[$USD] * #,##0.00_-;_-[$USD] * ""-""??_-;_-#_-"
My question is: if with the above string I set the number format, how could I get it?
I could clearly make string parsing, and this is the currently "horrible" solution I'm adopting for extracting the 3-letters ISO code:
ISOcode = Left(Replace(Split(Range("A1").NumberFormat, "[")(1), "$", ""), 3)
Note: the above code is splitting the all NumberFormat by [, hence taking the second element (starting with $USD), replacing the $ with "" and taking the first three letters, standing to the standard of ISO codes that are always 3-letters long).
Documentations are very poor on this: does anyone know if there's a way of properly get the ISO code from the currency format (without turning into an unelegant string parsing)?
I'm pretty sure you will need to parse the string, but the ISO code can be extracted slightly more cleanly using:
If InStr(Range("A1").NumberFormat, "[$") <> 0 Then _
ISOcode = Mid(Range("A1").NumberFormat, InStr(Range("A1").NumberFormat, "[$") + 2, 3)

How to split a String using multiple delimeters

I'm using a very particular program that doesn't have many pre loaded functions on it. I would like to split a Date and time into individual variables. 6 variables to be exact
I get the date and time like this 5/28/2014 15:34:40 so I have 3 characters "/" " " and ":" separating the 6 variables I want, but I can only get one to work at a time. I have tried many other ways but the x.Split() is the only syntax that this program seems to like (PARCView).
Dim x as String = "5/28/2014 15:34:40"
Dim y as String() = x.Split(New Char() {":"c})
So how can I add all three at once or use consecutive steps to store each number as a unique variable?
You actually have the Char Array that you need, though it only has one delineator... just fill it with the other delineators and it will split it for you.
Dim y As String() = x.Split(New Char() {":"c, "/"c, " "c})
example:
Another option is to parse it as a datetime object which will contain all the parts as properties:
Dim teststr = "5/28/2014 15:34:40"
Dim dt = DateTime.Parse(teststr)

EDIFACT How to group, spilt, sort and sum up values from a EDI string into variables in VB.NET

I am new to VB.Net 2008. I have a tricky task to resolve, it is regarding extracting characters (values) from a long string, the extracted values from the text shall be summed up and sorted by keywords, reformatted and saved into a CSV file.
It looks something like this but much longer :
UNH+RAM6957'COMPANY1BY500C10'ZEW+REQEST6957'COMPANY2SL200C20'COMPANY1SL300C10'ZEW
The values are seperated by ' .
As first step I splitted the string to make it readable, I used the function like:
Dim LineOfText As String
Dim i As Integer
Dim aryTextFile() As String
LineOfText = p_EDI
aryTextFile = LineOfText.Split("'")
For i = 0 To UBound(aryTextFile)
Console.WriteLine((aryTextFile(i)))
Next i
Now the result looks like:
UNB+UNOA:1+CCP:ZEW+STE:ZEW+100901:1200+2010917283
UNH+M000001+ORDRSP:D:96A:UN:EGT102
BGM+02G::ZEW+NOMRES24364+34
DTM+Z05:0:805
DTM+137:201009011000:203
DTM+Z01:201009090400201009100400:719
RFF+AHI:GSCOMPANY1
NAD+ZSO+CCP::ZEW
NAD+ZSH+GSSTATKRAFT::ZEW
TDT+41G++70
LOC+Z11+:::TTF
LIN+1+23
LOC+Z11+:::TTF
QTY+Z05:0:KW1
DTM+2:201009090400201009100400:719
NAD+ZUS+GSBNP::ZEW
LIN+2+23
LOC+Z11+:::TTF
QTY+Z05:0:KW1
DTM+2:201009090400201009100400:719
NAD+ZUS+GSBPA::ZEW
So far so good:
Now I have to extract the date and time from the header:
The line looks like:
**DTM+137**:201009011000:203 should look like
DTM+137:2010.09.01-10:00:203 and store it into a 'incomming_DTM' variable for example
Now the message period would be interresting to know:
The line looke like:
**DTM+Z01**:201009090400201009100400:719 the output should look like:
DTM+Z01 2010.09.09-04:00, 2010.09.10-04:00 and store it into 'period_DTM' variable
As next step I need to parse the next lines until it reaches the KEYWORD LIN
Like:
LIN+1+23
LOC+Z11+:::TTF
QTY+Z05:0:KW1
DTM+2:201009090400201009100400:719
NAD+ZUS+GSBNP::ZEW
NAD+ZSH+COMPANY1RPH N001::ZEW (P Character in word -> SELL QTY:0 KW/h)
LIN+2+23
LOC+Z11+:::TTF
QTY+Z05:0:KW1
DTM+2:201009090400201009100400:719
NAD+ZUS+GSBPA::ZEW
NAD+ZSH+COMPANY1RRH N001::ZEW (R Character in word -> BUY QTY:0 KW/h)
and store the KEYWORDS "QTY" "DTM" "NAD+ZSH" and its following Characters
into variables.
THEN I need to parse until it reaches the next LIN Keyword and store the
keywords there into vaiables again. The goal of this complicated exercise is,
to sum up values of QTY and NAD+ZSH+COMPANY1RVH and NAD+ZSH+COMPANY1RPH
If we have a closer look at the last zwo charaters in COMPANY1RRH and COMPANY1RPH
we see RH and PH, RH means buy and PH means sell.
Maybe it is possible to store BUY or SELL into a Contract vaiable for each LIN?
I need to sum up all sells and buys which where found in the string.
Every LIN marks a time period of one hour, so we have probably 24 series per
string which contains 24 LIN every LIN have a Time period, BUY or SELL keywords
and a Quantity.
Can someone please help me with this task?
As first step, storing the keywords and its follwoing characters into variables would
be a very good start. It might be very good to do that probably until the parser reaches the LIN, then store the found values into a CSV file or Array?, then parse until the next LIN and so on...
I would like to create a CSV file out of the results like: So the CSV should contain
24 records one per every hour per every LIN..
Dim csvData = Now & "," & "TRADED_QTY" & "," & DTM+Z01 & "," & "N" & "," & QTY & "," & "KWH/h" & "," & Contract
Console.WriteLine(csvData)
Creating the CSV File with True Flag -> Append data to CSV.
Dim csvFile As String = "C:\Test.csv"
Dim outFile As IO.StreamWriter = My.Computer.FileSystem.OpenTextFileWriter(csvFile, True)
Any ideas are highly welcome, I consider this as very complex task
espacial as I am really new to VB.NET.
Thank you in advance!
I see "EDI" in your code. If this is an EDI format, then you should have, or be able to get, some kind of EDI specification. Likely, it will be a fixed-length specification, meaning that "Value X is characters 1 to 9", "Value Y is characters 10 to 11", "Value Z is character 12", etc.
Here is one possible approach to parse out the KEYWORDS as first step:
Dim EDI As Object
EDI = dataReader(0)
'Convert EDI Object into a string and write it to the console.
Dim p_EDI As String = Convert.ToString(EDI)
'Create LineBreaks after every " ' "
Dim LineOfText As String
Dim i As Integer
Dim aryTextFile() As String
LineOfText = p_EDI
aryTextFile = LineOfText.Split("'")
'Starting with IF clause to find keywords
For Each line As String In aryTextFile
Console.WriteLine(line)
If line.StartsWith("UNB") Then
Dim foundUNB_Data = p_EDI.IndexOf("UNB")
'Start at that position and extract UNB + 27 characters
Dim UNBData = EDI.Substring(foundUNB_Data, 30)
Console.WriteLine(UNBData)
ElseIf line.StartsWith("LIN") Then
.
.
ElseIf line.StartsWith("QTY") Then
.
.
End If
Next
Any further ideas are highly welcome..
Thank you.