Lotus Notes Domino Getting Date Difference - lotus-notes

I have made a code using lotusscript that would calculate the time difference between the two fields, now I want to calculate the difference between dates. I've pretty much started lotusscripting and I still got a minimum knowledge about it. Hope you can help me. Here's the code that I've made to calculate time difference:
Sub UpdateDuration()
Dim ws As New NotesUIWorkspace
Dim uidoc As NotesUIDocument
Dim starttime As NotesDateTime
Dim endtime As NotesDateTime
Dim duration As Integer
Set uidoc = ws.CurrentDocument
If uidoc.FieldGetText("StartTime") = "" Then
Exit Sub
Elseif uidoc.FieldGetText("StartTime") = "" Then
Exit Sub
End If
Set starttime = New NotesDateTime( uidoc.FieldGetText("StartTime") )
Set endtime = New NotesDateTime( uidoc.FieldGetText("EndTime") )
duration = endtime.TimeDifference( starttime )
Call uidoc.FieldSetText("Duration", Cstr(duration) )
Call uidoc.Refresh()
End Sub

TimeDifference returns the number of seconds between two NotesDateTimes. There are 60 * 60 * 24 seconds in a day, and that works out to 86400. So just write your code exactly as above and divide the result by 86400. (The only other thing you might want to change is your field and variable names, to reflect the fact that you are working with date input instead of time.)

Related

Convert local time to UTC without calling Win APIs while taking into account DST

Turns out my organisation have blocked all Win API calls from MS Office code with their ASR rules and are unwilling to apply any exclusions so any old code I have no longer works. Anyone help with Excel VBA code that can convert local datetime into UTC?GMT while taking into account DST. I tried using the COM object, but wasn't sure what to do with DST offsets. Users are in multiple countries and I'm not sure exactly where since most people work remotely.
Was directed to this answer that uses Outlook which gives exactly what I wanted. Noticeably slower than the Win API calls on large scale repetitive calls, but any complaints can be directed to the company's IT for their security policy change.
https://stackoverflow.com/a/45510712/16578424
Option Explicit
'mTimeZones by Patrick Honorez --- www.idevlop.com
'with the precious help of Julian Hess https://stackoverflow.com/a/45510712/78522
'You can reuse but please let all the original comments including this one.
'This modules uses late binding and therefore should not require an explicit reference to Outlook,
'however Outlook must be properly installed and configured on the machine using this module
'Module works with Excel and Access
Private oOutl As Object 'keep Outlook reference active, to save time in recurring calls
Private oOutlTimeZones As Object 'keep Outlook reference active, to save time in recurring calls
' seems to drop the reference if use previous scheme of returning boolean
' returning the actual object is more correct in any case
Private Function GetOutlookTimeZones() As Object
If oOutl Is Nothing Or oOutlTimeZones Is Nothing Then
Debug.Print "~"
On Error Resume Next
Err.Clear
Set oOutl = GetObject(, "Outlook.Application")
If Err.Number Then
Err.Clear
Set oOutl = CreateObject("Outlook.Application")
End If
Set oOutlTimeZones = oOutl.TimeZones
End If
Set GetOutlookTimeZones = oOutlTimeZones
On Error GoTo 0
End Function
Function ConvertTime(DT As Date, Optional TZfrom As String = "Central Standard Time", _
Optional TZto As String = "W. Europe Standard Time") As Date
'convert datetime with hour from Source time zone to Target time zone
'valid Source & Target time zones can be found in your registry under: HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows NT/CurrentVersion/Time Zones/
'this version using Outlook, properly handles Dailight Saving Times, including for past and future dates
'it includes a fix for the fact that ConvertTime seems to strip the seconds
'krammy85 2019-01-25 Edit: Outlook rounds minutes when it strips seconds, so modified code to strip seconds (without rounding) prior to running Outlook's ConvertTime.
Dim sourceTZ As Object
Dim destTZ As Object
Dim seconds As Single
Dim DT_SecondsStripped As Date
Dim oOutlTimeZones As Object: Set oOutlTimeZones = GetOutlookTimeZones()
If Not (oOutlTimeZones Is Nothing) Then
'fix for ConvertTime stripping the seconds
seconds = Second(DT) / 86400 'save the seconds as DateTime (86400 = 24*60*60)
DT_SecondsStripped = DT - seconds
Set sourceTZ = oOutlTimeZones.Item(TZfrom)
Set destTZ = oOutlTimeZones.Item(TZto)
ConvertTime = oOutlTimeZones.ConvertTime(DT_SecondsStripped, sourceTZ, destTZ) + seconds 'add the stripped seconds
End If
End Function
' returns number of minutes ahead of UTC (positive number) or behind
Function GetOffsetAt(DT As Date, TZfrom As String) As Long
Dim utc_DT As Date: utc_DT = ConvertTime(DT, TZfrom, "UTC")
GetOffsetAt = DateDiff("n", utc_DT, DT)
End Function
Sub test_ConvertTime()
Dim t As Date: t = #8/23/2017 6:15:05 AM#
Debug.Print t, ConvertTime(t), Format(t - ConvertTime(t), "h")
Debug.Print t, ConvertTime(t, "Central Standard Time", "W. Europe Standard Time"), Format(t - ConvertTime(t), "h")
End Sub
Sub test_DumpTZs()
Dim TZ As Object: For Each TZ In GetOutlookTimeZones()
Debug.Print "TZ:", TZ.Id, TZ.Name
Next TZ
End Sub
Last two Subs are not really necessary.
For example, I can now simply refer to the following to get the user's current timezone, regardless of daylight saving, and return the UTC converted value. This could be wrapped in a Format function to display accordingly.
ConvertTime(Now, oOutlTimeZones.CurrentTimeZone.id, "UTC")

How use SeleniumBasic (VBA) to interact with Shadow-Root DOM element in the chrome://downloads/

I am trying to interact with element in the Chrome Download page (chrome://downloads/) to be able to find out when the download finishes.
But I can't interact with the elements in this page. For what I find out this is because of the shadow-root DOM elements.
I found in google some examples of how interact with these elements using java ou C, but never with VBA. Could you help to translate these comands to VBA?
https://medium.com/rate-engineering/a-guide-to-working-with-shadow-dom-using-selenium-b124992559f
https://medium.com/#alan.canlin/how-to-find-web-elements-in-shadow-doms-using-selenium-webdriver-and-c-36978f7de9ba
Google Code Page:
Here is the simple method that will make sure the script will wait until the download is completed.
Function getDownLoadedFileName(maxTimeInMins As int)
Dim startTime As Date
startTime = Now()
Dim downloadPercentage As int
Do While ElapsedTime(Now(),startTime) < maxTimeInMins
downloadPercentage = driver.execute_script( "return document.querySelector('downloads-manager').shadowRoot.querySelector('#downloadsList downloads-item').shadowRoot.querySelector('#progress').value")
If (downloadPercentage = 100) Then
getDownLoadedFileName = driver.execute_script("return document.querySelector('downloads-manager').shadowRoot.querySelector('#downloadsList downloads-item').shadowRoot.querySelector('div#content #file-link').text")
End If
Loop
End Function
Function ElapsedTime(endTime As Date, startTime As Date)
Dim Interval As Date
' Calculate the time interval.
Interval = endTime - startTime
' Format and return the time interval in seconds.
ElapsedTime = Int(CSng(Interval * 24 * 3600))
End Function
Thank you very much! Works perfctly.
I am just posting here with some little modifications I needed to do:
Option Explicit
Sub Accessing_ShadowRoot_Object()
'================================='
'Declaração Early-Binding:
'================================='
Dim Selenium As New ChromeDriver '
'================================='
Selenium.Start "chrome", "chrome://downloads"
Selenium.get "/"
Dim Nome_Download As String
Nome_Download = getDownLoadedFileName(Selenium, 10)
Debug.Print Nome_Download
End Sub
Public Function getDownLoadedFileName(Driver As WebDriver, maxTimeInMins As Integer)
Dim startTime As Date
startTime = Now()
Dim downloadPercentage
Do While ElapsedTime(Now(), startTime) < maxTimeInMins
downloadPercentage = Driver.ExecuteScript("return document.querySelector('downloads-manager').shadowRoot.querySelector('#frb0').shadowRoot.querySelector('#progress').value")
Debug.Print downloadPercentage
If (downloadPercentage = 100) Then
getDownLoadedFileName = Driver.ExecuteScript("return document.querySelector('downloads-manager').shadowRoot.querySelector('#downloadsList downloads-item').shadowRoot.querySelector('div#content #file-link').text")
End If
DoEvents
Loop
End Function
Function ElapsedTime(endTime As Date, startTime As Date)
Dim Interval As Date
' Calculate the time interval.
Interval = endTime - startTime
' Format and return the time interval in seconds.
ElapsedTime = Int(CSng(Interval * 24 * 3600))
End Function

What data type should a date be set to and why?

I was trying to assign a date to a variable. I tried:
Dim DateEnd As Date
DateEnd = 7 / 21 / 2019
This didn't work... So I tried:
Dim DateEnd As Date
DateEnd = Now
This works which meant that I am formatting the date incorrectly. So I set out to find how to format the date correctly. Surprisingly, this was not as easy to find as I thought it should be... But ultimately, I found a site:
https://bettersolutions.com/vba/dates-times/index.htm
It had several things that surprised me, for example it says:
"You should always try and store your dates in variables that have the Long datatype" and "Always declare dates as Long (never Date)."
My question is why?
It says:
"If a subroutine requires a Date datatype, pass in a Long instead and it will be converted automatically."
And it says:
"In VBA dates and times are enclosed between two hash (#) signs, for example: dtExpiries = #12/31/2006#"
So... After reading this (although I haven't tried it yet) I am expecting this to work:
Dim DateEnd As Date
DateEnd = #07/21/2019#
But it says I shouldn't do that... Instead I should do:
Dim DateEnd As Long
DateEnd = X
What do I put in place of the X? Just simply 07/21/2019?
This works:
Sub dates()
Dim DateEnd As Date
DateEnd = #7/21/2019#
MsgBox DateEnd
End Sub
and if you start with a String:
Sub dates2()
Dim DateEnd As Date
Dim s As String
s = "7/21/2019"
DateEnd = CDate(s)
MsgBox DateEnd
End Sub
What do I put in place of the X? Just simply 07/21/2019?
No, since you have declared DateEnd as a long, it will coerce the date value to a long. 07/21/2019 will result in serial division --> 1.65098233448902E-04
So in place of X, you can put the date constant: #07/21/2019#, or something else that will create a date.
As to the why of their recommendation, you should direct that question to the authors, but only after you have a complete understanding of how both Excel and VBA handle and store date data, so you can evaluate whether their recommendation makes sense for you. Asking here will elicit a variety of opinions and is really off-topic.

While loop not terminating VBA

This is partial code. Basically I want to run a loop that terminates either when totalHoursNeeded is at 0 or below, or currentDate is at 6/30. The variable totalHoursNeeded is a global variable, and is reduced incrementally in function runReport. During runReport, currentDate, which is also a global variable, is also reassigned.
So lets say currentDate is initialized as 3/1/2016, and totalHoursNeeded is initialized as 234. runReport will be run on the basis of 200 hours, will set current date to be something like 5/5/2016, and then set totalHoursNeeded to be 34 (200 is the max each report can be run). Then, what I want to do is run another report, but instead of it being 200 and 3/1/2016, I want it to be 34 and 5/5/2016.
The issue is that these reports can't go past 6/30/2016; so for instance if I need to run a report based on 200 hours, and the starting date is 6/23/2016, the ending date needs to be 6/30/2016 and the amount of hours in the report needs to be correspondingly reduced.
Anyway, the while loop below is not terminating
Dim currentDate As Date
Dim totalHoursNeeded As Long
Dim totalHoursInExtension As Long
Dim hoursPerDay As Long
While totalHoursNeeded > 0 Or Not (Month(currentDate) = 6 And Day(currentDate) = 30)
'make a new word document object
Dim nWord As New Document
Set nWord = Documents.Open("c:\document\here", Visible:=False)
'run and save the report
On Error GoTo errhandler:
'if the extensions have not been written through 6/30 of any year
If Not (Month(currentDate) = 6) And Not (Day(currentDate) = 30) Then
'run a report based on the current row, two worksheets, and word object
totalHoursNeeded = totalHoursNeeded - runReport(row, summary, oWorksheet, nWord)
saveReport row, totalHoursInExtension, oWorksheet, nWord
Else
End If
' Close things
nWord.Close False
Wend

How can I extract the distance from Google Directions API via Excel web query?

I have a long list of origins and destinations in Excel, using webquery I can fill in the cities and postal code to give a webquery like:
http://maps.googleapis.com/maps/api/directions/xml?origin=Scoresby&destination=Melborne&sensor=false
This returns me a long XML file, but all I need is just the distance. Is there a way to extract only the distance value?
Or should I just run a macro script to extract distance one by one? (Since the format remains roughly the same each time I ask the server)
The short answer is XPath - well worth learning if you are going to work with any kind of XML
In the macro editor in Excel, go to Tools > References and add a reference to "Microsoft XML, v6.0" Now Insert > Module and add this code:
Sub getDistances()
Dim xhrRequest As XMLHTTP60
Dim domDoc As DOMDocument60
Dim ixnlDistanceNodes As IXMLDOMNodeList
Dim ixnNode As IXMLDOMNode
Dim lOutputRow As Long
' Read the data from the website
Set xhrRequest = New XMLHTTP60
xhrRequest.Open "GET", "http://maps.googleapis.com/maps/api/directions/xml?origin=Scoresby&destination=Melborne&sensor=false", False
xhrRequest.send
' Copy the results into a format we can manipulate with XPath
Set domDoc = New DOMDocument60
domDoc.loadXML xhrRequest.responseText
' The important bit: select every node called "value" which is the child of a node called "distance" which is
' in turn the child of a node called "step"
Set ixnlDistanceNodes = domDoc.selectNodes("//step/distance/value")
' Basic stuff to output the distances
lOutputRow = 1
With Worksheets("Sheet1")
.UsedRange.ClearContents
For Each ixnNode In ixnlDistanceNodes
.Cells(lOutputRow, 1).Value = ixnNode.Text
lOutputRow = lOutputRow + 1
Next ixnNode
End With
Set ixnNode = Nothing
Set ixnlDistanceNodes = Nothing
Set domDoc = Nothing
Set xhrRequest = Nothing
End Sub
To extend this to cover multiple trips you would just loop through the required origins and destinations, pass each pair as parameters to this procedure and then output the results in whichever format you need

Resources