Really new to the Excel VBA.
Been working on one task and tried to piece all different elements into one working macro.
Here is my goal
as you can see on the picture,
there is a list of ID and names who reported their leave during the month.
I would like to translate into below format
start date/ end date /hours taken
1 Tried the code to capture start date, but failed to resume the loop to capture the end date.
Sub FindMatchingValue()
Dim i As Integer, intValueToFind As Integer
intValueToFind = 8
For i = 1 To 500 ' Revise the 500 to include all of your values
If Cells(2, i).Value = intValueToFind Then
MsgBox ("Found value on row " & i)
Cells(2, 35).Value = Cells(1, i) 'copy the start date to same row column 35
Exit Sub
End If
Next i
' This MsgBox will only show if the loop completes with no success
MsgBox ("Value not found in the range!")
End Sub
2 End date would be the last day for employee who took leave in consecutive days.
Really appreciate help from our community.
Following code will return you the first set of consecutive leave for first ID (Row 2) with start date, end date and hours taken:
Sub FindMatchingValue()
Dim i As Integer, intValueToFind As Integer, Found As Boolean, HoursTaken As Single
intValueToFind = 8
For i = 1 To 34 'Considering 34 is the max date column
If Found Then
If Cells(2, i).Value = "" Then
MsgBox ("Last consecutive column " & i - 1)
Cells(2, 36).Value = Cells(1, i - 1) 'copy the end date to same row column 36
Cells(2, 37).Value = HoursTaken 'Hours taken to same row column 37
Found = False
Exit Sub 'Skip after first set of leave
Else
HoursTaken = HoursTaken + Cells(2, i)
End If
ElseIf Cells(2, i).Value = intValueToFind Then
MsgBox ("Found value on column " & i)
Cells(2, 35).Value = Cells(1, i) 'copy the start date to same row column 35
Found = True
HoursTaken = Cells(2, i)
End If
Next i
'This MsgBox will only show if the loop completes with no success
MsgBox ("Value not found in the range!")
End Sub
You have to think more on how will you capture the next sets of leave for the same person and run it for entire set of data row. Hope this will be help in solving your problem.
Related
I have a consolidator tool that consolidates data from different worksheets. It can handle up to 1 million rows. However, when I click the button to check duplicates, there's an error that says "There isn't enough memory to do this action." I noticed that this error only happens when this macro runs. Please excuse the bad practice code as I am new to programming and this is what currently works right now. Is there anyway I can clean this code properly while still maintaining the functionality?
This is how it works:
| Employee ID | Status |
E100 Deactivated
E100 Activated
Turns into:
| Employee ID | Status | Status |
E100 Deactivated Activated
Code:
Sub mergeCategoryValues()
Dim lngRow As Long
Dim rngPrimaryKey As Range
Application.ScreenUpdating = False
Application.EnableEvents = False
'This is using activesheet, so make sure your worksheet is
' selected before running this code.
Sheets("Consolidated").Activate
With ActiveSheet
Set rngPrimaryKey = .Range("A:Z").Find("Full Name")
Dim columnToMatch As Integer
columnToMatch = rngPrimaryKey.Column
'Figure out the last row
lngRow = .Cells(1000000, columnToMatch).End(xlUp).Row
.Cells(columnToMatch).CurrentRegion.Sort key1:=.Cells(columnToMatch), Header:=xlYes
For Each Cell In ActiveSheet.UsedRange
If Cell.Value <> "" Then
Cell.Value = Trim(Cell.Value)
End If
Next Cell
'Loop through each row starting with last and working our way up.
Do
'Does this row match with the next row up accoding to the Job Number in Column A?
If .Cells(lngRow, columnToMatch) = .Cells(lngRow - 1, columnToMatch) Then
'Loop through columns B though P
For i = 1 To 1000 '1000 max (?)
'Determine if the next row up already has a value. If it does leave it be
' if it doesn't then use the value from this row to populate the next
' next one up.
If .Cells(lngRow - 1, i).Value <> "" Then 'if not blank
If .Cells(lngRow - 1, i).Value <> .Cells(lngRow, i).Value Then 'if previous value is not equal to current value
''''''
'INSERT NEW COLUMN HERE
If i <> 1 Then 'if column is not "Data Source"
If .Cells(lngRow, i).Value <> "" Then
Cells(lngRow - 1, i + 1).EntireColumn.Insert
.Cells(lngRow - 1, i + 1).Value = .Cells(lngRow, i).Value
'INSERT COLUMN NAME
.Cells(1, i + 1).Value = .Cells(1, i).Value
End If
Else
.Cells(lngRow - 1, i).Value = .Cells(lngRow - 1, i).Value & "; " & .Cells(lngRow, i).Value
End If
Else
'Do Nothing
End If
End If
Next i
'Now that we've processed all of the columns, delete this row
' as the next row up will have all the values
.Rows(lngRow).Delete
End If
'Go to the next row up and do it all again.
lngRow = lngRow - 1
Loop Until lngRow = 1
End With
With ActiveWindow
.SplitColumn = 1
.SplitRow = 0
End With
ActiveWindow.FreezePanes = True
Worksheets("Consolidated").Range("A:Z").Columns.AutoFit
Application.ScreenUpdating = True
Application.EnableEvents = True
If Err <> 0 Then
MsgBox "An unexpected error no. " & Err & ": " _
& Err.Description & " occured!", vbExclamation
End If
End Sub
You can use a pivot table with a few mouse clicks that provides the same information value.
If you want to replace the numbers with the words, you can then copy the pivot table and perform a Find/Replace for each column.
In Excel VBA I would like to match 3 criteria out 3 columns and get a message if there is any match.
My code so far is:
Private Sub Worksheet_Change(ByVal Target As Range)
If Range("A1:A10").Value = "America" And Range("B1:B10").Value = "cloudy"
And Range("C1:C10").Value > 30 Then
MsgBox "This is the promised land!"
End If
End Sub
I get an error that there is a problem with different values.
A different approach but works similar.
Dim i As Integer
For i = 2 To 10 ' Put something more variable instead of 10
If Range("A" & i).Value = "Value4" And Range("B" & i).Value = "Value8" And Range("C" & i).Value > 30 Then
MsgBox "Test"
End If
Next i
Loop over each row:
Sub ceckit()
Dim cell As Range, A As Range
Set A = Range("A1:A10")
For Each cell In A
With cell
If .Value = "America" And .Offset(0, 1).Value = "cloudy" And .Offset(0, 2).Value > 30 Then
MsgBox "This is the promised land!"
End If
End With
Next cell
End Sub
This question already has answers here:
IsDate function returns unexpected results
(2 answers)
Closed 3 years ago.
I am currently working on a sheet, specifically column that contains various data types; where I am interested in calculating difference between the first date occured in the column and the next one to it (because the main problem is that the data in the column is heterogeneous and I am interested just in succession ).
So for each cell in the range I have to check whether is a Date , and if so calculate difference between the actual date and the that of the next cell.
I have tried some code but all I can say it is not stable since the IsDate function is acting wierd and seems to change the outcome for different reasons but never the same.
Sub loopDate()
Dim rnge, cell As range
Set rnge = range("P1:P21")
Application.ScreenUpdating = True
For Each cell In rnge
cd = cell.Value2
If IsDate(cd) = True Then
If IsDate(ActiveCell.Offset(1, 0)) = True Then
n = DateDiff("d", cd, ActiveCell.Offset(1, 0))
If n < 0 Then
MsgBox "here is a difference " & n
Else
MsgBox "normal pos diff " & n
End If
Else
MsgBox "contenent of the this cell isnt date intIF "
End If
Else
MsgBox "contenent of the this cell isnt date outIF "
End If
Next
End Sub
I am expecting either a negative or positive number that will refer to difference between two dates and tell weather we still gave time or we already got the deadline passed.
thanks for any help or suggestions about the code above.
try this:
Sub loopDate()
Dim rnge, cell As Range
Set rnge = Range("P1:P21")
For Each cell In rnge
If IsDate(cell) = True Then
If IsDate(cell.Offset(1, 0)) = True Then
n = DateDiff("d", cell, cell.Offset(1, 0))
If n < 0 Then
MsgBox "here is a difference " & n
Else
MsgBox "normal pos diff " & n
End If
Else
MsgBox "contenent of the this cell isnt date intIF "
End If
Else
MsgBox "contenent of the this cell isnt date outIF "
End If
Next
End Sub
If I understand you correctly, this is what you're trying to achieve; I have cleaned up some of the unnecessary bits and now you just have to edit DateCol and FindLastRow as is necessary.
Sub loopDate()
'Dim rnge As Range, cell As Range
Dim DateCol As Integer, FindLastRow As Single Dim i As Single
'Set rnge = Range("P1:P21")
'Application.ScreenUpdating = True
' For Each cell In rnge
DateCol = 16
FindLastRow = 21
For i = 1 To FindLastRow
' cd = cell.Value2
If IsDate(Cells(i, DateCol)) Then
If IsDate(Cells(i, DateCol + 1)) Then
n = DateDiff("d", Cells(i, DateCol).Value, Cells(i, DateCol + 1).Value)
If n < 0 Then
MsgBox "here is a difference " & n
Else
MsgBox "normal pos diff " & n
End If
Else
MsgBox "contenent of the this cell isnt date intIF "
End If
Else
MsgBox "contenent of the this cell isnt date outIF "
End If
' Next
Next i
End Sub
New member here trying to fathom what might be wrong with the following code...
I am trying to copy rows from "A5" to the last row and columns A:L except columns "C & D" when C = "Y" but not getting anything when execute Macro and debug now giving much away (although I am new to this :-)). Any ideas or help would be appreciated.
Private Sub UpdateImportFile_Click()
Dim count As Long
count = WorksheetFunction.CountA(Range("A5", Range("A5").End(xlDown)))
For i = 5 To count
If Worksheets("Case Entry").Cells(i, 3).Value = "Y" Then
Worksheets("Case Entry").Rows(i).Columns(1, 2).Copy
Worksheets("Import File").Activate
Worksheets("Import File").Cells("A2").Select
ActiveSheet.PasteSpecial xlPasteValues
End If
Next
Application.CutCopyMode = False
ThisWorkbook.Worksheets("Case Entry").Cells(1, 1).Select
End Sub
Try this:
Private Sub UpdateImportFile_Click()
Dim count As Long
count = WorksheetFunction.CountA(Range("A5", Range("A5").End(xlDown)))
With Worksheets("Case Entry")
For i = 5 To count + 4
If .Cells(i, 3).Value = "Y" Then
Worksheets("Import File").Cells(i, 1).Resize(1, 2).Value = .Cells(i, 1).Resize(1, 2).Value
End If
Next
End With
End Sub
I'm working on a program with Excel's VBA functionality, but ran into a very strange logic error.
For SheetIndex = 1 To 6
With ActiveSheet
For ColIndex = 2 To 6
For DateIndex = 0 To MinLimit
datethingy = .Cells(1, ColIndex).Value
If (.Cells(1, ColIndex).Value = Date_Array(DateIndex, 1)) Then
For RowIndex = 2 To 11
' Compare every time slot value here to every time slot value in the array
datethingy = Trim(CStr(.Cells(RowIndex, 1).Value)) 'ERROR OCCURS HERE
If (Trim(CStr(.Cells(RowIndex, 1).Value)) = Date_Array(DateIndex, 2)) Then
.Cells(RowIndex, ColIndex).Value = "Checked"
End If
Next
End If
Next
Next
End With
SheetIndex = SheetIndex + 1
Application.Worksheets(SheetIndex).Activate
Next
So in the code above, I go through a series of cell values and make comparisons to values I already have in my array. However, when I draw the values from the cells, rather than "8:30", it comes up as "0.354166666...7". I have no idea why it's coming up like this, I'm even making sure it's being compared as a string and not as an int or anything else.
Here is where I set the values for the sheet's cells.
.Cells(2, 1).Value = "8:30"
.Cells(3, 1).Value = "9:00"
.Cells(4, 1).Value = "10:15"
.Cells(5, 1).Value = "11:30"
.Cells(6, 1).Value = "12:30"
.Cells(7, 1).Value = "13:30"
.Cells(8, 1).Value = "14:45"
.Cells(9, 1).Value = "16:00"
.Cells(10, 1).Value = "17:15"
.Cells(11, 1).Value = "18:15"
With Range("A2", "A11")
.HorizontalAlignment = xlCenter
.Font.Bold = True
.ColumnWidth = 15
End With
ActiveSheet.Cells.Rows.AutoFit
Does anyone have any idea why this could be happening?
Excel stores times and dates as numbers. Each whole number is a day and hours, minutes and seconds are broken down as fractions of that day. 8:30 is just a time so there is no whole number and 8.5/24 = 0.3541667.
You can test this with this code and this may provide you a way to format your inputs. Type 8:30 into cell A1
Sub test()
Debug.Print sheet1.Range("A1").Value = "8:30" 'returns false
Debug.Print Format(sheet1.Range("A1").Value, "h:mm") = "8:30" 'returns true
Debug.Print Sheet1.Range("A1").Text = "8:30" 'return true
End Sub