PR_LAST_VERB_EXECUTION_TIME - vba

I have exported outlook email data to excel.
Now,another problem that I have come across is that the PR_LAST_VERB_EXECUTION_TIME do not display as the same date formats. The dates can be in ddmmyyyy hh:mm:ss AM/PM or mmddyyyy hh:mm format ( Please refer to the img ).
I have also made sure that all the cells format are general.Is it possible to standardize the date format or there might be any other reasons causing this?
my code is as follows:
For Each itm In Items
'Check item type
If TypeName(itm) = "MailItem" Then
intColumnCounter = 1
Set msg = itm
intRowCounter = intRowCounter + 1
Set rng = wks.Cells(intRowCounter, intColumnCounter)
rng.Value = GetLastVerb(msg)
End If
Next
Function GetLastVerb(olkMsg As Outlook.MailItem) As String
Dim intVerb As Integer
intVerb = GetProperty(olkMsg, "http://schemas.microsoft.com/mapi/proptag/0x10810003")
Select Case intVerb
Case 102
Debug.Print ("Reply to Sender")
GetLastVerb = GetLastVerbTime(olkMsg)
Case 103
Debug.Print ("Reply to All")
GetLastVerb = GetLastVerbTime(olkMsg)
Case 104
Debug.Print ("Forward")
GetLastVerb = olkMsg.ReceivedTime
Case 108
Debug.Print ("Reply to Forward")
GetLastVerb = GetLastVerbTime(olkMsg)
Case Else
Debug.Print ("Unknown")
GetLastVerb = olkMsg.ReceivedTime
End Select
End Function
Public Function GetProperty(olkItm As Object, strPropName As String) As Date
Dim olkPA As Outlook.PropertyAccessor
Set olkPA = olkItm.PropertyAccessor
GetProperty = olkPA.GetProperty(strPropName)
Set olkPA = Nothing
End Function
Function GetLastVerbTime(olkItm As Object) As Variant
GetLastVerbTime = GetDateProperty(olkItm, "http://schemas.microsoft.com/mapi/proptag/0x10820040")
End Function
Public Function GetDateProperty(olkItm As Object, strPropName As String) As Date
Dim olkPA As Outlook.PropertyAccessor
Set olkPA = olkItm.PropertyAccessor
GetDateProperty = olkPA.UTCToLocalTime(olkPA.GetProperty(strPropName))
Set olkPA = Nothing
End Function

The reason behind it very simple
The function GetLastVerb calls other functions which return a Date or a variant and then finally GetLastVerb returns a string. The best way is to simply format the output before writing it to the range
If you are not concerned with the type of final output i.e whether it is a string or a date then replace rng.Value = GetLastVerb(msg) by rng.Value = Format(GetLastVerb(msg), "dd/mm/yyyy hh:mm:ss AM/PM")
If you want a proper date output then, format the column as relevant date/time format and then use formula to update the cell
For example
Columns("A:A").NumberFormat = "dd/mm/yyyy hh:mm:ss AM/PM"
rng.FormulaR1C1 = Format(GetLastVerb(msg), "dd/mm/yyyy hh:mm:ss AM/PM")

Related

VBA compare date from the inputbox with the date in the sheet

I would like to use the date from inputbox , then compare it with the date in the excel sheet , so my code as below :
Sub test()
Dim date1 As Date
Date = InputBox("input the date ")
If date1 = Sheet3.Range("A2").Value Then
Debug.Print "TRUE"
Else
Debug.Print "FALSE"
End If
End Sub
the result it got is always "FALSE" in the immediate box although i have set the date match with the date inputted from inputbox , can you please assist on this case ? Any assist is appreciated.
The InputBox always returns a string, so convert this:
Sub test()
Dim Date1 As Date
Dim Value As String
Value = InputBox("Input the date")
If IsDate(Value) Then
Date1 = DateValue(Value)
If DateDiff("d", Date1, Sheet3.Range("A2").Value) = 0 Then
Debug.Print "TRUE"
Else
Debug.Print "FALSE"
End If
Else
Debug.Print "N/A"
End If
End Sub
A short solution, protected against the error of mismatching the type of input data and the data on the sheet (text or error instead of date in a cell)
Debug.Print IIf(InputBox("Input the date: ") = Sheet3.Range("A2").Text, "TRUE", "FALSE")

How to output date value from a text

So I have obfuscated date information in my column. e.g. Jan preplan-2017, Feb-afterplan-2017-low, etc.
Two things are always consistent: Months always come in the beginning with 3 letters. And year comes in 4 digits (may in anywhere.)
I basically need them in the standard date format( e.g. 1/1/2017, 1/2/2017, etc.)
First convert your string to a date value:
s = "Jan preplan-2017"
TrueDate = DateValue("1 " & Left(s, 3) & " " & Right(s, 4))
Then - for display - format as required:
ShowDate = Format(TrueDate, "d.m.yyyy")
Or in one go:
ShowDate = Format(DateValue("1 " & Left(s, 3) & " " & Right(s, 4)), "d.m.yyyy")
Edit: Use Split to create an array of the elements, loop these and pick the one that is an integer:
Year = Split("Feb-afterplan-2017-low", "-")(2)
I'm not brilliant with RegEx so no doubt this can be improved.
As a worksheet function:
Public Function ConvertDate(sData As String) As Variant
Dim RE As Object, REMatches As Object
Dim Temp As String
Set RE = CreateObject("vbscript.regexp")
With RE
.MultiLine = False
.Global = False
.IgnoreCase = True
.Pattern = "\d{4}"
End With
Set REMatches = RE.Execute(sData)
If REMatches.Count > 0 Then
Temp = "1-" & Left(sData, 3) & "-" & REMatches(0)
ConvertDate = CDate(DateValue(Temp))
Else
'Returns #VALUE error on no match.
ConvertDate = CVErr(xlValue)
End If
End Function
Passes date by reference and returns TRUE/FALSE:
Public Sub Test()
Dim MyDate As Date
If ConvertDate1("Jan preplan-2017", MyDate) Then
MsgBox "Date converted to " & Format(MyDate, "dd-mmm-yy"), vbOKOnly
Else
MsgBox "Date not converted.", vbOKOnly
End If
End Sub
Public Function ConvertDate1(sData As String, ByRef ReturnValue As Date) As Boolean
Dim RE As Object, REMatches As Object
Dim Temp As String
Set RE = CreateObject("vbscript.regexp")
With RE
.MultiLine = False
.Global = False
.IgnoreCase = True
.Pattern = "\d{4}"
End With
Set REMatches = RE.Execute(sData)
If REMatches.Count > 0 Then
Temp = "1-" & Left(sData, 3) & "-" & REMatches(0)
ReturnValue = CDate(DateValue(Temp))
ConvertDate1 = True
Else
ConvertDate1 = False
End If
End Function
The RegEx can be improved to check first three letters are a month... loads can be done to improve, but you get the picture I hope.

Changing the output sheet

I have the below code that will give the count based on some filter according to the date.
But the problem is I want to change the destination where the O/P gets pasted.
Currently the calculation is done on "Latency" sheet and the O/P is paste there itself. I just want to change the output to cell AE5 in sheet"WBR45"
Option Explicit
Const strFormTitle = "Enter Minimum and Maximum Dates in d/m/yyyy format" 'Edit for different regional date format
Const strShtName As String = "Latency" 'Name of worksheet with ranges to be processed
Const strDateFormat As String = "d mmm yyyy" 'Edit for different regional date format
Const strCrit1 As String = "Pass, Fail, In Progress" 'Criteria for output to AE2. (Can insert or delete criteria with comma between values. OK to have spaces with the commas)
Const strCrit2 As String = "COMPATIBLE" 'Criteria for column E. (One criteria only)
Const strDateRng As String = "K:K" 'Column with Dates
Const strCrit1Col As String = "O:O" 'Column with "Pass, Fail, In Progress"
Const strCrit2Col As String = "E:E" 'Column with "COMPATIBLE"
Const strOutput1 As String = "AE2" 'The cell for output "Pass, Fail, In Progress"
Const strOutput2 As String = "AF2" 'The cell for output "Pass, Fail, In Progress" plus "COMPATIBLE"
Private Sub UserForm_Initialize()
Me.lblTitle = strFormTitle
End Sub
Private Sub cmdProcess_Click()
Dim wf As WorksheetFunction
Dim ws As Worksheet
Dim rngDates As Range 'Range of dates
Dim rngCrit1 As Range 'Range to match Criteria 1
Dim rngCrit2 As Range 'Range to match Criteria 2
Dim dteMin As Date
Dim dteMax As Date
Dim rngOutput1 As Range
Dim rngOutput2 As Range
Dim arrSplit As Variant
Dim i As Long
Set wf = Application.WorksheetFunction
Set ws = Worksheets(strShtName)
With ws
Set rngDates = .Columns(strDateRng)
Set rngOutput1 = .Range(strOutput1)
Set rngOutput2 = .Range(strOutput2)
Set rngCrit1 = .Range(strCrit1Col)
Set rngCrit2 = .Range(strCrit2Col)
End With
dteMin = CDate(Me.txtMinDate)
dteMax = Int(CDate(Me.txtMaxDate) + 1)
If dteMin > dteMax Then
MsgBox "Minimum date must be less than maximum date." & vbCrLf & _
"Please re-enter a valid dates."
Exit Sub
End If
arrSplit = Split(strCrit1, ",")
'Following loop removes any additional leading or trailing spaces (Can be in the string constant)
For i = LBound(arrSplit) To UBound(arrSplit)
arrSplit(i) = Trim(arrSplit(i))
Next i
rngOutput1.ClearContents 'Start with blank cell
For i = LBound(arrSplit) To UBound(arrSplit)
rngOutput1.Value = rngOutput1.Value + wf.CountIfs(rngDates, ">=" & CLng(dteMin), _
rngDates, "<" & CLng(dteMax), _
rngCrit1, arrSplit(i))
Next i
rngOutput2.ClearContents 'Start with blank cell
For i = LBound(arrSplit) To UBound(arrSplit)
rngOutput2.Value = rngOutput2.Value + wf.CountIfs(rngDates, ">=" & CLng(dteMin), _
rngDates, "<" & CLng(dteMax), _
rngCrit1, arrSplit(i), rngCrit2, strCrit2)
Next i
End Sub
Private Sub cmdCancel_Click()
Unload Me
End Sub
Private Sub txtMinDate_AfterUpdate()
If IsDate(Me.txtMinDate) Then
Me.txtMinDate = Format(CDate(Me.txtMinDate), strDateFormat)
Else
MsgBox "Invalid Minimum date. Please re-enter a valid date."
End If
End Sub
Private Sub txtMaxDate_AfterUpdate()
If IsDate(Me.txtMaxDate) Then
Me.txtMaxDate = Format(CDate(Me.txtMaxDate), strDateFormat)
Else
MsgBox "Invalid Maximum date. Please re-enter a valid date."
End If
End Sub
Private Sub chkEntireRng_Click()
Dim wf As WorksheetFunction
Dim ws As Worksheet
Dim rngDates As Range
Set wf = WorksheetFunction
Set ws = Worksheets(strShtName)
With ws
Set rngDates = .Columns(strDateRng)
End With
If Me.chkEntireRng = True Then
Me.txtMinDate = Format(wf.Min(rngDates), strDateFormat)
Me.txtMaxDate = Format(wf.Max(rngDates), strDateFormat)
Me.txtMinDate.Enabled = False
Me.txtMaxDate.Enabled = False
Else
Me.txtMinDate = ""
Me.txtMaxDate = ""
Me.txtMinDate.Enabled = True
Me.txtMaxDate.Enabled = True
End If
End Sub
A lot could be done to streamline and simplify this code, but in the current context, this is what I think you need to do.
After
Const strShtName As String = "Latency"
add
Const StrOPName as string = "WBR45"
change
Const strOutput1 As String = "AE2"
to
Const strOutput1 As String = "AE5"
and I guess change
Const strOutput2 As String = "AF2"
to
`Const strOutput2 As String = "AF5"` 'not sure if this is what you want as well
add
Dim wsOP As Worksheet
after
dim ws as worksheeet
and
set wsOP = sheets (strOPname)
after set ws = worksheets (strShtName)
take this out of the "with ws" section
Set rngOutput1 = .Range(strOutput1)
Set rngOutput2 = .Range(strOutput2)
and add this after the "End With"
Set rngOutput1 = wsOP.Range(strOutput1)
Set rngOutput2 = wsOP.Range(strOutput2)
Then, when the rngoutput1.value statement is reached, the target range will be wsOP.range ("AE5")
and the rngoutput2.value will move to AF5
I think that's what you need. fiddle with it a bit.

Getting week number in PowerPoint

I have got a code to generate PowerPoint with an Excel file. I have mostly modified the code as per my requirement, but I want to add one more feature into my .ppt. I want VBA to extract Week Number from some source and do the following:
Rename my .ppt as "XXX_Weeknumber.ppt"
In one of the textboxes in the slides I want to add the same Weeknumber.
I tried getting the week number by using the function WeekNum and trying to call the function in my Main Sub but unfortunately doesn't work!
My code for function in Module 1:
Function WeekNum(D As Date) As Integer
WeekNum = CInt(Format(D, "ww", 2))
End Function
Code for the .xls to .ppt in Module 2:
Dim oPPTApp As PowerPoint.Application
Dim oPPTShape As PowerPoint.Shape
Dim oPPTShape2 As PowerPoint.Shape
Dim oPPTFile As PowerPoint.Presentation
Dim PPSlide As PowerPoint.slide
Dim SlideNum As Integer
Dim rng As Range
Dim WeekNumm$
Sub PPTableMacro()
Dim sourcexl As Workbook
Dim wk As Integer
Dim strPresPath As String, strExcelFilePath As String, strNewPresPath As String
strExcelFilePath = "C:\MySource.xls"
strPresPath = "C:\Presentation1.ppt"
Call WeekNum
WeekNumm = WeekNum()
Set wk = WeekNumm
strNewPresPath = "C:\Presentation1_" & wk & ".ppt" 'This is how I want the name
strNewPresPath = "C:\new1.ppt"
Set oPPTApp = CreateObject("PowerPoint.Application")
oPPTApp.Visible = msoTrue
Set oPPTFile = oPPTApp.Presentations.Open(strPresPath)
SlideNum = 2
oPPTFile.Slides(SlideNum).Select
Set oPPTShape = oPPTFile.Slides(SlideNum).Shapes("Table 1")
Set sourcexl = Workbooks.Open(strExcelFilePath) 'Source excel file
With sourcexl
.Sheets("Sheet1").Activate
oPPTShape.Table.Cell(1, 1).Shape.TextFrame.TextRange.Text = Cells(1, 1).Text
oPPTShape.Table.Cell(1, 2).Shape.TextFrame.TextRange.Text = Cells(1, 2).Text
oPPTShape.Table.Cell(1, 3).Shape.TextFrame.TextRange.Text = Cells(1, 3).Text
oPPTShape.Table.Cell(2, 1).Shape.TextFrame.TextRange.Text = Cells(2, 1).Text
oPPTShape.Table.Cell(2, 2).Shape.TextFrame.TextRange.Text = Cells(2, 2).Text
oPPTShape.Table.Cell(2, 3).Shape.TextFrame.TextRange.Text = Cells(2, 3).Text
End With
Set oPPTShape2 = oPPTFile.Slides(SlideNum).Shapes("TextBox 1")
Text1 = "weekXX" ' actually wanted week number here
oPPTShape2.TextFrame.TextRange.Text = Text1
oPPTFile.SaveAs strNewPresPath
'oPPTFile.Close
'oPPTApp.Quit
Set oPPTShape = Nothing
Set oPPTFile = Nothing
Set oPPTApp = Nothing
MsgBox "Presentation Created", vbOKOnly + vbInformation
End Sub
Your function asks for a data input ("D"), and it's not optional. If you want to retrieve the day of the week of today ("Date" system variable), you should call it like this:
WeekNumm = WeekNum(Date)
Also, you are using a Set statement in "Set wk = WeekNumm". As the variable isn't an object, you have to use (a preferably omitted) Let.
Also, your function will not return the day of the week, because "ww" means the week number of the year. If you want the day of the week by this approach, you have to use "w".
For a better approach, you should use the builtin function Weekday to get the weekday.
Like:
iWeekDay = Weekday(Date,vbUseSystemDayOfWeek) 'Retrieves today's day of the week (Tuesday = 3...)

Excel to create task in Outlook

I am relatively new to VBA and so I'm sure this is a basic mistake that I am making!
A1 contains valid date, A2 contains task information, A3 contains number of days before A1 date to trigger task reminder.
The problem is when I put =addtotasks(A1,A2,A3)
It just comes up with #NAME?
I have enabled the Microsoft Outlook 14.0 Object Library in the references.
I am based in the UK telling you for dates purposes.
This is the following code. I have included some extra code for setting a remainder only on a business day.
'Function NextBusinessDay(dateFrom As Date, _
Optional daysAhead As Long = 1) As Date
Dim currentDate As Date
Dim nextDate As Date
' convert neg to pos
If daysAhead < 0 Then
daysAhead = Abs(daysAhead)
End If
' determine next date
currentDate = dateFrom
nextDate = DateAdd("d", daysAhead, currentDate)
' is next date a weekend day?
Select Case Weekday(nextDate, vbUseSystemDayOfWeek)
Case vbSunday
nextDate = DateAdd("d", 1, nextDate)
Case vbSaturday
nextDate = DateAdd("d", 2, nextDate)
End Select
NextBusinessDay = CDate(Int(nextDate))
End Function
Dim bWeStartedOutlook As Boolean
Function AddToTasks(strDate As String, strText As String, DaysOut As Integer) As Boolean
' Adds a task reminder to Outlook Tasks a specific number of days before the date specified
' Returns TRUE if successful ' Will not trigger OMG because no protected properties are accessed
'
' Usage:
' =AddToTasks("12/31/2008", "Something to remember", 30)
' or:
' =AddToTasks(A1, A2, A3)
' where A1 contains valid date, A2 contains task information, A3 contains number of days before A1 date to trigger task reminder '
' can also be used in VBA :
'If AddToTasks("12/31/2008", "Christmas shopping", 30) Then
' MsgBox "ok!"
'End If
Dim intDaysBack As Integer
Dim dteDate As Date
Dim olApp As Object 'Outlook.Application
Dim objTask As Object ' Outlook.TaskItem
' make sure all fields were filled in
If (Not IsDate(strDate)) Or (strText = "") Or (DaysOut <= 0) Then
AddToTasks = False
GoTo ExitProc
End If
' We want the task reminder a certain number of days BEFORE the due date
' ex: if DaysOut = 120, then we want the due date to be -120 before the date specified
' we need to pass -120 to the NextBusinessDay function, so to go from 120 to -120,
' we subtract double the number (240) from the number provided (120).
' 120 - (120 * 2); 120 - 240 = -120
intDaysBack = DaysOut - (DaysOut * 2)
dteDate = NextBusinessDay(CDate(strDate), intDaysBack)
On Error Resume Next
Set olApp = GetOutlookApp
On Error GoTo 0
If Not olApp Is Nothing Then
Set objTask = olApp.CreateItem(3) ' task item
With objTask
.StartDate = dteDate
.Subject = strText & ", due on: " & strDate
.ReminderSet = True
.Save
End With
Else
AddToTasks = False
GoTo ExitProc
End If
' if we got this far, it must have worked
AddToTasks = True
ExitProc:
If bWeStartedOutlook Then
olApp.Quit
End If
Set olApp = Nothing
Set objTask = Nothing
End Function
Function GetOutlookApp() As Object
On Error Resume Next
Set GetOutlookApp = GetObject(, "Outlook.Application")
If Err.Number <> 0 Then
Set GetOutlookApp = CreateObject("Outlook.Application")
bWeStartedOutlook = True
End If
On Error GoTo 0
End Function
I have taken this code from this website, by the way:
http://www.jpsoftwaretech.com/get-previous-business-day-in-vba/
The #Name? error happens when you reference a function or variable unknown to the program. It's not sure where this function resides. Try using the "fx" button next to the formula bar and selecting user defined functions, it should be listed there.
My guess is you created this function in a different work book probably the personal.xlsb.
In order to use user defined functions you have to reference the full path to them. Try reading the last paragraph here:
http://office.microsoft.com/en-us/excel-help/creating-custom-functions-HA001111701.aspx