There are around 500 slides, the first slide is an introduction, second slide is for instructions with the action button for the Start_time macro - once clicked the timer starts. Slides 3 - 499 have one word in each, so the reader will have to go through each of the slide in a period of time, that's why the word_count equals slide.count minus three. The last slide will have the action button that when clicked will show the reading evaluation.
This macro is for my PowerPoint presentation intended to give a reading evaluation to my students.
Dim Start_time As Date
_______________________________________________________________________________________
Sub Start_time()
'at action button click in the first slide the time starts counting
Start_time = Now()
End Sub
_______________________________________________________________________________________
Sub ReadingTime()
'at action button click on the last slide the evaluaton message appears
Dim Reading_Time As String
Dim End_Time As Date
Dim iTotal_time As Long
Dim Word_count As Integer
End_Time = Now()
iTotal_time = DateDiff("d", End_Time, Start_time)
Word_count = ActivePresentation.Slides.Count - 3
Reading_Time = Word_count / iTotal_time * 24 * 60
MsgBox "Evaluation : Your reading speed is " & Reading_Time & "words per minute"
End Sub
Didn't you mean end_time = now()?!!!
Another deeper issue is you probably want to declare start_time at the top of the module as it will go out if scope (I.e. will no longer be available) once the start_time sub exits: type
dim start_time
right at the top of the module to do this.
Try this:
Dim m_start_time As Date 'renamed this as it clashes with a function name
Public Sub Start_time()
'at action button click in the first slide the time starts counting
m_start_time = Now()
End Sub
Public Sub ReadingTime()
'at action button click on the last slide the evaluaton message appears
Dim Reading_Time As String
Dim End_Time As Date
Dim iTotal_time As Double 'use a double as fraction days are important
Dim Word_count As Integer
End_Time = Now()
iTotal_time = End_Time - m_start_time
Word_count = ActivePresentation.Slides.Count - 3
Reading_Time = Word_count / iTotal_time * 24 * 60
MsgBox "Evaluation : Your reading speed is " & Reading_Time & "words per minute"
End Sub
Related
I have too many meetings at work, so I thought I might use an Outlook VBA macro to block my calendar when I have too many meetings, so I can use the rest of the time to actually get things done.
`Sub BlockMoreCalendarAppts()
Dim myAcct As Outlook.Recipient
Dim myFB As String
Dim tDate As Date
Dim d As Long
Dim i As Long
Dim test As String
Dim oAppt As AppointmentItem
' it needs to know whose FB to check
Set myAcct = Session.CreateRecipient("name.lastname#domain.com")
' days to check
For d = 0 To 5
tDate = Date + d
' use start of working day or there about
' false counts tenetive and oof as busy
myFB = myAcct.FreeBusy(tDate + #9:30:00 AM#, 5, False)
' this gets the # of 5 min periods before the start time
i = (TimeValue(tDate + #9:30:00 AM#) * 288)
' only count free busy for 7:10 hours from start + at least 1 additional 5 min period
' # of min in working day / 5
' skips busy times in the evening
test = Mid(myFB, i, 435 / 5)
CountOccurrences = UBound(Split(test, "1")) ' busy, oof or tentative
' theoretical WHERE statement goes here?
CountO = UBound(Split(test, "0")) ' free
'round to hours for subject
times = Round(((CountOccurrences * 5) / 60), 2)
' create all day busy event
' there are 12 5 minute periods per hour
' 60 = 5 hours
If CountOccurrences >= 60 Then
' default calendar
Set oAppt = Application.CreateItem(olAppointmentItem)
With oAppt
.Subject = times & " hours of appt today"
.Start = tDate
.ReminderSet = False
.Categories = "Full Day"
.AllDayEvent = True
.BusyStatus = olBusy
.Save
End With
End If
' check next day
Next d
End Sub`
The logic is that if I have more than 5 hours of meetings in a day, it sets an all day appointment and marks me as busy.
I tested the attached macro, which works, but, I want to filter out appointments which contain certain words in the subject. For example, "Lunch" or "Focus". In other words, I don't want "Lunch" to be counted in my five hours of meetings.
I have not figured out how to use a WHERE function to filter particular appointments for that day. Any help would be appreciated.
This is based (heavily) on the great work of Diane Poremsky at https://www.slipstick.com/outlook/calendar/limit-number-appointments-day/
If you switch to looping through appointments then you could add them all up like that? Pseudocode:
' Set the start and end times for the day
Dim startTime As Date
startTime = DateSerial(year, month, day) + TimeValue("9:00 AM")
Dim endTime As Date
endTime = DateSerial(year, month, day) + TimeValue("5:00 PM")
' Set the search criteria for the appointments
Dim filter As String
filter = "[Start] >= '" & startTime & "' AND [End] <= '" & endTime & "'" & _
"AND [Subject] NOT Like '*focus*'"
' Get the calendar folder for the default account
Dim calendarFolder As Folder
Set calendarFolder = Application.Session.GetDefaultFolder(olFolderCalendar)
' Set the current appointment to the first appointment of the day
Dim currentAppointment As AppointmentItem
Set currentAppointment = calendarFolder.Items.Find(filter)
' Loop through all appointments on the day
Do While Not (currentAppointment Is Nothing)
' Process the current appointment
' ...
' Get the next appointment
Set currentAppointment = calendarFolder.Items.FindNext
Loop
I used the following code to have a Countdown which would span over 10 slides whilst in slideshow mode. I placed the shapes in a SlideMaster Layout.
Set QS = ActivePresentation.Designs(2).SlideMaster.CustomLayouts(2)
Dim Seconds As Integer
Seconds = 30
QS.Shapes("Counter").TextFrame.TextRange = Seconds
For i = 1 To 30
Dim WAIT As Double
WAIT = Timer
While Timer < WAIT + 1
DoEvents
Wend
Seconds = Seconds - 1
QS.Shapes("Counter").TextFrame.TextRange = Seconds
Next i
Dim time As Date
Dim count As Integer
time = Now()
count = 30
time = DateAdd("s", count, time)
Do Until time < Now
DoEvents
With ActivePresentation.Designs(2).SlideMaster.CustomLayouts(2).Shapes("Counter").TextFrame.TextRange
.Text = Format((time - Now()), "hh:mm:ss")
End With
Loop
Both the codes work properly if they are not placed in SlideMaster Layout.
Are there any better means to have a countdown that spans across multiple slides?
There is a better way to show a countdown by using the Format (Now(), "hh:mm:ss")
To create a countdown we need two values:
The current time
The future time when the countdown expires
Dim time As Date
Dim count As Integer
time = Now() 'the current time
count = 30
time = DateAdd("s", count, time) 'the future time after 30 seconds
The above gives us the two values.
Now, we can make a loop to change the text inside the Counter shape.
Do Until time < Now() 'We change text until the present time passes the set "future time"
DoEvents
For i = 1 To 10 'Assuming you want the countdown in slides 1 To 10
With ActivePresentation.Slides(i).Shapes("countdown").TextFrame.TextRange
.Text = Format((time - Now()), "hh:mm:ss")
End With
Next i
Loop
You can use this to have a countdown across multiples slides.
I mocked up similar code along the lines of:
Set Shape = Application.ActivePresentation.Designs(1).SlideMaster.CustomLayouts(1).Shapes("Testing")
Shape.TextFrame.TextRange.Text = "Did it work"
As you found, the shape's text did not change while presenting the slideshow, although it did update the underlying slide master once you left the slideshow. However, I found that by including the following after this code, it worked as expected:
Shape.Visible = msoTrue
I am trying to create a button that will hide rows based on the date the function reads.
My excel sheet is for meeting minutes, and based off column D, I will decide whether to hide or show the cell row. Now, column D contains dates of particular minutes, but occasionally contains a string called "Date" as part of a header row. For some reason, I cannot successfully write an if statement to skip said rows. Therefore, I am getting an error where my variable Current_Date is assigned the default VBA date value and my code crashes.
I made sure to format those particular cells as "Text" on the spread sheet, but it seems like my if statement still does not execute.
Can some one please provide me with some guidance.
Thank you in advance.
Private Sub CommandButton1_Click()
Dim x As Integer
Dim Current_Date As Date
Dim Last_Meeting_Date As Date
Dim default_date As Date
' Loop to hide old meeting minutes
For x = 150 To 1000
If Worksheets("Minutes").Cells(x,4) = "Date" Then
x = x + 1
End If
Current_Date = Worksheets("MINUTES").Cells(x, 4)
Last_Meeting_Date = Worksheets("HOME").Cells(19, 16)
If Current_Date < Last_Meeting_Date Then
Worksheets("MINUTES").Rows(x).Hidden = True
End If
Next x
End Sub
You might try:
Private Sub CommandButton1_Click()
Dim x As Integer
Dim Current_Date As Date
Dim Last_Meeting_Date As Date
Dim default_date As Date
Last_Meeting_Date = Worksheets("HOME").Cells(19, 16)
' Loop to hide old meeting minutes
For x = 150 To 1000
If Worksheets("Minutes").Cells(x,4) <> "Date" Then 'You might want to use IsDate()?
Current_Date = Worksheets("MINUTES").Cells(x, 4)
'original code is only able to hide row, this one can unhide them as well
Worksheets("MINUTES").Rows(x).Hidden = (Current_Date < Last_Meeting_Date)
End If
Next x
End Sub
I took a few liberties in reformatting and simplifying your code. I reordered the declarations, removed 'default date' since it was unused, changed your references to column '4' to 'D', reversed the logic of your if statement, and used a 'With' statement to prevent repeated specifications of your Worksheet.
Private Sub CommandButton1_Click()
Dim Last_Meeting_Date As Date
Last_Meeting_Date = CDate(Worksheets("HOME").Cells(19, 16).Value2)
Dim x As Long
Dim Current_Date As Date
' Loop to hide old meeting minutes
With Worksheets("MINUTES")
For x = 150 To 1000
If CStr(.Cells(x, "D").Value2) <> "Date" Then
Current_Date = CDate(.Cells(x, "D").Value2)
If Current_Date < Last_Meeting_Date Then .Rows(x).Hidden = True
End If
Next x
End With
End Sub
I have a excel file.
I wish to write a Excel vba to compare the system time and the cell value time.
If system time is exceed the cell value time, it will show a pop out message to inform user that, the time is exceed.
My file will look like this:
I have been research a while but seem like only vba code will able to complete this requirement.
Sub TimeCheck()
Dim ValueTime As Date
Dim SysTime As Date
SysTime = Now()
Finalrow = Cells(Rows.Count, 14).End(xlUp).Row
'Column 14 stands for N, change as required
For I = 6 To Finalrow
'6 stands for first row filled with value, change as required
ValueTime = Cells(I, 14).Value
If TimeValue(ValueTime) < TimeValue(SysTime) Then
Cells(I, 14).Offset(, 1).Value = "Time is exceeeded" '1 is offsetting to column O. Use 2 for column P, 3 for Q and so on, as you prefer.
MsgBox ("Time is exceeeded for user entry in N" & I)
'To store the time error in adjacent O column cells, and to popup for each error
'Remove either as required - esp MsgBox, it is very annoying - put only because you asked in original question
End If
Next I
End Sub
If you want only advise the guest that the time input does not exceed the current, you don't need a vba (intersect will be one way) you can use the validate date
and you can customize the input msg and also the error msg if the value isn't correct.
Example
Sub TimeNow()
Dim cValue As Date '// Cell Value
Dim sTime As Date '// System
cValue = Sheets("Sheet1").Range("B2").Value
sTime = TimeValue(Now)
If sTime > cValue Then
MsgBox "TiMe iS Up. STOP " & TimeValue(Now)
Else: Exit Sub
'or do something
End If
End Sub
You can use the function TimeValue, which returns the value of time as a number between 0 and 1. Posting a simple code to check on cell N6 alone.
/// You may, of course, use loops to check for a range of cells, or use the excel events, or keyboard shortcuts to run the macro.///
Sub TimeCheck()
Dim ValueTime As Date
Dim SysTime As Date
ValueTime = Range("N6").Value
SysTime = Now()
If TimeValue(ValueTime) < TimeValue(SysTime) Then
MsgBox ("Time is exceeeded")
End If
End Sub
Hello I have this program that lets you start and stop time on a job the problem I am having now is that if it switches from A.M to P.M while time is tracked the program doesn't work right. so I have a button that puts the Time.Now when its pressed in a excel cell than when you stop the job it puts the End time in another cell and then it go's in and grabs the two cells and subtracts them. what I need it to do is put the Date and Time in the cell then both and only give me the Minutes and hours that it took. here is what I have for code.
'This code is for when you start the job.
'which this is only hours and minutes prob should be
'Date and Time
Dim StartTime As String = DateTime.Now.ToString("h\:mm")
'This line of code puts it in an excel cell
oXL.ActiveCell.Offset(0, 13).Value = StartTime
'This code is for when you end a Job.
'Again its only hours and minutes but prob should be
'Date and Time
Dim EndTime As String = DateTime.Now.ToString("h\:mm")
'This is the Total Time I am going to have
'I used TimeSpan
Dim TotalTime As TimeSpan
'Now this is where I put the End time when the
'Button is clicked.
oXL.ActiveCell.Offset(0, 14).Value = EndTime
'Once Both cells have the start and end Times I get them both with this code.
'Again this should prob be Date and Time.
Dim time1 = TimeSpan.ParseExact(oXL.ActiveCell.Offset(0, 13).Value, "h\:mm", CultureInfo.CurrentCulture)
Dim time2 = TimeSpan.ParseExact(oXL.ActiveCell.Offset(0, 14).Value, "h\:mm", CultureInfo.CurrentCulture)
'I then use this code to do my math.
TotalTime = time2 - time1
The Total time I need i only to be the hour an minutes that it took to do the job.
You are taking two dates, converting them and storing them into string variables, then reading them back into dates to calculate. You are hoping that they are in the right format when you parse them back, this in itself is top heavy. But why store dates as string at all? You can convert a date to a string at any time on the fly with the .ToString() method. Just keep them as dates and write them out to the excel sheet as strings when needed. The values will be the same either way, and you're not relying on your sheet to have the data in the adjacent locations, you will just perform the calculation and you are done.
'This code is for when you start the job.
'which this is only hours and minutes prob should be
'Date and Time
Dim StartTime As DateTime = DateTime.Now
'This line of code puts it in an excel cell
oXL.ActiveCell.Offset(0, 13).Value = StartTime.ToString("h\:mm")
'This code is for when you end a Job.
'Again its only hours and minutes but prob should be
'Date and Time
Dim EndTime As DateTime = DateTime.Now
'Now this is where I put the End time when the
'Button is clicked.
oXL.ActiveCell.Offset(0, 14).Value = EndTime.ToString("h\:mm")
'Once Both cells have the start and end Times I get them both with this code.
'Again this should prob be Date and Time.
' Dim time1 = TimeSpan.ParseExact(oXL.ActiveCell.Offset(0, 13).Value, "h\:mm", CultureInfo.CurrentCulture)
' Dim time2 = TimeSpan.ParseExact(oXL.ActiveCell.Offset(0, 14).Value, "h\:mm", CultureInfo.CurrentCulture)
'This is the Total Time I am going to have
'I used TimeSpan
Dim TotalTime As TimeSpan
'I then use this code to do my math.
TotalTime = EndTime.Subtract(StartTime)
'output time difference
MsgBox(TotalTime.ToString)
.:EDIT:.
To give you an example of total hours and minutes:
Dim startTime As DateTime = DateTime.Now 'read from excel instead
Dim endTime As DateTime = DateTime.Now.AddDays(1.5).AddMinutes(60) 'read from excel
Dim span As TimeSpan
span = endTime.Subtract(startTime)
MessageBox.Show("Total Hours: " & (span.Days * 24) + span.Hours & ", Total Mins: " & span.Minutes)
I hope this will be able to assist in your calculation (grabbing a start and end date string, converting it to DateTime, then outputting the hours and minutes):
'This code is for when you start the job.
'which this is only hours and minutes prob should be
'Date and Time
Dim StartTime As String = DateTime.Now.ToString("h\:mm")
'This code is for when you end a Job.
'Again its only hours and minutes but prob should be
'Date and Time
Dim EndTime As String = DateTime.Now.AddHours(3.5).ToString("h\:mm")
'This is the Total Time I am going to have
'I used TimeSpan
Dim TotalTime As TimeSpan
'Once Both cells have the start and end Times I get them both with this code.
'Again this should prob be Date and Time.
Dim time1 = DateTime.Parse(StartTime)
Dim time2 = DateTime.Parse(EndTime)
'I then use this code to do my math.
TotalTime = time2 - time1
Dim Hours = TotalTime.Hours
Dim Minutes = TotalTime.Minutes
System.Console.WriteLine(Hours & "h " & Minutes & "m")