I've written the following to get calendar items for a certain date range:
Sub printCal()
Dim sesh As Outlook.NameSpace
Set sesh = ThisOutlookSession.Session
Dim myCal As MAPIFolder
Set myCal = sesh.GetDefaultFolder(olFolderCalendar)
Dim target As Recipient
With sesh.GetSelectNamesDialog
.AllowMultipleSelection = False 'aside: this doesn't seem to force me to select only one
.ForceResolution = True
Debug.Print "displaying: "; .Display
Set target = .Recipients.Item(1)
End With
Dim targetCalendar As MAPIFolder
Set targetCalendar = sesh.GetSharedDefaultFolder(target, olFolderCalendar)
Dim x As Variant
'ISSUE these calendars aren't VBA accessible unless shared all details
'https://social.msdn.microsoft.com/Forums/en-US/bffddb8e-0344-459f-a586-105035eb4192/permission-levels-for-shared-calendars-when-reading-with-vba?forum=outlookdev
For Each x In targetCalendar.Items.Restrict( _
"[Start]>='08/06/2022 1 AM' and [End] <='08/06/2022 10 PM'" _
)
Debug.Print x.Start; x.Duration; "mins", x.Subject
Next
End Sub
This works for my calendar or someone who has shared their calendar publicly/with me specifically. It does not work for a calendar I can see in the scheduling assistant (they are in my organisation) but the titles of meetings are hidden.
I'm trying to write a VBA addin for Outlook that uses an algorithm I came up with to schedule meetings.
I only need to know when people are busy. Can I get it from the raw mail server rather than the Outlook API?
Recipient.FreeBusy does the trick. It shows when someone is marked as busy for the next 30 days in n minute intervals. e.g.
Sub useFreeBusy()
Dim target As Recipient
Set target = ThisOutlookSession.Session.CreateRecipient("Joe Bloggs")
Dim status As String
Const INTERVAL As Long = 60
status = target.FreeBusy(Date, INTERVAL, True) '60 min intervals 00:00 today, True showing all status info
Dim i As Long
For i = 1 To Len(status)
Dim slotTimestamp As Date
slotTimestamp = DateAdd("n", INTERVAL * (i - 1), Date)
Dim statusNumber As String
statusNumber = Mid(status, i, 1)
Debug.Print slotTimestamp ;statusNumber ; "-"; IIf(statusNumber = "0", "Free", "Busy")
Next i
End Sub
Which outputs something like:
14/02/2023 08:00:00 0-Free
14/02/2023 09:00:00 0-Free
14/02/2023 10:00:00 0-Free
14/02/2023 11:00:00 0-Free
14/02/2023 12:00:00 2-Busy
14/02/2023 13:00:00 0-Free
14/02/2023 14:00:00 1-Busy
14/02/2023 15:00:00 0-Free
14/02/2023 16:00:00 0-Free
14/02/2023 17:00:00 0-Free
14/02/2023 18:00:00 0-Free
14/02/2023 19:00:00 0-Free
14/02/2023 20:00:00 0-Free
[etc...]
Graph SDK requires you to have Global Admin permissions in Azure in order to view the calendars of other users. I don't have this.
Related
I'm trying to figure out how to calculate log hours with different dates.
Here's my sample code. It works fine but when the dates are different, it produces negative result.
'03-14-2018 4:00:00 PM
'03-015-2018 1:00:00 AM
Login = 4:00:00 PM
Logout = 1:00:00 AM
total = Logout - Login
totalHours = (total / 1) * 24
Thanks in advance.
If you are using literal Date/Time then you can use it as
Sub Sample()
Dim Login As Date, Logout As Date
Login = #3/14/2018 4:00:00 PM#
Logout = #3/15/2018 1:00:00 AM#
Total = Logout - Login
totalHours = (Total / 1) * 24
Debug.Print totalHours
End Sub
If your time is in a String variable then you can use DateDiff
Sub Sample()
Dim Login As String, Logout As String
Login = "03-14-2018 4:00:00 PM"
Logout = "03-15-2018 1:00:00 AM"
Total = DateDiff("n", Logout, Login) / 60
Debug.Print Total
End Sub
I am using VB.NET. I have a dropdownlist named startTimeDDL. Than I am using loop to enter in time inside that dropdownlist.
' Auto fill "Start Time" for DropDownList
Dim StartTime As DateTime = #12:00:00 AM#
For i As Integer = 0 To 47
StartTimeDDL.Items.Add(StartTime.ToString("hh:mm tt"))
StartTime = DateAdd(DateInterval.Minute, 30, StartTime)
Next
So look below and that will be inside the dropdownList. notie the format is hh:mm am/pm.
12:00 AM
12:30 AM
01:00 AM
01:30 AM
02:00 AM
...
11:30 PM
Problem:
lets say current time is 1:21:01 pm than I want to write code so it select 1:30 pm from dropdownlist. Now les take another example. les say current time is 12:00:00 AM than I was to select 12:30 AM from dropdownlist. les take one last example. les say current time is 2:10:12 AM than I want to select 2:30 AM from the dropdownlist.
here is the code I wrote so far. problem with it is that I am only selecting the current time. now can I modfily to do what I want?
Dim dDate As DateTime = DateTime.Now.ToString("hh:mm tt")
Dim temp As String = dDate
StartTimeDDL.Items.FindByValue(temp).Selected = True
Round up if the minute value exceeds 30, round down if it's lower.
Here is an example implementation, you'll need to decide what to do with the "exactly 30 minutes past the hour" edge case. In my code it'll round up for that too.
Private Function RoundDateToHalfHours() As Date
Dim current As DateTime = DateTime.Now
Dim ts As TimeSpan
If current.Minute >= 30 Then
ts = New TimeSpan(current.Hour + 1, 0, 0)
Else
ts = New TimeSpan(current.Hour, 30, 0)
End If
Return current.Date.AddTicks(ts.Ticks)
End Function
Usage:
Dim roundedDate As DateTime = RoundDateToHalfHours()
StartTimeDDL.Items.FindByValue(roundedDate.ToString("hh:mm tt")).Selected = True
You are playing fast and loose with DateTime when you should be using TimeSpan, some caution required. The general way to round up an integral number to an arbitrary interval is
roundedUp = interval * ((number + interval - 1) \ interval)
Which you can readily use on DateTime as well by converting it to ticks, a one-liner
Public Function RoundupDate(dt As DateTime, interval As TimeSpan) As DateTime
Return New DateTime(interval.Ticks * ((dt.Ticks + interval.Ticks - 1) \ interval.Ticks))
End Function
Sample usage:
Dim example = #2:10:12 AM#
Dim rounded = RoundupDate(example, TimeSpan.FromMinutes(30))
Wasn't sure what you meant by a 'dropdownList'. For this example I used a ComboBox.
Dim StartTime As DateTime = #12:00:00 AM#
'load combo box
Do
StartTimeDDL.Items.Add(StartTime.ToString("hh:mm tt"))
StartTime = StartTime.AddMinutes(30)
Loop While StartTime.TimeOfDay.TotalDays > 0
Dim selectTime As DateTime = #2:10:12 PM# 'TEST find this <<<<<<<<<<<<<<<<<<<
'round time to 30 minutes
Dim numSecs As Integer = (CInt(selectTime.TimeOfDay.TotalSeconds) \ 1800) * 1800
'the OP said 'les say current time is 12:00:00 AM than I was to select 12:30 AM"
'so....
numSecs += 1800 'round up 30 minutes ????????
'create 'find'
Dim ts As New TimeSpan(0, 0, numSecs)
Dim findDate As New DateTime(ts.Ticks)
StartTimeDDL.SelectedIndex = StartTimeDDL.FindStringExact(findDate.ToString("hh:mm tt"))
I have value of this for example
Dim start_time As String = 12/30/1899 8:30:00 PM
Then i want to change it into
Dim final_start_time As String = 0000-00-00 20:30:00 ' i want to come up with this value
or another example is
Dim start_time As String = 12/30/1899 10:30:00 AM
to
Dim final_start_time As String = 0000-00-00 10:30:00
Based on your revised Question, here is some code. Revise it as necessary. I used es-ES as culture.. actually have no clue what culture that is... but on the dateformat MSDN page, that seems to generate the format you want...
Dim myOriginalDateTime As DateTime = Now
Dim mynewDateString As String = ""
Dim myFinalDateString As String = ""
Dim culture As New System.Globalization.CultureInfo("es-ES")
mynewDateString = myOriginalDateTime.ToString("G", culture)
Dim arrDateParts() As String = Split(mynewDateString, " ")
myFinalDateString = "0000-00-00 " & arrDateParts(1)
MsgBox(myFinalDateString)
Try this link:
http://msdn.microsoft.com/en-us/library/zdtaw1bw(v=vs.110).aspx
And this:
http://msdn.microsoft.com/en-us/library/vstudio/az4se3k1(v=vs.100).aspx
You use the .tostring method, and specify a format.
We send out a daily email using Outlook that contains the work week and day in the format of WW.D Our work week starts on Monday, so like today would be 50.2 How can I add this programatically using VB?
Sub MakeItem()
Dim objMail As MailItem
Set newItem = Application.CreateItemFromTemplate("C:\Users\Update.oft")
' Work week number
WW = 50.2
' Setup Subject replacing the <SHIFT>
newItem.Subject = Replace("<WorkWeek> Shift Passdown ", "<WorkWeek>", WW)
newItem.Display
Set newItem = Nothing
End Sub
You can do it like this:
Dim cal As New GregorianCalendar()
Dim week As Integer = cal.GetWeekOfYear(Date.Now, CalendarWeekRule.FirstFullWeek, DayOfWeek.Monday)
Dim day As Integer = cal.GetDayOfWeek(Date.Now)
Dim workDayId As String = String.Format("{0:00}.{1}", week, day)
I'm trying to develop a module in Outlook that can use the ReceivedTime of an email and then add x hours to it to give a 'response time'. The hours added though have to be within the working week (Mon-Fri) and the office hours (9-5).
For my case, x can be declared a constant of 36 hours, however (as below) I don't know how to write the code for this with the constraints of the work week and office hours.
I was able to write a basic module that adds 100 hours, as this can give the correct response time in some cases.
Sub TargetResolution()
Dim myMail As Outlook.MailItem
For Each myMail In Application.ActiveExplorer.Selection
Dim LDate As Date
LDate = DateAdd("h", 100, myMail.ReceivedTime)
MsgBox "Time Received: " & (myMail.ReceivedTime) & Chr(13) & "Target Resolution: " & (LDate)
Next
Set myMail = Nothing
End Sub
Any help would be greatly appreciated, thank you :)
OK, so to do this you're going to need to work with some of the Date & Time functions I mentioned above. I am not certain this will account for Holidays -- actually, I'm pretty sure it will not, since those vary by locale, and even by business. In any case this should get you 99% of the way there:
You should be able to call this function in your macro by:
LDate = GetTargetDate(myMail.ReceivedTime, 36)
I include a test subroutine, so you can plug in a date/time and see what results:
Sub TestDate()
Dim dt As Date
dt = "6/1/2013 12:06:00 PM"
Debug.Print "Received at " & dt
Debug.Print "Due by " & GetTargetDate(dt, 36)
End Sub
Here is the function, place it within your code module:
Option Explicit
Const startDay As String = " 9:00:00 AM"
Const endDay As String = " 5:00:00 PM"
Const hrsPerDay As Long = 8
Function GetTargetDate(myDate As Date, numHours As Long) As Date
Dim effRecdDate As Date
Dim newDate As Date
Dim resolveDays As Double 'number of hours, converted to full days
Dim resolveHours As Long
Dim hh As Long
resolveDays = numHours / hrsPerDay 'convert to days
'## Ensure the timestamp is within business hours
effRecdDate = ValidBizHours(myDate)
'## Ensure the date is a business day
effRecdDate = ValidWeekday(myDate)
'Convert to hours, carrying the partial day as a fraction of the 8-hr workday
resolveHours = (Int(resolveDays) * 24) + numHours Mod hrsPerDay
'## Add each of the resolveHours, but if the result is not a weekday, then
' add another day
For hh = 1 To resolveHours
newDate = DateAdd("h", hh, effRecdDate)
If Weekday(newDate, vbMonday) > 5 Then
effRecdDate = DateAdd("d", 1, effRecdDate)
End If
Next
'## Make sure this date falls between biz hours AND that
' it consequently falls on a business DAY
Do
If TimeValue(newDate) > TimeValue(startDay) And TimeValue(newDate) < TimeValue(endDay) Then
If Weekday(newDate, vbMonday) <= 5 Then
Exit Do
Else:
newDate = DateAdd("d", 1, newDate)
End If
Else:
newDate = DateAdd("h", 1, newDate)
End If
Loop
'## Return the newDate to the function:
GetTargetDate = newDate
End Function
Private Function ValidWeekday(myDate As Date) As Date
'Converts timestamps received on the weekend to Monday morning, 9:00:00 AM
Do While Weekday(myDate, vbMonday) > 5
myDate = DateValue(DateAdd("d", 1, myDate)) & startDay
Loop
ValidWeekday = myDate
End Function
Private Function ValidBizHours(myDate As Date) As Date
'Converts timestamps after business hours to 9:00:00 AM the following day
'Converts timestamps before business hours to 9:00:00 AM same business day
Select Case TimeValue(myDate)
Case Is > TimeValue(endDay)
'Assume this is received at start of the following day:
myDate = DateValue(DateAdd("d", 1, myDate)) & startDay
Case Is < TimeValue(startDay)
'Assume this is received at start of day, but not earlier:
myDate = DateValue(myDate) & startDay
Case Else
'do nothing
End Select
ValidBizHours = myDate
End Function
This yields the following:
If email is received during business hours:
Received at 5/27/2013 9:06:00 AM
Due by 5/31/2013 1:06:00 PM
If email is received during business hours, but the deadline becomes after business hours or on weekend, carry the remainder :
Received at 5/30/2013 1:06:00 PM
Due by 6/6/2013 9:06:00 AM
If a mail is received before business hours, consider it received at 9:00:00 AM :
Received at 5/27/2013 7:06:00 AM
Due by 5/31/2013 1:00:00 PM
If a mail is received after business hours, consider it received at 9:00:00 AM the following business day:
Received at 5/27/2013 9:06:00 PM
Due by 6/3/2013 1:00:00 PM
And also works if the mail is received on the weekend, consider it received at 9:00:00 AM on Monday:
Received at 6/1/2013 12:06:00 PM
Due by 6/7/2013 1:00:00 PM