How to get the Design Last modified date of the Database using Lotus Script? - lotus-domino

I want to get the Design Last modified(Not Database modified) date of the database using lotus script. I can get the Design last modified date from the catalog.nsf, But I need to take it from the database.

Look in database for every design element when it was last modified and take the most recent.
You can get all design elements with NotesNoteCollection. As design elements are NotesDocuments you can get the last modified date with doc.LastModified.
This is an example for an agent where you can choose a database and get printed the design last modified date:
Dim workspace As New NotesUIWorkspace
Dim session As New NotesSession
Dim db As NotesDatabase
Dim nid As String
Dim i As Integer
Dim doc As NotesDocument
Dim designLastModified As Variant
Dim serverDatabase As variant
serverDatabase = workspace.Prompt(13, "Choose Database", "")
If IsEmpty(serverDatabase) Then Exit Sub
Set db = session.Getdatabase(serverDatabase(0), serverDatabase(1), false)
Dim nc As NotesNoteCollection
Set nc = db.CreateNoteCollection(False)
Call nc.SelectAllDesignElements(True)
Call nc.BuildCollection
designLastModified = 0
nid = nc.GetFirstNoteId
For i = 1 To nc.Count
Set doc = db.GetDocumentByID(nid)
If Not doc Is Nothing then
If designLastModified < doc.LastModified Then
designLastModified = doc.LastModified
End If
End if
nid = nc.GetNextNoteId(nid)
Next
Print "Design last modified: " & designLastModified
It prints exactly the time shown in field "Design last modified date:" in catalog.nsf for selected database.

Related

VB ListBox list ftp directories and remove multiple lines based on number in folder name

I do get a lot of help from this website searching for a solution but at this point I'm completely stuck. I'm not a programmer, still was able to get that far.
The idea of my little project is to download newest version of a program (folder) from FTP server. Unzip files and update current program folder with new files. But before that backup the exiting program folder to a different FTP address.
What I'm struggling with is a way they post program versions (folders) on FTP:
folder structure on FTP
I can't really predict what would be the next folder to download because e.g. for program version:
7.6.16
it might be:
WERSJA_NOWY_TEMPLATE_7.6.17
or
WERSJA_NOWY_TEMPLATE_7.7.01
what ever is being released.
There is an ini file on C drive that holds the current program version. I was able to retrieve that information by reading the line, removing the unnecessary characters and splitting the string:
Dim wersja1 As String = File.ReadAllLines("C:\Windows\file.ini").FirstOrDefault(Function(x) x.Contains("WERSJA="))
Dim characterToRemove1 As String = "WERSJA="
Dim wersja2 As String = Replace(wersja1, characterToRemove1, "")
Dim characterToRemove2 As String = "T"
Dim wersja3 As String = Replace(wersja2, characterToRemove2, "")
Dim wersja4 As String() = wersja3.Split(New Char() {"."c})
Dim w1 As String = wersja4(0)
Dim w2 As String = wersja4(1)
Dim w3 As String = wersja4(2)
e.g. from a line:
WERSJA=7.6.5T
I get:
w1 = 7
w2 = 6
w3 = 5
Then I change the last one (w3) to a two digits number (because of the way folders are named on FTP):
If w3 < 10 Then
w3 = "0" & w3
Else
w3 = w3
End If
So if:
w3 = 5 >> I get 05
w3 = 16 >> I get 16
So far, so good.
In the next step I would like to see a filtered list of program versions (folders) in a ListBox or 2 ListBoxes. I would like to filter the list to see only folder with a bigger number than the current program version, so I can choose the correct one to download.
Why this way? Because if current version is e.g.
7.6.16
and there are 3 new ones e.g.:
7.6.17
7.6.18
7.7.01
I need to download all of them one by one, update program files and start the program to update sql database in order they were released. I can't skip any version on update.
Dim FTPurl As String = "ftp://xx.xx.xxx.xxx/wersje/"
Dim FTPwersja As String = "WERSJA_NOWY_TEMPLATE_*"
Dim FTPlog As String = "xxx"
Dim FTPpass As String = "yyy"
Dim clsRequest As FtpWebRequest = System.Net.WebRequest.Create(FTPurl & FTPwersja)
clsRequest.Credentials = New System.Net.NetworkCredential(FTPlog, FTPpass)
clsRequest.Method = System.Net.WebRequestMethods.Ftp.ListDirectory
Dim listResponse As FtpWebResponse = clsRequest.GetResponse
Dim reader As StreamReader = New StreamReader(listResponse.GetResponseStream())
'folder list
While reader.Peek >= 0
ListBox1.Items.Add(reader.ReadLine)
End While
'remove empty lines
For i As Integer = ListBox1.Items.Count - 1 To 0 Step -1
If ListBox1.GetItemText(ListBox1.Items(i)) = String.Empty Then
ListBox1.Items.RemoveAt(i)
End If
Next i
The above code gives me this result.
I found this code that enables filtering of ListBox but I have no clue on how to convert it to an loop so I would see only folders with bigger numbers than the current version of program:
'filter result in list box
Dim items = From it In ListBox1.Items.Cast(Of Object)()
Where it.ToString().IndexOf("7.5", StringComparison.CurrentCultureIgnoreCase) >= 0
Dim matchingItemList As List(Of Object) = items.ToList()
ListBox1.BeginUpdate()
'ListBox1.Items.Clear() 'add to list
For Each item In matchingItemList
ListBox1.Items.Remove(item) 'remove from list
'ListBox1.Items.Add(item) 'add to list
Next
ListBox1.EndUpdate()
I also have this code to catch choice and prevent crash when clicked on empty line :
Private Sub ListBox1_SelectedIndexChanged(sender As Object, e As EventArgs) _
Handles ListBox1.SelectedIndexChanged
Try
Dim LB1choice = ListBox1.SelectedItem.ToString()
Label5.Text = LB1choice
Catch ex As Exception
ListBox1.SelectedIndex = 0
End Try
End Sub
The ideal would be 2 ComboBoxes where 1st would display e.g.
WERSJA_NOWY_TEMPLATE_7.6
WERSJA_NOWY_TEMPLATE_7.7
and based on the choice 2nd ComboBox would list newer subfolders in it e.g.
WERSJA_NOWY_TEMPLATE_7.6.16
WERSJA_NOWY_TEMPLATE_7.6.17
for the 1st one, and:
WERSJA_NOWY_TEMPLATE_7.7.01
for the 2nd one.
I much appreciate if anyone could help me this because it's beyond my skills.

MS Word Interop replacing fields in word document with data from database

Hi I have written some code to open a word document that contains fields e.g.«Date» and I am trying to replace the fields with data in the database.
I am storing the Data in the database as variables then opening a word application and document then using an nested if statement with in a for each loop to find and replace each field in the document with the corresponding value.
Edit: The fields are all mergefields: { MERGEFIELD Fieldname }
I want to download the document afterwords or prompt the user to save on their machine.
Have i got this replacement thing right or is there a better way.
thanks
'Code to open the word template for invoices and editing it.
Protected Sub MakeDoc(ByVal sender As Object, ByVal e As EventArgs) Handles InvoiceGenBtn.Click
Dim ItmList = SQLHelper.RowQuery("SELECT * FROM QoItemList WHERE Quote_ID = #Quote_ID",
New SqlParameter("Quote_ID", Request.QueryString("QuoteID")))
'Variables.
Dim Qty = ItmList("Item_Quant")
Dim IName = ItmList("Item_Name")
Dim UPrice = ItmList("Item_QValue")
Dim TPrice = ItmList("Quote_TCliCost")
Dim Id = EditQuoteID.Text
Dim Client As String = DdlClient.Text
Dim Staff As String = DdlStaff.Text
Dim Dates = RadSDate.SelectedDate
Dim Total = SellValueTxt.Text
Dim WordTemplate As New Microsoft.Office.Interop.Word.Application()
Dim DocTemplate As New Microsoft.Office.Interop.Word.Document()
'Open and Store Doc Template.
DocTemplate = WordTemplate.Documents.Add("~/WordTemplates/BlankQuote.doc")
WordTemplate.Visible = True
'Find and rewrite the document on fields.
For Each Field As Microsoft.Office.Interop.Word.Field In DocTemplate.Fields
If Field.Code.Text.Contains("Date") Then
Field.Select()
WordTemplate.Selection.TypeText(Dates)
ElseIf Field.Code.Text.Contains("ID") Then
Field.Select()
WordTemplate.Selection.TypeText(Id)
ElseIf Field.Code.Text.Contains("Staff") Then
Field.Select()
WordTemplate.Selection.TypeText(Staff)
ElseIf Field.Code.Text.Contains("Client") Then
Field.Select()
WordTemplate.Selection.TypeText(Client)
ElseIf Field.Code.Text.Contains("TValue") Then
Field.Select()
WordTemplate.Selection.TypeText(Total)
ElseIf Field.Code.Text.Contains("QTY") Then
Field.Select()
WordTemplate.Selection.TypeText(Qty)
ElseIf Field.Code.Text.Contains("IName") Then
Field.Select()
WordTemplate.Selection.TypeText(IName)
ElseIf Field.Code.Text.Contains("UPrice") Then
Field.Select()
WordTemplate.Selection.TypeText(UPrice)
ElseIf Field.Code.Text.Contains("TPrice") Then
Field.Select()
WordTemplate.Selection.TypeText(TPrice)
End If
Next
'Download the File
DocTemplate.Save()
DocTemplate.Close()
WordTemplate.Quit()
End Sub
End Class
There are many ways to approach this. Using Selection is usually not efficient, even if the document is not visible and/or ScreenUpdating is set to false.
The following suggestion (snippet, only) works with a Range object. It sets the Range to the field at the beginning of the loop and also picks up the field's code in a String. Not calling Field.Code.Text multiple times is much more efficient. On finding a field, that field is deleted and the text is written to that Range (deleting the field does not invalidate the Range).
Dim rngField as Word.Range = Nothing
Dim sFieldCode as String
For Each Field As Microsoft.Office.Interop.Word.Field In DocTemplate.Fields
rngField = Field.Result
sFieldCode = Field.Code.Text
If sFieldCode.Contains("Date") Then
Field.Delete()
rngField.Text = Dates
ElseIf sFieldCode.Contains("ID") Then
Field.Delete()
rngField.Text = Dates

Dlookup passing incorrect value

I am using DLookup
Dim FormName As String
Dim OldBBusinessterm As Long
Dim field As Long
Dim NewBusinessTerm As String
Dim NewRecord As DAO.Database
Dim rstUpdate As DAO.Recordset
oldbusinessterm = Me!BusinessTermID.OldValue 'equal 5194 in test
NewBusinessTerm = Me!BusinessTermID.Value ' equal 5195 in test
BusinessTerm = DLookup("[businesstermdesc]", "tblbusinessterm", " [businesstermid] =" & oldbusinessterm)
' here is the issue - [businesstermid] = 5195 - it should be setting the value from Oldbusinessterm but it is populating it from New businessterm
Set NewRecord = CurrentDb
Set rstUpdate = NewRecord.OpenRecordset("TblFieldTermLink")
rstUpdate.AddNew
rstUpdate("GTSBusinessTerm").Value = BusinessTerm
rstUpdate("BusinessTermID").Value = Me!BusinessTermID.Value
rstUpdate.Update
My problem is that it is reading the businesstermID from my open form, instead of doing the dlookup using the old value.
Any ideas as to why
When you are adding a new record to table TblFieldTermLink you are using the new BusinessTermID value. If you want the Old value you should modify your code to reflect that:
rstUpdate.AddNew
rstUpdate("GTSBusinessTerm").Value = BusinessTerm 'String Text describing old BusinessTermID
rstUpdate("BusinessTermID").Value = oldbusinessterm 'Long Value of old BusinessTermID
rstUpdate.Update
I also notice that you are not using the variable you declared to hold the old business term id:
Dim OldBBusinessterm As Long
oldbusinessterm = Me!BusinessTermID.OldValue 'equal 5194 in test
Notice the spelling of the two. Which is why capitalization did not follow. Perhaps you want to correct the Dim statement:
Dim OldBusinessTerm As Long

Read a table in outlook mail using macro

I'm writing a macro to read the below Email:
Start Date: July-07-2016
Name Accept Approved
John Yes No
Peter No No
I'm good with search the word "Start date" and get the next 13 character to copy and paste that in a text file. But my problem is the next part is in a Table format. So when I'm searching for the name "John" and trying to copy the next 10 Characters. It doesn't work.
Is there a way to search for the word "Accept" and get the First Row data(Which will be No) and then Second Row data(Which will be No)? Is that possible?
This EMail's table will have only 2 Rows. So, I don't need any dynamic way to get the data. Can someone guide me?
I've tried searching the internet first, but the solutions are too huge for me to understand. Is there any simple way?
I have even tried the solution give here: How to read table pasted in outlook message body using vba? but that method works when the body has ONLY TABLE. But my EMail will have text as well as table.
I've never actually programmed in vba, but I think I can help (a bit) nevertheless.
In the answer on the post you linked to, there is the line
Set msg = ActiveExplorer.Selection.item(1)
I think you can change this to something like
Set msg = Right(ActiveExplorer.Selection.item(1), 25)
to get rid of the text before the table (I got the Right part from here: http://www.exceltrick.com/formulas_macros/vba-substring-function/, but it should also work in Outlook).
This way, you run the code on the table itself instead of on the whole message.If there is also text after the table, it might be more difficult, but you might get that done by searching for the table ending.
I hope this helps!
Attempt 2
After some searching and thinking, I came up with the idea to get the html of the message and use that to parse the table (Ok, not really, I got it from the comments here: http://www.codeproject.com/Questions/567073/Howplustoplusrecognizeplusandplusreadplustableplus). Based on that and other sources, it is possible to write a code that gets the table from an email.
I've written some code that might work, but I couldn't test it as I do not have Outlook. Also, this is my first time writing vba, so there may be a lot of syntax errors (and the code is ugly).
Sub GetTable()
Dim msg As Outlook.mailItem
Dim html As String
Dim tableBegin As String
Dim tableEnd As String
Dim posTableBegin As Long
Dim posTableEnd As Long
Dim table As String
Dim rowBegin As String
Dim rowEnd As String
Dim rowCount As Long
Dim columnBegin As String
Dim columnBeginLen As Long
Dim columnEnd As String
Dim posRowBegin As Long
Dim posRowEnd As Long
Dim values As String(0, 3)
Dim beginValue0 As Long
Dim beginValue1 As Long
Dim beginValue2 As Long
Dim EndValue0 As Long
Dim EndValue1 As Long
Dim EndValue2 As Long
' Get the message and the html
Set msg = ActiveExplorer.Selection.item(1)
html = msg.HTMLbody
' Get the begin and end positions of the table (within the html)
tableBegin = "<table>"
tableEnd = "</table>"
posTableBegin = InStr(1, html, tableBegin)
posTableEnd = InStr(posTableBegin, html, tableEnd)
' Get the html table
table = Mid(html, posTableBegin + Len(tableBegin), posTableEnd - posTableBegin - Len(tableBegin))
' Set the variables for the loop
rowBegin = "<tr>"
rowEnd = "</tr>"
rowCount = 0
columnBegin = "<td>"
columnBeginLen = Len(columnBegin)
columnEnd = "</td>"
' Loop trough all rows
posRowBegin = InStr(lastPos, table, rowBegin)
Do While posRowBegin != 0
' Get the end from the current row
posRowEnd = InStr(posRowBegin, table, rowEnd)
rowCount = rowCount + 1
' Make the array larger
ReDim Preserve values(rowCount + 1, 3)
' Get the contents from that row
row = Mid(table, posRowBegin + Len(rowBegin), posRowEnd - posRowBegin - Len(rowBegin))
' Get the three values from that row (name, Accept, Approved) and put it in the array
beginValue0 = InStr(1, row, columnBegin) + columnBeginLen
endValue0 = InStr(beginValue0, row, columnEnd)
beginValue1 = InStr(endValue0, row, columnBegin) + columnBeginLen
endValue1 = InStr(beginValue1, row, columnEnd)
beginValue2 = InStr(endValue1, row, columnBegin) + columnBeginLen
endValue2 = InStr(beginValue2, row, columnEnd)
values(rowCount, 0) = Mid(row, beginValue0, endValue0)
values(rowCount, 1) = Mid(row, beginValue1, endValue1)
values(rowCount, 2) = Mid(row, beginValue2, endValue2)
' Get the beginning of the next row
posRowBegin = InStr(lastPos, table, rowBegin)
Loop
' The values are now in the (double) array 'values'.
' values(0, [1-3]) contains the headers.
End Sub
As said before, the original idea came from http://www.codeproject.com/Questions/567073/Howplustoplusrecognizeplusandplusreadplustableplus. Additionally, I used Word VBA how to select text between two substrings and assign to variable? and the Microsoft documentation to write this.
While it is likely that the code does not work out of the box, I think it still gets the general idea (and some specifics) across, so that it can be used as a guide. I hope this is the solution you need!
You can actually use the Word Object Model to parse out the text from the table - assuming that the email is in HTML format.
Get a Word.Document object from the Inspector.WordEditor property and use Word objects and methods to get the text, like the following below example from MSDN. Just replace ActiveDocument with the variable you declare and set from WordEditor.
Sub ReturnCellContentsToArray()
Dim intCells As Integer
Dim celTable As Cell
Dim strCells() As String
Dim intCount As Integer
Dim rngText As Range
If ActiveDocument.Tables.Count >= 1 Then
With ActiveDocument.Tables(1).Range
intCells = .Cells.Count
ReDim strCells(intCells)
intCount = 1
For Each celTable In .Cells
Set rngText = celTable.Range
rngText.MoveEnd Unit:=wdCharacter, Count:=-1
strCells(intCount) = rngText
intCount = intCount + 1
Next celTable
End With
End If
End Sub

VBA on click_ delete records of a table

I am trying to delete the records of a table rather than deleting the records of a form. I have the following code, which does not work:
please can someone help.
Private Sub Cmd_X_Click()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim rsCount As Integer
Dim BizNO As Field
Dim Bank_Role As Field
Dim i, j As Integer
Set db = CurrentDb()
Set rs_date = db.OpenRecordset("TRD_Pricing-In date_REAL")
Set PE_ID = rs_date.Fields("Pricing_Element_ID")
rs_date.MoveLast
rs_dateCount = rs_date.RecordCount
MsgBox (rs_dateCount)
MsgBox (Me.Pricing_Element_ID)
MsgBox (PE_ID.Value)
rs_date.MoveLast
For i = 1 To rs_dateCount
If Me!Pricing_Element_ID = PE_ID Then
rs_date.DELETE
Else
rs_date.MovePrevious
End If
Next i
End Sub
In your for loop you are not comparing the right elements. When you do:
Set PE_ID = rs_date.Fields("Pricing_Element_ID")
you set PE_ID to the value of the Pricing_Element_ID of the first record. You intend to set a reference to it, and everytime the recordset advances to the next record, you want this reference to be updated. But that's not how it works. You have to get the field in the current record every time you advance the recordset. So you have to write:
If Me!Pricing_Element_ID = rs_date.Fields("Pricing_Element_ID") Then
Note: from experience I found the count of a recordset is not always accurate. So rather than a for loop, use a while loop:
While (Not EOF(rs_date))
If Me!Pricing_Element_ID = rs_date.Fields("Pricing_Element_ID") Then
rs_date.DELETE
Else
rs_date.MoveNext
End If
Wend
Note also that there is no need to proces the recordset from last to first; just advance to next until EOF.