VBA help for newbie

DAD

Board Regular
Joined
Jan 8, 2010
Messages
54
Hi Guys and Gals,

I have a project I have been working on for quite some time, but unable to find a workable solution. Up until now, I have been trying to find a solution without the use of VBA, as I am a relative newbie to VBA, but doing lots of reading and "trial and error" coding to fix that. Unfortunately the non-VBA solution is too big and too unworkable, so I am now trying it using VBA solution. I was hoping some of you may generously help get me on the right track?

So I work for a small company, and I am trying to make our system of allocation holiday/vacation dates a little more streamlined. To this end, I have come up with an algorithm to allocate the leave, but just now need to be able to code that into excel so employees can see if their desired leave dates will be approved.

If you observe the pic below, I have drastically simplified the final solution so that it may make it easier for you to help me down the right path. You will see that the employees are Smith, Jones and Chang. They can request up to 3 periods of Holidays/vacation per year, and they allocate each of the periods a priority, 1 being the most desired, 3 being the least. If there is no clash with other requested dates, it is approved, and the column titled "Approved" beside the requested period will say YES. If there is a clash of dates (with any of the dates entered in Priority 1-3), then the person that has the higher priority dates entered (1-3) will have their leave approved (YES) and the lower priority will have NO in the Approved? column. Should the dates clash, and the priority be the same, then the person with the higher seniority (that is the earlier date in column L will be approved (YES), the lower seniority with NO. Should The dates clash, the priority the same, the seniority the same, then the final step will be to allocate the leave to the oldest person (column N).

So to summarise:

1. No clash of dates = Approved
2. Clash of dates = Approved to higher Priority
3. Same dates + same Priority = Approved to higher Seniority
4. Same dates + same Priority + same Seniority = Approved to older person.

I realise this is more complicated than most questions asked here, but I would really appreciate your help. While the final solution is a lot more complicated, if I can gain an understanding of how you experts solve a smaller problem like this, I am sure I will be able to figure out the larger solution.

Many thanks for your time.

1596v9.jpg
 

Excel Facts

Difference between two dates
Secret function! Use =DATEDIF(A2,B2,"Y")&" years"&=DATEDIF(A2,B2,"YM")&" months"&=DATEDIF(A2,B2,"MD")&" days"
I found some unexpected time when I arrived home today. Hopefully this is the solution that you desire.

I'm offering a set of notes because I'd like you to compile a set of data that is different to mine, and maybe with more personnel. Then advise me.

I found it easier to code in ‘segments’, ie, build macros for just those parts in my focus and so avoid an awkward and lengthy growing page. In the end I have linked them into one program my calling their specific name in order at the end of the macro named lap().
There is a separate macro, clear(), which I found useful to erase the “Yes/No/NA” as I was testing.
I did add two buttons to my sheet. One I attached to lap() to run the full programming (during this process I did actually use other buttons, now deleted that allowed me to run those "segments" as I needed). That is where the second button attached to clear() was useful.

The image shows at the top an unprocessed table while that below is the result when the macros have been run.

You will be able to copy and paste A1:M11 from the image into a blank worksheet.
That said, you will have to delete row 1 and Column A which leave you with just the unblemished data. You’ll then have to do a bit of work yourself, add cell borders and resize columns. Now, in the lower table I’ve actually overlaid colours which Conditional Formatting generates when these conditions are applied:
Cell value contains ‘NA’ =$H$3:$H$11,$K$3:$K$11 Background Colour is dark gray.
Cell value contains ‘Yes’ =$E$3:$E$11,$H$3:$H$11,$K$3:$K$11 Background Colour is yellow
Cell value contains ‘No’ =$E$3:$E$11,$H$3:$H$11,$K$3:$K$11 Background Colour is red.
as the HTMLMaker does not pick up Conditional formatting.


If you have followed what I have noted above, then when you add and run the macros, the table should look exactly as that shown in my second table. You’ll note that poor Jones has missed out!

Firstly here is all of the code (clear and the various "lap" stages - btw 'lap' was my abbreviation of "overlapping dates" which this project is essentially about).
Code:
Sub clear()
Range("E3:E11, H3:H11, K3:K11").ClearContents
End Sub
Sub lap()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Dim day1, day2, day3, day4 As Long
Dim sen1, sen2, age1, age2 As Long
Dim lastrow, a, b, flag As Long
Rows(16 & ":" & 17).ClearContents
lastrow = Cells(Rows.Count, "C").End(xlUp).Row
'PRIORITY ONE
For a = 3 To lastrow

flag = 0
day1 = Range("C" & a).Value
day2 = Range("D" & a).Value
sen1 = Range("L" & a).Value
age1 = Range("M" & a).Value


For b = 3 To lastrow

If a <> b Then
flag = 0

day3 = Range("C" & b).Value
day4 = Range("D" & b).Value
sen2 = Range("L" & b).Value
age2 = Range("M" & b).Value


'Set filter for overlap of dates
  If (day3 >= day1 And day3 <= day2) Or (day1 >= day3 And day1 <= day4) Then
   
    If sen1 > sen2 Then
        flag = 1
        
        Exit For
        End If
   If sen1 = sen2 Then
           If age1 < age2 Then
             flag = 1
            
                Exit For
            End If
            End If
End If
End If
Next
If flag = 1 Then
Range("E" & a).Value = "No"
Else
Range("E" & a).Value = "Yes"
Range("H" & a).Value = "NA"
Range("K" & a).Value = "NA"
End If
Next
lapB
lapC
lapD
lapE
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
Sub lapB()
Dim day1, day2, day3, day4 As Long
Dim sen1, sen2, age1, age2 As Long
Dim lastrow, a, b, flag As Long
lastrow = Cells(Rows.Count, "C").End(xlUp).Row
For a = 3 To lastrow
If Range("H" & a).Value <> "NA" Then

day1 = Range("F" & a).Value
day2 = Range("G" & a).Value
sen1 = Range("L" & a).Value
age1 = Range("M" & a).Value

For b = 3 To lastrow
day3 = Range("C" & b).Value
day4 = Range("D" & b).Value
sen2 = Range("L" & b).Value
age2 = Range("M" & b).Value


'Set filter for overlap of dates
  If (day3 >= day1 And day3 <= day2) Or (day1 >= day3 And day1 <= day4) Then
   Range("H" & a).Value = "No"
   'Range("K" & a).Value = "NA"
End If
Next
End If
Next
End Sub

Sub lapC()
Dim day1, day2, day3, day4 As Long
Dim sen1, sen2, age1, age2 As Long
Dim lastrow, a, b, flag As Long
lastrow = Cells(Rows.Count, "C").End(xlUp).Row
For a = 3 To lastrow
If Range("H" & a).Value = "" Then
flag = 0
day1 = Range("F" & a).Value
day2 = Range("G" & a).Value
sen1 = Range("L" & a).Value
age1 = Range("M" & a).Value


For b = 3 To lastrow

If a <> b Then
flag = 0

day3 = Range("F" & b).Value
day4 = Range("G" & b).Value
sen2 = Range("L" & b).Value
age2 = Range("M" & b).Value


'Set filter for overlap of dates
  If (day3 >= day1 And day3 <= day2) Or (day1 >= day3 And day1 <= day4) Then
   
    If sen1 < sen2 Then
        flag = 1
        
        Exit For
        End If
   If sen1 = sen2 Then
           If age1 < age2 Then
             flag = 1
            
                Exit For
            End If
            End If
End If
End If
Next

If flag = 1 Then
Range("H" & a).Value = "No"
Else
Range("H" & a).Value = "Yes"

Range("K" & a).Value = "NA"
End If
End If
Next
End Sub

Sub lapD()
Dim day1, day2, day3, day4 As Long
Dim sen1, sen2, age1, age2 As Long
Dim lastrow, a, b, flag As Long
lastrow = Cells(Rows.Count, "C").End(xlUp).Row
For a = 3 To lastrow
If Range("K" & a).Value <> "NA" Then

day1 = Range("I" & a).Value
day2 = Range("J" & a).Value
sen1 = Range("L" & a).Value
age1 = Range("M" & a).Value

For b = 3 To lastrow
day3 = Range("C" & b).Value
day4 = Range("D" & b).Value
sen2 = Range("L" & b).Value
age2 = Range("M" & b).Value


'Set filter for overlap of dates
  If (day3 >= day1 And day3 <= day2) Or (day1 >= day3 And day1 <= day4) Then
   Range("K" & a).Value = "No"
   'Range("K" & a).Value = "NA"
End If
Next
End If
Next
For a = 3 To lastrow
If Range("K" & a).Value <> "NA" Then

day1 = Range("I" & a).Value
day2 = Range("J" & a).Value
sen1 = Range("L" & a).Value
age1 = Range("M" & a).Value

For b = 3 To lastrow
day3 = Range("F" & b).Value
day4 = Range("G" & b).Value
sen2 = Range("L" & b).Value
age2 = Range("M" & b).Value

'Set filter for overlap of dates
  If (day3 >= day1 And day3 <= day2) Or (day1 >= day3 And day1 <= day4) Then
   Range("K" & a).Value = "No"
   'Range("K" & a).Value = "NA"
End If
Next
End If
Next
End Sub
Sub lapE()
Dim day1, day2, day3, day4 As Long
Dim sen1, sen2, age1, age2 As Long
Dim lastrow, a, b, flag As Long
lastrow = Cells(Rows.Count, "C").End(xlUp).Row
For a = 3 To lastrow
If Range("K" & a).Value = "" Then
flag = 0
day1 = Range("I" & a).Value
day2 = Range("J" & a).Value
sen1 = Range("L" & a).Value
age1 = Range("M" & a).Value


For b = 3 To lastrow

If a <> b Then
flag = 0

day3 = Range("I" & b).Value
day4 = Range("J" & b).Value
sen2 = Range("L" & b).Value
age2 = Range("M" & b).Value


'Set filter for overlap of dates
  If (day3 >= day1 And day3 <= day2) Or (day1 >= day3 And day1 <= day4) Then
   
    If sen1 < sen2 Then
        flag = 1
        
        Exit For
        End If
   If sen1 = sen2 Then
           If age1 < age2 Then
             flag = 1
            
                Exit For
            End If
            End If
End If
End If
Next

If flag = 1 Then
Range("K" & a).Value = "No"
Else
Range("K" & a).Value = "Yes"


End If
End If
Next
End Sub

Now those tables:

Excel 2013/2016
ABCDEFGHIJKLM
1PR1App?PR2App?PR3App?SenAge
2NameStEndStEndStEnd
3Jones3-Jan-1812-Jan-186-May-1814-May-184-Apr-1814-Apr-183-Jun-1735
4Smith13-May-1825-May-1810-Nov-1820-Nov-187-Jun-1817-Jun-182-Jun-1730
5Chan2-Jan-183-Jan-185-Dec-1812-Dec-1813-Aug-1823-Aug-181-Jun-1740
6Wills12-Jan-1823-Jan-182-Jul-1818-Jul-185-Oct-1815-Oct-184-Jun-1741
7Thom6-Feb-1813-Feb-181-Mar-1811-Mar-184-Jul-1814-Jul-185-Jun-1742
8Ford3-Mar-1817-Mar-183-Apr-1810-Apr-1815-Jan-1825-Jan-186-Jun-1744
9Simons8-Mar-1815-Mar-184-Mar-1814-Mar-186-Sep-1816-Sep-187-Jun-1743
10Dean9-Apr-1816-Apr-189-Oct-1819-Oct-182-Feb-1812-Feb-189-Jun-1745
11George15-Apr-1828-Apr-183-May-1811-May-187-May-1817-May-188-Jun-1746
12
13PR1App?PR2App?PR3App?SenAge
14NameStEndStEndStEnd
15Jones3-Jan-1812-Jan-18No6-May-1814-May-18No4-Apr-1814-Apr-18No3-Jun-1735
16Smith13-May-1825-May-18Yes10-Nov-1820-Nov-18NA7-Jun-1817-Jun-18NA2-Jun-1730
17Chan2-Jan-183-Jan-18Yes5-Dec-1812-Dec-18NA13-Aug-1823-Aug-18NA1-Jun-1740
18Wills12-Jan-1823-Jan-18No2-Jul-1818-Jul-18Yes5-Oct-1815-Oct-18NA4-Jun-1741
19Thom6-Feb-1813-Feb-18Yes1-Mar-1811-Mar-18NA4-Jul-1814-Jul-18NA5-Jun-1742
20Ford3-Mar-1817-Mar-18Yes3-Apr-1810-Apr-18NA15-Jan-1825-Jan-18NA6-Jun-1744
21Simons8-Mar-1815-Mar-18No4-Mar-1814-Mar-18No6-Sep-1816-Sep-18Yes7-Jun-1743
22Dean9-Apr-1816-Apr-18No9-Oct-1819-Oct-18Yes2-Feb-1812-Feb-18NA9-Jun-1745
23George15-Apr-1828-Apr-18Yes3-May-1811-May-18NA7-May-1817-May-18NA8-Jun-1746
Sheet1
 
  • Like
Reactions: DAD
Upvote 0
Hi Brian,

Thank you so much mate. Absolutely brilliant. I will set to work tonight to test it and see if I can understand how you did it. I will report back tomorrow with any questions or problems I find.

So thankful for your time. muchas gracias

Pete
 
Upvote 0
The code does work fantastically well so far, so thank you for that. Maybe I am not understanding it correctly, but so far the code only allocates one leave period? once it is allocated, it ignores the rest? What I am hoping is that, should there be no overlaps, in theory, a person such as Jones can have all three of his proposed leave periods Approved. The priority system is only there to help decide which ones may be declined if there is an overlap. He decides on the most important leave period, but if there is no overlaps, all three may be approved. Again, sorry if I did not explain this well enough.
 
Last edited:
Upvote 0
Ok. If I now understand that correctly, someone whom I have allowed under a Priority 1 but disallowed by virtue of a first allocation is still allowed to have their second, and even third choice, granted provided by virtue of criteria.

Fine. My assumption was to accept the first allocation. Ok, then by your criteria, someone can have up to three preferences approved to be selected as required.
On that basis I've gone back through my code and commented out all lines associated with "NA". That merely means adding an " ' " at the start of the line.

On running the code my small table now looks like this (oh, I've overlaid colours because conditional formatting is not detected):

Excel 2013/2016
ABCDEFGHIJKLMN
1PR1App?PR2App?PR3App?SenAge
2NameStEndStEndStEnd
3Jones3-Jan-1812-Jan-18No6-May-1814-May-18No4-Apr-1814-Apr-18No3-Jun-1735***
4Smith13-May-1825-May-18Yes10-Nov-1820-Nov-18Yes7-Jun-1817-Jun-18Yes2-Jun-1730
5Chan2-Jan-183-Jan-18Yes5-Dec-1812-Dec-18Yes13-Aug-1823-Aug-18Yes1-Jun-1740
6Wills12-Jan-1823-Jan-18No2-Jul-1818-Jul-18Yes5-Oct-1815-Oct-18No4-Jun-1741
7Thom6-Feb-1813-Feb-18Yes1-Mar-1811-Mar-18No4-Jul-1814-Jul-18No5-Jun-1742
8Ford3-Mar-1817-Mar-18Yes3-Apr-1810-Apr-18No15-Jan-1825-Jan-18No6-Jun-1744
9Simons8-Mar-1815-Mar-18No4-Mar-1814-Mar-18No6-Sep-1816-Sep-18Yes7-Jun-1743
10Dean9-Apr-1816-Apr-18No9-Oct-1819-Oct-18Yes2-Feb-1812-Feb-18No9-Jun-1745
11George15-Apr-1828-Apr-18Yes3-May-1811-May-18Yes7-May-1817-May-18No8-Jun-1746
Sheet1
Cell Formulas
RangeFormula
N3=IF(AND(E3="No",H3="No",K3="No"),"***","")

I've added a formula which alerts to situations as "Jones" being deferred three times.
Is this more like we need?
 
Upvote 0
Hi Brian,

That is brilliant mate. Thank you again for your time. It is almost perfect now. The only issue I can see, is that for some reason in priority 2 leave dates, if 2 priority 2 leave dates overlap, it looks at seniority, but it allocates it to the most junior person, not the most senior like it does for the priority 1 column and the Priority 3 column. I have tried sorting through the code, but can't find where the mix up is yet.

Pete
 
Upvote 0
Hi Brian,

I may have found the code, but thought I would check with you first. In sub Lap() the code says "If sen1 > sen2 Then" but in sub lapC the code says "If sen1 < sen2 Then" and in sub lapE it also says "If sen1 < sen2 Then". Could the "less than" sign be the wrong way around in sub lapC and E?
 
Upvote 0
Hi Brian,

I may have found the code, but thought I would check with you first. In sub Lap() the code says "If sen1 > sen2 Then" but in sub lapC the code says "If sen1 < sen2 Then" and in sub lapE it also says "If sen1 < sen2 Then". Could the "less than" sign be the wrong way around in sub lapC and E?
I'll get back to you on that.
I think that you are right as your seniority order goes from oldest to latest which means that sen1 be preferred.
 
Upvote 0
I've gone back and did a "desk-check" against your thoughts.
By that I mean that I have actually scanned what my computer was telling me after it gave me its logic.

Yes, you are correct in your surmise. In creating additional "segments" of code I've copy/pasted but seemingly I've done that from an earlier listing, one I did not void!

In this screenshot we have my check of priority to validate what the computer has already determined to the left. Further down is a table as to what dates are available after the computer transaction.

I am wondering, are you in Australia?
As Annual leave is 4 weeks (maybe 5 if on Shift).
Then too, does your plan have the concept of splitting that leave into 2-2, 3-1 week periods, or even allowing that to be split further?
I'm guessing that, if in Australia, you may have RDOs (Rostered Days Off). Do you have to apply this to your business? Should you need to build that into your calculations?
Lastly, at some point in time you will face Long Service Leave (3/6 months?). That is not addressed.

Probably those are hard questions to be addressed by higher levels of administration.

Excel 2013/2016
ABCDEFGHIJKLMNOP
1PR1App?PR2App?PR3App?SenAge
2NameStEndStEndStEndP1P2P3
3Jones3-Jan-1812-Jan-18No6-May-1814-May-18No4-Apr-1814-Apr-18No3-Jun-1735NNN
4Smith13-May-1825-May-18Yes10-Nov-1820-Nov-18Yes7-Jun-1817-Jun-18Yes2-Jun-1730YYY
5Chan2-Jan-183-Jan-18Yes5-Dec-1812-Dec-18Yes13-Aug-1823-Aug-18Yes1-Jun-1740YYY
6Wills12-Jan-1823-Jan-18No2-Jul-1818-Jul-18Yes5-Oct-1815-Oct-18No4-Jun-1741NYN
7Thom6-Feb-1813-Feb-18Yes1-Mar-1811-Mar-18No4-Jul-1814-Jul-18No5-Jun-1742YNN
8Ford3-Mar-1817-Mar-18Yes3-Apr-1810-Apr-18No15-Jan-1825-Jan-18No6-Jun-1744YNN
9Simons8-Mar-1815-Mar-18No4-Mar-1814-Mar-18No6-Sep-1816-Sep-18Yes7-Jun-1743NNY
10Dean9-Apr-1816-Apr-18No9-Oct-1819-Oct-18Yes2-Feb-1812-Feb-18No9-Jun-1745NYN
11George15-Apr-1828-Apr-18Yes3-May-1811-May-18No7-May-1817-May-18No8-Jun-1746YNN
12
Sheet1




Excel 2013/2016
ABCDEFGHIJKLMNOPQRSTUVWXYZAAABACADAEAF
1Jan145678910111213141516171819202122232425262728293031
2Feb12345141516171819202122232425262728
3Mar1819202122232425262728293031
4Apr12111213142930
5May12345262728293031
6Jun12345618192021222324252627282930
7Jul119202122232425262728293031
8Aug1234567891011122425262728293031
9Sep123451718192021222324252627282930
10Oct12345678202122232425262728293031
11Nov12345678921222324252627282930
12Dec123413141516171819202122232425262728293031
Sheet2

Anyway the code for my "calendar" of left dates is also added.


Code:
Sub clean_dates()
Sheets("Sheet1").Select
Dim a, b, c, d As Long
Dim lastrow As Long
Dim dy1, mt1, dy2, mt2 As Integer
lastrow = Cells(Rows.Count, "C").End(xlUp).Row

For a = 3 To lastrow
Sheets("Sheet1").Select
dy1 = day(Range("sheet1!c" & a).Value) + 1
mt1 = Month(Range("sheet1!c" & a).Value)
dy2 = day(Range("sheet1!d" & a).Value) + 1
mt2 = Month(Range("sheet1!d" & a).Value)
    If Range("sheet1!E" & a).Value = "Yes" Then
        Sheets("sheet2").Select
        Range(Cells(mt1, dy1), Cells(mt2, dy2)).ClearContents
    End If
Next

For a = 3 To lastrow
Sheets("Sheet1").Select
dy1 = day(Range("sheet1!f" & a).Value) + 1
mt1 = Month(Range("sheet1!f" & a).Value)
dy2 = day(Range("sheet1!g" & a).Value) + 1
mt2 = Month(Range("sheet1!g" & a).Value)
    If Range("sheet1!H" & a).Value = "Yes" Then
        Sheets("sheet2").Select
        Range(Cells(mt1, dy1), Cells(mt2, dy2)).ClearContents
    End If
Next

For a = 3 To lastrow
Sheets("Sheet1").Select
dy1 = day(Range("sheet1!i" & a).Value) + 1
mt1 = Month(Range("sheet1!i" & a).Value)
dy2 = day(Range("sheet1!j" & a).Value) + 1
mt2 = Month(Range("sheet1!j" & a).Value)
    If Range("sheet1!K" & a).Value = "Yes" Then
        Sheets("sheet2").Select
        Range(Cells(mt1, dy1), Cells(mt2, dy2)).ClearContents
    End If
Next
End Sub
 
  • Like
Reactions: DAD
Upvote 0
Hi Brian,

Thank you so much again, I will run some detailed testing again tonight and tomorrow.

With regard to your questions, yes I am located in Australia, and we do have RDO's scheduled, but they are based on a roster system, and therefore do not impact the leave system. As for the leave splitting, we are hoping a system like this will negate the need to mandate fixed duration of leave splitting, giving everyone more flexibility. Though that may need to change in the future, we will have to trial it and see. You raise a good point regarding the Long Service Leave, but at this stage we will keep that on a different ledger. My initial reaction is that a good deal of thought needs to be put into that before we can embark on incorporating that into this system. But great ideas, my gut tells me you have been in Management positions over the years!

Thanks again, I'll get back to you after some testing.

Pete
 
Upvote 0

Forum statistics

Threads
1,223,238
Messages
6,170,939
Members
452,368
Latest member
jayp2104

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top