How to split date and time - excel

I would like to know how to split date and time into separate rows.
I would like Date in Column A and time in Column B with AM/PM included.
I tried with a delimiter of space but I get errors. On the internet people were first selecting cells but I want to do it without selecting cells.
Sub CompareTime()
Dim ws As Worksheet
Dim lastRow As Long
Dim arr As Long
Dim test As Double
Set ws = ActiveSheet
Cells(1, 2).EntireColumn.Insert
'Find last data point
With ws
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
For Count = 1 To lastRow
'split date
Cells(1, Count).Offset(0, 1) = Split(Cells(1, Count).Value, " ")
Next Count
End Sub

Date/time is a number and not a text string so to get the date you need to plit the integer from the decimal, then format them:
Sub CompareTime()
Dim ws As Worksheet
Dim lastRow As Long
Dim Count As Long
Dim test As Double
Set ws = ActiveSheet
'Find last data point
With ws
.Columns(2).Insert
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
For Count = 5 To lastRow
'split date
test = .Cells(Count, 1).Value2
.Cells(Count, 1).Value2 = Int(test)
.Cells(Count, 1).NumberFormat = "m/d/yyyy"
.Cells(Count, 1).Offset(0, 1).Value2 = test - Int(test)
.Cells(Count, 1).Offset(0, 1).NumberFormat = "hh:mm AM/PM"
Next Count
End With

The other method. Scott's code more simple.
Sub CompareTime()
Dim ws As Worksheet
Dim lastRow As Long
Dim arr As Long
Dim test As Double
Dim vDB, vR(), n As Long, i As Long
Set ws = ActiveSheet
'Find last data point
With ws
.Cells(1, 2).EntireColumn.Insert
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
vDB = .Range("a5", "a" & lastRow)
n = UBound(vDB, 1)
ReDim vR(1 To n, 1 To 2)
For i = 1 To n
vR(i, 1) = DateValue(Format(vDB(i, 1), "yyyy/mm/dd"))
vR(i, 2) = TimeValue(Format(vDB(i, 1), "hh:mm"))
Next i
.Range("a5").Resize(n, 2) = vR
.Columns(1).NumberFormatLocal = "mm/dd/yyyy"
.Columns(2).NumberFormatLocal = "hh:mm"
End With
End Sub

So I found a super easy way after messing with the split function. I just used a delimiter of space and split the date from time with AM/PM included.
Sub CompareTime()
Dim ws As Worksheet
Dim count As Long
Dim lastRow As Long
Dim arr As Long
Dim store As Double
Set ws = ActiveSheet
Cells(1, 2).EntireColumn.Insert
'Find last data point
With ws
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
For Count = 5 To lastRow
'split date
Cells(Count, 1).Offset(0, 1).Value = Split(Cells(Count, 1), " ")(1) & " " & Split(Cells(Count, 1), " ")(2)
Cells(Count, 1).Value = Split(Cells(Count, 1), " ")
Next Count
End Sub

Related

How to write Pythagoras formula in excel VBA, like I need to select all the values of column A and column B

Sub MS()
Data = Sheets("Tabelle1").Select
Rows("1:1").Select
Rows("11409:11409").Select
Dim bilder As Long
Dim n As Long
Dim d As Long
Dim t As Long
bilder = 64
n = 1
d = 0
t = 0
'Dim i As Long
'For i = 1 To lastrow
Range("a1:a" & Cells(Rows.Count, 1).End(xlUp).Row).Select
Range("b1:b" & Cells(Rows.Count, 1).End(xlUp).Row).Select
'Range("a1").Select
'Range("b1").Select
Range("a1,b1").Select
Do While ActiveCell.Value <> ""
Radius = Sqr(Range("A1").Value * Range("A1").Value + Range("B1").Value * Range("B1").Value)
ActiveCell.Offset(1, 1).Select
Loop
End Sub
I'm not sure why you'd want to do it this way (given that it can be done with a simple formula in-cell), but looking at the remnants of code in your question we can see what you're trying to achieve. Here's how I'd do it:
Sub MS()
Dim sht As Worksheet, StartRow As Long, LastRow As Long, OutputColumn As Long
Dim SideA As Double, SideB As Double, SideC As Double
With Worksheets("Tabelle1")
'Set StartRow to the first row of your data ignoring headers
StartRow = 2
'Locate LastRow as last occupied cell in column A
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
'Set OutputColumn to 3
OutputColumn = 3
'Start loop
For r = StartRow To LastRow
SideA = .Cells(r, 1).Value
SideB = .Cells(r, 2).Value
SideC = Sqr(SideA * SideA + SideB * SideB)
.Cells(r, OutputColumn).Value = SideC
Next
End With
End Sub
Output:
You do not need to select the range to work with it. You may want to see How to avoid using Select in Excel VBA
In your code you are not writing the output to any cell. Here are two ways that will help you achieve what you want.
NON VBA - WAY 1
Put the formula =SQRT(A1*A1+B1*B1) or =SQRT(A1^2+B1^2) in C1 and drag it down
VBA - WAY 2 (Without Looping)
Option Explicit
Sub Sample()
Dim ws As Worksheet
Dim lRow As Long
Set ws = Sheets("Tabelle1")
With ws
lRow = .Range("A" & .Rows.Count).End(xlUp).Row
With .Range("C1:C" & lRow)
.Formula = "=SQRT(A1*A1+B1*B1)"
.Value = .Value
End With
End With
End Sub
VBA - WAY 3 (Without Looping) Slightly complicated way of doing this. Explanation can be seen HERE
Option Explicit
Sub Sample()
Dim ws As Worksheet
Dim lRow As Long
Set ws = Sheets("Tabelle1")
With ws
lRow = .Range("A" & .Rows.Count).End(xlUp).Row
With .Range("C1:C" & lRow)
.Value = Evaluate("index(SQRT((A1:A" & lRow & _
")^2+(B1:B" & lRow & _
")^2),)")
End With
End With
End Sub

VBA / Copy the Max of column and the the date in the same row and previous column and paste into new sheet

I want to find the max of a column and the the date in the same row and previous column and paste into a new sheet.
Please, ignore the comments. I tried over and over just hoping make it work but unfortunately didn't.
Ia appreciate your time and help!!!!!!!
Sub FloodFreqCurve()
'Dim MaxAddr As Variant
Dim MaxN As Integer
Dim rng As Range
Dim i As Integer
Dim Rw As Integer
Dim y As Integer
Dim CopyMax As Range
Dim a As Integer
Dim b As Integer
For i = 2 To 100 Step 2
Worksheets("Discharge").Activate
'MaxN = Worksheets("Discharge").Application.WorksheetFunction.Max(Columns(2))
'Columns(2).Find(MaxN, , xlValues).Row
'This part was from Snakehips
Set rng = Worksheets("Discharge").Columns(i) 'or whatever
Mx = WorksheetFunction.Max(rng)
Rw = WorksheetFunction.Match(Mx, rng, 0) + rng.Row - 1
'-------------------------------
If y = i - 1 > 0 Then
a = Cells(Rw, y).Value
b = Cells(Rw, a).Value
'CopyMax.Copy
'Cells(1, 1).Value = Rw
'Range(Cells(3, 1), Cells(3, 2)).Copy
'Range(
'Cells(Rw, i).Copy ', Cells(Rw, y)).Copy
'Selection.Copy
'CopyMax.Select
'Selection.Copy
'Range("A1").Paste
'MaxAddr = Application.WorksheetFunction.CELL("ADDRESS", Index(Columns(2), Match(Max(Columns(2)), Columns(2), 0)))
'RowNo = Application.WorksheetFunction.Match(Max(Columns(2)), Columns(2))
'MaxAddr.Select
'r = ActiveCell.Row
'ActiveSheet.Range(Cells(r, i), Cells(r - 1, i - 1)).Select
'Worksheets("FLOOD-FREQUENCY CURVE").Activate
'.Paste
End If
Worksheets("FLOOD-FREQUENCY CURVE").Activate
Cells(i, 1).Value = a
Cells(i, 2).Value = b '.PasteSpecial xlPasteAll
Next i
End Sub
Option Explicit
Sub test()
Dim ws1 As Worksheet, ws2 As Worksheet
Dim LastRow1 As Long, LastCol1 As Long, LastRow2 As Long, Column As Long, Row As Long
Dim iDate As Date
Dim Amount As Double
Set ws1 = ThisWorkbook.Worksheets("Sheet1")
Set ws2 = ThisWorkbook.Worksheets("Sheet2")
LastCol1 = ws1.Cells(2, ws1.Columns.Count).End(xlToLeft).Column
For Column = 10 To LastCol1 Step 2
With ws1
LastRow1 = .Cells(.Rows.Count, Column).End(xlUp).Row
Amount = 0
iDate = Empty
For Row = 3 To LastRow1
If .Cells(Row, Column).Value > Amount Then
Amount = .Cells(Row, Column).Value
iDate = .Cells(Row, Column - 1).Value
End If
Next Row
End With
With ws2
LastRow2 = .Cells(.Rows.Count, "A").End(xlUp).Row
.Range("A" & LastRow2 + 1).Value = iDate
.Range("B" & LastRow2 + 1).Value = Amount
End With
Next Column
End Sub
I think this will do what you require. You can modify it to fit your needs, but it works fine on my side. The main sub to call is MoveMaxValuesFromColumns(). You will notice that I used if dblTemp >= dblMax then add to max list. this can be changed to only get the maximum once by the following dblTemp > dblMax. Finally, I did the comparison using doubles however, you can modify it to use whatever value you prefer, even variants if you like. I hope this helps.
Option Explicit
Public Sub MoveMaxValuesFromColumns()
Dim lngI As Long
Dim strSheet As String
Dim strCol As String
Dim strSplit() As String
Dim strFrom as string
Dim strTo as string
strFrom = "Sheet1"
strTo = "Sheet2"
With ThisWorkbook.Worksheets(strFrom)
For lngI = 2 To 100 Step 2
strCol = .Cells(1, lngI).Address(ColumnAbsolute:=True)
'Now, Parse the $'s out to get just the column!
strSplit = Split(strCol, "$")
strCol = strSplit(1)
'call the MoveMax routine
MoveMax strCol, strFrom, strTo
Next lngI
End With
End Sub
Private Sub MoveMax(strInColumn As String, strFromSheet As String, strToSheet As String)
Dim rng As Range
Dim dblMax As Double
Dim dblTemp As Double
Dim strMySheet As String
Dim strTransferSheet As String
Dim lngLastRow As Long
Dim lngI As Long
Dim lngJ As Long
Dim strOutVals() As String
Dim strTemp As String
Dim intCnt As Integer
Dim lngColOffset As Long
strMySheet = strFromSheet
strTransferSheet = strToSheet
With ThisWorkbook.Worksheets(strMySheet)
lngColOffset = .Range(strInColumn & ":" & strInColumn).Column
lngLastRow = .Range(strInColumn & .Range(strInColumn & ":" & strInColumn).Rows.Count).End(xlUp).Row
Set rng = .Range(strInColumn & "1:" & strInColumn & lngLastRow).Cells
dblMax = -1.79769313486231E+308 'Set the max to the double precision absolute minimum!
ReDim strOutVals(0 To (rng.Rows.Count - 1), 0 To 1)
For lngI = 1 To rng.Rows.Count
strTemp = rng.Cells(lngI, 1).Value
If IsNumeric(strTemp) Then
dblTemp = CDbl(strTemp)
If dblTemp >= dblMax Then
dblMax = dblTemp
End If
End If
Next lngI
'Now, loop through again and get the max's
intCnt = 0
For lngI = 1 To rng.Rows.Count
strTemp = rng.Cells(lngI, 1).Value
If IsNumeric(strTemp) Then
dblTemp = CDbl(strTemp)
If dblTemp >= dblMax Then
strOutVals(intCnt, 1) = rng.Cells(lngI, 1).Value
strOutVals(intCnt, 0) = rng.Cells(lngI, 1).Offset(0, -1).Value
intCnt = intCnt + 1
End If
End If
Next lngI
End With
'Finally, Write out to new Sheet
With ThisWorkbook.Worksheets(strTransferSheet)
For lngI = 0 To (intCnt - 1)
For lngJ = 0 To UBound(strOutVals, 2) 'This is just 1
.Cells(lngI + 1, lngColOffset + lngJ - 1).Value = strOutVals(lngI, lngJ)
Next lngJ
Next lngI
End With
Set rng = Nothing
End Sub

How to make a simple "Sum" loop faster?

I am beginning to learn how to use loops and arrays but this one has me stuck. Below is a code that loops through cells and adds them together in column P.
Sub Loop_Test()
Dim sht1 As Worksheet
Dim lr As Long
Dim i As Long
Set sht1 = Worksheets("Sheet1")
lr = Fcst.Cells(Rows.Count, "A").End(xlUp).Row
With sht1
For i = 4 To lr
.Range("P" & i).Value = Application.Sum(Range("D" & i, "O" & i))
Next
End With
End Sub
Overall, this code works but it is very slow and I need to apply it to thousands of rows. I know that in order to make this faster, I need to turn the sum range into an array but I am not entirely sure how to do this when a loop is included.
Any help would be greatly appreciated.
Thanks,
G
Disclaimer: I know there are more efficient ways to sum cells together but this is just me playing around and learning.
Just do them all at once. Looping only adds time to process individual iterations.
With sht1.Range(sht1.cells(4, "P"), sht1.cells(lr, "P"))
.formula = "=sum(D4:O4)"
.Value = .value
End With
Use a variant array to limit the number of times that the vba accesses the worksheets:
Sub Loop_Test()
Dim sht1 As Worksheet
Set sht1 = Worksheets("Sheet1")
Dim fcst As Worksheet
Set fcst = Worksheets("Sheet2")
Dim lr As Long
lr = fcst.Cells(Rows.Count, "A").End(xlUp).Row
Dim dta As Variant
dta = fcst.Range(fcst.Cells(4, "D"), fcst.Cells(lr, "O")).Value
Dim otpt As Variant
ReDim otpt(1 To UBound(dta, 1), 1 To 1)
With sht1
Dim i As Long
For i = LBound(dta, 1) To UBound(dta, 1)
otpt(i, 1) = Application.Sum(Application.Index(dta, i, 0))
Next i
.Range("P4").Resize(UBound(dta, 1), 1).Value = otpt
End With
End Sub
Edit
The SUM(INDEX()) is slow it is quicker just to add the parts individually.
Sub Loop_Test()
Dim sht1 As Worksheet
Set sht1 = Worksheets("Sheet1")
Dim fcst As Worksheet
Set fcst = Worksheets("Sheet2")
Dim lr As Long
lr = fcst.Cells(Rows.Count, "A").End(xlUp).Row
Dim dta As Variant
dta = fcst.Range(fcst.Cells(4, "D"), fcst.Cells(lr, "O")).Value
Dim otpt As Variant
ReDim otpt(1 To UBound(dta, 1), 1 To 1)
With sht1
Dim i As Long
For i = LBound(dta, 1) To UBound(dta, 1)
Dim j as Long
For j = lbound(dta,2) to ubound(dta,2)
otpt(i, 1) = otpt(i, 1) + dta(i, j)
Next j
Next i
.Range("P4").Resize(UBound(dta, 1), 1).Value = otpt
End With
End Sub
Tested on 50,000 rows and result was near instantaneous.
Rather than looping over each row you can insert a summation formula into each row of column P with a single line of code:
.Range("P4:P" & lr).Formula="=SUM(D4:O4)"
assuming 4 is the starting row, and your variable lr is the last row.
Faster With an Array
Sub Loop_Test()
Const cSheet1 As Variant = "Sheet1"
Const cSheet2 As Variant = "Sheet2"
Const fr As Integer = 4
Dim sht1 As Worksheet
Dim fcst As Worksheet
Dim lr As Long
Dim i As Long
Dim vnt As Variant
Set sht1 = Worksheets(cSheet1)
Set fcst = Worksheets(cSheet2)
With fcst
lr = .Cells(.Rows.Count, "A").End(xlUp).Row
ReDim vnt(1 To lr - fr + 1, 1 To 1)
For i = 1 To UBound(vnt)
vnt(i, 1) = WorksheetFunction.Sum( _
.Range("D" & i + fr - 1, "O" & i + fr - 1))
Next
End With
sht1.Cells(fr, "P").Resize(UBound(vnt)) = vnt
End Sub

Excel - Fill with blocks of dates

I am looking to fill a spreadsheet with data repeating data, so 25 appointments for today, 25 appointments for tomorrow with the same name and so on for as far as possible.
Is the a simple way of filling the table where the date increases in blocks of 25?
Example of what i am trying to do
Try using this you might be able to achieve what you want ,any problems shout out
'to change the date to the next day
Public Function ExtraDay(strDate As String)
Dim tDay As Date
tDay = Format(DateAdd("d", 1, strDate), "dd/mm/yy")
ExtraDay = tDay
End Function
'gets the last used row
Function getThelastUsedRowAddress() As Integer
'Get Last Row in Worksheet UsedRange
Dim LastRow As Range, ws As Worksheet
Set ws = ActiveSheet
MsgBox ws.UsedRange.Rows(ws.UsedRange.Rows.Count).Row
getThelastUsedRowAddress = ws.UsedRange.Rows(ws.UsedRange.Rows.Count).Row
End Function
'button command on the sheet
Private Sub CommandButton1_Click()
Dim n, t As Integer
Dim ns As String
n = getThelastUsedRowAddress()
t = n + n
ns = CStr(t)
Call getThelastUsedRow(CStr(n))
Call TheLoopRange(CStr(n) + 1, ns)
End Sub
'get the last used and paste after
Sub getThelastUsedRow(address As String)
'Get Last Row in Worksheet UsedRange
Dim LastRow As Range, ws As Worksheet
Dim numcopied As Integer
Dim numonpaper As Integer
Set ws = ActiveSheet
numcopied = ws.UsedRange.Rows(ws.UsedRange.Rows.Count).Row
numonpaper = numcopied + 1
ws.UsedRange.Copy 'Destination:=Wst.Cells(1, 1)
'paste
Sheets("Sheet1").Range("A" & numonpaper).PasteSpecial xlPasteValues
End Sub
'loop the pasted range and change date to the next day from date
Sub TheLoopRange(rangestart As String, rangeend As String)
'rangestart,rangeend
Dim rCell As Range
Dim rRng As Range
Set rRng = Sheet1.Range("E" & rangestart & ":E" & rangeend)
For Each rCell In rRng.Cells
'MsgBox rCell.Value
rCell.Value = ExtraDay(rCell.Value)
Next rCell
End Sub
Lets as assume that:
We use Sheet1
Company column is column D
Date column is column I
Pease try:
Option Explicit
Sub Test()
Dim Lastrow As Long, i As Long
With ThisWorkbook.Worksheets("Sheet1")
Lastrow = .Cells(.Rows.Count, "D").End(xlUp).Row
For i = 2 To Lastrow
If i = 2 Then
.Cells(i, 9).Value = Date + 1
ElseIf i <> 2 And .Cells(i, 4).Value = 1 Then
.Cells(i, 9).Value = .Cells(i, 9).Offset(-1, 0).Value + 1
Else: .Cells(i, 9).Value = .Cells(i, 9).Offset(-1, 0).Value
End If
Next i
End With
End Sub

vba cut and past function without any blank row

Please advise as to what is wrong in my below coding. I am able to cut and past the row but after that i can see blank row in my sheet. How can we automatically adjust the row.
After cut and past there should not be any blank row in original sheet.
Dim i As Variant
endrow = ws1.Range("A" & ws1.Rows.Count).End(xlUp).Row
For i = 2 To endrow
If ws1.Cells(i, "M").Value = str Then
ws1.Cells(i, "M").EntireRow.Cut Destination:=ws2.Range("A" & LastRow + ).EndxlUp).Offset(1)
End If
Next
This will do the trick:
Sub Test()
Dim i As Long
Dim endrow As Long
'Added this code to get it working on my test file.
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Dim str As String
Dim lastrow As Long
Set ws1 = ThisWorkbook.Worksheets("Sheet1")
Set ws2 = ThisWorkbook.Worksheets("Sheet2")
str = "DELETE THIS ROW"
lastrow = 30
''''''''''''''''''''''
endrow = ws1.Range("A" & ws1.Rows.Count).End(xlUp).Row
For i = endrow To 2 Step -1
If ws1.Cells(i, "M").Value = str Then
ws1.Cells(i, "M").EntireRow.Cut Destination:=ws2.Range("A" & lastrow).End(xlUp).Offset(1)
ws1.Cells(i, "M").EntireRow.Delete Shift:=xlUp
End If
Next
End Sub

Resources