Domino 9 und frühere Versionen > ND8: Entwicklung

Lotusscript Optimierung

(1/5) > >>

schroederk:
Hallo zusammen,

ich würde gerne von Euch über den folgende Code schauen lassen. Dieser wird über Web aufgerufen und soll aus dem Raum-und Reservierungsplaner mit angegebenem Datum und Raumname die vorhandenen Termine auflisten.
Der Code hat sicher noch Optimierungspotential und ich würde gerne konstruktive Kritik erfahren, wie ich was besser machen kann.
Die Ausgabe ist im Moment noch sehr spartanisch, ich weiß aber auch noch nicht, ob ich die Werte Komma-separiert übertrage und vom Web aus die Aufbereitung vornehme oder ob ich das schon im Script machen soll.


--- Zitat ---Option Public
Option Declare

Sub Initialize
   Dim s As New NotesSession
   Dim db As NotesDatabase
   Dim view As NotesView
   Dim doc As NotesDocument
   Dim vc As NotesViewEntryCollection
   Dim str_datum, str_aktdatum, str_raumname As String
   Dim col As NotesDocumentCollection
   Dim arg As String, p1 As Long
   Dim argarray As Variant
   Dim todaysdate As New NotesDateTime("Today")
   Dim startdatum, enddatum, raumname As String
   Dim teilnehmer As String
   Dim besprechtitel As String

   str_aktdatum = todaysdate.DateOnly

   On Error GoTo processError

   arg = s.DocumentContext.Query_String(0)
   p1 = InStr(arg, "&")
   arg = LCase(Mid$(arg, p1 + 1))                     ' alle Parameter aus der URL extrahieren
   argarray = Evaluate({@Explode("} & arg & {"; "&")})      ' jeden Parameter trennen und in Array speichern

   str_datum = argarray(0)
   str_raumname = argarray(1)
   If str_datum = "" Then                           ' Wenn kein Datum angegeben wurde, dann aktuelles Datum wählen
      str_datum = str_aktdatum
   End if
 
   Set db = s.GetDatabase("MAILSERVER/SRV/Group", "Besprech.nsf", False)
   If Not db.IsOpen Then Call db.Open("", "")

   Set view = db.GetView("Reservierungen nach Datum")         ' Alle Reservierungen nach Datum
   Set doc = view.GetFirstDocument

   While Not(doc Is Nothing)                           ' Alle Dokumente in Ansicht abarbeiten
      startdatum = Left(doc.GetItemValue("StartDate")(0),10)
      enddatum = Left(doc.GetItemValue("EndDate")(0),10)
      raumname = doc.GetItemValue("Room")(0)
      If raumname <> "" then
         raumname = Left(raumname,InStr(raumname,"/")-1)
      End if
      teilnehmer = doc.GetItemValue("Capacity")(0)
      besprechtitel = doc.GetItemValue("Purpose")(0)
      If str_datum = startdatum Or str_datum = enddatum Then
         If str_raumname = "" Or str_raumname = LCase(raumname) Then
            Print startdatum, enddatum, raumname, teilnehmer, besprechtitel, "<br>"
         End if
      End If
      Set doc = view.GetNextDocument(doc)
   Wend   
   Exit Sub
processError:
   Print "Fehler " & Str(Err) & ": " & Error$ & " in Zeile " & Str(Erl)
   Exit Sub    
End Sub

--- Ende Zitat ---

Peter Klett:
Option Public
Option Declare

Sub Initialize
   Dim s As New NotesSession
   Dim db As NotesDatabase
   Dim view As NotesView
   Dim doc As NotesDocument
   Dim vc As NotesViewEntryCollection *
   Dim str_datum, str_aktdatum, str_raumname As String **
   Dim col As NotesDocumentCollection *
   Dim arg As String, p1 As Long
   Dim argarray As Variant
   Dim todaysdate As New NotesDateTime("Today")
   Dim startdatum, enddatum, raumname As String **
   Dim teilnehmer As String
   Dim besprechtitel As String

* nicht verwendete Variablen solltest Du nicht definieren
** diese Deklarationen sind m.W. nicht korrekt, da die ersten Variablen Variants werden, und keine Strings

   str_aktdatum = todaysdate.DateOnly

   On Error GoTo processError

   arg = s.DocumentContext.Query_String(0)
   p1 = InStr(arg, "&")
   arg = LCase(Mid$(arg, p1 + 1))                     ' alle Parameter aus der URL extrahieren
   argarray = Evaluate({@Explode("} & arg & {"; "&")})      ' jeden Parameter trennen und in Array speichern

   Hier könntest Du auch den Script-Befehl Split verwenden

   str_datum = argarray(0)
   str_raumname = argarray(1)
   Du solltest vorher prüfen, ob es argarray (1) gibt (z.B. If Ubound (argarray) > 0 Then ...)
   If str_datum = "" Then                           ' Wenn kein Datum angegeben wurde, dann aktuelles Datum wählen
      str_datum = str_aktdatum
   End if
 
   Set db = s.GetDatabase("MAILSERVER/SRV/Group", "Besprech.nsf", False)
Server- und Dateinamen solltest Du nicht hart codieren, und wenn Du keine Möglichkeit siehst, diese Information irgendwo zu hinterlegen oder automatisch zu ermitteln (z.B. den Server aus der aktuellen Datenbank), dann sollte die Definition in Konstanten ganz oben im Script erfolgen, damit Du die später schnell findest und ändern kannst
Const server = "Mailserver/...."
   If Not db.IsOpen Then Call db.Open("", "")

   Set view = db.GetView("Reservierungen nach Datum")         ' Alle Reservierungen nach Datum
   Set doc = view.GetFirstDocument

   While Not(doc Is Nothing)                           ' Alle Dokumente in Ansicht abarbeiten
      startdatum = Left(doc.GetItemValue("StartDate")(0),10)
      enddatum = Left(doc.GetItemValue("EndDate")(0),10)
      raumname = doc.GetItemValue("Room")(0)
      If raumname <> "" then
         raumname = Left(raumname,InStr(raumname,"/")-1)
Das kracht, wenn Raumname kein "/" enthält, sicherer ist
         raumname = Left(raumname,InStr(raumname & "/","/")-1)
      End if
      teilnehmer = doc.GetItemValue("Capacity")(0)
      besprechtitel = doc.GetItemValue("Purpose")(0)
      If str_datum = startdatum Or str_datum = enddatum Then
         If str_raumname = "" Or str_raumname = LCase(raumname) Then
            Print startdatum, enddatum, raumname, teilnehmer, besprechtitel, "<br>"
         End if
      End If
      Set doc = view.GetNextDocument(doc)
   Wend   
   Exit Sub
processError:
   Print "Fehler " & Str(Err) & ": " & Error$ & " in Zeile " & Str(Erl)
   Exit Sub   
End Sub

Deine Suchlogik solltest Du überprüfen. Wenn Du einen Raum hast, der vom 01.12. bis zum 03.12. gebucht ist, und Du suchst nun nach diesem Raum am 02.12., wirst Du ihn so nicht finden, da Du nur Start- und Enddatum vergleichst. Auch das Durchkämmen der ganzen Ansicht wird mit der Dauer immer langsamer werden, wenn alte Einträge stehen bleiben. Ich würde da lieber ein db.Search nehmen. Da könntest Du
1. nur nach dem Raum suchen
2. nach Buchungen, deren Anfangsdatum <= dem Suchdatum ist und deren Enddatum >= dem Suchdatum ist (mehrtägige Buchungen hast Du anscheinend nicht in Deiner Suchabfrage)
Als Ergebnis hast Du gleich alle relevanten Dokumente. Die musst Du dann nur noch sortieren

schroederk:
Vielen Dank für die Prüfung und die konstruktiven Anmerkungen.
Ich werde sie beherzigen.

Bei den Variablen-Deklarationen verhau ich mich immer wieder, dank anderer Programmiersprachen.

Bei unseren Besprechungen haben wir bisher noch keine Reservierung gehabt, die länger als 1 Tag gedauert hat. Aber sicher hast Du recht, dass hier zukünftige Eventualitäten gleich berücksichtigt werden sollte.

Ich werde mir die Suche mit db.Search mal anschauen. Ist damit sicher besser umgesetzt.

mezz:

--- Code: ---   arg = s.DocumentContext.Query_String(0)
   p1 = InStr(arg, "&")
   arg = LCase(Mid$(arg, p1 + 1))                     ' alle Parameter aus der URL extrahieren
   argarray = Evaluate({@Explode("} & arg & {"; "&")})      ' jeden Parameter trennen und in Array speichern

--- Ende Code ---

Dazu noch eine Anmerkung: Dieses oder ähnliche Konstrukte sieht man leider häufiger, der QueryString wird hier ungefiltert in ein Evaluate übernommen dies kann im ungünstigsten Fall dazu führen das in den QueryString eingehängter Code (Formelsprache) im Kontext des Programmes/Agenten ausgeführt wird.
Ich empfehle mal etwas Lektüre zum Thema Sicherheit in Webanwendungen. :)

schroederk:
Danke für den Hinweis, mezz. Da der Agent nicht vom Benutzer sondern vom Webserver aufgerufen wird, ist da die Manipulationsmöglichkeit eingeschränkt. Zudem habe ich jetzt auf die Split-Funktion umgebaut, insofern konnte ich auf das Evaluate verzichten. (Bin ich eh kein Fan von)

Die Suche mit db.Search bereitet mir noch ein paar Problemchen. Die Hilfe ist dabei etwas verwirrend und die gefundenden Beispiele im Internet halfen nicht wirklich weiter.
In den Beispielen wird immer innerhalb einer Form gesucht. Kann ich anstelle der Form auch nach einer View suchen?

Also etwa sowas:
searchFormula = {View = "Reservierungen nach Datum" & Left(StartDate,10) <= str_datum & Left(EndDate,10) >= str_datum}

Ist die Suche wirklich schneller oder wäre es nur schneller wenn man FTSearch verwendet. (Vorausgesetzt, dass der Fulltext Index erstellt wurde, was ja nicht das Problem darstellen sollte)

Navigation

[0] Themen-Index

[#] Nächste Seite

Zur normalen Ansicht wechseln