Get and sort all views in a database - lotus-notes

I have some code that gets a list of all views&folders in a database. The problem is everything is very poorly organized. The list of views shows as almost random, although I assume there is some order...
Is there a way to take the list of all the views that show on the dialog prompt, and then sort the list alphabetically?
Sub Initialize
Dim s As New NotesSession
Dim w As New NotesUIWorkspace
Dim dbSource As NotesDatabase, dbDest As NotesDatabase
Dim source As NotesView, dest As NotesView
Dim vc As NotesViewEntryCollection
Dim docDest As NotesDocument
Dim ve As NotesViewEntry
Dim folders() As String
Dim i As Integer
Dim ret, rez
Set dbSource = s.CurrentDatabase
ForAll v In dbSource.Views
If v.IsFolder Then
i = i + 1
ReDim Preserve folders( i - 1 ) As String
folders( i - 1 ) = v.Name
End If
End ForAll
ret = w.Prompt( PROMPT_OKCANCELLISTMULT, "Folder selection", "Select one or more folders to move.", folders(0), folders )
If IsEmpty( ret ) Then
MessageBox "User canceled", , "Folder not selected"
Exit Sub
Else
rez = w.Prompt( 13, "Database selection", "Choose the database to move the folder to" )
ForAll f In ret
Set source = dbSource.GetView( f )
Set vc = source.AllEntries
Set dbDest = s.GetDatabase( rez(0), rez(1), False )
Call dbDest.EnableFolder( f )
Set ve = vc.GetFirstEntry
Do Until ve Is Nothing
Set docDest = ve.Document.CopyToDatabase( dbDest )
Call docDest.PutInFolder( f )
Set ve = vc.GetNextEntry( ve )
Loop
Call vc.RemoveAllFromFolder( f )
Call source.Remove
End ForAll
End If
End Sub

You can add this subroutine to sort the folders array before you include it in your prompt method.
Just call ShellSort(folders) before the line with w.Prompt();
Sub ShellSort( ar( ) As String )
Dim Lower As Integer
Dim Upper As Integer
Dim botMax As Integer
Dim i As Integer
Dim k As Integer
Dim h As Integer
Dim v As String
Lower% = Lbound( ar$( ) )
Upper% = Ubound( ar$( ) )
h% = 1
Do
h% = (3*h%) + 1
Loop Until h% > Upper%-Lower%+1
Do
h% = h% \ 3
botMax% = Lower% + h% - 1
For i% = botMax% + 1 To Upper%
v$ = ar$( i% )
k% = i%
While ar$( k% - h% ) > v$
ar$( k% ) = ar$( k% - h% )
k% = k% - h%
If (k% <= botMax%) Then Goto wOut
Wend
wOut:
If (k% <> i%) Then ar$(k%) = v$
Next
Loop Until h% = 1
End Sub
(source: http://www.dominoexperts.com/articles/Very-fast-sorting-algorithm)

You can use #Sort in a Evaluate call to get the folder names sorted.
Dim foldersList As String
Dim folders As Variant
...
ForAll v In dbSource.Views
If v.IsFolder Then
foldersList = foldersList + |:"| + Replace(Replace(v.Name, |\|, |\\|), |"|, |\"|) + |"|
End If
End ForAll
If foldersList <> "" then
folders = Evaluate(|#Sort(| + StrRight(foldersList, ":") + |)|)
...
The code above works this way:
First collect all folder names in a string as a formula list like
"xyz":"abc":"mno":"def"
Make sure that quotation marks in folder names are replaced by \" and backslashes for subfolders are replaced by \\.
Second evaluate a formula with #Sort("xyz":"abc":"mno":"def").
The result is a sorted variant string array you can use in your w.Prompt(..., ..., folders(0), folders ) like before.
The benefit of this solution is a very short code and it is fast too.

If you use a list instead of an array then the values will be automatically placed in a sorted order. eg.
Dim folders List As Boolean
ForAll v In dbSource.Views
If (v.IsFolder) Then folders(v.Name) = True
End ForAll

Related

Etabs API using VBA

I don't know why I cannot assign the stiffness value when I am using the code from Etabs API documentation.
Sub Main()
'if the above flag is set to True, specify the path to ETABS below
Dim ProgramPath As String
''set it to the desired path of your model
Dim ModelDirectory As String
ModelDirectory = "C:\CSi_ETABS_API_Example"
If Len(Dir(ModelDirectory, vbDirectory)) = 0 Then
MkDir ModelDirectory
End If
Dim ModelName As String
ModelName = "ETABS_API_Example.edb"
Dim ModelPath As String
ModelPath = ModelDirectory & Application.PathSeparator & ModelName
'create API helper object
Dim myHelper As cHelper
Set myHelper = New Helper
''dimension the ETABS Object as cOAPI type
Dim myETABSObject As cOAPI
Set myETABSObject = Nothing
''use ret to check return values of API calls
Dim ret As Long
On Error Resume Next
''get the active ETABS object
Set myETABSObject = GetObject(, "CSI.ETABS.API.ETABSObject")
If myETABSObject Is Nothing Then
If ProgramPath <> "" Then
''create an instance of the ETABS object from the specified path
Set myETABSObject = myHelper.CreateObject(ProgramPath)
Else
''create an instance of the ETABS object from the latest installed ETABS
Set myETABSObject = myHelper.CreateObjectProgID("CSI.ETABS.API.ETABSObject")
End If
''start ETABS application
myETABSObject.ApplicationStart
End If
''get a reference to cSapModel to access all OAPI classes and functions
Dim mySapModel As ETABS2016.cSapModel
Set mySapModel = myETABSObject.SapModel
''initialize model
ret = ret + mySapModel.InitializeNewModel()
''create steel deck template model
ret = ret + mySapModel.File.NewSteelDeck(1, 12, 12, 2, 2, 8, 8)
''Set release
Dim ii() As Boolean
Dim jj() As Boolean
Dim StartValue() As Double
Dim EndValue() As Double
ReDim ii(5)
ReDim jj(5)
ReDim StartValue(5)
ReDim EndValue(5)
ii(5) = True
jj(5) = True
StartValue(5) = 10000#
EndValue(5) = 10000#
ret = mySapModel.FrameObj.SetReleases("5", ii, jj, StartValue, EndValue)
''
''clean up variables
mySapModel = Nothing
myETABSObject = Nothing
End Sub
enter image description here
The code can set the release but it cannot assign the value.
Is there any way to fix it.
Thanks for any helps.
I guess the problem is in the assignment of ii, jj, StartValue and EndValue.
It would need to take a longer code to assign every value to these arrays. Something like that
Dim StartValue(5) As Double, EndValue(5) As Double
Dim ii(5) As Boolean, jj(5) As Boolean
Dim i As Integer
'<If you need to make the 2 points released at M33 only>
'First: the DOFs with no release
For i = 0 To 4
StartValue(i) = 1
EndValue(i) = 1
ii(i) = False
jj(i) = False
Next i
'Second: the DOFs that have release
StartValue(5) = 0
EndValue(5) = 0
ii(5) = True
jj(5) = True
P.S. No need to use the form ret = ret + Some_method, ret = Some_method would be enough to just make your method works.
Note:-
Partial fixity (I guess this is what you mean by stiffness) is a value within range between 0 and 1, to assign a value to M33's partial fixity, just assign the values you want to StartValue(5) and EndValue(5).

Trying to export a view but only getting the first line of data repeated

I am trying to export a view using LotusScript. Some of the columns in the view are displaying multi-value field values which display on separate lines within the view. I have made some changes to this code that I imported from the web. I made the change for the separator from commas to pipes "|" because a field in the document may contain commas.
The problem I am having is that I am getting the first line of data to be repeated for the number of entries in the view.
My view looks similar to this:
(For display purposes, I am using commas to separate 3 different items in view)
first column: ReqNum contains
A93120, A93120, A94192
second column: Qty contains
1, 16, 10
third column: Desc contains
tax, APXT918 7" Bolt, 391" sheet metal
The view that I am using is displaying the fields that are needing to be exported. The second and third column are multi-valued fields.
When I export the view, I get the first item repeated 3 times in the file since the view knows that their are 3 entries within the view.
The exported file will look like this:
|ReqNumber|Qty|Desc
|A93120|1|tax
|A93120|1|tax
|A93120|1|tax
Instead of looking like this:
|ReqNumber|Qty|Desc
|A93120|1|tax
|A93120|16|APXT918 7" Bolt
|A94192|10| 391" sheet metal
Can someone tell me where I am missing the piece to move to the next record in the view?
Thank you in advance for your help.... It is very much appreciated.
Jean Stachler
%REM
Agent Copied Export Code
Mar 26, 2015 by Jean Stachler
Description: Comments for Agent
%END REM
Option Public
Option Declare
%Include "lsconst.lss"
%REM
Agent View Export
Created Mar 27, 2013 by Karl-Henry Martinsson
Description: Code to export a specified view as CSV.
Copyright (c) 2013 by Karl-Henry Martinsson
This code is distributed under the terms of
the GNU General Public License V3.
See http://www.gnu.org/licenses/gpl.txt
%END REM
Class RowData
Public column List As String
Public Sub New()
End Sub
Public Sub SetColumnHeader(view As NotesView)
Dim viewcolumn As NotesViewColumn
Dim cnt As Integer
ForAll vc In view.Columns
Set viewcolumn = vc
column(CStr(cnt)) = viewcolumn.Title
cnt = cnt + 1
End ForAll
End Sub
Public Sub SetColumnValues(values As Variant)
Dim cnt As Integer
Dim tmp As String
ForAll v In values
If IsArray(v) Then
ForAll c In v
' tmp = tmp + c + Chr$(13)
tmp = c + Chr$(13)
Messagebox tmp
End ForAll
column(CStr(cnt)) = Left$(tmp,Len(tmp)-1)
Messagebox column(CStr(cnt))
Else
column(CStr(cnt)) = v
Messagebox column(CStr(cnt))
End If
cnt = cnt + 1
End ForAll
End Sub
End Class
Class CSVData
Private row List As RowData
Private rowcnt As Long
%REM
Function New
Description: Open the view and read view data
into a list of RowData objects.
%END REM
Public Sub New(server As String, database As String, viewname As String)
Dim db As NotesDatabase
Dim view As NotesView
Dim col As NotesViewEntryCollection
Dim entry As NotesViewEntry
Dim colcnt As Integer
Set db = New NotesDatabase(server, database)
If db Is Nothing Then
MsgBox "Could not open " + database + " on " + server,16,"Error"
Exit Sub
End If
Set view = db.GetView(viewname)
If view Is Nothing Then
MsgBox "Could not access view " + viewname + ".",16,"Error"
Exit Sub
End If
Set col = view.AllEntries()
rowcnt = 0
Set entry = col.GetFirstEntry()
Set row("Header") = New RowData()
Call row("Header").SetColumnHeader(view)
Do Until entry Is Nothing
rowcnt = rowcnt + 1
Set row(CStr(rowcnt)) = New RowData()
Call row(CStr(rowcnt)).SetColumnValues(entry.ColumnValues)
Set entry = col.GetNextEntry(entry)
Loop
End Sub
%REM
Function CSVArray
Description: Returns a string array of CSV data by row
%END REM
Public Function CSVArray() As Variant
Dim rowarray() As String
Dim textrow As String
Dim cnt As Long
ReDim rowarray(rowcnt) As String
ForAll r In row
textrow = ""
ForAll h In r.column
Messagebox h
' textrow = textrow + |"| + Replace(h,Chr$(13),"\n") + |",|
' textrow = textrow + |"| + Replace(h,Chr$(13),"|")
textrow = textrow + "|" + Replace(h,Chr$(13),"|")
Messagebox textrow
End ForAll
Messagebox textrow
rowarray(cnt) = Left$(textrow,Len(textrow)-1)
Messagebox rowarray(cnt)
cnt = cnt + 1
End ForAll
CSVArray = rowarray
End Function
%REM
Function HTMLArray
Description: Returns a string array of HTML data by row
%END REM
Public Function HTMLArray() As Variant
Dim rowarray() As String
Dim textrow As String
Dim cnt As Long
ReDim rowarray(rowcnt) As String
ForAll r In row
textrow = ""
ForAll h In r.column
textrow = textrow + |<td>| + Replace(h,Chr$(13),"<br>") + |</td>|
End ForAll
rowarray(cnt) = "<tr>" + textrow + "</tr>"
cnt = cnt + 1
End ForAll
HTMLArray = rowarray
End Function
End Class
%REM
********************************
Example of how to call the class
********************************
%END REM
Sub Initialize
Dim csv As CSVData
Dim outfile As String
Set csv = New CSVData("CrownNotes2/CrownNotes", "Purchasing\purreqdyn.nsf", "(ExportDetail)")
outfile = "c:\Data\ReqdetailSecond.txt"
Open outfile For Output As #1
ForAll row In csv.CSVArray()
Print #1, row
End ForAll
Close #1
outfile = "c:\Data\ExcelExportTest.xls"
Open outfile For Output As #2
Print #2, "<table>"
ForAll row In csv.HTMLArray()
Print #2, row
End ForAll
Print #2, "</table>"
Close #2
End Sub
I will try again to get the details listed.
Here is the section that will repeat the line the number of times the line is listed. It seems to me that it is picking up the first item, instead of going through the multivalue field.
ForAll r In row
textrow = ""
ForAll h In r.column
Messagebox h
textrow = textrow + "|" + Replace(h,Chr$(13),"|")
Messagebox textrow
End ForAll
Messagebox textrow
rowarray(cnt) = Left$(textrow,Len(textrow)-1)
Messagebox rowarray(cnt)
cnt = cnt + 1
End ForAll
CSVArray = rowarray
I have also come up with another way of doing this but am having a problem trying to get rid of carriage returns. Will post this issue shortly.

LotusScript cannot get file attachment from email

I had never run into this problem, but I cannot get a handle on a file attachment on an email. I have code that can either search the document for Embedded Objects or search a field for Embedded Objects -- neither of them are returning the file. I can see the file on the email and I can see the $FILE field which contains the file attachment.
Here is the code:
Function FileDetachFiles(doc As NotesDocument, fieldName As String, getFromField As Integer) As Variant
On Error Goto ProcessError
Dim s As NotesSession
Dim db As NotesDatabase
Dim rtItem As NotesRichTextItem
Dim fileToExtract As String
Dim fileName As String
Dim fileArray() As String
Dim message As String
Dim embedObjects As Variant
Dim attachFile As Integer
Dim x As Integer
Set s = New NotesSession
Set db = s.CurrentDatabase
Const fileImport = "C:\"
attachFile = False
'Let's see if there are attached files...
If getFromField = True Then
'Locate field and get files...
If doc.HasEmbedded Then
If doc.HasItem(fieldName) Then
'Set the first field...
Set rtItem = doc.GetFirstItem(fieldName)
embedObjects = rtItem.EmbeddedObjects
If Isarray(embedObjects) Then
Forall Files In rtItem.EmbeddedObjects
If Files.Type = EMBED_ATTACHMENT Then
fileName = Files.Source
fileToExtract = fileImport & fileName
Redim Preserve fileArray(x)
fileArray(x) = fileToExtract
x = x + 1
Call Files.ExtractFile(fileToExtract)
attachFile = True
End If
End Forall
End If
End If
End If
Else
x = 0
'Go through doc looking for all embedded objects...
If doc.HasEmbedded Then
Forall o In doc.EmbeddedObjects
If o.Type = EMBED_ATTACHMENT Then
fileName = o.Name
fileToExtract = fileImport & fileName
Call o.ExtractFile(fileToExtract)
Redim Preserve fileArray(x)
fileArray(x) = fileToExtract
x = x + 1
attachFile = True
End If
End Forall
End If
End If
If attachFile = True Then
FileDetachFiles = fileArray
End If
Exit Function
ProcessError:
message = "Error (" & Cstr(Err) & "): " & Error$ & " on line " & Cstr(Erl) & " in GlobalUtilities: " & Lsi_info(2) & "."
Messagebox message, 16, "Error In Processing..."
Exit Function
End Function
I tried both routines above -- passing the $FILE and Body field names, as well as searching the document. It does not find any file attachments.
I even tried this:
Extracting attachments as MIME using LotusScript
Which did not find any MIME on the document.
I have never run into this problems -- any ideas would be great.
Thanks!
I had that before, but unfortunately do not remember, where it comes from, it might have to do something with V2- Style Attachments coming from Domino Websites...
Try Evaluate( #AttachmentNames ) to get a Variant containing the names of all attachments. Then loop through this with a Forall- loop and try the NotesDocument.getAttachment( strLoopValue ) - Function to get a handle to the attachment.
For further info read here and follow the links on that page, especially this one
Code would be something like this:
Dim doc as NotesDocument
Dim varAttachmentNamens as Variant
Dim object as NotesEmbeddedObject
REM "Get the document here"
varAttachmentNames = Evaluate( "#AttachmentNames" , doc )
Forall strAttachmentName in varAttachmentNames
Set object = doc.GetAttachment( strAttachmentName )
REM "Do whatever you want..."
End Forall

Lotus Notes View with multiline data Export to Excel

I need to export a lotus notes view to excel. The problem is, I have two columns in the view which displays multiple values with "New line" as the separator. I tried the inbuilt export function as well as with a new lotus script export function with few formatting. In both the cases the multiple values cannot be made to appear in one cell. Only the first value is displayed in each row. The rest of the values are ignored. Our User wants the excel report only with Multiple values in New line and not with any other delimiter.
Kindly help me with your suggestions. I am using Lotus notes 6.5 and Microsoft office 2010.
Thank you.
Write the export in Lotusscript. Not hard, and you get full control of the export.
If the fields are multi-value fields, simply read the values as a variant and then write them to the output file with newline between each item.
Here is one idea of how to solve it:
%REM
Agent View Export
Created Mar 27, 2013 by Karl-Henry Martinsson
Description: Code to export a specified view as CSV.
Copyright (c) 2013 by Karl-Henry Martinsson
This code is distributed under the terms of
the GNU General Public License V3.
See http://www.gnu.org/licenses/gpl.txt
%END REM
Option Public
Option Declare
Class RowData
Public column List As String
Public Sub New()
End Sub
Public Sub SetColumnHeader(view As NotesView)
Dim viewcolumn As NotesViewColumn
Dim cnt As Integer
ForAll vc In view.Columns
Set viewcolumn = vc
column(CStr(cnt)) = viewcolumn.Title
cnt = cnt + 1
End Forall
End Sub
Public Sub SetColumnValues(values As Variant)
Dim cnt As Integer
Dim tmp As String
ForAll v In values
If IsArray(v) Then
ForAll c In v
tmp = tmp + c + Chr$(13)
End ForAll
column(CStr(cnt)) = Left$(tmp,Len(tmp)-1)
Else
column(CStr(cnt)) = v
End If
cnt = cnt + 1
End ForAll
End Sub
End Class
Class CSVData
Private row List As RowData
Private rowcnt As Long
%REM
Function New
Description: Open the view and read view data
into a list of RowData objects.
%END REM
Public Sub New(server As String, database As String, viewname As String)
Dim db As NotesDatabase
Dim view As NotesView
Dim col As NotesViewEntryCollection
Dim entry As NotesViewEntry
Dim colcnt As Integer
Set db = New NotesDatabase(server, database)
If db Is Nothing Then
MsgBox "Could not open " + database + " on " + server,16,"Error"
Exit Sub
End If
Set view = db.GetView(viewname)
If view Is Nothing Then
MsgBox "Could not access view " + viewname + ".",16,"Error"
Exit Sub
End If
Set col = view.AllEntries()
rowcnt = 0
Set entry = col.GetFirstEntry()
Set row("Header") = New RowData()
Call row("Header").SetColumnHeader(view)
Do Until entry Is Nothing
rowcnt = rowcnt + 1
Set row(CStr(rowcnt)) = New RowData()
Call row(CStr(rowcnt)).SetColumnValues(entry.ColumnValues)
Set entry = col.GetNextEntry(entry)
Loop
End Sub
%REM
Function CSVArray
Description: Returns a string array of CSV data by row
%END REM
Public Function CSVArray() As Variant
Dim rowarray() As String
Dim textrow As String
Dim cnt As Long
ReDim rowarray(rowcnt) As String
ForAll r In row
textrow = ""
ForAll h In r.column
textrow = textrow + |"| + Replace(h,Chr$(13),"\n") + |",|
End ForAll
rowarray(cnt) = Left$(textrow,Len(textrow)-1)
cnt = cnt + 1
End ForAll
CSVArray = rowarray
End Function
%REM
Function HTMLArray
Description: Returns a string array of HTML data by row
%END REM
Public Function HTMLArray() As Variant
Dim rowarray() As String
Dim textrow As String
Dim cnt As Long
ReDim rowarray(rowcnt) As String
ForAll r In row
textrow = ""
ForAll h In r.column
textrow = textrow + |<td>| + Replace(h,Chr$(13),"<br>") + |</td>|
End ForAll
rowarray(cnt) = "<tr>" + textrow + "</tr>"
cnt = cnt + 1
End ForAll
HTMLArray = rowarray
End Function
End Class
%REM
********************************
Example of how to call the class
********************************
%END REM
Sub Initialize
Dim csv As CSVData
Dim outfile As String
Set csv = New CSVData("DominoServer/YourDomain", "names.nsf", "People\By Last Name")
outfile = "c:\ExcelExportTest.csv"
Open outfile For Output As #1
ForAll row In csv.CSVArray()
Print #1, row
End ForAll
Close #1
outfile = "c:\ExcelExportTest.xls"
Open outfile For Output As #2
Print #2, "<table>"
ForAll row In csv.HTMLArray()
Print #2, row
End ForAll
Print #2, "</table>"
Close #2
End Sub

Can anyone offer feedback on my LotusScript agent?

Hi there I'm not a developer and so am unaware of best practices. I created this to bypass manual data copying of log data. This agent is for a single feed which I'll copy and adjust for each additional one. For the specified feed it reads the log for the last time processed and number of files processed so far today and for yesterday. It also counts files in the input folder and reads the server's timezone. Each data item is separated by a comma for csv and emailed, which later is hosted on a website. Thanks for any constructive criticism.
Sub Initialize
Dim customername As String
Dim servername As String
Dim feedname As String
Dim alertthresholdinhours As Integer
Dim inputfeedpath As String
' Set for each feed
customername = "gRrhio"
servername = "gRrhioEdge2"
feedname = "FF Thompson ADT"
alertthresholdinhours = 6
inputfeedpath = "\\mhinec\elycon\data\adt\*.*"
' Counts files in input folder
Dim pathName As String, fileName As String
Dim inputfeedcounter As Integer
inputfeedcounter = 0
pathName$ = inputfeedpath
fileName$ = Dir$(pathName$, 0)
Do While fileName$ <> ""
inputfeedcounter = inputfeedcounter + 1
fileName$ = Dir$()
Loop
Dim entry As NotesViewEntry
Dim vc As NotesViewEntryCollection
Dim filesprocessed As Integer
Dim session As New NotesSession
Dim db As NotesDatabase
Dim newDoc As NotesDocument
Dim rtitem As NotesRichTextItem
Set db = session.CurrentDatabase
Dim view As NotesView
Set view = db.GetView( "Sessions\by Feed" )
Set newDoc = New NotesDocument( db )
Set rtitem = New NotesRichTextItem( newDoc, "Body" )
Dim todaysdate As New NotesDateTime("Today")
Dim flag As Integer
Dim counter As Integer
Dim files As Integer
Dim errors As Integer
Dim lastdate As String
Dim lastdayran As String
Dim lasttime As String
Dim lasttimeran As String
Dim filesp As Integer
Dim lastdayfiles As Integer
Dim lastdaysfiles2 As Integer
Dim terrors As Integer
Dim lastdayerrors As Integer
lastdate = ""
lastdayran = ""
counter = 0
flag = 0
filesp = 0
lastdayfiles = 0
lastdaysfiles2 = 0
terrors = 0
lastdayerrors = 0
' Finds date for last time processed, counts files processed and errors
While flag = 0
Dim dateTime As New NotesDateTime(todaysdate.DateOnly)
Dim keyarray(1) As Variant
keyarray(0) = feedname
Set keyarray(1) = dateTime
Set vc = view.GetAllEntriesByKey(keyarray, False)
Set entry = vc.GetFirstEntry
If entry Is Nothing Then
Call todaysdate.AdjustDay(-1)
End If
While Not entry Is Nothing
files = 0
Forall colval In entry.ColumnValues
If counter = 9 Then
counter = 0
Elseif counter = 8 Then
counter = 9
Elseif counter = 7 Then
counter = 8
Elseif counter = 6 Then
errors = Cint(colval)
counter = 7
Elseif counter = 5 Then
counter = 6
Elseif counter = 4 Then
files = Cint(colval)
counter = 5
Elseif counter = 3 Then
counter = 4
Elseif counter = 2 Then
counter = 3
lasttime = colval
Elseif counter = 1 Then
counter = 2
lastdate = colval
Elseif counter = 0 Then
counter = 1
End If
End Forall
filesp = filesp + files
terrors = terrors + errors
Set entry=vc.GetNextEntry (entry)
flag = 1
Wend
Wend
lastdayfiles = filesp
lastdayerrors = terrors
lastdayran = lastdate
lasttimeran = lasttime
'Counts previous files processed
filesp = 0
terrors = 0
lastdate = ""
flag = 0
Call todaysdate.AdjustDay(-1)
While flag = 0
Dim dateTime2 As New NotesDateTime(todaysdate.DateOnly)
Dim keyarray2(1) As Variant
keyarray2(0) = feedname
Set keyarray2(1) = dateTime2
Set vc = view.GetAllEntriesByKey(keyarray2, False)
Set entry = vc.GetFirstEntry
If entry Is Nothing Then
Call todaysdate.AdjustDay(-1)
End If
While Not entry Is Nothing
files = 0
Forall colval In entry.ColumnValues
If counter = 9 Then
counter = 0
Elseif counter = 8 Then
counter = 9
Elseif counter = 7 Then
counter = 8
Elseif counter = 6 Then
counter = 7
Elseif counter = 5 Then
counter = 6
Elseif counter = 4 Then
files = Cint(colval)
counter = 5
Elseif counter = 3 Then
counter = 4
Elseif counter = 2 Then
counter = 3
Elseif counter = 1 Then
counter = 2
Elseif counter = 0 Then
counter = 1
End If
End Forall
filesp = filesp + files
Set entry=vc.GetNextEntry (entry)
flag = 1
Wend
Wend
lastdaysfiles2 = filesp
' Prints line of CSV into body of email
Call rtitem.AppendText ( customername )
Call rtitem.AppendText ( ", " )
Call rtitem.AppendText ( servername )
Call rtitem.AppendText ( ", " )
Call rtitem.AppendText ( datetime.timezone )
Call rtitem.AppendText ( ", " )
Call rtitem.AppendText ( lastdayran )
Call rtitem.AppendText ( " " )
Call rtitem.AppendText ( lasttimeran )
Call rtitem.AppendText ( ", " )
Call rtitem.AppendText ( lastdayfiles )
Call rtitem.AppendText ( ", " )
Call rtitem.AppendText ( lastdayerrors )
Call rtitem.AppendText ( ", " )
Call rtitem.AppendText ( lastdaysfiles2 )
Call rtitem.AppendText ( ", " )
Call rtitem.AppendText ( inputfeedcounter )
Call rtitem.AppendText ( ", " )
Call rtitem.AppendText ( alertthresholdinhours )
Call newDoc.Save( False, True )
newDoc.Subject = feedname
' Running from server line should be
'newDoc.SendTo = "Ecmon Feedcheck/Ecmonitor#ECMONITOR"
newDoc.SendTo = "AX1Forward Feedcheck/ACHQ#company.com"
newDoc.Send( False )
End Sub
For not being a developer, you can write a lot of code :)
If you are looking for some lessons to start becoming a good developer, then take Mitch's advice (from the comments) and break up this into subroutines. Lesson 1: There's definitely some repetitve code here, and it's always a good idea to put repetitive code into a method (function or subroutine) so it only exists once. The section that counts files processed and previous files processed looks similar and could probably be put into a routine like:
Function GetCountFilesProcessed() As Integer
'code here
End Function
However, you might even be able to save the need for that if I'm understanding your code correctly. Instead of doing that strange loop in the middle, it appears you're are trying to simply get a value from a column of a viewentry. Say you are interetsed in column 4's value. You can simply get at the value for the column you want by accessing it by index. For example, your files variable could be set directly to column 4's value by this line
files = Cint(entry.ColumnValues(4)) 'check this, it might be 3 if the array is zero based.
Anyway, bottom line is if this code works then you're off to a good start!
On more of the style side of things, I've always found it easier to maintain other people's code when they've
Declared Option 'Explicit' in the Declarations section
Declared variables from approximately higher to lower (eg, session before db before view before doc)
Prefixed notes objects with their type (docMail, dbMyDatabase, viewOutstandingInvoices)
Put all of the Declarations at the top before (helps finding the declaration when you come across a variable)
As others have mentioned, break it up into functions/subs where applicable.
Your comment about copying this agent for other instances of the same problem also raises a flag. Try to work out what is common between these agents and push those functions into a script library. This sort of thing saves a lot of time when maintaining the code as you don't need to think about in what way each agent is different (Eg. does my change apply to all instances of this agent, or just some of them?)
You want to decompose your code much more and ... one little thing. Instead of
while not item is nothing
which is a double negation and a popular brain bender.. write:
do until item is nothing
...
loop
This also allows you to break out of the loop with exit do
you can optimize both of your ForAll loops.
This is how the first one would look:
Forall colval In entry.ColumnValues
Select Case (counter)
Case 1: lastdate = colval
Case 2: lasttime = colval
Case 4: files = Cint(colval)
Case 6: errors = Cint(colval)
End Select
counter = (counter + 1) Mod 10
End Forall
This is how the second would one would look like:
Forall colval In entry.ColumnValues
if (counter = 4) Then files = Cint(colval)
counter = (counter + 1) Mod 10
End Forall
Just a note regarding this bit
While Not entry Is Nothing
files = 0
Forall colval In entry.ColumnValues
If counter = 9 Then
counter = 0
Elseif counter = 8 Then
counter = 9
....
As ken says you can get columnValues by using the entry.ColumnValues(x) method so interating through the values is un-needed. But; you could have done this
While Not entry Is Nothing
files = 0
counter = 0
Forall colval In entry.ColumnValues
counter = counter + 1
Select case counter
case 6
errors = Cint(colval)
.....
end select
Some good points already. To add to them if you have variables that share a common object then create a class. Add your variables to that class.
So instead of say:
Dim userFullName as String
Dim age as Integer
Dim addressLine1 as String
' ... etc.
You can have:
Class UserDetails
Dim fullName as String
Dim age as Integer
Dim addressLine1 as String
' ... etc
End Class
and reference:
Dim u as new UserDetails
u.fullName = "full name"
u.age = 22
u.addressLine1 = "1 main street"
The advantage of this is you can add methods to manipulate that data and you know the code relates to that object rather then hunting through your application.

Resources