Create time range based on time input - vba

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)

Related

How to put character if there is one digit in cell in VBA Macro?

I would like to ask, how to put character, in this case 0 to cell, if the cell already contains digit in it.
To clarify what do I mean, if on the cell is number 5, I would like to put before the number 5, number 0 to have the result 05.
As far as I know, cell format should be TEXT to avoid automatic Excel correction. But, this question is specific due to several different characters in the cells. In some point I got in the same column different characters in the cells (1, 2, 3, AV, AR, IX etc.).
For example: I would like to select column K, find the numeric characters with one digit (1, 2, 3, -9) and paste there 0 before it to have two space digit like 01, 02, 03, …
Of course, with macro. I know how to put Text format to it, but do not know how to manage the whole macro function to select column K, format whole column as text, find one digit number in the column and paste 0 before it.
Does anybody know how to do that?
Many thanks in advance.
There are 2 solutions:
Format the numbers
Convert numbers to text and format them
1. Format the numbers
The advantage of this solution is that the numbers will still be numbers (not text) but formatted with leading zeros. Therefore you still can calculate with these numbers as before.
Public Sub ChangeNumberFormat()
ThisWorkbook.Worksheets("YourDesiredSheetName").Columns("K").NumberFormat = "00"
'this will keep them numbers but only change the format of them
End Sub
Note that you don't need to do this necessarily with VBA you can just set a user defined cell format 00 for column K (open format cells with Ctrl + 1).
2. Convert numbers to text and format them
If you really need to convert them to text this would be a possible solution. But I really don't recommend that because you cannot calculate with these "numbers" anymore because they are converted to text.
The trick would be to format the number with numberformat first and then convert it to text (see comments in the code).
Option Explicit 'force variable declaring
Public Sub FixLeadingZerosInText()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("YourDesiredSheetName") '<-- change your sheet name here
Dim lRow As Long
lRow = ws.Cells(ws.Rows.Count, "K").End(xlUp).Row 'find last used row in column K
Dim iCell As Range
For Each iCell In ws.Range("K1:K" & lRow) 'loop from row 1 to last used in column K
If iCell.Value < 10 And iCell.Value > -10 Then 'check if it is a one digit number
Dim tmpText As String
tmpText = Format(iCell.Value, "00") 'format the one digit number
iCell.NumberFormat = "#" 'convert number to text
iCell.Value = tmpText 're-write formatted number
End If
iCell.NumberFormat = "#" 'make all other numbers in column K formatted as text too
Next iCell
End Sub

How to convert Quarter years to other format

I have cells that can either contain time in this format:
1625 (16 for 2016 and 25 for week 25)
Or in this format
2016-Q2 (Q2 means quarter 2 if the year)
When converting I want quarters to be the mid week of the quarter
2016-Q1 = 1608
2016-Q2 = 1620
2016-Q3 = 1633
2016-Q4 = 1646
I dont want to convert the times in the cell its in. I want to convert it to YYWW format for a formula for a timeline in another sheet. So I use help cells with the converted value and reference those instead of the values in the other sheet.
I have done this with nested if functions resulting in mile long formulas because the timeline needs to be very long and the time can very well be 2025-Q3.
a =IF('Gulpilspuls NT'!U4="2016-Q1";1608;IF('Gulpilspuls NT'!U4="2016-Q2";1620;IF('Gulpilspuls NT'!U4="2016-Q3";1633;IF('Gulpilspuls NT'!U4="2016-Q4";1646;IF('Gulpilspuls NT'!U4="2017-Q1";1708;IF('Gulpilspuls NT'!U4="2017-Q2";1720;IF('Gulpilspuls NT'!U4="2017-Q3";1733;IF('Gulpilspuls NT'!U4="2017-Q4";1746;IF('Gulpilspuls NT'!U4="2018-Q1";1808;IF('Gulpilspuls NT'!U4="2018-Q2";1820;IF('Gulpilspuls NT'!U4="2018-Q3";1833;IF('Gulpilspuls NT'!U4="2018-Q4";1846;IF('Gulpilspuls NT'!U4="2019-Q1";1908;IF('Gulpilspuls NT'!U4="2019-Q2";1920;IF('Gulpilspuls NT'!U4="2019-Q3";1933;IF('Gulpilspuls NT'!U4="2019-Q4";1946;IF('Gulpilspuls NT'!U4="2020-Q1";2008;IF('Gulpilspuls NT'!U4="2020-Q2";2020;IF('Gulpilspuls NT'!U4="2020-Q3";2033;IF('Gulpilspuls NT'!U4="2020-Q4";2046;IF('Gulpilspuls NT'!U4="2021-Q1";2108;IF('Gulpilspuls NT'!U4="2021-Q2";2120;IF('Gulpilspuls NT'!U4="2021-Q3";2133;IF('Gulpilspuls NT'!U4="2021-Q4";2146;IF('Gulpilspuls NT'!U4="2022-Q1";2208;IF('Gulpilspuls NT'!U4="2022-Q2";2220;IF('Gulpilspuls NT'!U4="2022-Q3";2233;IF('Gulpilspuls NT'!U4="2022-Q4";2246;IF('Gulpilspuls NT'!U4="2023-Q1";2308;IF('Gulpilspuls NT'!U4="2023-Q2";2320;IF('Gulpilspuls NT'!U4="2023-Q3";2333;IF('Gulpilspuls NT'!U4="2023-Q4";2346;IF('Gulpilspuls NT'!U4="2024-Q1";2408;IF('Gulpilspuls NT'!U4="2024-Q2";2420;IF('Gulpilspuls NT'!U4="2024-Q3";2433;IF('Gulpilspuls NT'!U4="2024-Q4";2446;IF('Gulpilspuls NT'!U4="2025-Q1";2508;IF('Gulpilspuls NT'!U4="2025-Q2";2520;IF('Gulpilspuls NT'!U4="2025-Q3";2533;IF('Gulpilspuls NT'!U4="2025-Q4";2546;IF('Gulpilspuls NT'!U4="2026-Q1";2608;IF('Gulpilspuls NT'!U4="2026-Q2";2620;IF('Gulpilspuls NT'!U4="2026-Q3";2633;IF('Gulpilspuls NT'!U4="2026-Q4";2646;IF('Gulpilspuls NT'!U4="2027-Q1";2708;IF('Gulpilspuls NT'!U4="2027-Q2";2720;IF('Gulpilspuls NT'!U4="2027-Q3";2733;IF('Gulpilspuls NT'!U4="2027-Q4";2746;IF('Gulpilspuls NT'!U4="2028-Q1";2808;IF('Gulpilspuls NT'!U4="2028-Q2";2820;IF('Gulpilspuls NT'!U4="2028-Q3";2833;IF('Gulpilspuls NT'!U4="2028-Q4";2846;IF('Gulpilspuls NT'!U4="2029-Q1";2908;IF('Gulpilspuls NT'!U4="2029-Q2";2920;IF('Gulpilspuls NT'!U4="2029-Q3";2933;IF('Gulpilspuls NT'!U4="2029-Q4";2946;IF('Gulpilspuls NT'!U4="2030-Q1";3008;IF('Gulpilspuls NT'!U4="2030-Q2";3020;IF('Gulpilspuls NT'!U4="2030-Q3";3033;IF('Gulpilspuls NT'!U4="2030-Q4";3046;IF('Gulpilspuls NT'!U4="2031-Q1";3108;IF('Gulpilspuls NT'!U4="2031-Q2";3120;IF('Gulpilspuls NT'!U4="2031-Q3";3146;IF('Gulpilspuls NT'!U4="2031-Q4";3146;IF('Gulpilspuls NT'!U4="2032-Q1";3208;IF('Gulpilspuls NT'!U4="2032-Q2";3220;IF('Gulpilspuls NT'!U4="2032-Q3";3233;IF('Gulpilspuls NT'!U4="2032-Q4";3246;IF('Gulpilspuls NT'!U4="2033-Q1";3308;IF('Gulpilspuls NT'!U4="2033-Q2";3320;IF('Gulpilspuls NT'!U4="2033-Q3";3333;IF('Gulpilspuls NT'!U4="2033-Q4";3346;IF('Gulpilspuls NT'!U4="2034-Q1";3408;IF('Gulpilspuls NT'!U4="2034-Q2";3420;IF('Gulpilspuls NT'!U4="2034-Q3";3433;IF('Gulpilspuls NT'!U4="2034-Q4";3446;IF('Gulpilspuls NT'!U4="2035-Q1";3508;IF('Gulpilspuls NT'!U4="2035-Q2";3520;IF('Gulpilspuls NT'!U4="2035-Q3";3533;IF('Gulpilspuls NT'!U4="2035-Q4";3546;IF('Gulpilspuls NT'!U4="2036-Q1";3608;IF('Gulpilspuls NT'!U4="2036-Q2";3620;IF('Gulpilspuls NT'!U4="2036-Q3";3633;IF('Gulpilspuls NT'!U4="2036-Q4";3646;IF('Gulpilspuls NT'!U4="2037-Q1";3708;IF('Gulpilspuls NT'!U4="2037-Q2";3720;IF('Gulpilspuls NT'!U4="2037-Q3";3733;IF('Gulpilspuls NT'!U4="2037-Q4";3746;IF('Gulpilspuls NT'!U4="2038-Q1";3808;IF('Gulpilspuls NT'!U4="2038-Q2";3820;IF('Gulpilspuls NT'!U4="2038-Q3";3833;IF('Gulpilspuls NT'!U4="2038-Q4";3846;'Gulpilspuls NT'!U4))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
As you can clearly see this method is not the best. I cant make it this long because nested if functions can only contain 64 levels of nesting. Do you guys have a better suggestion for this?
The formula has to work with both formats of time entry and I need it to be able to convert all the cells 1:1 meaning 1 cell in the calendar has to be 1 converted cell in the other spot that I can use for the formula. If the cell in the calendar does not have YYYY-Q1234? it should just show what it is instead as you can see at the end of my formula.
Here is your formula.
=IF(AND(LEN(C6)=4,ISERROR(FIND("-",C6))),C6,MID(C6,3,2)&INDEX({"08",20,33,46},RIGHT(C6,1)))
Make sure there is no excess space in your data. Not like this "2016-Q1 ", but like this "2016-Q1".
EDIT: I just realized that if the original is in the format of YYWW, that you do NOT want it changed to the mid quarter week number. So we simplify the formulas:
=IF(ISNUMBER(-A1),A1,MID(A1,3,2) & CHOOSE(RIGHT(A1,1),"08",20,33,46))
and if you want YYWW to always be rendered as numeric:
=1*IF(ISNUMBER(-A1),A1,MID(A1,3,2) & CHOOSE(RIGHT(A1,1),"08",20,33,46))
And here are the results for various samples:
EDIT: If you need to check for blanks, you can do this simply:
=IF(LEN(A1)=0,"",1*IF(ISNUMBER(-A1),A1,MID(A1,3,2) & CHOOSE(RIGHT(A1,1),"08",20,33,46)))
However, if a 0 will not result in a downstream problem, you can use the original, shorter formula, and merely use a custom format to suppress zero returns: 0;;
And if you need to check for other conditions for which you don't want to process, you can perform similar actions.
something like this should do it, however, mid way through Q1, is week 6, so you'll need to adjust if your year doesn't start at 1/1
Function get_week(strInput As String) As String
Dim strQ As String
Dim bytQ As Byte
Dim dblMultiplier As Double
Dim intWeekNumber As Integer
strQ = Split(strInput, "-")(0)
bytQ = CByte(Right(strQ, 1))
dblMultiplier = (bytQ - 1) / 4
intWeekNumber = (dblMultiplier * 52)
intWeekNumber = intWeekNumber + (13 / 2)
get_week = Split(strInput, "-")(1) & "-" & CStr(intWeekNumber)
End Function
Let me try again
="20"&LEFT(N5,2)&IF(MOD(N5,100)<=8,"-Q1",IF(MOD(N5,100)<=20,"-Q2",IF(MOD(N5,100)<=33,"-Q3",if(MOD(N5,100)<=46,"-Q4","-Q1"))))
Should work for everything past year 2000 ;)

VBA Split string and convert to Int

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.

Excel: macro to auto-format time (without date)

I'm looking for a simple macro to specify cells as being of type "time" and typing only numbers (for example "955") will format that (and recognise as) "hh:mm" time. In other words, by typing "955", the cell would interpret to "09:55", whereas all I can have it do right now is interpret to "1902-08-12 00:00:00" (most likely 955 is the day number for 1902-08-12).
EDIT:
Part of the need for this is to allow calculation of times post typing (for example, substract two time values to get a timespan, or add several timespans to get a total).
VBA code:
Dim val As String
val = myCell.Value
Dim newval As String
If Len(val) = 2 Then
newval = "00:" & val
ElseIf Len(val) = 3 Then
newval = "0" & Left(val, 1) & ":" & Right(val, 2)
ElseIf Len(val) = 4 Then
newval = Left(val, 2) & ":" & Right(val, 2)
Else
newval = "Not a valid time"
End If
myCell.Value = newval
This code does not detect if the last two digits are a valid time (greater than 59 minutes), but otherwise it should handle most cases.
You'll also need to add a case if someone types in 1 digit, ie. 1 thru 9 minutes after midnight.
If you want it to be formatted as an actual time (date-time type), then change the formatting of the cell to hh:mm.
The value typed in, for example 955, must be manipulated to produce a fraction of a day.
pseudocode:
(left(myCell,len(myCell)-2) + (right(myCell,2)/60)) / 24
This produces the proper decimal value for how much of the day has elapsed and thus will display as a proper 'Time' in the cell with hh:mm formatting.
This isn't the VBA, but a formula that will change the formatting. You could incorporate this into VBA if you wanted to, but should help as a jumping point.
=TIMEVALUE(IF(LEN(A5)=3,"0"&LEFT(A5,1)&":",LEFT(A5,2)&":")&RIGHT(A5,2))
(If A5 is the cell where you enter 955)
(Also, make sure to format the formula cell as your desired time formatting.)
I can help with the code if needed. Just post back.
For some reason Excel does not allow to use ":" in your custom format.
But if you OK with another delimiter, say dash "-", then you can simply create a custom format like this: ##-##
Of course your time has to be in 24 hours format.
Alternatively, you may first enter all your times just like numbers (or better as text if you don't want to lose trailing zeros). And then run your script to insert semicolons between hours and minutes.

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