1

If the users fill in the serial no. column in col B (it doesn't have to be all 10 of them, as long as one is filled), they need to fill up the other columns from col C to col F. Hence, if col B is filled up but any of the cells in col C to F are not filled up, I want an error message to pop up. I hope the image below gives a clearer idea..:

I'm not sure if Worksheet_SelectionChange will do what I want to accomplish...because I don't want to include a command button. As some users may not bother clicking on the command button to verify their inputs. This is the code I have at the moment, please feel free to advise accordingly....thank you:)

Private Sub Worksheet_SelectionChange(ByVal Target As Range)

 If Range("B4").Value = "" Then
 MsgBox "serial no. is a Mandatory field", vbExclamation, "Required Entry"
 Range("B4").Select
 End If

 If Range("B4:B") <> "" Then
 If Range("C4:C").Value = "" Then
 MsgBox "Product is a Mandatory field", vbExclamation, "Required Entry"
 Range("C4:C").Select
 End If

' Adding values from sheet 2 for fruits drop-down list.
If Not Intersect(Target, Range("D3")) Is Nothing Then

Sheets("Sheet1").Range("D3") = "[Please Select]"

Dim col As New Collection
Dim rng As Range
Dim i As Long
Dim dvlist As String

'Loop thru the data range
For Each rng In Sheet2.Range("B2:B7")
'ignore blanks
    If Len(Trim(rng.Value)) <> 0 Then
        'create a unique list
        On Error Resume Next
        col.Add rng.Value, CStr(rng.Value)
        On Error GoTo 0
    End If
Next rng

'concatenate with "," as the delimiter
For i = 2 To col.Count
    dvlist = dvlist & col.Item(i) & ","
Next i

With Sheet1.Range("C2:C").Validation
    .Delete
    .Add Type:=xlValidateList, _
    AlertStyle:=xlValidAlertStop, _
    Formula1:=dvlist
End With

End If

' Adding values from sheet 2 for country of origin drop-down list.
If Not Intersect(Target, Range("E4")) Is Nothing Then
Sheets("Screening Request").Range("E4") = "[Please Select]"

'Loop thru the data range
For Each rng In Sheet2.Range("A2:A7")
'ignore blanks
    If Len(Trim(rng.Value)) <> 0 Then
        'create a unique list
        On Error Resume Next
        col.Add rng.Value, CStr(rng.Value)
        On Error GoTo 0
    End If
Next rng

'concatenate with "," as the delimiter for list in Sheet 2
For i = 2 To col.Count
    dvlist1 = dvlist1 & col.Item(i) & ","
Next i

'add it to the DV
With Sheet1.Range("D3").Validation
    .Delete
    .Add Type:=xlValidateList, _
    AlertStyle:=xlValidAlertStop, _
    Formula1:=dvlist1
End With

End If


 ' This is for the date (YYYYMMDD) column. I need it to be in YYYYMMDD format:
 If Not Intersect(Target, Range("F4:F13")) Is Nothing Then

       If Not IsNumeric(.Value) And Not cel.NumberFormat = "yyyymmdd" Then
            MsgBox "Date format must be in YYYYMMDD"
            cel.Value = ""
            Exit Sub
       Else: cel.NumberFormat = "yyyymmdd"
       End If
  End With

  End If

enter image description here

enter image description here

  • Can't you add that condition in the `USERFORM` ? it will not submit the info if serial number is missing – Mikku Aug 18 '19 at 07:18
  • but its currently not a userform...hm..without a userform is it still possible? –  Aug 18 '19 at 07:24
  • Yes it is possible. You can add that in the `Before_Save` event. It will check before saving the workbook if the rows that have serial number, have the other columns filled or not. – Mikku Aug 18 '19 at 07:28
  • In addition to @Mikku you could also use `Worksheet_Calculate`. Of course this will run each time your worksheet calculates but you can most certainly get it to check your grid each time. – Dean Aug 18 '19 at 07:35
  • 2
    How about using conditional formatting? For instance, you could have a formula `=AND(B4<>"",ISBLANK(C4))` and set the fill to an appropriate warning colour? This would provide a very visible hint to the user, where values are missing. – Jonathan Willcock Aug 18 '19 at 07:43
  • @Mikku thanks Mikku, I'm checking it out :) –  Aug 18 '19 at 07:48
  • @Dean hm..i've nvr seen this function before...I'll look it up first!! Edit: I saw this post....not too sure if worksheet_calculate is still appropriate here..https://stackoverflow.com/questions/4388279/how-can-i-run-a-vba-code-each-time-a-cell-get-is-value-changed-by-a-formula –  Aug 18 '19 at 07:49
  • @JonathanWillcock hm...but can an error message pop-up? Cause that would be a more effective thing for users.. –  Aug 18 '19 at 07:50
  • @psyduck No It won't popup an error message, but it will highlight all required fields as soon as a serial no. is entered. You probably don't want an error popup to occur when the serial no. is first entered, as this would irritate your users. Give them a chance to enter required data before giving them an error message. Conditional formatting is a neat way to do this. I was making the suggestion as an addition (pre-process) to a popup message, not as a replacement. – Jonathan Willcock Aug 18 '19 at 07:56
  • @JonathanWillcock ah i see.....thanks for that! :) but at the current moment, my code definitely has something wrong and I'm still trying to figure it out –  Aug 18 '19 at 08:00

1 Answers1

1

In general, you are making life much too hard for yourself. Use the tools that Excel provides (and there are many); you do not need to re-invent the wheel.

For example the lists for fruits and country of origin in your Sheet2 should be used as a list for data validation purposes in Sheet1 (Data Tab, Data Tools, Data Validation). Choose Allow List, make sure Ignore blank and In-cell dropdown are checked and select the range from Sheet2.

Similarly you can use data validation to validate dates in your last column.

You now do not need to validate these columns yourself, as they will always have blanks or valid values.

Combine this with my suggestion of conditional formatting (eg for the range c4:c13 you should enter =AND(B4<>"",ISBLANK(C4)) and for all three columns, you can produce a very simple verification routine. Something like:

Private Sub Workbook_BeforeClose(Cancel As Boolean)

    Cancel = MissingEntries()

End Sub

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)

    Cancel = MissingEntries()

End Sub

Private Function MissingEntries() As Boolean

Dim i As Integer
Dim j As Integer
Dim atLeastOneLine As Boolean

    atLeastOneLine = False
    For i = 4 To 13
        If (Cells(i, 2) <> "") Then
            atLeastOneLine = True
            For j = 3 To 6
                If Cells(i, j) = "" Then
                    MsgBox ("Please supply values for highlighted cells")
                    MissingEntries = True
                    Exit Function
                End If
            Next
            If WrongSerialNumber(i) Then
                MissingEntries = True
                Exit Function
            End If
        End If
    Next
    If Not atLeastOneLine Then
        MsgBox ("Please supply values for at least one line")
        MissingEntries = True
    Else
        MissingEntries = False
    End If

End Function

Private Function WrongSerialNumber(i As Integer) As Boolean

    Dim yr As Integer
    Dim serialNo As String
    Dim yrStr As String
    Dim yrCell As String


    serialNo = Cells(i, 2)
    If Len(serialNo) < 3 Then
        WrongSerialNumber = True
        MsgBox "Serial Number for row no. " + CStr(i - 3) + " is too short.  Please correct."
        Exit Function
    End If
    yrCell = Cells(i, 6)

    If Len(yrCell) = 8 Then

        yr = CInt(Left(Cells(i, 6), 4))
        If yr > 1968 Then
            If Mid(yrCell, 3, 2) <> Mid(serialNo, 2, 2) Then
                WrongSerialNumber = True
                MsgBox "Serial Number for row no. " + CStr(i - 3) + " has wrong second and third digits.  These should match the third and fourth digits of the date.  Please correct."
                Exit Function
            End If
        End If
    End If
    WrongSerialNumber = False

End Function

Note that I validate on both close and save. The former is optional.

Because of the highlighting, a simple message suffices, you are spared the work of informing the user, which cells are missing. In this way the combination of in-built Data Validation and Conditional Formatting makes the remainder of your task so much easier.

Jonathan Willcock
  • 5,012
  • 3
  • 20
  • 31
  • This seems to be working! Thank you:) I'm still using the drop down list in VBA cause data validation can't add more than 2 sources to the list. Currently the code for my date column in YYYYMMDD format is not working because I'm still using the worksheet_SelectionChange for my drop-down list. Is there any way i can improve on the current code above for my date column? –  Aug 18 '19 at 12:44
  • Also..is it possible for the 3rd and 4th digits of the date to tally with the 2nd and 3rd digits of the serial number? For example date = 19**69**0819 and serial no. = T**69**0909090. The 69 should tally. But this condition is only needed for the dates starting from 1969 onwards... –  Aug 18 '19 at 12:54
  • @psyduck Sorry I have gone swimming, so just have my phone. What do you mean by data validation can't add more than two sources to the list? Normally one source is enough? As for the date column, you can use data validation to restrict it to dates within a given range, and a custom format to get it in yyyyMMdd format. Note however if you do this, users should enter dates in Windows locale format and let Excel convert. When I'm back at a computer, I give an update to show one way to do the serial no. verification. – Jonathan Willcock Aug 18 '19 at 13:11
  • haha its ok, thank you for your prompt response still :) yeah, for example, the data validation for country of origin comes from two different ranges say C4:C7 & D4:D9 (in the actual excel file not the sample file you see). Hm....yeah I tried that with date validation (by using data validation in Excel) but they asked for a range of dates in the input boxes. However, I dont want to restrict my range of dates for users.. –  Aug 18 '19 at 13:18
  • For the countries, can you not combine them? With dates I for my test simply used an extremely wide range (19000101 and 22000101); something like that ought to be OK?? I have edited my answer to show one way to verify the serial no. using the ´Mid´ function – Jonathan Willcock Aug 18 '19 at 15:15
  • yes! I tried 19000101 but an error message pops up saying "The date you entered for the Start Date is invalid" thank you, I am looking thru your update now :) –  Aug 18 '19 at 15:20
  • No you need to enter the start date in your normal windows format, not yyyyMMdd. EG in the uk you must enter dd/MM/yyyy – Jonathan Willcock Aug 18 '19 at 16:01
  • But i need it to be specifically in the YYYYMMDD format like '19000101'. Hence I kinda guessed data validation wouldnt work...not too sure if it will work for vba code cause so far mine isnt working at all –  Aug 18 '19 at 16:05
  • As I said in my earlier comment, you can User Data Validation in the date column but have the cells formatted with a custom format yyyyMMdd. This does mean that users enter a date in their normal fashion but Excel will present it in your desired format. It also means maximum start and end dates are also entered normally. The result however is what you want. – Jonathan Willcock Aug 18 '19 at 16:11
  • Sorry....i tried both custom and date validation but it doesnt work. See my updated pics above..I dont really get what you mean by 'Excel will present it in your desired format' cause i cant seem to do it with date validation either –  Aug 18 '19 at 16:21
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/198108/discussion-between-jonathan-willcock-and-psyduck). – Jonathan Willcock Aug 18 '19 at 16:22