VBA Split string and convert to Int - vba

I have an Excel sheet where I have data in a column J4:J163, Each cell contains a string e.g. J4 = "1 6, 8 18, 20 24"
Using VBA I want to use the Split function to separate on the delimiter ','
then convert string values e.g. "1 6, 8 18, 20 24" into integers. Which should result into something like this '1 6' '8 18' '20 24'
I want to iterate through each two integer values subtracting like so
1-6 = 5
8-18 = 10
20-24 = 4
Each time adding these results to a variable i.e. 'total'
Depending on how many subtractions have been performed increment a variable, cnt++, in this case 3 times, (total + cnt).
total = 22
This result calculated from cell J4 i.e. 22 should be inputted into L4.
The result from J5 should be inputted into L5 etc.
Hope this makes sense.
Below is a very bare pseudo code, (newbie to VBA) your guidance would be well received.
Sub CalcHrs()
'Variables
Dim wrdArray() As String
Dim textString As String
Dim total As Integer 'substration results accumulation
Dim cnt As Integer 'for loop iteration count
' Grab String
textString = Range("J4")
' Place string into Array and Split
wrdArray() = Split(textString)
'Loop to convert string array to int array
'Some loop (i < array.length, bla bla)
'array index 0 - array index 1 place result into 'total'
'iterate through until length of array is reached, while cnt++
'place result of total + cnt into cell "L4"
'Move onto cell "J5" until "J163"
End Sub

Like somebody writted up. It's not a free "write-my-code" service, You should try yourself and If your code doesn't work then You can post it here to get help.
I will give you some tips:
Split the cell value like this: Split (Cell, ",")
Iterate the array result of this Split with for-each and split each value like this: Split(value, " ")
Add 1 to the normal count and add ABS(cint(value1) - cint(value2)) to the total count. Value1 and Value2 are the values retorned by the second split.

Related

Create time range based on time input

Greetings I would like to use a VBA to create a 30 minute time range (Column B) on worksheet "Inbound Fids". For example 1015 would become 0945-1045, 0015 would become 2345-0045. I am able to create this using the formula bar, but I have to add no less than five columns. The first added Column takes text and converts it into a time format =TIMEVALUE(LEFT(D2,2)&":"&MID(D2,3,2)). The second added column takes 30 minutes off the new column, =MOD(H2-0.5/24,1). The third added column adds 30 minutes to the first added column, =(H2+0.5/24). The fourth Column combines the 2nd and 3rd Column and converts it back to text, =TEXT(I2,"hh:mm")&"-"&TEXT(J2,"hh:mm"). The last column drops the Colon =SUBSTITUTE(K2,":",""). Can we work all this into a MACRO keeping the end result in Column B. I do realize that the format is not ideal, but we have to use military time where leading zeros will not be drop and not have a colon. Lastly, I would only want this to apply Column B where only cells with numbers are considered.
Try to paste this function to your vba editor and use it as a formula in your target cell
Function GET30MINRANGE(strTime As String) As String
Dim strRange, strHour, strMin, lowerBound, upperBound As String
Dim timeVal As Date
strMin = Mid(strTime, 3, 2)
strHour = Left(strTime, 2)
timeVal = Date + TimeValue(strHour & ":" & strMin)
lowerBound = Format(timeVal - TimeSerial(0, 30, 0), "hhnn")
upperBound = Format(timeVal + TimeSerial(0, 30, 0), "hhnn")
strRange = lowerBound & "-" & upperBound
GET30MINRANGE = strRange
End Function
Like so,
=GET30MINRANGE(B2)

Excel VBA Text to Columns Backwards with maximum # of columns

Apples, Oranges, Strawberries, Pears, Almonds, Peanuts, Peaches
I would like to find "," from backwards (instrrev) and perform something similar to text to columns function in Excel, which would
#1 > Apples, Oranges
#2 > Apples | Oranges
perform action that takes #1 to #2.
However, I would like to have maximum columns of 5 (split into 5 pieces and the split-base character searched from backwards)
so that the top example would result in:
Apples, Oranges, Strawberries | Pears | Almonds | Peanuts | Peaches
Please keep in mind that it is possible for the text to have no commas, so I need to check if they exists first
Thanks for the help!
Try this, by putting your example text in a cell, selecting that cell and then running the below. You will need to test this, and possibly handle some scenarios yourself - but this code should get you going and works on your example.
Sub SplitIntoColumns()
Dim intMaxCols As Integer
Dim intCommaFoundPos As Integer
Dim intNumCommasFound As Integer
Dim strTextToCheck As String
Dim strFoundText As String
Dim intRowToWriteTo As Integer
Dim intColToWriteTo As Integer
'this should be max num of columns you want -1
intMaxCols = 4
'just putting the text into the activecell and running on that
strTextToCheck = ActiveCell
'row to write output to
intRowToWriteTo = 10
'column to write output to - it will go backwards from here
intColToWriteTo = 10
'find the comma
intCommaFoundPos = InStrRev(strTextToCheck, ",")
'if there is a comma
If intCommaFoundPos > 0 Then
'loop until you have looped the max columns number of times, or until there are no commas left in the string
Do Until (intNumCommasFound = intMaxCols) Or intCommaFoundPos = 0
'get comma position
intCommaFoundPos = InStrRev(strTextToCheck, ",")
'if there is still a comma
If intCommaFoundPos > 0 Then
'keep track of the number found
intNumCommasFound = intNumCommasFound + 1
'take everything to right of comma
strFoundText = Trim(Mid(strTextToCheck, intCommaFoundPos + 1, Len(strTextToCheck)))
'write to sheet, adjust next column number
ActiveSheet.Cells(intRowToWriteTo, intColToWriteTo) = strFoundText
intColToWriteTo = intColToWriteTo - 1
'change the text to check to not include the word just found
strTextToCheck = Left(strTextToCheck, intCommaFoundPos - 1)
End If
Loop
'if there is any text left, write to sheet
If Len(strTextToCheck) > 0 Then ActiveSheet.Cells(intRowToWriteTo, intColToWriteTo) = strTextToCheck
End If
End Sub
You can also implement it in formula:
=IF(LEN(A3)-LEN(SUBSTITUTE(A3,",",""))<5,SUBSTITUTE(A3,",","|"),REPLACE(A3,FIND("#",SUBSTITUTE(A3,",","#",LEN(A3)-LEN(SUBSTITUTE(A3,",",""))-4))+1,LEN(A3),SUBSTITUTE(MID(A3,FIND("#",SUBSTITUTE(A3,",","#",LEN(A3)-LEN(SUBSTITUTE(A3,",",""))-4))+1,LEN(A3)),",","|")))
with the string in A3
How it works:
Find out the number of "," in the string by subtracting length of comma-less string from full string.
if less than 5 commas then substitute all "," with "|"
if equal to or more than 5 commas then, find the character position of the 5th comma from right,and replace the string after that character position with the substituted string.

Parse a text string into fields based on text and position VB

I have a .text file of strings delimited by spaces. That would be the obvious parsing solution when I bring it into Excel or Access, but since the strings are not the same size, the fields will be incorrect. I'm hoping to find some help here as I'm not really experienced with this.
This is an example section of the string:
259998887575 15 00:14:38 C33 0:14:42 T33 00:14:52 00:14:58
202224446898 33 00:16:24 B23 00:17:00 C31 00:17:15 T31 00:19:30 C04 00:17:15 T28 00:19:30 00:19:32
The numbers with colons are time stamps and the letter codes (T/C/B) all represent a different field type. My problem is that there can be any number of C and T time stamps listed in the string and there may or may not be a B time stamp.
I'd like the result to show 4 fields... the first, the first c time stamp, the last t time stamp and the last time stamp (the bolded time stamps). All other information can be disregarded. I'd like to use VB to cycle through due to the number of records.
Any help is appreciated!
Edit: It seems like you want to split the dates into types, determined by the bit before each letter.
You can use the Strings.Split method to divide the lines at the spaces. Then use the Date.TryParse method to check which parts are Dates (or times, it's the same). Then you select the first letter of the previous part and sort the dates into their respective lists.
Dim s As String = "202224446898 33 00:16:24 B23 00:17:00 C31 00:17:15 T31 00:19:30 C04 00:17:15 T28 00:19:30 00:19:32"
Dim parts() As String = Strings.Split(s, " ") 'Split the string at all spaces
'Create lists of Date, one list for all dates, one list for each Letter
Dim Tdates As New List(Of Date) 'This stores converted dates
Dim Cdates As New List(Of Date) 'This stores converted dates
Dim Bdates As New List(Of Date) 'This stores converted dates
Dim Alldates As New List(Of Date) 'This stores converted dates
For i = 0 To parts.Count - 1 'Iterate through all parts
Dim ThisDate As Date
If Date.TryParse(parts(i), ThisDate) = True Then 'This tries to parse the current part as a date, returns True if the part is a date
Alldates.Add(ThisDate) 'You want to store all dates in this list
If i > 0 AndAlso parts(i - 1).Length > 0 Then
Dim PrevPartsFirstLetter As String = parts(i - 1)(0) 'Crop the first letter of the previous part
Select Case PrevPartsFirstLetter
Case "T" : Tdates.Add(ThisDate)
Case "C" : Cdates.Add(ThisDate)
Case "B" : Bdates.Add(ThisDate)
End Select
End If
End If
Next
'You can now select the parts you want from the lists
The Tdates-List contains all dates which have a T thing before them and so on. The AllDates-List contains all dates in the line.

Array Calculation with CSV file

I am trying to work with taking in and parsing CSV files. Right now I have it taking in and producing something like this:
The program loads the csv and copies the data into an array as such:
ReDim strarray(num_rows, num_cols)
For x = 0 To num_rows
strline = strlines(x).Split(",")
For y = 0 To num_cols
strarray(x, y) = strline(y)
Next
Next
The CSV file data is very basic formatted with two columns and x number of rows:
212, 343
324, 232
etc. I guess my main problem is trying to perform calculations to all values in a specific column. To start I am just trying to figure out how to isolate the columns and found that by using MsgBox(strarray(x, num_cols)) it will msgbox everything in the second column twice. I just want to try and understand how I can perform a basic calculation like multiply every value in the first column by 2 and every value in the second column one by 3.
To start with: In VB arrays go from 0 to number of items minus 1. However you will have specify the maximum index, not the size:
Dim x As String() = new String(N-1) 'Where N is the number of items.
Dim y As String() = new String(MAX) 'Where MAX is the highest index.
And you have integer numbers. So you would have to declare:
Dim matrix As Integer(,) = new Integer(num_rows-1, num_cols-1)
And then fill it with:
For row As Integer = 0 To num_rows-1
Dim strline As String() = strlines(row).Split(",")
For col As Integer = 0 To num_cols-1
matrix(row, col) = Integer.Parse(strline(col))
Next
Next
Example calculation:
For row As Integer = 0 To num_rows-1
matrix(row,0) *= 2
matrix(row,1) *= 3
Next

VBA: preceding zeros dropped when copied over

I am creating a copy of an Excel file using VBA. In the file, there is a column that includes numbers with preceding zeros. The copy of the file is created, but the data in this column is dropped. I need to keep the values with the preceding zeros. How can I resolve this problem with VBA?
The best way is to pre-format the column as Text by setting Range.NumberFormat to "#". This way, if a user edits the cell, the cell will stay as text and maintain it's leading zeros. Here is a VBA example:
ActiveSheet.Range("C:C").NumberFormat = "#"
Convert each cell in that column to a text field prior to exporting it. That should ensure that every character is retained (and not treated like a number, which is what it sounds like is happening).
An additional possibility is to append an apostrphe to each cell. This will treat all the values as text which is useful when different tabs treat common values as text vs number (ie copied in vs calculated).
This is done by using the Chr() function and assigning it the character code 39('):
For x = 1 to 100
If Sheets(origSheet).Cells(x, "A").Value <> "" Then
Sheets(origSheet).Cells(x, "A").Value = Chr(39) & Sheets(origSheet).Cells(x, "A").Value
End If
Given the accepted answer, it's probably not what you need, but setting a custom number format will also get the preceeding zeroes back into the displayed value.
To show a value with leading zeroes up to 8 digits, for example, set the format to 00000000, then 123 will be displayed as 00000123.
Both the method here and the format-as-text method will result in cell values that will still work in calculations, although horizontal alignment will be different by default. Note also that, for example, concatenating strings to the values will result in differences:
as text: displays 00000123, append "x" to get 00000123x
as number with custom format: displays 00000123, append "x" to get 123x, because it's still really a number.
Probably TMI, though!
This is the code I have created to resolve this issue:
Public Sub Change_10_Digit()
'----------------------------------------------------------------------------
' Change numeric loan number ot a 10 digit text number
' 2010-05-21 by Jamie Coxe
'
' Note: Insure exracted data Column is formated as text before running macro
'----------------------------------------------------------------------------
Dim Lastrow As Long
Dim StartRow As Long
Dim Col As String
Dim RowNum As Long
Dim nCol As String
Dim Loan As String
Dim Digit_Loan As String
Dim MyCell As String
Dim NewCell As String
Dim Cell_Len As Long
Dim MyOption As Long
'----- Set Options -------------------------------------------------------
MyOption = 2 '1 = place data in new column, 2 = Replace data in cell
StartRow = 2 'Start processing data at this row (skip header row)
Col = "B" 'Loan number in this colmun to be changed to 10 digit
nCol = "G" 'New column to place value (option 1 only)
'----- End Option Setings ------------------------------------------------
'Get last row
Lastrow = Range(Col & "65536").End(xlUp).Row
For RowNum = StartRow To Lastrow
'Combined Column and Row number to get cell data
MyCell = Col & RowNum
'Get data in cell
Loan = Range(MyCell).Value
'Change data in cell to 10 digit numeric with leading zeros
Digit_Loan = Format(Loan, "0000000000")
If My0ption = 1 Then
'Option 1 enter value in new cell
NewCell = nCol & RowNum
Range(NewCell).Value = Digit_Loan
Else
'Option 2 replace value in cell
Range(MyCell).Value = Digit_Loan
End If
Next RowNum
End Sub