I would like to determine if a cell in my range contains a date (any date) and if it does to exit the sub with a message.
The date format looks like this: dd-mmm-yy but is generated by a formula within the cell.
Here is some of my code already written along with some pseudo code of what I want to achieve.
Sub RemoveRowButton()
'This Macro deletes a row where the button is clicked.
'Variables
Dim row As Long
Dim varResponse As Variant
Application.ScreenUpdating = False
'Message box confirming user is doing the right thing
varResponse = MsgBox("Delete this row? 'Yes' or 'No'", vbYesNo, "Delete Row")
If varResponse <> vbYes Then Exit Sub
'Carry on with deleting row.....
Set rng = ActiveSheet.Buttons(Application.Caller).TopLeftCell.EntireRow
*******Pseudo Code *******
'Check if the row to be deleted has a date in the D Column of the range (which is a Row)
'If IsDate **in D column of the Range is ture*** Then
'MsgBox "This Row Contains a Date!"
'End If
'Unprotect sheet
ActiveSheet.Unprotect Password:="***"
'Delete row on button row
rng.Delete
'Protect sheet again
ActiveSheet.Protect Password:="***"
End Sub
If you could explain your code/answers too I would be grateful, Thanks.
EDIT:
Thank you for all the help, I have, through trial and error created this which works for me.
Set rng2 = rng.Cells(, 4)
If IsDate(rng2.Value) Then 'Check Cell for Date
MsgBox "Warning: This Row Cannot be deleted!"
Exit Sub
End If
Since I am unfamiliar with VBA I do not know if this is "OKAY" in the sense of best practices. If not and you feel like correcting it please do so.
Here is an idea for your problem. Install the code in the code sheet of the worksheet on which you wish to have the action (not in a standard module like 'Module1' !!) Note that the code reacts to a double-click in column D from row 2 down to the last used row in column A. You can adjust that. Follow the directions in the code itself. I use this method instead of the button you seem to have in every row of your sheet - a matter of preference, but used here for demonstration and to avoid creating buttons.
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
' 03 Jan 2019
Dim Rng As Range
Dim R As Long
Dim Cell As Range
Dim i As Integer
R = Cells(Rows.Count, "A").End(xlUp).Row ' last used row in column A
Set Rng = Range(Cells(2, 4), Cells(R, 4)) ' used range in column D
If Not Application.Intersect(Target, Rng) Is Nothing Then
' if a cell in Rng as double-clicked:-
R = Target.Row
Set Rng = Range(Cells(R, "A"), Cells(R, "S"))
For Each Cell In Rng
With Cell
If IsDate(.Value) Then
For i = 3 To 1 Step -1
' check if the Numberformat contains all of "m", "d" and "y"
If InStr(1, .NumberFormat, Mid("dmy", i, 1), vbTextCompare) = 0 Then Exit For
Next i
If i = 0 Then ' all 3 were found
If MsgBox("Do you want to delete row " & R & " ?", _
vbQuestion Or vbYesNo, _
"Click ""No"" to keep the row") = vbYes Then
Rows(R).Delete
End If
Exit For
End If
End If
End With
Next Cell
Cancel = True ' ends in-cell editing
End If
End Sub
The code carries out two checks on each cell (A:S). It first checks if its value is a date. Then, presuming it is a number, it checks the cell format. If the NumberFormat includes all of the letters 'm", "d" and "y" it is confirmed as a date and released for deletion before which the user can confirm his intention.
This method may require a little fine tuning. Firstly, if the cell has text date a different second check would have to be carried out. Second, if the date format consists of only 2 of the 3 criteria the test for their presence in the mask must be reduced accordingly. Either of these modifications, or both, could be implemented once the nature of your data is better understood.
#J4C3N-14 did you try:
Sub Test_Date()
Dim strDate As String
With ThisWorkbook.Worksheets("Sheet1")
strDate = .Range("A1").Value
If IsDate(strDate) Then
'Code
End If
End With
End Sub
Related
I am trying to copy the row value of Column E:N from 'Screening List' to 'Consented' sheets to start in column A:J. Both Sheets contained the same header on the specific column mentioned. I would like the row value of each of these columns in 'Screening List' to be pasted to the 'Consented' sheet if the row in Column D ('Screening List') = "Y". The dropdown is Y or N. Please also note that D data in the early rows may eventually change from "N" to "Y" after the other data on the succeeding rows. So I would like data pasted in the next sheet in sequence when the D column is changed to "Y"
I have tried every code available that I know of but it seems most of the code copy entire row of all columns not specific ones. I finally tried the below code but it didn't come out as I would like it to be see attached.
Screening List
Consented
I am sorry I am completely new to VBA and have not done complex coding (for me!) such as this.
I would be forever grateful if you could help me with this.
I did try the below code but it only keep copying the 1st row to the next empty row and not the other row with "Y" in D column. Also some of the columns have blank value with Y on the row and still want them all copied.
'VBA in Screening List Sheet'
Private Sub Worksheet_Change(ByVal Target As Range)
Dim Z As Long
Dim xVal As String
On Error Resume Next
If Intersect(Target, Range("D:D")) Is Nothing Then Exit Sub
Application.EnableEvents = False
For Z = 1 To Target.Count
If Target(Z).Value > 0 Then
Call MoveBasedOnValue
End If
Next
Application.EnableEvents = True
End Sub
'Module'
Sub MoveBasedOnValue()
Dim i As Long, shtSrc As Worksheet, rngDest As Range
Application.ScreenUpdating = False
Set shtSrc = Sheets("Screening List")
Set rngDest = Sheets("Consented").Cells(Rows.Count, 1).End(xlUp).Offset(1, 0)
For i = 2 To shtSrc.Range("D2").End(xlDown).Row
If shtSrc.Range("D" & i).Value = "Y" Then
shtSrc.Range("E" & i & ":N" & i).Copy rngDest
Set rngDest = rngDest.Offset(1, 0)
End If
Next i
Application.ScreenUpdating = True
End Sub
I cannot seem to find what i am looking for so here i am.
The situation: We have a spreadsheet that is used by multiple users. They will have to fill in certain cells with an employee's name, but they must be typed exactly as in our system. To remove as much human error as possible, we are making a simple button they can push after typing in their last name and a Vlookup gives us the proper format.
Problem: There are about 10 cells all in one column (B10:B19) that are where the names will go. The vlookup output is in Cell G4. So we want if they press the button, the contents of G4 goes in the next available cell within that range of B10-B19. I have gotten close but it appears to skip some lines and miss others.
Here is what i have so far:
Sub SecondTestFunction()
Dim cellRange As Range
Dim nameInCell As Range
Set cellRange = Range("B11:B20")
'Loop through cells in range B11 thru B20
For i = 1 To cellRange.Count
'Set nameInCell to equal the index of column B
Set nameInCell = cellRange(i)
'If the cell in Column B is empty....
If IsEmpty(nameInCell) Then
'Paste the name from cell G4...
nameInCell(i).Value = Range("G4")
GoTo GoToHere
Else
MsgBox "Cell is NOT EMPTY"
nameInCell(i).Interior.ColorIndex = 3 'Testing line to see which get affected
End If
Next i
GoToHere:
MsgBox "Done looping"
End Sub
Any help is appreciated!
You can do something like this:
Sub SecondTest()
Dim c As Range, bFound As Boolean, ws As Worksheet
Set ws = ActiveSheet 'always use an explicit sheet
For Each c in ws.Range("B11:B20").Cells
If Len(c.value) = 0 Then
c.Value = ws.Range("G4").Value
bFound = True
Exit for
End If
Next c
If not bFound Then Msgbox "No empty cell found!"
End Sub
I am trying to create a range print by entering a number in a cell. If a person enter a number 20 (this is just an example, for the real thing it will scan barcode and with a formula will take the number from another table but the basics are like this)... so when the number 20 in in the cell to select the first 20 rows from column B and print this selection. Then to delete all the 20 rows.
I have only the print code :
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim celltxt As String
celltxt = ActiveSheet.Range("D2").Text
If InStr(1, celltxt, "") Then
Dim ws As Worksheet
For Each ws In Worksheets
If ws.Range("D2") <> "" Then
Range("D2").PrintOut
Range("E2").ClearContents
Application.SendKeys ("{LEFT}")
End If
Next ws
Else
End If
End Sub
This code is just simple code for printing a cell if the cell in not empty. I am using it but I need to upgrade it with the above idea. :)
If anyone have idea how to create this I will be grateful as I am just a VBA beginner.
I find a solution for this one too with FINALISE
Private Sub Worksheet_Change(ByVal Target As Range)
Dim celltxt As String
Dim n As Range
'H2 is where the entry number is going to be
Set n = Worksheets("Sheet1").Range("H2")
On Error GoTo Finalise
'Select Column C and H2 number
ActiveSheet.Range(Cells(1, 3), Cells(n, 3)).Select
celltxt = ActiveSheet.Range("H2").Text
If InStr(1, celltxt, "") Then
Dim ws As Worksheet
For Each ws In Worksheets
If ws.Range("H2") <> "" Then
Selection.PrintOut
Range("H2").ClearContents
'Application.SendKeys ("{LEFT}")
End If
Next ws
Else
End If
Finalise:
Application.EnableEvents = True
ActiveSheet.Range("H2").Select
End Sub
Next... How can I make the code to take the data from another worksheet. Lets say H2 is at sheet1 and the data that should be selected ActiveSheet.Range(Cells(1, 3), Cells(n, 3)).Select is at Sheet2. At the end of my code I used ActiveSheet.Range("H2").Select but still need to get back to H2 in Sheet1.
Also my step after this is to clear all the selected rows content after the print.
I am trying to identify duplicates in Excel. I can highlight all duplicates in a column, using standard excel tools.
Ideally I would like to, say, click in cell A3 and have excel instantaneously highlight all instances in column A, which are duplicates of A3. This should happen in "real-time".
If you wanted a VBA solution to this problem you could try the below, but as noted already by PEH this would not be ideal with a large amount of data.
This would have to be applied to the sheet you're using and assumes that you're only assessing Column A.
Note: It will check Column A any time a cell on the sheet is double clicked...
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
'Name your sheet here
SheetName = "Sheet1"
'Work out how many rows there are in Column A
LastRow = Sheets(SheetName).Cells(Rows.Count, 1).End(xlUp).Row
'Copy current value to check later
CheckValue = Selection.Value
'Validate there is more than 1 filled cell
If LastRow > 1 Then
'Redim an array to hold all Column A data then load it to the array
ReDim DataArray(1 To LastRow) As Variant
DataArray = Range(Sheets(SheetName).Cells(1, 1), Sheets(SheetName).Cells(LastRow, 1))
'Clear previous highlighting
Range(Sheets(SheetName).Cells(1, 1), Sheets(SheetName).Cells(LastRow, 1)).Interior.Pattern = xlNone
'loop through array highlighting cells that match the "CheckValue"
For I = 1 To LastRow
If DataArray(I, 1) = CheckValue Then
Sheets(SheetName).Cells(I, 1).Interior.ColorIndex = 4
End If
Next I
End If
End Sub
It's likely a more elegant solution exists.
quick and dirty, place this in the wanted sheet code pane:
Option Explicit
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Column > 1 Then Exit Sub
Dim cellsToHighlight As Range, cell As Range
Set cellsToHighlight = Range("B1")
For Each cell In Range("A1", Cells(Rows.Count, 1).End(xlUp))
If cell.Value2 = Target.Value2 Then Set cellsToHighlight = Union(cellsToHighlight, cell)
Next
Set cellsToHighlight = Intersect(cellsToHighlight, Columns(1))
If Not cellsToHighlight Is Nothing Then cellsToHighlight.Select
End Sub
Use conditional formating for "Duplicate Values"
I have two columns, Column (A) and Column (B) in a spreadsheet.
Column (A) contains names extracted from a query (ex. Brian, Bob, Bill, etc...) and column (B) contains one of three statuses (Assigned, In Progress, or Pending).
However, this query sometimes pulls up some line items showing "Assigned" for the status with no name, therefore corresponding cell representing the name in Column (A) is blank. So I manually fill in those empty cells with "Unknown".
What I want to do is to create a macro that finds the every empty cell in column (A) and fill in the word "Unknown" if the cell to its right contains the word "Assinged".
So the conditions are:
Blank cell in column (A)
Correspoding cell to its right (column B) contains the word "assinged"
This is my Code:
Private Sub CommandButton2_Click()
For Each cell In Columns("A")
If ActiveCell.Value = Empty And ActiveCell.Offset(0, 1).Value = "Assigned" Then ActiveCell.Value = "Unknown"
Next cell
End Sub
There is no need to loop here, take advantage of excels built in methods which will execute faster.
Private Sub CommandButton2_Click()
Application.ScreenUpdating = False
With ActiveSheet.UsedRange
.AutoFilter Field:=1, Criteria1:=""
.AutoFilter Field:=2, Criteria1:="Assigned"
If WorksheetFunction.CountBlank(.Columns(1)) > 0 Then
If .Columns(1).SpecialCells(xlCellTypeVisible).Count > 1 Then
.Columns(1).SpecialCells(xlCellTypeBlanks).Value = "Unknown"
End If
End If
.AutoFilter
End With
Application.ScreenUpdating = True
End Sub
Welcome to SO.
Try this code. It will work a bit faster and should get you what you want.
Update: Made the code more bullet proof!
Private Sub CommandButton2_Click()
Dim cel As Range, rngFind As Range, rngFilter As Range
Dim wks As Worksheet
Set wks = Sheets("sheet1")
With wks
'-> Error check to make sure "blanks" exist
Set rngFind = .Range("A1:A" & .Range("B" & Rows.Count).End(xlUp).Row).Find("", lookat:=xlWhole)
If Not rngFind Is Nothing Then
Set rngFilter = .Range("A1:B" & .Range("B" & Rows.Count).End(xlUp).Row)
rngFilter.AutoFilter 1, "="
'-> Error check to make sure "assigned" exists for blank cells
Set rngFind = .Columns("B:B").SpecialCells(xlCellTypeVisible).Find("Assigned", lookat:=xlWhole)
If Not rngFind Is Nothing Then
'-> okay, it exists. filter and loop through cells
rngFilter.AutoFilter 2, "Assigned"
Set rngFind = Intersect(.UsedRange, .UsedRange.Offset(1), .Columns(1)).SpecialCells(xlCellTypeVisible)
For Each cel In rngFind
If cel.Offset(0, 1).Value = "Assigned" Then cel.Value = "Unknown"
Next cel
End If
End If
End With
End Sub
If you only need to do this a few times you could
format your used range as a table
on column A filter to only show "(Blanks)"
on column B filter to only show "assinged"
select all the resulting cells in column B
press alt + : to select only the visible cells
press F2
type "unknown"
press ctrl + enter
Your bad data should be good now!
Obviously this is a non-vba based solution but if you can avoid coding it's probably for the best.