Das Notes Forum
Domino 9 und frühere Versionen => Entwicklung => Thema gestartet von: TMC am 27.09.03 - 18:16:48
-
Hi,
ich habe folgenden Code - fast 1:1 aus der Designerhilfe (remove item) - nur eingeschränkt auf "Set collection = db.UnprocessedDocuments".
Sub Initialize
'Löscht alle Items "Untitled" aus ausgewählten Docs in der View (auch wenn Item mehrfach enthalten)..
Dim session As New NotesSession
Dim db As NotesDatabase
Dim collection As NotesDocumentCollection
Dim doc As NotesDocument
Dim item As NotesItem
Set db = session.CurrentDatabase
Set collection = db.UnprocessedDocuments
Set doc = collection.GetFirstDocument
While Not(doc Is Nothing)
If doc.HasItem("Untitled") Then
Set item = doc.GetFirstItem("Untitled")
Call item.Remove
Call doc.Save(True, True)
Set doc = collection.GetNextDocument(doc)
End If
Wend
End Sub
Allerdings wohl eine Endlosschleife, der Mauszeiger zeigt ewig die Sanduhr (mit STRG+Pause aber abbrechbar).
Wo könnte der Fehler liegen?
Im Agenten habe ich unter "Which docs should it act on" "Selected docs" eingestellt. Wenn ich "All docs in view" nehme ist es dasselbe, auch dann hängt er.
Ach ja, was soll das Script machen (Zitat Hilfe, und genau das brauche ich ;)):
This example uses the Remove method of the NotesItem class to remove all the ModifiedBy items in the database. To handle multiple items with the same name, the code removes items in a loop that tests HasItem.
TMC
-
While Not(doc Is Nothing)
If doc.HasItem("Untitled") Then
Set item = doc.GetFirstItem("Untitled")
Call item.Remove
Call doc.Save(True, True)
Set doc = collection.GetNextDocument(doc)
End If
Wend
sollte eigentlich
While Not(doc Is Nothing)
If doc.HasItem("Untitled") Then
Set item = doc.GetFirstItem("Untitled")
Call item.Remove
Call doc.Save(True, True)
End If
Set doc = collection.GetNextDocument(doc)
Wend
heißen
-
Danke Ulrich!
So funktioniert es auch, aber nun werden nicht alle Items des gleichen Namens gelöscht sondern nur das erste.
Und die Hilfe meinte ja:
the code removes items in a loop that tests HasItem.
Nur haben die Help-Ersteller wohl übersehen dass das endlos ist :-\
Wie auch immer, ich hab jetzt einfach einen 2. while/wend reingebaut dann gehts:
Sub Initialize
Dim session As New NotesSession
Dim db As NotesDatabase
Dim collection As NotesDocumentCollection
Dim doc As NotesDocument
Dim item As NotesItem
Set db = session.CurrentDatabase
Set collection = db.UnprocessedDocuments
Set doc = collection.GetFirstDocument
While Not(doc Is Nothing)
While (doc.HasItem("test33"))
Set item = doc.GetFirstItem("test33")
Call item.Remove
Call doc.Save(True, True)
Wend
Set doc = collection.GetNextDocument(doc)
Wend
End Sub
So speichert das Script zwar 17mal das Doc wenn 17 Items vorhanden, aber mir genügt das trotzdem, lasse ja nicht 100k Docs ändern ;D
Grüße,
TMC
-
Da könnte man auch was machen mit
bChanged = false
ForAll items in NotesDocument
If item.Name = "xxx"
Call item.Remove
BChanged = true
End If
End ForAll
If bChanged = true then
Call NotesDocument.Save (True, False, True)
End If
Hilft Dir das? Und sorry, daß es so "aus dem Bauch geschrieben wurde". Sitze gerade über einem Problem, daß aus einer DB alle Attachments auf Platte (und ann -> CD) gelöst werden müssen und dabei an Hand der vielstufigen Kategorien/Subkategorien/... eine übersichtliche Verzeichnisstruktur aufgebaut werden muß ... Glücklicherweise sind jetzt die wesentlichen Probleme (Anlage der Verzeichnisstruktur an Hand der Kategorisierung) gelöst ;-)
Ciao,
Bernhard
-
Glücklicherweise sind jetzt die wesentlichen Probleme (Anlage der Verzeichnisstruktur an Hand der Kategorisierung) gelöst ;-)
das hätte ich per API gelöst
Declare Function MakePath Lib "imagehlp.dll" Alias "MakeSureDirectoryPathExists" (ByVal lpPath As String) As Long
Sub Click(Source As Button)
Msgbox MakePath("C:\Notes\Data\Test\")
End Sub
eknori
-
Danke, Dein "Bauch-Gefühl" hört sich gut an, werde ich noch testen.
Glücklicherweise sind jetzt die wesentlichen Probleme (Anlage der Verzeichnisstruktur an Hand der Kategorisierung) gelöst ;-)
Stelle ich mir auch etwas komplex vor.
Schätze Du hast da jew. die Kategorie(n) ausgelesen, als Variablen definiert, und dann jew. Ordner erstellt.
Und jetzt wars wahrscheinlich komplex: Wenn 3. Unterkategorie, dann erstelle Ordner in OrdnerVar1 / OrdnerVar2 / ..
usw.
(so hätt ich jetzt mal versucht zu starten mit der Vorgabe....)
Na ja, super, wenn Du es schon gelöst hast :D
TMC
** Edit **
;D Ulrich hat da natürlich gleich was mit API als Lösung ;D
-
Hallo, eknori,
ich hatte es schon befürchtet, daß es einfacher sein würde, wenn ich meine Problemstellung einfach mal posten würde ;-)
A-Bär:
Nr. 1: Ich wollte einfach auch die Bordmittel selber kennen lernen, nachdem ich bis jetzt für Exports recht einfache Routinen verwendet habe (Schande über mich ;-(
Nr. 2: Es gibt Randbedingungen zu beachten - die (vier) zu verwendenden Kategorie-Bezeichnungen können sowohl insgesamt zu lang werden als auch Zeichen enthalten, die als SubDir-Namen verboten sind. Das könnte man natürlich auch bei Deiner API-Routine ausfiltern, aber ...
Nr. 3: Ich habe Deine Routine ausprobiert, aber in der vierten SubDir-Ebene ist Feierabend - die wird einfach nicht mehr angelegt:
MakePath ("D:\A1\B2\C3\D4")
Was jetzt aber mystisch ist ...
Trotzdem aber herzlichen Dank, und ich werde die von Dir erwähnte API-Funktion sehr gerne in meine "Raupensammlung" aufnehmen ;-)
Ciao,
Bernhard
-
@TMC & @eknori:
Wenn die benötigte LS-Routine fertig ist, dann stelle ich sie hier unter Tipps und Tricks rein.
Und sehr gerne werfe ich sie vorher weg, wenn eknori bei der API-Routine nachlegt oder mir sagt, wo mein Fehler liegt, wenn ich die API-Routine verwende.
Aber pure LS wird vielleicht auch ganz interessant - da braucht man ja ein spezielles Parsing, ErrorHandling etc.
So long,
Bernhard
PS: API wäre mir wirklich lieber - und auch meine Routinen gehorchen nur den Directory-Konventionen von Windows - AIX, Linux etc. sind aussen vor (aber ich muß ja sowieso nur von einem Client - ergo Windows - alle Attachments lösen und strukturieren)
-
habe das mit der API nochmals geteste; funzt auch nach n ebenen noch. Gib mir bitte mal ein Beispiel wo das nicht funzt. Hätte da schon eine Idee, warum das nicht geht.
Aber gib mal ein Beispiel, dann sehe ich, ob ich auf dem richtigen weg bin.
-
@Bernhard:
Nachdem Du online bist und ich mir jetzt langsam "den Wolf suche" in der Hilfe und in anderen Scripts, frag ich nochmal:
Der Debugger hält an der Stelle "Forall item....."
Meine try&error - Tests habe ich ausgeklammert:
Sub Initialize
Dim session As New NotesSession
Dim db As NotesDatabase
Dim collection As NotesDocumentCollection
Dim doc As NotesDocument
Dim item As NotesItem
Dim itemName As String
Set db = session.CurrentDatabase
Set collection = db.UnprocessedDocuments
Set doc = collection.GetFirstDocument
While Not(doc Is Nothing)
vItemChanged = False
' Forall item In NotesDocument
' Forall items In doc.Item
' Forall item In doc.items
' Forall items In doc.items
If item.Name = "test33" Then
Call item.Remove
BChanged = True
End If
End Forall
If vItemChanged = True Then
Call doc.Save (True, False, True)
End If
Set doc = collection.GetNextDocument(doc)
Wend
End Sub
TMC
-
Hallo, TMC,
wie gesagt, mein Vorschlag war nur so "hingeschmiert". Vielleicht hakt es an einem reservierten Namen - habe jetzt leider keine Zeit, gleich tiefer nachzuschauen.
Aus der DesignerHelp mal schnell gezogen (NotesItem.Property):
itemList = doc.Items
Forall i In itemList
If ( Instr( i.Name, "$" ) = 0 ) Then
Call plainItem.AppendText( i.Name + ": " + i.Text )
Call plainItem.AddNewLine( 1 )
End If
End Forall
Hilft Dir das schnell weiter ? Sorry für meine "Kurz-Angebundenheit" ...
Was ich aber noch sehe:
Du kannst Option Declare nicht gesetzt haben ;-(
vItemChanged heißt bei mir bChanged - und kommt in Deinem Script noch vor.
Also: vItemChanged deklarieren und bChanged damit ersetzen.
Hat aber nix mit Deinem eigentlichen Problem zu tun ;-)
Ciao, viel Glück, und sag mal an, was rausgekommen ist. Ich schaue heute nochmal rein.
Bernhard
-
Hallo, eknori,
ich bin auch verwirrt - es sollte ja einfach funktionieren.
Declarations wie bei Dir, dann folgender Code in einem Buhtong:
Msgbox MakePath ("D:\A1\B2\C3\D4")
Bis C3 tut er ... Natürlich habe ich auch den ganzen Pfad von der Platte geknallt und neuen Versuch gestartet. Wie gesagt: Ich bin verwirrt.
Ciao & danke,
Bernhard
-
Hi Bernhard,
wohl eine weitere Möglichkeit mit itemList, nur dann hängt bei
"If Item.Name..."
Ich komm irgendwie nicht drauf....
TMC
PS. Danke für den Hint wegen Option Declare / bChanged....
Hast Recht, sollte man eigentlich immer setzen
-
Wenn Du das so übernommen hast, dann müßte es bei Dir heissen:
If ItemList.Name
Wie gesagt - bin selbst im Streß, daher nur so auf die Schnelle.
Bernhard
-
Hi Multitasking-fähiger gestresster Bernhard mit parallelem Win-Verz.-Problem:
Da sagt Notes/Debuuger "Variant does not contain an object", wenn ich "If ItemList.Name..." reinsetze.
Viel Erfolg bei der Verzeichnis-Sache.
TMC
-
@Multitasking-Bernhard:
Jetzt hab ich beschlossen: "Never touch a running Code".
Mein While/Wend läuft ja prima auf die Items, daher hab ich einfach die Änderungsabfrage von Dir in meinem bestehenden Code integriert und nun läuft es prima :). Ich übersehe jetzt mal das item.name... (auch wenn ich das dann bestimmt in 2 Wochen brauche :-\).
However: Code geht jetzt 1a, ist performant, und ich verstehe was er macht :)
cu,
TMC
Sub Initialize
Dim session As New NotesSession
Dim db As NotesDatabase
Dim collection As NotesDocumentCollection
Dim doc As NotesDocument
Dim item As NotesItem
Set db = session.CurrentDatabase
Set collection = db.UnprocessedDocuments
Set doc = collection.GetFirstDocument
While Not(doc Is Nothing)
vItemChanged = False 'Variable um zu Überprüfen ob Doc sich geändert hat (damit nicht 100000mal gespeichert wird)
While (doc.HasItem("test33"))
Set item = doc.GetFirstItem("test33")
Call item.Remove
vItemChanged = True 'Jetzt Änderung setzen
Wend
'** Wenn Doc sich geändert: Speichern, else: fortfahren
If vItemChanged = True Then
Call doc.Save (True, False, True)
End If
Set doc = collection.GetNextDocument(doc)
Wend
End Sub
-
Cool - das kommt ja auf's selbe 'raus.
Und demnächst schauen wir mal, warum mein voreilig gepostetes Zeugs nicht auf Anhieb funktioniert hat - machen wir zusammen, okay ?
Und mein Programm, um mögliche Verzeichnisnamen anzulegen und unmögliche Verzeichnisnamen zusammenzustutzen und dann anzulegen, läuft *prinzipiell* jetzt auch ;-)
Ciao,
Bernhard
-
Probiers mal so: Ich hab schon beobachtet, das Objekte innerhalb von Objekten nicht initialisiert sind, wenn man sie direkt ansprechen will. Warum das so ist weiss ich nicht.
Set Items=doc.items
Forall item In items
If item.Name = "test33" Then
Call item.Remove
BChanged = True
End If
End Forall
-
@Semaphoros:
Danke für diesen Tipp.
Hast Du vielleicht Lust, die Thematik hier zu ergänzen bezügl. items in Forall ?
http://www.atnotes.de/index.php?board=11;action=display;threadid=11314 (http://www.atnotes.de/index.php?board=11;action=display;threadid=11314)
TMC
-
Also, ich hab in Deinem anderen Thread mal noch eine Uebersicht über die Schlaufen in LS gemacht, da ich eigentlich hier aufräumen sollte (aber keine Lust dazu habe ...) hab ich mich mal darauf beschränkt. Wenn ich da nix mehr schreibe, erinnere mich in ein paar Tagen nochmal dran, da liesse sich tatsächlich eine Schlaufen-Uebersicht zusammenstellen. Kann ich gut verstehen, dass man mit dem Schlaufen - Zeugs in eine Endlos-Schlaufe gerät mit dem Kapieren :-)
-
danke schonmal :-)
na ja, gerade als Anfänger sind halt die Möglichkeiten vielzählig und nicht immer ist erkennbar was man im Fall xy nun verwenden soll; und das will ich eben eingrenzen. Und warum nur in meine private Knowhow-DB schreiben, wenn auch andere daran teilnehmen können....
TMC