marco1234
Goto Top

Print Outlook Attachment - AdobeReader ist zu langsam für Makro!

Hallo zusammen

Die Logistikabteilung unserer Firma bekommt täglich vom Zoll Mails mit einem PDF im Anhang. Ich wurde angefragt, ob es eine Lösung gibt, um nur den Anhang automatisiert auszudrucken. Ich habe mich für ein Makro entschieden. (wir wollten keine kostenpflichtigen Tools anschaffen)

Dieses Makro läuft auch recht gut. Kürzlich ist aber das Problem entdeckt worden, dass, wenn zwei Mails zur gleichen Zeit ankommen, nur das erste Mail gedruckt wird und das zweite vom Programm "vergessen" wird. Ich habe darauf hin eine While-Schlaufe eingebaut, welche alle Mails im Posteingang nochmals durchgeht und die Anhänge der nicht gelesenen Mails ausdruckt.

Dies würde theoretisch auch funktionieren... nur, das Makro ist viel zu schnell für den AdobeReader. Der Reader bringt immer eine Meldung, dass er die Datei nicht finden kann. Und ich habe leider keine Ahnung wieso. Wenn ich das Makro Debugge (F8) erscheint vom AdobeReader keine Fehlermeldung.
Zuerst dachte ich, es sei, weil das Makro die Datei zu schnell wieder löscht. Dies habe ich aber rausgenommen, indem ich eine Funktion (AttachmentFolder()) erstellte, welche nur einmal, beim Eintreffen neuer eMails, aufgerufen wird. Meine zweite Überlegung war, dass vielleicht der zweite Druckauftrag zu schnell kommt. Darum habe ich nach dem Druck-Befehl eine Sleep-Funktion von 10 Sek. eingebaut. Aber auch dies brachte keinen Erfolg.

Ich bin langsam wirklich ratlos, wie ich das Problem lösen soll. Ist es überhaupt lösbar wenn das Problem beim AdobeReader liegt? Gibt es eine bessere Lösung (Code)?

Besten Dank für eure Hilfe!

Gruss
Marco

Hier der Code:

Option Explicit


Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)  
Private Declare Function ShellExecute Lib "shell32.dll" Alias _  
"ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, _  
ByVal lpFile As String, ByVal lpParameters As String, _
ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long

Private WithEvents Items As Outlook.Items

Private Sub Application_Startup()
    Dim Ns As Outlook.NameSpace
    Dim Folder As Outlook.MAPIFolder
    Set Ns = Application.GetNamespace("MAPI")  
    Set Folder = Ns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox) 'Ordner definieren (hier Posteingang)  
    Set Items = Folder.Items
End Sub


Private Sub Items_ItemAdd(ByVal Item As Object)
   
   
   Dim i As Integer 'Variable i wird als Integer definiert  

   AttachmentFolder 'Ordner Bereinigungs-Funktion aufrufen  
   
   'PrintAttachments Item 'Print-Funktion aufrufen  
   Item.UnRead = False 'Mail als ungelesen markieren  
  
   'Anzahl Mails im Posteingang zählen und in die Variable i schreiben  
   i = Items.count
   
   'While-Schlaufe, die alle Mails durchgeht und die Anhänge der ungelesenen Mails ausdruckt  
    Do While i <> 1
        'Falls Mail(x) = ungelesen...  
        If Items.Item(i).UnRead = True Then
              ' PrintAttachments Items.Item(i)  'Print-Funktion aufrufen  
               Items.Item(i).UnRead = False   'Mail als ungelesen markieren  
        End If
        i = i - 1 'Variabel i verkleinern  
    Loop
        
End Sub

Private Sub PrintAttachments(oMail As Outlook.MailItem)
    'Variabeln definieren  
    'On Error Resume Next    'Fehlermeldungen ignorieren  
    Dim colAtts As Outlook.Attachments
    Dim oAtt As Outlook.Attachment
    Dim sFile As String
    Dim sDirectory As String
    Dim sFileType As String
   
    Dim txt As String
    
    Dim filename_count As Integer
    filename_count = 1
    
    sDirectory = "C:\tmp\Attachment\" 'Dahin werden Anhänge temporär abgespeichert  
        
    Set colAtts = oMail.Attachments   'Mailanhang  

        If colAtts.count Then
        
            'Anzahl Anhnänge = Anzahl Durchläufe  
            For Each oAtt In colAtts
    
                'die letzten 4 Zeichen = Dateiendung  
                sFileType = LCase$(Right$(oAtt.FileName, 4))
    
                Select Case sFileType
                    Case ".xls", ".doc", ".pdf" 'Hier alle gewünschten Dateiendungen dazupacken  
                        sFile = sDirectory & filename_count & oAtt.FileName 'Pfad erstellen  
                        oAtt.SaveAsFile sFile 'Angang abspeichern...  
                        ShellExecute 0, "print", sFile, vbNullString, vbNullString, 0 'ausdrucken  
                        'MsgBox ("Print" + sFile)  
                        
                        '10 Sek. warten bevor Datei gelöscht wird  
                        Sleep 10000
                            
                            'Logdatei schreiben (Datum, Zeit: Dateiname)  
                                txt = (Date & ", " & Time & ": " & filename_count & oAtt.FileName)  
                                 
                                Open "C:\PrintAttLogfile.txt" For Append As #1  
                                Print #1, txt
                                Close #1
                                
                              '!Kill File ausgeschaltet, da die Datei so gelöscht wird, bevor der AdobeReader die Datei drucken kann  
                             'Kill sFile  
                    
                        'filename_count + 1  
                        filename_count = filename_count + 1

                    End Select
                Next
        End If
        
End Sub

Private Sub AttachmentFolder()

'[gespeicherte Anhänge müssen gelöscht werden damit die Festplatte nicht vollläuft].  

    Dim fso As Object
    Dim count As Integer

   'Falls der Ordner "Attachment" existiert...  
   If Dir("C:\tmp\Attachment", vbDirectory) <> "" Then  
  
           'Anzahl Dateien in Ordner zählen  
           Set fso = CreateObject("Scripting.FileSystemObject")  
           count = fso.GetFolder("C:\tmp\Attachment").Files.count 'zählen  
           
                'Wenn Ordner Dateien enthält, alle Dateien löschen.  
                If count <> 0 Then
                 Kill "C:\tmp\Attachment\*.*" 'Alle Dateien im Ordner Attachment löschen  
                End If
        
          RmDir ("C:\tmp\Attachment")  'Temp Ordner löschen  
   End If
        
  
    MkDir ("C:\tmp\Attachment") 'Temp Ordner für Anhänge erstellen  
    

End Sub

Content-ID: 136828

Url: https://administrator.de/contentid/136828

Ausgedruckt am: 19.11.2024 um 15:11 Uhr

maretz
maretz 25.02.2010 um 11:46:27 Uhr
Goto Top
Moin,

vorab: VBS ist für mich ne Sprache der Hölle... Ich bleib lieber bei richtigen Programmiersprachen ;)

Aber: Wenn du das Script eh genau für EINE Abteilung angepasst hast dann gibt es ja ggf. die Möglichkeit das du den Drucker missbrauchst. Viele Netzwerk-Drucker haben die Option das du denen auch ne PDF in nen bestimmtes Folder (per ftp) legst und die das dann ausdrucken. D.h. dich kümmert der Acrobat dann gar nicht mehr - du machst nen FTP-Upload und löscht danach die Datei... Wäre das ne Alternative?
marco1234
marco1234 25.02.2010 um 14:57:10 Uhr
Goto Top
Hallo maretz

Vielen Dank für deine rasche Antwort!

Oja, bin ich deiner Meinung! Ist auch nicht meine Lieblingssprache. Aber es schien mir am einfachsten für dieses Projekt. Wie hättest du es gelöst?

Deine Idee mit dem FTP find’ ich super! Wollte dies heute Nachmittag ausprobieren. Jedoch war meine Freude schnell verflogen..... unsere super Xerox Multifunktionsgeräte (Xerox WorkCentre 5230 PS) haben keinen FTP! -.-

Ich kann nur folgendes auswählen:

TCP/IP
Microsoft-Netzwerk
LPD
Port 9100
http

Ich glaube FTP kann ich vergessen -.-


Gruss
Marco
76109
76109 25.02.2010 um 15:39:09 Uhr
Goto Top
Hallo marco1234!

Also, ich habe mal diese Funktion bei mir getestet:
Option Explicit

Private Declare Function ShellExecute Lib "shell32.dll" Alias _  
"ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, _  
ByVal lpFile As String, ByVal lpParameters As String, _
ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long

Const Path1 = "C:\Test1.Pdf"  
Const Path2 = "C:\Test2.Pdf"  
Const Path3 = "C:\Test3.Pdf"  
Const Path4 = "C:\Test4.Pdf"  
Const Path5 = "C:\Test5.Pdf"  

Sub Test()
    Dim Files As Variant, i As Integer
    
    Files = Array(Path1, Path2, Path3, Path4, Path5)
    
    For i = 0 To UBound(Files)
        ShellExecute 0, "print", Files(i), vbNullString, vbNullString, 0  
    Next
End Sub
Mit dem Resultat, dass es bei mir einwandfrei funktioniert hat. D.h. Code schneller durchlaufen, als das Auge sehen kann und dann in aller seelenruhe die Druckaufträge nacheinander am virtuellen PDF-Drucker gedruckt, wobei der AcrobatReader minimiert auf der Taskleiste verblieb. Das gleiche hat auch mit einem normalen Drucker funktioniert bzw. wurden in der Druckerwarteschlange angezeigt und von mir gelöscht. Die PDF-Dateien hatten dabei eine Größe zwischen 5MB und 6MB.

Möglichlicherweise, werden bei dir keine Druckaufträge in die Warteschlange gespoolt.

Gruß Dieter
marco1234
marco1234 25.02.2010 um 16:12:31 Uhr
Goto Top
Hallo didi1954

Habe dein Script bei mir auch ausprobiert. Läuft einwandfrei. PDFs werden ohne Reklamationen gedruckt.

Ist denn mein Code das Problem? Aber wieso läuft alles rund, wenn ich Debugge? :-S

Gruss
Marco
76109
76109 25.02.2010 um 16:28:10 Uhr
Goto Top
Hallo marco1234!

Mhm, dass kann ich Dir leider nicht sagen.

Ich habe Outlook nur im XP-Mode Virtual PC ohne EMail-Konten etc. installiert. Von daher funktioniert kein vollständiger Test mit Deinem Code.

Es könnte aber durchaus sein, dass ein anderer Fehler die Ursache Deine Problems ist, zumal bei einem Fehler nix passiert, wenn z.B. eine Datei garnicht existiert.

Gruß Dieter
76109
76109 26.02.2010 um 12:33:16 Uhr
Goto Top
Hallo marco1234!

Falls Du das Problem noch nicht gelöst hast, so ist mir nach nochmaligem Durchlesen aufgefallen, dass Die Anhänge ja erst gespeichert und dann gedruckt werden. Dann hast Du vermutlich doch ein Zeitproblem, weil das Speichern zu lange dauert und beim Druckauftrag kein Fehler bei noch nicht existierender Datei ausgegeben wird. Insofern würde ich erst den Druckbefehl mit aktuellem Pfad absetzen und danach speichern.

Gruß Dieter
marco1234
marco1234 01.03.2010 um 08:06:09 Uhr
Goto Top
Hallo Dieter

Ja, die Anhänge werden lokal abgespeichert, dann gedruckt und lokal wieder gelöscht.

Aha, du meinst also, dass der Druckauftrag kommt, bevor das File vollständig abgespeichert wurde? Könnte sein...

Ich baue 'mal eine Sleep-Funktion vor dem Druck ein. Mal schauen, ob’s was bringt.

Vielen Dank für den Tipp!

Gruss
Marco
76109
76109 01.03.2010 um 09:36:10 Uhr
Goto Top
Hallo Marco!

Zitat von @marco1234:
Aha, du meinst also, dass der Druckauftrag kommt, bevor das File vollständig abgespeichert wurde? Könnte sein...
Ist sogar sehr wahrscheinlichface-wink
Ich baue 'mal eine Sleep-Funktion vor dem Druck ein. Mal schauen, ob’s was bringt.
Dann sollte es gehen. Versuchs mal ab 100ms.

Das erklärt ja auch, warum's beim debuggen funktioniertface-wink

Gruß Dieter
marco1234
marco1234 01.03.2010 um 15:38:19 Uhr
Goto Top
Genial! Es funktioniert! Die Lösung ist manchmal so einfach =P

Thanks for your help!

Gruss
Marco
marco1234
marco1234 01.03.2010 um 16:13:14 Uhr
Goto Top
OK, zu früh gefreut face-sad Zwei Mal ist das Problem bereits wieder aufgetreten face-sad

Die genaue Fehlermeldung von AdobeReader lautet: "Beim Öffnen dieses Dokuments ist ein Fehler aufgetreten. Diese Datei kann nicht gefunden werden"

Wenn ich auf OK klicke, wird das Dokument korrekt gedruckt. Jedoch zweimal.

Die Sleep-Funktion nach dem Speichern habe ich auf 5 Sekunden eingestellt. Die PDF-Files, welche ich zum Testen verwendet habe, sind um die 40KB gross.

….ich verstehe es nicht :-S


Gruss
Marco
76109
76109 01.03.2010 um 16:42:18 Uhr
Goto Top
Hallo Marco!

So ein Mistface-wink

Also, wenn 5 Sekunden nicht ausreichen, dann weiß ich auch nicht, wo's da klemmt?

Und ein Drucken per "oAtt.FilePath" oder "oAtt.Path", sowas in der Art, geht das nicht?


Gruß Dieter
marco1234
marco1234 14.04.2010 um 16:27:05 Uhr
Goto Top
Wie meinst du das?

Gruss
Marco
76109
76109 14.04.2010 um 17:11:38 Uhr
Goto Top
Hallo Marco!

Falls Du das mit dem Direkt-Drucken meinst, dann vergiss meinen blödsinnigen Kommentar. Mein Gedanke war, dass die PDF-Datei ja schon real vorhanden sein müsste, aber tatsächlich befindet sich die Datei nur base64-codiert in der InBox und muss zum drucken also doch erst gespeichert werden.

Gruß Dieter
marco1234
marco1234 15.04.2010 um 07:56:42 Uhr
Goto Top
OK, schon vergessen. face-wink

Aber wie soll ich mein Problem jetzt lösen? Ich sollte an diesem Script schon längst weitermachen aber ich habe keine Idee, wo ich beginnen soll bzw. was ich ändern soll *ratlos bin* face-sad

Gruss
Marco
marco1234
marco1234 26.04.2010 um 16:45:13 Uhr
Goto Top
Hätte jemand eine Idee, wie ich Outlook beibringen können, dass das Eintreffen von mehreren Mails mit Anhang erkannt wird?
Also wenn zwei Mails ankommen, dass ich von Outlook die Information bekomme: hey, hier sind zwei neue Mails! Momentan funktioniert das ja nur mit dem ersten Mail, welches ankommt.

Ich habe mir überlegt, ob es nicht besser ist, wenn zuerst alle Anhänge gespeichert werden und anschliessend dann alle Dateien im Ordner Attachment gedruckt werden. Eine Option?

Danke und Gruss
Marco