I have an Excel macro which calculates no. of hours spent on a task for each day in a month.
The first row contains day numbers from 1 to 31 and data is filled using the macro accordingly for each day number for a month. The sheet name contains the month name.
Now, the problem is the macro leaves blank for the days for which data is not available. That day can be a Saturday, Sunday, or the person was absent that day.
I want the macro to identify weekends and highlight those with gray color so that only absent days appear as blank.
Using cell formulas and conditional formatting (VBA below)
You could do this quite easily with the built-in WEEKDAY cell formula, together with the DATE formula.
By setting up the year and month value in the sheet, you can create an extra column which gives the day of the week as a number between 1 and 7:
=WEEKDAY(DATE($A$2, $B$2,C2))
Then you can set up conditional formatting to colour days 7 and 1 (Saturday and Sunday respectively) grey
Using VBA
You can apply the same logic as above, but from a sub. This doesn't require the month and year values to be stored in the sheet, and takes the month from the sheet name. It then directly colours the day number grey if on the weekend.
Sub weekdayhighlight()
Dim days As Range
Set days = ActiveSheet.Range("C2:C8") ' Range where date numbers are stored, 1,2,...,31
Dim month As String
month = ActiveSheet.Name ' Active sheet name is "May"
Dim day As Range
Dim daynum As Long
' Loop over days to test for weekday
For Each day In days
' Get day number, from date in format "1 May, 2017"
daynum = Weekday(DateValue(day.Value & " " & month & ", 2017"), firstdayofweek:=vbSunday)
If daynum = 7 Or daynum = 1 Then
day.Interior.Color = RGB(200, 200, 200) ' Grey for saturdays or sundays
End If
Next day
End Sub
Note: This macro will throw an error if you try and compute the weekday of a non-existant date, for instance the 31st of Feb. You say each sheet has day numbers from 1 to 31, you should limit that to actual existing dates or add error handling to the code.
Try combining your sheet name and column headers into date (what about a year?) in a loop and then use DatePart() function to determine whether it is weekend day or not. It would be easier if column headers were real dates (may be formatted to show day only).
Related
I have this monthly work report sheet. And I don't know how to make some autofill for column B which will provide a number of a day for a right name of a week day in column A.
I was only able to find formula which gave me date of first work day in first week of the month.
This will take month and year from B2 and B3 cells and generate first
day in month:
=TEXT(DATEVALUE(CONCATENATE(1;B2;B3));"dd.mm.yyyy")
This will find from first day in mnoth the first working day.
=TEXT(WORKDAY(EOMONTH(R2;-1); 1);"dd.mm.yyyy")
But the first problem is that the each next month a first work day starts in different name of a week.
And second problem is that the each week has a "Sum:" after each friday.
Please, can someone provide me any solution via formulas or macro?
This is really poorly written tbh, but maybe you can make use of it.
Basically, just select the cell that has the first day of the month and enter the date:
The code will then use the current date and work its way down your list until it runs into Sum: at the bottom or the current month ends and put in the date using dd.mm format (feel free to change this in the code).
If it finds Sum: to its left, it will add 3 days to its current date.
Otherwise, it will add 1 day to its current date.
Worth noting that it looks for the name of the current month in cell B2
If you want to add a period after the format (like you showed in your screenshot), just add an extra . to the line Format(aDate, "dd.mm")
It would become ActiveCell.Value = Format(aDate, "dd.mm.")
Sub GenerateDates()
Dim aDate
aDate = InputBox("Enter Date of Current Cell", "Enter Date of Current Cell")
If IsDate(aDate) Then
aDate = DateValue(aDate)
Do While ActiveCell.Value = ""
ActiveCell.Value = Format(aDate, "dd.mm")
ActiveCell.Offset(1, 0).Select
If ActiveCell.Offset(0, -1).Value = "Sum:" Then
aDate = DateAdd("d", 3, aDate)
ActiveCell.Offset(1, 0).Select
Else
aDate = DateAdd("d", 1, aDate)
End If
If MonthName(Month(aDate)) <> Range("B2").Value Then Exit Sub
Loop
Else
MsgBox "Invalid Date", vbCritical, "Invalid Date!"
Exit Sub
End If
End Sub
Of course, this could be modified to assume that you select the first of the month on the cell - or it could attempt to figure out the first of the month for you to begin by starting at the top, but this just seemed simple enough.
Display the date in reference to the weekdays
Let's use an Excel formula:
=LET(
WeekRange; A6:A34;
WeekInterval; 6;
ThisMonth; MATCH(B2; {"January";"February";"March";"April";"May";"June";"July";"August";"September";"October";"November";"December"};);
ThisYear; B3;
WeekNames; {"Monday";"Tuesday";"Wednesday";"Thursday";"Friday"};
FirstDay; DATE(ThisYear; ThisMonth; 1);
LastDay; EOMONTH(FirstDay; 0);
FirstWorkDay; WORKDAY(EOMONTH(FirstDay; -1); 1);
WeekShift; WEEKDAY(FirstWorkDay; 2);
WeekInMonth; QUOTIENT(ROW(WeekRange) - INDEX(ROW(WeekRange); 1); WeekInterval);
WorkDays; IFNA(FirstWorkDay - WeekShift + MATCH(WeekRange;WeekNames;0) + 7*WeekInMonth; "");
TEXT(WorkDays; "[<" & FirstDay & "] ;[>" & LastDay & "] ;dd.mm."))
Details:
WeekInterval - the number of cells between the same weekdays
WeekShift - the weekday of the first workday of the month starting from Monday
WeekInMonth - a week number in WeekRange
IFNA(...; "") - put an empty string next to the "Sum:"
"[<FirstDay] ;[>LastDay] ;dd.mm." - display a space when a date is outside the month (keep spaces after closing square brackets ])
I use semicolon ; as a separator due to my locale settings.
This formula has to be placed once next to the first Monday of the WeekRange (in your case in a cell B6). The result will be spilled on weekdays.
I have a worksheet with three columns. Column C:C has all calendar dates, N:N contains Data 1 and R:R Data 2.
The macro I am trying to write should check dates in Column C to find dates that are (EDIT) less than today and copy data of Column R:R to Column N:N.
Does this make sense? I have a feeling it's a super basic thing, but oh well, I spent one hour Googling without success.
Example
Thanks!
In Excel a date is just the number of days which starts counting from January 1st 1900. So January 1, 1900 is number 1. With this in mind, it is very easy to calculate with dates. Hours and minutes are fractions.
This sub should do the job:
Sub CopyData()
For i = 1 To 100
If Cells(i, 3) < DateTime.Date Then
Cells(i, 14) = Cells(i, 18)
End If
Next
End Sub
Replace the number 100 with the amount of lines you have or with some logic to count the number of lines.
Succes.
Is it possible to have Excel freeze a calculated date until the calculated date itself has passed?
Within the Excel example below, Today's Date is formulated with TODAY(), and Next Proposed Meeting is a calculated date by adding Today's Date plus Meeting Cadence.
Excel Example:
Here is what I'm looking to do: when a user opens the workbook and sets the initial meeting cadence, I would like to freeze the Next Proposed Meeting date until that specific date meets the date referenced in today's date.
(Example: today's date is Monday, October 1, 2018 and the next proposed meeting date is Monday, October 1, 2018).
When the two dates match, I would like it to cycle to the next date, depending on the numerical value of the cadence. So, if the meeting cadence continued to be 7 days, the Next Proposed Meeting cell would automatically populate to "Monday, October 8, 2018."
What would be the best way to accomplish this?
Cheers, and thank you!
:)
Hacked this out.
In a module:
Sub setCurrentProposedDate(cadenceChanged As Boolean)
Dim currProposedDate As Name, currCadence As Name
Set currProposedDate = ThisWorkbook.Names.Item("CurrentProposed")
Set currCadence = ThisWorkbook.Names.Item("CurrentCadence")
If cadenceChanged Then
currProposedDate.Value = Sheet1.Range("B2").Value - Evaluate(currCadence.Value) + Evaluate(currProposedDate.Value)
currCadence.Value = Sheet1.Range("B2").Value
End If
If Sheet1.Range("B1").Value - Evaluate(currProposedDate.Value) >= 0 Then
currProposedDate.Value = Sheet1.Range("B2").Value + Evaluate(currProposedDate.Value)
End If
End Sub
In workbook module:
Private Sub Workbook_Open()
setCurrentProposedDate False
End Sub
In Sheet1 module:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Sheet1.Range("B2")) Is Nothing Then
setCurrentProposedDate True
End If
End Sub
Set workbook level names to be :
Put this formula in B3:
=CurrentProposed
Here is a stab at doing that via formula...
- Set a Project Start Date such as Monday, 3 September, 2018 in B1
- Enter your cadence value (7, 10, 14, etc.) in B2
- Formula for "Next Meeting" in B3 is =SUM(B1,PRODUCT(ROUNDDOWN(DAYS(TODAY(),B1)/B2,0)+1,B2))
Explanation:
- The Rounded down value of the date difference between two dates (Start Date and Today) gives you a whole number indicating the number of periods (based on cadence) you are after the start
- Add one to that b/c you want to predict the next meeting date
- Multiply that by the cadence to get the number of days until next meeting date (from the start)
- Modify the cadence (B2) and your next meeting date should adjust appropriately.
I tested with my project and a few random dates and cadences and it seems to work.
I spent last night looking for an answer to my question but i didn't find anything specific to my ask.
I have a huge sheet that contains lots of data. In Column A, I have the Date and time. I would like to have a VBA code that does few actions.
1) Insert a column B next to column A that gives the weekday name. For example if the date in column A is January 10, 2016 8:30 then column B will have "Sunday"
2) Then the VBA code to filter this sheet based on Column B. For instance given a user input of a particular day (example Friday), the autofilter will filter for 4 days ahead ( Friday, Saturday, Sunday, Monday ).
3) The result of the autofilter then is copied to new blank sheet.
4) In the new sheet I want the vba to delete any row data for the same user defined day ( example Friday ) that has time of less than user defined time (example 8:00 am) in Column A. Finally shifting cells up to remove any blank rows.
Hope I am not overwhelming you with this problem, but I hope I get feedback from one of the brilliant minds in here
Here it the code attempted for part 1
Sub sbInsertingColumns()
Worksheets("Imported").Activate
'Inserting a Column at Column B
If Range("B1").Value = "Weekday" Then
Range("B1").Value = "Weekday1"
Else
Range("B1").EntireColumn.Insert
Range("B1").Value = "Weekday"
Worksheets("Imported").Range("B2").Formula = "=choose(weekday(A2),""Sunday"",""Monday"",""Tuesday"",""Wednesday"",""Thursday"",""Friday"",""Saturday"")"
LastRow = Range("A" & Rows.Count).End(xlUp).Row
Range("B2").Copy Range("B2:B" & LastRow)
End If
End Sub
This is only to get you started.
If A2 contains a genuine Excel date/time, then in B1 enter:
=TEXT(A2,"dddd")
If you want a VBA macro to accomplish your project, start by turning on the macro recorder and performing the task once manually.
You will then have a macro that you can begin to optimize and generalize.
I am trying to move data from a 5 column spread sheet in excel to other sub spread sheets based on one of the date columns in the first spread sheet. The sub-spreadsheets will be created if they do not exist, otherwise they will be populated with data from the master spreadsheet. The spread sheets names will be a date that is the start of the week(being monday). my columns are: Work Order, Description, Location, Asset, Date.
Example:
Work Order - Description - Location - Asset - Date
123 ---------- test&inspect - NC-231 - KK32 - 8/21/14
In this example my master spreadsheet with a date row of 8/21/14 will create a subspread sheet with a name of 8/18/14 since this row falls in the week of 8/18/14 and insert the other columns with it. How can this be done inside of an excel workbook?
Dim firstDate As Date, secondDate As Date
Dim I as Date
firstDate = Inputbox("What start date?") ' request your input for what date Monday is
secondDate = DateAdd("d", 6, firstDate)
For Each Cell in Range("E2"),Range("E2").End(xldown)
ActiveCell = Cell
If cell => firstdate and =< secondate then ' test if falls under days of week
ActiveCell.Row.Copy
On error resume next
Worksheets.Add.Name = Firstdate
Sheets(" & Firstdate &").Select
Range("A1").End(lxDown).Offset(1,0).pastespecial
Next Cell
End Sub
Not tested but should be a start .